diff --git a/.github/labeler.yml b/.github/labeler.yml index 0002f9b7327..23f9cda941a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -87,3 +87,7 @@ trigger: tutorial: - changed-files: - any-glob-to-any-file: ["Tutorials/**"] + +photon: + - changed-files: + - any-glob-to-any-file: ["PWGEM/PhotonMeson/**", "*/PWGEM/PhotonMeson/**"] diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 7bca50984a3..7b558e9e825 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@v9.2.0 + uses: oxsecurity/megalinter@v9.4.0 env: # All available variables are described in documentation: # https://megalinter.io/configuration/ @@ -49,7 +49,7 @@ jobs: # Upload MegaLinter artifacts - name: Archive production artifacts - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 if: success() || failure() with: name: MegaLinter reports diff --git a/.github/workflows/o2-linter.yml b/.github/workflows/o2-linter.yml index 00c710dbd5a..f5a1b39a950 100644 --- a/.github/workflows/o2-linter.yml +++ b/.github/workflows/o2-linter.yml @@ -20,12 +20,12 @@ jobs: steps: - name: Set branches run: | - if [[ "${{ github.event_name }}" == "push" ]]; then + if [[ "${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "pull_request" ]]; then branch_head="${{ github.ref }}" - branch_base="${{ env.BRANCH_MAIN }}" + branch_base="origin/${{ env.BRANCH_MAIN }}" else branch_head="refs/pull/${{ github.event.pull_request.number }}/merge" - branch_base="${{ github.event.pull_request.base.ref }}" + branch_base="origin/${{ github.event.pull_request.base.ref }}" fi echo BRANCH_HEAD="$branch_head" >> "$GITHUB_ENV" echo BRANCH_BASE="$branch_base" >> "$GITHUB_ENV" @@ -37,9 +37,10 @@ jobs: - name: Run tests id: linter run: | + git log -n 1 --pretty='format:%ci %h %s %d%n' # Diff against the common ancestor of the source (head) branch and the target (base) branch. echo "Diffing ${{ env.BRANCH_HEAD }} against ${{ env.BRANCH_BASE }}." - readarray -t files < <(git diff --diff-filter d --name-only origin/${{ env.BRANCH_BASE }}...) + readarray -t files < <(git diff --diff-filter d --name-only ${{ env.BRANCH_BASE }}...) if [ ${#files[@]} -eq 0 ]; then echo "::notice::No files to lint." echo "linter_ran=0" >> "$GITHUB_OUTPUT" @@ -47,6 +48,8 @@ jobs: fi echo "linter_ran=1" >> "$GITHUB_OUTPUT" [[ "${{ github.event_name }}" == "pull_request_target" ]] && options="-g" + # Checkout the script from the base branch to prevent execution of arbitrary code in the head branch. + git checkout ${{ env.BRANCH_BASE }} -- Scripts/o2_linter.py # shellcheck disable=SC2086 # Ignore unquoted options. python3 Scripts/o2_linter.py $options "${files[@]}" echo "Tip: If you allow actions in your fork repository, O2 linter will run when you push commits." diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c154ffad42..f837e1ad5a0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v21.1.8 # clang-format version + rev: v20.1.3 # clang-format version (keep synced with https://github.com/alisw/ali-bot/blob/master/.github/workflows/c++-code-formatting.yml) hooks: - id: clang-format - repo: https://github.com/cpplint/cpplint diff --git a/ALICE3/Core/ALICE3CoreLinkDef.h b/ALICE3/Core/ALICE3CoreLinkDef.h index 05d2a78fc00..076c21f8a79 100644 --- a/ALICE3/Core/ALICE3CoreLinkDef.h +++ b/ALICE3/Core/ALICE3CoreLinkDef.h @@ -14,3 +14,5 @@ #pragma link off all functions; #pragma link C++ class o2::pid::tof::TOFResoALICE3 + ; +#pragma link C++ class std::vector < std::vector < unsigned int>> + ; +#pragma link C++ class std::vector < std::vector < std::uint32_t>> + ; diff --git a/ALICE3/Core/CMakeLists.txt b/ALICE3/Core/CMakeLists.txt index 6d44d580c45..7f8672c7d64 100644 --- a/ALICE3/Core/CMakeLists.txt +++ b/ALICE3/Core/CMakeLists.txt @@ -13,6 +13,7 @@ o2physics_add_library(ALICE3Core SOURCES TOFResoALICE3.cxx TrackUtilities.cxx DelphesO2TrackSmearer.cxx + GeometryContainer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) @@ -20,6 +21,7 @@ o2physics_target_root_dictionary(ALICE3Core HEADERS TOFResoALICE3.h TrackUtilities.h DelphesO2TrackSmearer.h + GeometryContainer.h LINKDEF ALICE3CoreLinkDef.h) o2physics_add_library(FastTracker diff --git a/ALICE3/Core/Decayer.h b/ALICE3/Core/Decayer.h index 22cc46139cd..bec6b9506d9 100644 --- a/ALICE3/Core/Decayer.h +++ b/ALICE3/Core/Decayer.h @@ -21,18 +21,18 @@ #include "ALICE3/Core/TrackUtilities.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include -#include -#include +#include // IWYU pragma: keep #include #include -#include #include #include #include -#include +#include #include namespace o2 @@ -69,7 +69,7 @@ class Decayer vy = pos[1] + rxyz * (mom[1] / track.getP()); vz = pos[2] + rxyz * (mom[2] / track.getP()); px = mom[0]; - py = mom[2]; + py = mom[1]; } else { float sna, csa; o2::math_utils::CircleXYf_t circle; diff --git a/ALICE3/Core/DelphesO2LutWriter.cxx b/ALICE3/Core/DelphesO2LutWriter.cxx index 987383092ec..c2df9431ef4 100644 --- a/ALICE3/Core/DelphesO2LutWriter.cxx +++ b/ALICE3/Core/DelphesO2LutWriter.cxx @@ -25,14 +25,27 @@ #include "ALICE3/Core/FastTracker.h" #include "ALICE3/Core/TrackUtilities.h" -#include "TAxis.h" -#include "TDatabasePDG.h" -#include "TLorentzVector.h" -#include "TMatrixD.h" -#include "TMatrixDSymEigen.h" -#include "TVectorD.h" - +#include +#include + +#include +#include +#include +#include +#include // IWYU pragma: keep (do not replace with TMatrixDfwd.h) +#include +#include +#include +#include +#include +#include + +#include + +#include #include +#include +#include #include // #define USE_FWD_PARAM diff --git a/ALICE3/Core/DelphesO2LutWriter.h b/ALICE3/Core/DelphesO2LutWriter.h index 1528ab80bac..e234efd3bdb 100644 --- a/ALICE3/Core/DelphesO2LutWriter.h +++ b/ALICE3/Core/DelphesO2LutWriter.h @@ -23,10 +23,13 @@ #include "ALICE3/Core/DelphesO2TrackSmearer.h" #include "ALICE3/Core/FastTracker.h" -#include "ReconstructionDataFormats/PID.h" +#include -#include "TGraph.h" +#include +#include + +#include #include namespace o2::fastsim diff --git a/ALICE3/Core/DelphesO2TrackSmearer.cxx b/ALICE3/Core/DelphesO2TrackSmearer.cxx index 7eacb473d74..7d7f6fc6077 100644 --- a/ALICE3/Core/DelphesO2TrackSmearer.cxx +++ b/ALICE3/Core/DelphesO2TrackSmearer.cxx @@ -28,18 +28,18 @@ /// @author: Roberto Preghenella /// @email: preghenella@bo.infn.it -// #include "TrackSmearer.hh" -// #include "TrackUtils.hh" -// #include "TRandom.h" -// #include -// #include - #include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/Core/GeometryContainer.h" + #include #include -#include +#include + +#include +#include +#include #include namespace o2 @@ -61,43 +61,13 @@ bool TrackSmearer::loadTable(int pdg, const char* filename, bool forceReload) LOG(info) << " --- LUT table for PDG " << pdg << " has been already loaded with index " << ipdg << std::endl; return false; } - if (strncmp(filename, "ccdb:", 5) == 0) { // Check if filename starts with "ccdb:" - LOG(info) << " --- LUT file source identified as CCDB."; - std::string path = std::string(filename).substr(5); // Remove "ccdb:" prefix - const std::string outPath = "/tmp/LUTs/"; - filename = Form("%s/%s/snapshot.root", outPath.c_str(), path.c_str()); - LOG(info) << " --- Local LUT filename will be: " << filename; - std::ifstream checkFile(filename); // Check if file already exists - if (!checkFile.is_open()) { // File does not exist, retrieve from CCDB - LOG(info) << " --- CCDB source detected for PDG " << pdg << ": " << path; - if (!mCcdbManager) { - LOG(fatal) << " --- CCDB manager not set. Please set it before loading LUT from CCDB."; - } - std::map metadata; - mCcdbManager->getCCDBAccessor().retrieveBlob(path, outPath, metadata, 1); - // Add CCDB handling logic here if needed - LOG(info) << " --- Now retrieving LUT file from CCDB to: " << filename; - if (mCleanupDownloadedFile) { // Clean up the downloaded file if needed - bool status = loadTable(pdg, filename, forceReload); - if (std::remove(filename) != 0) { - LOG(warn) << " --- Could not remove temporary LUT file: " << filename; - } else { - LOG(info) << " --- Removed temporary LUT file: " << filename; - } - return status; - } - } else { // File exists, proceed to load - LOG(info) << " --- LUT file already exists: " << filename << ". Skipping download."; - checkFile.close(); - } - return loadTable(pdg, filename, forceReload); - } + const std::string localFilename = o2::fastsim::GeometryEntry::accessFile(filename, "./.ALICE3/LUTs/", mCcdbManager, 10); mLUTHeader[ipdg] = new lutHeader_t; - std::ifstream lutFile(filename, std::ifstream::binary); + std::ifstream lutFile(localFilename, std::ifstream::binary); if (!lutFile.is_open()) { - LOG(info) << " --- cannot open covariance matrix file for PDG " << pdg << ": " << filename << std::endl; + LOG(info) << " --- cannot open covariance matrix file for PDG " << pdg << ": " << localFilename << std::endl; delete mLUTHeader[ipdg]; mLUTHeader[ipdg] = nullptr; return false; @@ -105,6 +75,7 @@ bool TrackSmearer::loadTable(int pdg, const char* filename, bool forceReload) lutFile.read(reinterpret_cast(mLUTHeader[ipdg]), sizeof(lutHeader_t)); if (lutFile.gcount() != sizeof(lutHeader_t)) { LOG(info) << " --- troubles reading covariance matrix header for PDG " << pdg << ": " << filename << std::endl; + LOG(info) << " --- expected/detected " << sizeof(lutHeader_t) << "/" << lutFile.gcount() << std::endl; delete mLUTHeader[ipdg]; mLUTHeader[ipdg] = nullptr; return false; @@ -147,7 +118,8 @@ bool TrackSmearer::loadTable(int pdg, const char* filename, bool forceReload) mLUTEntry[ipdg][inch][irad][ieta][ipt] = new lutEntry_t; lutFile.read(reinterpret_cast(mLUTEntry[ipdg][inch][irad][ieta][ipt]), sizeof(lutEntry_t)); if (lutFile.gcount() != sizeof(lutEntry_t)) { - LOG(info) << " --- troubles reading covariance matrix entry for PDG " << pdg << ": " << filename << std::endl; + LOG(info) << " --- troubles reading covariance matrix entry for PDG " << pdg << ": " << localFilename << std::endl; + LOG(info) << " --- expected/detected " << sizeof(lutHeader_t) << "/" << lutFile.gcount() << std::endl; return false; } } diff --git a/ALICE3/Core/DelphesO2TrackSmearer.h b/ALICE3/Core/DelphesO2TrackSmearer.h index f6e916e32a4..6d941f336ca 100644 --- a/ALICE3/Core/DelphesO2TrackSmearer.h +++ b/ALICE3/Core/DelphesO2TrackSmearer.h @@ -27,21 +27,14 @@ #include #include -#include - +#include #include -#include -#include -#include +#include /////////////////////////////// /// DelphesO2/src/lutCovm.hh // /////////////////////////////// -/// @author: Roberto Preghenella -/// @email: preghenella@bo.infn.it - -// #pragma // once #define LUTCOVM_VERSION 20210801 struct map_t { @@ -153,17 +146,6 @@ struct lutEntry_t { /// DelphesO2/src/TrackSmearer.hh // //////////////////////////////////// -/// @author: Roberto Preghenella -/// @email: preghenella@bo.infn.it - -// #ifndef _DelphesO2_TrackSmearer_h_ -// #define _DelphesO2_TrackSmearer_h_ - -// #include "ReconstructionDataFormats/Track.h" -// #include "classes/DelphesClasses.h" -// #include "lutCovm.hh" -// #include - using O2Track = o2::track::TrackParCov; namespace o2 @@ -250,7 +232,6 @@ class TrackSmearer } void setdNdEta(float val) { mdNdEta = val; } //; void setCcdbManager(o2::ccdb::BasicCCDBManager* mgr) { mCcdbManager = mgr; } //; - void setCleanupDownloadedFile(bool val) { mCleanupDownloadedFile = val; } //; protected: static constexpr unsigned int nLUTs = 9; // Number of LUT available @@ -264,16 +245,14 @@ class TrackSmearer private: o2::ccdb::BasicCCDBManager* mCcdbManager = nullptr; - bool mCleanupDownloadedFile = true; }; } // namespace delphes } // namespace o2 -// #endif /** _DelphesO2_TrackSmearer_h_ **/ - namespace o2::delphes { using DelphesO2TrackSmearer = TrackSmearer; } + #endif // ALICE3_CORE_DELPHESO2TRACKSMEARER_H_ diff --git a/ALICE3/Core/DetLayer.cxx b/ALICE3/Core/DetLayer.cxx index 2e72d641a2b..d93fd77373f 100644 --- a/ALICE3/Core/DetLayer.cxx +++ b/ALICE3/Core/DetLayer.cxx @@ -21,8 +21,10 @@ #include #include +#include +#include + #include -#include namespace o2::fastsim { diff --git a/ALICE3/Core/DetLayer.h b/ALICE3/Core/DetLayer.h index 32c5a839684..b3ed3ed6b34 100644 --- a/ALICE3/Core/DetLayer.h +++ b/ALICE3/Core/DetLayer.h @@ -22,6 +22,7 @@ #include #include +#include #include namespace o2::fastsim diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index 41c6637d59b..254ab8d6643 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -11,21 +11,36 @@ #include "FastTracker.h" -#include "Common/Core/TableHelper.h" - +#include "DetLayer.h" +#include "GeometryContainer.h" + +#include +#include +#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include // IWYU pragma: keep (do not replace with TMatrixDfwd.h) #include +#include +#include #include #include -#include +#include +#include + +#include +#include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -34,81 +49,6 @@ namespace o2 namespace fastsim { -std::map> GeometryContainer::parseTEnvConfiguration(std::string filename, std::vector& layers) -{ - std::map> configMap; - filename = gSystem->ExpandPathName(filename.c_str()); - TEnv env(filename.c_str()); - THashList* table = env.GetTable(); - layers.clear(); - for (int i = 0; i < table->GetEntries(); ++i) { - const std::string key = table->At(i)->GetName(); - // key should contain exactly one dot - if (key.find('.') == std::string::npos || key.find('.') != key.rfind('.')) { - LOG(fatal) << "Key " << key << " does not contain exactly one dot"; - continue; - } - const std::string firstPart = key.substr(0, key.find('.')); - if (std::find(layers.begin(), layers.end(), firstPart) == layers.end()) { - layers.push_back(firstPart); - } - } - env.Print(); - // Layers - for (const auto& layer : layers) { - LOG(info) << " Reading layer " << layer; - for (int i = 0; i < table->GetEntries(); ++i) { - const std::string key = table->At(i)->GetName(); - if (key.find(layer + ".") == 0) { - const std::string paramName = key.substr(key.find('.') + 1); - const std::string value = env.GetValue(key.c_str(), ""); - configMap[layer][paramName] = value; - } - } - } - return configMap; -} - -void GeometryContainer::init(o2::framework::InitContext& initContext) -{ - std::vector detectorConfiguration; - const bool found = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "detectorConfiguration", detectorConfiguration, false); - if (!found) { - LOG(fatal) << "Could not retrieve detector configuration from OnTheFlyDetectorGeometryProvider task."; - return; - } - LOG(info) << "Size of detector configuration: " << detectorConfiguration.size(); - for (const auto& configFile : detectorConfiguration) { - LOG(info) << "Detector geometry configuration file used: " << configFile; - addEntry(configFile); - } -} - -std::map GeometryContainer::GeometryEntry::getConfiguration(const std::string& layerName) const -{ - auto it = mConfigurations.find(layerName); - if (it != mConfigurations.end()) { - return it->second; - } else { - LOG(fatal) << "Layer " << layerName << " not found in geometry configurations."; - return {}; - } -} - -std::string GeometryContainer::GeometryEntry::getValue(const std::string& layerName, const std::string& key, bool require) const -{ - auto layer = getConfiguration(layerName); - auto entry = layer.find(key); - if (entry != layer.end()) { - return layer.at(key); - } else if (require) { - LOG(fatal) << "Key " << key << " not found in layer " << layerName << " configurations."; - return ""; - } else { - return ""; - } -} - // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ DetLayer* FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi, float resZ, float eff, int type) @@ -169,106 +109,6 @@ void FastTracker::Print() LOG(info) << "+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+"; } -void FastTracker::AddSiliconALICE3v4(std::vector pixelResolution) -{ - LOG(info) << " ALICE 3: Adding v4 tracking layers"; - float x0IT = 0.001; // 0.1% - float x0OT = 0.005; // 0.5% - float xrhoIB = 1.1646e-02; // 50 mum Si - float xrhoOT = 1.1646e-01; // 500 mum Si - float eff = 1.00; - - float resRPhiIT = pixelResolution[0]; - float resZIT = pixelResolution[1]; - float resRPhiOT = pixelResolution[2]; - float resZOT = pixelResolution[3]; - - AddLayer("bpipe0", 0.48, 250, 0.00042, 2.772e-02, 0.0f, 0.0f, 0.0f, 0); // 150 mum Be - AddLayer("ddd0", 0.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1); - AddLayer("ddd1", 1.2, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1); - AddLayer("ddd2", 2.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1); - AddLayer("bpipe1", 5.7, 250, 0.0014, 9.24e-02, 0.0f, 0.0f, 0.0f, 0); // 500 mum Be - AddLayer("ddd3", 7., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("ddd4", 10., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("ddd5", 13., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("ddd6", 16., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("ddd7", 25., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("ddd8", 40., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("ddd9", 45., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); -} - -void FastTracker::AddSiliconALICE3v2(std::vector pixelResolution) -{ - LOG(info) << "ALICE 3: Adding v2 tracking layers;"; - float x0IT = 0.001; // 0.1% - float x0OT = 0.01; // 1.0% - float xrhoIB = 2.3292e-02; // 100 mum Si - float xrhoOT = 2.3292e-01; // 1000 mum Si - float eff = 1.00; - - float resRPhiIT = pixelResolution[0]; - float resZIT = pixelResolution[1]; - float resRPhiOT = pixelResolution[2]; - float resZOT = pixelResolution[3]; - - AddLayer("bpipe0", 0.48, 250, 0.00042, 2.772e-02, 0.0f, 0.0f, 0.0f, 0); // 150 mum Be - AddLayer("B00", 0.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1); - AddLayer("B01", 1.2, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1); - AddLayer("B02", 2.5, 250, x0IT, xrhoIB, resRPhiIT, resZIT, eff, 1); - AddLayer("bpipe1", 3.7, 250, 0.0014, 9.24e-02, 0.0f, 0.0f, 0.0f, 0); // 500 mum Be - AddLayer("B03", 3.75, 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B04", 7., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B05", 12., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B06", 20., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B07", 30., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B08", 45., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B09", 60., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B10", 80., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); -} - -void FastTracker::AddSiliconALICE3(float scaleX0VD, std::vector pixelResolution) -{ - float x0Pipe0 = 0.001592; // 200 um AlBe - float x0VDL0 = 0.00076; // 30 um Si + 50 um glue + carbon foam 0.03% - float x0VDL1 = 0.00096; // 30 um Si + 50 um glue + carbon foam 0.05% - float x0VDL2 = 0.00167; // 30 um Si + 50 um glue + carbon foam 0.05% + 0.07% Be case - float x0Coldplate = 0.02f; // (1.5 mm Al2O3 2%) - float x0Pipe1 = 0.0023f; // 800 um Be - float x0OT = 0.01; // 1.0% - float x0iTOF = x0OT * 3.; - - float resRPhiVD = pixelResolution[0]; - float resZVD = pixelResolution[1]; - float resRPhiOT = pixelResolution[2]; - float resZOT = pixelResolution[3]; - - float xrhoPipe0 = 0; - float xrhoVDL0 = 0; - float xrhoVDL1 = 0; - float xrhoVDL2 = 0; - float xrhoColdplate = 0; - float xrhoPipe1 = 0; - float xrhoOT = 2.3292e-01; - float xrhoiTOF = 0.03; - float eff = 1.00; - - AddLayer("bpipe0", 0.48, 250, x0Pipe0, xrhoPipe0, 0.0f, 0.0f, 0.0f, 0); - AddLayer("B00", 0.5, 250, x0VDL0 * scaleX0VD, xrhoVDL0, resRPhiVD, resZVD, eff, 1); - AddLayer("B01", 1.2, 250, x0VDL1 * scaleX0VD, xrhoVDL1, resRPhiVD, resZVD, eff, 1); - AddLayer("B02", 2.5, 250, x0VDL2 * scaleX0VD, xrhoVDL2, resRPhiVD, resZVD, eff, 1); - AddLayer("coldplate", 2.6, 250, x0Coldplate, xrhoColdplate, 0.0f, 0.0f, 0.0f, 0); - AddLayer("bpipe1", 5.7, 250, x0Pipe1, xrhoPipe1, 0.0f, 0.0f, 0.0f, 0); - AddLayer("B03", 7., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B04", 9., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B05", 12., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("iTOF", 19, 250, x0iTOF, xrhoiTOF, resRPhiOT, resZOT, eff, 0); - AddLayer("B06", 20., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B07", 30., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B08", 45., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B09", 60., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); - AddLayer("B10", 80., 250, x0OT, xrhoOT, resRPhiOT, resZOT, eff, 1); -} - void FastTracker::AddTPC(float phiResMean, float zResMean) { LOG(info) << " Adding standard time projection chamber"; @@ -314,7 +154,7 @@ void FastTracker::AddTPC(float phiResMean, float zResMean) } } -void FastTracker::AddGenericDetector(GeometryContainer::GeometryEntry configMap, o2::ccdb::BasicCCDBManager* ccdbManager) +void FastTracker::AddGenericDetector(o2::fastsim::GeometryEntry configMap, o2::ccdb::BasicCCDBManager* ccdbManager) { // Layers for (const auto& layer : configMap.getLayerNames()) { @@ -461,7 +301,7 @@ float FastTracker::ProbGoodChiSqHit(float radius, float searchRadiusRPhi, float // 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, const float nch) +int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch, const float maxRadius) { dNdEtaCent = nch; // set the number of charged particles per unit rapidity hits.clear(); @@ -508,6 +348,14 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa continue; // this layer should not be attempted, but go ahead } + if (layers[il].getRadius() > maxRadius) { + if (lastLayerReached == -1) { + // This means that we didn't reach the first layer + return -9; + } + break; // could not reach + } + // check if layer is reached float targetX = 1e+3; inputTrack.getXatLabR(layers[il].getRadius(), targetX, magneticField); @@ -540,6 +388,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa break; } } + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && mApplyZacceptance) { break; // out of acceptance bounds } @@ -578,8 +427,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa static constexpr float kLargeErr2Dir = 0.7 * 0.7; static constexpr float kLargeErr2PtI = 30.5 * 30.5; std::array largeCov = {0.}; - for (int ic = o2::track::kCovMatSize; ic--;) + for (int ic = o2::track::kCovMatSize; ic--;) { largeCov[ic] = 0.; + } largeCov[o2::track::CovLabels::kSigY2] = largeCov[o2::track::CovLabels::kSigZ2] = kLargeErr2Coord; largeCov[o2::track::CovLabels::kSigSnp2] = largeCov[o2::track::CovLabels::kSigTgl2] = kLargeErr2Dir; largeCov[o2::track::CovLabels::kSigQ2Pt2] = kLargeErr2PtI * trPars[o2::track::ParLabels::kQ2Pt] * trPars[o2::track::ParLabels::kQ2Pt]; @@ -615,8 +465,10 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa std::cos(alpha) * spacePoint[0] + std::sin(alpha) * spacePoint[1], -std::sin(alpha) * spacePoint[0] + std::cos(alpha) * spacePoint[1], spacePoint[2]}; - if (!inwardTrack.propagateTo(xyz1[0], magneticField)) + + if (!inwardTrack.propagateTo(xyz1[0], magneticField)) { continue; + } if (!layers[il].isInert()) { // only update covm for tracker hits const o2::track::TrackParametrization::dim2_t hitpoint = { @@ -647,13 +499,14 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } } - if (layers[il].isSilicon()) + if (layers[il].isSilicon()) { nSiliconPoints++; // count silicon hits - if (layers[il].isGas()) + } + if (layers[il].isGas()) { nGasPoints++; // count TPC/gas hits + } hits.push_back(thisHit); - if (!layers[il].isInert()) { // good hit probability calculation float sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); float sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); @@ -675,21 +528,24 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } // only attempt to continue if intercepts are at least four - if (nIntercepts < 4) + if (nIntercepts < 4) { return nIntercepts; + } // generate efficiency float eff = 1.; for (size_t i = 0; i < layers.size(); i++) { float iGoodHit = goodHitProbability[i]; - if (iGoodHit <= 0) + if (iGoodHit <= 0) { continue; + } eff *= iGoodHit; } if (mApplyEffCorrection) { - if (gRandom->Uniform() > eff) + if (gRandom->Uniform() > eff) { return -8; + } } outputTrack.setCov(inwardTrack.getCov()); @@ -697,8 +553,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa // Use covariance matrix based smearing std::array covMat = {0.}; - for (int ii = 0; ii < o2::track::kCovMatSize; ii++) + for (int ii = 0; ii < o2::track::kCovMatSize; ii++) { covMat[ii] = outputTrack.getCov()[ii]; + } TMatrixDSym m(5); double fcovm[5][5]; // double precision is needed for regularisation diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index 8703269296e..d593c568fb9 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -13,13 +13,17 @@ #define ALICE3_CORE_FASTTRACKER_H_ #include "DetLayer.h" +#include "GeometryContainer.h" #include -#include -#include #include -#include +#include + +#include + +#include +#include #include #include @@ -28,63 +32,6 @@ namespace o2 namespace fastsim { -class GeometryContainer -{ - public: - GeometryContainer() = default; - virtual ~GeometryContainer() = default; - - void init(o2::framework::InitContext& initContext); - - /** - * @brief Parses a TEnv configuration file and returns the key-value pairs split per entry - * @param filename Path to the TEnv configuration file - * @param layers Vector to store the order of the layers as they appear in the file - * @return A map where each key is a layer name and the value is another map of key-value pairs for that layer - */ - static std::map> parseTEnvConfiguration(std::string filename, std::vector& layers); - - // A container for the geometry info - struct GeometryEntry { - // Default constructor - GeometryEntry() = default; - explicit GeometryEntry(std::string filename) : name(filename) - { - mConfigurations = GeometryContainer::parseTEnvConfiguration(filename, layerNames); - } - std::map> getConfigurations() const { return mConfigurations; } - std::map getConfiguration(const std::string& layerName) const; - std::vector getLayerNames() const { return layerNames; } - std::string getValue(const std::string& layerName, const std::string& key, bool require = true) const; - float getFloatValue(const std::string& layerName, const std::string& key) const { return std::stof(getValue(layerName, key)); } - int getIntValue(const std::string& layerName, const std::string& key) const { return std::stoi(getValue(layerName, key)); } - - private: - std::string name; // Filename of the geometry - std::map> mConfigurations; - std::vector layerNames; // Ordered names of the layers - }; - - // Add a geometry entry from a configuration file - void addEntry(const std::string& filename) { entries.emplace_back(filename); } - - // Getters - int getNumberOfConfigurations() const { return entries.size(); } - const std::vector& getEntries() const { return entries; } - const GeometryEntry& getEntry(const int id) const { return entries.at(id); } - GeometryEntry getGeometryEntry(const int id) const { return entries.at(id); } - - // Get configuration maps - std::map> getConfigurations(const int id) const { return entries.at(id).getConfigurations(); } - std::map getConfiguration(const int id, const std::string& layerName) const { return entries.at(id).getConfiguration(layerName); } - - // Get specific values - float getFloatValue(const int id, const std::string& layerName, const std::string& key) const { return entries.at(id).getFloatValue(layerName, key); } - - private: - std::vector entries; -}; - // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ // this class implements a synthetic smearer that allows @@ -122,9 +69,6 @@ class FastTracker SetResolutionZ(layerName, resZ); } - void AddSiliconALICE3v4(std::vector pixelResolution); - void AddSiliconALICE3v2(std::vector pixelResolution); - void AddSiliconALICE3(float scaleX0VD, std::vector pixelResolution); void AddTPC(float phiResMean, float zResMean); /** @@ -136,7 +80,7 @@ class FastTracker * * @param configMap Configuration map describing the detector. */ - void AddGenericDetector(GeometryContainer::GeometryEntry configMap, o2::ccdb::BasicCCDBManager* ccdbManager = nullptr); + void AddGenericDetector(o2::fastsim::GeometryEntry configMap, o2::ccdb::BasicCCDBManager* ccdbManager = nullptr); void Print(); @@ -151,7 +95,7 @@ class FastTracker * @param nch Charged particle multiplicity (used for hit density calculations). * @return int i.e. number of intercepts (implementation-defined). */ - int FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch); + int FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch, const float maxRadius = 100.f); // For efficiency calculation float Dist(float z, float radius); diff --git a/ALICE3/Core/GeometryContainer.cxx b/ALICE3/Core/GeometryContainer.cxx new file mode 100644 index 00000000000..aee8e36ebd8 --- /dev/null +++ b/ALICE3/Core/GeometryContainer.cxx @@ -0,0 +1,292 @@ +// 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 GeometryContainer.h +/// \author Nicolò Jacazio, Università del Piemonte Orientale (IT) +/// \brief Set of utilities for the ALICE3 geometry handling +/// \since February 13, 2026 +/// + +#include "GeometryContainer.h" + +#include "Common/Core/TableHelper.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace o2::fastsim +{ + +std::map> GeometryEntry::parseTEnvConfiguration(std::string& filename, std::vector& layers) +{ + std::map> configMap; + filename = gSystem->ExpandPathName(filename.c_str()); + LOG(info) << "Parsing TEnv configuration file: " << filename; + TEnv env(filename.c_str()); + THashList* table = env.GetTable(); + layers.clear(); + for (int i = 0; i < table->GetEntries(); ++i) { + const std::string key = table->At(i)->GetName(); + // key should contain exactly one dot + if (key.find('.') == std::string::npos || key.find('.') != key.rfind('.')) { + LOG(fatal) << "Key " << key << " does not contain exactly one dot"; + continue; + } + const std::string firstPart = key.substr(0, key.find('.')); + if (std::find(layers.begin(), layers.end(), firstPart) == layers.end()) { + layers.push_back(firstPart); + } + } + env.Print(); + // Layers + for (const auto& layer : layers) { + LOG(info) << " Reading layer " << layer; + for (int i = 0; i < table->GetEntries(); ++i) { + const std::string key = table->At(i)->GetName(); + if (key.find(layer + ".") == 0) { + const std::string paramName = key.substr(key.find('.') + 1); + const std::string value = env.GetValue(key.c_str(), ""); + configMap[layer][paramName] = value; + } + } + } + return configMap; +} + +bool GeometryContainer::mCleanLutWhenLoaded = true; +void GeometryContainer::init(o2::framework::InitContext& initContext) +{ + std::vector detectorConfiguration; + const bool foundDetectorConfiguration = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "detectorConfiguration", detectorConfiguration, false); + if (!foundDetectorConfiguration) { + LOG(fatal) << "Could not retrieve detector configuration from OnTheFlyDetectorGeometryProvider task."; + return; + } + LOG(info) << "Size of detector configuration: " << detectorConfiguration.size(); + + bool cleanLutWhenLoaded; + const bool foundCleanLutWhenLoaded = common::core::getTaskOptionValue(initContext, "on-the-fly-detector-geometry-provider", "cleanLutWhenLoaded", cleanLutWhenLoaded, false); + if (!foundCleanLutWhenLoaded) { + LOG(fatal) << "Could not retrieve foundCleanLutWhenLoaded option from OnTheFlyDetectorGeometryProvider task."; + return; + } + setLutCleanupSetting(cleanLutWhenLoaded); + + for (std::string& configFile : detectorConfiguration) { + LOG(info) << "Detector geometry configuration file used: " << configFile; + addEntry(configFile); + } +} + +void GeometryContainer::addEntry(const std::string& filename) +{ + if (!mCcdb) { + LOG(fatal) << " --- ccdb is not set"; + } + mEntries.emplace_back(filename, mCcdb); +} + +std::map GeometryEntry::getConfiguration(const std::string& layerName) const +{ + auto it = mConfigurations.find(layerName); + if (it != mConfigurations.end()) { + return it->second; + } else { + LOG(fatal) << "Layer " << layerName << " not found in geometry configurations."; + return {}; + } +} + +bool GeometryEntry::hasValue(const std::string& layerName, const std::string& key) const +{ + auto layerIt = mConfigurations.find(layerName); + if (layerIt != mConfigurations.end()) { + auto keyIt = layerIt->second.find(key); + return keyIt != layerIt->second.end(); + } + return false; +} + +std::string GeometryEntry::getValue(const std::string& layerName, const std::string& key, bool require) const +{ + auto layer = getConfiguration(layerName); + auto entry = layer.find(key); + if (entry != layer.end()) { + return layer.at(key); + } else if (require) { + LOG(fatal) << "Key " << key << " not found in layer " << layerName << " configurations."; + return ""; + } else { + return ""; + } +} + +void GeometryEntry::replaceValue(const std::string& layerName, const std::string& key, const std::string& value) +{ + if (!hasValue(layerName, key)) { // check that the key exists + LOG(fatal) << "Key " << key << " does not exist in layer " << layerName << ". Cannot replace value."; + } + setValue(layerName, key, value); +} + +std::string GeometryEntry::accessFile(const std::string& path, const std::string downloadPath, o2::ccdb::BasicCCDBManager* ccdb, int timeoutSeconds) +{ + + if (path.rfind("ccdb:", 0) == 0) { + const std::string ccdbPath = path.substr(5); // remove "ccdb:" prefix + const std::string localPath = Form("%s/%s/snapshot.root", downloadPath.c_str(), ccdbPath.c_str()); + const std::string lockFile = localPath + ".lock"; + const std::string doneFile = localPath + ".done"; + + // Create directory structure if it doesn't exist + std::string dirPath = localPath.substr(0, localPath.find_last_of('/')); + gSystem->mkdir(dirPath.c_str(), true); + + // Check if file is already fully downloaded + struct stat buffer; + if (stat(doneFile.c_str(), &buffer) == 0) { + LOG(info) << " --- Geometry configuration file already exists: " << localPath << ". Skipping download."; + return localPath; + } + + // Acquire file lock for inter-process synchronization + int lockFd = open(lockFile.c_str(), O_CREAT | O_RDWR, 0666); + if (lockFd == -1) { + LOG(error) << " --- Failed to create lock file: " << lockFile; + return localPath; + } + + // Try to acquire exclusive lock (non-blocking) + LOG(info) << " --- Attempting to acquire lock for: " << localPath; + int lockResult = flock(lockFd, LOCK_EX | LOCK_NB); + + if (lockResult == -1 && errno == EWOULDBLOCK) { + // Lock is held by another process - wait up to 10 minutes for download to complete + LOG(info) << " --- Lock is held by another process. Waiting for download to complete (up to 10 minutes)..."; + close(lockFd); + + const auto startTime = std::chrono::steady_clock::now(); + const auto timeout = std::chrono::minutes(10); + const auto checkInterval = std::chrono::seconds(5); + + while (true) { + // Check if download is complete + if (stat(doneFile.c_str(), &buffer) == 0) { + LOG(info) << " --- Geometry configuration file was downloaded by another process: " << localPath; + return localPath; + } + + // Check timeout + auto elapsed = std::chrono::steady_clock::now() - startTime; + if (elapsed >= timeout) { + LOG(fatal) << " --- Timeout waiting for geometry file download: " << localPath << ". Waited for 10 minutes."; + return localPath; + } + + // Wait before checking again + std::this_thread::sleep_for(checkInterval); + } + } else if (lockResult == -1) { + LOG(error) << " --- Failed to acquire lock for: " << lockFile; + close(lockFd); + return localPath; + } + + // Lock acquired successfully - double-check if file was downloaded while we were trying + if (stat(doneFile.c_str(), &buffer) == 0) { + LOG(info) << " --- Geometry configuration file was downloaded by another process: " << localPath; + flock(lockFd, LOCK_UN); + close(lockFd); + return localPath; + } + + // File does not exist, retrieve from CCDB + LOG(info) << " --- CCDB source detected for detector geometry " << path; + std::map metadata; + bool status = ccdb->getCCDBAccessor().retrieveBlob(ccdbPath, downloadPath, metadata, 1); + if (!status) { + flock(lockFd, LOCK_UN); + close(lockFd); + LOG(fatal) << " --- Failed to retrieve geometry configuration from CCDB for path: " << ccdbPath; + return ""; + } + LOG(info) << " --- Retrieved geometry configuration from CCDB to: " << localPath; + + // Verify the integrity of the downloaded file + if (stat(localPath.c_str(), &buffer) != 0) { + flock(lockFd, LOCK_UN); + close(lockFd); + LOG(fatal) << " --- Downloaded file does not exist or is not accessible: " << localPath; + return ""; + } + if (buffer.st_size == 0) { + flock(lockFd, LOCK_UN); + close(lockFd); + LOG(fatal) << " --- Downloaded file is empty: " << localPath; + return ""; + } + LOG(info) << " --- File integrity verified. Size: " << buffer.st_size << " bytes"; + + // Create done marker file to indicate successful download + std::ofstream doneMarker(doneFile); + doneMarker.close(); + + // Release lock + flock(lockFd, LOCK_UN); + close(lockFd); + + // If timeout is specified, schedule file deletion after timeout + if (timeoutSeconds > 0 && GeometryContainer::cleanLutWhenLoaded()) { + LOG(info) << " --- Deleting geometry configuration file after timeout: " << localPath; + std::thread deletionThread([localPath, doneFile, timeoutSeconds]() { + LOG(info) << " --- Operating deletion of geometry configuration file after timeout: " << localPath; + std::this_thread::sleep_for(std::chrono::seconds(timeoutSeconds)); + if (std::remove(localPath.c_str()) == 0) { + LOG(info) << " --- File deleted successfully: " << localPath; + } else { + LOG(warning) << " --- Failed to delete file: " << localPath; + } + // Also remove the done marker file + if (std::remove(doneFile.c_str()) == 0) { + LOG(info) << " --- Done marker deleted: " << doneFile; + } + }); + deletionThread.detach(); + } + + return localPath; + } + return path; +} + +} // namespace o2::fastsim diff --git a/ALICE3/Core/GeometryContainer.h b/ALICE3/Core/GeometryContainer.h new file mode 100644 index 00000000000..d5892b5b97b --- /dev/null +++ b/ALICE3/Core/GeometryContainer.h @@ -0,0 +1,119 @@ +// 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 GeometryContainer.h +/// \author Nicolò Jacazio, Università del Piemonte Orientale (IT) +/// \brief Set of utilities for the ALICE3 geometry handling +/// \since February 13, 2026 +/// + +#ifndef ALICE3_CORE_GEOMETRYCONTAINER_H_ +#define ALICE3_CORE_GEOMETRYCONTAINER_H_ + +#include +#include +#include + +#include +#include +#include + +namespace o2::fastsim +{ + +// A container for the geometry info +struct GeometryEntry { + // Default constructor + GeometryEntry() = default; + explicit GeometryEntry(std::string filename, o2::ccdb::BasicCCDBManager* ccdb = nullptr) + { + mFileName = accessFile(filename, "./.ALICE3/Configuration/", ccdb); + mConfigurations = GeometryEntry::parseTEnvConfiguration(mFileName, mLayerNames); + LOG(info) << "Loaded geometry configuration from file: " << mFileName << " with " << mLayerNames.size() << " layers."; + if (mLayerNames.empty()) { + LOG(warning) << "No layers found in geometry configuration file: " << filename; + } + } + + /** + * @brief Parses a TEnv configuration file and returns the key-value pairs split per entry + * @param filename Path to the TEnv configuration file + * @param layers Vector to store the order of the layers as they appear in the file + * @return A map where each key is a layer name and the value is another map of key-value pairs for that layer + */ + static std::map> parseTEnvConfiguration(std::string& filename, std::vector& layers); + + /** + * @brief Accesses a file given its path, which can be either a local path or a ccdb path (starting with "ccdb:"). In the first case it returns the local path, in the second it retrieves the file from ccdb and returns the local path to the retrieved file. + * @param path The path to the file, either local or ccdb (starting with "ccdb:") + * @param downloadPath The local path where to download the file if it's a ccdb path. Default is "/tmp/GeometryContainer/" + * @param ccdb Pointer to the CCDB manager to use for retrieving the file if it's a ccdb path. If nullptr, the function will create a temporary CCDB manager instance. Default is nullptr. + * @param timeoutSeconds If positive, then this function will wait for these seconds after download before removing the downloaded file. + * @return The local path to the file, either the original local path or the path to the retrieved file from ccdb + */ + static std::string accessFile(const std::string& path, const std::string downloadPath = "/tmp/GeometryContainer/", o2::ccdb::BasicCCDBManager* ccdb = nullptr, int timeoutSeconds = 0); + + std::map> getConfigurations() const { return mConfigurations; } + std::map getConfiguration(const std::string& layerName) const; + std::vector getLayerNames() const { return mLayerNames; } + bool hasValue(const std::string& layerName, const std::string& key) const; + std::string getValue(const std::string& layerName, const std::string& key, bool require = true) const; + void setValue(const std::string& layerName, const std::string& key, const std::string& value) { mConfigurations[layerName][key] = value; } + void replaceValue(const std::string& layerName, const std::string& key, const std::string& value); + float getFloatValue(const std::string& layerName, const std::string& key) const { return std::stof(getValue(layerName, key)); } + int getIntValue(const std::string& layerName, const std::string& key) const { return std::stoi(getValue(layerName, key)); } + + private: + std::string mFileName; // Filename of the geometry + std::map> mConfigurations; // Layer configurations + std::vector mLayerNames; // Ordered names of the layers +}; + +class GeometryContainer +{ + public: + GeometryContainer() = default; + virtual ~GeometryContainer() = default; + + /** + * @brief Initializes the GeometryContainer by retrieving the list of geometry configuration files from the OnTheFlyDetectorGeometryProvider task options and parsing them to fill the container entries. + **/ + void init(o2::framework::InitContext& initContext); + + // Add a geometry entry from a configuration file + void addEntry(const std::string& filename); + static void setLutCleanupSetting(const bool cleanLutWhenLoaded) { mCleanLutWhenLoaded = cleanLutWhenLoaded; } + void setCcdbManager(o2::ccdb::BasicCCDBManager* mgr) { mCcdb = mgr; } + + // Getters + int getNumberOfConfigurations() const { return mEntries.size(); } + const std::vector& getEntries() const { return mEntries; } + const GeometryEntry& getEntry(const int id) const { return mEntries.at(id); } + GeometryEntry getGeometryEntry(const int id) const { return mEntries.at(id); } + static bool cleanLutWhenLoaded() { return mCleanLutWhenLoaded; } + + // Get configuration maps + std::map> getConfigurations(const int id) const { return mEntries.at(id).getConfigurations(); } + std::map getConfiguration(const int id, const std::string& layerName) const { return mEntries.at(id).getConfiguration(layerName); } + + // Get specific values + std::string getValue(const int id, const std::string& layerName, const std::string& key, bool require = true) const { return mEntries.at(id).getValue(layerName, key, require); } + float getFloatValue(const int id, const std::string& layerName, const std::string& key) const { return mEntries.at(id).getFloatValue(layerName, key); } + + private: + static bool mCleanLutWhenLoaded; // Whether to clean the LUT when loading a new geometry configuration + std::vector mEntries; + o2::ccdb::BasicCCDBManager* mCcdb = nullptr; +}; + +} // namespace o2::fastsim + +#endif // ALICE3_CORE_GEOMETRYCONTAINER_H_ diff --git a/ALICE3/Core/TOFResoALICE3.cxx b/ALICE3/Core/TOFResoALICE3.cxx index ebd5247230b..6d3bdd40383 100644 --- a/ALICE3/Core/TOFResoALICE3.cxx +++ b/ALICE3/Core/TOFResoALICE3.cxx @@ -18,6 +18,10 @@ #include "ALICE3/Core/TOFResoALICE3.h" +#include + +#include + namespace o2::pid::tof { diff --git a/ALICE3/Core/TOFResoALICE3.h b/ALICE3/Core/TOFResoALICE3.h index b102091f756..e392d120ecf 100644 --- a/ALICE3/Core/TOFResoALICE3.h +++ b/ALICE3/Core/TOFResoALICE3.h @@ -16,14 +16,18 @@ /// \brief Implementation for the TOF PID response of the expected times resolution /// -#ifndef O2_ANALYSIS_PID_TOFRESOALICE3_H_ -#define O2_ANALYSIS_PID_TOFRESOALICE3_H_ +#ifndef ALICE3_CORE_TOFRESOALICE3_H_ +#define ALICE3_CORE_TOFRESOALICE3_H_ -// O2 includes -#include "PID/ParamBase.h" -#include "PID/DetectorResponse.h" -#include "PID/PIDTOF.h" -#include "ReconstructionDataFormats/PID.h" +#include +#include + +#include + +#include +#include + +#include namespace o2::pid::tof { @@ -72,4 +76,4 @@ float TOFResoALICE3ParamTrack(const T& track, const Parameters& parameters) } // namespace o2::pid::tof -#endif +#endif // ALICE3_CORE_TOFRESOALICE3_H_ diff --git a/ALICE3/Core/TrackUtilities.cxx b/ALICE3/Core/TrackUtilities.cxx index c07fe145ccf..739e1df28ae 100644 --- a/ALICE3/Core/TrackUtilities.cxx +++ b/ALICE3/Core/TrackUtilities.cxx @@ -17,6 +17,13 @@ #include "TrackUtilities.h" +#include +#include + +#include + +#include +#include #include void o2::upgrade::convertTLorentzVectorToO2Track(const int charge, diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index dcfb3bfb245..d883a0d2dc8 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -18,9 +18,9 @@ #ifndef ALICE3_CORE_TRACKUTILITIES_H_ #define ALICE3_CORE_TRACKUTILITIES_H_ -#include "ReconstructionDataFormats/Track.h" +#include -#include "TLorentzVector.h" +#include #include @@ -33,8 +33,10 @@ struct OTFParticle { float mE; float mVx, mVy, mVz; float mPx, mPy, mPz; + bool mIsAlive; // Setters + void setIsAlive(bool isAlive) { mIsAlive = isAlive; } void setPDG(int pdg) { mPdgCode = pdg; } void setVxVyVz(float vx, float vy, float vz) { @@ -52,6 +54,7 @@ struct OTFParticle { // Getters int pdgCode() const { return mPdgCode; } + bool isAlive() const { return mIsAlive; } float vx() const { return mVx; } float vy() const { return mVy; } float vz() const { return mVz; } @@ -97,7 +100,9 @@ void convertTLorentzVectorToO2Track(int pdgCode, /// \param o2track the address of the resulting TrackParCov /// \param pdg the pdg service template -void convertOTFParticleToO2Track(const OTFParticle& particle, o2::track::TrackParCov& o2track, const PdgService& pdg) +void convertOTFParticleToO2Track(const OTFParticle& particle, + o2::track::TrackParCov& o2track, + const PdgService& pdg) { static TLorentzVector tlv; tlv.SetPxPyPzE(particle.px(), particle.py(), particle.pz(), particle.e()); diff --git a/ALICE3/DataModel/A3DecayFinderTables.h b/ALICE3/DataModel/A3DecayFinderTables.h index d1c87c989bd..bd9aa5592b3 100644 --- a/ALICE3/DataModel/A3DecayFinderTables.h +++ b/ALICE3/DataModel/A3DecayFinderTables.h @@ -18,11 +18,12 @@ #ifndef ALICE3_DATAMODEL_A3DECAYFINDERTABLES_H_ #define ALICE3_DATAMODEL_A3DECAYFINDERTABLES_H_ -// O2 includes #include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" +#include + +#include +#include enum a3selectionBit : uint32_t { kDCAxy = 0, kInnerTOFPion, @@ -389,6 +390,7 @@ namespace a3_mc_truth DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int); //! DECLARE_SOA_COLUMN(BHadMotherPtRec, bHadMotherPtRec, float); //! DECLARE_SOA_COLUMN(FlagMcRec, flagMcRec, int); //! +DECLARE_SOA_COLUMN(ParticleMcRec, particleMcRec, int); //! DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int); //! DECLARE_SOA_COLUMN(BHadMotherPtGen, bHadMotherPtGen, float); //! DECLARE_SOA_COLUMN(FlagMcGen, flagMcGen, int); //! @@ -396,7 +398,8 @@ DECLARE_SOA_COLUMN(FlagMcGen, flagMcGen, int); //! DECLARE_SOA_TABLE(Alice3McRecFlags, "AOD", "ALICE3MCRECFLAG", //! a3_mc_truth::OriginMcRec, a3_mc_truth::BHadMotherPtRec, - a3_mc_truth::FlagMcRec); + a3_mc_truth::FlagMcRec, + a3_mc_truth::ParticleMcRec); DECLARE_SOA_TABLE(Alice3McGenFlags, "AOD", "ALICE3MCGENFLAG", //! a3_mc_truth::OriginMcGen, diff --git a/ALICE3/DataModel/ECAL.h b/ALICE3/DataModel/ECAL.h index 1e029d24174..9ef1e8a3391 100644 --- a/ALICE3/DataModel/ECAL.h +++ b/ALICE3/DataModel/ECAL.h @@ -16,11 +16,10 @@ /// \brief Set of tables for the ALICE3 ECAL information /// -#ifndef O2_ANALYSIS_ALICE3_ECAL_H_ -#define O2_ANALYSIS_ALICE3_ECAL_H_ +#ifndef ALICE3_DATAMODEL_ECAL_H_ +#define ALICE3_DATAMODEL_ECAL_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { @@ -53,4 +52,4 @@ using ECAL = ECALs::iterator; } // namespace o2::aod -#endif // O2_ANALYSIS_ALICE3_ECAL_H_ +#endif // ALICE3_DATAMODEL_ECAL_H_ diff --git a/ALICE3/DataModel/FTOF.h b/ALICE3/DataModel/FTOF.h index e24c1c0585d..3d047c21fd5 100644 --- a/ALICE3/DataModel/FTOF.h +++ b/ALICE3/DataModel/FTOF.h @@ -16,11 +16,10 @@ /// \brief Set of tables for the ALICE3 FTOF information /// -#ifndef O2_ANALYSIS_ALICE3_FTOF_H_ -#define O2_ANALYSIS_ALICE3_FTOF_H_ +#ifndef ALICE3_DATAMODEL_FTOF_H_ +#define ALICE3_DATAMODEL_FTOF_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { @@ -61,4 +60,4 @@ using FTOF = FTOFs::iterator; } // namespace o2::aod -#endif // O2_ANALYSIS_ALICE3_FTOF_H_ +#endif // ALICE3_DATAMODEL_FTOF_H_ diff --git a/ALICE3/DataModel/MID.h b/ALICE3/DataModel/MID.h index 7d932b90802..7357e689eda 100644 --- a/ALICE3/DataModel/MID.h +++ b/ALICE3/DataModel/MID.h @@ -16,11 +16,12 @@ /// \brief Set of tables for the ALICE3 MID information /// -#ifndef O2_ANALYSIS_ALICE3_MID_H_ -#define O2_ANALYSIS_ALICE3_MID_H_ +#ifndef ALICE3_DATAMODEL_MID_H_ +#define ALICE3_DATAMODEL_MID_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include + +#include namespace o2::aod { @@ -41,4 +42,4 @@ using MID = MIDs::iterator; } // namespace o2::aod -#endif // O2_ANALYSIS_ALICE3_MID_H_ +#endif // ALICE3_DATAMODEL_MID_H_ diff --git a/ALICE3/DataModel/OTFTracks.h b/ALICE3/DataModel/OTFCollision.h similarity index 62% rename from ALICE3/DataModel/OTFTracks.h rename to ALICE3/DataModel/OTFCollision.h index 390e3680716..e146515f89b 100644 --- a/ALICE3/DataModel/OTFTracks.h +++ b/ALICE3/DataModel/OTFCollision.h @@ -10,26 +10,25 @@ // or submit itself to any jurisdiction. /// -/// \file OTFTracks.h +/// \file OTFCollision.h /// \author Jesper Karlsson Gumprecht -/// \since 11/11/2025 -/// \brief Table to map track to LUT configuration +/// \since 26/01/2026 +/// \brief Table to map collisions to LUT configuration /// -#ifndef ALICE3_DATAMODEL_OTFTRACKS_H_ -#define ALICE3_DATAMODEL_OTFTRACKS_H_ +#ifndef ALICE3_DATAMODEL_OTFCOLLISION_H_ +#define ALICE3_DATAMODEL_OTFCOLLISION_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { -namespace otftracks +namespace upgrade_collision { DECLARE_SOA_COLUMN(LUTConfigId, lutConfigId, int); //! Index for LUT configuration -} // namespace otftracks +} // namespace upgrade_collision -DECLARE_SOA_TABLE(OTFLUTConfigId, "AOD", "OTFLUTConfigId", otftracks::LUTConfigId); +DECLARE_SOA_TABLE(OTFLUTConfigId, "AOD", "OTFLUTConfigId", upgrade_collision::LUTConfigId); } // namespace o2::aod -#endif // ALICE3_DATAMODEL_OTFTRACKS_H_ +#endif // ALICE3_DATAMODEL_OTFCOLLISION_H_ diff --git a/ALICE3/DataModel/OTFMCParticle.h b/ALICE3/DataModel/OTFMCParticle.h index 92f5af37c3e..cf24e2e7691 100644 --- a/ALICE3/DataModel/OTFMCParticle.h +++ b/ALICE3/DataModel/OTFMCParticle.h @@ -19,8 +19,7 @@ #ifndef ALICE3_DATAMODEL_OTFMCPARTICLE_H_ #define ALICE3_DATAMODEL_OTFMCPARTICLE_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { @@ -32,16 +31,25 @@ DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(P, p, float); DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(IsAlive, isAlive, bool); +DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); + +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother0, mother0, int, "McPartsWithDau_Mother0"); //! Track index of the first mother +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother1, mother1, int, "McPartsWithDau_Mother1"); //! Track index of the last mother +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter0, daughter0, int, "McPartsWithDau_Daughter0"); //! Track index of the first daugther +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter1, daughter1, int, "McPartsWithDau_Daughter1"); //! Track index of the last daugther +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) +DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) slice. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) } // namespace otfmcparticle -DECLARE_SOA_TABLE_FULL(McParticlesWithDau, "McParticlesWithDau", "AOD", "MCPARTICLEWITHDAU", +DECLARE_SOA_TABLE_FULL(McPartWithDaus, "McPartWithDaus", "AOD", "MCPARTSWITHDAU", o2::soa::Index<>, mcparticle::McCollisionId, mcparticle::PdgCode, mcparticle::StatusCode, mcparticle::Flags, - mcparticle::MothersIds, - mcparticle::DaughtersIdSlice, + otfmcparticle::MothersIds, + otfmcparticle::DaughtersIdSlice, mcparticle::Weight, mcparticle::Px, mcparticle::Py, @@ -56,6 +64,8 @@ DECLARE_SOA_TABLE_FULL(McParticlesWithDau, "McParticlesWithDau", "AOD", "MCPARTI otfmcparticle::Pt, otfmcparticle::P, otfmcparticle::Y, + otfmcparticle::IsAlive, + otfmcparticle::IsPrimary, mcparticle::PVector, mcparticle::ProducedByGenerator, mcparticle::FromBackgroundEvent, @@ -64,7 +74,18 @@ DECLARE_SOA_TABLE_FULL(McParticlesWithDau, "McParticlesWithDau", "AOD", "MCPARTI mcparticle::GetProcess, mcparticle::IsPhysicalPrimary); -using McParticleWithDau = McParticlesWithDau::iterator; +using McPartWithDau = McPartWithDaus::iterator; + +namespace otfmctracklable +{ +DECLARE_SOA_INDEX_COLUMN(McPartWithDau, mcPartWithDau); //! MC particle +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); //! Bit mask to indicate detector mismatches (bit ON means mismatch). Bit 0-6: mismatch at ITS layer. Bit 12: ITSAB tracklet mismatch. Bit 13: ITS-TPC mismatch. Bit 14: isNoise == True (global track), Bit 15: isFake == True (global track) +} // namespace otfmctracklable + +DECLARE_SOA_TABLE(McTrackWithDauLabels, "AOD", "MCTRACKWithDAULABEL", //! Table joined to the track table containing the MC index + otfmctracklable::McPartWithDauId, otfmctracklable::McMask); + +using McTrackWithDauLabel = McTrackWithDauLabels::iterator; } // namespace o2::aod diff --git a/ALICE3/DataModel/OTFMulticharm.h b/ALICE3/DataModel/OTFMulticharm.h index 944aa578ab2..643d36c0adb 100644 --- a/ALICE3/DataModel/OTFMulticharm.h +++ b/ALICE3/DataModel/OTFMulticharm.h @@ -20,10 +20,9 @@ #ifndef ALICE3_DATAMODEL_OTFMULTICHARM_H_ #define ALICE3_DATAMODEL_OTFMULTICHARM_H_ -// O2 includes #include "ALICE3/DataModel/OTFStrangeness.h" -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { @@ -75,31 +74,6 @@ DECLARE_SOA_COLUMN(XicProperLength, xicProperLength, float); DECLARE_SOA_COLUMN(XicDistanceFromPV, xicDistanceFromPV, float); DECLARE_SOA_COLUMN(XiccProperLength, xiccProperLength, float); -// PID -DECLARE_SOA_COLUMN(Pi1cTofDeltaInner, pi1cTofDeltaInner, float); -DECLARE_SOA_COLUMN(Pi1cTofNSigmaInner, pi1cTofNSigmaInner, float); -DECLARE_SOA_COLUMN(Pi1cTofDeltaOuter, pi1cTofDeltaOuter, float); -DECLARE_SOA_COLUMN(Pi1cTofNSigmaOuter, pi1cTofNSigmaOuter, float); -DECLARE_SOA_COLUMN(Pi1cHasRichSignal, pi1cHasRichSignal, bool); -DECLARE_SOA_COLUMN(Pi1cRichNSigma, pi1cRichNSigma, float); -DECLARE_SOA_COLUMN(Pi1cPdgCode, pi1cPdgCode, int); - -DECLARE_SOA_COLUMN(Pi2cTofDeltaInner, pi2cTofDeltaInner, float); -DECLARE_SOA_COLUMN(Pi2cTofNSigmaInner, pi2cTofNSigmaInner, float); -DECLARE_SOA_COLUMN(Pi2cTofDeltaOuter, pi2cTofDeltaOuter, float); -DECLARE_SOA_COLUMN(Pi2cTofNSigmaOuter, pi2cTofNSigmaOuter, float); -DECLARE_SOA_COLUMN(Pi2cHasRichSignal, pi2cHasRichSignal, bool); -DECLARE_SOA_COLUMN(Pi2cRichNSigma, pi2cRichNSigma, float); -DECLARE_SOA_COLUMN(Pi2cPdgCode, pi2cPdgCode, int); - -DECLARE_SOA_COLUMN(PiccTofDeltaInner, piccTofDeltaInner, float); -DECLARE_SOA_COLUMN(PiccTofNSigmaInner, piccTofNSigmaInner, float); -DECLARE_SOA_COLUMN(PiccTofDeltaOuter, piccTofDeltaOuter, float); -DECLARE_SOA_COLUMN(PiccTofNSigmaOuter, piccTofNSigmaOuter, float); -DECLARE_SOA_COLUMN(PiccHasRichSignal, piccHasRichSignal, bool); -DECLARE_SOA_COLUMN(PiccRichNSigma, piccRichNSigma, float); -DECLARE_SOA_COLUMN(PiccPdgCode, piccPdgCode, int); - // Daughter info DECLARE_SOA_COLUMN(PosPt, posPt, float); DECLARE_SOA_COLUMN(PosEta, posEta, float); @@ -159,31 +133,6 @@ DECLARE_SOA_TABLE(MCharmCores, "AOD", "MCharmCores", otfmulticharm::PiccPt, otfmulticharm::LUTConfigId); -DECLARE_SOA_TABLE(MCharmPID, "AOD", "MCharmPID", - otfmulticharm::Pi1cTofDeltaInner, - otfmulticharm::Pi1cTofNSigmaInner, - otfmulticharm::Pi1cTofDeltaOuter, - otfmulticharm::Pi1cTofNSigmaOuter, - otfmulticharm::Pi1cHasRichSignal, - otfmulticharm::Pi1cRichNSigma, - otfmulticharm::Pi1cPdgCode, - - otfmulticharm::Pi2cTofDeltaInner, - otfmulticharm::Pi2cTofNSigmaInner, - otfmulticharm::Pi2cTofDeltaOuter, - otfmulticharm::Pi2cTofNSigmaOuter, - otfmulticharm::Pi2cHasRichSignal, - otfmulticharm::Pi2cRichNSigma, - otfmulticharm::Pi2cPdgCode, - - otfmulticharm::PiccTofDeltaInner, - otfmulticharm::PiccTofNSigmaInner, - otfmulticharm::PiccTofDeltaOuter, - otfmulticharm::PiccTofNSigmaOuter, - otfmulticharm::PiccHasRichSignal, - otfmulticharm::PiccRichNSigma, - otfmulticharm::PiccPdgCode); - DECLARE_SOA_TABLE(MCharmExtra, "AOD", "MCharmExtra", otfmulticharm::BachPt, otfmulticharm::BachEta, diff --git a/ALICE3/DataModel/OTFPIDTrk.h b/ALICE3/DataModel/OTFPIDTrk.h index ce8a5d07a4f..c07a0d6579c 100644 --- a/ALICE3/DataModel/OTFPIDTrk.h +++ b/ALICE3/DataModel/OTFPIDTrk.h @@ -20,8 +20,10 @@ #ifndef ALICE3_DATAMODEL_OTFPIDTRK_H_ #define ALICE3_DATAMODEL_OTFPIDTRK_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include +#include + +#include namespace o2::aod { diff --git a/ALICE3/DataModel/OTFRICH.h b/ALICE3/DataModel/OTFRICH.h index 05771dda57b..bcd42d585ed 100644 --- a/ALICE3/DataModel/OTFRICH.h +++ b/ALICE3/DataModel/OTFRICH.h @@ -19,8 +19,10 @@ #ifndef ALICE3_DATAMODEL_OTFRICH_H_ #define ALICE3_DATAMODEL_OTFRICH_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include +#include + +#include namespace o2::aod { diff --git a/ALICE3/DataModel/OTFStrangeness.h b/ALICE3/DataModel/OTFStrangeness.h index 73bbf0fc39c..395f1ab8681 100644 --- a/ALICE3/DataModel/OTFStrangeness.h +++ b/ALICE3/DataModel/OTFStrangeness.h @@ -19,10 +19,13 @@ #ifndef ALICE3_DATAMODEL_OTFSTRANGENESS_H_ #define ALICE3_DATAMODEL_OTFSTRANGENESS_H_ -// O2 includes #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisDataModel.h" +#include +#include + +#include +#include namespace o2::aod { @@ -35,8 +38,8 @@ 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(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); @@ -55,8 +58,8 @@ DECLARE_SOA_TABLE(UpgradeCascades, "AOD", "UPGRADECASCADES", otfcascade::PosTrackId, otfcascade::NegTrackId, otfcascade::BachTrackId, - otfcascade::DCAV0Daughters, - otfcascade::DCACascadeDaughters, + otfcascade::DcaV0Daughters, + otfcascade::DcaCascadeDaughters, otfcascade::V0Radius, otfcascade::CascRadius, otfcascade::CascRadiusMC, @@ -75,7 +78,7 @@ DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, Tracks, "_Neg"); //! DECLARE_SOA_INDEX_COLUMN(V0, v0); //! index of the mc particle corresponding to the V0 // topo vars -DECLARE_SOA_COLUMN(DCAV0Daughters, dcaV0Daughters, float); +DECLARE_SOA_COLUMN(DcaV0Daughters, dcaV0Daughters, float); DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); DECLARE_SOA_COLUMN(MLambda, mLambda, float); DECLARE_SOA_COLUMN(MAntiLambda, mAntiLambda, float); @@ -91,7 +94,7 @@ DECLARE_SOA_TABLE(UpgradeV0s, "AOD", "UPGRADEV0S", otfv0::V0Id, otfv0::PosTrackId, otfv0::NegTrackId, - otfv0::DCAV0Daughters, + otfv0::DcaV0Daughters, otfv0::V0Radius, otfv0::MLambda, otfv0::MAntiLambda, @@ -107,25 +110,28 @@ DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, Tracks, "_Pos"); //! DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, Tracks, "_Neg"); //! DECLARE_SOA_INDEX_COLUMN(V0, v0); //! +// Label to MC particle +DECLARE_SOA_INDEX_COLUMN_FULL(McParticle, mcParticle, int, McParticles, ""); //! label to the MC particle corresponding to the V0 + // General V0 properties: position, momentum DECLARE_SOA_COLUMN(PosX, posX, float); //! positive track X at min DECLARE_SOA_COLUMN(NegX, negX, float); //! negative track X at min -DECLARE_SOA_COLUMN(PxPos, pxpos, float); //! positive track px at min -DECLARE_SOA_COLUMN(PyPos, pypos, float); //! positive track py at min -DECLARE_SOA_COLUMN(PzPos, pzpos, float); //! positive track pz at min -DECLARE_SOA_COLUMN(PxNeg, pxneg, float); //! negative track px at min -DECLARE_SOA_COLUMN(PyNeg, pyneg, float); //! negative track py at min -DECLARE_SOA_COLUMN(PzNeg, pzneg, float); //! negative track pz at min +DECLARE_SOA_COLUMN(PxPos, pxPos, float); //! positive track px at min +DECLARE_SOA_COLUMN(PyPos, pyPos, float); //! positive track py at min +DECLARE_SOA_COLUMN(PzPos, pzPos, float); //! positive track pz at min +DECLARE_SOA_COLUMN(PxNeg, pxNeg, float); //! negative track px at min +DECLARE_SOA_COLUMN(PyNeg, pyNeg, float); //! negative track py at min +DECLARE_SOA_COLUMN(PzNeg, pzNeg, float); //! negative track pz at min DECLARE_SOA_COLUMN(X, x, float); //! decay position X DECLARE_SOA_COLUMN(Y, y, float); //! decay position Y DECLARE_SOA_COLUMN(Z, z, float); //! decay position Z // topo vars -DECLARE_SOA_COLUMN(DCAV0Daughters, dcaV0Daughters, float); +DECLARE_SOA_COLUMN(DcaV0Daughters, dcaV0Daughters, float); DECLARE_SOA_COLUMN(CosPA, cosPA, float); -DECLARE_SOA_COLUMN(DCAPosToPV, dcaPosToPV, float); -DECLARE_SOA_COLUMN(DCANegToPV, dcaNegToPV, float); -DECLARE_SOA_COLUMN(DCAV0ToPV, dcaV0ToPV, float); +DECLARE_SOA_COLUMN(DcaPosToPV, dcaPosToPV, float); +DECLARE_SOA_COLUMN(DcaNegToPV, dcaNegToPV, float); +DECLARE_SOA_COLUMN(DcaV0ToPV, dcaV0ToPV, float); //______________________________________________________ // DYNAMIC COLUMNS @@ -151,14 +157,14 @@ DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! Pseudorapidity, conditionally defined t return RecoDecay::eta(std::array{pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg}); }); // Length quantities -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); }); // Distance Over To Mom -DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to V0decay distance over total momentum +DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distOverTotMom, //! PV to V0decay distance over total momentum [](float X, float Y, float Z, float pxPos, float pyPos, float pzPos, float pxNeg, float pyNeg, float pzNeg, float pvX, float pvY, float pvZ) { - float P = RecoDecay::sqrtSumOfSquares(pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg); - return std::sqrt(std::pow(X - pvX, 2) + std::pow(Y - pvY, 2) + std::pow(Z - pvZ, 2)) / (P + 1E-10); + float p = RecoDecay::sqrtSumOfSquares(pxPos + pxNeg, pyPos + pyNeg, pzPos + pzNeg); + return std::sqrt(std::pow(X - pvX, 2) + std::pow(Y - pvY, 2) + std::pow(Z - pvZ, 2)) / (p + 1E-10); }); // Armenteros-Podolanski variables @@ -170,7 +176,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Alpha, alpha, //! Armenteros Alpha return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); // alphav0 }); -DECLARE_SOA_DYNAMIC_COLUMN(QtArm, qtarm, //! Armenteros Qt +DECLARE_SOA_DYNAMIC_COLUMN(QtArm, qtArm, //! Armenteros Qt [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { float momTot = RecoDecay::p2(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); float dp = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); @@ -199,29 +205,29 @@ DECLARE_SOA_DYNAMIC_COLUMN(YLambda, yLambda, //! V0 y with lambda or antilambda return RecoDecay::y(std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}, o2::constants::physics::MassLambda); }); // Daughter track momenta -DECLARE_SOA_DYNAMIC_COLUMN(NegativePt, negativept, //! negative daughter pT +DECLARE_SOA_DYNAMIC_COLUMN(NegativePt, negativePt, //! negative daughter pT [](float pxneg, float pyneg) -> float { return RecoDecay::sqrtSumOfSquares(pxneg, pyneg); }); -DECLARE_SOA_DYNAMIC_COLUMN(PositivePt, positivept, //! positive daughter pT +DECLARE_SOA_DYNAMIC_COLUMN(PositivePt, positivePt, //! positive daughter pT [](float pxpos, float pypos) -> float { return RecoDecay::sqrtSumOfSquares(pxpos, pypos); }); -DECLARE_SOA_DYNAMIC_COLUMN(NegativeEta, negativeeta, //! negative daughter eta +DECLARE_SOA_DYNAMIC_COLUMN(NegativeEta, negativeEta, //! negative daughter eta [](float PxNeg, float PyNeg, float PzNeg) -> float { return RecoDecay::eta(std::array{PxNeg, PyNeg, PzNeg}); }); -DECLARE_SOA_DYNAMIC_COLUMN(NegativePhi, negativephi, //! negative daughter phi +DECLARE_SOA_DYNAMIC_COLUMN(NegativePhi, negativePhi, //! negative daughter phi [](float PxNeg, float PyNeg) -> float { return RecoDecay::phi(PxNeg, PyNeg); }); -DECLARE_SOA_DYNAMIC_COLUMN(PositiveEta, positiveeta, //! positive daughter eta +DECLARE_SOA_DYNAMIC_COLUMN(PositiveEta, positiveEta, //! positive daughter eta [](float PxPos, float PyPos, float PzPos) -> float { return RecoDecay::eta(std::array{PxPos, PyPos, PzPos}); }); -DECLARE_SOA_DYNAMIC_COLUMN(PositivePhi, positivephi, //! positive daughter phi +DECLARE_SOA_DYNAMIC_COLUMN(PositivePhi, positivePhi, //! positive daughter phi [](float PxPos, float PyPos) -> float { return RecoDecay::phi(PxPos, PyPos); }); } // namespace candidatev0 DECLARE_SOA_TABLE(V0CandidateIndices, "AOD", "V0CANDIDATEINDEX", //! index table - o2::soa::Index<>, candidatev0::CollisionId, candidatev0::PosTrackId, candidatev0::NegTrackId); + o2::soa::Index<>, candidatev0::CollisionId, candidatev0::PosTrackId, candidatev0::NegTrackId, candidatev0::McParticleId); DECLARE_SOA_TABLE(V0CandidateCores, "AOD", "V0CANDIDATECORE", o2::soa::Index<>, candidatev0::X, candidatev0::Y, candidatev0::Z, candidatev0::PxPos, candidatev0::PyPos, candidatev0::PzPos, candidatev0::PxNeg, candidatev0::PyNeg, candidatev0::PzNeg, - candidatev0::DCAV0Daughters, candidatev0::DCAPosToPV, candidatev0::DCANegToPV, - candidatev0::CosPA, candidatev0::DCAV0ToPV, + candidatev0::DcaV0Daughters, candidatev0::DcaPosToPV, candidatev0::DcaNegToPV, + candidatev0::CosPA, candidatev0::DcaV0ToPV, candidatev0::Px, candidatev0::Py, candidatev0::Pz, @@ -229,7 +235,7 @@ DECLARE_SOA_TABLE(V0CandidateCores, "AOD", "V0CANDIDATECORE", candidatev0::P, candidatev0::Phi, candidatev0::Eta, - candidatev0::V0Radius, + candidatev0::V0radius, candidatev0::DistOverTotMom, candidatev0::Alpha, candidatev0::QtArm, diff --git a/ALICE3/DataModel/OTFTOF.h b/ALICE3/DataModel/OTFTOF.h index 150efc91f5e..b4bf1f26670 100644 --- a/ALICE3/DataModel/OTFTOF.h +++ b/ALICE3/DataModel/OTFTOF.h @@ -20,8 +20,10 @@ #ifndef ALICE3_DATAMODEL_OTFTOF_H_ #define ALICE3_DATAMODEL_OTFTOF_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include +#include + +#include namespace o2::aod { diff --git a/ALICE3/DataModel/RICH.h b/ALICE3/DataModel/RICH.h index ab670002078..a1fc7c7c692 100644 --- a/ALICE3/DataModel/RICH.h +++ b/ALICE3/DataModel/RICH.h @@ -16,12 +16,11 @@ /// \brief Set of tables for the ALICE3 RICH information /// -#ifndef O2_ANALYSIS_ALICE3_RICH_H_ -#define O2_ANALYSIS_ALICE3_RICH_H_ +#ifndef ALICE3_DATAMODEL_RICH_H_ +#define ALICE3_DATAMODEL_RICH_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/PID.h" +#include +#include namespace o2::aod { @@ -176,4 +175,4 @@ using FRICH = FRICHs::iterator; } // namespace o2::aod -#endif // O2_ANALYSIS_ALICE3_RICH_H_ +#endif // ALICE3_DATAMODEL_RICH_H_ diff --git a/ALICE3/DataModel/collisionAlice3.h b/ALICE3/DataModel/collisionAlice3.h index ddb10ca9f1d..a1238e9e1d9 100644 --- a/ALICE3/DataModel/collisionAlice3.h +++ b/ALICE3/DataModel/collisionAlice3.h @@ -19,8 +19,7 @@ #ifndef ALICE3_DATAMODEL_COLLISIONALICE3_H_ #define ALICE3_DATAMODEL_COLLISIONALICE3_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h index 280c5ccb110..04cb2d1a9d4 100644 --- a/ALICE3/DataModel/tracksAlice3.h +++ b/ALICE3/DataModel/tracksAlice3.h @@ -19,8 +19,8 @@ #ifndef ALICE3_DATAMODEL_TRACKSALICE3_H_ #define ALICE3_DATAMODEL_TRACKSALICE3_H_ -// O2 includes -#include "Framework/AnalysisDataModel.h" +#include +#include namespace o2::aod { @@ -29,16 +29,30 @@ 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 +DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); //! PDG code of the linked truth MC particle } // namespace track_alice3 DECLARE_SOA_TABLE(TracksAlice3, "AOD", "TRACKSALICE3", track_alice3::IsReconstructed); using TrackAlice3 = TracksAlice3::iterator; +DECLARE_SOA_TABLE(TracksAlice3Pdg, "AOD", "TRACKSALICE3PDG", + track_alice3::PdgCode); +using TrackAlice3Pdg = TracksAlice3Pdg::iterator; + DECLARE_SOA_TABLE(TracksExtraA3, "AOD", "TracksExtraA3", track_alice3::NSiliconHits, track_alice3::NTPCHits); using TrackExtraA3 = TracksExtraA3::iterator; +namespace mcparticle_alice3 +{ +DECLARE_SOA_COLUMN(NHits, nHits, int); //! number of silicon hits +DECLARE_SOA_COLUMN(Charge, charge, float); //! particle charge +} // namespace mcparticle_alice3 +DECLARE_SOA_TABLE(MCParticlesExtraA3, "AOD", "MCParticlesExtraA3", + mcparticle_alice3::NHits, + mcparticle_alice3::Charge); +using MCParticleExtraA3 = MCParticlesExtraA3::iterator; } // namespace o2::aod #endif // ALICE3_DATAMODEL_TRACKSALICE3_H_ diff --git a/ALICE3/ML/HfMlResponse3Prong.h b/ALICE3/ML/HfMlResponse3Prong.h index 24c7b479213..7c360634d37 100644 --- a/ALICE3/ML/HfMlResponse3Prong.h +++ b/ALICE3/ML/HfMlResponse3Prong.h @@ -19,8 +19,6 @@ #include "Tools/ML/MlResponse.h" #include -#include -#include #include // Fill the map of available input features diff --git a/ALICE3/Macros/CMakeLists.txt b/ALICE3/Macros/CMakeLists.txt index 683fc7b95b1..b9e1c9c448e 100644 --- a/ALICE3/Macros/CMakeLists.txt +++ b/ALICE3/Macros/CMakeLists.txt @@ -13,6 +13,7 @@ install(FILES Configuration/a3geo.ini Configuration/a3geometry_v2_10kG.ini Configuration/a3geometry_v2_20kG_dipole.ini Configuration/a3geometry_v2_20kG.ini + Configuration/a3geometry_v3_extra_ml.ini Configuration/a3geometry_v3.ini Configuration/a3geometry_v4.ini PERMISSIONS GROUP_READ GROUP_EXECUTE OWNER_EXECUTE OWNER_WRITE OWNER_READ WORLD_EXECUTE WORLD_READ diff --git a/ALICE3/Macros/Configuration/a3geo.ini b/ALICE3/Macros/Configuration/a3geo.ini index d7b3ac40e47..3595857d1e5 100644 --- a/ALICE3/Macros/Configuration/a3geo.ini +++ b/ALICE3/Macros/Configuration/a3geo.ini @@ -159,4 +159,10 @@ B10.resZ: 0.001 B10.eff: 1. B10.type: 1 -global.lutEl: /tmp/lutCovm.el.20kG.rmin20.geometry_v2.dat +global.lutEl: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/el +global.lutMu: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/mu +global.lutPi: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/pi +global.lutKa: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/ka +global.lutPr: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/pr + +global.magneticfield: 20 diff --git a/ALICE3/Macros/Configuration/a3geometry_v3.ini b/ALICE3/Macros/Configuration/a3geometry_v3.ini index 0b005aa4759..e4eb415c133 100644 --- a/ALICE3/Macros/Configuration/a3geometry_v3.ini +++ b/ALICE3/Macros/Configuration/a3geometry_v3.ini @@ -147,11 +147,11 @@ B10.eff: 1.00 B10.type: 1 # Lookup tables -global.lutEl: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/el -global.lutMu: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/mu -global.lutPi: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/pi -global.lutKa: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/ka -global.lutPr: ccdb:/Users/j/jekarlss/LookUpTables/NoEloss/pr +global.lutEl: ccdb:/Users/j/jekarlss/LUTs/v3/b/el +global.lutMu: ccdb:/Users/j/jekarlss/LUTs/v3/b/mu +global.lutPi: ccdb:/Users/j/jekarlss/LUTs/v3/b/pi +global.lutKa: ccdb:/Users/j/jekarlss/LUTs/v3/b/ka +global.lutPr: ccdb:/Users/j/jekarlss/LUTs/v3/b/pr # in kGauss global.magneticfield: 20 diff --git a/ALICE3/Macros/Configuration/a3geometry_v3_extra_ml.ini b/ALICE3/Macros/Configuration/a3geometry_v3_extra_ml.ini new file mode 100644 index 00000000000..8d7304d943f --- /dev/null +++ b/ALICE3/Macros/Configuration/a3geometry_v3_extra_ml.ini @@ -0,0 +1,166 @@ +# Format: +# .: +# Example: +# layer1.r: 0.5 # radius in cm +# layer1.z: 250 # half-length in cm +# layer1.x0: 0.001 # radiation length +# layer1.xrho: 0 # density in g/cm^2 +# layer1.resRPhi: 0.0001 # resolution in R-Phi in cm +# layer1.resZ: 0.0001 # resolution in Z in cm +# layer1.eff: 1.0 # efficiency (0 to 1) +# layer1.type: 1 # type of layer (0: passive, 1: active) +# layer1.deadPhiRegions: /path/to/dead_regions.root # optional dead regions file + +bpipe0.r: 0.48 +bpipe0.z: 250 +bpipe0.x0: 0.001592 +bpipe0.xrho: 0 +bpipe0.resRPhi: 0.0f +bpipe0.resZ: 0.0f +bpipe0.eff: 0.0f +bpipe0.type: 0 + +B00.r: 0.5 +B00.z: 250 +B00.x0: 0.00076 +B00.xrho: 0 +B00.resRPhi: 0.00025 +B00.resZ: 0.00025 +B00.eff: 1.00 +B00.type: 1 + +B01.r 1.2 +B01.z 250 +B01.x0 0.00096 +B01.xrho 0 +B01.resRPhi 0.00025 +B01.resZ 0.00025 +B01.eff 1.00 +B01.type 1 + +B02.r: 2.5 +B02.z: 250 +B02.x0: 0.00167 +B02.xrho: 0 +B02.resRPhi: 0.00025 +B02.resZ: 0.00025 +B02.eff: 1.00 +B02.type: 1 + +coldplate.r: 2.6 +coldplate.z: 250 +coldplate.x0: 0.02f +coldplate.xrho: 0 +coldplate.resRPhi: 0.0f +coldplate.resZ: 0.0f +coldplate.eff: 0.0f +coldplate.type: 0 + +bpipe1.r: 5.7 +bpipe1.z: 250 +bpipe1.x0: 0.0023f +bpipe1.xrho: 0 +bpipe1.resRPhi: 0.0f +bpipe1.resZ: 0.0f +bpipe1.eff: 0.0f +bpipe1.type: 0 + +B03.r: 7. +B03.z: 250 +B03.x0: 0.01 +B03.xrho: 2.3292e-01 +B03.resRPhi: 0.001 +B03.resZ: 0.001 +B03.eff: 1.00 +B03.type: 1 + +B04.r: 9. +B04.z: 250 +B04.x0: 0.01 +B04.xrho: 2.3292e-01 +B04.resRPhi: 0.001 +B04.resZ: 0.001 +B04.eff: 1.00 +B04.type: 1 + +B05.r: 12. +B05.z: 250 +B05.x0: 0.01 +B05.xrho: 2.3292e-01 +B05.resRPhi: 0.001 +B05.resZ: 0.001 +B05.eff: 1.00 +B05.type: 1 + +iTOF.r: 19 +iTOF.z: 250 +iTOF.x0: 0.01*3. +iTOF.xrho: 0.03 +iTOF.resRPhi: 0.001 +iTOF.resZ: 0.001 +iTOF.eff: 1.00 +iTOF.type: 0 + +B06.r: 20. +B06.z: 250 +B06.x0: 0.01 +B06.xrho: 2.3292e-01 +B06.resRPhi: 0.001 +B06.resZ: 0.001 +B06.eff: 1.00 +B06.type: 1 + +B07.r: 30. +B07.z: 250 +B07.x0: 0.01 +B07.xrho: 2.3292e-01 +B07.resRPhi: 0.001 +B07.resZ: 0.001 +B07.eff: 1.00 +B07.type: 1 + +B08.r: 35. +B08.z: 250 +B08.x0: 0.01 +B08.xrho: 2.3292e-01 +B08.resRPhi: 0.001 +B08.resZ: 0.001 +B08.eff: 1.00 +B08.type: 1 + +B09.r: 45. +B09.z: 250 +B09.x0: 0.01 +B09.xrho: 2.3292e-01 +B09.resRPhi: 0.001 +B09.resZ: 0.001 +B09.eff: 1.00 +B09.type: 1 + +B10.r: 60. +B10.z: 250 +B10.x0: 0.01 +B10.xrho: 2.3292e-01 +B10.resRPhi: 0.001 +B10.resZ: 0.001 +B10.eff: 1.00 +B10.type: 1 + +B11.r: 80. +B11.z: 250 +B11.x0: 0.01 +B11.xrho: 2.3292e-01 +B11.resRPhi: 0.001 +B11.resZ: 0.001 +B11.eff: 1.00 +B11.type: 1 + +# Lookup tables +global.lutEl: ccdb:/Users/j/jekarlss/LUTs/v3/extra_ml/el +global.lutMu: ccdb:/Users/j/jekarlss/LUTs/v3/extra_ml/mu +global.lutPi: ccdb:/Users/j/jekarlss/LUTs/v3/extra_ml/pi +global.lutKa: ccdb:/Users/j/jekarlss/LUTs/v3/extra_ml/ka +global.lutPr: ccdb:/Users/j/jekarlss/LUTs/v3/extra_ml/pr + +# in kGauss +global.magneticfield: 20 \ No newline at end of file diff --git a/ALICE3/Macros/drawFastTracker.C b/ALICE3/Macros/drawFastTracker.C index f15ebaacc68..71f44970d37 100644 --- a/ALICE3/Macros/drawFastTracker.C +++ b/ALICE3/Macros/drawFastTracker.C @@ -75,7 +75,7 @@ void drawFastTracker(float magneticField = 5.f, // in units of kGauss fastTracker.AddLayer("B11", 100., 250, x0OB, xrhoOB, resRPhiOB, resZOB, eff, 1); } else { std::vector pixelRes{0.025, 0.025, 0.01, 0.01}; - fastTracker.AddSiliconALICE3v4(pixelRes); + // fastTracker.AddSiliconALICE3v4(pixelRes); // FIXME } fastTracker.Print(); diff --git a/ALICE3/Macros/testFastTracker.C b/ALICE3/Macros/testFastTracker.C index f9ec72e0765..68d416295a8 100644 --- a/ALICE3/Macros/testFastTracker.C +++ b/ALICE3/Macros/testFastTracker.C @@ -17,8 +17,7 @@ #include #include - -#include +#include void testFastTracker(std::string geometryFile = "a3geo.ini") { @@ -28,7 +27,7 @@ void testFastTracker(std::string geometryFile = "a3geo.ini") // auto& ccdb = o2::ccdb::BasicCCDBManager::instance(); // ccdb.setURL("http://alice-ccdb.cern.ch"); o2::fastsim::FastTracker fastTracker; - fastTracker.AddGenericDetector(geometryFile); + // fastTracker.AddGenericDetector(geometryFile); // FIXME // fastTracker.AddGenericDetector(geometryFile, &ccdb); fastTracker.Print(); } diff --git a/ALICE3/TableProducer/CMakeLists.txt b/ALICE3/TableProducer/CMakeLists.txt index a3ec83bd851..233088b6d5e 100644 --- a/ALICE3/TableProducer/CMakeLists.txt +++ b/ALICE3/TableProducer/CMakeLists.txt @@ -36,8 +36,8 @@ o2physics_add_dpl_workflow(alice3-decayfinder PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(alice3-multicharm-table - SOURCES alice3-multicharmTable.cxx +o2physics_add_dpl_workflow(alice3-multicharm-finder + SOURCES alice3MulticharmFinder.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) @@ -58,10 +58,15 @@ o2physics_add_dpl_workflow(alice3-hf-tree-creator-3prong o2physics_add_dpl_workflow(alice3-tracking-translator SOURCES alice3TrackingTranslator.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::ALICE3Core COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(alice3-strangeness-finder - SOURCES alice3-strangenessFinder.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore +o2physics_add_dpl_workflow(alice3-dq-table-maker + SOURCES alice3-dq-table-maker.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2Physics::AnalysisCCDB O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(alice3strangenessfinder + SOURCES alice3strangenessFinder.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::ALICE3Core COMPONENT_NAME Analysis) diff --git a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx index f61bab5605f..da4988d5648 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx @@ -19,28 +19,31 @@ #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFMCParticle.h" -#include #include -#include -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#include #include +#include +#include #include -#include +#include #include -#include -#include +#include +#include #include +#include + +#include +#include +#include #include #include +#include #include #include #include @@ -51,7 +54,7 @@ using namespace o2::framework; static constexpr int NumDecays = 7; static constexpr int NumParameters = 1; static constexpr int DefaultParameters[NumDecays][NumParameters]{{1}, {1}, {1}, {1}, {1}, {1}, {1}}; -static constexpr float VerySmall = 1e-7f; +static constexpr float Tolerance = 1e-7f; static const std::vector parameterNames{"enable"}; static const std::vector particleNames{"K0s", "Lambda", @@ -69,14 +72,15 @@ static const std::vector pdgCodes{kK0Short, kOmegaPlusBar}; struct OnTheFlyDecayer { - Produces tableMcParticlesWithDau; + Produces tableMcParticlesWithDau; o2::upgrade::Decayer decayer; Service pdgDB; - std::map> mDecayDaughters; + std::map> mDecayDaughters; Configurable seed{"seed", 0, "Set seed for particle decayer"}; Configurable magneticField{"magneticField", 20., "Magnetic field (kG)"}; + Configurable maxEta{"maxEta", 2.5, "Only decay particles that appear within selected eta range"}; Configurable> enabledDecays{"enabledDecays", {DefaultParameters[0], NumDecays, NumParameters, particleNames, parameterNames}, "Enable option for particle to be decayed: 0 - no, 1 - yes"}; @@ -84,9 +88,71 @@ struct OnTheFlyDecayer { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; 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"}; + struct McParticleAlice3 { + McParticleAlice3() = default; + ~McParticleAlice3() = default; + McParticleAlice3(const McParticleAlice3& src) = default; + McParticleAlice3(int collisionId, + int pdgCode, + int statusCode, + int flags, + int mother0, + int mother1, + int daughter0, + int daughter1, + float weight, + float px, float py, float pz, float e, + float vx, float vy, float vz, float vt, + float phi, float eta, float pt, float p, float y, + bool isAlive, bool isPrimary) : collisionId(collisionId), + pdgCode(pdgCode), + statusCode(statusCode), + flags(flags), + mothersIds{mother0, mother1}, + daughtersIdSlice{daughter0, daughter1}, + weight(weight), + px(px), + py(py), + pz(pz), + e(e), + vx(vx), + vy(vy), + vz(vz), + vt(vt), + phi(phi), + eta(eta), + pt(pt), + p(p), + y(y), + isAlive(isAlive), + isPrimary(isPrimary) {} + + bool hasNaN() const + { + return std::isnan(px) || std::isnan(py) || std::isnan(pz) || std::isnan(e) || + std::isnan(vx) || std::isnan(vy) || std::isnan(vz) || std::isnan(vt) || + std::isnan(phi) || std::isnan(eta) || std::isnan(pt) || std::isnan(p) || + std::isnan(y) || std::isnan(weight); + } + + int collisionId; + int pdgCode; + int statusCode; + int flags; + int mothersIds[2]; + int daughtersIdSlice[2]; + float weight; + float px, py, pz, e; + float vx, vy, vz, vt; + float phi, eta, pt, p, y; + bool isAlive; + bool isPrimary; + }; + std::vector mEnabledDecays; void init(o2::framework::InitContext&) { + LOG(info) << "Initializing on-the-fly-decayer."; decayer.setSeed(seed); decayer.setBField(magneticField); for (int i = 0; i < NumDecays; ++i) { @@ -95,6 +161,10 @@ struct OnTheFlyDecayer { } } + auto hNaNBookkeeping = histos.add("hNaNBookkeeping", "hNaNBookkeeping", kTH1D, {{2, -0.5, 1.5}}); + hNaNBookkeeping->GetXaxis()->SetBinLabel(1, "OK"); + hNaNBookkeeping->GetXaxis()->SetBinLabel(2, "NaN"); + histos.add("K0S/hGenK0S", "hGenK0S", kTH1D, {axisPt}); histos.add("Lambda/hGenLambda", "hGenLambda", kTH1D, {axisPt}); histos.add("AntiLambda/hGenAntiLambda", "hGenAntiLambda", kTH1D, {axisPt}); @@ -102,6 +172,12 @@ struct OnTheFlyDecayer { histos.add("AntiXi/hGenAntiXi", "hGenAntiXi", kTH1D, {axisPt}); histos.add("Omega/hGenOmega", "hGenOmega", kTH1D, {axisPt}); histos.add("AntiOmega/hGenAntiOmega", "hGenAntiOmega", kTH1D, {axisPt}); + + histos.add("GeneratedElectron/hGenEl", "hGenEl", kTH1D, {axisPt}); + histos.add("GeneratedMuon/hGenMu", "hGenMu", kTH1D, {axisPt}); + histos.add("GeneratedPion/hGenPi", "hGenPi", kTH1D, {axisPt}); + histos.add("GeneratedKaon/hGenKa", "hGenKa", kTH1D, {axisPt}); + histos.add("GeneratedProton/hGenPr", "hGenPr", kTH1D, {axisPt}); } bool canDecay(const int pdgCode) @@ -109,31 +185,36 @@ struct OnTheFlyDecayer { return std::find(mEnabledDecays.begin(), mEnabledDecays.end(), pdgCode) != mEnabledDecays.end(); } + std::vector mcParticlesAlice3; void process(aod::McCollision const&, aod::McParticles const& mcParticles) { mDecayDaughters.clear(); + mcParticlesAlice3.clear(); u_int64_t nStoredDaughters = 0; - for (int64_t index{0}; index < mcParticles.size(); ++index) { - const auto& particle = mcParticles.iteratorAt(index); - std::vector decayDaughters; - static constexpr int MaxNestedDecays = 10; - int nDecays = 0; - if (canDecay(particle.pdgCode())) { + for (int index{0}; index < static_cast(mcParticles.size()); ++index) { + const auto& particle = mcParticles.rawIteratorAt(index); + std::vector decayDaughters, decayStack; + if (canDecay(particle.pdgCode()) && std::abs(particle.eta()) < maxEta) { o2::track::TrackParCov o2track; o2::upgrade::convertMCParticleToO2Track(particle, o2track, pdgDB); - decayDaughters = decayer.decayParticle(pdgDB, o2track, particle.pdgCode()); - for (size_t idau{0}; idau < decayDaughters.size(); ++idau) { - const auto& dau = decayDaughters[idau]; + decayStack = decayer.decayParticle(pdgDB, o2track, particle.pdgCode()); + while (!decayStack.empty()) { + o2::upgrade::OTFParticle otfParticle = decayStack.back(); + decayStack.pop_back(); + + const bool stable = !canDecay(otfParticle.pdgCode()); + otfParticle.setIsAlive(stable); + decayDaughters.push_back(otfParticle); + + if (stable) { + continue; + } + o2::track::TrackParCov dauTrack; - o2::upgrade::convertOTFParticleToO2Track(dau, dauTrack, pdgDB); - if (canDecay(dau.pdgCode())) { - std::vector cascadingDaughers = decayer.decayParticle(pdgDB, dauTrack, dau.pdgCode()); - for (const auto& daudau : cascadingDaughers) { - decayDaughters.push_back(daudau); - if (MaxNestedDecays < ++nDecays) { - LOG(error) << "Seemingly stuck trying to perpetually decay products from pdg: " << particle.pdgCode(); - } - } + o2::upgrade::convertOTFParticleToO2Track(otfParticle, dauTrack, pdgDB); + std::vector daughters = decayer.decayParticle(pdgDB, dauTrack, otfParticle.pdgCode()); + for (o2::upgrade::OTFParticle dau : daughters) { + decayStack.push_back(dau); } } @@ -141,22 +222,39 @@ struct OnTheFlyDecayer { LOG(error) << "Attempted to decay " << particle.pdgCode() << " but resulting vector of daugthers were empty"; continue; } - } - if (particle.pdgCode() == kK0Short) { - histos.fill(HIST("K0S/hGenK0S"), particle.pt()); - } else if (particle.pdgCode() == kLambda0) { - histos.fill(HIST("Lambda/hGenLambda"), particle.pt()); - } else if (particle.pdgCode() == kLambda0Bar) { - histos.fill(HIST("AntiLambda/hGenAntiLambda"), particle.pt()); - } else if (particle.pdgCode() == kXiMinus) { - histos.fill(HIST("Xi/hGenXi"), particle.pt()); - } else if (particle.pdgCode() == kXiPlusBar) { - histos.fill(HIST("AntiXi/hGenAntiXi"), particle.pt()); - } else if (particle.pdgCode() == kOmegaMinus) { - histos.fill(HIST("Omega/hGenOmega"), particle.pt()); - } else if (particle.pdgCode() == kOmegaPlusBar) { - histos.fill(HIST("AntiOmega/hGenAntiOmega"), particle.pt()); + switch (particle.pdgCode()) { + case kK0Short: + histos.fill(HIST("K0S/hGenK0S"), particle.pt()); + break; + + case kLambda0: + histos.fill(HIST("Lambda/hGenLambda"), particle.pt()); + break; + + case kLambda0Bar: + histos.fill(HIST("AntiLambda/hGenAntiLambda"), particle.pt()); + break; + + case kXiMinus: + histos.fill(HIST("Xi/hGenXi"), particle.pt()); + break; + + case kXiPlusBar: + histos.fill(HIST("AntiXi/hGenAntiXi"), particle.pt()); + break; + + case kOmegaMinus: + histos.fill(HIST("Omega/hGenOmega"), particle.pt()); + break; + + case kOmegaPlusBar: + histos.fill(HIST("AntiOmega/hGenAntiOmega"), particle.pt()); + break; + + default: + break; + } } int daughtersIdSlice[2]; @@ -168,23 +266,22 @@ struct OnTheFlyDecayer { daughtersIdSlice[1] = static_cast(particle.daughtersIds()[1]); } - std::span motherSpan(particle.mothersIds().data(), particle.mothersIds().size()); mDecayDaughters.emplace(index, decayDaughters); nStoredDaughters += decayDaughters.size(); - float phi = o2::constants::math::PI + std::atan2(-1.0f * particle.py(), -1.0f * particle.px()); + const float phi = o2::constants::math::PI + std::atan2(-1.0f * particle.py(), -1.0f * particle.px()); float eta; // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 - float pt = std::sqrt(particle.px() * particle.px() + particle.py() * particle.py()); - float p = std::sqrt(particle.px() * particle.px() + particle.py() * particle.py() + particle.pz() * particle.pz()); + const float pt = std::sqrt(particle.px() * particle.px() + particle.py() * particle.py()); + const float p = std::sqrt(particle.px() * particle.px() + particle.py() * particle.py() + particle.pz() * particle.pz()); float y; // As https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 - if ((p - particle.pz()) < VerySmall) { + if ((p - particle.pz()) < Tolerance) { eta = (particle.pz() < 0.0f) ? -100.0f : 100.0f; } else { eta = 0.5f * std::log((p + particle.pz()) / (p - particle.pz())); } - if ((particle.e() - particle.pz()) < VerySmall) { + if ((particle.e() - particle.pz()) < Tolerance) { y = (particle.pz() < 0.0f) ? -100.0f : 100.0f; } else { y = 0.5f * std::log((particle.e() + particle.pz()) / (particle.e() - particle.pz())); @@ -192,53 +289,95 @@ struct OnTheFlyDecayer { // TODO: Particle status code // TODO: Expression columns - tableMcParticlesWithDau(particle.mcCollisionId(), particle.pdgCode(), particle.statusCode(), - particle.flags(), motherSpan, daughtersIdSlice, particle.weight(), - particle.px(), particle.py(), particle.pz(), particle.e(), - particle.vx(), particle.vy(), particle.vz(), particle.vt(), - phi, eta, pt, p, y); + auto mothers = particle.mothersIds(); + int mother0 = mothers.size() > 0 ? mothers[0] : -1; + int mother1 = mothers.size() > 1 ? mothers[1] : mother0; + mcParticlesAlice3.push_back(McParticleAlice3{particle.mcCollisionId(), particle.pdgCode(), particle.statusCode(), + particle.flags(), mother0, mother1, + daughtersIdSlice[0], daughtersIdSlice[1], particle.weight(), + particle.px(), particle.py(), particle.pz(), particle.e(), + particle.vx(), particle.vy(), particle.vz(), particle.vt(), + phi, eta, pt, p, y, !canDecay(particle.pdgCode()), true}); } int daughtersIdSlice[2] = {-1, -1}; for (const auto& [index, decayDaughters] : mDecayDaughters) { for (const auto& dau : decayDaughters) { if (index >= mcParticles.size()) { - LOG(warn) << "--- Index " << index << " out of bounds for mcParticles table of size " << mcParticles.size(); + LOG(error) << "--- Index " << index << " out of bounds for mcParticles table of size " << mcParticles.size() << std::endl; continue; } - auto mother = mcParticles.iteratorAt(index); - std::vector motherIds = {static_cast(index)}; - std::span motherSpan(motherIds.data(), motherIds.size()); - - float phi = o2::constants::math::PI + std::atan2(-1.0f * dau.py(), -1.0f * dau.px()); + const float phi = o2::constants::math::PI + std::atan2(-1.0f * dau.py(), -1.0f * dau.px()); float eta; // Conditional as https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1922 - float pt = std::sqrt(dau.px() * dau.px() + dau.py() * dau.py()); - float p = std::sqrt(dau.px() * dau.px() + dau.py() * dau.py() + dau.pz() * dau.pz()); + const float pt = std::sqrt(dau.px() * dau.px() + dau.py() * dau.py()); + const float p = std::sqrt(dau.px() * dau.px() + dau.py() * dau.py() + dau.pz() * dau.pz()); float y; // Conditional as https://github.com/AliceO2Group/AliceO2/blob/dev/Framework/Core/include/Framework/AnalysisDataModel.h#L1943 - if ((p - dau.pz()) < VerySmall) { + if ((p - dau.pz()) < Tolerance) { eta = (dau.pz() < 0.0f) ? -100.0f : 100.0f; } else { eta = 0.5f * std::log((p + dau.pz()) / (p - dau.pz())); } - if ((dau.e() - dau.pz()) < VerySmall) { + if ((dau.e() - dau.pz()) < Tolerance) { y = (dau.pz() < 0.0f) ? -100.0f : 100.0f; } else { y = 0.5f * std::log((dau.e() + dau.pz()) / (dau.e() - dau.pz())); } + switch (dau.pdgCode()) { + case kElectron: + histos.fill(HIST("GeneratedElectron/hGenEl"), pt); + break; + + case kMuonMinus: + histos.fill(HIST("GeneratedMuon/hGenMu"), pt); + break; + + case kPiPlus: + histos.fill(HIST("GeneratedPion/hGenPi"), pt); + break; + + case kKPlus: + histos.fill(HIST("GeneratedKaon/hGenKa"), pt); + break; + + case kProton: + histos.fill(HIST("GeneratedProton/hGenPr"), pt); + break; + + default: + break; + } + // TODO: Particle status code // TODO: Expression columns // TODO: vt - tableMcParticlesWithDau(mother.mcCollisionId(), dau.pdgCode(), 1, - mother.flags(), motherSpan, daughtersIdSlice, mother.weight(), - dau.px(), dau.py(), dau.pz(), dau.e(), - dau.vx(), dau.vy(), dau.vz(), mother.vt(), - phi, eta, pt, p, y); + auto mother = mcParticles.rawIteratorAt(index); + mcParticlesAlice3.push_back(McParticleAlice3{mother.mcCollisionId(), dau.pdgCode(), 1, + -1, index, index, daughtersIdSlice[0], daughtersIdSlice[1], mother.weight(), + dau.px(), dau.py(), dau.pz(), dau.e(), + dau.vx(), dau.vy(), dau.vz(), mother.vt(), + phi, eta, pt, p, y, dau.isAlive(), false}); } } + + for (const auto& particle : mcParticlesAlice3) { + if (particle.hasNaN()) { + histos.fill(HIST("hNaNBookkeeping"), 1); + continue; + } + + histos.fill(HIST("hNaNBookkeeping"), 0); + std::span motherSpan(particle.mothersIds, 2); + tableMcParticlesWithDau(particle.collisionId, particle.pdgCode, particle.statusCode, + particle.flags, motherSpan, particle.daughtersIdSlice, particle.weight, + particle.px, particle.py, particle.pz, particle.e, + particle.vx, particle.vy, particle.vz, particle.vt, + particle.phi, particle.eta, particle.pt, particle.p, particle.y, + particle.isAlive, particle.isPrimary); + } } }; diff --git a/ALICE3/TableProducer/OTF/onTheFlyDetectorGeometryProvider.cxx b/ALICE3/TableProducer/OTF/onTheFlyDetectorGeometryProvider.cxx index 8d774280a88..c4caf97f17a 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyDetectorGeometryProvider.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyDetectorGeometryProvider.cxx @@ -16,18 +16,29 @@ /// \author Nicolò Jacazio , Universita del Piemonte Orientale (IT) /// -#include "ALICE3/Core/FastTracker.h" +#include "GeometryContainer.h" #include +#include +#include #include +#include +#include +#include +#include +#include #include -#include +#include +#include + +#include #include #include struct OnTheFlyDetectorGeometryProvider { - + o2::framework::HistogramRegistry histos{"Histos", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::Configurable cleanLutWhenLoaded{"cleanLutWhenLoaded", true, "clean LUTs after being loaded to save disk space"}; o2::framework::Configurable> detectorConfiguration{"detectorConfiguration", std::vector{"$O2PHYSICS_ROOT/share/alice3/a3geometry_v3.ini"}, "Paths of the detector geometry configuration files"}; @@ -37,33 +48,17 @@ struct OnTheFlyDetectorGeometryProvider { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setTimestamp(-1); o2::fastsim::GeometryContainer geometryContainer; // Checking that the geometry files can be accessed and loaded + geometryContainer.setCcdbManager(ccdb.operator->()); LOG(info) << "On-the-fly detector geometry provider running."; if (detectorConfiguration.value.empty()) { LOG(fatal) << "No detector configuration files provided."; return; } int idx = 0; - for (auto& configFile : detectorConfiguration.value) { + for (std::string& configFile : detectorConfiguration.value) { LOG(info) << "Loading detector geometry from configuration file: " << configFile; - // If the filename starts with ccdb: then take the file from the ccdb - if (configFile.rfind("ccdb:", 0) == 0) { - std::string ccdbPath = configFile.substr(5); // remove "ccdb:" prefix - const std::string outPath = "/tmp/DetGeo/"; - configFile = Form("%s/%s/snapshot.root", outPath.c_str(), ccdbPath.c_str()); - std::ifstream checkFile(configFile); // Check if file already exists - if (!checkFile.is_open()) { // File does not exist, retrieve from CCDB - LOG(info) << " --- CCDB source detected for detector geometry " << configFile; - std::map metadata; - ccdb->getCCDBAccessor().retrieveBlob(ccdbPath, outPath, metadata, 1); - LOG(info) << " --- Now retrieving geometry configuration from CCDB to: " << configFile; - } else { // File exists, proceed to load - LOG(info) << " --- Geometry configuration file already exists: " << configFile << ". Skipping download."; - checkFile.close(); - } - detectorConfiguration.value[idx] = configFile; // Update the filename to the local file - } + histos.add(Form("GeometryConfigFile_%d", idx++), configFile.c_str(), o2::framework::HistType::kTH1D, {{1, 0, 1}})->Fill(0.5); geometryContainer.addEntry(configFile); - idx++; } // First we check that the magnetic field is consistent @@ -75,10 +70,12 @@ struct OnTheFlyDetectorGeometryProvider { LOG(fatal) << "Inconsistent magnetic field values between configurations 0 and " << icfg << ": " << mMagneticField << " vs " << cfgBfield; } } + LOG(info) << "Initialization completed"; } - void process(o2::aod::McCollisions const&) + void process(o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) { + LOG(debug) << "On-the-fly detector geometry provider processing " << mcCollisions.size() << " collisions and " << mcParticles.size() << " particles."; } }; diff --git a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx index 4563e9dbe8b..42c9a022fe6 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx @@ -30,42 +30,41 @@ /// \since May 22, 2024 /// +#include "GeometryContainer.h" + #include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/Core/FastTracker.h" #include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFCollision.h" #include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFTracks.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" #include -#include -#include #include #include -#include -#include -#include -#include #include -#include #include +#include #include +#include #include +#include +#include #include -#include +#include #include -#include -#include +#include #include +#include #include #include -#include #include +#include +#include #include #include +#include #include #include #include @@ -129,7 +128,6 @@ struct OnTheFlyRichPid { Configurable bRichRefractiveIndexSector20{"bRichRefractiveIndexSector20", 1.03, "barrel RICH refractive index central(s)-20 and central(s)+20"}; // central(s)-20 and central(s)+20 Configurable bRICHPixelSize{"bRICHPixelSize", 0.1, "barrel RICH pixel size (cm)"}; Configurable bRichGapRefractiveIndex{"bRichGapRefractiveIndex", 1.000283, "barrel RICH gap refractive index"}; - Configurable cleanLutWhenLoaded{"cleanLutWhenLoaded", true, "clean LUTs after being loaded to save disk space"}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; @@ -289,61 +287,61 @@ struct OnTheFlyRichPid { float mMagneticField = 0.0f; void init(o2::framework::InitContext& initContext) { + mGeoContainer.setCcdbManager(ccdb.operator->()); mGeoContainer.init(initContext); const int nGeometries = mGeoContainer.getNumberOfConfigurations(); - mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); - pRandomNumberGenerator.SetSeed(0); // fully randomize + mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); - for (int icfg = 0; icfg < nGeometries; ++icfg) { - const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - mSmearer.emplace_back(std::make_unique()); - mSmearer[icfg]->setCleanupDownloadedFile(cleanLutWhenLoaded.value); - mSmearer[icfg]->setCcdbManager(ccdb.operator->()); - std::map globalConfiguration = mGeoContainer.getConfiguration(icfg, "global"); - for (const auto& entry : globalConfiguration) { - int pdg = 0; - if (entry.first.find("lut") != 0) { - continue; - } - if (entry.first.find("lutEl") != std::string::npos) { - pdg = kElectron; - } else if (entry.first.find("lutMu") != std::string::npos) { - pdg = kMuonMinus; - } else if (entry.first.find("lutPi") != std::string::npos) { - pdg = kPiPlus; - } else if (entry.first.find("lutKa") != std::string::npos) { - pdg = kKPlus; - } else if (entry.first.find("lutPr") != std::string::npos) { - pdg = kProton; - } else if (entry.first.find("lutDe") != std::string::npos) { - pdg = o2::constants::physics::kDeuteron; - } else if (entry.first.find("lutTr") != std::string::npos) { - pdg = o2::constants::physics::kTriton; - } else if (entry.first.find("lutHe3") != std::string::npos) { - pdg = o2::constants::physics::kHelium3; - } else if (entry.first.find("lutAl") != std::string::npos) { - pdg = o2::constants::physics::kAlpha; - } + if (flagRICHLoadDelphesLUTs) { + for (int icfg = 0; icfg < nGeometries; ++icfg) { + mSmearer.emplace_back(std::make_unique()); + mSmearer[icfg]->setCcdbManager(ccdb.operator->()); + std::map globalConfiguration = mGeoContainer.getConfiguration(icfg, "global"); + for (const auto& entry : globalConfiguration) { + int pdg = 0; + if (entry.first.find("lut") != 0) { + continue; + } + if (entry.first.find("lutEl") != std::string::npos) { + pdg = kElectron; + } else if (entry.first.find("lutMu") != std::string::npos) { + pdg = kMuonMinus; + } else if (entry.first.find("lutPi") != std::string::npos) { + pdg = kPiPlus; + } else if (entry.first.find("lutKa") != std::string::npos) { + pdg = kKPlus; + } else if (entry.first.find("lutPr") != std::string::npos) { + pdg = kProton; + } else if (entry.first.find("lutDe") != std::string::npos) { + pdg = o2::constants::physics::kDeuteron; + } else if (entry.first.find("lutTr") != std::string::npos) { + pdg = o2::constants::physics::kTriton; + } else if (entry.first.find("lutHe3") != std::string::npos) { + pdg = o2::constants::physics::kHelium3; + } else if (entry.first.find("lutAl") != std::string::npos) { + pdg = o2::constants::physics::kAlpha; + } - std::string filename = entry.second; - if (pdg == 0) { - LOG(fatal) << "Unknown LUT entry " << entry.first << " for global configuration"; - } - LOG(info) << "Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file '" << filename << "'"; - if (filename.empty()) { - LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; - } - // strip from leading/trailing spaces - filename.erase(0, filename.find_first_not_of(" ")); - filename.erase(filename.find_last_not_of(" ") + 1); - if (filename.empty()) { - LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; - } - bool success = mSmearer[icfg]->loadTable(pdg, filename.c_str()); - if (!success) { - LOG(fatal) << "Having issue with loading the LUT " << pdg << " " << filename; + std::string filename = entry.second; + if (pdg == 0) { + LOG(fatal) << "Unknown LUT entry " << entry.first << " for global configuration"; + } + LOG(info) << "Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file '" << filename << "'"; + if (filename.empty()) { + LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; + } + // strip from leading/trailing spaces + filename.erase(0, filename.find_first_not_of(" ")); + filename.erase(filename.find_last_not_of(" ") + 1); + if (filename.empty()) { + LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; + } + bool success = mSmearer[icfg]->loadTable(pdg, filename.c_str()); + if (!success) { + LOG(fatal) << "Having issue with loading the LUT " << pdg << " " << filename; + } } } } @@ -760,7 +758,6 @@ struct OnTheFlyRichPid { } for (const auto& track : tracks) { - auto fillDummyValues = [&](bool gasRich = false) { upgradeRich(kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue); upgradeRichSignal(false, false, false, false, false, false, false, false, false, false, gasRich); diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index e408b59d784..731bc940b5b 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -24,44 +24,50 @@ /// \since May 22, 2024 /// +#include "GeometryContainer.h" + #include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/Core/FastTracker.h" #include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFCollision.h" #include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/OTFTracks.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" #include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include +#include #include +#include #include +#include +#include #include -#include +#include #include -#include -#include +#include +#include +#include +#include #include +#include #include #include #include +#include +#include +#include +#include #include +#include #include #include #include +#include + using namespace o2; using namespace o2::framework; @@ -128,7 +134,6 @@ struct OnTheFlyTofPid { Configurable nBinsMult{"nBinsMult", 200, "number of bins in multiplicity"}; Configurable maxMultRange{"maxMultRange", 1000.f, "upper limit in multiplicity plots"}; } plotsConfig; - Configurable cleanLutWhenLoaded{"cleanLutWhenLoaded", true, "clean LUTs after being loaded to save disk space"}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; @@ -148,61 +153,62 @@ struct OnTheFlyTofPid { float mMagneticField = 0.0f; void init(o2::framework::InitContext& initContext) { + mGeoContainer.setCcdbManager(ccdb.operator->()); mGeoContainer.init(initContext); const int nGeometries = mGeoContainer.getNumberOfConfigurations(); mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); pRandomNumberGenerator.SetSeed(0); // fully randomize + if (simConfig.flagTOFLoadDelphesLUTs) { + for (int icfg = 0; icfg < nGeometries; ++icfg) { + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; + mSmearer.emplace_back(std::make_unique()); + mSmearer[icfg]->setCcdbManager(ccdb.operator->()); + std::map globalConfiguration = mGeoContainer.getConfiguration(icfg, "global"); + for (const auto& entry : globalConfiguration) { + int pdg = 0; + if (entry.first.find("lut") != 0) { + continue; + } + if (entry.first.find("lutEl") != std::string::npos) { + pdg = kElectron; + } else if (entry.first.find("lutMu") != std::string::npos) { + pdg = kMuonMinus; + } else if (entry.first.find("lutPi") != std::string::npos) { + pdg = kPiPlus; + } else if (entry.first.find("lutKa") != std::string::npos) { + pdg = kKPlus; + } else if (entry.first.find("lutPr") != std::string::npos) { + pdg = kProton; + } else if (entry.first.find("lutDe") != std::string::npos) { + pdg = o2::constants::physics::kDeuteron; + } else if (entry.first.find("lutTr") != std::string::npos) { + pdg = o2::constants::physics::kTriton; + } else if (entry.first.find("lutHe3") != std::string::npos) { + pdg = o2::constants::physics::kHelium3; + } else if (entry.first.find("lutAl") != std::string::npos) { + pdg = o2::constants::physics::kAlpha; + } - for (int icfg = 0; icfg < nGeometries; ++icfg) { - const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - mSmearer.emplace_back(std::make_unique()); - mSmearer[icfg]->setCleanupDownloadedFile(cleanLutWhenLoaded.value); - mSmearer[icfg]->setCcdbManager(ccdb.operator->()); - std::map globalConfiguration = mGeoContainer.getConfiguration(icfg, "global"); - for (const auto& entry : globalConfiguration) { - int pdg = 0; - if (entry.first.find("lut") != 0) { - continue; - } - if (entry.first.find("lutEl") != std::string::npos) { - pdg = kElectron; - } else if (entry.first.find("lutMu") != std::string::npos) { - pdg = kMuonMinus; - } else if (entry.first.find("lutPi") != std::string::npos) { - pdg = kPiPlus; - } else if (entry.first.find("lutKa") != std::string::npos) { - pdg = kKPlus; - } else if (entry.first.find("lutPr") != std::string::npos) { - pdg = kProton; - } else if (entry.first.find("lutDe") != std::string::npos) { - pdg = o2::constants::physics::kDeuteron; - } else if (entry.first.find("lutTr") != std::string::npos) { - pdg = o2::constants::physics::kTriton; - } else if (entry.first.find("lutHe3") != std::string::npos) { - pdg = o2::constants::physics::kHelium3; - } else if (entry.first.find("lutAl") != std::string::npos) { - pdg = o2::constants::physics::kAlpha; - } - - std::string filename = entry.second; - if (pdg == 0) { - LOG(fatal) << "Unknown LUT entry " << entry.first << " for global configuration"; - } - LOG(info) << "Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file '" << filename << "'"; - if (filename.empty()) { - LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; - } - // strip from leading/trailing spaces - filename.erase(0, filename.find_first_not_of(" ")); - filename.erase(filename.find_last_not_of(" ") + 1); - if (filename.empty()) { - LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; - } - bool success = mSmearer[icfg]->loadTable(pdg, filename.c_str()); - if (!success) { - LOG(fatal) << "Having issue with loading the LUT " << pdg << " " << filename; + std::string filename = entry.second; + if (pdg == 0) { + LOG(fatal) << "Unknown LUT entry " << entry.first << " for global configuration"; + } + LOG(info) << "Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file '" << filename << "'"; + if (filename.empty()) { + LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; + } + // strip from leading/trailing spaces + filename.erase(0, filename.find_first_not_of(" ")); + filename.erase(filename.find_last_not_of(" ") + 1); + if (filename.empty()) { + LOG(warning) << "No LUT file passed for pdg " << pdg << ", skipping."; + } + bool success = mSmearer[icfg]->loadTable(pdg, filename.c_str()); + if (!success) { + LOG(fatal) << "Having issue with loading the LUT " << pdg << " " << filename; + } } } } diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index 4e10b6a5779..0be208dbdb7 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -23,46 +23,87 @@ /// \author Roberto Preghenella preghenella@bo.infn.it /// +#include "GeometryContainer.h" + #include "ALICE3/Core/DelphesO2TrackSmearer.h" #include "ALICE3/Core/DetLayer.h" #include "ALICE3/Core/FastTracker.h" #include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFCollision.h" +#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFTracks.h" #include "ALICE3/DataModel/collisionAlice3.h" #include "ALICE3/DataModel/tracksAlice3.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" +#include #include #include +#include +#include +#include #include #include +#include #include #include #include +#include #include #include +#include #include +#include +#include #include +#include +#include #include -#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include #include +#include +#include #include #include +#include +#include #include +#include +#include #include #include +#include + +#include + +#include +#include #include +#include +#include +#include +#include #include +#include #include +#include #include #include +#include + using namespace o2; using namespace o2::framework; using std::array; @@ -83,6 +124,7 @@ struct OnTheFlyTracker { Produces tableStoredTracksCov; Produces tableTracksCovExtension; Produces tableMcTrackLabels; + Produces tableMcTrackWithDauLabels; Produces tableTracksDCA; Produces tableTracksDCACov; Produces tableCollisionsAlice3; @@ -105,6 +147,7 @@ struct OnTheFlyTracker { 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 primaryVertexOption{"primaryVertexOption", "pvertexer.maxChi2TZDebris=10;pvertexer.acceptableScale2=9;pvertexer.minScale2=2;pvertexer.timeMarginVertexTime=1.3;;pvertexer.maxChi2TZDebris=40;pvertexer.maxChi2Mean=12;pvertexer.maxMultRatDebris=1.;pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;", "Option for the primary vertexer"}; Configurable interpolateLutEfficiencyVsNch{"interpolateLutEfficiencyVsNch", true, "interpolate LUT efficiency as f(Nch)"}; Configurable populateTracksDCA{"populateTracksDCA", true, "populate TracksDCA table"}; @@ -115,11 +158,13 @@ struct OnTheFlyTracker { 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 cleanLutWhenLoaded{"cleanLutWhenLoaded", true, "clean LUTs after being loaded to save disk space"}; 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 axisDeltaVtxCoord{"axisDeltaVtxCoord", {100, -5., 5}, "Delta Vtx coord (cm)"}; + ConfigurableAxis axisDeltaMultPVRecoGen{"axisDeltaMultPVRecoGen", {51, -25, 25}, "Delta Multiplicity_{PV} (cm)"}; + ConfigurableAxis axisVtxMult{"axisVtxMult", {101, 0, 100}, "Vertex Multiplicity"}; 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)"}; @@ -141,14 +186,12 @@ struct OnTheFlyTracker { struct : ConfigurableGroup { std::string prefix = "fastTrackerSettings"; // JSON group name Configurable minSiliconHits{"minSiliconHits", 6, "minimum number of silicon hits to accept track"}; + Configurable minSiliconHitsForKinkReco{"minSiliconHitsForKinkReco", 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 applyZacceptance{"applyZacceptance", false, "apply z limits to detector layers or not"}; Configurable applyMSCorrection{"applyMSCorrection", true, "apply ms corrections for secondaries or not"}; Configurable applyElossCorrection{"applyElossCorrection", true, "apply eloss corrections for secondaries or not"}; - Configurable applyEffCorrection{"applyEffCorrection", true, "apply efficiency correction or not"}; - Configurable scaleVD{"scaleVD", 1, "scale x0 and xrho in VD layers"}; - Configurable> pixelRes{"pixelRes", {0.00025, 0.00025, 0.001, 0.001}, "RPhiIT, ZIT, RPhiOT, ZOT"}; } fastTrackerSettings; // allows for gap between peak and bg in case someone wants to struct : ConfigurableGroup { @@ -158,7 +201,6 @@ struct OnTheFlyTracker { Configurable applyZacceptance{"applyZacceptance", false, "apply z limits to detector layers or not"}; Configurable applyMSCorrection{"applyMSCorrection", true, "apply ms corrections for secondaries or not"}; Configurable applyElossCorrection{"applyElossCorrection", true, "apply eloss corrections for secondaries or not"}; - Configurable applyEffCorrection{"applyEffCorrection", true, "apply efficiency correction or not"}; } fastPrimaryTrackerSettings; struct : ConfigurableGroup { @@ -167,6 +209,8 @@ struct OnTheFlyTracker { Configurable findXi{"findXi", false, "if decayXi on, find Xi and fill Tracks table also with Xi"}; Configurable trackXi{"trackXi", false, "if findXi on, attempt to track Xi"}; Configurable doXiQA{"doXiQA", false, "QA plots for when treating Xi"}; + Configurable minStraTrackHits{"minStraTrackHits", 1, "if trackXi, set min strangeness tracking hits"}; + Configurable doKinkReco{"doKinkReco", 0, "Flag for kink reco setting: 0 - disabled, 1 - complementary, 2 - only"}; } cascadeDecaySettings; struct : ConfigurableGroup { @@ -176,6 +220,19 @@ struct OnTheFlyTracker { Configurable doV0QA{"doV0QA", false, "QA plots for when treating V0"}; } v0DecaySettings; + struct : ConfigurableGroup { + std::string prefix = "cfgFitter"; + Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + 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 maxDZIni{"maxDZIni", 1e9, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4, "reject (if>0) PCA candidate if tracks DXY exceeds threshold"}; + Configurable maxVtxChi2{"maxVtxChi2", 1e9, "reject (if>0) vtx. chi2 above this value"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + } cfgFitter; + using PVertex = o2::dataformats::PrimaryVertex; // for secondary vertex finding @@ -229,6 +286,8 @@ struct OnTheFlyTracker { int negativeId; // track index in the Tracks table int bachelorId; // track index in the Tracks table + float pt; + float eta; float dcaV0dau; float dcacascdau; float v0radius; @@ -246,8 +305,8 @@ struct OnTheFlyTracker { // Helper struct to pass V0 information struct v0candidate { - int positiveId; // track index in the Tracks table - int negativeId; // track index in the Tracks table + int positiveId; // track index in the Tracks table + int negativeId; // track index in the Tracks table int mcParticleId; // mc particle index float pt; @@ -266,6 +325,17 @@ struct OnTheFlyTracker { kLambda0, kLambda0Bar}; + static constexpr std::array longLivedHandledPDGs = {kElectron, + kMuonMinus, + kPiPlus, + kKPlus, + kProton}; + + static constexpr std::array nucleiPDGs = {o2::constants::physics::kDeuteron, + o2::constants::physics::kTriton, + o2::constants::physics::kHelium3, + o2::constants::physics::kAlpha}; + // necessary for particle charges Service pdgDB; @@ -299,6 +369,7 @@ struct OnTheFlyTracker { LOG(info) << "Initializing OnTheFlyTracker task"; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setTimestamp(-1); + mGeoContainer.setCcdbManager(ccdb.operator->()); mGeoContainer.init(initContext); const int nGeometries = mGeoContainer.getNumberOfConfigurations(); @@ -306,7 +377,6 @@ struct OnTheFlyTracker { for (int icfg = 0; icfg < nGeometries; ++icfg) { const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; mSmearer.emplace_back(std::make_unique()); - mSmearer[icfg]->setCleanupDownloadedFile(cleanLutWhenLoaded.value); mSmearer[icfg]->setCcdbManager(ccdb.operator->()); std::map globalConfiguration = mGeoContainer.getConfiguration(icfg, "global"); if (enablePrimarySmearing) { @@ -362,24 +432,37 @@ struct OnTheFlyTracker { // smear un-reco'ed tracks if asked to do so mSmearer[icfg]->skipUnreconstructed(!processUnreconstructedTracks.value); - insertHist(histPath + "hPtGenerated", "hPtGenerated", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPhiGenerated", "hPhiGenerated", {kTH1D, {{100, 0.0f, 2 * M_PI, "#phi (rad)"}}}); - - insertHist(histPath + "hPtGeneratedEl", "hPtGeneratedEl", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtGeneratedPi", "hPtGeneratedPi", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtGeneratedKa", "hPtGeneratedKa", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtGeneratedPr", "hPtGeneratedPr", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtReconstructed", "hPtReconstructed", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtReconstructedEl", "hPtReconstructedEl", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtReconstructedPi", "hPtReconstructedPi", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtReconstructedKa", "hPtReconstructedKa", {kTH1D, {{axes.axisMomentum}}}); - insertHist(histPath + "hPtReconstructedPr", "hPtReconstructedPr", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtGenerated", "hPtGenerated;#it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPhiGenerated", "hPhiGenerated;#phi (rad);Counts", {kTH1D, {{100, 0.0f, 2 * M_PI, "#phi (rad)"}}}); + + insertHist(histPath + "hPtGeneratedEl", "hPtGeneratedEl;Gen #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtGeneratedPi", "hPtGeneratedPi;Gen #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtGeneratedKa", "hPtGeneratedKa;Gen #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtGeneratedPr", "hPtGeneratedPr;Gen #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtReconstructed", "hPtReconstructed;Reco #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtReconstructedEl", "hPtReconstructedEl;Reco #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtReconstructedPi", "hPtReconstructedPi;Reco #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtReconstructedKa", "hPtReconstructedKa;Reco #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); + insertHist(histPath + "hPtReconstructedPr", "hPtReconstructedPr;Reco #it{p}_{T} (GeV/c);Counts", {kTH1D, {{axes.axisMomentum}}}); } // Collision QA - insertHist(histPath + "hPVz", "hPVz", {kTH1D, {{axes.axisVertexZ}}}); - insertHist(histPath + "hLUTMultiplicity", "hLUTMultiplicity", {kTH1D, {{axes.axisMultiplicity}}}); - insertHist(histPath + "hSimMultiplicity", "hSimMultiplicity", {kTH1D, {{axes.axisMultiplicity}}}); - insertHist(histPath + "hRecoMultiplicity", "hRecoMultiplicity", {kTH1D, {{axes.axisMultiplicity}}}); + insertHist(histPath + "hPVz", "hPVz;Primary Vertex Z (cm);Counts", {kTH1D, {{axes.axisVertexZ}}}); + insertHist(histPath + "hLUTMultiplicity", "hLUTMultiplicity;dN/d#eta;Counts", {kTH1D, {{axes.axisMultiplicity}}}); + insertHist(histPath + "hSimMultiplicity", "hSimMultiplicity;Gen. multiplicity;Counts", {kTH1D, {{axes.axisMultiplicity}}}); + insertHist(histPath + "hRecoMultiplicity", "hRecoMultiplicity;Reco Multiplicity;Counts", {kTH1D, {{axes.axisMultiplicity}}}); + + if (enablePrimaryVertexing) { + insertHist(histPath + "hDeltaXPVRecoGen", "hDeltaXPVRecoGen;Delta X (reco - gen), cm", {kTH1D, {{axes.axisDeltaVtxCoord}}}); + insertHist(histPath + "hDeltaYPVRecoGen", "hDeltaYPVRecoGen;Delta Y (reco - gen), cm", {kTH1D, {{axes.axisDeltaVtxCoord}}}); + insertHist(histPath + "hDeltaZPVRecoGen", "hDeltaZPVRecoGen;Delta Z (reco - gen), cm", {kTH1D, {{axes.axisDeltaVtxCoord}}}); + insertHist(histPath + "hDeltaMultPVRecoGen", "hDeltaMultPVRecoGen;Delta Multiplicity (reco - gen)", {kTH1D, {{axes.axisDeltaMultPVRecoGen}}}); + insertHist(histPath + "hVtxMultGen", "hVtxMultGen;Generated Vertex Multiplicity", {kTH1D, {{axes.axisVtxMult}}}); + insertHist(histPath + "hVtxMultReco", "hVtxMultReco;Reconstructed Vertex Multiplicity", {kTH1D, {{axes.axisVtxMult}}}); + insertHist(histPath + "hVtxTrials", "hVtxTrials;Vertex Reconstruction Trials", {kTH1D, {{2, -0.5, 1.5}}}); + // Set the bin labels + getHist(TH1, histPath + "hVtxTrials")->GetXaxis()->SetBinLabel(1, "Tried"); + getHist(TH1, histPath + "hVtxTrials")->GetXaxis()->SetBinLabel(2, "Succeeded"); + } if (enableSecondarySmearing) { fastTracker.emplace_back(std::make_unique()); @@ -388,16 +471,60 @@ struct OnTheFlyTracker { fastTracker[icfg]->SetApplyMSCorrection(fastTrackerSettings.applyMSCorrection); fastTracker[icfg]->SetApplyElossCorrection(fastTrackerSettings.applyElossCorrection); fastTracker[icfg]->AddGenericDetector(mGeoContainer.getEntry(icfg), ccdb.operator->()); - // print fastTracker settings - fastTracker[icfg]->Print(); - if (cascadeDecaySettings.doXiQA) - insertHist(histPath + "hMassXi", "hMassXi", {kTH1D, {{axes.axisXiMass}}}); + fastTracker[icfg]->Print(); // print fastTracker settings + + if (cascadeDecaySettings.doXiQA) { + insertHist(histPath + "hXiBuilding", "hXiBuilding", {kTH1F, {{10, -0.5f, 9.5f}}}); + + insertHist(histPath + "hGenXi", "hGenXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoXi", "hRecoXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + + insertHist(histPath + "hGenPiFromXi", "hGenPiFromXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hGenPiFromLa", "hGenPiFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hGenPrFromLa", "hGenPrFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoPiFromXi", "hRecoPiFromXi", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoPiFromLa", "hRecoPiFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + insertHist(histPath + "hRecoPrFromLa", "hRecoPrFromLa", {kTH2F, {axes.axisDecayRadius, axes.axisMomentum}}); + + // basic mass histograms to see if we're in business + insertHist(histPath + "hMassLambda", "hMassLambda", {kTH1F, {{axes.axisLambdaMass}}}); + insertHist(histPath + "hMassXi", "hMassXi", {kTH1F, {{axes.axisXiMass}}}); + insertHist(histPath + "h2dMassXi", "h2dMassXi", {kTH2F, {{axes.axisXiMass}, {axes.axisMomentum}}}); + + // OTF strangeness tracking QA + insertHist(histPath + "hFoundVsFindable", "hFoundVsFindable", {kTH2F, {{10, -0.5f, 9.5f}, {10, -0.5f, 9.5f}}}); + + insertHist(histPath + "h2dDCAxyCascade", "h2dDCAxyCascade", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascadeBachelor", "h2dDCAxyCascadeBachelor", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascadeNegative", "h2dDCAxyCascadeNegative", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAxyCascadePositive", "h2dDCAxyCascadePositive", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + + insertHist(histPath + "h2dDCAzCascade", "h2dDCAzCascade", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascadeBachelor", "h2dDCAzCascadeBachelor", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascadeNegative", "h2dDCAzCascadeNegative", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + insertHist(histPath + "h2dDCAzCascadePositive", "h2dDCAzCascadePositive", {kTH2F, {axes.axisMomentum, axes.axisDCA}}); + + insertHist(histPath + "h2dDeltaPtVsPt", "h2dDeltaPtVsPt;Gen p_{T};#Delta p_{T}", {kTH2F, {axes.axisMomentum, axes.axisDeltaPt}}); + insertHist(histPath + "h2dDeltaEtaVsPt", "h2dDeltaEtaVsPt;Gen p_{T};#Delta #eta", {kTH2F, {axes.axisMomentum, axes.axisDeltaEta}}); + + insertHist(histPath + "hFastTrackerHits", "hFastTrackerHits", {kTH2F, {axes.axisZ, axes.axisRadius}}); + insertHist(histPath + "hFastTrackerQA", "hFastTrackerQA", {kTH1F, {{8, -0.5f, 7.5f}}}); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(1, "Negative eigenvalue"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(2, "Failed sanity check"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(3, "intercept original radius"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(4, "propagate to original radius"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(5, "problematic layer"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(6, "multiple scattering"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(7, "energy loss"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(8, "efficiency"); + getHist(TH1, histPath + "hFastTrackerQA")->GetXaxis()->SetBinLabel(9, "no layers hit"); + } } if (doExtraQA) { - insertHist(histPath + "h2dPtRes", "h2dPtRes", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}}); - insertHist(histPath + "h2dDCAxy", "h2dDCAxy", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); - insertHist(histPath + "h2dDCAz", "h2dDCAz", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); + insertHist(histPath + "h2dPtRes", "h2dPtRes;Gen p_{T};#Delta p_{T} / Reco p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}}); + insertHist(histPath + "h2dDCAxy", "h2dDCAxy;p_{T};DCA_{xy}", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); + insertHist(histPath + "h2dDCAz", "h2dDCAz;p_{T};DCA_{z}", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}}); } } // end config loop @@ -417,75 +544,53 @@ struct OnTheFlyTracker { hCovMatOK->GetXaxis()->SetBinLabel(1, "Not OK"); hCovMatOK->GetXaxis()->SetBinLabel(2, "OK"); + auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitterStatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitterStatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitterStatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitterStatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitterStatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitterStatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitterStatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitterStatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitterStatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitterStatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitterStatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + if (doExtraQA) { - histos.add("h2dVerticesVsContributors", "h2dVerticesVsContributors", kTH2F, {axes.axisMultiplicity, axes.axisNVertices}); - histos.add("hRecoVsSimMultiplicity", "hRecoVsSimMultiplicity", kTH2F, {axes.axisMultiplicity, axes.axisMultiplicity}); + histos.add("h2dVerticesVsContributors", "h2dVerticesVsContributors;Multiplicity;N vertices", kTH2F, {axes.axisMultiplicity, axes.axisNVertices}); + histos.add("h1dVerticesNotReco", "h1dVerticesNotReco;Multiplicity;Vertices Not Reco", kTH1F, {axes.axisMultiplicity}); + histos.add("hRecoVsSimMultiplicity", "hRecoVsSimMultiplicity;Reco Mult.;Sim Mult.", kTH2F, {axes.axisMultiplicity, axes.axisMultiplicity}); histos.add("hSimTrackX", "hSimTrackX", kTH1F, {axes.axisX}); histos.add("hRecoTrackX", "hRecoTrackX", kTH1F, {axes.axisX}); histos.add("hTrackXatDCA", "hTrackXatDCA", kTH1F, {axes.axisX}); } - if (cascadeDecaySettings.doXiQA) { - histos.add("hXiBuilding", "hXiBuilding", kTH1F, {{10, -0.5f, 9.5f}}); - - 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("hGenPiFromLa", "hGenPiFromLa", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); - histos.add("hGenPrFromLa", "hGenPrFromLa", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); - histos.add("hRecoPiFromXi", "hRecoPiFromXi", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); - histos.add("hRecoPiFromLa", "hRecoPiFromLa", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); - histos.add("hRecoPrFromLa", "hRecoPrFromLa", 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("h2dDCAzCascade", "h2dDCAzCascade", kTH2F, {axes.axisMomentum, axes.axisDCA}); - histos.add("h2dDCAzCascadeBachelor", "h2dDCAzCascadeBachelor", kTH2F, {axes.axisMomentum, axes.axisDCA}); - histos.add("h2dDCAzCascadeNegative", "h2dDCAzCascadeNegative", kTH2F, {axes.axisMomentum, axes.axisDCA}); - histos.add("h2dDCAzCascadePositive", "h2dDCAzCascadePositive", 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}); - auto hFastTrackerQA = histos.add("hFastTrackerQA", "hFastTrackerQA", kTH1D, {{8, -0.5f, 7.5f}}); - hFastTrackerQA->GetXaxis()->SetBinLabel(1, "Negative eigenvalue"); - hFastTrackerQA->GetXaxis()->SetBinLabel(2, "Failed sanity check"); - hFastTrackerQA->GetXaxis()->SetBinLabel(3, "intercept original radius"); - hFastTrackerQA->GetXaxis()->SetBinLabel(4, "propagate to original radius"); - hFastTrackerQA->GetXaxis()->SetBinLabel(5, "problematic layer"); - hFastTrackerQA->GetXaxis()->SetBinLabel(6, "multiple scattering"); - hFastTrackerQA->GetXaxis()->SetBinLabel(7, "energy loss"); - hFastTrackerQA->GetXaxis()->SetBinLabel(8, "efficiency"); - } if (v0DecaySettings.doV0QA) { - for (int icfg = 0; icfg < nGeometries; icfg++) { std::string v0histPath = "V0Building_Configuration_" + std::to_string(icfg) + "/"; insertHist(v0histPath + "hV0Building", "hV0Building", kTH1F, {{10, -0.5f, 9.5f}}); insertHist(v0histPath + "hFastTrackerHits", "hV0Building", kTH2F, {{axes.axisZ, axes.axisRadius}}); - auto hFastTrackerQA = histos.add(v0histPath + "hFastTrackerQA", "hFastTrackerQA", kTH1D, {{8, -0.5f, 7.5f}}); - hFastTrackerQA->GetXaxis()->SetBinLabel(1, "Negative eigenvalue"); - hFastTrackerQA->GetXaxis()->SetBinLabel(2, "Failed sanity check"); - hFastTrackerQA->GetXaxis()->SetBinLabel(3, "intercept original radius"); - hFastTrackerQA->GetXaxis()->SetBinLabel(4, "propagate to original radius"); - hFastTrackerQA->GetXaxis()->SetBinLabel(5, "problematic layer"); - hFastTrackerQA->GetXaxis()->SetBinLabel(6, "multiple scattering"); - hFastTrackerQA->GetXaxis()->SetBinLabel(7, "energy loss"); - hFastTrackerQA->GetXaxis()->SetBinLabel(8, "efficiency"); - histPointers.insert({v0histPath + "hFastTrackerQA", hFastTrackerQA}); + auto h = histos.add(v0histPath + "hFastTrackerQA", "hFastTrackerQA", kTH1D, {{8, -0.5f, 7.5f}}); + h->GetXaxis()->SetBinLabel(1, "Negative eigenvalue"); + h->GetXaxis()->SetBinLabel(2, "Failed sanity check"); + h->GetXaxis()->SetBinLabel(3, "intercept original radius"); + h->GetXaxis()->SetBinLabel(4, "propagate to original radius"); + h->GetXaxis()->SetBinLabel(5, "problematic layer"); + h->GetXaxis()->SetBinLabel(6, "multiple scattering"); + h->GetXaxis()->SetBinLabel(7, "energy loss"); + h->GetXaxis()->SetBinLabel(8, "efficiency"); + h->GetXaxis()->SetBinLabel(8, "no layers hit"); + histPointers.insert({v0histPath + "hFastTrackerQA", h}); // K0s insertHist(v0histPath + "K0/hGen", "hGen", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); insertHist(v0histPath + "K0/hReco", "hReco", kTH2F, {axes.axisDecayRadius, axes.axisMomentum}); @@ -544,19 +649,25 @@ struct OnTheFlyTracker { irSampler.init(); vertexer.setValidateWithIR(kFALSE); + vertexer.setTrackSources(o2::dataformats::GlobalTrackID::ITS); vertexer.setBunchFilling(irSampler.getBunchFilling()); + vertexer.setBz(mMagneticField); + o2::conf::ConfigurableParam::updateFromString("pvertexer.doBCValidation=false;" + primaryVertexOption.value); vertexer.init(); + o2::vertexing::PVertexerParams::Instance().printKeyValues(); + // 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.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter.setMaxR(cfgFitter.maxR); + fitter.setMinParamChange(cfgFitter.minParamChange); + fitter.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter.setMaxDZIni(cfgFitter.maxDZIni); + fitter.setMaxDXYIni(cfgFitter.maxDXYIni); + fitter.setMaxChi2(cfgFitter.maxVtxChi2); + fitter.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter.setWeightedFinalPCA(cfgFitter.useWeightedFinalPCA); + fitter.setBz(mMagneticField); fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); // such a light detector here // Set seed for TGenPhaseSpace @@ -564,6 +675,31 @@ struct OnTheFlyTracker { gRandom->SetSeed(seed); } + /// Function to get the internal PID for a given pdgCode + /// \param pdgCode pdg code for a common particle (particle handled by the tracker) + int pdgCodeToPID(int pdgCode) const + { + if (std::abs(pdgCode) == PDG_t::kElectron) { + return o2::track::PID::Electron; + } else if (std::abs(pdgCode) == PDG_t::kMuonMinus) { + return o2::track::PID::Muon; + } else if (std::abs(pdgCode) == PDG_t::kPiPlus) { + return o2::track::PID::Pion; + } else if (std::abs(pdgCode) == PDG_t::kKPlus) { + return o2::track::PID::Kaon; + } else if (std::abs(pdgCode) == PDG_t::kProton) { + return o2::track::PID::Proton; + } else if (std::abs(pdgCode) == PDG_t::kLambda0) { + return o2::track::PID::Lambda; + } else if (std::abs(pdgCode) == PDG_t::kXiMinus) { + return o2::track::PID::XiMinus; + } else if (std::abs(pdgCode) == PDG_t::kOmegaMinus) { + return o2::track::PID::OmegaMinus; + } else { + return o2::track::PID::Pion; // Default trackParCov assumption + } + } + /// Function to decay the xi /// \param particle the particle to decay /// \param track track of particle to decay @@ -630,21 +766,28 @@ struct OnTheFlyTracker { double posDauMass = -1.; double ctau = -1.; - if (std::abs(pdgCode) == kK0Short) { - v0Mass = o2::constants::physics::MassK0Short; - negDauMass = o2::constants::physics::MassPionCharged; - posDauMass = o2::constants::physics::MassPionCharged; - ctau = 2.68; - } else if (std::abs(pdgCode) == kLambda0) { - v0Mass = o2::constants::physics::MassLambda; - negDauMass = o2::constants::physics::MassPionCharged; - posDauMass = o2::constants::physics::MassProton; - ctau = 7.845; - } else if (std::abs(pdgCode) == kLambda0Bar) { - v0Mass = o2::constants::physics::MassLambda; - negDauMass = o2::constants::physics::MassProton; - posDauMass = o2::constants::physics::MassPionCharged; - ctau = 7.845; + switch (pdgCode) { + case kK0Short: + case -kK0Short: + v0Mass = o2::constants::physics::MassK0Short; + negDauMass = o2::constants::physics::MassPionCharged; + posDauMass = o2::constants::physics::MassPionCharged; + ctau = 2.68; + break; + case kLambda0: + v0Mass = o2::constants::physics::MassLambda; + negDauMass = o2::constants::physics::MassPionCharged; + posDauMass = o2::constants::physics::MassProton; + ctau = 7.845; + break; + case kLambda0Bar: + v0Mass = o2::constants::physics::MassLambda; + negDauMass = o2::constants::physics::MassProton; + posDauMass = o2::constants::physics::MassPionCharged; + ctau = 7.845; + break; + default: + LOG(fatal) << "Trying to decay unsupported V0 with PDG " << pdgCode; } const double v0BetaGamma = particle.p() / v0Mass; @@ -663,10 +806,12 @@ struct OnTheFlyTracker { decayDaughters.push_back(*v0Decay.GetDecay(1)); } - float dNdEta = 0.f; // Charged particle multiplicity to use in the efficiency evaluation - void processWithLUTs(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, int const& icfg) + float dNdEta = 0.f; // Charged particle multiplicity to use in the efficiency evaluation + std::pair vertexReconstructionEfficiencyCounters = {0, 0}; // {nVerticesWithMoreThan2Contributors, nVerticesReconstructed} + void processWithLUTs(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg) { - int lastTrackIndex = tableStoredTracksCov.lastIndex() + 1; // bookkeep the last added track + vertexReconstructionEfficiencyCounters.first += 1; + const int lastTrackIndex = tableStoredTracksCov.lastIndex() + 1; // bookkeep the last added track const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; tracksAlice3.clear(); @@ -682,19 +827,9 @@ struct OnTheFlyTracker { auto ir = irSampler.generateCollisionTime(); const float eventCollisionTimeNS = ir.timeInBCNS; - constexpr std::array longLivedHandledPDGs = {kElectron, - kMuonMinus, - kPiPlus, - kKPlus, - kProton}; - - constexpr std::array nucleiPDGs = {o2::constants::physics::kDeuteron, - o2::constants::physics::kTriton, - o2::constants::physics::kHelium3, - o2::constants::physics::kAlpha}; - // First we compute the number of charged particles in the event dNdEta = 0.f; + LOG(debug) << "Processing " << mcParticles.size() << " MC particles to compute dNch/deta"; for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.eta()) > multEtaRange) { continue; @@ -722,6 +857,7 @@ struct OnTheFlyTracker { } dNdEta += 1.f; } + LOG(debug) << "Computed dNch/deta before normalization: " << dNdEta; dNdEta /= (multEtaRange * 2.0f); uint32_t multiplicityCounter = 0; @@ -731,7 +867,7 @@ struct OnTheFlyTracker { double xiDecayRadius2D = 0; double laDecayRadius2D = 0; double v0DecayRadius2D = 0; - std::vector decayProducts; + std::vector cascadeDecayProducts; std::vector v0DecayProducts; std::vector xiDecayVertex, laDecayVertex, v0DecayVertex; for (const auto& mcParticle : mcParticles) { @@ -742,19 +878,26 @@ struct OnTheFlyTracker { laDecayVertex.clear(); v0DecayVertex.clear(); - if (cascadeDecaySettings.decayXi) { - if (mcParticle.pdgCode() == kXiMinus) { - o2::track::TrackParCov xiTrackParCov; - o2::upgrade::convertMCParticleToO2Track(mcParticle, xiTrackParCov, pdgDB); - decayCascade(mcParticle, xiTrackParCov, decayProducts, xiDecayVertex, laDecayVertex); - xiDecayRadius2D = std::hypot(xiDecayVertex[0], xiDecayVertex[1]); - laDecayRadius2D = std::hypot(laDecayVertex[0], laDecayVertex[1]); + cascadeDecayProducts.clear(); + v0DecayProducts.clear(); + const bool isCascade = mcParticle.pdgCode() == kXiMinus; + if (cascadeDecaySettings.decayXi && isCascade) { + o2::track::TrackParCov xiTrackParCov; + o2::upgrade::convertMCParticleToO2Track(mcParticle, xiTrackParCov, pdgDB); + decayCascade(mcParticle, xiTrackParCov, cascadeDecayProducts, xiDecayVertex, laDecayVertex); + if (cascadeDecayProducts.size() != 3) { + LOG(fatal) << "Xi decay did not produce 3 daughters as expected!"; } + xiDecayRadius2D = std::hypot(xiDecayVertex[0], xiDecayVertex[1]); + laDecayRadius2D = std::hypot(laDecayVertex[0], laDecayVertex[1]); } - const bool isV0 = std::find(v0PDGs.begin(), v0PDGs.end(), std::abs(mcParticle.pdgCode())) != v0PDGs.end(); + const bool isV0 = std::find(v0PDGs.begin(), v0PDGs.end(), mcParticle.pdgCode()) != v0PDGs.end(); if (v0DecaySettings.decayV0 && isV0) { - decayV0Particle(mcParticle, v0DecayProducts, v0DecayVertex, std::abs(mcParticle.pdgCode())); + decayV0Particle(mcParticle, v0DecayProducts, v0DecayVertex, mcParticle.pdgCode()); + if (v0DecayProducts.size() != 2) { + LOG(fatal) << "V0 decay did not produce 2 daughters as expected!"; + } v0DecayRadius2D = std::hypot(v0DecayVertex[0], v0DecayVertex[1]); } @@ -764,7 +907,7 @@ struct OnTheFlyTracker { const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), std::abs(mcParticle.pdgCode())) != longLivedHandledPDGs.end(); const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), std::abs(mcParticle.pdgCode())) != nucleiPDGs.end(); - const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled) || (cascadeDecaySettings.decayXi && mcParticle.pdgCode() == kXiMinus) || (v0DecaySettings.decayV0 && isV0); + const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled) || (cascadeDecaySettings.decayXi && isCascade) || (v0DecaySettings.decayV0 && isV0); if (!pdgsToBeHandled) { continue; } @@ -790,11 +933,11 @@ struct OnTheFlyTracker { break; } } - if (cascadeDecaySettings.doXiQA && mcParticle.pdgCode() == kXiMinus) { - histos.fill(HIST("hGenXi"), xiDecayRadius2D, mcParticle.pt()); - histos.fill(HIST("hGenPiFromXi"), xiDecayRadius2D, decayProducts[0].Pt()); - histos.fill(HIST("hGenPiFromLa"), laDecayRadius2D, decayProducts[1].Pt()); - histos.fill(HIST("hGenPrFromLa"), laDecayRadius2D, decayProducts[2].Pt()); + if (cascadeDecaySettings.doXiQA && isCascade) { + getHist(TH2, histPath + "hGenXi")->Fill(xiDecayRadius2D, mcParticle.pt()); + getHist(TH2, histPath + "hGenPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt()); + getHist(TH2, histPath + "hGenPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt()); + getHist(TH2, histPath + "hGenPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt()); } if (v0DecaySettings.doV0QA && isV0) { for (size_t indexV0 = 0; indexV0 < v0PDGs.size(); indexV0++) { @@ -824,42 +967,48 @@ struct OnTheFlyTracker { const float timeResolutionUs = timeResolutionNs * nsToMus; // us const float time = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; static constexpr int kCascProngs = 3; - std::vector xiDaughterTrackParCovsPerfect(3); - std::vector xiDaughterTrackParCovsTracked(3); - std::vector isReco(kCascProngs); - std::vector nHits(kCascProngs); // total - std::vector nSiliconHits(kCascProngs); // silicon type - std::vector nTPCHits(kCascProngs); // TPC type - if (cascadeDecaySettings.decayXi && mcParticle.pdgCode() == kXiMinus) { + std::array xiDaughterTrackParCovsPerfect; + std::array xiDaughterTrackParCovsTracked; + std::array isReco; + std::array nHitsCascadeProngs; // total + std::array nSiliconHitsCascadeProngs; // silicon type + std::array nTPCHitsCascadeProngs; // TPC type + + bool tryKinkReco = false; + if (cascadeDecaySettings.decayXi && isCascade) { + bool reconstructedCascade = false; if (cascadeDecaySettings.doXiQA) { - histos.fill(HIST("hXiBuilding"), 0.0f); + getHist(TH1, histPath + "hXiBuilding")->Fill(0.0f); } - o2::upgrade::convertTLorentzVectorToO2Track(kPiMinus, decayProducts[0], xiDecayVertex, xiDaughterTrackParCovsPerfect[0], pdgDB); - o2::upgrade::convertTLorentzVectorToO2Track(kPiMinus, decayProducts[1], laDecayVertex, xiDaughterTrackParCovsPerfect[1], pdgDB); - o2::upgrade::convertTLorentzVectorToO2Track(kProton, decayProducts[2], laDecayVertex, xiDaughterTrackParCovsPerfect[2], pdgDB); + o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kPiMinus, cascadeDecayProducts[0], xiDecayVertex, xiDaughterTrackParCovsPerfect[0], pdgDB); + xiDaughterTrackParCovsPerfect[0].setPID(pdgCodeToPID(PDG_t::kPiMinus)); + o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kPiMinus, cascadeDecayProducts[1], laDecayVertex, xiDaughterTrackParCovsPerfect[1], pdgDB); + xiDaughterTrackParCovsPerfect[1].setPID(pdgCodeToPID(PDG_t::kPiMinus)); + o2::upgrade::convertTLorentzVectorToO2Track(PDG_t::kProton, cascadeDecayProducts[2], laDecayVertex, xiDaughterTrackParCovsPerfect[2], pdgDB); + xiDaughterTrackParCovsPerfect[2].setPID(pdgCodeToPID(PDG_t::kProton)); for (int i = 0; i < kCascProngs; i++) { isReco[i] = false; - nHits[i] = 0; - nSiliconHits[i] = 0; - nTPCHits[i] = 0; + nHitsCascadeProngs[i] = 0; + nSiliconHitsCascadeProngs[i] = 0; + nTPCHitsCascadeProngs[i] = 0; if (enableSecondarySmearing) { - nHits[i] = fastTracker[icfg]->FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i], dNdEta); - nSiliconHits[i] = fastTracker[icfg]->GetNSiliconPoints(); - nTPCHits[i] = fastTracker[icfg]->GetNGasPoints(); + nHitsCascadeProngs[i] = fastTracker[icfg]->FastTrack(xiDaughterTrackParCovsPerfect[i], xiDaughterTrackParCovsTracked[i], dNdEta); + nSiliconHitsCascadeProngs[i] = fastTracker[icfg]->GetNSiliconPoints(); + nTPCHitsCascadeProngs[i] = fastTracker[icfg]->GetNGasPoints(); - if (nHits[i] < 0) { // QA - histos.fill(HIST("hFastTrackerQA"), o2::math_utils::abs(nHits[i])); + if (nHitsCascadeProngs[i] < 0 && cascadeDecaySettings.doXiQA) { // QA + getHist(TH1, histPath + "hFastTrackerQA")->Fill(o2::math_utils::abs(nHitsCascadeProngs[i])); } - if (nSiliconHits[i] >= fastTrackerSettings.minSiliconHits || (nSiliconHits[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nTPCHits[i] >= fastTrackerSettings.minTPCClusters)) { + if (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHits || (nSiliconHitsCascadeProngs[i] >= fastTrackerSettings.minSiliconHitsIfTPCUsed && nTPCHitsCascadeProngs[i] >= fastTrackerSettings.minTPCClusters)) { isReco[i] = true; } else { continue; // extra sure } - for (uint32_t ih = 0; ih < fastTracker[icfg]->GetNHits(); ih++) { - histos.fill(HIST("hFastTrackerHits"), fastTracker[icfg]->GetHitZ(ih), std::hypot(fastTracker[icfg]->GetHitX(ih), fastTracker[icfg]->GetHitY(ih))); + for (uint32_t ih = 0; ih < fastTracker[icfg]->GetNHits() && cascadeDecaySettings.doXiQA; ih++) { + getHist(TH2, histPath + "hFastTrackerHits")->Fill(fastTracker[icfg]->GetHitZ(ih), std::hypot(fastTracker[icfg]->GetHitX(ih), fastTracker[icfg]->GetHitY(ih))); } } else { isReco[i] = true; @@ -872,31 +1021,27 @@ struct OnTheFlyTracker { histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); } if (isReco[i]) { - tracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHits[i], nTPCHits[i]}); + tracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i]}); } else { ghostTracksAlice3.push_back(TrackAlice3{xiDaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2}); } } - if (cascadeDecaySettings.doXiQA && mcParticle.pdgCode() == kXiMinus) { - 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("hRecoPiFromLa"), laDecayRadius2D, decayProducts[1].Pt()); - if (isReco[2]) - histos.fill(HIST("hRecoPrFromLa"), laDecayRadius2D, decayProducts[2].Pt()); + if (!isReco[1] || !isReco[2]) { + tryKinkReco = true; // Lambda outside acceptance, set flag for kink reco to be used if mode 1 + } + + if (isReco[0] && isReco[1] && isReco[2]) { + reconstructedCascade = true; } // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ // combine particles into actual Xi candidate // cascade building starts here - if (cascadeDecaySettings.findXi && mcParticle.pdgCode() == kXiMinus && isReco[0] && isReco[1] && isReco[2]) { - if (cascadeDecaySettings.doXiQA) - histos.fill(HIST("hXiBuilding"), 3.0f); + if (cascadeDecaySettings.findXi && isReco[0] && isReco[1] && isReco[2] && cascadeDecaySettings.doKinkReco != 2) { + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(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 @@ -918,10 +1063,18 @@ struct OnTheFlyTracker { if (nCand == 0) { dcaFitterOK_V0 = false; } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterOK_V0 = false; + } + // V0 found successfully if (dcaFitterOK_V0) { - if (cascadeDecaySettings.doXiQA) - histos.fill(HIST("hXiBuilding"), 4.0f); + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(4.0f); + } + std::array pos; std::array posCascade; std::array posP; @@ -955,12 +1108,13 @@ struct OnTheFlyTracker { 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); + v0Track.setPID(pdgCodeToPID(PDG_t::kLambda0)); // dca fitter step nCand = 0; @@ -975,12 +1129,20 @@ struct OnTheFlyTracker { dcaFitterOK_Cascade = false; } + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterOK_Cascade = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); // Cascade found successfully if (dcaFitterOK_Cascade) { - if (cascadeDecaySettings.doXiQA) - histos.fill(HIST("hXiBuilding"), 5.0f); - o2::track::TrackParCov bachelorTrackAtPCA = fitter.getTrack(1); + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(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]; @@ -998,10 +1160,12 @@ struct OnTheFlyTracker { // 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 + cascadeTrack.setAbsCharge(-1); // may require more adjustments + cascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas thisCascade.cascradiusMC = xiDecayRadius2D; + thisCascade.pt = cascadeTrack.getPt(); + thisCascade.eta = cascadeTrack.getEta(); thisCascade.findableClusters = 0; thisCascade.foundClusters = 0; @@ -1024,8 +1188,9 @@ struct OnTheFlyTracker { // find perfect intercept XYZ float targetX = 1e+3; trackParCov.getXatLabR(layer.getRadius(), targetX, mMagneticField); - if (targetX > 999) + if (targetX > 999) { continue; // failed to find intercept + } if (!trackParCov.propagateTo(targetX, mMagneticField)) { continue; // failed to propagate @@ -1044,8 +1209,9 @@ struct OnTheFlyTracker { posClusterCandidate[2] = gRandom->Gaus(posClusterCandidate[2], layer.getResolutionZ()); } - if (std::isnan(phi)) + if (std::isnan(phi)) { continue; // Catch when getXatLabR misses layer[i] + } // towards adding cluster: move to track alpha double alpha = cascadeTrack.getAlpha(); @@ -1054,8 +1220,10 @@ struct OnTheFlyTracker { -TMath::Sin(alpha) * posClusterCandidate[0] + TMath::Cos(alpha) * posClusterCandidate[1], posClusterCandidate[2]}; - if (!(cascadeTrack.propagateTo(xyz1[0], mMagneticField))) + if (!(cascadeTrack.propagateTo(xyz1[0], mMagneticField))) { continue; + } + const o2::track::TrackParametrization::dim2_t hitpoint = {static_cast(xyz1[1]), static_cast(xyz1[2])}; const o2::track::TrackParametrization::dim3_t hitpointcov = {layer.getResolutionRPhi() * layer.getResolutionRPhi(), 0.f, layer.getResolutionZ() * layer.getResolutionZ()}; if (layer.isInDeadPhiRegion(phi)) { @@ -1065,31 +1233,131 @@ struct OnTheFlyTracker { cascadeTrack.update(hitpoint, hitpointcov); thisCascade.foundClusters++; // add to findable } + + if (thisCascade.foundClusters < cascadeDecaySettings.minStraTrackHits) { + continue; // We didn't find enough hits for strangeness tracking + } } // add cascade track thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this is the next index to be filled -> should be it tracksAlice3.push_back(TrackAlice3{cascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters}); - if (cascadeDecaySettings.doXiQA) { - histos.fill(HIST("hXiBuilding"), 6.0f); - 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); - getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi); - } - // add this cascade to vector (will fill cursor later with collision ID) cascadesAlice3.push_back(thisCascade); } } } // end cascade building + + if (isReco[0] && ((cascadeDecaySettings.doKinkReco == 1 && tryKinkReco) || cascadeDecaySettings.doKinkReco == 2)) { // mode 1 or 2 + o2::track::TrackParCov prefectCascadeTrack, trackedCascade; + const o2::track::TrackParCov& trackedBach = xiDaughterTrackParCovsTracked[0]; + o2::upgrade::convertMCParticleToO2Track(mcParticle, prefectCascadeTrack, pdgDB); + + // back track is already smeared + prefectCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas + const int nCascHits = fastTracker[icfg]->FastTrack(prefectCascadeTrack, trackedCascade, dNdEta, xiDecayRadius2D); + reconstructedCascade = (fastTrackerSettings.minSiliconHitsForKinkReco < nCascHits) ? true : false; + if (reconstructedCascade) { + std::array pCasc; + std::array pBach; + std::array pV0; + trackedCascade.getPxPyPzGlo(pCasc); + trackedBach.getPxPyPzGlo(pBach); + for (size_t i = 0; i < pCasc.size(); ++i) { + pV0[i] = pCasc[i] - pBach[i]; + } + + if (isReco[1] && !isReco[2]) { + thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 1; + thisCascade.positiveId = -1; + } else if (!isReco[1] && isReco[2]) { + thisCascade.negativeId = -1; + thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1; + } else if (isReco[1] && isReco[2]) { + thisCascade.positiveId = lastTrackIndex + tracksAlice3.size() - 1; + thisCascade.negativeId = lastTrackIndex + tracksAlice3.size() - 2; + } else { + thisCascade.positiveId = -1; + thisCascade.negativeId = -1; + } + + int nCand = 0; + bool kinkFitterOK = true; + try { + nCand = fitter.process(trackedCascade, trackedBach); + } catch (...) { + kinkFitterOK = false; + } + + if (nCand == 0) { + kinkFitterOK = false; + } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + kinkFitterOK = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); + if (kinkFitterOK) { + if (cascadeDecaySettings.doXiQA) { + getHist(TH1, histPath + "hXiBuilding")->Fill(6.0f); + } + + o2::track::TrackParCov newCascadeTrack = fitter.getTrack(0); // (cascade) + std::array kinkVtx = {-999, -999, -999}; + kinkVtx = fitter.getPCACandidatePos(); + thisCascade.bachelorId = lastTrackIndex + tracksAlice3.size() - isReco.size(); + thisCascade.cascadeTrackId = lastTrackIndex + tracksAlice3.size(); // this should be ok + thisCascade.dcaV0dau = -1.f; // unknown + thisCascade.v0radius = -1.f; // unknown + thisCascade.dcacascdau = std::sqrt(fitter.getChi2AtPCACandidate()); + thisCascade.cascradius = std::hypot(kinkVtx[0], kinkVtx[1]); + thisCascade.cascradiusMC = xiDecayRadius2D; + thisCascade.mLambda = o2::constants::physics::MassLambda; + thisCascade.findableClusters = nCascHits; + thisCascade.foundClusters = nCascHits; + thisCascade.pt = newCascadeTrack.getPt(); + thisCascade.eta = newCascadeTrack.getEta(); + thisCascade.mXi = RecoDecay::m(std::array{std::array{pBach[0], pBach[1], pBach[2]}, std::array{pV0[0], pV0[1], pV0[2]}}, + std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); + + newCascadeTrack.setPID(pdgCodeToPID(PDG_t::kXiMinus)); // FIXME: not OK for omegas + tracksAlice3.push_back(TrackAlice3{newCascadeTrack, mcParticle.globalIndex(), time, timeResolutionUs, false, false, 1, thisCascade.foundClusters}); + + // add this cascade to vector (will fill cursor later with collision ID) + cascadesAlice3.push_back(thisCascade); + } // end fitter OK + } // end cascade found + } // end cascade kink building + // +-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+-~-+ + if (cascadeDecaySettings.doXiQA) { + if (reconstructedCascade) { + getHist(TH2, histPath + "hRecoXi")->Fill(xiDecayRadius2D, mcParticle.pt()); + getHist(TH1, histPath + "hMassLambda")->Fill(thisCascade.mLambda); + getHist(TH1, histPath + "hMassXi")->Fill(thisCascade.mXi); + getHist(TH2, histPath + "h2dMassXi")->Fill(thisCascade.mXi, thisCascade.pt); + getHist(TH2, histPath + "h2dDeltaPtVsPt")->Fill(thisCascade.pt, (mcParticle.pt() - thisCascade.pt) / thisCascade.pt); + getHist(TH2, histPath + "h2dDeltaEtaVsPt")->Fill(thisCascade.pt, mcParticle.eta() - thisCascade.eta); + getHist(TH2, histPath + "hFoundVsFindable")->Fill(thisCascade.findableClusters, thisCascade.foundClusters); + } + if (isReco[0]) { + getHist(TH2, histPath + "hRecoPiFromXi")->Fill(xiDecayRadius2D, cascadeDecayProducts[0].Pt()); + } + if (isReco[1]) { + getHist(TH2, histPath + "hRecoPiFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[1].Pt()); + } + if (isReco[2]) { + getHist(TH2, histPath + "hRecoPrFromLa")->Fill(laDecayRadius2D, cascadeDecayProducts[2].Pt()); + } + } + continue; // Cascade handling done, should not be considered anymore } + // V0 handling std::vector v0DaughterTrackParCovsPerfect(2); std::vector v0DaughterTrackParCovsTracked(2); @@ -1150,7 +1418,7 @@ struct OnTheFlyTracker { // histos.fill(HIST("hNaNBookkeeping"), i + 1, 1.0f); // } if (isReco[i]) { - tracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHits[i], nTPCHits[i]}); + tracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2, nSiliconHitsCascadeProngs[i], nTPCHitsCascadeProngs[i]}); } else { ghostTracksAlice3.push_back(TrackAlice3{v0DaughterTrackParCovsTracked[i], mcParticle.globalIndex(), time, timeResolutionUs, true, true, i + 2}); } @@ -1207,6 +1475,14 @@ struct OnTheFlyTracker { if (nCand == 0) { dcaFitterOK_V0 = false; } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + dcaFitterOK_V0 = false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); // V0 found successfully if (dcaFitterOK_V0) { if (v0DecaySettings.doV0QA) { @@ -1246,8 +1522,8 @@ struct OnTheFlyTracker { if (mcParticle.pdgCode() == kLambda0) { thisV0.mLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, std::array{negP[0], negP[1], negP[2]}}, - std::array{o2::constants::physics::MassPionCharged, - o2::constants::physics::MassProton}); + std::array{o2::constants::physics::MassProton, + o2::constants::physics::MassPionCharged}); } else { thisV0.mLambda = -1; } @@ -1255,17 +1531,23 @@ struct OnTheFlyTracker { if (mcParticle.pdgCode() == kLambda0Bar) { thisV0.mAntiLambda = RecoDecay::m(std::array{std::array{posP[0], posP[1], posP[2]}, std::array{negP[0], negP[1], negP[2]}}, - std::array{o2::constants::physics::MassProton, - o2::constants::physics::MassPionCharged}); + std::array{o2::constants::physics::MassPionCharged, + o2::constants::physics::MassProton}); } else { thisV0.mAntiLambda = -1; } if (v0DecaySettings.doV0QA) { fillHist(TH1, Form("V0Building_Configuration_%i/hV0Building", icfg), 4.0f); - fillHist(TH2, Form("V0Building_Configuration_%i/K0/hMass", icfg), thisV0.mK0, thisV0.pt); - fillHist(TH2, Form("V0Building_Configuration_%i/Lambda/hMass", icfg), thisV0.mLambda, thisV0.pt); - fillHist(TH2, Form("V0Building_Configuration_%i/AntiLambda/hMass", icfg), thisV0.mAntiLambda, thisV0.pt); + if (std::abs(mcParticle.pdgCode()) == kK0Short) { + fillHist(TH2, Form("V0Building_Configuration_%i/K0/hMass", icfg), thisV0.mK0, thisV0.pt); + } + if (mcParticle.pdgCode() == kLambda0) { + fillHist(TH2, Form("V0Building_Configuration_%i/Lambda/hMass", icfg), thisV0.mLambda, thisV0.pt); + } + if (mcParticle.pdgCode() == kLambda0Bar) { + fillHist(TH2, Form("V0Building_Configuration_%i/AntiLambda/hMass", icfg), thisV0.mAntiLambda, thisV0.pt); + } } // add this V0 to vector (will fill cursor later with collision ID) @@ -1277,15 +1559,21 @@ struct OnTheFlyTracker { if (doExtraQA) { histos.fill(HIST("hSimTrackX"), trackParCov.getX()); } + if (isV0) { + continue; // V0 handling done, should not be considered anymore + } bool reconstructed = true; + int nTrkHits = 0; if (enablePrimarySmearing && !fastPrimaryTrackerSettings.fastTrackPrimaries) { reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + nTrkHits = fastTrackerSettings.minSiliconHits; } else if (fastPrimaryTrackerSettings.fastTrackPrimaries) { o2::track::TrackParCov o2Track; o2::upgrade::convertMCParticleToO2Track(mcParticle, o2Track, pdgDB); - const int nHits = fastTracker[icfg]->FastTrack(o2Track, trackParCov, dNdEta); - if (nHits < fastPrimaryTrackerSettings.minSiliconHits) { + o2Track.setPID(pdgCodeToPID(mcParticle.pdgCode())); + nTrkHits = fastTracker[icfg]->FastTrack(o2Track, trackParCov, dNdEta); + if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) { reconstructed = false; } } @@ -1320,7 +1608,7 @@ struct OnTheFlyTracker { // populate vector with track if we reco-ed it if (reconstructed) { - tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); + tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits}); } else { ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); } @@ -1332,6 +1620,7 @@ struct OnTheFlyTracker { o2::vertexing::PVertex primaryVertex; if (enablePrimaryVertexing) { LOG(debug) << "Starting primary vertexing with " << tracksAlice3.size() << " tracks."; + fillHist(TH1, histPath + "hVtxMultGen", tracksAlice3.size()); std::vector lblTracks; std::vector vertices; std::vector vertexTrackIDs; @@ -1346,6 +1635,8 @@ struct OnTheFlyTracker { idxVec.emplace_back(i, o2::dataformats::GlobalTrackID::ITS); // let's say ITS } + getHist(TH1, histPath + "hVtxTrials")->Fill(0); // Tried vertexing + // Calculate vertices const int n_vertices = vertexer.process(tracksAlice3, // track array idxVec, @@ -1356,9 +1647,17 @@ struct OnTheFlyTracker { gsl::span{lblTracks}, lblVtx); + LOG(debug) << "Vertex reconstruction efficiency " << vertexReconstructionEfficiencyCounters.second << "/" << vertexReconstructionEfficiencyCounters.first << "=" << vertexReconstructionEfficiencyCounters.second / vertexReconstructionEfficiencyCounters.first; if (n_vertices < 1) { + LOG(debug) << "Vertexing completed, no vtx found."; + if (doExtraQA) { + histos.fill(HIST("h1dVerticesNotReco"), tracksAlice3.size()); + } return; // primary vertex not reconstructed } + vertexReconstructionEfficiencyCounters.second += 1; + getHist(TH1, histPath + "hVtxTrials")->Fill(1); // Succeeded vertexing + LOG(debug) << "Vertexing completed with " << n_vertices << " vertices found."; // Find largest vertex int largestVertex = 0; @@ -1371,6 +1670,11 @@ struct OnTheFlyTracker { if (doExtraQA) { histos.fill(HIST("h2dVerticesVsContributors"), primaryVertex.getNContributors(), n_vertices); } + fillHist(TH1, histPath + "hVtxMultReco", primaryVertex.getNContributors()); + fillHist(TH1, histPath + "hDeltaMultPVRecoGen", static_cast(primaryVertex.getNContributors()) - static_cast(tracksAlice3.size())); + fillHist(TH1, histPath + "hDeltaXPVRecoGen", primaryVertex.getX() - mcCollision.posX()); + fillHist(TH1, histPath + "hDeltaYPVRecoGen", primaryVertex.getY() - mcCollision.posY()); + fillHist(TH1, histPath + "hDeltaZPVRecoGen", primaryVertex.getZ() - mcCollision.posZ()); } else { primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); } @@ -1400,6 +1704,7 @@ struct OnTheFlyTracker { // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* // populate tracks + LOG(debug) << "Populating " << tracksAlice3.size() << " tracks."; for (const auto& trackParCov : tracksAlice3) { // Fixme: collision index could be changeable aod::track::TrackTypeEnum trackType = aod::track::Track; @@ -1418,20 +1723,20 @@ struct OnTheFlyTracker { } if (cascadeDecaySettings.doXiQA) { if (trackParCov.isUsedInCascading == 1) { - histos.fill(HIST("h2dDCAxyCascade"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - histos.fill(HIST("h2dDCAzCascade"), trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAxyCascade")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascade")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please } if (trackParCov.isUsedInCascading == 2) { - histos.fill(HIST("h2dDCAxyCascadeBachelor"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - histos.fill(HIST("h2dDCAzCascadeBachelor"), trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAxyCascadeBachelor")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascadeBachelor")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please } if (trackParCov.isUsedInCascading == 3) { - histos.fill(HIST("h2dDCAxyCascadeNegative"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - histos.fill(HIST("h2dDCAzCascadeNegative"), trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAxyCascadeNegative")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascadeNegative")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please } if (trackParCov.isUsedInCascading == 4) { - histos.fill(HIST("h2dDCAxyCascadePositive"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please - histos.fill(HIST("h2dDCAzCascadePositive"), trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAxyCascadePositive")->Fill(trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + getHist(TH2, histPath + "h2dDCAzCascadePositive")->Fill(trackParametrization.getPt(), dcaZ * 1e+4); // in microns, please } } tableTracksDCA(dcaXY, dcaZ); @@ -1467,6 +1772,7 @@ struct OnTheFlyTracker { } // populate ghost tracks + LOG(debug) << "Populating " << ghostTracksAlice3.size() << " ghost tracks."; for (const auto& trackParCov : ghostTracksAlice3) { // Fixme: collision index could be changeable aod::track::TrackTypeEnum trackType = aod::track::Track; @@ -1517,6 +1823,7 @@ struct OnTheFlyTracker { } // populate Cascades + LOG(debug) << "Populating " << cascadesAlice3.size() << " cascades."; for (const auto& cascade : cascadesAlice3) { tableUpgradeCascades(tableCollisions.lastIndex(), // now we know the collision index -> populate table cascade.cascadeTrackId, @@ -1535,6 +1842,7 @@ struct OnTheFlyTracker { } // populate V0s + LOG(debug) << "Populating " << v0sAlice3.size() << " V0s."; for (const auto& v0 : v0sAlice3) { tableUpgradeV0s(tableCollisions.lastIndex(), // now we know the collision index -> populate table v0.mcParticleId, @@ -1553,14 +1861,284 @@ struct OnTheFlyTracker { histos.fill(HIST("hCovMatOK"), 0.0f, fastTracker[icfg]->GetCovMatNotOK()); histos.fill(HIST("hCovMatOK"), 1.0f, fastTracker[icfg]->GetCovMatOK()); } + LOG(debug) << " <- Finished processing OTF tracking with LUT configuration ID " << icfg; } // end process - void process(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + void processOnTheFly(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) { for (size_t icfg = 0; icfg < mSmearer.size(); ++icfg) { + LOG(debug) << " -> Processing OTF tracking with LUT configuration ID " << icfg; processWithLUTs(mcCollision, mcParticles, static_cast(icfg)); } } + + void processConfigurationDev(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles, const int icfg) + { + // const int lastTrackIndex = tableStoredTracksCov.lastIndex() + 1; // bookkeep the last added track + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; + tracksAlice3.clear(); + ghostTracksAlice3.clear(); + bcData.clear(); + cascadesAlice3.clear(); + v0sAlice3.clear(); + + o2::dataformats::DCA dcaInfo; + o2::dataformats::VertexBase vtx; + + // generate collision time + auto ir = irSampler.generateCollisionTime(); + const float eventCollisionTimeNS = ir.timeInBCNS; + + // First we compute the number of charged particles in the event + dNdEta = 0.f; + for (const auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.eta()) > multEtaRange) { + continue; + } + + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + + const auto pdg = std::abs(mcParticle.pdgCode()); + const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), pdg) != longLivedHandledPDGs.end(); + const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), pdg) != nucleiPDGs.end(); + const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled); + if (!pdgsToBeHandled) { + continue; + } + + const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database"; + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + dNdEta += 1.f; + } + + dNdEta /= (multEtaRange * 2.0f); + uint32_t multiplicityCounter = 0; + getHist(TH1, histPath + "hLUTMultiplicity")->Fill(dNdEta); + + // Now that the multiplicity is known, we can process the particles to smear them + for (const auto& mcParticle : mcParticles) { + const bool longLivedToBeHandled = std::find(longLivedHandledPDGs.begin(), longLivedHandledPDGs.end(), std::abs(mcParticle.pdgCode())) != longLivedHandledPDGs.end(); + const bool nucleiToBeHandled = std::find(nucleiPDGs.begin(), nucleiPDGs.end(), std::abs(mcParticle.pdgCode())) != nucleiPDGs.end(); + const bool pdgsToBeHandled = longLivedToBeHandled || (enableNucleiSmearing && nucleiToBeHandled); + if (!pdgsToBeHandled) { + continue; + } + + if (std::fabs(mcParticle.eta()) > maxEta) { + continue; + } + + if (mcParticle.pt() < minPt) { + continue; + } + + if (enablePrimarySmearing) { + getHist(TH1, histPath + "hPtGenerated")->Fill(mcParticle.pt()); + getHist(TH1, histPath + "hPhiGenerated")->Fill(mcParticle.phi()); + switch (std::abs(mcParticle.pdgCode())) { + case kElectron: + getHist(TH1, histPath + "hPtGeneratedEl")->Fill(mcParticle.pt()); + break; + case kPiPlus: + getHist(TH1, histPath + "hPtGeneratedPi")->Fill(mcParticle.pt()); + break; + case kKPlus: + getHist(TH1, histPath + "hPtGeneratedKa")->Fill(mcParticle.pt()); + break; + case kProton: + getHist(TH1, histPath + "hPtGeneratedPr")->Fill(mcParticle.pt()); + break; + } + } + + multiplicityCounter++; + o2::track::TrackParCov trackParCov; + const bool isDecayDaughter = (mcParticle.getProcess() == TMCProcess::kPDecay); + const float timeResolutionNs = 100.f; // ns + const float nsToMus = 1e-3f; + const float timeResolutionUs = timeResolutionNs * nsToMus; // us + const float time = (eventCollisionTimeNS + gRandom->Gaus(0., timeResolutionNs)) * nsToMus; + + bool reconstructed = false; + int nTrkHits = 0; + if (enablePrimarySmearing && mcParticle.isPrimary()) { + o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB); + reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + nTrkHits = fastTrackerSettings.minSiliconHits; + } else if (enableSecondarySmearing) { + o2::track::TrackParCov perfectTrackParCov; + o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB); + perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode())); + nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta); + if (nTrkHits < fastTrackerSettings.minSiliconHits) { + reconstructed = false; + } else { + reconstructed = true; + } + } + + if (!reconstructed && processUnreconstructedTracks) { + continue; // failed to reconstruct track + } + + if (std::isnan(trackParCov.getZ())) { + histos.fill(HIST("hNaNBookkeeping"), 0.0f, 0.0f); + continue; // capture smearing mistakes + } + + histos.fill(HIST("hNaNBookkeeping"), 0.0f, 1.0f); + if (enablePrimarySmearing) { + getHist(TH1, histPath + "hPtReconstructed")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kElectron) + getHist(TH1, histPath + "hPtReconstructedEl")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) + getHist(TH1, histPath + "hPtReconstructedPi")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kKPlus) + getHist(TH1, histPath + "hPtReconstructedKa")->Fill(trackParCov.getPt()); + if (std::abs(mcParticle.pdgCode()) == kProton) + getHist(TH1, histPath + "hPtReconstructedPr")->Fill(trackParCov.getPt()); + } + + if (reconstructed) { + tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter, false, 0, nTrkHits}); + } else { + ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), time, timeResolutionUs, isDecayDaughter}); + } + } + + o2::vertexing::PVertex primaryVertex; + if (enablePrimaryVertexing) { // disabled for now + primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + } else { + primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + } + + getHist(TH1, histPath + "hSimMultiplicity")->Fill(multiplicityCounter); + getHist(TH1, histPath + "hRecoMultiplicity")->Fill(tracksAlice3.size()); + getHist(TH1, histPath + "hPVz")->Fill(primaryVertex.getZ()); + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // populate collisions + tableCollisions(-1, // BC is irrelevant in synthetic MC tests for now, could be adjusted in future + primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), + primaryVertex.getSigmaX2(), primaryVertex.getSigmaXY(), primaryVertex.getSigmaY2(), + primaryVertex.getSigmaXZ(), primaryVertex.getSigmaYZ(), primaryVertex.getSigmaZ2(), + 0, primaryVertex.getChi2(), primaryVertex.getNContributors(), + eventCollisionTimeNS, 0.f); // For the moment the event collision time is taken as the "GEANT" time, the computation of the event time is done a posteriori from the tracks in the OTF TOF PID task + tableMcCollisionLabels(mcCollision.globalIndex(), 0); + tableCollisionsAlice3(dNdEta); + tableOTFLUTConfigId(icfg); // Populate OTF LUT configuration ID + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // populate tracks + for (const auto& trackParCov : tracksAlice3) { + aod::track::TrackTypeEnum trackType = aod::track::Track; + + if (populateTracksDCA) { + float dcaXY = 1e+10, dcaZ = 1e+10; + o2::track::TrackParCov trackParametrization(trackParCov); + if (trackParametrization.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + } + + tableTracksDCA(dcaXY, dcaZ); + if (populateTracksDCACov) { + tableTracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); + } + } + + tableStoredTracks(tableCollisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); + tableTracksExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); + + // TODO do we keep the rho as 0? Also the sigma's are duplicated information + tableStoredTracksCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), + std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + tableTracksCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), + trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), + trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), + trackParCov.getSigma1Pt2()); + tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); + tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); + + // populate extra tables if required to do so + if (populateTracksExtra) { + tableStoredTracksExtra(0.0f, static_cast(0), static_cast(0), static_cast(0), static_cast(0), + static_cast(0), static_cast(0), static_cast(0), static_cast(0), + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } + if (populateTrackSelection) { + tableTrackSelection(static_cast(0), false, false, false, false, false, false); + tableTrackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + } + tableTracksAlice3(true); + } + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // populate ghost tracks + for (const auto& trackParCov : ghostTracksAlice3) { + aod::track::TrackTypeEnum trackType = aod::track::Track; + + if (populateTracksDCA) { + float dcaXY = 1e+10, dcaZ = 1e+10; + o2::track::TrackParCov trackParametrization(trackParCov); + if (trackParametrization.propagateToDCA(primaryVertex, mMagneticField, &dcaInfo)) { + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + } + + tableTracksDCA(dcaXY, dcaZ); + if (populateTracksDCACov) { + tableTracksDCACov(dcaInfo.getSigmaY2(), dcaInfo.getSigmaZ2()); + } + } + + tableStoredTracks(tableCollisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); + tableTracksExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); + + // TODO do we keep the rho as 0? Also the sigma's are duplicated information + tableStoredTracksCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), + std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + tableTracksCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), + trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), + trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), + trackParCov.getSigma1Pt2()); + tableMcTrackWithDauLabels(trackParCov.mcLabel, 0); + tableTracksExtraA3(trackParCov.nSiliconHits, trackParCov.nTPCHits); + + // populate extra tables if required to do so + if (populateTracksExtra) { + tableStoredTracksExtra(0.0f, static_cast(0), static_cast(0), static_cast(0), static_cast(0), + static_cast(0), static_cast(0), static_cast(0), static_cast(0), + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } + if (populateTrackSelection) { + tableTrackSelection(static_cast(0), false, false, false, false, false, false); + tableTrackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + } + tableTracksAlice3(false); + } + } + + void processDecayer(aod::McCollision const& mcCollision, aod::McPartWithDaus const& mcParticles) + { + for (size_t icfg = 0; icfg < mSmearer.size(); ++icfg) { + processConfigurationDev(mcCollision, mcParticles, static_cast(icfg)); + } + } + + PROCESS_SWITCH(OnTheFlyTracker, processOnTheFly, "Enable default workflow", true); + PROCESS_SWITCH(OnTheFlyTracker, processDecayer, "Enable experimental decayer workflow", false); }; /// Extends TracksExtra if necessary diff --git a/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx index f5ab4c78495..fdb0e72afe2 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTrackerPid.cxx @@ -20,43 +20,39 @@ /// \since May 22, 2025 /// -#include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/Core/FastTracker.h" +#include "GeometryContainer.h" + #include "ALICE3/Core/TrackUtilities.h" #include "ALICE3/DataModel/OTFPIDTrk.h" -#include "ALICE3/DataModel/OTFTracks.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" #include #include -#include -#include -#include -#include -#include -#include #include -#include #include +#include #include +#include #include +#include +#include #include -#include +#include #include -#include -#include +#include +#include +#include #include #include -#include -#include +#include +#include #include -#include #include #include #include +#include +#include #include #include #include @@ -433,12 +429,13 @@ struct OnTheFlyTrackerPid { float mMagneticField = 0.0f; void init(o2::framework::InitContext& initContext) { - mGeoContainer.init(initContext); - mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); - ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setTimestamp(-1); + mGeoContainer.setCcdbManager(ccdb.operator->()); + mGeoContainer.init(initContext); + mMagneticField = mGeoContainer.getFloatValue(0, "global", "magneticfield"); + if (static_cast(maxBarrelLayers.value) > kTrackerRadii.size()) { LOG(fatal) << "Configured maxBarrelLayers (" << maxBarrelLayers.value << ") exceeds the size of kTrackerRadii (" << kTrackerRadii.size() diff --git a/ALICE3/TableProducer/alice3-centrality.cxx b/ALICE3/TableProducer/alice3-centrality.cxx index 48c7ae617bf..bc06a838697 100644 --- a/ALICE3/TableProducer/alice3-centrality.cxx +++ b/ALICE3/TableProducer/alice3-centrality.cxx @@ -11,13 +11,26 @@ /// \author Nicolo' Jacazio , CERN /// \author David Dobrigkeit Chinellato , UNICAMP/CERN -// O2 includes -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/TrackSelectionTables.h" + #include -#include "Common/DataModel/Centrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/ALICE3/TableProducer/alice3-correlatorDDbar.cxx b/ALICE3/TableProducer/alice3-correlatorDDbar.cxx index b17216e9b76..0e27bec4476 100644 --- a/ALICE3/TableProducer/alice3-correlatorDDbar.cxx +++ b/ALICE3/TableProducer/alice3-correlatorDDbar.cxx @@ -14,19 +14,26 @@ /// /// \author Fabio Colamaria , INFN Bari -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" #include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include using namespace o2; diff --git a/ALICE3/TableProducer/alice3-decayfinder.cxx b/ALICE3/TableProducer/alice3-decayfinder.cxx index 15556e78519..f828ee5fbff 100644 --- a/ALICE3/TableProducer/alice3-decayfinder.cxx +++ b/ALICE3/TableProducer/alice3-decayfinder.cxx @@ -21,34 +21,36 @@ #include "ALICE3/DataModel/OTFPIDTrk.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/RICH.h" #include "ALICE3/Utils/utilsHfAlice3.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include #include +#include #include -#include -#include -#include +#include #include using namespace o2; @@ -64,7 +66,8 @@ using std::array; // #define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) // For MC association in pre-selection -using Alice3TracksWPid = soa::Join; +using Alice3TracksWPid = soa::Join; +using Alice3TracksWTrkPid = soa::Join; struct alice3decayFinder { SliceCache cache; @@ -78,16 +81,20 @@ struct alice3decayFinder { Produces mcGenFlags; // contains MC gen info for 3-prong candidates // Vertexing - Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; - Configurable useAbsDCA{"useAbsDCA", true, "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", 1e9, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; - Configurable maxVtxChi2{"maxVtxChi2", 1e9, "reject (if>0) vtx. chi2 above this value"}; - 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"}; + struct : ConfigurableGroup { + std::string prefix = "dcaFitter"; // JSON group name + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", true, "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", 1e9, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxVtxChi2{"maxVtxChi2", 1e9, "reject (if>0) vtx. chi2 above this value"}; + 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 magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; + } dcaFitterSettings; + // Operation and minimisation criteria - Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; Configurable doDCAplotsD{"doDCAplotsD", true, "do daughter prong DCA plots for D mesons"}; Configurable doDCAplots3Prong{"doDCAplots3Prong", true, "do daughter prong DCA plots for Lc baryons"}; Configurable doTopoPlotsForSAndB{"doTopoPlotsForSAndB", true, "do topological variable distributions for S and B separately"}; @@ -129,19 +136,17 @@ struct alice3decayFinder { Configurable lowPtDLimit{"lowPtDLimit", 3.5, "Upper boundary of low pT D range, for topological selection (GeV/c)"}; Configurable highPtDLimit{"highPtDLimit", 16, "Upper boundary of high pT D range, for topological selection (GeV/c)"}; - ConfigurableAxis axisEta{"axisEta", {8, -4.0f, +4.0f}, "#eta"}; - ConfigurableAxis axisY{"axisY", {12, -6.0f, +6.0f}, "y"}; - 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 axisDCADaughters{"axisDCADaughters", {200, 0, 100}, "DCA (#mum)"}; - ConfigurableAxis axisDMass{"axisDMass", {200, 1.765f, 1.965f}, "D Inv Mass (GeV/c^{2})"}; - ConfigurableAxis axisLcMass{"axisLcMass", {200, 2.186f, 2.386f}, "#Lambda_{c} Inv Mass (GeV/c^{2})"}; + ConfigurableAxis binsEta{"binsEta", {8, -4.0f, +4.0f}, "#eta"}; + ConfigurableAxis binsY{"binsY", {12, -6.0f, +6.0f}, "y"}; + ConfigurableAxis binsPt{"binsPt", {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 bins for QA histograms"}; + ConfigurableAxis binsDCA{"binsDCA", {200, -100, 100}, "DCA (#mum)"}; + ConfigurableAxis binsDCADaughters{"binsDCADaughters", {200, 0, 100}, "DCA (#mum)"}; + ConfigurableAxis binsDMass{"binsDMass", {200, 1.765f, 1.965f}, "D Inv Mass (GeV/c^{2})"}; + ConfigurableAxis binsLcMass{"binsLcMass", {200, 2.186f, 2.386f}, "#Lambda_{c} Inv Mass (GeV/c^{2})"}; - o2::vertexing::DCAFitterN<2> fitter; - o2::vertexing::DCAFitterN<3> fitter3; + o2::vertexing::DCAFitterN<2> fitter2prongs; + o2::vertexing::DCAFitterN<3> fitter3prongs; - double bz{0.}; - const float toMicrometers{10000.}; // from cm to µm std::array daugsPdgCodes3Prong{{-1, -1, -1}}; std::array daughtersMasses3Prong{{-1.f, -1.f, -1.f}}; int motherPdgCode{-1}; @@ -181,18 +186,17 @@ struct alice3decayFinder { ((aod::a3DecayMap::decayMap & trackSelectionKaMinusFromD) == trackSelectionKaMinusFromD) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > kaFromD_dcaXYconstant + kaFromD_dcaXYpTdep* nabs(aod::track::signed1Pt); // partitions for Lc baryons - Partition tracksPiPlusFromLc = + Partition tracksPiPlusFromLc = ((aod::a3DecayMap::decayMap & trackSelectionPiPlusFromLc) == trackSelectionPiPlusFromLc) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > piFromLc_dcaXYconstant + piFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); - Partition tracksKaPlusFromLc = + Partition tracksKaPlusFromLc = ((aod::a3DecayMap::decayMap & trackSelectionKaPlusFromLc) == trackSelectionKaPlusFromLc) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > kaFromLc_dcaXYconstant + kaFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); - Partition tracksPrPlusFromLc = + Partition tracksPrPlusFromLc = ((aod::a3DecayMap::decayMap & trackSelectionPrPlusFromLc) == trackSelectionPrPlusFromLc) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > prFromLc_dcaXYconstant + prFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); - // partitions for Lc baryons - Partition tracksPiMinusFromLc = + Partition tracksPiMinusFromLc = ((aod::a3DecayMap::decayMap & trackSelectionPiMinusFromLc) == trackSelectionPiMinusFromLc) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > piFromLc_dcaXYconstant + piFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); - Partition tracksKaMinusFromLc = + Partition tracksKaMinusFromLc = ((aod::a3DecayMap::decayMap & trackSelectionKaMinusFromLc) == trackSelectionKaMinusFromLc) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > kaFromLc_dcaXYconstant + kaFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); - Partition tracksPrMinusFromLc = + Partition tracksPrMinusFromLc = ((aod::a3DecayMap::decayMap & trackSelectionPrMinusFromLc) == trackSelectionPrMinusFromLc) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > prFromLc_dcaXYconstant + prFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); // Helper struct to pass candidate information @@ -245,7 +249,8 @@ struct alice3decayFinder { int flagMc; // 0 = bkg, CharmHadAlice3 otherwise int origin; // 1 = prompt, 2 = non-prompt float ptBMotherRec; // pT of the B hadron mother (reconstructed) - } cand3prong; + int particleMcRec; // MC particle reconstructed + } mCandidate3Prong; template bool buildDecayCandidateTwoBody(TTrackType const& posTrackRow, TTrackType const& negTrackRow, float posMass, float negMass, aod::McParticles const& mcParticles) @@ -257,7 +262,7 @@ struct alice3decayFinder { // Move close to minima int nCand = 0; try { - nCand = fitter.process(posTrack, negTrack); + nCand = fitter2prongs.process(posTrack, negTrack); } catch (...) { return false; } @@ -266,13 +271,13 @@ struct alice3decayFinder { } //}-{}-{}-{}-{}-{}-{}-{}-{}-{} - posTrack = fitter.getTrack(0); - negTrack = fitter.getTrack(1); + posTrack = fitter2prongs.getTrack(0); + negTrack = fitter2prongs.getTrack(1); std::array posP; std::array negP; posTrack.getPxPyPzGlo(posP); negTrack.getPxPyPzGlo(negP); - dmeson.dcaDau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + dmeson.dcaDau = TMath::Sqrt(fitter2prongs.getChi2AtPCACandidate()); dmeson.Pdaug[0] = posP[0]; dmeson.Pdaug[1] = posP[1]; dmeson.Pdaug[2] = posP[2]; @@ -288,11 +293,11 @@ struct alice3decayFinder { dmeson.phi = RecoDecay::phi(array{posP[0] + negP[0], posP[1] + negP[1]}); dmeson.eta = RecoDecay::eta(array{posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}); dmeson.y = RecoDecay::y(std::array{posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}, dmeson.mass); - const auto posSV = fitter.getPCACandidate(); + const auto posSV = fitter2prongs.getPCACandidate(); dmeson.posSV[0] = posSV[0]; dmeson.posSV[1] = posSV[1]; dmeson.posSV[2] = posSV[2]; - o2::track::TrackParCov parentTrack = fitter.createParentTrackParCov(); + o2::track::TrackParCov parentTrack = fitter2prongs.createParentTrackParCov(); parentTrack.getPxPyPzGlo(dmeson.P); dmeson.cosThetaStar = RecoDecay::cosThetaStar(std::array{std::array{posP[0], posP[1], posP[2]}, std::array{negP[0], negP[1], negP[2]}}, std::array{posMass, negMass}, dmeson.mass, 0); @@ -315,7 +320,11 @@ struct alice3decayFinder { } template - bool buildDecayCandidateThreeBody(aod::Collision const& collision, TTrackType const& prong0, TTrackType const& prong1, TTrackType const& prong2, aod::McParticles const& mcParticles) + bool buildDecayCandidateThreeBody(aod::Collision const& collision, + TTrackType const& prong0, + TTrackType const& prong1, + TTrackType const& prong2, + aod::McParticles const& mcParticles) { // get the collision primary vertex auto primaryVertex = getPrimaryVertex(collision); @@ -324,38 +333,38 @@ struct alice3decayFinder { o2::track::TrackParCov trackParVar0 = getTrackParCov(prong0); o2::track::TrackParCov trackParVar1 = getTrackParCov(prong1); o2::track::TrackParCov trackParVar2 = getTrackParCov(prong2); - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima int nCand = 0; try { histos.fill(HIST("hCandidateBuilderStatus3Prong"), 0.f); // builds candidate - nCand = fitter3.process(trackParVar0, trackParVar1, trackParVar2); + nCand = fitter3prongs.process(trackParVar0, trackParVar1, trackParVar2); } catch (...) { LOG(info) << "Second vertex fit failed"; return false; } - histos.fill(HIST("hCandidateBuilderStatus3Prong"), 1.f); // builds candidate + histos.fill(HIST("hCandidateBuilderStatus3Prong"), 1.f); // fit success if (nCand == 0) { + LOG(debug) << "No candidate found in vertex fit " << fitter3prongs.getFitStatus(); return false; } - histos.fill(HIST("hCandidateBuilderStatus3Prong"), 2.f); // builds candidate - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + histos.fill(HIST("hCandidateBuilderStatus3Prong"), 2.f); // nCand > 0 - auto covMatrixPCA = fitter3.calcPCACovMatrixFlat(); - cand3prong.chi2PCA = fitter3.getChi2AtPCACandidate(); - cand3prong.dcaDau = TMath::Sqrt(fitter3.getChi2AtPCACandidate()); - if (cand3prong.dcaDau > dcaDaughtersSelection) { + auto covMatrixPCA = fitter3prongs.calcPCACovMatrixFlat(); + mCandidate3Prong.chi2PCA = fitter3prongs.getChi2AtPCACandidate(); + mCandidate3Prong.dcaDau = TMath::Sqrt(fitter3prongs.getChi2AtPCACandidate()); + if (mCandidate3Prong.dcaDau > dcaDaughtersSelection) { return false; } - histos.fill(HIST("hCandidateBuilderStatus3Prong"), 3.f); // builds candidate + histos.fill(HIST("hCandidateBuilderStatus3Prong"), 3.f); // DCA cut passed - cand3prong.primaryVertex = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; - auto secondaryVertex = fitter3.getPCACandidate(); - cand3prong.secondaryVertex = {secondaryVertex[0], secondaryVertex[1], secondaryVertex[2]}; + mCandidate3Prong.primaryVertex = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; + auto secondaryVertex = fitter3prongs.getPCACandidate(); + mCandidate3Prong.secondaryVertex = {secondaryVertex[0], secondaryVertex[1], secondaryVertex[2]}; - trackParVar0 = fitter3.getTrack(0); - trackParVar1 = fitter3.getTrack(1); - trackParVar2 = fitter3.getTrack(2); + trackParVar0 = fitter3prongs.getTrack(0); + trackParVar1 = fitter3prongs.getTrack(1); + trackParVar2 = fitter3prongs.getTrack(2); std::array P0{}; std::array P1{}; @@ -367,9 +376,10 @@ struct alice3decayFinder { o2::dataformats::DCA impactParameter0; o2::dataformats::DCA impactParameter1; o2::dataformats::DCA impactParameter2; - trackParVar0.propagateToDCA(primaryVertex, bz, &impactParameter0); - trackParVar1.propagateToDCA(primaryVertex, bz, &impactParameter1); - trackParVar2.propagateToDCA(primaryVertex, bz, &impactParameter2); + trackParVar0.propagateToDCA(primaryVertex, dcaFitterSettings.magneticField, &impactParameter0); + trackParVar1.propagateToDCA(primaryVertex, dcaFitterSettings.magneticField, &impactParameter1); + trackParVar2.propagateToDCA(primaryVertex, dcaFitterSettings.magneticField, &impactParameter2); + const float toMicrometers = 10000.; // from cm to µm histos.fill(HIST("hDcaXYProngs"), prong0.pt(), impactParameter0.getY() * toMicrometers); histos.fill(HIST("hDcaXYProngs"), prong1.pt(), impactParameter1.getY() * toMicrometers); histos.fill(HIST("hDcaXYProngs"), prong2.pt(), impactParameter2.getY() * toMicrometers); @@ -380,62 +390,57 @@ struct alice3decayFinder { // get uncertainty of the decay length double phi, theta; getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); - cand3prong.errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); - cand3prong.errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); - - cand3prong.impactParameterY0 = impactParameter0.getY(); - cand3prong.errorImpactParameterY0 = impactParameter0.getSigmaY2(); - cand3prong.impactParameterY1 = impactParameter1.getY(); - cand3prong.errorImpactParameterY1 = impactParameter1.getSigmaY2(); - cand3prong.impactParameterY2 = impactParameter2.getY(); - cand3prong.errorImpactParameterY2 = impactParameter2.getSigmaY2(); - - cand3prong.impactParameterZ0 = impactParameter0.getZ(); - cand3prong.errorImpactParameterZ0 = impactParameter0.getSigmaZ2(); - cand3prong.impactParameterZ1 = impactParameter1.getZ(); - cand3prong.errorImpactParameterZ1 = impactParameter1.getSigmaZ2(); - cand3prong.impactParameterZ2 = impactParameter2.getZ(); - cand3prong.errorImpactParameterZ2 = impactParameter2.getSigmaZ2(); + mCandidate3Prong.errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + mCandidate3Prong.errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + mCandidate3Prong.impactParameterY0 = impactParameter0.getY(); + mCandidate3Prong.errorImpactParameterY0 = impactParameter0.getSigmaY2(); + mCandidate3Prong.impactParameterY1 = impactParameter1.getY(); + mCandidate3Prong.errorImpactParameterY1 = impactParameter1.getSigmaY2(); + mCandidate3Prong.impactParameterY2 = impactParameter2.getY(); + mCandidate3Prong.errorImpactParameterY2 = impactParameter2.getSigmaY2(); + + mCandidate3Prong.impactParameterZ0 = impactParameter0.getZ(); + mCandidate3Prong.errorImpactParameterZ0 = impactParameter0.getSigmaZ2(); + mCandidate3Prong.impactParameterZ1 = impactParameter1.getZ(); + mCandidate3Prong.errorImpactParameterZ1 = impactParameter1.getSigmaZ2(); + mCandidate3Prong.impactParameterZ2 = impactParameter2.getZ(); + mCandidate3Prong.errorImpactParameterZ2 = impactParameter2.getSigmaZ2(); // return mass - cand3prong.mass = RecoDecay::m(array{array{P0[0], P0[1], P0[2]}, - array{P1[0], P1[1], P1[2]}, - array{P2[0], P2[1], P2[2]}}, - daughtersMasses3Prong); - - cand3prong.pt = std::hypot(P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1]); - cand3prong.phi = RecoDecay::phi(array{P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1]}); - cand3prong.eta = RecoDecay::eta(array{P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1], P0[2] + P1[2] + P2[2]}); - cand3prong.Pdaug0[0] = P0[0]; - cand3prong.Pdaug0[1] = P0[1]; - cand3prong.Pdaug0[2] = P0[2]; - cand3prong.Pdaug1[0] = P1[0]; - cand3prong.Pdaug1[1] = P1[1]; - cand3prong.Pdaug1[2] = P1[2]; - cand3prong.Pdaug2[0] = P2[0]; - cand3prong.Pdaug2[1] = P2[1]; - cand3prong.Pdaug2[2] = P2[2]; + mCandidate3Prong.mass = RecoDecay::m(array{array{P0[0], P0[1], P0[2]}, + array{P1[0], P1[1], P1[2]}, + array{P2[0], P2[1], P2[2]}}, + daughtersMasses3Prong); + + mCandidate3Prong.pt = std::hypot(P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1]); + mCandidate3Prong.phi = RecoDecay::phi(array{P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1]}); + mCandidate3Prong.eta = RecoDecay::eta(array{P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1], P0[2] + P1[2] + P2[2]}); + mCandidate3Prong.Pdaug0[0] = P0[0]; + mCandidate3Prong.Pdaug0[1] = P0[1]; + mCandidate3Prong.Pdaug0[2] = P0[2]; + mCandidate3Prong.Pdaug1[0] = P1[0]; + mCandidate3Prong.Pdaug1[1] = P1[1]; + mCandidate3Prong.Pdaug1[2] = P1[2]; + mCandidate3Prong.Pdaug2[0] = P2[0]; + mCandidate3Prong.Pdaug2[1] = P2[1]; + mCandidate3Prong.Pdaug2[2] = P2[2]; // MC truth check - cand3prong.flagMc = 0; // bkg + mCandidate3Prong.flagMc = 0; // bkg int8_t sign = 0; auto arrayDaughters = std::array{prong0, prong1, prong2}; - int indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, motherPdgCode, daugsPdgCodes3Prong, true, &sign, 2); - auto motherPart = mcParticles.rawIteratorAt(indexRec); - if (indexRec > -1) { - cand3prong.flagMc = motherPart.pdgCode() > 0 ? charmHadFlag : -charmHadFlag; // Particle - } - - cand3prong.origin = 0; - if (indexRec > -1) { - auto motherParticle = mcParticles.rawIteratorAt(indexRec); + mCandidate3Prong.particleMcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, motherPdgCode, daugsPdgCodes3Prong, true, &sign, 2); + mCandidate3Prong.origin = 0; // Default: unknown origin + if (mCandidate3Prong.particleMcRec > -1) { + const auto& motherParticle = mcParticles.rawIteratorAt(mCandidate3Prong.particleMcRec); + mCandidate3Prong.flagMc = motherParticle.pdgCode() > 0 ? charmHadFlag : -charmHadFlag; // Particle std::vector idxBhadMothers{}; - int origin = RecoDecay::getCharmHadronOrigin(mcParticles, motherParticle, false, &idxBhadMothers); - cand3prong.origin = origin; - cand3prong.ptBMotherRec = -1.f; - if (origin == RecoDecay::OriginType::NonPrompt) { + mCandidate3Prong.origin = RecoDecay::getCharmHadronOrigin(mcParticles, motherParticle, false, &idxBhadMothers); + mCandidate3Prong.ptBMotherRec = -1.f; + if (mCandidate3Prong.origin == RecoDecay::OriginType::NonPrompt) { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); - cand3prong.ptBMotherRec = bHadMother.pt(); + mCandidate3Prong.ptBMotherRec = bHadMother.pt(); } } return true; @@ -467,27 +472,35 @@ struct alice3decayFinder { void init(InitContext&) { // initialize O2 2-prong fitter (only once) - fitter.setPropagateToPCA(propagateToPCA); - fitter.setMaxR(maxR); - fitter.setMinParamChange(minParamChange); - fitter.setMinRelChi2Change(minRelChi2Change); - fitter.setMaxDZIni(maxDZIni); - fitter.setMaxChi2(maxVtxChi2); - fitter.setUseAbsDCA(useAbsDCA); - fitter.setWeightedFinalPCA(useWeightedFinalPCA); - fitter.setBz(magneticField); - fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); - - fitter3.setPropagateToPCA(propagateToPCA); - fitter3.setMaxR(maxR); - fitter3.setMinParamChange(minParamChange); - fitter3.setMinRelChi2Change(minRelChi2Change); - fitter3.setMaxDZIni(maxDZIni); - fitter3.setMaxChi2(maxVtxChi2); - fitter3.setUseAbsDCA(useAbsDCA); - fitter3.setWeightedFinalPCA(useWeightedFinalPCA); - fitter3.setBz(magneticField); - fitter3.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + fitter2prongs.setPropagateToPCA(dcaFitterSettings.propagateToPCA); + fitter2prongs.setMaxR(dcaFitterSettings.maxR); + fitter2prongs.setMinParamChange(dcaFitterSettings.minParamChange); + fitter2prongs.setMinRelChi2Change(dcaFitterSettings.minRelChi2Change); + fitter2prongs.setMaxDZIni(dcaFitterSettings.maxDZIni); + fitter2prongs.setMaxChi2(dcaFitterSettings.maxVtxChi2); + fitter2prongs.setUseAbsDCA(dcaFitterSettings.useAbsDCA); + fitter2prongs.setWeightedFinalPCA(dcaFitterSettings.useWeightedFinalPCA); + fitter2prongs.setBz(dcaFitterSettings.magneticField); + fitter2prongs.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + fitter3prongs.setPropagateToPCA(dcaFitterSettings.propagateToPCA); + fitter3prongs.setMaxR(dcaFitterSettings.maxR); + fitter3prongs.setMinParamChange(dcaFitterSettings.minParamChange); + fitter3prongs.setMinRelChi2Change(dcaFitterSettings.minRelChi2Change); + fitter3prongs.setMaxDZIni(dcaFitterSettings.maxDZIni); + fitter3prongs.setMaxChi2(dcaFitterSettings.maxVtxChi2); + fitter3prongs.setUseAbsDCA(dcaFitterSettings.useAbsDCA); + fitter3prongs.setWeightedFinalPCA(dcaFitterSettings.useWeightedFinalPCA); + fitter3prongs.setBz(dcaFitterSettings.magneticField); + fitter3prongs.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + const o2::framework::AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + const o2::framework::AxisSpec axisEta{binsEta, "#eta"}; + const o2::framework::AxisSpec axisY{binsY, "y"}; + const o2::framework::AxisSpec axisDCA{binsDCA, "DCA (#mum)"}; + const o2::framework::AxisSpec axisDCADaughters{binsDCADaughters, "DCA dau (#mum)"}; + const o2::framework::AxisSpec axisDMass{binsDMass, "M (GeV/#it{c}^{2})"}; + const o2::framework::AxisSpec axisLcMass{binsLcMass, "M (GeV/#it{c}^{2})"}; if (doprocessFindDmesons) { histos.add("h2dGenD", "h2dGenD", kTH2F, {axisPt, axisEta}); @@ -574,7 +587,11 @@ struct alice3decayFinder { } } if (doprocessFindLc) { - histos.add("hCandidateBuilderStatus3Prong", "hCandidateBuilderStatus3Prong", kTH1D, {{10, -0.5, 9.5}}); + auto h = histos.add("hCandidateBuilderStatus3Prong", "hCandidateBuilderStatus3Prong", kTH1D, {{10, -0.5, 9.5}}); + h->GetXaxis()->SetBinLabel(1, "candidate calls"); + h->GetXaxis()->SetBinLabel(2, "fit success"); + h->GetXaxis()->SetBinLabel(3, "nCand > 0"); + h->GetXaxis()->SetBinLabel(4, "DCA cut passed"); histos.add("h2dGen3Prong", "h2dGen3Prong", kTH2F, {axisPt, axisEta}); histos.add("h2dGen3ProngBar", "h2dGen3ProngBar", kTH2F, {axisPt, axisEta}); histos.add("h3dRec3Prong", "h3dRec3Prong", kTH3F, {axisPt, axisEta, axisLcMass}); @@ -646,7 +663,7 @@ struct alice3decayFinder { if (doprocessFindLc) { for (auto const& mcParticle : mcParticles) { if (std::abs(mcParticle.pdgCode()) != motherPdgCode) { - mcGenFlags(-1, -1, -1); + mcGenFlags(-1, 0, 0); continue; } std::vector idxBhadMothers{}; @@ -656,7 +673,7 @@ struct alice3decayFinder { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); ptBMotherGen = bHadMother.pt(); } - mcGenFlags(origin, ptBMotherGen, mcParticle.pdgCode() ? charmHadFlag : -charmHadFlag); + mcGenFlags(origin, ptBMotherGen, mcParticle.pdgCode() > 0 ? charmHadFlag : -charmHadFlag); if (mcParticle.pdgCode() > 0) { histos.fill(HIST("h2dGen3Prong"), mcParticle.pt(), mcParticle.eta()); } else { @@ -1009,35 +1026,35 @@ struct alice3decayFinder { if (!buildDecayCandidateThreeBody(collision, prong0, prong1, prong2, mcParticles)) { continue; } - histos.fill(HIST("hDCA3ProngDaughters"), cand3prong.dcaDau * 1e+4); - histos.fill(HIST("hMass3Prong"), cand3prong.mass); - histos.fill(HIST("h3dRec3Prong"), cand3prong.pt, cand3prong.eta, cand3prong.mass); + histos.fill(HIST("hDCA3ProngDaughters"), mCandidate3Prong.dcaDau * 1e+4); + histos.fill(HIST("hMass3Prong"), mCandidate3Prong.mass); + histos.fill(HIST("h3dRec3Prong"), mCandidate3Prong.pt, mCandidate3Prong.eta, mCandidate3Prong.mass); - auto candPx = cand3prong.Pdaug0[0] + cand3prong.Pdaug1[0] + cand3prong.Pdaug2[0]; - auto candPy = cand3prong.Pdaug0[1] + cand3prong.Pdaug1[1] + cand3prong.Pdaug2[1]; - auto candPz = cand3prong.Pdaug0[2] + cand3prong.Pdaug1[2] + cand3prong.Pdaug2[2]; + auto candPx = mCandidate3Prong.Pdaug0[0] + mCandidate3Prong.Pdaug1[0] + mCandidate3Prong.Pdaug2[0]; + auto candPy = mCandidate3Prong.Pdaug0[1] + mCandidate3Prong.Pdaug1[1] + mCandidate3Prong.Pdaug2[1]; + auto candPz = mCandidate3Prong.Pdaug0[2] + mCandidate3Prong.Pdaug1[2] + mCandidate3Prong.Pdaug2[2]; candidate3Prong(collision.globalIndex(), - cand3prong.primaryVertex[0], cand3prong.primaryVertex[1], cand3prong.primaryVertex[2], - cand3prong.secondaryVertex[0], cand3prong.secondaryVertex[1], cand3prong.secondaryVertex[2], - cand3prong.errorDecayLength, cand3prong.errorDecayLengthXY, - cand3prong.chi2PCA, - cand3prong.eta, - cand3prong.phi, - cand3prong.pt, - cand3prong.Pdaug2[0], cand3prong.Pdaug2[1], cand3prong.Pdaug2[2], - cand3prong.Pdaug1[0], cand3prong.Pdaug1[1], cand3prong.Pdaug1[2], - cand3prong.Pdaug0[0], cand3prong.Pdaug0[1], cand3prong.Pdaug0[2], - cand3prong.impactParameterY0, cand3prong.impactParameterY1, cand3prong.impactParameterY2, - std::sqrt(cand3prong.errorImpactParameterY0), - std::sqrt(cand3prong.errorImpactParameterY1), - std::sqrt(cand3prong.errorImpactParameterY2), - cand3prong.impactParameterZ0, cand3prong.impactParameterZ1, cand3prong.impactParameterZ2, - std::sqrt(cand3prong.errorImpactParameterZ0), - std::sqrt(cand3prong.errorImpactParameterZ1), - std::sqrt(cand3prong.errorImpactParameterZ2), + mCandidate3Prong.primaryVertex[0], mCandidate3Prong.primaryVertex[1], mCandidate3Prong.primaryVertex[2], + mCandidate3Prong.secondaryVertex[0], mCandidate3Prong.secondaryVertex[1], mCandidate3Prong.secondaryVertex[2], + mCandidate3Prong.errorDecayLength, mCandidate3Prong.errorDecayLengthXY, + mCandidate3Prong.chi2PCA, + mCandidate3Prong.eta, + mCandidate3Prong.phi, + mCandidate3Prong.pt, + mCandidate3Prong.Pdaug0[0], mCandidate3Prong.Pdaug0[1], mCandidate3Prong.Pdaug0[2], + mCandidate3Prong.Pdaug1[0], mCandidate3Prong.Pdaug1[1], mCandidate3Prong.Pdaug1[2], + mCandidate3Prong.Pdaug2[0], mCandidate3Prong.Pdaug2[1], mCandidate3Prong.Pdaug2[2], + mCandidate3Prong.impactParameterY0, mCandidate3Prong.impactParameterY1, mCandidate3Prong.impactParameterY2, + std::sqrt(mCandidate3Prong.errorImpactParameterY0), + std::sqrt(mCandidate3Prong.errorImpactParameterY1), + std::sqrt(mCandidate3Prong.errorImpactParameterY2), + mCandidate3Prong.impactParameterZ0, mCandidate3Prong.impactParameterZ1, mCandidate3Prong.impactParameterZ2, + std::sqrt(mCandidate3Prong.errorImpactParameterZ0), + std::sqrt(mCandidate3Prong.errorImpactParameterZ1), + std::sqrt(mCandidate3Prong.errorImpactParameterZ2), candPx, candPy, candPz); - mcRecFlags(cand3prong.origin, cand3prong.ptBMotherRec, cand3prong.flagMc); // placeholder for prompt/non-prompt + mcRecFlags(mCandidate3Prong.origin, mCandidate3Prong.ptBMotherRec, mCandidate3Prong.flagMc, mCandidate3Prong.particleMcRec); // placeholder for prompt/non-prompt fillPidTable(prong0, prong1, prong2); } } @@ -1051,15 +1068,27 @@ struct alice3decayFinder { void processFindLc(aod::Collision const& collision, aod::McParticles const& mcParticles, - Alice3TracksWPid const&) + Alice3TracksWTrkPid const& tracks) { + LOG(debug) << "Processing Lc candidates for collision " << collision.globalIndex() << " with " << tracks.size() << " tracks"; + for (auto const& track : tracks) { + if (track.has_mcParticle()) { + LOG(debug) << " - track index: " << track.globalIndex() << ", pT: " << track.pt() << " (MC pt " << track.mcParticle().pt() << "), PID: " << track.mcParticle().pdgCode(); + } + } auto tracksPiPlus = tracksPiPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPiPlus.size() << " pi+ from Lc"; auto tracksKaPlus = tracksKaPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksKaPlus.size() << " K+ from Lc"; auto tracksPrPlus = tracksPrPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPrPlus.size() << " p+ from Lc"; auto tracksPiMinus = tracksPiMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPiMinus.size() << " pi- from Lc"; auto tracksKaMinus = tracksKaMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksKaMinus.size() << " K- from Lc"; auto tracksPrMinus = tracksPrMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + LOG(debug) << " - found " << tracksPrMinus.size() << " p- from Lc"; if (doDCAplots3Prong) { for (auto const& track : tracksPiPlus) diff --git a/ALICE3/TableProducer/alice3-decaypreselector.cxx b/ALICE3/TableProducer/alice3-decaypreselector.cxx index 139f53a6f82..3b138ad03b7 100644 --- a/ALICE3/TableProducer/alice3-decaypreselector.cxx +++ b/ALICE3/TableProducer/alice3-decaypreselector.cxx @@ -17,43 +17,30 @@ // HF decays. Work in progress: use at your own risk! // -#include "PWGLF/DataModel/LFParticleIdentification.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - #include "ALICE3/DataModel/A3DecayFinderTables.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFTOF.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include -#include -#include -#include -#include -#include -#include -#include + #include +#include #include -#include +#include +#include +#include +#include +#include #include -#include -#include +#include + #include +#include #include -#include -#include -#include #include 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))) @@ -74,9 +61,6 @@ struct alice3decaypreselector { 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; @@ -104,7 +88,17 @@ struct alice3decaypreselector { void init(InitContext&) { - // future dev if needed + auto h = histos.add("TracksProcessed", "TracksProcessed", o2::framework::HistType::kTH1D, {{10, 0, 10}}); + h->GetXaxis()->SetBinLabel(1, "TotalTracks"); + h->GetXaxis()->SetBinLabel(2, "InnerTOFPiRejected"); + h->GetXaxis()->SetBinLabel(3, "InnerTOFKaRejected"); + h->GetXaxis()->SetBinLabel(4, "InnerTOFPrRejected"); + h->GetXaxis()->SetBinLabel(5, "OuterTOFPiRejected "); + h->GetXaxis()->SetBinLabel(6, "OuterTOFKaRejected"); + h->GetXaxis()->SetBinLabel(7, "OuterTOFPrRejected"); + h->GetXaxis()->SetBinLabel(8, "RICHPiRejected"); + h->GetXaxis()->SetBinLabel(9, "RICHKaRejected"); + h->GetXaxis()->SetBinLabel(10, "RICHPrRejected"); } // go declarative: use partitions instead of "if", then just toggle bits to allow for mask selection later @@ -129,37 +123,56 @@ struct alice3decaypreselector { /// This process function ensures that all V0s are built. It will simply tag everything as true. void processInitialize(aod::Tracks const& tracks) { + histos.fill(HIST("TracksProcessed"), 0.5, tracks.size()); initializeMasks(tracks.size()); } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* void processFilterInnerTOF(tofTracks const&) { - for (auto const& track : pInnerTOFPi) + for (auto const& track : pInnerTOFPi) { bitoff(selectionMap[track.globalIndex()], kInnerTOFPion); - for (auto const& track : pInnerTOFKa) + histos.fill(HIST("TracksProcessed"), 1.5); + } + for (auto const& track : pInnerTOFKa) { bitoff(selectionMap[track.globalIndex()], kInnerTOFKaon); - for (auto const& track : pInnerTOFPr) + histos.fill(HIST("TracksProcessed"), 2.5); + } + for (auto const& track : pInnerTOFPr) { bitoff(selectionMap[track.globalIndex()], kInnerTOFProton); + histos.fill(HIST("TracksProcessed"), 3.5); + } } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* void processFilterOuterTOF(tofTracks const&) { - for (auto const& track : pOuterTOFPi) + for (auto const& track : pOuterTOFPi) { bitoff(selectionMap[track.globalIndex()], kOuterTOFPion); - for (auto const& track : pOuterTOFKa) + histos.fill(HIST("TracksProcessed"), 4.5); + } + for (auto const& track : pOuterTOFKa) { bitoff(selectionMap[track.globalIndex()], kOuterTOFKaon); - for (auto const& track : pOuterTOFPr) + histos.fill(HIST("TracksProcessed"), 5.5); + } + for (auto const& track : pOuterTOFPr) { bitoff(selectionMap[track.globalIndex()], kOuterTOFProton); + histos.fill(HIST("TracksProcessed"), 6.5); + } } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* void processFilterRICH(richTracks const&) { - for (auto const& track : pRICHPi) + for (auto const& track : pRICHPi) { bitoff(selectionMap[track.globalIndex()], kRICHPion); - for (auto const& track : pRICHKa) + histos.fill(HIST("TracksProcessed"), 7.5); + } + for (auto const& track : pRICHKa) { bitoff(selectionMap[track.globalIndex()], kRICHKaon); - for (auto const& track : pRICHPr) + histos.fill(HIST("TracksProcessed"), 8.5); + } + for (auto const& track : pRICHPr) { bitoff(selectionMap[track.globalIndex()], kRICHProton); + histos.fill(HIST("TracksProcessed"), 9.5); + } } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* void processFilterOnMonteCarloTruth(labeledTracks const& tracks, aod::McParticles const&) diff --git a/ALICE3/TableProducer/alice3-dq-table-maker.cxx b/ALICE3/TableProducer/alice3-dq-table-maker.cxx new file mode 100644 index 00000000000..a6f36151732 --- /dev/null +++ b/ALICE3/TableProducer/alice3-dq-table-maker.cxx @@ -0,0 +1,722 @@ +// 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: Ionut Cristian Arsene iarsene@cern.ch, i.c.arsene@fys.uio.no +// Alexander Tiekoetter (alexander.tiekoetter@cern.ch) +/// \file alice3-dq-table-maker.cxx +/// \brief DQ table maker for ALICE 3 + +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/MCSignal.h" +#include "PWGDQ/Core/MCSignalLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedTablesAlice3.h" + +#include "ALICE3/DataModel/OTFRICH.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "ALICE3/DataModel/collisionAlice3.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +using MyBarrelTracks = soa::Join; + +using MyEvents = soa::Join; +using MyEventsMC = aod::McCollisions; + +constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::Collision; +constexpr static uint32_t gkEventMcFillMap = VarManager::ObjTypes::CollisionMC; + +constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; + +struct Alice3DQTableMaker { + + Produces eventMC; + Produces trackMC; + + Produces event; + Produces eventVtxCov; + Produces eventInfo; + Produces eventMClabels; + + Produces trackBarrelInfo; + Produces trackBasic; + Produces trackBarrel; + Produces trackBarrelCov; + Produces trackBarrelAssoc; + Produces trackBarrelLabels; + + Produces trackPIDTOF; + Produces trackPIDRich; + Produces trackPIDRichSig; + + OutputObj fOutputList{"output"}; + OutputObj fStatsList{"Statistics"}; //! skimming statistics + + HistogramManager* fHistMan; + + // Event and track AnalysisCut configurables + struct : ConfigurableGroup { + Configurable fConfigEventCuts{"cfgEventCuts", "", "Event selection"}; + Configurable fConfigTrackCuts{"cfgBarrelTrackCuts", "", "barrel track cut"}; + Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event selection in JSON format"}; + Configurable fConfigTrackCutsJSON{"cfgBarrelTrackCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; + } fConfigCuts; + + // MC signals to be skimmed + Configurable fConfigMCSignals{"cfgMCsignals", "", "Comma separated list of MC signals"}; + Configurable fConfigMCSignalsJSON{"cfgMCsignalsJSON", "", "Additional list of MC signals via JSON"}; + + // Steer QA output + struct : ConfigurableGroup { + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigDetailedQA{"cfgDetailedQA", false, "If true, include more QA histograms (BeforeCuts classes)"}; + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddMCTruthHistogram{"cfgAddMCTruthHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + } fConfigHistOutput; + + AnalysisCompositeCut* fEventCut; //! Event selection cut + std::vector fTrackCuts; //! Barrel track cuts + std::vector fMuonCuts; //! Muon track cuts + + bool fDoDetailedQA = false; + + std::vector fMCSignals; + std::map fLabelsMap; + std::map fLabelsMapReversed; + std::map fMCFlags; + std::map fCollIndexMap; // key: old collision index, value: skimmed collision index + std::map fTrackIndexMap; // key: old track global index, value: new track global index + + void init(InitContext& context) + { + bool isProcessSkimmingEnabled = context.mOptions.get("processSkimming"); + + if (!isProcessSkimmingEnabled) + LOG(fatal) << "No process function was enabled ALICE 3 TableMaker"; + + VarManager::SetDefaultVarNames(); // Important that this is called before DefineCuts() !!! + + DefineCuts(); + + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + if (fConfigHistOutput.fConfigQA && fConfigHistOutput.fConfigDetailedQA) { + fDoDetailedQA = true; + } + + TString histClasses = ""; + + if (fDoDetailedQA) { + histClasses += "Event_BeforeCuts;"; + } + + if (fConfigHistOutput.fConfigQA) { + histClasses += "Event_AfterCuts;"; + histClasses += "Event_MCTruth;"; + } + + if (isProcessSkimmingEnabled) { + if (fDoDetailedQA) { + histClasses += "TrackBarrel_BeforeCuts;"; + } + + if (fConfigHistOutput.fConfigQA) { + for (const auto& cut : fTrackCuts) { + histClasses += Form("TrackBarrel_%s;", cut->GetName()); + } + } + } + + TString configNamesStr = fConfigMCSignals.value; + std::unique_ptr objArray(configNamesStr.Tokenize(",")); + + if (objArray->GetEntries() > 0) { + for (int isig = 0; isig < objArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objArray->At(isig)->GetName()); + if (sig) { + fMCSignals.push_back(sig); + } + } + } + + TString addMCSignalsStr = fConfigMCSignalsJSON.value; + + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + + for (const auto& mcIt : addMCSignals) { + if (mcIt) { + fMCSignals.push_back(mcIt); + } + } + } + + for (const auto& mcIt : fMCSignals) { + if (fConfigHistOutput.fConfigQA) { + histClasses += Form("MCTruth_%s;", mcIt->GetName()); + } + if (fDoDetailedQA) { + if (isProcessSkimmingEnabled) { + for (const auto& cut : fTrackCuts) { + histClasses += Form("TrackBarrel_%s_%s;", cut->GetName(), mcIt->GetName()); + } + } + } + } + + DefineHistograms(histClasses); + + TString addHistsStr = fConfigHistOutput.fConfigAddJSONHistograms.value; + if (fConfigHistOutput.fConfigQA && addHistsStr != "") { + dqhistograms::AddHistogramsFromJSON(fHistMan, addHistsStr.Data()); + } + + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + void DefineCuts() + { + fEventCut = new AnalysisCompositeCut(true); + TString eventCutStr = fConfigCuts.fConfigEventCuts.value; + fEventCut->AddCut(dqcuts::GetAnalysisCut(eventCutStr.Data())); + + TString addEvCutsStr = fConfigCuts.fConfigEventCutsJSON.value; + if (addEvCutsStr != "") { + std::vector addEvCuts = dqcuts::GetCutsFromJSON(addEvCutsStr.Data()); + for (const auto& cutIt : addEvCuts) { + fEventCut->AddCut(cutIt); + } + } + + // Barrel track cuts + TString cutNamesStr = fConfigCuts.fConfigTrackCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fTrackCuts.push_back(dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + // Additional Barrel track cuts via JSON + TString addTrackCutsStr = fConfigCuts.fConfigTrackCutsJSON.value; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (const auto& t : addTrackCuts) { + fTrackCuts.push_back(reinterpret_cast(t)); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + } + + void DefineHistograms(TString histClasses) + { + std::unique_ptr objArray(histClasses.Tokenize(";")); + for (int iclass = 0; iclass < objArray->GetEntries(); ++iclass) { + TString classStr = objArray->At(iclass)->GetName(); + if (fConfigHistOutput.fConfigQA) { + fHistMan->AddHistClass(classStr.Data()); + } + + TString histEventName = fConfigHistOutput.fConfigAddEventHistogram.value; + if (classStr.Contains("Event")) { + if (fConfigHistOutput.fConfigQA && !classStr.Contains("MCTruth")) { + dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "event", histEventName); + } else { + dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "event", "generator"); + } + } + + TString histTrackName = fConfigHistOutput.fConfigAddTrackHistogram.value; + if (classStr.Contains("Track")) { + if (fConfigHistOutput.fConfigQA) { + dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "track", histTrackName); + } + } + + TString histMCTruthName = fConfigHistOutput.fConfigAddMCTruthHistogram.value; + if (classStr.Contains("MCTruth") && !classStr.Contains("Event")) { + if (fConfigHistOutput.fConfigQA) { + dqhistograms::DefineHistograms(fHistMan, objArray->At(iclass)->GetName(), "mctruth_track", histMCTruthName); + } + } + } + + // create statistics histograms (event, tracks, muons, MCsignals) + fStatsList.setObject(new TList()); + fStatsList->SetOwner(true); + std::vector eventLabels{"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, (float)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()); + } + for (int ib = 1; ib <= o2::aod::evsel::kNsel; ib++) { + histEvents->GetYaxis()->SetBinLabel(ib, o2::aod::evsel::selectionLabels[ib - 1]); + } + histEvents->GetYaxis()->SetBinLabel(o2::aod::evsel::kNsel + 1, "Total"); + 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); + ib = 1; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, ib++) { + histTracks->GetXaxis()->SetBinLabel(ib, (*cut)->GetName()); + } + constexpr int nV0Tags = 5; + const char* v0TagNames[nV0Tags] = {"Photon conversion", "K^{0}_{s}", "#Lambda", "#bar{#Lambda}", "#Omega"}; + for (int ib = 0; ib < nV0Tags; ib++) { + histTracks->GetXaxis()->SetBinLabel(fTrackCuts.size() + 1 + ib, v0TagNames[ib]); + } + fStatsList->Add(histTracks); + + TH1I* histMCsignals = new TH1I("MCsignals", "MC signals", fMCSignals.size() + 1, -0.5, fMCSignals.size() - 0.5 + 1.0); + ib = 1; + for (auto signal = fMCSignals.begin(); signal != fMCSignals.end(); signal++, ib++) { + histMCsignals->GetXaxis()->SetBinLabel(ib, (*signal)->GetName()); + } + histMCsignals->GetXaxis()->SetBinLabel(fMCSignals.size() + 1, "Others (matched to reco tracks)"); + fStatsList->Add(histMCsignals); + } + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + void skimMCCollisions(MyEventsMC const& mcCollisions) + { + // 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. + VarManager::ResetValues(0, VarManager::kNVars); + + for (const auto& mcCollision : mcCollisions) { + VarManager::FillEventAlice3(mcCollision); + + fHistMan->FillHistClass("Event_MCTruth", VarManager::fgValues); + + eventMC(mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), + mcCollision.t(), mcCollision.weight(), mcCollision.impactParameter()); // TODO: Determine and fill multiplicity values + } + } + + void skimMCParticles(aod::McParticles const& mcTracks, MyEventsMC const&) + { + // Select MC particles which fulfill at least one of the user specified MC signals + // In this function we just fill a map with the labels of selected particles, not creating the tables themselves. + // The reason is that in the skims we will additionally add any MC label connected to selected reconstructed tracks + // which were not selected already via the MC signals + + fLabelsMap.clear(); + fLabelsMapReversed.clear(); + fMCFlags.clear(); + + uint16_t mcflags = static_cast(0); // flags which will hold the decisions for each MC signal + int trackCounter = 0; + + for (const auto& mctrack : mcTracks) { + // check all the requested MC signals and fill the decision bit map + mcflags = 0; + int i = 0; + for (const auto& sig : fMCSignals) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = mcTracks.rawIteratorAt(mctrack.globalIndex()); + checked = sig->CheckSignal(true, mctrack_raw); + } else { + checked = sig->CheckSignal(true, mctrack); + } + if (checked) { + mcflags |= (static_cast(1) << i); + } + i++; + } + + // if no MC signals were matched, continue + if (mcflags == 0) { + continue; + } + + // If this MC track was not already added to the map, add it now + if (fLabelsMap.find(mctrack.globalIndex()) == fLabelsMap.end()) { + fLabelsMap[mctrack.globalIndex()] = trackCounter; + fLabelsMapReversed[trackCounter] = mctrack.globalIndex(); + fMCFlags[mctrack.globalIndex()] = mcflags; + trackCounter++; + + // fill histograms for each of the signals, if found + if (fConfigHistOutput.fConfigQA) { + VarManager::FillTrackMC(mcTracks, mctrack); + auto mcCollision = mctrack.template mcCollision_as(); + VarManager::FillEvent(mcCollision); + int j = 0; + for (auto signal = fMCSignals.begin(); signal != fMCSignals.end(); signal++, j++) { + if (mcflags & (static_cast(1) << j)) { + fHistMan->FillHistClass(Form("MCTruth_%s", (*signal)->GetName()), VarManager::fgValues); + } + } + } + } + } + } + + void skimCollisions(MyEvents const& collisions) + { + // Skim reconstructed collisions which are selected by the user specified cuts + // Create a collision index map to relate between the "old" AO2D indices and the skimmed ones + fCollIndexMap.clear(); + + // Loop over collisions + for (const auto& collision : collisions) { + + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(o2::aod::evsel::kNsel)); + + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEventAlice3(collision); // extract event information and place it in the fValues array + + if (collision.has_mcCollision()) { + auto mcCollision = collision.template mcCollision_as(); + VarManager::FillEventAlice3(mcCollision); + } + + if (fDoDetailedQA) { + fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); + } + + // Apply the user specified event selection + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + + (reinterpret_cast(fStatsList->At(0)))->Fill(3.0, static_cast(o2::aod::evsel::kNsel)); + + // Fill historams after event cuts + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + + event(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), + collision.collisionTime(), collision.collisionTimeRes(), collision.multDensity()); + + eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); + eventMClabels(collision.mcCollisionId(), collision.mcMask()); + eventInfo(collision.globalIndex()); + + // add an element for this collision into the map + fCollIndexMap[collision.globalIndex()] = event.lastIndex(); + } + } + + void skimTracks(MyEvents::iterator const& collision, MyBarrelTracks const& /*tracks*/, TrackAssoc const& assocs, aod::McParticles const& mcTracks) + { + // Skim the barrel track associations + // Apply track cuts for each collision association and if it passes the cuts, we skim it. + // NOTE: If selection cuts include conditions on quantities dependent on the associated collision (e.g. DCA), + // one track may pass for some association and fail for others. + // Tracks are written only once in the skims, even if they contribute to more than one association + // so in case of multiple associations, the variables depending on the collision association (e.g. DCA, secondary vertexing, etc) + // have to be recomputed at analysis time for each association. + + uint64_t trackFilteringTag = static_cast(0); + uint32_t trackTempFilterMap = static_cast(0); + uint16_t mcflags = static_cast(0); + int trackCounter = fLabelsMap.size(); + + for (const auto& assoc : assocs) { + + auto track = assoc.template track_as(); + + if (fCollIndexMap.find(track.collisionId()) == fCollIndexMap.end()) { + continue; + } + + trackFilteringTag = static_cast(0); + trackTempFilterMap = static_cast(0); + + // Compute track quantities and fill histograms + VarManager::FillTrackAlice3(track); + + if (fDoDetailedQA) { + fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); + } + + int i = 0; + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, i++) { + if ((*cut)->IsSelected(VarManager::fgValues)) { + trackTempFilterMap |= (static_cast(1) << i); + if (fConfigHistOutput.fConfigQA) { + fHistMan->FillHistClass(Form("TrackBarrel_%s", (*cut)->GetName()), VarManager::fgValues); + } + (reinterpret_cast(fStatsList->At(1)))->Fill(static_cast(i)); + } + } + if (!trackTempFilterMap) { + continue; + } + + // If this track is already present in the index map, it means it was already skimmed, + // so we just store the association and we skip the track + if (fTrackIndexMap.find(track.globalIndex()) != fTrackIndexMap.end()) { + trackBarrelAssoc(fCollIndexMap[collision.globalIndex()], fTrackIndexMap[track.globalIndex()]); + continue; + } + + trackFilteringTag |= (static_cast(trackTempFilterMap) << VarManager::kBarrelUserCutsBits); // BIT13-...: user track filters + + // NOTE: The collision ID that is written in the table is the one originally assigned in the AOD. + // However, in data analysis one should loop over associations, so this one should not be used. + // In the case of Run2-like analysis, there will be no associations, so this ID will be the one originally assigned in the AO2Ds (updated for the skims) + uint32_t reducedEventIdx = fCollIndexMap[track.collisionId()]; + + // 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(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.flags(), track.itsClusterMap(), track.itsChi2NCl(), + track.isReconstructed(), track.nSiliconHits(), track.nTPCHits(), track.length(), track.dcaXY(), + track.dcaZ()); + + if constexpr (static_cast(gkTrackFillMapWithCov & VarManager::ObjTypes::TrackCov)) { + trackBarrelCov(track.cYY(), track.cZY(), track.cZZ(), track.cSnpY(), track.cSnpZ(), + track.cSnpSnp(), track.cTglY(), track.cTglZ(), track.cTglSnp(), track.cTglTgl(), + track.c1PtY(), track.c1PtZ(), track.c1PtSnp(), track.c1PtTgl(), track.c1Pt21Pt2()); + } + + if constexpr (static_cast(gkTrackFillMapWithCov & VarManager::ObjTypes::TrackPID)) { + + trackPIDTOF(track.tofEventTime(), track.tofEventTimeErr(), + track.nSigmaElectronInnerTOF(), track.nSigmaMuonInnerTOF(), track.nSigmaPionInnerTOF(), + track.nSigmaKaonInnerTOF(), track.nSigmaProtonInnerTOF(), track.nSigmaDeuteronInnerTOF(), + track.nSigmaTritonInnerTOF(), track.nSigmaHelium3InnerTOF(), track.nSigmaAlphaInnerTOF(), + track.innerTOFTrackTimeReco(), track.innerTOFTrackLengthReco(), + track.nSigmaElectronOuterTOF(), track.nSigmaMuonOuterTOF(), track.nSigmaPionOuterTOF(), + track.nSigmaKaonOuterTOF(), track.nSigmaProtonOuterTOF(), track.nSigmaDeuteronOuterTOF(), + track.nSigmaTritonOuterTOF(), track.nSigmaHelium3OuterTOF(), track.nSigmaAlphaOuterTOF(), + track.outerTOFTrackTimeReco(), track.outerTOFTrackLengthReco()); + + trackPIDRich(track.nSigmaElectronRich(), track.nSigmaMuonRich(), track.nSigmaPionRich(), + track.nSigmaKaonRich(), track.nSigmaProtonRich(), track.nSigmaDeuteronRich(), + track.nSigmaTritonRich(), track.nSigmaHelium3Rich(), track.nSigmaAlphaRich()); + + trackPIDRichSig(track.hasSig(), track.hasSigInGas(), + track.hasSigEl(), track.hasSigMu(), track.hasSigPi(), + track.hasSigKa(), track.hasSigPr(), track.hasSigDe(), + track.hasSigTr(), track.hasSigHe3(), track.hasSigAl()); + } + + fTrackIndexMap[track.globalIndex()] = trackBasic.lastIndex(); + + // Check whether the MCParticle corresponding to this reconstructed track was already selected for skimming + // If not, add it to the skimming map + if (!track.has_mcParticle()) { + trackBarrelLabels(-1, 0, 0); // this is the case when there is no matched MCParticle + } else { + auto mctrack = track.template mcParticle_as(); + VarManager::FillTrackMC(mcTracks, mctrack); + VarManager::FillResolutions(mctrack, track); + + mcflags = 0; + int i = 0; // runs over the MC signals + int j = 0; // runs over the track cuts + // check all the specified signals and fill histograms for MC truth matched tracks + for (const auto& sig : fMCSignals) { + if (sig->CheckSignal(true, mctrack)) { + mcflags |= (static_cast(1) << i); + // If detailed QA is on, fill histograms for each MC signal and track cut combination + if (fDoDetailedQA) { + j = 0; + for (const auto& cut : fTrackCuts) { + if (trackTempFilterMap & (uint8_t(1) << j)) { + fHistMan->FillHistClass(Form("TrackBarrel_%s_%s", cut->GetName(), sig->GetName()), VarManager::fgValues); // fill the reconstructed truth + } + j++; + } + } + } + i++; + } + + // if the MC truth particle corresponding to this reconstructed track is not already written, + // add it to the skimmed stack + if (!(fLabelsMap.find(mctrack.globalIndex()) != fLabelsMap.end())) { + fLabelsMap[mctrack.globalIndex()] = trackCounter; + fLabelsMapReversed[trackCounter] = mctrack.globalIndex(); + fMCFlags[mctrack.globalIndex()] = mcflags; + trackCounter++; + } + + trackBarrelLabels(fLabelsMap.find(mctrack.globalIndex())->second, track.mcMask(), mcflags); + } + + trackBarrelAssoc(fCollIndexMap[collision.globalIndex()], fTrackIndexMap[track.globalIndex()]); + } // end loop over associations + } // end skimTracks + + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perCollisionTracks = aod::track::collisionId; + + void fullSkimming(MyEvents const& collisions, + MyBarrelTracks const& tracksBarrel, aod::TrackAssoc const& trackAssocs, + MyEventsMC const& mcCollisions, aod::McParticles const& mcParticles) + { + eventMC.reserve(mcCollisions.size()); + skimMCCollisions(mcCollisions); + + // skim collisions + event.reserve(collisions.size()); + eventVtxCov.reserve(collisions.size()); + eventMClabels.reserve(collisions.size()); + eventInfo.reserve(collisions.size()); + + skimCollisions(collisions); + + if (fCollIndexMap.size() == 0) + return; + + skimMCParticles(mcParticles, mcCollisions); + + if constexpr (static_cast(gkTrackFillMapWithCov)) { + fTrackIndexMap.clear(); + trackBasic.reserve(tracksBarrel.size()); + trackBarrel.reserve(tracksBarrel.size()); + trackBarrelCov.reserve(tracksBarrel.size()); + trackPIDTOF.reserve(tracksBarrel.size()); + trackPIDRich.reserve(tracksBarrel.size()); + trackPIDRichSig.reserve(tracksBarrel.size()); + trackBarrelAssoc.reserve(tracksBarrel.size()); + trackBarrelLabels.reserve(tracksBarrel.size()); + } + + if (fCollIndexMap.size() > 0) { + + for (auto const& [origIdx, skimIdx] : fCollIndexMap) { + auto collision = collisions.rawIteratorAt(origIdx); + + if constexpr (static_cast(gkTrackFillMapWithCov)) { + auto groupedTrackIndices = trackAssocs.sliceBy(trackIndicesPerCollision, origIdx); + + skimTracks(collision, tracksBarrel, groupedTrackIndices, mcParticles); + } + } + } + + // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack + for (const auto& [newLabel, oldLabel] : fLabelsMapReversed) { + auto mctrack = mcParticles.iteratorAt(oldLabel); + uint16_t mcflags = fMCFlags.find(oldLabel)->second; + + std::vector mothers; + if (mctrack.has_mothers()) { + for (const auto& m : mctrack.mothersIds()) { + if (m < mcParticles.size()) { // protect against bad mother indices + if (fLabelsMap.find(m) != fLabelsMap.end()) { + mothers.push_back(fLabelsMap.find(m)->second); + } + } else { + LOG(warn) << "Mother label (" << m << ") exceeds the McParticles size (" << mcParticles.size() << ")"; + LOG(warn) << " Check the MC generator"; + } + } + } + + // TODO: Check that the daughter slice in the skimmed table works as expected + // Note that not all daughters from the original table are preserved in the skimmed MC stack + std::vector daughters; + if (mctrack.has_daughters()) { + 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 < mcParticles.size()) { // protect against bad daughter indices + if (fLabelsMap.find(d) != fLabelsMap.end()) { + daughters.push_back(fLabelsMap.find(d)->second); + } + } else { + LOG(warn) << "Daughter label (" << d << ") exceeds the McParticles size (" << mcParticles.size() << ")"; + LOG(warn) << " Check the MC generator"; + } + } + } + int daughterRange[2] = {-1, -1}; + if (daughters.size() > 0) { + daughterRange[0] = daughters[0]; + daughterRange[1] = daughters[daughters.size() - 1]; + } + + // NOTE: Here we assume that MC collisions are not filtered, so there is no new vs old index map for translation + auto mcCollision = mctrack.template mcCollision_as(); + trackMC(mcCollision.globalIndex(), mctrack.pdgCode(), mctrack.statusCode(), mctrack.flags(), + mothers, daughterRange, + mctrack.weight(), mctrack.pt(), mctrack.eta(), mctrack.phi(), mctrack.e(), + mctrack.vx(), mctrack.vy(), mctrack.vz(), mctrack.vt(), mcflags); + + for (unsigned int isig = 0; isig < fMCSignals.size(); isig++) { + if (mcflags & (static_cast(1) << isig)) { + (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(isig)); + } + } + if (mcflags == 0) { + (reinterpret_cast(fStatsList->At(2)))->Fill(static_cast(fMCSignals.size())); + } + } + } + + void processSkimming(MyEvents const& collisions, + MyBarrelTracks const& tracksBarrel, aod::TrackAssoc const& trackAssocs, + MyEventsMC const& mcCollisions, aod::McParticles const& mcParticles) + { + fullSkimming(collisions, tracksBarrel, trackAssocs, mcCollisions, mcParticles); + } + + PROCESS_SWITCH(Alice3DQTableMaker, processSkimming, "Build DQ skimmed data model for ALICE3", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/alice3-multicharmTable.cxx b/ALICE3/TableProducer/alice3-multicharmTable.cxx deleted file mode 100644 index 74728aca472..00000000000 --- a/ALICE3/TableProducer/alice3-multicharmTable.cxx +++ /dev/null @@ -1,848 +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. -// -// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* -// 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 "PWGLF/DataModel/LFParticleIdentification.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "ALICE3/DataModel/OTFMulticharm.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/OTFTracks.h" -#include "ALICE3/DataModel/tracksAlice3.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexer.h" -#include "DetectorsVertexing/PVertexerHelpers.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -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))) -#define getHist(type, name) std::get>(histPointers[name]) - -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 alice3multicharmTable { - SliceCache cache; - - Produces multiCharmIdx; - Produces multiCharmCore; - Produces multiCharmPID; - Produces multiCharmExtra; - - // 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", 0.002f, "DCA between XiC daughters (cm)"}; - Configurable dcaXiCCDaughtersSelection{"dcaXiCCDaughtersSelection", 0.002f, "DCA between XiCC daughters (cm)"}; - - Configurable piFromXiC_dcaXYconstant{"piFromXiC_dcaXYconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiC_dcaZconstant{"piFromXiC_dcaZconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiC_dcaXYpTdep{"piFromXiC_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiC_dcaZpTdep{"piFromXiC_dcaZpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiC_tofDiffInner{"piFromXiC_tofDiffInner", 50, "|signal - expected| (ps)"}; - Configurable piFromXiCC_tofDiffInner{"piFromXiCC_tofDiffInner", 50, "|signal - expected| (ps)"}; - Configurable piFromXiCC_dcaXYconstant{"piFromXiCC_dcaXYconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiCC_dcaZconstant{"piFromXiCC_dcaZconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiCC_dcaXYpTdep{"piFromXiCC_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - Configurable piFromXiCC_dcaZpTdep{"piFromXiCC_dcaZpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - Configurable xiFromXiC_dcaXYconstant{"xiFromXiC_dcaXYconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable xiFromXiC_dcaZconstant{"xiFromXiC_dcaZconstant", 0.001f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable xiFromXiC_dcaXYpTdep{"xiFromXiC_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - Configurable xiFromXiC_dcaZpTdep{"xiFromXiC_dcaZpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - - Configurable xiCFromXiCC_dcaXY{"xiCFromXiCC_dcaXY", 0.0015f, "maxDCA"}; - Configurable xiCFromXiCC_dcaZ{"xiCFromXiCC_dcaZ", 0.0015f, "maxDCA"}; - Configurable xiCC_dcaXY{"xiCC_dcaXY", 0.002f, "maxDCA"}; - Configurable xiCC_dcaZ{"xiCC_dcaZ", 0.002f, "maxDCA"}; - - Configurable minPiCPt{"minPiCPt", 0.15, "Minimum pT for XiC pions"}; - Configurable minPiCCPt{"minPiCCPt", 0.3, "Minimum pT for XiCC pions"}; - Configurable> minNTracks{"minNTracks", {-1}, "Minimum number of tracks"}; - - Configurable minXiRadius{"minXiRadius", 0.5, "Minimum R2D for XiC decay (cm)"}; - Configurable minXiCRadius{"minXiCRadius", 0.001, "Minimum R2D for XiC decay (cm)"}; - Configurable minXiCCRadius{"minXiCCRadius", 0.005, "Minimum R2D for XiCC decay (cm)"}; - Configurable xicMinDecayDistanceFromPV{"xicMinDecayDistanceFromPV", 0.002, "Minimum distance for XiC decay from PV (cm)"}; - Configurable xicMinProperLength{"xicMinProperLength", 0.002, "Minimum proper length for XiC decay (cm)"}; - Configurable xicMaxProperLength{"xicMaxProperLength", 0.06, "Minimum proper length for XiC decay (cm)"}; - Configurable xiccMinProperLength{"xiccMinProperLength", 0.004, "Minimum proper length for XiCC decay (cm)"}; - Configurable xiccMaxProperLength{"xiccMaxProperLength", 999, "Minimum proper length for XiCC decay (cm)"}; - Configurable xiccMaxEta{"xiccMaxEta", 1.5, "Max eta"}; - Configurable massWindowXi{"massWindowXi", 0.015, "Mass window around Xi peak (GeV/c)"}; - Configurable massWindowXiC{"massWindowXiC", 0.015, "Mass window around XiC peak (GeV/c)"}; - Configurable massWindowXiCC{"massWindowXiCC", 0.4, "Mass window around XiCC peak (GeV/c). Make sure that bkg region is included in this window"}; - - 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 axisDCA2D{"axisDCA2D", {400, -200, 200}, "DCA2d (#mum)"}; - ConfigurableAxis axisDCA{"axisDCA", {400, 0, 400}, "DCA (#mum)"}; - ConfigurableAxis axisRadius{"axisRadius", {10000, 0, 10000}, "Decay radius (#mum)"}; - ConfigurableAxis axisRadius2D{"axisRadius2D", {1000, 0, 100000}, "Decay radius (#mum)"}; - ConfigurableAxis axisRadius2DXi{"axisRadius2DXi", {1000, 0, 20}, "Decay radius (cm)"}; - ConfigurableAxis axisDecayLength{"axisDecayLength", {2000, 0, 2000}, "Decay lenght (#mum)"}; - ConfigurableAxis axisTOFTrack{"axisTOFTrack", {1000, 0, 5000}, "TOF track time"}; - - 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 (mum)"}; - ConfigurableAxis axisDCAXiCCDaughters{"axisDCAXiCCDaughters", {200, 0, 100}, "DCA (mum)"}; - - 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}; - std::map histPointers; - std::vector savedConfigs; - - 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) && nabs(aod::track::dcaZ) > piFromXiC_dcaZconstant + piFromXiC_dcaZpTdep* 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) && nabs(aod::track::dcaZ) > piFromXiCC_dcaZconstant + piFromXiCC_dcaZpTdep* 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}); - - if (std::fabs(thisXiCCcandidate.mass - o2::constants::physics::MassXiCCPlusPlus) > massWindowXiCC) { - return false; - } - - 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; - } - - template - int getPdgCodeForTrack(TTrackType track) - { - auto mcParticle = track.template mcParticle_as(); - return mcParticle.pdgCode(); - } - - /// 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; - } - - template - bool checkSameLUTConf(TTrackType const& track1, const int track2) - { - return track1.lutConfigId() == track2; - } - - 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("h3dMassXiCC", "h3dMassXiCC", kTH3D, {axisPt, axisEta, axisXiCCMass}); - - histos.add("hDCAXiCDaughters", "hDCAXiCDaughters", kTH1D, {axisDCAXiCDaughters}); - histos.add("hDCAXiCCDaughters", "hDCAXiCCDaughters", kTH1D, {axisDCAXiCCDaughters}); - histos.add("hDCAxyXi", "hDCAxyXi", kTH1D, {axisDCA}); - histos.add("hDCAzXi", "hDCAzXi", kTH1D, {axisDCA}); - - histos.add("hDCAxyXiC", "hDCAxyXiC", kTH1D, {axisDCA}); - histos.add("hDCAzXiC", "hDCAzXiC", kTH1D, {axisDCA}); - - histos.add("hDCAxyXiCC", "hDCAxyXiCC", kTH1D, {axisDCA}); - histos.add("hDCAzXiCC", "hDCAzXiCC", kTH1D, {axisDCA}); - - histos.add("hPi1cPt", "hPi1cPt", kTH1D, {axisPt}); - histos.add("hPi2cPt", "hPi2cPt", kTH1D, {axisPt}); - histos.add("hPiccPt", "hPiccPt", kTH1D, {axisPt}); - - histos.add("hPi1cDCAxy", "hPi1cDCAxy", kTH1D, {axisDCA}); - histos.add("hPi1cDCAz", "hPi1cDCAz", kTH1D, {axisDCA}); - histos.add("hPi2cDCAxy", "hPi2cDCAxy", kTH1D, {axisDCA}); - histos.add("hPi2cDCAz", "hPi2cDCAz", kTH1D, {axisDCA}); - histos.add("hPiccDCAxy", "hPiccDCAxy", kTH1D, {axisDCA}); - histos.add("hPiccDCAz", "hPiccDCAz", kTH1D, {axisDCA}); - - histos.add("hMinXiDecayRadius", "hMinXiDecayRadius", kTH1D, {axisRadius2DXi}); - histos.add("hMinXiCDecayRadius", "hMinXiCDecayRadius", kTH1D, {axisRadius}); - histos.add("hMinXiCCDecayRadius", "hMinXiCCDecayRadius", kTH1D, {axisRadius}); - - histos.add("hMinxicDecayDistanceFromPV", "hMinxicDecayDistanceFromPV", kTH1D, {axisDecayLength}); - histos.add("hProperLengthXiC", "hProperLengthXiC", kTH1D, {axisDecayLength}); - histos.add("hProperLengthXiCC", "hProperLengthXiCC", kTH1D, {axisDecayLength}); - - histos.add("hInnerTOFTrackTimeRecoPi1c", "hInnerTOFTrackTimeRecoPi1c", kTH1D, {axisTOFTrack}); - histos.add("hInnerTOFTrackTimeRecoPi2c", "hInnerTOFTrackTimeRecoPi2c", kTH1D, {axisTOFTrack}); - histos.add("hInnerTOFTrackTimeRecoPicc", "hInnerTOFTrackTimeRecoPicc", kTH1D, {axisTOFTrack}); - - histos.add("hXiRadiusVsXicRadius", "hXiRadiusVsXicRadius", kTH2D, {axisRadius2D, axisRadius2D}); - histos.add("hXicRadiusVsXiccRadius", "hXicRadiusVsXiccRadius", kTH2D, {axisRadius2D, axisRadius2D}); - - // 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}); - histos.add("hNCollisions", "hNCollisions", kTH1D, {{2, 0.5, 2.5}}); - histos.add("hNTracks", "hNTracks", kTH1D, {{20000, 0, 20000}}); - - if (doDCAplots) { - histos.add("h2dDCAxyVsPtXiFromXiC", "h2dDCAxyVsPtXiFromXiC", kTH2D, {axisPt, axisDCA2D}); - histos.add("h2dDCAxyVsPtPiFromXiC", "h2dDCAxyVsPtPiFromXiC", kTH2D, {axisPt, axisDCA2D}); - histos.add("h2dDCAxyVsPtPiFromXiCC", "h2dDCAxyVsPtPiFromXiCC", kTH2D, {axisPt, axisDCA2D}); - } - } - - void initConf(const int icfg) - { - const bool confExists = std::find(savedConfigs.begin(), savedConfigs.end(), icfg) != savedConfigs.end(); - if (confExists) { - return; - } - savedConfigs.push_back(icfg); - - // do more plots - std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; - histPointers.insert({histPath + "hMassXiCC", histos.add((histPath + "hMassXiCC").c_str(), "hMassXiCC", {kTH1D, {{axisXiCCMass}}})}); - histPointers.insert({histPath + "hNCollisions", histos.add((histPath + "hNCollisions").c_str(), "hNCollisions", {kTH1D, {{2, 0.5, 2.5}}})}); - histPointers.insert({histPath + "hNTracks", histos.add((histPath + "hNTracks").c_str(), "hNTracks", {kTH1D, {{20000, 0, 20000}}})}); - } - - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - 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()); - } - } - - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - 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); - - static constexpr int kMaxLUTConfigs = 20; - std::vector nTracks(kMaxLUTConfigs); - for (auto const& track : tracks) { - int lutConfigId = track.lutConfigId(); - nTracks[lutConfigId]++; - - 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) { - auto xi = xiCand.cascadeTrack_as(); // de-reference cascade track - int lutConfigId = xi.lutConfigId(); - initConf(lutConfigId); - if (minNTracks.value.size() < static_cast(lutConfigId)) { - if (nTracks[lutConfigId] < minNTracks.value.front()) { - continue; // fallback to first - } - } else { - if (nTracks[lutConfigId] < minNTracks.value[lutConfigId]) { - continue; - } - } - - std::string histPath = "Configuration_" + std::to_string(lutConfigId) + "/"; - histos.fill(HIST("hMassXi"), xiCand.mXi()); - histos.fill(HIST("h2dDCAxyVsPtXiFromXiC"), xi.pt(), xi.dcaXY() * 1e+4); - if (std::fabs(xiCand.mXi() - o2::constants::physics::MassXiMinus) > massWindowXi) - continue; // out of mass region - - uint32_t nCombinationsC = 0; - 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; - if (std::fabs(xi.dcaXY()) < xiFromXiC_dcaXYconstant || std::fabs(xi.dcaZ()) < xiFromXiC_dcaZconstant) - continue; // likely a primary xi - - histos.fill(HIST("hDCAxyXi"), std::fabs(xi.dcaXY() * 1e+4)); - histos.fill(HIST("hDCAzXi"), std::fabs(xi.dcaZ() * 1e+4)); - - if (xiCand.cascRadius() < minXiRadius) - continue; - - histos.fill(HIST("hMinXiDecayRadius"), xiCand.cascRadius()); - for (auto const& pi1c : tracksPiFromXiCgrouped) { - if (!checkSameLUTConf(pi1c, lutConfigId)) - continue; - 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; // too low momentum - - histos.fill(HIST("hPi1cPt"), pi1c.pt()); - float pi1cTOFDiffInner = std::fabs(pi1c.innerTOFTrackTimeReco() - pi1c.innerTOFExpectedTimePi()); - float pi1cTOFDiffOuter = std::fabs(pi1c.outerTOFTrackTimeReco() - pi1c.outerTOFExpectedTimePi()); - if (pi1cTOFDiffInner > piFromXiC_tofDiffInner) - continue; // did not arrive at expected time - - histos.fill(HIST("hInnerTOFTrackTimeRecoPi1c"), pi1cTOFDiffInner); - // second pion from XiC decay for starts here - for (auto const& pi2c : tracksPiFromXiCgrouped) { - if (!checkSameLUTConf(pi2c, lutConfigId)) - continue; - 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; // too low momentum - - histos.fill(HIST("hPi2cPt"), pi2c.pt()); - float pi2cTOFDiffInner = std::fabs(pi2c.innerTOFTrackTimeReco() - pi2c.innerTOFExpectedTimePi()); - float pi2cTOFDiffOuter = std::fabs(pi2c.outerTOFTrackTimeReco() - pi2c.outerTOFExpectedTimePi()); - if (pi2cTOFDiffInner > piFromXiC_tofDiffInner) - continue; // did not arrive at expected time - - histos.fill(HIST("hInnerTOFTrackTimeRecoPi2c"), pi2cTOFDiffInner); - // 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, o2::constants::physics::MassXiMinus, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged)) - continue; // failed at building candidate - - histos.fill(HIST("hDCAXiCDaughters"), thisXiCcandidate.dca * 1e+4); - - if (std::fabs(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); - float xicDecayRadius2D = std::hypot(thisXiCcandidate.xyz[0], thisXiCcandidate.xyz[1]); - if (xicDecayRadius2D < minXiCRadius) - continue; // do not take if radius too small, likely a primary combination - - histos.fill(HIST("hMinXiCDecayRadius"), xicDecayRadius2D * 1e+4); - - if (xicDecayRadius2D > xiCand.cascRadius()) - continue; - - histos.fill(HIST("hXiRadiusVsXicRadius"), xiCand.cascRadius() * 1e+4, xicDecayRadius2D * 1e+4); - - 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(); - } - - if (std::fabs(xicdcaXY) < xiCFromXiCC_dcaXY || std::fabs(xicdcaZ) < xiCFromXiCC_dcaZ) - continue; // likely a primary xic - - histos.fill(HIST("hDCAxyXiC"), std::fabs(xicdcaXY * 1e+4)); - histos.fill(HIST("hDCAzXiC"), std::fabs(xicdcaZ * 1e+4)); - histos.fill(HIST("hMassXiC"), thisXiCcandidate.mass); - - // attempt XiCC finding - uint32_t nCombinationsCC = 0; - for (auto const& picc : tracksPiFromXiCCgrouped) { - if (!checkSameLUTConf(picc, lutConfigId)) - continue; - - if (mcSameMotherCheck && !checkSameMotherExtra(xi, picc)) - continue; - - 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; // too low momentum - - histos.fill(HIST("hPiccPt"), picc.pt()); - - float piccTOFDiffInner = std::fabs(picc.innerTOFTrackTimeReco() - picc.innerTOFExpectedTimePi()); - float piccTOFDiffOuter = std::fabs(picc.outerTOFTrackTimeReco() - picc.outerTOFExpectedTimePi()); - if (piccTOFDiffInner > piFromXiCC_tofDiffInner) - continue; // did not arrive at expected time - - histos.fill(HIST("hInnerTOFTrackTimeRecoPicc"), piccTOFDiffInner); - - o2::track::TrackParCov piccTrack = getTrackParCov(picc); - nCombinationsCC++; - histos.fill(HIST("hCharmBuilding"), 2.0f); - if (!buildDecayCandidateTwoBody(xicTrack, piccTrack, o2::constants::physics::MassXiCPlus, o2::constants::physics::MassPionCharged)) - continue; // failed at building candidate - - histos.fill(HIST("hDCAXiCCDaughters"), thisXiCCcandidate.dca * 1e+4); - - 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 xiccDecayRadius2D = std::hypot(thisXiCCcandidate.xyz[0], thisXiCCcandidate.xyz[1]); - if (xiccDecayRadius2D < minXiCCRadius) - continue; // do not take if radius too small, likely a primary combination - - histos.fill(HIST("hMinXiCCDecayRadius"), xiccDecayRadius2D * 1e+4); - - float totalMomentumC = std::hypot(momentumC[0], momentumC[1], momentumC[2]); - float decayLengthXiC = std::hypot( - thisXiCcandidate.xyz[0] - thisXiCCcandidate.xyz[0], - thisXiCcandidate.xyz[1] - thisXiCCcandidate.xyz[1], - thisXiCcandidate.xyz[2] - thisXiCCcandidate.xyz[2]); - float xicProperLength = decayLengthXiC * thisXiCcandidate.mass / totalMomentumC; - - if (xicProperLength < xicMinProperLength || xicProperLength > xicMaxProperLength) - continue; // likely background - - histos.fill(HIST("hProperLengthXiC"), xicProperLength * 1e+4); - - float xicDistanceFromPV = std::hypot( - thisXiCcandidate.xyz[0] - collision.posX(), - thisXiCcandidate.xyz[1] - collision.posY(), - thisXiCcandidate.xyz[2] - collision.posZ()); - float xicDecayDistanceFromPV = xicDistanceFromPV * thisXiCcandidate.mass / totalMomentumC; - if (xicDecayDistanceFromPV < xicMinDecayDistanceFromPV) - continue; // too close to PV - - histos.fill(HIST("hMinxicDecayDistanceFromPV"), xicDecayDistanceFromPV * 1e+4); - - float totalMomentumCC = std::hypot(momentumCC[0], momentumCC[1], momentumCC[2]); - float decayLengthXiCC = std::hypot( - thisXiCCcandidate.xyz[0] - collision.posX(), - thisXiCCcandidate.xyz[1] - collision.posY(), - thisXiCCcandidate.xyz[2] - collision.posZ()); - float xiccProperLength = decayLengthXiCC * thisXiCCcandidate.mass / totalMomentumCC; - if (xiccProperLength < xiccMinProperLength || xiccProperLength > xicMaxProperLength) - continue; // likely background - - histos.fill(HIST("hProperLengthXiCC"), xiccProperLength * 1e+4); - if (xiccDecayRadius2D > xicDecayRadius2D) - continue; // XiCC should decay before XiC - - histos.fill(HIST("hXicRadiusVsXiccRadius"), xicDecayRadius2D * 1e+4, xiccDecayRadius2D * 1e+4); - - float xiccdcaXY = 1e+10, xiccdcaZ = 1e+10; - if (xiccTrack.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { - xiccdcaXY = dcaInfo.getY(); - xiccdcaZ = dcaInfo.getZ(); - } - - if (std::fabs(xiccdcaXY) > xiCC_dcaXY || std::fabs(xiccdcaZ) > xiCC_dcaZ) - continue; // not pointing to PV - - histos.fill(HIST("hDCAxyXiCC"), std::fabs(xiccdcaXY * 1e+4)); - histos.fill(HIST("hDCAzXiCC"), std::fabs(xiccdcaZ * 1e+4)); - - if (std::fabs(thisXiCCcandidate.eta) > xiccMaxEta) - continue; // not in central barrel - - histos.fill(HIST("hCharmBuilding"), 3.0f); - histos.fill(HIST("hMassXiCC"), thisXiCCcandidate.mass); - getHist(TH1, histPath + "hMassXiCC")->Fill(thisXiCCcandidate.mass); - - histos.fill(HIST("hPtXiCC"), thisXiCCcandidate.pt); - histos.fill(HIST("hEtaXiCC"), thisXiCCcandidate.eta); - histos.fill(HIST("h3dMassXiCC"), thisXiCCcandidate.pt, thisXiCCcandidate.eta, thisXiCCcandidate.mass); - - // produce multi-charm table for posterior analysis - if (fillDerivedTable) { - multiCharmIdx( - xiCand.globalIndex(), - pi1c.globalIndex(), pi2c.globalIndex(), - picc.globalIndex()); - - multiCharmCore( - thisXiCCcandidate.mass, thisXiCCcandidate.pt, - thisXiCCcandidate.eta, thisXiCCcandidate.dca, - thisXiCcandidate.mass, thisXiCcandidate.pt, - thisXiCcandidate.eta, thisXiCcandidate.dca, - xi.dcaXY(), xi.dcaZ(), - xicdcaXY, xicdcaZ, - xiccdcaXY, xiccdcaZ, - pi1c.dcaXY(), pi1c.dcaZ(), - pi2c.dcaXY(), pi2c.dcaZ(), - picc.dcaXY(), picc.dcaZ(), - xicDecayRadius2D, xiccDecayRadius2D, - xicProperLength, - xicDecayDistanceFromPV, - xiccProperLength, - pi1c.pt(), pi2c.pt(), picc.pt(), - lutConfigId); - - multiCharmPID( - pi1cTOFDiffInner, pi1c.nSigmaPionInnerTOF(), - pi1cTOFDiffOuter, pi1c.nSigmaPionOuterTOF(), - pi1c.hasSigPi(), pi1c.nSigmaPionRich(), - getPdgCodeForTrack(pi1c), - pi2cTOFDiffInner, pi2c.nSigmaPionInnerTOF(), - pi2cTOFDiffOuter, pi2c.nSigmaPionOuterTOF(), - pi2c.hasSigPi(), pi2c.nSigmaPionRich(), - getPdgCodeForTrack(pi2c), - piccTOFDiffInner, picc.nSigmaPionInnerTOF(), - piccTOFDiffOuter, picc.nSigmaPionOuterTOF(), - picc.hasSigPi(), picc.nSigmaPionRich(), - getPdgCodeForTrack(picc)); - - multiCharmExtra( - piFromXi.pt(), piFromXi.eta(), - piFromXi.dcaXY(), piFromXi.dcaZ(), - prFromLa.pt(), prFromLa.eta(), - prFromLa.dcaXY(), prFromLa.dcaZ(), - piFromLa.pt(), piFromLa.eta(), - piFromLa.dcaXY(), piFromLa.dcaZ(), - pi1c.eta(), pi2c.eta(), picc.eta()); - - histos.fill(HIST("hPi1cDCAxy"), std::abs(pi1c.dcaXY() * 1e+4)); - histos.fill(HIST("hPi1cDCAz"), std::abs(pi1c.dcaZ() * 1e+4)); - histos.fill(HIST("hPi2cDCAxy"), std::abs(pi2c.dcaXY() * 1e+4)); - histos.fill(HIST("hPi2cDCAz"), std::abs(pi2c.dcaZ() * 1e+4)); - histos.fill(HIST("hPiccDCAxy"), std::abs(picc.dcaXY() * 1e+4)); - histos.fill(HIST("hPiccDCAz"), std::abs(picc.dcaZ() * 1e+4)); - } - } - histos.fill(HIST("hCombinationsXiCC"), nCombinationsCC); - } - } - histos.fill(HIST("hCombinationsXiC"), nCombinationsC); - } - } - //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - - //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* - PROCESS_SWITCH(alice3multicharmTable, processGenerated, "fill MC-only histograms", true); - PROCESS_SWITCH(alice3multicharmTable, processFindXiCC, "find XiCC baryons", true); - //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; -} diff --git a/ALICE3/TableProducer/alice3-strangenessFinder.cxx b/ALICE3/TableProducer/alice3-strangenessFinder.cxx deleted file mode 100644 index 29e05d5e7e7..00000000000 --- a/ALICE3/TableProducer/alice3-strangenessFinder.cxx +++ /dev/null @@ -1,197 +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 alice3-strangenessFinder.cxx -/// -/// \brief finding of V0 and cascade candidates for ALICE 3 -/// -/// This task finds and build condidates for strange hadrons (K0s, Lambda, AntiLambda, Xi-, Xi+, Omega-, Omega+) -/// using the output of the on-the-fly tracker. -/// -/// \author Lucia Anna Tarasovičová, Pavol Jozef Šafárik University (SK) -/// - -#include "ALICE3/DataModel/OTFPIDTrk.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/tracksAlice3.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" -#include - -#include - -using namespace o2; -// using namespace o2::analysis; -using namespace o2::framework; -using namespace o2::constants::physics; - -using Alice3TracksWPid = soa::Join; -using Alice3Tracks = soa::Join; - -struct alice3strangenessFinder { - SliceCache cache; - - Produces v0CandidateIndices; // contains V0 candidate indices - Produces v0CandidateCores; // contains V0 candidate core information - - Configurable mcSameMotherCheck{"mcSameMotherCheck", true, "check if tracks come from the same MC mother"}; - - Configurable nSigmaTOF{"nSigmaTOF", 5.0f, "Nsigma for TOF PID (if enabled)"}; - Configurable dcaXYconstant{"dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable dcaXYpTdep{"dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; - - o2::vertexing::DCAFitterN<2> fitter; - o2::vertexing::DCAFitterN<3> fitter3; - - // partitions for D mesons - Partition positiveSecondaryTracks = - aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); - Partition negativeSecondaryTracks = - aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); - // Partition negativeSecondaryPions = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaPionOuterTOF) < nSigmaTOF && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); - // Partition positiveSecondaryPions = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaPionOuterTOF) < nSigmaTOF && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); - // Partition secondaryProtons = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) < nSigmaTOF && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); - // Partition secondaryAntiProtons = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) < nSigmaTOF && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); - - struct { - float dcaDau; - std::array posSV; - std::array P; - std::array Pdaug; // positive track - std::array Ndaug; // negative track - float cosPA; - float dcaToPV; - } v0cand; - - void init(InitContext&) - { - // Initialization code here - } - /// function to check if tracks have the same mother in MC - template - bool checkSameMother(TTrackType const& track1, TTrackType const& track2) - { - bool sameMother = false; - if (!track1.has_mcParticle() || !track2.has_mcParticle()) - return sameMother; - auto mcParticle1 = track1.template mcParticle_as(); - auto mcParticle2 = track2.template mcParticle_as(); - if (!mcParticle1.has_mothers() || !mcParticle2.has_mothers()) - return sameMother; - for (auto& mcParticleMother1 : mcParticle1.template mothers_as()) { - for (auto& mcParticleMother2 : mcParticle2.template mothers_as()) { - if (mcParticleMother1.globalIndex() == mcParticleMother2.globalIndex()) { - sameMother = true; - } - } - } - return sameMother; - } - - template - bool buildDecayCandidateTwoBody(TTrackType const& posTrack, TTrackType const& negTrack) - { - o2::track::TrackParCov posTrackCov = getTrackParCov(posTrack); - o2::track::TrackParCov negTrackCov = getTrackParCov(negTrack); - - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} - // Move close to minima - int nCand = 0; - try { - nCand = fitter.process(posTrackCov, negTrackCov); - } catch (...) { - return false; - } - if (nCand == 0) { - return false; - } - //}-{}-{}-{}-{}-{}-{}-{}-{}-{} - - posTrackCov = fitter.getTrack(0); - negTrackCov = fitter.getTrack(1); - std::array posP; - std::array negP; - posTrackCov.getPxPyPzGlo(posP); - negTrackCov.getPxPyPzGlo(negP); - v0cand.dcaDau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); - v0cand.Pdaug[0] = posP[0]; - v0cand.Pdaug[1] = posP[1]; - v0cand.Pdaug[2] = posP[2]; - v0cand.Ndaug[0] = negP[0]; - v0cand.Ndaug[1] = negP[1]; - v0cand.Ndaug[2] = negP[2]; - v0cand.P[0] = posP[0] + negP[0]; - v0cand.P[1] = posP[1] + negP[1]; - v0cand.P[2] = posP[2] + negP[2]; - const auto posSV = fitter.getPCACandidate(); - v0cand.posSV[0] = posSV[0]; - v0cand.posSV[1] = posSV[1]; - v0cand.posSV[2] = posSV[2]; - - return true; - } - 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)); - } - void processFindV0CandidateNoPid(aod::Collision const& collision, Alice3Tracks const&, aod::McParticles const&) - { - auto negativeSecondaryTracksGrouped = negativeSecondaryTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto positiveSecondaryTracksGrouped = positiveSecondaryTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - - for (auto const& posTrack : positiveSecondaryTracksGrouped) { - for (auto const& negTrack : negativeSecondaryTracksGrouped) { - - if (mcSameMotherCheck && !checkSameMother(posTrack, negTrack)) - continue; - if (!buildDecayCandidateTwoBody(posTrack, negTrack)) - continue; - v0cand.cosPA = RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2]}, std::array{v0cand.P[0], v0cand.P[1], v0cand.P[2]}); - v0cand.dcaToPV = CalculateDCAStraightToPV( - v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], - v0cand.P[0], v0cand.P[1], v0cand.P[2], - collision.posX(), collision.posY(), collision.posZ()); - v0CandidateIndices(collision.globalIndex(), - posTrack.globalIndex(), - negTrack.globalIndex()); - v0CandidateCores( - v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], - v0cand.Pdaug[0], v0cand.Pdaug[1], v0cand.Pdaug[2], - v0cand.Ndaug[0], v0cand.Ndaug[1], v0cand.Ndaug[2], - v0cand.dcaDau, posTrack.dcaXY(), negTrack.dcaXY(), - v0cand.cosPA, v0cand.dcaToPV); - } - } - } - // void processFindV0CandidateWithPid(aod::Collision const& collision, aod::McParticles const& mcParticles, Alice3TracksWPid const&) - // { - // auto negativeSecondaryPionsGrouped = negativeSecondaryPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - // auto positiveSecondaryPionsGrouped = positiveSecondaryPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - // auto secondaryProtonsGrouped = secondaryProtons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - // auto secondaryAntiProtonsGrouped = secondaryAntiProtons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - // } - PROCESS_SWITCH(alice3strangenessFinder, processFindV0CandidateNoPid, "find V0 without PID", true); - // PROCESS_SWITCH(alice3strangenessFinder, processFindV0CandidateWithPid, "find V0 with PID", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; -} diff --git a/ALICE3/TableProducer/alice3-trackextension.cxx b/ALICE3/TableProducer/alice3-trackextension.cxx index 578d1979310..384810ffdeb 100644 --- a/ALICE3/TableProducer/alice3-trackextension.cxx +++ b/ALICE3/TableProducer/alice3-trackextension.cxx @@ -13,11 +13,16 @@ // Task performing basic track selection for the ALICE3. // -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/ALICE3/TableProducer/alice3-trackselection.cxx b/ALICE3/TableProducer/alice3-trackselection.cxx index 58f3a4f33ce..1a621f81df7 100644 --- a/ALICE3/TableProducer/alice3-trackselection.cxx +++ b/ALICE3/TableProducer/alice3-trackselection.cxx @@ -14,11 +14,23 @@ /// \brief Track selection for the ALICE3 studies /// -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/ALICE3/TableProducer/alice3HfSelector3Prong.cxx b/ALICE3/TableProducer/alice3HfSelector3Prong.cxx index fddd52c4d24..89c34ff1cf3 100644 --- a/ALICE3/TableProducer/alice3HfSelector3Prong.cxx +++ b/ALICE3/TableProducer/alice3HfSelector3Prong.cxx @@ -16,12 +16,9 @@ #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" #include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "ALICE3/DataModel/OTFPIDTrk.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/RICH.h" #include "ALICE3/ML/HfMlResponse3Prong.h" #include "ALICE3/Utils/utilsHfAlice3.h" #include "ALICE3/Utils/utilsSelectionsAlice3.h" @@ -36,14 +33,14 @@ #include #include #include -#include #include +#include #include -#include +#include + #include -#include #include #include @@ -82,7 +79,6 @@ struct Alice3HfSelector3Prong { Configurable> binsPt{"binsPt", std::vector{hf_cuts_3prongs_alice3::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_3prongs_alice3::Cuts[0], hf_cuts_3prongs_alice3::NBinsPt, hf_cuts_3prongs_alice3::NCutVars, hf_cuts_3prongs_alice3::labelsPt, hf_cuts_3prongs_alice3::labelsCutVar}, "Lc cand selection per pT bin"}; // QA switch - Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; @@ -110,21 +106,34 @@ struct Alice3HfSelector3Prong { void init(InitContext const&) { - if (activateQA) { - constexpr int kNBinsSelections = 1 + aod::SelectionStep::NSelectionSteps; - std::string labels[kNBinsSelections]; - labels[0] = "No selection"; - labels[1 + aod::SelectionStep::RecoSkims] = "Skims selection"; - labels[1 + aod::SelectionStep::RecoTopol] = "Skims & Topological selections"; - labels[1 + aod::SelectionStep::RecoPID] = "Skims & Topological & PID selections"; - labels[1 + aod::SelectionStep::RecoMl] = "ML selection"; - 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})"}}}); - registry.add("hSelectionsTopology", "hSelectionsTopology", {HistType::kTH1D, {{10, -0.5, 9.5, "Selection step"}}}); - for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { - registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); - } + constexpr int kNBinsSelections = 1 + aod::SelectionStep::NSelectionSteps; + std::string labels[kNBinsSelections]; + labels[0] = "No selection"; + labels[1 + aod::SelectionStep::RecoSkims] = "Skims selection"; + labels[1 + aod::SelectionStep::RecoTopol] = "Skims & Topological selections"; + labels[1 + aod::SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + labels[1 + aod::SelectionStep::RecoMl] = "ML selection"; + 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()); } + auto h = registry.add("hSelectionsTopology", "hSelectionsTopology", {HistType::kTH1D, {{11, -0.5, 10.5, "Selection step"}}}); + h->GetXaxis()->SetBinLabel(1, "All candidates"); + h->GetXaxis()->SetBinLabel(2, "pT cand"); + h->GetXaxis()->SetBinLabel(3, "pT prong cuts"); + h->GetXaxis()->SetBinLabel(4, "cos pointing angle"); + h->GetXaxis()->SetBinLabel(5, "chi2PCA"); + h->GetXaxis()->SetBinLabel(6, "decay length"); + h->GetXaxis()->SetBinLabel(7, "decay length XY"); + h->GetXaxis()->SetBinLabel(8, "norm decay length XY"); + h->GetXaxis()->SetBinLabel(9, "impPar XY"); + h->GetXaxis()->SetBinLabel(10, "prong DCA"); + h->GetXaxis()->SetBinLabel(11, "finally accepted"); + + registry.add("Tried/hChi2PCA", "Chi2PCA;Chi2PCA;entries", {HistType::kTH1F, {{100, 0., 100.}}}); + registry.add("Tried/hDecayLength", "Decay Length;Decay Length;entries", {HistType::kTH1F, {{100, 0., 200.}}}); + registry.addClone("Tried/", "Accepted/"); if (applyMl) { mlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); @@ -152,17 +161,12 @@ struct Alice3HfSelector3Prong { bool selectionTopol(const T& cand, float candPt) { int const ptBin = findBin(binsPt, candPt); - auto fillQAHistogram = [&](float bin) { - if (activateQA) { - registry.fill(HIST("hSelectionsTopology"), bin); - } - }; - fillQAHistogram(0.f); + registry.fill(HIST("hSelectionsTopology"), 0.f); // check that the cand pT is within the analysis range if (candPt < ptCandMin || candPt >= ptCandMax) { return false; } - fillQAHistogram(1.f); + registry.fill(HIST("hSelectionsTopology"), 1.f); // cut on daughter pT if (cand.ptProng0() < cuts->get(ptBin, "pT prong 0") || @@ -170,49 +174,55 @@ struct Alice3HfSelector3Prong { cand.ptProng2() < cuts->get(ptBin, "pT prong 2")) { return false; } - fillQAHistogram(2.f); + registry.fill(HIST("hSelectionsTopology"), 2.f); // cosine of pointing angle if (cand.cpa() <= cuts->get(ptBin, "cos pointing angle")) { return false; } - fillQAHistogram(3.f); + registry.fill(HIST("hSelectionsTopology"), 3.f); // cand chi2PCA + registry.fill(HIST("Tried/hChi2PCA"), cand.chi2PCA()); if (cand.chi2PCA() > cuts->get(ptBin, "Chi2PCA")) { return false; } - fillQAHistogram(4.f); + registry.fill(HIST("Accepted/hChi2PCA"), cand.chi2PCA()); + registry.fill(HIST("hSelectionsTopology"), 4.f); + // cand decay length + registry.fill(HIST("Tried/hDecayLength"), cand.decayLength()); if (cand.decayLength() <= cuts->get(ptBin, "decay length")) { return false; } - fillQAHistogram(5.f); + registry.fill(HIST("Accepted/hDecayLength"), cand.decayLength()); + registry.fill(HIST("hSelectionsTopology"), 5.f); // cand decay length XY if (cand.decayLengthXY() <= cuts->get(ptBin, "decLengthXY")) { return false; } - fillQAHistogram(6.f); + registry.fill(HIST("hSelectionsTopology"), 6.f); // cand normalized decay length XY if (cand.decayLengthXYNormalised() < cuts->get(ptBin, "normDecLXY")) { return false; } - fillQAHistogram(7.f); + registry.fill(HIST("hSelectionsTopology"), 7.f); // cand impact parameter XY if (std::abs(cand.impactParameterXY()) > cuts->get(ptBin, "impParXY")) { return false; } - fillQAHistogram(8.f); + registry.fill(HIST("hSelectionsTopology"), 8.f); // cand daughter prong DCA if (!isSelectedCandidateProngDca(cand)) { return false; } - fillQAHistogram(9.f); + registry.fill(HIST("hSelectionsTopology"), 9.f); + registry.fill(HIST("hSelectionsTopology"), 10.f); return true; } @@ -226,7 +236,7 @@ struct Alice3HfSelector3Prong { template bool selectionCandidateMass(int const ptBin, const TCandidate& cand) { - float massCand = hfHelper.getCandMass(cand); + const float massCand = hfHelper.getCandMass(cand); // cut on mass window if (std::abs(massCand - MassReference) > cuts->get(ptBin, "m")) { return false; @@ -300,23 +310,19 @@ struct Alice3HfSelector3Prong { template void runSelect3Prong(CandType const& cands) { - bool isSelMassHypo0{false}; - bool isSelMassHypo1{false}; std::vector outputMl{-1.f, -1.f, -1.f}; uint32_t pidMask = 0; // looping over 3-prong cands for (const auto& cand : cands) { - if (activateQA) { - registry.fill(HIST("hSelections"), 1, cand.pt()); - } + registry.fill(HIST("hSelections"), 1, cand.pt()); outputMl = {-1.f, -1.f, -1.f}; pidMask = 0; - auto ptCand = cand.pt(); - int const ptBin = findBin(binsPt, ptCand); + const float ptCand = cand.pt(); + const int ptBin = findBin(binsPt, ptCand); if (ptBin == -1) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } @@ -324,43 +330,37 @@ struct Alice3HfSelector3Prong { } // Here all cands pass the cut on the mass selection - bool const selMassHypo0 = selectionCandidateMass(ptBin, cand); - bool const selMassHypo1 = selectionCandidateMass(ptBin, cand); + const bool selMassHypo0 = selectionCandidateMass(ptBin, cand); + const bool selMassHypo1 = selectionCandidateMass(ptBin, cand); if (!selMassHypo0 && !selMassHypo1) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } continue; } - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoSkims, ptCand); - } + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoSkims, ptCand); // Topological selection (TODO: track quality selection) if (!selectionTopol(cand, ptCand)) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } continue; } - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoTopol, ptCand); - } + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoTopol, ptCand); // PID selection configurePidMask(cand, pidMask); if (pidMask == 0) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); if (applyMl) { candMlScores(outputMl[0], outputMl[1], outputMl[2]); } continue; } - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoPID, ptCand); - } + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoPID, ptCand); bool isSelectedMl = true; // ML selections @@ -370,13 +370,11 @@ struct Alice3HfSelector3Prong { isSelectedMl = mlResponse.isSelectedMl(inputFeaturesMassHypo0, ptCand, outputMl); candMlScores(outputMl[0], outputMl[1], outputMl[2]); if (!isSelectedMl) { - candSelFlags(isSelMassHypo0, isSelMassHypo1, pidMask); + candSelFlags(false, false, pidMask); continue; } - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoMl, ptCand); - } + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoMl, ptCand); } candSelFlags(selMassHypo0, selMassHypo1, pidMask); diff --git a/ALICE3/TableProducer/alice3HfTreeCreator3Prong.cxx b/ALICE3/TableProducer/alice3HfTreeCreator3Prong.cxx index 15bfcd8da17..7a97f1420ff 100644 --- a/ALICE3/TableProducer/alice3HfTreeCreator3Prong.cxx +++ b/ALICE3/TableProducer/alice3HfTreeCreator3Prong.cxx @@ -16,14 +16,9 @@ /// \author Marcello Di Costanzo , Turin Polytechnic University and INFN Turin #include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "ALICE3/DataModel/OTFPIDTrk.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/RICH.h" #include "ALICE3/Utils/utilsHfAlice3.h" #include "Common/Core/RecoDecay.h" -#include #include #include #include @@ -32,8 +27,9 @@ #include #include +#include #include -#include +#include using namespace o2; using namespace o2::analysis; @@ -270,6 +266,7 @@ struct Alice3HfTreeCreator3Prong { Configurable fillPid{"fillPid", false, "fill PID info"}; } fillTables; // parameters for production of training samples + Configurable fillSwapMassHypo{"fillSwapMassHypo", false, "Flag to fill derived tables with swapped mass hypothesis"}; Configurable fillOnlySignal{"fillOnlySignal", true, "Flag to fill derived tables with signal"}; Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background"}; Configurable downSampleFactor{"downSampleFactor", 1., "Fraction of cands to keep"}; @@ -475,8 +472,10 @@ struct Alice3HfTreeCreator3Prong { if (cand.isSelMassHypo0()) { fillRecoTables(cand); } - if (cand.isSelMassHypo1()) { - fillRecoTables(cand); + if (fillSwapMassHypo) { + if (cand.isSelMassHypo1()) { + fillRecoTables(cand); + } } } fillGenTables(candsGen); diff --git a/ALICE3/TableProducer/alice3MulticharmFinder.cxx b/ALICE3/TableProducer/alice3MulticharmFinder.cxx new file mode 100644 index 00000000000..fd4a7a47881 --- /dev/null +++ b/ALICE3/TableProducer/alice3MulticharmFinder.cxx @@ -0,0 +1,941 @@ +// 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 alice3MulticharmFinder.cxx +/// \brief produces table of xicc candidates +/// \author Jesper Karlsson Gumprecht + +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// 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 "ALICE3/DataModel/A3DecayFinderTables.h" +#include "ALICE3/DataModel/OTFCollision.h" +#include "ALICE3/DataModel/OTFMulticharm.h" +#include "ALICE3/DataModel/OTFStrangeness.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// simple checkers +// #define biton(var, nbit) ((var) |= (static_cast(1) << (nbit))) +// #define bitoff(var, nbit) ((var) &= ~(static_cast(1) << (nbit))) //((a) &= ~(1ULL<<(b))) +#define BIT_CHECK(var, nbit) ((var) & (static_cast(1) << (nbit))) +#define GET_HIST(type, name) std::get>(histPointers[name]) +#define INSERT_HIST(name, ...) histPointers[name] = histos.add((name).c_str(), __VA_ARGS__); + +using Alice3Tracks = soa::Join; +using Alice3Collision = soa::Join::iterator; + +struct Alice3MulticharmFinder { + SliceCache cache; + + Produces multiCharmIdx; + Produces multiCharmCore; + Produces multiCharmExtra; + + // Operation and minimisation criteria + + struct : ConfigurableGroup { + std::string prefix = "derivedTable"; // JSON group name + Configurable fillMCharmIdx{"fillMCharmIdx", true, "fill MCharmIdx[] tables (careful: memory)"}; + Configurable fillMCharmCore{"fillMCharmCore", true, "fill MCharmCores[] tables (careful: memory)"}; + Configurable fillMCharmExtra{"fillMCharmExtra", false, "fill MCharmExtra[] tables (careful: memory)"}; + } derivedTable; + + struct : ConfigurableGroup { + std::string prefix = "cfgFitter"; + Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + 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 maxDZIni{"maxDZIni", 1e9, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4, "reject (if>0) PCA candidate if tracks DXY exceeds threshold"}; + Configurable maxVtxChi2{"maxVtxChi2", 1e9, "reject (if>0) vtx. chi2 above this value"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + } cfgFitter; + + Configurable cfgMagneticField{"cfgMagneticField", 20.0f, "Magnetic field (in kilogauss) if value not found from geo provider"}; + 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> minNTracks{"minNTracks", {-1}, "Minimum number of tracks"}; + + Configurable xiMinConstDCAxy{"xiMinConstDCAxy", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable xiMinConstDCAz{"xiMinConstDCAz", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable xiMinPtDepDCAxy{"xiMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable xiMinPtDepDCAz{"xiMinPtDepDCAz", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable xiMinDecayRadius{"xiMinDecayRadius", 0.5, "Minimum R2D for XiC decay (cm)"}; + Configurable xiMassWindow{"xiMassWindow", 0.005, "Mass window around Xi peak (GeV/c)"}; + + Configurable picMinConstDCAxy{"picMinConstDCAxy", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable picMinConstDCAz{"picMinConstDCAz", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable picMinPtDepDCAxy{"picMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable picMinPtDepDCAz{"picMinPtDepDCAz", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable picMinPt{"picMinPt", 0.15, "Minimum pT for XiC pions"}; + + Configurable xicMaxDauDCA{"xicMaxDauDCA", 0.005f, "DCA between XiC daughters (cm)"}; + Configurable xicMaxDCAxy{"xicMaxDCAxy", 0.0005f, "maxDCA"}; + Configurable xicMaxDCAz{"xicMaxDCAz", 0.0005f, "maxDCA"}; + Configurable xicMinDecayRadius{"xicMinDecayRadius", -1, "Minimum R2D for XiC decay (cm)"}; + Configurable xicMinDecayDistanceFromPV{"xicMinDecayDistanceFromPV", -1, "Minimum distance for XiC decay from PV (cm)"}; + Configurable xicMinProperLength{"xicMinProperLength", 0.002, "Minimum proper length for XiC decay (cm)"}; + Configurable xicMaxProperLength{"xicMaxProperLength", 0.1, "Minimum proper length for XiC decay (cm)"}; + Configurable xicMassWindow{"xicMassWindow", 0.012, "Mass window around XiC peak (GeV/c)"}; + + Configurable piccMinConstDCAxy{"piccMinConstDCAxy", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable piccMinConstDCAz{"piccMinConstDCAz", 0.0005f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable piccMinPtDepDCAxy{"piccMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable piccMinPtDepDCAz{"piccMinPtDepDCAz", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable piccMinPt{"piccMinPt", 0.3, "Minimum pT for XiCC pions"}; + + Configurable xiccMaxDauDCA{"xiccMaxDauDCA", 0.005f, "DCA between XiCC daughters (cm)"}; + Configurable xiccMaxDCAxy{"xiccMaxDCAxy", 0.005f, "maxDCA"}; + Configurable xiccMaxDCAz{"xiccMaxDCAz", 0.005f, "maxDCA"}; + Configurable xiccMaxEta{"xiccMaxEta", 1.5, "Max eta"}; + Configurable xiccMinDecayRadius{"xiccMinDecayRadius", -1, "Minimum R2D for XiCC decay (cm)"}; + Configurable xiccMinProperLength{"xiccMinProperLength", -1, "Minimum proper length for XiCC decay (cm)"}; + Configurable xiccMaxProperLength{"xiccMaxProperLength", 999, "Minimum proper length for XiCC decay (cm)"}; + Configurable xiccMassWindow{"xiccMassWindow", 0.25, "Mass window around XiCC peak (GeV/c). Make sure that bkg region is included in this window"}; + + 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 axisDCA2D{"axisDCA2D", {400, -200, 200}, "DCA2d (#mum)"}; + ConfigurableAxis axisDCA{"axisDCA", {400, 0, 400}, "DCA (#mum)"}; + ConfigurableAxis axisRadius{"axisRadius", {10000, 0, 10000}, "Decay radius (#mum)"}; + ConfigurableAxis axisRadius2D{"axisRadius2D", {1000, 0, 100000}, "Decay radius (#mum)"}; + ConfigurableAxis axisRadius2DXi{"axisRadius2DXi", {1000, 0, 20}, "Decay radius (cm)"}; + ConfigurableAxis axisDecayLength{"axisDecayLength", {2000, 0, 2000}, "Decay lenght (#mum)"}; + ConfigurableAxis axisTOFTrack{"axisTOFTrack", {1000, 0, 5000}, "TOF track time"}; + + 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 (mum)"}; + ConfigurableAxis axisDCAXiCCDaughters{"axisDCAXiCCDaughters", {200, 0, 100}, "DCA (mum)"}; + + 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}; + std::map histPointers; + std::vector savedConfigs; + + // Constants + static constexpr std::array MomentumIndices = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + static constexpr float ToMicrons = 1e+4; + + // filter expressions for pions + static constexpr uint32_t TrackSelectionPic = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiC; + static constexpr uint32_t TrackSelectionPicc = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiFromXiCC; + + // partitions + Partition trueXi = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); + Partition trueXiC = aod::mcparticle::pdgCode == static_cast(o2::constants::physics::kXiCPlus); + Partition trueXiCC = aod::mcparticle::pdgCode == static_cast(o2::constants::physics::kXiCCPlusPlus); + + Partition picTracks = + ((aod::a3DecayMap::decayMap & TrackSelectionPic) == TrackSelectionPic) && aod::track::signed1Pt > 0.0f && 1.0f / nabs(aod::track::signed1Pt) > picMinPt&& nabs(aod::track::dcaXY) > picMinConstDCAxy + picMinPtDepDCAxy* nabs(aod::track::signed1Pt) && nabs(aod::track::dcaZ) > picMinConstDCAz + picMinPtDepDCAz* nabs(aod::track::signed1Pt); + + Partition piccTracks = + ((aod::a3DecayMap::decayMap & TrackSelectionPicc) == TrackSelectionPicc) && aod::track::signed1Pt > 0.0f && 1.0f / nabs(aod::track::signed1Pt) > piccMinPt&& nabs(aod::track::dcaXY) > piccMinConstDCAxy + piccMinPtDepDCAxy* nabs(aod::track::signed1Pt) && nabs(aod::track::dcaZ) > piccMinConstDCAz + piccMinPtDepDCAz* 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; + + // charm daughters + int nSiliconHitsPiCC; + int nTPCHitsPiCC; + } thisXiccCandidate; + + struct ProngInfo { + float pt = 1e+10; + float eta = 1e+10; + float dcaXY = 1e+10; + float dcaZ = 1e+10; + }; + + 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; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); + if (nCand == 0) { + return false; + } + + fitter.propagateTracksToVertex(); + if (!fitter.isPropagateTracksToVertexDone()) { + 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 (size_t i = 0; i < thisXiccCandidate.xyz.size(); i++) { + thisXiccCandidate.xyz[i] = vtx[i]; + } + + // compute cov mat + for (int ii = 0; ii < o2::track::kLabCovMatSize; ii++) { + thisXiccCandidate.parentTrackCovMatrix[ii] = 0.0f; + } + + std::array covA = {0}; + std::array covB = {0}; + fitter.getTrack(0).getCovXYZPxPyPzGlo(covA); + fitter.getTrack(1).getCovXYZPxPyPzGlo(covB); + + for (size_t i = 0; i < MomentumIndices.size(); i++) { + int j = MomentumIndices[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 = std::sqrt(fitter.getChi2AtPCACandidate()); + if (thisXiccCandidate.dca > xiccMaxDauDCA) { + return false; + } + + thisXiccCandidate.mass = RecoDecay::m(std::array{std::array{thisXiccCandidate.prong0mom[0], thisXiccCandidate.prong0mom[1], thisXiccCandidate.prong0mom[2]}, std::array{thisXiccCandidate.prong1mom[0], thisXiccCandidate.prong1mom[1], thisXiccCandidate.prong1mom[2]}}, std::array{mass0, mass1}); + + if (std::fabs(thisXiccCandidate.mass - o2::constants::physics::MassXiCCPlusPlus) > xiccMassWindow) { + return false; + } + + thisXiccCandidate.pt = std::hypot(thisXiccCandidate.prong0mom[0] + thisXiccCandidate.prong1mom[0], thisXiccCandidate.prong0mom[1] + thisXiccCandidate.prong1mom[1]); + thisXiccCandidate.eta = RecoDecay::eta(std::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; + } + + const u_int8_t fitter3StatusCode = fitter3.getFitStatus(); + histos.fill(HIST("hFitter3StatusCode"), fitter3StatusCode); + if (nCand == 0) { + return false; + } + + fitter3.propagateTracksToVertex(); + if (!fitter3.isPropagateTracksToVertexDone()) { + 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 (size_t i = 0; i < thisXicCandidate.xyz.size(); i++) { + thisXicCandidate.xyz[i] = vtx[i]; + } + + // compute cov mat + for (int ii = 0; ii < o2::track::kLabCovMatSize; 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); + + for (size_t i = 0; i < MomentumIndices.size(); i++) { + int j = MomentumIndices[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 = std::sqrt(fitter3.getChi2AtPCACandidate()); + if (thisXicCandidate.dca > xicMaxDauDCA) { + return false; + } + thisXicCandidate.mass = RecoDecay::m(std::array{std::array{thisXicCandidate.prong0mom[0], thisXicCandidate.prong0mom[1], thisXicCandidate.prong0mom[2]}, std::array{thisXicCandidate.prong1mom[0], thisXicCandidate.prong1mom[1], thisXicCandidate.prong1mom[2]}, std::array{thisXicCandidate.prong2mom[0], thisXicCandidate.prong2mom[1], thisXicCandidate.prong2mom[2]}}, std::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(std::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 (const auto& mcParticleMother1 : mcParticle1.template mothers_as()) { + for (const 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 (const auto& mcParticleMother1 : mcParticle1.template mothers_as()) { + if (mcParticleMother1.has_mothers()) { + for (const auto& mcParticleGrandMother1 : mcParticleMother1.template mothers_as()) { + for (const auto& mcParticleMother2 : mcParticle2.template mothers_as()) { + if (mcParticleGrandMother1.globalIndex() == mcParticleMother2.globalIndex()) { + returnValue = true; + } + } + } + } + } + } + } // end association check + return returnValue; + } + + void init(o2::framework::InitContext&) + { + // initialize O2 2-prong fitter (only once) + fitter.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter.setMaxR(cfgFitter.maxR); + fitter.setMinParamChange(cfgFitter.minParamChange); + fitter.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter.setMaxDZIni(cfgFitter.maxDZIni); + fitter.setMaxDXYIni(cfgFitter.maxDXYIni); + fitter.setMaxChi2(cfgFitter.maxVtxChi2); + fitter.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter.setWeightedFinalPCA(cfgFitter.useWeightedFinalPCA); + fitter.setBz(cfgMagneticField); + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + fitter3.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter3.setMaxR(cfgFitter.maxR); + fitter3.setMinParamChange(cfgFitter.minParamChange); + fitter3.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter3.setMaxDZIni(cfgFitter.maxDZIni); + fitter3.setMaxDZIni(cfgFitter.maxDXYIni); + fitter3.setMaxChi2(cfgFitter.maxVtxChi2); + fitter3.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter3.setWeightedFinalPCA(cfgFitter.useWeightedFinalPCA); + fitter3.setBz(cfgMagneticField); + fitter3.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitterStatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitterStatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitterStatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitterStatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitterStatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitterStatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitterStatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitterStatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitterStatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitterStatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitterStatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + + auto hFitter3StatusCode = histos.add("hFitter3StatusCode", "hFitter3StatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitter3StatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitter3StatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitter3StatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitter3StatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitter3StatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitter3StatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitter3StatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitter3StatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitter3StatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitter3StatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitter3StatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + + INSERT_HIST(std::string("h2dGenXi"), "h2dGenXi", {kTH2D, {{axisPt, axisEta}}}); + INSERT_HIST(std::string("h2dGenXiC"), "h2dGenXiC", {kTH2D, {{axisPt, axisEta}}}); + INSERT_HIST(std::string("h2dGenXiCC"), "h2dGenXiCC", {kTH2D, {{axisPt, axisEta}}}); + } + + void initDetectorConfiguration(const int icfg) + { + if (std::find(savedConfigs.begin(), savedConfigs.end(), icfg) != savedConfigs.end()) { + return; + } + + savedConfigs.push_back(icfg); + const std::string histPath = "Configuration_" + std::to_string(icfg) + "/"; + + // 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 + INSERT_HIST(histPath + "hCharmBuilding", "hCharmBuilding", {kTH1D, {{10, -0.5, 9.5f}}}); + INSERT_HIST(histPath + "hMultiCharmBuilding", "hMultiCharmBuilding", {kTH1D, {{10, -0.5, 9.5f}}}); + + INSERT_HIST(histPath + "hMassXi", "hMassXi", {kTH1D, {{axisXiMass}}}); + INSERT_HIST(histPath + "hMassXiC", "hMassXiC", {kTH1D, {{axisXiCMass}}}); + + INSERT_HIST(histPath + "hEtaXiCC", "hEtaXiCC", {kTH1D, {{axisEta}}}); + INSERT_HIST(histPath + "hPtXiCC", "hPtXiCC", {kTH1D, {{axisPt}}}); + INSERT_HIST(histPath + "h3dMassXiCC", "h3dMassXiCC", {kTH3D, {{axisPt, axisEta, axisXiCCMass}}}); + + INSERT_HIST(histPath + "hDCAXiCDaughters", "hDCAXiCDaughters", {kTH1D, {{axisDCAXiCDaughters}}}); + INSERT_HIST(histPath + "hDCAXiCCDaughters", "hDCAXiCCDaughters", {kTH1D, {{axisDCAXiCCDaughters}}}); + INSERT_HIST(histPath + "hDCAxyXi", "hDCAxyXi", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hDCAzXi", "hDCAzXi", {kTH1D, {{axisDCA}}}); + + INSERT_HIST(histPath + "hDCAxyXiC", "hDCAxyXiC", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hDCAzXiC", "hDCAzXiC", {kTH1D, {{axisDCA}}}); + + INSERT_HIST(histPath + "hDCAxyXiCC", "hDCAxyXiCC", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hDCAzXiCC", "hDCAzXiCC", {kTH1D, {{axisDCA}}}); + + INSERT_HIST(histPath + "hPi1cPt", "hPi1cPt", {kTH1D, {{axisPt}}}); + INSERT_HIST(histPath + "hPi2cPt", "hPi2cPt", {kTH1D, {{axisPt}}}); + INSERT_HIST(histPath + "hPiccPt", "hPiccPt", {kTH1D, {{axisPt}}}); + + INSERT_HIST(histPath + "hPi1cDCAxy", "hPi1cDCAxy", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hPi1cDCAz", "hPi1cDCAz", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hPi2cDCAxy", "hPi2cDCAxy", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hPi2cDCAz", "hPi2cDCAz", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hPiccDCAxy", "hPiccDCAxy", {kTH1D, {{axisDCA}}}); + INSERT_HIST(histPath + "hPiccDCAz", "hPiccDCAz", {kTH1D, {{axisDCA}}}); + + INSERT_HIST(histPath + "hMinXiDecayRadius", "hMinXiDecayRadius", {kTH1D, {{axisRadius2DXi}}}); + INSERT_HIST(histPath + "hMinXiCDecayRadius", "hMinXiCDecayRadius", {kTH1D, {{axisRadius}}}); + INSERT_HIST(histPath + "hMinXiCCDecayRadius", "hMinXiCCDecayRadius", {kTH1D, {{axisRadius}}}); + + INSERT_HIST(histPath + "hMinXicDecayDistanceFromPV", "hMinXicDecayDistanceFromPV", {kTH1D, {{axisDecayLength}}}); + INSERT_HIST(histPath + "hProperLengthXiC", "hProperLengthXiC", {kTH1D, {{axisDecayLength}}}); + INSERT_HIST(histPath + "hProperLengthXiCC", "hProperLengthXiCC", {kTH1D, {{axisDecayLength}}}); + + INSERT_HIST(histPath + "hInnerTOFTrackTimeRecoPi1c", "hInnerTOFTrackTimeRecoPi1c", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hInnerTOFTrackTimeRecoPi2c", "hInnerTOFTrackTimeRecoPi2c", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hInnerTOFTrackTimeRecoPicc", "hInnerTOFTrackTimeRecoPicc", {kTH1D, {{axisTOFTrack}}}); + + INSERT_HIST(histPath + "hOuterTOFTrackTimeRecoPi1c", "hOuterTOFTrackTimeRecoPi1c", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hOuterTOFTrackTimeRecoPi2c", "hOuterTOFTrackTimeRecoPi2c", {kTH1D, {{axisTOFTrack}}}); + INSERT_HIST(histPath + "hOuterTOFTrackTimeRecoPicc", "hOuterTOFTrackTimeRecoPicc", {kTH1D, {{axisTOFTrack}}}); + + INSERT_HIST(histPath + "hXiRadiusVsXicRadius", "hXiRadiusVsXicRadius", {kTH2D, {{axisRadius2D, axisRadius2D}}}); + INSERT_HIST(histPath + "hXicRadiusVsXiccRadius", "hXicRadiusVsXiccRadius", {kTH2D, {{axisRadius2D, axisRadius2D}}}); + + INSERT_HIST(histPath + "hMassXiCC", "hMassXiCC", {kTH1D, {{axisXiCCMass}}}); + INSERT_HIST(histPath + "hNCollisions", "hNCollisions", {kTH1D, {{2, 0.5, 2.5}}}); + INSERT_HIST(histPath + "hNTracks", "hNTracks", {kTH1D, {{20000, 0, 20000}}}); + + // These histograms bookkeep the exact number of combinations attempted + // CombinationsXiC: triplets Xi-pi-pi considered per Xi + // CombinationsXiCC: doublets XiC-pi considered per XiC + INSERT_HIST(histPath + "hCombinationsXiC", "hCombinationsXiC", {kTH1D, {{axisNConsidered}}}); + INSERT_HIST(histPath + "hCombinationsXiCC", "hCombinationsXiCC", {kTH1D, {{axisNConsidered}}}); + + if (doDCAplots) { + INSERT_HIST(histPath + "h2dDCAxyVsPtXiFromXiC", "h2dDCAxyVsPtXiFromXiC", {kTH2D, {{axisPt, axisDCA2D}}}); + INSERT_HIST(histPath + "h2dDCAxyVsPtPiFromXiC", "h2dDCAxyVsPtPiFromXiC", {kTH2D, {{axisPt, axisDCA2D}}}); + INSERT_HIST(histPath + "h2dDCAxyVsPtPiFromXiCC", "h2dDCAxyVsPtPiFromXiCC", {kTH2D, {{axisPt, axisDCA2D}}}); + + INSERT_HIST(histPath + "h2dDCAzVsPtXiFromXiC", "h2dDCAzVsPtXiFromXiC", {kTH2D, {{axisPt, axisDCA2D}}}); + INSERT_HIST(histPath + "h2dDCAzVsPtPiFromXiC", "h2dDCAzVsPtPiFromXiC", {kTH2D, {{axisPt, axisDCA2D}}}); + INSERT_HIST(histPath + "h2dDCAzVsPtPiFromXiCC", "h2dDCAzVsPtPiFromXiCC", {kTH2D, {{axisPt, axisDCA2D}}}); + } + } + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processGenerated(aod::McParticles const&) + { + for (auto const& mcParticle : trueXi) { + GET_HIST(TH2, "h2dGenXi")->Fill(mcParticle.pt(), mcParticle.eta()); + } + for (auto const& mcParticle : trueXiC) { + GET_HIST(TH2, "h2dGenXiC")->Fill(mcParticle.pt(), mcParticle.eta()); + } + for (auto const& mcParticle : trueXiCC) { + GET_HIST(TH2, "h2dGenXiCC")->Fill(mcParticle.pt(), mcParticle.eta()); + } + } + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFindXicc(Alice3Collision const& collision, Alice3Tracks const& tracks, aod::McParticles const&, aod::UpgradeCascades const& cascades) + { + const std::string histPath = "Configuration_" + std::to_string(collision.lutConfigId()) + "/"; + initDetectorConfiguration(collision.lutConfigId()); + + GET_HIST(TH1, histPath + "hNCollisions")->Fill(1); + GET_HIST(TH1, histPath + "hNTracks")->Fill(tracks.size()); + if (tracks.size() < minNTracks.value[collision.lutConfigId()]) { + return; + } + + GET_HIST(TH1, histPath + "hNCollisions")->Fill(2); + // group with this collision + // n.b. cascades do not need to be grouped, being used directly in iterator-grouping + auto picTracksGrouped = picTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto piccTracksGrouped = piccTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + for (auto const& track : tracks) { + if (BIT_CHECK(track.decayMap(), kTruePiFromXiC)) { + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiC")->Fill(track.pt(), track.dcaXY() * ToMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiC")->Fill(track.pt(), track.dcaZ() * ToMicrons); + } + if (BIT_CHECK(track.decayMap(), kTruePiFromXiCC)) { + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiCC")->Fill(track.pt(), track.dcaXY() * ToMicrons); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtPiFromXiCC")->Fill(track.pt(), track.dcaZ() * ToMicrons); + } + } + + for (auto const& xiCand : cascades) { + auto xi = xiCand.cascadeTrack_as(); // de-reference cascade track + GET_HIST(TH1, histPath + "hMassXi")->Fill(xiCand.mXi()); + GET_HIST(TH2, histPath + "h2dDCAxyVsPtXiFromXiC")->Fill(xi.pt(), xi.dcaXY() * ToMicrons); + GET_HIST(TH2, histPath + "h2dDCAzVsPtXiFromXiC")->Fill(xi.pt(), xi.dcaZ() * ToMicrons); + + if (std::fabs(xiCand.mXi() - o2::constants::physics::MassXiMinus) > xiMassWindow) { + continue; // out of mass region + } + + uint32_t nCombinationsC = 0; + if (!BIT_CHECK(xi.decayMap(), kTrueXiFromXiC)) { + continue; + } + + if (std::fabs(xi.dcaXY()) < xiMinConstDCAxy || std::fabs(xi.dcaZ()) < xiMinConstDCAz) { + continue; // likely a primary xi + } + + GET_HIST(TH1, histPath + "hDCAxyXi")->Fill(xi.dcaXY() * ToMicrons); + GET_HIST(TH1, histPath + "hDCAzXi")->Fill(xi.dcaZ() * ToMicrons); + if (xiCand.cascRadius() < xiMinDecayRadius) { + continue; + } + + GET_HIST(TH1, histPath + "hMinXiDecayRadius")->Fill(xiCand.cascRadius()); + for (auto const& pi1c : picTracksGrouped) { + 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() < picMinPt) { + continue; // too low momentum + } + + GET_HIST(TH1, histPath + "hPi1cPt")->Fill(pi1c.pt()); + // second pion from XiC decay for starts here + for (auto const& pi2c : picTracksGrouped) { + 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() < picMinPt) { + continue; // too low momentum + } + + GET_HIST(TH1, histPath + "hPi2cPt")->Fill(pi2c.pt()); + // 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++; + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(0.0f); + + if (!buildDecayCandidateThreeBody(xi, pi1c, pi2c, o2::constants::physics::MassXiMinus, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged)) { + continue; // failed at building candidate + } + + GET_HIST(TH1, histPath + "hDCAXiCDaughters")->Fill(thisXicCandidate.dca * ToMicrons); + if (std::fabs(thisXicCandidate.mass - o2::constants::physics::MassXiCPlus) > xicMassWindow) { + continue; // out of mass region + } + + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(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); + float xicDecayRadius2D = std::hypot(thisXicCandidate.xyz[0], thisXicCandidate.xyz[1]); + if (xicDecayRadius2D < xiccMinDecayRadius) { + continue; // do not take if radius too small, likely a primary combination + } + + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(2.0f); + GET_HIST(TH1, histPath + "hMinXiCDecayRadius")->Fill(xicDecayRadius2D * ToMicrons); + if (xicDecayRadius2D > xiCand.cascRadius()) { + continue; + } + + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(3.0f); + GET_HIST(TH2, histPath + "hXiRadiusVsXicRadius")->Fill(xiCand.cascRadius() * ToMicrons, xicDecayRadius2D * ToMicrons); + 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, cfgMagneticField, &dcaInfo)) { + xicdcaXY = dcaInfo.getY(); + xicdcaZ = dcaInfo.getZ(); + } + + if (std::fabs(xicdcaXY) < xicMaxDCAxy || std::fabs(xicdcaZ) < xicMaxDCAz) { + continue; // likely a primary xic + } + + GET_HIST(TH1, histPath + "hCharmBuilding")->Fill(4.0f); + GET_HIST(TH1, histPath + "hDCAxyXiC")->Fill(std::fabs(xicdcaXY * ToMicrons)); + GET_HIST(TH1, histPath + "hDCAzXiC")->Fill(std::fabs(xicdcaZ * ToMicrons)); + GET_HIST(TH1, histPath + "hMassXiC")->Fill(thisXicCandidate.mass); + + // attempt XiCC finding + uint32_t nCombinationsCC = 0; + for (auto const& picc : piccTracksGrouped) { + if (mcSameMotherCheck && !checkSameMotherExtra(xi, picc)) { + continue; + } + + 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() < piccMinPt) { + continue; // too low momentum + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(0.0f); + GET_HIST(TH1, histPath + "hPiccPt")->Fill(picc.pt()); + o2::track::TrackParCov piccTrack = getTrackParCov(picc); + nCombinationsCC++; + if (!buildDecayCandidateTwoBody(xicTrack, piccTrack, o2::constants::physics::MassXiCPlus, o2::constants::physics::MassPionCharged)) { + continue; // failed at building candidate + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(1.0f); + GET_HIST(TH1, histPath + "hDCAXiCCDaughters")->Fill(thisXiccCandidate.dca * ToMicrons); + 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 xiccDecayRadius2D = std::hypot(thisXiccCandidate.xyz[0], thisXiccCandidate.xyz[1]); + if (xiccDecayRadius2D < xiccMinDecayRadius) { + continue; // do not take if radius too small, likely a primary combination + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(2.0f); + GET_HIST(TH1, histPath + "hDCAXiCCDaughters")->Fill(thisXiccCandidate.dca * ToMicrons); + float totalMomentumC = std::hypot(momentumC[0], momentumC[1], momentumC[2]); + float decayLengthXiC = std::hypot( + thisXicCandidate.xyz[0] - thisXiccCandidate.xyz[0], + thisXicCandidate.xyz[1] - thisXiccCandidate.xyz[1], + thisXicCandidate.xyz[2] - thisXiccCandidate.xyz[2]); + float xicProperLength = decayLengthXiC * thisXicCandidate.mass / totalMomentumC; + + if (xicProperLength < xicMinProperLength || xicProperLength > xicMaxProperLength) { + continue; // likely background + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(3.0f); + GET_HIST(TH1, histPath + "hProperLengthXiC")->Fill(xicProperLength * ToMicrons); + float xicDistanceFromPV = std::hypot( + thisXicCandidate.xyz[0] - collision.posX(), + thisXicCandidate.xyz[1] - collision.posY(), + thisXicCandidate.xyz[2] - collision.posZ()); + float xicDecayDistanceFromPV = xicDistanceFromPV * thisXicCandidate.mass / totalMomentumC; + if (xicDecayDistanceFromPV < xicMinDecayDistanceFromPV) { + continue; // too close to PV + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(4.0f); + GET_HIST(TH1, histPath + "hMinXicDecayDistanceFromPV")->Fill(xicDecayDistanceFromPV * ToMicrons); + float totalMomentumCC = std::hypot(momentumCC[0], momentumCC[1], momentumCC[2]); + float decayLengthXiCC = std::hypot( + thisXiccCandidate.xyz[0] - collision.posX(), + thisXiccCandidate.xyz[1] - collision.posY(), + thisXiccCandidate.xyz[2] - collision.posZ()); + float xiccProperLength = decayLengthXiCC * thisXiccCandidate.mass / totalMomentumCC; + if (xiccProperLength < xiccMinProperLength || xiccProperLength > xicMaxProperLength) { + continue; // likely background + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(5.0f); + GET_HIST(TH1, histPath + "hProperLengthXiCC")->Fill(xiccProperLength * ToMicrons); + if (xiccDecayRadius2D > xicDecayRadius2D) { + continue; // XiCC should decay before XiC + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(6.0f); + GET_HIST(TH2, histPath + "hXicRadiusVsXiccRadius")->Fill(xicDecayRadius2D * ToMicrons, xiccDecayRadius2D * ToMicrons); + float xiccdcaXY = 1e+10, xiccdcaZ = 1e+10; + if (xiccTrack.propagateToDCA(primaryVertex, cfgMagneticField, &dcaInfo)) { + xiccdcaXY = dcaInfo.getY(); + xiccdcaZ = dcaInfo.getZ(); + } + + if (std::fabs(xiccdcaXY) > xiccMaxDCAxy || std::fabs(xiccdcaZ) > xiccMaxDCAz) { + continue; // not pointing to PV + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(7.0f); + GET_HIST(TH1, histPath + "hDCAxyXiCC")->Fill(xiccdcaXY * ToMicrons); + GET_HIST(TH1, histPath + "hDCAzXiCC")->Fill(xiccdcaZ * ToMicrons); + if (std::fabs(thisXiccCandidate.eta) > xiccMaxEta) { + continue; // not in central barrel + } + + GET_HIST(TH1, histPath + "hMultiCharmBuilding")->Fill(8.0f); + GET_HIST(TH1, histPath + "hMassXiCC")->Fill(thisXiccCandidate.mass); + GET_HIST(TH1, histPath + "hPtXiCC")->Fill(thisXiccCandidate.pt); + GET_HIST(TH1, histPath + "hEtaXiCC")->Fill(thisXiccCandidate.eta); + GET_HIST(TH3, histPath + "h3dMassXiCC")->Fill(thisXiccCandidate.pt, thisXiccCandidate.eta, thisXiccCandidate.mass); + + GET_HIST(TH1, histPath + "hPi1cDCAxy")->Fill(std::abs(pi1c.dcaXY() * ToMicrons)); + GET_HIST(TH1, histPath + "hPi1cDCAz")->Fill(std::abs(pi1c.dcaZ() * ToMicrons)); + GET_HIST(TH1, histPath + "hPi2cDCAxy")->Fill(std::abs(pi2c.dcaXY() * ToMicrons)); + GET_HIST(TH1, histPath + "hPi2cDCAz")->Fill(std::abs(pi2c.dcaZ() * ToMicrons)); + GET_HIST(TH1, histPath + "hPiccDCAxy")->Fill(std::abs(picc.dcaXY() * ToMicrons)); + GET_HIST(TH1, histPath + "hPiccDCAz")->Fill(std::abs(picc.dcaZ() * ToMicrons)); + + // produce multi-charm table for posterior analysis + if (derivedTable.fillMCharmIdx) { + multiCharmIdx( + xiCand.globalIndex(), + pi1c.globalIndex(), pi2c.globalIndex(), + picc.globalIndex()); + } + + if (derivedTable.fillMCharmCore) { + multiCharmCore( + thisXiccCandidate.mass, thisXiccCandidate.pt, + thisXiccCandidate.eta, thisXiccCandidate.dca, + thisXicCandidate.mass, thisXicCandidate.pt, + thisXicCandidate.eta, thisXicCandidate.dca, + xi.dcaXY(), xi.dcaZ(), + xicdcaXY, xicdcaZ, + xiccdcaXY, xiccdcaZ, + pi1c.dcaXY(), pi1c.dcaZ(), + pi2c.dcaXY(), pi2c.dcaZ(), + picc.dcaXY(), picc.dcaZ(), + xicDecayRadius2D, xiccDecayRadius2D, + xicProperLength, + xicDecayDistanceFromPV, + xiccProperLength, + pi1c.pt(), pi2c.pt(), picc.pt(), + collision.lutConfigId()); + } + + if (derivedTable.fillMCharmExtra) { + ProngInfo bachelor, positive, negative; + if (xiCand.has_bachTrack()) { + auto bach = xiCand.bachTrack_as(); // de-reference bach track + bachelor.pt = bach.pt(); + bachelor.eta = bach.eta(); + bachelor.dcaXY = bach.dcaXY(); + bachelor.dcaZ = bach.dcaZ(); + } + + if (xiCand.has_negTrack()) { + auto neg = xiCand.negTrack_as(); // de-reference neg track + negative.pt = neg.pt(); + negative.eta = neg.eta(); + negative.dcaXY = neg.dcaXY(); + negative.dcaZ = neg.dcaZ(); + } + + if (xiCand.has_posTrack()) { + auto pos = xiCand.posTrack_as(); // de-reference pos track + positive.pt = pos.pt(); + positive.eta = pos.eta(); + positive.dcaXY = pos.dcaXY(); + positive.dcaZ = pos.dcaZ(); + } + + multiCharmExtra( + bachelor.pt, bachelor.eta, + bachelor.dcaXY, bachelor.dcaZ, + positive.pt, positive.eta, + positive.dcaXY, positive.dcaZ, + negative.pt, negative.eta, + negative.dcaXY, negative.dcaZ, + pi1c.eta(), pi2c.eta(), picc.eta()); + } + } + GET_HIST(TH1, histPath + "hCombinationsXiCC")->Fill(nCombinationsCC); + } + } + GET_HIST(TH1, histPath + "hCombinationsXiC")->Fill(nCombinationsC); + } + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* + PROCESS_SWITCH(Alice3MulticharmFinder, processGenerated, "fill MC-only histograms", true); + PROCESS_SWITCH(Alice3MulticharmFinder, processFindXicc, "find XiCC baryons", true); + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/alice3TrackingTranslator.cxx b/ALICE3/TableProducer/alice3TrackingTranslator.cxx index 94e5f0ef5d1..c68cb2adbe3 100644 --- a/ALICE3/TableProducer/alice3TrackingTranslator.cxx +++ b/ALICE3/TableProducer/alice3TrackingTranslator.cxx @@ -16,6 +16,7 @@ /// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT) /// +#include "ALICE3/DataModel/OTFCollision.h" #include "ALICE3/DataModel/collisionAlice3.h" #include "ALICE3/DataModel/tracksAlice3.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -23,29 +24,33 @@ #include #include #include +#include +#include #include -#include +#include #include #include -#include +#include #include #include +#include #include #include #include #include +#include + +#include +#include #include +#include +#include #include #include #include -#ifdef __CLING__ -#pragma link C++ class std::vector < std::vector < unsigned int>> + ; -#pragma link C++ class std::vector < std::vector < std::uint32_t>> + ; -#endif - TString inputPath; struct Alice3TrackingTranslator { @@ -60,26 +65,31 @@ struct Alice3TrackingTranslator { o2::framework::Produces tableTracksDCACov; o2::framework::Produces tableCollisionsAlice3; o2::framework::Produces tableTracksAlice3; + o2::framework::Produces tableTracksAlice3Pdg; o2::framework::Produces tableTracksExtraA3; + o2::framework::Produces tableMCParticlesExtraA3; o2::framework::Produces tableStoredTracksExtra; o2::framework::Produces tableTrackSelection; o2::framework::Produces tableTrackSelectionExtension; o2::framework::Produces tableStoredMcParticles; o2::framework::Produces tableMcCollisions; + o2::framework::Produces tableOTFLUTConfigId; + + o2::framework::Configurable maxCollisions{"maxCollisions", -1000, "Maximum number of collisions translated"}; + o2::framework::Configurable addDaughterInfo{"addDaughterInfo", false, "Add daughter particle information to the MC truth output tables"}; void init(o2::framework::InitContext&) { // Initialization if needed LOG(info) << "Alice3TrackingTranslator init called"; - // Load dictionary for nested vector - gInterpreter->GenerateDictionary("vector>", "vector"); } #define SETADDRESS(branchname, branchvar) \ if (mTree->SetBranchAddress(branchname, &branchvar)) { \ LOG(fatal) << "Could not set branch address for " << branchname; \ } + struct FileStruct { FileStruct(std::string filename, std::string treename) : mFile(filename.c_str(), "READ") { @@ -118,6 +128,12 @@ struct Alice3TrackingTranslator { SETADDRESS("pz", m_pz); SETADDRESS("m", m_m); SETADDRESS("p", m_p); + SETADDRESS("q", m_q); + SETADDRESS("number_of_hits", m_number_of_hits); + SETADDRESS("particle_id", m_particleId); + if (mTree->GetBranchStatus("mother_particle_id")) { + SETADDRESS("mother_particle_id", m_motherId); + } } std::vector* m_particle_type = nullptr; std::vector* m_vx = nullptr; @@ -129,6 +145,10 @@ struct Alice3TrackingTranslator { std::vector* m_pz = nullptr; std::vector* m_m = nullptr; std::vector* m_p = nullptr; + std::vector* m_number_of_hits = nullptr; + std::vector* m_particleId = nullptr; + std::vector* m_q = nullptr; + std::vector* m_motherId = nullptr; }; struct TrackStruct : public FileStruct { @@ -150,8 +170,8 @@ struct Alice3TrackingTranslator { SETADDRESS("eQOP_fit", m_eQOP_fit); SETADDRESS("eT_fit", m_eT_fit); SETADDRESS("nMajorityHits", m_nMajorityHits); - // SETADDRESS("majorityParticleId", m_majorityParticleId); - mTree->SetBranchAddress("majorityParticleId", &m_majorityParticleId); + SETADDRESS("majorityParticleId", m_majorityParticleId); + // mTree->SetBranchAddress("majorityParticleId", &m_majorityParticleId); SETADDRESS("t_charge", m_t_charge); SETADDRESS("t_vx", m_t_vx); SETADDRESS("t_vy", m_t_vy); @@ -182,20 +202,20 @@ struct Alice3TrackingTranslator { std::vector* m_eT_fit = nullptr; // time // The majority truth particle info - std::vector* m_nMajorityHits = nullptr; /// The number of hits from majority particle - std::vector>* m_majorityParticleId = nullptr; /// The particle Id of the majority particle - std::vector* m_t_charge = nullptr; /// Charge of majority particle - std::vector* m_t_time = nullptr; /// Time of majority particle - std::vector* m_t_vx = nullptr; /// Vertex x positions of majority particle - std::vector* m_t_vy = nullptr; /// Vertex y positions of majority particle - std::vector* m_t_vz = nullptr; /// Vertex z positions of majority particle - std::vector* m_t_px = nullptr; /// Initial momenta m_px of majority particle - std::vector* m_t_py = nullptr; /// Initial momenta m_py of majority particle - std::vector* m_t_pz = nullptr; /// Initial momenta m_pz of majority particle - std::vector* m_t_theta = nullptr; /// Initial momenta theta of majority particle - std::vector* m_t_phi = nullptr; /// Initial momenta phi of majority particle - std::vector* m_t_pT = nullptr; /// Initial momenta pT of majority particle - std::vector* m_t_eta = nullptr; /// Initial momenta eta of majority particle + std::vector* m_nMajorityHits = nullptr; /// The number of hits from majority particle + std::vector* m_majorityParticleId = nullptr; /// The particle Id of the majority particle + std::vector* m_t_charge = nullptr; /// Charge of majority particle + std::vector* m_t_time = nullptr; /// Time of majority particle + std::vector* m_t_vx = nullptr; /// Vertex x positions of majority particle + std::vector* m_t_vy = nullptr; /// Vertex y positions of majority particle + std::vector* m_t_vz = nullptr; /// Vertex z positions of majority particle + std::vector* m_t_px = nullptr; /// Initial momenta m_px of majority particle + std::vector* m_t_py = nullptr; /// Initial momenta m_py of majority particle + std::vector* m_t_pz = nullptr; /// Initial momenta m_pz of majority particle + std::vector* m_t_theta = nullptr; /// Initial momenta theta of majority particle + std::vector* m_t_phi = nullptr; /// Initial momenta phi of majority particle + std::vector* m_t_pT = nullptr; /// Initial momenta pT of majority particle + std::vector* m_t_eta = nullptr; /// Initial momenta eta of majority particle std::vector* m_majorityParticlePDG = nullptr; // IA }; @@ -208,6 +228,28 @@ struct Alice3TrackingTranslator { } std::vector* barcode = nullptr; }; + void addMCParticle(int collIndex, ParticleStruct& fileParticles, int iParticle, uint8_t flags, int firstMother, int firstDaughter, int numberOfHits) + { + int mothers[2] = {firstMother, -1}; + int daughters[2] = {firstDaughter, -1}; + tableStoredMcParticles(collIndex, // mcCollisionId + fileParticles.m_particle_type->at(iParticle), // pdgCode + 0, // statusCode + flags, // flags + mothers, // mothersIds + daughters, // daughtersIdSlice + 1.0f, // weight + fileParticles.m_px->at(iParticle), // m_px + fileParticles.m_py->at(iParticle), // m_py + fileParticles.m_pz->at(iParticle), // m_pz + std::hypot(fileParticles.m_p->at(iParticle), fileParticles.m_m->at(iParticle)), // e + fileParticles.m_vx->at(iParticle), // m_vx + fileParticles.m_vy->at(iParticle), // m_vy + fileParticles.m_vz->at(iParticle), // m_vz + fileParticles.m_vt->at(iParticle)); // m_vt + tableMCParticlesExtraA3(numberOfHits, // number_of_hits + fileParticles.m_q->at(iParticle)); // charge + }; void process(o2::aod::BCs const&) { @@ -243,19 +285,34 @@ struct Alice3TrackingTranslator { LOG(info) << "Processing file: " << justFilename.Data(); files[justFilename.Data()] = filename; } - + LOG(info) << "All files loaded successfully"; // Now open the files to translate and read the trees - ParticleStruct fileParticles(files["particles_simulation.root"], "particles"); + ParticleStruct fileParticles(files["particles.root"], "particles"); + LOG(info) << "Particles loaded successfully"; + ParticleStruct fileParticlesSim(files["particles_simulation.root"], "particles"); + LOG(info) << "Particles Sim loaded successfully"; + std::string daughterFileName = addDaughterInfo ? "particles_decay.root" : "particles_simulation.root"; + ParticleStruct fileDaughterParticles(files[daughterFileName], "particles"); + LOG(info) << "Daughter particles loaded successfully from file " << daughterFileName; // FileStruct fileVertices(files["performance_vertexing.root"], "vertexing"); TrackStruct fileTracksummary(files["tracksummary_ambi.root"], "tracksummary"); // HitsStruct fileHits(files["hits.root"], "hits"); + LOG(info) << "Tracks loaded successfully"; const Long64_t kEvents = fileParticles.getEntries(); + int indexOfLastParticleAfterEvent = -1; for (Long64_t iEvent = 0; iEvent < kEvents; ++iEvent) { + if (iEvent > 0 && maxCollisions.value > 0 && (iEvent % maxCollisions) == 0) { + LOG(info) << "Stopping at event " << iEvent << "/" << kEvents; + break; + } fileParticles.setEventEntry(iEvent); // fileVertices.setEventEntry(iEvent); fileTracksummary.setEventEntry(iEvent); // fileHits.setEventEntry(iEvent); + if (addDaughterInfo) + fileDaughterParticles.setEventEntry(iEvent); + fileParticlesSim.setEventEntry(iEvent); LOG(info) << "Processing event " << iEvent << "/" << kEvents; @@ -265,6 +322,13 @@ struct Alice3TrackingTranslator { float collisionY = 0.0f; float collisionZ = 0.0f; + tableOTFLUTConfigId(0); // dummy for the moment + + // Determine the collision ID for the new entry. + // If the table is empty, lastIndex() returns -1, so we start at 0. + // If it has entries, lastIndex() returns the index of the last element, so we use lastIndex() + 1. + int collisionId = tableCollisions.lastIndex() + 1; + tableCollisions(0, // bcId collisionX, // posX collisionY, // posY @@ -286,10 +350,6 @@ struct Alice3TrackingTranslator { tableCollisionsAlice3(0.f); // multDensity - // Fill MC particles - int mothers[2] = {-1, -1}; - int daughters[2] = {-1, -1}; - struct addedParticle { float px; float py; @@ -298,50 +358,92 @@ struct Alice3TrackingTranslator { float vy; float vz; }; - std::map> addedParticles; // Convert tracks from ACTS to ALICE format const size_t nParticlesGen = fileParticles.m_vx->size(); - const size_t nParticles = fileTracksummary.m_t_vx->size(); + const size_t nParticlesSim = fileParticlesSim.m_vx->size(); + const size_t nDaughterParticles = fileDaughterParticles.m_vx->size(); const size_t nTracks = fileTracksummary.m_eLOC0_fit->size(); + std::vector idMCparticles; + for (size_t iTrack = 0; iTrack < nTracks; ++iTrack) { - LOG(info) << "Processing track " << iTrack << "/" << nTracks << " (nParticles=" << nParticles << ") nParticlesGen=" << nParticlesGen; + LOG(info) << "Processing track " << iTrack << "/" << nTracks << " (nParticlesSim=" << nParticlesSim << ") nParticlesGen=" << nParticlesGen; const size_t iParticle = iTrack; + if (iParticle == 0) { - tableMcCollisions(0, // mccollision::BCId, - 0, // mccollision::GeneratorsID, - fileTracksummary.m_t_vx->at(iParticle), // mccollision::PosX, - fileTracksummary.m_t_vy->at(iParticle), // mccollision::PosY, - fileTracksummary.m_t_vz->at(iParticle), // mccollision::PosZ - fileTracksummary.m_t_time->at(iParticle), // mccollision::T - 1.0f, // mccollision::Weight - 0.0f, // mccollision::ImpactParameter, - 0.f); // mccollision::EventPlaneAngle, + tableMcCollisions(0, // mccollision::BCId, + 0, // mccollision::GeneratorsID, + fileParticles.m_vx->at(iParticle), // mccollision::PosX, + fileParticles.m_vy->at(iParticle), // mccollision::PosY, + fileParticles.m_vz->at(iParticle), // mccollision::PosZ + fileParticles.m_vt->at(iParticle), // mccollision::T + 1.0f, // mccollision::Weight + 0.0f, // mccollision::ImpactParameter, + 0.f); // mccollision::EventPlaneAngle, } uint8_t flags = 0; - flags |= o2::aod::mcparticle::enums::PhysicalPrimary; - - addedParticles[fileTracksummary.m_majorityParticlePDG->at(iParticle)].push_back({fileTracksummary.m_t_px->at(iParticle), - fileTracksummary.m_t_py->at(iParticle), - fileTracksummary.m_t_pz->at(iParticle), - fileTracksummary.m_t_vx->at(iParticle), - fileTracksummary.m_t_vy->at(iParticle), - fileTracksummary.m_t_vz->at(iParticle)}); - tableStoredMcParticles(tableMcCollisions.lastIndex(), // mcCollisionId - fileTracksummary.m_majorityParticlePDG->at(iParticle), // pdgCode - 0, // statusCode - flags, // flags - mothers, // mothersIds - daughters, // daughtersIdSlice - 1.0f, // weight - fileTracksummary.m_t_px->at(iParticle), // m_px - fileTracksummary.m_t_py->at(iParticle), // m_py - fileTracksummary.m_t_pz->at(iParticle), // m_pz - 0, // e - fileTracksummary.m_t_vx->at(iParticle), // m_vx - fileTracksummary.m_t_vy->at(iParticle), // m_vy - fileTracksummary.m_t_vz->at(iParticle), // m_vz - fileTracksummary.m_t_time->at(iParticle)); // m_vt + ULong64_t idMCTrueParticle = fileTracksummary.m_majorityParticleId->at(iParticle); + int32_t mcParticleId = -1; + int pdgCode = -1; + + for (size_t iMC = 0; iMC < nParticlesGen; ++iMC) { + if (fileParticles.m_particleId->at(iMC) == idMCTrueParticle) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileParticles.m_particleId->at(iMC)) > 0) { + continue; + } + idMCparticles.push_back(fileParticles.m_particleId->at(iMC)); + flags |= o2::aod::mcparticle::enums::PhysicalPrimary; + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileParticles.m_particleId->at(iMC)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); + break; + } + } + addMCParticle(tableMcCollisions.lastIndex(), fileParticles, iMC, flags, -1, -1, nHits); + mcParticleId = tableStoredMcParticles.lastIndex(); + pdgCode = fileParticles.m_particle_type->at(iMC); + break; + } + } + if (addDaughterInfo) { + for (size_t iMC = 0; iMC < nDaughterParticles; ++iMC) { + if (fileDaughterParticles.m_particleId->at(iMC) == idMCTrueParticle) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_particleId->at(iMC)) > 0) { + break; + } + + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileDaughterParticles.m_particleId->at(iMC)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); + break; + } + } + for (size_t iMother = 0; iMother < nParticlesGen; ++iMother) { + if (fileDaughterParticles.m_motherId->at(iMC) == fileParticles.m_particleId->at(iMother)) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileParticles.m_particleId->at(iMother)) > 0) { + break; + } + idMCparticles.push_back(fileParticles.m_particleId->at(iMother)); + uint8_t flagsMother = o2::aod::mcparticle::enums::PhysicalPrimary; + addMCParticle(tableMcCollisions.lastIndex(), fileParticles, iMother, flagsMother, -1, tableStoredMcParticles.lastIndex() + 2, 0); + break; + } + } + int motherId = -1; + if (count(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iMC)) > 0) { + auto it = find(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iMC)); + motherId = it - idMCparticles.begin() + indexOfLastParticleAfterEvent + 1; + } + idMCparticles.push_back(fileDaughterParticles.m_particleId->at(iMC)); + addMCParticle(tableMcCollisions.lastIndex(), fileDaughterParticles, iMC, flags, motherId, -1, nHits); + mcParticleId = tableStoredMcParticles.lastIndex(); + pdgCode = fileDaughterParticles.m_particle_type->at(iMC); + break; + } + } + } // Extract ACTS track parameters const float phi = fileTracksummary.m_ePHI_fit->at(iTrack); const float theta = fileTracksummary.m_eTHETA_fit->at(iTrack); @@ -398,7 +500,7 @@ struct Alice3TrackingTranslator { o2::track::TrackParCov trackParCov(x, alpha, trackParams, trackCov, charge); // Fill StoredTracks table (basic track parameters) - tableStoredTracks(tableCollisions.lastIndex(), // collisionId + tableStoredTracks(collisionId, // collisionId o2::aod::track::TrackTypeEnum::Track, // trackType trackParCov.getX(), // x trackParCov.getAlpha(), // alpha @@ -449,8 +551,6 @@ struct Alice3TrackingTranslator { // Fill MC track labels // Get particle linkage from hits using the majority hit index - int32_t mcParticleId = -1; // Default to invalid particle ID - mcParticleId = tableStoredMcParticles.lastIndex(); // Temporary: link all tracks to the last added MC particle // if (fileTracksummary.nMajorityHits && iTrack < fileTracksummary.nMajorityHits->size()) { // unsigned int hitIndex = fileTracksummary.nMajorityHits->at(iTrack); // if (fileHits.barcode && hitIndex < fileHits.barcode->size()) { @@ -478,7 +578,8 @@ struct Alice3TrackingTranslator { 0.0f); // sigmaDcaZ2 // Fill ALICE3 specific tables - tableTracksAlice3(true); // isReconstructed + tableTracksAlice3(true); // isReconstructed + tableTracksAlice3Pdg(pdgCode); // PdgCode to the linked MC truth particle tableTracksExtraA3(m_nMeasurements, // nSiliconHits (using m_nMeasurements as proxy) 0); // nTPCHits @@ -535,43 +636,64 @@ struct Alice3TrackingTranslator { } for (size_t iParticle = 0; iParticle < nParticlesGen; ++iParticle) { - + if (iParticle == 0 && nTracks == 0) { + tableMcCollisions(0, // mccollision::BCId, + 0, // mccollision::GeneratorsID, + fileParticles.m_vx->at(iParticle), // mccollision::PosX, + fileParticles.m_vy->at(iParticle), // mccollision::PosY, + fileParticles.m_vz->at(iParticle), // mccollision::PosZ + fileParticles.m_vt->at(iParticle), // mccollision::T + 1.0f, // mccollision::Weight + 0.0f, // mccollision::ImpactParameter, + 0.f); // mccollision::EventPlaneAngle, + } + if (idMCparticles.end() != std::find(idMCparticles.begin(), idMCparticles.end(), fileParticles.m_particleId->at(iParticle))) { + // Already added via track + continue; + } uint8_t flags = 0; flags |= o2::aod::mcparticle::enums::PhysicalPrimary; - bool alreadyAdded = false; - for (const auto& ap : addedParticles[fileParticles.m_particle_type->at(iParticle)]) { - if (std::abs(ap.px - fileParticles.m_px->at(iParticle)) <= 1.e-5 && - std::abs(ap.py - fileParticles.m_py->at(iParticle)) <= 1.e-5 && - std::abs(ap.pz - fileParticles.m_pz->at(iParticle)) <= 1.e-5 && - std::abs(ap.vx - fileParticles.m_vx->at(iParticle)) <= 1.e-5 && - std::abs(ap.vy - fileParticles.m_vy->at(iParticle)) <= 1.e-5 && - std::abs(ap.vz - fileParticles.m_vz->at(iParticle)) <= 1.e-5) { - alreadyAdded = true; + + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileParticles.m_particleId->at(iParticle)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); break; } } - if (alreadyAdded) { - continue; + addMCParticle(tableMcCollisions.lastIndex(), fileParticles, iParticle, flags, -1, -1, nHits); + idMCparticles.push_back(fileParticles.m_particleId->at(iParticle)); + } + if (addDaughterInfo) { + for (size_t iParticle = 0; iParticle < nDaughterParticles; ++iParticle) { + if (idMCparticles.end() != std::find(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_particleId->at(iParticle))) { + // Already added via track + continue; + } + uint8_t flags = 0; + int nHits = 0; + for (size_t iPartSim = 0; iPartSim < nParticlesSim; ++iPartSim) { + if (fileParticlesSim.m_particleId->at(iPartSim) == fileDaughterParticles.m_particleId->at(iParticle)) { + nHits = fileParticlesSim.m_number_of_hits->at(iPartSim); + break; + } + } + int motherId = -1; + for (size_t iMother = 0; iMother < nParticlesGen; ++iMother) { + if (fileDaughterParticles.m_motherId->at(iParticle) == fileParticles.m_particleId->at(iMother)) { + if (count(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iParticle)) > 0) { + auto it = find(idMCparticles.begin(), idMCparticles.end(), fileDaughterParticles.m_motherId->at(iParticle)); + motherId = it - idMCparticles.begin() + indexOfLastParticleAfterEvent + 1; + } + } + } + addMCParticle(tableMcCollisions.lastIndex(), fileDaughterParticles, iParticle, flags, motherId, -1, nHits); } - - tableStoredMcParticles(tableMcCollisions.lastIndex(), // mcCollisionId - fileParticles.m_particle_type->at(iParticle), // pdgCode - 0, // statusCode - flags, // flags - mothers, // mothersIds - daughters, // daughtersIdSlice - 1.0f, // weight - fileParticles.m_px->at(iParticle), // m_px - fileParticles.m_py->at(iParticle), // m_py - fileParticles.m_pz->at(iParticle), // m_pz - std::hypot(fileParticles.m_p->at(iParticle), fileParticles.m_m->at(iParticle)), // e - fileParticles.m_vx->at(iParticle), // m_vx - fileParticles.m_vy->at(iParticle), // m_vy - fileParticles.m_vz->at(iParticle), // m_vz - fileParticles.m_vt->at(iParticle)); // m_vt } - LOG(info) << "Event " << iEvent << ": has " << nTracks << " tracks and " << nParticles << " particles."; + LOG(info) << "Event " << iEvent << ": has " << nTracks << " tracks, " << nParticlesGen << " particles " << nDaughterParticles << " daughter particles, " << nParticlesSim << " propagated particles."; + LOG(info) << "Total numbers of stored MC particles: " << tableStoredMcParticles.lastIndex() + 1; + indexOfLastParticleAfterEvent = tableStoredMcParticles.lastIndex(); } } }; diff --git a/ALICE3/TableProducer/alice3strangenessFinder.cxx b/ALICE3/TableProducer/alice3strangenessFinder.cxx new file mode 100644 index 00000000000..e96db585c25 --- /dev/null +++ b/ALICE3/TableProducer/alice3strangenessFinder.cxx @@ -0,0 +1,703 @@ +// 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 alice3strangenessFinder.cxx +/// +/// \brief finding of V0 and cascade candidates for ALICE 3 +/// +/// This task finds and build condidates for strange hadrons (K0s, Lambda, AntiLambda, Xi-, Xi+, Omega-, Omega+) +/// using the output of the on-the-fly tracker. +/// +/// \author Lucia Anna Tarasovičová, Pavol Jozef Šafárik University (SK) +/// + +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFMCParticle.h" +#include "ALICE3/DataModel/OTFPIDTrk.h" +#include "ALICE3/DataModel/OTFRICH.h" +#include "ALICE3/DataModel/OTFStrangeness.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace o2; +// using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::constants::physics; + +using Alice3TracksWPid = soa::Join; +using Alice3TracksACTS = soa::Join; +using Alice3TracksOTF = soa::Join; +using Alice3MCParticles = soa::Join; + +struct Alice3strangenessFinder { + SliceCache cache; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Produces v0CandidateIndices; // contains V0 candidate indices + Produces v0CandidateCores; // contains V0 candidate core information + Produces tableCascadeCores; + Produces tableCascadeIndices; + + Configurable buildCascade{"buildCascade", false, "build cascade candidates"}; + + Configurable nSigmaTOF{"nSigmaTOF", 5.0f, "Nsigma for TOF PID (if enabled)"}; + Configurable dcaXYconstant{"dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable dcaXYpTdep{"dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + + ConfigurableAxis axisK0Mass{"axisK0Mass", {200, 0.4f, 0.6f}, "K0 mass axis"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {200, 1.101f, 1.131f}, "Lambda mass axis"}; + ConfigurableAxis axisXiMass{"axisXiMass", {200, 1.22f, 1.42f}, "Xi mass axis"}; + ConfigurableAxis axisMassOmega{"axisMassOmega", {200, 1.57f, 1.77f}, "Omega mass axis"}; + + ConfigurableAxis axisEta{"axisEta", {80, -4.f, 4.f}, "Eta axis"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.025f, 0.05f, 0.075f, 0.1f, 0.125f, 0.15f, 0.175f, 0.2f, 0.225f, 0.25f, 0.275f, 0.3f, 0.325f, 0.35f, 0.375f, 0.4f, 0.425f, 0.45f, 0.475f, 0.5f, 0.525f, 0.55f, 0.575f, 0.6f, 0.625f, 0.65f, 0.675f, 0.7f, 0.725f, 0.75f, 0.775f, 0.8f, 0.82f, 0.85f, 0.875f, 0.9f, 0.925f, 0.95f, 0.975f, 1.0f, 1.05f, 1.1f}, "pt axis for QA histograms"}; + + Configurable bachMinConstDCAxy{"bachMinConstDCAxy", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable bachMinPtDepDCAxy{"bachMinPtDepDCAxy", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable bachMinConstDCAz{"bachMinConstDCAz", -1.0f, "[0] in |DCAz| > [0]+[1]/pT"}; + Configurable bachMinPtDepDCAz{"bachMinPtDepDCAz", 0.0, "[1] in |DCAz| > [0]+[1]/pT"}; + + Configurable v0MaxDauDCA{"v0MaxDauDCA", 0.005f, "DCA between v0 daughters (cm)"}; + Configurable cascMaxDauDCA{"cascMaxDauDCA", 0.005f, "DCA between cascade daughters (cm)"}; + + // DCA Fitter + struct : ConfigurableGroup { + std::string prefix = "cfgFitter"; + + // Vertexing + Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", true, "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", 150., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 5, "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4, "reject (if>0) PCA candidate if tracks DXY exceeds threshold"}; + Configurable maxVtxChi2{"maxVtxChi2", 10, "reject (if>0) vtx. chi2 above this value"}; + 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"}; + + // propagation options + Configurable usePropagator{"usePropagator", false, "use external propagator"}; + Configurable refitWithMatCorr{"refitWithMatCorr", false, "refit V0 applying material corrections"}; + Configurable useCollinearV0{"useCollinearV0", true, "use collinear approximation for V0 fitting"}; + Configurable maxIter{"maxIter", 30, "maximum number of iterations for vertex fitter"}; + } cfgFitter; + + Configurable acceptedLambdaMassWindow{"acceptedLambdaMassWindow", 0.2f, "accepted Lambda mass window around PDG mass"}; + + // Operation + Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; + Configurable mcSameMotherCheck{"mcSameMotherCheck", true, "check if tracks come from the same MC mother"}; + + // for the ACTS study + Configurable isK0Gun{"isK0Gun", false, "is K0s Monte Carlo gun used"}; + Configurable isLambdaGun{"isLambdaGun", true, "is Lambda Monte Carlo gun used"}; + Configurable skipFitter{"skipFitter", false, "calculate V0 properties without calling the DCA fitter, using only the track parameters "}; + Configurable useOriginalTrackParams{"useOriginalTrackParams", false, "use original track parameters instead of the ones propagated to PCA (effective only if skipFitter is false) and for MC truth info"}; + + o2::vertexing::DCAFitterN<2> fitter; + o2::vertexing::DCAFitterN<3> fitter3; + + Service pdgDB; + + // partitions for v0/casc dau tracks + Partition positiveSecondaryTracksACTS = + aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition negativeSecondaryTracksACTS = + aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition bachelorTracksACTS = + nabs(aod::track::dcaXY) > bachMinConstDCAxy + bachMinPtDepDCAxy* nabs(aod::track::signed1Pt) && nabs(aod::track::dcaZ) > bachMinConstDCAz + bachMinPtDepDCAz* nabs(aod::track::signed1Pt); + + Partition positiveSecondaryTracksOTF = + aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition negativeSecondaryTracksOTF = + aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition bachelorTracksOTF = + nabs(aod::track::dcaXY) > bachMinConstDCAxy + bachMinPtDepDCAxy* nabs(aod::track::signed1Pt) && nabs(aod::track::dcaZ) > bachMinConstDCAz + bachMinPtDepDCAz* nabs(aod::track::signed1Pt); + + Partition positiveMCParticles = aod::mcparticle_alice3::charge > 0.0f; + Partition negativeMCParticles = aod::mcparticle_alice3::charge < 0.0f; + + Partition trueK0s = aod::mcparticle::pdgCode == static_cast(PDG_t::kK0Short); + Partition trueLambda = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0); + Partition trueAntiLambda = aod::mcparticle::pdgCode == static_cast(PDG_t::kLambda0Bar); + Partition trueXi = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiMinus); + Partition trueAntiXi = aod::mcparticle::pdgCode == static_cast(PDG_t::kXiPlusBar); + Partition trueOmega = aod::mcparticle::pdgCode == static_cast(PDG_t::kOmegaMinus); + Partition trueAntiOmega = aod::mcparticle::pdgCode == static_cast(PDG_t::kOmegaPlusBar); + + // Partition negativeSecondaryPions = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaPionOuterTOF) < nSigmaTOF && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + // Partition positiveSecondaryPions = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaPionOuterTOF) < nSigmaTOF && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + // Partition secondaryProtons = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) < nSigmaTOF && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + // Partition secondaryAntiProtons = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) < nSigmaTOF && nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) < nSigmaTOF && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > dcaXYconstant + dcaXYpTdep* nabs(aod::track::signed1Pt); + + struct Candidate { + // decay properties + float dcaDau{}; + float eta{}; + std::array p{}; + std::array posSV{}; + std::array pDau0{}; + std::array pDau1{}; + std::array parentTrackCovMatrix{}; + float cosPA{}; + float dcaToPV{}; + }; + + void init(InitContext&) + { + // Initialization code here + fitter.setBz(magneticField); + fitter.setUseAbsDCA(cfgFitter.useAbsDCA); + fitter.setPropagateToPCA(cfgFitter.propagateToPCA); + fitter.setMaxR(cfgFitter.maxR); + fitter.setMinParamChange(cfgFitter.minParamChange); + fitter.setMinRelChi2Change(cfgFitter.minRelChi2Change); + fitter.setMaxDZIni(cfgFitter.maxDZIni); + fitter.setMaxDXYIni(cfgFitter.maxDXYIni); + fitter.setMaxChi2(cfgFitter.maxVtxChi2); + fitter.setUsePropagator(cfgFitter.usePropagator); + fitter.setRefitWithMatCorr(cfgFitter.refitWithMatCorr); + fitter.setCollinear(cfgFitter.useCollinearV0); + fitter.setMaxIter(cfgFitter.maxIter); + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + histos.add("hFitterQA", "", kTH1D, {{10, 0, 10}}); // For QA reasons, counting found candidates at different stages + auto hFitterStatusCode = histos.add("hFitterStatusCode", "hFitterStatusCode", kTH1D, {{15, -0.5, 14.5}}); + hFitterStatusCode->GetXaxis()->SetBinLabel(1, "None"); // no status set (should not be possible!) + + /* Good Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(2, "Converged"); // fit converged + hFitterStatusCode->GetXaxis()->SetBinLabel(3, "MaxIter"); // max iterations reached before fit convergence + + /* Error Conditions */ + hFitterStatusCode->GetXaxis()->SetBinLabel(4, "NoCrossing"); // no reasaonable crossing was found + hFitterStatusCode->GetXaxis()->SetBinLabel(5, "RejRadius"); // radius of crossing was not acceptable + hFitterStatusCode->GetXaxis()->SetBinLabel(6, "RejTrackX"); // one candidate track x was below the mimimum required radius + hFitterStatusCode->GetXaxis()->SetBinLabel(7, "RejTrackRoughZ"); // rejected by rough cut on tracks Z difference + hFitterStatusCode->GetXaxis()->SetBinLabel(8, "RejChi2Max"); // rejected by maximum chi2 cut + hFitterStatusCode->GetXaxis()->SetBinLabel(9, "FailProp"); // propagation of at least prong to PCA failed + hFitterStatusCode->GetXaxis()->SetBinLabel(10, "FailInvCov"); // inversion of cov.-matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(11, "FailInvWeight"); // inversion of Ti weight matrix failed + hFitterStatusCode->GetXaxis()->SetBinLabel(12, "FailInv2ndDeriv"); // inversion of 2nd derivatives failed + hFitterStatusCode->GetXaxis()->SetBinLabel(13, "FailCorrTracks"); // correction of tracks to updated x failed + hFitterStatusCode->GetXaxis()->SetBinLabel(14, "FailCloserAlt"); // alternative PCA is closer + hFitterStatusCode->GetXaxis()->SetBinLabel(15, "NStatusesDefined"); + + histos.add("hPtPosDau", "", kTH1D, {axisPt}); + histos.add("hPtNegDau", "", kTH1D, {axisPt}); + histos.add("hPtPosDauAfterV0Finding", "", kTH2D, {axisPt, axisPt}); + histos.add("hPtNegDauAfterV0Finding", "", kTH2D, {axisPt, axisPt}); + histos.add("hEventCounter", "", kTH1D, {{1, 0, 2}}); // counting processed events + auto hV0Counter = histos.add("hV0Counter", "hV0Counter", kTH1D, {{4, 0, 4}}); + hV0Counter->GetXaxis()->SetBinLabel(1, "K0S"); + hV0Counter->GetXaxis()->SetBinLabel(2, "Lambda"); + hV0Counter->GetXaxis()->SetBinLabel(3, "AntiLambda"); + hV0Counter->GetXaxis()->SetBinLabel(4, "Misidentified"); + + histos.add("hRadiusVsHitsNeg", "", kTH2D, {{400, 0, 400}, {12, 0.5, 12.5}}); // radius vs hist for MC studies + histos.add("hRadiusVsHitsPos", "", kTH2D, {{400, 0, 400}, {12, 0.5, 12.5}}); // radius vs hist for MC studies + + auto hV0Building = histos.add("hV0Building", "hV0Building", kTH1D, {{10, 0.5, 10.5}}); + hV0Building->GetXaxis()->SetBinLabel(1, "Pair"); + hV0Building->GetXaxis()->SetBinLabel(2, "Pdg check"); + hV0Building->GetXaxis()->SetBinLabel(3, "DCA Fitter"); + + auto hCascadeBuilding = histos.add("hCascadeBuilding", "hCascadeBuilding", kTH1D, {{10, 0.5, 10.5}}); + hCascadeBuilding->GetXaxis()->SetBinLabel(1, "Attempts"); + hCascadeBuilding->GetXaxis()->SetBinLabel(2, "La mass window"); + hCascadeBuilding->GetXaxis()->SetBinLabel(3, "DCA Fitter"); + + if (doprocessGenerated) { + histos.add("hGeneratedK0s", "hGeneratedK0s", kTH2D, {{axisPt}, {axisEta}}); + histos.add("hGeneratedLambda", "hGeneratedLambda", kTH2D, {{axisPt}, {axisEta}}); + histos.add("hGeneratedAntiLambda", "hGeneratedAntiLambda", kTH2D, {{axisPt}, {axisEta}}); + histos.add("hGeneratedXi", "hGeneratedXi", kTH2D, {{axisPt}, {axisEta}}); + histos.add("hGeneratedAntiXi", "hGeneratedAntiXi", kTH2D, {{axisPt}, {axisEta}}); + histos.add("hGeneratedOmega", "hGeneratedOmega", kTH2D, {{axisPt}, {axisEta}}); + histos.add("hGeneratedAntiOmega", "hGeneratedAntiOmega", kTH2D, {{axisPt}, {axisEta}}); + } + + histos.print(); + } + + 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)); + } + + /// function to check if tracks have the same mother in MC + template + bool checkSameMother(TTrackType const& track1, TTrackType const& track2) + { + // MC label points to McPartWithDaus + if constexpr (requires { track1.has_mcPartWithDau(); }) { + if (!track1.has_mcPartWithDau() || !track2.has_mcPartWithDau()) { + return false; + } + auto mcParticle1 = track1.template mcPartWithDau_as(); + auto mcParticle2 = track2.template mcPartWithDau_as(); + if (mcParticle1.mothersIds().empty() || mcParticle2.mothersIds().empty()) { + return false; + } + return mcParticle1.mothersIds()[0] == mcParticle2.mothersIds()[0]; + } else { // MC label points directly to aod::McParticles + bool returnValue = false; + 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 (const auto& m1 : mcParticle1.template mothers_as()) { + for (const auto& m2 : mcParticle2.template mothers_as()) { + if (m1.globalIndex() == m2.globalIndex()) { + returnValue = true; + } + } + } + } + } + return returnValue; + } + } + + template + bool buildDecayCandidateTwoBody(TTrackType const& t0, TTrackType const& t1, std::array vtx, Candidate& thisCandidate) + { + + histos.fill(HIST("hPtNegDau"), t1.getPt()); + histos.fill(HIST("hPtPosDau"), t0.getPt()); + + if (!skipFitter) { + + histos.fill(HIST("hFitterQA"), 0.5); + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima + int nCand = 0; + try { + nCand = fitter.process(t0, t1); + } catch (...) { + return false; + } + + const u_int8_t fitterStatusCode = fitter.getFitStatus(); + histos.fill(HIST("hFitterStatusCode"), fitterStatusCode); + histos.fill(HIST("hFitterQA"), 1.5); + if (nCand == 0) { + LOG(debug) << "0 candidates found by fitter"; + return false; + } + histos.fill(HIST("hFitterQA"), 2.5); + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { + LOG(debug) << "RejProp failed"; + return false; + } + histos.fill(HIST("hFitterQA"), 3.5); + o2::track::TrackParCov t0New = fitter.getTrack(0); + o2::track::TrackParCov t1New = fitter.getTrack(1); + t0New.getPxPyPzGlo(thisCandidate.pDau0); + t1New.getPxPyPzGlo(thisCandidate.pDau1); + if (useOriginalTrackParams) { + t0.getPxPyPzGlo(thisCandidate.pDau0); + t1.getPxPyPzGlo(thisCandidate.pDau1); + } + histos.fill(HIST("hPtNegDauAfterV0Finding"), std::sqrt(thisCandidate.pDau1[0] * thisCandidate.pDau1[0] + thisCandidate.pDau1[1] + thisCandidate.pDau1[1]), t1.getPt()); + histos.fill(HIST("hPtPosDauAfterV0Finding"), std::sqrt(thisCandidate.pDau0[0] * thisCandidate.pDau0[0] + thisCandidate.pDau0[1] + thisCandidate.pDau0[1]), t0.getPt()); + + thisCandidate.dcaDau = std::sqrt(fitter.getChi2AtPCACandidate()); + thisCandidate.p[0] = thisCandidate.pDau0[0] + thisCandidate.pDau1[0]; + thisCandidate.p[1] = thisCandidate.pDau0[1] + thisCandidate.pDau1[1]; + thisCandidate.p[2] = thisCandidate.pDau0[2] + thisCandidate.pDau1[2]; + const auto posSV = fitter.getPCACandidatePos(); + thisCandidate.posSV[0] = posSV[0]; + thisCandidate.posSV[1] = posSV[1]; + thisCandidate.posSV[2] = posSV[2]; + + std::array covA = {0}; + std::array covB = {0}; + fitter.getTrack(0).getCovXYZPxPyPzGlo(covA); + fitter.getTrack(1).getCovXYZPxPyPzGlo(covB); + + static constexpr std::array MomentumIndices = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (size_t i = 0; i < MomentumIndices.size(); i++) { + int j = MomentumIndices[i]; + thisCandidate.parentTrackCovMatrix[j] = covA[j] + covB[j]; + } + + auto covVtx = fitter.calcPCACovMatrix(); + thisCandidate.parentTrackCovMatrix[0] = covVtx(0, 0); + thisCandidate.parentTrackCovMatrix[1] = covVtx(1, 0); + thisCandidate.parentTrackCovMatrix[2] = covVtx(1, 1); + thisCandidate.parentTrackCovMatrix[3] = covVtx(2, 0); + thisCandidate.parentTrackCovMatrix[4] = covVtx(2, 1); + thisCandidate.parentTrackCovMatrix[5] = covVtx(2, 2); + thisCandidate.parentTrackCovMatrix[0] = 0; + thisCandidate.parentTrackCovMatrix[1] = 0; + thisCandidate.parentTrackCovMatrix[2] = 0; + thisCandidate.parentTrackCovMatrix[3] = 0; + thisCandidate.parentTrackCovMatrix[4] = 0; + thisCandidate.parentTrackCovMatrix[5] = 0; + + thisCandidate.eta = RecoDecay::eta(std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.cosPA = RecoDecay::cpa(vtx, std::array{thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2]}, + std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.dcaToPV = calculateDCAStraightToPV(thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2], + thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2], + vtx[0], vtx[1], vtx[2]); + + return true; + } else { + t0.getPxPyPzGlo(thisCandidate.pDau0); + t1.getPxPyPzGlo(thisCandidate.pDau1); + thisCandidate.dcaDau = 0; + thisCandidate.p[0] = thisCandidate.pDau0[0] + thisCandidate.pDau1[0]; + thisCandidate.p[1] = thisCandidate.pDau0[1] + thisCandidate.pDau1[1]; + thisCandidate.p[2] = thisCandidate.pDau0[2] + thisCandidate.pDau1[2]; + thisCandidate.posSV[0] = 0; + thisCandidate.posSV[1] = 0; + thisCandidate.posSV[2] = 0; + thisCandidate.eta = RecoDecay::eta(std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.cosPA = RecoDecay::cpa(vtx, std::array{thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2]}, + std::array{thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2]}); + thisCandidate.dcaToPV = calculateDCAStraightToPV(thisCandidate.posSV[0], thisCandidate.posSV[1], thisCandidate.posSV[2], + thisCandidate.p[0], thisCandidate.p[1], thisCandidate.p[2], + vtx[0], vtx[1], vtx[2]); + return true; + } + } + + void processGenerated(aod::McParticles const&) + { + for (const auto& mcParticle : trueK0s) { + histos.fill(HIST("hGeneratedK0s"), mcParticle.pt(), mcParticle.eta()); + } + for (const auto& mcParticle : trueLambda) { + histos.fill(HIST("hGeneratedLambda"), mcParticle.pt(), mcParticle.eta()); + } + for (const auto& mcParticle : trueAntiLambda) { + histos.fill(HIST("hGeneratedAntiLambda"), mcParticle.pt(), mcParticle.eta()); + } + for (const auto& mcParticle : trueXi) { + histos.fill(HIST("hGeneratedXi"), mcParticle.pt(), mcParticle.eta()); + } + for (const auto& mcParticle : trueAntiXi) { + histos.fill(HIST("hGeneratedAntiXi"), mcParticle.pt(), mcParticle.eta()); + } + for (const auto& mcParticle : trueOmega) { + histos.fill(HIST("hGeneratedOmega"), mcParticle.pt(), mcParticle.eta()); + } + for (const auto& mcParticle : trueAntiOmega) { + histos.fill(HIST("hGeneratedAntiOmega"), mcParticle.pt(), mcParticle.eta()); + } + } + + template + void processFindV0CandidateNoPid(TCollision collision, TTracksGrouped negTracksGrouped, TTracksGrouped posTracksGrouped, TTracksGrouped bachTracksGrouped) + { + const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; + histos.fill(HIST("hEventCounter"), 1.0); + + for (auto const& posTrack : posTracksGrouped) { + if (!posTrack.isReconstructed()) { + continue; // no ghost tracks + } + + o2::track::TrackParCov pos = getTrackParCov(posTrack); + + for (auto const& negTrack : negTracksGrouped) { + if (!negTrack.isReconstructed()) { + continue; // no ghost tracks + } + + histos.fill(HIST("hV0Building"), 1.0); + if (mcSameMotherCheck && !checkSameMother(posTrack, negTrack)) { + continue; // keep only if same mother + } + + // ACTS: pdg code attached to track + if constexpr (requires { posTrack.pdgCode(); }) { + if ((posTrack.pdgCode() != kPiPlus && negTrack.pdgCode() != kPiMinus) && isK0Gun) { + continue; + } + if ((posTrack.pdgCode() != kProton && negTrack.pdgCode() != kPiMinus) && isLambdaGun) { + continue; + } + } + + // OTF: pdg code from mcParticle table + if constexpr (requires { posTrack.has_mcPartWithDau(); }) { + if (!posTrack.has_mcPartWithDau() && !negTrack.has_mcPartWithDau()) { + continue; + } + auto mcParticlePos = posTrack.template mcPartWithDau_as(); + auto mcParticleNeg = negTrack.template mcPartWithDau_as(); + if ((mcParticlePos.pdgCode() != kPiPlus && mcParticleNeg.pdgCode() != kPiMinus) && isK0Gun) { + continue; + } + if ((mcParticlePos.pdgCode() != kProton && mcParticleNeg.pdgCode() != kPiMinus) && isLambdaGun) { + continue; + } + } + + histos.fill(HIST("hV0Building"), 2.0); + o2::track::TrackParCov neg = getTrackParCov(negTrack); + Candidate v0cand; + if (!buildDecayCandidateTwoBody(pos, neg, vtx, v0cand)) { + continue; // failed at building candidate + } + + histos.fill(HIST("hV0Building"), 3.0); + + // TODO: not all ACTS tracks have MC association, so this check is not possible for all candidates, fix is needed + // auto mcParticle1 = posTrack.template mcParticle_as(); + // if (mcParticle1.pdgCode() == kK0Short) { + // histos.fill(HIST("hV0Counter"), 0.5); + // } else if (mcParticle1.pdgCode() == kLambda0) { + // histos.fill(HIST("hV0Counter"), 1.5); + // } else if (mcParticle1.pdgCode() == kLambda0Bar) { + // histos.fill(HIST("hV0Counter"), 2.5); + // } else { + // histos.fill(HIST("hV0Counter"), 3.5); + // } + + v0CandidateIndices(collision.globalIndex(), + posTrack.globalIndex(), + negTrack.globalIndex(), + -1); + + v0CandidateCores(v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], + v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2], + v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2], + v0cand.dcaDau, posTrack.dcaXY(), negTrack.dcaXY(), + v0cand.cosPA, v0cand.dcaToPV); + + o2::track::TrackParCov v0(v0cand.posSV, v0cand.p, v0cand.parentTrackCovMatrix, 0); + const float lambdaMassHypothesis = RecoDecay::m(std::array{std::array{v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2]}, + std::array{v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2]}}, + std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + + const float antiLambdaMassHypothesis = RecoDecay::m(std::array{std::array{v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2]}, + std::array{v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2]}}, + std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + + if (!buildCascade) { + continue; // not building cascades, so skip the rest + } + + const bool inLambdaMassWindow = std::abs(lambdaMassHypothesis - o2::constants::physics::MassLambda0) < acceptedLambdaMassWindow; + const bool inAntiLambdaMassWindow = std::abs(antiLambdaMassHypothesis - o2::constants::physics::MassLambda0) < acceptedLambdaMassWindow; + if (!inLambdaMassWindow && !inAntiLambdaMassWindow) { + continue; // Likely not a lambda, should not be considered for cascade building + } + + for (const auto& bachTrack : bachTracksGrouped) { + if (bachTrack.globalIndex() == posTrack.globalIndex() || bachTrack.globalIndex() == negTrack.globalIndex()) { + continue; // avoid using any track that was already used + } + + histos.fill(HIST("hCascadeBuilding"), 1.0); + if (inLambdaMassWindow && bachTrack.sign() > 0) { + continue; // only consider lambda and neg bach track + } + + if (inAntiLambdaMassWindow && bachTrack.sign() < 0) { + continue; // only consider anti-lambda and pos bach track + } + + histos.fill(HIST("hCascadeBuilding"), 2.0); + + // TODO mc same mother check + + Candidate cascCand; + o2::track::TrackParCov bach = getTrackParCov(bachTrack); + if (!buildDecayCandidateTwoBody(v0, bach, vtx, cascCand)) { + continue; // failed at building candidate + } + histos.fill(HIST("hCascadeBuilding"), 3.0); + + const float massXi = RecoDecay::m(std::array{std::array{cascCand.pDau0[0], cascCand.pDau0[1], cascCand.pDau0[2]}, + std::array{cascCand.pDau1[0], cascCand.pDau1[1], cascCand.pDau1[2]}}, + std::array{o2::constants::physics::MassLambda, o2::constants::physics::MassPionCharged}); + + const float massOm = RecoDecay::m(std::array{std::array{cascCand.pDau0[0], cascCand.pDau0[1], cascCand.pDau0[2]}, + std::array{cascCand.pDau1[0], cascCand.pDau1[1], cascCand.pDau1[2]}}, + std::array{o2::constants::physics::MassLambda, o2::constants::physics::MassKaonCharged}); + + const float dcaPosToPV = calculateDCAStraightToPV(posTrack.x(), posTrack.y(), posTrack.z(), + posTrack.px(), posTrack.py(), posTrack.pz(), + vtx[0], vtx[1], vtx[2]); + + const float dcaNegToPV = calculateDCAStraightToPV(negTrack.x(), negTrack.y(), negTrack.z(), + negTrack.px(), negTrack.py(), negTrack.pz(), + vtx[0], vtx[1], vtx[2]); + + const float dcaBachToPV = calculateDCAStraightToPV(bachTrack.x(), bachTrack.y(), bachTrack.z(), + bachTrack.px(), bachTrack.py(), bachTrack.pz(), + vtx[0], vtx[1], vtx[2]); + + tableCascadeIndices(0, // cascade index, dummy value + posTrack.globalIndex(), + negTrack.globalIndex(), + bachTrack.globalIndex(), + collision.globalIndex()); + + tableCascadeCores(bachTrack.sign(), massXi, massOm, + cascCand.posSV[0], cascCand.posSV[1], cascCand.posSV[2], + v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], + v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2], + v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2], + cascCand.pDau1[0], cascCand.pDau1[1], cascCand.pDau1[2], + cascCand.p[0], cascCand.p[1], cascCand.p[2], + v0cand.dcaDau, cascCand.dcaDau, + dcaPosToPV, dcaNegToPV, dcaBachToPV, + cascCand.dcaToPV, cascCand.dcaToPV); + } // end bachTrack + } // end negTrack + } // end posTrack + } + + void processMCTrueFromACTS(aod::McCollision const& collision, Alice3MCParticles const&) + { + + auto negativeMCParticlesGrouped = negativeMCParticles->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + auto positiveMCParticlesGrouped = positiveMCParticles->sliceByCached(aod::mcparticle::mcCollisionId, collision.globalIndex(), cache); + const std::array vtx = {collision.posX(), collision.posY(), collision.posZ()}; + + float radiusPos = 0.0f; + float radiusNeg = 0.0f; + bool isK0s = false; + bool isLambda = false; + bool isAntiLambda = false; + int iPosPart = 0; + for (auto const& posParticle : positiveMCParticlesGrouped) { + radiusPos = std::hypot(posParticle.vx(), posParticle.vy()); + histos.fill(HIST("hRadiusVsHitsPos"), radiusPos, posParticle.nHits()); + for (auto const& negParticle : negativeMCParticlesGrouped) { + if (negParticle.pdgCode() != kPiMinus && negParticle.pdgCode() != kProtonBar) { + continue; + } + radiusNeg = std::hypot(negParticle.vx(), negParticle.vy()); + if (iPosPart == 0) { + histos.fill(HIST("hRadiusVsHitsNeg"), radiusNeg, negParticle.nHits()); + } + if (radiusPos == radiusNeg) { + isK0s = (posParticle.pdgCode() == kPiPlus && negParticle.pdgCode() == kPiMinus); + isLambda = (posParticle.pdgCode() == kProton && negParticle.pdgCode() == kPiMinus); + isAntiLambda = (posParticle.pdgCode() == kPiPlus && negParticle.pdgCode() == kProtonBar); + if (isK0s || isLambda || isAntiLambda) { + if (!isK0s && isK0Gun) + continue; + if (!isLambda && isLambdaGun) + continue; + Candidate v0cand; + std::vector v0DecayVertex; + v0DecayVertex.push_back(negParticle.vx()); + v0DecayVertex.push_back(negParticle.vy()); + v0DecayVertex.push_back(negParticle.vz()); + TLorentzVector posLorVector = {posParticle.px(), posParticle.py(), posParticle.pz(), posParticle.e()}; + TLorentzVector negLorVector = {negParticle.px(), negParticle.py(), negParticle.pz(), negParticle.e()}; + o2::track::TrackParCov posParCov; + o2::track::TrackParCov negParCov; + o2::upgrade::convertTLorentzVectorToO2Track(1, posLorVector, v0DecayVertex, posParCov); + o2::upgrade::convertTLorentzVectorToO2Track(-1, negLorVector, v0DecayVertex, negParCov); + if (!buildDecayCandidateTwoBody(posParCov, negParCov, vtx, v0cand)) + continue; + v0CandidateIndices(collision.globalIndex(), + posParticle.globalIndex(), + negParticle.globalIndex(), + 0); + v0CandidateCores(v0cand.posSV[0], v0cand.posSV[1], v0cand.posSV[2], + v0cand.pDau0[0], v0cand.pDau0[1], v0cand.pDau0[2], + v0cand.pDau1[0], v0cand.pDau1[1], v0cand.pDau1[2], + v0cand.dcaDau, 0, 0, + v0cand.cosPA, v0cand.dcaToPV); + if (isK0s) { + histos.fill(HIST("hV0Counter"), 0.5); + } else if (isLambda) { + histos.fill(HIST("hV0Counter"), 1.5); + } else if (isAntiLambda) { + histos.fill(HIST("hV0Counter"), 2.5); + } else { + histos.fill(HIST("hV0Counter"), 3.5); + } + } + } + } + iPosPart++; + } + } + // void processFindV0CandidateWithPid(aod::Collision const& collision, aod::McParticles const& mcParticles, Alice3TracksWPid const&) + // { + // auto negativeSecondaryPionsGrouped = negativeSecondaryPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + // auto positiveSecondaryPionsGrouped = positiveSecondaryPions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + // auto secondaryProtonsGrouped = secondaryProtons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + // auto secondaryAntiProtonsGrouped = secondaryAntiProtons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + // } + + void processFindV0CandidateACTS(aod::Collision const& collision, Alice3TracksACTS const&, aod::McParticles const&) + { + auto negTracksGrouped = negativeSecondaryTracksACTS->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto posTracksGrouped = positiveSecondaryTracksACTS->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto bachTracksGrouped = bachelorTracksACTS->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + processFindV0CandidateNoPid(collision, negTracksGrouped, posTracksGrouped, bachTracksGrouped); + } + + void processFindV0CandidateOTF(aod::Collision const& collision, Alice3TracksOTF const&, aod::McPartWithDaus const&) + { + auto negTracksGrouped = negativeSecondaryTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto posTracksGrouped = positiveSecondaryTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto bachTracksGrouped = bachelorTracksOTF->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + processFindV0CandidateNoPid(collision, negTracksGrouped, posTracksGrouped, bachTracksGrouped); + } + + PROCESS_SWITCH(Alice3strangenessFinder, processGenerated, "process generated information", true); + PROCESS_SWITCH(Alice3strangenessFinder, processFindV0CandidateACTS, "find V0 without PID from ACTS reconstruction", true); + PROCESS_SWITCH(Alice3strangenessFinder, processFindV0CandidateOTF, "find V0 without PID from OTF simulations", false); + PROCESS_SWITCH(Alice3strangenessFinder, processMCTrueFromACTS, "process MC truth from ACTS", false); + // PROCESS_SWITCH(alice3strangenessFinder, processFindV0CandidateWithPid, "find V0 with PID", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/Tasks/CMakeLists.txt b/ALICE3/Tasks/CMakeLists.txt index f1158275ec8..822d407221f 100644 --- a/ALICE3/Tasks/CMakeLists.txt +++ b/ALICE3/Tasks/CMakeLists.txt @@ -60,7 +60,7 @@ o2physics_add_dpl_workflow(alice3-taskcorrelationddbar COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(alice3-multicharm - SOURCES alice3-multicharm.cxx + SOURCES alice3Multicharm.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) @@ -84,12 +84,17 @@ o2physics_add_dpl_workflow(alice3-pid-evaluation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(alice3-strangeness - SOURCES alice3-strangeness.cxx +o2physics_add_dpl_workflow(alice3strangeness + SOURCES alice3Strangeness.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(alice3-dq-efficiency + SOURCES alice3-dq-efficiency.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(alice3-decayer-qa - SOURCES alice3DecayerQA.cxx + SOURCES alice3DecayerQa.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/ALICE3/Tasks/ECALqa.cxx b/ALICE3/Tasks/ECALqa.cxx index 5e337cefdbd..73a73ca32a3 100644 --- a/ALICE3/Tasks/ECALqa.cxx +++ b/ALICE3/Tasks/ECALqa.cxx @@ -16,16 +16,24 @@ /// \brief Task to use the ALICE3 ECAL table /// -// O2 includes #include "ALICE3/DataModel/ECAL.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; -using namespace o2::track; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/ALICE3/Tasks/alice3-cdeuteron.cxx b/ALICE3/Tasks/alice3-cdeuteron.cxx index c3c67e2efdb..6dc574189f2 100644 --- a/ALICE3/Tasks/alice3-cdeuteron.cxx +++ b/ALICE3/Tasks/alice3-cdeuteron.cxx @@ -12,18 +12,30 @@ /// \author Nicolo' Jacazio , CERN /// \author Alexander Kalweit , CERN -// O2 includes -#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/PIDResponseTOF.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/ALICE3/Tasks/alice3-dilepton.cxx b/ALICE3/Tasks/alice3-dilepton.cxx index ae86516f95a..099e6205262 100644 --- a/ALICE3/Tasks/alice3-dilepton.cxx +++ b/ALICE3/Tasks/alice3-dilepton.cxx @@ -14,6 +14,7 @@ /// \author s.scheid@cern.ch, daiki.sekihata@cern.ch /// +#include "ALICE3/DataModel/OTFCollision.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFTOF.h" #include "ALICE3/DataModel/tracksAlice3.h" @@ -22,12 +23,23 @@ #include #include #include +#include #include +#include #include +#include +#include +#include +#include #include -#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include #include using namespace o2; @@ -54,6 +66,8 @@ struct Alice3Dilepton { SliceCache cache_mc; SliceCache cache_rec; + Service inspdg; + Configurable pdg{"pdg", 11, "pdg code for analysis. dielectron:11, dimuon:13"}; Configurable requireHFEid{"requireHFEid", true, "Require HFE identification for both leptons"}; Configurable ptMin{"pt-min", 0.f, "Lower limit in pT"}; @@ -68,6 +82,7 @@ struct Alice3Dilepton { Configurable nSigmaPionCutInnerTOF{"nSigmaPionCutInnerTOF", 3., "Pion exclusion in inner TOF"}; Configurable nSigmaElectronRich{"nSigmaElectronRich", 3., "Electron inclusion RICH"}; Configurable nSigmaPionRich{"nSigmaPionRich", 3., "Pion exclusion RICH"}; + Configurable otfConfig{"otfConfig", 0, "OTF configuration flag"}; HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -88,68 +103,73 @@ struct Alice3Dilepton { const AxisSpec axisPrody{2000, -100, 100, "Prod. Vertex Y (cm)"}; const AxisSpec axisProdz{2000, -100, 100, "Prod. Vertex Z (cm)"}; - registry.add("Generated/Event/VtxX", "Vertex X", kTH1F, {axisVx}); - registry.add("Generated/Event/VtxY", "Vertex Y", kTH1F, {axisVy}); - registry.add("Generated/Event/VtxZ", "Vertex Z", kTH1F, {axisVz}); - registry.add("Generated/Particle/Pt", "Particle Pt", kTH1F, {axisPt}); - registry.add("Generated/Particle/Eta", "Particle Eta", kTH1F, {axisEta}); - registry.add("Generated/Particle/Phi", "Particle Phi", kTH1F, {axisPhi}); - registry.add("Generated/Particle/Eta_Pt", "Eta vs. Pt", kTH2F, {axisPt, axisEta}, true); - registry.add("Generated/Particle/prodVx", "Particle Prod. Vertex X", kTH1F, {axisProdx}); - registry.add("Generated/Particle/prodVy", "Particle Prod. Vertex Y", kTH1F, {axisPrody}); - registry.add("Generated/Particle/prodVz", "Particle Prod. Vertex Z", kTH1F, {axisProdz}); - registry.add("Generated/Particle/ParticlesPerEvent", "Particles per event", kTH1F, {{100, 0, 100}}); - - registry.add("Generated/Pair/ULS/Tried", "Pair tries", kTH1F, {{10, -0.5, 9.5}}); - registry.add("Generated/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("Generated/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("Generated/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("Generated/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("Generated/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); - - registry.addClone("Generated/Pair/ULS/", "Generated/Pair/LSpp/"); - registry.addClone("Generated/Pair/ULS/", "Generated/Pair/LSnn/"); - - registry.add("Reconstructed/Event/VtxX", "Vertex X", kTH1F, {axisVx}); - registry.add("Reconstructed/Event/VtxY", "Vertex Y", kTH1F, {axisVy}); - registry.add("Reconstructed/Event/VtxZ", "Vertex Z", kTH1F, {axisVz}); - - registry.add("Reconstructed/Track/Pt", "Track Pt", kTH1F, {axisPt}); - registry.add("Reconstructed/Track/Eta", "Track Eta", kTH1F, {axisEta}); - registry.add("Reconstructed/Track/Phi", "Track Eta", kTH1F, {axisPhi}); - registry.add("Reconstructed/Track/Eta_Pt", "Eta vs. Pt", kTH2F, {axisPt, axisEta}, true); - registry.add("Reconstructed/Track/SigmaOTofvspt", "Track #sigma oTOF", kTH2F, {axisPt, axisSigmaEl}); - registry.add("Reconstructed/Track/SigmaITofvspt", "Track #sigma iTOF", kTH2F, {axisPt, axisSigmaEl}); - registry.add("Reconstructed/Track/SigmaRichvspt", "Track #sigma RICH", kTH2F, {axisPt, axisSigmaEl}); - registry.add("Reconstructed/Track/outerTOFTrackLength", "Track length outer TOF", kTH1F, {axisTrackLengthOuterTOF}); - - registry.addClone("Reconstructed/Track/", "Reconstructed/TrackPID/"); - - registry.add("Reconstructed/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("Reconstructed/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("Reconstructed/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("Reconstructed/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("Reconstructed/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); - - registry.addClone("Reconstructed/Pair/ULS/", "Reconstructed/Pair/LSpp/"); - registry.addClone("Reconstructed/Pair/ULS/", "Reconstructed/Pair/LSnn/"); - - registry.add("ReconstructedFiltered/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("ReconstructedFiltered/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("ReconstructedFiltered/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("ReconstructedFiltered/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("ReconstructedFiltered/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); - - registry.addClone("ReconstructedFiltered/Pair/ULS/", "ReconstructedFiltered/Pair/LSpp/"); - registry.addClone("ReconstructedFiltered/Pair/ULS/", "ReconstructedFiltered/Pair/LSnn/"); - - HistogramConfigSpec hs_rec{HistType::kTHnSparseF, {axisM, axisPt, axisDCAxy}, 3}; - registry.add("Reconstructed/Pair/ULS/hs_rec", "", hs_rec); - registry.add("Reconstructed/Pair/LSpp/hs_rec", "", hs_rec); - registry.add("Reconstructed/Pair/LSnn/hs_rec", "", hs_rec); - registry.get(HIST("Reconstructed/Pair/ULS/hs_rec"))->Sumw2(); - registry.get(HIST("Reconstructed/Pair/LSpp/hs_rec"))->Sumw2(); - registry.get(HIST("Reconstructed/Pair/LSnn/hs_rec"))->Sumw2(); + if (doprocessGen) { + registry.add("Generated/Event/VtxX", "Vertex X", kTH1F, {axisVx}); + registry.add("Generated/Event/VtxY", "Vertex Y", kTH1F, {axisVy}); + registry.add("Generated/Event/VtxZ", "Vertex Z", kTH1F, {axisVz}); + registry.add("Generated/Particle/Pt", "Particle Pt", kTH1F, {axisPt}); + registry.add("Generated/Particle/Eta", "Particle Eta", kTH1F, {axisEta}); + registry.add("Generated/Particle/Phi", "Particle Phi", kTH1F, {axisPhi}); + registry.add("Generated/Particle/Eta_Pt", "Eta vs. Pt", kTH2F, {axisPt, axisEta}, true); + registry.add("Generated/Particle/prodVx", "Particle Prod. Vertex X", kTH1F, {axisProdx}); + registry.add("Generated/Particle/prodVy", "Particle Prod. Vertex Y", kTH1F, {axisPrody}); + registry.add("Generated/Particle/prodVz", "Particle Prod. Vertex Z", kTH1F, {axisProdz}); + registry.add("Generated/Particle/ParticlesPerEvent", "Particles per event", kTH1F, {{100, 0, 100}}); + registry.add("Generated/Particle/ParticlesFit", "Charged Particles in Fit acceptance per event", kTH1F, {{15000, 0, 15000}}); + + registry.add("Generated/Pair/ULS/Tried", "Pair tries", kTH1F, {{10, -0.5, 9.5}}); + registry.add("Generated/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); + registry.add("Generated/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); + registry.add("Generated/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); + registry.add("Generated/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); + registry.add("Generated/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); + + registry.addClone("Generated/Pair/ULS/", "Generated/Pair/LSpp/"); + registry.addClone("Generated/Pair/ULS/", "Generated/Pair/LSnn/"); + } + + if (doprocessRec) { + registry.add("Reconstructed/Event/VtxX", "Vertex X", kTH1F, {axisVx}); + registry.add("Reconstructed/Event/VtxY", "Vertex Y", kTH1F, {axisVy}); + registry.add("Reconstructed/Event/VtxZ", "Vertex Z", kTH1F, {axisVz}); + + registry.add("Reconstructed/Track/Pt", "Track Pt", kTH1F, {axisPt}); + registry.add("Reconstructed/Track/Eta", "Track Eta", kTH1F, {axisEta}); + registry.add("Reconstructed/Track/Phi", "Track Phi", kTH1F, {axisPhi}); + registry.add("Reconstructed/Track/Eta_Pt", "Eta vs. Pt", kTH2F, {axisPt, axisEta}, true); + registry.add("Reconstructed/Track/SigmaOTofvspt", "Track #sigma oTOF", kTH2F, {axisPt, axisSigmaEl}); + registry.add("Reconstructed/Track/SigmaITofvspt", "Track #sigma iTOF", kTH2F, {axisPt, axisSigmaEl}); + registry.add("Reconstructed/Track/SigmaRichvspt", "Track #sigma RICH", kTH2F, {axisPt, axisSigmaEl}); + registry.add("Reconstructed/Track/outerTOFTrackLength", "Track length outer TOF", kTH1F, {axisTrackLengthOuterTOF}); + + registry.addClone("Reconstructed/Track/", "Reconstructed/TrackPID/"); + + registry.add("Reconstructed/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); + registry.add("Reconstructed/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); + registry.add("Reconstructed/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); + registry.add("Reconstructed/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); + registry.add("Reconstructed/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); + + registry.addClone("Reconstructed/Pair/ULS/", "Reconstructed/Pair/LSpp/"); + registry.addClone("Reconstructed/Pair/ULS/", "Reconstructed/Pair/LSnn/"); + + registry.add("ReconstructedFiltered/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); + registry.add("ReconstructedFiltered/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); + registry.add("ReconstructedFiltered/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); + registry.add("ReconstructedFiltered/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); + registry.add("ReconstructedFiltered/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); + + registry.addClone("ReconstructedFiltered/Pair/ULS/", "ReconstructedFiltered/Pair/LSpp/"); + registry.addClone("ReconstructedFiltered/Pair/ULS/", "ReconstructedFiltered/Pair/LSnn/"); + + HistogramConfigSpec hs_rec{HistType::kTHnSparseF, {axisM, axisPt, axisDCAxy}, 3}; + registry.add("Reconstructed/Pair/ULS/hs_rec", "", hs_rec); + registry.add("Reconstructed/Pair/LSpp/hs_rec", "", hs_rec); + registry.add("Reconstructed/Pair/LSnn/hs_rec", "", hs_rec); + registry.get(HIST("Reconstructed/Pair/ULS/hs_rec"))->Sumw2(); + registry.get(HIST("Reconstructed/Pair/LSpp/hs_rec"))->Sumw2(); + registry.get(HIST("Reconstructed/Pair/LSnn/hs_rec"))->Sumw2(); + } } template @@ -597,7 +617,19 @@ struct Alice3Dilepton { auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); int nParticlesInEvent = 0; + int nParticlesFIT = 0; for (const auto& mcParticle : mcParticles_per_coll) { + if (mcParticle.isPhysicalPrimary()) { + if ((2.2 < mcParticle.eta() && mcParticle.eta() < 5.0) || (-3.4 < mcParticle.eta() && mcParticle.eta() < -2.3)) { + auto pdgParticle = inspdg->GetParticle(mcParticle.pdgCode()); + if (pdgParticle) { + float charge = pdgParticle->Charge() / 3.f; // Charge in units of |e| + if (std::abs(charge) >= 1.) { + nParticlesFIT++; + } + } + } + } if (std::abs(mcParticle.pdgCode()) != pdg) { continue; } @@ -620,6 +652,7 @@ struct Alice3Dilepton { } // end of mc particle loop registry.fill(HIST("Generated/Particle/ParticlesPerEvent"), nParticlesInEvent); + registry.fill(HIST("Generated/Particle/ParticlesFit"), nParticlesFIT); auto neg_mcParticles_coll = neg_mcParticles->sliceByCached(o2::aod::mcparticle::mcCollisionId, mccollision.globalIndex(), cache_mc); auto pos_mcParticles_coll = pos_mcParticles->sliceByCached(o2::aod::mcparticle::mcCollisionId, mccollision.globalIndex(), cache_mc); @@ -632,6 +665,8 @@ struct Alice3Dilepton { } // end of processGen using MyTracksMC = soa::Join; + using Alice3Collision = soa::Join; + // Filter trackFilter = etaMin < o2::aod::track::eta && // o2::aod::track::eta < etaMax && // ptMin < o2::aod::track::pt && @@ -639,11 +674,13 @@ struct Alice3Dilepton { // o2::aod::track_alice3::isReconstructed == selectReconstructed; Filter trackFilter = o2::aod::track_alice3::isReconstructed == selectReconstructed; using MyFilteredTracksMC = soa::Filtered; + Filter configFilter = (aod::upgrade_collision::lutConfigId == otfConfig); + using MyFilteredAlice3Collision = soa::Filtered; Preslice perCollision = aod::track::collisionId; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; - void processRec(const o2::aod::Collisions& collisions, + void processRec(MyFilteredAlice3Collision const& collisions, MyFilteredTracksMC const& tracks, const o2::aod::McCollisions&, const aod::McParticles& mcParticles) diff --git a/ALICE3/Tasks/alice3-dq-efficiency.cxx b/ALICE3/Tasks/alice3-dq-efficiency.cxx new file mode 100644 index 00000000000..99dcd281727 --- /dev/null +++ b/ALICE3/Tasks/alice3-dq-efficiency.cxx @@ -0,0 +1,2525 @@ +// 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 +// alexander.tiekoetter@cern.ch +// Configurable workflow for running several DQ or other PWG analyses + +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/MCSignal.h" +#include "PWGDQ/Core/MCSignalLibrary.h" +#include "PWGDQ/Core/MixingHandler.h" +#include "PWGDQ/Core/MixingLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGDQ/DataModel/ReducedTablesAlice3.h" + +#include "Common/Core/TableHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::string; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::common::core; + +// Some definitions +namespace o2::aod +{ +namespace dqanalysisflags +{ +DECLARE_SOA_COLUMN(MixingHash, mixingHash, int); //! Hash used in event mixing //need to understand +DECLARE_SOA_BITMAP_COLUMN(IsEventSelected, isEventSelected, 32); //! Event decision +DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelected, isBarrelSelected, 32); //! Barrel track decisions +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(IsBarrelSelectedPrefilter, isBarrelSelectedPrefilter, 32); //! Barrel prefilter decisions (joinable to ReducedA3TracksAssoc) + +DECLARE_SOA_COLUMN(Massee, massee, float); +DECLARE_SOA_COLUMN(Etaee, etaee, float); +DECLARE_SOA_COLUMN(Rapee, rapee, float); +DECLARE_SOA_COLUMN(Phiee, phiee, float); +DECLARE_SOA_COLUMN(Ptee, ptee, float); +DECLARE_SOA_COLUMN(Lxyee, lxyee, float); +DECLARE_SOA_COLUMN(LxyeePoleMass, lxyeepolemass, float); +DECLARE_SOA_COLUMN(Lzee, lzee, float); +DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); +DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0CJPsi2ee, float); +DECLARE_SOA_COLUMN(PercentileFT0M, percentileFT0MJPsi2ee, float); +DECLARE_SOA_COLUMN(MultiplicityNContrib, multiplicityNContribJPsi2ee, float); +DECLARE_SOA_COLUMN(AmbiguousInBunchPairs, AmbiguousJpsiPairsInBunch, bool); +DECLARE_SOA_COLUMN(AmbiguousOutOfBunchPairs, AmbiguousJpsiPairsOutOfBunch, bool); +DECLARE_SOA_COLUMN(Corrassoc, corrassoc, bool); +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); +// Candidate columns efficiency calculation for prompt-non-prompt JPsi separation +DECLARE_SOA_COLUMN(OniaPt, oniaPt, float); +DECLARE_SOA_COLUMN(OniaY, oniaY, float); +DECLARE_SOA_COLUMN(OniaEta, oniaEta, float); +DECLARE_SOA_COLUMN(OniaPhi, oniaPhi, float); +DECLARE_SOA_COLUMN(OniaVz, oniaVz, float); +DECLARE_SOA_COLUMN(OniaVtxZ, oniaVtxZ, float); +} // namespace dqanalysisflags + +DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents +DECLARE_SOA_TABLE(MixingHashes, "AOD", "DQANAMIXHASHA", dqanalysisflags::MixingHash); //! joinable to ReducedEvents +DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected); //! joinable to ReducedA3TracksAssoc +DECLARE_SOA_TABLE(BarrelAmbiguities, "AOD", "DQBARRELAMB", dqanalysisflags::BarrelAmbiguityInBunch, dqanalysisflags::BarrelAmbiguityOutOfBunch); //! joinable to ReducedBarrelTracks +DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); //! joinable to ReducedA3TracksAssoc + +DECLARE_SOA_TABLE(OniaMCTruth, "AOD", "MCTRUTHONIA", dqanalysisflags::OniaPt, dqanalysisflags::OniaEta, dqanalysisflags::OniaY, dqanalysisflags::OniaPhi, dqanalysisflags::OniaVz, dqanalysisflags::OniaVtxZ, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); + +} // namespace o2::aod + +// TODO: USE PROPER TABLES + +using MyEvents = soa::Join; +using MyEventsSelected = soa::Join; +using MyEventsVtxCov = soa::Join; +using MyEventsVtxCovSelected = soa::Join; + +using MyBarrelAssocs = soa::Join; +using MyBarrelAssocsPrefilter = soa::Join; + +using MyBarrelTracks = soa::Join; + +using MyBarrelTracksWithCov = soa::Join; + +using MyBarrelTracksWithCovWithAmbiguities = soa::Join; + +constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::ReducedEvent; +constexpr static uint32_t gkEventFillMapWithCov = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventVtxCov; + +constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; + +// Global function used to define needed histogram classes +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups); // defines histograms for all tasks + +constexpr int TWO_PRONG = 2; +constexpr int THREE_PRONG = 3; + +// Analysis task that produces event decisions and the Hash table used in event mixing +struct AnalysisEventSelection { + Produces eventSel; + Produces hash; + OutputObj fOutputList{"output"}; + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; + Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddEventMCHistogram{"cfgAddEventMCHistogram", "generator", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Add event histograms defined via JSON formatting (see HistogramsLibrary)"}; + + HistogramManager* fHistMan = nullptr; + MixingHandler* fMixHandler = nullptr; + + AnalysisCompositeCut* fEventCut; + + std::map fSelMap; // key: reduced event global index, value: event selection decision + + void init(o2::framework::InitContext& context) + { + if (context.mOptions.get("processDummy")) { + return; + } + VarManager::SetDefaultVarNames(); + + fEventCut = new AnalysisCompositeCut(true); + TString eventCutStr = fConfigEventCuts.value; + if (eventCutStr != "") { + AnalysisCut* cut = dqcuts::GetAnalysisCut(eventCutStr.Data()); + if (cut != nullptr) { + fEventCut->AddCut(cut); + } + } + // Additional cuts via JSON + TString eventCutJSONStr = fConfigEventCutsJSON.value; + if (eventCutJSONStr != "") { + std::vector jsonCuts = dqcuts::GetCutsFromJSON(eventCutJSONStr.Data()); + for (const auto& cutIt : jsonCuts) { + fEventCut->AddCut(cutIt); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + + if (fConfigQA) { + fHistMan = new HistogramManager("analysisHistos", "", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;", fConfigAddEventHistogram.value.data()); + DefineHistograms(fHistMan, "EventsMC", fConfigAddEventMCHistogram.value.data()); + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // aditional histograms via JSON + VarManager::SetUseVars(fHistMan->GetUsedVars()); + 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()); + } + } + } + + void runEventSelection(MyEventsVtxCov const& events, ReducedA3MCEvents const& mcEvents) + { + fSelMap.clear(); + + for (const auto& event : events) { + // Reset the fValues array and fill event observables + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEventAlice3(event); + if (event.has_reducedA3MCEvent()) { + VarManager::FillEventAlice3(event.reducedA3MCEvent()); + } + + bool decision = false; + // if QA is requested fill histograms before event selections + 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); + } + decision = true; + } + fSelMap[event.globalIndex()] = decision; + if (fMixHandler != nullptr) { + int hh = fMixHandler->FindEventCategory(VarManager::fgValues); + hash(hh); + } + } + + for (const auto& event : mcEvents) { + // Reset the fValues array and fill event observables + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEventAlice3(event); + if (fConfigQA) { + fHistMan->FillHistClass("EventsMC", VarManager::fgValues); + } + } + } + + void publishSelections(MyEventsVtxCov const& events) + { + // publish the table + uint32_t evSel = static_cast(0); + for (const auto& event : events) { + evSel = 0; + if (fSelMap[event.globalIndex()]) { // event passed the user cuts + evSel |= (static_cast(1) << 0); + } + eventSel(evSel); + } + } + + void processSkimmed(MyEventsVtxCov const& events, aod::ReducedA3MCEvents const& mcEvents) + { + runEventSelection(events, mcEvents); + publishSelections(events); + } + + void processDummy(MyEventsVtxCov const&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisEventSelection, processSkimmed, "Run event selection on DQ skimmed events", false); + PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", true); +}; + +// Produces a table with barrel track decisions (joinable to the ReducedA3TracksAssociations) +// Here one should add all the track cuts needed through the workflow (e.g. cuts for same-even pairing, electron prefiltering, track for dilepton-track correlations) +struct AnalysisTrackSelection { + Produces trackSel; + Produces trackAmbiguities; + OutputObj fOutputList{"output"}; + + Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigCutsJSON{"cfgBarrelTrackCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + Configurable fConfigPublishAmbiguity{"cfgPublishAmbiguity", true, "If true, publish ambiguity table and fill QA histograms"}; + + Configurable fConfigMCSignals{"cfgTrackMCSignals", "", "Comma separated list of MC signals"}; + Configurable fConfigMCSignalsJSON{"cfgTrackMCsignalsJSON", "", "Additional list of MC signals via JSON"}; + + HistogramManager* fHistMan; + std::vector fTrackCuts; + std::vector fMCSignals; // list of signals to be checked + std::vector fHistNamesReco; + std::vector fHistNamesMCMatched; + + 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) + + void init(o2::framework::InitContext& context) + { + if (context.mOptions.get("processDummy")) { + return; + } + VarManager::SetDefaultVarNames(); + + TString cutNamesStr = fConfigCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fTrackCuts.push_back(dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + // add extra cuts from JSON + TString addTrackCutsStr = fConfigCutsJSON.value; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (const auto& t : addTrackCuts) { + fTrackCuts.push_back(reinterpret_cast(t)); + } + } + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + + TString configSigNamesStr = fConfigMCSignals.value; + std::unique_ptr sigNamesArray(configSigNamesStr.Tokenize(",")); + // Setting the MC signals + 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 + continue; + } + fMCSignals.push_back(sig); + } + } + // Add the MCSignals from the JSON config + TString addMCSignalsStr = fConfigMCSignalsJSON.value; + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + for (const auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() != 1) { // NOTE: only 1 prong signals + continue; + } + fMCSignals.push_back(mcIt); + } + } + + if (fConfigQA) { + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Configure histogram classes for each track cut; + // Add histogram classes for each track cut and for each requested MC signal (reconstructed tracks with MC truth) + TString histClasses = "AssocsBarrel_BeforeCuts;"; + for (const auto& cut : fTrackCuts) { + TString nameStr = Form("AssocsBarrel_%s", cut->GetName()); + fHistNamesReco.push_back(nameStr); + histClasses += Form("%s;", nameStr.Data()); + for (const auto& sig : fMCSignals) { + TString nameStr2 = Form("AssocsCorrectBarrel_%s_%s", cut->GetName(), sig->GetName()); + fHistNamesMCMatched.push_back(nameStr2); + histClasses += Form("%s;", nameStr2.Data()); + nameStr2 = Form("AssocsIncorrectBarrel_%s_%s", cut->GetName(), sig->GetName()); + fHistNamesMCMatched.push_back(nameStr2); + histClasses += Form("%s;", nameStr2.Data()); + } + } + + DefineHistograms(fHistMan, histClasses.Data(), fConfigAddTrackHistogram.value.data()); + if (fConfigPublishAmbiguity) { + DefineHistograms(fHistMan, "TrackBarrel_AmbiguityInBunch;TrackBarrel_AmbiguityOutOfBunch;", "ambiguity"); + } + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + } + + void runTrackSelection(ReducedA3TracksAssoc const& assocs, MyEventsVtxCovSelected const& /*events*/, MyBarrelTracksWithCov const& tracks, ReducedA3MCEvents const& /*eventsMC*/, ReducedA3MCTracks const& tracksMC) + { + fNAssocsInBunch.clear(); + fNAssocsOutOfBunch.clear(); + + trackSel.reserve(assocs.size()); + trackAmbiguities.reserve(tracks.size()); + + // Loop over associations + for (const auto& assoc : assocs) { + auto event = assoc.template reducedA3event_as(); + if (!event.isEventSelected_bit(0)) { + trackSel(0); + continue; + } + + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + // fill event information which might be needed in histograms/cuts that combine track and event properties + VarManager::FillEventAlice3(event); + if (event.has_reducedA3MCEvent()) { + VarManager::FillEventAlice3(event.reducedA3MCEvent()); + } + + auto track = assoc.template reducedA3track_as(); + VarManager::FillTrackAlice3(track); + // compute quantities which depend on the associated collision, such as DCA + VarManager::FillTrackCollision(track, event); + + bool isCorrectAssoc = false; + if (track.has_reducedA3MCTrack()) { + auto trackMC = track.reducedA3MCTrack(); + auto eventMCfromTrack = trackMC.reducedA3MCEvent(); + if (event.has_reducedA3MCEvent()) { + isCorrectAssoc = (eventMCfromTrack.globalIndex() == event.reducedA3MCEvent().globalIndex()); + } + VarManager::FillTrackMC(tracksMC, trackMC); + VarManager::FillResolutions(trackMC, track); + } + + if (fConfigQA) { + fHistMan->FillHistClass("AssocsBarrel_BeforeCuts", VarManager::fgValues); + } + + int iCut = 0; + uint32_t filterMap = static_cast(0); + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, iCut++) { + if ((*cut)->IsSelected(VarManager::fgValues)) { + filterMap |= (static_cast(1) << iCut); + if (fConfigQA) { + fHistMan->FillHistClass(fHistNamesReco[iCut], VarManager::fgValues); + } + } + } // end loop over cuts + trackSel(filterMap); + + // compute MC matching decisions and fill histograms for matched associations + int isig = 0; + if (filterMap > 0 && track.has_reducedA3MCTrack()) { + // loop over all MC signals + for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { + // check if this MC signal is matched + if ((*sig)->CheckSignal(true, track.reducedA3MCTrack())) { + // mcDecision |= (static_cast(1) << isig); + // loop over cuts and fill histograms for the cuts that are fulfilled + for (unsigned int icut = 0; icut < fTrackCuts.size(); icut++) { + if (filterMap & (static_cast(1) << icut)) { + if (isCorrectAssoc) { + fHistMan->FillHistClass(fHistNamesMCMatched[icut * 2 * fMCSignals.size() + 2 * isig].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(fHistNamesMCMatched[icut * 2 * fMCSignals.size() + 2 * isig + 1].Data(), VarManager::fgValues); + } + } + } // end loop over cuts + } + } + } // end if (filterMap > 0) + + // count the number of associations per track + if (fConfigPublishAmbiguity && filterMap > 0) { + if (event.isEventSelected_bit(1)) { + // for this track, count the number of associated collisions with in-bunch pileup and out of bunch associations + 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 associations + + // QA the collision-track associations + // TODO: some tracks can be associated to both collisions that have in bunch pileup and collisions from different bunches + // So one could QA these tracks separately + if (fConfigPublishAmbiguity) { + if (fConfigQA) { + for (const auto& [trackIdx, evIndices] : fNAssocsInBunch) { + if (evIndices.size() == 1) { + continue; + } + auto track = tracks.rawIteratorAt(trackIdx); + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + VarManager::FillTrackAlice3(track); + VarManager::fgValues[VarManager::kBarrelNAssocsInBunch] = static_cast(evIndices.size()); + fHistMan->FillHistClass("TrackBarrel_AmbiguityInBunch", VarManager::fgValues); + } // end loop over in-bunch ambiguous tracks + + for (const auto& [trackIdx, evIndices] : fNAssocsOutOfBunch) { + if (evIndices.size() == 1) { + continue; + } + auto track = tracks.rawIteratorAt(trackIdx); + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + VarManager::FillTrackAlice3(track); + VarManager::fgValues[VarManager::kBarrelNAssocsOutOfBunch] = static_cast(evIndices.size()); + fHistMan->FillHistClass("TrackBarrel_AmbiguityOutOfBunch", VarManager::fgValues); + } // end loop over out-of-bunch ambiguous tracks + } + + // publish the ambiguity table + for (const auto& track : tracks) { + 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(); + } + trackAmbiguities(nInBunch, nOutOfBunch); + } + } + } // end runTrackSelection() + + void processSkimmedWithCov(ReducedA3TracksAssoc const& assocs, MyEventsVtxCovSelected const& events, MyBarrelTracksWithCov const& tracks, ReducedA3MCEvents const& eventsMC, ReducedA3MCTracks const& tracksMC) + { + runTrackSelection(assocs, events, tracks, eventsMC, tracksMC); + } + + void processDummy(MyEvents const&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisTrackSelection, processSkimmedWithCov, "Run barrel track selection on DQ skimmed tracks w/ cov matrix associations", false); + PROCESS_SWITCH(AnalysisTrackSelection, processDummy, "Dummy function", true); +}; + +struct AnalysisPrefilterSelection { + Produces prefilter; // joinable with ReducedA3TracksAssoc + + // Configurables + 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", false, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; + + std::map fPrefilterMap; + AnalysisCompositeCut* fPairCut; + uint32_t fPrefilterMask; + int fPrefilterCutBit; + + PresliceUnsorted trackAssocsPerCollision = aod::reducedA3track_association::reducedA3eventId; + + void init(o2::framework::InitContext& context) + { + if (context.mOptions.get("processDummy")) { + return; + } + + bool runPrefilter = true; + // get the list of track cuts to be prefiltered + TString trackCutsStr = fConfigTrackCuts.value; + TObjArray* objArrayTrackCuts = nullptr; + if (!trackCutsStr.IsNull()) { + objArrayTrackCuts = trackCutsStr.Tokenize(","); + if (objArrayTrackCuts == nullptr) { + runPrefilter = false; + } + } else { + LOG(warn) << " No track cuts to prefilter! Prefilter will not be run"; + runPrefilter = false; + } + // get the cut to be used as loose selection + TString prefilterTrackCutStr = fConfigPrefilterTrackCut.value; + if (prefilterTrackCutStr.IsNull()) { + LOG(warn) << " No prefilter loose selection specified! Prefilter will not be run"; + runPrefilter = false; + } + + fPrefilterMask = 0; + fPrefilterCutBit = -1; + if (runPrefilter) { + // get the list of cuts that were computed in the barrel track-selection task and create a bit mask + // to mark just the ones we want to apply a prefilter on + string trackCuts; + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", trackCuts, false); + TString allTrackCutsStr = trackCuts; + // check also the cuts added via JSON and add them to the string of cuts + getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", trackCuts, false); + TString addTrackCutsStr = trackCuts; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (const auto& t : addTrackCuts) { + allTrackCutsStr += Form(",%s", t->GetName()); + } + } + + std::unique_ptr objArray(allTrackCutsStr.Tokenize(",")); + if (objArray == nullptr) { + LOG(fatal) << " Not getting any track cuts from the barrel-track-selection "; + } + if (objArray->FindObject(prefilterTrackCutStr.Data()) == nullptr) { + LOG(fatal) << " Prefilter track cut not among the cuts calculated by the track-selection task! "; + } + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + if (objArrayTrackCuts->FindObject(tempStr.Data()) != nullptr) { + fPrefilterMask |= (static_cast(1) << icut); + } + if (tempStr.CompareTo(fConfigPrefilterTrackCut.value) == 0) { + fPrefilterCutBit = icut; + } + } + // setup the prefilter pair cut + fPairCut = new AnalysisCompositeCut(true); + TString pairCutStr = fConfigPrefilterPairCut.value; + if (!pairCutStr.IsNull()) { + fPairCut = dqcuts::GetCompositeCut(pairCutStr.Data()); + } + } + if (fPrefilterMask == static_cast(0) || fPrefilterCutBit < 0) { + LOG(warn) << "No specified loose cut or track cuts for prefiltering. This task will do nothing."; + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetDefaultVarNames(); + + VarManager::SetupTwoProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, true); // TODO: get these parameters from Configurables + VarManager::SetupTwoProngFwdDCAFitter(5.0f, true, 200.0f, 1.0e-3f, 0.9f, true); + } + + void runPrefilter(MyEvents::iterator const& event, MyBarrelAssocs const& assocs, MyBarrelTracks const& /*tracks*/) + { + if (fPrefilterCutBit < 0 || fPrefilterMask == 0) { + return; + } + + for (const auto& [assoc1, assoc2] : o2::soa::combinations(assocs, assocs)) { + auto track1 = assoc1.template reducedA3track_as(); + auto track2 = assoc2.template reducedA3track_as(); + + // NOTE: here we restrict to just pairs of opposite sign (conversions), but in principle this can be made + // a configurable and check also same-sign pairs (track splitting) + if (track1.sign() * track2.sign() > 0) { + continue; + } + + // here we check the cuts fulfilled by both tracks, for both the tight and loose selections + uint32_t track1Candidate = (assoc1.isBarrelSelected_raw() & fPrefilterMask); + uint32_t track2Candidate = (assoc2.isBarrelSelected_raw() & fPrefilterMask); + bool track1Loose = assoc1.isBarrelSelected_bit(fPrefilterCutBit); + bool track2Loose = assoc2.isBarrelSelected_bit(fPrefilterCutBit); + + if (!((track1Candidate > 0 && track2Loose) || (track2Candidate > 0 && track1Loose))) { + continue; + } + + // compute pair quantities + VarManager::FillPairAlice3(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) { + fPrefilterMap[track1.globalIndex()] = track1Candidate; + } + if (fPrefilterMap.find(track2.globalIndex()) == fPrefilterMap.end() && track2Candidate > 0) { + fPrefilterMap[track2.globalIndex()] = track2Candidate; + } + } + } // end loop over combinations + } + + void processBarrelSkimmed(MyEvents const& events, MyBarrelAssocs const& assocs, MyBarrelTracks const& tracks) + { + + fPrefilterMap.clear(); + + for (const auto& event : events) { + auto groupedAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); + if (groupedAssocs.size() > 1) { + runPrefilter(event, groupedAssocs, tracks); + } + } + + uint32_t mymap = -1; + // If cuts were not configured, then produce a map with all 1's and publish it for all associations + if (fPrefilterCutBit < 0 || fPrefilterMask == 0) { + for (int i = 0; i < assocs.size(); ++i) { + prefilter(mymap); + } + } else { + for (const auto& assoc : assocs) { + // TODO: just use the index from the assoc (no need to cast the whole track) + auto track = assoc.template reducedA3track_as(); + mymap = -1; + if (fPrefilterMap.find(track.globalIndex()) != fPrefilterMap.end()) { + // NOTE: publish the bitwise negated bits (~), so there will be zeroes for cuts that failed the prefiltering and 1 everywhere else + mymap = ~fPrefilterMap[track.globalIndex()]; + prefilter(mymap); + } else { + prefilter(mymap); // track did not pass the prefilter selections, so publish just 1's + } + } + } + } + + void processDummy(MyEvents const&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisPrefilterSelection, processBarrelSkimmed, "Run Prefilter selection on reduced tracks", false); + PROCESS_SWITCH(AnalysisPrefilterSelection, processDummy, "Do nothing", true); +}; + +// Run the same-event pairing +// This task assumes that both legs of the resonance fulfill the same cuts (symmetric decay channel) +// Runs combinatorics for barrel-barrel combinations +// The task implements also process functions for running event mixing +struct AnalysisSameEventPairing { + + Produces dielectronList; + Produces dielectronsExtraList; + Produces dielectronAllList; + Produces MCTruthTableEffi; + + o2::base::MatLayerCylSet* fLUT = nullptr; + OutputObj fOutputList{"output"}; + + struct : ConfigurableGroup { + Configurable track{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable pair{"cfgPairCuts", "", "Comma separated list of pair cuts, !!! Use only if you know what you are doing, otherwise leave empty"}; + Configurable MCgenAcc{"cfgMCGenAccCut", "", "cut for MC generated particles acceptance"}; + // TODO: Add pair cuts via JSON + } fConfigCuts; + + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + + struct : ConfigurableGroup { + Configurable flatTables{"cfgFlatTables", false, "Produce a single flat tables with all relevant information of the pairs and single tracks"}; + Configurable propToPCA{"cfgPropToPCA", false, "Propagate tracks to secondary vertex"}; + Configurable collisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; + Configurable centerMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; + } fConfigOptions; + + struct : ConfigurableGroup { + Configurable genSignals{"cfgBarrelMCGenSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable genSignalsJSON{"cfgMCGenSignalsJSON", "", "Additional list of MC signals (generated) via JSON"}; + Configurable recSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable recSignalsJSON{"cfgMCRecSignalsJSON", "", "Comma separated list of MC signals (reconstructed) via JSON"}; + Configurable skimSignalOnly{"cfgSkimSignalOnly", false, "Configurable to select only matched candidates"}; + } fConfigMC; + + // Track related options + Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; + + // Filter filterEventSelected = aod::dqanalysisflags::isEventSelected & uint32_t(1); + Filter eventFilter = aod::dqanalysisflags::isEventSelected > static_cast(0); + + HistogramManager* fHistMan; + + // keep histogram class names in maps, so we don't have to buld their names in the pair loops + std::map> fTrackHistNames; + std::map> fBarrelHistNamesMCmatched; + std::vector fRecMCSignals; + std::vector fGenMCSignals; + + std::vector fPairCuts; + AnalysisCompositeCut fMCGenAccCut; + bool fUseMCGenAccCut = false; + + uint32_t fTrackFilterMask; // mask for the track cuts required in this task to be applied on the barrel cuts produced upstream + int fNCutsBarrel; + int fNPairCuts; + bool fHasTwoProngGenMCsignals = false; + + bool fEnableBarrelHistos; + + PresliceUnsorted trackAssocsPerCollision = aod::reducedA3track_association::reducedA3eventId; + + void init(o2::framework::InitContext& context) + { + if (context.mOptions.get("processDummy")) { + return; + } + bool isMCGen = context.mOptions.get("processMCGen") || context.mOptions.get("processMCGenWithGrouping") || context.mOptions.get("processBarrelOnlySkimmed"); + VarManager::SetDefaultVarNames(); + + fEnableBarrelHistos = context.mOptions.get("processBarrelOnlySkimmed"); + + // Keep track of all the histogram class names to avoid composing strings in the pairing loop + TString histNames = ""; + TString cutNamesStr = fConfigCuts.pair.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fPairCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + + // get the list of cuts for tracks, check that they were played by the barrel selection tasks + // and make a mask for active cuts (barrel selection tasks may run more cuts, needed for other analyses) + TString trackCutsStr = fConfigCuts.track.value; + TObjArray* objArrayTrackCuts = nullptr; + if (!trackCutsStr.IsNull()) { + objArrayTrackCuts = trackCutsStr.Tokenize(","); + } + + // Setting the MC rec signal names + TString sigNamesStr = fConfigMC.recSignals.value; + std::unique_ptr objRecSigArray(sigNamesStr.Tokenize(",")); + for (int isig = 0; isig < objRecSigArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objRecSigArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required + continue; + } + fRecMCSignals.push_back(sig); + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsStr = fConfigMC.recSignalsJSON.value; + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + for (const auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() != TWO_PRONG) { // NOTE: only 2 prong signals + continue; + } + fRecMCSignals.push_back(mcIt); + } + } + + // get the barrel track selection cuts + string tempCuts; + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempCuts, false); + TString tempCutsStr = tempCuts; + // check also the cuts added via JSON and add them to the string of cuts + getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", tempCuts, false); + TString addTrackCutsStr = tempCuts; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (const auto& t : addTrackCuts) { + tempCutsStr += Form(",%s", t->GetName()); + } + } + + // get the mc generated acceptance cut + TString mcGenAccCutStr = fConfigCuts.MCgenAcc.value; + if (mcGenAccCutStr != "") { + AnalysisCut* cut = dqcuts::GetAnalysisCut(mcGenAccCutStr.Data()); + if (cut != nullptr) { + fMCGenAccCut.AddCut(cut); + } + fUseMCGenAccCut = true; + } + + // check that the barrel track cuts array required in this task is not empty + if (!trackCutsStr.IsNull()) { + // tokenize and loop over the barrel cuts produced by the barrel track selection task + std::unique_ptr objArray(tempCutsStr.Tokenize(",")); + fNCutsBarrel = objArray->GetEntries(); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + // if the current barrel selection cut is required in this task, then switch on the corresponding bit in the mask + // and assign histogram directories + if (objArrayTrackCuts->FindObject(tempStr.Data()) != nullptr) { + fTrackFilterMask |= (static_cast(1) << icut); + + if (fEnableBarrelHistos) { + // assign the pair hist directories for the current cut + std::vector names = { + Form("PairsBarrelSEPM_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEMM_%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 (const auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fTrackHistNames[icut] = names; + + // if there are pair cuts specified, assign hist directories for each barrel cut - pair cut combination + // NOTE: This could possibly lead to large histogram outputs. It is strongly advised to use pair cuts only + // if you know what you are doing. + TString cutNamesStr = fConfigCuts.pair.value; + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + fNPairCuts = objArrayPair->GetEntries(); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + names = { + Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsBarrelSEPP_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsBarrelSEMM_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + // NOTE: In the numbering scheme for the map key, we use the number of barrel cuts in the barrel-track selection task + fTrackHistNames[fNCutsBarrel + icut * fNPairCuts + iPairCut] = names; + } // end loop (pair cuts) + } // end if (pair cuts) + + // assign hist directories for the MC matched pairs for each (track cut,MCsignal) combination + if (!sigNamesStr.IsNull()) { + 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("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 (const auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fBarrelHistNamesMCmatched.try_emplace(icut * fRecMCSignals.size() + isig, names); + } // end loop over MC signals + } + } // end if enableBarrelHistos + } + } + } + + // Add histogram classes for each specified MCsignal at the generator level + // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function + TString sigGenNamesStr = fConfigMC.genSignals.value; + std::unique_ptr objGenSigArray(sigGenNamesStr.Tokenize(",")); + for (int isig = 0; isig < objGenSigArray->GetEntries(); isig++) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objGenSigArray->At(isig)->GetName()); + if (sig) { + fGenMCSignals.push_back(sig); + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsGenStr = fConfigMC.genSignalsJSON.value; + if (addMCSignalsGenStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsGenStr.Data()); + for (const auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() > TWO_PRONG) { // NOTE: only 2 prong signals + continue; + } + fGenMCSignals.push_back(mcIt); + } + } + + if (isMCGen) { + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() == 1) { + histNames += Form("MCTruthGen_%s;", sig->GetName()); // TODO: Add these names to a std::vector to avoid using Form in the process function + histNames += Form("MCTruthGenSel_%s;", sig->GetName()); + } else if (sig->GetNProngs() == TWO_PRONG) { + histNames += Form("MCTruthGenPair_%s;", sig->GetName()); + histNames += Form("MCTruthGenPairSel_%s;", sig->GetName()); + fHasTwoProngGenMCsignals = true; + } + } + } + + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + VarManager::SetCollisionSystem((TString)fConfigOptions.collisionSystem, fConfigOptions.centerMassEnergy); // set collision system and center of mass energy + + DefineHistograms(fHistMan, histNames.Data(), fConfigAddSEPHistogram.value.data()); // define all histograms + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON + 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) + void runSameEventPairing(MyEventsVtxCovSelected const& events, PresliceUnsorted& preslice, MyBarrelAssocsPrefilter const& assocs, MyBarrelTracksWithCovWithAmbiguities const& /*tracks*/, ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& /*mcTracks*/) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + + TString cutNames = fConfigCuts.track.value; + std::map> histNames = fTrackHistNames; + std::map> histNamesMC = fBarrelHistNamesMCmatched; + int ncuts = fNCutsBarrel; + + uint32_t twoTrackFilter = static_cast(0); + int sign1 = 0; + int sign2 = 0; + uint32_t mcDecision = static_cast(0); + bool isCorrectAssoc_leg1 = false; + bool isCorrectAssoc_leg2 = false; + dielectronList.reserve(1); + dielectronsExtraList.reserve(1); + + if (fConfigOptions.flatTables.value) { + dielectronAllList.reserve(1); + } + + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEventAlice3(event, VarManager::fgValues); + VarManager::FillEventAlice3(event.reducedA3MCEvent(), VarManager::fgValues); + + auto groupedAssocs = assocs.sliceBy(preslice, event.globalIndex()); + if (groupedAssocs.size() == 0) { + continue; + } + + for (const auto& [a1, a2] : o2::soa::combinations(groupedAssocs, groupedAssocs)) { + + 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 + continue; + } + + auto t1 = a1.template reducedA3track_as(); + auto t2 = a2.template reducedA3track_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) { + twoTrackFilter |= (static_cast(1) << 28); + } + if (t2.barrelAmbiguityInBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 29); + } + if (t1.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 30); + } + if (t2.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 31); + } + + // run MC matching for this pair + int isig = 0; + mcDecision = 0; + for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { + if (t1.has_reducedA3MCTrack() && t2.has_reducedA3MCTrack()) { + if ((*sig)->CheckSignal(true, t1.reducedA3MCTrack(), t2.reducedA3MCTrack())) { + mcDecision |= (static_cast(1) << isig); + } + } + } // end loop over MC signals + if (t1.has_reducedA3MCTrack() && t2.has_reducedA3MCTrack()) { + isCorrectAssoc_leg1 = (t1.reducedA3MCTrack().reducedA3MCEvent() == event.reducedA3MCEvent()); + isCorrectAssoc_leg2 = (t2.reducedA3MCTrack().reducedA3MCEvent() == event.reducedA3MCEvent()); + } + + VarManager::FillPairAlice3(t1, t2); + if (fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } + /* TODO: Reimplement Pair vertexing when secondary vertexing is available + if constexpr (TTwoProngFitter) { + // VarManager::FillPairVertexing(event, t1, t2, fConfigOptions.propToPCA); + }*/ + if (!fConfigMC.skimSignalOnly || (fConfigMC.skimSignalOnly && 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); + } + + // Fill histograms + bool isAmbiInBunch = false; + bool isAmbiOutOfBunch = false; + + for (int icut = 0; icut < ncuts; icut++) { + if (twoTrackFilter & (static_cast(1) << icut)) { + isAmbiInBunch = (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)); + isAmbiOutOfBunch = (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)); + if (sign1 * sign2 < 0) { // +- pairs + 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 & (static_cast(1) << isig)) { + 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 (isAmbiInBunch) { // ambiguous in bunch + fHistMan->FillHistClass(histNamesMC[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(histNamesMC[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); + } + } + } + } + if (fConfigQA) { + if (isAmbiInBunch) { + fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(histNames[icut][3 + 3].Data(), VarManager::fgValues); + } + } + } + } else { + if (sign1 > 0) { // ++ pairs + fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][1].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); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][2].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); + } + } + } + } + for (unsigned int iPairCut = 0; iPairCut < fPairCuts.size(); iPairCut++) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!(cut.IsSelected(VarManager::fgValues))) // apply pair cuts + continue; + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(histNames[ncuts + icut * ncuts + iPairCut][0].Data(), VarManager::fgValues); + } else { + if (sign1 > 0) { + fHistMan->FillHistClass(histNames[ncuts + icut * ncuts + iPairCut][1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(histNames[ncuts + icut * ncuts + iPairCut][2].Data(), VarManager::fgValues); + } + } + } // end loop (pair cuts) + } + } // end loop (cuts) + } // end loop over pairs of track associations + } // end loop over events + } + + PresliceUnsorted perReducedMcEvent = aod::reducedA3trackMC::reducedA3MCEventId; + + void runMCGenWithGrouping(MyEventsVtxCovSelected const& events, ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& mcTracks) + { + [[maybe_unused]] uint32_t mcDecision = 0; + int isig = 0; + + for (const auto& mctrack : mcTracks) { + VarManager::FillTrackMC(mcTracks, mctrack); + // if we have a mc generated acceptance cut, apply it here + if (fUseMCGenAccCut) { + if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { + continue; + } + } + // NOTE: Signals are checked here mostly based on the skimmed MC stack, so depending on the requested signal, the stack could be incomplete. + // NOTE: However, the working model is that the decisions on MC signals are precomputed during skimming and are stored in the mcReducedFlags member. + // TODO: Use the mcReducedFlags to select signals + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, mctrack)) { + fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); + } + } + } + // Fill Generated histograms taking into account selected collisions + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + + for (const auto& track : mcTracks) { + if (track.reducedA3MCEventId() != event.reducedA3MCEventId()) { + continue; + } + VarManager::FillTrackMC(mcTracks, track); + // if we have a mc generated acceptance cut, apply it here + if (fUseMCGenAccCut) { + if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { + continue; + } + } + auto track_raw = mcTracks.rawIteratorAt(track.globalIndex()); + mcDecision = 0; + isig = 0; + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, track_raw)) { + mcDecision |= (static_cast(1) << isig); + fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); + MCTruthTableEffi(VarManager::fgValues[VarManager::kMCPt], VarManager::fgValues[VarManager::kMCEta], VarManager::fgValues[VarManager::kMCY], VarManager::fgValues[VarManager::kMCPhi], VarManager::fgValues[VarManager::kMCVz], VarManager::fgValues[VarManager::kMCVtxZ], VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + } + isig++; + } + } + } // end loop over reconstructed events + + if (fHasTwoProngGenMCsignals) { + for (const auto& [t1, t2] : combinations(mcTracks, mcTracks)) { + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); + if (t1_raw.reducedA3MCEventId() == t2_raw.reducedA3MCEventId()) { + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required here + continue; + } + if (sig->CheckSignal(true, t1_raw, t2_raw)) { + VarManager::FillPairMC(t1, t2); + if (fUseMCGenAccCut) { + if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { + continue; + } + } + fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } + } + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + // CURRENTLY ONLY FOR 1-GENERATION 2-PRONG SIGNALS + if (fHasTwoProngGenMCsignals) { + auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.reducedA3MCEventId()); + groupedMCTracks.bindInternalIndicesTo(&mcTracks); + for (const auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); + if (t1_raw.reducedA3MCEventId() == t2_raw.reducedA3MCEventId()) { + mcDecision = 0; + isig = 0; + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required here + continue; + } + if (sig->CheckSignal(true, t1_raw, t2_raw)) { + mcDecision |= (static_cast(1) << isig); + VarManager::FillPairMC(t1, t2); + if (fUseMCGenAccCut) { + if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { + continue; + } + } + fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s", sig->GetName()), VarManager::fgValues); + } + isig++; + } + } + } + } // end loop over reconstructed events + } + } + + void processBarrelOnlySkimmed(MyEventsVtxCovSelected const& events, + MyBarrelAssocsPrefilter const& barrelAssocs, + MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, ReducedA3MCEvents const& mcEvents, ReducedA3MCTracks const& mcTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); + runMCGenWithGrouping(events, mcEvents, mcTracks); + } + + PresliceUnsorted perReducedMcGenEvent = aod::reducedA3trackMC::reducedA3MCEventId; + + void processMCGen(soa::Filtered const& events, ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& mcTracks) + { + // Fill Generated histograms taking into account all generated tracks + [[maybe_unused]] uint32_t mcDecision = 0; + int isig = 0; + + for (const auto& mctrack : mcTracks) { + VarManager::FillTrackMC(mcTracks, mctrack); + // NOTE: Signals are checked here mostly based on the skimmed MC stack, so depending on the requested signal, the stack could be incomplete. + // NOTE: However, the working model is that the decisions on MC signals are precomputed during skimming and are stored in the mcReducedFlags member. + // TODO: Use the mcReducedFlags to select signals + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, mctrack)) { + fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); + } + } + } + + // Fill Generated histograms taking into account selected collisions + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + VarManager::FillEventAlice3(event, VarManager::fgValues); + VarManager::FillEventAlice3(event.reducedA3MCEvent(), VarManager::fgValues); + // auto groupedMCTracks = mcTracks.sliceBy(perReducedMcGenEvent, event.reducedA3MCEventId()); + // groupedMCTracks.bindInternalIndicesTo(&mcTracks); + // for (const auto& track : groupedMCTracks) { + for (const auto& track : mcTracks) { + if (track.reducedA3MCEventId() != event.reducedA3MCEventId()) { + continue; + } + VarManager::FillTrackMC(mcTracks, track); + auto track_raw = mcTracks.rawIteratorAt(track.globalIndex()); + // auto track_raw = groupedMCTracks.rawIteratorAt(track.globalIndex()); + mcDecision = 0; + isig = 0; + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, track_raw)) { + mcDecision |= (static_cast(1) << isig); + fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); + MCTruthTableEffi(VarManager::fgValues[VarManager::kMCPt], VarManager::fgValues[VarManager::kMCEta], VarManager::fgValues[VarManager::kMCY], VarManager::fgValues[VarManager::kMCPhi], VarManager::fgValues[VarManager::kMCVz], VarManager::fgValues[VarManager::kMCVtxZ], VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + } + isig++; + } + } + } // end loop over reconstructed events + if (fHasTwoProngGenMCsignals) { + for (const auto& [t1, t2] : combinations(mcTracks, mcTracks)) { + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); + if (t1_raw.reducedA3MCEventId() == t2_raw.reducedA3MCEventId()) { + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required here + continue; + } + if (sig->CheckSignal(true, t1_raw, t2_raw)) { + fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } + } + // Fill Generated PAIR histograms taking into account selected collisions + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + + if (fHasTwoProngGenMCsignals) { + for (const auto& [t1, t2] : combinations(mcTracks, mcTracks)) { + if (t1.reducedA3MCEventId() != event.reducedA3MCEventId()) { + continue; + } + if (t2.reducedA3MCEventId() != event.reducedA3MCEventId()) { + continue; + } + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); + if (t1_raw.reducedA3MCEventId() == t2_raw.reducedA3MCEventId()) { + mcDecision = 0; + isig = 0; + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required here + continue; + } + if (sig->CheckSignal(true, t1_raw, t2_raw)) { + mcDecision |= (static_cast(1) << isig); + fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s", sig->GetName()), VarManager::fgValues); + } + isig++; + } + } + } + } + } // end loop over reconstructed events + } + + void processMCGenWithGrouping(soa::Filtered const& events, ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& mcTracks) + { + [[maybe_unused]] uint32_t mcDecision = 0; + int isig = 0; + + for (const auto& mctrack : mcTracks) { + VarManager::FillTrackMC(mcTracks, mctrack); + // NOTE: Signals are checked here mostly based on the skimmed MC stack, so depending on the requested signal, the stack could be incomplete. + // NOTE: However, the working model is that the decisions on MC signals are precomputed during skimming and are stored in the mcReducedFlags member. + // TODO: Use the mcReducedFlags to select signals + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, mctrack)) { + fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); + } + } + } + // Fill Generated histograms taking into account selected collisions + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + + for (const auto& track : mcTracks) { + if (track.reducedA3MCEventId() != event.reducedA3MCEventId()) { + continue; + } + VarManager::FillTrackMC(mcTracks, track); + auto track_raw = mcTracks.rawIteratorAt(track.globalIndex()); + mcDecision = 0; + isig = 0; + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, track_raw)) { + mcDecision |= (static_cast(1) << isig); + fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); + MCTruthTableEffi(VarManager::fgValues[VarManager::kMCPt], VarManager::fgValues[VarManager::kMCEta], VarManager::fgValues[VarManager::kMCY], VarManager::fgValues[VarManager::kMCPhi], VarManager::fgValues[VarManager::kMCVz], VarManager::fgValues[VarManager::kMCVtxZ], VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + } + isig++; + } + } + } // end loop over reconstructed events + if (fHasTwoProngGenMCsignals) { + for (const auto& [t1, t2] : combinations(mcTracks, mcTracks)) { + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); + if (t1_raw.reducedA3MCEventId() == t2_raw.reducedA3MCEventId()) { + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required here + continue; + } + if (sig->CheckSignal(true, t1_raw, t2_raw)) { + fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } + } + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + // CURRENTLY ONLY FOR 1-GENERATION 2-PRONG SIGNALS + if (fHasTwoProngGenMCsignals) { + auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.reducedA3MCEventId()); + groupedMCTracks.bindInternalIndicesTo(&mcTracks); + for (const auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { + auto t1_raw = groupedMCTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = groupedMCTracks.rawIteratorAt(t2.globalIndex()); + if (t1_raw.reducedA3MCEventId() == t2_raw.reducedA3MCEventId()) { + mcDecision = 0; + isig = 0; + for (const auto& sig : fGenMCSignals) { + if (sig->GetNProngs() != TWO_PRONG) { // NOTE: 2-prong signals required here + continue; + } + if (sig->CheckSignal(true, t1_raw, t2_raw)) { + mcDecision |= (static_cast(1) << isig); + fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s", sig->GetName()), VarManager::fgValues); + } + isig++; + } + } + } + } // end loop over reconstructed events + } + } + + void processDummy(MyEvents const&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmed, "Run barrel only pairing, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processMCGen, "Loop over MC particle stack and fill generator level histograms", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processMCGenWithGrouping, "Loop over MC particle stack (grouped MCTracks) and fill generator level histograms", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", true); +}; + +struct AnalysisAsymmetricPairing { + + Produces ditrackList; + Produces ditrackExtraList; + + // Output objects + OutputObj fOutputList{"output"}; + + // 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 fConfigPairCutsJSON{"cfgPairCutsJSON", "", "Additional list of pair cuts in JSON format"}; + 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"}; + Configurable fConfigReflectedHistograms{"cfgReflectedHistograms", false, "Include separate histograms for pairs which are reflections of previously counted pairs"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + + Configurable fConfigMCGenSignals{"cfgBarrelMCGenSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable fConfigMCRecSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigMCRecSignalsJSON{"cfgMCRecSignalsJSON", "", "Additional list of MC signals (reconstructed) via JSON"}; + Configurable fConfigMCGenSignalsJSON{"cfgMCGenSignalsJSON", "", "Comma separated list of MC signals (generated) via JSON"}; + + HistogramManager* fHistMan; + + std::vector fPairCuts; + int fNPairHistPrefixes; + + std::vector fRecMCSignals; + std::vector fGenMCSignals; + + // Filter masks to find legs in BarrelTrackCuts table + uint32_t fLegAFilterMask; + uint32_t fLegBFilterMask; + uint32_t fLegCFilterMask; + // Maps tracking which combination of leg cuts the track cuts participate in + std::map fConstructedLegAFilterMasksMap; + std::map fConstructedLegBFilterMasksMap; + std::map fConstructedLegCFilterMasksMap; + // Filter map for common track cuts + uint32_t fCommonTrackCutMask; + // Map tracking which common track cut the track cuts correspond to + std::map fCommonTrackCutFilterMasks; + + int fNLegCuts; + int fNPairCuts = 0; + int fNCommonTrackCuts; + // vectors for cut names and signal names, for easy access when calling FillHistogramList() + std::vector fLegCutNames; + std::vector fPairCutNames; + std::vector fCommonCutNames; + std::vector fRecMCSignalNames; + + Filter eventFilter = aod::dqanalysisflags::isEventSelected > static_cast(0); + + PresliceUnsorted trackAssocsPerCollision = aod::reducedA3track_association::reducedA3eventId; + // PresliceUnsorted trackAssocsPerCollision = aod::reducedA3track_association::reducedA3eventId; + + // Partitions for triplets and asymmetric pairs + Partition legACandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fConfigLegAFilterMask) > static_cast(0); + Partition legBCandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fConfigLegBFilterMask) > static_cast(0); + Partition legCCandidateAssocs = (o2::aod::dqanalysisflags::isBarrelSelected & fConfigLegCFilterMask) > static_cast(0); + + // Map to track how many times a pair of tracks has been encountered + std::map, int8_t> fPairCount; + + void init(o2::framework::InitContext& context) + { + bool isMCGen = context.mOptions.get("processMCGen") || context.mOptions.get("processMCGenWithEventSelection"); + if (context.mOptions.get("processDummy")) { + return; + } + + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Get the leg cut filter masks + fLegAFilterMask = fConfigLegAFilterMask.value; + fLegBFilterMask = fConfigLegBFilterMask.value; + fLegCFilterMask = fConfigLegCFilterMask.value; + + // Get the pair cuts + TString cutNamesStr = fConfigPairCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fPairCuts.push_back(dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + // Extra pair cuts via JSON + TString addPairCutsStr = fConfigPairCutsJSON.value; + if (addPairCutsStr != "") { + std::vector addPairCuts = dqcuts::GetCutsFromJSON(addPairCutsStr.Data()); + for (const auto& t : addPairCuts) { + fPairCuts.push_back(reinterpret_cast(t)); + cutNamesStr += Form(",%s", t->GetName()); + } + } + std::unique_ptr objArrayPairCuts(cutNamesStr.Tokenize(",")); + fNPairCuts = objArrayPairCuts->GetEntries(); + for (int j = 0; j < fNPairCuts; j++) { + fPairCutNames.push_back(objArrayPairCuts->At(j)->GetName()); + } + + // Setting the MC rec signal names + TString sigNamesStr = fConfigMCRecSignals.value; + std::unique_ptr objRecSigArray(sigNamesStr.Tokenize(",")); + for (int isig = 0; isig < objRecSigArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objRecSigArray->At(isig)->GetName()); + if (sig) { + fRecMCSignals.push_back(sig); + } + } + // Add the reco MCSignals from the JSON config + TString addMCSignalsStr = fConfigMCRecSignalsJSON.value; + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + for (const auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() != TWO_PRONG && mcIt->GetNProngs() != THREE_PRONG) { + LOG(fatal) << "Signal at reconstructed level requested (" << mcIt->GetName() << ") " << "does not have 2 or 3 prongs! Fix it"; + } + fRecMCSignals.push_back(mcIt); + sigNamesStr += Form(",%s", mcIt->GetName()); + } + } + // Put all the reco MCSignal names in the vector for histogram naming + std::unique_ptr objArrayRecMCSignals(sigNamesStr.Tokenize(",")); + for (int i = 0; i < objArrayRecMCSignals->GetEntries(); i++) { + fRecMCSignalNames.push_back(objArrayRecMCSignals->At(i)->GetName()); + } + + // Get the barrel track selection cuts + string tempCuts; + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempCuts, false); + TString tempCutsStr = tempCuts; + // check also the cuts added via JSON and add them to the string of cuts + getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", tempCuts, false); + TString addTrackCutsStr = tempCuts; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (const auto& t : addTrackCuts) { + tempCutsStr += Form(",%s", t->GetName()); + } + } + std::unique_ptr objArray(tempCutsStr.Tokenize(",")); + // Get the common leg cuts + int commonCutIdx; + TString commonNamesStr = fConfigCommonTrackCuts.value; + if (!commonNamesStr.IsNull()) { // if common track cuts + std::unique_ptr objArrayCommon(commonNamesStr.Tokenize(",")); + fNCommonTrackCuts = objArrayCommon->GetEntries(); + for (int icut = 0; icut < fNCommonTrackCuts; ++icut) { + commonCutIdx = objArray->IndexOf(objArrayCommon->At(icut)); + if (commonCutIdx >= 0) { + fCommonTrackCutMask |= static_cast(1) << objArray->IndexOf(objArrayCommon->At(icut)); + fCommonTrackCutFilterMasks[icut] = static_cast(1) << objArray->IndexOf(objArrayCommon->At(icut)); + fCommonCutNames.push_back(objArrayCommon->At(icut)->GetName()); + } else { + LOGF(fatal, "Common track cut %s was not calculated upstream. Check the config!", objArrayCommon->At(icut)->GetName()); + } + } + } + // Check that the leg cut masks make sense + if (static_cast(std::floor(std::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(std::log2(fLegAFilterMask))) + 1, objArray->GetEntries()); + } + if (static_cast(std::floor(std::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(std::log2(fLegBFilterMask))) + 1, objArray->GetEntries()); + } + if (static_cast(std::floor(std::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(std::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 && !isMCGen) { + LOG(fatal) << "No cuts defining legs. Check the config!"; + } + fNLegCuts = objArrayLegs->GetEntries(); + std::vector isThreeProng; + int legAIdx; + int legBIdx; + int legCIdx; + // Loop over leg defining cuts + for (int icut = 0; icut < fNLegCuts; ++icut) { + TString legsStr = objArrayLegs->At(icut)->GetName(); + std::unique_ptr legs(legsStr.Tokenize(":")); + if (legs->GetEntries() == THREE_PRONG) { + isThreeProng.push_back(true); + } else if (legs->GetEntries() == TWO_PRONG) { + isThreeProng.push_back(false); + } else { + LOGF(fatal, "Leg cuts %s has the wrong format and could not be parsed!", legsStr.Data()); + continue; + } + // Find leg cuts in the track selection cuts + legAIdx = objArray->IndexOf(legs->At(0)); + if (legAIdx >= 0) { + fConstructedLegAFilterMask |= static_cast(1) << legAIdx; + fConstructedLegAFilterMasksMap[icut] |= static_cast(1) << legAIdx; + } else { + LOGF(fatal, "Leg A cut %s was not calculated upstream. Check the config!", legs->At(0)->GetName()); + continue; + } + legBIdx = objArray->IndexOf(legs->At(1)); + if (legBIdx >= 0) { + fConstructedLegBFilterMask |= static_cast(1) << legBIdx; + fConstructedLegBFilterMasksMap[icut] |= static_cast(1) << legBIdx; + } else { + LOGF(fatal, "Leg B cut %s was not calculated upstream. Check the config!", legs->At(1)->GetName()); + continue; + } + if (isThreeProng[icut]) { + legCIdx = objArray->IndexOf(legs->At(2)); + if (legCIdx >= 0) { + fConstructedLegCFilterMask |= static_cast(1) << legCIdx; + fConstructedLegCFilterMasksMap[icut] |= static_cast(1) << legCIdx; + } else { + LOGF(fatal, "Leg C cut %s was not calculated upstream. Check the config!", legs->At(2)->GetName()); + continue; + } + } + // Leg cut config is fine, store the leg cut name in a vector + fLegCutNames.push_back(legsStr); + + // Define histogram and histogram directory names + if (isThreeProng[icut]) { + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s", legsStr.Data()), fConfigHistogramSubgroups.value.data()); + if (fConfigQA) { + DefineHistograms(fHistMan, Form("TripletsBarrelSE_ambiguous_%s", legsStr.Data()), fConfigHistogramSubgroups.value.data()); + } + + std::unique_ptr objArrayCommon(commonNamesStr.Tokenize(",")); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s", legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName()), fConfigHistogramSubgroups.value.data()); + } + + TString cutNamesStr = fConfigPairCuts.value; + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + fNPairCuts = objArrayPair->GetEntries(); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s", legsStr.Data(), objArrayPair->At(iPairCut)->GetName()), fConfigHistogramSubgroups.value.data()); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s_%s", legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), objArrayPair->At(iPairCut)->GetName()), fConfigHistogramSubgroups.value.data()); + } // end loop (common cuts) + } // end loop (pair cuts) + } // end if (pair cuts) + + // TODO: assign hist directories for the MC matched triplets for each (leg cut combo,MCsignal) combination + if (!sigNamesStr.IsNull()) { + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s", legsStr.Data(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s_%s", legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } + + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s_%s", legsStr.Data(), objArrayPair->At(iPairCut)->GetName(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + DefineHistograms(fHistMan, Form("TripletsBarrelSE_%s_%s_%s_%s", legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), objArrayPair->At(iPairCut)->GetName(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } // end loop (common cuts) + } // end loop (pair cuts) + } // end if (pair cuts) + } // end loop over MC signals + } // end if (MC signals) + } else { + std::vector pairHistPrefixes = {"PairsBarrelSEPM"}; + if (fConfigSameSignHistograms.value) { + pairHistPrefixes.push_back("PairsBarrelSEPP"); + pairHistPrefixes.push_back("PairsBarrelSEMM"); + } + fNPairHistPrefixes = pairHistPrefixes.size(); + + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data()), fConfigHistogramSubgroups.value.data()); + } + if (fConfigQA) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_ambiguous_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data()), fConfigHistogramSubgroups.value.data()); + } + } + if (fConfigReflectedHistograms.value) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_reflected_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data()), fConfigHistogramSubgroups.value.data()); + } + } + + std::unique_ptr objArrayCommon(commonNamesStr.Tokenize(",")); + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName()), fConfigHistogramSubgroups.value.data()); + } + } + + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + fNPairCuts = objArrayPair->GetEntries(); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), objArrayPair->At(iPairCut)->GetName()), fConfigHistogramSubgroups.value.data()); + } + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), objArrayPair->At(iPairCut)->GetName()), fConfigHistogramSubgroups.value.data()); + } + } // end loop (common cuts) + } // end loop (pair cuts) + } // end if (pair cuts) + + // assign hist directories for the MC matched triplets for each (leg cut combo,MCsignal) combination + if (!sigNamesStr.IsNull()) { + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } + if (fConfigReflectedHistograms.value) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_reflected_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } + } + + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } + } + + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), objArrayPair->At(iPairCut)->GetName(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + for (int iPrefix = 0; iPrefix < fNPairHistPrefixes; ++iPrefix) { + DefineHistograms(fHistMan, Form("%s_%s_%s_%s_%s", pairHistPrefixes[iPrefix].Data(), legsStr.Data(), objArrayCommon->At(iCommonCut)->GetName(), objArrayPair->At(iPairCut)->GetName(), sig->GetName()), fConfigHistogramSubgroups.value.data()); + } + } // end loop (common cuts) + } // end loop (pair cuts) + } // end if (pair cuts) + } // end loop over MC signals + } // end if (MC signals) + } + } + + // Add histogram classes for each specified MCsignal at the generator level + // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function + TString sigGenNamesStr = fConfigMCGenSignals.value; + std::unique_ptr objGenSigArray(sigGenNamesStr.Tokenize(",")); + for (int isig = 0; isig < objGenSigArray->GetEntries(); isig++) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objGenSigArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() == 1) { // NOTE: 1-prong signals required + fGenMCSignals.push_back(sig); + DefineHistograms(fHistMan, Form("MCTruthGen_%s;", sig->GetName()), fConfigHistogramSubgroups.value.data()); // TODO: Add these names to a std::vector to avoid using Form in the process function + DefineHistograms(fHistMan, Form("MCTruthGenSel_%s;", sig->GetName()), fConfigHistogramSubgroups.value.data()); // TODO: Add these names to a std::vector to avoid using Form in the process function + } + } + } + + // Add the gen MCSignals from the JSON config + addMCSignalsStr = fConfigMCGenSignalsJSON.value; + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + for (const auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() == 1) { + fGenMCSignals.push_back(mcIt); + DefineHistograms(fHistMan, Form("MCTruthGen_%s;", mcIt->GetName()), fConfigHistogramSubgroups.value.data()); // TODO: Add these names to a std::vector to avoid using Form in the process function + DefineHistograms(fHistMan, Form("MCTruthGenSel_%s;", mcIt->GetName()), fConfigHistogramSubgroups.value.data()); // TODO: Add these names to a std::vector to avoid using Form in the process function + } + } + } + + // 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) { + LOGF(fatal, "A mix of pairs and triplets was given as leg cuts. Check your config!"); + } + + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + // Function to run same event pairing with asymmetric pairs (e.g. kaon-pion) + void runAsymmetricPairing(MyEventsVtxCovSelected const& events, PresliceUnsorted& preslice, MyBarrelAssocs const& /*assocs*/, MyBarrelTracksWithCovWithAmbiguities const& /*tracks*/, ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& /*mcTracks*/) + { + fPairCount.clear(); + + int sign1 = 0; + int sign2 = 0; + uint32_t mcDecision = 0; + ditrackList.reserve(1); + ditrackExtraList.reserve(1); + + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEventAlice3(event, VarManager::fgValues); + + auto groupedLegAAssocs = legACandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegAAssocs.size() == 0) { + continue; + } + auto groupedLegBAssocs = legBCandidateAssocs.sliceBy(preslice, event.globalIndex()); + if (groupedLegBAssocs.size() == 0) { + continue; + } + + for (const 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 + if ((a1.isBarrelSelected_raw() & fConstructedLegAFilterMasksMap[icut]) && (a2.isBarrelSelected_raw() & fConstructedLegBFilterMasksMap[icut])) { + twoTrackFilter |= static_cast(1) << icut; + // If the supposed pion passes a kaon cut, this is a K+K-. Skip it. + if (fConfigSkipAmbiguousIdCombinations.value) { + if (a2.isBarrelSelected_raw() & fLegAFilterMask) { + isPairIdWrong = true; + } + } + } + } + + if (!twoTrackFilter || isPairIdWrong) { + continue; + } + + // Find common track cuts both candidates pass + twoTrackCommonFilter |= a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & fCommonTrackCutMask; + + auto t1 = a1.template reducedA3track_as(); + auto t2 = a2.template reducedA3track_as(); + + // Avoid self-pairs + if (t1.globalIndex() == t2.globalIndex()) { + continue; + } + + bool isReflected = false; + std::pair trackIds(t1.globalIndex(), t2.globalIndex()); + if (fPairCount.find(trackIds) != fPairCount.end()) { + // Double counting is possible due to track-collision ambiguity. Skip pairs which were counted before + fPairCount[trackIds] += 1; + continue; + } + if (fPairCount.find(std::pair(trackIds.second, trackIds.first)) != fPairCount.end()) { + isReflected = true; + } + fPairCount[trackIds] += 1; + + 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 |= static_cast(1) << 30; + } + if (t2.barrelAmbiguityInBunch() > 1 || t2.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= static_cast(1) << 31; + } + + // run MC matching for this pair + int isig = 0; + mcDecision = 0; + for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { + if (t1.has_reducedA3MCTrack() && t2.has_reducedA3MCTrack()) { + VarManager::FillPairMC(t1.reducedA3MCTrack(), t2.reducedA3MCTrack()); + if ((*sig)->CheckSignal(true, t1.reducedA3MCTrack(), t2.reducedA3MCTrack())) { + mcDecision |= static_cast(1) << isig; + } + } + } // end loop over MC signals + + VarManager::FillPairAlice3(t1, t2); + /*TODO: Reimplement when secondary vertexing is available + if constexpr (TTwoProngFitter) { + VarManager::FillPairVertexing(event, t1, t2, fConfigPropToPCA); + }*/ + + // Fill histograms + bool isAmbi = false; + for (int icut = 0; icut < fNLegCuts; icut++) { + if (twoTrackFilter & (static_cast(1) << icut)) { + isAmbi = (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)); + if (sign1 * sign2 < 0) { // +- pairs + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s", fLegCutNames[icut].Data()), VarManager::fgValues); // reconstructed, unmatched + if (isAmbi && fConfigQA) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_ambiguous_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + if (isReflected && fConfigReflectedHistograms.value) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_reflected_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { // ++ pairs + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + if (isAmbi && fConfigQA) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_ambiguous_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + if (isReflected && fConfigReflectedHistograms.value) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_reflected_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + } else { // -- pairs + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + if (isAmbi && fConfigQA) { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_ambiguous_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + if (isReflected && fConfigReflectedHistograms) { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_reflected_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + } + } + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + if (isReflected && fConfigReflectedHistograms.value) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_reflected_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + if (isReflected && fConfigReflectedHistograms.value) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_reflected_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + if (isReflected && fConfigReflectedHistograms.value) { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_reflected_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } + } + } + } + } + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (twoTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data()), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data()), VarManager::fgValues); + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data()), VarManager::fgValues); + } + } + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } + } + } + } + } + } // end loop (common cuts) + int iPairCut = 0; + for (auto cut = fPairCuts.begin(); cut != fPairCuts.end(); cut++, iPairCut++) { + if (!((*cut)->IsSelected(VarManager::fgValues))) // apply pair cuts + continue; + pairFilter |= (static_cast(1) << iPairCut); + // Histograms with pair cuts + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + } + } + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } + } + } + } + // 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(Form("PairsBarrelSEPM_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + } + } + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPM_%s_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } else if (fConfigSameSignHistograms.value) { + if (sign1 > 0) { + fHistMan->FillHistClass(Form("PairsBarrelSEPP_%s_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); + } else { + fHistMan->FillHistClass(Form("PairsBarrelSEMM_%s_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].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, twoTrackCommonFilter); + } // end inner assoc loop (leg A) + } // end event loop + } + + // Function to run same event triplets (e.g. D+->K-pi+pi+) + void runThreeProng(MyEventsVtxCovSelected const& events, PresliceUnsorted& preslice, MyBarrelAssocs const& /*assocs*/, MyBarrelTracksWithCovWithAmbiguities const& tracks, ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& /*mcTracks*/, VarManager::PairCandidateType tripletType) + { + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEventAlice3(event, VarManager::fgValues); + + 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; + } + + // Based on triplet type, make suitable combinations of the partitions + if (tripletType == VarManager::kTripleCandidateToPKPi) { + for (const auto& [a1, a2, a3] : combinations(soa::CombinationsFullIndexPolicy(groupedLegAAssocs, groupedLegBAssocs, groupedLegCAssocs))) { + readTriplet(a1, a2, a3, tracks, event, tripletType); + } + } else if (tripletType == VarManager::kTripleCandidateToKPiPi) { + for (const auto& a1 : groupedLegAAssocs) { + for (const auto& [a2, a3] : combinations(groupedLegBAssocs, groupedLegCAssocs)) { + readTriplet(a1, a2, a3, tracks, event, tripletType); + } + } + } else { + LOG(fatal) << "Given tripletType not recognized. Don't know how to make combinations!\n"; + } + } // end event loop + } + + // Helper function to process triplet + void readTriplet(MyBarrelAssocs::iterator const& a1, MyBarrelAssocs::iterator const& a2, MyBarrelAssocs::iterator const& a3, MyBarrelTracksWithCovWithAmbiguities const& /*tracks*/, MyEventsVtxCovSelected::iterator const& /*event*/, VarManager::PairCandidateType tripletType) + { + uint32_t mcDecision = 0; + + uint32_t threeTrackFilter = 0; + uint32_t threeTrackCommonFilter = 0; + for (int icut = 0; icut < fNLegCuts; ++icut) { + // Find out which leg cut combinations the triplet passes + if ((a1.isBarrelSelected_raw() & fConstructedLegAFilterMasksMap[icut]) && (a2.isBarrelSelected_raw() & fConstructedLegBFilterMasksMap[icut]) && (a3.isBarrelSelected_raw() & fConstructedLegCFilterMasksMap[icut])) { + threeTrackFilter |= (static_cast(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; + } + } + } + } + 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 reducedA3track_as(); + auto t2 = a2.template reducedA3track_as(); + auto t3 = a3.template reducedA3track_as(); + + // Avoid self-pairs + if (t1 == t2 || t1 == t3 || t2 == t3) { + return; + } + // Check charge + if (tripletType == VarManager::kTripleCandidateToKPiPi) { + if (!((t1.sign() == -1 && t2.sign() == 1 && t3.sign() == 1) || (t1.sign() == 1 && t2.sign() == -1 && t3.sign() == -1))) { + return; + } + } + if (tripletType == VarManager::kTripleCandidateToPKPi) { + if (!((t1.sign() == 1 && t2.sign() == -1 && t3.sign() == 1) || (t1.sign() == -1 && t2.sign() == 1 && t3.sign() == -1))) { + return; + } + } + + // store the ambiguity of the three legs in the last 3 digits of the two-track filter + if (t1.barrelAmbiguityInBunch() > 1 || t1.barrelAmbiguityOutOfBunch() > 1) { + threeTrackFilter |= (static_cast(1) << 29); + } + if (t2.barrelAmbiguityInBunch() > 1 || t2.barrelAmbiguityOutOfBunch() > 1) { + threeTrackFilter |= (static_cast(1) << 30); + } + if (t3.barrelAmbiguityInBunch() > 1 || t3.barrelAmbiguityOutOfBunch() > 1) { + threeTrackFilter |= (static_cast(1) << 31); + } + + // run MC matching for this triplet + int isig = 0; + mcDecision = 0; + for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { + if (t1.has_reducedA3MCTrack() && t2.has_reducedA3MCTrack() && t3.has_reducedA3MCTrack()) { + if ((*sig)->CheckSignal(true, t1.reducedA3MCTrack(), t2.reducedA3MCTrack(), t3.reducedA3MCTrack())) { + mcDecision |= (static_cast(1) << isig); + } + } + } // end loop over MC signals + + VarManager::FillTriple(t1, t2, t3, VarManager::fgValues, tripletType); + /* TODO: Reimplement when secondary vertexing is available + if constexpr (TThreeProngFitter) { + VarManager::FillTripletVertexing(event, t1, t2, t3, tripletType); + }*/ + + // Fill histograms + bool isAmbi = false; + for (int icut = 0; icut < fNLegCuts; icut++) { + isAmbi = (threeTrackFilter & (static_cast(1) << 29)) || (threeTrackFilter & (static_cast(1) << 30)) || (threeTrackFilter & (static_cast(1) << 31)); + if (threeTrackFilter & (static_cast(1) << icut)) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s", fLegCutNames[icut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); // matched signal + } + } // end loop (MC signals) + if (fConfigQA && isAmbi) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_ambiguous_%s", fLegCutNames[icut].Data()), VarManager::fgValues); + } + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; iCommonCut++) { + if (threeTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data()), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); // matched signal + } + } // end loop (MC signals) + } + } // end loop (common cuts) + int iPairCut = 0; + for (auto cut = fPairCuts.begin(); cut != fPairCuts.end(); cut++, iPairCut++) { + if (!((*cut)->IsSelected(VarManager::fgValues))) // apply pair cuts + continue; + // Histograms with pair cuts + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s_%s", fLegCutNames[icut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); // matched signal + } + } // end loop (MC signals) + // Histograms with pair cuts and common track cuts + for (int iCommonCut = 0; iCommonCut < fNCommonTrackCuts; ++iCommonCut) { + if (threeTrackCommonFilter & fCommonTrackCutFilterMasks[iCommonCut]) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data()), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(Form("TripletsBarrelSE_%s_%s_%s_%s", fLegCutNames[icut].Data(), fCommonCutNames[iCommonCut].Data(), fPairCutNames[iPairCut].Data(), fRecMCSignalNames[isig].Data()), VarManager::fgValues); // matched signal + } + } // end loop (MC signals) + } + } + } // end loop (pair cuts) + } + } // end loop (cuts) + } + + void processKaonPionSkimmed(MyEventsVtxCovSelected const& events, + MyBarrelAssocs const& barrelAssocs, + MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, + ReducedA3MCEvents const& mcEvents, ReducedA3MCTracks const& mcTracks) + { + runAsymmetricPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); + } + + void processKaonPionPionSkimmed(MyEventsVtxCovSelected const& events, + MyBarrelAssocs const& barrelAssocs, + MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, + ReducedA3MCEvents const& mcEvents, ReducedA3MCTracks const& mcTracks) + { + runThreeProng(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks, VarManager::kTripleCandidateToKPiPi); + } + + void processMCGen(ReducedA3MCTracks const& mcTracks) + { + // loop over mc stack and fill histograms for pure MC truth signals + // group all the MC tracks which belong to the MC event corresponding to the current reconstructed event + // auto groupedMCTracks = tracksMC.sliceBy(aod::reducedA3trackMC::reducedA3MCEventId, event.reducedMCevent().globalIndex()); + for (const auto& mctrack : mcTracks) { + + VarManager::FillTrackMC(mcTracks, mctrack); + // NOTE: Signals are checked here mostly based on the skimmed MC stack, so depending on the requested signal, the stack could be incomplete. + // NOTE: However, the working model is that the decisions on MC signals are precomputed during skimming and are stored in the mcReducedFlags member. + // TODO: Use the mcReducedFlags to select signals + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, mctrack)) { + fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } + + PresliceUnsorted perReducedMcEvent = aod::reducedA3trackMC::reducedA3MCEventId; + + void processMCGenWithEventSelection(soa::Filtered const& events, + ReducedA3MCEvents const& /*mcEvents*/, ReducedA3MCTracks const& mcTracks) + { + for (const auto& event : events) { + if (!event.isEventSelected_bit(0)) { + continue; + } + if (!event.has_reducedA3MCEvent()) { + continue; + } + + auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.reducedA3MCEventId()); + groupedMCTracks.bindInternalIndicesTo(&mcTracks); + for (const auto& track : groupedMCTracks) { + + VarManager::FillTrackMC(mcTracks, track); + + auto track_raw = groupedMCTracks.rawIteratorAt(track.globalIndex()); + for (const auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, track_raw)) { + fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } // end loop over reconstructed events + } + + void processDummy(MyEvents const&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisAsymmetricPairing, processKaonPionSkimmed, "Run kaon pion pairing, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisAsymmetricPairing, processKaonPionPionSkimmed, "Run kaon pion pion triplets, with skimmed tracks", false); + PROCESS_SWITCH(AnalysisAsymmetricPairing, processMCGen, "Loop over MC particle stack and fill generator level histograms", false); + PROCESS_SWITCH(AnalysisAsymmetricPairing, processMCGenWithEventSelection, "Loop over MC particle stack and fill generator level histograms", false); + PROCESS_SWITCH(AnalysisAsymmetricPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} + +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) +{ + // + // 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 iclass = 0; iclass < objArray->GetEntries(); ++iclass) { + TString classStr = objArray->At(iclass)->GetName(); + histMan->AddHistClass(classStr.Data()); + + TString histName = histGroups; + // 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("SameBunchCorrelations") || classStr.Contains("OutOfBunchCorrelations")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "two-collisions", histName); + } + + // TODO: CHANGE TO PROPER PID + + if ((classStr.Contains("Track") || classStr.Contains("Assoc")) && !classStr.Contains("Pairs")) { + if (classStr.Contains("Barrel")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + if (classStr.Contains("PIDCalibElectron")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "postcalib_electron"); + } + if (classStr.Contains("PIDCalibPion")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "postcalib_pion"); + } + if (classStr.Contains("PIDCalibProton")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "postcalib_proton"); + } + if (classStr.Contains("Ambiguity")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "ambiguity"); + } + } + } + + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + + if (classStr.Contains("Triplets")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + + if (classStr.Contains("MCTruthGenPair")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_pair", histName); + } + + if (classStr.Contains("MCTruthGenSelBR")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_triple"); + } else if (classStr.Contains("MCTruthGen")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_track"); + } + + if (classStr.Contains("DileptonsSelected")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", "barrel,vertexing"); + } + + if (classStr.Contains("DileptonTrack") && !classStr.Contains("ME")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-track", histName); + } + + if (classStr.Contains("DileptonTrackME")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-track", "mixedevent"); + } + + if (classStr.Contains("HadronsSelected")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + } + + if (classStr.Contains("DileptonHadronInvMass")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-mass"); + } + + } // end loop over histogram classes +} diff --git a/ALICE3/Tasks/alice3-lutmaker.cxx b/ALICE3/Tasks/alice3-lutmaker.cxx index 4b57e462a8e..de28c90583c 100644 --- a/ALICE3/Tasks/alice3-lutmaker.cxx +++ b/ALICE3/Tasks/alice3-lutmaker.cxx @@ -13,60 +13,64 @@ /// \brief Task to extract LUTs for the fast simulation from full simulation /// \since 27/04/2021 -// O2 includes -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/Track.h" -#include "SimulationDataFormat/MCUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include -using namespace o2; -using namespace framework; -using namespace framework::expressions; - -void customize(std::vector& workflowOptions) -{ - std::vector options{ - {"lut-el", VariantType::Int, 0, {"LUT input for the Electron PDG code"}}, - {"lut-mu", VariantType::Int, 0, {"LUT input for the Muon PDG code"}}, - {"lut-pi", VariantType::Int, 1, {"LUT input for the Pion PDG code"}}, - {"lut-ka", VariantType::Int, 0, {"LUT input for the Kaon PDG code"}}, - {"lut-pr", VariantType::Int, 0, {"LUT input for the Proton PDG code"}}, - {"lut-tr", VariantType::Int, 0, {"LUT input for the Triton PDG code"}}, - {"lut-de", VariantType::Int, 0, {"LUT input for the Deuteron PDG code"}}, - {"lut-he", VariantType::Int, 0, {"LUT input for the Helium3 PDG code"}}}; - std::swap(workflowOptions, options); -} - -#include "Framework/runDataProcessing.h" - -template struct Alice3LutMaker { static constexpr int nSpecies = 8; static constexpr int PDGs[nSpecies] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton, 1000010020, 1000010030, 1000020030}; - static_assert(particle < nSpecies && "Maximum of particles reached"); - static constexpr int pdg = PDGs[particle]; - Configurable addQA{"addQA", false, "Flag to use add QA plots to show the covariance matrix elements"}; - Configurable selPrim{"selPrim", false, "If true selects primaries, if not select all particles"}; + static constexpr std::string_view hDirPos[nSpecies] = {"PDG_11/", "PDG_13/", "PDG_211/", "PDG_321/", "PDG_2212/", "PDG_1000010020/", "PDG_1000010030/", "PDG_1000020030/"}; + static constexpr std::string_view hDirNeg[nSpecies] = {"PDG_11/", "PDG_13/", "PDG_211/", "PDG_321/", "PDG_2212/", "PDG_1000010020/", "PDG_1000010030/", "PDG_1000020030/"}; + o2::framework::Configurable addQA{"addQA", false, "Flag to use add QA plots to show the covariance matrix elements"}; + o2::framework::Configurable selPrim{"selPrim", false, "If true selects primaries, if not select all particles"}; + o2::framework::Configurable> enabledPdgs{"enabledPdgs", std::vector{211, -211}, "List of PDGs enabled"}; - Configurable nchBins{"nchBins", 20, "Number of multiplicity bins"}; - Configurable nchMin{"nchMin", 0.5f, "Lower limit in multiplicity"}; - Configurable nchMax{"nchMax", 3.5f, "Upper limit in multiplicity"}; - Configurable nchLog{"nchLog", 1, "Flag to use a logarithmic multiplicity axis, in this case the Nch limits are the expontents"}; + o2::framework::Configurable nchBins{"nchBins", 20, "Number of multiplicity bins"}; + o2::framework::Configurable nchMin{"nchMin", 0.5f, "Lower limit in multiplicity"}; + o2::framework::Configurable nchMax{"nchMax", 3.5f, "Upper limit in multiplicity"}; + o2::framework::Configurable nchLog{"nchLog", 1, "Flag to use a logarithmic multiplicity axis, in this case the Nch limits are the expontents"}; - Configurable etaBins{"etaBins", 80, "Number of eta bins"}; - Configurable etaMin{"etaMin", -4.f, "Lower limit in eta"}; - Configurable etaMax{"etaMax", 4.f, "Upper limit in eta"}; + o2::framework::Configurable etaBins{"etaBins", 80, "Number of eta bins"}; + o2::framework::Configurable etaMin{"etaMin", -4.f, "Lower limit in eta"}; + o2::framework::Configurable etaMax{"etaMax", 4.f, "Upper limit in eta"}; - Configurable ptBins{"ptBins", 200, "Number of pT bins"}; - Configurable ptMin{"ptMin", -2.f, "Lower limit in pT"}; - Configurable ptMax{"ptMax", 2.f, "Upper limit in pT"}; - Configurable ptLog{"ptLog", 1, "Flag to use a logarithmic pT axis, in this case the pT limits are the expontents"}; + o2::framework::Configurable ptBins{"ptBins", 200, "Number of pT bins"}; + o2::framework::Configurable ptMin{"ptMin", -2.f, "Lower limit in pT"}; + o2::framework::Configurable ptMax{"ptMax", 2.f, "Upper limit in pT"}; + o2::framework::Configurable ptLog{"ptLog", 1, "Flag to use a logarithmic pT axis, in this case the pT limits are the expontents"}; - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry histos{"Histos", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) + void initParticle(o2::track::PID::ID particle, int sign = 1) { + const int pdg = sign * PDGs[particle]; + if (std::find(enabledPdgs.value.begin(), enabledPdgs.value.end(), pdg) == enabledPdgs.value.end()) { + return; + } + LOG(info) << "Initializing LUT maker for PDG " << pdg; const TString commonTitle = Form(" PDG %i", pdg); - AxisSpec axisPt{ptBins, ptMin, ptMax, "#it{p}_{T} GeV/#it{c}"}; + const TString pdgdir = (sign > 0 ? hDirPos[particle] : hDirNeg[particle]).data(); + o2::framework::AxisSpec axisPt{ptBins, ptMin, ptMax, "#it{p}_{T} GeV/#it{c}"}; if (ptLog) { if (axisPt.binEdges.size() > 2) { LOG(fatal) << "Cannot make a variabled bin width axis logaritmic"; @@ -82,134 +86,159 @@ struct Alice3LutMaker { } axisPt.nBins = std::nullopt; } - AxisSpec axisNch{nchBins, nchMin, nchMax, "N_{Ch}"}; + o2::framework::AxisSpec axisNch{nchBins, nchMin, nchMax, "N_{Ch}"}; if (nchLog) { axisNch.makeLogarithmic(); } - const AxisSpec axisEta{etaBins, etaMin, etaMax, "#it{#eta}"}; + const o2::framework::AxisSpec axisEta{etaBins, etaMin, etaMax, "#it{#eta}"}; // Track quantities - histos.add("multiplicity", "Track multiplicity;Tracks per event;Events", kTH1F, {axisNch}); - histos.add("pt", "pt" + commonTitle, kTH1F, {axisPt}); - histos.add("eta", "eta" + commonTitle, kTH1F, {axisEta}); + histos.add(pdgdir + "multiplicity", "Track multiplicity;Tracks per event;Events", o2::framework::HistType::kTH1F, {axisNch}); + histos.add(pdgdir + "pt", "pt" + commonTitle, o2::framework::HistType::kTH1F, {axisPt}); + histos.add(pdgdir + "eta", "eta" + commonTitle, o2::framework::HistType::kTH1F, {axisEta}); // Track covariance matrix quantities - histos.add("CovMat_sigmaY", "sigmaY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_sigmaZ", "sigmaZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_sigmaSnp", "sigmaSnp" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_sigmaTgl", "sigmaTgl" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_sigma1Pt", "sigma1Pt" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rhoZY", "rhoZY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rhoSnpY", "rhoSnpY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rhoSnpZ", "rhoSnpZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rhoTglY", "rhoTglY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rhoTglZ", "rhoTglZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rhoTglSnp", "rhoTglSnp" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rho1PtY", "rho1PtY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rho1PtZ", "rho1PtZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rho1PtSnp", "rho1PtSnp" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_rho1PtTgl", "rho1PtTgl" + commonTitle, kTProfile2D, {axisPt, axisEta}); - - histos.add("CovMat_cYY", "cYY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cZY", "cZY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cZZ", "cZZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cSnpY", "cSnpY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cSnpZ", "cSnpZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cSnpSnp", "cSnpSnp" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cTglY", "cTglY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cTglZ", "cTglZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cTglSnp", "cTglSnp" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_cTglTgl", "cTglTgl" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_c1PtY", "c1PtY" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_c1PtZ", "c1PtZ" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_c1PtSnp", "c1PtSnp" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_c1PtTgl", "c1PtTgl" + commonTitle, kTProfile2D, {axisPt, axisEta}); - histos.add("CovMat_c1Pt21Pt2", "c1Pt21Pt2" + commonTitle, kTProfile2D, {axisPt, axisEta}); - - histos.add("Efficiency", "Efficiency" + commonTitle, kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_sigmaY", "sigmaY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_sigmaZ", "sigmaZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_sigmaSnp", "sigmaSnp" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_sigmaTgl", "sigmaTgl" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_sigma1Pt", "sigma1Pt" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rhoZY", "rhoZY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rhoSnpY", "rhoSnpY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rhoSnpZ", "rhoSnpZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rhoTglY", "rhoTglY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rhoTglZ", "rhoTglZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rhoTglSnp", "rhoTglSnp" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rho1PtY", "rho1PtY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rho1PtZ", "rho1PtZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rho1PtSnp", "rho1PtSnp" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_rho1PtTgl", "rho1PtTgl" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + + histos.add(pdgdir + "CovMat_cYY", "cYY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cZY", "cZY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cZZ", "cZZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cSnpY", "cSnpY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cSnpZ", "cSnpZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cSnpSnp", "cSnpSnp" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cTglY", "cTglY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cTglZ", "cTglZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cTglSnp", "cTglSnp" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_cTglTgl", "cTglTgl" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_c1PtY", "c1PtY" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_c1PtZ", "c1PtZ" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_c1PtSnp", "c1PtSnp" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_c1PtTgl", "c1PtTgl" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + histos.add(pdgdir + "CovMat_c1Pt21Pt2", "c1Pt21Pt2" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); + + histos.add(pdgdir + "Efficiency", "Efficiency" + commonTitle, o2::framework::HistType::kTProfile2D, {axisPt, axisEta}); if (!addQA) { // Only if QA histograms are enabled return; } - const AxisSpec axissigmaY{300, 0.0, 0.04, "sigmaY"}; - const AxisSpec axissigmaZ{300, 0.0, 0.07, "sigmaZ"}; - const AxisSpec axissigmaSnp{300, 0.0, 0.09, "sigmaSnp"}; - const AxisSpec axissigmaTgl{300, 0.0, 0.15, "sigmaTgl"}; - const AxisSpec axissigma1Pt{300, 0.0, 5, "sigma1Pt"}; - const AxisSpec axisrhoZY{300, -18.0, 18.0, "rhoZY"}; - const AxisSpec axisrhoSnpY{300, -300.0, 0.0, "rhoSnpY"}; - const AxisSpec axisrhoSnpZ{300, -10.0, 10.0, "rhoSnpZ"}; - const AxisSpec axisrhoTglY{300, -20.0, 20.0, "rhoTglY"}; - const AxisSpec axisrhoTglZ{300, -300.0, 0.0, "rhoTglZ"}; - const AxisSpec axisrhoTglSnp{300, -15.0, 15.0, "rhoTglSnp"}; - const AxisSpec axisrho1PtY{321, -250.0, 250.0, "rho1PtY"}; - const AxisSpec axisrho1PtZ{300, -90.0, 90.0, "rho1PtZ"}; - const AxisSpec axisrho1PtSnp{375, -300.0, 300.0, "rho1PtSnp"}; - const AxisSpec axisrho1PtTgl{300, -90.0, 90.0, "rho1PtTgl"}; - - histos.add("QA/CovMat_sigmaY", "sigmaY" + commonTitle, kTH3F, {axisPt, axisEta, axissigmaY}); - histos.add("QA/CovMat_sigmaZ", "sigmaZ" + commonTitle, kTH3F, {axisPt, axisEta, axissigmaZ}); - histos.add("QA/CovMat_sigmaSnp", "sigmaSnp" + commonTitle, kTH3F, {axisPt, axisEta, axissigmaSnp}); - histos.add("QA/CovMat_sigmaTgl", "sigmaTgl" + commonTitle, kTH3F, {axisPt, axisEta, axissigmaTgl}); - histos.add("QA/CovMat_sigma1Pt", "sigma1Pt" + commonTitle, kTH3F, {axisPt, axisEta, axissigma1Pt}); - histos.add("QA/sigma1Pt", "sigma1Pt" + commonTitle, kTH3F, {axisPt, axisEta, axissigma1Pt}); - histos.add("QA/CovMat_rhoZY", "rhoZY" + commonTitle, kTH3F, {axisPt, axisEta, axisrhoZY}); - histos.add("QA/CovMat_rhoSnpY", "rhoSnpY" + commonTitle, kTH3F, {axisPt, axisEta, axisrhoSnpY}); - histos.add("QA/CovMat_rhoSnpZ", "rhoSnpZ" + commonTitle, kTH3F, {axisPt, axisEta, axisrhoSnpZ}); - histos.add("QA/CovMat_rhoTglY", "rhoTglY" + commonTitle, kTH3F, {axisPt, axisEta, axisrhoTglY}); - histos.add("QA/CovMat_rhoTglZ", "rhoTglZ" + commonTitle, kTH3F, {axisPt, axisEta, axisrhoTglZ}); - histos.add("QA/CovMat_rhoTglSnp", "rhoTglSnp" + commonTitle, kTH3F, {axisPt, axisEta, axisrhoTglSnp}); - histos.add("QA/CovMat_rho1PtY", "rho1PtY" + commonTitle, kTH3F, {axisPt, axisEta, axisrho1PtY}); - histos.add("QA/CovMat_rho1PtZ", "rho1PtZ" + commonTitle, kTH3F, {axisPt, axisEta, axisrho1PtZ}); - histos.add("QA/CovMat_rho1PtSnp", "rho1PtSnp" + commonTitle, kTH3F, {axisPt, axisEta, axisrho1PtSnp}); - histos.add("QA/CovMat_rho1PtTgl", "rho1PtTgl" + commonTitle, kTH3F, {axisPt, axisEta, axisrho1PtTgl}); - - const AxisSpec axiscYY{300, 0.0, 0.0009, "cYY"}; - const AxisSpec axiscZY{300, -6e-08, 6e-08, "cZY"}; - const AxisSpec axiscZZ{300, 0.0, 0.003, "cZZ"}; - const AxisSpec axiscSnpY{300, -0.0021, 0.0, "cSnpY"}; - const AxisSpec axiscSnpZ{300, -8e-08, 8e-08, "cSnpZ"}; - const AxisSpec axiscSnpSnp{300, 0.0, 0.0025, "cSnpSnp"}; - const AxisSpec axiscTglY{300, -2e-07, 2e-07, "cTglY"}; - const AxisSpec axiscTglZ{300, -0.004, 0.0, "cTglZ"}; - const AxisSpec axiscTglSnp{300, -3.5e-05, 3.5e-05, "cTglSnp"}; - const AxisSpec axiscTglTgl{300, 0.0, 0.008, "cTglTgl"}; - const AxisSpec axisc1PtY{300, -0.004, 0.004, "c1PtY"}; - const AxisSpec axisc1PtZ{300, -0.03, 0.03, "c1PtZ"}; - const AxisSpec axisc1PtSnp{300, -0.015, 0.015, "c1PtSnp"}; - const AxisSpec axisc1PtTgl{300, -0.06, 0.06, "c1PtTgl"}; - const AxisSpec axisc1Pt21Pt2{300, 0.0, 10, "c1Pt21Pt2"}; - - histos.add("QA/CovMat_cYY", "cYY" + commonTitle, kTH3F, {axisPt, axisEta, axiscYY}); - histos.add("QA/CovMat_cZY", "cZY" + commonTitle, kTH3F, {axisPt, axisEta, axiscZY}); - histos.add("QA/CovMat_cZZ", "cZZ" + commonTitle, kTH3F, {axisPt, axisEta, axiscZZ}); - histos.add("QA/CovMat_cSnpY", "cSnpY" + commonTitle, kTH3F, {axisPt, axisEta, axiscSnpY}); - histos.add("QA/CovMat_cSnpZ", "cSnpZ" + commonTitle, kTH3F, {axisPt, axisEta, axiscSnpZ}); - histos.add("QA/CovMat_cSnpSnp", "cSnpSnp" + commonTitle, kTH3F, {axisPt, axisEta, axiscSnpSnp}); - histos.add("QA/CovMat_cTglY", "cTglY" + commonTitle, kTH3F, {axisPt, axisEta, axiscTglY}); - histos.add("QA/CovMat_cTglZ", "cTglZ" + commonTitle, kTH3F, {axisPt, axisEta, axiscTglZ}); - histos.add("QA/CovMat_cTglSnp", "cTglSnp" + commonTitle, kTH3F, {axisPt, axisEta, axiscTglSnp}); - histos.add("QA/CovMat_cTglTgl", "cTglTgl" + commonTitle, kTH3F, {axisPt, axisEta, axiscTglTgl}); - histos.add("QA/CovMat_c1PtY", "c1PtY" + commonTitle, kTH3F, {axisPt, axisEta, axisc1PtY}); - histos.add("QA/CovMat_c1PtZ", "c1PtZ" + commonTitle, kTH3F, {axisPt, axisEta, axisc1PtZ}); - histos.add("QA/CovMat_c1PtSnp", "c1PtSnp" + commonTitle, kTH3F, {axisPt, axisEta, axisc1PtSnp}); - histos.add("QA/CovMat_c1PtTgl", "c1PtTgl" + commonTitle, kTH3F, {axisPt, axisEta, axisc1PtTgl}); - histos.add("QA/CovMat_c1Pt21Pt2", "c1Pt21Pt2" + commonTitle, kTH3F, {axisPt, axisEta, axisc1Pt21Pt2}); + const o2::framework::AxisSpec axissigmaY{300, 0.0, 0.04, "sigmaY"}; + const o2::framework::AxisSpec axissigmaZ{300, 0.0, 0.07, "sigmaZ"}; + const o2::framework::AxisSpec axissigmaSnp{300, 0.0, 0.09, "sigmaSnp"}; + const o2::framework::AxisSpec axissigmaTgl{300, 0.0, 0.15, "sigmaTgl"}; + const o2::framework::AxisSpec axissigma1Pt{300, 0.0, 5, "sigma1Pt"}; + const o2::framework::AxisSpec axisrhoZY{300, -18.0, 18.0, "rhoZY"}; + const o2::framework::AxisSpec axisrhoSnpY{300, -300.0, 0.0, "rhoSnpY"}; + const o2::framework::AxisSpec axisrhoSnpZ{300, -10.0, 10.0, "rhoSnpZ"}; + const o2::framework::AxisSpec axisrhoTglY{300, -20.0, 20.0, "rhoTglY"}; + const o2::framework::AxisSpec axisrhoTglZ{300, -300.0, 0.0, "rhoTglZ"}; + const o2::framework::AxisSpec axisrhoTglSnp{300, -15.0, 15.0, "rhoTglSnp"}; + const o2::framework::AxisSpec axisrho1PtY{321, -250.0, 250.0, "rho1PtY"}; + const o2::framework::AxisSpec axisrho1PtZ{300, -90.0, 90.0, "rho1PtZ"}; + const o2::framework::AxisSpec axisrho1PtSnp{375, -300.0, 300.0, "rho1PtSnp"}; + const o2::framework::AxisSpec axisrho1PtTgl{300, -90.0, 90.0, "rho1PtTgl"}; + + histos.add(pdgdir + "QA/CovMat_sigmaY", "sigmaY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axissigmaY}); + histos.add(pdgdir + "QA/CovMat_sigmaZ", "sigmaZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axissigmaZ}); + histos.add(pdgdir + "QA/CovMat_sigmaSnp", "sigmaSnp" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axissigmaSnp}); + histos.add(pdgdir + "QA/CovMat_sigmaTgl", "sigmaTgl" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axissigmaTgl}); + histos.add(pdgdir + "QA/CovMat_sigma1Pt", "sigma1Pt" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axissigma1Pt}); + histos.add(pdgdir + "QA/sigma1Pt", "sigma1Pt" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axissigma1Pt}); + histos.add(pdgdir + "QA/CovMat_rhoZY", "rhoZY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrhoZY}); + histos.add(pdgdir + "QA/CovMat_rhoSnpY", "rhoSnpY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrhoSnpY}); + histos.add(pdgdir + "QA/CovMat_rhoSnpZ", "rhoSnpZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrhoSnpZ}); + histos.add(pdgdir + "QA/CovMat_rhoTglY", "rhoTglY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrhoTglY}); + histos.add(pdgdir + "QA/CovMat_rhoTglZ", "rhoTglZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrhoTglZ}); + histos.add(pdgdir + "QA/CovMat_rhoTglSnp", "rhoTglSnp" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrhoTglSnp}); + histos.add(pdgdir + "QA/CovMat_rho1PtY", "rho1PtY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrho1PtY}); + histos.add(pdgdir + "QA/CovMat_rho1PtZ", "rho1PtZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrho1PtZ}); + histos.add(pdgdir + "QA/CovMat_rho1PtSnp", "rho1PtSnp" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrho1PtSnp}); + histos.add(pdgdir + "QA/CovMat_rho1PtTgl", "rho1PtTgl" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisrho1PtTgl}); + + const o2::framework::AxisSpec axiscYY{300, 0.0, 0.0009, "cYY"}; + const o2::framework::AxisSpec axiscZY{300, -6e-08, 6e-08, "cZY"}; + const o2::framework::AxisSpec axiscZZ{300, 0.0, 0.003, "cZZ"}; + const o2::framework::AxisSpec axiscSnpY{300, -0.0021, 0.0, "cSnpY"}; + const o2::framework::AxisSpec axiscSnpZ{300, -8e-08, 8e-08, "cSnpZ"}; + const o2::framework::AxisSpec axiscSnpSnp{300, 0.0, 0.0025, "cSnpSnp"}; + const o2::framework::AxisSpec axiscTglY{300, -2e-07, 2e-07, "cTglY"}; + const o2::framework::AxisSpec axiscTglZ{300, -0.004, 0.0, "cTglZ"}; + const o2::framework::AxisSpec axiscTglSnp{300, -3.5e-05, 3.5e-05, "cTglSnp"}; + const o2::framework::AxisSpec axiscTglTgl{300, 0.0, 0.008, "cTglTgl"}; + const o2::framework::AxisSpec axisc1PtY{300, -0.004, 0.004, "c1PtY"}; + const o2::framework::AxisSpec axisc1PtZ{300, -0.03, 0.03, "c1PtZ"}; + const o2::framework::AxisSpec axisc1PtSnp{300, -0.015, 0.015, "c1PtSnp"}; + const o2::framework::AxisSpec axisc1PtTgl{300, -0.06, 0.06, "c1PtTgl"}; + const o2::framework::AxisSpec axisc1Pt21Pt2{300, 0.0, 10, "c1Pt21Pt2"}; + + histos.add(pdgdir + "QA/CovMat_cYY", "cYY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscYY}); + histos.add(pdgdir + "QA/CovMat_cZY", "cZY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscZY}); + histos.add(pdgdir + "QA/CovMat_cZZ", "cZZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscZZ}); + histos.add(pdgdir + "QA/CovMat_cSnpY", "cSnpY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscSnpY}); + histos.add(pdgdir + "QA/CovMat_cSnpZ", "cSnpZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscSnpZ}); + histos.add(pdgdir + "QA/CovMat_cSnpSnp", "cSnpSnp" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscSnpSnp}); + histos.add(pdgdir + "QA/CovMat_cTglY", "cTglY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscTglY}); + histos.add(pdgdir + "QA/CovMat_cTglZ", "cTglZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscTglZ}); + histos.add(pdgdir + "QA/CovMat_cTglSnp", "cTglSnp" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscTglSnp}); + histos.add(pdgdir + "QA/CovMat_cTglTgl", "cTglTgl" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axiscTglTgl}); + histos.add(pdgdir + "QA/CovMat_c1PtY", "c1PtY" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisc1PtY}); + histos.add(pdgdir + "QA/CovMat_c1PtZ", "c1PtZ" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisc1PtZ}); + histos.add(pdgdir + "QA/CovMat_c1PtSnp", "c1PtSnp" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisc1PtSnp}); + histos.add(pdgdir + "QA/CovMat_c1PtTgl", "c1PtTgl" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisc1PtTgl}); + histos.add(pdgdir + "QA/CovMat_c1Pt21Pt2", "c1Pt21Pt2" + commonTitle, o2::framework::HistType::kTH3F, {axisPt, axisEta, axisc1Pt21Pt2}); } - void process(const o2::aod::McParticles& mcParticles, - const o2::soa::Join&, - const o2::soa::Join& tracks, - const o2::aod::McCollisions&) + void init(o2::framework::InitContext&) { + initParticle(o2::track::PID::Pion, 1); + // initParticle(o2::track::PID::Electron, 1); + return; // For now only filling the LUT for electrons, to save time, will enable the others later + for (int i = -1; i >= 1; i += 2) { + initParticle(o2::track::PID::Electron, i); + initParticle(o2::track::PID::Muon, i); + initParticle(o2::track::PID::Kaon, i); + initParticle(o2::track::PID::Proton, i); + initParticle(o2::track::PID::Deuteron, i); + initParticle(o2::track::PID::Triton, i); + initParticle(o2::track::PID::Helium3, i); + } + } + + template + void processParticle(const o2::aod::McParticles& mcParticles, + const o2::soa::Join::iterator&, + const o2::soa::Join& tracks, + const o2::aod::McCollisions::iterator&) + { + constexpr int pdg = (sign > 0 ? 1 : -1) * PDGs[particle]; + constexpr auto hDIR = HIST((sign > 0 ? hDirPos[particle] : hDirNeg[particle]).data()); + + if (std::find(enabledPdgs.value.begin(), enabledPdgs.value.end(), pdg) == enabledPdgs.value.end()) { + return; + } + LOG(info) << "Processing LUT maker for PDG " << pdg; std::vector recoTracks(tracks.size()); int ntrks = 0; for (const auto& track : tracks) { - if (!track.has_mcParticle()) + if (!track.has_mcParticle()) { continue; - const auto mcParticle = track.mcParticle_as(); + } + const auto& mcParticle = track.mcParticle_as(); if (mcParticle.pdgCode() != pdg) { continue; } @@ -219,79 +248,79 @@ struct Alice3LutMaker { recoTracks[ntrks++] = mcParticle.globalIndex(); - histos.fill(HIST("pt"), mcParticle.pt()); - histos.fill(HIST("eta"), mcParticle.eta()); - - histos.fill(HIST("CovMat_sigmaY"), mcParticle.pt(), mcParticle.eta(), track.sigmaY()); - histos.fill(HIST("CovMat_sigmaZ"), mcParticle.pt(), mcParticle.eta(), track.sigmaZ()); - histos.fill(HIST("CovMat_sigmaSnp"), mcParticle.pt(), mcParticle.eta(), track.sigmaSnp()); - histos.fill(HIST("CovMat_sigmaTgl"), mcParticle.pt(), mcParticle.eta(), track.sigmaTgl()); - histos.fill(HIST("CovMat_sigma1Pt"), mcParticle.pt(), mcParticle.eta(), track.sigma1Pt()); - histos.fill(HIST("CovMat_rhoZY"), mcParticle.pt(), mcParticle.eta(), track.rhoZY()); - histos.fill(HIST("CovMat_rhoSnpY"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpY()); - histos.fill(HIST("CovMat_rhoSnpZ"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpZ()); - histos.fill(HIST("CovMat_rhoTglY"), mcParticle.pt(), mcParticle.eta(), track.rhoTglY()); - histos.fill(HIST("CovMat_rhoTglZ"), mcParticle.pt(), mcParticle.eta(), track.rhoTglZ()); - histos.fill(HIST("CovMat_rhoTglSnp"), mcParticle.pt(), mcParticle.eta(), track.rhoTglSnp()); - histos.fill(HIST("CovMat_rho1PtY"), mcParticle.pt(), mcParticle.eta(), track.rho1PtY()); - histos.fill(HIST("CovMat_rho1PtZ"), mcParticle.pt(), mcParticle.eta(), track.rho1PtZ()); - histos.fill(HIST("CovMat_rho1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.rho1PtSnp()); - histos.fill(HIST("CovMat_rho1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.rho1PtTgl()); - - histos.fill(HIST("CovMat_cYY"), mcParticle.pt(), mcParticle.eta(), track.cYY()); - histos.fill(HIST("CovMat_cZY"), mcParticle.pt(), mcParticle.eta(), track.cZY()); - histos.fill(HIST("CovMat_cZZ"), mcParticle.pt(), mcParticle.eta(), track.cZZ()); - histos.fill(HIST("CovMat_cSnpY"), mcParticle.pt(), mcParticle.eta(), track.cSnpY()); - histos.fill(HIST("CovMat_cSnpZ"), mcParticle.pt(), mcParticle.eta(), track.cSnpZ()); - histos.fill(HIST("CovMat_cSnpSnp"), mcParticle.pt(), mcParticle.eta(), track.cSnpSnp()); - histos.fill(HIST("CovMat_cTglY"), mcParticle.pt(), mcParticle.eta(), track.cTglY()); - histos.fill(HIST("CovMat_cTglZ"), mcParticle.pt(), mcParticle.eta(), track.cTglZ()); - histos.fill(HIST("CovMat_cTglSnp"), mcParticle.pt(), mcParticle.eta(), track.cTglSnp()); - histos.fill(HIST("CovMat_cTglTgl"), mcParticle.pt(), mcParticle.eta(), track.cTglTgl()); - histos.fill(HIST("CovMat_c1PtY"), mcParticle.pt(), mcParticle.eta(), track.c1PtY()); - histos.fill(HIST("CovMat_c1PtZ"), mcParticle.pt(), mcParticle.eta(), track.c1PtZ()); - histos.fill(HIST("CovMat_c1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.c1PtSnp()); - histos.fill(HIST("CovMat_c1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.c1PtTgl()); - histos.fill(HIST("CovMat_c1Pt21Pt2"), mcParticle.pt(), mcParticle.eta(), track.c1Pt21Pt2()); + histos.fill(hDIR + HIST("pt"), mcParticle.pt()); + histos.fill(hDIR + HIST("eta"), mcParticle.eta()); + + histos.fill(hDIR + HIST("CovMat_sigmaY"), mcParticle.pt(), mcParticle.eta(), track.sigmaY()); + histos.fill(hDIR + HIST("CovMat_sigmaZ"), mcParticle.pt(), mcParticle.eta(), track.sigmaZ()); + histos.fill(hDIR + HIST("CovMat_sigmaSnp"), mcParticle.pt(), mcParticle.eta(), track.sigmaSnp()); + histos.fill(hDIR + HIST("CovMat_sigmaTgl"), mcParticle.pt(), mcParticle.eta(), track.sigmaTgl()); + histos.fill(hDIR + HIST("CovMat_sigma1Pt"), mcParticle.pt(), mcParticle.eta(), track.sigma1Pt()); + histos.fill(hDIR + HIST("CovMat_rhoZY"), mcParticle.pt(), mcParticle.eta(), track.rhoZY()); + histos.fill(hDIR + HIST("CovMat_rhoSnpY"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpY()); + histos.fill(hDIR + HIST("CovMat_rhoSnpZ"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpZ()); + histos.fill(hDIR + HIST("CovMat_rhoTglY"), mcParticle.pt(), mcParticle.eta(), track.rhoTglY()); + histos.fill(hDIR + HIST("CovMat_rhoTglZ"), mcParticle.pt(), mcParticle.eta(), track.rhoTglZ()); + histos.fill(hDIR + HIST("CovMat_rhoTglSnp"), mcParticle.pt(), mcParticle.eta(), track.rhoTglSnp()); + histos.fill(hDIR + HIST("CovMat_rho1PtY"), mcParticle.pt(), mcParticle.eta(), track.rho1PtY()); + histos.fill(hDIR + HIST("CovMat_rho1PtZ"), mcParticle.pt(), mcParticle.eta(), track.rho1PtZ()); + histos.fill(hDIR + HIST("CovMat_rho1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.rho1PtSnp()); + histos.fill(hDIR + HIST("CovMat_rho1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.rho1PtTgl()); + + histos.fill(hDIR + HIST("CovMat_cYY"), mcParticle.pt(), mcParticle.eta(), track.cYY()); + histos.fill(hDIR + HIST("CovMat_cZY"), mcParticle.pt(), mcParticle.eta(), track.cZY()); + histos.fill(hDIR + HIST("CovMat_cZZ"), mcParticle.pt(), mcParticle.eta(), track.cZZ()); + histos.fill(hDIR + HIST("CovMat_cSnpY"), mcParticle.pt(), mcParticle.eta(), track.cSnpY()); + histos.fill(hDIR + HIST("CovMat_cSnpZ"), mcParticle.pt(), mcParticle.eta(), track.cSnpZ()); + histos.fill(hDIR + HIST("CovMat_cSnpSnp"), mcParticle.pt(), mcParticle.eta(), track.cSnpSnp()); + histos.fill(hDIR + HIST("CovMat_cTglY"), mcParticle.pt(), mcParticle.eta(), track.cTglY()); + histos.fill(hDIR + HIST("CovMat_cTglZ"), mcParticle.pt(), mcParticle.eta(), track.cTglZ()); + histos.fill(hDIR + HIST("CovMat_cTglSnp"), mcParticle.pt(), mcParticle.eta(), track.cTglSnp()); + histos.fill(hDIR + HIST("CovMat_cTglTgl"), mcParticle.pt(), mcParticle.eta(), track.cTglTgl()); + histos.fill(hDIR + HIST("CovMat_c1PtY"), mcParticle.pt(), mcParticle.eta(), track.c1PtY()); + histos.fill(hDIR + HIST("CovMat_c1PtZ"), mcParticle.pt(), mcParticle.eta(), track.c1PtZ()); + histos.fill(hDIR + HIST("CovMat_c1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.c1PtSnp()); + histos.fill(hDIR + HIST("CovMat_c1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.c1PtTgl()); + histos.fill(hDIR + HIST("CovMat_c1Pt21Pt2"), mcParticle.pt(), mcParticle.eta(), track.c1Pt21Pt2()); if (!addQA) { // Only if QA histograms are enabled continue; } - histos.fill(HIST("QA/CovMat_sigmaY"), mcParticle.pt(), mcParticle.eta(), track.sigmaY()); - histos.fill(HIST("QA/CovMat_sigmaZ"), mcParticle.pt(), mcParticle.eta(), track.sigmaZ()); - histos.fill(HIST("QA/CovMat_sigmaSnp"), mcParticle.pt(), mcParticle.eta(), track.sigmaSnp()); - histos.fill(HIST("QA/CovMat_sigmaTgl"), mcParticle.pt(), mcParticle.eta(), track.sigmaTgl()); - histos.fill(HIST("QA/CovMat_sigma1Pt"), mcParticle.pt(), mcParticle.eta(), track.sigma1Pt()); - histos.fill(HIST("QA/sigma1Pt"), mcParticle.pt(), mcParticle.eta(), std::abs(track.signed1Pt()) - 1. / mcParticle.pt()); - histos.fill(HIST("QA/CovMat_rhoZY"), mcParticle.pt(), mcParticle.eta(), track.rhoZY()); - histos.fill(HIST("QA/CovMat_rhoSnpY"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpY()); - histos.fill(HIST("QA/CovMat_rhoSnpZ"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpZ()); - histos.fill(HIST("QA/CovMat_rhoTglY"), mcParticle.pt(), mcParticle.eta(), track.rhoTglY()); - histos.fill(HIST("QA/CovMat_rhoTglZ"), mcParticle.pt(), mcParticle.eta(), track.rhoTglZ()); - histos.fill(HIST("QA/CovMat_rhoTglSnp"), mcParticle.pt(), mcParticle.eta(), track.rhoTglSnp()); - histos.fill(HIST("QA/CovMat_rho1PtY"), mcParticle.pt(), mcParticle.eta(), track.rho1PtY()); - histos.fill(HIST("QA/CovMat_rho1PtZ"), mcParticle.pt(), mcParticle.eta(), track.rho1PtZ()); - histos.fill(HIST("QA/CovMat_rho1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.rho1PtSnp()); - histos.fill(HIST("QA/CovMat_rho1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.rho1PtTgl()); - - histos.fill(HIST("QA/CovMat_cYY"), mcParticle.pt(), mcParticle.eta(), track.cYY()); - histos.fill(HIST("QA/CovMat_cZY"), mcParticle.pt(), mcParticle.eta(), track.cZY()); - histos.fill(HIST("QA/CovMat_cZZ"), mcParticle.pt(), mcParticle.eta(), track.cZZ()); - histos.fill(HIST("QA/CovMat_cSnpY"), mcParticle.pt(), mcParticle.eta(), track.cSnpY()); - histos.fill(HIST("QA/CovMat_cSnpZ"), mcParticle.pt(), mcParticle.eta(), track.cSnpZ()); - histos.fill(HIST("QA/CovMat_cSnpSnp"), mcParticle.pt(), mcParticle.eta(), track.cSnpSnp()); - histos.fill(HIST("QA/CovMat_cTglY"), mcParticle.pt(), mcParticle.eta(), track.cTglY()); - histos.fill(HIST("QA/CovMat_cTglZ"), mcParticle.pt(), mcParticle.eta(), track.cTglZ()); - histos.fill(HIST("QA/CovMat_cTglSnp"), mcParticle.pt(), mcParticle.eta(), track.cTglSnp()); - histos.fill(HIST("QA/CovMat_cTglTgl"), mcParticle.pt(), mcParticle.eta(), track.cTglTgl()); - histos.fill(HIST("QA/CovMat_c1PtY"), mcParticle.pt(), mcParticle.eta(), track.c1PtY()); - histos.fill(HIST("QA/CovMat_c1PtZ"), mcParticle.pt(), mcParticle.eta(), track.c1PtZ()); - histos.fill(HIST("QA/CovMat_c1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.c1PtSnp()); - histos.fill(HIST("QA/CovMat_c1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.c1PtTgl()); - histos.fill(HIST("QA/CovMat_c1Pt21Pt2"), mcParticle.pt(), mcParticle.eta(), track.c1Pt21Pt2()); + histos.fill(hDIR + HIST("QA/CovMat_sigmaY"), mcParticle.pt(), mcParticle.eta(), track.sigmaY()); + histos.fill(hDIR + HIST("QA/CovMat_sigmaZ"), mcParticle.pt(), mcParticle.eta(), track.sigmaZ()); + histos.fill(hDIR + HIST("QA/CovMat_sigmaSnp"), mcParticle.pt(), mcParticle.eta(), track.sigmaSnp()); + histos.fill(hDIR + HIST("QA/CovMat_sigmaTgl"), mcParticle.pt(), mcParticle.eta(), track.sigmaTgl()); + histos.fill(hDIR + HIST("QA/CovMat_sigma1Pt"), mcParticle.pt(), mcParticle.eta(), track.sigma1Pt()); + histos.fill(hDIR + HIST("QA/sigma1Pt"), mcParticle.pt(), mcParticle.eta(), std::abs(track.signed1Pt()) - 1. / mcParticle.pt()); + histos.fill(hDIR + HIST("QA/CovMat_rhoZY"), mcParticle.pt(), mcParticle.eta(), track.rhoZY()); + histos.fill(hDIR + HIST("QA/CovMat_rhoSnpY"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpY()); + histos.fill(hDIR + HIST("QA/CovMat_rhoSnpZ"), mcParticle.pt(), mcParticle.eta(), track.rhoSnpZ()); + histos.fill(hDIR + HIST("QA/CovMat_rhoTglY"), mcParticle.pt(), mcParticle.eta(), track.rhoTglY()); + histos.fill(hDIR + HIST("QA/CovMat_rhoTglZ"), mcParticle.pt(), mcParticle.eta(), track.rhoTglZ()); + histos.fill(hDIR + HIST("QA/CovMat_rhoTglSnp"), mcParticle.pt(), mcParticle.eta(), track.rhoTglSnp()); + histos.fill(hDIR + HIST("QA/CovMat_rho1PtY"), mcParticle.pt(), mcParticle.eta(), track.rho1PtY()); + histos.fill(hDIR + HIST("QA/CovMat_rho1PtZ"), mcParticle.pt(), mcParticle.eta(), track.rho1PtZ()); + histos.fill(hDIR + HIST("QA/CovMat_rho1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.rho1PtSnp()); + histos.fill(hDIR + HIST("QA/CovMat_rho1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.rho1PtTgl()); + + histos.fill(hDIR + HIST("QA/CovMat_cYY"), mcParticle.pt(), mcParticle.eta(), track.cYY()); + histos.fill(hDIR + HIST("QA/CovMat_cZY"), mcParticle.pt(), mcParticle.eta(), track.cZY()); + histos.fill(hDIR + HIST("QA/CovMat_cZZ"), mcParticle.pt(), mcParticle.eta(), track.cZZ()); + histos.fill(hDIR + HIST("QA/CovMat_cSnpY"), mcParticle.pt(), mcParticle.eta(), track.cSnpY()); + histos.fill(hDIR + HIST("QA/CovMat_cSnpZ"), mcParticle.pt(), mcParticle.eta(), track.cSnpZ()); + histos.fill(hDIR + HIST("QA/CovMat_cSnpSnp"), mcParticle.pt(), mcParticle.eta(), track.cSnpSnp()); + histos.fill(hDIR + HIST("QA/CovMat_cTglY"), mcParticle.pt(), mcParticle.eta(), track.cTglY()); + histos.fill(hDIR + HIST("QA/CovMat_cTglZ"), mcParticle.pt(), mcParticle.eta(), track.cTglZ()); + histos.fill(hDIR + HIST("QA/CovMat_cTglSnp"), mcParticle.pt(), mcParticle.eta(), track.cTglSnp()); + histos.fill(hDIR + HIST("QA/CovMat_cTglTgl"), mcParticle.pt(), mcParticle.eta(), track.cTglTgl()); + histos.fill(hDIR + HIST("QA/CovMat_c1PtY"), mcParticle.pt(), mcParticle.eta(), track.c1PtY()); + histos.fill(hDIR + HIST("QA/CovMat_c1PtZ"), mcParticle.pt(), mcParticle.eta(), track.c1PtZ()); + histos.fill(hDIR + HIST("QA/CovMat_c1PtSnp"), mcParticle.pt(), mcParticle.eta(), track.c1PtSnp()); + histos.fill(hDIR + HIST("QA/CovMat_c1PtTgl"), mcParticle.pt(), mcParticle.eta(), track.c1PtTgl()); + histos.fill(hDIR + HIST("QA/CovMat_c1Pt21Pt2"), mcParticle.pt(), mcParticle.eta(), track.c1Pt21Pt2()); } - histos.fill(HIST("multiplicity"), ntrks); + histos.fill(hDIR + HIST("multiplicity"), ntrks); for (const auto& mcParticle : mcParticles) { if (mcParticle.pdgCode() != pdg) { @@ -302,40 +331,45 @@ struct Alice3LutMaker { } if (std::find(recoTracks.begin(), recoTracks.end(), mcParticle.globalIndex()) != recoTracks.end()) { - histos.fill(HIST("Efficiency"), mcParticle.pt(), mcParticle.eta(), 1.); + histos.fill(hDIR + HIST("Efficiency"), mcParticle.pt(), mcParticle.eta(), 1.); } else { - histos.fill(HIST("Efficiency"), mcParticle.pt(), mcParticle.eta(), 0.); + histos.fill(hDIR + HIST("Efficiency"), mcParticle.pt(), mcParticle.eta(), 0.); } } } + + o2::framework::Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + o2::framework::SliceCache cache; + void process(const o2::soa::Join::iterator& collision, + const o2::soa::Join& tracks, + const o2::aod::McParticles& mcParticles, + const o2::aod::McCollisions&) + { + const auto& mcCollision = collision.mcCollision_as(); + const auto& particlesInCollision = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, + mcCollision.globalIndex(), + cache); + processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + // processParticle(particlesInCollision, collision, tracks, mcCollision); + } }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec w; - if (cfgc.options().get("lut-el")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-electron"})); - } - if (cfgc.options().get("lut-mu")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-muon"})); - } - if (cfgc.options().get("lut-pi")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-pion"})); - } - if (cfgc.options().get("lut-ka")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-kaon"})); - } - if (cfgc.options().get("lut-pr")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-proton"})); - } - if (cfgc.options().get("lut-de")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-deuteron"})); - } - if (cfgc.options().get("lut-tr")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-triton"})); - } - if (cfgc.options().get("lut-he")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"alice3-lutmaker-helium3"})); - } - return w; + return o2::framework::WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/Tasks/alice3-qa-multiplicity.cxx b/ALICE3/Tasks/alice3-qa-multiplicity.cxx index b798209dfde..a5440ff8d53 100644 --- a/ALICE3/Tasks/alice3-qa-multiplicity.cxx +++ b/ALICE3/Tasks/alice3-qa-multiplicity.cxx @@ -10,12 +10,22 @@ // or submit itself to any jurisdiction. /// \author Nicolo' Jacazio , CERN -// O2 includes -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/ALICE3/Tasks/alice3-qa-singleparticle.cxx b/ALICE3/Tasks/alice3-qa-singleparticle.cxx index 70559fdd33c..fcd3f92bbc9 100644 --- a/ALICE3/Tasks/alice3-qa-singleparticle.cxx +++ b/ALICE3/Tasks/alice3-qa-singleparticle.cxx @@ -15,14 +15,29 @@ /// \brief Task to monitor the single particle QA, at the particle and track level, showing the tracked and the origin of particles /// +#include +#include +#include #include +#include #include +#include +#include #include +#include #include #include +#include +#include #include +#include +#include + +#include +#include +#include #include using namespace o2; diff --git a/ALICE3/Tasks/alice3-taskcorrelationDDbar.cxx b/ALICE3/Tasks/alice3-taskcorrelationDDbar.cxx index b6c8058f747..67ada10b571 100644 --- a/ALICE3/Tasks/alice3-taskcorrelationDDbar.cxx +++ b/ALICE3/Tasks/alice3-taskcorrelationDDbar.cxx @@ -14,17 +14,26 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" -// #include "PWGHF/DataModel/CandidateReconstructionTables.h" -// #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/ALICE3/Tasks/alice3DecayerQA.cxx b/ALICE3/Tasks/alice3DecayerQA.cxx deleted file mode 100644 index 7eff59fe2d0..00000000000 --- a/ALICE3/Tasks/alice3DecayerQA.cxx +++ /dev/null @@ -1,113 +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 alice3DecayerQA.cxx -/// -/// \brief QA task for otf decayer -/// -/// \author Jesper Karlsson Gumprecht -/// \since Dec 23, 2025 -/// - -#include "ALICE3/DataModel/OTFMCParticle.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamRegistry.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include - -#include - -#include -#include - -using namespace o2; -using namespace o2::framework; - -struct Alice3DecayerQA { - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - 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"}; - - Partition trueEl = aod::mcparticle::pdgCode == static_cast(kElectron); - Partition trueMu = aod::mcparticle::pdgCode == static_cast(kMuonMinus); - Partition truePi = aod::mcparticle::pdgCode == static_cast(kPiPlus); - Partition trueKa = aod::mcparticle::pdgCode == static_cast(kKMinus); - Partition truePr = aod::mcparticle::pdgCode == static_cast(kProton); - - Partition trueElWithDau = aod::mcparticle::pdgCode == static_cast(kElectron); - Partition trueMuWithDau = aod::mcparticle::pdgCode == static_cast(kMuonMinus); - Partition truePiWithDau = aod::mcparticle::pdgCode == static_cast(kPiPlus); - Partition trueKaWithDau = aod::mcparticle::pdgCode == static_cast(kKMinus); - Partition truePrWithDau = aod::mcparticle::pdgCode == static_cast(kProton); - - void init(o2::framework::InitContext&) - { - histos.add("DefaultMC/hElPt", "hElPt", kTH1D, {axisPt}); - histos.add("DefaultMC/hMuPt", "hMuPt", kTH1D, {axisPt}); - histos.add("DefaultMC/hPiPt", "hPiPt", kTH1D, {axisPt}); - histos.add("DefaultMC/hKaPt", "hKaPt", kTH1D, {axisPt}); - histos.add("DefaultMC/hPrPt", "hPrPt", kTH1D, {axisPt}); - - histos.add("MCWithDau/hElPt", "hElPt", kTH1D, {axisPt}); - histos.add("MCWithDau/hMuPt", "hMuPt", kTH1D, {axisPt}); - histos.add("MCWithDau/hPiPt", "hPiPt", kTH1D, {axisPt}); - histos.add("MCWithDau/hKaPt", "hKaPt", kTH1D, {axisPt}); - histos.add("MCWithDau/hPrPt", "hPrPt", kTH1D, {axisPt}); - } - - void processMC(const aod::McParticles&) - { - for (auto const& particle : trueEl) { - histos.fill(HIST("DefaultMC/hElPt"), particle.pt()); - } - for (auto const& particle : trueMu) { - histos.fill(HIST("DefaultMC/hMuPt"), particle.pt()); - } - for (auto const& particle : truePi) { - histos.fill(HIST("DefaultMC/hPiPt"), particle.pt()); - } - for (auto const& particle : trueKa) { - histos.fill(HIST("DefaultMC/hKaPt"), particle.pt()); - } - for (auto const& particle : truePr) { - histos.fill(HIST("DefaultMC/hPrPt"), particle.pt()); - } - } - - void processMCWithDau(const aod::McParticlesWithDau&) - { - for (auto const& particle : trueElWithDau) { - histos.fill(HIST("MCWithDau/hElPt"), particle.pt()); - } - for (auto const& particle : trueMuWithDau) { - histos.fill(HIST("MCWithDau/hMuPt"), particle.pt()); - } - for (auto const& particle : truePiWithDau) { - histos.fill(HIST("MCWithDau/hPiPt"), particle.pt()); - } - for (auto const& particle : trueKaWithDau) { - histos.fill(HIST("MCWithDau/hKaPt"), particle.pt()); - } - for (auto const& particle : truePrWithDau) { - histos.fill(HIST("MCWithDau/hPrPt"), particle.pt()); - } - } - - PROCESS_SWITCH(Alice3DecayerQA, processMC, "fill MC-only histograms", true); - PROCESS_SWITCH(Alice3DecayerQA, processMCWithDau, "fill MC-with-dau histograms", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& ctx) -{ - return WorkflowSpec{adaptAnalysisTask(ctx)}; -} diff --git a/ALICE3/Tasks/alice3DecayerQa.cxx b/ALICE3/Tasks/alice3DecayerQa.cxx new file mode 100644 index 00000000000..cf1c369d17f --- /dev/null +++ b/ALICE3/Tasks/alice3DecayerQa.cxx @@ -0,0 +1,183 @@ +// 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 alice3DecayerQA.cxx +/// +/// \brief QA task for otf decayer +/// +/// \author Jesper Karlsson Gumprecht +/// \since Dec 23, 2025 +/// + +#include "ALICE3/DataModel/OTFMCParticle.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace o2; +using namespace o2::framework; + +struct Alice3DecayerQA { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + struct : ConfigurableGroup { + ConfigurableAxis axisCollisionId{"axisCollisionId", {1000, 0, 999}, "CollisionId axis for QA histograms"}; + ConfigurableAxis axisPdgCode{"axisPdgCode", {1000, 0, 999}, "PdgCode axis for QA histograms"}; + ConfigurableAxis axisStatusCode{"axisStatusCode", {1000, 0, 999}, "StatusCode axis for QA histograms"}; + ConfigurableAxis axisFlags{"axisFlags", {10, 0, 9}, "Flags axis for QA histograms"}; + ConfigurableAxis axisMothersIds{"axisMothersIds", {1000, 0, 999}, "MothersIds axis for QA histograms"}; + ConfigurableAxis axisDaughtersIds{"axisDaughtersIds", {1000, 0, 999}, "DaughtersIds axis for QA histograms"}; + ConfigurableAxis axisWeight{"axisWeight", {2, 0, 1}, "Weight axis for QA histograms"}; + ConfigurableAxis axisPos{"axisPos", {1000, 0, 999}, "Position axis for QA histograms"}; + ConfigurableAxis axisPhi{"axisPhi", {720, -360, 360}, "Phi axis for QA histograms"}; + ConfigurableAxis axisEta{"axisEta", {80, -4, 4}, "Eta axis for QA histograms"}; + ConfigurableAxis axisRapidity{"axisRapidity", {80, -4, 4}, "Rapidity axis for QA histograms"}; + ConfigurableAxis axisIsAlive{"axisIsAlive", {2, 0, 1}, "IsAlive axis for QA histograms"}; + ConfigurableAxis axisIsPrimary{"axisIsPrimary", {2, 0, 1}, "IsPrimary axis for QA histograms"}; + 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"}; + } axes; + + Partition trueEl = aod::mcparticle::pdgCode == static_cast(kElectron); + Partition trueMu = aod::mcparticle::pdgCode == static_cast(kMuonMinus); + Partition truePi = aod::mcparticle::pdgCode == static_cast(kPiPlus); + Partition trueKa = aod::mcparticle::pdgCode == static_cast(kKMinus); + Partition truePr = aod::mcparticle::pdgCode == static_cast(kProton); + + Partition trueElWithDau = aod::mcparticle::pdgCode == static_cast(kElectron); + Partition trueMuWithDau = aod::mcparticle::pdgCode == static_cast(kMuonMinus); + Partition truePiWithDau = aod::mcparticle::pdgCode == static_cast(kPiPlus); + Partition trueKaWithDau = aod::mcparticle::pdgCode == static_cast(kKMinus); + Partition truePrWithDau = aod::mcparticle::pdgCode == static_cast(kProton); + + void init(o2::framework::InitContext&) + { + histos.add("DefaultMC/hElPt", "hElPt", kTH1D, {axes.axisPt}); + histos.add("DefaultMC/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); + histos.add("DefaultMC/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); + histos.add("DefaultMC/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); + histos.add("DefaultMC/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); + + histos.add("MCWithDau/hElPt", "hElPt", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hMuPt", "hMuPt", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hPiPt", "hPiPt", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hKaPt", "hKaPt", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hPrPt", "hPrPt", kTH1D, {axes.axisPt}); + + histos.add("MCWithDau/hCollisionId", "hCollisionId", kTH1D, {axes.axisCollisionId}); + histos.add("MCWithDau/hPdgCode", "hPdgCode", kTH1D, {axes.axisPdgCode}); + histos.add("MCWithDau/hStatusCode", "hStatusCode", kTH1D, {axes.axisStatusCode}); + histos.add("MCWithDau/hFlags", "hFlags", kTH1D, {axes.axisFlags}); + histos.add("MCWithDau/hMothersIds", "hMothersIds", kTH1D, {axes.axisMothersIds}); + histos.add("MCWithDau/hDaughtersIds", "hDaughtersIds", kTH1D, {axes.axisDaughtersIds}); + histos.add("MCWithDau/hWeight", "hWeight", kTH1D, {axes.axisWeight}); + histos.add("MCWithDau/hVx", "hVx", kTH1D, {axes.axisPos}); + histos.add("MCWithDau/hVy", "hVy", kTH1D, {axes.axisPos}); + histos.add("MCWithDau/hVz", "hVz", kTH1D, {axes.axisPos}); + histos.add("MCWithDau/hVt", "hVt", kTH1D, {axes.axisPos}); + histos.add("MCWithDau/hPhi", "hPhi", kTH1D, {axes.axisPhi}); + histos.add("MCWithDau/hEta", "hEta", kTH1D, {axes.axisEta}); + histos.add("MCWithDau/hRapidity", "hRapidity", kTH1D, {axes.axisRapidity}); + histos.add("MCWithDau/hIsAlive", "hIsAlive", kTH1D, {axes.axisIsAlive}); + histos.add("MCWithDau/hIsPrimary", "hIsPrimary", kTH1D, {axes.axisIsPrimary}); + histos.add("MCWithDau/hPx", "hPx", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hPy", "hPy", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hPz", "hPz", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hPt", "hPt", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hP", "hP", kTH1D, {axes.axisPt}); + histos.add("MCWithDau/hE", "hE", kTH1D, {axes.axisPt}); + } + + void processMC(const aod::McParticles&) + { + for (const auto& particle : trueEl) { + histos.fill(HIST("DefaultMC/hElPt"), particle.pt()); + } + for (const auto& particle : trueMu) { + histos.fill(HIST("DefaultMC/hMuPt"), particle.pt()); + } + for (const auto& particle : truePi) { + histos.fill(HIST("DefaultMC/hPiPt"), particle.pt()); + } + for (const auto& particle : trueKa) { + histos.fill(HIST("DefaultMC/hKaPt"), particle.pt()); + } + for (const auto& particle : truePr) { + histos.fill(HIST("DefaultMC/hPrPt"), particle.pt()); + } + } + + void processMCWithDau(const aod::McCollision&, const aod::McPartWithDaus& particles) + { + for (const auto& particle : trueElWithDau) { + histos.fill(HIST("MCWithDau/hElPt"), particle.pt()); + } + for (const auto& particle : trueMuWithDau) { + histos.fill(HIST("MCWithDau/hMuPt"), particle.pt()); + } + for (const auto& particle : truePiWithDau) { + histos.fill(HIST("MCWithDau/hPiPt"), particle.pt()); + } + for (const auto& particle : trueKaWithDau) { + histos.fill(HIST("MCWithDau/hKaPt"), particle.pt()); + } + for (const auto& particle : truePrWithDau) { + histos.fill(HIST("MCWithDau/hPrPt"), particle.pt()); + } + + for (const auto& particle : particles) { + histos.fill(HIST("MCWithDau/hCollisionId"), particle.mcCollisionId()); + histos.fill(HIST("MCWithDau/hPdgCode"), particle.pdgCode()); + histos.fill(HIST("MCWithDau/hStatusCode"), particle.statusCode()); + histos.fill(HIST("MCWithDau/hFlags"), particle.flags()); + histos.fill(HIST("MCWithDau/hWeight"), particle.weight()); + histos.fill(HIST("MCWithDau/hVx"), particle.vx()); + histos.fill(HIST("MCWithDau/hVy"), particle.vy()); + histos.fill(HIST("MCWithDau/hVz"), particle.vz()); + histos.fill(HIST("MCWithDau/hVt"), particle.vt()); + histos.fill(HIST("MCWithDau/hPhi"), particle.phi()); + histos.fill(HIST("MCWithDau/hEta"), particle.eta()); + histos.fill(HIST("MCWithDau/hRapidity"), particle.y()); + histos.fill(HIST("MCWithDau/hIsAlive"), particle.isAlive()); + histos.fill(HIST("MCWithDau/hIsPrimary"), particle.isPrimary()); + histos.fill(HIST("MCWithDau/hPx"), particle.px()); + histos.fill(HIST("MCWithDau/hPy"), particle.py()); + histos.fill(HIST("MCWithDau/hPz"), particle.pz()); + histos.fill(HIST("MCWithDau/hPt"), particle.pt()); + histos.fill(HIST("MCWithDau/hP"), particle.p()); + histos.fill(HIST("MCWithDau/hE"), particle.e()); + for (const auto& motherParticleId : particle.mothersIds()) { + histos.fill(HIST("MCWithDau/hMothersIds"), motherParticleId); + } + for (const auto& dauParticleId : particle.mothersIds()) { + histos.fill(HIST("MCWithDau/hDaughtersIds"), dauParticleId); + } + } + } + + PROCESS_SWITCH(Alice3DecayerQA, processMC, "fill MC-only histograms", false); + PROCESS_SWITCH(Alice3DecayerQA, processMCWithDau, "fill MC-with-dau histograms", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& ctx) +{ + return WorkflowSpec{adaptAnalysisTask(ctx)}; +} diff --git a/ALICE3/Tasks/alice3Efficiency.cxx b/ALICE3/Tasks/alice3Efficiency.cxx index 7741ea24696..bb44f33a6e2 100644 --- a/ALICE3/Tasks/alice3Efficiency.cxx +++ b/ALICE3/Tasks/alice3Efficiency.cxx @@ -17,16 +17,24 @@ /// \since May 27, 2025 /// +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include #include +#include #include -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ConfigParamRegistry.h" -#include "TEfficiency.h" -#include "THashList.h" - using namespace o2; using namespace o2::framework; std::map effVsPt; diff --git a/ALICE3/Tasks/alice3HfTask3Prong.cxx b/ALICE3/Tasks/alice3HfTask3Prong.cxx index 73fe84e2e63..4f21bada994 100644 --- a/ALICE3/Tasks/alice3HfTask3Prong.cxx +++ b/ALICE3/Tasks/alice3HfTask3Prong.cxx @@ -14,16 +14,11 @@ /// \author Marcello Di Costanzo , Polytechnic University of Turin and INFN Turin #include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "ALICE3/DataModel/OTFPIDTrk.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/RICH.h" #include "ALICE3/Utils/utilsHfAlice3.h" #include "ALICE3/Utils/utilsSelectionsAlice3.h" #include "Common/Core/RecoDecay.h" #include -#include #include #include #include @@ -33,12 +28,12 @@ #include #include #include -#include #include #include +#include #include -#include +#include #include #include @@ -58,6 +53,7 @@ struct Alice3HfTask3Prong { Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_3prongs_alice3::vecBinsPt}, "pT bin limits"}; Configurable fillThn{"fillThn", false, "fill Thn"}; + Configurable fillSwapMassHypo{"fillSwapMassHypo", false, "Flag to fill derived tables with swapped mass hypothesis"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; 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)"}; @@ -87,14 +83,15 @@ struct Alice3HfTask3Prong { HistogramRegistry registry{"registry", {}}; // Names of folders and suffixes for MC signal histograms - constexpr static std::string_view SignalFolders[] = {"signal", "prompt", "nonprompt"}; - constexpr static std::string_view SignalSuffixes[] = {"", "Prompt", "NonPrompt"}; - enum SignalClasses : int { Signal = 0, Prompt, - NonPrompt + NonPrompt, + Bkg, + NSignalClasses }; + constexpr static std::string_view SignalFolders[SignalClasses::NSignalClasses] = {"signal", "prompt", "nonprompt", "background"}; + constexpr static std::string_view SignalSuffixes[SignalClasses::NSignalClasses] = {"", "Prompt", "NonPrompt", "Bkg"}; void init(InitContext&) { @@ -109,9 +106,11 @@ struct Alice3HfTask3Prong { } auto addHistogramsRec = [&](const std::string& histoName, const std::string& xAxisTitle, const std::string& yAxisTitle, const HistogramConfigSpec& configSpec) { - registry.add(("MC/rec/signal/" + histoName + "RecSig").c_str(), ("3-prong cands (matched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); - registry.add(("MC/rec/prompt/" + histoName + "RecSigPrompt").c_str(), ("3-prong cands (matched, prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); - registry.add(("MC/rec/nonprompt/" + histoName + "RecSigNonPrompt").c_str(), ("3-prong cands (matched, non-prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + const char* basePath = "MC/rec"; + registry.add(Form("%s/signal/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Signal].data()), ("3-prong cands (matched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/prompt/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Prompt].data()), ("3-prong cands (matched, prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/nonprompt/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::NonPrompt].data()), ("3-prong cands (matched, non-prompt);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); + registry.add(Form("%s/background/%sRecSig%s", basePath, histoName.c_str(), SignalSuffixes[SignalClasses::Bkg].data()), ("3-prong cands (unmatched);" + xAxisTitle + ";" + yAxisTitle).c_str(), configSpec); }; auto addHistogramsGen = [&](const std::string& histoName, const std::string& xAxisTitle, const std::string& yAxisTitle, const HistogramConfigSpec& configSpec) { @@ -171,12 +170,23 @@ struct Alice3HfTask3Prong { addHistogramsGen("hMass", "inv. mass (p K #pi) (GeV/#it{c}^{2})", "", {HistType::kTH1F, {{600, 1.98, 2.58}}}); /// selection status - registry.add("hSelectionStatus", "3-prong cands;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hCandidateCounter", "Candidate counter;entries", {HistType::kTH1D, {{1, -0.5, 0.5}}}); + auto h2 = registry.add("hSelectionStatus", "3-prong cands;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + h2->GetXaxis()->SetBinLabel(1, "mass hypo 0"); + h2->GetXaxis()->SetBinLabel(2, "mass hypo 1"); + auto h = registry.add("MC/rec/hCandidateCounter", "Candidate counter;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + h->GetXaxis()->SetBinLabel(1, "Calls"); + h->GetXaxis()->SetBinLabel(2, "Candidates"); + h->GetXaxis()->SetBinLabel(3, "Passed Y cut"); + h->GetXaxis()->SetBinLabel(4, "Has MC match"); + + registry.add("MC/rec/hPtDeltaProng0", ";prong 0 (#it{p}_{T}-#it{p}_{T, gen}) (GeV/#it{c});entries", {HistType::kTH1F, {{100, -5, 5.}}}); + registry.add("MC/rec/hPtDeltaProng1", ";prong 1 (#it{p}_{T}-#it{p}_{T, gen}) (GeV/#it{c});entries", {HistType::kTH1F, {{100, -5, 5.}}}); + registry.add("MC/rec/hPtDeltaProng2", ";prong 2 (#it{p}_{T}-#it{p}_{T, gen}) (GeV/#it{c});entries", {HistType::kTH1F, {{100, -5, 5.}}}); + // Number of events processed - registry.add("hNEventsProcessed", "number of events processed;entries;", {HistType::kTH1F, {{2, 0.5, 2.5}}}); - registry.get(HIST("hNEventsProcessed"))->GetXaxis()->SetBinLabel(1, "Generated"); - registry.get(HIST("hNEventsProcessed"))->GetXaxis()->SetBinLabel(2, "Reconstructed"); + h = registry.add("hNEventsProcessed", "number of events processed;entries;", {HistType::kTH1F, {{2, 0.5, 2.5}}}); + h->GetXaxis()->SetBinLabel(1, "Generated"); + h->GetXaxis()->SetBinLabel(2, "Reconstructed"); if (fillThn) { const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; @@ -203,7 +213,7 @@ struct Alice3HfTask3Prong { /// Helper function for filling MC reconstructed histograms for prompt, nonpromt and common (signal) /// \param candidate is a reconstructed candidate /// \tparam SignalType is an enum defining which histogram in which folder (signal, prompt or nonpromt) to fill - template + template void fillHistogramsRecSig(CandidateType const& candidate, float mass, bool isSwapped = false) { static constexpr auto histoPrefix = HIST("MC/rec/") + HIST(SignalFolders[SignalType]) + HIST("/"); @@ -254,19 +264,48 @@ struct Alice3HfTask3Prong { /// \tparam SaveMl indicates whether ML scores are saved in the THnSparse /// \tparam CandsRec is the type of the reconstructed candidates collection /// \param candidates is the collection of reconstructed candidates - template - void fillHistosMcRec(CandsRec const& candidates) + template + void fillHistosMcRec(CandsRec const& candidates, AllParticles const& allParticles) { + registry.fill(HIST("MC/rec/hCandidateCounter"), 0.); for (const auto& candidate : candidates) { - registry.fill(HIST("hCandidateCounter"), 0.); + registry.fill(HIST("MC/rec/hCandidateCounter"), 1.); /// rapidity selection if (yCandRecoMax >= 0. && std::abs(hfHelper.getCandY(candidate)) > yCandRecoMax) { continue; } + registry.fill(HIST("MC/rec/hCandidateCounter"), 2.); + if (candidate.particleMcRec() >= 0) { + registry.fill(HIST("MC/rec/hCandidateCounter"), 3.); + auto mcParticle = allParticles.iteratorAt(candidate.particleMcRec()); + if (mcParticle.has_daughters()) { + auto daughters = mcParticle.daughtersIds(); + LOG(debug) << "Reco candidate matched to MC particle with PDG " << mcParticle.pdgCode() << " daughters: " << daughters.size(); + int prongIdx = 0; + for (int dauId = daughters[0]; dauId <= daughters[1]; dauId++) { + auto dau = allParticles.iteratorAt(dauId); + LOG(debug) << " dauId: " << dauId << " PDG: " << dau.pdgCode() << " with pT: " << dau.pt(); + switch (prongIdx) { + case 0: + registry.fill(HIST("MC/rec/hPtDeltaProng0"), candidate.ptProng0() - dau.pt()); + break; + case 1: + registry.fill(HIST("MC/rec/hPtDeltaProng1"), candidate.ptProng1() - dau.pt()); + break; + case 2: + registry.fill(HIST("MC/rec/hPtDeltaProng2"), candidate.ptProng2() - dau.pt()); + break; + default: + break; + } + prongIdx++; + } + } + } - if (candidate.flagMcRec() != 0) { - // Get the corresponding MC particle. + if (candidate.flagMcRec() != 0) { // Particle is matched to MC truth + // Get the corresponding MC particle. const auto pt = candidate.pt(); const auto originType = candidate.originMcRec(); @@ -274,11 +313,11 @@ struct Alice3HfTask3Prong { registry.fill(HIST("hSelectionStatus"), 0., pt); double mass = hfHelper.getCandMass(candidate); /// Fill histograms - fillHistogramsRecSig(candidate, mass); + fillHistogramsRecSig(candidate, mass, false); if (originType == RecoDecay::OriginType::Prompt) { - fillHistogramsRecSig(candidate, mass); + fillHistogramsRecSig(candidate, mass, false); } else if (originType == RecoDecay::OriginType::NonPrompt) { - fillHistogramsRecSig(candidate, mass); + fillHistogramsRecSig(candidate, mass, false); } if (fillThn) { std::vector valuesToFill{mass, pt}; @@ -291,15 +330,17 @@ struct Alice3HfTask3Prong { valuesToFill.push_back(static_cast(originType)); registry.get(HIST("hSparseRec"))->Fill(valuesToFill.data()); } + } + if (fillSwapMassHypo) { if (candidate.isSelMassHypo1()) { registry.fill(HIST("hSelectionStatus"), 1., pt); double mass = hfHelper.getCandMass(candidate); /// Fill histograms - fillHistogramsRecSig(candidate, mass, true); + fillHistogramsRecSig(candidate, mass, true); if (originType == RecoDecay::OriginType::Prompt) { - fillHistogramsRecSig(candidate, mass, true); + fillHistogramsRecSig(candidate, mass, true); } else if (originType == RecoDecay::OriginType::NonPrompt) { - fillHistogramsRecSig(candidate, mass, true); + fillHistogramsRecSig(candidate, mass, true); } if (fillThn) { std::vector valuesToFill{mass, pt}; @@ -314,6 +355,17 @@ struct Alice3HfTask3Prong { } } } + } else { // Background + if (candidate.isSelMassHypo0()) { + double mass = hfHelper.getCandMass(candidate); + fillHistogramsRecSig(candidate, mass, false); + } + if (fillSwapMassHypo) { + if (candidate.isSelMassHypo1()) { + double mass = hfHelper.getCandMass(candidate); + fillHistogramsRecSig(candidate, mass, true); + } + } } } } @@ -410,7 +462,7 @@ struct Alice3HfTask3Prong { collision.posX(); // to avoid unused variable warning registry.fill(HIST("hNEventsProcessed"), 2.); // Reconstructed } - fillHistosMcRec(candsLc); + fillHistosMcRec(candsLc, mcParticles); fillHistosMcGen(candsGenLcs, mcParticles); } PROCESS_SWITCH(Alice3HfTask3Prong, processLc, "Process Lc w/o ML sels", true); @@ -418,7 +470,7 @@ struct Alice3HfTask3Prong { void processLcWMl(Cands3PRecoWMl const& candsLcWMl, Cands3PGen const& mcParticles) { - fillHistosMcRec(candsLcWMl); + fillHistosMcRec(candsLcWMl, mcParticles); fillHistosMcGen(candsGenLcs, mcParticles); } PROCESS_SWITCH(Alice3HfTask3Prong, processLcWMl, "Process Lc with ML sels", false); diff --git a/ALICE3/Tasks/alice3-multicharm.cxx b/ALICE3/Tasks/alice3Multicharm.cxx similarity index 76% rename from ALICE3/Tasks/alice3-multicharm.cxx rename to ALICE3/Tasks/alice3Multicharm.cxx index 8797759b57b..56689b48530 100644 --- a/ALICE3/Tasks/alice3-multicharm.cxx +++ b/ALICE3/Tasks/alice3Multicharm.cxx @@ -8,55 +8,40 @@ // 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 alice3Multicharm.cxx +/// \brief consumer task for alice 3 multicharm studies +/// \author Jesper Karlsson Gumprecht + // *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* // 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 "PWGLF/DataModel/LFParticleIdentification.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "ALICE3/DataModel/A3DecayFinderTables.h" #include "ALICE3/DataModel/OTFMulticharm.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/tracksAlice3.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Tools/ML/MlResponse.h" #include "Tools/ML/model.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexer.h" -#include "DetectorsVertexing/PVertexerHelpers.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include +#include #include -#include #include #include -#include #include using namespace o2; @@ -64,27 +49,23 @@ using namespace o2::ml; using namespace o2::framework; using namespace o2::framework::expressions; -using multiCharmTracksPID = soa::Join; -using multiCharmTracksFull = soa::Join; +using MultiCharmTracksPID = soa::Join; +using MultiCharmTracksFull = soa::Join; -struct alice3multicharm { +struct Alice3Multicharm { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::map histPointers; - std::vector savedConfigs; - std::string histPath; std::map pdgToBin; o2::ml::OnnxModel bdtMCharm; - std::map metadata; o2::ccdb::CcdbApi ccdbApi; Service ccdb; struct : ConfigurableGroup { std::string prefix = "bdt"; // JSON group name - Configurable ccdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable localPath{"localPath", "MCharm_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; - Configurable pathCCDB{"btdPathCCDB", "Users/j/jekarlss/MLModels", "Path on CCDB"}; + Configurable pathCCDB{"pathCCDB", "Users/j/jekarlss/MLModels", "Path on CCDB"}; Configurable timestampCCDB{"timestampCCDB", 1695750420200, "timestamp of the ONNX file for ML model used to query in CCDB. Please use 1695750420200"}; 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)"}; @@ -131,6 +112,7 @@ struct alice3multicharm { Configurable xiccMinProperLength{"xiccMinProperLength", -1, "Minimum proper length for Xicc decay (cm)"}; Configurable xiccMaxProperLength{"xiccMaxProperLength", 1e+4, "Minimum proper length for Xicc decay (cm)"}; Configurable otfConfig{"otfConfig", 0, "OTF configuration flag"}; + Filter configFilter = (aod::otfmulticharm::lutConfigId == otfConfig); void init(InitContext&) @@ -182,44 +164,6 @@ struct alice3multicharm { hMCharmBuilding->GetXaxis()->SetBinLabel(21, "xiccMaxProperLength"); hMCharmBuilding->GetXaxis()->SetBinLabel(22, "xicMinDecayDistanceFromPV"); - if (doprocessXiccPID || doprocessXiccExtra) { - auto hPdgCodes = histos.add("PIDQA/hPdgCodes", "hPdgCodes", kTH2D, {{3, 0.5, 3.5}, {7, 0.5, 7.5}}); - hPdgCodes->GetXaxis()->SetBinLabel(1, "pi1c"); - hPdgCodes->GetXaxis()->SetBinLabel(2, "pi2c"); - hPdgCodes->GetXaxis()->SetBinLabel(3, "picc"); - hPdgCodes->GetYaxis()->SetBinLabel(1, "el"); - hPdgCodes->GetYaxis()->SetBinLabel(2, "mu"); - hPdgCodes->GetYaxis()->SetBinLabel(3, "pi"); - hPdgCodes->GetYaxis()->SetBinLabel(4, "ka"); - hPdgCodes->GetYaxis()->SetBinLabel(5, "pr"); - hPdgCodes->GetYaxis()->SetBinLabel(6, "xi"); - hPdgCodes->GetYaxis()->SetBinLabel(7, "other"); - pdgToBin.insert({kElectron, 1}); - pdgToBin.insert({kMuonMinus, 2}); - pdgToBin.insert({kPiPlus, 3}); - pdgToBin.insert({kKPlus, 4}); - pdgToBin.insert({kProton, 5}); - pdgToBin.insert({kXiMinus, 6}); - - histos.add("PIDQA/hInnerTofTimeDeltaPi1c", "hInnerTofTimeDeltaPi1c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hInnerTofTimeDeltaPi2c", "hInnerTofTimeDeltaPi2c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hInnerTofTimeDeltaPicc", "hInnerTofTimeDeltaPicc; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hOuterTofTimeDeltaPi1c", "hOuterTofTimeDeltaPi1c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hOuterTofTimeDeltaPi2c", "hOuterTofTimeDeltaPi2c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("PIDQA/hOuterTofTimeDeltaPicc", "hOuterTofTimeDeltaPicc; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - - histos.add("PIDQA/hInnerTofNSigmaPi1c", "hInnerTofNSigmaPi1c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hOuterTofNSigmaPi1c", "hOuterTofNSigmaPi1c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hInnerTofNSigmaPi2c", "hInnerTofNSigmaPi2c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hOuterTofNSigmaPi2c", "hOuterTofNSigmaPi2c; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hInnerTofNSigmaPicc", "hInnerTofNSigmaPicc; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hOuterTofNSigmaPicc", "hOuterTofNSigmaPicc; TOF NSigma pion", kTH2D, {axisPt, axisNSigma}); - - histos.add("PIDQA/hRichNSigmaPi1c", "hRichNSigmaPi1c; RICH NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hRichNSigmaPi2c", "hRichNSigmaPi2c; RICH NSigma pion", kTH2D, {axisPt, axisNSigma}); - histos.add("PIDQA/hRichNSigmaPicc", "hRichNSigmaPicc; RICH NSigma pion", kTH2D, {axisPt, axisNSigma}); - } - if (doprocessXiccExtra) { histos.add("XiccProngs/h3dPos", "h3dPos; Xicc pT (GeV/#it(c)); Pos pT (GeV/#it(c)); Pos #eta", kTH3D, {axisPt, axisPt, axisEta}); histos.add("XiccProngs/h3dNeg", "h3dNeg; Xicc pT (GeV/#it(c)); Neg pT (GeV/#it(c)); Neg #eta", kTH3D, {axisPt, axisPt, axisEta}); @@ -285,12 +229,6 @@ struct alice3multicharm { } } - int getBin(const std::map& pdgToBin, int pdg) - { - auto it = pdgToBin.find(pdg); - return (it != pdgToBin.end()) ? it->second : 7; - } - template void genericProcessXicc(TMCharmCands const& xiccCands) { @@ -505,34 +443,6 @@ struct alice3multicharm { histos.fill(HIST("SelectionQA/hPi2cPt"), xiccCand.pi2cPt()); histos.fill(HIST("SelectionQA/hPiccPt"), xiccCand.piccPt()); - if constexpr (requires { xiccCand.pi1cTofDeltaInner(); }) { // if pid table - histos.fill(HIST("PIDQA/hInnerTofTimeDeltaPi1c"), xiccCand.pi1cTofDeltaInner()); - histos.fill(HIST("PIDQA/hInnerTofTimeDeltaPi2c"), xiccCand.pi2cTofDeltaInner()); - histos.fill(HIST("PIDQA/hInnerTofTimeDeltaPicc"), xiccCand.piccTofDeltaInner()); - histos.fill(HIST("PIDQA/hOuterTofTimeDeltaPi1c"), xiccCand.pi1cTofDeltaOuter()); - histos.fill(HIST("PIDQA/hOuterTofTimeDeltaPi2c"), xiccCand.pi2cTofDeltaOuter()); - histos.fill(HIST("PIDQA/hOuterTofTimeDeltaPicc"), xiccCand.piccTofDeltaOuter()); - histos.fill(HIST("PIDQA/hInnerTofNSigmaPi1c"), xiccCand.pi1cPt(), xiccCand.pi1cTofNSigmaInner()); - histos.fill(HIST("PIDQA/hOuterTofNSigmaPi1c"), xiccCand.pi1cPt(), xiccCand.pi1cTofNSigmaOuter()); - histos.fill(HIST("PIDQA/hInnerTofNSigmaPi2c"), xiccCand.pi2cPt(), xiccCand.pi2cTofNSigmaInner()); - histos.fill(HIST("PIDQA/hOuterTofNSigmaPi2c"), xiccCand.pi2cPt(), xiccCand.pi2cTofNSigmaOuter()); - histos.fill(HIST("PIDQA/hInnerTofNSigmaPicc"), xiccCand.piccPt(), xiccCand.piccTofNSigmaInner()); - histos.fill(HIST("PIDQA/hOuterTofNSigmaPicc"), xiccCand.piccPt(), xiccCand.piccTofNSigmaOuter()); - if (xiccCand.pi1cHasRichSignal()) { - histos.fill(HIST("PIDQA/hRichNSigmaPi1c"), xiccCand.pi1cPt(), xiccCand.pi1cRichNSigma()); - } - if (xiccCand.pi2cHasRichSignal()) { - histos.fill(HIST("PIDQA/hRichNSigmaPi2c"), xiccCand.pi2cPt(), xiccCand.pi2cRichNSigma()); - } - if (xiccCand.piccHasRichSignal()) { - histos.fill(HIST("PIDQA/hRichNSigmaPicc"), xiccCand.piccPt(), xiccCand.piccRichNSigma()); - } - - histos.fill(HIST("PIDQA/hPdgCodes"), 1, getBin(pdgToBin, std::abs(xiccCand.pi1cPdgCode()))); - histos.fill(HIST("PIDQA/hPdgCodes"), 2, getBin(pdgToBin, std::abs(xiccCand.pi2cPdgCode()))); - histos.fill(HIST("PIDQA/hPdgCodes"), 3, getBin(pdgToBin, std::abs(xiccCand.piccPdgCode()))); - } - if constexpr (requires { xiccCand.negPt(); }) { // if extra table histos.fill(HIST("XiccProngs/h3dNeg"), xiccCand.xiccPt(), xiccCand.negPt(), xiccCand.negEta()); histos.fill(HIST("XiccProngs/h3dPos"), xiccCand.xiccPt(), xiccCand.posPt(), xiccCand.posEta()); @@ -555,23 +465,17 @@ struct alice3multicharm { genericProcessXicc(multiCharmTracks); } - void processXiccPID(soa::Filtered const& multiCharmTracks) - { - genericProcessXicc(multiCharmTracks); - } - - void processXiccExtra(soa::Filtered const& multiCharmTracks) + void processXiccExtra(soa::Filtered const& multiCharmTracks) { genericProcessXicc(multiCharmTracks); } - PROCESS_SWITCH(alice3multicharm, processXicc, "find Xicc baryons", true); - PROCESS_SWITCH(alice3multicharm, processXiccPID, "find Xicc baryons with more QA from PID information", false); - PROCESS_SWITCH(alice3multicharm, processXiccExtra, "find Xicc baryons with all QA", false); + PROCESS_SWITCH(Alice3Multicharm, processXicc, "find Xicc baryons", true); + PROCESS_SWITCH(Alice3Multicharm, processXiccExtra, "find Xicc baryons with all QA", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/Tasks/alice3PidEvaluation.cxx b/ALICE3/Tasks/alice3PidEvaluation.cxx index 2ee64ea7623..888b7a27dde 100644 --- a/ALICE3/Tasks/alice3PidEvaluation.cxx +++ b/ALICE3/Tasks/alice3PidEvaluation.cxx @@ -23,23 +23,24 @@ #include "ALICE3/DataModel/OTFPIDTrk.h" #include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFTOF.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CommonUtils/NameConf.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "TH1F.h" -#include "TH2F.h" -#include "TProfile.h" -#include "TVector3.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include #include +#include +#include #include #include #include diff --git a/ALICE3/Tasks/alice3SeparationPower.cxx b/ALICE3/Tasks/alice3SeparationPower.cxx index 2c7a829f5bb..77f425d36d4 100644 --- a/ALICE3/Tasks/alice3SeparationPower.cxx +++ b/ALICE3/Tasks/alice3SeparationPower.cxx @@ -17,21 +17,25 @@ /// \since May 13, 2025 /// -#include "ALICE3/DataModel/OTFRICH.h" #include "ALICE3/DataModel/OTFTOF.h" #include +#include #include +#include #include -#include +#include +#include #include #include #include +#include -#include +#include +#include +#include #include -#include #include using namespace o2; diff --git a/ALICE3/Tasks/alice3-strangeness.cxx b/ALICE3/Tasks/alice3Strangeness.cxx similarity index 54% rename from ALICE3/Tasks/alice3-strangeness.cxx rename to ALICE3/Tasks/alice3Strangeness.cxx index 107356fc2ac..7527db49495 100644 --- a/ALICE3/Tasks/alice3-strangeness.cxx +++ b/ALICE3/Tasks/alice3Strangeness.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \file alice3-strangeness.cxx +/// \file alice3Strangeness.cxx /// /// \brief This task produces invariant mass distributions for strange hadrons /// @@ -17,83 +17,80 @@ /// \since November 20, 2025 /// +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "ALICE3/DataModel/OTFCollision.h" +#include "ALICE3/DataModel/OTFMCParticle.h" #include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFTracks.h" #include "ALICE3/DataModel/tracksAlice3.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include #include -#include -#include -#include -#include -#include -#include #include #include #include #include #include -#include +#include +#include +#include #include #include -#include -#include - -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include +#include #include using namespace o2; using namespace o2::framework; using namespace o2::constants::math; -using alice3tracks = soa::Join; -using fullV0Candidates = soa::Join; -using fullCollisions = soa::Join; +using Alice3Tracks = soa::Join; +using FullV0Candidates = soa::Join; +using FullCascadeCandidates = soa::Join; +using FullCollisions = soa::Join; -struct alice3strangeness { +struct Alice3Strangeness { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable idGeometry{"idGeometry", 0, "geometry ID used for propagation"}; - struct ConfigurableGroup { + struct : ConfigurableGroup { 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 axisK0Mass{"axisK0Mass", {200, 0.4f, 0.6f}, ""}; ConfigurableAxis axisLambdaMass{"axisLambdaMass", {200, 1.08f, 1.2f}, ""}; + ConfigurableAxis axisXiMass{"axisXiMass", {200, 1.22f, 1.42f}, ""}; + ConfigurableAxis axisOmegaMass{"axisOmegaMass", {200, 1.57f, 1.77f}, ""}; ConfigurableAxis axisVertexZ{"axisVertexZ", {40, -20, 20}, "vertex Z (cm)"}; ConfigurableAxis axisDCA{"axisDCA", {200, 0, 5}, "DCA (cm)"}; ConfigurableAxis axisV0Radius{"axisV0Radius", {50, 0.0, 100}, "V0 radius (cm)"}; ConfigurableAxis axisDCAV0Daughters{"axisDCAV0Daughters", {20, 0, 5}, "DCA V0 daughters"}; ConfigurableAxis axisPointingAngle{"axisPointingAngle", {40, 0.0f, 0.4f}, "pointing angle "}; ConfigurableAxis axisProperLifeTime{"axisProperLifeTime", {100, 0.0f, 100.0f}, "proper lifetime (cm)"}; - + ConfigurableAxis axisEta{"axisEta", {100, -5.0f, 5.0f}, "eta"}; } histAxes; struct : ConfigurableGroup { + std::string prefix = "selectionFlags"; Configurable applyRapiditySelection{"applyRapiditySelection", true, "apply rapidity selection"}; - Configurable applyDCAdaughterSelection{"applyDCADaughterSelection", true, "apply DCA daughter selection"}; + Configurable applyDCAdaughterSelection{"applyDCAdaughterSelection", true, "apply DCA daughter selection"}; Configurable applyCosOfPAngleSelection{"applyCosOfPAngleSelection", true, "apply cosine of pointing angle selection"}; - Configurable applyDCAdaughtersToPVSelection{"applyDCADaughtersToPVSelection", true, "apply DCA daughters to primary vertex selection"}; + Configurable applyDCADaughtersToPVSelection{"applyDCADaughtersToPVSelection", true, "apply DCA daughters to primary vertex selection"}; Configurable applyV0RadiusSelection{"applyV0RadiusSelection", true, "apply V0 radius selection"}; Configurable applyArmenterosSelection{"applyArmenterosSelection", true, "apply Armenteros-Podolanski selection"}; Configurable applyCompetingMassRejection{"applyCompetingMassRejection", true, "apply competing mass rejection"}; Configurable applyLifetimeSelection{"applyLifetimeSelection", true, "apply lifetime selection"}; Configurable applyEtaDaughterSelection{"applyEtaDaughterSelection", true, "apply eta daughter selection"}; Configurable doQAforSelectionVariables{"doQAforSelectionVariables", false, "enable QA plots"}; + Configurable analyseOnlyTrueV0s{"analyseOnlyTrueV0s", false, "analyse only true V0s from MC"}; } selectionFlags; struct : ConfigurableGroup { + std::string prefix = "selectionValues"; Configurable yK0Selection{"yK0Selection", 0.5f, "rapidity selection for K0"}; Configurable yLambdaSelection{"yLambdaSelection", 0.5f, "rapidity selection for Lambda"}; Configurable dcaDaughterSelection{"dcaDaughterSelection", 1.0f, "DCA daughter selection"}; @@ -106,12 +103,17 @@ struct alice3strangeness { Configurable lifetimecutambda{"lifetimecutambda", 30, "lifetime cut for Lambda in cm"}; Configurable lifetimecutak0{"lifetimecutak0", 20, "lifetime cut for K0 in cm"}; Configurable etaDaughterSelection{"etaDaughterSelection", 0.8f, "eta daughter selection"}; + Configurable acceptedLambdaMassWindow{"acceptedLambdaMassWindow", 0.2f, "accepted Lambda mass window around PDG mass"}; + Configurable acceptedK0MassWindow{"acceptedK0MassWindow", 0.3f, "accepted K0 mass window around PDG mass"}; + Configurable acceptedXiMassWindow{"acceptedXiMassWindow", 0.5f, "accepted Xi mass window around PDG mass"}; + Configurable acceptedOmegaMassWindow{"acceptedOmegaMassWindow", 0.5f, "accepted Omega mass window around PDG mass"}; } selectionValues; - uint16_t AppliedSelectionCheckMask; + uint16_t appliedSelectionCheckMask; double selectionCheck; double selectionCheckPos; - static constexpr std::string_view kSelectionNames[] = {"DCAV0Daughters", "PointingAngle", "DCAtoPVNegDaughter", "DCAtoPVPosDaughter", "V0Radius", "ProperLifeTime"}; + const int posDaugDCAselIDx = 3; + static constexpr std::string_view KSelectionNames[] = {"DCAV0Daughters", "PointingAngle", "DCAtoPVNegDaughter", "DCAtoPVPosDaughter", "V0Radius", "ProperLifeTime"}; void init(InitContext&) { @@ -120,14 +122,31 @@ struct alice3strangeness { histos.add("K0/hSelections", "", kTH1D, {{10, 0, 10}}); histos.add("K0/hDCANegDaughter", "", kTH1D, {{200, -5, 5}}); histos.add("K0/hDCAPosDaughter", "", kTH1D, {{200, -5, 5}}); + histos.add("Xi/hMassAllCandidates", "hMassAllCandidates", kTH1D, {histAxes.axisXiMass}); + histos.add("Xi/hMassSelected", "hMassSelected", kTH1D, {histAxes.axisXiMass}); + histos.add("hPVz", "hPVz", kTH1F, {histAxes.axisVertexZ}); histos.add("hV0CandidateCounter", "hV0CandidateCounter", kTH1F, {{11, 0, 11}}); - histos.add("reconstructedCandidates/K0/hMass", "hMass", kTH2D, {histAxes.axisK0Mass, histAxes.axisPt}); - histos.add("reconstructedCandidates/Lambda/hMass", "hMass", kTH2D, {histAxes.axisLambdaMass, histAxes.axisPt}); - histos.add("reconstructedCandidates/hArmeterosBeforeAllSelections", "hArmeterosBeforeAllSelections", kTH2D, {{100, -1.0f, 1.0f}, {100, 0.0f, 0.25f}}); - histos.add("reconstructedCandidates/hArmeterosAfterAllSelections", "hArmeterosAfterAllSelections", kTH2D, {{100, -1.0f, 1.0f}, {100, 0.0f, 0.25f}}); + histos.add("reconstructedCandidates/hEtaDaughters", "hEtaDaughters", kTH1F, {histAxes.axisEta}); + histos.add("reconstructedCandidates/K0/hMass", "hMass", kTH3D, {histAxes.axisK0Mass, histAxes.axisPt, histAxes.axisEta}); + histos.add("reconstructedCandidates/K0/hMass1D", "hMass1D", kTH1D, {histAxes.axisK0Mass}); + histos.add("reconstructedCandidates/Lambda/hMass", "hMass", kTH3D, {histAxes.axisLambdaMass, histAxes.axisPt, histAxes.axisEta}); + histos.add("reconstructedCandidates/Lambda/hMass1D", "hMass1D", kTH1D, {histAxes.axisLambdaMass}); + histos.add("reconstructedCandidates/hArmeterosBeforeAllSelections", "hArmeterosBeforeAllSelections", kTH2D, {{100, -1.0f, 1.0f}, {200, 0.0f, 0.5f}}); + histos.add("reconstructedCandidates/hArmeterosAfterAllSelections", "hArmeterosAfterAllSelections", kTH2D, {{100, -1.0f, 1.0f}, {200, 0.0f, 0.5f}}); + + if (doprocessFoundCascadeCandidates) { + histos.add("reconstructedCandidates/Xi/hMassAllCandidates", "hMassAllCandidates", kTH1D, {histAxes.axisXiMass}); + histos.add("reconstructedCandidates/Xi/hMassSelected", "hMassSelected", kTH1D, {histAxes.axisXiMass}); + histos.add("reconstructedCandidates/Omega/hMassAllCandidates", "hMassAllCandidates", kTH1D, {histAxes.axisOmegaMass}); + histos.add("reconstructedCandidates/Omega/hMassSelected", "hMassSelected", kTH1D, {histAxes.axisOmegaMass}); + + histos.addClone("reconstructedCandidates/Xi/", "reconstructedCandidates/AntiXi/"); + histos.addClone("reconstructedCandidates/Omega/", "reconstructedCandidates/AntiOmega/"); + } + if (selectionFlags.doQAforSelectionVariables) { - if (!selectionFlags.applyDCAdaughtersToPVSelection) { + if (!selectionFlags.applyDCADaughtersToPVSelection) { histos.add("reconstructedCandidates/K0/hDCAtoPVNegDaughter", "hDCAtoPVNegDaughter", kTH3D, {histAxes.axisK0Mass, histAxes.axisPt, histAxes.axisDCA}); histos.add("reconstructedCandidates/K0/hDCAtoPVPosDaughter", "hDCAtoPVPosDaughter", kTH3D, {histAxes.axisK0Mass, histAxes.axisPt, histAxes.axisDCA}); histos.add("reconstructedCandidates/Lambda/hDCAtoPVNegDaughter", "hDCAtoPVNegDaughter", kTH3D, {histAxes.axisLambdaMass, histAxes.axisPt, histAxes.axisDCA}); @@ -152,92 +171,105 @@ struct alice3strangeness { } histos.addClone("reconstructedCandidates/Lambda/", "reconstructedCandidates/AntiLambda/"); - AppliedSelectionCheckMask = 0; + appliedSelectionCheckMask = 0; if (!selectionFlags.applyDCAdaughterSelection) - SETBIT(AppliedSelectionCheckMask, 0); + SETBIT(appliedSelectionCheckMask, 0); if (!selectionFlags.applyCosOfPAngleSelection) - SETBIT(AppliedSelectionCheckMask, 1); - if (!selectionFlags.applyDCAdaughtersToPVSelection) { - SETBIT(AppliedSelectionCheckMask, 2); - SETBIT(AppliedSelectionCheckMask, 3); + SETBIT(appliedSelectionCheckMask, 1); + if (!selectionFlags.applyDCADaughtersToPVSelection) { + SETBIT(appliedSelectionCheckMask, 2); + SETBIT(appliedSelectionCheckMask, 3); } if (!selectionFlags.applyV0RadiusSelection) - SETBIT(AppliedSelectionCheckMask, 4); + SETBIT(appliedSelectionCheckMask, 4); if (!selectionFlags.applyLifetimeSelection) - SETBIT(AppliedSelectionCheckMask, 5); + SETBIT(appliedSelectionCheckMask, 5); } - long int nEvents = 0; - void processAllFindableCandidates(aod::Collisions const& collisions, aod::McCollisions const& mcCollisions, aod::UpgradeV0s const& v0Recos, alice3tracks const&) + void processAllFindableCandidates(aod::Collisions const& collisions, aod::McCollisions const&, aod::UpgradeV0s const& v0Recos, aod::UpgradeCascades const& cascRecos, Alice3Tracks const&) { - LOG(info) << "Event processed " << nEvents++ << " :" << collisions.size() << " " << mcCollisions.size(); for (const auto& collision : collisions) { float collisionZ = collision.posZ(); // std::cout << "______ process V0_______" << collision.size() << std::endl; histos.fill(HIST("hPVz"), collisionZ); - for (const auto& v0Cand : v0Recos) { - - auto negV0Daughter = v0Cand.negTrack_as(); // de-reference neg track - auto posV0Daughter = v0Cand.posTrack_as(); // de-reference pos track - - bool isK0 = v0Cand.mK0() > 0; - if (isK0) { - histos.fill(HIST("K0/hMassAllCandidates"), v0Cand.mK0(), v0Cand.pt()); - histos.fill(HIST("K0/hSelections"), 0); // all candidates - histos.fill(HIST("K0/hDCANegDaughter"), negV0Daughter.dcaXY()); - histos.fill(HIST("K0/hDCAPosDaughter"), posV0Daughter.dcaXY()); - if (std::abs(negV0Daughter.dcaXY()) < 0.05) - continue; - histos.fill(HIST("K0/hSelections"), 1); // dcaXY cut - if (std::abs(posV0Daughter.dcaXY()) < 0.05) - continue; - histos.fill(HIST("K0/hSelections"), 2); // dcaXY cut - if (v0Cand.dcaV0Daughters() > 1.0) - continue; - histos.fill(HIST("K0/hSelections"), 3); // dca between daughters - if (v0Cand.v0Radius() < 0.5) - continue; - histos.fill(HIST("K0/hSelections"), 4); // radius cut - if (std::abs(negV0Daughter.eta()) > 0.8 || std::abs(posV0Daughter.eta()) > 0.8) - continue; - histos.fill(HIST("K0/hSelections"), 5); // eta cut - histos.fill(HIST("K0/hMassSelected"), v0Cand.mK0(), v0Cand.pt()); - } + } + + for (const auto& v0Cand : v0Recos) { + auto negV0Daughter = v0Cand.negTrack_as(); // de-reference neg track + auto posV0Daughter = v0Cand.posTrack_as(); // de-reference pos track + + bool isK0 = v0Cand.mK0() > 0; + if (isK0) { + histos.fill(HIST("K0/hMassAllCandidates"), v0Cand.mK0(), v0Cand.pt()); + histos.fill(HIST("K0/hSelections"), 0); // all candidates + histos.fill(HIST("K0/hDCANegDaughter"), negV0Daughter.dcaXY()); + histos.fill(HIST("K0/hDCAPosDaughter"), posV0Daughter.dcaXY()); + if (std::abs(negV0Daughter.dcaXY()) < selectionValues.dcaDaughtersToPVSelection) + continue; + histos.fill(HIST("K0/hSelections"), 1); // dcaXY cut + if (std::abs(posV0Daughter.dcaXY()) < selectionValues.dcaDaughtersToPVSelection) + continue; + histos.fill(HIST("K0/hSelections"), 2); // dcaXY cut + if (v0Cand.dcaV0Daughters() > selectionValues.dcaDaughterSelection) + continue; + histos.fill(HIST("K0/hSelections"), 3); // dca between daughters + if (v0Cand.v0Radius() < selectionValues.v0RadiusSelection) + continue; + histos.fill(HIST("K0/hSelections"), 4); // radius cut + if (std::abs(negV0Daughter.eta()) > selectionValues.etaDaughterSelection || std::abs(posV0Daughter.eta()) > selectionValues.etaDaughterSelection) + continue; + histos.fill(HIST("K0/hSelections"), 5); // eta cut + histos.fill(HIST("K0/hMassSelected"), v0Cand.mK0(), v0Cand.pt()); } } + + for (const auto& cascCand : cascRecos) { + // auto bach = cascCand.bachTrack_as(); // de-reference bach track + // auto neg = cascCand.negTrack_as(); // de-reference neg track + // auto pos = cascCand.posTrack_as(); // de-reference pos track + + // Only XiMinus in the tracker for now + histos.fill(HIST("Xi/hMassAllCandidates"), cascCand.mXi()); + + // TODO Add selections + histos.fill(HIST("Xi/hMassSelected"), cascCand.mXi()); + } } - void processFoundV0Candidates(aod::Collision const& collision, fullV0Candidates const& v0Candidates, alice3tracks const&) + + void processFoundV0Candidates(aod::Collision const& collision, FullV0Candidates const& v0Candidates, Alice3Tracks const&, aod::McParticles const&) { // if(collision.lutConfigId()!=idGeometry) // return; + float collisionZ = collision.posZ(); + histos.fill(HIST("hPVz"), collisionZ); for (auto const& v0 : v0Candidates) { - bool isK0 = (v0.mK0Short() - o2::constants::physics::MassK0Short) < 0.3; - bool isLambda = (v0.mLambda() - o2::constants::physics::MassLambda0) < 0.2; - bool isAntiLambda = (v0.mAntiLambda() - o2::constants::physics::MassLambda0) < 0.2; + bool isK0 = std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < selectionValues.acceptedK0MassWindow; + bool isLambda = std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < selectionValues.acceptedLambdaMassWindow; + bool isAntiLambda = std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < selectionValues.acceptedLambdaMassWindow; - histos.fill(HIST("reconstructedCandidates/hArmeterosBeforeAllSelections"), v0.alpha(), v0.qtarm()); - histos.fill(HIST("hV0CandidateCounter"), 1); + histos.fill(HIST("reconstructedCandidates/hArmeterosBeforeAllSelections"), v0.alpha(), v0.qtArm()); + histos.fill(HIST("hV0CandidateCounter"), 0.5); if (selectionFlags.applyRapiditySelection) { - if (isK0 && std::abs(v0.yK0Short()) < selectionValues.yK0Selection) + if (isK0 && std::abs(v0.yK0Short()) > selectionValues.yK0Selection) continue; - if ((isLambda || isAntiLambda) && std::abs(v0.yLambda()) < selectionValues.yLambdaSelection) + if ((isLambda || isAntiLambda) && std::abs(v0.yLambda()) > selectionValues.yLambdaSelection) continue; } - histos.fill(HIST("hV0CandidateCounter"), 2); + histos.fill(HIST("hV0CandidateCounter"), 1.5); if (selectionFlags.applyDCAdaughterSelection) { if (std::abs(v0.dcaV0Daughters()) > selectionValues.dcaDaughterSelection) continue; } else { selectionCheck = v0.dcaV0Daughters(); } - histos.fill(HIST("hV0CandidateCounter"), 3); + histos.fill(HIST("hV0CandidateCounter"), 2.5); if (selectionFlags.applyCosOfPAngleSelection) { if (v0.cosPA() < selectionValues.cosPAngleSelection) continue; } else { selectionCheck = std::acos(v0.cosPA()); } - histos.fill(HIST("hV0CandidateCounter"), 4); - if (selectionFlags.applyDCAdaughtersToPVSelection) { + histos.fill(HIST("hV0CandidateCounter"), 3.5); + if (selectionFlags.applyDCADaughtersToPVSelection) { if ((std::abs(v0.dcaNegToPV()) < selectionValues.dcaDaughtersToPVSelection) || (std::abs(v0.dcaPosToPV()) < selectionValues.dcaDaughtersToPVSelection)) continue; @@ -245,21 +277,21 @@ struct alice3strangeness { selectionCheckPos = std::abs(v0.dcaPosToPV()); selectionCheck = std::abs(v0.dcaNegToPV()); } - histos.fill(HIST("hV0CandidateCounter"), 5); + histos.fill(HIST("hV0CandidateCounter"), 4.5); if (selectionFlags.applyV0RadiusSelection) { if (v0.v0radius() < selectionValues.v0RadiusSelection) continue; } else { selectionCheck = v0.v0radius(); } - histos.fill(HIST("hV0CandidateCounter"), 6); + histos.fill(HIST("hV0CandidateCounter"), 5.5); if (isK0) { if (selectionFlags.applyArmenterosSelection) { - if (v0.qtarm() < selectionValues.armenterosSelection * std::abs(v0.alpha())) + if (v0.qtArm() < selectionValues.armenterosSelection * std::abs(v0.alpha())) continue; } } - histos.fill(HIST("hV0CandidateCounter"), 7); + histos.fill(HIST("hV0CandidateCounter"), 6.5); if (isK0 && selectionFlags.applyCompetingMassRejection) { if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < selectionValues.competingMassRejectionK0) continue; @@ -270,57 +302,110 @@ struct alice3strangeness { if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < selectionValues.competingMassRejectionLambda) continue; } - histos.fill(HIST("hV0CandidateCounter"), 8); + histos.fill(HIST("hV0CandidateCounter"), 7.5); if (selectionFlags.applyLifetimeSelection) { - if (isK0 && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < selectionValues.lifetimecutak0) + if (isK0 && v0.distOverTotMom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short > selectionValues.lifetimecutak0) continue; - if ((isLambda || isAntiLambda) && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < selectionValues.lifetimecutambda) + if ((isLambda || isAntiLambda) && v0.distOverTotMom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 > selectionValues.lifetimecutambda) continue; } else { if (isK0) - selectionCheck = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; + selectionCheck = v0.distOverTotMom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; else - selectionCheck = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + selectionCheck = v0.distOverTotMom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; } - histos.fill(HIST("hV0CandidateCounter"), 9); + histos.fill(HIST("hV0CandidateCounter"), 8.5); + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); if (selectionFlags.applyEtaDaughterSelection) { - auto posTrack = v0.template posTrack_as(); - auto negTrack = v0.template negTrack_as(); if (std::abs(posTrack.eta()) > selectionValues.etaDaughterSelection || std::abs(negTrack.eta()) > selectionValues.etaDaughterSelection) continue; } - histos.fill(HIST("hV0CandidateCounter"), 10); + histos.fill(HIST("reconstructedCandidates/hEtaDaughters"), posTrack.eta()); + histos.fill(HIST("reconstructedCandidates/hEtaDaughters"), negTrack.eta()); + histos.fill(HIST("hV0CandidateCounter"), 9.5); - histos.fill(HIST("reconstructedCandidates/hArmeterosAfterAllSelections"), v0.alpha(), v0.qtarm()); + histos.fill(HIST("reconstructedCandidates/hArmeterosAfterAllSelections"), v0.alpha(), v0.qtArm()); if (selectionFlags.doQAforSelectionVariables) { static_for<0, 5>([&](auto i) { constexpr int In = i.value; - if (TESTBIT(AppliedSelectionCheckMask, In)) { - if (In == 3) + if (TESTBIT(appliedSelectionCheckMask, In)) { + if (In == posDaugDCAselIDx) selectionCheck = selectionCheckPos; if (isK0) - histos.fill(HIST("reconstructedCandidates/K0/h") + HIST(kSelectionNames[In]), v0.mK0Short(), v0.pt(), selectionCheck); + histos.fill(HIST("reconstructedCandidates/K0/h") + HIST(KSelectionNames[In]), v0.mK0Short(), v0.pt(), selectionCheck); if (isLambda) - histos.fill(HIST("reconstructedCandidates/Lambda/h") + HIST(kSelectionNames[In]), v0.mLambda(), v0.pt(), selectionCheck); + histos.fill(HIST("reconstructedCandidates/Lambda/h") + HIST(KSelectionNames[In]), v0.mLambda(), v0.pt(), selectionCheck); if (isAntiLambda) - histos.fill(HIST("reconstructedCandidates/AntiLambda/h") + HIST(kSelectionNames[In]), v0.mAntiLambda(), v0.pt(), selectionCheck); + histos.fill(HIST("reconstructedCandidates/AntiLambda/h") + HIST(KSelectionNames[In]), v0.mAntiLambda(), v0.pt(), selectionCheck); } }); } - if (isK0) - histos.fill(HIST("reconstructedCandidates/K0/hMass"), v0.mK0Short(), v0.pt()); - if (isLambda) - histos.fill(HIST("reconstructedCandidates/Lambda/hMass"), v0.mLambda(), v0.pt()); - if (isAntiLambda) - histos.fill(HIST("reconstructedCandidates/AntiLambda/hMass"), v0.mAntiLambda(), v0.pt()); + if (isK0) { + histos.fill(HIST("reconstructedCandidates/K0/hMass"), v0.mK0Short(), v0.pt(), v0.eta()); + histos.fill(HIST("reconstructedCandidates/K0/hMass1D"), v0.mK0Short()); + } + if (isLambda) { + histos.fill(HIST("reconstructedCandidates/Lambda/hMass"), v0.mLambda(), v0.pt(), v0.eta()); + histos.fill(HIST("reconstructedCandidates/Lambda/hMass1D"), v0.mLambda()); + } + if (isAntiLambda) { + histos.fill(HIST("reconstructedCandidates/AntiLambda/hMass"), v0.mAntiLambda(), v0.pt(), v0.eta()); + histos.fill(HIST("reconstructedCandidates/AntiLambda/hMass1D"), v0.mAntiLambda()); + } } } - PROCESS_SWITCH(alice3strangeness, processAllFindableCandidates, "", false); - PROCESS_SWITCH(alice3strangeness, processFoundV0Candidates, "", true); + + void processFoundCascadeCandidates(aod::Collision const&, FullCascadeCandidates const& cascadeCandidates, Alice3Tracks const&, aod::McParticles const&) + { + for (const auto& casc : cascadeCandidates) { + const bool isXi = (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) < selectionValues.acceptedXiMassWindow) && casc.sign() > 0; + const bool isOm = (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < selectionValues.acceptedOmegaMassWindow) && casc.sign() > 0; + const bool isAntiXi = (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) < selectionValues.acceptedXiMassWindow) && casc.sign() < 0; + const bool isAntiOm = (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < selectionValues.acceptedOmegaMassWindow) && casc.sign() < 0; + + if (isXi) { + histos.fill(HIST("reconstructedCandidates/Xi/hMassAllCandidates"), casc.mXi()); + } + + if (isOm) { + histos.fill(HIST("reconstructedCandidates/Omega/hMassAllCandidates"), casc.mOmega()); + } + + if (isAntiXi) { + histos.fill(HIST("reconstructedCandidates/AntiXi/hMassAllCandidates"), casc.mXi()); + } + + if (isAntiOm) { + histos.fill(HIST("reconstructedCandidates/AntiOmega/hMassAllCandidates"), casc.mOmega()); + } + + // TODO Add selections + if (isXi) { + histos.fill(HIST("reconstructedCandidates/Xi/hMassSelected"), casc.mXi()); + } + + if (isOm) { + histos.fill(HIST("reconstructedCandidates/Omega/hMassSelected"), casc.mOmega()); + } + + if (isAntiXi) { + histos.fill(HIST("reconstructedCandidates/AntiXi/hMassSelected"), casc.mXi()); + } + + if (isAntiOm) { + histos.fill(HIST("reconstructedCandidates/AntiOmega/hMassSelected"), casc.mOmega()); + } + } + } + + PROCESS_SWITCH(Alice3Strangeness, processAllFindableCandidates, "", false); + PROCESS_SWITCH(Alice3Strangeness, processFoundV0Candidates, "", true); + PROCESS_SWITCH(Alice3Strangeness, processFoundCascadeCandidates, "", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/Tasks/alice3TrackingPerformance.cxx b/ALICE3/Tasks/alice3TrackingPerformance.cxx index a5958bab772..fe903bf6176 100644 --- a/ALICE3/Tasks/alice3TrackingPerformance.cxx +++ b/ALICE3/Tasks/alice3TrackingPerformance.cxx @@ -19,14 +19,24 @@ #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamRegistry.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include #include +#include #include using namespace o2; diff --git a/ALICE3/Tasks/pidFTOFqa.cxx b/ALICE3/Tasks/pidFTOFqa.cxx index 52dbaf8dcfa..ba899e4dc85 100644 --- a/ALICE3/Tasks/pidFTOFqa.cxx +++ b/ALICE3/Tasks/pidFTOFqa.cxx @@ -9,14 +9,19 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "ALICE3/DataModel/FTOF.h" -#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/ALICE3/Tasks/pidRICHqa.cxx b/ALICE3/Tasks/pidRICHqa.cxx index 3a8a960b4ed..4a420ffe34f 100644 --- a/ALICE3/Tasks/pidRICHqa.cxx +++ b/ALICE3/Tasks/pidRICHqa.cxx @@ -15,12 +15,28 @@ /// \brief Task to produce QA output of the PID with ALICE3 RICH running on the MC. /// -// O2 includes #include "ALICE3/DataModel/RICH.h" #include "Common/DataModel/PIDResponseTOF.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/PID.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::track; @@ -36,7 +52,7 @@ void customize(std::vector& workflowOptions) std::swap(workflowOptions, options); } -#include "Framework/runDataProcessing.h" +#include namespace o2::aod { diff --git a/ALICE3/Utils/utilsHfAlice3.h b/ALICE3/Utils/utilsHfAlice3.h index b0106f739e4..04d089f8a58 100644 --- a/ALICE3/Utils/utilsHfAlice3.h +++ b/ALICE3/Utils/utilsHfAlice3.h @@ -19,6 +19,11 @@ #include "PWGHF/Core/HfHelper.h" +#include "Common/Core/RecoDecay.h" + +#include +#include + namespace o2::analysis { diff --git a/CODEOWNERS b/CODEOWNERS index 32cb83e7bd2..f2ea6f38a0b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -11,7 +11,7 @@ # @alibuild has to be in each line to allow self approval of PRs -* @AliceO2Group/core @alibuild @jgrosseo @iarsene @ktf @ddobrigk +* @AliceO2Group/core @alibuild @jgrosseo @iarsene @ktf @ddobrigk @dsekihat /Common/CCDB @alibuild @jgrosseo @iarsene @ekryshen @ddobrigk /Common/Tools/Multiplicity @alibuild @ddobrigk @victor-gonzalez /ALICE3 @alibuild @njacazio @hscheid @@ -22,19 +22,33 @@ /DPG/Tasks/FT0 @alibuild @jotwinow @sahilupadhyaya92 @andreasmolander @afurs /DPG/Tasks/FV0 @alibuild @jotwinow @sahilupadhyaya92 @andreasmolander @afurs /DPG/Tasks/FDD @alibuild @jotwinow @sahilupadhyaya92 @andreasmolander @afurs -/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 +/EventFiltering @alibuild @mpuccio @lietava @fgrosa @ariedel-cern +/EventFiltering/PWGHF @alibuild @fgrosa @zhangbiao-phy @mpuccio @lietava @ariedel-cern +/EventFiltering/PWGUD @alibuild @pbuehler @mpuccio @lietava @fgrosa @ariedel-cern +/EventFiltering/PWGLF @alibuild @mpuccio @ercolessi @ChiaraDeMartin95 @lietava @fgrosa @ariedel-cern +/EventFiltering/PWGCF @alibuild @lauraser @mpuccio @lietava @fgrosa @ariedel-cern +/EventFiltering/PWGMM @alibuild @aortizve @mpuccio @lietava @fgrosa @ariedel-cern +/EventFiltering/PWGJE @alibuild @fkrizek @nzardosh @raymondEhlers @mpuccio @lietava @fgrosa @ariedel-cern +/EventFiltering/PWGEM @alibuild @dsekihat @nstrangm @mpuccio @lietava @fgrosa @ariedel-cern + +/PWGCF @alibuild @victor-gonzalez @otonvd @shouqiye +/PWGCF/Core @alibuild @jgrosseo +/PWGCF/DataModel @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye +/PWGCF/TableProducer @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye +/PWGCF/Tasks @alibuild @jgrosseo @jaelpark @victor-gonzalez @otonvd @shouqiye +/PWGCF/EbyEFluctuations @alibuild @SwatiSaha-1997 @isputows @victor-gonzalez @otonvd @shouqiye +/PWGCF/Femto @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/FemtoDream @alibuild @lauraser @ariedel-cern @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/Femto3D @alibuild @glromane @sofiatomassini @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/FemtoUniverse @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/FemtoWorld @alibuild @prchakra @lgraczykCern @majanik @lauraser @dimihayl @victor-gonzalez @otonvd @shouqiye +/PWGCF/Flow @alibuild @majanik @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/GenericFramework @alibuild @EmilGorm @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/MultiparticleCorrelations @alibuild @abilandz @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/JCorran @alibuild @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/TwoParticleCorrelations @alibuild @Luzhiyongg @jaelpark @wenyaCern @victor-gonzalez @otonvd @shouqiye +/PWGCF/Tutorial @alibuild @ariedel-cern @victor-gonzalez @otonvd @shouqiye -/PWGCF @alibuild @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/Core @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/DataModel @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/TableProducer @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane -/PWGCF/Tasks @alibuild @jgrosseo @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane /PWGDQ @alibuild @iarsene @mcoquet642 @lucamicheletti93 @XiaozhiBai /PWGEM @alibuild @feisenhu @dsekihat @ivorobye @jokonig /PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu @hscheid @jokonig @@ -42,34 +56,34 @@ /PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @NicoleBastid @hahassan7 @jpxrk @apalasciano @zhangbiao-phy @gluparel @stefanopolitano @xinyepeng @singhra1994 # PWG-LF /PWGLF @alibuild @omvazque @skundu692 @mpuccio -/PWGLF/DataModel @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter +/PWGLF/DataModel @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova /PWGLF/Tasks/GlobalEventProperties @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @omvazque /PWGLF/TableProducer/GlobalEventProperties @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @omvazque /PWGLF/Tasks/Nuspex @alibuild @omvazque @skundu692 @mpuccio @fmazzasc @maciacco @HorstMa /PWGLF/TableProducer/Nuspex @alibuild @omvazque @skundu692 @mpuccio @fmazzasc @maciacco @HorstMa -/PWGLF/Tasks/Resonances @alibuild @omvazque @skundu692 @mpuccio @dmallick2 @smaff92 -/PWGLF/TableProducer/Resonances @alibuild @omvazque @skundu692 @mpuccio @dmallick2 @smaff92 -/PWGLF/Tasks/Strangeness @alibuild @omvazque @skundu692 @mpuccio @ercolessi @romainschotter -/PWGLF/TableProducer/Strangeness @alibuild @omvazque @mpuccio @skundu692 @ercolessi @romainschotter -/PWGLF/TableProducer/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter -/PWGLF/Tasks/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter -/PWGLF/Utils @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter +/PWGLF/Tasks/Resonances @alibuild @omvazque @skundu692 @mpuccio @dmallick2 @smaff92 @prottayCMT +/PWGLF/TableProducer/Resonances @alibuild @omvazque @skundu692 @mpuccio @dmallick2 @smaff92 @prottayCMT +/PWGLF/Tasks/Strangeness @alibuild @omvazque @skundu692 @mpuccio @ercolessi @romainschotter @lhusova +/PWGLF/TableProducer/Strangeness @alibuild @omvazque @mpuccio @skundu692 @ercolessi @romainschotter @lhusova +/PWGLF/TableProducer/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova +/PWGLF/Tasks/QC @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova +/PWGLF/Utils @alibuild @omvazque @skundu692 @mpuccio @gbencedi @abmodak @fmazzasc @maciacco @HorstMa @dmallick2 @smaff92 @ercolessi @romainschotter @prottayCMT @lhusova # PWG-MM (fused with LF, LF conveners included. Directories to be merged in the future) -/PWGMM @alibuild @mpuccio @skundu692 @aalkin @jgcn -/PWGMM/Mult @alibuild @mpuccio @skundu692 @aalkin @aortizve @ddobrigk @gbencedi @jgcn -/PWGMM/Lumi @alibuild @mpuccio @skundu692 @aalkin @jgcn @gbencedi @abmodak -/PWGMM/UE @alibuild @mpuccio @skundu692 @aalkin @aortizve @jgcn +/PWGMM @alibuild @omvazque @mpuccio @skundu692 @aalkin @jgcn +/PWGMM/Mult @alibuild @omvazque @mpuccio @skundu692 @aalkin @aortizve @ddobrigk @gbencedi @jgcn +/PWGMM/Lumi @alibuild @omvazque @mpuccio @skundu692 @aalkin @jgcn @gbencedi @abmodak +/PWGMM/UE @alibuild @omvazque @mpuccio @skundu692 @aalkin @aortizve @jgcn /PWGUD @alibuild @amatyja @rolavick -/PWGJE @alibuild @lhavener @maoyx @nzardosh @fjonasALICE @mfasDa @mhemmer-cern +/PWGJE @alibuild @lhavener @maoyx @nzardosh @raymondEhlers @fjonasALICE @mfasDa @mhemmer-cern /Tools/PIDML @alibuild @saganatt /Tools/ML @alibuild @fcatalan92 @fmazzasc /Tutorials/PWGCF @alibuild @jgrosseo @victor-gonzalez @zchochul /Tutorials/PWGDQ @alibuild @iarsene @mcoquet @lucamicheletti93 /Tutorials/PWGEM @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu /Tutorials/PWGHF @alibuild @vkucera @fcolamar @fgrosa @gluparel @xinyepeng -/Tutorials/PWGJE @alibuild @lhavener @maoyx @nzardosh @mfasDa @fjonasALICE -/Tutorials/PWGLF @alibuild @alcaliva @lbariogl @chiarapinto @BongHwi @lbarnby @ercolessi @iravasen @njacazio @romainschotter @skundu692 +/Tutorials/PWGJE @alibuild @lhavener @maoyx @nzardosh @raymondEhlers @mfasDa @fjonasALICE +/Tutorials/PWGLF @alibuild @alcaliva @lbariogl @chiarapinto @BongHwi @lbarnby @ercolessi @iravasen @njacazio @romainschotter @skundu692 @lhusova /Tutorials/PWGMM @alibuild @aalkin @ddobrigk /Tutorials/PWGUD @alibuild @pbuehler @amatyja diff --git a/Common/CCDB/macros/upload_trigger_aliases_run3.C b/Common/CCDB/macros/upload_trigger_aliases_run3.C index e946d9117d4..4e26ade06cc 100644 --- a/Common/CCDB/macros/upload_trigger_aliases_run3.C +++ b/Common/CCDB/macros/upload_trigger_aliases_run3.C @@ -30,7 +30,7 @@ void createDefaultAliases(map& mAliases) mAliases[kTVXinTRD] = "CMTVX-B-NOPF-TRD,minbias_TVX"; mAliases[kTVXinEMC] = "C0TVX-B-NOPF-EMC,minbias_TVX_L0,CMTVXTSC-B-NOPF-EMC,CMTVXTCE-B-NOPF-EMC"; mAliases[kTVXinPHOS] = "C0TVX-B-NOPF-PHSCPV,minbias_TVX_L0,CMTVXTSC-B-NOPF-PHSCPV,CMTVXTSC-B-NOPF-PHSCPV"; - mAliases[kTVXinHMP] = "C0TVX-B-NOPF-HMP,minbias_TVX_L0,CMTVXTSC-B-NOPF-HMP"; + mAliases[kTVXinHMP] = "C0TVX-B-NOPF-HMP,minbias_TVX_L0,CMTVXTSC-B-NOPF-HMP,CMTVX-B-NOPF-HMP"; mAliases[kPHOS] = "CTVXPH0-B-NOPF-PHSCPV,mb_PH0_TVX,CPH0SC-B-NOPF-PHSCPV,CPH0CE-B-NOPF-PHSCPV"; } diff --git a/Common/Core/TrackSelectorPID.h b/Common/Core/TrackSelectorPID.h index e8ceaa4fa07..c9daf4057fd 100644 --- a/Common/Core/TrackSelectorPID.h +++ b/Common/Core/TrackSelectorPID.h @@ -133,6 +133,10 @@ class TrackSelectorPidBase nSigma = track.tpcNSigmaPr(); } else if constexpr (pdg == o2::constants::physics::Pdg::kDeuteron) { nSigma = track.tpcNSigmaDe(); + } else if constexpr (pdg == o2::constants::physics::Pdg::kTriton) { + nSigma = track.tpcNSigmaTr(); + } else if constexpr (pdg == o2::constants::physics::Pdg::kHelium3) { + nSigma = track.tpcNSigmaHe(); } else { errorPdg(); } @@ -229,6 +233,10 @@ class TrackSelectorPidBase nSigma = track.tofNSigmaPr(); } else if constexpr (pdg == o2::constants::physics::Pdg::kDeuteron) { nSigma = track.tofNSigmaDe(); + } else if constexpr (pdg == o2::constants::physics::Pdg::kTriton) { + nSigma = track.tofNSigmaTr(); + } else if constexpr (pdg == o2::constants::physics::Pdg::kHelium3) { + nSigma = track.tofNSigmaHe(); } else { errorPdg(); } @@ -567,6 +575,10 @@ class TrackSelectorPidBase return track.bayesID() == o2::track::PID::Proton; } else if constexpr (pdg == o2::constants::physics::Pdg::kDeuteron) { return track.bayesID() == o2::track::PID::Deuteron; + } else if constexpr (pdg == o2::constants::physics::Pdg::kTriton) { + return track.bayesID() == o2::track::PID::Triton; + } else if constexpr (pdg == o2::constants::physics::Pdg::kHelium3) { + return track.bayesID() == o2::track::PID::Helium3; } else { errorPdg(); return false; @@ -597,6 +609,10 @@ class TrackSelectorPidBase prob = track.bayesPr(); } else if constexpr (pdg == o2::constants::physics::Pdg::kDeuteron) { prob = track.bayesDe(); + } else if constexpr (pdg == o2::constants::physics::Pdg::kTriton) { + prob = track.bayesTr(); + } else if constexpr (pdg == o2::constants::physics::Pdg::kHelium3) { + prob = track.bayesHe(); } else { errorPdg(); } @@ -680,5 +696,7 @@ using TrackSelectorPi = TrackSelectorPidBase; using TrackSelectorKa = TrackSelectorPidBase; // Ka using TrackSelectorPr = TrackSelectorPidBase; // Pr using TrackSelectorDe = TrackSelectorPidBase; // De +using TrackSelectorTr = TrackSelectorPidBase; // Tr +using TrackSelectorHe = TrackSelectorPidBase; // He #endif // COMMON_CORE_TRACKSELECTORPID_H_ diff --git a/Common/Core/fwdtrackUtilities.h b/Common/Core/fwdtrackUtilities.h index b30a0316439..883000d6696 100644 --- a/Common/Core/fwdtrackUtilities.h +++ b/Common/Core/fwdtrackUtilities.h @@ -48,33 +48,6 @@ using SMatrix55 = ROOT::Math::SMatrix; using SMatrix5 = ROOT::Math::SVector; -template -o2::track::TrackParCovFwd getTrackParCovFwd(TFwdTrack const& track, TFwdTrackCov const& cov) -{ - // This function works for (glMuon, glMuon), (saMuon, saMuon) and (MFTTrack, MFTTrackCov). - - double chi2 = track.chi2(); - if constexpr (std::is_same_v, aod::MFTTracksCov::iterator>) { - chi2 = track.chi2(); - } else { - if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - chi2 = track.chi2(); - } else if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - chi2 = track.chi2() * (2.f * track.nClusters() - 5.f); - } - } - - SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); - std::vector v1{cov.cXX(), cov.cXY(), cov.cYY(), cov.cPhiX(), cov.cPhiY(), - cov.cPhiPhi(), cov.cTglX(), cov.cTglY(), cov.cTglPhi(), cov.cTglTgl(), - cov.c1PtX(), cov.c1PtY(), cov.c1PtPhi(), cov.c1PtTgl(), cov.c1Pt21Pt2()}; - SMatrix55 tcovs(v1.begin(), v1.end()); - o2::track::TrackParCovFwd trackparCov{track.z(), tpars, tcovs, chi2}; // this is chi2! Not chi2/ndf. - v1.clear(); - v1.shrink_to_fit(); - return trackparCov; -} - /// Produce TrackParCovFwds for MFT and FwdTracks, w/ or w/o cov, with z shift template o2::track::TrackParCovFwd getTrackParCovFwdShift(TFwdTrack const& track, float zshift, TCovariance const&... covOpt) @@ -107,6 +80,8 @@ o2::track::TrackParCovFwd getTrackParCovFwdShift(TFwdTrack const& track, float z cov.cPhiPhi(), cov.cTglX(), cov.cTglY(), cov.cTglPhi(), cov.cTglTgl(), cov.c1PtX(), cov.c1PtY(), cov.c1PtPhi(), cov.c1PtTgl(), cov.c1Pt21Pt2()}; tcovs = SMatrix55(v1.begin(), v1.end()); + v1.clear(); + v1.shrink_to_fit(); } else { tcovs = SMatrix55{}; } @@ -114,17 +89,46 @@ o2::track::TrackParCovFwd getTrackParCovFwdShift(TFwdTrack const& track, float z return o2::track::TrackParCovFwd(track.z() + zshift, tpars, tcovs, chi2); } +template +o2::track::TrackParCovFwd getTrackParCovFwd(TFwdTrack const& track, TFwdTrackCov const& cov) +{ + return getTrackParCovFwdShift(track, 0, cov); + + // // This function works for (glMuon, glMuon), (saMuon, saMuon) and (MFTTrack, MFTTrackCov). + + // double chi2 = track.chi2(); + // if constexpr (std::is_same_v, aod::MFTTracksCov::iterator>) { + // chi2 = track.chi2(); + // } else { + // if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // chi2 = track.chi2(); + // } else if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // chi2 = track.chi2() * (2.f * track.nClusters() - 5.f); + // } + // } + + // SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); + // std::vector v1{cov.cXX(), cov.cXY(), cov.cYY(), cov.cPhiX(), cov.cPhiY(), + // cov.cPhiPhi(), cov.cTglX(), cov.cTglY(), cov.cTglPhi(), cov.cTglTgl(), + // cov.c1PtX(), cov.c1PtY(), cov.c1PtPhi(), cov.c1PtTgl(), cov.c1Pt21Pt2()}; + // SMatrix55 tcovs(v1.begin(), v1.end()); + // o2::track::TrackParCovFwd trackparCov{track.z(), tpars, tcovs, chi2}; // this is chi2! Not chi2/ndf. + // v1.clear(); + // v1.shrink_to_fit(); + // return trackparCov; +} + /// propagate fwdtrack to a certain point. template -o2::dataformats::GlobalFwdTrack propagateMuon(TFwdTrack const& muon, TFwdTrackCov const& cov, TCollision const& collision, const propagationPoint endPoint, const float matchingZ, const float bzkG) +o2::dataformats::GlobalFwdTrack propagateMuon(TFwdTrack const& muon, TFwdTrackCov const& cov, TCollision const& collision, const propagationPoint endPoint, const float matchingZ, const float bzkG, const float zshift = 0.f) { o2::track::TrackParCovFwd trackParCovFwd; if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - trackParCovFwd = getTrackParCovFwd(muon, cov); + trackParCovFwd = getTrackParCovFwdShift(muon, zshift, cov); } else if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - trackParCovFwd = getTrackParCovFwd(muon, muon); + trackParCovFwd = getTrackParCovFwdShift(muon, zshift, muon); } else { - trackParCovFwd = getTrackParCovFwd(muon, muon); + trackParCovFwd = getTrackParCovFwdShift(muon, zshift, muon); } o2::dataformats::GlobalFwdTrack propmuon = propagateTrackParCovFwd(trackParCovFwd, muon.trackType(), collision, endPoint, matchingZ, bzkG); diff --git a/Common/DataModel/CMakeLists.txt b/Common/DataModel/CMakeLists.txt index dc9001e61ff..f70f2a66d16 100644 --- a/Common/DataModel/CMakeLists.txt +++ b/Common/DataModel/CMakeLists.txt @@ -15,7 +15,6 @@ o2physics_add_header_only_library(DataModel EventSelection.h FT0Corrected.h Multiplicity.h - PIDResponse.h PIDResponseITS.h PIDResponseTOF.h PIDResponseTPC.h diff --git a/Common/DataModel/PIDResponse.h b/Common/DataModel/PIDResponse.h deleted file mode 100644 index a2b3c0f7390..00000000000 --- a/Common/DataModel/PIDResponse.h +++ /dev/null @@ -1,45 +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 PIDResponse.h -/// \author Nicolò Jacazio nicolo.jacazio@cern.ch -/// \brief Set of tables, tasks and utilities to provide the interface between -/// the analysis data model and the PID response. This is interim. To be removed -/// - -#ifndef COMMON_DATAMODEL_PIDRESPONSE_H_ -#define COMMON_DATAMODEL_PIDRESPONSE_H_ - -#include "Common/DataModel/PIDResponseTOF.h" // FIXME: remove -#include "Common/DataModel/PIDResponseTPC.h" // FIXME: remove - -namespace o2::aod -{ -namespace pidutils -{ -// Function to pack a float into a binned value in table (interim solution) -template -void packInTable(const float& valueToBin, T& table) -{ - binningType::packInTable(valueToBin, table); -} - -// Function to unpack a binned value into a float -template -float unPackInTable(const typename binningType::binned_t& valueToUnpack) -{ - return binningType::unPackInTable(valueToUnpack); -} -} // namespace pidutils -} // namespace o2::aod - -#endif // COMMON_DATAMODEL_PIDRESPONSE_H_ diff --git a/Common/DataModel/PIDResponseTOF.h b/Common/DataModel/PIDResponseTOF.h index 16ad2e8bf35..72007579e70 100644 --- a/Common/DataModel/PIDResponseTOF.h +++ b/Common/DataModel/PIDResponseTOF.h @@ -254,12 +254,18 @@ namespace pidtofsignal DECLARE_SOA_COLUMN(TOFSignal, tofSignal, float); //! TOF signal from track time DECLARE_SOA_DYNAMIC_COLUMN(EventCollisionTime, eventCollisionTime, //! Event collision time used for the track. Needs the TOF [](float signal, float tMinusTexp, float texp) -> float { return texp + tMinusTexp - signal; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFSignalInAnotherBC, tofSignalInAnotherBC, //! TOF signal but computed in another Bunch Crossing. Needs the original globalBC and the new globalBC to compute the delta time to apply to the signal. + [](float signal, int64_t originalGlobalBC, int64_t newGlobalBC) -> float { + const int64_t deltaBcPos = originalGlobalBC - newGlobalBC; + return signal + o2::constants::lhc::LHCBunchSpacingNS * deltaBcPos * 1000.0f; + }); } // namespace pidtofsignal DECLARE_SOA_TABLE(TOFSignal, "AOD", "TOFSignal", //! Table of the TOF signal pidtofsignal::TOFSignal, - pidtofsignal::EventCollisionTime); + pidtofsignal::EventCollisionTime, + pidtofsignal::TOFSignalInAnotherBC); namespace pidtofevtime { @@ -335,10 +341,10 @@ DECLARE_SOA_COLUMN(TOFNSigmaAl, tofNSigmaAl, float); //! Nsigma separation with //! Expected resolution with the TOF detector for electron (computed on the fly) #define PERSPECIES_TOF_SIGMA_COLUMN(name, id) \ DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSigma##name##Imp, tofExpSigmaDyn##name, \ - [](float tofSignal, \ - float tofExpMom, \ + [](float tofExpMom, \ float momentum, \ float eta, \ + float tofSignal, \ float tofEvTimeErr) -> float { \ return o2::pid::tof::TOFResponseImpl::expectedSigma(tofSignal, \ tofExpMom, \ @@ -360,11 +366,11 @@ PERSPECIES_TOF_SIGMA_COLUMN(Al, o2::track::PID::Alpha); #define PERSPECIES_TOF_SEPARATION_COLUMN(name, id) \ DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigma##name##Imp, tofNSigmaDyn##name, \ - [](const float tofSignal, \ - const float tofExpMom, \ + [](const float tofExpMom, \ const float length, \ const float momentum, \ const float eta, \ + const float tofSignal, \ const float tofEvTime, \ const float tofEvTimeErr) -> float { \ return o2::pid::tof::TOFResponseImpl::nSigma(tofSignal, \ @@ -389,25 +395,45 @@ PERSPECIES_TOF_SEPARATION_COLUMN(Al, o2::track::PID::Alpha); } // namespace pidtof -using TOFExpSigmaDynEl = pidtof::TOFExpSigmaElImp; -using TOFExpSigmaDynMu = pidtof::TOFExpSigmaMuImp; -using TOFExpSigmaDynPi = pidtof::TOFExpSigmaPiImp; -using TOFExpSigmaDynKa = pidtof::TOFExpSigmaKaImp; -using TOFExpSigmaDynPr = pidtof::TOFExpSigmaPrImp; -using TOFExpSigmaDynDe = pidtof::TOFExpSigmaDeImp; -using TOFExpSigmaDynTr = pidtof::TOFExpSigmaTrImp; -using TOFExpSigmaDynHe = pidtof::TOFExpSigmaHeImp; -using TOFExpSigmaDynAl = pidtof::TOFExpSigmaAlImp; - -using TOFNSigmaDynEl = pidtof::TOFNSigmaElImp; -using TOFNSigmaDynMu = pidtof::TOFNSigmaMuImp; -using TOFNSigmaDynPi = pidtof::TOFNSigmaPiImp; -using TOFNSigmaDynKa = pidtof::TOFNSigmaKaImp; -using TOFNSigmaDynPr = pidtof::TOFNSigmaPrImp; -using TOFNSigmaDynDe = pidtof::TOFNSigmaDeImp; -using TOFNSigmaDynTr = pidtof::TOFNSigmaTrImp; -using TOFNSigmaDynHe = pidtof::TOFNSigmaHeImp; -using TOFNSigmaDynAl = pidtof::TOFNSigmaAlImp; +using TOFExpSigmaDynEl = pidtof::TOFExpSigmaElImp; +using TOFExpSigmaDynMu = pidtof::TOFExpSigmaMuImp; +using TOFExpSigmaDynPi = pidtof::TOFExpSigmaPiImp; +using TOFExpSigmaDynKa = pidtof::TOFExpSigmaKaImp; +using TOFExpSigmaDynPr = pidtof::TOFExpSigmaPrImp; +using TOFExpSigmaDynDe = pidtof::TOFExpSigmaDeImp; +using TOFExpSigmaDynTr = pidtof::TOFExpSigmaTrImp; +using TOFExpSigmaDynHe = pidtof::TOFExpSigmaHeImp; +using TOFExpSigmaDynAl = pidtof::TOFExpSigmaAlImp; + +using TOFNSigmaDynEl = pidtof::TOFNSigmaElImp; +using TOFNSigmaDynMu = pidtof::TOFNSigmaMuImp; +using TOFNSigmaDynPi = pidtof::TOFNSigmaPiImp; +using TOFNSigmaDynKa = pidtof::TOFNSigmaKaImp; +using TOFNSigmaDynPr = pidtof::TOFNSigmaPrImp; +using TOFNSigmaDynDe = pidtof::TOFNSigmaDeImp; +using TOFNSigmaDynTr = pidtof::TOFNSigmaTrImp; +using TOFNSigmaDynHe = pidtof::TOFNSigmaHeImp; +using TOFNSigmaDynAl = pidtof::TOFNSigmaAlImp; + +using TOFExpSigmaDynEvTimeEl = pidtof::TOFExpSigmaElImp; +using TOFExpSigmaDynEvTimeMu = pidtof::TOFExpSigmaMuImp; +using TOFExpSigmaDynEvTimePi = pidtof::TOFExpSigmaPiImp; +using TOFExpSigmaDynEvTimeKa = pidtof::TOFExpSigmaKaImp; +using TOFExpSigmaDynEvTimePr = pidtof::TOFExpSigmaPrImp; +using TOFExpSigmaDynEvTimeDe = pidtof::TOFExpSigmaDeImp; +using TOFExpSigmaDynEvTimeTr = pidtof::TOFExpSigmaTrImp; +using TOFExpSigmaDynEvTimeHe = pidtof::TOFExpSigmaHeImp; +using TOFExpSigmaDynEvTimeAl = pidtof::TOFExpSigmaAlImp; + +using TOFNSigmaDynEvTimeEl = pidtof::TOFNSigmaElImp; +using TOFNSigmaDynEvTimeMu = pidtof::TOFNSigmaMuImp; +using TOFNSigmaDynEvTimePi = pidtof::TOFNSigmaPiImp; +using TOFNSigmaDynEvTimeKa = pidtof::TOFNSigmaKaImp; +using TOFNSigmaDynEvTimePr = pidtof::TOFNSigmaPrImp; +using TOFNSigmaDynEvTimeDe = pidtof::TOFNSigmaDeImp; +using TOFNSigmaDynEvTimeTr = pidtof::TOFNSigmaTrImp; +using TOFNSigmaDynEvTimeHe = pidtof::TOFNSigmaHeImp; +using TOFNSigmaDynEvTimeAl = pidtof::TOFNSigmaAlImp; namespace pidtof_tiny { diff --git a/Common/DataModel/Qvectors.h b/Common/DataModel/Qvectors.h index 4a750306cbf..d723d659bc5 100644 --- a/Common/DataModel/Qvectors.h +++ b/Common/DataModel/Qvectors.h @@ -51,24 +51,6 @@ DECLARE_SOA_COLUMN(QvecTPCnegImVec, qvecTPCnegImVec, std::vector); DECLARE_SOA_COLUMN(QvecTPCallReVec, qvecTPCallReVec, std::vector); DECLARE_SOA_COLUMN(QvecTPCallImVec, qvecTPCallImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedRe, qvecShiftedRe, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedIm, qvecShiftedIm, std::vector); - -DECLARE_SOA_COLUMN(QvecShiftedFT0CReVec, qvecShiftedFT0CReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFT0CImVec, qvecShiftedFT0CImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFT0AReVec, qvecShiftedFT0AReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFT0AImVec, qvecShiftedFT0AImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFT0MReVec, qvecShiftedFT0MReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFT0MImVec, qvecShiftedFT0MImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFV0AReVec, qvecShiftedFV0AReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedFV0AImVec, qvecShiftedFV0AImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedTPCposReVec, qvecShiftedTPCposReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedTPCposImVec, qvecShiftedTPCposImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedTPCnegReVec, qvecShiftedTPCnegReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedTPCnegImVec, qvecShiftedTPCnegImVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedTPCallReVec, qvecShiftedTPCallReVec, std::vector); -DECLARE_SOA_COLUMN(QvecShiftedTPCallImVec, qvecShiftedTPCallImVec, std::vector); - DECLARE_SOA_COLUMN(QvecFT0CRe, qvecFT0CRe, float); DECLARE_SOA_COLUMN(QvecFT0CIm, qvecFT0CIm, float); DECLARE_SOA_COLUMN(QvecFT0ARe, qvecFT0ARe, float); @@ -122,9 +104,6 @@ DECLARE_SOA_COLUMN(LabelsBTot, labelsBTot, std::vector); DECLARE_SOA_TABLE(Qvectors, "AOD", "QVECTORDEVS", //! Table with all Qvectors. qvec::Cent, qvec::IsCalibrated, qvec::QvecRe, qvec::QvecIm, qvec::QvecAmp); using Qvector = Qvectors::iterator; -DECLARE_SOA_TABLE(QvectorsShifteds, "AOD", "QVECTORSCDEVS", //! Table with all shifted Qvectors. - qvec::Cent, qvec::IsCalibrated, qvec::QvecShiftedRe, qvec::QvecShiftedIm, qvec::QvecAmp); -using QvectorShifted = QvectorsShifteds::iterator; DECLARE_SOA_TABLE(QvectorFT0Cs, "AOD", "QVECTORSFT0C", qvec::IsCalibrated, qvec::QvecFT0CRe, qvec::QvecFT0CIm, qvec::SumAmplFT0C); DECLARE_SOA_TABLE(QvectorFT0As, "AOD", "QVECTORSFT0A", qvec::IsCalibrated, qvec::QvecFT0ARe, qvec::QvecFT0AIm, qvec::SumAmplFT0A); @@ -142,14 +121,6 @@ DECLARE_SOA_TABLE(QvectorTPCposVecs, "AOD", "QVECTORSTPCPVEC", qvec::IsCalibrate 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); -DECLARE_SOA_TABLE(QvectorShiftedFT0CVecs, "AOD", "QVECSHIFTEDFT0C", qvec::IsCalibrated, qvec::QvecShiftedFT0CReVec, qvec::QvecShiftedFT0CImVec, qvec::SumAmplFT0C); -DECLARE_SOA_TABLE(QvectorShiftedFT0AVecs, "AOD", "QVECSHIFTEDFT0A", qvec::IsCalibrated, qvec::QvecShiftedFT0AReVec, qvec::QvecShiftedFT0AImVec, qvec::SumAmplFT0A); -DECLARE_SOA_TABLE(QvectorShiftedFT0MVecs, "AOD", "QVECSHIFTEDFT0M", qvec::IsCalibrated, qvec::QvecShiftedFT0MReVec, qvec::QvecShiftedFT0MImVec, qvec::SumAmplFT0M); -DECLARE_SOA_TABLE(QvectorShiftedFV0AVecs, "AOD", "QVECSHIFTEDFV0A", qvec::IsCalibrated, qvec::QvecShiftedFV0AReVec, qvec::QvecShiftedFV0AImVec, qvec::SumAmplFV0A); -DECLARE_SOA_TABLE(QvectorShiftedTPCposVecs, "AOD", "QVECSHIFTEDTPCP", qvec::IsCalibrated, qvec::QvecShiftedTPCposReVec, qvec::QvecShiftedTPCposImVec, qvec::NTrkTPCpos, qvec::LabelsTPCpos); -DECLARE_SOA_TABLE(QvectorShiftedTPCnegVecs, "AOD", "QVECSHIFTEDTPCN", qvec::IsCalibrated, qvec::QvecShiftedTPCnegReVec, qvec::QvecShiftedTPCnegImVec, qvec::NTrkTPCneg, qvec::LabelsTPCneg); -DECLARE_SOA_TABLE(QvectorShiftedTPCallVecs, "AOD", "QVECSHIFTEDTPCA", qvec::IsCalibrated, qvec::QvecShiftedTPCallReVec, qvec::QvecShiftedTPCallImVec, qvec::NTrkTPCall, qvec::LabelsTPCall); - using QvectorFT0C = QvectorFT0Cs::iterator; using QvectorFT0A = QvectorFT0As::iterator; using QvectorFT0M = QvectorFT0Ms::iterator; @@ -166,14 +137,6 @@ using QvectorTPCposVec = QvectorTPCposVecs::iterator; using QvectorTPCnegVec = QvectorTPCnegVecs::iterator; using QvectorTPCallVec = QvectorTPCallVecs::iterator; -using QvectorShiftedFT0CVec = QvectorShiftedFT0CVecs::iterator; -using QvectorShiftedFT0AVec = QvectorShiftedFT0AVecs::iterator; -using QvectorShiftedFT0MVec = QvectorShiftedFT0MVecs::iterator; -using QvectorShiftedFV0AVec = QvectorShiftedFV0AVecs::iterator; -using QvectorShiftedTPCposVec = QvectorShiftedTPCposVecs::iterator; -using QvectorShiftedTPCnegVec = QvectorShiftedTPCnegVecs::iterator; -using QvectorShiftedTPCallVec = QvectorShiftedTPCallVecs::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); diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 2282a06b5e7..69cd6084a09 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -22,12 +22,6 @@ o2physics_add_dpl_workflow(trackselection PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(event-selection - SOURCES eventSelection.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCCDB - O2::DataFormatsITSMFT - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(event-selection-service SOURCES eventSelectionService.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCCDB @@ -104,8 +98,8 @@ o2physics_add_dpl_workflow(fwdtrackextension SOURCES fwdtrackextension.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ReconstructionDataFormats - O2::DetectorsBase - O2::DetectorsCommonDataFormats + O2::GlobalTracking + O2::MCHTracking COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(track-to-collision-associator diff --git a/Common/TableProducer/PID/pidTPC.cxx b/Common/TableProducer/PID/pidTPC.cxx index ebb66f8934a..1cdc936a175 100644 --- a/Common/TableProducer/PID/pidTPC.cxx +++ b/Common/TableProducer/PID/pidTPC.cxx @@ -103,17 +103,17 @@ struct tpcPid { // TPC PID Response o2::pid::tpc::Response* response; + // CCDB accessor + Service ccdb; + // Network correction for TPC PID response OnnxModel network; - o2::ccdb::CcdbApi ccdbApi; std::map metadata; - std::map nullmetadata; std::map headers; std::vector speciesNetworkFlags = std::vector(9); std::string networkVersion; // Input parameters - Service ccdb; Configurable paramfile{"param-file", "", "Path to the parametrization object, if empty the parametrization is not taken from file"}; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPath{"ccdbPath", "Analysis/PID/TPC/Response", "Path of the TPC parametrization on the CCDB"}; @@ -242,21 +242,18 @@ struct tpcPid { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdbApi.init(url); if (time != 0) { LOGP(info, "Initialising TPC PID response for fixed timestamp {} and reco pass {}:", time, recoPass.value); ccdb->setTimestamp(time); - response = ccdb->getSpecific(path, time, metadata); - headers = ccdbApi.retrieveHeaders(path, metadata, time); + response = ccdb->getSpecific(path, time, metadata, &headers); if (!response) { LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); - response = ccdb->getForTimeStamp(path, time); - headers = ccdbApi.retrieveHeaders(path, metadata, time); - networkVersion = headers["NN-Version"]; + response = ccdb->getForTimeStamp(path, time, &headers); if (!response) { LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); } } + networkVersion = headers["NN-Version"]; LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << time << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB response->PrintAll(); @@ -274,8 +271,7 @@ struct tpcPid { if (ccdbTimestamp > 0) { /// Fetching network for specific timestamp LOG(info) << "Fetching network for timestamp: " << ccdbTimestamp.value; - bool retrieveSuccess = ccdbApi.retrieveBlob(networkPathCCDB.value, ".", metadata, ccdbTimestamp.value, false, networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(networkPathCCDB.value, metadata, ccdbTimestamp.value); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(networkPathCCDB.value, ".", metadata, ccdbTimestamp.value, false, networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(networkPathLocally.value, enableNetworkOptimizations.value, networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); @@ -318,17 +314,15 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); - networkVersion = headers["NN-Version"]; + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } } + networkVersion = headers["NN-Version"]; LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB response->PrintAll(); @@ -336,14 +330,13 @@ struct tpcPid { if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); - bool retrieveSuccess = ccdbApi.retrieveBlob(networkPathCCDB.value, ".", metadata, bc.timestamp(), false, networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(networkPathCCDB.value, metadata, bc.timestamp()); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(networkPathCCDB.value, ".", metadata, bc.timestamp(), false, networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(networkPathLocally.value, enableNetworkOptimizations.value, networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); std::vector dummyInput(network.getNumInputNodes(), 1.); network.evalModel(dummyInput); - LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number{}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); + LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number {}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); } else { LOG(fatal) << "No valid NN object found matching retrieved Bethe-Bloch parametrisation for pass " << metadata["RecoPassName"] << ". Please ensure that the requested pass has dedicated NN corrections available"; } @@ -553,12 +546,10 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } @@ -651,12 +642,11 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); + if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); - headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } @@ -737,10 +727,10 @@ struct tpcPid { } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); } - response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } diff --git a/Common/TableProducer/PID/pidTPCBase.h b/Common/TableProducer/PID/pidTPCBase.h index bd948bc99e6..494f1bf8685 100644 --- a/Common/TableProducer/PID/pidTPCBase.h +++ b/Common/TableProducer/PID/pidTPCBase.h @@ -100,8 +100,8 @@ typedef struct Str_dEdx_correction { for (int i = 0; i < fMatrix.GetNrows(); i++) { for (int j = 0; j < fMatrix.GetNcols(); j++) { double param = fMatrix(i, j); - double value1 = i > static_cast(vec1.size()) ? 0 : vec1[i]; - double value2 = j > static_cast(vec2.size()) ? 0 : vec2[j]; + double value1 = i >= static_cast(vec1.size()) ? 0 : vec1[i]; + double value2 = j >= static_cast(vec2.size()) ? 0 : vec2[j]; result += param * value1 * value2; } } diff --git a/Common/TableProducer/PID/pidTPCService.cxx b/Common/TableProducer/PID/pidTPCService.cxx index 6ad86916c1f..974f29b2106 100644 --- a/Common/TableProducer/PID/pidTPCService.cxx +++ b/Common/TableProducer/PID/pidTPCService.cxx @@ -47,7 +47,6 @@ struct pidTpcService { // CCDB boilerplate declarations o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service ccdb; - o2::ccdb::CcdbApi ccdbApi; o2::aod::pid::pidTPCProducts products; o2::aod::pid::pidTPCConfigurables pidTPCopts; @@ -61,25 +60,24 @@ struct pidTpcService { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdbApi.init(ccdburl.value); // task-specific - pidTPC.init(ccdb, ccdbApi, initContext, pidTPCopts, metadataInfo); + pidTPC.init(ccdb, initContext, pidTPCopts, metadataInfo); } void processTracksIU(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } void processTracksMCIU(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const&) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } void processTracksIUWithTracksQA(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::TracksQAVersion const& tracksQA) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, tracksQA, products); + pidTPC.process(ccdb, bcs, collisions, tracks, tracksQA, products); } PROCESS_SWITCH(pidTpcService, processTracksIU, "Process TracksIU (Run 3)", true); diff --git a/Common/TableProducer/PID/pidTPCServiceRun2.cxx b/Common/TableProducer/PID/pidTPCServiceRun2.cxx index 184fb4eb6e0..642f3bf08b7 100644 --- a/Common/TableProducer/PID/pidTPCServiceRun2.cxx +++ b/Common/TableProducer/PID/pidTPCServiceRun2.cxx @@ -47,7 +47,6 @@ struct pidTpcServiceRun2 { // CCDB boilerplate declarations o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service ccdb; - o2::ccdb::CcdbApi ccdbApi; o2::aod::pid::pidTPCProducts products; o2::aod::pid::pidTPCConfigurables pidTPCopts; @@ -61,20 +60,19 @@ struct pidTpcServiceRun2 { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdbApi.init(ccdburl.value); // task-specific - pidTPC.init(ccdb, ccdbApi, initContext, pidTPCopts, metadataInfo); + pidTPC.init(ccdb, initContext, pidTPCopts, metadataInfo); } void processTracks(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } void processTracksMC(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const&) { - pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, static_cast(nullptr), products); + pidTPC.process(ccdb, bcs, collisions, tracks, static_cast(nullptr), products); } PROCESS_SWITCH(pidTpcServiceRun2, processTracks, "Process Tracks", true); diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx deleted file mode 100644 index b671247bd80..00000000000 --- a/Common/TableProducer/eventSelection.cxx +++ /dev/null @@ -1,1502 +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 eventSelection.cxx -/// \brief Event selection task -/// -/// \author Evgeny Kryshen and Igor Altsybeev - -#include "Common/DataModel/EventSelection.h" - -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/CCDB/TriggerAliases.h" -#include "Common/Core/MetadataHelper.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::aod::evsel; - -o2::common::core::MetadataHelper metadataInfo; // Metadata helper - -using BCsWithRun2InfosTimestampsAndMatches = soa::Join; -using BCsWithRun3Matchings = soa::Join; -using BCsWithBcSelsRun2 = soa::Join; -using BCsWithBcSelsRun3 = soa::Join; -using FullTracks = soa::Join; -using FullTracksIU = soa::Join; -static const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; -static const int32_t nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; - -struct BcSelectionTask { - Produces bcsel; - Service ccdb; - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Configurable confTriggerBcShift{"triggerBcShift", 0, "set either custom shift or 999 for apass2/apass3 in LHC22o-t"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeFrameStartBorderMargin{"TimeFrameStartBorderMargin", -1, "Number of bcs to cut at the start of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeFrameEndBorderMargin{"TimeFrameEndBorderMargin", -1, "Number of bcs to cut at the end of the Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confCheckRunDurationLimits{"checkRunDurationLimits", false, "Check if the BCs are within the run duration limits"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable> maxInactiveChipsPerLayer{"maxInactiveChipsPerLayer", {8, 8, 8, 111, 111, 195, 195}, "Maximum allowed number of inactive ITS chips per layer"}; - Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - - int lastRun = -1; - int64_t lastTF = -1; - uint32_t lastRCT = 0; - uint64_t sorTimestamp = 0; // default SOR timestamp - uint64_t eorTimestamp = 1; // default EOR timestamp - int64_t bcSOR = -1; // global bc of the start of run - int64_t nBCsPerTF = -1; // duration of TF in bcs, should be 128*3564 or 32*3564 - int rofOffset = -1; // ITS ROF offset, in bc - int rofLength = -1; // ITS ROF length, in bc - int mITSROFrameStartBorderMargin = 10; // default value - int mITSROFrameEndBorderMargin = 20; // default value - int mTimeFrameStartBorderMargin = 300; // default value - int mTimeFrameEndBorderMargin = 4000; // default value - std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata - - TriggerAliases* aliases = nullptr; - EventSelectionParams* par = nullptr; - std::map* mapRCT = nullptr; - std::map> mapInactiveChips; // number of inactive chips vs orbit per layer - int64_t prevOrbitForInactiveChips = 0; // cached next stored orbit in the inactive chip map - int64_t nextOrbitForInactiveChips = 0; // cached previous stored orbit in the inactive chip map - bool isGoodITSLayer3 = true; // default value - bool isGoodITSLayer0123 = true; // default value - bool isGoodITSLayersAll = true; // default value - void init(InitContext&) - { - // ccdb->setURL("http://ccdb-test.cern.ch:8080"); - ccdb->setURL("http://alice-ccdb.cern.ch"); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag - - histos.add("hCounterInvalidBCTimestamp", "", kTH1D, {{1, 0., 1.}}); - } - - void processRun2( - BCsWithRun2InfosTimestampsAndMatches const& bcs, - aod::Zdcs const&, - aod::FV0As const&, - aod::FV0Cs const&, - aod::FT0s const&, - aod::FDDs const&) - { - bcsel.reserve(bcs.size()); - - for (const auto& bc : bcs) { - par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); - aliases = ccdb->getForTimeStamp("EventSelection/TriggerAliases", bc.timestamp()); - // fill fired aliases - uint32_t alias{0}; - uint64_t triggerMask = bc.triggerMask(); - for (const auto& al : aliases->GetAliasToTriggerMaskMap()) { - if (triggerMask & al.second) { - alias |= BIT(al.first); - } - } - uint64_t triggerMaskNext50 = bc.triggerMaskNext50(); - for (const auto& al : aliases->GetAliasToTriggerMaskNext50Map()) { - if (triggerMaskNext50 & al.second) { - alias |= BIT(al.first); - } - } - alias |= BIT(kALL); - - // get timing info from ZDC, FV0, FT0 and FDD - float timeZNA = bc.has_zdc() ? bc.zdc().timeZNA() : -999.f; - float timeZNC = bc.has_zdc() ? bc.zdc().timeZNC() : -999.f; - float timeV0A = bc.has_fv0a() ? bc.fv0a().time() : -999.f; - float timeV0C = bc.has_fv0c() ? bc.fv0c().time() : -999.f; - float timeT0A = bc.has_ft0() ? bc.ft0().timeA() : -999.f; - float timeT0C = bc.has_ft0() ? bc.ft0().timeC() : -999.f; - float timeFDA = bc.has_fdd() ? bc.fdd().timeA() : -999.f; - float timeFDC = bc.has_fdd() ? bc.fdd().timeC() : -999.f; - - LOGF(debug, "timeZNA=%f timeZNC=%f", timeZNA, timeZNC); - LOGF(debug, "timeV0A=%f timeV0C=%f", timeV0A, timeV0C); - LOGF(debug, "timeFDA=%f timeFDC=%f", timeFDA, timeFDC); - LOGF(debug, "timeT0A=%f timeT0C=%f", timeT0A, timeT0C); - - // fill time-based selection criteria - uint64_t selection{0}; - selection |= timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper ? BIT(kIsBBV0A) : 0; - selection |= timeV0C > par->fV0CBBlower && timeV0C < par->fV0CBBupper ? BIT(kIsBBV0C) : 0; - selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(kIsBBFDA) : 0; - selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(kIsBBFDC) : 0; - selection |= !(timeV0A > par->fV0ABGlower && timeV0A < par->fV0ABGupper) ? BIT(kNoBGV0A) : 0; - selection |= !(timeV0C > par->fV0CBGlower && timeV0C < par->fV0CBGupper) ? BIT(kNoBGV0C) : 0; - selection |= !(timeFDA > par->fFDABGlower && timeFDA < par->fFDABGupper) ? BIT(kNoBGFDA) : 0; - selection |= !(timeFDC > par->fFDCBGlower && timeFDC < par->fFDCBGupper) ? BIT(kNoBGFDC) : 0; - selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(kIsBBT0A) : 0; - selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(kIsBBT0C) : 0; - selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(kIsBBZNA) : 0; - selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(kIsBBZNC) : 0; - selection |= !(std::fabs(timeZNA) > par->fZNABGlower && std::fabs(timeZNA) < par->fZNABGupper) ? BIT(kNoBGZNA) : 0; - selection |= !(std::fabs(timeZNC) > par->fZNCBGlower && std::fabs(timeZNC) < par->fZNCBGupper) ? BIT(kNoBGZNC) : 0; - selection |= (std::pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + std::pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(kIsBBZAC) : 0; - - // Calculate V0 multiplicity per ring - float multRingV0A[5] = {0.}; - float multRingV0C[4] = {0.}; - float multFV0A = 0; - float multFV0C = 0; - if (bc.has_fv0a()) { - for (unsigned int i = 0; i < bc.fv0a().amplitude().size(); ++i) { - int ring = bc.fv0a().channel()[i] / 8; - multRingV0A[ring] += bc.fv0a().amplitude()[i]; - multFV0A += bc.fv0a().amplitude()[i]; - } - } - - if (bc.has_fv0c()) { - for (unsigned int i = 0; i < bc.fv0c().amplitude().size(); ++i) { - int ring = bc.fv0c().channel()[i] / 8; - multRingV0C[ring] += bc.fv0c().amplitude()[i]; - multFV0C += bc.fv0c().amplitude()[i]; - } - } - - // Calculate pileup and background related selection flags - // V0A0 excluded from online V0A charge sum => excluding also from offline sum for consistency - float ofV0M = multFV0A + multFV0C - multRingV0A[0]; - float onV0M = bc.v0TriggerChargeA() + bc.v0TriggerChargeC(); - float ofSPD = bc.spdFiredChipsL0() + bc.spdFiredChipsL1(); - float onSPD = bc.spdFiredFastOrL0() + bc.spdFiredFastOrL1(); - float multV0C012 = multRingV0C[0] + multRingV0C[1] + multRingV0C[2]; - - selection |= (onV0M > par->fV0MOnVsOfA + par->fV0MOnVsOfB * ofV0M) ? BIT(kNoV0MOnVsOfPileup) : 0; - selection |= (onSPD > par->fSPDOnVsOfA + par->fSPDOnVsOfB * ofSPD) ? BIT(kNoSPDOnVsOfPileup) : 0; - selection |= (multRingV0C[3] > par->fV0CasymA + par->fV0CasymB * multV0C012) ? BIT(kNoV0Casymmetry) : 0; - selection |= (TESTBIT(selection, kIsBBV0A) || TESTBIT(selection, kIsBBV0C) || ofSPD) ? BIT(kIsINT1) : 0; - selection |= (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : 0) ? BIT(kIsTriggerTVX) : 0; - - // copy remaining selection decisions from eventCuts - uint32_t eventCuts = bc.eventCuts(); - selection |= (eventCuts & 1 << aod::kTimeRangeCut) ? BIT(kIsGoodTimeRange) : 0; - selection |= (eventCuts & 1 << aod::kIncompleteDAQ) ? BIT(kNoIncompleteDAQ) : 0; - selection |= !(eventCuts & 1 << aod::kIsTPCLaserWarmUp) ? BIT(kNoTPCLaserWarmUp) : 0; - selection |= !(eventCuts & 1 << aod::kIsTPCHVdip) ? BIT(kNoTPCHVdip) : 0; - selection |= !(eventCuts & 1 << aod::kIsPileupFromSPD) ? BIT(kNoPileupFromSPD) : 0; - selection |= !(eventCuts & 1 << aod::kIsV0PFPileup) ? BIT(kNoV0PFPileup) : 0; - selection |= (eventCuts & 1 << aod::kConsistencySPDandTrackVertices) ? BIT(kNoInconsistentVtx) : 0; - selection |= (eventCuts & 1 << aod::kPileupInMultBins) ? BIT(kNoPileupInMultBins) : 0; - selection |= (eventCuts & 1 << aod::kPileUpMV) ? BIT(kNoPileupMV) : 0; - selection |= (eventCuts & 1 << aod::kTPCPileUp) ? BIT(kNoPileupTPC) : 0; - - int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; - int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; - int32_t foundFDD = bc.has_fdd() ? bc.fdd().globalIndex() : -1; - int32_t foundZDC = bc.has_zdc() ? bc.zdc().globalIndex() : -1; - - // Fill TVX (T0 vertex) counters - if (TESTBIT(selection, kIsTriggerTVX)) { - histos.get(HIST("hCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); - } - - uint32_t rct = 0; - // Fill bc selection columns - bcsel(alias, selection, rct, foundFT0, foundFV0, foundFDD, foundZDC); - } - } - PROCESS_SWITCH(BcSelectionTask, processRun2, "Process Run2 event selection", true); - - void processRun3(BCsWithRun3Matchings const& bcs, - aod::Zdcs const&, - aod::FV0As const&, - aod::FT0s const&, - aod::FDDs const&) - { - if (bcs.size() == 0) - return; - bcsel.reserve(bcs.size()); - - int run = bcs.iteratorAt(0).runNumber(); - - if (run != lastRun) { - lastRun = run; - int run3min = 500000; - if (run < run3min) { // unanchored Run3 MC - auto runDuration = ccdb->getRunDuration(run, true); // fatalise if timestamps are not found - // SOR and EOR timestamps - sorTimestamp = runDuration.first; // timestamp of the SOR/SOX/STF in ms - eorTimestamp = runDuration.second; // timestamp of the EOR/EOX/ETF in ms - auto ctp = ccdb->getForTimeStamp>("CTP/Calib/OrbitReset", sorTimestamp / 2 + eorTimestamp / 2); - auto orbitResetMUS = (*ctp)[0]; - // first bc of the first orbit - bcSOR = static_cast((sorTimestamp * 1000 - orbitResetMUS) / o2::constants::lhc::LHCOrbitMUS) * nBCsPerOrbit; - // duration of TF in bcs - nBCsPerTF = 32; // hard-coded for Run3 MC (no info from ccdb at the moment) - } else { - auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); - // SOR and EOR timestamps - sorTimestamp = runInfo.sor; - eorTimestamp = runInfo.eor; - // first bc of the first orbit - bcSOR = runInfo.orbitSOR * nBCsPerOrbit; - // duration of TF in bcs - nBCsPerTF = confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : confNumberOfOrbitsPerTF * nBCsPerOrbit; - if (strLPMProductionTag == "LHC25f3") // temporary workaround for MC production LHC25f3 anchored to Pb-Pb 2023 apass5 (to be removed once the info is in ccdb) - nBCsPerTF = 8 * nBCsPerOrbit; - } - - // timestamp of the middle of the run used to access run-wise CCDB entries - int64_t ts = sorTimestamp / 2 + eorTimestamp / 2; - // access ITSROF and TF border margins - par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", ts); - mITSROFrameStartBorderMargin = confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : confITSROFrameStartBorderMargin; - mITSROFrameEndBorderMargin = confITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : confITSROFrameEndBorderMargin; - mTimeFrameStartBorderMargin = confTimeFrameStartBorderMargin < 0 ? par->fTimeFrameStartBorderMargin : confTimeFrameStartBorderMargin; - mTimeFrameEndBorderMargin = confTimeFrameEndBorderMargin < 0 ? par->fTimeFrameEndBorderMargin : confTimeFrameEndBorderMargin; - // ITSROF parameters - auto alppar = ccdb->getForTimeStamp>("ITS/Config/AlpideParam", ts); - rofOffset = alppar->roFrameBiasInBC; - rofLength = alppar->roFrameLengthInBC; - // Trigger aliases - aliases = ccdb->getForTimeStamp("EventSelection/TriggerAliases", ts); - - // prepare map of inactive chips - auto itsDeadMap = ccdb->getForTimeStamp("ITS/Calib/TimeDeadMap", ts); - auto itsDeadMapOrbits = itsDeadMap->getEvolvingMapKeys(); // roughly every second, ~350 TFs = 350x32 orbits - std::vector vClosest; // temporary vector of inactive chip ids for the current orbit range - for (const auto& orbit : itsDeadMapOrbits) { - itsDeadMap->getMapAtOrbit(orbit, vClosest); - // insert initial (orbit,vector) pair for each layer - mapInactiveChips[orbit].resize(o2::itsmft::ChipMappingITS::NLayers, 0); - - // fill map of inactive chips - for (size_t iel = 0; iel < vClosest.size(); iel++) { - uint16_t w1 = vClosest[iel]; - bool isLastInSequence = (w1 & 0x8000) == 0; - uint16_t w2 = isLastInSequence ? w1 + 1 : vClosest[iel + 1]; - uint16_t chipId1 = w1 & 0x7FFF; - uint16_t chipId2 = w2 & 0x7FFF; - for (int chipId = chipId1; chipId < chipId2; chipId++) { - auto layer = o2::itsmft::ChipMappingITS::getLayer(chipId); - mapInactiveChips[orbit][layer]++; - } - } // loop over vector of inactive chip ids - } // loop over orbits - - // QC info - std::map metadata; - metadata["run"] = Form("%d", run); - ccdb->setFatalWhenNull(0); - mapRCT = ccdb->getSpecific>("RCT/Flags/RunFlags", ts, metadata); - ccdb->setFatalWhenNull(1); - if (mapRCT == nullptr) { - LOGP(info, "rct object missing... inserting dummy rct flags"); - mapRCT = new std::map; - uint32_t dummyValue = 1u << 31; // setting bit 31 to indicate that rct object is missing - mapRCT->insert(std::pair(sorTimestamp, dummyValue)); - } - } - - // map from GlobalBC to BcId needed to find triggerBc - std::map mapGlobalBCtoBcId; - for (const auto& bc : bcs) { - mapGlobalBCtoBcId[bc.globalBC()] = bc.globalIndex(); - } - - int triggerBcShift = confTriggerBcShift; - if (confTriggerBcShift == 999) { // o2-linter: disable=magic-number (special shift for early 2022 data) - triggerBcShift = (run <= 526766 || (run >= 526886 && run <= 527237) || (run >= 527259 && run <= 527518) || run == 527523 || run == 527734 || run >= 534091) ? 0 : 294; // o2-linter: disable=magic-number (magic list of runs) - } - - // bc loop - for (auto bc : bcs) { // o2-linter: disable=const-ref-in-for-loop (use bc as nonconst iterator) - // store rct flags - uint32_t rct = lastRCT; - int64_t thisTF = (bc.globalBC() - bcSOR) / nBCsPerTF; - if (mapRCT != nullptr && thisTF != lastTF) { // skip for unanchored runs; do it once per TF - auto itrct = mapRCT->upper_bound(bc.timestamp()); - if (itrct != mapRCT->begin()) - itrct--; - rct = itrct->second; - LOGP(debug, "sor={} eor={} ts={} rct={}", sorTimestamp, eorTimestamp, bc.timestamp(), rct); - lastRCT = rct; - lastTF = thisTF; - } - - uint32_t alias{0}; - // workaround for pp2022 (trigger info is shifted by -294 bcs) - int32_t triggerBcId = mapGlobalBCtoBcId[bc.globalBC() + triggerBcShift]; - if (triggerBcId && aliases) { - auto triggerBc = bcs.iteratorAt(triggerBcId); - uint64_t triggerMask = triggerBc.triggerMask(); - for (const auto& al : aliases->GetAliasToTriggerMaskMap()) { - if (triggerMask & al.second) { - alias |= BIT(al.first); - } - } - } - alias |= BIT(kALL); - - // get timing info from ZDC, FV0, FT0 and FDD - float timeZNA = bc.has_zdc() ? bc.zdc().timeZNA() : -999.f; - float timeZNC = bc.has_zdc() ? bc.zdc().timeZNC() : -999.f; - float timeV0A = bc.has_fv0a() ? bc.fv0a().time() : -999.f; - float timeT0A = bc.has_ft0() ? bc.ft0().timeA() : -999.f; - float timeT0C = bc.has_ft0() ? bc.ft0().timeC() : -999.f; - float timeFDA = bc.has_fdd() ? bc.fdd().timeA() : -999.f; - float timeFDC = bc.has_fdd() ? bc.fdd().timeC() : -999.f; - float timeV0ABG = -999.f; - float timeT0ABG = -999.f; - float timeT0CBG = -999.f; - float timeFDABG = -999.f; - float timeFDCBG = -999.f; - - uint64_t globalBC = bc.globalBC(); - // move to previous bcs to check beam-gas in FT0, FV0 and FDD - int64_t backwardMoveCount = 0; - int64_t deltaBC = 6; // up to 6 bcs back - while (bc.globalBC() + deltaBC >= globalBC) { - if (bc == bcs.begin()) { - break; - } - --bc; - backwardMoveCount++; - int bcDistanceToBeamGasForFT0 = 1; - int bcDistanceToBeamGasForFDD = 5; - if (bc.globalBC() + bcDistanceToBeamGasForFT0 == globalBC) { - timeV0ABG = bc.has_fv0a() ? bc.fv0a().time() : -999.f; - timeT0ABG = bc.has_ft0() ? bc.ft0().timeA() : -999.f; - timeT0CBG = bc.has_ft0() ? bc.ft0().timeC() : -999.f; - } - if (bc.globalBC() + bcDistanceToBeamGasForFDD == globalBC) { - timeFDABG = bc.has_fdd() ? bc.fdd().timeA() : -999.f; - timeFDCBG = bc.has_fdd() ? bc.fdd().timeC() : -999.f; - } - } - // move back to initial position - bc.moveByIndex(backwardMoveCount); - - // fill time-based selection criteria - uint64_t selection{0}; - selection |= timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper ? BIT(kIsBBV0A) : 0; - selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(kIsBBFDA) : 0; - selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(kIsBBFDC) : 0; - selection |= !(timeV0ABG > par->fV0ABGlower && timeV0ABG < par->fV0ABGupper) ? BIT(kNoBGV0A) : 0; - selection |= !(timeFDABG > par->fFDABGlower && timeFDABG < par->fFDABGupper) ? BIT(kNoBGFDA) : 0; - selection |= !(timeFDCBG > par->fFDCBGlower && timeFDCBG < par->fFDCBGupper) ? BIT(kNoBGFDC) : 0; - selection |= !(timeT0ABG > par->fT0ABGlower && timeT0ABG < par->fT0ABGupper) ? BIT(kNoBGT0A) : 0; - selection |= !(timeT0CBG > par->fT0CBGlower && timeT0CBG < par->fT0CBGupper) ? BIT(kNoBGT0C) : 0; - selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(kIsBBT0A) : 0; - selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(kIsBBT0C) : 0; - selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(kIsBBZNA) : 0; - selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(kIsBBZNC) : 0; - selection |= (std::pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + std::pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(kIsBBZAC) : 0; - selection |= !(std::fabs(timeZNA) > par->fZNABGlower && std::fabs(timeZNA) < par->fZNABGupper) ? BIT(kNoBGZNA) : 0; - selection |= !(std::fabs(timeZNC) > par->fZNCBGlower && std::fabs(timeZNC) < par->fZNCBGupper) ? BIT(kNoBGZNC) : 0; - selection |= (bc.has_ft0() ? (bc.ft0().triggerMask() & BIT(o2::ft0::Triggers::bitVertex)) > 0 : 0) ? BIT(kIsTriggerTVX) : 0; - - // check if bc is far from start and end of the ITS RO Frame border - uint16_t bcInITSROF = (globalBC + nBCsPerOrbit - rofOffset) % rofLength; - LOGP(debug, "bcInITSROF={}", bcInITSROF); - selection |= bcInITSROF > mITSROFrameStartBorderMargin && bcInITSROF < rofLength - mITSROFrameEndBorderMargin ? BIT(kNoITSROFrameBorder) : 0; - - // check if bc is far from the Time Frame borders - int64_t bcInTF = (globalBC - bcSOR) % nBCsPerTF; - LOGP(debug, "bcInTF={}", bcInTF); - selection |= bcInTF > mTimeFrameStartBorderMargin && bcInTF < nBCsPerTF - mTimeFrameEndBorderMargin ? BIT(kNoTimeFrameBorder) : 0; - - // check number of inactive chips and set kIsGoodITSLayer3, kIsGoodITSLayer0123, kIsGoodITSLayersAll flags - int64_t orbit = globalBC / nBCsPerOrbit; - if (mapInactiveChips.size() > 0 && (orbit < prevOrbitForInactiveChips || orbit > nextOrbitForInactiveChips)) { - auto it = mapInactiveChips.upper_bound(orbit); - bool isEnd = (it == mapInactiveChips.end()); - if (isEnd) - it--; - nextOrbitForInactiveChips = isEnd ? orbit : it->first; // setting current orbit in case we reached the end of mapInactiveChips - auto vNextInactiveChips = it->second; - if (it != mapInactiveChips.begin() && !isEnd) - it--; - prevOrbitForInactiveChips = it->first; - auto vPrevInactiveChips = it->second; - LOGP(debug, "orbit: {}, previous orbit: {}, next orbit: {} ", orbit, prevOrbitForInactiveChips, nextOrbitForInactiveChips); - LOGP(debug, "next inactive chips: {} {} {} {} {} {} {}", vNextInactiveChips[0], vNextInactiveChips[1], vNextInactiveChips[2], vNextInactiveChips[3], vNextInactiveChips[4], vNextInactiveChips[5], vNextInactiveChips[6]); - LOGP(debug, "prev inactive chips: {} {} {} {} {} {} {}", vPrevInactiveChips[0], vPrevInactiveChips[1], vPrevInactiveChips[2], vPrevInactiveChips[3], vPrevInactiveChips[4], vPrevInactiveChips[5], vPrevInactiveChips[6]); - isGoodITSLayer3 = vPrevInactiveChips[3] <= maxInactiveChipsPerLayer->at(3) && vNextInactiveChips[3] <= maxInactiveChipsPerLayer->at(3); - isGoodITSLayer0123 = true; - for (int i = 0; i < 4; i++) { // o2-linter: disable=magic-number (counting first 4 ITS layers) - isGoodITSLayer0123 &= vPrevInactiveChips[i] <= maxInactiveChipsPerLayer->at(i) && vNextInactiveChips[i] <= maxInactiveChipsPerLayer->at(i); - } - isGoodITSLayersAll = true; - for (int i = 0; i < o2::itsmft::ChipMappingITS::NLayers; i++) { - isGoodITSLayersAll &= vPrevInactiveChips[i] <= maxInactiveChipsPerLayer->at(i) && vNextInactiveChips[i] <= maxInactiveChipsPerLayer->at(i); - } - } - - selection |= isGoodITSLayer3 ? BIT(kIsGoodITSLayer3) : 0; - selection |= isGoodITSLayer0123 ? BIT(kIsGoodITSLayer0123) : 0; - selection |= isGoodITSLayersAll ? BIT(kIsGoodITSLayersAll) : 0; - - // fill found indices - int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; - int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; - int32_t foundFDD = bc.has_fdd() ? bc.fdd().globalIndex() : -1; - int32_t foundZDC = bc.has_zdc() ? bc.zdc().globalIndex() : -1; - LOGP(debug, "foundFT0={}", foundFT0); - - const char* srun = Form("%d", run); - if (bc.timestamp() < sorTimestamp || bc.timestamp() > 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, rct, foundFT0, foundFV0, foundFDD, foundZDC); - } - } - PROCESS_SWITCH(BcSelectionTask, processRun3, "Process Run3 event selection", false); -}; - -struct EventSelectionTask { - SliceCache cache; - Produces evsel; - 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, "-1 - autoset, 0 - data, 1 - MC"}; - Configurable confSigmaBCforHighPtTracks{"confSigmaBCforHighPtTracks", 4, "Custom sigma (in bcs) for collisions with high-pt tracks"}; - - // configurables for occupancy-based event selection - Configurable confTimeIntervalForOccupancyCalculationMin{"TimeIntervalForOccupancyCalculationMin", -40, "Min time diff window for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeIntervalForOccupancyCalculationMax{"TimeIntervalForOccupancyCalculationMax", 100, "Max time diff window for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeRangeVetoOnCollStandard{"TimeRangeVetoOnCollStandard", 10.0, "Exclusion of a collision if there are other collisions nearby, +/- us"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeRangeVetoOnCollNarrow{"TimeRangeVetoOnCollNarrow", 2.0, "Exclusion of a collision if there are other collisions nearby, +/- us"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confFT0CamplCutVetoOnCollInTimeRange{"FT0CamplPerCollCutVetoOnCollInTimeRange", 8000, "Max allowed FT0C amplitude for each nearby collision in +/- time range"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confFT0CamplCutVetoOnCollInROF{"FT0CamplPerCollCutVetoOnCollInROF", 5000, "Max allowed FT0C amplitude for each nearby collision inside this ITS ROF"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confEpsilonVzDiffVetoInROF{"EpsilonVzDiffVetoInROF", 0.3, "Minumum distance to nearby collisions along z inside this ITS ROF, cm"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confUseWeightsForOccupancyVariable{"UseWeightsForOccupancyEstimator", 1, "Use or not the delta-time weights for the occupancy estimator"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) - - Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); - - Preslice perCollision = aod::track::collisionId; - Preslice perCollisionIU = aod::track::collisionId; - - Service ccdb; - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - int lastRun = -1; // last run number (needed to access ccdb only if run!=lastRun) - std::bitset bcPatternB; // bc pattern of colliding bunches - - int64_t bcSOR = -1; // global bc of the start of the first orbit - int64_t nBCsPerTF = -1; // duration of TF in bcs, should be 128*3564 or 32*3564 - int rofOffset = -1; // ITS ROF offset, in bc - int rofLength = -1; // ITS ROF length, in bc - std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata - - int32_t findClosest(int64_t globalBC, const std::map& bcs) - { - auto it = bcs.lower_bound(globalBC); - int64_t bc1 = it->first; - int32_t index1 = it->second; - if (it != bcs.begin()) - --it; - int64_t bc2 = it->first; - int32_t index2 = it->second; - int64_t dbc1 = std::abs(bc1 - globalBC); - int64_t dbc2 = std::abs(bc2 - globalBC); - return (dbc1 <= dbc2) ? index1 : index2; - } - - // helper function to find median time in the vector of TOF or TRD-track times - float getMedian(std::vector v) - { - int medianIndex = v.size() / 2; - std::nth_element(v.begin(), v.begin() + medianIndex, v.end()); - return v[medianIndex]; - } - - // helper function to find closest TVX signal in time and in zVtx - int64_t findBestGlobalBC(int64_t meanBC, int64_t sigmaBC, int32_t nContrib, float zVtxCol, std::map& mapGlobalBcVtxZ) - { - // protection against - if (sigmaBC < 1) - sigmaBC = 1; - - int64_t minBC = meanBC - 3 * sigmaBC; - int64_t maxBC = meanBC + 3 * sigmaBC; - // TODO: use ITS ROF bounds to reduce the search range? - - float zVtxSigma = 2.7 * std::pow(nContrib, -0.466) + 0.024; - zVtxSigma += 1.0; // additional uncertainty due to imperfectections of FT0 time calibration - - auto itMin = mapGlobalBcVtxZ.lower_bound(minBC); - auto itMax = mapGlobalBcVtxZ.upper_bound(maxBC); - - float bestChi2 = 1e+10; - int64_t bestGlobalBC = 0; - for (std::map::iterator it = itMin; it != itMax; ++it) { - float chi2 = std::pow((it->second - zVtxCol) / zVtxSigma, 2) + std::pow(static_cast(it->first - meanBC) / sigmaBC, 2.); - if (chi2 < bestChi2) { - bestChi2 = chi2; - bestGlobalBC = it->first; - } - } - - return bestGlobalBC; - } - - void init(InitContext&) - { - if (metadataInfo.isFullyDefined()) { // Check if the metadata is initialized (only if not forced from the workflow configuration) - if (isMC == -1) { - LOG(info) << "Autosetting the MC mode based on metadata"; - if (metadataInfo.isMC()) { - isMC.value = 1; - } else { - isMC.value = 0; - } - } - } - strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag - - ccdb->setURL("http://alice-ccdb.cern.ch"); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - - histos.add("hColCounterAll", "", kTH1D, {{1, 0., 1.}}); - histos.add("hColCounterTVX", "", kTH1D, {{1, 0., 1.}}); - histos.add("hColCounterAcc", "", kTH1D, {{1, 0., 1.}}); - } - - void process(aod::Collisions const& collisions) - { - evsel.reserve(collisions.size()); - } - - void processRun2(aod::Collision const& col, BCsWithBcSelsRun2 const&, FullTracks const&, aod::FV0Cs const&) - { - auto bc = col.bc_as(); - EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); - bool* applySelection = par->getSelection(muonSelection); - if (isMC == 1) { - applySelection[kIsBBZAC] = 0; - applySelection[kNoV0MOnVsOfPileup] = 0; - applySelection[kNoSPDOnVsOfPileup] = 0; - applySelection[kNoV0Casymmetry] = 0; - applySelection[kNoV0PFPileup] = 0; - } - - int32_t foundBC = bc.globalIndex(); - int32_t foundFT0 = bc.foundFT0Id(); - int32_t foundFV0 = bc.foundFV0Id(); - int32_t foundFDD = bc.foundFDDId(); - int32_t foundZDC = bc.foundZDCId(); - - // copy alias decisions from bcsel table - uint32_t alias = bc.alias_raw(); - - // copy selection decisions from bcsel table - uint64_t selection = bc.selection_raw(); - - // calculate V0C012 multiplicity - float multRingV0C[4] = {0.}; - if (bc.has_fv0c()) { - for (unsigned int i = 0; i < bc.fv0c().amplitude().size(); ++i) { - int ring = bc.fv0c().channel()[i] / 8; - multRingV0C[ring] += bc.fv0c().amplitude()[i]; - } - } - float multV0C012 = multRingV0C[0] + multRingV0C[1] + multRingV0C[2]; - - // applying selections depending on the number of tracklets - auto trackletsGrouped = tracklets->sliceByCached(aod::track::collisionId, col.globalIndex(), cache); - int nTkl = trackletsGrouped.size(); - int spdClusters = bc.spdClustersL0() + bc.spdClustersL1(); - - selection |= (spdClusters < par->fSPDClsVsTklA + nTkl * par->fSPDClsVsTklB) ? BIT(kNoSPDClsVsTklBG) : 0; - selection |= !(nTkl < 6 && multV0C012 > par->fV0C012vsTklA + nTkl * par->fV0C012vsTklB) ? BIT(kNoV0C012vsTklBG) : 0; // o2-linter: disable=magic-number (nTkl dependent parameterization) - - // copy rct flags from bcsel table - uint32_t rct = bc.rct_raw(); - - // apply int7-like selections - bool sel7 = 1; - for (int i = 0; i < kNsel; i++) { - sel7 = sel7 && (applySelection[i] ? TESTBIT(selection, i) : 1); - } - - // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = bc.selection_bit(kIsBBT0A) && bc.selection_bit(kIsBBT0C); // TODO apply other cuts for sel8 - bool sel1 = bc.selection_bit(kIsINT1); - sel1 = sel1 && bc.selection_bit(kNoBGV0A); - sel1 = sel1 && bc.selection_bit(kNoBGV0C); - sel1 = sel1 && bc.selection_bit(kNoTPCLaserWarmUp); - sel1 = sel1 && bc.selection_bit(kNoTPCHVdip); - - // INT1 (SPDFO>0 | V0A | V0C) minimum bias trigger logic used in pp2010 and pp2011 - bool isINT1period = bc.runNumber() <= 136377 || (bc.runNumber() >= 144871 && bc.runNumber() <= 159582); // o2-linter: disable=magic-number (magic run numbers) - - // fill counters - 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); - } - } - - evsel(alias, selection, rct, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, 0, 0, 0); - } - PROCESS_SWITCH(EventSelectionTask, processRun2, "Process Run2 event selection", true); - - Partition pvTracks = ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)); - void processRun3(aod::Collisions const& cols, FullTracksIU const&, BCsWithBcSelsRun3 const& bcs, aod::FT0s const&) - { - int run = bcs.iteratorAt(0).runNumber(); - // extract bc pattern from CCDB for data or anchored MC only - int run3min = 500000; - if (run != lastRun && run >= run3min) { - lastRun = run; - auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); - // first bc of the first orbit - bcSOR = runInfo.orbitSOR * nBCsPerOrbit; - // duration of TF in bcs - nBCsPerTF = confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : confNumberOfOrbitsPerTF * nBCsPerOrbit; - // colliding bc pattern - int64_t ts = bcs.iteratorAt(0).timestamp(); - auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); - bcPatternB = grplhcif->getBunchFilling().getBCPattern(); - - // extract ITS ROF parameters - auto alppar = ccdb->getForTimeStamp>("ITS/Config/AlpideParam", ts); - rofOffset = alppar->roFrameBiasInBC; - rofLength = alppar->roFrameLengthInBC; - LOGP(debug, "ITS ROF Offset={} ITS ROF Length={}", rofOffset, rofLength); - } // if run != lastRun - - // create maps from globalBC to bc index for TVX-fired bcs - // to be used for closest TVX searches - std::map mapGlobalBcWithTVX; - std::map mapGlobalBcVtxZ; - for (const auto& bc : bcs) { - int64_t globalBC = bc.globalBC(); - // skip non-colliding bcs for data and anchored runs - if (run >= run3min && bcPatternB[globalBC % nBCsPerOrbit] == 0) { - continue; - } - if (bc.selection_bit(kIsTriggerTVX)) { - mapGlobalBcWithTVX[globalBC] = bc.globalIndex(); - mapGlobalBcVtxZ[globalBC] = bc.has_ft0() ? bc.ft0().posZ() : 0; - } - } - - // protection against empty FT0 maps - if (mapGlobalBcWithTVX.size() == 0) { - LOGP(error, "FT0 table is empty or corrupted. Filling evsel table with dummy values"); - for (const auto& col : cols) { - auto bc = col.bc_as(); - int32_t foundBC = bc.globalIndex(); - int32_t foundFT0 = bc.foundFT0Id(); - int32_t foundFV0 = bc.foundFV0Id(); - int32_t foundFDD = bc.foundFDDId(); - int32_t foundZDC = bc.foundZDCId(); - uint32_t rct = 0; - evsel(bc.alias_raw(), bc.selection_raw(), rct, kFALSE, kFALSE, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, -1, -1, -1); - } - return; - } - std::vector vTracksITS567perColl(cols.size(), 0); // counter of tracks per collision for occupancy studies - std::vector vAmpFT0CperColl(cols.size(), 0); // amplitude FT0C per collision - std::vector vCollVz(cols.size(), 0); // vector with vZ positions for each collision - std::vector vIsFullInfoForOccupancy(cols.size(), 0); // info for occupancy in +/- windows is available (i.e. a given coll is not too close to the TF borders) - const float timeWinOccupancyCalcMinNS = confTimeIntervalForOccupancyCalculationMin * 1e3; // ns - const float timeWinOccupancyCalcMaxNS = confTimeIntervalForOccupancyCalculationMax * 1e3; // ns - std::vector vIsVertexITSTPC(cols.size(), 0); // at least one of vertex contributors is ITS-TPC track - std::vector vIsVertexTOFmatched(cols.size(), 0); // at least one of vertex contributors is matched to TOF - std::vector vIsVertexTRDmatched(cols.size(), 0); // at least one of vertex contributors is matched to TRD - - std::vector vCollisionsPerBc(bcs.size(), 0); // counter of collisions per found bc for pileup checks - std::vector vFoundBCindex(cols.size(), -1); // indices of found bcs - std::vector vFoundGlobalBC(cols.size(), 0); // global BCs for collisions - - std::vector vIsVertexTOF(cols.size(), 0); - std::vector vIsVertexTRD(cols.size(), 0); - std::vector vIsVertexTPC(cols.size(), 0); - std::vector vIsVertexHighPtTPC(cols.size(), 0); - std::vector vNcontributors(cols.size(), 0); - std::vector vWeightedTimesTPCnoTOFnoTRD(cols.size(), 0); - std::vector vWeightedSigmaTPCnoTOFnoTRD(cols.size(), 0); - - // temporary vectors to find tracks with median time - std::vector vTrackTimesTOF; - std::vector vTrackTimesTRDnoTOF; - - // first loop to match collisions to TVX, also extract other per-collision information for further use - for (const auto& col : cols) { - int32_t colIndex = col.globalIndex(); - auto bc = col.bc_as(); - - vCollVz[colIndex] = col.posZ(); - - int64_t globalBC = bc.globalBC(); - int bcInTF = (bc.globalBC() - bcSOR) % nBCsPerTF; - vIsFullInfoForOccupancy[colIndex] = ((bcInTF - 300) * bcNS > -timeWinOccupancyCalcMinNS) && ((nBCsPerTF - 4000 - bcInTF) * bcNS > timeWinOccupancyCalcMaxNS) ? true : false; - - const auto& colPvTracks = pvTracks.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); - vTrackTimesTOF.clear(); - vTrackTimesTRDnoTOF.clear(); - int nPvTracksTPCnoTOFnoTRD = 0; - int nPvTracksHighPtTPCnoTOFnoTRD = 0; - float sumTime = 0, sumW = 0, sumHighPtTime = 0, sumHighPtW = 0; - for (const auto& track : colPvTracks) { - float trackTime = track.trackTime(); - if (track.itsNCls() >= 5) // o2-linter: disable=magic-number (indeed counting layers 5 6 7) - vTracksITS567perColl[colIndex]++; - if (track.hasTRD()) - vIsVertexTRDmatched[colIndex] = 1; - if (track.hasTPC()) - vIsVertexITSTPC[colIndex] = 1; - if (track.hasTOF()) { - vTrackTimesTOF.push_back(trackTime); - vIsVertexTOFmatched[colIndex] = 1; - } else if (track.hasTRD()) { - vTrackTimesTRDnoTOF.push_back(trackTime); - } else if (track.hasTPC()) { - float trackTimeRes = track.trackTimeRes(); - float trackPt = track.pt(); - float w = 1. / (trackTimeRes * trackTimeRes); - sumTime += trackTime * w; - sumW += w; - nPvTracksTPCnoTOFnoTRD++; - if (trackPt > 1) { - sumHighPtTime += trackTime * w; - sumHighPtW += w; - nPvTracksHighPtTPCnoTOFnoTRD++; - } - } - } - vWeightedTimesTPCnoTOFnoTRD[colIndex] = sumW > 0 ? sumTime / sumW : 0; - vWeightedSigmaTPCnoTOFnoTRD[colIndex] = sumW > 0 ? std::sqrt(1. / sumW) : 0; - vNcontributors[colIndex] = colPvTracks.size(); - int nPvTracksTOF = vTrackTimesTOF.size(); - int nPvTracksTRDnoTOF = vTrackTimesTRDnoTOF.size(); - // collision type - vIsVertexTOF[colIndex] = nPvTracksTOF > 0; - vIsVertexTRD[colIndex] = nPvTracksTRDnoTOF > 0; - vIsVertexTPC[colIndex] = nPvTracksTPCnoTOFnoTRD > 0; - vIsVertexHighPtTPC[colIndex] = nPvTracksHighPtTPCnoTOFnoTRD > 0; - - int64_t foundGlobalBC = 0; - int32_t foundBCindex = -1; - - if (nPvTracksTOF > 0) { - // for collisions with TOF tracks: - // take bc corresponding to TOF track with median time - int64_t tofGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTOF) / bcNS); - std::map::iterator it = mapGlobalBcWithTVX.find(tofGlobalBC); - if (it != mapGlobalBcWithTVX.end()) { - foundGlobalBC = it->first; - foundBCindex = it->second; - } - } else if (nPvTracksTPCnoTOFnoTRD == 0 && nPvTracksTRDnoTOF > 0) { - // for collisions with TRD tracks but without TOF or ITSTPC-only tracks: - // take bc corresponding to TRD track with median time - int64_t trdGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTRDnoTOF) / bcNS); - std::map::iterator it = mapGlobalBcWithTVX.find(trdGlobalBC); - if (it != mapGlobalBcWithTVX.end()) { - foundGlobalBC = it->first; - foundBCindex = it->second; - } - } else if (nPvTracksHighPtTPCnoTOFnoTRD > 0) { - // for collisions with high-pt ITSTPC-nonTOF-nonTRD tracks - // search in 3*confSigmaBCforHighPtTracks range (3*4 bcs by default) - int64_t meanBC = globalBC + TMath::Nint(sumHighPtTime / sumHighPtW / bcNS); - int64_t bestGlobalBC = findBestGlobalBC(meanBC, confSigmaBCforHighPtTracks, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ); - if (bestGlobalBC > 0) { - foundGlobalBC = bestGlobalBC; - foundBCindex = mapGlobalBcWithTVX[bestGlobalBC]; - } - } - - // fill foundBC indices and global BCs - // keep current bc if TVX matching failed at this step - vFoundBCindex[colIndex] = foundBCindex >= 0 ? foundBCindex : bc.globalIndex(); - vFoundGlobalBC[colIndex] = foundGlobalBC > 0 ? foundGlobalBC : globalBC; - - // erase found global BC with TVX from the pool of bcs for the next loop over low-pt TPCnoTOFnoTRD collisions - if (foundBCindex >= 0) - mapGlobalBcVtxZ.erase(foundGlobalBC); - } - - // second loop to match remaining low-pt TPCnoTOFnoTRD collisions - for (const auto& col : cols) { - int32_t colIndex = col.globalIndex(); - if (vIsVertexTPC[colIndex] > 0 && vIsVertexTOF[colIndex] == 0 && vIsVertexHighPtTPC[colIndex] == 0) { - float weightedTime = vWeightedTimesTPCnoTOFnoTRD[colIndex]; - float weightedSigma = vWeightedSigmaTPCnoTOFnoTRD[colIndex]; - auto bc = col.bc_as(); - int64_t globalBC = bc.globalBC(); - int64_t meanBC = globalBC + TMath::Nint(weightedTime / bcNS); - int64_t sigmaBC = TMath::CeilNint(weightedSigma / bcNS); - int64_t bestGlobalBC = findBestGlobalBC(meanBC, sigmaBC, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ); - vFoundGlobalBC[colIndex] = bestGlobalBC > 0 ? bestGlobalBC : globalBC; - vFoundBCindex[colIndex] = bestGlobalBC > 0 ? mapGlobalBcWithTVX[bestGlobalBC] : bc.globalIndex(); - } - // fill pileup counter - vCollisionsPerBc[vFoundBCindex[colIndex]]++; - } - - // save indices of collisions for occupancy calculation (both in ROF and in time range) - std::vector> vCollsInSameITSROF; - std::vector> vCollsInPrevITSROF; - std::vector> vCollsInTimeWin; - std::vector> vTimeDeltaForColls; // delta time wrt a given collision - for (const auto& col : cols) { - int32_t colIndex = col.globalIndex(); - int64_t foundGlobalBC = vFoundGlobalBC[colIndex]; - auto bc = bcs.iteratorAt(vFoundBCindex[colIndex]); - if (bc.has_foundFT0()) - vAmpFT0CperColl[colIndex] = bc.foundFT0().sumAmpC(); - - int64_t tfId = (foundGlobalBC - bcSOR) / nBCsPerTF; - int64_t rofId = (foundGlobalBC + nBCsPerOrbit - rofOffset) / rofLength; - - // ### for in-ROF occupancy - std::vector vAssocCollInSameROF; - // find all collisions in the same ROF before a given collision - int32_t minColIndex = colIndex - 1; - while (minColIndex >= 0) { - int64_t thisBC = vFoundGlobalBC[minColIndex]; - // check if this is still the same TF - int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; - if (thisTFid != tfId) - break; - // int thisRofIdInTF = (thisBC - rofOffset) / rofLength; - int64_t thisRofId = (thisBC + nBCsPerOrbit - rofOffset) / rofLength; - - // check if we are within the same ROF - if (thisRofId != rofId) - break; - vAssocCollInSameROF.push_back(minColIndex); - minColIndex--; - } - // find all collisions in the same ROF after the current one - int32_t maxColIndex = colIndex + 1; - while (maxColIndex < cols.size()) { - int64_t thisBC = vFoundGlobalBC[maxColIndex]; - int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; - if (thisTFid != tfId) - break; - int64_t thisRofId = (thisBC + nBCsPerOrbit - rofOffset) / rofLength; - if (thisRofId != rofId) - break; - vAssocCollInSameROF.push_back(maxColIndex); - maxColIndex++; - } - vCollsInSameITSROF.push_back(vAssocCollInSameROF); - - // ### bookkeep collisions in previous ROF - std::vector vAssocCollInPrevROF; - minColIndex = colIndex - 1; - while (minColIndex >= 0) { - int64_t thisBC = vFoundGlobalBC[minColIndex]; - // check if this is still the same TF - int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; - if (thisTFid != tfId) - break; - int64_t thisRofId = (thisBC + nBCsPerOrbit - rofOffset) / rofLength; - if (thisRofId == rofId - 1) - vAssocCollInPrevROF.push_back(minColIndex); - else if (thisRofId < rofId - 1) - break; - minColIndex--; - } - vCollsInPrevITSROF.push_back(vAssocCollInPrevROF); - - // ### for occupancy in time windows - std::vector vAssocToThisCol; - std::vector vCollsTimeDeltaWrtGivenColl; - // protection against the TF borders - if (!vIsFullInfoForOccupancy[colIndex]) { - vCollsInTimeWin.push_back(vAssocToThisCol); - vTimeDeltaForColls.push_back(vCollsTimeDeltaWrtGivenColl); - continue; - } - // find all collisions in time window before the current one - minColIndex = colIndex - 1; - while (minColIndex >= 0) { - int64_t thisBC = vFoundGlobalBC[minColIndex]; - // check if this is still the same TF - int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; - if (thisTFid != tfId) - break; - float dt = (thisBC - foundGlobalBC) * bcNS; // ns - // check if we are within the chosen time range - if (dt < timeWinOccupancyCalcMinNS) - break; - vAssocToThisCol.push_back(minColIndex); - vCollsTimeDeltaWrtGivenColl.push_back(dt); - minColIndex--; - } - // find all collisions in time window after the current one - maxColIndex = colIndex + 1; - while (maxColIndex < cols.size()) { - int64_t thisBC = vFoundGlobalBC[maxColIndex]; - int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; - if (thisTFid != tfId) - break; - float dt = (thisBC - foundGlobalBC) * bcNS; // ns - if (dt > timeWinOccupancyCalcMaxNS) - break; - vAssocToThisCol.push_back(maxColIndex); - vCollsTimeDeltaWrtGivenColl.push_back(dt); - maxColIndex++; - } - vCollsInTimeWin.push_back(vAssocToThisCol); - vTimeDeltaForColls.push_back(vCollsTimeDeltaWrtGivenColl); - } - - // perform the occupancy calculation per ITS ROF and also in the pre-defined time window - std::vector vNumTracksITS567inFullTimeWin(cols.size(), 0); // counter of tracks in full time window for occupancy studies (excluding given event) - std::vector vSumAmpFT0CinFullTimeWin(cols.size(), 0); // sum of FT0C of tracks in full time window for occupancy studies (excluding given event) - - std::vector vNoCollInTimeRangeStrict(cols.size(), 0); // no collisions in a specified time range - std::vector vNoCollInTimeRangeNarrow(cols.size(), 0); // no collisions in a specified time range (narrow) - std::vector vNoHighMultCollInTimeRange(cols.size(), 0); // no high-mult collisions in a specified time range - - std::vector vNoCollInSameRofStrict(cols.size(), 0); // to veto events with other collisions in the same ITS ROF - std::vector vNoCollInSameRofStandard(cols.size(), 0); // to veto events with other collisions in the same ITS ROF, with per-collision multiplicity above threshold - std::vector vNoCollInSameRofWithCloseVz(cols.size(), 0); // to veto events with nearby collisions with close vZ - std::vector vNoHighMultCollInPrevRof(cols.size(), 0); // veto events if FT0C amplitude in previous ITS ROF is above threshold - - for (const auto& col : cols) { - int32_t colIndex = col.globalIndex(); - float vZ = col.posZ(); - - // ### in-ROF occupancy - std::vector vAssocCollInSameROF = vCollsInSameITSROF[colIndex]; - int nITS567tracksForSameRofVetoStrict = 0; // to veto events with other collisions in the same ITS ROF - int nCollsInRofWithFT0CAboveVetoStandard = 0; // to veto events with other collisions in the same ITS ROF, with per-collision multiplicity above threshold - int nITS567tracksForRofVetoOnCloseVz = 0; // to veto events with nearby collisions with close vZ - for (uint32_t iCol = 0; iCol < vAssocCollInSameROF.size(); iCol++) { - int thisColIndex = vAssocCollInSameROF[iCol]; - nITS567tracksForSameRofVetoStrict += vTracksITS567perColl[thisColIndex]; - if (vAmpFT0CperColl[thisColIndex] > confFT0CamplCutVetoOnCollInROF) - nCollsInRofWithFT0CAboveVetoStandard++; - if (std::fabs(vCollVz[thisColIndex] - vZ) < confEpsilonVzDiffVetoInROF) - nITS567tracksForRofVetoOnCloseVz += vTracksITS567perColl[thisColIndex]; - } - // in-ROF occupancy flags - vNoCollInSameRofStrict[colIndex] = (nITS567tracksForSameRofVetoStrict == 0); - vNoCollInSameRofStandard[colIndex] = (nCollsInRofWithFT0CAboveVetoStandard == 0); - vNoCollInSameRofWithCloseVz[colIndex] = (nITS567tracksForRofVetoOnCloseVz == 0); - - // ### occupancy in previous ROF - std::vector vAssocCollInPrevROF = vCollsInPrevITSROF[colIndex]; - float totalFT0amplInPrevROF = 0; - for (uint32_t iCol = 0; iCol < vAssocCollInPrevROF.size(); iCol++) { - int thisColIndex = vAssocCollInPrevROF[iCol]; - totalFT0amplInPrevROF += vAmpFT0CperColl[thisColIndex]; - } - // veto events if FT0C amplitude in previous ITS ROF is above threshold - vNoHighMultCollInPrevRof[colIndex] = (totalFT0amplInPrevROF < confFT0CamplCutVetoOnCollInROF); - - // ### occupancy in time windows - // protection against TF borders - if (!vIsFullInfoForOccupancy[colIndex]) { // occupancy in undefined (too close to TF borders) - vNumTracksITS567inFullTimeWin[colIndex] = -1; - vSumAmpFT0CinFullTimeWin[colIndex] = -1; - continue; - } - std::vector vAssocToThisCol = vCollsInTimeWin[colIndex]; - std::vector vCollsTimeDeltaWrtGivenColl = vTimeDeltaForColls[colIndex]; - int nITS567tracksInFullTimeWindow = 0; - float sumAmpFT0CInFullTimeWindow = 0; - int nITS567tracksForVetoNarrow = 0; // to veto events with nearby collisions (narrower range) - int nITS567tracksForVetoStrict = 0; // to veto events with nearby collisions - int nCollsWithFT0CAboveVetoStandard = 0; // to veto events with per-collision multiplicity above threshold - for (uint32_t iCol = 0; iCol < vAssocToThisCol.size(); iCol++) { - int thisColIndex = vAssocToThisCol[iCol]; - float dt = vCollsTimeDeltaWrtGivenColl[iCol] / 1e3; // ns -> us - float wOccup = 1.; - if (confUseWeightsForOccupancyVariable) { - // weighted occupancy - wOccup = 0; - if (dt >= -40 && dt < -5) // collisions in the past // o2-linter: disable=magic-number (to be checked by Igor) - wOccup = 1. / 1225 * (dt + 40) * (dt + 40); // o2-linter: disable=magic-number (to be checked by Igor) - else if (dt >= -5 && dt < 15) // collisions near a given one // o2-linter: disable=magic-number (to be checked by Igor) - wOccup = 1; - // else if (dt >= 15 && dt < 100) // collisions from the future - // wOccup = -1. / 85 * dt + 20. / 17; - else if (dt >= 15 && dt < 40) // collisions from the future // o2-linter: disable=magic-number (to be checked by Igor) - wOccup = -0.4 / 25 * dt + 1.24; // o2-linter: disable=magic-number (to be checked by Igor) - else if (dt >= 40 && dt < 100) // collisions from the distant future // o2-linter: disable=magic-number (to be checked by Igor) - wOccup = -0.4 / 60 * dt + 0.6 + 0.8 / 3; // o2-linter: disable=magic-number (to be checked by Igor) - } - nITS567tracksInFullTimeWindow += wOccup * vTracksITS567perColl[thisColIndex]; - sumAmpFT0CInFullTimeWindow += wOccup * vAmpFT0CperColl[thisColIndex]; - - // counting tracks from other collisions in fixed time windows - if (std::fabs(dt) < confTimeRangeVetoOnCollNarrow) - nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex]; - if (std::fabs(dt) < confTimeRangeVetoOnCollStandard) - nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex]; - - // standard cut on other collisions vs delta-times - const float driftV = 2.5; // drift velocity in cm/us, TPC drift_length / drift_time = 250 cm / 100 us - if (std::fabs(dt) < 2.0) { // us, complete veto on other collisions // o2-linter: disable=magic-number (to be checked by Igor) - nCollsWithFT0CAboveVetoStandard++; - } else if (dt > -4.0 && dt <= -2.0) { // us, strict veto to suppress fake ITS-TPC matches more // o2-linter: disable=magic-number (to be checked by Igor) - if (vAmpFT0CperColl[thisColIndex] > confFT0CamplCutVetoOnCollInTimeRange / 5) - nCollsWithFT0CAboveVetoStandard++; - } else if (std::fabs(dt) < 8 + std::fabs(vZ) / driftV) { // loose veto, 8 us corresponds to maximum possible |vZ|, which is ~20 cm // o2-linter: disable=magic-number (to be checked by Igor) - // counting number of other collisions with multiplicity above threshold - if (vAmpFT0CperColl[thisColIndex] > confFT0CamplCutVetoOnCollInTimeRange) - nCollsWithFT0CAboveVetoStandard++; - } - } - vNumTracksITS567inFullTimeWin[colIndex] = nITS567tracksInFullTimeWindow; // occupancy by a sum of number of ITS tracks (without a current collision) - vSumAmpFT0CinFullTimeWin[colIndex] = sumAmpFT0CInFullTimeWindow; // occupancy by a sum of FT0C amplitudes (without a current collision) - // occupancy flags based on nearby collisions - vNoCollInTimeRangeNarrow[colIndex] = (nITS567tracksForVetoNarrow == 0); - vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0); - vNoHighMultCollInTimeRange[colIndex] = (nCollsWithFT0CAboveVetoStandard == 0); - } - - for (const auto& col : cols) { - int32_t colIndex = col.globalIndex(); - int32_t foundBC = vFoundBCindex[colIndex]; - auto bc = bcs.iteratorAt(foundBC); - int32_t foundFT0 = bc.foundFT0Id(); - int32_t foundFV0 = bc.foundFV0Id(); - int32_t foundFDD = bc.foundFDDId(); - int32_t foundZDC = bc.foundZDCId(); - - // compare zVtx from FT0 and from PV - bool isGoodZvtxFT0vsPV = bc.has_foundFT0() ? std::fabs(bc.foundFT0().posZ() - col.posZ()) < maxDiffZvtxFT0vsPV : 0; - - // copy alias decisions from bcsel table - uint32_t alias = bc.alias_raw(); - - // copy selection decisions from bcsel table - uint64_t selection = bc.selection_raw(); - selection |= vCollisionsPerBc[foundBC] <= 1 ? BIT(kNoSameBunchPileup) : 0; - selection |= vIsVertexITSTPC[colIndex] ? BIT(kIsVertexITSTPC) : 0; - selection |= vIsVertexTOFmatched[colIndex] ? BIT(kIsVertexTOFmatched) : 0; - selection |= vIsVertexTRDmatched[colIndex] ? BIT(kIsVertexTRDmatched) : 0; - selection |= isGoodZvtxFT0vsPV ? BIT(kIsGoodZvtxFT0vsPV) : 0; - - // selection bits based on occupancy time pattern - selection |= vNoCollInTimeRangeNarrow[colIndex] ? BIT(kNoCollInTimeRangeNarrow) : 0; - selection |= vNoCollInTimeRangeStrict[colIndex] ? BIT(kNoCollInTimeRangeStrict) : 0; - selection |= vNoHighMultCollInTimeRange[colIndex] ? BIT(kNoCollInTimeRangeStandard) : 0; - - // selection bits based on ITS in-ROF occupancy - selection |= vNoCollInSameRofStrict[colIndex] ? BIT(kNoCollInRofStrict) : 0; - selection |= (vNoCollInSameRofStandard[colIndex] && vNoCollInSameRofWithCloseVz[colIndex]) ? BIT(kNoCollInRofStandard) : 0; - selection |= vNoHighMultCollInPrevRof[colIndex] ? BIT(kNoHighMultCollInPrevRof) : 0; - - // copy rct flags from bcsel table - uint32_t rct = bc.rct_raw(); - - // apply int7-like selections - bool sel7 = 0; - - // TODO apply other cuts for sel8 - // TODO introduce sel1 etc? - // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = bc.selection_bit(kIsTriggerTVX) && bc.selection_bit(kNoTimeFrameBorder) && bc.selection_bit(kNoITSROFrameBorder); - - // fill counters - histos.get(HIST("hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); - if (bc.selection_bit(kIsTriggerTVX)) { - histos.get(HIST("hColCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); - } - if (sel8) { - histos.get(HIST("hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); - } - - evsel(alias, selection, rct, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, - vNumTracksITS567inFullTimeWin[colIndex], vSumAmpFT0CinFullTimeWin[colIndex], 0); - } - } - - PROCESS_SWITCH(EventSelectionTask, processRun3, "Process Run3 event selection", false); -}; - -struct LumiTask { - Service ccdb; - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - int lastRun = -1; // last run number (needed to access ccdb only if run!=lastRun) - float csTVX = -1; // dummy -1 for the visible TVX cross section (in ub) used in lumi accounting - float csTCE = -1; // dummy -1 for the visible TCE cross section (in ub) used in lumi accounting - float csZEM = -1; // dummy -1 for the visible ZEM cross section (in ub) used in lumi accounting - float csZNC = -1; // dummy -1 for the visible ZNC cross section (in ub) used in lumi accounting - - std::vector mOrbits; - std::vector mPileupCorrectionTVX; - std::vector mPileupCorrectionTCE; - std::vector mPileupCorrectionZEM; - std::vector mPileupCorrectionZNC; - - int64_t minOrbitInRange = std::numeric_limits::max(); - int64_t maxOrbitInRange = 0; - uint32_t currentOrbitIndex = 0; - std::bitset bcPatternB; // bc pattern of colliding bunches - std::vector mRCTFlagsCheckers; - - void init(InitContext&) - { - histos.add("hCounterTVX", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterTCE", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZEM", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZNC", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterTVXZDC", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterTVXafterBCcuts", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterTCEafterBCcuts", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZEMafterBCcuts", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZNCafterBCcuts", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterTVXZDCafterBCcuts", "", 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.}}); - histos.add("hLumiZNC", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); - histos.add("hLumiTVXafterBCcuts", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); - histos.add("hLumiTCEafterBCcuts", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); - histos.add("hLumiZEMafterBCcuts", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); - histos.add("hLumiZNCafterBCcuts", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); - - const int nLists = 6; - TString rctListNames[] = {"CBT", "CBT_hadronPID", "CBT_electronPID", "CBT_calo", "CBT_muon", "CBT_muon_glo"}; - histos.add("hLumiTVXafterBCcutsRCT", ";;Luminosity, 1/#mub", kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); - histos.add("hLumiTCEafterBCcutsRCT", ";;Luminosity, 1/#mub", kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); - histos.add("hLumiZEMafterBCcutsRCT", ";;Luminosity, 1/#mub", kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); - histos.add("hLumiZNCafterBCcutsRCT", ";;Luminosity, 1/#mub", kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); - - for (int i = 0; i < nLists; i++) { - const auto& rctListName = rctListNames[i]; - mRCTFlagsCheckers.emplace_back(rctListName.Data(), false, false); // disable zdc check, disable lim. acc. check - mRCTFlagsCheckers.emplace_back(rctListName.Data(), false, true); // disable zdc check, enable lim. acc. check - mRCTFlagsCheckers.emplace_back(rctListName.Data(), true, false); // enable zdc check, disable lim. acc. check - mRCTFlagsCheckers.emplace_back(rctListName.Data(), true, true); // enable zdc check, enable lim. acc. check - histos.get(HIST("hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); - histos.get(HIST("hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); - histos.get(HIST("hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); - histos.get(HIST("hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); - histos.get(HIST("hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); - histos.get(HIST("hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); - histos.get(HIST("hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); - histos.get(HIST("hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); - histos.get(HIST("hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); - histos.get(HIST("hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); - histos.get(HIST("hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); - histos.get(HIST("hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); - histos.get(HIST("hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); - histos.get(HIST("hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); - histos.get(HIST("hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); - histos.get(HIST("hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); - } - } - - void processRun2(aod::BCs const&) - { - LOGP(debug, "Dummy process function for Run 2"); - } - - PROCESS_SWITCH(LumiTask, processRun2, "Process Run2 lumi task", true); - - void processRun3(BCsWithBcSelsRun3 const& bcs, aod::FT0s const&) - { - if (bcs.size() == 0) - return; - int run = bcs.iteratorAt(0).runNumber(); - if (run < 500000) // o2-linter: disable=magic-number (skip for unanchored MCs) - return; - if (run != lastRun && run >= 520259) { // o2-linter: disable=magic-number (scalers available for runs above 520120) - lastRun = run; - int64_t ts = bcs.iteratorAt(0).timestamp(); - - // getting GRP LHCIF object to extract colliding system, energy and colliding bc pattern - auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); - int beamZ1 = grplhcif->getBeamZ(constants::lhc::BeamA); - int beamZ2 = grplhcif->getBeamZ(constants::lhc::BeamC); - float sqrts = grplhcif->getSqrtS(); - int nCollidingBCs = grplhcif->getBunchFilling().getNBunches(); - bcPatternB = grplhcif->getBunchFilling().getBCPattern(); - - // visible cross sections in ub. Using dummy -1 if lumi estimator is not reliable for this colliding system - csTVX = -1; - csTCE = -1; - csZEM = -1; - csZNC = -1; - // Temporary workaround to get visible cross section. TODO: store run-by-run visible cross sections in CCDB - if (beamZ1 == 1 && beamZ2 == 1) { - if (std::fabs(sqrts - 900.) < 100.) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csTVX = 0.0357e6; // ub - } else if (std::fabs(sqrts - 5360.) < 100.) { // pp-ref // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csTVX = 0.0503e6; // ub - } else if (std::fabs(sqrts - 13600.) < 300.) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csTVX = 0.0594e6; // ub - } else { - LOGP(warn, "Cross section for pp @ {} GeV is not defined", sqrts); - } - } else if (beamZ1 == 82 && beamZ2 == 82) { // o2-linter: disable=magic-number (PbPb colliding system) - // see AN: https://alice-notes.web.cern.ch/node/1515 - if (std::fabs(sqrts - 5360) < 20) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csZNC = 214.5e6; // ub - csZEM = 415.2e6; // ub - csTCE = 10.36e6; // ub - if (run > 543437 && run < 543514) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csTCE = 8.3e6; // ub - } else if (run >= 543514 && run < 545367) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csTCE = 4.10e6; // ub - } else if (run >= 559544) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) - csTCE = 3.86e6; // ub - } - } else { - LOGP(warn, "Cross section for PbPb @ {} GeV is not defined", sqrts); - } - } else { - LOGP(warn, "Cross section for z={} + z={} @ {} GeV is not defined", beamZ1, beamZ2, sqrts); - } - // getting CTP config to extract lumi class indices (used for rate fetching and pileup correction) - std::map metadata; - metadata["runNumber"] = std::to_string(run); - auto config = ccdb->getSpecific("CTP/Config/Config", ts, metadata); - auto classes = config->getCTPClasses(); - TString lumiClassNameZNC = "C1ZNC-B-NOPF-CRU"; - TString lumiClassNameTCE = "CMTVXTCE-B-NOPF-CRU"; - TString lumiClassNameTVX1 = "MINBIAS_TVX"; // run >= 534467 - TString lumiClassNameTVX2 = "MINBIAS_TVX_NOMASK"; // run >= 534468 - TString lumiClassNameTVX3 = "CMTVX-NONE-NOPF-CRU"; // run >= 534996 - TString lumiClassNameTVX4 = "CMTVX-B-NOPF-CRU"; // run >= 543437 - - // find class indices - int classIdZNC = -1; - int classIdTCE = -1; - int classIdTVX = -1; - for (unsigned int i = 0; i < classes.size(); i++) { - TString clname = classes[i].name; - clname.ToUpper(); - // using position (i) in the vector of classes instead of classes[i].getIndex() - // due to bug or inconsistencies in scaler record and class indices - if (clname == lumiClassNameZNC) - classIdZNC = i; - if (clname == lumiClassNameTCE) - classIdTCE = i; - if (clname == lumiClassNameTVX4 || clname == lumiClassNameTVX3 || clname == lumiClassNameTVX2 || clname == lumiClassNameTVX1) - classIdTVX = i; - } - - // extract trigger counts from CTP scalers - auto scalers = ccdb->getSpecific("CTP/Calib/Scalers", ts, metadata); - scalers->convertRawToO2(); - std::vector mCounterTVX; - std::vector mCounterTCE; - std::vector mCounterZNC; - std::vector mCounterZEM; - mOrbits.clear(); - for (const auto& record : scalers->getScalerRecordO2()) { - mOrbits.push_back(record.intRecord.orbit); - mCounterTVX.push_back(classIdTVX >= 0 ? record.scalers[classIdTVX].lmBefore : 0); - mCounterTCE.push_back(classIdTCE >= 0 ? record.scalers[classIdTCE].lmBefore : 0); - if (run >= 543437 && run < 544448 && record.scalersInps.size() >= 26) { // o2-linter: disable=magic-number (ZNC class not defined for this run range) - mCounterZNC.push_back(record.scalersInps[25]); // see ZNC=1ZNC input index in https://indico.cern.ch/event/1153630/contributions/4844362/ - } else { - mCounterZNC.push_back(classIdZNC >= 0 ? record.scalers[classIdZNC].l1Before : 0); - } - // ZEM class not defined, using inputs instead - uint32_t indexZEM = 24; // see ZEM=1ZED input index in https://indico.cern.ch/event/1153630/contributions/4844362/ - mCounterZEM.push_back(record.scalersInps.size() >= indexZEM + 1 ? record.scalersInps[indexZEM] : 0); - } - - // calculate pileup corrections - mPileupCorrectionTVX.clear(); - mPileupCorrectionTCE.clear(); - mPileupCorrectionZEM.clear(); - mPileupCorrectionZNC.clear(); - for (uint32_t i = 0; i < mOrbits.size() - 1; i++) { - int64_t nOrbits = mOrbits[i + 1] - mOrbits[i]; - if (nOrbits <= 0 || nCollidingBCs == 0) - continue; - double perBcRateTVX = static_cast(mCounterTVX[i + 1] - mCounterTVX[i]) / nOrbits / nCollidingBCs; - double perBcRateTCE = static_cast(mCounterTCE[i + 1] - mCounterTCE[i]) / nOrbits / nCollidingBCs; - double perBcRateZNC = static_cast(mCounterZNC[i + 1] - mCounterZNC[i]) / nOrbits / nCollidingBCs; - double perBcRateZEM = static_cast(mCounterZEM[i + 1] - mCounterZEM[i]) / nOrbits / nCollidingBCs; - double muTVX = (perBcRateTVX < 1 && perBcRateTVX > 1e-10) ? -std::log(1 - perBcRateTVX) : 0; - double muTCE = (perBcRateTCE < 1 && perBcRateTCE > 1e-10) ? -std::log(1 - perBcRateTCE) : 0; - double muZNC = (perBcRateZNC < 1 && perBcRateZNC > 1e-10) ? -std::log(1 - perBcRateZNC) : 0; - double muZEM = (perBcRateZEM < 1 && perBcRateZEM > 1e-10) ? -std::log(1 - perBcRateZEM) : 0; - LOGP(debug, "orbit={} muTVX={} muTCE={} muZNC={} muZEM={}", mOrbits[i], muTVX, muTCE, muZNC, muZEM); - mPileupCorrectionTVX.push_back(muTVX > 1e-10 ? muTVX / (1 - std::exp(-muTVX)) : 1); - mPileupCorrectionTCE.push_back(muTCE > 1e-10 ? muTCE / (1 - std::exp(-muTCE)) : 1); - mPileupCorrectionZNC.push_back(muZNC > 1e-10 ? muZNC / (1 - std::exp(-muZNC)) : 1); - mPileupCorrectionZEM.push_back(muZEM > 1e-10 ? muZEM / (1 - std::exp(-muZEM)) : 1); - } - // filling last orbit range using previous orbit range - mPileupCorrectionTVX.push_back(mPileupCorrectionTVX.back()); - mPileupCorrectionTCE.push_back(mPileupCorrectionTCE.back()); - mPileupCorrectionZNC.push_back(mPileupCorrectionZNC.back()); - mPileupCorrectionZEM.push_back(mPileupCorrectionZEM.back()); - } // access ccdb once per run - - const char* srun = Form("%d", run); - - for (const auto& bc : bcs) { - auto& selection = bc.selection_raw(); - if (bcPatternB[bc.globalBC() % nBCsPerOrbit] == 0) // skip non-colliding bcs - continue; - - bool noBorder = TESTBIT(selection, kNoTimeFrameBorder) && TESTBIT(selection, kNoITSROFrameBorder); - bool isTriggerTVX = TESTBIT(selection, kIsTriggerTVX); - bool isTriggerTCE = bc.has_ft0() ? (TESTBIT(selection, kIsTriggerTVX) && TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitCen)) : 0; - bool isTriggerZNA = TESTBIT(selection, kIsBBZNA); - bool isTriggerZNC = TESTBIT(selection, kIsBBZNC); - bool isTriggerZEM = isTriggerZNA || isTriggerZNC; - - // determine pileup correction - int64_t orbit = bc.globalBC() / nBCsPerOrbit; - if ((orbit < minOrbitInRange || orbit > maxOrbitInRange) && mOrbits.size() > 1) { - auto it = std::lower_bound(mOrbits.begin(), mOrbits.end(), orbit); - uint32_t nextOrbitIndex = std::distance(mOrbits.begin(), it); - if (nextOrbitIndex == 0) // if orbit is below stored scaler orbits - nextOrbitIndex = 1; - else if (nextOrbitIndex == mOrbits.size()) // if orbit is above stored scaler orbits - nextOrbitIndex = mOrbits.size() - 1; - currentOrbitIndex = nextOrbitIndex - 1; - minOrbitInRange = mOrbits[currentOrbitIndex]; - maxOrbitInRange = mOrbits[nextOrbitIndex]; - } - double pileupCorrectionTVX = currentOrbitIndex < mPileupCorrectionTVX.size() ? mPileupCorrectionTVX[currentOrbitIndex] : 1.; - double pileupCorrectionTCE = currentOrbitIndex < mPileupCorrectionTCE.size() ? mPileupCorrectionTCE[currentOrbitIndex] : 1.; - double pileupCorrectionZNC = currentOrbitIndex < mPileupCorrectionZNC.size() ? mPileupCorrectionZNC[currentOrbitIndex] : 1.; - double pileupCorrectionZEM = currentOrbitIndex < mPileupCorrectionZEM.size() ? mPileupCorrectionZEM[currentOrbitIndex] : 1.; - - double lumiTVX = 1. / csTVX * pileupCorrectionTVX; - double lumiTCE = 1. / csTCE * pileupCorrectionTCE; - double lumiZNC = 1. / csZNC * pileupCorrectionZNC; - double lumiZEM = 1. / csZEM * pileupCorrectionZEM; - - if (isTriggerTVX) { - histos.get(HIST("hCounterTVX"))->Fill(srun, 1); - histos.get(HIST("hLumiTVX"))->Fill(srun, lumiTVX); - if (isTriggerZNA && isTriggerZNC) { - histos.get(HIST("hCounterTVXZDC"))->Fill(srun, 1); - } - if (noBorder) { - histos.get(HIST("hCounterTVXafterBCcuts"))->Fill(srun, 1); - histos.get(HIST("hLumiTVXafterBCcuts"))->Fill(srun, lumiTVX); - if (isTriggerZNA && isTriggerZNC) { - histos.get(HIST("hCounterTVXZDCafterBCcuts"))->Fill(srun, 1); - } - for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { - if (mRCTFlagsCheckers[i](bc)) - histos.get(HIST("hLumiTVXafterBCcutsRCT"))->Fill(srun, i, lumiTVX); - } - } - } - - if (isTriggerTCE) { - histos.get(HIST("hCounterTCE"))->Fill(srun, 1); - histos.get(HIST("hLumiTCE"))->Fill(srun, lumiTCE); - if (noBorder) { - histos.get(HIST("hCounterTCEafterBCcuts"))->Fill(srun, 1); - histos.get(HIST("hLumiTCEafterBCcuts"))->Fill(srun, lumiTCE); - for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { - if (mRCTFlagsCheckers[i](bc)) - histos.get(HIST("hLumiTCEafterBCcutsRCT"))->Fill(srun, i, lumiTCE); - } - } - } - - if (isTriggerZEM) { - histos.get(HIST("hCounterZEM"))->Fill(srun, 1); - histos.get(HIST("hLumiZEM"))->Fill(srun, lumiZEM); - if (noBorder) { - histos.get(HIST("hCounterZEMafterBCcuts"))->Fill(srun, 1); - histos.get(HIST("hLumiZEMafterBCcuts"))->Fill(srun, lumiZEM); - for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { - if (mRCTFlagsCheckers[i](bc)) - histos.get(HIST("hLumiZEMafterBCcutsRCT"))->Fill(srun, i, lumiZEM); - } - } - } - - if (isTriggerZNC) { - histos.get(HIST("hCounterZNC"))->Fill(srun, 1); - histos.get(HIST("hLumiZNC"))->Fill(srun, lumiZNC); - if (noBorder) { - histos.get(HIST("hCounterZNCafterBCcuts"))->Fill(srun, 1); - histos.get(HIST("hLumiZNCafterBCcuts"))->Fill(srun, lumiZNC); - for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { - if (mRCTFlagsCheckers[i](bc)) - histos.get(HIST("hLumiZNCafterBCcutsRCT"))->Fill(srun, i, lumiZNC); - } - } - } - - } // bcs - } // process - PROCESS_SWITCH(LumiTask, processRun3, "Process Run3 lumi task", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - // Parse the metadata - metadataInfo.initMetadata(cfgc); - - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; -} diff --git a/Common/TableProducer/fwdtrackextension.cxx b/Common/TableProducer/fwdtrackextension.cxx index c554b2c4fbf..5ffdf73bf7a 100644 --- a/Common/TableProducer/fwdtrackextension.cxx +++ b/Common/TableProducer/fwdtrackextension.cxx @@ -10,21 +10,30 @@ // or submit itself to any jurisdiction. // -// Task performing forward track DCA computation +// \file fwdtrackextension.cxx +// \brief Task performing forward track DCA computation. +// \author Maurice Coquet, maurice.louis.coquet@cern.ch // +#include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include +#include #include using namespace o2; @@ -34,30 +43,68 @@ using namespace o2::framework::expressions; using SMatrix55 = ROOT::Math::SMatrix>; using SMatrix5 = ROOT::Math::SVector; +using MuonsWithCov = soa::Join; + struct FwdTrackExtension { - Produces extendedTrackQuantities; + Produces fwdDCA; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable configCcdbUrl{"configCcdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable refitGlobalMuon{"refitGlobalMuon", false, "Recompute parameters of global muons"}; + + 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 - void process(aod::FwdTracks const& tracks, aod::Collisions const&) + void init(o2::framework::InitContext&) { - for (auto& track : tracks) { + // Load geometry + fCCDB->setURL(configCcdbUrl); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + LOGF(info, "Load geometry from CCDB"); + fCCDB->get(geoPath); + } + } + + void process(MuonsWithCov const& tracks, aod::MFTTracks const& /*...*/, o2::aod::BCsWithTimestamps const& /*...*/, aod::Collisions const& /*...*/) + { + for (const auto& track : tracks) { + const auto trackType = track.trackType(); float dcaX = -999; float dcaY = -999; if (track.has_collision()) { - if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack || track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - - auto const& collision = track.collision(); - double chi2 = track.chi2(); - SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); - std::vector v1; - SMatrix55 tcovs(v1.begin(), v1.end()); - o2::track::TrackParCovFwd pars1{track.z(), tpars, tcovs, chi2}; - pars1.propagateToZlinear(collision.posZ()); + auto const& collision = track.collision(); + auto bc = collision.template bc_as(); + if (fCurrentRun != bc.runNumber()) { + grpmag = fCCDB->getForTimeStamp(grpmagPath, bc.timestamp()); + if (grpmag != nullptr) { + LOGF(info, "Init field from GRP"); + o2::base::Propagator::initFieldFromGRP(grpmag); + } + LOGF(info, "Set field for muons"); + o2::mch::TrackExtrap::setField(); + fCurrentRun = bc.runNumber(); + } + const float zField = grpmag->getNominalL3Field(); - dcaX = (pars1.getX() - collision.posX()); - dcaY = (pars1.getY() - collision.posY()); + o2::track::TrackParCovFwd fwdtrack = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, 0.0); + if (refitGlobalMuon && (trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || trackType == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack)) { + auto muontrack = track.template matchMCHTrack_as(); + auto mfttrack = track.template matchMFTTrack_as(); + o2::dataformats::GlobalFwdTrack propmuon = o2::aod::fwdtrackutils::propagateMuon(muontrack, muontrack, collision, o2::aod::fwdtrackutils::propagationPoint::kToVertex, 0.f, zField); + SMatrix5 tpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + SMatrix55 tcovs{}; + o2::track::TrackParCovFwd mft{mfttrack.z(), tpars, tcovs, mfttrack.chi2()}; + fwdtrack = o2::aod::fwdtrackutils::refitGlobalMuonCov(propmuon, mft); } + auto proptrack = o2::aod::fwdtrackutils::propagateTrackParCovFwd(fwdtrack, trackType, collision, o2::aod::fwdtrackutils::propagationPoint::kToDCA, 0.f, zField); + dcaX = (proptrack.getX() - collision.posX()); + dcaY = (proptrack.getY() - collision.posY()); } - extendedTrackQuantities(dcaX, dcaY); + fwdDCA(dcaX, dcaY); } } }; diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx index f3ffaa91369..d7bab672261 100644 --- a/Common/TableProducer/qVectorsTable.cxx +++ b/Common/TableProducer/qVectorsTable.cxx @@ -129,15 +129,6 @@ struct qVectorsTable { Produces qVectorTPCnegVec; Produces qVectorTPCallVec; - Produces qVectorShifted; - Produces qVectorFT0CShiftedVec; - Produces qVectorFT0AShiftedVec; - Produces qVectorFT0MShiftedVec; - Produces qVectorFV0AShiftedVec; - Produces qVectorTPCposShiftedVec; - Produces qVectorTPCnegShiftedVec; - Produces qVectorTPCallShiftedVec; - std::vector FT0RelGainConst{}; std::vector FV0RelGainConst{}; @@ -184,17 +175,7 @@ struct qVectorsTable { {"QvectorFV0As", cfgUseFV0A}, {"QvectorFT0Ms", cfgUseFT0M}, {"QvectorFT0As", cfgUseFT0A}, - {"QvectorFT0Cs", cfgUseFT0C}, - {"QvectorShiftedBTots", cfgUseBTot}, - {"QvectorShiftedBNegs", cfgUseBNeg}, - {"QvectorShiftedBPoss", cfgUseBPos}, - {"QvectorShiftedTPCalls", cfgUseTPCall}, - {"QvectorShiftedTPCnegs", cfgUseTPCneg}, - {"QvectorShiftedTPCposs", cfgUseTPCpos}, - {"QvectorShiftedFV0As", cfgUseFV0A}, - {"QvectorShiftedFT0Ms", cfgUseFT0M}, - {"QvectorShiftedFT0As", cfgUseFT0A}, - {"QvectorShiftedFT0Cs", cfgUseFT0C}}; + {"QvectorFT0Cs", cfgUseFT0C}}; void init(InitContext& initContext) { @@ -202,7 +183,7 @@ struct qVectorsTable { const auto& workflows = initContext.services().get(); for (DeviceSpec const& device : workflows.devices) { for (auto const& input : device.inputs) { - if (input.matcher.binding == "Qvectors" || input.matcher.binding == "QvectorsShifteds") { + if (input.matcher.binding == "Qvectors") { for (auto const& det : useDetector) { useDetector[det.first.data()] = true; } @@ -596,25 +577,6 @@ struct qVectorsTable { std::vector qvecReTPCall{}; std::vector qvecImTPCall{}; - std::vector qvecShiftedRe{}; - std::vector qvecShiftedIm{}; - std::vector qvecShiftedAmp{}; - - std::vector qvecReShiftedFT0C{}; - std::vector qvecImShiftedFT0C{}; - std::vector qvecReShiftedFT0A{}; - std::vector qvecImShiftedFT0A{}; - std::vector qvecReShiftedFT0M{}; - std::vector qvecImShiftedFT0M{}; - std::vector qvecReShiftedFV0A{}; - std::vector qvecImShiftedFV0A{}; - std::vector qvecReShiftedTPCpos{}; - std::vector qvecImShiftedTPCpos{}; - std::vector qvecReShiftedTPCneg{}; - std::vector qvecImShiftedTPCneg{}; - std::vector qvecReShiftedTPCall{}; - std::vector qvecImShiftedTPCall{}; - auto bc = coll.bc_as(); int currentRun = bc.runNumber(); if (runNumber != currentRun) { @@ -693,36 +655,43 @@ struct qVectorsTable { deltapsiTPCall += ((2. / (1.0 * ishift)) * (-coeffshiftxTPCall * TMath::Cos(ishift * static_cast(nmode) * psidefTPCall) + coeffshiftyTPCall * TMath::Sin(ishift * static_cast(nmode) * psidefTPCall))) / static_cast(nmode); } - qvecReShiftedFT0C.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Cos(deltapsiFT0C) - qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Sin(deltapsiFT0C)); - qvecImShiftedFT0C.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Sin(deltapsiFT0C) + qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Cos(deltapsiFT0C)); - qvecReShiftedFT0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Cos(deltapsiFT0A) - qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Sin(deltapsiFT0A)); - qvecImShiftedFT0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Sin(deltapsiFT0A) + qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Cos(deltapsiFT0A)); - qvecReShiftedFT0M.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Cos(deltapsiFT0M) - qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Sin(deltapsiFT0M)); - qvecImShiftedFT0M.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Sin(deltapsiFT0M) + qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Cos(deltapsiFT0M)); - qvecReShiftedFV0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Cos(deltapsiFV0A) - qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Sin(deltapsiFV0A)); - qvecImShiftedFV0A.push_back(qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Sin(deltapsiFV0A) + qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Cos(deltapsiFV0A)); - qvecReShiftedTPCpos.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Cos(deltapsiTPCpos) - qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Sin(deltapsiTPCpos)); - qvecImShiftedTPCpos.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Sin(deltapsiTPCpos) + qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Cos(deltapsiTPCpos)); - qvecReShiftedTPCneg.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Cos(deltapsiTPCneg) - qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Sin(deltapsiTPCneg)); - qvecImShiftedTPCneg.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Sin(deltapsiTPCneg) + qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Cos(deltapsiTPCneg)); - qvecReShiftedTPCall.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Cos(deltapsiTPCall) - qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Sin(deltapsiTPCall)); - qvecImShiftedTPCall.push_back(qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Sin(deltapsiTPCall) + qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Cos(deltapsiTPCall)); - - qvecShiftedRe.push_back(qvecReShiftedFT0C[id]); - qvecShiftedRe.push_back(qvecReShiftedFT0A[id]); - qvecShiftedRe.push_back(qvecReShiftedFT0M[id]); - qvecShiftedRe.push_back(qvecReShiftedFV0A[id]); - qvecShiftedRe.push_back(qvecReShiftedTPCpos[id]); - qvecShiftedRe.push_back(qvecReShiftedTPCneg[id]); - qvecShiftedRe.push_back(qvecReShiftedTPCall[id]); - - qvecShiftedIm.push_back(qvecImShiftedFT0C[id]); - qvecShiftedIm.push_back(qvecImShiftedFT0A[id]); - qvecShiftedIm.push_back(qvecImShiftedFT0M[id]); - qvecShiftedIm.push_back(qvecImShiftedFV0A[id]); - qvecShiftedIm.push_back(qvecImShiftedTPCpos[id]); - qvecShiftedIm.push_back(qvecImShiftedTPCneg[id]); - qvecShiftedIm.push_back(qvecImShiftedTPCall[id]); + deltapsiFT0C *= static_cast(nmode); + deltapsiFT0A *= static_cast(nmode); + deltapsiFT0M *= static_cast(nmode); + deltapsiFV0A *= static_cast(nmode); + deltapsiTPCpos *= static_cast(nmode); + deltapsiTPCneg *= static_cast(nmode); + deltapsiTPCall *= static_cast(nmode); + + float qvecReShiftedFT0C = qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Cos(deltapsiFT0C) - qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Sin(deltapsiFT0C); + float qvecImShiftedFT0C = qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Sin(deltapsiFT0C) + qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] * TMath::Cos(deltapsiFT0C); + float qvecReShiftedFT0A = qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Cos(deltapsiFT0A) - qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Sin(deltapsiFT0A); + float qvecImShiftedFT0A = qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Sin(deltapsiFT0A) + qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] * TMath::Cos(deltapsiFT0A); + float qvecReShiftedFT0M = qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Cos(deltapsiFT0M) - qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Sin(deltapsiFT0M); + float qvecImShiftedFT0M = qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Sin(deltapsiFT0M) + qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] * TMath::Cos(deltapsiFT0M); + float qvecReShiftedFV0A = qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Cos(deltapsiFV0A) - qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Sin(deltapsiFV0A); + float qvecImShiftedFV0A = qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Sin(deltapsiFV0A) + qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] * TMath::Cos(deltapsiFV0A); + float qvecReShiftedTPCpos = qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Cos(deltapsiTPCpos) - qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Sin(deltapsiTPCpos); + float qvecImShiftedTPCpos = qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Sin(deltapsiTPCpos) + qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] * TMath::Cos(deltapsiTPCpos); + float qvecReShiftedTPCneg = qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Cos(deltapsiTPCneg) - qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Sin(deltapsiTPCneg); + float qvecImShiftedTPCneg = qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Sin(deltapsiTPCneg) + qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] * TMath::Cos(deltapsiTPCneg); + float qvecReShiftedTPCall = qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Cos(deltapsiTPCall) - qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Sin(deltapsiTPCall); + float qvecImShiftedTPCall = qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Sin(deltapsiTPCall) + qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] * TMath::Cos(deltapsiTPCall); + + qvecRe[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] = qvecReShiftedFT0C; + qvecIm[(kTPCall + 1) * 4 * id + kFT0C * 4 + 3] = qvecImShiftedFT0C; + qvecRe[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] = qvecReShiftedFT0A; + qvecIm[(kTPCall + 1) * 4 * id + kFT0A * 4 + 3] = qvecImShiftedFT0A; + qvecRe[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] = qvecReShiftedFT0M; + qvecIm[(kTPCall + 1) * 4 * id + kFT0M * 4 + 3] = qvecImShiftedFT0M; + qvecRe[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] = qvecReShiftedFV0A; + qvecIm[(kTPCall + 1) * 4 * id + kFV0A * 4 + 3] = qvecImShiftedFV0A; + qvecRe[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] = qvecReShiftedTPCpos; + qvecIm[(kTPCall + 1) * 4 * id + kTPCpos * 4 + 3] = qvecImShiftedTPCpos; + qvecRe[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] = qvecReShiftedTPCneg; + qvecIm[(kTPCall + 1) * 4 * id + kTPCneg * 4 + 3] = qvecImShiftedTPCneg; + qvecRe[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] = qvecReShiftedTPCall; + qvecIm[(kTPCall + 1) * 4 * id + kTPCall * 4 + 3] = qvecImShiftedTPCall; } } int CorrLevel = cfgCorrLevel == 0 ? 0 : cfgCorrLevel - 1; @@ -767,17 +736,6 @@ struct qVectorsTable { qVectorTPCnegVec(IsCalibrated, qvecReTPCneg, qvecImTPCneg, qvecAmp[kTPCneg], TrkTPCnegLabel); qVectorTPCallVec(IsCalibrated, qvecReTPCall, qvecImTPCall, qvecAmp[kTPCall], TrkTPCallLabel); - if (cfgShiftCorr) { - qVectorShifted(cent, IsCalibrated, qvecShiftedRe, qvecShiftedIm, qvecAmp); - qVectorFT0CShiftedVec(IsCalibrated, qvecReShiftedFT0C, qvecImShiftedFT0C, qvecAmp[kFT0C]); - qVectorFT0AShiftedVec(IsCalibrated, qvecReShiftedFT0A, qvecImShiftedFT0A, qvecAmp[kFT0A]); - qVectorFT0MShiftedVec(IsCalibrated, qvecReShiftedFT0M, qvecImShiftedFT0M, qvecAmp[kFT0M]); - qVectorFV0AShiftedVec(IsCalibrated, qvecReShiftedFV0A, qvecImShiftedFV0A, qvecAmp[kFV0A]); - qVectorTPCposShiftedVec(IsCalibrated, qvecReShiftedTPCpos, qvecImShiftedTPCpos, qvecAmp[kTPCpos], TrkTPCposLabel); - qVectorTPCnegShiftedVec(IsCalibrated, qvecReShiftedTPCneg, qvecImShiftedTPCneg, qvecAmp[kTPCneg], TrkTPCnegLabel); - qVectorTPCallShiftedVec(IsCalibrated, qvecReShiftedTPCall, qvecImShiftedTPCall, 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); diff --git a/Common/TableProducer/selectionStudyTable.cxx b/Common/TableProducer/selectionStudyTable.cxx index bd7febf9bb9..6f69da4b4f1 100644 --- a/Common/TableProducer/selectionStudyTable.cxx +++ b/Common/TableProducer/selectionStudyTable.cxx @@ -105,9 +105,6 @@ struct SelectionStudyTable { if (std::abs(mcPart.pdgCode()) == 3334) { ptom.push_back(mcPart.pt()); } - if (std::abs(mcPart.pdgCode()) == 3334) { - ptom.push_back(mcPart.pt()); - } // inclusive HF for now if (std::abs(mcPart.pdgCode()) == 421) { ptd.push_back(mcPart.pt()); diff --git a/Common/TableProducer/zdcExtraTableProducer.cxx b/Common/TableProducer/zdcExtraTableProducer.cxx index 500854b196b..24e34f058df 100644 --- a/Common/TableProducer/zdcExtraTableProducer.cxx +++ b/Common/TableProducer/zdcExtraTableProducer.cxx @@ -58,17 +58,18 @@ struct ZdcExtraTableProducer { // Event selections Configurable cfgEvSelSel8{"cfgEvSelSel8", true, "Event selection: sel8"}; Configurable cfgEvSelVtxZ{"cfgEvSelVtxZ", 10, "Event selection: zVtx"}; - Configurable cfgEvSelsDoOccupancySel{"cfgEvSelsDoOccupancySel", true, "Event selection: do occupancy selection"}; + Configurable cfgEvSelsDoOccupancySel{"cfgEvSelsDoOccupancySel", false, "Event selection: do occupancy selection"}; Configurable cfgEvSelsMaxOccupancy{"cfgEvSelsMaxOccupancy", 10000, "Event selection: set max occupancy"}; - Configurable cfgEvSelsNoSameBunchPileupCut{"cfgEvSelsNoSameBunchPileupCut", true, "Event selection: no same bunch pileup cut"}; - Configurable cfgEvSelsIsGoodZvtxFT0vsPV{"cfgEvSelsIsGoodZvtxFT0vsPV", true, "Event selection: is good ZVTX FT0 vs PV"}; - Configurable cfgEvSelsNoCollInTimeRangeStandard{"cfgEvSelsNoCollInTimeRangeStandard", true, "Event selection: no collision in time range standard"}; - Configurable cfgEvSelsIsVertexITSTPC{"cfgEvSelsIsVertexITSTPC", true, "Event selection: is vertex ITSTPC"}; - Configurable cfgEvSelsIsGoodITSLayersAll{"cfgEvSelsIsGoodITSLayersAll", true, "Event selection: is good ITS layers all"}; + Configurable cfgEvSelsNoSameBunchPileupCut{"cfgEvSelsNoSameBunchPileupCut", false, "Event selection: no same bunch pileup cut"}; + Configurable cfgEvSelsIsGoodZvtxFT0vsPV{"cfgEvSelsIsGoodZvtxFT0vsPV", false, "Event selection: is good ZVTX FT0 vs PV"}; + Configurable cfgEvSelsNoCollInTimeRangeStandard{"cfgEvSelsNoCollInTimeRangeStandard", false, "Event selection: no collision in time range standard"}; + Configurable cfgEvSelsIsVertexITSTPC{"cfgEvSelsIsVertexITSTPC", false, "Event selection: is vertex ITSTPC"}; + Configurable cfgEvSelsIsGoodITSLayersAll{"cfgEvSelsIsGoodITSLayersAll", false, "Event selection: is good ITS layers all"}; // Calibration settings Configurable cfgCalibrationDownscaling{"cfgCalibrationDownscaling", 1.f, "Percentage of events to be saved to derived table"}; - HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // Output settings + Configurable cfgSaveQaHistos{"cfgSaveQaHistos", false, "Flag to save QA histograms"}; enum SelectionCriteria { evSel_zvtx, @@ -83,8 +84,27 @@ struct ZdcExtraTableProducer { nEventSelections }; + HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + void init(InitContext const&) { + + registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_allEvents + 1, "All events"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_zvtx + 1, "vtxZ"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_occupancy + 1, "kOccupancy"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoSameBunchPileup + 1, "kNoSameBunchPileup"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsVertexITSTPC + 1, "kIsVertexITSTPC"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + + // Skip histogram registration if QA flag is false + if (!cfgSaveQaHistos) { + return; + } + 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}}}); @@ -100,17 +120,6 @@ struct ZdcExtraTableProducer { registry.add("ZNACentroid", "ZNA Centroid; X; Y", {HistType::kTH2F, {{50, -1.5, 1.5}, {50, -1.5, 1.5}}}); registry.add("ZNCCentroid", "ZNC Centroid; X; Y", {HistType::kTH2F, {{50, -1.5, 1.5}, {50, -1.5, 1.5}}}); - - registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_allEvents + 1, "All events"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_zvtx + 1, "vtxZ"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_occupancy + 1, "kOccupancy"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoSameBunchPileup + 1, "kNoSameBunchPileup"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kNoCollInTimeRangeStandard + 1, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsVertexITSTPC + 1, "kIsVertexITSTPC"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); } template @@ -176,7 +185,7 @@ struct ZdcExtraTableProducer { void process(ColEvSels const& cols, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) { // collision-based event selection - int nTowers = 4; // number of ZDC towers + constexpr int NTowers = 4; // number of ZDC towers for (auto const& collision : cols) { const auto& foundBC = collision.foundBC_as(); @@ -185,6 +194,24 @@ struct ZdcExtraTableProducer { uint8_t evSelection = eventSelected(collision); + // add event selection + if (cfgEvSelSel8 && !(evSelection & (1 << evSel_sel8))) + continue; + if (!(evSelection & (1 << evSel_zvtx))) + continue; + if (cfgEvSelsDoOccupancySel && !(evSelection & (1 << evSel_occupancy))) + continue; + if (cfgEvSelsNoSameBunchPileupCut && !(evSelection & (1 << evSel_kNoSameBunchPileup))) + continue; + if (cfgEvSelsIsGoodZvtxFT0vsPV && !(evSelection & (1 << evSel_kIsGoodZvtxFT0vsPV))) + continue; + if (cfgEvSelsNoCollInTimeRangeStandard && !(evSelection & (1 << evSel_kNoCollInTimeRangeStandard))) + continue; + if (cfgEvSelsIsVertexITSTPC && !(evSelection & (1 << evSel_kIsVertexITSTPC))) + continue; + if (cfgEvSelsIsGoodITSLayersAll && !(evSelection & (1 << evSel_kIsGoodITSLayersAll))) + continue; + float centrality = collision.centFT0C(); // To assure that ZN have a genuine signal (tagged by the relative TDC) @@ -196,6 +223,7 @@ struct ZdcExtraTableProducer { // double tdcZNC = zdc.timeZNC(); double tdcZNA = zdc.timeZNA(); + // OR we can select a narrow window in both ZN TDCs using the configurable parameters if (tdcCut) { // a narrow TDC window is set if ((tdcZNC >= tdcZNmincut) && (tdcZNC <= tdcZNmaxcut)) { @@ -219,29 +247,34 @@ struct ZdcExtraTableProducer { double pmqZNA[4] = {}; // if (isZNChit) { - for (int it = 0; it < nTowers; it++) { + for (int it = 0; it < NTowers; 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 (cfgSaveQaHistos) { + 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 < nTowers; it++) { + for (int it = 0; it < NTowers; 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 (cfgSaveQaHistos) { + 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); + } } // Q-vectors (centroid) calculation @@ -257,8 +290,7 @@ struct ZdcExtraTableProducer { float numXZNA = 0., numYZNA = 0., denZNA = 0.; // Calculate weighted sums of the x and y coordinates - constexpr int kNTowers = 4; // number of ZDC towers - for (int i = 0; i < kNTowers; i++) { + for (int i = 0; i < NTowers; i++) { if (pmqZNC[i] > 0.) { float wZNC = std::pow(pmqZNC[i], kAlpha); numXZNC -= X[i] * wZNC; // numerator x (minus sign due to opposite orientation of ZNC) @@ -307,8 +339,14 @@ struct ZdcExtraTableProducer { centroidZNA[0] = 999.; centroidZNA[1] = 999.; } - registry.get(HIST("ZNCCentroid"))->Fill(centroidZNC[0], centroidZNC[1]); - registry.get(HIST("ZNACentroid"))->Fill(centroidZNA[0], centroidZNA[1]); + if (cfgSaveQaHistos) { + if (isZNChit) { + registry.get(HIST("ZNCCentroid"))->Fill(centroidZNC[0], centroidZNC[1]); + } + if (isZNAhit) { + registry.get(HIST("ZNACentroid"))->Fill(centroidZNA[0], centroidZNA[1]); + } + } auto vz = collision.posZ(); auto vx = collision.posX(); diff --git a/Common/Tasks/centralityStudy.cxx b/Common/Tasks/centralityStudy.cxx index a8765e488fc..e4a99dedb88 100644 --- a/Common/Tasks/centralityStudy.cxx +++ b/Common/Tasks/centralityStudy.cxx @@ -106,6 +106,7 @@ struct centralityStudy { Configurable minTimeDelta{"minTimeDelta", -1.0f, "reject collision if another collision is this close or less in time"}; Configurable minFT0CforVertexZ{"minFT0CforVertexZ", -1.0f, "minimum FT0C for vertex-Z profile calculation"}; + Configurable scaleSignalFT0A{"scaleSignalFT0A", 1.00f, "scale FT0A signal for convenience"}; Configurable scaleSignalFT0C{"scaleSignalFT0C", 1.00f, "scale FT0C signal for convenience"}; Configurable scaleSignalFT0M{"scaleSignalFT0M", 1.00f, "scale FT0M signal for convenience"}; Configurable scaleSignalFV0A{"scaleSignalFV0A", 1.00f, "scale FV0A signal for convenience"}; @@ -150,6 +151,7 @@ struct centralityStudy { ConfigurableAxis axisMultUltraFineFV0A{"axisMultUltraFineFV0A", {60000, 0, 60000}, "FV0A amplitude"}; ConfigurableAxis axisMultUltraFineFT0M{"axisMultUltraFineFT0M", {50000, 0, 200000}, "FT0M amplitude"}; ConfigurableAxis axisMultUltraFineFT0C{"axisMultUltraFineFT0C", {60000, 0, 60000}, "FT0C amplitude"}; + ConfigurableAxis axisMultUltraFineFT0A{"axisMultUltraFineFT0A", {60000, 0, 60000}, "FT0A amplitude"}; ConfigurableAxis axisMultUltraFinePVContributors{"axisMultUltraFinePVContributors", {10000, 0, 10000}, "Number of PV Contributors"}; ConfigurableAxis axisMultUltraFineGlobalTracks{"axisMultUltraFineGlobalTracks", {5000, 0, 5000}, "Number of global tracks"}; ConfigurableAxis axisMultUltraFineMFTTracks{"axisMultUltraFineMFTTracks", {5000, 0, 5000}, "Number of MFT tracks"}; @@ -200,6 +202,7 @@ struct centralityStudy { histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(12, "no ITS in-ROF pileup (standard)"); histos.get(HIST("hCollisionSelection"))->GetXaxis()->SetBinLabel(13, "no ITS in-ROF pileup (strict)"); + histos.add("hFT0A_Collisions", "hFT0C_Collisions", kTH1D, {axisMultUltraFineFT0A}); histos.add("hFT0C_Collisions", "hFT0C_Collisions", kTH1D, {axisMultUltraFineFT0C}); histos.add("hFT0M_Collisions", "hFT0M_Collisions", kTH1D, {axisMultUltraFineFT0M}); histos.add("hFV0A_Collisions", "hFV0A_Collisions", kTH1D, {axisMultUltraFineFV0A}); @@ -319,7 +322,7 @@ struct centralityStudy { } template - void initRun(TCollision collision) + void initRun(const TCollision& collision) { if (mRunNumber == collision.multRunNumber()) { return; @@ -371,6 +374,7 @@ struct centralityStudy { getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(13, "no ITS in-ROF pileup (strict)"); histPointers.insert({histPath + "hFT0C_Collisions", histos.add((histPath + "hFT0C_Collisions").c_str(), "hFT0C_Collisions", {kTH1D, {{axisMultUltraFineFT0C}}})}); + histPointers.insert({histPath + "hFT0A_Collisions", histos.add((histPath + "hFT0A_Collisions").c_str(), "hFT0A_Collisions", {kTH1D, {{axisMultUltraFineFT0A}}})}); histPointers.insert({histPath + "hFT0M_Collisions", histos.add((histPath + "hFT0M_Collisions").c_str(), "hFT0M_Collisions", {kTH1D, {{axisMultUltraFineFT0M}}})}); histPointers.insert({histPath + "hFV0A_Collisions", histos.add((histPath + "hFV0A_Collisions").c_str(), "hFV0A_Collisions", {kTH1D, {{axisMultUltraFineFV0A}}})}); histPointers.insert({histPath + "hNGlobalTracks", histos.add((histPath + "hNGlobalTracks").c_str(), "hNGlobalTracks", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); @@ -446,7 +450,7 @@ struct centralityStudy { } template - void genericProcessCollision(TCollision collision) + void genericProcessCollision(const TCollision& collision) // process this collisions { initRun(collision); @@ -625,6 +629,7 @@ struct centralityStudy { // if we got here, we also finally fill the FT0C histogram, please histos.fill(HIST("hNPVContributors"), collision.multNTracksPV()); + histos.fill(HIST("hFT0A_Collisions"), collision.multFT0A() * scaleSignalFT0C); histos.fill(HIST("hFT0C_Collisions"), collision.multFT0C() * scaleSignalFT0C); histos.fill(HIST("hFT0M_Collisions"), (collision.multFT0A() + collision.multFT0C()) * scaleSignalFT0M); histos.fill(HIST("hFV0A_Collisions"), collision.multFV0A() * scaleSignalFV0A); @@ -637,6 +642,7 @@ struct centralityStudy { // save vertex-Z equalized getHist(TH1, histPath + "hNPVContributors")->Fill(multNTracksPV); + getHist(TH1, histPath + "hFT0A_Collisions")->Fill(multFT0A * scaleSignalFT0A); getHist(TH1, histPath + "hFT0C_Collisions")->Fill(multFT0C * scaleSignalFT0C); getHist(TH1, histPath + "hFT0M_Collisions")->Fill((multFT0A + multFT0C) * scaleSignalFT0M); getHist(TH1, histPath + "hFV0A_Collisions")->Fill(multFV0A * scaleSignalFV0A); diff --git a/Common/Tasks/integrationTest.cxx b/Common/Tasks/integrationTest.cxx index c3915100f2a..ba90bdc39f8 100644 --- a/Common/Tasks/integrationTest.cxx +++ b/Common/Tasks/integrationTest.cxx @@ -31,6 +31,7 @@ #include #include +#include using namespace o2; using namespace o2::framework; @@ -51,31 +52,54 @@ struct integrationTest { Configurable do2DNTrackCorr{"do2DNTrackCorr", true, "Do 2D Ntrack correlation plots"}; Configurable doBasicQA{"doBasicQA", true, "Do basic QA"}; + Configurable checkThinning{"checkThinning", true, "Check thinning-related quantities (retaining of TPC-only tracks)"}; ConfigurableAxis axisHasDetector{"axisHasDetector", {16, -0.5f, 15.5f}, ""}; ConfigurableAxis axisEta{"axisEta", {200, -2.0f, 2.0f}, ""}; ConfigurableAxis axisPhi{"axisPhi", {200, 0.0f, +2 * TMath::Pi()}, ""}; ConfigurableAxis axisNclu{"axisNclu", {10, -0.5f, 9.5f}, ""}; 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 analysis"}; + enum kTrackType { kTrackUsedV0 = 0, + kTrackUsedCascade, + kTrackUsedDecay3Body, + kTrackUsedTrackedV0, + kTrackUsedTrackedCascade, + kTrackUsedQA, + kNTrackTypes }; + enum kTable { kBC = 0, + kBCFlag, kCollision, + kOrigin, kTrack, kTrackCov, kTrackExtra, kMftTrack, + kMftTrackCov, kFwdTrack, kFwdTrackCov, + kFwdTrackCl, kAmbiguousTrack, kAmbiguousMftTrack, kAmbiguousFwdTrack, + kTracked3Body, + kTrackedCascade, + kTrackedV0, + kTrackQA, kV0, kCascade, + kDecay3Body, kCalo, kCaloTrigger, + kCpvCluster, kFDD, + kFDDExtra, kFT0, - kV0A, + kFT0Extra, + kFV0A, + kFV0AExtra, kZDC, + kHMPID, kMcCollision, kMcCollisionLabel, kMcParticle, @@ -91,24 +115,38 @@ struct integrationTest { TString lTableNames[] = { "bc", + "bcflag", "collision", + "origin", "track_iu", "trackcov_iu", "trackextra", "mfttrack", + "mfttrackcov", "fwdtrack", "fwdtrackcov", + "fwdtrkcl", "ambiguoustrack", "ambiguousmfttrack", "ambiguousfwdtrack", + "tracked3body", + "trackedcascade", + "trackedv0", + "trackqa", "v0", "cascade", + "decay3body", "calo", - "calotrigger" + "calotrigger", + "cpvcluster", "fdd", + "fddextra", "ft0", + "ft0extra", "fv0a", + "fv0aextra", "zdc", + "hmpid", "mccollision", "mccollisionlabel", "mcparticle", @@ -118,7 +156,7 @@ struct integrationTest { "Total count", "" // empty (last) }; - const AxisSpec axisTables{30, 0.0f, 30.0f, ""}; + const AxisSpec axisTables{40, 0.0f, 40.0f, ""}; const AxisSpec axisTracks{nBinsTracks, -0.5f, MaxNTrack - 0.5f, "N_{tracks}"}; const AxisSpec axisCollisions{nBinsCollisions, -0.5f, nBinsCollisions - 0.5f, "N_{collisions}"}; // Label correctly to avoid confusion @@ -171,6 +209,31 @@ struct integrationTest { histos.add("hNCluAll", "hNCluAll", HistType::kTH1D, {axisNclu}); histos.add("hNCluNoTPCOnly", "hNCluNoTPCOnly", HistType::kTH1D, {axisNclu}); } + if (checkThinning) { + auto hThinningQA = histos.add("hThinningQA", "hThinningQA", HistType::kTH2D, {{64, -0.5f, 63.5f}, {2, -0.5f, 1.5f}}); + + TString kTrackTypeNames[] = + { + "V", + "tV", + "3b", + "C", + "tC", + "QA"}; + + // construct labels to make this plot easier to understand + for (uint8_t i = 0; i < (1 << kNTrackTypes); i++) { + TString trackTypeString = ""; + for (uint8_t j = 0; j < kTrackUsedQA + 1; j++) { + if (((i) & (1 << (j)))) { + trackTypeString.Append(Form("%s ", kTrackTypeNames[j].Data())); + } + } + hThinningQA->GetXaxis()->SetBinLabel(i + 1, trackTypeString.Data()); + } + hThinningQA->GetYaxis()->SetBinLabel(0, "Not TPConly"); + hThinningQA->GetYaxis()->SetBinLabel(1, "TPConly"); + } } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* // Standard sizes (uncorrelated) @@ -193,42 +256,163 @@ struct integrationTest { aod::FDDs const& fdds, aod::FT0s const& ft0s, aod::FV0As const& fv0as, + aod::Zdcs const& zdcs) + { + histos.fill(HIST("hTableSizes"), static_cast(kBC) + 0.5f, bcs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kCollision) + 0.5f, collisions.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTrack) + 0.5f, tracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTrackCov) + 0.5f, trackcovs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTrackExtra) + 0.5f, trackextras.size()); + histos.fill(HIST("hTableSizes"), static_cast(kMftTrack) + 0.5f, mfttracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFwdTrack) + 0.5f, fwdtracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFwdTrackCov) + 0.5f, fwdtrackcovs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kAmbiguousTrack) + 0.5f, ambitracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kAmbiguousMftTrack) + 0.5f, ambimfttracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kAmbiguousFwdTrack) + 0.5f, ambifwdtracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kV0) + 0.5f, v0s.size()); + histos.fill(HIST("hTableSizes"), static_cast(kCascade) + 0.5f, cascades.size()); + histos.fill(HIST("hTableSizes"), static_cast(kCalo) + 0.5f, calos.size()); + histos.fill(HIST("hTableSizes"), static_cast(kCaloTrigger) + 0.5f, calotriggers.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFDD) + 0.5f, fdds.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFT0) + 0.5f, ft0s.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFV0A) + 0.5f, fv0as.size()); + histos.fill(HIST("hTableSizes"), static_cast(kZDC) + 0.5f, zdcs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFrameCounter) + 0.5f); + } + PROCESS_SWITCH(integrationTest, processDataModel, "Check data model", true); + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // Revised tables for newer data + // Warning: will not work for legacy AO2Ds + void processDataModel2026( + aod::BCs const& bcs, + aod::BCFlags const& bcflags, + aod::Collisions const& collisions, + aod::Origins const& origins, + aod::TracksIU const& tracks, + aod::TracksCovIU const& trackcovs, + aod::TracksExtra const& trackextras, + aod::MFTTracks const& mfttracks, + aod::MFTTracksCov const& mfttrackcovs, + aod::FwdTracks const& fwdtracks, + aod::FwdTracksCov const& fwdtrackcovs, + aod::FwdTrkCls const& fwdtrkcls, + aod::AmbiguousTracks const& ambitracks, + aod::AmbiguousMFTTracks const& ambimfttracks, + aod::AmbiguousFwdTracks const& ambifwdtracks, + aod::Tracked3Bodys const& tracked3bodys, + aod::TrackedCascades const& trackedcascades, + aod::TrackedV0s const& trackedv0s, + aod::TracksQAVersion const& tracksQA, // does not comply with normal iterator naming + aod::V0s const& v0s, + aod::Cascades const& cascades, + aod::Decay3Bodys const& decay3bodys, + aod::Calos const& calos, + aod::CaloTriggers const& calotriggers, + aod::CPVClusters const& cpvclusters, + aod::FDDs const& fdds, + aod::FDDsExtra const& fddsextra, + aod::FT0s const& ft0s, + aod::FT0sExtra const& ft0sextra, + aod::FV0As const& fv0as, + aod::FV0AsExtra const& fv0asextra, aod::Zdcs const& zdcs, - aod::McCollisions const& mccollisions, - aod::McCollisionLabels const& mccollisionlabels, - aod::McParticles const& mcparticles, - aod::McTrackLabels const& mctracklabels, - aod::McMFTTrackLabels const& mcmfttracklabels, - aod::McFwdTrackLabels const& mcfwdtracklabels) + aod::HMPIDs const& hmpids) { histos.fill(HIST("hTableSizes"), static_cast(kBC) + 0.5f, bcs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kBCFlag) + 0.5f, bcflags.size()); histos.fill(HIST("hTableSizes"), static_cast(kCollision) + 0.5f, collisions.size()); + histos.fill(HIST("hTableSizes"), static_cast(kOrigin) + 0.5f, origins.size()); histos.fill(HIST("hTableSizes"), static_cast(kTrack) + 0.5f, tracks.size()); histos.fill(HIST("hTableSizes"), static_cast(kTrackCov) + 0.5f, trackcovs.size()); histos.fill(HIST("hTableSizes"), static_cast(kTrackExtra) + 0.5f, trackextras.size()); histos.fill(HIST("hTableSizes"), static_cast(kMftTrack) + 0.5f, mfttracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kMftTrackCov) + 0.5f, mfttrackcovs.size()); histos.fill(HIST("hTableSizes"), static_cast(kFwdTrack) + 0.5f, fwdtracks.size()); histos.fill(HIST("hTableSizes"), static_cast(kFwdTrackCov) + 0.5f, fwdtrackcovs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFwdTrackCl) + 0.5f, fwdtrkcls.size()); histos.fill(HIST("hTableSizes"), static_cast(kAmbiguousTrack) + 0.5f, ambitracks.size()); histos.fill(HIST("hTableSizes"), static_cast(kAmbiguousMftTrack) + 0.5f, ambimfttracks.size()); histos.fill(HIST("hTableSizes"), static_cast(kAmbiguousFwdTrack) + 0.5f, ambifwdtracks.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTracked3Body) + 0.5f, tracked3bodys.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTrackedCascade) + 0.5f, trackedcascades.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTrackedV0) + 0.5f, trackedv0s.size()); + histos.fill(HIST("hTableSizes"), static_cast(kTrackQA) + 0.5f, tracksQA.size()); histos.fill(HIST("hTableSizes"), static_cast(kV0) + 0.5f, v0s.size()); histos.fill(HIST("hTableSizes"), static_cast(kCascade) + 0.5f, cascades.size()); + histos.fill(HIST("hTableSizes"), static_cast(kDecay3Body) + 0.5f, decay3bodys.size()); histos.fill(HIST("hTableSizes"), static_cast(kCalo) + 0.5f, calos.size()); histos.fill(HIST("hTableSizes"), static_cast(kCaloTrigger) + 0.5f, calotriggers.size()); + histos.fill(HIST("hTableSizes"), static_cast(kCpvCluster) + 0.5f, cpvclusters.size()); histos.fill(HIST("hTableSizes"), static_cast(kFDD) + 0.5f, fdds.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFDDExtra) + 0.5f, fddsextra.size()); histos.fill(HIST("hTableSizes"), static_cast(kFT0) + 0.5f, ft0s.size()); - histos.fill(HIST("hTableSizes"), static_cast(kV0A) + 0.5f, fv0as.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFT0Extra) + 0.5f, ft0sextra.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFV0A) + 0.5f, fv0as.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFV0AExtra) + 0.5f, fv0asextra.size()); histos.fill(HIST("hTableSizes"), static_cast(kZDC) + 0.5f, zdcs.size()); + histos.fill(HIST("hTableSizes"), static_cast(kHMPID) + 0.5f, hmpids.size()); + histos.fill(HIST("hTableSizes"), static_cast(kFrameCounter) + 0.5f); + + if (checkThinning) { + // perform checks regarding thinning + std::vector trackBits(tracks.size(), 0); + + if (tracks.size() != trackextras.size()) { + LOGF(fatal, "Check thinning requested and Tracks.size() != TracksExtra.size(). Very bad. Quitting..."); + } + + // mark tracks that are used by each kind of composite object + for (const auto& v0 : v0s) { + trackBits[v0.negTrackId()] = trackBits[v0.negTrackId()] | (1 << kTrackUsedV0); + trackBits[v0.posTrackId()] = trackBits[v0.posTrackId()] | (1 << kTrackUsedV0); + } + for (const auto& cascade : cascades) { + auto v0 = cascade.v0(); // simple de-ref, no table joining + trackBits[v0.negTrackId()] = trackBits[v0.negTrackId()] | (1 << kTrackUsedCascade); + trackBits[v0.posTrackId()] = trackBits[v0.posTrackId()] | (1 << kTrackUsedCascade); + trackBits[cascade.bachelorId()] = trackBits[cascade.bachelorId()] | (1 << kTrackUsedCascade); + } + for (const auto& trackedv0 : trackedv0s) { + auto v0 = trackedv0.v0(); // simple de-ref, no table joining + trackBits[v0.negTrackId()] = trackBits[v0.negTrackId()] | (1 << kTrackUsedTrackedV0); + trackBits[v0.posTrackId()] = trackBits[v0.posTrackId()] | (1 << kTrackUsedTrackedV0); + } + for (const auto& trackedcascade : trackedcascades) { + auto cascade = trackedcascade.cascade(); // simple de-ref, no table joining + auto v0 = cascade.v0(); // simple de-ref, no table joining + trackBits[v0.negTrackId()] = trackBits[v0.negTrackId()] | (1 << kTrackUsedTrackedCascade); + trackBits[v0.posTrackId()] = trackBits[v0.posTrackId()] | (1 << kTrackUsedTrackedCascade); + trackBits[cascade.bachelorId()] = trackBits[cascade.bachelorId()] | (1 << kTrackUsedTrackedCascade); + } + for (const auto& trackQA : tracksQA) { + trackBits[trackQA.trackId()] = trackBits[trackQA.trackId()] | (1 << kTrackUsedQA); + } + for (uint32_t iTrack = 0; iTrack < trackextras.size(); iTrack++) { + auto track = trackextras.rawIteratorAt(iTrack); + bool isTPConly = track.hasTPC() && !track.hasTOF() && !track.hasTRD() && !track.hasITS(); + histos.fill(HIST("hThinningQA"), static_cast(trackBits[iTrack]), static_cast(isTPConly)); + } + } + } + PROCESS_SWITCH(integrationTest, processDataModel2026, "Check data model, 2026 version", false); + + void processDataModelMC( + aod::McCollisions const& mccollisions, + aod::McCollisionLabels const& mccollisionlabels, + aod::McParticles const& mcparticles, + aod::McTrackLabels const& mctracklabels, + aod::McMFTTrackLabels const& mcmfttracklabels, + aod::McFwdTrackLabels const& mcfwdtracklabels) + { histos.fill(HIST("hTableSizes"), static_cast(kMcCollision) + 0.5f, mccollisions.size()); histos.fill(HIST("hTableSizes"), static_cast(kMcCollisionLabel) + 0.5f, mccollisionlabels.size()); histos.fill(HIST("hTableSizes"), static_cast(kMcParticle) + 0.5f, mcparticles.size()); histos.fill(HIST("hTableSizes"), static_cast(kMcTrackLabel) + 0.5f, mctracklabels.size()); histos.fill(HIST("hTableSizes"), static_cast(kMcMftTrackLabel) + 0.5f, mcmfttracklabels.size()); histos.fill(HIST("hTableSizes"), static_cast(kMcFwdTrackLabel) + 0.5f, mcfwdtracklabels.size()); - histos.fill(HIST("hTableSizes"), static_cast(kFrameCounter) + 0.5f); } - PROCESS_SWITCH(integrationTest, processDataModel, "Check data model", true); + PROCESS_SWITCH(integrationTest, processDataModelMC, "Check data model for MC tables", false); void processBCs(aod::BC const&, aod::Collisions const& collisions) { @@ -239,7 +423,7 @@ struct integrationTest { void processCollisions(aod::Collision const&, FullTracksIU const& tracks, aod::V0s const& v0s, aod::Cascades const& cascades) { Int_t lHasITS = 0, lHasTPC = 0, lHasTRD = 0, lHasTOF = 0, lNotTPCOnly = 0; - for (auto& track : tracks) { + for (const auto& track : tracks) { // TPC only bool bool isTPConly = track.hasTPC() && !track.hasTOF() && !track.hasTRD() && !track.hasITS(); histos.fill(HIST("hPt"), track.pt()); diff --git a/Common/Tasks/integrationTestCCDB.cxx b/Common/Tasks/integrationTestCCDB.cxx index c7096d5774c..d1fe98d142c 100644 --- a/Common/Tasks/integrationTestCCDB.cxx +++ b/Common/Tasks/integrationTestCCDB.cxx @@ -103,12 +103,12 @@ struct integrationTestCCDB { lut = 0x0; const AxisSpec axis{1, 0.0f, 1.0f, ""}; histos.add("hDFs", "hDFs", HistType::kTH1F, {axis}); + + mRunNumber = 0; } void process(aod::BCsWithTimestamps const& bcs) { - mRunNumber = 0; - auto bc = bcs.begin(); // first element histos.fill(HIST("hDFs"), 0.5f); diff --git a/Common/Tasks/qVectorsCorrection.cxx b/Common/Tasks/qVectorsCorrection.cxx index 042756e3c82..facbf144c4d 100644 --- a/Common/Tasks/qVectorsCorrection.cxx +++ b/Common/Tasks/qVectorsCorrection.cxx @@ -49,7 +49,6 @@ using namespace o2; using namespace o2::framework; using MyCollisions = soa::Join; -using MyCollisionsWithSC = soa::Join; using MyTracks = soa::Join; struct qVectorsCorrection { @@ -757,49 +756,6 @@ struct qVectorsCorrection { } } PROCESS_SWITCH(qVectorsCorrection, processDefault, "default process", true); - - void processWithSC(MyCollisionsWithSC::iterator const& qVec, MyTracks const& tracks) - { - histosQA.fill(HIST("histCentFull"), qVec.cent()); - if (cfgAddEvtSel) { - if (std::abs(qVec.posZ()) > 10.) - return; - switch (cfgEvtSel) { - case 0: // Sel8 - if (!qVec.sel8()) - return; - break; - case 1: // PbPb standard - if (!qVec.sel8() || !qVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !qVec.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 2: // PbPb with pileup - if (!qVec.sel8() || !qVec.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || - !qVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !qVec.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 3: // Small systems (OO, NeNe, pp) - if (!qVec.sel8() || !qVec.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - default: - LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); - } - // Check occupancy - if (qVec.trackOccupancyInTimeRange() > cfgMaxOccupancy || qVec.trackOccupancyInTimeRange() < cfgMinOccupancy) - return; - } - histosQA.fill(HIST("histCentSelected"), qVec.cent()); - histosQA.fill(HIST("histVtxSelected"), qVec.posZ()); - - for (uint i = 0; i < cfgnMods->size(); i++) { - fillHistosQvecWithSC(qVec, cfgnMods->at(i)); - if (cfgQAFinal && cfgQAFlowStudy) { - fillHistosFlowWithSC(qVec, tracks, cfgnMods->at(i)); - } - } - } - PROCESS_SWITCH(qVectorsCorrection, processWithSC, "process with shift correction", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index e57adbaa7dd..d96f05fc2a6 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -533,7 +533,7 @@ struct muonQa { for (size_t i = 0; i < 2; i++) { std::string topBottom = (i == 0) ? "top" : "bottom"; AxisSpec deAxis = {26, 0, 26, "DE index"}; - AxisSpec phiAxis = {16, -180, 180, "#phi (degrees)"}; + AxisSpec phiAxisInner = {16, -180, 180, "#phi (degrees)"}; for (size_t j = 0; j < 2; j++) { std::string sign = (j == 0) ? "positive" : "negative"; for (int chamber = 0; chamber < 10; chamber++) { @@ -542,8 +542,8 @@ struct muonQa { residualsHistosPerDE[i][j][chamber]["dx_vs_de"] = registryResidualsMFT.add((histPath + "dx_vs_de").c_str(), "Cluster x residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); residualsHistosPerDE[i][j][chamber]["dy_vs_de"] = registryResidualsMFT.add((histPath + "dy_vs_de").c_str(), "Cluster y residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); - residualsHistosPerDE[i][j][chamber]["dx_vs_phi"] = registryResidualsMFT.add((histPath + "dx_vs_phi").c_str(), "Cluster x residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); - residualsHistosPerDE[i][j][chamber]["dy_vs_phi"] = registryResidualsMFT.add((histPath + "dy_vs_phi").c_str(), "Cluster y residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); + residualsHistosPerDE[i][j][chamber]["dx_vs_phi"] = registryResidualsMFT.add((histPath + "dx_vs_phi").c_str(), "Cluster x residual vs. cluster #phi", {HistType::kTH2F, {phiAxisInner, dxAxis}}); + residualsHistosPerDE[i][j][chamber]["dy_vs_phi"] = registryResidualsMFT.add((histPath + "dy_vs_phi").c_str(), "Cluster y residual vs. cluster #phi", {HistType::kTH2F, {phiAxisInner, dxAxis}}); // mixed events histPath = std::string("Alignment/mixed-event/Residuals/MFT/MFT_") + topBottom + "/" + sign + "/CH" + std::to_string(chamber + 1) + "/"; @@ -551,8 +551,8 @@ struct muonQa { residualsHistosPerDEMixedEvents[i][j][chamber]["dx_vs_de"] = registryResidualsMFT.add((histPath + "dx_vs_de").c_str(), "Cluster x residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); residualsHistosPerDEMixedEvents[i][j][chamber]["dy_vs_de"] = registryResidualsMFT.add((histPath + "dy_vs_de").c_str(), "Cluster y residual vs. DE index", {HistType::kTH2F, {deAxis, dxAxis}}); - residualsHistosPerDEMixedEvents[i][j][chamber]["dx_vs_phi"] = registryResidualsMFT.add((histPath + "dx_vs_phi").c_str(), "Cluster x residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); - residualsHistosPerDEMixedEvents[i][j][chamber]["dy_vs_phi"] = registryResidualsMFT.add((histPath + "dy_vs_phi").c_str(), "Cluster y residual vs. cluster #phi", {HistType::kTH2F, {phiAxis, dxAxis}}); + residualsHistosPerDEMixedEvents[i][j][chamber]["dx_vs_phi"] = registryResidualsMFT.add((histPath + "dx_vs_phi").c_str(), "Cluster x residual vs. cluster #phi", {HistType::kTH2F, {phiAxisInner, dxAxis}}); + residualsHistosPerDEMixedEvents[i][j][chamber]["dy_vs_phi"] = registryResidualsMFT.add((histPath + "dy_vs_phi").c_str(), "Cluster y residual vs. cluster #phi", {HistType::kTH2F, {phiAxisInner, dxAxis}}); } } } @@ -738,7 +738,7 @@ struct muonQa { AxisSpec rAbsAxis = {10, 0., 100.0, "R_{abs} (cm)"}; AxisSpec dcaAxis = {400, -10.0, 10.0, "DCA"}; AxisSpec dcaAxisReduced = {40, -10.0, 10.0, "DCA"}; - AxisSpec phiAxis = {36, -180.0, 180.0, "#phi (degrees)"}; + AxisSpec phiAxisInner = {36, -180.0, 180.0, "#phi (degrees)"}; // dimuons AxisSpec invMassAxis = {400, 1, 5, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; AxisSpec invMassCorrelationAxis = {80, 0, 8, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; @@ -801,8 +801,8 @@ struct muonQa { registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosDca_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} DCA", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, dcaAxisReduced}}); registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegDca_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} DCA", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, dcaAxisReduced}}); // - registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosPhi_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} #phi", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, phiAxis}}); - registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegPhi_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} #phi", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, phiAxis}}); + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosPhi_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} #phi", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, phiAxisInner}}); + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegPhi_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} #phi", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, phiAxisInner}}); } // MCH-MID tracks with MCH acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); @@ -1739,8 +1739,8 @@ struct muonQa { float dcaXY = std::sqrt(fgValues.dcaX * fgValues.dcaX + fgValues.dcaY * fgValues.dcaY); fgValues.dcaXY = dcaXY; - mch::TrackParam trackParam = mch::TrackParam(muon.first()); - float p = trackParam.p(); + mch::TrackParam trackParamInner = mch::TrackParam(muon.first()); + float p = trackParamInner.p(); fgValues.pDca = p * dcaXY; } @@ -1806,14 +1806,14 @@ struct muonQa { // double pz = pMCH * cos(M_PI / 2 - atan(mft.tgl())); double pt = std::sqrt(std::pow(px, 2) + std::pow(py, 2)); - double chi2 = muon.chi2(); + double chi2Inner = muon.chi2(); double signed1Pt = endPoint == kToDCA ? muon.signed1Pt() : sign / pt; SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), signed1Pt); std::vector v1{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; SMatrix55 tcovs(v1.begin(), v1.end()); - o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2}; + o2::track::TrackParCovFwd fwdtrack{muon.z(), tpars, tcovs, chi2Inner}; track.setParameters(tpars); track.setZ(fwdtrack.getZ()); track.setCovariances(tcovs); diff --git a/Common/Tools/EventSelectionModule.h b/Common/Tools/EventSelectionModule.h index 9d869f3c25f..f808b70fb85 100644 --- a/Common/Tools/EventSelectionModule.h +++ b/Common/Tools/EventSelectionModule.h @@ -159,6 +159,8 @@ class BcSelectionModule int mTimeFrameStartBorderMargin = 300; // default value int mTimeFrameEndBorderMargin = 4000; // default value std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata + std::string strPassName = ""; // RecoPassName (for data) or AnchorPassName (for MC) from metadata + bool isMC = false; TriggerAliases* aliases = nullptr; EventSelectionParams* par = nullptr; @@ -194,7 +196,9 @@ class BcSelectionModule return; } } + isMC = metadataInfo.isMC(); strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag + strPassName = metadataInfo.get(isMC ? "AnchorPassName" : "RecoPassName"); // add counter histos.add("bcselection/hCounterInvalidBCTimestamp", "", o2::framework::kTH1D, {{1, 0., 1.}}); @@ -223,7 +227,10 @@ class BcSelectionModule // duration of TF in bcs nBCsPerTF = 32; // hard-coded for Run3 MC (no info from ccdb at the moment) } else { - auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); + auto runInfo = (!isMC) ? o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run) + : o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); + LOGP(info, "BcSelectionModule: isMC = {}, NumberOfOrbitsPerTF extracted from AggregatedRunInfo = {}", isMC, runInfo.orbitsPerTF); + // SOR and EOR timestamps sorTimestamp = runInfo.sor; eorTimestamp = runInfo.eor; @@ -274,8 +281,15 @@ class BcSelectionModule // QC info std::map metadata; metadata["run"] = Form("%d", run); + metadata["passName"] = strPassName; + LOGP(info, "accessing pass-specific rct object for run={} and passName={} from ccdb", run, strPassName); ccdb->setFatalWhenNull(0); mapRCT = ccdb->template getSpecific>("RCT/Flags/RunFlags", ts, metadata); + if (mapRCT == nullptr) { + LOGP(info, "pass-specific rct object missing... trying the latest"); + metadata.erase("passName"); + mapRCT = ccdb->template getSpecific>("RCT/Flags/RunFlags", ts, metadata); + } ccdb->setFatalWhenNull(1); if (mapRCT == nullptr) { LOGP(info, "rct object missing... inserting dummy rct flags"); @@ -751,7 +765,10 @@ class EventSelectionModule // extract bc pattern from CCDB for data or anchored MC only if (run != lastRun && run >= run3min) { lastRun = run; - auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); + auto runInfo = (!evselOpts.isMC) ? o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run) + : o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); + LOGP(info, "EventSelectionModule: isMC = {}, NumberOfOrbitsPerTF extracted from AggregatedRunInfo = {}", (bool)evselOpts.isMC, runInfo.orbitsPerTF); + // first bc of the first orbit bcSOR = runInfo.orbitSOR * nBCsPerOrbit; // duration of TF in bcs @@ -786,10 +803,10 @@ class EventSelectionModule diffVzParMean = *parMeans; diffVzParSigma = *parSigmas; LOGP(info, ">>> special treatment for diffVz for light ion run {}", runLightIons); - for (int i = 0; i < 5; i++) - LOGP(info, " mean par {} = {}", i, diffVzParMean[i]); - for (int i = 0; i < 5; i++) - LOGP(info, " sigma par {} = {}", i, diffVzParSigma[i]); + for (int j = 0; j < 5; j++) + LOGP(info, " mean par {} = {}", j, diffVzParMean[j]); + for (int j = 0; j < 5; j++) + LOGP(info, " sigma par {} = {}", j, diffVzParSigma[j]); break; } } @@ -1044,8 +1061,9 @@ class EventSelectionModule } } } - } // end of if TOF-matched vertex - else { // for non-TOF and low-mult vertices, consider nearby nominal bcs + // end of if TOF-matched vertex + } else { + // for non-TOF and low-mult vertices, consider nearby nominal bcs int64_t meanBC = globalBC + TMath::Nint(sumHighPtTime / sumHighPtW / bcNS); int64_t bestGlobalBC = findBestGlobalBC(meanBC, evselOpts.confSigmaBCforHighPtTracks, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ); if (bestGlobalBC > 0) { @@ -1064,7 +1082,7 @@ class EventSelectionModule foundBCindex = bc.globalIndex(); // keep original BC index } } // end of non-TOF matched vertices - // sanitity check: if BC was not found + // sanity check: if BC was not found if (foundBCindex == -1) { foundBCindex = bc.globalIndex(); } @@ -1496,10 +1514,14 @@ class EventSelectionModule // apply int7-like selections bool sel7 = 0; - // TODO apply other cuts for sel8 - // TODO introduce sel1 etc? + // Combination of bits for Run 3 event selection decisions + // TODO apply other cuts for sel8? // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + bool sel8 = false; + if (lastRun < 568873) // pre-2026 data & MC: require all three bits: TVX, TF and ROF border cuts + sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + else // for pp 2026: sel8 without kNoITSROFrameBorder bit, because the cross-ROF reconstruction for ITS will be On (the switch by a runNumber is a temporary solution) + sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder); // fill counters histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); diff --git a/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx b/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx index 85c86e808fd..44d7cbe79de 100644 --- a/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx +++ b/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -383,7 +384,7 @@ Double_t multGlauberNBDFitter::ContinuousNBD(Double_t n, Double_t mu, Double_t k return F; } -void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange, Double_t lHiRange) +void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange, Double_t lHiRange, TH3D* lNpNcEcc, TH2F* lEcc2DPlot, TH3D* lNpNcB, TH2F* lB2DPlot, TH2F* lNancestor2DPlot, Double_t fProbabilityCutoff) { cout << "Calculating , in centrality bins..." << endl; cout << "Range to calculate: " << lLoRange << " to " << lHiRange << endl; @@ -414,17 +415,56 @@ void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCol } // bypass to zero for (int ibin = 0; ibin < fNNpNcPairs; ibin++) { - if (ibin % 2000 == 0) + if (ibin % 200 == 0) cout << "At NpNc pair #" << ibin << " of " << fNNpNcPairs << "..." << endl; Double_t lNAncestors0 = (Int_t)(fNpart[ibin] * ff + fNcoll[ibin] * (1.0 - ff)); Double_t lNAncestors1 = TMath::Floor(fNpart[ibin] * ff + fNcoll[ibin] * (1.0 - ff) + 0.5); Double_t lNAncestors2 = (fNpart[ibin] * ff + fNcoll[ibin] * (1.0 - ff)); + + // define ancestors officially + Double_t lNancestors = lNAncestors0; + if (fAncestorMode == 1) + lNancestors = lNAncestors1; + if (fAncestorMode == 2) + lNancestors = lNAncestors2; + + // eccentricity handling + TH1D* hEccentricity = 0x0; + if (lNpNcEcc) { + // locate the histogram that corresponds to the eccentricity distribution in this NpNc pair + lNpNcEcc->GetXaxis()->SetRange(lNpNcEcc->GetXaxis()->FindBin(fNpart[ibin]), lNpNcEcc->GetXaxis()->FindBin(fNpart[ibin])); + lNpNcEcc->GetYaxis()->SetRange(lNpNcEcc->GetYaxis()->FindBin(fNcoll[ibin]), lNpNcEcc->GetYaxis()->FindBin(fNcoll[ibin])); + hEccentricity = reinterpret_cast(lNpNcEcc->Project3D("z")); + hEccentricity->SetName(Form("hEccentricity_%i", ibin)); + + // normalize into unitary fractions + Double_t eccIntegral = hEccentricity->Integral(1, hEccentricity->GetNbinsX() + 1); + if (eccIntegral > 1e-6) { // no counts + hEccentricity->Scale(1. / eccIntegral); + } else { + hEccentricity->Scale(0.0); + } + } + + // impact parameter handling + TH1D* hImpactParameter = 0x0; + if (lNpNcB) { + // locate the histogram that corresponds to the eccentricity distribution in this NpNc pair + lNpNcB->GetXaxis()->SetRange(lNpNcB->GetXaxis()->FindBin(fNpart[ibin]), lNpNcB->GetXaxis()->FindBin(fNpart[ibin])); + lNpNcB->GetYaxis()->SetRange(lNpNcB->GetYaxis()->FindBin(fNcoll[ibin]), lNpNcB->GetYaxis()->FindBin(fNcoll[ibin])); + hImpactParameter = reinterpret_cast(lNpNcB->Project3D("z")); + hImpactParameter->SetName(Form("hImpactParameter_%i", ibin)); + + // normalize into unitary fractions + Double_t bIntegral = hImpactParameter->Integral(1, hImpactParameter->GetNbinsX() + 1); + if (bIntegral > 1e-6) { // no counts + hImpactParameter->Scale(1. / bIntegral); + } else { + hImpactParameter->Scale(0.0); + } + } + for (Long_t lMultValue = 1; lMultValue < lHiRange; lMultValue++) { - Double_t lNancestors = lNAncestors0; - if (fAncestorMode == 1) - lNancestors = lNAncestors1; - if (fAncestorMode == 2) - lNancestors = lNAncestors2; Double_t lNancestorCount = fContent[ibin]; Double_t lThisMu = (((Double_t)lNancestors)) * fMu; Double_t lThisk = (((Double_t)lNancestors)) * fk; @@ -435,15 +475,36 @@ void multGlauberNBDFitter::CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCol if (lMultValue > 1e-6) lMult = fAncestorMode != 2 ? fNBD->Eval(lMultValue) : ContinuousNBD(lMultValue, lThisMu, lThisk); Double_t lProbability = lNancestorCount * lMult; + + if (lProbability < fProbabilityCutoff) { + continue; // skip if probability of contributing too small + } + Double_t lMultValueToFill = lMultValue; if (hPercentileMap) lMultValueToFill = hPercentileMap->GetBinContent(hPercentileMap->FindBin(lMultValue)); lNPartProf->Fill(lMultValueToFill, fNpart[ibin], lProbability); lNCollProf->Fill(lMultValueToFill, fNcoll[ibin], lProbability); + if (lNancestor2DPlot) { + // fill cross-check histogram with lNancestorCount at lNancestors value + lNancestor2DPlot->Fill(lMultValueToFill, lNancestors, lProbability); + } if (lNPart2DPlot) lNPart2DPlot->Fill(lMultValueToFill, fNpart[ibin], lProbability); if (lNColl2DPlot) lNColl2DPlot->Fill(lMultValueToFill, fNcoll[ibin], lProbability); + if (lNpNcEcc) { + // collapse the entire eccentricity distribution for this combo + for (int ib = 1; ib < hEccentricity->GetNbinsX() + 1; ib++) { + lEcc2DPlot->Fill(lMultValueToFill, hEccentricity->GetBinCenter(ib), lProbability * hEccentricity->GetBinContent(ib)); + } + } + if (lNpNcB) { + // collapse the entire impact parameter distribution for this combo + for (int ib = 1; ib < hImpactParameter->GetNbinsX() + 1; ib++) { + lB2DPlot->Fill(lMultValueToFill, hImpactParameter->GetBinCenter(ib), lProbability * hImpactParameter->GetBinContent(ib)); + } + } } } } diff --git a/Common/Tools/Multiplicity/multGlauberNBDFitter.h b/Common/Tools/Multiplicity/multGlauberNBDFitter.h index 218caf43fc3..598ef312ce9 100644 --- a/Common/Tools/Multiplicity/multGlauberNBDFitter.h +++ b/Common/Tools/Multiplicity/multGlauberNBDFitter.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -77,7 +78,8 @@ class multGlauberNBDFitter : public TNamed Double_t ContinuousNBD(Double_t n, Double_t mu, Double_t k); // For estimating Npart, Ncoll in multiplicity bins - void CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange = -1, Double_t lHiRange = -1); + // also viable: eccentricity, impact parameter, ancestor cross-check plot + void CalculateAvNpNc(TProfile* lNPartProf, TProfile* lNCollProf, TH2F* lNPart2DPlot, TH2F* lNColl2DPlot, TH1F* hPercentileMap, Double_t lLoRange = -1, Double_t lHiRange = -1, TH3D* lNpNcEcc = 0x0, TH2F* lEcc2DPlot = 0x0, TH3D* lNpNcB = 0x0, TH2F* lB2DPlot = 0x0, TH2F* lNancestor2DPlot = 0x0, Double_t fProbabilityCutoff = -1); // void Print(Option_t *option="") const; diff --git a/Common/Tools/PID/pidTPCModule.h b/Common/Tools/PID/pidTPCModule.h index 721fd86f826..efe9dc56ded 100644 --- a/Common/Tools/PID/pidTPCModule.h +++ b/Common/Tools/PID/pidTPCModule.h @@ -189,8 +189,8 @@ typedef struct Str_dEdx_correction { for (int i = 0; i < fMatrix.GetNrows(); i++) { for (int j = 0; j < fMatrix.GetNcols(); j++) { double param = fMatrix(i, j); - double value1 = i > static_cast(vec1.size()) ? 0 : vec1[i]; - double value2 = j > static_cast(vec2.size()) ? 0 : vec2[j]; + double value1 = i >= static_cast(vec1.size()) ? 0 : vec1[i]; + double value2 = j >= static_cast(vec2.size()) ? 0 : vec2[j]; result += param * value1 * value2; } } @@ -201,19 +201,14 @@ typedef struct Str_dEdx_correction { class pidTPCModule { public: - pidTPCModule() - { - // constructor - } o2::aod::pid::pidTPCConfigurables pidTPCopts; // TPC PID Response - o2::pid::tpc::Response* response; + o2::pid::tpc::Response* response{nullptr}; // Network correction for TPC PID response ml::OnnxModel network; std::map metadata; - std::map nullmetadata; std::map headers; std::vector speciesNetworkFlags = std::vector(9); std::string networkVersion; @@ -230,20 +225,20 @@ class pidTPCModule Str_dEdx_correction str_dedx_correction; //__________________________________________________ - template - void init(TCCDB& ccdb, TCCDBApi& ccdbApi, TContext& context, TpidTPCOpts const& external_pidtpcopts, TMetadataInfo const& metadataInfo) + template + void init(TCCDB& ccdb, TContext& context, TpidTPCOpts const& external_pidtpcopts, TMetadataInfo const& metadataInfo) { // read in configurations from the task where it's used pidTPCopts = external_pidtpcopts; if (pidTPCopts.useCorrecteddEdx.value) { - LOGF(info, "***************************************************"); - LOGF(info, " WARNING: YOU HAVE SWITCHED ON 'corrected dEdx!"); - LOGF(info, " This mode is still in development and it is meant"); - LOGF(info, " ONLY FOR EXPERTS at this time. Please switch "); - LOGF(info, " this option off UNLESS you are absolutely SURE"); - LOGF(info, " of what you're doing! You've been warned!"); - LOGF(info, "***************************************************"); + LOGF(warning, "***************************************************"); + LOGF(warning, " WARNING: YOU HAVE SWITCHED ON 'corrected dEdx!"); + LOGF(warning, " This mode is still in development and it is meant"); + LOGF(warning, " ONLY FOR EXPERTS at this time. Please switch "); + LOGF(warning, " this option off UNLESS you are absolutely SURE"); + LOGF(warning, " of what you're doing! You've been warned!"); + LOGF(warning, "***************************************************"); } if (pidTPCopts.skipTPCOnly.value == -1) { @@ -262,7 +257,7 @@ class pidTPCModule pidTPCopts.skipTPCOnly.value = 1; // loop over devices in this execution - auto& workflows = context.services().template get(); + auto const& workflows = context.services().template get(); for (o2::framework::DeviceSpec const& device : workflows.devices) { // Look for propagation service if (device.name.compare("propagation-service") == 0) { @@ -373,17 +368,15 @@ class pidTPCModule if (time != 0) { LOGP(info, "Initialising TPC PID response for fixed timestamp {} and reco pass {}:", time, pidTPCopts.recoPass.value); ccdb->setTimestamp(time); - response = ccdb->template getSpecific(path, time, metadata); - headers = ccdbApi.retrieveHeaders(path, metadata, time); + response = ccdb->template getSpecific(path, time, metadata, &headers); if (!response) { LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); - response = ccdb->template getForTimeStamp(path, time); - headers = ccdbApi.retrieveHeaders(path, metadata, time); - networkVersion = headers["NN-Version"]; + response = ccdb->template getForTimeStamp(path, time, &headers); if (!response) { LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); } } + networkVersion = headers["NN-Version"]; LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << time << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; metadata["RecoPassName"] = headers["RecoPassName"]; // Force pass number for NN request to match retrieved BB o2::parameters::GRPLHCIFData* grpo = ccdb->template getForTimeStamp(pidTPCopts.cfgPathGrpLhcIf.value, time); @@ -411,8 +404,7 @@ class pidTPCModule if (pidTPCopts.ccdbTimestamp > 0) { /// Fetching network for specific timestamp LOG(info) << "Fetching network for timestamp: " << pidTPCopts.ccdbTimestamp.value; - bool retrieveSuccess = ccdbApi.retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, pidTPCopts.ccdbTimestamp.value, false, pidTPCopts.networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(pidTPCopts.networkPathCCDB.value, metadata, pidTPCopts.ccdbTimestamp.value); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, pidTPCopts.ccdbTimestamp.value, false, pidTPCopts.networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(pidTPCopts.networkPathLocally.value, pidTPCopts.enableNetworkOptimizations.value, pidTPCopts.networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); @@ -443,8 +435,8 @@ class pidTPCModule } // end init //__________________________________________________ - template - std::vector createNetworkPrediction(TCCDB& ccdb, TCCDBApi& ccdbApi, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) + template + std::vector createNetworkPrediction(TCCDB& ccdb, soa::Join const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) { std::vector network_prediction; @@ -459,13 +451,11 @@ class pidTPCModule } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), pidTPCopts.recoPass.value); } - response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata, &headers); networkVersion = headers["NN-Version"]; if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, nullmetadata, bc.timestamp()); - response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp()); + response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } @@ -489,14 +479,13 @@ class pidTPCModule if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); - bool retrieveSuccess = ccdbApi.retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, bc.timestamp(), false, pidTPCopts.networkPathLocally.value); - headers = ccdbApi.retrieveHeaders(pidTPCopts.networkPathCCDB.value, metadata, bc.timestamp()); + bool retrieveSuccess = ccdb->getCCDBAccessor().retrieveBlob(pidTPCopts.networkPathCCDB.value, ".", metadata, bc.timestamp(), false, pidTPCopts.networkPathLocally.value, "", "", &headers); networkVersion = headers["NN-Version"]; if (retrieveSuccess) { network.initModel(pidTPCopts.networkPathLocally.value, pidTPCopts.enableNetworkOptimizations.value, pidTPCopts.networkSetNumThreads.value, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); std::vector dummyInput(network.getNumInputNodes(), 1.); network.evalModel(dummyInput); - LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number{}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); + LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, NN-Version number {}", headers["LPMProductionTag"], headers["RecoPassName"], headers["NN-Version"]); } else { LOG(fatal) << "No valid NN object found matching retrieved Bethe-Bloch parametrisation for pass " << metadata["RecoPassName"] << ". Please ensure that the requested pass has dedicated NN corrections available"; } @@ -542,9 +531,11 @@ class pidTPCModule static constexpr int NParticleTypes = 9; constexpr int ExpectedInputDimensionsNNV2 = 7; constexpr int ExpectedInputDimensionsNNV3 = 8; + constexpr int ExpectedInputDimensionsNNV4 = 9; constexpr auto NetworkVersionV2 = "2"; constexpr auto NetworkVersionV3 = "3"; - for (int i = 0; i < NParticleTypes; i++) { // Loop over particle number for which network correction is used + constexpr auto NetworkVersionV4 = "4"; + for (int j = 0; j < NParticleTypes; j++) { // Loop over particle number for which network correction is used for (auto const& trk : tracks) { if (!trk.hasTPC()) { continue; @@ -557,7 +548,7 @@ class pidTPCModule track_properties[counter_track_props] = trk.tpcInnerParam(); track_properties[counter_track_props + 1] = trk.tgl(); track_properties[counter_track_props + 2] = trk.signed1Pt(); - track_properties[counter_track_props + 3] = o2::track::pid_constants::sMasses[i]; + track_properties[counter_track_props + 3] = o2::track::pid_constants::sMasses[j]; track_properties[counter_track_props + 4] = trk.has_collision() ? mults[trk.collisionId()] / 11000. : 1.; track_properties[counter_track_props + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); if (input_dimensions == ExpectedInputDimensionsNNV2 && networkVersion == NetworkVersionV2) { @@ -580,6 +571,25 @@ class pidTPCModule } } } + + if (input_dimensions == ExpectedInputDimensionsNNV4 && networkVersion == NetworkVersionV4) { + track_properties[counter_track_props + 6] = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + if (trk.has_collision()) { + if (collsys == CollisionSystemType::kCollSyspp) { + track_properties[counter_track_props + 7] = hadronicRateForCollision[trk.collisionId()] / 1500.; + } else { + track_properties[counter_track_props + 7] = hadronicRateForCollision[trk.collisionId()] / 50.; + } + } else { + // asign Hadronic Rate at beginning of run if track does not belong to a collision + if (collsys == CollisionSystemType::kCollSyspp) { + track_properties[counter_track_props + 7] = hadronicRateBegin / 1500.; + } else { + track_properties[counter_track_props + 7] = hadronicRateBegin / 50.; + } + } + track_properties[counter_track_props + 8] = std::fmod(std::fmod(trk.phi(), 2 * M_PI) + 2 * M_PI, M_PI / 9.0); + } counter_track_props += input_dimensions; } @@ -587,9 +597,9 @@ class pidTPCModule float* output_network = network.evalModel(track_properties); auto stop_network_eval = std::chrono::high_resolution_clock::now(); duration_network += std::chrono::duration>(stop_network_eval - start_network_eval).count(); - for (uint64_t i = 0; i < prediction_size; i += output_dimensions) { - for (int j = 0; j < output_dimensions; j++) { - network_prediction[i + j + prediction_size * loop_counter] = output_network[i + j]; + for (uint64_t k = 0; k < prediction_size; k += output_dimensions) { + for (int l = 0; l < output_dimensions; l++) { + network_prediction[k + l + prediction_size * loop_counter] = output_network[k + l]; } } @@ -660,7 +670,7 @@ class pidTPCModule nSigma = (tpcSignal / expSignal - network_prediction[NumOutputNodesAsymmetricSigma * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[NumOutputNodesAsymmetricSigma * (count_tracks + tracksForNet_size * pid)] - network_prediction[NumOutputNodesAsymmetricSigma * (count_tracks + tracksForNet_size * pid) + 2]); } } else { - LOGF(fatal, "Network output-dimensions incompatible!"); + LOGF(fatal, "Network output dimensions incompatible!"); } } else { nSigma = response->GetNumberOfSigmaMCTunedAtMultiplicity(multTPC, trk, pid, tpcSignal); @@ -672,8 +682,8 @@ class pidTPCModule }; //__________________________________________________ - template - void process(TCCDB& ccdb, TCCDBApi& ccdbApi, TBCs const& bcs, soa::Join const& cols, TTracks const& tracks, TTracksQA const& tracksQA, TProducts& products) + template + void process(TCCDB& ccdb, TBCs const& bcs, soa::Join const& cols, TTracks const& tracks, TTracksQA const& tracksQA, TProducts& products) { if (tracks.size() == 0) { return; // empty protection @@ -736,7 +746,7 @@ class pidTPCModule std::vector network_prediction; if (pidTPCopts.useNetworkCorrection) { - network_prediction = createNetworkPrediction(ccdb, ccdbApi, cols, pidmults, tracks, bcs, tracksForNet_size); + network_prediction = createNetworkPrediction(ccdb, cols, pidmults, tracks, bcs, tracksForNet_size); } uint64_t count_tracks = 0; @@ -866,12 +876,10 @@ class pidTPCModule } else { LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), pidTPCopts.recoPass.value); } - response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, metadata, bc.timestamp()); + response = ccdb->template getSpecific(pidTPCopts.ccdbPath.value, bc.timestamp(), metadata, &headers); if (!response) { LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); - response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp()); - headers = ccdbApi.retrieveHeaders(pidTPCopts.ccdbPath.value, nullmetadata, bc.timestamp()); + response = ccdb->template getForTimeStamp(pidTPCopts.ccdbPath.value, bc.timestamp(), &headers); if (!response) { LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); } diff --git a/Common/Tools/TrackTuner.h b/Common/Tools/TrackTuner.h index 4eef7d6d434..01ca6930d89 100644 --- a/Common/Tools/TrackTuner.h +++ b/Common/Tools/TrackTuner.h @@ -189,6 +189,10 @@ struct TrackTuner : o2::framework::ConfigurableGroup { LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 564356 <= runNumber && runNumber <= 564445 +++"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ [CASE 5]: OO, 5.36 TeV 2025, period LHC25af: CCDB path Users/m/mfaggin/test/inputsTrackTuner/OO/LHC25af +++"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 564468 <= runNumber && runNumber <= 564472 +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ [CASE 6]: pp, 5.36 TeV 2024, period LHC24ap: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_positive +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 559348 <= runNumber && runNumber <= 559387 +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ [CASE 7]: pp, 5.36 TeV 2024, period LHC24aq: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_negative +++"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++ Run list: 559408 <= runNumber && runNumber <= 559456 +++"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; LOG(info) << ""; @@ -234,6 +238,22 @@ struct TrackTuner : o2::framework::ConfigurableGroup { pathInputFile = "Users/m/mfaggin/test/inputsTrackTuner/OO/LHC25af"; LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: >>> OO, 5.36 TeV 2025, period LHC25af: CCDB path " << pathInputFile; LOG(info) << " >>> Run list: 564468 <= runNumber && runNumber <= 564472"; + } else if (559348 <= runNumber && runNumber <= 559387) { + /// + /// [CASE 6]: pp, 5.36 TeV 2024, period LHC24ap: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_positive + /// Run list: 559348 <= runNumber && runNumber <= 559387 + /// + pathInputFile = "Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_positive"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: >>> pp, 5.36 TeV 2024, period LHC24ap: CCDB path " << pathInputFile; + LOG(info) << " >>> Run list: 559348 <= runNumber && runNumber <= 559387"; + } else if (559408 <= runNumber && runNumber <= 559456) { + /// + /// [CASE 7]: pp, 5.36 TeV 2024, period LHC24aq: CCDB path Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_negative + /// Run list: 559408 <= runNumber && runNumber <= 559456 + /// + pathInputFile = "Users/m/mfaggin/test/inputsTrackTuner/pp2024/ppRef/polarity_negative"; + LOG(info) << "[TrackTuner::getPathInputFileAutomaticFromCCDB]: >>> pp, 5.36 TeV 2024, period LHC24aq: CCDB path " << pathInputFile; + LOG(info) << " >>> Run list: 559408 <= runNumber && runNumber <= 559456"; } else { LOG(fatal) << "runNumber " << runNumber << " not supported for the autodetection. Please switch to manual configuration of the TrackTuner object. Aborting..."; } @@ -735,19 +755,24 @@ struct TrackTuner : o2::framework::ConfigurableGroup { dcaZResMC = evalGraph(ptMC, grDcaZResVsPtPionMC[phiBin].get()); dcaZResData = evalGraph(ptMC, grDcaZResVsPtPionData[phiBin].get()); - // For Q/Pt corrections, files on CCDB will be used if both qOverPtMC and qOverPtData are null + // Local Q/Pt resolution: either the constant configurable value, or evaluated per-track from graphs + double smearQOverPtMC = qOverPtMC; + double smearQOverPtData = qOverPtData; if (updateCurvature || updateCurvatureIU) { - if ((qOverPtMC < 0) || (qOverPtData < 0)) { - if (debugInfo) { - LOG(info) << "### q/pt smearing: qOverPtMC=" << qOverPtMC << ", qOverPtData=" << qOverPtData << ". One of them is negative. Retrieving then values from graphs from input .root file"; - } + if ((smearQOverPtMC < 0) || (smearQOverPtData < 0)) { /// check that input graphs for q/pt smearing are correctly retrieved if (!grOneOverPtPionData.get() || !grOneOverPtPionMC.get()) { LOG(fatal) << "### q/pt smearing: input graphs not correctly retrieved. Aborting."; } - qOverPtMC = std::max(0.0, evalGraph(ptMC, grOneOverPtPionMC.get())); - qOverPtData = std::max(0.0, evalGraph(ptMC, grOneOverPtPionData.get())); - } // qOverPtMC, qOverPtData block ends here + smearQOverPtMC = std::max(0.0, evalGraph(ptMC, grOneOverPtPionMC.get())); + smearQOverPtData = std::max(0.0, evalGraph(ptMC, grOneOverPtPionData.get())); + if (debugInfo) { + LOG(info) << "### q/pt graph-based smearing: pT=" << ptMC + << " sigma(1/pT)_MC=" << smearQOverPtMC + << " sigma(1/pT)_Data=" << smearQOverPtData + << " ratio(Data/MC)=" << (smearQOverPtMC > 0. ? smearQOverPtData / smearQOverPtMC : -1.); + } + } // smearQOverPtMC, smearQOverPtData block ends here } // updateCurvature, updateCurvatureIU block ends here if (updateTrackDCAs) { @@ -816,7 +841,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup { // double dpt1o =pt1o-pt1mc; deltaQpt = trackParQPtMCRec - trackParQPtMC; // double dpt1n =dpt1o *(spt1o >0. ? (spt1n /spt1o ) : 1.); - deltaQptTuned = deltaQpt * (qOverPtMC > 0. ? (qOverPtData / qOverPtMC) : 1.); + deltaQptTuned = deltaQpt * (smearQOverPtMC > 0. ? (smearQOverPtData / smearQOverPtMC) : 1.); // double pt1n = pt1mc+dpt1n; trackParQPtTuned = trackParQPtMC + deltaQptTuned; trackParCov.setQ2Pt(trackParQPtTuned); @@ -824,36 +849,36 @@ struct TrackTuner : o2::framework::ConfigurableGroup { // updating track cov matrix elements for 1/Pt at innermost update point // if(sd0rpo>0. && spt1o>0.)covar[10]*=(sd0rpn/sd0rpo)*(spt1n/spt1o);//ypt sigma1PtY = trackParCov.getSigma1PtY(); - if (dcaXYResMC > 0. && qOverPtMC > 0.) { - sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (qOverPtData / qOverPtMC)); + if (dcaXYResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtY, 10); } // if(sd0zo>0. && spt1o>0.) covar[11]*=(sd0zn/sd0zo)*(spt1n/spt1o);//zpt sigma1PtZ = trackParCov.getSigma1PtZ(); - if (dcaZResMC > 0. && qOverPtMC > 0.) { - sigma1PtZ *= ((dcaZResData / dcaZResMC) * (qOverPtData / qOverPtMC)); + if (dcaZResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtZ *= ((dcaZResData / dcaZResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtZ, 11); } // if(spt1o>0.) covar[12]*=(spt1n/spt1o);//sinPhipt sigma1PtSnp = trackParCov.getSigma1PtSnp(); - if (qOverPtMC > 0.) { - sigma1PtSnp *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtSnp *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtSnp, 12); } // if(spt1o>0.) covar[13]*=(spt1n/spt1o);//tanTpt sigma1PtTgl = trackParCov.getSigma1PtTgl(); - if (qOverPtMC > 0.) { - sigma1PtTgl *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtTgl *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtTgl, 13); } // if(spt1o>0.) covar[14]*=(spt1n/spt1o)*(spt1n/spt1o);//ptpt sigma1Pt2 = trackParCov.getSigma1Pt2(); - if (qOverPtMC > 0.) { - sigma1Pt2 *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1Pt2 *= (smearQOverPtData / smearQOverPtMC) * (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1Pt2, 14); } } // updateCurvatureIU block ends here @@ -949,7 +974,7 @@ struct TrackTuner : o2::framework::ConfigurableGroup { } deltaQpt = trackParQPtMCRec - trackParQPtMC; // double dpt1n =dpt1o *(spt1o >0. ? (spt1n /spt1o ) : 1.); - deltaQptTuned = deltaQpt * (qOverPtMC > 0. ? (qOverPtData / qOverPtMC) : 1.); + deltaQptTuned = deltaQpt * (smearQOverPtMC > 0. ? (smearQOverPtData / smearQOverPtMC) : 1.); // double pt1n = pt1mc+dpt1n; trackParQPtTuned = trackParQPtMC + deltaQptTuned; trackParCov.setQ2Pt(trackParQPtTuned); @@ -1010,36 +1035,36 @@ struct TrackTuner : o2::framework::ConfigurableGroup { if ((updateCurvature) && (!updateCurvatureIU)) { // if(sd0rpo>0. && spt1o>0.)covar[10]*=(sd0rpn/sd0rpo)*(spt1n/spt1o);//ypt sigma1PtY = trackParCov.getSigma1PtY(); - if (dcaXYResMC > 0. && qOverPtMC > 0.) { - sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (qOverPtData / qOverPtMC)); + if (dcaXYResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtY *= ((dcaXYResData / dcaXYResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtY, 10); } // if(sd0zo>0. && spt1o>0.) covar[11]*=(sd0zn/sd0zo)*(spt1n/spt1o);//zpt sigma1PtZ = trackParCov.getSigma1PtZ(); - if (dcaZResMC > 0. && qOverPtMC > 0.) { - sigma1PtZ *= ((dcaZResData / dcaZResMC) * (qOverPtData / qOverPtMC)); + if (dcaZResMC > 0. && smearQOverPtMC > 0.) { + sigma1PtZ *= ((dcaZResData / dcaZResMC) * (smearQOverPtData / smearQOverPtMC)); trackParCov.setCov(sigma1PtZ, 11); } // if(spt1o>0.) covar[12]*=(spt1n/spt1o);//sinPhipt sigma1PtSnp = trackParCov.getSigma1PtSnp(); - if (qOverPtMC > 0.) { - sigma1PtSnp *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtSnp *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtSnp, 12); } // if(spt1o>0.) covar[13]*=(spt1n/spt1o);//tanTpt sigma1PtTgl = trackParCov.getSigma1PtTgl(); - if (qOverPtMC > 0.) { - sigma1PtTgl *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1PtTgl *= (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1PtTgl, 13); } // if(spt1o>0.) covar[14]*=(spt1n/spt1o)*(spt1n/spt1o);//ptpt sigma1Pt2 = trackParCov.getSigma1Pt2(); - if (qOverPtMC > 0.) { - sigma1Pt2 *= (qOverPtData / qOverPtMC); + if (smearQOverPtMC > 0.) { + sigma1Pt2 *= (smearQOverPtData / smearQOverPtMC) * (smearQOverPtData / smearQOverPtMC); trackParCov.setCov(sigma1Pt2, 14); } } // ---> track cov matrix elements for 1/Pt ends here diff --git a/DPG/Tasks/AOTEvent/dEdxVsOccupancyWithTrackQAinfo.cxx b/DPG/Tasks/AOTEvent/dEdxVsOccupancyWithTrackQAinfo.cxx index c87fd48bc99..444406a6c42 100644 --- a/DPG/Tasks/AOTEvent/dEdxVsOccupancyWithTrackQAinfo.cxx +++ b/DPG/Tasks/AOTEvent/dEdxVsOccupancyWithTrackQAinfo.cxx @@ -14,30 +14,29 @@ /// /// \author Igor Altsybeev -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/HistogramRegistry.h" -#include "CommonDataFormat/BunchFilling.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "TH1F.h" -#include "TH2F.h" -#include "TH3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx index 3fc293c7e84..a79bd82a5c3 100644 --- a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx +++ b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx @@ -16,27 +16,32 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/BunchFilling.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "TH1F.h" -#include "TH2F.h" -#include "TH3.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include #include #include diff --git a/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx b/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx index e87ca9c73f3..b85b1d3b42c 100644 --- a/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx +++ b/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx @@ -15,30 +15,28 @@ /// \author Igor Altsybeev #include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -// #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/BunchFilling.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsFT0/RecPoints.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "TH1F.h" -#include "TH2F.h" -#include "TH3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include diff --git a/DPG/Tasks/AOTEvent/lumiQa.cxx b/DPG/Tasks/AOTEvent/lumiQa.cxx index 254e58f0b67..f03419fff52 100644 --- a/DPG/Tasks/AOTEvent/lumiQa.cxx +++ b/DPG/Tasks/AOTEvent/lumiQa.cxx @@ -9,24 +9,44 @@ // 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 "Framework/HistogramRegistry.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsFT0/Digit.h" -#include "TList.h" -#include "TH1.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; using BCsRun3 = soa::Join; struct LumiQaTask { + Configurable confTimeBinWidthInSec{"TimeBinWidthInSec", 60., "Width of time bins in seconds"}; // o2-linter: disable=name/configurable (temporary fix) Service ccdb; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; int lastRunNumber = -1; + double maxSec = 1; + double minSec = 0; + TH1* hCalibV0A = nullptr; TH1* hCalibT0C = nullptr; static const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; std::bitset bcPatternB; @@ -40,11 +60,14 @@ struct LumiQaTask { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); + const AxisSpec axisMultZNA{2000, 0., 400., "ZNA multiplicity"}; const AxisSpec axisMultZNC{2000, 0., 400., "ZNC multiplicity"}; + const AxisSpec axisMultV0A{1000, 0., 200000., "V0A multiplicity"}; const AxisSpec axisMultT0M{1000, 0., 270000., "T0M multiplicity"}; const AxisSpec axisMultT0A{1000, 0., 200000., "T0A multiplicity"}; const AxisSpec axisMultT0C{1000, 0., 70000., "T0C multiplicity"}; + const AxisSpec axisCentV0A{100, 0., 100., "V0A centrality"}; const AxisSpec axisCentT0C{100, 0., 100., "T0C centrality"}; const AxisSpec axisTime{700, -35., 35., "time (ns)"}; const AxisSpec axisMultChannelT0A{5000, 0., 5000., "T0A channel multiplicity"}; @@ -56,10 +79,24 @@ struct LumiQaTask { histos.add("hMultZNA", "", kTH1F, {axisMultZNA}); histos.add("hMultZNC", "", kTH1F, {axisMultZNC}); + histos.add("hMultV0A", "", kTH1F, {axisMultV0A}); histos.add("hMultT0M", "", kTH1F, {axisMultT0M}); histos.add("hMultT0A", "", kTH1F, {axisMultT0A}); histos.add("hMultT0C", "", kTH1F, {axisMultT0C}); + histos.add("hCentV0A", "", kTH1F, {axisCentV0A}); histos.add("hCentT0C", "", kTH1F, {axisCentT0C}); + + histos.add("hMultV0AselTVXB", "", kTH1F, {axisMultV0A}); + histos.add("hCentV0AselTVXB", "", kTH1F, {axisCentV0A}); + histos.add("hMultVCHselTVXB", "", kTH1F, {axisMultV0A}); + histos.add("hCentVCHselTVXB", "", kTH1F, {axisCentV0A}); + histos.add("hMultV0AselZACTVXB", "", kTH1F, {axisMultV0A}); + histos.add("hCentV0AselZACTVXB", "", kTH1F, {axisCentV0A}); + histos.add("hMultVCHselZACTVXB", "", kTH1F, {axisMultV0A}); + histos.add("hCentVCHselZACTVXB", "", kTH1F, {axisCentV0A}); + + histos.add("hMultT0CselTVXB", "", kTH1F, {axisMultT0C}); + histos.add("hCentT0CselTVXB", "", kTH1F, {axisCentT0C}); histos.add("hMultT0MselTSC", "", kTH1F, {axisMultT0M}); histos.add("hMultT0MselTCE", "", kTH1F, {axisMultT0M}); histos.add("hMultT0CselTCE", "", kTH1F, {axisMultT0C}); @@ -80,15 +117,29 @@ struct LumiQaTask { histos.add("hTimeZNAselC", "", kTH1F, {axisTime}); histos.add("hTimeZNCselC", "", kTH1F, {axisTime}); - histos.add("hCounterTCE", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZNA", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZNC", "", kTH1D, {{1, 0., 1.}}); - histos.add("hCounterZEM", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterTCEselB", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNAselB", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNCselB", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZEMselB", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterVCHselB", "", kTH1D, {{1, 0., 1.}}); + + histos.add("hCounterTCEselA", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNAselA", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNCselA", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZEMselA", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterVCHselA", "", kTH1D, {{1, 0., 1.}}); + + histos.add("hCounterTCEselC", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNAselC", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNCselC", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZEMselC", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterVCHselC", "", kTH1D, {{1, 0., 1.}}); + histos.add("hMultT0AperChannel", "", kTH2D, {axisMultChannelT0A, axisChannelsT0A}); histos.add("hMultT0CperChannel", "", kTH2D, {axisMultChannelT0C, axisChannelsT0C}); } - void process(BCsRun3 const& bcs, aod::Zdcs const&, aod::FT0s const&) + void process(BCsRun3 const& bcs, aod::Zdcs const&, aod::FT0s const&, aod::FV0As const&) { int runNumber = bcs.iteratorAt(0).runNumber(); const char* srun = Form("%d", runNumber); @@ -111,66 +162,197 @@ struct LumiQaTask { return; } + hCalibV0A = reinterpret_cast(callst->FindObject("hCalibZeqFV0")); + if (hCalibV0A == nullptr) { + LOGF(info, "hCalibZeqFV0 histogram is not available for run=%d at timestamp=%llu", runNumber, ts); + return; + } + hCalibT0C = reinterpret_cast(callst->FindObject("hCalibZeqFT0C")); if (hCalibT0C == nullptr) { LOGF(info, "hCalibZeqFT0C histogram is not available for run=%d at timestamp=%llu", runNumber, ts); return; } + + if (runNumber >= 500000) { + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), runNumber); + auto tsSOR = runInfo.sor; + auto tsEOR = runInfo.eor; + minSec = floor(tsSOR / 1000.); + maxSec = ceil(tsEOR / 1000.); + } + + int nTimeBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec); + double timeInterval = nTimeBins * confTimeBinWidthInSec; + + const AxisSpec axisBCs{nBCsPerOrbit, 0., static_cast(nBCsPerOrbit), ""}; + const AxisSpec axisSeconds{nTimeBins, 0, timeInterval, "seconds"}; + histos.add("hSecondsBcsTCEselB", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNAselB", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNCselB", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZEMselB", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsVCHselB", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsTCEselA", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNAselA", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNCselA", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZEMselA", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsVCHselA", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsTCEselC", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNAselC", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZNCselC", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsZEMselC", "", kTH2D, {axisSeconds, axisBCs}); + histos.add("hSecondsBcsVCHselC", "", kTH2D, {axisSeconds, axisBCs}); } for (const auto& bc : bcs) { + int64_t ts = bc.timestamp(); + auto inputMask = bc.inputMask(); + double secFromSOR = ts / 1000. - minSec; + int bcInOrbit = bc.globalBC() % nBCsPerOrbit; + bool maskB = bcPatternB[bcInOrbit]; + bool maskA = bcPatternA[bcInOrbit]; + bool maskC = bcPatternC[bcInOrbit]; + bool tvxCTP = TESTBIT(inputMask, 2); + bool tscCTP = TESTBIT(inputMask, 3); + bool tceCTP = TESTBIT(inputMask, 4); + bool vchCTP = TESTBIT(inputMask, 9); + bool zemCTP = TESTBIT(inputMask, 24); + bool zncCTP = TESTBIT(inputMask, 25); + + LOGP(debug, "CTP: tvx={} tsc={} tce={} vch={} zem={} znc={}", tvxCTP, tscCTP, tceCTP, vchCTP, zemCTP, zncCTP); + + bool tvx = bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : 0; + bool tsc = bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitSCen) : 0; + bool tce = bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitCen) : 0; + bool vch = bc.has_fv0a() ? TESTBIT(bc.fv0a().triggerMask(), o2::fit::Triggers::bitTrgCharge) : 0; + + float meanTimeZNA = 0.; + float meanTimeZNC = 0.; + bool zna = bc.has_zdc() ? std::fabs(bc.zdc().timeZNA() - meanTimeZNA) < 2 : 0; // ns + bool znc = bc.has_zdc() ? std::fabs(bc.zdc().timeZNC() - meanTimeZNC) < 2 : 0; // ns + bool zem = zna || znc; + bool zac = zna && znc; + + // check if TCE triggers from FT0 mask and CTP are consistent + if (tce != tceCTP) { + LOGP(warning, "TCEfromFT0={} TCEfromCTP={}", tce, tceCTP); + } + if (bc.has_zdc()) { float timeZNA = bc.zdc().timeZNA(); float timeZNC = bc.zdc().timeZNC(); float multZNA = bc.zdc().energyCommonZNA(); float multZNC = bc.zdc().energyCommonZNC(); - histos.fill(HIST("hMultZNA"), multZNA); histos.fill(HIST("hMultZNC"), multZNC); histos.fill(HIST("hTimeZNA"), timeZNA); histos.fill(HIST("hTimeZNC"), timeZNC); - if (bc.has_ft0() && TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex)) { // TVX + if (tvx) { // TVX histos.fill(HIST("hTimeZNAselTVX"), timeZNA); histos.fill(HIST("hTimeZNCselTVX"), timeZNC); } - - if (bcPatternB[bc.globalBC() % nBCsPerOrbit]) { // B-mask + if (maskB) { // B-mask histos.fill(HIST("hTimeZNAselB"), timeZNA); histos.fill(HIST("hTimeZNCselB"), timeZNC); } - if (bcPatternA[bc.globalBC() % nBCsPerOrbit]) { // A-mask + if (maskA) { // A-mask histos.fill(HIST("hTimeZNAselA"), timeZNA); histos.fill(HIST("hTimeZNCselA"), timeZNC); } - if (bcPatternC[bc.globalBC() % nBCsPerOrbit]) { // C-mask + if (maskC) { // C-mask histos.fill(HIST("hTimeZNAselC"), timeZNA); histos.fill(HIST("hTimeZNCselC"), timeZNC); } - double meanTimeZNA = 0; - double meanTimeZNC = 0; - if (runNumber == 544795) { - meanTimeZNA = 0.49; - meanTimeZNC = -5.19; - } else if (runNumber == 544911) { - meanTimeZNA = -1.44; - meanTimeZNC = -11.39; + // B-mask + if (zna && maskB) { + histos.get(HIST("hCounterZNAselB"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNAselB"), secFromSOR, bcInOrbit); + } + if (znc && maskB) { + histos.get(HIST("hCounterZNCselB"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNCselB"), secFromSOR, bcInOrbit); + } + if (zem && maskB) { + histos.get(HIST("hCounterZEMselB"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZEMselB"), secFromSOR, bcInOrbit); + } + + // A-mask + if (zna && maskA) { + histos.get(HIST("hCounterZNAselA"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNAselA"), secFromSOR, bcInOrbit); + } + if (znc && maskA) { + histos.get(HIST("hCounterZNCselA"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNCselA"), secFromSOR, bcInOrbit); + } + if (zem && maskA) { + histos.get(HIST("hCounterZEMselA"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZEMselA"), secFromSOR, bcInOrbit); } - if (fabs(timeZNA - meanTimeZNA) < 2) { - histos.get(HIST("hCounterZNA"))->Fill(srun, 1); + // C-mask + if (zna && maskC) { + histos.get(HIST("hCounterZNAselC"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNAselC"), secFromSOR, bcInOrbit); } - if (fabs(timeZNC - meanTimeZNC) < 2) { - histos.get(HIST("hCounterZNC"))->Fill(srun, 1); + if (znc && maskC) { + histos.get(HIST("hCounterZNCselC"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZNCselC"), secFromSOR, bcInOrbit); } - if (fabs(timeZNA - meanTimeZNA) < 2 || fabs(timeZNC - meanTimeZNC) < 2) { - histos.get(HIST("hCounterZEM"))->Fill(srun, 1); + if (zem && maskC) { + histos.get(HIST("hCounterZEMselC"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsZEMselC"), secFromSOR, bcInOrbit); + } + } + + if (bc.has_fv0a()) { + float multV0A = 0.; + for (auto mult : bc.fv0a().amplitude()) { + multV0A += mult; + } + float centV0A = hCalibV0A->GetBinContent(hCalibV0A->FindFixBin(multV0A)); + histos.fill(HIST("hMultV0A"), multV0A); + histos.fill(HIST("hCentV0A"), centV0A); + + if (tvx && maskB) { + histos.fill(HIST("hMultV0AselTVXB"), multV0A); + histos.fill(HIST("hCentV0AselTVXB"), centV0A); + } + + if (tvx && maskB && vch) { + histos.fill(HIST("hMultVCHselTVXB"), multV0A); + histos.fill(HIST("hCentVCHselTVXB"), centV0A); + histos.get(HIST("hCounterVCHselB"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsVCHselB"), secFromSOR, bcInOrbit); + } + + if (tvx && maskA && vch) { + histos.get(HIST("hCounterVCHselA"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsVCHselA"), secFromSOR, bcInOrbit); + } + + if (tvx && maskC && vch) { + histos.get(HIST("hCounterVCHselC"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsVCHselC"), secFromSOR, bcInOrbit); + } + + if (tvx && maskB && zac) { + histos.fill(HIST("hMultV0AselZACTVXB"), multV0A); + histos.fill(HIST("hCentV0AselZACTVXB"), centV0A); + } + + if (tvx && maskB && vch && zac) { + histos.fill(HIST("hMultVCHselZACTVXB"), multV0A); + histos.fill(HIST("hCentVCHselZACTVXB"), centV0A); } } if (!bc.has_ft0()) { continue; } + for (unsigned int ic = 0; ic < bc.ft0().amplitudeA().size(); ic++) { histos.fill(HIST("hMultT0AperChannel"), bc.ft0().amplitudeA()[ic], bc.ft0().channelA()[ic]); } @@ -187,32 +369,34 @@ struct LumiQaTask { histos.fill(HIST("hMultT0C"), multT0C); histos.fill(HIST("hCentT0C"), centT0C); - if (TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitSCen)) { // TSC - histos.fill(HIST("hMultT0MselTSC"), multT0M); + if (tvx && maskB) { + histos.fill(HIST("hMultT0CselTVXB"), multT0C); + histos.fill(HIST("hCentT0CselTVXB"), centT0C); } - if (!TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitCen)) { // TCE - continue; + if (tsc) { + histos.fill(HIST("hMultT0MselTSC"), multT0M); } - histos.fill(HIST("hMultT0MselTCE"), multT0M); - histos.fill(HIST("hMultT0CselTCE"), multT0C); - histos.fill(HIST("hCentT0CselTCE"), centT0C); - if (!TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex)) { // TVX - continue; + if (tce) { + histos.fill(HIST("hMultT0MselTCE"), multT0M); + histos.fill(HIST("hMultT0CselTCE"), multT0C); + histos.fill(HIST("hCentT0CselTCE"), centT0C); } - histos.fill(HIST("hMultT0CselTVXTCE"), multT0C); - histos.fill(HIST("hCentT0CselTVXTCE"), centT0C); - if (!bcPatternB[bc.globalBC() % nBCsPerOrbit]) { // B-mask - continue; + if (tce && tvx) { + histos.fill(HIST("hMultT0CselTVXTCE"), multT0C); + histos.fill(HIST("hCentT0CselTVXTCE"), centT0C); } - histos.fill(HIST("hMultT0CselTVXTCEB"), multT0C); - histos.fill(HIST("hCentT0CselTVXTCEB"), centT0C); - histos.get(HIST("hCounterTCE"))->Fill(srun, 1); - } - } + if (tce && tvx && maskB) { + histos.fill(HIST("hMultT0CselTVXTCEB"), multT0C); + histos.fill(HIST("hCentT0CselTVXTCEB"), centT0C); + histos.get(HIST("hCounterTCEselB"))->Fill(srun, 1); + histos.fill(HIST("hSecondsBcsTCEselB"), secFromSOR, bcInOrbit); + } + } // bc loop + } // process }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/DPG/Tasks/AOTEvent/matchingQa.cxx b/DPG/Tasks/AOTEvent/matchingQa.cxx index 3b266f047e9..62bece530f7 100644 --- a/DPG/Tasks/AOTEvent/matchingQa.cxx +++ b/DPG/Tasks/AOTEvent/matchingQa.cxx @@ -9,14 +9,34 @@ // 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 "Framework/HistogramRegistry.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "MetadataHelper.h" +#include "Common/Core/MetadataHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTEvent/rofOccupancyQa.cxx b/DPG/Tasks/AOTEvent/rofOccupancyQa.cxx index cbc8d7d56d1..af9e0697922 100644 --- a/DPG/Tasks/AOTEvent/rofOccupancyQa.cxx +++ b/DPG/Tasks/AOTEvent/rofOccupancyQa.cxx @@ -14,20 +14,27 @@ /// /// \author Igor Altsybeev -#include - -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/EventSelection.h" #include "Common/CCDB/EventSelectionParams.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "Framework/HistogramRegistry.h" -// #include "DataFormatsParameters/GRPLHCIFData.h" -#include "ITSMFTBase/DPLAlpideParam.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/D0CalibTables.h b/DPG/Tasks/AOTTrack/D0CalibTables.h index 33c9efdc2dd..81e16201b63 100644 --- a/DPG/Tasks/AOTTrack/D0CalibTables.h +++ b/DPG/Tasks/AOTTrack/D0CalibTables.h @@ -16,16 +16,14 @@ #ifndef DPG_TASKS_AOTTRACK_D0CALIBTABLES_H_ #define DPG_TASKS_AOTTRACK_D0CALIBTABLES_H_ -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include #include -#include - +#include +#include #include -#include #include #include @@ -444,6 +442,8 @@ DECLARE_SOA_COLUMN(Eta, eta, float); / DECLARE_SOA_COLUMN(Phi, phi, float); //! D0-candidate phi DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! invariant mass (D0 hypothesis) DECLARE_SOA_COLUMN(InvMassD0bar, invMassD0bar, float); //! invariant mass (D0bar hypothesis) +DECLARE_SOA_COLUMN(CosThetaStarD0, cosThetaStarD0, float); //! D0-candidate cost* (Helicity frame, D0 mass hypothesis) +DECLARE_SOA_COLUMN(CosThetaStarD0bar, cosThetaStarD0bar, float); //! D0-candidate cost* (Helicity frame, D0bar mass hypthesis) DECLARE_SOA_COLUMN(DecLength, decLength, uint8_t); //! compressed decay length DECLARE_SOA_COLUMN(DecLengthXY, decLengthXY, uint8_t); //! compressed decay length XY DECLARE_SOA_COLUMN(NormDecLength, normDecLength, uint8_t); //! compressed normalised decay length @@ -472,6 +472,8 @@ DECLARE_SOA_TABLE(D0CalibCands, "AOD", "D0CALIBCAND", hf_calib::Phi, hf_calib::InvMassD0, hf_calib::InvMassD0bar, + hf_calib::CosThetaStarD0, + hf_calib::CosThetaStarD0bar, hf_calib::DecLength, hf_calib::DecLengthXY, hf_calib::NormDecLength, diff --git a/DPG/Tasks/AOTTrack/MonitorFilterBit.cxx b/DPG/Tasks/AOTTrack/MonitorFilterBit.cxx index b8fb6679b1c..648c1258127 100644 --- a/DPG/Tasks/AOTTrack/MonitorFilterBit.cxx +++ b/DPG/Tasks/AOTTrack/MonitorFilterBit.cxx @@ -15,12 +15,29 @@ /// \brief Task performing basic checks on filter-bit selections. /// -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/RecoDecay.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/ASoA.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/Combined/qaPIDWithV0s.cxx b/DPG/Tasks/AOTTrack/PID/Combined/qaPIDWithV0s.cxx index 9b1d4f9c692..8ff792a860b 100644 --- a/DPG/Tasks/AOTTrack/PID/Combined/qaPIDWithV0s.cxx +++ b/DPG/Tasks/AOTTrack/PID/Combined/qaPIDWithV0s.cxx @@ -18,19 +18,21 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidDeuteron.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidDeuteron.cxx index 98ea08f7add..27451cff7e3 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidDeuteron.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidDeuteron.cxx @@ -12,10 +12,17 @@ #include "tableHMPID.h" #include +#include +#include +#include +#include +#include #include #include -#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidQa.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidQa.cxx index 5a1f821cda2..50059151aab 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidQa.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidQa.cxx @@ -11,31 +11,29 @@ #include "tableHMPID.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" - +#include #include -#include #include #include +#include #include -#include +#include +#include +#include #include -#include -#include -#include -#include #include #include +#include #include -#include +#include #include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx index 76267171742..e7cb03e25be 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx +++ b/DPG/Tasks/AOTTrack/PID/HMPID/hmpidTableProducer.cxx @@ -11,33 +11,28 @@ #include "tableHMPID.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" +#include #include -#include #include +#include #include +#include #include -#include +#include +#include +#include #include -#include -#include -#include -#include - -#include +#include #include +#include using namespace o2; using namespace o2::framework; @@ -57,24 +52,28 @@ struct HmpidTableProducer { Produces hmpidAnalysis; - // using TrackCandidates = soa::Join; + // configurable for quality requirements + Configurable requireITS{"requireITS", true, "Require ITS track"}; + Configurable requireTPC{"requireTPC", true, "Require TPC track"}; + Configurable requireTOF{"requireTOF", true, "Require TOF track"}; - using CollisionCandidates = o2::soa::Join; + using CollisionCandidates = o2::soa::Join; using TrackCandidates = soa::Join; - // using CentralityClass = o2::soa::Join; - void init(o2::framework::InitContext&) { // Configure CCDB ccdb->setURL(ccdbConfig.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); histos.add("eventCounter", "eventCounter", kTH1F, {axisEvtCounter}); + histos.add("goodEventCounter", "goodEventCounter", kTH1F, {axisEvtCounter}); + histos.add("eventsHmpid", "eventsWithHmpid", kTH1F, {axisEvtCounter}); } // function to manage ccdb @@ -87,50 +86,75 @@ struct HmpidTableProducer { mCCDBRunNumber = bc.runNumber(); } - void process(soa::Join::iterator const& col, - const aod::HMPIDs& hmpids, - TrackCandidates const&, - aod::BCsWithTimestamps const&) + void processEvent(CollisionCandidates::iterator const& col, + aod::BCsWithTimestamps const&) { histos.fill(HIST("eventCounter"), 0.5); + if (col.sel8()) { + histos.fill(HIST("goodEventCounter"), 0.5); + } + // initialize CCDB for current BC initCCDB(col.bc_as()); + } + PROCESS_SWITCH(HmpidTableProducer, processEvent, "Process event level - collisions", true); - for (const auto& t : hmpids) { + void processHmpid( + aod::HMPIDs const& hmpids, + TrackCandidates const&, + CollisionCandidates const&, + aod::BCsWithTimestamps const&) + { + // --- Static set to track unique collisions with HMPID tracks --- + static std::unordered_set collisionsWithHmpid; - // global tracks associated to hmpid tracks + for (auto const& t : hmpids) { + + // Access the global track associated to the HMPID track const auto& globalTrack = t.track_as(); - if (!globalTrack.isGlobalTrack()) - continue; - if (!globalTrack.hasITS() || !globalTrack.hasTPC() || !globalTrack.hasTOF()) + + if (!globalTrack.has_collision()) continue; - // verify accessible collision - if (!globalTrack.has_collision()) { + // Access the associated collision + const auto& col = globalTrack.collision_as(); + initCCDB(col.bc_as()); + uint32_t collId = col.globalIndex(); + + // --- Track quality selection --- + if ((requireITS && !globalTrack.hasITS()) || + (requireTPC && !globalTrack.hasTPC()) || + (requireTOF && !globalTrack.hasTOF())) { continue; } + // Count collisions with at least one valid HMPID track + if (collisionsWithHmpid.insert(collId).second) { + histos.fill(HIST("eventsHmpid"), 0.5); + } + + float centrality = col.centFV0A(); + float hmpidPhotsCharge2[o2::aod::kDimPhotonsCharge]; for (int i = 0; i < o2::aod::kDimPhotonsCharge; i++) { hmpidPhotsCharge2[i] = t.hmpidPhotsCharge()[i]; } - float centrality = col.centFV0A(); - - /////FILL TABLE - hmpidAnalysis( - t.hmpidSignal(), globalTrack.phi(), globalTrack.eta(), t.hmpidMom(), - globalTrack.p(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), - t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, - t.hmpidClusSize() / 1000000, hmpidPhotsCharge2, globalTrack.eta(), globalTrack.phi(), - globalTrack.px(), globalTrack.py(), globalTrack.pz(), globalTrack.itsNCls(), - globalTrack.tpcNClsFound(), globalTrack.tpcNClsCrossedRows(), globalTrack.tpcChi2NCl(), globalTrack.itsChi2NCl(), - globalTrack.dcaXY(), globalTrack.dcaZ(), globalTrack.tpcNSigmaPi(), globalTrack.tofNSigmaPi(), - globalTrack.tpcNSigmaKa(), globalTrack.tofNSigmaKa(), globalTrack.tpcNSigmaPr(), globalTrack.tofNSigmaPr(), - globalTrack.tpcNSigmaDe(), globalTrack.tofNSigmaDe(), centrality); - } + /////FILL HMPID CUSTOM TABLE + hmpidAnalysis(t.hmpidSignal(), t.hmpidMom(), + globalTrack.p(), t.hmpidXTrack(), t.hmpidYTrack(), t.hmpidXMip(), + t.hmpidYMip(), t.hmpidNPhotons(), t.hmpidQMip(), (t.hmpidClusSize() % 1000000) / 1000, + t.hmpidClusSize() / 1000000, hmpidPhotsCharge2, globalTrack.eta(), globalTrack.phi(), + globalTrack.px(), globalTrack.py(), globalTrack.pz(), globalTrack.itsNCls(), + globalTrack.tpcNClsFound(), globalTrack.tpcNClsCrossedRows(), globalTrack.tpcChi2NCl(), globalTrack.itsChi2NCl(), + globalTrack.dcaXY(), globalTrack.dcaZ(), globalTrack.tpcNSigmaPi(), globalTrack.tofNSigmaPi(), + globalTrack.tpcNSigmaKa(), globalTrack.tofNSigmaKa(), globalTrack.tpcNSigmaPr(), globalTrack.tofNSigmaPr(), + globalTrack.tpcNSigmaDe(), globalTrack.tofNSigmaDe(), centrality); + } // end loop on hmpid table entries } + + PROCESS_SWITCH(HmpidTableProducer, processHmpid, "Process hmpid entries - tracks", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfg) { return WorkflowSpec{adaptAnalysisTask(cfg)}; } diff --git a/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h b/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h index 045282d3e0e..6844da6c519 100644 --- a/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h +++ b/DPG/Tasks/AOTTrack/PID/HMPID/tableHMPID.h @@ -12,8 +12,8 @@ #ifndef DPG_TASKS_AOTTRACK_PID_HMPID_TABLEHMPID_H_ #define DPG_TASKS_AOTTRACK_PID_HMPID_TABLEHMPID_H_ -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" +#include +#include namespace o2::aod { @@ -23,8 +23,6 @@ inline constexpr int kDimPhotonsCharge = 10; namespace variables_table { 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); @@ -60,15 +58,12 @@ DECLARE_SOA_COLUMN(TpcNSigmaPr, tpcNSigmaPr, float); DECLARE_SOA_COLUMN(TofNSigmaPr, tofNSigmaPr, float); DECLARE_SOA_COLUMN(TpcNSigmaDe, tpcNSigmaDe, float); DECLARE_SOA_COLUMN(TofNSigmaDe, tofNSigmaDe, float); - DECLARE_SOA_COLUMN(Centrality, centrality, float); } // namespace variables_table DECLARE_SOA_TABLE(HmpidAnalysis, "AOD", "HMPIDANALYSIS", variables_table::ChAngle, - variables_table::Phi, - variables_table::Eta, variables_table::MomentumHmpid, variables_table::MomentumTrack, variables_table::XTrack, diff --git a/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx b/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx index 8b74a7beb77..03dfe30779b 100644 --- a/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx +++ b/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx @@ -20,11 +20,30 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include #include #include diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx index 95f9016d388..bbe18f83730 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx @@ -16,15 +16,27 @@ /// #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx index a1461cb0509..2a9d59a71b0 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBeta.cxx @@ -16,15 +16,24 @@ /// #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBetaImp.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBetaImp.cxx index 2bcccc5a67b..8a83649dbc7 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBetaImp.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFBetaImp.cxx @@ -16,16 +16,26 @@ /// #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" +#include +#include +#include #include +#include +#include #include -#include +#include +#include +#include #include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx index b9ead03b14f..c0b4e628fe2 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFEvTime.cxx @@ -21,15 +21,25 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFT0/Digit.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" - -#include "TEfficiency.h" -#include "THashList.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFMC.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFMC.cxx index 3a0f2de652f..d9ef9cd278b 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFMC.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOFMC.cxx @@ -18,10 +18,29 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" +#include +#include +#include #include +#include #include +#include +#include +#include +#include #include #include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPC.cxx b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPC.cxx index 53c03e6c338..cbc4084e922 100644 --- a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPC.cxx +++ b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPC.cxx @@ -20,10 +20,25 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCMC.cxx b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCMC.cxx index e05023b4b3a..8ff86797176 100644 --- a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCMC.cxx +++ b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCMC.cxx @@ -15,13 +15,24 @@ /// \brief Task to produce QA output of the PID with TPC running on the MC. /// -// O2 includes #include "Common/DataModel/PIDResponseTPC.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx index bf8492b8036..2c0501963b5 100644 --- a/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx +++ b/DPG/Tasks/AOTTrack/PID/TPC/qaPIDTPCSignal.cxx @@ -16,12 +16,29 @@ /// \brief Implementation for QA tasks of the TPC signal (lite task, refer to qaPIDTPC.cxx for full TPC QA for PID) /// -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx b/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx index 1ab36ad9f71..aa2f13ba744 100644 --- a/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx +++ b/DPG/Tasks/AOTTrack/V0Cascades/perfK0sResolution.cxx @@ -20,10 +20,12 @@ #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -37,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -44,15 +47,13 @@ #include #include #include -#include #include #include #include +#include #include -#include - #include #include #include diff --git a/DPG/Tasks/AOTTrack/V0Cascades/qaCascades.cxx b/DPG/Tasks/AOTTrack/V0Cascades/qaCascades.cxx index 2513ad92a91..be37adc3943 100644 --- a/DPG/Tasks/AOTTrack/V0Cascades/qaCascades.cxx +++ b/DPG/Tasks/AOTTrack/V0Cascades/qaCascades.cxx @@ -18,21 +18,17 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/V0Cascades/qaEfficiencyV0s.cxx b/DPG/Tasks/AOTTrack/V0Cascades/qaEfficiencyV0s.cxx index a728b252007..ff6236ec9a9 100644 --- a/DPG/Tasks/AOTTrack/V0Cascades/qaEfficiencyV0s.cxx +++ b/DPG/Tasks/AOTTrack/V0Cascades/qaEfficiencyV0s.cxx @@ -17,23 +17,26 @@ /// The efficiency for particles is computed according to the PDG code (sign included and not charge) /// -// 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/LFStrangenessTables.h" -// ROOT includes -#include "TPDGCode.h" -#include "TEfficiency.h" -#include "THashList.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include using namespace o2::framework; static constexpr int nSpecies = 2; // One per PDG diff --git a/DPG/Tasks/AOTTrack/V0Cascades/qaK0sTrackingEfficiency.cxx b/DPG/Tasks/AOTTrack/V0Cascades/qaK0sTrackingEfficiency.cxx index 64b84711d90..2765e7e87d9 100644 --- a/DPG/Tasks/AOTTrack/V0Cascades/qaK0sTrackingEfficiency.cxx +++ b/DPG/Tasks/AOTTrack/V0Cascades/qaK0sTrackingEfficiency.cxx @@ -11,19 +11,24 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx index a8bd2c6d321..33a4a2a9ed7 100644 --- a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx +++ b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx @@ -25,28 +25,41 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/OccupancyTables.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Tools/ML/MlResponse.h" -#include "CommonDataFormat/InteractionRecord.h" +#include +#include #include +#include #include +#include +#include +#include +#include #include -#include +#include +#include +#include #include #include #include -#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector3Dfwd.h) +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include -#include #include #include +#include #include #include #include @@ -412,6 +425,7 @@ struct DerivedDataCreatorD0Calibration { } float invMassD0{0.f}, invMassD0bar{0.f}; + float cosThetaStarD0{0.f}, cosThetaStarD0bar{0.f}; std::vector bdtScoresD0{0.f, 1.f, 1.f}, bdtScoresD0bar{0.f, 1.f, 1.f}; // always selected a priori if (massHypo == D0MassHypo::D0 || massHypo == D0MassHypo::D0AndD0Bar) { invMassD0 = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); @@ -424,6 +438,14 @@ struct DerivedDataCreatorD0Calibration { std::vector featuresCandD0 = {dcaPos.getY(), dcaNeg.getY(), chi2PCA, cosPaD0, cosPaXYD0, decLenXYD0, decLenD0, dcaPos.getY() * dcaNeg.getY(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaPi(), trackPos.tofNSigmaPi()), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaKa()), trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaKa(), trackPos.tofNSigmaKa()), trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaPi(), trackNeg.tofNSigmaPi())}; if (!mlResponse.isSelectedMl(featuresCandD0, ptD0, bdtScoresD0)) { massHypo -= D0MassHypo::D0; + } else { // selected, we compute cost* + ROOT::Math::PxPyPzMVector const fourVecPi = ROOT::Math::PxPyPzMVector(pVecPos[0], pVecPos[1], pVecPos[2], o2::constants::physics::MassPiPlus); + ROOT::Math::PxPyPzMVector const fourVecMother = ROOT::Math::PxPyPzMVector(pVecD0[0], pVecD0[1], pVecD0[2], invMassD0); + ROOT::Math::Boost const boost{fourVecMother.BoostToCM()}; + ROOT::Math::PxPyPzMVector const fourVecPiCM = boost(fourVecPi); + ROOT::Math::XYZVector const threeVecPiCM = fourVecPiCM.Vect(); + ROOT::Math::XYZVector const helicityVec = fourVecMother.Vect(); + cosThetaStarD0 = helicityVec.Dot(threeVecPiCM) / std::sqrt(threeVecPiCM.Mag2()) / std::sqrt(helicityVec.Mag2()); } } } @@ -439,6 +461,14 @@ struct DerivedDataCreatorD0Calibration { std::vector featuresCandD0bar = {dcaPos.getY(), dcaNeg.getY(), chi2PCA, cosPaD0, cosPaXYD0, decLenXYD0, decLenD0, dcaPos.getY() * dcaNeg.getY(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaPi(), trackNeg.tofNSigmaPi()), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaKa(), trackPos.tofNSigmaKa()), trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaKa()), trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaPi(), trackPos.tofNSigmaPi())}; if (!mlResponse.isSelectedMl(featuresCandD0bar, ptD0, bdtScoresD0bar)) { massHypo -= D0MassHypo::D0Bar; + } else { // selected, we compute cost* + ROOT::Math::PxPyPzMVector const fourVecPi = ROOT::Math::PxPyPzMVector(pVecNeg[0], pVecNeg[1], pVecNeg[2], o2::constants::physics::MassPiPlus); + ROOT::Math::PxPyPzMVector const fourVecMother = ROOT::Math::PxPyPzMVector(pVecD0[0], pVecD0[1], pVecD0[2], invMassD0bar); + ROOT::Math::Boost const boost{fourVecMother.BoostToCM()}; + ROOT::Math::PxPyPzMVector const fourVecPiCM = boost(fourVecPi); + ROOT::Math::XYZVector const threeVecPiCM = fourVecPiCM.Vect(); + ROOT::Math::XYZVector const helicityVec = fourVecMother.Vect(); + cosThetaStarD0bar = helicityVec.Dot(threeVecPiCM) / std::sqrt(threeVecPiCM.Mag2()) / std::sqrt(helicityVec.Mag2()); } } } @@ -813,6 +843,8 @@ struct DerivedDataCreatorD0Calibration { phiD0, invMassD0, invMassD0bar, + cosThetaStarD0, + cosThetaStarD0bar, getCompressedDecayLength(decLenD0), getCompressedDecayLength(decLenXYD0), getCompressedNormDecayLength(decLenD0 / errorDecayLengthD0), diff --git a/DPG/Tasks/AOTTrack/qaDcaMC.cxx b/DPG/Tasks/AOTTrack/qaDcaMC.cxx index 4054c59b33a..28b65bfa304 100644 --- a/DPG/Tasks/AOTTrack/qaDcaMC.cxx +++ b/DPG/Tasks/AOTTrack/qaDcaMC.cxx @@ -15,23 +15,29 @@ /// \brief Task to analyse the DCA distributions in the MC according to PDG code and status /// -// 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" -// ROOT includes -#include "TPDGCode.h" -#include "TEfficiency.h" -#include "THashList.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.h b/DPG/Tasks/AOTTrack/qaEventTrack.h index e2230e37c87..edd9512c5ec 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.h +++ b/DPG/Tasks/AOTTrack/qaEventTrack.h @@ -17,10 +17,14 @@ /// \brief Header file for QA tasks for the track and the event properties. /// -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#ifndef DPG_TASKS_AOTTRACK_QAEVENTTRACK_H_ +#define DPG_TASKS_AOTTRACK_QAEVENTTRACK_H_ + #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" + +#include + +#include // Output table declaration namespace o2::aod @@ -165,3 +169,5 @@ DECLARE_SOA_TABLE(DPGNonRecoParticles, "AOD", "DPGNonRecoPart", //! Table of the dpgparticles::IsFromMaterial, mcparticle::Vx, mcparticle::Vy, mcparticle::Vz); } // namespace o2::aod + +#endif // DPG_TASKS_AOTTRACK_QAEVENTTRACK_H_ diff --git a/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx b/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx index f6812f35a8e..61938e1d348 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrackLite.cxx @@ -20,25 +20,34 @@ #include "qaEventTrack.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "MathUtils/BetheBlochAleph.h" -#include "ReconstructionDataFormats/PID.h" - -#include "TF1.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::dataformats; // Lite version of the QA task to run on skimmed dataset struct qaEventTrackLite { diff --git a/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx b/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx index 0184d5b39f0..8e41e7a24cc 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx @@ -19,27 +19,27 @@ #include "qaEventTrack.h" -#include - -#include "TRandom.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/TableProducer/PID/pidTOFBase.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::dataformats; struct QaEventTrackLiteProducer { // Tables to produce diff --git a/DPG/Tasks/AOTTrack/qaFakeHits.cxx b/DPG/Tasks/AOTTrack/qaFakeHits.cxx index 4005b0834c9..b0dc3c553cc 100644 --- a/DPG/Tasks/AOTTrack/qaFakeHits.cxx +++ b/DPG/Tasks/AOTTrack/qaFakeHits.cxx @@ -16,19 +16,26 @@ /// \brief Task to analyze the fraction of the true and fake hits depending on where the fake hits are picked /// -#include "PWGLF/DataModel/LFParticleIdentification.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include #include +#include #include +#include +#include +#include #include #include -#include -#include +#include + +#include +#include + +#include +#include +#include using namespace o2::framework; // Particle information diff --git a/DPG/Tasks/AOTTrack/qaMatchEff.cxx b/DPG/Tasks/AOTTrack/qaMatchEff.cxx index 4b6d3e87d13..d34c897ac55 100644 --- a/DPG/Tasks/AOTTrack/qaMatchEff.cxx +++ b/DPG/Tasks/AOTTrack/qaMatchEff.cxx @@ -80,7 +80,6 @@ using namespace o2; using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; using namespace extConfPar; using o2::constants::math::PI; using o2::constants::math::TwoPI; diff --git a/DPG/Tasks/AOTTrack/qaPrimVtxVsTime.cxx b/DPG/Tasks/AOTTrack/qaPrimVtxVsTime.cxx index dd66692a4e2..2c1d251b710 100644 --- a/DPG/Tasks/AOTTrack/qaPrimVtxVsTime.cxx +++ b/DPG/Tasks/AOTTrack/qaPrimVtxVsTime.cxx @@ -10,18 +10,21 @@ // or submit itself to any jurisdiction. /// \author Mattia Faggin , Padova University and INFN -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/HistogramRegistry.h" -#include "CommonDataFormat/BunchFilling.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "TH1F.h" -#include "TH2F.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include using namespace o2::framework; using namespace o2; diff --git a/DPG/Tasks/AOTTrack/qaSignChargeMC.cxx b/DPG/Tasks/AOTTrack/qaSignChargeMC.cxx index e40dd0e76e9..1de78d081a2 100644 --- a/DPG/Tasks/AOTTrack/qaSignChargeMC.cxx +++ b/DPG/Tasks/AOTTrack/qaSignChargeMC.cxx @@ -16,11 +16,19 @@ /// \since 08/05/2024 /// -// O2 includes -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2::framework; diff --git a/DPG/Tasks/AOTTrack/qaTrackSelection.cxx b/DPG/Tasks/AOTTrack/qaTrackSelection.cxx index f7ea3dd2f53..6cb389b8608 100644 --- a/DPG/Tasks/AOTTrack/qaTrackSelection.cxx +++ b/DPG/Tasks/AOTTrack/qaTrackSelection.cxx @@ -16,15 +16,27 @@ /// \brief Task to check how many tracks pass the cuts /// -// O2 includes -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/EventSelection.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + using namespace o2::framework; struct QaTrackCuts { diff --git a/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx b/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx index 3125f1e7c03..680cb819b34 100644 --- a/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx +++ b/DPG/Tasks/AOTTrack/qaTrackSplitting.cxx @@ -15,13 +15,28 @@ /// \brief Task to analyse the numbers of particles reconstructed more than once /// -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/EventSelection.h" +#include "TrackSelection.h" + #include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx b/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx index a4eb702af1e..842f167d7d2 100644 --- a/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx +++ b/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx @@ -16,6 +16,7 @@ #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" @@ -26,17 +27,39 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Tools/ML/MlResponse.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include +#include + +#include #include +#include +#include +#include +#include +#include #include #include @@ -399,38 +422,11 @@ struct TagTwoProngDisplacedVertices { } } - /// Fill a vector with the Mothers pdg codes - /// \param pdgDecayMothers vector pdg codes of possible mothers - /// \param pdgResonances vector pdg codes of possible resonanced in the decays - /// \param channel decay channel - void pdgMothersDecayChannel(std::vector& pdgDecayMothers, std::vector& pdgResonances, const uint8_t channel) - { - pdgDecayMothers.clear(); - pdgResonances.clear(); - if (channel == aod::tagandprobe::TagChannels::DplusToKPiPi) { - pdgDecayMothers.push_back(constants::physics::Pdg::kDPlus); - pdgResonances.push_back(constants::physics::Pdg::kK0Star892); - pdgResonances.push_back(10313); // o2-linter: disable=pdg/explicit-code (PDG code of K1(1270)0 to be added in O2) - pdgResonances.push_back(100313); // o2-linter: disable=pdg/explicit-code (PDG code of K*(1410)0 to be added in O2) - pdgResonances.push_back(10311); // o2-linter: disable=pdg/explicit-code (PDG code of K*0(1430)0 to be added in O2) - pdgResonances.push_back(100311); // o2-linter: disable=pdg/explicit-code (PDG code of K*(1460)0 to be added in O2) - pdgResonances.push_back(20313); // o2-linter: disable=pdg/explicit-code (PDG code of K1(1400)0 to be added in O2) - pdgResonances.push_back(30313); // o2-linter: disable=pdg/explicit-code (PDG code of K*(1680)0 to be added in O2) - } else if (channel == aod::tagandprobe::TagChannels::DsOrDplusToKKPi) { - pdgDecayMothers.push_back(constants::physics::Pdg::kDPlus); - pdgDecayMothers.push_back(constants::physics::Pdg::kDS); - } else if (channel == aod::tagandprobe::TagChannels::DstarPlusToDzeroPi || channel == aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi || channel == aod::tagandprobe::TagChannels::DstarToDzeroToKK) { - pdgDecayMothers.push_back(constants::physics::Pdg::kDStar); - } - } - /// Check if the given tag tracks belong to a D meson /// \param firstTrack candidate /// \param SecondTrack candidate /// \param mcParticles McParticles table /// \param channel decay channel - /// \param pdgDecayMothers vector pdg codes of possible mothers - /// \param pdgResonances vector pdg codes of possible resonanced in the decays /// \param motherIdx particle mother index /// \return a flag that contains the information of MC truth (see aod::tagandprobe::SignalFlags) template @@ -438,23 +434,18 @@ struct TagTwoProngDisplacedVertices { TTrack const& secondTrack, PParticles const& mcParticles, const uint8_t channel, - std::vector& pdgDecayMothers, - std::vector& pdgResonances, int& motherIdx) { - int pdgTagMother{0}; - int pdgProbeParticle{-1}; + std::array pdgTagParticles{}; uint8_t signalFlag = 0; + bool isTaggedAsSignal{false}, isResonant{false}; if (channel == aod::tagandprobe::TagChannels::DplusToKPiPi) { - pdgTagMother = constants::physics::Pdg::kDPlus; - pdgProbeParticle = kKPlus; + pdgTagParticles = {kPiPlus, kPiPlus}; } else if (channel == aod::tagandprobe::TagChannels::DsOrDplusToKKPi) { - pdgTagMother = constants::physics::Pdg::kPhi; - pdgProbeParticle = kPiPlus; + pdgTagParticles = {kKPlus, kKPlus}; } else { - pdgTagMother = constants::physics::Pdg::kD0; - pdgProbeParticle = kPiPlus; + pdgTagParticles = {kKPlus, kPiPlus}; } if (!firsTrack.has_mcParticle() || !secondTrack.has_mcParticle()) { @@ -464,56 +455,58 @@ struct TagTwoProngDisplacedVertices { } else { auto firstMcTrack = firsTrack.template mcParticle_as(); auto secondMcTrack = secondTrack.template mcParticle_as(); - auto firstTrackMotherId = RecoDecay::getMother(mcParticles, firstMcTrack, pdgTagMother, true); - auto secondTrackMotherId = RecoDecay::getMother(mcParticles, secondMcTrack, pdgTagMother, true); - - bool isTaggedAsSignal{false}, isResonant{false}; - const int nDauReso{2}, nDauNonReso{3}; - if ((firstTrackMotherId == secondTrackMotherId) && (firstTrackMotherId != -1)) { - auto particleMother = mcParticles.rawIteratorAt(firstTrackMotherId); + auto pdgCodeFirst = std::abs(firstMcTrack.pdgCode()); + auto pdgCodeSecond = std::abs(secondMcTrack.pdgCode()); + if ((pdgCodeFirst == pdgTagParticles[0] && pdgCodeSecond == pdgTagParticles[1]) || (pdgCodeFirst == pdgTagParticles[1] && pdgCodeSecond == pdgTagParticles[0])) { + int8_t sign{0}; + auto arrayDaughters = std::array{firsTrack, secondTrack}; /// π±π± for D± → K∓π±π± decays if (channel == aod::tagandprobe::TagChannels::DplusToKPiPi) { - auto particleMother = mcParticles.rawIteratorAt(firstTrackMotherId); - auto daughters = particleMother.template daughters_as(); - - // Check if the probe is within the mother's particle daughters - if (daughters.size() == nDauNonReso) { // non-resonant decay - for (auto const& daughter : daughters) { - if (std::abs(daughter.pdgCode()) == pdgProbeParticle) { - isTaggedAsSignal = true; - motherIdx = firstTrackMotherId; - break; - } + // let's first try with depth == 1 (non resonant) + motherIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kDPlus, std::array{+kPiPlus, +kPiPlus}, true, &sign, 1); + if (motherIdx < 0) { + motherIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kDPlus, std::array{+kPiPlus, +kPiPlus}, true, &sign, 2); + isResonant = true; + } + if (motherIdx > -1) { + // let's check that the full decay is correct from gen particle mother + auto particleMother = mcParticles.rawIteratorAt(motherIdx); + if (RecoDecay::isMatchedMCGen(mcParticles, particleMother, constants::physics::Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + isTaggedAsSignal = true; + } else { + motherIdx = -1; + isResonant = false; + } + } + } else if (channel == aod::tagandprobe::TagChannels::DsOrDplusToKKPi) { /// K∓K± for φ from Ds± or D± → φπ± decays + // we first check φ + auto phiIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kPhi, std::array{+kKPlus, -kKPlus}, false, &sign, 1); + if (phiIdx > -1) { + motherIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kDS, std::array{+kKPlus, -kKPlus}, true, &sign, 2); + if (motherIdx < 0) { + motherIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kDPlus, std::array{+kKPlus, -kKPlus}, true, &sign, 2); } - } else if (daughters.size() == nDauReso) { // resonant decay - for (auto const& daughter : daughters) { - auto absPdg = std::abs(daughter.pdgCode()); - if (std::find(pdgResonances.begin(), pdgResonances.end(), absPdg) != pdgResonances.end()) { + if (motherIdx > -1) { + auto particleMother = mcParticles.rawIteratorAt(motherIdx); + if (RecoDecay::isMatchedMCGen(mcParticles, particleMother, constants::physics::Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2) || RecoDecay::isMatchedMCGen(mcParticles, particleMother, constants::physics::Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { isTaggedAsSignal = true; - isResonant = true; - motherIdx = firstTrackMotherId; - break; + } else { + motherIdx = -1; } } } - } else { - /// K∓K± for φ from Ds± or D± → φπ± decays - /// K∓π± for D0 from D±* → D0π± decays - for (auto const& pdgGrandMother : pdgDecayMothers) { - auto grandMotherId = RecoDecay::getMother(mcParticles, particleMother, pdgGrandMother, true); - if (grandMotherId != -1) { - auto particleGrandMother = mcParticles.rawIteratorAt(grandMotherId); - auto daughters = particleGrandMother.template daughters_as(); - // Check if the probe is within the GrandMother's particle daughters - if (daughters.size() == nDauReso) { // exclude undesired decays, such as Ds± → φπ±π±π∓ - for (auto const& daughter : daughters) { - if (std::abs(daughter.pdgCode()) == pdgProbeParticle) { - isTaggedAsSignal = true; - motherIdx = grandMotherId; - break; - } - } + } else if (channel == aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi) { /// K∓π± for D0 from D±* → D0π± decays + // we first check D0 + auto dzeroIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kD0, std::array{+kPiPlus, -kKPlus}, false, &sign, 1); + if (dzeroIdx > -1) { + motherIdx = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, constants::physics::Pdg::kDStar, std::array{+kPiPlus, -kKPlus}, true, &sign, 2); + if (motherIdx > -1) { + auto particleMother = mcParticles.rawIteratorAt(motherIdx); + if (RecoDecay::isMatchedMCGen(mcParticles, particleMother, constants::physics::Pdg::kDStar, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + isTaggedAsSignal = true; + } else { + motherIdx = -1; } } } @@ -522,7 +515,7 @@ struct TagTwoProngDisplacedVertices { // check if it is non-prompt from beauty if (isTaggedAsSignal) { - if (RecoDecay::getCharmHadronOrigin(mcParticles, mcParticles.rawIteratorAt(firstTrackMotherId)) == RecoDecay::OriginType::NonPrompt) { + if (RecoDecay::getCharmHadronOrigin(mcParticles, mcParticles.rawIteratorAt(motherIdx), false) == RecoDecay::OriginType::NonPrompt) { SETBIT(signalFlag, aod::tagandprobe::SignalFlags::NonPrompt); } else { SETBIT(signalFlag, aod::tagandprobe::SignalFlags::Prompt); @@ -674,8 +667,6 @@ struct TagTwoProngDisplacedVertices { TTracks const& tracks, // pool of tracks const uint8_t channel, float& /*bz*/, - std::vector& pdgDecayMothers, - std::vector& pdgResonances, PParticles const& mcParticles) { for (auto trackFirst = tracks.begin(); trackFirst != tracks.end(); ++trackFirst) { @@ -731,7 +722,7 @@ struct TagTwoProngDisplacedVertices { uint8_t isSignal{0u}; int motherIdx{-1}; if constexpr (doMc) { - isSignal = getTagOrigin(trackFirst, trackSecond, mcParticles, channel, pdgDecayMothers, pdgResonances, motherIdx); + isSignal = getTagOrigin(trackFirst, trackSecond, mcParticles, channel, motherIdx); } std::vector mlScoresTag{}; @@ -798,8 +789,6 @@ struct TagTwoProngDisplacedVertices { TTracks const& tracksNeg, const uint8_t channel, float& /*bz*/, - std::vector& pdgDecayMothers, - std::vector& pdgResonances, PParticles const& mcParticles) { for (const auto& trackPos : tracksPos) { @@ -855,7 +844,7 @@ struct TagTwoProngDisplacedVertices { uint8_t isSignal{0u}; int motherIdx{-1}; if constexpr (doMc) { - isSignal = getTagOrigin(trackPos, trackNeg, mcParticles, channel, pdgDecayMothers, pdgResonances, motherIdx); + isSignal = getTagOrigin(trackPos, trackNeg, mcParticles, channel, motherIdx); } std::vector mlScoresTag{}; @@ -990,15 +979,11 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DplusToKPiPi); - auto groupPositive = positivePionsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialSameCharge(collision, groupPositive, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, pdgDecayMothers, pdgResonances, mcParticles); + computeCombinatorialSameCharge(collision, groupPositive, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, mcParticles); auto groupNegative = negativePionsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialSameCharge(collision, groupNegative, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, pdgDecayMothers, pdgResonances, mcParticles); + computeCombinatorialSameCharge(collision, groupNegative, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, mcParticles); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processPiPiFromDplusMc, "Process pipi combinatorial to tag pion pairs from D+ decays Mc", false); @@ -1019,15 +1004,11 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DplusToKPiPi); - auto groupPositive = positivePions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialSameCharge(collision, groupPositive, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, pdgDecayMothers, pdgResonances, tracks); + computeCombinatorialSameCharge(collision, groupPositive, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, tracks); auto groupNegative = negativePions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialSameCharge(collision, groupNegative, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, pdgDecayMothers, pdgResonances, tracks); + computeCombinatorialSameCharge(collision, groupNegative, aod::tagandprobe::TagChannels::DplusToKPiPi, bz, tracks); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processPiPiFromDplus, "Process pipi combinatorial to tag pion pairs from D+ decays", false); @@ -1049,13 +1030,9 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DsOrDplusToKKPi); - auto groupPositive = positiveKaonsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupNegative = negativeKaonsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialOppositeCharge(collision, groupPositive, groupNegative, aod::tagandprobe::TagChannels::DsOrDplusToKKPi, bz, pdgDecayMothers, pdgResonances, mcParticles); + computeCombinatorialOppositeCharge(collision, groupPositive, groupNegative, aod::tagandprobe::TagChannels::DsOrDplusToKKPi, bz, mcParticles); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processKaKaFromDsOrDplusMc, "Process KK combinatorial to tag kaon pairs from Ds+/D+ decays Mc", false); @@ -1076,13 +1053,9 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DsOrDplusToKKPi); - auto groupPositive = positiveKaons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupNegative = negativeKaons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialOppositeCharge(collision, groupPositive, groupNegative, aod::tagandprobe::TagChannels::DsOrDplusToKKPi, bz, pdgDecayMothers, pdgResonances, tracks); + computeCombinatorialOppositeCharge(collision, groupPositive, groupNegative, aod::tagandprobe::TagChannels::DsOrDplusToKKPi, bz, tracks); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processKaKaFromDsOrDplus, "Process KK combinatorial to tag kaon pairs from Ds+/D+ decays", false); @@ -1103,13 +1076,9 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DstarToDzeroToKK); - auto groupPositive = positiveKaons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupNegative = negativeKaons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialOppositeCharge(collision, groupPositive, groupNegative, aod::tagandprobe::TagChannels::DstarToDzeroToKK, bz, pdgDecayMothers, pdgResonances, tracks); + computeCombinatorialOppositeCharge(collision, groupPositive, groupNegative, aod::tagandprobe::TagChannels::DstarToDzeroToKK, bz, tracks); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processKaKaFromDzero, "Process KK combinatorial to tag kaon pairs from Dzero decays", false); @@ -1130,16 +1099,12 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DstarPlusToDzeroPi); - auto groupPionPositive = positivePions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupPionNegative = negativePions->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupKaonPositive = positiveKaons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupKaonNegative = negativeKaons->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialOppositeCharge(collision, groupPionPositive, groupKaonNegative, aod::tagandprobe::TagChannels::DstarPlusToDzeroPi, bz, pdgDecayMothers, pdgResonances, tracks); - computeCombinatorialOppositeCharge(collision, groupKaonPositive, groupPionNegative, aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi, bz, pdgDecayMothers, pdgResonances, tracks); + computeCombinatorialOppositeCharge(collision, groupPionPositive, groupKaonNegative, aod::tagandprobe::TagChannels::DstarPlusToDzeroPi, bz, tracks); + computeCombinatorialOppositeCharge(collision, groupKaonPositive, groupPionNegative, aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi, bz, tracks); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processKaPiFromDstar, "Process Kpi combinatorial to tag D0 from D*+ decays", false); @@ -1161,16 +1126,12 @@ struct TagTwoProngDisplacedVertices { runNumber = bc.runNumber(); } - std::vector pdgDecayMothers{}; - std::vector pdgResonances{}; - pdgMothersDecayChannel(pdgDecayMothers, pdgResonances, aod::tagandprobe::TagChannels::DstarPlusToDzeroPi); - auto groupPionPositive = positivePionsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupPionNegative = negativePionsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupKaonPositive = positiveKaonsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto groupKaonNegative = negativeKaonsMc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - computeCombinatorialOppositeCharge(collision, groupPionPositive, groupKaonNegative, aod::tagandprobe::TagChannels::DstarPlusToDzeroPi, bz, pdgDecayMothers, pdgResonances, mcParticles); - computeCombinatorialOppositeCharge(collision, groupKaonPositive, groupPionNegative, aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi, bz, pdgDecayMothers, pdgResonances, mcParticles); + computeCombinatorialOppositeCharge(collision, groupPionPositive, groupKaonNegative, aod::tagandprobe::TagChannels::DstarPlusToDzeroPi, bz, mcParticles); + computeCombinatorialOppositeCharge(collision, groupKaonPositive, groupPionNegative, aod::tagandprobe::TagChannels::DstarMinusToDzeroBarPi, bz, mcParticles); } PROCESS_SWITCH(TagTwoProngDisplacedVertices, processKaPiFromDstarMc, "Process Kpi combinatorial to tag D0 from D*+ decays", false); }; diff --git a/DPG/Tasks/AOTTrack/unitTestForReconstruction.cxx b/DPG/Tasks/AOTTrack/unitTestForReconstruction.cxx index a5e6016d9fb..b5f44d9c311 100644 --- a/DPG/Tasks/AOTTrack/unitTestForReconstruction.cxx +++ b/DPG/Tasks/AOTTrack/unitTestForReconstruction.cxx @@ -15,21 +15,17 @@ /// \author Alberto Caliva (alberto.caliva@cern.ch), Catalin-Lucian Ristea (catalin.ristea@cern.ch) /// \since September 9, 2025 -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include #include #include #include diff --git a/DPG/Tasks/FDD/qaFDD.cxx b/DPG/Tasks/FDD/qaFDD.cxx index c985d7dbb9d..96f4d31dcab 100644 --- a/DPG/Tasks/FDD/qaFDD.cxx +++ b/DPG/Tasks/FDD/qaFDD.cxx @@ -9,21 +9,35 @@ // 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 "Common/DataModel/EventSelection.h" -#include "DataFormatsFDD/Digit.h" -#include "DataFormatsFIT/Triggers.h" #include "Common/DataModel/FT0Corrected.h" -#include "CCDB/CcdbApi.h" -#include "CommonDataFormat/BunchFilling.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "TH1F.h" -#include "TH2F.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/FT0/qaFT0TrgBased.cxx b/DPG/Tasks/FT0/qaFT0TrgBased.cxx index 35a2c2cc884..c42b839087a 100644 --- a/DPG/Tasks/FT0/qaFT0TrgBased.cxx +++ b/DPG/Tasks/FT0/qaFT0TrgBased.cxx @@ -13,27 +13,29 @@ /// \author Uliana Dmitrieva uliana.dmitrieva@cern.ch /// \brief FT0 QA +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include #include -#include +#include #include #include #include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" -#include "Common/DataModel/Multiplicity.h" -#include "DataFormatsFT0/Digit.h" - -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFIT/Triggers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/InitContext.h" -#include "Framework/runDataProcessing.h" - using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/FV0/qaFV0.cxx b/DPG/Tasks/FV0/qaFV0.cxx index 295f981b0b7..1e21e679f1a 100644 --- a/DPG/Tasks/FV0/qaFV0.cxx +++ b/DPG/Tasks/FV0/qaFV0.cxx @@ -13,28 +13,27 @@ /// \author Andreas Molander andreas.molander@cern.ch /// \brief FV0 QA +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + #include #include -#include -#include #include +#include #include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" - -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFIT/Triggers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/InitContext.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/runDataProcessing.h" - -#include "TH1F.h" -#include "TH2F.h" - using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/ITS/filterTracks.cxx b/DPG/Tasks/ITS/filterTracks.cxx index b97c48d4f5c..6a9ee148142 100644 --- a/DPG/Tasks/ITS/filterTracks.cxx +++ b/DPG/Tasks/ITS/filterTracks.cxx @@ -14,22 +14,26 @@ /// /// \author Andrea Rossi +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include using namespace o2; @@ -55,15 +59,15 @@ DECLARE_SOA_COLUMN(Pz, pz, float); //! track pz // DECLARE_SOA_COLUMN(Z, z, float); //! track z position at the DCA to the primary vertex // DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); //! track distance of closest approach at the primary vertex: in xy plane // DECLARE_SOA_COLUMN(DcaZ, dcaz, float); //! track distance of closest approach at the primary vertex: along z (beam line) direction -DECLARE_SOA_COLUMN(Charge, charge, int); //! track sign, not really charge -DECLARE_SOA_COLUMN(NsigmaTPCpi, nsigmaTPCpi, float); //! TPC nsigma w.r.t. pion mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTPCka, nsigmaTPCka, float); //! TPC nsigma w.r.t. kaon mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTPCpr, nsigmaTPCpr, float); //! TPC nsigma w.r.t. proton mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTOFpi, nsigmaTOFpi, float); //! TOF nsigma w.r.t. pion mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTOFka, nsigmaTOFka, float); //! TOF nsigma w.r.t. kaon mass hypothesis -DECLARE_SOA_COLUMN(NsigmaTOFpr, nsigmaTOFpr, float); //! TOF nsigma w.r.t. proton mass hypothesis -DECLARE_SOA_COLUMN(TpcNCluster, tpcNCluster, int); //! TOF nsigma w.r.t. proton mass hypothesis - +DECLARE_SOA_COLUMN(Charge, charge, int); //! track sign, not really charge +DECLARE_SOA_COLUMN(NsigmaTPCpi, nsigmaTPCpi, float); //! TPC nsigma w.r.t. pion mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTPCka, nsigmaTPCka, float); //! TPC nsigma w.r.t. kaon mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTPCpr, nsigmaTPCpr, float); //! TPC nsigma w.r.t. proton mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTOFpi, nsigmaTOFpi, float); //! TOF nsigma w.r.t. pion mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTOFka, nsigmaTOFka, float); //! TOF nsigma w.r.t. kaon mass hypothesis +DECLARE_SOA_COLUMN(NsigmaTOFpr, nsigmaTOFpr, float); //! TOF nsigma w.r.t. proton mass hypothesis +DECLARE_SOA_COLUMN(TpcNCluster, tpcNCluster, int); //! TOF nsigma w.r.t. proton mass hypothesis +DECLARE_SOA_COLUMN(EventIsGoodITS123, eventIsGoodITS0123, uint8_t); //! flag to store bit of o2::aod::evsel::kIsGoodITSLayer0123 ///// MC INFO DECLARE_SOA_COLUMN(MainHfMotherPdgCode, mainHfMotherPdgCode, int); //! mother pdg code for particles coming from HF, skipping intermediate resonance states. Not trustable when mother is not HF. Not suited for Sc->Lc decays, since Sc are never pointed to DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); //! is phyiscal primary according to ALICE definition @@ -92,7 +96,8 @@ DECLARE_SOA_TABLE(FilterColl, "AOD", "FILTERCOLL", o2::aod::collision::Chi2, o2::aod::collision::NumContrib, o2::aod::collision::CollisionTime, - o2::aod::collision::CollisionTimeRes); + o2::aod::collision::CollisionTimeRes, + aod::filtertracks::EventIsGoodITS123); DECLARE_SOA_TABLE(FilterCollLite, "AOD", "FILTERCOLLLITE", o2::aod::collision::PosX, o2::aod::collision::PosY, @@ -105,14 +110,16 @@ DECLARE_SOA_TABLE(FilterCollLite, "AOD", "FILTERCOLLLITE", o2::aod::collision::CovZZ, o2::aod::collision::Chi2, o2::aod::collision::NumContrib, - o2::aod::collision::CollisionTime); + o2::aod::collision::CollisionTime, + aod::filtertracks::EventIsGoodITS123); DECLARE_SOA_TABLE(FilterCollPos, "AOD", "FILTERCOLLPOS", o2::aod::collision::PosX, o2::aod::collision::PosY, o2::aod::collision::PosZ, o2::aod::collision::Chi2, o2::aod::collision::NumContrib, - o2::aod::collision::CollisionTime); + o2::aod::collision::CollisionTime, + aod::filtertracks::EventIsGoodITS123); DECLARE_SOA_TABLE(FiltTrackColIdx, "AOD", "FILTTRACKCOLIDX", o2::aod::track::CollisionId); DECLARE_SOA_TABLE(FilterTrack, "AOD", "FILTERTRACK", @@ -166,7 +173,7 @@ DECLARE_SOA_TABLE(GenParticles, "AOD", "GENPARTICLES", } // namespace o2::aod struct FilterTracks { - const static int nStudiedParticlesMc = 3; + static const int nStudiedParticlesMc = 3; Produces filteredTracksCollIdx; Produces filteredTracksTableExtra; @@ -307,30 +314,30 @@ struct FilterTracks { for (auto const& track : tracks) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } } else { auto lowPtTracksThisColl = lowPtTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto const& track : lowPtTracksThisColl) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } auto midPtTracksThisColl = midPtTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto const& track : midPtTracksThisColl) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } auto highPtTracksThisColl = highPtTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto const& track : highPtTracksThisColl) { fillTableData(track); if (produceCollTableExtraLite == 2) { - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); - }; + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); + } } } } @@ -338,11 +345,11 @@ struct FilterTracks { void processCollisions(FilterCollisionsWithEvSel::iterator const& collision) { if (produceCollTableFull) - filterCollTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.flags(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes()); + filterCollTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.flags(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); if (produceCollTableLite) - filterCollLiteTable(collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); + filterCollLiteTable(collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); if (produceCollTableExtraLite == 1) - filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime(), collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)); } PROCESS_SWITCH(FilterTracks, processCollisions, "process collisions", true); diff --git a/DPG/Tasks/MFT/aQCMFTTracks.cxx b/DPG/Tasks/MFT/aQCMFTTracks.cxx index 5b5f4a71aa4..be34d97fe69 100644 --- a/DPG/Tasks/MFT/aQCMFTTracks.cxx +++ b/DPG/Tasks/MFT/aQCMFTTracks.cxx @@ -16,24 +16,17 @@ /// \author David Grund /// \since -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/TimingInfo.h" -#include "Framework/runDataProcessing.h" - -#include -#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/Monitor/MC/taskMcSimpleQC.cxx b/DPG/Tasks/Monitor/MC/taskMcSimpleQC.cxx index 5f285fcc2b4..fc38e305938 100644 --- a/DPG/Tasks/Monitor/MC/taskMcSimpleQC.cxx +++ b/DPG/Tasks/Monitor/MC/taskMcSimpleQC.cxx @@ -12,13 +12,16 @@ /// \brief Simple QC task to run /// \author Fabrizio Grosa, fabrizio.grosa@cern.ch (CERN) -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; @@ -36,7 +39,7 @@ struct mcSimpleQc { {"histNumGlobalTracks", ";#it{N}_{global tracks};entries", {HistType::kTH1F, {{200, -0.5, 200.}}}}, // {"histNumPvContributors", ";#it{N}_{PV contributors};entries", {HistType::kTH1F, {{200, -0.5, 200.}}}}, // {"histFracAmbiguousTracks", ";#it{N}_{ambiguous tracks} / #it{N}_{tracks};entries", {HistType::kTH1F, {{100, 0., 1.}}}} // - } // + } // }; using CollisionsWithMCLabels = soa::Join; @@ -84,4 +87,4 @@ struct mcSimpleQc { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} \ No newline at end of file +} diff --git a/DPG/Tasks/TOF/tofOfflineCalib.cxx b/DPG/Tasks/TOF/tofOfflineCalib.cxx index 950efc83e07..f3b6aed8ab8 100644 --- a/DPG/Tasks/TOF/tofOfflineCalib.cxx +++ b/DPG/Tasks/TOF/tofOfflineCalib.cxx @@ -24,9 +24,33 @@ #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/TOF/tofSkimsTableCreator.cxx b/DPG/Tasks/TOF/tofSkimsTableCreator.cxx index c61a3336982..4fcdc3fb7cb 100644 --- a/DPG/Tasks/TOF/tofSkimsTableCreator.cxx +++ b/DPG/Tasks/TOF/tofSkimsTableCreator.cxx @@ -20,12 +20,24 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/DPG/Tasks/TOF/tofSkimsTableCreator.h b/DPG/Tasks/TOF/tofSkimsTableCreator.h index 4f0ec48ed06..f3a6f63bb9b 100644 --- a/DPG/Tasks/TOF/tofSkimsTableCreator.h +++ b/DPG/Tasks/TOF/tofSkimsTableCreator.h @@ -19,10 +19,13 @@ #ifndef DPG_TASKS_TOF_TOFSKIMSTABLECREATOR_H_ #define DPG_TASKS_TOF_TOFSKIMSTABLECREATOR_H_ -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/FT0Corrected.h" -#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include + +#include namespace o2::aod { diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index c91afe4734f..85607d41636 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -45,6 +45,7 @@ #include #include +#include #include #include diff --git a/DPG/Tasks/TPC/tpcTreeCreatorLight.cxx b/DPG/Tasks/TPC/tpcTreeCreatorLight.cxx index a0871336051..7d9ae11ea1b 100644 --- a/DPG/Tasks/TPC/tpcTreeCreatorLight.cxx +++ b/DPG/Tasks/TPC/tpcTreeCreatorLight.cxx @@ -18,28 +18,27 @@ #include "tpcTreeCreatorLight.h" -#include - -#include -/// ROOT -#include "TRandom3.h" -/// O2 -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -/// O2Physics -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::track; -using namespace o2::dataformats; struct TreeWriterTPCTOF { using Trks = soa::Join; diff --git a/DPG/Tasks/TPC/tpcTreeCreatorLight.h b/DPG/Tasks/TPC/tpcTreeCreatorLight.h index df02c1de1ec..a9b7af27966 100644 --- a/DPG/Tasks/TPC/tpcTreeCreatorLight.h +++ b/DPG/Tasks/TPC/tpcTreeCreatorLight.h @@ -17,10 +17,9 @@ #ifndef DPG_TASKS_TPC_TPCTREECREATORLIGHT_H_ #define DPG_TASKS_TPC_TPCTREECREATORLIGHT_H_ -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/PIDResponse.h" +#include + +#include enum ParticleSpecies { kPionTrack = BIT(0), diff --git a/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h b/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h index e32cee320fc..32c27233067 100644 --- a/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h +++ b/DPG/Tasks/TPC/utilsTpcSkimsTableCreator.h @@ -24,6 +24,8 @@ #include "Common/DataModel/OccupancyTables.h" +#include + #include #include diff --git a/EventFiltering/CMakeLists.txt b/EventFiltering/CMakeLists.txt index 7ed2450830c..8d5bf4622dc 100644 --- a/EventFiltering/CMakeLists.txt +++ b/EventFiltering/CMakeLists.txt @@ -69,7 +69,7 @@ o2physics_add_dpl_workflow(je-hf-filter o2physics_add_dpl_workflow(fje-filter SOURCES PWGJE/fullJetFilter.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib Boost::system + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lf-strangeness-filter @@ -82,6 +82,11 @@ o2physics_add_dpl_workflow(mult-filter PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(em-global-dimuon-filter + SOURCES PWGEM/globalDimuonFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(em-photon-filter SOURCES PWGEM/EMPhotonFilter.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase O2Physics::PWGEMPhotonMesonCore @@ -102,7 +107,12 @@ o2physics_add_dpl_workflow(lf-f1proton-filter PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore KFParticle::KFParticle O2::DetectorsBase COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(lf-doublephi-filter +o2physics_add_dpl_workflow(lf-doublephi-filter SOURCES PWGLF/filterdoublephi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(h2-from-beauty-filter + SOURCES PWGHF/H2fromLbFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) diff --git a/EventFiltering/PWGCF/CFFilterAll.cxx b/EventFiltering/PWGCF/CFFilterAll.cxx index 84807d4d257..3f2540f27b0 100644 --- a/EventFiltering/PWGCF/CFFilterAll.cxx +++ b/EventFiltering/PWGCF/CFFilterAll.cxx @@ -18,7 +18,9 @@ #include "PWGLF/Utils/strangenessBuilderHelper.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseITS.h" @@ -26,22 +28,35 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector4D.h" -#include "TMath.h" - -#include "fairlogger/Logger.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include +#include +#include +#include #include #include @@ -140,7 +155,10 @@ struct CFFilterAll { struct : ConfigurableGroup { std::string prefix = "EventSel"; Configurable zvtx{"zvtx", 10.f, "Max. z-Vertex (cm)"}; - Configurable eventSel{"eventSel", true, "Use sel8"}; + Configurable useSel8{"useSel8", true, "Use sel8"}; + Configurable useIsTriggerTvx{"useIsTriggerTvx", false, "Use TVX trigger"}; + Configurable useNoTimeFrameBorder{"useNoTimeFrameBorder", false, "Use time frame border cut"}; + Configurable useNoItsRofFrameBorder{"useNoItsRofFrameBorder", false, "Use ITS ROF border cut"}; } EventSelection; // Configs for tracks @@ -1051,7 +1069,18 @@ struct CFFilterAll { if (std::abs(col.posZ()) > EventSelection.zvtx.value) { return false; } - if (EventSelection.eventSel.value && !col.sel8()) { + // full cut on sel 8 + if (EventSelection.useSel8.value && !col.sel8()) { + return false; + } + // allow cut on components of sel8 in case we dont need ROF cut in 2026 anymore + if (EventSelection.useIsTriggerTvx.value && !col.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + if (EventSelection.useNoTimeFrameBorder.value && !col.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (EventSelection.useNoItsRofFrameBorder.value && !col.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return false; } return true; diff --git a/EventFiltering/PWGEM/EMPhotonFilter.cxx b/EventFiltering/PWGEM/EMPhotonFilter.cxx index 3e88524a89b..7a78c6485b1 100644 --- a/EventFiltering/PWGEM/EMPhotonFilter.cxx +++ b/EventFiltering/PWGEM/EMPhotonFilter.cxx @@ -14,17 +14,29 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/CaloClusters.h" +#include "Common/DataModel/EventSelection.h" #include "EventFiltering/filterTables.h" -#include "DataFormatsPHOS/TriggerRecord.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::soa; diff --git a/EventFiltering/PWGEM/EMPhotonFilterQC.cxx b/EventFiltering/PWGEM/EMPhotonFilterQC.cxx index de4d59f00da..d805ac673cf 100644 --- a/EventFiltering/PWGEM/EMPhotonFilterQC.cxx +++ b/EventFiltering/PWGEM/EMPhotonFilterQC.cxx @@ -12,18 +12,31 @@ // \brief Quick QC task for CEFP for EM photon // \author daiki.sekihata@cern.ch -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/CaloClusters.h" -#include "DataFormatsPHOS/TriggerRecord.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" #include "EventFiltering/filterTables.h" -#include "Framework/HistogramRegistry.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::soa; diff --git a/EventFiltering/PWGEM/HeavyNeutralMesonFilter.cxx b/EventFiltering/PWGEM/HeavyNeutralMesonFilter.cxx index 013bee26a88..763b3a70bb2 100644 --- a/EventFiltering/PWGEM/HeavyNeutralMesonFilter.cxx +++ b/EventFiltering/PWGEM/HeavyNeutralMesonFilter.cxx @@ -14,6 +14,7 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt; Maximilian Korwieser (maximilian.korwieser@cern.ch) - Technical University Munich /// +#include "Common/CCDB/EventSelectionParams.h" #include "EventFiltering/filterTables.h" // #include "PWGEM/PhotonMeson/Utils/HNMUtilities.h" @@ -44,7 +45,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include @@ -136,6 +137,9 @@ struct HeavyNeutralMesonFilter { Configurable confEvtSelectZvtx{"confEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; Configurable confEvtZvtx{"confEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; Configurable confEvtRequireSel8{"confEvtRequireSel8", false, "Evt sel: check for offline selection (sel8)"}; + Configurable confEvtRequireTVX{"confEvtRequireTVX", false, "Evt sel: require the TVX trigger"}; + Configurable confEvtRequireNoTFBorder{"confEvtRequireNoTFBorder", false, "Evt sel: exclude time frame border edges"}; + Configurable confEvtRequireNoITSROFBorder{"confEvtRequireNoITSROFBorder", false, "Evt sel: exclude ITS readout frame border edges"}; // ---> Track selection Configurable> cfgPtCuts{"cfgPtCuts", {hnmtrigger::ptcutsTable[0], hnmtrigger::kNFemtoPartners, 3, hnmtrigger::speciesName, hnmtrigger::pTCutsName}, "Track pT selections"}; @@ -276,6 +280,12 @@ struct HeavyNeutralMesonFilter { return false; if (confEvtRequireSel8 && !col.sel8()) return false; + if (confEvtRequireTVX && !col.selection_bit(aod::evsel::kIsTriggerTVX)) + return false; + if (confEvtRequireNoTFBorder && !col.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return false; + if (confEvtRequireNoITSROFBorder && !col.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return false; return true; } diff --git a/EventFiltering/PWGEM/globalDimuonFilter.cxx b/EventFiltering/PWGEM/globalDimuonFilter.cxx new file mode 100644 index 00000000000..be71fc72cd6 --- /dev/null +++ b/EventFiltering/PWGEM/globalDimuonFilter.cxx @@ -0,0 +1,1294 @@ +// 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 software trigger for global dimuons +// \author daiki.sekihata@cern.ch + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "EventFiltering/filterTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::aod::fwdtrackutils; + +struct globalDimuonFilter { + Produces tags; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable minNmuon{"minNmuon", 2, "min number of global muon candidates per collision"}; + + struct : ConfigurableGroup { + std::string prefix = "eventCutGroup"; + Configurable minZvtx{"minZvtx", -11.f, "min. Zvtx of collision"}; + Configurable maxZvtx{"maxZvtx", +11.f, "max. Zvtx of collision"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border"}; + } eventCutGroup; + + struct : ConfigurableGroup { + std::string prefix = "glMuonCutGroup"; + Configurable minPt{"minPt", 0.01, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEta{"minEta", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEta{"maxEta", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 17.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 0.2, "max. DCAxy for global muons"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 100.f, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 20, "max. chi2/ndf for global muon"}; + Configurable maxChi2MFT{"maxChi2MFT", 1e+10, "max. chi2/ndf for MFTsa"}; + Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable maxDEta{"maxDEta", 0.15, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 0.15, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } glMuonCutGroup; + + struct : ConfigurableGroup { // tight cut + std::string prefix = "tagMuonCutGroup"; + Configurable minPt{"minPt", 0.4, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEta{"minEta", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEta{"maxEta", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 27.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 0.06, "max. DCAxy for global muons"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 40.f, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 4.f, "max. chi2/ndf for global muon"}; + Configurable maxChi2MFT{"maxChi2MFT", 4.f, "max. chi2/ndf for MFTsa"}; + Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable maxDEta{"maxDEta", 0.08, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 0.08, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } tagMuonCutGroup; + + struct : ConfigurableGroup { // loose cut + std::string prefix = "probeMuonCutGroup"; + Configurable minPt{"minPt", 0.01, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEta{"minEta", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEta{"maxEta", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 17.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 1e+10, "max. DCAxy for global muons"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 1e+10, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 1e+10, "max. chi2/ndf for global muon"}; + Configurable maxChi2MFT{"maxChi2MFT", 1e+10, "max. chi2/ndf for MFTsa"}; + Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable maxDEta{"maxDEta", 1e+10, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 1e+10, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } probeMuonCutGroup; + + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber = 0; + float mBz = 0; + float mZShift = 0; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + mRunNumber = 0; + mBz = 0; + mZShift = 0; + + addHistograms(); + } + + template + void initCCDB(TBC 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(); + const double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + mBz = field->getBz(centerMFT); // Get field at centre of MFT + LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } + } + + void addHistograms() + { + auto hCollisionCounter{std::get>(fRegistry.add("hCollisionCounter", "Number of collisions", HistType::kTH1D, {{10, 0.5, 10.5}}))}; + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "TVX"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "No TFB"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "No ITS ROFB"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "|Z_{vtx}| < 10 cm"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "MB"); + hCollisionCounter->GetXaxis()->SetBinLabel(8, "MB && global dimuon"); + hCollisionCounter->GetXaxis()->SetBinLabel(9, "MB && global dimuon for QA"); + + fRegistry.add("hNmu", "#mu multiplicity;N_{#mu}^{global} candidates per collision", kTH1D, {{11, -0.5, 10.5}}, false); + + fRegistry.add("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1D, {{200, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2D, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2D, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/hDEtaDPhi", "#Delta#eta vs. #Delta#varphi;#Delta#varphi (rad.);#Delta#eta", kTH2D, {{90, -M_PI / 4, M_PI / 4}, {100, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hSign", "sign;sign", kTH1D, {{3, -1.5, +1.5}}, false); + fRegistry.add("MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1D, {{21, -0.5f, 20.5}}, false); + fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1D, {{11, -0.5f, 10.5}}, false); + fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1D, {{200, 0, 100}}, false); + fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2D, {{200, 0, 100}, {100, 0, 1000}}, false); + fRegistry.add("MFTMCHMID/hChi2", "chi2;#chi^{2}/ndf", kTH1D, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;#chi^{2} MFT/ndf", kTH1D, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;matching #chi^{2}/ndf between MCH-MID", kTH1D, {{200, 0.0f, 20}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;matching #chi^{2}/ndf between MFT-MCH", kTH1D, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2D, {{400, -1, 1}, {400, -1, +1}}, false); + fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2D, {{200, -10, 10}, {200, -10, +10}}, false); + fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1D, {{100, 0, 1}}, false); + fRegistry.add("MFTMCHMID/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2D, {{100, 0, 1}, {200, -0.1, 0.1}}, false); + fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1D, {{100, 0, 10}}, false); + fRegistry.add("MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} resolution vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2D, {{100, 0, 10.f}, {500, 0, 500}}, false); + fRegistry.add("MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} resolution vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2D, {{100, 0, 10.f}, {500, 0, 500}}, false); + fRegistry.add("MFTMCHMID/hDCAxyResolutionvsPt", "DCA_{xy} resolution vs. p_{T};p_{T} (GeV/c);DCA_{xy} resolution (#mum);", kTH2D, {{100, 0, 10.f}, {500, 0, 500}}, false); + fRegistry.add("MFTMCHMID/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hdR_Chi2MatchMCHMFT", "dr vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;#DeltaR", kTH2F, {{200, 0, 50}, {200, 0, 0.5}}, false); + fRegistry.add("MFTMCHMID/hdR_Chi2", "dr vs. chi2;global chi2/ndf;#DeltaR", kTH2F, {{100, 0, 10}, {200, 0, 0.5}}, false); + fRegistry.add("MFTMCHMID/hChi2_Chi2MatchMCHMFT", "chi2 vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;global chi2/ndf", kTH2F, {{200, 0, 50}, {100, 0, 10}}, false); + + const AxisSpec axisMll{{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.50, 5.00, 5.50, 6.00, 6.50, 7.00, 7.50, 8.00, 8.1, 8.2, 8.3, 8.4, 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.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0}, "m_{#mu#mu} (GeV/c^{2})"}; + const AxisSpec axisPtll{{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.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "p_{T,#mu#mu} (GeV/c)"}; + const AxisSpec axisYll{40, -4.0, -2.0, "y_{#mu#mu}"}; + + fRegistry.add("Pair/same/uls/hs", "dimuon", kTHnSparseD, {axisMll, axisPtll, axisYll}, false); + fRegistry.add("Pair/same/lspp/hs", "dimuon", kTHnSparseD, {axisMll, axisPtll, axisYll}, false); + fRegistry.add("Pair/same/lsmm/hs", "dimuon", kTHnSparseD, {axisMll, axisPtll, axisYll}, false); + + const AxisSpec axisMllLMR{{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.01, 2.02, 2.03, 2.04, 2.05, 2.06, 2.07, 2.08, 2.09, 2.10, 2.11, 2.12, 2.13, 2.14, 2.15, 2.16, 2.17, 2.18, 2.19, 2.20, 2.21, 2.22, 2.23, 2.24, 2.25, 2.26, 2.27, 2.28, 2.29, 2.30, 2.31, 2.32, 2.33, 2.34, 2.35, 2.36, 2.37, 2.38, 2.39, 2.40, 2.41, 2.42, 2.43, 2.44, 2.45, 2.46, 2.47, 2.48, 2.49, 2.50, 2.51, 2.52, 2.53, 2.54, 2.55, 2.56, 2.57, 2.58, 2.59, 2.60, 2.61, 2.62, 2.63, 2.64, 2.65, 2.66, 2.67, 2.68, 2.69, 2.70, 2.71, 2.72, 2.73, 2.74, 2.75, 2.76, 2.77, 2.78, 2.79, 2.80, 2.81, 2.82, 2.83, 2.84, 2.85, 2.86, 2.87, 2.88, 2.89, 2.90, 2.91, 2.92, 2.93, 2.94, 2.95, 2.96, 2.97, 2.98, 2.99, 3.00, 3.01, 3.02, 3.03, 3.04, 3.05, 3.06, 3.07, 3.08, 3.09, 3.10, 3.11, 3.12, 3.13, 3.14, 3.15, 3.16, 3.17, 3.18, 3.19, 3.20, 3.21, 3.22, 3.23, 3.24, 3.25, 3.26, 3.27, 3.28, 3.29, 3.30, 3.31, 3.32, 3.33, 3.34, 3.35, 3.36, 3.37, 3.38, 3.39, 3.40, 3.41, 3.42, 3.43, 3.44, 3.45, 3.46, 3.47, 3.48, 3.49, 3.50, 3.51, 3.52, 3.53, 3.54, 3.55, 3.56, 3.57, 3.58, 3.59, 3.60, 3.61, 3.62, 3.63, 3.64, 3.65, 3.66, 3.67, 3.68, 3.69, 3.70, 3.71, 3.72, 3.73, 3.74, 3.75, 3.76, 3.77, 3.78, 3.79, 3.80, 3.81, 3.82, 3.83, 3.84, 3.85, 3.86, 3.87, 3.88, 3.89, 3.90, 3.91, 3.92, 3.93, 3.94, 3.95, 3.96, 3.97, 3.98, 3.99, 4.00}, "m_{#mu#mu} (GeV/c^{2})"}; + const AxisSpec axisPt{{0, 0.05, 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, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "p_{T,#mu} (GeV/c)"}; + const AxisSpec axisEta{40, -4.0, -2.0, "#eta_{#mu}"}; + const AxisSpec axisPhi{36, 0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; + const AxisSpec axisDEta{100, -0.5, 0.5, "#Delta#eta"}; + const AxisSpec axisDPhi{90, -M_PI / 4, M_PI / 4, "#Delta#varphi (rad.)"}; + const AxisSpec axisDCAxy{100, 0, 1, "DCA_{xy} (cm)"}; + const AxisSpec axisChi2{200, 0, 20, "global #chi^{2}/ndf"}; + const AxisSpec axisChi2MFT{100, 0, 10, "MFTsa #chi^{2}/ndf"}; + const AxisSpec axisChi2MFTMCH{100, 0, 100, "matching #chi^{2}/ndf between MFT-MCH"}; + const AxisSpec axisPDCA{100, 0, 1000, "p #times DCA_{xy} (GeV/c #upoint cm)"}; + const AxisSpec axisRabs{150, 15, 90, "R_{xy} at absorber end (cm)"}; + const AxisSpec axisNclsMCH{21, -0.5, 20.5, "N_{cls}^{MCH}"}; + const AxisSpec axisNclsMFT{11, -0.5, 10.5, "N_{cls}^{MFT}"}; + + // for track cut efficiency with tag and probe + fRegistry.add("TAP/same/uls/hs", "dimuon for T&P", kTHnSparseD, {axisMllLMR, axisPt, axisEta, axisPhi, axisDEta, axisDPhi, axisDCAxy, axisChi2, axisChi2MFT, axisChi2MFTMCH, axisPDCA, axisRabs, axisNclsMCH, axisNclsMFT}, false); + fRegistry.add("TAP/same/lspp/hs", "dimuon for T&P", kTHnSparseD, {axisMllLMR, axisPt, axisEta, axisPhi, axisDEta, axisDPhi, axisDCAxy, axisChi2, axisChi2MFT, axisChi2MFTMCH, axisPDCA, axisRabs, axisNclsMCH, axisNclsMFT}, false); + fRegistry.add("TAP/same/lsmm/hs", "dimuon for T&P", kTHnSparseD, {axisMllLMR, axisPt, axisEta, axisPhi, axisDEta, axisDPhi, axisDCAxy, axisChi2, axisChi2MFT, axisChi2MFTMCH, axisPDCA, axisRabs, axisNclsMCH, axisNclsMFT}, false); + } + + std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; + + template + void findBestMatchPerMCHMID(TCollision const&, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&) + { + // make a unordered_map : globalIndex of global muon -> boolean isSelected. + + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + return; + } + + const auto& muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); + // LOGF(info, "stanadalone: muon.globalIndex() = %d, muon.chi2MatchMCHMFT() = %f", muon.globalIndex(), muon.chi2MatchMCHMFT()); + // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); + + // o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, glMuonCutGroup.matchingZ, mBz, mZShift); + // float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + // float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + // o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + float min_chi2MatchMCHMFT = 1e+10; + std::tuple tupleIds_at_min_chi2mftmch; + for (const auto& muon_tmp : muons_per_MCHMID) { + if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // auto tupleId = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); + // auto mchtrack = muon_tmp.template matchMCHTrack_as(); // MCH-MID + // auto mfttrack = muon_tmp.template matchMFTTrack_as(); // MFTsa + + // o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon_tmp, muon_tmp, collision, propagationPoint::kToVertex, glMuonCutGroup.matchingZ, mBz, mZShift); + // float eta = propmuonAtPV.getEta(); + // float phi = propmuonAtPV.getPhi(); + // o2::math_utils::bringTo02Pi(phi); + + // float deta = etaMatchedMCHMID - eta; + // float dphi = phiMatchedMCHMID - phi; + // o2::math_utils::bringToPMPi(dphi); + // float dr = std::sqrt(deta * deta + dphi * dphi); + + // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { + min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); + tupleIds_at_min_chi2mftmch = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); + } + } + } + vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min_chi2mftmch); + // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); + } + + template + int countMatchedCandidatesPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const& mfttracks) + { + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + return -1; + } + + int nGoodGLPerSA = 0; + auto muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); + for (const auto& muon_tmp : muons_per_MCHMID) { + if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + float pt = 999.f, eta = 999.f, phi = 999.f; + if (isSelectedGlobalMuon(collision, muon_tmp, fwdtracks, mfttracks, pt, eta, phi)) { + nGoodGLPerSA++; + } + } + } + return nGoodGLPerSA; + } + + PresliceUnsorted perMFTTrack = o2::aod::fwdtrack::matchMFTTrackId; + template + bool isBestMatch(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const& mfttracks) + { + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + std::map map_chi2MCHMFT; + map_chi2MCHMFT[fwdtrack.globalIndex()] = fwdtrack.chi2MatchMCHMFT(); // add myself + // LOGF(info, "add myself: fwdtrack.globalIndex() = %d, fwdtrack.chi2MatchMCHMFT() = %f", fwdtrack.globalIndex(), fwdtrack.chi2MatchMCHMFT()); + + auto candidates = fwdtracks.sliceBy(perMFTTrack, fwdtrack.matchMFTTrackId()); // global muon candidates including this fwdtrack. + for (const auto& candidate : candidates) { + if (candidate.globalIndex() == fwdtrack.globalIndex()) { + continue; // don't add fwdtrack.globalIndex() again. + } + + float pt = 999.f, eta = 999.f, phi = 999.f; + if (isSelectedGlobalMuon(collision, candidate, fwdtracks, mfttracks, pt, eta, phi)) { + map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); + // LOGF(info, "same MFT found: candidate.globalIndex() = %d, candidate.chi2MatchMCHMFT() = %f", candidate.globalIndex(), candidate.chi2MatchMCHMFT()); + } + } + + auto it = std::min_element(map_chi2MCHMFT.begin(), map_chi2MCHMFT.end(), [](decltype(map_chi2MCHMFT)::value_type& l, decltype(map_chi2MCHMFT)::value_type& r) -> bool { return l.second < r.second; }); + + // LOGF(info, "min: globalIndex = %d, chi2 = %f", it->first, it->second); + // LOGF(info, "bool = %d", it->first == fwdtrack.globalIndex()); + + if (it->first == fwdtrack.globalIndex()) { // search for minimum matching-chi2 + map_chi2MCHMFT.clear(); + return true; + } else { + map_chi2MCHMFT.clear(); + return false; + } + } else { + return true; + } + } + + template + bool isSelectedGlobalMuon(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const&, TMFTTracks const&, float& pt, float& eta, float& phi) + { + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + return false; + } + + if (fwdtrack.chi2MatchMCHMFT() > glMuonCutGroup.maxMatchingChi2MCHMFT) { + return false; + } + + if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return false; + } + + if (fwdtrack.rAtAbsorberEnd() < glMuonCutGroup.minRabs || glMuonCutGroup.maxRabs < fwdtrack.rAtAbsorberEnd()) { + return false; + } + + auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + + if (mfttrack.nClusters() < glMuonCutGroup.minNclsMFT) { + return false; + } + if (mchtrack.nClusters() < glMuonCutGroup.minNclsMCH) { + return false; + } + + float rAtAbsorberEnd = fwdtrack.rAtAbsorberEnd(); // this works only for GlobalMuonTrack + int nClustersMFT = mfttrack.nClusters(); + int ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; + float chi2 = fwdtrack.chi2() / ndf_mchmft; + if (glMuonCutGroup.maxChi2 < chi2) { + return false; + } + + int ndf_mft = 2.f * nClustersMFT - 5.f; + float chi2mft = mfttrack.chi2() / ndf_mft; + if (glMuonCutGroup.maxChi2MFT < chi2mft) { + return false; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, glMuonCutGroup.matchingZ, mBz, mZShift); + // float ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, glMuonCutGroup.matchingZ, mBz, mZShift); + pt = propmuonAtPV.getPt(); + eta = propmuonAtPV.getEta(); + phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + if (glMuonCutGroup.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + if (std::sqrt(std::pow(deta / glMuonCutGroup.maxDEta, 2) + std::pow(dphi / glMuonCutGroup.maxDPhi, 2)) > 1.f) { + return false; + } + + float dr = std::sqrt(deta * deta + dphi * dphi); + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaZ = propmuonAtPV.getZ() - collision.posZ(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + float cXX = propmuonAtPV.getSigma2X(); + float cYY = propmuonAtPV.getSigma2Y(); + float cXY = propmuonAtPV.getSigmaXY(); + if (glMuonCutGroup.maxDCAxy < dcaXY) { + return false; + } + + float det = cXX * cYY - cXY * cXY; // determinanat + float dcaXYinSigma = 999.f; + if (det < 0) { + dcaXYinSigma = 999.f; + } else { + dcaXYinSigma = std::sqrt(std::fabs((dcaX * dcaX * cYY + dcaY * dcaY * cXX - 2.f * dcaX * dcaY * cXY) / det / 2.f)); // dca xy in sigma + } + float sigma_dcaXY = dcaXY / dcaXYinSigma; + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, glMuonCutGroup.matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = mchtrack.p() * dcaXY_Matched; + + if (pt < glMuonCutGroup.minPt || glMuonCutGroup.maxPt < pt) { + return false; + } + + if (eta < glMuonCutGroup.minEta || glMuonCutGroup.maxEta < eta) { + return false; + } + + if constexpr (fillHistograms) { + fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); + fRegistry.fill(HIST("MFTMCHMID/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFTMCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + fRegistry.fill(HIST("MFTMCHMID/hDEtaDPhi"), dphi, deta); + fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); + fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); + fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); + fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + fRegistry.fill(HIST("MFTMCHMID/hChi2"), chi2); + fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MFTMCHMID/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("MFTMCHMID/hDCAxyinSigma"), dcaXYinSigma); + fRegistry.fill(HIST("MFTMCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + fRegistry.fill(HIST("MFTMCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + fRegistry.fill(HIST("MFTMCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + fRegistry.fill(HIST("MFTMCHMID/hDCAx_PosZ"), collision.posZ(), dcaX); + fRegistry.fill(HIST("MFTMCHMID/hDCAy_PosZ"), collision.posZ(), dcaY); + fRegistry.fill(HIST("MFTMCHMID/hDCAx_Phi"), phi, dcaX); + fRegistry.fill(HIST("MFTMCHMID/hDCAy_Phi"), phi, dcaY); + fRegistry.fill(HIST("MFTMCHMID/hdR_Chi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT(), dr); + fRegistry.fill(HIST("MFTMCHMID/hdR_Chi2"), chi2, dr); + fRegistry.fill(HIST("MFTMCHMID/hChi2_Chi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT(), chi2); + } + + return true; + } + + template + bool isTaggedMuon(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const&, TMFTTracks const&, TMFTCovs const&, float& pt, float& eta, float& phi) + { + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + return false; + } + + if (std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + return false; + } + + if (fwdtrack.chi2MatchMCHMFT() > tagMuonCutGroup.maxMatchingChi2MCHMFT) { + return false; + } + + if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return false; + } + + if (fwdtrack.rAtAbsorberEnd() < tagMuonCutGroup.minRabs || tagMuonCutGroup.maxRabs < fwdtrack.rAtAbsorberEnd()) { + return false; + } + + auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + if (mfttrack.nClusters() < tagMuonCutGroup.minNclsMFT) { + return false; + } + if (mchtrack.nClusters() < tagMuonCutGroup.minNclsMCH) { + return false; + } + + int nClustersMFT = mfttrack.nClusters(); + int ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; + float chi2 = fwdtrack.chi2() / ndf_mchmft; + if (tagMuonCutGroup.maxChi2 < chi2) { + return false; + } + + int ndf_mft = 2.f * nClustersMFT - 5.f; + float chi2mft = mfttrack.chi2() / ndf_mft; + if (tagMuonCutGroup.maxChi2MFT < chi2mft) { + return false; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, tagMuonCutGroup.matchingZ, mBz, mZShift); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, tagMuonCutGroup.matchingZ, mBz, mZShift); + pt = propmuonAtPV.getPt(); + eta = propmuonAtPV.getEta(); + phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + if (tagMuonCutGroup.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + + if (std::sqrt(std::pow(deta / tagMuonCutGroup.maxDEta, 2) + std::pow(dphi / tagMuonCutGroup.maxDPhi, 2)) > 1.f) { + return false; + } + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + if (tagMuonCutGroup.maxDCAxy < dcaXY) { + return false; + } + // float cXX = propmuonAtPV.getSigma2X(); + // float cYY = propmuonAtPV.getSigma2Y(); + // float cXY = propmuonAtPV.getSigmaXY(); + + // float det = cXX * cYY - cXY * cXY; // determinanat + // float dcaXYinSigma = 999.f; + // if (det < 0) { + // dcaXYinSigma = 999.f; + // } else { + // dcaXYinSigma = std::sqrt(std::fabs((dcaX * dcaX * cYY + dcaY * dcaY * cXX - 2.f * dcaX * dcaY * cXY) / det / 2.f)); // dca xy in sigma + // } + // float sigma_dcaXY = dcaXY / dcaXYinSigma; + + // o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, tagMuonCutGroup.matchingZ, mBz); + // float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + // float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + // float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + // float pDCA = mchtrack.p() * dcaXY_Matched; + + if (pt < tagMuonCutGroup.minPt || tagMuonCutGroup.maxPt < pt) { + return false; + } + + if (eta < tagMuonCutGroup.minEta || tagMuonCutGroup.maxEta < eta) { + return false; + } + + return true; + } + + template + bool isProbeMuon(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const&, TMFTTracks const&, TMFTCovs const&, float& pt, float& eta, float& phi, float& deta, float& dphi, float& dcaXY, float& chi2, float& chi2mft, float& chi2MFTMCH, float& pDCA, float& rAtAbsorberEnd, int& nclsMCH, int& nclsMFT) + { + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + return false; + } + + if (std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + return false; + } + + if (fwdtrack.chi2MatchMCHMFT() > probeMuonCutGroup.maxMatchingChi2MCHMFT) { + return false; + } + + if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return false; + } + + if (fwdtrack.rAtAbsorberEnd() < probeMuonCutGroup.minRabs || probeMuonCutGroup.maxRabs < fwdtrack.rAtAbsorberEnd()) { + return false; + } + rAtAbsorberEnd = fwdtrack.rAtAbsorberEnd(); + chi2MFTMCH = fwdtrack.chi2MatchMCHMFT(); + + auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + if (mfttrack.nClusters() < probeMuonCutGroup.minNclsMFT) { + return false; + } + if (mchtrack.nClusters() < probeMuonCutGroup.minNclsMCH) { + return false; + } + + nclsMCH = mchtrack.nClusters(); + nclsMFT = mfttrack.nClusters(); + int ndf_mchmft = 2.f * (nclsMCH + nclsMFT) - 5.f; + chi2 = fwdtrack.chi2() / ndf_mchmft; + if (probeMuonCutGroup.maxChi2 < chi2) { + return false; + } + + int ndf_mft = 2.f * nclsMFT - 5.f; + chi2mft = mfttrack.chi2() / ndf_mft; + if (probeMuonCutGroup.maxChi2MFT < chi2mft) { + return false; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, probeMuonCutGroup.matchingZ, mBz, mZShift); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, probeMuonCutGroup.matchingZ, mBz, mZShift); + pt = propmuonAtPV.getPt(); + eta = propmuonAtPV.getEta(); + phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + if (probeMuonCutGroup.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + deta = etaMatchedMCHMID - eta; + dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + + if (std::sqrt(std::pow(deta / probeMuonCutGroup.maxDEta, 2) + std::pow(dphi / probeMuonCutGroup.maxDPhi, 2)) > 1.f) { + return false; + } + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + if (probeMuonCutGroup.maxDCAxy < dcaXY) { + return false; + } + // float cXX = propmuonAtPV.getSigma2X(); + // float cYY = propmuonAtPV.getSigma2Y(); + // float cXY = propmuonAtPV.getSigmaXY(); + + // float det = cXX * cYY - cXY * cXY; // determinanat + // float dcaXYinSigma = 999.f; + // if (det < 0) { + // dcaXYinSigma = 999.f; + // } else { + // dcaXYinSigma = std::sqrt(std::fabs((dcaX * dcaX * cYY + dcaY * dcaY * cXX - 2.f * dcaX * dcaY * cXY) / det / 2.f)); // dca xy in sigma + // } + // float sigma_dcaXY = dcaXY / dcaXYinSigma; + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, probeMuonCutGroup.matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + pDCA = mchtrack.p() * dcaXY_Matched; + + if (pt < probeMuonCutGroup.minPt || probeMuonCutGroup.maxPt < pt) { + return false; + } + + if (eta < probeMuonCutGroup.minEta || probeMuonCutGroup.maxEta < eta) { + return false; + } + + return true; + } + + template + void runPairing(TCollision const& collision, TMuons const& posMuons, TMuons const& negMuons, TFwdTracks const& fwdtracks, TMFTTracks const& mfttracks, TMFTCovs const&) + { + for (const auto& pos : posMuons) { + auto v1 = std::get<1>(pos); + auto fwdtrack1 = fwdtracks.rawIteratorAt(std::get<0>(pos)); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + + for (const auto& neg : negMuons) { + auto v2 = std::get<1>(neg); + auto fwdtrack2 = fwdtracks.rawIteratorAt(std::get<0>(neg)); + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + + auto v12 = v1 + v2; + fRegistry.fill(HIST("Pair/same/uls/hs"), v12.M(), v12.Pt(), v12.Rapidity()); + + } // end end of negative muon loop + } // end end of positive muon loop + + for (int i1 = 0; i1 < static_cast(posMuons.size()) - 1; i1++) { + auto pos1 = posMuons[i1]; + auto v1 = std::get<1>(pos1); + auto fwdtrack1 = fwdtracks.rawIteratorAt(std::get<0>(pos1)); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + + for (int i2 = i1 + 1; i2 < static_cast(posMuons.size()); i2++) { + auto pos2 = posMuons[i2]; + auto v2 = std::get<1>(pos2); + auto fwdtrack2 = fwdtracks.rawIteratorAt(std::get<0>(pos2)); + // if (std::get<0>(pos1) == std::get<0>(pos2)) { + // continue; + // } + + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + + auto v12 = v1 + v2; + fRegistry.fill(HIST("Pair/same/lspp/hs"), v12.M(), v12.Pt(), v12.Rapidity()); + } // end end of positive muon loop + } // end end of positive muon loop + + for (int i1 = 0; i1 < static_cast(negMuons.size()) - 1; i1++) { + auto neg1 = negMuons[i1]; + auto v1 = std::get<1>(neg1); + auto fwdtrack1 = fwdtracks.rawIteratorAt(std::get<0>(neg1)); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + + for (int i2 = i1 + 1; i2 < static_cast(negMuons.size()); i2++) { + auto neg2 = negMuons[i2]; + auto v2 = std::get<1>(neg2); + auto fwdtrack2 = fwdtracks.rawIteratorAt(std::get<0>(neg2)); + // if (std::get<0>(neg1) == std::get<0>(neg2)) { + // continue; + // } + + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + + auto v12 = v1 + v2; + fRegistry.fill(HIST("Pair/same/lsmm/hs"), v12.M(), v12.Pt(), v12.Rapidity()); + } // end end of negative muon loop + } // end end of negative muon loop + } + + template + void runTAP(TCollision const& collision, TMuons const& posMuons, TMuons const& negMuons, TFwdTracks const& fwdtracks, TMFTTracks const& mfttracks, TMFTCovs const& mftCovs) + { + // pos is tag, neg is probe + for (const auto& pos : posMuons) { + auto fwdtrack1 = fwdtracks.rawIteratorAt(pos); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + float pt1 = 999.f, eta1 = 999.f, phi1 = 999.f; + if (!isTaggedMuon(collision, fwdtrack1, fwdtracks, mfttracks, mftCovs, pt1, eta1, phi1)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, o2::constants::physics::MassMuon); + + for (const auto& neg : negMuons) { + auto fwdtrack2 = fwdtracks.rawIteratorAt(neg); + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + + float pt2 = 999.f, eta2 = 999.f, phi2 = 999.f; + float deta = 999.f, dphi = 999.f, dcaXY = 999.f, chi2 = 999.f, chi2MFT = 999.f, chi2MFTMCH = 999.f, pDCA = 999.f, rAtAbsorberEnd = 999.f; + int nclsMCH = 0, nclsMFT = 0; + if (!isProbeMuon(collision, fwdtrack2, fwdtracks, mfttracks, mftCovs, pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, o2::constants::physics::MassMuon); + + auto v12 = v1 + v2; + fRegistry.fill(HIST("TAP/same/uls/hs"), v12.M(), pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT); + + } // end end of negative muon loop + } // end end of positive muon loop + + // neg is tag, pos is probe + for (const auto& neg : negMuons) { + auto fwdtrack1 = fwdtracks.rawIteratorAt(neg); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + float pt1 = 999, eta1 = 999, phi1 = 999; + if (!isTaggedMuon(collision, fwdtrack1, fwdtracks, mfttracks, mftCovs, pt1, eta1, phi1)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, o2::constants::physics::MassMuon); + + for (const auto& pos : posMuons) { + auto fwdtrack2 = fwdtracks.rawIteratorAt(pos); + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + + float pt2 = 999, eta2 = 999, phi2 = 999; + float deta = 999.f, dphi = 999.f, dcaXY = 999.f, chi2 = 999.f, chi2MFT = 999.f, chi2MFTMCH = 999.f, pDCA = 999.f, rAtAbsorberEnd = 999.f; + int nclsMCH = 0, nclsMFT = 0; + if (!isProbeMuon(collision, fwdtrack2, fwdtracks, mfttracks, mftCovs, pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, o2::constants::physics::MassMuon); + + auto v12 = v1 + v2; + fRegistry.fill(HIST("TAP/same/uls/hs"), v12.M(), pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT); + + } // end end of negative muon loop + } // end end of positive muon loop + + for (const auto pos1 : posMuons) { + auto fwdtrack1 = fwdtracks.rawIteratorAt(pos1); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + float pt1 = 999, eta1 = 999, phi1 = 999; + if (!isTaggedMuon(collision, fwdtrack1, fwdtracks, mfttracks, mftCovs, pt1, eta1, phi1)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, o2::constants::physics::MassMuon); + + for (const auto pos2 : posMuons) { + auto fwdtrack2 = fwdtracks.rawIteratorAt(pos2); + if (pos1 == pos2) { + continue; + } + + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + float pt2 = 999, eta2 = 999, phi2 = 999; + float deta = 999.f, dphi = 999.f, dcaXY = 999.f, chi2 = 999.f, chi2MFT = 999.f, chi2MFTMCH = 999.f, pDCA = 999.f, rAtAbsorberEnd = 999.f; + int nclsMCH = 0, nclsMFT = 0; + if (!isProbeMuon(collision, fwdtrack2, fwdtracks, mfttracks, mftCovs, pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, o2::constants::physics::MassMuon); + + auto v12 = v1 + v2; + fRegistry.fill(HIST("TAP/same/lspp/hs"), v12.M(), pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT); + } // end end of positive muon loop + } // end end of positive muon loop + + for (const auto neg1 : negMuons) { + auto fwdtrack1 = fwdtracks.rawIteratorAt(neg1); + if (!isBestMatch(collision, fwdtrack1, fwdtracks, mfttracks)) { + continue; + } + float pt1 = 999, eta1 = 999, phi1 = 999; + if (!isTaggedMuon(collision, fwdtrack1, fwdtracks, mfttracks, mftCovs, pt1, eta1, phi1)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(pt1, eta1, phi1, o2::constants::physics::MassMuon); + + for (const auto neg2 : negMuons) { + auto fwdtrack2 = fwdtracks.rawIteratorAt(neg2); + if (neg1 == neg2) { + continue; + } + + if (!isBestMatch(collision, fwdtrack2, fwdtracks, mfttracks)) { + continue; + } + float pt2 = 999, eta2 = 999, phi2 = 999; + float deta = 999.f, dphi = 999.f, dcaXY = 999.f, chi2 = 999.f, chi2MFT = 999.f, chi2MFTMCH = 999.f, pDCA = 999.f, rAtAbsorberEnd = 999.f; + int nclsMCH = 0, nclsMFT = 0; + if (!isProbeMuon(collision, fwdtrack2, fwdtracks, mfttracks, mftCovs, pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v2(pt2, eta2, phi2, o2::constants::physics::MassMuon); + + auto v12 = v1 + v2; + fRegistry.fill(HIST("TAP/same/lsmm/hs"), v12.M(), pt2, eta2, phi2, deta, dphi, dcaXY, chi2, chi2MFT, chi2MFTMCH, pDCA, rAtAbsorberEnd, nclsMCH, nclsMFT); + } // end end of negative muon loop + } // end end of negative muon loop + } + + template + bool isSelectedCollision(TCollision const& collision) + { + if (!(eventCutGroup.minZvtx < collision.posZ() && collision.posZ() < eventCutGroup.maxZvtx)) { + return false; + } + if (eventCutGroup.cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + if (eventCutGroup.cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (eventCutGroup.cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + return true; + } + + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; + + using MyBCs = soa::Join; + using MyBC = MyBCs::iterator; + + using MyFwdTracks = soa::Join; // muon tracks are repeated. i.e. not exclusive. + using MyFwdTrack = MyFwdTracks::iterator; + + SliceCache cache; + Preslice perCollision = o2::aod::fwdtrack::collisionId; + Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; + PresliceUnsorted fwdtrackIndicesPerFwdTrack = aod::track_association::fwdtrackId; + PresliceUnsorted fwdtracksPerMCHTrack = aod::fwdtrack::matchMCHTrackId; + + std::unordered_map map_mfttrackcovs; + std::unordered_map mapSelectedCollisions; + + void processSA(MyCollisions const& collisions, MyBCs const&, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::MFTTracksCov const& mftCovs) + { + for (const auto& mfttrackConv : mftCovs) { + map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + } + + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + fRegistry.fill(HIST("hCollisionCounter"), 1); + + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("hCollisionCounter"), 2); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("hCollisionCounter"), 3); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("hCollisionCounter"), 4); + } + if (eventCutGroup.minZvtx < collision.posZ() && collision.posZ() < eventCutGroup.maxZvtx) { + fRegistry.fill(HIST("hCollisionCounter"), 5); + } + if (collision.sel8()) { + fRegistry.fill(HIST("hCollisionCounter"), 6); + } + + if (isSelectedCollision(collision)) { + fRegistry.fill(HIST("hCollisionCounter"), 7); + + int nGlobalMuon = 0; + // LOGF(info, "collision.globalIndex() = %d, fwdtrackIdsThisCollision = %d", collision.globalIndex(), fwdtrackIdsThisCollision.size()); + auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + // float pt = 999.f, eta = 999.f, phi = 999.f; + // if (isSelectedGlobalMuon(collision, fwdtrack, fwdtracks, mfttracks, pt, eta, phi)) { + // nGlobalMuon++; + // } + + int nGoodGLPerSA = countMatchedCandidatesPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + if (nGoodGLPerSA > 0) { + nGlobalMuon++; + } + } + + // LOGF(info, "nGlobalMuon = %d", nGlobalMuon); + fRegistry.fill(HIST("hNmu"), nGlobalMuon); + + if (nGlobalMuon >= minNmuon) { + fRegistry.fill(HIST("hCollisionCounter"), 8); + mapSelectedCollisions[collision.globalIndex()] = true; + tags(true); + } else { + mapSelectedCollisions[collision.globalIndex()] = false; + tags(false); + } + } else { + mapSelectedCollisions[collision.globalIndex()] = false; + tags(false); + } + } // end of collision loop + + // trigger QA + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!mapSelectedCollisions[collision.globalIndex()]) { + continue; + } + fRegistry.fill(HIST("hCollisionCounter"), 9); + + auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + std::vector> posMuons; + std::vector> negMuons; + posMuons.reserve(fwdtracks_per_coll.size()); + negMuons.reserve(fwdtracks_per_coll.size()); + + for (const auto& fwdtrack : fwdtracks_per_coll) { + float pt = 999.f, eta = 999.f, phi = 999.f; + if (isSelectedGlobalMuon(collision, fwdtrack, fwdtracks, mfttracks, pt, eta, phi)) { + if (fwdtrack.sign() > 0) { + posMuons.emplace_back(std::make_pair(fwdtrack.globalIndex(), ROOT::Math::PtEtaPhiMVector(pt, eta, phi, o2::constants::physics::MassMuon))); + } else { + negMuons.emplace_back(std::make_pair(fwdtrack.globalIndex(), ROOT::Math::PtEtaPhiMVector(pt, eta, phi, o2::constants::physics::MassMuon))); + } + } + } // end of fwdtrack loop + + // make pairs + runPairing(collision, posMuons, negMuons, fwdtracks, mfttracks, mftCovs); + + posMuons.clear(); + posMuons.shrink_to_fit(); + negMuons.clear(); + negMuons.shrink_to_fit(); + } // end of collision loop + + // for TAP + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!isSelectedCollision(collision)) { + continue; + } + + auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + std::vector posProbeMuons; + std::vector negProbeMuons; + posProbeMuons.reserve(fwdtracks_per_coll.size()); + negProbeMuons.reserve(fwdtracks_per_coll.size()); + + for (const auto& fwdtrack : fwdtracks_per_coll) { + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + if (fwdtrack.sign() > 0) { + posProbeMuons.emplace_back(fwdtrack.globalIndex()); + } else { + negProbeMuons.emplace_back(fwdtrack.globalIndex()); + } + } + } // end of fwdtrack loop + + // track cut efficiency + runTAP(collision, posProbeMuons, negProbeMuons, fwdtracks, mfttracks, mftCovs); // currently, select global muons with min matching chi2 MCH-MFT + + posProbeMuons.clear(); + posProbeMuons.shrink_to_fit(); + negProbeMuons.clear(); + negProbeMuons.shrink_to_fit(); + } // end of collision loop + + map_mfttrackcovs.clear(); + mapSelectedCollisions.clear(); + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); + } + PROCESS_SWITCH(globalDimuonFilter, processSA, "process without FTTCA", false); + + void processFTTCA(MyCollisions const& collisions, MyBCs const&, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::MFTTracksCov const& mftCovs, aod::FwdTrackAssoc const& fwdtrackIndices) + { + for (const auto& mfttrackConv : mftCovs) { + map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + } + + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + fRegistry.fill(HIST("hCollisionCounter"), 1); + + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("hCollisionCounter"), 2); + } + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("hCollisionCounter"), 3); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("hCollisionCounter"), 4); + } + if (eventCutGroup.minZvtx < collision.posZ() && collision.posZ() < eventCutGroup.maxZvtx) { + fRegistry.fill(HIST("hCollisionCounter"), 5); + } + if (collision.sel8()) { + fRegistry.fill(HIST("hCollisionCounter"), 6); + } + + if (isSelectedCollision(collision)) { + fRegistry.fill(HIST("hCollisionCounter"), 7); + + int nGlobalMuon = 0; + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // LOGF(info, "collision.globalIndex() = %d, fwdtrackIdsThisCollision = %d", collision.globalIndex(), fwdtrackIdsThisCollision.size()); + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + + // if (std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + // float pt = 999.f, eta = 999.f, phi = 999.f; + // if (isSelectedGlobalMuon(collision, fwdtrack, fwdtracks, mfttracks, pt, eta, phi)) { + // nGlobalMuon++; + // } + + int nGoodGLPerSA = countMatchedCandidatesPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + if (nGoodGLPerSA > 0) { + nGlobalMuon++; + } + } // end of fwdtrack loop + + // LOGF(info, "nGlobalMuon = %d", nGlobalMuon); + fRegistry.fill(HIST("hNmu"), nGlobalMuon); + + if (nGlobalMuon >= minNmuon) { + fRegistry.fill(HIST("hCollisionCounter"), 8); + mapSelectedCollisions[collision.globalIndex()] = true; + tags(true); + } else { + mapSelectedCollisions[collision.globalIndex()] = false; + tags(false); + } + } else { + mapSelectedCollisions[collision.globalIndex()] = false; + tags(false); + } + } // end of collision loop + + // trigger QA + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!mapSelectedCollisions[collision.globalIndex()]) { + continue; + } + fRegistry.fill(HIST("hCollisionCounter"), 9); + + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + std::vector> posMuons; + std::vector> negMuons; + posMuons.reserve(fwdtrackIdsThisCollision.size()); + negMuons.reserve(fwdtrackIdsThisCollision.size()); + + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + if (std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + continue; + } + + float pt = 999.f, eta = 999.f, phi = 999.f; + if (isSelectedGlobalMuon(collision, fwdtrack, fwdtracks, mfttracks, pt, eta, phi)) { + if (fwdtrack.sign() > 0) { + posMuons.emplace_back(std::make_pair(fwdtrack.globalIndex(), ROOT::Math::PtEtaPhiMVector(pt, eta, phi, o2::constants::physics::MassMuon))); + } else { + negMuons.emplace_back(std::make_pair(fwdtrack.globalIndex(), ROOT::Math::PtEtaPhiMVector(pt, eta, phi, o2::constants::physics::MassMuon))); + } + } + } // end of fwdtrack loop + + // make pairs + runPairing(collision, posMuons, negMuons, fwdtracks, mfttracks, mftCovs); + + posMuons.clear(); + posMuons.shrink_to_fit(); + negMuons.clear(); + negMuons.shrink_to_fit(); + } // end of collision loop + + // for TAP + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!isSelectedCollision(collision)) { + continue; + } + + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + std::vector posProbeMuons; + std::vector negProbeMuons; + posProbeMuons.reserve(fwdtrackIdsThisCollision.size()); + negProbeMuons.reserve(fwdtrackIdsThisCollision.size()); + + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + if (fwdtrack.sign() > 0) { + posProbeMuons.emplace_back(fwdtrack.globalIndex()); + } else { + negProbeMuons.emplace_back(fwdtrack.globalIndex()); + } + } + } // end of fwdtrack loop + + // track cut efficiency + runTAP(collision, posProbeMuons, negProbeMuons, fwdtracks, mfttracks, mftCovs); // currently, select global muons with min matching chi2 MCH-MFT + + posProbeMuons.clear(); + posProbeMuons.shrink_to_fit(); + negProbeMuons.clear(); + negProbeMuons.shrink_to_fit(); + } // end of collision loop + + map_mfttrackcovs.clear(); + mapSelectedCollisions.clear(); + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); + } + PROCESS_SWITCH(globalDimuonFilter, processFTTCA, "process with FTTCA", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfg, TaskName{"em-global-dimuon-filter"})}; +} diff --git a/EventFiltering/PWGHF/H2fromLbFilter.cxx b/EventFiltering/PWGHF/H2fromLbFilter.cxx new file mode 100644 index 00000000000..85fc65df1fa --- /dev/null +++ b/EventFiltering/PWGHF/H2fromLbFilter.cxx @@ -0,0 +1,268 @@ +// 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 A filter task for non prompt deuterons +/// \author Marta Razza marta.razza@cern.ch +/// \author Francesca Ercolessi francesca.ercolessi@cern.ch +/// \since Dec 17, 2025 + +#include "../filterTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +struct H2fromLbFilter { + + // Recall the output table + o2::framework::Produces table; + + o2::framework::Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histo"}; + + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + // Define a histograms and registries + o2::framework::HistogramRegistry QAHistos{"QAHistos", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, true}; + o2::framework::OutputObj hProcessedEvents{TH1D("hProcessedEvents", "Event filtered;; Number of events", 6, 0., 6.)}; + + o2::framework::ConfigurableAxis pTAxis{"pTAxis", {200, -10.f, 10.f}, "p_{T} GeV/c"}; + o2::framework::ConfigurableAxis nSigmaAxis{"nSigmaAxis", {200, -10.f, 10.f}, "p_{T} GeV/c"}; + o2::framework::ConfigurableAxis DCAxyAxis{"DCAxyAxis", {1000, -0.2f, 0.2f}, "DCA xy (cm)"}; + o2::framework::ConfigurableAxis DCAzAxis{"DCAzAxis", {1000, -0.2f, 0.2f}, "DCA z (cm)"}; + + o2::framework::Configurable cutzvertex{"cutzvertex", 20.0f, "Accepted z-vertex range"}; // 20 cm + o2::framework::Configurable isTVX{"isTVX", true, "isTVX event selection"}; + o2::framework::Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", true, "isNoTimeFrameBorder event selection"}; + o2::framework::Configurable isNoITSROFrameBorder{"isNoITSROFrameBorder", true, "isNoITSROFrameBorder event selection"}; + o2::framework::Configurable cfgTPCNsigma{"cfgTPCNsigma", 4.0f, "TPC n sigma for deuteron PID"}; + o2::framework::Configurable cfgTOFNsigma{"cfgTOFNsigma", 4.0f, "TOF n sigma for deuteron PID"}; + o2::framework::Configurable cfgITSNsigma{"cfgITSNsigma", -2.0f, "ITS n sigma for deuteron PID"}; + o2::framework::Configurable cfgEta{"cfgEta", 0.8f, "Track eta selection"}; + o2::framework::Configurable cfgTPCNclsFound{"cfgTPCNclsFound", 100, "Minimum TPC clusters found"}; + o2::framework::Configurable cfgTPCChi2Ncl{"cfgTPCChi2Ncl", 4.0f, "Maximum TPC chi2 per N clusters"}; + o2::framework::Configurable cfgITSChi2Ncl{"cfgITSChi2Ncl", 36.0f, "Maximum ITS chi2 per N clusters"}; + o2::framework::Configurable cfgITScls{"cfgITScls", 2, "Minimum ITS clusters"}; + o2::framework::Configurable cfgMaxPt{"cfgMaxPt", 5.0f, "Maximum pT cut"}; + o2::framework::Configurable cfgMinPt{"cfgMinPt", 0.5f, "Minimum pT cut"}; + o2::framework::Configurable cfgDCAcut{"cfgDCAcut", 0.003f, "DCA cut for non prompt deuteron"}; + o2::framework::Configurable ptThresholdPid{"ptThresholdPid", 1.0f, "pT threshold to switch between ITS and TOF PID"}; + + o2::framework::Service ccdb; + + void init(o2::framework::InitContext&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); // Set CCDB URL to get magnetic field + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + + o2::framework::AxisSpec ptAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + + // general QA histograms + QAHistos.add("hVtxZ", "Z-Vertex distribution after selection;Z (cm)", o2::framework::HistType::kTH1F, {{100, -50, 50}}); + QAHistos.add("hDCAxyVsPt", "DCAxy #bar{d} vs p_{T}", {o2::framework::HistType::kTH2D, {pTAxis, DCAxyAxis}}); + QAHistos.add("hDCAzVsPt", "DCAz #bar{d} vs p_{T}", {o2::framework::HistType::kTH2D, {pTAxis, DCAzAxis}}); + QAHistos.add("hnSigmaTPCVsPt", "n#sigma TPC vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TPC", {o2::framework::HistType::kTH2D, {pTAxis, nSigmaAxis}}); + QAHistos.add("hnSigmaTOFVsPt", "n#sigma TOF vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma TOF", {o2::framework::HistType::kTH2D, {pTAxis, nSigmaAxis}}); + QAHistos.add("hnSigmaITSVsPt", "n#sigma ITS vs p_{T} for #bar{d} hypothesis; p_{T} (GeV/c); n#sigma ITS", {o2::framework::HistType::kTH2D, {pTAxis, nSigmaAxis}}); + QAHistos.add("ptAntiDeuteron", "ptAntiDeuteron", {o2::framework::HistType::kTH1F, {ptAxis}}); + QAHistos.add("etaAntideuteron", "etaAntideuteron", {o2::framework::HistType::kTH1F, {{100, -1.0f, 1.0f, "eta #bar{d}"}}}); + QAHistos.add("hDCAxyVsPt-pre_selection", "DCAxy #bar{d} vs p_{T}", {o2::framework::HistType::kTH2D, {pTAxis, DCAxyAxis}}); + QAHistos.add("hDCAzVsPt-pre-selection", "DCAz #bar{d} vs p_{T}", {o2::framework::HistType::kTH2D, {pTAxis, DCAzAxis}}); + + // processed events + hProcessedEvents->GetXaxis()->SetBinLabel(1, "Events processed"); + hProcessedEvents->GetXaxis()->SetBinLabel(2, "TVX"); + hProcessedEvents->GetXaxis()->SetBinLabel(3, "TF border"); + hProcessedEvents->GetXaxis()->SetBinLabel(4, "ITS-RO border"); + hProcessedEvents->GetXaxis()->SetBinLabel(5, "z-vertex"); + hProcessedEvents->GetXaxis()->SetBinLabel(6, o2::aod::filtering::H2fromLb::columnLabel()); + } + + // Tables + using CollisionCandidates = o2::soa::Join; + using TrackCandidates = o2::soa::Join; + + // Single-Track Selection + template + bool passedSingleTrackSelection(const T1& track) + { + // Single-Track Selections + if (std::abs(track.eta()) > cfgEta) + return false; + if (!track.hasITS()) + return false; + if (!track.hasTPC()) + return false; + if (!track.hasTOF()) + return false; + if (track.tpcNClsFound() < cfgTPCNclsFound) + return false; + if (track.tpcChi2NCl() > cfgTPCChi2Ncl) + return false; + if (track.itsChi2NCl() > cfgITSChi2Ncl) + return false; + if (track.itsNCls() < cfgITScls) + return false; + if (track.pt() > cfgMaxPt) + return false; + if (track.pt() < cfgMinPt) + return false; + if (track.sign() > 0) + return false; + + return true; + } + + void fillTriggerTable(bool keepEvent[]) + { + table(keepEvent[0]); + } + + o2::framework::Preslice trackIndicesPerCollision = o2::aod::track_association::collisionId; + int mCurrentRun = -1; + + void process(CollisionCandidates const& collisions, + o2::aod::TrackAssoc const& trackIndices, + TrackCandidates const& tracks, + o2::aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) // start loop over collisions + { + if (mCurrentRun != collision.bc_as().runNumber()) { // If the run is new then we need to initialize the propagator field + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", collision.bc_as().timestamp()); + o2::base::Propagator::initFieldFromGRP(grpo); + mCurrentRun = collision.bc_as().runNumber(); + } + + // Is event good? keepEvent[0] = non promp deuteron + bool keepEvent[1]{}; // explicitly zero-initialised + hProcessedEvents->Fill(0.5); + // Event selection cuts + if (isTVX && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fillTriggerTable(keepEvent); + continue; + } + hProcessedEvents->Fill(1.5); + if (isNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fillTriggerTable(keepEvent); + continue; + } + hProcessedEvents->Fill(2.5); + if (isNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fillTriggerTable(keepEvent); + continue; + } + hProcessedEvents->Fill(3.5); + if (std::abs(collision.posZ()) > cutzvertex) { + fillTriggerTable(keepEvent); + continue; + } + hProcessedEvents->Fill(4.5); + QAHistos.fill(HIST("hVtxZ"), collision.posZ()); + + // Loop over tracks + const auto& trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + auto tracksWithItsPid = o2::soa::Attach(tracks); + + for (const auto& trackId : trackIdsThisCollision) { // start loop over tracks + + const auto& track = tracksWithItsPid.rawIteratorAt(trackId.trackId()); + + std::array dca{track.dcaXY(), track.dcaZ()}; + std::array pVec = track.pVector(); + + if (track.collisionId() != collision.globalIndex()) { + auto trackPar = getTrackParCov(track); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackPar, 2.f, noMatCorr, &dca); + getPxPyPz(trackPar, pVec); + } + + if (!passedSingleTrackSelection(track)) { + continue; + } + + const bool isTOFDe = std::abs(track.tofNSigmaDe()) < cfgTOFNsigma; + const bool isTPCDe = std::abs(track.tpcNSigmaDe()) < cfgTPCNsigma; + const bool isITSDe = track.itsNSigmaDe() > cfgITSNsigma; + + if (track.pt() < ptThresholdPid) { + if (isTPCDe && isITSDe) { + QAHistos.fill(HIST("hDCAxyVsPt-pre_selection"), track.pt(), dca[0]); + QAHistos.fill(HIST("hDCAzVsPt-pre-selection"), track.pt(), dca[1]); + if (std::abs(dca[0]) < cfgDCAcut) { + continue; + } + keepEvent[0] = true; + QAHistos.fill(HIST("ptAntiDeuteron"), track.pt()); + QAHistos.fill(HIST("etaAntideuteron"), track.eta()); + QAHistos.fill(HIST("hDCAxyVsPt"), track.pt(), dca[0]); + QAHistos.fill(HIST("hDCAzVsPt"), track.pt(), dca[1]); + QAHistos.fill(HIST("hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + QAHistos.fill(HIST("hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); + QAHistos.fill(HIST("hnSigmaITSVsPt"), track.pt(), track.itsNSigmaDe()); + } + } else { + if (isTPCDe && isTOFDe) { + + QAHistos.fill(HIST("hDCAxyVsPt-pre_selection"), track.pt(), dca[0]); + QAHistos.fill(HIST("hDCAzVsPt-pre-selection"), track.pt(), dca[1]); + if (std::abs(dca[0]) < cfgDCAcut) { + continue; + } + keepEvent[0] = true; + QAHistos.fill(HIST("ptAntiDeuteron"), track.pt()); + QAHistos.fill(HIST("etaAntideuteron"), track.eta()); + QAHistos.fill(HIST("hDCAxyVsPt"), track.pt(), dca[0]); + QAHistos.fill(HIST("hDCAzVsPt"), track.pt(), dca[1]); + QAHistos.fill(HIST("hnSigmaTPCVsPt"), track.pt(), track.tpcNSigmaDe()); + QAHistos.fill(HIST("hnSigmaTOFVsPt"), track.pt(), track.tofNSigmaDe()); + QAHistos.fill(HIST("hnSigmaITSVsPt"), track.pt(), track.itsNSigmaDe()); + } + } + } // end track loop + if (keepEvent[0]) { + hProcessedEvents->Fill(5.5); + } + + fillTriggerTable(keepEvent); + } + } +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + return o2::framework::WorkflowSpec{o2::framework::adaptAnalysisTask(cfgc)}; +} diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 071c021c367..aedd6d3c7ce 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -19,6 +19,7 @@ /// \author Federica Zanone , Heidelberg University /// \author Antonio Palasciano , INFN Bari +#include "Common/CCDB/EventSelectionParams.h" #include "EventFiltering/PWGHF/HFFilterHelpers.h" #include "EventFiltering/filterTables.h" // @@ -94,8 +95,16 @@ struct HfFilter { // Main struct for HF triggers Configurable activateSecVtxForB{"activateSecVtxForB", false, "flag to enable 2nd vertex fitting - only beauty hadrons"}; // parameters for all triggers + // event selection + struct : o2::framework::ConfigurableGroup { + Configurable applyTVX{"applyTVX", true, "flag to apply TVX selection"}; + Configurable applyTFBorderCut{"applyTFBorderCut", true, "apply TF border cut"}; + Configurable applyITSROFBorderCut{"applyITSROFBorderCut", false, "apply ITS ROF border cut"}; + Configurable maxPvZ{"maxPvZ", 11.f, "maximum absolute value of PV position in the Z coordinate"}; + } evSel; + // nsigma PID (except for V0 and cascades) - Configurable> nSigmaPidCuts{"nSigmaPidCuts", {cutsNsigma[0], 4, 8, labelsRowsNsigma, labelsColumnsNsigma}, "Nsigma cuts for ITS/TPC/TOF PID (except for V0 and cascades)"}; + Configurable> nSigmaPidCuts{"nSigmaPidCuts", {cutsNsigma[0], 4, 9, labelsRowsNsigma, labelsColumnsNsigma}, "Nsigma cuts for ITS/TPC/TOF PID (except for V0 and cascades)"}; // min and max pts for tracks and bachelors (except for V0 and cascades) Configurable> ptCuts{"ptCuts", {cutsPt[0], 2, 10, labelsRowsCutsPt, labelsColumnsCutsPt}, "minimum and maximum pT for bachelor tracks (except for V0 and cascades)"}; Configurable> trackQaulityCuts{"trackQaulityCuts", {cutsTrackQuality[0], 2, 7, labelsColumnsPtThresholdsForFemto, labelsColumnsTrackQuality}, "Track quality cuts for proton and deuteron)"}; @@ -104,9 +113,10 @@ struct HfFilter { // Main struct for HF triggers // parameters for beauty triggers Configurable> pTBinsTrack{"pTBinsTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCAXY pT-dependent cut"}; - Configurable> cutsTrackBeauty3Prong{"cutsTrackBeauty3Prong", {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 per pT bin for 3-prong beauty candidates"}; - Configurable> cutsTrackBeauty4Prong{"cutsTrackBeauty4Prong", {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 per pT bin for 4-prong beauty candidates"}; - Configurable> cutsTrackBeautyToJPsi{"cutsTrackBeautyToJPsi", {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 per pT bin for beauty->JPsi candidates (not muons)"}; + struct : o2::framework::ConfigurableGroup { + Configurable> cutsTrackBeauty3Prong{"cutsTrackBeauty3Prong", {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 per pT bin for 3-prong beauty candidates"}; + Configurable> cutsTrackBeauty4Prong{"cutsTrackBeauty4Prong", {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 per pT bin for 4-prong beauty candidates and J/Psi channels"}; + } cutsTrackBeauty; Configurable paramCharmMassShape{"paramCharmMassShape", "2023_pass3", "Parametrisation of charm-hadron mass shape (options: 2023_pass3)"}; Configurable numSigmaDeltaMassCharmHad{"numSigmaDeltaMassCharmHad", 2.5, "Number of sigma for charm-hadron delta mass cut in B and D resonance triggers"}; Configurable> pTBinsBHadron{"pTBinsBHadron", std::vector{hf_trigger_cuts_presel_beauty::vecBinsPt}, "pT bin limits for beauty hadrons preselections"}; @@ -127,6 +137,7 @@ struct HfFilter { // Main struct for HF triggers Configurable> ptThresholdsForFemto{"ptThresholdsForFemto", {cutsPtThresholdsForFemto[0], 1, 2, labelsEmpty, labelsColumnsPtThresholdsForFemto}, "pT treshold for proton or deuteron for kFemto triggers in GeV/c"}; Configurable forceTofProtonForFemto{"forceTofProtonForFemto", true, "flag to force TOF PID for protons"}; Configurable forceTofDeuteronForFemto{"forceTofDeuteronForFemto", false, "flag to force TOF PID for deuterons"}; + Configurable forceTofProtonForLcReso{"forceTofProtonForLcReso", false, "flag to force TOF PID for protons in Lc* channels"}; // double charm Configurable> enableDoubleCharmChannels{"enableDoubleCharmChannels", {activeDoubleCharmChannels[0], 2, 3, labelsRowsDoubleCharmChannels, labelsColumnsDoubleCharmChannels}, "Flags to enable/disable double charm channels"}; @@ -134,25 +145,41 @@ struct HfFilter { // Main struct for HF triggers // parameters for resonance triggers Configurable> cutsGammaK0sLambda{"cutsGammaK0sLambda", {cutsV0s[0], 1, 6, labelsEmpty, labelsColumnsV0s}, "Selections for V0s (gamma, K0s, Lambda) for D+V0 triggers"}; - Configurable> cutsPtDeltaMassCharmReso{"cutsPtDeltaMassCharmReso", {cutsCharmReso[0], 4, 13, labelsRowsDeltaMassCharmReso, labelsColumnsDeltaMassCharmReso}, "pt (GeV/c) and invariant-mass delta (GeV/c2) for charm hadron resonances"}; - Configurable keepAlsoWrongDmesLambdaPairs{"keepAlsoWrongDmesLambdaPairs", true, "flat go keep also wrong sign D+Lambda pairs"}; - Configurable keepAlsoWrongDmesProtonPairs{"keepAlsoWrongDmesProtonPairs", true, "flat go keep also wrong sign D0p pairs"}; - Configurable keepAlsoWrongDstarMesProtonPairs{"keepAlsoWrongDstarMesProtonPairs", true, "flat go keep also wrong sign D*0p pairs"}; + Configurable> cutsPtDeltaMassCharmReso{"cutsPtDeltaMassCharmReso", {cutsCharmReso[0], 4, 14, labelsRowsDeltaMassCharmReso, labelsColumnsDeltaMassCharmReso}, "pt (GeV/c) and invariant-mass delta (GeV/c2) for charm hadron resonances"}; + struct : o2::framework::ConfigurableGroup { + Configurable keepAlsoWrongDmesLambdaPairs{"keepAlsoWrongDmesLambdaPairs", true, "flat go keep also wrong sign D+Lambda pairs"}; + Configurable keepAlsoWrongDmesProtonPairs{"keepAlsoWrongDmesProtonPairs", true, "flat go keep also wrong sign D0p pairs"}; + Configurable keepAlsoWrongDstarMesProtonPairs{"keepAlsoWrongDstarMesProtonPairs", true, "flat go keep also wrong sign D*0p pairs"}; + } enableWrongMassHyp; + + // parameters for Sigma_C proton trigger + Configurable> cutsSigmaCPr{ + "cutsSigmaCPr", + {cutsSigmaCPrDefault[0], + static_cast(labelsRowsSigmaCPr.size()), + static_cast(labelsColumnsSigmaCPr.size()), + labelsRowsSigmaCPr, + labelsColumnsSigmaCPr}, + "Cuts for SigmaCPr trigger (proton pT and TOF threshold pT)"}; + Configurable forceTofProtonForSigmaCPr{"forceTofProtonForSigmaCPr", true, "flag to force TOF PID for protons in SigmaCPr trigger"}; // parameters for charm baryons to Xi bachelor Configurable> cutsXiCascades{"cutsXiCascades", {cutsCascades[0], 1, 8, labelsEmpty, labelsColumnsCascades}, "Selections for cascades (Xi) for Xi+bachelor triggers"}; - Configurable> cutsXiBachelor{"cutsXiBachelor", {cutsCharmBaryons[0], 1, 11, labelsEmpty, labelsColumnsCharmBarCuts}, "Selections for charm baryons (Xi+Pi, Xi+Ka, Xi+Pi+Pi)"}; + Configurable> cutsXiBachelor{"cutsXiBachelor", {cutsCharmBaryons[0], 1, 15, labelsEmpty, labelsColumnsCharmBarCuts}, "Selections for charm baryons (Xi+Pi, Xi+Ka, Xi+Pi+Pi)"}; Configurable> cutsTrackCharmBaryonBachelor{"cutsTrackCharmBaryonBachelor", {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 per pT bin for charm-baryon bachelor candidates"}; Configurable> requireStrangenessTracking{"requireStrangenessTracking", {requireStrangenessTrackedXi[0], 1, 2, labelsEmpty, labelsColumnsCharmBaryons}, "Flags to require strangeness tracking for channels with Xi"}; // parameters for ML application Configurable> pTBinsBDT{"pTBinsBDT", std::vector{hf_cuts_bdt_multiclass::vecBinsPt}, "track pT bin limits for BDT cut"}; - Configurable> thresholdBDTScoreD0ToKPi{"thresholdBDTScoreD0ToKPi", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of D0 candidates"}; - Configurable> thresholdBDTScoreDPlusToPiKPi{"thresholdBDTScoreDPlusToPiKPi", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of D+ candidates"}; - Configurable> thresholdBDTScoreDSToPiKK{"thresholdBDTScoreDSToPiKK", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Ds+ candidates"}; - Configurable> thresholdBDTScoreLcToPiKP{"thresholdBDTScoreLcToPiKP", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Lc+ candidates"}; - Configurable> thresholdBDTScoreXicToPiKP{"thresholdBDTScoreXicToPiKP", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Xic+ candidates"}; + struct : o2::framework::ConfigurableGroup { + Configurable> thresholdBDTScoreD0ToKPi{"thresholdBDTScoreD0ToKPi", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of D0 candidates"}; + Configurable> thresholdBDTScoreDPlusToPiKPi{"thresholdBDTScoreDPlusToPiKPi", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of D+ candidates"}; + Configurable> thresholdBDTScoreDSToPiKK{"thresholdBDTScoreDSToPiKK", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Ds+ candidates"}; + Configurable> thresholdBDTScoreLcToPiKP{"thresholdBDTScoreLcToPiKP", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Lc+ candidates"}; + Configurable> thresholdBDTScoreXicToPiKP{"thresholdBDTScoreXicToPiKP", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Xic+ candidates"}; + Configurable> thresholdBDTScoreScForSigmaCPr{"thresholdBDTScoreScForSigmaCPr", {hf_cuts_bdt_multiclass::Cuts[0], hf_cuts_bdt_multiclass::NBinsPt, hf_cuts_bdt_multiclass::NCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Lc<--Sc candidates for sigmaC-pr trigger"}; + } thresholdsBDT; Configurable acceptBdtBkgOnly{"acceptBdtBkgOnly", true, "Enable / disable selection based on BDT bkg score only"}; @@ -216,8 +243,8 @@ struct HfFilter { // Main struct for HF triggers std::array, kNCharmParticles> hCharmProtonKstarDistr{}; std::array, kNCharmParticles> hCharmDeuteronKstarDistr{}; std::array, nTotBeautyParts> hMassVsPtB{}; - std::array, kNCharmParticles + 23> hMassVsPtC{}; // +9 for resonances (D*+, D*0, Ds*+, Ds1+, Ds2*+, Xic+* right sign, Xic+* wrong sign, Xic0* right sign, Xic0* wrong sign) +2 for SigmaC (SigmaC++, SigmaC0) +2 for SigmaCK pairs (SigmaC++K-, SigmaC0K0s) +3 for charm baryons (Xi+Pi, Xi+Ka, Xi+Pi+Pi) + JPsi + 4 for charm baryons (D0+p, D0+pWrongSign, D*0p, D*0+pWrongSign) - std::array, 4> hPrDePID; // proton TPC, proton TOF, deuteron TPC, deuteron TOF + std::array, kNCharmParticles + 24> hMassVsPtC{}; // +9 for resonances (D*+, D*0, Ds*+, Ds1+, Ds2*+, Xic+* right sign, Xic+* wrong sign, Xic0* right sign, Xic0* wrong sign) +2 for SigmaC (SigmaC++, SigmaC0) +2 for SigmaCK pairs (SigmaC++K-, SigmaC0K0s) +3 for charm baryons (Xi+Pi, Xi+Ka, Xi+Pi+Pi) + JPsi + 4 for charm baryons (D0+p, D0+pWrongSign, D*0p, D*0+pWrongSign) +1 for SigmaCPr correlation + std::array, 6> hPrDePID; // proton TPC, proton TOF, deuteron TPC, deuteron TOF std::array, kNCharmParticles> hBDTScoreBkg{}; std::array, kNCharmParticles> hBDTScorePrompt{}; std::array, kNCharmParticles> hBDTScoreNonPrompt{}; @@ -251,21 +278,23 @@ struct HfFilter { // Main struct for HF triggers helper.setPtLimitsCharmBaryonBachelor(ptCuts->get(0u, 3u), ptCuts->get(1u, 3u)); helper.setPtLimitsLcResonanceBachelor(ptCuts->get(0u, 8u), ptCuts->get(1u, 8u)); helper.setPtLimitsThetaCBachelor(ptCuts->get(0u, 9u), ptCuts->get(1u, 9u)); - helper.setCutsSingleTrackBeauty(cutsTrackBeauty3Prong, cutsTrackBeauty4Prong, cutsTrackBeauty4Prong); + helper.setCutsSingleTrackBeauty(cutsTrackBeauty.cutsTrackBeauty3Prong, cutsTrackBeauty.cutsTrackBeauty4Prong, cutsTrackBeauty.cutsTrackBeauty4Prong); helper.setCutsSingleTrackCharmBaryonBachelor(cutsTrackCharmBaryonBachelor); helper.setCutsBhadrons(cutsBtoHadrons.cutsBplus, cutsBtoHadrons.cutsBzeroToDstar, cutsBtoHadrons.cutsBc, cutsBtoHadrons.cutsBzero, cutsBtoHadrons.cutsBs, cutsBtoHadrons.cutsLb, cutsBtoHadrons.cutsXib); helper.setCutsBtoJPsi(cutsBtoHadrons.cutsBtoJPsiX); helper.setNsigmaProtonCutsForFemto(std::array{nSigmaPidCuts->get(0u, 3u), nSigmaPidCuts->get(1u, 3u), nSigmaPidCuts->get(2u, 3u), nSigmaPidCuts->get(3u, 3u)}); helper.setNsigmaDeuteronCutsForFemto(std::array{nSigmaPidCuts->get(0u, 6u), nSigmaPidCuts->get(1u, 6u), nSigmaPidCuts->get(2u, 6u), nSigmaPidCuts->get(3u, 6u)}); + helper.setNsigmaProtonCutsForSigmaCPr(std::array{nSigmaPidCuts->get(0u, 8u), nSigmaPidCuts->get(1u, 8u), nSigmaPidCuts->get(2u, 6u), nSigmaPidCuts->get(3u, 8u)}); helper.setDeuteronTrackSelectionForFemto(trackQaulityCuts->get(1u, 0u), trackQaulityCuts->get(1u, 1u), trackQaulityCuts->get(1u, 2u), trackQaulityCuts->get(1u, 3u), trackQaulityCuts->get(1u, 4u), trackQaulityCuts->get(1u, 5u), trackQaulityCuts->get(1u, 6u)); helper.setNsigmaProtonCutsForCharmBaryons(nSigmaPidCuts->get(0u, 0u), nSigmaPidCuts->get(1u, 0u)); helper.setNsigmaPionKaonCutsForDzero(nSigmaPidCuts->get(0u, 1u), nSigmaPidCuts->get(1u, 1u)); helper.setNsigmaKaonCutsFor3Prongs(nSigmaPidCuts->get(0u, 2u), nSigmaPidCuts->get(1u, 2u)); helper.setNsigmaKaonProtonCutsForBeautyToJPsi(nSigmaPidCuts->get(0u, 7u), nSigmaPidCuts->get(1u, 7u)); helper.setForceTofForFemto(forceTofProtonForFemto, forceTofDeuteronForFemto); + helper.setForceTofForLcResonances(forceTofProtonForLcReso); helper.setV0Selections(cutsGammaK0sLambda->get(0u, 0u), cutsGammaK0sLambda->get(0u, 1u), cutsGammaK0sLambda->get(0u, 2u), cutsGammaK0sLambda->get(0u, 3u), cutsGammaK0sLambda->get(0u, 4u), cutsGammaK0sLambda->get(0u, 5u)); helper.setXiSelections(cutsXiCascades->get(0u, 0u), cutsXiCascades->get(0u, 1u), cutsXiCascades->get(0u, 2u), cutsXiCascades->get(0u, 3u), cutsXiCascades->get(0u, 4u), cutsXiCascades->get(0u, 5u), cutsXiCascades->get(0u, 6u), cutsXiCascades->get(0u, 7u)); - helper.setXiBachelorSelections(cutsXiBachelor->get(0u, 0u), cutsXiBachelor->get(0u, 1u), cutsXiBachelor->get(0u, 2u), cutsXiBachelor->get(0u, 3u), cutsXiBachelor->get(0u, 4u), cutsXiBachelor->get(0u, 5u), cutsXiBachelor->get(0u, 6u), cutsXiBachelor->get(0u, 7u), cutsXiBachelor->get(0u, 8u), cutsXiBachelor->get(0u, 9u), cutsXiBachelor->get(0u, 10u)); + helper.setXiBachelorSelections(cutsXiBachelor->get(0u, 0u), cutsXiBachelor->get(0u, 1u), cutsXiBachelor->get(0u, 2u), cutsXiBachelor->get(0u, 3u), cutsXiBachelor->get(0u, 4u), cutsXiBachelor->get(0u, 5u), cutsXiBachelor->get(0u, 6u), cutsXiBachelor->get(0u, 7u), cutsXiBachelor->get(0u, 8u), cutsXiBachelor->get(0u, 9u), cutsXiBachelor->get(0u, 10u), cutsXiBachelor->get(0u, 11u), cutsXiBachelor->get(0u, 12u), cutsXiBachelor->get(0u, 13u), cutsXiBachelor->get(0u, 14u)); helper.setNsigmaPiCutsForCharmBaryonBachelor(nSigmaPidCuts->get(0u, 4u), nSigmaPidCuts->get(1u, 4u)); helper.setTpcPidCalibrationOption(setTPCCalib); helper.setMassResolParametrisation(paramCharmMassShape); @@ -273,8 +302,16 @@ struct HfFilter { // Main struct for HF triggers helper.setPtRangeSoftPiSigmaC(ptCuts->get(0u, 4u), ptCuts->get(1u, 4u)); helper.setPtDeltaMassRangeSigmaC(cutsPtDeltaMassCharmReso->get(0u, 6u), cutsPtDeltaMassCharmReso->get(1u, 6u), cutsPtDeltaMassCharmReso->get(0u, 7u), cutsPtDeltaMassCharmReso->get(1u, 7u), cutsPtDeltaMassCharmReso->get(0u, 8u), cutsPtDeltaMassCharmReso->get(1u, 8u), cutsPtDeltaMassCharmReso->get(0u, 9u), cutsPtDeltaMassCharmReso->get(1u, 9u), cutsPtDeltaMassCharmReso->get(2u, 6u), cutsPtDeltaMassCharmReso->get(2u, 7u), cutsPtDeltaMassCharmReso->get(2u, 8u), cutsPtDeltaMassCharmReso->get(2u, 9u)); helper.setPtRangeSoftKaonXicResoToSigmaC(ptCuts->get(0u, 5u), ptCuts->get(1u, 5u)); - helper.setVtxConfiguration(dfStrangeness, true); // (DCAFitterN, useAbsDCA) + helper.setVtxConfiguration(dfStrangeness, true); // (DCAFitterN, useAbsDCA) helper.setVtxConfiguration(dfStrangeness3, true); // (DCAFitterN, useAbsDCA) + helper.setParSigmaCPr( + cutsPtDeltaMassCharmReso->get(0u, 13u), // min ΔM + cutsPtDeltaMassCharmReso->get(1u, 13u), // max ΔM + cutsPtDeltaMassCharmReso->get(2u, 13u), // min pT SigmaC + cutsSigmaCPr->get(0u, 0u), // min pT proton + cutsSigmaCPr->get(1u, 0u), // max pT proton + cutsSigmaCPr->get(2u, 0u), // TOF pT threshold + forceTofProtonForSigmaCPr); // set True for force TOF on proton candidate after threshold dfStrangeness.setMatCorrType(matCorr); dfStrangeness3.setMatCorrType(matCorr); helper.setVtxConfiguration(df2, false); // (DCAFitterN, useAbsDCA) @@ -361,6 +398,8 @@ struct HfFilter { // Main struct for HF triggers // ThetaC hMassVsPtC[kNCharmParticles + 21] = registry.add("fMassVsPtCharmBaryonToDstarP", "#it{M} vs. #it{p}_{T} distribution of triggered D^{*0}#p candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 21]}); hMassVsPtC[kNCharmParticles + 22] = registry.add("fMassVsPtCharmBaryonToDstarPWrongSign", "#it{M} vs. #it{p}_{T} distribution of triggered D^{*0}#p wrong sign candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 22]}); + // SigmaC-p + hMassVsPtC[kNCharmParticles + 23] = registry.add("fMassVsPtSigmaCPr", "#it{M} vs. #it{p}_{T} distribution of #Sigma_{c} for SigmaCPr trigger;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2D, {ptAxis, massAxisC[kNCharmParticles + 23]}); for (int iBeautyPart{0}; iBeautyPart < kNBeautyParticles; ++iBeautyPart) { hMassVsPtB[iBeautyPart] = registry.add(Form("fMassVsPt%s", beautyParticleNames[iBeautyPart].data()), Form("#it{M} vs. #it{p}_{T} distribution of triggered %s candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", beautyParticleNames[iBeautyPart].data()), HistType::kTH2D, {ptAxis, massAxisB[iBeautyPart]}); @@ -398,6 +437,8 @@ struct HfFilter { // Main struct for HF triggers hPrDePID[1] = registry.add("fProtonTOFPID", "#it{N}_{#sigma}^{TOF} vs. #it{p} for selected protons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TOF}", HistType::kTH2D, {pAxis, nSigmaAxis}); hPrDePID[2] = registry.add("fDeuteronTPCPID", "#it{N}_{#sigma}^{TPC} vs. #it{p} for selected deuterons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TPC}", HistType::kTH2D, {pAxis, nSigmaAxis}); hPrDePID[3] = registry.add("fDeuteronTOFPID", "#it{N}_{#sigma}^{TOF} vs. #it{p} for selected deuterons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TOF}", HistType::kTH2D, {pAxis, nSigmaAxis}); + hPrDePID[4] = registry.add("fProtonTPCPIDSigmaCPr", "#it{N}_{#sigma}^{TPC} vs. #it{p} for selected protons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TPC}", HistType::kTH2D, {pAxis, nSigmaAxis}); + hPrDePID[5] = registry.add("fProtonTOFPIDSigmaCPr", "#it{N}_{#sigma}^{TOF} vs. #it{p} for selected protons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TOF}", HistType::kTH2D, {pAxis, nSigmaAxis}); hV0Selected = registry.add("fV0Selected", "Selections for V0s;;counts", HistType::kTH2D, {{9, -0.5, 8.5}, {kNV0, -0.5, +kNV0 - 0.5}}); @@ -423,7 +464,7 @@ struct HfFilter { // Main struct for HF triggers ccdbApi.init(url); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); - thresholdBDTScores = {thresholdBDTScoreD0ToKPi, thresholdBDTScoreDPlusToPiKPi, thresholdBDTScoreDSToPiKK, thresholdBDTScoreLcToPiKP, thresholdBDTScoreXicToPiKP}; + thresholdBDTScores = {thresholdsBDT.thresholdBDTScoreD0ToKPi, thresholdsBDT.thresholdBDTScoreDPlusToPiKPi, thresholdsBDT.thresholdBDTScoreDSToPiKK, thresholdsBDT.thresholdBDTScoreLcToPiKP, thresholdsBDT.thresholdBDTScoreXicToPiKP}; } void process(CollsWithEvSel const& collisions, @@ -441,9 +482,16 @@ struct HfFilter { // Main struct for HF triggers { for (const auto& collision : collisions) { + // all processed collisions + hProcessedEvents->Fill(0); + bool keepEvent[kNtriggersHF]{false}; - if (!collision.sel8() || std::fabs(collision.posZ()) > 11.f) { // 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], keepEvent[kSingleCharm2P], keepEvent[kSingleCharm3P], keepEvent[kSingleNonPromptCharm2P], keepEvent[kSingleNonPromptCharm3P], keepEvent[kCharmBarToXi2Bach], keepEvent[kPrCharm2P], keepEvent[kBtoJPsiKa], keepEvent[kBtoJPsiKstar], keepEvent[kBtoJPsiPhi], keepEvent[kBtoJPsiPrKa], keepEvent[kBtoJPsiPi]); + bool isSelectedTVX = evSel.applyTVX ? collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) : true; + bool isSelectedTFBorder = evSel.applyTFBorderCut ? collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) : true; + bool isSelectedITSROFBorder = evSel.applyITSROFBorderCut ? collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) : true; + bool isSelectedPvZ = (std::fabs(collision.posZ()) < evSel.maxPvZ); + if (!isSelectedTVX || !isSelectedTFBorder || !isSelectedITSROFBorder || !isSelectedPvZ) { + 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], keepEvent[kCharmBarToXi2Bach], keepEvent[kPrCharm2P], keepEvent[kBtoJPsiKa], keepEvent[kBtoJPsiKstar], keepEvent[kBtoJPsiPhi], keepEvent[kBtoJPsiPrKa], keepEvent[kBtoJPsiPi], keepEvent[kSigmaCPr]); continue; } @@ -483,8 +531,6 @@ struct HfFilter { // Main struct for HF triggers currentRun = bc.runNumber(); } - hProcessedEvents->Fill(0); - std::vector> indicesDau2Prong{}, indicesDau2ProngPrompt{}; auto cand2ProngsThisColl = cand2Prongs.sliceBy(hf2ProngPerCollision, thisCollId); @@ -803,9 +849,11 @@ struct HfFilter { // Main struct for HF triggers } // end beauty selection // 2-prong femto - if (!keepEvent[kFemto2P] && enableFemtoChannels->get(0u, 0u) && isD0CharmTagged && track.collisionId() == thisCollId) { - bool isProton = helper.isSelectedTrack4Femto(track, trackParThird, activateQA, hPrDePID[0], hPrDePID[1], kProtonForFemto); - if (isProton) { + bool isProtonForCharm2Prong = helper.isSelectedTrack4Corr(track, trackParThird, activateQA, hPrDePID[0], hPrDePID[1], kProtonForFemto); + bool isDeuteronForCharm2Prong = helper.isSelectedTrack4Corr(track, trackParThird, activateQA, hPrDePID[2], hPrDePID[3], kDeuteronForFemto); + + if (track.collisionId() == thisCollId) { + if (isProtonForCharm2Prong && !keepEvent[kFemto2P] && enableFemtoChannels->get(0u, 0u) && isD0CharmTagged) { float relativeMomentum = helper.computeRelativeMomentum(pVecThird, pVec2Prong, massD0); if (applyOptimisation) { optimisationTreeFemto(thisCollId, o2::constants::physics::Pdg::kD0, pt2Prong, scores[0], scores[1], scores[2], relativeMomentum, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.tpcNSigmaDe(), track.tofNSigmaDe()); @@ -817,7 +865,20 @@ struct HfFilter { // Main struct for HF triggers } } } - } // end femto selection + + if (isDeuteronForCharm2Prong && !keepEvent[kFemto2P] && enableFemtoChannels->get(1u, 0u) && isD0CharmTagged) { + float relativeMomentum = helper.computeRelativeMomentum(pVecThird, pVec2Prong, massD0); + if (applyOptimisation) { + optimisationTreeFemto(thisCollId, o2::constants::physics::Pdg::kD0, pt2Prong, scores[0], scores[1], scores[2], relativeMomentum, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.tpcNSigmaDe(), track.tofNSigmaDe()); + } + if (relativeMomentum < femtoMaxRelativeMomentum) { + keepEvent[kFemto2P] = true; + if (activateQA) { + hCharmDeuteronKstarDistr[kD0]->Fill(relativeMomentum); + } + } + } + } // end femto charm 2prong selection // Beauty with JPsi if (preselJPsiToMuMu) { @@ -1037,19 +1098,19 @@ struct HfFilter { // Main struct for HF triggers if (isGoodXicStar) { if (isRightSignXicStar) { hMassVsPtC[kNCharmParticles + 7]->Fill(ptCand, massDiffXicStarCand); - } else if (keepAlsoWrongDmesLambdaPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesLambdaPairs) { hMassVsPtC[kNCharmParticles + 8]->Fill(ptCand, massDiffXicStarBarCand); } } if (isGoodXicStarBar) { if (isRightSignXicStarBar) { hMassVsPtC[kNCharmParticles + 7]->Fill(ptCand, massDiffXicStarCand); - } else if (keepAlsoWrongDmesLambdaPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesLambdaPairs) { hMassVsPtC[kNCharmParticles + 8]->Fill(ptCand, massDiffXicStarBarCand); } } } - if ((isGoodXicStar && (isRightSignXicStar || keepAlsoWrongDmesLambdaPairs)) || (isGoodXicStarBar && (isRightSignXicStarBar || keepAlsoWrongDmesLambdaPairs))) { + if ((isGoodXicStar && (isRightSignXicStar || enableWrongMassHyp.keepAlsoWrongDmesLambdaPairs)) || (isGoodXicStarBar && (isRightSignXicStarBar || enableWrongMassHyp.keepAlsoWrongDmesLambdaPairs))) { keepEvent[kV0Charm2P] = true; break; } @@ -1136,19 +1197,19 @@ struct HfFilter { // Main struct for HF triggers if (isGoodThetac) { if (isRightSignThetaC) { hMassVsPtC[kNCharmParticles + 21]->Fill(ptCand, massDiffThetacCand); - } else if (keepAlsoWrongDmesProtonPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesProtonPairs) { hMassVsPtC[kNCharmParticles + 22]->Fill(ptCand, massDiffThetacBarCand); } } if (isGoodThetacBar) { if (isRightSignThetaCBar) { hMassVsPtC[kNCharmParticles + 21]->Fill(ptCand, massDiffThetacCand); - } else if (keepAlsoWrongDmesProtonPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesProtonPairs) { hMassVsPtC[kNCharmParticles + 22]->Fill(ptCand, massDiffThetacBarCand); } } } - if ((isGoodThetac && (isRightSignThetaC || keepAlsoWrongDstarMesProtonPairs)) || (isGoodThetacBar && (isRightSignThetaCBar || keepAlsoWrongDstarMesProtonPairs))) { + if ((isGoodThetac && (isRightSignThetaC || enableWrongMassHyp.keepAlsoWrongDstarMesProtonPairs)) || (isGoodThetacBar && (isRightSignThetaCBar || enableWrongMassHyp.keepAlsoWrongDstarMesProtonPairs))) { keepEvent[kPrCharm2P] = true; break; } @@ -1187,19 +1248,19 @@ struct HfFilter { // Main struct for HF triggers if (isGoodLcStar) { if (isRightSignLcStar) { hMassVsPtC[kNCharmParticles + 19]->Fill(ptCand, massDiffLcStarCand); - } else if (keepAlsoWrongDmesProtonPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesProtonPairs) { hMassVsPtC[kNCharmParticles + 20]->Fill(ptCand, massDiffLcStarBarCand); } } if (isGoodLcStarBar) { if (isRightSignLcStarBar) { hMassVsPtC[kNCharmParticles + 19]->Fill(ptCand, massDiffLcStarCand); - } else if (keepAlsoWrongDmesProtonPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesProtonPairs) { hMassVsPtC[kNCharmParticles + 20]->Fill(ptCand, massDiffLcStarBarCand); } } } - if ((isGoodLcStar && (isRightSignLcStar || keepAlsoWrongDmesProtonPairs)) || (isGoodLcStarBar && (isRightSignLcStarBar || keepAlsoWrongDmesProtonPairs))) { + if ((isGoodLcStar && (isRightSignLcStar || enableWrongMassHyp.keepAlsoWrongDmesProtonPairs)) || (isGoodLcStarBar && (isRightSignLcStarBar || enableWrongMassHyp.keepAlsoWrongDmesProtonPairs))) { keepEvent[kPrCharm2P] = true; break; } @@ -1459,8 +1520,8 @@ struct HfFilter { // Main struct for HF triggers } // end beauty selection // 3-prong femto - bool isProton = helper.isSelectedTrack4Femto(track, trackParFourth, activateQA, hPrDePID[0], hPrDePID[1], kProtonForFemto); - bool isDeuteron = helper.isSelectedTrack4Femto(track, trackParFourth, activateQA, hPrDePID[2], hPrDePID[3], kDeuteronForFemto); + bool isProton = helper.isSelectedTrack4Corr(track, trackParFourth, activateQA, hPrDePID[0], hPrDePID[1], kProtonForFemto); + bool isDeuteron = helper.isSelectedTrack4Corr(track, trackParFourth, activateQA, hPrDePID[2], hPrDePID[3], kDeuteronForFemto); if (isProton && track.collisionId() == thisCollId) { for (int iHypo{0}; iHypo < kNCharmParticles - 1 && !keepEvent[kFemto3P]; ++iHypo) { @@ -1495,9 +1556,13 @@ struct HfFilter { // Main struct for HF triggers } } // end femto selection - // SigmaC++ K- trigger - if (!keepEvent[kSigmaCPPK] && is3Prong[2] > 0 && is3ProngInMass[2] > 0 && isSignalTagged[2] > 0 && helper.isSelectedKaonFromXicResoToSigmaC(track)) { - // we need a candidate Lc->pKpi and a candidate soft kaon + // SigmaC++ K- and SigmaC++,0 - p trigger + + bool isTrackKaon = helper.isSelectedKaonFromXicResoToSigmaC(track); + bool isTrackProton = helper.isSelectedTrack4Corr(track, trackParFourth, activateQA, hPrDePID[4], hPrDePID[5], kProtonForScPrCorr); + + if ((!keepEvent[kSigmaCPPK] || !keepEvent[kSigmaCPr]) && is3Prong[2] > 0 && is3ProngInMass[2] > 0 && isSignalTagged[2] > 0 && (isTrackKaon || isTrackProton)) { + // we need a candidate Lc->pKpi and a candidate soft kaon, and also need a candidate of proton for sigmaC correlation // look for SigmaC++ candidates for (const auto& trackSoftPiId : trackIdsThisCollision) { // start loop over tracks (soft pi) @@ -1511,8 +1576,7 @@ struct HfFilter { // Main struct for HF triggers // do not consider as candidate soft pion a track already used to build the current 3-prong candidate continue; } - - // exclude already the current track if it corresponds to the K- candidate + // exclude already the current track if it corresponds to the K- or proton candidate if (globalIndexSoftPi == track.globalIndex()) { continue; } @@ -1520,9 +1584,6 @@ struct HfFilter { // Main struct for HF triggers // check the candidate SigmaC++ charge std::array chargesSc = {trackFirst.sign(), trackSecond.sign(), trackThird.sign(), trackSoftPi.sign()}; int chargeSc = std::accumulate(chargesSc.begin(), chargesSc.end(), 0); // SIGNED electric charge of SigmaC candidate - if (std::abs(chargeSc) != 2) { - continue; - } // select soft pion candidates auto trackParSoftPi = getTrackPar(trackSoftPi); @@ -1540,59 +1601,66 @@ struct HfFilter { // Main struct for HF triggers // check the mass of the SigmaC++ candidate auto pVecSigmaC = RecoDecay::pVec(pVecFirst, pVecSecond, pVecThird, pVecSoftPi); auto ptSigmaC = RecoDecay::pt(pVecSigmaC); - int8_t whichSigmaC = helper.isSelectedSigmaCInDeltaMassRange<2>(pVecFirst, pVecThird, pVecSecond, pVecSoftPi, ptSigmaC, is3Prong[2], hMassVsPtC[kNCharmParticles + 9], activateQA); + int8_t whichSigmaC = helper.isSelectedSigmaCInDeltaMassRange<2>(pVecFirst, pVecThird, pVecSecond, pVecSoftPi, ptSigmaC, is3Prong[2], hMassVsPtC[kNCharmParticles + 9], activateQA); // put charge = -1, it ensure the function is not looking charge and calculate the bit for ground state of SigmaC in the specified mass range if (whichSigmaC > 0) { /// let's build a candidate SigmaC++K- pair /// and keep it only if: /// - it has the correct charge (±1) /// - it is in the correct mass range - // check the charge for SigmaC++K- candidates - if (std::abs(chargeSc + track.sign()) != 1) { - continue; - } - - // check the invariant mass - float massSigmaCPKPi{-999.}, massSigmaCPiKP{-999.}, deltaMassXicResoPKPi{-999.}, deltaMassXicResoPiKP{-999.}; - float ptSigmaCKaon = RecoDecay::pt(pVecSigmaC, pVecFourth); + if (!keepEvent[kSigmaCPPK] && (std::abs(chargeSc + track.sign()) == 1 && std::abs(chargeSc) == 2)) { + // check the invariant mass + float massSigmaCPKPi{-999.}, massSigmaCPiKP{-999.}, deltaMassXicResoPKPi{-999.}, deltaMassXicResoPiKP{-999.}; + float ptSigmaCKaon = RecoDecay::pt(pVecSigmaC, pVecFourth); - if (ptSigmaCKaon > cutsPtDeltaMassCharmReso->get(2u, 10u)) { - if (TESTBIT(whichSigmaC, 0)) { - massSigmaCPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi}, std::array{massProton, massKa, massPi, massPi}); - deltaMassXicResoPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi, pVecFourth}, std::array{massProton, massKa, massPi, massPi, massKa}) - massSigmaCPKPi; - } - if (TESTBIT(whichSigmaC, 1)) { - massSigmaCPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi}, std::array{massPi, massKa, massProton, massPi}); - deltaMassXicResoPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi, pVecFourth}, std::array{massPi, massKa, massProton, massPi, massKa}) - massSigmaCPiKP; - } - bool isPKPiOk = (cutsPtDeltaMassCharmReso->get(0u, 10u) < deltaMassXicResoPKPi && deltaMassXicResoPKPi < cutsPtDeltaMassCharmReso->get(1u, 10u)); - bool isPiKPOk = (cutsPtDeltaMassCharmReso->get(0u, 10u) < deltaMassXicResoPiKP && deltaMassXicResoPiKP < cutsPtDeltaMassCharmReso->get(1u, 10u)); - if (isPKPiOk || isPiKPOk) { - /// This is a good SigmaC++K- event - keepEvent[kSigmaCPPK] = true; + if (ptSigmaCKaon > cutsPtDeltaMassCharmReso->get(2u, 10u)) { + if (TESTBIT(whichSigmaC, 0)) { + massSigmaCPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi}, std::array{massProton, massKa, massPi, massPi}); + deltaMassXicResoPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi, pVecFourth}, std::array{massProton, massKa, massPi, massPi, massKa}) - massSigmaCPKPi; + } + if (TESTBIT(whichSigmaC, 1)) { + massSigmaCPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi}, std::array{massPi, massKa, massProton, massPi}); + deltaMassXicResoPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecSoftPi, pVecFourth}, std::array{massPi, massKa, massProton, massPi, massKa}) - massSigmaCPiKP; + } + bool isPKPiOk = (cutsPtDeltaMassCharmReso->get(0u, 10u) < deltaMassXicResoPKPi && deltaMassXicResoPKPi < cutsPtDeltaMassCharmReso->get(1u, 10u)); + bool isPiKPOk = (cutsPtDeltaMassCharmReso->get(0u, 10u) < deltaMassXicResoPiKP && deltaMassXicResoPiKP < cutsPtDeltaMassCharmReso->get(1u, 10u)); + if ((isPKPiOk || isPiKPOk) && isTrackKaon) { + /// This is a good SigmaC++K- event + keepEvent[kSigmaCPPK] = true; - /// QA plot - if (activateQA) { - if (isPKPiOk) { - if (TESTBIT(whichSigmaC, 2)) { - hMassVsPtC[kNCharmParticles + 11]->Fill(ptSigmaCKaon, deltaMassXicResoPKPi); - } - if (TESTBIT(whichSigmaC, 3)) { - hMassVsPtC[kNCharmParticles + 12]->Fill(ptSigmaCKaon, deltaMassXicResoPKPi); - } - } - if (isPiKPOk) { - if (TESTBIT(whichSigmaC, 2)) { - hMassVsPtC[kNCharmParticles + 11]->Fill(ptSigmaCKaon, deltaMassXicResoPiKP); + /// QA plot + if (activateQA) { + if (isPKPiOk) { + if (TESTBIT(whichSigmaC, 2)) { + hMassVsPtC[kNCharmParticles + 11]->Fill(ptSigmaCKaon, deltaMassXicResoPKPi); + } + if (TESTBIT(whichSigmaC, 3)) { + hMassVsPtC[kNCharmParticles + 12]->Fill(ptSigmaCKaon, deltaMassXicResoPKPi); + } } - if (TESTBIT(whichSigmaC, 3)) { - hMassVsPtC[kNCharmParticles + 12]->Fill(ptSigmaCKaon, deltaMassXicResoPiKP); + if (isPiKPOk) { + if (TESTBIT(whichSigmaC, 2)) { + hMassVsPtC[kNCharmParticles + 11]->Fill(ptSigmaCKaon, deltaMassXicResoPiKP); + } + if (TESTBIT(whichSigmaC, 3)) { + hMassVsPtC[kNCharmParticles + 12]->Fill(ptSigmaCKaon, deltaMassXicResoPiKP); + } } } } } } } + // now from here we are looking for SigmaC-proton trigger + // DeltaEta is the difference in Eta between SigmaC candiate and proton + float deltaEta = std::abs(RecoDecay::eta(pVecSigmaC) - track.eta()); + if (!keepEvent[kSigmaCPr] && (isTrackProton && deltaEta < 1.0)) { + auto tagBDT = helper.isBDTSelected(scores[2], thresholdsBDT.thresholdBDTScoreScForSigmaCPr.value); + int8_t whichSigmaC = helper.isSelectedSigmaCInDeltaMassRange<-1>(pVecFirst, pVecThird, pVecSecond, pVecSoftPi, ptSigmaC, is3Prong[2], hMassVsPtC[kNCharmParticles + 23], activateQA); // put charge {-1} for not looking charge specific SigmaC ground state, it will return bit 4 corresponding to it + if (TESTBIT(whichSigmaC, 4) && TESTBIT(tagBDT, RecoDecay::OriginType::Prompt)) { + keepEvent[kSigmaCPr] = true; + } + } } // end SigmaC++ candidate } // end loop over tracks (soft pi) } // end candidate Lc->pKpi @@ -1696,11 +1764,11 @@ struct HfFilter { // Main struct for HF triggers if (activateQA) { if (isRightSign) { hMassVsPtC[kNCharmParticles + 5]->Fill(ptCand, massDiffXicStar); - } else if (keepAlsoWrongDmesLambdaPairs) { + } else if (enableWrongMassHyp.keepAlsoWrongDmesLambdaPairs) { hMassVsPtC[kNCharmParticles + 6]->Fill(ptCand, massDiffXicStar); } } - if (isRightSign || keepAlsoWrongDmesLambdaPairs) { + if (isRightSign || enableWrongMassHyp.keepAlsoWrongDmesLambdaPairs) { keepEvent[kV0Charm3P] = true; } } @@ -1989,7 +2057,7 @@ struct HfFilter { // Main struct for HF triggers } } - 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], keepEvent[kCharmBarToXi2Bach], keepEvent[kPrCharm2P], keepEvent[kBtoJPsiKa], keepEvent[kBtoJPsiKstar], keepEvent[kBtoJPsiPhi], keepEvent[kBtoJPsiPrKa], keepEvent[kBtoJPsiPi]); + 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], keepEvent[kCharmBarToXi2Bach], keepEvent[kPrCharm2P], keepEvent[kBtoJPsiKa], keepEvent[kBtoJPsiKstar], keepEvent[kBtoJPsiPhi], keepEvent[kBtoJPsiPrKa], keepEvent[kBtoJPsiPi], keepEvent[kSigmaCPr]); if (!std::accumulate(keepEvent, keepEvent + kNtriggersHF, 0)) { hProcessedEvents->Fill(1); diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index 04297f1ff09..d215fb0df8d 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include #include +#include #include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) @@ -97,6 +97,7 @@ enum HfTriggers { kBtoJPsiPhi, kBtoJPsiPrKa, kBtoJPsiPi, + kSigmaCPr, kNtriggersHF }; @@ -154,7 +155,8 @@ enum PIDSpecies { enum trackSpecies { kProtonForFemto, - kDeuteronForFemto + kDeuteronForFemto, + kProtonForScPrCorr }; enum V0Species { @@ -245,7 +247,7 @@ static const int nTotBeautyParts = static_cast(kNBeautyParticles) + static_ static const std::array beautyParticleNames{"Bplus", "B0toDStar", "Bc", "B0", "Bs", "Lb", "Xib", "BplusToJPsi", "B0ToJPsi", "BsToJPsi", "LbToJPsi", "BcToJPsi"}; static const std::array pdgCodesCharm{421, 411, 431, 4122, 4232}; static const std::array eventTitles = {"all", "rejected"}; -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(), filtering::HfCharmBarToXi2Bach::columnLabel(), filtering::HfPrCharm2P::columnLabel(), filtering::HfBtoJPsiKa::columnLabel(), filtering::HfBtoJPsiKstar::columnLabel(), filtering::HfBtoJPsiPhi::columnLabel(), filtering::HfBtoJPsiPrKa::columnLabel(), filtering::HfBtoJPsiPi::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(), filtering::HfCharmBarToXi2Bach::columnLabel(), filtering::HfPrCharm2P::columnLabel(), filtering::HfBtoJPsiKa::columnLabel(), filtering::HfBtoJPsiKstar::columnLabel(), filtering::HfBtoJPsiPhi::columnLabel(), filtering::HfBtoJPsiPrKa::columnLabel(), filtering::HfBtoJPsiPi::columnLabel(), filtering::HfSigmaCPr::columnLabel()}; static const std::array v0Labels{"#gamma", "K_{S}^{0}", "#Lambda", "#bar{#Lambda}"}; static const std::array v0Names{"Photon", "K0S", "Lambda", "AntiLambda"}; @@ -293,7 +295,7 @@ static const o2::framework::AxisSpec alphaAxis{100, -1.f, 1.f}; static const o2::framework::AxisSpec qtAxis{100, 0.f, 0.25f}; static const o2::framework::AxisSpec bdtAxis{100, 0.f, 1.f}; static const o2::framework::AxisSpec phiAxis{36, 0., o2::constants::math::TwoPI}; -static const std::array massAxisC = {o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.75f, 2.25f}, o2::framework::AxisSpec{250, 2.05f, 2.55f}, o2::framework::AxisSpec{250, 2.25f, 2.75f}, o2::framework::AxisSpec{200, 0.139f, 0.159f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{240, 2.4f, 3.6f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}}; +static const std::array massAxisC = {o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.75f, 2.25f}, o2::framework::AxisSpec{250, 2.05f, 2.55f}, o2::framework::AxisSpec{250, 2.25f, 2.75f}, o2::framework::AxisSpec{200, 0.139f, 0.159f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{240, 2.4f, 3.6f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.14f, 0.26f}}; static const std::array massAxisB = {o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 5.4f, 7.4f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.4f, 6.4f}, o2::framework::AxisSpec{400, 5.0f, 6.6f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{400, 5.0f, 6.6f}, o2::framework::AxisSpec{240, 5.8f, 7.0f}}; // default values for configurables @@ -312,13 +314,13 @@ static const std::vector labelsColumnsCutsPt = {"Beauty", "DstarPlu static const std::vector labelsRowsCutsPt = {"Minimum", "Maximum"}; // PID cuts -constexpr float cutsNsigma[4][8] = { - {3., 3., 3., 5., 3., 3., 5., 3.}, // TPC proton from Lc, pi/K from D0, K from 3-prong, femto selected proton, pi/K from Xic/Omegac, K from Xic*->SigmaC-Kaon, femto selected deuteron, K/p from beauty->JPsiX - {3., 3., 3., 2.5, 3., 3., 5., 3.}, // TOF proton from Lc, pi/K from D0, K from 3-prong, femto selected proton, pi/K from Xic/Omegac, K from Xic*->SigmaC-Kaon, femto selected deuteron, K/p from beauty->JPsiX - {999., 999., 999., 2.5, 999., 999., 5., 999.}, // Sum in quadrature of TPC and TOF (used only for femto selected proton and deuteron for pT < 4 GeV/c) - {999., 999., 999., 999., 999., 999., -4., 999.} // ITS used only for femto selected deuteron for less than pt threshold +constexpr float cutsNsigma[4][9] = { + {3., 3., 3., 5., 3., 3., 5., 3., 3.}, // TPC proton from Lc, pi/K from D0, K from 3-prong, femto selected proton, pi/K from Xic/Omegac, K from Xic*->SigmaC-Kaon, femto selected deuteron, K/p from beauty->JPsiX, proton from SigmaC-Pr correlation + {3., 3., 3., 2.5, 3., 3., 5., 3., 3.}, // TOF proton from Lc, pi/K from D0, K from 3-prong, femto selected proton, pi/K from Xic/Omegac, K from Xic*->SigmaC-Kaon, femto selected deuteron, K/p from beauty->JPsiX, proton from SigmaC-Pr correlation + {999., 999., 999., 2.5, 999., 999., 5., 999., 3.}, // Sum in quadrature of TPC and TOF (used only for femto selected proton and deuteron for pT < 4 GeV/c) + {999., 999., 999., 999., 999., 999., -4., 999., 999.} // ITS used only for femto selected deuteron for less than pt threshold }; -static const std::vector labelsColumnsNsigma = {"PrFromLc", "PiKaFromDZero", "KaFrom3Prong", "PrForFemto", "PiKaFromCharmBaryon", "SoftKaonFromXicResoToSigmaC", "DeForFemto", "KaPrFromBeautyToJPsi"}; +static const std::vector labelsColumnsNsigma = {"PrFromLc", "PiKaFromDZero", "KaFrom3Prong", "PrForFemto", "PiKaFromCharmBaryon", "SoftKaonFromXicResoToSigmaC", "DeForFemto", "KaPrFromBeautyToJPsi", "PrFromSigmaCPr"}; static const std::vector labelsRowsNsigma = {"TPC", "TOF", "Comb", "ITS"}; // track cut @@ -363,11 +365,11 @@ static const std::vector labelsColumnsDoubleCharmChannels = {"Doubl static const std::vector labelsRowsDoubleCharmChannels = {"", "KeepNonprompt"}; // charm resonances -constexpr float cutsCharmReso[4][13] = {{0.0, 0.0, 0.0, 0.0, 0.4, 0., 0.0, 0.00, 0.21, 0.21, 0.0, 0.7, 0.7}, - {0.155, 0.3, 0.3, 0.88, 0.88, 1.35, 0.18, 0.18, 0.25, 0.25, 0.8, 1.3, 1.3}, - {0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 6.0, 0.0, 6.0, 0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; // D*+, D*0, Ds*0, Ds1+, Ds2*+, Xic*->D, SigmaC0, SigmaC++, SigmaC(2520)0, SigmaC(2520)++, Xic*->SigmaC, Lc*->D0P, Lc*->D*+P -static const std::vector labelsColumnsDeltaMassCharmReso = {"DstarPlus", "DstarZero", "DsStarZero", "Ds1Plus", "Ds2StarPlus", "XicResoToD", "SigmaC0", "SigmaCPlusPlus", "SigmaC02520", "SigmaCPlusPlus2520", "XicResoToSigmaC", "LcResoToD0Pr", "ThetaC"}; +constexpr float cutsCharmReso[4][14] = {{0.0, 0.0, 0.0, 0.0, 0.4, 0., 0.0, 0.00, 0.21, 0.21, 0.0, 0.7, 0.7, 0.15}, + {0.155, 0.3, 0.3, 0.88, 0.88, 1.35, 0.18, 0.18, 0.25, 0.25, 0.8, 1.3, 1.3, 0.19}, + {0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 0.0, 6.0, 0.0, 6.0, 0.0, 0.0, 0.0, 5.0}, + {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; // D*+, D*0, Ds*0, Ds1+, Ds2*+, Xic*->D, SigmaC0, SigmaC++, SigmaC(2520)0, SigmaC(2520)++, Xic*->SigmaC, Lc*->D0P, Lc*->D*+P +static const std::vector labelsColumnsDeltaMassCharmReso = {"DstarPlus", "DstarZero", "DsStarZero", "Ds1Plus", "Ds2StarPlus", "XicResoToD", "SigmaC0", "SigmaCPlusPlus", "SigmaC02520", "SigmaCPlusPlus2520", "XicResoToSigmaC", "LcResoToD0Pr", "ThetaC", "SigmaCPr"}; static const std::vector labelsRowsDeltaMassCharmReso = {"deltaMassMin", "deltaMassMax", "ptMin", "ptMinCharmDaugh"}; // V0s for charm resonances constexpr float cutsV0s[1][6] = {{0.85, 0.97, 0.5, 4., 0.02, 0.01}}; // cosPaGamma, cosPaK0sLambda, radiusK0sLambda, nSigmaPrLambda, deltaMassK0S, deltaMassLambda @@ -376,8 +378,21 @@ static const std::vector labelsColumnsV0s = {"CosPaGamma", "CosPaK0 // cascades for Xi + bachelor triggers constexpr float cutsCascades[1][8] = {{0.2, 1., 0.01, 0.01, 0.99, 0.99, 0.3, 3.}}; // ptXiBachelor, deltaMassXi, deltaMassLambda, cosPaXi, cosPaLambda, DCAxyXi, nSigmaPid static const std::vector labelsColumnsCascades = {"PtBachelor", "PtXi", "DeltaMassXi", "DeltaMassLambda", "CosPAXi", "CosPaLambda", "DCAxyXi", "NsigmaPid"}; -constexpr float cutsCharmBaryons[1][11] = {{5., 5., 1000., 2.35, 2.60, 2.35, 3., 3., 2.7, -2., -2.}}; // MinPtXiPi, MinPtXiKa, MinPtXiPiPi, MinMassXiPi, MinMassXiKa, MinMassXiPiPi, MaxMassXiPi, MaxMassXiKa, MaxMassXiPiPi, CosPaXiBach, CosPaXiBachBach -static const std::vector labelsColumnsCharmBarCuts = {"MinPtXiPi", "MinPtXiKa", "MinPtXiPiPi", "MinMassXiPi", "MinMassXiKa", "MinMassXiPiPi", "MaxMassXiPi", "MaxMassXiKa", "MaxMassXiPiPi", "CosPaXiBach", "CosPaXiBachBach"}; +constexpr float cutsCharmBaryons[1][15] = {{5., 5., 1000., 2.35, 2.60, 2.35, 3., 3., 2.7, -2., -2., 1.e6, 1.e6, -1., -1.}}; // MinPtXiPi, MinPtXiKa, MinPtXiPiPi, MinMassXiPi, MinMassXiKa, MinMassXiPiPi, MaxMassXiPi, MaxMassXiKa, MaxMassXiPiPi, CosPaXiBach, CosPaXiBachBach, Chi2PcaXiBach, Chi2PcaXiBachBach, DecLenXiBach, DecLenBachBach +static const std::vector labelsColumnsCharmBarCuts = {"MinPtXiPi", "MinPtXiKa", "MinPtXiPiPi", "MinMassXiPi", "MinMassXiKa", "MinMassXiPiPi", "MaxMassXiPi", "MaxMassXiKa", "MaxMassXiPiPi", "CosPaXiBach", "CosPaXiBachBach", "Chi2PcaXiBach", "Chi2PcaXiBachBach", "DecLenXiBach", "DecLenBachBach"}; + +// proton for SigmaC-pr trigger +constexpr float cutsSigmaCPrDefault[3][1] = { + {0.399}, // ptPrMin + {4.501}, // ptPrMax + {1.0} // ptTOFThreshold +}; +static const std::vector labelsRowsSigmaCPr = { + "ptPrMin", + "ptPrMax", + "ptTOFThreshold"}; +static const std::vector labelsColumnsSigmaCPr = { + "SigmaCPr"}; constexpr int requireStrangenessTrackedXi[1][2] = {{1, 0}}; static const std::vector labelsColumnsCharmBaryons = {"CharmBarToXiBach", "CharmBarToXiBachBach"}; @@ -388,7 +403,7 @@ static constexpr double cutsTrackDummy[o2::analysis::hf_cuts_single_track::NBins 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}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}, {1.1}}; // one for each trigger +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}, {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 @@ -415,6 +430,10 @@ class HfFilterHelper mForceTofProtonForFemto = forceTofProtons; mForceTofDeuteronForFemto = forceTofDeuterons; } + void setForceTofForLcResonances(bool forceTofProtons) + { + mForceTofProtonForLcResonances = forceTofProtons; + } void setPtBinsSingleTracks(const std::vector& ptBins) { mPtBinsTracks = ptBins; } void setPtBinsBeautyHadrons(const std::vector& ptBins) { mPtBinsBeautyHadrons = ptBins; } void setCutsSingleTrackBeauty(const o2::framework::LabeledArray& cutsSingleTrack3P, const o2::framework::LabeledArray& cutsSingleTrack4P, const o2::framework::LabeledArray& cutsSingleToJPsi) @@ -479,6 +498,19 @@ class HfFilterHelper mPtMinSigmaCPlusPlus = minPtSigmaCPlusPlus; mPtMinSigmaC2520PlusPlus = minPtSigmaC2520PlusPlus; } + void setParSigmaCPr(float minDeltaMassSigmaC, float maxDeltaMassSigmaC, float minPtSigmaC, float minPtProton, float maxPtProton, float minPtForTOF, bool forceTOF) + { + mMinDeltaMassScSigmaCPr = minDeltaMassSigmaC; + mMaxDeltaMassScSigmaCPr = maxDeltaMassSigmaC; + + mMinPtScSigmaPr = minPtSigmaC; + + mMinPtPrSigmaCPr = minPtProton; + mMaxPtPrSigmaCPr = maxPtProton; + + mForceTOFForPrSigmaCPr = forceTOF; + mThresholdPtTOFForPrSigmaCPr = minPtForTOF; + } void setPtRangeSoftKaonXicResoToSigmaC(float minPt, float maxPt) { mPtMinSoftKaonForXicResoToSigmaC = minPt; @@ -502,6 +534,7 @@ class HfFilterHelper void setNsigmaProtonCutsForFemto(std::array nSigmaCuts) { mNSigmaPrCutsForFemto = nSigmaCuts; } void setNsigmaDeuteronCutsForFemto(std::array nSigmaCuts) { mNSigmaDeCutsForFemto = nSigmaCuts; } + void setNsigmaProtonCutsForSigmaCPr(std::array nSigmaCuts) { mNSigmaPrCutsForSigmaCPr = nSigmaCuts; } void setDeuteronTrackSelectionForFemto(float minTpcCluster, float minTpcRow, float minTpcCrossedOverFound, float maxTpcShared, float maxTpcFracShared, float minItsCluster, float minItsIbCluster) { @@ -566,7 +599,7 @@ class HfFilterHelper mNSigmaTofKaonFromXicResoToSigmaC = nSigmaTof; } - void setXiBachelorSelections(float ptMinXiPi, float ptMinXiKa, float ptMinXiPiPi, float massMinXiPi, float massMinXiKa, float massMinXiPiPi, float massMaxXiPi, float massMaxXiKa, float massMaxXiPiPi, float cosPaMinXiBach, float cosPaMinXiBachBach) + void setXiBachelorSelections(float ptMinXiPi, float ptMinXiKa, float ptMinXiPiPi, float massMinXiPi, float massMinXiKa, float massMinXiPiPi, float massMaxXiPi, float massMaxXiKa, float massMaxXiPiPi, float cosPaMinXiBach, float cosPaMinXiBachBach, float chi2PcaMaxXiBach, float chi2PcaMaxXiBachBach, float decLenMinXiBach, float decLenMinXiBachBach) { mPtMinXiBach[0] = ptMinXiPi; mPtMinXiBach[1] = ptMinXiKa; @@ -579,6 +612,10 @@ class HfFilterHelper mMassMaxXiBach[2] = massMaxXiPiPi; mCosPaMinXiBach[0] = cosPaMinXiBach; mCosPaMinXiBach[1] = cosPaMinXiBachBach; + mChi2PcaMaxXiBach[0] = chi2PcaMaxXiBach; + mChi2PcaMaxXiBach[1] = chi2PcaMaxXiBachBach; + mDecLenMinXiBach[0] = decLenMinXiBach; + mDecLenMinXiBach[1] = decLenMinXiBachBach; } void setTpcPidCalibrationOption(int opt) { mTpcPidCalibrationOption = opt; } @@ -603,6 +640,15 @@ class HfFilterHelper mSigmaPars3Prongs[1] = 0.00176f; mDeltaMassPars3Prongs[0] = -0.013f; mDeltaMassPars3Prongs[1] = 0.00029f; + } else if (recoPass == "2026_pass1") { + mSigmaPars2Prongs[0] = 0.01424f; + mSigmaPars2Prongs[1] = 0.00178f; + mDeltaMassPars2Prongs[0] = 0.004f; + mDeltaMassPars2Prongs[1] = 0.0001f; + mSigmaPars3Prongs[0] = 0.00796f; + mSigmaPars3Prongs[1] = 0.00176f; + mDeltaMassPars3Prongs[0] = 0.004f; + mDeltaMassPars3Prongs[1] = 0.0001f; } else { LOGP(fatal, "Mass resolution parametrisation {} not supported! Please set 2023_pass3", recoPass.data()); } @@ -624,7 +670,7 @@ class HfFilterHelper template int16_t isSelectedTrackForSoftPionOrBeauty(const T& track, const T1& trackPar, const T2& dca); template - bool isSelectedTrack4Femto(const T1& track, const T2& trackPar, const int& activateQA, H2 hTPCPID, H2 hTOFPID, const int& trackSpecies); + bool isSelectedTrack4Corr(const T1& track, const T2& trackPar, const int& activateQA, H2 hTPCPID, H2 hTOFPID, const int& trackSpecies); template int8_t isDzeroPreselected(const T& trackPos, const T& trackNeg); template @@ -744,6 +790,7 @@ class HfFilterHelper float mPtMinSigmaC2520PlusPlus{0.f}; // pt min SigmaC(2520)++ candidate std::array mNSigmaPrCutsForFemto{3., 3., 3., -4.}; // cut values for Nsigma TPC, TOF, combined, ITS for femto protons std::array mNSigmaDeCutsForFemto{3., 3., 3., -4.}; // cut values for Nsigma TPC, TOF, combined, ITS for femto deuterons + std::array mNSigmaPrCutsForSigmaCPr{3., 3., 3., -4.}; // cut values for Nsigma TPC, TOF, combined, ITS for proton in Sc-p correlation float mNSigmaTpcPrCutForCharmBaryons{3.}; // maximum Nsigma TPC for protons in Lc and Xic decays float mNSigmaTofPrCutForCharmBaryons{3.}; // maximum Nsigma TOF for protons in Lc and Xic decays float mNSigmaTpcKaCutFor3Prongs{3.}; // maximum Nsigma TPC for kaons in 3-prong decays @@ -788,10 +835,13 @@ class HfFilterHelper float mNSigmaTofKaonFromXicResoToSigmaC{3.}; // maximum Nsigma TOF for kaons in Xic*->SigmaC-Kaon bool mForceTofProtonForFemto = true; // flag to force TOF PID for protons bool mForceTofDeuteronForFemto = false; // flag to force TOF PID for deuterons + bool mForceTofProtonForLcResonances = false; // flag to force TOF PID for protons in Lc resonances std::array mPtMinXiBach{5., 5., 5.}; // minimum pT for XiBachelor candidates std::array mMassMinXiBach{2.35, 2.6, 2.35}; // minimum invariant-mass for XiBachelor candidates std::array mMassMaxXiBach{3.0, 3.0, 2.7}; // maximum invariant-mass for XiBachelor candidates std::array mCosPaMinXiBach{-2.f, -2.f}; // minimum cosine of pointing angle for XiBachelor candidates + std::array mChi2PcaMaxXiBach{1.e6, 1.e6}; // minimum chi2PCA for XiBachelor candidates + std::array mDecLenMinXiBach{-2.f, -2.f}; // minimum decay length for XiBachelor candidates std::array, kNBeautyParticles> mCutsBhad{}; // selections for B-hadron candidates (DeltaMass, CPA, DecayLength, ImpactParameterProduct) o2::framework::LabeledArray mCutsBhadToJPsi{}; // selections for B->JPsi candidates (PtMinMu, DeltaMass, CPA, DecayLength) float mMinTpcCluster{90.}; // Minimum number of TPC clusters required on a track @@ -801,6 +851,15 @@ class HfFilterHelper float mMaxTpcFracShared{1.}; // Maximum allowed fraction of shared TPC clusters relative to total clusters float mMinItsCluster{1.}; // Minimum required number of ITS clusters float mMinItsIbCluster{1.}; // Minimum required number of ITS clusters for IB + // SigmaC–p (ScPr) trigger + float mMinDeltaMassScSigmaCPr{0.15f}; // min Delta mass (SigmaC) for SigmaC-Proton trigger + float mMaxDeltaMassScSigmaCPr{0.19f}; // max Delta mass (SigmaC) for SigmaC-Proton trigger + float mMinPtScSigmaPr{4.99f}; // min pT(SigmaC) for SigmaC-Proton trigger + float mMinPtPrSigmaCPr{0.399f}; // min pT(proton) for SigmaC-Proton trigger + float mMaxPtPrSigmaCPr{4.501f}; // max pT(proton) for SigmaC-Proton trigger + bool mForceTOFForPrSigmaCPr{true}; // force TOF for protonfor SigmaC-Proton trigger + float mThresholdPtTOFForPrSigmaCPr{1.0f}; // pT threshold above which TOF is required for SigmaC-Proton trigger + // PID recalibrations int mTpcPidCalibrationOption{0}; // Option for TPC PID calibration (0 -> AO2D, 1 -> postcalibrations, 2 -> alternative bethe bloch parametrisation) std::array mHistMapPiPrKaDe{}; // Map for TPC PID postcalibrations for pions, kaon, protons and deuterons @@ -867,7 +926,7 @@ inline int16_t HfFilterHelper::isSelectedTrackForSoftPionOrBeauty(const T& track return kRejected; } - if constexpr (whichTrigger == kSigmaCPPK || whichTrigger == kSigmaC0K0) { + if constexpr (whichTrigger == kSigmaCPPK || whichTrigger == kSigmaC0K0 || whichTrigger == kSigmaCPr) { // SigmaC0,++ soft pion pt cut if (pT < mPtMinSoftPionForSigmaC || pT > mPtMaxSoftPionForSigmaC) { @@ -931,7 +990,7 @@ inline int16_t HfFilterHelper::isSelectedTrackForSoftPionOrBeauty(const T& track /// \param trackSpecies flag to choose proton or deuteron /// \return true if track passes all cuts template -inline bool HfFilterHelper::isSelectedTrack4Femto(const T1& track, const T2& trackPar, const int& activateQA, H2 hTPCPID, H2 hTOFPID, const int& trackSpecies) +inline bool HfFilterHelper::isSelectedTrack4Corr(const T1& track, const T2& trackPar, const int& activateQA, H2 hTPCPID, H2 hTOFPID, const int& trackSpecies) { float pt = trackPar.getPt(); float ptMin, ptMax, ptThresholdPidStrategy; @@ -954,6 +1013,13 @@ inline bool HfFilterHelper::isSelectedTrack4Femto(const T1& track, const T2& tra forceTof = mForceTofDeuteronForFemto; ptThresholdPidStrategy = mPtThresholdDeuteronForFemto; break; + case kProtonForScPrCorr: + ptMin = mMinPtPrSigmaCPr; + ptMax = mMaxPtPrSigmaCPr; + nSigmaCuts = mNSigmaPrCutsForSigmaCPr; + forceTof = mForceTOFForPrSigmaCPr; + ptThresholdPidStrategy = mThresholdPtTOFForPrSigmaCPr; + break; default: return false; // Unknown particle type } @@ -971,27 +1037,27 @@ inline bool HfFilterHelper::isSelectedTrack4Femto(const T1& track, const T2& tra return false; // use only global tracks } // PID evaluation - float NSigmaITS = (trackSpecies == kProtonForFemto) ? track.itsNSigmaPr() : track.itsNSigmaDe(); // only used for deuteron - float NSigmaTPC = (trackSpecies == kProtonForFemto) ? track.tpcNSigmaPr() : track.tpcNSigmaDe(); - float NSigmaTOF = (trackSpecies == kProtonForFemto) ? track.tofNSigmaPr() : track.tofNSigmaDe(); + float NSigmaITS = (trackSpecies == kDeuteronForFemto) ? track.itsNSigmaDe() : track.itsNSigmaPr(); // only used for deuteron + float NSigmaTPC = (trackSpecies == kDeuteronForFemto) ? track.tpcNSigmaDe() : track.tpcNSigmaPr(); + float NSigmaTOF = (trackSpecies == kDeuteronForFemto) ? track.tofNSigmaDe() : track.tofNSigmaPr(); if (!forceTof && !track.hasTOF()) { NSigmaTOF = 0.; // always accepted } // Apply TPC PID post-calibration(only available for proton, dummy for deuteron) if (mTpcPidCalibrationOption == 1) { - NSigmaTPC = getTPCPostCalib(track, trackSpecies == kProtonForFemto ? kPr : kDe); + NSigmaTPC = getTPCPostCalib(track, trackSpecies == kDeuteronForFemto ? kDe : kPr); } else if (mTpcPidCalibrationOption == 2) { if (track.sign() > 0) { - NSigmaTPC = getTPCSplineCalib(track, trackSpecies == kProtonForFemto ? kPr : kDe); + NSigmaTPC = getTPCSplineCalib(track, trackSpecies == kDeuteronForFemto ? kDe : kPr); } else { - NSigmaTPC = getTPCSplineCalib(track, trackSpecies == kProtonForFemto ? kAntiPr : kAntiDe); + NSigmaTPC = getTPCSplineCalib(track, trackSpecies == kDeuteronForFemto ? kAntiDe : kAntiPr); } } float NSigma = std::sqrt(NSigmaTPC * NSigmaTPC + NSigmaTOF * NSigmaTOF); float momentum = track.p(); - if (trackSpecies == kProtonForFemto) { + if (trackSpecies == kProtonForFemto || trackSpecies == kProtonForScPrCorr) { if (momentum <= ptThresholdPidStrategy) { if (NSigma > nSigmaCuts[2]) { return false; @@ -1331,7 +1397,15 @@ inline int8_t HfFilterHelper::isSelectedSigmaCInDeltaMassRange(const T& pTrackSa } else if constexpr (charge == 2) { isSigmaC2455 = (mDeltaMassMinSigmaCPlusPlus < deltaMassPKPi && deltaMassPKPi < mDeltaMassMaxSigmaCPlusPlus && ptSigmaC > mPtMinSigmaCPlusPlus); isSigmaC2520 = (mDeltaMassMinSigmaC2520PlusPlus < deltaMassPKPi && deltaMassPKPi < mDeltaMassMaxSigmaC2520PlusPlus && ptSigmaC > mPtMinSigmaC2520PlusPlus); + } else if constexpr (charge == -1) { + if (deltaMassPKPi > mMinDeltaMassScSigmaCPr && deltaMassPKPi < mMaxDeltaMassScSigmaCPr && ptSigmaC > mMinPtScSigmaPr) { // sigmaC charge independent for SigmaCPr + SETBIT(retValue, 4); // SigmaCPr bit + if (activateQA) { + hMassVsPt->Fill(ptSigmaC, deltaMassPKPi); + } + } } + if (isSigmaC2455 || isSigmaC2520) { retValue |= BIT(0); if (isSigmaC2455) { @@ -1346,6 +1420,7 @@ inline int8_t HfFilterHelper::isSelectedSigmaCInDeltaMassRange(const T& pTrackSa } } } + if (TESTBIT(isSelectedLc, 1)) { /// Lc->piKp case auto invMassLcToPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massKa, massProton}); @@ -1360,6 +1435,13 @@ inline int8_t HfFilterHelper::isSelectedSigmaCInDeltaMassRange(const T& pTrackSa } else if constexpr (charge == 2) { isSigmaC2455 = (mDeltaMassMinSigmaCPlusPlus < deltaMassPiKP && deltaMassPiKP < mDeltaMassMaxSigmaCPlusPlus && ptSigmaC > mPtMinSigmaCPlusPlus); isSigmaC2520 = (mDeltaMassMinSigmaC2520PlusPlus < deltaMassPiKP && deltaMassPiKP < mDeltaMassMaxSigmaC2520PlusPlus && ptSigmaC > mPtMinSigmaC2520PlusPlus); + } else if constexpr (charge == -1) { + if (deltaMassPiKP > mMinDeltaMassScSigmaCPr && deltaMassPiKP < mMaxDeltaMassScSigmaCPr && ptSigmaC > mMinPtScSigmaPr) { // sigmaC charge independent for SigmaCPr + SETBIT(retValue, 4); // SigmaCPr bit + if (activateQA) { + hMassVsPt->Fill(ptSigmaC, deltaMassPiKP); + } + } } if (isSigmaC2455 || isSigmaC2520) { retValue |= BIT(1); @@ -2034,7 +2116,8 @@ inline bool HfFilterHelper::isSelectedKaon4Charm3ProngOrBeautyToJPsi(const T& tr template inline bool HfFilterHelper::isSelectedProtonFromLcResoOrThetaC(const T& track) { - + bool forceTOF = mForceTofProtonForLcResonances; + float NSigmaTOF = track.tofNSigmaPr(); // pt selections float pt = track.pt(); if constexpr (is4ThetaC) { @@ -2046,6 +2129,12 @@ inline bool HfFilterHelper::isSelectedProtonFromLcResoOrThetaC(const T& track) return false; } } + if (track.hasTOF()) { + if (std::fabs(NSigmaTOF) > mNSigmaTofPrCutForCharmBaryons) + return false; + } else if (forceTOF) { + return false; + } return true; } @@ -2364,7 +2453,7 @@ inline bool HfFilterHelper::isSelectedXiBach(T const& trackParCasc, T const& tra bool isSelected = isSelectedXiPi || isSelectedXiKa; - if (isSelected && mCosPaMinXiBach[0] > -1.f) { // if selected by pT and mass, check topology if applicable + if (isSelected && (mCosPaMinXiBach[0] > -1.f || mChi2PcaMaxXiBach[0] < 1.e6 || mDecLenMinXiBach[0] > 0.)) { // if selected by pT and mass, check topology if applicable int nCand = 0; try { nCand = dcaFitter.process(trackParCasc, trackParBachelor); @@ -2384,11 +2473,19 @@ inline bool HfFilterHelper::isSelectedXiBach(T const& trackParCasc, T const& tra trackBachProp.getPxPyPzGlo(momBach); auto momXiBach = RecoDecay::pVec(momCasc, momBach); + if (dcaFitter.getChi2AtPCACandidate() > mChi2PcaMaxXiBach[0]) { + return false; + } + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; if (RecoDecay::cpa(primVtx, std::array{vtx[0], vtx[1], vtx[2]}, momXiBach) < mCosPaMinXiBach[0]) { return false; } + if (RecoDecay::distance(primVtx, vtx) < mDecLenMinXiBach[0]) { + return false; + } + if (activateQA) { if (isSelectedXiPi) { hMassVsPtXiPi->Fill(ptXiBach, massXiPi); @@ -2428,7 +2525,7 @@ inline bool HfFilterHelper::isSelectedXiBachBach(T const& trackParCasc, std::arr return false; } - if (mCosPaMinXiBach[1] > -1.f) { // check topology if applicable + if (mCosPaMinXiBach[1] > -1.f || mChi2PcaMaxXiBach[1] < 1.e6 || mDecLenMinXiBach[0] > 0.) { // check topology if applicable int nCand = 0; if constexpr (Nprongs == 3) { try { @@ -2465,11 +2562,19 @@ inline bool HfFilterHelper::isSelectedXiBachBach(T const& trackParCasc, std::arr } auto momXiBachBach = RecoDecay::pVec(momCasc, momBachFirst, momBachSecond); + if (dcaFitter.getChi2AtPCACandidate() > mChi2PcaMaxXiBach[1]) { + return false; + } + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; if (RecoDecay::cpa(primVtx, std::array{vtx[0], vtx[1], vtx[2]}, momXiBachBach) < mCosPaMinXiBach[1]) { return false; } + if (RecoDecay::distance(primVtx, vtx) < mDecLenMinXiBach[1]) { + return false; + } + if (activateQA) { hMassVsPtXiPiPi->Fill(ptXiBachBach, massXiPiPi); } diff --git a/EventFiltering/PWGJE/fullJetFilter.cxx b/EventFiltering/PWGJE/fullJetFilter.cxx index 25096b7bb7a..b47b9354eb3 100644 --- a/EventFiltering/PWGJE/fullJetFilter.cxx +++ b/EventFiltering/PWGJE/fullJetFilter.cxx @@ -12,35 +12,50 @@ // Full Jet Filter // Author: Gijs van Weelden -#include -#include -#include -#include -#include +#include "../filterTables.h" -#include +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsCTP/Configuration.h" -#include "EMCALBase/Geometry.h" -#include "ReconstructionDataFormats/Track.h" -#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 "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/CCDB/TriggerAliases.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include -#include "../filterTables.h" +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/EventFiltering/PWGJE/jetFilter.cxx b/EventFiltering/PWGJE/jetFilter.cxx index 47761d62c1e..d9f9f153333 100644 --- a/EventFiltering/PWGJE/jetFilter.cxx +++ b/EventFiltering/PWGJE/jetFilter.cxx @@ -13,26 +13,23 @@ #include "../filterTables.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetBkgSubUtils.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/Jet.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include diff --git a/EventFiltering/PWGJE/jetHFFilter.cxx b/EventFiltering/PWGJE/jetHFFilter.cxx index 6657e785751..f5a3aebdf40 100644 --- a/EventFiltering/PWGJE/jetHFFilter.cxx +++ b/EventFiltering/PWGJE/jetHFFilter.cxx @@ -11,31 +11,24 @@ // Author: Nima Zardoshti -#include -#include -#include +#include "../filterTables.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGJE/DataModel/Jet.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "../filterTables.h" - -#include "Framework/HistogramRegistry.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/EventFiltering/PWGLF/filterdoublephi.cxx b/EventFiltering/PWGLF/filterdoublephi.cxx index 9a7a6d42dba..ac4b0fe5327 100644 --- a/EventFiltering/PWGLF/filterdoublephi.cxx +++ b/EventFiltering/PWGLF/filterdoublephi.cxx @@ -16,36 +16,30 @@ #include "../filterTables.h" -#include "PWGLF/DataModel/ReducedDoublePhiTables.h" - -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "CommonConstants/MathConstants.h" -#include "MathUtils/BetheBlochAleph.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include -#include -#include -#include // FIXME +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include -#include // FIXME - -#include -#include +#include #include #include #include diff --git a/EventFiltering/PWGLF/filterf1proton.cxx b/EventFiltering/PWGLF/filterf1proton.cxx index 64fe2761e18..9d345cc9194 100644 --- a/EventFiltering/PWGLF/filterf1proton.cxx +++ b/EventFiltering/PWGLF/filterf1proton.cxx @@ -16,44 +16,43 @@ #include "../filterTables.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/Utils/strangenessBuilderHelper.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/TrackParametrization.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include -#include -#include - -#include +#include +#include +#include #include +#include #include #include diff --git a/EventFiltering/PWGLF/nucleiFilter.cxx b/EventFiltering/PWGLF/nucleiFilter.cxx index c336bf381c6..0a50f17cd0a 100644 --- a/EventFiltering/PWGLF/nucleiFilter.cxx +++ b/EventFiltering/PWGLF/nucleiFilter.cxx @@ -8,41 +8,54 @@ // 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. -// O2 includes #include "../filterTables.h" #include "PWGLF/DataModel/LFPIDTOFGenericTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" #include "PWGLF/Utils/pidTOFGeneric.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/MetadataHelper.h" #include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsTOF/ParameterContainers.h" -#include "MathUtils/BetheBlochAleph.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector4D.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include + +#include #include +#include +#include #include #include #include diff --git a/EventFiltering/PWGLF/strangenessFilter.cxx b/EventFiltering/PWGLF/strangenessFilter.cxx index 33d83d92d6f..dde0d18f4c8 100644 --- a/EventFiltering/PWGLF/strangenessFilter.cxx +++ b/EventFiltering/PWGLF/strangenessFilter.cxx @@ -16,34 +16,53 @@ #include "../filterTables.h" +#include "PWGLF/DataModel/LFKinkDecayTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/Utils/strangenessBuilderHelper.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/TrackParametrization.h" - -#include "TVector3.h" - +#include "Common/DataModel/PIDResponseTOF.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include #include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -78,8 +97,10 @@ struct strangenessFilter { HistogramRegistry QAHistosTopologicalVariables{"QAHistosTopologicalVariables", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry QAHistosTriggerParticles{"QAHistosTriggerParticles", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry QAHistosStrangenessTracking{"QAHistosStrangenessTracking", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry QAHistosSigma{"QAHistosSigma", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry EventsvsMultiplicity{"EventsvsMultiplicity", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - OutputObj hProcessedEvents{TH1D("hProcessedEvents", "Strangeness - event filtered;; Number of events", 17, -1., 16.)}; + OutputObj hProcessedEvents{TH1D("hProcessedEvents", "Strangeness - event filtered;; Number of events", 21, -1., 20.)}; 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.)}; @@ -146,9 +167,20 @@ struct strangenessFilter { Configurable hastof{"hastof", 1, "Has TOF (OOB condition)"}; Configurable ptthrtof{"ptthrtof", 1.0, "Pt threshold to apply TOF condition"}; Configurable sel8{"sel8", 0, "Apply sel8 event selection"}; - Configurable LowLimitFT0MMult{"LowLimitFT0MMult", 3100, "FT0M selection for omega + high multiplicity trigger"}; - Configurable LowLimitFT0MMultNorm{"LowLimitFT0MMultNorm", 70, "FT0M selection for omega + high multiplicity trigger with Normalised FT0M"}; - Configurable useNormalisedMult{"useNormalisedMult", 1, "Use avarage multiplicity for HM omega like in multFilter.cxx"}; + Configurable isTriggerTVX{"isTriggerTVX", 1, "Require TVX"}; + struct : ConfigurableGroup { + Configurable HMTrgSelectionForOmegaFT0M{"HMTrgSelectionForOmegaFT0M", 1, "0: none, 1: normalised FT0M, 2: FT0M "}; + Configurable LowLimitHMTrgOmegaT0M{"LowLimitHMTrgOmegaT0M", 3100, "T0M"}; + Configurable LowLimitHMTrgOmegaT0MNorm{"LowLimitHMTrgOmegaT0MNorm", 70, "normalised T0M selection [2] of multFiler"}; + Configurable LowLimitHMTrgT0MNorm{"LowLimitHMTrgT0MNorm", 140, "normalised T0M selection [2] of multFiler"}; + Configurable HMTrgSelectionForOmegaTrks{"HMTrgSelectionForOmegaTrks", 1, "0: none, 1: GlobalMult,2: selectTrack"}; + Configurable LowLimitHMTrgOmegaTrkGlob{"LowLimitHMTrgOmegaTrkGlob", 45, "Omega HM GlobalMult"}; + Configurable LowLimitHMTrgOmegaTrkSel{"LowLimitHMTrgOmegaTrkSel", 50, "Omega HM selectTrackHMO"}; + Configurable LowLimitHMTrgTrkGlob{"LowLimitHMTrgTrksGlob", 100, "HM Omega normalisation GlobalMult"}; + Configurable LowLimitHMTrgTrkSel{"LowLimitHMTrgTrkSel", 50, "HM Omega normalisation selectTrackHMO"}; + Configurable hEtaHM{"hEtaHM", 1.0f, "Eta range for particles defining HM events"}; + Configurable hMinPtHM{"hMinPtHM", 0.2f, "Min pt for particles defining HM events"}; + } cfgHMOmegaCuts; Configurable avPyT0C{"avPyT0C", 8.83, "nch from pythia T0C"}; Configurable avPyT0A{"avPyT0A", 8.16, "nch from pythia T0A"}; Configurable isTimeFrameBorderCut{"isTimeFrameBorderCut", 1, "Apply timeframe border cut"}; @@ -158,9 +190,11 @@ struct strangenessFilter { Configurable massWindowXiNsigma{"massWindowXiNsigma", 6, "Inv. mass window for tracked Xi"}; // Selections criteria for tracks - Configurable hEta{"hEta", 0.9f, "Eta range for trigger particles"}; - Configurable hMinPt{"hMinPt", 1.0f, "Min pt for trigger particles"}; - Configurable isTrackFilter{"isTrackFilter", true, "Apply track myTrackSelections"}; + struct : ConfigurableGroup { + Configurable hEta{"hEta", 0.9f, "Eta range for trigger particles"}; + Configurable hMinPt{"hMinPt", 1.0f, "Min pt for trigger particles"}; + Configurable isTrackFilter{"isTrackFilter", true, "Apply track myTrackSelections"}; + } cfgTrackCuts; // Settings for strangeness tracking filter Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -190,6 +224,23 @@ struct strangenessFilter { Configurable maxCpaTrackedXi{"maxCpaTrackedXi", 1., "Maximum CPA for tracked cascades"}; Configurable minDcaTrackedOmega{"minDcaTrackedOmega", -1., "Minimum DCA for tracked cascades (ST)"}; Configurable maxCpaTrackedOmega{"maxCpaTrackedOmega", 1., "Maximum CPA for tracked cascades (ST)"}; + + // Settings for sigmaplus filter + struct : ConfigurableGroup { + Configurable nsigmatpcSigma{"nsigmatpcSigma", 3.f, "N Sigmas TPC Sigma"}; + Configurable nsigmatofSigma{"nsigmatofSigma", 3.f, "N Sigmas TOF Sigma"}; + Configurable minMassSigma{"minMassSigma", 1.15f, "min mass for Sigma"}; + Configurable maxMassSigma{"maxMassSigma", 1.25f, "max mass for Sigma"}; + Configurable minPtSigma{"minPtSigma", 1.2f, "min Pt for Sigma"}; + Configurable minQtAPSigma{"minQtAPSigma", 0.15f, "min QtAP for Sigma"}; + Configurable maxQtAPSigma{"maxQtAPSigma", 0.20f, "max QtAP for Sigma"}; + Configurable maxDCAtoPVSigma{"maxDCAtoPVSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; + Configurable minRadiusSigma{"minRadiusSigma", 19.f, "Min radius for Sigma+ decay vertex (cm)"}; + Configurable minCosPASigma{"minCosPASigma", 0.995f, "Min Cosine of pointing angle for Sigma candidates"}; + Configurable minPtProtonTOF{"minPtProtonTOF", 0.75f, "Min Pt for proton to have TOF signal (GeV/c)"}; + Configurable maxKStarSigmaProton{"maxKStarSigmaProton", 0.8f, "Max k* for Sigma-Proton pairs (GeV/c)"}; + } cfgSigma; + Configurable> parSigmaMass{ "parSigmaMass", {stfilter::massSigmaParameters[0], 4, 2, @@ -209,9 +260,12 @@ struct strangenessFilter { bool selectTrack(const auto& track) { - return track.pt() > hMinPt && std::abs(track.eta()) < hEta && track.tpcNClsCrossedRows() >= tpcmincrossedrows && track.tpcCrossedRowsOverFindableCls() >= 0.8f && track.tpcChi2NCl() <= 4.f && track.itsChi2NCl() <= 36.f && (track.itsClusterMap() & 0x7) != 0; + return track.pt() > cfgTrackCuts.hMinPt && std::abs(track.eta()) < cfgTrackCuts.hEta && track.tpcNClsCrossedRows() >= tpcmincrossedrows && track.tpcChi2NCl() <= 4.f && track.itsChi2NCl() <= 36.f && (track.itsClusterMap() & 0x7) != 0; + } + bool selectTrackOHM(const auto& track) + { + return track.pt() > cfgHMOmegaCuts.hMinPtHM && std::abs(track.eta()) < cfgHMOmegaCuts.hEtaHM && track.tpcNClsCrossedRows() >= tpcmincrossedrows && track.tpcChi2NCl() <= 4.f && track.itsChi2NCl() <= 36.f && (track.itsClusterMap() & 0x7) != 0; } - float getV0V0DCA(TVector3 v01pos, TVector3 v01mom, TVector3 v02pos, TVector3 v02mom) { TVector3 posdiff = v02pos - v01pos; @@ -287,6 +341,48 @@ struct strangenessFilter { return true; } + float getAlphaAP(const std::array& momMother, const std::array& momKink) + { + std::array momMissing = {momMother[0] - momKink[0], momMother[1] - momKink[1], momMother[2] - momKink[2]}; + float lQlP = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); + float lQlN = std::inner_product(momMother.begin(), momMother.end(), momMissing.begin(), 0.f); + return (lQlP - lQlN) / (lQlP + lQlN); + } + + float getQtAP(const std::array& momMother, const std::array& momKink) + { + float dp = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); + float p2V0 = std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f); + float p2A = std::inner_product(momKink.begin(), momKink.end(), momKink.begin(), 0.f); + return std::sqrt(p2A - dp * dp / p2V0); + } + + float getCosPA(const std::array& momMother, const std::array& decayVertex, const std::array& primaryVertex) + { + std::array decayVec = {decayVertex[0] - primaryVertex[0], decayVertex[1] - primaryVertex[1], decayVertex[2] - primaryVertex[2]}; + float dotProduct = std::inner_product(momMother.begin(), momMother.end(), decayVec.begin(), 0.f); + float momMotherMag = std::sqrt(std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f)); + float decayVecMag = std::sqrt(std::inner_product(decayVec.begin(), decayVec.end(), decayVec.begin(), 0.f)); + return dotProduct / (momMotherMag * decayVecMag); + } + + float getKStar(TLorentzVector const& part1, TLorentzVector const& part2) + { + TLorentzVector trackSum, PartOneCMS, PartTwoCMS, trackRelK; + trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); + PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + void init(o2::framework::InitContext&) { // set V0 parameters in the helper @@ -333,6 +429,10 @@ struct strangenessFilter { hProcessedEvents->GetXaxis()->SetBinLabel(15, aod::filtering::DoubleOmega::columnLabel()); hProcessedEvents->GetXaxis()->SetBinLabel(16, aod::filtering::OmegaXi::columnLabel()); hProcessedEvents->GetXaxis()->SetBinLabel(17, "LL"); + hProcessedEvents->GetXaxis()->SetBinLabel(18, aod::filtering::OmegaHighMultTrk::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(19, aod::filtering::HighMultFT0M::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(20, aod::filtering::HighMultTrk::columnLabel()); + hProcessedEvents->GetXaxis()->SetBinLabel(21, aod::filtering::SigmaProton::columnLabel()); hCandidate->GetXaxis()->SetBinLabel(1, "All"); hCandidate->GetXaxis()->SetBinLabel(2, "PassBuilderSel"); @@ -358,7 +458,8 @@ struct strangenessFilter { std::vector centBinning = {0., 1., 5., 10., 20., 30., 40., 50., 70., 100.}; AxisSpec multAxisNTPV = {100, 0.0f, 100.0f, "N. tracks PV estimator"}; AxisSpec multAxisT0M = {600, 0.0f, 6000.0f, "T0M multiplicity estimator"}; - AxisSpec multAxisT0MNorm = {150, 0.0f, 150.0f, "Normalised T0M multiplicity estimator"}; + AxisSpec multAxisT0MNorm = {200, 0.0f, 200.0f, "Normalised T0M multiplicity estimator"}; + AxisSpec multAxisTrack = {150, 0.0f, 150.0f, "Track multiplicity"}; AxisSpec multAxisV0A = {500, 0.0f, 25000.0f, "V0A multiplicity estimator"}; AxisSpec ximassAxis = {200, 1.28f, 1.36f}; AxisSpec omegamassAxis = {200, 1.59f, 1.75f}; @@ -421,7 +522,14 @@ struct strangenessFilter { EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MNorm", "T0M Normalised of all events", HistType::kTH1F, {multAxisT0MNorm}); EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MwOmegaNorm", "T0M distribution of events w/ Omega candidate - Normalised FT0M", HistType::kTH1F, {multAxisT0MNorm}); EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MNoFT0", "T0M distribution of events without FT0", HistType::kTH1F, {multAxisT0M}); - + EventsvsMultiplicity.add("AllEventsvsMultiplicityTracks", "Track distribution of all events", HistType::kTH1F, {multAxisTrack}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityTrackswOmega", "Track distribution of events w/ Omega candidate", HistType::kTH1F, {multAxisTrack}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityTracksGlob", "MultGlob Track distribution of all events", HistType::kTH1F, {multAxisTrack}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityTracksGlobwOmega", "MultGlob Track distribution of events w/ Omega candidate", HistType::kTH1F, {multAxisTrack}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MTrackswOmega", "Track distribution of events w/ Omega candidate", HistType::kTH1F, {multAxisTrack}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MTracksGlobwOmega", "MultGlob Track distribution of events w/ Omega candidate", HistType::kTH1F, {multAxisTrack}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MTrackswOmega2D", "2D Track vs FT0M normalised distribution of events w/ Omega candidate", HistType::kTH2F, {multAxisTrack, multAxisT0MNorm}); + EventsvsMultiplicity.add("AllEventsvsMultiplicityFT0MTracksGlobwOmega2D", "2D Track vs FT0M normalised distribution of events w/ Omega candidate", HistType::kTH2F, {multAxisTrack, multAxisT0MNorm}); if (doextraQA) { EventsvsMultiplicity.add("AllEventsvsMultiplicityZeqV0A", "ZeqV0A distribution of all events", HistType::kTH1F, {multAxisV0A}); EventsvsMultiplicity.add("hadEventsvsMultiplicityZeqV0A", "ZeqV0A distribution of events with hight pT hadron", HistType::kTH1F, {multAxisV0A}); @@ -510,6 +618,13 @@ struct strangenessFilter { QAHistosStrangenessTracking.add("hPtVsMassTrkOmega", "cascades;p_{T} (GeV/#it{c});m (GeV/#it{c}^2)", HistType::kTH2D, {{200, 0., 10.}, {1000, 1.6, 2.1}}); QAHistosStrangenessTracking.add("hPtVsMassTrkXiSelected", "cascades;p_{T} (GeV/#it{c});m (GeV/#it{c}^2)", HistType::kTH2D, {{200, 0., 10.}, {1000, 1.2, 1.7}}); QAHistosStrangenessTracking.add("hPtVsMassTrkOmegaSelected", "cascades;p_{T} (GeV/#it{c});m (GeV/#it{c}^2)", HistType::kTH2D, {{200, 0., 10.}, {1000, 1.6, 2.1}}); + + // Sigma QA histograms + QAHistosSigma.add("hPtVsMassSigmaPlus", ";p_{T} (GeV/#it{c});m (GeV/#it{c}^2)", HistType::kTH2D, {{20, -5, 5.}, {50, 1.1, 1.3}}); + QAHistosSigma.add("hDecayRadiusSigma", ";R (cm)", HistType::kTH1D, {{100, 0., 40.}}); + QAHistosSigma.add("hPtNSigmaTPCPrPair", ";p_{T} (GeV/#it{c});#sigma_{TPC}", HistType::kTH2D, {{200, -5., 5.}, {200, -5., 5.}}); + QAHistosSigma.add("hPtNSigmaTOFPrPair", ";p_{T} (GeV/#it{c});#sigma_{TOF}", HistType::kTH2D, {{200, -5., 5.}, {200, -5., 5.}}); + QAHistosSigma.add("hKStarSigmaPr", ";k*", HistType::kTH1D, {{200, 0., 2}}); } } @@ -520,11 +635,10 @@ struct strangenessFilter { o2::parameters::GRPMagField* grpmag = ccdb->getForRun("GLO/Config/GRPMagField", run); o2::base::Propagator::initFieldFromGRP(grpmag); mBz = static_cast(grpmag->getNominalL3Field()); - if (useNormalisedMult) + if (cfgHMOmegaCuts.HMTrgSelectionForOmegaFT0M == 1) { mMeanMultT0C = ccdb->getForRun>("Users/e/ekryshen/meanT0C", run); - if (useNormalisedMult) mMeanMultT0A = ccdb->getForRun>("Users/e/ekryshen/meanT0A", run); - + } mDCAFitter.setBz(mBz); mDCAFitter.setPropagateToPCA(propToDCA); mDCAFitter.setMaxR(maxR); @@ -546,8 +660,8 @@ struct strangenessFilter { } // Tables - using CollisionCandidates = soa::Join::iterator; - using TrackCandidates = soa::Join; + using CollisionCandidates = soa::Join::iterator; + using TrackCandidates = soa::Join; float getMassWindow(const stfilter::species s, const float pt, const float nsigma = 6) { @@ -561,25 +675,28 @@ 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], keepEvent[10], keepEvent[11], keepEvent[12]); + 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], keepEvent[12], keepEvent[13], keepEvent[14], keepEvent[15], keepEvent[16]); } - void process(CollisionCandidates const& collision, TrackCandidates const& tracks, aod::Cascades const& cascadesBase, aod::AssignedTrackedCascades const& trackedCascades, aod::AssignedTrackedV0s const& /*trackedV0s*/, aod::AssignedTracked3Bodys const& /*tracked3Bodys*/, aod::V0s const& v0Base, aod::BCs const&, aod::FT0s const& /*ft0s*/) + void process(CollisionCandidates const& collision, TrackCandidates const& tracks, aod::Cascades const& cascadesBase, aod::AssignedTrackedCascades const& trackedCascades, aod::KinkCands const& kinkCands, aod::AssignedTrackedV0s const& /*trackedV0s*/, aod::AssignedTracked3Bodys const& /*tracked3Bodys*/, aod::V0s const& v0Base, aod::BCs const&, aod::FT0s const& /*ft0s*/) { // 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[13]{}; // explicitly zero-initialised + bool keepEvent[17]{}; // explicitly zero-initialised std::vector> v0sFromOmegaID; std::vector> v0sFromXiID; initCCDB(collision.bc().runNumber()); + hProcessedEvents->Fill(-0.5); if (sel8 && !collision.sel8()) { fillTriggerTable(keepEvent); return; } - hProcessedEvents->Fill(-0.5); - + if (isTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + fillTriggerTable(keepEvent); + return; + } if (isTimeFrameBorderCut && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { fillTriggerTable(keepEvent); return; @@ -598,14 +715,14 @@ struct strangenessFilter { EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityZeqNTracksPV"), collision.multZeqNTracksPV()); } - Bool_t isHighMultEvent = 0; + Bool_t isHighMultEvent = 0; // tail + Bool_t isHighMultEventOmegaCut = 0; // Omega HM cut float multFT0MNorm = 0.f; - EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0M"), collision.multFT0M()); - if (!useNormalisedMult) { - if (collision.multFT0M() > LowLimitFT0MMult) { - isHighMultEvent = 1; - } - } else { + Bool_t isHighMultEventTrk = 0; // tail + Bool_t isHighMultEventTrkOmegaCut = 0; // Omega HM cut + + float multTrack = 0.f; + if (cfgHMOmegaCuts.HMTrgSelectionForOmegaFT0M == 1) { float meanMultT0C = 0.f; float fac_FT0C_ebe = 1.; meanMultT0C = (*mMeanMultT0C)[0]; @@ -646,10 +763,13 @@ struct strangenessFilter { ampneg++; } EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MNorm"), multFT0MNorm); - if (multFT0MNorm > LowLimitFT0MMultNorm) { - isHighMultEvent = 1; + if (multFT0MNorm > cfgHMOmegaCuts.LowLimitHMTrgOmegaT0MNorm) { + isHighMultEventOmegaCut = 1; LOG(debug) << "Found FT0 using norm mult"; } + if (multFT0MNorm > cfgHMOmegaCuts.LowLimitHMTrgT0MNorm) { + isHighMultEvent = 1; + } } else { LOG(warn) << "Found FT0 but, bith amplitudes are <=0 "; EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MNorm"), 148); @@ -663,8 +783,36 @@ struct strangenessFilter { EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MNorm"), 149); EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MNoFT0"), collision.multFT0M()); } + } else if (cfgHMOmegaCuts.HMTrgSelectionForOmegaFT0M == 2) { + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0M"), collision.multFT0M()); + if (collision.multFT0M() > cfgHMOmegaCuts.LowLimitHMTrgOmegaT0M) { + isHighMultEventOmegaCut = 1; + } } + if (cfgHMOmegaCuts.HMTrgSelectionForOmegaTrks == 1) { + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityTracksGlob"), collision.multNTracksGlobal()); + if (collision.multNTracksGlobal() > cfgHMOmegaCuts.LowLimitHMTrgOmegaTrkGlob) { + isHighMultEventTrkOmegaCut = 1; + } + if (collision.multNTracksGlobal() > cfgHMOmegaCuts.LowLimitHMTrgTrkGlob) { + isHighMultEventTrk = 1; + } + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityTracks"), collision.multNTracksGlobal()); + } else if (cfgHMOmegaCuts.HMTrgSelectionForOmegaTrks == 2) { + for (auto& track : tracks) { + if (selectTrackOHM(track)) { + multTrack++; + } + } + if (multTrack > cfgHMOmegaCuts.LowLimitHMTrgOmegaTrkSel) { + isHighMultEventTrkOmegaCut = 1; + } + if (multTrack > cfgHMOmegaCuts.LowLimitHMTrgTrkSel) { + isHighMultEventTrk = 1; + } + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityTracks"), multTrack); + } // constants const float ctauxi = 4.91; // from PDG const float ctauomega = 2.461; // from PDG @@ -1070,7 +1218,7 @@ struct strangenessFilter { // QA tracks int triggcounterAllEv = 0; for (auto track : tracks) { // start loop over tracks - if (isTrackFilter && !selectTrack(track)) { + if (cfgTrackCuts.isTrackFilter && !selectTrack(track)) { continue; } triggcounterAllEv++; @@ -1162,14 +1310,32 @@ struct strangenessFilter { } // Omega in high multiplicity events - if (omegacounter > 0) { + if (omegacounter > 0 && isHighMultEventOmegaCut) { EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MwOmega"), collision.multFT0M()); EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MwOmegaNorm"), multFT0MNorm); } - if (omegacounter > 0 && isHighMultEvent) { + if (omegacounter > 0 && isHighMultEventTrkOmegaCut) { + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityTrackswOmega"), multTrack); + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityTracksGlobwOmega"), collision.multNTracksGlobal()); + } + if (omegacounter > 0 && (isHighMultEventOmegaCut || isHighMultEventTrkOmegaCut)) { // to compute "OR" selectivity + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MTrackswOmega"), multTrack); + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MTracksGlobwOmega"), collision.multNTracksGlobal()); + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MTrackswOmega2D"), multTrack, multFT0MNorm); + EventsvsMultiplicity.fill(HIST("AllEventsvsMultiplicityFT0MTracksGlobwOmega2D"), collision.multNTracksGlobal(), multFT0MNorm); + } + if (omegacounter > 0 && isHighMultEventOmegaCut) { keepEvent[9] = true; } - + if (omegacounter > 0 && isHighMultEventTrkOmegaCut) { + keepEvent[13] = true; + } + if (isHighMultEvent) { // Normalisation tail + keepEvent[14] = true; + } + if (isHighMultEventTrk) { // Normalisation tail + keepEvent[15] = true; + } for (const auto& trackedCascade : trackedCascades) { const auto trackCasc = trackedCascade.track_as(); QAHistosStrangenessTracking.fill(HIST("hPtCascTracked"), trackCasc.pt()); @@ -1316,6 +1482,82 @@ struct strangenessFilter { } } } + // // Sigma - proton trigger definition + for (const auto& kinkCand : kinkCands) { + auto dauTrack = kinkCand.trackDaug_as(); + if (!dauTrack.hasTPC() || !dauTrack.hasTOF()) { + continue; + } + if (std::abs(dauTrack.tpcNSigmaPr()) > cfgSigma.nsigmatpcSigma || std::abs(dauTrack.tofNSigmaPr()) > cfgSigma.nsigmatofSigma) { + continue; + } + if (kinkCand.ptMoth() < cfgSigma.minPtSigma) { + continue; + } + if (kinkCand.mSigmaPlus() < cfgSigma.minMassSigma || kinkCand.mSigmaPlus() > cfgSigma.maxMassSigma) { + continue; + } + QAHistosSigma.fill(HIST("hPtVsMassSigmaPlus"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaPlus()); + std::array momMoth = {kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}; + std::array momDaug = {kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}; + std::array primaryVtx = {collision.posX(), collision.posY(), collision.posZ()}; + std::array decayVtx = {kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}; + float qtAP = getQtAP(momMoth, momDaug); + float alphaAP = getAlphaAP(momMoth, momDaug); + float cosPA = getCosPA(momMoth, decayVtx, primaryVtx); + if (alphaAP < 0) { + continue; + } + if (qtAP < cfgSigma.minQtAPSigma || qtAP > cfgSigma.maxQtAPSigma) { + continue; + } + if (cosPA < cfgSigma.minCosPASigma) { + continue; + } + if (std::abs(kinkCand.dcaMothPv()) > cfgSigma.maxDCAtoPVSigma) { + continue; + } + float decRad = std::hypot(kinkCand.xDecVtx(), kinkCand.yDecVtx()); + if (decRad < cfgSigma.minRadiusSigma) { + continue; + } + QAHistosSigma.fill(HIST("hDecayRadiusSigma"), decRad); + // pair a proton + bool isProtonPaired = false; + for (auto track : tracks) { + if (track.globalIndex() == dauTrack.globalIndex()) { + continue; + } + if (std::abs(track.tpcNSigmaPr()) > cfgSigma.nsigmatpcSigma) { + continue; + } + QAHistosSigma.fill(HIST("hPtNSigmaTPCPrPair"), track.sign() * track.pt(), track.tpcNSigmaPr()); + TLorentzVector sigmaVec, protonVec; + sigmaVec.SetXYZM(kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth(), o2::constants::physics::MassSigmaPlus); + protonVec.SetXYZM(track.px(), track.py(), track.pz(), o2::constants::physics::MassProton); + float kstar = getKStar(sigmaVec, protonVec); + if (kstar > cfgSigma.maxKStarSigmaProton) { + continue; + } + QAHistosSigma.fill(HIST("hKStarSigmaPr"), kstar); + if (track.pt() < cfgSigma.minPtProtonTOF) { + isProtonPaired = true; + break; + } + if (!track.hasTOF()) { + continue; + } + QAHistosSigma.fill(HIST("hPtNSigmaTOFPrPair"), track.sign() * track.pt(), track.tofNSigmaPr()); + if (std::abs(track.tofNSigmaPr()) > cfgSigma.nsigmatofSigma) { + continue; + } + isProtonPaired = true; + break; + } + if (isProtonPaired) { + keepEvent[16] = true; + } + } // Fill centrality dependent histos if (keepEvent[0]) { @@ -1360,6 +1602,18 @@ struct strangenessFilter { if (keepEvent[12]) { hProcessedEvents->Fill(15.5); } + if (keepEvent[13]) { + hProcessedEvents->Fill(16.5); + } + if (keepEvent[14]) { + hProcessedEvents->Fill(17.5); + } + if (keepEvent[15]) { + hProcessedEvents->Fill(18.5); + } + if (keepEvent[16]) { + hProcessedEvents->Fill(19.5); + } // Filling the table fillTriggerTable(keepEvent); } diff --git a/EventFiltering/PWGMM/multFilter.cxx b/EventFiltering/PWGMM/multFilter.cxx index fe641438a43..7ab341b4591 100644 --- a/EventFiltering/PWGMM/multFilter.cxx +++ b/EventFiltering/PWGMM/multFilter.cxx @@ -8,23 +8,42 @@ // 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 "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/filterTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "DataFormatsFT0/Digit.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include #include +#include +#include +#include #include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/EventFiltering/PWGUD/diffractionBCFilter.cxx b/EventFiltering/PWGUD/diffractionBCFilter.cxx index c6ce85ec845..a2c8f8c2ed9 100644 --- a/EventFiltering/PWGUD/diffractionBCFilter.cxx +++ b/EventFiltering/PWGUD/diffractionBCFilter.cxx @@ -8,19 +8,39 @@ // 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. -// O2 includes // // \brief A filter task for diffractive BCs // \author P. Buehler, paul.buehler@oeaw.ac.at // \since December, 2022 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "PWGUD/TableProducer/DGBCCandProducer.h" +#include "../filterTables.h" + #include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/DGSelector.h" #include "PWGUD/Core/UDHelpers.h" -#include "../filterTables.h" +#include "PWGUD/TableProducer/DGBCCandProducer.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/EventFiltering/PWGUD/diffractionFilter.cxx b/EventFiltering/PWGUD/diffractionFilter.cxx index c5adfcf90c5..946f95026e0 100644 --- a/EventFiltering/PWGUD/diffractionFilter.cxx +++ b/EventFiltering/PWGUD/diffractionFilter.cxx @@ -8,20 +8,39 @@ // 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. -// O2 includes // // \brief A filter task for diffractive events // \author P. Buehler, paul.buehler@oeaw.ac.at // \since June 1, 2021 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/EventSelection.h" +#include "../filterTables.h" + #include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/DGSelector.h" #include "PWGUD/Core/UDHelpers.h" -#include "../filterTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/EventFiltering/cefpTask.cxx b/EventFiltering/cefpTask.cxx index 64cf4435b85..eb64a60db54 100644 --- a/EventFiltering/cefpTask.cxx +++ b/EventFiltering/cefpTask.cxx @@ -8,31 +8,47 @@ // 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. -// O2 includes -#include +#include "filterTables.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include #include #include +#include + +#include +#include #include +#include #include #include #include -#include #include #include - -#include "filterTables.h" - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/LHCConstants.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsCTP/Scalers.h" +#include // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) @@ -43,7 +59,7 @@ void customize(std::vector& workflowOptions) std::swap(workflowOptions, options); } -#include "Framework/runDataProcessing.h" +#include using namespace o2; using namespace o2::aod; diff --git a/EventFiltering/filterTables.h b/EventFiltering/filterTables.h index 1371d152e75..cd4ad719297 100644 --- a/EventFiltering/filterTables.h +++ b/EventFiltering/filterTables.h @@ -8,14 +8,19 @@ // 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_FILTERTABLES_H_ #define EVENTFILTERING_FILTERTABLES_H_ +#include + #include -#include +#include +#include #include +#include +#include #include -#include namespace o2::aod { @@ -23,8 +28,6 @@ template struct Hash; } -#include "Framework/ASoA.h" - namespace o2::soa { template @@ -69,6 +72,9 @@ DECLARE_SOA_COLUMN(DiMuon, hasDiMuon, bool); //! dimuon trigger with // EM dielectrons DECLARE_SOA_COLUMN(LMeeIMR, hasLMeeIMR, bool); //! dielectron trigger for intermediate mass region DECLARE_SOA_COLUMN(LMeeHMR, hasLMeeHMR, bool); //! dielectron trigger for high mass region +// EM global muons +DECLARE_SOA_COLUMN(GlobalDimuon, hasGlobalDimuon, bool); //! global dimuon trigger (2 MFT+MCH+MID fwdtracks) + // Electron-muon pair DECLARE_SOA_COLUMN(ElectronMuon, hasElectronMuon, bool); //! dimuon trigger with low pT on muons @@ -89,6 +95,7 @@ DECLARE_SOA_COLUMN(HfCharmBarToXi2Bach, hasHfCharmBarToXi2Bach, bool); DECLARE_SOA_COLUMN(HfPrCharm2P, hasHfPrCharm2P, bool); //! Charm baryon to 2-prong + bachelors DECLARE_SOA_COLUMN(HfSigmaCPPK, hasHfSigmaCPPK, bool); //! SigmaC(2455)++K- and SigmaC(2520)++K- + c.c. DECLARE_SOA_COLUMN(HfSigmaC0K0, hasHfSigmaC0K0, bool); //! SigmaC(2455)0KS0 and SigmaC(2520)0KS0 +DECLARE_SOA_COLUMN(HfSigmaCPr, hasHfSigmaCPr, bool); //! SigmaC(2455)Proton corr 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) @@ -168,7 +175,10 @@ DECLARE_SOA_COLUMN(TrackedOmega, hasTrackedOmega, bool); //! at least 1 DECLARE_SOA_COLUMN(Tracked3Body, hasTracked3Body, bool); //! at least 1 tracked 3Body DECLARE_SOA_COLUMN(OmegaHighMult, hasOmegaHighMult, bool); //! at least 1 Omega + high-mult event DECLARE_SOA_COLUMN(LambdaLambda, lambdaLambda, bool); //! at least 2 lambda satisfying selection - +DECLARE_SOA_COLUMN(OmegaHighMultTrk, hasOmegaHighMultTrk, bool); //! at least 1 Omega + high-mult track event +DECLARE_SOA_COLUMN(HighMultFT0M, hasHighMultFT0M, bool); //! at least 1 Omega + high-mult track event +DECLARE_SOA_COLUMN(HighMultTrk, hasHighMultTrk, bool); //! at least 1 Omega + high-mult track event +DECLARE_SOA_COLUMN(SigmaProton, hasSigmaProton, bool); //! at least 1 Sigma - proton candidate // F1-proton DECLARE_SOA_COLUMN(TriggerEventF1Proton, triggereventf1proton, bool); //! F1 - proton femto trigger event @@ -207,6 +217,9 @@ DECLARE_SOA_COLUMN(EtaPrimeP, hasEtaPrimeP, bool); //! eta'P meson candidate ( DECLARE_SOA_COLUMN(EtaPrimePP, hasEtaPrimePP, bool); //! eta'PP meson candidate (3pi) in the collision DECLARE_SOA_COLUMN(EtaPrimed, hasEtaPrimed, bool); //! eta'd meson candidate (3pi) in the collision +// deuterons non prompt +DECLARE_SOA_COLUMN(H2fromLb, hasH2fromLb, bool); //! deuteron from Lb decay + } // namespace filtering namespace decision @@ -251,6 +264,11 @@ DECLARE_SOA_TABLE(DqFilters, "AOD", "DqFilters", //! filtering::SingleE, filtering::LMeeIMR, filtering::LMeeHMR, filtering::DiElectron, filtering::SingleMuLow, filtering::SingleMuHigh, filtering::DiMuon, filtering::ElectronMuon); using DqFilter = DqFilters::iterator; +// Global dimuons +DECLARE_SOA_TABLE(GlobalDimuonFilters, "AOD", "GlDimuonFilters", //! + filtering::GlobalDimuon); +using GlobalDimuonFilter = GlobalDimuonFilters::iterator; + // heavy flavours DECLARE_SOA_TABLE(HfFilters, "AOD", "HfFilters", //! filtering::HfHighPt2P, @@ -279,7 +297,8 @@ DECLARE_SOA_TABLE(HfFilters, "AOD", "HfFilters", //! filtering::HfBtoJPsiKstar, filtering::HfBtoJPsiPhi, filtering::HfBtoJPsiPrKa, - filtering::HfBtoJPsiPi); + filtering::HfBtoJPsiPi, + filtering::HfSigmaCPr); using HfFilter = HfFilters::iterator; @@ -321,8 +340,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::DoubleOmega, filtering::OmegaXi, filtering::LambdaLambda); - + filtering::Omega, filtering::hadronOmega, filtering::DoubleXi, filtering::TripleXi, filtering::QuadrupleXi, filtering::SingleXiYN, filtering::OmegaLargeRadius, filtering::TrackedXi, filtering::TrackedOmega, filtering::OmegaHighMult, filtering::DoubleOmega, filtering::OmegaXi, filtering::LambdaLambda, filtering::OmegaHighMultTrk, filtering::HighMultFT0M, filtering::HighMultTrk, filtering::SigmaProton); using StrangenessFilter = StrangenessFilters::iterator; // F1 proton @@ -354,6 +372,11 @@ DECLARE_SOA_TABLE(HeavyNeutralMesonFilters, "AOD", "HNMesonFilters", //! using HeavyNeutralMesonFilter = HeavyNeutralMesonFilters::iterator; +// beauty non prompt deuterons +DECLARE_SOA_TABLE(H2fromLbFilters, "AOD", "H2LbFilters", //! + filtering::H2fromLb); +using H2fromLbFilter = H2fromLbFilters::iterator; + // cefp decision DECLARE_SOA_TABLE(CefpDecisions, "AOD", "CefpDecision", //! decision::BCId, decision::GlobalBCId, decision::EvSelBC, decision::CollisionTime, decision::CollisionTimeRes, decision::CefpTriggered0, decision::CefpTriggered1, decision::CefpSelected0, decision::CefpSelected1); @@ -365,11 +388,11 @@ DECLARE_SOA_TABLE(BCRanges, "AOD", "BCRanges", //! using BCRange = BCRanges::iterator; /// List of the available filters, the description of their tables and the name of the tasks -constexpr int NumberOfFilters{14}; -constexpr std::array AvailableFilters{"NucleiFilters", "DiffractionFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "JetHFFilters", "FullJetFilters", "StrangenessFilters", "MultFilters", "PhotonFilters", "F1ProtonFilters", "DoublePhiFilters", "HeavyNeutralMesonFilters"}; -constexpr std::array FilterDescriptions{"NucleiFilters", "DiffFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "JetHFFilters", "FullJetFilters", "LFStrgFilters", "MultFilters", "PhotonFilters", "F1ProtonFilters", "LF2PhiFilters", "HNMesonFilters"}; -constexpr std::array FilteringTaskNames{"o2-analysis-nuclei-filter", "o2-analysis-diffraction-filter", "o2-analysis-dq-filter-pp-with-association", "o2-analysis-hf-filter", "o2-analysis-cf-filter", "o2-analysis-je-filter", "o2-analysis-je-hf-filter", "o2-analysis-fje-filter", "o2-analysis-lf-strangeness-filter", "o2-analysis-mult-filter", "o2-analysis-em-photon-filter", "o2-analysis-lf-f1proton-filter", "o2-analysis-lf-doublephi-filter", "o2-analysis-heavy-neutral-meson-filter"}; -constexpr o2::framework::pack FiltersPack; +constexpr int NumberOfFilters{16}; +constexpr std::array AvailableFilters{"NucleiFilters", "DiffractionFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "JetHFFilters", "FullJetFilters", "StrangenessFilters", "MultFilters", "PhotonFilters", "F1ProtonFilters", "DoublePhiFilters", "HeavyNeutralMesonFilters", "GlobalDimuonFilters", "H2fromLbFilters"}; +constexpr std::array FilterDescriptions{"NucleiFilters", "DiffFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "JetHFFilters", "FullJetFilters", "LFStrgFilters", "MultFilters", "PhotonFilters", "F1ProtonFilters", "LF2PhiFilters", "HNMesonFilters", "GlDimuonFilters", "H2LbFilters"}; +constexpr std::array FilteringTaskNames{"o2-analysis-nuclei-filter", "o2-analysis-diffraction-filter", "o2-analysis-dq-filter-pp-with-association", "o2-analysis-hf-filter", "o2-analysis-cf-filter", "o2-analysis-je-filter", "o2-analysis-je-hf-filter", "o2-analysis-fje-filter", "o2-analysis-lf-strangeness-filter", "o2-analysis-mult-filter", "o2-analysis-em-photon-filter", "o2-analysis-lf-f1proton-filter", "o2-analysis-lf-doublephi-filter", "o2-analysis-heavy-neutral-meson-filter", "o2-analysis-em-global-dimuon-filter", "o2-analysis-h2-from-beauty-filter"}; +constexpr o2::framework::pack FiltersPack; static_assert(o2::framework::pack_size(FiltersPack) == NumberOfFilters); template diff --git a/EventFiltering/macros/cefpOutputChecker.C b/EventFiltering/macros/cefpOutputChecker.C index d053cedf866..48295a1746e 100644 --- a/EventFiltering/macros/cefpOutputChecker.C +++ b/EventFiltering/macros/cefpOutputChecker.C @@ -8,11 +8,16 @@ // 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. -// O2 includes #include +#include +#include #include +#include + +#include + void cefpOutputChecker(std::string histoFile = "AnalysisResults.root", std::string treeFile = "AO2D.root") { TFile referenceFile(histoFile.data()); diff --git a/EventFiltering/macros/checkBCRange.C b/EventFiltering/macros/checkBCRange.C index 9bcc14981f4..413e223bdff 100644 --- a/EventFiltering/macros/checkBCRange.C +++ b/EventFiltering/macros/checkBCRange.C @@ -8,14 +8,21 @@ // 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. -// O2 includes -#include +#include +#include + +#include #include +#include +#include #include -#include "CommonDataFormat/InteractionRecord.h" -#include "CommonDataFormat/IRFrame.h" +#include + +#include +#include +#include using o2::InteractionRecord; using o2::dataformats::IRFrame; diff --git a/EventFiltering/macros/checkBCrangesSkimming.C b/EventFiltering/macros/checkBCrangesSkimming.C index f71212238c3..db58d7d9848 100644 --- a/EventFiltering/macros/checkBCrangesSkimming.C +++ b/EventFiltering/macros/checkBCrangesSkimming.C @@ -8,18 +8,25 @@ // 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. -// O2 includes -#include -#include -#include -#include +#include +#include + #include #include #include #include -#include "CommonDataFormat/InteractionRecord.h" -#include "CommonDataFormat/IRFrame.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include using o2::InteractionRecord; using o2::dataformats::IRFrame; @@ -187,7 +194,7 @@ std::string getRunNumber(std::string fileName) } // Detailed checks for specific trigger, not enabled by default -void checkBCForSelectedTrg(std::vector& originalFrames, std::vector& skimmedFrames, string runNumber, string triggerLabel) +void checkBCForSelectedTrg(std::vector& originalFrames, std::vector& skimmedFrames, std::string runNumber, std::string triggerLabel) { TH1D hTriggerCounter("hTriggerCounter", (runNumber + " " + triggerLabel + ";;Total number of trigger").data(), 2, -0.5, 1.5); @@ -328,7 +335,7 @@ void checkBCForSelectedTrg(std::vector& originalFrames, std::vec void checkBCForSelectedTrg(std::string AnaFileName = "AnalysisResults.root", std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root", int triggerID = 1, bool useAlien = true) { - string runNumber = getRunNumber(originalFileName); + std::string runNumber = getRunNumber(originalFileName); if (useAlien) { TGrid::Connect("alien://"); AnaFileName = "alien://" + AnaFileName; @@ -365,7 +372,7 @@ void checkBCForSelectedTrg(std::string AnaFileName = "AnalysisResults.root", std void checkBCrangesSkimming(std::string AnaFileName = "AnalysisResults.root", std::string originalFileName = "bcRanges_fullrun.root", std::string skimmedFileName = "bcRanges_fullrun_skimmed.root", bool useAlien = true) { - string runNumber = getRunNumber(originalFileName); + std::string runNumber = getRunNumber(originalFileName); if (useAlien) { TGrid::Connect("alien://"); AnaFileName = "alien://" + AnaFileName; diff --git a/EventFiltering/macros/checkSkimming.C b/EventFiltering/macros/checkSkimming.C index 5496f303873..a69f9d5d129 100644 --- a/EventFiltering/macros/checkSkimming.C +++ b/EventFiltering/macros/checkSkimming.C @@ -10,15 +10,17 @@ // or submit itself to any jurisdiction. #include -#include +#include #include +#include #include +#include #include #include -#include -#include #include +#include +#include void checkSkimming(std::string original_path = "AnalysisResults.root", std::string skimmed_path = "AnalysisResults_skimmed.root", TFile* outputFile = nullptr, bool skipDownscaled = true) { @@ -129,4 +131,4 @@ void checkSkimming(std::string listName = "period.txt", bool skipDownscaled = tr counter++; } outputFile->Close(); -} \ No newline at end of file +} diff --git a/EventFiltering/macros/getMenu.C b/EventFiltering/macros/getMenu.C index 02386a68870..f1674d14539 100644 --- a/EventFiltering/macros/getMenu.C +++ b/EventFiltering/macros/getMenu.C @@ -9,17 +9,20 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "CCDB/BasicCCDBManager.h" +#include #include #include #include #include +#include #include +#include +#include #include +#include #include -#include #include #include #include diff --git a/EventFiltering/macros/selectivityPlot.C b/EventFiltering/macros/selectivityPlot.C index 56215bcd3e6..344101a0984 100644 --- a/EventFiltering/macros/selectivityPlot.C +++ b/EventFiltering/macros/selectivityPlot.C @@ -9,6 +9,20 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + void selectivityPlot(int runNumber = 550781, TString inputfile = "AnalysisResults_550781.root", TString outputfolder = "") { TCanvas* Canvas_1 = new TCanvas("Canvas_1", "Canvas_1", 928, 592); diff --git a/EventFiltering/macros/splitFile.C b/EventFiltering/macros/splitFile.C index b38149dca42..b3c182e3c82 100644 --- a/EventFiltering/macros/splitFile.C +++ b/EventFiltering/macros/splitFile.C @@ -8,13 +8,14 @@ // 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. -// O2 includes + +#include +#include +#include +#include +#include #include -#include -#include "TFile.h" -#include "TDirectory.h" -#include "TTree.h" void splitFile(const char* inputFileName = "bcSelection.root", const char* outputFileName1 = "bcRanges.root") { diff --git a/EventFiltering/macros/uploadOTSobjects.C b/EventFiltering/macros/uploadOTSobjects.C index ec60c44ec0a..b1703a6ba45 100644 --- a/EventFiltering/macros/uploadOTSobjects.C +++ b/EventFiltering/macros/uploadOTSobjects.C @@ -12,22 +12,29 @@ #include "Common/Core/ZorroHelper.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" +#include +#include +#include -#include "TFile.h" -#include "TGrid.h" -#include "TH1.h" -#include "TKey.h" -#include "TSystem.h" -#include "TTree.h" +#include +#include +#include +#include +#include +#include +#include -#include +#include + +#include #include +#include #include #include #include +#include #include +#include #include constexpr uint32_t chunkSize = 1000000; diff --git a/EventFiltering/selectBCRange.cxx b/EventFiltering/selectBCRange.cxx index 8a2d200e8e6..a52127fe32e 100644 --- a/EventFiltering/selectBCRange.cxx +++ b/EventFiltering/selectBCRange.cxx @@ -9,15 +9,28 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "filterTables.h" + #include "Common/DataModel/EventSelection.h" -#include "CommonConstants/LHCConstants.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "CommonDataFormat/IRFrame.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" -#include "filterTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index 6f456e2d0ef..8af9d7fef71 100644 --- a/PWGCF/DataModel/CorrelationsDerived.h +++ b/PWGCF/DataModel/CorrelationsDerived.h @@ -139,7 +139,7 @@ DECLARE_SOA_COLUMN(InvMass, invMass, float); DECLARE_SOA_COLUMN(Decay, decay, uint8_t); //! Particle decay enum ParticleDecay { D0ToPiK, - D0barToKPi, + D0barToKPi, // note: often duplicate to D0ToPiK. Choose D0barToKPiExclusive to select uniquely reconstructed D0bars JPsiToEE, JPsiToMuMu, Generic2Prong, @@ -156,7 +156,8 @@ enum ParticleDecay { LambdaToPPiLoose, LambdaToPPiTight, AntiLambdaToPiPLoose, - AntiLambdaToPiPTight + AntiLambdaToPiPTight, + D0barToKPiExclusive }; } // namespace cf2prongtrack DECLARE_SOA_TABLE(CF2ProngTracks, "AOD", "CF2PRONGTRACK", //! Reduced track table diff --git a/PWGCF/DataModel/FemtoDerived.h b/PWGCF/DataModel/FemtoDerived.h index 2c6999853d4..16e52a2e262 100644 --- a/PWGCF/DataModel/FemtoDerived.h +++ b/PWGCF/DataModel/FemtoDerived.h @@ -16,7 +16,8 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGCF/DataModel/SPTableZDC.h b/PWGCF/DataModel/SPTableZDC.h index 6e732ee562e..1410b038e4f 100644 --- a/PWGCF/DataModel/SPTableZDC.h +++ b/PWGCF/DataModel/SPTableZDC.h @@ -18,7 +18,6 @@ #define PWGCF_DATAMODEL_SPTABLEZDC_H_ #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisDataModel.h" diff --git a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt index c65d1705a93..a10cc46db09 100644 --- a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt +++ b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt @@ -44,11 +44,6 @@ o2physics_add_dpl_workflow(robust-fluctuation-observables PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(v0pt-pp-task - SOURCES Diff_pT_fluct_PID.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(factorial-moments SOURCES FactorialMomentsTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore @@ -83,3 +78,8 @@ o2physics_add_dpl_workflow(radial-flow-decorr SOURCES radialFlowDecorr.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(net-prot-cumulants + SOURCES netprotcumulants.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/EbyEFluctuations/Tasks/Diff_pT_fluct_PID.cxx b/PWGCF/EbyEFluctuations/Tasks/Diff_pT_fluct_PID.cxx deleted file mode 100644 index 8d01f25b5cd..00000000000 --- a/PWGCF/EbyEFluctuations/Tasks/Diff_pT_fluct_PID.cxx +++ /dev/null @@ -1,761 +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 This task provides the parameters required to calculate the observable -/// v0(pT) along with its statistical uncertainity using subsampling technique. -/// \author Anna Binoy (anna.binoy@niser.ac.in) - -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" -#include - -#include "TDatabasePDG.h" -#include "TF1.h" -#include "TH1D.h" -#include "TH2D.h" -#include "TList.h" -#include "TLorentzVector.h" -#include "TMath.h" -#include "TProfile.h" -#include "TProfile2D.h" -#include "TRandom3.h" - -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace std; - -#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; - -double massPi = TDatabasePDG::Instance()->GetParticle(211)->Mass(); -double massKa = TDatabasePDG::Instance()->GetParticle(321)->Mass(); -double massPr = TDatabasePDG::Instance()->GetParticle(2212)->Mass(); - -struct Diff_pT_fluct_PID { - // Histogram registry: an object to hold your histograms - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - std::vector>> Subsample; - TRandom3* fRndm = new TRandom3(0); - - Configurable nPtBins_qa{"nBinsPt_qa", 280, "N bins in pT histo qualitative analysis"}; - - Configurable nPtBins{"nBinsPt", 14, "N bins in pT histo"}; - Configurable nEtaBins{"nEtaBins", 100, ""}; - - Configurable ptMax{"ptMax", 3.0, "maximum pT"}; - Configurable ptMin{"ptMin", 0.2, "minimum pT"}; - - Configurable etaMin{"etaMin", 0.4, "Eta min"}; - Configurable etaCut{"etaCut", 0.8, "Eta cut"}; - Configurable rapCut{"rapCut", 0.5, "Rapidity Cut"}; - - Configurable cfgCutPtUpperTPC{"cfgCutPtUpperTPC", 0.6f, "Upper pT cut for PID using TPC only"}; - Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; - Configurable cfgnSigmaCut{"cfgnSigmaCut", 2.0f, "PID nSigma cut"}; - - Configurable cfgnSigmaCut_TPC_pi{"cfgnSigmaCut_TPC_pi", 2.0f, "PID nSigma cut for TPC for pion"}; - Configurable cfgnSigmaCut_TOF_pi{"cfgnSigmaCut_TOF_pi", 3.0f, "PID nSigma cut for TOF for pion"}; - Configurable cfgnSigmaCut_TPC_ka{"cfgnSigmaCut_TPC_ka", 2.0f, "PID nSigma cut for TPC for kaon"}; - Configurable cfgnSigmaCut_TOF_ka{"cfgnSigmaCut_TOF_ka", 3.0f, "PID nSigma cut for TOF for kaon"}; - Configurable cfgnSigmaCut_TPC_pr{"cfgnSigmaCut_TPC_pr", 2.0f, "PID nSigma cut for TPC for proton"}; - Configurable cfgnSigmaCut_TOF_pr{"cfgnSigmaCut_TOF_pr", 3.0f, "PID nSigma cut for TOF for proton"}; - - // QualityCuts - - Configurable dcaXYCut{"dcaXYCut", 0.2, "DCAxy cut"}; - Configurable dcaZCut{"dcaZCut", 2.0, "DCAz cut"}; - Configurable posZCut{"posZCut", 10.0, "cut for vertex Z"}; - - Configurable TPCNCrossedRowsCut{"TPCNCrossedRowsCut", 2.5, "n_TPC crossed rows Cut"}; - Configurable chi2TPCperClstrCut{"chi2TPCperClstrCut", 4, "Chi2 TPC per Cluster Cut"}; - Configurable chi2ITSperClstrCut{"chi2ITSperClstrCut", 36, "Chi2 ITS per Cluster Cut"}; - - ConfigurableAxis dcaXYBins{"dcaXYBins", {100, -0.15, 0.15}, "dcaXY bins"}; - ConfigurableAxis dcaZBins{"dcaZBins", {100, -1.2, 1.2}, "dcaZ bins"}; - - O2_DEFINE_CONFIGURABLE(cfgUse22sEventCut, bool, true, "Use 22s event cut on mult correlations") - - // 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"}; - - // for the sub-sampling - Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; - - // Event selection cuts - Alex - TF1* fMultPVCutLow = nullptr; - TF1* fMultPVCutHigh = nullptr; - TF1* fMultCutLow = nullptr; - TF1* fMultCutHigh = nullptr; - TF1* fMultMultPVCut = nullptr; - - // This is an example of a convenient declaration of "using" - using MyAllTracks = soa::Join; - using MyRun2Collisions = soa::Join; - using MyRun3Collisions = soa::Join; - - void init(InitContext const&) - { - - const AxisSpec axisEvents{5, 0, 5, "Counts"}; - const AxisSpec axisEta{nEtaBins, -1., +1., "#eta"}; - const AxisSpec axisY{nEtaBins, -1., +1., "Rapidity"}; - const AxisSpec axisPt{nPtBins, 0.2, 3., "p_{T} (GeV/c)"}; - const AxisSpec axisPt_qa{nPtBins_qa, 0.2, 3., "p_{T} (GeV/c)"}; - const AxisSpec axisP{nPtBins, 0.2, 3., "p (GeV/c)"}; - const AxisSpec axisCent{100, 0., 100, ""}; - const AxisSpec axis1Bin{1, 0., 1, ""}; - - const AxisSpec axisNumberOfHadronEtaLess0{3000, 0, 3000, "Number of proton eta less than 0"}; - const AxisSpec axisNumberOfProtonEtaLess0{3000, 0, 3000, "Number of proton eta less than 0"}; - const AxisSpec axisNumberOfPionEtaLess0{3000, 0, 3000, "Number of pion eta less than 0"}; - const AxisSpec axisNumberOfKaonEtaLess0{3000, 0, 3000, "Number of kaon eta less than 0"}; - - const AxisSpec axisVtxZ{80, -20., 20., "V_{Z} (cm)"}; - const AxisSpec axisDCAz{dcaZBins, "DCA_{Z} (cm)"}; - const AxisSpec axisDCAxy{dcaXYBins, "DCA_{XY} (cm)"}; - const AxisSpec axisTPCNsigma{500, -5., 5., "n #sigma_{TPC}"}; - const AxisSpec axisTOFNsigma{500, -5., 5., "n #sigma_{TOF}"}; - const AxisSpec axisTPCTOFNsigma{800, -8., 8., "n #sigma_{TOF+TPC}"}; - const AxisSpec axisTPCSignal{720, 20., 200., "#frac{dE}{dx}"}; - const AxisSpec axisTOFSignal{400, 0.2, 1.2, "TOF #beta"}; - const AxisSpec axisChi2{50, 0., 50., "Chi2"}; - const AxisSpec axisCrossedTPC{500, 0, 500, "Crossed TPC"}; - - HistogramConfigSpec TOFnSigmaHist({HistType::kTH2D, {axisPt_qa, axisTOFNsigma}}); - HistogramConfigSpec TOFSignalHist({HistType::kTH2D, {axisPt_qa, axisTOFSignal}}); - HistogramConfigSpec TPCnSigmaHist({HistType::kTH2D, {axisPt_qa, axisTPCNsigma}}); - HistogramConfigSpec TPCSignalHist({HistType::kTH2D, {axisPt_qa, axisTPCSignal}}); - HistogramConfigSpec TPCTOFHist({HistType::kTH2D, {axisTPCNsigma, axisTOFNsigma}}); - HistogramConfigSpec TPCTOFnSigmaHist({HistType::kTH2D, {axisPt_qa, axisTPCTOFNsigma}}); - - histos.add("fA_hadron", "", kTProfile2D, {axisCent, axisPt}); - histos.add("fA_pion", "", kTProfile2D, {axisCent, axisPt}); - histos.add("fA_kaon", "", kTProfile2D, {axisCent, axisPt}); - histos.add("fA_proton", "", kTProfile2D, {axisCent, axisPt}); - - histos.add("fB1_hadron", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fB1_pion", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fB1_kaon", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fB1_proton", "", kTProfile2D, {axisCent, axis1Bin}); - - histos.add("fB2_hadron", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fB2_pion", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fB2_kaon", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fB2_proton", "", kTProfile2D, {axisCent, axis1Bin}); - - histos.add("fC_hadron", "", kTProfile2D, {axisCent, axisPt}); - histos.add("fC_pion", "", kTProfile2D, {axisCent, axisPt}); - histos.add("fC_kaon", "", kTProfile2D, {axisCent, axisPt}); - histos.add("fC_proton", "", kTProfile2D, {axisCent, axisPt}); - - histos.add("fD_hadron", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fD_pion", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fD_kaon", "", kTProfile2D, {axisCent, axis1Bin}); - histos.add("fD_proton", "", kTProfile2D, {axisCent, axis1Bin}); - - // QA Plots: - histos.add("QA/before/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); - histos.add("QA/before/h_TPCChi2perCluster", "TPC #Chi^{2}/Cluster", kTH1D, {axisChi2}); - histos.add("QA/before/h_ITSChi2perCluster", "ITS #Chi^{2}/Cluster", kTH1D, {axisChi2}); - histos.add("QA/before/h_crossedTPC", "Crossed TPC", kTH1D, {axisCrossedTPC}); - histos.add("QA/before/h2_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); - histos.add("QA/before/h2_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); - histos.add("QA/before/h2_TPCSignal", "TPC Signal", TPCSignalHist); - histos.add("QA/before/h2_TOFSignal", "TOF Signal", TOFSignalHist); - - histos.addClone("QA/before/", "QA/after/"); - - histos.add("QA/Pion/h_Pt", "p_{T} (TPC & TPC+TOF)", kTH1D, {axisPt_qa}); - histos.add("QA/Pion/h_rap", "y (TPC & TPC+TOF)", kTH1D, {axisY}); - histos.add("QA/Pion/h2_Pt_rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt_qa}}); - histos.add("QA/Pion/h2_DcaZ", "DCA_{z}", kTH2D, {{axisPt_qa}, {axisDCAz}}); - histos.add("QA/Pion/h2_DcaXY", "DCA_{xy}", kTH2D, {{axisPt_qa}, {axisDCAxy}}); - - histos.add("QA/Pion/before/h2_TPCNsigma", "n #sigma_{TPC}", TPCnSigmaHist); - histos.add("QA/Pion/before/h2_TOFNsigma", "n #sigma_{TOF}", TOFnSigmaHist); - histos.add("QA/Pion/before/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", TPCTOFHist); - histos.add("QA/Pion/before/h2_TpcTofNsigma1", "n #sigma_{TPC+TOF}", TPCTOFnSigmaHist); - - histos.add("QA/Pion/h2_TPCNsigma", "n #sigma_{TPC}", TPCnSigmaHist); - histos.add("QA/Pion/h2_TOFNsigma", "n #sigma_{TOF}", TOFnSigmaHist); - histos.add("QA/Pion/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", TPCTOFHist); - histos.add("QA/Pion/h2_TpcTofNsigma1", "n #sigma_{TPC+TOF}", TPCTOFnSigmaHist); - - histos.add("QA/Pion/h2_TPCSignal", "TPC Signal vs pT", TPCSignalHist); - histos.add("QA/Pion/h2_TOFSignal", "TOF Signal vs pT", TOFSignalHist); - histos.add("QA/Pion/h2_ExpTPCSignal", "Expected TPC Signal vs pT", TPCSignalHist); - - histos.addClone("QA/Pion/", "QA/Kaon/"); - histos.addClone("QA/Pion/", "QA/Proton/"); - - // Define Subsamples - Subsample.resize(cfgNSubsample); - for (int i = 0; i < cfgNSubsample; i++) { - Subsample[i].resize(20); - } - for (int i = 0; i < cfgNSubsample; i++) { - Subsample[i][0] = std::get>(histos.add(Form("Subsample_%d/fA_hadron", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - Subsample[i][1] = std::get>(histos.add(Form("Subsample_%d/fA_pion", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - Subsample[i][2] = std::get>(histos.add(Form("Subsample_%d/fA_kaon", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - Subsample[i][3] = std::get>(histos.add(Form("Subsample_%d/fA_proton", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - - Subsample[i][4] = std::get>(histos.add(Form("Subsample_%d/fB1_hadron", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][5] = std::get>(histos.add(Form("Subsample_%d/fB1_pion", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][6] = std::get>(histos.add(Form("Subsample_%d/fB1_kaon", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][7] = std::get>(histos.add(Form("Subsample_%d/fB1_proton", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - - Subsample[i][8] = std::get>(histos.add(Form("Subsample_%d/fB2_hadron", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][9] = std::get>(histos.add(Form("Subsample_%d/fB2_pion", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][10] = std::get>(histos.add(Form("Subsample_%d/fB2_kaon", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][11] = std::get>(histos.add(Form("Subsample_%d/fB2_proton", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - - Subsample[i][12] = std::get>(histos.add(Form("Subsample_%d/fC_hadron", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - Subsample[i][13] = std::get>(histos.add(Form("Subsample_%d/fC_pion", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - Subsample[i][14] = std::get>(histos.add(Form("Subsample_%d/fC_kaon", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - Subsample[i][15] = std::get>(histos.add(Form("Subsample_%d/fC_proton", i), "", {HistType::kTProfile2D, {axisCent, axisPt}})); - - Subsample[i][16] = std::get>(histos.add(Form("Subsample_%d/fD_hadron", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][17] = std::get>(histos.add(Form("Subsample_%d/fD_pion", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][18] = std::get>(histos.add(Form("Subsample_%d/fD_kaon", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - Subsample[i][19] = std::get>(histos.add(Form("Subsample_%d/fD_proton", i), "", {HistType::kTProfile2D, {axisCent, axis1Bin}})); - } - } - - template - bool selRun2Col(T const& col) - { - if (std::abs(col.posZ()) > posZCut) - return false; - - if (!col.sel7()) - return false; - - if (!col.alias_bit(kINT7)) - return false; - - return true; - } - - template - bool selRun3Col(T const& col) - { - if (std::abs(col.posZ()) > posZCut) - return false; - - if (!col.sel8()) - return false; - - return true; - } - - template - bool selTrack(T const& track) - { - - // kinematic cuts - - if (track.pt() < ptMin) - return false; - - if (track.pt() > ptMax) - return false; - - if (std::abs(track.eta()) > etaCut) - return false; - - if (std::abs(track.dcaZ()) > dcaZCut) - return false; - - if (std::abs(track.dcaXY()) > dcaXYCut) - return false; - - if (track.tpcChi2NCl() > chi2TPCperClstrCut) - return false; - - if (track.itsChi2NCl() > chi2ITSperClstrCut) - return false; - - if (track.tpcNClsCrossedRows() > TPCNCrossedRowsCut) - return false; - - if (!track.isGlobalTrack()) - return false; - - return true; - } - - template - bool selPions(T const& track) - { - const float combNSigmaPi = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); - const float combNSigmaKa = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); - const float combNSigmaPr = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); - - if (track.pt() <= cfgCutPtUpperTPC) { - Int_t flag = 0; - if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_pi) - flag += 1; - if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_pi) - flag += 1; - if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_pi) - flag += 1; - if (flag > 1) - return false; - else if (flag == 1 && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_pi) - return true; - - } else if (track.pt() > cfgCutPtUpperTPC) { - Int_t flag = 0; - if (track.hasTOF() && track.hasTPC() && combNSigmaPi < cfgnSigmaCut_TOF_pi) - flag += 1; - if (track.hasTOF() && track.hasTPC() && combNSigmaKa < cfgnSigmaCut_TOF_pi) - flag += 1; - if (track.hasTOF() && track.hasTPC() && combNSigmaPr < cfgnSigmaCut_TOF_pi) - flag += 1; - if (flag > 1) - return false; - else if (flag == 1 && combNSigmaPi < cfgnSigmaCut_TOF_pi) - return true; - } - - return false; - } - - template - bool selKaons(T const& track) - { - const float combNSigmaPi = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); - const float combNSigmaKa = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); - const float combNSigmaPr = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); - - if (track.pt() <= cfgCutPtUpperTPC) { - Int_t flag = 0; - if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_ka) - flag += 1; - if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_ka) - flag += 1; - if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_ka) - flag += 1; - if (flag > 1) - return false; - else if (flag == 1 && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_ka) - return true; - - } else if (track.pt() > cfgCutPtUpperTPC) { - Int_t flag = 0; - if (track.hasTOF() && track.hasTPC() && combNSigmaPi < cfgnSigmaCut_TOF_ka) - flag += 1; - if (track.hasTOF() && track.hasTPC() && combNSigmaKa < cfgnSigmaCut_TOF_ka) - flag += 1; - if (track.hasTOF() && track.hasTPC() && combNSigmaPr < cfgnSigmaCut_TOF_ka) - flag += 1; - if (flag > 1) - return false; - else if (flag == 1 && combNSigmaKa < cfgnSigmaCut_TOF_ka) - return true; - } - - return false; - } - - template - bool selProtons(T const& track) - { - const float combNSigmaPi = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); - const float combNSigmaKa = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); - const float combNSigmaPr = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); - - // if (abs(track.rapidity(massPr)) < 0.5) - // return true; - if (track.pt() <= cfgCutPtUpperTPC && track.pt() > 0.4) { - Int_t flag = 0; - if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cfgnSigmaCut_TPC_pr) - flag += 1; - if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cfgnSigmaCut_TPC_pr) - flag += 1; - if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_pr) - flag += 1; - if (flag > 1) - return false; - else if (flag == 1 && std::abs(track.tpcNSigmaPr()) < cfgnSigmaCut_TPC_pr) - return true; - - } else if (track.pt() > cfgCutPtUpperTPC) { - Int_t flag = 0; - if (track.hasTOF() && track.hasTPC() && combNSigmaPi < cfgnSigmaCut_TOF_pr) - flag += 1; - if (track.hasTOF() && track.hasTPC() && combNSigmaKa < cfgnSigmaCut_TOF_pr) - flag += 1; - if (track.hasTOF() && track.hasTPC() && combNSigmaPr < cfgnSigmaCut_TOF_pr) - flag += 1; - if (flag > 1) - return false; - else if (flag == 1 && combNSigmaPr < cfgnSigmaCut_TOF_pr) - return true; - } - - return false; - } - - void process(MyRun3Collisions::iterator const& col, MyAllTracks const& tracks) - { - double Cent_FT0M = 0; - - if (selRun3Col(col)) { - - Cent_FT0M = col.centFT0M(); - - Double_t pT_bin[14] = {0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9}; - - Double_t N_Pi_eta_less_0 = 0; - Double_t N_Ka_eta_less_0 = 0; - Double_t N_Pr_eta_less_0 = 0; - Double_t Nch_eta_less_0 = 0; - - Double_t pT_sum_etaLess0 = 0; - Double_t pT_sum_etaGreaterEtamin = 0; - Double_t N_sum_etaGreaterEtamin = 0; - - Double_t pt_Ch = 0, pt_Pi = 0, pt_Ka = 0, pt_Pr = 0; - - Double_t fA_hadron[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - Double_t fA_pion[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - Double_t fA_kaon[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - Double_t fA_proton[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - Double_t fB1_hadron = 0; - Double_t fB1_pion = 0; - Double_t fB1_kaon = 0; - Double_t fB1_proton = 0; - - Double_t fB2_hadron = 0; - Double_t fB2_pion = 0; - Double_t fB2_kaon = 0; - Double_t fB2_proton = 0; - - Double_t fC_hadron[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - Double_t fC_pion[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - Double_t fC_kaon[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - Double_t fC_proton[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - Double_t fD_hadron = 0; - Double_t fD_pion = 0; - Double_t fD_kaon = 0; - Double_t fD_proton = 0; - - // normal creation of a histogram - TH1D* fPt_profile = new TH1D("fPt_profile", "fPt_profile", 14, 0.2, 3); - TH1D* fPt_profile_pion = new TH1D("fPt_profile_pion", "fPt_profile_pion", 14, 0.2, 3); - TH1D* fPt_profile_kaon = new TH1D("fPt_profile_kaon", "fPt_profile_kaon", 14, 0.2, 3); - TH1D* fPt_profile_proton = new TH1D("fPt_profile_proton", "fPt_profile_proton", 14, 0.2, 3); - - for (auto& track : tracks) { - - histos.fill(HIST("QA/before/h2_DcaXY"), track.dcaXY()); - histos.fill(HIST("QA/before/h2_DcaZ"), track.dcaZ()); - histos.fill(HIST("QA/before/h_VtxZ"), col.posZ()); - - histos.fill(HIST("QA/before/h_TPCChi2perCluster"), track.tpcChi2NCl()); - histos.fill(HIST("QA/before/h_ITSChi2perCluster"), track.itsChi2NCl()); - histos.fill(HIST("QA/before/h_crossedTPC"), track.tpcNClsCrossedRows()); - - if (selTrack(track)) - continue; - - histos.fill(HIST("QA/after/h2_DcaXY"), track.dcaXY()); - histos.fill(HIST("QA/after/h2_DcaZ"), track.dcaZ()); - - histos.fill(HIST("QA/after/h_TPCChi2perCluster"), track.tpcChi2NCl()); - histos.fill(HIST("QA/after/h_ITSChi2perCluster"), track.itsChi2NCl()); - histos.fill(HIST("QA/after/h_crossedTPC"), track.tpcNClsCrossedRows()); - - histos.fill(HIST("QA/before/h2_TOFSignal"), track.pt(), track.beta()); - histos.fill(HIST("QA/before/h2_TPCSignal"), track.pt(), track.tpcSignal()); - - histos.fill(HIST("QA/Pion/before/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("QA/Pion/before/h2_TOFNsigma"), track.pt(), track.tofNSigmaPi()); - histos.fill(HIST("QA/Pion/before/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - - histos.fill(HIST("QA/Proton/before/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("QA/Proton/before/h2_TOFNsigma"), track.pt(), track.tofNSigmaPr()); - histos.fill(HIST("QA/Proton/before/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - - histos.fill(HIST("QA/Kaon/before/h2_TPCNsigma"), track.pt(), track.tpcNSigmaKa()); - histos.fill(HIST("QA/Kaon/before/h2_TOFNsigma"), track.pt(), track.tofNSigmaKa()); - histos.fill(HIST("QA/Kaon/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); - - const float combNSigmaPi1 = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); - const float combNSigmaKa1 = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); - const float combNSigmaPr1 = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); - - histos.fill(HIST("QA/Pion/before/h2_TpcTofNsigma1"), track.pt(), combNSigmaPi1); - histos.fill(HIST("QA/Kaon/before/h2_TpcTofNsigma1"), track.pt(), combNSigmaKa1); - histos.fill(HIST("QA/Proton/before/h2_TpcTofNsigma1"), track.pt(), combNSigmaPr1); - - if (track.eta() < 0) { - Nch_eta_less_0++; - pt_Ch = track.pt(); - - pT_sum_etaLess0 += pt_Ch; - fPt_profile->Fill(pt_Ch); - - // For Pions: - if (selPions(track)) { - N_Pi_eta_less_0++; - pt_Pi = track.pt(); - - fPt_profile_pion->Fill(pt_Pi); - - // QA - histos.fill(HIST("QA/Pion/h_Pt"), track.pt()); - histos.fill(HIST("QA/Pion/h_rap"), track.rapidity(massPi)); - histos.fill(HIST("QA/Pion/h2_Pt_rap"), track.rapidity(massPi), track.pt()); - histos.fill(HIST("QA/Pion/h2_DcaXY"), track.pt(), track.dcaXY()); - histos.fill(HIST("QA/Pion/h2_DcaZ"), track.pt(), track.dcaZ()); - - histos.fill(HIST("QA/Pion/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST("QA/Pion/h2_TOFNsigma"), track.pt(), track.tofNSigmaPi()); - histos.fill(HIST("QA/Pion/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - histos.fill(HIST("QA/Pion/h2_TOFSignal"), track.pt(), track.beta()); - histos.fill(HIST("QA/Pion/h2_TPCSignal"), track.pt(), track.tpcSignal()); - histos.fill(HIST("QA/Pion/h2_ExpTPCSignal"), track.pt(), track.tpcExpSignalPi(track.tpcSignal())); - - histos.fill(HIST("QA/after/h2_TOFSignal"), track.pt(), track.beta()); - histos.fill(HIST("QA/after/h2_TPCSignal"), track.pt(), track.tpcSignal()); - - const float combNSigmaPi2 = std::sqrt(pow(track.tpcNSigmaPi(), 2.0) + pow(track.tofNSigmaPi(), 2.0)); - - histos.fill(HIST("QA/Pion/h2_TpcTofNsigma1"), track.pt(), combNSigmaPi2); - } - - // For Kaons: - if (selKaons(track)) { - N_Ka_eta_less_0++; - pt_Ka = track.pt(); - - fPt_profile_kaon->Fill(pt_Ka); - - // QA - - histos.fill(HIST("QA/Kaon/h_Pt"), track.pt()); - histos.fill(HIST("QA/Kaon/h_rap"), track.rapidity(massKa)); - histos.fill(HIST("QA/Kaon/h2_Pt_rap"), track.rapidity(massKa), track.pt()); - histos.fill(HIST("QA/Kaon/h2_DcaXY"), track.pt(), track.dcaXY()); - histos.fill(HIST("QA/Kaon/h2_DcaZ"), track.pt(), track.dcaZ()); - - histos.fill(HIST("QA/Kaon/h2_TPCNsigma"), track.pt(), track.tpcNSigmaKa()); - histos.fill(HIST("QA/Kaon/h2_TOFNsigma"), track.pt(), track.tofNSigmaKa()); - histos.fill(HIST("QA/Kaon/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); - histos.fill(HIST("QA/Kaon/h2_TOFSignal"), track.pt(), track.beta()); - histos.fill(HIST("QA/Kaon/h2_TPCSignal"), track.pt(), track.tpcSignal()); - histos.fill(HIST("QA/Kaon/h2_ExpTPCSignal"), track.pt(), track.tpcExpSignalKa(track.tpcSignal())); - histos.fill(HIST("QA/after/h2_TOFSignal"), track.pt(), track.beta()); - histos.fill(HIST("QA/after/h2_TPCSignal"), track.pt(), track.tpcSignal()); - - const float combNSigmaKa2 = std::sqrt(pow(track.tpcNSigmaKa(), 2.0) + pow(track.tofNSigmaKa(), 2.0)); - - histos.fill(HIST("QA/Kaon/h2_TpcTofNsigma1"), track.pt(), combNSigmaKa2); - } - - // For Protons: - if (selProtons(track)) { - N_Pr_eta_less_0++; - pt_Pr = track.pt(); - - fPt_profile_proton->Fill(pt_Pr); - - // QA - - histos.fill(HIST("QA/Proton/h_Pt"), track.pt()); - histos.fill(HIST("QA/Proton/h_rap"), track.rapidity(massPr)); - histos.fill(HIST("QA/Proton/h2_Pt_rap"), track.rapidity(massPr), track.pt()); - histos.fill(HIST("QA/Proton/h2_DcaZ"), track.pt(), track.dcaZ()); - histos.fill(HIST("QA/Proton/h2_DcaXY"), track.pt(), track.dcaXY()); - - histos.fill(HIST("QA/Proton/h2_TPCNsigma"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST("QA/Proton/h2_TOFNsigma"), track.pt(), track.tofNSigmaPr()); - histos.fill(HIST("QA/Proton/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - histos.fill(HIST("QA/Proton/h2_TPCSignal"), track.pt(), track.tpcSignal()); - histos.fill(HIST("QA/Proton/h2_TOFSignal"), track.pt(), track.beta()); - histos.fill(HIST("QA/Proton/h2_ExpTPCSignal"), track.pt(), track.tpcExpSignalPr(track.tpcSignal())); - histos.fill(HIST("QA/after/h2_TPCSignal"), track.pt(), track.tpcSignal()); - histos.fill(HIST("QA/after/h2_TOFSignal"), track.pt(), track.beta()); - - const float combNSigmaPr2 = std::sqrt(pow(track.tpcNSigmaPr(), 2.0) + pow(track.tofNSigmaPr(), 2.0)); - - histos.fill(HIST("QA/Proton/h2_TpcTofNsigma1"), track.pt(), combNSigmaPr2); - } - - } else if (track.eta() > etaMin) { - pT_sum_etaGreaterEtamin += pt_Ch; - N_sum_etaGreaterEtamin++; - } - } - - // selecting subsample and filling profiles - float l_Random = fRndm->Rndm(); - int SampleIndex = static_cast(cfgNSubsample * l_Random); - - // B1, B2, and D Calculation for hadrons - if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0) { - fB1_hadron = pT_sum_etaLess0 / Nch_eta_less_0; - histos.fill(HIST("fB1_hadron"), Cent_FT0M, 0.5, fB1_hadron); - Subsample[SampleIndex][4]->Fill(Cent_FT0M, 0.5, fB1_hadron); - - fB2_hadron = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; - histos.fill(HIST("fB2_hadron"), Cent_FT0M, 0.5, fB2_hadron); - Subsample[SampleIndex][8]->Fill(Cent_FT0M, 0.5, fB2_hadron); - - fD_hadron = fB1_hadron * fB2_hadron; - histos.fill(HIST("fD_hadron"), Cent_FT0M, 0.5, fD_hadron); - Subsample[SampleIndex][16]->Fill(Cent_FT0M, 0.5, fD_hadron); - } - - // B1, B2, and D Calculation for pions - if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0 && N_Pi_eta_less_0 != 0) { - fB1_pion = pT_sum_etaLess0 / Nch_eta_less_0; - histos.fill(HIST("fB1_pion"), Cent_FT0M, 0.5, fB1_pion); - Subsample[SampleIndex][5]->Fill(Cent_FT0M, 0.5, fB1_pion); - - fB2_pion = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; - histos.fill(HIST("fB2_pion"), Cent_FT0M, 0.5, fB2_pion); - Subsample[SampleIndex][9]->Fill(Cent_FT0M, 0.5, fB2_pion); - - fD_pion = fB1_pion * fB2_pion; - histos.fill(HIST("fD_pion"), Cent_FT0M, 0.5, fD_pion); - Subsample[SampleIndex][17]->Fill(Cent_FT0M, 0.5, fD_pion); - } - - // B1, B2, and D Calculation for kaons - if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0 && N_Ka_eta_less_0 != 0) { - fB1_kaon = pT_sum_etaLess0 / Nch_eta_less_0; - histos.fill(HIST("fB1_kaon"), Cent_FT0M, 0.5, fB1_kaon); - Subsample[SampleIndex][6]->Fill(Cent_FT0M, 0.5, fB1_kaon); - - fB2_kaon = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; - histos.fill(HIST("fB2_kaon"), Cent_FT0M, 0.5, fB2_kaon); - Subsample[SampleIndex][10]->Fill(Cent_FT0M, 0.5, fB2_kaon); - - fD_kaon = fB1_kaon * fB2_kaon; - histos.fill(HIST("fD_kaon"), Cent_FT0M, 0.5, fD_kaon); - Subsample[SampleIndex][18]->Fill(Cent_FT0M, 0.5, fD_kaon); - } - - // B1, B2, and D Calculation for protons - if (N_sum_etaGreaterEtamin != 0 && Nch_eta_less_0 != 0 && N_Pr_eta_less_0 != 0) { - fB1_proton = pT_sum_etaLess0 / Nch_eta_less_0; - histos.fill(HIST("fB1_proton"), Cent_FT0M, 0.5, fB1_proton); - Subsample[SampleIndex][7]->Fill(Cent_FT0M, 0.5, fB1_proton); - - fB2_proton = pT_sum_etaGreaterEtamin / N_sum_etaGreaterEtamin; - histos.fill(HIST("fB2_proton"), Cent_FT0M, 0.5, fB2_proton); - Subsample[SampleIndex][11]->Fill(Cent_FT0M, 0.5, fB2_proton); - - fD_proton = fB1_proton * fB2_proton; - histos.fill(HIST("fD_proton"), Cent_FT0M, 0.5, fD_proton); - Subsample[SampleIndex][19]->Fill(Cent_FT0M, 0.5, fD_proton); - } - - for (int i = 0; i < 14; i++) { - // A_hadrone Calculation - if (Nch_eta_less_0 != 0) { - fA_hadron[i] = fPt_profile->GetBinContent(i + 1) / Nch_eta_less_0; - histos.fill(HIST("fA_hadron"), Cent_FT0M, pT_bin[i], fA_hadron[i]); - Subsample[SampleIndex][0]->Fill(Cent_FT0M, pT_bin[i], fA_hadron[i]); - } - - // A_pion Calculation - if (N_Pi_eta_less_0 != 0) { - fA_pion[i] = fPt_profile_pion->GetBinContent(i + 1) / N_Pi_eta_less_0; - histos.fill(HIST("fA_pion"), Cent_FT0M, pT_bin[i], fA_pion[i]); - Subsample[SampleIndex][1]->Fill(Cent_FT0M, pT_bin[i], fA_pion[i]); - } - - // A_kaon Calculation - if (N_Ka_eta_less_0 != 0) { - fA_kaon[i] = fPt_profile_kaon->GetBinContent(i + 1) / N_Ka_eta_less_0; - histos.fill(HIST("fA_kaon"), Cent_FT0M, pT_bin[i], fA_kaon[i]); - Subsample[SampleIndex][2]->Fill(Cent_FT0M, pT_bin[i], fA_kaon[i]); - } - - // A_proton Calculation - if (N_Pr_eta_less_0 != 0) { - fA_proton[i] = fPt_profile_proton->GetBinContent(i + 1) / N_Pr_eta_less_0; - histos.fill(HIST("fA_proton"), Cent_FT0M, pT_bin[i], fA_proton[i]); - Subsample[SampleIndex][3]->Fill(Cent_FT0M, pT_bin[i], fA_proton[i]); - } - - // C_hadron Calculation - if (Nch_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { - fC_hadron[i] = fA_hadron[i] * fB2_hadron; - histos.fill(HIST("fC_hadron"), Cent_FT0M, pT_bin[i], fC_hadron[i]); - Subsample[SampleIndex][12]->Fill(Cent_FT0M, pT_bin[i], fC_hadron[i]); - } - - // C_pion Calculation - if (N_Pi_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { - fC_pion[i] = fA_pion[i] * fB2_pion; - histos.fill(HIST("fC_pion"), Cent_FT0M, pT_bin[i], fC_pion[i]); - Subsample[SampleIndex][13]->Fill(Cent_FT0M, pT_bin[i], fC_pion[i]); - } - - // A_kaon Calculation - if (N_Ka_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { - fC_kaon[i] = fA_kaon[i] * fB2_kaon; - histos.fill(HIST("fC_kaon"), Cent_FT0M, pT_bin[i], fC_kaon[i]); - Subsample[SampleIndex][14]->Fill(Cent_FT0M, pT_bin[i], fC_kaon[i]); - } - - // A_proton Calculation - if (N_Pr_eta_less_0 != 0 && N_sum_etaGreaterEtamin != 0) { - fC_proton[i] = fA_proton[i] * fB2_proton; - histos.fill(HIST("fC_proton"), Cent_FT0M, pT_bin[i], fC_proton[i]); - Subsample[SampleIndex][15]->Fill(Cent_FT0M, pT_bin[i], fC_proton[i]); - } - } - - fPt_profile->Delete(); - fPt_profile_pion->Delete(); - fPt_profile_kaon->Delete(); - fPt_profile_proton->Delete(); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; -} diff --git a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx index b544208e91e..9ca0bbb7e3f 100644 --- a/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/FactorialMomentsTask.cxx @@ -12,6 +12,7 @@ /// \brief This task is for Normalized Factorial Moments Analysis: PRC 85, 044914 (2012), nucl-ex:1411.6083 /// \author Salman Malik /// \author Balwan Singh + #include "TRandom.h" #include @@ -40,17 +41,20 @@ using namespace o2::framework::expressions; TH1D* tmpFqErr[6][5][52]; struct FactorialMomentsTask { + Configurable useITS{"useITS", false, "Select tracks with ITS"}; + Configurable useTPC{"useTPC", false, "Select tracks with TPC"}; + Configurable useGlobal{"useGlobal", true, "Select global tracks"}; Configurable applyCheckPtForRec{"applyCheckPtForRec", false, "Apply checkpT for reconstructed tracks"}; Configurable applyCheckPtForMC{"applyCheckPtForMC", true, "Apply checkpT for MC-generated tracks"}; - Configurable centralEta{"centralEta", 0.9, "eta limit for tracks"}; - Configurable numPt{"numPt", 5, "number of pT bins"}; - Configurable ptMin{"ptMin", 0.2f, "lower pT cut"}; - Configurable dcaXY{"dcaXY", 2.4f, "DCA xy cut"}; - Configurable dcaZ{"dcaZ", 2.0f, "DCA z cut"}; - Configurable minTPCCls{"minTPCCls", 70.0f, "minimum number of TPC clusters"}; - Configurable> centLimits{"centLimits", {0, 5}, "centrality min and max"}; - Configurable> vertexXYZ{"vertexXYZ", {0.3f, 0.4f, 10.0f}, "vertex cuts"}; - Configurable> ptCuts{"ptCuts", {0.2f, 2.0f}, "pT cuts"}; + Configurable centralEta{"centralEta", 0.9, "eta limit for tracks"}; + Configurable numPt{"numPt", 5, "number of pT bins"}; + Configurable ptMin{"ptMin", 0.2f, "lower pT cut"}; + Configurable dcaXY{"dcaXY", 2.4f, "DCA xy cut"}; + Configurable dcaZ{"dcaZ", 2.0f, "DCA z cut"}; + Configurable mintPCCls{"mintPCCls", 70.0f, "minimum number of TPC clusters"}; + Configurable> centLimits{"centLimits", {0, 5}, "centrality min and max"}; + Configurable> vertexXYZ{"vertexXYZ", {0.3f, 0.4f, 10.0f}, "vertex cuts"}; + Configurable> ptCuts{"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"}; @@ -112,7 +116,7 @@ struct FactorialMomentsTask { {"mVertexZ", "vertexZ", {HistType::kTH1F, {{100, -20, 20}}}}, {"mEta", "#eta", {HistType::kTH1F, {{1000, -2, 2}}}}, {"mPt", "#pt", {HistType::kTH1F, {{1000, -0.01, 50}}}}, - {"mPhi", "#phi", {HistType::kTH1F, {{100, 0, TMath::TwoPi()}}}}, + {"mPhi", "#phi", {HistType::kTH1F, {{100, 0, o2::constants::math::TwoPI}}}}, {"mEvents", "events", {HistType::kTH1D, {{5, -0.5, 4.5}}}}, {"mNFindableClsTPC", "findable TPC clusters;findable clusters", {HistType::kTH1F, {{100, 0, 200}}}}, {"mNClsTPC", "number of clusters TPC; nClusters TPC", {HistType::kTH1F, {{100, 0, 200}}}}, @@ -135,18 +139,18 @@ struct FactorialMomentsTask { }, OutputObjHandlingPolicy::AnalysisObject, true}; - static const Int_t nBins = 52; + static const int nBins = 52; double kMinCharge = 1e-6; - static const Int_t nfqOrder = 6; - Int_t countSamples = 0; - Int_t testc1 = 0, testc2 = 0, testc3 = 0; - std::array binningM; - std::array countTracks{0, 0, 0, 0, 0}; - std::array, 5>, 6> fqEvent; - std::array, 5>, 6> fqEventSampled; - std::array, 5> binConEvent; - std::array, 5>, 6> binConEventSampled; - std::array, 5>, 6> errorFq = {{{{{0, 0, 0, 0, 0}}}}}; + static const int nfqOrder = 6; + int countSamples = 0; + int testc1 = 0, testc2 = 0, testc3 = 0; + std::array binningM; + std::array countTracks{0, 0, 0, 0, 0}; + std::array, 5>, 6> fqEvent; + std::array, 5>, 6> fqEventSampled; + std::array, 5> binConEvent; + std::array, 5>, 6> binConEventSampled; + std::array, 5>, 6> errorFq = {{{{{0, 0, 0, 0, 0}}}}}; std::vector> mHistArrReset; std::vector> mHistArrQA; std::vector> mFqBinFinal; @@ -185,22 +189,22 @@ struct FactorialMomentsTask { if (useMC) { auto mMcTrackSelected = std::get>(histos.add("mMcTrackSelected", "mcTrackSelection", HistType::kTH1D, {{5, 0.5, 5.5}})); } - for (Int_t iM = 0; iM < nBins; ++iM) { + for (int iM = 0; iM < nBins; ++iM) { binningM[iM] = 2 * (iM + 2); } - for (Int_t iPt = 0; iPt < numPt; ++iPt) { + for (int iPt = 0; iPt < numPt; ++iPt) { mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mEta", iPt + 1), Form("#eta for bin %.2f-%.2f;#eta", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{1000, -2, 2}}))); mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mPt", iPt + 1), Form("pT for bin %.2f-%.2f;pT", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {axisPt[iPt]}))); - mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mPhi", iPt + 1), Form("#phi for bin %.2f-%.2f;#phi", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{1000, 0, 2 * TMath::Pi()}}))); + mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mPhi", iPt + 1), Form("#phi for bin %.2f-%.2f;#phi", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{1000, 0, o2::constants::math::TwoPI}}))); mHistArrQA.push_back(std::get>(histos.add(Form("bin%i/mMultiplicity", iPt + 1), Form("Multiplicity for bin %.2f-%.2f;Multiplicity", ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{1000, 0, 15000}}))); - for (Int_t iM = 0; iM < nBins; ++iM) { - auto mHistsR = std::get>(histos.add(Form("bin%i/Reset/mEtaPhi%i", iPt + 1, iM), Form("#eta#phi_%i for bin %.2f-%.2f;#eta;#phi", iM, ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH2F, {{binningM[iM], -0.8, 0.8}, {binningM[iM], 0, 2 * TMath::Pi()}})); + for (int iM = 0; iM < nBins; ++iM) { + auto mHistsR = std::get>(histos.add(Form("bin%i/Reset/mEtaPhi%i", iPt + 1, iM), Form("#eta#phi_%i for bin %.2f-%.2f;#eta;#phi", iM, ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH2F, {{binningM[iM], -0.8, 0.8}, {binningM[iM], 0, o2::constants::math::TwoPI}})); mHistArrReset.push_back(mHistsR); - for (Int_t iq = 0; iq < nfqOrder; ++iq) { + for (int iq = 0; iq < nfqOrder; ++iq) { tmpFqErr[iq][iPt][iM] = new TH1D(Form("tmpFqErr%i%i%i", iq, iPt, iM), Form("tmpFqErr%i%i%i", iq, iPt, iM), 100, 0, 10); } } - for (Int_t i = 0; i < nfqOrder; ++i) { + for (int i = 0; i < nfqOrder; ++i) { auto mHistFq = std::get>(histos.add(Form("mFinalFq%i_bin%i", i + 2, iPt + 1), Form("Final F_%i for bin %.2f-%.2f;M", i + 2, ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{nBins, -0.5, nBins - 0.5}})); mFqBinFinal.push_back(mHistFq); auto mHistAv = std::get>(histos.add(Form("mFinalAvBin%i_bin%i", i + 2, iPt + 1), Form("Final AvBin_%i for bin %.2f-%.2f;M", i + 2, ptCuts.value[2 * iPt], ptCuts.value[2 * iPt + 1]), HistType::kTH1F, {{nBins, -0.5, nBins - 0.5}})); @@ -218,10 +222,10 @@ struct FactorialMomentsTask { template void checkpT(const T& track) { - for (Int_t iPt = 0; iPt < numPt; ++iPt) { + for (int iPt = 0; iPt < numPt; ++iPt) { if (track.pt() > ptCuts.value[2 * iPt] && track.pt() < ptCuts.value[2 * iPt + 1]) { float iphi = track.phi(); - iphi = gRandom->Gaus(iphi, TMath::TwoPi()); + iphi = gRandom->Gaus(iphi, o2::constants::math::TwoPI); iphi = RecoDecay::constrainAngle(iphi); mHistArrQA[iPt * 4]->Fill(track.eta()); @@ -229,7 +233,7 @@ struct FactorialMomentsTask { mHistArrQA[iPt * 4 + 2]->Fill(track.phi()); countTracks[iPt]++; - for (Int_t iM = 0; iM < nBins; ++iM) { + for (int iM = 0; iM < nBins; ++iM) { mHistArrReset[iPt * nBins + iM]->Fill(track.eta(), track.phi()); } } @@ -238,26 +242,26 @@ struct FactorialMomentsTask { void calculateMoments(std::vector> hist) { - Double_t binContent = 0; + double binContent = 0; countSamples++; - Bool_t compSample = kFALSE; + bool compSample = kFALSE; if (countSamples == samplesize) { compSample = kTRUE; countSamples = 0; } // Calculate the normalized factorial moments - for (Int_t iPt = 0; iPt < numPt; ++iPt) { - for (Int_t iM = 0; iM < nBins; ++iM) { + for (int iPt = 0; iPt < numPt; ++iPt) { + for (int iM = 0; iM < nBins; ++iM) { binContent = 0; - Double_t sumfqBin[6] = {0}; + double sumfqBin[6] = {0}; - for (Int_t iEta = 1; iEta <= hist[iPt * nBins + iM]->GetNbinsX(); ++iEta) { - for (Int_t iPhi = 1; iPhi <= hist[iPt * nBins + iM]->GetNbinsY(); ++iPhi) { + for (int iEta = 1; iEta <= hist[iPt * nBins + iM]->GetNbinsX(); ++iEta) { + for (int iPhi = 1; iPhi <= hist[iPt * nBins + iM]->GetNbinsY(); ++iPhi) { double binconVal = 0; binconVal = hist[iPt * nBins + iM]->GetBinContent(iEta, iPhi); binContent += binconVal; - for (Int_t iq = 0; iq < nfqOrder; ++iq) { - Double_t fqBin = 0; + for (int iq = 0; iq < nfqOrder; ++iq) { + double fqBin = 0; if (binconVal >= iq + 2) { fqBin = TMath::Factorial(binconVal) / (TMath::Factorial(binconVal - (iq + 2))); } @@ -268,10 +272,10 @@ struct FactorialMomentsTask { } } } - binConEvent[iPt][iM] = binContent / (TMath::Power(binningM[iM], 2)); - for (Int_t iq = 0; iq < nfqOrder; ++iq) { + binConEvent[iPt][iM] = binContent / (std::pow(binningM[iM], 2)); + for (int iq = 0; iq < nfqOrder; ++iq) { if (sumfqBin[iq] > 0) { - fqEvent[iq][iPt][iM] = sumfqBin[iq] / (TMath::Power(binningM[iM], 2)); + fqEvent[iq][iPt][iM] = sumfqBin[iq] / (std::pow(binningM[iM], 2)); fqEventSampled[iq][iPt][iM] += fqEvent[iq][iPt][iM]; } binConEventSampled[iq][iPt][iM] += binConEvent[iPt][iM]; @@ -280,10 +284,10 @@ struct FactorialMomentsTask { if (compSample) { mBinConFinalSampled[iPt * 6 + iq]->Fill(iM, binConEventSampled[iq][iPt][iM] / samplesize); - double tmp = (fqEventSampled[iq][iPt][iM] / (samplesize)) / (TMath::Power(binConEventSampled[iq][iPt][iM] / (samplesize), (iq + 2))); + double tmp = (fqEventSampled[iq][iPt][iM] / (samplesize)) / (std::pow(binConEventSampled[iq][iPt][iM] / (samplesize), (iq + 2))); mFqBinFinalSampled[iPt * 6 + iq]->Fill(iM, tmp); tmpFqErr[iq][iPt][iM]->Fill(tmp); - errorFq[iq][iPt][iM] += TMath::Power(fqEventSampled[iq][iPt][iM] / (samplesize), 2); + errorFq[iq][iPt][iM] += std::pow(fqEventSampled[iq][iPt][iM] / (samplesize), 2); mFqError[iPt * 6 + iq]->SetBinContent(iM + 1, 0); mFqError[iPt * 6 + iq]->Fill(iM, tmpFqErr[iq][iPt][iM]->GetStdDev()); @@ -297,6 +301,7 @@ struct FactorialMomentsTask { // write a template that takes coll and tracks from processRun3 and processMCRec using TracksFMs = soa::Filtered>; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; void processRun3(soa::Filtered>::iterator const& coll, TracksFMs const& tracks) { // selection of events @@ -353,7 +358,7 @@ struct FactorialMomentsTask { checkpT(track); } } - for (Int_t iPt = 0; iPt < numPt; ++iPt) { + for (int iPt = 0; iPt < numPt; ++iPt) { if (countTracks[iPt] > 0) { mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); } @@ -361,14 +366,116 @@ struct FactorialMomentsTask { calculateMoments(mHistArrReset); } PROCESS_SWITCH(FactorialMomentsTask, processRun3, "main process function", false); - using EventSelection_Run2 = soa::Join; + using CollisionCandidateMCRec = soa::Join; + using TracksMc = soa::Filtered>; + void processMCRec(soa::Filtered::iterator const& coll, TracksMc const& colltracks, aod::McParticles const& mcParticles, aod::McCollisions const&) + { + if (!coll.has_mcCollision()) { + return; + } + histos.fill(HIST("mEventSelected"), 0); + if (!coll.sel8()) { + return; + } + histos.fill(HIST("mEventSelected"), 1); + if (isApplySameBunchPileup && !coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return; + } + histos.fill(HIST("mEventSelected"), 2); + if (isApplyGoodZvtxFT0vsPV && !coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + histos.fill(HIST("mEventSelected"), 3); + if (isApplyVertexITSTPC && !coll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return; + } + histos.fill(HIST("mEventSelected"), 4); + if (coll.centFT0C() < centLimits.value[0] || coll.centFT0C() > centLimits.value[1]) { + return; + } + histos.fill(HIST("mEventSelected"), 5); + histos.fill(HIST("mVertexX"), coll.posX()); + histos.fill(HIST("mVertexY"), coll.posY()); + histos.fill(HIST("mVertexZ"), coll.posZ()); + 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}}}; + for (auto const& track : colltracks) { + if (useITS && !track.hasITS()) + continue; + if (useTPC && !track.hasTPC()) + continue; + if (useGlobal && !track.isGlobalTrack()) + continue; + histos.fill(HIST("mCollID"), track.collisionId()); + histos.fill(HIST("mEta"), track.eta()); + histos.fill(HIST("mPt"), track.pt()); + histos.fill(HIST("mPhi"), track.phi()); + histos.fill(HIST("mNFindableClsTPC"), track.tpcNClsFindable()); + histos.fill(HIST("mNClsTPC"), track.tpcNClsFound()); + histos.fill(HIST("mNClsITS"), track.itsNCls()); + histos.fill(HIST("mChi2TPC"), track.tpcChi2NCl()); + histos.fill(HIST("mChi2ITS"), track.itsChi2NCl()); + histos.fill(HIST("mChi2TRD"), track.trdChi2()); + histos.fill(HIST("mDCAxy"), track.dcaXY()); + histos.fill(HIST("mDCAx"), track.dcaZ()); + histos.fill(HIST("mDCAxyPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("mDCAzPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("mNSharedClsTPC"), track.tpcNClsShared()); + histos.fill(HIST("mCrossedRowsTPC"), track.tpcNClsCrossedRows()); + histos.fill(HIST("mNFinClsminusCRows"), track.tpcNClsFindableMinusCrossedRows()); + histos.fill(HIST("mNFractionShClsTPC"), track.tpcFractionSharedCls()); + histos.fill(HIST("mSharedClsvsPt"), track.pt(), track.tpcNClsShared()); + histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); + if (applyCheckPtForRec && !applyCheckPtForMC) { + checkpT(track); + } + } + auto mcParts = mcParticles.sliceBy(perMcCollision, coll.mcCollision().globalIndex()); + for (auto const& mc : mcParts) { + int pdgCode = mc.pdgCode(); + auto pdgInfo = pdg->GetParticle(pdgCode); + if (!pdgInfo) { + continue; + } + double charge = pdgInfo->Charge(); + double physCharge = charge / 3.0; + histos.fill(HIST("mChargeBefore"), physCharge); + if (mc.isPhysicalPrimary() && std::abs(mc.eta()) < centralEta && std::abs(physCharge) >= kMinCharge) { + histos.fill(HIST("mChargeAfter"), physCharge); + histos.fill(HIST("mEta"), mc.eta()); + histos.fill(HIST("mPt"), mc.pt()); + histos.fill(HIST("mPhi"), mc.phi()); + if (applyCheckPtForMC && !applyCheckPtForRec) { + checkpT(mc); + } + } + } + for (auto iPt = 0; iPt < numPt; ++iPt) { + // if (countTracks[iPt] > 0)countTracks = {0, 0, 0, 0, 0}; + if (countTracks[iPt] > 0) { + mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); + } + } + histos.fill(HIST("mEventSelected"), 6); + // Calculate the normalized factorial moments + calculateMoments(mHistArrReset); + } + PROCESS_SWITCH(FactorialMomentsTask, processMCRec, "main process function", false); + using EventSelectionrun2 = soa::Join; using TracksRecSim = soa::Join; - using CollisionRecSim_Run2 = soa::Filtered>::iterator; + using CollisionRecSimRun2 = soa::Filtered>::iterator; using BCsWithRun2Info = soa::Join; - Preslice perMcCollision = aod::mcparticle::mcCollisionId; - void processMcRun2(CollisionRecSim_Run2 const& coll, + void processMcRun2(CollisionRecSimRun2 const& coll, + aod::BCs const&, TracksRecSim const& tracks, - aod::McParticles const& mcParticles) + aod::McParticles const& mcParticles, + aod::McCollisions const&, + BCsWithRun2Info const&) { auto bc = coll.bc_as(); if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) { @@ -429,11 +536,9 @@ struct FactorialMomentsTask { } } - for (Int_t iPt = 0; iPt < numPt; ++iPt) { + for (int iPt = 0; iPt < numPt; ++iPt) { if (countTracks[iPt] > 0) { mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); - } else { - return; } } @@ -461,7 +566,7 @@ struct FactorialMomentsTask { fqEvent = {{{{{0, 0, 0, 0, 0, 0}}}}}; binConEvent = {{{0, 0, 0, 0, 0}}}; for (auto const& track : tracks) { - if ((track.pt() < ptMin) || (!track.isGlobalTrack()) || (track.tpcNClsFindable() < minTPCCls)) { + if ((track.pt() < ptMin) || (!track.isGlobalTrack()) || (track.tpcNClsFindable() < mintPCCls)) { continue; } histos.fill(HIST("mCollID"), track.collisionId()); @@ -486,11 +591,9 @@ struct FactorialMomentsTask { histos.fill(HIST("mSharedClsProbvsPt"), track.pt(), track.tpcFractionSharedCls() / track.tpcNClsCrossedRows()); checkpT(track); } - for (Int_t iPt = 0; iPt < numPt; ++iPt) { + for (int iPt = 0; iPt < numPt; ++iPt) { if (countTracks[iPt] > 0) { mHistArrQA[iPt * 4 + 3]->Fill(countTracks[iPt]); - } else { - return; } } // Calculate the normalized factorial moments diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx index 77706f1bfd6..c67c9f767f8 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx @@ -27,14 +27,20 @@ #include "Framework/runDataProcessing.h" #include -#include "TF1.h" -#include "TH1D.h" -#include "TH2D.h" -#include "TList.h" -#include "TMath.h" -#include "TProfile.h" -#include "TProfile2D.h" -#include "TRandom3.h" +#include "TDatabasePDG.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -44,27 +50,16 @@ #include #include -namespace o2::aod -{ -namespace pt_qn -{ -DECLARE_SOA_COLUMN(Q1, q1, float); //! sum of pT of tracks in an event -DECLARE_SOA_COLUMN(Q2, q2, float); //! sum of (pT)^2 of tracks in an event -DECLARE_SOA_COLUMN(Q3, q3, float); //! sum of (pT)^3 of tracks in an event -DECLARE_SOA_COLUMN(Q4, q4, float); //! sum of (pT)^4 of tracks in an event -DECLARE_SOA_COLUMN(Nch, nch, float); //! no of charged particles/multiplicity in an event -DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Centrality of event -} // namespace pt_qn -DECLARE_SOA_TABLE(MultPtQn, "AOD", "PTQN", pt_qn::Q1, pt_qn::Q2, pt_qn::Q3, pt_qn::Q4, pt_qn::Nch, pt_qn::Centrality); //! table to store e-by-e sum of pT, (pT)^2, (pT)^3, (pT)^4 of tracks, multiplicity and centrality -} // namespace o2::aod - 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 MeanptFluctuationsQAQnTable { +struct MeanptFluctuationsAnalysis { + + // MC + Configurable cfgIsMC{"cfgIsMC", true, "Run MC"}; Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgCutPreSelEta{"cfgCutPreSelEta", 0.8f, "|eta| cfgITScluster{"cfgITScluster", 1, "Minimum Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 80, "Minimum Number of TPC cluster"}; Configurable cfgTPCnCrossedRows{"cfgTPCnCrossedRows", 70, "Minimum Number of TPC crossed-rows"}; + Configurable cfgTPCnCrossedRowsOverFindableCls{"cfgTPCnCrossedRowsOverFindableCls", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; ConfigurableAxis nchAxis{"nchAxis", {500, 0.5, 500.5}, "Axis for multiplicity of GlobalTracks/PVTracks"}; ConfigurableAxis nchAxis2{"nchAxis2", {1000, 0.5, 30000.5}, "Axis for multiplicity of FT0A/FT0C/FV0A"}; ConfigurableAxis nchAxis3{"nchAxis3", {1000, 0.5, 100000.5}, "Axis for multiplicity of FT0A/FT0C/FV0A"}; ConfigurableAxis centAxis{"centAxis", {90, 0., 90.0}, ""}; + Configurable cfgMinNch{"cfgMinNch", 3.0f, "Min. no of Nch in each event for correlators"}; + Configurable cfgNsubSample{"cfgNsubSample", 10, "Number of subsamples"}; + ConfigurableAxis multAxis{"multAxis", {5000, 0.5, 5000.5}, ""}; + ConfigurableAxis meanpTAxis{"meanpTAxis", {500, 0, 5.0}, ""}; Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; Configurable cfgEvSelkNoITSROFrameBorder{"cfgEvSelkNoITSROFrameBorder", true, "ITSROFrame border event selection cut"}; @@ -88,6 +88,14 @@ struct MeanptFluctuationsQAQnTable { Configurable cfgEvSelUseGoodZvtxFT0vsPV{"cfgEvSelUseGoodZvtxFT0vsPV", true, "GoodZvertex and FT0 vs PV cut"}; Configurable cfgCentralityEstimator{"cfgCentralityEstimator", 1, "Centrlaity estimatore choice: 1-->FT0C, 2-->FT0A; 3-->FT0M, 4-->FV0A"}; + // pT dep DCAxy and DCAz cuts + Configurable cfgUsePtDepDCAxy{"cfgUsePtDepDCAxy", true, "Use pt-dependent DCAxy cut"}; + Configurable cfgUsePtDepDCAz{"cfgUsePtDepDCAz", true, "Use pt-dependent DCAz cut"}; + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAz cut"); + TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAz = nullptr; + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") struct : ConfigurableGroup { @@ -127,6 +135,7 @@ struct MeanptFluctuationsQAQnTable { O2_DEFINE_CONFIGURABLE(cfgUse22sEventCut, bool, true, "Use 22s event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgUseSmallIonAdditionalEventCut, bool, true, "Use additional event cut on mult correlations for small ions") + O2_DEFINE_CONFIGURABLE(cfgUseSmallIonAdditionalEventCutInMC, bool, false, "Use additional event cut on mult correlations for small ions while using MC generated") // Filter command*********** Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -137,13 +146,26 @@ struct MeanptFluctuationsQAQnTable { 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 ccdburl{"ccdburl", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + // Define Output HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::vector>> subSampleMcGen; + std::vector>> subSample; + std::vector>> subSampleMcGenV2; + std::vector>> subSampleV2; + TRandom3* fRndm = new TRandom3(0); // filtering collisions and tracks*********** using AodCollisions = soa::Filtered>; - // using aodCollisions = soa::Filtered>; using AodTracks = soa::Filtered>; + // filtering collisions and tracks for MC rec data*********** + using MyMCRecCollisions = soa::Filtered>; + using MyMCTracks = soa::Filtered>; + using EventCandidatesMC = soa::Join; + + Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + // Event selection cuts - Alex TF1* fMultPVCutLow = nullptr; TF1* fMultPVCutHigh = nullptr; @@ -162,6 +184,7 @@ struct MeanptFluctuationsQAQnTable { AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; // Add histograms to histogram manager (as in the output object of in AliPhysics) + histos.add("hEventStatData", "Data Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); histos.add("hZvtx_after_sel", ";Z (cm)", kTH1F, {vtxZAxis}); histos.add("hP", ";#it{p} (GeV/#it{c})", kTH1F, {{35, 0.2, 4.}}); histos.add("hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); @@ -170,6 +193,10 @@ struct MeanptFluctuationsQAQnTable { histos.add("hCentrality", ";centrality (%)", kTH1F, {{90, 0, 90}}); histos.add("hDcaXY", ";#it{dca}_{XY}", kTH1F, {{1000, -5, 5}}); histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -5, 5}}); + histos.add("his2DdcaXYvsPt", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaZvsPt", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaXYvsPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); + histos.add("his2DdcaZvsPtBeforePtDepSel", "", {HistType::kTH2D, {ptAxis, {1000, -1, 1}}}); histos.add("hMeanPt", "", kTProfile, {centAxis}); histos.add("Hist2D_globalTracks_PVTracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histos.add("Hist2D_cent_nch", "", {HistType::kTH2D, {nchAxis, centAxis}}); @@ -190,6 +217,85 @@ struct MeanptFluctuationsQAQnTable { histos.add("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis3}}); } + // Analysis Profiles for central val (reconstructed data) + histos.add("AnalysisProfiles/Prof_mean_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("AnalysisProfiles/Prof_var_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("AnalysisProfiles/Prof_skew_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("AnalysisProfiles/Prof_kurt_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("AnalysisProfiles/Hist2D_Nch_centrality", "", {HistType::kTH2D, {centAxis, multAxis}}); + histos.add("AnalysisProfiles/Hist2D_meanpt_centrality", "", {HistType::kTH2D, {centAxis, meanpTAxis}}); + + // Analysis Profiles for error (reconstructed data) + subSample.resize(cfgNsubSample); + for (int i = 0; i < cfgNsubSample; i++) { + subSample[i].resize(4); + } + for (int i = 0; i < cfgNsubSample; i++) { + subSample[i][0] = std::get>(histos.add(Form("AnalysisProfiles/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + subSample[i][1] = std::get>(histos.add(Form("AnalysisProfiles/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + subSample[i][2] = std::get>(histos.add(Form("AnalysisProfiles/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + subSample[i][3] = std::get>(histos.add(Form("AnalysisProfiles/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + } + + if (cfgIsMC) { + // MC event counts + histos.add("MCGenerated/hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); + histos.add("MCGenerated/hCentgen", "MCGen Multiplicity percentile from FT0M (%)", kTH1F, {{100, 0.0, 100.0}}); + // tracks Gen level histograms + histos.add("MCGenerated/hP", ";#it{p} (GeV/#it{c})", kTH1F, {{35, 0.2, 4.}}); + histos.add("MCGenerated/hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("MCGenerated/hPhi", ";#phi", kTH1F, {{100, 0., o2::constants::math::TwoPI}}); + histos.add("MCGenerated/hEta", ";#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("MCGenerated/hMeanPt", "", kTH2F, {centAxis, meanpTAxis}); + histos.add("MCGenerated/hPtParticleVsTrack", "", kTH2F, {ptAxis, ptAxis}); + histos.add("MCGenerated/hEtaParticleVsTrack", "", kTH2F, {{100, -2.01, 2.01}, {100, -2.01, 2.01}}); + histos.add("MCGenerated/hPhiParticleVsTrack", "", kTH2F, {{100, 0., o2::constants::math::TwoPI}, {100, 0., o2::constants::math::TwoPI}}); + histos.add("MCGenerated/hNgenVsNrec", "Gen multiplicity vs. Rec multiplicity in MC", kTH2F, {multAxis, multAxis}); + + // Analysis Profiles for central val + histos.add("MCGenerated/AnalysisProfiles/Prof_mean_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("MCGenerated/AnalysisProfiles/Prof_var_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("MCGenerated/AnalysisProfiles/Prof_skew_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("MCGenerated/AnalysisProfiles/Prof_kurt_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); + histos.add("MCGenerated/AnalysisProfiles/Hist2D_Nch_centrality", "", {HistType::kTH2D, {centAxis, multAxis}}); + histos.add("MCGenerated/AnalysisProfiles/Hist2D_meanpt_centrality", "", {HistType::kTH2D, {centAxis, meanpTAxis}}); + + histos.add("MCGenerated/AnalysisProfilesV2/Prof_mean_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_var_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_skew_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("MCGenerated/AnalysisProfilesV2/Prof_kurt_t1", "", {HistType::kTProfile, {multAxis}}); + histos.add("AnalysisProfilesV2/Prof_mean_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + histos.add("AnalysisProfilesV2/Prof_var_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + histos.add("AnalysisProfilesV2/Prof_skew_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + histos.add("AnalysisProfilesV2/Prof_kurt_t1", "", {HistType::kTProfile2D, {multAxis, multAxis}}); + + // Analysis Profiles for error + subSampleMcGen.resize(cfgNsubSample); + subSampleMcGenV2.resize(cfgNsubSample); + subSampleV2.resize(cfgNsubSample); + for (int i = 0; i < cfgNsubSample; i++) { + subSampleMcGen[i].resize(4); + subSampleMcGenV2[i].resize(4); + subSampleV2[i].resize(4); + } + for (int i = 0; i < cfgNsubSample; i++) { + subSampleMcGen[i][0] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + subSampleMcGen[i][1] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + subSampleMcGen[i][2] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + subSampleMcGen[i][3] = std::get>(histos.add(Form("MCGenerated/AnalysisProfiles/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); + + subSampleMcGenV2[i][0] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile, {multAxis}})); + subSampleMcGenV2[i][1] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile, {multAxis}})); + subSampleMcGenV2[i][2] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile, {multAxis}})); + subSampleMcGenV2[i][3] = std::get>(histos.add(Form("MCGenerated/AnalysisProfilesV2/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile, {multAxis}})); + + subSampleV2[i][0] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + subSampleV2[i][1] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + subSampleV2[i][2] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + subSampleV2[i][3] = std::get>(histos.add(Form("AnalysisProfilesV2/subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile2D, {multAxis, multAxis}})); + } + } + // Event selection - Alex if (cfgUse22sEventCut) { 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); @@ -232,6 +338,13 @@ struct MeanptFluctuationsQAQnTable { cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } + if (cfgUsePtDepDCAxy) { + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("%s", cfgDCAxyFunc->c_str()), 0.001, 1000); + } + if (cfgUsePtDepDCAz) { + fPtDepDCAz = new TF1("ptDepDCAz", Form("%s", cfgDCAzFunc->c_str()), 0.001, 1000); + } + } //! end init function template @@ -310,36 +423,406 @@ struct MeanptFluctuationsQAQnTable { return 1; } - Produces multPtQn; - - // void process(aod::Collision const& coll, aod::Tracks const& inputTracks) - void process(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + template + bool eventSelectionDefaultCuts(TCollision coll) { + histos.fill(HIST("hEventStatData"), 0.5); if (!coll.sel8()) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 1.5); if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 2.5); if (cfgEvSelkNoSameBunchPileup && !(coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 3.5); if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 4.5); if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 5.5); if (cfgEvSelUseGoodZvtxFT0vsPV && !(coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { - return; + return 0; } + histos.fill(HIST("hEventStatData"), 6.5); + return 1; + } + + template + void fillMultCorrPlotsBeforeSel(C const& coll, T const& inputTracks) + { histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_PVTracks_beforeSel"), coll.multNTracksPV(), inputTracks.size()); histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_centFT0C_beforeSel"), coll.centFT0C(), inputTracks.size()); histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_PVTracks_centFT0C_beforeSel"), coll.centFT0C(), coll.multNTracksPV()); histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_V0ATracks_beforeSel"), coll.multFV0A(), inputTracks.size()); histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_T0ATracks_beforeSel"), coll.multFT0A(), inputTracks.size()); histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_V0ATracks_T0CTracks_beforeSel"), coll.multFT0C(), coll.multFV0A()); + } + + template + void fillMultCorrPlotsAfterSel(C const& coll, T const& inputTracks) + { + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_PVTracks_afterSel"), coll.multNTracksPV(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel"), coll.centFT0C(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel"), coll.centFT0C(), coll.multNTracksPV()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel"), coll.multFV0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel"), coll.multFT0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel"), coll.multFT0C(), coll.multFV0A()); + } + + void processMCGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions, MyMCTracks const& tracks) + { + histos.fill(HIST("MCGenerated/hMC"), 0.5); + if (std::abs(mcCollision.posZ()) < cfgCutVertex) { + histos.fill(HIST("MCGenerated/hMC"), 1.5); + } + auto cent = 0; + + int nchInel = 0; + for (const auto& mcParticle : mcParticles) { + auto pdgcode = std::abs(mcParticle.pdgCode()); + if (mcParticle.isPhysicalPrimary() && (pdgcode == PDG_t::kPiPlus || pdgcode == PDG_t::kKPlus || pdgcode == PDG_t::kProton || pdgcode == PDG_t::kElectron || pdgcode == PDG_t::kMuonMinus)) { + if (std::abs(mcParticle.eta()) < 1.0) { + nchInel = nchInel + 1; + } + } + } + if (nchInel > 0 && std::abs(mcCollision.posZ()) < cfgCutVertex) + histos.fill(HIST("MCGenerated/hMC"), 2.5); + std::vector selectedEvents(collisions.size()); + int nevts = 0; + + for (const auto& collision : collisions) { + if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cfgCutVertex) { + continue; + } + if (cfgUseGoodITSLayerAllCut && !(collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + if (cfgEvSelkNoSameBunchPileup && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (cfgEvSelkNoITSROFrameBorder && !(collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (cfgEvSelkNoTimeFrameBorder && !(collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (cfgEvSelUseGoodZvtxFT0vsPV && !(collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + + auto rectrackspart = tracks.sliceBy(perCollision, collision.globalIndex()); + cent = collision.centFT0C(); + if (cfgUseSmallIonAdditionalEventCutInMC && !eventSelectedSmallion(collision, rectrackspart.size(), cent)) { + continue; + } + + 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("MCGenerated/hMC"), 3.5); + if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + return; + } + histos.fill(HIST("MCGenerated/hMC"), 4.5); + histos.fill(HIST("MCGenerated/hCentgen"), cent); + + // creating phi, pt, eta dstribution of generted MC particles + + // Generated track variables + + // initialized variable to be calculated event-by-event + double pTsumgen = 0.0; + double nNgen = 0.0; + float q1gen = 0.0; + float q2gen = 0.0; + float q3gen = 0.0; + float q4gen = 0.0; + float nChgen = 0.0; + + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.has_mcCollision()) + continue; + + // charged check + auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (!pdgEntry) + continue; + if (pdgEntry->Charge() == 0) + continue; + + if (mcParticle.isPhysicalPrimary()) { + if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < cfgCutPreSelPt) && (std::abs(mcParticle.eta()) < cfgCutPreSelEta)) { + histos.fill(HIST("MCGenerated/hP"), mcParticle.p()); + histos.fill(HIST("MCGenerated/hPt"), mcParticle.pt()); + histos.fill(HIST("MCGenerated/hEta"), mcParticle.eta()); + histos.fill(HIST("MCGenerated/hPhi"), mcParticle.phi()); + + pTsumgen += mcParticle.pt(); + nNgen += 1.0; + + if (mcParticle.pt() > cfgCutPtLower && mcParticle.pt() < cfgCutPtUpper) { + q1gen = q1gen + std::pow(mcParticle.pt(), 1.0); + q2gen = q2gen + std::pow(mcParticle.pt(), 2.0); + q3gen = q3gen + std::pow(mcParticle.pt(), 3.0); + q4gen = q4gen + std::pow(mcParticle.pt(), 4.0); + nChgen = nChgen + 1.0; + } + } + } + } //! end particle loop + + // Generated MeanPt distribution + if (nNgen > 0.0f) + histos.fill(HIST("MCGenerated/hMeanPt"), cent, pTsumgen / nNgen); + + // calculating observables + if (nChgen > cfgMinNch) { + float meanTerm1gen = q1gen / nChgen; + float varianceTerm1gen = (std::pow(q1gen, 2.0f) - q2gen) / (nChgen * (nChgen - 1.0f)); + float skewnessTerm1gen = (std::pow(q1gen, 3.0f) - 3.0f * q2gen * q1gen + 2.0f * q3gen) / (nChgen * (nChgen - 1.0f) * (nChgen - 2.0f)); + float kurtosisTerm1gen = (std::pow(q1gen, 4.0f) - (6.0f * q4gen) + (8.0f * q1gen * q3gen) - (6.0f * std::pow(q1gen, 2.0f) * q2gen) + (3.0f * std::pow(q2gen, 2.0f))) / (nChgen * (nChgen - 1.0f) * (nChgen - 2.0f) * (nChgen - 3.0f)); + + // filling profiles and histograms for central values + histos.get(HIST("MCGenerated/AnalysisProfiles/Prof_mean_t1"))->Fill(cent, nChgen, meanTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfiles/Prof_var_t1"))->Fill(cent, nChgen, varianceTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfiles/Prof_skew_t1"))->Fill(cent, nChgen, skewnessTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfiles/Prof_kurt_t1"))->Fill(cent, nChgen, kurtosisTerm1gen); + histos.fill(HIST("MCGenerated/AnalysisProfiles/Hist2D_Nch_centrality"), cent, nChgen); + histos.fill(HIST("MCGenerated/AnalysisProfiles/Hist2D_meanpt_centrality"), cent, meanTerm1gen); + + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_mean_t1"))->Fill(nChgen, meanTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_var_t1"))->Fill(nChgen, varianceTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_skew_t1"))->Fill(nChgen, skewnessTerm1gen); + histos.get(HIST("MCGenerated/AnalysisProfilesV2/Prof_kurt_t1"))->Fill(nChgen, kurtosisTerm1gen); + + // selecting subsample and filling profiles + float lRandomMc = fRndm->Rndm(); + int sampleIndexMc = static_cast(cfgNsubSample * lRandomMc); + subSampleMcGen[sampleIndexMc][0]->Fill(cent, nChgen, meanTerm1gen); + subSampleMcGen[sampleIndexMc][1]->Fill(cent, nChgen, varianceTerm1gen); + subSampleMcGen[sampleIndexMc][2]->Fill(cent, nChgen, skewnessTerm1gen); + subSampleMcGen[sampleIndexMc][3]->Fill(cent, nChgen, kurtosisTerm1gen); + + subSampleMcGenV2[sampleIndexMc][0]->Fill(nChgen, meanTerm1gen); + subSampleMcGenV2[sampleIndexMc][1]->Fill(nChgen, varianceTerm1gen); + subSampleMcGenV2[sampleIndexMc][2]->Fill(nChgen, skewnessTerm1gen); + subSampleMcGenV2[sampleIndexMc][3]->Fill(nChgen, kurtosisTerm1gen); + } + //------------------------------------------------------------------------------------------- + } + PROCESS_SWITCH(MeanptFluctuationsAnalysis, processMCGen, "Process Generated MC data", true); + + void processMCRec(MyMCRecCollisions::iterator const& collision, MyMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const& mcParticles) + { + histos.fill(HIST("MCGenerated/hMC"), 5.5); + + if (!collision.has_mcCollision()) { + return; + } + histos.fill(HIST("MCGenerated/hMC"), 6.5); + + if (!eventSelectionDefaultCuts(collision)) { + return; + } + histos.fill(HIST("MCGenerated/hMC"), 7.5); + + fillMultCorrPlotsBeforeSel(collision, tracks); + + const auto centralityFT0C = collision.centFT0C(); + if (cfgUse22sEventCut && !eventSelected(collision, tracks.size(), centralityFT0C)) + return; + if (cfgUseSmallIonAdditionalEventCut && !eventSelectedSmallion(collision, tracks.size(), centralityFT0C)) + return; + + if (cfgUseSmallIonAdditionalEventCut) { + fillMultCorrPlotsAfterSel(collision, tracks); + } + + histos.fill(HIST("MCGenerated/hMC"), 8.5); + histos.fill(HIST("hZvtx_after_sel"), collision.posZ()); + + double cent = 0.0; + int centChoiceFT0C = 1; + int centChoiceFT0A = 2; + int centChoiceFT0M = 3; + int centChoiceFV0A = 4; + if (cfgCentralityEstimator == centChoiceFT0C) + cent = collision.centFT0C(); + else if (cfgCentralityEstimator == centChoiceFT0A) + cent = collision.centFT0A(); + else if (cfgCentralityEstimator == centChoiceFT0M) + cent = collision.centFT0M(); + else if (cfgCentralityEstimator == centChoiceFV0A) + cent = collision.centFV0A(); + + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), centralityFT0C); + + // Calculating generated no of particles for the collision event + double noGen = 0.0; + auto mcColl = collision.mcCollision(); + // Slice particles belonging only to this MC collision + auto particlesThisEvent = mcParticles.sliceBy(perMcCollision, mcColl.globalIndex()); + + for (const auto& mcParticle : particlesThisEvent) { + if (!mcParticle.has_mcCollision()) + continue; + + // charged check + auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (!pdgEntry) + continue; + if (pdgEntry->Charge() == 0) + continue; + + if (mcParticle.isPhysicalPrimary()) { + if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < cfgCutPreSelPt) && (std::abs(mcParticle.eta()) < cfgCutPreSelEta)) { + if (mcParticle.pt() > cfgCutPtLower && mcParticle.pt() < cfgCutPtUpper) { + noGen = noGen + 1.0; + } + } + } + } //! end particle loop + + // variables + double pTsum = 0.0; + double nN = 0.0; + + float q1 = 0.0; + float q2 = 0.0; + float q3 = 0.0; + float q4 = 0.0; + float nCh = 0.0; + + for (const auto& track : tracks) { // Loop over tracks + + if (!track.has_collision()) { + continue; + } + if (!track.has_mcParticle()) { //! check if track has corresponding MC particle + continue; + } + + auto particle = track.mcParticle(); + if (!particle.has_mcCollision()) { + continue; + } + + if (!track.isPVContributor()) { + continue; + } + if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows) || !(track.tpcCrossedRowsOverFindableCls() >= cfgTPCnCrossedRowsOverFindableCls)) { + continue; + } + + histos.fill(HIST("his2DdcaXYvsPtBeforePtDepSel"), track.pt(), track.dcaXY()); + histos.fill(HIST("his2DdcaZvsPtBeforePtDepSel"), track.pt(), track.dcaZ()); + + if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { + continue; + } + if (cfgUsePtDepDCAz && !(std::abs(track.dcaZ()) < fPtDepDCAz->Eval(track.pt()))) { + continue; + } + + if (particle.isPhysicalPrimary()) { + if ((particle.pt() > cfgCutPtLower) && (particle.pt() < cfgCutPreSelPt) && (std::abs(particle.eta()) < cfgCutPreSelEta)) { + histos.fill(HIST("hP"), track.p()); + histos.fill(HIST("hPt"), track.pt()); + histos.fill(HIST("hEta"), track.eta()); + histos.fill(HIST("hPhi"), track.phi()); + histos.fill(HIST("hDcaXY"), track.dcaXY()); + histos.fill(HIST("hDcaZ"), track.dcaZ()); + histos.fill(HIST("his2DdcaXYvsPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("his2DdcaZvsPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("MCGenerated/hPtParticleVsTrack"), particle.pt(), track.pt()); + histos.fill(HIST("MCGenerated/hEtaParticleVsTrack"), particle.eta(), track.eta()); + histos.fill(HIST("MCGenerated/hPhiParticleVsTrack"), particle.phi(), track.phi()); + + pTsum += particle.pt(); + nN += 1.0; + + float pT = particle.pt(); + // calculating Q1, Q2, Q3, Q4. Nch + if (particle.pt() > cfgCutPtLower && particle.pt() < cfgCutPtUpper && track.sign() != 0) { + q1 = q1 + std::pow(pT, 1.0); + q2 = q2 + std::pow(pT, 2.0); + q3 = q3 + std::pow(pT, 3.0); + q4 = q4 + std::pow(pT, 4.0); + nCh = nCh + 1; + } + } + } + } // end track loop + + histos.fill(HIST("MCGenerated/hNgenVsNrec"), noGen, nCh); + + // MeanPt + if (nN > 0.0f) + histos.fill(HIST("hMeanPt"), cent, pTsum / nN); + + // calculating observables + if (nCh > cfgMinNch) { + float meanTerm1 = q1 / nCh; + float varianceTerm1 = (std::pow(q1, 2.0f) - q2) / (nCh * (nCh - 1.0f)); + float skewnessTerm1 = (std::pow(q1, 3.0f) - 3.0f * q2 * q1 + 2.0f * q3) / (nCh * (nCh - 1.0f) * (nCh - 2.0f)); + float kurtosisTerm1 = (std::pow(q1, 4.0f) - (6.0f * q4) + (8.0f * q1 * q3) - (6.0f * std::pow(q1, 2.0f) * q2) + (3.0f * std::pow(q2, 2.0f))) / (nCh * (nCh - 1.0f) * (nCh - 2.0f) * (nCh - 3.0f)); + + // filling profiles and histograms for central values + histos.get(HIST("AnalysisProfiles/Prof_mean_t1"))->Fill(cent, nCh, meanTerm1); + histos.get(HIST("AnalysisProfiles/Prof_var_t1"))->Fill(cent, nCh, varianceTerm1); + histos.get(HIST("AnalysisProfiles/Prof_skew_t1"))->Fill(cent, nCh, skewnessTerm1); + histos.get(HIST("AnalysisProfiles/Prof_kurt_t1"))->Fill(cent, nCh, kurtosisTerm1); + histos.fill(HIST("AnalysisProfiles/Hist2D_Nch_centrality"), cent, nCh); + histos.fill(HIST("AnalysisProfiles/Hist2D_meanpt_centrality"), cent, meanTerm1); + + histos.get(HIST("AnalysisProfilesV2/Prof_mean_t1"))->Fill(noGen, nCh, meanTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_var_t1"))->Fill(noGen, nCh, varianceTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_skew_t1"))->Fill(noGen, nCh, skewnessTerm1); + histos.get(HIST("AnalysisProfilesV2/Prof_kurt_t1"))->Fill(noGen, nCh, kurtosisTerm1); + + // selecting subsample and filling profiles + float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNsubSample * lRandom); + subSample[sampleIndex][0]->Fill(cent, nCh, meanTerm1); + subSample[sampleIndex][1]->Fill(cent, nCh, varianceTerm1); + subSample[sampleIndex][2]->Fill(cent, nCh, skewnessTerm1); + subSample[sampleIndex][3]->Fill(cent, nCh, kurtosisTerm1); + + subSampleV2[sampleIndex][0]->Fill(noGen, nCh, meanTerm1); + subSampleV2[sampleIndex][1]->Fill(noGen, nCh, varianceTerm1); + subSampleV2[sampleIndex][2]->Fill(noGen, nCh, skewnessTerm1); + subSampleV2[sampleIndex][3]->Fill(noGen, nCh, kurtosisTerm1); + } + //------------------------------------------------------------------------------------------- + } + PROCESS_SWITCH(MeanptFluctuationsAnalysis, processMCRec, "Process MC Reconstructed Data", true); + + // void process(aod::Collision const& coll, aod::Tracks const& inputTracks) + void processData(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + { + if (!eventSelectionDefaultCuts(coll)) { + return; + } + + fillMultCorrPlotsBeforeSel(coll, inputTracks); const auto centralityFT0C = coll.centFT0C(); if (cfgUse22sEventCut && !eventSelected(coll, inputTracks.size(), centralityFT0C)) @@ -348,14 +831,11 @@ struct MeanptFluctuationsQAQnTable { return; if (cfgUseSmallIonAdditionalEventCut) { - histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_PVTracks_afterSel"), coll.multNTracksPV(), inputTracks.size()); - histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel"), coll.centFT0C(), inputTracks.size()); - histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel"), coll.centFT0C(), coll.multNTracksPV()); - histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel"), coll.multFV0A(), inputTracks.size()); - histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel"), coll.multFT0A(), inputTracks.size()); - histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel"), coll.multFT0C(), coll.multFV0A()); + fillMultCorrPlotsAfterSel(coll, inputTracks); } + histos.fill(HIST("hEventStatData"), 7.5); + histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); double cent = 0.0; @@ -397,7 +877,17 @@ struct MeanptFluctuationsQAQnTable { continue; } - if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) { + if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows) || !(track.tpcCrossedRowsOverFindableCls() >= cfgTPCnCrossedRowsOverFindableCls)) { + continue; + } + + histos.fill(HIST("his2DdcaXYvsPtBeforePtDepSel"), track.pt(), track.dcaXY()); + histos.fill(HIST("his2DdcaZvsPtBeforePtDepSel"), track.pt(), track.dcaZ()); + + if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { + continue; + } + if (cfgUsePtDepDCAz && !(std::abs(track.dcaZ()) < fPtDepDCAz->Eval(track.pt()))) { continue; } @@ -407,6 +897,8 @@ struct MeanptFluctuationsQAQnTable { histos.fill(HIST("hPhi"), track.phi()); histos.fill(HIST("hDcaXY"), track.dcaXY()); histos.fill(HIST("hDcaZ"), track.dcaZ()); + histos.fill(HIST("his2DdcaXYvsPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("his2DdcaZvsPt"), track.pt(), track.dcaZ()); pTsum += track.pt(); nN += 1.0; @@ -421,98 +913,41 @@ struct MeanptFluctuationsQAQnTable { nCh = nCh + 1; } } - multPtQn(q1, q2, q3, q4, nCh, cent); // MeanPt if (nN > 0.0f) histos.fill(HIST("hMeanPt"), cent, pTsum / nN); - } -}; - -struct MeanptFluctuationsAnalysis { - - Configurable cfgNsubSample{"cfgNsubSample", 10, "Number of subsamples"}; - ConfigurableAxis centAxis{"centAxis", {90, 0, 90}, ""}; - ConfigurableAxis multAxis{"multAxis", {5000, 0.5, 5000.5}, ""}; - ConfigurableAxis meanpTAxis{"meanpTAxis", {500, 0, 5.0}, ""}; - - float minNch = 3.0f; - expressions::Filter nchFilter = aod::pt_qn::nch > minNch; - using FilteredMultPtQn = soa::Filtered; - - // Connect to ccdb - Service 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 ccdburl{"ccdburl", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; - - // Define output - HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::vector>> subSample; - TRandom3* fRndm = new TRandom3(0); - - void init(o2::framework::InitContext&) - { - // AxisSpec centAxis = {90, 0, 90, "centrality (%)"}; - // AxisSpec multAxis = {5000, 0.5, 5000.5, "#it{N}_{ch,acc}"}; - - registry.add("Prof_mean_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); - registry.add("Prof_var_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); - registry.add("Prof_skew_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); - registry.add("Prof_kurt_t1", "", {HistType::kTProfile2D, {centAxis, multAxis}}); - registry.add("Hist2D_Nch_centrality", "", {HistType::kTH2D, {centAxis, multAxis}}); - registry.add("Hist2D_meanpt_centrality", "", {HistType::kTH2D, {centAxis, meanpTAxis}}); - - // initial array - subSample.resize(cfgNsubSample); - for (int i = 0; i < cfgNsubSample; i++) { - subSample[i].resize(4); - } - for (int i = 0; i < cfgNsubSample; i++) { - subSample[i][0] = std::get>(registry.add(Form("subSample_%d/Prof_mean_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); - subSample[i][1] = std::get>(registry.add(Form("subSample_%d/Prof_var_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); - subSample[i][2] = std::get>(registry.add(Form("subSample_%d/Prof_skew_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); - subSample[i][3] = std::get>(registry.add(Form("subSample_%d/Prof_kurt_t1", i), "", {HistType::kTProfile2D, {centAxis, multAxis}})); - } - } - - float meanTerm1; - float varianceTerm1; - float skewnessTerm1; - float kurtosisTerm1; - - // void process(aod::MultPtQn::iterator const& event_ptqn) - void process(FilteredMultPtQn::iterator const& event_ptqn) - { - // LOGF(info, "Centrality= %f Nch= %f Q1= %f Q2= %f", event_ptqn.centrality(), event_ptqn.nch(), event_ptqn.q1(), event_ptqn.q2()); // calculating observables - meanTerm1 = event_ptqn.q1() / event_ptqn.nch(); - varianceTerm1 = (std::pow(event_ptqn.q1(), 2.0f) - event_ptqn.q2()) / (event_ptqn.nch() * (event_ptqn.nch() - 1.0f)); - skewnessTerm1 = (std::pow(event_ptqn.q1(), 3.0f) - 3.0f * event_ptqn.q2() * event_ptqn.q1() + 2.0f * event_ptqn.q3()) / (event_ptqn.nch() * (event_ptqn.nch() - 1.0f) * (event_ptqn.nch() - 2.0f)); - kurtosisTerm1 = (std::pow(event_ptqn.q1(), 4.0f) - (6.0f * event_ptqn.q4()) + (8.0f * event_ptqn.q1() * event_ptqn.q3()) - (6.0f * std::pow(event_ptqn.q1(), 2.0f) * event_ptqn.q2()) + (3.0f * std::pow(event_ptqn.q2(), 2.0f))) / (event_ptqn.nch() * (event_ptqn.nch() - 1.0f) * (event_ptqn.nch() - 2.0f) * (event_ptqn.nch() - 3.0f)); - - // filling profiles and histograms for central values - registry.get(HIST("Prof_mean_t1"))->Fill(event_ptqn.centrality(), event_ptqn.nch(), meanTerm1); - registry.get(HIST("Prof_var_t1"))->Fill(event_ptqn.centrality(), event_ptqn.nch(), varianceTerm1); - registry.get(HIST("Prof_skew_t1"))->Fill(event_ptqn.centrality(), event_ptqn.nch(), skewnessTerm1); - registry.get(HIST("Prof_kurt_t1"))->Fill(event_ptqn.centrality(), event_ptqn.nch(), kurtosisTerm1); - registry.fill(HIST("Hist2D_Nch_centrality"), event_ptqn.centrality(), event_ptqn.nch()); - registry.fill(HIST("Hist2D_meanpt_centrality"), event_ptqn.centrality(), meanTerm1); - - // selecting subsample and filling profiles - float lRandom = fRndm->Rndm(); - int sampleIndex = static_cast(cfgNsubSample * lRandom); - subSample[sampleIndex][0]->Fill(event_ptqn.centrality(), event_ptqn.nch(), meanTerm1); - subSample[sampleIndex][1]->Fill(event_ptqn.centrality(), event_ptqn.nch(), varianceTerm1); - subSample[sampleIndex][2]->Fill(event_ptqn.centrality(), event_ptqn.nch(), skewnessTerm1); - subSample[sampleIndex][3]->Fill(event_ptqn.centrality(), event_ptqn.nch(), kurtosisTerm1); + if (nCh > cfgMinNch) { + float meanTerm1 = q1 / nCh; + float varianceTerm1 = (std::pow(q1, 2.0f) - q2) / (nCh * (nCh - 1.0f)); + float skewnessTerm1 = (std::pow(q1, 3.0f) - 3.0f * q2 * q1 + 2.0f * q3) / (nCh * (nCh - 1.0f) * (nCh - 2.0f)); + float kurtosisTerm1 = (std::pow(q1, 4.0f) - (6.0f * q4) + (8.0f * q1 * q3) - (6.0f * std::pow(q1, 2.0f) * q2) + (3.0f * std::pow(q2, 2.0f))) / (nCh * (nCh - 1.0f) * (nCh - 2.0f) * (nCh - 3.0f)); + + // filling profiles and histograms for central values + histos.get(HIST("AnalysisProfiles/Prof_mean_t1"))->Fill(cent, nCh, meanTerm1); + histos.get(HIST("AnalysisProfiles/Prof_var_t1"))->Fill(cent, nCh, varianceTerm1); + histos.get(HIST("AnalysisProfiles/Prof_skew_t1"))->Fill(cent, nCh, skewnessTerm1); + histos.get(HIST("AnalysisProfiles/Prof_kurt_t1"))->Fill(cent, nCh, kurtosisTerm1); + histos.fill(HIST("AnalysisProfiles/Hist2D_Nch_centrality"), cent, nCh); + histos.fill(HIST("AnalysisProfiles/Hist2D_meanpt_centrality"), cent, meanTerm1); + + // selecting subsample and filling profiles + float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNsubSample * lRandom); + subSample[sampleIndex][0]->Fill(cent, nCh, meanTerm1); + subSample[sampleIndex][1]->Fill(cent, nCh, varianceTerm1); + subSample[sampleIndex][2]->Fill(cent, nCh, skewnessTerm1); + subSample[sampleIndex][3]->Fill(cent, nCh, kurtosisTerm1); + } + //------------------------------------------------------------------------------------------- } + PROCESS_SWITCH(MeanptFluctuationsAnalysis, processData, "Process Real Data", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { // Equivalent to the AddTask in AliPhysics return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx index 0ccf2544364..3cfea59e573 100644 --- a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx @@ -20,6 +20,7 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CCDB/BasicCCDBManager.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -28,7 +29,10 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include + #include +#include #include using namespace o2; @@ -37,9 +41,59 @@ using namespace o2::framework::expressions; using namespace o2::constants::physics; // for constants using namespace std; +#define ID_BIT_PI 0 // Identificationi bits for PID checks +#define ID_BIT_KA 1 +#define ID_BIT_PR 2 +#define ID_BIT_EL 3 +#define ID_BIT_DE 4 + +#define BITSET(mask, ithBit) ((mask) |= (1 << (ithBit))) // avoid name bitset as std::bitset is already there +#define BITCHECK(mask, ithBit) ((mask) & (1 << (ithBit))) // bit check will return int value, not bool, use BITCHECK != 0 in Analysi + +enum PidEnum { + kCh = 0, + kPi, // dont use kPion, kKaon, as these enumeration + kKa, // are already defined in $ROOTSYS/root/include/TPDGCode.h + kPr, + kEl, + kDe +}; + +enum ChargeEnum { + kPos = 0, + kNeg = 1 +}; + +static constexpr std::string_view PidDire[] = { + "Ch/", + "Pi/", + "Ka/", + "Pr/", + "El/", + "De/"}; + +static constexpr std::string_view ChargeDire[] = { + "Pos/", + "Neg/"}; + +std::string getModifiedStr(const std::string& myString) +{ + size_t pos = myString.rfind('/'); + if (pos != std::string::npos) { + std::string subString = myString.substr(0, pos); // remove "/" from end of the string + return subString; + } else { + return myString; + } +} + struct NchCumulantsId { HistogramRegistry hist{"hist", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry recoTracks{"recoTracks", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry genAnalysis{"genAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry recoAnalysis{"recoAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry purityAnalysis{"purityAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject}; // PDG data base Service pdgDB; @@ -50,6 +104,17 @@ struct NchCumulantsId { Configurable cfgCutEta{"cfgCutEta", 0.8, "cut for eta"}; Configurable cfgCutPtMax{"cfgCutPtMax", 3.0, "max cut for pT"}; Configurable cfgCutPtMin{"cfgCutPtMin", 0.15, "min cut for pT"}; + Configurable netChBin{"netChBin", 160, "bins for netch"}; + Configurable netChMax{"netChMax", 80.0, "max for netch"}; + Configurable netChMin{"netChMin", -80.0, "min for netch"}; + Configurable chBins{"chBins", 501, "bins for ch"}; + Configurable chMax{"chMax", 500.0, "max for ch"}; + Configurable chMin{"chMin", -1.0, "min for ch"}; + Configurable midRapMax{"midRapMax", 1000.0, "max for midrapmult"}; + Configurable midRapBins{"midRapBins", 1001, "bins for midrapmult"}; + + Configurable checkCollPosZMc{"checkCollPosZMc", false, "checkCollPosZMc"}; + Configurable flagUnusedVariableError{"flagUnusedVariableError", false, "flagUnusedVariableError"}; // Configurables for particle Identification Configurable cfgId01CheckVetoCut{"cfgId01CheckVetoCut", false, "cfgId01CheckVetoCut"}; @@ -101,12 +166,60 @@ struct NchCumulantsId { Configurable cfgVetoId10DeTOF{"cfgVetoId10DeTOF", 3.0, "cfgVetoId10DeTOF"}; } cfgVetoIdCut; + struct : ConfigurableGroup { + Configurable cfgCCDB01URL{"cfgCCDB01URL", "http://ccdb-test.cern.ch:8080", "cfgCCDB01URL"}; + Configurable cfgCCDB02Path{"cfgCCDB02Path", "Users/p/ppanigra/NchCumulants/correctionWeights/", "cfgCCDB02Path"}; + Configurable cfgCCDB03SOR{"cfgCCDB03SOR", 1, "cfgCCDB03SOR"}; + Configurable cfgCCDB04StrHistP{"cfgCCDB04StrHistP", "h01_p", "cfgCCDB04StrHistP"}; + Configurable cfgCCDB05StrHistPt{"cfgCCDB05StrHistPt", "h02_pt", "cfgCCDB05StrHistPt"}; + Configurable cfgCCDB06StrHistPtEta{"cfgCCDB06StrHistPtEta", "h20_pt_eta", "cfgCCDB06StrHistPtEta"}; + } cfgCCDB; + + struct : ConfigurableGroup { + Configurable printDebugMessages{"printDebugMessages", false, "printDebugMessages"}; + Configurable resetHistograms{"resetHistograms", false, "resetHistograms"}; + } cfgDebug; + + // Efficieny containing Histograms. + TH2F* hPtEtaForBinSearch = nullptr; + std::vector> hPtEtaForEffCorrection{kDe + 1, std::array{}}; + void init(InitContext const&) { + auto& mgr = o2::ccdb::BasicCCDBManager::instance(); + mgr.setURL(cfgCCDB.cfgCCDB01URL); + mgr.setCaching(true); + auto ccdbObj = mgr.getForTimeStamp(cfgCCDB.cfgCCDB02Path, cfgCCDB.cfgCCDB03SOR); + if (!ccdbObj) { + if (cfgDebug.printDebugMessages) + LOG(info) << "DEBUG :: CCDB OBJECT NOT FOUND"; + } else { + if (cfgDebug.printDebugMessages) + LOG(info) << "DEBUG :: CCDB OBJECT FOUND"; + } + + ccdbObj->Print(); + + hPtEtaForBinSearch = reinterpret_cast(ccdbObj->FindObject("hPtEta")); + if (cfgDebug.printDebugMessages) + LOG(info) << "DEBUG :: Obj Name = " << hPtEtaForBinSearch->GetName() << " :: entries = " << hPtEtaForBinSearch->GetEntries(); + std::string name = ""; + for (int i = 0; i <= kDe; i++) { + for (int j = 0; j < (kNeg + 1); j++) { + name = "hPtEta" + getModifiedStr(static_cast(PidDire[i])) + getModifiedStr(static_cast(ChargeDire[j])); + hPtEtaForEffCorrection[i][j] = reinterpret_cast(ccdbObj->FindObject(name.c_str())); + if (cfgDebug.printDebugMessages) + LOG(info) << "DEBUG :: Obj Name = " << hPtEtaForEffCorrection[i][j]->GetName() << " :: entries = " << hPtEtaForBinSearch->GetEntries(); + } + } + + mgr.setURL("http://alice-ccdb.cern.ch"); // RESET the URL otherwise the other process functions which contains ccdb lookups will fail + // QA check axes const AxisSpec axisEvents{1, 0, 1, "Counts"}; const AxisSpec axisEta{100, -1., +1., "#eta"}; - const AxisSpec axisPt{100, 0., 3., "p_{T} (GeV/c)"}; + const AxisSpec axisRapidity{200, -5, 5, "Rapidity (y)"}; + const AxisSpec axisPt{100, 0., 5., "p_{T} (GeV/c)"}; const AxisSpec axisP{100, 0., 5., "p (GeV/c)"}; const AxisSpec axisTPCInnerParam{100, 0, 3, "P_innerParam_Gev"}; const AxisSpec axisdEdx(100, 20, 500, {"#frac{dE}{dx}"}); @@ -123,16 +236,16 @@ struct NchCumulantsId { const AxisSpec axisTOFNSigma = {200, -10.0, 10.0, "n#sigma_{TOF}"}; const AxisSpec axisTOFExpMom = {200, 0.0f, 10.0f, "#it{p}_{tofExpMom} (GeV/#it{c})"}; - const AxisSpec axisNch(100, -50, 50, "Net_charge_dN"); - const AxisSpec axisPosCh(101, -1, 100, "Pos_charge"); - const AxisSpec axisNegCh(101, -1, 100, "Neg_charge"); - const AxisSpec axisNt(201, -1, 200, "Mult_midRap_Nch"); - const AxisSpec axisPrCh(101, -1, 100, "Pr_charge"); - const AxisSpec axisAPrCh(101, -1, 100, "APr_charge"); - const AxisSpec axisKaCh(101, -1, 100, "Ka_charge"); - const AxisSpec axisAKaCh(101, -1, 100, "AKa_charge"); - const AxisSpec axisPiCh(101, -1, 100, "Pion_Positive"); - const AxisSpec axisAPiCh(101, -1, 100, "Pion_Negative"); + const AxisSpec axisNch(netChBin, netChMin, netChMax, "Net_charge_dN"); + const AxisSpec axisPosCh(chBins, chMin, chMax, "Pos_charge"); + const AxisSpec axisNegCh(chBins, chMin, chMax, "Neg_charge"); + const AxisSpec axisNt(midRapBins, chMin, midRapMax, "Mult_midRap_Nch"); + const AxisSpec axisPrCh(chBins, chMin, chMax, "Pr_charge"); + const AxisSpec axisAPrCh(chBins, chMin, chMax, "APr_charge"); + const AxisSpec axisKaCh(chBins, chMin, chMax, "Ka_charge"); + const AxisSpec axisAKaCh(chBins, chMin, chMax, "AKa_charge"); + const AxisSpec axisPiCh(chBins, chMin, chMax, "Pion_Positive"); + const AxisSpec axisAPiCh(chBins, chMin, chMax, "Pion_Negative"); HistogramConfigSpec qnHist1({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPrCh, axisAPrCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); HistogramConfigSpec qnHist2({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPiCh, axisAPiCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); @@ -153,6 +266,8 @@ struct NchCumulantsId { HistogramConfigSpec histTofExpMomTofNSigma({HistType::kTH2F, {axisTOFExpMom, axisTOFNSigma}}); HistogramConfigSpec histTpcNSigmaTofNSigma({HistType::kTH2F, {axisTPCNSigma, axisTOFNSigma}}); + HistogramConfigSpec histPtMc({HistType::kTH1F, {axisPt}}); + // QA check histos hist.add("QA/events/preSel/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); @@ -222,8 +337,137 @@ struct NchCumulantsId { hist.add("sparse1", "sparse1", qnHist1); hist.add("sparse2", "sparse2", qnHist2); + + hist.add("sim/gen/sparse1", "sparse1", qnHist1); + hist.add("sim/gen/sparse2", "sparse2", qnHist2); + + hist.add("sim/reco/sparse1", "sparse1", qnHist1); + hist.add("sim/reco/sparse2", "sparse2", qnHist2); + + hist.add("sim/purity/sparse1", "sparse1", qnHist1); + hist.add("sim/purity/sparse2", "sparse2", qnHist2); + + recoAnalysis.add("recoAnalysis/Pi/Pos/h12_p", "p", kTH1F, {axisP}); + recoAnalysis.add("recoAnalysis/Pi/Pos/h13_pt", "pt", kTH1F, {axisPt}); + recoAnalysis.add("recoAnalysis/Pi/Pos/h14_eta", "eta", kTH1F, {axisEta}); + recoAnalysis.add("recoAnalysis/Pi/Pos/h15_phi", "phi", kTH1F, {axisPhi}); + recoAnalysis.add("recoAnalysis/Pi/Pos/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + recoAnalysis.add("recoAnalysis/Pi/Pos/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + recoAnalysis.add("recoAnalysis/Pi/Neg/h12_p", "p", kTH1F, {axisP}); + recoAnalysis.add("recoAnalysis/Pi/Neg/h13_pt", "pt", kTH1F, {axisPt}); + recoAnalysis.add("recoAnalysis/Pi/Neg/h14_eta", "eta", kTH1F, {axisEta}); + recoAnalysis.add("recoAnalysis/Pi/Neg/h15_phi", "phi", kTH1F, {axisPhi}); + recoAnalysis.add("recoAnalysis/Pi/Neg/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + recoAnalysis.add("recoAnalysis/Pi/Neg/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + + recoAnalysis.addClone("recoAnalysis/Pi/", "recoAnalysis/Ka/"); + recoAnalysis.addClone("recoAnalysis/Pi/", "recoAnalysis/Pr/"); + // recoAnalysis.addClone("recoAnalysis/Pi/", "recoAnalysis/El/"); + // recoAnalysis.addClone("recoAnalysis/Pi/", "recoAnalysis/De/"); + recoAnalysis.add("recoAnalysis/Charge/Pos/h12_p", "p", kTH1F, {axisP}); + recoAnalysis.add("recoAnalysis/Charge/Pos/h13_pt", "pt", kTH1F, {axisPt}); + recoAnalysis.add("recoAnalysis/Charge/Pos/h14_eta", "eta", kTH1F, {axisEta}); + recoAnalysis.add("recoAnalysis/Charge/Pos/h15_phi", "phi", kTH1F, {axisPhi}); + recoAnalysis.add("recoAnalysis/Charge/Pos/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + recoAnalysis.add("recoAnalysis/Charge/Pos/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + recoAnalysis.add("recoAnalysis/Charge/Neg/h12_p", "p", kTH1F, {axisP}); + recoAnalysis.add("recoAnalysis/Charge/Neg/h13_pt", "pt", kTH1F, {axisPt}); + recoAnalysis.add("recoAnalysis/Charge/Neg/h14_eta", "eta", kTH1F, {axisEta}); + recoAnalysis.add("recoAnalysis/Charge/Neg/h15_phi", "phi", kTH1F, {axisPhi}); + recoAnalysis.add("recoAnalysis/Charge/Neg/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + recoAnalysis.add("recoAnalysis/Charge/Neg/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + + genAnalysis.add("genAnalysis/Pi/Pos/h12_p", "p", kTH1F, {axisP}); + genAnalysis.add("genAnalysis/Pi/Pos/h13_pt", "pt", kTH1F, {axisPt}); + genAnalysis.add("genAnalysis/Pi/Pos/h14_eta", "eta", kTH1F, {axisEta}); + genAnalysis.add("genAnalysis/Pi/Pos/h15_phi", "phi", kTH1F, {axisPhi}); + genAnalysis.add("genAnalysis/Pi/Pos/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + genAnalysis.add("genAnalysis/Pi/Pos/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + genAnalysis.add("genAnalysis/Pi/Neg/h12_p", "p", kTH1F, {axisP}); + genAnalysis.add("genAnalysis/Pi/Neg/h13_pt", "pt", kTH1F, {axisPt}); + genAnalysis.add("genAnalysis/Pi/Neg/h14_eta", "eta", kTH1F, {axisEta}); + genAnalysis.add("genAnalysis/Pi/Neg/h15_phi", "phi", kTH1F, {axisPhi}); + genAnalysis.add("genAnalysis/Pi/Neg/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + genAnalysis.add("genAnalysis/Pi/Neg/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + + genAnalysis.addClone("genAnalysis/Pi/", "genAnalysis/Ka/"); + genAnalysis.addClone("genAnalysis/Pi/", "genAnalysis/Pr/"); + // genAnalysis.addClone("genAnalysis/Pi/", "genAnalysis/El/"); + // genAnalysis.addClone("genAnalysis/Pi/", "genAnalysis/De/"); + + genAnalysis.add("genAnalysis/Charge/Pos/h12_p", "p", kTH1F, {axisP}); + genAnalysis.add("genAnalysis/Charge/Pos/h13_pt", "pt", kTH1F, {axisPt}); + genAnalysis.add("genAnalysis/Charge/Pos/h14_eta", "eta", kTH1F, {axisEta}); + genAnalysis.add("genAnalysis/Charge/Pos/h15_phi", "phi", kTH1F, {axisPhi}); + genAnalysis.add("genAnalysis/Charge/Pos/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + genAnalysis.add("genAnalysis/Charge/Pos/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + genAnalysis.add("genAnalysis/Charge/Neg/h12_p", "p", kTH1F, {axisP}); + genAnalysis.add("genAnalysis/Charge/Neg/h13_pt", "pt", kTH1F, {axisPt}); + genAnalysis.add("genAnalysis/Charge/Neg/h14_eta", "eta", kTH1F, {axisEta}); + genAnalysis.add("genAnalysis/Charge/Neg/h15_phi", "phi", kTH1F, {axisPhi}); + genAnalysis.add("genAnalysis/Charge/Neg/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + genAnalysis.add("genAnalysis/Charge/Neg/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + + purityAnalysis.add("purityAnalysis/Charge/Pos/h12_p", "p", kTH1F, {axisP}); + purityAnalysis.add("purityAnalysis/Charge/Pos/h13_pt", "pt", kTH1F, {axisPt}); + purityAnalysis.add("purityAnalysis/Charge/Pos/h14_eta", "eta", kTH1F, {axisEta}); + purityAnalysis.add("purityAnalysis/Charge/Pos/h15_phi", "phi", kTH1F, {axisPhi}); + purityAnalysis.add("purityAnalysis/Charge/Pos/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + purityAnalysis.add("purityAnalysis/Charge/Pos/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + purityAnalysis.add("purityAnalysis/Charge/Neg/h12_p", "p", kTH1F, {axisP}); + purityAnalysis.add("purityAnalysis/Charge/Neg/h13_pt", "pt", kTH1F, {axisPt}); + purityAnalysis.add("purityAnalysis/Charge/Neg/h14_eta", "eta", kTH1F, {axisEta}); + purityAnalysis.add("purityAnalysis/Charge/Neg/h15_phi", "phi", kTH1F, {axisPhi}); + purityAnalysis.add("purityAnalysis/Charge/Neg/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + purityAnalysis.add("purityAnalysis/Charge/Neg/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + + purityAnalysis.add("purityAnalysis/Pi/Pos/h12_p", "p", kTH1F, {axisP}); + purityAnalysis.add("purityAnalysis/Pi/Pos/h13_pt", "pt", kTH1F, {axisPt}); + purityAnalysis.add("purityAnalysis/Pi/Pos/h14_eta", "eta", kTH1F, {axisEta}); + purityAnalysis.add("purityAnalysis/Pi/Pos/h15_phi", "phi", kTH1F, {axisPhi}); + purityAnalysis.add("purityAnalysis/Pi/Pos/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + purityAnalysis.add("purityAnalysis/Pi/Pos/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + purityAnalysis.add("purityAnalysis/Pi/Neg/h12_p", "p", kTH1F, {axisP}); + purityAnalysis.add("purityAnalysis/Pi/Neg/h13_pt", "pt", kTH1F, {axisPt}); + purityAnalysis.add("purityAnalysis/Pi/Neg/h14_eta", "eta", kTH1F, {axisEta}); + purityAnalysis.add("purityAnalysis/Pi/Neg/h15_phi", "phi", kTH1F, {axisPhi}); + purityAnalysis.add("purityAnalysis/Pi/Neg/h16_rapidity", "rapidity", kTH1F, {axisRapidity}); + purityAnalysis.add("purityAnalysis/Pi/Neg/h20_pt_eta", "pt_eta", kTH2F, {axisPt, axisEta}); + + purityAnalysis.addClone("purityAnalysis/Pi/", "purityAnalysis/Ka/"); + purityAnalysis.addClone("purityAnalysis/Pi/", "purityAnalysis/Pr/"); + // purityAnalysis.addClone("purityAnalysis/Pi/", "purityAnalysis/El/"); + // purityAnalysis.addClone("purityAnalysis/Pi/", "purityAnalysis/De/"); + } // init ends + static constexpr std::string_view HistRegDire2[] = { + "v0Table/Full/", + "v0Table/postK0sCheck/", + "v0Table/postMassCut/", + "v0Table/postSelectionCut/", + "recoK0s/PreSel/", + "recoK0s/PostSel/", + "recoTracks/PreSel/", + "recoTracks/PostSel/", + "recoAnalysis/", + "genAnalysis/", + "purityAnalysis/"}; + + enum HistRegEnum2 { + v0Full = 0, + v0PostK0sCheck, + v0PostMassCut, + v0PostSelectionCut, + recoK0sPreSel, + recoK0sPostSel, + recoTracksPreSel, + recoTracksPostSel, + recoAnalysisDir, + genAnalysisDir, + purityAnalysisDir + }; + enum IdentificationType { kTPCidentified = 0, kTOFidentified, @@ -255,7 +499,7 @@ struct NchCumulantsId { qaEventPostSel, qaTracksPreSel, qaTracksPostSel, - qaTracksIdfd + qaTracksIdfd, }; static constexpr std::string_view HistRegDire[] = { @@ -265,21 +509,14 @@ struct NchCumulantsId { "QA/tracks/postSel/", "QA/tracks/Idfd/"}; - enum PidEnum { - kPi = 0, // dont use kPion, kKaon, as these enumeration - kKa, // are already defined in $ROOTSYS/root/include/TPDGCode.h - kPr, - kEl, - kDe + enum ProcessTypeEnum { + doDataProcessing = 0, + doRecoProcessing, + doPurityProcessing, + doGenProcessing, + doSimProcessing }; - static constexpr std::string_view PidDire[] = { - "Pi/", - "Ka/", - "Pr/", - "El/", - "De/"}; - // particle identifications // tpc Selections @@ -648,10 +885,145 @@ struct NchCumulantsId { fillIdentificationQA(hist, track); // Look at Proton } - using MyAllTracks = soa::Join; + template + void fillGenTrackQA(HistogramRegistry& r, const TrackType& t) + { + auto base = + HIST(HistRegDire2[DIR]) + + HIST(PidDire[P]) + + HIST(ChargeDire[C]); + r.fill(base + HIST("h12_p"), t.p()); + r.fill(base + HIST("h13_pt"), t.pt()); + r.fill(base + HIST("h14_eta"), t.eta()); + r.fill(base + HIST("h15_phi"), t.phi()); + r.fill(base + HIST("h16_rapidity"), t.y()); + r.fill(base + HIST("h20_pt_eta"), t.pt(), t.eta()); + } + + template + void fillRecoTrackQA(HistogramRegistry& r, const TrackType& t) + { + auto base = + HIST(HistRegDire2[DIR]) + + HIST(PidDire[P]) + + HIST(ChargeDire[C]); + r.fill(base + HIST("h12_p"), t.p()); + r.fill(base + HIST("h13_pt"), t.pt()); + r.fill(base + HIST("h14_eta"), t.eta()); + r.fill(base + HIST("h15_phi"), t.phi()); + r.fill(base + HIST("h16_rapidity"), t.y()); + r.fill(base + HIST("h20_pt_eta"), t.pt(), t.eta()); + } + + template + void fillPurityTrackQA(HistogramRegistry& r, const TrackType& t) + { + auto base = + HIST(HistRegDire2[DIR]) + + HIST(PidDire[P]) + + HIST(ChargeDire[C]); + r.fill(base + HIST("h12_p"), t.p()); + r.fill(base + HIST("h13_pt"), t.pt()); + r.fill(base + HIST("h14_eta"), t.eta()); + r.fill(base + HIST("h15_phi"), t.phi()); + r.fill(base + HIST("h16_rapidity"), t.y()); + r.fill(base + HIST("h20_pt_eta"), t.pt(), t.eta()); + } + + template + void executeTrackAnalysisPart(const T& track, const int& trackIdTag, float& nP, float& nM, + const int& idMethodPi, const bool& trackIsPion, float& nAPi, float& nPi, + const int& idMethodKa, const bool& trackIsKaon, float& nAKa, float& nKa, + const int& idMethodPr, const bool& trackIsProton, float& nPr, float& nAPr, H& recoAnalysis) + { + if (flagUnusedVariableError) + LOG(info) << trackIdTag << idMethodPi << ":" << idMethodKa << ":" << idMethodPr; + if (track.sign() > 0) { + // fillRecoTrackQA(recoAnalysis, track); + nP++; + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h12_p"), track.p()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h13_pt"), track.pt()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h14_eta"), track.eta()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h15_phi"), track.phi()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h16_rapidity"), track.y()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h20_pt_eta"), track.pt(), track.eta()); + } + if (track.sign() < 0) { + // fillRecoTrackQA(recoAnalysis, track); + nM++; + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h12_p"), track.p()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h13_pt"), track.pt()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h14_eta"), track.eta()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h15_phi"), track.phi()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h16_rapidity"), track.y()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h20_pt_eta"), track.pt(), track.eta()); + } + + if (trackIsPion) { + // if (idMethodPi == kTPCidentified) { + // fillIdentificationQA(hist, track); // set hist as recoAnalysis after tpcId etc add true + // } else if (idMethodPi == kTPCTOFidentified) { + // fillIdentificationQA(hist, track); + // } else if (idMethodPi == kUnidentified) { + // fillIdentificationQA(hist, track); + // } + if (track.sign() > 0) { + nPi++; + fillRecoTrackQA(recoAnalysis, track); + } else if (track.sign() < 0) { + nAPi++; + fillRecoTrackQA(recoAnalysis, track); + } + // fillRecoTrackQA(recoAnalysis, track); + } + if (trackIsKaon) { + // if (idMethodKa == kTPCidentified) { + // fillIdentificationQA(hist, track); + // } else if (idMethodKa == kTPCTOFidentified) { + // fillIdentificationQA(hist, track); + // } else if (idMethodKa == kUnidentified) { + // fillIdentificationQA(hist, track); + // } + if (track.sign() > 0) { + nKa++; + fillRecoTrackQA(recoAnalysis, track); + } else if (track.sign() < 0) { + nAKa++; + fillRecoTrackQA(recoAnalysis, track); + } + // fillRecoTrackQA(recoAnalysis, track); + } + if (trackIsProton) { + // if (idMethodPr == kTPCidentified) { + // fillIdentificationQA(hist, track); + // } else if (idMethodPr == kTPCTOFidentified) { + // fillIdentificationQA(hist, track); + // } else if (idMethodPr == kUnidentified) { + // fillIdentificationQA(hist, track); + // } + if (track.sign() > 0) { + nPr++; + fillRecoTrackQA(recoAnalysis, track); + } else if (track.sign() < 0) { + nAPr++; + fillRecoTrackQA(recoAnalysis, track); + } + // fillRecoTrackQA(recoAnalysis, track); + } + + // recoAnalysis.fill(HIST("recoAnalysis/SelectedTrack_IdentificationTag"), trackIdTag); + } + + using MyAllTracks = soa::Join; using MyCollisions = soa::Join; + + using MyTracksWithMclabels = soa::Join; + using MyCollisionsWithMcLabels = soa::Join; + // tracks and collision filters Filter col = aod::evsel::sel8 == true; Filter colFilter = nabs(aod::collision::posZ) < cfgCutPosZ; @@ -664,94 +1036,639 @@ struct NchCumulantsId { using MyFilteredCol = soa::Filtered; using MyFilteredTracks = soa::Filtered; + using MyFilteredColsWithMcLabels = soa::Filtered; + using MyFilteredTracksWithMcLabels = soa::Filtered; + // manual sliceby SliceCache cache; + Preslice tracksPerCollisionPreslice = o2::aod::track::collisionId; + Preslice mctracksPerCollisionPreslice = o2::aod::track::collisionId; - void process(MyFilteredCol const& collisions, MyFilteredTracks const& tracks) + template + void executeAnalysis(const C& collisions, const T& tracks) { - for (const auto& col : collisions) { - - int nP = 0; - int nM = 0; - int nCh = 0; - int nT = 0; - int nPr = 0; - int nAPr = 0; - int nKa = 0; - int nAKa = 0; - int nPi = 0; - int nAPi = 0; - // group tracks manually with corresponding collision using col id; - const uint64_t collIdx = col.globalIndex(); - const auto tracksTablePerColl = tracks.sliceBy(tracksPerCollisionPreslice, collIdx); - - for (const auto& track : tracksTablePerColl) { - - fillTrackQA(track); - - if (track.sign() == 1) { - nP++; - } - if (track.sign() == -1) { - nM++; - } + float nP = 0; + float nM = 0; + float nCh = 0; + float nT = 0; + float nPr = 0; + float nAPr = 0; + float nKa = 0; + float nAKa = 0; + float nPi = 0; + float nAPi = 0; + + bool trackIsPion = false; + bool trackIsKaon = false; + bool trackIsProton = false; + + int trackIdTag = 0; + int idMethodPi = kUnidentified; + int idMethodKa = kUnidentified; + int idMethodPr = kUnidentified; + + int ptEtaBin = -1; + + if constexpr (analysisType == doDataProcessing) { + for (const auto& col : collisions) { + nP = 0; + nM = 0; + nCh = 0; + nT = 0; + nPr = 0; + nAPr = 0; + nKa = 0; + nAKa = 0; + nPi = 0; + nAPi = 0; + + // group tracks manually with corresponding collision using col id; + const uint64_t collIdx = col.globalIndex(); + const auto tracksTablePerColl = tracks.sliceBy(tracksPerCollisionPreslice, collIdx); + + for (const auto& track : tracksTablePerColl) { + + ptEtaBin = hPtEtaForBinSearch->FindBin(track.pt(), track.eta()); // Find Track Bin for efficiency correction + + fillTrackQA(track); - int idMethod; - // pion - if (selPion(track, idMethod)) { if (track.sign() == 1) { - nPi++; + // nP++; + nP += hPtEtaForEffCorrection[kCh][kPos]->GetBinContent(ptEtaBin); } if (track.sign() == -1) { - nAPi++; + nM += hPtEtaForEffCorrection[kCh][kNeg]->GetBinContent(ptEtaBin); } - if (idMethod == kTPCidentified) - fillIdentificationQA(hist, track); - if (idMethod == kTPCTOFidentified) - fillIdentificationQA(hist, track); - } - // kaon - if (selKaon(track, idMethod)) { - if (track.sign() == 1) { - nKa++; + int idMethod; + // pion + if (selPion(track, idMethod)) { + if (track.sign() == 1) { + nPi += hPtEtaForEffCorrection[kPi][kPos]->GetBinContent(ptEtaBin); + } + if (track.sign() == -1) { + nAPi += hPtEtaForEffCorrection[kPi][kNeg]->GetBinContent(ptEtaBin); + } + + if (idMethod == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethod == kTPCTOFidentified) + fillIdentificationQA(hist, track); } - if (track.sign() == -1) { - nAKa++; + // kaon + if (selKaon(track, idMethod)) { + if (track.sign() == 1) { + nKa += hPtEtaForEffCorrection[kKa][kPos]->GetBinContent(ptEtaBin); + } + if (track.sign() == -1) { + nAKa += hPtEtaForEffCorrection[kKa][kNeg]->GetBinContent(ptEtaBin); + } + + if (idMethod == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethod == kTPCTOFidentified) + fillIdentificationQA(hist, track); } + // proton + if (selProton(track, idMethod)) { + if (track.sign() == 1) { + nPr += hPtEtaForEffCorrection[kPr][kPos]->GetBinContent(ptEtaBin); + } + if (track.sign() == -1) { + nAPr += hPtEtaForEffCorrection[kPr][kNeg]->GetBinContent(ptEtaBin); + } + + if (idMethod == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethod == kTPCTOFidentified) + fillIdentificationQA(hist, track); + } + } // track loop ends + nCh = nP - nM; + nT = nP + nM; + + fillCollQA(col, nCh, nT); - if (idMethod == kTPCidentified) - fillIdentificationQA(hist, track); - if (idMethod == kTPCTOFidentified) - fillIdentificationQA(hist, track); + hist.fill(HIST("sparse1"), nCh, nP, nM, nPr, nAPr, nKa, nAKa, nT, col.centFT0M()); + hist.fill(HIST("sparse2"), nCh, nP, nM, nPi, nAPi, nKa, nAKa, nT, col.centFT0M()); + + } // collision loop ends + } else if constexpr (analysisType == doRecoProcessing || analysisType == doPurityProcessing) { + + for (const auto& col : collisions) { + + if (!col.has_mcCollision()) { + LOG(warning) << "No MC collision for this collision, skip..."; + continue; } - // proton - if (selProton(track, idMethod)) { - if (track.sign() == 1) { - nPr++; + float nP = 0; + float nM = 0; + float nCh = 0; + float nT = 0; + float nPr = 0; + float nAPr = 0; + float nKa = 0; + float nAKa = 0; + float nPi = 0; + float nAPi = 0; + // group tracks manually with corresponding collision using col id; + const uint64_t collIdx = col.globalIndex(); + const auto tracksTablePerColl = tracks.sliceBy(mctracksPerCollisionPreslice, collIdx); + + for (const auto& track : tracksTablePerColl) { + + if (!track.has_mcParticle()) { + LOG(warning) << "No MC Particle for this track, skip..."; + continue; } - if (track.sign() == -1) { - nAPr++; + + auto mcPart = track.mcParticle(); + + fillTrackQA(track); + + // Do Proper Track Identification + trackIsPion = false; + trackIsKaon = false; + trackIsProton = false; + + trackIdTag = 0; + idMethodPi = kUnidentified; + idMethodKa = kUnidentified; + idMethodPr = kUnidentified; + + if (selPion(track, idMethodPi)) { + trackIsPion = true; + BITSET(trackIdTag, ID_BIT_PI); } + if (selKaon(track, idMethodKa)) { + trackIsKaon = true; + BITSET(trackIdTag, ID_BIT_KA); + } + if (selProton(track, idMethodPr)) { + trackIsProton = true; + BITSET(trackIdTag, ID_BIT_PR); + } + + if constexpr (analysisType == doPurityProcessing) { + if (trackIsPion) { + if (track.sign() > 0 && mcPart.pdgCode() != kPiPlus) { + trackIsPion = false; + } + if (track.sign() < 0 && mcPart.pdgCode() != kPiMinus) { + trackIsPion = false; + } + } + if (trackIsKaon) { + if (track.sign() > 0 && mcPart.pdgCode() != kKPlus) { + trackIsKaon = false; + } + if (track.sign() < 0 && mcPart.pdgCode() != kKMinus) { + trackIsKaon = false; + } + } + if (trackIsProton) { + if (track.sign() > 0 && mcPart.pdgCode() != kProton) { + trackIsProton = false; + } + if (track.sign() < 0 && mcPart.pdgCode() != kProtonBar) { + trackIsProton = false; + } + } + } + + executeTrackAnalysisPart(track, trackIdTag, nP, nM, + idMethodPi, trackIsPion, nAPi, nPi, + idMethodKa, trackIsKaon, nAKa, nKa, + idMethodPr, trackIsProton, nPr, nAPr, recoAnalysis); - if (idMethod == kTPCidentified) - fillIdentificationQA(hist, track); - if (idMethod == kTPCTOFidentified) - fillIdentificationQA(hist, track); + } // track itteration ends + + nCh = nP - nM; + nT = nP + nM; + + fillCollQA(col, nCh, nT); + + hist.fill(HIST("sparse1"), nCh, nP, nM, nPr, nAPr, nKa, nAKa, nT, col.centFT0M()); + hist.fill(HIST("sparse2"), nCh, nP, nM, nPi, nAPi, nKa, nAKa, nT, col.centFT0M()); + + } // collision ends + } + } + + void processRun3(MyFilteredCol const& collisions, MyFilteredTracks const& tracks) + { + executeAnalysis(collisions, tracks); + } + PROCESS_SWITCH(NchCumulantsId, processRun3, "Process for Run-3", false); + + void processMcRecco(MyFilteredColsWithMcLabels const& collisions, MyFilteredTracksWithMcLabels const& tracks, aod::McParticles const&) + { + executeAnalysis(collisions, tracks); + } + PROCESS_SWITCH(NchCumulantsId, processMcRecco, "Process for MC Recco", false); + + void processPurity(MyFilteredColsWithMcLabels const& collisions, MyFilteredTracksWithMcLabels const& tracks, aod::McParticles const&) + { + executeAnalysis(collisions, tracks); + } + PROCESS_SWITCH(NchCumulantsId, processPurity, "Process for MC generated purity", false); + // process fun is over + + // process for truth and response matrix starts now + + Preslice mcTracksPerMcCollisionPreslice = o2::aod::mcparticle::mcCollisionId; + + using MyMcCollisions = aod::McCollisions; + + void processGen(MyMcCollisions const&, MyFilteredColsWithMcLabels const& collisions, aod::McParticles const& mcParticles) + { + for (const auto& col : collisions) { + if (!col.has_mcCollision()) { + LOG(warning) << "No MC collision for this event, skip..."; + continue; + } + const auto& mcColl = col.mcCollision(); + + // ---- apply same Vz cut as data/reco ---- + if (std::abs(mcColl.posZ()) > cfgCutPosZ) { + continue; // reject GEN events outside acceptance + } + // slice MCParticles for this MC collision + const auto mcTracksTablePerMcColl = mcParticles.sliceBy(mcTracksPerMcCollisionPreslice, mcColl.globalIndex()); + + float nP = 0; + float nM = 0; + float nCh = 0; + float nT = 0; + float nPr = 0; + float nAPr = 0; + float nKa = 0; + float nAKa = 0; + float nPi = 0; + float nAPi = 0; + for (const auto& mcTrack : mcTracksTablePerMcColl) { + if (!mcTrack.isPhysicalPrimary()) { + continue; + } + // pt / eta acceptance (same as RECO acceptance) + if (mcTrack.pt() <= cfgCutPtMin || + mcTrack.pt() >= cfgCutPtMax || + std::abs(mcTrack.eta()) >= cfgCutEta) { + continue; } - } // track itteration ends + int pdg = mcTrack.pdgCode(); + + if (pdg == kPiPlus || pdg == kKPlus || pdg == kProton || pdg == kPositron || pdg == kMuonPlus || pdg == kDeuteron) { + nP++; + + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h12_p"), mcTrack.p()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h13_pt"), mcTrack.pt()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h14_eta"), mcTrack.eta()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h15_phi"), mcTrack.phi()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h16_rapidity"), mcTrack.y()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); + } else if (pdg == kPiMinus || pdg == kKMinus || pdg == kProtonBar || pdg == kElectron || pdg == kMuonMinus || pdg == -kDeuteron) { + nM++; + + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h12_p"), mcTrack.p()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h13_pt"), mcTrack.pt()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h14_eta"), mcTrack.eta()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h15_phi"), mcTrack.phi()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h16_rapidity"), mcTrack.y()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); + } + // ----- Pions ----- + if (pdg == kPiPlus) { + nPi++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kPiMinus) { + nAPi++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kKPlus) { + nKa++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kKMinus) { + nAKa++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kProton) { + nPr++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kProtonBar) { + nAPr++; + fillGenTrackQA(genAnalysis, mcTrack); + } + } nCh = nP - nM; nT = nP + nM; - fillCollQA(col, nCh, nT); - hist.fill(HIST("sparse1"), nCh, nP, nM, nPr, nAPr, nKa, nAKa, nT, col.centFT0M()); hist.fill(HIST("sparse2"), nCh, nP, nM, nPi, nAPi, nKa, nAKa, nT, col.centFT0M()); - } // collision ends - } // process ends + } + PROCESS_SWITCH(NchCumulantsId, processGen, "Process for MC generated or truth", false); + + void processSim(MyFilteredColsWithMcLabels const& collisions, MyFilteredTracksWithMcLabels const& tracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + { + if (flagUnusedVariableError) + LOG(info) << mcCollisions.size(); + bool trackIsPion = false; + bool trackIsKaon = false; + bool trackIsProton = false; + + int trackIdTag = 0; + int idMethodPi = kUnidentified; + int idMethodKa = kUnidentified; + int idMethodPr = kUnidentified; + + int ptEtaBin = -1; + + for (auto const& col : collisions) { + + if (!col.has_mcCollision()) { + LOG(warning) << "No MC collision for this collision, skip..."; + continue; + } + auto mcCollision = col.mcCollision(); + + if (checkCollPosZMc && std::abs(mcCollision.posZ()) > cfgCutPosZ) + continue; + + // slice reco tracks to this collision + const uint64_t collIdx = col.globalIndex(); + const auto tracksTablePerColl = tracks.sliceBy(mctracksPerCollisionPreslice, collIdx); + + // slice mc particles to mc collisions + const auto mcTracksTablePerMcColl = mcParticles.sliceBy(mcTracksPerMcCollisionPreslice, mcCollision.globalIndex()); + + // Denominator -- Generator level(truth) + + float nPGen = 0, nMGen = 0, nChGen = 0, nTGen = 0; + float nPrGen = 0, nAPrGen = 0; + float nKaGen = 0, nAKaGen = 0; + float nPiGen = 0, nAPiGen = 0; + + for (const auto& mcTrack : mcTracksTablePerMcColl) { + if (!mcTrack.isPhysicalPrimary()) + continue; + if (mcTrack.pt() <= cfgCutPtMin || + mcTrack.pt() >= cfgCutPtMax || + std::abs(mcTrack.eta()) >= cfgCutEta) + continue; + + int pdg = mcTrack.pdgCode(); + + if (pdg == kPiPlus || pdg == kKPlus || pdg == kProton || pdg == kPositron || pdg == kMuonPlus || pdg == kDeuteron) { + nPGen++; + + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h12_p"), mcTrack.p()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h13_pt"), mcTrack.pt()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h14_eta"), mcTrack.eta()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h15_phi"), mcTrack.phi()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h16_rapidity"), mcTrack.y()); + genAnalysis.fill(HIST("genAnalysis/Charge/Pos/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); + } else if (pdg == kPiMinus || pdg == kKMinus || pdg == kProtonBar || pdg == kElectron || pdg == kMuonMinus || pdg == -kDeuteron) { + nMGen++; + + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h12_p"), mcTrack.p()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h13_pt"), mcTrack.pt()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h14_eta"), mcTrack.eta()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h15_phi"), mcTrack.phi()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h16_rapidity"), mcTrack.y()); + genAnalysis.fill(HIST("genAnalysis/Charge/Neg/h20_pt_eta"), mcTrack.pt(), mcTrack.eta()); + } + + if (pdg == kPiPlus) { + nPiGen++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kPiMinus) { + nAPiGen++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kKPlus) { + nKaGen++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kKMinus) { + nAKaGen++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kProton) { + nPrGen++; + fillGenTrackQA(genAnalysis, mcTrack); + } else if (pdg == kProtonBar) { + nAPrGen++; + fillGenTrackQA(genAnalysis, mcTrack); + } + + } // particle/track loop for gen ends + nChGen = nPGen - nMGen; + nTGen = nPGen + nMGen; + + // ── Fill GEN sparse (denominator) ──────────────────────── + hist.fill(HIST("sim/gen/sparse1"), nChGen, nPGen, nMGen, + nPrGen, nAPrGen, nKaGen, nAKaGen, nTGen, + col.centFT0M()); + hist.fill(HIST("sim/gen/sparse2"), nChGen, nPGen, nMGen, + nPiGen, nAPiGen, nKaGen, nAKaGen, nTGen, + col.centFT0M()); + // + // Numerator - Reconstructed + truth matched + // reco->selFunc passed, no pdg + // purity -> selFunc matched with pdg matched + // + float nPRec = 0, nMRec = 0, nChRec = 0, nTRec = 0; + float nPrRec = 0, nAPrRec = 0; + float nKaRec = 0, nAKaRec = 0; + float nPiRec = 0, nAPiRec = 0; + + // purity counters — separate from reco + float nPPur = 0, nMPur = 0, nChPur = 0, nTPur = 0; + float nPrPur = 0, nAPrPur = 0; + float nKaPur = 0, nAKaPur = 0; + float nPiPur = 0, nAPiPur = 0; + + for (const auto& track : tracksTablePerColl) { + + if (!track.has_mcParticle()) { + LOG(warning) << "No MC Particle for this track, skip..."; + continue; + } + auto mcPart = track.mcParticle(); + if (!mcPart.isPhysicalPrimary()) + continue; + int pdg = mcPart.pdgCode(); + + fillTrackQA(track); + + trackIsPion = false; + trackIsKaon = false; + trackIsProton = false; + trackIdTag = 0; + idMethodPi = kUnidentified; + idMethodKa = kUnidentified; + idMethodPr = kUnidentified; + + if (selPion(track, idMethodPi)) { + trackIsPion = true; + BITSET(trackIdTag, ID_BIT_PI); + } + if (selKaon(track, idMethodKa)) { + trackIsKaon = true; + BITSET(trackIdTag, ID_BIT_KA); + } + if (selProton(track, idMethodPr)) { + trackIsProton = true; + BITSET(trackIdTag, ID_BIT_PR); + } + + // bool isKnownCharged = (std::abs(pdg) == kPiPlus || + // std::abs(pdg) == kKPlus || + // std::abs(pdg) == kProton || + // std::abs(pdg) == kElectron || + // std::abs(pdg) == kMuonMinus || + // std::abs(pdg) == kDeuteron); + + ptEtaBin = hPtEtaForBinSearch->FindBin(track.pt(), track.eta()); // Find Track Bin for efficiency correction + + if (track.sign() > 0) { + nPRec += hPtEtaForEffCorrection[kCh][kPos]->GetBinContent(ptEtaBin); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h12_p"), track.p()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h13_pt"), track.pt()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h14_eta"), track.eta()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h15_phi"), track.phi()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h16_rapidity"), track.y()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Pos/h20_pt_eta"), track.pt(), track.eta()); + } else if (track.sign() < 0) { + nMRec += hPtEtaForEffCorrection[kCh][kNeg]->GetBinContent(ptEtaBin); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h12_p"), track.p()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h13_pt"), track.pt()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h14_eta"), track.eta()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h15_phi"), track.phi()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h16_rapidity"), track.y()); + recoAnalysis.fill(HIST("recoAnalysis/Charge/Neg/h20_pt_eta"), track.pt(), track.eta()); + } + + // species reco — sel passes, PDG not checked (raw reco) + if (trackIsPion) { + if (track.sign() > 0) { + nPiRec += hPtEtaForEffCorrection[kPi][kPos]->GetBinContent(ptEtaBin); + fillRecoTrackQA(recoAnalysis, track); + } else if (track.sign() < 0) { + nAPiRec += hPtEtaForEffCorrection[kPi][kNeg]->GetBinContent(ptEtaBin); + fillRecoTrackQA(recoAnalysis, track); + } + } else if (trackIsKaon) { + if (track.sign() > 0) { + nKaRec += hPtEtaForEffCorrection[kKa][kPos]->GetBinContent(ptEtaBin); + fillRecoTrackQA(recoAnalysis, track); + } else if (track.sign() < 0) { + nAKaRec += hPtEtaForEffCorrection[kKa][kNeg]->GetBinContent(ptEtaBin); + fillRecoTrackQA(recoAnalysis, track); + } + } else if (trackIsProton) { + if (track.sign() > 0) { + nPrRec += hPtEtaForEffCorrection[kPr][kPos]->GetBinContent(ptEtaBin); + fillRecoTrackQA(recoAnalysis, track); + } else if (track.sign() < 0) { + nAPrRec += hPtEtaForEffCorrection[kPr][kNeg]->GetBinContent(ptEtaBin); + fillRecoTrackQA(recoAnalysis, track); + } + } + // purity check - check pdg aginst sign + bool purityPion = false; + if (trackIsPion) { + if (track.sign() > 0 && pdg == kPiPlus) + purityPion = true; + if (track.sign() < 0 && pdg == kPiMinus) + purityPion = true; + } + + bool purityKaon = false; + if (trackIsKaon) { + if (track.sign() > 0 && pdg == kKPlus) + purityKaon = true; + if (track.sign() < 0 && pdg == kKMinus) + purityKaon = true; + } + + bool purityProton = false; + if (trackIsProton) { + if (track.sign() > 0 && pdg == kProton) + purityProton = true; + if (track.sign() < 0 && pdg == kProtonBar) + purityProton = true; + } + + // charge purity — track.sign() + isKnownCharged + PDG sign consistency + bool pdgPositive = (pdg == kPiPlus || pdg == kKPlus || pdg == kProton || + pdg == kPositron || pdg == kMuonPlus || pdg == kDeuteron); + bool pdgNegative = (pdg == kPiMinus || pdg == kKMinus || pdg == kProtonBar || + pdg == kElectron || pdg == kMuonMinus || pdg == -kDeuteron); + + if (track.sign() > 0 && pdgPositive) { + nPPur++; + purityAnalysis.fill(HIST("purityAnalysis/Charge/Pos/h12_p"), track.p()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Pos/h13_pt"), track.pt()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Pos/h14_eta"), track.eta()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Pos/h15_phi"), track.phi()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Pos/h16_rapidity"), track.y()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Pos/h20_pt_eta"), track.pt(), track.eta()); + } else if (track.sign() < 0 && pdgNegative) { + nMPur++; + purityAnalysis.fill(HIST("purityAnalysis/Charge/Neg/h12_p"), track.p()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Neg/h13_pt"), track.pt()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Neg/h14_eta"), track.eta()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Neg/h15_phi"), track.phi()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Neg/h16_rapidity"), track.y()); + purityAnalysis.fill(HIST("purityAnalysis/Charge/Neg/h20_pt_eta"), track.pt(), track.eta()); + } + + // species purity fill + if (purityPion) { + if (track.sign() > 0) { + nPiPur++; + fillPurityTrackQA(purityAnalysis, track); + } else { + nAPiPur++; + fillPurityTrackQA(purityAnalysis, track); + } + } else if (purityKaon) { + if (track.sign() > 0) { + nKaPur++; + fillPurityTrackQA(purityAnalysis, track); + } else { + nAKaPur++; + fillPurityTrackQA(purityAnalysis, track); + } + } else if (purityProton) { + if (track.sign() > 0) { + nPrPur++; + fillPurityTrackQA(purityAnalysis, track); + } else { + nAPrPur++; + fillPurityTrackQA(purityAnalysis, track); + } + } + } + nChRec = nPRec - nMRec; + nTRec = nPRec + nMRec; + nChPur = nPPur - nMPur; + nTPur = nPPur + nMPur; + + // ── fill reco histos ───────────────────────────────────── + hist.fill(HIST("sim/reco/sparse1"), nChRec, nPRec, nMRec, + nPrRec, nAPrRec, nKaRec, nAKaRec, nTRec, col.centFT0M()); + hist.fill(HIST("sim/reco/sparse2"), nChRec, nPRec, nMRec, + nPiRec, nAPiRec, nKaRec, nAKaRec, nTRec, col.centFT0M()); + + // ── fill purity histos ─────────────────────────────────── + hist.fill(HIST("sim/purity/sparse1"), nChPur, nPPur, nMPur, + nPrPur, nAPrPur, nKaPur, nAKaPur, nTPur, col.centFT0M()); + hist.fill(HIST("sim/purity/sparse2"), nChPur, nPPur, nMPur, + nPiPur, nAPiPur, nKaPur, nAKaPur, nTPur, col.centFT0M()); + + } // common collision loop ends + } // process sim ends + PROCESS_SWITCH(NchCumulantsId, processSim, "Process Sim: Gen + Reco + Purity", true); }; // structure ends WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx index c94a99a1670..77f8c37a625 100644 --- a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx @@ -81,8 +81,9 @@ struct NetchargeFluctuations { // CCDB related configurations 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 cfgUrlCCDB{"cfgUrlCCDB", "http://alice-ccdb.cern.ch", "url of ccdb"}; - Configurable cfgPathCCDB{"cfgPathCCDB", "Users/n/nimalik/netcharge/p/Run3/LHC24f3d", "Path for ccdb-object"}; + Configurable cfgPathCCDB{"cfgPathCCDB", "Users/n/nimalik/My/Object/pn", "Path for ccdb-object"}; Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; + Configurable cfgEffNue{"cfgEffNue", false, "efficiency correction to nu_dyn"}; // Track and event selection cuts Configurable vertexZcut{"vertexZcut", 10.f, "Vertex Z"}; @@ -123,7 +124,7 @@ struct NetchargeFluctuations { Configurable cPVcont{"cPVcont", false, "primary vertex contributor"}; // Configurable to enable multiplicity correlation cuts - O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, false, "Multiplicity correlation cut") // Struct grouping multiplicity vs centrality/vertex cuts and related parameters struct : ConfigurableGroup { @@ -164,7 +165,10 @@ struct NetchargeFluctuations { } cfgFunCoeff; // Histogram pointer for CCDB efficiency - TH1D* efficiency = nullptr; + // TH1D* efficiency = nullptr; + + TH1D* efficiencyPos = nullptr; + TH1D* efficiencyNeg = nullptr; // Filters for selecting collisions and tracks Filter collisionFilter = nabs(aod::collision::posZ) <= vertexZcut; @@ -287,8 +291,6 @@ struct NetchargeFluctuations { histogramRegistry.add("data/cent_posneg", "cent vs fpos*fneg", kTProfile, {cent1Axis}); histogramRegistry.add("data/hPt_cor", "", kTH1F, {ptAxis}); histogramRegistry.add("data/hEta_cor", "", kTH1F, {etaAxis}); - histogramRegistry.add("data/cent_nchTotal", "cent vs nchTotal", kTProfile, {cent1Axis}); - histogramRegistry.add("data/cent_nchTotalCor", "cent vs nchTotalCor", kTProfile, {cent1Axis}); histogramRegistry.add("data/nch_nchCor", "", kTProfile, {nchAxis}); histogramRegistry.add("data/nchCor", "", kTH1F, {nchAxis}); histogramRegistry.add("data/cent_nchCor", "", kTProfile, {cent1Axis}); @@ -345,6 +347,11 @@ struct NetchargeFluctuations { histogramRegistry.add("QA/hNchGlobal", "", kTH1F, {nchAxis}); histogramRegistry.add("QA/hNchPV", "", kTH1F, {nchAxis}); + histogramRegistry.add("eff/hPt_np_gen", "", kTH1F, {ptAxis}); + histogramRegistry.add("eff/hPt_nm_gen", "", kTH1F, {ptAxis}); + histogramRegistry.add("eff/hPt_np", "", kTH1F, {ptAxis}); + histogramRegistry.add("eff/hPt_nm", "", kTH1F, {ptAxis}); + // QA histograms for multiplicity correlations histogramRegistry.add("MultCorrelationPlots/globalTracks_PV_bef", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histogramRegistry.add("MultCorrelationPlots/globalTracks_FT0C_bef", "", {HistType::kTH2D, {centAxis, nchAxis}}); @@ -412,9 +419,10 @@ struct NetchargeFluctuations { ccdb->setLocalObjectValidityChecking(); TList* list = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); - efficiency = reinterpret_cast(list->FindObject("efficiency_Run3")); + efficiencyPos = reinterpret_cast(list->FindObject("efficiency_Pos_Run3")); + efficiencyNeg = reinterpret_cast(list->FindObject("efficiency_Neg_Run3")); // Log fatal error if efficiency histogram is not found - if (!efficiency) { + if (!efficiencyPos || !efficiencyNeg) { LOGF(info, "FATAL!! Could not find required histograms in CCDB"); } } @@ -549,8 +557,16 @@ struct NetchargeFluctuations { return true; } - double getEfficiency(float pt, TH1D* hEff) + double getEfficiency(float pt, int sign) { + TH1D* hEff = nullptr; + + if (sign > 0) { + hEff = efficiencyPos; + } else if (sign < 0) { + hEff = efficiencyNeg; + } + if (!hEff) { return 1e-6; } @@ -624,20 +640,22 @@ struct NetchargeFluctuations { histogramRegistry.fill(HIST("QA/hMultiplicity"), mult); int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0; - int nch = 0, nchTotal = 0; - double posWeight = 0, negWeight = 0, nchCor = 0, nchTotalCor = 0; + double fposW = 0, fnegW = 0, fposW2 = 0.0, fnegW2 = 0.0; + double posnegW = 0.0, termnW = 0.0, termpW = 0.0; + int nch = 0; + double nchCor = 0; for (const auto& track : tracks) { - double eff = getEfficiency(track.pt(), efficiency); - if (eff < threshold) - continue; - double weight = 1.0 / eff; - fillBeforeQA(track); - nchTotal += 1; - nchTotalCor += weight; if (!selTrack(track)) continue; + + double eff = getEfficiency(track.pt(), track.sign()); + if (eff < threshold) { + continue; + } + double weight = 1.0 / eff; + nch += 1; fillAfterQA(track); histogramRegistry.fill(HIST("QA/cent_hEta"), cent, track.eta()); @@ -645,28 +663,43 @@ struct NetchargeFluctuations { histogramRegistry.fill(HIST("data/hPt_cor"), track.pt(), weight); histogramRegistry.fill(HIST("data/hEta_cor"), track.eta(), weight); + if (track.sign() == 1) { + histogramRegistry.fill(HIST("eff/hPt_np"), track.pt()); + } else if (track.sign() == -1) { + histogramRegistry.fill(HIST("eff/hPt_nm"), track.pt()); + } + nchCor += weight; if (track.sign() == 1) { fpos += 1; - posWeight += weight; + fposW += weight; + fposW2 += weight * weight; } else if (track.sign() == -1) { fneg += 1; - negWeight += weight; + fnegW += weight; + fnegW2 += weight * weight; } - } // track termp = fpos * (fpos - 1); termn = fneg * (fneg - 1); posneg = fpos * fneg; - histogramRegistry.fill(HIST("data/cent_nchTotal"), cent, nchTotal); - histogramRegistry.fill(HIST("data/cent_nchTotalCor"), cent, nchTotalCor); + termpW = fposW * fposW - fposW2; + termnW = fnegW * fnegW - fnegW2; + posnegW = fposW * fnegW; + histogramRegistry.fill(HIST("data/nch_nchCor"), nch, nchCor); histogramRegistry.fill(HIST("data/nchCor"), nchCor); histogramRegistry.fill(HIST("data/cent_nchCor"), cent, nchCor); - histogramRegistry.fill(HIST("data/cent_pos_cor"), cent, posWeight); - histogramRegistry.fill(HIST("data/cent_neg_cor"), cent, negWeight); - fillHistograms(nch, cent, fpos, fneg, posneg, termp, termn); + histogramRegistry.fill(HIST("data/cent_nch"), cent, nch); + histogramRegistry.fill(HIST("data/cent_pos_cor"), cent, fposW); + histogramRegistry.fill(HIST("data/cent_neg_cor"), cent, fnegW); + + if (cfgEffNue) { + fillHistograms(nchCor, cent, fposW, fnegW, posnegW, termpW, termnW); + } else { + fillHistograms(nch, cent, fpos, fneg, posneg, termp, termn); + } } template @@ -706,8 +739,10 @@ struct NetchargeFluctuations { histogramRegistry.fill(HIST("QA/hMultiplicity"), mult); int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0; - int nch = 0, nchCor = 0; - double posRecWeight = 0, negRecWeight = 0; + double fposW = 0.0, fnegW = 0.0, fposW2 = 0.0, fnegW2 = 0.0; + double posnegW = 0.0, termnW = 0.0, termpW = 0.0; + int nch = 0; + double nchCor = 0.0; for (const auto& track : inputTracks) { fillBeforeQA(track); @@ -715,10 +750,17 @@ struct NetchargeFluctuations { continue; nch += 1; fillAfterQA(track); + + if (track.sign() == 1) { + histogramRegistry.fill(HIST("eff/hPt_np"), track.pt()); + } else if (track.sign() == -1) { + histogramRegistry.fill(HIST("eff/hPt_nm"), track.pt()); + } + histogramRegistry.fill(HIST("QA/cent_hEta"), cent, track.eta()); histogramRegistry.fill(HIST("QA/cent_hPt"), cent, track.pt()); - double eff = getEfficiency(track.pt(), efficiency); + double eff = getEfficiency(track.pt(), track.sign()); if (eff < threshold) continue; double weight = 1.0 / eff; @@ -727,23 +769,35 @@ struct NetchargeFluctuations { if (track.sign() == 1) { fpos += 1; - posRecWeight += weight; + fposW += weight; + fposW2 += weight * weight; } else if (track.sign() == -1) { fneg += 1; - negRecWeight += weight; + fnegW += weight; + fnegW2 += weight * weight; } - nchCor = posRecWeight + negRecWeight; + nchCor += weight; } // track termp = fpos * (fpos - 1); termn = fneg * (fneg - 1); posneg = fpos * fneg; + + termpW = fposW * fposW - fposW2; + termnW = fnegW * fnegW - fnegW2; + posnegW = fposW * fnegW; + histogramRegistry.fill(HIST("data/nch_nchCor"), nch, nchCor); histogramRegistry.fill(HIST("data/nchCor"), nchCor); histogramRegistry.fill(HIST("data/cent_nchCor"), cent, nchCor); - histogramRegistry.fill(HIST("data/cent_pos_cor"), cent, posRecWeight); - histogramRegistry.fill(HIST("data/cent_neg_cor"), cent, negRecWeight); + histogramRegistry.fill(HIST("data/cent_nch"), cent, nch); + histogramRegistry.fill(HIST("data/cent_pos_cor"), cent, fposW); + histogramRegistry.fill(HIST("data/cent_neg_cor"), cent, fnegW); - fillHistograms(nch, cent, fpos, fneg, posneg, termp, termn); + if (cfgEffNue) { + fillHistograms(nchCor, cent, fposW, fnegW, posnegW, termpW, termnW); + } else { + fillHistograms(nch, cent, fpos, fneg, posneg, termp, termn); + } int posGen = 0, negGen = 0, posNegGen = 0, termNGen = 0, termPGen = 0, nchGen = 0; @@ -773,8 +827,15 @@ struct NetchargeFluctuations { continue; if (std::fabs(mcpart.eta()) >= etaCut) continue; - if ((mcpart.pt() <= ptMinCut) || (mcpart.pt() >= ptMaxCut)) + if ((mcpart.pt() <= ptMinCut) || (mcpart.pt() >= ptMaxCut)) { continue; + } + if (sign == 1) { + histogramRegistry.fill(HIST("eff/hPt_np_gen"), mcpart.pt()); + } else if (sign == -1) { + histogramRegistry.fill(HIST("eff/hPt_nm_gen"), mcpart.pt()); + } + histogramRegistry.fill(HIST("gen/hPt"), mcpart.pt()); histogramRegistry.fill(HIST("gen/cent_hPt"), cent, mcpart.pt()); histogramRegistry.fill(HIST("gen/hEta"), mcpart.eta()); @@ -831,61 +892,98 @@ struct NetchargeFluctuations { return; histogramRegistry.fill(HIST("data/delta_eta_cent"), cent); - int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0, nch = 0, nchTotal = 0; - double nchCor = 0, posWeight = 0, negWeight = 0; + int fpos = 0, fneg = 0, termp = 0, termn = 0, posneg = 0; + double fposW = 0.0, fnegW = 0.0; + double fposW2 = 0.0, fnegW2 = 0.0; + double termpW = 0.0, termnW = 0.0, posnegW = 0.0; + + int nch = 0; + double nchCor = 0.0; + for (const auto& track : tracks) { - nchTotal += 1; + if (!selTrack(track)) continue; - nch += 1; - double eff = getEfficiency(track.pt(), efficiency); + + double eta = track.eta(); + if (eta < deta1 || eta > deta2) + continue; + + double eff = getEfficiency(track.pt(), track.sign()); if (eff < threshold) continue; + double weight = 1.0 / eff; + + nch += 1; nchCor += weight; - double eta = track.eta(); - if (eta < deta1 || eta > deta2) - continue; histogramRegistry.fill(HIST("data/delta_eta_eta"), eta); if (track.sign() == 1) { - fpos++; - posWeight += weight; + fpos += 1; + fposW += weight; + fposW2 += weight * weight; } else if (track.sign() == -1) { - fneg++; - negWeight += weight; + fneg += 1; + fnegW += weight; + fnegW2 += weight * weight; } } + termp = fpos * (fpos - 1); termn = fneg * (fneg - 1); posneg = fpos * fneg; + termpW = fposW * fposW - fposW2; + termnW = fnegW * fnegW - fnegW2; + posnegW = fposW * fnegW; + float deltaEtaWidth = deta2 - deta1 + 1e-5f; - histogramRegistry.fill(HIST("data/delta_eta_nchTotal"), deltaEtaWidth, nchTotal); histogramRegistry.fill(HIST("data/delta_eta_nch"), deltaEtaWidth, nch); histogramRegistry.fill(HIST("data/delta_eta_nchCor"), deltaEtaWidth, nchCor); - histogramRegistry.fill(HIST("data/delta_eta_pos"), deltaEtaWidth, fpos); - histogramRegistry.fill(HIST("data/delta_eta_pos_cor"), deltaEtaWidth, posWeight); - histogramRegistry.fill(HIST("data/delta_eta_neg"), deltaEtaWidth, fneg); - histogramRegistry.fill(HIST("data/delta_eta_neg_cor"), deltaEtaWidth, negWeight); - histogramRegistry.fill(HIST("data/delta_eta_termp"), deltaEtaWidth, termp); - histogramRegistry.fill(HIST("data/delta_eta_termn"), deltaEtaWidth, termn); - histogramRegistry.fill(HIST("data/delta_eta_pos_sq"), deltaEtaWidth, fpos * fpos); - histogramRegistry.fill(HIST("data/delta_eta_neg_sq"), deltaEtaWidth, fneg * fneg); - histogramRegistry.fill(HIST("data/delta_eta_posneg"), deltaEtaWidth, posneg); - + histogramRegistry.fill(HIST("data/delta_eta_pos_cor"), deltaEtaWidth, fposW); + histogramRegistry.fill(HIST("data/delta_eta_neg_cor"), deltaEtaWidth, fnegW); + + if (cfgEffNue) { + histogramRegistry.fill(HIST("data/delta_eta_pos"), deltaEtaWidth, fposW); + histogramRegistry.fill(HIST("data/delta_eta_neg"), deltaEtaWidth, fnegW); + histogramRegistry.fill(HIST("data/delta_eta_termp"), deltaEtaWidth, termpW); + histogramRegistry.fill(HIST("data/delta_eta_termn"), deltaEtaWidth, termnW); + histogramRegistry.fill(HIST("data/delta_eta_pos_sq"), deltaEtaWidth, fposW * fposW); + histogramRegistry.fill(HIST("data/delta_eta_neg_sq"), deltaEtaWidth, fnegW * fnegW); + histogramRegistry.fill(HIST("data/delta_eta_posneg"), deltaEtaWidth, posnegW); + } else { + + histogramRegistry.fill(HIST("data/delta_eta_pos"), deltaEtaWidth, fpos); + histogramRegistry.fill(HIST("data/delta_eta_neg"), deltaEtaWidth, fneg); + histogramRegistry.fill(HIST("data/delta_eta_termp"), deltaEtaWidth, termp); + histogramRegistry.fill(HIST("data/delta_eta_termn"), deltaEtaWidth, termn); + histogramRegistry.fill(HIST("data/delta_eta_pos_sq"), deltaEtaWidth, fpos * fpos); + histogramRegistry.fill(HIST("data/delta_eta_neg_sq"), deltaEtaWidth, fneg * fneg); + histogramRegistry.fill(HIST("data/delta_eta_posneg"), deltaEtaWidth, posneg); + } float lRandom = fRndm->Rndm(); int sampleIndex = static_cast(cfgNSubsample * lRandom); - histogramRegistry.fill(HIST("subsample/delta_eta/pos"), deltaEtaWidth, sampleIndex, fpos); - histogramRegistry.fill(HIST("subsample/delta_eta/neg"), deltaEtaWidth, sampleIndex, fneg); - histogramRegistry.fill(HIST("subsample/delta_eta/termp"), deltaEtaWidth, sampleIndex, termp); - histogramRegistry.fill(HIST("subsample/delta_eta/termn"), deltaEtaWidth, sampleIndex, termn); - histogramRegistry.fill(HIST("subsample/delta_eta/pos_sq"), deltaEtaWidth, sampleIndex, fpos * fpos); - histogramRegistry.fill(HIST("subsample/delta_eta/neg_sq"), deltaEtaWidth, sampleIndex, fneg * fneg); - histogramRegistry.fill(HIST("subsample/delta_eta/posneg"), deltaEtaWidth, sampleIndex, posneg); + if (cfgEffNue) { + histogramRegistry.fill(HIST("subsample/delta_eta/pos"), deltaEtaWidth, sampleIndex, fposW); + histogramRegistry.fill(HIST("subsample/delta_eta/neg"), deltaEtaWidth, sampleIndex, fnegW); + histogramRegistry.fill(HIST("subsample/delta_eta/termp"), deltaEtaWidth, sampleIndex, termpW); + histogramRegistry.fill(HIST("subsample/delta_eta/termn"), deltaEtaWidth, sampleIndex, termnW); + histogramRegistry.fill(HIST("subsample/delta_eta/pos_sq"), deltaEtaWidth, sampleIndex, fposW * fposW); + histogramRegistry.fill(HIST("subsample/delta_eta/neg_sq"), deltaEtaWidth, sampleIndex, fnegW * fnegW); + histogramRegistry.fill(HIST("subsample/delta_eta/posneg"), deltaEtaWidth, sampleIndex, posnegW); + } else { + histogramRegistry.fill(HIST("subsample/delta_eta/pos"), deltaEtaWidth, sampleIndex, fpos); + histogramRegistry.fill(HIST("subsample/delta_eta/neg"), deltaEtaWidth, sampleIndex, fneg); + histogramRegistry.fill(HIST("subsample/delta_eta/termp"), deltaEtaWidth, sampleIndex, termp); + histogramRegistry.fill(HIST("subsample/delta_eta/termn"), deltaEtaWidth, sampleIndex, termn); + histogramRegistry.fill(HIST("subsample/delta_eta/pos_sq"), deltaEtaWidth, sampleIndex, fpos * fpos); + histogramRegistry.fill(HIST("subsample/delta_eta/neg_sq"), deltaEtaWidth, sampleIndex, fneg * fneg); + histogramRegistry.fill(HIST("subsample/delta_eta/posneg"), deltaEtaWidth, sampleIndex, posneg); + } } template @@ -912,11 +1010,12 @@ struct NetchargeFluctuations { float deltaEtaWidth = deta2 - deta1 + 1e-5f; int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0; - int nch = 0, nchTotal = 0; - double nchCor = 0, posRecWeight = 0, negRecWeight = 0; + int nch = 0; + double fposW = 0.0, fnegW = 0.0; + double fposW2 = 0.0, fnegW2 = 0.0; + double nchCor = 0.0, termpW = 0.0, termnW = 0.0, posnegW = 0.0; for (const auto& track : inputTracks) { - nchTotal += 1; if (!selTrack(track)) continue; double eta = track.eta(); @@ -924,7 +1023,7 @@ struct NetchargeFluctuations { continue; histogramRegistry.fill(HIST("data/delta_eta_eta"), eta); - double eff = getEfficiency(track.pt(), efficiency); + double eff = getEfficiency(track.pt(), track.sign()); if (eff < threshold) continue; double weight = 1.0 / eff; @@ -932,10 +1031,12 @@ struct NetchargeFluctuations { nchCor += weight; if (track.sign() == 1) { fpos += 1; - posRecWeight += weight; + fposW += weight; + fposW2 += weight * weight; } else if (track.sign() == -1) { fneg += 1; - negRecWeight += weight; + fnegW += weight; + fnegW2 += weight * weight; } } // tracks @@ -943,18 +1044,33 @@ struct NetchargeFluctuations { termn = fneg * (fneg - 1); posneg = fpos * fneg; - histogramRegistry.fill(HIST("data/delta_eta_nchTotal"), deltaEtaWidth, nchTotal); + termpW = fposW * fposW - fposW2; + termnW = fnegW * fnegW - fnegW2; + posnegW = fposW * fnegW; + histogramRegistry.fill(HIST("data/delta_eta_nch"), deltaEtaWidth, nch); histogramRegistry.fill(HIST("data/delta_eta_nchCor"), deltaEtaWidth, nchCor); - histogramRegistry.fill(HIST("data/delta_eta_pos"), deltaEtaWidth, fpos); - histogramRegistry.fill(HIST("data/delta_eta_pos_cor"), deltaEtaWidth, posRecWeight); - histogramRegistry.fill(HIST("data/delta_eta_neg"), deltaEtaWidth, fneg); - histogramRegistry.fill(HIST("data/delta_eta_neg_cor"), deltaEtaWidth, negRecWeight); - histogramRegistry.fill(HIST("data/delta_eta_termp"), deltaEtaWidth, termp); - histogramRegistry.fill(HIST("data/delta_eta_termn"), deltaEtaWidth, termn); - histogramRegistry.fill(HIST("data/delta_eta_pos_sq"), deltaEtaWidth, fpos * fpos); - histogramRegistry.fill(HIST("data/delta_eta_neg_sq"), deltaEtaWidth, fneg * fneg); - histogramRegistry.fill(HIST("data/delta_eta_posneg"), deltaEtaWidth, posneg); + histogramRegistry.fill(HIST("data/delta_eta_pos_cor"), deltaEtaWidth, fposW); + histogramRegistry.fill(HIST("data/delta_eta_neg_cor"), deltaEtaWidth, fnegW); + + if (cfgEffNue) { + histogramRegistry.fill(HIST("data/delta_eta_pos"), deltaEtaWidth, fposW); + histogramRegistry.fill(HIST("data/delta_eta_neg"), deltaEtaWidth, fnegW); + histogramRegistry.fill(HIST("data/delta_eta_termp"), deltaEtaWidth, termpW); + histogramRegistry.fill(HIST("data/delta_eta_termn"), deltaEtaWidth, termnW); + histogramRegistry.fill(HIST("data/delta_eta_pos_sq"), deltaEtaWidth, fposW * fposW); + histogramRegistry.fill(HIST("data/delta_eta_neg_sq"), deltaEtaWidth, fnegW * fnegW); + histogramRegistry.fill(HIST("data/delta_eta_posneg"), deltaEtaWidth, posnegW); + } else { + + histogramRegistry.fill(HIST("data/delta_eta_pos"), deltaEtaWidth, fpos); + histogramRegistry.fill(HIST("data/delta_eta_neg"), deltaEtaWidth, fneg); + histogramRegistry.fill(HIST("data/delta_eta_termp"), deltaEtaWidth, termp); + histogramRegistry.fill(HIST("data/delta_eta_termn"), deltaEtaWidth, termn); + histogramRegistry.fill(HIST("data/delta_eta_pos_sq"), deltaEtaWidth, fpos * fpos); + histogramRegistry.fill(HIST("data/delta_eta_neg_sq"), deltaEtaWidth, fneg * fneg); + histogramRegistry.fill(HIST("data/delta_eta_posneg"), deltaEtaWidth, posneg); + } const auto& mccolgen = coll.template mcCollision_as(); @@ -1058,7 +1174,7 @@ struct NetchargeFluctuations { } } - PROCESS_SWITCH(NetchargeFluctuations, processDataRun2, "Process for Run2 DATA", true); + PROCESS_SWITCH(NetchargeFluctuations, processDataRun2, "Process for Run2 DATA", false); // process function for MC Run3 @@ -1072,7 +1188,7 @@ struct NetchargeFluctuations { calculationMcDeltaEta(coll, inputTracks, mcCollisions, mcParticles, etaMin, etaMax); } } - PROCESS_SWITCH(NetchargeFluctuations, processMcRun3, "Process reconstructed", false); + PROCESS_SWITCH(NetchargeFluctuations, processMcRun3, "Process reconstructed", true); // process function for MC Run2 diff --git a/PWGCF/EbyEFluctuations/Tasks/netprotcumulants.cxx b/PWGCF/EbyEFluctuations/Tasks/netprotcumulants.cxx new file mode 100644 index 00000000000..66eadcf5369 --- /dev/null +++ b/PWGCF/EbyEFluctuations/Tasks/netprotcumulants.cxx @@ -0,0 +1,2988 @@ +// 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 NetProtCumulants.cxx +/// \brief Task for analyzing efficiency of proton, and net-proton distributions in MC reconstructed and generated, and calculating net-proton cumulants +/// \author Yash Parakh + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct NetProtCumulants { + // events + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + // MC + Configurable cfgIsMC{"cfgIsMC", true, "Run MC"}; + // tracks + Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; + Configurable cfgCutPtUpper{"cfgCutPtUpper", 3.0f, "Higher pT cut"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; + Configurable cfgPIDchoice{"cfgPIDchoice", 1, "PID selection fucntion choice"}; + Configurable cfgCutPtUpperTPC{"cfgCutPtUpperTPC", 0.6f, "Upper pT cut for PID using TPC only"}; + Configurable cfgnSigmaCutTPC{"cfgnSigmaCutTPC", 2.0f, "PID nSigma cut for TPC"}; + Configurable cfgnSigmaCutTOF{"cfgnSigmaCutTOF", 2.0f, "PID nSigma cut for TOF"}; + Configurable cfgnSigmaCutCombTPCTOF{"cfgnSigmaCutCombTPCTOF", 2.0f, "PID nSigma combined cut for TPC and TOF"}; + Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; + Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable cfgITScluster{"cfgITScluster", 1, "Minimum Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 80, "Minimum Number of TPC cluster"}; + Configurable cfgTPCnCrossedRows{"cfgTPCnCrossedRows", 70, "Minimum Number of TPC crossed-rows"}; + Configurable cfgUseItsPid{"cfgUseItsPid", true, "Use ITS nSigma Cut"}; + + // Calculation of cumulants central/error + Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples for ERR"}; + Configurable cfgIsCalculateCentral{"cfgIsCalculateCentral", true, "Calculate Central value"}; + Configurable cfgIsCalculateError{"cfgIsCalculateError", false, "Calculate Error"}; + + // Efficiencies + Configurable> cfgPtBins{"cfgPtBins", {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}, "Pt Bins for Efficiency of protons"}; + Configurable> cfgProtonEff{"cfgProtonEff", {0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "Efficiency of protons"}; + Configurable> cfgAntiprotonEff{"cfgAntiprotonEff", {0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "Efficiency of anti-protons"}; + + Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency from file"}; + Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", true, "Pileup removal"}; + Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; + Configurable cfgIfRejectElectron{"cfgIfRejectElectron", true, "Remove electrons"}; + Configurable cfgIfMandatoryTOF{"cfgIfMandatoryTOF", true, "Mandatory TOF requirement to remove pileup"}; + Configurable cfgEvSelkIsVertexTOFmatched{"cfgEvSelkIsVertexTOFmatched", true, "If matched with TOF, for pileup"}; + ConfigurableAxis cfgCentralityBins{"cfgCentralityBins", {90, 0., 90.}, "Centrality/Multiplicity percentile bining"}; + + // Connect to ccdb + Service 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 ccdbUrl{"ccdbUrl", "https://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPath{"ccdbPath", "Users/s/swati/EtavsPtEfficiency_LHC24f3b_PIDchoice0", "CCDB path to ccdb object containing eff(pt, eta) in 2D hist"}; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + TRandom3* fRndm = new TRandom3(0); + + // Eff histograms 2d: eff(pT, eta) + TH2F* hRatio2DEtaVsPtProton = nullptr; + TH2F* hRatio2DEtaVsPtAntiproton = nullptr; + + // Filter command for rec (data)*********** + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtLower) && (aod::track::pt < 5.0f) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgCutTpcChi2NCl) && (aod::track::itsChi2NCl < cfgCutItsChi2NCl) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::dcaXY) < cfgCutDCAxy); + + // filtering collisions and tracks for real data*********** + using AodCollisions = soa::Filtered>; + using AodTracks = soa::Filtered>; + + // filtering collisions and tracks for MC rec data*********** + using MyMCRecCollisions = soa::Filtered>; + using MyMCRecCollision = MyMCRecCollisions::iterator; + using MyMCTracks = soa::Filtered>; + using EventCandidatesMC = soa::Join; + + // Equivalent of the AliRoot task UserCreateOutputObjects + void init(o2::framework::InitContext&) + { + // Loading efficiency histograms from ccdb + if (cfgLoadEff) { + + // Accessing eff histograms + ccdb->setURL(ccdbUrl.value); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now, will be replaced by the value of the train creation + // This avoids that users can replace objects **while** a train is running + ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + LOGF(info, "Getting object %s", ccdbPath.value.data()); + TList* lst = ccdb->getForTimeStamp(ccdbPath.value, ccdbNoLaterThan.value); + hRatio2DEtaVsPtProton = reinterpret_cast(lst->FindObject("hRatio2DEtaVsPtProton")); + hRatio2DEtaVsPtAntiproton = reinterpret_cast(lst->FindObject("hRatio2DEtaVsPtAntiproton")); + if (!hRatio2DEtaVsPtProton || !hRatio2DEtaVsPtAntiproton) + LOGF(info, "FATAL!! could not get efficiency---------> check"); + } + + // Define your axes + // Constant bin width axis + AxisSpec vtxZAxis = {100, -20, 20}; + // Variable bin width axis + std::vector ptBinning = {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}; + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + std::vector etaBinning = {-0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; + AxisSpec etaAxis = {etaBinning, "#it{#eta}"}; + // std::vector centBining = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90}; + // AxisSpec centAxis = {centBining, "Multiplicity percentile from FT0C (%)"}; + const AxisSpec centAxis{cfgCentralityBins, "Multiplicity percentile from FT0C (%)"}; + AxisSpec netprotonAxis = {41, -20.5, 20.5, "net-proton number"}; + AxisSpec protonAxis = {21, -0.5, 20.5, "proton number"}; + AxisSpec antiprotonAxis = {21, -0.5, 20.5, "antiproton number"}; + AxisSpec nSigmaAxis = {200, -5.0, 5.0, "nSigma(Proton)"}; + + auto noSubsample = static_cast(cfgNSubsample); + float maxSubsample = 1.0 * noSubsample; + AxisSpec subsampleAxis = {noSubsample, 0.0, maxSubsample, "subsample no."}; + + // For purity (data) + AxisSpec nSigmaWideAxis = {400, -10.0, 10.0, "nSigma"}; + + histos.add("h2_nSigmaTPC_p", "nSigmaTPC vs pT (proton candidates);pT; nSigmaTPC", + kTH2F, {ptAxis, nSigmaWideAxis}); + + histos.add("h2_nSigmaTPC_ap", "nSigmaTPC vs pT (antiproton candidates);pT; nSigmaTPC", + kTH2F, {ptAxis, nSigmaWideAxis}); + + histos.add("h2_nSigmaTOF_p", "nSigmaTOF vs pT (proton candidates);pT; nSigmaTOF", + kTH2F, {ptAxis, nSigmaWideAxis}); + + histos.add("h2_nSigmaTOF_ap", "nSigmaTOF vs pT (antiproton candidates);pT; nSigmaTOF", + kTH2F, {ptAxis, nSigmaWideAxis}); + + // histograms for events + histos.add("hZvtx_after", "Vertex dist. after event selection;Z (cm)", kTH1F, {vtxZAxis}); + histos.add("hCentrec", "MCRec Multiplicity percentile from FT0C (%)", kTH1F, {{100, 0.0, 100.0}}); + // tracks Rec level histograms + histos.add("hrecPtAll", "Reconstructed All particles;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecPtProton", "Reconstructed Protons;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecPtAntiproton", "Reconstructed Antiprotons;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecPhiAll", "Reconstructed All particles;#phi", kTH1F, {{100, 0., 7.}}); + histos.add("hrecPhiProton", "Reconstructed Protons;#phi", kTH1F, {{100, 0., 7.}}); + histos.add("hrecPhiAntiproton", "Reconstructed Antiprotons;#phi", kTH1F, {{100, 0., 7.}}); + histos.add("hrecEtaAll", "Reconstructed All particles;#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("hrecEtaProton", "Reconstructed Proton;#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("hrecEtaAntiproton", "Reconstructed Antiprotons;#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("hrecDcaXYAll", "Reconstructed All particles;DCA_{xy} (in cm)", kTH1F, {{400, -2.0, 2.0}}); + histos.add("hrecDcaXYProton", "Reconstructed Proton;DCA_{xy} (in cm)", kTH1F, {{400, -2.0, 2.0}}); + histos.add("hrecDcaXYAntiproton", "Reconstructed Antiprotons;DCA_{xy} (in cm)", kTH1F, {{400, -2.0, 2.0}}); + histos.add("hrecDcaZAll", "Reconstructed All particles;DCA_{z} (in cm)", kTH1F, {{400, -2.0, 2.0}}); + histos.add("hrecDcaZProton", "Reconstructed Proton;DCA_{z} (in cm)", kTH1F, {{400, -2.0, 2.0}}); + histos.add("hrecDcaZAntiproton", "Reconstructed Antiprotons;DCA_{z} (in cm)", kTH1F, {{400, -2.0, 2.0}}); + histos.add("hrecPtDistProtonVsCentrality", "Reconstructed proton number vs centrality in 2D", kTH2F, {ptAxis, centAxis}); + histos.add("hrecPtDistAntiprotonVsCentrality", "Reconstructed antiproton number vs centrality in 2D", kTH2F, {ptAxis, centAxis}); + histos.add("hrecNetProtonVsCentrality", "Reconstructed net-proton number vs centrality in 2D", kTH2F, {netprotonAxis, centAxis}); + histos.add("hrecProtonVsCentrality", "Reconstructed proton number vs centrality in 2D", kTH2F, {protonAxis, centAxis}); + histos.add("hrecAntiprotonVsCentrality", "Reconstructed antiproton number vs centrality in 2D", kTH2F, {antiprotonAxis, centAxis}); + histos.add("hrecProfileTotalProton", "Reconstructed total proton number vs. centrality", kTProfile, {centAxis}); + histos.add("hrecProfileProton", "Reconstructed proton number vs. centrality", kTProfile, {centAxis}); + histos.add("hrecProfileAntiproton", "Reconstructed antiproton number vs. centrality", kTProfile, {centAxis}); + histos.add("hCorrProfileTotalProton", "Eff. Corrected total proton number vs. centrality", kTProfile, {centAxis}); + histos.add("hCorrProfileProton", "Eff. Corrected proton number vs. centrality", kTProfile, {centAxis}); + histos.add("hCorrProfileAntiproton", "Eff. Corrected antiproton number vs. centrality", kTProfile, {centAxis}); + histos.add("hrec2DEtaVsPtProton", "2D hist of Reconstructed Proton y: eta vs. x: pT", kTH2F, {ptAxis, etaAxis}); + histos.add("hrec2DEtaVsPtAntiproton", "2D hist of Reconstructed Anti-proton y: eta vs. x: pT", kTH2F, {ptAxis, etaAxis}); + histos.add("hgen2DEtaVsPtProton", "2D hist of Generated Proton y: eta vs. x: pT", kTH2F, {ptAxis, etaAxis}); + histos.add("hgen2DEtaVsPtAntiproton", "2D hist of Generated Anti-proton y: eta vs. x: pT", kTH2F, {ptAxis, etaAxis}); + + // 2D histograms of nSigma + histos.add("h2DnsigmaTpcVsPt", "2D hist of nSigmaTPC vs. pT", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaTofVsPt", "2D hist of nSigmaTOF vs. pT", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaItsVsPt", "2D hist of nSigmaITS vs. pT", kTH2F, {ptAxis, nSigmaAxis}); + + if (cfgIsCalculateCentral) { + // uncorrected + histos.add("Prof_mu1_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu2_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu3_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu4_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu5_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu6_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu7_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_mu8_netproton", "", {HistType::kTProfile, {centAxis}}); + + // eff. corrected + histos.add("Prof_Q11_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q11_2", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q11_3", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q11_4", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q21_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q22_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q31_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q32_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q33_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q41_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q42_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q43_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q44_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q21_2", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q22_2", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2122_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2122_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2122_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3132_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3132_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3132_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3133_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3133_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3133_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3233_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3233_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q3233_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2241_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2241_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2241_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2242_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2242_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2242_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2243_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2243_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2243_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2244_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2244_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2244_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2141_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2141_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2141_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2142_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2142_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2142_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2143_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2143_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2143_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2144_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2144_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2144_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1151_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1151_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1151_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1152_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1152_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1152_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1153_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1153_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1153_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1154_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1154_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1154_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1155_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1155_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1155_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2221_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2221_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2221_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2221_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2221_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2122_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2122_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_02", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_12", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_22", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_02", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_12", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_22", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_200", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_201", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_210", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_211", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_31", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1131_30", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_31", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1132_30", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_31", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1133_30", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q11_5", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q11_6", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_30", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_31", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_40", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1121_41", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_30", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_31", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_40", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1122_41", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2211_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2211_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2211_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2211_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2211_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2111_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2111_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2111_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2111_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2111_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_001", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_010", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_100", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_011", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_101", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_110", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1141_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1141_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1141_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1141_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1141_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1142_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1142_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1142_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1142_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1142_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1143_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1143_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1143_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1143_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1143_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1144_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1144_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1144_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1144_20", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q1144_21", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2131_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2131_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2131_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2132_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2132_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2132_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2133_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2133_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2133_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2231_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2231_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2231_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2232_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2232_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2232_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2233_11", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2233_01", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q2233_10", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q51_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q52_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q53_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q54_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q55_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q21_3", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q22_3", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q31_2", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q32_2", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q33_2", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q61_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q62_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q63_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q64_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q65_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q66_1", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112122_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112131_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112132_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112133_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112231_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112232_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112233_111", "", {HistType::kTProfile, {centAxis}}); + histos.add("Prof_Q112221_111", "", {HistType::kTProfile, {centAxis}}); + } + + if (cfgIsCalculateError) { + // uncorrected + histos.add("Prof2D_mu1_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu2_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu3_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu4_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu5_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu6_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu7_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_mu8_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + + // eff. corrected + histos.add("Prof2D_Q11_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q11_2", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q11_3", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q11_4", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q21_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q22_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q31_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q32_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q33_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q41_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q42_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q43_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q44_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q21_2", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q22_2", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2122_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2122_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2122_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3132_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3132_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3132_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3133_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3133_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3133_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3233_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3233_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q3233_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2241_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2241_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2241_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2242_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2242_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2242_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2243_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2243_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2243_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2244_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2244_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2244_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2141_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2141_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2141_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2142_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2142_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2142_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2143_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2143_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2143_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2144_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2144_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2144_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1151_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1151_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1151_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1152_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1152_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1152_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1153_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1153_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1153_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1154_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1154_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1154_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1155_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1155_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1155_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2221_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2221_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2221_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2221_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2221_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2122_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2122_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_02", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_12", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_22", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_02", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_12", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_22", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_200", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_201", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_210", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_211", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_31", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1131_30", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_31", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1132_30", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_31", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1133_30", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q11_5", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q11_6", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_30", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_31", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_40", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1121_41", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_30", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_31", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_40", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1122_41", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2211_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2211_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2211_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2211_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2211_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2111_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2111_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2111_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2111_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2111_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_001", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_010", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_100", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_011", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_101", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_110", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1141_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1141_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1141_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1141_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1141_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1142_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1142_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1142_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1142_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1142_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1143_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1143_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1143_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1143_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1143_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1144_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1144_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1144_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1144_20", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q1144_21", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2131_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2131_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2131_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2132_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2132_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2132_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2133_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2133_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2133_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2231_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2231_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2231_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2232_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2232_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2232_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2233_11", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2233_01", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q2233_10", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q51_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q52_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q53_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q54_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q55_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q21_3", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q22_3", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q31_2", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q32_2", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q33_2", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q61_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q62_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q63_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q64_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q65_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q66_1", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112122_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112131_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112132_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112133_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112231_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112232_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112233_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("Prof2D_Q112221_111", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + } + + if (cfgIsMC) { + // MC event counts + histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); + histos.add("hCentgen", "MCGen Multiplicity percentile from FT0C (%)", kTH1F, {{100, 0.0, 100.0}}); + // tracks Gen level histograms + histos.add("hgenPtAll", "Generated All particles;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hgenPtProton", "Generated Protons;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hgenPtAntiproton", "Generated Antiprotons;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecPartPtAll", "Reconstructed All particles filled mcparticle pt;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecPartPtProton", "Reconstructed Protons filled mcparticle pt;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecPartPtAntiproton", "Reconstructed Antiprotons filled mcparticle pt;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hgenPhiAll", "Generated All particles;#phi", kTH1F, {{100, 0., 7.}}); + histos.add("hgenPhiProton", "Generated Protons;#phi", kTH1F, {{100, 0., 7.}}); + histos.add("hgenPhiAntiproton", "Generated Antiprotons;#phi", kTH1F, {{100, 0., 7.}}); + histos.add("hgenEtaAll", "Generated All particles;#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("hgenEtaProton", "Generated Proton;#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("hgenEtaAntiproton", "Generated Antiprotons;#eta", kTH1F, {{100, -2.01, 2.01}}); + histos.add("hgenPtDistProtonVsCentrality", "Generated proton number vs centrality in 2D", kTH2F, {ptAxis, centAxis}); + histos.add("hgenPtDistAntiprotonVsCentrality", "Generated antiproton number vs centrality in 2D", kTH2F, {ptAxis, centAxis}); + histos.add("hrecTruePtProton", "Reconstructed pdgcode verified protons;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hrecTruePtAntiproton", "Reconstructed pdgcode verified Antiprotons;#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + histos.add("hgenNetProtonVsCentrality", "Generated net-proton number vs centrality in 2D", kTH2F, {netprotonAxis, centAxis}); + histos.add("hgenProtonVsCentrality", "Generated proton number vs centrality in 2D", kTH2F, {protonAxis, centAxis}); + histos.add("hgenAntiprotonVsCentrality", "Generated antiproton number vs centrality in 2D", kTH2F, {antiprotonAxis, centAxis}); + histos.add("hgenProfileTotalProton", "Generated total proton number vs. centrality", kTProfile, {centAxis}); + histos.add("hgenProfileProton", "Generated proton number vs. centrality", kTProfile, {centAxis}); + histos.add("hgenProfileAntiproton", "Generated antiproton number vs. centrality", kTProfile, {centAxis}); + + if (cfgIsCalculateCentral) { + histos.add("GenProf_mu1_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu2_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu3_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu4_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu5_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu6_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu7_netproton", "", {HistType::kTProfile, {centAxis}}); + histos.add("GenProf_mu8_netproton", "", {HistType::kTProfile, {centAxis}}); + } + + if (cfgIsCalculateError) { + histos.add("GenProf2D_mu1_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu2_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu3_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu4_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu5_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu6_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu7_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + histos.add("GenProf2D_mu8_netproton", "", {HistType::kTProfile2D, {centAxis, subsampleAxis}}); + } + } + } // end init() + + template + bool selectionPIDold(const T& candidate) + { + if (!candidate.hasTPC()) + return false; + + //! PID checking as done in Run2 my analysis + //! ---------------------------------------------------------------------- + int flag = 0; //! pid check main flag + + if (candidate.pt() > 0.2f && candidate.pt() <= cfgCutPtUpperTPC) { + if (std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC) { + flag = 1; + } + } + if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < 5.0f) { + const float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); + const float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); + + int flag2 = 0; + if (combNSigmaPr < 3.0) + flag2 += 1; + if (combNSigmaPi < 3.0) + flag2 += 1; + if (combNSigmaKa < 3.0) + flag2 += 1; + if (!(flag2 > 1) && !(combNSigmaPr > combNSigmaPi) && !(combNSigmaPr > combNSigmaKa)) { + if (combNSigmaPr < cfgnSigmaCutCombTPCTOF) { + flag = 1; + } + } + } + if (flag == 1) + return true; + else + return false; + } + + template + bool selectionPIDoldTOFveto(const T& candidate) + { + if (!candidate.hasTPC()) + return false; + + //! PID checking as done in Run2 my analysis + //! ---------------------------------------------------------------------- + int flag = 0; //! pid check main flag + + if (candidate.pt() > 0.2f && candidate.pt() <= cfgCutPtUpperTPC) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC) { + flag = 1; + } + if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF) { + flag = 1; + } + } + if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < 5.0f) { + const float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); + const float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); + const float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); + + int flag2 = 0; + if (combNSigmaPr < 3.0) + flag2 += 1; + if (combNSigmaPi < 3.0) + flag2 += 1; + if (combNSigmaKa < 3.0) + flag2 += 1; + if (!(flag2 > 1) && !(combNSigmaPr > combNSigmaPi) && !(combNSigmaPr > combNSigmaKa)) { + if (combNSigmaPr < cfgnSigmaCutCombTPCTOF) { + flag = 1; + } + } + } + if (flag == 1) + return true; + else + return false; + } + + // electron rejection function + template + bool isElectron(const T& candidate) // Victor's BF analysis + { + if (candidate.tpcNSigmaEl() > -3.0f && candidate.tpcNSigmaEl() < 5.0f && std::abs(candidate.tpcNSigmaPi()) > 3.0f && std::abs(candidate.tpcNSigmaKa()) > 3.0f && std::abs(candidate.tpcNSigmaPr()) > 3.0f) { + return true; + } + return false; + } + + template + bool selectionPIDnew(const T& candidate) // Victor's BF analysis + { + // electron rejection + if (candidate.tpcNSigmaEl() > -3.0f && candidate.tpcNSigmaEl() < 5.0f && std::abs(candidate.tpcNSigmaPi()) > 3.0f && std::abs(candidate.tpcNSigmaKa()) > 3.0f && std::abs(candidate.tpcNSigmaPr()) > 3.0f) { + return false; + } + + //! if pt < threshold + if (candidate.pt() > 0.2f && candidate.pt() <= cfgCutPtUpperTPC) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tpcNSigmaPi()) > cfgnSigmaCutTPC && std::abs(candidate.tpcNSigmaKa()) > cfgnSigmaCutTPC) { + return true; + } + if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tpcNSigmaPi()) > cfgnSigmaCutTPC && std::abs(candidate.tpcNSigmaKa()) > cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF && std::abs(candidate.tofNSigmaPi()) > cfgnSigmaCutTOF && std::abs(candidate.tofNSigmaKa()) > cfgnSigmaCutTOF) { + return true; + } + } + + //! if pt > threshold + if (candidate.pt() > cfgCutPtUpperTPC) { + if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tpcNSigmaPi()) > cfgnSigmaCutTPC && std::abs(candidate.tpcNSigmaKa()) > cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF && std::abs(candidate.tofNSigmaPi()) > cfgnSigmaCutTOF && std::abs(candidate.tofNSigmaKa()) > cfgnSigmaCutTOF) { + return true; + } + } + return false; + } + + // Function to check which pt bin the track lies in and assign the corresponding efficiency + + template + float getEfficiency(const T& candidate) + { + // Load eff from histograms in CCDB + if (cfgLoadEff) { + if (candidate.sign() > 0) { + float effmeanval = hRatio2DEtaVsPtProton->GetBinContent(hRatio2DEtaVsPtProton->FindBin(candidate.pt(), candidate.eta())); + return effmeanval; + } + if (candidate.sign() < 0) { + float effmeanval = hRatio2DEtaVsPtAntiproton->GetBinContent(hRatio2DEtaVsPtAntiproton->FindBin(candidate.pt(), candidate.eta())); + return effmeanval; + } + return 0.0; + } else { + // Find the pt bin index based on the track's pt value + int binIndex = -1; + + for (int i = 0; i < 16; ++i) { + if (candidate.pt() >= cfgPtBins.value[i] && candidate.pt() < cfgPtBins.value[i + 1]) { + binIndex = i; + break; + } + } + // If the pt is outside the defined bins, return a default efficiency or handle it differently + if (binIndex == -1) { + return 0.0; // Default efficiency (0% if outside bins) + } + if (candidate.sign() > 0) + return cfgProtonEff.value[binIndex]; + if (candidate.sign() < 0) + return cfgAntiprotonEff.value[binIndex]; + return 0.0; + } + } + + void processMCGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) + { + histos.fill(HIST("hMC"), 0.5); + if (std::abs(mcCollision.posZ()) < cfgCutVertex) { + histos.fill(HIST("hMC"), 1.5); + } + auto cent = 0; + + int nchInel = 0; + for (const auto& mcParticle : mcParticles) { + auto pdgcode = std::abs(mcParticle.pdgCode()); + if (mcParticle.isPhysicalPrimary() && (pdgcode == PDG_t::kPiPlus || pdgcode == PDG_t::kKPlus || pdgcode == PDG_t::kProton || pdgcode == PDG_t::kElectron || pdgcode == PDG_t::kMuonMinus)) { + 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; + + for (const auto& collision : collisions) { + if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cfgCutVertex) { + continue; + } + if (cfgUseGoodITSLayerAllCut && !(collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + if (cfgEvSelkNoSameBunchPileup && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (cfgEvSelkIsVertexTOFmatched && !(collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched))) { + continue; + } + + cent = collision.centFT0C(); + + 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); + histos.fill(HIST("hCentgen"), cent); + + // creating phi, pt, eta dstribution of generted MC particles + + float nProt = 0.0; + float nAntiprot = 0.0; + + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.has_mcCollision()) + continue; + + if (mcParticle.isPhysicalPrimary()) { + if ((mcParticle.pt() > cfgCutPtLower) && (mcParticle.pt() < 5.0f) && (std::abs(mcParticle.eta()) < cfgCutEta)) { + histos.fill(HIST("hgenPtAll"), mcParticle.pt()); + histos.fill(HIST("hgenEtaAll"), mcParticle.eta()); + histos.fill(HIST("hgenPhiAll"), mcParticle.phi()); + + if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton /*&& std::abs(mcParticle.y()) < 0.5*/) { + if (mcParticle.pdgCode() == PDG_t::kProton) { + histos.fill(HIST("hgenPtProton"), mcParticle.pt()); //! hist for p gen + histos.fill(HIST("hgenPtDistProtonVsCentrality"), mcParticle.pt(), cent); + histos.fill(HIST("hgen2DEtaVsPtProton"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("hgenEtaProton"), mcParticle.eta()); + histos.fill(HIST("hgenPhiProton"), mcParticle.phi()); + if (mcParticle.pt() < cfgCutPtUpper) + nProt = nProt + 1.0; + } + if (mcParticle.pdgCode() == PDG_t::kProtonBar) { + histos.fill(HIST("hgenPtAntiproton"), mcParticle.pt()); //! hist for anti-p gen + histos.fill(HIST("hgenPtDistAntiprotonVsCentrality"), mcParticle.pt(), cent); + histos.fill(HIST("hgen2DEtaVsPtAntiproton"), mcParticle.pt(), mcParticle.eta()); + histos.fill(HIST("hgenEtaAntiproton"), mcParticle.eta()); + histos.fill(HIST("hgenPhiAntiproton"), mcParticle.phi()); + if (mcParticle.pt() < cfgCutPtUpper) + nAntiprot = nAntiprot + 1.0; + } + } + } + } + } //! end particle loop + + float netProt = nProt - nAntiprot; + histos.fill(HIST("hgenNetProtonVsCentrality"), netProt, cent); + histos.fill(HIST("hgenProtonVsCentrality"), nProt, cent); + histos.fill(HIST("hgenAntiprotonVsCentrality"), nAntiprot, cent); + histos.fill(HIST("hgenProfileTotalProton"), cent, (nProt + nAntiprot)); + histos.fill(HIST("hgenProfileProton"), cent, nProt); + histos.fill(HIST("hgenProfileAntiproton"), cent, nAntiprot); + + // Profiles for generated level cumulants + //------------------------------------------------------------------------------------------- + + if (cfgIsCalculateCentral) { + histos.get(HIST("GenProf_mu1_netproton"))->Fill(cent, std::pow(netProt, 1.0)); + histos.get(HIST("GenProf_mu2_netproton"))->Fill(cent, std::pow(netProt, 2.0)); + histos.get(HIST("GenProf_mu3_netproton"))->Fill(cent, std::pow(netProt, 3.0)); + histos.get(HIST("GenProf_mu4_netproton"))->Fill(cent, std::pow(netProt, 4.0)); + histos.get(HIST("GenProf_mu5_netproton"))->Fill(cent, std::pow(netProt, 5.0)); + histos.get(HIST("GenProf_mu6_netproton"))->Fill(cent, std::pow(netProt, 6.0)); + histos.get(HIST("GenProf_mu7_netproton"))->Fill(cent, std::pow(netProt, 7.0)); + histos.get(HIST("GenProf_mu8_netproton"))->Fill(cent, std::pow(netProt, 8.0)); + } + + if (cfgIsCalculateError) { + + float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNSubsample * lRandom); + + histos.get(HIST("GenProf2D_mu1_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 1.0)); + histos.get(HIST("GenProf2D_mu2_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 2.0)); + histos.get(HIST("GenProf2D_mu3_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 3.0)); + histos.get(HIST("GenProf2D_mu4_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 4.0)); + histos.get(HIST("GenProf2D_mu5_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 5.0)); + histos.get(HIST("GenProf2D_mu6_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 6.0)); + histos.get(HIST("GenProf2D_mu7_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 7.0)); + histos.get(HIST("GenProf2D_mu8_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 8.0)); + } + //------------------------------------------------------------------------------------------- + } + PROCESS_SWITCH(NetProtCumulants, processMCGen, "Process Generated", false); + + void processMCRec(MyMCRecCollision const& collision, MyMCTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) + { + if (!collision.has_mcCollision()) { + return; + } + + if (!collision.sel8()) { + return; + } + if (cfgUseGoodITSLayerAllCut && !(collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { + return; + } + if (cfgEvSelkNoSameBunchPileup && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + return; + } + if (cfgEvSelkIsVertexTOFmatched && !(collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched))) { + return; + ; + } + + auto cent = collision.centFT0C(); + histos.fill(HIST("hCentrec"), cent); + histos.fill(HIST("hMC"), 5.5); + histos.fill(HIST("hZvtx_after"), collision.posZ()); + + float nProt = 0.0; + float nAntiprot = 0.0; + std::array powerEffProt = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::array powerEffAntiprot = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::array fTCP0 = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::array fTCP1 = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + o2::aod::ITSResponse itsResponse; + + // Start of the Monte-Carlo reconstructed tracks + for (const auto& track : tracks) { + if (!track.has_collision()) { + continue; + } + + if (!track.has_mcParticle()) //! check if track has corresponding MC particle + { + continue; + } + if (!track.isPVContributor()) //! track check as used in data + { + continue; + } + + auto particle = track.mcParticle(); + if (!particle.has_mcCollision()) + continue; + if ((particle.pt() < cfgCutPtLower) || (particle.pt() > 5.0f) || (std::abs(particle.eta()) > cfgCutEta)) { + continue; + } + if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) { + continue; + } + + if (particle.isPhysicalPrimary()) { + histos.fill(HIST("hrecPartPtAll"), particle.pt()); + histos.fill(HIST("hrecPtAll"), track.pt()); + histos.fill(HIST("hrecEtaAll"), particle.eta()); + histos.fill(HIST("hrecPhiAll"), particle.phi()); + histos.fill(HIST("hrecDcaXYAll"), track.dcaXY()); + histos.fill(HIST("hrecDcaZAll"), track.dcaZ()); + + // rejecting electron + if (cfgIfRejectElectron && isElectron(track)) { + continue; + } + // use ITS pid as well + if (cfgUseItsPid && (std::abs(itsResponse.nSigmaITS(track)) > 3.0)) { + continue; + } + // required tracks with TOF mandatory to avoid pileup + if (cfgIfMandatoryTOF && !track.hasTOF()) { + continue; + } + + bool trackSelected = false; + if (cfgPIDchoice == 0) + trackSelected = selectionPIDoldTOFveto(track); + if (cfgPIDchoice == 1) + trackSelected = selectionPIDnew(track); + if (cfgPIDchoice == 2) + trackSelected = selectionPIDold(track); + + if (trackSelected) { + // filling nSigma distribution + histos.fill(HIST("h2DnsigmaTpcVsPt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("h2DnsigmaTofVsPt"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST("h2DnsigmaItsVsPt"), track.pt(), itsResponse.nSigmaITS(track)); + + if (track.sign() > 0) { + histos.fill(HIST("hrecPartPtProton"), particle.pt()); //! hist for p rec + histos.fill(HIST("hrecPtProton"), track.pt()); //! hist for p rec + histos.fill(HIST("hrecPtDistProtonVsCentrality"), particle.pt(), cent); + histos.fill(HIST("hrec2DEtaVsPtProton"), particle.pt(), particle.eta()); + histos.fill(HIST("hrecEtaProton"), particle.eta()); + histos.fill(HIST("hrecPhiProton"), particle.phi()); + histos.fill(HIST("hrecDcaXYProton"), track.dcaXY()); + histos.fill(HIST("hrecDcaZProton"), track.dcaZ()); + if (particle.pt() < cfgCutPtUpper) { + nProt = nProt + 1.0; + float pEff = getEfficiency(track); // get efficiency of track + if (pEff != 0) { + for (int i = 1; i < 7; i++) { + powerEffProt[i] += std::pow(1.0 / pEff, i); + } + } + } + if (particle.pdgCode() == PDG_t::kProton) { + histos.fill(HIST("hrecTruePtProton"), particle.pt()); //! hist for p purity + } + } + if (track.sign() < 0) { + histos.fill(HIST("hrecPartPtAntiproton"), particle.pt()); //! hist for anti-p rec + histos.fill(HIST("hrecPtAntiproton"), track.pt()); //! hist for anti-p rec + histos.fill(HIST("hrecPtDistAntiprotonVsCentrality"), particle.pt(), cent); + histos.fill(HIST("hrec2DEtaVsPtAntiproton"), particle.pt(), particle.eta()); + histos.fill(HIST("hrecEtaAntiproton"), particle.eta()); + histos.fill(HIST("hrecPhiAntiproton"), particle.phi()); + histos.fill(HIST("hrecDcaXYAntiproton"), track.dcaXY()); + histos.fill(HIST("hrecDcaZAntiproton"), track.dcaZ()); + if (particle.pt() < cfgCutPtUpper) { + nAntiprot = nAntiprot + 1.0; + float pEff = getEfficiency(track); // get efficiency of track + if (pEff != 0) { + for (int i = 1; i < 7; i++) { + powerEffAntiprot[i] += std::pow(1.0 / pEff, i); + } + } + } + if (particle.pdgCode() == PDG_t::kProtonBar) { + histos.fill(HIST("hrecTruePtAntiproton"), particle.pt()); //! hist for anti-p purity + } + } + } //! checking PID + } //! checking if primary + } //! end track loop + + float netProt = nProt - nAntiprot; + histos.fill(HIST("hrecNetProtonVsCentrality"), netProt, cent); + histos.fill(HIST("hrecProtonVsCentrality"), nProt, cent); + histos.fill(HIST("hrecAntiprotonVsCentrality"), nAntiprot, cent); + histos.fill(HIST("hrecProfileTotalProton"), cent, (nProt + nAntiprot)); + histos.fill(HIST("hrecProfileProton"), cent, nProt); + histos.fill(HIST("hrecProfileAntiproton"), cent, nAntiprot); + histos.fill(HIST("hCorrProfileTotalProton"), cent, (powerEffProt[1] + powerEffAntiprot[1])); + histos.fill(HIST("hCorrProfileProton"), cent, powerEffProt[1]); + histos.fill(HIST("hCorrProfileAntiproton"), cent, powerEffAntiprot[1]); + + // Calculating q_{r,s} as required + for (int i = 1; i < 7; i++) { + fTCP0[i] = powerEffProt[i] + powerEffAntiprot[i]; + fTCP1[i] = powerEffProt[i] - powerEffAntiprot[i]; + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + float fQ11_1 = fTCP1[1]; + float fQ11_2 = std::pow(fTCP1[1], 2); + float fQ11_3 = std::pow(fTCP1[1], 3); + float fQ11_4 = std::pow(fTCP1[1], 4); + float fQ11_5 = std::pow(fTCP1[1], 5); + float fQ11_6 = std::pow(fTCP1[1], 6); + + float fQ21_3 = std::pow(fTCP0[1], 3); + float fQ22_3 = std::pow(fTCP0[2], 3); + float fQ31_2 = std::pow(fTCP1[1], 2); + float fQ32_2 = std::pow(fTCP1[2], 2); + float fQ33_2 = std::pow(fTCP1[3], 2); + + float fQ61_1 = fTCP0[1]; + float fQ62_1 = fTCP0[2]; + float fQ63_1 = fTCP0[3]; + float fQ64_1 = fTCP0[4]; + float fQ65_1 = fTCP0[5]; + float fQ66_1 = fTCP0[6]; + + float fQ112122_111 = fTCP1[1] * fTCP0[1] * fTCP0[2]; + float fQ112131_111 = fTCP1[1] * fTCP0[1] * fTCP1[1]; + float fQ112132_111 = fTCP1[1] * fTCP0[1] * fTCP1[2]; + float fQ112133_111 = fTCP1[1] * fTCP0[1] * fTCP1[3]; + float fQ112231_111 = fTCP1[1] * fTCP0[2] * fTCP1[1]; + float fQ112232_111 = fTCP1[1] * fTCP0[2] * fTCP1[2]; + float fQ112233_111 = fTCP1[1] * fTCP0[2] * fTCP1[3]; + float fQ112221_111 = fTCP1[1] * fTCP0[2] * fTCP0[1]; + + float fQ21_1 = fTCP0[1]; + float fQ22_1 = fTCP0[2]; + float fQ31_1 = fTCP1[1]; + float fQ32_1 = fTCP1[2]; + float fQ33_1 = fTCP1[3]; + float fQ41_1 = fTCP0[1]; + float fQ42_1 = fTCP0[2]; + float fQ43_1 = fTCP0[3]; + float fQ44_1 = fTCP0[4]; + float fQ21_2 = std::pow(fTCP0[1], 2); + float fQ22_2 = std::pow(fTCP0[2], 2); + float fQ1121_11 = fTCP1[1] * fTCP0[1]; + float fQ1121_01 = fTCP0[1]; + float fQ1121_10 = fTCP1[1]; + float fQ1121_20 = std::pow(fTCP1[1], 2); + float fQ1121_21 = std::pow(fTCP1[1], 2) * fTCP0[1]; + float fQ1122_11 = fTCP1[1] * fTCP0[2]; + float fQ1122_01 = fTCP0[2]; + float fQ1122_10 = fTCP1[1]; + float fQ1122_20 = std::pow(fTCP1[1], 2); + float fQ1122_21 = std::pow(fTCP1[1], 2) * fTCP0[2]; + float fQ1131_11 = fTCP1[1] * fTCP1[1]; + float fQ1131_01 = fTCP1[1]; + float fQ1131_10 = fTCP1[1]; + float fQ1132_11 = fTCP1[1] * fTCP1[2]; + float fQ1132_01 = fTCP1[2]; + float fQ1132_10 = fTCP1[1]; + float fQ1133_11 = fTCP1[1] * fTCP1[3]; + float fQ1133_01 = fTCP1[3]; + float fQ1133_10 = fTCP1[1]; + float fQ2122_11 = fTCP0[1] * fTCP0[2]; + float fQ2122_01 = fTCP0[2]; + float fQ2122_10 = fTCP0[1]; + + ///////////////---------------------> + float fQ3132_11 = fTCP1[1] * fTCP1[2]; + float fQ3132_01 = fTCP1[2]; + float fQ3132_10 = fTCP1[1]; + float fQ3133_11 = fTCP1[1] * fTCP1[3]; + float fQ3133_01 = fTCP1[3]; + float fQ3133_10 = fTCP1[1]; + float fQ3233_11 = fTCP1[2] * fTCP1[3]; + float fQ3233_01 = fTCP1[3]; + float fQ3233_10 = fTCP1[2]; + float fQ2241_11 = fTCP0[2] * fTCP0[1]; + float fQ2241_01 = fTCP0[1]; + float fQ2241_10 = fTCP0[2]; + float fQ2242_11 = fTCP0[2] * fTCP0[2]; + float fQ2242_01 = fTCP0[2]; + float fQ2242_10 = fTCP0[2]; + float fQ2243_11 = fTCP0[2] * fTCP0[3]; + float fQ2243_01 = fTCP0[3]; + float fQ2243_10 = fTCP0[2]; + float fQ2244_11 = fTCP0[2] * fTCP0[4]; + float fQ2244_01 = fTCP0[4]; + float fQ2244_10 = fTCP0[2]; + float fQ2141_11 = fTCP0[1] * fTCP0[1]; + float fQ2141_01 = fTCP0[1]; + float fQ2141_10 = fTCP0[1]; + float fQ2142_11 = fTCP0[1] * fTCP0[2]; + float fQ2142_01 = fTCP0[2]; + float fQ2142_10 = fTCP0[1]; + float fQ2143_11 = fTCP0[1] * fTCP0[3]; + float fQ2143_01 = fTCP0[3]; + float fQ2143_10 = fTCP0[1]; + float fQ2144_11 = fTCP0[1] * fTCP0[4]; + float fQ2144_01 = fTCP0[4]; + float fQ2144_10 = fTCP0[1]; + float fQ1151_11 = fTCP1[1] * fTCP1[1]; + float fQ1151_01 = fTCP1[1]; + float fQ1151_10 = fTCP1[1]; + float fQ1152_11 = fTCP1[1] * fTCP1[2]; + float fQ1152_01 = fTCP1[2]; + float fQ1152_10 = fTCP1[1]; + float fQ1153_11 = fTCP1[1] * fTCP1[3]; + float fQ1153_01 = fTCP1[3]; + float fQ1153_10 = fTCP1[1]; + float fQ1154_11 = fTCP1[1] * fTCP1[4]; + float fQ1154_01 = fTCP1[4]; + float fQ1154_10 = fTCP1[1]; + float fQ1155_11 = fTCP1[1] * fTCP1[5]; + float fQ1155_01 = fTCP1[5]; + float fQ1155_10 = fTCP1[1]; + + float fQ112233_001 = fTCP1[3]; + float fQ112233_010 = fTCP0[2]; + float fQ112233_100 = fTCP1[1]; + float fQ112233_011 = fTCP0[2] * fTCP1[3]; + float fQ112233_101 = fTCP1[1] * fTCP1[3]; + float fQ112233_110 = fTCP1[1] * fTCP0[2]; + float fQ112232_001 = fTCP1[2]; + float fQ112232_010 = fTCP0[2]; + float fQ112232_100 = fTCP1[1]; + float fQ112232_011 = fTCP0[2] * fTCP1[2]; + float fQ112232_101 = fTCP1[1] * fTCP1[2]; + float fQ112232_110 = fTCP1[1] * fTCP0[2]; + // + float fQ112231_001 = fTCP1[1]; + float fQ112231_010 = fTCP0[2]; + float fQ112231_100 = fTCP1[1]; + float fQ112231_011 = fTCP0[2] * fTCP1[1]; + float fQ112231_101 = fTCP1[1] * fTCP1[1]; + float fQ112231_110 = fTCP1[1] * fTCP0[2]; + float fQ112133_001 = fTCP1[3]; + float fQ112133_010 = fTCP0[1]; + float fQ112133_100 = fTCP1[1]; + float fQ112133_011 = fTCP0[1] * fTCP1[3]; + float fQ112133_101 = fTCP1[1] * fTCP1[3]; + float fQ112133_110 = fTCP1[1] * fTCP0[1]; + + float fQ112132_001 = fTCP1[2]; + float fQ112132_010 = fTCP0[1]; + float fQ112132_100 = fTCP1[1]; + float fQ112132_011 = fTCP0[1] * fTCP1[2]; + float fQ112132_101 = fTCP1[1] * fTCP1[2]; + float fQ112132_110 = fTCP1[1] * fTCP0[1]; + float fQ112131_001 = fTCP1[1]; + float fQ112131_010 = fTCP0[1]; + float fQ112131_100 = fTCP1[1]; + float fQ112131_011 = fTCP0[1] * fTCP1[1]; + float fQ112131_101 = fTCP1[1] * fTCP1[1]; + float fQ112131_110 = fTCP1[1] * fTCP0[1]; + + float fQ2221_11 = fTCP0[2] * fTCP0[1]; + float fQ2221_01 = fTCP0[1]; + float fQ2221_10 = fTCP0[2]; + float fQ2221_21 = std::pow(fTCP0[2], 2) * fTCP0[1]; + float fQ2221_20 = std::pow(fTCP0[2], 2); + + float fQ2122_21 = std::pow(fTCP0[1], 2) * fTCP0[2]; + float fQ2122_20 = std::pow(fTCP0[1], 2); + float fQ1121_02 = std::pow(fTCP0[1], 2); + float fQ1121_12 = fTCP1[1] * std::pow(fTCP0[1], 2); + float fQ1121_22 = std::pow(fTCP1[1], 2) * std::pow(fTCP0[1], 2); + float fQ1122_02 = std::pow(fTCP0[2], 2); + float fQ1122_12 = fTCP1[1] * std::pow(fTCP0[2], 2); + float fQ1122_22 = std::pow(fTCP1[1], 2) * std::pow(fTCP0[2], 2); + + float fQ112221_001 = fTCP0[1]; + float fQ112221_010 = fTCP0[2]; + float fQ112221_100 = fTCP1[1]; + float fQ112221_011 = fTCP0[2] * fTCP0[1]; + float fQ112221_101 = fTCP1[1] * fTCP0[1]; + float fQ112221_110 = fTCP1[1] * fTCP0[2]; + float fQ112221_200 = std::pow(fTCP1[1], 2); + float fQ112221_201 = std::pow(fTCP1[1], 2) * fTCP0[1]; + float fQ112221_210 = std::pow(fTCP1[1], 2) * fTCP0[2]; + float fQ112221_211 = std::pow(fTCP1[1], 2) * fTCP0[2] * fTCP0[1]; + float fQ1131_21 = std::pow(fTCP1[1], 2) * fTCP1[1]; + float fQ1131_20 = std::pow(fTCP1[1], 2); + float fQ1131_31 = std::pow(fTCP1[1], 3) * fTCP1[1]; + float fQ1131_30 = std::pow(fTCP1[1], 3); + + float fQ1132_21 = std::pow(fTCP1[1], 2) * fTCP1[2]; + float fQ1132_20 = std::pow(fTCP1[1], 2); + float fQ1132_31 = std::pow(fTCP1[1], 3) * fTCP1[2]; + float fQ1132_30 = std::pow(fTCP1[1], 3); + float fQ1133_21 = std::pow(fTCP1[1], 2) * fTCP1[3]; + float fQ1133_20 = std::pow(fTCP1[1], 2); + float fQ1133_31 = std::pow(fTCP1[1], 3) * fTCP1[3]; + float fQ1133_30 = std::pow(fTCP1[1], 3); + float fQ1121_30 = std::pow(fTCP1[1], 3); + float fQ1121_31 = std::pow(fTCP1[1], 3) * fTCP0[1]; + float fQ1121_40 = std::pow(fTCP1[1], 4); + float fQ1121_41 = std::pow(fTCP1[1], 4) * fTCP0[1]; + float fQ1122_30 = std::pow(fTCP1[1], 3); + float fQ1122_31 = std::pow(fTCP1[1], 3) * fTCP0[2]; + float fQ1122_40 = std::pow(fTCP1[1], 4); + float fQ1122_41 = std::pow(fTCP1[1], 4) * fTCP0[2]; + + float fQ2211_11 = fTCP0[2] * fTCP1[1]; + float fQ2211_01 = fTCP1[1]; + float fQ2211_10 = fTCP0[2]; + float fQ2211_20 = std::pow(fTCP0[2], 2); + float fQ2211_21 = std::pow(fTCP0[2], 2) * fTCP1[1]; + float fQ2111_11 = fTCP0[1] * fTCP1[1]; + float fQ2111_01 = fTCP1[1]; + float fQ2111_10 = fTCP0[1]; + float fQ2111_20 = std::pow(fTCP0[1], 2); + float fQ2111_21 = std::pow(fTCP0[1], 2) * fTCP1[1]; + + float fQ112122_001 = fTCP0[2]; + float fQ112122_010 = fTCP0[1]; + float fQ112122_100 = fTCP1[1]; + float fQ112122_011 = fTCP0[1] * fTCP0[2]; + float fQ112122_101 = fTCP1[1] * fTCP0[2]; + float fQ112122_110 = fTCP1[1] * fTCP0[1]; + + float fQ1141_11 = fTCP1[1] * fTCP0[1]; + float fQ1141_01 = fTCP0[1]; + float fQ1141_10 = fTCP1[1]; + float fQ1141_20 = std::pow(fTCP1[1], 2); + float fQ1141_21 = std::pow(fTCP1[1], 2) * fTCP0[1]; + float fQ1142_11 = fTCP1[1] * fTCP0[2]; + float fQ1142_01 = fTCP0[2]; + float fQ1142_10 = fTCP1[1]; + float fQ1142_20 = std::pow(fTCP1[1], 2); + float fQ1142_21 = std::pow(fTCP1[1], 2) * fTCP0[2]; + + float fQ1143_11 = fTCP1[1] * fTCP0[3]; + float fQ1143_01 = fTCP0[3]; + float fQ1143_10 = fTCP1[1]; + float fQ1143_20 = std::pow(fTCP1[1], 2); + float fQ1143_21 = std::pow(fTCP1[1], 2) * fTCP0[3]; + float fQ1144_11 = fTCP1[1] * fTCP0[4]; + float fQ1144_01 = fTCP0[4]; + float fQ1144_10 = fTCP1[1]; + float fQ1144_20 = std::pow(fTCP1[1], 2); + float fQ1144_21 = std::pow(fTCP1[1], 2) * fTCP0[4]; + float fQ2131_11 = fTCP0[1] * fTCP1[1]; + float fQ2131_01 = fTCP1[1]; + float fQ2131_10 = fTCP0[1]; + + float fQ2132_11 = fTCP0[1] * fTCP1[2]; + float fQ2132_01 = fTCP1[2]; + float fQ2132_10 = fTCP0[1]; + float fQ2133_11 = fTCP0[1] * fTCP1[3]; + float fQ2133_01 = fTCP1[3]; + float fQ2133_10 = fTCP0[1]; + float fQ2231_11 = fTCP0[2] * fTCP1[1]; + float fQ2231_01 = fTCP1[1]; + float fQ2231_10 = fTCP0[2]; + float fQ2232_11 = fTCP0[2] * fTCP1[2]; + float fQ2232_01 = fTCP1[2]; + float fQ2232_10 = fTCP0[2]; + float fQ2233_11 = fTCP0[2] * fTCP1[3]; + float fQ2233_01 = fTCP1[3]; + float fQ2233_10 = fTCP0[2]; + + float fQ51_1 = fTCP1[1]; + float fQ52_1 = fTCP1[2]; + float fQ53_1 = fTCP1[3]; + float fQ54_1 = fTCP1[4]; + float fQ55_1 = fTCP1[5]; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if (cfgIsCalculateCentral) { + + // uncorrected + histos.get(HIST("Prof_mu1_netproton"))->Fill(cent, std::pow(netProt, 1.0)); + histos.get(HIST("Prof_mu2_netproton"))->Fill(cent, std::pow(netProt, 2.0)); + histos.get(HIST("Prof_mu3_netproton"))->Fill(cent, std::pow(netProt, 3.0)); + histos.get(HIST("Prof_mu4_netproton"))->Fill(cent, std::pow(netProt, 4.0)); + histos.get(HIST("Prof_mu5_netproton"))->Fill(cent, std::pow(netProt, 5.0)); + histos.get(HIST("Prof_mu6_netproton"))->Fill(cent, std::pow(netProt, 6.0)); + histos.get(HIST("Prof_mu7_netproton"))->Fill(cent, std::pow(netProt, 7.0)); + histos.get(HIST("Prof_mu8_netproton"))->Fill(cent, std::pow(netProt, 8.0)); + + // eff. corrected + histos.get(HIST("Prof_Q11_1"))->Fill(cent, fQ11_1); + histos.get(HIST("Prof_Q11_2"))->Fill(cent, fQ11_2); + histos.get(HIST("Prof_Q11_3"))->Fill(cent, fQ11_3); + histos.get(HIST("Prof_Q11_4"))->Fill(cent, fQ11_4); + histos.get(HIST("Prof_Q21_1"))->Fill(cent, fQ21_1); + histos.get(HIST("Prof_Q22_1"))->Fill(cent, fQ22_1); + histos.get(HIST("Prof_Q31_1"))->Fill(cent, fQ31_1); + histos.get(HIST("Prof_Q32_1"))->Fill(cent, fQ32_1); + histos.get(HIST("Prof_Q33_1"))->Fill(cent, fQ33_1); + histos.get(HIST("Prof_Q41_1"))->Fill(cent, fQ41_1); + histos.get(HIST("Prof_Q42_1"))->Fill(cent, fQ42_1); + histos.get(HIST("Prof_Q43_1"))->Fill(cent, fQ43_1); + histos.get(HIST("Prof_Q44_1"))->Fill(cent, fQ44_1); + histos.get(HIST("Prof_Q21_2"))->Fill(cent, fQ21_2); + histos.get(HIST("Prof_Q22_2"))->Fill(cent, fQ22_2); + histos.get(HIST("Prof_Q1121_11"))->Fill(cent, fQ1121_11); + histos.get(HIST("Prof_Q1121_01"))->Fill(cent, fQ1121_01); + histos.get(HIST("Prof_Q1121_10"))->Fill(cent, fQ1121_10); + histos.get(HIST("Prof_Q1121_20"))->Fill(cent, fQ1121_20); + histos.get(HIST("Prof_Q1121_21"))->Fill(cent, fQ1121_21); + histos.get(HIST("Prof_Q1122_11"))->Fill(cent, fQ1122_11); + histos.get(HIST("Prof_Q1122_01"))->Fill(cent, fQ1122_01); + histos.get(HIST("Prof_Q1122_10"))->Fill(cent, fQ1122_10); + histos.get(HIST("Prof_Q1122_20"))->Fill(cent, fQ1122_20); + histos.get(HIST("Prof_Q1122_21"))->Fill(cent, fQ1122_21); + histos.get(HIST("Prof_Q1131_11"))->Fill(cent, fQ1131_11); + histos.get(HIST("Prof_Q1131_01"))->Fill(cent, fQ1131_01); + histos.get(HIST("Prof_Q1131_10"))->Fill(cent, fQ1131_10); + histos.get(HIST("Prof_Q1132_11"))->Fill(cent, fQ1132_11); + histos.get(HIST("Prof_Q1132_01"))->Fill(cent, fQ1132_01); + histos.get(HIST("Prof_Q1132_10"))->Fill(cent, fQ1132_10); + histos.get(HIST("Prof_Q1133_11"))->Fill(cent, fQ1133_11); + histos.get(HIST("Prof_Q1133_01"))->Fill(cent, fQ1133_01); + histos.get(HIST("Prof_Q1133_10"))->Fill(cent, fQ1133_10); + histos.get(HIST("Prof_Q2122_11"))->Fill(cent, fQ2122_11); + histos.get(HIST("Prof_Q2122_01"))->Fill(cent, fQ2122_01); + histos.get(HIST("Prof_Q2122_10"))->Fill(cent, fQ2122_10); + histos.get(HIST("Prof_Q3132_11"))->Fill(cent, fQ3132_11); + histos.get(HIST("Prof_Q3132_01"))->Fill(cent, fQ3132_01); + histos.get(HIST("Prof_Q3132_10"))->Fill(cent, fQ3132_10); + histos.get(HIST("Prof_Q3133_11"))->Fill(cent, fQ3133_11); + histos.get(HIST("Prof_Q3133_01"))->Fill(cent, fQ3133_01); + histos.get(HIST("Prof_Q3133_10"))->Fill(cent, fQ3133_10); + histos.get(HIST("Prof_Q3233_11"))->Fill(cent, fQ3233_11); + histos.get(HIST("Prof_Q3233_01"))->Fill(cent, fQ3233_01); + histos.get(HIST("Prof_Q3233_10"))->Fill(cent, fQ3233_10); + histos.get(HIST("Prof_Q2241_11"))->Fill(cent, fQ2241_11); + histos.get(HIST("Prof_Q2241_01"))->Fill(cent, fQ2241_01); + histos.get(HIST("Prof_Q2241_10"))->Fill(cent, fQ2241_10); + histos.get(HIST("Prof_Q2242_11"))->Fill(cent, fQ2242_11); + histos.get(HIST("Prof_Q2242_01"))->Fill(cent, fQ2242_01); + histos.get(HIST("Prof_Q2242_10"))->Fill(cent, fQ2242_10); + histos.get(HIST("Prof_Q2243_11"))->Fill(cent, fQ2243_11); + histos.get(HIST("Prof_Q2243_01"))->Fill(cent, fQ2243_01); + histos.get(HIST("Prof_Q2243_10"))->Fill(cent, fQ2243_10); + histos.get(HIST("Prof_Q2244_11"))->Fill(cent, fQ2244_11); + histos.get(HIST("Prof_Q2244_01"))->Fill(cent, fQ2244_01); + histos.get(HIST("Prof_Q2244_10"))->Fill(cent, fQ2244_10); + histos.get(HIST("Prof_Q2141_11"))->Fill(cent, fQ2141_11); + histos.get(HIST("Prof_Q2141_01"))->Fill(cent, fQ2141_01); + histos.get(HIST("Prof_Q2141_10"))->Fill(cent, fQ2141_10); + histos.get(HIST("Prof_Q2142_11"))->Fill(cent, fQ2142_11); + histos.get(HIST("Prof_Q2142_01"))->Fill(cent, fQ2142_01); + histos.get(HIST("Prof_Q2142_10"))->Fill(cent, fQ2142_10); + histos.get(HIST("Prof_Q2143_11"))->Fill(cent, fQ2143_11); + histos.get(HIST("Prof_Q2143_01"))->Fill(cent, fQ2143_01); + histos.get(HIST("Prof_Q2143_10"))->Fill(cent, fQ2143_10); + histos.get(HIST("Prof_Q2144_11"))->Fill(cent, fQ2144_11); + histos.get(HIST("Prof_Q2144_01"))->Fill(cent, fQ2144_01); + histos.get(HIST("Prof_Q2144_10"))->Fill(cent, fQ2144_10); + histos.get(HIST("Prof_Q1151_11"))->Fill(cent, fQ1151_11); + histos.get(HIST("Prof_Q1151_01"))->Fill(cent, fQ1151_01); + histos.get(HIST("Prof_Q1151_10"))->Fill(cent, fQ1151_10); + histos.get(HIST("Prof_Q1152_11"))->Fill(cent, fQ1152_11); + histos.get(HIST("Prof_Q1152_01"))->Fill(cent, fQ1152_01); + histos.get(HIST("Prof_Q1152_10"))->Fill(cent, fQ1152_10); + histos.get(HIST("Prof_Q1153_11"))->Fill(cent, fQ1153_11); + histos.get(HIST("Prof_Q1153_01"))->Fill(cent, fQ1153_01); + histos.get(HIST("Prof_Q1153_10"))->Fill(cent, fQ1153_10); + histos.get(HIST("Prof_Q1154_11"))->Fill(cent, fQ1154_11); + histos.get(HIST("Prof_Q1154_01"))->Fill(cent, fQ1154_01); + histos.get(HIST("Prof_Q1154_10"))->Fill(cent, fQ1154_10); + histos.get(HIST("Prof_Q1155_11"))->Fill(cent, fQ1155_11); + histos.get(HIST("Prof_Q1155_01"))->Fill(cent, fQ1155_01); + histos.get(HIST("Prof_Q1155_10"))->Fill(cent, fQ1155_10); + histos.get(HIST("Prof_Q112233_001"))->Fill(cent, fQ112233_001); + histos.get(HIST("Prof_Q112233_010"))->Fill(cent, fQ112233_010); + histos.get(HIST("Prof_Q112233_100"))->Fill(cent, fQ112233_100); + histos.get(HIST("Prof_Q112233_011"))->Fill(cent, fQ112233_011); + histos.get(HIST("Prof_Q112233_101"))->Fill(cent, fQ112233_101); + histos.get(HIST("Prof_Q112233_110"))->Fill(cent, fQ112233_110); + histos.get(HIST("Prof_Q112232_001"))->Fill(cent, fQ112232_001); + histos.get(HIST("Prof_Q112232_010"))->Fill(cent, fQ112232_010); + histos.get(HIST("Prof_Q112232_100"))->Fill(cent, fQ112232_100); + histos.get(HIST("Prof_Q112232_011"))->Fill(cent, fQ112232_011); + histos.get(HIST("Prof_Q112232_101"))->Fill(cent, fQ112232_101); + histos.get(HIST("Prof_Q112232_110"))->Fill(cent, fQ112232_110); + histos.get(HIST("Prof_Q112231_001"))->Fill(cent, fQ112231_001); + histos.get(HIST("Prof_Q112231_010"))->Fill(cent, fQ112231_010); + histos.get(HIST("Prof_Q112231_100"))->Fill(cent, fQ112231_100); + histos.get(HIST("Prof_Q112231_011"))->Fill(cent, fQ112231_011); + histos.get(HIST("Prof_Q112231_101"))->Fill(cent, fQ112231_101); + histos.get(HIST("Prof_Q112231_110"))->Fill(cent, fQ112231_110); + histos.get(HIST("Prof_Q112133_001"))->Fill(cent, fQ112133_001); + histos.get(HIST("Prof_Q112133_010"))->Fill(cent, fQ112133_010); + histos.get(HIST("Prof_Q112133_100"))->Fill(cent, fQ112133_100); + histos.get(HIST("Prof_Q112133_011"))->Fill(cent, fQ112133_011); + histos.get(HIST("Prof_Q112133_101"))->Fill(cent, fQ112133_101); + histos.get(HIST("Prof_Q112133_110"))->Fill(cent, fQ112133_110); + histos.get(HIST("Prof_Q112132_001"))->Fill(cent, fQ112132_001); + histos.get(HIST("Prof_Q112132_010"))->Fill(cent, fQ112132_010); + histos.get(HIST("Prof_Q112132_100"))->Fill(cent, fQ112132_100); + histos.get(HIST("Prof_Q112132_011"))->Fill(cent, fQ112132_011); + histos.get(HIST("Prof_Q112132_101"))->Fill(cent, fQ112132_101); + histos.get(HIST("Prof_Q112132_110"))->Fill(cent, fQ112132_110); + histos.get(HIST("Prof_Q112131_001"))->Fill(cent, fQ112131_001); + histos.get(HIST("Prof_Q112131_010"))->Fill(cent, fQ112131_010); + histos.get(HIST("Prof_Q112131_100"))->Fill(cent, fQ112131_100); + histos.get(HIST("Prof_Q112131_011"))->Fill(cent, fQ112131_011); + histos.get(HIST("Prof_Q112131_101"))->Fill(cent, fQ112131_101); + histos.get(HIST("Prof_Q112131_110"))->Fill(cent, fQ112131_110); + histos.get(HIST("Prof_Q2221_11"))->Fill(cent, fQ2221_11); + histos.get(HIST("Prof_Q2221_01"))->Fill(cent, fQ2221_01); + histos.get(HIST("Prof_Q2221_10"))->Fill(cent, fQ2221_10); + histos.get(HIST("Prof_Q2221_21"))->Fill(cent, fQ2221_21); + histos.get(HIST("Prof_Q2221_20"))->Fill(cent, fQ2221_20); + histos.get(HIST("Prof_Q2122_21"))->Fill(cent, fQ2122_21); + histos.get(HIST("Prof_Q2122_20"))->Fill(cent, fQ2122_20); + histos.get(HIST("Prof_Q1121_02"))->Fill(cent, fQ1121_02); + histos.get(HIST("Prof_Q1121_12"))->Fill(cent, fQ1121_12); + histos.get(HIST("Prof_Q1121_22"))->Fill(cent, fQ1121_22); + histos.get(HIST("Prof_Q1122_02"))->Fill(cent, fQ1122_02); + histos.get(HIST("Prof_Q1122_12"))->Fill(cent, fQ1122_12); + histos.get(HIST("Prof_Q1122_22"))->Fill(cent, fQ1122_22); + histos.get(HIST("Prof_Q112221_001"))->Fill(cent, fQ112221_001); + histos.get(HIST("Prof_Q112221_010"))->Fill(cent, fQ112221_010); + histos.get(HIST("Prof_Q112221_100"))->Fill(cent, fQ112221_100); + histos.get(HIST("Prof_Q112221_011"))->Fill(cent, fQ112221_011); + histos.get(HIST("Prof_Q112221_101"))->Fill(cent, fQ112221_101); + histos.get(HIST("Prof_Q112221_110"))->Fill(cent, fQ112221_110); + histos.get(HIST("Prof_Q112221_200"))->Fill(cent, fQ112221_200); + histos.get(HIST("Prof_Q112221_201"))->Fill(cent, fQ112221_201); + histos.get(HIST("Prof_Q112221_210"))->Fill(cent, fQ112221_210); + histos.get(HIST("Prof_Q112221_211"))->Fill(cent, fQ112221_211); + histos.get(HIST("Prof_Q1131_21"))->Fill(cent, fQ1131_21); + histos.get(HIST("Prof_Q1131_20"))->Fill(cent, fQ1131_20); + histos.get(HIST("Prof_Q1131_31"))->Fill(cent, fQ1131_31); + histos.get(HIST("Prof_Q1131_30"))->Fill(cent, fQ1131_30); + histos.get(HIST("Prof_Q1132_21"))->Fill(cent, fQ1132_21); + histos.get(HIST("Prof_Q1132_20"))->Fill(cent, fQ1132_20); + histos.get(HIST("Prof_Q1132_31"))->Fill(cent, fQ1132_31); + histos.get(HIST("Prof_Q1132_30"))->Fill(cent, fQ1132_30); + histos.get(HIST("Prof_Q1133_21"))->Fill(cent, fQ1133_21); + histos.get(HIST("Prof_Q1133_20"))->Fill(cent, fQ1133_20); + histos.get(HIST("Prof_Q1133_31"))->Fill(cent, fQ1133_31); + histos.get(HIST("Prof_Q1133_30"))->Fill(cent, fQ1133_30); + histos.get(HIST("Prof_Q11_5"))->Fill(cent, fQ11_5); + histos.get(HIST("Prof_Q11_6"))->Fill(cent, fQ11_6); + histos.get(HIST("Prof_Q1121_30"))->Fill(cent, fQ1121_30); + histos.get(HIST("Prof_Q1121_31"))->Fill(cent, fQ1121_31); + histos.get(HIST("Prof_Q1121_40"))->Fill(cent, fQ1121_40); + histos.get(HIST("Prof_Q1121_41"))->Fill(cent, fQ1121_41); + histos.get(HIST("Prof_Q1122_30"))->Fill(cent, fQ1122_30); + histos.get(HIST("Prof_Q1122_31"))->Fill(cent, fQ1122_31); + histos.get(HIST("Prof_Q1122_40"))->Fill(cent, fQ1122_40); + histos.get(HIST("Prof_Q1122_41"))->Fill(cent, fQ1122_41); + histos.get(HIST("Prof_Q2211_11"))->Fill(cent, fQ2211_11); + histos.get(HIST("Prof_Q2211_01"))->Fill(cent, fQ2211_01); + histos.get(HIST("Prof_Q2211_10"))->Fill(cent, fQ2211_10); + histos.get(HIST("Prof_Q2211_20"))->Fill(cent, fQ2211_20); + histos.get(HIST("Prof_Q2211_21"))->Fill(cent, fQ2211_21); + histos.get(HIST("Prof_Q2111_11"))->Fill(cent, fQ2111_11); + histos.get(HIST("Prof_Q2111_01"))->Fill(cent, fQ2111_01); + histos.get(HIST("Prof_Q2111_10"))->Fill(cent, fQ2111_10); + histos.get(HIST("Prof_Q2111_20"))->Fill(cent, fQ2111_20); + histos.get(HIST("Prof_Q2111_21"))->Fill(cent, fQ2111_21); + histos.get(HIST("Prof_Q112122_001"))->Fill(cent, fQ112122_001); + histos.get(HIST("Prof_Q112122_010"))->Fill(cent, fQ112122_010); + histos.get(HIST("Prof_Q112122_100"))->Fill(cent, fQ112122_100); + histos.get(HIST("Prof_Q112122_011"))->Fill(cent, fQ112122_011); + histos.get(HIST("Prof_Q112122_101"))->Fill(cent, fQ112122_101); + histos.get(HIST("Prof_Q112122_110"))->Fill(cent, fQ112122_110); + histos.get(HIST("Prof_Q1141_11"))->Fill(cent, fQ1141_11); + histos.get(HIST("Prof_Q1141_01"))->Fill(cent, fQ1141_01); + histos.get(HIST("Prof_Q1141_10"))->Fill(cent, fQ1141_10); + histos.get(HIST("Prof_Q1141_20"))->Fill(cent, fQ1141_20); + histos.get(HIST("Prof_Q1141_21"))->Fill(cent, fQ1141_21); + histos.get(HIST("Prof_Q1142_11"))->Fill(cent, fQ1142_11); + histos.get(HIST("Prof_Q1142_01"))->Fill(cent, fQ1142_01); + histos.get(HIST("Prof_Q1142_10"))->Fill(cent, fQ1142_10); + histos.get(HIST("Prof_Q1142_20"))->Fill(cent, fQ1142_20); + histos.get(HIST("Prof_Q1142_21"))->Fill(cent, fQ1142_21); + histos.get(HIST("Prof_Q1143_11"))->Fill(cent, fQ1143_11); + histos.get(HIST("Prof_Q1143_01"))->Fill(cent, fQ1143_01); + histos.get(HIST("Prof_Q1143_10"))->Fill(cent, fQ1143_10); + histos.get(HIST("Prof_Q1143_20"))->Fill(cent, fQ1143_20); + histos.get(HIST("Prof_Q1143_21"))->Fill(cent, fQ1143_21); + histos.get(HIST("Prof_Q1144_11"))->Fill(cent, fQ1144_11); + histos.get(HIST("Prof_Q1144_01"))->Fill(cent, fQ1144_01); + histos.get(HIST("Prof_Q1144_10"))->Fill(cent, fQ1144_10); + histos.get(HIST("Prof_Q1144_20"))->Fill(cent, fQ1144_20); + histos.get(HIST("Prof_Q1144_21"))->Fill(cent, fQ1144_21); + histos.get(HIST("Prof_Q2131_11"))->Fill(cent, fQ2131_11); + histos.get(HIST("Prof_Q2131_01"))->Fill(cent, fQ2131_01); + histos.get(HIST("Prof_Q2131_10"))->Fill(cent, fQ2131_10); + histos.get(HIST("Prof_Q2132_11"))->Fill(cent, fQ2132_11); + histos.get(HIST("Prof_Q2132_01"))->Fill(cent, fQ2132_01); + histos.get(HIST("Prof_Q2132_10"))->Fill(cent, fQ2132_10); + histos.get(HIST("Prof_Q2133_11"))->Fill(cent, fQ2133_11); + histos.get(HIST("Prof_Q2133_01"))->Fill(cent, fQ2133_01); + histos.get(HIST("Prof_Q2133_10"))->Fill(cent, fQ2133_10); + histos.get(HIST("Prof_Q2231_11"))->Fill(cent, fQ2231_11); + histos.get(HIST("Prof_Q2231_01"))->Fill(cent, fQ2231_01); + histos.get(HIST("Prof_Q2231_10"))->Fill(cent, fQ2231_10); + histos.get(HIST("Prof_Q2232_11"))->Fill(cent, fQ2232_11); + histos.get(HIST("Prof_Q2232_01"))->Fill(cent, fQ2232_01); + histos.get(HIST("Prof_Q2232_10"))->Fill(cent, fQ2232_10); + histos.get(HIST("Prof_Q2233_11"))->Fill(cent, fQ2233_11); + histos.get(HIST("Prof_Q2233_01"))->Fill(cent, fQ2233_01); + histos.get(HIST("Prof_Q2233_10"))->Fill(cent, fQ2233_10); + histos.get(HIST("Prof_Q51_1"))->Fill(cent, fQ51_1); + histos.get(HIST("Prof_Q52_1"))->Fill(cent, fQ52_1); + histos.get(HIST("Prof_Q53_1"))->Fill(cent, fQ53_1); + histos.get(HIST("Prof_Q54_1"))->Fill(cent, fQ54_1); + histos.get(HIST("Prof_Q55_1"))->Fill(cent, fQ55_1); + histos.get(HIST("Prof_Q21_3"))->Fill(cent, fQ21_3); + histos.get(HIST("Prof_Q22_3"))->Fill(cent, fQ22_3); + histos.get(HIST("Prof_Q31_2"))->Fill(cent, fQ31_2); + histos.get(HIST("Prof_Q32_2"))->Fill(cent, fQ32_2); + histos.get(HIST("Prof_Q33_2"))->Fill(cent, fQ33_2); + histos.get(HIST("Prof_Q61_1"))->Fill(cent, fQ61_1); + histos.get(HIST("Prof_Q62_1"))->Fill(cent, fQ62_1); + histos.get(HIST("Prof_Q63_1"))->Fill(cent, fQ63_1); + histos.get(HIST("Prof_Q64_1"))->Fill(cent, fQ64_1); + histos.get(HIST("Prof_Q65_1"))->Fill(cent, fQ65_1); + histos.get(HIST("Prof_Q66_1"))->Fill(cent, fQ66_1); + histos.get(HIST("Prof_Q112122_111"))->Fill(cent, fQ112122_111); + histos.get(HIST("Prof_Q112131_111"))->Fill(cent, fQ112131_111); + histos.get(HIST("Prof_Q112132_111"))->Fill(cent, fQ112132_111); + histos.get(HIST("Prof_Q112133_111"))->Fill(cent, fQ112133_111); + histos.get(HIST("Prof_Q112231_111"))->Fill(cent, fQ112231_111); + histos.get(HIST("Prof_Q112232_111"))->Fill(cent, fQ112232_111); + histos.get(HIST("Prof_Q112233_111"))->Fill(cent, fQ112233_111); + histos.get(HIST("Prof_Q112221_111"))->Fill(cent, fQ112221_111); + } + + if (cfgIsCalculateError) { + // selecting subsample and filling profiles + float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNSubsample * lRandom); + + histos.get(HIST("Prof2D_mu1_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 1.0)); + histos.get(HIST("Prof2D_mu2_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 2.0)); + histos.get(HIST("Prof2D_mu3_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 3.0)); + histos.get(HIST("Prof2D_mu4_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 4.0)); + histos.get(HIST("Prof2D_mu5_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 5.0)); + histos.get(HIST("Prof2D_mu6_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 6.0)); + histos.get(HIST("Prof2D_mu7_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 7.0)); + histos.get(HIST("Prof2D_mu8_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 8.0)); + + histos.get(HIST("Prof2D_Q11_1"))->Fill(cent, sampleIndex, fQ11_1); + histos.get(HIST("Prof2D_Q11_2"))->Fill(cent, sampleIndex, fQ11_2); + histos.get(HIST("Prof2D_Q11_3"))->Fill(cent, sampleIndex, fQ11_3); + histos.get(HIST("Prof2D_Q11_4"))->Fill(cent, sampleIndex, fQ11_4); + histos.get(HIST("Prof2D_Q21_1"))->Fill(cent, sampleIndex, fQ21_1); + histos.get(HIST("Prof2D_Q22_1"))->Fill(cent, sampleIndex, fQ22_1); + histos.get(HIST("Prof2D_Q31_1"))->Fill(cent, sampleIndex, fQ31_1); + histos.get(HIST("Prof2D_Q32_1"))->Fill(cent, sampleIndex, fQ32_1); + histos.get(HIST("Prof2D_Q33_1"))->Fill(cent, sampleIndex, fQ33_1); + histos.get(HIST("Prof2D_Q41_1"))->Fill(cent, sampleIndex, fQ41_1); + histos.get(HIST("Prof2D_Q42_1"))->Fill(cent, sampleIndex, fQ42_1); + histos.get(HIST("Prof2D_Q43_1"))->Fill(cent, sampleIndex, fQ43_1); + histos.get(HIST("Prof2D_Q44_1"))->Fill(cent, sampleIndex, fQ44_1); + histos.get(HIST("Prof2D_Q21_2"))->Fill(cent, sampleIndex, fQ21_2); + histos.get(HIST("Prof2D_Q22_2"))->Fill(cent, sampleIndex, fQ22_2); + histos.get(HIST("Prof2D_Q1121_11"))->Fill(cent, sampleIndex, fQ1121_11); + histos.get(HIST("Prof2D_Q1121_01"))->Fill(cent, sampleIndex, fQ1121_01); + histos.get(HIST("Prof2D_Q1121_10"))->Fill(cent, sampleIndex, fQ1121_10); + histos.get(HIST("Prof2D_Q1121_20"))->Fill(cent, sampleIndex, fQ1121_20); + histos.get(HIST("Prof2D_Q1121_21"))->Fill(cent, sampleIndex, fQ1121_21); + histos.get(HIST("Prof2D_Q1122_11"))->Fill(cent, sampleIndex, fQ1122_11); + histos.get(HIST("Prof2D_Q1122_01"))->Fill(cent, sampleIndex, fQ1122_01); + histos.get(HIST("Prof2D_Q1122_10"))->Fill(cent, sampleIndex, fQ1122_10); + histos.get(HIST("Prof2D_Q1122_20"))->Fill(cent, sampleIndex, fQ1122_20); + histos.get(HIST("Prof2D_Q1122_21"))->Fill(cent, sampleIndex, fQ1122_21); + histos.get(HIST("Prof2D_Q1131_11"))->Fill(cent, sampleIndex, fQ1131_11); + histos.get(HIST("Prof2D_Q1131_01"))->Fill(cent, sampleIndex, fQ1131_01); + histos.get(HIST("Prof2D_Q1131_10"))->Fill(cent, sampleIndex, fQ1131_10); + histos.get(HIST("Prof2D_Q1132_11"))->Fill(cent, sampleIndex, fQ1132_11); + histos.get(HIST("Prof2D_Q1132_01"))->Fill(cent, sampleIndex, fQ1132_01); + histos.get(HIST("Prof2D_Q1132_10"))->Fill(cent, sampleIndex, fQ1132_10); + histos.get(HIST("Prof2D_Q1133_11"))->Fill(cent, sampleIndex, fQ1133_11); + histos.get(HIST("Prof2D_Q1133_01"))->Fill(cent, sampleIndex, fQ1133_01); + histos.get(HIST("Prof2D_Q1133_10"))->Fill(cent, sampleIndex, fQ1133_10); + histos.get(HIST("Prof2D_Q2122_11"))->Fill(cent, sampleIndex, fQ2122_11); + histos.get(HIST("Prof2D_Q2122_01"))->Fill(cent, sampleIndex, fQ2122_01); + histos.get(HIST("Prof2D_Q2122_10"))->Fill(cent, sampleIndex, fQ2122_10); + histos.get(HIST("Prof2D_Q3132_11"))->Fill(cent, sampleIndex, fQ3132_11); + histos.get(HIST("Prof2D_Q3132_01"))->Fill(cent, sampleIndex, fQ3132_01); + histos.get(HIST("Prof2D_Q3132_10"))->Fill(cent, sampleIndex, fQ3132_10); + histos.get(HIST("Prof2D_Q3133_11"))->Fill(cent, sampleIndex, fQ3133_11); + histos.get(HIST("Prof2D_Q3133_01"))->Fill(cent, sampleIndex, fQ3133_01); + histos.get(HIST("Prof2D_Q3133_10"))->Fill(cent, sampleIndex, fQ3133_10); + histos.get(HIST("Prof2D_Q3233_11"))->Fill(cent, sampleIndex, fQ3233_11); + histos.get(HIST("Prof2D_Q3233_01"))->Fill(cent, sampleIndex, fQ3233_01); + histos.get(HIST("Prof2D_Q3233_10"))->Fill(cent, sampleIndex, fQ3233_10); + histos.get(HIST("Prof2D_Q2241_11"))->Fill(cent, sampleIndex, fQ2241_11); + histos.get(HIST("Prof2D_Q2241_01"))->Fill(cent, sampleIndex, fQ2241_01); + histos.get(HIST("Prof2D_Q2241_10"))->Fill(cent, sampleIndex, fQ2241_10); + histos.get(HIST("Prof2D_Q2242_11"))->Fill(cent, sampleIndex, fQ2242_11); + histos.get(HIST("Prof2D_Q2242_01"))->Fill(cent, sampleIndex, fQ2242_01); + histos.get(HIST("Prof2D_Q2242_10"))->Fill(cent, sampleIndex, fQ2242_10); + histos.get(HIST("Prof2D_Q2243_11"))->Fill(cent, sampleIndex, fQ2243_11); + histos.get(HIST("Prof2D_Q2243_01"))->Fill(cent, sampleIndex, fQ2243_01); + histos.get(HIST("Prof2D_Q2243_10"))->Fill(cent, sampleIndex, fQ2243_10); + histos.get(HIST("Prof2D_Q2244_11"))->Fill(cent, sampleIndex, fQ2244_11); + histos.get(HIST("Prof2D_Q2244_01"))->Fill(cent, sampleIndex, fQ2244_01); + histos.get(HIST("Prof2D_Q2244_10"))->Fill(cent, sampleIndex, fQ2244_10); + histos.get(HIST("Prof2D_Q2141_11"))->Fill(cent, sampleIndex, fQ2141_11); + histos.get(HIST("Prof2D_Q2141_01"))->Fill(cent, sampleIndex, fQ2141_01); + histos.get(HIST("Prof2D_Q2141_10"))->Fill(cent, sampleIndex, fQ2141_10); + histos.get(HIST("Prof2D_Q2142_11"))->Fill(cent, sampleIndex, fQ2142_11); + histos.get(HIST("Prof2D_Q2142_01"))->Fill(cent, sampleIndex, fQ2142_01); + histos.get(HIST("Prof2D_Q2142_10"))->Fill(cent, sampleIndex, fQ2142_10); + histos.get(HIST("Prof2D_Q2143_11"))->Fill(cent, sampleIndex, fQ2143_11); + histos.get(HIST("Prof2D_Q2143_01"))->Fill(cent, sampleIndex, fQ2143_01); + histos.get(HIST("Prof2D_Q2143_10"))->Fill(cent, sampleIndex, fQ2143_10); + histos.get(HIST("Prof2D_Q2144_11"))->Fill(cent, sampleIndex, fQ2144_11); + histos.get(HIST("Prof2D_Q2144_01"))->Fill(cent, sampleIndex, fQ2144_01); + histos.get(HIST("Prof2D_Q2144_10"))->Fill(cent, sampleIndex, fQ2144_10); + histos.get(HIST("Prof2D_Q1151_11"))->Fill(cent, sampleIndex, fQ1151_11); + histos.get(HIST("Prof2D_Q1151_01"))->Fill(cent, sampleIndex, fQ1151_01); + histos.get(HIST("Prof2D_Q1151_10"))->Fill(cent, sampleIndex, fQ1151_10); + histos.get(HIST("Prof2D_Q1152_11"))->Fill(cent, sampleIndex, fQ1152_11); + histos.get(HIST("Prof2D_Q1152_01"))->Fill(cent, sampleIndex, fQ1152_01); + histos.get(HIST("Prof2D_Q1152_10"))->Fill(cent, sampleIndex, fQ1152_10); + histos.get(HIST("Prof2D_Q1153_11"))->Fill(cent, sampleIndex, fQ1153_11); + histos.get(HIST("Prof2D_Q1153_01"))->Fill(cent, sampleIndex, fQ1153_01); + histos.get(HIST("Prof2D_Q1153_10"))->Fill(cent, sampleIndex, fQ1153_10); + histos.get(HIST("Prof2D_Q1154_11"))->Fill(cent, sampleIndex, fQ1154_11); + histos.get(HIST("Prof2D_Q1154_01"))->Fill(cent, sampleIndex, fQ1154_01); + histos.get(HIST("Prof2D_Q1154_10"))->Fill(cent, sampleIndex, fQ1154_10); + histos.get(HIST("Prof2D_Q1155_11"))->Fill(cent, sampleIndex, fQ1155_11); + histos.get(HIST("Prof2D_Q1155_01"))->Fill(cent, sampleIndex, fQ1155_01); + histos.get(HIST("Prof2D_Q1155_10"))->Fill(cent, sampleIndex, fQ1155_10); + histos.get(HIST("Prof2D_Q112233_001"))->Fill(cent, sampleIndex, fQ112233_001); + histos.get(HIST("Prof2D_Q112233_010"))->Fill(cent, sampleIndex, fQ112233_010); + histos.get(HIST("Prof2D_Q112233_100"))->Fill(cent, sampleIndex, fQ112233_100); + histos.get(HIST("Prof2D_Q112233_011"))->Fill(cent, sampleIndex, fQ112233_011); + histos.get(HIST("Prof2D_Q112233_101"))->Fill(cent, sampleIndex, fQ112233_101); + histos.get(HIST("Prof2D_Q112233_110"))->Fill(cent, sampleIndex, fQ112233_110); + histos.get(HIST("Prof2D_Q112232_001"))->Fill(cent, sampleIndex, fQ112232_001); + histos.get(HIST("Prof2D_Q112232_010"))->Fill(cent, sampleIndex, fQ112232_010); + histos.get(HIST("Prof2D_Q112232_100"))->Fill(cent, sampleIndex, fQ112232_100); + histos.get(HIST("Prof2D_Q112232_011"))->Fill(cent, sampleIndex, fQ112232_011); + histos.get(HIST("Prof2D_Q112232_101"))->Fill(cent, sampleIndex, fQ112232_101); + histos.get(HIST("Prof2D_Q112232_110"))->Fill(cent, sampleIndex, fQ112232_110); + histos.get(HIST("Prof2D_Q112231_001"))->Fill(cent, sampleIndex, fQ112231_001); + histos.get(HIST("Prof2D_Q112231_010"))->Fill(cent, sampleIndex, fQ112231_010); + histos.get(HIST("Prof2D_Q112231_100"))->Fill(cent, sampleIndex, fQ112231_100); + histos.get(HIST("Prof2D_Q112231_011"))->Fill(cent, sampleIndex, fQ112231_011); + histos.get(HIST("Prof2D_Q112231_101"))->Fill(cent, sampleIndex, fQ112231_101); + histos.get(HIST("Prof2D_Q112231_110"))->Fill(cent, sampleIndex, fQ112231_110); + histos.get(HIST("Prof2D_Q112133_001"))->Fill(cent, sampleIndex, fQ112133_001); + histos.get(HIST("Prof2D_Q112133_010"))->Fill(cent, sampleIndex, fQ112133_010); + histos.get(HIST("Prof2D_Q112133_100"))->Fill(cent, sampleIndex, fQ112133_100); + histos.get(HIST("Prof2D_Q112133_011"))->Fill(cent, sampleIndex, fQ112133_011); + histos.get(HIST("Prof2D_Q112133_101"))->Fill(cent, sampleIndex, fQ112133_101); + histos.get(HIST("Prof2D_Q112133_110"))->Fill(cent, sampleIndex, fQ112133_110); + histos.get(HIST("Prof2D_Q112132_001"))->Fill(cent, sampleIndex, fQ112132_001); + histos.get(HIST("Prof2D_Q112132_010"))->Fill(cent, sampleIndex, fQ112132_010); + histos.get(HIST("Prof2D_Q112132_100"))->Fill(cent, sampleIndex, fQ112132_100); + histos.get(HIST("Prof2D_Q112132_011"))->Fill(cent, sampleIndex, fQ112132_011); + histos.get(HIST("Prof2D_Q112132_101"))->Fill(cent, sampleIndex, fQ112132_101); + histos.get(HIST("Prof2D_Q112132_110"))->Fill(cent, sampleIndex, fQ112132_110); + histos.get(HIST("Prof2D_Q112131_001"))->Fill(cent, sampleIndex, fQ112131_001); + histos.get(HIST("Prof2D_Q112131_010"))->Fill(cent, sampleIndex, fQ112131_010); + histos.get(HIST("Prof2D_Q112131_100"))->Fill(cent, sampleIndex, fQ112131_100); + histos.get(HIST("Prof2D_Q112131_011"))->Fill(cent, sampleIndex, fQ112131_011); + histos.get(HIST("Prof2D_Q112131_101"))->Fill(cent, sampleIndex, fQ112131_101); + histos.get(HIST("Prof2D_Q112131_110"))->Fill(cent, sampleIndex, fQ112131_110); + histos.get(HIST("Prof2D_Q2221_11"))->Fill(cent, sampleIndex, fQ2221_11); + histos.get(HIST("Prof2D_Q2221_01"))->Fill(cent, sampleIndex, fQ2221_01); + histos.get(HIST("Prof2D_Q2221_10"))->Fill(cent, sampleIndex, fQ2221_10); + histos.get(HIST("Prof2D_Q2221_21"))->Fill(cent, sampleIndex, fQ2221_21); + histos.get(HIST("Prof2D_Q2221_20"))->Fill(cent, sampleIndex, fQ2221_20); + histos.get(HIST("Prof2D_Q2122_21"))->Fill(cent, sampleIndex, fQ2122_21); + histos.get(HIST("Prof2D_Q2122_20"))->Fill(cent, sampleIndex, fQ2122_20); + histos.get(HIST("Prof2D_Q1121_02"))->Fill(cent, sampleIndex, fQ1121_02); + histos.get(HIST("Prof2D_Q1121_12"))->Fill(cent, sampleIndex, fQ1121_12); + histos.get(HIST("Prof2D_Q1121_22"))->Fill(cent, sampleIndex, fQ1121_22); + histos.get(HIST("Prof2D_Q1122_02"))->Fill(cent, sampleIndex, fQ1122_02); + histos.get(HIST("Prof2D_Q1122_12"))->Fill(cent, sampleIndex, fQ1122_12); + histos.get(HIST("Prof2D_Q1122_22"))->Fill(cent, sampleIndex, fQ1122_22); + histos.get(HIST("Prof2D_Q112221_001"))->Fill(cent, sampleIndex, fQ112221_001); + histos.get(HIST("Prof2D_Q112221_010"))->Fill(cent, sampleIndex, fQ112221_010); + histos.get(HIST("Prof2D_Q112221_100"))->Fill(cent, sampleIndex, fQ112221_100); + histos.get(HIST("Prof2D_Q112221_011"))->Fill(cent, sampleIndex, fQ112221_011); + histos.get(HIST("Prof2D_Q112221_101"))->Fill(cent, sampleIndex, fQ112221_101); + histos.get(HIST("Prof2D_Q112221_110"))->Fill(cent, sampleIndex, fQ112221_110); + histos.get(HIST("Prof2D_Q112221_200"))->Fill(cent, sampleIndex, fQ112221_200); + histos.get(HIST("Prof2D_Q112221_201"))->Fill(cent, sampleIndex, fQ112221_201); + histos.get(HIST("Prof2D_Q112221_210"))->Fill(cent, sampleIndex, fQ112221_210); + histos.get(HIST("Prof2D_Q112221_211"))->Fill(cent, sampleIndex, fQ112221_211); + histos.get(HIST("Prof2D_Q1131_21"))->Fill(cent, sampleIndex, fQ1131_21); + histos.get(HIST("Prof2D_Q1131_20"))->Fill(cent, sampleIndex, fQ1131_20); + histos.get(HIST("Prof2D_Q1131_31"))->Fill(cent, sampleIndex, fQ1131_31); + histos.get(HIST("Prof2D_Q1131_30"))->Fill(cent, sampleIndex, fQ1131_30); + histos.get(HIST("Prof2D_Q1132_21"))->Fill(cent, sampleIndex, fQ1132_21); + histos.get(HIST("Prof2D_Q1132_20"))->Fill(cent, sampleIndex, fQ1132_20); + histos.get(HIST("Prof2D_Q1132_31"))->Fill(cent, sampleIndex, fQ1132_31); + histos.get(HIST("Prof2D_Q1132_30"))->Fill(cent, sampleIndex, fQ1132_30); + histos.get(HIST("Prof2D_Q1133_21"))->Fill(cent, sampleIndex, fQ1133_21); + histos.get(HIST("Prof2D_Q1133_20"))->Fill(cent, sampleIndex, fQ1133_20); + histos.get(HIST("Prof2D_Q1133_31"))->Fill(cent, sampleIndex, fQ1133_31); + histos.get(HIST("Prof2D_Q1133_30"))->Fill(cent, sampleIndex, fQ1133_30); + histos.get(HIST("Prof2D_Q11_5"))->Fill(cent, sampleIndex, fQ11_5); + histos.get(HIST("Prof2D_Q11_6"))->Fill(cent, sampleIndex, fQ11_6); + histos.get(HIST("Prof2D_Q1121_30"))->Fill(cent, sampleIndex, fQ1121_30); + histos.get(HIST("Prof2D_Q1121_31"))->Fill(cent, sampleIndex, fQ1121_31); + histos.get(HIST("Prof2D_Q1121_40"))->Fill(cent, sampleIndex, fQ1121_40); + histos.get(HIST("Prof2D_Q1121_41"))->Fill(cent, sampleIndex, fQ1121_41); + histos.get(HIST("Prof2D_Q1122_30"))->Fill(cent, sampleIndex, fQ1122_30); + histos.get(HIST("Prof2D_Q1122_31"))->Fill(cent, sampleIndex, fQ1122_31); + histos.get(HIST("Prof2D_Q1122_40"))->Fill(cent, sampleIndex, fQ1122_40); + histos.get(HIST("Prof2D_Q1122_41"))->Fill(cent, sampleIndex, fQ1122_41); + histos.get(HIST("Prof2D_Q2211_11"))->Fill(cent, sampleIndex, fQ2211_11); + histos.get(HIST("Prof2D_Q2211_01"))->Fill(cent, sampleIndex, fQ2211_01); + histos.get(HIST("Prof2D_Q2211_10"))->Fill(cent, sampleIndex, fQ2211_10); + histos.get(HIST("Prof2D_Q2211_20"))->Fill(cent, sampleIndex, fQ2211_20); + histos.get(HIST("Prof2D_Q2211_21"))->Fill(cent, sampleIndex, fQ2211_21); + histos.get(HIST("Prof2D_Q2111_11"))->Fill(cent, sampleIndex, fQ2111_11); + histos.get(HIST("Prof2D_Q2111_01"))->Fill(cent, sampleIndex, fQ2111_01); + histos.get(HIST("Prof2D_Q2111_10"))->Fill(cent, sampleIndex, fQ2111_10); + histos.get(HIST("Prof2D_Q2111_20"))->Fill(cent, sampleIndex, fQ2111_20); + histos.get(HIST("Prof2D_Q2111_21"))->Fill(cent, sampleIndex, fQ2111_21); + histos.get(HIST("Prof2D_Q112122_001"))->Fill(cent, sampleIndex, fQ112122_001); + histos.get(HIST("Prof2D_Q112122_010"))->Fill(cent, sampleIndex, fQ112122_010); + histos.get(HIST("Prof2D_Q112122_100"))->Fill(cent, sampleIndex, fQ112122_100); + histos.get(HIST("Prof2D_Q112122_011"))->Fill(cent, sampleIndex, fQ112122_011); + histos.get(HIST("Prof2D_Q112122_101"))->Fill(cent, sampleIndex, fQ112122_101); + histos.get(HIST("Prof2D_Q112122_110"))->Fill(cent, sampleIndex, fQ112122_110); + histos.get(HIST("Prof2D_Q1141_11"))->Fill(cent, sampleIndex, fQ1141_11); + histos.get(HIST("Prof2D_Q1141_01"))->Fill(cent, sampleIndex, fQ1141_01); + histos.get(HIST("Prof2D_Q1141_10"))->Fill(cent, sampleIndex, fQ1141_10); + histos.get(HIST("Prof2D_Q1141_20"))->Fill(cent, sampleIndex, fQ1141_20); + histos.get(HIST("Prof2D_Q1141_21"))->Fill(cent, sampleIndex, fQ1141_21); + histos.get(HIST("Prof2D_Q1142_11"))->Fill(cent, sampleIndex, fQ1142_11); + histos.get(HIST("Prof2D_Q1142_01"))->Fill(cent, sampleIndex, fQ1142_01); + histos.get(HIST("Prof2D_Q1142_10"))->Fill(cent, sampleIndex, fQ1142_10); + histos.get(HIST("Prof2D_Q1142_20"))->Fill(cent, sampleIndex, fQ1142_20); + histos.get(HIST("Prof2D_Q1142_21"))->Fill(cent, sampleIndex, fQ1142_21); + histos.get(HIST("Prof2D_Q1143_11"))->Fill(cent, sampleIndex, fQ1143_11); + histos.get(HIST("Prof2D_Q1143_01"))->Fill(cent, sampleIndex, fQ1143_01); + histos.get(HIST("Prof2D_Q1143_10"))->Fill(cent, sampleIndex, fQ1143_10); + histos.get(HIST("Prof2D_Q1143_20"))->Fill(cent, sampleIndex, fQ1143_20); + histos.get(HIST("Prof2D_Q1143_21"))->Fill(cent, sampleIndex, fQ1143_21); + histos.get(HIST("Prof2D_Q1144_11"))->Fill(cent, sampleIndex, fQ1144_11); + histos.get(HIST("Prof2D_Q1144_01"))->Fill(cent, sampleIndex, fQ1144_01); + histos.get(HIST("Prof2D_Q1144_10"))->Fill(cent, sampleIndex, fQ1144_10); + histos.get(HIST("Prof2D_Q1144_20"))->Fill(cent, sampleIndex, fQ1144_20); + histos.get(HIST("Prof2D_Q1144_21"))->Fill(cent, sampleIndex, fQ1144_21); + histos.get(HIST("Prof2D_Q2131_11"))->Fill(cent, sampleIndex, fQ2131_11); + histos.get(HIST("Prof2D_Q2131_01"))->Fill(cent, sampleIndex, fQ2131_01); + histos.get(HIST("Prof2D_Q2131_10"))->Fill(cent, sampleIndex, fQ2131_10); + histos.get(HIST("Prof2D_Q2132_11"))->Fill(cent, sampleIndex, fQ2132_11); + histos.get(HIST("Prof2D_Q2132_01"))->Fill(cent, sampleIndex, fQ2132_01); + histos.get(HIST("Prof2D_Q2132_10"))->Fill(cent, sampleIndex, fQ2132_10); + histos.get(HIST("Prof2D_Q2133_11"))->Fill(cent, sampleIndex, fQ2133_11); + histos.get(HIST("Prof2D_Q2133_01"))->Fill(cent, sampleIndex, fQ2133_01); + histos.get(HIST("Prof2D_Q2133_10"))->Fill(cent, sampleIndex, fQ2133_10); + histos.get(HIST("Prof2D_Q2231_11"))->Fill(cent, sampleIndex, fQ2231_11); + histos.get(HIST("Prof2D_Q2231_01"))->Fill(cent, sampleIndex, fQ2231_01); + histos.get(HIST("Prof2D_Q2231_10"))->Fill(cent, sampleIndex, fQ2231_10); + histos.get(HIST("Prof2D_Q2232_11"))->Fill(cent, sampleIndex, fQ2232_11); + histos.get(HIST("Prof2D_Q2232_01"))->Fill(cent, sampleIndex, fQ2232_01); + histos.get(HIST("Prof2D_Q2232_10"))->Fill(cent, sampleIndex, fQ2232_10); + histos.get(HIST("Prof2D_Q2233_11"))->Fill(cent, sampleIndex, fQ2233_11); + histos.get(HIST("Prof2D_Q2233_01"))->Fill(cent, sampleIndex, fQ2233_01); + histos.get(HIST("Prof2D_Q2233_10"))->Fill(cent, sampleIndex, fQ2233_10); + histos.get(HIST("Prof2D_Q51_1"))->Fill(cent, sampleIndex, fQ51_1); + histos.get(HIST("Prof2D_Q52_1"))->Fill(cent, sampleIndex, fQ52_1); + histos.get(HIST("Prof2D_Q53_1"))->Fill(cent, sampleIndex, fQ53_1); + histos.get(HIST("Prof2D_Q54_1"))->Fill(cent, sampleIndex, fQ54_1); + histos.get(HIST("Prof2D_Q55_1"))->Fill(cent, sampleIndex, fQ55_1); + histos.get(HIST("Prof2D_Q21_3"))->Fill(cent, sampleIndex, fQ21_3); + histos.get(HIST("Prof2D_Q22_3"))->Fill(cent, sampleIndex, fQ22_3); + histos.get(HIST("Prof2D_Q31_2"))->Fill(cent, sampleIndex, fQ31_2); + histos.get(HIST("Prof2D_Q32_2"))->Fill(cent, sampleIndex, fQ32_2); + histos.get(HIST("Prof2D_Q33_2"))->Fill(cent, sampleIndex, fQ33_2); + histos.get(HIST("Prof2D_Q61_1"))->Fill(cent, sampleIndex, fQ61_1); + histos.get(HIST("Prof2D_Q62_1"))->Fill(cent, sampleIndex, fQ62_1); + histos.get(HIST("Prof2D_Q63_1"))->Fill(cent, sampleIndex, fQ63_1); + histos.get(HIST("Prof2D_Q64_1"))->Fill(cent, sampleIndex, fQ64_1); + histos.get(HIST("Prof2D_Q65_1"))->Fill(cent, sampleIndex, fQ65_1); + histos.get(HIST("Prof2D_Q66_1"))->Fill(cent, sampleIndex, fQ66_1); + histos.get(HIST("Prof2D_Q112122_111"))->Fill(cent, sampleIndex, fQ112122_111); + histos.get(HIST("Prof2D_Q112131_111"))->Fill(cent, sampleIndex, fQ112131_111); + histos.get(HIST("Prof2D_Q112132_111"))->Fill(cent, sampleIndex, fQ112132_111); + histos.get(HIST("Prof2D_Q112133_111"))->Fill(cent, sampleIndex, fQ112133_111); + histos.get(HIST("Prof2D_Q112231_111"))->Fill(cent, sampleIndex, fQ112231_111); + histos.get(HIST("Prof2D_Q112232_111"))->Fill(cent, sampleIndex, fQ112232_111); + histos.get(HIST("Prof2D_Q112233_111"))->Fill(cent, sampleIndex, fQ112233_111); + histos.get(HIST("Prof2D_Q112221_111"))->Fill(cent, sampleIndex, fQ112221_111); + } + } + PROCESS_SWITCH(NetProtCumulants, processMCRec, "Process Generated", false); + + void processDataRec(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + { + if (!coll.sel8()) { + return; + } + if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { + return; + } + if (cfgEvSelkNoSameBunchPileup && !(coll.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; + } + + if (cfgEvSelkIsVertexTOFmatched && !(coll.selection_bit(o2::aod::evsel::kIsVertexTOFmatched))) { + return; + ; + } + + histos.fill(HIST("hZvtx_after"), coll.posZ()); + // variables + auto cent = coll.centFT0C(); + histos.fill(HIST("hCentrec"), cent); + + float nProt = 0.0; + float nAntiprot = 0.0; + std::array powerEffProt = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::array powerEffAntiprot = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::array fTCP0 = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::array fTCP1 = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + o2::aod::ITSResponse itsResponse; + + // Start of the Monte-Carlo reconstructed tracks + for (const auto& track : inputTracks) { + if (!track.has_collision()) { + continue; + } + + if (!track.isPVContributor()) //! track check as used in data + { + continue; + } + if ((track.pt() < cfgCutPtLower) || (track.pt() > 5.0f) || (std::abs(track.eta()) > cfgCutEta)) { + continue; + } + if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) { + continue; + } + // for purity calculation + float nsTPC = track.tpcNSigmaPr(); + float nsTOF = track.tofNSigmaPr(); + + if (track.sign() > 0) { + + histos.fill(HIST("h2_nSigmaTPC_p"), track.pt(), nsTPC); + + if (track.hasTOF()) { + histos.fill(HIST("h2_nSigmaTOF_p"), track.pt(), nsTOF); + } + } + + if (track.sign() < 0) { + + histos.fill(HIST("h2_nSigmaTPC_ap"), track.pt(), nsTPC); + + if (track.hasTOF()) { + histos.fill(HIST("h2_nSigmaTOF_ap"), track.pt(), nsTOF); + } + } + + histos.fill(HIST("hrecPtAll"), track.pt()); + histos.fill(HIST("hrecEtaAll"), track.eta()); + histos.fill(HIST("hrecPhiAll"), track.phi()); + histos.fill(HIST("hrecDcaXYAll"), track.dcaXY()); + histos.fill(HIST("hrecDcaZAll"), track.dcaZ()); + + // rejecting electron + if (cfgIfRejectElectron && isElectron(track)) { + continue; + } + // use ITS pid as well + if (cfgUseItsPid && (std::abs(itsResponse.nSigmaITS(track)) > 3.0)) { + continue; + } + // required tracks with TOF mandatory to avoid pileup + if (cfgIfMandatoryTOF && !track.hasTOF()) { + continue; + } + + bool trackSelected = false; + if (cfgPIDchoice == 0) + trackSelected = selectionPIDoldTOFveto(track); + if (cfgPIDchoice == 1) + trackSelected = selectionPIDnew(track); + if (cfgPIDchoice == 2) + trackSelected = selectionPIDold(track); + + if (trackSelected) { + + // filling nSigma distribution + histos.fill(HIST("h2DnsigmaTpcVsPt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("h2DnsigmaTofVsPt"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST("h2DnsigmaItsVsPt"), track.pt(), itsResponse.nSigmaITS(track)); + + // for protons + if (track.sign() > 0) { + histos.fill(HIST("hrecPtProton"), track.pt()); //! hist for p rec + histos.fill(HIST("hrecPtDistProtonVsCentrality"), track.pt(), cent); + histos.fill(HIST("hrecEtaProton"), track.eta()); + histos.fill(HIST("hrecPhiProton"), track.phi()); + histos.fill(HIST("hrecDcaXYProton"), track.dcaXY()); + histos.fill(HIST("hrecDcaZProton"), track.dcaZ()); + + if (track.pt() < cfgCutPtUpper) { + nProt = nProt + 1.0; + float pEff = getEfficiency(track); // get efficiency of track + if (pEff != 0) { + for (int i = 1; i < 7; i++) { + powerEffProt[i] += std::pow(1.0 / pEff, i); + } + } + } + } + // for anti-protons + if (track.sign() < 0) { + histos.fill(HIST("hrecPtAntiproton"), track.pt()); //! hist for anti-p rec + histos.fill(HIST("hrecPtDistAntiprotonVsCentrality"), track.pt(), cent); + histos.fill(HIST("hrecEtaAntiproton"), track.eta()); + histos.fill(HIST("hrecPhiAntiproton"), track.phi()); + histos.fill(HIST("hrecDcaXYAntiproton"), track.dcaXY()); + histos.fill(HIST("hrecDcaZAntiproton"), track.dcaZ()); + if (track.pt() < cfgCutPtUpper) { + nAntiprot = nAntiprot + 1.0; + float pEff = getEfficiency(track); // get efficiency of track + if (pEff != 0) { + for (int i = 1; i < 7; i++) { + powerEffAntiprot[i] += std::pow(1.0 / pEff, i); + } + } + } + } + + } //! checking PID + } //! end track loop + + float netProt = nProt - nAntiprot; + histos.fill(HIST("hrecNetProtonVsCentrality"), netProt, cent); + histos.fill(HIST("hrecProtonVsCentrality"), nProt, cent); + histos.fill(HIST("hrecAntiprotonVsCentrality"), nAntiprot, cent); + histos.fill(HIST("hrecProfileTotalProton"), cent, (nProt + nAntiprot)); + histos.fill(HIST("hrecProfileProton"), cent, nProt); + histos.fill(HIST("hrecProfileAntiproton"), cent, nAntiprot); + histos.fill(HIST("hCorrProfileTotalProton"), cent, (powerEffProt[1] + powerEffAntiprot[1])); + histos.fill(HIST("hCorrProfileProton"), cent, powerEffProt[1]); + histos.fill(HIST("hCorrProfileAntiproton"), cent, powerEffAntiprot[1]); + + // Calculating q_{r,s} as required + for (int i = 1; i < 7; i++) { + fTCP0[i] = powerEffProt[i] + powerEffAntiprot[i]; + fTCP1[i] = powerEffProt[i] - powerEffAntiprot[i]; + } + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + float fQ11_1 = fTCP1[1]; + float fQ11_2 = std::pow(fTCP1[1], 2); + float fQ11_3 = std::pow(fTCP1[1], 3); + float fQ11_4 = std::pow(fTCP1[1], 4); + float fQ11_5 = std::pow(fTCP1[1], 5); + float fQ11_6 = std::pow(fTCP1[1], 6); + + float fQ21_3 = std::pow(fTCP0[1], 3); + float fQ22_3 = std::pow(fTCP0[2], 3); + float fQ31_2 = std::pow(fTCP1[1], 2); + float fQ32_2 = std::pow(fTCP1[2], 2); + float fQ33_2 = std::pow(fTCP1[3], 2); + + float fQ61_1 = fTCP0[1]; + float fQ62_1 = fTCP0[2]; + float fQ63_1 = fTCP0[3]; + float fQ64_1 = fTCP0[4]; + float fQ65_1 = fTCP0[5]; + float fQ66_1 = fTCP0[6]; + + float fQ112122_111 = fTCP1[1] * fTCP0[1] * fTCP0[2]; + float fQ112131_111 = fTCP1[1] * fTCP0[1] * fTCP1[1]; + float fQ112132_111 = fTCP1[1] * fTCP0[1] * fTCP1[2]; + float fQ112133_111 = fTCP1[1] * fTCP0[1] * fTCP1[3]; + float fQ112231_111 = fTCP1[1] * fTCP0[2] * fTCP1[1]; + float fQ112232_111 = fTCP1[1] * fTCP0[2] * fTCP1[2]; + float fQ112233_111 = fTCP1[1] * fTCP0[2] * fTCP1[3]; + float fQ112221_111 = fTCP1[1] * fTCP0[2] * fTCP0[1]; + + float fQ21_1 = fTCP0[1]; + float fQ22_1 = fTCP0[2]; + float fQ31_1 = fTCP1[1]; + float fQ32_1 = fTCP1[2]; + float fQ33_1 = fTCP1[3]; + float fQ41_1 = fTCP0[1]; + float fQ42_1 = fTCP0[2]; + float fQ43_1 = fTCP0[3]; + float fQ44_1 = fTCP0[4]; + float fQ21_2 = std::pow(fTCP0[1], 2); + float fQ22_2 = std::pow(fTCP0[2], 2); + float fQ1121_11 = fTCP1[1] * fTCP0[1]; + float fQ1121_01 = fTCP0[1]; + float fQ1121_10 = fTCP1[1]; + float fQ1121_20 = std::pow(fTCP1[1], 2); + float fQ1121_21 = std::pow(fTCP1[1], 2) * fTCP0[1]; + float fQ1122_11 = fTCP1[1] * fTCP0[2]; + float fQ1122_01 = fTCP0[2]; + float fQ1122_10 = fTCP1[1]; + float fQ1122_20 = std::pow(fTCP1[1], 2); + float fQ1122_21 = std::pow(fTCP1[1], 2) * fTCP0[2]; + float fQ1131_11 = fTCP1[1] * fTCP1[1]; + float fQ1131_01 = fTCP1[1]; + float fQ1131_10 = fTCP1[1]; + float fQ1132_11 = fTCP1[1] * fTCP1[2]; + float fQ1132_01 = fTCP1[2]; + float fQ1132_10 = fTCP1[1]; + float fQ1133_11 = fTCP1[1] * fTCP1[3]; + float fQ1133_01 = fTCP1[3]; + float fQ1133_10 = fTCP1[1]; + float fQ2122_11 = fTCP0[1] * fTCP0[2]; + float fQ2122_01 = fTCP0[2]; + float fQ2122_10 = fTCP0[1]; + + ///////////////---------------------> + float fQ3132_11 = fTCP1[1] * fTCP1[2]; + float fQ3132_01 = fTCP1[2]; + float fQ3132_10 = fTCP1[1]; + float fQ3133_11 = fTCP1[1] * fTCP1[3]; + float fQ3133_01 = fTCP1[3]; + float fQ3133_10 = fTCP1[1]; + float fQ3233_11 = fTCP1[2] * fTCP1[3]; + float fQ3233_01 = fTCP1[3]; + float fQ3233_10 = fTCP1[2]; + float fQ2241_11 = fTCP0[2] * fTCP0[1]; + float fQ2241_01 = fTCP0[1]; + float fQ2241_10 = fTCP0[2]; + float fQ2242_11 = fTCP0[2] * fTCP0[2]; + float fQ2242_01 = fTCP0[2]; + float fQ2242_10 = fTCP0[2]; + float fQ2243_11 = fTCP0[2] * fTCP0[3]; + float fQ2243_01 = fTCP0[3]; + float fQ2243_10 = fTCP0[2]; + float fQ2244_11 = fTCP0[2] * fTCP0[4]; + float fQ2244_01 = fTCP0[4]; + float fQ2244_10 = fTCP0[2]; + float fQ2141_11 = fTCP0[1] * fTCP0[1]; + float fQ2141_01 = fTCP0[1]; + float fQ2141_10 = fTCP0[1]; + float fQ2142_11 = fTCP0[1] * fTCP0[2]; + float fQ2142_01 = fTCP0[2]; + float fQ2142_10 = fTCP0[1]; + float fQ2143_11 = fTCP0[1] * fTCP0[3]; + float fQ2143_01 = fTCP0[3]; + float fQ2143_10 = fTCP0[1]; + float fQ2144_11 = fTCP0[1] * fTCP0[4]; + float fQ2144_01 = fTCP0[4]; + float fQ2144_10 = fTCP0[1]; + float fQ1151_11 = fTCP1[1] * fTCP1[1]; + float fQ1151_01 = fTCP1[1]; + float fQ1151_10 = fTCP1[1]; + float fQ1152_11 = fTCP1[1] * fTCP1[2]; + float fQ1152_01 = fTCP1[2]; + float fQ1152_10 = fTCP1[1]; + float fQ1153_11 = fTCP1[1] * fTCP1[3]; + float fQ1153_01 = fTCP1[3]; + float fQ1153_10 = fTCP1[1]; + float fQ1154_11 = fTCP1[1] * fTCP1[4]; + float fQ1154_01 = fTCP1[4]; + float fQ1154_10 = fTCP1[1]; + float fQ1155_11 = fTCP1[1] * fTCP1[5]; + float fQ1155_01 = fTCP1[5]; + float fQ1155_10 = fTCP1[1]; + + float fQ112233_001 = fTCP1[3]; + float fQ112233_010 = fTCP0[2]; + float fQ112233_100 = fTCP1[1]; + float fQ112233_011 = fTCP0[2] * fTCP1[3]; + float fQ112233_101 = fTCP1[1] * fTCP1[3]; + float fQ112233_110 = fTCP1[1] * fTCP0[2]; + float fQ112232_001 = fTCP1[2]; + float fQ112232_010 = fTCP0[2]; + float fQ112232_100 = fTCP1[1]; + float fQ112232_011 = fTCP0[2] * fTCP1[2]; + float fQ112232_101 = fTCP1[1] * fTCP1[2]; + float fQ112232_110 = fTCP1[1] * fTCP0[2]; + // + float fQ112231_001 = fTCP1[1]; + float fQ112231_010 = fTCP0[2]; + float fQ112231_100 = fTCP1[1]; + float fQ112231_011 = fTCP0[2] * fTCP1[1]; + float fQ112231_101 = fTCP1[1] * fTCP1[1]; + float fQ112231_110 = fTCP1[1] * fTCP0[2]; + float fQ112133_001 = fTCP1[3]; + float fQ112133_010 = fTCP0[1]; + float fQ112133_100 = fTCP1[1]; + float fQ112133_011 = fTCP0[1] * fTCP1[3]; + float fQ112133_101 = fTCP1[1] * fTCP1[3]; + float fQ112133_110 = fTCP1[1] * fTCP0[1]; + + float fQ112132_001 = fTCP1[2]; + float fQ112132_010 = fTCP0[1]; + float fQ112132_100 = fTCP1[1]; + float fQ112132_011 = fTCP0[1] * fTCP1[2]; + float fQ112132_101 = fTCP1[1] * fTCP1[2]; + float fQ112132_110 = fTCP1[1] * fTCP0[1]; + float fQ112131_001 = fTCP1[1]; + float fQ112131_010 = fTCP0[1]; + float fQ112131_100 = fTCP1[1]; + float fQ112131_011 = fTCP0[1] * fTCP1[1]; + float fQ112131_101 = fTCP1[1] * fTCP1[1]; + float fQ112131_110 = fTCP1[1] * fTCP0[1]; + + float fQ2221_11 = fTCP0[2] * fTCP0[1]; + float fQ2221_01 = fTCP0[1]; + float fQ2221_10 = fTCP0[2]; + float fQ2221_21 = std::pow(fTCP0[2], 2) * fTCP0[1]; + float fQ2221_20 = std::pow(fTCP0[2], 2); + + float fQ2122_21 = std::pow(fTCP0[1], 2) * fTCP0[2]; + float fQ2122_20 = std::pow(fTCP0[1], 2); + float fQ1121_02 = std::pow(fTCP0[1], 2); + float fQ1121_12 = fTCP1[1] * std::pow(fTCP0[1], 2); + float fQ1121_22 = std::pow(fTCP1[1], 2) * std::pow(fTCP0[1], 2); + float fQ1122_02 = std::pow(fTCP0[2], 2); + float fQ1122_12 = fTCP1[1] * std::pow(fTCP0[2], 2); + float fQ1122_22 = std::pow(fTCP1[1], 2) * std::pow(fTCP0[2], 2); + + float fQ112221_001 = fTCP0[1]; + float fQ112221_010 = fTCP0[2]; + float fQ112221_100 = fTCP1[1]; + float fQ112221_011 = fTCP0[2] * fTCP0[1]; + float fQ112221_101 = fTCP1[1] * fTCP0[1]; + float fQ112221_110 = fTCP1[1] * fTCP0[2]; + float fQ112221_200 = std::pow(fTCP1[1], 2); + float fQ112221_201 = std::pow(fTCP1[1], 2) * fTCP0[1]; + float fQ112221_210 = std::pow(fTCP1[1], 2) * fTCP0[2]; + float fQ112221_211 = std::pow(fTCP1[1], 2) * fTCP0[2] * fTCP0[1]; + float fQ1131_21 = std::pow(fTCP1[1], 2) * fTCP1[1]; + float fQ1131_20 = std::pow(fTCP1[1], 2); + float fQ1131_31 = std::pow(fTCP1[1], 3) * fTCP1[1]; + float fQ1131_30 = std::pow(fTCP1[1], 3); + + float fQ1132_21 = std::pow(fTCP1[1], 2) * fTCP1[2]; + float fQ1132_20 = std::pow(fTCP1[1], 2); + float fQ1132_31 = std::pow(fTCP1[1], 3) * fTCP1[2]; + float fQ1132_30 = std::pow(fTCP1[1], 3); + float fQ1133_21 = std::pow(fTCP1[1], 2) * fTCP1[3]; + float fQ1133_20 = std::pow(fTCP1[1], 2); + float fQ1133_31 = std::pow(fTCP1[1], 3) * fTCP1[3]; + float fQ1133_30 = std::pow(fTCP1[1], 3); + float fQ1121_30 = std::pow(fTCP1[1], 3); + float fQ1121_31 = std::pow(fTCP1[1], 3) * fTCP0[1]; + float fQ1121_40 = std::pow(fTCP1[1], 4); + float fQ1121_41 = std::pow(fTCP1[1], 4) * fTCP0[1]; + float fQ1122_30 = std::pow(fTCP1[1], 3); + float fQ1122_31 = std::pow(fTCP1[1], 3) * fTCP0[2]; + float fQ1122_40 = std::pow(fTCP1[1], 4); + float fQ1122_41 = std::pow(fTCP1[1], 4) * fTCP0[2]; + + float fQ2211_11 = fTCP0[2] * fTCP1[1]; + float fQ2211_01 = fTCP1[1]; + float fQ2211_10 = fTCP0[2]; + float fQ2211_20 = std::pow(fTCP0[2], 2); + float fQ2211_21 = std::pow(fTCP0[2], 2) * fTCP1[1]; + float fQ2111_11 = fTCP0[1] * fTCP1[1]; + float fQ2111_01 = fTCP1[1]; + float fQ2111_10 = fTCP0[1]; + float fQ2111_20 = std::pow(fTCP0[1], 2); + float fQ2111_21 = std::pow(fTCP0[1], 2) * fTCP1[1]; + + float fQ112122_001 = fTCP0[2]; + float fQ112122_010 = fTCP0[1]; + float fQ112122_100 = fTCP1[1]; + float fQ112122_011 = fTCP0[1] * fTCP0[2]; + float fQ112122_101 = fTCP1[1] * fTCP0[2]; + float fQ112122_110 = fTCP1[1] * fTCP0[1]; + + float fQ1141_11 = fTCP1[1] * fTCP0[1]; + float fQ1141_01 = fTCP0[1]; + float fQ1141_10 = fTCP1[1]; + float fQ1141_20 = std::pow(fTCP1[1], 2); + float fQ1141_21 = std::pow(fTCP1[1], 2) * fTCP0[1]; + float fQ1142_11 = fTCP1[1] * fTCP0[2]; + float fQ1142_01 = fTCP0[2]; + float fQ1142_10 = fTCP1[1]; + float fQ1142_20 = std::pow(fTCP1[1], 2); + float fQ1142_21 = std::pow(fTCP1[1], 2) * fTCP0[2]; + + float fQ1143_11 = fTCP1[1] * fTCP0[3]; + float fQ1143_01 = fTCP0[3]; + float fQ1143_10 = fTCP1[1]; + float fQ1143_20 = std::pow(fTCP1[1], 2); + float fQ1143_21 = std::pow(fTCP1[1], 2) * fTCP0[3]; + float fQ1144_11 = fTCP1[1] * fTCP0[4]; + float fQ1144_01 = fTCP0[4]; + float fQ1144_10 = fTCP1[1]; + float fQ1144_20 = std::pow(fTCP1[1], 2); + float fQ1144_21 = std::pow(fTCP1[1], 2) * fTCP0[4]; + float fQ2131_11 = fTCP0[1] * fTCP1[1]; + float fQ2131_01 = fTCP1[1]; + float fQ2131_10 = fTCP0[1]; + + float fQ2132_11 = fTCP0[1] * fTCP1[2]; + float fQ2132_01 = fTCP1[2]; + float fQ2132_10 = fTCP0[1]; + float fQ2133_11 = fTCP0[1] * fTCP1[3]; + float fQ2133_01 = fTCP1[3]; + float fQ2133_10 = fTCP0[1]; + float fQ2231_11 = fTCP0[2] * fTCP1[1]; + float fQ2231_01 = fTCP1[1]; + float fQ2231_10 = fTCP0[2]; + float fQ2232_11 = fTCP0[2] * fTCP1[2]; + float fQ2232_01 = fTCP1[2]; + float fQ2232_10 = fTCP0[2]; + float fQ2233_11 = fTCP0[2] * fTCP1[3]; + float fQ2233_01 = fTCP1[3]; + float fQ2233_10 = fTCP0[2]; + + float fQ51_1 = fTCP1[1]; + float fQ52_1 = fTCP1[2]; + float fQ53_1 = fTCP1[3]; + float fQ54_1 = fTCP1[4]; + float fQ55_1 = fTCP1[5]; + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + if (cfgIsCalculateCentral) { + + // uncorrected + histos.get(HIST("Prof_mu1_netproton"))->Fill(cent, std::pow(netProt, 1.0)); + histos.get(HIST("Prof_mu2_netproton"))->Fill(cent, std::pow(netProt, 2.0)); + histos.get(HIST("Prof_mu3_netproton"))->Fill(cent, std::pow(netProt, 3.0)); + histos.get(HIST("Prof_mu4_netproton"))->Fill(cent, std::pow(netProt, 4.0)); + histos.get(HIST("Prof_mu5_netproton"))->Fill(cent, std::pow(netProt, 5.0)); + histos.get(HIST("Prof_mu6_netproton"))->Fill(cent, std::pow(netProt, 6.0)); + histos.get(HIST("Prof_mu7_netproton"))->Fill(cent, std::pow(netProt, 7.0)); + histos.get(HIST("Prof_mu8_netproton"))->Fill(cent, std::pow(netProt, 8.0)); + + // eff. corrected + histos.get(HIST("Prof_Q11_1"))->Fill(cent, fQ11_1); + histos.get(HIST("Prof_Q11_2"))->Fill(cent, fQ11_2); + histos.get(HIST("Prof_Q11_3"))->Fill(cent, fQ11_3); + histos.get(HIST("Prof_Q11_4"))->Fill(cent, fQ11_4); + histos.get(HIST("Prof_Q21_1"))->Fill(cent, fQ21_1); + histos.get(HIST("Prof_Q22_1"))->Fill(cent, fQ22_1); + histos.get(HIST("Prof_Q31_1"))->Fill(cent, fQ31_1); + histos.get(HIST("Prof_Q32_1"))->Fill(cent, fQ32_1); + histos.get(HIST("Prof_Q33_1"))->Fill(cent, fQ33_1); + histos.get(HIST("Prof_Q41_1"))->Fill(cent, fQ41_1); + histos.get(HIST("Prof_Q42_1"))->Fill(cent, fQ42_1); + histos.get(HIST("Prof_Q43_1"))->Fill(cent, fQ43_1); + histos.get(HIST("Prof_Q44_1"))->Fill(cent, fQ44_1); + histos.get(HIST("Prof_Q21_2"))->Fill(cent, fQ21_2); + histos.get(HIST("Prof_Q22_2"))->Fill(cent, fQ22_2); + histos.get(HIST("Prof_Q1121_11"))->Fill(cent, fQ1121_11); + histos.get(HIST("Prof_Q1121_01"))->Fill(cent, fQ1121_01); + histos.get(HIST("Prof_Q1121_10"))->Fill(cent, fQ1121_10); + histos.get(HIST("Prof_Q1121_20"))->Fill(cent, fQ1121_20); + histos.get(HIST("Prof_Q1121_21"))->Fill(cent, fQ1121_21); + histos.get(HIST("Prof_Q1122_11"))->Fill(cent, fQ1122_11); + histos.get(HIST("Prof_Q1122_01"))->Fill(cent, fQ1122_01); + histos.get(HIST("Prof_Q1122_10"))->Fill(cent, fQ1122_10); + histos.get(HIST("Prof_Q1122_20"))->Fill(cent, fQ1122_20); + histos.get(HIST("Prof_Q1122_21"))->Fill(cent, fQ1122_21); + histos.get(HIST("Prof_Q1131_11"))->Fill(cent, fQ1131_11); + histos.get(HIST("Prof_Q1131_01"))->Fill(cent, fQ1131_01); + histos.get(HIST("Prof_Q1131_10"))->Fill(cent, fQ1131_10); + histos.get(HIST("Prof_Q1132_11"))->Fill(cent, fQ1132_11); + histos.get(HIST("Prof_Q1132_01"))->Fill(cent, fQ1132_01); + histos.get(HIST("Prof_Q1132_10"))->Fill(cent, fQ1132_10); + histos.get(HIST("Prof_Q1133_11"))->Fill(cent, fQ1133_11); + histos.get(HIST("Prof_Q1133_01"))->Fill(cent, fQ1133_01); + histos.get(HIST("Prof_Q1133_10"))->Fill(cent, fQ1133_10); + histos.get(HIST("Prof_Q2122_11"))->Fill(cent, fQ2122_11); + histos.get(HIST("Prof_Q2122_01"))->Fill(cent, fQ2122_01); + histos.get(HIST("Prof_Q2122_10"))->Fill(cent, fQ2122_10); + histos.get(HIST("Prof_Q3132_11"))->Fill(cent, fQ3132_11); + histos.get(HIST("Prof_Q3132_01"))->Fill(cent, fQ3132_01); + histos.get(HIST("Prof_Q3132_10"))->Fill(cent, fQ3132_10); + histos.get(HIST("Prof_Q3133_11"))->Fill(cent, fQ3133_11); + histos.get(HIST("Prof_Q3133_01"))->Fill(cent, fQ3133_01); + histos.get(HIST("Prof_Q3133_10"))->Fill(cent, fQ3133_10); + histos.get(HIST("Prof_Q3233_11"))->Fill(cent, fQ3233_11); + histos.get(HIST("Prof_Q3233_01"))->Fill(cent, fQ3233_01); + histos.get(HIST("Prof_Q3233_10"))->Fill(cent, fQ3233_10); + histos.get(HIST("Prof_Q2241_11"))->Fill(cent, fQ2241_11); + histos.get(HIST("Prof_Q2241_01"))->Fill(cent, fQ2241_01); + histos.get(HIST("Prof_Q2241_10"))->Fill(cent, fQ2241_10); + histos.get(HIST("Prof_Q2242_11"))->Fill(cent, fQ2242_11); + histos.get(HIST("Prof_Q2242_01"))->Fill(cent, fQ2242_01); + histos.get(HIST("Prof_Q2242_10"))->Fill(cent, fQ2242_10); + histos.get(HIST("Prof_Q2243_11"))->Fill(cent, fQ2243_11); + histos.get(HIST("Prof_Q2243_01"))->Fill(cent, fQ2243_01); + histos.get(HIST("Prof_Q2243_10"))->Fill(cent, fQ2243_10); + histos.get(HIST("Prof_Q2244_11"))->Fill(cent, fQ2244_11); + histos.get(HIST("Prof_Q2244_01"))->Fill(cent, fQ2244_01); + histos.get(HIST("Prof_Q2244_10"))->Fill(cent, fQ2244_10); + histos.get(HIST("Prof_Q2141_11"))->Fill(cent, fQ2141_11); + histos.get(HIST("Prof_Q2141_01"))->Fill(cent, fQ2141_01); + histos.get(HIST("Prof_Q2141_10"))->Fill(cent, fQ2141_10); + histos.get(HIST("Prof_Q2142_11"))->Fill(cent, fQ2142_11); + histos.get(HIST("Prof_Q2142_01"))->Fill(cent, fQ2142_01); + histos.get(HIST("Prof_Q2142_10"))->Fill(cent, fQ2142_10); + histos.get(HIST("Prof_Q2143_11"))->Fill(cent, fQ2143_11); + histos.get(HIST("Prof_Q2143_01"))->Fill(cent, fQ2143_01); + histos.get(HIST("Prof_Q2143_10"))->Fill(cent, fQ2143_10); + histos.get(HIST("Prof_Q2144_11"))->Fill(cent, fQ2144_11); + histos.get(HIST("Prof_Q2144_01"))->Fill(cent, fQ2144_01); + histos.get(HIST("Prof_Q2144_10"))->Fill(cent, fQ2144_10); + histos.get(HIST("Prof_Q1151_11"))->Fill(cent, fQ1151_11); + histos.get(HIST("Prof_Q1151_01"))->Fill(cent, fQ1151_01); + histos.get(HIST("Prof_Q1151_10"))->Fill(cent, fQ1151_10); + histos.get(HIST("Prof_Q1152_11"))->Fill(cent, fQ1152_11); + histos.get(HIST("Prof_Q1152_01"))->Fill(cent, fQ1152_01); + histos.get(HIST("Prof_Q1152_10"))->Fill(cent, fQ1152_10); + histos.get(HIST("Prof_Q1153_11"))->Fill(cent, fQ1153_11); + histos.get(HIST("Prof_Q1153_01"))->Fill(cent, fQ1153_01); + histos.get(HIST("Prof_Q1153_10"))->Fill(cent, fQ1153_10); + histos.get(HIST("Prof_Q1154_11"))->Fill(cent, fQ1154_11); + histos.get(HIST("Prof_Q1154_01"))->Fill(cent, fQ1154_01); + histos.get(HIST("Prof_Q1154_10"))->Fill(cent, fQ1154_10); + histos.get(HIST("Prof_Q1155_11"))->Fill(cent, fQ1155_11); + histos.get(HIST("Prof_Q1155_01"))->Fill(cent, fQ1155_01); + histos.get(HIST("Prof_Q1155_10"))->Fill(cent, fQ1155_10); + histos.get(HIST("Prof_Q112233_001"))->Fill(cent, fQ112233_001); + histos.get(HIST("Prof_Q112233_010"))->Fill(cent, fQ112233_010); + histos.get(HIST("Prof_Q112233_100"))->Fill(cent, fQ112233_100); + histos.get(HIST("Prof_Q112233_011"))->Fill(cent, fQ112233_011); + histos.get(HIST("Prof_Q112233_101"))->Fill(cent, fQ112233_101); + histos.get(HIST("Prof_Q112233_110"))->Fill(cent, fQ112233_110); + histos.get(HIST("Prof_Q112232_001"))->Fill(cent, fQ112232_001); + histos.get(HIST("Prof_Q112232_010"))->Fill(cent, fQ112232_010); + histos.get(HIST("Prof_Q112232_100"))->Fill(cent, fQ112232_100); + histos.get(HIST("Prof_Q112232_011"))->Fill(cent, fQ112232_011); + histos.get(HIST("Prof_Q112232_101"))->Fill(cent, fQ112232_101); + histos.get(HIST("Prof_Q112232_110"))->Fill(cent, fQ112232_110); + histos.get(HIST("Prof_Q112231_001"))->Fill(cent, fQ112231_001); + histos.get(HIST("Prof_Q112231_010"))->Fill(cent, fQ112231_010); + histos.get(HIST("Prof_Q112231_100"))->Fill(cent, fQ112231_100); + histos.get(HIST("Prof_Q112231_011"))->Fill(cent, fQ112231_011); + histos.get(HIST("Prof_Q112231_101"))->Fill(cent, fQ112231_101); + histos.get(HIST("Prof_Q112231_110"))->Fill(cent, fQ112231_110); + histos.get(HIST("Prof_Q112133_001"))->Fill(cent, fQ112133_001); + histos.get(HIST("Prof_Q112133_010"))->Fill(cent, fQ112133_010); + histos.get(HIST("Prof_Q112133_100"))->Fill(cent, fQ112133_100); + histos.get(HIST("Prof_Q112133_011"))->Fill(cent, fQ112133_011); + histos.get(HIST("Prof_Q112133_101"))->Fill(cent, fQ112133_101); + histos.get(HIST("Prof_Q112133_110"))->Fill(cent, fQ112133_110); + histos.get(HIST("Prof_Q112132_001"))->Fill(cent, fQ112132_001); + histos.get(HIST("Prof_Q112132_010"))->Fill(cent, fQ112132_010); + histos.get(HIST("Prof_Q112132_100"))->Fill(cent, fQ112132_100); + histos.get(HIST("Prof_Q112132_011"))->Fill(cent, fQ112132_011); + histos.get(HIST("Prof_Q112132_101"))->Fill(cent, fQ112132_101); + histos.get(HIST("Prof_Q112132_110"))->Fill(cent, fQ112132_110); + histos.get(HIST("Prof_Q112131_001"))->Fill(cent, fQ112131_001); + histos.get(HIST("Prof_Q112131_010"))->Fill(cent, fQ112131_010); + histos.get(HIST("Prof_Q112131_100"))->Fill(cent, fQ112131_100); + histos.get(HIST("Prof_Q112131_011"))->Fill(cent, fQ112131_011); + histos.get(HIST("Prof_Q112131_101"))->Fill(cent, fQ112131_101); + histos.get(HIST("Prof_Q112131_110"))->Fill(cent, fQ112131_110); + histos.get(HIST("Prof_Q2221_11"))->Fill(cent, fQ2221_11); + histos.get(HIST("Prof_Q2221_01"))->Fill(cent, fQ2221_01); + histos.get(HIST("Prof_Q2221_10"))->Fill(cent, fQ2221_10); + histos.get(HIST("Prof_Q2221_21"))->Fill(cent, fQ2221_21); + histos.get(HIST("Prof_Q2221_20"))->Fill(cent, fQ2221_20); + histos.get(HIST("Prof_Q2122_21"))->Fill(cent, fQ2122_21); + histos.get(HIST("Prof_Q2122_20"))->Fill(cent, fQ2122_20); + histos.get(HIST("Prof_Q1121_02"))->Fill(cent, fQ1121_02); + histos.get(HIST("Prof_Q1121_12"))->Fill(cent, fQ1121_12); + histos.get(HIST("Prof_Q1121_22"))->Fill(cent, fQ1121_22); + histos.get(HIST("Prof_Q1122_02"))->Fill(cent, fQ1122_02); + histos.get(HIST("Prof_Q1122_12"))->Fill(cent, fQ1122_12); + histos.get(HIST("Prof_Q1122_22"))->Fill(cent, fQ1122_22); + histos.get(HIST("Prof_Q112221_001"))->Fill(cent, fQ112221_001); + histos.get(HIST("Prof_Q112221_010"))->Fill(cent, fQ112221_010); + histos.get(HIST("Prof_Q112221_100"))->Fill(cent, fQ112221_100); + histos.get(HIST("Prof_Q112221_011"))->Fill(cent, fQ112221_011); + histos.get(HIST("Prof_Q112221_101"))->Fill(cent, fQ112221_101); + histos.get(HIST("Prof_Q112221_110"))->Fill(cent, fQ112221_110); + histos.get(HIST("Prof_Q112221_200"))->Fill(cent, fQ112221_200); + histos.get(HIST("Prof_Q112221_201"))->Fill(cent, fQ112221_201); + histos.get(HIST("Prof_Q112221_210"))->Fill(cent, fQ112221_210); + histos.get(HIST("Prof_Q112221_211"))->Fill(cent, fQ112221_211); + histos.get(HIST("Prof_Q1131_21"))->Fill(cent, fQ1131_21); + histos.get(HIST("Prof_Q1131_20"))->Fill(cent, fQ1131_20); + histos.get(HIST("Prof_Q1131_31"))->Fill(cent, fQ1131_31); + histos.get(HIST("Prof_Q1131_30"))->Fill(cent, fQ1131_30); + histos.get(HIST("Prof_Q1132_21"))->Fill(cent, fQ1132_21); + histos.get(HIST("Prof_Q1132_20"))->Fill(cent, fQ1132_20); + histos.get(HIST("Prof_Q1132_31"))->Fill(cent, fQ1132_31); + histos.get(HIST("Prof_Q1132_30"))->Fill(cent, fQ1132_30); + histos.get(HIST("Prof_Q1133_21"))->Fill(cent, fQ1133_21); + histos.get(HIST("Prof_Q1133_20"))->Fill(cent, fQ1133_20); + histos.get(HIST("Prof_Q1133_31"))->Fill(cent, fQ1133_31); + histos.get(HIST("Prof_Q1133_30"))->Fill(cent, fQ1133_30); + histos.get(HIST("Prof_Q11_5"))->Fill(cent, fQ11_5); + histos.get(HIST("Prof_Q11_6"))->Fill(cent, fQ11_6); + histos.get(HIST("Prof_Q1121_30"))->Fill(cent, fQ1121_30); + histos.get(HIST("Prof_Q1121_31"))->Fill(cent, fQ1121_31); + histos.get(HIST("Prof_Q1121_40"))->Fill(cent, fQ1121_40); + histos.get(HIST("Prof_Q1121_41"))->Fill(cent, fQ1121_41); + histos.get(HIST("Prof_Q1122_30"))->Fill(cent, fQ1122_30); + histos.get(HIST("Prof_Q1122_31"))->Fill(cent, fQ1122_31); + histos.get(HIST("Prof_Q1122_40"))->Fill(cent, fQ1122_40); + histos.get(HIST("Prof_Q1122_41"))->Fill(cent, fQ1122_41); + histos.get(HIST("Prof_Q2211_11"))->Fill(cent, fQ2211_11); + histos.get(HIST("Prof_Q2211_01"))->Fill(cent, fQ2211_01); + histos.get(HIST("Prof_Q2211_10"))->Fill(cent, fQ2211_10); + histos.get(HIST("Prof_Q2211_20"))->Fill(cent, fQ2211_20); + histos.get(HIST("Prof_Q2211_21"))->Fill(cent, fQ2211_21); + histos.get(HIST("Prof_Q2111_11"))->Fill(cent, fQ2111_11); + histos.get(HIST("Prof_Q2111_01"))->Fill(cent, fQ2111_01); + histos.get(HIST("Prof_Q2111_10"))->Fill(cent, fQ2111_10); + histos.get(HIST("Prof_Q2111_20"))->Fill(cent, fQ2111_20); + histos.get(HIST("Prof_Q2111_21"))->Fill(cent, fQ2111_21); + histos.get(HIST("Prof_Q112122_001"))->Fill(cent, fQ112122_001); + histos.get(HIST("Prof_Q112122_010"))->Fill(cent, fQ112122_010); + histos.get(HIST("Prof_Q112122_100"))->Fill(cent, fQ112122_100); + histos.get(HIST("Prof_Q112122_011"))->Fill(cent, fQ112122_011); + histos.get(HIST("Prof_Q112122_101"))->Fill(cent, fQ112122_101); + histos.get(HIST("Prof_Q112122_110"))->Fill(cent, fQ112122_110); + histos.get(HIST("Prof_Q1141_11"))->Fill(cent, fQ1141_11); + histos.get(HIST("Prof_Q1141_01"))->Fill(cent, fQ1141_01); + histos.get(HIST("Prof_Q1141_10"))->Fill(cent, fQ1141_10); + histos.get(HIST("Prof_Q1141_20"))->Fill(cent, fQ1141_20); + histos.get(HIST("Prof_Q1141_21"))->Fill(cent, fQ1141_21); + histos.get(HIST("Prof_Q1142_11"))->Fill(cent, fQ1142_11); + histos.get(HIST("Prof_Q1142_01"))->Fill(cent, fQ1142_01); + histos.get(HIST("Prof_Q1142_10"))->Fill(cent, fQ1142_10); + histos.get(HIST("Prof_Q1142_20"))->Fill(cent, fQ1142_20); + histos.get(HIST("Prof_Q1142_21"))->Fill(cent, fQ1142_21); + histos.get(HIST("Prof_Q1143_11"))->Fill(cent, fQ1143_11); + histos.get(HIST("Prof_Q1143_01"))->Fill(cent, fQ1143_01); + histos.get(HIST("Prof_Q1143_10"))->Fill(cent, fQ1143_10); + histos.get(HIST("Prof_Q1143_20"))->Fill(cent, fQ1143_20); + histos.get(HIST("Prof_Q1143_21"))->Fill(cent, fQ1143_21); + histos.get(HIST("Prof_Q1144_11"))->Fill(cent, fQ1144_11); + histos.get(HIST("Prof_Q1144_01"))->Fill(cent, fQ1144_01); + histos.get(HIST("Prof_Q1144_10"))->Fill(cent, fQ1144_10); + histos.get(HIST("Prof_Q1144_20"))->Fill(cent, fQ1144_20); + histos.get(HIST("Prof_Q1144_21"))->Fill(cent, fQ1144_21); + histos.get(HIST("Prof_Q2131_11"))->Fill(cent, fQ2131_11); + histos.get(HIST("Prof_Q2131_01"))->Fill(cent, fQ2131_01); + histos.get(HIST("Prof_Q2131_10"))->Fill(cent, fQ2131_10); + histos.get(HIST("Prof_Q2132_11"))->Fill(cent, fQ2132_11); + histos.get(HIST("Prof_Q2132_01"))->Fill(cent, fQ2132_01); + histos.get(HIST("Prof_Q2132_10"))->Fill(cent, fQ2132_10); + histos.get(HIST("Prof_Q2133_11"))->Fill(cent, fQ2133_11); + histos.get(HIST("Prof_Q2133_01"))->Fill(cent, fQ2133_01); + histos.get(HIST("Prof_Q2133_10"))->Fill(cent, fQ2133_10); + histos.get(HIST("Prof_Q2231_11"))->Fill(cent, fQ2231_11); + histos.get(HIST("Prof_Q2231_01"))->Fill(cent, fQ2231_01); + histos.get(HIST("Prof_Q2231_10"))->Fill(cent, fQ2231_10); + histos.get(HIST("Prof_Q2232_11"))->Fill(cent, fQ2232_11); + histos.get(HIST("Prof_Q2232_01"))->Fill(cent, fQ2232_01); + histos.get(HIST("Prof_Q2232_10"))->Fill(cent, fQ2232_10); + histos.get(HIST("Prof_Q2233_11"))->Fill(cent, fQ2233_11); + histos.get(HIST("Prof_Q2233_01"))->Fill(cent, fQ2233_01); + histos.get(HIST("Prof_Q2233_10"))->Fill(cent, fQ2233_10); + histos.get(HIST("Prof_Q51_1"))->Fill(cent, fQ51_1); + histos.get(HIST("Prof_Q52_1"))->Fill(cent, fQ52_1); + histos.get(HIST("Prof_Q53_1"))->Fill(cent, fQ53_1); + histos.get(HIST("Prof_Q54_1"))->Fill(cent, fQ54_1); + histos.get(HIST("Prof_Q55_1"))->Fill(cent, fQ55_1); + histos.get(HIST("Prof_Q21_3"))->Fill(cent, fQ21_3); + histos.get(HIST("Prof_Q22_3"))->Fill(cent, fQ22_3); + histos.get(HIST("Prof_Q31_2"))->Fill(cent, fQ31_2); + histos.get(HIST("Prof_Q32_2"))->Fill(cent, fQ32_2); + histos.get(HIST("Prof_Q33_2"))->Fill(cent, fQ33_2); + histos.get(HIST("Prof_Q61_1"))->Fill(cent, fQ61_1); + histos.get(HIST("Prof_Q62_1"))->Fill(cent, fQ62_1); + histos.get(HIST("Prof_Q63_1"))->Fill(cent, fQ63_1); + histos.get(HIST("Prof_Q64_1"))->Fill(cent, fQ64_1); + histos.get(HIST("Prof_Q65_1"))->Fill(cent, fQ65_1); + histos.get(HIST("Prof_Q66_1"))->Fill(cent, fQ66_1); + histos.get(HIST("Prof_Q112122_111"))->Fill(cent, fQ112122_111); + histos.get(HIST("Prof_Q112131_111"))->Fill(cent, fQ112131_111); + histos.get(HIST("Prof_Q112132_111"))->Fill(cent, fQ112132_111); + histos.get(HIST("Prof_Q112133_111"))->Fill(cent, fQ112133_111); + histos.get(HIST("Prof_Q112231_111"))->Fill(cent, fQ112231_111); + histos.get(HIST("Prof_Q112232_111"))->Fill(cent, fQ112232_111); + histos.get(HIST("Prof_Q112233_111"))->Fill(cent, fQ112233_111); + histos.get(HIST("Prof_Q112221_111"))->Fill(cent, fQ112221_111); + } + + if (cfgIsCalculateError) { + // selecting subsample and filling profiles + float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNSubsample * lRandom); + + histos.get(HIST("Prof2D_mu1_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 1.0)); + histos.get(HIST("Prof2D_mu2_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 2.0)); + histos.get(HIST("Prof2D_mu3_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 3.0)); + histos.get(HIST("Prof2D_mu4_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 4.0)); + histos.get(HIST("Prof2D_mu5_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 5.0)); + histos.get(HIST("Prof2D_mu6_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 6.0)); + histos.get(HIST("Prof2D_mu7_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 7.0)); + histos.get(HIST("Prof2D_mu8_netproton"))->Fill(cent, sampleIndex, std::pow(netProt, 8.0)); + + histos.get(HIST("Prof2D_Q11_1"))->Fill(cent, sampleIndex, fQ11_1); + histos.get(HIST("Prof2D_Q11_2"))->Fill(cent, sampleIndex, fQ11_2); + histos.get(HIST("Prof2D_Q11_3"))->Fill(cent, sampleIndex, fQ11_3); + histos.get(HIST("Prof2D_Q11_4"))->Fill(cent, sampleIndex, fQ11_4); + histos.get(HIST("Prof2D_Q21_1"))->Fill(cent, sampleIndex, fQ21_1); + histos.get(HIST("Prof2D_Q22_1"))->Fill(cent, sampleIndex, fQ22_1); + histos.get(HIST("Prof2D_Q31_1"))->Fill(cent, sampleIndex, fQ31_1); + histos.get(HIST("Prof2D_Q32_1"))->Fill(cent, sampleIndex, fQ32_1); + histos.get(HIST("Prof2D_Q33_1"))->Fill(cent, sampleIndex, fQ33_1); + histos.get(HIST("Prof2D_Q41_1"))->Fill(cent, sampleIndex, fQ41_1); + histos.get(HIST("Prof2D_Q42_1"))->Fill(cent, sampleIndex, fQ42_1); + histos.get(HIST("Prof2D_Q43_1"))->Fill(cent, sampleIndex, fQ43_1); + histos.get(HIST("Prof2D_Q44_1"))->Fill(cent, sampleIndex, fQ44_1); + histos.get(HIST("Prof2D_Q21_2"))->Fill(cent, sampleIndex, fQ21_2); + histos.get(HIST("Prof2D_Q22_2"))->Fill(cent, sampleIndex, fQ22_2); + histos.get(HIST("Prof2D_Q1121_11"))->Fill(cent, sampleIndex, fQ1121_11); + histos.get(HIST("Prof2D_Q1121_01"))->Fill(cent, sampleIndex, fQ1121_01); + histos.get(HIST("Prof2D_Q1121_10"))->Fill(cent, sampleIndex, fQ1121_10); + histos.get(HIST("Prof2D_Q1121_20"))->Fill(cent, sampleIndex, fQ1121_20); + histos.get(HIST("Prof2D_Q1121_21"))->Fill(cent, sampleIndex, fQ1121_21); + histos.get(HIST("Prof2D_Q1122_11"))->Fill(cent, sampleIndex, fQ1122_11); + histos.get(HIST("Prof2D_Q1122_01"))->Fill(cent, sampleIndex, fQ1122_01); + histos.get(HIST("Prof2D_Q1122_10"))->Fill(cent, sampleIndex, fQ1122_10); + histos.get(HIST("Prof2D_Q1122_20"))->Fill(cent, sampleIndex, fQ1122_20); + histos.get(HIST("Prof2D_Q1122_21"))->Fill(cent, sampleIndex, fQ1122_21); + histos.get(HIST("Prof2D_Q1131_11"))->Fill(cent, sampleIndex, fQ1131_11); + histos.get(HIST("Prof2D_Q1131_01"))->Fill(cent, sampleIndex, fQ1131_01); + histos.get(HIST("Prof2D_Q1131_10"))->Fill(cent, sampleIndex, fQ1131_10); + histos.get(HIST("Prof2D_Q1132_11"))->Fill(cent, sampleIndex, fQ1132_11); + histos.get(HIST("Prof2D_Q1132_01"))->Fill(cent, sampleIndex, fQ1132_01); + histos.get(HIST("Prof2D_Q1132_10"))->Fill(cent, sampleIndex, fQ1132_10); + histos.get(HIST("Prof2D_Q1133_11"))->Fill(cent, sampleIndex, fQ1133_11); + histos.get(HIST("Prof2D_Q1133_01"))->Fill(cent, sampleIndex, fQ1133_01); + histos.get(HIST("Prof2D_Q1133_10"))->Fill(cent, sampleIndex, fQ1133_10); + histos.get(HIST("Prof2D_Q2122_11"))->Fill(cent, sampleIndex, fQ2122_11); + histos.get(HIST("Prof2D_Q2122_01"))->Fill(cent, sampleIndex, fQ2122_01); + histos.get(HIST("Prof2D_Q2122_10"))->Fill(cent, sampleIndex, fQ2122_10); + histos.get(HIST("Prof2D_Q3132_11"))->Fill(cent, sampleIndex, fQ3132_11); + histos.get(HIST("Prof2D_Q3132_01"))->Fill(cent, sampleIndex, fQ3132_01); + histos.get(HIST("Prof2D_Q3132_10"))->Fill(cent, sampleIndex, fQ3132_10); + histos.get(HIST("Prof2D_Q3133_11"))->Fill(cent, sampleIndex, fQ3133_11); + histos.get(HIST("Prof2D_Q3133_01"))->Fill(cent, sampleIndex, fQ3133_01); + histos.get(HIST("Prof2D_Q3133_10"))->Fill(cent, sampleIndex, fQ3133_10); + histos.get(HIST("Prof2D_Q3233_11"))->Fill(cent, sampleIndex, fQ3233_11); + histos.get(HIST("Prof2D_Q3233_01"))->Fill(cent, sampleIndex, fQ3233_01); + histos.get(HIST("Prof2D_Q3233_10"))->Fill(cent, sampleIndex, fQ3233_10); + histos.get(HIST("Prof2D_Q2241_11"))->Fill(cent, sampleIndex, fQ2241_11); + histos.get(HIST("Prof2D_Q2241_01"))->Fill(cent, sampleIndex, fQ2241_01); + histos.get(HIST("Prof2D_Q2241_10"))->Fill(cent, sampleIndex, fQ2241_10); + histos.get(HIST("Prof2D_Q2242_11"))->Fill(cent, sampleIndex, fQ2242_11); + histos.get(HIST("Prof2D_Q2242_01"))->Fill(cent, sampleIndex, fQ2242_01); + histos.get(HIST("Prof2D_Q2242_10"))->Fill(cent, sampleIndex, fQ2242_10); + histos.get(HIST("Prof2D_Q2243_11"))->Fill(cent, sampleIndex, fQ2243_11); + histos.get(HIST("Prof2D_Q2243_01"))->Fill(cent, sampleIndex, fQ2243_01); + histos.get(HIST("Prof2D_Q2243_10"))->Fill(cent, sampleIndex, fQ2243_10); + histos.get(HIST("Prof2D_Q2244_11"))->Fill(cent, sampleIndex, fQ2244_11); + histos.get(HIST("Prof2D_Q2244_01"))->Fill(cent, sampleIndex, fQ2244_01); + histos.get(HIST("Prof2D_Q2244_10"))->Fill(cent, sampleIndex, fQ2244_10); + histos.get(HIST("Prof2D_Q2141_11"))->Fill(cent, sampleIndex, fQ2141_11); + histos.get(HIST("Prof2D_Q2141_01"))->Fill(cent, sampleIndex, fQ2141_01); + histos.get(HIST("Prof2D_Q2141_10"))->Fill(cent, sampleIndex, fQ2141_10); + histos.get(HIST("Prof2D_Q2142_11"))->Fill(cent, sampleIndex, fQ2142_11); + histos.get(HIST("Prof2D_Q2142_01"))->Fill(cent, sampleIndex, fQ2142_01); + histos.get(HIST("Prof2D_Q2142_10"))->Fill(cent, sampleIndex, fQ2142_10); + histos.get(HIST("Prof2D_Q2143_11"))->Fill(cent, sampleIndex, fQ2143_11); + histos.get(HIST("Prof2D_Q2143_01"))->Fill(cent, sampleIndex, fQ2143_01); + histos.get(HIST("Prof2D_Q2143_10"))->Fill(cent, sampleIndex, fQ2143_10); + histos.get(HIST("Prof2D_Q2144_11"))->Fill(cent, sampleIndex, fQ2144_11); + histos.get(HIST("Prof2D_Q2144_01"))->Fill(cent, sampleIndex, fQ2144_01); + histos.get(HIST("Prof2D_Q2144_10"))->Fill(cent, sampleIndex, fQ2144_10); + histos.get(HIST("Prof2D_Q1151_11"))->Fill(cent, sampleIndex, fQ1151_11); + histos.get(HIST("Prof2D_Q1151_01"))->Fill(cent, sampleIndex, fQ1151_01); + histos.get(HIST("Prof2D_Q1151_10"))->Fill(cent, sampleIndex, fQ1151_10); + histos.get(HIST("Prof2D_Q1152_11"))->Fill(cent, sampleIndex, fQ1152_11); + histos.get(HIST("Prof2D_Q1152_01"))->Fill(cent, sampleIndex, fQ1152_01); + histos.get(HIST("Prof2D_Q1152_10"))->Fill(cent, sampleIndex, fQ1152_10); + histos.get(HIST("Prof2D_Q1153_11"))->Fill(cent, sampleIndex, fQ1153_11); + histos.get(HIST("Prof2D_Q1153_01"))->Fill(cent, sampleIndex, fQ1153_01); + histos.get(HIST("Prof2D_Q1153_10"))->Fill(cent, sampleIndex, fQ1153_10); + histos.get(HIST("Prof2D_Q1154_11"))->Fill(cent, sampleIndex, fQ1154_11); + histos.get(HIST("Prof2D_Q1154_01"))->Fill(cent, sampleIndex, fQ1154_01); + histos.get(HIST("Prof2D_Q1154_10"))->Fill(cent, sampleIndex, fQ1154_10); + histos.get(HIST("Prof2D_Q1155_11"))->Fill(cent, sampleIndex, fQ1155_11); + histos.get(HIST("Prof2D_Q1155_01"))->Fill(cent, sampleIndex, fQ1155_01); + histos.get(HIST("Prof2D_Q1155_10"))->Fill(cent, sampleIndex, fQ1155_10); + histos.get(HIST("Prof2D_Q112233_001"))->Fill(cent, sampleIndex, fQ112233_001); + histos.get(HIST("Prof2D_Q112233_010"))->Fill(cent, sampleIndex, fQ112233_010); + histos.get(HIST("Prof2D_Q112233_100"))->Fill(cent, sampleIndex, fQ112233_100); + histos.get(HIST("Prof2D_Q112233_011"))->Fill(cent, sampleIndex, fQ112233_011); + histos.get(HIST("Prof2D_Q112233_101"))->Fill(cent, sampleIndex, fQ112233_101); + histos.get(HIST("Prof2D_Q112233_110"))->Fill(cent, sampleIndex, fQ112233_110); + histos.get(HIST("Prof2D_Q112232_001"))->Fill(cent, sampleIndex, fQ112232_001); + histos.get(HIST("Prof2D_Q112232_010"))->Fill(cent, sampleIndex, fQ112232_010); + histos.get(HIST("Prof2D_Q112232_100"))->Fill(cent, sampleIndex, fQ112232_100); + histos.get(HIST("Prof2D_Q112232_011"))->Fill(cent, sampleIndex, fQ112232_011); + histos.get(HIST("Prof2D_Q112232_101"))->Fill(cent, sampleIndex, fQ112232_101); + histos.get(HIST("Prof2D_Q112232_110"))->Fill(cent, sampleIndex, fQ112232_110); + histos.get(HIST("Prof2D_Q112231_001"))->Fill(cent, sampleIndex, fQ112231_001); + histos.get(HIST("Prof2D_Q112231_010"))->Fill(cent, sampleIndex, fQ112231_010); + histos.get(HIST("Prof2D_Q112231_100"))->Fill(cent, sampleIndex, fQ112231_100); + histos.get(HIST("Prof2D_Q112231_011"))->Fill(cent, sampleIndex, fQ112231_011); + histos.get(HIST("Prof2D_Q112231_101"))->Fill(cent, sampleIndex, fQ112231_101); + histos.get(HIST("Prof2D_Q112231_110"))->Fill(cent, sampleIndex, fQ112231_110); + histos.get(HIST("Prof2D_Q112133_001"))->Fill(cent, sampleIndex, fQ112133_001); + histos.get(HIST("Prof2D_Q112133_010"))->Fill(cent, sampleIndex, fQ112133_010); + histos.get(HIST("Prof2D_Q112133_100"))->Fill(cent, sampleIndex, fQ112133_100); + histos.get(HIST("Prof2D_Q112133_011"))->Fill(cent, sampleIndex, fQ112133_011); + histos.get(HIST("Prof2D_Q112133_101"))->Fill(cent, sampleIndex, fQ112133_101); + histos.get(HIST("Prof2D_Q112133_110"))->Fill(cent, sampleIndex, fQ112133_110); + histos.get(HIST("Prof2D_Q112132_001"))->Fill(cent, sampleIndex, fQ112132_001); + histos.get(HIST("Prof2D_Q112132_010"))->Fill(cent, sampleIndex, fQ112132_010); + histos.get(HIST("Prof2D_Q112132_100"))->Fill(cent, sampleIndex, fQ112132_100); + histos.get(HIST("Prof2D_Q112132_011"))->Fill(cent, sampleIndex, fQ112132_011); + histos.get(HIST("Prof2D_Q112132_101"))->Fill(cent, sampleIndex, fQ112132_101); + histos.get(HIST("Prof2D_Q112132_110"))->Fill(cent, sampleIndex, fQ112132_110); + histos.get(HIST("Prof2D_Q112131_001"))->Fill(cent, sampleIndex, fQ112131_001); + histos.get(HIST("Prof2D_Q112131_010"))->Fill(cent, sampleIndex, fQ112131_010); + histos.get(HIST("Prof2D_Q112131_100"))->Fill(cent, sampleIndex, fQ112131_100); + histos.get(HIST("Prof2D_Q112131_011"))->Fill(cent, sampleIndex, fQ112131_011); + histos.get(HIST("Prof2D_Q112131_101"))->Fill(cent, sampleIndex, fQ112131_101); + histos.get(HIST("Prof2D_Q112131_110"))->Fill(cent, sampleIndex, fQ112131_110); + histos.get(HIST("Prof2D_Q2221_11"))->Fill(cent, sampleIndex, fQ2221_11); + histos.get(HIST("Prof2D_Q2221_01"))->Fill(cent, sampleIndex, fQ2221_01); + histos.get(HIST("Prof2D_Q2221_10"))->Fill(cent, sampleIndex, fQ2221_10); + histos.get(HIST("Prof2D_Q2221_21"))->Fill(cent, sampleIndex, fQ2221_21); + histos.get(HIST("Prof2D_Q2221_20"))->Fill(cent, sampleIndex, fQ2221_20); + histos.get(HIST("Prof2D_Q2122_21"))->Fill(cent, sampleIndex, fQ2122_21); + histos.get(HIST("Prof2D_Q2122_20"))->Fill(cent, sampleIndex, fQ2122_20); + histos.get(HIST("Prof2D_Q1121_02"))->Fill(cent, sampleIndex, fQ1121_02); + histos.get(HIST("Prof2D_Q1121_12"))->Fill(cent, sampleIndex, fQ1121_12); + histos.get(HIST("Prof2D_Q1121_22"))->Fill(cent, sampleIndex, fQ1121_22); + histos.get(HIST("Prof2D_Q1122_02"))->Fill(cent, sampleIndex, fQ1122_02); + histos.get(HIST("Prof2D_Q1122_12"))->Fill(cent, sampleIndex, fQ1122_12); + histos.get(HIST("Prof2D_Q1122_22"))->Fill(cent, sampleIndex, fQ1122_22); + histos.get(HIST("Prof2D_Q112221_001"))->Fill(cent, sampleIndex, fQ112221_001); + histos.get(HIST("Prof2D_Q112221_010"))->Fill(cent, sampleIndex, fQ112221_010); + histos.get(HIST("Prof2D_Q112221_100"))->Fill(cent, sampleIndex, fQ112221_100); + histos.get(HIST("Prof2D_Q112221_011"))->Fill(cent, sampleIndex, fQ112221_011); + histos.get(HIST("Prof2D_Q112221_101"))->Fill(cent, sampleIndex, fQ112221_101); + histos.get(HIST("Prof2D_Q112221_110"))->Fill(cent, sampleIndex, fQ112221_110); + histos.get(HIST("Prof2D_Q112221_200"))->Fill(cent, sampleIndex, fQ112221_200); + histos.get(HIST("Prof2D_Q112221_201"))->Fill(cent, sampleIndex, fQ112221_201); + histos.get(HIST("Prof2D_Q112221_210"))->Fill(cent, sampleIndex, fQ112221_210); + histos.get(HIST("Prof2D_Q112221_211"))->Fill(cent, sampleIndex, fQ112221_211); + histos.get(HIST("Prof2D_Q1131_21"))->Fill(cent, sampleIndex, fQ1131_21); + histos.get(HIST("Prof2D_Q1131_20"))->Fill(cent, sampleIndex, fQ1131_20); + histos.get(HIST("Prof2D_Q1131_31"))->Fill(cent, sampleIndex, fQ1131_31); + histos.get(HIST("Prof2D_Q1131_30"))->Fill(cent, sampleIndex, fQ1131_30); + histos.get(HIST("Prof2D_Q1132_21"))->Fill(cent, sampleIndex, fQ1132_21); + histos.get(HIST("Prof2D_Q1132_20"))->Fill(cent, sampleIndex, fQ1132_20); + histos.get(HIST("Prof2D_Q1132_31"))->Fill(cent, sampleIndex, fQ1132_31); + histos.get(HIST("Prof2D_Q1132_30"))->Fill(cent, sampleIndex, fQ1132_30); + histos.get(HIST("Prof2D_Q1133_21"))->Fill(cent, sampleIndex, fQ1133_21); + histos.get(HIST("Prof2D_Q1133_20"))->Fill(cent, sampleIndex, fQ1133_20); + histos.get(HIST("Prof2D_Q1133_31"))->Fill(cent, sampleIndex, fQ1133_31); + histos.get(HIST("Prof2D_Q1133_30"))->Fill(cent, sampleIndex, fQ1133_30); + histos.get(HIST("Prof2D_Q11_5"))->Fill(cent, sampleIndex, fQ11_5); + histos.get(HIST("Prof2D_Q11_6"))->Fill(cent, sampleIndex, fQ11_6); + histos.get(HIST("Prof2D_Q1121_30"))->Fill(cent, sampleIndex, fQ1121_30); + histos.get(HIST("Prof2D_Q1121_31"))->Fill(cent, sampleIndex, fQ1121_31); + histos.get(HIST("Prof2D_Q1121_40"))->Fill(cent, sampleIndex, fQ1121_40); + histos.get(HIST("Prof2D_Q1121_41"))->Fill(cent, sampleIndex, fQ1121_41); + histos.get(HIST("Prof2D_Q1122_30"))->Fill(cent, sampleIndex, fQ1122_30); + histos.get(HIST("Prof2D_Q1122_31"))->Fill(cent, sampleIndex, fQ1122_31); + histos.get(HIST("Prof2D_Q1122_40"))->Fill(cent, sampleIndex, fQ1122_40); + histos.get(HIST("Prof2D_Q1122_41"))->Fill(cent, sampleIndex, fQ1122_41); + histos.get(HIST("Prof2D_Q2211_11"))->Fill(cent, sampleIndex, fQ2211_11); + histos.get(HIST("Prof2D_Q2211_01"))->Fill(cent, sampleIndex, fQ2211_01); + histos.get(HIST("Prof2D_Q2211_10"))->Fill(cent, sampleIndex, fQ2211_10); + histos.get(HIST("Prof2D_Q2211_20"))->Fill(cent, sampleIndex, fQ2211_20); + histos.get(HIST("Prof2D_Q2211_21"))->Fill(cent, sampleIndex, fQ2211_21); + histos.get(HIST("Prof2D_Q2111_11"))->Fill(cent, sampleIndex, fQ2111_11); + histos.get(HIST("Prof2D_Q2111_01"))->Fill(cent, sampleIndex, fQ2111_01); + histos.get(HIST("Prof2D_Q2111_10"))->Fill(cent, sampleIndex, fQ2111_10); + histos.get(HIST("Prof2D_Q2111_20"))->Fill(cent, sampleIndex, fQ2111_20); + histos.get(HIST("Prof2D_Q2111_21"))->Fill(cent, sampleIndex, fQ2111_21); + histos.get(HIST("Prof2D_Q112122_001"))->Fill(cent, sampleIndex, fQ112122_001); + histos.get(HIST("Prof2D_Q112122_010"))->Fill(cent, sampleIndex, fQ112122_010); + histos.get(HIST("Prof2D_Q112122_100"))->Fill(cent, sampleIndex, fQ112122_100); + histos.get(HIST("Prof2D_Q112122_011"))->Fill(cent, sampleIndex, fQ112122_011); + histos.get(HIST("Prof2D_Q112122_101"))->Fill(cent, sampleIndex, fQ112122_101); + histos.get(HIST("Prof2D_Q112122_110"))->Fill(cent, sampleIndex, fQ112122_110); + histos.get(HIST("Prof2D_Q1141_11"))->Fill(cent, sampleIndex, fQ1141_11); + histos.get(HIST("Prof2D_Q1141_01"))->Fill(cent, sampleIndex, fQ1141_01); + histos.get(HIST("Prof2D_Q1141_10"))->Fill(cent, sampleIndex, fQ1141_10); + histos.get(HIST("Prof2D_Q1141_20"))->Fill(cent, sampleIndex, fQ1141_20); + histos.get(HIST("Prof2D_Q1141_21"))->Fill(cent, sampleIndex, fQ1141_21); + histos.get(HIST("Prof2D_Q1142_11"))->Fill(cent, sampleIndex, fQ1142_11); + histos.get(HIST("Prof2D_Q1142_01"))->Fill(cent, sampleIndex, fQ1142_01); + histos.get(HIST("Prof2D_Q1142_10"))->Fill(cent, sampleIndex, fQ1142_10); + histos.get(HIST("Prof2D_Q1142_20"))->Fill(cent, sampleIndex, fQ1142_20); + histos.get(HIST("Prof2D_Q1142_21"))->Fill(cent, sampleIndex, fQ1142_21); + histos.get(HIST("Prof2D_Q1143_11"))->Fill(cent, sampleIndex, fQ1143_11); + histos.get(HIST("Prof2D_Q1143_01"))->Fill(cent, sampleIndex, fQ1143_01); + histos.get(HIST("Prof2D_Q1143_10"))->Fill(cent, sampleIndex, fQ1143_10); + histos.get(HIST("Prof2D_Q1143_20"))->Fill(cent, sampleIndex, fQ1143_20); + histos.get(HIST("Prof2D_Q1143_21"))->Fill(cent, sampleIndex, fQ1143_21); + histos.get(HIST("Prof2D_Q1144_11"))->Fill(cent, sampleIndex, fQ1144_11); + histos.get(HIST("Prof2D_Q1144_01"))->Fill(cent, sampleIndex, fQ1144_01); + histos.get(HIST("Prof2D_Q1144_10"))->Fill(cent, sampleIndex, fQ1144_10); + histos.get(HIST("Prof2D_Q1144_20"))->Fill(cent, sampleIndex, fQ1144_20); + histos.get(HIST("Prof2D_Q1144_21"))->Fill(cent, sampleIndex, fQ1144_21); + histos.get(HIST("Prof2D_Q2131_11"))->Fill(cent, sampleIndex, fQ2131_11); + histos.get(HIST("Prof2D_Q2131_01"))->Fill(cent, sampleIndex, fQ2131_01); + histos.get(HIST("Prof2D_Q2131_10"))->Fill(cent, sampleIndex, fQ2131_10); + histos.get(HIST("Prof2D_Q2132_11"))->Fill(cent, sampleIndex, fQ2132_11); + histos.get(HIST("Prof2D_Q2132_01"))->Fill(cent, sampleIndex, fQ2132_01); + histos.get(HIST("Prof2D_Q2132_10"))->Fill(cent, sampleIndex, fQ2132_10); + histos.get(HIST("Prof2D_Q2133_11"))->Fill(cent, sampleIndex, fQ2133_11); + histos.get(HIST("Prof2D_Q2133_01"))->Fill(cent, sampleIndex, fQ2133_01); + histos.get(HIST("Prof2D_Q2133_10"))->Fill(cent, sampleIndex, fQ2133_10); + histos.get(HIST("Prof2D_Q2231_11"))->Fill(cent, sampleIndex, fQ2231_11); + histos.get(HIST("Prof2D_Q2231_01"))->Fill(cent, sampleIndex, fQ2231_01); + histos.get(HIST("Prof2D_Q2231_10"))->Fill(cent, sampleIndex, fQ2231_10); + histos.get(HIST("Prof2D_Q2232_11"))->Fill(cent, sampleIndex, fQ2232_11); + histos.get(HIST("Prof2D_Q2232_01"))->Fill(cent, sampleIndex, fQ2232_01); + histos.get(HIST("Prof2D_Q2232_10"))->Fill(cent, sampleIndex, fQ2232_10); + histos.get(HIST("Prof2D_Q2233_11"))->Fill(cent, sampleIndex, fQ2233_11); + histos.get(HIST("Prof2D_Q2233_01"))->Fill(cent, sampleIndex, fQ2233_01); + histos.get(HIST("Prof2D_Q2233_10"))->Fill(cent, sampleIndex, fQ2233_10); + histos.get(HIST("Prof2D_Q51_1"))->Fill(cent, sampleIndex, fQ51_1); + histos.get(HIST("Prof2D_Q52_1"))->Fill(cent, sampleIndex, fQ52_1); + histos.get(HIST("Prof2D_Q53_1"))->Fill(cent, sampleIndex, fQ53_1); + histos.get(HIST("Prof2D_Q54_1"))->Fill(cent, sampleIndex, fQ54_1); + histos.get(HIST("Prof2D_Q55_1"))->Fill(cent, sampleIndex, fQ55_1); + histos.get(HIST("Prof2D_Q21_3"))->Fill(cent, sampleIndex, fQ21_3); + histos.get(HIST("Prof2D_Q22_3"))->Fill(cent, sampleIndex, fQ22_3); + histos.get(HIST("Prof2D_Q31_2"))->Fill(cent, sampleIndex, fQ31_2); + histos.get(HIST("Prof2D_Q32_2"))->Fill(cent, sampleIndex, fQ32_2); + histos.get(HIST("Prof2D_Q33_2"))->Fill(cent, sampleIndex, fQ33_2); + histos.get(HIST("Prof2D_Q61_1"))->Fill(cent, sampleIndex, fQ61_1); + histos.get(HIST("Prof2D_Q62_1"))->Fill(cent, sampleIndex, fQ62_1); + histos.get(HIST("Prof2D_Q63_1"))->Fill(cent, sampleIndex, fQ63_1); + histos.get(HIST("Prof2D_Q64_1"))->Fill(cent, sampleIndex, fQ64_1); + histos.get(HIST("Prof2D_Q65_1"))->Fill(cent, sampleIndex, fQ65_1); + histos.get(HIST("Prof2D_Q66_1"))->Fill(cent, sampleIndex, fQ66_1); + histos.get(HIST("Prof2D_Q112122_111"))->Fill(cent, sampleIndex, fQ112122_111); + histos.get(HIST("Prof2D_Q112131_111"))->Fill(cent, sampleIndex, fQ112131_111); + histos.get(HIST("Prof2D_Q112132_111"))->Fill(cent, sampleIndex, fQ112132_111); + histos.get(HIST("Prof2D_Q112133_111"))->Fill(cent, sampleIndex, fQ112133_111); + histos.get(HIST("Prof2D_Q112231_111"))->Fill(cent, sampleIndex, fQ112231_111); + histos.get(HIST("Prof2D_Q112232_111"))->Fill(cent, sampleIndex, fQ112232_111); + histos.get(HIST("Prof2D_Q112233_111"))->Fill(cent, sampleIndex, fQ112233_111); + histos.get(HIST("Prof2D_Q112221_111"))->Fill(cent, sampleIndex, fQ112221_111); + } + } + PROCESS_SWITCH(NetProtCumulants, processDataRec, "Process real data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx index 916fabd1213..eb5ec1866a7 100644 --- a/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/partNumFluc.cxx @@ -21,33 +21,38 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include +#include #include #include -#include +#include #include #include #include #include -#include +#include #include #include -#include +#include #include +#include #include #include #include +#include #include #include @@ -59,11 +64,11 @@ namespace o2 { namespace aod { -using JoinedCollisions = soa::Join; +using JoinedCollisions = soa::Join; using JoinedTracks = soa::Join; -using JoinedCollisionsWithMc = soa::Join; +using JoinedCollisionsWithMc = soa::Join; using JoinedTracksWithMc = soa::Join; -using JoinedMcCollisions = soa::Join; +using JoinedMcCollisions = soa::Join; } // namespace aod } // namespace o2 @@ -445,263 +450,281 @@ class FluctuationCalculatorTrack std::array mQs; }; -struct HolderCcdb { - std::vector runNumbers; - std::vector runNumbersBad; - - TH3* hCentralityPtEtaShiftTpcNSigmaPiP = nullptr; - TH3* hCentralityPtEtaShiftTpcNSigmaPiM = nullptr; - TH3* hCentralityPtEtaShiftTpcNSigmaKaP = nullptr; - TH3* hCentralityPtEtaShiftTpcNSigmaKaM = nullptr; - TH3* hCentralityPtEtaShiftTpcNSigmaPrP = nullptr; - TH3* hCentralityPtEtaShiftTpcNSigmaPrM = nullptr; - TH3* hCentralityPtEtaShiftTofNSigmaPiP = nullptr; - TH3* hCentralityPtEtaShiftTofNSigmaPiM = nullptr; - TH3* hCentralityPtEtaShiftTofNSigmaKaP = nullptr; - TH3* hCentralityPtEtaShiftTofNSigmaKaM = nullptr; - TH3* hCentralityPtEtaShiftTofNSigmaPrP = nullptr; - TH3* hCentralityPtEtaShiftTofNSigmaPrM = nullptr; - - std::vector pCentralityPtEtaEfficiencyTpcPiP; - std::vector pCentralityPtEtaEfficiencyTpcPiM; - std::vector pCentralityPtEtaEfficiencyTpcKaP; - std::vector pCentralityPtEtaEfficiencyTpcKaM; - std::vector pCentralityPtEtaEfficiencyTpcPrP; - std::vector pCentralityPtEtaEfficiencyTpcPrM; - std::vector pCentralityPtEtaEfficiencyTpcTofPiP; - std::vector pCentralityPtEtaEfficiencyTpcTofPiM; - std::vector pCentralityPtEtaEfficiencyTpcTofKaP; - std::vector pCentralityPtEtaEfficiencyTpcTofKaM; - std::vector pCentralityPtEtaEfficiencyTpcTofPrP; - std::vector pCentralityPtEtaEfficiencyTpcTofPrM; -}; - -struct HolderEvent { - std::int32_t runNumber = 0; - std::int32_t runIndex = 0; - double vz = 0.; - std::int32_t vzBinIndex = 0; - std::int32_t nGlobalTracks = 0; - std::int32_t nPvContributors = 0; - double meanDcaXy = 0.; - double meanSquareDcaXy = 0.; - double meanDcaZ = 0.; - double meanSquareDcaZ = 0.; - std::int32_t nTofBeta = 0; - double centrality = 0.; - std::int32_t subgroupIndex = 0; - std::int32_t nChPMc = 0; - std::int32_t nChMMc = 0; - std::int32_t nKaPMc = 0; - std::int32_t nKaMMc = 0; - std::int32_t nPrPMc = 0; - std::int32_t nPrMMc = 0; - std::int32_t nChP = 0; - std::int32_t nChM = 0; - std::int32_t nKaP = 0; - std::int32_t nKaM = 0; - std::int32_t nPrP = 0; - std::int32_t nPrM = 0; - std::vector mcParticleIndicesMatchedTpcPiP; - std::vector mcParticleIndicesMatchedTpcPiM; - std::vector mcParticleIndicesMatchedTpcKaP; - std::vector mcParticleIndicesMatchedTpcKaM; - std::vector mcParticleIndicesMatchedTpcPrP; - std::vector mcParticleIndicesMatchedTpcPrM; - std::vector mcParticleIndicesMatchedTpcTofPiP; - std::vector mcParticleIndicesMatchedTpcTofPiM; - std::vector mcParticleIndicesMatchedTpcTofKaP; - std::vector mcParticleIndicesMatchedTpcTofKaM; - std::vector mcParticleIndicesMatchedTpcTofPrP; - std::vector mcParticleIndicesMatchedTpcTofPrM; - - void clear() - { - runNumber = 0; - runIndex = 0; - vz = 0.; - vzBinIndex = 0; - nGlobalTracks = 0; - nPvContributors = 0; - meanDcaXy = 0.; - meanSquareDcaXy = 0.; - meanDcaZ = 0.; - meanSquareDcaZ = 0.; - nTofBeta = 0; - centrality = 0.; - subgroupIndex = 0; - nChPMc = 0; - nChMMc = 0; - nKaPMc = 0; - nKaMMc = 0; - nPrPMc = 0; - nPrMMc = 0; - nChP = 0; - nChM = 0; - nKaP = 0; - nKaM = 0; - nPrP = 0; - nPrM = 0; - mcParticleIndicesMatchedTpcPiP.clear(); - mcParticleIndicesMatchedTpcPiM.clear(); - mcParticleIndicesMatchedTpcKaP.clear(); - mcParticleIndicesMatchedTpcKaM.clear(); - mcParticleIndicesMatchedTpcPrP.clear(); - mcParticleIndicesMatchedTpcPrM.clear(); - mcParticleIndicesMatchedTpcTofPiP.clear(); - mcParticleIndicesMatchedTpcTofPiM.clear(); - mcParticleIndicesMatchedTpcTofKaP.clear(); - mcParticleIndicesMatchedTpcTofKaM.clear(); - mcParticleIndicesMatchedTpcTofPrP.clear(); - mcParticleIndicesMatchedTpcTofPrM.clear(); - } -}; - -struct HolderTrack { - static constexpr double TruncationAbsNSigmaPid = 999.; - static constexpr double truncateNSigmaPid(const double value) { return (!(std::abs(value) < TruncationAbsNSigmaPid) ? -TruncationAbsNSigmaPid : value); } - - std::int32_t sign = 0; - double p = 0.; - double pt = 0.; - double eta = 0.; - double phi = 0.; - double pOverQ = 0.; - double ptOverQ = 0.; - double rapidityPi = 0.; - double rapidityKa = 0.; - double rapidityPr = 0.; - bool hasTpcPid = false; - double tpcNSigmaPi = 0.; - double tpcNSigmaKa = 0.; - double tpcNSigmaPr = 0.; - bool hasTofPid = false; - double tofNSigmaPi = 0.; - double tofNSigmaKa = 0.; - double tofNSigmaPr = 0.; - double tpcTofNSigmaPi = 0.; - double tpcTofNSigmaKa = 0.; - double tpcTofNSigmaPr = 0.; - std::int32_t mcParticleId = 0; - - void clear() - { - sign = 0; - p = 0.; - pt = 0.; - eta = 0.; - phi = 0.; - pOverQ = 0.; - ptOverQ = 0.; - rapidityPi = 0.; - rapidityKa = 0.; - rapidityPr = 0.; - hasTpcPid = false; - tpcNSigmaPi = 0.; - tpcNSigmaKa = 0.; - tpcNSigmaPr = 0.; - hasTofPid = false; - tofNSigmaPi = 0.; - tofNSigmaKa = 0.; - tofNSigmaPr = 0.; - tpcTofNSigmaPi = 0.; - tpcTofNSigmaKa = 0.; - tpcTofNSigmaPr = 0.; - mcParticleId = 0; - } -}; - -struct HolderMcParticle { - std::int32_t globalIndex = 0; - std::int32_t pdgCode = 0; - double pt = 0.; - double eta = 0.; - - void clear() - { - globalIndex = 0; - pdgCode = 0; - pt = 0.; - eta = 0.; - } -}; - struct PartNumFluc { - enum class CentralityDefinitionIndices { kFV0A = 0, - kFT0M, - kFT0A, - kFT0C, - kNIndices }; - - Configurable cfgCcdbUrl{"cfgCcdbUrl", "https://alice-ccdb.cern.ch", "Url of CCDB"}; - Configurable cfgCcdbPath{"cfgCcdbPath", "Users/f/fasi/test", "Path in CCDB"}; - - Configurable cfgFlagQaRun{"cfgFlagQaRun", false, "Run QA flag"}; - Configurable cfgFlagQaEvent{"cfgFlagQaEvent", false, "Event QA flag"}; - Configurable cfgFlagQaCentrality{"cfgFlagQaCentrality", false, "Centrality QA flag"}; - Configurable cfgFlagQaTrack{"cfgFlagQaTrack", false, "Track QA flag"}; - Configurable cfgFlagQaAcceptance{"cfgFlagQaAcceptance", false, "Acceptance QA flag"}; - Configurable cfgFlagQaPid{"cfgFlagQaPid", false, "PID QA flag"}; - Configurable cfgFlagCalculationPurityPi{"cfgFlagCalculationPurityPi", false, "Pion purity calculation flag"}; - Configurable cfgFlagCalculationPurityKa{"cfgFlagCalculationPurityKa", false, "Kaon purity calculation flag"}; - Configurable cfgFlagCalculationPurityPr{"cfgFlagCalculationPurityPr", false, "(Anti)proton purity calculation flag"}; - Configurable cfgFlagCalculationEfficiencyPi{"cfgFlagCalculationEfficiencyPi", false, "Pion efficiency calculation flag"}; - Configurable cfgFlagCalculationEfficiencyKa{"cfgFlagCalculationEfficiencyKa", false, "Kaon efficiency calculation flag"}; - Configurable cfgFlagCalculationEfficiencyPr{"cfgFlagCalculationEfficiencyPr", false, "(Anti)proton efficiency calculation flag"}; - Configurable cfgFlagCalculationFluctuationCh{"cfgFlagCalculationFluctuationCh", false, "Charge number fluctuation calculation flag"}; - Configurable cfgFlagCalculationFluctuationKa{"cfgFlagCalculationFluctuationKa", false, "Kaon number fluctuation calculation flag"}; - Configurable cfgFlagCalculationFluctuationPr{"cfgFlagCalculationFluctuationPr", false, "(Anti)proton number fluctuation calculation flag"}; - - Configurable cfgFlagRejectionRunBad{"cfgFlagRejectionRunBad", false, "Bad run rejection flag"}; - Configurable cfgFlagSelectionEvent{"cfgFlagSelectionEvent", 0b00000000001111110100000000000000000000000000000000ULL, "Event selection flag"}; - Configurable cfgCutMaxAbsVertexZ{"cfgCutMaxAbsVertexZ", 6., "Maximum absolute vertex z position (cm)"}; - Configurable cfgCutMinDeviationNPvContributors{"cfgCutMinDeviationNPvContributors", -4, "Minimum nPvContributors deviation from nGlobalTracks"}; - Configurable cfgIndexDefinitionCentrality{"cfgIndexDefinitionCentrality", 1, "Centrality definition index"}; - - Configurable cfgFlagPvContributor{"cfgFlagPvContributor", true, "Flag of requiring PV contributor"}; - Configurable cfgCutMinItsNCls{"cfgCutMinItsNCls", 5, "Minimum number of clusters ITS"}; - Configurable cfgCutMaxItsChi2NCls{"cfgCutMaxItsChi2NCls", 30., "Maximum chi2 per cluster ITS"}; - Configurable cfgCutMinTpcNCls{"cfgCutMinTpcNCls", 55, "Minimum number of clusters TPC"}; // 50, 60 - Configurable cfgCutMaxTpcChi2NCls{"cfgCutMaxTpcChi2NCls", 3.5, "Maximum chi2 per cluster TPC"}; // 3., 4. - Configurable cfgCutMaxTpcNClsSharedRatio{"cfgCutMaxTpcNClsSharedRatio", 0.2, "Maximum ratio of shared clusters over clusters TPC"}; - Configurable cfgCutMinTpcNClsCrossedRows{"cfgCutMinTpcNClsCrossedRows", 75, "Minimum number of crossed rows TPC"}; // 70, 80 - Configurable cfgCutMinTpcNClsCrossedRowsRatio{"cfgCutMinTpcNClsCrossedRowsRatio", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; - Configurable> cfgParSigmaDcaXy{"cfgParSigmaDcaXy", {0.0015, 0.005, 1.1}, "Parameters of sigma of DCAxy (cm) in [0]+[1]*pt^[2]"}; - Configurable cfgCutMaxAbsNSigmaDcaXy{"cfgCutMaxAbsNSigmaDcaXy", 6., "Maximum absolute nSigma of DCAxy (cm)"}; // 5., 7. - Configurable cfgCutMaxAbsDcaZ{"cfgCutMaxAbsDcaZ", 0.2, "Maximum absolute DCAz (cm)"}; // 0.15, 0.25 - Configurable cfgCutMinPt{"cfgCutMinPt", 0.4, "Minimum pT (GeV/c)"}; - Configurable cfgCutMaxPt{"cfgCutMaxPt", 2., "Maximum pT (GeV/c)"}; - Configurable cfgCutMaxAbsEta{"cfgCutMaxAbsEta", 0.8, "Maximum absolute eta"}; - Configurable cfgThresholdPtTofPi{"cfgThresholdPtTofPi", 0.5, "pT (GeV/c) threshold for TOF pions"}; - Configurable cfgThresholdPtTofKa{"cfgThresholdPtTofKa", 0.5, "pT (GeV/c) threshold for TOF kaons"}; - Configurable cfgThresholdPtTofPr{"cfgThresholdPtTofPr", 0.8, "pT (GeV/c) threshold for TOF (anti)protons"}; - Configurable cfgFlagRecalibrationNSigmaPi{"cfgFlagRecalibrationNSigmaPi", false, "nSigmaPi recalibration flag"}; - Configurable cfgFlagRecalibrationNSigmaKa{"cfgFlagRecalibrationNSigmaKa", false, "nSigmaKa recalibration flag"}; - Configurable cfgFlagRecalibrationNSigmaPr{"cfgFlagRecalibrationNSigmaPr", false, "nSigmaPr recalibration flag"}; - Configurable cfgCutMaxAbsNSigmaPid{"cfgCutMaxAbsNSigmaPid", 2., "Maximum absolute nSigma for PID"}; // 1.5, 2.5 - - Configurable cfgNCentralityBins{"cfgNCentralityBins", 20, "Number of centrality bins in fluctuation calculation"}; - Configurable cfgNSubgroups{"cfgNSubgroups", 20, "Number of subgroups in fluctuation calculation"}; - + enum class CentralityDefinition { kFt0a = 0, + kFt0c, + kFt0m, + kNDefinitions }; + enum class ParticleSpecies { kPi = 0, + kKa, + kPr, + kNSpecies }; + enum class PidStrategy { kTpc = 0, + kTof, + kTpcAndTof, + kTpcTof, + kNStrategies }; + + struct : ConfigurableGroup { + Configurable cfgCcdbUrl{"cfgCcdbUrl", "http://ccdb-test.cern.ch:8080", "Url of CCDB"}; + Configurable cfgCcdbPath{"cfgCcdbPath", "Users/f/fasi/test", "Path in CCDB"}; + Configurable cfgCcdbTimestampLatest{"cfgCcdbTimestampLatest", 0, "Latest timestamp in CCDB"}; + } groupCcdb; + + struct : ConfigurableGroup { + Configurable cfgFlagQaRun{"cfgFlagQaRun", false, "Run QA flag"}; + Configurable cfgFlagQaEvent{"cfgFlagQaEvent", false, "Event QA flag"}; + Configurable cfgFlagQaCentrality{"cfgFlagQaCentrality", false, "Centrality QA flag"}; + Configurable cfgFlagQaTrack{"cfgFlagQaTrack", false, "Track QA flag"}; + Configurable cfgFlagQaDca{"cfgFlagQaDca", false, "DCA QA flag"}; + Configurable cfgFlagQaAcceptance{"cfgFlagQaAcceptance", false, "Acceptance QA flag"}; + Configurable cfgFlagQaAcceptancePi{"cfgFlagQaAcceptancePi", false, "Pion acceptance QA flag"}; + Configurable cfgFlagQaAcceptanceKa{"cfgFlagQaAcceptanceKa", false, "Kaon acceptance QA flag"}; + Configurable cfgFlagQaAcceptancePr{"cfgFlagQaAcceptancePr", false, "(Anti)proton acceptance QA flag"}; + Configurable cfgFlagQaPhi{"cfgFlagQaPhi", false, "Phi QA flag"}; + Configurable cfgFlagQaPhiPi{"cfgFlagQaPhiPi", false, "Pion Phi QA flag"}; + Configurable cfgFlagQaPhiKa{"cfgFlagQaPhiKa", false, "Kaon Phi QA flag"}; + Configurable cfgFlagQaPhiPr{"cfgFlagQaPhiPr", false, "(Anti)proton Phi QA flag"}; + Configurable cfgFlagQaPid{"cfgFlagQaPid", false, "PID QA flag"}; + Configurable cfgFlagQaPidPi{"cfgFlagQaPidPi", false, "Pion PID QA flag"}; + Configurable cfgFlagQaPidKa{"cfgFlagQaPidKa", false, "Kaon PID QA flag"}; + Configurable cfgFlagQaPidPr{"cfgFlagQaPidPr", false, "(Anti)proton PID QA flag"}; + Configurable cfgFlagQaMc{"cfgFlagQaMc", false, "MC QA flag"}; + Configurable cfgFlagCalculationYieldPi{"cfgFlagCalculationYieldPi", false, "Pion yield calculation flag"}; + Configurable cfgFlagCalculationYieldKa{"cfgFlagCalculationYieldKa", false, "Kaon yield calculation flag"}; + Configurable cfgFlagCalculationYieldPr{"cfgFlagCalculationYieldPr", false, "(Anti)proton yield calculation flag"}; + Configurable cfgFlagCalculationPurityPi{"cfgFlagCalculationPurityPi", false, "Pion purity calculation flag"}; + Configurable cfgFlagCalculationPurityKa{"cfgFlagCalculationPurityKa", false, "Kaon purity calculation flag"}; + Configurable cfgFlagCalculationPurityPr{"cfgFlagCalculationPurityPr", false, "(Anti)proton purity calculation flag"}; + Configurable cfgFlagCalculationFractionPrimaryPi{"cfgFlagCalculationFractionPrimaryPi", false, "Pion primary fraction calculation flag"}; + Configurable cfgFlagCalculationFractionPrimaryKa{"cfgFlagCalculationFractionPrimaryKa", false, "Kaon primary fraction calculation flag"}; + Configurable cfgFlagCalculationFractionPrimaryPr{"cfgFlagCalculationFractionPrimaryPr", false, "(Anti)proton primary fraction calculation flag"}; + Configurable cfgFlagCalculationFluctuationCh{"cfgFlagCalculationFluctuationCh", false, "Charge number fluctuation calculation flag"}; + Configurable cfgFlagCalculationFluctuationKa{"cfgFlagCalculationFluctuationKa", false, "Kaon number fluctuation calculation flag"}; + Configurable cfgFlagCalculationFluctuationPr{"cfgFlagCalculationFluctuationPr", false, "(Anti)proton number fluctuation calculation flag"}; + } groupAnalysis; + + struct : ConfigurableGroup { + Configurable cfgFlagRejectionRunBad{"cfgFlagRejectionRunBad", true, "Bad run rejection flag"}; + Configurable cfgFlagRejectionRunBadMc{"cfgFlagRejectionRunBadMc", false, "MC bad run rejection flag"}; + Configurable cfgLabelFlagsRct{"cfgLabelFlagsRct", "CBT_hadronPID", "RCT flags label"}; + Configurable cfgBitsSelectionEvent{"cfgBitsSelectionEvent", 0b10000000001101000000000000000000000000000000000000ULL, "Event selection bits"}; + Configurable cfgFlagInelEvent{"cfgFlagInelEvent", true, "Flag of requiring inelastic event"}; + Configurable cfgFlagInelEventMc{"cfgFlagInelEventMc", false, "Flag of requiring inelastic MC event"}; + Configurable cfgCutMaxAbsVertexZ{"cfgCutMaxAbsVertexZ", 6., "Maximum absolute vertex z position (cm)"}; + Configurable cfgCutMaxAbsVertexZMc{"cfgCutMaxAbsVertexZMc", 999., "Maximum absolute MC vertex z position (cm) for MC"}; + Configurable cfgCutMinDeviationNPvContributors{"cfgCutMinDeviationNPvContributors", -4, "Minimum nPvContributors deviation from nGlobalTracks"}; + Configurable cfgIndexDefinitionCentrality{"cfgIndexDefinitionCentrality", 2, "Centrality definition index"}; + ConfigurableAxis cfgAxisCentrality{"cfgAxisCentrality", {VARIABLE_WIDTH, 0., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 90.}, "Centrality axis in fluctuation calculation"}; + Configurable cfgNSubgroups{"cfgNSubgroups", 20, "Number of subgroups in fluctuation calculation"}; + } groupEvent; + + struct : ConfigurableGroup { + Configurable cfgFlagPvContributor{"cfgFlagPvContributor", true, "Flag of requiring PV contributor"}; + Configurable cfgCutMinItsNCls{"cfgCutMinItsNCls", 5, "Minimum number of clusters ITS"}; + Configurable cfgCutMaxItsChi2NCls{"cfgCutMaxItsChi2NCls", 30., "Maximum chi2 per cluster ITS"}; + Configurable cfgCutMinTpcNCls{"cfgCutMinTpcNCls", 55, "Minimum number of clusters TPC"}; + Configurable cfgCutMaxTpcChi2NCls{"cfgCutMaxTpcChi2NCls", 3.5, "Maximum chi2 per cluster TPC"}; + Configurable cfgCutMaxTpcNClsSharedRatio{"cfgCutMaxTpcNClsSharedRatio", 0.25, "Maximum ratio of shared clusters over clusters TPC"}; + Configurable cfgCutMinTpcNCrossedRows{"cfgCutMinTpcNCrossedRows", 75, "Minimum number of crossed rows TPC"}; + Configurable cfgCutMinTpcNCrossedRowsRatio{"cfgCutMinTpcNCrossedRowsRatio", 0.8, "Minimum ratio of crossed rows over findable clusters TPC"}; + Configurable cfgFlagRecalibrationDca{"cfgFlagRecalibrationDca", false, "DCA recalibration flag"}; + Configurable cfgCutMaxAbsNSigmaDcaXy{"cfgCutMaxAbsNSigmaDcaXy", 2.5, "Maximum absolute nSigma of DCAxy (cm)"}; + Configurable cfgCutMaxAbsNSigmaDcaZ{"cfgCutMaxAbsNSigmaDcaZ", 2.5, "Maximum absolute nSigma of DCAz (cm)"}; + Configurable cfgCutMinPt{"cfgCutMinPt", 0.4, "Minimum pT (GeV/c)"}; + Configurable cfgCutMaxPt{"cfgCutMaxPt", 2., "Maximum pT (GeV/c)"}; + Configurable cfgCutMaxAbsEta{"cfgCutMaxAbsEta", 0.8, "Maximum absolute eta"}; + Configurable cfgThresholdPtTofPi{"cfgThresholdPtTofPi", 0.5, "pT (GeV/c) threshold for TOF pions"}; + Configurable cfgThresholdPtTofKa{"cfgThresholdPtTofKa", 0.5, "pT (GeV/c) threshold for TOF kaons"}; + Configurable cfgThresholdPtTofPr{"cfgThresholdPtTofPr", 0.8, "pT (GeV/c) threshold for TOF (anti)protons"}; + Configurable cfgFlagRecalibrationNSigmaPi{"cfgFlagRecalibrationNSigmaPi", false, "nSigmaPi recalibration flag"}; + Configurable cfgFlagRecalibrationNSigmaKa{"cfgFlagRecalibrationNSigmaKa", false, "nSigmaKa recalibration flag"}; + Configurable cfgFlagRecalibrationNSigmaPr{"cfgFlagRecalibrationNSigmaPr", false, "nSigmaPr recalibration flag"}; + Configurable cfgFlagRejectionOthers{"cfgFlagRejectionOthers", false, "Other particle species rejection flag"}; + Configurable cfgCutMaxAbsNSigmaPid{"cfgCutMaxAbsNSigmaPid", 2., "Maximum absolute nSigma for PID"}; + Configurable cfgFlagMcParticlePhysicalPrimary{"cfgFlagMcParticlePhysicalPrimary", true, "Flag of requiring physical primary MC particle"}; + Configurable cfgFlagMcParticleMomentum{"cfgFlagMcParticleMomentum", true, "Flag of using momentum of MC particle"}; + } groupTrack; + + aod::rctsel::RCTFlagsChecker rctFlagsChecker; + + Service pdg; Service ccdb; - HolderCcdb holderCcdb; - HolderEvent holderEvent; - HolderTrack holderTrack; - HolderMcParticle holderMcParticle; - - std::vector> pCentralityPtEtaEfficiencyTpcPiP; - std::vector> pCentralityPtEtaEfficiencyTpcPiM; - std::vector> pCentralityPtEtaEfficiencyTpcKaP; - std::vector> pCentralityPtEtaEfficiencyTpcKaM; - std::vector> pCentralityPtEtaEfficiencyTpcPrP; - std::vector> pCentralityPtEtaEfficiencyTpcPrM; - std::vector> pCentralityPtEtaEfficiencyTpcTofPiP; - std::vector> pCentralityPtEtaEfficiencyTpcTofPiM; - std::vector> pCentralityPtEtaEfficiencyTpcTofKaP; - std::vector> pCentralityPtEtaEfficiencyTpcTofKaM; - std::vector> pCentralityPtEtaEfficiencyTpcTofPrP; - std::vector> pCentralityPtEtaEfficiencyTpcTofPrM; + struct HolderCcdb { + std::map> runNumbersIndicesGroupIndices; + + std::vector fPtMeanDcaXyP; + std::vector fPtMeanDcaXyM; + std::vector fPtMeanDcaZP; + std::vector fPtMeanDcaZM; + std::vector fPtSigmaDcaXyP; + std::vector fPtSigmaDcaXyM; + std::vector fPtSigmaDcaZP; + std::vector fPtSigmaDcaZM; + + std::vector hCentralityPtEtaShiftTpcNSigmaPiP; + std::vector hCentralityPtEtaShiftTpcNSigmaPiM; + std::vector hCentralityPtEtaShiftTpcNSigmaKaP; + std::vector hCentralityPtEtaShiftTpcNSigmaKaM; + std::vector hCentralityPtEtaShiftTpcNSigmaPrP; + std::vector hCentralityPtEtaShiftTpcNSigmaPrM; + std::vector hCentralityPtEtaShiftTofNSigmaPiP; + std::vector hCentralityPtEtaShiftTofNSigmaPiM; + std::vector hCentralityPtEtaShiftTofNSigmaKaP; + std::vector hCentralityPtEtaShiftTofNSigmaKaM; + std::vector hCentralityPtEtaShiftTofNSigmaPrP; + std::vector hCentralityPtEtaShiftTofNSigmaPrM; + + std::vector hVzCentralityPtEtaEfficiencyTpcPiP; + std::vector hVzCentralityPtEtaEfficiencyTpcPiM; + std::vector hVzCentralityPtEtaEfficiencyTpcKaP; + std::vector hVzCentralityPtEtaEfficiencyTpcKaM; + std::vector hVzCentralityPtEtaEfficiencyTpcPrP; + std::vector hVzCentralityPtEtaEfficiencyTpcPrM; + std::vector hVzCentralityPtEtaEfficiencyTpcTofPiP; + std::vector hVzCentralityPtEtaEfficiencyTpcTofPiM; + std::vector hVzCentralityPtEtaEfficiencyTpcTofKaP; + std::vector hVzCentralityPtEtaEfficiencyTpcTofKaM; + std::vector hVzCentralityPtEtaEfficiencyTpcTofPrP; + std::vector hVzCentralityPtEtaEfficiencyTpcTofPrM; + + void clear() + { + runNumbersIndicesGroupIndices.clear(); + + fPtMeanDcaXyP.clear(); + fPtMeanDcaXyM.clear(); + fPtMeanDcaZP.clear(); + fPtMeanDcaZM.clear(); + fPtSigmaDcaXyP.clear(); + fPtSigmaDcaXyM.clear(); + fPtSigmaDcaZP.clear(); + fPtSigmaDcaZM.clear(); + + hCentralityPtEtaShiftTpcNSigmaPiP.clear(); + hCentralityPtEtaShiftTpcNSigmaPiM.clear(); + hCentralityPtEtaShiftTpcNSigmaKaP.clear(); + hCentralityPtEtaShiftTpcNSigmaKaM.clear(); + hCentralityPtEtaShiftTpcNSigmaPrP.clear(); + hCentralityPtEtaShiftTpcNSigmaPrM.clear(); + hCentralityPtEtaShiftTofNSigmaPiP.clear(); + hCentralityPtEtaShiftTofNSigmaPiM.clear(); + hCentralityPtEtaShiftTofNSigmaKaP.clear(); + hCentralityPtEtaShiftTofNSigmaKaM.clear(); + hCentralityPtEtaShiftTofNSigmaPrP.clear(); + hCentralityPtEtaShiftTofNSigmaPrM.clear(); + + hVzCentralityPtEtaEfficiencyTpcPiP.clear(); + hVzCentralityPtEtaEfficiencyTpcPiM.clear(); + hVzCentralityPtEtaEfficiencyTpcKaP.clear(); + hVzCentralityPtEtaEfficiencyTpcKaM.clear(); + hVzCentralityPtEtaEfficiencyTpcPrP.clear(); + hVzCentralityPtEtaEfficiencyTpcPrM.clear(); + hVzCentralityPtEtaEfficiencyTpcTofPiP.clear(); + hVzCentralityPtEtaEfficiencyTpcTofPiM.clear(); + hVzCentralityPtEtaEfficiencyTpcTofKaP.clear(); + hVzCentralityPtEtaEfficiencyTpcTofKaM.clear(); + hVzCentralityPtEtaEfficiencyTpcTofPrP.clear(); + hVzCentralityPtEtaEfficiencyTpcTofPrM.clear(); + } + } holderCcdb; + + struct HolderMcEvent { + std::int32_t runNumber{}; + std::int32_t runIndex{}; + std::int32_t runGroupIndex{}; + double vz{}; + std::int32_t nChP{}; + std::int32_t nChM{}; + std::int32_t nKaP{}; + std::int32_t nKaM{}; + std::int32_t nPrP{}; + std::int32_t nPrM{}; + + void clear() + { + *this = {}; + } + } holderMcEvent; + + struct HolderEvent { + static constexpr std::pair RangeCentrality = {0., 100.}; + + std::int32_t runNumber{}; + std::int32_t runIndex{}; + std::int32_t runGroupIndex{}; + double vz{}; + std::int32_t nGlobalTracksP{}; + std::int32_t nGlobalTracksM{}; + std::int32_t nPvContributorsP{}; + std::int32_t nPvContributorsM{}; + double meanDcaXyP{}; + double meanDcaXyM{}; + double meanSquareDcaXyP{}; + double meanSquareDcaXyM{}; + double meanDcaZP{}; + double meanDcaZM{}; + double meanSquareDcaZP{}; + double meanSquareDcaZM{}; + std::int32_t nTofBetaP{}; + std::int32_t nTofBetaM{}; + double centrality{}; + std::int32_t subgroupIndex{}; + std::int32_t nChP{}; + std::int32_t nChM{}; + std::int32_t nKaP{}; + std::int32_t nKaM{}; + std::int32_t nPrP{}; + std::int32_t nPrM{}; + + void clear() + { + *this = {}; + } + } holderEvent; + + struct HolderMcParticle { + std::int32_t pdgCode{}; + std::int32_t charge{}; + double pt{}; + double eta{}; + double phi{}; + + void clear() + { + *this = {}; + } + } holderMcParticle; + + struct HolderTrack { + static constexpr double TruncationAbsNSigmaPid = 999.; + static constexpr double truncateNSigmaPid(const double value) { return (!(std::abs(value) < TruncationAbsNSigmaPid) ? -TruncationAbsNSigmaPid : value); } + + double dcaXY{}; + double dcaZ{}; + std::int32_t sign{}; + double p{}; + double pt{}; + double eta{}; + double phi{}; + bool hasTpcPid{}; + double tpcNSigmaPi{}; + double tpcNSigmaKa{}; + double tpcNSigmaPr{}; + bool hasTofPid{}; + double tofNSigmaPi{}; + double tofNSigmaKa{}; + double tofNSigmaPr{}; + double tpcTofNSigmaPi{}; + double tpcTofNSigmaKa{}; + double tpcTofNSigmaPr{}; + + void clear() + { + *this = {}; + } + } holderTrack; std::unique_ptr fluctuationCalculatorTrackChP; std::unique_ptr fluctuationCalculatorTrackChM; @@ -717,10 +740,14 @@ struct PartNumFluc { std::unique_ptr fluctuationCalculatorTrackPrN; HistogramRegistry hrCalculationFluctuation{"hrCalculationFluctuation", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry hrCalculationEfficiency{"hrCalculationEfficiency", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hrCalculationFractionPrimary{"hrCalculationFractionPrimary", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrCalculationPurity{"hrCalculationPurity", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry hrQaAcceptance{"hrQaAcceptance", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hrCalculationYield{"hrCalculationYield", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hrQaMc{"hrQaMc", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrQaPid{"hrQaPid", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hrQaPhi{"hrQaPhi", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hrQaAcceptance{"hrQaAcceptance", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hrQaDca{"hrQaDca", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrQaTrack{"hrQaTrack", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrQaCentrality{"hrQaCentrality", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hrQaEvent{"hrQaEvent", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -728,8 +755,8 @@ struct PartNumFluc { HistogramRegistry hrCounter{"hrCounter", {}, OutputObjHandlingPolicy::AnalysisObject}; Filter filterCollision = (aod::evsel::sel8 == true); - Filter filterfTrack = requireGlobalTrackWoPtEtaInFilter(); - Filter filterfMcCollision = (aod::mccollisionprop::numRecoCollision > 0); + Filter filterTrack = requireQualityTracksInFilter(); + Filter filterMcCollision = (aod::mccollisionprop::numRecoCollision > 0); Preslice presliceTracksPerCollision = aod::track::collisionId; @@ -737,424 +764,689 @@ struct PartNumFluc { { gRandom->SetSeed(0); - assert(doprocessRaw.value ^ doprocessMc.value); + if (doprocessRaw.value == doprocessMc.value) { + LOG(fatal) << "Identical doprocessRaw and doprocessMc!"; + } if (doprocessRaw.value) { LOG(info) << "Enabling raw data process."; } else if (doprocessMc.value) { LOG(info) << "Enabling MC data process."; } - ccdb->setURL(cfgCcdbUrl.value); + if (!groupEvent.cfgLabelFlagsRct.value.empty()) { + rctFlagsChecker.init(groupEvent.cfgLabelFlagsRct.value, false, true, true); + } + + ccdb->setURL(groupCcdb.cfgCcdbUrl.value); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(true); + if (groupCcdb.cfgCcdbTimestampLatest.value >= 0) { + ccdb->setCreatedNotAfter(groupCcdb.cfgCcdbTimestampLatest.value > 0 ? groupCcdb.cfgCcdbTimestampLatest.value : std::chrono::time_point_cast(std::chrono::system_clock::now()).time_since_epoch().count()); + } - const TList* const ccdbObject = ccdb->getForTimeStamp(cfgCcdbPath.value, -1); - assert(ccdbObject && ccdbObject->IsA() == TList::Class()); + const TList* const ccdbObject = ccdb->getForTimeStamp(groupCcdb.cfgCcdbPath.value, -1); + if (!ccdbObject || ccdbObject->IsA() != TList::Class()) { + LOG(fatal) << "Invalid ccdb_object!"; + } - const TGraph* const gRunNumberIsBad = static_cast(ccdbObject->FindObject("gRunNumberIsBad")); - assert(gRunNumberIsBad && gRunNumberIsBad->IsA() == TGraph::Class()); - holderCcdb.runNumbers.reserve(gRunNumberIsBad->GetN()); - holderCcdb.runNumbersBad.reserve(gRunNumberIsBad->GetN()); - for (std::int32_t const& iRun : std::views::iota(0, gRunNumberIsBad->GetN())) { - holderCcdb.runNumbers.push_back(static_cast(std::llrint(gRunNumberIsBad->GetX()[iRun]))); - if (cfgFlagRejectionRunBad.value && gRunNumberIsBad->GetY()[iRun]) { - holderCcdb.runNumbersBad.push_back(static_cast(std::llrint(gRunNumberIsBad->GetX()[iRun]))); + const TGraph* const gRunNumberGroupIndex = dynamic_cast(ccdbObject->FindObject("gRunNumberGroupIndex")); + if (!gRunNumberGroupIndex || gRunNumberGroupIndex->IsA() != TGraph::Class()) { + LOG(fatal) << "Invalid gRunNumberGroupIndex!"; + } + holderCcdb.clear(); + std::int32_t nRunsBad = 0; + std::int32_t nRunGroups = 0; + for (std::int32_t const& iRun : std::views::iota(0, gRunNumberGroupIndex->GetN())) { + const std::int32_t runGroupIndex = std::llrint(gRunNumberGroupIndex->GetY()[iRun]); + if (runGroupIndex == 0 || (groupEvent.cfgFlagRejectionRunBad.value && runGroupIndex < 0)) { + nRunsBad++; } + nRunGroups = std::max(nRunGroups, std::abs(runGroupIndex)); + holderCcdb.runNumbersIndicesGroupIndices[std::llrint(gRunNumberGroupIndex->GetX()[iRun])] = std::pair(iRun, runGroupIndex); } - if (holderCcdb.runNumbers.empty()) { + if (holderCcdb.runNumbersIndicesGroupIndices.empty()) { LOG(info) << "No run process enabled."; } else { - LOG(info) << "Number of runs: " << holderCcdb.runNumbers.size(); - for (std::int32_t const& runNumber : holderCcdb.runNumbers) { - LOG(info) << "Enabling processing run: " << runNumber; + LOG(info) << "Number of runs: " << holderCcdb.runNumbersIndicesGroupIndices.size(); + for (const auto& [runNumber, runIndexGroupIndex] : holderCcdb.runNumbersIndicesGroupIndices) { + LOG(info) << "Enabling processing run: " << runNumber << " (" << std::abs(runIndexGroupIndex.second) << ")"; } } - if (holderCcdb.runNumbersBad.empty()) { + if (nRunsBad <= 0) { LOG(info) << "No run rejection enabled."; } else { - LOG(info) << "Number of bad runs: " << holderCcdb.runNumbersBad.size(); - for (std::int32_t const& runNumberBad : holderCcdb.runNumbersBad) { - LOG(info) << "Enabling rejecting run: " << runNumberBad; + LOG(info) << "Number of bad runs: " << nRunsBad; + for (const auto& [runNumber, runIndexGroupIndex] : holderCcdb.runNumbersIndicesGroupIndices) { + if (runIndexGroupIndex.second == 0 || (groupEvent.cfgFlagRejectionRunBad.value && runIndexGroupIndex.second < 0)) { + LOG(info) << "Enabling rejecting run: " << runNumber; + } } } - if ((cfgFlagSelectionEvent.value & ((1ULL << aod::evsel::EventSelectionFlags::kNsel) - 1)) == 0) { + if (groupEvent.cfgLabelFlagsRct.value.empty()) { + LOG(info) << "No RCT flags enabled."; + } else { + LOG(info) << "Enabling RCT flags label: " << groupEvent.cfgLabelFlagsRct.value; + } + + if ((groupEvent.cfgBitsSelectionEvent.value & ((1ULL << aod::evsel::EventSelectionFlags::kNsel) - 1)) == 0) { LOG(info) << "No event selection bit enabled."; } else { for (std::int32_t const& iEvSel : std::views::iota(0, aod::evsel::EventSelectionFlags::kNsel)) { - if ((cfgFlagSelectionEvent.value >> iEvSel) & 1) { + if ((groupEvent.cfgBitsSelectionEvent.value >> iEvSel) & 1) { LOG(info) << "Enabling event selection bit: " << aod::evsel::selectionLabels[iEvSel]; } } } - switch (cfgIndexDefinitionCentrality) { - default: - LOG(info) << "Enabling centrality definition: FV0A"; - break; - case static_cast(CentralityDefinitionIndices::kFT0M): - LOG(info) << "Enabling centrality definition: FT0M"; - break; - case static_cast(CentralityDefinitionIndices::kFT0A): + switch (groupEvent.cfgIndexDefinitionCentrality.value) { + case static_cast(CentralityDefinition::kFt0a): LOG(info) << "Enabling centrality definition: FT0A"; break; - case static_cast(CentralityDefinitionIndices::kFT0C): + case static_cast(CentralityDefinition::kFt0c): LOG(info) << "Enabling centrality definition: FT0C"; break; + default: + LOG(info) << "Enabling centrality definition: FT0M"; + break; + } + + const auto readListRunGroup = [&](const std::int32_t runGroupIndex) -> const TList* { + const std::string name = Form("lRunGroup_%d", runGroupIndex); + const TList* const lRunGroup = dynamic_cast(ccdbObject->FindObject(name.c_str())); + if (!lRunGroup || lRunGroup->IsA() != TList::Class()) { + LOG(fatal) << "Invalid " << name << "!"; + } + return lRunGroup; + }; + const auto readFormula = [&](const TList* const lRunGroup, const char* const nameBase, const bool doAddingSuffixMc, const std::int32_t runGroupIndex) -> const TFormula* { + const std::string name = Form("%s%s_runGroup%d", nameBase, doAddingSuffixMc ? "_mc" : "", runGroupIndex); + const TFormula* const formula = dynamic_cast(lRunGroup->FindObject(name.c_str())); + if (!formula || formula->IsA() != TFormula::Class()) { + LOG(fatal) << "Invalid " << name << "!"; + } + LOG(info) << "Reading from CCDB: " << formula->GetName() << " \"" << formula->GetExpFormula("clingp") << "\""; + return formula; + }; + const auto readH3 = [&](const TList* const lRunGroup, const char* const nameBase, const bool doAddingSuffixMc, const std::int32_t runGroupIndex) -> const TH3* { + const std::string name = Form("%s%s_runGroup%d", nameBase, doAddingSuffixMc ? "_mc" : "", runGroupIndex); + const TH3* const h3 = dynamic_cast(lRunGroup->FindObject(name.c_str())); + if (!h3 || !h3->InheritsFrom(TH3::Class())) { + LOG(fatal) << "Invalid " << name << "!"; + } + LOG(info) << "Reading from CCDB: " << h3->GetName(); + return h3; + }; + const auto readHn = [&](const TList* const lRunGroup, const char* const nameBase, const bool doAddingSuffixMc, const std::int32_t runGroupIndex, const std::int32_t nDimensions) -> const THnBase* { + const std::string name = Form("%s%s_runGroup%d", nameBase, doAddingSuffixMc ? "_mc" : "", runGroupIndex); + const THnBase* const hn = dynamic_cast(lRunGroup->FindObject(name.c_str())); + if (!hn || !hn->InheritsFrom(THnBase::Class()) || hn->GetNdimensions() != nDimensions) { + LOG(fatal) << "Invalid " << name << "!"; + } + LOG(info) << "Reading from CCDB: " << hn->GetName(); + return hn; + }; + + if (groupTrack.cfgFlagRecalibrationDca.value) { + LOG(info) << "Enabling DCA recalibration."; + + holderCcdb.fPtMeanDcaXyP.resize(nRunGroups); + holderCcdb.fPtMeanDcaXyM.resize(nRunGroups); + holderCcdb.fPtMeanDcaZP.resize(nRunGroups); + holderCcdb.fPtMeanDcaZM.resize(nRunGroups); + holderCcdb.fPtSigmaDcaXyP.resize(nRunGroups); + holderCcdb.fPtSigmaDcaXyM.resize(nRunGroups); + holderCcdb.fPtSigmaDcaZP.resize(nRunGroups); + holderCcdb.fPtSigmaDcaZM.resize(nRunGroups); + for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { + const TList* const lRunGroup = readListRunGroup(iRunGroup + 1); + holderCcdb.fPtMeanDcaXyP[iRunGroup] = readFormula(lRunGroup, "fPtMeanDcaXyP", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtMeanDcaXyM[iRunGroup] = readFormula(lRunGroup, "fPtMeanDcaXyM", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtMeanDcaZP[iRunGroup] = readFormula(lRunGroup, "fPtMeanDcaZP", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtMeanDcaZM[iRunGroup] = readFormula(lRunGroup, "fPtMeanDcaZM", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtSigmaDcaXyP[iRunGroup] = readFormula(lRunGroup, "fPtSigmaDcaXyP", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtSigmaDcaXyM[iRunGroup] = readFormula(lRunGroup, "fPtSigmaDcaXyM", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtSigmaDcaZP[iRunGroup] = readFormula(lRunGroup, "fPtSigmaDcaZP", doprocessMc.value, iRunGroup + 1); + holderCcdb.fPtSigmaDcaZM[iRunGroup] = readFormula(lRunGroup, "fPtSigmaDcaZM", doprocessMc.value, iRunGroup + 1); + } } - if (cfgFlagRecalibrationNSigmaPi.value) { - LOG(info) << "Enabling nSigmaPi recalibration."; - - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPiP%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP && holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP->GetName(); - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPiM%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM && holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPiP%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP && holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPiM%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM && holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM->GetName(); - } - - if (cfgFlagRecalibrationNSigmaKa.value) { - LOG(info) << "Enabling nSigmaKa recalibration."; - - holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaKaP%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP && holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP->GetName(); - holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaKaM%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM && holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTofNSigmaKaP%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP && holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTofNSigmaKaM%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM && holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM->GetName(); - } - - if (cfgFlagRecalibrationNSigmaPr.value) { - LOG(info) << "Enabling nSigmaPr recalibration."; - - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPrP%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP && holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP->GetName(); - holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTpcNSigmaPrM%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM && holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPrP%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP && holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP->GetName(); - holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM = static_cast(ccdbObject->FindObject(Form("hCentralityPtEtaShiftTofNSigmaPrM%s", doprocessMc.value ? "_mc" : ""))); - assert(holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM && holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM->InheritsFrom(TH3::Class())); - LOG(info) << "Reading from CCDB: " << holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM->GetName(); + if (groupTrack.cfgFlagRecalibrationNSigmaPi.value || groupTrack.cfgFlagRecalibrationNSigmaKa.value || groupTrack.cfgFlagRecalibrationNSigmaPr.value) { + const auto readH3ShiftNSigmaPid = [&](std::initializer_list*, const char*>> pairsVectorH3NameBase) { + for (const auto& [vectorH3, nameBase] : pairsVectorH3NameBase) { + vectorH3->resize(nRunGroups); + } + for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { + const TList* const lRunGroup = readListRunGroup(iRunGroup + 1); + for (const auto& [vectorH3, nameBase] : pairsVectorH3NameBase) { + (*vectorH3)[iRunGroup] = readH3(lRunGroup, nameBase, doprocessMc.value, iRunGroup + 1); + } + } + }; + + if (groupTrack.cfgFlagRecalibrationNSigmaPi.value) { + LOG(info) << "Enabling nSigmaPi recalibration."; + + readH3ShiftNSigmaPid({{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP, "hCentralityPtEtaShiftTpcNSigmaPiP"}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM, "hCentralityPtEtaShiftTpcNSigmaPiM"}, {&holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP, "hCentralityPtEtaShiftTofNSigmaPiP"}, {&holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM, "hCentralityPtEtaShiftTofNSigmaPiM"}}); + } + + if (groupTrack.cfgFlagRecalibrationNSigmaKa.value) { + LOG(info) << "Enabling nSigmaKa recalibration."; + + readH3ShiftNSigmaPid({{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP, "hCentralityPtEtaShiftTpcNSigmaKaP"}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM, "hCentralityPtEtaShiftTpcNSigmaKaM"}, {&holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP, "hCentralityPtEtaShiftTofNSigmaKaP"}, {&holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM, "hCentralityPtEtaShiftTofNSigmaKaM"}}); + } + + if (groupTrack.cfgFlagRecalibrationNSigmaPr.value) { + LOG(info) << "Enabling nSigmaPr recalibration."; + + readH3ShiftNSigmaPid({{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP, "hCentralityPtEtaShiftTpcNSigmaPrP"}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM, "hCentralityPtEtaShiftTpcNSigmaPrM"}, {&holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP, "hCentralityPtEtaShiftTofNSigmaPrP"}, {&holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM, "hCentralityPtEtaShiftTofNSigmaPrM"}}); + } } hrCounter.add("hNEvents", ";;No. of Events", {HistType::kTH1D, {{10 + aod::evsel::EventSelectionFlags::kNsel, -0.5, 9.5 + static_cast(aod::evsel::EventSelectionFlags::kNsel), "Selection"}}}); + if (doprocessMc.value) { + hrCounter.add("hNMcEvents", ";;No. of MC Events", {HistType::kTH1D, {{10, -0.5, 9.5, "Selection"}}}); + } - if (cfgFlagQaRun.value) { + if (groupAnalysis.cfgFlagQaRun.value) { LOG(info) << "Enabling run QA."; - HistogramConfigSpec hcsQaRun(HistType::kTProfile, {{static_cast(holderCcdb.runNumbers.size()), -0.5, holderCcdb.runNumbers.size() - 0.5, "Run Index"}}); + const HistogramConfigSpec hcsQaRun(HistType::kTProfile, {{static_cast(holderCcdb.runNumbersIndicesGroupIndices.size()), -0.5, holderCcdb.runNumbersIndicesGroupIndices.size() - 0.5, "Run Index"}}); + hrQaRun.add("QaRun/pRunIndexVx", ";;#LT#it{V}_{#it{x}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexVy", ";;#LT#it{V}_{#it{y}}#GT (cm)", hcsQaRun); hrQaRun.add("QaRun/pRunIndexVz", ";;#LT#it{V}_{#it{z}}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMultFv0a", ";;FV0A #LTMultiplicity#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMultFt0a", ";;FT0A #LTMultiplicity#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMultFt0c", ";;FT0C #LTMultiplicity#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexNGlobalTracks", ";;#LTnGlobalTracks#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexNPvContributors", ";;#LTnPvContributors#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMeanDcaXy", ";;#LT#LTDCA_{#it{xy}}#GT_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexSigmaDcaXy", ";;#LT#it{#sigma}(DCA_{#it{xy}})_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexMeanDcaZ", ";;#LT#LTDCA_{#it{z}}#GT_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexSigmaDcaZ", ";;#LT#it{#sigma}(DCA_{#it{z}})_{event}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexNTofBeta", ";;#LTnTofBeta#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexItsNCls", ";;ITS #LTnClusters#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexItsChi2NCls", ";;ITS #LT#it{#chi}^{2}/nClusters#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNCls", ";;TPC #LTnClusters#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcChi2NCls", ";;TPC #LT#it{#chi}^{2}/nClusters#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNClsSharedRatio", ";;TPC #LTnSharedClusters/nClusters#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNClsCrossedRows", ";;TPC #LTnCrossedRows#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNClsCrossedRowsRatio", ";;TPC #LTnCrossedRows/nFindableClusters#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexDcaXy", ";;#LTDCA_{#it{xy}}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexDcaZ", ";;#LTDCA_{#it{z}}#GT (cm)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexPt", ";;#LT#it{p}_{T}#GT (GeV/#it{c})", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexEta", ";;#LT#it{#eta}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexPhi", ";;#LT#it{#varphi}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcDeDx", ";;TPC #LTd#it{E}/d#it{x}#GT (a.u.)", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNSigmaPi", ";;TPC #LT#it{n}#it{#sigma}_{#pi}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNSigmaKa", ";;TPC #LT#it{n}#it{#sigma}_{K}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTpcNSigmaPr", ";;TPC #LT#it{n}#it{#sigma}_{p}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTofInverseBeta", ";;TOF #LT1/#it{#beta}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTofNSigmaPi", ";;TOF #LT#it{n}#it{#sigma}_{#pi}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTofNSigmaKa", ";;TOF #LT#it{n}#it{#sigma}_{K}#GT", hcsQaRun); - hrQaRun.add("QaRun/pRunIndexTofNSigmaPr", ";;TOF #LT#it{n}#it{#sigma}_{p}#GT", hcsQaRun); - } - - if (cfgFlagQaEvent.value) { + hrQaRun.add("QaRun/pRunIndexMultiplicityFt0a", ";;FT0A #LTMultiplicity#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMultiplicityFt0c", ";;FT0C #LTMultiplicity#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexCentralityFt0a", ";;FT0A #LTCentrality#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexCentralityFt0c", ";;FT0C #LTCentrality#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexCentralityFt0m", ";;FT0M #LTCentrality#GT", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNGlobalTracks_p", ";;#LTnGlobalTracks#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNGlobalTracks_m", ";;#LTnGlobalTracks#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNPvContributors_p", ";;#LTnPvContributors#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNPvContributors_m", ";;#LTnPvContributors#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaXy_p", ";;#LT#LTDCA_{#it{xy}}#GT_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaXy_m", ";;#LT#LTDCA_{#it{xy}}#GT_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaXy_p", ";;#LT#it{#sigma}(DCA_{#it{xy}})_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaXy_m", ";;#LT#it{#sigma}(DCA_{#it{xy}})_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaZ_p", ";;#LT#LTDCA_{#it{z}}#GT_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexMeanDcaZ_m", ";;#LT#LTDCA_{#it{z}}#GT_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaZ_p", ";;#LT#it{#sigma}(DCA_{#it{z}})_{event}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexSigmaDcaZ_m", ";;#LT#it{#sigma}(DCA_{#it{z}})_{event}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNTofBeta_p", ";;#LTnTofBeta#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexNTofBeta_m", ";;#LTnTofBeta#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexItsNCls_p", ";;ITS #LTnClusters#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexItsNCls_m", ";;ITS #LTnClusters#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexItsChi2NCls_p", ";;ITS #LT#it{#chi}^{2}/nClusters#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexItsChi2NCls_m", ";;ITS #LT#it{#chi}^{2}/nClusters#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNCls_p", ";;TPC #LTnClusters#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNCls_m", ";;TPC #LTnClusters#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcChi2NCls_p", ";;TPC #LT#it{#chi}^{2}/nClusters#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcChi2NCls_m", ";;TPC #LT#it{#chi}^{2}/nClusters#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNClsSharedRatio_p", ";;TPC #LTnSharedClusters/nClusters#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNClsSharedRatio_m", ";;TPC #LTnSharedClusters/nClusters#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNCrossedRows_p", ";;TPC #LTnCrossedRows#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNCrossedRows_m", ";;TPC #LTnCrossedRows#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNCrossedRowsRatio_p", ";;TPC #LTnCrossedRows/nFindableClusters#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNCrossedRowsRatio_m", ";;TPC #LTnCrossedRows/nFindableClusters#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexDcaXy_p", ";;#LTDCA_{#it{xy}}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexDcaXy_m", ";;#LTDCA_{#it{xy}}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexDcaZ_p", ";;#LTDCA_{#it{z}}#GT (cm) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexDcaZ_m", ";;#LTDCA_{#it{z}}#GT (cm) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexPt_p", ";;#LT#it{p}_{T}#GT (GeV/#it{c}) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexPt_m", ";;#LT#it{p}_{T}#GT (GeV/#it{c}) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexEta_p", ";;#LT#it{#eta}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexEta_m", ";;#LT#it{#eta}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexPhi_p", ";;#LT#it{#varphi}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexPhi_m", ";;#LT#it{#varphi}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcDeDx_p", ";;TPC #LTd#it{E}/d#it{x}#GT (a.u.) (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcDeDx_m", ";;TPC #LTd#it{E}/d#it{x}#GT (a.u.) (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNSigmaPi_p", ";;TPC #LT#it{n}#it{#sigma}_{#pi}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNSigmaPi_m", ";;TPC #LT#it{n}#it{#sigma}_{#pi}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNSigmaKa_p", ";;TPC #LT#it{n}#it{#sigma}_{K}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNSigmaKa_m", ";;TPC #LT#it{n}#it{#sigma}_{K}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNSigmaPr_p", ";;TPC #LT#it{n}#it{#sigma}_{p}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTpcNSigmaPr_m", ";;TPC #LT#it{n}#it{#sigma}_{p}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofInverseBeta_p", ";;TOF #LT1/#it{#beta}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofInverseBeta_m", ";;TOF #LT1/#it{#beta}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofNSigmaPi_p", ";;TOF #LT#it{n}#it{#sigma}_{#pi}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofNSigmaPi_m", ";;TOF #LT#it{n}#it{#sigma}_{#pi}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofNSigmaKa_p", ";;TOF #LT#it{n}#it{#sigma}_{K}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofNSigmaKa_m", ";;TOF #LT#it{n}#it{#sigma}_{K}#GT (#it{q}<0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofNSigmaPr_p", ";;TOF #LT#it{n}#it{#sigma}_{p}#GT (#it{q}>0)", hcsQaRun); + hrQaRun.add("QaRun/pRunIndexTofNSigmaPr_m", ";;TOF #LT#it{n}#it{#sigma}_{p}#GT (#it{q}<0)", hcsQaRun); + } + + if (groupAnalysis.cfgFlagQaEvent.value) { LOG(info) << "Enabling event QA."; - AxisSpec asRunIndex(static_cast(holderCcdb.runNumbers.size()), -0.5, holderCcdb.runNumbers.size() - 0.5, "Run Index"); - AxisSpec asNGlobalTracks(180, -0.5, 179.5, "nGlobalTracks"); - hrQaEvent.add("QaEvent/hRunIndexVxVy", "", {HistType::kTHnSparseF, {asRunIndex, {150, -0.15, 0.15, "#it{V}_{#it{x}} (cm)"}, {150, -0.15, 0.15, "#it{V}_{#it{y}} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexVz", "", {HistType::kTH2F, {asRunIndex, {300, -15., 15., "#it{V}_{#it{z}} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNPvContributorsNGlobalTracks", "", {HistType::kTHnSparseF, {asRunIndex, {180, -0.5, 179.5, "nPvContributors"}, asNGlobalTracks}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaXy", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -0.5, 0.5, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaXy_nPvContributorsCut", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaZ", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNGlobalTracksMeanDcaZ_nPvContributorsCut", "", {HistType::kTHnSparseF, {asRunIndex, asNGlobalTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); - hrQaEvent.add("QaEvent/hRunIndexNTofBetaNGlobalTracks", "", {HistType::kTHnSparseF, {asRunIndex, {60, -0.5, 59.5, "nTofBeta"}, asNGlobalTracks}}); - hrQaEvent.add("QaEvent/hRunIndexNTofBetaNGlobalTracks_nPvContributorsCut", "", {HistType::kTHnSparseF, {asRunIndex, {60, -0.5, 59.5, "nTofBeta"}, asNGlobalTracks}}); + const AxisSpec asNTracks(200, -0.5, 199.5); + const HistogramConfigSpec hcsQaEvent(HistType::kTHnSparseD, {asNTracks, asNTracks}); + + hrQaEvent.add("QaEvent/hVxVy", "", {HistType::kTHnSparseD, {{150, -0.15, 0.15, "#it{V}_{#it{x}} (cm)"}, {150, -0.15, 0.15, "#it{V}_{#it{y}} (cm)"}}}); + hrQaEvent.add("QaEvent/hVz", "", {HistType::kTH1D, {{300, -15., 15., "#it{V}_{#it{z}} (cm)"}}}); + hrQaEvent.add("QaEvent/hNPvContributorsNGlobalTracks", ";nPvContributors;nGlobalTracks;", hcsQaEvent); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {250, -0.25, 0.25, "#LTDCA_{#it{xy}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {250, -0.25, 0.25, "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut", ";nGlobalTracks;", {HistType::kTHnSparseD, {asNTracks, {200, -2., 2., "#LTDCA_{#it{z}}#GT_{event} (cm)"}}}); + hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks", ";nTofBeta;nGlobalTracks;", hcsQaEvent); + hrQaEvent.add("QaEvent/hNTofBetaNGlobalTracks_nPvContributorsCut", ";nTofBeta;nGlobalTracks;", hcsQaEvent); } - if (cfgFlagQaCentrality.value) { + if (groupAnalysis.cfgFlagQaCentrality.value) { LOG(info) << "Enabling centrality QA."; - AxisSpec asQaCentrality(20, 0., 100., "Centrality (%)"); - hrQaCentrality.add("QaCentrality/hCentralityFv0a", "", {HistType::kTHnSparseF, {asQaCentrality, {2400, 0., 24000., "FV0A Multiplicity"}}}); - hrQaCentrality.add("QaCentrality/hCentralityFt0a", "", {HistType::kTHnSparseF, {asQaCentrality, {1600, 0., 8000., "FT0A Multiplicity"}}}); - hrQaCentrality.add("QaCentrality/hCentralityFt0c", "", {HistType::kTHnSparseF, {asQaCentrality, {400, 0., 2000., "FT0C Multiplicity"}}}); - hrQaCentrality.add("QaCentrality/hCentralityFt0m", "", {HistType::kTHnSparseF, {asQaCentrality, {2000, 0., 10000., "FT0A+FT0C Multiplicity"}}}); + const AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); + + hrQaCentrality.add("QaCentrality/hCentralityFt0a", "", {HistType::kTHnSparseF, {asCentrality, {12000, 0., 12000., "FT0A Multiplicity"}}}); + hrQaCentrality.add("QaCentrality/hCentralityFt0c", "", {HistType::kTHnSparseF, {asCentrality, {3000, 0., 3000., "FT0C Multiplicity"}}}); + hrQaCentrality.add("QaCentrality/hCentralityFt0m", "", {HistType::kTHnSparseF, {asCentrality, {15000, 0., 15000., "FT0M Multiplicity"}}}); } - if (cfgFlagQaTrack.value) { + if (groupAnalysis.cfgFlagQaTrack.value) { LOG(info) << "Enabling track QA."; - AxisSpec asPt(200, 0., 2., "#it{p}_{T} (GeV/#it{c})"); - hrQaTrack.add("QaTrack/hItsNCls", "", {HistType::kTH1D, {{10, -0.5, 9.5, "ITS nClusters"}}}); - hrQaTrack.add("QaTrack/hItsChi2NCls", "", {HistType::kTH1D, {{80, 0., 40., "ITS #it{#chi}^{2}/nClusters"}}}); - hrQaTrack.add("QaTrack/hTpcNClsNClsSharedNClsFindableNClsCrossedRows", "", {HistType::kTHnSparseF, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}, {180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); - hrQaTrack.add("QaTrack/hTpcChi2NCls", "", {HistType::kTH1D, {{100, 0., 5., "TPC #it{#chi}^{2}/nClusters"}}}); - hrQaTrack.add("QaTrack/hPtDcaXy", "", {HistType::kTH2D, {asPt, {200, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); - hrQaTrack.add("QaTrack/hPtDcaXy_pvContributor", "", {HistType::kTH2D, {asPt, {200, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); - hrQaTrack.add("QaTrack/hPtDcaZ", "", {HistType::kTH2D, {asPt, {200, -2., 2., "DCA_{#it{z}} (cm)"}}}); - hrQaTrack.add("QaTrack/hPtDcaZ_pvContributor", "", {HistType::kTH2D, {asPt, {200, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); - } - - if (cfgFlagQaAcceptance.value) { - LOG(info) << "Enabling acceptance QA."; - - AxisSpec asPt(250, 0., 2.5, "#it{p}_{T} (GeV/#it{c})"); - HistogramConfigSpec hcsQaAcceptanceEta(HistType::kTH2D, {{300, -1.5, 1.5, "#it{#eta}"}, asPt}); - HistogramConfigSpec hcsQaAcceptancePhi(HistType::kTH1D, {{360, 0., constants::math::TwoPI, "#it{#varphi} (rad)"}}); - HistogramConfigSpec hcsQaAcceptanceY(HistType::kTH2D, {{300, -1.5, 1.5, "#it{y}"}, asPt}); - hrQaAcceptance.add("QaAcceptance/hEtaPt_tpc", "", hcsQaAcceptanceEta); - hrQaAcceptance.add("QaAcceptance/hPhi_tpc", "", hcsQaAcceptancePhi); - hrQaAcceptance.add("QaAcceptance/hYPt_tpcPi", "", hcsQaAcceptanceY); - hrQaAcceptance.add("QaAcceptance/hYPt_tpcKa", "", hcsQaAcceptanceY); - hrQaAcceptance.add("QaAcceptance/hYPt_tpcPr", "", hcsQaAcceptanceY); - hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcTof", "", hcsQaAcceptanceEta); - hrQaAcceptance.add("QaAcceptance/hPhi_tpcTof", "", hcsQaAcceptancePhi); - hrQaAcceptance.add("QaAcceptance/hYPt_tpcTofPi", "", hcsQaAcceptanceY); - hrQaAcceptance.add("QaAcceptance/hYPt_tpcTofKa", "", hcsQaAcceptanceY); - hrQaAcceptance.add("QaAcceptance/hYPt_tpcTofPr", "", hcsQaAcceptanceY); - } - - if (cfgFlagQaPid.value) { - LOG(info) << "Enabling PID QA."; - - AxisSpec asQaCentrality(20, 0., 100., "Centrality (%)"); - AxisSpec asPOverQ(350, -3.5, 3.5, "#it{p}/#it{q} (GeV/#it{c})"); - AxisSpec asPtOverQ(80, -2., 2., "#it{p}_{T}/#it{q} (GeV/#it{c})"); - AxisSpec asEta(48, -1.2, 1.2, "#it{#eta}"); - HistogramConfigSpec hcsQaPid(HistType::kTHnSparseF, {asQaCentrality, asPtOverQ, asEta, {200, -10., 10.}}); - hrQaPid.add("QaPid/hCentralityPOverQEtaTpcLnDeDx", "", {HistType::kTHnSparseF, {asQaCentrality, asPOverQ, asEta, {240, 3., 9., "TPC ln(d#it{E}/d#it{x} (a.u.))"}}}); - hrQaPid.add("QaPid/hCentralityPtOverQEtaTpcNSigmaPi_tofPi", ";;;;TPC #it{n}#it{#sigma}_{#pi}", hcsQaPid); - hrQaPid.add("QaPid/hCentralityPtOverQEtaTpcNSigmaKa_tofKa", ";;;;TPC #it{n}#it{#sigma}_{K}", hcsQaPid); - hrQaPid.add("QaPid/hCentralityPtOverQEtaTpcNSigmaPr_tofPr", ";;;;TPC #it{n}#it{#sigma}_{p}", hcsQaPid); - hrQaPid.add("QaPid/hCentralityPOverQEtaTofInverseBeta", "", {HistType::kTHnSparseF, {asQaCentrality, asPOverQ, asEta, {120, 0.5, 3.5, "TOF 1/#it{#beta}"}}}); - hrQaPid.add("QaPid/hCentralityPtOverQEtaTofNSigmaPi_tpcPi", ";;;;TOF #it{n}#it{#sigma}_{#pi}", hcsQaPid); - hrQaPid.add("QaPid/hCentralityPtOverQEtaTofNSigmaKa_tpcKa", ";;;;TOF #it{n}#it{#sigma}_{K}", hcsQaPid); - hrQaPid.add("QaPid/hCentralityPtOverQEtaTofNSigmaPr_tpcPr", ";;;;TOF #it{n}#it{#sigma}_{p}", hcsQaPid); + hrQaTrack.add("QaTrack/hItsNCls_p", "", {HistType::kTH1D, {{10, -0.5, 9.5, "ITS nClusters"}}}); + hrQaTrack.add("QaTrack/hItsNCls_m", "", {HistType::kTH1D, {{10, -0.5, 9.5, "ITS nClusters"}}}); + hrQaTrack.add("QaTrack/hItsChi2NCls_p", "", {HistType::kTH1D, {{80, 0., 40., "ITS #it{#chi}^{2}/nClusters"}}}); + hrQaTrack.add("QaTrack/hItsChi2NCls_m", "", {HistType::kTH1D, {{80, 0., 40., "ITS #it{#chi}^{2}/nClusters"}}}); + hrQaTrack.add("QaTrack/hTpcNClsNClsShared_p", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}}}); + hrQaTrack.add("QaTrack/hTpcNClsNClsShared_m", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nClusters"}, {180, -0.5, 179.5, "TPC nSharedClusters"}}}); + hrQaTrack.add("QaTrack/hTpcChi2NCls_p", "", {HistType::kTH1D, {{100, 0., 5., "TPC #it{#chi}^{2}/nClusters"}}}); + hrQaTrack.add("QaTrack/hTpcChi2NCls_m", "", {HistType::kTH1D, {{100, 0., 5., "TPC #it{#chi}^{2}/nClusters"}}}); + hrQaTrack.add("QaTrack/hTpcNClsFindableNCrossedRows_p", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); + hrQaTrack.add("QaTrack/hTpcNClsFindableNCrossedRows_m", "", {HistType::kTHnSparseD, {{180, -0.5, 179.5, "TPC nFindableClusters"}, {180, -0.5, 179.5, "TPC nCrossedRows"}}}); + } + + if (groupAnalysis.cfgFlagQaDca.value) { + LOG(info) << "Enabling DCA QA."; + + const AxisSpec asPt(200, 0., 2., "#it{p}_{T} (GeV/#it{c})"); + + hrQaDca.add("QaDca/hPtDcaXy_p", "", {HistType::kTHnSparseD, {asPt, {500, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); + hrQaDca.add("QaDca/hPtDcaXy_m", "", {HistType::kTHnSparseD, {asPt, {500, -0.5, 0.5, "DCA_{#it{xy}} (cm)"}}}); + hrQaDca.add("QaDca/pPtDcaXy_p", ";;#LTDCA_{#it{xy}}#GT (cm)", {HistType::kTProfile, {asPt}}); + hrQaDca.add("QaDca/pPtDcaXy_m", ";;#LTDCA_{#it{xy}}#GT (cm)", {HistType::kTProfile, {asPt}}); + hrQaDca.add("QaDca/hPtDcaZ_p", "", {HistType::kTHnSparseD, {asPt, {500, -1., 1., "DCA_{#it{z}} (cm)"}}}); + hrQaDca.add("QaDca/hPtDcaZ_m", "", {HistType::kTHnSparseD, {asPt, {500, -1., 1., "DCA_{#it{z}} (cm)"}}}); + hrQaDca.add("QaDca/pPtDcaZ_p", ";;#LTDCA_{#it{z}}#GT (cm)", {HistType::kTProfile, {asPt}}); + hrQaDca.add("QaDca/pPtDcaZ_m", ";;#LTDCA_{#it{z}}#GT (cm)", {HistType::kTProfile, {asPt}}); + } + + if (groupAnalysis.cfgFlagQaAcceptance.value || groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) { + const AxisSpec asPt(250, 0., 2.5, "#it{p}_{T} (GeV/#it{c})"); + + if (groupAnalysis.cfgFlagQaAcceptance.value) { + LOG(info) << "Enabling acceptance QA."; + + const HistogramConfigSpec hcsQaAcceptance(HistType::kTHnSparseD, {{300, -1.5, 1.5, "#it{#eta}"}, asPt}); + + hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcEdgeP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcEdgeM", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcTofEdgeP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hEtaPt_tpcTofEdgeM", "", hcsQaAcceptance); + } + + if (groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) { + const HistogramConfigSpec hcsQaAcceptance(HistType::kTHnSparseD, {{300, -1.5, 1.5, "#it{y}"}, asPt}); + + if (groupAnalysis.cfgFlagQaAcceptancePi.value) { + LOG(info) << "Enabling pion acceptance QA."; + + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgePiP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgePiM", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcTofEdgePiP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcTofEdgePiM", "", hcsQaAcceptance); + } + + if (groupAnalysis.cfgFlagQaAcceptanceKa.value) { + LOG(info) << "Enabling kaon acceptance QA."; + + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgeKaP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgeKaM", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcTofEdgeKaP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcTofEdgeKaM", "", hcsQaAcceptance); + } + + if (groupAnalysis.cfgFlagQaAcceptancePr.value) { + LOG(info) << "Enabling (anti)proton acceptance QA."; + + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgePrP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcEdgePrM", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcTofEdgePrP", "", hcsQaAcceptance); + hrQaAcceptance.add("QaAcceptance/hRapidityPt_tpcTofEdgePrM", "", hcsQaAcceptance); + } + } + } + + if (groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) { + const HistogramConfigSpec hcsQaPhi(HistType::kTHnSparseF, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}, {360, 0., constants::math::TwoPI, "#it{#varphi} (rad)"}}); + + if (groupAnalysis.cfgFlagQaPhi.value) { + LOG(info) << "Enabling phi QA."; + + if (doprocessMc.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofM", "", hcsQaPhi); + } else if (doprocessRaw.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofM", "", hcsQaPhi); + } + } + + if (groupAnalysis.cfgFlagQaPhiPi.value) { + LOG(info) << "Enabling pion phi QA."; + + if (doprocessMc.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcPiM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcPiM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPiM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcPiM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofPiM", "", hcsQaPhi); + } else if (doprocessRaw.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcPiM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofPiP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofPiM", "", hcsQaPhi); + } + } + + if (groupAnalysis.cfgFlagQaPhiKa.value) { + LOG(info) << "Enabling kaon phi QA."; + + if (doprocessMc.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcKaM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcKaM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofKaM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcKaM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofKaM", "", hcsQaPhi); + } else if (doprocessRaw.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcKaM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofKaP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofKaM", "", hcsQaPhi); + } + } + + if (groupAnalysis.cfgFlagQaPhiPr.value) { + LOG(info) << "Enabling (anti)proton phi QA."; + + if (doprocessMc.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcPrM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcPrM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPrM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcPrM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_mcTpcTofPrM", "", hcsQaPhi); + } else if (doprocessRaw.value) { + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcPrM", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofPrP", "", hcsQaPhi); + hrQaPhi.add("QaPhi/hCentralityPtEtaPhi_tpcTofPrM", "", hcsQaPhi); + } + } + } + + if (groupAnalysis.cfgFlagQaPid.value || groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) { + const AxisSpec asCentrality({0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"); + + if (groupAnalysis.cfgFlagQaPid.value) { + LOG(info) << "Enabling PID QA."; + + const AxisSpec asPOverQ(350, -3.5, 3.5, "#it{p}/#it{q} (GeV/#it{c})"); + const AxisSpec asEta(48, -1.2, 1.2, "#it{#eta}"); + + hrQaPid.add("QaPid/hCentralityPOverQEtaTpcLnDeDx", "", {HistType::kTHnSparseF, {asCentrality, asPOverQ, asEta, {240, 3., 9., "TPC ln(d#it{E}/d#it{x} (a.u.))"}}}); + hrQaPid.add("QaPid/hCentralityPOverQEtaTofInverseBeta", "", {HistType::kTHnSparseF, {asCentrality, asPOverQ, asEta, {120, 0.5, 3.5, "TOF 1/#it{#beta}"}}}); + } + + if (groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) { + const HistogramConfigSpec hcsQaPid(HistType::kTHnSparseF, {asCentrality, {40, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {32, -0.8, 0.8, "#it{#eta}"}, {300, -30., 30.}}); + + if (groupAnalysis.cfgFlagQaPidPi.value) { + LOG(info) << "Enabling pion PID QA."; + + if (doprocessMc.value) { + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiP", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiM", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiP", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiM", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + } else if (doprocessRaw.value) { + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_p", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_m", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiP", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiM", ";;;;TPC #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiP", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiM", ";;;;TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPi_p", ";;;;TPC-TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPi_m", ";;;;TPC-TOF #it{n}#it{#sigma}_{#pi};", hcsQaPid); + } + } + + if (groupAnalysis.cfgFlagQaPidKa.value) { + LOG(info) << "Enabling kaon PID QA."; + + if (doprocessMc.value) { + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaP", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaM", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaP", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaM", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + } else if (doprocessRaw.value) { + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_p", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_m", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaP", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaM", ";;;;TPC #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaP", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaM", ";;;;TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaKa_p", ";;;;TPC-TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaKa_m", ";;;;TPC-TOF #it{n}#it{#sigma}_{K};", hcsQaPid); + } + } + + if (groupAnalysis.cfgFlagQaPidPr.value) { + LOG(info) << "Enabling (anti)proton PID QA."; + + if (doprocessMc.value) { + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrP", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrM", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrP", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrM", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + } else if (doprocessRaw.value) { + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_p", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_m", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrP", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrM", ";;;;TPC #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrP", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrM", ";;;;TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPr_p", ";;;;TPC-TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + hrQaPid.add("QaPid/hCentralityPtEtaTpcTofNSigmaPr_m", ";;;;TPC-TOF #it{n}#it{#sigma}_{p};", hcsQaPid); + } + } + } + } + + if (doprocessMc.value) { + if (groupAnalysis.cfgFlagQaMc.value) { + LOG(info) << "Enabling MC QA."; + + const AxisSpec asCentrality(20, 0., 100., "Centrality (%)"); + + hrQaMc.add("QaMc/hCentralityVzDeltaVz", "", {HistType::kTHnSparseF, {asCentrality, {200, -10., 10., "#it{V}_{#it{z}}^{Rec} (cm)"}, {200, -1., 1., "#it{V}_{#it{z}}^{Rec}#minus#it{V}_{#it{z}}^{Gen} (cm)"}}}); + hrQaMc.add("QaMc/hCentralityPtEtaDeltaPt", "", {HistType::kTHnSparseF, {asCentrality, {100, 0., 2., "#it{p}_{T}^{Rec} (GeV/#it{c})"}, {120, -1.2, 1.2, "#it{#eta}_{Rec}"}, {200, -1., 1., "#it{p}_{T}^{Rec}#minus#it{p}_{T}^{Gen} (GeV/#it{c})"}}}); + hrQaMc.add("QaMc/hCentralityPtEtaDeltaEta", "", {HistType::kTHnSparseF, {asCentrality, {100, 0., 2., "#it{p}_{T}^{Rec} (GeV/#it{c})"}, {120, -1.2, 1.2, "#it{#eta}_{Rec}"}, {200, -1., 1., "#it{#eta}_{Rec}#minus#it{#eta}_{Gen}"}}}); + } + } + + if (groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) { + const HistogramConfigSpec hcsCalculationYield(HistType::kTHnSparseF, {{static_cast(std::llrint(std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value))) * 2, -std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value), std::ceil(groupEvent.cfgCutMaxAbsVertexZ.value), "#it{V}_{#it{z}} (cm)"}, {{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {40, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {32, -0.8, 0.8, "#it{#eta}"}}); + + if (groupAnalysis.cfgFlagCalculationYieldPi.value) { + LOG(info) << "Enabling pion yield calculation."; + + if (doprocessMc.value) { + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcPiM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcPiM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPiM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcPiM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcTofPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcTofPiM", "", hcsCalculationYield); + } else if (doprocessRaw.value) { + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcPiM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcTofPiP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcTofPiM", "", hcsCalculationYield); + } + } + + if (groupAnalysis.cfgFlagCalculationYieldKa.value) { + LOG(info) << "Enabling kaon yield calculation."; + + if (doprocessMc.value) { + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcKaM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcKaM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofKaM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcKaM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcTofKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcTofKaM", "", hcsCalculationYield); + } else if (doprocessRaw.value) { + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcKaM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcTofKaP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcTofKaM", "", hcsCalculationYield); + } + } + + if (groupAnalysis.cfgFlagCalculationYieldPr.value) { + LOG(info) << "Enabling (anti)proton yield calculation."; + + if (doprocessMc.value) { + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcPrM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcPrM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPrM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcPrM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcTofPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_mcTpcTofPrM", "", hcsCalculationYield); + } else if (doprocessRaw.value) { + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcPrM", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcTofPrP", "", hcsCalculationYield); + hrCalculationYield.add("CalculationYield/hVzCentralityPtEta_tpcTofPrM", "", hcsCalculationYield); + } + } } if (doprocessMc.value) { - if (cfgFlagCalculationPurityPi.value || cfgFlagCalculationPurityKa.value || cfgFlagCalculationPurityPr.value) { - AxisSpec asQaCentrality(20, 0., 100., "Centrality (%)"); - AxisSpec asEta(24, -1.2, 1.2, "#it{#eta}"); - HistogramConfigSpec hcsCalculationPurityP(HistType::kTProfile3D, {asQaCentrality, {35, 0., 3.5, "#it{p} (GeV/#it{c})"}, asEta}); - HistogramConfigSpec hcsCalculationPurityPt(HistType::kTProfile3D, {asQaCentrality, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, asEta}); + if (groupAnalysis.cfgFlagCalculationPurityPi.value || groupAnalysis.cfgFlagCalculationPurityKa.value || groupAnalysis.cfgFlagCalculationPurityPr.value) { + const HistogramConfigSpec hcsCalculationPurity(HistType::kTProfile3D, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}}); - if (cfgFlagCalculationPurityPi.value) { + if (groupAnalysis.cfgFlagCalculationPurityPi.value) { LOG(info) << "Enabling pion purity calculation."; - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcPiP", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcPiM", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcTofPiP", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcTofPiM", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPiP", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPiM", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPiP", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPiM", "", hcsCalculationPurityPt); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPiP", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPiM", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPiP", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPiM", "", hcsCalculationPurity); } - if (cfgFlagCalculationPurityKa.value) { + if (groupAnalysis.cfgFlagCalculationPurityKa.value) { LOG(info) << "Enabling kaon purity calculation."; - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcKaP", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcKaM", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcTofKaP", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcTofKaM", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcKaP", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcKaM", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofKaP", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofKaM", "", hcsCalculationPurityPt); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcKaP", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcKaM", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofKaP", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofKaM", "", hcsCalculationPurity); } - if (cfgFlagCalculationPurityPr.value) { + if (groupAnalysis.cfgFlagCalculationPurityPr.value) { LOG(info) << "Enabling (anti)proton purity calculation."; - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcPrP", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcPrM", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcTofPrP", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPEtaPurityTpcTofPrM", "", hcsCalculationPurityP); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPrP", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPrM", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPrP", "", hcsCalculationPurityPt); - hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPrM", "", hcsCalculationPurityPt); - } - } - - if (cfgFlagCalculationEfficiencyPi.value || cfgFlagCalculationEfficiencyKa.value || cfgFlagCalculationEfficiencyPr.value) { - HistogramConfigSpec hcsCalculationEfficiency(HistType::kTProfile3D, {{20, 0., 100., "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {24, -1.2, 1.2, "#it{#eta}"}}); - - if (cfgFlagCalculationEfficiencyPi.value) { - LOG(info) << "Enabling pion efficiency calculation."; - - holderEvent.mcParticleIndicesMatchedTpcPiP.reserve(60); - holderEvent.mcParticleIndicesMatchedTpcPiM.reserve(60); - holderEvent.mcParticleIndicesMatchedTpcTofPiP.reserve(40); - holderEvent.mcParticleIndicesMatchedTpcTofPiM.reserve(40); - - pCentralityPtEtaEfficiencyTpcPiP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcPiM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcTofPiP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcTofPiM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - for (std::int32_t const& iVzBin : std::views::iota(0, static_cast(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2))) { - pCentralityPtEtaEfficiencyTpcPiP[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcPiP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcPiM[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcPiM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcTofPiP[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcTofPiP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcTofPiM[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcTofPiM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - } - } - - if (cfgFlagCalculationEfficiencyKa.value) { - LOG(info) << "Enabling kaon efficiency calculation."; - - holderEvent.mcParticleIndicesMatchedTpcKaP.reserve(30); - holderEvent.mcParticleIndicesMatchedTpcKaM.reserve(30); - holderEvent.mcParticleIndicesMatchedTpcTofKaP.reserve(20); - holderEvent.mcParticleIndicesMatchedTpcTofKaM.reserve(20); - - pCentralityPtEtaEfficiencyTpcKaP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcKaM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcTofKaP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcTofKaM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - for (std::int32_t const& iVzBin : std::views::iota(0, static_cast(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2))) { - pCentralityPtEtaEfficiencyTpcKaP[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcKaP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcKaM[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcKaM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcTofKaP[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcTofKaP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcTofKaM[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcTofKaM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - } - } - - if (cfgFlagCalculationEfficiencyPr.value) { - LOG(info) << "Enabling (anti)proton efficiency calculation."; - - holderEvent.mcParticleIndicesMatchedTpcPrP.reserve(30); - holderEvent.mcParticleIndicesMatchedTpcPrM.reserve(30); - holderEvent.mcParticleIndicesMatchedTpcTofPrP.reserve(20); - holderEvent.mcParticleIndicesMatchedTpcTofPrM.reserve(20); - - pCentralityPtEtaEfficiencyTpcPrP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcPrM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcTofPrP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - pCentralityPtEtaEfficiencyTpcTofPrM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - for (std::int32_t const& iVzBin : std::views::iota(0, static_cast(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2))) { - pCentralityPtEtaEfficiencyTpcPrP[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcPrP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcPrM[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcPrM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcTofPrP[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcTofPrP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - pCentralityPtEtaEfficiencyTpcTofPrM[iVzBin] = hrCalculationEfficiency.add(Form("CalculationEfficiency/pCentralityPtEtaEfficiencyTpcTofPrM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1), "", hcsCalculationEfficiency); - } - } - } - } - - if (cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value) { - HistogramConfigSpec hcsCalculationFluctuation(HistType::kTH3D, {{cfgNCentralityBins.value, 0., 100., "Centrality (%)"}, {40, -0.5, 39.5}, {40, -0.5, 39.5}}); - HistogramConfigSpec hcsFluctuationCalculator(HistType::kTH3D, {{cfgNCentralityBins.value, 0., 100., "Centrality (%)"}, {cfgNSubgroups.value, -0.5, cfgNSubgroups.value - 0.5, "Subgroup Index"}, {fluctuation_calculator_base::NOrderVectors, -0.5, fluctuation_calculator_base::NOrderVectors - 0.5, "Order Vector Index"}}); - - if (cfgFlagCalculationFluctuationCh.value) { - holderCcdb.pCentralityPtEtaEfficiencyTpcPiP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcPiM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - for (std::int32_t const& iVzBin : std::views::iota(0, static_cast(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2))) { - holderCcdb.pCentralityPtEtaEfficiencyTpcPiP[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcPiP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcPiP[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcPiP[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcPiP[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcPiM[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcPiM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcPiM[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcPiM[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcPiM[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiP[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcTofPiP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiP[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiP[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiP[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiM[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcTofPiM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiM[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiM[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiM[iVzBin]->GetName(); - } - } - - if (cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value) { - holderCcdb.pCentralityPtEtaEfficiencyTpcKaP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcKaM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - for (std::int32_t const& iVzBin : std::views::iota(0, static_cast(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2))) { - holderCcdb.pCentralityPtEtaEfficiencyTpcKaP[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcKaP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcKaP[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcKaP[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcKaP[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcKaM[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcKaM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcKaM[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcKaM[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcKaM[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcTofKaP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcTofKaM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM[iVzBin]->GetName(); - } - } - - if (cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationPr.value) { - holderCcdb.pCentralityPtEtaEfficiencyTpcPrP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcPrM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM.resize(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2); - for (std::int32_t const& iVzBin : std::views::iota(0, static_cast(std::llrint(std::ceil(cfgCutMaxAbsVertexZ.value)) * 2))) { - holderCcdb.pCentralityPtEtaEfficiencyTpcPrP[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcPrP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcPrP[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcPrP[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcPrP[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcPrM[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcPrM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcPrM[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcPrM[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcPrM[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcTofPrP_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP[iVzBin]->GetName(); - holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM[iVzBin] = static_cast(ccdbObject->FindObject(Form("pCentralityPtEtaEfficiencyTpcTofPrM_vz%gto%g", std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin, std::floor(-cfgCutMaxAbsVertexZ.value) + iVzBin + 1))); - assert(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM[iVzBin] && holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM[iVzBin]->IsA() == TProfile3D::Class()); - LOG(info) << "Reading from CCDB: " << holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM[iVzBin]->GetName(); - } - } - - if (cfgFlagCalculationFluctuationCh.value) { + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPrP", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcPrM", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPrP", "", hcsCalculationPurity); + hrCalculationPurity.add("CalculationPurity/pCentralityPtEtaPurityTpcTofPrM", "", hcsCalculationPurity); + } + } + } + + if (doprocessMc.value) { + if (groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value || groupAnalysis.cfgFlagCalculationFractionPrimaryKa.value || groupAnalysis.cfgFlagCalculationFractionPrimaryPr.value) { + const HistogramConfigSpec hcsCalculationFractionPrimary(HistType::kTProfile3D, {{{0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90.}, "Centrality (%)"}, {20, 0., 2., "#it{p}_{T} (GeV/#it{c})"}, {16, -0.8, 0.8, "#it{#eta}"}}); + + if (groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value) { + LOG(info) << "Enabling pion primary fraction calculation."; + + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPiP", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPiM", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPiP", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPiM", "", hcsCalculationFractionPrimary); + } + + if (groupAnalysis.cfgFlagCalculationFractionPrimaryKa.value) { + LOG(info) << "Enabling kaon primary fraction calculation."; + + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcKaP", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcKaM", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofKaP", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofKaM", "", hcsCalculationFractionPrimary); + } + + if (groupAnalysis.cfgFlagCalculationFractionPrimaryPr.value) { + LOG(info) << "Enabling (anti)proton primary fraction calculation."; + + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPrP", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPrM", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPrP", "", hcsCalculationFractionPrimary); + hrCalculationFractionPrimary.add("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPrM", "", hcsCalculationFractionPrimary); + } + } + } + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + const AxisSpec asCentrality(groupEvent.cfgAxisCentrality, "Centrality (%)"); + const HistogramConfigSpec hcsDistribution(HistType::kTHnSparseD, {asCentrality, {200, -0.5, 199.5}, {200, -0.5, 199.5}}); + const HistogramConfigSpec hcsFluctuationCalculator(HistType::kTH3D, {asCentrality, {groupEvent.cfgNSubgroups.value, -0.5, groupEvent.cfgNSubgroups.value - 0.5, "Subgroup Index"}, {fluctuation_calculator_base::NOrderVectors, -0.5, fluctuation_calculator_base::NOrderVectors - 0.5, "Order Vector Index"}}); + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { LOG(info) << "Enabling charge number fluctuation calculation."; fluctuationCalculatorTrackChP = std::make_unique(); @@ -1163,16 +1455,20 @@ struct PartNumFluc { fluctuationCalculatorTrackChN = std::make_unique(); if (doprocessMc.value) { - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM_mc", ";;#it{N}(h^{+});#it{N}(h^{#minus})", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM_mc", ";;#it{N}(h^{+});#it{N}(h^{#minus});", hcsDistribution); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChP_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChM_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChT_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChN_mc", "", hcsFluctuationCalculator); } - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM", ";;#it{N}(h^{+});#it{N}(h^{#minus})", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNChPNChM", ";;#it{N}(h^{+});#it{N}(h^{#minus});", hcsDistribution); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChP", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChM", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChT", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorChN", "", hcsFluctuationCalculator); } - if (cfgFlagCalculationFluctuationKa.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { LOG(info) << "Enabling kaon number fluctuation calculation."; fluctuationCalculatorTrackKaP = std::make_unique(); @@ -1181,16 +1477,20 @@ struct PartNumFluc { fluctuationCalculatorTrackKaN = std::make_unique(); if (doprocessMc.value) { - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM_mc", ";;#it{N}(K^{+});#it{N}(K^{#minus})", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM_mc", ";;#it{N}(K^{+});#it{N}(K^{#minus});", hcsDistribution); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaP_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaM_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaT_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaN_mc", "", hcsFluctuationCalculator); } - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM", ";;#it{N}(K^{+});#it{N}(K^{#minus})", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNKaPNKaM", ";;#it{N}(K^{+});#it{N}(K^{#minus});", hcsDistribution); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaP", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaM", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaT", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorKaN", "", hcsFluctuationCalculator); } - if (cfgFlagCalculationFluctuationPr.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { LOG(info) << "Enabling (anti)proton number fluctuation calculation."; fluctuationCalculatorTrackPrP = std::make_unique(); @@ -1199,134 +1499,199 @@ struct PartNumFluc { fluctuationCalculatorTrackPrN = std::make_unique(); if (doprocessMc.value) { - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM_mc", ";;#it{N}(p);#it{N}(#bar{p})", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM_mc", ";;#it{N}(p);#it{N}(#bar{p});", hcsDistribution); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrP_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrM_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrT_mc", "", hcsFluctuationCalculator); + hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrN_mc", "", hcsFluctuationCalculator); } - hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM", ";;#it{N}(p);#it{N}(#bar{p})", hcsCalculationFluctuation); + hrCalculationFluctuation.add("CalculationFluctuation/hCentralityNPrPNPrM", ";;#it{N}(p);#it{N}(#bar{p});", hcsDistribution); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrP", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrM", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrT", "", hcsFluctuationCalculator); hrCalculationFluctuation.add("CalculationFluctuation/hFluctuationCalculatorPrN", "", hcsFluctuationCalculator); } + + const auto readHnEfficiency = [&](std::initializer_list*, const char*>> pairsVectorHnNameBase) { + for (const auto& [vectorHn, nameBase] : pairsVectorHnNameBase) { + vectorHn->resize(nRunGroups); + } + for (std::int32_t const& iRunGroup : std::views::iota(0, nRunGroups)) { + const TList* const lRunGroup = readListRunGroup(iRunGroup + 1); + for (const auto& [vectorHn, nameBase] : pairsVectorHnNameBase) { + (*vectorHn)[iRunGroup] = readHn(lRunGroup, nameBase, false, iRunGroup + 1, 4); + } + } + }; + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { + readHnEfficiency({{&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP, "hVzCentralityPtEtaEfficiencyTpcPiP"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM, "hVzCentralityPtEtaEfficiencyTpcPiM"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP, "hVzCentralityPtEtaEfficiencyTpcTofPiP"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM, "hVzCentralityPtEtaEfficiencyTpcTofPiM"}}); + } + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value) { + readHnEfficiency({{&holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP, "hVzCentralityPtEtaEfficiencyTpcKaP"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM, "hVzCentralityPtEtaEfficiencyTpcKaM"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP, "hVzCentralityPtEtaEfficiencyTpcTofKaP"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM, "hVzCentralityPtEtaEfficiencyTpcTofKaM"}}); + } + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + readHnEfficiency({{&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP, "hVzCentralityPtEtaEfficiencyTpcPrP"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM, "hVzCentralityPtEtaEfficiencyTpcPrM"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP, "hVzCentralityPtEtaEfficiencyTpcTofPrP"}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM, "hVzCentralityPtEtaEfficiencyTpcTofPrM"}}); + } } } - double getShiftNSigmaPid(const bool flagRecalibrationNSigmaPid, const TH3* const hCentralityPtEtaShiftNSigmaPidP, const TH3* const hCentralityPtEtaShiftNSigmaPidM) + template + double getEfficiency(const bool doUsingMcParticleMomentum) { - const TH3* const hCentralityPtEtaShiftNSigmaPid = [&]() -> const TH3* { - switch (static_cast(flagRecalibrationNSigmaPid) * holderTrack.sign) { - case 1: - return hCentralityPtEtaShiftNSigmaPidP; - case -1: - return hCentralityPtEtaShiftNSigmaPidM; - default: - return nullptr; - } - }(); - return hCentralityPtEtaShiftNSigmaPid ? hCentralityPtEtaShiftNSigmaPid->Interpolate(std::max(std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetXaxis()->GetBinCenter(1), std::numeric_limits::infinity()), std::min(holderEvent.centrality, std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetXaxis()->GetBinCenter(hCentralityPtEtaShiftNSigmaPid->GetNbinsX()), -std::numeric_limits::infinity()))), std::max(std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetYaxis()->GetBinCenter(1), std::numeric_limits::infinity()), std::min(holderTrack.pt, std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetYaxis()->GetBinCenter(hCentralityPtEtaShiftNSigmaPid->GetNbinsY()), -std::numeric_limits::infinity()))), std::max(std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetZaxis()->GetBinCenter(1), std::numeric_limits::infinity()), std::min(holderTrack.eta, std::nextafter(hCentralityPtEtaShiftNSigmaPid->GetZaxis()->GetBinCenter(hCentralityPtEtaShiftNSigmaPid->GetNbinsZ()), -std::numeric_limits::infinity())))) : 0.; - } + static_assert(particleSpecies == ParticleSpecies::kPi || particleSpecies == ParticleSpecies::kKa || particleSpecies == ParticleSpecies::kPr); + static_assert(pidStrategy == PidStrategy::kTpc || pidStrategy == PidStrategy::kTpcTof); + + static const std::array*, 2>, 2>, static_cast(ParticleSpecies::kNSpecies)> pointersVectorHistogramEfficiency = {{{{{&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiP, &holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiP}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPiM, &holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPiM}}}, {{{&holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaP, &holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaP}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcKaM, &holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofKaM}}}, {{{&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrP, &holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrP}, {&holderCcdb.hVzCentralityPtEtaEfficiencyTpcPrM, &holderCcdb.hVzCentralityPtEtaEfficiencyTpcTofPrM}}}}}; - template - double getEfficiency(const std::vector& pCentralityPtEtaEfficiency) - { if constexpr (doProcessingMc) { - return pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetBinContent(pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetXaxis()->FindBin(holderEvent.centrality), pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetYaxis()->FindBin(holderMcParticle.pt), pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetZaxis()->FindBin(holderMcParticle.eta)); + if (holderMcParticle.charge == 0) { + return 0.; + } + const THnBase* const hVzCentralityPtEtaEfficiency = pointersVectorHistogramEfficiency[static_cast(particleSpecies)][holderMcParticle.charge > 0 ? 0 : 1][pidStrategy == PidStrategy::kTpc ? 0 : 1]->at(std::abs(holderEvent.runGroupIndex) - 1); + return hVzCentralityPtEtaEfficiency ? (doUsingMcParticleMomentum ? hVzCentralityPtEtaEfficiency->GetBinContent(hVzCentralityPtEtaEfficiency->GetBin(std::array{holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta}.data())) : hVzCentralityPtEtaEfficiency->GetBinContent(hVzCentralityPtEtaEfficiency->GetBin(std::array{holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta}.data()))) : 0.; + } + + if (holderTrack.sign == 0) { + return 0.; } - return pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetBinContent(pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetXaxis()->FindBin(holderEvent.centrality), pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetYaxis()->FindBin(holderTrack.pt), pCentralityPtEtaEfficiency[holderEvent.vzBinIndex]->GetZaxis()->FindBin(holderTrack.eta)); + const THnBase* const hVzCentralityPtEtaEfficiency = pointersVectorHistogramEfficiency[static_cast(particleSpecies)][holderTrack.sign > 0 ? 0 : 1][pidStrategy == PidStrategy::kTpc ? 0 : 1]->at(std::abs(holderEvent.runGroupIndex) - 1); + return hVzCentralityPtEtaEfficiency ? hVzCentralityPtEtaEfficiency->GetBinContent(hVzCentralityPtEtaEfficiency->GetBin(std::array{holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta}.data())) : 0.; } - template - std::int32_t isPi() + template + double getShiftNSigmaPid() { - if constexpr (doRequiringTof && doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcTofNSigmaPi) < std::min(cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(holderTrack.tpcTofNSigmaKa), std::fabs(holderTrack.tpcTofNSigmaPr))))) { - return 0; + static_assert(particleSpecies == ParticleSpecies::kPi || particleSpecies == ParticleSpecies::kKa || particleSpecies == ParticleSpecies::kPr); + static_assert(pidStrategy == PidStrategy::kTpc || pidStrategy == PidStrategy::kTof); + + if constexpr (particleSpecies == ParticleSpecies::kPi) { + if (!groupTrack.cfgFlagRecalibrationNSigmaPi.value) { + return 0.; } - } - if constexpr (doRequiringTof && !doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcTofNSigmaPi) < cfgCutMaxAbsNSigmaPid.value)) { - return 0; + } else if constexpr (particleSpecies == ParticleSpecies::kKa) { + if (!groupTrack.cfgFlagRecalibrationNSigmaKa.value) { + return 0.; } - } - if constexpr (!doRequiringTof && doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcNSigmaPi) < std::min(cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(holderTrack.tpcNSigmaKa), std::fabs(holderTrack.tpcNSigmaPr))))) { - return 0; + } else if constexpr (particleSpecies == ParticleSpecies::kPr) { + if (!groupTrack.cfgFlagRecalibrationNSigmaPr.value) { + return 0.; } + } else { + return 0.; } - if constexpr (!doRequiringTof && !doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcNSigmaPi) < cfgCutMaxAbsNSigmaPid.value)) { - return 0; - } + + static const std::array*, 2>, 2>, static_cast(ParticleSpecies::kNSpecies)> pointersVectorHistogramShiftNSigmaPid = {{{{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM}}}, {{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM}}}, {{{&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP}, {&holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM, &holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM}}}}}; + static const auto clampInAxis = [](const double value, const TAxis* const axis) { + const std::int32_t first = std::clamp(axis->GetFirst(), 1, axis->GetNbins()); + const std::int32_t last = std::clamp(axis->GetLast(), 1, axis->GetNbins()); + return first == last ? axis->GetBinCenter(first) : std::clamp(value, std::nextafter(axis->GetBinCenter(first), std::numeric_limits::infinity()), std::nextafter(axis->GetBinCenter(last), -std::numeric_limits::infinity())); + }; + + if (holderTrack.sign == 0) { + return 0.; } - return holderTrack.sign; + const TH3* const hCentralityPtEtaShiftNSigmaPid = pointersVectorHistogramShiftNSigmaPid[static_cast(particleSpecies)][holderTrack.sign > 0 ? 0 : 1][pidStrategy == PidStrategy::kTpc ? 0 : 1]->at(std::abs(holderEvent.runGroupIndex) - 1); + return hCentralityPtEtaShiftNSigmaPid ? hCentralityPtEtaShiftNSigmaPid->Interpolate(clampInAxis(holderEvent.centrality, hCentralityPtEtaShiftNSigmaPid->GetXaxis()), clampInAxis(holderTrack.pt, hCentralityPtEtaShiftNSigmaPid->GetYaxis()), clampInAxis(holderTrack.eta, hCentralityPtEtaShiftNSigmaPid->GetZaxis())) : 0.; } - template - std::int32_t isKa() + template + std::int32_t isPid(const bool doRejectingOthers) { - if constexpr (doRequiringTof && doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcTofNSigmaKa) < std::min(cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(holderTrack.tpcTofNSigmaPi), std::fabs(holderTrack.tpcTofNSigmaPr))))) { - return 0; + static_assert(particleSpecies == ParticleSpecies::kPi || particleSpecies == ParticleSpecies::kKa || particleSpecies == ParticleSpecies::kPr); + static_assert(pidStrategy == PidStrategy::kTpc || pidStrategy == PidStrategy::kTof || pidStrategy == PidStrategy::kTpcAndTof || pidStrategy == PidStrategy::kTpcTof); + + static const std::array, static_cast(ParticleSpecies::kNSpecies)> pointersNSigmaPid = {{{&holderTrack.tpcNSigmaPi, &holderTrack.tofNSigmaPi, &holderTrack.tpcTofNSigmaPi}, {&holderTrack.tpcNSigmaKa, &holderTrack.tofNSigmaKa, &holderTrack.tpcTofNSigmaKa}, {&holderTrack.tpcNSigmaPr, &holderTrack.tofNSigmaPr, &holderTrack.tpcTofNSigmaPr}}}; + + if constexpr (pidStrategy == PidStrategy::kTpc) { + if (doRejectingOthers) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][0]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][0])}))) { + return 0; + } + } else { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + return 0; + } } - } - if constexpr (doRequiringTof && !doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcTofNSigmaKa) < cfgCutMaxAbsNSigmaPid.value)) { - return 0; + } else if constexpr (pidStrategy == PidStrategy::kTof) { + if (doRejectingOthers) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][1]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][1])}))) { + return 0; + } + } else { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + return 0; + } } - } - if constexpr (!doRequiringTof && doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcNSigmaKa) < std::min(cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(holderTrack.tpcNSigmaPi), std::fabs(holderTrack.tpcNSigmaPr))))) { - return 0; + } else if constexpr (pidStrategy == PidStrategy::kTpcAndTof) { + if (doRejectingOthers) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value && std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][1]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][1])}))) { + return 0; + } + } else { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][0]) < groupTrack.cfgCutMaxAbsNSigmaPid.value && std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][1]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + return 0; + } } - } - if constexpr (!doRequiringTof && !doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcNSigmaKa) < cfgCutMaxAbsNSigmaPid.value)) { - return 0; + } else if constexpr (pidStrategy == PidStrategy::kTpcTof) { + if (doRejectingOthers) { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][2]) < std::min({groupTrack.cfgCutMaxAbsNSigmaPid.value, std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 1) % static_cast(ParticleSpecies::kNSpecies)][2]), std::abs(*pointersNSigmaPid[(static_cast(particleSpecies) + 2) % static_cast(ParticleSpecies::kNSpecies)][2])}))) { + return 0; + } + } else { + if (!(std::abs(*pointersNSigmaPid[static_cast(particleSpecies)][2]) < groupTrack.cfgCutMaxAbsNSigmaPid.value)) { + return 0; + } } + } else { + return 0; } return holderTrack.sign; } - template - std::int32_t isPr() + bool isGoodMomentum(const bool doUsingMcParticleMomentum) { - if constexpr (doRequiringTof && doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcTofNSigmaPr) < std::min(cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(holderTrack.tpcTofNSigmaPi), std::fabs(holderTrack.tpcTofNSigmaKa))))) { - return 0; + if (doUsingMcParticleMomentum) { + if (!(groupTrack.cfgCutMinPt.value < holderMcParticle.pt && holderMcParticle.pt < groupTrack.cfgCutMaxPt.value)) { + return false; } - } - if constexpr (doRequiringTof && !doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcTofNSigmaPr) < cfgCutMaxAbsNSigmaPid.value)) { - return 0; + if (!(std::abs(holderMcParticle.eta) < groupTrack.cfgCutMaxAbsEta.value)) { + return false; } - } - if constexpr (!doRequiringTof && doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcNSigmaPr) < std::min(cfgCutMaxAbsNSigmaPid.value, std::min(std::fabs(holderTrack.tpcNSigmaPi), std::fabs(holderTrack.tpcNSigmaKa))))) { - return 0; + } else { + if (!(groupTrack.cfgCutMinPt.value < holderTrack.pt && holderTrack.pt < groupTrack.cfgCutMaxPt.value)) { + return false; } - } - if constexpr (!doRequiringTof && !doRejectingOthers) { - if (!(std::fabs(holderTrack.tpcNSigmaPr) < cfgCutMaxAbsNSigmaPid.value)) { - return 0; + if (!(std::abs(holderTrack.eta) < groupTrack.cfgCutMaxAbsEta.value)) { + return false; } } - return holderTrack.sign; + return true; } - template - bool isGoodMomentum() + bool isGoodDca() { - if constexpr (doProcessingMc) { - if (!(cfgCutMinPt.value < holderMcParticle.pt && holderMcParticle.pt < cfgCutMaxPt.value)) { + if (!groupTrack.cfgFlagRecalibrationDca.value) { + if (!(std::abs(holderTrack.dcaXY) < groupTrack.cfgCutMaxAbsNSigmaDcaXy.value)) { return false; } - if (!(std::fabs(holderMcParticle.eta) < cfgCutMaxAbsEta.value)) { + if (!(std::abs(holderTrack.dcaZ) < groupTrack.cfgCutMaxAbsNSigmaDcaZ.value)) { return false; } } else { - if (!(cfgCutMinPt.value < holderTrack.pt && holderTrack.pt < cfgCutMaxPt.value)) { + if (holderTrack.sign == 0) { + return false; + } + const TFormula* const fPtMeanDcaXy = (holderTrack.sign > 0 ? holderCcdb.fPtMeanDcaXyP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtMeanDcaXyM.at(std::abs(holderEvent.runGroupIndex) - 1)); + const TFormula* const fPtSigmaDcaXy = (holderTrack.sign > 0 ? holderCcdb.fPtSigmaDcaXyP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtSigmaDcaXyM.at(std::abs(holderEvent.runGroupIndex) - 1)); + if (!fPtMeanDcaXy || !fPtSigmaDcaXy || !(std::abs(holderTrack.dcaXY - fPtMeanDcaXy->Eval(holderTrack.pt)) < groupTrack.cfgCutMaxAbsNSigmaDcaXy.value * fPtSigmaDcaXy->Eval(holderTrack.pt))) { return false; } - if (!(std::fabs(holderTrack.eta) < cfgCutMaxAbsEta.value)) { + const TFormula* const fPtMeanDcaZ = (holderTrack.sign > 0 ? holderCcdb.fPtMeanDcaZP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtMeanDcaZM.at(std::abs(holderEvent.runGroupIndex) - 1)); + const TFormula* const fPtSigmaDcaZ = (holderTrack.sign > 0 ? holderCcdb.fPtSigmaDcaZP.at(std::abs(holderEvent.runGroupIndex) - 1) : holderCcdb.fPtSigmaDcaZM.at(std::abs(holderEvent.runGroupIndex) - 1)); + if (!fPtMeanDcaZ || !fPtSigmaDcaZ || !(std::abs(holderTrack.dcaZ - fPtMeanDcaZ->Eval(holderTrack.pt)) < groupTrack.cfgCutMaxAbsNSigmaDcaZ.value * fPtSigmaDcaZ->Eval(holderTrack.pt))) { return false; } } @@ -1336,159 +1701,258 @@ struct PartNumFluc { template bool isGoodTrack(const T& track) { - if ((cfgFlagPvContributor.value && !track.isPVContributor())) { - return false; - } - if (!(track.itsNCls() > cfgCutMinItsNCls.value)) { - return false; - } - if (!(track.itsChi2NCl() < cfgCutMaxItsChi2NCls.value)) { + if ((groupTrack.cfgFlagPvContributor.value && !track.isPVContributor())) { return false; } - if (!(track.tpcNClsFound() > cfgCutMinTpcNCls.value)) { + if (!(track.itsNCls() > groupTrack.cfgCutMinItsNCls.value)) { return false; } - if (!(track.tpcChi2NCl() < cfgCutMaxTpcChi2NCls.value)) { + if (!(track.itsChi2NCl() < groupTrack.cfgCutMaxItsChi2NCls.value)) { return false; } - if (!(track.tpcFractionSharedCls() < cfgCutMaxTpcNClsSharedRatio.value)) { + if (!(track.tpcNClsFound() > groupTrack.cfgCutMinTpcNCls.value)) { return false; } - if (!(track.tpcNClsCrossedRows() > cfgCutMinTpcNClsCrossedRows.value)) { + if (!(track.tpcChi2NCl() < groupTrack.cfgCutMaxTpcChi2NCls.value)) { return false; } - if (!(track.tpcCrossedRowsOverFindableCls() > cfgCutMinTpcNClsCrossedRowsRatio.value)) { + if (!(track.tpcFractionSharedCls() < groupTrack.cfgCutMaxTpcNClsSharedRatio.value)) { return false; } - if (!(std::fabs(track.dcaXY()) < cfgCutMaxAbsNSigmaDcaXy.value * (cfgParSigmaDcaXy.value[0] + cfgParSigmaDcaXy.value[1] * std::pow(track.pt(), cfgParSigmaDcaXy.value[2])))) { + if (!(track.tpcNClsCrossedRows() > groupTrack.cfgCutMinTpcNCrossedRows.value)) { return false; } - if (!(std::fabs(track.dcaZ()) < cfgCutMaxAbsDcaZ.value)) { + if (!(track.tpcCrossedRowsOverFindableCls() > groupTrack.cfgCutMinTpcNCrossedRowsRatio.value)) { return false; } return true; } - template + template bool isGoodMcParticle(const MP& mcParticle) { - if (!mcParticle.isPhysicalPrimary()) { - return false; + if constexpr (doProcessingMc) { + if (!mcParticle.isPhysicalPrimary()) { + return false; + } } return true; } - template - bool initMcParticle(const MP& mcParticle) + template + void calculateFluctuation() { - holderMcParticle.clear(); - holderMcParticle.globalIndex = mcParticle.globalIndex(); - holderMcParticle.pdgCode = mcParticle.pdgCode(); - holderMcParticle.pt = mcParticle.pt(); - holderMcParticle.eta = mcParticle.eta(); - - if (!isGoodMcParticle(mcParticle)) { - return false; + const bool doUsingMcParticleMomentum = doProcessingMc && groupTrack.cfgFlagMcParticleMomentum.value; + if (!(isGoodMomentum(doUsingMcParticleMomentum) && holderTrack.hasTpcPid)) { + return; } - return true; + const auto processSign = [&](const std::int32_t sign, const std::int32_t pdgCodeP, const std::int32_t pdgCodeM, std::int32_t& nP, std::int32_t& nM, std::unique_ptr& fluctuationCalculatorTrackP, std::unique_ptr& fluctuationCalculatorTrackM, std::unique_ptr& fluctuationCalculatorTrackT, std::unique_ptr& fluctuationCalculatorTrackN) { + if (std::abs(sign) != 1) { + return; + } + if constexpr (doProcessingMc) { + if (holderMcParticle.pdgCode != (sign > 0 ? pdgCodeP : pdgCodeM)) { + return; + } + } + + const double efficiency = getEfficiency(doUsingMcParticleMomentum); + if (sign > 0) { + nP++; + fluctuationCalculatorTrackP->fill(1., efficiency); + fluctuationCalculatorTrackT->fill(1., efficiency); + fluctuationCalculatorTrackN->fill(1., efficiency); + } else { + nM++; + fluctuationCalculatorTrackM->fill(1., efficiency); + fluctuationCalculatorTrackT->fill(1., efficiency); + fluctuationCalculatorTrackN->fill(-1., efficiency); + } + }; // NOLINT(readability/braces) + + const auto processSpecies = [&](const double thresholdPtTof, const std::int32_t pdgCodeP, const std::int32_t pdgCodeM, std::int32_t& nP, std::int32_t& nM, std::unique_ptr& fluctuationCalculatorTrackP, std::unique_ptr& fluctuationCalculatorTrackM, std::unique_ptr& fluctuationCalculatorTrackT, std::unique_ptr& fluctuationCalculatorTrackN) { + if ((doUsingMcParticleMomentum ? holderMcParticle.pt : holderTrack.pt) < thresholdPtTof) { + processSign.template operator()(isPid(groupTrack.cfgFlagRejectionOthers.value), pdgCodeP, pdgCodeM, nP, nM, fluctuationCalculatorTrackP, fluctuationCalculatorTrackM, fluctuationCalculatorTrackT, fluctuationCalculatorTrackN); + } else if (holderTrack.hasTofPid) { + processSign.template operator()(isPid(groupTrack.cfgFlagRejectionOthers.value), pdgCodeP, pdgCodeM, nP, nM, fluctuationCalculatorTrackP, fluctuationCalculatorTrackM, fluctuationCalculatorTrackT, fluctuationCalculatorTrackN); + } + }; // NOLINT(readability/braces) + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { + processSpecies.template operator()(groupTrack.cfgThresholdPtTofPi.value, PDG_t::kPiPlus, PDG_t::kPiMinus, holderEvent.nChP, holderEvent.nChM, fluctuationCalculatorTrackChP, fluctuationCalculatorTrackChM, fluctuationCalculatorTrackChT, fluctuationCalculatorTrackChN); + processSpecies.template operator()(groupTrack.cfgThresholdPtTofKa.value, PDG_t::kKPlus, PDG_t::kKMinus, holderEvent.nChP, holderEvent.nChM, fluctuationCalculatorTrackChP, fluctuationCalculatorTrackChM, fluctuationCalculatorTrackChT, fluctuationCalculatorTrackChN); + processSpecies.template operator()(groupTrack.cfgThresholdPtTofPr.value, PDG_t::kProton, PDG_t::kProtonBar, holderEvent.nChP, holderEvent.nChM, fluctuationCalculatorTrackChP, fluctuationCalculatorTrackChM, fluctuationCalculatorTrackChT, fluctuationCalculatorTrackChN); + } + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { + processSpecies.template operator()(groupTrack.cfgThresholdPtTofKa.value, PDG_t::kKPlus, PDG_t::kKMinus, holderEvent.nKaP, holderEvent.nKaM, fluctuationCalculatorTrackKaP, fluctuationCalculatorTrackKaM, fluctuationCalculatorTrackKaT, fluctuationCalculatorTrackKaN); + } + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + processSpecies.template operator()(groupTrack.cfgThresholdPtTofPr.value, PDG_t::kProton, PDG_t::kProtonBar, holderEvent.nPrP, holderEvent.nPrM, fluctuationCalculatorTrackPrP, fluctuationCalculatorTrackPrM, fluctuationCalculatorTrackPrT, fluctuationCalculatorTrackPrN); + } } template bool initTrack(const T& track) { holderTrack.clear(); + holderTrack.dcaXY = track.dcaXY(); + holderTrack.dcaZ = track.dcaZ(); holderTrack.sign = track.sign(); holderTrack.p = track.p(); holderTrack.pt = track.pt(); holderTrack.eta = track.eta(); holderTrack.phi = track.phi(); - holderTrack.pOverQ = holderTrack.p / holderTrack.sign; - holderTrack.ptOverQ = holderTrack.pt / holderTrack.sign; - holderTrack.rapidityPi = track.rapidity(constants::physics::MassPiPlus); - holderTrack.rapidityKa = track.rapidity(constants::physics::MassKPlus); - holderTrack.rapidityPr = track.rapidity(constants::physics::MassProton); holderTrack.hasTpcPid = (track.hasTPC() && track.tpcSignal() > 0.); - holderTrack.tpcNSigmaPi = HolderTrack::truncateNSigmaPid(track.tpcNSigmaPi() - getShiftNSigmaPid(cfgFlagRecalibrationNSigmaPi.value, holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiP, holderCcdb.hCentralityPtEtaShiftTpcNSigmaPiM)); - holderTrack.tpcNSigmaKa = HolderTrack::truncateNSigmaPid(track.tpcNSigmaKa() - getShiftNSigmaPid(cfgFlagRecalibrationNSigmaKa.value, holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaP, holderCcdb.hCentralityPtEtaShiftTpcNSigmaKaM)); - holderTrack.tpcNSigmaPr = HolderTrack::truncateNSigmaPid(track.tpcNSigmaPr() - getShiftNSigmaPid(cfgFlagRecalibrationNSigmaPr.value, holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrP, holderCcdb.hCentralityPtEtaShiftTpcNSigmaPrM)); + if (holderTrack.hasTpcPid) { + holderTrack.tpcNSigmaPi = HolderTrack::truncateNSigmaPid(track.tpcNSigmaPi() - getShiftNSigmaPid()); + holderTrack.tpcNSigmaKa = HolderTrack::truncateNSigmaPid(track.tpcNSigmaKa() - getShiftNSigmaPid()); + holderTrack.tpcNSigmaPr = HolderTrack::truncateNSigmaPid(track.tpcNSigmaPr() - getShiftNSigmaPid()); + } else { + holderTrack.tpcNSigmaPi = holderTrack.tpcNSigmaKa = holderTrack.tpcNSigmaPr = HolderTrack::truncateNSigmaPid(HolderTrack::TruncationAbsNSigmaPid); + } holderTrack.hasTofPid = (track.hasTOF() && track.beta() > 0.); - holderTrack.tofNSigmaPi = HolderTrack::truncateNSigmaPid(track.tofNSigmaPi() - getShiftNSigmaPid(cfgFlagRecalibrationNSigmaPi.value, holderCcdb.hCentralityPtEtaShiftTofNSigmaPiP, holderCcdb.hCentralityPtEtaShiftTofNSigmaPiM)); - holderTrack.tofNSigmaKa = HolderTrack::truncateNSigmaPid(track.tofNSigmaKa() - getShiftNSigmaPid(cfgFlagRecalibrationNSigmaKa.value, holderCcdb.hCentralityPtEtaShiftTofNSigmaKaP, holderCcdb.hCentralityPtEtaShiftTofNSigmaKaM)); - holderTrack.tofNSigmaPr = HolderTrack::truncateNSigmaPid(track.tofNSigmaPr() - getShiftNSigmaPid(cfgFlagRecalibrationNSigmaPr.value, holderCcdb.hCentralityPtEtaShiftTofNSigmaPrP, holderCcdb.hCentralityPtEtaShiftTofNSigmaPrM)); - holderTrack.tpcTofNSigmaPi = HolderTrack::truncateNSigmaPid(std::sqrt(std::pow(holderTrack.tpcNSigmaPi, 2.) + std::pow(holderTrack.tofNSigmaPi, 2.))); - holderTrack.tpcTofNSigmaKa = HolderTrack::truncateNSigmaPid(std::sqrt(std::pow(holderTrack.tpcNSigmaKa, 2.) + std::pow(holderTrack.tofNSigmaKa, 2.))); - holderTrack.tpcTofNSigmaPr = HolderTrack::truncateNSigmaPid(std::sqrt(std::pow(holderTrack.tpcNSigmaPr, 2.) + std::pow(holderTrack.tofNSigmaPr, 2.))); - if constexpr (doProcessingMc) { - holderTrack.mcParticleId = track.mcParticleId(); + if (holderTrack.hasTofPid) { + holderTrack.tofNSigmaPi = HolderTrack::truncateNSigmaPid(track.tofNSigmaPi() - getShiftNSigmaPid()); + holderTrack.tofNSigmaKa = HolderTrack::truncateNSigmaPid(track.tofNSigmaKa() - getShiftNSigmaPid()); + holderTrack.tofNSigmaPr = HolderTrack::truncateNSigmaPid(track.tofNSigmaPr() - getShiftNSigmaPid()); + } else { + holderTrack.tofNSigmaPi = holderTrack.tofNSigmaKa = holderTrack.tofNSigmaPr = HolderTrack::truncateNSigmaPid(HolderTrack::TruncationAbsNSigmaPid); } - - if constexpr (doInitingEvent) { - holderEvent.nGlobalTracks++; - if (track.isPVContributor()) { - holderEvent.nPvContributors++; - } - holderEvent.meanDcaXy += track.dcaXY(); - holderEvent.meanSquareDcaXy += std::pow(track.dcaXY(), 2.); - holderEvent.meanDcaZ += track.dcaZ(); - holderEvent.meanSquareDcaZ += std::pow(track.dcaZ(), 2.); - if (holderTrack.hasTofPid) { - holderEvent.nTofBeta++; - } + if (holderTrack.hasTpcPid && holderTrack.hasTofPid) { + holderTrack.tpcTofNSigmaPi = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaPi, holderTrack.tofNSigmaPi), holderTrack.tpcNSigmaPi + holderTrack.tofNSigmaPi)); + holderTrack.tpcTofNSigmaKa = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaKa, holderTrack.tofNSigmaKa), holderTrack.tpcNSigmaKa + holderTrack.tofNSigmaKa)); + holderTrack.tpcTofNSigmaPr = HolderTrack::truncateNSigmaPid(std::copysign(std::hypot(holderTrack.tpcNSigmaPr, holderTrack.tofNSigmaPr), holderTrack.tpcNSigmaPr + holderTrack.tofNSigmaPr)); + } else { + holderTrack.tpcTofNSigmaPi = holderTrack.tpcTofNSigmaKa = holderTrack.tpcTofNSigmaPr = HolderTrack::truncateNSigmaPid(HolderTrack::TruncationAbsNSigmaPid); } if constexpr (doInitingEvent) { - if (cfgFlagQaRun.value) { - hrQaRun.fill(HIST("QaRun/pRunIndexItsNCls"), holderEvent.runIndex, track.itsNCls()); - hrQaRun.fill(HIST("QaRun/pRunIndexItsChi2NCls"), holderEvent.runIndex, track.itsChi2NCl()); - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCls"), holderEvent.runIndex, track.tpcNClsFound()); - hrQaRun.fill(HIST("QaRun/pRunIndexTpcChi2NCls"), holderEvent.runIndex, track.tpcChi2NCl()); - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNClsSharedRatio"), holderEvent.runIndex, track.tpcFractionSharedCls()); - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNClsCrossedRows"), holderEvent.runIndex, track.tpcNClsCrossedRows()); - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNClsCrossedRowsRatio"), holderEvent.runIndex, track.tpcCrossedRowsOverFindableCls()); - hrQaRun.fill(HIST("QaRun/pRunIndexDcaXy"), holderEvent.runIndex, track.dcaXY()); - hrQaRun.fill(HIST("QaRun/pRunIndexDcaZ"), holderEvent.runIndex, track.dcaZ()); - hrQaRun.fill(HIST("QaRun/pRunIndexPt"), holderEvent.runIndex, holderTrack.pt); - hrQaRun.fill(HIST("QaRun/pRunIndexEta"), holderEvent.runIndex, holderTrack.eta); - hrQaRun.fill(HIST("QaRun/pRunIndexPhi"), holderEvent.runIndex, holderTrack.phi); - if (holderTrack.hasTpcPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTpcDeDx"), holderEvent.runIndex, track.tpcSignal()); - if (std::fabs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPi"), holderEvent.runIndex, holderTrack.tpcNSigmaPi); - } - if (std::fabs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaKa"), holderEvent.runIndex, holderTrack.tpcNSigmaKa); - } - if (std::fabs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPr"), holderEvent.runIndex, holderTrack.tpcNSigmaPr); + if (holderTrack.sign > 0) { + if (track.isPrimaryTrack()) { + holderEvent.nGlobalTracksP++; + if (track.isPVContributor()) { + holderEvent.nPvContributorsP++; } - } - if (holderTrack.hasTofPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTofInverseBeta"), holderEvent.runIndex, 1. / track.beta()); - if (std::fabs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPi"), holderEvent.runIndex, holderTrack.tofNSigmaPi); + holderEvent.meanDcaXyP += holderTrack.dcaXY; + holderEvent.meanSquareDcaXyP += std::pow(holderTrack.dcaXY, 2.); + holderEvent.meanDcaZP += holderTrack.dcaZ; + holderEvent.meanSquareDcaZP += std::pow(holderTrack.dcaZ, 2.); + if (holderTrack.hasTofPid) { + holderEvent.nTofBetaP++; } - if (std::fabs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaKa"), holderEvent.runIndex, holderTrack.tofNSigmaKa); + } + } else if (holderTrack.sign < 0) { + if (track.isPrimaryTrack()) { + holderEvent.nGlobalTracksM++; + if (track.isPVContributor()) { + holderEvent.nPvContributorsM++; } - if (std::fabs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { - hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPr"), holderEvent.runIndex, holderTrack.tofNSigmaPr); + holderEvent.meanDcaXyM += holderTrack.dcaXY; + holderEvent.meanSquareDcaXyM += std::pow(holderTrack.dcaXY, 2.); + holderEvent.meanDcaZM += holderTrack.dcaZ; + holderEvent.meanSquareDcaZM += std::pow(holderTrack.dcaZ, 2.); + if (holderTrack.hasTofPid) { + holderEvent.nTofBetaM++; } } } } - if constexpr (!doInitingEvent) { - if (cfgFlagQaTrack.value) { - hrQaTrack.fill(HIST("QaTrack/hItsNCls"), track.itsNCls()); - hrQaTrack.fill(HIST("QaTrack/hItsChi2NCls"), track.itsChi2NCl()); - hrQaTrack.fill(HIST("QaTrack/hTpcNClsNClsSharedNClsFindableNClsCrossedRows"), track.tpcNClsFound(), track.tpcNClsShared(), track.tpcNClsFindable(), track.tpcNClsCrossedRows()); - hrQaTrack.fill(HIST("QaTrack/hTpcChi2NCls"), track.tpcChi2NCl()); - hrQaTrack.fill(HIST("QaTrack/hPtDcaXy"), holderTrack.pt, track.dcaXY()); - hrQaTrack.fill(HIST("QaTrack/hPtDcaZ"), holderTrack.pt, track.dcaZ()); - if (track.isPVContributor()) { - hrQaTrack.fill(HIST("QaTrack/hPtDcaXy_pvContributor"), holderTrack.pt, track.dcaXY()); - hrQaTrack.fill(HIST("QaTrack/hPtDcaZ_pvContributor"), holderTrack.pt, track.dcaZ()); + if constexpr (doInitingEvent) { + if (groupAnalysis.cfgFlagQaRun.value && track.isPrimaryTrack()) { + if (holderTrack.sign > 0.) { + hrQaRun.fill(HIST("QaRun/pRunIndexItsNCls_p"), holderEvent.runIndex, track.itsNCls()); + hrQaRun.fill(HIST("QaRun/pRunIndexItsChi2NCls_p"), holderEvent.runIndex, track.itsChi2NCl()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCls_p"), holderEvent.runIndex, track.tpcNClsFound()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcChi2NCls_p"), holderEvent.runIndex, track.tpcChi2NCl()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNClsSharedRatio_p"), holderEvent.runIndex, track.tpcFractionSharedCls()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCrossedRows_p"), holderEvent.runIndex, track.tpcNClsCrossedRows()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCrossedRowsRatio_p"), holderEvent.runIndex, track.tpcCrossedRowsOverFindableCls()); + hrQaRun.fill(HIST("QaRun/pRunIndexDcaXy_p"), holderEvent.runIndex, holderTrack.dcaXY); + hrQaRun.fill(HIST("QaRun/pRunIndexDcaZ_p"), holderEvent.runIndex, holderTrack.dcaZ); + hrQaRun.fill(HIST("QaRun/pRunIndexPt_p"), holderEvent.runIndex, holderTrack.pt); + hrQaRun.fill(HIST("QaRun/pRunIndexEta_p"), holderEvent.runIndex, holderTrack.eta); + hrQaRun.fill(HIST("QaRun/pRunIndexPhi_p"), holderEvent.runIndex, holderTrack.phi); + if (holderTrack.hasTpcPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcDeDx_p"), holderEvent.runIndex, track.tpcSignal()); + if (std::abs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPi_p"), holderEvent.runIndex, holderTrack.tpcNSigmaPi); + } + if (std::abs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaKa_p"), holderEvent.runIndex, holderTrack.tpcNSigmaKa); + } + if (std::abs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPr_p"), holderEvent.runIndex, holderTrack.tpcNSigmaPr); + } + } + if (holderTrack.hasTofPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofInverseBeta_p"), holderEvent.runIndex, 1. / track.beta()); + if (std::abs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPi_p"), holderEvent.runIndex, holderTrack.tofNSigmaPi); + } + if (std::abs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaKa_p"), holderEvent.runIndex, holderTrack.tofNSigmaKa); + } + if (std::abs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPr_p"), holderEvent.runIndex, holderTrack.tofNSigmaPr); + } + } + } else if (holderTrack.sign < 0.) { + hrQaRun.fill(HIST("QaRun/pRunIndexItsNCls_m"), holderEvent.runIndex, track.itsNCls()); + hrQaRun.fill(HIST("QaRun/pRunIndexItsChi2NCls_m"), holderEvent.runIndex, track.itsChi2NCl()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCls_m"), holderEvent.runIndex, track.tpcNClsFound()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcChi2NCls_m"), holderEvent.runIndex, track.tpcChi2NCl()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNClsSharedRatio_m"), holderEvent.runIndex, track.tpcFractionSharedCls()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCrossedRows_m"), holderEvent.runIndex, track.tpcNClsCrossedRows()); + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNCrossedRowsRatio_m"), holderEvent.runIndex, track.tpcCrossedRowsOverFindableCls()); + hrQaRun.fill(HIST("QaRun/pRunIndexDcaXy_m"), holderEvent.runIndex, holderTrack.dcaXY); + hrQaRun.fill(HIST("QaRun/pRunIndexDcaZ_m"), holderEvent.runIndex, holderTrack.dcaZ); + hrQaRun.fill(HIST("QaRun/pRunIndexPt_m"), holderEvent.runIndex, holderTrack.pt); + hrQaRun.fill(HIST("QaRun/pRunIndexEta_m"), holderEvent.runIndex, holderTrack.eta); + hrQaRun.fill(HIST("QaRun/pRunIndexPhi_m"), holderEvent.runIndex, holderTrack.phi); + if (holderTrack.hasTpcPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcDeDx_m"), holderEvent.runIndex, track.tpcSignal()); + if (std::abs(holderTrack.tpcNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPi_m"), holderEvent.runIndex, holderTrack.tpcNSigmaPi); + } + if (std::abs(holderTrack.tpcNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaKa_m"), holderEvent.runIndex, holderTrack.tpcNSigmaKa); + } + if (std::abs(holderTrack.tpcNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTpcNSigmaPr_m"), holderEvent.runIndex, holderTrack.tpcNSigmaPr); + } + } + if (holderTrack.hasTofPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofInverseBeta_m"), holderEvent.runIndex, 1. / track.beta()); + if (std::abs(holderTrack.tofNSigmaPi) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPi_m"), holderEvent.runIndex, holderTrack.tofNSigmaPi); + } + if (std::abs(holderTrack.tofNSigmaKa) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaKa_m"), holderEvent.runIndex, holderTrack.tofNSigmaKa); + } + if (std::abs(holderTrack.tofNSigmaPr) < HolderTrack::TruncationAbsNSigmaPid) { + hrQaRun.fill(HIST("QaRun/pRunIndexTofNSigmaPr_m"), holderEvent.runIndex, holderTrack.tofNSigmaPr); + } + } + } + } + } + + if constexpr (!doInitingEvent) { + if (groupAnalysis.cfgFlagQaTrack.value && track.isPrimaryTrack()) { + if (holderTrack.sign > 0) { + hrQaTrack.fill(HIST("QaTrack/hItsNCls_p"), track.itsNCls()); + hrQaTrack.fill(HIST("QaTrack/hItsChi2NCls_p"), track.itsChi2NCl()); + hrQaTrack.fill(HIST("QaTrack/hTpcNClsNClsShared_p"), track.tpcNClsFound(), track.tpcNClsShared()); + hrQaTrack.fill(HIST("QaTrack/hTpcChi2NCls_p"), track.tpcChi2NCl()); + hrQaTrack.fill(HIST("QaTrack/hTpcNClsFindableNCrossedRows_p"), track.tpcNClsFindable(), track.tpcNClsCrossedRows()); + } else if (holderTrack.sign < 0) { + hrQaTrack.fill(HIST("QaTrack/hItsNCls_m"), track.itsNCls()); + hrQaTrack.fill(HIST("QaTrack/hItsChi2NCls_m"), track.itsChi2NCl()); + hrQaTrack.fill(HIST("QaTrack/hTpcNClsNClsShared_m"), track.tpcNClsFound(), track.tpcNClsShared()); + hrQaTrack.fill(HIST("QaTrack/hTpcChi2NCls_m"), track.tpcChi2NCl()); + hrQaTrack.fill(HIST("QaTrack/hTpcNClsFindableNCrossedRows_m"), track.tpcNClsFindable(), track.tpcNClsCrossedRows()); } } } @@ -1497,71 +1961,101 @@ struct PartNumFluc { return false; } - if constexpr (doProcessingMc && doInitingEvent) { - if ((cfgFlagCalculationEfficiencyPi.value || cfgFlagCalculationEfficiencyKa.value || cfgFlagCalculationEfficiencyPr.value) && holderTrack.hasTpcPid) { - if (cfgFlagCalculationEfficiencyPi.value) { - switch (isPi()) { - case 1: - holderEvent.mcParticleIndicesMatchedTpcPiP.push_back(holderTrack.mcParticleId); - break; - case -1: - holderEvent.mcParticleIndicesMatchedTpcPiM.push_back(holderTrack.mcParticleId); - break; - } + if constexpr (!doInitingEvent) { + if (groupAnalysis.cfgFlagQaDca.value) { + if (holderTrack.sign > 0) { + hrQaDca.fill(HIST("QaDca/hPtDcaXy_p"), holderTrack.pt, holderTrack.dcaXY); + hrQaDca.fill(HIST("QaDca/pPtDcaXy_p"), holderTrack.pt, holderTrack.dcaXY); + hrQaDca.fill(HIST("QaDca/hPtDcaZ_p"), holderTrack.pt, holderTrack.dcaZ); + hrQaDca.fill(HIST("QaDca/pPtDcaZ_p"), holderTrack.pt, holderTrack.dcaZ); + } else if (holderTrack.sign < 0) { + hrQaDca.fill(HIST("QaDca/hPtDcaXy_m"), holderTrack.pt, holderTrack.dcaXY); + hrQaDca.fill(HIST("QaDca/pPtDcaXy_m"), holderTrack.pt, holderTrack.dcaXY); + hrQaDca.fill(HIST("QaDca/hPtDcaZ_m"), holderTrack.pt, holderTrack.dcaZ); + hrQaDca.fill(HIST("QaDca/pPtDcaZ_m"), holderTrack.pt, holderTrack.dcaZ); } + } + } - if (cfgFlagCalculationEfficiencyKa.value) { - switch (isKa()) { - case 1: - holderEvent.mcParticleIndicesMatchedTpcKaP.push_back(holderTrack.mcParticleId); - break; - case -1: - holderEvent.mcParticleIndicesMatchedTpcKaM.push_back(holderTrack.mcParticleId); - break; + if (!isGoodDca()) { + return false; + } + + if constexpr (!doInitingEvent) { + if ((groupAnalysis.cfgFlagQaAcceptance.value || groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) && ((holderTrack.eta > 0. && holderEvent.vz > groupEvent.cfgCutMaxAbsVertexZ.value - 1.) || (holderTrack.eta < 0. && holderEvent.vz < -groupEvent.cfgCutMaxAbsVertexZ.value + 1.)) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagQaAcceptance.value) { + if (holderTrack.sign > 0) { + hrQaAcceptance.fill(HIST("QaAcceptance/hEtaPt_tpcEdgeP"), holderTrack.eta, holderTrack.pt); + } else if (holderTrack.sign < 0) { + hrQaAcceptance.fill(HIST("QaAcceptance/hEtaPt_tpcEdgeM"), holderTrack.eta, holderTrack.pt); + } + if (holderTrack.hasTofPid) { + if (holderTrack.sign > 0) { + hrQaAcceptance.fill(HIST("QaAcceptance/hEtaPt_tpcTofEdgeP"), holderTrack.eta, holderTrack.pt); + } else if (holderTrack.sign < 0) { + hrQaAcceptance.fill(HIST("QaAcceptance/hEtaPt_tpcTofEdgeM"), holderTrack.eta, holderTrack.pt); + } } } - if (cfgFlagCalculationEfficiencyPr.value) { - switch (isPr()) { + if (groupAnalysis.cfgFlagQaAcceptancePi.value) { + switch (isPid(false)) { case 1: - holderEvent.mcParticleIndicesMatchedTpcPrP.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcEdgePiP"), track.rapidity(constants::physics::MassPiPlus), holderTrack.pt); break; case -1: - holderEvent.mcParticleIndicesMatchedTpcPrM.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcEdgePiM"), track.rapidity(constants::physics::MassPiPlus), holderTrack.pt); break; } - } - - if (holderTrack.hasTofPid) { - if (cfgFlagCalculationEfficiencyPi.value) { - switch (isPi()) { + if (holderTrack.hasTofPid) { + switch (isPid(false)) { case 1: - holderEvent.mcParticleIndicesMatchedTpcTofPiP.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcTofEdgePiP"), track.rapidity(constants::physics::MassPiPlus), holderTrack.pt); break; case -1: - holderEvent.mcParticleIndicesMatchedTpcTofPiM.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcTofEdgePiM"), track.rapidity(constants::physics::MassPiPlus), holderTrack.pt); break; } } + } - if (cfgFlagCalculationEfficiencyKa.value) { - switch (isKa()) { + if (groupAnalysis.cfgFlagQaAcceptanceKa.value) { + switch (isPid(false)) { + case 1: + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcEdgeKaP"), track.rapidity(constants::physics::MassKPlus), holderTrack.pt); + break; + case -1: + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcEdgeKaM"), track.rapidity(constants::physics::MassKPlus), holderTrack.pt); + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(false)) { case 1: - holderEvent.mcParticleIndicesMatchedTpcTofKaP.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcTofEdgeKaP"), track.rapidity(constants::physics::MassKPlus), holderTrack.pt); break; case -1: - holderEvent.mcParticleIndicesMatchedTpcTofKaM.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcTofEdgeKaM"), track.rapidity(constants::physics::MassKPlus), holderTrack.pt); break; } } + } - if (cfgFlagCalculationEfficiencyPr.value) { - switch (isPr()) { + if (groupAnalysis.cfgFlagQaAcceptancePr.value) { + switch (isPid(false)) { + case 1: + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcEdgePrP"), track.rapidity(constants::physics::MassProton), holderTrack.pt); + break; + case -1: + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcEdgePrM"), track.rapidity(constants::physics::MassProton), holderTrack.pt); + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(false)) { case 1: - holderEvent.mcParticleIndicesMatchedTpcTofPrP.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcTofEdgePrP"), track.rapidity(constants::physics::MassProton), holderTrack.pt); break; case -1: - holderEvent.mcParticleIndicesMatchedTpcTofPrM.push_back(holderTrack.mcParticleId); + hrQaAcceptance.fill(HIST("QaAcceptance/hRapidityPt_tpcTofEdgePrM"), track.rapidity(constants::physics::MassProton), holderTrack.pt); break; } } @@ -1570,58 +2064,39 @@ struct PartNumFluc { } if constexpr (!doInitingEvent) { - if (cfgFlagQaAcceptance.value && ((holderTrack.eta > 0. && holderEvent.vz > cfgCutMaxAbsVertexZ.value - 0.5) || (holderTrack.eta < 0. && holderEvent.vz < -cfgCutMaxAbsVertexZ.value + 0.5)) && holderTrack.hasTpcPid) { - hrQaAcceptance.fill(HIST("QaAcceptance/hEtaPt_tpc"), holderTrack.eta, holderTrack.pt); - hrQaAcceptance.fill(HIST("QaAcceptance/hPhi_tpc"), holderTrack.phi); - if (std::abs(isPi()) == 1) { - hrQaAcceptance.fill(HIST("QaAcceptance/hYPt_tpcPi"), holderTrack.rapidityPi, holderTrack.pt); - } - if (std::abs(isKa()) == 1) { - hrQaAcceptance.fill(HIST("QaAcceptance/hYPt_tpcKa"), holderTrack.rapidityKa, holderTrack.pt); - } - if (std::abs(isPr()) == 1) { - hrQaAcceptance.fill(HIST("QaAcceptance/hYPt_tpcPr"), holderTrack.rapidityPr, holderTrack.pt); - } + if (groupAnalysis.cfgFlagQaPid.value && holderTrack.hasTpcPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPOverQEtaTpcLnDeDx"), holderEvent.centrality, holderTrack.p / holderTrack.sign, holderTrack.eta, track.tpcSignal()); if (holderTrack.hasTofPid) { - hrQaAcceptance.fill(HIST("QaAcceptance/hEtaPt_tpcTof"), holderTrack.eta, holderTrack.pt); - hrQaAcceptance.fill(HIST("QaAcceptance/hPhi_tpcTof"), holderTrack.phi); - if (std::abs(isPi()) == 1) { - hrQaAcceptance.fill(HIST("QaAcceptance/hYPt_tpcTofPi"), holderTrack.rapidityPi, holderTrack.pt); - } - if (std::abs(isKa()) == 1) { - hrQaAcceptance.fill(HIST("QaAcceptance/hYPt_tpcTofKa"), holderTrack.rapidityKa, holderTrack.pt); - } - if (std::abs(isPr()) == 1) { - hrQaAcceptance.fill(HIST("QaAcceptance/hYPt_tpcTofPr"), holderTrack.rapidityPr, holderTrack.pt); - } + hrQaPid.fill(HIST("QaPid/hCentralityPOverQEtaTofInverseBeta"), holderEvent.centrality, holderTrack.p / holderTrack.sign, holderTrack.eta, 1. / track.beta()); } } + } - if (cfgFlagQaPid.value && holderTrack.hasTpcPid) { - hrQaPid.fill(HIST("QaPid/hCentralityPOverQEtaTpcLnDeDx"), holderEvent.centrality, holderTrack.pOverQ, holderTrack.eta, std::log(track.tpcSignal())); - if (std::fabs(holderTrack.tofNSigmaPi) < cfgCutMaxAbsNSigmaPid.value) { - hrQaPid.fill(HIST("QaPid/hCentralityPtOverQEtaTpcNSigmaPi_tofPi"), holderEvent.centrality, holderTrack.ptOverQ, holderTrack.eta, holderTrack.tpcNSigmaPi); - } - if (std::fabs(holderTrack.tofNSigmaKa) < cfgCutMaxAbsNSigmaPid.value) { - hrQaPid.fill(HIST("QaPid/hCentralityPtOverQEtaTpcNSigmaKa_tofKa"), holderEvent.centrality, holderTrack.ptOverQ, holderTrack.eta, holderTrack.tpcNSigmaKa); - } - if (std::fabs(holderTrack.tofNSigmaPr) < cfgCutMaxAbsNSigmaPid.value) { - hrQaPid.fill(HIST("QaPid/hCentralityPtOverQEtaTpcNSigmaPr_tofPr"), holderEvent.centrality, holderTrack.ptOverQ, holderTrack.eta, holderTrack.tpcNSigmaPr); - } - if (track.beta() > 0.) { - hrQaPid.fill(HIST("QaPid/hCentralityPOverQEtaTofInverseBeta"), holderEvent.centrality, holderTrack.pOverQ, holderTrack.eta, 1. / track.beta()); - if (std::fabs(holderTrack.tpcNSigmaPi) < cfgCutMaxAbsNSigmaPid.value) { - hrQaPid.fill(HIST("QaPid/hCentralityPtOverQEtaTofNSigmaPi_tpcPi"), holderEvent.centrality, holderTrack.ptOverQ, holderTrack.eta, holderTrack.tofNSigmaPi); - } - if (std::fabs(holderTrack.tpcNSigmaKa) < cfgCutMaxAbsNSigmaPid.value) { - hrQaPid.fill(HIST("QaPid/hCentralityPtOverQEtaTofNSigmaKa_tpcKa"), holderEvent.centrality, holderTrack.ptOverQ, holderTrack.eta, holderTrack.tofNSigmaKa); - } - if (std::fabs(holderTrack.tpcNSigmaPr) < cfgCutMaxAbsNSigmaPid.value) { - hrQaPid.fill(HIST("QaPid/hCentralityPtOverQEtaTofNSigmaPr_tpcPr"), holderEvent.centrality, holderTrack.ptOverQ, holderTrack.eta, holderTrack.tofNSigmaPr); - } - } + return true; + } + + template + bool initMcParticle(const MP& mcParticle) + { + holderMcParticle.clear(); + holderMcParticle.pdgCode = mcParticle.pdgCode(); + const TParticlePDG* particlePdg = pdg->GetParticle(mcParticle.pdgCode()); + if (particlePdg) { + holderMcParticle.charge = std::llrint(particlePdg->Charge()); + } else { + switch (std::abs(holderMcParticle.pdgCode) / 100000000) { + case 10: + holderMcParticle.charge = holderMcParticle.pdgCode / 10000 % 1000; + break; } } + holderMcParticle.pt = mcParticle.pt(); + holderMcParticle.eta = mcParticle.eta(); + holderMcParticle.phi = mcParticle.phi(); + + if (!isGoodMcParticle(mcParticle)) { + return false; + } return true; } @@ -1631,20 +2106,16 @@ struct PartNumFluc { { holderEvent.clear(); holderEvent.vz = collision.posZ(); - holderEvent.vzBinIndex = std::llrint(std::floor(holderEvent.vz - std::floor(-cfgCutMaxAbsVertexZ.value))); - switch (cfgIndexDefinitionCentrality) { - default: - holderEvent.centrality = collision.centFV0A(); - break; - case static_cast(CentralityDefinitionIndices::kFT0M): - holderEvent.centrality = collision.centFT0M(); - break; - case static_cast(CentralityDefinitionIndices::kFT0A): + switch (groupEvent.cfgIndexDefinitionCentrality.value) { + case static_cast(CentralityDefinition::kFt0a): holderEvent.centrality = collision.centFT0A(); break; - case static_cast(CentralityDefinitionIndices::kFT0C): + case static_cast(CentralityDefinition::kFt0c): holderEvent.centrality = collision.centFT0C(); break; + default: + holderEvent.centrality = collision.centFT0M(); + break; } hrCounter.fill(HIST("hNEvents"), 0.); @@ -1656,38 +2127,62 @@ struct PartNumFluc { const auto& bc = collision.template bc_as(); holderEvent.runNumber = bc.runNumber(); - holderEvent.runIndex = std::distance(holderCcdb.runNumbers.begin(), std::ranges::find(holderCcdb.runNumbers, holderEvent.runNumber)); - if (std::ranges::find(holderCcdb.runNumbers, holderEvent.runNumber) == holderCcdb.runNumbers.end() || std::ranges::find(holderCcdb.runNumbersBad, holderEvent.runNumber) != holderCcdb.runNumbersBad.end()) { + if (holderCcdb.runNumbersIndicesGroupIndices.find(holderEvent.runNumber) == holderCcdb.runNumbersIndicesGroupIndices.end()) { + hrCounter.fill(HIST("hNEvents"), 2.); + return false; + } + + std::tie(holderEvent.runIndex, holderEvent.runGroupIndex) = holderCcdb.runNumbersIndicesGroupIndices.at(holderEvent.runNumber); + + if (holderEvent.runGroupIndex == 0 || (groupEvent.cfgFlagRejectionRunBad.value && holderEvent.runGroupIndex < 0)) { hrCounter.fill(HIST("hNEvents"), 2.); return false; } + if (!groupEvent.cfgLabelFlagsRct.value.empty() && !rctFlagsChecker.checkTable(collision)) { + hrCounter.fill(HIST("hNEvents"), 3.); + return false; + } + for (std::int32_t const& iEvSel : std::views::iota(0, aod::evsel::EventSelectionFlags::kNsel)) { - if (((cfgFlagSelectionEvent.value >> iEvSel) & 1) && !collision.selection_bit(iEvSel)) { - hrCounter.fill(HIST("hNEvents"), 3); - hrCounter.fill(HIST("hNEvents"), 10 + iEvSel); + if (((groupEvent.cfgBitsSelectionEvent.value >> iEvSel) & 1) && !collision.selection_bit(iEvSel)) { + hrCounter.fill(HIST("hNEvents"), 4.); + hrCounter.fill(HIST("hNEvents"), 10. + iEvSel); return false; } } - if (cfgFlagQaEvent.value) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexVxVy"), holderEvent.runIndex, collision.posX(), collision.posY()); - hrQaEvent.fill(HIST("QaEvent/hRunIndexVz"), holderEvent.runIndex, holderEvent.vz); + if (groupEvent.cfgFlagInelEvent.value && !collision.isInelGt0()) { + hrCounter.fill(HIST("hNEvents"), 5.); + return false; + } + + if (groupAnalysis.cfgFlagQaEvent.value) { + hrQaEvent.fill(HIST("QaEvent/hVxVy"), collision.posX(), collision.posY()); + hrQaEvent.fill(HIST("QaEvent/hVz"), holderEvent.vz); } - if (!(std::fabs(holderEvent.vz) < cfgCutMaxAbsVertexZ.value)) { - hrCounter.fill(HIST("hNEvents"), 4); + if (!(std::abs(holderEvent.vz) < groupEvent.cfgCutMaxAbsVertexZ.value)) { + hrCounter.fill(HIST("hNEvents"), 6.); return false; } - if (cfgFlagQaRun.value) { + if (groupAnalysis.cfgFlagQaRun.value) { hrQaRun.fill(HIST("QaRun/pRunIndexVx"), holderEvent.runIndex, collision.posX()); hrQaRun.fill(HIST("QaRun/pRunIndexVy"), holderEvent.runIndex, collision.posY()); hrQaRun.fill(HIST("QaRun/pRunIndexVz"), holderEvent.runIndex, holderEvent.vz); - hrQaRun.fill(HIST("QaRun/pRunIndexMultFv0a"), holderEvent.runIndex, collision.multZeqFV0A()); - hrQaRun.fill(HIST("QaRun/pRunIndexMultFt0a"), holderEvent.runIndex, collision.multZeqFT0A()); - hrQaRun.fill(HIST("QaRun/pRunIndexMultFt0c"), holderEvent.runIndex, collision.multZeqFT0C()); + hrQaRun.fill(HIST("QaRun/pRunIndexMultiplicityFt0a"), holderEvent.runIndex, collision.multZeqFT0A()); + hrQaRun.fill(HIST("QaRun/pRunIndexMultiplicityFt0c"), holderEvent.runIndex, collision.multZeqFT0C()); + if (HolderEvent::RangeCentrality.first <= collision.centFT0A() && collision.centFT0A() <= HolderEvent::RangeCentrality.second) { + hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0a"), holderEvent.runIndex, collision.centFT0A()); + } + if (HolderEvent::RangeCentrality.first <= collision.centFT0C() && collision.centFT0C() <= HolderEvent::RangeCentrality.second) { + hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0c"), holderEvent.runIndex, collision.centFT0C()); + } + if (HolderEvent::RangeCentrality.first <= collision.centFT0M() && collision.centFT0M() <= HolderEvent::RangeCentrality.second) { + hrQaRun.fill(HIST("QaRun/pRunIndexCentralityFt0m"), holderEvent.runIndex, collision.centFT0M()); + } } for (const auto& track : tracks) { @@ -1697,51 +2192,65 @@ struct PartNumFluc { initTrack(track); } - if (holderEvent.nGlobalTracks > 0.) { - holderEvent.meanDcaXy /= holderEvent.nGlobalTracks; - holderEvent.meanSquareDcaXy /= holderEvent.nGlobalTracks; - holderEvent.meanDcaZ /= holderEvent.nGlobalTracks; - holderEvent.meanSquareDcaZ /= holderEvent.nGlobalTracks; - } - - if (cfgFlagQaRun.value) { - hrQaRun.fill(HIST("QaRun/pRunIndexNGlobalTracks"), holderEvent.runIndex, holderEvent.nGlobalTracks); - hrQaRun.fill(HIST("QaRun/pRunIndexNPvContributors"), holderEvent.runIndex, holderEvent.nPvContributors); - if (holderEvent.nGlobalTracks > 0) { - hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaXy"), holderEvent.runIndex, holderEvent.meanDcaXy); - hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaXy"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaXy - std::pow(holderEvent.meanDcaXy, 2.))); - hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaZ"), holderEvent.runIndex, holderEvent.meanDcaZ); - hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaZ"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaZ - std::pow(holderEvent.meanDcaZ, 2.))); + if (holderEvent.nGlobalTracksP > 0.) { + holderEvent.meanDcaXyP /= holderEvent.nGlobalTracksP; + holderEvent.meanSquareDcaXyP /= holderEvent.nGlobalTracksP; + holderEvent.meanDcaZP /= holderEvent.nGlobalTracksP; + holderEvent.meanSquareDcaZP /= holderEvent.nGlobalTracksP; + } + if (holderEvent.nGlobalTracksM > 0.) { + holderEvent.meanDcaXyM /= holderEvent.nGlobalTracksM; + holderEvent.meanSquareDcaXyM /= holderEvent.nGlobalTracksM; + holderEvent.meanDcaZM /= holderEvent.nGlobalTracksM; + holderEvent.meanSquareDcaZM /= holderEvent.nGlobalTracksM; + } + + if (groupAnalysis.cfgFlagQaRun.value) { + hrQaRun.fill(HIST("QaRun/pRunIndexNGlobalTracks_p"), holderEvent.runIndex, holderEvent.nGlobalTracksP); + hrQaRun.fill(HIST("QaRun/pRunIndexNGlobalTracks_m"), holderEvent.runIndex, holderEvent.nGlobalTracksM); + hrQaRun.fill(HIST("QaRun/pRunIndexNPvContributors_p"), holderEvent.runIndex, holderEvent.nPvContributorsP); + hrQaRun.fill(HIST("QaRun/pRunIndexNPvContributors_m"), holderEvent.runIndex, holderEvent.nPvContributorsM); + if (holderEvent.nGlobalTracksP > 0) { + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaXy_p"), holderEvent.runIndex, holderEvent.meanDcaXyP); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaXy_p"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaXyP - std::pow(holderEvent.meanDcaXyP, 2.))); + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaZ_p"), holderEvent.runIndex, holderEvent.meanDcaZP); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaZ_p"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaZP - std::pow(holderEvent.meanDcaZP, 2.))); + } + if (holderEvent.nGlobalTracksM > 0) { + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaXy_m"), holderEvent.runIndex, holderEvent.meanDcaXyM); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaXy_m"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaXyM - std::pow(holderEvent.meanDcaXyM, 2.))); + hrQaRun.fill(HIST("QaRun/pRunIndexMeanDcaZ_m"), holderEvent.runIndex, holderEvent.meanDcaZM); + hrQaRun.fill(HIST("QaRun/pRunIndexSigmaDcaZ_m"), holderEvent.runIndex, std::sqrt(holderEvent.meanSquareDcaZM - std::pow(holderEvent.meanDcaZM, 2.))); } - hrQaRun.fill(HIST("QaRun/pRunIndexNTofBeta"), holderEvent.runIndex, holderEvent.nTofBeta); + hrQaRun.fill(HIST("QaRun/pRunIndexNTofBeta_p"), holderEvent.runIndex, holderEvent.nTofBetaP); + hrQaRun.fill(HIST("QaRun/pRunIndexNTofBeta_m"), holderEvent.runIndex, holderEvent.nTofBetaM); } - if (cfgFlagQaEvent.value) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexNPvContributorsNGlobalTracks"), holderEvent.runIndex, holderEvent.nPvContributors, holderEvent.nGlobalTracks); - if (holderEvent.nGlobalTracks > 0) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaXy"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaXy); - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaZ"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaZ); + if (groupAnalysis.cfgFlagQaEvent.value) { + hrQaEvent.fill(HIST("QaEvent/hNPvContributorsNGlobalTracks"), holderEvent.nPvContributorsP + holderEvent.nPvContributorsM, holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM); + if (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM > 0) { + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaXy"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaXyP * holderEvent.nGlobalTracksP + holderEvent.meanDcaXyM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaZ"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaZP * holderEvent.nGlobalTracksP + holderEvent.meanDcaZM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); } - hrQaEvent.fill(HIST("QaEvent/hRunIndexNTofBetaNGlobalTracks"), holderEvent.runIndex, holderEvent.nTofBeta, holderEvent.nGlobalTracks); + hrQaEvent.fill(HIST("QaEvent/hNTofBetaNGlobalTracks"), holderEvent.nTofBetaP + holderEvent.nTofBetaM, holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM); } - if (!(holderEvent.nPvContributors - holderEvent.nGlobalTracks > cfgCutMinDeviationNPvContributors.value)) { - hrCounter.fill(HIST("hNEvents"), 5); + if (!(holderEvent.nPvContributorsP + holderEvent.nPvContributorsM - holderEvent.nGlobalTracksP - holderEvent.nGlobalTracksM > groupEvent.cfgCutMinDeviationNPvContributors.value)) { + hrCounter.fill(HIST("hNEvents"), 7.); return false; } hrCounter.fill(HIST("hNEvents"), 1.); - if (cfgFlagQaEvent.value) { - if (holderEvent.nGlobalTracks > 0) { - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaXy_nPvContributorsCut"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaXy); - hrQaEvent.fill(HIST("QaEvent/hRunIndexNGlobalTracksMeanDcaZ_nPvContributorsCut"), holderEvent.runIndex, holderEvent.nGlobalTracks, holderEvent.meanDcaZ); + if (groupAnalysis.cfgFlagQaEvent.value) { + if (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM > 0) { + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaXy_nPvContributorsCut"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaXyP * holderEvent.nGlobalTracksP + holderEvent.meanDcaXyM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); + hrQaEvent.fill(HIST("QaEvent/hNGlobalTracksMeanDcaZ_nPvContributorsCut"), holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM, (holderEvent.meanDcaZP * holderEvent.nGlobalTracksP + holderEvent.meanDcaZM * holderEvent.nGlobalTracksM) / (holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM)); } - hrQaEvent.fill(HIST("QaEvent/hRunIndexNTofBetaNGlobalTracks_nPvContributorsCut"), holderEvent.runIndex, holderEvent.nTofBeta, holderEvent.nGlobalTracks); + hrQaEvent.fill(HIST("QaEvent/hNTofBetaNGlobalTracks_nPvContributorsCut"), holderEvent.nTofBetaP + holderEvent.nTofBetaM, holderEvent.nGlobalTracksP + holderEvent.nGlobalTracksM); } - if (cfgFlagQaCentrality.value) { - hrQaCentrality.fill(HIST("QaCentrality/hCentralityFv0a"), collision.centFV0A(), collision.multZeqFV0A()); + if (groupAnalysis.cfgFlagQaCentrality.value) { hrQaCentrality.fill(HIST("QaCentrality/hCentralityFt0a"), collision.centFT0A(), collision.multZeqFT0A()); hrQaCentrality.fill(HIST("QaCentrality/hCentralityFt0c"), collision.centFT0C(), collision.multZeqFT0C()); hrQaCentrality.fill(HIST("QaCentrality/hCentralityFt0m"), collision.centFT0M(), collision.multZeqFT0A() + collision.multZeqFT0C()); @@ -1750,261 +2259,69 @@ struct PartNumFluc { return true; } - template - void calculateFluctuation() + template + bool initMcEvent(const MC& mcCollision) { - if (isGoodMomentum() && holderTrack.hasTpcPid) { - if (cfgFlagCalculationFluctuationCh.value) { - if (holderTrack.pt < cfgThresholdPtTofPi.value) { - switch (isPi()) { - case 1: { - holderEvent.nChP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcPiP); - - fluctuationCalculatorTrackChP->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nChM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcPiM); - - fluctuationCalculatorTrackChM->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(-1., efficiency); - } break; - } - } else if (holderTrack.hasTofPid) { - switch (isPi()) { - case 1: { - holderEvent.nChP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiP); - - fluctuationCalculatorTrackChP->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nChM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPiM); - - fluctuationCalculatorTrackChM->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(-1., efficiency); - } break; - } - } - if (holderTrack.pt < cfgThresholdPtTofKa.value) { - switch (isKa()) { - case 1: { - holderEvent.nChP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcKaP); - - fluctuationCalculatorTrackChP->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nChM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcKaM); - - fluctuationCalculatorTrackChM->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(-1., efficiency); - } break; - } - } else if (holderTrack.hasTofPid) { - switch (isKa()) { - case 1: { - holderEvent.nChP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP); - - fluctuationCalculatorTrackChP->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nChM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM); - - fluctuationCalculatorTrackChM->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(-1., efficiency); - } break; - } - } - if (holderTrack.pt < cfgThresholdPtTofPr.value) { - switch (isPr()) { - case 1: { - holderEvent.nChP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcPrP); - - fluctuationCalculatorTrackChP->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nChM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcPrM); - - fluctuationCalculatorTrackChM->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(-1., efficiency); - } break; - } - } else if (holderTrack.hasTofPid) { - switch (isPr()) { - case 1: { - holderEvent.nChP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP); - - fluctuationCalculatorTrackChP->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nChM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM); - - fluctuationCalculatorTrackChM->fill(1., efficiency); - fluctuationCalculatorTrackChT->fill(1., efficiency); - fluctuationCalculatorTrackChN->fill(-1., efficiency); - } break; - } - } - } - - if (cfgFlagCalculationFluctuationKa.value) { - if (holderTrack.pt < cfgThresholdPtTofKa.value) { - switch (isKa()) { - case 1: { - holderEvent.nKaP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcKaP); - - fluctuationCalculatorTrackKaP->fill(1., efficiency); - fluctuationCalculatorTrackKaT->fill(1., efficiency); - fluctuationCalculatorTrackKaN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nKaM++; + holderMcEvent.vz = mcCollision.posZ(); - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcKaM); + hrCounter.fill(HIST("hNMcEvents"), 0.); - fluctuationCalculatorTrackKaM->fill(1., efficiency); - fluctuationCalculatorTrackKaT->fill(1., efficiency); - fluctuationCalculatorTrackKaN->fill(-1., efficiency); - } break; - } - } else if (holderTrack.hasTofPid) { - switch (isKa()) { - case 1: { - holderEvent.nKaP++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaP); - - fluctuationCalculatorTrackKaP->fill(1., efficiency); - fluctuationCalculatorTrackKaT->fill(1., efficiency); - fluctuationCalculatorTrackKaN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nKaM++; - - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofKaM); - - fluctuationCalculatorTrackKaM->fill(1., efficiency); - fluctuationCalculatorTrackKaT->fill(1., efficiency); - fluctuationCalculatorTrackKaN->fill(-1., efficiency); - } break; - } - } - } - - if (cfgFlagCalculationFluctuationPr.value) { - if (holderTrack.pt < cfgThresholdPtTofPr.value) { - switch (isPr()) { - case 1: { - holderEvent.nPrP++; + if (!mcCollision.has_bc()) { + hrCounter.fill(HIST("hNMcEvents"), 2.); + return false; + } - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcPrP); + const auto& bc = mcCollision.template bc_as(); + holderMcEvent.runNumber = bc.runNumber(); - fluctuationCalculatorTrackPrP->fill(1., efficiency); - fluctuationCalculatorTrackPrT->fill(1., efficiency); - fluctuationCalculatorTrackPrN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nPrM++; + if (holderCcdb.runNumbersIndicesGroupIndices.find(holderMcEvent.runNumber) == holderCcdb.runNumbersIndicesGroupIndices.end()) { + hrCounter.fill(HIST("hNMcEvents"), 2.); + return false; + } - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcPrM); + std::tie(holderMcEvent.runIndex, holderMcEvent.runGroupIndex) = holderCcdb.runNumbersIndicesGroupIndices.at(holderMcEvent.runNumber); - fluctuationCalculatorTrackPrM->fill(1., efficiency); - fluctuationCalculatorTrackPrT->fill(1., efficiency); - fluctuationCalculatorTrackPrN->fill(-1., efficiency); - } break; - } - } else if (holderTrack.hasTofPid) { - switch (isPr()) { - case 1: { - holderEvent.nPrP++; + if (holderMcEvent.runGroupIndex == 0 || (groupEvent.cfgFlagRejectionRunBadMc.value && holderMcEvent.runGroupIndex < 0)) { + hrCounter.fill(HIST("hNMcEvents"), 2.); + return false; + } - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrP); + if (groupEvent.cfgFlagInelEventMc.value && !mcCollision.isInelGt0()) { + hrCounter.fill(HIST("hNMcEvents"), 3.); + return false; + } - fluctuationCalculatorTrackPrP->fill(1., efficiency); - fluctuationCalculatorTrackPrT->fill(1., efficiency); - fluctuationCalculatorTrackPrN->fill(1., efficiency); - } break; - case -1: { - holderEvent.nPrM++; + if (!(std::abs(holderMcEvent.vz) < groupEvent.cfgCutMaxAbsVertexZMc.value)) { + hrCounter.fill(HIST("hNMcEvents"), 4.); + return false; + } - const double efficiency = getEfficiency(holderCcdb.pCentralityPtEtaEfficiencyTpcTofPrM); + hrCounter.fill(HIST("hNMcEvents"), 1.); - fluctuationCalculatorTrackPrM->fill(1., efficiency); - fluctuationCalculatorTrackPrT->fill(1., efficiency); - fluctuationCalculatorTrackPrN->fill(-1., efficiency); - } break; - } - } - } - } + return true; } void processRaw(const soa::Filtered::iterator& collision, const soa::Filtered& tracks, const aod::BCsWithTimestamps&) { - if (!initEvent(collision, tracks)) { - return; - } - - if (!cfgFlagQaTrack.value && !cfgFlagQaAcceptance.value && !cfgFlagQaPid.value && !cfgFlagCalculationFluctuationCh.value && !cfgFlagCalculationFluctuationKa.value && !cfgFlagCalculationFluctuationPr.value) { + if (!initEvent(collision, tracks) || (!groupAnalysis.cfgFlagQaTrack.value && !groupAnalysis.cfgFlagQaDca.value && !(groupAnalysis.cfgFlagQaAcceptance.value || groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) && !(groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) && !(groupAnalysis.cfgFlagQaPid.value || groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) && !(groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) && !(groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value))) { return; } - if (cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value) { - holderEvent.subgroupIndex = gRandom->Integer(cfgNSubgroups.value); - if (cfgFlagCalculationFluctuationCh.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + holderEvent.subgroupIndex = gRandom->Integer(groupEvent.cfgNSubgroups.value); + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { fluctuationCalculatorTrackChP->init(); fluctuationCalculatorTrackChM->init(); fluctuationCalculatorTrackChT->init(); fluctuationCalculatorTrackChN->init(); } - if (cfgFlagCalculationFluctuationKa.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { fluctuationCalculatorTrackKaP->init(); fluctuationCalculatorTrackKaM->init(); fluctuationCalculatorTrackKaT->init(); fluctuationCalculatorTrackKaN->init(); } - if (cfgFlagCalculationFluctuationPr.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { fluctuationCalculatorTrackPrP->init(); fluctuationCalculatorTrackPrM->init(); fluctuationCalculatorTrackPrT->init(); @@ -2017,157 +2334,484 @@ struct PartNumFluc { continue; } - if (cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value) { - calculateFluctuation(); - } - } - - if (cfgFlagCalculationFluctuationCh.value) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNChPNChM"), holderEvent.centrality, holderEvent.nChP, holderEvent.nChM); - for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChP->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChM"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChM->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChT"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChT->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChN->getProductFast(iOrderVector)); - } - } - if (cfgFlagCalculationFluctuationKa.value) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNKaPNKaM"), holderEvent.centrality, holderEvent.nKaP, holderEvent.nKaM); - for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaP->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaM"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaM->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaT"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaT->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaN->getProductFast(iOrderVector)); - } - } - if (cfgFlagCalculationFluctuationPr.value) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNPrPNPrM"), holderEvent.centrality, holderEvent.nPrP, holderEvent.nPrM); - for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrP->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrM"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrM->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrT"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrT->getProductFast(iOrderVector)); - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrN->getProductFast(iOrderVector)); - } - } - } - PROCESS_SWITCH(PartNumFluc, processRaw, "Process raw data", true); - - void processMc(const soa::Filtered::iterator& mcCollision, const aod::McParticles& mcParticles, const soa::SmallGroups& collisions, const soa::Filtered& tracksUngrouped, const aod::BCsWithTimestamps&) - { - for (const auto& collision : collisions) { - if (collision.globalIndex() != mcCollision.bestCollisionIndex()) { - continue; - } - - const auto& tracks = tracksUngrouped.sliceBy(presliceTracksPerCollision, collision.globalIndex()); - - if (!initEvent(collision, tracks)) { - continue; - } - - if (cfgFlagCalculationEfficiencyPi.value || cfgFlagCalculationEfficiencyKa.value || cfgFlagCalculationEfficiencyPr.value || cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value) { - for (const auto& mcParticle : mcParticles) { - if (!initMcParticle(mcParticle)) { - continue; + if ((groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagQaPhi.value) { + if (holderTrack.sign > 0) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } else if (holderTrack.sign < 0) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } + if (holderTrack.hasTofPid) { + if (holderTrack.sign > 0) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } else if (holderTrack.sign < 0) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } } + } - switch (holderMcParticle.pdgCode) { - case PDG_t::kPiPlus: - if (cfgFlagCalculationEfficiencyPi.value) { - pCentralityPtEtaEfficiencyTpcPiP[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcPiP, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcPiP.end() ? 1. : 0.); - pCentralityPtEtaEfficiencyTpcTofPiP[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcTofPiP, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcTofPiP.end() ? 1. : 0.); - } - if (cfgFlagCalculationFluctuationCh.value && isGoodMomentum()) { - holderEvent.nChPMc++; - } + if (groupAnalysis.cfgFlagQaPhiPi.value) { + switch (isPid(false)) { + case 1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; - case PDG_t::kPiMinus: - if (cfgFlagCalculationEfficiencyPi.value) { - pCentralityPtEtaEfficiencyTpcPiM[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcPiM, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcPiM.end() ? 1. : 0.); - pCentralityPtEtaEfficiencyTpcTofPiM[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcTofPiM, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcTofPiM.end() ? 1. : 0.); - } - if (cfgFlagCalculationFluctuationCh.value && isGoodMomentum()) { - holderEvent.nChMMc++; - } + case -1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; - case PDG_t::kKPlus: - if (cfgFlagCalculationEfficiencyKa.value) { - pCentralityPtEtaEfficiencyTpcKaP[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcKaP, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcKaP.end() ? 1. : 0.); - pCentralityPtEtaEfficiencyTpcTofKaP[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcTofKaP, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcTofKaP.end() ? 1. : 0.); - } - if (cfgFlagCalculationFluctuationCh.value && isGoodMomentum()) { - holderEvent.nChPMc++; - } - if (cfgFlagCalculationFluctuationKa.value && isGoodMomentum()) { - holderEvent.nKaPMc++; - } + } + switch (isPid(false)) { + case 1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; - case PDG_t::kKMinus: - if (cfgFlagCalculationEfficiencyKa.value) { - pCentralityPtEtaEfficiencyTpcKaM[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcKaM, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcKaM.end() ? 1. : 0.); - pCentralityPtEtaEfficiencyTpcTofKaM[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcTofKaM, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcTofKaM.end() ? 1. : 0.); - } - if (cfgFlagCalculationFluctuationCh.value && isGoodMomentum()) { - holderEvent.nChMMc++; - } - if (cfgFlagCalculationFluctuationKa.value && isGoodMomentum()) { - holderEvent.nKaMMc++; - } + case -1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; - case PDG_t::kProton: - if (cfgFlagCalculationEfficiencyPr.value) { - pCentralityPtEtaEfficiencyTpcPrP[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcPrP, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcPrP.end() ? 1. : 0.); - pCentralityPtEtaEfficiencyTpcTofPrP[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcTofPrP, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcTofPrP.end() ? 1. : 0.); - } - if (cfgFlagCalculationFluctuationCh.value && isGoodMomentum()) { - holderEvent.nChPMc++; - } - if (cfgFlagCalculationFluctuationPr.value && isGoodMomentum()) { - holderEvent.nPrPMc++; - } + } + } + + if (groupAnalysis.cfgFlagQaPhiKa.value) { + switch (isPid(false)) { + case 1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; - case PDG_t::kProtonBar: - if (cfgFlagCalculationEfficiencyPr.value) { - pCentralityPtEtaEfficiencyTpcPrM[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcPrM, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcPrM.end() ? 1. : 0.); - pCentralityPtEtaEfficiencyTpcTofPrM[holderEvent.vzBinIndex]->Fill(holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, std::ranges::find(holderEvent.mcParticleIndicesMatchedTpcTofPrM, holderMcParticle.globalIndex) != holderEvent.mcParticleIndicesMatchedTpcTofPrM.end() ? 1. : 0.); - } - if (cfgFlagCalculationFluctuationCh.value && isGoodMomentum()) { - holderEvent.nChMMc++; - } - if (cfgFlagCalculationFluctuationPr.value && isGoodMomentum()) { - holderEvent.nPrMMc++; - } + case -1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + switch (isPid(false)) { + case 1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case -1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); break; } } - if (cfgFlagCalculationFluctuationCh.value) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNChPNChM_mc"), holderEvent.centrality, holderEvent.nChPMc, holderEvent.nChMMc); - } - if (cfgFlagCalculationFluctuationKa.value) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNKaPNKaM_mc"), holderEvent.centrality, holderEvent.nKaPMc, holderEvent.nKaMMc); - } - if (cfgFlagCalculationFluctuationPr.value) { - hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNPrPNPrM_mc"), holderEvent.centrality, holderEvent.nPrPMc, holderEvent.nPrMMc); - } - } + if (groupAnalysis.cfgFlagQaPhiPr.value) { + switch (isPid(false)) { + case 1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case -1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + switch (isPid(false)) { + case 1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case -1: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_tpcTofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + } + } + + if ((groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagQaPidPi.value) { + if (holderTrack.sign > 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPi_p"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPi); + } else if (holderTrack.sign < 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPi_m"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPi); + } + if (holderTrack.hasTofPid) { + switch (isPid(false)) { + case 1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPi); + break; + case -1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPi_tofPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPi); + break; + } + switch (isPid(false)) { + case 1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPi); + break; + case -1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPi_tpcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPi); + break; + } + if (holderTrack.sign > 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcTofNSigmaPi_p"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcTofNSigmaPi); + } else if (holderTrack.sign < 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcTofNSigmaPi_m"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcTofNSigmaPi); + } + } + } + + if (groupAnalysis.cfgFlagQaPidKa.value) { + if (holderTrack.sign > 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaKa_p"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaKa); + } else if (holderTrack.sign < 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaKa_m"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaKa); + } + if (holderTrack.hasTofPid) { + switch (isPid(false)) { + case 1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaKa); + break; + case -1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaKa_tofKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaKa); + break; + } + switch (isPid(false)) { + case 1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaKa); + break; + case -1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaKa_tpcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaKa); + break; + } + if (holderTrack.sign > 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcTofNSigmaKa_p"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcTofNSigmaKa); + } else if (holderTrack.sign < 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcTofNSigmaKa_m"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcTofNSigmaKa); + } + } + } + + if (groupAnalysis.cfgFlagQaPidPr.value) { + if (holderTrack.sign > 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPr_p"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPr); + } else if (holderTrack.sign < 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPr_m"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPr); + } + if (holderTrack.hasTofPid) { + switch (isPid(false)) { + case 1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPr); + break; + case -1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPr_tofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPr); + break; + } + switch (isPid(false)) { + case 1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPr); + break; + case -1: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPr_tpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPr); + break; + } + if (holderTrack.sign > 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcTofNSigmaPr_p"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcTofNSigmaPr); + } else if (holderTrack.sign < 0) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcTofNSigmaPr_m"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcTofNSigmaPr); + } + } + } + } + + if ((groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagCalculationYieldPi.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcPiP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + case -1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcPiM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + } + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcTofPiP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + case -1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcTofPiM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + } + } + + if (groupAnalysis.cfgFlagCalculationYieldKa.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcKaP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + case -1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcKaM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + } + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcTofKaP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + case -1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcTofKaM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + } + } - if ((cfgFlagCalculationPurityPi.value || cfgFlagCalculationPurityKa.value || cfgFlagCalculationPurityPr.value || cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value)) { - if (cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value) { - holderEvent.subgroupIndex = gRandom->Integer(cfgNSubgroups.value); - if (cfgFlagCalculationFluctuationCh.value) { + if (groupAnalysis.cfgFlagCalculationYieldPr.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcPrP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + case -1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcPrM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + } + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcTofPrP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + case -1: + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_tpcTofPrM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + break; + } + } + } + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + calculateFluctuation(); + } + } + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNChPNChM"), holderEvent.centrality, holderEvent.nChP, holderEvent.nChM); + for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChP->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChM"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChM->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChT"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChT->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChN->getProductFast(iOrderVector)); + } + } + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNKaPNKaM"), holderEvent.centrality, holderEvent.nKaP, holderEvent.nKaM); + for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaP->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaM"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaM->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaT"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaT->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaN->getProductFast(iOrderVector)); + } + } + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNPrPNPrM"), holderEvent.centrality, holderEvent.nPrP, holderEvent.nPrM); + for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrP->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrM"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrM->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrT"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrT->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrN->getProductFast(iOrderVector)); + } + } + } + PROCESS_SWITCH(PartNumFluc, processRaw, "Process raw data", true); + + void processMc(const soa::Filtered::iterator& mcCollision, const aod::McParticles& mcParticles, const soa::SmallGroups& collisions, const soa::Filtered& tracksUngrouped, const aod::BCsWithTimestamps&) + { + if (!initMcEvent(mcCollision)) { + return; + } + + for (const auto& collision : collisions) { + if (collision.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + + const auto& tracks = tracksUngrouped.sliceBy(presliceTracksPerCollision, collision.globalIndex()); + + if (!initEvent(collision, tracks)) { + continue; + } + + if (groupAnalysis.cfgFlagQaMc.value) { + hrQaMc.fill(HIST("QaMc/hCentralityVzDeltaVz"), holderEvent.centrality, holderEvent.vz, holderEvent.vz - holderMcEvent.vz); + } + + if ((groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) || (groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) || (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value)) { + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + holderEvent.subgroupIndex = gRandom->Integer(groupEvent.cfgNSubgroups.value); + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { fluctuationCalculatorTrackChP->init(); fluctuationCalculatorTrackChM->init(); fluctuationCalculatorTrackChT->init(); fluctuationCalculatorTrackChN->init(); } - if (cfgFlagCalculationFluctuationKa.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { fluctuationCalculatorTrackKaP->init(); fluctuationCalculatorTrackKaM->init(); fluctuationCalculatorTrackKaT->init(); fluctuationCalculatorTrackKaN->init(); } - if (cfgFlagCalculationFluctuationPr.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + fluctuationCalculatorTrackPrP->init(); + fluctuationCalculatorTrackPrM->init(); + fluctuationCalculatorTrackPrT->init(); + fluctuationCalculatorTrackPrN->init(); + } + } + + for (const auto& mcParticle : mcParticles) { + if (!initMcParticle(mcParticle)) { + continue; + } + + if (groupAnalysis.cfgFlagQaPhi.value) { + if (holderMcParticle.charge > 0) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } else if (holderMcParticle.charge < 0) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + } + + if ((groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) || (groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) || (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value)) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kPiPlus: + if (groupAnalysis.cfgFlagQaPhiPi.value) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPiP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + if (groupAnalysis.cfgFlagCalculationYieldPi.value) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPiP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value && isGoodMomentum(true)) { + holderMcEvent.nChP++; + fluctuationCalculatorTrackChP->fill(1., 1.); + fluctuationCalculatorTrackChT->fill(1., 1.); + fluctuationCalculatorTrackChN->fill(1., 1.); + } + break; + case PDG_t::kPiMinus: + if (groupAnalysis.cfgFlagQaPhiPi.value) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPiM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + if (groupAnalysis.cfgFlagCalculationYieldPi.value) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPiM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value && isGoodMomentum(true)) { + holderMcEvent.nChM++; + fluctuationCalculatorTrackChM->fill(1., 1.); + fluctuationCalculatorTrackChT->fill(1., 1.); + fluctuationCalculatorTrackChN->fill(-1., 1.); + } + break; + case PDG_t::kKPlus: + if (groupAnalysis.cfgFlagQaPhiKa.value) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcKaP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + if (groupAnalysis.cfgFlagCalculationYieldKa.value) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcKaP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value && isGoodMomentum(true)) { + holderMcEvent.nChP++; + fluctuationCalculatorTrackChP->fill(1., 1.); + fluctuationCalculatorTrackChT->fill(1., 1.); + fluctuationCalculatorTrackChN->fill(1., 1.); + } + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value && isGoodMomentum(true)) { + holderMcEvent.nKaP++; + fluctuationCalculatorTrackKaP->fill(1., 1.); + fluctuationCalculatorTrackKaT->fill(1., 1.); + fluctuationCalculatorTrackKaN->fill(1., 1.); + } + break; + case PDG_t::kKMinus: + if (groupAnalysis.cfgFlagQaPhiKa.value) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcKaM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + if (groupAnalysis.cfgFlagCalculationYieldKa.value) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcKaM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value && isGoodMomentum(true)) { + holderMcEvent.nChM++; + fluctuationCalculatorTrackChM->fill(1., 1.); + fluctuationCalculatorTrackChT->fill(1., 1.); + fluctuationCalculatorTrackChN->fill(-1., 1.); + } + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value && isGoodMomentum(true)) { + holderMcEvent.nKaM++; + fluctuationCalculatorTrackKaM->fill(1., 1.); + fluctuationCalculatorTrackKaT->fill(1., 1.); + fluctuationCalculatorTrackKaN->fill(-1., 1.); + } + break; + case PDG_t::kProton: + if (groupAnalysis.cfgFlagQaPhiPr.value) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + if (groupAnalysis.cfgFlagCalculationYieldPr.value) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPrP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value && isGoodMomentum(true)) { + holderMcEvent.nChP++; + fluctuationCalculatorTrackChP->fill(1., 1.); + fluctuationCalculatorTrackChT->fill(1., 1.); + fluctuationCalculatorTrackChN->fill(1., 1.); + } + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value && isGoodMomentum(true)) { + holderMcEvent.nPrP++; + fluctuationCalculatorTrackPrP->fill(1., 1.); + fluctuationCalculatorTrackPrT->fill(1., 1.); + fluctuationCalculatorTrackPrN->fill(1., 1.); + } + break; + case PDG_t::kProtonBar: + if (groupAnalysis.cfgFlagQaPhiPr.value) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + } + if (groupAnalysis.cfgFlagCalculationYieldPr.value) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcPrM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + } + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value && isGoodMomentum(true)) { + holderMcEvent.nChM++; + fluctuationCalculatorTrackChM->fill(1., 1.); + fluctuationCalculatorTrackChT->fill(1., 1.); + fluctuationCalculatorTrackChN->fill(-1., 1.); + } + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value && isGoodMomentum(true)) { + holderMcEvent.nPrM++; + fluctuationCalculatorTrackPrM->fill(1., 1.); + fluctuationCalculatorTrackPrT->fill(1., 1.); + fluctuationCalculatorTrackPrN->fill(-1., 1.); + } + break; + } + } + } + + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNChPNChM_mc"), holderEvent.centrality, holderMcEvent.nChP, holderMcEvent.nChM); + for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChP_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChP->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChM_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChM->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChT_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChT->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChN_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChN->getProductFast(iOrderVector)); + } + } + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNKaPNKaM_mc"), holderEvent.centrality, holderMcEvent.nKaP, holderMcEvent.nKaM); + for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaP_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaP->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaM_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaM->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaT_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaT->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaN_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaN->getProductFast(iOrderVector)); + } + } + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNPrPNPrM_mc"), holderEvent.centrality, holderMcEvent.nPrP, holderMcEvent.nPrM); + for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrP_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrP->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrM_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrM->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrT_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrT->getProductFast(iOrderVector)); + hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrN_mc"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrN->getProductFast(iOrderVector)); + } + } + } + + if (groupAnalysis.cfgFlagQaTrack.value || groupAnalysis.cfgFlagQaDca.value || (groupAnalysis.cfgFlagQaAcceptance.value || groupAnalysis.cfgFlagQaAcceptancePi.value || groupAnalysis.cfgFlagQaAcceptanceKa.value || groupAnalysis.cfgFlagQaAcceptancePr.value) || (groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) || (groupAnalysis.cfgFlagQaPid.value || groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) || (groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) || (groupAnalysis.cfgFlagCalculationPurityPi.value || groupAnalysis.cfgFlagCalculationPurityKa.value || groupAnalysis.cfgFlagCalculationPurityPr.value) || (groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value || groupAnalysis.cfgFlagCalculationFractionPrimaryKa.value || groupAnalysis.cfgFlagCalculationFractionPrimaryPr.value) || (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value)) { + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { + fluctuationCalculatorTrackChP->init(); + fluctuationCalculatorTrackChM->init(); + fluctuationCalculatorTrackChT->init(); + fluctuationCalculatorTrackChN->init(); + } + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { + fluctuationCalculatorTrackKaP->init(); + fluctuationCalculatorTrackKaM->init(); + fluctuationCalculatorTrackKaT->init(); + fluctuationCalculatorTrackKaN->init(); + } + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { fluctuationCalculatorTrackPrP->init(); fluctuationCalculatorTrackPrM->init(); fluctuationCalculatorTrackPrT->init(); @@ -2181,89 +2825,323 @@ struct PartNumFluc { } const auto& mcParticle = track.template mcParticle_as(); - if (!mcParticle.has_mcCollision()) { + if (!mcParticle.has_mcCollision() || !initTrack(track) || !initMcParticle(mcParticle)) { continue; } - if (!initTrack(track) || !initMcParticle(mcParticle)) { - continue; + if ((groupAnalysis.cfgFlagQaPhi.value || groupAnalysis.cfgFlagQaPhiPi.value || groupAnalysis.cfgFlagQaPhiKa.value || groupAnalysis.cfgFlagQaPhiPr.value) && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary()) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagQaPhi.value) { + if (holderTrack.sign > 0.) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } else if (holderTrack.sign < 0.) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } + if (holderTrack.hasTofPid) { + if (holderTrack.sign > 0.) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } else if (holderTrack.sign < 0.) { + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + } + } + } + + if (groupAnalysis.cfgFlagQaPhiPi.value) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kPiPlus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcPiP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case PDG_t::kPiMinus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcPiM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + if (holderTrack.hasTofPid) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kPiPlus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPiP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case PDG_t::kPiMinus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPiM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + } + } + + if (groupAnalysis.cfgFlagQaPhiKa.value) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kKPlus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcKaP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case PDG_t::kKMinus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcKaM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + if (holderTrack.hasTofPid) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kKPlus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofKaP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case PDG_t::kKMinus: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofKaM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + } + } + + if (groupAnalysis.cfgFlagQaPhiPr.value) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kProton: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case PDG_t::kProtonBar: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + if (holderTrack.hasTofPid) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kProton: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPrP"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + case PDG_t::kProtonBar: + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhiMc_mcTpcTofPrM"), holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta, holderMcParticle.phi); + hrQaPhi.fill(HIST("QaPhi/hCentralityPtEtaPhi_mcTpcTofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.phi); + break; + } + } + } } - if ((cfgFlagCalculationPurityPi.value || cfgFlagCalculationPurityKa.value || cfgFlagCalculationPurityPr.value) && holderTrack.hasTpcPid) { - if (cfgFlagCalculationPurityPi.value) { - switch (isPi()) { + if ((groupAnalysis.cfgFlagQaPidPi.value || groupAnalysis.cfgFlagQaPidKa.value || groupAnalysis.cfgFlagQaPidPr.value) && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary()) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagQaPidPi.value) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kPiPlus: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPi); + if (holderTrack.hasTofPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPi); + } + break; + case PDG_t::kPiMinus: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPi_mcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPi); + if (holderTrack.hasTofPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPi_mcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPi); + } + break; + } + } + + if (groupAnalysis.cfgFlagQaPidKa.value) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kKPlus: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaKa); + if (holderTrack.hasTofPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaKa); + } + break; + case PDG_t::kKMinus: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaKa_mcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaKa); + if (holderTrack.hasTofPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaKa_mcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaKa); + } + break; + } + } + + if (groupAnalysis.cfgFlagQaPidPr.value) { + switch (holderMcParticle.pdgCode) { + case PDG_t::kProton: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPr); + if (holderTrack.hasTofPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPr); + } + break; + case PDG_t::kProtonBar: + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTpcNSigmaPr_mcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tpcNSigmaPr); + if (holderTrack.hasTofPid) { + hrQaPid.fill(HIST("QaPid/hCentralityPtEtaTofNSigmaPr_mcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.tofNSigmaPr); + } + break; + } + } + } + + if (groupAnalysis.cfgFlagQaMc.value && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary())) { + hrQaMc.fill(HIST("QaMc/hCentralityPtEtaDeltaPt"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.pt - holderMcParticle.pt); + hrQaMc.fill(HIST("QaMc/hCentralityPtEtaDeltaEta"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderTrack.eta - holderMcParticle.eta); + } + + if ((groupAnalysis.cfgFlagCalculationYieldPi.value || groupAnalysis.cfgFlagCalculationYieldKa.value || groupAnalysis.cfgFlagCalculationYieldPr.value) && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary()) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagCalculationYieldPi.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { case 1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcPiP"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiPlus ? 1. : 0.); - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiPlus ? 1. : 0.); + if (holderMcParticle.pdgCode == PDG_t::kPiPlus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcPiP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcPiP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } break; case -1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcPiM"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiMinus ? 1. : 0.); - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiMinus ? 1. : 0.); + if (holderMcParticle.pdgCode == PDG_t::kPiMinus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcPiM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcPiM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } break; } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kPiPlus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPiP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcTofPiP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kPiMinus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPiM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcTofPiM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } + break; + } + } } - if (cfgFlagCalculationPurityKa.value) { - switch (isKa()) { + if (groupAnalysis.cfgFlagCalculationYieldKa.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { case 1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcKaP"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKPlus ? 1. : 0.); - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKPlus ? 1. : 0.); + if (holderMcParticle.pdgCode == PDG_t::kKPlus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcKaP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcKaP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } break; case -1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcKaM"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKMinus ? 1. : 0.); - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKMinus ? 1. : 0.); + if (holderMcParticle.pdgCode == PDG_t::kKMinus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcKaM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcKaM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } break; } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kKPlus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofKaP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcTofKaP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kKMinus) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofKaM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcTofKaM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } + break; + } + } } - if (cfgFlagCalculationPurityPr.value) { - switch (isPr()) { + if (groupAnalysis.cfgFlagCalculationYieldPr.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { case 1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcPrP"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProton ? 1. : 0.); - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProton ? 1. : 0.); + if (holderMcParticle.pdgCode == PDG_t::kProton) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcPrP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcPrP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } break; case -1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcPrM"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProtonBar ? 1. : 0.); - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProtonBar ? 1. : 0.); + if (holderMcParticle.pdgCode == PDG_t::kProtonBar) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcPrM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcPrM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } break; } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kProton) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPrP"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcTofPrP"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kProtonBar) { + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEtaMc_mcTpcTofPrM"), holderEvent.vz, holderEvent.centrality, holderMcParticle.pt, holderMcParticle.eta); + hrCalculationYield.fill(HIST("CalculationYield/hVzCentralityPtEta_mcTpcTofPrM"), holderEvent.vz, holderEvent.centrality, holderTrack.pt, holderTrack.eta); + } + break; + } + } } + } - if (holderTrack.hasTofPid) { - if (cfgFlagCalculationPurityPi.value) { - switch (isPi()) { + if ((groupAnalysis.cfgFlagCalculationPurityPi.value || groupAnalysis.cfgFlagCalculationPurityKa.value || groupAnalysis.cfgFlagCalculationPurityPr.value) && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary()) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagCalculationPurityPi.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiPlus ? 1. : 0.); + break; + case -1: + hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiMinus ? 1. : 0.); + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { case 1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcTofPiP"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiPlus ? 1. : 0.); hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcTofPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiPlus ? 1. : 0.); break; case -1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcTofPiM"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiMinus ? 1. : 0.); hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcTofPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kPiMinus ? 1. : 0.); break; } } + } - if (cfgFlagCalculationPurityKa.value) { - switch (isKa()) { + if (groupAnalysis.cfgFlagCalculationPurityKa.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKPlus ? 1. : 0.); + break; + case -1: + hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKMinus ? 1. : 0.); + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { case 1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcTofKaP"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKPlus ? 1. : 0.); hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcTofKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKPlus ? 1. : 0.); break; case -1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcTofKaM"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKMinus ? 1. : 0.); hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcTofKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kKMinus ? 1. : 0.); break; } } + } - if (cfgFlagCalculationPurityPr.value) { - switch (isPr()) { + if (groupAnalysis.cfgFlagCalculationPurityPr.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProton ? 1. : 0.); + break; + case -1: + hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProtonBar ? 1. : 0.); + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { case 1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcTofPrP"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProton ? 1. : 0.); hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcTofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProton ? 1. : 0.); break; case -1: - hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPEtaPurityTpcTofPrM"), holderEvent.centrality, holderTrack.p, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProtonBar ? 1. : 0.); hrCalculationPurity.fill(HIST("CalculationPurity/pCentralityPtEtaPurityTpcTofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, holderMcParticle.pdgCode == PDG_t::kProtonBar ? 1. : 0.); break; } @@ -2271,12 +3149,101 @@ struct PartNumFluc { } } - if ((cfgFlagCalculationFluctuationCh.value || cfgFlagCalculationFluctuationKa.value || cfgFlagCalculationFluctuationPr.value)) { + if ((groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value || groupAnalysis.cfgFlagCalculationFractionPrimaryKa.value || groupAnalysis.cfgFlagCalculationFractionPrimaryPr.value) && holderTrack.hasTpcPid) { + if (groupAnalysis.cfgFlagCalculationFractionPrimaryPi.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kPiPlus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kPiMinus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kPiPlus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPiP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kPiMinus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPiM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + } + } + } + + if (groupAnalysis.cfgFlagCalculationFractionPrimaryKa.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kKPlus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kKMinus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kKPlus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofKaP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kKMinus) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofKaM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + } + } + } + + if (groupAnalysis.cfgFlagCalculationFractionPrimaryPr.value) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kProton) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kProtonBar) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + } + if (holderTrack.hasTofPid) { + switch (isPid(groupTrack.cfgFlagRejectionOthers.value)) { + case 1: + if (holderMcParticle.pdgCode == PDG_t::kProton) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPrP"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + case -1: + if (holderMcParticle.pdgCode == PDG_t::kProtonBar) { + hrCalculationFractionPrimary.fill(HIST("CalculationFractionPrimary/pCentralityPtEtaFractionPrimaryTpcTofPrM"), holderEvent.centrality, holderTrack.pt, holderTrack.eta, mcParticle.isPhysicalPrimary() ? 1. : 0.); + } + break; + } + } + } + } + + if ((groupAnalysis.cfgFlagCalculationFluctuationCh.value || groupAnalysis.cfgFlagCalculationFluctuationKa.value || groupAnalysis.cfgFlagCalculationFluctuationPr.value) && (!groupTrack.cfgFlagMcParticlePhysicalPrimary.value || mcParticle.isPhysicalPrimary())) { calculateFluctuation(); } } - if (cfgFlagCalculationFluctuationCh.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationCh.value) { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNChPNChM"), holderEvent.centrality, holderEvent.nChP, holderEvent.nChM); for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChP->getProductFast(iOrderVector)); @@ -2285,7 +3252,7 @@ struct PartNumFluc { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorChN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackChN->getProductFast(iOrderVector)); } } - if (cfgFlagCalculationFluctuationKa.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationKa.value) { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNKaPNKaM"), holderEvent.centrality, holderEvent.nKaP, holderEvent.nKaM); for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaP->getProductFast(iOrderVector)); @@ -2294,7 +3261,7 @@ struct PartNumFluc { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorKaN"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackKaN->getProductFast(iOrderVector)); } } - if (cfgFlagCalculationFluctuationPr.value) { + if (groupAnalysis.cfgFlagCalculationFluctuationPr.value) { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hCentralityNPrPNPrM"), holderEvent.centrality, holderEvent.nPrP, holderEvent.nPrM); for (std::int32_t const& iOrderVector : std::views::iota(0, static_cast(fluctuation_calculator_base::NOrderVectors))) { hrCalculationFluctuation.fill(HIST("CalculationFluctuation/hFluctuationCalculatorPrP"), holderEvent.centrality, holderEvent.subgroupIndex, iOrderVector, fluctuationCalculatorTrackPrP->getProductFast(iOrderVector)); diff --git a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx index a3e9bd56fcd..2de872a6b52 100644 --- a/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/radialFlowDecorr.cxx @@ -13,11 +13,13 @@ /// \brief Analysis task for event-by-event radial-flow decorrelation measurement. /// \author Somadutta Bhatta -#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -25,6 +27,8 @@ #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/MathConstants.h" #include "DataFormatsParameters/GRPObject.h" +#include "DetectorsCommonDataFormats/AlignParam.h" +#include "FT0Base/Geometry.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -35,6 +39,7 @@ #include "Framework/runDataProcessing.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/TrackTPCITS.h" @@ -43,6 +48,7 @@ #include "TH1F.h" #include "TH2F.h" #include "TH3F.h" +#include "THnSparse.h" #include "TMath.h" #include "TProfile.h" #include "TProfile2D.h" @@ -54,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -67,41 +74,34 @@ using namespace constants::math; struct RadialFlowDecorr { + static constexpr int KPidPionOne = 1; + static constexpr int KPidKaonTwo = 2; + static constexpr int KPidProtonThree = 3; + static constexpr int KConstTen = 10; + + static constexpr int KnFt0cCell = 96; static constexpr int KIntM = 3; static constexpr int KIntK = 3; - static constexpr int KNEta = 17; - static constexpr int KNpT = 3; - static constexpr float KFloatEpsilon = 1e-6f; static constexpr int KPiPlus = 211; static constexpr int KKPlus = 321; static constexpr int KProton = 2212; - - static constexpr float KCentTestMin = 10.f; - static constexpr float KCentTestMaxLo = 60.f; - static constexpr float KCentTestMaxHi = 70.f; - static constexpr float KCentCovCut = 1.0f; static constexpr float KBinOffset = 0.5f; - static constexpr float KHalf = 0.5f; static constexpr float KPhiMin = 0.f; - static constexpr int KNbinsZvtx = 240; static constexpr float KZvtxMin = -12.f; static constexpr float KZvtxMax = 12.f; - static constexpr int KNbinsP = 100; static constexpr float KPMin = 0.f; static constexpr float KPMax = 10.f; static constexpr int KNbinsPt = 200; - static constexpr float KPtMin = 0.f; + static constexpr float KPtMin = 0.15f; static constexpr float KPtMax = 10.f; - static constexpr int KNbinsEta = 120; static constexpr float KEtaMin = -1.2f; static constexpr float KEtaMax = 1.2f; static constexpr int KNbinsPhi = 64; static constexpr float KEtaAxisMin = -0.8f; static constexpr float KEtaAxisMax = 0.8f; - static constexpr int KNbinsPhiFine = 30; static constexpr int KNbinsPtRes = 50; static constexpr float KPtResMax = 1.f; static constexpr int KNbinsEtaRes = 100; @@ -114,50 +114,72 @@ struct RadialFlowDecorr { static constexpr float KEtaFineMax = 1.f; static constexpr int KNbinsDca = 400; static constexpr float KDcaMax = 0.2f; - static constexpr int KNbinsPtCoarse = 50; - static constexpr float KPtMinDefault = 0.2f; - static constexpr float KPtMidMax = 3.0f; - static constexpr float KPtHighMax = 5.0f; - static constexpr float KPtFullMax = 10.0f; static constexpr float KCentMax = 90; - enum PID { kInclusive = 0, - kCombinedPID, - kNumPID }; + + enum PIDIdx { + kInclusiveIdx = 0, + kPiMinusIdx, + kPiPlusIdx, + kPiAllIdx, + kKaMinusIdx, + kKaPlusIdx, + kKaAllIdx, + kAntiPrIdx, + kPrIdx, + kPrAllIdx, + KNsp + }; + + inline static const std::vector pidSuffix = {"", "_PiMinus", "_PiPlus", "_PiAll", "_KaMinus", "_KaPlus", "_KaAll", "_AntiPr", "_Pr", "_PrAll"}; + + struct PIDMeanSigmaMap { + static constexpr int MaxCentBins = 100; + double meanTOF[KNsp][MaxCentBins] = {{0.0}}; + double sigmaTOF[KNsp][MaxCentBins] = {{1.0}}; // Default sigma = 1 + double meanTPC[KNsp][MaxCentBins] = {{0.0}}; + double sigmaTPC[KNsp][MaxCentBins] = {{1.0}}; // Default sigma = 1 + }; + + PIDMeanSigmaMap* pidMeanSigmaMap = nullptr; + enum ECentralityEstimator { kCentFT0C = 1, - kCentFT0A = 2, - kCentFT0M = 3, + kCentFT0M = 2, + kCentFDDM = 3, kCentFV0A = 4 }; + enum SystemType { + kPbPb = 1, + kNeNe = 2, + kOO = 3, + kpp = 4 + }; static constexpr float KinvalidCentrality = -1.0f; - const std::vector pidSuffix = {"", "_PID"}; - - const std::vector etaLw = { + inline static const std::vector etaLw = { -0.8, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7}; - const std::vector etaUp = { + inline static const std::vector etaUp = { 0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; - const std::vector pTLw = {KPtMinDefault, KPtMinDefault, KPtMinDefault}; - const std::vector pTUp = {KPtMidMax, KPtHighMax, KPtFullMax}; - Configurable cfgVtxZCut{"cfgVtxZCut", 10.f, "z-vertex range"}; Configurable cfgPtMin{"cfgPtMin", 0.2f, "min pT"}; - Configurable cfgPtMax{"cfgPtMax", 10.0f, "max pT"}; + Configurable cfgPtMax{"cfgPtMax", 5.0f, "max pT"}; Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "|η| cut"}; - Configurable cfgDCAXY{"cfgDCAXY", 2.4f, "DCAxy cut"}; - Configurable cfgDCAZ{"cfgDCAZ", 3.2f, "DCAz cut"}; - Configurable cfgTPCClsMin{"cfgTPCClsMin", 70.f, "min TPC clusters"}; - Configurable cfgChi2TPCMax{"cfgChi2TPCMax", 4.0f, "max TPC χ²"}; - Configurable cfgPIDnSigmaCut{"cfgPIDnSigmaCut", 3.f, "TPC PID |nσ| cut"}; - Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; - Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; Configurable cfgCutTracKDcaMaxZ{"cfgCutTracKDcaMaxZ", 2.0f, "Maximum DcaZ"}; Configurable cfgCutTracKDcaMaxXY{"cfgCutTracKDcaMaxXY", 0.2f, "Maximum DcaZ"}; + Configurable cfgPtDepDCAxy{"cfgPtDepDCAxy", false, "Use pt-dependent DCAxy cut"}; + Configurable cfgDcaXyP0{"cfgDcaXyP0", 0.0026f, "p0 for DCAxy"}; + Configurable cfgDcaXyP1{"cfgDcaXyP1", 0.005f, "p1 for DCAxy"}; + Configurable cfgDcaXyP2{"cfgDcaXyP2", 1.01f, "p2 for DCAxy"}; + + Configurable cfgPtDepDCAz{"cfgPtDepDCAz", false, "Use pt-dependent DCAz cut"}; + Configurable cfgDcaZP0{"cfgDcaZP0", 0.0026f, "p0 for DCAz"}; + Configurable cfgDcaZP1{"cfgDcaZP1", 0.005f, "p1 for DCAz"}; + Configurable cfgDcaZP2{"cfgDcaZP2", 1.01f, "p2 for DCAz"}; + Configurable cfgITScluster{"cfgITScluster", 1, "Minimum Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 80, "Minimum Number of TPC cluster"}; Configurable cfgTPCnCrossedRows{"cfgTPCnCrossedRows", 70, "Minimum Number of TPC crossed-rows"}; @@ -166,79 +188,439 @@ struct RadialFlowDecorr { Configurable cfgnSigmaCutTPC{"cfgnSigmaCutTPC", 2.0f, "PID nSigma cut for TPC"}; Configurable cfgnSigmaCutTOF{"cfgnSigmaCutTOF", 2.0f, "PID nSigma cut for TOF"}; Configurable cfgnSigmaCutCombTPCTOF{"cfgnSigmaCutCombTPCTOF", 2.0f, "PID nSigma combined cut for TPC and TOF"}; + Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; - Configurable cfgCutPtLowerProt{"cfgCutPtLowerProt", 0.2f, "Lower pT cut"}; Configurable cfgCutPtUpper{"cfgCutPtUpper", 10.0f, "Higher pT cut for inclusive hadron analysis"}; Configurable cfgCutPtUpperPID{"cfgCutPtUpperPID", 6.0f, "Higher pT cut for identified particle analysis"}; Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; - Configurable cfgCutEtaLeft{"cfgCutEtaLeft", 0.8f, "Left end of eta gap"}; - Configurable cfgCutEtaRight{"cfgCutEtaRight", 0.8f, "Right end of eta gap"}; - Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; - Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FT0A, 3-->FT0M, 4-->FV0A"}; - Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", true, "Pileup removal"}; + Configurable cfgNsubsample{"cfgNsubsample", 10, "Number of subsamples"}; + Configurable cfgCentralityChoice{"cfgCentralityChoice", 1, "Which centrality estimator? 1-->FT0C, 2-->FT0M, 3-->FDDM, 4-->FV0A"}; + Configurable cfgEvSelNoSameBunchPileup{"cfgEvSelNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; - Configurable cfgEvSelkNoITSROFrameBorder{"cfgEvSelkNoITSROFrameBorder", true, "ITSROFrame border event selection cut"}; - Configurable cfgEvSelkNoTimeFrameBorder{"cfgEvSelkNoTimeFrameBorder", true, "TimeFrame border event selection cut"}; + Configurable cfgIsGoodZvtxFT0VsPV{"cfgIsGoodZvtxFT0VsPV", true, "Good Vertexing cut"}; + + Configurable cfgPupnSig{"cfgPupnSig", 6.0f, "Additional Pileup Cut"}; + Configurable cfgApplySigPupCut{"cfgApplySigPupCut", 0, "nSig Pileup Cut"}; + Configurable cfgApplyLinPupCut{"cfgApplyLinPupCut", 0, "Lin Pileup Cut"}; + Configurable cfgLinPupParam0{"cfgLinPupParam0", 3.0f, "(Upper) Linear Pileup Cut Const"}; + Configurable cfgLinPupParam1{"cfgLinPupParam1", 3.0f, "(Upper) Linear Pileup Slope"}; + Configurable cfgLinPupParam2{"cfgLinPupParam2", 3.0f, "(Lower) Linear Pileup Cut Const"}; + Configurable cfgLinPupParam3{"cfgLinPupParam3", 3.0f, "(Lower) Linear Pileup Slope"}; + + Configurable cfgNchPbMax{"cfgNchPbMax", 4000, "Max Nch range for PbPb collisions"}; + Configurable cfgNchOMax{"cfgNchOMax", 800, "Max Nch range for OO collisions"}; + + Configurable cfgSys{"cfgSys", 1, "Efficiency to be used for which system? 1-->PbPb, 2-->NeNe, 3-->OO, 4-->pp"}; + Configurable cfgFlat{"cfgFlat", false, "Whether to use flattening weights"}; + Configurable cfgEff{"cfgEff", false, "Whether to use Efficiency weights"}; + Configurable cfgZDC{"cfgZDC", false, "Whether to use ZDC for pileup histograms"}; + + Configurable cfgCCDBurl{"cfgCCDBurl", "https://alice-ccdb.cern.ch", "ccdb url"}; + Configurable cfgCCDBUserPath{"cfgCCDBUserPath", "/Users/s/somadutt", "Base CCDB path"}; + + ConfigurableAxis cfgAxisCent{"cfgAxisCent", {0.0, 1.0, 5.0, 10, 20, 40, 60, 80, 100}, "centrality axis (percentile)"}; + + const AxisSpec centAxis{cfgAxisCent, "Centrality (%)"}; + const AxisSpec centAxis1Per{100, 0.0, 100.0, "Centrality (%)"}; + AxisSpec nChAxis{1, 0., 1., "Nch", "Nch"}; + AxisSpec nChAxis2{1, 0., 1., "Nch", "Nch"}; + + const AxisSpec vzAxis{5, -12.5, 12.5, "Vz"}; + const AxisSpec chgAxis{3, -1.5, 1.5}; + const AxisSpec pTAxis{{0.0, 0.2, 0.4, 0.6, 0.8, 1, 3, 5, 7, 10}, "pT Axis"}; + const AxisSpec etaAxis{{-0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}, "Eta"}; + const AxisSpec phiAxis{KNbinsPhi, KPhiMin, TwoPI, "#phi"}; + const AxisSpec etaBinAxis{KNEta + 1, -0.5, KNEta + 0.5, "#eta bin Number"}; + const AxisSpec spBinAxis{KNsp + 1, -KBinOffset, static_cast(KNsp) + KBinOffset, "species index Number"}; + + const AxisSpec gapAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, + -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, + 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, + 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, + "Gap"}; + + const AxisSpec sumAxis{{-1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85, + -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, + 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, + 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55}, + "Sum"}; + + Configurable cfgRunMCGetNSig{"cfgRunMCGetNSig", false, "Run MC pass to get mean of Nsig Plots"}; + Configurable cfgRunGetEff{"cfgRunGetEff", false, "Run MC pass to build efficiency/fake maps"}; + Configurable cfgRunGetMCFlat{"cfgRunGetMCFlat", false, "Run MC to Get Flattening Weights"}; + Configurable cfgRunMCMean{"cfgRunMCMean", false, "Run MC mean(pT) & mean(Et)"}; + Configurable cfgRunMCFluc{"cfgRunMCFluc", false, "Run MC fluctuations (C2, subevent)"}; + + Configurable cfgRunDataGetNSig{"cfgRunDataGetNSig", false, "Run MC pass to get mean of Nsig Plots"}; + Configurable cfgRunGetDataFlat{"cfgRunGetDataFlat", false, "Run Data Get Flattening Weights"}; + Configurable cfgRunDataMean{"cfgRunDataMean", false, "Run DATA mean(pT) & mean(Et)"}; + Configurable cfgRunDataFluc{"cfgRunDataFluc", false, "Run DATA fluctuations (C2, subevent)"}; Service ccdb; Service pdg; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::array hEff{}; - std::array hFake{}; - std::array hWeightMap3D{}; + struct InternalState { + std::array hEff{}; + std::array hFake{}; + std::array hFlatWeight{}; + + std::vector> mLimitsNchCent; + float mMinXNchCent = 0, mMaxXNchCent = 0; + + TProfile3D* pmeanTruNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanRecoNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanRecoEffcorrNchEtabinSpbinStep2 = nullptr; + + TProfile3D* pmeanMultTruNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultRecoNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultRecoEffcorrNchEtabinSpbinStep2 = nullptr; + + TProfile3D* pmeanNchEtabinSpbinStep2 = nullptr; + TProfile3D* pmeanMultNchEtabinSpbinStep2 = nullptr; + + TProfile* pmeanFT0AmultpvStep2 = nullptr; + TProfile* pmeanFT0CmultpvStep2 = nullptr; + } state; + o2::ft0::Geometry ft0Det; + + template + void fillNSigmaBefCut(const T& track, float cent) + { + float pt = track.pt(); + auto sign = track.sign(); + + if (sign > 0) { + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiPlus"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiPlus"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiPlus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaPlus"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaPlus"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaPlus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_Pr"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_Pr"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_Pr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } else if (sign < 0) { + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiMinus"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiMinus"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiMinus"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaMinus"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaMinus"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaMinus"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_AntiPr"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_AntiPr"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_AntiPr"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PiAll"), cent, pt, track.tpcNSigmaPi()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PiAll"), cent, pt, track.tofNSigmaPi()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PiAll"), cent, track.tofNSigmaPi(), track.tpcNSigmaPi()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_KaAll"), cent, pt, track.tpcNSigmaKa()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_KaAll"), cent, pt, track.tofNSigmaKa()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_KaAll"), cent, track.tofNSigmaKa(), track.tpcNSigmaKa()); + + histos.fill(HIST("h3DnsigmaTpcVsPtBefCut_Cent_PrAll"), cent, pt, track.tpcNSigmaPr()); + histos.fill(HIST("h3DnsigmaTofVsPtBefCut_Cent_PrAll"), cent, pt, track.tofNSigmaPr()); + histos.fill(HIST("h3DnsigmaTpcVsTofBefCut_Cent_PrAll"), cent, track.tofNSigmaPr(), track.tpcNSigmaPr()); + } + + template + void fillNSigmaAftCut(const T& track, float cent, bool isSpecies[]) + { + float pt = track.pt(); + float tpcPi = track.tpcNSigmaPi(); + float tofPi = track.tofNSigmaPi(); + + float tpcKa = track.tpcNSigmaKa(); + float tofKa = track.tofNSigmaKa(); + + float tpcPr = track.tpcNSigmaPr(); + float tofPr = track.tofNSigmaPr(); + + if (isSpecies[kPiPlusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiPlus"), cent, pt, tpcPi); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiPlus"), cent, pt, tofPi); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiPlus"), cent, tofPi, tpcPi); + } + if (isSpecies[kPiMinusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiMinus"), cent, pt, tpcPi); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiMinus"), cent, pt, tofPi); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiMinus"), cent, tofPi, tpcPi); + } + if (isSpecies[kPiAllIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PiAll"), cent, pt, tpcPi); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PiAll"), cent, pt, tofPi); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PiAll"), cent, tofPi, tpcPi); + } + if (isSpecies[kKaPlusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaPlus"), cent, pt, tpcKa); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaPlus"), cent, pt, tofKa); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaPlus"), cent, tofKa, tpcKa); + } + if (isSpecies[kKaMinusIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaMinus"), cent, pt, tpcKa); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaMinus"), cent, pt, tofKa); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaMinus"), cent, tofKa, tpcKa); + } + if (isSpecies[kKaAllIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_KaAll"), cent, pt, tpcKa); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_KaAll"), cent, pt, tofKa); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_KaAll"), cent, tofKa, tpcKa); + } + if (isSpecies[kPrIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_Pr"), cent, pt, tpcPr); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_Pr"), cent, pt, tofPr); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_Pr"), cent, tofPr, tpcPr); + } + if (isSpecies[kAntiPrIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_AntiPr"), cent, pt, tpcPr); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_AntiPr"), cent, pt, tofPr); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_AntiPr"), cent, tofPr, tpcPr); + } + if (isSpecies[kPrAllIdx]) { + histos.fill(HIST("h3DnsigmaTpcVsPtAftCut_Cent_PrAll"), cent, pt, tpcPr); + histos.fill(HIST("h3DnsigmaTofVsPtAftCut_Cent_PrAll"), cent, pt, tofPr); + histos.fill(HIST("h3DnsigmaTpcVsTofAftCut_Cent_PrAll"), cent, tofPr, tpcPr); + } else { + return; + } + } + + // Returns: 0 = Unknown/Reject, 1 = Pion, 2 = Kaon, 3 = Proton + template + int identifyTrack(const T& candidate, int cent) + { + if (!candidate.hasTPC()) + return 0; + + float pt = candidate.pt(); + if (pt <= cfgCutPtLower || pt >= cfgCutPtUpperPID) + return 0; // Out of bounds + + if (!pidMeanSigmaMap) + return 0; + + int centBin = cent + 0.5; + auto charge = candidate.sign(); + int piIdx = (charge > 0) ? kPiPlusIdx : kPiMinusIdx; + int kaIdx = (charge > 0) ? kKaPlusIdx : kKaMinusIdx; + int prIdx = (charge > 0) ? kPrIdx : kAntiPrIdx; + + // TPC + float mPiTpc = pidMeanSigmaMap->meanTPC[piIdx][centBin]; + float sPiTpc = pidMeanSigmaMap->sigmaTPC[piIdx][centBin]; + + float mKaTpc = pidMeanSigmaMap->meanTPC[kaIdx][centBin]; + float sKaTpc = pidMeanSigmaMap->sigmaTPC[kaIdx][centBin]; + + float mPrTpc = pidMeanSigmaMap->meanTPC[prIdx][centBin]; + float sPrTpc = pidMeanSigmaMap->sigmaTPC[prIdx][centBin]; + + // TOF + float mPiTof = pidMeanSigmaMap->meanTOF[piIdx][centBin]; + float sPiTof = pidMeanSigmaMap->sigmaTOF[piIdx][centBin]; - TProfile3D* pmeanTruNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanRecoNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanRecoMatchedNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanRecoEffcorrNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanRecoMatchedEffcorrNchEtabinPtbinStep2 = nullptr; + float mKaTof = pidMeanSigmaMap->meanTOF[kaIdx][centBin]; + float sKaTof = pidMeanSigmaMap->sigmaTOF[kaIdx][centBin]; - TProfile3D* pmeanEtTruNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtRecoNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtRecoMatchedNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtRecoEffcorrNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtRecoMatchedEffcorrNchEtabinPtbinStep2 = nullptr; + float mPrTof = pidMeanSigmaMap->meanTOF[prIdx][centBin]; + float sPrTof = pidMeanSigmaMap->sigmaTOF[prIdx][centBin]; + + static int debugLogCounter = 0; + if (debugLogCounter < KConstTen) { + LOGF(info, "[PID DEBUG] CentBin: %d, Charge: %d", centBin, charge); + LOGF(info, " -> TPC USED | Pi (\u03bc=%.3f, \u03c3=%.3f) | Ka (\u03bc=%.3f, \u03c3=%.3f) | Pr (\u03bc=%.3f, \u03c3=%.3f)", + mPiTpc, sPiTpc, mKaTpc, sKaTpc, mPrTpc, sPrTpc); + + if (candidate.hasTOF()) { + LOGF(info, " -> TOF USED | Pi (\u03bc=%.3f, \u03c3=%.3f) | Ka (\u03bc=%.3f, \u03c3=%.3f) | Pr (\u03bc=%.3f, \u03c3=%.3f)", + mPiTof, sPiTof, mKaTof, sKaTof, mPrTof, sPrTof); + } else { + LOGF(info, " -> TOF USED | Track has no TOF signal."); + } + debugLogCounter++; + } + // Fetch Raw nSigma Values + float rawTpcPi = candidate.tpcNSigmaPi(); + float rawTpcKa = candidate.tpcNSigmaKa(); + float rawTpcPr = candidate.tpcNSigmaPr(); + + float rawTofPi = 0.f, rawTofKa = 0.f, rawTofPr = 0.f; + if (candidate.hasTOF()) { + rawTofPi = candidate.tofNSigmaPi(); + rawTofKa = candidate.tofNSigmaKa(); + rawTofPr = candidate.tofNSigmaPr(); + } + + // --- Low PT Regime --- + if (pt <= cfgCutPtUpperTPC) { + // Basic TPC passing check: |Raw - Mean| < (Cut * Sigma) + bool inTpcPi = std::abs(rawTpcPi - mPiTpc) < (cfgnSigmaCutTPC * sPiTpc); + bool inTpcKa = std::abs(rawTpcKa - mKaTpc) < (cfgnSigmaCutTPC * sKaTpc); + bool inTpcPr = std::abs(rawTpcPr - mPrTpc) < (cfgnSigmaCutTPC * sPrTpc); + + // Combined passing check (adds TOF if available) + bool passPi = inTpcPi && (!candidate.hasTOF() || std::abs(rawTofPi - mPiTof) < (cfgnSigmaCutTOF * sPiTof)); + bool passKa = inTpcKa && (!candidate.hasTOF() || std::abs(rawTofKa - mKaTof) < (cfgnSigmaCutTOF * sKaTof)); + bool passPr = inTpcPr && (!candidate.hasTOF() || std::abs(rawTofPr - mPrTof) < (cfgnSigmaCutTOF * sPrTof)); + + // Uniqueness check: Must pass target cut, and NOT fall into the TPC range of the others + if (passPi && !passKa && !passPr) + return 1; + if (passKa && !passPi && !passPr) + return 2; + if (passPr && !passPi && !passKa) + return 3; + + return 0; // Ambiguous or failed all cuts + } - TProfile3D* pmeanNchEtabinPtbinStep2 = nullptr; - TProfile3D* pmeanEtNchEtabinPtbinStep2 = nullptr; + // --- High PT Regime--- + if (candidate.hasTOF() && pt > cfgCutPtUpperTPC) { + // Calculate 2D Normalized Distance (Elliptical distance normalized by sigma) + float dPi = std::hypot((rawTpcPi - mPiTpc) / sPiTpc, (rawTofPi - mPiTof) / sPiTof); + float dKa = std::hypot((rawTpcKa - mKaTpc) / sKaTpc, (rawTofKa - mKaTof) / sKaTof); + float dPr = std::hypot((rawTpcPr - mPrTpc) / sPrTpc, (rawTofPr - mPrTof) / sPrTof); + + // Count how many particles are within the ambiguity radius + int competitors = (dPi < cfgnSigmaOtherParticles) + + (dKa < cfgnSigmaOtherParticles) + + (dPr < cfgnSigmaOtherParticles); + + // If 1 or fewer are in the ambiguity region, pick the absolute best match + if (competitors <= 1) { + if (dPi <= dKa && dPi <= dPr && dPi < cfgnSigmaCutCombTPCTOF) + return 1; + if (dKa <= dPi && dKa <= dPr && dKa < cfgnSigmaCutCombTPCTOF) + return 2; + if (dPr <= dPi && dPr <= dKa && dPr < cfgnSigmaCutCombTPCTOF) + return 3; + } + } + return 0; // Unknown/Reject + } template bool isEventSelected(const T& col) { + histos.fill(HIST("hEvtCount"), 0.5); + if (!col.sel8()) return false; + histos.fill(HIST("hEvtCount"), 1.5); + if (std::abs(col.posZ()) > cfgCutVertex) return false; - if (cfgEvSelkNoSameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + histos.fill(HIST("hEvtCount"), 2.5); + + if (cfgEvSelNoSameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) return false; - if (cfgEvSelkNoITSROFrameBorder && !col.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + histos.fill(HIST("hEvtCount"), 3.5); + + if (cfgUseGoodITSLayerAllCut && !col.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) return false; - if (cfgEvSelkNoTimeFrameBorder && !col.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + histos.fill(HIST("hEvtCount"), 4.5); + + if (cfgIsGoodZvtxFT0VsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; + histos.fill(HIST("hEvtCount"), 5.5); + return true; + } + + bool isPassAddPileup(int multPV, int trksize, float cent) + { + auto checkLimits = [](float x, float y, const std::vector>& limits, float xM, float xMx) { + if (limits.empty()) + return true; + int bin = 1 + static_cast((x - xM) / (xMx - xM) * (limits.size() - 2)); + if (bin < 1 || bin >= static_cast(limits.size() - 1)) + return false; + return (y >= limits[bin].first && y <= limits[bin].second); + }; + if (cfgApplySigPupCut) { + if (!checkLimits(cent, trksize, state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent)) + return false; + histos.fill(HIST("hEvtCount"), 6.5); + } + + if (cfgApplyLinPupCut) { + if (trksize > (cfgLinPupParam0 + cfgLinPupParam1 * multPV)) + return false; + histos.fill(HIST("hEvtCount"), 7.5); + if (trksize < (cfgLinPupParam2 + cfgLinPupParam3 * multPV)) + return false; + histos.fill(HIST("hEvtCount"), 8.5); + } return true; } template bool isTrackSelected(const T& trk) { + histos.fill(HIST("hTrkCount"), 0.5); + if (trk.sign() == 0) return false; + histos.fill(HIST("hTrkCount"), 1.5); + if (!trk.has_collision()) return false; + histos.fill(HIST("hTrkCount"), 2.5); + if (!trk.isPVContributor()) return false; + histos.fill(HIST("hTrkCount"), 3.5); + if (!(trk.itsNCls() > cfgITScluster)) return false; + histos.fill(HIST("hTrkCount"), 4.5); + if (!(trk.tpcNClsFound() >= cfgTPCcluster)) return false; + histos.fill(HIST("hTrkCount"), 5.5); + if (!(trk.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) return false; + histos.fill(HIST("hTrkCount"), 6.5); if (trk.pt() < cfgCutPtLower || trk.pt() > cfgCutPtUpper || std::abs(trk.eta()) > cfgCutEta) return false; - if (std::abs(trk.dcaXY()) > cfgCutTracKDcaMaxXY || std::abs(trk.dcaZ()) > cfgCutTracKDcaMaxZ) + histos.fill(HIST("hTrkCount"), 7.5); + + if (!trk.isGlobalTrack()) return false; + histos.fill(HIST("hTrkCount"), 8.5); + + if (cfgPtDepDCAxy) { + // Evaluates: P0 + P1 / (pt^P2) + float maxDcaXY = cfgDcaXyP0 + cfgDcaXyP1 / std::pow(trk.pt(), cfgDcaXyP2); + if (std::abs(trk.dcaXY()) > maxDcaXY) { + return false; + } + histos.fill(HIST("hTrkCount"), 9.5); + } else { + if (std::abs(trk.dcaXY()) > cfgCutTracKDcaMaxXY) { + return false; + } + histos.fill(HIST("hTrkCount"), 9.5); + } + if (cfgPtDepDCAz) { + // Evaluates: P0 + P1 / (pt^P2) + float maxDcaZ = cfgDcaZP0 + cfgDcaZP1 / std::pow(trk.pt(), cfgDcaZP2); + if (std::abs(trk.dcaZ()) > maxDcaZ) { + return false; // Reject track if DCA is too large + } + histos.fill(HIST("hTrkCount"), 10.5); + } else { + if (std::abs(trk.dcaZ()) > cfgCutTracKDcaMaxZ) { + return false; + } + histos.fill(HIST("hTrkCount"), 10.5); + } return true; } @@ -248,7 +630,6 @@ struct RadialFlowDecorr { auto* pd = pdg->GetParticle(particle.pdgCode()); if (!pd) return false; - // if (dpt::isStrangeBaryonPDG(particle.pdgCode())) return false; if (std::abs(pd->Charge()) == 0) return false; if (particle.pt() < cfgCutPtLower || particle.pt() > cfgCutPtUpper || std::abs(particle.eta()) > cfgCutEta) @@ -258,165 +639,97 @@ struct RadialFlowDecorr { return true; } - template - bool selectionProton(const T& candidate) - { - if (!candidate.hasTPC()) - return false; - int flag = 0; - - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC) { - flag = 1; - } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPr()) < cfgnSigmaCutTOF) { - flag = 1; - } - } - if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); - float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); - float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); - - int flag2 = 0; - if (combNSigmaPr < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaPi < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaKa < cfgnSigmaOtherParticles) - flag2 += 1; - if (!(flag2 > 1) && !(combNSigmaPr > combNSigmaPi) && !(combNSigmaPr > combNSigmaKa)) { - if (combNSigmaPr < cfgnSigmaCutCombTPCTOF) { - flag = 1; - } - } - } - if (flag == 1) - return true; - else - return false; - } - - template - bool selectionPion(const T& candidate) - { - if (!candidate.hasTPC()) - return false; - int flag = 0; - - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPC) { - flag = 1; - } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaPi()) < cfgnSigmaCutTOF) { - flag = 1; - } - } - if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); - float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); - float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); - - int flag2 = 0; - if (combNSigmaPr < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaPi < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaKa < cfgnSigmaOtherParticles) - flag2 += 1; - if (!(flag2 > 1) && !(combNSigmaPi > combNSigmaPr) && !(combNSigmaPi > combNSigmaKa)) { - if (combNSigmaPi < cfgnSigmaCutCombTPCTOF) { - flag = 1; - } - } - } - if (flag == 1) - return true; - else - return false; - } - - template - bool selectionKaon(const T& candidate) - { - if (!candidate.hasTPC()) - return false; - int flag = 0; - - if (candidate.pt() > cfgCutPtLower && candidate.pt() <= cfgCutPtUpperTPC) { - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPC) { - flag = 1; - } - if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < cfgnSigmaCutTPC && std::abs(candidate.tofNSigmaKa()) < cfgnSigmaCutTOF) { - flag = 1; - } - } - if (candidate.hasTOF() && candidate.pt() > cfgCutPtUpperTPC && candidate.pt() < cfgCutPtUpperPID) { - float combNSigmaPr = std::sqrt(std::pow(candidate.tpcNSigmaPr(), 2.0) + std::pow(candidate.tofNSigmaPr(), 2.0)); - float combNSigmaPi = std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2.0) + std::pow(candidate.tofNSigmaPi(), 2.0)); - float combNSigmaKa = std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2.0) + std::pow(candidate.tofNSigmaKa(), 2.0)); - - int flag2 = 0; - if (combNSigmaPr < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaPi < cfgnSigmaOtherParticles) - flag2 += 1; - if (combNSigmaKa < cfgnSigmaOtherParticles) - flag2 += 1; - if (!(flag2 > 1) && !(combNSigmaKa > combNSigmaPi) && !(combNSigmaKa > combNSigmaPr)) { - if (combNSigmaKa < cfgnSigmaCutCombTPCTOF) { - flag = 1; - } - } - } - if (flag == 1) - return true; - else - return false; - } - float getCentrality(const auto& col) const { if (cfgCentralityChoice.value == kCentFT0C) return col.centFT0C(); - if (cfgCentralityChoice.value == kCentFT0A) - return col.centFT0A(); if (cfgCentralityChoice.value == kCentFT0M) return col.centFT0M(); + if (cfgCentralityChoice.value == kCentFDDM) + return col.centFDDM(); if (cfgCentralityChoice.value == kCentFV0A) return col.centFV0A(); return KinvalidCentrality; } - float getEfficiency(float mult, float pt, float eta, PID pidType, int effidx) const + float getEfficiency(float mult, float pt, float eta, PIDIdx pidType, int effidx, bool cfgEff) const { - TH3F* h = nullptr; - if (effidx == 0) - h = hEff[pidType]; - if (effidx == 1) - h = hFake[pidType]; + if (!cfgEff) { + return (effidx == 0) ? 1.0f : 0.0f; + } + TH3F* h = (effidx == 0) ? state.hEff[pidType] : state.hFake[pidType]; if (!h) return -1; - const int ibx = h->GetXaxis()->FindBin(mult); - const int iby = h->GetYaxis()->FindBin(pt); - const int ibz = h->GetZaxis()->FindBin(eta); + + int ibx = h->GetXaxis()->FindBin(mult); + int iby = h->GetYaxis()->FindBin(pt); + int ibz = h->GetZaxis()->FindBin(eta); float val = h->GetBinContent(ibx, iby, ibz); + + if (effidx == 0) + return (val > 0.f) ? val : 1.0f; return val; } - float getFlatteningWeight(float cent, float eta, float phi, PID pidType) const + float getFlatteningWeight(float vz, float chg, float pt, float eta, float phi, PIDIdx pidType, bool cfgflat) const { - TH3F* h = hWeightMap3D[pidType]; + if (!cfgflat) + return 1.0; + THnSparseF* h = state.hFlatWeight[pidType]; + if (!h) - return -1; - const int ibx = h->GetXaxis()->FindBin(cent); - const int iby = h->GetYaxis()->FindBin(eta); - const int ibz = h->GetZaxis()->FindBin(phi); - float val = h->GetBinContent(ibx, iby, ibz); + return 0.0; + int bins[5]; + bins[0] = h->GetAxis(0)->FindBin(vz); + bins[1] = h->GetAxis(1)->FindBin(chg); + bins[2] = h->GetAxis(2)->FindBin(pt); + bins[3] = h->GetAxis(3)->FindBin(eta); + bins[4] = h->GetAxis(4)->FindBin(phi); + float val = h->GetBinContent(bins); + return val; } + std::vector* offsetFT0 = nullptr; + uint64_t mLastTimestamp = 0; + double getEtaFT0(uint64_t globalChno, int i) + { + if (i > 1 || i < 0) { + LOGF(fatal, "kFIT Index %d out of range", i); + } + auto chPos = ft0Det.getChannelCenter(globalChno); + auto x = chPos.X() + (*offsetFT0)[i].getX(); + auto y = chPos.Y() + (*offsetFT0)[i].getY(); + auto z = chPos.Z() + (*offsetFT0)[i].getZ(); + // i == 0 is FT0A (A-side, positive Z) + // i == 1 is FT0C (C-side, negative Z) + if (i == 1) { + z = -std::abs(z); + } else if (i == 0) { + z = std::abs(z); + } + auto r = std::sqrt(x * x + y * y); + auto theta = std::atan2(r, z); + return -std::log(std::tan(0.5 * theta)); + } + + void loadAlignParam(uint64_t timestamp) + { + if (timestamp == mLastTimestamp && offsetFT0 != nullptr) { + return; + } + offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", timestamp); + if (!offsetFT0) { + LOGF(fatal, "Failed to load valid FT0 alignment from CCDB!"); + return; + } + mLastTimestamp = timestamp; + LOGF(info, "Successfully loaded new alignment parameters for timestamp %llu", timestamp); + LOGF(info, "Offset for FT0A: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[0].getX(), (*offsetFT0)[0].getY(), (*offsetFT0)[0].getZ()); + LOGF(info, "Offset for FT0C: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[1].getX(), (*offsetFT0)[1].getY(), (*offsetFT0)[1].getZ()); + } + template std::pair calculateMeanAndC2FromSums(const double sumpmwk[KIntM][KIntK], const double sumwk[KIntK], float referenceMeanPt) const { @@ -456,27 +769,11 @@ struct RadialFlowDecorr { return {calculatedMeanPt, twopcorr}; } - ConfigurableAxis cfgAxisCent{"cfgAxisCent", {0.0, 1.0, 3.0, 5.0, 10, 20, 30, 40, 50, 60, 70, 80, 100}, "centrality axis (percentile)"}; // FT0*/FV0A style - const AxisSpec centAxis{cfgAxisCent, "Centrality (%)"}; - static constexpr int KNbinsNch = 5000; - static constexpr float KNchMax = 5000.5f; - static constexpr int KNbinsNchCoarse = 500; - ConfigurableAxis nChAxis{"nChAxis", {KNbinsNch, KBinOffset, KNchMax}, "PV-contributor track multiplicity axis"}; - ConfigurableAxis nChAxis2{"nChAxis2", {KNbinsNchCoarse, KBinOffset, KNchMax}, "PV-contributor track multiplicity axis"}; - - Configurable cfgRunGetEff{"cfgRunGetEff", false, "Run MC pass to build efficiency/fake maps"}; - Configurable cfgRunMCMean{"cfgRunMCMean", false, "Run MC mean(pT) & mean(Et)"}; - Configurable cfgRunMCFluc{"cfgRunMCFluc", false, "Run MC fluctuations (C2, subevent)"}; - Configurable cfgRunGetFlat{"cfgRunGetFlat", false, "Run Data Get Flattening Weights"}; - Configurable cfgRunDataMean{"cfgRunDataMean", false, "Run DATA mean(pT) & mean(Et)"}; - Configurable cfgRunDataFluc{"cfgRunDataFluc", false, "Run DATA fluctuations (C2, subevent)"}; + using GeneralCollisions = soa::Join; - using GeneralCollisions = soa::Join< - aod::Collisions, - aod::EvSels, - aod::Mults, - aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFV0As, - aod::CentNGlobals>; Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZCut; using AodCollisionsSel = soa::Filtered; @@ -485,271 +782,298 @@ struct RadialFlowDecorr { aod::TracksExtra, aod::TrackSelection, aod::TracksDCA, - aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, - aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; - Filter trackFilter = nabs(aod::track::eta) < cfgEtaCut && - aod::track::pt > cfgPtMin&& - aod::track::pt < cfgPtMax&& - nabs(aod::track::dcaXY) < cfgDCAXY&& nabs(aod::track::dcaZ) < cfgDCAZ; + aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullEl, + aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullEl>; + Filter trackFilter = aod::track::pt > KPtMin&& + aod::track::pt < KPtMax&& + requireGlobalTrackInFilter(); using AodTracksSel = soa::Filtered; using TCs = soa::Join; using FilteredTCs = soa::Filtered; + using BCsRun3 = soa::Join; using MyRun3MCCollisions = soa::Join< aod::Collisions, aod::EvSels, aod::Mults, aod::MultsExtra, - aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFV0As, + aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFDDMs, aod::CentFV0As, aod::CentNGlobals, aod::McCollisionLabels>; - using MyMCTracks = soa::Join< - aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA, - aod::McTrackLabels, - aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, - aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; - - PresliceUnsorted partPerMcCollision = aod::mcparticle::mcCollisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; - PresliceUnsorted trackPerMcParticle = aod::mctracklabel::mcParticleId; - Preslice perCollision = aod::track::collisionId; - Preslice trackPerCollision = aod::track::collisionId; void declareCommonQA() { - histos.add("hZvtx_after_sel", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); + histos.add("hVtxZ_after_sel", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); histos.add("hVtxZ", ";z_{vtx} (cm)", kTH1F, {{KNbinsZvtx, KZvtxMin, KZvtxMax}}); - histos.add("hCentrality", ";centrality (%)", kTH1F, {{centAxis}}); - histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis2}, {nChAxis2}}); - histos.add("Hist2D_cent_nch", ";N_{PV};cent (%)", kTH2F, {{nChAxis2}, {centAxis}}); - histos.add("hP", ";p (GeV/c)", kTH1F, {{KNbinsP, KPMin, KPMax}}); - histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); - histos.add("hEta", ";#eta", kTH1F, {{KNbinsEta, KEtaMin, KEtaMax}}); - histos.add("hPhi", ";#phi", kTH1F, {{KNbinsPhi, KPhiMin, TwoPI}}); - - histos.add("hCentEtaPhi", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCent1EtaPhi", ";#eta;#phi", kTH2F, {{(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCent7EtaPhi", ";#eta;#phi", kTH2F, {{(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCentEtaPhiWtd", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCent1EtaPhiWtd", ";#eta;#phi", kTH2F, {{(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCent7EtaPhiWtd", ";#eta;#phi", kTH2F, {{(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("hCentrality", ";centrality (%)", kTH1F, {{centAxis1Per}}); + histos.add("Hist2D_globalTracks_PVTracks", ";N_{global};N_{PV}", kTH2F, {{nChAxis}, {nChAxis}}); + histos.add("Hist2D_cent_nch", ";N_{PV};cent (%)", kTH2F, {{nChAxis}, {centAxis1Per}}); - histos.add("hCentEtaPhiWtd_PID", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCent1EtaPhiWtd_PID", ";#eta;#phi", kTH2F, {{(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCent7EtaPhiWtd_PID", ";#eta;#phi", kTH2F, {{(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("Hist2D_globalTracks_cent", "cent (%);N_{global}", kTH2F, {{centAxis1Per}, {nChAxis}}); + histos.add("Hist2D_PVTracks_cent", "cent (%);N_{PV}", kTH2F, {{centAxis1Per}, {nChAxis}}); - histos.add("hCentEtaPhiTrue", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCentEtaPhiReco", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCentEtaPhiRecoMatched", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("hP", ";p (GeV/c)", kTH1F, {{KNbinsPt, KPMin, KPMax}}); + histos.add("hPt", ";p_{T} (GeV/c)", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); + histos.add("hEta", ";#eta", kTH1F, {{KNbinsEtaFine, KEtaMin, KEtaMax}}); + histos.add("hPhi", ";#phi", kTH1F, {{KNbinsPhi, KPhiMin, TwoPI}}); - histos.add("hCentEtaPhiTrue_PID", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCentEtaPhiReco_PID", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); - histos.add("hCentEtaPhiRecoMatched_PID", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, KPhiMin, TwoPI}}); + histos.add("hEvtCount", "Number of Event;; Count", kTH1F, {{9, 0, 9}}); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(1, "all Events"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(3, "after VertexZ Cut"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(4, "after kNoSameBunchPileup"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(5, "after kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(6, "after kIsGoodITSLayersAll"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(7, "after PVTracksCent Pileup Cut"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(8, "after Linear Pileup Cut (Up)"); + histos.get(HIST("hEvtCount"))->GetXaxis()->SetBinLabel(9, "after Linear Pileup Cut (Lw)"); + + histos.add("hTrkCount", "Number of Tracks;; Count", kTH1F, {{11, 0, 11}}); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(1, "all Tracks"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(2, "after sign!=0"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(3, "after has_collision"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(4, "after isPVContributor"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(5, "after itsNCls"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(6, "after tpcNClsFound"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(7, "after tpcNClsCrossedRows"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(8, "after pT,#eta selections"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(9, "after isGlobalTrack"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(10, "after dcaXY"); + histos.get(HIST("hTrkCount"))->GetXaxis()->SetBinLabel(11, "after dcaZ"); } + void declareMCCommonHists() { + for (const auto& suf : pidSuffix) { + histos.add("h3_AllPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoMatchedToPrimary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_AllReco" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoUnMatchedToPrimary_Secondary" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoUnMatchedToPrimary_Fake" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + histos.add("h3_RecoMatchedToPrimary_MisID" + suf, ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, KPtMin, KPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + } - histos.add("ptResolution", ";p_{T}^{MC};p_{T}^{MC}-p_{T}^{reco}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, -KPtResMax, KPtResMax}}); - histos.add("ptTruthReco", ";p_{T}^{MC};p_{T}^{reco}", kTH2F, {{KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("etaResolution", ";#eta^{MC};#eta^{MC}-#eta^{reco}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {KNbinsPtRes, -KEtaResMax, KEtaResMax}}); - histos.add("etaTruthReco", ";#eta^{MC};#eta^{reco}", kTH2F, {{KNbinsPtRes, -KEtaFineMax, KEtaFineMax}, {KNbinsPtRes, -KEtaFineMax, KEtaFineMax}}); - + histos.add("ptResolution", ";p_{T}^{MC};(p_{T}^{reco}-p_{T}^{MC})/p_{T}^{MC}", kTH2F, {{KNbinsPtRes, KPtMin, KPtMax}, {100, -0.2, 0.2}}); + histos.add("etaResolution", ";#eta^{MC};#eta^{reco}-#eta^{MC}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {100, -0.02, 0.02}}); + histos.add("etaTruthReco", ";#eta^{MC};#eta^{reco}", kTH2F, {{KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}, {KNbinsEtaRes, -KEtaFineMax, KEtaFineMax}}); histos.add("TruthTracKVz", ";Vz^{MC};Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, KVzMin, KVzMax}}); - histos.add("vzResolution", ";Vz^{MC};Vz^{MC}-Vz^{Reco}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {KNbinsVz, -KVzResMax, KVzResMax}}); - - histos.add("h3_AllPrimary", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoMatchedToPrimary", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Secondary", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Fake", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_AllReco", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - - histos.add("h3_AllPrimary_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoMatchedToPrimary_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Secondary_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_RecoUnMatchedToPrimary_Fake_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("h3_AllReco_PID", ";N_{PV};p_{T};#eta", kTH3F, {{nChAxis2}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - - histos.add("h_AllPrimary", ";p_{T}", kTH1F, {{KNbinsP, cfgPtMin, cfgPtMax}}); - histos.add("h_RecoMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); - histos.add("h_RecoUnMatchedToPrimary", ";p_{T}", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); - histos.add("h_AllReco", ";p_{T}", kTH1F, {{KNbinsPt, KPtMin, KPtMax}}); - - histos.add("hReco_ParticleWeight", ";cent;p_{T};#eta", kTH3F, {{centAxis}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, -KEtaFineMax, KEtaFineMax}}); - histos.add("hTruth_ParticleWeight", ";cent;p_{T};#eta", kTH3F, {{centAxis}, {KNbinsPtRes, cfgPtMin, cfgPtMax}, {KNbinsPtRes, -KEtaFineMax, KEtaFineMax}}); - - histos.add("hDCAxy_Unmatched", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAz_Unmatched", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAxy_NotPrimary", ";DCA_{xy} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); - histos.add("hDCAz_NotPrimary", ";DCA_{z} (cm)", kTH1F, {{KNbinsDca, -KDcaMax, KDcaMax}}); + histos.add("vzResolution", ";Vz^{MC};(Vz^{reco}-Vz^{MC})/Vz^{MC}", kTH2F, {{KNbinsVz, KVzMin, KVzMax}, {100, -0.1, 0.1}}); + } + + void declarenSigHists() + { + for (const auto& suf : pidSuffix) { + histos.add("h3DnsigmaTpcVsPtBefCut_Cent" + suf, "TPC nSigma vs pT Before Cut;cent [%]; p_{T} (GeV/c);n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTofVsPtBefCut_Cent" + suf, "TOF nSigma vs pT Before Cut;cent [%]; p_{T} (GeV/c);n#sigma_{TOF}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTpcVsTofBefCut_Cent" + suf, "TPC vs TOF nSigma Before Cut;cent [%]; n#sigma_{TOF};n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {200, -10.f, 10.f}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTpcVsPtAftCut_Cent" + suf, "TPC nSigma vs pT After Cut;cent [%],; p_{T} (GeV/c);n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTofVsPtAftCut_Cent" + suf, "TOF nSigma vs pT After Cut;cent [%],; p_{T} (GeV/c);n#sigma_{TOF}", kTH3F, {{centAxis1Per}, {KNbinsPtRes, KPtMin, KPtMax}, {200, -10.f, 10.f}}); + histos.add("h3DnsigmaTpcVsTofAftCut_Cent" + suf, "TPC vs TOF nSigma After Cut;cent [%],; n#sigma_{TOF};n#sigma_{TPC}", kTH3F, {{centAxis1Per}, {200, -10.f, 10.f}, {200, -10.f, 10.f}}); + } + } + + void declareMCGetFlatHists() + { + for (const auto& suf : pidSuffix) { + histos.add("MCGen/hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("MCGen/hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("MCGen/hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + } } void declareMCMeanHists() { - histos.add("Eff_cent", ";cent;#epsilon", kTProfile, {centAxis}); - histos.add("Fake_cent", ";cent;f_{fake}", kTProfile, {centAxis}); - histos.add("wgt_cent", ";cent;w", kTProfile, {centAxis}); - histos.add("Eff_Ntrk", ";N_{PV};#epsilon", kTProfile, {nChAxis2}); - histos.add("Fake_Ntrk", ";N_{PV};f_{fake}", kTProfile, {nChAxis2}); - histos.add("wgt_Ntrk", ";N_{PV};w", kTProfile, {nChAxis2}); - histos.add("Eff_pT", ";p_{T};#epsilon", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("Fake_pT", ";p_{T};f_{fake}", kTProfile, {{KNbinsPtRes, cfgPtMin, cfgPtMax}}); - histos.add("wgt_pT", ";p_{T};w", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); - histos.add("Eff_eta", ";#eta;#epsilon", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("Fake_eta", ";#eta;f_{fake}", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - histos.add("wgt_eta", ";#eta;w", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); - // MC mean profiles (pT & Et) for various selections - histos.add("MCGen/Prof_cent_Nchrec", ";cent;#LT N_{PV}#GT", kTProfile, {centAxis}); - histos.add("MCGen/Prof_MeanpT_Cent", ";cent;#LT p_{T}#GT", kTProfile, {centAxis}); - histos.add("MCGen/Prof_MeanpT_Mult", ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); - histos.add("pmeanTruNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoMatchedNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoMatchedEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("MCGen/Prof_MeanEt_Cent", ";cent;#LT E_{T}#GT", kTProfile, {centAxis}); - histos.add("MCGen/Prof_MeanEt_Mult", ";N_{PV};#LT E_{T}#GT", kTProfile, {nChAxis}); - histos.add("pmeanEtTruNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoMatchedNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoMatchedEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.addClone("MCGen/", "MCReco/"); - histos.addClone("MCGen/", "MCRecoMatched/"); - histos.addClone("MCGen/", "MCRecoEffCorr/"); - histos.addClone("MCGen/", "MCRecoMatchedEffCorr/"); + histos.add("Eff_cent", ";cent", kTProfile, {centAxis1Per}); + histos.add("Eff_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); + histos.add("Eff_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); + histos.add("Eff_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + + histos.add("Fake_cent", ";cent", kTProfile, {centAxis1Per}); + histos.add("Fake_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); + histos.add("Fake_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); + histos.add("Fake_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + + histos.add("wgt_cent", ";cent", kTProfile, {centAxis1Per}); + histos.add("wgt_Ntrk", ";N_{PV}", kTProfile, {nChAxis2}); + histos.add("wgt_pT", ";p_{T}", kTProfile, {{KNbinsPtRes, KPtMin, KPtMax}}); + histos.add("wgt_eta", ";#eta", kTProfile, {{KNbinsEtaFine, -KEtaFineMax, KEtaFineMax}}); + + histos.add("pmeanFT0Amultpv", ";N_{PV};Ampl", kTProfile, {nChAxis}); + histos.add("pmeanFT0Cmultpv", ";N_{PV};Ampl", kTProfile, {nChAxis}); + histos.add("pmeanFT0A_cent", ";cent;Ampl", kTProfile, {centAxis1Per}); + histos.add("pmeanFT0C_cent", ";cent;Ampl", kTProfile, {centAxis1Per}); + histos.add("pmean_cent_id_eta_FT0", ";cent;id;#eta", kTProfile3D, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); + histos.add("h3_cent_id_eta_FT0", ";cent;id;#eta", kTH3F, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); + + histos.add("MCGen/Prof_Cent_Nsp_Nchrec", ";cent;isp", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_Nsp_Nchrec", ";mult;isp", kTProfile2D, {{nChAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cent_Nsp_MeanpT", ";cent;isp", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_Nsp_MeanpT", ";mult;isp", kTProfile2D, {{nChAxis}, {spBinAxis}}); + + histos.add("pmeanTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + + histos.add("pmeanMultTru_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanMultReco_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("pmeanMultRecoEffcorr_nch_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + + histos.add("Prof2D_MeanpTSub_Tru" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); + histos.add("Prof2D_MeanpTSub_Reco" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); + histos.add("Prof2D_MeanpTSub_RecoEffCorr" + suf, ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {etaBinAxis}}); + } } + void declareMCFlucHists() { - static constexpr int KNbinsNchFluc = 1000; - - ConfigurableAxis nChAxis{"nChAxis", {KNbinsNch, KBinOffset, KNchMax}, "PV-contributor track multiplicity axis"}; - ConfigurableAxis nChAxis2{"nChAxis2", {KNbinsNchCoarse, KBinOffset, KNchMax}, "PV-contributor track multiplicity axis"}; - - // pT cumulants - histos.add("MCGen/Prof_C2_Cent", ";cent;C_{2}", kTProfile, {centAxis}); - histos.add("MCGen/Prof_C2_Mult", ";N_{PV};C_{2}", kTProfile, {nChAxis}); - histos.add("MCGen/Prof_C2Sub_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{KNbinsNchFluc, KBinOffset, KNchMax}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_ipt0_C2Sub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt1_C2Sub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt2_C2Sub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt0_Cov_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt0_Cov_Eta", ";#eta;cov", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt1_Cov_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt1_Cov_Eta", ";#eta;cov", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt2_Cov_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt2_Cov_Eta", ";#eta;cov", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("MCGen/Prof_C2Et_Cent", ";cent;C_{2}^{E_{T}}", kTProfile, {centAxis}); - histos.add("MCGen/Prof_C2Et_Mult", ";N_{PV};C_{2}^{E_{T}}", kTProfile, {nChAxis}); - histos.add("MCGen/Prof_C2EtSub_Mult_etabin_ptbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{KNbinsNchFluc, KBinOffset, KNchMax}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("MCGen/Prof_ipt0_C2EtSub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt1_C2EtSub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt2_C2EtSub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt0_CovEt_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt0_CovEt_Eta", ";#eta;cov^{E_{T}}", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt1_CovEt_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt1_CovEt_Eta", ";#eta;cov^{E_{T}}", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt2_CovEt_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("MCGen/Prof_ipt2_CovEt_Eta", ";#eta;cov^{E_{T}}", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - - histos.add("MCGen/Prof_cent_Nchrec", ";cent;#LT N_{PV}#GT", kTProfile, {centAxis}); - histos.add("MCGen/Prof_MeanpT_Cent", ";cent;#LT p_{T}#GT", kTProfile, {centAxis}); - histos.add("MCGen/Prof_MeanpT_Mult", ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); - - histos.add("pmeanTruNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoMatchedNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanRecoMatchedEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("MCGen/Prof_MeanEt_Cent", ";cent;#LT E_{T}#GT", kTProfile, {centAxis}); - histos.add("MCGen/Prof_MeanEt_Mult", ";N_{PV};#LT E_{T}#GT", kTProfile, {nChAxis}); - histos.add("pmeanEtTruNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoMatchedNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("pmeanEtRecoMatchedEffcorrNchEtabinPtbin", ";N_{PV};#eta-bin; p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + histos.add("MCGen/Prof_Cent_NEta_Nsp_Nchrec", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_NEta_Nsp_Nchrec", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cent_NEta_Nsp_MeanpT", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Mult_NEta_Nsp_MeanpT", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + + histos.add("MCGen/Prof_MeanpT_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2Sub_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cov_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0A_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0C_Cent_etabin_spbin", ";cent;eta;isp", kTProfile3D, {{centAxis1Per}, {etaBinAxis}, {spBinAxis}}); + + histos.add("MCGen/Prof_MeanpT_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_C2Sub_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_Cov_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0A_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + histos.add("MCGen/Prof_CovFT0C_Mult_etabin_spbin", ";mult;eta;isp", kTProfile3D, {{nChAxis}, {etaBinAxis}, {spBinAxis}}); + + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + + histos.add(Form("MCGen/Prof_C2Sub2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add(Form("MCGen/Prof_GapSum2D%s", suf.c_str()), ";cent;gap;sum", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); + histos.add(Form("MCGen/Prof_Cov2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add(Form("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add(Form("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC%s", suf.c_str()), ";cent;etaA;etaC", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + } } - void declareDataMeanHists() + + void declareDataGetFlatHists() { - histos.add("Prof_cent_Nchrec", ";cent;#LT N_{PV}#GT", kTProfile, {centAxis}); - histos.add("Prof_MeanpT_Cent", ";cent;#LT p_{T}#GT", kTProfile, {centAxis}); - histos.add("pmean_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - // Et - histos.add("Prof_MeanEt_Cent", ";cent;#LT E_{T}#GT", kTProfile, {centAxis}); - histos.add("pmeanEt_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + } + histos.add("hnTrkPVZDC", ";N_{PV};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 3000}}); + histos.add("hNchZDC", ";N_{trk};ZDC_{A+C}", kTH2F, {{nChAxis2}, {200, 0, 30000}}); } - void declareDataGetFlatHists() + void declareDataMeanHists() { - histos.add("hCentEtaPhi_PID", ";cent;#eta;#phi", kTH3F, {{centAxis}, {(KNEta - 1), KEtaAxisMin, KEtaAxisMax}, {KNbinsPhiFine, 0, TwoPI}}); + histos.add("pmeanFT0Amultpv", "N_{PV}; AmplitudeA", kTProfile, {nChAxis}); + histos.add("pmeanFT0A_cent", "cent; AmplitudeA", kTProfile, {centAxis1Per}); + histos.add("pmeanFT0Cmultpv", "N_{PV}; AmplitudeA", kTProfile, {nChAxis}); + histos.add("pmeanFT0C_cent", "cent; AmplitudeA", kTProfile, {centAxis1Per}); + + histos.add("pmean_cent_id_eta_FT0", ";cent;channel id; #eta;amplitude", kTProfile3D, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); + histos.add("h3_cent_id_eta_FT0", ";cent;channel id; #eta", kTH3F, {{centAxis1Per}, {200, -0.5, 199.5}, {100, -5.0, 5.0}}); + + histos.add("Prof_Cent_Nsp_Nchrec", ";cent;Species;#LT N_{PV}#GT", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("Prof_Mult_Nsp_Nchrec", ";N_{PV};Species;#LT N_{PV}#GT", kTProfile2D, {{nChAxis}, {spBinAxis}}); + histos.add("Prof_Cent_Nsp_MeanpT", ";cent;Species;#LT p_{T}#GT", kTProfile2D, {{centAxis1Per}, {spBinAxis}}); + histos.add("Prof_Mult_Nsp_MeanpT", ";N_{PV};Species;#LT p_{T}#GT", kTProfile2D, {{nChAxis}, {spBinAxis}}); + + histos.add("pmean_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("pmeanMult_nch_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("pmean_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("pmeanMult_cent_etabin_spbin", ";Centrality (%) ;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + + histos.add("Prof2D_MeanpTSub" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {{etaBinAxis}}}); + } } void declareDataFlucHists() { - histos.add("pmean_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - histos.add("Prof_MeanEt_Cent", ";cent;#LT E_{T}#GT", kTProfile, {centAxis}); - histos.add("pmeanEt_nch_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("Prof_C2_Cent", ";cent;C_{2}", kTProfile, {centAxis}); - histos.add("Prof_MeanpT_Cent", ";cent;#LT p_{T}#GT", kTProfile, {centAxis}); - histos.add("Prof_MeanpT_Mult", ";N_{PV};#LT p_{T}#GT", kTProfile, {nChAxis}); - histos.add("Prof_C2_Mult_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("Prof_ipt0_Cov_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("Prof_ipt0_Cov_Eta", ";#eta;cov", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("Prof_ipt1_Cov_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("Prof_ipt1_Cov_Eta", ";#eta;cov", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("Prof_ipt2_Cov_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("Prof_ipt2_Cov_Eta", ";#eta;cov", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - - histos.add("Prof_C2Et_Cent", ";cent;C_{2}^{E_{T}}", kTProfile, {centAxis}); - histos.add("Prof_MeanEt_Mult", ";N_{PV};#LT E_{T}#GT", kTProfile, {nChAxis}); - histos.add("Prof_C2Et_Mult_etabin_ptbin", ";N_{PV};#eta-bin;p_{T}-bin", kTProfile3D, {{nChAxis}, {KNEta + 1, -KBinOffset, KNEta + KBinOffset}, {KNpT + 1, -KBinOffset, KNpT + KBinOffset}}); - - histos.add("Prof_ipt0_CovEt_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("Prof_ipt0_CovEt_Eta", ";#eta;cov^{E_{T}}", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("Prof_ipt1_CovEt_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("Prof_ipt1_CovEt_Eta", ";#eta;cov^{E_{T}}", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - histos.add("Prof_ipt2_CovEt_Cent_eta", ";cent;#eta", kTProfile2D, {{centAxis}, {(KNEta - 1) / 2, 0, KEtaAxisMax}}); - histos.add("Prof_ipt2_CovEt_Eta", ";#eta;cov^{E_{T}}", kTProfile, {{(KNEta - 1) / 2, 0., KEtaAxisMax}}); - - histos.add("Prof_ipt0_C2Sub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("Prof_ipt1_C2Sub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("Prof_ipt2_C2Sub2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("Prof_ipt0_C2SubEt2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("Prof_ipt1_C2SubEt2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); - histos.add("Prof_ipt2_C2SubEt2D_Mult_etaA_etaC", ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}, {KNEta - 1, KEtaAxisMin, KEtaAxisMax}}); + histos.add("Prof_MeanpT_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_MeanpT_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_C2_Cent_etabin_spbin", ";cent;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_C2_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + + histos.add("Prof_C2Sub_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_C2Sub_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_Cov_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_Cov_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + + histos.add("Prof_CovFT0A_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_CovFT0A_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_CovFT0C_Cent_etabin_spbin", ";Centrality;#eta-bin;Species", kTProfile3D, {{centAxis1Per}, {{etaBinAxis}}, {spBinAxis}}); + histos.add("Prof_CovFT0C_Mult_etabin_spbin", ";N_{PV};#eta-bin;Species", kTProfile3D, {{nChAxis}, {{etaBinAxis}}, {spBinAxis}}); + + for (const auto& suf : pidSuffix) { + histos.add("hEtaPhiReco" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoEffWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("hEtaPhiRecoWtd" + suf, ";vz;sign;pt;eta;phi", kTHnSparseF, {{vzAxis}, {chgAxis}, {pTAxis}, {etaAxis}, {phiAxis}}); + histos.add("Prof_C2Sub2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{C}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof_GapSum2D" + suf, ";cent;#Delta#eta (Gap);#Sigma#eta/2 (Sum)", kTProfile3D, {{centAxis1Per}, {gapAxis}, {sumAxis}}); + histos.add("Prof_Cov2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A} bin;#eta_{C} bin", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof_CovFT0A2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + histos.add("Prof_CovFT0C2D_Cent_etaA_etaC" + suf, ";cent;#eta_{A};#eta_{B}", kTProfile3D, {{centAxis1Per}, {etaAxis}, {etaAxis}}); + } } - TH3F* buildWeightMapFromRaw(TH3F* hRaw, const char* mapName) + THnSparseF* buildWeightMapFromRaw(THnSparseF* hRaw, const char* mapName) { if (!hRaw) { LOGF(error, "Raw eta-phi map for '%s' is null; no flattening will be applied.", mapName); return nullptr; } - auto hWeightMap = reinterpret_cast(hRaw->Clone(mapName)); - hWeightMap->SetTitle(Form("Flattening Weight Map %s (w_{#phi} = / N_{#phi})", mapName)); - hWeightMap->SetDirectory(nullptr); - hWeightMap->Reset(); - auto axC = hRaw->GetXaxis(); - auto axE = hRaw->GetYaxis(); - auto axP = hRaw->GetZaxis(); - for (int ic = 1; ic <= axC->GetNbins(); ++ic) { - for (int ie = 1; ie <= axE->GetNbins(); ++ie) { - // average over phi at fixed (cent,eta) - double sum = 0.0; - int nphi = axP->GetNbins(); - for (int ip = 1; ip <= nphi; ++ip) - sum += hRaw->GetBinContent(ic, ie, ip); - const double avg = (nphi > 0 ? sum / nphi : 0.0); - for (int ip = 1; ip <= nphi; ++ip) { - const double raw = hRaw->GetBinContent(ic, ie, ip); - const double w = (avg > 0.0 && raw > 0.0) ? (avg / raw) : 1.0; - hWeightMap->SetBinContent(ic, ie, ip, w); + auto hWMap = reinterpret_cast(hRaw->Clone(mapName)); + hWMap->SetTitle(Form("Flattening Weight Map %s (w_{#phi} = / N_{#phi})", mapName)); + hWMap->Reset(); + auto axV = hRaw->GetAxis(0); // Vz + auto axChg = hRaw->GetAxis(1); // Charge + auto axPt = hRaw->GetAxis(2); // Pt + auto axE = hRaw->GetAxis(3); // Eta + auto axP = hRaw->GetAxis(4); // Phi + + int bins[5]; + for (int iv = 1; iv <= axV->GetNbins(); ++iv) { + bins[0] = iv; + for (int ichg = 1; ichg <= axChg->GetNbins(); ++ichg) { + bins[1] = ichg; + for (int ipt = 1; ipt <= axPt->GetNbins(); ++ipt) { + bins[2] = ipt; + for (int ie = 1; ie <= axE->GetNbins(); ++ie) { + bins[3] = ie; + double sum = 0.0; + int nphi = axP->GetNbins(); + for (int ip = 1; ip <= nphi; ++ip) { + bins[4] = ip; + sum += hRaw->GetBinContent(bins); + } + const double avg = (nphi > 0 ? sum / nphi : 0.0); + for (int ip = 1; ip <= nphi; ++ip) { + bins[4] = ip; + const double raw = hRaw->GetBinContent(bins); + const double w = (avg > 0.0 && raw > 0.0) ? (avg / raw) : 1.0; + hWMap->SetBinContent(bins, w); + } + } } } } + LOGF(info, "Flattening weight map '%s' built.", mapName); - return hWeightMap; + return hWMap; } inline void loadTProfile3D(TDirectory* dir, const char* name, TProfile3D*& target) @@ -758,19 +1082,16 @@ struct RadialFlowDecorr { LOGF(error, "loadTProfile3D: directory is null for object %s", name); return; } - auto* obj = dir->Get(name); if (!obj) { LOGF(error, "loadTProfile3D: object '%s' not found in directory %s", name, dir->GetName()); return; } - auto* prof = dynamic_cast(obj); if (!prof) { LOGF(error, "loadTProfile3D: object '%s' is not a TProfile3D (it is %s)", name, obj->ClassName()); return; } - target = reinterpret_cast(prof->Clone(Form("%s_clone", name))); target->SetDirectory(nullptr); LOGF(info, "Loaded TProfile3D '%s' with entries = %.0f", name, target->GetEntries()); @@ -778,33 +1099,76 @@ struct RadialFlowDecorr { void init(InitContext&) { - ccdb->setURL("https://alice-ccdb.cern.ch"); + if (cfgSys == kPbPb) { + nChAxis = {cfgNchPbMax / 2, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + nChAxis2 = {cfgNchPbMax / 4, KBinOffset, cfgNchPbMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + } else { + nChAxis = {cfgNchOMax, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + nChAxis2 = {cfgNchOMax, KBinOffset, cfgNchOMax + KBinOffset, "Nch", "PV-contributor track multiplicity"}; + } + + ccdb->setURL(cfgCCDBurl.value); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - int64_t now = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); - declareCommonQA(); + loadAlignParam(now); + ft0Det.calculateChannelCenter(); + + std::string sysDir = ""; + switch (cfgSys) { + case kPbPb: + sysDir = "PbPbTest"; + break; + case kNeNe: + sysDir = "NeNeTest"; + break; + case kOO: + sysDir = "OOTest"; + break; + case kpp: + sysDir = "ppTest"; + break; + default: + LOGF(fatal, "Invalid cfgSys value: %d", cfgSys.value); + } + std::string pathNsig = cfgCCDBUserPath.value + "/" + sysDir + "/Job0_nSigMaps"; + std::string pathEff = cfgCCDBUserPath.value + "/" + sysDir + "/Job1_EffMaps"; + std::string pathMCFlat = cfgCCDBUserPath.value + "/" + sysDir + "/Job1_MCFlatMaps"; + std::string pathMCMean = cfgCCDBUserPath.value + "/" + sysDir + "/Job2_MCMean"; + + std::string pathDataNsig = cfgCCDBUserPath.value + "/" + sysDir + "/Job0_DatanSigMaps"; + std::string pathDataFlat = cfgCCDBUserPath.value + "/" + sysDir + "/Job1_DataFlatMaps"; + std::string pathDataMean = cfgCCDBUserPath.value + "/" + sysDir + "/Job2_DataMean"; - const std::string userCcdbPath = "/Users/s/somadutt/PbPbTest/"; + declareCommonQA(); + if (cfgRunMCGetNSig || cfgRunGetEff || cfgRunDataGetNSig || cfgRunGetDataFlat) { + declarenSigHists(); + } if (cfgRunMCMean || cfgRunMCFluc || cfgRunGetEff) { declareMCCommonHists(); } + if (cfgRunGetMCFlat) { + declareMCGetFlatHists(); + histos.addClone("MCGen/", "MCReco/"); + histos.addClone("MCGen/", "MCRecoEffCorr/"); + } if (cfgRunMCMean) { declareMCMeanHists(); + histos.addClone("MCGen/", "MCReco/"); + histos.addClone("MCGen/", "MCRecoEffCorr/"); } if (cfgRunMCFluc) { declareMCFlucHists(); - histos.addClone("MCGen/", "MCReco/"); - histos.addClone("MCGen/", "MCRecoMatched/"); histos.addClone("MCGen/", "MCRecoEffCorr/"); - histos.addClone("MCGen/", "MCRecoMatchedEffCorr/"); } - if (cfgRunGetFlat) { + if (cfgRunDataGetNSig) { + declareDataGetFlatHists(); + } + if (cfgRunGetDataFlat) { declareDataGetFlatHists(); } if (cfgRunDataMean) { @@ -814,1205 +1178,1919 @@ struct RadialFlowDecorr { declareDataFlucHists(); } - const bool needEffMaps = cfgRunMCMean || cfgRunMCFluc || cfgRunDataMean || cfgRunDataFluc; - if (needEffMaps && !cfgRunGetEff) { + if (!cfgRunGetEff && !cfgRunMCGetNSig && (cfgEff)) { + TList* lst = ccdb->getForTimeStamp(pathEff, now); + + if (!lst) { + LOGF(fatal, "Efficiency maps required but CCDB list is null at %s!", pathEff.c_str()); + } - LOGF(info, "Loading Eff/Fake maps from CCDB path: %s", userCcdbPath.c_str()); + LOGF(info, "Loading Eff/Fake maps from TList for all species..."); - auto loadEffFakeForPID = [&](PID pidType) { + auto loadEffFakeForPID = [&](PIDIdx pidType) { std::string suffix = pidSuffix[pidType]; std::string hEffNumName = "h3_RecoMatchedToPrimary" + suffix; std::string hEffDenName = "h3_AllPrimary" + suffix; std::string hFakeNumSecName = "h3_RecoUnMatchedToPrimary_Secondary" + suffix; std::string hFakeNumFakName = "h3_RecoUnMatchedToPrimary_Fake" + suffix; + std::string hFakeNumFakName2 = "h3_RecoMatchedToPrimary_MisID" + suffix; std::string hFakeDenName = "h3_AllReco" + suffix; - // --- Efficiency --- - auto* hNum = ccdb->get(userCcdbPath + hEffNumName); - auto* hDen = ccdb->get(userCcdbPath + hEffDenName); + auto* hNum = reinterpret_cast(lst->FindObject(hEffNumName.c_str())); + auto* hDen = reinterpret_cast(lst->FindObject(hEffDenName.c_str())); + if (hNum && hDen) { - hEff[pidType] = reinterpret_cast(hNum->Clone(Form("hEff%s", suffix.c_str()))); - hEff[pidType]->SetDirectory(nullptr); - hEff[pidType]->Divide(hDen); + state.hEff[pidType] = reinterpret_cast(hNum->Clone(Form("hEff%s", suffix.c_str()))); + state.hEff[pidType]->SetDirectory(nullptr); + state.hEff[pidType]->Divide(hDen); } else { - LOGF(error, "Missing CCDB objects for efficiency. Checked:\n%s\n%s", - (userCcdbPath + hEffNumName).c_str(), - (userCcdbPath + hEffDenName).c_str()); + LOGF(error, "Missing CCDB objects for efficiency. Checked: %s, %s", hEffNumName.c_str(), hEffDenName.c_str()); } - // --- Fakes --- - auto* hNumS = ccdb->get(userCcdbPath + hFakeNumSecName); - auto* hNumF = ccdb->get(userCcdbPath + hFakeNumFakName); - auto* hDenF = ccdb->get(userCcdbPath + hFakeDenName); + auto* hNumS = reinterpret_cast(lst->FindObject(hFakeNumSecName.c_str())); + auto* hNumF = reinterpret_cast(lst->FindObject(hFakeNumFakName.c_str())); + auto* hNumF2 = reinterpret_cast(lst->FindObject(hFakeNumFakName2.c_str())); + auto* hDenF = reinterpret_cast(lst->FindObject(hFakeDenName.c_str())); + if (hNumS && hNumF && hDenF) { - hFake[pidType] = reinterpret_cast(hNumS->Clone(Form("hFake%s", suffix.c_str()))); - hFake[pidType]->Add(hNumF); - hFake[pidType]->SetDirectory(nullptr); - hFake[pidType]->Divide(hDenF); + state.hFake[pidType] = reinterpret_cast(hNumS->Clone(Form("hFake%s", suffix.c_str()))); + state.hFake[pidType]->Add(hNumF); + if (pidType != kInclusiveIdx && hNumF2) { + state.hFake[pidType]->Add(hNumF2); + } + state.hFake[pidType]->SetDirectory(nullptr); + state.hFake[pidType]->Divide(hDenF); } else { - LOGF(error, "Missing CCDB object(s) for fakes for %s. Checked path prefix: %s", - suffix.c_str(), userCcdbPath.c_str()); + LOGF(error, "Missing CCDB object(s) for fakes for %s in list.", suffix.c_str()); } }; - loadEffFakeForPID(kInclusive); - loadEffFakeForPID(kCombinedPID); + for (int i = 0; i < KNsp; ++i) { + loadEffFakeForPID(static_cast(i)); + } + } - const bool isDataRun = cfgRunDataMean || cfgRunDataFluc; - if (isDataRun) { - LOGF(info, "Data Run: Loading flattening maps from CCDB path: %s", userCcdbPath.c_str()); + bool requiresMCMap = (cfgRunGetEff || cfgRunGetMCFlat || cfgRunMCMean || cfgRunMCFluc); + bool requiresDataMap = (cfgRunGetDataFlat || cfgRunDataMean || cfgRunDataFluc); - auto* hRawIncl = ccdb->get(userCcdbPath + "hCentEtaPhi"); - if (hRawIncl) { - hWeightMap3D[kInclusive] = buildWeightMapFromRaw(hRawIncl, "hWeightMap3D"); - } else { - LOGF(error, "Data flattening 'hCentEtaPhi' not found at path %s", - (userCcdbPath + "hCentEtaPhi").c_str()); - } + if (requiresMCMap || requiresDataMap) { + std::string currentPath = requiresMCMap ? pathNsig : pathDataNsig; + TList* pidList = ccdb->getForTimeStamp(currentPath, now); - auto* hRawPID = ccdb->get(userCcdbPath + "hCentEtaPhi_PID"); - if (hRawPID) { - hWeightMap3D[kCombinedPID] = buildWeightMapFromRaw(hRawPID, "hWeightMap3D_PID"); - } else { - LOGF(error, "Data flattening 'hCentEtaPhi_PID' not found at path %s", - (userCcdbPath + "hCentEtaPhi_PID").c_str()); - } + if (!pidList) { + LOGF(warn, "nSigma maps required but CCDB list is null at %s! Using raw values.", currentPath.c_str()); } else { - LOGF(info, "MC Run: Loading flattening maps from CCDB path: %s", userCcdbPath.c_str()); - - auto loadFlatForPID = [&](PID pidType) { + if (!pidMeanSigmaMap) { + pidMeanSigmaMap = new PIDMeanSigmaMap(); + } + LOGF(info, "Performing 2D Gaussian fits on PID maps from CCDB..."); + auto loadPIDMeans = [&](PIDIdx pidType) { std::string suffix = pidSuffix[pidType]; - std::string hFlatSrcName = "hCentEtaPhiReco" + suffix; - auto* hRaw = ccdb->get(userCcdbPath + hFlatSrcName); - if (hRaw) { - hWeightMap3D[pidType] = buildWeightMapFromRaw(hRaw, Form("hWeightMap3D%s", suffix.c_str())); - } else { - LOGF(warning, "MC flattening source '%s' not found at %s; skipping this PID.", - hFlatSrcName.c_str(), (userCcdbPath + hFlatSrcName).c_str()); + std::string hName = "h3DnsigmaTpcVsTofBefCut_Cent" + suffix; + auto* h3 = reinterpret_cast(pidList->FindObject(hName.c_str())); + if (!h3) { + LOGF(warn, " [!] PID Hist %s not found in CCDB list.", hName.c_str()); + return; + } + int nCentBins = std::min(h3->GetXaxis()->GetNbins(), PIDMeanSigmaMap::MaxCentBins - 1); + LOGF(info, " -> Species: %s (Bins: %d)", hName.c_str(), nCentBins); + for (int iCent = 1; iCent <= nCentBins; ++iCent) { + h3->GetXaxis()->SetRange(iCent, iCent); + // Projecting: Z(TPC) vs Y(TOF). Result: X_axis=TOF, Y_axis=TPC + std::unique_ptr h2(reinterpret_cast(h3->Project3D("zy"))); + if (h2) { + int binX, binY, binZ; + h2->GetMaximumBin(binX, binY, binZ); + double guessMeanTOF = h2->GetXaxis()->GetBinCenter(binX); + double guessMeanTPC = h2->GetYaxis()->GetBinCenter(binY); + TF2 f2("f2", "[0]*TMath::Gaus(x,[1],[2])*TMath::Gaus(y,[3],[4])", -3, 3, -3, 3); + f2.SetParameters(h2->GetMaximum(), guessMeanTOF, 1.0, guessMeanTPC, 1.0); + h2->Fit(&f2, "QRN"); // Q=Quiet, R=Range, N=NoDraw + pidMeanSigmaMap->meanTOF[pidType][iCent - 1] = f2.GetParameter(1); + pidMeanSigmaMap->meanTPC[pidType][iCent - 1] = f2.GetParameter(3); + pidMeanSigmaMap->sigmaTOF[pidType][iCent - 1] = std::abs(f2.GetParameter(2)); + pidMeanSigmaMap->sigmaTPC[pidType][iCent - 1] = std::abs(f2.GetParameter(4)); + if (iCent % KConstTen == 0) { + LOGF(info, " Derived: For Species: %s (Bins: %d), Mean TOF = %.3f, Mean TPC = %.3f, Sigma TOF = %.3f, Sigma TPC = %.3f", hName.c_str(), iCent - 1, f2.GetParameter(1), f2.GetParameter(3), f2.GetParameter(2), f2.GetParameter(4)); + } + } } }; - loadFlatForPID(kInclusive); - loadFlatForPID(kCombinedPID); - } - } + for (int i = 1; i < KNsp; ++i) { + loadPIDMeans(static_cast(i)); + } - auto loadTProfile3DFromCCDB = [&](const std::string& ccdbPath, const char* objName, TProfile3D*& target) { - std::string fullPath = ccdbPath + objName; - LOGF(info, "Loading TProfile3D from CCDB: %s", fullPath.c_str()); - if (auto* tp = ccdb->get(fullPath)) { - target = reinterpret_cast(tp->Clone()); - target->SetDirectory(nullptr); - } else { - LOGF(error, "Histogram %s missing in CCDB at path: %s", objName, fullPath.c_str()); - } - }; + auto loadLimits = [&](const char* name, std::vector>& limits, float& xMin, float& xMax) { + auto* h2 = reinterpret_cast(pidList->FindObject(name)); + if (!h2) + return; - if (cfgRunMCFluc) { - LOGF(info, "Loading MC Mean profiles from CCDB path: %s", userCcdbPath.c_str()); + std::unique_ptr prof(h2->ProfileX("ptmp", 1, -1, "S")); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanTruNchEtabinPtbin", pmeanTruNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanRecoNchEtabinPtbin", pmeanRecoNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanRecoMatchedNchEtabinPtbin", pmeanRecoMatchedNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanRecoEffcorrNchEtabinPtbin", pmeanRecoEffcorrNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanRecoMatchedEffcorrNchEtabinPtbin", pmeanRecoMatchedEffcorrNchEtabinPtbinStep2); + int nBins = prof->GetNbinsX(); + xMin = prof->GetXaxis()->GetXmin(); + xMax = prof->GetXaxis()->GetXmax(); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanEtTruNchEtabinPtbin", pmeanEtTruNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanEtRecoNchEtabinPtbin", pmeanEtRecoNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanEtRecoMatchedNchEtabinPtbin", pmeanEtRecoMatchedNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanEtRecoEffcorrNchEtabinPtbin", pmeanEtRecoEffcorrNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanEtRecoMatchedEffcorrNchEtabinPtbin", pmeanEtRecoMatchedEffcorrNchEtabinPtbinStep2); + limits.assign(nBins + 2, {-99999.f, 999999.f}); + + for (int i = 1; i <= nBins; ++i) { + float mean = prof->GetBinContent(i); + float rms = prof->GetBinError(i); + + limits[i] = {mean - cfgPupnSig * rms, mean + cfgPupnSig * rms}; + } + }; + loadLimits("Hist2D_globalTracks_cent", state.mLimitsNchCent, state.mMinXNchCent, state.mMaxXNchCent); + } } + if (!cfgRunGetEff && (cfgFlat)) { + if (cfgRunDataMean || cfgRunDataFluc) { + LOGF(info, "Data Run: Loading flattening maps from %s", pathDataFlat.c_str()); + TList* lstDataFlat = ccdb->getForTimeStamp(pathDataFlat, now); + + if (lstDataFlat) { + for (int i = 0; i < KNsp; ++i) { + std::string suffix = pidSuffix[i]; + std::string hName; + + if (cfgEff && cfgFlat) { + hName = "hEtaPhiRecoWtd" + suffix; + } else if (cfgEff) { + hName = "hEtaPhiRecoEffWtd" + suffix; + } else { + hName = "hEtaPhiReco" + suffix; + } + auto* hRaw = reinterpret_cast(lstDataFlat->FindObject(hName.c_str())); - if (cfgRunDataFluc) { - LOGF(info, "Loading Data Mean profiles from CCDB path: %s", userCcdbPath.c_str()); - loadTProfile3DFromCCDB(userCcdbPath, "pmean_nch_etabin_ptbin", pmeanNchEtabinPtbinStep2); - loadTProfile3DFromCCDB(userCcdbPath, "pmeanEt_nch_etabin_ptbin", pmeanEtNchEtabinPtbinStep2); + if (hRaw) { + state.hFlatWeight[i] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); + } else { + LOGF(error, "Data flattening map '%s' not found.", hName.c_str()); + } + } + } else { + LOGF(error, "Could not retrieve Data Flattening TList from: %s", pathDataFlat.c_str()); + } + } + + if (cfgRunMCMean || cfgRunMCFluc) { + LOGF(info, "MC Run: Loading flattening maps from %s", pathMCFlat.c_str()); + TList* lstMCFlat = ccdb->getForTimeStamp(pathMCFlat, now); + + if (lstMCFlat) { + auto loadFlatForPID = [&](PIDIdx pidType) { + std::string suffix = pidSuffix[pidType]; + std::string hFlatSrcName; + if (cfgEff && cfgFlat) { + hFlatSrcName = "MCReco/hEtaPhiRecoWtd" + suffix; + } else if (cfgEff) { + hFlatSrcName = "MCReco/hEtaPhiRecoEffWtd" + suffix; + } else { + hFlatSrcName = "MCReco/hEtaPhiReco" + suffix; + } + + auto* hRaw = reinterpret_cast(lstMCFlat->FindObject(hFlatSrcName.c_str())); + + if (hRaw) { + state.hFlatWeight[pidType] = buildWeightMapFromRaw(hRaw, Form("hFlatWeight%s", suffix.c_str())); + } else { + LOGF(warning, "MC flattening source '%s' not found in list.", hFlatSrcName.c_str()); + } + }; + + for (int i = 0; i < KNsp; ++i) { + loadFlatForPID(static_cast(i)); + } + } else { + LOGF(error, "Could not retrieve MC Flattening TList from: %s", pathMCFlat.c_str()); + } + } } + auto loadTProfile3DFromList = [&](TList* sourceList, const char* objName, TProfile3D*& target) { + if (!sourceList) + return; + auto* tp = reinterpret_cast(sourceList->FindObject(objName)); + if (tp) { + target = reinterpret_cast(tp->Clone()); + target->SetDirectory(nullptr); + LOGF(info, "Loaded %s from list", objName); + } else { + LOGF(error, "Histogram %s missing in CCDB TList", objName); + } + }; + + auto loadTProfileFromList = [&](TList* sourceList, const char* objName, TProfile*& target) { + if (!sourceList) + return; + auto* tp = reinterpret_cast(sourceList->FindObject(objName)); + if (tp) { + target = reinterpret_cast(tp->Clone()); + target->SetDirectory(nullptr); + LOGF(info, "Loaded %s from list", objName); + } else { + LOGF(error, "Histogram %s missing in CCDB TList", objName); + } + }; + + if (cfgRunMCFluc) { + LOGF(info, "Loading MC Mean profiles from CCDB path: %s", pathMCMean.c_str()); + TList* lstMCMean = ccdb->getForTimeStamp(pathMCMean, now); + + if (lstMCMean) { + loadTProfileFromList(lstMCMean, "pmeanFT0Amultpv", state.pmeanFT0AmultpvStep2); + loadTProfileFromList(lstMCMean, "pmeanFT0Cmultpv", state.pmeanFT0CmultpvStep2); + + loadTProfile3DFromList(lstMCMean, "pmeanTru_nch_etabin_spbin", state.pmeanTruNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanReco_nch_etabin_spbin", state.pmeanRecoNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanRecoEffcorr_nch_etabin_spbin", state.pmeanRecoEffcorrNchEtabinSpbinStep2); + + loadTProfile3DFromList(lstMCMean, "pmeanMultTru_nch_etabin_spbin", state.pmeanMultTruNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultReco_nch_etabin_spbin", state.pmeanMultRecoNchEtabinSpbinStep2); + loadTProfile3DFromList(lstMCMean, "pmeanMultRecoEffcorr_nch_etabin_spbin", state.pmeanMultRecoEffcorrNchEtabinSpbinStep2); + } else { + LOGF(error, "Could not retrieve TList for MC Mean from: %s", pathMCMean.c_str()); + } + } + + if (cfgRunDataFluc) { + LOGF(info, "Loading Data Mean profiles from CCDB path: %s", pathDataMean.c_str()); + TList* lstDataMean = ccdb->getForTimeStamp(pathDataMean, now); + + if (lstDataMean) { + loadTProfileFromList(lstDataMean, "pmeanFT0Amultpv", state.pmeanFT0AmultpvStep2); + loadTProfileFromList(lstDataMean, "pmeanFT0Cmultpv", state.pmeanFT0CmultpvStep2); + + loadTProfile3DFromList(lstDataMean, "pmean_nch_etabin_spbin", state.pmeanNchEtabinSpbinStep2); + loadTProfile3DFromList(lstDataMean, "pmeanMult_nch_etabin_spbin", state.pmeanMultNchEtabinSpbinStep2); + } else { + LOGF(error, "Could not retrieve TList for Data Mean from: %s", pathDataMean.c_str()); + } + } LOGF(info, "CCDB initialization complete for RadialFlowDecorr."); } - void processGetEffHists(aod::McCollisions const& mcColl, soa::SmallGroups const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCGetMeanNsig(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks) { - for (const auto& mcCollision : mcColl) { - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) - continue; + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); - for (const auto& col : colSlice) { - if (!col.has_mcCollision()) - continue; - if (!isEventSelected(col)) - continue; + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) - continue; + for (const auto& track : mcTracks) { + if (track.collisionId() != mcCollision.index()) + continue; - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (partSlice.size() < 1) - continue; - if (col.globalIndex() >= trackSlice.size()) { - LOGF(warning, "Skipping invalid globalIndex=%d for tracks (tracks.size=%d)", col.globalIndex(), tracks.size()); - continue; - } + if (!isTrackSelected(track)) + continue; + fillNSigmaBefCut(track, cent); + } + } + PROCESS_SWITCH(RadialFlowDecorr, processMCGetMeanNsig, "process MC to calculate Mean values of nSig Plots", cfgRunMCGetNSig); - float cent = getCentrality(col); - if (cent > KCentMax) - continue; + void processGetEffHists(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks, aod::McParticles const& mcParticles) + { + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle)) - continue; - if (!particle.isPhysicalPrimary()) - continue; + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); - const int absPdgId = std::abs(particle.pdgCode()); - const bool isPion = (absPdgId == KPiPlus); - const bool isKaon = (absPdgId == KKPlus); - const bool isProton = (absPdgId == KProton); - const bool isPid = (isPion || isKaon || isProton); + for (const auto& particle : mcParticles) { + if (particle.mcCollisionId() != mcCollision.mcCollisionId()) + continue; - histos.fill(HIST("hTruth_ParticleWeight"), cent, particle.pt(), particle.eta(), particle.weight()); - histos.fill(HIST("hCentEtaPhiTrue"), cent, particle.eta(), particle.phi()); - histos.fill(HIST("h3_AllPrimary"), col.multNTracksPV(), particle.pt(), particle.eta()); + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; - if (cent < KCentTestMin) - histos.fill(HIST("hCent1EtaPhi"), particle.eta(), particle.phi()); - if (cent > KCentTestMaxLo && cent < KCentTestMaxHi) - histos.fill(HIST("hCent7EtaPhi"), particle.eta(), particle.phi()); + const int pdg = particle.pdgCode(); + const int absPdg = std::abs(pdg); + float pt = particle.pt(), eta = particle.eta(); + + bool isSpecies[KNsp] = { + true, // kInclusiveIdx + pdg == -KPiPlus, // kPiMinusIdx + pdg == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdg == -KKPlus, // kKaMinusIdx + pdg == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdg == -KProton, // kAntiPrIdx + pdg == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx + }; - if (isPid) { - histos.fill(HIST("hCentEtaPhiTrue_PID"), cent, particle.eta(), particle.phi()); - histos.fill(HIST("h3_AllPrimary_PID"), col.multNTracksPV(), particle.pt(), particle.eta()); - } - } - histos.fill(HIST("TruthTracKVz"), mcCollision.posZ(), col.posZ()); - histos.fill(HIST("vzResolution"), mcCollision.posZ(), mcCollision.posZ() - col.posZ()); + histos.fill(HIST("h3_AllPrimary"), multPV, pt, eta); + if (isSpecies[kPiMinusIdx]) + histos.fill(HIST("h3_AllPrimary_PiMinus"), multPV, pt, eta); + else if (isSpecies[kPiPlusIdx]) + histos.fill(HIST("h3_AllPrimary_PiPlus"), multPV, pt, eta); + if (isSpecies[kPiAllIdx]) + histos.fill(HIST("h3_AllPrimary_PiAll"), multPV, pt, eta); + + if (isSpecies[kKaMinusIdx]) + histos.fill(HIST("h3_AllPrimary_KaMinus"), multPV, pt, eta); + else if (isSpecies[kKaPlusIdx]) + histos.fill(HIST("h3_AllPrimary_KaPlus"), multPV, pt, eta); + if (isSpecies[kKaAllIdx]) + histos.fill(HIST("h3_AllPrimary_KaAll"), multPV, pt, eta); + + if (isSpecies[kAntiPrIdx]) + histos.fill(HIST("h3_AllPrimary_AntiPr"), multPV, pt, eta); + else if (isSpecies[kPrIdx]) + histos.fill(HIST("h3_AllPrimary_Pr"), multPV, pt, eta); + if (isSpecies[kPrAllIdx]) + histos.fill(HIST("h3_AllPrimary_PrAll"), multPV, pt, eta); + } - // Reconstructed - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; + for (const auto& track : mcTracks) { + if (track.collisionId() != mcCollision.index()) + continue; - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - const bool isPid = (isPion || isKaon || isProton); + if (!isTrackSelected(track)) + continue; - histos.fill(HIST("h3_AllReco"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("hCentEtaPhiReco"), cent, track.eta(), track.phi()); + float pt = track.pt(), eta = track.eta(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + auto sign = track.sign(); + fillNSigmaBefCut(track, cent); + + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + fillNSigmaAftCut(track, cent, isSpecies); + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; - if (isPid) { - histos.fill(HIST("h3_AllReco_PID"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("hCentEtaPhiReco_PID"), cent, track.eta(), track.phi()); + if (isp == kInclusiveIdx) { + histos.fill(HIST("h3_AllReco"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + histos.fill(HIST("ptResolution"), mcP.pt(), (pt - mcP.pt()) / mcP.pt()); + histos.fill(HIST("etaResolution"), mcP.eta(), eta - mcP.eta()); + histos.fill(HIST("etaTruthReco"), mcP.eta(), eta); + histos.fill(HIST("vzResolution"), mcP.vz(), (vz - mcP.vz()) / mcP.vz()); + histos.fill(HIST("TruthTracKVz"), mcP.vz(), vz); + histos.fill(HIST("h3_RecoMatchedToPrimary"), multPV, mcP.pt(), mcP.eta()); + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), multPV, pt, eta); } - + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("h3_AllReco_PiMinus"), multPV, pt, eta); if (track.has_mcParticle()) { - auto mcPart2 = track.mcParticle(); - if (mcPart2.isPhysicalPrimary()) { - const int absPdgId = std::abs(mcPart2.pdgCode()); - const bool isPionTrue = (absPdgId == kPiPlus); - const bool isKaonTrue = (absPdgId == kKPlus); - const bool isProtonTrue = (absPdgId == kProton); - const bool isPidTrue = (isPionTrue || isKaonTrue || isProtonTrue); - - histos.fill(HIST("hReco_ParticleWeight"), cent, mcPart2.pt(), mcPart2.eta(), mcPart2.weight()); - histos.fill(HIST("ptResolution"), mcPart2.pt(), mcPart2.pt() - track.pt()); - histos.fill(HIST("ptTruthReco"), mcPart2.pt(), track.pt()); - histos.fill(HIST("etaResolution"), mcPart2.eta(), mcPart2.eta() - track.eta()); - histos.fill(HIST("etaTruthReco"), mcPart2.eta(), track.eta()); - histos.fill(HIST("h3_RecoMatchedToPrimary"), col.multNTracksPV(), mcPart2.pt(), mcPart2.eta()); - histos.fill(HIST("hCentEtaPhiRecoMatched"), cent, mcPart2.eta(), mcPart2.phi()); - - if (isPid && isPidTrue) { - histos.fill(HIST("h3_RecoMatchedToPrimary_PID"), col.multNTracksPV(), mcPart2.pt(), mcPart2.eta()); - histos.fill(HIST("hCentEtaPhiRecoMatched_PID"), cent, mcPart2.eta(), mcPart2.phi()); + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiMinus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiMinus"), multPV, pt, eta); } - } else { - // Matched to secondary - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("hDCAxy_Unmatched"), track.dcaXY()); - histos.fill(HIST("hDCAz_Unmatched"), track.dcaZ()); - if (isPid) { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PID"), col.multNTracksPV(), track.pt(), track.eta()); + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiMinus"), multPV, pt, eta); + } + } else { // No MC + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiMinus"), multPV, pt, eta); + } + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("h3_AllReco_PiPlus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiPlus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiPlus"), multPV, pt, eta); } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiPlus"), multPV, pt, eta); } } else { - // Fake track - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake"), col.multNTracksPV(), track.pt(), track.eta()); - histos.fill(HIST("hDCAxy_NotPrimary"), track.dcaXY()); - histos.fill(HIST("hDCAz_NotPrimary"), track.dcaZ()); - if (isPid) { - histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PID"), col.multNTracksPV(), track.pt(), track.eta()); + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiPlus"), multPV, pt, eta); + } + } else if (isp == kPiAllIdx) { + histos.fill(HIST("h3_AllReco_PiAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KPiPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PiAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PiAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PiAll"), multPV, pt, eta); } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PiAll"), multPV, pt, eta); } - } // tracks - } // cols - } // mcColl - LOGF(info, "FINISHED RUNNING processGetEffHists"); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("h3_AllReco_KaMinus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaMinus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaMinus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaMinus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaMinus"), multPV, pt, eta); + } + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("h3_AllReco_KaPlus"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaPlus"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaPlus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaPlus"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaPlus"), multPV, pt, eta); + } + } else if (isp == kKaAllIdx) { + histos.fill(HIST("h3_AllReco_KaAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KKPlus) { + histos.fill(HIST("h3_RecoMatchedToPrimary_KaAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_KaAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_KaAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_KaAll"), multPV, pt, eta); + } + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("h3_AllReco_AntiPr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == -KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_AntiPr"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_AntiPr"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_AntiPr"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_AntiPr"), multPV, pt, eta); + } + } else if (isp == kPrIdx) { + histos.fill(HIST("h3_AllReco_Pr"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (mcP.pdgCode() == KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_Pr"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_Pr"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_Pr"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_Pr"), multPV, pt, eta); + } + } else if (isp == kPrAllIdx) { + histos.fill(HIST("h3_AllReco_PrAll"), multPV, pt, eta); + if (track.has_mcParticle()) { + auto mcP = track.mcParticle(); + if (mcP.isPhysicalPrimary()) { + if (std::abs(mcP.pdgCode()) == KProton) { + histos.fill(HIST("h3_RecoMatchedToPrimary_PrAll"), multPV, mcP.pt(), mcP.eta()); + } else { // Misidentified + histos.fill(HIST("h3_RecoMatchedToPrimary_MisID_PrAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Secondary_PrAll"), multPV, pt, eta); + } + } else { + histos.fill(HIST("h3_RecoUnMatchedToPrimary_Fake_PrAll"), multPV, pt, eta); + } + } + } + } } - PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate Eff and Fakes", cfgRunGetEff); + PROCESS_SWITCH(RadialFlowDecorr, processGetEffHists, "process MC to calculate EffWeights", cfgRunGetEff); - void processMCMean(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCFlat(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks) { - float sumWiTruth[KNEta][KNpT], sumWiptiTruth[KNEta][KNpT]; - float sumWiReco[KNEta][KNpT], sumWiptiReco[KNEta][KNpT]; - float sumWiRecoMatched[KNEta][KNpT], sumWiptiRecoMatched[KNEta][KNpT]; - float sumWiRecoEffCorr[KNEta][KNpT], sumWiptiRecoEffCorr[KNEta][KNpT]; - float sumWiRecoMatchedEffCorr[KNEta][KNpT], sumWiptiRecoMatchedEffCorr[KNEta][KNpT]; - float sumWiTruthEt[KNEta][KNpT], sumWiptiTruthEt[KNEta][KNpT]; - float sumWiRecoEt[KNEta][KNpT], sumWiptiRecoEt[KNEta][KNpT]; - float sumWiRecoMatchedEt[KNEta][KNpT], sumWiptiRecoMatchedEt[KNEta][KNpT]; - float sumWiRecoEffCorrEt[KNEta][KNpT], sumWiptiRecoEffCorrEt[KNEta][KNpT]; - float sumWiRecoMatchedEffCorrEt[KNEta][KNpT], sumWiptiRecoMatchedEffCorrEt[KNEta][KNpT]; - - for (const auto& mcCollision : mcColl) { - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - - if (colSlice.size() != 1) - continue; - for (const auto& col : colSlice) { - if (!col.has_mcCollision()) - continue; - if (!isEventSelected(col)) - continue; + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) - continue; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - if (partSlice.size() < 1) - continue; - if (col.globalIndex() >= trackSlice.size()) { - LOGF(warning, "Skipping invalid globalIndex=%d for tracks (tracks.size=%d)", col.globalIndex(), tracks.size()); - continue; - } + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); - float cent = getCentrality(col); - if (cent > KCentMax) - continue; + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - if (col.globalIndex() >= trackSlice.size()) { - LOGF(warning, "Skipping invalid globalIndex=%d for tracks (tracks.size=%d)", col.globalIndex(), tracks.size()); - continue; - } + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), mcCollision.multNTracksPV(), mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); + for (const auto& track : mcTracks) { + if (track.collisionId() != mcCollision.index()) + continue; - LOGF(info, "Event Check: cent = %.1f, nTracks = %d", cent, (int)trackSlice.size()); - memset(sumWiTruth, 0, sizeof(sumWiTruth)); - memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); - memset(sumWiReco, 0, sizeof(sumWiReco)); - memset(sumWiptiReco, 0, sizeof(sumWiptiReco)); - memset(sumWiRecoMatched, 0, sizeof(sumWiRecoMatched)); - memset(sumWiptiRecoMatched, 0, sizeof(sumWiptiRecoMatched)); - memset(sumWiRecoEffCorr, 0, sizeof(sumWiRecoEffCorr)); - memset(sumWiptiRecoEffCorr, 0, sizeof(sumWiptiRecoEffCorr)); - memset(sumWiRecoMatchedEffCorr, 0, sizeof(sumWiRecoMatchedEffCorr)); - memset(sumWiptiRecoMatchedEffCorr, 0, sizeof(sumWiptiRecoMatchedEffCorr)); - memset(sumWiTruthEt, 0, sizeof(sumWiTruthEt)); - memset(sumWiptiTruthEt, 0, sizeof(sumWiptiTruthEt)); - memset(sumWiRecoEt, 0, sizeof(sumWiRecoEt)); - memset(sumWiptiRecoEt, 0, sizeof(sumWiptiRecoEt)); - memset(sumWiRecoMatchedEt, 0, sizeof(sumWiRecoMatchedEt)); - memset(sumWiptiRecoMatchedEt, 0, sizeof(sumWiptiRecoMatchedEt)); - memset(sumWiRecoEffCorrEt, 0, sizeof(sumWiRecoEffCorrEt)); - memset(sumWiptiRecoEffCorrEt, 0, sizeof(sumWiptiRecoEffCorrEt)); - memset(sumWiRecoMatchedEffCorrEt, 0, sizeof(sumWiRecoMatchedEffCorrEt)); - memset(sumWiptiRecoMatchedEffCorrEt, 0, sizeof(sumWiptiRecoMatchedEffCorrEt)); - - // Truth - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle)) - continue; - if (!particle.isPhysicalPrimary()) - continue; + if (!isTrackSelected(track)) + continue; - const int absPdgId = std::abs(particle.pdgCode()); - const bool isPion = (absPdgId == kPiPlus); - const bool isKaon = (absPdgId == kKPlus); - const bool isProton = (absPdgId == kProton); - - float pt = particle.pt(); - float eta = particle.eta(); - float p = particle.p(); - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiTruth[ieta][ipt]++; - sumWiptiTruth[ieta][ipt] += pt; - if (isPion || isKaon || isProton) { - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) = E * (pT / p) - sumWiTruthEt[ieta][ipt]++; - sumWiptiTruthEt[ieta][ipt] += et; - } - } + float pt = track.pt(), eta = track.eta(), phi = track.phi(); + auto sign = track.sign(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float w = (eff > KFloatEpsilon) ? (1.0f - fake) / eff : 0.0f; + + if (std::isfinite(w) && w > 0.f) { + if (isp == kInclusiveIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_Pr"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("MCReco/hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("MCReco/hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi, 1.0); + histos.fill(HIST("MCReco/hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); } } + } + } + } + PROCESS_SWITCH(RadialFlowDecorr, processMCFlat, "process MC to calculate FlatWeights", cfgRunGetMCFlat); - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; + void processMCMean(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks, aod::FT0s const&, aod::McParticles const& mcParticles) + { + double sumWiTruth[KNsp][KNEta]{}, sumWiptiTruth[KNsp][KNEta]{}; + double sumWiReco[KNsp][KNEta]{}, sumWiptiReco[KNsp][KNEta]{}; + double sumWiRecoEffCorr[KNsp][KNEta]{}, sumWiptiRecoEffCorr[KNsp][KNEta]{}; + histos.fill(HIST("hVtxZ"), mcCollision.posZ()); + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; - float pt = track.pt(); - float eta = track.eta(); - float p = track.p(); - float phi = track.phi(); - - histos.fill(HIST("hCentEtaPhi"), cent, eta, phi); - if (cent < KCentTestMin) - histos.fill(HIST("hCent1EtaPhi"), eta, phi); - if (cent > KCentTestMaxLo && cent < KCentTestMaxHi) - histos.fill(HIST("hCent7EtaPhi"), eta, phi); - - float effIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 0); - float fakeIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 1); - float flatWeightIncl = getFlatteningWeight(cent, eta, phi, kInclusive); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - - histos.fill(HIST("hCentEtaPhiWtd"), cent, eta, track.phi(), flatWeightIncl); - if (cent < KCentTestMin) - histos.fill(HIST("hCent1EtaPhiWtd"), track.eta(), track.phi(), flatWeightIncl); - if (cent > KCentTestMaxLo && cent < KCentTestMaxHi) - histos.fill(HIST("hCent7EtaPhiWtd"), track.eta(), track.phi(), flatWeightIncl); - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiReco[ieta][ipt] += 1.0; - sumWiptiReco[ieta][ipt] += pt; - } - } + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); - if (effIncl <= 0 || !std::isfinite(wIncl) || !std::isfinite(fakeIncl) || !std::isfinite(flatWeightIncl)) - continue; + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), mcCollision.multNTracksPV(), mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiRecoEffCorr[ieta][ipt] += wIncl; - sumWiptiRecoEffCorr[ieta][ipt] += wIncl * pt; - } - } + memset(sumWiTruth, 0, sizeof(sumWiTruth)); + memset(sumWiptiTruth, 0, sizeof(sumWiptiTruth)); + memset(sumWiReco, 0, sizeof(sumWiReco)); + memset(sumWiptiReco, 0, sizeof(sumWiptiReco)); + memset(sumWiRecoEffCorr, 0, sizeof(sumWiRecoEffCorr)); + memset(sumWiptiRecoEffCorr, 0, sizeof(sumWiptiRecoEffCorr)); - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - float effPid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 0); - float fakePid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 1); - float flatWeightPid = getFlatteningWeight(cent, eta, phi, kCombinedPID); - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - - histos.fill(HIST("hCentEtaPhiWtd_PID"), cent, eta, track.phi(), flatWeightPid); - if (cent < KCentTestMin) - histos.fill(HIST("hCent1EtaPhiWtd_PID"), track.eta(), track.phi(), flatWeightPid); - if (cent > KCentTestMaxLo && cent < KCentTestMaxHi) - histos.fill(HIST("hCent7EtaPhiWtd_PID"), track.eta(), track.phi(), flatWeightPid); - - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiRecoEt[ieta][ipt] += 1.0; - sumWiptiRecoEt[ieta][ipt] += et; - } - } + for (const auto& particle : mcParticles) { + if (particle.mcCollisionId() != mcCollision.mcCollisionId()) + continue; - if (effPid <= KFloatEpsilon || !std::isfinite(wPid) || !std::isfinite(fakePid) || !std::isfinite(flatWeightPid)) - continue; - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiRecoEffCorrEt[ieta][ipt] += wPid; - sumWiptiRecoEffCorrEt[ieta][ipt] += wPid * et; - } - } - } + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; + float pt = particle.pt(), eta = particle.eta(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + int pdgCode = particle.pdgCode(); + int absPdg = std::abs(pdgCode); + + bool isSpecies[KNsp] = { + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx + }; - if (std::isfinite(wIncl)) { - if (cent < KCentTestMin) { - histos.fill(HIST("wgt_pT"), pt, wIncl); - histos.fill(HIST("Eff_pT"), pt, effIncl); - histos.fill(HIST("Fake_pT"), pt, fakeIncl); - histos.fill(HIST("Eff_eta"), eta, effIncl); - histos.fill(HIST("Fake_eta"), eta, fakeIncl); - histos.fill(HIST("wgt_eta"), eta, wIncl); - } - histos.fill(HIST("Eff_cent"), cent, effIncl); - histos.fill(HIST("Eff_Ntrk"), col.multNTracksPV(), effIncl); - histos.fill(HIST("Fake_cent"), cent, fakeIncl); - histos.fill(HIST("Fake_Ntrk"), col.multNTracksPV(), fakeIncl); - histos.fill(HIST("wgt_cent"), cent, wIncl); - histos.fill(HIST("wgt_Ntrk"), col.multNTracksPV(), wIncl); + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + continue; + + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + sumWiTruth[isp][ieta]++; + sumWiptiTruth[isp][ieta] += pt; } + } + } + } - } // end track loop + for (int isp = 0; isp < KNsp; ++isp) { + histos.fill(HIST("MCGen/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiTruth[isp][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiTruth[isp][0]); + if (sumWiTruth[isp][0] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); + histos.fill(HIST("MCGen/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiTruth[isp][0] / sumWiTruth[isp][0]); + } + } + + for (const auto& track : mcTracks) { + if (track.collisionId() != mcCollision.index()) + continue; + + if (!isTrackSelected(track)) + continue; + float pt = track.pt(), eta = track.eta(), phi = track.phi(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + auto sign = track.sign(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatW * (1.0 - fake) / eff; + if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) + continue; - if (std::isfinite(sumWiTruth[0][0])) { - float meanPtTruth = sumWiptiTruth[0][0] / sumWiTruth[0][0]; - if (!std::isfinite(meanPtTruth)) - LOGF(info, "meanPtTruth = %.3f, num = %.3f, den =%.3f", meanPtTruth, sumWiptiTruth[0][0], sumWiTruth[0][0]); - if (!std::isfinite(meanPtTruth)) + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - histos.fill(HIST("MCGen/Prof_cent_Nchrec"), cent, sumWiTruth[0][0]); - histos.fill(HIST("MCGen/Prof_MeanpT_Cent"), cent, meanPtTruth); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult"), col.multNTracksPV(), meanPtTruth); + sumWiReco[isp][ieta]++; + sumWiptiReco[isp][ieta] += pt; + sumWiRecoEffCorr[isp][ieta] += w; + sumWiptiRecoEffCorr[isp][ieta] += w * pt; } - if (std::isfinite(sumWiReco[0][0])) { - float meanPtReco = sumWiptiReco[0][0] / sumWiReco[0][0]; - if (!std::isfinite(meanPtReco)) - LOGF(info, "meanPtReco = %.3f, num = %.3f, den =%.3f", meanPtReco, sumWiptiReco[0][0], sumWiReco[0][0]); - if (!std::isfinite(meanPtReco)) - continue; - histos.fill(HIST("MCReco/Prof_cent_Nchrec"), cent, sumWiReco[0][0]); - histos.fill(HIST("MCReco/Prof_MeanpT_Cent"), cent, meanPtReco); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult"), col.multNTracksPV(), meanPtReco); + + if (isp == kInclusiveIdx) { + histos.fill(HIST("Eff_cent"), cent, eff); + histos.fill(HIST("Fake_cent"), cent, fake); + histos.fill(HIST("wgt_cent"), cent, w); + + histos.fill(HIST("Eff_Ntrk"), multPV, eff); + histos.fill(HIST("Fake_Ntrk"), multPV, fake); + histos.fill(HIST("wgt_Ntrk"), multPV, w); + + histos.fill(HIST("Eff_pT"), pt, eff); + histos.fill(HIST("Fake_pT"), pt, fake); + histos.fill(HIST("wgt_pT"), pt, w); + + histos.fill(HIST("Eff_eta"), eta, eff); + histos.fill(HIST("Fake_eta"), eta, fake); + histos.fill(HIST("wgt_eta"), eta, w); } - if (std::isfinite(sumWiRecoEffCorr[0][0])) { - float meanpTeffcorr = sumWiptiRecoEffCorr[0][0] / sumWiRecoEffCorr[0][0]; - if (!std::isfinite(meanpTeffcorr)) - LOGF(info, "meanPtRecoEffcorr = %.3f, num = %.3f, den =%.3f", meanpTeffcorr, sumWiptiRecoEffCorr[0][0], sumWiRecoEffCorr[0][0]); - if (!std::isfinite(meanpTeffcorr)) - continue; - histos.fill(HIST("MCRecoEffCorr/Prof_cent_Nchrec"), cent, sumWiRecoEffCorr[0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent"), cent, meanpTeffcorr); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult"), col.multNTracksPV(), meanpTeffcorr); + if (isp == kInclusiveIdx) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrIdx) { + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); } + } + } - if (std::isfinite(sumWiTruthEt[0][0])) { - float meanEt = sumWiptiTruthEt[0][0] / sumWiTruthEt[0][0]; - if (!std::isfinite(meanEt)) - LOGF(info, "meanEtTruthEt = %.3f, num = %.3f, den =%.3f", meanEt, sumWiptiTruthEt[0][0], sumWiTruthEt[0][0]); - if (!std::isfinite(meanEt)) - continue; - histos.fill(HIST("MCGen/Prof_MeanEt_Cent"), cent, meanEt); - histos.fill(HIST("MCGen/Prof_MeanEt_Mult"), col.multNTracksPV(), meanEt); + for (int isp = 0; isp < KNsp; ++isp) { + histos.fill(HIST("MCReco/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiReco[isp][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiReco[isp][0]); + + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_Nchrec"), cent, isp, sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_Nchrec"), multPV, isp, sumWiRecoEffCorr[isp][0]); + + if (sumWiReco[isp][0] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); + histos.fill(HIST("MCReco/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiReco[isp][0] / sumWiReco[isp][0]); + } + if (sumWiRecoEffCorr[isp][0] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_Nsp_MeanpT"), cent, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_Nsp_MeanpT"), multPV, isp, sumWiptiRecoEffCorr[isp][0] / sumWiRecoEffCorr[isp][0]); + } + } + + for (int ietaA = 0; ietaA < KNEta; ++ietaA) { + for (int ietaC = 0; ietaC < KNEta; ++ietaC) { + for (int isp = 0; isp < KNsp; ++isp) { + float nTruAB = sumWiTruth[isp][ietaA] + sumWiTruth[isp][ietaC]; + float nRecoAB = sumWiReco[isp][ietaA] + sumWiReco[isp][ietaC]; + float nCorrAB = sumWiRecoEffCorr[isp][ietaA] + sumWiRecoEffCorr[isp][ietaC]; + + float mptsubTru = (sumWiptiTruth[isp][ietaA] + sumWiptiTruth[isp][ietaC]) / nTruAB; + float mptsubReco = (sumWiptiReco[isp][ietaA] + sumWiptiReco[isp][ietaC]) / nRecoAB; + float mptsubRecoEffCorr = (sumWiptiRecoEffCorr[isp][ietaA] + sumWiptiRecoEffCorr[isp][ietaC]) / nCorrAB; + + if (nTruAB > 0) { + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiMinus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiPlus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PiAll"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaMinus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaPlus"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_KaAll"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_Pr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_AntiPr"), cent, ietaA, ietaC, mptsubTru); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Tru_PrAll"), cent, ietaA, ietaC, mptsubTru); + } + + if (nRecoAB > 0) { + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiMinus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiPlus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PiAll"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaMinus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaPlus"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_KaAll"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_Pr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_AntiPr"), cent, ietaA, ietaC, mptsubReco); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Reco_PrAll"), cent, ietaA, ietaC, mptsubReco); + } + + if (nCorrAB > 0) { + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PiAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaMinus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaPlus"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_KaAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_Pr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_AntiPr"), cent, ietaA, ietaC, mptsubRecoEffCorr); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_RecoEffCorr_PrAll"), cent, ietaA, ietaC, mptsubRecoEffCorr); + } } - // "MCReco" - if (std::isfinite(sumWiRecoEt[0][0])) { - float meanEt = sumWiptiRecoEt[0][0] / sumWiRecoEt[0][0]; - if (!std::isfinite(meanEt)) - LOGF(info, "meanEtRecoEt = %.3f, num = %.3f, den =%.3f", meanEt, sumWiptiRecoEt[0][0], sumWiRecoEt[0][0]); - if (!std::isfinite(meanEt)) - continue; - histos.fill(HIST("MCReco/Prof_MeanEt_Cent"), cent, meanEt); - histos.fill(HIST("MCReco/Prof_MeanEt_Mult"), col.multNTracksPV(), meanEt); + } + + for (int isp = 0; isp < KNsp; ++isp) { + if (sumWiTruth[isp][ietaA] > 0) { + float val = sumWiptiTruth[isp][ietaA] / sumWiTruth[isp][ietaA]; + histos.fill(HIST("pmeanTru_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultTru_nch_etabin_spbin"), multPV, ietaA, isp, sumWiTruth[isp][ietaA]); } - // "MCRecoEffCorr" - if (std::isfinite(sumWiRecoEffCorrEt[0][0])) { - float meanEt = sumWiptiRecoEffCorrEt[0][0] / sumWiRecoEffCorrEt[0][0]; - if (!std::isfinite(meanEt)) - LOGF(info, "meanEtRecoEffcorrEt = %.3f, num = %.3f, den =%.3f", meanEt, sumWiptiRecoEffCorrEt[0][0], sumWiRecoEffCorrEt[0][0]); - if (!std::isfinite(meanEt)) - continue; - histos.fill(HIST("MCRecoEffCorr/Prof_MeanEt_Cent"), cent, meanEt); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanEt_Mult"), col.multNTracksPV(), meanEt); + if (sumWiReco[isp][ietaA] > 0) { + float val = sumWiptiReco[isp][ietaA] / sumWiReco[isp][ietaA]; + histos.fill(HIST("pmeanReco_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultReco_nch_etabin_spbin"), multPV, ietaA, isp, sumWiReco[isp][ietaA]); } - - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (std::isfinite(sumWiTruth[ieta][ipt])) - histos.fill(HIST("pmeanTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiTruth[ieta][ipt] / sumWiTruth[ieta][ipt]); - if (std::isfinite(sumWiReco[ieta][ipt])) - histos.fill(HIST("pmeanRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiReco[ieta][ipt] / sumWiReco[ieta][ipt]); - if (std::isfinite(sumWiRecoEffCorr[ieta][ipt])) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiRecoEffCorr[ieta][ipt] / sumWiRecoEffCorr[ieta][ipt]); - - if (std::isfinite(sumWiTruthEt[ieta][ipt])) - histos.fill(HIST("pmeanEtTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiTruthEt[ieta][ipt] / sumWiTruthEt[ieta][ipt]); - if (std::isfinite(sumWiRecoEt[ieta][ipt])) - histos.fill(HIST("pmeanEtRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiRecoEt[ieta][ipt] / sumWiRecoEt[ieta][ipt]); - if (std::isfinite(sumWiRecoEffCorrEt[ieta][ipt])) - histos.fill(HIST("pmeanEtRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, sumWiptiRecoEffCorrEt[ieta][ipt] / sumWiRecoEffCorrEt[ieta][ipt]); - } + if (sumWiRecoEffCorr[isp][ietaA] > 0) { + float val = sumWiptiRecoEffCorr[isp][ietaA] / sumWiRecoEffCorr[isp][ietaA]; + histos.fill(HIST("pmeanRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, val); + histos.fill(HIST("pmeanMultRecoEffcorr_nch_etabin_spbin"), multPV, ietaA, isp, sumWiRecoEffCorr[isp][ietaA]); } - } // end col loop + } + } // end ietaA + + double amplFT0A = 0, amplFT0C = 0; + if (mcCollision.has_foundFT0()) { + const auto& ft0 = mcCollision.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + auto chanelid = ft0.channelA()[iCh]; + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + auto eta = getEtaFT0(chanelid, 0); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + auto chanelid = ft0.channelC()[iCh]; + auto globalId = chanelid + KnFt0cCell; + float ampl = ft0.amplitudeC()[iCh]; + auto eta = getEtaFT0(globalId, 1); + amplFT0C += ampl; + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, globalId, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, globalId, eta, ampl); + } } - LOGF(info, "FINISHED RUNNING processMCMean (pT + Et)"); + histos.fill(HIST("pmeanFT0Amultpv"), multPV, amplFT0A); + histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); + histos.fill(HIST("pmeanFT0Cmultpv"), multPV, amplFT0C); + histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); } - PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt/Et and Eff Hists", cfgRunMCMean); + PROCESS_SWITCH(RadialFlowDecorr, processMCMean, "process MC to calculate mean pt and Eff Hists", cfgRunMCMean); - void processMCFluc(aod::McCollisions const& mcColl, MyRun3MCCollisions const& collisions, TCs const& tracks, FilteredTCs const& /*filteredTracks*/, aod::McParticles const& mcParticles) + void processMCFluc(MyRun3MCCollisions::iterator const& mcCollision, FilteredTCs const& mcTracks, aod::FT0s const&, aod::McParticles const& mcParticles) { - double sumPmwkTru[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkTru[KNEta][KNpT][KIntK]{}; - double sumPmwkReco[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkReco[KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEffCor[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEffCor[KNEta][KNpT][KIntK]{}; - double sumPmwkTruEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkTruEt[KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEt[KNEta][KNpT][KIntK]{}; - double sumPmwkRecoEffCorEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumWkRecoEffCorEt[KNEta][KNpT][KIntK]{}; - double meanTru[KNEta][KNpT]{}, c2Tru[KNEta][KNpT]{}; - double meanReco[KNEta][KNpT]{}, c2Reco[KNEta][KNpT]{}; - double meanRecoEffCor[KNEta][KNpT]{}, c2RecoEffCor[KNEta][KNpT]{}; - double meanTruEt[KNEta][KNpT]{}, c2TruEt[KNEta][KNpT]{}; - double meanRecoEt[KNEta][KNpT]{}, c2RecoEt[KNEta][KNpT]{}; - double meanRecoEffCorEt[KNEta][KNpT]{}, c2RecoEffCorEt[KNEta][KNpT]{}; - - for (const auto& mcCollision : mcColl) { - auto partSlice = mcParticles.sliceBy(partPerMcCollision, mcCollision.globalIndex()); - auto colSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - if (colSlice.size() != 1) + if (!state.pmeanTruNchEtabinSpbinStep2 || !state.pmeanRecoNchEtabinSpbinStep2 || !state.pmeanRecoEffcorrNchEtabinSpbinStep2 || + !state.pmeanMultTruNchEtabinSpbinStep2 || !state.pmeanMultRecoNchEtabinSpbinStep2 || !state.pmeanMultRecoEffcorrNchEtabinSpbinStep2) { + LOGF(warning, "MC fluc: Unified Mean pT or Mult map missing"); + return; + } + double sumPmwkTru[KNsp][KNEta][KIntM][KIntK]{}; + double sumWkTru[KNsp][KNEta][KIntK]{}; + double sumPmwkReco[KNsp][KNEta][KIntM][KIntK]{}; + double sumWkReco[KNsp][KNEta][KIntK]{}; + double sumPmwkRecoEffCor[KNsp][KNEta][KIntM][KIntK]{}; + double sumWkRecoEffCor[KNsp][KNEta][KIntK]{}; + + double meanTru[KNsp][KNEta]{}, c2Tru[KNsp][KNEta]{}; + double meanReco[KNsp][KNEta]{}, c2Reco[KNsp][KNEta]{}; + double meanRecoEffCor[KNsp][KNEta]{}, c2RecoEffCor[KNsp][KNEta]{}; + + double meanTruMult[KNsp][KNEta]{}; + double meanRecoMult[KNsp][KNEta]{}; + double meanRecoEffCorMult[KNsp][KNEta]{}; + + double p1kBarTru[KNsp][KNEta]{}, p1kBarReco[KNsp][KNEta]{}, p1kBarRecoEffCor[KNsp][KNEta]{}; + double p1kBarTruMult[KNsp][KNEta]{}, p1kBarRecoMult[KNsp][KNEta]{}, p1kBarRecoEffCorMult[KNsp][KNEta]{}; + + if (!mcCollision.has_mcCollision() || !isEventSelected(mcCollision)) + return; + float cent = getCentrality(mcCollision); + if (cent > KCentMax) + return; + float multPV = mcCollision.multNTracksPV(); + float vz = mcCollision.posZ(); + if (!isPassAddPileup(multPV, mcTracks.size(), cent)) + return; + + histos.fill(HIST("hVtxZ_after_sel"), mcCollision.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), multPV, mcTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), mcTracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, mcTracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, multPV); + + memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); + memset(sumWkTru, 0, sizeof(sumWkTru)); + memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); + memset(sumWkReco, 0, sizeof(sumWkReco)); + memset(sumPmwkRecoEffCor, 0, sizeof(sumPmwkRecoEffCor)); + memset(sumWkRecoEffCor, 0, sizeof(sumWkRecoEffCor)); + + memset(meanTru, 0, sizeof(meanTru)); + memset(c2Tru, 0, sizeof(c2Tru)); + memset(meanReco, 0, sizeof(meanReco)); + memset(c2Reco, 0, sizeof(c2Reco)); + memset(meanRecoEffCor, 0, sizeof(meanRecoEffCor)); + memset(c2RecoEffCor, 0, sizeof(c2RecoEffCor)); + + memset(meanTruMult, 0, sizeof(meanTruMult)); + memset(meanRecoMult, 0, sizeof(meanRecoMult)); + memset(meanRecoEffCorMult, 0, sizeof(meanRecoEffCorMult)); + + memset(p1kBarTru, 0, sizeof(p1kBarTru)); + memset(p1kBarReco, 0, sizeof(p1kBarReco)); + memset(p1kBarRecoEffCor, 0, sizeof(p1kBarRecoEffCor)); + + memset(p1kBarTruMult, 0, sizeof(p1kBarTruMult)); + memset(p1kBarRecoMult, 0, sizeof(p1kBarRecoMult)); + memset(p1kBarRecoEffCorMult, 0, sizeof(p1kBarRecoEffCorMult)); + + double p1kBarFt0A = 0.0, p1kBarFt0C = 0.0; + + for (const auto& particle : mcParticles) { + if (particle.mcCollisionId() != mcCollision.mcCollisionId()) continue; - // histos.fill(HIST("MCGen/hVtxZ"), mcCollision.posZ()); - for (const auto& col : colSlice) { - auto trackSlice = tracks.sliceBy(trackPerCollision, col.globalIndex()); - if (trackSlice.size() < 1) + if (!isParticleSelected(particle) || !particle.isPhysicalPrimary()) + continue; + + float pt = particle.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + float eta = particle.eta(); + int pdgCode = particle.pdgCode(); + int absPdg = std::abs(pdgCode); + + bool isSpecies[KNsp] = { + true, // kInclusiveIdx + pdgCode == -KPiPlus, // kPiMinusIdx + pdgCode == KPiPlus, // kPiPlusIdx + absPdg == KPiPlus, // kPiAllIdx + pdgCode == -KKPlus, // kKaMinusIdx + pdgCode == KKPlus, // kKaPlusIdx + absPdg == KKPlus, // kKaAllIdx + pdgCode == -KProton, // kAntiPrIdx + pdgCode == KProton, // kPrIdx + absPdg == KProton // kPrAllIdx + }; + + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (isSpecies[isp]) { + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkTru[isp][ieta][m][k] += std::pow(pt, m); + } + sumWkTru[isp][ieta][k]++; + } + } + } + } + } // end truth loop + + for (const auto& track : mcTracks) { + if (track.collisionId() != mcCollision.index()) + continue; + + if (!isTrackSelected(track)) + continue; - memset(sumPmwkTru, 0, sizeof(sumPmwkTru)); - memset(sumWkTru, 0, sizeof(sumWkTru)); - memset(sumPmwkReco, 0, sizeof(sumPmwkReco)); - memset(sumWkReco, 0, sizeof(sumWkReco)); - memset(sumPmwkRecoEffCor, 0, sizeof(sumPmwkRecoEffCor)); - memset(sumWkRecoEffCor, 0, sizeof(sumWkRecoEffCor)); - - memset(sumPmwkTruEt, 0, sizeof(sumPmwkTruEt)); - memset(sumWkTruEt, 0, sizeof(sumWkTruEt)); - memset(sumPmwkRecoEt, 0, sizeof(sumPmwkRecoEt)); - memset(sumWkRecoEt, 0, sizeof(sumWkRecoEt)); - memset(sumPmwkRecoEffCorEt, 0, sizeof(sumPmwkRecoEffCorEt)); - memset(sumWkRecoEffCorEt, 0, sizeof(sumWkRecoEffCorEt)); - - memset(meanTru, 0, sizeof(meanTru)); - memset(c2Tru, 0, sizeof(c2Tru)); - memset(meanReco, 0, sizeof(meanReco)); - memset(c2Reco, 0, sizeof(c2Reco)); - memset(meanRecoEffCor, 0, sizeof(meanRecoEffCor)); - memset(c2RecoEffCor, 0, sizeof(c2RecoEffCor)); - - memset(meanTruEt, 0, sizeof(meanTruEt)); - memset(c2TruEt, 0, sizeof(c2TruEt)); - memset(meanRecoEt, 0, sizeof(meanRecoEt)); - memset(c2RecoEt, 0, sizeof(c2RecoEt)); - memset(meanRecoEffCorEt, 0, sizeof(meanRecoEffCorEt)); - memset(c2RecoEffCorEt, 0, sizeof(c2RecoEffCorEt)); - - if (!col.has_mcCollision() || !isEventSelected(col)) + float pt = track.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + float eta = track.eta(); + float phi = track.phi(); + auto sign = track.sign(); + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) continue; - float cent = getCentrality(col); - if (cent > KCentMax) + float eff = getEfficiency(multPV, pt, eta, static_cast(isp), 0, cfgEff); + float fake = getEfficiency(multPV, pt, eta, static_cast(isp), 1, cfgEff); + float flatW = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatW * (1.0 - fake) / eff; + + if (!std::isfinite(w) || w <= 0.f || eff <= KFloatEpsilon) continue; - // truth - for (const auto& particle : partSlice) { - if (!isParticleSelected(particle)) - continue; - if (!particle.isPhysicalPrimary()) + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - float pt = particle.pt(); - float eta = particle.eta(); - float p = particle.p(); - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkTru[ieta][ipt][m][k] += std::pow(pt, m); - } - sumWkTru[ieta][ipt][k]++; - } - } - } - const int absPdgId = std::abs(particle.pdgCode()); - const bool isPion = (absPdgId == kPiPlus); - const bool isKaon = (absPdgId == kKPlus); - const bool isProton = (absPdgId == kProton); - if (isPion || isKaon || isProton) { - - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkTruEt[ieta][ipt][m][k] += std::pow(et, m); - } - sumWkTruEt[ieta][ipt][k]++; - } - } + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumPmwkReco[isp][ieta][m][k] += std::pow(1.0, k) * std::pow(pt, m); + sumPmwkRecoEffCor[isp][ieta][m][k] += std::pow(w, k) * std::pow(pt, m); } + sumWkReco[isp][ieta][k] += std::pow(1.0, k); + sumWkRecoEffCor[isp][ieta][k] += std::pow(w, k); } + } - } // end truth loop + if (isp == kInclusiveIdx) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrIdx) { + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0 - fake) / eff); + } + } + } // trkslice - for (const auto& track : trackSlice) { - if (!isTrackSelected(track)) - continue; - float pt = track.pt(); - float eta = track.eta(); - float p = track.p(); - float phi = track.phi(); - - float effIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 0); - float fakeIncl = getEfficiency(col.multNTracksPV(), pt, eta, kInclusive, 1); - float flatWeightIncl = getFlatteningWeight(cent, eta, phi, kInclusive); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= 0.f) - continue; - if (effIncl <= 0 || !std::isfinite(effIncl) || !std::isfinite(fakeIncl) || !std::isfinite(flatWeightIncl)) - continue; + for (int ieta = 0; ieta < KNEta; ++ieta) { + const int ibx = state.pmeanTruNchEtabinSpbinStep2->GetXaxis()->FindBin(mcCollision.multNTracksPV()); + const int iby = ieta + 1; + + for (int isp = 0; isp < KNsp; ++isp) { + const int ibz = isp + 1; + + meanTruMult[isp][ieta] = sumWkTru[isp][ieta][1]; + meanRecoMult[isp][ieta] = sumWkReco[isp][ieta][1]; + meanRecoEffCorMult[isp][ieta] = sumWkRecoEffCor[isp][ieta][1]; + + float mmptTru = state.pmeanTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptReco = state.pmeanRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmptRecoEffCor = state.pmeanRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + float mmMultTru = state.pmeanMultTruNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultReco = state.pmeanMultRecoNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMultRecoEffCor = state.pmeanMultRecoEffcorrNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + if (std::isfinite(mmptTru)) + std::tie(meanTru[isp][ieta], c2Tru[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkTru[isp][ieta], sumWkTru[isp][ieta], mmptTru); + if (std::isfinite(mmptReco)) + std::tie(meanReco[isp][ieta], c2Reco[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkReco[isp][ieta], sumWkReco[isp][ieta], mmptReco); + if (std::isfinite(mmptRecoEffCor)) + std::tie(meanRecoEffCor[isp][ieta], c2RecoEffCor[isp][ieta]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[isp][ieta], sumWkRecoEffCor[isp][ieta], mmptRecoEffCor); + + if (mmptTru != 0.0f) + p1kBarTru[isp][ieta] = meanTru[isp][ieta] - mmptTru; + if (mmptReco != 0.0f) + p1kBarReco[isp][ieta] = meanReco[isp][ieta] - mmptReco; + if (mmptRecoEffCor != 0.0f) + p1kBarRecoEffCor[isp][ieta] = meanRecoEffCor[isp][ieta] - mmptRecoEffCor; + + if (mmMultTru != 0.0f) + p1kBarTruMult[isp][ieta] = meanTruMult[isp][ieta] - mmMultTru; + if (mmMultReco != 0.0f) + p1kBarRecoMult[isp][ieta] = meanRecoMult[isp][ieta] - mmMultReco; + if (mmMultRecoEffCor != 0.0f) + p1kBarRecoEffCorMult[isp][ieta] = meanRecoEffCorMult[isp][ieta] - mmMultRecoEffCor; + } + } - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkReco[ieta][ipt][m][k] += std::pow(1.0f, k) * std::pow(pt, m); - sumPmwkRecoEffCor[ieta][ipt][m][k] += std::pow(wIncl, k) * std::pow(pt, m); - } - sumWkReco[ieta][ipt][k] += std::pow(1.0f, k); - sumWkRecoEffCor[ieta][ipt][k] += std::pow(wIncl, k); - } - } - } + double amplFT0A = 0, amplFT0C = 0; + if (mcCollision.has_foundFT0()) { + const auto& ft0 = mcCollision.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + float ampl = ft0.amplitudeC()[iCh]; + amplFT0C += ampl; + } + } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - - if (isPion || isKaon || isProton) { - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) - float effPid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 0); - float fakePid = getEfficiency(col.multNTracksPV(), pt, eta, kCombinedPID, 1); - float flatWeightPid = getFlatteningWeight(cent, eta, phi, kCombinedPID); - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - if (effPid >= 1.f || fakePid >= 1.f || !std::isfinite(effPid) || effPid <= KFloatEpsilon || !std::isfinite(fakePid) || !std::isfinite(flatWeightPid)) - continue; - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) - continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) { - sumPmwkRecoEt[ieta][ipt][m][k] += std::pow(1.0f, k) * std::pow(et, m); - sumPmwkRecoEffCorEt[ieta][ipt][m][k] += std::pow(wPid, k) * std::pow(et, m); - } - sumWkRecoEt[ieta][ipt][k] += std::pow(1.0f, k); - sumWkRecoEffCorEt[ieta][ipt][k] += std::pow(wPid, k); - } - } - } - } + for (int isp = 0; isp < KNsp; ++isp) { + for (int ieta = 0; ieta < KNEta; ++ieta) { + histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkTru[isp][ieta][1]); + histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkTru[isp][ieta][1]); - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - const int ibx = pmeanTruNchEtabinPtbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); - const int iby = ieta + 1; - const int ibz = ipt + 1; - - float mmptTru = pmeanTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptReco = pmeanRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetTru = pmeanEtTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetReco = pmeanEtRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetRecoEffCor = pmeanEtRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - - if (std::isfinite(mmptTru)) - std::tie(meanTru[ieta][ipt], c2Tru[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkTru[ieta][ipt], sumWkTru[ieta][ipt], mmptTru); - if (std::isfinite(mmptReco)) - std::tie(meanReco[ieta][ipt], c2Reco[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkReco[ieta][ipt], sumWkReco[ieta][ipt], mmptReco); - if (std::isfinite(mmptRecoEffCor)) - std::tie(meanRecoEffCor[ieta][ipt], c2RecoEffCor[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCor[ieta][ipt], sumWkRecoEffCor[ieta][ipt], mmptRecoEffCor); - - if (std::isfinite(mmetTru)) - std::tie(meanTruEt[ieta][ipt], c2TruEt[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkTruEt[ieta][ipt], sumWkTruEt[ieta][ipt], mmetTru); - if (std::isfinite(mmetReco)) - std::tie(meanRecoEt[ieta][ipt], c2RecoEt[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEt[ieta][ipt], sumWkRecoEt[ieta][ipt], mmetReco); - if (std::isfinite(mmetRecoEffCor)) - std::tie(meanRecoEffCorEt[ieta][ipt], c2RecoEffCorEt[ieta][ipt]) = calculateMeanAndC2FromSums(sumPmwkRecoEffCorEt[ieta][ipt], sumWkRecoEffCorEt[ieta][ipt], mmetRecoEffCor); - } - } + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkReco[isp][ieta][1]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkReco[isp][ieta][1]); + + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_NEta_Nsp_Nchrec"), cent, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_NEta_Nsp_Nchrec"), multPV, ieta, isp, sumWkRecoEffCor[isp][ieta][1]); + + if (sumWkTru[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCGen/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanTru[isp][ieta]); + } + if (sumWkReco[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCReco/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanReco[isp][ieta]); + } + if (sumWkRecoEffCor[isp][ieta][1] > 1.0f) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cent_NEta_Nsp_MeanpT"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_Mult_NEta_Nsp_MeanpT"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); } - if (std::isfinite(c2Tru[0][0])) { - histos.fill(HIST("MCGen/Prof_C2_Cent"), cent, c2Tru[0][0]); - histos.fill(HIST("MCGen/Prof_C2_Mult"), col.multNTracksPV(), c2Tru[0][0]); + } + } + + for (int ieta = 0; ieta < KNEta; ++ieta) { + for (int isp = 0; isp < KNsp; ++isp) { + if (std::isfinite(meanTru[isp][ieta])) { + histos.fill(HIST("MCGen/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanTru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanTru[isp][ieta]); } - if (std::isfinite(c2TruEt[0][0])) { - histos.fill(HIST("MCGen/Prof_C2Et_Cent"), cent, c2TruEt[0][0]); - histos.fill(HIST("MCGen/Prof_C2Et_Mult"), col.multNTracksPV(), c2TruEt[0][0]); + if (std::isfinite(c2Tru[isp][ieta])) { + histos.fill(HIST("MCGen/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Tru[isp][ieta]); + histos.fill(HIST("MCGen/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Tru[isp][ieta]); } - // "MCReco" - if (std::isfinite(c2Reco[0][0])) { - histos.fill(HIST("MCReco/Prof_C2_Cent"), cent, c2Reco[0][0]); - histos.fill(HIST("MCReco/Prof_C2_Mult"), col.multNTracksPV(), c2Reco[0][0]); + if (std::isfinite(meanReco[isp][ieta])) { + histos.fill(HIST("MCReco/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanReco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanReco[isp][ieta]); } - if (std::isfinite(c2RecoEt[0][0])) { - histos.fill(HIST("MCReco/Prof_C2Et_Cent"), cent, c2RecoEt[0][0]); - histos.fill(HIST("MCReco/Prof_C2Et_Mult"), col.multNTracksPV(), c2RecoEt[0][0]); + if (std::isfinite(c2Reco[isp][ieta])) { + histos.fill(HIST("MCReco/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2Reco[isp][ieta]); + histos.fill(HIST("MCReco/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2Reco[isp][ieta]); } - - if (std::isfinite(c2RecoEffCor[0][0])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent"), cent, c2RecoEffCor[0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult"), col.multNTracksPV(), c2RecoEffCor[0][0]); + if (std::isfinite(meanRecoEffCor[isp][ieta])) { + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, meanRecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult_etabin_spbin"), multPV, ieta, isp, meanRecoEffCor[isp][ieta]); } - if (std::isfinite(c2RecoEffCorEt[0][0])) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Et_Cent"), cent, c2RecoEffCorEt[0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_C2Et_Mult"), col.multNTracksPV(), c2RecoEffCorEt[0][0]); + if (std::isfinite(c2RecoEffCor[isp][ieta])) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2RecoEffCor[isp][ieta]); + histos.fill(HIST("MCRecoEffCorr/Prof_C2_Mult_etabin_spbin"), multPV, ieta, isp, c2RecoEffCor[isp][ieta]); } + } + } + + p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(multPV)); + p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(multPV)); - if (std::isfinite(sumWkTru[0][0][1])) { - histos.fill(HIST("MCGen/Prof_cent_Nchrec"), cent, sumWkTru[0][0][1]); - histos.fill(HIST("MCGen/Prof_MeanpT_Cent"), cent, meanTru[0][0]); - histos.fill(HIST("MCGen/Prof_MeanpT_Mult"), col.multNTracksPV(), meanTru[0][0]); + for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { + int ietaC = KNEta - ietaA; + for (int isp = 0; isp < KNsp; ++isp) { + float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; + float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; + float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; + float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; + + float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; + float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; + float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; + + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubTru); + histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubTru); } - if (std::isfinite(sumWkTruEt[0][0][1])) { - histos.fill(HIST("MCGen/Prof_MeanEt_Cent"), cent, meanTruEt[0][0]); - histos.fill(HIST("MCGen/Prof_MeanEt_Mult"), col.multNTracksPV(), meanTruEt[0][0]); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubReco); + histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubReco); } - // "MCReco" - if (std::isfinite(sumWkReco[0][0][1])) { - histos.fill(HIST("MCReco/Prof_cent_Nchrec"), cent, sumWkReco[0][0][1]); - histos.fill(HIST("MCReco/Prof_MeanpT_Cent"), cent, meanReco[0][0]); - histos.fill(HIST("MCReco/Prof_MeanpT_Mult"), col.multNTracksPV(), meanReco[0][0]); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_spbin"), multPV, ietaA, isp, c2SubRecoEffCor); } - if (std::isfinite(sumWkRecoEt[0][0][1])) { - histos.fill(HIST("MCReco/Prof_MeanEt_Cent"), cent, meanRecoEt[0][0]); - histos.fill(HIST("MCReco/Prof_MeanEt_Mult"), col.multNTracksPV(), meanRecoEt[0][0]); + if (std::isfinite(covTru)) { + histos.fill(HIST("MCGen/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covTru); + histos.fill(HIST("MCGen/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covTru); } - // "MCRecoEffCorr" - if (std::isfinite(sumWkRecoEffCor[0][0][1])) { - histos.fill(HIST("MCRecoEffCorr/Prof_cent_Nchrec"), cent, sumWkRecoEffCor[0][0][1]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Cent"), cent, meanRecoEffCor[0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanpT_Mult"), col.multNTracksPV(), meanRecoEffCor[0][0]); + if (std::isfinite(covReco)) { + histos.fill(HIST("MCReco/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covReco); + histos.fill(HIST("MCReco/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covReco); } - if (std::isfinite(sumWkRecoEffCorEt[0][0][1])) { - histos.fill(HIST("MCRecoEffCorr/Prof_MeanEt_Cent"), cent, meanRecoEffCorEt[0][0]); - histos.fill(HIST("MCRecoEffCorr/Prof_MeanEt_Mult"), col.multNTracksPV(), meanRecoEffCorEt[0][0]); + if (std::isfinite(covRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_Cov_Mult_etabin_spbin"), multPV, ietaA, isp, covRecoEffCor); } - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (std::isfinite(sumWkTru[ieta][ipt][1])) - histos.fill(HIST("pmeanTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, meanTru[ieta][ipt]); - if (std::isfinite(sumWkReco[ieta][ipt][1])) - histos.fill(HIST("pmeanRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, meanReco[ieta][ipt]); - if (std::isfinite(sumWkRecoEffCor[ieta][ipt][1])) - histos.fill(HIST("pmeanRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, meanRecoEffCor[ieta][ipt]); - if (std::isfinite(sumWkTruEt[ieta][ipt][1])) - histos.fill(HIST("pmeanEtTruNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, meanTruEt[ieta][ipt]); - if (std::isfinite(sumWkRecoEt[ieta][ipt][1])) - histos.fill(HIST("pmeanEtRecoNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, meanRecoEt[ieta][ipt]); - if (std::isfinite(sumWkRecoEffCorEt[ieta][ipt][1])) - histos.fill(HIST("pmeanEtRecoEffcorrNchEtabinPtbin"), col.multNTracksPV(), ieta, ipt, meanRecoEffCorEt[ieta][ipt]); - } + if (std::isfinite(covFT0ATru)) { + histos.fill(HIST("MCGen/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ATru); + histos.fill(HIST("MCGen/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ATru); + } + if (std::isfinite(covFT0AReco)) { + histos.fill(HIST("MCReco/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0AReco); + histos.fill(HIST("MCReco/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0AReco); + } + if (std::isfinite(covFT0ARecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0ARecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0ARecoEffCor); } - float p1kBarTru[KNEta][KNpT]{}, p1kBarReco[KNEta][KNpT]{}, p1kBarRecoEffCor[KNEta][KNpT]{}; - float p1kBarTruEt[KNEta][KNpT]{}, p1kBarRecoEt[KNEta][KNpT]{}, p1kBarRecoEffCorEt[KNEta][KNpT]{}; - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - const int ibx = pmeanTruNchEtabinPtbinStep2->GetXaxis()->FindBin(col.multNTracksPV()); - const int iby = ieta + 1; - const int ibz = ipt + 1; - - float mmptTru = pmeanTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptReco = pmeanRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmptRecoEffCor = pmeanRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetTru = pmeanEtTruNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetReco = pmeanEtRecoNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmetRecoEffCor = pmeanEtRecoEffcorrNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - - if (mmptTru != 0.0f) - p1kBarTru[ieta][ipt] = meanTru[ieta][ipt] - mmptTru; - if (mmptReco != 0.0f) - p1kBarReco[ieta][ipt] = meanReco[ieta][ipt] - mmptReco; - if (mmptRecoEffCor != 0.0f) - p1kBarRecoEffCor[ieta][ipt] = meanRecoEffCor[ieta][ipt] - mmptRecoEffCor; - - if (mmetTru != 0.0f) - p1kBarTruEt[ieta][ipt] = meanTruEt[ieta][ipt] - mmetTru; - if (mmetReco != 0.0f) - p1kBarRecoEt[ieta][ipt] = meanRecoEt[ieta][ipt] - mmetReco; - if (mmetRecoEffCor != 0.0f) - p1kBarRecoEffCorEt[ieta][ipt] = meanRecoEffCorEt[ieta][ipt] - mmetRecoEffCor; - } + if (std::isfinite(covFT0CTru)) { + histos.fill(HIST("MCGen/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CTru); + histos.fill(HIST("MCGen/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CTru); } + if (std::isfinite(covFT0CReco)) { + histos.fill(HIST("MCReco/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CReco); + histos.fill(HIST("MCReco/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CReco); + } + if (std::isfinite(covFT0CRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0CRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C_Mult_etabin_spbin"), multPV, ietaA, isp, covFT0CRecoEffCor); + } + } + } - // 1D Covariance (vs eta) - for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { - int ietaC = KNEta - ietaA; - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - { - const int ipt = 0; - float c2Sub = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCGen/Prof_ipt0_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCGen/Prof_ipt0_Cov_Eta"), valy, c2Sub); + for (int ietaA = 1; ietaA < KNEta; ++ietaA) { + for (int ietaC = 1; ietaC < KNEta; ++ietaC) { + + float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; + float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; + float gap = etaValA - etaValB; + float sum = (etaValA + etaValB); + for (int isp = 0; isp < KNsp; ++isp) { + + float c2SubTru = p1kBarTru[isp][ietaA] * p1kBarTru[isp][ietaC]; + float c2SubReco = p1kBarReco[isp][ietaA] * p1kBarReco[isp][ietaC]; + float c2SubRecoEffCor = p1kBarRecoEffCor[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covTru = p1kBarTruMult[isp][ietaA] * p1kBarTru[isp][ietaC]; + float covReco = p1kBarRecoMult[isp][ietaA] * p1kBarReco[isp][ietaC]; + float covRecoEffCor = p1kBarRecoEffCorMult[isp][ietaA] * p1kBarRecoEffCor[isp][ietaC]; + + float covFT0ATru = p1kBarFt0A * p1kBarTru[isp][ietaC]; + float covFT0AReco = p1kBarFt0A * p1kBarReco[isp][ietaC]; + float covFT0ARecoEffCor = p1kBarFt0A * p1kBarRecoEffCor[isp][ietaC]; + + float covFT0CTru = p1kBarFt0C * p1kBarTru[isp][ietaA]; + float covFT0CReco = p1kBarFt0C * p1kBarReco[isp][ietaA]; + float covFT0CRecoEffCor = p1kBarFt0C * p1kBarRecoEffCor[isp][ietaA]; + + if (isp == kInclusiveIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCGen/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCGen/Prof_ipt0_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCGen/Prof_ipt0_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D"), cent, gap, sum, c2SubReco); } - } - // ipt = 1 - { - const int ipt = 1; - float c2Sub = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCGen/Prof_ipt1_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCGen/Prof_ipt0_Cov_Eta"), valy, c2Sub); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D"), cent, gap, sum, c2SubRecoEffCor); } - float c2SubEt = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCGen/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCGen/Prof_ipt1_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCGen/Prof_ipt1_CovEt_Eta"), valy, c2SubEt); + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiMinusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubTru); } - } - // ipt = 2 - { - const int ipt = 2; - float c2Sub = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCGen/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCGen/Prof_ipt2_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCGen/Prof_ipt2_Cov_Eta"), valy, c2Sub); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubReco); } - float c2SubEt = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCGen/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCGen/Prof_ipt2_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCGen/Prof_ipt2_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiMinus"), cent, gap, sum, c2SubRecoEffCor); } - } - } - for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaC = 1; ietaC < KNEta; ++ietaC) { - float valx = KHalf * (etaLw[ietaA] + etaUp[ietaA]); - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - // ipt = 0 - { - const int ipt = 0; - float c2Sub = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCGen/Prof_ipt0_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCGen/Prof_ipt0_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiPlusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubTru); } - // ipt = 1 - { - const int ipt = 1; - float c2Sub = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCGen/Prof_ipt1_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCGen/Prof_ipt1_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubReco); } - // ipt = 2 - { - const int ipt = 2; - float c2Sub = p1kBarTru[ietaA][ipt] * p1kBarTru[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCGen/Prof_ipt2_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarTruEt[ietaA][ipt] * p1kBarTruEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCGen/Prof_ipt2_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiPlus"), cent, gap, sum, c2SubRecoEffCor); } - } - } - for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { - int ietaC = KNEta - ietaA; - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - // ipt = 0 - { - const int ipt = 0; - float c2Sub = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCReco/Prof_ipt0_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCReco/Prof_ipt0_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPiAllIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCReco/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCReco/Prof_ipt0_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCReco/Prof_ipt0_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PiAll"), cent, gap, sum, c2SubRecoEffCor); } - } - // ipt = 1 - { - const int ipt = 1; - float c2Sub = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCReco/Prof_ipt1_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCReco/Prof_ipt1_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaMinusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCReco/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCReco/Prof_ipt1_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCReco/Prof_ipt1_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaMinus"), cent, gap, sum, c2SubRecoEffCor); } - } - // ipt = 2 - { - const int ipt = 2; - float c2Sub = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCReco/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCReco/Prof_ipt2_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCReco/Prof_ipt2_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaPlusIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCReco/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCReco/Prof_ipt2_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCReco/Prof_ipt2_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubReco); } - } - } - - for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaC = 1; ietaC < KNEta; ++ietaC) { - float valx = KHalf * (etaLw[ietaA] + etaUp[ietaA]); - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - - // ipt = 0 - { - const int ipt = 0; - float c2Sub = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCReco/Prof_ipt0_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCReco/Prof_ipt0_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaPlus"), cent, gap, sum, c2SubRecoEffCor); } - // ipt = 1 - { - const int ipt = 1; - float c2Sub = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCReco/Prof_ipt1_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCReco/Prof_ipt1_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kKaAllIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubTru); } - - // ipt = 2 - { - const int ipt = 2; - float c2Sub = p1kBarReco[ietaA][ipt] * p1kBarReco[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCReco/Prof_ipt2_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarRecoEt[ietaA][ipt] * p1kBarRecoEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCReco/Prof_ipt2_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_KaAll"), cent, gap, sum, c2SubRecoEffCor); } - } - } - - for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { - int ietaC = KNEta - ietaA; - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - // ipt = 0 - { - const int ipt = 0; - float c2Sub = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPrIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_Pr"), cent, gap, sum, c2SubRecoEffCor); } - } - // ipt = 1 - { - const int ipt = 1; - float c2Sub = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kAntiPrIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubReco); + } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_AntiPr"), cent, gap, sum, c2SubRecoEffCor); } - } - // ipt = 2 - { - const int ipt = 2; - float c2Sub = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2Sub); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0CRecoEffCor); + + } else if (isp == kPrAllIdx) { + if (std::isfinite(c2SubTru)) { + histos.fill(HIST("MCGen/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubTru); + histos.fill(HIST("MCGen/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubTru); } - float c2SubEt = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("MCRecoEffCorr/Prof_C2EtSub_Mult_etabin_ptbin"), col.multNTracksPV(), ietaA, ipt, c2SubEt); - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(c2SubReco)) { + histos.fill(HIST("MCReco/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubReco); + histos.fill(HIST("MCReco/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubReco); } + if (std::isfinite(c2SubRecoEffCor)) { + histos.fill(HIST("MCRecoEffCorr/Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2SubRecoEffCor); + histos.fill(HIST("MCRecoEffCorr/Prof_GapSum2D_PrAll"), cent, gap, sum, c2SubRecoEffCor); + } + + if (std::isfinite(covTru)) + histos.fill(HIST("MCGen/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covTru); + if (std::isfinite(covReco)) + histos.fill(HIST("MCReco/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covReco); + if (std::isfinite(covRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covRecoEffCor); + + if (std::isfinite(covFT0ATru)) + histos.fill(HIST("MCGen/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ATru); + if (std::isfinite(covFT0AReco)) + histos.fill(HIST("MCReco/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0AReco); + if (std::isfinite(covFT0ARecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0ARecoEffCor); + + if (std::isfinite(covFT0CTru)) + histos.fill(HIST("MCGen/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CTru); + if (std::isfinite(covFT0CReco)) + histos.fill(HIST("MCReco/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CReco); + if (std::isfinite(covFT0CRecoEffCor)) + histos.fill(HIST("MCRecoEffCorr/Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0CRecoEffCor); } } + } + } + } + PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt fluc", cfgRunMCFluc); - for (int ietaA = 1; ietaA < KNEta; ++ietaA) { - for (int ietaC = 1; ietaC < KNEta; ++ietaC) { - float valx = 0.5f * (etaLw[ietaA] + etaUp[ietaA]); - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - - // ipt = 0 - { - const int ipt = 0; - float c2Sub = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt0_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); - } + void processDataGetNSig(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) + { + histos.fill(HIST("hVtxZ"), coll.posZ()); + if (!isEventSelected(coll)) + return; + float cent = getCentrality(coll); + if (cent > KCentMax) + return; + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); + histos.fill(HIST("hCentrality"), cent); - // ipt = 1 - { - const int ipt = 1; - float c2Sub = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt1_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); - } + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); - // ipt = 2 - { - const int ipt = 2; - float c2Sub = p1kBarRecoEffCor[ietaA][ipt] * p1kBarRecoEffCor[ietaC][ipt]; - if (std::isfinite(c2Sub)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, c2Sub); - float c2SubEt = p1kBarRecoEffCorEt[ietaA][ipt] * p1kBarRecoEffCorEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) - histos.fill(HIST("MCRecoEffCorr/Prof_ipt2_C2EtSub2D_Mult_etaA_etaC"), cent, valx, valy, c2SubEt); - } - } - } + int ntrk = 0; + for (const auto& track : tracks) { + if (!isTrackSelected(track)) + continue; + float pt = track.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + float eta = track.eta(); + if (eta > etaLw[0] && eta < etaUp[0]) + ntrk++; + fillNSigmaBefCut(track, cent); + } + + if (cfgZDC) { + const auto& foundBC = coll.foundBC_as(); + if (!foundBC.has_zdc()) { + return; } + auto zdc = foundBC.zdc(); + auto zdcAmp = zdc.energyCommonZNA() + zdc.energyCommonZNC(); + histos.fill(HIST("hnTrkPVZDC"), coll.multNTracksPV(), zdcAmp); + histos.fill(HIST("hNchZDC"), ntrk, zdcAmp); } - LOGF(info, "FINISHED RUNNING processMCFluc (pT + Et)"); } - PROCESS_SWITCH(RadialFlowDecorr, processMCFluc, "process MC to calculate pt/Et fluc", cfgRunMCFluc); + PROCESS_SWITCH(RadialFlowDecorr, processDataGetNSig, "process data to Get Nsigma cuts", cfgRunDataGetNSig); - void processGetFlat(AodCollisionsSel::iterator const& coll, aod::BCsWithTimestamps const&, AodTracksSel const& tracks) + void processGetDataFlat(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, AodTracksSel const& tracks) { + histos.fill(HIST("hVtxZ"), coll.posZ()); if (!isEventSelected(coll)) return; float cent = getCentrality(coll); if (cent > KCentMax) return; + + if (!isPassAddPileup(coll.multNTracksPV(), tracks.size(), cent)) + return; + + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); + + int ntrk = 0; + float vz = coll.posZ(); + for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; - float p = track.p(); + float pt = track.pt(); + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; float eta = track.eta(); float phi = track.phi(); - if (p < KFloatEpsilon) - continue; - histos.fill(HIST("hCentEtaPhi"), cent, eta, phi); - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - histos.fill(HIST("hCentEtaPhi_PID"), cent, eta, phi); + auto sign = track.sign(); + + histos.fill(HIST("hPt"), pt); + histos.fill(HIST("hEta"), eta); + histos.fill(HIST("hPhi"), phi); + + if (eta > etaLw[0] && eta < etaUp[0]) + ntrk++; + fillNSigmaBefCut(track, cent); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + fillNSigmaAftCut(track, cent, isSpecies); + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + if (eff <= KFloatEpsilon) + continue; + + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float w = (1.0f - fake) / eff; + + if (!std::isfinite(w) || w <= 0.f) + continue; + + if (isp == kInclusiveIdx) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrIdx) { + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + } + } + } + + if (cfgZDC) { + const auto& foundBC = coll.foundBC_as(); + if (!foundBC.has_zdc()) { + return; } + auto zdc = foundBC.zdc(); + auto zdcAmp = zdc.energyCommonZNA() + zdc.energyCommonZNC(); + histos.fill(HIST("hnTrkPVZDC"), coll.multNTracksPV(), zdcAmp); + histos.fill(HIST("hNchZDC"), ntrk, zdcAmp); } } - PROCESS_SWITCH(RadialFlowDecorr, processGetFlat, "process real data to calculate mean pT and Et", cfgRunGetFlat); + PROCESS_SWITCH(RadialFlowDecorr, processGetDataFlat, "process data to calculate Flattening maps", cfgRunGetDataFlat); - void processDataMean(AodCollisionsSel::iterator const& coll, aod::BCsWithTimestamps const&, AodTracksSel const& tracks) + void processDataMean(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FT0s const&, AodTracksSel const& tracks) { - float sumWi[KNEta][KNpT]{}, sumWipti[KNEta][KNpT]{}; - float sumWiEt[KNEta][KNpT]{}, sumWiEtVal[KNEta][KNpT]{}; + double sumWi[KNsp][KNEta]{}, sumWipti[KNsp][KNEta]{}; + if (!isEventSelected(coll)) return; @@ -2020,322 +3098,499 @@ struct RadialFlowDecorr { if (cent > KCentMax) return; - histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); + if (!isPassAddPileup(coll.multNTracksPV(), tracks.size(), cent)) + return; + + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); histos.fill(HIST("hCentrality"), cent); histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); + + float vz = coll.posZ(); for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; + + float p = track.p(); float pt = track.pt(); float eta = track.eta(); - float p = track.p(); float phi = track.phi(); + auto sign = track.sign(); + if (p < KFloatEpsilon) continue; + + if (pt <= cfgPtMin || pt > cfgPtMax) + continue; + histos.fill(HIST("hP"), p); histos.fill(HIST("hPt"), pt); histos.fill(HIST("hEta"), eta); - histos.fill(HIST("hPhi"), track.phi()); - - float effIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 0); - float fakeIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 1); - float flatWeightIncl = getFlatteningWeight(cent, eta, phi, kInclusive); - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= KFloatEpsilon || effIncl <= KFloatEpsilon) - continue; + histos.fill(HIST("hPhi"), phi); + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + if (eff <= KFloatEpsilon) + continue; - histos.fill(HIST("hCentEtaPhi"), cent, eta, track.phi()); - histos.fill(HIST("hCentEtaPhiWtd"), cent, eta, track.phi(), flatWeightIncl); + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatWeight * (1.0f - fake) / eff; - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + if (!std::isfinite(w) || w <= 0.f) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) + + if (isp == kInclusiveIdx) { + histos.fill(HIST("hEtaPhiReco"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiMinusIdx) { + histos.fill(HIST("hEtaPhiReco_PiMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiPlusIdx) { + histos.fill(HIST("hEtaPhiReco_PiPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kPiAllIdx) { + histos.fill(HIST("hEtaPhiReco_PiAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PiAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PiAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaMinusIdx) { + histos.fill(HIST("hEtaPhiReco_KaMinus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaMinus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaMinus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaPlusIdx) { + histos.fill(HIST("hEtaPhiReco_KaPlus"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaPlus"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaPlus"), vz, sign, pt, eta, phi, w); + } else if (isp == kKaAllIdx) { + histos.fill(HIST("hEtaPhiReco_KaAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_KaAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_KaAll"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrIdx) { + histos.fill(HIST("hEtaPhiReco_Pr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_Pr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_Pr"), vz, sign, pt, eta, phi, w); + } else if (isp == kAntiPrIdx) { + histos.fill(HIST("hEtaPhiReco_AntiPr"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_AntiPr"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_AntiPr"), vz, sign, pt, eta, phi, w); + } else if (isp == kPrAllIdx) { + histos.fill(HIST("hEtaPhiReco_PrAll"), vz, sign, pt, eta, phi); + histos.fill(HIST("hEtaPhiRecoEffWtd_PrAll"), vz, sign, pt, eta, phi, (1.0f - fake) / eff); + histos.fill(HIST("hEtaPhiRecoWtd_PrAll"), vz, sign, pt, eta, phi, w); + } + + for (int ieta = 0; ieta < KNEta; ++ieta) { + if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - sumWi[ieta][ipt] += wIncl; - sumWipti[ieta][ipt] += wIncl * pt; + sumWi[isp][ieta] += w; + sumWipti[isp][ieta] += w * pt; } } + } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - - float effPid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 0); - float fakePid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 1); - float flatWeightPid = getFlatteningWeight(cent, eta, phi, kCombinedPID); - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - if (!std::isfinite(wPid) || wPid <= KFloatEpsilon || effPid <= KFloatEpsilon) - continue; + for (int isp = 0; isp < KNsp; ++isp) { + if (sumWi[isp][0] < 1.0f) + continue; + histos.fill(HIST("Prof_Cent_Nsp_Nchrec"), cent, isp, sumWi[isp][0]); + histos.fill(HIST("Prof_Mult_Nsp_Nchrec"), coll.multNTracksPV(), isp, sumWi[isp][0]); + histos.fill(HIST("Prof_Cent_Nsp_MeanpT"), cent, isp, sumWipti[isp][0] / sumWi[isp][0]); + histos.fill(HIST("Prof_Mult_Nsp_MeanpT"), coll.multNTracksPV(), isp, sumWipti[isp][0] / sumWi[isp][0]); + } - histos.fill(HIST("hCentEtaPhiWtd_PID"), cent, eta, track.phi(), flatWeightPid); - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + for (int ietaA = 0; ietaA < KNEta; ++ietaA) { + for (int ietaC = 0; ietaC < KNEta; ++ietaC) { + for (int isp = 0; isp < KNsp; ++isp) { + if ((sumWi[isp][ietaA] < 1.0f) || (sumWi[isp][ietaC] < 1.0f)) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - sumWiEt[ieta][ipt] += wPid; - sumWiEtVal[ieta][ipt] += wPid * et; + + double wCorrAB = sumWi[isp][ietaA] + sumWi[isp][ietaC]; + if (wCorrAB > 0) { + float mptsub = (sumWipti[isp][ietaA] + sumWipti[isp][ietaC]) / wCorrAB; + if (isp == kInclusiveIdx) + histos.fill(HIST("Prof2D_MeanpTSub"), cent, ietaA, ietaC, mptsub); + else if (isp == kPiMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_PiMinus"), cent, ietaA, ietaC, mptsub); + else if (isp == kPiPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_PiPlus"), cent, ietaA, ietaC, mptsub); + else if (isp == kPiAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_PiAll"), cent, ietaA, ietaC, mptsub); + else if (isp == kKaMinusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_KaMinus"), cent, ietaA, ietaC, mptsub); + else if (isp == kKaPlusIdx) + histos.fill(HIST("Prof2D_MeanpTSub_KaPlus"), cent, ietaA, ietaC, mptsub); + else if (isp == kKaAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_KaAll"), cent, ietaA, ietaC, mptsub); + else if (isp == kPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_Pr"), cent, ietaA, ietaC, mptsub); + else if (isp == kAntiPrIdx) + histos.fill(HIST("Prof2D_MeanpTSub_AntiPr"), cent, ietaA, ietaC, mptsub); + else if (isp == kPrAllIdx) + histos.fill(HIST("Prof2D_MeanpTSub_PrAll"), cent, ietaA, ietaC, mptsub); + } + if (ietaA == ietaC) { + double mpt = sumWipti[isp][ietaA] / sumWi[isp][ietaA]; + if (sumWi[isp][ietaA] >= 1.0f && std::isfinite(mpt)) { + histos.fill(HIST("pmean_nch_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, mpt); + histos.fill(HIST("pmeanMult_nch_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, sumWi[isp][ietaA]); + histos.fill(HIST("pmean_cent_etabin_spbin"), cent, ietaA, isp, mpt); + histos.fill(HIST("pmeanMult_cent_etabin_spbin"), cent, ietaA, isp, sumWi[isp][ietaA]); + } } } } } - histos.fill(HIST("Prof_cent_Nchrec"), cent, sumWi[0][0]); - if (std::isfinite(sumWi[0][0])) - histos.fill(HIST("Prof_MeanpT_Cent"), cent, sumWipti[0][0] / sumWi[0][0]); - if (std::isfinite(sumWiEt[0][0])) - histos.fill(HIST("Prof_MeanEt_Cent"), cent, sumWiEtVal[0][0] / sumWiEt[0][0]); - - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (std::isfinite(sumWi[ieta][ipt])) - histos.fill(HIST("pmean_nch_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, sumWipti[ieta][ipt] / sumWi[ieta][ipt]); - if (std::isfinite(sumWiEt[ieta][ipt])) - histos.fill(HIST("pmeanEt_nch_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, sumWiEtVal[ieta][ipt] / sumWiEt[ieta][ipt]); + double amplFT0A = 0, amplFT0C = 0; + if (coll.has_foundFT0()) { + const auto& ft0 = coll.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + auto chanelid = ft0.channelA()[iCh]; + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + auto eta = getEtaFT0(chanelid, 0); + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, chanelid, eta, ampl); + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + auto chanelid = ft0.channelC()[iCh]; + auto globalId = chanelid + KnFt0cCell; + float ampl = ft0.amplitudeC()[iCh]; + auto eta = getEtaFT0(globalId, 1); + amplFT0C += ampl; + histos.fill(HIST("pmean_cent_id_eta_FT0"), cent, globalId, eta, ampl); + histos.fill(HIST("h3_cent_id_eta_FT0"), cent, globalId, eta, ampl); } } + + histos.fill(HIST("pmeanFT0Amultpv"), coll.multNTracksPV(), amplFT0A); + histos.fill(HIST("pmeanFT0A_cent"), cent, amplFT0A); + histos.fill(HIST("pmeanFT0Cmultpv"), coll.multNTracksPV(), amplFT0C); + histos.fill(HIST("pmeanFT0C_cent"), cent, amplFT0C); } - PROCESS_SWITCH(RadialFlowDecorr, processDataMean, "process real data to calculate mean pT and Et", cfgRunDataMean); + PROCESS_SWITCH(RadialFlowDecorr, processDataMean, "process data to calculate mean pT", cfgRunDataMean); - void processDataFluc(AodCollisionsSel::iterator const& coll, aod::BCsWithTimestamps const&, AodTracksSel const& tracks) + void processDataFluc(AodCollisionsSel::iterator const& coll, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FT0s const&, AodTracksSel const& tracks) { if (!isEventSelected(coll)) return; float cent = getCentrality(coll); if (cent > KCentMax) return; - if (!pmeanNchEtabinPtbinStep2 || !pmeanEtNchEtabinPtbinStep2) { - LOGF(warning, "Data fluc: Mean pT or Et map missing"); + + if (!isPassAddPileup(coll.multNTracksPV(), tracks.size(), cent)) return; - } - if (!hEff[kInclusive] || !hFake[kInclusive] || !hWeightMap3D[kInclusive] || !hEff[kCombinedPID] || !hFake[kCombinedPID] || !hWeightMap3D[kCombinedPID]) { - LOGF(warning, "Data fluc: Inclusive or PID correction maps are null"); + histos.fill(HIST("hVtxZ_after_sel"), coll.posZ()); + histos.fill(HIST("hCentrality"), cent); + + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), tracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), tracks.size(), cent); + histos.fill(HIST("Hist2D_globalTracks_cent"), cent, tracks.size()); + histos.fill(HIST("Hist2D_PVTracks_cent"), cent, coll.multNTracksPV()); + + if (!state.pmeanNchEtabinSpbinStep2 || !state.pmeanMultNchEtabinSpbinStep2) { + LOGF(warning, "Data fluc: Mean pT or Mult map missing"); return; } - double sumpmwk[KNEta][KNpT][KIntM][KIntK]{}; - double sumwk[KNEta][KNpT][KIntK]{}; - double sumpmwkEt[KNEta][KNpT][KIntM][KIntK]{}; - double sumwkEt[KNEta][KNpT][KIntK]{}; - double mean[KNEta][KNpT]{}, c2[KNEta][KNpT]{}; - double p1kBar[KNEta][KNpT]{}; - double meanEt[KNEta][KNpT]{}, c2Et[KNEta][KNpT]{}; - double p1kBarEt[KNEta][KNpT]{}; + + for (int isp = 0; isp < KNsp; ++isp) { + auto pid = static_cast(isp); + if (!state.hEff[pid] || !state.hFake[pid] || !state.hFlatWeight[pid]) { + LOGF(warning, "Data fluc: Correction maps (Eff, Fake, or Flat) are null for species index %d", isp); + return; + } + } + + double sumpmwk[KNsp][KNEta][KIntM][KIntK]{}; + double sumwk[KNsp][KNEta][KIntK]{}; + + double mean[KNsp][KNEta]{}, c2[KNsp][KNEta]{}; + double p1kBar[KNsp][KNEta]{}; + double meanMult[KNsp][KNEta]{}, p1kBarMult[KNsp][KNEta]{}; + + float vz = coll.posZ(); for (const auto& track : tracks) { if (!isTrackSelected(track)) continue; + + float p = track.p(); float pt = track.pt(); float eta = track.eta(); - float p = track.p(); float phi = track.phi(); + auto sign = track.sign(); + if (p < KFloatEpsilon) continue; - float effIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 0); - float fakeIncl = getEfficiency(coll.multNTracksPV(), pt, eta, kInclusive, 1); - float flatWeightIncl = getFlatteningWeight(cent, eta, phi, kInclusive); - - float wIncl = flatWeightIncl * (1.0 - fakeIncl) / effIncl; - if (!std::isfinite(wIncl) || wIncl <= KFloatEpsilon || effIncl <= KFloatEpsilon) + if (pt <= cfgPtMin || pt > cfgPtMax) continue; - - for (int ieta = 0; ieta < KNEta; ++ieta) { - if (eta <= etaLw[ieta] || eta > etaUp[ieta]) + int id = identifyTrack(track, cent); + bool isPi = (id == KPidPionOne); + bool isKa = (id == KPidKaonTwo); + bool isPr = (id == KPidProtonThree); + bool isSpecies[KNsp] = { + true, + isPi && sign < 0, isPi && sign > 0, isPi, + isKa && sign < 0, isKa && sign > 0, isKa, + isPr && sign < 0, isPr && sign > 0, isPr}; + + for (int isp = 0; isp < KNsp; ++isp) { + if (!isSpecies[isp]) + continue; + float eff = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 0, cfgEff); + if (eff <= KFloatEpsilon) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) - sumpmwk[ieta][ipt][m][k] += std::pow(wIncl, k) * std::pow(pt, m); - sumwk[ieta][ipt][k] += std::pow(wIncl, k); - } - } - } - const bool isPion = selectionPion(track); - const bool isKaon = selectionKaon(track); - const bool isProton = selectionProton(track); - if (isPion || isKaon || isProton) { - float effPid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 0); - float fakePid = getEfficiency(coll.multNTracksPV(), pt, eta, kCombinedPID, 1); - float flatWeightPid = getFlatteningWeight(cent, eta, phi, kCombinedPID); + float fake = getEfficiency(coll.multNTracksPV(), pt, eta, static_cast(isp), 1, cfgEff); + float flatWeight = getFlatteningWeight(vz, sign, pt, eta, phi, static_cast(isp), cfgFlat); + float w = flatWeight * (1.0f - fake) / eff; - float wPid = flatWeightPid * (1.0 - fakePid) / effPid; - if (!std::isfinite(wPid) || wPid <= KFloatEpsilon || effPid <= KFloatEpsilon) + if (!std::isfinite(w) || w <= 0.f) continue; - float m = isPion ? o2::constants::physics::MassPiPlus : isKaon ? o2::constants::physics::MassKPlus - : o2::constants::physics::MassProton; - - float energy = std::sqrt(p * p + m * m); - float et = energy * (pt / p); // E_T = E * sin(theta) for (int ieta = 0; ieta < KNEta; ++ieta) { if (eta <= etaLw[ieta] || eta > etaUp[ieta]) continue; - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (pt <= pTLw[ipt] || pt > pTUp[ipt]) - continue; - for (int k = 0; k < KIntK; ++k) { - for (int m = 0; m < KIntM; ++m) - sumpmwkEt[ieta][ipt][m][k] += std::pow(wPid, k) * std::pow(et, m); - sumwkEt[ieta][ipt][k] += std::pow(wPid, k); + for (int k = 0; k < KIntK; ++k) { + for (int m = 0; m < KIntM; ++m) { + sumpmwk[isp][ieta][m][k] += std::pow(w, k) * std::pow(pt, m); } + sumwk[isp][ieta][k] += std::pow(w, k); } } } } + double amplFT0A = 0, amplFT0C = 0; + if (coll.has_foundFT0()) { + const auto& ft0 = coll.foundFT0(); + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + float ampl = ft0.amplitudeA()[iCh]; + amplFT0A += ampl; + } + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + float ampl = ft0.amplitudeC()[iCh]; + amplFT0C += ampl; + } + } + double p1kBarFt0A = amplFT0A - state.pmeanFT0AmultpvStep2->GetBinContent(state.pmeanFT0AmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); + double p1kBarFt0C = amplFT0C - state.pmeanFT0CmultpvStep2->GetBinContent(state.pmeanFT0CmultpvStep2->GetXaxis()->FindBin(coll.multNTracksPV())); + for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - const int ibx = pmeanNchEtabinPtbinStep2->GetXaxis()->FindBin(coll.multNTracksPV()); - const int iby = ieta + 1; - const int ibz = ipt + 1; - float mmpt = pmeanNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); - float mmet = pmeanEtNchEtabinPtbinStep2->GetBinContent(ibx, iby, ibz); + const int ibx = state.pmeanNchEtabinSpbinStep2->GetXaxis()->FindBin(coll.multNTracksPV()); + const int iby = ieta + 1; - mean[ieta][ipt] = sumpmwk[ieta][ipt][1][1] / sumwk[ieta][ipt][1]; - meanEt[ieta][ipt] = sumpmwkEt[ieta][ipt][1][1] / sumwkEt[ieta][ipt][1]; + for (int isp = 0; isp < KNsp; ++isp) { + const int ibz = isp + 1; + + float mmpt = state.pmeanNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + float mmMult = state.pmeanMultNchEtabinSpbinStep2->GetBinContent(ibx, iby, ibz); + + mean[isp][ieta] = sumpmwk[isp][ieta][1][1] / sumwk[isp][ieta][1]; + meanMult[isp][ieta] = sumwk[isp][ieta][1]; if (std::isfinite(mmpt)) { - std::tie(mean[ieta][ipt], c2[ieta][ipt]) = - calculateMeanAndC2FromSums(sumpmwk[ieta][ipt], sumwk[ieta][ipt], mmpt); - p1kBar[ieta][ipt] = mean[ieta][ipt] - mmpt; - } - if (std::isfinite(mmet)) { - std::tie(meanEt[ieta][ipt], c2Et[ieta][ipt]) = - calculateMeanAndC2FromSums(sumpmwkEt[ieta][ipt], sumwkEt[ieta][ipt], mmet); - p1kBarEt[ieta][ipt] = meanEt[ieta][ipt] - mmet; + std::tie(mean[isp][ieta], c2[isp][ieta]) = calculateMeanAndC2FromSums(sumpmwk[isp][ieta], sumwk[isp][ieta], mmpt); + p1kBar[isp][ieta] = mean[isp][ieta] - mmpt; } + p1kBarMult[isp][ieta] = meanMult[isp][ieta] - mmMult; } } - - if (std::isfinite(c2[0][0])) - histos.fill(HIST("Prof_C2_Cent"), cent, c2[0][0]); - if (std::isfinite(c2Et[0][0])) - histos.fill(HIST("Prof_C2Et_Cent"), cent, c2Et[0][0]); - if (std::isfinite(sumwk[0][0][1])) { - histos.fill(HIST("Prof_MeanpT_Cent"), cent, mean[0][0]); - histos.fill(HIST("Prof_MeanpT_Mult"), coll.multNTracksPV(), mean[0][0]); - } - if (std::isfinite(sumwkEt[0][0][1])) { - histos.fill(HIST("Prof_MeanEt_Cent"), cent, meanEt[0][0]); - histos.fill(HIST("Prof_MeanEt_Mult"), coll.multNTracksPV(), meanEt[0][0]); - } - for (int ieta = 0; ieta < KNEta; ++ieta) { - for (int ipt = 0; ipt < KNpT; ++ipt) { - if (std::isfinite(c2[ieta][ipt])) - histos.fill(HIST("Prof_C2_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2[ieta][ipt]); - if (std::isfinite(c2Et[ieta][ipt])) - histos.fill(HIST("Prof_C2Et_Mult_etabin_ptbin"), coll.multNTracksPV(), ieta, ipt, c2Et[ieta][ipt]); + for (int isp = 0; isp < KNsp; ++isp) { + if (std::isfinite(mean[isp][ieta])) { + histos.fill(HIST("Prof_MeanpT_Cent_etabin_spbin"), cent, ieta, isp, mean[isp][ieta]); + histos.fill(HIST("Prof_MeanpT_Mult_etabin_spbin"), coll.multNTracksPV(), ieta, isp, mean[isp][ieta]); + } + if (std::isfinite(c2[isp][ieta])) { + histos.fill(HIST("Prof_C2_Cent_etabin_spbin"), cent, ieta, isp, c2[isp][ieta]); + histos.fill(HIST("Prof_C2_Mult_etabin_spbin"), coll.multNTracksPV(), ieta, isp, c2[isp][ieta]); + } } } for (int ietaA = 1; ietaA <= (KNEta - 1) / 2; ++ietaA) { int ietaC = KNEta - ietaA; - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); + for (int isp = 0; isp < KNsp; ++isp) { + float c2Sub = p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; + float covAC = p1kBarMult[isp][ietaA] * p1kBar[isp][ietaC]; + float covCA = p1kBar[isp][ietaA] * p1kBarMult[isp][ietaC]; - { - const int ipt = 0; - float c2Sub = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt0_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("Prof_ipt0_Cov_Eta"), valy, c2Sub); - } - float c2SubEt = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("Prof_ipt0_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("Prof_ipt0_CovEt_Eta"), valy, c2SubEt); - } - } + float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; + float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; - { - const int ipt = 1; - float c2Sub = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt1_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("Prof_ipt1_Cov_Eta"), valy, c2Sub); + histos.fill(HIST("Prof_C2Sub_Cent_etabin_spbin"), cent, ietaA, isp, c2Sub); + histos.fill(HIST("Prof_C2Sub_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, c2Sub); } - float c2SubEt = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("Prof_ipt1_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("Prof_ipt1_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(covAC)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covAC); + histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covAC); } - } - - { - const int ipt = 2; - float c2Sub = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(c2Sub)) { - histos.fill(HIST("Prof_ipt2_Cov_Cent_eta"), cent, valy, c2Sub); - if (cent < KCentCovCut) - histos.fill(HIST("Prof_ipt2_Cov_Eta"), valy, c2Sub); + if (std::isfinite(covCA)) { + histos.fill(HIST("Prof_Cov_Cent_etabin_spbin"), cent, ietaA, isp, covCA); + histos.fill(HIST("Prof_Cov_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covCA); } - float c2SubEt = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(c2SubEt)) { - histos.fill(HIST("Prof_ipt2_CovEt_Cent_eta"), cent, valy, c2SubEt); - if (cent < KCentCovCut) - histos.fill(HIST("Prof_ipt2_CovEt_Eta"), valy, c2SubEt); + if (std::isfinite(covFT0A)) { + histos.fill(HIST("Prof_CovFT0A_Cent_etabin_spbin"), cent, ietaA, isp, covFT0A); + histos.fill(HIST("Prof_CovFT0A_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covFT0A); + } + if (std::isfinite(covFT0C)) { + histos.fill(HIST("Prof_CovFT0C_Cent_etabin_spbin"), cent, ietaA, isp, covFT0C); + histos.fill(HIST("Prof_CovFT0C_Mult_etabin_spbin"), coll.multNTracksPV(), ietaA, isp, covFT0C); } } } for (int ietaA = 1; ietaA < KNEta; ++ietaA) { for (int ietaC = 1; ietaC < KNEta; ++ietaC) { - float valx = KHalf * (etaLw[ietaA] + etaUp[ietaA]); - float valy = KHalf * (etaLw[ietaC] + etaUp[ietaC]); - { - const int ipt = 0; - float covpt = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(covpt)) - histos.fill(HIST("Prof_ipt0_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, covpt); - - float covet = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(covet)) - histos.fill(HIST("Prof_ipt0_C2SubEt2D_Mult_etaA_etaC"), cent, valx, valy, covet); - } - { - const int ipt = 1; - float covpt = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(covpt)) - histos.fill(HIST("Prof_ipt1_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, covpt); + float etaValA = (etaLw[ietaA] + etaUp[ietaA]) / 2.0f; + float etaValB = (etaLw[ietaC] + etaUp[ietaC]) / 2.0f; + float gap = etaValA - etaValB; + float sum = (etaValA + etaValB); - float covet = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(covet)) - histos.fill(HIST("Prof_ipt1_C2SubEt2D_Mult_etaA_etaC"), cent, valx, valy, covet); - } - { - const int ipt = 2; + for (int isp = 0; isp < KNsp; ++isp) { - float covpt = p1kBar[ietaA][ipt] * p1kBar[ietaC][ipt]; - if (std::isfinite(covpt)) - histos.fill(HIST("Prof_ipt2_C2Sub2D_Mult_etaA_etaC"), cent, valx, valy, covpt); + float c2Sub = p1kBar[isp][ietaA] * p1kBar[isp][ietaC]; + float cov = p1kBarMult[isp][ietaA] * p1kBar[isp][ietaC]; + float covFT0A = p1kBarFt0A * p1kBar[isp][ietaC]; + float covFT0C = p1kBarFt0C * p1kBar[isp][ietaA]; - float covet = p1kBarEt[ietaA][ipt] * p1kBarEt[ietaC][ipt]; - if (std::isfinite(covet)) - histos.fill(HIST("Prof_ipt2_C2SubEt2D_Mult_etaA_etaC"), cent, valx, valy, covet); + if (isp == kInclusiveIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPiMinusIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PiMinus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiMinus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPiPlusIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PiPlus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiPlus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPiAllIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PiAll"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PiAll"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kKaMinusIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_KaMinus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaMinus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kKaPlusIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_KaPlus"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaPlus"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kKaAllIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_KaAll"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_KaAll"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPrIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_Pr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_Pr"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kAntiPrIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_AntiPr"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_AntiPr"), cent, etaValA, etaValB, covFT0C); + } else if (isp == kPrAllIdx) { + if (std::isfinite(c2Sub)) { + histos.fill(HIST("Prof_C2Sub2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, c2Sub); + histos.fill(HIST("Prof_GapSum2D_PrAll"), cent, gap, sum, c2Sub); + } + if (std::isfinite(cov)) + histos.fill(HIST("Prof_Cov2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, cov); + if (std::isfinite(covFT0A)) + histos.fill(HIST("Prof_CovFT0A2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0A); + if (std::isfinite(covFT0C)) + histos.fill(HIST("Prof_CovFT0C2D_Cent_etaA_etaC_PrAll"), cent, etaValA, etaValB, covFT0C); + } } } } } - PROCESS_SWITCH(RadialFlowDecorr, processDataFluc, "process real data to calculate fluc pT and Et", cfgRunDataFluc); + PROCESS_SWITCH(RadialFlowDecorr, processDataFluc, "process data to calculate fluc pT", cfgRunDataFluc); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx index 6bdeab9fe76..f79cb80298b 100644 --- a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -39,6 +39,7 @@ #include "ReconstructionDataFormats/Track.h" #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +69,8 @@ using namespace o2::framework::expressions; static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + struct V0ptHadPiKaProt { // ITS response @@ -74,7 +78,8 @@ struct V0ptHadPiKaProt { // Connect to ccdb Service 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 ccdbUrl{"ccdbUrl", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable ccdbUrl{"ccdbUrl", "https://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPath{"ccdbPath", "Users/s/swati/PhiWeight", "CCDB path to ccdb object containing phi weight in a 3D histogram"}; enum Particles { PIONS = 0, @@ -115,6 +120,9 @@ struct V0ptHadPiKaProt { Configurable cfgnSigmaCutCombTPCTOF{"cfgnSigmaCutCombTPCTOF", 2.0f, "PID nSigma combined cut for TPC and TOF"}; ConfigurableAxis nchAxis{"nchAxis", {5000, 0.5, 5000.5}, ""}; ConfigurableAxis centAxis{"centAxis", {90, 0., 90.}, "Centrality/Multiplicity percentile bining"}; + ConfigurableAxis nchAxis1{"nchAxis1", {500, 0.5, 500.5}, "Axis for multiplicity of GlobalTracks/PVTracks"}; + ConfigurableAxis nchAxis2{"nchAxis2", {1000, 0.5, 30000.5}, "Axis for multiplicity of FT0A/FT0C/FV0A"}; + ConfigurableAxis nchAxis3{"nchAxis3", {1000, 0.5, 100000.5}, "Axis for multiplicity of FT0A/FT0C/FV0A"}; Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; Configurable cfgCutPtLowerProt{"cfgCutPtLowerProt", 0.2f, "Lower pT cut"}; Configurable cfgCutPtUpper{"cfgCutPtUpper", 10.0f, "Higher pT cut for inclusive hadron analysis"}; @@ -122,7 +130,7 @@ struct V0ptHadPiKaProt { Configurable cfgCutEta{"cfgCutEta", 0.8f, "absolute Eta cut"}; Configurable cfgCutEtaLeft{"cfgCutEtaLeft", 0.8f, "Left end of eta gap"}; Configurable cfgCutEtaRight{"cfgCutEtaRight", 0.8f, "Right end of eta gap"}; - Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; + Configurable cfgNSubsample{"cfgNSubsample", 20, "Number of subsamples"}; Configurable cfgCentralityChoice{"cfgCentralityChoice", 0, "Which centrality estimator? 0-->FT0C, 1-->FT0A, 2-->FT0M, 3-->FV0A"}; Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", true, "Pileup removal"}; Configurable cfgUseGoodITSLayerAllCut{"cfgUseGoodITSLayerAllCut", true, "Remove time interval with dead ITS zone"}; @@ -133,11 +141,67 @@ struct V0ptHadPiKaProt { Configurable cfgPtCutTOF{"cfgPtCutTOF", 0.3f, "Minimum pt to use TOF N-sigma"}; Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"pos_pi", "pos_ka", "pos_pr", "neg_pi", "neg_ka", "neg_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; Configurable cfgUseRun3V2PID{"cfgUseRun3V2PID", true, "True if PID cuts to be used are similar to Run3 v2 PID analysis"}; - + Configurable cfgNbinsV02pt{"cfgNbinsV02pt", 14, "No. of pT bins for v02(pT) analysis"}; + Configurable cfgCutPtMaxForV02{"cfgCutPtMaxForV02", 3.0f, "Max. pT for v02(pT)"}; + Configurable cfgCutEtaWindowB{"cfgCutEtaWindowB", 0.4f, "value of x in |eta| cfgLoadPhiWeights{"cfgLoadPhiWeights", false, "Load phi weights from CCDB to take care of non-uniform acceptance"}; + + // pT dep DCAxy and DCAz cuts + Configurable cfgUsePtDepDCAxy{"cfgUsePtDepDCAxy", true, "Use pt-dependent DCAxy cut"}; + Configurable cfgUsePtDepDCAz{"cfgUsePtDepDCAz", true, "Use pt-dependent DCAz cut"}; + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAzFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAz cut"); + TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAz = nullptr; + + O2_DEFINE_CONFIGURABLE(cfgUseSmallIonAdditionalEventCut, bool, true, "Use additional event cut on mult correlations for small ions") + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultT0CCutEnabled, bool, false, "Enable Global multiplicity vs T0C centrality cut") + Configurable> cfgMultT0CCutPars{"cfgMultT0CCutPars", std::vector{143.04, -4.58368, 0.0766055, -0.000727796, 2.86153e-06, 23.3108, -0.36304, 0.00437706, -4.717e-05, 1.98332e-07}, "Global multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultPVT0CCutEnabled, bool, false, "Enable PV multiplicity vs T0C centrality cut") + Configurable> cfgMultPVT0CCutPars{"cfgMultPVT0CCutPars", std::vector{195.357, -6.15194, 0.101313, -0.000955828, 3.74793e-06, 30.0326, -0.43322, 0.00476265, -5.11206e-05, 2.13613e-07}, "PV multiplicity vs T0C centrality cut parameter values"}; + + O2_DEFINE_CONFIGURABLE(cfgMultMultPVHighCutFunction, std::string, "[0]+[1]*x + 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultPVLowCutFunction, std::string, "[0]+[1]*x - 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCutEnabled, bool, false, "Enable global multiplicity vs PV multiplicity cut") + Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.140809, 0.734344, 2.77495, 0.0165935}, "PV multiplicity vs T0C centrality cut parameter values"}; + + O2_DEFINE_CONFIGURABLE(cfgMultMultV0AHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 4.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ACutEnabled, bool, false, "Enable global multiplicity vs V0A multiplicity cut") + Configurable> cfgMultMultV0ACutPars{"cfgMultMultV0ACutPars", std::vector{534.893, 184.344, 0.423539, -0.00331436, 5.34622e-06, 871.239, 53.3735, -0.203528, 0.000122758, 5.41027e-07}, "Global multiplicity vs V0A multiplicity cut parameter values"}; + + std::vector multT0CCutPars; + std::vector multPVT0CCutPars; + std::vector multGlobalPVCutPars; + std::vector multMultV0ACutPars; + TF1* fMultPVT0CCutLow = nullptr; + TF1* fMultPVT0CCutHigh = nullptr; + TF1* fMultT0CCutLow = nullptr; + TF1* fMultT0CCutHigh = nullptr; + TF1* fMultGlobalPVCutLow = nullptr; + TF1* fMultGlobalPVCutHigh = nullptr; + TF1* fMultMultV0ACutLow = nullptr; + TF1* fMultMultV0ACutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + + } cfgFuncParas; + + // Output HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histosAnalysis{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; std::vector>> subSample; + std::vector>> subSampleV02; TRandom3* funRndm = new TRandom3(0); + // Phi weight histograms initialization + TH2F* hWeightPhiFunctionVzEtaPhi = nullptr; + // Filter command*********** Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtLower) && (aod::track::pt < cfgCutPtUpper) && (requireGlobalTrackInFilter()) && (aod::track::tpcChi2NCl < cfgCutTpcChi2NCl) && (aod::track::itsChi2NCl < cfgCutItsChi2NCl) && (nabs(aod::track::dcaZ) < cfgCutTrackDcaZ); @@ -175,6 +239,24 @@ struct V0ptHadPiKaProt { itsNsigmaCut[kKaonLowCut] = nSigmas->getData()[kITS][kKaonLowCut]; itsNsigmaCut[kProtonLowCut] = nSigmas->getData()[kITS][kProtonLowCut]; + // Loading phi weight histograms from CCDB + if (cfgLoadPhiWeights) { + + // Accessing eff histograms + ccdb->setURL(ccdbUrl.value); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now, will be replaced by the value of the train creation + // This avoids that users can replace objects **while** a train is running + ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + LOGF(info, "Getting object %s", ccdbPath.value.data()); + TList* lst = ccdb->getForTimeStamp(ccdbPath.value, ccdbNoLaterThan.value); + hWeightPhiFunctionVzEtaPhi = reinterpret_cast(lst->FindObject("hWeightPhiFunctionVzEtaPhi")); + if (!hWeightPhiFunctionVzEtaPhi) + LOGF(info, "FATAL!! could not get phi weights---------> check"); + } + // Define axes std::vector ptBin = {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.5, 4.0, 5.0, 6.0, 8.0, 10.0}; AxisSpec ptAxis = {ptBin, "#it{p}_{T} (GeV/#it{c})"}; @@ -184,18 +266,39 @@ struct V0ptHadPiKaProt { // Add histograms to histogram manager (as in the output object of in AliPhysics) // QA hists + histos.add("hEventStatData", "Data Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); histos.add("hZvtx_after_sel", ";Z (cm)", kTH1F, {{240, -12, 12}}); histos.add("hCentrality", ";centrality (%)", kTH1F, {{90, 0, 90}}); + // before selection + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_PVTracks_beforeSel", "", {HistType::kTH2D, {nchAxis1, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_centFT0C_beforeSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_PVTracks_centFT0C_beforeSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_V0ATracks_beforeSel", "", {HistType::kTH2D, {nchAxis3, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_T0ATracks_beforeSel", "", {HistType::kTH2D, {nchAxis2, nchAxis1}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_V0ATracks_T0CTracks_beforeSel", "", {HistType::kTH2D, {nchAxis2, nchAxis3}}); + // after selection + if (cfgUseSmallIonAdditionalEventCut) { + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_PVTracks_afterSel", "", {HistType::kTH2D, {nchAxis1, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel", "", {HistType::kTH2D, {centAxis, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel", "", {HistType::kTH2D, {nchAxis3, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis1}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis3}}); + } + histos.add("Hist2D_globalTracks_PVTracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histos.add("Hist2D_cent_nch", "", {HistType::kTH2D, {nchAxis, centAxis}}); histos.add("hP", ";#it{p} (GeV/#it{c})", kTH1F, {{35, 0.2, 4.}}); histos.add("hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); histos.add("hPhi", ";#phi", kTH1F, {{100, 0., o2::constants::math::TwoPI}}); histos.add("hEta", ";#eta", kTH1F, {{100, -2.01, 2.01}}); - histos.add("hDcaXY", ";#it{dca}_{XY}", kTH1F, {{1000, -5, 5}}); - histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -5, 5}}); + histos.add("hDcaXY", ";#it{dca}_{XY}", kTH1F, {{1000, -0.5, 0.5}}); + histos.add("hDcaZ", ";#it{dca}_{Z}", kTH1F, {{1000, -0.5, 0.5}}); histos.add("hMeanPt", "", kTProfile, {centAxis}); + // phi weight hist for non-uniform acceptance correction + histos.add("h3DVtxZetaPhi", "", kTH3D, {{20, -10, 10}, {16, -0.8, +0.8}, {100, 0., o2::constants::math::TwoPI}}); + // 2D histograms of nSigma // before cut histos.add("h2DnsigmaPionTpcVsPtBeforeCut", "2D hist of nSigmaTPC vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); @@ -244,10 +347,23 @@ struct V0ptHadPiKaProt { histos.add("Prof_Bone_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); histos.add("Prof_Btwo_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + // Analysis profile for v02(pT) + histos.add("Prof_XY", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_XYZ_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_XYZ_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_Z_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + // initial array subSample.resize(cfgNSubsample); + subSampleV02.resize(cfgNSubsample); for (int i = 0; i < cfgNSubsample; i++) { subSample[i].resize(20); + subSampleV02[i].resize(9); } for (int i = 0; i < cfgNSubsample; i++) { subSample[i][0] = std::get>(histos.add(Form("subSample_%d/Prof_A_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); @@ -273,7 +389,52 @@ struct V0ptHadPiKaProt { subSample[i][17] = std::get>(histos.add(Form("subSample_%d/Prof_D_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); subSample[i][18] = std::get>(histos.add(Form("subSample_%d/Prof_Bone_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); subSample[i][19] = std::get>(histos.add(Form("subSample_%d/Prof_Btwo_prot", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + + subSampleV02[i][0] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XY", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSampleV02[i][1] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][2] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][3] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][4] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][5] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][6] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][7] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_XYZ_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSampleV02[i][8] = std::get>(histosAnalysis.add(Form("subSampleV02_%d/Prof_Z_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + } + + if (cfgEvSelMultCorrelation) { + cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; + cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; + cfgFuncParas.multGlobalPVCutPars = cfgFuncParas.cfgMultGlobalPVCutPars; + cfgFuncParas.multMultV0ACutPars = cfgFuncParas.cfgMultMultV0ACutPars; + cfgFuncParas.fMultPVT0CCutLow = new TF1("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutLow->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); + cfgFuncParas.fMultPVT0CCutHigh = new TF1("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutHigh->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); + cfgFuncParas.fMultT0CCutLow = new TF1("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutLow->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); + cfgFuncParas.fMultT0CCutHigh = new TF1("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutHigh->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); + cfgFuncParas.fMultGlobalPVCutLow = new TF1("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutLow->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); + cfgFuncParas.fMultGlobalPVCutHigh = new TF1("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutHigh->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); + cfgFuncParas.fMultMultV0ACutLow = new TF1("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutLow->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); + cfgFuncParas.fMultMultV0ACutHigh = new TF1("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutHigh->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); + cfgFuncParas.fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + cfgFuncParas.fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); + cfgFuncParas.fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); + } + + if (cfgUsePtDepDCAxy) { + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("%s", cfgDCAxyFunc->c_str()), 0.001, 1000); } + if (cfgUsePtDepDCAz) { + fPtDepDCAz = new TF1("ptDepDCAz", Form("%s", cfgDCAzFunc->c_str()), 0.001, 1000); + } + } // end init //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -444,28 +605,139 @@ struct V0ptHadPiKaProt { return pid; // 0 = not identified, 1 = pion, 2 = kaon, 3 = proton } - // process Data - void process(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + // additional multiplicity correlation based event selection cuts + template + bool eventSelectedSmallion(TCollision collision, const int multTrk, const float centrality) { + auto multNTracksPV = collision.multNTracksPV(); + + if (cfgEvSelMultCorrelation) { + if (cfgFuncParas.cfgMultPVT0CCutEnabled) { + if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(centrality)) + return 0; + if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(centrality)) + return 0; + } + + if (cfgFuncParas.cfgMultT0CCutEnabled) { + if (multTrk < cfgFuncParas.fMultT0CCutLow->Eval(centrality)) + return 0; + if (multTrk > cfgFuncParas.fMultT0CCutHigh->Eval(centrality)) + return 0; + } + + if (cfgFuncParas.cfgMultGlobalPVCutEnabled) { + if (multTrk < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) + return 0; + if (multTrk > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) + return 0; + } + + if (cfgFuncParas.cfgMultMultV0ACutEnabled) { + if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(multTrk)) + return 0; + if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(multTrk)) + return 0; + } + } + + float sigma = 5.0; + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + + return 1; + } + + template + bool eventSelectionDefaultCuts(TCollision coll) + { + histos.fill(HIST("hEventStatData"), 0.5); if (!coll.sel8()) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 1.5); if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 2.5); if (cfgEvSelkNoSameBunchPileup && !(coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 3.5); if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 4.5); if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { - return; + return 0; } + + histos.fill(HIST("hEventStatData"), 5.5); if (cfgEvSelUseGoodZvtxFT0vsPV && !(coll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV))) { + return 0; + } + + histos.fill(HIST("hEventStatData"), 6.5); + return 1; + } + + template + void fillMultCorrPlotsBeforeSel(C const& coll, T const& inputTracks) + { + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_PVTracks_beforeSel"), coll.multNTracksPV(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_centFT0C_beforeSel"), coll.centFT0C(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_PVTracks_centFT0C_beforeSel"), coll.centFT0C(), coll.multNTracksPV()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_V0ATracks_beforeSel"), coll.multFV0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_T0ATracks_beforeSel"), coll.multFT0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/BeforeSelection/His2D_V0ATracks_T0CTracks_beforeSel"), coll.multFT0C(), coll.multFV0A()); + } + + template + void fillMultCorrPlotsAfterSel(C const& coll, T const& inputTracks) + { + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_PVTracks_afterSel"), coll.multNTracksPV(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel"), coll.centFT0C(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel"), coll.centFT0C(), coll.multNTracksPV()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel"), coll.multFV0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel"), coll.multFT0A(), inputTracks.size()); + histos.fill(HIST("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel"), coll.multFT0C(), coll.multFV0A()); + } + + template + float getPhiWeight(const T& candidate, float vtxz) + { + if (!cfgLoadPhiWeights || !hWeightPhiFunctionVzEtaPhi) { + return 1.0; + } + int bin = hWeightPhiFunctionVzEtaPhi->FindBin(vtxz, candidate.eta(), candidate.phi()); + float weight = hWeightPhiFunctionVzEtaPhi->GetBinContent(bin); + if (!std::isfinite(weight) || weight <= 0) { + return 1.0; + } + return weight; + } + + // process Data + void process(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) + { + if (!eventSelectionDefaultCuts(coll)) { return; } + fillMultCorrPlotsBeforeSel(coll, inputTracks); + + const auto centralityFT0C = coll.centFT0C(); + if (cfgUseSmallIonAdditionalEventCut && !eventSelectedSmallion(coll, inputTracks.size(), centralityFT0C)) + return; + + if (cfgUseSmallIonAdditionalEventCut) { + fillMultCorrPlotsAfterSel(coll, inputTracks); + } + // Centrality double cent = 0.0; if (cfgCentralityChoice == kFT0C) @@ -482,7 +754,7 @@ struct V0ptHadPiKaProt { histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), inputTracks.size()); histos.fill(HIST("Hist2D_cent_nch"), inputTracks.size(), cent); - // Analysis variables + // Analysis variables for v0(pT) int nbinsHad = 20; int nbinsPid = 18; double binsarray[21] = {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.5, 4.0, 5.0, 6.0, 8.0, 10.0}; @@ -498,6 +770,18 @@ struct V0ptHadPiKaProt { double nSumEtaLeftKa = 0.0; double nSumEtaLeftProt = 0.0; + // Analysis variables for v02(pT) + TH1D* fPtProfileHadInWinB = new TH1D("fPtProfileHadInWinB", "fPtProfileHadInWinB", 20, binsarray); + TH1D* fPtProfilePiInWinB = new TH1D("fPtProfilePiInWinB", "fPtProfilePiInWinB", 20, binsarray); + TH1D* fPtProfileKaInWinB = new TH1D("fPtProfileKaInWinB", "fPtProfileKaInWinB", 20, binsarray); + TH1D* fPtProfileProtInWinB = new TH1D("fPtProfileProtInWinB", "fPtProfileProtInWinB", 20, binsarray); + double nSumInWinB = 0.0; // for Z = f(pT) = n(pT)/N_B in window B + + double nSumInWinA = 0.0; // for X (in window A) to calculate v2^2 + double nSumInWinC = 0.0; // for Y (in window C) to calculate v2^2 + TComplex vecQInWinA = TComplex(0., 0.); + TComplex vecQInWinC = TComplex(0., 0.); + for (const auto& track : inputTracks) { // Loop over tracks if (!track.has_collision()) { @@ -512,6 +796,13 @@ struct V0ptHadPiKaProt { continue; } + if (cfgUsePtDepDCAxy && !(std::abs(track.dcaXY()) < fPtDepDCAxy->Eval(track.pt()))) { + continue; + } + if (cfgUsePtDepDCAz && !(std::abs(track.dcaZ()) < fPtDepDCAz->Eval(track.pt()))) { + continue; + } + histos.fill(HIST("hP"), track.p()); histos.fill(HIST("hPt"), track.pt()); histos.fill(HIST("hEta"), track.eta()); @@ -521,6 +812,7 @@ struct V0ptHadPiKaProt { double trkPt = track.pt(); double trkEta = track.eta(); + double trkPhi = track.phi(); // inclusive charged particles if (track.sign() != 0) { @@ -535,6 +827,33 @@ struct V0ptHadPiKaProt { } } + // fill subevent B for f(pT) in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (std::abs(trkEta) < cfgCutEtaWindowB) { + fPtProfileHadInWinB->Fill(trkPt); + nSumInWinB += 1.0; + } + } + double phiweight = 1.0; + if (cfgLoadPhiWeights) { + phiweight = getPhiWeight(track, coll.posZ()); + } + // fill subevent C for v2^2 in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + histos.fill(HIST("h3DVtxZetaPhi"), coll.posZ(), trkEta, trkPhi); + if (cfgCutEtaWindowB < trkEta && trkEta < 0.8) { + vecQInWinC += phiweight * TComplex(TMath::Cos(2. * trkPhi), TMath::Sin(2. * trkPhi)); + nSumInWinC += phiweight; + } + } + // fill subevent A for v2^2 in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (-0.8 < trkEta && trkEta < -1.0 * cfgCutEtaWindowB) { + vecQInWinA += phiweight * TComplex(TMath::Cos(2. * trkPhi), TMath::Sin(2. * trkPhi)); + nSumInWinA += phiweight; + } + } + // PID QAs before selection double nSigmaTpcPi = track.tpcNSigmaPi(); double nSigmaTpcKa = track.tpcNSigmaKa(); @@ -607,6 +926,21 @@ struct V0ptHadPiKaProt { } } + // fill subevent B for ***identified particles'*** f(pT) in v02(pT) + if (track.sign() != 0 && trkPt < cfgCutPtMaxForV02) { + if (std::abs(trkEta) < cfgCutEtaWindowB) { + if (isPion) { + fPtProfilePiInWinB->Fill(trkPt); + } + if (isKaon) { + fPtProfileKaInWinB->Fill(trkPt); + } + if (isProton && trkPt > cfgCutPtLowerProt) { + fPtProfileProtInWinB->Fill(trkPt); + } + } + } + } // End track loop // selecting subsample and filling profiles @@ -676,11 +1010,68 @@ struct V0ptHadPiKaProt { } } + if (nSumInWinA > 4 && nSumInWinB > 4 && nSumInWinC > 4) { + double twoParCorr = (vecQInWinA * TComplex::Conjugate(vecQInWinC)).Re(); + twoParCorr *= 1.0 / (nSumInWinA * nSumInWinC); + histos.get(HIST("Prof_XY"))->Fill(cent, 0.5, twoParCorr); + + subSampleV02[sampleIndex][0]->Fill(cent, 0.5, twoParCorr); + + // hadrons + for (int i = 0; i < cfgNbinsV02pt; i++) { + double threeParCorrHad = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileHadInWinB->GetBinContent(i + 1)).Re(); + threeParCorrHad *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad); + histos.get(HIST("Prof_Z_had"))->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][1]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), threeParCorrHad); + subSampleV02[sampleIndex][2]->Fill(cent, fPtProfileHadInWinB->GetBinCenter(i + 1), (fPtProfileHadInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + + // pions + for (int i = 0; i < cfgNbinsV02pt; i++) { + double threeParCorrPi = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfilePiInWinB->GetBinContent(i + 1)).Re(); + threeParCorrPi *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); + histos.get(HIST("Prof_Z_pi"))->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][3]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), threeParCorrPi); + subSampleV02[sampleIndex][4]->Fill(cent, fPtProfilePiInWinB->GetBinCenter(i + 1), (fPtProfilePiInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + + // kaons + for (int i = 0; i < cfgNbinsV02pt; i++) { + double threeParCorrKa = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileKaInWinB->GetBinContent(i + 1)).Re(); + threeParCorrKa *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); + histos.get(HIST("Prof_Z_ka"))->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][5]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), threeParCorrKa); + subSampleV02[sampleIndex][6]->Fill(cent, fPtProfileKaInWinB->GetBinCenter(i + 1), (fPtProfileKaInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + + // protons + for (int i = 1; i < cfgNbinsV02pt; i++) { + double threeParCorrProt = (vecQInWinA * TComplex::Conjugate(vecQInWinC) * fPtProfileProtInWinB->GetBinContent(i + 1)).Re(); + threeParCorrProt *= 1.0 / (nSumInWinA * nSumInWinC * nSumInWinB); + histos.get(HIST("Prof_XYZ_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); + histos.get(HIST("Prof_Z_prot"))->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); + + subSampleV02[sampleIndex][7]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), threeParCorrProt); + subSampleV02[sampleIndex][8]->Fill(cent, fPtProfileProtInWinB->GetBinCenter(i + 1), (fPtProfileProtInWinB->GetBinContent(i + 1) / nSumInWinB)); + } + } + fPtProfileHad->Delete(); fPtProfilePi->Delete(); fPtProfileKa->Delete(); fPtProfileProt->Delete(); + fPtProfileHadInWinB->Delete(); + fPtProfilePiInWinB->Delete(); + fPtProfileKaInWinB->Delete(); + fPtProfileProtInWinB->Delete(); + } // End process loop }; diff --git a/PWGCF/Femto/Core/baseSelection.h b/PWGCF/Femto/Core/baseSelection.h index ceb2184a96a..5bc9a598c1f 100644 --- a/PWGCF/Femto/Core/baseSelection.h +++ b/PWGCF/Femto/Core/baseSelection.h @@ -18,9 +18,11 @@ #include "PWGCF/Femto/Core/selectionContainer.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include -#include "fairlogger/Logger.h" +#include #include #include @@ -40,9 +42,9 @@ namespace o2::analysis::femto /// It evaluates which selections are fulfilled, assembles a final bitmask, and tracks required vs. optional cuts. /// /// \tparam T Type of observable values (mostly floats). -/// \tparam BitmaskType Type used for internal bitmask operations (e.g., uint32_t, uint64_t). +/// \tparam BitmaskType Integer type used for bitmask operations (e.g., uint32_t, uint64_t). /// \tparam NumObservables Total number of observables handled. -template +template class BaseSelection { public: @@ -53,57 +55,41 @@ class BaseSelection virtual ~BaseSelection() = default; /// \brief Add a static-value based selection for a specific observable. - /// \param selectionValues Vector of threshold values. /// \param observableIndex Index of the observable. + /// \param selectionName Name of the selection. + /// \param selectionValues Vector of threshold values. /// \param limitType Type of limit (from limits::LimitType). - /// \param skipMostPermissiveBit Whether to skip the loosest threshold in the bitmask. - /// \param isMinimalCut Whether this cut is mandatory or optional. + /// \param skipMostPermissiveBit Whether to skip the loosest threshold when assembling the bitmask. + /// \param isMinimalCut Whether this cut is mandatory (must be passed for the candidate to be accepted). + /// \param isOptionalCut Whether this cut is optional (candidate is accepted if any optional cut passes). void addSelection(int observableIndex, std::string const& selectionName, std::vector const& selectionValues, limits::LimitType limitType, bool skipMostPermissiveBit, bool isMinimalCut, - bool isOptionCut) + bool isOptionalCut) { // check index - if (static_cast(observableIndex) >= NumObservables) { + if (static_cast(observableIndex) >= NumObservables) { LOG(fatal) << "Observable is not valid. Observable (index) has to be smaller than " << NumObservables; } // init selection container for selection at given index - mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, selectionValues, limitType, skipMostPermissiveBit, isMinimalCut, isOptionCut); - - // check if any selections are configured - if (mSelectionContainers.at(observableIndex).isEmpty()) { - return; - } - - // keep track of selections and bits - mNSelectionBits += mSelectionContainers.at(observableIndex).getShift(); - mNSelection += mSelectionContainers.at(observableIndex).getNSelections(); + mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, selectionValues, limitType, skipMostPermissiveBit, isMinimalCut, isOptionalCut); - if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { - LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " number of bits are supported"; - } - // check if any selection is minimal - if (mSelectionContainers.at(observableIndex).isMinimalCut()) { - mHasMinimalSelection = true; - } - // check if selection is optional - if (mSelectionContainers.at(observableIndex).isOptionalCut()) { - mHasOptionalSelection = true; - } + init(observableIndex); } /// \brief Add a function-based selection for a specific observable. - /// \param baseName Base name for TF1 functions. - /// \param lowerLimit Lower bound for the TF1 domain. - /// \param upperLimit Upper bound for the TF1 domain. - /// \param selectionValues Function definitions as strings. /// \param observableIndex Index of the observable. - /// \param limitType Type of limit. - /// \param skipMostPermissiveBit Whether to skip the loosest threshold in the bitmask. - /// \param isMinimalCut Whether this cut is mandatory or optional. + /// \param selectionName Name of the selection. + /// \param lowerLimit Lower bound of the TF1 domain. + /// \param upperLimit Upper bound of the TF1 domain. + /// \param functions Selection threshold functions as strings (parsed as TF1 expressions). + /// \param limitType Type of limit (from limits::LimitType). + /// \param skipMostPermissiveBit Whether to skip the loosest threshold when assembling the bitmask. + /// \param isMinimalCut Whether this cut is mandatory (must be passed for the candidate to be accepted). + /// \param isOptionalCut Whether this cut is optional (candidate is accepted if any optional cut passes). void addSelection(int observableIndex, std::string const& selectionName, T lowerLimit, @@ -114,73 +100,75 @@ class BaseSelection bool isMinimalCut, bool isOptionalCut) { - if (static_cast(observableIndex) >= NumObservables) { + if (static_cast(observableIndex) >= NumObservables) { LOG(fatal) << "Observable is not valid. Observable (index) has to be smaller than " << NumObservables; } mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, lowerLimit, upperLimit, functions, limitType, skipMostPermissiveBit, isMinimalCut, isOptionalCut); - // check if any selections are configured - if (mSelectionContainers.at(observableIndex).isEmpty()) { - return; - } - - // advance mNSelections so we can use it as offset for next selection - mNSelectionBits += mSelectionContainers.at(observableIndex).getShift(); - mNSelection += mSelectionContainers.at(observableIndex).getNSelections(); + init(observableIndex); + } - if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { - LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " are supported"; - } - // keep track of selection selections - // check if any cut is minimal - if (mSelectionContainers.at(observableIndex).isMinimalCut()) { - mHasMinimalSelection = true; - } - // check if any selection is optional - if (mSelectionContainers.at(observableIndex).isOptionalCut()) { - mHasOptionalSelection = true; + /// \brief Add a static-value based selection for a specific observable. + /// \param observableIndex Index of the observable. + /// \param selectionName Name of the selection. + /// \param selectionValues Vector of threshold values. + /// \param limitType Type of limit (from limits::LimitType). + /// \param skipMostPermissiveBit Whether to skip the loosest threshold when assembling the bitmask. + /// \param isMinimalCut Whether this cut is mandatory (must be passed for the candidate to be accepted). + /// \param isOptionalCut Whether this cut is optional (candidate is accepted if any optional cut passes). + void addSelection(int observableIndex, + std::string const& selectionName, + std::vector const& selectionRanges, + bool skipMostPermissiveBit, + bool isMinimalCut, + bool isOptionalCut) + { + // check index + if (static_cast(observableIndex) >= NumObservables) { + LOG(fatal) << "Observable is not valid. Observable (index) has to be smaller than " << NumObservables; } + // init selection container for selection at given index + mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, selectionRanges, skipMostPermissiveBit, isMinimalCut, isOptionalCut); + + init(observableIndex); } - /// \brief Add a boolean based selection for a specific observable. - /// \param mode Whether the selection is not applied, minimal or optional cut + /// \brief Add a boolean-based selection for a specific observable. /// \param observableIndex Index of the observable. + /// \param selectionName Name of the selection. + /// \param mode Controls how the cut is applied: + /// -1 = optional cut, bit is stored in bitmask; + /// 0 = cut is disabled, no bit stored; + /// 1 = minimal (mandatory) cut, no extra bit stored since only one threshold exists. void addSelection(int observableIndex, std::string const& selectionName, int mode) { switch (mode) { - case -1: // cut is optional and we store bit for the cut + case -1: // cut is optional and we store a bit for it mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, std::vector{1}, limits::LimitType::kEqual, false, false, true); - mHasOptionalSelection = true; - mNSelectionBits += 1; - mNSelection += 1; break; - case 0: // cut is not applied, initalize with empty vector, so we bail out later + case 0: // cut is disabled; initialize with empty vector so evaluation bails out early mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, std::vector{}, limits::LimitType::kEqual, false, false, false); break; - case 1: // cut is added as mininal selection (since it is only one value, no extra bit is stored) + case 1: // mandatory cut; only one threshold so the most permissive bit is skipped and no extra bit is stored mSelectionContainers.at(observableIndex) = SelectionContainer(selectionName, std::vector{1}, limits::LimitType::kEqual, true, true, false); - mHasMinimalSelection = true; - mNSelection += 1; break; default: LOG(fatal) << "Invalid switch for boolean selection"; } - if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { - LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " are supported"; - } + init(observableIndex); } /// \brief Update the limits of a function-based selection for a specific observable. /// \param observable Index of the observable. - /// \param value Value at which to evaluate the selection functions. + /// \param value Value at which to re-evaluate the selection functions. void updateLimits(int observable, T value) { mSelectionContainers.at(observable).updateLimits(value); } - /// \brief Reset the internal bitmask and evaluation flags before evaluating a new event. + /// \brief Reset the internal bitmask and evaluation flags before processing a new candidate. void reset() { mFinalBitmask.reset(); @@ -195,6 +183,8 @@ class BaseSelection } } + /// \brief Reset the selection container for a single observable. + /// \param observableIndex Index of the observable to reset. void reset(int observableIndex) { mSelectionContainers.at(observableIndex).reset(); } /// \brief Evaluate a single observable against its configured selections. @@ -206,22 +196,20 @@ class BaseSelection if (mSelectionContainers.at(observableIndex).isEmpty()) { return; } - // if any previous observable did not pass minimal selections, there is no point in setting bitmask for other observables - // minimal selection for each observable is computed after adding it + // if a previous observable already failed a minimal selection, + // there is no point in evaluating further observables if (!mPassesMinimalSelections) { return; } // set bitmask for given observable mSelectionContainers.at(observableIndex).evaluate(value); - // check if minimal selction for this observable holds - // if one minimal selection is not fullfilled, the condition failes + // if any minimal selection is not fulfilled, the candidate is rejected if (mHasMinimalSelection) { if (!mSelectionContainers.at(observableIndex).passesAsMinimalCut()) { mPassesMinimalSelections = false; } } - // check if any optional selection holds - // if one optional selection is fullfilled, the condition succeeds + // if any optional selection is fulfilled, the candidate is accepted if (mHasOptionalSelection) { if (mSelectionContainers.at(observableIndex).passesAsOptionalCut()) { mPassesOptionalSelections = true; @@ -231,39 +219,41 @@ class BaseSelection /// \brief Evaluate a single observable against its configured selections. /// \param observableIndex Index of the observable. - /// \param values vector of values of the observable. + /// \param values Vector of values of the observable. void evaluateObservable(int observableIndex, std::vector values) { // if there are no selections configured, bail out if (mSelectionContainers.at(observableIndex).isEmpty()) { return; } - // if any previous observable did not pass minimal selections, there is no point in setting bitmask for other observables - // minimal selection for each observable is computed after adding it + // if a previous observable already failed a minimal selection, + // there is no point in evaluating further observables if (!mPassesMinimalSelections) { return; } // set bitmask for given observable mSelectionContainers.at(observableIndex).evaluate(values); - // check if minimal selction for this observable holds + // if any minimal selection is not fulfilled, the candidate is rejected if (mHasMinimalSelection) { - if (mSelectionContainers.at(observableIndex).passesAsMinimalCut() == false) { + if (!mSelectionContainers.at(observableIndex).passesAsMinimalCut()) { mPassesMinimalSelections = false; } } - // check if any optional selection holds + // if any optional selection is fulfilled, the candidate is accepted if (mHasOptionalSelection) { - if (mSelectionContainers.at(observableIndex).passesAsOptionalCut() == true) { + if (mSelectionContainers.at(observableIndex).passesAsOptionalCut()) { mPassesOptionalSelections = true; } } } - /// \brief Add comments to specific observabel + /// \brief Add comments to the selections of a specific observable. + /// \param observableIndex Index of the observable. + /// \param comments Vector of comment strings, one per selection threshold. void addComments(int observableIndex, std::vector const& comments) { mSelectionContainers.at(observableIndex).addComments(comments); } - /// \brief Check if all required (minimal) and optional cuts are passed. - /// \return True if all required and at least one optional cut (if present) is passed. + /// \brief Check whether all required and optional cuts are passed. + /// \return True if all minimal cuts pass and, if optional cuts are present, at least one of them passes. bool passesAllRequiredSelections() const { if (mHasMinimalSelection && !mHasOptionalSelection) { @@ -275,23 +265,25 @@ class BaseSelection if (mHasMinimalSelection && mHasOptionalSelection) { return mPassesMinimalSelections && mPassesOptionalSelections; } + // if there are no minimal or optional selections, we pass let it pass with true return true; } - /// \brief Check if the optional selection for a specific observable is passed. + /// \brief Check whether the optional selection for a specific observable is passed. /// \param observableIndex Index of the observable. - /// \return True if at least one optional selection is fulfilled. + /// \return True if at least one optional selection for this observable is fulfilled. bool passesOptionalSelection(int observableIndex) const { return mSelectionContainers.at(observableIndex).passesAsOptionalCut(); } - /// \brief Assemble the global selection bitmask from individual observable selections. + /// \brief Assemble the global selection bitmask from all individual observable selections. + /// \tparam HistName Name of the histogram used to track selection statistics. template void assembleBitmask() { mHistRegistry->fill(HIST(HistName), mNSelection); - // if the required selections are not passed, we can break early + // if the required selections are not passed, clear the bitmask and return early if (!this->passesAllRequiredSelections()) { mFinalBitmask.reset(); return; @@ -299,17 +291,16 @@ class BaseSelection mHistRegistry->fill(HIST(HistName), mNSelection + 1); int binCenter = 0; - // to assemble bitmask, convert all bitmask into integers - // shift the current one and add the new bits + // assemble the final bitmask by shifting each container's bitmask to its offset and OR-ing it in for (auto const& selectionContainer : mSelectionContainers) { - // if there are no selections for a certain observable, skip + // skip observables with no configured selections if (selectionContainer.isEmpty()) { continue; } - // Shift the result to its offset and add the new values + // shift the container's bitmask to its offset and merge mFinalBitmask |= (selectionContainer.getBitmask() << selectionContainer.getOffset()); - for (int j = 0; j < selectionContainer.getNSelections(); ++j) { + for (std::size_t j = 0; j < selectionContainer.getNSelections(); ++j) { if (j == 0 && selectionContainer.isMinimalCut()) { // minimal cuts are always filled mHistRegistry->fill(HIST(HistName), binCenter); @@ -325,28 +316,36 @@ class BaseSelection } /// \brief Retrieve the assembled bitmask as an integer value. - /// \return The combined selection bitmask. + /// \return The combined selection bitmask for all observables. BitmaskType getBitmask() const { return static_cast(mFinalBitmask.to_ullong()); } - /// \brief Retrieve the assembled bitmask as an integer value. - /// \return The combined selection bitmask. + /// \brief Retrieve the bitmask for a single observable as an integer value. + /// \param observableIndex Index of the observable. + /// \return The selection bitmask for the specified observable. BitmaskType getBitmask(int observableIndex) const { return static_cast(mSelectionContainers.at(observableIndex).getBitmask().to_ullong()); } - /// \brief Set the assembled bitmask for on observable - /// \return The combined selection bitmask. + /// \brief Manually set the bitmask for a specific observable. + /// \tparam R Integer type of the bitmask value. + /// \param observableIndex Index of the observable. + /// \param bitmask Bitmask value to set. template void setBitmask(int observableIndex, R bitmask) { mSelectionContainers.at(observableIndex).setBitmask(bitmask); } + /// \brief Retrieve the loosest (most permissive) selection threshold for a specific observable. + /// \param observableIndex Index of the observable. + /// \return The loosest threshold value configured for this observable. T getLoosestSelection(int observableIndex) const { return mSelectionContainers.at(observableIndex).getLoosestSelection(); } + /// \brief Print the full configuration of all selections to the log. + /// \param objectName Name of the object owning this selection (used as label in the log output). void printSelections(const std::string& objectName) const { LOG(info) << "Printing Configuration of " << objectName; for (size_t idx = 0; idx < mSelectionContainers.size(); ++idx) { - const auto& container = mSelectionContainers[idx]; + const auto& container = mSelectionContainers.at(idx); if (container.isEmpty()) { continue; } @@ -360,15 +359,11 @@ class BaseSelection LOG(info) << " Bitmask shift : " << container.getShift(); LOG(info) << " Selections:"; - const bool useFunctions = container.isUsingFunctions(); - const auto& values = container.getSelectionValues(); - const auto& functions = container.getSelectionFunction(); - const auto& comments = container.getComments(); - - for (int j = 0; j < container.getNSelections(); ++j) { + for (std::size_t j = 0; j < container.getNSelections(); ++j) { std::stringstream line; - std::string sel = useFunctions ? std::string(functions[j].GetExpFormula().Data()) : std::to_string(values[j]); + std::string sel = container.getValueAsString(j); + std::string comment = container.getComment(j); line << " " << std::left << std::setw(25) << sel; @@ -379,8 +374,8 @@ class BaseSelection line << "-> Bit: 0x" << std::hex << std::uppercase << (1ULL << bit) << std::dec; } - if (!comments.empty()) { - line << " (" << comments.at(j) << ")"; + if (!comment.empty()) { + line << " (" << comment << ")"; } LOG(info) << line.str(); } @@ -390,24 +385,27 @@ class BaseSelection LOG(info) << "Printing done"; } + /// \brief Initialize histograms and set bitmask offsets for all configured observables. + /// \tparam HistName Name of the histogram to create in the registry. + /// \param registry Pointer to the histogram registry. template void setupContainers(o2::framework::HistogramRegistry* registry) { mHistRegistry = registry; - // Create histogram with correct number of bins + // create histogram with one bin per selection, plus two summary bins (all analyzed, all passed) int nBins = mNSelection + 2; mHistRegistry->add(HistName, "; Selection Bits; Entries", o2::framework::kTH1F, {{nBins, -0.5, nBins - 0.5}}); - size_t binIndex = 0; + int binIndex = 0; int offset = 0; - for (size_t idx = 0; idx < mSelectionContainers.size(); ++idx) { + for (std::size_t idx = 0; idx < mSelectionContainers.size(); ++idx) { auto& container = mSelectionContainers[idx]; if (container.isEmpty()) { continue; } container.setOffset(offset); offset += container.getShift(); - for (int j = 0; j < container.getNSelections(); j++) { + for (std::size_t j = 0; j < container.getNSelections(); j++) { std::string label = container.getBinLabel(j); mHistRegistry->get(HIST(HistName))->GetXaxis()->SetBinLabel(binIndex + 1, label.c_str()); binIndex++; @@ -418,15 +416,40 @@ class BaseSelection } protected: + void init(int observableIndex) + { + // check if any selections are configured + if (mSelectionContainers.at(observableIndex).isEmpty()) { + return; + } + + // track the number of occupied bits and total selections + mNSelectionBits += mSelectionContainers.at(observableIndex).getShift(); + mNSelection += mSelectionContainers.at(observableIndex).getNSelections(); + + // check if any selection is minimal + if (mSelectionContainers.at(observableIndex).isMinimalCut()) { + mHasMinimalSelection = true; + } + // check if selection is optional + if (mSelectionContainers.at(observableIndex).isOptionalCut()) { + mHasOptionalSelection = true; + } + + if (mNSelectionBits > sizeof(BitmaskType) * CHAR_BIT) { + LOG(fatal) << "Too many selections. At most " << sizeof(BitmaskType) * CHAR_BIT << " number of bits are supported"; + } + } + o2::framework::HistogramRegistry* mHistRegistry = nullptr; - std::array, NumObservables> mSelectionContainers = {}; ///< Array containing all selections - std::bitset mFinalBitmask = {}; ///< final bitmaks - std::size_t mNSelectionBits = 0; ///< Number of selections (all - minimal selections) - int mNSelection = 0; ///< Number of selections all selections - bool mHasMinimalSelection = false; ///< Set to true if all minimal (mandatory) selections are passed - bool mPassesMinimalSelections = true; ///< Set to true if all minimal (mandatory) selections are passed - bool mHasOptionalSelection = false; ///< Set to true if at least one selections is optional - bool mPassesOptionalSelections = false; ///< Set to true if at least one optional (non-mandatory) selections is passed + std::array, NumObservables> mSelectionContainers = {}; ///< Array of selection containers, one per observable + std::bitset mFinalBitmask = {}; ///< Assembled bitmask combining all observable selections + std::size_t mNSelectionBits = 0; ///< Number of bits occupied in the bitmask (excludes skipped most-permissive bits) + std::size_t mNSelection = 0; ///< Total number of configured selection thresholds across all observables + bool mHasMinimalSelection = false; ///< True if at least one observable has a mandatory (minimal) cut configured + bool mPassesMinimalSelections = true; ///< True if all mandatory (minimal) cuts have been passed so far + bool mHasOptionalSelection = false; ///< True if at least one observable has an optional cut configured + bool mPassesOptionalSelections = false; ///< True if at least one optional cut has been passed }; } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/cascadeBuilder.h b/PWGCF/Femto/Core/cascadeBuilder.h index dd022f91501..2de7099ee6f 100644 --- a/PWGCF/Femto/Core/cascadeBuilder.h +++ b/PWGCF/Femto/Core/cascadeBuilder.h @@ -23,11 +23,11 @@ #include "PWGCF/Femto/Core/selectionContainer.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" - -#include "fairlogger/Logger.h" +#include +#include +#include +#include +#include #include #include @@ -398,20 +398,66 @@ class CascadeBuilder continue; } + collisionBuilder.template fillCollision(collisionProducts, col); + // cleaner, but without ITS pid: auto bachelor = cascade.template bachelor_as(); auto bachelor = tracksWithItsPid.iteratorAt(cascade.bachelorId() - tracksWithItsPid.offset()); + bachelorIndex = trackBuilder.template getDaughterIndex(bachelor, trackProducts, collisionProducts); + // cleaner, but without ITS pid: auto posDaughter = cascade.template posTrack_as(); auto posDaughter = tracksWithItsPid.iteratorAt(cascade.posTrackId() - tracksWithItsPid.offset()); + posDaughterIndex = trackBuilder.template getDaughterIndex(posDaughter, trackProducts, collisionProducts); + // cleaner, but without ITS pid: auto negDaughter = cascade.template negTrack_as(); auto negDaughter = tracksWithItsPid.iteratorAt(cascade.negTrackId() - tracksWithItsPid.offset()); + negDaughterIndex = trackBuilder.template getDaughterIndex(negDaughter, trackProducts, collisionProducts); - collisionBuilder.template fillCollision(collisionProducts, col); + fillCascade(collisionProducts, cascadeProducts, cascade, col, bachelorIndex, posDaughterIndex, negDaughterIndex); + } + } - bachelorIndex = trackBuilder.template getDaughterIndex(bachelor, trackProducts, collisionProducts); - posDaughterIndex = trackBuilder.template getDaughterIndex(posDaughter, trackProducts, collisionProducts); - negDaughterIndex = trackBuilder.template getDaughterIndex(negDaughter, trackProducts, collisionProducts); + template + void fillMcCascades(T1 const& col, T2& collisionBuilder, T3& collisionProducts, T4 const& mcCols, T5& trackProducts, T6& cascadeProducts, T7 const& cascades, T8 const& tracks, T9 const& tracksWithItsPid, T10& trackBuilder, T11 const& mcParticles, T12& mcBuilder, T13& mcProducts) + { + if (!mFillAnyTable) { + return; + } + + int64_t bachelorIndex = 0; + int64_t posDaughterIndex = 0; + int64_t negDaughterIndex = 0; + for (const auto& cascade : cascades) { + if (!mCascadeSelection.checkFilters(cascade)) { + continue; + } + mCascadeSelection.applySelections(cascade, tracks, col); + if (!mCascadeSelection.passesAllRequiredSelections()) { + continue; + } + + collisionBuilder.template fillMcCollision(collisionProducts, col, mcCols, mcProducts, mcBuilder); + + auto bachelor = tracks.iteratorAt(cascade.bachelorId() - tracks.offset()); + auto bachelorWithItsPid = tracksWithItsPid.iteratorAt(cascade.bachelorId() - tracksWithItsPid.offset()); + bachelorIndex = trackBuilder.template getDaughterIndex(col, collisionProducts, mcCols, bachelor, bachelorWithItsPid, trackProducts, mcParticles, mcBuilder, mcProducts); + + auto posDaughter = tracks.iteratorAt(cascade.posTrackId() - tracks.offset()); + auto posDaughterWithItsPid = tracksWithItsPid.iteratorAt(cascade.posTrackId() - tracksWithItsPid.offset()); + posDaughterIndex = trackBuilder.template getDaughterIndex(col, collisionProducts, mcCols, posDaughter, posDaughterWithItsPid, trackProducts, mcParticles, mcBuilder, mcProducts); + + auto negDaughter = tracks.iteratorAt(cascade.negTrackId() - tracks.offset()); + auto negDaughterWithItsPid = tracksWithItsPid.iteratorAt(cascade.negTrackId() - tracksWithItsPid.offset()); + negDaughterIndex = trackBuilder.template getDaughterIndex(col, collisionProducts, mcCols, negDaughter, negDaughterWithItsPid, trackProducts, mcParticles, mcBuilder, mcProducts); fillCascade(collisionProducts, cascadeProducts, cascade, col, bachelorIndex, posDaughterIndex, negDaughterIndex); + if constexpr (modes::isEqual(cascadeType, modes::Cascade::kXi)) { + mcBuilder.template fillMcXiWithLabel(col, mcCols, cascade, mcParticles, mcProducts); + ; + } + if constexpr (modes::isEqual(cascadeType, modes::Cascade::kOmega)) { + mcBuilder.template fillMcOmegaWithLabel(col, mcCols, cascade, mcParticles, mcProducts); + ; + } } } diff --git a/PWGCF/Femto/Core/cascadeHistManager.h b/PWGCF/Femto/Core/cascadeHistManager.h index e4bd045f7d5..d1218ec4e8e 100644 --- a/PWGCF/Femto/Core/cascadeHistManager.h +++ b/PWGCF/Femto/Core/cascadeHistManager.h @@ -20,12 +20,17 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/trackHistManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include +#include +#include + +#include +#include #include +#include #include #include #include @@ -49,6 +54,10 @@ enum CascadeHist { kCosPa, kDecayDauDca, kTransRadius, + kLambdaCosPa, + kLambdaDauDca, + kLambdaTransRadius, + kLambdaDcaToPv, // 2d qa kPtVsEta, kPtVsPhi, @@ -57,9 +66,29 @@ enum CascadeHist { kPtVsMassXi, kPtVsMassOmega, kMassXiVsMassOmega, + // mc + kOrigin, + kPdg, + kPdgMother, + kPdgPartonicMother, + kTruePtVsPt, + kTrueEtaVsEta, + kTruePhiVsPhi, + // histograms for fraction estimation of v0s + kNoMcParticle, + kPrimary, + kFromWrongCollision, + kFromMaterial, + kMissidentified, + kSecondary1, + kSecondary2, + kSecondary3, + kSecondaryOther, kCascadeHistLast }; +constexpr std::size_t MaxSecondary = 3; + template struct ConfCascadeBinning : o2::framework::ConfigurableGroup { std::string prefix = Prefix; @@ -68,6 +97,7 @@ struct ConfCascadeBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis phi{"phi", {{720, 0, 1.f * o2::constants::math::TwoPI}}, "Phi"}; o2::framework::ConfigurableAxis mass{"mass", {{1000, 1.f, 2.f}}, "Mass"}; o2::framework::ConfigurableAxis sign{"sign", {{3, -1.5, 1.5}}, "Sign"}; + o2::framework::ConfigurableAxis pdgCodes{"pdgCodes", {{8001, -4000.5, 4000.5}}, "MC ONLY: PDG codes of reconstructed cascades"}; }; constexpr const char PrefixXiBinning[] = "XiBinning"; @@ -84,6 +114,10 @@ struct ConfCascadeQaBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis transRadius{"transRadius", {{100, 0, 100}}, "Transverse radius"}; o2::framework::ConfigurableAxis massXi{"massXi", {{400, 1.2f, 1.6f}}, "mass for antiparticle hypothesis"}; o2::framework::ConfigurableAxis massOmega{"massOmega", {{400, 1.4f, 1.8f}}, "mass for antiparticle hypothesis"}; + o2::framework::ConfigurableAxis lambdaCosPa{"lambdaCosPa", {{100, 0.9, 1}}, "Cosine of poiting angle of daughter lambda"}; + o2::framework::ConfigurableAxis lambdaDauDca{"lambdaDauDca", {{150, 0, 1.0}}, "DCA of lambda daughters at lambda decay vertex"}; + o2::framework::ConfigurableAxis lambdaTransRadius{"lambdaTransRadius", {{100, 0, 100}}, "DCA of lambda daughters at lambda decay vertex"}; + o2::framework::ConfigurableAxis lambdaDcaToPv{"lambdaDcaToPv", {{100, 0, 200}}, "DCA of lambda daughter from primary vertex"}; }; constexpr const char PrefixXiQaBinning[] = "XiQaBinning"; @@ -102,50 +136,124 @@ constexpr std::array, kCascadeHistLast> HistT {kSign, o2::framework::kTH1F, "hSign", "Sign (-1 -> antiparticle, 0 -> self conjugate, +1 -> particle); sign; Entries"}, {kMassXi, o2::framework::kTH1F, "hMassXi", "Mass #Xi; m_{#Lambda#pi} (GeV/#it{c}^{2}); Entries"}, {kMassOmega, o2::framework::kTH1F, "hMassOmega", "mass #Omega; m_{#LambdaK} (GeV/#it{c}^{2}); Entries"}, - {kCosPa, o2::framework::kTH1F, "hCosPa", "Cosine of pointing angle; coa(#alpha); Entries"}, + {kCosPa, o2::framework::kTH1F, "hCosPa", "Cosine of pointing angle; cos(#alpha); Entries"}, {kDecayDauDca, o2::framework::kTH1F, "hDauDca", "Daughter DCA at decay vertex ; DCA_{Decay vertex} (cm); Entries"}, {kTransRadius, o2::framework::kTH1F, "hTransRadius", "Transverse radius ; r_{xy} (cm); Entries"}, + {kLambdaCosPa, o2::framework::kTH1F, "hLambdaCosPa", "Cosine of poiting angle of daughter lambda ; cos_{#Lambda}(#alpha); Entries"}, + {kLambdaDauDca, o2::framework::kTH1F, "hLambdaDauDca", "Daughter DCA at #Lambda decay vertex ; DCA_{#Lambda decay vertex} (cm); Entries"}, + {kLambdaTransRadius, o2::framework::kTH1F, "hLambdaTransRadius", "Transverse radius of daughter #Lambda ; r_{xy} (cm); Entries"}, + {kLambdaDcaToPv, o2::framework::kTH1F, "hLambdaDcaToPv", "DCA to primary vertex of daughter #Lambda ; DCA (cm); Entries"}, {kPtVsEta, o2::framework::kTH2F, "hPtVsEta", "p_{T} vs #eta; p_{T} (GeV/#it{c}) ; #eta"}, {kPtVsPhi, o2::framework::kTH2F, "hPtVsPhi", "p_{T} vs #varphi; p_{T} (GeV/#it{c}) ; #varphi"}, {kPhiVsEta, o2::framework::kTH2F, "hPhiVsEta", "#varphi vs #eta; #varphi ; #eta"}, {kPtVsCosPa, o2::framework::kTH2F, "hPtVsCosPa", "Cosine of poiting angle vs p_{T}; cos(#alpha); p_{T} (GeV/#it{c})"}, {kPtVsMassXi, o2::framework::kTH2F, "hPtVsMassXi", "p_{T} vs mass #Xi; p_{T} (GeV/#it{c}); m_{#Lambda#pi} (GeV/#it{c}^{2})"}, {kPtVsMassOmega, o2::framework::kTH2F, "hPtVsMassOmega", "p_{T} vs mass #Omega; p_{T} (GeV/#it{c}); m_{#LambdaK} (GeV/#it{c}^{2})"}, - {kMassXiVsMassOmega, o2::framework::kTH2F, "hMassXiVsMassOmega", "mass #Xi vs mass #Omega; m_{#Lambda#pi} (GeV/#it{c}^{2}); m_{#LambdaK} (GeV/#it{c}^{2})"}}}; + {kMassXiVsMassOmega, o2::framework::kTH2F, "hMassXiVsMassOmega", "mass #Xi vs mass #Omega; m_{#Lambda#pi} (GeV/#it{c}^{2}); m_{#LambdaK} (GeV/#it{c}^{2})"}, + {kOrigin, o2::framework::kTH1F, "hOrigin", "Status Codes (=Origin); Status Code; Entries"}, + {kPdg, o2::framework::kTH1F, "hPdg", "PDG Codes of reconstructed v0; PDG Code; Entries"}, + {kPdgMother, o2::framework::kTH1F, "hPdgMother", "PDG Codes of mother of reconstructed v0; PDG Code; Entries"}, + {kPdgPartonicMother, o2::framework::kTH1F, "hPdgPartonicMother", "PDG Codes of partonic mother of reconstructed v0; PDG Code; Entries"}, + {kTruePtVsPt, o2::framework::kTH2F, "hTruePtVsPt", "True transverse momentum vs transverse momentum; p_{T,True} (GeV/#it{c}); p_{T,True} (GeV/#it{c})"}, + {kTrueEtaVsEta, o2::framework::kTH2F, "hTrueEtaVsEta", "True pseudorapdity vs pseudorapdity; #eta_{True}; #eta"}, + {kTruePhiVsPhi, o2::framework::kTH2F, "hTruePhiVsPhi", "True azimuthal angle vs azimuthal angle; #varphi_{True}; #varphi"}, + {kNoMcParticle, o2::framework::kTH2F, "hNoMcParticle", "Wrongly reconstructed particles; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kPrimary, o2::framework::kTH2F, "hPrimary", "Primary particles; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kFromWrongCollision, o2::framework::kTH2F, "hFromWrongCollision", "Particles associated to wrong collision; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kFromMaterial, o2::framework::kTH2F, "hFromMaterial", "Particles from material; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kMissidentified, o2::framework::kTH2F, "hMissidentified", "Missidentified particles (fake/wrong PDG code); p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondary1, o2::framework::kTH2F, "hFromSecondary1", "Particles from secondary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondary2, o2::framework::kTH2F, "hFromSecondary2", "Particles from seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondary3, o2::framework::kTH2F, "hFromSecondary3", "Particles from seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}, + {kSecondaryOther, o2::framework::kTH2F, "hFromSecondaryOther", "Particles from every other seconary decay; p_{T} (GeV/#it{c}); cos(#alpha)"}}, +}; + +#define CASCADE_HIST_ANALYSIS_MAP(conf) \ + {kPt, {conf.pt}}, \ + {kEta, {conf.eta}}, \ + {kPhi, {conf.phi}}, \ + {kMass, {conf.mass}}, \ + {kSign, {conf.sign}}, + +#define CASCADE_HIST_MC_MAP(conf) \ + {kTruePtVsPt, {conf.pt, conf.pt}}, \ + {kTrueEtaVsEta, {conf.eta, conf.eta}}, \ + {kTruePhiVsPhi, {conf.phi, conf.phi}}, \ + {kPdg, {conf.pdgCodes}}, \ + {kPdgMother, {conf.pdgCodes}}, \ + {kPdgPartonicMother, {conf.pdgCodes}}, + +#define CASCADE_HIST_QA_MAP(confAnalysis, confQa) \ + {kPt, {confAnalysis.pt}}, \ + {kEta, {confAnalysis.eta}}, \ + {kPhi, {confAnalysis.phi}}, \ + {kMass, {confAnalysis.mass}}, \ + {kSign, {confAnalysis.sign}}, \ + {kCosPa, {confQa.cosPa}}, \ + {kDecayDauDca, {confQa.dauDcaAtDecay}}, \ + {kTransRadius, {confQa.transRadius}}, \ + {kLambdaCosPa, {confQa.lambdaCosPa}}, \ + {kLambdaDauDca, {confQa.lambdaDauDca}}, \ + {kLambdaTransRadius, {confQa.lambdaTransRadius}}, \ + {kLambdaDcaToPv, {confQa.lambdaDcaToPv}}, \ + {kPtVsEta, {confAnalysis.pt, confAnalysis.eta}}, \ + {kPtVsPhi, {confAnalysis.pt, confAnalysis.phi}}, \ + {kPhiVsEta, {confAnalysis.phi, confAnalysis.eta}}, \ + {kPtVsCosPa, {confAnalysis.pt, confQa.cosPa}}, \ + {kMassXi, {confQa.massXi}}, \ + {kMassOmega, {confQa.massOmega}}, \ + {kPtVsMassXi, {confAnalysis.pt, confQa.massXi}}, \ + {kPtVsMassOmega, {confAnalysis.pt, confQa.massOmega}}, \ + {kMassXiVsMassOmega, {confQa.massXi, confQa.massOmega}}, + +#define CASCADE_HIST_MC_QA_MAP(confAnalysis, confQa) \ + {kNoMcParticle, {confAnalysis.pt, confQa.cosPa}}, \ + {kPrimary, {confAnalysis.pt, confQa.cosPa}}, \ + {kFromWrongCollision, {confAnalysis.pt, confQa.cosPa}}, \ + {kFromMaterial, {confAnalysis.pt, confQa.cosPa}}, \ + {kMissidentified, {confAnalysis.pt, confQa.cosPa}}, \ + {kSecondary1, {confAnalysis.pt, confQa.cosPa}}, \ + {kSecondary2, {confAnalysis.pt, confQa.cosPa}}, \ + {kSecondary3, {confAnalysis.pt, confQa.cosPa}}, \ + {kSecondaryOther, {confAnalysis.pt, confQa.cosPa}}, template auto makeCascadeHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ - {kPt, {confBinningAnalysis.pt}}, - {kEta, {confBinningAnalysis.eta}}, - {kPhi, {confBinningAnalysis.phi}}, - {kMass, {confBinningAnalysis.mass}}, - {kSign, {confBinningAnalysis.sign}}}; + return std::map>{ + CASCADE_HIST_ANALYSIS_MAP(confBinningAnalysis)}; +} + +template +auto makeCascadeMcHistSpecMap(const T& confBinningAnalysis) +{ + return std::map>{ + CASCADE_HIST_ANALYSIS_MAP(confBinningAnalysis) + CASCADE_HIST_MC_MAP(confBinningAnalysis)}; } template -std::map> makeCascadeQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) +std::map> makeCascadeQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ - {kPt, {confBinningAnalysis.pt}}, - {kEta, {confBinningAnalysis.eta}}, - {kPhi, {confBinningAnalysis.phi}}, - {kMass, {confBinningAnalysis.mass}}, - {kSign, {confBinningAnalysis.sign}}, - {kCosPa, {confBinningQa.cosPa}}, - {kDecayDauDca, {confBinningQa.dauDcaAtDecay}}, - {kTransRadius, {confBinningQa.transRadius}}, - {kPtVsEta, {confBinningAnalysis.pt, confBinningAnalysis.eta}}, - {kPtVsPhi, {confBinningAnalysis.pt, confBinningAnalysis.phi}}, - {kPhiVsEta, {confBinningAnalysis.phi, confBinningAnalysis.eta}}, - {kPtVsCosPa, {confBinningAnalysis.pt, confBinningQa.cosPa}}, - {kMassXi, {confBinningQa.massXi}}, - {kMassOmega, {confBinningQa.massOmega}}, - {kPtVsMassXi, {confBinningAnalysis.pt, confBinningQa.massXi}}, - {kPtVsMassOmega, {confBinningAnalysis.pt, confBinningQa.massOmega}}, - {kMassXiVsMassOmega, {confBinningQa.massXi, confBinningQa.massOmega}}}; -}; + return std::map>{ + CASCADE_HIST_ANALYSIS_MAP(confBinningAnalysis) + CASCADE_HIST_QA_MAP(confBinningAnalysis, confBinningQa)}; +} + +template +std::map> makeCascadeMcQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) +{ + return std::map>{ + CASCADE_HIST_ANALYSIS_MAP(confBinningAnalysis) + CASCADE_HIST_QA_MAP(confBinningAnalysis, confBinningQa) + CASCADE_HIST_MC_MAP(confBinningAnalysis) + CASCADE_HIST_MC_QA_MAP(confBinningAnalysis, confBinningQa)}; +} + +#undef CASCADE_HIST_ANALYSIS_MAP +#undef CASCADE_HIST_MC_MAP +#undef CASCADE_HIST_QA_MAP +#undef CASCADE_HIST_MC_QA_MAP constexpr char PrefixXiQa[] = "XiQA/"; constexpr char PrefixXi[] = "Xi/"; @@ -154,10 +262,9 @@ constexpr char PrefixOmega[] = "Omega/"; constexpr char PrefixLambdaCascade[] = "LambdaCascadeQa/"; -constexpr std::string_view AnalysisDir = "Kinematics/"; +constexpr std::string_view AnalysisDir = "Analysis/"; constexpr std::string_view QaDir = "QA/"; - -constexpr int AbsChargeDaughters = 1; +constexpr std::string_view McDir = "MC/"; /// \class FemtoDreamEventHisto /// \brief Class for histogramming event properties @@ -199,7 +306,7 @@ class CascadeHistManager posDauPdgCodeAbs = std::abs(PDG_t::kProton); negDauPdgCodeAbs = std::abs(PDG_t::kPiMinus); } else { - mPdgCode = -1 * mPdgCode; // Xi+ has negative pdg code + mPdgCode = -1 * mPdgCode; // Xi+ has negative pdg code because it is the anti particle bachelorPdgCodeAbs = std::abs(PDG_t::kPiPlus); signBachelor = 1; posDauPdgCodeAbs = std::abs(PDG_t::kPiPlus); @@ -212,7 +319,7 @@ class CascadeHistManager posDauPdgCodeAbs = std::abs(PDG_t::kProton); negDauPdgCodeAbs = std::abs(PDG_t::kPiMinus); } else { - mPdgCode = -1 * mPdgCode; // Omega+ has negative pdg code + mPdgCode = -1 * mPdgCode; // Omega+ has negative pdg code because it is the anti particle bachelorPdgCodeAbs = std::abs(PDG_t::kKPlus); signBachelor = 1; posDauPdgCodeAbs = std::abs(PDG_t::kPiPlus); @@ -229,6 +336,9 @@ class CascadeHistManager if constexpr (modes::isFlagSet(mode, modes::Mode::kAnalysis)) { initAnalysis(cascadeSpecs); } + if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { + this->initMc(cascadeSpecs); + } } template @@ -295,15 +405,14 @@ class CascadeHistManager if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { initQa(cascadeSpecs); } + if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { + this->initMc(cascadeSpecs); + } } template void fill(T1 const& cascadeCandidate, T2 const& tracks) { - // this used to work, still under investigation - // auto bachelor = cascadeCandidate.template bachelor_as(); - // auto posDaughter = cascadeCandidate.template posDau_as(); - // auto negDaughter = cascadeCandidate.template negDau_as(); auto posDaughter = tracks.rawIteratorAt(cascadeCandidate.posDauId() - tracks.offset()); mPosDauManager.template fill(posDaughter, tracks); auto negDaughter = tracks.rawIteratorAt(cascadeCandidate.negDauId() - tracks.offset()); @@ -319,6 +428,27 @@ class CascadeHistManager } } + template + void fill(T1 const& cascadeCandidate, T2 const& tracks, T3 const& mcParticles, T4 const& mcMothers, T5 const& mcPartonicMothers) + { + auto posDaughter = tracks.rawIteratorAt(cascadeCandidate.posDauId() - tracks.offset()); + mPosDauManager.template fill(posDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + auto negDaughter = tracks.rawIteratorAt(cascadeCandidate.negDauId() - tracks.offset()); + mNegDauManager.template fill(negDaughter, tracks, mcParticles, mcMothers, mcPartonicMothers); + auto bachelor = tracks.rawIteratorAt(cascadeCandidate.bachelorId() - tracks.offset()); + mBachelorManager.template fill(bachelor, tracks, mcParticles, mcMothers, mcPartonicMothers); + + if constexpr (modes::isFlagSet(mode, modes::Mode::kAnalysis)) { + this->fillAnalysis(cascadeCandidate); + } + if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { + this->fillQa(cascadeCandidate); + } + if constexpr (modes::isFlagSet(mode, modes::Mode::kMc)) { + this->template fillMc(cascadeCandidate, mcParticles, mcMothers, mcPartonicMothers); + } + } + private: template void enableOptionalHistograms(T const& CascadeConfBinningQa) @@ -342,6 +472,10 @@ class CascadeHistManager mHistogramRegistry->add(qaDir + getHistNameV2(kCosPa, HistTable), getHistDesc(kCosPa, HistTable), getHistType(kCosPa, HistTable), {cascadeSpecs.at(kCosPa)}); mHistogramRegistry->add(qaDir + getHistNameV2(kDecayDauDca, HistTable), getHistDesc(kDecayDauDca, HistTable), getHistType(kDecayDauDca, HistTable), {cascadeSpecs.at(kDecayDauDca)}); mHistogramRegistry->add(qaDir + getHistNameV2(kTransRadius, HistTable), getHistDesc(kTransRadius, HistTable), getHistType(kTransRadius, HistTable), {cascadeSpecs.at(kTransRadius)}); + mHistogramRegistry->add(qaDir + getHistNameV2(kLambdaCosPa, HistTable), getHistDesc(kLambdaCosPa, HistTable), getHistType(kLambdaCosPa, HistTable), {cascadeSpecs.at(kLambdaCosPa)}); + mHistogramRegistry->add(qaDir + getHistNameV2(kLambdaDauDca, HistTable), getHistDesc(kLambdaDauDca, HistTable), getHistType(kLambdaDauDca, HistTable), {cascadeSpecs.at(kLambdaDauDca)}); + mHistogramRegistry->add(qaDir + getHistNameV2(kLambdaTransRadius, HistTable), getHistDesc(kLambdaTransRadius, HistTable), getHistType(kLambdaTransRadius, HistTable), {cascadeSpecs.at(kLambdaTransRadius)}); + mHistogramRegistry->add(qaDir + getHistNameV2(kLambdaDcaToPv, HistTable), getHistDesc(kLambdaDcaToPv, HistTable), getHistType(kLambdaDcaToPv, HistTable), {cascadeSpecs.at(kLambdaDcaToPv)}); mHistogramRegistry->add(qaDir + getHistNameV2(kMassXi, HistTable), getHistDesc(kMassXi, HistTable), getHistType(kMassXi, HistTable), {cascadeSpecs.at(kMassXi)}); mHistogramRegistry->add(qaDir + getHistNameV2(kMassOmega, HistTable), getHistDesc(kMassOmega, HistTable), getHistType(kMassOmega, HistTable), {cascadeSpecs.at(kMassOmega)}); @@ -357,6 +491,47 @@ class CascadeHistManager } } + void initMc(std::map> const& V0Specs) + { + std::string mcDir = std::string(cascadePrefix) + std::string(McDir); + mHistogramRegistry->add(mcDir + getHistNameV2(kTruePtVsPt, HistTable), getHistDesc(kTruePtVsPt, HistTable), getHistType(kTruePtVsPt, HistTable), {V0Specs.at(kTruePtVsPt)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kTrueEtaVsEta, HistTable), getHistDesc(kTrueEtaVsEta, HistTable), getHistType(kTrueEtaVsEta, HistTable), {V0Specs.at(kTrueEtaVsEta)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kTruePhiVsPhi, HistTable), getHistDesc(kTruePhiVsPhi, HistTable), getHistType(kTruePhiVsPhi, HistTable), {V0Specs.at(kTruePhiVsPhi)}); + + // mc origin can be configured here + const o2::framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; + mHistogramRegistry->add(mcDir + getHistNameV2(kOrigin, HistTable), getHistDesc(kOrigin, HistTable), getHistType(kOrigin, HistTable), {axisOrigin}); + mHistogramRegistry->get(HIST(cascadePrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kNoMcParticle), modes::mcOriginToString(modes::McOrigin::kNoMcParticle)); + mHistogramRegistry->get(HIST(cascadePrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kFromWrongCollision), modes::mcOriginToString(modes::McOrigin::kFromWrongCollision)); + mHistogramRegistry->get(HIST(cascadePrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kPhysicalPrimary), modes::mcOriginToString(modes::McOrigin::kPhysicalPrimary)); + mHistogramRegistry->get(HIST(cascadePrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kFromSecondaryDecay), modes::mcOriginToString(modes::McOrigin::kFromSecondaryDecay)); + mHistogramRegistry->get(HIST(cascadePrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kFromMaterial), modes::mcOriginToString(modes::McOrigin::kFromMaterial)); + mHistogramRegistry->get(HIST(cascadePrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kMissidentified), modes::mcOriginToString(modes::McOrigin::kMissidentified)); + + mHistogramRegistry->add(mcDir + getHistNameV2(kPdg, HistTable), getHistDesc(kPdg, HistTable), getHistType(kPdg, HistTable), {V0Specs.at(kPdg)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kPdgMother, HistTable), getHistDesc(kPdgMother, HistTable), getHistType(kPdgMother, HistTable), {V0Specs.at(kPdgMother)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kPdgPartonicMother, HistTable), getHistDesc(kPdgPartonicMother, HistTable), getHistType(kPdgPartonicMother, HistTable), {V0Specs.at(kPdgPartonicMother)}); + + if (mPlotOrigins) { + mHistogramRegistry->add(mcDir + getHistNameV2(kNoMcParticle, HistTable), getHistDesc(kNoMcParticle, HistTable), getHistType(kNoMcParticle, HistTable), {V0Specs.at(kNoMcParticle)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kPrimary, HistTable), getHistDesc(kPrimary, HistTable), getHistType(kPrimary, HistTable), {V0Specs.at(kPrimary)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kFromWrongCollision, HistTable), getHistDesc(kFromWrongCollision, HistTable), getHistType(kFromWrongCollision, HistTable), {V0Specs.at(kFromWrongCollision)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kFromMaterial, HistTable), getHistDesc(kFromMaterial, HistTable), getHistType(kFromMaterial, HistTable), {V0Specs.at(kFromMaterial)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kMissidentified, HistTable), getHistDesc(kMissidentified, HistTable), getHistType(kMissidentified, HistTable), {V0Specs.at(kMissidentified)}); + + if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel1) { + mHistogramRegistry->add(mcDir + getHistNameV2(kSecondary1, HistTable), getHistDesc(kSecondary1, HistTable), getHistType(kSecondary1, HistTable), {V0Specs.at(kSecondary1)}); + } + if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel2) { + mHistogramRegistry->add(mcDir + getHistNameV2(kSecondary2, HistTable), getHistDesc(kSecondary2, HistTable), getHistType(kSecondary2, HistTable), {V0Specs.at(kSecondary2)}); + } + if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel3) { + mHistogramRegistry->add(mcDir + getHistNameV2(kSecondary3, HistTable), getHistDesc(kSecondary3, HistTable), getHistType(kSecondary3, HistTable), {V0Specs.at(kSecondary3)}); + } + mHistogramRegistry->add(mcDir + getHistNameV2(kSecondaryOther, HistTable), getHistDesc(kSecondaryOther, HistTable), getHistType(kSecondaryOther, HistTable), {V0Specs.at(kSecondaryOther)}); + } + } + template void fillAnalysis(T const& cascadeCandidate) { @@ -383,6 +558,10 @@ class CascadeHistManager mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kCosPa, HistTable)), cascadeCandidate.cascadeCosPa()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kDecayDauDca, HistTable)), cascadeCandidate.cascadeDauDca()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kTransRadius, HistTable)), cascadeCandidate.cascadeTransRadius()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kLambdaCosPa, HistTable)), cascadeCandidate.lambdaCosPa()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kLambdaDauDca, HistTable)), cascadeCandidate.lambdaDauDca()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kLambdaTransRadius, HistTable)), cascadeCandidate.lambdaTransRadius()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kLambdaDcaToPv, HistTable)), cascadeCandidate.lambdaDcaToPv()); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kMassXi, HistTable)), massXi); mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(QaDir) + HIST(getHistName(kMassOmega, HistTable)), massOmega); @@ -397,12 +576,107 @@ class CascadeHistManager } } + template + void fillMc(T1 const& cascadeCandidate, T2 const& /*mcParticles*/, T3 const& /*mcMothers*/, T4 const& /*mcPartonicMothers*/) + { + // No MC Particle + if (!cascadeCandidate.has_fMcParticle()) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdg, HistTable)), 0); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kNoMcParticle)); + if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { + if (mPlotOrigins) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kNoMcParticle, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } + } + return; + } + + // Retrieve MC particle + auto mcParticle = cascadeCandidate.template fMcParticle_as(); + + // missidentifed particles are special case + // whether a particle is missidentfied or not cannot be known by the producer so we check it here + bool isMissidentified = mcParticle.pdgCode() != mPdgCode; + + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kTruePtVsPt, HistTable)), mcParticle.pt(), cascadeCandidate.pt()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kTrueEtaVsEta, HistTable)), mcParticle.eta(), cascadeCandidate.eta()); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kTruePhiVsPhi, HistTable)), mcParticle.phi(), cascadeCandidate.phi()); + if (isMissidentified) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), static_cast(modes::McOrigin::kMissidentified)); + } else { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kOrigin, HistTable)), mcParticle.origin()); + } + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdg, HistTable)), mcParticle.pdgCode()); + + // get mother + if (cascadeCandidate.has_fMcMother()) { + auto mother = cascadeCandidate.template fMcMother_as(); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), mother.pdgCode()); + } else { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgMother, HistTable)), 0); + } + + // get partonic mother + if (cascadeCandidate.has_fMcPartMoth()) { + auto partonicMother = cascadeCandidate.template fMcPartMoth_as(); + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), partonicMother.pdgCode()); + } else { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPdgPartonicMother, HistTable)), 0); + } + + if constexpr (modes::isFlagSet(mode, modes::Mode::kQa)) { + if (mPlotOrigins) { + // check first if particle is missidentified + if (isMissidentified) { + // if it is, we fill it as such + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kMissidentified, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } else { + // if not, we fill it acccoridng to its origin + switch (static_cast(mcParticle.origin())) { + case modes::McOrigin::kPhysicalPrimary: + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kPrimary, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + break; + case modes::McOrigin::kFromWrongCollision: + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kFromWrongCollision, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + break; + case modes::McOrigin::kFromMaterial: + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kFromMaterial, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + break; + case modes::McOrigin::kFromSecondaryDecay: + if (cascadeCandidate.has_fMcMother()) { + auto mother = cascadeCandidate.template fMcMother_as(); + int motherPdgCode = std::abs(mother.pdgCode()); + // Switch on PDG of the mother + if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel1 && motherPdgCode == mPdgCodesSecondaryMother[0]) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kSecondary1, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } else if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel2 && motherPdgCode == mPdgCodesSecondaryMother[1]) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kSecondary2, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } else if (mPlotNSecondaries >= histmanager::kSecondaryPlotLevel3 && motherPdgCode == mPdgCodesSecondaryMother[2]) { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kSecondary3, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } else { + mHistogramRegistry->fill(HIST(cascadePrefix) + HIST(McDir) + HIST(getHistName(kSecondaryOther, HistTable)), cascadeCandidate.pt(), cascadeCandidate.cascadeCosPa()); + } + } + break; + default: + LOG(warn) << "Encounted partilce with unknown origin!"; + break; + } + } + } + } + } + o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; - bool mPlot2d = true; + int mPdgCode = 0; + bool mPlotOrigins = false; + int mPlotNSecondaries = 0; + std::array mPdgCodesSecondaryMother = {0}; + bool mPlot2d = false; + trackhistmanager::TrackHistManager mBachelorManager; trackhistmanager::TrackHistManager mPosDauManager; trackhistmanager::TrackHistManager mNegDauManager; - int mPdgCode = 0; }; }; // namespace cascadehistmanager }; // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/closePairRejection.h b/PWGCF/Femto/Core/closePairRejection.h index 9ac2ea0ad8b..3edc198aba9 100644 --- a/PWGCF/Femto/Core/closePairRejection.h +++ b/PWGCF/Femto/Core/closePairRejection.h @@ -16,20 +16,25 @@ #ifndef PWGCF_FEMTO_CORE_CLOSEPAIRREJECTION_H_ #define PWGCF_FEMTO_CORE_CLOSEPAIRREJECTION_H_ -#include "RecoDecay.h" - -#include "PWGCF/Femto/Core/femtoUtils.h" #include "PWGCF/Femto/Core/histManager.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include + +#include +#include +#include +#include +#include #include +#include #include #include +#include #include #include +#include +#include #include #include @@ -50,6 +55,8 @@ enum CprHist { kRadius6, kRadius7, kRadius8, + kPhi1VsPhi2, + kEta1VsEta2, kCprHistogramLast }; @@ -61,14 +68,18 @@ struct ConfCpr : o2::framework::ConfigurableGroup { o2::framework::Configurable cutAnyRadius{"cutAnyRadius", false, "Apply CPR if the deta-dphistar is below the configured values at any radius"}; o2::framework::Configurable plotAllRadii{"plotAllRadii", true, "Plot deta-dphi distribution at all radii"}; o2::framework::Configurable plotAverage{"plotAverage", true, "Plot average deta dphi distribution"}; + o2::framework::Configurable plotAngularCorrelation{"plotAngularCorrelation", false, "Plot angular correlation of particles (eta1 vs eta2 & phi1 vs phi2"}; o2::framework::Configurable detaMax{"detaMax", 0.01f, "Maximium deta"}; o2::framework::Configurable dphistarMax{"dphistarMax", 0.01f, "Maximum dphistar"}; o2::framework::Configurable detaCenter{"detaCenter", 0.f, "Center of deta cut"}; o2::framework::Configurable dphistarCenter{"dphistarCenter", 0.f, "Center of dphistar cut"}; - o2::framework::Configurable kstarMin{"kstarMin", -1.f, "Minimum kstar of pair for plotting (Set to negative value to turn off the cut)"}; - o2::framework::Configurable kstarMax{"kstarMax", -1.f, "Maximum kstar of pair for plotting (Set to negative value to turn off the cut)"}; + o2::framework::Configurable kinematicMin{"kinematicMin", -1.f, "Minimum kstar/Q3 of pair/triplet for plotting (Set to negative value to turn off the cut)"}; + o2::framework::Configurable kinematicMax{"kinematicMax", -1.f, "Maximum kstar/Q3 of pair/triplet for plotting (Set to negative value to turn off the cut)"}; o2::framework::ConfigurableAxis binningDeta{"binningDeta", {{250, -0.5, 0.5}}, "deta"}; o2::framework::ConfigurableAxis binningDphistar{"binningDphistar", {{250, -0.5, 0.5}}, "dphi"}; + o2::framework::ConfigurableAxis binningCorrelationPhi{"binningCorrelationPhi", {{720, 0, o2::constants::math::TwoPI}}, "Phi binning for correlation plot"}; + o2::framework::ConfigurableAxis binningCorrelationEta{"binningCorrelationEta", {{160, -0.8, 0.8}}, "Eta binning for correlation plot"}; + o2::framework::Configurable seed{"seed", -1, "Seed to randomize particle 1 and particle 2. Set to negative value to deactivate. Set to 0 to generate unique seed in time."}; }; constexpr const char PrefixCprTrackTrack[] = "CprTrackTrack"; @@ -79,6 +90,7 @@ constexpr const char PrefixCprV0DaughterV0DaughterPos[] = "CprV0DaughterV0Daught constexpr const char PrefixCprV0DaughterV0DaughterNeg[] = "CprV0DaughterV0DaughterNeg"; constexpr const char PrefixCprTrackCascadeBachelor[] = "CprTrackCascadeBachelor"; +// pairs using ConfCprTrackTrack = ConfCpr; using ConfCprTrackV0Daughter = ConfCpr; using ConfCprTrackResonanceDaughter = ConfCpr; @@ -119,12 +131,14 @@ constexpr std::array, kCprHistogramLast> HistTabl {kRadius5, o2::framework::kTH2F, "hRadius5", "Radius 5: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, {kRadius6, o2::framework::kTH2F, "hRadius6", "Radius 6: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, {kRadius7, o2::framework::kTH2F, "hRadius7", "Radius 7: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, - {kRadius8, o2::framework::kTH2F, "hRadius8", "Radius 8: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}}}; + {kRadius8, o2::framework::kTH2F, "hRadius8", "Radius 8: #Delta #eta vs #Delta #phi*; #Delta #eta; #Delta #phi*"}, + {kPhi1VsPhi2, o2::framework::kTH2F, "hPhi1vsPhi2", "#phi_{1} vs #phi_{2}; #phi_{1}; #phi_{2}"}, + {kEta1VsEta2, o2::framework::kTH2F, "hEta1VsEta2", "#eta_{1} vs #eta_{2}; #eta_{1}; #eta_{2}"}}}; template auto makeCprHistSpecMap(const T& confCpr) { - return std::map>{ + return std::map>{ {kAverage, {confCpr.binningDeta, confCpr.binningDphistar}}, {kRadius0, {confCpr.binningDeta, confCpr.binningDphistar}}, {kRadius1, {confCpr.binningDeta, confCpr.binningDphistar}}, @@ -134,7 +148,10 @@ auto makeCprHistSpecMap(const T& confCpr) {kRadius5, {confCpr.binningDeta, confCpr.binningDphistar}}, {kRadius6, {confCpr.binningDeta, confCpr.binningDphistar}}, {kRadius7, {confCpr.binningDeta, confCpr.binningDphistar}}, - {kRadius8, {confCpr.binningDeta, confCpr.binningDphistar}}}; + {kRadius8, {confCpr.binningDeta, confCpr.binningDphistar}}, + {kPhi1VsPhi2, {confCpr.binningCorrelationPhi, confCpr.binningCorrelationPhi}}, + {kEta1VsEta2, {confCpr.binningCorrelationEta, confCpr.binningCorrelationEta}}, + }; }; template @@ -168,12 +185,25 @@ class CloseTrackRejection mCutAverage = confCpr.cutAverage.value; mCutAnyRadius = confCpr.cutAnyRadius.value; - mKstarMin = confCpr.kstarMin.value; - mKstarMax = confCpr.kstarMax.value; + mKinematicMin = confCpr.kinematicMin.value; + mKinematicMax = confCpr.kinematicMax.value; mPlotAverage = confCpr.plotAverage.value; mPlotAllRadii = confCpr.plotAllRadii.value; + mPlotAngularCorrelation = confCpr.plotAngularCorrelation.value; + + if (confCpr.seed.value >= 0) { + uint64_t randomSeed; + mRandomizeTracks = true; + if (confCpr.seed.value == 0) { + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } else { + randomSeed = static_cast(confCpr.seed.value); + } + mRng = std::mt19937(randomSeed); + } + // check if we need to apply any cut a plot is requested mIsActivated = mCutAverage || mCutAnyRadius || mPlotAverage || mPlotAllRadii; @@ -193,6 +223,11 @@ class CloseTrackRejection mHistogramRegistry->add(std::string(prefix) + getHistNameV2(kRadius7, HistTable), getHistDesc(kRadius7, HistTable), getHistType(kRadius7, HistTable), {specs.at(kRadius7)}); mHistogramRegistry->add(std::string(prefix) + getHistNameV2(kRadius8, HistTable), getHistDesc(kRadius8, HistTable), getHistType(kRadius8, HistTable), {specs.at(kRadius8)}); } + + if (mPlotAngularCorrelation) { + mHistogramRegistry->add(std::string(prefix) + getHistNameV2(kPhi1VsPhi2, HistTable), getHistDesc(kPhi1VsPhi2, HistTable), getHistType(kPhi1VsPhi2, HistTable), {specs.at(kPhi1VsPhi2)}); + mHistogramRegistry->add(std::string(prefix) + getHistNameV2(kEta1VsEta2, HistTable), getHistDesc(kEta1VsEta2, HistTable), getHistType(kEta1VsEta2, HistTable), {specs.at(kEta1VsEta2)}); + } } void setMagField(float magField) { mMagField = magField; } @@ -210,39 +245,59 @@ class CloseTrackRejection mDphistar.fill(0.f); mDphistarMask.fill(false); - mDeta = track1.eta() - track2.eta(); + bool swapTracks = false; + if (mRandomizeTracks) { + swapTracks = (mSwapDist(mRng) == 1); + } + + auto const& t1 = swapTracks ? track2 : track1; + auto const& t2 = swapTracks ? track1 : track2; + + mDeta = t1.eta() - t2.eta(); for (size_t i = 0; i < TpcRadii.size(); i++) { - auto phistar1 = utils::dphistar(mMagField, TpcRadii[i], mChargeAbsTrack1 * track1.signedPt(), track1.phi()); - auto phistar2 = utils::dphistar(mMagField, TpcRadii[i], mChargeAbsTrack2 * track2.signedPt(), track2.phi()); + auto phistar1 = phistar(mMagField, TpcRadii[i], mChargeAbsTrack1 * t1.signedPt(), t1.phi()); + auto phistar2 = phistar(mMagField, TpcRadii[i], mChargeAbsTrack2 * t2.signedPt(), t2.phi()); if (phistar1 && phistar2) { mDphistar.at(i) = RecoDecay::constrainAngle(phistar1.value() - phistar2.value(), -o2::constants::math::PI); // constrain angular difference between -pi and pi mDphistarMask.at(i) = true; count++; } } - // for small momemeta the calculation of phistar might fail, if the particle did not reach a certain radius + // for small momemeta the calculation of phistar might fail, if the particle did not reach one or more of the outer radii if (count > 0) { mAverageDphistar = std::accumulate(mDphistar.begin(), mDphistar.end(), 0.f) / count; // only average values if phistar could be computed } else { mAverageDphistar = 0.f; // if computation at all radii fail, set it 0 } + + if (mPlotAngularCorrelation) { + mPhi1 = t1.phi(); + mPhi2 = t2.phi(); + mEta1 = t1.eta(); + mEta2 = t2.eta(); + } } - void fill(float kstar) + void fill(float kinematic) { if (!mIsActivated) { return; } - if (mKstarMin > 0.f && kstar < mKstarMin) { + if (mKinematicMin > 0.f && kinematic < mKinematicMin) { return; } - if (mKstarMax > 0.f && kstar > mKstarMax) { + if (mKinematicMax > 0.f && kinematic > mKinematicMax) { return; } + if (mPlotAngularCorrelation) { + mHistogramRegistry->fill(HIST(prefix) + HIST(getHistName(kPhi1VsPhi2, HistTable)), mPhi1, mPhi2); + mHistogramRegistry->fill(HIST(prefix) + HIST(getHistName(kEta1VsEta2, HistTable)), mEta1, mEta2); + } + // fill average hist if (mPlotAverage) { mHistogramRegistry->fill(HIST(prefix) + HIST(getHistName(kAverage, HistTable)), mDeta, mAverageDphistar); @@ -308,12 +363,23 @@ class CloseTrackRejection bool isActivated() const { return mIsActivated; } private: + std::optional phistar(float magfield, float radius, float signedPt, float phi) + { + double arg = 0.3 * (0.1 * magfield) * (0.01 * radius) / (2. * signedPt); + if (std::fabs(arg) <= 1.) { + double phistar = phi - std::asin(arg); + return static_cast(RecoDecay::constrainAngle(phistar)); + } + return std::nullopt; + } + o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; bool mPlotAllRadii = false; bool mPlotAverage = false; + bool mPlotAngularCorrelation = false; - float mKstarMin = -1.f; - float mKstarMax = -1.f; + float mKinematicMin = -1.f; + float mKinematicMax = -1.f; bool mCutAverage = false; bool mCutAnyRadius = false; @@ -330,8 +396,18 @@ class CloseTrackRejection float mAverageDphistar = 0.f; float mDeta = 0.f; + + float mPhi1 = 0.f; + float mPhi2 = 0.f; + float mEta1 = 0.f; + float mEta2 = 0.f; + std::array mDphistar = {0.f}; std::array mDphistarMask = {false}; + + bool mRandomizeTracks = false; + std::mt19937 mRng; + std::uniform_int_distribution mSwapDist{0, 1}; }; template diff --git a/PWGCF/Femto/Core/closeTripletRejection.h b/PWGCF/Femto/Core/closeTripletRejection.h new file mode 100644 index 00000000000..dd1bd0182c0 --- /dev/null +++ b/PWGCF/Femto/Core/closeTripletRejection.h @@ -0,0 +1,156 @@ +// 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 closeTripletRejection.h +/// \brief Definition of CloseTripletRejection class +/// \author Anton Riedel, TU München, anton.riedel@tum.de + +#ifndef PWGCF_FEMTO_CORE_CLOSETRIPLETREJECTION_H_ +#define PWGCF_FEMTO_CORE_CLOSETRIPLETREJECTION_H_ + +#include "PWGCF/Femto/Core/closePairRejection.h" + +#include +#include + +#include +#include +#include + +namespace o2::analysis::femto +{ +namespace closetripletrejection +{ + +constexpr const char PrefixCtrTrackTrackTrack[] = "CtrTrackTrackTrack"; +using ConfCtrTrackTrackTrack = closepairrejection::ConfCpr; + +// directory names +constexpr char PrefixTrack1Track2Se[] = "CPR_Track1Track2/SE/"; +constexpr char PrefixTrack2Track3Se[] = "CPR_Track2Track3/SE/"; +constexpr char PrefixTrack1Track3Se[] = "CPR_Track1Track3/SE/"; +constexpr char PrefixTrack1Track2Me[] = "CPR_Track1Track2/ME/"; +constexpr char PrefixTrack2Track3Me[] = "CPR_Track2Track3/ME/"; +constexpr char PrefixTrack1Track3Me[] = "CPR_Track1Track3/ME/"; + +constexpr char PrefixTrack1V0Se[] = "CPR_Track1V0/SE/"; +constexpr char PrefixTrack2V0Se[] = "CPR_Track2V0/SE/"; +constexpr char PrefixTrack1V0Me[] = "CPR_Track1V0/ME/"; +constexpr char PrefixTrack2V0Me[] = "CPR_Track2V0/ME/"; + +template +class CloseTripletRejectionTrackTrackTrack +{ + public: + CloseTripletRejectionTrackTrackTrack() = default; + ~CloseTripletRejectionTrackTrackTrack() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + std::map> const& specs, + T const& confCpr, + int absChargeTrack1, + int absChargeTrack2, + int absChargeTrack3) + { + mCtrTrack12.init(registry, specs, confCpr, absChargeTrack1, absChargeTrack2); + mCtrTrack23.init(registry, specs, confCpr, absChargeTrack2, absChargeTrack3); + mCtrTrack13.init(registry, specs, confCpr, absChargeTrack1, absChargeTrack3); + } + + void setMagField(float magField) + { + mCtrTrack12.setMagField(magField); + mCtrTrack23.setMagField(magField); + mCtrTrack13.setMagField(magField); + } + template + void setTriplet(T1 const& track1, T2 const& track2, T3 const& track3, T4 const& trackTable) + { + mCtrTrack12.setPair(track1, track2, trackTable); + mCtrTrack23.setPair(track2, track3, trackTable); + mCtrTrack13.setPair(track1, track3, trackTable); + } + bool isCloseTriplet() const + { + return mCtrTrack12.isClosePair() || mCtrTrack23.isClosePair() || mCtrTrack13.isClosePair(); + } + + void fill(float q3) + { + mCtrTrack12.fill(q3); + mCtrTrack23.fill(q3); + mCtrTrack13.fill(q3); + } + + private: + closepairrejection::ClosePairRejectionTrackTrack mCtrTrack12; + closepairrejection::ClosePairRejectionTrackTrack mCtrTrack23; + closepairrejection::ClosePairRejectionTrackTrack mCtrTrack13; +}; + +template +class CloseTripletRejectionTrackTrackV0 +{ + public: + CloseTripletRejectionTrackTrackV0() = default; + ~CloseTripletRejectionTrackTrackV0() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + std::map> const& specs, + T const& confCpr, + int absChargeTrack1, + int absChargeTrack2) + { + mCtrTrack12.init(registry, specs, confCpr, absChargeTrack1, absChargeTrack2); + mCtrTrack1V0.init(registry, specs, confCpr, absChargeTrack1); + mCtrTrack2V0.init(registry, specs, confCpr, absChargeTrack2); + } + + void setMagField(float magField) + { + mCtrTrack12.setMagField(magField); + mCtrTrack1V0.setMagField(magField); + mCtrTrack2V0.setMagField(magField); + } + template + void setTriplet(T1 const& track1, T2 const& track2, T3 const& v0, T4 const& trackTable) + { + mCtrTrack12.setPair(track1, track2, trackTable); + mCtrTrack1V0.setPair(track1, v0, trackTable); + mCtrTrack2V0.setPair(track2, v0, trackTable); + } + bool isCloseTriplet() const + { + return mCtrTrack12.isClosePair() || mCtrTrack1V0.isClosePair() || mCtrTrack2V0.isClosePair(); + } + + void fill(float q3) + { + mCtrTrack12.fill(q3); + mCtrTrack1V0.fill(q3); + mCtrTrack2V0.fill(q3); + } + + private: + closepairrejection::ClosePairRejectionTrackTrack mCtrTrack12; + closepairrejection::ClosePairRejectionTrackV0 mCtrTrack1V0; + closepairrejection::ClosePairRejectionTrackV0 mCtrTrack2V0; +}; + +}; // namespace closetripletrejection +}; // namespace o2::analysis::femto +#endif // PWGCF_FEMTO_CORE_CLOSETRIPLETREJECTION_H_ diff --git a/PWGCF/Femto/Core/collisionBuilder.h b/PWGCF/Femto/Core/collisionBuilder.h index 0d094bc5abf..e6b77102023 100644 --- a/PWGCF/Femto/Core/collisionBuilder.h +++ b/PWGCF/Femto/Core/collisionBuilder.h @@ -23,15 +23,15 @@ #include "PWGCF/Femto/Core/selectionContainer.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/Core/Zorro.h" +#include +#include +#include -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" - -#include "fairlogger/Logger.h" +#include +#include +#include +#include +#include #include #include @@ -225,7 +225,7 @@ class CollisionSelection : public BaseSelection void setSphericity(T tracks) { - mSphericity = utils::sphericity(tracks); + mSphericity = computeSphericity(tracks); } float getSphericity() const { return mSphericity; } @@ -312,6 +312,39 @@ class CollisionSelection : public BaseSelection + float computeSphericity(T const& tracks) + { + int minNumberTracks = 2; + double maxSphericity = 2.f; + if (tracks.size() <= minNumberTracks) { + return maxSphericity; + } + // Initialize the transverse momentum tensor components + double sxx = 0.; + double syy = 0.; + double sxy = 0.; + double sumPt = 0.; + // Loop over the tracks to compute the tensor components + for (const auto& track : tracks) { + sxx += (track.px() * track.px()) / track.pt(); + syy += (track.py() * track.py()) / track.pt(); + sxy += (track.px() * track.py()) / track.pt(); + sumPt += track.pt(); + } + sxx /= sumPt; + syy /= sumPt; + sxy /= sumPt; + // Compute the eigenvalues (real values) + double lambda1 = ((sxx + syy) + std::sqrt((sxx + syy) * (sxx + syy) - 4. * (sxx * syy - sxy * sxy))) / 2.; + double lambda2 = ((sxx + syy) - std::sqrt((sxx + syy) * (sxx + syy) - 4. * (sxx * syy - sxy * sxy))) / 2.; + if (lambda1 <= 0. || lambda2 <= 0.) { + return maxSphericity; + } + // Compute sphericity + return static_cast(2. * lambda2 / (lambda1 + lambda2)); + } + // filter cuts float mVtxZMin = -12.f; float mVtxZMax = -12.f; @@ -362,20 +395,10 @@ class CollisionBuilder void init(o2::framework::HistogramRegistry* registry, T1& confFilter, T2& confBits, T3& confRct, T4& confCcdb, T5& confTable, T6& initContext) { LOG(info) << "Initialize femto collision builder..."; - mProducedCollisions = utils::enableTable("FCols_001", confTable.produceCollisions.value, initContext); - mProducedCollisionMasks = utils::enableTable("FColMasks_001", confTable.produceCollisionMasks.value, initContext); - mProducedPositions = utils::enableTable("FColPos_001", confTable.producePositions.value, initContext); - mProducedSphericities = utils::enableTable("FColSphericities_001", confTable.produceSphericities.value, initContext); - mProducedMultiplicities = utils::enableTable("FColMults_001", confTable.produceMults.value, initContext); - mProducedCentralities = utils::enableTable("FColCents_001", confTable.produceCents.value, initContext); - mProduceQns = utils::enableTable("FColQnBins_001", confTable.produceQns.value, initContext); - if (mProducedCollisions || mProducedCollisionMasks || mProducedPositions || mProducedSphericities || mProducedMultiplicities || mProducedCentralities) { - mFillAnyTable = true; - } else { - LOG(info) << "No tables configured, Selection object will not be configured..."; - LOG(info) << "Initialization done..."; - return; - } + + mMagFieldForced = confCcdb.magFieldForced.value; + mGrpPath = confCcdb.grpPath.value; + mSubGeneratorId = confFilter.subGeneratorId.value; if (!confBits.triggers.value.empty()) { mUseTrigger = true; @@ -389,11 +412,24 @@ class CollisionBuilder } if (confRct.useRctFlags.value) { mUseRctFlags = true; + LOG(info) << "Init RCT flag checker with label: " << confRct.label.value << "; use ZDC: " << confRct.useZdc.value << "; Limimted acceptance is bad: " << confRct.treatLimitedAcceptanceAsBad.value; mRctFlagsChecker.init(confRct.label.value, confRct.useZdc.value, confRct.treatLimitedAcceptanceAsBad.value); } - mMagFieldForced = confCcdb.magFieldForced.value; - mGrpPath = confCcdb.grpPath.value; - mSubGeneratorId = confFilter.subGeneratorId.value; + + mProducedCollisions = utils::enableTable("FCols_001", confTable.produceCollisions.value, initContext); + mProducedCollisionMasks = utils::enableTable("FColMasks_001", confTable.produceCollisionMasks.value, initContext); + mProducedPositions = utils::enableTable("FColPos_001", confTable.producePositions.value, initContext); + mProducedSphericities = utils::enableTable("FColSphericities_001", confTable.produceSphericities.value, initContext); + mProducedMultiplicities = utils::enableTable("FColMults_001", confTable.produceMults.value, initContext); + mProducedCentralities = utils::enableTable("FColCents_001", confTable.produceCents.value, initContext); + mProduceQns = utils::enableTable("FColQnBins_001", confTable.produceQns.value, initContext); + if (mProducedCollisions || mProducedCollisionMasks || mProducedPositions || mProducedSphericities || mProducedMultiplicities || mProducedCentralities) { + mFillAnyTable = true; + } else { + LOG(info) << "No tables configured, Selection object will not be configured..."; + LOG(info) << "Initialization done..."; + return; + } mCollisionSelection.configure(registry, confFilter, confBits); mCollisionSelection.printSelections(colSelsName); @@ -407,16 +443,19 @@ class CollisionBuilder mRunNumber = bc.runNumber(); if (mMagFieldForced == 0) { static o2::parameters::GRPMagField* grpo = nullptr; + LOG(info) << "Get magentic field with Path: " << mGrpPath << "; Run number: " << mRunNumber; grpo = ccdb->template getForRun(mGrpPath, mRunNumber); if (grpo == nullptr) { LOG(fatal) << "GRP object not found for Run " << mRunNumber; } mMagField = static_cast(grpo->getNominalL3Field()); // get magnetic field in kG } else { + LOG(info) << "Force magentic field to " << mMagFieldForced << "kG"; mMagField = mMagFieldForced; } if (mUseTrigger) { + LOG(info) << "Init Zorro with Run Number: " << mRunNumber << "; timestamp: " << bc.timestamp() << "; Trigger Names: " << mTriggerNames; mZorro.initCCDB(ccdb.service, mRunNumber, bc.timestamp(), mTriggerNames); mZorro.populateHistRegistry(histRegistry, mRunNumber); } @@ -439,8 +478,10 @@ class CollisionBuilder bool checkCollision(T1 const& col) { // check RCT flags first - if (mUseRctFlags && !mRctFlagsChecker(col)) { - return false; + if (mUseRctFlags) { + if (!mRctFlagsChecker(col)) { + return false; + } } // make other checks return mCollisionSelection.checkFilters(col) && diff --git a/PWGCF/Femto/Core/collisionHistManager.h b/PWGCF/Femto/Core/collisionHistManager.h index 108921ba5be..a4bbda81b6f 100644 --- a/PWGCF/Femto/Core/collisionHistManager.h +++ b/PWGCF/Femto/Core/collisionHistManager.h @@ -19,11 +19,13 @@ #include "PWGCF/Femto/Core/histManager.h" #include "PWGCF/Femto/Core/modes.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include #include +#include +#include #include #include #include @@ -51,15 +53,18 @@ enum ColHist { kCentVsMult, kCentVsSphericity, kMultVsSphericity, + // particle number correlation + kNpart1VsNpart2, + kNpart1VsNpart2VsNpart3, // mc kTrueCentVsCent, kTrueMultVsMult, kColHistLast }; -constexpr std::string_view ColAnalysisDir = "Collisions/Analysis/"; -constexpr std::string_view ColQaDir = "Collisions/QA/"; -constexpr std::string_view ColMcDir = "Collisions/MC/"; +constexpr std::string_view AnalysisDir = "Collisions/Analysis/"; +constexpr std::string_view QaDir = "Collisions/QA/"; +constexpr std::string_view McDir = "Collisions/MC/"; constexpr std::array, kColHistLast> HistTable = { { @@ -79,16 +84,21 @@ constexpr std::array, kColHistLast> HistTable = { {kCentVsMult, o2::framework::kTH2F, "hCentVsMult", "Centrality vs Multiplicity; Centrality (%); Multiplicity"}, {kMultVsSphericity, o2::framework::kTH2F, "hMultVsSphericity", "Multiplicity vs Sphericity; Multiplicity; Sphericity"}, {kCentVsSphericity, o2::framework::kTH2F, "hCentVsSphericity", "Centrality vs Sphericity; Centrality (%); Sphericity"}, + // particle number correlation + {kNpart1VsNpart2, o2::framework::kTH2F, "hNpart1VsNpart2", "# particle 1 vs # particle 2; # particle 1; # particle 2"}, + {kNpart1VsNpart2VsNpart3, o2::framework::kTHnSparseF, "hNpart1VsNpart2VsNpart3", "# particle 1 vs # particle 2 vs particle 3; # particle 1; # particle 2; # particle 3"}, // mc {kTrueCentVsCent, o2::framework::kTH2F, "hTrueCentVsCent", "True centrality vs centrality; Centrality_{True} (%); Centrality (%)"}, {kTrueMultVsMult, o2::framework::kTH2F, "hTrueMultVsMult", "True multiplicity vs multiplicity; Multiplicity_{True}; Multiplicity"}, }}; -#define COL_HIST_ANALYSIS_MAP(conf) \ - {kPosZ, {conf.vtxZ}}, \ - {kMult, {conf.mult}}, \ - {kCent, {conf.cent}}, \ - {kMagField, {conf.magField}}, +#define COL_HIST_ANALYSIS_MAP(conf) \ + {kPosZ, {conf.vtxZ}}, \ + {kMult, {conf.mult}}, \ + {kCent, {conf.cent}}, \ + {kMagField, {conf.magField}}, \ + {kNpart1VsNpart2, {conf.particleCorrelation, conf.particleCorrelation}}, \ + {kNpart1VsNpart2VsNpart3, {conf.particleCorrelation, conf.particleCorrelation, conf.particleCorrelation}}, #define COL_HIST_QA_MAP(confAnalysis, confQa) \ {kPosX, {confQa.vtxXY}}, \ @@ -109,14 +119,14 @@ constexpr std::array, kColHistLast> HistTable = { template auto makeColHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ COL_HIST_ANALYSIS_MAP(confBinningAnalysis)}; } template auto makeColMcHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ COL_HIST_ANALYSIS_MAP(confBinningAnalysis) COL_HIST_MC_MAP(confBinningAnalysis)}; } @@ -124,7 +134,7 @@ auto makeColMcHistSpecMap(const T& confBinningAnalysis) template auto makeColQaHistSpecMap(const T1& confBinningAnalysis, const T2& confBinningQa) { - return std::map>{ + return std::map>{ COL_HIST_ANALYSIS_MAP(confBinningAnalysis) COL_HIST_QA_MAP(confBinningAnalysis, confBinningQa)}; } @@ -132,7 +142,7 @@ auto makeColQaHistSpecMap(const T1& confBinningAnalysis, const T2& confBinningQa template auto makeColMcQaHistSpecMap(const T1& confBinningAnalysis, const T2& confBinningQa) { - return std::map>{ + return std::map>{ COL_HIST_ANALYSIS_MAP(confBinningAnalysis) COL_HIST_QA_MAP(confBinningAnalysis, confBinningQa) COL_HIST_MC_MAP(confBinningAnalysis)}; @@ -148,6 +158,9 @@ struct ConfCollisionBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis mult{"mult", {200, 0, 200}, "Multiplicity binning"}; o2::framework::ConfigurableAxis cent{"cent", {100, 0.0f, 100.0f}, "Centrality (multiplicity percentile) binning"}; o2::framework::ConfigurableAxis magField{"magField", {11, -5.5, 5.5}, "Magnetic field binning"}; + o2::framework::Configurable plotParticlePairCorrelation{"plotParticlePairCorrelation", false, "Plot particle number correlation for pairs"}; + o2::framework::Configurable plotParticleTripletCorrelation{"plotParticleTripletCorrelation", false, "Plot particle number correlation for triplets"}; + o2::framework::ConfigurableAxis particleCorrelation{"particleCorrelation", {6, -0.5f, 5.5f}, "Binning for particle number correlation of pairs/triplets"}; }; struct ConfCollisionQaBinning : o2::framework::ConfigurableGroup { @@ -165,10 +178,14 @@ class CollisionHistManager CollisionHistManager() = default; ~CollisionHistManager() = default; - template - void init(o2::framework::HistogramRegistry* registry, std::map> const& Specs) + template + void init(o2::framework::HistogramRegistry* registry, + std::map> const& Specs, + T const& ConfCollisionBinning) { mHistogramRegistry = registry; + mPlotPairCorrelation = ConfCollisionBinning.plotParticlePairCorrelation.value; + mPlotTripletCorrelation = ConfCollisionBinning.plotParticleTripletCorrelation.value; if constexpr (isFlagSet(mode, modes::Mode::kAnalysis)) { initAnalysis(Specs); } @@ -186,18 +203,21 @@ class CollisionHistManager mPlot2d = ConfBinningQa.plot2d.value; } - template - void init(o2::framework::HistogramRegistry* registry, std::map> const& Specs, T const& ConfBinningQa) + template + void init(o2::framework::HistogramRegistry* registry, + std::map> const& Specs, + T1 const& ConfCollisionBinning, + T2 const& ConfBinningQa) { enableOptionalHistograms(ConfBinningQa); - this->template init(registry, Specs); + init(registry, Specs, ConfCollisionBinning); } template - void fill(T const& col) + void fill(T const& col, int64_t nSlice1, int64_t nSlice2, int64_t nSlice3) { if constexpr (isFlagSet(mode, modes::Mode::kAnalysis)) { - fillAnalysis(col); + fillAnalysis(col, nSlice1, nSlice2, nSlice3); } if constexpr (isFlagSet(mode, modes::Mode::kQa)) { fillQa(col); @@ -205,10 +225,10 @@ class CollisionHistManager } template - void fill(T1 const& col, T2 const& mcCols) + void fill(T1 const& col, T2 const& mcCols, int64_t nSlice1, int64_t nSlice2, int64_t nSlice3) { if constexpr (isFlagSet(mode, modes::Mode::kAnalysis)) { - fillAnalysis(col); + fillAnalysis(col, nSlice1, nSlice2, nSlice3); } if constexpr (isFlagSet(mode, modes::Mode::kQa)) { fillQa(col); @@ -221,16 +241,22 @@ class CollisionHistManager private: void initAnalysis(std::map> const& Specs) { - std::string analysisDir = std::string(ColAnalysisDir); + std::string analysisDir = std::string(AnalysisDir); mHistogramRegistry->add(analysisDir + getHistNameV2(kPosZ, HistTable), getHistDesc(kPosZ, HistTable), getHistType(kPosZ, HistTable), {Specs.at(kPosZ)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kMult, HistTable), getHistDesc(kMult, HistTable), getHistType(kMult, HistTable), {Specs.at(kMult)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kCent, HistTable), getHistDesc(kCent, HistTable), getHistType(kCent, HistTable), {Specs.at(kCent)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kMagField, HistTable), getHistDesc(kMagField, HistTable), getHistType(kMagField, HistTable), {Specs.at(kMagField)}); + if (mPlotPairCorrelation) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kNpart1VsNpart2, HistTable), getHistDesc(kNpart1VsNpart2, HistTable), getHistType(kNpart1VsNpart2, HistTable), {Specs.at(kNpart1VsNpart2)}); + } + if (mPlotTripletCorrelation) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kNpart1VsNpart2VsNpart3, HistTable), getHistDesc(kNpart1VsNpart2VsNpart3, HistTable), getHistType(kNpart1VsNpart2VsNpart3, HistTable), {Specs.at(kNpart1VsNpart2VsNpart3)}); + } } void initQa(std::map> const& Specs) { - std::string qaDir = std::string(ColQaDir); + std::string qaDir = std::string(QaDir); mHistogramRegistry->add(qaDir + getHistNameV2(kPosX, HistTable), getHistDesc(kPosX, HistTable), getHistType(kPosX, HistTable), {Specs.at(kPosX)}); mHistogramRegistry->add(qaDir + getHistNameV2(kPosY, HistTable), getHistDesc(kPosY, HistTable), getHistType(kPosY, HistTable), {Specs.at(kPosY)}); mHistogramRegistry->add(qaDir + getHistNameV2(kPos, HistTable), getHistDesc(kPos, HistTable), getHistType(kPos, HistTable), {Specs.at(kPos)}); @@ -247,34 +273,40 @@ class CollisionHistManager void initMc(std::map> const& Specs) { - std::string mcDir = std::string(ColMcDir); + std::string mcDir = std::string(McDir); mHistogramRegistry->add(mcDir + getHistNameV2(kTrueMultVsMult, HistTable), getHistDesc(kTrueMultVsMult, HistTable), getHistType(kTrueMultVsMult, HistTable), {Specs.at(kTrueMultVsMult)}); mHistogramRegistry->add(mcDir + getHistNameV2(kTrueCentVsCent, HistTable), getHistDesc(kTrueCentVsCent, HistTable), getHistType(kTrueCentVsCent, HistTable), {Specs.at(kTrueCentVsCent)}); } template - void fillAnalysis(T const& col) + void fillAnalysis(T const& col, size_t nSlice1, size_t nSlice2, size_t nSlice3) { - mHistogramRegistry->fill(HIST(ColAnalysisDir) + HIST(getHistName(kPosZ, HistTable)), col.posZ()); - mHistogramRegistry->fill(HIST(ColAnalysisDir) + HIST(getHistName(kMult, HistTable)), col.mult()); - mHistogramRegistry->fill(HIST(ColAnalysisDir) + HIST(getHistName(kCent, HistTable)), col.cent()); - mHistogramRegistry->fill(HIST(ColAnalysisDir) + HIST(getHistName(kMagField, HistTable)), col.magField()); + mHistogramRegistry->fill(HIST(AnalysisDir) + HIST(getHistName(kPosZ, HistTable)), col.posZ()); + mHistogramRegistry->fill(HIST(AnalysisDir) + HIST(getHistName(kMult, HistTable)), col.mult()); + mHistogramRegistry->fill(HIST(AnalysisDir) + HIST(getHistName(kCent, HistTable)), col.cent()); + mHistogramRegistry->fill(HIST(AnalysisDir) + HIST(getHistName(kMagField, HistTable)), col.magField()); + if (mPlotPairCorrelation) { + mHistogramRegistry->fill(HIST(AnalysisDir) + HIST(getHistName(kNpart1VsNpart2, HistTable)), nSlice1, nSlice2); + } + if (mPlotTripletCorrelation) { + mHistogramRegistry->fill(HIST(AnalysisDir) + HIST(getHistName(kNpart1VsNpart2VsNpart3, HistTable)), nSlice1, nSlice2, nSlice3); + } } template void fillQa(T const& col) { - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kPosX, HistTable)), col.posX()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kPosY, HistTable)), col.posY()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kPos, HistTable)), std::hypot(col.posX(), col.posY(), col.posZ())); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kSphericity, HistTable)), col.sphericity()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kOccupancy, HistTable)), col.trackOccupancyInTimeRange()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kPosX, HistTable)), col.posX()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kPosY, HistTable)), col.posY()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kPos, HistTable)), std::hypot(col.posX(), col.posY(), col.posZ())); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kSphericity, HistTable)), col.sphericity()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kOccupancy, HistTable)), col.trackOccupancyInTimeRange()); if (mPlot2d) { - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kPoszVsMult, HistTable)), col.posZ(), col.mult()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kPoszVsCent, HistTable)), col.posZ(), col.cent()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kCentVsMult, HistTable)), col.cent(), col.mult()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kMultVsSphericity, HistTable)), col.mult(), col.sphericity()); - mHistogramRegistry->fill(HIST(ColQaDir) + HIST(getHistName(kCentVsSphericity, HistTable)), col.cent(), col.sphericity()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kPoszVsMult, HistTable)), col.posZ(), col.mult()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kPoszVsCent, HistTable)), col.posZ(), col.cent()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kCentVsMult, HistTable)), col.cent(), col.mult()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kMultVsSphericity, HistTable)), col.mult(), col.sphericity()); + mHistogramRegistry->fill(HIST(QaDir) + HIST(getHistName(kCentVsSphericity, HistTable)), col.cent(), col.sphericity()); } } @@ -285,12 +317,14 @@ class CollisionHistManager return; } auto mcCol = col.template fMcCol_as(); - mHistogramRegistry->fill(HIST(ColMcDir) + HIST(getHistName(kTrueMultVsMult, HistTable)), mcCol.mult(), col.mult()); - mHistogramRegistry->fill(HIST(ColMcDir) + HIST(getHistName(kTrueCentVsCent, HistTable)), mcCol.cent(), col.cent()); + mHistogramRegistry->fill(HIST(McDir) + HIST(getHistName(kTrueMultVsMult, HistTable)), mcCol.mult(), col.mult()); + mHistogramRegistry->fill(HIST(McDir) + HIST(getHistName(kTrueCentVsCent, HistTable)), mcCol.cent(), col.cent()); } o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; - bool mPlot2d = true; + bool mPlot2d = false; + bool mPlotPairCorrelation = false; + bool mPlotTripletCorrelation = false; }; // namespace femtounitedcolhistmanager }; // namespace colhistmanager }; // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/femtoUtils.h b/PWGCF/Femto/Core/femtoUtils.h index abd53f2bc75..1da7fde8635 100644 --- a/PWGCF/Femto/Core/femtoUtils.h +++ b/PWGCF/Femto/Core/femtoUtils.h @@ -16,24 +16,19 @@ #ifndef PWGCF_FEMTO_CORE_FEMTOUTILS_H_ #define PWGCF_FEMTO_CORE_FEMTOUTILS_H_ -#include "RecoDecay.h" +#include -#include "Common/Core/TableHelper.h" +#include +#include +#include -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/InitContext.h" - -#include "TPDGCode.h" - -#include "fairlogger/Logger.h" +#include #include +#include #include -#include #include #include -#include namespace o2::analysis::femto { @@ -63,55 +58,16 @@ float itsSignal(T const& track) auto clSizeLayer6 = (clsizeflag >> (6 * 4)) & 0xf; int numLayers = 7; int sumClusterSizes = clSizeLayer0 + clSizeLayer1 + clSizeLayer2 + clSizeLayer3 + clSizeLayer4 + clSizeLayer5 + clSizeLayer6; - float cosLamnda = 1. / std::cosh(track.eta()); - return (static_cast(sumClusterSizes) / numLayers) * cosLamnda; + double cosLamnda = 1. / std::cosh(track.eta()); + double signal = (static_cast(sumClusterSizes) / numLayers) * cosLamnda; + return static_cast(signal); }; -template -float sphericity(T const& tracks) -{ - - int minNumberTracks = 2; - float maxSphericity = 2.f; - - if (tracks.size() <= minNumberTracks) { - return maxSphericity; - } - - // Initialize the transverse momentum tensor components - float sxx = 0.f; - float syy = 0.f; - float sxy = 0.f; - float sumPt = 0.f; - - // Loop over the tracks to compute the tensor components - for (const auto& track : tracks) { - sxx += (track.px() * track.px()) / track.pt(); - syy += (track.py() * track.py()) / track.pt(); - sxy += (track.px() * track.py()) / track.pt(); - sumPt += track.pt(); - } - sxx /= sumPt; - syy /= sumPt; - sxy /= sumPt; - - // Compute the eigenvalues (real values) - float lambda1 = ((sxx + syy) + std::sqrt((sxx + syy) * (sxx + syy) - 4 * (sxx * syy - sxy * sxy))) / 2; - float lambda2 = ((sxx + syy) - std::sqrt((sxx + syy) * (sxx + syy) - 4 * (sxx * syy - sxy * sxy))) / 2; - - if (lambda1 <= 0.f || lambda2 <= 0.f) { - return maxSphericity; - } - - // Compute sphericity - return 2.f * lambda2 / (lambda1 + lambda2); -} - -inline float getMass(int pdgCode) +inline double getPdgMass(int pdgCode) { // use this function instead of TDatabasePDG to return masses defined in the PhysicsConstants.h header // this approach saves a lot of memory and important partilces like deuteron are missing in TDatabasePDG anyway - float mass = 0.f; + double mass = 0.f; // add new particles if necessary here switch (std::abs(pdgCode)) { case kPiPlus: @@ -163,7 +119,7 @@ inline float getMass(int pdgCode) mass = o2::constants::physics::MassOmegaMinus; break; default: - LOG(fatal) << "PDG code is not suppored"; + LOG(warn) << "PDG code is not suppored. Return 0..."; } return mass; } @@ -175,13 +131,62 @@ float qn(T const& col) return qn; } -inline std::optional dphistar(float magfield, float radius, float signedPt, float phi) +/// Recalculate pT for Kinks (Sigmas) using kinematic constraints +inline float calcPtnew(float pxMother, float pyMother, float pzMother, float pxDaughter, float pyDaughter, float pzDaughter) { - float arg = 0.3f * (0.1f * magfield) * (0.01 * radius) / (2.f * signedPt); - if (std::fabs(arg) <= 1.f) { - return RecoDecay::constrainAngle(phi - std::asin(arg)); - } - return std::nullopt; + float almost0 = 1e-6f; + // Particle masses in GeV/c^2 + auto massPion = o2::constants::physics::MassPionCharged; + auto massNeutron = o2::constants::physics::MassNeutron; + auto massSigmaMinus = o2::constants::physics::MassSigmaMinus; + + // Calculate mother momentum and direction versor + float pMother = std::sqrt(pxMother * pxMother + pyMother * pyMother + pzMother * pzMother); + if (pMother < almost0) + return -999.f; + + float versorX = pxMother / pMother; + float versorY = pyMother / pMother; + float versorZ = pzMother / pMother; + + // Calculate daughter energy + float ePi = std::sqrt(massPion * massPion + pxDaughter * pxDaughter + pyDaughter * pyDaughter + pzDaughter * pzDaughter); + + // Scalar product of versor with daughter momentum + float scalarProduct = versorX * pxDaughter + versorY * pyDaughter + versorZ * pzDaughter; + + // Solve quadratic equation for momentum magnitude + float k = massSigmaMinus * massSigmaMinus + massPion * massPion - massNeutron * massNeutron; + float a = 4.f * (ePi * ePi - scalarProduct * scalarProduct); + float b = -4.f * scalarProduct * k; + float c = 4.f * ePi * ePi * massSigmaMinus * massSigmaMinus - k * k; + + if (std::abs(a) < almost0) + return -999.f; + + float d = b * b - 4.f * a * c; + if (d < 0.f) + return -999.f; + + float sqrtD = std::sqrt(d); + float p1 = (-b + sqrtD) / (2.f * a); + float p2 = (-b - sqrtD) / (2.f * a); + + // Pick physical solution: prefer P2 if positive, otherwise P1 + if (p2 < 0.f && p1 < 0.f) + return -999.f; + if (p2 < 0.f) + return p1; + + // Choose solution closest to original momentum + float p1Diff = std::abs(p1 - pMother); + float p2Diff = std::abs(p2 - pMother); + float p = (p1Diff < p2Diff) ? p1 : p2; + + // Calculate pT from recalibrated momentum + float pxS = versorX * p; + float pyS = versorY * p; + return std::sqrt(pxS * pxS + pyS * pyS); } inline bool enableTable(const char* tableName, int userSetting, o2::framework::InitContext& initContext) @@ -201,11 +206,16 @@ inline bool enableTable(const char* tableName, int userSetting, o2::framework::I return required; } -template -using HasMass = decltype(std::declval().mass()); +// template +// using HasMass = decltype(std::declval().mass()); +// +// template +// using HasSign = decltype(std::declval().sign()); template -using HasSign = decltype(std::declval().sign()); +concept HasMass = requires(T t) { + { t.mass() } -> std::convertible_to; // or double, whatever mass() returns +}; template inline int signum(T x) diff --git a/PWGCF/Femto/Core/histManager.h b/PWGCF/Femto/Core/histManager.h index 19b1b0ce502..ceadf18f38a 100644 --- a/PWGCF/Femto/Core/histManager.h +++ b/PWGCF/Femto/Core/histManager.h @@ -16,7 +16,7 @@ #ifndef PWGCF_FEMTO_CORE_HISTMANAGER_H_ #define PWGCF_FEMTO_CORE_HISTMANAGER_H_ -#include "Framework/HistogramSpec.h" +#include #include #include diff --git a/PWGCF/Femto/Core/kinkBuilder.h b/PWGCF/Femto/Core/kinkBuilder.h index 2e427f79287..728197f049f 100644 --- a/PWGCF/Femto/Core/kinkBuilder.h +++ b/PWGCF/Femto/Core/kinkBuilder.h @@ -24,13 +24,13 @@ #include "PWGCF/Femto/Core/selectionContainer.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Common/Core/RecoDecay.h" +#include -#include "CommonConstants/MathConstants.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" - -#include "fairlogger/Logger.h" +#include +#include +#include +#include +#include #include #include @@ -307,9 +307,19 @@ class KinkSelection : public BaseSelection momMother = {kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}; - mKinkMotherPt = RecoDecay::pt(momMother); + std::array momDaughter = {kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}; + mKinkMotherEta = RecoDecay::eta(momMother); mKinkMotherPhi = RecoDecay::phi(momMother); + + // Recalculate pT using kinematic constraints + float ptRecalc = utils::calcPtnew(momMother[0], momMother[1], momMother[2], + momDaughter[0], momDaughter[1], momDaughter[2]); + if (ptRecalc > 0.f) { + mKinkMotherPt = ptRecalc; + } else { + mKinkMotherPt = -1.f; + } } template @@ -401,7 +411,7 @@ class KinkBuilder { if constexpr (modes::isEqual(kinkType, modes::Kink::kSigma)) { LOG(info) << "Initialize femto Sigma builder..."; - mProduceSigmas = utils::enableTable("FSigmas_001", table.produceSigmas.value, initContext); + mProduceSigmas = utils::enableTable("FSigmas_002", table.produceSigmas.value, initContext); mProduceSigmaMasks = utils::enableTable("FSigmaMasks_001", table.produceSigmaMasks.value, initContext); mProduceSigmaExtras = utils::enableTable("FSigmaExtras_001", table.produceSigmaExtras.value, initContext); } @@ -510,11 +520,12 @@ class KinkBuilder template void fillSigma(T1& collisionProducts, T2& kinkProducts, T3 const& kink, int64_t daughterIndex) { + // Mass is calculated from original momentum components stored in kink table float mass = kink.mSigmaMinus(); if (mProduceSigmas) { kinkProducts.producedSigmas(collisionProducts.producedCollision.lastIndex(), - kink.mothSign() * mKinkSelection.getKinkMotherPt(), + kink.mothSign() * mKinkSelection.getKinkMotherPt(), // Recalculated pT mKinkSelection.getKinkMotherEta(), mKinkSelection.getKinkMotherPhi(), mass, @@ -538,11 +549,12 @@ class KinkBuilder template void fillSigmaPlus(T1& collisionProducts, T2& kinkProducts, T3 const& kink, int64_t daughterIndex) { + // Mass is calculated from original momentum components stored in kink table float mass = kink.mSigmaPlus(); if (mProduceSigmaPlus) { kinkProducts.producedSigmaPlus(collisionProducts.producedCollision.lastIndex(), - kink.mothSign() * mKinkSelection.getKinkMotherPt(), + kink.mothSign() * mKinkSelection.getKinkMotherPt(), // Recalculated pT mKinkSelection.getKinkMotherEta(), mKinkSelection.getKinkMotherPhi(), mass, @@ -576,6 +588,103 @@ class KinkBuilder bool mProduceSigmaPlusExtras = false; }; +struct ConfKinkTablesDerivedToDerived : o2::framework::ConfigurableGroup { + std::string prefix = std::string("KinkTables"); + o2::framework::Configurable limitSigma{"limitSigma", 1, "At least this many sigmas need to be in the collision"}; + o2::framework::Configurable limitSigmaPlus{"limitSigmaPlus", 0, "At least this many sigma pluses need to be in the collision"}; +}; + +struct KinkBuilderDerivedToDerivedProducts : o2::framework::ProducesGroup { + o2::framework::Produces producedSigmas; + o2::framework::Produces producedSigmaMasks; + o2::framework::Produces producedSigmaPluses; + o2::framework::Produces producedSigmaPlusMasks; +}; + +class KinkBuilderDerivedToDerived +{ + public: + KinkBuilderDerivedToDerived() = default; + ~KinkBuilderDerivedToDerived() = default; + + template + void init(T& config) + { + mLimitSigma = config.limitSigma.value; + mLimitSigmaPlus = config.limitSigmaPlus.value; + + if (mLimitSigma == 0 && mLimitSigmaPlus == 0) { + LOG(fatal) << "Both sigma limit and sigmaplus limit are 0. Breaking..."; + } + } + + template + bool collisionHasTooFewSigma(T1 const& col, T2 const& /*sigmaTable*/, T3& partitionSigma, T4& cache) + { + auto sigmaSlice = partitionSigma->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (sigmaSlice.size() >= mLimitSigma) { + return false; + } + return true; + } + + template + bool collisionHasTooFewSigmaPlus(T1 const& col, T2 const& /*sigmaPlusTable*/, T3& partitionSigmaPlus, T4& cache) + { + auto sigmaPlusSlice = partitionSigmaPlus->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (sigmaPlusSlice.size() >= mLimitSigmaPlus) { + return false; + } + return true; + } + + template + void processSigma(T1 const& col, T2 const& /*sigmaTable*/, T3 const& oldTrackTable, T4& partitionSigma, T5& trackBuilder, T6& cache, T7& newSigmaTable, T8& newTrackTable, T9& newCollisionTable) + { + auto sigmaSlice = partitionSigma->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + + for (auto const& sigma : sigmaSlice) { + + auto chaDaughter = oldTrackTable.rawIteratorAt(sigma.chaDauId() - oldTrackTable.offset()); + + int chaDaughterIndex = trackBuilder.getDaughterIndex(chaDaughter, newTrackTable, newCollisionTable); + + newSigmaTable.producedSigmas(newCollisionTable.producedCollision.lastIndex(), + sigma.signedPt(), + sigma.eta(), + sigma.phi(), + sigma.mass(), + chaDaughterIndex); + newSigmaTable.producedSigmaMasks(sigma.mask()); + } + } + + template + void processSigmaPlus(T1 const& col, T2 const& /*sigmaPlusTable*/, T3 const& oldTrackTable, T4& partitionSigmaPlus, T5& trackBuilder, T6& cache, T7& newSigmaPlusTable, T8& newTrackTable, T9& newCollisionTable) + { + auto sigmaPlusSlice = partitionSigmaPlus->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + + for (auto const& sigmaPlus : sigmaPlusSlice) { + + auto chaDaughter = oldTrackTable.rawIteratorAt(sigmaPlus.chaDauId() - oldTrackTable.offset()); + + int chaDaughterIndex = trackBuilder.getDaughterIndex(chaDaughter, newTrackTable, newCollisionTable); + + newSigmaPlusTable.producedSigmaPluses(newCollisionTable.producedCollision.lastIndex(), + sigmaPlus.signedPt(), + sigmaPlus.eta(), + sigmaPlus.phi(), + sigmaPlus.mass(), + chaDaughterIndex); + newSigmaPlusTable.producedSigmaPlusMasks(sigmaPlus.mask()); + } + } + + private: + int mLimitSigma = 0; + int mLimitSigmaPlus = 0; +}; + } // namespace kinkbuilder } // namespace o2::analysis::femto #endif // PWGCF_FEMTO_CORE_KINKBUILDER_H_ diff --git a/PWGCF/Femto/Core/kinkHistManager.h b/PWGCF/Femto/Core/kinkHistManager.h index 6a3c00c189a..b3f27e3f4e0 100644 --- a/PWGCF/Femto/Core/kinkHistManager.h +++ b/PWGCF/Femto/Core/kinkHistManager.h @@ -21,12 +21,17 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/trackHistManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include +#include +#include + +#include +#include #include +#include #include #include #include @@ -210,30 +215,30 @@ constexpr std::array, kKinkHistLast> HistTable = template auto makeKinkHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ KINK_HIST_ANALYSIS_MAP(confBinningAnalysis)}; } template auto makeKinkMcHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ KINK_HIST_ANALYSIS_MAP(confBinningAnalysis) KINK_HIST_MC_MAP(confBinningAnalysis)}; } template -std::map> makeKinkQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) +std::map> makeKinkQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ + return std::map>{ KINK_HIST_ANALYSIS_MAP(confBinningAnalysis) KINK_HIST_QA_MAP(confBinningAnalysis, confBinningQa)}; } template -std::map> makeKinkMcQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) +std::map> makeKinkMcQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ + return std::map>{ KINK_HIST_ANALYSIS_MAP(confBinningAnalysis) KINK_HIST_QA_MAP(confBinningAnalysis, confBinningQa) KINK_HIST_MC_MAP(confBinningAnalysis) @@ -252,7 +257,7 @@ constexpr char PrefixSigmaPlusQa[] = "SigmaPlusQA/"; constexpr char PrefixSigmaPlus1[] = "SigmaPlus1/"; constexpr char PrefixSigmaPlus2[] = "SigmaPlus2/"; -constexpr std::string_view AnalysisDir = "Kinematics/"; +constexpr std::string_view AnalysisDir = "Analysis/"; constexpr std::string_view QaDir = "QA/"; constexpr std::string_view McDir = "MC/"; @@ -450,7 +455,7 @@ class KinkHistManager mHistogramRegistry->add(mcDir + getHistNameV2(kTruePhi, HistTable), getHistDesc(kTruePhi, HistTable), getHistType(kTruePhi, HistTable), {KinkSpecs.at(kTruePhi)}); // mc origin can be configured here - const framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; + const o2::framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; mHistogramRegistry->add(mcDir + getHistNameV2(kOrigin, HistTable), getHistDesc(kOrigin, HistTable), getHistType(kOrigin, HistTable), {axisOrigin}); mHistogramRegistry->get(HIST(kinkPrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kNoMcParticle), modes::mcOriginToString(modes::McOrigin::kNoMcParticle)); mHistogramRegistry->get(HIST(kinkPrefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kFromWrongCollision), modes::mcOriginToString(modes::McOrigin::kFromWrongCollision)); diff --git a/PWGCF/Femto/Core/mcBuilder.h b/PWGCF/Femto/Core/mcBuilder.h index bf4f023f78d..30f6210c027 100644 --- a/PWGCF/Femto/Core/mcBuilder.h +++ b/PWGCF/Femto/Core/mcBuilder.h @@ -21,10 +21,11 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" +#include +#include +#include -#include "fairlogger/Logger.h" +#include #include #include @@ -40,6 +41,7 @@ namespace mcbuilder struct ConfMc : o2::framework::ConfigurableGroup { std::string prefix = std::string("MonteCarlo"); o2::framework::Configurable passThrough{"passThrough", false, "Passthrough all MC collisions and particles"}; + o2::framework::Configurable findLastPartonicMother{"findLastPartonicMother", true, "If true, the partonic mother will be the first parton directly after the initial collision. If false, the partonic mother will be the last parton before hadronization"}; }; struct McBuilderProducts : o2::framework::ProducesGroup { @@ -54,6 +56,8 @@ struct McBuilderProducts : o2::framework::ProducesGroup { o2::framework::Produces producedK0shortLabels; o2::framework::Produces producedSigmaLabels; o2::framework::Produces producedSigmaPlusLabels; + o2::framework::Produces producedXiLabels; + o2::framework::Produces producedOmegaLabels; }; struct ConfMcTables : o2::framework::ConfigurableGroup { @@ -69,6 +73,8 @@ struct ConfMcTables : o2::framework::ConfigurableGroup { o2::framework::Configurable producedK0shortLabels{"producedK0shortLabels", -1, "Produce k0short labels (-1: auto; 0 off; 1 on)"}; o2::framework::Configurable producedSigmaLabels{"producedSigmaLabels", -1, "Produce k0short labels (-1: auto; 0 off; 1 on)"}; o2::framework::Configurable producedSigmaPlusLabels{"producedSigmaPlusLabels", -1, "Produce k0short labels (-1: auto; 0 off; 1 on)"}; + o2::framework::Configurable producedXiLabels{"producedXiLabels", -1, "Produce xi labels (-1: auto; 0 off; 1 on)"}; + o2::framework::Configurable producedOmegaLabels{"producedOmegaLabels", -1, "Produce omega labels (-1: auto; 0 off; 1 on)"}; }; class McBuilder @@ -93,8 +99,15 @@ class McBuilder mProduceK0shortLabels = utils::enableTable("FK0shortLabels", table.producedK0shortLabels.value, initContext); mProduceSigmaLabels = utils::enableTable("FSigmaLabels", table.producedSigmaLabels.value, initContext); mProduceSigmaPlusLabels = utils::enableTable("FSigmaPlusLabels", table.producedSigmaPlusLabels.value, initContext); - - if (mProduceMcCollisions || mProduceMcParticles || mProduceMcMothers || mProduceMcPartonicMothers || mProduceCollisionLabels || mProduceTrackLabels || mProduceLambdaLabels || mProduceK0shortLabels) { + mProduceXiLabels = utils::enableTable("FXiLabels", table.producedXiLabels.value, initContext); + mProduceOmegaLabels = utils::enableTable("FOmegaLabels", table.producedOmegaLabels.value, initContext); + + if (mProduceMcCollisions || mProduceCollisionLabels || + mProduceMcParticles || mProduceMcMothers || mProduceMcPartonicMothers || + mProduceTrackLabels || + mProduceLambdaLabels || mProduceK0shortLabels || + mProduceSigmaLabels || mProduceSigmaPlusLabels || + mProduceXiLabels || mProduceOmegaLabels) { mFillAnyTable = true; } else { LOG(info) << "No tables configured..."; @@ -102,6 +115,7 @@ class McBuilder return; } mPassThrough = config.passThrough.value; + mFindLastPartonicMother = config.findLastPartonicMother.value; LOG(info) << "Initialization done..."; } @@ -125,7 +139,7 @@ class McBuilder // Add label mcProducts.producedCollisionLabels(it->second); } else { - // Case: No MC collision associated + // If no MC collision associated, fill empty label mcProducts.producedCollisionLabels(-1); } } @@ -178,14 +192,39 @@ class McBuilder fillMcLabelGeneric(col, mcCols, sigmaPlusDaughter, mcParticles, mcProducts, [](auto& prod, int64_t p, int64_t m, int64_t pm) { prod.producedSigmaPlusLabels(p, m, pm); }, true); } + template + void fillMcXiWithLabel(T1 const& col, T2 const& mcCols, T3 const& xi, T4 const& mcParticles, T5& mcProducts) + { + if (!mProduceXiLabels) { + mcProducts.producedXiLabels(-1, -1, -1); + return; + } + fillMcLabelGeneric(col, mcCols, xi, mcParticles, mcProducts, [](auto& prod, int64_t p, int64_t m, int64_t pm) { prod.producedXiLabels(p, m, pm); }); + } + + template + void fillMcOmegaWithLabel(T1 const& col, T2 const& mcCols, T3 const& omega, T4 const& mcParticles, T5& mcProducts) + { + if (!mProduceOmegaLabels) { + mcProducts.producedOmegaLabels(-1, -1, -1); + return; + } + fillMcLabelGeneric(col, mcCols, omega, mcParticles, mcProducts, [](auto& prod, int64_t p, int64_t m, int64_t pm) { prod.producedOmegaLabels(p, m, pm); }); + } + bool fillAnyTable() const { return mFillAnyTable; } - void reset() + template + void reset(T1 const& mcCollisions, T2 const& mcParticles) { mCollisionMap.clear(); + mCollisionMap.reserve(mcCollisions.size()); mMcParticleMap.clear(); + mMcParticleMap.reserve(mcParticles.size()); mMcMotherMap.clear(); + mMcMotherMap.reserve(mcParticles.size()); mMcPartonicMotherMap.clear(); + mMcPartonicMotherMap.reserve(mcParticles.size()); } private: @@ -304,7 +343,12 @@ class McBuilder // Partonic mother int64_t mcPartonicMotherRow = -1; - auto mcPartonicMotherIndex = this->findFirstPartonicMother(mcParticle, mcParticles); + int64_t mcPartonicMotherIndex = -1; + if (mFindLastPartonicMother) { + mcPartonicMotherIndex = this->findLastPartonicMother(mcParticle, mcParticles); + } else { + mcPartonicMotherIndex = this->findFirstPartonicMother(mcParticle, mcParticles); + } if (mcPartonicMotherIndex >= 0) { auto itPM = mMcPartonicMotherMap.find(mcPartonicMotherIndex); if (itPM != mMcPartonicMotherMap.end()) { @@ -321,14 +365,12 @@ class McBuilder } template - int findFirstPartonicMother(const T1& mcParticle, const T2& mcParticles) + int64_t findFirstPartonicMother(const T1& mcParticle, const T2& mcParticles) { if (!mcParticle.has_mothers()) { return -1; } - auto motherIds = mcParticle.mothersIds(); - // adapted these checks from MCUtils in PWGEM const int defaultMotherSize = 2; std::vector allMotherIds; @@ -343,32 +385,69 @@ class McBuilder for (const int& id : motherIds) allMotherIds.push_back(id); } - // Loop over all mothers for (const int& i : allMotherIds) { if (i < 0 || i >= mcParticles.size()) continue; - const auto& mother = mcParticles.iteratorAt(i); int pdgAbs = std::abs(mother.pdgCode()); - // Is it a parton? (quark or gluon) if (pdgAbs <= PDG_t::kTop || pdgAbs == PDG_t::kGluon) { return i; // Found a parton → return index } - // Recurse upward - int found = this->findFirstPartonicMother(mother, mcParticles); + int64_t found = this->findFirstPartonicMother(mother, mcParticles); if (found != -1) return found; } - // No partonic ancestor found return -1; } + template + int64_t findLastPartonicMother(const T1& mcParticle, const T2& mcParticles) + { + int64_t lastPartonIndex = -1; + int64_t currentIndex = mcParticle.globalIndex(); + while (currentIndex >= 0 && currentIndex < mcParticles.size()) { + const auto& current = mcParticles.iteratorAt(currentIndex); + if (!current.has_mothers()) + break; + auto motherIds = current.mothersIds(); + int nextIndex = -1; + const int defaultMotherSize = 2; + if (motherIds.size() == defaultMotherSize && motherIds[1] > motherIds[0]) { + nextIndex = motherIds[0]; + } else { + for (const int& id : motherIds) { + if (id >= 0 && id < mcParticles.size()) { + nextIndex = id; + break; + } + } + } + if (nextIndex < 0 || nextIndex >= mcParticles.size()) + break; + const auto& mother = mcParticles.iteratorAt(nextIndex); + int pdgAbs = std::abs(mother.pdgCode()); + int status = std::abs(o2::mcgenstatus::getGenStatusCode(mother.statusCode())); + bool isParton = (pdgAbs <= PDG_t::kTop || pdgAbs == PDG_t::kGluon); + const int isBeamParticleLowerLimit = 11; + const int isBeamParticleUpperLimit = 19; + bool isBeam = (status >= isBeamParticleLowerLimit && status <= isBeamParticleUpperLimit); + if (isBeam) + return lastPartonIndex; + if (isParton) + lastPartonIndex = nextIndex; + + currentIndex = nextIndex; + } + return -1; + } + bool mPassThrough = false; + bool mFindLastPartonicMother = false; bool mFillAnyTable = false; bool mProduceMcCollisions = false; bool mProduceMcParticles = false; @@ -381,6 +460,8 @@ class McBuilder bool mProduceK0shortLabels = false; bool mProduceSigmaLabels = false; bool mProduceSigmaPlusLabels = false; + bool mProduceXiLabels = false; + bool mProduceOmegaLabels = false; std::unordered_map mCollisionMap; diff --git a/PWGCF/Femto/Core/modes.h b/PWGCF/Femto/Core/modes.h index bf337fab232..45c0db54f63 100644 --- a/PWGCF/Femto/Core/modes.h +++ b/PWGCF/Femto/Core/modes.h @@ -118,20 +118,6 @@ constexpr const char* mcOriginToString(McOrigin origin) } } -constexpr bool - hasMass(Particle p) -{ - switch (p) { - case Particle::kV0: - case Particle::kTwoTrackResonance: - case Particle::kKink: - case Particle::kCascade: - return true; - default: - return false; - } -} - enum class Track : o2::aod::femtodatatypes::TrackType { kTrack, kV0Daughter, diff --git a/PWGCF/Femto/Core/pairBuilder.h b/PWGCF/Femto/Core/pairBuilder.h index 41d8b8d894b..af6e9aa51bb 100644 --- a/PWGCF/Femto/Core/pairBuilder.h +++ b/PWGCF/Femto/Core/pairBuilder.h @@ -24,15 +24,17 @@ #include "PWGCF/Femto/Core/pairCleaner.h" #include "PWGCF/Femto/Core/pairHistManager.h" #include "PWGCF/Femto/Core/pairProcessHelpers.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/Core/twoTrackResonanceHistManager.h" #include "PWGCF/Femto/Core/v0HistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include -#include "fairlogger/Logger.h" +#include #include #include @@ -45,12 +47,10 @@ namespace o2::analysis::femto namespace pairbuilder { -template +const int64_t nLimitPartitionIdenticalParticles = 2; +const int64_t nLimitPartitionParticles = 1; + +template class PairTrackTrackBuilder { public: @@ -68,30 +68,38 @@ class PairTrackTrackBuilder typename T8, typename T9, typename T10, - typename T11> + typename T11, + typename T12, + typename T13, + typename T14> void init(o2::framework::HistogramRegistry* registry, - T1 const& confTrackSelection1, - T2 const& confTrackSelection2, - T3 const& confCpr, - T4 const& confMixing, - T5 const& confPairBinning, - T6 const& confPairCuts, - std::map> const& colHistSpec, - std::map> const& trackHistSpec1, - std::map> const& trackHistSpec2, - std::map> const& pairHistSpec, - std::map> const& cprHistSpec) + T1 const& confCollisionBinning, + T2 const& confTrackSelection1, + T3 const& confTrackSelection2, + T4 const& confTrackCleaner1, + T5 const& confTrackCleaner2, + T6 const& confCpr, + T7 const& confMixing, + T8 const& confPairBinning, + T9 const& confPairCuts, + std::map> const& colHistSpec, + std::map> const& trackHistSpec1, + std::map> const& trackHistSpec2, + std::map> const& pairHistSpec, + std::map> const& cprHistSpec) { // check if correlate the same tracks or not mSameSpecies = confMixing.sameSpecies.value; - mColHistManager.template init(registry, colHistSpec); + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); mPairHistManagerSe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); mPairHistManagerMe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); mPc.template init(confPairCuts); if (mSameSpecies) { + mTrackCleaner1.init(confTrackCleaner1); + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); mPairHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value); @@ -102,6 +110,8 @@ class PairTrackTrackBuilder mPairHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); mCprMe.init(registry, cprHistSpec, confCpr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); } else { + mTrackCleaner1.init(confTrackCleaner1); + mTrackCleaner2.init(confTrackCleaner2); mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); mTrackHistManager2.template init(registry, trackHistSpec2, confTrackSelection2); @@ -128,6 +138,7 @@ class PairTrackTrackBuilder randomSeed = static_cast(confMixing.seed.value); } mRng = std::mt19937(randomSeed); + mDist = std::uniform_int_distribution(static_cast(pairprocesshelpers::kOrder12), static_cast(pairprocesshelpers::kOrder21)); } } @@ -137,19 +148,23 @@ class PairTrackTrackBuilder { if (mSameSpecies) { auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice1.size() == 0) { + if (trackSlice1.size() < nLimitPartitionIdenticalParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, trackSlice1.size(), trackSlice1.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice1, trackTable, col, mTrackHistManager1, mPairHistManagerSe, mCprSe, mPc, mRng, mMixIdenticalParticles); + pairprocesshelpers::PairOrder pairOrder = pairprocesshelpers::kOrder12; + if (mMixIdenticalParticles) { + pairOrder = static_cast(mDist(mRng)); + } + pairprocesshelpers::processSameEvent(trackSlice1, trackTable, col, mTrackHistManager1, mPairHistManagerSe, mCprSe, mPc, pairOrder); } else { auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice1.size() == 0 || trackSlice2.size() == 0) { + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, trackSlice1.size(), trackSlice2.size(), 0); mCprSe.setMagField(col.magField()); pairprocesshelpers::processSameEvent(trackSlice1, trackSlice2, trackTable, col, mTrackHistManager1, mTrackHistManager2, mPairHistManagerSe, mCprSe, mPc); } @@ -161,21 +176,25 @@ class PairTrackTrackBuilder { if (mSameSpecies) { auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice1.size() == 0) { + if (trackSlice1.size() < nLimitPartitionIdenticalParticles) { return; } - mColHistManager.template fill(col, mcCols); + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice1.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice1, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mPairHistManagerSe, mCprSe, mPc, mRng, mMixIdenticalParticles); + pairprocesshelpers::PairOrder pairOrder = pairprocesshelpers::kOrder12; + if (mMixIdenticalParticles) { + pairOrder = static_cast(mDist(mRng)); + } + pairprocesshelpers::processSameEvent(trackSlice1, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mPairHistManagerSe, mTrackCleaner1, mCprSe, mPc, pairOrder); } else { auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice1.size() == 0 || trackSlice2.size() == 0) { + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col, mcCols); + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice2.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice1, trackSlice2, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTrackHistManager2, mPairHistManagerSe, mCprSe, mPc); + pairprocesshelpers::processSameEvent(trackSlice1, trackSlice2, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTrackHistManager2, mPairHistManagerSe, mTrackCleaner1, mTrackCleaner2, mCprSe, mPc); } } @@ -186,13 +205,13 @@ class PairTrackTrackBuilder if (mSameSpecies) { switch (mMixingPolicy) { case static_cast(pairhistmanager::kVtxMult): - pairprocesshelpers::processMixedEvent(cols, partition1, trackTable, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, partition1, partition1, trackTable, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxCent): - pairprocesshelpers::processMixedEvent(cols, partition1, trackTable, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, partition1, partition1, trackTable, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxMultCent): - pairprocesshelpers::processMixedEvent(cols, partition1, trackTable, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, partition1, partition1, trackTable, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); break; default: LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; @@ -214,19 +233,19 @@ class PairTrackTrackBuilder } } - template - void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6 const& mcParticles, T7& cache, T8& binsVtxMult, T9& binsVtxCent, T10& binsVtxMultCent) + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6 const& mcParticles, T7 const& mcMothers, T8 const& mcPartonicMothers, T9& cache, T10& binsVtxMult, T11& binsVtxCent, T12& binsVtxMultCent) { if (mSameSpecies) { switch (mMixingPolicy) { case static_cast(pairhistmanager::kVtxMult): - pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mTrackCleaner1, mTrackCleaner1, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner1, mTrackCleaner1, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxMultCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner1, mTrackCleaner1, mCprMe, mPc); break; default: LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; @@ -234,13 +253,13 @@ class PairTrackTrackBuilder } else { switch (mMixingPolicy) { case static_cast(pairhistmanager::kVtxMult): - pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mTrackCleaner1, mTrackCleaner2, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner1, mTrackCleaner2, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxMultCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner1, mTrackCleaner2, mCprMe, mPc); break; default: LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; @@ -257,11 +276,14 @@ class PairTrackTrackBuilder closepairrejection::ClosePairRejectionTrackTrack mCprSe; closepairrejection::ClosePairRejectionTrackTrack mCprMe; paircleaner::TrackTrackPairCleaner mPc; - std::mt19937 mRng; + particlecleaner::ParticleCleaner mTrackCleaner1; + particlecleaner::ParticleCleaner mTrackCleaner2; pairhistmanager::MixingPolicy mMixingPolicy = pairhistmanager::MixingPolicy::kVtxMult; - bool mSameSpecies = false; int mMixingDepth = 5; + bool mSameSpecies = false; bool mMixIdenticalParticles = false; + std::mt19937 mRng; + std::uniform_int_distribution<> mDist; }; template + typename T15, + typename T16, + typename T18, + typename T17> void init(o2::framework::HistogramRegistry* registry, - T1 const& confV0Selection1, - T2 const& confV0Selection2, - T3 const& confCprPos, - T4 const& confCprNeg, - T5 const& confMixing, - T6 const& confPairBinning, - T7 const& confPairCuts, - std::map> const& colHistSpec, - std::map> const& V0HistSpec1, - std::map> const& V0HistSpec2, - std::map> const& PosDauHistSpec, - std::map> const& NegDauHistSpec, - std::map> const& pairHistSpec, - std::map> const& cprHistSpecPos, - std::map> const& cprHistSpecNeg) + T1 const& confCollisionBinning, + T2 const& confV0Selection1, + T3 const& confV0Selection2, + T4 const& confV0Cleaner1, + T5 const& confV0Cleaner2, + T6 const& confCprPos, + T7 const& confCprNeg, + T8 const& confMixing, + T9 const& confPairBinning, + T10 const& confPairCuts, + std::map> const& colHistSpec, + std::map> const& V0HistSpec1, + std::map> const& V0HistSpec2, + std::map> const& PosDauHistSpec, + std::map> const& NegDauHistSpec, + std::map> const& pairHistSpec, + std::map> const& cprHistSpecPos, + std::map> const& cprHistSpecNeg) { // check if correlate the same tracks or not mSameSpecies = confMixing.sameSpecies.value; - mColHistManager.template init(registry, colHistSpec); + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); mPairHistManagerSe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); mPairHistManagerMe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); if (mSameSpecies) { + mV0Cleaner1.init(confV0Cleaner1); mV0HistManager1.template init(registry, V0HistSpec1, confV0Selection1, PosDauHistSpec, NegDauHistSpec); mPairHistManagerSe.setMass(confV0Selection1.pdgCodeAbs.value, confV0Selection1.pdgCodeAbs.value); @@ -336,6 +365,8 @@ class PairV0V0Builder mPairHistManagerMe.setCharge(1, 1); mCprMe.init(registry, cprHistSpecPos, cprHistSpecNeg, confCprPos, confCprNeg); } else { + mV0Cleaner1.init(confV0Cleaner1); + mV0Cleaner2.init(confV0Cleaner2); mV0HistManager1.template init(registry, V0HistSpec1, confV0Selection1, PosDauHistSpec, NegDauHistSpec); mV0HistManager2.template init(registry, V0HistSpec2, confV0Selection2, PosDauHistSpec, NegDauHistSpec); @@ -366,42 +397,74 @@ class PairV0V0Builder } template - void processSameEvent(T1 const& col, T2& trackTable, T3& /*lambdaTable*/, T4& partition1, T5& partition2, T6& cache) + void processSameEvent(T1 const& col, T2 const& trackTable, T3& /*v0table*/, T4& partition1, T5& partition2, T6& cache) { if (mSameSpecies) { auto v0Slice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (v0Slice1.size() == 0) { + if (v0Slice1.size() < nLimitPartitionIdenticalParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, v0Slice1.size(), v0Slice1.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(v0Slice1, trackTable, col, mV0HistManager1, mPairHistManagerSe, mCprSe, mPc, mRng, mMixIdenticalParticles); + pairprocesshelpers::PairOrder pairOrder = pairprocesshelpers::kOrder12; + if (mMixIdenticalParticles) { + pairOrder = static_cast(mDist(mRng)); + } + pairprocesshelpers::processSameEvent(v0Slice1, trackTable, col, mV0HistManager1, mPairHistManagerSe, mCprSe, mPc, pairOrder); } else { auto v0Slice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto v0Slice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (v0Slice1.size() == 0 || v0Slice2.size() == 0) { + if (v0Slice1.size() < nLimitPartitionParticles || v0Slice2.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, v0Slice1.size(), v0Slice2.size(), 0); mCprSe.setMagField(col.magField()); pairprocesshelpers::processSameEvent(v0Slice1, v0Slice2, trackTable, col, mV0HistManager1, mV0HistManager2, mPairHistManagerSe, mCprSe, mPc); } } - template - void processMixedEvent(T1 const& cols, T2& trackTable, T3& partition1, T4& partition2, T5& cache, T6& binsVtxMult, T7& binsVtxCent, T8& binsVtxMultCent) + // mc + template + void processSameEvent(T1 const& col, T2 const& mcCols, T3 const& trackTable, T4 const& /*v0table*/, T5& partition1, T6& partition2, T7 const& mcParticles, T8 const& mcMothers, T9 const& mcPartonicMothers, T10& cache) + { + if (mSameSpecies) { + auto v0Slice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (v0Slice1.size() < nLimitPartitionIdenticalParticles) { + return; + } + mColHistManager.template fill(col, mcCols, v0Slice1.size(), v0Slice1.size(), 0); + mCprSe.setMagField(col.magField()); + pairprocesshelpers::PairOrder pairOrder = pairprocesshelpers::kOrder12; + if (mMixIdenticalParticles) { + pairOrder = static_cast(mDist(mRng)); + } + pairprocesshelpers::processSameEvent(v0Slice1, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mV0HistManager1, mPairHistManagerSe, mV0Cleaner1, mCprSe, mPc, pairOrder); + } else { + auto v0Slice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto v0Slice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (v0Slice1.size() < nLimitPartitionParticles || v0Slice2.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols, v0Slice1.size(), v0Slice2.size(), 0); + mCprSe.setMagField(col.magField()); + pairprocesshelpers::processSameEvent(v0Slice1, v0Slice2, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mV0HistManager1, mV0HistManager2, mPairHistManagerSe, mV0Cleaner1, mV0Cleaner2, mCprSe, mPc); + } + } + + template + void processMixedEvent(T1 const& cols, T2 const& trackTable, T3 const& /*v0table*/, T4& partition1, T5& partition2, T6& cache, T7& binsVtxMult, T8& binsVtxCent, T9& binsVtxMultCent) { if (mSameSpecies) { switch (mMixingPolicy) { case static_cast(pairhistmanager::kVtxMult): - pairprocesshelpers::processMixedEvent(cols, partition1, trackTable, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, partition1, partition1, trackTable, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxCent): - pairprocesshelpers::processMixedEvent(cols, partition1, trackTable, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, partition1, partition1, trackTable, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxMultCent): - pairprocesshelpers::processMixedEvent(cols, partition1, trackTable, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, partition1, partition1, trackTable, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); break; default: LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; @@ -423,20 +486,57 @@ class PairV0V0Builder } } + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6 const& mcParticles, T7 const& mcMothers, T8 const& mcPartonicMothers, T9& cache, T10& binsVtxMult, T11& binsVtxCent, T12& binsVtxMultCent) + { + if (mSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mV0Cleaner1, mV0Cleaner1, mCprMe, mPc); + break; + case static_cast(pairhistmanager::kVtxCent): + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mV0Cleaner1, mV0Cleaner1, mCprMe, mPc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mV0Cleaner1, mV0Cleaner1, mCprMe, mPc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mV0Cleaner1, mV0Cleaner2, mCprMe, mPc); + break; + case static_cast(pairhistmanager::kVtxCent): + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mV0Cleaner1, mV0Cleaner2, mCprMe, mPc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + pairprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mV0Cleaner1, mV0Cleaner2, mCprMe, mPc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + private: colhistmanager::CollisionHistManager mColHistManager; v0histmanager::V0HistManager mV0HistManager1; v0histmanager::V0HistManager mV0HistManager2; + particlecleaner::ParticleCleaner mV0Cleaner1; + particlecleaner::ParticleCleaner mV0Cleaner2; pairhistmanager::PairHistManager mPairHistManagerSe; pairhistmanager::PairHistManager mPairHistManagerMe; closepairrejection::ClosePairRejectionV0V0 mCprSe; closepairrejection::ClosePairRejectionV0V0 mCprMe; paircleaner::V0V0PairCleaner mPc; - std::mt19937 mRng; pairhistmanager::MixingPolicy mMixingPolicy = pairhistmanager::MixingPolicy::kVtxMult; bool mSameSpecies = false; int mMixingDepth = 5; bool mMixIdenticalParticles = false; + std::mt19937 mRng; + std::uniform_int_distribution<> mDist; }; template + typename T13, + typename T14, + typename T15, + typename T16> void init(o2::framework::HistogramRegistry* registry, - T1 const& confTrackSelection, - T2 const& confV0Selection, - T3 const& confCpr, - T4 const& confMixing, - T5 const& confPairBinning, - T6 const& confPairCuts, - std::map>& colHistSpec, - std::map>& trackHistSpec, - std::map>& v0HistSpec, - std::map>& posDauHistSpec, - std::map>& negDauHistSpec, - std::map>& pairHistSpec, - std::map>& cprHistSpec) + T1 const& confCollisionBinning, + T2 const& confTrackSelection, + T3 const& confTrackCleaner, + T4 const& confV0Selection, + T5 const& confV0Cleaner, + T6 const& confCpr, + T7 const& confMixing, + T8 const& confPairBinning, + T9 const& confPairCuts, + std::map>& colHistSpec, + std::map>& trackHistSpec, + std::map>& v0HistSpec, + std::map>& posDauHistSpec, + std::map>& negDauHistSpec, + std::map>& pairHistSpec, + std::map>& cprHistSpec) { - mColHistManager.template init(registry, colHistSpec); + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); mTrackHistManager.template init(registry, trackHistSpec, confTrackSelection); mV0HistManager.template init(registry, v0HistSpec, confV0Selection, posDauHistSpec, negDauHistSpec); + mTrackCleaner.init(confTrackCleaner); + mV0Cleaner.init(confV0Cleaner); + + int pdgCodePosDau = 0; + int pdgCodeNegDau = 0; + if (modes::isEqual(v0Type, modes::V0::kK0short)) { + pdgCodeNegDau = kPiPlus; + pdgCodeNegDau = kPiMinus; + } else if (modes::isEqual(v0Type, modes::V0::kLambda) || modes::isEqual(v0Type, modes::V0::kAntiLambda)) { + if (confV0Selection.sign.value > 0) { + pdgCodeNegDau = kProton; + pdgCodeNegDau = kPiMinus; + } else { + pdgCodeNegDau = kProtonBar; + pdgCodeNegDau = kPiPlus; + } + } + mPairHistManagerSe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); - mPairHistManagerSe.setMass(confTrackSelection.pdgCodeAbs.value, confV0Selection.pdgCodeAbs.value); + mPairHistManagerSe.setMass(confTrackSelection.pdgCodeAbs.value, 0, 0, confV0Selection.pdgCodeAbs.value, pdgCodePosDau, pdgCodeNegDau); mPairHistManagerSe.setCharge(confTrackSelection.chargeAbs.value, 1); mCprSe.init(registry, cprHistSpec, confCpr, confTrackSelection.chargeAbs.value); mPairHistManagerMe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); - mPairHistManagerMe.setMass(confTrackSelection.pdgCodeAbs.value, confV0Selection.pdgCodeAbs.value); + mPairHistManagerMe.setMass(confTrackSelection.pdgCodeAbs.value, 0, 0, confV0Selection.pdgCodeAbs.value, pdgCodePosDau, pdgCodeNegDau); mPairHistManagerMe.setCharge(confTrackSelection.chargeAbs.value, 1); mCprMe.init(registry, cprHistSpec, confCpr, confTrackSelection.chargeAbs.value); mPc.template init(confPairCuts); @@ -509,10 +633,10 @@ class PairTrackV0Builder { auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto v0Slice = v0Partition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice.size() == 0 || v0Slice.size() == 0) { + if (trackSlice.size() < nLimitPartitionParticles || v0Slice.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, trackSlice.size(), v0Slice.size(), 0); mCprSe.setMagField(col.magField()); pairprocesshelpers::processSameEvent(trackSlice, v0Slice, trackTable, col, mTrackHistManager, mV0HistManager, mPairHistManagerSe, mCprSe, mPc); } @@ -522,12 +646,12 @@ class PairTrackV0Builder { auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto v0Slice = v0Partition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice.size() == 0 || v0Slice.size() == 0) { + if (trackSlice.size() < nLimitPartitionParticles || v0Slice.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col, mcCols); + mColHistManager.template fill(col, mcCols, trackSlice.size(), v0Slice.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice, v0Slice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager, mV0HistManager, mPairHistManagerSe, mCprSe, mPc); + pairprocesshelpers::processSameEvent(trackSlice, v0Slice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager, mV0HistManager, mPairHistManagerSe, mTrackCleaner, mV0Cleaner, mCprSe, mPc); } template @@ -548,18 +672,18 @@ class PairTrackV0Builder } } - template - void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& trackPartition, T5& v0Partition, T6 const& mcParticles, T7& cache, T8& binsVtxMult, T9& binsVtxCent, T10& binsVtxMultCent) + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& trackPartition, T5& v0Partition, T6 const& mcParticles, T7 const& mcMothers, T8 const& mcPartonicMothers, T9& cache, T10& binsVtxMult, T11& binsVtxCent, T12& binsVtxMultCent) { switch (mMixingPolicy) { case static_cast(pairhistmanager::kVtxMult): - pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, v0Partition, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, v0Partition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mV0Cleaner, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, v0Partition, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, v0Partition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mV0Cleaner, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxMultCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, v0Partition, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, v0Partition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mV0Cleaner, mCprMe, mPc); break; default: LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; @@ -570,6 +694,8 @@ class PairTrackV0Builder colhistmanager::CollisionHistManager mColHistManager; trackhistmanager::TrackHistManager mTrackHistManager; v0histmanager::V0HistManager mV0HistManager; + particlecleaner::ParticleCleaner mTrackCleaner; + particlecleaner::ParticleCleaner mV0Cleaner; pairhistmanager::PairHistManager mPairHistManagerSe; pairhistmanager::PairHistManager mPairHistManagerMe; closepairrejection::ClosePairRejectionTrackV0 mCprSe; @@ -607,23 +733,25 @@ class PairTrackTwoTrackResonanceBuilder typename T10, typename T11, typename T12, - typename T13> + typename T13, + typename T14> void init(o2::framework::HistogramRegistry* registry, - T1 const& confTrackSelection, - T2 const& confResonanceSelection, - T3 const& confCpr, - T4 const& confMixing, - T5 const& confPairBinning, - T6 const& confPairCuts, - std::map> const& colHistSpec, - std::map> const& trackHistSpec, - std::map> const& resonanceHistSpec, - std::map> const& posDauHistSpec, - std::map> const& negDauHistSpec, - std::map> const& pairHistSpec, - std::map> const& cprHistSpec) + T1 const& confCollisionBinning, + T2 const& confTrackSelection, + T3 const& confResonanceSelection, + T4 const& confCpr, + T5 const& confMixing, + T6 const& confPairBinning, + T7 const& confPairCuts, + std::map> const& colHistSpec, + std::map> const& trackHistSpec, + std::map> const& resonanceHistSpec, + std::map> const& posDauHistSpec, + std::map> const& negDauHistSpec, + std::map> const& pairHistSpec, + std::map> const& cprHistSpec) { - mColHistManager.template init(registry, colHistSpec); + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); mTrackHistManager.template init(registry, trackHistSpec, confTrackSelection); mResonanceHistManager.template init(registry, resonanceHistSpec, confResonanceSelection, posDauHistSpec, negDauHistSpec); @@ -647,13 +775,13 @@ class PairTrackTwoTrackResonanceBuilder void processSameEvent(T1 const& col, T2& trackTable, T3& trackPartition, T4& /*resonanceTable*/, T5& resonancePartition, T6& cache) { auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - auto v0Slice = resonancePartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice.size() == 0 || v0Slice.size() == 0) { + auto resonanaceSlice = resonancePartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice.size() < nLimitPartitionParticles || resonanaceSlice.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, trackSlice.size(), resonanaceSlice.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice, v0Slice, trackTable, col, mTrackHistManager, mResonanceHistManager, mPairHistManagerSe, mCprSe, mPc); + pairprocesshelpers::processSameEvent(trackSlice, resonanaceSlice, trackTable, col, mTrackHistManager, mResonanceHistManager, mPairHistManagerSe, mCprSe, mPc); } template @@ -713,26 +841,35 @@ class PairTrackKinkBuilder typename T9, typename T10, typename T11, - typename T12> + typename T12, + typename T13, + typename T14, + typename T15> void init(o2::framework::HistogramRegistry* registry, - T1 const& confTrackSelection, - T2 const& confKinkSelection, - T3 const& confCpr, - T4 const& confMixing, - T5 const& confPairBinning, - T6 const& confPairCuts, - std::map> const& colHistSpec, - std::map> const& trackHistSpec, - std::map> const& kinkHistSpec, - std::map> const& chaDauHistSpec, - std::map> const& pairHistSpec, - std::map> const& cprHistSpec) + T1 const& confCollisionBinning, + T2 const& confTrackSelection, + T3 const& confTrackCleaner, + T4 const& confKinkSelection, + T5 const& confKinkCleaner, + T6 const& confCpr, + T7 const& confMixing, + T8 const& confPairBinning, + T9 const& confPairCuts, + std::map> const& colHistSpec, + std::map> const& trackHistSpec, + std::map> const& kinkHistSpec, + std::map> const& chaDauHistSpec, + std::map> const& pairHistSpec, + std::map> const& cprHistSpec) { - mColHistManager.template init(registry, colHistSpec); + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); mTrackHistManager.template init(registry, trackHistSpec, confTrackSelection); mKinkHistManager.template init(registry, kinkHistSpec, confKinkSelection, chaDauHistSpec); + mTrackCleaner.init(confTrackCleaner); + mKinkCleaner.init(confKinkCleaner); + mPairHistManagerSe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); mPairHistManagerSe.setMass(confTrackSelection.pdgCodeAbs.value, confKinkSelection.pdgCodeAbs.value); mPairHistManagerSe.setCharge(confTrackSelection.chargeAbs.value, 1); // abs charge of kink daughter is always 1 @@ -754,10 +891,10 @@ class PairTrackKinkBuilder { auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto kinkSlice = kinkPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice.size() == 0 || kinkSlice.size() == 0) { + if (trackSlice.size() < nLimitPartitionParticles || kinkSlice.size() < nLimitPartitionParticles) { return; } - mColHistManager.fill(col); + mColHistManager.template fill(col, 0, 0, 0); mCprSe.setMagField(col.magField()); pairprocesshelpers::processSameEvent(trackSlice, kinkSlice, trackTable, col, mTrackHistManager, mKinkHistManager, mPairHistManagerSe, mCprSe, mPc); } @@ -767,12 +904,12 @@ class PairTrackKinkBuilder { auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto kinkSlice = kinkPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice.size() == 0 || kinkSlice.size() == 0) { + if (trackSlice.size() < nLimitPartitionParticles || kinkSlice.size() < nLimitPartitionParticles) { return; } - mColHistManager.fill(col, mcCols); + mColHistManager.template fill(col, mcCols, 0, 0, 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice, kinkSlice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager, mKinkHistManager, mPairHistManagerSe, mCprSe, mPc); + pairprocesshelpers::processSameEvent(trackSlice, kinkSlice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager, mKinkHistManager, mPairHistManagerSe, mTrackCleaner, mKinkCleaner, mCprSe, mPc); } template @@ -793,18 +930,18 @@ class PairTrackKinkBuilder } } - template - void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& trackPartition, T5& kinkPartition, T6 const& mcParticles, T7& cache, T8& binsVtxMult, T9& binsVtxCent, T10& binsVtxMultCent) + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& trackPartition, T5& kinkPartition, T6 const& mcParticles, T7 const& mcMothers, T8 const& mcPartonicMothers, T9& cache, T10& binsVtxMult, T11& binsVtxCent, T12& binsVtxMultCent) { switch (mMixingPolicy) { case static_cast(pairhistmanager::kVtxMult): - pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, kinkPartition, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, kinkPartition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mKinkCleaner, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, kinkPartition, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, kinkPartition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mKinkCleaner, mCprMe, mPc); break; case static_cast(pairhistmanager::kVtxMultCent): - pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, kinkPartition, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mCprMe, mPc); + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, kinkPartition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mKinkCleaner, mCprMe, mPc); break; default: LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; @@ -815,6 +952,8 @@ class PairTrackKinkBuilder colhistmanager::CollisionHistManager mColHistManager; trackhistmanager::TrackHistManager mTrackHistManager; kinkhistmanager::KinkHistManager mKinkHistManager; + particlecleaner::ParticleCleaner mTrackCleaner; + particlecleaner::ParticleCleaner mKinkCleaner; pairhistmanager::PairHistManager mPairHistManagerSe; pairhistmanager::PairHistManager mPairHistManagerMe; closepairrejection::ClosePairRejectionTrackKink mCprSe; @@ -858,30 +997,39 @@ class PairTrackCascadeBuilder typename T13, typename T14, typename T15, - typename T16> + typename T16, + typename T17, + typename T18, + typename T19> void init(o2::framework::HistogramRegistry* registry, - T1 const& confTrackSelection, - T2 const& confCascadeSelection, - T3 const& confCprBachelor, - T4 const& confCprV0Daughter, - T5 const& confMixing, - T6 const& confPairBinning, - T7 const& confPairCuts, - std::map> const& colHistSpec, - std::map> const& trackHistSpec, - std::map> const& cascadeHistSpec, - std::map> const& bachelorHistSpec, - std::map> const& posDauHistSpec, - std::map> const& negDauHistSpec, - std::map> const& pairHistSpec, - std::map> const& cprHistSpecBachelor, - std::map> const& cprHistSpecV0Daughter) + T1 const& confCollisionBinning, + T2 const& confTrackSelection, + T3 const& confTrackCleaner, + T4 const& confCascadeSelection, + T5 const& confCascadeCleaner, + T6 const& confCprBachelor, + T7 const& confCprV0Daughter, + T8 const& confMixing, + T9 const& confPairBinning, + T10 const& confPairCuts, + std::map> const& colHistSpec, + std::map> const& trackHistSpec, + std::map> const& cascadeHistSpec, + std::map> const& bachelorHistSpec, + std::map> const& posDauHistSpec, + std::map> const& negDauHistSpec, + std::map> const& pairHistSpec, + std::map> const& cprHistSpecBachelor, + std::map> const& cprHistSpecV0Daughter) { - mColHistManager.template init(registry, colHistSpec); + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); mTrackHistManager.template init(registry, trackHistSpec, confTrackSelection); mCascadeHistManager.template init(registry, cascadeHistSpec, confCascadeSelection, bachelorHistSpec, posDauHistSpec, negDauHistSpec); + mTrackCleaner.init(confTrackCleaner); + mCascadeCleaner.init(confCascadeCleaner); + mPairHistManagerSe.template init(registry, pairHistSpec, confPairBinning, confPairCuts); mPairHistManagerSe.setMass(confTrackSelection.pdgCodeAbs.value, confCascadeSelection.pdgCodeAbs.value); mPairHistManagerSe.setCharge(confTrackSelection.chargeAbs.value, 1); @@ -898,16 +1046,29 @@ class PairTrackCascadeBuilder } template - void processSameEvent(T1 const& col, T2& trackTable, T3& trackPartition, T4& /*cascadeTable*/, T5& v0Partition, T6& cache) + void processSameEvent(T1 const& col, T2& trackTable, T3& trackPartition, T4& /*cascadeTable*/, T5& cascadePartition, T6& cache) { auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - auto v0Slice = v0Partition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice.size() == 0 || v0Slice.size() == 0) { + auto cascadeSlice = cascadePartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice.size() < nLimitPartitionParticles || cascadeSlice.size() < nLimitPartitionParticles) { return; } - mColHistManager.template fill(col); + mColHistManager.template fill(col, trackSlice.size(), cascadeSlice.size(), 0); mCprSe.setMagField(col.magField()); - pairprocesshelpers::processSameEvent(trackSlice, v0Slice, trackTable, col, mTrackHistManager, mCascadeHistManager, mPairHistManagerSe, mCprSe, mPc); + pairprocesshelpers::processSameEvent(trackSlice, cascadeSlice, trackTable, col, mTrackHistManager, mCascadeHistManager, mPairHistManagerSe, mCprSe, mPc); + } + + template + void processSameEvent(T1 const& col, T2 const& mcCols, T3 const& trackTable, T4& trackPartition, T5 const& /*cascadeTabel*/, T6& cascadePartition, T7 const& mcParticles, T8 const& mcMothers, T9 const& mcPartonicMothers, T10& cache) + { + auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto cascadeSlice = cascadePartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice.size() < nLimitPartitionParticles || cascadeSlice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols, trackSlice.size(), cascadeSlice.size(), 0); + mCprSe.setMagField(col.magField()); + pairprocesshelpers::processSameEvent(trackSlice, cascadeSlice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager, mCascadeHistManager, mPairHistManagerSe, mTrackCleaner, mCascadeCleaner, mCprSe, mPc); } template @@ -928,10 +1089,30 @@ class PairTrackCascadeBuilder } } + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& trackPartition, T5& cascadePartition, T6 const& mcParticles, T7 const& mcMothers, T8 const& mcPartonicMothers, T9& cache, T10& binsVtxMult, T11& binsVtxCent, T12& binsVtxMultCent) + { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, cascadePartition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMult, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mCascadeCleaner, mCprMe, mPc); + break; + case static_cast(pairhistmanager::kVtxCent): + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, cascadePartition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mCascadeCleaner, mCprMe, mPc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + pairprocesshelpers::processMixedEvent(cols, mcCols, trackPartition, cascadePartition, trackTable, mcParticles, mcMothers, mcPartonicMothers, cache, binsVtxMultCent, mMixingDepth, mPairHistManagerMe, mTrackCleaner, mCascadeCleaner, mCprMe, mPc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + private: colhistmanager::CollisionHistManager mColHistManager; trackhistmanager::TrackHistManager mTrackHistManager; cascadehistmanager::CascadeHistManager mCascadeHistManager; + particlecleaner::ParticleCleaner mTrackCleaner; + particlecleaner::ParticleCleaner mCascadeCleaner; pairhistmanager::PairHistManager mPairHistManagerSe; pairhistmanager::PairHistManager mPairHistManagerMe; closepairrejection::ClosePairRejectionTrackCascade mCprSe; diff --git a/PWGCF/Femto/Core/pairCleaner.h b/PWGCF/Femto/Core/pairCleaner.h index b1076efa0b0..0d66be6721f 100644 --- a/PWGCF/Femto/Core/pairCleaner.h +++ b/PWGCF/Femto/Core/pairCleaner.h @@ -18,7 +18,7 @@ #include "PWGCF/Femto/Core/modes.h" -#include "fairlogger/Logger.h" +#include namespace o2::analysis::femto { @@ -53,7 +53,7 @@ class BasePairCleaner template bool pairHasCommonAncestor(T1 const& particle1, T2 const& particle2, T3 const& /*partonicMothers*/) const { - // if one of the two particles has no associated partonic mother, we cannot now if they have a common anchestor, so we break out with false + // if one of the two particles has no associated partonic mother, we cannot know if they have a common anchestor, so we break out with false if (!particle1.has_fMcPartMoth() || !particle2.has_fMcPartMoth()) { return false; } @@ -94,9 +94,9 @@ class TrackTrackPairCleaner : public BasePairCleaner } template - bool isCleanPair(T1 const& track1, T2 const& track2, T3 const& /*trackTable*/, T4 const& partonicMothers) const + bool isCleanPair(T1 const& track1, T2 const& track2, T3 const& trackTable, T4 const& partonicMothers) const { - if (!this->isCleanTrackPair(track1, track2)) { + if (!this->isCleanPair(track1, track2, trackTable)) { return false; } // pair is clean @@ -124,6 +124,23 @@ class V0V0PairCleaner : public BasePairCleaner auto negDaughter2 = trackTable.rawIteratorAt(v02.negDauId() - trackTable.offset()); return this->isCleanTrackPair(posDaughter1, posDaughter2) && this->isCleanTrackPair(negDaughter1, negDaughter2); } + + template + bool isCleanPair(T1 const& v01, T2 const& v02, T3 const& trackTable, T4 const& partonicMothers) const + { + if (!this->isCleanPair(v01, v02, trackTable)) { + return false; + } + // pair is clean + // no check if we require common or non-common ancestry + if (mMixPairsWithCommonAncestor) { + return this->pairHasCommonAncestor(v01, v02, partonicMothers); + } + if (mMixPairsWithNonCommonAncestor) { + return this->pairHasNonCommonAncestor(v01, v02, partonicMothers); + } + return true; + } }; class TrackV0PairCleaner : public BasePairCleaner // also works for particles decaying into a positive and negative daughter, like resonances @@ -197,6 +214,23 @@ class TrackCascadePairCleaner : public BasePairCleaner auto negDaughter = trackTable.rawIteratorAt(cascade.negDauId() - trackTable.offset()); return (this->isCleanTrackPair(bachelor, track) && this->isCleanTrackPair(posDaughter, track) && this->isCleanTrackPair(negDaughter, track)); } + + template + bool isCleanPair(T1 const& track1, T2 const& cascade, T3 const& trackTable, T4 const& partonicMothers) const + { + if (!this->isCleanPair(track1, cascade, trackTable)) { + return false; + } + // pair is clean + // now check if we require common or non-common ancestry + if (mMixPairsWithCommonAncestor) { + return this->pairHasCommonAncestor(track1, cascade, partonicMothers); + } + if (mMixPairsWithNonCommonAncestor) { + return this->pairHasNonCommonAncestor(track1, cascade, partonicMothers); + } + return true; + } }; } // namespace paircleaner } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/pairHistManager.h b/PWGCF/Femto/Core/pairHistManager.h index 21bed35be22..31efc4779a4 100644 --- a/PWGCF/Femto/Core/pairHistManager.h +++ b/PWGCF/Femto/Core/pairHistManager.h @@ -20,12 +20,14 @@ #include "PWGCF/Femto/Core/histManager.h" #include "PWGCF/Femto/Core/modes.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include +#include #include -#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include @@ -63,13 +65,20 @@ enum PairHist { // higher dimensions kKstarVsMtVsMult, kKstarVsMtVsMultVsCent, + // higher dimensions with pt + kKstarVsMtVsPt1VsPt2, kKstarVsMtVsPt1VsPt2VsMult, kKstarVsMtVsPt1VsPt2VsMultVsCent, // higher dimensions with mass - kKstarVsMass1VsMass2, - kKstarVsMass1VsMult, - kKstarVsMass2VsMult, - kKstarVsMass1VsMass2VsMult, + kKstarVsMtVsMass1VsMass2, + kKstarVsMtVsMass1VsMass2VsMult, + kKstarVsMtVsMass1VsMass2VsMultVsCent, + // higher dimension with pt and mass + kKstarVsMtVsMass1VsMass2VsPt1VsPt2, + kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, + kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, + // dalitz plots + kDalitz, // between a track and pos/neg daughter of another particle // mc kTrueKstarVsKstar, kTrueKtVsKt, @@ -101,16 +110,21 @@ struct ConfMixing : o2::framework::ConfigurableGroup { struct ConfPairBinning : o2::framework::ConfigurableGroup { std::string prefix = std::string("PairBinning"); + o2::framework::Configurable usePdgMass{"usePdgMass", true, "Use PDF masses for 4-vectors. If false, use reconstructed mass (if available)"}; o2::framework::Configurable plot1D{"plot1D", true, "Enable 1D histograms"}; o2::framework::Configurable plot2D{"plot2D", true, "Enable 2D histograms"}; o2::framework::Configurable plotKstarVsMtVsMult{"plotKstarVsMtVsMult", false, "Enable 3D histogram (Kstar Vs Mt Vs Mult)"}; o2::framework::Configurable plotKstarVsMtVsMultVsCent{"plotKstarVsMtVsMultVsCent", false, "Enable 4D histogram (Kstar Vs Mt Vs Mult Vs Cent)"}; + o2::framework::Configurable plotKstarVsMtVsPt1VsPt2{"plotKstarVsMtVsPt1VsPt2", false, "Enable 4D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2 Vs Mult)"}; o2::framework::Configurable plotKstarVsMtVsPt1VsPt2VsMult{"plotKstarVsMtVsPt1VsPt2VsMult", false, "Enable 5D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2 Vs Mult)"}; o2::framework::Configurable plotKstarVsMtVsPt1VsPt2VsMultVsCent{"plotKstarVsMtVsPt1VsPt2VsMultVsCent", false, "Enable 6D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2 Vs Mult Vs Cent)"}; - o2::framework::Configurable plotKstarVsMass1VsMass2{"plotKstarVsMass1VsMass2", false, "Enable 3D histogram (Kstar Vs Mass1 Vs Mass2)"}; - o2::framework::Configurable plotKstarVsMass1VsMult{"plotKstarVsMass1VsMult", false, "Enable 3D histogram (Kstar Vs Mass1 Vs Mult)"}; - o2::framework::Configurable plotKstarVsMass2VsMult{"plotKstarVsMass2VsMult", false, "Enable 3D histogram (Kstar Vs Mass2 Vs Mult)"}; - o2::framework::Configurable plotKstarVsMass1VsMass2VsMult{"plotKstarVsMass1VsMass2VsMult", false, "Enable 4D histogram (Kstar Vs Mass1 Vs Mass2 Vs Mult)"}; + o2::framework::Configurable plotKstarVsMtVsMass1VsMass2{"plotKstarVsMtVsMass1VsMass2", false, "Enable 4D histogram (Kstar Vs Mt Vs Mass1 Vs Mass2)"}; + o2::framework::Configurable plotKstarVsMtVsMass1VsMass2VsMult{"plotKstarVsMtVsMass1VsMass2VsMult", false, "Enable 5D histogram (Kstar Vs Mt Vs Mass1 Vs Mass2 Vs Mult)"}; + o2::framework::Configurable plotKstarVsMtVsMass1VsMass2VsMultVsCent{"plotKstarVsMtVsMass1VsMass2VsMultVsCent", false, "Enable 6D histogram (Kstar Vs Mt Vs Mass1 Vs Mass2 Vs Mult Vs Cent)"}; + o2::framework::Configurable plotKstarVsMtVsMass1VsMass2VsPt1VsPt2{"plotKstarVsMtVsMass1VsMass2VsPt1VsPt2", false, "Enable 6D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2 Vs Mass1 Vs Mass2)"}; + o2::framework::Configurable plotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult{"plotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult", false, "Enable 7D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2 Vs Mass1 Vs Mass2 Vs Mult)"}; + o2::framework::Configurable plotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent{"plotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent", false, "Enable 8D histogram (Kstar Vs Mt Vs Pt1 Vs Pt2 Vs Mass1 Vs Mass2 Vs Mult Vs Cent)"}; + o2::framework::Configurable plotDalitz{"plotDalitz", false, "Enable dalitz plot"}; o2::framework::ConfigurableAxis kstar{"kstar", {{600, 0, 6}}, "kstar"}; o2::framework::ConfigurableAxis kt{"kt", {{600, 0, 6}}, "kt"}; o2::framework::ConfigurableAxis mt{"mt", {{500, 0.8, 5.8}}, "mt"}; @@ -118,8 +132,11 @@ struct ConfPairBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis centrality{"centrality", {{10, 0, 100}}, "centrality (mult. percentile)"}; o2::framework::ConfigurableAxis pt1{"pt1", {{100, 0, 6}}, "Pt binning for particle 1"}; o2::framework::ConfigurableAxis pt2{"pt2", {{100, 0, 6}}, "Pt binning for particle 2"}; - o2::framework::ConfigurableAxis mass1{"mass1", {{100, 0, 2}}, "Mass binning for particle 1 (if particle has mass getter)"}; - o2::framework::ConfigurableAxis mass2{"mass2", {{100, 0, 2}}, "Mass binning for particle 2 (if particle has mass getter)"}; + o2::framework::ConfigurableAxis mass1{"mass1", {{100, 0, 2}}, "Mass binning for particle 1 (if particle has mass getter, otherwise PDG mass)"}; + o2::framework::ConfigurableAxis mass2{"mass2", {{100, 0, 2}}, "Mass binning for particle 2 (if particle has mass getter, otherwise PDG mass)"}; + o2::framework::ConfigurableAxis dalitzMtot{"dalitzMtot", {{100, 0, 10}}, "Total invariant mass squared binning in darlitz plot"}; + o2::framework::ConfigurableAxis dalitzM12{"dalitzM12", {{100, 0, 10}}, "Mass12 binning of darlitz plot"}; + o2::framework::ConfigurableAxis dalitzM13{"dalitzM13", {{100, 0, 10}}, "Mass13 binning of darlitz plot"}; o2::framework::Configurable transverseMassType{"transverseMassType", static_cast(modes::TransverseMassType::kAveragePdgMass), "Type of transverse mass (0-> Average Pdg Mass, 1-> Reduced Pdg Mass, 2-> Mt from combined 4 vector)"}; }; @@ -160,48 +177,58 @@ constexpr std::array, kPairHistogramLast> {kKstarVsMass2, o2::framework::kTH2F, "hKstarVsMass2", "k* vs m_{2}; k* (GeV/#it{c}); m_{2} (GeV/#it{c}^{2})"}, {kMass1VsMass2, o2::framework::kTH2F, "hMass1VsMass2", "m_{1} vs m_{2}; m_{1} (GeV/#it{c}^{2}); m_{2} (GeV/#it{c}^{2})"}, // n-D - {kKstarVsMtVsMult, o2::framework::kTHnSparseF, "hKstarVsMtVsMult", "k* vs m_{T} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity"}, - {kKstarVsMtVsMultVsCent, o2::framework::kTHnSparseF, "hKstarVsMtVsMultVsCent", "k* vs m_{T} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity; Centrality (%)"}, - {kKstarVsMtVsPt1VsPt2VsMult, o2::framework::kTHnSparseF, "hKstarVsMtVsPt1VsPt2VsMult", "k* vs m_{T} vs p_{T,1} vs p_{T,2} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c}); Multiplicity"}, - {kKstarVsMtVsPt1VsPt2VsMultVsCent, o2::framework::kTHnSparseF, "hKstarVsMtVsPt1VsPt2VsMultVsCent", "k* vs m_{T} vs p_{T,1} vs p_{T,2} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c}); Multiplicity; Centrality"}, + {kKstarVsMtVsMult, o2::framework::kTHnSparseF, "hKstarVsMtVsMult", "k* vs m_{T} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity;"}, + {kKstarVsMtVsMultVsCent, o2::framework::kTHnSparseF, "hKstarVsMtVsMultVsCent", "k* vs m_{T} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity; Centrality (%);"}, + // n-D with pt + {kKstarVsMtVsPt1VsPt2, o2::framework::kTHnSparseF, "hKstarVsMtVsPt1VsPt2", "k* vs m_{T} vs p_{T,1} vs p_{T,2}; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c});"}, + {kKstarVsMtVsPt1VsPt2VsMult, o2::framework::kTHnSparseF, "hKstarVsMtVsPt1VsPt2VsMult", "k* vs m_{T} vs p_{T,1} vs p_{T,2} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c}); Multiplicity;"}, + {kKstarVsMtVsPt1VsPt2VsMultVsCent, o2::framework::kTHnSparseF, "hKstarVsMtVsPt1VsPt2VsMultVsCent", "k* vs m_{T} vs p_{T,1} vs p_{T,2} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c}); Multiplicity; Centrality;"}, // n-D with mass - {kKstarVsMass1VsMass2, o2::framework::kTHnSparseF, "hKstarVsMass1VsMass2", "k* vs m_{1} vs m_{2}; k* (GeV/#it{c}); m_{1} (GeV/#it{c}^{2}); m_{2} (GeV/#it{c}^{2})"}, - {kKstarVsMass1VsMult, o2::framework::kTHnSparseF, "hKstarVsMass1VsMult", "k* vs m_{1} vs multiplicity; k* (GeV/#it{c}); m_{1} (GeV/#it{c}^{2}); Multiplicity"}, - {kKstarVsMass2VsMult, o2::framework::kTHnSparseF, "hKstarVsMass2VsMult", "k* vs m_{2} vs multiplicity; k* (GeV/#it{c}); m_{2} (GeV/#it{c}^{2}); Multiplicity"}, - {kKstarVsMass1VsMass2VsMult, o2::framework::kTHnSparseF, "hKstarVsMass1VsMass2VsMult", "k* vs m_{1} vs m_{2} vs multiplicity; k* (GeV/#it{c}); m_{1} (GeV/#it{c}^{2}); m_{2} (GeV/#it{c}^{2}); Multiplicity"}, + {kKstarVsMtVsMass1VsMass2, o2::framework::kTHnSparseF, "hKstarVsMtVsMass1VsMass2", "k* vs m_{T} vs m_{1} vs m_{2}; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2});"}, + {kKstarVsMtVsMass1VsMass2VsMult, o2::framework::kTHnSparseF, "hKstarVsMtVsMass1VsMass2VsMult", "k* vs m_{T} vs m_{1} vs m_{2} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); Multiplicity;"}, + {kKstarVsMtVsMass1VsMass2VsMultVsCent, o2::framework::kTHnSparseF, "hKstarVsMtVsMass1VsMass2VsMultVsCent", "k* vs m_{T} vs m_{1} vs m_{2} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); Multiplicity; Centrality (%);"}, + // n-D with pt and mass + {kKstarVsMtVsMass1VsMass2VsPt1VsPt2, o2::framework::kTHnSparseF, "hKstarVsMtVsMass1VsMass2VsPt1VsPt2", "k* vs m_{T} vs m_{1} vs m_{2} vs p_{T,1} vs p_{T,2}; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c});"}, + {kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, o2::framework::kTHnSparseF, "hKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult", "k* vs m_{T} vs m_{1} vs m_{2} vs p_{T,1} vs p_{T,2} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c}); Multiplicity;"}, + {kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, o2::framework::kTHnSparseF, "hKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent", "k* vs m_{T} vs m_{1} vs m_{2} vs p_{T,1} vs p_{T,2} vs multiplicity vs centrality; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); m_{1} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}); p_{T,2} (GeV/#it{c}); Multiplicity; Centrality (%);"}, + {kDalitz, o2::framework::kTHnSparseF, "hDalitz", "Dalitz plot; k* (GeV/#it{c}); m^{2}_{123} (GeV/#it{c}^{2})^{2}; m^{2}_{12} (GeV/#it{c}^{2})^{2}; m^{2}_{13} (GeV/#it{c}^{2})^{2};"}, {kTrueKstarVsKstar, o2::framework::kTH2F, "hTrueKstarVsKstar", "k*_{True} vs k*; k*_{True} (GeV/#it{c}); k* (GeV/#it{c})"}, {kTrueKtVsKt, o2::framework::kTH2F, "hTrueKtVsKt", "k_{T,True} vs k_{T}; k_{T,True} (GeV/#it{c}); k_{T} (GeV/#it{c})"}, - {kTrueMtVsMt, o2::framework::kTH2F, "hTrueMtVsMt", "m_{T,True} vs m_{T}; m_{T,True} (GeV/#it{c}^{2}); m_{T,True} (GeV/#it{c}^{2})"}, + {kTrueMtVsMt, o2::framework::kTH2F, "hTrueMtVsMt", "m_{T,True} vs m_{T}; m_{T,True} (GeV/#it{c}^{2}); m_{T} (GeV/#it{c}^{2})"}, {kTrueMultVsMult, o2::framework::kTH2F, "hTrueMultVsMult", "Multiplicity_{True} vs Multiplicity; Multiplicity_{True} ; Multiplicity"}, {kTrueCentVsCent, o2::framework::kTH2F, "hTrueCentVsCent", "Centrality_{True} vs Centrality; Centrality_{True} (%); Centrality (%)"}, }}; -#define PAIR_HIST_ANALYSIS_MAP(conf) \ - {kKstar, {conf.kstar}}, \ - {kKt, {conf.kt}}, \ - {kMt, {conf.mt}}, \ - {kPt1VsPt2, {conf.pt1, conf.pt2}}, \ - {kPt1VsKstar, {conf.pt1, conf.kstar}}, \ - {kPt2VsKstar, {conf.pt2, conf.kstar}}, \ - {kPt1VsKt, {conf.pt1, conf.kt}}, \ - {kPt2VsKt, {conf.pt2, conf.kt}}, \ - {kPt1VsMt, {conf.pt1, conf.mt}}, \ - {kPt2VsMt, {conf.pt2, conf.mt}}, \ - {kKstarVsKt, {conf.kstar, conf.kt}}, \ - {kKstarVsMt, {conf.kstar, conf.mt}}, \ - {kKstarVsMult, {conf.kstar, conf.multiplicity}}, \ - {kKstarVsCent, {conf.kstar, conf.centrality}}, \ - {kKstarVsMass1, {conf.kstar, conf.mass1}}, \ - {kKstarVsMass2, {conf.kstar, conf.mass2}}, \ - {kMass1VsMass2, {conf.mass1, conf.mass2}}, \ - {kKstarVsMtVsMult, {conf.kstar, conf.mt, conf.multiplicity}}, \ - {kKstarVsMtVsMultVsCent, {conf.kstar, conf.mt, conf.multiplicity, conf.centrality}}, \ - {kKstarVsMtVsPt1VsPt2VsMult, {conf.kstar, conf.mt, conf.pt1, conf.pt2, conf.multiplicity}}, \ - {kKstarVsMtVsPt1VsPt2VsMultVsCent, {conf.kstar, conf.mt, conf.pt1, conf.pt2, conf.multiplicity, conf.centrality}}, \ - {kKstarVsMass1VsMass2, {conf.kstar, conf.mass1, conf.mass2}}, \ - {kKstarVsMass1VsMult, {conf.kstar, conf.mass1, conf.multiplicity}}, \ - {kKstarVsMass2VsMult, {conf.kstar, conf.mass2, conf.multiplicity}}, \ - {kKstarVsMass1VsMass2VsMult, {conf.kstar, conf.mass1, conf.mass2, conf.multiplicity}}, +#define PAIR_HIST_ANALYSIS_MAP(conf) \ + {kKstar, {conf.kstar}}, \ + {kKt, {conf.kt}}, \ + {kMt, {conf.mt}}, \ + {kPt1VsPt2, {conf.pt1, conf.pt2}}, \ + {kPt1VsKstar, {conf.pt1, conf.kstar}}, \ + {kPt2VsKstar, {conf.pt2, conf.kstar}}, \ + {kPt1VsKt, {conf.pt1, conf.kt}}, \ + {kPt2VsKt, {conf.pt2, conf.kt}}, \ + {kPt1VsMt, {conf.pt1, conf.mt}}, \ + {kPt2VsMt, {conf.pt2, conf.mt}}, \ + {kKstarVsKt, {conf.kstar, conf.kt}}, \ + {kKstarVsMt, {conf.kstar, conf.mt}}, \ + {kKstarVsMult, {conf.kstar, conf.multiplicity}}, \ + {kKstarVsCent, {conf.kstar, conf.centrality}}, \ + {kKstarVsMass1, {conf.kstar, conf.mass1}}, \ + {kKstarVsMass2, {conf.kstar, conf.mass2}}, \ + {kMass1VsMass2, {conf.mass1, conf.mass2}}, \ + {kKstarVsMtVsMult, {conf.kstar, conf.mt, conf.multiplicity}}, \ + {kKstarVsMtVsMultVsCent, {conf.kstar, conf.mt, conf.multiplicity, conf.centrality}}, \ + {kKstarVsMtVsPt1VsPt2, {conf.kstar, conf.mt, conf.pt1, conf.pt2}}, \ + {kKstarVsMtVsPt1VsPt2VsMult, {conf.kstar, conf.mt, conf.pt1, conf.pt2, conf.multiplicity}}, \ + {kKstarVsMtVsPt1VsPt2VsMultVsCent, {conf.kstar, conf.mt, conf.pt1, conf.pt2, conf.multiplicity, conf.centrality}}, \ + {kKstarVsMtVsMass1VsMass2, {conf.kstar, conf.mt, conf.mass1, conf.mass2}}, \ + {kKstarVsMtVsMass1VsMass2VsMult, {conf.kstar, conf.mt, conf.mass1, conf.mass2, conf.multiplicity}}, \ + {kKstarVsMtVsMass1VsMass2VsMultVsCent, {conf.kstar, conf.mt, conf.mass1, conf.mass2, conf.multiplicity, conf.centrality}}, \ + {kKstarVsMtVsMass1VsMass2VsPt1VsPt2, {conf.kstar, conf.mt, conf.mass1, conf.mass2, conf.pt1, conf.pt2}}, \ + {kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, {conf.kstar, conf.mt, conf.mass1, conf.mass2, conf.pt1, conf.pt2, conf.multiplicity}}, \ + {kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, {conf.kstar, conf.mt, conf.mass1, conf.mass2, conf.pt1, conf.pt2, conf.multiplicity, conf.centrality}}, \ + {kDalitz, {conf.kstar, conf.dalitzMtot, conf.dalitzM12, conf.dalitzM13}}, #define PAIR_HIST_MC_MAP(conf) \ {kTrueKstarVsKstar, {conf.kstar, conf.kstar}}, \ @@ -213,14 +240,14 @@ constexpr std::array, kPairHistogramLast> template auto makePairHistSpecMap(const T& confPairBinning) { - return std::map>{ + return std::map>{ PAIR_HIST_ANALYSIS_MAP(confPairBinning)}; }; template auto makePairMcHistSpecMap(const T& confPairBinning) { - return std::map>{ + return std::map>{ PAIR_HIST_ANALYSIS_MAP(confPairBinning) PAIR_HIST_MC_MAP(confPairBinning)}; }; @@ -267,18 +294,27 @@ class PairHistManager { mHistogramRegistry = registry; + mUsePdgMass = ConfPairBinning.usePdgMass.value; + // flags for histograms mPlot1d = ConfPairBinning.plot1D.value; mPlot2d = ConfPairBinning.plot2D.value; mPlotKstarVsMtVsMult = ConfPairBinning.plotKstarVsMtVsMult.value; mPlotKstarVsMtVsMultVsCent = ConfPairBinning.plotKstarVsMtVsMultVsCent.value; - mPlotKstarVsMtVsPt1VsP2VsMult = ConfPairBinning.plotKstarVsMtVsPt1VsPt2VsMult.value; - mPlotKstarVsMtVsPt1VsP2VsMultVsCent = ConfPairBinning.plotKstarVsMtVsPt1VsPt2VsMultVsCent.value; - mPlotKstarVsMass1VsMass2 = ConfPairBinning.plotKstarVsMass1VsMass2.value; - mPlotKstarVsMass1VsMult = ConfPairBinning.plotKstarVsMass1VsMult.value; - mPlotKstarVsMass2VsMult = ConfPairBinning.plotKstarVsMass2VsMult.value; - mPlotKstarVsMass1VsMass2VsMult = ConfPairBinning.plotKstarVsMass1VsMass2VsMult.value; + mPlotKstarVsMtVsPt1VsPt2 = ConfPairBinning.plotKstarVsMtVsPt1VsPt2.value; + mPlotKstarVsMtVsPt1VsPt2VsMult = ConfPairBinning.plotKstarVsMtVsPt1VsPt2VsMult.value; + mPlotKstarVsMtVsPt1VsPt2VsMultVsCent = ConfPairBinning.plotKstarVsMtVsPt1VsPt2VsMultVsCent.value; + + mPlotKstarVsMtVsMass1VsMass2 = ConfPairBinning.plotKstarVsMtVsMass1VsMass2.value; + mPlotKstarVsMtVsMass1VsMass2VsMult = ConfPairBinning.plotKstarVsMtVsMass1VsMass2VsMult.value; + mPlotKstarVsMtVsMass1VsMass2VsMultVsCent = ConfPairBinning.plotKstarVsMtVsMass1VsMass2VsMultVsCent.value; + + mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2 = ConfPairBinning.plotKstarVsMtVsMass1VsMass2VsPt1VsPt2.value; + mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult = ConfPairBinning.plotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult.value; + mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent = ConfPairBinning.plotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent.value; + + mPlotDalitz = ConfPairBinning.plotDalitz.value; // transverse mass type mMtType = static_cast(ConfPairBinning.transverseMassType.value); @@ -302,10 +338,18 @@ class PairHistManager void setMass(int PdgParticle1, int PdgParticle2) { - mPdgMass1 = o2::analysis::femto::utils::getMass(PdgParticle1); - mPdgMass2 = o2::analysis::femto::utils::getMass(PdgParticle2); - mAverageMass = (mPdgMass1 + mPdgMass2) / 2.f; - mReducedMass = 2.f * (mPdgMass1 * mPdgMass2) / (mPdgMass1 + mPdgMass2); + mPdgMass1 = utils::getPdgMass(PdgParticle1); + mPdgMass2 = utils::getPdgMass(PdgParticle2); + } + + void setMass(int PdgParticle1, int PdgPosDauParticle1, int PdgNegDauParticle1, int PdgParticle2, int PdgPosDauParticle2, int PdgNegDauParticle2) + { + mPdgMass1 = utils::getPdgMass(PdgParticle1); + mPdgMassPosDau1 = utils::getPdgMass(PdgPosDauParticle1); + mPdgMassNegDau1 = utils::getPdgMass(PdgNegDauParticle1); + mPdgMass2 = utils::getPdgMass(PdgParticle2); + mPdgMassPosDau2 = utils::getPdgMass(PdgPosDauParticle2); + mPdgMassNegDau2 = utils::getPdgMass(PdgNegDauParticle2); } void setCharge(int chargeAbsParticle1, int chargeAbsParticle2) { @@ -314,56 +358,78 @@ class PairHistManager mAbsCharge2 = std::abs(chargeAbsParticle2); } - template - void setPair(const T1& particle1, const T2& particle2) + template + void setPair(T1 const& particle1, T2 const& particle2, T3 const& trackTable) { + // if one of the particles has a mass getter (like lambda), we cache the value for the filling later + // otherwise set it to the pdg mass + if constexpr (utils::HasMass) { + mRecoMass1 = particle1.mass(); + } else { + mRecoMass1 = mPdgMass1; + } + if constexpr (utils::HasMass) { + mRecoMass2 = particle2.mass(); + } else { + mRecoMass2 = mPdgMass2; + } + + // get mass for 4-vectors + double mass1 = 0.f; + double mass2 = 0.f; + if (mUsePdgMass) { + mass1 = mPdgMass1; + mass2 = mPdgMass2; + } else { + mass1 = mRecoMass1; + mass2 = mRecoMass2; + } + // pt in track table is calculated from 1/signedPt from the original track table // in case of He with Z=2, we have to rescale the pt with the absolute charge - mParticle1 = ROOT::Math::PtEtaPhiMVector{mAbsCharge1 * particle1.pt(), particle1.eta(), particle1.phi(), mPdgMass1}; - mParticle2 = ROOT::Math::PtEtaPhiMVector{mAbsCharge2 * particle2.pt(), particle2.eta(), particle2.phi(), mPdgMass2}; - auto partSum = mParticle1 + mParticle2; + mParticle1 = ROOT::Math::PtEtaPhiMVector(mAbsCharge1 * particle1.pt(), particle1.eta(), particle1.phi(), mass1); + mParticle2 = ROOT::Math::PtEtaPhiMVector(mAbsCharge2 * particle2.pt(), particle2.eta(), particle2.phi(), mass2); // set kT - mKt = 0.5f * partSum.Pt(); + mKt = getKt(mParticle1, mParticle2); // set mT - mMt = computeMt(partSum); - - // Boost particle to the pair rest frame (Prf) and calculate k* (would be equivalent using particle 2) - // make a copy of particle 1 - auto particle1Prf = ROOT::Math::PtEtaPhiMVector(mParticle1); - // get lorentz boost into pair rest frame - ROOT::Math::Boost boostPrf(partSum.BoostToCM()); - // boost particle 1 into pair rest frame and calculate its momentum, which has the same value as k* - mKstar = boostPrf(particle1Prf).P(); - - // if one of the particles has a mass getter, we cache the value for the filling later - if constexpr (modes::hasMass(particleType1)) { - mMass1 = particle1.mass(); - } - if constexpr (modes::hasMass(particleType2)) { - mMass2 = particle2.mass(); + mMt = getMt(mParticle1, mParticle2); + + // set kstar + mKstar = getKstar(mParticle1, mParticle2); + + if (mPlotDalitz) { + if constexpr (modes::isEqual(particleType1, modes::Particle::kTrack) && modes::isEqual(particleType2, modes::Particle::kV0)) { + auto posDaughter = trackTable.rawIteratorAt(particle2.posDauId() - trackTable.offset()); + auto negDaughter = trackTable.rawIteratorAt(particle2.negDauId() - trackTable.offset()); + ROOT::Math::PtEtaPhiMVector posDau4v = ROOT::Math::PtEtaPhiMVector(posDaughter.pt(), posDaughter.eta(), posDaughter.phi(), mPdgMassPosDau2); + ROOT::Math::PtEtaPhiMVector negDau4v = ROOT::Math::PtEtaPhiMVector(negDaughter.pt(), negDaughter.eta(), negDaughter.phi(), mPdgMassNegDau2); + mMassTot2 = (mParticle1 + posDau4v + negDau4v).M2(); + mMass12 = (mParticle1 + posDau4v).M2(); + mMass13 = (mParticle1 + negDau4v).M2(); + } } } - template - void setPair(const T1& particle1, const T2& particle2, const T3& col) + template + void setPair(T1 const& particle1, T2 const& particle2, T3 const& trackTable, T4 const& col) { - setPair(particle1, particle2); + setPair(particle1, particle2, trackTable); mMult = col.mult(); mCent = col.cent(); } - template - void setPair(const T1& particle1, const T2& particle2, const T3& col1, const T4& col2) + template + void setPair(T1 const& particle1, T2 const& particle2, T3 const& trackTable, T4 const& col1, T5 const& col2) { - setPair(particle1, particle2); + setPair(particle1, particle2, trackTable); mMult = 0.5f * (col1.mult() + col2.mult()); // if mixing with multiplicity, should be in the same mixing bin mCent = 0.5f * (col1.cent() + col2.cent()); // if mixing with centrality, should be in the same mixing bin } template - void setPairMc(const T1& particle1, const T2& particle2, const T3& /*mcParticles*/) + void setPairMc(T1 const& particle1, T2 const& particle2, const T3& /*mcParticles*/) { if (!particle1.has_fMcParticle() || !particle2.has_fMcParticle()) { mHasMcPair = false; @@ -374,52 +440,45 @@ class PairHistManager auto mcParticle1 = particle1.template fMcParticle_as(); auto mcParticle2 = particle2.template fMcParticle_as(); - mParticle1 = ROOT::Math::PtEtaPhiMVector{mAbsCharge1 * mcParticle1.pt(), mcParticle1.eta(), mcParticle1.phi(), mPdgMass1}; - mParticle2 = ROOT::Math::PtEtaPhiMVector{mAbsCharge2 * mcParticle2.pt(), mcParticle2.eta(), mcParticle2.phi(), mPdgMass2}; - auto partSum = mParticle1 + mParticle2; + mTrueParticle1 = ROOT::Math::PtEtaPhiMVector(mAbsCharge1 * mcParticle1.pt(), mcParticle1.eta(), mcParticle1.phi(), mPdgMass1); + mTrueParticle2 = ROOT::Math::PtEtaPhiMVector(mAbsCharge2 * mcParticle2.pt(), mcParticle2.eta(), mcParticle2.phi(), mPdgMass2); // set kT - mTrueKt = partSum.Pt() / 2.f; + mTrueKt = getKt(mTrueParticle1, mTrueParticle2); // set mT - mTrueMt = computeMt(partSum); + mTrueMt = getMt(mTrueParticle1, mTrueParticle2); - // Boost particle to the pair rest frame (Prf) and calculate k* (would be equivalent using particle 2) - // make a copy of particle 1 - auto particle1Prf = ROOT::Math::PtEtaPhiMVector(mParticle1); - // get lorentz boost into pair rest frame - ROOT::Math::Boost boostPrf(partSum.BoostToCM()); - // boost particle 1 into pair rest frame and calculate its momentum, which has the same value as k* - mTrueKstar = boostPrf(particle1Prf).P(); + mTrueKstar = getKstar(mTrueParticle1, mTrueParticle2); } - template - void setPairMc(const T1& particle1, const T2& particle2, const T3& mcParticles, const T4& col, const T5& /*mcCols*/) + template + void setPairMc(T1 const& particle1, T2 const& particle2, T3 const& trackTable, T4 const& mcParticles, T5 const& col, T6 const& /*mcCols*/) { - setPair(particle1, particle2, col); + setPair(particle1, particle2, trackTable, col); setPairMc(particle1, particle2, mcParticles); if (!col.has_fMcCol()) { mHasMcCol = false; return; } mHasMcCol = true; - auto mcCol = col.template fMcCol_as(); + auto mcCol = col.template fMcCol_as(); mTrueMult = mcCol.mult(); mTrueCent = mcCol.cent(); } - template - void setPairMc(const T1& particle1, const T2& particle2, const T3& mcParticles, const T4& col1, const T5& col2, const T6& /*mcCols*/) + template + void setPairMc(T1 const& particle1, T2 const& particle2, T3 const& trackTable, T4 const& mcParticles, T5 const& col1, T6 const& col2, T7 const& /*mcCols*/) { - setPair(particle1, particle2, col1, col2); + setPair(particle1, particle2, trackTable, col1, col2); setPairMc(particle1, particle2, mcParticles); if (!col1.has_fMcCol() || !col2.has_fMcCol()) { mHasMcCol = false; return; } mHasMcCol = true; - auto mcCol1 = col1.template fMcCol_as(); - auto mcCol2 = col2.template fMcCol_as(); + auto mcCol1 = col1.template fMcCol_as(); + auto mcCol2 = col2.template fMcCol_as(); mTrueMult = 0.5f * (mcCol1.mult() + mcCol2.mult()); mTrueCent = 0.5f * (mcCol1.cent() + mcCol2.cent()); } @@ -469,50 +528,49 @@ class PairHistManager mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMt, HistTable), getHistDesc(kKstarVsMt, HistTable), getHistType(kKstarVsMt, HistTable), {Specs.at(kKstarVsMt)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMult, HistTable), getHistDesc(kKstarVsMult, HistTable), getHistType(kKstarVsMult, HistTable), {Specs.at(kKstarVsMult)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsCent, HistTable), getHistDesc(kKstarVsCent, HistTable), getHistType(kKstarVsCent, HistTable), {Specs.at(kKstarVsCent)}); - - // special care for mass plots since not all particles have "mass" - if constexpr (modes::hasMass(particleType1)) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass1, HistTable), getHistDesc(kKstarVsMass1, HistTable), getHistType(kKstarVsMass1, HistTable), {Specs.at(kKstarVsMass1)}); - } - if constexpr (modes::hasMass(particleType2)) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass2, HistTable), getHistDesc(kKstarVsMass2, HistTable), getHistType(kKstarVsMass2, HistTable), {Specs.at(kKstarVsMass2)}); - } - if constexpr (modes::hasMass(particleType1) && modes::hasMass(particleType2)) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kMass1VsMass2, HistTable), getHistDesc(kMass1VsMass2, HistTable), getHistType(kMass1VsMass2, HistTable), {Specs.at(kMass1VsMass2)}); - } + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass1, HistTable), getHistDesc(kKstarVsMass1, HistTable), getHistType(kKstarVsMass1, HistTable), {Specs.at(kKstarVsMass1)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass2, HistTable), getHistDesc(kKstarVsMass2, HistTable), getHistType(kKstarVsMass2, HistTable), {Specs.at(kKstarVsMass2)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kMass1VsMass2, HistTable), getHistDesc(kMass1VsMass2, HistTable), getHistType(kMass1VsMass2, HistTable), {Specs.at(kMass1VsMass2)}); } + // higher dimensional histograms if (mPlotKstarVsMtVsMult) { mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMult, HistTable), getHistDesc(kKstarVsMtVsMult, HistTable), getHistType(kKstarVsMtVsMult, HistTable), {Specs.at(kKstarVsMtVsMult)}); } if (mPlotKstarVsMtVsMultVsCent) { mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMultVsCent, HistTable), getHistDesc(kKstarVsMtVsMultVsCent, HistTable), getHistType(kKstarVsMtVsMultVsCent, HistTable), {Specs.at(kKstarVsMtVsMultVsCent)}); } - if (mPlotKstarVsMtVsPt1VsP2VsMult) { + // add pt + if (mPlotKstarVsMtVsPt1VsPt2) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsPt1VsPt2, HistTable), getHistDesc(kKstarVsMtVsPt1VsPt2, HistTable), getHistType(kKstarVsMtVsPt1VsPt2, HistTable), {Specs.at(kKstarVsMtVsPt1VsPt2)}); + } + if (mPlotKstarVsMtVsPt1VsPt2VsMult) { mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsPt1VsPt2VsMult, HistTable), getHistDesc(kKstarVsMtVsPt1VsPt2VsMult, HistTable), getHistType(kKstarVsMtVsPt1VsPt2VsMult, HistTable), {Specs.at(kKstarVsMtVsPt1VsPt2VsMult)}); } - if (mPlotKstarVsMtVsPt1VsP2VsMultVsCent) { + if (mPlotKstarVsMtVsPt1VsPt2VsMultVsCent) { mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsPt1VsPt2VsMultVsCent, HistTable), getHistDesc(kKstarVsMtVsPt1VsPt2VsMultVsCent, HistTable), getHistType(kKstarVsMtVsPt1VsPt2VsMultVsCent, HistTable), {Specs.at(kKstarVsMtVsPt1VsPt2VsMultVsCent)}); } - - // again special care for particles with "mass" - if constexpr (modes::hasMass(particleType1)) { - if (mPlotKstarVsMass1VsMult) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass1VsMult, HistTable), getHistDesc(kKstarVsMass1VsMult, HistTable), getHistType(kKstarVsMass1VsMult, HistTable), {Specs.at(kKstarVsMass1VsMult)}); - } + // add mass + if (mPlotKstarVsMtVsMass1VsMass2) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMass1VsMass2, HistTable), getHistDesc(kKstarVsMtVsMass1VsMass2, HistTable), getHistType(kKstarVsMtVsMass1VsMass2, HistTable), {Specs.at(kKstarVsMtVsMass1VsMass2)}); } - if constexpr (modes::hasMass(particleType2)) { - if (mPlotKstarVsMass2VsMult) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass2VsMult, HistTable), getHistDesc(kKstarVsMass2VsMult, HistTable), getHistType(kKstarVsMass2VsMult, HistTable), {Specs.at(kKstarVsMass2VsMult)}); - } + if (mPlotKstarVsMtVsMass1VsMass2VsMult) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMass1VsMass2VsMult, HistTable), getHistDesc(kKstarVsMtVsMass1VsMass2VsMult, HistTable), getHistType(kKstarVsMtVsMass1VsMass2VsMult, HistTable), {Specs.at(kKstarVsMtVsMass1VsMass2VsMult)}); } - if constexpr (modes::hasMass(particleType1) && modes::hasMass(particleType2)) { - if (mPlotKstarVsMass1VsMass2) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass1VsMass2, HistTable), getHistDesc(kKstarVsMass1VsMass2, HistTable), getHistType(kKstarVsMass1VsMass2, HistTable), {Specs.at(kKstarVsMass1VsMass2)}); - } - if (mPlotKstarVsMass1VsMass2VsMult) { - mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMass1VsMass2VsMult, HistTable), getHistDesc(kKstarVsMass1VsMass2VsMult, HistTable), getHistType(kKstarVsMass1VsMass2VsMult, HistTable), {Specs.at(kKstarVsMass1VsMass2VsMult)}); - } + if (mPlotKstarVsMtVsMass1VsMass2VsMultVsCent) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMass1VsMass2VsMultVsCent, HistTable), getHistDesc(kKstarVsMtVsMass1VsMass2VsMultVsCent, HistTable), getHistType(kKstarVsMtVsMass1VsMass2VsMultVsCent, HistTable), {Specs.at(kKstarVsMtVsMass1VsMass2VsMultVsCent)}); + } + if (mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMass1VsMass2VsPt1VsPt2, HistTable), getHistDesc(kKstarVsMtVsMass1VsMass2VsPt1VsPt2, HistTable), getHistType(kKstarVsMtVsMass1VsMass2VsPt1VsPt2, HistTable), {Specs.at(kKstarVsMtVsMass1VsMass2VsPt1VsPt2)}); + } + if (mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, HistTable), getHistDesc(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, HistTable), getHistType(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, HistTable), {Specs.at(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult)}); + } + if (mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, HistTable), getHistDesc(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, HistTable), getHistType(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, HistTable), {Specs.at(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent)}); + } + if (mPlotDalitz) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kDalitz, HistTable), getHistDesc(kDalitz, HistTable), getHistType(kDalitz, HistTable), {Specs.at(kDalitz)}); } } @@ -546,50 +604,49 @@ class PairHistManager mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMult, HistTable)), mKstar, mMult); mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsCent, HistTable)), mKstar, mCent); - // // special care for mass plots since not all particles have "mass" - if constexpr (modes::hasMass(particleType1)) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass1, HistTable)), mKstar, mMass1); - } - if constexpr (modes::hasMass(particleType2)) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass2, HistTable)), mKstar, mMass2); - } - if constexpr (modes::hasMass(particleType1) && modes::hasMass(particleType2)) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kMass1VsMass2, HistTable)), mMass1, mMass2); - } + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass1, HistTable)), mKstar, mRecoMass1); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass2, HistTable)), mKstar, mRecoMass2); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kMass1VsMass2, HistTable)), mRecoMass1, mRecoMass2); } // n-D histograms are only filled if enabled + // if "mass" getter does not exist for particle, it will be just set to 0 + // the user has to make sure that in this case the bin number of this dimension is set to 1 if (mPlotKstarVsMtVsMult) { mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMult, HistTable)), mKstar, mMt, mMult); } if (mPlotKstarVsMtVsMultVsCent) { mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMultVsCent, HistTable)), mKstar, mMt, mMult, mCent); } - if (mPlotKstarVsMtVsPt1VsP2VsMult) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsPt1VsPt2VsMult, HistTable)), mKstar, mMt, mParticle1.Pt(), mParticle2.pt(), mMult); + if (mPlotKstarVsMtVsPt1VsPt2) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsPt1VsPt2, HistTable)), mKstar, mMt, mParticle1.Pt(), mParticle2.Pt()); } - if (mPlotKstarVsMtVsPt1VsP2VsMultVsCent) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsPt1VsPt2VsMultVsCent, HistTable)), mKstar, mMt, mParticle1.Pt(), mParticle2.pt(), mMult, mCent); + if (mPlotKstarVsMtVsPt1VsPt2VsMult) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsPt1VsPt2VsMult, HistTable)), mKstar, mMt, mParticle1.Pt(), mParticle2.Pt(), mMult); } - - // again special care for particles with "mass" - if constexpr (modes::hasMass(particleType1)) { - if (mPlotKstarVsMass1VsMult) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass1VsMult, HistTable)), mKstar, mMass1, mMult); - } + if (mPlotKstarVsMtVsPt1VsPt2VsMultVsCent) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsPt1VsPt2VsMultVsCent, HistTable)), mKstar, mMt, mParticle1.Pt(), mParticle2.Pt(), mMult, mCent); } - if constexpr (modes::hasMass(particleType2)) { - if (mPlotKstarVsMass2VsMult) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass2VsMult, HistTable)), mKstar, mMass2, mMult); - } + if (mPlotKstarVsMtVsMass1VsMass2) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMass1VsMass2, HistTable)), mKstar, mMt, mRecoMass1, mRecoMass2); } - if constexpr (modes::hasMass(particleType1) && modes::hasMass(particleType2)) { - if (mPlotKstarVsMass1VsMass2) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass1VsMass2, HistTable)), mKstar, mMass1, mMass2); - } - if (mPlotKstarVsMass1VsMass2VsMult) { - mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMass1VsMass2VsMult, HistTable)), mKstar, mMass1, mMass2, mMult); - } + if (mPlotKstarVsMtVsMass1VsMass2VsMult) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMass1VsMass2VsMult, HistTable)), mKstar, mMt, mRecoMass1, mRecoMass2, mMult); + } + if (mPlotKstarVsMtVsMass1VsMass2VsMultVsCent) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMass1VsMass2VsMultVsCent, HistTable)), mKstar, mMt, mRecoMass1, mRecoMass2, mMult, mCent); + } + if (mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMass1VsMass2VsPt1VsPt2, HistTable)), mKstar, mMt, mRecoMass1, mRecoMass2, mParticle1.Pt(), mParticle2.Pt()); + } + if (mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult, HistTable)), mKstar, mMt, mRecoMass1, mRecoMass2, mParticle1.Pt(), mParticle2.Pt(), mMult); + } + if (mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent, HistTable)), mKstar, mMt, mRecoMass1, mRecoMass2, mParticle1.Pt(), mParticle2.Pt(), mMult, mCent); + } + if (mPlotDalitz) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kDalitz, HistTable)), mKstar, mMassTot2, mMass12, mMass13); } } @@ -606,47 +663,79 @@ class PairHistManager } } - float computeMt(ROOT::Math::PtEtaPhiMVector const& PairMomentum) + float getKt(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2) { - float mt = 0; + auto sum = (part1 + part2); + double kt = 0.5 * sum.Pt(); + return static_cast(kt); + } + + float getMt(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2) + { + auto sum = part1 + part2; + double mt = 0; + double averageMass = 0; + double reducedMass = 0; switch (mMtType) { case modes::TransverseMassType::kAveragePdgMass: - mt = std::hypot(0.5 * PairMomentum.Pt(), mAverageMass); + averageMass = 0.5 * (part1.M() + part2.M()); + mt = std::hypot(0.5 * sum.Pt(), averageMass); break; case modes::TransverseMassType::kReducedPdgMass: - mt = std::hypot(0.5 * PairMomentum.Pt(), mReducedMass); + reducedMass = 2. * (part1.M() * part2.M()) / (part1.M() + part2.M()); + mt = std::hypot(0.5 * sum.Pt(), reducedMass); break; case modes::TransverseMassType::kMt4Vector: - mt = PairMomentum.Mt() / 2.f; + mt = 0.5 * sum.Mt(); break; default: - LOG(warn) << "Invalid transverse mass type, falling back to default..."; - mt = std::hypot(0.5 * PairMomentum.Pt(), mAverageMass); + LOG(fatal) << "Invalid transverse mass type, breaking..."; } - return mt; + return static_cast(mt); + } + + float getKstar(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2) + { + // compute pair momentum + auto sum = part1 + part2; + // Boost particle 1 to the pair rest frame (Prf) and calculate k* (would be equivalent using particle 2) + // make a copy of particle 1 + auto particle1Prf = ROOT::Math::PtEtaPhiMVector(part1); + // get lorentz boost into pair rest frame + ROOT::Math::Boost boostPrf(sum.BoostToCM()); + // boost particle 1 into pair rest frame and calculate its momentum, which has the same value as k* + return static_cast(boostPrf(particle1Prf).P()); } o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; - float mPdgMass1 = 0.f; - float mPdgMass2 = 0.f; + bool mUsePdgMass = true; + double mPdgMass1 = 0.; + double mPdgMassPosDau1 = 0; + double mPdgMassNegDau1 = 0; + double mPdgMass2 = 0.; + double mPdgMassPosDau2 = 0; + double mPdgMassNegDau2 = 0; modes::TransverseMassType mMtType = modes::TransverseMassType::kAveragePdgMass; - float mAverageMass = 0.f; - float mReducedMass = 0.f; int mAbsCharge1 = 1; int mAbsCharge2 = 1; ROOT::Math::PtEtaPhiMVector mParticle1{}; ROOT::Math::PtEtaPhiMVector mParticle2{}; - float mMass1 = 0.f; - float mMass2 = 0.f; + float mRecoMass1 = 0.f; + float mRecoMass2 = 0.f; float mKstar = 0.f; float mKt = 0.f; float mMt = 0.f; float mMult = 0.f; float mCent = 0.f; + double mMass12 = 0.; + double mMass13 = 0.; + double mMassTot2 = 0.; // mc + ROOT::Math::PtEtaPhiMVector mTrueParticle1{}; + ROOT::Math::PtEtaPhiMVector mTrueParticle2{}; float mTrueKstar = 0.f; float mTrueKt = 0.f; float mTrueMt = 0.f; @@ -666,15 +755,23 @@ class PairHistManager // flags bool mPlot1d = true; bool mPlot2d = true; + bool mPlotKstarVsMtVsMult = false; bool mPlotKstarVsMtVsMultVsCent = false; - bool mPlotKstarVsMtVsPt1VsP2VsMult = false; - bool mPlotKstarVsMtVsPt1VsP2VsMultVsCent = false; - bool mPlotKstarVsMass1VsMass2 = false; - bool mPlotKstarVsMass1VsMult = false; - bool mPlotKstarVsMass2VsMult = false; - bool mPlotKstarVsMass1VsMass2VsMult = false; + bool mPlotKstarVsMtVsPt1VsPt2 = false; + bool mPlotKstarVsMtVsPt1VsPt2VsMult = false; + bool mPlotKstarVsMtVsPt1VsPt2VsMultVsCent = false; + + bool mPlotKstarVsMtVsMass1VsMass2 = false; + bool mPlotKstarVsMtVsMass1VsMass2VsMult = false; + bool mPlotKstarVsMtVsMass1VsMass2VsMultVsCent = false; + + bool mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2 = false; + bool mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMult = false; + bool mPlotKstarVsMtVsMass1VsMass2VsPt1VsPt2VsMultVsCent = false; + + bool mPlotDalitz = false; }; }; // namespace pairhistmanager diff --git a/PWGCF/Femto/Core/pairProcessHelpers.h b/PWGCF/Femto/Core/pairProcessHelpers.h index 6380685bdc2..9279921b00b 100644 --- a/PWGCF/Femto/Core/pairProcessHelpers.h +++ b/PWGCF/Femto/Core/pairProcessHelpers.h @@ -19,16 +19,20 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" +#include -#include +#include namespace o2::analysis::femto { namespace pairprocesshelpers { +enum PairOrder : uint8_t { + kOrder12, + kOrder21 +}; + // process same event for identical particles template + typename T7> void processSameEvent(T1 const& SliceParticle, T2 const& TrackTable, T3 const& Collision, @@ -46,13 +49,11 @@ void processSameEvent(T1 const& SliceParticle, T5& PairHistManager, T6& CprManager, T7& PcManager, - T8& rng, - bool randomize) + PairOrder pairOrder) { for (auto const& part : SliceParticle) { ParticleHistManager.template fill(part, TrackTable); } - std::uniform_real_distribution dist(0.f, 1.f); for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle, SliceParticle))) { // check if pair is clean if (!PcManager.isCleanPair(p1, p2, TrackTable)) { @@ -64,12 +65,15 @@ void processSameEvent(T1 const& SliceParticle, continue; } // Randomize pair order if enabled - float threshold = 0.5f; - bool swapPair = randomize ? (dist(rng) > threshold) : false; - if (swapPair) { - PairHistManager.setPair(p2, p1, Collision); - } else { - PairHistManager.setPair(p1, p2, Collision); + switch (pairOrder) { + case kOrder12: + PairHistManager.setPair(p1, p2, TrackTable, Collision); + break; + case kOrder21: + PairHistManager.setPair(p2, p1, TrackTable, Collision); + break; + default: + PairHistManager.setPair(p1, p2, TrackTable, Collision); } // fill deta-dphi histograms with kstar cutoff CprManager.fill(PairHistManager.getKstar()); @@ -103,16 +107,23 @@ void processSameEvent(T1 const& SliceParticle, T7 const& mcCollisions, T8& ParticleHistManager, T9& PairHistManager, - T10& CprManager, - T11& PcManager, - T12& rng, - bool randomize) + T10& ParticleCleaner, + T11& CprManager, + T12& PcManager, + PairOrder pairOrder) { for (auto const& part : SliceParticle) { + if (!ParticleCleaner.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } ParticleHistManager.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); } - std::uniform_real_distribution dist(0.f, 1.f); for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle, SliceParticle))) { + // check if particles are clean + if (!ParticleCleaner.isClean(p1, mcParticles, mcMothers, mcPartonicMothers) || + !ParticleCleaner.isClean(p2, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } // check if pair is clean if (!PcManager.isCleanPair(p1, p2, TrackTable, mcPartonicMothers)) { continue; @@ -123,12 +134,15 @@ void processSameEvent(T1 const& SliceParticle, continue; } // Randomize pair order if enabled - float threshold = 0.5f; - bool swapPair = randomize ? (dist(rng) > threshold) : false; - if (swapPair) { - PairHistManager.setPairMc(p2, p1, mcParticles, Collision, mcCollisions); - } else { - PairHistManager.setPairMc(p1, p2, mcParticles, Collision, mcCollisions); + switch (pairOrder) { + case kOrder12: + PairHistManager.setPairMc(p1, p2, TrackTable, mcParticles, Collision, mcCollisions); + break; + case kOrder21: + PairHistManager.setPairMc(p2, p1, TrackTable, mcParticles, Collision, mcCollisions); + break; + default: + PairHistManager.setPairMc(p1, p2, TrackTable, mcParticles, Collision, mcCollisions); } // fill deta-dphi histograms with kstar cutoff CprManager.fill(PairHistManager.getKstar()); @@ -177,7 +191,7 @@ void processSameEvent(T1 const& SliceParticle1, if (CprManager.isClosePair()) { continue; } - PairHistManager.setPair(p1, p2, Collision); + PairHistManager.setPair(p1, p2, TrackTable, Collision); CprManager.fill(PairHistManager.getKstar()); if (PairHistManager.checkPairCuts()) { PairHistManager.template fill(); @@ -199,7 +213,9 @@ template + typename T13, + typename T14, + typename T15> void processSameEvent(T1 const& SliceParticle1, T2 const& SliceParticle2, T3 const& TrackTable, @@ -211,17 +227,30 @@ void processSameEvent(T1 const& SliceParticle1, T9& ParticleHistManager1, T10& ParticleHistManager2, T11& PairHistManager, - T12& CprManager, - T13& PcManager) + T12& ParticleCleaner1, + T13& ParticleCleaner2, + T14& CprManager, + T15& PcManager) { // Fill single particle histograms for (auto const& part : SliceParticle1) { + if (!ParticleCleaner1.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } ParticleHistManager1.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& part : SliceParticle2) { + if (!ParticleCleaner2.isClean(part, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } ParticleHistManager2.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); } for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(SliceParticle1, SliceParticle2))) { + // check if particles are clean + if (!ParticleCleaner1.isClean(p1, mcParticles, mcMothers, mcPartonicMothers) || + !ParticleCleaner2.isClean(p2, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } // pair cleaning if (!PcManager.isCleanPair(p1, p2, TrackTable, mcPartonicMothers)) { continue; @@ -231,7 +260,7 @@ void processSameEvent(T1 const& SliceParticle1, if (CprManager.isClosePair()) { continue; } - PairHistManager.setPairMc(p1, p2, mcParticles, Collision, mcCollisions); + PairHistManager.setPairMc(p1, p2, TrackTable, mcParticles, Collision, mcCollisions); CprManager.fill(PairHistManager.getKstar()); if (PairHistManager.checkPairCuts()) { PairHistManager.template fill(); @@ -239,111 +268,7 @@ void processSameEvent(T1 const& SliceParticle1, } } -// process mixed event for identical particles -template -void processMixedEvent(T1 const& Collisions, - T2& Partition, - T3 const& TrackTable, - T4& cache, - T5 const& policy, - T6 const& depth, - T7& PairHistManager, - T8& CprManager, - T9& PcManager) -{ - for (auto const& [collision1, collision2] : o2::soa::selfCombinations(policy, depth, -1, Collisions, Collisions)) { - if (!(std::fabs(collision1.magField() - collision2.magField()) < o2::constants::math::Epsilon)) { - continue; - } - CprManager.setMagField(collision1.magField()); - auto sliceParticle1 = Partition->sliceByCached(o2::aod::femtobase::stored::fColId, collision1.globalIndex(), cache); - auto sliceParticle2 = Partition->sliceByCached(o2::aod::femtobase::stored::fColId, collision2.globalIndex(), cache); - if (sliceParticle1.size() == 0 || sliceParticle2.size() == 0) { - continue; - } - for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(sliceParticle1, sliceParticle2))) { - // pair cleaning - if (!PcManager.isCleanPair(p1, p2, TrackTable)) { - continue; - } - // Close pair rejection - CprManager.setPair(p1, p2, TrackTable); - if (CprManager.isClosePair()) { - continue; - } - PairHistManager.setPair(p1, p2, collision1, collision2); - CprManager.fill(PairHistManager.getKstar()); - if (PairHistManager.checkPairCuts()) { - PairHistManager.template fill(); - } - } - } -} - -// process mixed event for identical particles with mc information -template -void processMixedEvent(T1 const& Collisions, - T2 const& mcCollisions, - T3& Partition, - T4 const& TrackTable, - T5 const& mcParticles, - T6& cache, - T7 const& policy, - T8 const& depth, - T9& PairHistManager, - T10& CprManager, - T11& PcManager) -{ - for (auto const& [collision1, collision2] : o2::soa::selfCombinations(policy, depth, -1, Collisions, Collisions)) { - if (!(std::fabs(collision1.magField() - collision2.magField()) < o2::constants::math::Epsilon)) { - continue; - } - CprManager.setMagField(collision1.magField()); - auto sliceParticle1 = Partition->sliceByCached(o2::aod::femtobase::stored::fColId, collision1.globalIndex(), cache); - auto sliceParticle2 = Partition->sliceByCached(o2::aod::femtobase::stored::fColId, collision2.globalIndex(), cache); - if (sliceParticle1.size() == 0 || sliceParticle2.size() == 0) { - continue; - } - for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(sliceParticle1, sliceParticle2))) { - // pair cleaning - if (!PcManager.isCleanPair(p1, p2, TrackTable)) { - continue; - } - // Close pair rejection - CprManager.setPair(p1, p2, TrackTable); - if (CprManager.isClosePair()) { - continue; - } - PairHistManager.setPairMc(p1, p2, mcParticles, collision1, collision2, mcCollisions); - CprManager.fill(PairHistManager.getKstar()); - if (PairHistManager.checkPairCuts()) { - PairHistManager.template fill(); - } - } - } -} - -// process mixed event different particles +// process mixed event template (); @@ -395,7 +320,7 @@ void processMixedEvent(T1 const& Collisions, } } -// process mixed event different particles with mc information +// process mixed event with mc information template + typename T12, + typename T13, + typename T14, + typename T15, + typename T16> void processMixedEvent(T1 const& Collisions, T2 const& mcCollisions, T3& Partition1, T4& Partition2, T5 const& TrackTable, T6 const& mcParticles, - T7& cache, - T8& policy, - T9& depth, - T10& PairHistManager, - T11& CprManager, - T12& PcManager) + T7 const& mcMothers, + T8 const& mcPartonicMothers, + T9& cache, + T10 const& policy, + T11 const& depth, + T12& PairHistManager, + T13& ParticleCleaner1, + T14& ParticleCleaner2, + T15& CprManager, + T16& PcManager) { for (auto const& [collision1, collision2] : o2::soa::selfCombinations(policy, depth, -1, Collisions, Collisions)) { - if (!(std::fabs(collision1.magField() - collision2.magField()) < o2::constants::math::Epsilon)) { + if (collision1.magField() != collision2.magField()) { continue; } CprManager.setMagField(collision1.magField()); @@ -433,6 +366,11 @@ void processMixedEvent(T1 const& Collisions, continue; } for (auto const& [p1, p2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(sliceParticle1, sliceParticle2))) { + // particle cleaning + if (!ParticleCleaner1.isClean(p1, mcParticles, mcMothers, mcPartonicMothers) || + !ParticleCleaner2.isClean(p2, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } // pair cleaning if (!PcManager.isCleanPair(p1, p2, TrackTable)) { continue; @@ -442,7 +380,7 @@ void processMixedEvent(T1 const& Collisions, if (CprManager.isClosePair()) { continue; } - PairHistManager.setPairMc(p1, p2, mcParticles, collision1, collision2, mcCollisions); + PairHistManager.setPairMc(p1, p2, TrackTable, mcParticles, collision1, collision2, mcCollisions); CprManager.fill(PairHistManager.getKstar()); if (PairHistManager.checkPairCuts()) { PairHistManager.template fill(); diff --git a/PWGCF/Femto/Core/particleCleaner.h b/PWGCF/Femto/Core/particleCleaner.h new file mode 100644 index 00000000000..045f3dea785 --- /dev/null +++ b/PWGCF/Femto/Core/particleCleaner.h @@ -0,0 +1,232 @@ +// 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 particleCleaner.h +/// \brief particle cleaner class +/// \author anton.riedel@tum.de, TU München, anton.riedel@tum.de + +#ifndef PWGCF_FEMTO_CORE_PARTICLECLEANER_H_ +#define PWGCF_FEMTO_CORE_PARTICLECLEANER_H_ + +#include + +#include +#include + +namespace o2::analysis::femto +{ +namespace particlecleaner +{ + +template +struct ConfParticleCleaner : o2::framework::ConfigurableGroup { + std::string prefix = std::string(Prefix); + o2::framework::Configurable activate{"activate", false, "Activate particle cleaner"}; + o2::framework::Configurable> requiredPdgCodes{"requiredPdgCodes", {}, "Only consider particles with this exact pdg code (including the sign!)"}; + o2::framework::Configurable> rejectedPdgCodes{"rejectedPdgCodes", {}, "Reject particles with this exact pdg code (including the sign!)"}; + o2::framework::Configurable rejectParticleWithoutMcParticle{"rejectParticleWithoutMcParticle", false, "If true, particles which have no associated MC information, are rejected"}; + o2::framework::Configurable rejectParticleWithoutMcMother{"rejectParticleWithoutMcMother", false, "If true, particles which have no associated mother are rejected"}; + o2::framework::Configurable rejectParticleWithoutMcPartonicMother{"rejectParticleWithoutMcPartonicMother", false, "If true, all particles which have no associated partonic mother"}; + o2::framework::Configurable> requiredMotherPdgCodes{"requiredMotherPdgCodes", {}, "Only consider particles whose mothers have one of the supplied pdg codes (inclduing the sign!)"}; + o2::framework::Configurable> rejectMotherPdgCodes{"rejectMotherPdgCodes", {}, "Only consider particles whose mothers do not have one of the supplied pdg codes (inclduing the sign!)"}; + o2::framework::Configurable> requiredPartonicMotherPdgCodes{"requiredPartonicMotherPdgCodes", {}, "Only consider particles whose partonic mothers have one of the supplied pdg codes (inclduing the sign!)"}; + o2::framework::Configurable> rejectPartonicMotherPdgCodes{"rejectPartonicMotherPdgCodes", {}, "Only consider particles whose mothers do not have one of the supplied pdg codes (inclduing the sign!)"}; +}; + +constexpr const char PrefixTrackCleaner1[] = "TrackCleaner1"; +constexpr const char PrefixTrackCleaner2[] = "TrackCleaner2"; +constexpr const char PrefixTrackCleaner3[] = "TrackCleaner3"; +using ConfTrackCleaner1 = ConfParticleCleaner; +using ConfTrackCleaner2 = ConfParticleCleaner; +using ConfTrackCleaner3 = ConfParticleCleaner; + +constexpr const char PrefixLambdaCleaner1[] = "LambdaCleaner1"; +constexpr const char PrefixLambdaCleaner2[] = "LambdaCleaner2"; +using ConfLambdaCleaner1 = ConfParticleCleaner; +using ConfLambdaCleaner2 = ConfParticleCleaner; + +constexpr const char PrefixK0shortCleaner1[] = "K0shortCleaner1"; +constexpr const char PrefixK0shortCleaner2[] = "K0shortCleaner2"; +using ConfK0shortCleaner1 = ConfParticleCleaner; +using ConfK0shortCleaner2 = ConfParticleCleaner; + +constexpr const char PrefixSigmaCleaner1[] = "SigmaCleaner1"; +constexpr const char PrefixSigmaCleaner2[] = "SigmaCleaner2"; +using ConfSigmaCleaner1 = ConfParticleCleaner; +using ConfSigmaCleaner2 = ConfParticleCleaner; + +constexpr const char PrefixSigmaPlusCleaner1[] = "SigmaPlusCleaner1"; +constexpr const char PrefixSigmaPlusCleaner2[] = "SigmaPlusCleaner2"; +using ConfSigmaPlusCleaner1 = ConfParticleCleaner; +using ConfSigmaPlusCleaner2 = ConfParticleCleaner; + +constexpr const char PrefixXiCleaner1[] = "XiCleaner1"; +constexpr const char PrefixXiCleaner2[] = "XiCleaner2"; +using ConfXiCleaner1 = ConfParticleCleaner; +using ConfXiCleaner2 = ConfParticleCleaner; + +constexpr const char PrefixOmegaCleaner1[] = "OmegaCleaner1"; +constexpr const char PrefixOmegaCleaner2[] = "OmegaCleaner2"; +using ConfOmegaCleaner1 = ConfParticleCleaner; +using ConfOmegaCleaner2 = ConfParticleCleaner; + +class ParticleCleaner +{ + public: + ParticleCleaner() = default; + ~ParticleCleaner() = default; + + template + void init(T const& confMpc) + { + mActivate = confMpc.activate.value; + + mRejectParticleWithoutMcParticle = confMpc.rejectParticleWithoutMcParticle.value; + mRejectParticleWithoutMcMother = confMpc.rejectParticleWithoutMcMother.value; + mRejectParticleWithoutMcPartonicMother = confMpc.rejectParticleWithoutMcPartonicMother.value; + + mRequiredPdgCodes = confMpc.requiredPdgCodes.value; + mRejectedPdgCodes = confMpc.rejectedPdgCodes.value; + + mRequiredMotherPdgCodes = confMpc.requiredMotherPdgCodes.value; + mRejectedMotherPdgCodes = confMpc.rejectMotherPdgCodes.value; + + mRequiredPartonicMotherPdgCodes = confMpc.requiredPartonicMotherPdgCodes.value; + mRejectedPartonicMotherPdgCodes = confMpc.rejectPartonicMotherPdgCodes.value; + } + + template + bool isClean(T1 const& particle, + T2 const& /*mcParticles*/, + T3 const& /*mcMothers*/, + T4 const& /*mcPartonicMothers*/) + { + if (!mActivate) { + return true; + } + + bool hasRequiredPdgCode = true; + bool hasRejectedPdgCode = false; + + bool hasMotherWithRequiredPdgCode = true; + bool hasMotherWithRejectedPdgCode = false; + + bool hasPartonicMotherWithRequiredPdgCode = true; + bool hasPartonicMotherWithRejectedPdgCode = false; + + // MC particle + if (!particle.has_fMcParticle()) { + if (mRejectParticleWithoutMcParticle || !mRequiredPdgCodes.empty()) { + return false; + } + } else { + auto mcParticle = particle.template fMcParticle_as(); + + if (!mRequiredPdgCodes.empty()) { + hasRequiredPdgCode = false; + for (int const& pdgCode : mRequiredPdgCodes) { + if (pdgCode == mcParticle.pdgCode()) { + hasRequiredPdgCode = true; + break; + } + } + } + + if (!mRejectedPdgCodes.empty()) { + for (int const& pdgCode : mRejectedPdgCodes) { + if (pdgCode == mcParticle.pdgCode()) { + hasRejectedPdgCode = true; + break; + } + } + } + } + + // MC mother + if (!particle.has_fMcMother()) { + if (mRejectParticleWithoutMcMother || !mRequiredMotherPdgCodes.empty()) { + return false; + } + } else { + auto mother = particle.template fMcMother_as(); + + if (!mRequiredMotherPdgCodes.empty()) { + hasMotherWithRequiredPdgCode = false; + for (int const& pdgCode : mRequiredMotherPdgCodes) { + if (pdgCode == mother.pdgCode()) { + hasMotherWithRequiredPdgCode = true; + break; + } + } + } + + if (!mRejectedMotherPdgCodes.empty()) { + for (int const& pdgCode : mRejectedMotherPdgCodes) { + if (pdgCode == mother.pdgCode()) { + hasMotherWithRejectedPdgCode = true; + break; + } + } + } + } + + // MC partonic mother + if (!particle.has_fMcPartMoth()) { + if (mRejectParticleWithoutMcPartonicMother || + !mRequiredPartonicMotherPdgCodes.empty()) { + return false; + } + } else { + auto partonicMother = particle.template fMcPartMoth_as(); + + if (!mRequiredPartonicMotherPdgCodes.empty()) { + hasPartonicMotherWithRequiredPdgCode = false; + for (int const& pdgCode : mRequiredPartonicMotherPdgCodes) { + if (pdgCode == partonicMother.pdgCode()) { + hasPartonicMotherWithRequiredPdgCode = true; + break; + } + } + } + + if (!mRejectedPartonicMotherPdgCodes.empty()) { + for (int const& pdgCode : mRejectedPartonicMotherPdgCodes) { + if (pdgCode == partonicMother.pdgCode()) { + hasPartonicMotherWithRejectedPdgCode = true; + break; + } + } + } + } + + return hasRequiredPdgCode && !hasRejectedPdgCode && + hasMotherWithRequiredPdgCode && !hasMotherWithRejectedPdgCode && + hasPartonicMotherWithRequiredPdgCode && + !hasPartonicMotherWithRejectedPdgCode; + } + + private: + bool mActivate = false; + bool mRejectParticleWithoutMcParticle = true; + bool mRejectParticleWithoutMcMother = true; + bool mRejectParticleWithoutMcPartonicMother = true; + std::vector mRequiredPdgCodes = {}; + std::vector mRejectedPdgCodes = {}; + std::vector mRequiredMotherPdgCodes{}; + std::vector mRejectedMotherPdgCodes{}; + std::vector mRequiredPartonicMotherPdgCodes{}; + std::vector mRejectedPartonicMotherPdgCodes{}; +}; + +} // namespace particlecleaner +} // namespace o2::analysis::femto + +#endif // PWGCF_FEMTO_CORE_PARTICLECLEANER_H_ diff --git a/PWGCF/Femto/Core/partitions.h b/PWGCF/Femto/Core/partitions.h index d399729d66b..52f2d7bb135 100644 --- a/PWGCF/Femto/Core/partitions.h +++ b/PWGCF/Femto/Core/partitions.h @@ -17,126 +17,139 @@ #define PWGCF_FEMTO_CORE_PARTITIONS_H_ // collsion selection -#define MAKE_COLLISION_FILTER(selection) \ - (femtocollisions::posZ >= selection.vtxZMin && femtocollisions::posZ <= selection.vtxZMax) && \ - (femtocollisions::mult >= selection.multMin && femtocollisions::mult <= selection.multMax) && \ - (femtocollisions::cent >= selection.centMin && femtocollisions::cent <= selection.centMax) && \ - (femtocollisions::magField >= static_cast(selection.magFieldMin) && femtocollisions::magField <= static_cast(selection.magFieldMax)) && \ - ncheckbit(femtocollisions::mask, selection.collisionMask) +#define MAKE_COLLISION_FILTER(selection) \ + (o2::aod::femtocollisions::posZ >= selection.vtxZMin && o2::aod::femtocollisions::posZ <= selection.vtxZMax) && \ + (o2::aod::femtocollisions::mult >= selection.multMin && o2::aod::femtocollisions::mult <= selection.multMax) && \ + (o2::aod::femtocollisions::cent >= selection.centMin && o2::aod::femtocollisions::cent <= selection.centMax) && \ + (o2::aod::femtocollisions::magField >= o2::framework::expressions::as(selection.magFieldMin) && \ + o2::aod::femtocollisions::magField <= o2::framework::expressions::as(selection.magFieldMax)) && \ + ncheckbit(o2::aod::femtocollisions::mask, selection.collisionMask) + +// macro for track momentum, i.e. ||q|*pT/q| * cosh(eta) +// there is no ncosh function, so we have to make our own, i.e. cosh(x) = (exp(x)+exp(-x))/2 +#define TRACK_MOMENTUM(chargeAbs, signedPt, eta) nabs((chargeAbs) * (signedPt)) * (nexp(eta) + nexp(-1.f * (eta))) / 2.f // standard track partition -#define MAKE_TRACK_PARTITION(selection) \ - ifnode(selection.chargeSign.node() != 0, ifnode(selection.chargeSign.node() > 0, femtobase::stored::signedPt > 0.f, femtobase::stored::signedPt < 0.f), true) && \ - (nabs(selection.chargeAbs.node() * femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(selection.chargeAbs.node() * femtobase::stored::signedPt) < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - ifnode(nabs(selection.chargeAbs.node() * femtobase::stored::signedPt) * (nexp(femtobase::stored::eta) + nexp(-1.f * femtobase::stored::eta)) / (2.f) <= selection.pidThres, \ - ncheckbit(femtotracks::mask, selection.maskLowMomentum), \ - ncheckbit(femtotracks::mask, selection.maskHighMomentum)) +#define MAKE_TRACK_PARTITION(selection) \ + ifnode(selection.chargeSign.node() != 0, ifnode(selection.chargeSign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(selection.chargeAbs * o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(selection.chargeAbs * o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + ifnode(TRACK_MOMENTUM(selection.chargeAbs, o2::aod::femtobase::stored::signedPt, o2::aod::femtobase::stored::eta) <= selection.pidThres, \ + ncheckbit(o2::aod::femtotracks::mask, selection.maskLowMomentum) && \ + (o2::aod::femtotracks::mask & selection.rejectionMaskLowMomentum) == static_cast(0), \ + ncheckbit(o2::aod::femtotracks::mask, selection.maskHighMomentum) && \ + (o2::aod::femtotracks::mask & selection.rejectionMaskHighMomentum) == static_cast(0)) + +// track partition with optional mass cut +#define MAKE_TRACK_PARTITION_WITH_MASS(selection) \ + MAKE_TRACK_PARTITION(selection) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) // partition for phis and rhos, i.e. resonance that are their own antiparticle -#define MAKE_RESONANCE_0_PARTITON(selection) \ - (femtobase::stored::pt > selection.ptMin) && \ - (femtobase::stored::pt < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ifnode(ncheckbit(femtotwotrackresonances::mask, selection.posDauBitForThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.posDauMaskAboveThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.posDauMaskBelowThres)) && \ - ifnode(ncheckbit(femtotwotrackresonances::mask, selection.negDauBitForThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.negDauMaskAboveThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.negDauMaskBelowThres)) +#define MAKE_RESONANCE_0_PARTITON(selection) \ + (o2::aod::femtobase::stored::pt > selection.ptMin) && \ + (o2::aod::femtobase::stored::pt < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ifnode(ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.posDauBitForThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.posDauMaskAboveThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.posDauMaskBelowThres)) && \ + ifnode(ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.negDauBitForThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.negDauMaskAboveThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.negDauMaskBelowThres)) // partition for kstars, they have distinct antiparticle -#define MAKE_RESONANCE_1_PARTITON(selection) \ - ifnode(selection.sign.node() != 0, \ - ifnode(selection.sign.node() > 0, femtobase::stored::signedPt > 0.f, femtobase::stored::signedPt < 0.f), true) && \ - (nabs(femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(femtobase::stored::signedPt) < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ifnode(ncheckbit(femtotwotrackresonances::mask, selection.posDauBitForThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.posDauMaskAboveThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.posDauMaskBelowThres)) && \ - ifnode(ncheckbit(femtotwotrackresonances::mask, selection.negDauBitForThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.negDauMaskAboveThres), \ - ncheckbit(femtotwotrackresonances::mask, selection.negDauMaskBelowThres)) +#define MAKE_RESONANCE_1_PARTITON(selection) \ + ifnode(selection.sign.node() != 0, \ + ifnode(selection.sign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ifnode(ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.posDauBitForThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.posDauMaskAboveThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.posDauMaskBelowThres)) && \ + ifnode(ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.negDauBitForThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.negDauMaskAboveThres), \ + ncheckbit(o2::aod::femtotwotrackresonances::mask, selection.negDauMaskBelowThres)) // partition for lambdas -#define MAKE_LAMBDA_PARTITION(selection) \ - ifnode(selection.sign.node() != 0, \ - ifnode(selection.sign.node() > 0, femtobase::stored::signedPt > 0.f, femtobase::stored::signedPt < 0.f), true) && \ - (nabs(femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(femtobase::stored::signedPt) < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ncheckbit(femtov0s::mask, selection.mask) +#define MAKE_LAMBDA_PARTITION(selection) \ + ifnode(selection.sign.node() != 0, \ + ifnode(selection.sign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ncheckbit(o2::aod::femtov0s::mask, selection.mask) // partition for k0shorts // need special partition since k0shorts have no antiparticle -#define MAKE_K0SHORT_PARTITION(selection) \ - (femtobase::stored::pt > selection.ptMin) && \ - (femtobase::stored::pt < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ncheckbit(femtov0s::mask, selection.mask) +#define MAKE_K0SHORT_PARTITION(selection) \ + (o2::aod::femtobase::stored::pt > selection.ptMin) && \ + (o2::aod::femtobase::stored::pt < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ncheckbit(o2::aod::femtov0s::mask, selection.mask) -#define MAKE_CASCADE_PARTITION(selection) \ - ifnode(selection.sign.node() != 0, \ - ifnode(selection.sign.node() > 0, femtobase::stored::signedPt > 0.f, femtobase::stored::signedPt < 0.f), true) && \ - (nabs(femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(femtobase::stored::signedPt) < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ncheckbit(femtocascades::mask, selection.mask) +#define MAKE_CASCADE_PARTITION(selection) \ + ifnode(selection.sign.node() != 0, \ + ifnode(selection.sign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ncheckbit(o2::aod::femtocascades::mask, selection.mask) -#define MAKE_SIGMA_PARTITION(selection) \ - ifnode(selection.sign.node() != 0, \ - ifnode(selection.sign.node() > 0, femtobase::stored::signedPt > 0.f, femtobase::stored::signedPt < 0.f), true) && \ - (nabs(femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(femtobase::stored::signedPt) < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ncheckbit(femtokinks::mask, selection.mask) +#define MAKE_SIGMA_PARTITION(selection) \ + ifnode(selection.sign.node() != 0, \ + ifnode(selection.sign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ncheckbit(o2::aod::femtokinks::mask, selection.mask) -#define MAKE_SIGMAPLUS_PARTITION(selection) \ - ifnode(selection.sign.node() != 0, \ - ifnode(selection.sign.node() > 0, femtobase::stored::signedPt > 0.f, femtobase::stored::signedPt < 0.f), true) && \ - (nabs(femtobase::stored::signedPt) > selection.ptMin) && \ - (nabs(femtobase::stored::signedPt) < selection.ptMax) && \ - (femtobase::stored::eta > selection.etaMin) && \ - (femtobase::stored::eta < selection.etaMax) && \ - (femtobase::stored::phi > selection.phiMin) && \ - (femtobase::stored::phi < selection.phiMax) && \ - (femtobase::stored::mass > selection.massMin) && \ - (femtobase::stored::mass < selection.massMax) && \ - ncheckbit(femtokinks::mask, selection.mask) +#define MAKE_SIGMAPLUS_PARTITION(selection) \ + ifnode(selection.sign.node() != 0, \ + ifnode(selection.sign.node() > 0, o2::aod::femtobase::stored::signedPt > 0.f, o2::aod::femtobase::stored::signedPt < 0.f), true) && \ + (nabs(o2::aod::femtobase::stored::signedPt) > selection.ptMin) && \ + (nabs(o2::aod::femtobase::stored::signedPt) < selection.ptMax) && \ + (o2::aod::femtobase::stored::eta > selection.etaMin) && \ + (o2::aod::femtobase::stored::eta < selection.etaMax) && \ + (o2::aod::femtobase::stored::phi > selection.phiMin) && \ + (o2::aod::femtobase::stored::phi < selection.phiMax) && \ + (o2::aod::femtobase::stored::mass > selection.massMin) && \ + (o2::aod::femtobase::stored::mass < selection.massMax) && \ + ncheckbit(o2::aod::femtokinks::mask, selection.mask) #endif // PWGCF_FEMTO_CORE_PARTITIONS_H_ diff --git a/PWGCF/Femto/Core/selectionContainer.h b/PWGCF/Femto/Core/selectionContainer.h index e9d67e6354a..fe5616f8302 100644 --- a/PWGCF/Femto/Core/selectionContainer.h +++ b/PWGCF/Femto/Core/selectionContainer.h @@ -16,19 +16,21 @@ #ifndef PWGCF_FEMTO_CORE_SELECTIONCONTAINER_H_ #define PWGCF_FEMTO_CORE_SELECTIONCONTAINER_H_ -#include "CommonConstants/MathConstants.h" +#include +#include -#include "TF1.h" - -#include "fairlogger/Logger.h" +#include #include #include #include #include #include +#include +#include #include #include +#include #include namespace o2::analysis::femto @@ -37,20 +39,21 @@ namespace o2::analysis::femto /// Limit type for selections namespace limits { -enum LimitType { kUpperLimit, ///< simple upper limit for the value, e.g. p_T < 1 GeV/c - kAbsUpperLimit, ///< upper limit of the absolute value, e.g. |eta| < 0.8 - kLowerLimit, ///< simple lower limit for the value, e.g. p_T > 0.2 GeV/c - kAbsLowerLimit, ///< lower limit of the absolute value, e.g. |DCA_xyz| > 0.05 cm - kUpperFunctionLimit, ///< simple upper limit of a function value, e.g. DCA_xy > f(pt) - kAbsUpperFunctionLimit, ///< upper limit of an absolute value given by a function, e.g. |DCA_xy| > f(pt) - kLowerFunctionLimit, ///< simple lower limit of a function value, e.g. DCA_xy < f(pt) - kAbsLowerFunctionLimit, ///< lower limit of an absolute value given by a function, e.g. |DCA_xy| < f(pt) - kEqual, ///< values need to be equal, e.g. sign = 1 - kEqualArray, ///< values inside an array need to be equal +enum LimitType { kUpperLimit, ///< simple upper limit, e.g. p_T < 1 GeV/c + kAbsUpperLimit, ///< upper limit on the absolute value, e.g. |eta| < 0.8 + kLowerLimit, ///< simple lower limit, e.g. p_T > 0.2 GeV/c + kAbsLowerLimit, ///< lower limit on the absolute value, e.g. |DCA_xy| > 0.05 cm + kUpperFunctionLimit, ///< upper limit given by a function, e.g. DCA_xy < f(pt) + kAbsUpperFunctionLimit, ///< upper limit on the absolute value given by a function, e.g. |DCA_xy| < f(pt) + kLowerFunctionLimit, ///< lower limit given by a function, e.g. DCA_xy > f(pt) + kAbsLowerFunctionLimit, ///< lower limit on the absolute value given by a function, e.g. |DCA_xy| > f(pt) + kEqual, ///< value must equal a fixed threshold, e.g. sign == 1 + kEqualArray, ///< each element of a value array must equal the corresponding threshold + kRange, ///< value must fall within [lower, upper]; either bound can be omitted (open interval) kLimitTypeLast }; -std::unordered_map limitTypeAsStrings = { +inline const std::unordered_map limitTypeAsStrings = { {kUpperLimit, "Upper Limit"}, {kAbsUpperLimit, "Absolute Upper Limit"}, {kLowerLimit, "Lower Limit"}, @@ -61,283 +64,358 @@ std::unordered_map limitTypeAsStrings = { {kAbsLowerFunctionLimit, "Absolute Lower Function Limit"}, {kEqual, "Equal"}, {kEqualArray, "EqualArray"}, - + {kRange, "Range"}, + {kLimitTypeLast, "Last Limit Type"}, }; }; // namespace limits /// \class SelectionContainer -/// \brief Class for storing and evaluating multiple selection thresholds for a single observable. -/// \tparam T Data type for selection values (mostly floats) -/// \tparam BitmaskType Type used for bitmask storage (e.g., uint8_t, uint32_t). +/// \brief Stores and evaluates multiple selection thresholds for a single observable. +/// +/// Selections can be based on static threshold values or dynamically evaluated TF1 functions. +/// Thresholds are sorted from most permissive to most restrictive so that evaluation can bail +/// out early once a threshold fails. +/// +/// \tparam T Data type for selection values (mostly floats). +/// \tparam BitmaskType Integer type used for bitmask storage (e.g., uint8_t, uint32_t). template class SelectionContainer { public: - /// Default constructor + /// \brief Default constructor. SelectionContainer() = default; + + /// \brief Destructor. ~SelectionContainer() = default; - /// \brief Constructor for static value-based selection. - /// \param SelectionValues Vector of values for the selection. + /// \brief Constructor for static value-based selections. + /// \param selectionName Name of the observable this container manages. + /// \param selectionValues Vector of threshold values. /// \param limitType Type of limit (from limits::LimitType). - /// \param SkipMostPermissiveBit Whether to skip the most permissive bit in the bitmask. - /// \param IsMinimalCut Whether this selection should be treated as a minimal required cut. - SelectionContainer(std::string const& SelectionName, - std::vector const& SelectionValues, + /// \param skipMostPermissiveBit Whether to skip the most permissive threshold when assembling the bitmask. + /// \param isMinimalCut Whether this selection is mandatory (candidate is rejected if it fails). + /// \param isOptionalCut Whether this selection is optional (candidate is accepted if any optional cut passes). + SelectionContainer(std::string const& selectionName, + std::vector const& selectionValues, limits::LimitType limitType, - bool SkipMostPermissiveBit, - bool IsMinimalCut, + bool skipMostPermissiveBit, + bool isMinimalCut, bool isOptionalCut) - : mSelectionName(SelectionName), - mSelectionValues(SelectionValues), + : mSelectionName(selectionName), + mSelectionValues(selectionValues), mLimitType(limitType), - mSkipMostPermissiveBit(SkipMostPermissiveBit), - mIsMinimalCut(IsMinimalCut), + mSkipMostPermissiveBit(skipMostPermissiveBit), + mIsMinimalCut(isMinimalCut), mIsOptionalCut(isOptionalCut) { if (mSelectionValues.size() > sizeof(BitmaskType) * CHAR_BIT) { LOG(fatal) << "Too many selections for single a observable. Limit is " << sizeof(BitmaskType) * CHAR_BIT; } + if (isMinimalCut && isOptionalCut) { + LOG(fatal) << "A selection cannot be both minimal and optional"; + } // values for selection are not necessarily ordered correctly sortSelections(); } - /// \brief Constructor for function-based dynamic selection. - /// \param baseName Base name for TF1 functions. - /// \param lowerLimit Lower bound for TF1 domain. - /// \param upperLimit Upper bound for TF1 domain. - /// \param functions Vector of strings defining TF1 functions. - /// \param limitType Type of limit. - /// \param skipMostPermissiveBit Whether to skip the most permissive bit in the bitmask. - /// \param IsMinimalCut Whether this selection should be treated as a minimal required cut. - SelectionContainer(std::string const& SelectionName, + /// \brief Constructor for range-based selections defined as "lower;upper" strings. + /// Either bound may be omitted to represent an open interval, e.g. ";1.0" means value < 1.0. + /// \param selectionName Name of the observable this container manages. + /// \param rangeStrings Vector of range strings, each of the form "lower;upper". + /// \param skipMostPermissiveBit Whether to skip the most permissive threshold when assembling the bitmask. + /// \param isMinimalCut Whether this selection is mandatory (candidate is rejected if it fails). + /// \param isOptionalCut Whether this selection is optional (candidate is accepted if any optional cut passes). + SelectionContainer(std::string const& selectionName, + std::vector const& rangeStrings, + bool skipMostPermissiveBit, + bool isMinimalCut, + bool isOptionalCut) + : mSelectionName(selectionName), + mLimitType(limits::kRange), + mSkipMostPermissiveBit(skipMostPermissiveBit), + mIsMinimalCut(isMinimalCut), + mIsOptionalCut(isOptionalCut) + { + if (rangeStrings.size() > sizeof(BitmaskType) * CHAR_BIT) { + LOG(fatal) << "Too many selections for a single observable. Limit is " << sizeof(BitmaskType) * CHAR_BIT; + } + if (isMinimalCut && isOptionalCut) { + LOG(fatal) << "A selection cannot be both minimal and optional"; + } + for (auto const& rangeStr : rangeStrings) { + T lower, upper; + parseRangeString(rangeStr, lower, upper); + mSelectionRanges.emplace_back(lower, upper); + } + // ranges are sorted by their lenghts, i.e. from widest range to tightest range + // in principle the ranges do not have to include each other, exepct this is configured as minimal cut, check is added at the end + // to cover both cases, this also means we always check all ranges, when assembling the bit mask + sortSelections(); + // init mSelectionValues to be the widths of the intervals + for (std::size_t i = 0; i < mSelectionRanges.size(); i++) { + mSelectionValues.push_back(mSelectionRanges[i].second - mSelectionRanges[i].first); + } + + // for minimal range cut, ranges must be strictly nested (each range contains all narrower ones) + // this is required for the early-exit logic in passesAsMinimalCut() to be correct + if (isMinimalCut) { + for (std::size_t i = 0; i + 1 < mSelectionRanges.size(); i++) { + if (mSelectionRanges[i].first > mSelectionRanges[i + 1].first || + mSelectionRanges[i].second < mSelectionRanges[i + 1].second) { + LOG(fatal) << "Ranges for minimal cut " << selectionName + << " are not nested. Range [" << mSelectionRanges[i].first << ";" << mSelectionRanges[i].second + << "] does not contain [" << mSelectionRanges[i + 1].first << ";" << mSelectionRanges[i + 1].second << "]"; + } + } + } + } + + /// \brief Constructor for function-based dynamic selections. + /// \param selectionName Name of the observable this container manages. + /// \param lowerLimit Lower bound of the TF1 domain. + /// \param upperLimit Upper bound of the TF1 domain. + /// \param functions Vector of strings defining TF1 threshold functions. + /// \param limitType Type of limit (from limits::LimitType). + /// \param skipMostPermissiveBit Whether to skip the most permissive threshold when assembling the bitmask. + /// \param isMinimalCut Whether this selection is mandatory (candidate is rejected if it fails). + /// \param isOptionalCut Whether this selection is optional (candidate is accepted if any optional cut passes). + SelectionContainer(std::string const& selectionName, T lowerLimit, T upperLimit, std::vector const& functions, limits::LimitType limitType, bool skipMostPermissiveBit, - bool IsMinimalCut, + bool isMinimalCut, bool isOptionalCut) - : mSelectionName(SelectionName), + : mSelectionName(selectionName), mLimitType(limitType), mSkipMostPermissiveBit(skipMostPermissiveBit), - mIsMinimalCut(IsMinimalCut), + mIsMinimalCut(isMinimalCut), mIsOptionalCut(isOptionalCut) { if (functions.size() > sizeof(BitmaskType) * CHAR_BIT) { LOG(fatal) << "Too many selections for single a observable. Limit is " << sizeof(BitmaskType) * CHAR_BIT; } + if (isMinimalCut && isOptionalCut) { + LOG(fatal) << "A selection cannot be both minimal and optional"; + } for (std::size_t i = 0; i < functions.size(); i++) { mSelectionFunctions.emplace_back((mSelectionName + std::to_string(i)).c_str(), functions.at(i).c_str(), lowerLimit, upperLimit); } - // functions for selection are not necessarily ordered correctly - // use value at midpoint to order them - // here we rely on the user that the functions can be ordered like this over the whole interval + // functions are not necessarily ordered correctly; + // use the midpoint of the domain to establish their order. + // this relies on the user ensuring the ordering is consistent across the whole interval. T midPoint = (lowerLimit + upperLimit) / 2.; sortFunctions(midPoint); - // initialize the values also to the midpoint + // initialize threshold values to the functions evaluated at the midpoint for (std::size_t i = 0; i < functions.size(); i++) { mSelectionValues.push_back(mSelectionFunctions.at(i).Eval(midPoint)); } } - /// \brief Sort static selection values based on the limit type. - void sortSelections() + /// \brief Attach comments to the selection thresholds, one per threshold in the same order as the input values. + /// \param comments Vector of comment strings. + void addComments(std::vector const& comments) { - switch (mLimitType) { - case (limits::kUpperLimit): - case (limits::kAbsUpperLimit): - std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a > b; }); - break; - case (limits::kLowerLimit): - case (limits::kAbsLowerLimit): - std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a < b; }); - break; - default: - break; + // note: threshold values may be reordered by sortSelections() or sortFunctions(), + // so comments must be provided in the already-sorted order + if (comments.size() != getNSelections()) { + LOG(fatal) << "Number of comments and number of selections are inconsistent"; } + mComments = comments; } - /// \brief Sort selection functions based on evaluation at a given point. - /// \param value Point at which to evaluate the functions for ordering. - void sortFunctions(T value) + /// \brief Get comments attached to the selection thresholds. + /// \return Vector of comment strings. + std::string getComment(int selectionIndex) const { - switch (mLimitType) { - case (limits::kUpperFunctionLimit): - case (limits::kAbsUpperFunctionLimit): - std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) > b.Eval(value); }); - break; - case (limits::kLowerFunctionLimit): - case (limits::kAbsLowerFunctionLimit): - std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) < b.Eval(value); }); - break; - default: - break; + if (mComments.empty()) { + return std::string(""); } + return mComments.at(selectionIndex); } - /// \brief Add comments to the selection values - /// \param comments Vector of comments - void addComments(std::vector const& comments) - { - // make sure that the comments are in correct order - // the values passed to the selection container can be reordered based on the limit type - mComments = comments; - } - - std::vector const& getComments() const { return mComments; } + /// \brief Get the name of this selection. + /// \return Selection name string. std::string const& getSelectionName() const { return mSelectionName; } - /// \brief Update selection limits using internal functions evaluated at a given value. - /// \param value Input value to evaluate functions at. + /// \brief Update threshold values by re-evaluating the internal TF1 functions at a given point. + /// \param value Input value at which to evaluate the functions. void updateLimits(T value) { - // functions are ordered so just add the values in the same order + // functions are already sorted, so evaluate in the same order as mSelectionValues for (std::size_t i = 0; i < mSelectionValues.size(); i++) { mSelectionValues.at(i) = mSelectionFunctions.at(i).Eval(value); } } - /// \brief Evaluate which selection criteria are fulfilled for a given value. + /// \brief Evaluate which selection thresholds are passed for a given observable value. /// \param value Value of the observable to evaluate. void evaluate(T value) { - // better safe than sorry and reset the bitmask before you evaluate and set minimal selection to true + // reset the bitmask before evaluating mBitmask.reset(); - // the values are ordered, from most loose to most tight, as soon as one comparison is not true, we can break out of the loop - bool breakLoop = false; - // iterate over all limits and set the corresponding bit if we pass the selection, otherwise break out as soon as we can - // only break if the observable is used for the minimal selection - for (size_t i = 0; i < mSelectionValues.size(); i++) { - switch (mLimitType) { - case (limits::kUpperLimit): - case (limits::kUpperFunctionLimit): + + // switch on limit type once outside the loop; + // thresholds are sorted from most permissive to most restrictive, + // so we can break early as soon as one comparison fails + switch (mLimitType) { + case (limits::kUpperLimit): + case (limits::kUpperFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (value <= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kAbsUpperLimit): - case (limits::kAbsUpperFunctionLimit): + } + break; + case (limits::kAbsUpperLimit): + case (limits::kAbsUpperFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::abs(value) <= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kLowerLimit): - case (limits::kLowerFunctionLimit): + } + break; + case (limits::kLowerLimit): + case (limits::kLowerFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (value >= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kAbsLowerLimit): - case (limits::kAbsLowerFunctionLimit): + } + break; + case (limits::kAbsLowerLimit): + case (limits::kAbsLowerFunctionLimit): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::abs(value) >= mSelectionValues.at(i)) { mBitmask.set(i); } else { - breakLoop = true; + break; } - break; - case (limits::kEqual): - // special case for kEqual since here we cannot really establish an order so we need to check all cases explicitly and we cannot bail early + } + break; + case (limits::kRange): + // ranges are sorted widest-first but a narrower range passing does not imply a wider one fails (no check on boundries), + // so all ranges must be checked explicitly — no early exit + for (std::size_t i = 0; i < mSelectionRanges.size(); i++) { + if (value >= mSelectionRanges.at(i).first && value <= mSelectionRanges.at(i).second) { + mBitmask.set(i); + } + } + break; + case (limits::kEqual): + // kEqual has no natural ordering, so all thresholds must be checked and we cannot bail early + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::fabs(value - mSelectionValues.at(i)) < constants::math::Epsilon) { mBitmask.set(i); } - break; - default: - breakLoop = true; - } - // bail early if a comparison fails - // the values are ordered, so all following we also fail, there there is no point in contiuing - if (breakLoop) { + } break; - } + default: + LOG(warn) << "Limit type not known, no selection is applied"; } } - /// \brief Evaluate which selection criteria are fulfilled for a given value. - /// \param values Values of the observable to evaluate + /// \brief Evaluate which selection thresholds are passed for a vector of observable values. + /// Only kEqualArray is supported for now; each element is compared against the corresponding threshold. + /// \param values Values of the observable to evaluate. void evaluate(std::vector const& values) { if (values.size() != mSelectionValues.size()) { LOG(fatal) << "Wrong number of values have been passed"; } - for (size_t i = 0; i < mSelectionValues.size(); i++) { - switch (mLimitType) { - case (limits::kEqualArray): + // reset the bitmask before evaluating + mBitmask.reset(); + + switch (mLimitType) { + case (limits::kEqualArray): + for (std::size_t i = 0; i < mSelectionValues.size(); i++) { if (std::fabs(values.at(i) - mSelectionValues.at(i)) < constants::math::Epsilon) { mBitmask.set(i); } - break; - default: - continue; - } + } + break; + default: + LOG(warn) << "Limit type not known, no selection is applied"; } } - /// \brief Retrieve the bitmask indicating which selections were passed. + /// \brief Retrieve the bitmask indicating which thresholds were passed. + /// If mSkipMostPermissiveBit is set, the bit for the loosest threshold is removed by shifting. /// \return Bitset representing passed selections. std::bitset getBitmask() const { - // if we do not skip the last bit, return full bitmask - if (mSkipMostPermissiveBit == false) { + if (!mSkipMostPermissiveBit) { return mBitmask; } else { - // for the other selections we can remove the first bit since it is the minimal selection and therefore always true + // remove the first (most permissive) bit since it corresponds to the minimal selection and is always true return mBitmask >> 1; } } + + /// \brief Manually set the internal bitmask. + /// \tparam R Integer type of the bitmask value. + /// \param bitmask Bitmask value to set. template void setBitmask(R bitmask) { mBitmask = std::bitset(bitmask); } - /// \brief Check whether the minimal cut condition is fulfilled. - /// \return True if minimal selection is fulfilled, false otherwise. + /// \brief Reset the internal bitmask to zero. + void reset() { mBitmask.reset(); } + + /// \brief Check whether the mandatory (minimal) cut condition is fulfilled. + /// \return True if the minimal selection passes or if this container is not marked as a minimal cut. bool passesAsMinimalCut() const { if (mIsMinimalCut) { - // check if any bit is set - // in case were bits are evaluted in order, if the loosests fails, all fail, so testing any is safe here - return mBitmask.any(); + // if any bit is set the loosest threshold passed; since thresholds are ordered, + // the loosest passing implies all looser ones also pass + return mBitmask.test(0); } - // if a selection is not marked as minimal cut we return true by default + // not a minimal cut — return true by default so it does not block the candidate return true; } - /// \brief Check whether any optional cuts are fulfilled. - /// \return True if at least one optional cut is passed. + /// \brief Check whether any optional cut is fulfilled. + /// \return True if at least one optional threshold is passed, false if this container is not marked as optional. bool passesAsOptionalCut() const { if (mIsOptionalCut) { - // check if any bit is set - // in case were bits are evaluted in order, if the loosests fails, all fail, so testing any is safe here + // if any bit is set the loosest threshold passed return mBitmask.any(); } - // if a selection is not marked as optional cut we return false by default + // not an optional cut — return false by default so it does not accidentally accept the candidate return false; } - /// \brief Get the loosest (most permissive) selection value. - /// \return First (loosest) selection value. - T getLoosestSelection() const { return mSelectionValues.at(0); } + /// \brief Get the loosest (most permissive) selection threshold value. + /// \return The first element of the sorted threshold vector. + T getLoosestSelection() const + { + if (mSelectionValues.empty()) { + LOG(fatal) << "No selections configured"; + } + return mSelectionValues.at(0); + } - /// \brief Check if there are any selection values configured. We also init values in case of function so this is safe - /// \return True if no selections are configured. + /// \brief Check whether any selection thresholds are configured. + /// For function-based selections, mSelectionValues is always populated (initialised at the midpoint), + /// so this check is safe for both static and function-based containers. + /// \return True if no thresholds are configured. bool isEmpty() const { return mSelectionValues.empty(); } - /// \brief Check if there are any selection values configured. - /// \return True if no selections are configured. - bool isUsingFunctions() const { return !mSelectionFunctions.empty(); } - - /// \brief Get the number of bits to shift for the final bitmask. - /// \return Number of bits to shift. + /// \brief Get the number of bits this container contributes to the global bitmask. + /// If the most permissive bit is skipped, the contribution is reduced by one. + /// \return Number of bits to add to the global bitmask offset. int getShift() const { if (mSelectionValues.empty()) { @@ -345,22 +423,47 @@ class SelectionContainer } if (mSkipMostPermissiveBit) { return static_cast(mSelectionValues.size() - 1); - } else { - return static_cast(mSelectionValues.size()); } + return static_cast(mSelectionValues.size()); } + /// \brief Set the bit offset of this container within the global bitmask. + /// \param offset Bit position at which this container's bits start. void setOffset(int offset) { mOffset = offset; } + + /// \brief Get the bit offset of this container within the global bitmask. + /// \return Bit offset. int getOffset() const { return mOffset; } - int getNSelections() const { return mSelectionValues.size(); } + /// \brief Get the total number of configured selection thresholds. + /// \return Number of thresholds. + std::size_t getNSelections() const { return mSelectionValues.size(); } + /// \brief Build a histogram bin label string encoding the full configuration of a single threshold. + /// \param selectionIndex Index of the threshold within this container. + /// \return Encoded label string. std::string getBinLabel(int selectionIndex) const { std::ostringstream oss; std::string sectionDelimiter = ":::"; std::string valueDelimiter = "___"; std::string noValue = "X"; + + // Determine value string + std::string valueStr; + + if (mLimitType == limits::kRange) { + // Print actual lower;upper interval + const auto& range = mSelectionRanges.at(selectionIndex); + std::ostringstream rangeStream; + rangeStream << range.first << ";" << range.second; + valueStr = rangeStream.str(); + } else if (mSelectionFunctions.empty()) { + valueStr = std::to_string(mSelectionValues.at(selectionIndex)); + } else { + valueStr = mSelectionFunctions.at(selectionIndex).GetExpFormula().Data(); + } + oss << "SelectionName" << valueDelimiter << mSelectionName << sectionDelimiter << "LimitType" << valueDelimiter << getLimitTypeAsString() << sectionDelimiter << "MinimalCut" << valueDelimiter << (mIsMinimalCut ? "1" : "0") << sectionDelimiter @@ -368,12 +471,32 @@ class SelectionContainer << "OptionalCut" << valueDelimiter << (mIsOptionalCut ? "1" : "0") << sectionDelimiter << "Shift" << valueDelimiter << getShift() << sectionDelimiter << "Offset" << valueDelimiter << mOffset << sectionDelimiter - << "Value" << valueDelimiter << (mSelectionFunctions.empty() ? std::to_string(mSelectionValues.at(selectionIndex)) : mSelectionFunctions.at(selectionIndex).GetExpFormula().Data()) << sectionDelimiter + << "Value" << valueDelimiter << valueStr << sectionDelimiter << "BitPosition" << valueDelimiter << (mSkipMostPermissiveBit ? (selectionIndex == 0 ? noValue : std::to_string(mOffset + selectionIndex - 1)) : std::to_string(mOffset + selectionIndex)) << sectionDelimiter << "Comment" << valueDelimiter << (mComments.empty() ? noValue : mComments.at(selectionIndex)); return oss.str(); } + std::string getValueAsString(int selectionIndex) const + { + if (this->isEmpty()) { + return std::string("No value configured"); + } + if (!mSelectionFunctions.empty()) { + return std::string(mSelectionFunctions.at(selectionIndex).GetExpFormula().Data()); + } + if (!mSelectionRanges.empty()) { + std::ostringstream oss; + oss << mSelectionRanges.at(selectionIndex).first << ";" << mSelectionRanges.at(selectionIndex).second; + return oss.str(); + } + return std::to_string(mSelectionValues.at(selectionIndex)); + } + + /// \brief Get the global bit position of a threshold within the final bitmask. + /// Calling this for the skipped most-permissive threshold is a fatal error. + /// \param selectionIndex Index of the threshold within this container. + /// \return Global bit position. int getBitPosition(int selectionIndex) const { if (selectionIndex == 0 && mSkipMostPermissiveBit) { @@ -387,43 +510,107 @@ class SelectionContainer } } - /// \brief Get string representation of the limit type. - /// \return String name of the limit type. - std::string getLimitTypeAsString() const { return limits::limitTypeAsStrings[mLimitType]; } + /// \brief Get the string representation of the configured limit type. + /// \return Human-readable limit type name. + std::string getLimitTypeAsString() const { return limits::limitTypeAsStrings.at(mLimitType); } - /// \brief Get a copy of all selection values. - /// \return Vector of selection values. + /// \brief Get the configured static threshold values. + /// \return Const reference to the vector of threshold values. std::vector const& getSelectionValues() const { return mSelectionValues; } - /// \brief Get a copy of all selection values. - /// \return Vector of selection values. + /// \brief Get the configured TF1 threshold functions. + /// \return Const reference to the vector of TF1 functions. std::vector const& getSelectionFunction() const { return mSelectionFunctions; } - /// \brief Check if this container is marked as minimal cut - /// \return True if minimal cut, false otherwise. + /// \brief Check whether this container is marked as a mandatory (minimal) cut. + /// \return True if this is a minimal cut. bool isMinimalCut() const { return mIsMinimalCut; } - /// \brief Check if this container is marked as optional cut - /// \return True if minimal cut, false otherwise. + /// \brief Check whether this container is marked as an optional cut. + /// \return True if this is an optional cut. bool isOptionalCut() const { return mIsOptionalCut; } - /// \brief Check whether the most permissive bit is skipped. - /// \return True if skipped, false otherwise. + /// \brief Check whether the most permissive threshold bit is skipped when assembling the bitmask. + /// \return True if the most permissive bit is skipped. bool skipMostPermissiveBit() const { return mSkipMostPermissiveBit; } - void reset() { mBitmask.reset(); } - private: - std::string mSelectionName = std::string(""); - std::vector mSelectionValues = {}; ///< Values used for the selection - std::vector mSelectionFunctions = {}; ///< Function used for the selection - limits::LimitType mLimitType = limits::kLimitTypeLast; ///< Limit type of selection - bool mSkipMostPermissiveBit = false; ///< whether to skip the last bit or not - bool mIsMinimalCut = false; ///< whether to use this observable for minimal selection or not - bool mIsOptionalCut = false; ///< whether to use this observable for minimal selection or not - std::vector mComments = {}; ///< Comments for the values - std::bitset mBitmask = {}; ///< bitmask for the observable - int mOffset = 0; + /// \brief Sort static threshold values from most permissive to most restrictive based on the limit type. + void sortSelections() + { + switch (mLimitType) { + case (limits::kUpperLimit): + case (limits::kAbsUpperLimit): + std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a > b; }); + break; + case (limits::kLowerLimit): + case (limits::kAbsLowerLimit): + std::sort(mSelectionValues.begin(), mSelectionValues.end(), [](T a, T b) { return a < b; }); + break; + case (limits::kRange): + // sort by range width descending so the most permissive (widest) range comes first + std::sort(mSelectionRanges.begin(), mSelectionRanges.end(), + [](std::pair const& a, std::pair const& b) { + return (a.second - a.first) > (b.second - b.first); + }); + break; + default: + break; + } + } + + /// \brief Sort selection functions from most permissive to most restrictive, evaluated at a given point. + /// \param value Point at which to evaluate the functions for ordering. + void sortFunctions(T value) + { + switch (mLimitType) { + case (limits::kUpperFunctionLimit): + case (limits::kAbsUpperFunctionLimit): + std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) > b.Eval(value); }); + break; + case (limits::kLowerFunctionLimit): + case (limits::kAbsLowerFunctionLimit): + std::sort(mSelectionFunctions.begin(), mSelectionFunctions.end(), [value](TF1 const& a, TF1 const& b) { return a.Eval(value) < b.Eval(value); }); + break; + default: + break; + } + } + + /// \brief Parse a range string of the form "lower;upper" into a lower and upper bound. + /// Either bound may be omitted (e.g. ";1.0" or "0.5;"), in which case + /// -/+ numeric_limits::max() is used respectively. + /// \param rangeStr Input string to parse. + /// \param lower Output lower bound. + /// \param upper Output upper bound. + void parseRangeString(std::string const& rangeStr, T& lower, T& upper) const + { + auto pos = rangeStr.find(';'); + if (pos == std::string::npos) { + LOG(fatal) << "Range string '" << rangeStr << "' is missing ';' separator. Expected format: 'lower;upper'"; + } + std::string lowerStr = rangeStr.substr(0, pos); + std::string upperStr = rangeStr.substr(pos + 1); + + lower = lowerStr.empty() ? -std::numeric_limits::max() : static_cast(std::stod(lowerStr)); + upper = upperStr.empty() ? std::numeric_limits::max() : static_cast(std::stod(upperStr)); + + if (lower >= upper) { + LOG(fatal) << "Range string '" << rangeStr << "' has lower bound >= upper bound"; + } + } + + std::string mSelectionName = ""; + std::vector mSelectionValues = {}; ///< Threshold values, sorted from most permissive to most restrictive + std::vector mSelectionFunctions = {}; ///< TF1 threshold functions (empty for static selections) + std::vector> mSelectionRanges = {}; ///< Lower and upper bounds for kRange selections, one pair per threshold + limits::LimitType mLimitType = limits::kLimitTypeLast; ///< Comparison type applied during evaluation + bool mSkipMostPermissiveBit = false; ///< If true, the most permissive threshold does not occupy a bit in the global bitmask + bool mIsMinimalCut = false; ///< If true, this selection is mandatory; failing it rejects the candidate + bool mIsOptionalCut = false; ///< If true, this selection is optional; passing it accepts the candidate + std::vector mComments = {}; ///< Optional comments per threshold, in the same order as mSelectionValues + std::bitset mBitmask = {}; ///< Bitmask indicating which thresholds were passed during the last evaluation + int mOffset = 0; ///< Bit offset of this container within the global bitmask }; } // namespace o2::analysis::femto diff --git a/PWGCF/Femto/Core/trackBuilder.h b/PWGCF/Femto/Core/trackBuilder.h index 7e1c90317bc..7971c7fe34e 100644 --- a/PWGCF/Femto/Core/trackBuilder.h +++ b/PWGCF/Femto/Core/trackBuilder.h @@ -23,11 +23,11 @@ #include "PWGCF/Femto/Core/selectionContainer.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" - -#include "fairlogger/Logger.h" +#include +#include +#include +#include +#include #include #include @@ -67,65 +67,65 @@ struct ConfTrackBits : o2::framework::ConfigurableGroup { // Electron PID cuts o2::framework::Configurable requirePidElectron{"requirePidElectron", false, "Make election PID optional"}; o2::framework::Configurable minMomTofElectron{"minMomTofElectron", 0.3, "Minimum momentum to required TOF PID for Electron"}; - o2::framework::Configurable> itsElectron{"itsElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tpcElectron{"tpcElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tofElectron{"tofElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tpcitsElectron{"tpcitsElectron", {}, "Maximum |nsigma| for Electron PID"}; - o2::framework::Configurable> tpctofElectron{"tpctofElectron", {}, "Maximum |nsigma| for Electron PID"}; + o2::framework::Configurable> itsElectron{"itsElectron", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Electron PID"}; + o2::framework::Configurable> tpcElectron{"tpcElectron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Electron PID"}; + o2::framework::Configurable> tofElectron{"tofElectron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Electron PID"}; + o2::framework::Configurable> tpcitsElectron{"tpcitsElectron", {}, "Maximum nsigma_TPCITS for Electron PID"}; + o2::framework::Configurable> tpctofElectron{"tpctofElectron", {}, "Maximum nsigma_TPCTOF for Electron PID"}; // Pion PID cuts o2::framework::Configurable requirePidPion{"requirePidPion", false, "Make election PID optional"}; o2::framework::Configurable minMomTofPion{"minMomTofPion", 0.5, "Minimum momentum to required TOF PID for Pion"}; - o2::framework::Configurable> itsPion{"itsPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tpcPion{"tpcPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tofPion{"tofPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tpcitsPion{"tpcitsPion", {}, "Maximum |nsigma| for Pion PID"}; - o2::framework::Configurable> tpctofPion{"tpctofPion", {}, "Maximum |nsigma| for Pion PID"}; + o2::framework::Configurable> itsPion{"itsPion", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Pion PID"}; + o2::framework::Configurable> tpcPion{"tpcPion", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Pion PID"}; + o2::framework::Configurable> tofPion{"tofPion", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Pion PID"}; + o2::framework::Configurable> tpcitsPion{"tpcitsPion", {}, "Maximum nsigma_TPCITS for Pion PID"}; + o2::framework::Configurable> tpctofPion{"tpctofPion", {}, "Maximum nsigma_TPCTOF for Pion PID"}; // Kaon PID cuts o2::framework::Configurable requirePidKaon{"requirePidKaon", false, "Make election PID optional"}; o2::framework::Configurable minMomTofKaon{"minMomTofKaon", 0.4, "Minimum momentum to required TOF PID for Kaon"}; - o2::framework::Configurable> itsKaon{"itsKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tpcKaon{"tpcKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tofKaon{"tofKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tpcitsKaon{"tpcitsKaon", {}, "Maximum |nsigma| for Kaon PID"}; - o2::framework::Configurable> tpctofKaon{"tpctofKaon", {}, "Maximum |nsigma| for Kaon PID"}; + o2::framework::Configurable> itsKaon{"itsKaon", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Kaon PID"}; + o2::framework::Configurable> tpcKaon{"tpcKaon", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Kaon PID"}; + o2::framework::Configurable> tofKaon{"tofKaon", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Kaon PID"}; + o2::framework::Configurable> tpcitsKaon{"tpcitsKaon", {}, "Maximum nsigma_TPCITS for Kaon PID"}; + o2::framework::Configurable> tpctofKaon{"tpctofKaon", {}, "Maximum nsigma_TPCTOF for Kaon PID"}; // Proton PID cuts o2::framework::Configurable requirePidProton{"requirePidProton", true, "Make election PID optional"}; o2::framework::Configurable minMomTofProton{"minMomTofProton", 0.75, "Minimum momentum to required TOF PID for Proton"}; - o2::framework::Configurable> itsProton{"itsProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tpcProton{"tpcProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tofProton{"tofProton", {}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tpcitsProton{"tpcitsProton", {3.f}, "Maximum |nsigma| for Proton PID"}; - o2::framework::Configurable> tpctofProton{"tpctofProton", {3.f}, "Maximum |nsigma| for Proton PID"}; + o2::framework::Configurable> itsProton{"itsProton", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Proton PID"}; + o2::framework::Configurable> tpcProton{"tpcProton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Proton PID"}; + o2::framework::Configurable> tofProton{"tofProton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Proton PID"}; + o2::framework::Configurable> tpcitsProton{"tpcitsProton", {}, "Maximum nsigma_TPCITS for Proton PID"}; + o2::framework::Configurable> tpctofProton{"tpctofProton", {}, "Maximum nsigma_TPCTOF for Proton PID"}; // Deuteron PID cuts o2::framework::Configurable requirePidDeuteron{"requirePidDeuteron", false, "Make election PID optional"}; o2::framework::Configurable minMomTofDeuteron{"minMomTofDeuteron", 1.2, "Minimum momentum to required TOF PID for Deuteron"}; - o2::framework::Configurable> itsDeuteron{"itsDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tpcDeuteron{"tpcDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tofDeuteron{"tofDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tpcitsDeuteron{"tpcitsDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; - o2::framework::Configurable> tpctofDeuteron{"tpctofDeuteron", {}, "Maximum |nsigma| for Deuteron PID"}; + o2::framework::Configurable> itsDeuteron{"itsDeuteron", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Deuteron PID"}; + o2::framework::Configurable> tpcDeuteron{"tpcDeuteron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Deuteron PID"}; + o2::framework::Configurable> tofDeuteron{"tofDeuteron", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Deuteron PID"}; + o2::framework::Configurable> tpcitsDeuteron{"tpcitsDeuteron", {}, "Maximum nsigma_TPCITS for Deuteron PID"}; + o2::framework::Configurable> tpctofDeuteron{"tpctofDeuteron", {}, "Maximum nsigma_TPCTOF for Deuteron PID"}; // Triton PID cuts o2::framework::Configurable requirePidTriton{"requirePidTriton", false, "Make election PID optional"}; o2::framework::Configurable minMomTofTriton{"minMomTofTriton", 1.4, "Minimum momentum to required TOF PID for Triton"}; - o2::framework::Configurable> itsTriton{"itsTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tpcTriton{"tpcTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tofTriton{"tofTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tpcitsTriton{"tpcitsTriton", {}, "Maximum |nsigma| for Triton PID"}; - o2::framework::Configurable> tpctofTriton{"tpctofTriton", {}, "Maximum |nsigma| for Triton PID"}; + o2::framework::Configurable> itsTriton{"itsTriton", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Triton PID"}; + o2::framework::Configurable> tpcTriton{"tpcTriton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Triton PID"}; + o2::framework::Configurable> tofTriton{"tofTriton", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Triton PID"}; + o2::framework::Configurable> tpcitsTriton{"tpcitsTriton", {}, "Maximum nsigma_TPCITS for Triton PID"}; + o2::framework::Configurable> tpctofTriton{"tpctofTriton", {}, "Maximum nsigma_TPCTOF for Triton PID"}; // Helium PID cuts o2::framework::Configurable requirePidHelium{"requirePidHelium", false, "Make election PID optional"}; o2::framework::Configurable minMomTofHelium{"minMomTofHelium", 1.6, "Minimum momentum to required TOF PID for Helium"}; - o2::framework::Configurable> itsHelium{"itsHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tpcHelium{"tpcHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tofHelium{"tofHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tpcitsHelium{"tpcitsHelium", {}, "Maximum |nsigma| for Helium PID"}; - o2::framework::Configurable> tpctofHelium{"tpctofHelium", {}, "Maximum |nsigma| for Helium PID"}; + o2::framework::Configurable> itsHelium{"itsHelium", {}, "Ranges LowerLimit;UpperLimit for nsigma_ITS for Helium PID"}; + o2::framework::Configurable> tpcHelium{"tpcHelium", {}, "Ranges LowerLimit;UpperLimit for nsigma_TPC for Helium PID"}; + o2::framework::Configurable> tofHelium{"tofHelium", {}, "Ranges LowerLimit;UpperLimit for nsigma_TOF for Helium PID"}; + o2::framework::Configurable> tpcitsHelium{"tpcitsHelium", {}, "Maximum nsigma_TPCITS for Helium PID"}; + o2::framework::Configurable> tpctofHelium{"tpctofHelium", {}, "Maximum nsigma_TPCTOF for Helium PID"}; }; // define the template structure for TrackSelection @@ -143,9 +143,14 @@ struct ConfTrackSelection : public o2::framework::ConfigurableGroup { o2::framework::Configurable etaMax{"etaMax", 0.9f, "Maximum eta"}; o2::framework::Configurable phiMin{"phiMin", 0.f, "Minimum phi"}; o2::framework::Configurable phiMax{"phiMax", 1.f * o2::constants::math::TwoPI, "Maximum phi"}; + o2::framework::Configurable massMin{"massMin", 0.f, "Minimum TOF mass (only used if enabled)"}; + o2::framework::Configurable massMax{"massMax", 2.f, "Maximum TOF mass (only used if enabled)"}; // track selection masks - o2::framework::Configurable maskLowMomentum{"maskLowMomentum", 0x2u, "Bitmask for selections below momentum threshold"}; - o2::framework::Configurable maskHighMomentum{"maskHighMomentum", 0x1u, "Bitmask for selections above momentum threshold"}; + o2::framework::Configurable maskLowMomentum{"maskLowMomentum", 1ul, "Bitmask for selections below momentum threshold"}; + o2::framework::Configurable maskHighMomentum{"maskHighMomentum", 2ul, "Bitmask for selections above momentum threshold"}; + // track rejection masks + o2::framework::Configurable rejectionMaskLowMomentum{"rejectionMaskLowMomentum", 0ul, "Bitmask for rejections below momentum threshold"}; + o2::framework::Configurable rejectionMaskHighMomentum{"rejectionMaskHighMomentum", 0ul, "Bitmask for rejections above momentum threshold"}; // momentum threshold for PID usage o2::framework::Configurable pidThres{"pidThres", 1.2f, "Momentum threshold for using TPCTOF/TOF pid for tracks with large momentum (GeV/c)"}; }; @@ -283,12 +288,12 @@ class TrackSelection : public BaseSelection void configure(o2::framework::HistogramRegistry* registry, T1& config, T2& filter) { - mPtMin = filter.ptMin; - mPtMax = filter.ptMax; - mEtaMin = filter.etaMin; - mEtaMax = filter.etaMax; - mPhiMin = filter.phiMin; - mPhiMax = filter.phiMax; + mPtMin = filter.ptMin.value; + mPtMax = filter.ptMax.value; + mEtaMin = filter.etaMin.value; + mEtaMax = filter.etaMax.value; + mPhiMin = filter.phiMin.value; + mPhiMax = filter.phiMax.value; // add selections for track quality this->addSelection(kTPCnClsMin, trackSelectionNames.at(kTPCnClsMin), config.tpcClustersMin.value, limits::kLowerLimit, true, true, false); @@ -298,61 +303,61 @@ class TrackSelection : public BaseSelectionaddSelection(kTPCsClsFracMax, trackSelectionNames.at(kTPCsClsFracMax), config.tpcSharedClusterFractionMax.value, limits::kUpperLimit, true, true, false); this->addSelection(kITSnClsMin, trackSelectionNames.at(kITSnClsMin), config.itsClustersMin.value, limits::kLowerLimit, true, true, false); this->addSelection(kITSnClsIbMin, trackSelectionNames.at(kITSnClsIbMin), config.itsIbClustersMin.value, limits::kLowerLimit, true, true, false); - this->addSelection(kDCAxyMax, trackSelectionNames.at(kDCAxyMax), filter.ptMin, filter.ptMax.value, config.dcaxyMax.value, limits::kAbsUpperFunctionLimit, true, true, false); + this->addSelection(kDCAxyMax, trackSelectionNames.at(kDCAxyMax), filter.ptMin.value, filter.ptMax.value, config.dcaxyMax.value, limits::kAbsUpperFunctionLimit, true, true, false); this->addSelection(kDCAzMax, trackSelectionNames.at(kDCAzMax), filter.ptMin.value, filter.ptMax.value, config.dcazMax.value, limits::kAbsUpperFunctionLimit, true, true, false); // add selections for Electron pid - this->addSelection(kItsElectron, trackSelectionNames.at(kItsElectron), config.itsElectron.value, limits::kAbsUpperLimit, false, false, config.requirePidElectron); - this->addSelection(kTpcElectron, trackSelectionNames.at(kTpcElectron), config.tpcElectron.value, limits::kAbsUpperLimit, false, false, config.requirePidElectron); - this->addSelection(kTofElectron, trackSelectionNames.at(kTofElectron), config.tofElectron.value, limits::kAbsUpperLimit, false, false, config.requirePidElectron); + this->addSelection(kItsElectron, trackSelectionNames.at(kItsElectron), config.itsElectron.value, false, false, config.requirePidElectron); + this->addSelection(kTpcElectron, trackSelectionNames.at(kTpcElectron), config.tpcElectron.value, false, false, config.requirePidElectron); + this->addSelection(kTofElectron, trackSelectionNames.at(kTofElectron), config.tofElectron.value, false, false, config.requirePidElectron); this->addSelection(kTpcitsElectron, trackSelectionNames.at(kTpcitsElectron), config.tpcitsElectron.value, limits::kUpperLimit, false, false, config.requirePidElectron); this->addSelection(kTpctofElectron, trackSelectionNames.at(kTpctofElectron), config.tpctofElectron.value, limits::kUpperLimit, false, false, config.requirePidElectron); mElectronTofThres = config.minMomTofElectron.value; // add selections for Pion pid - this->addSelection(kItsPion, trackSelectionNames.at(kItsPion), config.itsPion.value, limits::kAbsUpperLimit, false, false, config.requirePidPion); - this->addSelection(kTpcPion, trackSelectionNames.at(kTpcPion), config.tpcPion.value, limits::kAbsUpperLimit, false, false, config.requirePidPion); - this->addSelection(kTofPion, trackSelectionNames.at(kTofPion), config.tofPion.value, limits::kAbsUpperLimit, false, false, config.requirePidPion); + this->addSelection(kItsPion, trackSelectionNames.at(kItsPion), config.itsPion.value, false, false, config.requirePidPion); + this->addSelection(kTpcPion, trackSelectionNames.at(kTpcPion), config.tpcPion.value, false, false, config.requirePidPion); + this->addSelection(kTofPion, trackSelectionNames.at(kTofPion), config.tofPion.value, false, false, config.requirePidPion); this->addSelection(kTpcitsPion, trackSelectionNames.at(kTpcitsPion), config.tpcitsPion.value, limits::kUpperLimit, false, false, config.requirePidPion); this->addSelection(kTpctofPion, trackSelectionNames.at(kTpctofPion), config.tpctofPion.value, limits::kUpperLimit, false, false, config.requirePidPion); mPionTofThres = config.minMomTofPion.value; // add selections for Kaon pid - this->addSelection(kItsKaon, trackSelectionNames.at(kItsKaon), config.itsKaon.value, limits::kAbsUpperLimit, false, false, config.requirePidKaon); - this->addSelection(kTpcKaon, trackSelectionNames.at(kTpcKaon), config.tpcKaon.value, limits::kAbsUpperLimit, false, false, config.requirePidKaon); - this->addSelection(kTofKaon, trackSelectionNames.at(kTofKaon), config.tofKaon.value, limits::kAbsUpperLimit, false, false, config.requirePidKaon); + this->addSelection(kItsKaon, trackSelectionNames.at(kItsKaon), config.itsKaon.value, false, false, config.requirePidKaon); + this->addSelection(kTpcKaon, trackSelectionNames.at(kTpcKaon), config.tpcKaon.value, false, false, config.requirePidKaon); + this->addSelection(kTofKaon, trackSelectionNames.at(kTofKaon), config.tofKaon.value, false, false, config.requirePidKaon); this->addSelection(kTpcitsKaon, trackSelectionNames.at(kTpcitsKaon), config.tpcitsKaon.value, limits::kUpperLimit, false, false, config.requirePidKaon); this->addSelection(kTpctofKaon, trackSelectionNames.at(kTpctofKaon), config.tpctofKaon.value, limits::kUpperLimit, false, false, config.requirePidKaon); mKaonTofThres = config.minMomTofKaon.value; // add selections for Proton pid - this->addSelection(kItsProton, trackSelectionNames.at(kItsProton), config.itsProton.value, limits::kAbsUpperLimit, false, false, config.requirePidProton); - this->addSelection(kTpcProton, trackSelectionNames.at(kTpcProton), config.tpcProton.value, limits::kAbsUpperLimit, false, false, config.requirePidProton); - this->addSelection(kTofProton, trackSelectionNames.at(kTofProton), config.tofProton.value, limits::kAbsUpperLimit, false, false, config.requirePidProton); + this->addSelection(kItsProton, trackSelectionNames.at(kItsProton), config.itsProton.value, false, false, config.requirePidProton); + this->addSelection(kTpcProton, trackSelectionNames.at(kTpcProton), config.tpcProton.value, false, false, config.requirePidProton); + this->addSelection(kTofProton, trackSelectionNames.at(kTofProton), config.tofProton.value, false, false, config.requirePidProton); this->addSelection(kTpcitsProton, trackSelectionNames.at(kTpcitsProton), config.tpcitsProton.value, limits::kUpperLimit, false, false, config.requirePidProton); this->addSelection(kTpctofProton, trackSelectionNames.at(kTpctofProton), config.tpctofProton.value, limits::kUpperLimit, false, false, config.requirePidProton); mProtonTofThres = config.minMomTofProton.value; // add selections for Deuteron pid - this->addSelection(kItsDeuteron, trackSelectionNames.at(kItsDeuteron), config.itsDeuteron.value, limits::kAbsUpperLimit, false, false, config.requirePidDeuteron); - this->addSelection(kTpcDeuteron, trackSelectionNames.at(kTpcDeuteron), config.tpcDeuteron.value, limits::kAbsUpperLimit, false, false, config.requirePidDeuteron); - this->addSelection(kTofDeuteron, trackSelectionNames.at(kTofDeuteron), config.tofDeuteron.value, limits::kAbsUpperLimit, false, false, config.requirePidDeuteron); + this->addSelection(kItsDeuteron, trackSelectionNames.at(kItsDeuteron), config.itsDeuteron.value, false, false, config.requirePidDeuteron); + this->addSelection(kTpcDeuteron, trackSelectionNames.at(kTpcDeuteron), config.tpcDeuteron.value, false, false, config.requirePidDeuteron); + this->addSelection(kTofDeuteron, trackSelectionNames.at(kTofDeuteron), config.tofDeuteron.value, false, false, config.requirePidDeuteron); this->addSelection(kTpcitsDeuteron, trackSelectionNames.at(kTpcitsDeuteron), config.tpcitsDeuteron.value, limits::kUpperLimit, false, false, config.requirePidDeuteron); this->addSelection(kTpctofDeuteron, trackSelectionNames.at(kTpctofDeuteron), config.tpctofDeuteron.value, limits::kUpperLimit, false, false, config.requirePidDeuteron); mDeuteronTofThres = config.minMomTofDeuteron.value; // add selections for Triton pid - this->addSelection(kItsTriton, trackSelectionNames.at(kItsTriton), config.itsTriton.value, limits::kAbsUpperLimit, false, false, config.requirePidTriton); - this->addSelection(kTpcTriton, trackSelectionNames.at(kTpcTriton), config.tpcTriton.value, limits::kAbsUpperLimit, false, false, config.requirePidTriton); - this->addSelection(kTofTriton, trackSelectionNames.at(kTofTriton), config.tofTriton.value, limits::kAbsUpperLimit, false, false, config.requirePidTriton); + this->addSelection(kItsTriton, trackSelectionNames.at(kItsTriton), config.itsTriton.value, false, false, config.requirePidTriton); + this->addSelection(kTpcTriton, trackSelectionNames.at(kTpcTriton), config.tpcTriton.value, false, false, config.requirePidTriton); + this->addSelection(kTofTriton, trackSelectionNames.at(kTofTriton), config.tofTriton.value, false, false, config.requirePidTriton); this->addSelection(kTpcitsTriton, trackSelectionNames.at(kTpcitsTriton), config.tpcitsTriton.value, limits::kUpperLimit, false, false, config.requirePidTriton); this->addSelection(kTpctofTriton, trackSelectionNames.at(kTpctofTriton), config.tpctofTriton.value, limits::kUpperLimit, false, false, config.requirePidTriton); mTritonTofThres = config.minMomTofTriton.value; // add selections for Helium pid - this->addSelection(kItsHelium, trackSelectionNames.at(kItsHelium), config.itsHelium.value, limits::kAbsUpperLimit, false, false, config.requirePidHelium); - this->addSelection(kTpcHelium, trackSelectionNames.at(kTpcHelium), config.tpcHelium.value, limits::kAbsUpperLimit, false, false, config.requirePidHelium); - this->addSelection(kTofHelium, trackSelectionNames.at(kTofHelium), config.tofHelium.value, limits::kAbsUpperLimit, false, false, config.requirePidHelium); + this->addSelection(kItsHelium, trackSelectionNames.at(kItsHelium), config.itsHelium.value, false, false, config.requirePidHelium); + this->addSelection(kTpcHelium, trackSelectionNames.at(kTpcHelium), config.tpcHelium.value, false, false, config.requirePidHelium); + this->addSelection(kTofHelium, trackSelectionNames.at(kTofHelium), config.tofHelium.value, false, false, config.requirePidHelium); this->addSelection(kTpcitsHelium, trackSelectionNames.at(kTpcitsHelium), config.tpcitsHelium.value, limits::kUpperLimit, false, false, config.requirePidHelium); this->addSelection(kTpctofHelium, trackSelectionNames.at(kTpctofHelium), config.tpctofHelium.value, limits::kUpperLimit, false, false, config.requirePidHelium); mHeliumTofThres = config.minMomTofHelium.value; @@ -378,30 +383,20 @@ class TrackSelection : public BaseSelectionevaluateObservable(its, nsigmaIts); - this->evaluateObservable(tpc, nsigmaTpc); - this->evaluateObservable(tpcits, std::hypot(nsigmaTpc, nsigmaIts)); - this->evaluateObservable(tof, nsigmaTof); - this->evaluateObservable(tpctof, std::hypot(nsigmaTpc, nsigmaTof)); + // above threshold without TOF: skip entirely unless forced + // forced evaluation is used in the second pass to populate rejection bits + if (!ignoreThreshold && Track.p() >= tofThreshold && !Track.hasTOF()) { return; } - // if track is above threshold, check if TOF PID is available - // if not, we dont check any selection and they stay at reseted values, i.e. the cut fails + this->evaluateObservable(its, nsigmaIts); + this->evaluateObservable(tpc, nsigmaTpc); + this->evaluateObservable(tpcits, std::hypot(nsigmaTpc, nsigmaIts)); if (Track.hasTOF()) { - // if tof inforamtion is available, check them first this->evaluateObservable(tof, nsigmaTof); this->evaluateObservable(tpctof, std::hypot(nsigmaTpc, nsigmaTof)); - // if both failed, the bitmask will be 0 and there is no need to check tpc and its information since we do not want to have this track - // so if we just bail out here, the PID for this particle type will failed for its, tpc and tof - if (this->passesOptionalSelection(tof) || this->passesOptionalSelection(tpctof)) { - this->evaluateObservable(its, nsigmaIts); - this->evaluateObservable(tpc, nsigmaTpc); - this->evaluateObservable(tpcits, std::hypot(nsigmaTpc, nsigmaIts)); - } } } @@ -416,90 +411,34 @@ class TrackSelection : public BaseSelectionevaluateObservable(kTPCsClsFracMax, static_cast(Track.tpcNClsShared()) / static_cast(Track.tpcNClsFound())); this->evaluateObservable(kITSnClsMin, Track.itsNCls()); this->evaluateObservable(kITSnClsIbMin, Track.itsNClsInnerBarrel()); - - // evalue bitmask for pt dependent dca cuts this->updateLimits(kDCAxyMax, Track.pt()); this->evaluateObservable(kDCAxyMax, Track.dcaXY()); - this->updateLimits(kDCAzMax, Track.pt()); this->evaluateObservable(kDCAzMax, Track.dcaZ()); - this->evaluatePid(Track, - mElectronTofThres, - Track.itsNSigmaEl(), - Track.tpcNSigmaEl(), - Track.tofNSigmaEl(), - kItsElectron, - kTpcElectron, - kTofElectron, - kTpcitsElectron, - kTpctofElectron); - - this->evaluatePid(Track, - mPionTofThres, - Track.itsNSigmaPi(), - Track.tpcNSigmaPi(), - Track.tofNSigmaPi(), - kItsPion, - kTpcPion, - kTofPion, - kTpcitsPion, - kTpctofPion); - - this->evaluatePid(Track, - mKaonTofThres, - Track.itsNSigmaKa(), - Track.tpcNSigmaKa(), - Track.tofNSigmaKa(), - kItsKaon, - kTpcKaon, - kTofKaon, - kTpcitsKaon, - kTpctofKaon); - - this->evaluatePid(Track, - mProtonTofThres, - Track.itsNSigmaPr(), - Track.tpcNSigmaPr(), - Track.tofNSigmaPr(), - kItsProton, - kTpcProton, - kTofProton, - kTpcitsProton, - kTpctofProton); - - this->evaluatePid(Track, - mDeuteronTofThres, - Track.itsNSigmaDe(), - Track.tpcNSigmaDe(), - Track.tofNSigmaDe(), - kItsDeuteron, - kTpcDeuteron, - kTofDeuteron, - kTpcitsDeuteron, - kTpctofDeuteron); - - this->evaluatePid(Track, - mTritonTofThres, - Track.itsNSigmaTr(), - Track.tpcNSigmaTr(), - Track.tofNSigmaTr(), - kItsTriton, - kTpcTriton, - kTofTriton, - kTpcitsTriton, - kTpctofTriton); - - this->evaluatePid(Track, - mHeliumTofThres, - Track.itsNSigmaHe(), - Track.tpcNSigmaHe(), - Track.tofNSigmaHe(), - kItsHelium, - kTpcHelium, - kTofHelium, - kTpcitsHelium, - kTpctofHelium); + // first pass: threshold-aware PID evaluation + // determines if the track passes any optional selection and should be stored + this->evaluatePid(Track, mElectronTofThres, Track.itsNSigmaEl(), Track.tpcNSigmaEl(), Track.tofNSigmaEl(), kItsElectron, kTpcElectron, kTofElectron, kTpcitsElectron, kTpctofElectron); + this->evaluatePid(Track, mPionTofThres, Track.itsNSigmaPi(), Track.tpcNSigmaPi(), Track.tofNSigmaPi(), kItsPion, kTpcPion, kTofPion, kTpcitsPion, kTpctofPion); + this->evaluatePid(Track, mKaonTofThres, Track.itsNSigmaKa(), Track.tpcNSigmaKa(), Track.tofNSigmaKa(), kItsKaon, kTpcKaon, kTofKaon, kTpcitsKaon, kTpctofKaon); + this->evaluatePid(Track, mProtonTofThres, Track.itsNSigmaPr(), Track.tpcNSigmaPr(), Track.tofNSigmaPr(), kItsProton, kTpcProton, kTofProton, kTpcitsProton, kTpctofProton); + this->evaluatePid(Track, mDeuteronTofThres, Track.itsNSigmaDe(), Track.tpcNSigmaDe(), Track.tofNSigmaDe(), kItsDeuteron, kTpcDeuteron, kTofDeuteron, kTpcitsDeuteron, kTpctofDeuteron); + this->evaluatePid(Track, mTritonTofThres, Track.itsNSigmaTr(), Track.tpcNSigmaTr(), Track.tofNSigmaTr(), kItsTriton, kTpcTriton, kTofTriton, kTpcitsTriton, kTpctofTriton); + this->evaluatePid(Track, mHeliumTofThres, Track.itsNSigmaHe(), Track.tpcNSigmaHe(), Track.tofNSigmaHe(), kItsHelium, kTpcHelium, kTofHelium, kTpcitsHelium, kTpctofHelium); + + // second pass: if the track passes minimal and any optional selection, + // re-evaluate all species ignoring thresholds so rejection bits are fully + // populated for all competing hypotheses. evaluate() resets each container + // before writing, so no explicit reset is needed before this pass. + if (this->passesAllRequiredSelections()) { + this->evaluatePid(Track, mElectronTofThres, Track.itsNSigmaEl(), Track.tpcNSigmaEl(), Track.tofNSigmaEl(), kItsElectron, kTpcElectron, kTofElectron, kTpcitsElectron, kTpctofElectron, true); + this->evaluatePid(Track, mPionTofThres, Track.itsNSigmaPi(), Track.tpcNSigmaPi(), Track.tofNSigmaPi(), kItsPion, kTpcPion, kTofPion, kTpcitsPion, kTpctofPion, true); + this->evaluatePid(Track, mKaonTofThres, Track.itsNSigmaKa(), Track.tpcNSigmaKa(), Track.tofNSigmaKa(), kItsKaon, kTpcKaon, kTofKaon, kTpcitsKaon, kTpctofKaon, true); + this->evaluatePid(Track, mProtonTofThres, Track.itsNSigmaPr(), Track.tpcNSigmaPr(), Track.tofNSigmaPr(), kItsProton, kTpcProton, kTofProton, kTpcitsProton, kTpctofProton, true); + this->evaluatePid(Track, mDeuteronTofThres, Track.itsNSigmaDe(), Track.tpcNSigmaDe(), Track.tofNSigmaDe(), kItsDeuteron, kTpcDeuteron, kTofDeuteron, kTpcitsDeuteron, kTpctofDeuteron, true); + this->evaluatePid(Track, mTritonTofThres, Track.itsNSigmaTr(), Track.tpcNSigmaTr(), Track.tofNSigmaTr(), kItsTriton, kTpcTriton, kTofTriton, kTpcitsTriton, kTpctofTriton, true); + this->evaluatePid(Track, mHeliumTofThres, Track.itsNSigmaHe(), Track.tpcNSigmaHe(), Track.tofNSigmaHe(), kItsHelium, kTpcHelium, kTofHelium, kTpcitsHelium, kTpctofHelium, true); + } this->assembleBitmask(); } @@ -523,6 +462,7 @@ class TrackSelection : public BaseSelection producedTracks; + o2::framework::Produces producedTrackMass; o2::framework::Produces producedTrackMasks; o2::framework::Produces producedTrackDcas; o2::framework::Produces producedTrackExtras; @@ -539,6 +479,7 @@ struct ConfTrackTables : o2::framework::ConfigurableGroup { std::string prefix = std::string("TrackTables"); o2::framework::Configurable produceTracks{"produceTracks", -1, "Produce Tracks (-1: auto; 0 off; 1 on)"}; o2::framework::Configurable produceTrackMasks{"produceTrackMasks", -1, "Produce TrackMasks (-1: auto; 0 off; 1 on)"}; + o2::framework::Configurable produceTrackMass{"produceTrackMass", -1, "Produce TrackMass (-1: auto; 0 off; 1 on)"}; o2::framework::Configurable produceTrackDcas{"produceTrackDcas", -1, "Produce TrackDcas (-1: auto; 0 off; 1 on)"}; o2::framework::Configurable produceTrackExtras{"produceTrackExtras", -1, "Produce TrackExtras (-1: auto; 0 off; 1 on)"}; o2::framework::Configurable produceElectronPids{"produceElectronPids", -1, "Produce ElectronPids (-1: auto; 0 off; 1 on)"}; @@ -564,6 +505,7 @@ class TrackBuilder mProduceTracks = utils::enableTable("FTracks_001", table.produceTracks.value, initContext); mProduceTrackMasks = utils::enableTable("FTrackMasks_001", table.produceTrackMasks.value, initContext); + mProduceTrackMass = utils::enableTable("FTrackMass_001", table.produceTrackMass.value, initContext); mProduceTrackDcas = utils::enableTable("FTrackDcas_001", table.produceTrackDcas.value, initContext); mProduceTrackExtras = utils::enableTable("FTrackExtras_001", table.produceTrackExtras.value, initContext); mProduceElectronPids = utils::enableTable("FElectronPids_001", table.produceElectronPids.value, initContext); @@ -574,7 +516,7 @@ class TrackBuilder mProduceTritonPids = utils::enableTable("FTritonPids_001", table.produceTritonPids.value, initContext); mProduceHeliumPids = utils::enableTable("FHeliumPids_001", table.produceHeliumPids.value, initContext); - if (mProduceTracks || mProduceTrackMasks || mProduceTrackDcas || mProduceTrackExtras || mProduceElectronPids || mProducePionPids || mProduceKaonPids || mProduceProtonPids || mProduceDeuteronPids || mProduceTritonPids || mProduceHeliumPids) { + if (mProduceTracks || mProduceTrackMasks || mProduceTrackMass || mProduceTrackDcas || mProduceTrackExtras || mProduceElectronPids || mProducePionPids || mProduceKaonPids || mProduceProtonPids || mProduceDeuteronPids || mProduceTritonPids || mProduceHeliumPids) { mFillAnyTable = true; } else { LOG(info) << "No tables configured, Selection object will not be configured..."; @@ -592,10 +534,6 @@ class TrackBuilder if (!mFillAnyTable) { return; } - - // clear index map before processing next batch of tracks - indexMap.clear(); - for (const auto& track : tracks) { if (!mTrackSelection.checkFilters(track)) { continue; @@ -627,6 +565,9 @@ class TrackBuilder trackProducts.producedTrackMasks(static_cast(0u)); } } + if (mProduceTrackMass) { + trackProducts.producedTrackMass(track.mass()); + } if (mProduceTrackDcas) { trackProducts.producedTrackDcas(track.dcaXY(), track.dcaZ()); } @@ -641,8 +582,7 @@ class TrackBuilder track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcNClsShared(), - track.beta(), - track.mass()); + track.beta()); } if (mProduceElectronPids) { trackProducts.producedElectronPids(track.itsNSigmaEl(), track.tpcNSigmaEl(), track.tofNSigmaEl()); @@ -673,8 +613,6 @@ class TrackBuilder if (!mFillAnyTable) { return; } - // clear index map before processing next batch of tracks - indexMap.clear(); for (const auto& trackWithItsPid : tracksWithItsPid) { if (!mTrackSelection.checkFilters(trackWithItsPid)) { continue; @@ -683,7 +621,6 @@ class TrackBuilder if (!mTrackSelection.passesAllRequiredSelections()) { continue; } - collisionBuilder.template fillMcCollision(collisionProducts, col, mcCols, mcProducts, mcBuilder); // get track from the track table so we can dereference mc particle properly auto track = tracks.iteratorAt(trackWithItsPid.index()); @@ -728,11 +665,19 @@ class TrackBuilder } } + template + void reset(T const& tracks) + { + indexMap.clear(); + indexMap.reserve(tracks.size()); + }; + private: TrackSelection mTrackSelection; bool mFillAnyTable = false; bool mProduceTracks = false; bool mProduceTrackMasks = false; + bool mProduceTrackMass = false; bool mProduceTrackDcas = false; bool mProduceTrackExtras = false; bool mProduceElectronPids = false; @@ -753,8 +698,8 @@ struct TrackBuilderDerivedToDerivedProducts : o2::framework::ProducesGroup { struct ConfTrackTablesDerivedToDerived : o2::framework::ConfigurableGroup { std::string prefix = std::string("TrackTables"); - o2::framework::Configurable limitTrack1{"limitTrack1", 1, "At least this many tracks of type 1 need to be in the collision"}; - o2::framework::Configurable limitTrack2{"limitTrack2", 0, "At least this many tracks of type 2 need to be in the collision"}; + o2::framework::Configurable limitTrack1{"limitTrack1", 1, "At least this many tracks of type 1 need to be in the collision. Ignored if set to 0."}; + o2::framework::Configurable limitTrack2{"limitTrack2", 0, "At least this many tracks of type 2 need to be in the collision. Ignored if set to 0."}; }; class TrackBuilderDerivedToDerived @@ -768,6 +713,10 @@ class TrackBuilderDerivedToDerived { mLimitTrack1 = config.limitTrack1.value; mLimitTrack2 = config.limitTrack2.value; + + if (mLimitTrack1 == 0 && mLimitTrack2 == 0) { + LOG(fatal) << "Both track limits are 0. Breaking..."; + } } template @@ -775,36 +724,40 @@ class TrackBuilderDerivedToDerived { auto trackSlice1 = partitionTrack1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); auto trackSlice2 = partitionTrack2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - if (trackSlice1.size() >= mLimitTrack1 && trackSlice2.size() >= mLimitTrack2) { - return false; - } - return true; + return trackSlice1.size() < mLimitTrack1 || trackSlice2.size() < mLimitTrack2; } template void processTracks(T1& col, T2& /*trackTable*/, T3& partitionTrack1, T4& partitionTrack2, T5& cache, T6& newTrackTable, T7& newCollisionTable) { indexMap.clear(); - auto trackSlice1 = partitionTrack1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - auto trackSlice2 = partitionTrack2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); - for (auto const& track : trackSlice1) { - this->fillTrack(track, newTrackTable, newCollisionTable); + if (mLimitTrack1 > 0) { + auto trackSlice1 = partitionTrack1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + for (auto const& track : trackSlice1) { + this->fillTrack(track, newTrackTable, newCollisionTable); + } } - for (auto const& track : trackSlice2) { - this->fillTrack(track, newTrackTable, newCollisionTable); + + if (mLimitTrack2 > 0) { + auto trackSlice2 = partitionTrack2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + for (auto const& track : trackSlice2) { + this->fillTrack(track, newTrackTable, newCollisionTable); + } } } template void fillTrack(T1 const& track, T2& trackProducts, T3& collisionProducts) { - trackProducts.producedTracks(collisionProducts.producedCollision.lastIndex(), - track.signedPt(), - track.eta(), - track.phi()); - trackProducts.producedTrackMasks(track.mask()); - indexMap.emplace(track.globalIndex(), trackProducts.producedTracks.lastIndex()); + if (indexMap.find(track.globalIndex()) == indexMap.end()) { // protect against double filling + trackProducts.producedTracks(collisionProducts.producedCollision.lastIndex(), + track.signedPt(), + track.eta(), + track.phi()); + trackProducts.producedTrackMasks(track.mask()); + indexMap.emplace(track.globalIndex(), trackProducts.producedTracks.lastIndex()); + } } template @@ -816,7 +769,6 @@ class TrackBuilderDerivedToDerived } else { this->fillTrack(daughter, trackProducts, collisionProducts); int64_t idx = trackProducts.producedTracks.lastIndex(); - indexMap.emplace(daughter.globalIndex(), idx); return idx; } } diff --git a/PWGCF/Femto/Core/trackHistManager.h b/PWGCF/Femto/Core/trackHistManager.h index 4977aa4bd30..dbff8bb2dd1 100644 --- a/PWGCF/Femto/Core/trackHistManager.h +++ b/PWGCF/Femto/Core/trackHistManager.h @@ -20,14 +20,16 @@ #include "PWGCF/Femto/Core/histManager.h" #include "PWGCF/Femto/Core/modes.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include +#include +#include -#include "TH1.h" +#include #include +#include #include #include #include @@ -45,6 +47,7 @@ enum TrackHist { kEta, kPhi, kSign, + kMass, // qa variables kPAtPv, kPTpc, @@ -145,11 +148,13 @@ struct ConfTrackBinning : o2::framework::ConfigurableGroup { o2::framework::ConfigurableAxis eta{"eta", {{300, -1.5, 1.5}}, "Eta"}; o2::framework::ConfigurableAxis phi{"phi", {{720, 0, 1.f * o2::constants::math::TwoPI}}, "Phi"}; o2::framework::ConfigurableAxis sign{"sign", {{3, -1.5, 1.5}}, "Sign"}; + o2::framework::ConfigurableAxis mass{"mass", {{200, 0.f, 2.f}}, "Mass (if enabled, plot TOF mass, otherwise PDG mass)"}; o2::framework::ConfigurableAxis pdgCodes{"pdgCodes", {{8001, -4000.5, 4000.5}}, "MC ONLY: PDG codes of selected tracks"}; }; constexpr const char PrefixTrackBinning1[] = "TrackBinning1"; constexpr const char PrefixTrackBinning2[] = "TrackBinning2"; +constexpr const char PrefixTrackBinning3[] = "TrackBinning3"; constexpr const char PrefixResonancePosDauBinning[] = "ResonancePosDauBinning"; constexpr const char PrefixResonanceNegDauBinning[] = "ResonanceNegDauBinning"; constexpr const char PrefixV0PosDauBinning[] = "V0PosDauBinning"; @@ -161,6 +166,7 @@ constexpr const char PrefixKinkChaDauBinning[] = "KinkChaDauBinning"; using ConfTrackBinning1 = ConfTrackBinning; using ConfTrackBinning2 = ConfTrackBinning; +using ConfTrackBinning3 = ConfTrackBinning; using ConfResonancePosDauBinning = ConfTrackBinning; using ConfResonanceNegDauBinning = ConfTrackBinning; using ConfV0PosDauBinning = ConfTrackBinning; @@ -266,7 +272,8 @@ constexpr std::array, kTrackHistLast> {kPt, o2::framework::kTH1F, "hPt", "Transverse Momentum; p_{T} (GeV/#it{c}); Entries"}, {kEta, o2::framework::kTH1F, "hEta", "Pseudorapidity; #eta; Entries"}, {kPhi, o2::framework::kTH1F, "hPhi", "Azimuthal angle; #varphi; Entries"}, - {kSign, o2::framework::kTH1F, "hSign", "Sign of charge ; Sign; Entries"}, + {kSign, o2::framework::kTH1F, "hSign", "Sign of charge; Sign; Entries"}, + {kMass, o2::framework::kTH1F, "hMass", "Mass; m (GeV/#it{c}^{2}); Entries"}, {kPAtPv, o2::framework::kTH1F, "hPAtPv", "Momentum at Primary vertex; p_{vertex}; Entries"}, {kPTpc, o2::framework::kTH1F, "hPTpc", "Momentum at inner wall of TPC; p_{TPC}; Entries"}, {kItsCluster, o2::framework::kTH1F, "hItsCluster", "ITS cluster; ITS cluster; Entries"}, @@ -351,7 +358,8 @@ constexpr std::array, kTrackHistLast> {kPt, {conf.pt}}, \ {kEta, {conf.eta}}, \ {kPhi, {conf.phi}}, \ - {kSign, {conf.sign}}, + {kSign, {conf.sign}}, \ + {kMass, {conf.mass}}, #define TRACK_HIST_QA_MAP(confAnalysis, confQa) \ {kPAtPv, {confQa.p}}, \ @@ -439,14 +447,14 @@ constexpr std::array, kTrackHistLast> template auto makeTrackHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ TRACK_HIST_ANALYSIS_MAP(confBinningAnalysis)}; } template auto makeTrackMcHistSpecMap(T const& confBinningAnalysis) { - return std::map>{ + return std::map>{ TRACK_HIST_ANALYSIS_MAP(confBinningAnalysis) TRACK_HIST_MC_MAP(confBinningAnalysis)}; }; @@ -454,7 +462,7 @@ auto makeTrackMcHistSpecMap(T const& confBinningAnalysis) template auto makeTrackQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ + return std::map>{ TRACK_HIST_ANALYSIS_MAP(confBinningAnalysis) TRACK_HIST_QA_MAP(confBinningAnalysis, confBinningQa)}; } @@ -462,7 +470,7 @@ auto makeTrackQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinning template auto makeTrackMcQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ + return std::map>{ TRACK_HIST_ANALYSIS_MAP(confBinningAnalysis) TRACK_HIST_QA_MAP(confBinningAnalysis, confBinningQa) TRACK_HIST_MC_MAP(confBinningAnalysis) @@ -501,7 +509,7 @@ constexpr char PrefixCascadeBachelorQa[] = "CascadeBachelorQa/"; constexpr char PrefixKinkChaDaughter[] = "KinkChaDau/"; constexpr char PrefixKinkChaDaughterQa[] = "KinkChaDauQa/"; -constexpr std::string_view AnalysisDir = "Kinematics/"; +constexpr std::string_view AnalysisDir = "Analysis/"; constexpr std::string_view QaDir = "QA/"; constexpr std::string_view PidDir = "PID/"; constexpr std::string_view McDir = "MC/"; @@ -635,6 +643,7 @@ class TrackHistManager mHistogramRegistry->add(analysisDir + getHistNameV2(kEta, HistTable), getHistDesc(kEta, HistTable), getHistType(kEta, HistTable), {Specs.at(kEta)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kPhi, HistTable), getHistDesc(kPhi, HistTable), getHistType(kPhi, HistTable), {Specs.at(kPhi)}); mHistogramRegistry->add(analysisDir + getHistNameV2(kSign, HistTable), getHistDesc(kSign, HistTable), getHistType(kSign, HistTable), {Specs.at(kSign)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kMass, HistTable), getHistDesc(kMass, HistTable), getHistType(kMass, HistTable), {Specs.at(kMass)}); } void initQa(std::map> const& Specs) @@ -742,7 +751,7 @@ class TrackHistManager mHistogramRegistry->add(mcDir + getHistNameV2(kTruePhiVsPhi, HistTable), getHistDesc(kTruePhiVsPhi, HistTable), getHistType(kTruePhiVsPhi, HistTable), {Specs.at(kTruePhiVsPhi)}); // mc origin can be configured here - const framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; + const o2::framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; mHistogramRegistry->add(mcDir + getHistNameV2(kOrigin, HistTable), getHistDesc(kOrigin, HistTable), getHistType(kOrigin, HistTable), {axisOrigin}); mHistogramRegistry->get(HIST(prefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kNoMcParticle), modes::mcOriginToString(modes::McOrigin::kNoMcParticle)); mHistogramRegistry->get(HIST(prefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kFromWrongCollision), modes::mcOriginToString(modes::McOrigin::kFromWrongCollision)); @@ -782,6 +791,11 @@ class TrackHistManager mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kEta, HistTable)), track.eta()); mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kPhi, HistTable)), track.phi()); mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kSign, HistTable)), track.sign()); + if constexpr (utils::HasMass) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kMass, HistTable)), track.mass()); + } else { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kMass, HistTable)), utils::getPdgMass(mPdgCode)); + } } template @@ -829,7 +843,7 @@ class TrackHistManager mHistogramRegistry->fill(HIST(prefix) + HIST(PidDir) + HIST(getHistName(kItsSignal, HistTable)), momentum, o2::analysis::femto::utils::itsSignal(track)); mHistogramRegistry->fill(HIST(prefix) + HIST(PidDir) + HIST(getHistName(kTpcSignal, HistTable)), momentum, track.tpcSignal()); mHistogramRegistry->fill(HIST(prefix) + HIST(PidDir) + HIST(getHistName(kTofBeta, HistTable)), momentum, track.tofBeta()); - mHistogramRegistry->fill(HIST(prefix) + HIST(PidDir) + HIST(getHistName(kTofMass, HistTable)), momentum, track.tofMass()); + mHistogramRegistry->fill(HIST(prefix) + HIST(PidDir) + HIST(getHistName(kTofMass, HistTable)), momentum, track.mass()); if (mPlotElectronPid) { mHistogramRegistry->fill(HIST(prefix) + HIST(PidDir) + HIST(getHistName(kItsElectron, HistTable)), momentum, track.itsNSigmaEl()); diff --git a/PWGCF/Femto/Core/tripletBuilder.h b/PWGCF/Femto/Core/tripletBuilder.h new file mode 100644 index 00000000000..1857f6a3996 --- /dev/null +++ b/PWGCF/Femto/Core/tripletBuilder.h @@ -0,0 +1,629 @@ +// Copyright 2019-2025 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 tripletBuilder.h +/// \brief histogram manager for pair tasks +/// \author anton.riedel@tum.de, TU München, anton.riedel@tum.de + +#ifndef PWGCF_FEMTO_CORE_TRIPLETBUILDER_H_ +#define PWGCF_FEMTO_CORE_TRIPLETBUILDER_H_ + +#include "PWGCF/Femto/Core/closeTripletRejection.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/tripletCleaner.h" +#include "PWGCF/Femto/Core/tripletHistManager.h" +#include "PWGCF/Femto/Core/tripletProcessHelpers.h" +#include "PWGCF/Femto/Core/v0HistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace o2::analysis::femto +{ +namespace tripletbuilder +{ + +const int64_t nLimitPartitionIdenticalParticles123 = 3; +const int64_t nLimitPartitionIdenticalParticles12 = 2; +const int64_t nLimitPartitionParticles = 1; + +template +class TripletTrackTrackTrackBuilder +{ + public: + TripletTrackTrackTrackBuilder() = default; + ~TripletTrackTrackTrackBuilder() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + T1 const& confCollisionBinning, + T2 const& confTrackSelection1, + T3 const& confTrackSelection2, + T4 const& confTrackSelection3, + T5 const& confCtr, + T6 const& confMixing, + T7 const& confTripletBinning, + T8 const& confTripletCuts, + std::map> const& colHistSpec, + std::map> const& trackHistSpec1, + std::map> const& trackHistSpec2, + std::map> const& trackHistSpec3, + std::map> const& pairHistSpec, + std::map> const& cprHistSpec) + { + // check if correlate the same tracks or not + mTrack1Track2Track3AreSameSpecies = confMixing.particle123AreSameSpecies.value; + mTrack1Track2AreSameSpecies = confMixing.particle12AreSameSpecies.value; + + if (mTrack1Track2Track3AreSameSpecies && mTrack1Track2AreSameSpecies) { + LOG(fatal) << "Option Track 1&2 are identical and Option Track 1&2&3 are identical is activated. Breaking..."; + } + + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); + mTripletHistManagerSe.template init(registry, pairHistSpec, confTripletBinning, confTripletCuts); + mTripletHistManagerMe.template init(registry, pairHistSpec, confTripletBinning, confTripletCuts); + + mTc.template init(confTripletCuts); + + if (mTrack1Track2Track3AreSameSpecies) { + // Track1 & Track2 & Track3 are the same particle species + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + mCtrSe.init(registry, cprHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + mCtrMe.init(registry, cprHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + } else if (mTrack1Track2AreSameSpecies) { + // Track1 & Track2 & are the same particle species and track 3 is something else + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + mTrackHistManager3.template init(registry, trackHistSpec3, confTrackSelection2); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confTrackSelection3.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection3.chargeAbs.value); + mCtrSe.init(registry, cprHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection3.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confTrackSelection3.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection3.chargeAbs.value); + mCtrMe.init(registry, cprHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, confTrackSelection3.chargeAbs.value); + } else { + // all three tracks are different + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + mTrackHistManager2.template init(registry, trackHistSpec2, confTrackSelection2); + mTrackHistManager3.template init(registry, trackHistSpec3, confTrackSelection3); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection2.pdgCodeAbs.value, confTrackSelection3.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, confTrackSelection3.chargeAbs.value); + mCtrSe.init(registry, cprHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, confTrackSelection3.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection2.pdgCodeAbs.value, confTrackSelection3.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, confTrackSelection3.chargeAbs.value); + mCtrMe.init(registry, cprHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, confTrackSelection3.chargeAbs.value); + } + + // setup mixing + mMixingPolicy = static_cast(confMixing.policy.value); + mMixingDepth = confMixing.depth.value; + + // setup rng if necessary + if (confMixing.seed.value >= 0) { + uint64_t randomSeed = 0; + mMixIdenticalParticles = true; + if (confMixing.seed.value == 0) { + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } else { + randomSeed = static_cast(confMixing.seed.value); + } + mRng = std::mt19937(randomSeed); + if (mTrack1Track2Track3AreSameSpecies) { + mDist = std::uniform_int_distribution<>(tripletprocesshelpers::kOrder123, tripletprocesshelpers::kOrder321); + } + if (mTrack1Track2AreSameSpecies) { + mDist = std::uniform_int_distribution<>(tripletprocesshelpers::kOrder123, tripletprocesshelpers::kOrder213); + } + } + } + + // data + template + void processSameEvent(T1 const& col, T2& trackTable, T3& partition1, T4& partition2, T5& partition3, T6& cache) + { + tripletprocesshelpers::TripletOrder tripletOrder = tripletprocesshelpers::kOrder123; + if (mTrack1Track2Track3AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles123) { + return; + } + mColHistManager.template fill(col, trackSlice1.size(), trackSlice1.size(), trackSlice1.size()); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, trackTable, col, mTrackHistManager1, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else if (mTrack1Track2AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice3 = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles12 || trackSlice3.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, trackSlice1.size(), trackSlice1.size(), trackSlice3.size()); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice3, trackTable, col, mTrackHistManager1, mTrackHistManager3, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice3 = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles || trackSlice3.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, trackSlice1.size(), trackSlice2.size(), trackSlice3.size()); + mCtrSe.setMagField(col.magField()); + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice2, trackSlice3, trackTable, col, mTrackHistManager1, mTrackHistManager2, mTrackHistManager3, mTripletHistManagerSe, mCtrSe, mTc); + } + } + + // mc + template + void processSameEvent(T1 const& col, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6& partition3, T7 const& mcParticles, T8 const& mcMothers, T9 const& mcPartonicMothers, T10& cache) + { + tripletprocesshelpers::TripletOrder tripletOrder = tripletprocesshelpers::kOrder123; + if (mTrack1Track2Track3AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles123) { + return; + } + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice1.size(), trackSlice1.size()); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else if (mTrack1Track2AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice3 = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles12 || trackSlice3.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice1.size(), trackSlice3.size()); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice3, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTrackHistManager3, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice3 = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles || trackSlice3.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice2.size(), trackSlice3.size()); + mCtrSe.setMagField(col.magField()); + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice2, trackSlice3, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTrackHistManager2, mTrackHistManager3, mTripletHistManagerSe, mCtrSe, mTc); + } + } + + template + void processMixedEvent(T1 const& cols, T2& trackTable, T3& partition1, T4& partition2, T5& partition3, T6& cache, T7& binsVtxMult, T8& binsVtxCent, T9& binsVtxMultCent) + { + if (mTrack1Track2Track3AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition1, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition1, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition1, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else if (mTrack1Track2AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6& partition3, T7 const& mcParticles, T8& cache, T9& binsVtxMult, T10& binsVtxCent, T11& binsVtxMultCent) + { + if (mTrack1Track2Track3AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition1, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition1, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition1, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else if (mTrack1Track2AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + + private: + colhistmanager::CollisionHistManager mColHistManager; + trackhistmanager::TrackHistManager mTrackHistManager1; + trackhistmanager::TrackHistManager mTrackHistManager2; + trackhistmanager::TrackHistManager mTrackHistManager3; + triplethistmanager::TripletHistManager mTripletHistManagerSe; + triplethistmanager::TripletHistManager mTripletHistManagerMe; + + closetripletrejection::CloseTripletRejectionTrackTrackTrack mCtrSe; + closetripletrejection::CloseTripletRejectionTrackTrackTrack mCtrMe; + tripletcleaner::TrackTrackTrackTripletCleaner mTc; + triplethistmanager::MixingPolicy mMixingPolicy = triplethistmanager::MixingPolicy::kVtxMult; + bool mTrack1Track2Track3AreSameSpecies = false; + bool mTrack1Track2AreSameSpecies = false; + int mMixingDepth = 5; + bool mMixIdenticalParticles = false; + std::mt19937 mRng; + std::uniform_int_distribution<> mDist; +}; + +template +class TripletTrackTrackV0Builder +{ + public: + TripletTrackTrackV0Builder() = default; + ~TripletTrackTrackV0Builder() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + T1 const& confCollisionBinning, + T2 const& confTrackSelection1, + T3 const& confTrackSelection2, + T4 const& confV0Selection, + T5 const& confCtr, + T6 const& confMixing, + T7 const& confTripletBinning, + T8 const& confTripletCuts, + std::map> const& colHistSpec, + std::map> const& trackHistSpec1, + std::map> const& trackHistSpec2, + std::map> const& v0histSpec, + std::map> const& posDauhistSpec, + std::map> const& negDauhistSpec, + std::map> const& tripletHistSpec, + std::map> const& ctrHistSpec) + { + // check if correlate the same tracks or not + mTrack1Track2AreSameSpecies = confMixing.particle12AreSameSpecies.value; + + mColHistManager.template init(registry, colHistSpec, confCollisionBinning); + mTripletHistManagerSe.template init(registry, tripletHistSpec, confTripletBinning, confTripletCuts); + mTripletHistManagerMe.template init(registry, tripletHistSpec, confTripletBinning, confTripletCuts); + + mTc.template init(confTripletCuts); + + if (mTrack1Track2AreSameSpecies) { + // Track1 & Track2 & are the same particle species and track 3 is something else + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + mV0HistManager.template init(registry, v0histSpec, confV0Selection, posDauhistSpec, negDauhistSpec); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confV0Selection.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, 1); + mCtrSe.init(registry, ctrHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection1.pdgCodeAbs.value, confV0Selection.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value, 1); + mCtrMe.init(registry, ctrHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection1.chargeAbs.value); + } else { + // all three tracks are different + mTrackHistManager1.template init(registry, trackHistSpec1, confTrackSelection1); + mTrackHistManager2.template init(registry, trackHistSpec2, confTrackSelection2); + mV0HistManager.template init(registry, v0histSpec, confV0Selection, posDauhistSpec, negDauhistSpec); + + mTripletHistManagerSe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection2.pdgCodeAbs.value, confV0Selection.pdgCodeAbs.value); + mTripletHistManagerSe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, 1); + mCtrSe.init(registry, ctrHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value); + + mTripletHistManagerMe.setMass(confTrackSelection1.pdgCodeAbs.value, confTrackSelection2.pdgCodeAbs.value, confV0Selection.pdgCodeAbs.value); + mTripletHistManagerMe.setCharge(confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value, 1); + mCtrMe.init(registry, ctrHistSpec, confCtr, confTrackSelection1.chargeAbs.value, confTrackSelection2.chargeAbs.value); + } + + // setup mixing + mMixingPolicy = static_cast(confMixing.policy.value); + mMixingDepth = confMixing.depth.value; + + // setup rng if necessary + if (confMixing.seed.value >= 0) { + uint64_t randomSeed = 0; + mMixIdenticalParticles = true; + if (confMixing.seed.value == 0) { + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } else { + randomSeed = static_cast(confMixing.seed.value); + } + mRng = std::mt19937(randomSeed); + mDist = std::uniform_int_distribution<>(tripletprocesshelpers::kOrder123, tripletprocesshelpers::kOrder213); + } + } + + // data + template + void processSameEvent(T1 const& col, T2& trackTable, T3& partition1, T4& partition2, T5& partition3, T6& cache) + { + tripletprocesshelpers::TripletOrder tripletOrder = tripletprocesshelpers::kOrder123; + if (mTrack1Track2AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto v0Slice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles12 || v0Slice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, trackSlice1.size(), trackSlice1.size(), v0Slice.size()); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, v0Slice, trackTable, col, mTrackHistManager1, mV0HistManager, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto v0Slice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles || v0Slice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, trackSlice1.size(), trackSlice2.size(), v0Slice.size()); + mCtrSe.setMagField(col.magField()); + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice2, v0Slice, trackTable, col, mTrackHistManager1, mTrackHistManager2, mV0HistManager, mTripletHistManagerSe, mCtrSe, mTc); + } + } + + // mc + template + void processSameEvent(T1 const& col, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6& partition3, T7 const& mcParticles, T8 const& mcMothers, T9 const& mcPartonicMothers, T10& cache) + { + tripletprocesshelpers::TripletOrder tripletOrder = tripletprocesshelpers::kOrder123; + if (mTrack1Track2AreSameSpecies) { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto v0Slice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionIdenticalParticles12 || v0Slice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice1.size(), v0Slice.size()); + mCtrSe.setMagField(col.magField()); + if (mMixIdenticalParticles) { + tripletOrder = static_cast(mDist(mRng)); + } + tripletprocesshelpers::processSameEvent(trackSlice1, v0Slice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mV0HistManager, mTripletHistManagerSe, mCtrSe, mTc, tripletOrder); + } else { + auto trackSlice1 = partition1->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto trackSlice2 = partition2->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + auto v0Slice = partition3->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + if (trackSlice1.size() < nLimitPartitionParticles || trackSlice2.size() < nLimitPartitionParticles || v0Slice.size() < nLimitPartitionParticles) { + return; + } + mColHistManager.template fill(col, mcCols, trackSlice1.size(), trackSlice2.size(), v0Slice.size()); + mCtrSe.setMagField(col.magField()); + tripletprocesshelpers::processSameEvent(trackSlice1, trackSlice2, v0Slice, trackTable, mcParticles, mcMothers, mcPartonicMothers, col, mcCols, mTrackHistManager1, mTrackHistManager2, mV0HistManager, mTripletHistManagerSe, mCtrSe, mTc); + } + } + + template + void processMixedEvent(T1 const& cols, T2& trackTable, T3& partition1, T4& partition2, T5& partition3, T6& cache, T7& binsVtxMult, T8& binsVtxCent, T9& binsVtxMultCent) + { + if (mTrack1Track2AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition1, partition3, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, partition1, partition2, partition3, trackTable, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + + template + void processMixedEvent(T1 const& cols, T2 const& mcCols, T3& trackTable, T4& partition1, T5& partition2, T6& partition3, T7 const& mcParticles, T8& cache, T9& binsVtxMult, T10& binsVtxCent, T11& binsVtxMultCent) + { + if (mTrack1Track2AreSameSpecies) { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition1, partition3, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } else { + switch (mMixingPolicy) { + case static_cast(pairhistmanager::kVtxMult): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxMult, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + case static_cast(pairhistmanager::kVtxMultCent): + tripletprocesshelpers::processMixedEvent(cols, mcCols, partition1, partition2, partition3, trackTable, mcParticles, cache, binsVtxMultCent, mMixingDepth, mTripletHistManagerMe, mCtrMe, mTc); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + } + + private: + colhistmanager::CollisionHistManager mColHistManager; + trackhistmanager::TrackHistManager mTrackHistManager1; + trackhistmanager::TrackHistManager mTrackHistManager2; + v0histmanager::V0HistManager mV0HistManager; + triplethistmanager::TripletHistManager mTripletHistManagerSe; + triplethistmanager::TripletHistManager mTripletHistManagerMe; + + closetripletrejection::CloseTripletRejectionTrackTrackV0 mCtrSe; + closetripletrejection::CloseTripletRejectionTrackTrackV0 mCtrMe; + tripletcleaner::TrackTrackV0TripletCleaner mTc; + triplethistmanager::MixingPolicy mMixingPolicy = triplethistmanager::MixingPolicy::kVtxMult; + bool mTrack1Track2AreSameSpecies = false; + int mMixingDepth = 5; + bool mMixIdenticalParticles = false; + std::mt19937 mRng; + std::uniform_int_distribution<> mDist; +}; + +} // namespace tripletbuilder +} // namespace o2::analysis::femto + +#endif // PWGCF_FEMTO_CORE_TRIPLETBUILDER_H_ diff --git a/PWGCF/Femto/Core/tripletCleaner.h b/PWGCF/Femto/Core/tripletCleaner.h new file mode 100644 index 00000000000..d6f38c78709 --- /dev/null +++ b/PWGCF/Femto/Core/tripletCleaner.h @@ -0,0 +1,105 @@ +// 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 tripletCleaner.h +/// \brief triplet cleaner class +/// \author anton.riedel@tum.de, TU München, anton.riedel@tum.de + +#ifndef PWGCF_FEMTO_CORE_TRIPLETCLEANER_H_ +#define PWGCF_FEMTO_CORE_TRIPLETCLEANER_H_ + +#include "PWGCF/Femto/Core/pairCleaner.h" + +namespace o2::analysis::femto +{ +namespace tripletcleaner +{ + +class TrackTrackTrackTripletCleaner : public paircleaner::BasePairCleaner +{ + public: + TrackTrackTrackTripletCleaner() = default; + ~TrackTrackTrackTripletCleaner() = default; + + template + bool isCleanTriplet(T1 const& track1, T2 const& track2, T3 const& track3, T4 const& /*trackTable*/) const + { + return this->isCleanTrackPair(track1, track2) && + this->isCleanTrackPair(track2, track3) && + this->isCleanTrackPair(track1, track3); + } + + template + bool isCleanTriplet(T1 const& track1, T2 const& track2, T3 const& track3, T4 const& trackTable, T5 const& partonicMothers) const + { + if (!this->isCleanTriplet(track1, track2, track3, trackTable)) { + return false; + } + // pair is clean + // no check if we require common or non-common ancestry + if (mMixPairsWithCommonAncestor) { + return this->pairHasCommonAncestor(track1, track2, partonicMothers) && + this->pairHasCommonAncestor(track2, track3, partonicMothers) && + this->pairHasCommonAncestor(track1, track3, partonicMothers); + } + if (mMixPairsWithNonCommonAncestor) { + return this->pairHasNonCommonAncestor(track1, track2, partonicMothers) && + this->pairHasNonCommonAncestor(track2, track3, partonicMothers) && + this->pairHasNonCommonAncestor(track1, track3, partonicMothers); + } + return true; + } +}; + +class TrackTrackV0TripletCleaner : public paircleaner::BasePairCleaner +{ + public: + TrackTrackV0TripletCleaner() = default; + ~TrackTrackV0TripletCleaner() = default; + + template + bool isCleanTriplet(T1 const& track1, T2 const& track2, T3 const& v0, T4 const& trackTable) const + { + auto posDaughter = trackTable.rawIteratorAt(v0.posDauId() - trackTable.offset()); + auto negDaughter = trackTable.rawIteratorAt(v0.negDauId() - trackTable.offset()); + return this->isCleanTrackPair(track1, track2) && + this->isCleanTrackPair(track1, posDaughter) && + this->isCleanTrackPair(track1, negDaughter) && + this->isCleanTrackPair(track2, posDaughter) && + this->isCleanTrackPair(track2, negDaughter); + } + + template + bool isCleanTriplet(T1 const& track1, T2 const& track2, T3 const& v0, T4 const& trackTable, T5 const& partonicMothers) const + { + if (!this->isCleanTriplet(track1, track2, v0, trackTable)) { + return false; + } + // pair is clean + // no check if we require common or non-common ancestry + if (mMixPairsWithCommonAncestor) { + return this->pairHasCommonAncestor(track1, track2, partonicMothers) && + this->pairHasCommonAncestor(track1, v0, partonicMothers) && + this->pairHasCommonAncestor(track2, v0, partonicMothers); + } + if (mMixPairsWithNonCommonAncestor) { + return this->pairHasNonCommonAncestor(track1, track2, partonicMothers) && + this->pairHasNonCommonAncestor(track1, v0, partonicMothers) && + this->pairHasNonCommonAncestor(track2, v0, partonicMothers); + } + return true; + } +}; + +} // namespace tripletcleaner +} // namespace o2::analysis::femto + +#endif // PWGCF_FEMTO_CORE_TRIPLETCLEANER_H_ diff --git a/PWGCF/Femto/Core/tripletHistManager.h b/PWGCF/Femto/Core/tripletHistManager.h new file mode 100644 index 00000000000..672e9f68055 --- /dev/null +++ b/PWGCF/Femto/Core/tripletHistManager.h @@ -0,0 +1,583 @@ +// Copyright 2019-2025 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 tripletHistManager.h +/// \brief histogram manager for triplet tasks +/// \author anton.riedel@tum.de, TU München, anton.riedel@tum.de + +#ifndef PWGCF_FEMTO_CORE_TRIPLETHISTMANAGER_H_ +#define PWGCF_FEMTO_CORE_TRIPLETHISTMANAGER_H_ + +#include "PWGCF/Femto/Core/femtoUtils.h" +#include "PWGCF/Femto/Core/histManager.h" +#include "PWGCF/Femto/Core/modes.h" + +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include +#include +#include +#include +#include + +namespace o2::analysis::femto +{ +namespace triplethistmanager +{ +// enum for pair histograms +enum TripletHist { + // standard 1D + kQ3, + kMt, // averate mt of all pairs in the triplet + // standard 2D + kPt1VsQ3, + kPt2VsQ3, + kPt3VsQ3, + kQ3VsMt, + kQ3VsMult, + kQ3VsCent, + // 2D with mass + // kQ3VsMass1, + // kQ3VsMass2, + // kQ3VsMass3, + // higher dimensions + kPt1VsPt2VsPt3, + kQ3VsPt1VsPt2VsPt3, + kQ3VsMtVsMult, + kQ3VsMtVsMultVsCent, + kQ3VsMtVsPt1VsPt2VsPt3VsMult, + kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, + // higher dimensions with mass + // mc + kTrueQ3VsQ3, + kTrueMtVsMt, + kTrueMultVsMult, + kTrueCentVsCent, + + kTripletHistogramLast +}; + +enum MixingPolicy { + kVtxMult, + kVtxCent, + kVtxMultCent, + kMixingPolicyLast +}; + +// Mixing configurables +struct ConfMixing : o2::framework::ConfigurableGroup { + std::string prefix = std::string("Mixing"); + o2::framework::ConfigurableAxis multBins{"multBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis centBins{"centBins", {o2::framework::VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f}, "Mixing bins - centrality"}; + o2::framework::ConfigurableAxis vtxBins{"vtxBins", {o2::framework::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"}; + o2::framework::Configurable depth{"depth", 5, "Number of events for mixing"}; + o2::framework::Configurable policy{"policy", 0, "Binning policy for mixing (alywas in combination with z-vertex) -> 0: multiplicity, -> 1: centrality, -> 2: both"}; + o2::framework::Configurable seed{"seed", -1, "Seed to randomize particle 1/2/3 (if they are identical). Set to negative value to deactivate. Set to 0 to generate unique seed in time."}; + o2::framework::Configurable particle123AreSameSpecies{"particle123AreSameSpecies", false, "Particle 1,2 and 3 are of the same species"}; + o2::framework::Configurable particle12AreSameSpecies{"particle12AreSameSpecies", false, "Particle 1 and 2 are of the same species"}; +}; + +struct ConfTripletBinning : o2::framework::ConfigurableGroup { + std::string prefix = std::string("TripletBinning"); + o2::framework::Configurable plot1D{"plot1D", true, "Enable 1D histograms"}; + o2::framework::Configurable plot2D{"plot2D", true, "Enable 2D histograms"}; + o2::framework::Configurable plotPt1VsPt2VsPt3{"plotPt1VsPt2VsPt3", false, "Enable 3D histogram (Pt1 vs Pt2 vs Pt3)"}; + o2::framework::Configurable plotQ3VsPt1VsPt2VsPt3{"plotQ3VsPt1VsPt2VsPt3", false, "Enable 4D histogram (Q3 vs Pt1 vs Pt2 vs Pt3)"}; + o2::framework::Configurable plotQ3VsMtVsMult{"plotQ3VsMtVsMult", false, "Enable 3D histogram (Q3 vs Mt vs Mult)"}; + o2::framework::Configurable plotQ3VsMtVsMultVsCent{"plotQ3VsMtVsMultVsCent", false, "Enable 4D histogram (Q3 vs Mt vs Mult Vs Cent)"}; + o2::framework::Configurable plotQ3VsMtVsPt1VsPt2VsPt3VsMult{"plotQ3VsMtVsPt1VsPt2VsPt3VsMult", false, "Enable 6D histogram (Q3 vs Mt Vs Pt1 vs Pt2 vs Pt3 vs Mult)"}; + o2::framework::Configurable plotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent{"plotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent", false, "Enable 3D histogram (Q3 vs Mt Vs Pt1 vs Pt2 vs Pt3 vs Mult vs Cent)"}; + o2::framework::ConfigurableAxis q3{"q3", {{600, 0, 6}}, "q3"}; + o2::framework::ConfigurableAxis mt{"mt", {{500, 0.8, 5.8}}, "mt"}; + o2::framework::ConfigurableAxis multiplicity{"multiplicity", {{50, 0, 200}}, "multiplicity"}; + o2::framework::ConfigurableAxis centrality{"centrality", {{10, 0, 100}}, "centrality (mult. percentile)"}; + o2::framework::ConfigurableAxis pt1{"pt1", {{100, 0, 6}}, "Pt binning for particle 1"}; + o2::framework::ConfigurableAxis pt2{"pt2", {{100, 0, 6}}, "Pt binning for particle 2"}; + o2::framework::ConfigurableAxis pt3{"pt3", {{100, 0, 6}}, "Pt binning for particle 3"}; + o2::framework::ConfigurableAxis mass1{"mass1", {{100, 0, 2}}, "Mass binning for particle 1 (if particle has mass getter, otherwise PDG mass)"}; + o2::framework::ConfigurableAxis mass2{"mass2", {{100, 0, 2}}, "Mass binning for particle 2 (if particle has mass getter, otherwise PDG mass)"}; + o2::framework::ConfigurableAxis mass3{"mass3", {{100, 0, 2}}, "Mass binning for particle 3 (if particle has mass getter, otherwise PDG mass)"}; + o2::framework::Configurable transverseMassType{"transverseMassType", static_cast(modes::TransverseMassType::kAveragePdgMass), "Type of transverse mass (0-> Average Pdg Mass, 1-> Reduced Pdg Mass, 2-> Mt from combined 4 vector)"}; +}; + +struct ConfTripletCuts : o2::framework::ConfigurableGroup { + std::string prefix = std::string("TripletCuts"); + o2::framework::Configurable q3Max{"q3Max", -1, "Maximal kstar (set to -1 to deactivate)"}; + o2::framework::Configurable q3Min{"q3Min", -1, "Minimal kstar (set to -1 to deactivate)"}; + o2::framework::Configurable mtMax{"mtMax", -1, "Maximal mt (set to -1 to deactivate)"}; + o2::framework::Configurable mtMin{"mtMin", -1, "Minimal mt (set to -1 to deactivate)"}; + o2::framework::Configurable mixOnlyCommonAncestor{"mixOnlyCommonAncestor", false, "Require pair to have common anchestor (in the same event)"}; + o2::framework::Configurable mixOnlyNonCommonAncestor{"mixOnlyNonCommonAncestor", false, "Require pair to have non-common anchestor (in the same event)"}; +}; + +// the enum gives the correct index in the array +constexpr std::array, kTripletHistogramLast> + HistTable = { + { + // 1D + {kQ3, o2::framework::kTH1F, "hQ3", "Q_{3}; Q_{3} (GeV/#it{c}); Entries"}, + {kMt, o2::framework::kTH1F, "hMt", "transverse mass; m_{T} (GeV/#it{c}^{2}); Entries"}, + // 2D + {kPt1VsQ3, o2::framework::kTH2F, "hPt1VsQ3", " p_{T,1} vs Q_{3}; p_{T,1} (GeV/#it{c}); Q_{3} (GeV/#it{c})"}, + {kPt2VsQ3, o2::framework::kTH2F, "hPt2VsQ3", "p_{T,2} vs Q_{3}; p_{T,2} (GeV/#it{c}); Q_{3} (GeV/#it{c})"}, + {kPt3VsQ3, o2::framework::kTH2F, "hPt3VsQ3", "p_{T,3} vs Q_{3}; p_{T,2} (GeV/#it{c}); Q_{3} (GeV/#it{c})"}, + {kQ3VsMt, o2::framework::kTH2F, "hQ3VsMt", "Q_{3} vs m_{T}; Q_{3} (GeV/#it{c}); m_{T} (GeV/#it{c}^{2})"}, + {kQ3VsMult, o2::framework::kTH2F, "hQ3VsMult", "Q_{3} vs Multiplicity; Q_{3} (GeV/#it{c}); Multiplicity"}, + {kQ3VsCent, o2::framework::kTH2F, "hQ3VsCent", "Q_{3} vs Centrality; Q_{3} (GeV/#it{c}); Centrality"}, + // n-D + {kPt1VsPt2VsPt3, o2::framework::kTHnSparseF, "hPt1VsPt2VsPt3", "k* vs m_{T} vs multiplicity; k* (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity"}, + {kQ3VsPt1VsPt2VsPt3, o2::framework::kTHnSparseF, "hQ3VsPt1VsPt2VsPt3", "Q_{3} vs p_{T,1} vs p_{T,2} vs p_{T,3}; Q_{3} (GeV/#it{c}); p_{T,1} (GeV/#it{c}) ; p_{T,2} (GeV/#it{c}); p_{T,3} (GeV/#it{c})"}, + {kQ3VsMtVsMult, o2::framework::kTHnSparseF, "hQ3VsMtVsMult", "Q_{3} vs m_{T} vs multiplicity; Q_{3} (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity"}, + {kQ3VsMtVsMultVsCent, o2::framework::kTHnSparseF, "hQ3VsMtVsMultVsCent", "Q_{3} vs m_{T} vs multiplicity vs centrality; Q_{3} (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); Multiplicity; Centrality"}, + // n-D with mass + {kQ3VsMtVsPt1VsPt2VsPt3VsMult, o2::framework::kTHnSparseF, "hQ3VsMtVsPt1VsPt2VsPt3VsMult", "Q_{3} vs m_{T} vs p_{T,1} vs p_{T,2} vs p_{T,3} vs multiplicity; Q_{3} (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}) ; p_{T,2} (GeV/#it{c}); p_{T,3} (GeV/#it{c}) ; Multiplicity"}, + {kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, o2::framework::kTHnSparseF, "hQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent", "Q_{3} vs m_{T} vs p_{T,1} vs p_{T,2} vs p_{T,3} vs multiplicity vs centrality; Q_{3} (GeV/#it{c}); m_{T} (GeV/#it{c}^{2}); p_{T,1} (GeV/#it{c}) ; p_{T,2} (GeV/#it{c}); p_{T,3} (GeV/#it{c}) vs multiplicity vs centrality"}, + {kTrueQ3VsQ3, o2::framework::kTH2F, "hTrueQ3VsQ3", "Q_{3,True} vs Q_{3}; Q_{3,true} (GeV/#it{c}); Q_{3} (GeV/#it{c})"}, + {kTrueMtVsMt, o2::framework::kTH2F, "hTrueMtVsMt", "m_{T,True} vs m_{T}; m_{T,True} (GeV/#it{c}^{2}); m_{T} (GeV/#it{c}^{2})"}, + {kTrueMultVsMult, o2::framework::kTH2F, "hTrueMultVsMult", "Multiplicity_{True} vs Multiplicity; Multiplicity_{True} ; Multiplicity"}, + {kTrueCentVsCent, o2::framework::kTH2F, "hTrueCentVsCent", "Centrality_{True} vs Centrality; Centrality_{True} (%); Centrality (%)"}, + }}; + +#define TRIPLET_HIST_ANALYSIS_MAP(conf) \ + {kQ3, {conf.q3}}, \ + {kMt, {conf.mt}}, \ + {kPt1VsQ3, {conf.pt1, conf.q3}}, \ + {kPt2VsQ3, {conf.pt2, conf.q3}}, \ + {kPt3VsQ3, {conf.pt3, conf.q3}}, \ + {kQ3VsMt, {conf.q3, conf.mt}}, \ + {kQ3VsMult, {conf.q3, conf.multiplicity}}, \ + {kQ3VsCent, {conf.q3, conf.centrality}}, \ + {kPt1VsPt2VsPt3, {conf.pt1, conf.pt2, conf.pt3}}, \ + {kQ3VsPt1VsPt2VsPt3, {conf.q3, conf.pt1, conf.pt2, conf.pt3}}, \ + {kQ3VsMtVsMult, {conf.q3, conf.mt, conf.multiplicity}}, \ + {kQ3VsMtVsMultVsCent, {conf.q3, conf.mt, conf.multiplicity, conf.centrality}}, \ + {kQ3VsMtVsPt1VsPt2VsPt3VsMult, {conf.q3, conf.mt, conf.pt1, conf.pt2, conf.pt3, conf.multiplicity}}, \ + {kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, {conf.q3, conf.mt, conf.pt1, conf.pt2, conf.pt3, conf.multiplicity, conf.centrality}}, + +#define TRIPLET_HIST_MC_MAP(conf) \ + {kTrueQ3VsQ3, {conf.q3, conf.q3}}, \ + {kTrueMtVsMt, {conf.mt, conf.mt}}, \ + {kTrueMultVsMult, {conf.multiplicity, conf.multiplicity}}, \ + {kTrueCentVsCent, {conf.centrality, conf.centrality}}, + +template +auto makeTripletHistSpecMap(const T& confPairBinning) +{ + return std::map>{ + TRIPLET_HIST_ANALYSIS_MAP(confPairBinning)}; +}; + +template +auto makeTripletMcHistSpecMap(const T& confPairBinning) +{ + return std::map>{ + TRIPLET_HIST_ANALYSIS_MAP(confPairBinning) + TRIPLET_HIST_MC_MAP(confPairBinning)}; +}; + +#undef TRIPLET_HIST_ANALYSIS_MAP +#undef TRIPLET_HIST_MC_MAP + +constexpr char PrefixTrackTrackTrackSe[] = "TrackTrackTrack/SE/"; +constexpr char PrefixTrackTrackTrackMe[] = "TrackTrackTrack/ME/"; + +constexpr char PrefixTrackTrackLambdaSe[] = "TrackTrackLambda/SE/"; +constexpr char PrefixTrackTrackLambdaMe[] = "TrackTrackLambda/ME/"; + +constexpr std::string_view AnalysisDir = "Analysis/"; +constexpr std::string_view QaDir = "QA/"; +constexpr std::string_view McDir = "MC/"; + +template +class TripletHistManager +{ + public: + TripletHistManager() = default; + ~TripletHistManager() = default; + + template + void init(o2::framework::HistogramRegistry* registry, + std::map> const& Specs, + T1 const& ConfTripletBinning, + T2 const& ConfTripletCuts) + { + mHistogramRegistry = registry; + + // flags for histograms + mPlot1d = ConfTripletBinning.plot1D.value; + mPlot2d = ConfTripletBinning.plot2D.value; + + // transverse mass type + mMtType = static_cast(ConfTripletBinning.transverseMassType.value); + + // values for cuts + mQ3Min = ConfTripletCuts.q3Min.value; + mQ3Max = ConfTripletCuts.q3Max.value; + mMtMin = ConfTripletCuts.mtMin.value; + mMtMax = ConfTripletCuts.mtMax.value; + + mPlotPt1VsPt2VsPt3 = ConfTripletBinning.plotPt1VsPt2VsPt3.value; + mPlotQ3VsPt1VsPt2VsPt3 = ConfTripletBinning.plotQ3VsPt1VsPt2VsPt3.value; + mPlotQ3VsMtVsMult = ConfTripletBinning.plotQ3VsMtVsMult.value; + mPlotQ3VsMtVsMultVsCent = ConfTripletBinning.plotQ3VsMtVsMultVsCent.value; + mPlotQ3VsMtVsPt1VsPt2VsPt3VsMult = ConfTripletBinning.plotQ3VsMtVsPt1VsPt2VsPt3VsMult.value; + mPlotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent = ConfTripletBinning.plotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent.value; + + if constexpr (isFlagSet(mode, modes::Mode::kAnalysis)) { + initAnalysis(Specs); + } + + if constexpr (isFlagSet(mode, modes::Mode::kMc)) { + initMc(Specs); + } + } + + void setMass(int PdgParticle1, int PdgParticle2, int PdgParticle3) + { + mPdgMass1 = utils::getPdgMass(PdgParticle1); + mPdgMass2 = utils::getPdgMass(PdgParticle2); + mPdgMass3 = utils::getPdgMass(PdgParticle3); + } + void setCharge(int chargeAbsParticle1, int chargeAbsParticle2, int chargeAbsParticle3) + { + // the pt stored is actually as pt/z for tracks, so in case of particles with z > 1, we have to rescale the pt (this is so far only for He3 the case) + mAbsCharge1 = std::abs(chargeAbsParticle1); + mAbsCharge2 = std::abs(chargeAbsParticle2); + mAbsCharge3 = std::abs(chargeAbsParticle3); + } + + template + void setTriplet(const T1& particle1, const T2& particle2, const T3& particle3) + { + // pt in track table is calculated from 1/signedPt from the original track table + // in case of He with Z=2, we have to rescale the pt with the absolute charge + mParticle1 = ROOT::Math::PtEtaPhiMVector(mAbsCharge1 * particle1.pt(), particle1.eta(), particle1.phi(), mPdgMass1); + mParticle2 = ROOT::Math::PtEtaPhiMVector(mAbsCharge2 * particle2.pt(), particle2.eta(), particle2.phi(), mPdgMass2); + mParticle3 = ROOT::Math::PtEtaPhiMVector(mAbsCharge3 * particle3.pt(), particle3.eta(), particle3.phi(), mPdgMass3); + + // set mT + mMt = getMt(mParticle1, mParticle2, mParticle3); + // set Q3 + mQ3 = getQ3(mParticle1, mParticle2, mParticle3); + + // if one of the particles has a mass getter, we cache the value for the filling later + if constexpr (utils::HasMass) { + mMass1 = particle1.mass(); + } + if constexpr (utils::HasMass) { + mMass2 = particle2.mass(); + } + if constexpr (utils::HasMass) { + mMass3 = particle3.mass(); + } + } + + template + void setTriplet(T1 const& particle1, T2 const& particle2, T3 const& particle3, T4 const& col) + { + setTriplet(particle1, particle2, particle3); + mMult = col.mult(); + mCent = col.cent(); + } + + template + void setTriplet(T1 const& particle1, T2 const& particle2, T3 const& particle3, T4 const& col1, T4 const& col2, T4 const& col3) + { + setTriplet(particle1, particle2, particle3); + mMult = (col1.mult() + col2.mult() + col3.mult()) / 3.f; // if mixing with multiplicity, should be in the same mixing bin + mCent = (col1.cent() + col2.cent() + col3.cent()) / 3.f; // if mixing with centrality, should be in the same mixing bin + } + + template + void setTripletMc(T1 const& particle1, T2 const& particle2, T3 const& particle3, const T4& /*mcParticles*/) + { + if (!particle1.has_fMcParticle() || !particle2.has_fMcParticle() || !particle3.has_fMcParticle()) { + mHasMcTriplet = false; + return; + } + mHasMcTriplet = true; + + auto mcParticle1 = particle1.template fMcParticle_as(); + auto mcParticle2 = particle2.template fMcParticle_as(); + auto mcParticle3 = particle3.template fMcParticle_as(); + + mTrueParticle1 = ROOT::Math::PtEtaPhiMVector(mAbsCharge1 * mcParticle1.pt(), mcParticle1.eta(), mcParticle1.phi(), mPdgMass1); + mTrueParticle2 = ROOT::Math::PtEtaPhiMVector(mAbsCharge2 * mcParticle2.pt(), mcParticle2.eta(), mcParticle2.phi(), mPdgMass2); + mTrueParticle3 = ROOT::Math::PtEtaPhiMVector(mAbsCharge3 * mcParticle3.pt(), mcParticle3.eta(), mcParticle3.phi(), mPdgMass3); + + // set true mT + mTrueMt = getMt(mTrueParticle1, mTrueParticle2, mTrueParticle3); + // set true Q3 + mTrueQ3 = getQ3(mTrueParticle1, mTrueParticle2, mTrueParticle3); + } + + template + void setTripletMc(T1 const& particle1, T2 const& particle2, T3 const& particle3, T4 const& mcParticles, T5 const& col, const T6& /*mcCols*/) + { + setTriplet(particle1, particle2, particle3, col); + setTripletMc(particle1, particle2, particle3, mcParticles); + if (!col.has_fMcCol()) { + mHasMcCol = false; + return; + } + mHasMcCol = true; + auto mcCol = col.template fMcCol_as(); + mTrueMult = mcCol.mult(); + mTrueCent = mcCol.cent(); + } + + template + void setTripletMc(T1 const& particle1, T2 const& particle2, T3 const& particle3, T4 const& mcParticles, T5 const& col1, T5 const& col2, T5 const& col3, const T6& /*mcCols*/) + { + setTriplet(particle1, particle2, particle3, col1, col2, col3); + setTripletMc(particle1, particle2, particle3, mcParticles); + if (!col1.has_fMcCol() || !col2.has_fMcCol() || !col2.has_fMcCol()) { + mHasMcCol = false; + return; + } + mHasMcCol = true; + auto mcCol1 = col1.template fMcCol_as(); + auto mcCol2 = col2.template fMcCol_as(); + auto mcCol3 = col2.template fMcCol_as(); + mTrueMult = (mcCol1.mult() + mcCol2.mult() + mcCol3.mult()) / 3.f; + mTrueCent = (mcCol1.cent() + mcCol2.cent() + mcCol3.cent()) / 3.f; + } + + bool checkTripletCuts() const + { + return (!(mQ3Min > 0.f) || mQ3 > mQ3Min) && + (!(mQ3Max > 0.f) || mQ3 < mQ3Max) && + (!(mMtMin > 0.f) || mMt > mMtMin) && + (!(mMtMax > 0.f) || mMt < mMtMax); + } + + template + void fill() + { + if constexpr (isFlagSet(mode, modes::Mode::kAnalysis)) { + fillAnalysis(); + } + if constexpr (isFlagSet(mode, modes::Mode::kMc)) { + fillMc(); + } + } + + float getQ3() const { return mQ3; } + + private: + ROOT::Math::PxPyPzEVector getqij(ROOT::Math::PtEtaPhiMVector const& pi, ROOT::Math::PtEtaPhiMVector const& pj) + { + // Convert to PxPyPzEVector to get proper Lorentz dot product + ROOT::Math::PxPyPzEVector vi(pi); + ROOT::Math::PxPyPzEVector vj(pj); + + auto trackSum = vi + vj; + auto trackDifference = vi - vj; + double scaling = trackDifference.Dot(trackSum) / trackSum.Dot(trackSum); + return trackDifference - scaling * trackSum; + } + + float getQ3(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2, ROOT::Math::PtEtaPhiMVector const& part3) + { + auto q12 = getqij(part1, part2); + auto q23 = getqij(part2, part3); + auto q31 = getqij(part3, part1); + double q = q12.M2() + q23.M2() + q31.M2(); + return static_cast(std::sqrt(-q)); + } + + void initAnalysis(std::map> const& Specs) + { + std::string analysisDir = std::string(prefix) + std::string(AnalysisDir); + if (mPlot1d) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3, HistTable), getHistDesc(kQ3, HistTable), getHistType(kQ3, HistTable), {Specs.at(kQ3)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kMt, HistTable), getHistDesc(kMt, HistTable), getHistType(kMt, HistTable), {Specs.at(kMt)}); + } + if (mPlot2d) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kPt1VsQ3, HistTable), getHistDesc(kPt1VsQ3, HistTable), getHistType(kPt1VsQ3, HistTable), {Specs.at(kPt1VsQ3)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kPt2VsQ3, HistTable), getHistDesc(kPt2VsQ3, HistTable), getHistType(kPt2VsQ3, HistTable), {Specs.at(kPt2VsQ3)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kPt3VsQ3, HistTable), getHistDesc(kPt3VsQ3, HistTable), getHistType(kPt3VsQ3, HistTable), {Specs.at(kPt3VsQ3)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsMt, HistTable), getHistDesc(kQ3VsMt, HistTable), getHistType(kQ3VsMt, HistTable), {Specs.at(kQ3VsMt)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsMult, HistTable), getHistDesc(kQ3VsMult, HistTable), getHistType(kQ3VsMult, HistTable), {Specs.at(kQ3VsMult)}); + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsCent, HistTable), getHistDesc(kQ3VsCent, HistTable), getHistType(kQ3VsCent, HistTable), {Specs.at(kQ3VsCent)}); + // TODO: implement histograms differential im mass of the particles + } + + if (mPlotPt1VsPt2VsPt3) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kPt1VsPt2VsPt3, HistTable), getHistDesc(kPt1VsPt2VsPt3, HistTable), getHistType(kPt1VsPt2VsPt3, HistTable), {Specs.at(kPt1VsPt2VsPt3)}); + } + if (mPlotQ3VsPt1VsPt2VsPt3) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsPt1VsPt2VsPt3, HistTable), getHistDesc(kQ3VsPt1VsPt2VsPt3, HistTable), getHistType(kQ3VsPt1VsPt2VsPt3, HistTable), {Specs.at(kQ3VsPt1VsPt2VsPt3)}); + } + if (mPlotQ3VsMtVsMult) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsMtVsMult, HistTable), getHistDesc(kQ3VsMtVsMult, HistTable), getHistType(kQ3VsMtVsMult, HistTable), {Specs.at(kQ3VsMtVsMult)}); + } + if (mPlotQ3VsMtVsMultVsCent) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsMtVsMultVsCent, HistTable), getHistDesc(kQ3VsMtVsMultVsCent, HistTable), getHistType(kQ3VsMtVsMultVsCent, HistTable), {Specs.at(kQ3VsMtVsMultVsCent)}); + } + if (mPlotQ3VsMtVsPt1VsPt2VsPt3VsMult) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsMtVsPt1VsPt2VsPt3VsMult, HistTable), getHistDesc(kQ3VsMtVsPt1VsPt2VsPt3VsMult, HistTable), getHistType(kQ3VsMtVsPt1VsPt2VsPt3VsMult, HistTable), {Specs.at(kQ3VsMtVsPt1VsPt2VsPt3VsMult)}); + } + if (mPlotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent) { + mHistogramRegistry->add(analysisDir + getHistNameV2(kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, HistTable), getHistDesc(kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, HistTable), getHistType(kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, HistTable), {Specs.at(kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent)}); + } + } + + void initMc(std::map> const& Specs) + { + std::string mcDir = std::string(prefix) + std::string(McDir); + mHistogramRegistry->add(mcDir + getHistNameV2(kTrueQ3VsQ3, HistTable), getHistDesc(kTrueQ3VsQ3, HistTable), getHistType(kTrueQ3VsQ3, HistTable), {Specs.at(kTrueQ3VsQ3)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kTrueMtVsMt, HistTable), getHistDesc(kTrueMtVsMt, HistTable), getHistType(kTrueMtVsMt, HistTable), {Specs.at(kTrueMtVsMt)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kTrueMultVsMult, HistTable), getHistDesc(kTrueMultVsMult, HistTable), getHistType(kTrueMultVsMult, HistTable), {Specs.at(kTrueMultVsMult)}); + mHistogramRegistry->add(mcDir + getHistNameV2(kTrueCentVsCent, HistTable), getHistDesc(kTrueCentVsCent, HistTable), getHistType(kTrueCentVsCent, HistTable), {Specs.at(kTrueCentVsCent)}); + } + + void fillAnalysis() + { + if (mPlot1d) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3, HistTable)), mQ3); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kMt, HistTable)), mMt); + } + if (mPlot2d) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kPt1VsQ3, HistTable)), mParticle1.Pt(), mQ3); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kPt2VsQ3, HistTable)), mParticle2.Pt(), mQ3); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kPt3VsQ3, HistTable)), mParticle3.Pt(), mQ3); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsMt, HistTable)), mQ3, mMt); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsMult, HistTable)), mQ3, mMult); + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsCent, HistTable)), mQ3, mCent); + } + + if (mPlotPt1VsPt2VsPt3) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kPt1VsPt2VsPt3, HistTable)), mParticle1.Pt(), mParticle2.Pt(), mParticle3.Pt()); + } + if (mPlotQ3VsPt1VsPt2VsPt3) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsPt1VsPt2VsPt3, HistTable)), mQ3, mParticle1.Pt(), mParticle2.Pt(), mParticle3.Pt()); + } + if (mPlotQ3VsMtVsMult) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsMtVsMult, HistTable)), mQ3, mMt, mMult); + } + if (mPlotQ3VsMtVsMultVsCent) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsMtVsMultVsCent, HistTable)), mQ3, mMt, mMult, mCent); + } + if (mPlotQ3VsMtVsPt1VsPt2VsPt3VsMult) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsMtVsPt1VsPt2VsPt3VsMult, HistTable)), mQ3, mMt, mParticle1.Pt(), mParticle2.Pt(), mParticle3.Pt(), mMult); + } + if (mPlotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent) { + mHistogramRegistry->fill(HIST(prefix) + HIST(AnalysisDir) + HIST(getHistName(kQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent, HistTable)), mQ3, mMt, mParticle1.Pt(), mParticle2.Pt(), mParticle3.Pt(), mMult, mCent); + } + } + + void fillMc() + { + if (mHasMcTriplet) { + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTrueQ3VsQ3, HistTable)), mTrueQ3, mQ3); + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTrueMtVsMt, HistTable)), mTrueMt, mMt); + } + if (mHasMcCol) { + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTrueMultVsMult, HistTable)), mTrueMult, mMult); + mHistogramRegistry->fill(HIST(prefix) + HIST(McDir) + HIST(getHistName(kTrueCentVsCent, HistTable)), mTrueCent, mCent); + } + } + + double getMt(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2) + { + auto sum = part1 + part2; + double mt = 0.; + double averageMass = 0.; + double reducedMass = 0.; + switch (mMtType) { + case modes::TransverseMassType::kAveragePdgMass: + averageMass = 0.5 * (part1.M() + part2.M()); + mt = std::hypot(0.5 * sum.Pt(), averageMass); + break; + case modes::TransverseMassType::kReducedPdgMass: + reducedMass = 2. * (part1.M() * part2.M() / (part1.M() + part2.M())); + mt = std::hypot(0.5 * sum.Pt(), reducedMass); + break; + case modes::TransverseMassType::kMt4Vector: + mt = 0.5 * sum.Mt(); + break; + default: + LOG(fatal) << "Invalid transverse mass type, breaking..."; + } + return mt; + } + + float getMt(ROOT::Math::PtEtaPhiMVector const& part1, ROOT::Math::PtEtaPhiMVector const& part2, ROOT::Math::PtEtaPhiMVector const& part3) + { + return static_cast((getMt(part1, part2) + getMt(part2, part3) + getMt(part1, part3)) / 3.); + } + + o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; + double mPdgMass1 = 0.; + double mPdgMass2 = 0.; + double mPdgMass3 = 0.; + + modes::TransverseMassType mMtType = modes::TransverseMassType::kAveragePdgMass; + + int mAbsCharge1 = 1; + int mAbsCharge2 = 1; + int mAbsCharge3 = 1; + ROOT::Math::PtEtaPhiMVector mParticle1{}; + ROOT::Math::PtEtaPhiMVector mParticle2{}; + ROOT::Math::PtEtaPhiMVector mParticle3{}; + float mMass1 = 0.f; + float mMass2 = 0.f; + float mMass3 = 0.f; + float mQ3 = 0.f; + float mMt = 0.f; + float mMult = 0.f; + float mCent = 0.f; + + // mc + ROOT::Math::PtEtaPhiMVector mTrueParticle1{}; + ROOT::Math::PtEtaPhiMVector mTrueParticle2{}; + ROOT::Math::PtEtaPhiMVector mTrueParticle3{}; + float mTrueQ3 = 0.f; + float mTrueMt = 0.f; + float mTrueMult = 0.f; + float mTrueCent = 0.f; + + // cuts + bool mHasMcTriplet = false; + bool mHasMcCol = false; + float mQ3Min = -1.f; + float mQ3Max = -1.f; + float mKtMin = -1.f; + float mKtMax = -1.f; + float mMtMin = -1.f; + float mMtMax = -1.f; + + // flags + bool mPlot1d = true; + bool mPlot2d = true; + + bool mPlotPt1VsPt2VsPt3 = false; + bool mPlotQ3VsPt1VsPt2VsPt3 = false; + bool mPlotQ3VsMtVsMult = false; + bool mPlotQ3VsMtVsMultVsCent = false; + bool mPlotQ3VsMtVsPt1VsPt2VsPt3VsMult = false; + bool mPlotQ3VsMtVsPt1VsPt2VsPt3VsMultVsCent = false; +}; + +}; // namespace triplethistmanager +}; // namespace o2::analysis::femto +#endif // PWGCF_FEMTO_CORE_TRIPLETHISTMANAGER_H_ diff --git a/PWGCF/Femto/Core/tripletProcessHelpers.h b/PWGCF/Femto/Core/tripletProcessHelpers.h new file mode 100644 index 00000000000..75538ae024d --- /dev/null +++ b/PWGCF/Femto/Core/tripletProcessHelpers.h @@ -0,0 +1,543 @@ +// Copyright 2019-2025 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 tripletProcessHelpers.h +/// \brief process functions used in pair tasks +/// \author anton.riedel@tum.de, TU München, anton.riedel@tum.de + +#ifndef PWGCF_FEMTO_CORE_TRIPLETPROCESSHELPERS_H_ +#define PWGCF_FEMTO_CORE_TRIPLETPROCESSHELPERS_H_ + +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include + +#include + +namespace o2::analysis::femto +{ +namespace tripletprocesshelpers +{ + +enum TripletOrder : uint8_t { + kOrder123, // no swap + kOrder213, // first two swap 1&2 so we can use them for the case that particle 1 & 2 are the same species, particle 3 is something else + kOrder132, // swap 2&3 + kOrder321, // swap 1&2&3 +}; + +// process same event for identical 3 particles +template +void processSameEvent(T1 const& SliceParticle, + T2 const& TrackTable, + T3 const& Collision, + T4& ParticleHistManager, + T5& TripletHistManager, + T6& CtrManager, + T7& TcManager, + TripletOrder tripletOrder) +{ + for (auto const& part : SliceParticle) { + ParticleHistManager.template fill(part, TrackTable); + } + + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle, SliceParticle, SliceParticle))) { + + // check if triplet is clean + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable)) { + continue; + } + + // check if triplet is close + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + + // Randomize pair order if enabled + switch (tripletOrder) { + case kOrder123: + TripletHistManager.setTriplet(p1, p2, p3, Collision); + break; + case kOrder213: + TripletHistManager.setTriplet(p2, p1, p3, Collision); + break; + case kOrder132: + TripletHistManager.setTriplet(p1, p3, p2, Collision); + break; + case kOrder321: + TripletHistManager.setTriplet(p3, p2, p1, Collision); + break; + default: + TripletHistManager.setTriplet(p1, p2, p3, Collision); + break; + } + + // fill deta-dphi histograms with !3 cutoff + CtrManager.fill(TripletHistManager.getQ3()); + + // if triplet cuts are configured check them before filling + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } +} + +// process same event for identical 2 particles and 1 other particle +template +void processSameEvent(T1 const& SliceParticle1, // 1&2 have same species + T2 const& SliceParticle3, + T3 const& TrackTable, + T4 const& Collision, + T5& ParticleHistManager1, + T6& ParticleHistManager3, + T7& TripletHistManager, + T8& CtrManager, + T9& TcManager, + TripletOrder triplerOrder) +{ + for (auto const& part : SliceParticle1) { + ParticleHistManager1.template fill(part, TrackTable); + } + for (auto const& part : SliceParticle3) { + ParticleHistManager3.template fill(part, TrackTable); + } + + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle1, SliceParticle1, SliceParticle3))) { + + // check if triplet is clean + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable)) { + continue; + } + + // check if triplet is close + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + + // Randomize triplet order if enabled + switch (triplerOrder) { + case kOrder123: + TripletHistManager.setTriplet(p1, p2, p3, Collision); + break; + case kOrder213: + TripletHistManager.setTriplet(p1, p2, p3, Collision); + break; + default: + TripletHistManager.setTriplet(p1, p2, p3, Collision); + break; + } + + // fill deta-dphi histograms with !3 cutoff + CtrManager.fill(TripletHistManager.getQ3()); + + // if triplet cuts are configured check them before filling + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } +} + +// process same event for 3 different particles +template +void processSameEvent(T1 const& SliceParticle1, + T2 const& SliceParticle2, + T3 const& SliceParticle3, + T4 const& TrackTable, + T5 const& Collision, + T6& ParticleHistManager1, + T7& ParticleHistManager2, + T8& ParticleHistManager3, + T9& TripletHistManager, + T10& CtrManager, + T11& TcManager) +{ + for (auto const& part : SliceParticle1) { + ParticleHistManager1.template fill(part, TrackTable); + } + for (auto const& part : SliceParticle2) { + ParticleHistManager2.template fill(part, TrackTable); + } + for (auto const& part : SliceParticle3) { + ParticleHistManager3.template fill(part, TrackTable); + } + + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle1, SliceParticle2, SliceParticle3))) { + + // check if triplet is clean + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable)) { + continue; + } + + // check if triplet is close + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + + TripletHistManager.setTriplet(p1, p2, p3, Collision); + + // fill deta-dphi histograms with !3 cutoff + CtrManager.fill(TripletHistManager.getQ3()); + + // if triplet cuts are configured check them before filling + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } +} + +// // process same event for 3 identical particles with mc information +template +void processSameEvent(T1 const& SliceParticle, + T2 const& TrackTable, + T3 const& mcParticles, + T4 const& mcMothers, + T5 const& mcPartonicMothers, + T6 const& Collision, + T7 const& mcCollisions, + T8& ParticleHistManager, + T9& TripletHistManager, + T10& CtrManager, + T11& TcManager, + int swapTriplet) +{ + for (auto const& part : SliceParticle) { + ParticleHistManager.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + } + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle, SliceParticle, SliceParticle))) { + // check if pair is clean + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable, mcPartonicMothers)) { + continue; + } + // check if pair is close + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + // Randomize pair order if enabled + // + switch (swapTriplet) { + case 3: + TripletHistManager.setTripletMc(p1, p3, p2, mcParticles, Collision, mcCollisions); + break; + case 2: + TripletHistManager.setTripletMc(p2, p1, p3, mcParticles, Collision, mcCollisions); + break; + case 1: + TripletHistManager.setTripletMc(p1, p2, p3, mcParticles, Collision, mcCollisions); + break; + default: + TripletHistManager.setTripletMc(p1, p2, p3, mcParticles, Collision, mcCollisions); + break; + } + // float threshold = 0.5f; + // fill deta-dphi histograms with q3 cutoff + CtrManager.fill(TripletHistManager.getQ3()); + // if pair cuts are configured check them before filling + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } +} + +// process same event for 2 identical particles and one other with mc information +template +void processSameEvent(T1 const& SliceParticle1, + T2 const& SliceParticle3, + T3 const& TrackTable, + T4 const& mcParticles, + T5 const& mcMothers, + T6 const& mcPartonicMothers, + T7 const& Collision, + T8 const& mcCollisions, + T9& ParticleHistManager1, + T10& ParticleHistManager3, + T11& TripletHistManager, + T12& CtrManager, + T13& TcManager, + int swapTriplet) +{ + for (auto const& part : SliceParticle1) { + ParticleHistManager1.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + } + for (auto const& part : SliceParticle3) { + ParticleHistManager3.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + } + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle1, SliceParticle1, SliceParticle3))) { + // check if pair is clean + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable, mcPartonicMothers)) { + continue; + } + // check if pair is close + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + // Randomize pair order if enabled + // + switch (swapTriplet) { + case 2: + TripletHistManager.setTripletMc(p2, p1, p3, mcParticles, Collision, mcCollisions); + break; + case 1: + TripletHistManager.setTripletMc(p1, p2, p3, mcParticles, Collision, mcCollisions); + break; + default: + TripletHistManager.setTripletMc(p1, p2, p3, mcParticles, Collision, mcCollisions); + break; + } + // fill deta-dphi histograms with q3 cutoff + CtrManager.fill(TripletHistManager.getQ3()); + // if pair cuts are configured check them before filling + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } +} + +// process same event for 3 different particles +template +void processSameEvent(T1 const& SliceParticle1, + T2 const& SliceParticle2, + T3 const& SliceParticle3, + T4 const& TrackTable, + T5 const& mcParticles, + T6 const& mcMothers, + T7 const& mcPartonicMothers, + T8 const& Collision, + T9 const& mcCollisions, + T10& ParticleHistManager1, + T11& ParticleHistManager2, + T12& ParticleHistManager3, + T13& TripletHistManager, + T14& CtrManager, + T15& TcManager) +{ + for (auto const& part : SliceParticle1) { + ParticleHistManager1.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + } + for (auto const& part : SliceParticle2) { + ParticleHistManager2.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + } + for (auto const& part : SliceParticle3) { + ParticleHistManager3.template fill(part, TrackTable, mcParticles, mcMothers, mcPartonicMothers); + } + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(SliceParticle1, SliceParticle2, SliceParticle3))) { + // check if pair is clean + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable, mcPartonicMothers)) { + continue; + } + // check if pair is close + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + TripletHistManager.setTripletMc(p1, p2, p3, mcParticles, Collision, mcCollisions); + // fill deta-dphi histograms with q3 cutoff + CtrManager.fill(TripletHistManager.getQ3()); + // if pair cuts are configured check them before filling + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } +} + +// process mixed event +template +void processMixedEvent(T1 const& Collisions, + T2& Partition1, + T3& Partition2, + T4& Partition3, + T5 const& TrackTable, + T6& cache, + T7 const& policy, + T8 const& depth, + T9& TripletHistManager, + T10& CtrManager, + T11& TcManager) +{ + for (auto const& [collision1, collision2, collision3] : o2::soa::selfCombinations(policy, depth, -1, Collisions, Collisions, Collisions)) { + if (collision1.magField() != collision2.magField() || + collision2.magField() != collision3.magField() || + collision1.magField() != collision3.magField()) { + continue; + } + CtrManager.setMagField(collision1.magField()); + auto sliceParticle1 = Partition1->sliceByCached(o2::aod::femtobase::stored::fColId, collision1.globalIndex(), cache); + auto sliceParticle2 = Partition2->sliceByCached(o2::aod::femtobase::stored::fColId, collision2.globalIndex(), cache); + auto sliceParticle3 = Partition3->sliceByCached(o2::aod::femtobase::stored::fColId, collision3.globalIndex(), cache); + if (sliceParticle1.size() == 0 || sliceParticle2.size() == 0 || sliceParticle3.size() == 0) { + continue; + } + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(sliceParticle1, sliceParticle2, sliceParticle3))) { + // pair cleaning + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable)) { + continue; + } + // Close pair rejection + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + TripletHistManager.setTriplet(p1, p2, p3, collision1, collision2, collision3); + CtrManager.fill(TripletHistManager.getQ3()); + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } + } +} + +// process mixed event in mc +template +void processMixedEvent(T1 const& Collisions, + T2 const& mcCollisions, + T3& Partition1, + T4& Partition2, + T5& Partition3, + T6 const& TrackTable, + T7 const& mcParticles, + T8& cache, + T9 const& policy, + T10 const& depth, + T11& TripletHistManager, + T12& CtrManager, + T13& TcManager) +{ + for (auto const& [collision1, collision2, collision3] : o2::soa::selfCombinations(policy, depth, -1, Collisions, Collisions, Collisions)) { + if (collision1.magField() != collision2.magField() || + collision2.magField() != collision3.magField() || + collision1.magField() != collision3.magField()) { + continue; + } + CtrManager.setMagField(collision1.magField()); + auto sliceParticle1 = Partition1->sliceByCached(o2::aod::femtobase::stored::fColId, collision1.globalIndex(), cache); + auto sliceParticle2 = Partition2->sliceByCached(o2::aod::femtobase::stored::fColId, collision2.globalIndex(), cache); + auto sliceParticle3 = Partition3->sliceByCached(o2::aod::femtobase::stored::fColId, collision3.globalIndex(), cache); + if (sliceParticle1.size() == 0 || sliceParticle2.size() == 0 || sliceParticle3.size() == 0) { + continue; + } + for (auto const& [p1, p2, p3] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(sliceParticle1, sliceParticle2, sliceParticle3))) { + // pair cleaning + if (!TcManager.isCleanTriplet(p1, p2, p3, TrackTable)) { + continue; + } + // Close pair rejection + CtrManager.setTriplet(p1, p2, p3, TrackTable); + if (CtrManager.isCloseTriplet()) { + continue; + } + TripletHistManager.setTripletMc(p1, p2, p3, mcParticles, collision1, collision2, collision3, mcCollisions); + CtrManager.fill(TripletHistManager.getQ3()); + if (TripletHistManager.checkTripletCuts()) { + TripletHistManager.template fill(); + } + } + } +} + +} // namespace tripletprocesshelpers +} // namespace o2::analysis::femto + +#endif // PWGCF_FEMTO_CORE_TRIPLETPROCESSHELPERS_H_ diff --git a/PWGCF/Femto/Core/twoTrackResonanceBuilder.h b/PWGCF/Femto/Core/twoTrackResonanceBuilder.h index 9183527b890..3a5aca2c5e6 100644 --- a/PWGCF/Femto/Core/twoTrackResonanceBuilder.h +++ b/PWGCF/Femto/Core/twoTrackResonanceBuilder.h @@ -16,8 +16,6 @@ #ifndef PWGCF_FEMTO_CORE_TWOTRACKRESONANCEBUILDER_H_ #define PWGCF_FEMTO_CORE_TWOTRACKRESONANCEBUILDER_H_ -#include "RecoDecay.h" - #include "PWGCF/Femto/Core/baseSelection.h" #include "PWGCF/Femto/Core/dataTypes.h" #include "PWGCF/Femto/Core/femtoUtils.h" @@ -25,15 +23,18 @@ #include "PWGCF/Femto/Core/selectionContainer.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" +#include -#include +#include +#include +#include +#include +#include +#include +#include -#include "fairlogger/Logger.h" +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include diff --git a/PWGCF/Femto/Core/twoTrackResonanceHistManager.h b/PWGCF/Femto/Core/twoTrackResonanceHistManager.h index 848dd69f521..de5317ff34c 100644 --- a/PWGCF/Femto/Core/twoTrackResonanceHistManager.h +++ b/PWGCF/Femto/Core/twoTrackResonanceHistManager.h @@ -20,10 +20,14 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/trackHistManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include +#include +#include +#include + +#include #include #include @@ -86,9 +90,9 @@ constexpr std::array, kTwoTrackReso {kPtVsMass, o2::framework::kTH2F, "hPtVsMass", "p_{T} vs invariant mass; p_{T} (GeV/#it{c}); m (GeV/#it{c}^{2})"}}}; template -std::map> makeTwoTrackResonanceHistSpecMap(const T& confBinningAnalysis) +std::map> makeTwoTrackResonanceHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ {kPt, {confBinningAnalysis.pt}}, {kEta, {confBinningAnalysis.eta}}, {kPhi, {confBinningAnalysis.phi}}, @@ -99,7 +103,7 @@ std::map> makeTwoTrackRe template auto makeTwoTrackResonanceQaHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ {kPt, {confBinningAnalysis.pt}}, {kEta, {confBinningAnalysis.eta}}, {kPhi, {confBinningAnalysis.phi}}, @@ -115,7 +119,7 @@ constexpr char PrefixRho[] = "Rho0/"; constexpr char PrefixPhi[] = "Phi/"; constexpr char PrefixKstar[] = "Kstar0/"; -constexpr std::string_view AnalysisDir = "Kinematics/"; +constexpr std::string_view AnalysisDir = "Analysis/"; constexpr std::string_view QaDir = "QA/"; template +#include +#include +#include +#include #include #include @@ -388,13 +388,14 @@ class V0Builder if (!mV0Selection.passesAllRequiredSelections()) { continue; } + + collisionBuilder.template fillCollision(collisionProducts, col); + // cleaner, but without ITS pid: auto posDaughter = v0.template posTrack_as(); auto posDaughter = tracksWithItsPid.iteratorAt(v0.posTrackId() - tracksWithItsPid.offset()); // cleaner, but without ITS pid: auto negDaughter = v0.template negTrack_as(); auto negDaughter = tracksWithItsPid.iteratorAt(v0.negTrackId() - tracksWithItsPid.offset()); - collisionBuilder.template fillCollision(collisionProducts, col); - posDaughterIndex = trackBuilder.template getDaughterIndex(posDaughter, trackProducts, collisionProducts); negDaughterIndex = trackBuilder.template getDaughterIndex(negDaughter, trackProducts, collisionProducts); @@ -554,10 +555,14 @@ class V0BuilderDerivedToDerived { mLimitLambda = config.limitLambda.value; mLimitK0short = config.limitK0short.value; + + if (mLimitLambda == 0 && mLimitK0short == 0) { + LOG(fatal) << "Both lambda limit and k0short limit are 0. Breaking..."; + } } template - bool collisionHasTooFewLambdas(T1& col, T2& /*lambdaTable*/, T3& partitionLambda, T4& cache) + bool collisionHasTooFewLambdas(T1 const& col, T2 const& /*lambdaTable*/, T3& partitionLambda, T4& cache) { auto lambdaSlice = partitionLambda->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); if (lambdaSlice.size() >= mLimitLambda) { @@ -567,7 +572,7 @@ class V0BuilderDerivedToDerived } template - bool collisionHasTooFewK0shorts(T1& col, T2& /*k0shortTable*/, T3& partitionK0short, T4& cache) + bool collisionHasTooFewK0shorts(T1 const& col, T2 const& /*k0shortTable*/, T3& partitionK0short, T4& cache) { auto k0shortSlice = partitionK0short->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); if (k0shortSlice.size() >= mLimitK0short) { @@ -577,14 +582,16 @@ class V0BuilderDerivedToDerived } template - void processLambdas(T1& col, T2& /*lambdaTable*/, T3& /*oldTrackTable*/, T4& partitionLambda, T5& trackBuilder, T6& cache, T7& newLambdaTable, T8& newTrackTable, T9& newCollisionTable) + void processLambdas(T1 const& col, T2 const& /*lambdaTable*/, T3 const& oldTrackTable, T4& partitionLambda, T5& trackBuilder, T6& cache, T7& newLambdaTable, T8& newTrackTable, T9& newCollisionTable) { auto lambdaSlice = partitionLambda->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& lambda : lambdaSlice) { - auto posDaughter = lambda.template posDau_as(); - auto negDaughter = lambda.template negDau_as(); + // auto posDaughter = lambda.template posDau_as(); + // auto negDaughter = lambda.template negDau_as(); + auto posDaughter = oldTrackTable.rawIteratorAt(lambda.posDauId() - oldTrackTable.offset()); + auto negDaughter = oldTrackTable.rawIteratorAt(lambda.negDauId() - oldTrackTable.offset()); int posDaughterIndex = trackBuilder.getDaughterIndex(posDaughter, newTrackTable, newCollisionTable); int negDaughterIndex = trackBuilder.getDaughterIndex(negDaughter, newTrackTable, newCollisionTable); @@ -601,14 +608,16 @@ class V0BuilderDerivedToDerived } template - void processK0shorts(T1& col, T2& /*k0shortTable*/, T3& /*oldTrackTable*/, T4& partitionK0short, T5& trackBuilder, T6& cache, T7& newK0shortTable, T8& newTrackTable, T9& newCollisionTable) + void processK0shorts(T1 const& col, T2 const& /*k0shortTable*/, T3 const& oldTrackTable, T4& partitionK0short, T5& trackBuilder, T6& cache, T7& newK0shortTable, T8& newTrackTable, T9& newCollisionTable) { auto k0shortSlice = partitionK0short->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& k0short : k0shortSlice) { - auto posDaughter = k0short.template posDau_as(); - auto negDaughter = k0short.template negDau_as(); + // auto posDaughter = k0short.template posDau_as(); + // auto negDaughter = k0short.template negDau_as(); + auto posDaughter = oldTrackTable.rawIteratorAt(k0short.posDauId() - oldTrackTable.offset()); + auto negDaughter = oldTrackTable.rawIteratorAt(k0short.negDauId() - oldTrackTable.offset()); int posDaughterIndex = trackBuilder.getDaughterIndex(posDaughter, newTrackTable, newCollisionTable); int negDaughterIndex = trackBuilder.getDaughterIndex(negDaughter, newTrackTable, newCollisionTable); diff --git a/PWGCF/Femto/Core/v0HistManager.h b/PWGCF/Femto/Core/v0HistManager.h index b79972437ef..b6cb832579f 100644 --- a/PWGCF/Femto/Core/v0HistManager.h +++ b/PWGCF/Femto/Core/v0HistManager.h @@ -20,12 +20,17 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/trackHistManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" +#include +#include +#include +#include +#include + +#include +#include #include +#include #include #include #include @@ -232,30 +237,30 @@ constexpr std::array, kV0HistLast> HistTable = { template auto makeV0HistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ V0_HIST_ANALYSIS_MAP(confBinningAnalysis)}; } template auto makeV0McHistSpecMap(const T& confBinningAnalysis) { - return std::map>{ + return std::map>{ V0_HIST_ANALYSIS_MAP(confBinningAnalysis) V0_HIST_MC_MAP(confBinningAnalysis)}; } template -std::map> makeV0QaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) +std::map> makeV0QaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ + return std::map>{ V0_HIST_ANALYSIS_MAP(confBinningAnalysis) V0_HIST_QA_MAP(confBinningAnalysis, confBinningQa)}; } template -std::map> makeV0McQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) +std::map> makeV0McQaHistSpecMap(T1 const& confBinningAnalysis, T2 const& confBinningQa) { - return std::map>{ + return std::map>{ V0_HIST_ANALYSIS_MAP(confBinningAnalysis) V0_HIST_QA_MAP(confBinningAnalysis, confBinningQa) V0_HIST_MC_MAP(confBinningAnalysis) @@ -276,7 +281,7 @@ constexpr char PrefixK0short2[] = "K0short2/"; constexpr char PrefixLambdaCascade[] = "LambdaCascadeQa/"; -constexpr std::string_view AnalysisDir = "Kinematics/"; +constexpr std::string_view AnalysisDir = "Analysis/"; constexpr std::string_view QaDir = "QA/"; constexpr std::string_view McDir = "MC/"; @@ -486,7 +491,7 @@ class V0HistManager mHistogramRegistry->add(mcDir + getHistNameV2(kTruePhiVsPhi, HistTable), getHistDesc(kTruePhiVsPhi, HistTable), getHistType(kTruePhiVsPhi, HistTable), {V0Specs.at(kTruePhiVsPhi)}); // mc origin can be configured here - const framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; + const o2::framework::AxisSpec axisOrigin = {static_cast(modes::McOrigin::kMcOriginLast), -0.5, static_cast(modes::McOrigin::kMcOriginLast) - 0.5}; mHistogramRegistry->add(mcDir + getHistNameV2(kOrigin, HistTable), getHistDesc(kOrigin, HistTable), getHistType(kOrigin, HistTable), {axisOrigin}); mHistogramRegistry->get(HIST(v0Prefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kNoMcParticle), modes::mcOriginToString(modes::McOrigin::kNoMcParticle)); mHistogramRegistry->get(HIST(v0Prefix) + HIST(McDir) + HIST(histmanager::getHistName(kOrigin, HistTable)))->GetXaxis()->SetBinLabel(1 + static_cast(modes::McOrigin::kFromWrongCollision), modes::mcOriginToString(modes::McOrigin::kFromWrongCollision)); @@ -679,10 +684,11 @@ class V0HistManager o2::framework::HistogramRegistry* mHistogramRegistry = nullptr; int mPdgCode = 0; - bool mPlot2d = false; bool mPlotOrigins = false; int mPlotNSecondaries = 0; std::array mPdgCodesSecondaryMother = {0}; + bool mPlot2d = false; + trackhistmanager::TrackHistManager mPosDauManager; trackhistmanager::TrackHistManager mNegDauManager; }; diff --git a/PWGCF/Femto/DataModel/FemtoTables.h b/PWGCF/Femto/DataModel/FemtoTables.h index 9f742edf96c..080e014ba30 100644 --- a/PWGCF/Femto/DataModel/FemtoTables.h +++ b/PWGCF/Femto/DataModel/FemtoTables.h @@ -18,13 +18,13 @@ #include "PWGCF/Femto/Core/dataTypes.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" +#include +#include +#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/Expressions.h" +#include +#include +#include #include #include @@ -58,7 +58,7 @@ using FCol = FCols::iterator; using StoredFCols = StoredFCols_001; // table for collisions selections -DECLARE_SOA_TABLE_STAGED_VERSIONED(FColMasks_001, "FCOLMASK", 1, //! track masks +DECLARE_SOA_TABLE_STAGED_VERSIONED(FColMasks_001, "FCOLMASK", 1, //! collision masks femtocollisions::Mask); using FColMasks = FColMasks_001; using StoredFColMasks = StoredFColMasks_001; @@ -106,7 +106,6 @@ DECLARE_SOA_COLUMN(Pt, pt, float); //! pt DECLARE_SOA_COLUMN(Eta, eta, float); //! eta DECLARE_SOA_COLUMN(Phi, phi, float); //! phi DECLARE_SOA_COLUMN(Mass, mass, float); //! mass of particle -DECLARE_SOA_COLUMN(MassAnti, massAnti, float); //! mass of antiparticle } // namespace stored namespace dynamic @@ -175,7 +174,7 @@ DECLARE_SOA_COLUMN(TpcChi2NCl, tpcChi2NCl, float); //! Tpc chi2 // tof related information DECLARE_SOA_COLUMN(TofBeta, tofBeta, float); //! Tof beta -DECLARE_SOA_COLUMN(TofMass, tofMass, float); //! Tof mass +// tof mass will be stored in mass column // PID information // ITS PID information @@ -247,6 +246,11 @@ DECLARE_SOA_TABLE_STAGED_VERSIONED(FTrackMasks_001, "FTRACKMASK", 1, //! track m using FTrackMasks = FTrackMasks_001; using StoredFTrackMasks = StoredFTrackMasks_001; +// table for track mass (using tof mass +DECLARE_SOA_TABLE_STAGED_VERSIONED(FTrackMass_001, "FTRACKMASS", 1, //! track mass + femtobase::stored::Mass); +using FTrackMass = FTrackMass_001; + // table for track DCA DECLARE_SOA_TABLE_STAGED_VERSIONED(FTrackDcas_001, "FTRACKDCAS", 1, //! track dcas femtotracks::DcaXY, @@ -267,7 +271,6 @@ DECLARE_SOA_TABLE_STAGED_VERSIONED(FTrackExtras_001, "FTRACKEXTRA", 1, //! track femtotracks::TpcNClsCrossedRows, femtotracks::TpcNClsShared, femtotracks::TofBeta, - femtotracks::TofMass, femtotracks::TpcCrossedRowsOverFound, femtotracks::TpcSharedOverFound); using FTrackExtras = FTrackExtras_001; @@ -401,9 +404,10 @@ namespace femtov0s DECLARE_SOA_COLUMN(Mask, mask, femtodatatypes::V0MaskType); //! Bitmask for v0 selections // columns for debug information -DECLARE_SOA_COLUMN(MassLambda, massLambda, float); //! Mass of Lambda -DECLARE_SOA_COLUMN(MassAntiLambda, massAntiLambda, float); //! Mass of AntiLambda -DECLARE_SOA_COLUMN(MassK0short, massK0short, float); //! Mass of K0short +DECLARE_SOA_COLUMN(MassAnti, massAnti, float); //! mass of particle using antiparticle hypothesis (for Lambda/AntiLambda extra table) +DECLARE_SOA_COLUMN(MassLambda, massLambda, float); //! Mass of Lambda (for k0short table) +DECLARE_SOA_COLUMN(MassAntiLambda, massAntiLambda, float); //! Mass of AntiLambda (for k0short table) +DECLARE_SOA_COLUMN(MassK0short, massK0short, float); //! Mass of K0short (for lambda/antitlambda table) DECLARE_SOA_COLUMN(CosPa, cosPa, float); //! Lambda daughter DCA at decay vertex DECLARE_SOA_COLUMN(DauDca, dauDca, float); //! Lambda daughter DCA at decay vertex DECLARE_SOA_COLUMN(TransRadius, transRadius, float); //! Lambda transvers radius @@ -447,7 +451,7 @@ using FLambdaMasks = FLambdaMasks_001; using StoredFLambdaMasks = StoredFLambdaMasks_001; DECLARE_SOA_TABLE_STAGED_VERSIONED(FLambdaExtras_001, "FLAMBDAEXTRA", 1, //! lambda extra information - femtobase::stored::MassAnti, // put mass of antiparticle, i.e. antilambda mass for lambdas and vice versa + femtov0s::MassAnti, // put mass of antiparticle, i.e. antilambda mass for lambdas and vice versa femtov0s::MassK0short, femtov0s::CosPa, femtov0s::DauDca, @@ -529,7 +533,24 @@ DECLARE_SOA_TABLE_STAGED_VERSIONED(FSigmas_001, "FSIGMA", 1, femtobase::dynamic::Py, femtobase::dynamic::Pz, femtobase::dynamic::Theta); -using FSigmas = FSigmas_001; + +// table for basic sigma information +DECLARE_SOA_TABLE_STAGED_VERSIONED(FSigmas_002, "FSIGMA", 2, + o2::soa::Index<>, + femtobase::stored::FColId, // use sign to differentiate between sigma minus (-1) and anti sigma minus (+1) + femtobase::stored::SignedPt, + femtobase::stored::Eta, + femtobase::stored::Phi, + femtobase::stored::Mass, + femtokinks::ChaDauId, + femtobase::dynamic::Sign, + femtobase::dynamic::Pt, + femtobase::dynamic::P, + femtobase::dynamic::Px, + femtobase::dynamic::Py, + femtobase::dynamic::Pz, + femtobase::dynamic::Theta); +using FSigmas = FSigmas_002; DECLARE_SOA_TABLE_STAGED_VERSIONED(FSigmaMasks_001, "FSIGMAMASKS", 1, femtokinks::Mask); @@ -760,5 +781,15 @@ DECLARE_SOA_TABLE(FSigmaPlusLabels, "AOD", "FSIGMAPLUSLABEL", femtolabels::FMcMotherId, femtolabels::FMcPartMothId); +DECLARE_SOA_TABLE(FXiLabels, "AOD", "FXILABEL", + femtolabels::FMcParticleId, + femtolabels::FMcMotherId, + femtolabels::FMcPartMothId); + +DECLARE_SOA_TABLE(FOmegaLabels, "AOD", "FOMEGALABEL", + femtolabels::FMcParticleId, + femtolabels::FMcMotherId, + femtolabels::FMcPartMothId); + } // namespace o2::aod #endif // PWGCF_FEMTO_DATAMODEL_FEMTOTABLES_H_ diff --git a/PWGCF/Femto/Macros/cutculator.py b/PWGCF/Femto/Macros/cutculator.py index 9e1d771b6da..34f9b2054c3 100755 --- a/PWGCF/Femto/Macros/cutculator.py +++ b/PWGCF/Femto/Macros/cutculator.py @@ -49,12 +49,20 @@ def ask_user_selection(group): Prompt user to select bin(s) for this selection group. - If minimal selections contain exactly 1 entry → auto-select it. - Optional selections remain user-selectable. + - Neither minimal nor optional selections are shown with a warning — useful for rejection masks. """ selection_name = group[0].get("SelectionName", "unknown") - # Separate minimal and optional bins + # Separate bins by type minimal_bins = [b for b in group if b.get("MinimalCut", "0") == "1" and b.get("OptionalCut", "0") == "0"] optional_bins = [b for b in group if b.get("OptionalCut", "0") == "1"] + neutral_bins = [ + b + for b in group + if b.get("MinimalCut", "0") == "0" + and b.get("OptionalCut", "0") == "0" + and b.get("BitPosition", "X").upper() != "X" + ] selected_bins = [] @@ -107,7 +115,34 @@ def ask_user_selection(group): b = optional_bins[i - 1] selected_bins.append(b) chosen.append(format_value_with_comment(b)) + print("Selected: " + ", ".join(chosen)) + break + except ValueError: + pass + + print("Invalid input. Please enter valid indices separated by space.") + # ----- Neither minimal nor optional----- + if neutral_bins: + print(f"\nSelection: {selection_name} (Neither minimal nor optional, 0 to skip)") + for idx, b in enumerate(neutral_bins, start=1): + print(f" [{idx}] {format_value_with_comment(b)}") + + while True: + sel_input = input("Enter indices separated by space (0 to skip): ") + if not sel_input.strip() or sel_input.strip() == "0": + print("Selected: (skipped)") + break + + try: + indices = [int(x) for x in sel_input.split()] + if all(0 <= i <= len(neutral_bins) for i in indices): + chosen = [] + for i in indices: + if i != 0: + b = neutral_bins[i - 1] + selected_bins.append(b) + chosen.append(format_value_with_comment(b)) print("Selected: " + ", ".join(chosen)) break except ValueError: diff --git a/PWGCF/Femto/Macros/cutculatorGui.py b/PWGCF/Femto/Macros/cutculatorGui.py new file mode 100755 index 00000000000..db776251e77 --- /dev/null +++ b/PWGCF/Femto/Macros/cutculatorGui.py @@ -0,0 +1,437 @@ +#!/usr/bin/env python3 + +# Copyright 2019-2025 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 CutCulator GUI (Compute bitmask for selecting particles in the Femto Framework) +@author Anton Riedel , Technical University of Munich +""" + +import tkinter as tk +from tkinter import ttk, filedialog, messagebox +import argparse +import sys + +try: + import ROOT + + ROOT.gROOT.SetBatch(True) +except ImportError: + ROOT = None + +VALUE_DELIM = "___" +SECTION_DELIM = ":::" + +# ── Colours ────────────────────────────────────────────────────────────────── +BG = "#1e1e2e" +BG_CARD = "#2a2a3e" +BG_HOVER = "#3a3a50" +ACCENT = "#89b4fa" # blue – minimal +ACCENT_OPT = "#a6e3a1" # green – optional +ACCENT_REJ = "#f38ba8" # red – rejection / neutral +FG = "#cdd6f4" +FG_DIM = "#6c7086" +BORDER = "#45475a" +SEL_BG = "#313244" + +FONT_TITLE = ("Inter", 15, "bold") +FONT_HEAD = ("Inter", 11, "bold") +FONT_BODY = ("Inter", 10) +FONT_MONO = ("JetBrains Mono", 11, "bold") +FONT_SMALL = ("Inter", 9) + + +# ── Helpers ─────────────────────────────────────────────────────────────────── +def parse_bin_label(label): + result = {} + for sec in label.split(SECTION_DELIM): + if VALUE_DELIM in sec: + k, v = sec.split(VALUE_DELIM, 1) + result[k.strip()] = v.strip() + return result + + +def format_value_with_comment(b): + val = b.get("Value", "") + comment = b.get("Comment", "") + if comment and comment.upper() != "X": + return f"{val} ({comment})" + return val + + +def bin_type(b): + """Return 'minimal', 'optional', 'neutral', or 'skip'.""" + is_min = b.get("MinimalCut", "0") == "1" + is_opt = b.get("OptionalCut", "0") == "1" + pos = b.get("BitPosition", "X") + if pos.upper() == "X": + return "skip" + if is_min and not is_opt: + return "minimal" + if is_opt: + return "optional" + return "neutral" + + +def load_bins_from_hist(hist): + nbins = hist.GetNbinsX() + bins = [] + for i in range(1, nbins - 2 + 1): + label = hist.GetXaxis().GetBinLabel(i) + if not label: + continue + b = parse_bin_label(label) + b["_bin_index"] = i + bins.append(b) + # group by SelectionName preserving order + groups = {} + for b in bins: + name = b.get("SelectionName", f"unknown_{b['_bin_index']}") + groups.setdefault(name, []).append(b) + return groups + + +# ── Main Application ────────────────────────────────────────────────────────── +class CutCulatorApp(tk.Tk): + def __init__(self, rootfile=None, tdir="femto-producer"): + super().__init__() + self.title("CutCulator") + self.configure(bg=BG) + self.geometry("920x720") + self.minsize(780, 560) + self.resizable(True, True) + + self._rootfile_path = rootfile + self._tdir_path = tdir + self._root_file = None + self._hist = None + self._groups = {} # SelectionName → list[bin_dict] + self._vars = {} # (SelectionName, idx) → BooleanVar + + self._build_ui() + + if rootfile: + self._load_file(rootfile) + + # ── UI skeleton ────────────────────────────────────────────────────────── + def _build_ui(self): + # ── top bar ── + top = tk.Frame(self, bg=BG, pady=10, padx=18) + top.pack(fill="x") + + tk.Label(top, text="✂ CutCulator", font=FONT_TITLE, bg=BG, fg=ACCENT).pack(side="left") + + btn_frame = tk.Frame(top, bg=BG) + btn_frame.pack(side="right") + self._btn_open = self._make_button(btn_frame, "📂 Open ROOT file", self._open_file_dialog, ACCENT) + self._btn_open.pack(side="left", padx=4) + + # ── file + histogram selector bar ── + bar = tk.Frame(self, bg=BG_CARD, pady=8, padx=18) + bar.pack(fill="x") + + tk.Label(bar, text="File:", font=FONT_BODY, bg=BG_CARD, fg=FG_DIM).pack(side="left") + self._lbl_file = tk.Label(bar, text="(none)", font=FONT_BODY, bg=BG_CARD, fg=FG, wraplength=400, anchor="w") + self._lbl_file.pack(side="left", padx=6) + + tk.Label(bar, text="Histogram:", font=FONT_BODY, bg=BG_CARD, fg=FG_DIM).pack(side="left", padx=(20, 0)) + self._hist_var = tk.StringVar() + self._hist_combo = ttk.Combobox(bar, textvariable=self._hist_var, state="disabled", width=30, font=FONT_BODY) + self._hist_combo.pack(side="left", padx=6) + self._hist_combo.bind("<>", self._on_hist_selected) + + self._style_combobox() + + # ── legend ── + legend = tk.Frame(self, bg=BG, pady=4, padx=18) + legend.pack(fill="x") + for color, label in [(ACCENT, "Minimal"), (ACCENT_OPT, "Optional"), (ACCENT_REJ, "Neutral")]: + dot = tk.Label(legend, text="●", font=FONT_BODY, bg=BG, fg=color) + dot.pack(side="left") + tk.Label(legend, text=label, font=FONT_SMALL, bg=BG, fg=FG_DIM).pack(side="left", padx=(2, 12)) + + # ── scrollable selection area ── + outer = tk.Frame(self, bg=BG) + outer.pack(fill="both", expand=True, padx=12, pady=4) + + self._canvas = tk.Canvas(outer, bg=BG, highlightthickness=0, bd=0) + vsb = ttk.Scrollbar(outer, orient="vertical", command=self._canvas.yview) + self._canvas.configure(yscrollcommand=vsb.set) + vsb.pack(side="right", fill="y") + self._canvas.pack(side="left", fill="both", expand=True) + + self._inner = tk.Frame(self._canvas, bg=BG) + self._canvas_win = self._canvas.create_window((0, 0), window=self._inner, anchor="nw") + self._inner.bind("", self._on_inner_configure) + self._canvas.bind("", self._on_canvas_configure) + self._canvas.bind_all("", self._on_mousewheel) + self._canvas.bind_all("", self._on_mousewheel) + self._canvas.bind_all("", self._on_mousewheel) + + # ── bottom result bar ── + bottom = tk.Frame(self, bg=BG_CARD, pady=10, padx=18) + bottom.pack(fill="x", side="bottom") + + tk.Label(bottom, text="Bitmask:", font=FONT_HEAD, bg=BG_CARD, fg=FG).pack(side="left") + + self._lbl_dec = tk.Label(bottom, text="—", font=FONT_MONO, bg=BG_CARD, fg=ACCENT, width=14, anchor="w") + self._lbl_dec.pack(side="left", padx=8) + + self._lbl_hex = tk.Label(bottom, text="—", font=FONT_MONO, bg=BG_CARD, fg=ACCENT_OPT, width=14, anchor="w") + self._lbl_hex.pack(side="left", padx=8) + + self._lbl_bin = tk.Label(bottom, text="—", font=FONT_MONO, bg=BG_CARD, fg=FG_DIM, anchor="w") + self._lbl_bin.pack(side="left", padx=8) + + copy_frame = tk.Frame(bottom, bg=BG_CARD) + copy_frame.pack(side="right") + self._make_button(copy_frame, "Copy Dec", lambda: self._copy(self._lbl_dec["text"]), ACCENT).pack( + side="left", padx=3 + ) + self._make_button(copy_frame, "Copy Hex", lambda: self._copy(self._lbl_hex["text"]), ACCENT_OPT).pack( + side="left", padx=3 + ) + + # ── Combobox styling ────────────────────────────────────────────────────── + def _style_combobox(self): + s = ttk.Style(self) + s.theme_use("clam") + s.configure( + "TCombobox", + fieldbackground=BG_CARD, + background=BG_CARD, + foreground=FG, + selectbackground=SEL_BG, + selectforeground=FG, + bordercolor=BORDER, + arrowcolor=ACCENT, + ) + s.map("TCombobox", fieldbackground=[("readonly", BG_CARD)]) + s.configure("TScrollbar", troughcolor=BG, background=BORDER) + + # ── Canvas resize helpers ───────────────────────────────────────────────── + def _on_inner_configure(self, _e=None): + self._canvas.configure(scrollregion=self._canvas.bbox("all")) + + def _on_canvas_configure(self, e): + self._canvas.itemconfig(self._canvas_win, width=e.width) + + def _on_mousewheel(self, e): + if e.num == 4: + self._canvas.yview_scroll(-1, "units") + elif e.num == 5: + self._canvas.yview_scroll(1, "units") + else: + self._canvas.yview_scroll(int(-1 * (e.delta / 120)), "units") + + # ── File / histogram loading ────────────────────────────────────────────── + def _open_file_dialog(self): + path = filedialog.askopenfilename( + title="Open ROOT file", filetypes=[("ROOT files", "*.root"), ("All files", "*.*")] + ) + if path: + self._load_file(path) + + def _load_file(self, path): + if ROOT is None: + messagebox.showerror("Missing dependency", "PyROOT is not available. Please install ROOT.") + return + f = ROOT.TFile.Open(path) + if not f or f.IsZombie(): + messagebox.showerror("Error", f"Cannot open ROOT file:\n{path}") + return + self._root_file = f + self._lbl_file.config(text=path) + + d = f.Get(self._tdir_path) + if not d: + messagebox.showerror("Error", f"Directory '{self._tdir_path}' not found in file.") + return + + histograms = [k.GetName() for k in d.GetListOfKeys() if k.ReadObj().InheritsFrom("TH1")] + if not histograms: + messagebox.showwarning("Warning", "No TH1 histograms found in directory.") + return + + self._hist_combo.config(values=histograms, state="readonly") + self._hist_combo.current(0) + self._on_hist_selected() + + def _on_hist_selected(self, _e=None): + if self._root_file is None: + return + d = self._root_file.Get(self._tdir_path) + if not d: + return + hname = self._hist_var.get() + hist = d.Get(hname) + if not hist: + return + self._hist = hist + self._groups = load_bins_from_hist(hist) + self._vars = {} + self._build_selections() + self._update_bitmask() + + # ── Selection cards ─────────────────────────────────────────────────────── + def _build_selections(self): + for w in self._inner.winfo_children(): + w.destroy() + + for sel_name, group in self._groups.items(): + self._build_group_card(sel_name, group) + + self._on_inner_configure() + + def _build_group_card(self, sel_name, group): + # categorise + minimal = [(i, b) for i, b in enumerate(group) if bin_type(b) == "minimal"] + optional = [(i, b) for i, b in enumerate(group) if bin_type(b) == "optional"] + neutral = [(i, b) for i, b in enumerate(group) if bin_type(b) == "neutral"] + + if not (minimal or optional or neutral): + return # nothing to show (all "skip") + + card = tk.Frame(self._inner, bg=BG_CARD, bd=0, highlightthickness=1, highlightbackground=BORDER) + card.pack(fill="x", padx=10, pady=5, ipadx=8, ipady=6) + + # header row + hdr = tk.Frame(card, bg=BG_CARD) + hdr.pack(fill="x", padx=6, pady=(4, 2)) + tk.Label(hdr, text=sel_name, font=FONT_HEAD, bg=BG_CARD, fg=FG).pack(side="left") + + # show the loosest (most permissive) minimal threshold as a hint. + # the truly loosest threshold has mSkipMostPermissiveBit=true so its + # BitPosition is "X" — it lands in the "skip" category. check there first, + # then fall back to the loosest bit-carrying minimal bin. + skipped_minimal = [ + b for b in group if b.get("MinimalCut", "0") == "1" and b.get("BitPosition", "X").upper() == "X" + ] + if skipped_minimal: + loosest_val = format_value_with_comment(skipped_minimal[0]) + tk.Label( + hdr, text=f"minimal cut → loosest selection: {loosest_val}", font=FONT_SMALL, bg=BG_CARD, fg=FG_DIM + ).pack(side="left", padx=10) + elif minimal: + loosest_val = format_value_with_comment(minimal[0][1]) + tk.Label( + hdr, text=f"minimal cut → loosest selection: {loosest_val}", font=FONT_SMALL, bg=BG_CARD, fg=FG_DIM + ).pack(side="left", padx=10) + elif optional: + tk.Label(hdr, text="optional", font=FONT_SMALL, bg=BG_CARD, fg=ACCENT_OPT).pack(side="left", padx=10) + elif neutral: + tk.Label(hdr, text="neutral", font=FONT_SMALL, bg=BG_CARD, fg=ACCENT_REJ).pack(side="left", padx=10) + + # separator + tk.Frame(card, bg=BORDER, height=1).pack(fill="x", padx=6, pady=2) + + # bins + bins_frame = tk.Frame(card, bg=BG_CARD) + bins_frame.pack(fill="x", padx=6, pady=4) + + for i, b in minimal: + self._build_bin_row(bins_frame, sel_name, i, b, "minimal") + for i, b in optional: + self._build_bin_row(bins_frame, sel_name, i, b, "optional") + for i, b in neutral: + self._build_bin_row(bins_frame, sel_name, i, b, "neutral") + + def _build_bin_row(self, parent, sel_name, idx, b, kind): + color = {"minimal": ACCENT, "optional": ACCENT_OPT, "neutral": ACCENT_REJ}[kind] + label_text = format_value_with_comment(b) + + var = tk.BooleanVar(value=False) + + self._vars[(sel_name, idx)] = var + + row = tk.Frame(parent, bg=BG_CARD) + row.pack(fill="x", pady=1) + + # coloured dot + tk.Label(row, text="●", font=FONT_BODY, bg=BG_CARD, fg=color).pack(side="left", padx=(0, 4)) + + # checkbox styled as a toggle button + cb = tk.Checkbutton( + row, + text=label_text, + variable=var, + font=FONT_BODY, + bg=BG_CARD, + fg=FG, + activebackground=BG_HOVER, + activeforeground=FG, + selectcolor=SEL_BG, + relief="flat", + bd=0, + highlightthickness=0, + cursor="hand2", + command=self._update_bitmask, + ) + cb.pack(side="left", fill="x", expand=True) + + # bit-position badge + pos = b.get("BitPosition", "X") + if pos.upper() != "X": + tk.Label(row, text=f"bit {pos}", font=FONT_SMALL, bg=BG_CARD, fg=FG_DIM, width=8).pack(side="right", padx=4) + + # ── Bitmask computation ─────────────────────────────────────────────────── + def _update_bitmask(self): + bitmask = 0 + for (sel_name, idx), var in self._vars.items(): + if not var.get(): + continue + b = self._groups[sel_name][idx] + pos = b.get("BitPosition", "X") + if pos.upper() == "X": + continue + bitmask |= 1 << int(pos) + + self._lbl_dec.config(text=str(bitmask)) + self._lbl_hex.config(text=hex(bitmask)) + self._lbl_bin.config(text=bin(bitmask)) + + # ── Utilities ───────────────────────────────────────────────────────────── + def _copy(self, text): + self.clipboard_clear() + self.clipboard_append(text) + self.update() + + @staticmethod + def _make_button(parent, text, cmd, color): + return tk.Button( + parent, + text=text, + command=cmd, + font=FONT_BODY, + bg=BG_CARD, + fg=color, + activebackground=BG_HOVER, + activeforeground=color, + relief="flat", + bd=0, + padx=10, + pady=4, + highlightthickness=1, + highlightbackground=color, + cursor="hand2", + ) + + +# ── Entry point ─────────────────────────────────────────────────────────────── +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="CutCulator GUI") + parser.add_argument("rootfile", nargs="?", default=None, help="Path to ROOT file (optional, can be opened via GUI)") + parser.add_argument("--dir", default="femto-producer", help="TDirectory path in ROOT file") + args = parser.parse_args() + + app = CutCulatorApp(rootfile=args.rootfile, tdir=args.dir) + app.mainloop() diff --git a/PWGCF/Femto/TableProducer/CMakeLists.txt b/PWGCF/Femto/TableProducer/CMakeLists.txt index fc9a5f82013..666b21a839c 100644 --- a/PWGCF/Femto/TableProducer/CMakeLists.txt +++ b/PWGCF/Femto/TableProducer/CMakeLists.txt @@ -18,3 +18,8 @@ o2physics_add_dpl_workflow(femto-producer-derived-to-derived SOURCES ./femtoProducerDerivedToDerived.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-producer-kink-pt-converter + SOURCES ./femtoProducerKinkPtConverter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Femto/TableProducer/femtoProducer.cxx b/PWGCF/Femto/TableProducer/femtoProducer.cxx index 36897c02afb..8d47b4a3730 100644 --- a/PWGCF/Femto/TableProducer/femtoProducer.cxx +++ b/PWGCF/Femto/TableProducer/femtoProducer.cxx @@ -19,67 +19,59 @@ #include "PWGCF/Femto/Core/mcBuilder.h" #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/trackBuilder.h" -#include "PWGCF/Femto/Core/twoTrackResonanceBuilder.h" #include "PWGCF/Femto/Core/v0Builder.h" #include "PWGLF/DataModel/LFKinkDecayTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include "fairlogger/Logger.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; namespace o2::analysis::femto { namespace consumeddata { -using Run3PpCollisions = soa::Join; -using Run3PpMcRecoCollisions = soa::Join; -using Run3PpMcGenCollisions = soa::Join; +using Run3PpCollisions = o2::soa::Join; +using Run3PpMcRecoCollisions = o2::soa::Join; +using Run3PpMcGenCollisions = o2::soa::Join; using Run3FullPidTracks = - soa::Join; -using Run3McRecoTracks = soa::Join; + soa::Join; +using Run3McRecoTracks = soa::Join; -using Run3Vzeros = aod::V0Datas; -using Run3RecoVzeros = soa::Join; +using Run3Vzeros = o2::aod::V0Datas; +using Run3RecoVzeros = o2::soa::Join; -using Run3Cascades = CascDatas; -using Run3RecoCascades = soa::Join; +using Run3Cascades = o2::aod::CascDatas; +using Run3RecoCascades = o2::soa::Join; -using Run3Kinks = KinkCands; +using Run3Kinks = o2::aod::KinkCands; -using Run3McGenParticles = aod::McParticles; +using Run3McGenParticles = o2::aod::McParticles; } // namespace consumeddata } // namespace o2::analysis::femto @@ -132,36 +124,6 @@ struct FemtoProducer { kinkbuilder::ConfSigmaPlusBits confSigmaPlusBits; kinkbuilder::KinkBuilder sigmaPlusBuilder; - // resonance daughter filters and partitions - twotrackresonancebuilder::ConfTwoTrackResonanceDaughterFilters confResonanceDaughterFilters; - // caching and preslicing - SliceCache cache; - Preslice perColTracks = track::collisionId; - Partition partitionPositiveDaughters = - (track::signed1Pt > 0.f) && - (track::pt > confResonanceDaughterFilters.ptMin && track::pt < confResonanceDaughterFilters.ptMax) && - (track::eta > confResonanceDaughterFilters.etaMin && track::eta < confResonanceDaughterFilters.etaMax) && - (track::phi > confResonanceDaughterFilters.phiMin && track::phi < confResonanceDaughterFilters.phiMax); - Partition partitionNegativeDaughters = - (track::signed1Pt < 0.f) && - (track::pt > confResonanceDaughterFilters.ptMin && track::pt < confResonanceDaughterFilters.ptMax) && - (track::eta > confResonanceDaughterFilters.etaMin && track::eta < confResonanceDaughterFilters.etaMax) && - (track::phi > confResonanceDaughterFilters.phiMin && track::phi < confResonanceDaughterFilters.phiMax); - - // resonance builders - twotrackresonancebuilder::TwoTrackResonanceBuilderProducts twoTrackResonanceBuilderProducts; - twotrackresonancebuilder::ConfTwoTrackResonanceTables confTwoTrackResonanceTables; - twotrackresonancebuilder::ConfRhoFilters confRhoFilters; - twotrackresonancebuilder::ConfRho0Bits confRho0Bits; - twotrackresonancebuilder::TwoTrackResonanceBuilder rho0Builder; - twotrackresonancebuilder::ConfPhiFilters confPhiFilters; - twotrackresonancebuilder::ConfPhiBits confPhiBits; - twotrackresonancebuilder::TwoTrackResonanceBuilder phiBuilder; - twotrackresonancebuilder::ConfKstarFilters confKstarFilters; - twotrackresonancebuilder::ConfKstar0Bits confKstar0Bits; - twotrackresonancebuilder::TwoTrackResonanceBuilder kstar0Builder; - twotrackresonancebuilder::TwoTrackResonanceBuilder kstar0barBuilder; - // mc builder mcbuilder::ConfMc confMc; mcbuilder::ConfMcTables confMcTables; @@ -170,12 +132,12 @@ struct FemtoProducer { // histogramming // add histograms in next iteration - HistogramRegistry hRegistry{"FemtoProducer", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoProducer", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; // data members - Service ccdb; /// Accessing the CCDB + o2::framework::Service ccdb; /// Accessing the CCDB - void init(InitContext& context) + void init(o2::framework::InitContext& context) { if ((xiBuilder.fillAnyTable() || omegaBuilder.fillAnyTable()) && (!doprocessTracksV0sCascadesRun3pp && !doprocessTracksV0sCascadesKinksRun3pp)) { LOG(fatal) << "At least one cascade table is enabled, but wrong process function is enabled. Breaking..."; @@ -191,6 +153,7 @@ struct FemtoProducer { } // init ccdb + LOG(info) << "Setting up connection to CCDB with URL: " << confCcdb.ccdbUrl.value; ccdb->setURL(confCcdb.ccdbUrl.value); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -216,19 +179,13 @@ struct FemtoProducer { xiBuilder.init(&hRegistry, confXiBits, confCascadeFilters, confCascadeTables, context); omegaBuilder.init(&hRegistry, confOmegaBits, confCascadeFilters, confCascadeTables, context); - // configure resonance selections - rho0Builder.init(&hRegistry, confRho0Bits, confRhoFilters, confResonanceDaughterFilters, confTwoTrackResonanceTables, context); - phiBuilder.init(&hRegistry, confPhiBits, confPhiFilters, confResonanceDaughterFilters, confTwoTrackResonanceTables, context); - kstar0Builder.init(&hRegistry, confKstar0Bits, confKstarFilters, confResonanceDaughterFilters, confTwoTrackResonanceTables, context); - kstar0barBuilder.init(&hRegistry, confKstar0Bits, confKstarFilters, confResonanceDaughterFilters, confTwoTrackResonanceTables, context); - // configure mcBuilder mcBuilder.init(confMc, confMcTables, context); hRegistry.print(); } - // Core implementations + // processing collisions template bool processCollisions(T1 const& col, T2 const& /* bcs*/, T3 const& tracks) { @@ -242,12 +199,11 @@ struct FemtoProducer { // collisions are filled if at least one partilce is found in the collisions return true; } - - template - bool processMcCollisions(T1 const& col, T2 const& mcCols, T3 const& /* bcs*/, T4 const& tracks) + template + bool processMcCollisions(T1 const& col, T2 const& mcCols, T3 const& /* bcs*/, T4 const& tracks, T5 const& mcParticles) { - mcBuilder.reset(); collisionBuilder.reset(); + mcBuilder.reset(mcCols, mcParticles); // we call this function always first so we reset the mcBuilder here auto bc = col.template bc_as(); collisionBuilder.initCollision(bc, col, tracks, ccdb, hRegistry); if (!collisionBuilder.checkCollision(col, mcCols)) { @@ -258,30 +214,21 @@ struct FemtoProducer { return true; } + // processing tracks template void processTracks(T1 const& col, T2 const& tracksWithItsPid) { + trackBuilder.reset(tracksWithItsPid); trackBuilder.fillTracks(col, collisionBuilder, collisionBuilderProducts, tracksWithItsPid, trackBuilderProducts); } - template void processMcTracks(T1 const& col, T2 const& mcCols, T3 const& tracks, T4 const& tracksWithItsPid, T5 const& mcParticles) { + trackBuilder.reset(tracksWithItsPid); trackBuilder.fillMcTracks(col, collisionBuilder, collisionBuilderProducts, mcCols, tracks, tracksWithItsPid, trackBuilderProducts, mcParticles, mcBuilder, mcProducts); } - template - void processResonances(T1 const& col, T2 const& tracks, T3 const& tracksWithItsPid) - { - auto groupPositiveTracks = partitionPositiveDaughters->sliceByCached(track::collisionId, col.globalIndex(), cache); - auto groupNegativeTracks = partitionNegativeDaughters->sliceByCached(track::collisionId, col.globalIndex(), cache); - rho0Builder.fillResonances(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, twoTrackResonanceBuilderProducts, groupPositiveTracks, groupNegativeTracks, tracks, tracksWithItsPid, trackBuilder); - phiBuilder.fillResonances(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, twoTrackResonanceBuilderProducts, groupPositiveTracks, groupNegativeTracks, tracks, tracksWithItsPid, trackBuilder); - kstar0Builder.fillResonances(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, twoTrackResonanceBuilderProducts, groupPositiveTracks, groupNegativeTracks, tracks, tracksWithItsPid, trackBuilder); - kstar0barBuilder.fillResonances(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, twoTrackResonanceBuilderProducts, groupPositiveTracks, groupNegativeTracks, tracks, tracksWithItsPid, trackBuilder); - } - - // add v0s + // processing v0s template void processV0s(T1 const& col, T2 const& tracks, T3 const& tracksWithItsPid, T4 const& v0s) { @@ -289,7 +236,6 @@ struct FemtoProducer { antilambdaBuilder.fillV0s(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, v0builderProducts, v0s, tracks, tracksWithItsPid, trackBuilder); k0shortBuilder.fillV0s(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, v0builderProducts, v0s, tracks, tracksWithItsPid, trackBuilder); } - template void processMcV0s(T1 const& col, T2 const& mcCols, T3 const& tracks, T4 const& tracksWithItsPid, T5 const& v0s, T6 const& mcParticles) { @@ -298,14 +244,13 @@ struct FemtoProducer { k0shortBuilder.fillMcV0s(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, v0builderProducts, v0s, tracks, tracksWithItsPid, trackBuilder, mcParticles, mcBuilder, mcProducts); } - // add kinks + // processing kinks template void processKinks(T1 const& col, T2 const& tracks, T3 const& tracksWithItsPid, T4 const& kinks) { sigmaBuilder.fillKinks(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, kinkBuilderProducts, kinks, tracks, tracksWithItsPid, trackBuilder); sigmaPlusBuilder.fillKinks(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, kinkBuilderProducts, kinks, tracks, tracksWithItsPid, trackBuilder); } - template void processMcKinks(T1 const& col, T2 const& mcCols, T3 const& tracks, T4 const& tracksWithItsPid, T5 const& kinks, T6 const& mcParticles) { @@ -313,7 +258,7 @@ struct FemtoProducer { sigmaPlusBuilder.fillMcKinks(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, kinkBuilderProducts, kinks, tracks, tracksWithItsPid, trackBuilder, mcParticles, mcBuilder, mcProducts); } - // add cascades + // processing cascades template void processCascades(T1 const& col, T2 const& tracks, T3 const& tracksWithItsPid, T4 const& cascades) { @@ -322,59 +267,62 @@ struct FemtoProducer { omegaBuilder.fillCascades(col, collisionBuilder, collisionBuilderProducts, trackBuilderProducts, cascadeBuilderProducts, cascades, tracks, tracksWithItsPid, trackBuilder); } + template + void processMcCascades(T1 const& col, T2 const& mcCols, T3 const& tracks, T4 const& tracksWithItsPid, T5 const& cascades, T6 const& mcParticles) + { + xiBuilder.fillMcCascades(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, cascadeBuilderProducts, cascades, tracks, tracksWithItsPid, trackBuilder, mcParticles, mcBuilder, mcProducts); + omegaBuilder.fillMcCascades(col, collisionBuilder, collisionBuilderProducts, mcCols, trackBuilderProducts, cascadeBuilderProducts, cascades, tracks, tracksWithItsPid, trackBuilder, mcParticles, mcBuilder, mcProducts); + } // proccess functions void processTracksRun3pp(consumeddata::Run3PpCollisions::iterator const& col, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3FullPidTracks const& tracks) { if (!processCollisions(col, bcs, tracks)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processResonances(col, tracks, tracksWithItsPid); } PROCESS_SWITCH(FemtoProducer, processTracksRun3pp, "Process tracks", true); // process tracks and v0s void processTracksV0sRun3pp(consumeddata::Run3PpCollisions::iterator const& col, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3FullPidTracks const& tracks, consumeddata::Run3Vzeros const& v0s) { if (!processCollisions(col, bcs, tracks)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processResonances(col, tracks, tracksWithItsPid); processV0s(col, tracks, tracksWithItsPid, v0s); }; PROCESS_SWITCH(FemtoProducer, processTracksV0sRun3pp, "Process tracks and v0s", false); // process tracks and kinks void processTracksKinksRun3pp(consumeddata::Run3PpCollisions::iterator const& col, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3FullPidTracks const& tracks, consumeddata::Run3Kinks const& kinks) { if (!processCollisions(col, bcs, tracks)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processResonances(col, tracks, tracksWithItsPid); processKinks(col, tracks, tracksWithItsPid, kinks); } PROCESS_SWITCH(FemtoProducer, processTracksKinksRun3pp, "Process tracks and kinks", false); // process tracks, v0s and cascades void processTracksV0sCascadesRun3pp(consumeddata::Run3PpCollisions::iterator const& col, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3FullPidTracks const& tracks, consumeddata::Run3Vzeros const& v0s, consumeddata::Run3Cascades const& cascades) @@ -382,10 +330,9 @@ struct FemtoProducer { if (!processCollisions(col, bcs, tracks)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processResonances(col, tracks, tracksWithItsPid); processV0s(col, tracks, tracksWithItsPid, v0s); processCascades(col, tracks, tracksWithItsPid, cascades); } @@ -393,7 +340,7 @@ struct FemtoProducer { // process tracks, v0s, cascades and kinks void processTracksV0sCascadesKinksRun3pp(consumeddata::Run3PpCollisions::iterator const& col, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3FullPidTracks const& tracks, consumeddata::Run3Vzeros const& v0s, consumeddata::Run3Cascades const& cascades, @@ -402,10 +349,9 @@ struct FemtoProducer { if (!processCollisions(col, bcs, tracks)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processTracks(col, tracksWithItsPid); - processResonances(col, tracks, tracksWithItsPid); processV0s(col, tracks, tracksWithItsPid, v0s); processKinks(col, tracks, tracksWithItsPid, kinks); processCascades(col, tracks, tracksWithItsPid, cascades); @@ -415,15 +361,15 @@ struct FemtoProducer { // process monte carlo tracks void processTracksRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, consumeddata::Run3PpMcGenCollisions const& mcCols, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3McRecoTracks const& tracks, consumeddata::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks)) { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); } PROCESS_SWITCH(FemtoProducer, processTracksRun3ppMc, "Provide reconstructed and generated Tracks", false); @@ -431,16 +377,16 @@ struct FemtoProducer { // process monte carlo tracks and v0s void processTracksV0sRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, consumeddata::Run3PpMcGenCollisions const& mcCols, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3McRecoTracks const& tracks, consumeddata::Run3RecoVzeros const& v0s, consumeddata::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks)) { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); processMcV0s(col, mcCols, tracks, tracksWithItsPid, v0s, mcParticles); } @@ -449,16 +395,16 @@ struct FemtoProducer { // process monte carlo tracks and kinks void processTracksKinksRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, consumeddata::Run3PpMcGenCollisions const& mcCols, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3McRecoTracks const& tracks, consumeddata::Run3Kinks const& kinks, consumeddata::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks)) { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); processMcKinks(col, mcCols, tracks, tracksWithItsPid, kinks, mcParticles); } @@ -467,26 +413,46 @@ struct FemtoProducer { // process monte carlo tracks and v0s and kinks (adding cascades later here) void processTracksV0sKinksRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, consumeddata::Run3PpMcGenCollisions const& mcCols, - BCsWithTimestamps const& bcs, + o2::aod::BCsWithTimestamps const& bcs, consumeddata::Run3McRecoTracks const& tracks, consumeddata::Run3RecoVzeros const& v0s, consumeddata::Run3Kinks const& kinks, consumeddata::Run3McGenParticles const& mcParticles) { - if (!processMcCollisions(col, mcCols, bcs, tracks)) { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { return; } - auto tracksWithItsPid = o2::soa::Attach(tracks); + auto tracksWithItsPid = o2::soa::Attach(tracks); processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); processMcV0s(col, mcCols, tracks, tracksWithItsPid, v0s, mcParticles); processMcKinks(col, mcCols, tracks, tracksWithItsPid, kinks, mcParticles); } PROCESS_SWITCH(FemtoProducer, processTracksV0sKinksRun3ppMc, "Provide reconstructed and generated tracks and v0s and kinks", false); + + // process monte carlo tracks and v0s + void processTracksV0sCascadesRun3ppMc(consumeddata::Run3PpMcRecoCollisions::iterator const& col, + consumeddata::Run3PpMcGenCollisions const& mcCols, + o2::aod::BCsWithTimestamps const& bcs, + consumeddata::Run3McRecoTracks const& tracks, + consumeddata::Run3RecoVzeros const& v0s, + consumeddata::Run3RecoCascades const& cascades, + consumeddata::Run3McGenParticles const& mcParticles) + { + if (!processMcCollisions(col, mcCols, bcs, tracks, mcParticles)) { + return; + } + auto tracksWithItsPid = o2::soa::Attach(tracks); + processMcTracks(col, mcCols, tracks, tracksWithItsPid, mcParticles); + processMcV0s(col, mcCols, tracks, tracksWithItsPid, v0s, mcParticles); + processMcCascades(col, mcCols, tracks, tracksWithItsPid, cascades, mcParticles); + } + PROCESS_SWITCH(FemtoProducer, processTracksV0sCascadesRun3ppMc, "Provide reconstructed and generated tracks and v0s", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + o2::framework::WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGCF/Femto/TableProducer/femtoProducerDerivedToDerived.cxx b/PWGCF/Femto/TableProducer/femtoProducerDerivedToDerived.cxx index 6f9347015eb..64a3ede4696 100644 --- a/PWGCF/Femto/TableProducer/femtoProducerDerivedToDerived.cxx +++ b/PWGCF/Femto/TableProducer/femtoProducerDerivedToDerived.cxx @@ -14,47 +14,42 @@ /// \author Anton Riedel, TU München, anton.riedel@tum.de #include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/kinkBuilder.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/v0Builder.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/InitContext.h" -#include "Framework/runDataProcessing.h" - -#include -#include -#include - -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; +#include +#include +#include +#include +#include +#include +#include + using namespace o2::analysis::femto; struct FemtoProducerDerivedToDerived { // setup tables - using Collisions = Join; + using Collisions = o2::soa::Join; using Collision = Collisions::iterator; using FilteredCollisions = o2::soa::Filtered; using FilteredCollision = FilteredCollisions::iterator; - using Tracks = o2::soa::Join; - using Lambdas = o2::soa::Join; - using K0shorts = o2::soa::Join; + using Tracks = o2::soa::Join; + using Lambdas = o2::soa::Join; + using K0shorts = o2::soa::Join; + using Sigma = o2::soa::Join; + using SigmaPlus = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // collision builder collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); collisionbuilder::CollisionBuilderDerivedToDerivedProducts collisionBuilderProducts; collisionbuilder::CollisionBuilderDerivedToDerived collisionBuilder; @@ -65,9 +60,9 @@ struct FemtoProducerDerivedToDerived { trackbuilder::ConfTrackSelection1 trackSelections1; trackbuilder::ConfTrackSelection2 trackSelections2; - Partition trackPartition1 = MAKE_TRACK_PARTITION(trackSelections1); - Partition trackPartition2 = MAKE_TRACK_PARTITION(trackSelections2); - Preslice perColTracks = femtobase::stored::fColId; + o2::framework::Partition trackPartition1 = MAKE_TRACK_PARTITION(trackSelections1); + o2::framework::Partition trackPartition2 = MAKE_TRACK_PARTITION(trackSelections2); + o2::framework::Preslice perColTracks = o2::aod::femtobase::stored::fColId; // v0 builder v0builder::V0BuilderDerivedToDerived v0Builder; @@ -75,19 +70,33 @@ struct FemtoProducerDerivedToDerived { v0builder::ConfV0TablesDerivedToDerived confV0Builder; v0builder::ConfLambdaSelection1 lambdaSelection1; - Partition lambdaPartition = MAKE_LAMBDA_PARTITION(lambdaSelection1); - Preslice perColLambdas = femtobase::stored::fColId; + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(lambdaSelection1); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; v0builder::ConfK0shortSelection1 k0shortSelection1; - Partition k0shortPartition = MAKE_K0SHORT_PARTITION(k0shortSelection1); - Preslice perColK0shorts = femtobase::stored::fColId; + o2::framework::Partition k0shortPartition = MAKE_K0SHORT_PARTITION(k0shortSelection1); + o2::framework::Preslice perColK0shorts = o2::aod::femtobase::stored::fColId; + + // kink builder + kinkbuilder::KinkBuilderDerivedToDerived kinkBuilder; + kinkbuilder::KinkBuilderDerivedToDerivedProducts kinkBuilderProducts; + kinkbuilder::ConfKinkTablesDerivedToDerived confKinkBuilder; + + kinkbuilder::ConfSigmaSelection1 sigmaSelection1; + o2::framework::Partition sigmaPartition = MAKE_SIGMA_PARTITION(sigmaSelection1); + o2::framework::Preslice perColSigma = o2::aod::femtobase::stored::fColId; - void init(InitContext& /*context*/) + kinkbuilder::ConfSigmaPlusSelection1 sigmaPlusSelection1; + o2::framework::Partition sigmaPlusPartition = MAKE_SIGMAPLUS_PARTITION(sigmaPlusSelection1); + o2::framework::Preslice perColSigmaPlus = o2::aod::femtobase::stored::fColId; + + void init(o2::framework::InitContext& /*context*/) { trackBuilder.init(confTrackBuilder); v0Builder.init(confV0Builder); + kinkBuilder.init(confKinkBuilder); - if ((doprocessTracks + doprocessLambdas + doprocessK0shorts) > 1) { + if ((doprocessTracks + doprocessTracksLambdas + doprocessTracksK0shorts + doprocessTracksSigma + doprocessTracksSigmaPlus) > 1) { LOG(fatal) << "Only one proccess function can be activated"; } } @@ -103,35 +112,53 @@ struct FemtoProducerDerivedToDerived { } PROCESS_SWITCH(FemtoProducerDerivedToDerived, processTracks, "Process tracks", true); - void processLambdas(FilteredCollision const& col, Tracks const& tracks, Lambdas const& lambdas) + void processTracksLambdas(FilteredCollision const& col, Tracks const& tracks, Lambdas const& lambdas) { - if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache) && v0Builder.collisionHasTooFewLambdas(col, lambdas, lambdaPartition, cache)) { + if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache) || v0Builder.collisionHasTooFewLambdas(col, lambdas, lambdaPartition, cache)) { return; } - if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache)) { - collisionBuilder.processCollision(col, collisionBuilderProducts); - trackBuilder.processTracks(col, tracks, trackPartition1, trackPartition2, cache, trackBuilderProducts, collisionBuilderProducts); - v0Builder.processLambdas(col, lambdas, tracks, lambdaPartition, trackBuilder, cache, v0BuilderProducts, trackBuilderProducts, collisionBuilderProducts); + collisionBuilder.processCollision(col, collisionBuilderProducts); + trackBuilder.processTracks(col, tracks, trackPartition1, trackPartition2, cache, trackBuilderProducts, collisionBuilderProducts); + v0Builder.processLambdas(col, lambdas, tracks, lambdaPartition, trackBuilder, cache, v0BuilderProducts, trackBuilderProducts, collisionBuilderProducts); + } + PROCESS_SWITCH(FemtoProducerDerivedToDerived, processTracksLambdas, "Process lambdas and tracks", false); + + void processTracksK0shorts(FilteredCollision const& col, Tracks const& tracks, K0shorts const& k0shorts) + { + if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache) || v0Builder.collisionHasTooFewK0shorts(col, k0shorts, k0shortPartition, cache)) { + return; } + collisionBuilder.processCollision(col, collisionBuilderProducts); + trackBuilder.processTracks(col, tracks, trackPartition1, trackPartition2, cache, trackBuilderProducts, collisionBuilderProducts); + v0Builder.processK0shorts(col, k0shorts, tracks, k0shortPartition, trackBuilder, cache, v0BuilderProducts, trackBuilderProducts, collisionBuilderProducts); } - PROCESS_SWITCH(FemtoProducerDerivedToDerived, processLambdas, "Process lambdas and tracks", false); + PROCESS_SWITCH(FemtoProducerDerivedToDerived, processTracksK0shorts, "Process k0short and tracks", false); - void processK0shorts(FilteredCollision const& col, Tracks const& tracks, K0shorts const& k0shorts) + void processTracksSigma(FilteredCollision const& col, Tracks const& tracks, Sigma const& sigma) { - if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache) && v0Builder.collisionHasTooFewK0shorts(col, k0shorts, k0shortPartition, cache)) { + if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache) || kinkBuilder.collisionHasTooFewSigma(col, sigma, sigmaPartition, cache)) { return; } - if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache)) { - collisionBuilder.processCollision(col, collisionBuilderProducts); - trackBuilder.processTracks(col, tracks, trackPartition1, trackPartition2, cache, trackBuilderProducts, collisionBuilderProducts); - v0Builder.processK0shorts(col, k0shorts, tracks, k0shortPartition, trackBuilder, cache, v0BuilderProducts, trackBuilderProducts, collisionBuilderProducts); + collisionBuilder.processCollision(col, collisionBuilderProducts); + trackBuilder.processTracks(col, tracks, trackPartition1, trackPartition2, cache, trackBuilderProducts, collisionBuilderProducts); + kinkBuilder.processSigma(col, sigma, tracks, sigmaPartition, trackBuilder, cache, kinkBuilderProducts, trackBuilderProducts, collisionBuilderProducts); + } + PROCESS_SWITCH(FemtoProducerDerivedToDerived, processTracksSigma, "Process sigma and tracks", false); + + void processTracksSigmaPlus(FilteredCollision const& col, Tracks const& tracks, SigmaPlus const& sigmaplus) + { + if (trackBuilder.collisionHasTooFewTracks(col, tracks, trackPartition1, trackPartition2, cache) || kinkBuilder.collisionHasTooFewSigmaPlus(col, sigmaplus, sigmaPlusPartition, cache)) { + return; } + collisionBuilder.processCollision(col, collisionBuilderProducts); + trackBuilder.processTracks(col, tracks, trackPartition1, trackPartition2, cache, trackBuilderProducts, collisionBuilderProducts); + kinkBuilder.processSigmaPlus(col, sigmaplus, tracks, sigmaPlusPartition, trackBuilder, cache, kinkBuilderProducts, trackBuilderProducts, collisionBuilderProducts); } - PROCESS_SWITCH(FemtoProducerDerivedToDerived, processK0shorts, "Process k0short and tracks", false); + PROCESS_SWITCH(FemtoProducerDerivedToDerived, processTracksSigmaPlus, "Process sigmaPlus and tracks", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + o2::framework::WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGCF/Femto/TableProducer/femtoProducerKinkPtConverter.cxx b/PWGCF/Femto/TableProducer/femtoProducerKinkPtConverter.cxx new file mode 100644 index 00000000000..f710e4ac194 --- /dev/null +++ b/PWGCF/Femto/TableProducer/femtoProducerKinkPtConverter.cxx @@ -0,0 +1,113 @@ +// Copyright 2019-2025 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 femtoProducerKinkPtConverter.cxx +/// \brief Task that converts FSigmas_001 to FSigmas_002 with recalculated pT +/// \author Henrik Fribert, TU München, henrik.fribert@tum.de + +#include "PWGCF/Femto/Core/femtoUtils.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include + +using namespace o2::analysis::femto; + +struct FemtoProducerKinkPtConverter { + + o2::framework::Produces producedSigmas; + + o2::framework::Configurable confUseRecalculatedPt{"confUseRecalculatedPt", true, "Use recalculated pT from kinematic constraints"}; + o2::framework::Configurable confFill1DHistos{"confFill1DHistos", true, "Fill 1D histograms"}; + o2::framework::Configurable confFill2DHistos{"confFill2DHistos", true, "Fill 2D histograms"}; + + o2::framework::HistogramRegistry mHistogramRegistry{"FemtoSigmaConverter", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + if (confFill1DHistos) { + mHistogramRegistry.add("hPtOriginal", "Original pT;p_{T} (GeV/c);Counts", o2::framework::kTH1F, {{100, 0, 10}}); + mHistogramRegistry.add("hPtRecalculated", "Recalculated pT;p_{T} (GeV/c);Counts", o2::framework::kTH1F, {{100, 0, 10}}); + mHistogramRegistry.add("hRecalcSuccess", "Recalculation Success;Success (0=fail, 1=success);Counts", o2::framework::kTH1I, {{2, -0.5, 1.5}}); + } + if (confFill2DHistos) { + mHistogramRegistry.add("hPtOriginalVsRecalculated", "Original vs Recalculated pT;p_{T,orig} (GeV/c);p_{T,recalc} (GeV/c)", o2::framework::kTH2F, {{100, 0, 10}, {100, 0, 10}}); + } + } + + void process(o2::aod::FSigmas_001 const& sigmasV1, + o2::aod::FTracks const& tracks) + { + for (const auto& sigma : sigmasV1) { + + float signedPtToUse = sigma.signedPt(); + + if (confUseRecalculatedPt) { + auto chaDaughter = tracks.rawIteratorAt(sigma.chaDauId() - tracks.offset()); + + float pxDaug = chaDaughter.pt() * std::cos(chaDaughter.phi()); + float pyDaug = chaDaughter.pt() * std::sin(chaDaughter.phi()); + float pzDaug = chaDaughter.pt() * std::sinh(chaDaughter.eta()); + + float pxMoth = sigma.pt() * std::cos(sigma.phi()); + float pyMoth = sigma.pt() * std::sin(sigma.phi()); + float pzMoth = sigma.pt() * std::sinh(sigma.eta()); + + float ptRecalc = utils::calcPtnew(pxMoth, pyMoth, pzMoth, pxDaug, pyDaug, pzDaug); + + ROOT::Math::PtEtaPhiMVector recalcVec(ptRecalc, sigma.eta(), sigma.phi(), sigma.mass()); + float ptFrom4Vec = recalcVec.Pt(); + + if (ptFrom4Vec > 0) { + signedPtToUse = ptFrom4Vec * utils::signum(sigma.signedPt()); + + if (confFill1DHistos) { + mHistogramRegistry.fill(HIST("hPtOriginal"), sigma.pt()); + mHistogramRegistry.fill(HIST("hPtRecalculated"), ptFrom4Vec); + mHistogramRegistry.fill(HIST("hRecalcSuccess"), 1); + } + if (confFill2DHistos) { + mHistogramRegistry.fill(HIST("hPtOriginalVsRecalculated"), sigma.pt(), ptFrom4Vec); + } + } else { + if (confFill1DHistos) { + mHistogramRegistry.fill(HIST("hRecalcSuccess"), 0); + } + } + } + + producedSigmas(sigma.fColId(), + signedPtToUse, + sigma.eta(), + sigma.phi(), + sigma.mass(), + sigma.chaDauId()); + } + } +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::framework::WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/Femto/Tasks/CMakeLists.txt b/PWGCF/Femto/Tasks/CMakeLists.txt index b124fbb05d0..baad9c28a8a 100644 --- a/PWGCF/Femto/Tasks/CMakeLists.txt +++ b/PWGCF/Femto/Tasks/CMakeLists.txt @@ -63,3 +63,13 @@ o2physics_add_dpl_workflow(femto-pair-v0-v0 SOURCES femtoPairV0V0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-triplet-track-track-track + SOURCES femtoTripletTrackTrackTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-triplet-track-track-v0 + SOURCES femtoTripletTrackTrackV0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Femto/Tasks/femtoCascadeQa.cxx b/PWGCF/Femto/Tasks/femtoCascadeQa.cxx index 2e9fd0c1b8c..ea60ae07ab2 100644 --- a/PWGCF/Femto/Tasks/femtoCascadeQa.cxx +++ b/PWGCF/Femto/Tasks/femtoCascadeQa.cxx @@ -18,55 +18,65 @@ #include "PWGCF/Femto/Core/collisionBuilder.h" #include "PWGCF/Femto/Core/collisionHistManager.h" #include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoCascadeQa { - // setup tables - using FemtoCollisions = o2::soa::Join; - using FemtoCollision = FemtoCollisions::iterator; - + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoXis = o2::soa::Join; - using FemtoOmegas = o2::soa::Join; - using FemtoTracks = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; + + using FemtoXis = o2::soa::Join; + using FemtoOmegas = o2::soa::Join; + using FemtoTracks = o2::soa::Join; + + using FemtoXisWithLabel = o2::soa::Join; + using FemtoOmegasWithLabel = o2::soa::Join; + using FemtoTracksWithLabel = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::CollisionHistManager colHistManager; colhistmanager::ConfCollisionBinning confCollisionBinning; colhistmanager::ConfCollisionQaBinning confCollisionQaBinning; // setup for xis cascadebuilder::ConfXiSelection confXiSelection; - Partition xiPartition = MAKE_CASCADE_PARTITION(confXiSelection); - Preslice preColXis = femtobase::stored::fColId; + + particlecleaner::ConfXiCleaner1 confXiCleaner; + particlecleaner::ParticleCleaner xiCleaner; + + o2::framework::Partition xiPartition = MAKE_CASCADE_PARTITION(confXiSelection); + o2::framework::Preslice preColXis = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition xiWithLabelPartition = MAKE_CASCADE_PARTITION(confXiSelection); + o2::framework::Preslice perColXisWithLabel = o2::aod::femtobase::stored::fColId; cascadehistmanager::ConfXiBinning confXiBinning; cascadehistmanager::ConfXiQaBinning confXiQaBinning; @@ -80,8 +90,15 @@ struct FemtoCascadeQa { // setup for omegas cascadebuilder::ConfOmegaSelection confOmegaSelection; - Partition omegaPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); - Preslice preColOmegas = femtobase::stored::fColId; + + particlecleaner::ConfOmegaCleaner1 confOmegaCleaner; + particlecleaner::ParticleCleaner omegaCleaner; + + o2::framework::Partition omegaPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); + o2::framework::Preslice preColOmegas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition omegaWithLabelPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); + o2::framework::Preslice perColOmegasWithLabel = o2::aod::femtobase::stored::fColId; cascadehistmanager::ConfOmegaBinning confOmegaBinning; cascadehistmanager::ConfOmegaQaBinning confOmegaQaBinning; @@ -101,56 +118,107 @@ struct FemtoCascadeQa { trackhistmanager::ConfCascadeBachelorBinning confBachelorBinning; trackhistmanager::ConfCascadeBachelorQaBinning confBachelorQaBinning; - HistogramRegistry hRegistry{"FemtoCascadeQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoCascadeQA", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) + void init(o2::framework::InitContext&) { - if ((doprocessXis + doprocessOmegas) > 1) { + if ((doprocessXi + doprocessXiMc + doprocessOmega + doprocessOmegaMc) > 1) { LOG(fatal) << "Only one process can be activated"; } - - auto colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto bachelorHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confBachelorBinning, confBachelorQaBinning); - auto posDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confPosDaughterBinning, confPosDaughterQaBinning); - auto negDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confNegDaughterBinning, confNegDaughterQaBinning); - - if (doprocessXis) { - auto xiHistSpec = cascadehistmanager::makeCascadeQaHistSpecMap(confXiBinning, confXiQaBinning); - xiHistManager.init(&hRegistry, xiHistSpec, confXiSelection, confXiQaBinning, bachelorHistSpec, confBachelorQaBinning, posDaughterHistSpec, confPosDaughterQaBinning, negDaughterHistSpec, confNegDaughterQaBinning); - } - - if (doprocessOmegas) { - auto omegaHistSpec = cascadehistmanager::makeCascadeQaHistSpecMap(confOmegaBinning, confOmegaQaBinning); - omegaHistManager.init(&hRegistry, omegaHistSpec, confOmegaSelection, confOmegaQaBinning, bachelorHistSpec, confBachelorQaBinning, posDaughterHistSpec, confPosDaughterQaBinning, negDaughterHistSpec, confNegDaughterQaBinning); + bool processData = doprocessXi || doprocessOmega; + + xiCleaner.init(confXiCleaner); + omegaCleaner.init(confOmegaCleaner); + + std::map> colHistSpec; + std::map> bachelorHistSpec; + std::map> posDaughterHistSpec; + std::map> negDaughterHistSpec; + std::map> xiHistSpec; + std::map> omegaHistSpec; + + if (processData) { + colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + bachelorHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confBachelorBinning, confBachelorQaBinning); + posDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confPosDaughterBinning, confPosDaughterQaBinning); + negDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confNegDaughterBinning, confNegDaughterQaBinning); + if (doprocessXi) { + xiHistSpec = cascadehistmanager::makeCascadeQaHistSpecMap(confXiBinning, confXiQaBinning); + xiHistManager.init(&hRegistry, xiHistSpec, confXiSelection, confXiQaBinning, bachelorHistSpec, confBachelorQaBinning, posDaughterHistSpec, confPosDaughterQaBinning, negDaughterHistSpec, confNegDaughterQaBinning); + } + if (doprocessOmega) { + omegaHistSpec = cascadehistmanager::makeCascadeQaHistSpecMap(confOmegaBinning, confOmegaQaBinning); + omegaHistManager.init(&hRegistry, omegaHistSpec, confOmegaSelection, confOmegaQaBinning, bachelorHistSpec, confBachelorQaBinning, posDaughterHistSpec, confPosDaughterQaBinning, negDaughterHistSpec, confNegDaughterQaBinning); + } + } else { + colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + bachelorHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confBachelorBinning, confBachelorQaBinning); + posDaughterHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confPosDaughterBinning, confPosDaughterQaBinning); + negDaughterHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confNegDaughterBinning, confNegDaughterQaBinning); + if (doprocessXiMc) { + xiHistSpec = cascadehistmanager::makeCascadeMcQaHistSpecMap(confXiBinning, confXiQaBinning); + xiHistManager.init(&hRegistry, xiHistSpec, confXiSelection, confXiQaBinning, bachelorHistSpec, confBachelorQaBinning, posDaughterHistSpec, confPosDaughterQaBinning, negDaughterHistSpec, confNegDaughterQaBinning); + } + if (doprocessOmegaMc) { + omegaHistSpec = cascadehistmanager::makeCascadeMcQaHistSpecMap(confOmegaBinning, confOmegaQaBinning); + omegaHistManager.init(&hRegistry, omegaHistSpec, confOmegaSelection, confOmegaQaBinning, bachelorHistSpec, confBachelorQaBinning, posDaughterHistSpec, confPosDaughterQaBinning, negDaughterHistSpec, confNegDaughterQaBinning); + } } hRegistry.print(); }; - void processXis(FilteredFemtoCollision const& col, FemtoXis const& /*xis*/, FemtoTracks const& tracks) + void processXi(FilteredFemtoCollision const& col, FemtoXis const& /*xis*/, FemtoTracks const& tracks) { - colHistManager.fill(col); - auto xiSlice = xiPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, 0, 0, 0); + auto xiSlice = xiPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& xi : xiSlice) { xiHistManager.fill(xi, tracks); } } - PROCESS_SWITCH(FemtoCascadeQa, processXis, "Process Xis", true); + PROCESS_SWITCH(FemtoCascadeQa, processXi, "Process Xis", true); + + void processXiMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& /*xis*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + colHistManager.fill(col, mcCols, 0, 0, 0); + auto xiSlice = xiWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + for (auto const& xi : xiSlice) { + if (!xiCleaner.isClean(xi, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } + xiHistManager.fill(xi, tracks, mcParticles, mcMothers, mcPartonicMothers); + } + } + PROCESS_SWITCH(FemtoCascadeQa, processXiMc, "Process Xis with MC information", false); - void processOmegas(FilteredFemtoCollision const& col, FemtoOmegas const& /*omegas*/, FemtoTracks const& tracks) + void processOmega(FilteredFemtoCollision const& col, FemtoOmegas const& /*omegas*/, FemtoTracks const& tracks) { - colHistManager.fill(col); - auto omegaSlice = omegaPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, 0, 0, 0); + auto omegaSlice = omegaPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& omega : omegaSlice) { omegaHistManager.fill(omega, tracks); } } - PROCESS_SWITCH(FemtoCascadeQa, processOmegas, "Process Omegas", false); + PROCESS_SWITCH(FemtoCascadeQa, processOmega, "Process Omegas", false); + + void processOmegaMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoOmegasWithLabel const& /*omegas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + colHistManager.fill(col, mcCols, 0, 0, 0); + auto omegaSlice = omegaWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); + for (auto const& omega : omegaSlice) { + if (!omegaCleaner.isClean(omega, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } + omegaHistManager.fill(omega, tracks, mcParticles, mcMothers, mcPartonicMothers); + } + } + PROCESS_SWITCH(FemtoCascadeQa, processOmegaMc, "Process Omegas with MC information", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoKinkQa.cxx b/PWGCF/Femto/Tasks/femtoKinkQa.cxx index 7887b563463..82ba5c380c8 100644 --- a/PWGCF/Femto/Tasks/femtoKinkQa.cxx +++ b/PWGCF/Femto/Tasks/femtoKinkQa.cxx @@ -19,54 +19,53 @@ #include "PWGCF/Femto/Core/kinkBuilder.h" #include "PWGCF/Femto/Core/kinkHistManager.h" #include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" #include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoKinkQa { // setup tables - using FemtoCollisions = o2::soa::Join; + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoCollisionsWithLabel = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; // Define kink/sigma tables (joining tables for comprehensive information) - using FemtoSigmas = o2::soa::Join; - using FemtoSigmaPlus = o2::soa::Join; - using FemtoTracks = o2::soa::Join; + using FemtoSigmas = o2::soa::Join; + using FemtoSigmaPlus = o2::soa::Join; + using FemtoTracks = o2::soa::Join; - using FemtoSigmasWithLabel = o2::soa::Join; - using FemtoSigmaPlusWithLabel = o2::soa::Join; - using FemtoTracksWithLabel = o2::soa::Join; + using FemtoSigmasWithLabel = o2::soa::Join; + using FemtoSigmaPlusWithLabel = o2::soa::Join; + using FemtoTracksWithLabel = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // setup for collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::CollisionHistManager colHistManager; colhistmanager::ConfCollisionBinning confCollisionBinning; @@ -75,11 +74,14 @@ struct FemtoKinkQa { // setup for sigmas kinkbuilder::ConfSigmaSelection1 confSigmaSelection; - Partition sigmaPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); - Preslice perColSigmas = femtobase::stored::fColId; + particlecleaner::ConfSigmaCleaner1 confSigmaCleaner; + particlecleaner::ParticleCleaner sigmaCleaner; - Partition sigmaWithLabelPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); - Preslice perColSigmasWithLabel = femtobase::stored::fColId; + o2::framework::Partition sigmaPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); + o2::framework::Preslice perColSigmas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition sigmaWithLabelPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); + o2::framework::Preslice perColSigmasWithLabel = o2::aod::femtobase::stored::fColId; kinkhistmanager::ConfSigmaBinning1 confSigmaBinning; kinkhistmanager::ConfSigmaQaBinning1 confSigmaQaBinning; @@ -92,11 +94,14 @@ struct FemtoKinkQa { // setup for sigma plus kinkbuilder::ConfSigmaPlusSelection1 confSigmaPlusSelection; - Partition sigmaPlusPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaPlusSelection); - Preslice perColSigmaPlus = femtobase::stored::fColId; + particlecleaner::ConfSigmaPlusCleaner1 confSigmaPlusCleaner; + particlecleaner::ParticleCleaner sigmaPlusCleaner; + + o2::framework::Partition sigmaPlusPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaPlusSelection); + o2::framework::Preslice perColSigmaPlus = o2::aod::femtobase::stored::fColId; - Partition sigmaPlusWithLabelPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaSelection); - Preslice perColSigmaPlussWithLabel = femtobase::stored::fColId; + o2::framework::Partition sigmaPlusWithLabelPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaSelection); + o2::framework::Preslice perColSigmaPlussWithLabel = o2::aod::femtobase::stored::fColId; kinkhistmanager::ConfSigmaPlusBinning1 confSigmaPlusBinning; kinkhistmanager::ConfSigmaPlusQaBinning1 confSigmaPlusQaBinning; @@ -110,9 +115,9 @@ struct FemtoKinkQa { trackhistmanager::ConfKinkChaDauBinning confKinkChaDaughterBinning; trackhistmanager::ConfKinkChaDauQaBinning confKinkChaDaughterQaBinning; - HistogramRegistry hRegistry{"FemtoKinkQa", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoKinkQa", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) + void init(o2::framework::InitContext&) { if ((doprocessSigma + doprocessSigmaMc + doprocessSigmaPlus + doprocessSigmaPlusMc) > 1) { LOG(fatal) << "Only one process can be activated"; @@ -120,28 +125,36 @@ struct FemtoKinkQa { bool processData = doprocessSigma || doprocessSigmaPlus; + sigmaCleaner.init(confSigmaCleaner); + sigmaPlusCleaner.init(confSigmaPlusCleaner); + + std::map> colHistSpec; + std::map> chaDauHistSpec; + std::map> sigmaHistSpec; + std::map> sigmaPlusHistSpec; + if (processData) { - auto colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto chaDauHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confKinkChaDaughterBinning, confKinkChaDaughterQaBinning); + colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + chaDauHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confKinkChaDaughterBinning, confKinkChaDaughterQaBinning); if (doprocessSigma) { - auto sigmaHistSpec = kinkhistmanager::makeKinkQaHistSpecMap(confSigmaBinning, confSigmaQaBinning); + sigmaHistSpec = kinkhistmanager::makeKinkQaHistSpecMap(confSigmaBinning, confSigmaQaBinning); sigmaHistManager.init(&hRegistry, sigmaHistSpec, confSigmaSelection, confSigmaQaBinning, chaDauHistSpec, confKinkChaDaughterQaBinning); } if (doprocessSigmaPlus) { - auto sigmaPlusHistSpec = kinkhistmanager::makeKinkQaHistSpecMap(confSigmaPlusBinning, confSigmaPlusQaBinning); + sigmaPlusHistSpec = kinkhistmanager::makeKinkQaHistSpecMap(confSigmaPlusBinning, confSigmaPlusQaBinning); sigmaPlusHistManager.init(&hRegistry, sigmaPlusHistSpec, confSigmaPlusSelection, confSigmaPlusQaBinning, chaDauHistSpec, confKinkChaDaughterQaBinning); } } else { - auto colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto chaDauHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confKinkChaDaughterBinning, confKinkChaDaughterQaBinning); + colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + chaDauHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confKinkChaDaughterBinning, confKinkChaDaughterQaBinning); if (doprocessSigmaMc) { - auto sigmaHistSpec = kinkhistmanager::makeKinkMcQaHistSpecMap(confSigmaBinning, confSigmaQaBinning); + sigmaHistSpec = kinkhistmanager::makeKinkMcQaHistSpecMap(confSigmaBinning, confSigmaQaBinning); sigmaHistManager.init(&hRegistry, sigmaHistSpec, confSigmaSelection, confSigmaQaBinning, chaDauHistSpec, confKinkChaDaughterQaBinning); } if (doprocessSigmaPlusMc) { - auto sigmaPlusHistSpec = kinkhistmanager::makeKinkMcQaHistSpecMap(confSigmaPlusBinning, confSigmaPlusQaBinning); + sigmaPlusHistSpec = kinkhistmanager::makeKinkMcQaHistSpecMap(confSigmaPlusBinning, confSigmaPlusQaBinning); sigmaPlusHistManager.init(&hRegistry, sigmaPlusHistSpec, confSigmaPlusSelection, confSigmaPlusQaBinning, chaDauHistSpec, confKinkChaDaughterQaBinning); } } @@ -150,19 +163,22 @@ struct FemtoKinkQa { void processSigma(FilteredFemtoCollision const& col, FemtoSigmas const& /*sigmas*/, FemtoTracks const& tracks) { - colHistManager.fill(col); - auto sigmaSlice = sigmaPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, 0, 0, 0); + auto sigmaSlice = sigmaPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& sigma : sigmaSlice) { sigmaHistManager.fill(sigma, tracks); } } PROCESS_SWITCH(FemtoKinkQa, processSigma, "Process sigmas", true); - void processSigmaMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmasWithLabel const& /*sigmas*/, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processSigmaMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmasWithLabel const& /*sigmas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - colHistManager.fill(col, mcCols); - auto sigmaSlice = sigmaWithLabelPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, mcCols, 0, 0, 0); + auto sigmaSlice = sigmaWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& sigma : sigmaSlice) { + if (!sigmaCleaner.isClean(sigma, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } sigmaHistManager.fill(sigma, tracks, mcParticles, mcMothers, mcPartonicMothers); } } @@ -170,9 +186,9 @@ struct FemtoKinkQa { void processSigmaPlus(FilteredFemtoCollision const& col, FemtoSigmaPlus const& /*sigmaplus*/, FemtoTracks const& tracks) { - colHistManager.fill(col); + colHistManager.fill(col, 0, 0, 0); - auto sigmaplusSlice = sigmaPlusPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + auto sigmaplusSlice = sigmaPlusPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& sp : sigmaplusSlice) { sigmaPlusHistManager.fill(sp, tracks); @@ -180,20 +196,23 @@ struct FemtoKinkQa { } PROCESS_SWITCH(FemtoKinkQa, processSigmaPlus, "Process sigma plus", false); - void processSigmaPlusMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmaPlusWithLabel const& /*sigmaPlus*/, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processSigmaPlusMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmaPlusWithLabel const& /*sigmaPlus*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - colHistManager.fill(col, mcCols); - auto sigmaPlusSlice = sigmaPlusWithLabelPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, mcCols, 0, 0, 0); + auto sigmaPlusSlice = sigmaPlusWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& sigmaPlus : sigmaPlusSlice) { + if (!sigmaPlusCleaner.isClean(sigmaPlus, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } sigmaPlusHistManager.fill(sigmaPlus, tracks, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoKinkQa, processSigmaPlusMc, "Process sigmas", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoPairTrackCascade.cxx b/PWGCF/Femto/Tasks/femtoPairTrackCascade.cxx index 905817348fd..9430fa71eef 100644 --- a/PWGCF/Femto/Tasks/femtoPairTrackCascade.cxx +++ b/PWGCF/Femto/Tasks/femtoPairTrackCascade.cxx @@ -21,57 +21,65 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/pairBuilder.h" #include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/BinningPolicy.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2; -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoPairTrackCascade { // setup tables - using Collisions = Join; - using Collision = Collisions::iterator; + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FilteredCollisions = o2::soa::Filtered; - using FilteredCollision = FilteredCollisions::iterator; + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using Tracks = o2::soa::Join; - using Xis = o2::soa::Join; - using Omegas = o2::soa::Join; + using FemtoTracks = o2::soa::Join; + using FemtoXis = o2::soa::Join; + using FemtoOmegas = o2::soa::Join; - SliceCache cache; + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoXisWithLabel = o2::soa::Join; + using FemtoOmegasWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::ConfCollisionBinning confCollisionBinning; // setup tracks - trackbuilder::ConfTrackSelection1 trackSelection; + trackbuilder::ConfTrackSelection1 confTrackSelection; trackhistmanager::ConfTrackBinning1 confTrackBinning; - Partition trackPartition = MAKE_TRACK_PARTITION(trackSelection); - Preslice perColTracks = aod::femtobase::stored::fColId; + particlecleaner::ConfTrackCleaner1 confTrackCleaner; + + o2::framework::Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColTracks = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; // setup for daughters/bachelor trackhistmanager::ConfCascadePosDauBinning confPosDauBinning; @@ -79,16 +87,26 @@ struct FemtoPairTrackCascade { trackhistmanager::ConfCascadeBachelorBinning confBachelorBinning; // setup xis - cascadebuilder::ConfXiSelection xiSelection; + cascadebuilder::ConfXiSelection confXiSelection; cascadehistmanager::ConfXiBinning confXiBinning; - Partition xiPartition = MAKE_CASCADE_PARTITION(xiSelection); - Preslice perColXis = aod::femtobase::stored::fColId; + particlecleaner::ConfXiCleaner1 confXiCleaner; + + o2::framework::Partition xiPartition = MAKE_CASCADE_PARTITION(confXiSelection); + o2::framework::Preslice perColXis = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition xiWithLabelPartition = MAKE_CASCADE_PARTITION(confXiSelection); + o2::framework::Preslice perColXisWithLabel = o2::aod::femtobase::stored::fColId; // setup omegas - cascadebuilder::ConfOmegaSelection omegaSelection; + cascadebuilder::ConfOmegaSelection confOmegaSelection; cascadehistmanager::ConfOmegaBinning confOmegaBinning; - Partition omegaPartition = MAKE_CASCADE_PARTITION(omegaSelection); - Preslice perColOmegas = aod::femtobase::stored::fColId; + particlecleaner::ConfOmegaCleaner1 confOmegaCleaner; + + o2::framework::Partition omegaPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); + o2::framework::Preslice perColOmegas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition omegaWithLabelPartition = MAKE_CASCADE_PARTITION(confOmegaSelection); + o2::framework::Preslice perColOmegasWithLabel = o2::aod::femtobase::stored::fColId; // setup pairs pairhistmanager::ConfPairBinning confPairBinning; @@ -128,19 +146,32 @@ struct FemtoPairTrackCascade { std::vector defaultVtxBins{10, -10, 10}; std::vector defaultMultBins{50, 0, 200}; std::vector defaultCentBins{10, 0, 100}; - ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; - ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; - ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; pairhistmanager::ConfMixing confMixing; - HistogramRegistry hRegistry{"FemtoTrackCascade", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoTrackCascade", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; // setup cpr closepairrejection::ConfCprTrackCascadeBachelor confCprBachelor; closepairrejection::ConfCprTrackV0Daughter confCprV0Daughter; - void init(InitContext&) + void init(o2::framework::InitContext&) { + bool processData = doprocessXiSameEvent || doprocessXiMixedEvent || doprocessOmegaSameEvent || doprocessOmegaMixedEvent; + bool processMc = doprocessXiSameEventMc || doprocessXiMixedEventMc || doprocessOmegaSameEventMc || doprocessOmegaMixedEventMc; + + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is enabled. Breaking..."; + } + + bool processXi = doprocessXiSameEvent || doprocessXiSameEventMc || doprocessXiMixedEvent || doprocessXiMixedEventMc; + bool processOmega = doprocessOmegaSameEvent || doprocessOmegaSameEventMc || doprocessOmegaMixedEvent || doprocessOmegaMixedEventMc; + + if (processXi && processOmega) { + LOG(fatal) << "Both xi-track and omega-track processing is enabled. Breaking..."; + } // setup columnpolicy for binning // default values are used during instantiation, so we need to explicity update them here @@ -148,63 +179,105 @@ struct FemtoPairTrackCascade { mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; - // setup histograms - auto colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); - auto trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); - auto bachelorHistSpec = trackhistmanager::makeTrackHistSpecMap(confBachelorBinning); - auto posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); - auto negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); - auto pairHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - auto cprHistSpecBachelor = closepairrejection::makeCprHistSpecMap(confCprBachelor); - auto cprHistSpecV0Daughter = closepairrejection::makeCprHistSpecMap(confCprV0Daughter); - - // setup for xis - if (doprocessXiSameEvent || doprocessXiMixedEvent) { - auto xiHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confXiBinning); - auto pairTrackXiHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairTrackXiBuilder.init(&hRegistry, trackSelection, xiSelection, confCprBachelor, confCprV0Daughter, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, xiHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, pairTrackXiHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter); - } - - // setup for omegas - if (doprocessOmegaSameEvent || doprocessOmegaMixedEvent) { - auto omegaHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confOmegaBinning); - auto pairTrackOmegaHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairTrackOmegaBuilder.init(&hRegistry, trackSelection, xiSelection, confCprBachelor, confCprV0Daughter, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, omegaHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, pairTrackOmegaHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter); - } - - if (((doprocessXiSameEvent || doprocessXiMixedEvent) + (doprocessOmegaSameEvent || doprocessOmegaMixedEvent)) > 1) { - LOG(fatal) << "Can only process xi-tracks Or omega-tracks"; + std::map> colHistSpec; + std::map> trackHistSpec; + std::map> bachelorHistSpec; + std::map> posDauSpec; + std::map> negDauSpec; + std::map> xiHistSpec; + std::map> omegaHistSpec; + std::map> pairTrackCascadeHistSpec; + + std::map> cprHistSpecBachelor = closepairrejection::makeCprHistSpecMap(confCprBachelor); + std::map> cprHistSpecV0Daughter = closepairrejection::makeCprHistSpecMap(confCprV0Daughter); + + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); + bachelorHistSpec = trackhistmanager::makeTrackHistSpecMap(confBachelorBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + pairTrackCascadeHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + if (processXi) { + xiHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confXiBinning); + pairTrackCascadeHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairTrackXiBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confXiSelection, confXiCleaner, confCprBachelor, confCprV0Daughter, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, xiHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, pairTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter); + } else { + omegaHistSpec = cascadehistmanager::makeCascadeHistSpecMap(confOmegaBinning); + pairTrackCascadeHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairTrackOmegaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confOmegaSelection, confOmegaCleaner, confCprBachelor, confCprV0Daughter, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, omegaHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, pairTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter); + } + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning); + bachelorHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confBachelorBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + pairTrackCascadeHistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + if (processXi) { + xiHistSpec = cascadehistmanager::makeCascadeMcHistSpecMap(confXiBinning); + pairTrackCascadeHistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairTrackXiBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confXiSelection, confXiCleaner, confCprBachelor, confCprV0Daughter, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, xiHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, pairTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter); + } else { + omegaHistSpec = cascadehistmanager::makeCascadeMcHistSpecMap(confOmegaBinning); + pairTrackCascadeHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairTrackOmegaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confOmegaSelection, confOmegaCleaner, confCprBachelor, confCprV0Daughter, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, omegaHistSpec, bachelorHistSpec, posDauSpec, negDauSpec, pairTrackCascadeHistSpec, cprHistSpecBachelor, cprHistSpecV0Daughter); + } } }; - void processXiSameEvent(FilteredCollision const& col, Tracks const& tracks, Xis const& xis) + void processXiSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoXis const& xis) { pairTrackXiBuilder.processSameEvent(col, tracks, trackPartition, xis, xiPartition, cache); } PROCESS_SWITCH(FemtoPairTrackCascade, processXiSameEvent, "Enable processing same event processing for tracks and xis", true); - void processXiMixedEvent(FilteredCollisions const& cols, Tracks const& tracks, Xis const& /*xis*/) + void processXiSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& xis, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairTrackXiBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition, xis, xiWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairTrackCascade, processXiSameEventMc, "Enable processing same event processing for tracks and xis with mc information", false); + + void processXiMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoXis const& /*xis*/) { pairTrackXiBuilder.processMixedEvent(cols, tracks, trackPartition, xiPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackCascade, processXiMixedEvent, "Enable processing mixed event processing for tracks and xis", true); - void processOmegaSameEvent(FilteredCollision const& col, Tracks const& tracks, Omegas const& omegas) + void processXiMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& /*xis*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairTrackXiBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, xiWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairTrackCascade, processXiMixedEventMc, "Enable processing mixed event processing for tracks and xis with mc information", false); + + void processOmegaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoOmegas const& omegas) { pairTrackOmegaBuilder.processSameEvent(col, tracks, trackPartition, omegas, omegaPartition, cache); } PROCESS_SWITCH(FemtoPairTrackCascade, processOmegaSameEvent, "Enable processing same event processing for tracks and omegas", false); - void processOmegaMixedEvent(FilteredCollisions const& cols, Tracks const& tracks, Omegas const& /*omegas*/) + void processOmegaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoOmegasWithLabel const& omegas, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairTrackOmegaBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition, omegas, omegaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairTrackCascade, processOmegaSameEventMc, "Enable processing same event processing for tracks and omegas with mc information", false); + + void processOmegaMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoOmegas const& /*omegas*/) { pairTrackOmegaBuilder.processMixedEvent(cols, tracks, trackPartition, omegaPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackCascade, processOmegaMixedEvent, "Enable processing mixed event processing for tracks and omegas", false); + + void processOmegaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoXisWithLabel const& /*xis*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairTrackOmegaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, omegaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairTrackCascade, processOmegaMixedEventMc, "Enable processing mixed event processing for tracks and omegas with mc information", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoPairTrackKink.cxx b/PWGCF/Femto/Tasks/femtoPairTrackKink.cxx index 438c91b474c..2132de4073e 100644 --- a/PWGCF/Femto/Tasks/femtoPairTrackKink.cxx +++ b/PWGCF/Femto/Tasks/femtoPairTrackKink.cxx @@ -22,67 +22,65 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/pairBuilder.h" #include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/BinningPolicy.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2; -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoPairTrackKink { // setup tables - using FemtoCollisions = Join; + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoCollisionsWithLabel = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using FemtoTracks = o2::soa::Join; - using FemtoSigmas = o2::soa::Join; - using FemtoSigmaPlus = o2::soa::Join; + using FemtoTracks = o2::soa::Join; + using FemtoSigmas = o2::soa::Join; + using FemtoSigmaPlus = o2::soa::Join; - using FemtoTracksWithLabel = o2::soa::Join; - using FemtoSigmasWithLabel = o2::soa::Join; - using FemtoSigmaPlusWithLabel = o2::soa::Join; + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoSigmasWithLabel = o2::soa::Join; + using FemtoSigmaPlusWithLabel = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::ConfCollisionBinning confCollisionBinning; // setup tracks trackbuilder::ConfTrackSelection1 confTrackSelection; trackhistmanager::ConfTrackBinning1 confTrackBinning; + particlecleaner::ConfTrackCleaner1 confTrackCleaner; - Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); - Preslice perColTracks = aod::femtobase::stored::fColId; + o2::framework::Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColTracks = o2::aod::femtobase::stored::fColId; - Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); - Preslice perColtracksWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; // setup for daughters trackhistmanager::ConfKinkChaDauBinning confChaDauBinning; @@ -90,22 +88,24 @@ struct FemtoPairTrackKink { // setup sigmas kinkbuilder::ConfSigmaSelection1 confSigmaSelection; kinkhistmanager::ConfSigmaBinning1 confSigmaBinning; + particlecleaner::ConfSigmaCleaner1 confSigmaCleaner; - Partition sigmaPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); - Preslice perColSigmas = aod::femtobase::stored::fColId; + o2::framework::Partition sigmaPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); + o2::framework::Preslice perColSigmas = o2::aod::femtobase::stored::fColId; - Partition sigmaWithLabelPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); - Preslice perColSigmasWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition sigmaWithLabelPartition = MAKE_SIGMA_PARTITION(confSigmaSelection); + o2::framework::Preslice perColSigmasWithLabel = o2::aod::femtobase::stored::fColId; // setup for sigma plus kinkbuilder::ConfSigmaPlusSelection1 confSigmaPlusSelection; kinkhistmanager::ConfSigmaPlusBinning1 confSigmaPlusBinning; + particlecleaner::ConfSigmaPlusCleaner1 confSigmaPlusCleaner; - Partition sigmaPlusPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaPlusSelection); - Preslice perColSigmaPlus = aod::femtobase::stored::fColId; + o2::framework::Partition sigmaPlusPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaPlusSelection); + o2::framework::Preslice perColSigmaPlus = o2::aod::femtobase::stored::fColId; - Partition sigmaPlusWithLabelPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaPlusSelection); - Preslice perColSigmaPlusWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition sigmaPlusWithLabelPartition = MAKE_SIGMAPLUS_PARTITION(confSigmaPlusSelection); + o2::framework::Preslice perColSigmaPlusWithLabel = o2::aod::femtobase::stored::fColId; // setup pairs pairhistmanager::ConfPairBinning confPairBinning; @@ -137,17 +137,17 @@ struct FemtoPairTrackKink { std::vector defaultVtxBins{10, -10, 10}; std::vector defaultMultBins{50, 0, 200}; std::vector defaultCentBins{10, 0, 100}; - ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; - ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; - ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; pairhistmanager::ConfMixing confMixing; - HistogramRegistry hRegistry{"FemtoTrackKink", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoTrackKink", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; // setup cpr closepairrejection::ConfCprTrackKinkDaughter confCpr; - void init(InitContext&) + void init(o2::framework::InitContext&) { bool processData = doprocessSigmaSameEvent || doprocessSigmaMixedEvent || doprocessSigmaPlusSameEvent || doprocessSigmaPlusMixedEvent; bool processMc = doprocessSigmaSameEventMc || doprocessSigmaMixedEventMc || doprocessSigmaPlusSameEventMc || doprocessSigmaPlusMixedEventMc; @@ -169,31 +169,37 @@ struct FemtoPairTrackKink { mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; - auto cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); + std::map> colHistSpec; + std::map> trackHistSpec; + std::map> chaDauSpec; + std::map> sigmaHistSpec; + std::map> sigmaPlusHistSpec; + std::map> pairTrackKinkHistSpec; + std::map> cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); if (processData) { - auto colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); - auto trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); - auto chaDauSpec = trackhistmanager::makeTrackHistSpecMap(confChaDauBinning); - auto pairTrackKinkHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); + chaDauSpec = trackhistmanager::makeTrackHistSpecMap(confChaDauBinning); + pairTrackKinkHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); if (processSigma) { - auto sigmaHistSpec = kinkhistmanager::makeKinkHistSpecMap(confSigmaBinning); - pairTrackSigmaBuilder.init(&hRegistry, confTrackSelection, confSigmaSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); + sigmaHistSpec = kinkhistmanager::makeKinkHistSpecMap(confSigmaBinning); + pairTrackSigmaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confSigmaSelection, confSigmaCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); } else { - auto sigmaplusHistSpec = kinkhistmanager::makeKinkHistSpecMap(confSigmaPlusBinning); - pairTrackSigmaPlusBuilder.init(&hRegistry, confTrackSelection, confSigmaPlusSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaplusHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); + sigmaPlusHistSpec = kinkhistmanager::makeKinkHistSpecMap(confSigmaPlusBinning); + pairTrackSigmaPlusBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confSigmaPlusSelection, confSigmaPlusCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaPlusHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); } } else { - auto colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); - auto trackHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning); - auto chaDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confChaDauBinning); - auto pairTrackKinkHistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning); + chaDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confChaDauBinning); + pairTrackKinkHistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); if (processSigma) { - auto sigmaHistSpec = kinkhistmanager::makeKinkMcHistSpecMap(confSigmaBinning); - pairTrackSigmaBuilder.init(&hRegistry, confTrackSelection, confSigmaSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); + sigmaHistSpec = kinkhistmanager::makeKinkMcHistSpecMap(confSigmaBinning); + pairTrackSigmaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confSigmaSelection, confSigmaCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); } else { - auto sigmaplusHistSpec = kinkhistmanager::makeKinkMcHistSpecMap(confSigmaPlusBinning); - pairTrackSigmaPlusBuilder.init(&hRegistry, confTrackSelection, confSigmaPlusSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaplusHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); + sigmaPlusHistSpec = kinkhistmanager::makeKinkMcHistSpecMap(confSigmaPlusBinning); + pairTrackSigmaPlusBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, confSigmaPlusSelection, confSigmaPlusCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, sigmaPlusHistSpec, chaDauSpec, pairTrackKinkHistSpec, cprHistSpec); } } hRegistry.print(); @@ -205,7 +211,7 @@ struct FemtoPairTrackKink { } PROCESS_SWITCH(FemtoPairTrackKink, processSigmaSameEvent, "Enable processing same event processing for tracks and sigmas", true); - void processSigmaSameEventMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmasWithLabel const& sigmas, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processSigmaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmasWithLabel const& sigmas, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { pairTrackSigmaBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition, sigmas, sigmaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); } @@ -217,9 +223,9 @@ struct FemtoPairTrackKink { } PROCESS_SWITCH(FemtoPairTrackKink, processSigmaMixedEvent, "Enable processing mixed event processing for tracks and sigmas", true); - void processSigmaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmasWithLabel const& /*sigmas*/, FMcParticles const& mcParticles) + void processSigmaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmasWithLabel const& /*sigmas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairTrackSigmaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, sigmaWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairTrackSigmaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, sigmaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackKink, processSigmaMixedEventMc, "Enable processing mixed event processing for tracks and sigmas with MC information", false); @@ -229,7 +235,7 @@ struct FemtoPairTrackKink { } PROCESS_SWITCH(FemtoPairTrackKink, processSigmaPlusSameEvent, "Enable processing same event processing for tracks and sigma plus", false); - void processSigmaPlusSameEventMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmaPlusWithLabel const& sigmaplus, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processSigmaPlusSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmaPlusWithLabel const& sigmaplus, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { pairTrackSigmaPlusBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition, sigmaplus, sigmaPlusWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); } @@ -241,16 +247,16 @@ struct FemtoPairTrackKink { } PROCESS_SWITCH(FemtoPairTrackKink, processSigmaPlusMixedEvent, "Enable processing mixed event processing for tracks and sigma plus", false); - void processSigmaPlusMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmaPlusWithLabel const& /*sigmaplus*/, FMcParticles const& mcParticles) + void processSigmaPlusMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoSigmaPlusWithLabel const& /*sigmaplus*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairTrackSigmaPlusBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, sigmaPlusWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairTrackSigmaPlusBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, sigmaPlusWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackKink, processSigmaPlusMixedEventMc, "Enable processing mixed event processing for tracks and sigma plus with MC information", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoPairTrackTrack.cxx b/PWGCF/Femto/Tasks/femtoPairTrackTrack.cxx index f8a647dfcfe..deb7c1164d8 100644 --- a/PWGCF/Femto/Tasks/femtoPairTrackTrack.cxx +++ b/PWGCF/Femto/Tasks/femtoPairTrackTrack.cxx @@ -19,67 +19,74 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/pairBuilder.h" #include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/BinningPolicy.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2; -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoPairTrackTrack { // setup tables - using FemtoCollisions = Join; + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoCollisionsWithLabel = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using FemtoTracks = o2::soa::Join; + using FemtoTracks = o2::soa::Join; - using FemtoTracksWithLabel = o2::soa::Join; + // for analysis which require particles at high pt, add tof mass so sidebands can be used + using FemtoTracksWithMass = o2::soa::Join; - SliceCache cache; + using FemtoTracksWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::ConfCollisionBinning confCollisionBinning; // setup tracks trackbuilder::ConfTrackSelection1 confTrackSelections1; + particlecleaner::ConfTrackCleaner1 confTrackCleaner1; trackhistmanager::ConfTrackBinning1 confTrackBinning1; + trackbuilder::ConfTrackSelection2 confTrackSelections2; + particlecleaner::ConfTrackCleaner2 confTrackCleaner2; trackhistmanager::ConfTrackBinning2 confTrackBinning2; - Partition trackPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); - Partition trackPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); - Preslice perColtracks = aod::femtobase::stored::fColId; + o2::framework::Partition trackPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Preslice perColtracks = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition trackWithMassPartition1 = MAKE_TRACK_PARTITION_WITH_MASS(confTrackSelections1); + o2::framework::Partition trackWithMassPartition2 = MAKE_TRACK_PARTITION_WITH_MASS(confTrackSelections2); + o2::framework::Preslice perColtracksWithMass = o2::aod::femtobase::stored::fColId; - Partition trackWithLabelPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); - Partition trackWithLabelPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); - Preslice perColtracksWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition trackWithLabelPartition1 = MAKE_TRACK_PARTITION_WITH_MASS(confTrackSelections1); + o2::framework::Partition trackWithLabelPartition2 = MAKE_TRACK_PARTITION_WITH_MASS(confTrackSelections2); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; // setup pairs pairhistmanager::ConfPairBinning confPairBinning; @@ -100,19 +107,19 @@ struct FemtoPairTrackTrack { std::vector defaultVtxBins{10, -10, 10}; std::vector defaultMultBins{50, 0, 200}; std::vector defaultCentBins{10, 0, 100}; - ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; - ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; - ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; pairhistmanager::ConfMixing confMixing; - HistogramRegistry hRegistry{"FemtoTrackTrack", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoTrackTrack", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) + void init(o2::framework::InitContext&) { - if ((doprocessSameEvent + doprocessSameEventMc) > 1 || (doprocessMixedEvent + doprocessMixedEventMc) > 1) { + if ((doprocessSameEvent + doprocessSameEventWithMass + doprocessSameEventMc) > 1 || (doprocessMixedEvent + doprocessMixedEventWithMass + doprocessMixedEventMc) > 1) { LOG(fatal) << "More than 1 same or mixed event process function is activated. Breaking..."; } - bool processData = doprocessSameEvent || doprocessMixedEvent; + bool processData = doprocessSameEvent || doprocessMixedEvent || doprocessSameEventWithMass || doprocessMixedEventWithMass; bool processMc = doprocessSameEventMc || doprocessMixedEventMc; if (processData && processMc) { LOG(fatal) << "Both data and mc processing is activated. Breaking..."; @@ -125,20 +132,24 @@ struct FemtoPairTrackTrack { mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; // setup histogram specs - auto cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); + std::map> colHistSpec; + std::map> trackHistSpec1; + std::map> trackHistSpec2; + std::map> pairHistSpec; + std::map> cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); if (processData) { - auto colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); - auto trackHistSpec1 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning1); - auto trackHistSpec2 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning2); - auto pairHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairTrackTrackBuilder.init(&hRegistry, confTrackSelections1, confTrackSelections2, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec1, trackHistSpec2, pairHistSpec, cprHistSpec); + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning2); + pairHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairTrackTrackBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackCleaner1, confTrackCleaner2, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec1, trackHistSpec2, pairHistSpec, cprHistSpec); } else { - auto colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); - auto trackHistSpec1 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning1); - auto trackHistSpec2 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning2); - auto pairHistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); - pairTrackTrackBuilder.init(&hRegistry, confTrackSelections1, confTrackSelections2, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec1, trackHistSpec2, pairHistSpec, cprHistSpec); + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning2); + pairHistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairTrackTrackBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackCleaner1, confTrackCleaner2, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec1, trackHistSpec2, pairHistSpec, cprHistSpec); } hRegistry.print(); }; @@ -149,7 +160,13 @@ struct FemtoPairTrackTrack { } PROCESS_SWITCH(FemtoPairTrackTrack, processSameEvent, "Enable processing same event processing", true); - void processSameEventMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processSameEventWithMass(FilteredFemtoCollision const& col, FemtoTracksWithMass const& tracks) + { + pairTrackTrackBuilder.processSameEvent(col, tracks, trackWithMassPartition1, trackWithMassPartition2, cache); + } + PROCESS_SWITCH(FemtoPairTrackTrack, processSameEventWithMass, "Enable processing same event processing (with track masses)", false); + + void processSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { pairTrackTrackBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, mcParticles, mcMothers, mcPartonicMothers, cache); } @@ -161,16 +178,22 @@ struct FemtoPairTrackTrack { } PROCESS_SWITCH(FemtoPairTrackTrack, processMixedEvent, "Enable processing mixed event processing", true); - void processMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FMcParticles const& mcParticles) + void processMixedEventWithMass(FilteredFemtoCollisions const& cols, FemtoTracksWithMass const& tracks) + { + pairTrackTrackBuilder.processMixedEvent(cols, tracks, trackWithMassPartition1, trackWithMassPartition2, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairTrackTrack, processMixedEventWithMass, "Enable processing mixed event processing (with track masses)", false); + + void processMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairTrackTrackBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairTrackTrackBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackTrack, processMixedEventMc, "Enable processing mixed event processing", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoPairTrackTwoTrackResonance.cxx b/PWGCF/Femto/Tasks/femtoPairTrackTwoTrackResonance.cxx index e3a43c5b67e..db7e18ba53b 100644 --- a/PWGCF/Femto/Tasks/femtoPairTrackTwoTrackResonance.cxx +++ b/PWGCF/Femto/Tasks/femtoPairTrackTwoTrackResonance.cxx @@ -26,16 +26,16 @@ #include "PWGCF/Femto/Core/twoTrackResonanceHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/BinningPolicy.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -177,21 +177,21 @@ struct FemtoPairTrackTwoTrackResonance { if (doprocessPhiSameEvent || doprocessPhiMixedEvent) { auto phiHistSpec = twotrackresonancehistmanager::makeTwoTrackResonanceHistSpecMap(confPhiBinning); auto pairTrackPhiHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairTrackPhiBuilder.init(&hRegistry, trackSelection, phiSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, phiHistSpec, posDauSpec, negDauSpec, pairTrackPhiHistSpec, cprHistSpec); + pairTrackPhiBuilder.init(&hRegistry, confCollisionBinning, trackSelection, phiSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, phiHistSpec, posDauSpec, negDauSpec, pairTrackPhiHistSpec, cprHistSpec); } // setup for kstar0 if (doprocessKstar0SameEvent || doprocessKstar0MixedEvent) { auto kstar0HistSpec = twotrackresonancehistmanager::makeTwoTrackResonanceHistSpecMap(confKstar0Binning); auto pairTrackKstar0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairTrackKstar0Builder.init(&hRegistry, trackSelection, kstar0Selection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, kstar0HistSpec, posDauSpec, negDauSpec, pairTrackKstar0HistSpec, cprHistSpec); + pairTrackKstar0Builder.init(&hRegistry, confCollisionBinning, trackSelection, kstar0Selection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, kstar0HistSpec, posDauSpec, negDauSpec, pairTrackKstar0HistSpec, cprHistSpec); } // setup for kstar0 if (doprocessRho0SameEvent || doprocessRho0MixedEvent) { auto rho0HistSpec = twotrackresonancehistmanager::makeTwoTrackResonanceHistSpecMap(confRho0Binning); auto pairTrackRho0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairTrackRho0Builder.init(&hRegistry, trackSelection, rho0Selection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, rho0HistSpec, posDauSpec, negDauSpec, pairTrackRho0HistSpec, cprHistSpec); + pairTrackRho0Builder.init(&hRegistry, confCollisionBinning, trackSelection, rho0Selection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, rho0HistSpec, posDauSpec, negDauSpec, pairTrackRho0HistSpec, cprHistSpec); } }; diff --git a/PWGCF/Femto/Tasks/femtoPairTrackV0.cxx b/PWGCF/Femto/Tasks/femtoPairTrackV0.cxx index 550d9778c6b..f112f60b973 100644 --- a/PWGCF/Femto/Tasks/femtoPairTrackV0.cxx +++ b/PWGCF/Femto/Tasks/femtoPairTrackV0.cxx @@ -19,6 +19,7 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/pairBuilder.h" #include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/trackHistManager.h" @@ -26,62 +27,59 @@ #include "PWGCF/Femto/Core/v0HistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/BinningPolicy.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2; -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoPairTrackV0 { // setup tables - using FemtoCollisions = Join; + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoCollisionsWithLabel = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using FemtoTracks = o2::soa::Join; - using FemtoLambdas = o2::soa::Join; - using FemtoK0shorts = o2::soa::Join; + using FemtoTracks = o2::soa::Join; + using FemtoLambdas = o2::soa::Join; + using FemtoK0shorts = o2::soa::Join; - using FemtoTracksWithLabel = o2::soa::Join; - using FemtoLambdasWithLabel = o2::soa::Join; - using FemtoK0shortsWithLabel = o2::soa::Join; + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoLambdasWithLabel = o2::soa::Join; + using FemtoK0shortsWithLabel = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::ConfCollisionBinning confCollisionBinning; // setup tracks trackbuilder::ConfTrackSelection1 confTrackSelection; trackhistmanager::ConfTrackBinning1 confTrackBinning; + particlecleaner::ConfTrackCleaner1 confTrackCleaner; - Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); - Preslice perColTracks = aod::femtobase::stored::fColId; + o2::framework::Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColTracks = o2::aod::femtobase::stored::fColId; - Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); - Preslice perColtracksWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; // setup for daughters trackhistmanager::ConfV0PosDauBinning confPosDauBinning; @@ -90,22 +88,24 @@ struct FemtoPairTrackV0 { // setup lambdas v0builder::ConfLambdaSelection1 lambdaSelection; v0histmanager::ConfLambdaBinning1 confLambdaBinning; + particlecleaner::ConfLambdaCleaner1 confLambdaCleaner; - Partition lambdaPartition = MAKE_LAMBDA_PARTITION(lambdaSelection); - Preslice perColLambdas = aod::femtobase::stored::fColId; + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(lambdaSelection); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; - Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(lambdaSelection); - Preslice perColLambdasWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(lambdaSelection); + o2::framework::Preslice perColLambdasWithLabel = o2::aod::femtobase::stored::fColId; // setup k0shorts v0builder::ConfK0shortSelection1 k0shortSelection; v0histmanager::ConfK0shortBinning1 confK0shortBinning; + particlecleaner::ConfK0shortCleaner1 confK0shortCleaner; - Partition k0shortPartition = MAKE_K0SHORT_PARTITION(k0shortSelection); - Preslice perColk0shorts = aod::femtobase::stored::fColId; + o2::framework::Partition k0shortPartition = MAKE_K0SHORT_PARTITION(k0shortSelection); + o2::framework::Preslice perColk0shorts = o2::aod::femtobase::stored::fColId; - Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(k0shortSelection); - Preslice perColk0shortsWithLabel = aod::femtobase::stored::fColId; + o2::framework::Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(k0shortSelection); + o2::framework::Preslice perColk0shortsWithLabel = o2::aod::femtobase::stored::fColId; // setup pairs pairhistmanager::ConfPairBinning confPairBinning; @@ -139,17 +139,17 @@ struct FemtoPairTrackV0 { std::vector defaultVtxBins{10, -10, 10}; std::vector defaultMultBins{50, 0, 200}; std::vector defaultCentBins{10, 0, 100}; - ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; - ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; - ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; pairhistmanager::ConfMixing confMixing; - HistogramRegistry hRegistry{"FemtoTrackV0", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoTrackV0", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; // setup cpr closepairrejection::ConfCprTrackV0Daughter confCpr; - void init(InitContext&) + void init(o2::framework::InitContext&) { bool processData = doprocessLambdaSameEvent || doprocessLambdaMixedEvent || doprocessK0shortSameEvent || doprocessK0shortMixedEvent; bool processMc = doprocessLambdaSameEventMc || doprocessLambdaMixedEventMc || doprocessK0shortSameEventMc || doprocessK0shortMixedEventMc; @@ -171,33 +171,40 @@ struct FemtoPairTrackV0 { mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; - auto cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); + std::map> colHistSpec; + std::map> trackHistSpec; + std::map> posDauSpec; + std::map> negDauSpec; + std::map> lambdaHistSpec; + std::map> k0shortHistSpec; + std::map> pairTrackV0HistSpec; + std::map> cprHistSpec = closepairrejection::makeCprHistSpecMap(confCpr); if (processData) { - auto colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); - auto trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); - auto posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); - auto negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); - auto pairTrackV0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec = trackhistmanager::makeTrackHistSpecMap(confTrackBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + pairTrackV0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); if (processLambda) { - auto lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); - pairTrackLambdaBuilder.init(&hRegistry, confTrackSelection, lambdaSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); + lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); + pairTrackLambdaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, lambdaSelection, confLambdaCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); } else { - auto k0shortHistSpec = v0histmanager::makeV0HistSpecMap(confK0shortBinning); - pairTrackK0shortBuilder.init(&hRegistry, confTrackSelection, lambdaSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); + k0shortHistSpec = v0histmanager::makeV0HistSpecMap(confK0shortBinning); + pairTrackK0shortBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, lambdaSelection, confTrackCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); } } else { - auto colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); - auto trackHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning); - auto posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); - auto negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); - auto pairTrackV0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + pairTrackV0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); if (processLambda) { - auto lambdaHistSpec = v0histmanager::makeV0McHistSpecMap(confLambdaBinning); - pairTrackLambdaBuilder.init(&hRegistry, confTrackSelection, lambdaSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); + lambdaHistSpec = v0histmanager::makeV0McHistSpecMap(confLambdaBinning); + pairTrackLambdaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, lambdaSelection, confLambdaCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); } else { - auto k0shortHistSpec = v0histmanager::makeV0McHistSpecMap(confK0shortBinning); - pairTrackK0shortBuilder.init(&hRegistry, confTrackSelection, lambdaSelection, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); + k0shortHistSpec = v0histmanager::makeV0McHistSpecMap(confK0shortBinning); + pairTrackK0shortBuilder.init(&hRegistry, confCollisionBinning, confTrackSelection, confTrackCleaner, lambdaSelection, confLambdaCleaner, confCpr, confMixing, confPairBinning, confPairCuts, colHistSpec, trackHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairTrackV0HistSpec, cprHistSpec); } } hRegistry.print(); @@ -209,7 +216,7 @@ struct FemtoPairTrackV0 { } PROCESS_SWITCH(FemtoPairTrackV0, processLambdaSameEvent, "Enable processing same event processing for tracks and lambdas", true); - void processLambdaSameEventMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& lambdas, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processLambdaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& lambdas, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { pairTrackLambdaBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition, lambdas, lambdaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); } @@ -221,9 +228,9 @@ struct FemtoPairTrackV0 { } PROCESS_SWITCH(FemtoPairTrackV0, processLambdaMixedEvent, "Enable processing mixed event processing for tracks and lambdas", true); - void processLambdaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambas*/, FMcParticles const& mcParticles) + void processLambdaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairTrackLambdaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, lambdaWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairTrackLambdaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, lambdaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackV0, processLambdaMixedEventMc, "Enable processing mixed event processing for tracks and lambdas with MC information", false); @@ -233,7 +240,7 @@ struct FemtoPairTrackV0 { } PROCESS_SWITCH(FemtoPairTrackV0, processK0shortSameEvent, "Enable processing same event processing for tracks and k0shorts", false); - void processK0shortSameEventMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& k0shorts, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processK0shortSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& k0shorts, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { pairTrackK0shortBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition, k0shorts, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); } @@ -245,16 +252,16 @@ struct FemtoPairTrackV0 { } PROCESS_SWITCH(FemtoPairTrackV0, processK0shortMixedEvent, "Enable processing mixed event processing for tracks and k0shorts", false); - void processK0shortMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, FMcParticles const& mcParticles) + void processK0shortMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairTrackK0shortBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, k0shortWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairTrackK0shortBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } PROCESS_SWITCH(FemtoPairTrackV0, processK0shortMixedEventMc, "Enable processing mixed event processing for tracks and k0shorts with mc information", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoPairV0V0.cxx b/PWGCF/Femto/Tasks/femtoPairV0V0.cxx index b3cf25d3967..1cf6ffaf677 100644 --- a/PWGCF/Femto/Tasks/femtoPairV0V0.cxx +++ b/PWGCF/Femto/Tasks/femtoPairV0V0.cxx @@ -19,52 +19,54 @@ #include "PWGCF/Femto/Core/modes.h" #include "PWGCF/Femto/Core/pairBuilder.h" #include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" -#include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/Core/v0Builder.h" #include "PWGCF/Femto/Core/v0HistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/BinningPolicy.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2; -using namespace o2::aod; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoPairV0V0 { // setup tables - using Collisions = Join; - using Collision = Collisions::iterator; + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FilteredCollisions = o2::soa::Filtered; - using FilteredCollision = FilteredCollisions::iterator; + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using Tracks = o2::soa::Join; - using Lambdas = o2::soa::Join; - using K0shorts = o2::soa::Join; + using FemtoTracks = o2::soa::Join; + using FemtoLambdas = o2::soa::Join; + using FemtoK0shorts = o2::soa::Join; - SliceCache cache; + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoLambdasWithLabel = o2::soa::Join; + using FemtoK0shortsWithLabel = o2::soa::Join; + // + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::ConfCollisionBinning confCollisionBinning; // setup for daughters @@ -72,16 +74,26 @@ struct FemtoPairV0V0 { trackhistmanager::ConfV0NegDauBinning confNegDauBinning; // setup lambdas - v0builder::ConfLambdaSelection1 lambdaSelection; + v0builder::ConfLambdaSelection1 confLambdaSelection; + particlecleaner::ConfLambdaCleaner1 confLambdaCleaner; v0histmanager::ConfLambdaBinning1 confLambdaBinning; - Partition lambdaPartition = MAKE_LAMBDA_PARTITION(lambdaSelection); - Preslice perColLambdas = aod::femtobase::stored::fColId; + + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Preslice perCollambdasWithLabel = o2::aod::femtobase::stored::fColId; // setup k0shorts - v0builder::ConfK0shortSelection1 k0shortSelection; + v0builder::ConfK0shortSelection1 confK0shortSelection; + particlecleaner::ConfK0shortCleaner1 confK0shortCleaner; v0histmanager::ConfK0shortBinning1 confK0shortBinning; - Partition k0shortPartition = MAKE_K0SHORT_PARTITION(k0shortSelection); - Preslice perColk0shorts = aod::femtobase::stored::fColId; + + o2::framework::Partition k0shortPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColk0shorts = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColk0shortsWithLabel = o2::aod::femtobase::stored::fColId; // setup pairs pairhistmanager::ConfPairBinning confPairBinning; @@ -125,22 +137,32 @@ struct FemtoPairV0V0 { std::vector defaultVtxBins{10, -10, 10}; std::vector defaultMultBins{50, 0, 200}; std::vector defaultCentBins{10, 0, 100}; - ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; - ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; - ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; pairhistmanager::ConfMixing confMixing; - HistogramRegistry hRegistry{"FemtoV0V0", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoV0V0", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; // setup cpr closepairrejection::ConfCprV0DaugherV0DaughterPos confCprPos; closepairrejection::ConfCprV0DaugherV0DaughterNeg confCprNeg; - void init(InitContext&) + void init(o2::framework::InitContext&) { + // TODO: implement lambda-k0short + bool processData = doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaSameEvent || doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortSameEvent; + bool processMc = doprocessLambdaLambdaSameEventMc || doprocessLambdaLambdaSameEventMc || doprocessK0shortK0shortSameEventMc || doprocessK0shortK0shortSameEventMc; + + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is enabled. Breaking..."; + } + + bool processLambdaLambda = doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaMixedEvent || doprocessLambdaLambdaSameEventMc || doprocessLambdaLambdaMixedEventMc; + bool processK0shortK0short = doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent || doprocessK0shortK0shortSameEventMc || doprocessK0shortK0shortMixedEventMc; - if (((doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaMixedEvent) + (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent)) > 1) { - LOG(fatal) << "Can only process lambda-tracks Or k0short-tracks"; + if (processLambdaLambda && processK0shortK0short) { + LOG(fatal) << "Both lambda-lambda and k0short-k0short processing is enabled. Breaking..."; } // setup columnpolicy for binning @@ -150,55 +172,103 @@ struct FemtoPairV0V0 { mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; // setup histograms - auto colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); - auto posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); - auto negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); - auto cprHistSpecPos = closepairrejection::makeCprHistSpecMap(confCprPos); - auto cprHistSpecNeg = closepairrejection::makeCprHistSpecMap(confCprNeg); - - // setup for lambda - if (doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaMixedEvent) { - auto lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); - auto pairLambdaLambdaHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairLambdaLambdaBuilder.init(&hRegistry, lambdaSelection, lambdaSelection, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairLambdaLambdaHistSpec, cprHistSpecPos, cprHistSpecNeg); - } + std::map> colHistSpec; + std::map> trackHistSpec; + std::map> posDauSpec; + std::map> negDauSpec; + std::map> lambdaHistSpec; + std::map> k0shortHistSpec; + std::map> pairV0V0HistSpec; + std::map> cprHistSpecPos = closepairrejection::makeCprHistSpecMap(confCprPos); + std::map> cprHistSpecNeg = closepairrejection::makeCprHistSpecMap(confCprNeg); - // setup for k0short - if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { - auto k0shortHistSpec = v0histmanager::makeV0HistSpecMap(confK0shortBinning); - auto pairK0shortK0shortHistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); - pairK0shortK0shortBuilder.init(&hRegistry, k0shortSelection, k0shortSelection, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairK0shortK0shortHistSpec, cprHistSpecPos, cprHistSpecNeg); + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + if (processLambdaLambda) { + lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); + pairV0V0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairLambdaLambdaBuilder.init(&hRegistry, confCollisionBinning, confLambdaSelection, confLambdaSelection, confLambdaCleaner, confLambdaCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + + // setup for k0short + if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { + k0shortHistSpec = v0histmanager::makeV0HistSpecMap(confK0shortBinning); + pairV0V0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairK0shortK0shortBuilder.init(&hRegistry, confCollisionBinning, confK0shortSelection, confK0shortSelection, confK0shortCleaner, confK0shortCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + if (processLambdaLambda) { + lambdaHistSpec = v0histmanager::makeV0McHistSpecMap(confLambdaBinning); + pairV0V0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairLambdaLambdaBuilder.init(&hRegistry, confCollisionBinning, confLambdaSelection, confLambdaSelection, confLambdaCleaner, confLambdaCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + + // setup for k0short + if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { + k0shortHistSpec = v0histmanager::makeV0McHistSpecMap(confK0shortBinning); + pairV0V0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairK0shortK0shortBuilder.init(&hRegistry, confCollisionBinning, confK0shortSelection, confK0shortSelection, confK0shortCleaner, confK0shortCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } } }; - void processLambdaLambdaSameEvent(FilteredCollision const& col, Tracks const& tracks, Lambdas const& lambdas) + void processLambdaLambdaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoLambdas const& lambdas) { pairLambdaLambdaBuilder.processSameEvent(col, tracks, lambdas, lambdaPartition, lambdaPartition, cache); } - PROCESS_SWITCH(FemtoPairV0V0, processLambdaLambdaSameEvent, "Enable processing same event processing for lambdas", true); + PROCESS_SWITCH(FemtoPairV0V0, processLambdaLambdaSameEvent, "Enable processing same event processing for lambda-lambda", true); + + void processLambdaLambdaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& lambdas, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairLambdaLambdaBuilder.processSameEvent(col, mcCols, tracks, lambdas, lambdaWithLabelPartition, lambdaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairV0V0, processLambdaLambdaSameEventMc, "Enable processing same event processing for lambda-lambda with mc information", false); + + void processLambdaLambdaMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoLambdas const& lambdas) + { + pairLambdaLambdaBuilder.processMixedEvent(cols, tracks, lambdas, lambdaPartition, lambdaPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairV0V0, processLambdaLambdaMixedEvent, "Enable processing mixed event processing for lambda-lambda", true); + + void processLambdaLambdaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambdas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairLambdaLambdaBuilder.processMixedEvent(cols, mcCols, tracks, lambdaWithLabelPartition, lambdaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairV0V0, processLambdaLambdaMixedEventMc, "Enable processing mixed event processing for lambda-lambda with mc information", false); + + void processK0shortK0shortSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoK0shorts const& k0shorts) + { + pairK0shortK0shortBuilder.processSameEvent(col, tracks, k0shorts, k0shortPartition, k0shortPartition, cache); + } + PROCESS_SWITCH(FemtoPairV0V0, processK0shortK0shortSameEvent, "Enable processing same event processing for k0short-k0short", false); - void processLambdaLambdaMixedEvent(FilteredCollisions const& cols, Tracks const& tracks, Lambdas const& /*lambas*/) + void processK0shortK0shortSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& k0shorts, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairLambdaLambdaBuilder.processMixedEvent(cols, tracks, lambdaPartition, lambdaPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairK0shortK0shortBuilder.processSameEvent(col, mcCols, tracks, k0shorts, k0shortWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); } - PROCESS_SWITCH(FemtoPairV0V0, processLambdaLambdaMixedEvent, "Enable processing mixed event processing for lambdas", true); + PROCESS_SWITCH(FemtoPairV0V0, processK0shortK0shortSameEventMc, "Enable processing same event processing for k0short-k0short with mc information", false); - void processK0shortK0shortSameEvent(FilteredCollision const& col, Tracks const& tracks, K0shorts const& k0shorts) + void processK0shortK0shortMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoK0shorts const& k0shorts) { - pairK0shortK0shortBuilder.processSameEvent(col, tracks, k0shorts, k0shortPartition, lambdaPartition, cache); + pairK0shortK0shortBuilder.processMixedEvent(cols, tracks, k0shorts, k0shortPartition, k0shortPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } - PROCESS_SWITCH(FemtoPairV0V0, processK0shortK0shortSameEvent, "Enable processing same event processing for lambdas", false); + PROCESS_SWITCH(FemtoPairV0V0, processK0shortK0shortMixedEvent, "Enable processing mixed event processing for k0short-k0short", false); - void processK0shortK0shortMixedEvent(FilteredCollisions const& cols, Tracks const& tracks, K0shorts const& /*k0shorts*/) + void processK0shortK0shortMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - pairK0shortK0shortBuilder.processMixedEvent(cols, tracks, k0shortPartition, k0shortPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + pairK0shortK0shortBuilder.processMixedEvent(cols, mcCols, tracks, k0shortWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); } - PROCESS_SWITCH(FemtoPairV0V0, processK0shortK0shortMixedEvent, "Enable processing mixed event processing for lambdas", false); + PROCESS_SWITCH(FemtoPairV0V0, processK0shortK0shortMixedEventMc, "Enable processing mixed event processing for k0short-k0short with mc information", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoTrackQa.cxx b/PWGCF/Femto/Tasks/femtoTrackQa.cxx index 52d082ff7fa..25916affb95 100644 --- a/PWGCF/Femto/Tasks/femtoTrackQa.cxx +++ b/PWGCF/Femto/Tasks/femtoTrackQa.cxx @@ -16,47 +16,48 @@ #include "PWGCF/Femto/Core/collisionBuilder.h" #include "PWGCF/Femto/Core/collisionHistManager.h" #include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackBuilder.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoTrackQa { // setup tables - using FemtoCollisions = o2::soa::Join; + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoCollisionsWithLabel = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using FemtoTracks = o2::soa::Join; + using FemtoTracks = o2::soa::Join; - using FemtoTracksWithLabel = o2::soa::Join; + using FemtoTracksWithLabel = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // setup collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::ConfCollisionBinning confCollisionBinning; colhistmanager::ConfCollisionQaBinning confCollisionQaBinning; colhistmanager::CollisionHistManager colHistManager; @@ -67,48 +68,37 @@ struct FemtoTrackQa { trackhistmanager::ConfTrackQaBinning1 confTrackQaBinning; trackhistmanager::TrackHistManager trackHistManager; - Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); - Preslice perColReco = femtobase::stored::fColId; + o2::framework::Partition trackPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColReco = o2::aod::femtobase::stored::fColId; - Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); - Preslice perColRecoWithLabel = femtobase::stored::fColId; + particlecleaner::ConfTrackCleaner1 confTrackCleaner; + particlecleaner::ParticleCleaner trackCleaner; - HistogramRegistry hRegistry{"FemtoTrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::Partition trackWithLabelPartition = MAKE_TRACK_PARTITION(confTrackSelection); + o2::framework::Preslice perColRecoWithLabel = o2::aod::femtobase::stored::fColId; - template - void initMode(MakeColSpec&& makeColSpec, - MakeTrackSpec&& makeTrackSpec) - { - auto colHistSpec = makeColSpec(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto trackHistSpec = makeTrackSpec(confTrackBinning, confTrackQaBinning); - - trackHistManager.init( - &hRegistry, - trackHistSpec, - confTrackSelection.chargeAbs.value, - confTrackSelection.chargeSign.value, - confTrackSelection.pdgCodeAbs.value, - confTrackQaBinning); - } + o2::framework::HistogramRegistry hRegistry{"FemtoTrackQA", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) + void init(o2::framework::InitContext&) { if ((doprocessData + doprocessMc) > 1) { LOG(fatal) << "More than 1 process function is activated. Breaking..."; } bool processData = doprocessData; + trackCleaner.init(confTrackCleaner); + + std::map> colHistSpec; + std::map> trackHistSpec; + if (processData) { - auto colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto trackHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confTrackBinning, confTrackQaBinning); + colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + trackHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confTrackBinning, confTrackQaBinning); trackHistManager.init(&hRegistry, trackHistSpec, confTrackSelection, confTrackQaBinning); } else { - auto colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto trackHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confTrackBinning, confTrackQaBinning); + colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + trackHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confTrackBinning, confTrackQaBinning); trackHistManager.init(&hRegistry, trackHistSpec, confTrackSelection, confTrackQaBinning); } hRegistry.print(); @@ -116,30 +106,32 @@ struct FemtoTrackQa { void processData(FilteredFemtoCollision const& col, FemtoTracks const& tracks) { - colHistManager.fill(col); - auto trackSlice = trackPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, 0, 0, 0); + auto trackSlice = trackPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& track : trackSlice) { trackHistManager.fill(track, tracks); } }; PROCESS_SWITCH(FemtoTrackQa, processData, "Track QA in Data", true); - void processMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - colHistManager.fill(col, mcCols); - auto trackSlice = trackWithLabelPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); - + colHistManager.fill(col, mcCols, 0, 0, 0); + auto trackSlice = trackWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& track : trackSlice) { + if (!trackCleaner.isClean(track, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } trackHistManager.fill(track, tracks, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoTrackQa, processMc, "Track QA in Monte Carlo", false); }; -WorkflowSpec - defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec + defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto/Tasks/femtoTripletTrackTrackTrack.cxx b/PWGCF/Femto/Tasks/femtoTripletTrackTrackTrack.cxx new file mode 100644 index 00000000000..05dcdd5b153 --- /dev/null +++ b/PWGCF/Femto/Tasks/femtoTripletTrackTrackTrack.cxx @@ -0,0 +1,191 @@ +// Copyright 2019-2025 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 femtoTripletTrackTrackTrack.cxx +/// \brief Tasks that computes correlation between three tracks +/// \author Anton Riedel, TU München, anton.riedel@cern.ch + +#include "PWGCF/Femto/Core/closePairRejection.h" +#include "PWGCF/Femto/Core/closeTripletRejection.h" +#include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/partitions.h" +#include "PWGCF/Femto/Core/trackBuilder.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/tripletBuilder.h" +#include "PWGCF/Femto/Core/tripletHistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2::analysis::femto; + +struct FemtoTripletTrackTrackTrack { + + // setup tables + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; + + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; + + using FemtoTracks = o2::soa::Join; + + using FemtoTracksWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; + + // setup collisions + collisionbuilder::ConfCollisionSelection collisionSelection; + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + colhistmanager::ConfCollisionBinning confCollisionBinning; + + // setup tracks + trackbuilder::ConfTrackSelection1 confTrackSelections1; + trackhistmanager::ConfTrackBinning1 confTrackBinning1; + trackbuilder::ConfTrackSelection2 confTrackSelections2; + trackhistmanager::ConfTrackBinning2 confTrackBinning2; + trackbuilder::ConfTrackSelection3 confTrackSelections3; + trackhistmanager::ConfTrackBinning3 confTrackBinning3; + + o2::framework::Partition trackPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Partition trackPartition3 = MAKE_TRACK_PARTITION(confTrackSelections3); + o2::framework::Preslice perColtracks = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition trackWithLabelPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackWithLabelPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Partition trackWithLabelPartition3 = MAKE_TRACK_PARTITION(confTrackSelections3); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; + + // setup triplets + triplethistmanager::ConfTripletBinning confTripletBinning; + triplethistmanager::ConfTripletCuts confTripletCuts; + + closetripletrejection::ConfCtrTrackTrackTrack confCtr; + + tripletbuilder::TripletTrackTrackTrackBuilder< + trackhistmanager::PrefixTrack1, + trackhistmanager::PrefixTrack2, + trackhistmanager::PrefixTrack3, + triplethistmanager::PrefixTrackTrackTrackSe, + triplethistmanager::PrefixTrackTrackTrackMe, + closetripletrejection::PrefixTrack1Track2Se, + closetripletrejection::PrefixTrack2Track3Se, + closetripletrejection::PrefixTrack1Track3Se, + closetripletrejection::PrefixTrack1Track2Me, + closetripletrejection::PrefixTrack2Track3Me, + closetripletrejection::PrefixTrack1Track3Me> + tripletTrackTrackTrackBuilder; + + // setup mixing + std::vector defaultVtxBins{10, -10, 10}; + std::vector defaultMultBins{50, 0, 200}; + std::vector defaultCentBins{10, 0, 100}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + triplethistmanager::ConfMixing confMixing; + + o2::framework::HistogramRegistry hRegistry{"FemtoTrackTrackTrack", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + if ((doprocessSameEvent + doprocessSameEventMc) > 1 || (doprocessMixedEvent + doprocessMixedEventMc) > 1) { + LOG(fatal) << "More than 1 same or mixed event process function is activated. Breaking..."; + } + bool processData = doprocessSameEvent || doprocessMixedEvent; + bool processMc = doprocessSameEventMc || doprocessMixedEventMc; + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is activated. Breaking..."; + } + + // setup columnpolicy for binning + // default values are used during instantiation, so we need to explicity update them here + mixBinsVtxMult = {{confMixing.vtxBins, confMixing.multBins.value}, true}; + mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; + mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; + + // setup histogram specs + + std::map> colHistSpec; + std::map> trackHistSpec1; + std::map> trackHistSpec2; + std::map> trackHistSpec3; + std::map> tripletHistSpec; + std::map> ctrHistSpec = closepairrejection::makeCprHistSpecMap(confCtr); + + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning2); + trackHistSpec3 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning3); + tripletHistSpec = triplethistmanager::makeTripletHistSpecMap(confTripletBinning); + tripletTrackTrackTrackBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackSelections3, confCtr, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, trackHistSpec3, tripletHistSpec, ctrHistSpec); + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning2); + trackHistSpec3 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning3); + tripletHistSpec = triplethistmanager::makeTripletMcHistSpecMap(confTripletBinning); + tripletTrackTrackTrackBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confTrackSelections3, confCtr, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, trackHistSpec3, tripletHistSpec, ctrHistSpec); + } + hRegistry.print(); + }; + + void processSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks) + { + tripletTrackTrackTrackBuilder.processSameEvent(col, tracks, trackPartition1, trackPartition2, trackPartition3, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackTrack, processSameEvent, "Enable processing same event processing", true); + + void processSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + tripletTrackTrackTrackBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, trackWithLabelPartition3, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackTrack, processSameEventMc, "Enable processing same event processing", false); + + void processMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks) + { + tripletTrackTrackTrackBuilder.processMixedEvent(cols, tracks, trackPartition1, trackPartition2, trackPartition3, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackTrack, processMixedEvent, "Enable processing mixed event processing", true); + + void processMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, o2::aod::FMcParticles const& mcParticles) + { + tripletTrackTrackTrackBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, trackWithLabelPartition3, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackTrack, processMixedEventMc, "Enable processing mixed event processing", false); +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::framework::WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/Femto/Tasks/femtoTripletTrackTrackV0.cxx b/PWGCF/Femto/Tasks/femtoTripletTrackTrackV0.cxx new file mode 100644 index 00000000000..370cee244a3 --- /dev/null +++ b/PWGCF/Femto/Tasks/femtoTripletTrackTrackV0.cxx @@ -0,0 +1,217 @@ +// Copyright 2019-2025 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 femtoTripletTrackTrackV0.cxx +/// \brief Tasks that computes correlation between two tracks +/// \author Anton Riedel, TU München, anton.riedel@cern.ch + +#include "PWGCF/Femto/Core/closePairRejection.h" +#include "PWGCF/Femto/Core/closeTripletRejection.h" +#include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/partitions.h" +#include "PWGCF/Femto/Core/trackBuilder.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/tripletBuilder.h" +#include "PWGCF/Femto/Core/tripletHistManager.h" +#include "PWGCF/Femto/Core/v0Builder.h" +#include "PWGCF/Femto/Core/v0HistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2::analysis::femto; + +struct FemtoTripletTrackTrackV0 { + + // setup tables + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; + + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; + + // TODO also implement K0shorts + using FemtoTracks = o2::soa::Join; + using FemtoLambdas = o2::soa::Join; + // using FemtoK0shorts = o2::soa::Join; + + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoLambdasWithLabel = o2::soa::Join; + // using FemtoK0shortsWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; + + // setup collisions + collisionbuilder::ConfCollisionSelection collisionSelection; + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + colhistmanager::ConfCollisionBinning confCollisionBinning; + + // setup tracks + trackbuilder::ConfTrackSelection1 confTrackSelections1; + trackhistmanager::ConfTrackBinning1 confTrackBinning1; + trackbuilder::ConfTrackSelection2 confTrackSelections2; + trackhistmanager::ConfTrackBinning2 confTrackBinning2; + + o2::framework::Partition trackPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Preslice perColtracks = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition trackWithLabelPartition1 = MAKE_TRACK_PARTITION(confTrackSelections1); + o2::framework::Partition trackWithLabelPartition2 = MAKE_TRACK_PARTITION(confTrackSelections2); + o2::framework::Preslice perColtracksWithLabel = o2::aod::femtobase::stored::fColId; + + // setup for daughters + trackhistmanager::ConfV0PosDauBinning confPosDauBinning; + trackhistmanager::ConfV0NegDauBinning confNegDauBinning; + + // setup lambdas + v0builder::ConfLambdaSelection1 confLambdaSelection; + v0histmanager::ConfLambdaBinning1 confLambdaBinning; + + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Preslice perColLambdasWithLabel = o2::aod::femtobase::stored::fColId; + + // setup triplets + triplethistmanager::ConfTripletBinning confTripletBinning; + triplethistmanager::ConfTripletCuts confTripletCuts; + + closetripletrejection::ConfCtrTrackTrackTrack confCtr; + + tripletbuilder::TripletTrackTrackV0Builder< + modes::V0::kLambda, + trackhistmanager::PrefixTrack1, + trackhistmanager::PrefixTrack2, + v0histmanager::PrefixLambda1, + trackhistmanager::PrefixV01PosDaughter, + trackhistmanager::PrefixV02NegDaughter, + triplethistmanager::PrefixTrackTrackLambdaSe, + triplethistmanager::PrefixTrackTrackLambdaMe, + closetripletrejection::PrefixTrack1Track2Se, + closetripletrejection::PrefixTrack1V0Se, + closetripletrejection::PrefixTrack2V0Se, + closetripletrejection::PrefixTrack1Track2Me, + closetripletrejection::PrefixTrack1V0Me, + closetripletrejection::PrefixTrack2V0Me> + tripletTrackTrackLambdaBuilder; + + // setup mixing + std::vector defaultVtxBins{10, -10, 10}; + std::vector defaultMultBins{50, 0, 200}; + std::vector defaultCentBins{10, 0, 100}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + triplethistmanager::ConfMixing confMixing; + + o2::framework::HistogramRegistry hRegistry{"FemtoTrackTrackTrack", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + if ((doprocessSameEvent + doprocessSameEventMc) > 1 || (doprocessMixedEvent + doprocessMixedEventMc) > 1) { + LOG(fatal) << "More than 1 same or mixed event process function is activated. Breaking..."; + } + bool processData = doprocessSameEvent || doprocessMixedEvent; + bool processMc = doprocessSameEventMc || doprocessMixedEventMc; + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is activated. Breaking..."; + } + + // setup columnpolicy for binning + // default values are used during instantiation, so we need to explicity update them here + mixBinsVtxMult = {{confMixing.vtxBins, confMixing.multBins.value}, true}; + mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; + mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; + + // setup histogram specs + std::map> colHistSpec; + std::map> trackHistSpec1; + std::map> trackHistSpec2; + + std::map> posDauSpec; + std::map> negDauSpec; + std::map> lambdaHistSpec; + std::map> tripletHistSpec; + std::map> ctrHistSpec = closepairrejection::makeCprHistSpecMap(confCtr); + + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackHistSpecMap(confTrackBinning2); + lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + tripletHistSpec = triplethistmanager::makeTripletHistSpecMap(confTripletBinning); + tripletTrackTrackLambdaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confLambdaSelection, confCtr, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, lambdaHistSpec, posDauSpec, negDauSpec, tripletHistSpec, ctrHistSpec); + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + trackHistSpec1 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning1); + trackHistSpec2 = trackhistmanager::makeTrackMcHistSpecMap(confTrackBinning2); + lambdaHistSpec = v0histmanager::makeV0McHistSpecMap(confLambdaBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + tripletHistSpec = triplethistmanager::makeTripletMcHistSpecMap(confTripletBinning); + tripletTrackTrackLambdaBuilder.init(&hRegistry, confCollisionBinning, confTrackSelections1, confTrackSelections2, confLambdaSelection, confCtr, confMixing, confTripletBinning, confTripletCuts, colHistSpec, trackHistSpec1, trackHistSpec2, lambdaHistSpec, posDauSpec, negDauSpec, tripletHistSpec, ctrHistSpec); + } + hRegistry.print(); + }; + + void processSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoLambdas const& /*lambdas*/) + { + tripletTrackTrackLambdaBuilder.processSameEvent(col, tracks, trackPartition1, trackPartition2, lambdaPartition, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackV0, processSameEvent, "Enable processing same event processing", true); + + void processSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdas const& /*lambdas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + tripletTrackTrackLambdaBuilder.processSameEvent(col, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, lambdaWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoTripletTrackTrackV0, processSameEventMc, "Enable processing same event processing", false); + + void processMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoLambdas const& /*lambdas*/) + { + tripletTrackTrackLambdaBuilder.processMixedEvent(cols, tracks, trackPartition1, trackPartition2, lambdaPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackV0, processMixedEvent, "Enable processing mixed event processing", true); + + void processMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdas const& /*lambdas*/, o2::aod::FMcParticles const& mcParticles) + { + tripletTrackTrackLambdaBuilder.processMixedEvent(cols, mcCols, tracks, trackWithLabelPartition1, trackWithLabelPartition2, lambdaWithLabelPartition, mcParticles, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoTripletTrackTrackV0, processMixedEventMc, "Enable processing mixed event processing", false); +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::framework::WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/Femto/Tasks/femtoTwotrackresonanceQa.cxx b/PWGCF/Femto/Tasks/femtoTwotrackresonanceQa.cxx index 537286f1482..5d2e3348c16 100644 --- a/PWGCF/Femto/Tasks/femtoTwotrackresonanceQa.cxx +++ b/PWGCF/Femto/Tasks/femtoTwotrackresonanceQa.cxx @@ -22,17 +22,16 @@ #include "PWGCF/Femto/Core/twoTrackResonanceHistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -53,7 +52,7 @@ struct FemtoTwotrackresonanceQa { using FemtoPhis = o2::soa::Join; using FemtoRho0s = o2::soa::Join; using FemtoKstar0s = o2::soa::Join; - using FemtoTracks = o2::soa::Join; + using FemtoTracks = o2::soa::Join; SliceCache cache; @@ -115,7 +114,7 @@ struct FemtoTwotrackresonanceQa { { // create a map for histogram specs auto colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); auto posDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confPosDaughterBinning, confPosDaughterQaBinning); auto negDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confNegDaughterBinning, confNegDaughterQaBinning); @@ -141,7 +140,7 @@ struct FemtoTwotrackresonanceQa { void processPhis(FilteredFemtoCollision const& col, FemtoPhis const& /*phis*/, FemtoTracks const& tracks) { - colHistManager.fill(col); + colHistManager.fill(col, 0, 0, 0); auto phiSlice = phiPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& phi : phiSlice) { phiHistManager.fill(phi, tracks); @@ -151,7 +150,7 @@ struct FemtoTwotrackresonanceQa { void processRho0s(FilteredFemtoCollision const& col, FemtoRho0s const& /*rho0s*/, FemtoTracks const& tracks) { - colHistManager.fill(col); + colHistManager.fill(col, 0, 0, 0); auto rho0Slice = rho0Partition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& rho0 : rho0Slice) { rho0HistManager.fill(rho0, tracks); @@ -161,7 +160,7 @@ struct FemtoTwotrackresonanceQa { void processKstar0s(FilteredFemtoCollision const& col, FemtoKstar0s const& /*kstar0s*/, FemtoTracks const& tracks) { - colHistManager.fill(col); + colHistManager.fill(col, 0, 0, 0); auto kstar0Slice = kstar0Partition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& kstar0 : kstar0Slice) { kstar0HistManager.fill(kstar0, tracks); diff --git a/PWGCF/Femto/Tasks/femtoV0Qa.cxx b/PWGCF/Femto/Tasks/femtoV0Qa.cxx index 1d1e0ec45f9..5ed29d305ba 100644 --- a/PWGCF/Femto/Tasks/femtoV0Qa.cxx +++ b/PWGCF/Femto/Tasks/femtoV0Qa.cxx @@ -16,66 +16,68 @@ #include "PWGCF/Femto/Core/collisionBuilder.h" #include "PWGCF/Femto/Core/collisionHistManager.h" #include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/particleCleaner.h" #include "PWGCF/Femto/Core/partitions.h" #include "PWGCF/Femto/Core/trackHistManager.h" #include "PWGCF/Femto/Core/v0Builder.h" #include "PWGCF/Femto/Core/v0HistManager.h" #include "PWGCF/Femto/DataModel/FemtoTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; using namespace o2::analysis::femto; struct FemtoV0Qa { // setup tables - using FemtoCollisions = o2::soa::Join; + using FemtoCollisions = o2::soa::Join; using FilteredFemtoCollisions = o2::soa::Filtered; using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; - using FemtoCollisionsWithLabel = o2::soa::Join; + using FemtoCollisionsWithLabel = o2::soa::Join; using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; - using FemtoLambdas = o2::soa::Join; - using FemtoK0shorts = o2::soa::Join; - using FemtoTracks = o2::soa::Join; + using FemtoLambdas = o2::soa::Join; + using FemtoK0shorts = o2::soa::Join; + using FemtoTracks = o2::soa::Join; - using FemtoLambdasWithLabel = o2::soa::Join; - using FemtoK0shortsWithLabel = o2::soa::Join; - using FemtoTracksWithLabel = o2::soa::Join; + using FemtoLambdasWithLabel = o2::soa::Join; + using FemtoK0shortsWithLabel = o2::soa::Join; + using FemtoTracksWithLabel = o2::soa::Join; - SliceCache cache; + o2::framework::SliceCache cache; // setup for collisions collisionbuilder::ConfCollisionSelection collisionSelection; - Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); colhistmanager::CollisionHistManager colHistManager; colhistmanager::ConfCollisionBinning confCollisionBinning; colhistmanager::ConfCollisionQaBinning confCollisionQaBinning; // setup for lambdas + particlecleaner::ConfLambdaCleaner1 confLambdaCleaner; v0builder::ConfLambdaSelection1 confLambdaSelection; - Partition lambdaPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); - Preslice perColLambdas = femtobase::stored::fColId; + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; - Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); - Preslice perColLambdasWithLabel = femtobase::stored::fColId; + o2::framework::Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Preslice perColLambdasWithLabel = o2::aod::femtobase::stored::fColId; + + particlecleaner::ParticleCleaner lambdaCleaner; v0histmanager::ConfLambdaBinning1 confLambdaBinning; v0histmanager::ConfLambdaQaBinning1 confLambdaQaBinning; @@ -87,13 +89,16 @@ struct FemtoV0Qa { lambdaHistManager; // setup for k0shorts + particlecleaner::ConfK0shortCleaner1 confK0shortCleaner; v0builder::ConfK0shortSelection1 confK0shortSelection; - Partition k0shortPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); - Preslice perColK0shorts = femtobase::stored::fColId; + o2::framework::Partition k0shortPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColK0shorts = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColK0shortsWithLabel = o2::aod::femtobase::stored::fColId; - Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); - Preslice perColK0shortsWithLabel = femtobase::stored::fColId; + particlecleaner::ParticleCleaner k0shortCleaner; v0histmanager::ConfK0shortBinning1 confK0shortBinning; v0histmanager::ConfK0shortQaBinning1 confK0shortQaBinning; @@ -111,40 +116,48 @@ struct FemtoV0Qa { trackhistmanager::ConfV0NegDauBinning confV0NegDaughterBinning; trackhistmanager::ConfV0NegDauQaBinning confV0NegDaughterQaBinning; - HistogramRegistry hRegistry{"FemtoV0Qa", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::framework::HistogramRegistry hRegistry{"FemtoV0Qa", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) + void init(o2::framework::InitContext&) { if ((doprocessLambda + doprocessLambdaMc + doprocessK0short + doprocessK0shortMc) > 1) { LOG(fatal) << "Only one process can be activated"; } - bool processData = doprocessLambda || doprocessK0short; + lambdaCleaner.init(confLambdaCleaner); + k0shortCleaner.init(confK0shortCleaner); + + std::map> colHistSpec; + std::map> posDaughterHistSpec; + std::map> negDaughterHistSpec; + std::map> lambdaHistSpec; + std::map> k0shortHistSpec; + if (processData) { - auto colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto posDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confV0PosDaughterBinning, confV0PosDaughterQaBinning); - auto negDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confV0NegDaughterBinning, confV0NegDaughterQaBinning); + colHistSpec = colhistmanager::makeColQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + posDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confV0PosDaughterBinning, confV0PosDaughterQaBinning); + negDaughterHistSpec = trackhistmanager::makeTrackQaHistSpecMap(confV0NegDaughterBinning, confV0NegDaughterQaBinning); if (doprocessLambda) { - auto lambdaHistSpec = v0histmanager::makeV0QaHistSpecMap(confLambdaBinning, confLambdaQaBinning); + lambdaHistSpec = v0histmanager::makeV0QaHistSpecMap(confLambdaBinning, confLambdaQaBinning); lambdaHistManager.init(&hRegistry, lambdaHistSpec, confLambdaSelection, confLambdaQaBinning, posDaughterHistSpec, confV0PosDaughterQaBinning, negDaughterHistSpec, confV0NegDaughterQaBinning); } if (doprocessK0short) { - auto k0shortHistSpec = v0histmanager::makeV0QaHistSpecMap(confK0shortBinning, confK0shortQaBinning); + k0shortHistSpec = v0histmanager::makeV0QaHistSpecMap(confK0shortBinning, confK0shortQaBinning); k0shortHistManager.init(&hRegistry, k0shortHistSpec, confK0shortSelection, confK0shortQaBinning, posDaughterHistSpec, confV0PosDaughterQaBinning, negDaughterHistSpec, confV0NegDaughterQaBinning); } } else { - auto colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); - colHistManager.init(&hRegistry, colHistSpec, confCollisionQaBinning); - auto posDaughterHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confV0PosDaughterBinning, confV0PosDaughterQaBinning); - auto negDaughterHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confV0NegDaughterBinning, confV0NegDaughterQaBinning); + colHistSpec = colhistmanager::makeColMcQaHistSpecMap(confCollisionBinning, confCollisionQaBinning); + colHistManager.init(&hRegistry, colHistSpec, confCollisionBinning, confCollisionQaBinning); + posDaughterHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confV0PosDaughterBinning, confV0PosDaughterQaBinning); + negDaughterHistSpec = trackhistmanager::makeTrackMcQaHistSpecMap(confV0NegDaughterBinning, confV0NegDaughterQaBinning); if (doprocessLambdaMc) { - auto lambdaHistSpec = v0histmanager::makeV0McQaHistSpecMap(confLambdaBinning, confLambdaQaBinning); + lambdaHistSpec = v0histmanager::makeV0McQaHistSpecMap(confLambdaBinning, confLambdaQaBinning); lambdaHistManager.init(&hRegistry, lambdaHistSpec, confLambdaSelection, confLambdaQaBinning, posDaughterHistSpec, confV0PosDaughterQaBinning, negDaughterHistSpec, confV0NegDaughterQaBinning); } if (doprocessK0shortMc) { - auto k0shortHistSpec = v0histmanager::makeV0McQaHistSpecMap(confK0shortBinning, confK0shortQaBinning); + k0shortHistSpec = v0histmanager::makeV0McQaHistSpecMap(confK0shortBinning, confK0shortQaBinning); k0shortHistManager.init(&hRegistry, k0shortHistSpec, confK0shortSelection, confK0shortQaBinning, posDaughterHistSpec, confV0PosDaughterQaBinning, negDaughterHistSpec, confV0NegDaughterQaBinning); } } @@ -153,48 +166,54 @@ struct FemtoV0Qa { void processK0short(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoK0shorts const& /*k0shorts*/) { - colHistManager.fill(col); - auto k0shortSlice = k0shortPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, 0, 0, 0); + auto k0shortSlice = k0shortPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& k0short : k0shortSlice) { k0shortHistManager.fill(k0short, tracks); } } PROCESS_SWITCH(FemtoV0Qa, processK0short, "Process k0shorts", false); - void processK0shortMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processK0shortMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - colHistManager.fill(col, mcCols); - auto k0shortSlice = k0shortWithLabelPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, mcCols, 0, 0, 0); + auto k0shortSlice = k0shortWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& k0short : k0shortSlice) { + if (!k0shortCleaner.isClean(k0short, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } k0shortHistManager.fill(k0short, tracks, mcParticles, mcMothers, mcPartonicMothers); } } - PROCESS_SWITCH(FemtoV0Qa, processK0shortMc, "Process k0shorts", false); + PROCESS_SWITCH(FemtoV0Qa, processK0shortMc, "Process k0shorts with MC information", false); void processLambda(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoLambdas const& /*lambdas*/) { - colHistManager.fill(col); - auto lambdaSlice = lambdaPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, 0, 0, 0); + auto lambdaSlice = lambdaPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& lambda : lambdaSlice) { lambdaHistManager.fill(lambda, tracks); } } PROCESS_SWITCH(FemtoV0Qa, processLambda, "Process lambdas", true); - void processLambdaMc(FilteredFemtoCollisionWithLabel const& col, FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambdas*/, FMcParticles const& mcParticles, FMcMothers const& mcMothers, FMcPartMoths const& mcPartonicMothers) + void processLambdaMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambdas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) { - colHistManager.fill(col, mcCols); - auto lambdaSlice = lambdaWithLabelPartition->sliceByCached(femtobase::stored::fColId, col.globalIndex(), cache); + colHistManager.fill(col, mcCols, 0, 0, 0); + auto lambdaSlice = lambdaWithLabelPartition->sliceByCached(o2::aod::femtobase::stored::fColId, col.globalIndex(), cache); for (auto const& lambda : lambdaSlice) { + if (!lambdaCleaner.isClean(lambda, mcParticles, mcMothers, mcPartonicMothers)) { + continue; + } lambdaHistManager.fill(lambda, tracks, mcParticles, mcMothers, mcPartonicMothers); } } PROCESS_SWITCH(FemtoV0Qa, processLambdaMc, "Process lambdas", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { - WorkflowSpec workflow{ + o2::framework::WorkflowSpec workflow{ adaptAnalysisTask(cfgc), }; return workflow; diff --git a/PWGCF/Femto3D/Core/femto3dPairTask.h b/PWGCF/Femto3D/Core/femto3dPairTask.h old mode 100755 new mode 100644 index db5949f4ae0..1fd450ac28b --- a/PWGCF/Femto3D/Core/femto3dPairTask.h +++ b/PWGCF/Femto3D/Core/femto3dPairTask.h @@ -20,18 +20,18 @@ // #include "Framework/ASoA.h" // #include "Framework/DataTypes.h" // #include "Framework/AnalysisDataModel.h" -// #include "Common/DataModel/PIDResponse.h" // #include "Framework/Logger.h" // #include "Common/DataModel/Multiplicity.h" -#include -#include +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" + +#include "TDatabasePDG.h" #include "TLorentzVector.h" #include "TVector3.h" -#include "TDatabasePDG.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CommonConstants/MathConstants.h" +#include +#include double particle_mass(const int PDGcode) { diff --git a/PWGCF/Femto3D/DataModel/PIDutils.h b/PWGCF/Femto3D/DataModel/PIDutils.h index 9e28f7b5863..74a3b7ef15a 100644 --- a/PWGCF/Femto3D/DataModel/PIDutils.h +++ b/PWGCF/Femto3D/DataModel/PIDutils.h @@ -19,10 +19,12 @@ #ifndef PWGCF_FEMTO3D_DATAMODEL_PIDUTILS_H_ #define PWGCF_FEMTO3D_DATAMODEL_PIDUTILS_H_ +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + #include #include #include -#include "Common/DataModel/PIDResponse.h" namespace o2::aod::singletrackselector { diff --git a/PWGCF/Femto3D/DataModel/singletrackselector.h b/PWGCF/Femto3D/DataModel/singletrackselector.h index d7f4f0822d3..cce33ef19aa 100644 --- a/PWGCF/Femto3D/DataModel/singletrackselector.h +++ b/PWGCF/Femto3D/DataModel/singletrackselector.h @@ -17,16 +17,17 @@ #define PWGCF_FEMTO3D_DATAMODEL_SINGLETRACKSELECTOR_H_ // #include -#include -#include +#include "PWGCF/Femto3D/DataModel/PIDutils.h" + +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" #include "Framework/Logger.h" -#include "Common/DataModel/Multiplicity.h" -#include "PWGCF/Femto3D/DataModel/PIDutils.h" + +#include +#include namespace o2::aod { diff --git a/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx b/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx index 252fb5fc410..0602efb9913 100644 --- a/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx @@ -162,7 +162,13 @@ struct FemtoCorrelationsMC { int N = _dcaBinning.value[0]; // number of bins -- must be odd otherwise will be increased by 1 if (N % 2 != 1) N += 1; - auto var_bins = calc_var_bins(N + 1, _dcaBinning.value[1], static_cast(_dcaBinning.value[2])); + + std::unique_ptr dca_bins; + if (static_cast(_dcaBinning.value[2]) != 1.0) { + dca_bins = calc_var_bins(N + 1, _dcaBinning.value[1], static_cast(_dcaBinning.value[2])); + } else { + dca_bins = calc_const_bins(N, -_dcaBinning.value[1], _dcaBinning.value[1]); + } auto const_bins = calc_const_bins(100, 0., 5.0); for (unsigned int i = 0; i < _centBins.value.size() - 1; i++) { @@ -172,9 +178,9 @@ struct FemtoCorrelationsMC { DCA_histos_1_perMult[1] = registry.add(Form("Cent%i/FirstParticle/dcaxyz_vs_pt_weakdecay", i), "dcaxyz_vs_pt_weakdecay", kTH3F, {{1, 0, 1, "pt"}, {1, 0, 1, "DCA_XY(pt) weakdecay"}, {1, 0, 1, "DCA_Z(pt) weakdecay"}}); DCA_histos_1_perMult[2] = registry.add(Form("Cent%i/FirstParticle/dcaxyz_vs_pt_material", i), "dcaxyz_vs_pt_material", kTH3F, {{1, 0, 1, "pt"}, {1, 0, 1, "DCA_XY(pt) material"}, {1, 0, 1, "DCA_Z(pt) material"}}); - DCA_histos_1_perMult[0]->SetBins(100, &const_bins[0], N, &var_bins[0], N, &var_bins[0]); // set variable bins in Y and Z axis; constant on X - DCA_histos_1_perMult[1]->SetBins(100, &const_bins[0], N, &var_bins[0], N, &var_bins[0]); - DCA_histos_1_perMult[2]->SetBins(100, &const_bins[0], N, &var_bins[0], N, &var_bins[0]); + DCA_histos_1_perMult[0]->SetBins(100, &const_bins[0], N, &dca_bins[0], N, &dca_bins[0]); // set variable bins in Y and Z axis; constant on X + DCA_histos_1_perMult[1]->SetBins(100, &const_bins[0], N, &dca_bins[0], N, &dca_bins[0]); + DCA_histos_1_perMult[2]->SetBins(100, &const_bins[0], N, &dca_bins[0], N, &dca_bins[0]); std::map> Purity_histos_1_perMult; Purity_histos_1_perMult[11] = registry.add(Form("Cent%i/FirstParticle/pSpectraEl", i), "pSpectraEl", kTH1F, {{100, 0., 5., "p"}}); @@ -194,9 +200,9 @@ struct FemtoCorrelationsMC { DCA_histos_2_perMult[1] = registry.add(Form("Cent%i/SecondParticle/dcaxyz_vs_pt_weakdecay", i), "dcaxyz_vs_pt_weakdecay", kTH3F, {{1, 0, 1, "pt"}, {1, 0, 1, "DCA_XY(pt) weakdecay"}, {1, 0, 1, "DCA_Z(pt) weakdecay"}}); DCA_histos_2_perMult[2] = registry.add(Form("Cent%i/SecondParticle/dcaxyz_vs_pt_material", i), "dcaxyz_vs_pt_material", kTH3F, {{1, 0, 1, "pt"}, {1, 0, 1, "DCA_XY(pt) material"}, {1, 0, 1, "DCA_Z(pt) material"}}); - DCA_histos_2_perMult[0]->SetBins(100, &const_bins[0], N, &var_bins[0], N, &var_bins[0]); // set variable bins in Y and Z axis; constant on X - DCA_histos_2_perMult[1]->SetBins(100, &const_bins[0], N, &var_bins[0], N, &var_bins[0]); - DCA_histos_2_perMult[2]->SetBins(100, &const_bins[0], N, &var_bins[0], N, &var_bins[0]); + DCA_histos_2_perMult[0]->SetBins(100, &const_bins[0], N, &dca_bins[0], N, &dca_bins[0]); // set variable bins in Y and Z axis; constant on X + DCA_histos_2_perMult[1]->SetBins(100, &const_bins[0], N, &dca_bins[0], N, &dca_bins[0]); + DCA_histos_2_perMult[2]->SetBins(100, &const_bins[0], N, &dca_bins[0], N, &dca_bins[0]); std::map> Purity_histos_2_perMult; Purity_histos_2_perMult[11] = registry.add(Form("Cent%i/SecondParticle/pSpectraEl", i), "pSpectraEl", kTH1F, {{100, 0., 5., "p"}}); diff --git a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h index 4e67c43b40c..8a455f073eb 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h @@ -219,35 +219,40 @@ class FemtoDreamCollisionSelection mHistogramQn = registry; mHistogramQn->add("Event/centFT0CBeforeQn", "; cent", kTH1F, {{10, 0, 100}}); mHistogramQn->add("Event/centFT0CAfterQn", "; cent", kTH1F, {{10, 0, 100}}); - mHistogramQn->add("Event/centVsqn", "; cent; qn", kTH2F, {{10, 0, 100}, {100, 0, 1000}}); + mHistogramQn->add("Event/centVsqn", "; cent; qn", kTH2F, {{10, 0, 100}, {1000, 0, 1000}}); mHistogramQn->add("Event/centVsqnVsSpher", "; cent; qn; Sphericity", kTH3F, {{10, 0, 100}, {100, 0, 1000}, {100, 0, 1}}); mHistogramQn->add("Event/qnBin", "; qnBin; entries", kTH1F, {{20, 0, 20}}); mHistogramQn->add("Event/psiEP", "; #Psi_{EP} (deg); entries", kTH1F, {{100, 0, 180}}); + mHistogramQn->add("Event/epReso_FT0CTPC", "; cent; qnBin; reso_ft0c_tpc", kTH2F, {{10, 0, 100}, {10, 0, 10}}); + mHistogramQn->add("Event/epReso_FT0ATPC", "; cent; qnBin; reso_ft0a_tpc", kTH2F, {{10, 0, 100}, {10, 0, 10}}); + mHistogramQn->add("Event/epReso_FT0CFT0A", "; cent; qnBin; reso_ft0c_ft0a", kTH2F, {{10, 0, 100}, {10, 0, 10}}); + mHistogramQn->add("Event/epReso_count", "; cent; qnBin; count", kTH2F, {{10, 0, 100}, {10, 0, 10}}); return; } /// Initializes histograms for the flow calculation /// \param registry Histogram registry to be passed - void initFlow(HistogramRegistry* registry, bool doQnSeparation, int mumQnBins = 10, int binPt = 100, int binEta = 32) + void initFlow(HistogramRegistry* registry, bool doQnSeparation, int mumQnBins = 10, int centBins = 10) { if (!mCutsSet) { LOGF(error, "Event selection not set - quitting!"); } - mReQthisEvt = new TH2D("ReQthisEvt", "", binPt, 0., 5., binEta, -0.8, 0.8); - mImQthisEvt = new TH2D("ImQthisEvt", "", binPt, 0., 5., binEta, -0.8, 0.8); - mReQ2thisEvt = new TH2D("ReQ2thisEvt", "", binPt, 0., 5., binEta, -0.8, 0.8); - mImQ2thisEvt = new TH2D("ImQ2thisEvt", "", binPt, 0., 5., binEta, -0.8, 0.8); - mMQthisEvt = new TH2D("MQthisEvt", "", binPt, 0., 5., binEta, -0.8, 0.8); - mMQWeightthisEvt = new TH2D("MQWeightthisEvt", "", binPt, 0., 5., binEta, -0.8, 0.8); mHistogramQn = registry; - mHistogramQn->add("Event/profileC22", "; cent; c22", kTProfile, {{10, 0, 100}}, "s"); - mHistogramQn->add("Event/profileC24", "; cent; c24", kTProfile, {{10, 0, 100}}, "s"); + mHistogramQn->add("Event/hN2allQn", ";centrality; #sum Re(Q_{2,A} Q_{2,B}^{*})", kTH1F, {{centBins, 0, 100}}); + mHistogramQn->add("Event/hD2allQn", ";centrality; #sum (W_{A} W_{B})", kTH1F, {{centBins, 0, 100}}); + mHistogramQn->get(HIST("Event/hN2allQn"))->Sumw2(); + mHistogramQn->get(HIST("Event/hD2allQn"))->Sumw2(); if (doQnSeparation) { for (int iqn(0); iqn < mumQnBins; ++iqn) { - profilesC22.push_back(mHistogramQn->add(("Qn/profileC22_" + std::to_string(iqn)).c_str(), "; cent; c22", kTProfile, {{10, 0, 100}}, "s")); + hN2.push_back(mHistogramQn->add(("Qn/hN2_" + std::to_string(iqn)).c_str(), ";centrality; #sum Re(Q_{2,A} Q_{2,B}^{*})", kTH1F, {{centBins, 0, 100}})); + hD2.push_back(mHistogramQn->add(("Qn/hD2_" + std::to_string(iqn)).c_str(), ";centrality; #sum (W_{A} W_{B})", kTH1F, {{centBins, 0, 100}})); + } + for (int iqn(0); iqn < mumQnBins; ++iqn) { + std::get>(hN2[iqn])->Sumw2(); + std::get>(hD2[iqn])->Sumw2(); } } return; @@ -329,9 +334,17 @@ class FemtoDreamCollisionSelection /// \param col Collision /// \return value of the qn-vector of FT0C of the event template - float computeqnVec(T const& col) + float computeqnVec(T const& col, int qvecMod = 0) { - double qn = std::sqrt(col.qvecFT0CReVec()[0] * col.qvecFT0CReVec()[0] + col.qvecFT0CImVec()[0] * col.qvecFT0CImVec()[0]) * std::sqrt(col.sumAmplFT0C()); + double qn = -999.f; + if (qvecMod == 0) { + qn = std::sqrt(col.qvecFT0CReVec()[0] * col.qvecFT0CReVec()[0] + col.qvecFT0CImVec()[0] * col.qvecFT0CImVec()[0]) * std::sqrt(col.sumAmplFT0C()); + } else if (qvecMod == 1) { + qn = std::sqrt(col.qvecFT0AReVec()[0] * col.qvecFT0AReVec()[0] + col.qvecFT0AImVec()[0] * col.qvecFT0AImVec()[0]) * std::sqrt(col.sumAmplFT0A()); + } else { + LOGP(error, "no selected detector of Qvec for ESE "); + return qn; + } return qn; } @@ -341,15 +354,43 @@ class FemtoDreamCollisionSelection /// \param nmode EP in which harmonic(default 2nd harmonic) /// \return angle of the event plane (rad) of FT0C of the event template - float computeEP(T const& col, int nmode) + float computeEP(T const& col, int nmode, int qvecMod) { - double EP = ((1. / nmode) * (TMath::ATan2(col.qvecFT0CImVec()[0], col.qvecFT0CReVec()[0]))); - if (EP < 0) + double EP = -999.f; + if (qvecMod == 0) { + EP = ((1. / nmode) * (TMath::ATan2(col.qvecFT0CImVec()[0], col.qvecFT0CReVec()[0]))); + } else if (qvecMod == 1) { + EP = ((1. / nmode) * (TMath::ATan2(col.qvecFT0AImVec()[0], col.qvecFT0AReVec()[0]))); + } else if (qvecMod == 2) { + EP = ((1. / nmode) * (TMath::ATan2(col.qvecTPCallImVec()[0], col.qvecTPCallReVec()[0]))); + } else { + LOGP(error, "no selected detector of Qvec for EP"); + return EP; + } + + if (EP < 0) { EP += TMath::Pi(); - // atan2 return in rad -pi/2-pi/2, then make it 0-pi + } // atan2 return in rad -pi/2-pi/2, then make it 0-pi return EP; } + /// Compute the event plane resolution of 3 sub-events + /// \tparam T type of the collision + /// \param col Collision + /// \param nmode EP in which harmonic(default 2nd harmonic) + template + void fillEPReso(T const& col, int nmode, float centrality) + { + const float psi_ft0c = ((1. / nmode) * (TMath::ATan2(col.qvecFT0CImVec()[0], col.qvecFT0CReVec()[0]))); + const float psi_ft0a = ((1. / nmode) * (TMath::ATan2(col.qvecFT0AImVec()[0], col.qvecFT0AReVec()[0]))); + const float psi_tpc = ((1. / nmode) * (TMath::ATan2(col.qvecTPCallImVec()[0], col.qvecTPCallReVec()[0]))); + + mHistogramQn->fill(HIST("Event/epReso_FT0CTPC"), centrality, mQnBin + 0.f, std::cos((psi_ft0c - psi_tpc) * nmode)); + mHistogramQn->fill(HIST("Event/epReso_FT0ATPC"), centrality, mQnBin + 0.f, std::cos((psi_ft0a - psi_tpc) * nmode)); + mHistogramQn->fill(HIST("Event/epReso_FT0CFT0A"), centrality, mQnBin + 0.f, std::cos((psi_ft0c - psi_ft0a) * nmode)); + mHistogramQn->fill(HIST("Event/epReso_count"), centrality, mQnBin + 0.f); + } + /// \return the 1-d qn-vector separator to 2-d std::vector> getQnBinSeparator2D(std::vector flat, const int numQnBins = 10) { @@ -412,52 +453,15 @@ class FemtoDreamCollisionSelection } /// \fill event-wise informations - void fillEPQA(float centrality, float fSpher, float qn, float psiEP) + template + void fillEPQA(T& col, float centrality, float fSpher, float qn, float psiEP, int nmode = 2) { mHistogramQn->fill(HIST("Event/centFT0CBeforeQn"), centrality); mHistogramQn->fill(HIST("Event/centVsqn"), centrality, qn); mHistogramQn->fill(HIST("Event/centVsqnVsSpher"), centrality, qn, fSpher); mHistogramQn->fill(HIST("Event/qnBin"), mQnBin + 0.f); mHistogramQn->fill(HIST("Event/psiEP"), psiEP); - } - - /// \todo to be implemented! - /// Fill cumulants histo for flow calculation - /// Reset hists event-by-event - /// \tparam T1 type of the collision - /// \tparam T2 type of the tracks - /// \param tracks All tracks - template - bool fillCumulants(T1 const& col, T2 const& tracks, float fHarmonic = 2.f) - { - int numOfTracks = col.numContrib(); - if (numOfTracks < 3) - return false; - - mReQthisEvt->Reset(); - mImQthisEvt->Reset(); - mReQ2thisEvt->Reset(); - mImQ2thisEvt->Reset(); - mMQthisEvt->Reset(); - mMQWeightthisEvt->Reset(); - - for (auto const& track : tracks) { - double weight = 1; // Will implement NUA&NUE correction - double phi = track.phi(); - double pt = track.pt(); - double eta = track.eta(); - double cosnphi = weight * TMath::Cos(fHarmonic * phi); - double sinnphi = weight * TMath::Sin(fHarmonic * phi); - double cos2nphi = weight * TMath::Cos(2 * fHarmonic * phi); - double sin2nphi = weight * TMath::Sin(2 * fHarmonic * phi); - mReQthisEvt->Fill(pt, eta, cosnphi); - mImQthisEvt->Fill(pt, eta, sinnphi); - mReQ2thisEvt->Fill(pt, eta, cos2nphi); - mImQ2thisEvt->Fill(pt, eta, sin2nphi); - mMQthisEvt->Fill(pt, eta); - mMQWeightthisEvt->Fill(pt, eta, weight); - } - return true; + fillEPReso(col, nmode, centrality); } /// \todo to be implemented! @@ -466,39 +470,63 @@ class FemtoDreamCollisionSelection /// \param doQnSeparation to fill flow in divied qn bins /// \param qnBin should be in 0-9 /// \param fEtaGap eta gap for flow cumulant - template - void doCumulants(T1 const& col, T2 const& tracks, float centrality, bool doQnSeparation = false, int numQnBins = 10, float fEtaGap = 0.3f, int binPt = 100, int binEta = 32) + template + void doCumulants(T1 const& col, T2 const& tracks, TC& trackCuts, float centrality, bool doQnSeparation = false, int numQnBins = 10, float fEtaGap = 0.5f, float ptMin = 0.2f, float ptMax = 5.0f, float harmonic = 2.0f) { - if (!fillCumulants(col, tracks)) + int numOfTracks = col.numContrib(); + if (numOfTracks < 3) return; - if (mMQthisEvt->Integral(1, binPt, 1, binEta) < 2) - return; + double Q2A_re = 0., Q2A_im = 0., WA = 0.; + double Q2B_re = 0., Q2B_im = 0., WB = 0.; - double allReQ = mReQthisEvt->Integral(1, binPt, 1, binEta); - double allImQ = mImQthisEvt->Integral(1, binPt, 1, binEta); - TComplex Q(allReQ, allImQ); - TComplex QStar = TComplex::Conjugate(Q); + int nA = 0, nB = 0; - double posEtaRe = mReQthisEvt->Integral(1, binPt, mReQthisEvt->GetYaxis()->FindBin(fEtaGap + 1e-6), binEta); - double posEtaIm = mImQthisEvt->Integral(1, binPt, mImQthisEvt->GetYaxis()->FindBin(fEtaGap + 1e-6), binEta); - if (mMQthisEvt->Integral(1, binPt, mMQthisEvt->GetYaxis()->FindBin(fEtaGap + 1e-6), binEta) < 2) - return; - float posEtaMQ = mMQWeightthisEvt->Integral(1, binPt, mMQthisEvt->GetYaxis()->FindBin(fEtaGap + 1e-6), binEta); - TComplex posEtaQ = TComplex(posEtaRe, posEtaIm); - TComplex posEtaQStar = TComplex::Conjugate(posEtaQ); + for (auto const& trk : tracks) { + if (!trackCuts.isSelectedMinimal(trk)) { + continue; + } + const double pt = trk.pt(); + const double eta = trk.eta(); + if (pt < ptMin || pt > ptMax) { + continue; + } + + const double w = 1.0; // TODO: NUA/NUE weight + const double phi = trk.phi(); + const double c = w * TMath::Cos(harmonic * phi); + const double s = w * TMath::Sin(harmonic * phi); + + if (eta > fEtaGap) { + Q2A_re += c; + Q2A_im += s; + WA += w; + nA++; + } else if (eta < -1 * fEtaGap) { + Q2B_re += c; + Q2B_im += s; + WB += w; + nB++; + } + } - double negEtaRe = mReQthisEvt->Integral(1, binPt, 1, mReQthisEvt->GetYaxis()->FindBin(-1 * fEtaGap - 1e-6)); - double negEtaIm = mImQthisEvt->Integral(1, binPt, 1, mImQthisEvt->GetYaxis()->FindBin(-1 * fEtaGap - 1e-6)); - if (mMQthisEvt->Integral(1, binPt, 1, mMQthisEvt->GetYaxis()->FindBin(-1 * fEtaGap - 1e-6)) < 2) + // need at least 1 track on each side to form pairs; for stability, require >=2 + if (nA < 2 || nB < 2) { + return; + } + const double D2_evt = WA * WB; + if (D2_evt <= 0.) { return; - float negEtaMQ = mMQWeightthisEvt->Integral(1, binPt, 1, mMQthisEvt->GetYaxis()->FindBin(-1 * fEtaGap - 1e-6)); - TComplex negEtaQ = TComplex(negEtaRe, negEtaIm); - TComplex negEtaQStar = TComplex::Conjugate(negEtaQ); + } + + // N2_evt = Re(Q2A * conj(Q2B)) = Q2A_re*Q2B_re + Q2A_im*Q2B_im + const double N2_evt = Q2A_re * Q2B_re + Q2A_im * Q2B_im; - mHistogramQn->get(HIST("Event/profileC22"))->Fill(centrality, (negEtaQ * posEtaQStar).Re() / (negEtaMQ * posEtaMQ), (negEtaMQ * posEtaMQ)); + mHistogramQn->fill(HIST("Event/hN2allQn"), centrality, N2_evt); + mHistogramQn->fill(HIST("Event/hD2allQn"), centrality, D2_evt); if (doQnSeparation && mQnBin >= 0 && mQnBin < numQnBins) { - std::get>(profilesC22[mQnBin])->Fill(centrality, (negEtaQ * posEtaQStar).Re() / (negEtaMQ * posEtaMQ), (negEtaMQ * posEtaMQ)); + std::get>(hN2[mQnBin])->Fill(centrality, N2_evt); + std::get>(hD2[mQnBin])->Fill(centrality, D2_evt); } return; } @@ -516,13 +544,8 @@ class FemtoDreamCollisionSelection float mSphericityPtmin = 0.f; int mQnBin = -999; HistogramRegistry* mHistogramQn = nullptr; ///< For flow cumulant output - std::vector profilesC22; /// Pofile Histograms of c22 per Qn bin - TH2D* mReQthisEvt = nullptr; ///< For flow cumulant in an event - TH2D* mImQthisEvt = nullptr; ///< For flow cumulant in an event - TH2D* mReQ2thisEvt = nullptr; ///< For flow cumulant in an event - TH2D* mImQ2thisEvt = nullptr; ///< For flow cumulant in an event - TH2D* mMQthisEvt = nullptr; ///< For flow cumulant in an event - TH2D* mMQWeightthisEvt = nullptr; ///< For flow cumulant in an event + std::vector hN2; ///< Histograms of c22 per Qn bin + std::vector hD2; ///< Histograms of c22 per Qn bin }; } // namespace o2::analysis::femtoDream diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainer.h b/PWGCF/FemtoDream/Core/femtoDreamContainer.h index a12b36fd8a2..4c3a5b24be0 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainer.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainer.h @@ -223,10 +223,26 @@ class FemtoDreamContainer mHistogramRegistry->add((folderName + "/relPair3dRmTMultPercentileQnPairphi").c_str(), ("; " + femtoDKout + femtoDKside + femtoDKlong + "; #it{m}_{T} (GeV/#it{c}); Centrality; qn; #varphi_{pair} - #Psi_{EP}").c_str(), kTHnSparseF, {femtoDKoutAxis, femtoDKsideAxis, femtoDKlongAxis, mTAxi4D, multPercentileAxis4D, qnAxis, pairPhiAxis}); } + template + void init_3Dqn_MC(std::string folderName, std::string femtoDKout, std::string femtoDKside, std::string femtoDKlong, + T& femtoDKoutAxis, T& femtoDKsideAxis, T& femtoDKlongAxis, bool smearingByOrigin = false) + { + mHistogramRegistry->add((folderName + "/hNoMCtruthPairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/hFakePairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + if (smearingByOrigin) { + const int nOriginBins = o2::aod::femtodreamMCparticle::ParticleOriginMCTruth::kNOriginMCTruthTypes; + mHistogramRegistry->add((folderName + "/relPair3dresolution").c_str(), (";" + femtoDKout + "mctruth;" + femtoDKout + "_reco;" + femtoDKside + "mctruth;" + femtoDKside + "_reco;" + femtoDKlong + "mctruth;" + femtoDKlong + "_reco;" + "MC origin particle 1; MC origin particle 2;").c_str(), + kTHnSparseF, {femtoDKoutAxis, femtoDKoutAxis, femtoDKsideAxis, femtoDKsideAxis, femtoDKlongAxis, femtoDKlongAxis, {nOriginBins, 0, nOriginBins}, {nOriginBins, 0, nOriginBins}}); + } else { + mHistogramRegistry->add((folderName + "/relPair3dresolution").c_str(), (";" + femtoDKout + "mctruth;" + femtoDKside + "mctruth;" + femtoDKlong + "mctruth;" + femtoDKout + "_reco;" + femtoDKside + "_reco;" + femtoDKlong + "_reco;").c_str(), + kTHnSparseF, {femtoDKoutAxis, femtoDKoutAxis, femtoDKsideAxis, femtoDKsideAxis, femtoDKlongAxis, femtoDKlongAxis}); + } + } + template void init_3Dqn(HistogramRegistry* registry, T& DKoutBins, T& DKsideBins, T& DKlongBins, T& mTBins4D, T& multPercentileBins4D, - bool isMC, ConfigurableAxis qnBins = {"qnBins", {10, 0, 10}, "qn binning"}, ConfigurableAxis pairPhiBins = {"phiBins", {10, 0 - 0.05, TMath::Pi() + 0.05}, "pair phi binning"}) + bool isMC, ConfigurableAxis qnBins = {"qnBins", {10, 0, 10}, "qn binning"}, ConfigurableAxis pairPhiBins = {"phiBins", {10, 0 - 0.05, TMath::Pi() + 0.05}, "pair phi binning"}, bool smearingByOrigin = false) { mHistogramRegistry = registry; @@ -251,6 +267,8 @@ class FemtoDreamContainer folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + static_cast("_3Dqn"); init_base_3Dqn(folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong, DKoutAxis, DKsideAxis, DKlongAxis, mTAxis4D, multPercentileAxis4D, qnAxis, pairPhiAxis); + init_3Dqn_MC(folderName, femtoObsDKout, femtoObsDKside, femtoObsDKlong, + DKoutAxis, DKsideAxis, DKlongAxis, smearingByOrigin); } } @@ -484,11 +502,26 @@ class FemtoDreamContainer mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("_3Dqn") + HIST("/relPair3dRmTMultPercentileQnPairphi"), femtoDKout, femtoDKside, femtoDKlong, mT, multPercentile, myQnBin, pairPhiEP); } + /// Called by setPair_3Dqn only in case of Monte Carlo truth + /// Fills resolution of DKout, DKside, DKlong + void setPair_3Dqn_MC(std::vector k3dMC, std::vector k3d, const int originPart1, const int originPart2, bool smearingByOrigin) + { + if (smearingByOrigin) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("_3Dqn") + HIST("/relPair3dresolution"), k3dMC[1], k3d[1], k3dMC[2], k3d[2], k3dMC[3], k3d[3], originPart1, originPart2); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("_3Dqn") + HIST("/relPair3dresolution"), k3dMC[1], k3d[1], k3dMC[2], k3d[2], k3dMC[3], k3d[3]); + } + } + template - void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float eventPlane) + void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float eventPlane, bool smearingByOrigin = false) { std::vector k3d = FemtoDreamMath::newpairfunc(part1, mMassOne, part2, mMassTwo, IsSameSpecies); + if (k3d.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } float DKout = k3d[1]; float DKside = k3d[2]; float DKlong = k3d[3]; @@ -503,12 +536,17 @@ class FemtoDreamContainer if constexpr (isMC) { if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { - std::vector k3dMC = FemtoDreamMath::newpairfunc(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + std::vector k3dMC = FemtoDreamMath::newpairfuncMC(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + if (k3dMC.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, eventPlane); if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates setPair_3Dqn_base(k3dMC[1], k3dMC[2], k3dMC[3], mTMC, multPercentile, myQnBin, pairPhiEPMC); + setPair_3Dqn_MC(k3dMC, k3d, part1.fdMCParticle().partOriginMCTruth(), part2.fdMCParticle().partOriginMCTruth(), smearingByOrigin); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); } @@ -521,10 +559,14 @@ class FemtoDreamContainer } template - void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float EP1, const float EP2) + void setPair_3Dqn(T1 const& part1, T2 const& part2, const float multPercentile, bool IsSameSpecies, const float myQnBin, const float EP1, const float EP2, bool smearingByOrigin = false) { std::vector k3d = FemtoDreamMath::newpairfunc(part1, mMassOne, part2, mMassTwo, IsSameSpecies); + if (k3d.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } float DKout = k3d[1]; float DKside = k3d[2]; float DKlong = k3d[3]; @@ -539,12 +581,17 @@ class FemtoDreamContainer if constexpr (isMC) { if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { - std::vector k3dMC = FemtoDreamMath::newpairfunc(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + std::vector k3dMC = FemtoDreamMath::newpairfuncMC(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, IsSameSpecies); + if (k3dMC.size() < 4) { + LOG(error) << "newpairfunc returned size=" << k3d.size(); + return; + } const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); const float pairPhiEPMC = FemtoDreamMath::getPairPhiEP(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, EP1, EP2); if (std::abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && std::abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates setPair_3Dqn_base(k3dMC[1], k3dMC[2], k3dMC[3], mTMC, multPercentile, myQnBin, pairPhiEPMC); + setPair_3Dqn_MC(k3dMC, k3d, part1.fdMCParticle().partOriginMCTruth(), part2.fdMCParticle().partOriginMCTruth(), smearingByOrigin); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); } diff --git a/PWGCF/FemtoDream/Core/femtoDreamMath.h b/PWGCF/FemtoDream/Core/femtoDreamMath.h index 867f519ba79..cbb8257f590 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamMath.h +++ b/PWGCF/FemtoDream/Core/femtoDreamMath.h @@ -249,6 +249,98 @@ class FemtoDreamMath return vect; } + /// Compute the 3d components of the pair momentum in LCMS and PRF + /// Copy from femto universe + /// \tparam T type of tracks + /// \param part1 Particle 1 + /// \param mass1 Mass of particle 1 + /// \param part2 Particle 2 + /// \param mass2 Mass of particle 2 + /// \param isiden Identical or non-identical particle pair + template + static std::vector newpairfuncMC(const T& part1, const float mass1, const T& part2, const float mass2, bool isiden) + { + const double trkPx1 = part1.pt() * std::cos(part1.phi()); + const double trkPy1 = part1.pt() * std::sin(part1.phi()); + const double trkPz1 = part1.pt() * std::sinh(part1.eta()); + + const double trkPx2 = part2.pt() * std::cos(part2.phi()); + const double trkPy2 = part2.pt() * std::sin(part2.phi()); + const double trkPz2 = part2.pt() * std::sinh(part2.eta()); + + const double e1 = std::sqrt(std::pow(trkPx1, 2) + std::pow(trkPy1, 2) + std::pow(trkPz1, 2) + std::pow(mass1, 2)); + const double e2 = std::sqrt(std::pow(trkPx2, 2) + std::pow(trkPy2, 2) + std::pow(trkPz2, 2) + std::pow(mass2, 2)); + + const ROOT::Math::PxPyPzEVector vecpart1(trkPx1, trkPy1, trkPz1, e1); + const ROOT::Math::PxPyPzEVector vecpart2(trkPx2, trkPy2, trkPz2, e2); + const ROOT::Math::PxPyPzEVector trackSum = vecpart1 + vecpart2; + + std::vector vect; + + const double tPx = trackSum.px(); + const double tPy = trackSum.py(); + const double tPz = trackSum.pz(); + const double tE = trackSum.E(); + + const double tPtSq = (tPx * tPx + tPy * tPy); + const double tMtSq = (tE * tE - tPz * tPz); + const double tM = std::sqrt(tMtSq - tPtSq); + const double tMt = std::sqrt(tMtSq); + const double tPt = std::sqrt(tPtSq); + + // Boost to LCMS + + const double beta_LCMS = tPz / tE; + const double gamma_LCMS = tE / tMt; + + const double fDKOut = (trkPx1 * tPx + trkPy1 * tPy) / tPt; + const double fDKSide = (-trkPx1 * tPy + trkPy1 * tPx) / tPt; + const double fDKLong = gamma_LCMS * (trkPz1 - beta_LCMS * e1); + const double fDE = gamma_LCMS * (e1 - beta_LCMS * trkPz1); + + const double px1LCMS = fDKOut; + const double py1LCMS = fDKSide; + const double pz1LCMS = fDKLong; + const double pE1LCMS = fDE; + + const double px2LCMS = (trkPx2 * tPx + trkPy2 * tPy) / tPt; + const double py2LCMS = (trkPy2 * tPx - trkPx2 * tPy) / tPt; + const double pz2LCMS = gamma_LCMS * (trkPz2 - beta_LCMS * e2); + const double pE2LCMS = gamma_LCMS * (e2 - beta_LCMS * trkPz2); + + const double fDKOutLCMS = px1LCMS - px2LCMS; + const double fDKSideLCMS = py1LCMS - py2LCMS; + const double fDKLongLCMS = pz1LCMS - pz2LCMS; + + // Boost to PRF + + const double betaOut = tPt / tMt; + const double gammaOut = tMt / tM; + + const double fDKOutPRF = gammaOut * (fDKOutLCMS - betaOut * (pE1LCMS - pE2LCMS)); + const double fDKSidePRF = fDKSideLCMS; + const double fDKLongPRF = fDKLongLCMS; + const double fKOut = gammaOut * (fDKOut - betaOut * fDE); + + const double qlcms = std::sqrt(fDKOutLCMS * fDKOutLCMS + fDKSideLCMS * fDKSideLCMS + fDKLongLCMS * fDKLongLCMS); + const double qinv = std::sqrt(fDKOutPRF * fDKOutPRF + fDKSidePRF * fDKSidePRF + fDKLongPRF * fDKLongPRF); + const double kstar = std::sqrt(fKOut * fKOut + fDKSide * fDKSide + fDKLong * fDKLong); + + if (isiden) { + vect.push_back(qinv); + vect.push_back(fDKOutLCMS); + vect.push_back(fDKSideLCMS); + vect.push_back(fDKLongLCMS); + vect.push_back(qlcms); + } else { + vect.push_back(kstar); + vect.push_back(fDKOut); + vect.push_back(fDKSide); + vect.push_back(fDKLong); + } + return vect; + } + /// Compute the phi angular of a pair with respect to the event plane /// \tparam T type of tracks /// \param part1 Particle 1 diff --git a/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h b/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h index b0041a2e12d..5c9780d2e82 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h +++ b/PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h @@ -22,7 +22,6 @@ #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx index 9072069ea19..15686d79e9b 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx @@ -61,10 +61,11 @@ namespace o2::aod using FemtoFullCollision = soa::Join::iterator; using FemtoFullCollision_noCent = soa::Join::iterator; using FemtoFullCollision_CentPbPb = soa::Join::iterator; -using FemtoFullCollision_CentPbPb_qvec = soa::Join::iterator; +using FemtoFullCollision_CentPbPb_qvec = soa::Join::iterator; using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullCollision_noCent_MC = soa::Join::iterator; using FemtoFullCollisionMC_CentPbPb = soa::Join::iterator; +using FemtoFullCollisionMC_CentPbPb_qvec = soa::Join::iterator; using FemtoFullMCgenCollisions = soa::Join; using FemtoFullMCgenCollision = FemtoFullMCgenCollisions::iterator; @@ -281,6 +282,9 @@ struct femtoDreamProducerTask { Configurable ConfCentralityMax{"ConfCentralityMax", 100.f, "Evt sel: Maximum Centrality cut"}; Configurable ConfCentBinWidth{"ConfCentBinWidth", 1.f, "Centrality bin length for qn separator"}; Configurable ConfNumQnBins{"ConfNumQnBins", 10, "Number of qn bins"}; + Configurable ConfMCQvec{"ConfMCQvec", false, "Enable Q vector table for Monte Carlo"}; + Configurable ConfQvecDetector{"ConfQvecDetector", 0, "Q-vec detector selection; 0 : FT0C; 1 : FT0A"}; + Configurable ConfEPDetector{"ConfEPDetector", 0, "Event-plane detector selection; 0 : FT0C; 1 : FT0A; 2 : TPC"}; } epCal; struct : o2::framework::ConfigurableGroup { @@ -307,10 +311,10 @@ struct femtoDreamProducerTask { void init(InitContext&) { - if (doprocessData == false && doprocessData_noCentrality == false && doprocessData_CentPbPb == false && doprocessData_CentPbPb_EP == false && doprocessMC == false && doprocessMC_noCentrality == false && doprocessMC_CentPbPb == false) { + if (doprocessData == false && doprocessData_noCentrality == false && doprocessData_CentPbPb == false && doprocessData_CentPbPb_EP == false && doprocessMC == false && doprocessMC_noCentrality == false && doprocessMC_CentPbPb == false && doprocessMC_CentPbPb_EP == 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) || (doprocessData_noCentrality == true && doprocessData == true) || (doprocessData_noCentrality == true && doprocessMC == true) || (doprocessData_noCentrality == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessData == true) || (doprocessData_CentPbPb == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC == true) || (doprocessData_CentPbPb == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData == true) || (doprocessData_CentPbPb_EP == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData_CentPbPb == 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) || (doprocessData_CentPbPb == true && doprocessData == true) || (doprocessData_CentPbPb == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC == true) || (doprocessData_CentPbPb == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData == true) || (doprocessData_CentPbPb_EP == true && doprocessData_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_noCentrality == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessData_CentPbPb == true) || (doprocessData_CentPbPb_EP == true && doprocessMC_CentPbPb_EP == true) || (doprocessMC_CentPbPb_EP == true && doprocessData == true) || (doprocessMC_CentPbPb_EP == true && doprocessData_noCentrality == true) || (doprocessMC_CentPbPb_EP == true && doprocessMC == true) || (doprocessMC_CentPbPb_EP == true && doprocessMC_noCentrality == true) || (doprocessMC_CentPbPb_EP == true && doprocessMC_CentPbPb == true) || (doprocessMC_CentPbPb_EP == true && doprocessData_CentPbPb == true)) { LOGF(fatal, "Cannot enable more than one process switch at the same time. " "Please choose one."); @@ -771,7 +775,7 @@ struct femtoDreamProducerTask { } if constexpr (doFlow) { - fillCollisionsFlow(col, tracks, mult, spher, epCal.ConfHarmonicOrder); + fillCollisionsFlow(col, tracks, mult, spher, epCal.ConfHarmonicOrder); } std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children @@ -1126,12 +1130,16 @@ struct femtoDreamProducerTask { } } - template + template void fillCollisionsFlow(CollisionType const& col, TrackType const& tracks, float mult, float spher, int EPHarmonic) { - float myqn = colCuts.computeqnVec(col); - float myEP = TMath::RadToDeg() * colCuts.computeEP(col, EPHarmonic); - // psi from rad(0-pi) to deg, in table psi would be in deg,from 0-180 + float myqn = 0.f; + float myEP = 0.f; + + if (!isMC || epCal.ConfMCQvec) { + myqn = colCuts.computeqnVec(col, epCal.ConfQvecDetector); + myEP = TMath::RadToDeg() * colCuts.computeEP(col, EPHarmonic, epCal.ConfEPDetector); // psi from rad(0-pi) to deg, in table psi would be in deg,from 0-180 + } if ((myqn >= 0 && myqn < 1e6) || (myEP >= 0 && myEP < 180)) { outputExtQnCollision(myqn, col.trackOccupancyInTimeRange()); @@ -1139,14 +1147,13 @@ struct femtoDreamProducerTask { } // Calculate flow via cumulant - - if (epCal.ConfQnSeparation) { + if (epCal.ConfQnSeparation && (!isMC || epCal.ConfMCQvec)) { colCuts.myqnBin(mult, epCal.ConfCentralityMax, epCal.ConfFillFlowQA, epCal.ConfQnBinSeparator, myqn, epCal.ConfNumQnBins, epCal.ConfCentBinWidth); } - if (epCal.ConfFillFlowQA) { - colCuts.fillEPQA(mult, spher, myqn, myEP); + if (epCal.ConfFillFlowQA && (!isMC || epCal.ConfMCQvec)) { + colCuts.fillEPQA(col, mult, spher, myqn, myEP, EPHarmonic); if (epCal.ConfDoCumlant) { - colCuts.doCumulants(col, tracks, mult, epCal.ConfQnSeparation); + colCuts.doCumulants(col, tracks, trackCuts, mult, epCal.ConfQnSeparation); } } } @@ -1277,6 +1284,21 @@ struct femtoDreamProducerTask { fillCollisionsAndTracksAndV0AndCascade(col, tracks, tracks, fullV0s, fullCascades); } PROCESS_SWITCH(femtoDreamProducerTask, processMC_CentPbPb, "Provide MC data with centrality information for PbPb collisions", false); + + void processMC_CentPbPb_EP(aod::FemtoFullCollisionMC_CentPbPb_qvec const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::FemtoFullMCgenCollisions const&, + aod::McParticles const&, + soa::Join const& fullV0s, /// \todo with FilteredFullV0s + soa::Join const& fullCascades) + { + // get magnetic field for run + initCCDB_Mag_Trig(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0AndCascade(col, tracks, tracks, fullV0s, fullCascades); + } + PROCESS_SWITCH(femtoDreamProducerTask, processMC_CentPbPb_EP, "Provide MC data with centrality and q-vector table for PbPb collisions", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx index a5d4b1d9fe7..5823ce94d9f 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx @@ -30,6 +30,7 @@ #include "Framework/runDataProcessing.h" #include +#include #include using namespace o2; @@ -57,6 +58,7 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { Configurable confNumberOfV0{"confNumberOfV0", 1, "Number of V0"}; Configurable confNumberOfCascades{"confNumberOfCascades", 0, "Number of Cascades"}; Configurable confNumberOfReso{"confNumberOfReso", 1, "Number of Reso"}; + Configurable confFillAlsoK0short{"confFillAlsoK0short", true, "Fill also K0short"}; /// Track selection Configurable confPIDthrMom{"confPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; @@ -80,9 +82,31 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { Configurable confChildNegCutV0{"confChildNegCutV0", 149, "Selection bit for negative child of V0"}; Configurable confChildNegTPCBitV0{"confChildNegTPCBitV0", 2, "PID TPC bit for negative child of V0"}; + Configurable confCheckV0PIDcutLegacy{"confCheckV0PIDcutLegacy", false, "Flag for V0-children must fulfill PID cut in K0Short-K*-Legacy selection"}; + Configurable confV0ParticleType1TPCBitLegacy{"confV0ParticleType1TPCBitLegacy", 0, "PID TPC bit for first particle type of V0 child, checked in K0Short-K*-Legacy selection"}; + Configurable confV0ParticleType2TPCBitLegacy{"confV0ParticleType2TPCBitLegacy", 0, "PID TPC bit for second particle type of V0 child, checked in K0Short-K*-Legacy selection"}; + /// Cascade selection - Configurable confMinInvMassCascade{"confMinInvMassCascade", 1.2, "Minimum invariant mass of Cascade (particle)"}; - Configurable confMaxInvMassCascade{"confMaxInvMassCascade", 1.5, "Maximum invariant mass of Cascade (particle)"}; + struct : ConfigurableGroup { + std::string prefix = std::string("Cascade"); + Configurable confMinInvMassCascade{"ConfMinInvMass", 1.2, "Minimum invariant mass of Cascade (particle)"}; + Configurable confMaxInvMassCascade{"ConfMaxInvMass", 1.5, "Maximum invariant mass of Cascade (particle)"}; + Configurable CutBit{"CutBit", 228874909, "Selection bit for Cascade"}; + Configurable ChildPos_CutBit{"ChildPos_CutBit", 1190, "Selection bit for positive child of Cascade"}; + Configurable ChildPos_TPCBit{"ChildPos_TPCBit", 64, "PID TPC bit for positive child of Cascade"}; + Configurable ChildNeg_CutBit{"ChildNeg_CutBit", 1189, "Selection bit for negative child of Cascade"}; + Configurable ChildNeg_TPCBit{"ChildNeg_TPCBit", 256, "PID TPC bit for negative child of Cascade"}; + Configurable ChildBach_CutBit{"ChildBach_CutBit", 1189, "Selection bit for negative child of Cascade"}; + Configurable ChildBach_TPCBit{"ChildBach_TPCBit", 16, "PID TPC bit for bachelor child of Cascade"}; + + Configurable AntiCutBit{"AntiCutBit", 228874910, "Selection bit for AntiCascade"}; + Configurable AntiChildPos_CutBit{"AntiChildPos_CutBit", 1190, "Selection bit for positive child of AntiCascade"}; + Configurable AntiChildPos_TPCBit{"AntiChildPos_TPCBit", 256, "PID TPC bit for positive child of AntiCascade"}; + Configurable AntiChildNeg_CutBit{"AntiChildNeg_CutBit", 1189, "Selection bit for negative child of AntiCascade"}; + Configurable AntiChildNeg_TPCBit{"AntiChildNeg_TPCBit", 64, "PID TPC bit for negative child of AntiCascade"}; + Configurable AntiChildBach_CutBit{"AntiChildBach_CutBit", 1190, "Selection bit for negative child of AntiCascade"}; + Configurable AntiChildBach_TPCBit{"AntiChildBach_TPCBit", 16, "PID TPC bit for bachelor child of AntiCascade"}; + } Cascade; struct : ConfigurableGroup { // set loosest cuts std::string prefix = std::string("Reso"); @@ -93,6 +117,10 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { Configurable daughPosCutBit{"daughPosCutBit", 2401446, "Selection bit for positive child of Reso"}; Configurable daughNegCutBit{"daughNegCutBit", 2401445, "Selection bit for negative child of Reso"}; + + Configurable confCheckResoPIDcutLegacy{"confCheckResoPIDcutLegacy", false, "Flag for Reso-children must fulfill PID cut in K0Short-K*-Legacy selection"}; + Configurable confParticleType1TPCBitLegacy{"confParticleType1TPCBitLegacy", 0, "PID TPC bit for first particle type of Reso child, checked in K0Short-K*-Legacy selection"}; + Configurable confParticleType2TPCBitLegacy{"confParticleType2TPCBitLegacy", 0, "PID TPC bit for second particle type of Reso child, checked in K0Short-K*-Legacy selection"}; } Reso; // Partition for selected particles @@ -132,6 +160,201 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { return rowInPrimaryTrackTableDaugh; } + auto countCascades(const auto& theCascades, const auto& theParts) + { + /// check Cascades + int cascadeCount = 0; + int antiCascadeCount = 0; + for (const auto& casc : theCascades) { + if ((casc.cut() & KSignPlusMask) == KSignPlusMask) { + if (confRequireBitmask) { + if (ncheckbit(casc.cut(), Cascade.AntiCutBit)) { + const auto& posChild = theParts.iteratorAt(casc.index() - 3); + const auto& negChild = theParts.iteratorAt(casc.index() - 2); + const auto& bachChild = theParts.iteratorAt(casc.index() - 1); + if (((posChild.cut() & Cascade.AntiChildPos_CutBit) == Cascade.AntiChildPos_CutBit && + (posChild.pidcut() & Cascade.AntiChildPos_TPCBit) == Cascade.AntiChildPos_TPCBit && + (negChild.cut() & Cascade.AntiChildNeg_CutBit) == Cascade.AntiChildNeg_CutBit && + (negChild.pidcut() & Cascade.AntiChildNeg_TPCBit) == Cascade.AntiChildNeg_TPCBit && + (bachChild.cut() & Cascade.AntiChildBach_CutBit) == Cascade.AntiChildBach_CutBit && + (bachChild.pidcut() & Cascade.AntiChildBach_TPCBit) == Cascade.AntiChildBach_TPCBit)) { + antiCascadeCount++; + } + } + } else { + antiCascadeCount++; + } + } else { + if (confRequireBitmask) { + if (ncheckbit(casc.cut(), Cascade.CutBit)) { + const auto& posChild = theParts.iteratorAt(casc.index() - 3); + const auto& negChild = theParts.iteratorAt(casc.index() - 2); + const auto& bachChild = theParts.iteratorAt(casc.index() - 1); + if (((posChild.cut() & Cascade.ChildPos_CutBit) == Cascade.ChildPos_CutBit && + (posChild.pidcut() & Cascade.ChildPos_TPCBit) == Cascade.ChildPos_TPCBit && + (negChild.cut() & Cascade.ChildNeg_CutBit) == Cascade.ChildNeg_CutBit && + (negChild.pidcut() & Cascade.ChildNeg_TPCBit) == Cascade.ChildNeg_TPCBit && + (bachChild.cut() & Cascade.ChildBach_CutBit) == Cascade.ChildBach_CutBit && + (bachChild.pidcut() & Cascade.ChildBach_TPCBit) == Cascade.ChildBach_TPCBit)) { + cascadeCount++; + } + } + } else { + cascadeCount++; + } + } + } + return std::make_pair(cascadeCount, antiCascadeCount); + } + + auto countV0s(const auto& theV0s, const auto& theParts) + { + int v0Count = 0; + int antiV0Count = 0; + for (const auto& V0 : theV0s) { + if ((V0.mLambda() > confMinInvMassV0) && (V0.mLambda() < confMaxInvMassV0)) { + if (confRequireBitmask) { + if (ncheckbit(V0.cut(), confCutV0SameForAntipart)) { + const auto& posChild = theParts.iteratorAt(V0.index() - 2); + const auto& negChild = theParts.iteratorAt(V0.index() - 1); + if (((posChild.cut() & confChildPosCutV0) == confChildPosCutV0 && + (posChild.pidcut() & confChildPosTPCBitV0) == confChildPosTPCBitV0 && + (negChild.cut() & confChildNegCutV0) == confChildNegCutV0 && + (negChild.pidcut() & confChildNegTPCBitV0) == confChildNegTPCBitV0)) { + v0Count++; + } + } + } else { + v0Count++; + } + } else if ((V0.mAntiLambda() > confMinInvMassAntiV0) && (V0.mAntiLambda() < confMaxInvMassAntiV0)) { + if (confRequireBitmask) { + if (ncheckbit(V0.cut(), confCutV0SameForAntipart)) { + const auto& posChild = theParts.iteratorAt(V0.index() - 2); + const auto& negChild = theParts.iteratorAt(V0.index() - 1); + if (((posChild.cut() & confChildPosCutV0) == confChildPosCutV0 && + (posChild.pidcut() & confChildNegTPCBitV0) == confChildNegTPCBitV0 && // exchanged values because checking antiparticle daughters and pid of particles exchange + (negChild.cut() & confChildNegCutV0) == confChildNegCutV0 && + (negChild.pidcut() & confChildPosTPCBitV0) == confChildPosTPCBitV0)) { // exchanged values because checking antiparticle daughters and pid of particles exchange + antiV0Count++; + } + } + } else { + antiV0Count++; + } + } + } + return std::make_pair(v0Count, antiV0Count); + } + + void fillV0sAndDaughters(const auto& femtoParticle, const auto& tmpIDtrack, bool isK0Short = false) + { + + aod::femtodreamparticle::ParticleType typeV0 = isK0Short ? aod::femtodreamparticle::ParticleType::kV0K0Short : aod::femtodreamparticle::ParticleType::kV0; + aod::femtodreamparticle::ParticleType typeV0Child = isK0Short ? aod::femtodreamparticle::ParticleType::kV0K0ShortChild : aod::femtodreamparticle::ParticleType::kV0Child; + + if (typeV0Child == femtoParticle.partType()) { + std::vector childIDs = {0, 0}; + const auto& children = femtoParticle.childrenIds(); + int childId = (children[0] != 0) ? children[0] : children[1]; + if (childId != -1) { + int rowInPrimaryTrackTable = getRowDaughters(childId, tmpIDtrack); + childIDs = (children[0] != 0) ? std::vector{rowInPrimaryTrackTable, 0} : std::vector{0, rowInPrimaryTrackTable}; + } else { + childIDs = (children[0] != 0) ? std::vector{-1, 0} : std::vector{0, -1}; + } + outputParts(outputCollision.lastIndex(), + femtoParticle.pt(), + femtoParticle.eta(), + femtoParticle.phi(), + femtoParticle.partType(), + femtoParticle.cut(), + femtoParticle.pidcut(), + femtoParticle.tempFitVar(), + childIDs, + femtoParticle.mLambda(), + femtoParticle.mAntiLambda()); + } + if (typeV0 == femtoParticle.partType()) { + // If the order in primary producer is changed of storing first pos, neg daughters and then V0 - this must be updated + const int rowOfLastTrack = outputParts.lastIndex(); + std::vector childIDs = {rowOfLastTrack - 1, rowOfLastTrack}; + outputParts(outputCollision.lastIndex(), + femtoParticle.pt(), + femtoParticle.eta(), + femtoParticle.phi(), + femtoParticle.partType(), + femtoParticle.cut(), + femtoParticle.pidcut(), + femtoParticle.tempFitVar(), + childIDs, + femtoParticle.mLambda(), + femtoParticle.mAntiLambda()); + } + } + + void fillCascadesAndDaughters(const auto& femtoParticle, const auto& tmpIDtrack) + { + if (aod::femtodreamparticle::ParticleType::kCascadeV0Child == femtoParticle.partType() || aod::femtodreamparticle::ParticleType::kCascadeBachelor == femtoParticle.partType()) { + std::vector childIDs = {0, 0, 0}; + const auto& children = femtoParticle.childrenIds(); + int childId = 0; + if (children[0] != 0) { + childId = children[0]; + } else if (children[1] != 0) { + childId = children[1]; + } else if (children[2] != 0) { + childId = children[2]; + } + + if (childId != -1) { + int rowInPrimaryTrackTable = getRowDaughters(childId, tmpIDtrack); + if (children[0] != 0) { + childIDs = std::vector{rowInPrimaryTrackTable, 0, 0}; + } else if (children[1] != 0) { + childIDs = std::vector{0, rowInPrimaryTrackTable, 0}; + } else if (children[2] != 0) { + childIDs = std::vector{0, 0, rowInPrimaryTrackTable}; + } + } else { + if (children[0] != 0) { + childIDs = std::vector{-1, 0, 0}; + } else if (children[1] != 0) { + childIDs = std::vector{0, -1, 0}; + } else if (children[2] != 0) { + childIDs = std::vector{0, 0, -1}; + } + } + outputParts(outputCollision.lastIndex(), + femtoParticle.pt(), + femtoParticle.eta(), + femtoParticle.phi(), + femtoParticle.partType(), + femtoParticle.cut(), + femtoParticle.pidcut(), + femtoParticle.tempFitVar(), + childIDs, + femtoParticle.mLambda(), + femtoParticle.mAntiLambda()); + } + if (aod::femtodreamparticle::ParticleType::kCascade == femtoParticle.partType()) { + // If the order in primary producer is changed of storing first pos, neg daughters and then V0 - this must be updated + const int rowOfLastTrack = outputParts.lastIndex(); + std::vector childIDs = {rowOfLastTrack - 2, rowOfLastTrack - 1, rowOfLastTrack}; + outputParts(outputCollision.lastIndex(), + femtoParticle.pt(), + femtoParticle.eta(), + femtoParticle.phi(), + femtoParticle.partType(), + femtoParticle.cut(), + femtoParticle.pidcut(), + femtoParticle.tempFitVar(), + childIDs, + femtoParticle.mLambda(), + femtoParticle.mAntiLambda()); + } + } + void init(InitContext&) { eventRegistry.add("hStatistiscs", ";bin;Entries", kTH1F, {{3, 0, 3}}); @@ -297,31 +520,30 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { int tracksCount = 0; int antitracksCount = 0; for (const auto& part : groupSelectedTracks) { - if (part.cut() & 1) { - antitracksCount++; + if ((part.cut() & KSignPlusMask) == KSignPlusMask) { + if (!confRequireBitmask || ncheckbit(part.cut(), confCutPart)) { + tracksCount++; + } } else { - tracksCount++; + if (!confRequireBitmask || ncheckbit(part.cut(), confCutPartAntiPart)) { + antitracksCount++; + } } } /// check Cascades - int ascadeCount = 0; - int antiCascadeCount = 0; - for (const auto& casc : groupSelectedCascades) { - if ((casc.cut() & KSignPlusMask) == KSignPlusMask) { - ascadeCount++; - } else { - antiCascadeCount++; - } - } + auto cascadeCounters = countCascades(groupSelectedCascades, parts); + int cascadeCount = cascadeCounters.first; + int antiCascadeCount = cascadeCounters.second; std::vector tmpIDtrack; - if ((ascadeCount >= confNumberOfCascades && tracksCount >= confNumberOfTracks) || (antiCascadeCount >= confNumberOfCascades && antitracksCount >= confNumberOfTracks)) { + if ((cascadeCount >= confNumberOfCascades && tracksCount >= confNumberOfTracks) || (antiCascadeCount >= confNumberOfCascades && antitracksCount >= confNumberOfTracks)) { eventRegistry.fill(HIST("hStatistiscs"), 1); outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); for (const auto& femtoParticle : parts) { + if (aod::femtodreamparticle::ParticleType::kTrack == femtoParticle.partType()) { std::vector childIDs = {0, 0}; outputParts(outputCollision.lastIndex(), @@ -337,63 +559,11 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { femtoParticle.mAntiLambda()); tmpIDtrack.push_back(femtoParticle.index()); } - if (aod::femtodreamparticle::ParticleType::kCascadeV0Child == femtoParticle.partType() || aod::femtodreamparticle::ParticleType::kCascadeBachelor == femtoParticle.partType()) { - std::vector childIDs = {0, 0, 0}; - const auto& children = femtoParticle.childrenIds(); - int childId = 0; - if (children[0] != 0) { - childId = children[0]; - } else if (children[1] != 0) { - childId = children[1]; - } else if (children[2] != 0) { - childId = children[2]; - } - if (childId != -1) { - int rowInPrimaryTrackTable = getRowDaughters(childId, tmpIDtrack); - if (children[0] != 0) { - childIDs = std::vector{rowInPrimaryTrackTable, 0, 0}; - } else if (children[1] != 0) { - childIDs = std::vector{0, rowInPrimaryTrackTable, 0}; - } else if (children[2] != 0) { - childIDs = std::vector{0, 0, rowInPrimaryTrackTable}; - } - } else { - if (children[0] != 0) { - childIDs = std::vector{-1, 0, 0}; - } else if (children[1] != 0) { - childIDs = std::vector{0, -1, 0}; - } else if (children[2] != 0) { - childIDs = std::vector{0, 0, -1}; - } - } - outputParts(outputCollision.lastIndex(), - femtoParticle.pt(), - femtoParticle.eta(), - femtoParticle.phi(), - femtoParticle.partType(), - femtoParticle.cut(), - femtoParticle.pidcut(), - femtoParticle.tempFitVar(), - childIDs, - femtoParticle.mLambda(), - femtoParticle.mAntiLambda()); - } - if (aod::femtodreamparticle::ParticleType::kCascade == femtoParticle.partType()) { - // If the order in primary producer is changed of storing first pos, neg daughters and then V0 - this must be updated - const int rowOfLastTrack = outputParts.lastIndex(); - std::vector childIDs = {rowOfLastTrack - 2, rowOfLastTrack - 1, rowOfLastTrack}; - outputParts(outputCollision.lastIndex(), - femtoParticle.pt(), - femtoParticle.eta(), - femtoParticle.phi(), - femtoParticle.partType(), - femtoParticle.cut(), - femtoParticle.pidcut(), - femtoParticle.tempFitVar(), - childIDs, - femtoParticle.mLambda(), - femtoParticle.mAntiLambda()); + fillCascadesAndDaughters(femtoParticle, tmpIDtrack); + + if (confFillAlsoK0short) { + fillV0sAndDaughters(femtoParticle, tmpIDtrack, true); } } } else { @@ -415,6 +585,55 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { } PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNCascades, "Enable producing data with tracks and Cascades collisions for data", false); + /// This function stores accepted collisions in derived data + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupSelectedTracks partition for the first particle passed by the process function + /// @param groupSelectedV0s partition for the second particle passed by the process function + /// @param parts femtoDreamParticles table + template + void createSpecifiedDerivedDataV0Cascade(const o2::aod::FDCollision& col, PartitionType groupSelectedV0s, PartitionType groupSelectedCascades, PartType parts) + { + + /// check V0s + auto v0Counters = countV0s(groupSelectedV0s, parts); + int v0Count = v0Counters.first; + int antiV0Count = v0Counters.second; + /// check Cascades + auto cascadeCounters = countCascades(groupSelectedCascades, parts); + int cascadeCount = cascadeCounters.first; + int antiCascadeCount = cascadeCounters.second; + + std::vector tmpIDtrack; + + if ((cascadeCount >= confNumberOfCascades && v0Count >= confNumberOfV0) || (antiCascadeCount >= confNumberOfCascades && antiV0Count >= confNumberOfV0)) { + eventRegistry.fill(HIST("hStatistiscs"), 1); + outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); + + for (const auto& femtoParticle : parts) { + fillV0sAndDaughters(femtoParticle, tmpIDtrack); + fillCascadesAndDaughters(femtoParticle, tmpIDtrack); + } + } else { + eventRegistry.fill(HIST("hStatistiscs"), 2); + } + } + + /// process function to create derived data with only collisions containing n tracks + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processCollisionsWithNV0sAndNCascades(const o2::aod::FDCollision& col, + const o2::aod::FDParticles& parts) + { + eventRegistry.fill(HIST("hStatistiscs"), 0); + auto thegroupSelectedV0s = selectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupSelectedCascades = selectedCascades->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + createSpecifiedDerivedDataV0Cascade(col, thegroupSelectedV0s, thegroupSelectedCascades, parts); + } + PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNV0sAndNCascades, "Enable producing data with ppp collisions for data", false); + template void createSpecifiedDerivedDataV0Phi(const o2::aod::FDCollision& col, PartitionType groupSelectedV0s, PartitionType groupSelectedResos, PartType parts) { @@ -801,7 +1020,11 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { for (const auto& femtoParticle : parts) { - if (aod::femtodreamparticle::ParticleType::kResoChild == femtoParticle.partType()) { + bool resoChildFulfillsPID = !Reso.confCheckResoPIDcutLegacy || + ((femtoParticle.pidcut() & Reso.confParticleType1TPCBitLegacy) == Reso.confParticleType1TPCBitLegacy) || + ((femtoParticle.pidcut() & Reso.confParticleType2TPCBitLegacy) == Reso.confParticleType2TPCBitLegacy); + + if ((aod::femtodreamparticle::ParticleType::kResoChild == femtoParticle.partType()) && resoChildFulfillsPID) { std::vector childIDs; const auto& children = femtoParticle.childrenIds(); childIDs.push_back(children[0]); @@ -841,7 +1064,11 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { femtoParticle.mAntiLambda()); } - if (aod::femtodreamparticle::ParticleType::kV0Child == femtoParticle.partType()) { + bool v0ChildFulfillsPID = !confCheckV0PIDcutLegacy || + ((femtoParticle.pidcut() & confV0ParticleType1TPCBitLegacy) == confV0ParticleType1TPCBitLegacy) || + ((femtoParticle.pidcut() & confV0ParticleType2TPCBitLegacy) == confV0ParticleType2TPCBitLegacy); + + if ((aod::femtodreamparticle::ParticleType::kV0Child == femtoParticle.partType()) && v0ChildFulfillsPID) { std::vector childIDs; const auto& children = femtoParticle.childrenIds(); childIDs.push_back(children[0]); @@ -891,6 +1118,207 @@ struct FemtoDreamProducerTaskForSpecificAnalysis { createSpecifiedDerivedDataK0ShortKStarLegacy(col, thegroupSelectedV0s, thegroupSelectedResos, parts); } PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, createSpecifiedDerivedDataNK0ShortNKStarLegacy, "Enable producing data with pp collisions for data K0Short-KStar with kV0Child/KResoChild daughter types", false); + + template + void createSpecifiedDerivedDataK0ShortKStarFromMothers(const o2::aod::FDCollision& col, PartitionType groupSelectedV0s, PartitionType groupSelectedResos, PartType parts) + { + // check v0's + int v0Count = 0; + int antiV0Count = 0; + int resoCount = 0; // no antiparticles + + for (const auto& V0 : groupSelectedV0s) { + if ((V0.mLambda() > confMinInvMassV0) && (V0.mLambda() < confMaxInvMassV0)) { + if (confRequireBitmask) { + if (ncheckbit(V0.cut(), confCutV0SameForAntipart)) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + if (((posChild.cut() & confChildPosCutV0) == confChildPosCutV0 && + (posChild.pidcut() & confChildPosTPCBitV0) == confChildPosTPCBitV0 && + (negChild.cut() & confChildNegCutV0) == confChildNegCutV0 && + (negChild.pidcut() & confChildNegTPCBitV0) == confChildNegTPCBitV0)) { + v0Count++; + } + } + } else { + v0Count++; + } + } else if ((V0.mAntiLambda() > confMinInvMassAntiV0) && (V0.mAntiLambda() < confMaxInvMassAntiV0)) { + if (confRequireBitmask) { + if (ncheckbit(V0.cut(), confCutV0SameForAntipart)) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + if (((posChild.cut() & confChildPosCutV0) == confChildPosCutV0 && + (posChild.pidcut() & confChildNegTPCBitV0) == confChildNegTPCBitV0 && // exchanged values because checking antiparticle daughters and pid of particles exchange + (negChild.cut() & confChildNegCutV0) == confChildNegCutV0 && + (negChild.pidcut() & confChildPosTPCBitV0) == confChildPosTPCBitV0)) { // exchanged values because checking antiparticle daughters and pid of particles exchange + antiV0Count++; + } + } + } else { + antiV0Count++; + } + } + } + + for (const auto& reso : groupSelectedResos) { + if (confRequireBitmask) { + + const auto& posresoChild = parts.iteratorAt(reso.index() - 2); + const auto& negresoChild = parts.iteratorAt(reso.index() - 1); + + if (((posresoChild.cut() & Reso.daughPosCutBit) == Reso.daughPosCutBit) && + ((negresoChild.cut() & Reso.daughNegCutBit) == Reso.daughNegCutBit)) { + + resoCount++; + } + } else { + resoCount++; + } + } + + std::vector tmpIDtrack; + + if ((v0Count >= confNumberOfV0 && resoCount >= confNumberOfReso) || (antiV0Count >= confNumberOfV0 && resoCount >= confNumberOfReso)) { + eventRegistry.fill(HIST("hStatistiscs"), 1); + outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); + + for (const auto& femtoParticle : parts) { + + if ((femtoParticle.partType() == uint8_t(aod::femtodreamparticle::kResoKStarPosdaughTPC_NegdaughTPC)) || + (femtoParticle.partType() == uint8_t(aod::femtodreamparticle::kResoKStarPosdaughTPC_NegdaughTOF)) || + (femtoParticle.partType() == uint8_t(aod::femtodreamparticle::kResoKStarPosdaughTOF_NegdaughTPC)) || + (femtoParticle.partType() == uint8_t(aod::femtodreamparticle::kResoKStarPosdaughTOF_NegdaughTOF))) { + + const auto& posresoChild = parts.iteratorAt(femtoParticle.index() - 2); + const auto& negresoChild = parts.iteratorAt(femtoParticle.index() - 1); + + // fill positive child + std::vector childIDsPos; + const auto& childrenPos = posresoChild.childrenIds(); + childIDsPos.push_back(childrenPos[0]); + childIDsPos.push_back(childrenPos[1]); + outputParts(outputCollision.lastIndex(), + posresoChild.pt(), + posresoChild.eta(), + posresoChild.phi(), + posresoChild.partType(), + posresoChild.cut(), + posresoChild.pidcut(), + posresoChild.tempFitVar(), + childIDsPos, + posresoChild.mLambda(), + posresoChild.mAntiLambda()); + + // fill negative child + std::vector childIDsNeg; + const auto& childrenNeg = negresoChild.childrenIds(); + childIDsNeg.push_back(childrenNeg[0]); + childIDsNeg.push_back(childrenNeg[1]); + outputParts(outputCollision.lastIndex(), + negresoChild.pt(), + negresoChild.eta(), + negresoChild.phi(), + negresoChild.partType(), + negresoChild.cut(), + negresoChild.pidcut(), + negresoChild.tempFitVar(), + childIDsNeg, + negresoChild.mLambda(), + negresoChild.mAntiLambda()); + + // fill mother + std::vector childIDs; + const auto& children = femtoParticle.childrenIds(); + childIDs.push_back(children[0]); + childIDs.push_back(children[1]); + outputParts(outputCollision.lastIndex(), + femtoParticle.pt(), + femtoParticle.eta(), + femtoParticle.phi(), + femtoParticle.partType(), + femtoParticle.cut(), + femtoParticle.pidcut(), + femtoParticle.tempFitVar(), + childIDs, + femtoParticle.mLambda(), + femtoParticle.mAntiLambda()); + } + + if (aod::femtodreamparticle::ParticleType::kV0K0Short == femtoParticle.partType()) { + + const auto& posV0Child = parts.iteratorAt(femtoParticle.index() - 2); + const auto& negV0Child = parts.iteratorAt(femtoParticle.index() - 1); + + // fill positive child + std::vector childIDsPos; + const auto& childrenPos = posV0Child.childrenIds(); + childIDsPos.push_back(childrenPos[0]); + childIDsPos.push_back(childrenPos[1]); + + outputParts(outputCollision.lastIndex(), + posV0Child.pt(), + posV0Child.eta(), + posV0Child.phi(), + posV0Child.partType(), + posV0Child.cut(), + posV0Child.pidcut(), + posV0Child.tempFitVar(), + childIDsPos, + posV0Child.mLambda(), + posV0Child.mAntiLambda()); + + // fill negative child + std::vector childIDsNeg; + const auto& childrenNeg = negV0Child.childrenIds(); + childIDsNeg.push_back(childrenNeg[0]); + childIDsNeg.push_back(childrenNeg[1]); + + outputParts(outputCollision.lastIndex(), + negV0Child.pt(), + negV0Child.eta(), + negV0Child.phi(), + negV0Child.partType(), + negV0Child.cut(), + negV0Child.pidcut(), + negV0Child.tempFitVar(), + childIDsNeg, + negV0Child.mLambda(), + negV0Child.mAntiLambda()); + + // fill mother + std::vector childIDs; + const auto& children = femtoParticle.childrenIds(); + childIDs.push_back(children[0]); + childIDs.push_back(children[1]); + outputParts(outputCollision.lastIndex(), + femtoParticle.pt(), + femtoParticle.eta(), + femtoParticle.phi(), + femtoParticle.partType(), + femtoParticle.cut(), + femtoParticle.pidcut(), + femtoParticle.tempFitVar(), + childIDs, + femtoParticle.mLambda(), + femtoParticle.mAntiLambda()); + } + } + } else { + eventRegistry.fill(HIST("hStatistiscs"), 2); + } + } + + void createSpecifiedDerivedDataNK0ShortNKStarFromMothers(const o2::aod::FDCollision& col, + const o2::aod::FDParticles& parts) + { + eventRegistry.fill(HIST("hStatistiscs"), 0); + auto thegroupSelectedResos = selectedKStar->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupSelectedV0s = selectedK0Short->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + createSpecifiedDerivedDataK0ShortKStarFromMothers(col, thegroupSelectedV0s, thegroupSelectedResos, parts); + } + PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, createSpecifiedDerivedDataNK0ShortNKStarFromMothers, "Enable producing data with pp collisions for data K0Short-KStar just from mother particle types", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx index f2100431efd..0d97ae5b676 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamPairTaskTrackTrack.cxx @@ -95,6 +95,7 @@ struct femtoDreamPairTaskTrackTrack { Configurable storeEvtTrkInfo{"storeEvtTrkInfo", false, "Fill info of track1 and track2 while pariing in divided qn bins"}; Configurable doQnSeparation{"doQnSeparation", false, "Do qn separation"}; Configurable doEPReClibForMixing{"doEPReClibForMixing", false, "While mixing, using respective event plane for participating particles azimuthal angle caulculation"}; + Configurable mcQvec{"mcQvec", false, "Enable Q vector table for Monte Carlo"}; Configurable> qnBinSeparator{"qnBinSeparator", std::vector{-999.f, -999.f, -999.f}, "Qn bin separator"}; Configurable numQnBins{"numQnBins", 10, "Number of qn bins"}; Configurable qnBinMin{"qnBinMin", 0, "Number of qn bins"}; @@ -113,6 +114,8 @@ struct femtoDreamPairTaskTrackTrack { using FilteredMCCollision = FilteredMCCollisions::iterator; using FilteredQnCollisions = soa::Filtered>; using FilteredQnCollision = FilteredQnCollisions::iterator; + using FilteredMCQnCollisions = soa::Filtered>; + using FilteredMCQnCollision = FilteredMCQnCollisions::iterator; using FilteredMaskedCollisions = soa::Filtered>; using FilteredMaskedCollision = FilteredMaskedCollisions::iterator; @@ -322,9 +325,9 @@ struct femtoDreamPairTaskTrackTrack { if (EPCal.do3DFemto) { sameEventQnCont.init_3Dqn(&Registry, EPCal.DKout, EPCal.DKside, EPCal.DKlong, - Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins); + Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins, Option.SmearingByOrigin); mixedEventQnCont.init_3Dqn(&Registry, EPCal.DKout, EPCal.DKside, EPCal.DKlong, - Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins); + Binning4D.mT, Binning4D.multPercentile, Option.IsMC, EPCal.qnBins, EPCal.pairPhiBins, Option.SmearingByOrigin); sameEventQnCont.setPDGCodes(Track1.PDGCode, Track2.PDGCode); mixedEventQnCont.setPDGCodes(Track1.PDGCode, Track2.PDGCode); if (EPCal.fillFlowQA) { @@ -377,7 +380,10 @@ struct femtoDreamPairTaskTrackTrack { (doprocessMixedEvent && doprocessMixedEventEP) || (doprocessMixedEventMasked && doprocessMixedEventEP) || (doprocessSameEventMC && doprocessSameEventMCMasked) || - (doprocessMixedEventMC && doprocessMixedEventMCMasked)) { + (doprocessSameEventMC && doprocessSameEventEPMC) || + (doprocessMixedEventMC && doprocessMixedEventMCMasked) || + (doprocessMixedEventMC && doprocessMixedEventEPMC) || + (doprocessMixedEventMCMasked && doprocessMixedEventEPMC)) { LOG(fatal) << "Normal and masked processing cannot be activated simultaneously!"; } }; @@ -704,17 +710,20 @@ struct femtoDreamPairTaskTrackTrack { } } - auto myEP = TMath::DegToRad() * col.eventPlane(); + float myEP = -999.f; int myqnBin = -999; - if (EPCal.doQnSeparation || EPCal.do3DFemto) { - myqnBin = epCalculator.myqnBin(col.multV0M(), EPCal.centMax, EPCal.fillFlowQA, EPCal.qnBinSeparator, col.qnVal(), EPCal.numQnBins, EPCal.centBinWidth); - if (myqnBin < EPCal.qnBinMin || myqnBin > EPCal.numQnBins) { - myqnBin = -999; - } - } - if (EPCal.fillFlowQA) { - epCalculator.fillEPQA(col.multV0M(), col.sphericity(), col.qnVal(), col.eventPlane()); + if (!isMC || EPCal.mcQvec) { + myEP = TMath::DegToRad() * col.eventPlane(); + if (EPCal.doQnSeparation || EPCal.do3DFemto) { + myqnBin = epCalculator.myqnBin(col.multV0M(), EPCal.centMax, EPCal.fillFlowQA, EPCal.qnBinSeparator, col.qnVal(), EPCal.numQnBins, EPCal.centBinWidth); + if (myqnBin < EPCal.qnBinMin || myqnBin > EPCal.numQnBins) { + myqnBin = -999; + } + } + } else { + myEP = 0.f; + myqnBin = 0; } /// Now build the combinations @@ -738,14 +747,14 @@ struct femtoDreamPairTaskTrackTrack { sameEventQnCont.setPair_EP(p1, p2, col.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? myqnBin + 0.f : myEP); } if (EPCal.do3DFemto) { - sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP); + sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP, Option.SmearingByOrigin); } } else { if (EPCal.do1DFemto) { sameEventQnCont.setPair_EP(p2, p1, col.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? myqnBin + 0.f : myEP); } if (EPCal.do3DFemto) { - sameEventQnCont.setPair_3Dqn(p2, p1, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP); + sameEventQnCont.setPair_3Dqn(p2, p1, col.multV0M(), Option.SameSpecies.value, myqnBin + 0.f, myEP, Option.SmearingByOrigin); } } } @@ -764,7 +773,7 @@ struct femtoDreamPairTaskTrackTrack { sameEventQnCont.setPair_EP(p1, p2, col.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? myqnBin + 0.f : myEP); } if (EPCal.do3DFemto) { - sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myEP, myqnBin); + sameEventQnCont.setPair_3Dqn(p1, p2, col.multV0M(), Option.SameSpecies.value, myEP, myqnBin, Option.SmearingByOrigin); } } } @@ -789,6 +798,28 @@ struct femtoDreamPairTaskTrackTrack { } PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processSameEventEP, "Enable processing same event wrt azimuthal angle and event-plane ", false); + /// process function for to call doSameEventEP with MC Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEventEPMC(FilteredMCQnCollision& col, + o2::aod::FDMCCollisions&, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + if (EPCal.storeEvtTrkInfo) { + fillCollision(col); + } + auto SliceTrk1 = PartitionMCTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto SliceTrk2 = PartitionMCTrk2->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + if (SliceTrk1.size() == 0 && SliceTrk2.size() == 0) { + return; + } + if (EPCal.do1DFemto || EPCal.do3DFemto) { + doSameEventEP(SliceTrk1, SliceTrk2, parts, col); + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processSameEventEPMC, "Enable processing same event of 3D for Monte Carlo", false); + template void doMixedEvent_NotMaskedEP(CollisionType& cols, PartType& parts, PartitionType& part1, PartitionType& part2, BinningType policy) { @@ -799,8 +830,16 @@ struct femtoDreamPairTaskTrackTrack { continue; } - auto myEP_event1 = TMath::DegToRad() * collision1.eventPlane(); - auto myEP_event2 = TMath::DegToRad() * collision2.eventPlane(); + auto myEP_event1 = -999.f; + auto myEP_event2 = -999.f; + + if (!isMC || EPCal.mcQvec) { + myEP_event1 = TMath::DegToRad() * collision1.eventPlane(); + myEP_event2 = TMath::DegToRad() * collision2.eventPlane(); + } else { + myEP_event1 = 0.f; + myEP_event2 = 0.f; + } for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(SliceTrk1, SliceTrk2))) { if (Option.CPROn.value) { @@ -816,13 +855,13 @@ struct femtoDreamPairTaskTrackTrack { mixedEventQnCont.setPair_EP(p1, p2, collision1.multV0M(), EPCal.doQnSeparation, myEP_event1, myEP_event2); } if (EPCal.do3DFemto) { - mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1, myEP_event2); + mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1, myEP_event2, Option.SmearingByOrigin); } } else { if (EPCal.do1DFemto) mixedEventQnCont.setPair_EP(p1, p2, collision1.multV0M(), EPCal.doQnSeparation, EPCal.doQnSeparation ? 0.f : myEP_event1); if (EPCal.do3DFemto) { - mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1); + mixedEventQnCont.setPair_3Dqn(p1, p2, collision1.multV0M(), Option.SameSpecies.value, 0.f, myEP_event1, Option.SmearingByOrigin); } } } @@ -855,6 +894,33 @@ struct femtoDreamPairTaskTrackTrack { } } PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processMixedEventEP, "Enable processing mixed events wrt azimuthal angle and event-plane", false); + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEventEPMC(FilteredMCQnCollisions& cols, o2::aod::FDMCCollisions&, soa::Join& parts, o2::aod::FDMCParticles&) + { + switch (Mixing.Policy.value) { + case femtodreamcollision::kMult: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMult); + break; + case femtodreamcollision::kMultPercentile: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultPercentile); + break; + case femtodreamcollision::kMultMultPercentile: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultMultPercentile); + break; + case femtodreamcollision::kMultPercentileQn: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultPercentileqn); + break; + case femtodreamcollision::kMultPercentileEP: + doMixedEvent_NotMaskedEP(cols, parts, PartitionMCTrk1, PartitionMCTrk2, colBinningMultPercentileEP); + break; + default: + LOG(fatal) << "Invalid binning policiy specifed. Breaking..."; + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrack, processMixedEventEPMC, "Enable processing mixed events wrt azimuthal angle and event-plane for Monte Carlo", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0PbPb.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0PbPb.cxx index 84ec7dc9cd8..32e5a81a5f8 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0PbPb.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackV0PbPb.cxx @@ -79,10 +79,10 @@ struct FemtoDreamTripletTaskTrackTrackV0PbPb { Configurable confMinDCAxy{"confMinDCAxy", -0.1f, "Minimum DCAxy of the particles"}; Configurable confPIDthrMom{"confPIDthrMom", 0.75f, "Momentum threshold from which TPC and TOF are required for PID"}; Configurable confIsMC{"confIsMC", false, "Enable additional Histogramms 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 confIsAddPairsInTriplet{"confIsAddPairsInTriplet", false, "Extra histograms and pairing for tracks in triplet"}; Configurable confDCACutPtDep{"confDCACutPtDep", false, "Use pt dependent dca cut for tracks"}; - Configurable confDCACutPtDepPar0{"confDCACutPtDepPar0", 0.0105, "Parameter par[0] of the pt dep cut, par[0] + par[1]/(pT/(GeV/c)−1.1) cm"}; - Configurable confDCACutPtDepPar1{"confDCACutPtDepPar1", 0.035, "Parameter par[1] of the pt dep cut, par[0] + par[1]/(pT/(GeV/c)−1.1) cm"}; + Configurable confDCACutPtDepPar0{"confDCACutPtDepPar0", 0.004, "Parameter par[0] of the pt dep cut, par[0] + par[1]/(pT/(GeV/c)−1.1) cm"}; + Configurable confDCACutPtDepPar1{"confDCACutPtDepPar1", 0.013, "Parameter par[1] of the pt dep cut, par[0] + par[1]/(pT/(GeV/c)−1.1) cm"}; /// Partition for selected particles Partition selectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && @@ -232,6 +232,10 @@ struct FemtoDreamTripletTaskTrackTrackV0PbPb { threeBodyQARegistry.add("TripletTaskQA/hTestPairCleanerPosAfter", ";primaryTrack; posDaughtID", kTH2F, {{40, -20, 20}, {40, -20, 20}}); threeBodyQARegistry.add("TripletTaskQA/hTestPairCleanerNegAfter", ";primaryTrack; negDaughtID", kTH2F, {{40, -20, 20}, {40, -20, 20}}); threeBodyQARegistry.add("TripletTaskQA/hCentralityME", ";Centrality;Entries", kTH1F, {{100, 0.0, 100.0}}); + if (confIsAddPairsInTriplet) { + threeBodyQARegistry.add("SameEvent/relPairDist_trackTrack", ";k* (GeV/c) ;Entries", kTH1F, {{4000, 0., 4.}}); + threeBodyQARegistry.add("MixedEvent/relPairDist_trackTrack", ";k* (GeV/c) ;Entries", kTH1F, {{4000, 0., 4.}}); + } sameEventCont.init(&resultRegistry, confQ3Bins, confMultBins, confIsMC); mixedEventCont.init(&resultRegistry, confQ3Bins, confMultBins, confIsMC); sameEventCont.setPDGCodes(confPDGCodePart, confPDGCodePart, confPDGCodeV0); @@ -322,6 +326,7 @@ struct FemtoDreamTripletTaskTrackTrackV0PbPb { trackHistoselectedParts.fillQA(part, aod::femtodreamparticle::kPt, multCol, centCol); } /// Histograming V0s + int v0Counter = 0; for (const auto& V0 : groupselectedV0s) { const auto& posChild = parts.iteratorAt(V0.index() - 2); const auto& negChild = parts.iteratorAt(V0.index() - 1); @@ -397,6 +402,15 @@ struct FemtoDreamTripletTaskTrackTrackV0PbPb { threeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_SE"), T1.pt(), T2.pt(), V0.pt(), q3); sameEventCont.setTriplet(T1, T2, V0, multCol, q3); threeBodyQARegistry.fill(HIST("TripletTaskQA/hCentrality"), centCol, q3); + + // Teporary test: pairing the same event tracks in the triplet task (without triplet-combinatoric repetitions) + if (confIsAddPairsInTriplet) { + if (v0Counter == 0) { + auto kstarTT = FemtoDreamMath::getkstar(T1, mMassOne, T2, mMassTwo); + threeBodyQARegistry.fill(HIST("SameEvent/relPairDist_trackTrack"), kstarTT); + } + } + v0Counter = 1; } } } @@ -577,6 +591,19 @@ struct FemtoDreamTripletTaskTrackTrackV0PbPb { threeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_ME"), T1.pt(), T2.pt(), V0.pt(), q3); mixedEventCont.setTriplet(T1, T2, V0, multCol, q3); } + + // Teporary test: pairing the mixed event tracks in the triplet task (without triplet-combinatoric repetitions) + if (confIsAddPairsInTriplet) { + for (const auto& [T1, T2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (confIsCPR.value) { + if (pairCloseRejectionTrackTrackME.isClosePair(T1, T2, parts, magFieldTesla)) { + continue; + } + } + auto kstarTT = FemtoDreamMath::getkstar(T1, mMassOne, T2, mMassTwo); + threeBodyQARegistry.fill(HIST("MixedEvent/relPairDist_trackTrack"), kstarTT); + } + } } /// process function for to call doMixedEvent with Data diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h index 77c8798a3b7..d0b33319ffd 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverse3DContainer.h @@ -216,22 +216,36 @@ 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) + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, bool isIdenLCMS, bool isWeight, bool isIdenPRF) { std::vector f3d; const float kT = FemtoUniverseMath::getkT(part1, mMassOne, part2, mMassTwo); const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); - f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, isiden); + f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, isIdenLCMS, isWeight, isIdenPRF); + + float varout = 0.0; + float varside = 0.0; + float varlong = 0.0; + + if (isIdenLCMS) { + varout = f3d[1]; + varside = f3d[2]; + varlong = f3d[3]; + } else if (isIdenPRF) { + varout = f3d[6]; + varside = f3d[7]; + varlong = f3d[8]; + } const float femtoObs1D = f3d[0]; - const float femtoObsKout = f3d[1]; - const float femtoObsKside = f3d[2]; - const float femtoObsKlong = f3d[3]; + const float femtoObsKout = varout; + const float femtoObsKside = varside; + const float femtoObsKlong = varlong; if (mHistogramRegistry) { - setPairBase(femtoObsKout, femtoObsKside, femtoObsKlong, femtoObs1D, kT, mT, part1, part2, mult, use3dplots, isiden); - if (!isiden) { + setPairBase(femtoObsKout, femtoObsKside, femtoObsKlong, femtoObs1D, kT, mT, part1, part2, mult, use3dplots, isIdenLCMS); + if (!isIdenLCMS) { if (femtoObsKout > 0.0) { mHistogramRegistry->fill(HIST(FolderSuffix[EventType]) + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[o2::aod::femtouniverse_mc_particle::MCType::kRecon]) + HIST("/KStarOutP"), femtoObs1D); } else { diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h index 2db4b16f03e..c72e756e062 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h @@ -91,6 +91,7 @@ class FemtoUniverseContainer if (use3dplots) { mHistogramRegistry->add((folderName + "/relPairkstarmTMult").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2}); Multiplicity").c_str(), kTH3F, {femtoObsAxis, mTAxis3D, multAxis3D}); mHistogramRegistry->add((folderName + "/relPairkstarkTMult").c_str(), ("; " + femtoObs + "; #it{k}_{T} (GeV/#it{c}^{2}); Multiplicity").c_str(), kTH3F, {femtoObsAxis, kTAxis, multAxis3D}); + mHistogramRegistry->add((folderName + "/relPairkTPtPart1PtPart2").c_str(), ("; #it{k}_{T} (GeV/#it{c}^{2}); #it{p}_{T,1} (GeV/#it{c}^{2}); #it{p}_{T,2} (GeV/#it{c}^{2})"), kTH3F, {kTAxis, {375, 0., 7.5}, {375, 0., 7.5}}); } } @@ -200,6 +201,7 @@ class FemtoUniverseContainer if (use3dplots) { mHistogramRegistry->fill(HIST(FolderSuffix[EventType]) + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/relPairkstarmTMult"), femtoObs, mT, mult, weight); mHistogramRegistry->fill(HIST(FolderSuffix[EventType]) + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/relPairkstarkTMult"), femtoObs, kT, mult, weight); + mHistogramRegistry->fill(HIST(FolderSuffix[EventType]) + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/relPairkTPtPart1PtPart2"), kT, part1.pt(), part2.pt()); } } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index c939a4f269d..05e0cfb5682 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -643,7 +643,7 @@ class FemtoUniverseDetaDphiStar /// Check if pair is close or not template - bool isClosePairkT(Part const& part1, Part const& part2, uint8_t ChosenEventType, float ktval, bool CircCut) + bool isClosePairkT(Part const& part1, Part const& part2, uint8_t ChosenEventType, float ktval, bool CircCut, bool IsDphiAvgOrDist, float lmagfield, float DistMax, float FracMax) { /// Track-Track combination // check if provided particles are in agreement with the class instantiation @@ -663,8 +663,11 @@ class FemtoUniverseDetaDphiStar ktbinval = 4; } + magfield = lmagfield; + auto deta = part1.eta() - part2.eta(); auto dphiAvg = averagePhiStar(part1, part2, 0); + auto distfrac = averagePhiStarFrac(part1, part2, DistMax); auto DeltaPhiStarMax = static_cast(cutDeltaPhiStarMaxVector[ktbinval]); auto DeltaPhiStarMin = static_cast(cutDeltaPhiStarMinVector[ktbinval]); auto DeltaEtaMax = static_cast(cutDeltaEtaMaxVector[ktbinval]); @@ -678,19 +681,35 @@ class FemtoUniverseDetaDphiStar LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; } - if (CircCut && (std::pow(dphiAvg, 2) / std::pow(DeltaPhiStarMax, 2) + std::pow(deta, 2) / std::pow(DeltaEtaMax, 2) < 1.)) { - return true; - } else if (!CircCut && (dphiAvg > DeltaPhiStarMin) && (dphiAvg < DeltaPhiStarMax) && (deta > DeltaEtaMin) && (deta < DeltaEtaMax)) { - return true; + if (IsDphiAvgOrDist) { + if (CircCut && (std::pow(dphiAvg, 2) / std::pow(DeltaPhiStarMax, 2) + std::pow(deta, 2) / std::pow(DeltaEtaMax, 2) < 1.)) { + // std::cout<<"1 "< DeltaPhiStarMin) && (dphiAvg < DeltaPhiStarMax) && (deta > DeltaEtaMin) && (deta < DeltaEtaMax)) { + return true; + } else { + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadphisameafterkT[ktbinval]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadphimixedafterkT[ktbinval]->Fill(deta, dphiAvg); + } else { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + } + return false; + } } else { - if (ChosenEventType == femto_universe_container::EventType::same) { - histdetadphisameafterkT[ktbinval]->Fill(deta, dphiAvg); - } else if (ChosenEventType == femto_universe_container::EventType::mixed) { - histdetadphimixedafterkT[ktbinval]->Fill(deta, dphiAvg); + if (((deta > DeltaEtaMin) && (deta < DeltaEtaMax)) && (distfrac > FracMax)) { + return true; } else { - LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadphisameafterkT[ktbinval]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadphimixedafterkT[ktbinval]->Fill(deta, dphiAvg); + } else { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + } + return false; } - return false; } } @@ -877,7 +896,7 @@ class FemtoUniverseDetaDphiStar badpoints++; } } - return badpoints / entries; + return (static_cast(badpoints) / static_cast(entries)); } // Get particle charge from mask diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h index 64d0f2153d3..680fc61eaf7 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h @@ -177,7 +177,7 @@ class FemtoUniverseMath /// \param mass2 Mass of particle 2 /// \param isiden Identical or non-identical particle pair template - static std::vector newpairfunc(const T& part1, const float mass1, const T& part2, const float mass2, bool isiden, bool isWeight = 0) + static std::vector newpairfunc(const T& part1, const float mass1, const T& part2, const float mass2, bool isIdenLCMS, bool isWeight, bool isIdenPRF) { const double e1 = std::sqrt(std::pow(part1.px(), 2) + std::pow(part1.py(), 2) + std::pow(part1.pz(), 2) + std::pow(mass1, 2)); const double e2 = std::sqrt(std::pow(part2.px(), 2) + std::pow(part2.py(), 2) + std::pow(part2.pz(), 2) + std::pow(mass2, 2)); @@ -225,7 +225,6 @@ class FemtoUniverseMath const double fDKOutLCMS = px1LCMS - px2LCMS; const double fDKSideLCMS = py1LCMS - py2LCMS; const double fDKLongLCMS = pz1LCMS - pz2LCMS; - const double mDE = pE1LCMS - pE2LCMS; // Boost to PRF @@ -241,7 +240,7 @@ class FemtoUniverseMath const double qinv = std::sqrt(fDKOutPRF * fDKOutPRF + fDKSidePRF * fDKSidePRF + fDKLongPRF * fDKLongPRF); const double kstar = std::sqrt(fKOut * fKOut + fDKSide * fDKSide + fDKLong * fDKLong); - if (isiden) { + if (isIdenLCMS) { vect.push_back(qinv); vect.push_back(fDKOutLCMS); vect.push_back(fDKSideLCMS); @@ -252,9 +251,10 @@ class FemtoUniverseMath vect.push_back(fDKOut); vect.push_back(fDKSide); vect.push_back(fDKLong); + vect.push_back(1.0); } - if (isiden && isWeight) { + if (isIdenLCMS && isWeight) { const double x1_lcms = (vecspace_part1.x() * tPx + vecspace_part1.y() * tPy) / tPt; const double y1_lcms = (-vecspace_part1.x() * tPy + vecspace_part1.y() * tPx) / tPt; const double x2_lcms = (vecspace_part2.x() * tPx + vecspace_part2.y() * tPy) / tPt; @@ -269,12 +269,22 @@ class FemtoUniverseMath const double mRS = (y1_lcms - y2_lcms) / 0.197327; const double mRL = (z1_lcms - z2_lcms) / 0.197327; const double mDT = (t1_lcms - t2_lcms) / 0.197327; + const double rOutPRF = gammaOut * (mRO - betaOut * mDT); + + const double phase_inv = fDKOutPRF * rOutPRF + fDKSidePRF * mRS + fDKLongPRF * mRL; + double quantumweight = 1.0 + TMath::Cos(2.0 * phase_inv); - const double quantumweight = 1.0 + std::cos(-fDKOutLCMS * mRO - fDKSideLCMS * mRS - fDKLongLCMS * mRL + mDE * mDT); vect.push_back(quantumweight); } else { vect.push_back(1.0); } + + if (isIdenPRF) { + vect.push_back(fDKOutPRF); + vect.push_back(fDKSidePRF); + vect.push_back(fDKLongPRF); + } + return vect; } }; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h index 377e7677c0b..9f5afb0ab1a 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePairSHCentMultKt.h @@ -51,7 +51,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, bool isqinvfill, int /*maxl*/) { pairSHCentMultKtRegistry = registry; AxisSpec kstarAxis = {kstarbins, "#it{k*} (GeV/#it{c})"}; @@ -154,6 +154,21 @@ class PairSHCentMultKt {(kMaxJM * 2), -0.5, ((static_cast(kMaxJM) * 2.0 - 0.5))}}); } + if (isqinvfill) { + if (FolderSuffix[EventType] == FolderSuffix[0]) { + std::string bufnameNum = "h1DNum"; + fnums1D[i][j] = pairSHCentMultKtRegistry->add( + (histFolderMult + "/" + histFolderkT + "/" + bufnameNum).c_str(), + ("; " + femtoObs1D + "; Entries").c_str(), kTH1D, {femtoObsAxis1D}); + fnums1D[i][j]->Sumw2(); + } else if (FolderSuffix[EventType] == FolderSuffix[1]) { + std::string bufnameNum = "h1DDen"; + fdens1D[i][j] = pairSHCentMultKtRegistry->add( + (histFolderMult + "/" + histFolderkT + "/" + bufnameNum).c_str(), + ("; " + femtoObs1D + "; Entries").c_str(), kTH1D, {femtoObsAxis1D}); + fdens1D[i][j]->Sumw2(); + } + } } } } @@ -165,7 +180,7 @@ class PairSHCentMultKt /// \param ktval kT value template void fillMultNumDen(T const& part1, T const& part2, uint8_t ChosenEventType, - int maxl, int multval, float ktval, bool isiden) + int maxl, int multval, float ktval, bool isIdenLCMS, bool isqinvfill, bool isWeight, bool isIdenPRF) { int multbinval; int absmultval = multval; @@ -182,7 +197,7 @@ class PairSHCentMultKt return; } // std::cout<<"multbinval "< void fillkTNumDen(T const& part1, T const& part2, uint8_t ChosenEventType, - int maxl, int multval, float ktval, bool isiden) + int maxl, int multval, float ktval, bool isIdenLCMS, bool isqinvfill, bool isWeight, bool isIdenPRF) { int ktbinval = -1; if (ktval >= ktBins[0] && ktval < ktBins[1]) { @@ -214,7 +229,7 @@ class PairSHCentMultKt } else { return; } - addEventPair(part1, part2, ChosenEventType, maxl, multval, ktbinval, isiden); + addEventPair(part1, part2, ChosenEventType, maxl, multval, ktbinval, isIdenLCMS, isqinvfill, isWeight, isIdenPRF); } /// Set the PDG codes of the two particles involved @@ -247,20 +262,33 @@ class PairSHCentMultKt /// \param ktval kT value template void addEventPair(T const& part1, T const& part2, uint8_t ChosenEventType, - int /*maxl*/, int multval, int ktval, bool isiden) + int /*maxl*/, int multval, int ktval, bool isIdenLCMS, bool isqinvfill, bool isWeight, bool isIdenPRF) { int fMultBin = multval; int fKtBin = ktval; std::vector> fYlmBuffer(kMaxJM); std::vector f3d; setPionPairMass(); - f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, - isiden); - const float qout = f3d[1]; - const float qside = f3d[2]; - const float qlong = f3d[3]; + f3d = FemtoUniverseMath::newpairfunc(part1, mMassOne, part2, mMassTwo, + isIdenLCMS, isWeight, isIdenPRF); + double varout = 0.0; + double varside = 0.0; + double varlong = 0.0; + + if (isIdenLCMS) { + varout = f3d[1]; + varside = f3d[2]; + varlong = f3d[3]; + } else if (isIdenPRF) { + varout = f3d[6]; + varside = f3d[7]; + varlong = f3d[8]; + } + const double qout = varout; + const double qside = varside; + const double qlong = varlong; double kv = std::sqrt(qout * qout + qside * qside + qlong * qlong); // int nqbin = fbinctn[0][0]->GetXaxis()->FindFixBin(kv); @@ -275,6 +303,9 @@ class PairSHCentMultKt fnumsimag[fMultBin][fKtBin][ihist]->Fill(kv, -imag(fYlmBuffer[ihist])); fbinctn[fMultBin][fKtBin]->Fill(kv, 1.0); } + if (isqinvfill) { + fnums1D[fMultBin][fKtBin]->Fill(f3d[0]); + } for (int ilmzero = 0; ilmzero < kMaxJM * 2; ilmzero++) { for (int ilmprim = 0; ilmprim < kMaxJM * 2; ilmprim++) { if ((ilmzero % 2) == 0 && (ilmprim % 2) == 0) { @@ -294,6 +325,9 @@ class PairSHCentMultKt fdensimag[fMultBin][fKtBin][ihist]->Fill(kv, -imag(fYlmBuffer[ihist])); fbinctd[fMultBin][fKtBin]->Fill(kv, 1.0); } + if (isqinvfill) { + fdens1D[fMultBin][fKtBin]->Fill(f3d[0]); + } for (int ilmzero = 0; ilmzero < kMaxJM * 2; ilmzero++) { for (int ilmprim = 0; ilmprim < kMaxJM * 2; ilmprim++) { if ((ilmzero % 2) == 0 && (ilmprim % 2) == 0) { @@ -362,6 +396,8 @@ class PairSHCentMultKt std::array, 10>, 7>, 4> fnumsimag{}; std::array, 10>, 7>, 4> fdensreal{}; std::array, 10>, 7>, 4> fdensimag{}; + std::array, 7>, 4> fnums1D{}; + std::array, 7>, 4> fdens1D{}; TH1D* fbinctn[10][10]; TH1D* fbinctd[10][10]; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h index 49c354dcd6b..508cb8994c4 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h @@ -70,7 +70,7 @@ class FemtoUniverseParticleHisto // comment template - void init_debug(std::string folderName, T& tempFitVarpTAxis) // o2-linter: disable=name/function-variable + void init_debug(std::string folderName, T& tempFitVarMomAxis) // o2-linter: disable=name/function-variable { std::string folderSuffix = static_cast(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]).c_str(); 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) { @@ -81,27 +81,27 @@ class FemtoUniverseParticleHisto mHistogramRegistry->add((folderName + folderSuffix + "/hTPCcrossedRows").c_str(), "; TPC crossed rows; Entries", kTH1F, {{163, -0.5, 162.5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfindableVsCrossed").c_str(), ";TPC findable clusters ; TPC crossed rows;", kTH2F, {{163, -0.5, 162.5}, {163, -0.5, 162.5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTPCshared").c_str(), "; TPC shared clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfractionSharedCls").c_str(), "; TPC fraction of shared clusters; Entries", kTH1F, {{100, 0.0, 100.0}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCfractionSharedCls").c_str(), "; TPC fraction of shared clusters; Entries", kTH1F, {{100, 0.0, 1.0}}); mHistogramRegistry->add((folderName + folderSuffix + "/hITSclusters").c_str(), "; ITS clusters; Entries", kTH1F, {{10, -0.5, 9.5}}); mHistogramRegistry->add((folderName + folderSuffix + "/hITSclustersIB").c_str(), "; ITS clusters in IB; Entries", kTH1F, {{10, -0.5, 9.5}}); 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, {{tempFitVarpTAxis}, {1000, 0, 1000}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{tempFitVarpTAxis}, {200, -4.975, 5.025}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{tempFitVarpTAxis}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{tempFitVarpTAxis}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{tempFitVarpTAxis}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{p}", kTH2F, {{tempFitVarpTAxis}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{d}", kTH2F, {{tempFitVarpTAxis}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTPCdEdX").c_str(), "; #it{p} (GeV/#it{c}); TPC Signal", kTH2F, {{tempFitVarMomAxis}, {1000, 0, 1000}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{tempFitVarMomAxis}, {200, -4.975, 5.025}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{tempFitVarMomAxis}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{tempFitVarMomAxis}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{tempFitVarMomAxis}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{p}", kTH2F, {{tempFitVarMomAxis}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{d}", kTH2F, {{tempFitVarMomAxis}, {100, 0, 5}}); } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0) { mHistogramRegistry->add((folderName + folderSuffix + "/hDaughDCA").c_str(), "; DCA^{daugh} (cm); Entries", kTH1F, {{1000, 0, 10}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTransRadius").c_str(), "; #it{r}_{xy} (cm); Entries", kTH1F, {{1500, 0, 150}}); @@ -238,6 +238,7 @@ class FemtoUniverseParticleHisto } framework::AxisSpec tempFitVarpTAxis = {tempFitVarpTBins, "#it{p}_{T} (GeV/#it{c})"}; // the pT binning may vary + framework::AxisSpec tempFitVarMomAxis = {tempFitVarpTBins, "#it{p} (GeV/#it{c})"}; // the p binning framework::AxisSpec tempFitVarAxis = {tempFitVarBins, tempFitVarAxisTitle}; // std::string folderName = (static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]).c_str() + static_cast(mFolderSuffix[mFolderSuffixType])).c_str(); @@ -246,7 +247,7 @@ class FemtoUniverseParticleHisto // Fill here the actual histogramms by calling init_base and init_MC init_base(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); if (isDebug) { - init_debug(folderName, tempFitVarpTAxis); + init_debug(folderName, tempFitVarMomAxis); } if (isMC) { init_base(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h index 63d9646cdde..5bee5c8940b 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h @@ -101,7 +101,7 @@ class FemtoUniverseSelection /// \param cutContainer Bit-wise container for the systematic variations /// \param counter Position in the bit-wise container for the systematic variations to be modified template - void checkSelectionSetBit(selValDataType observable, T& cutContainer, size_t& counter) + void checkSelectionSetBit(selValDataType observable, T& cutContainer, std::size_t& counter) { /// If the selection is fulfilled the bit at the specified position (counter) within the bit-wise container is set to 1 if (isSelected(observable)) { diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h index 51c711c8165..3aee759b29b 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h @@ -23,6 +23,8 @@ #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/HistogramRegistry.h" diff --git a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h index 4fe562d7fef..c9b158ce1b5 100644 --- a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h +++ b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h @@ -17,7 +17,8 @@ #define PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTODERIVED_H_ #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index fd01a746887..d73fc6794e5 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -135,6 +135,9 @@ struct FemtoUniverseProducerTask { Configurable confStoreMCmothers{"confStoreMCmothers", false, "MC truth: Fill with not only primary particles and store mothers' PDG in tempFitVar."}; Configurable confFillCollExt{"confFillCollExt", false, "Option to fill collision extended table"}; + Configurable confCollMCTruthOnlyReco{"confCollMCTruthOnlyReco", false, "Fill only MC truth collisions that were reconstructed and selected"}; + Configurable confFillMCTruthV0Daugh{"confFillMCTruthV0Daugh", true, "Fill MC truth daughters of V0"}; + /// Event filtering (used for v0-cascade analysis) Configurable zorroMask{"zorroMask", "", "zorro trigger class to select on (empty: none)"}; @@ -241,23 +244,20 @@ struct FemtoUniverseProducerTask { 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{"confDcaXYCustom11FilterCut", 0.004, "Value for [1] custom DCAxy cut -> |DCAxy| < [1] + [2]/pT"}; - Configurable confDcaXYCustom12FilterCut{"confDcaXYCustom12FilterCut", 0.013, "Value for [2] custom DCAxy cut -> |DCAxy| < [1] + [2]/pT"}; + Configurable confDcaXYCustom1FilterCut{"confDcaXYCustom1FilterCut", 0.0105, "Value for [1] custom DCAxy cut -> |DCAxy| < [1] + [2]/pT"}; + Configurable confDcaXYCustom2FilterCut{"confDcaXYCustom2FilterCut", 0.035, "Value for [2] custom DCAxy cut -> |DCAxy| < [1] + [2]/pT"}; + Configurable confDcaZCustom1FilterCut{"confDcaZCustom1FilterCut", 0.02, "Value for [1] custom cut on DCAz -> |DCAz| < [1] + [2]/pT"}; + Configurable confDcaZCustom2FilterCut{"confDcaZCustom2FilterCut", 0.0, "Value for [2] custom cut on DCAz -> |DCAz| < [1] + [2]/pT"}; Configurable confIsApplyTrkCutMCTruth{"confIsApplyTrkCutMCTruth", false, "Apply eta, pT selection cut on MCTruth tracks "}; Configurable confIsOnlyPrimary{"confIsOnlyPrimary", false, "Select only primaries"}; } ConfFilterCuts; - Filter globalCutFilter = requireGlobalTrackInFilter(); + Filter globalCutFilter = requireGlobalTrackWoDCAInFilter(); Filter customTrackFilter = (aod::track::pt > ConfFilterCuts.confPtLowFilterCut) && (aod::track::pt < ConfFilterCuts.confPtHighFilterCut) && (nabs(aod::track::eta) < ConfFilterCuts.confEtaFilterCut) && - (!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 + (nabs(aod::track::dcaZ) < (ConfFilterCuts.confDcaZCustom1FilterCut + ConfFilterCuts.confDcaZCustom2FilterCut / aod::track::pt)) && + (nabs(aod::track::dcaXY) < (ConfFilterCuts.confDcaXYCustom1FilterCut + ConfFilterCuts.confDcaXYCustom2FilterCut / aod::track::pt)); // CASCADE FemtoUniverseCascadeSelection cascadeCuts; @@ -341,7 +341,7 @@ struct FemtoUniverseProducerTask { Configurable trackD0pTGenMax{"trackD0pTGenMax", 24.0, "MC Truth, max. pT for tracks and D0/D0bar cand."}; Configurable useYCutD0Cand{"useYCutD0Cand", true, "True - apply cut on y of D0 cand./false - apply cut on eta"}; Configurable storeD0D0barDoubleMassHypo{"storeD0D0barDoubleMassHypo", false, "Store D0/D0bar cand. which pass selection criteria for both, D0 and D0bar"}; - Configurable> classMlD0D0bar{"classMlD0D0bar", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; + Configurable fillCorrBkgsD0{"fillCorrBkgsD0", false, "Flag to fill derived tables with correlated background candidates"}; } ConfD0Selection; // PID bitmask configurables @@ -881,12 +881,17 @@ struct FemtoUniverseProducerTask { template int32_t getMotherPDG(ParticleType particle) { - auto motherparticlesMC = particle.template mothers_as(); - if (!motherparticlesMC.empty()) { + if (particle.isPhysicalPrimary()) { + return 0; + } else if (particle.has_mothers()) { + if (particle.getProcess() == 20 || particle.getProcess() == 23) { // treat particles from hadronic scattering (20, 23) as primary + return 0; + } + auto motherparticlesMC = particle.template mothers_as(); auto motherparticleMC = motherparticlesMC.front(); - return particle.isPhysicalPrimary() ? 0 : motherparticleMC.pdgCode(); + return motherparticleMC.pdgCode(); } else { - return 9999; + return 999; } } @@ -926,7 +931,7 @@ struct FemtoUniverseProducerTask { outputPartsMCLabels(outputPartsMC.lastIndex()); } else { outputPartsMCLabels(-1); - outputDebugPartsMC(9999); + outputDebugPartsMC(-999); } } @@ -1234,8 +1239,9 @@ struct FemtoUniverseProducerTask { confIsUseCutculator ? cutContainer.at( femto_universe_track_selection::TrackContainerPosition::kPID) : PIDBitmask(track), - track.dcaXY(), childIDs, 0, - track.sign()); // sign getter is mAntiLambda() + track.dcaXY(), childIDs, + track.hasTOF(), // hasTOF getter is mLambda() + track.sign()); // sign getter is mAntiLambda() tmpIDtrack.push_back(track.globalIndex()); if (confIsDebug) { @@ -1422,7 +1428,7 @@ struct FemtoUniverseProducerTask { if (ConfFilterCuts.confIsOnlyPrimary) { if (!mc.isPhysicalPrimary()) { - return; + continue; } } @@ -1829,8 +1835,10 @@ struct FemtoUniverseProducerTask { for (const auto& hfCand : hfCands) { - if (!(hfCand.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { - continue; + if (!ConfD0Selection.fillCorrBkgsD0) { + if (!(hfCand.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + continue; + } } if (ConfD0Selection.useYCutD0Cand && std::abs(hfHelper.yD0(hfCand)) > ConfD0Selection.yD0CandMax) { @@ -1847,11 +1855,11 @@ struct FemtoUniverseProducerTask { auto arrayDaughters = std::array{postrack, negtrack}; indexMcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); - if (!(indexMcRec > -1)) { + if (!ConfD0Selection.fillCorrBkgsD0 && !(indexMcRec > -1)) { continue; } - if (std::abs(hfCand.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { + if ((std::abs(hfCand.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (ConfD0Selection.fillCorrBkgsD0 && hfCand.flagMcMatchRec() != 0)) { int postrackID = hfCand.prong0Id(); // Index to first prong int rowInPrimaryTrackTablePos = -1; rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); @@ -2139,6 +2147,7 @@ struct FemtoUniverseProducerTask { // instead of the bitmask, the PDG of the particle is stored as uint32_t int32_t variablePDG = confStoreMCmothers ? getMotherPDG(particle) : particle.pdgCode(); + int32_t variableCut = confStoreMCmothers ? particle.getProcess() : 0; // now the table is filled if constexpr (resolveDaughs) { @@ -2153,7 +2162,7 @@ struct FemtoUniverseProducerTask { particle.eta(), particle.phi(), aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, + variableCut, pdgCode, variablePDG, childIDs, @@ -2168,7 +2177,7 @@ struct FemtoUniverseProducerTask { // aligned, so that they can be joined in the task. if constexpr (transientLabels) { outputPartsMCLabels(-1); - outputDebugPartsMC(9999); + outputDebugPartsMC(-999); } } if constexpr (resolveDaughs) { @@ -2192,13 +2201,14 @@ struct FemtoUniverseProducerTask { } int32_t variablePDG = confStoreMCmothers ? getMotherPDG(particle) : particle.pdgCode(); + int32_t variableCut = confStoreMCmothers ? particle.getProcess() : 0; outputParts(outputCollision.lastIndex(), particle.pt(), particle.eta(), particle.phi(), aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, + variableCut, static_cast(particle.pdgCode()), variablePDG, childIDs, @@ -2213,7 +2223,7 @@ struct FemtoUniverseProducerTask { // aligned, so that they can be joined in the task. if constexpr (transientLabels) { outputPartsMCLabels(-1); - outputDebugPartsMC(9999); + outputDebugPartsMC(-999); } } } @@ -2300,7 +2310,7 @@ struct FemtoUniverseProducerTask { template - void fillCollisionsAndTracksAndV0AndPhi(CollisionType const& col, TrackType const& tracks, V0Type const& fullV0s) + bool fillCollisionsAndTracksAndV0AndPhi(CollisionType const& col, TrackType const& tracks, V0Type const& fullV0s) { const auto colcheck = fillCollisions(col, tracks); if (colcheck) { @@ -2312,6 +2322,7 @@ struct FemtoUniverseProducerTask { fillPhi(col, tracks); } } + return colcheck; } void processFullData(aod::FemtoFullCollision const& col, @@ -2564,7 +2575,11 @@ struct FemtoUniverseProducerTask { Preslice& ps) { // recos - std::set recoMcIds; + static std::set recoMcIds; + static std::set mcColIds; + recoMcIds.clear(); + mcColIds.clear(); + for (const auto& col : collisions) { auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); auto groupedStrageParts = strangeParts.sliceBy(ps, col.globalIndex()); @@ -2572,11 +2587,15 @@ struct FemtoUniverseProducerTask { if constexpr (std::experimental::is_detected::value) { const auto colcheck = fillCollisions(col, groupedTracks); if (colcheck) { + mcColIds.insert(col.mcCollisionId()); fillTracks(groupedTracks); fillCascade(col, groupedStrageParts, groupedTracks); } } else { - fillCollisionsAndTracksAndV0AndPhi(col, groupedTracks, groupedStrageParts); + const auto colcheck = fillCollisionsAndTracksAndV0AndPhi(col, groupedTracks, groupedStrageParts); + if (colcheck) { + mcColIds.insert(col.mcCollisionId()); + } } for (const auto& track : groupedTracks) { if (trackCuts.isSelectedMinimal(track)) @@ -2587,6 +2606,9 @@ struct FemtoUniverseProducerTask { // truth for (const auto& mccol : mccols) { auto groupedMCParticles = mcParticles.sliceBy(perMCCollision, mccol.globalIndex()); + if (confCollMCTruthOnlyReco && !mcColIds.contains(mccol.globalIndex())) { + continue; + } auto groupedCollisions = collisions.sliceBy(recoCollsPerMCColl, mccol.globalIndex()); fillMCTruthCollisions(groupedCollisions, groupedMCParticles); // fills the reco collisions for mc collision fillParticles(groupedMCParticles, recoMcIds); // fills mc particles @@ -2601,6 +2623,7 @@ struct FemtoUniverseProducerTask { { // recos std::set recoMcIds; + std::set mcCollisions; for (const auto& col : collisions) { auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); auto bc = col.bc_as(); @@ -2616,6 +2639,7 @@ struct FemtoUniverseProducerTask { } if (colcheck) { + mcCollisions.insert(col.mcCollisionId()); fillCollisionsCentRun3ColExtra(col, ir); fillTracks(groupedTracks); } @@ -2627,6 +2651,9 @@ struct FemtoUniverseProducerTask { // truth for (const auto& mccol : mccols) { + if (confCollMCTruthOnlyReco && !mcCollisions.contains(mccol.globalIndex())) { + continue; + } auto groupedCollisions = collisions.sliceBy(recoCollsPerMCCollCentPbPb, mccol.globalIndex()); for (const auto& col : groupedCollisions) { const auto colcheck = fillMCTruthCollisionsCentRun3(col); // fills the reco collisions for mc collision @@ -2871,12 +2898,14 @@ struct FemtoUniverseProducerTask { // MCReco std::set recoMcIds; + std::set mcCollisions; for (const auto& col : collisions) { // loop over collisions auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); // slicing for tracks auto groupedV0Parts = fullV0s.sliceBy(perCollisionV0s, col.globalIndex()); // slicing for V0 getMagneticFieldTesla(col.bc_as()); const auto colcheck = fillCollisionsCentRun3(col); if (colcheck) { + mcCollisions.insert(col.mcCollisionId()); fillTracks(groupedTracks); fillV0(col, groupedV0Parts, groupedTracks); } @@ -2888,13 +2917,20 @@ struct FemtoUniverseProducerTask { // MCTruth for (const auto& mccol : mccols) { + if (confCollMCTruthOnlyReco && !mcCollisions.contains(mccol.globalIndex())) { + continue; + } auto groupedCollisions = collisions.sliceBy(recoCollsPerMCCollCentPbPb, mccol.globalIndex()); // slicing for MC collisions auto groupedMCParticles = mcParticles.sliceBy(perMCCollision, mccol.globalIndex()); // slicing for MC particles for (const auto& col : groupedCollisions) { const auto colcheck = fillMCTruthCollisionsCentRun3(col); if (colcheck) { outputCollExtra(1.0, 1.0); - fillV0MCTruth(groupedMCParticles); // fills MC V0s and its daughters + if (confFillMCTruthV0Daugh) { + fillV0MCTruth(groupedMCParticles); // fills MC V0s and its daughters + } else { + fillParticles(groupedMCParticles, recoMcIds); // fills mc particles + } } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx index 6e5af4e8d52..c503b0e46c8 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx @@ -14,14 +14,17 @@ /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch -#include -#include -#include #include "PWGCF/FemtoUniverse/Core/FemtoUniverseCutculator.h" + #include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include +#include +#include +#include + using namespace o2::analysis::femto_universe; /// The function takes the path to the dpl-config.json as a argument and the @@ -30,9 +33,8 @@ using namespace o2::analysis::femto_universe; int main(int /*argc*/, char* argv[]) { std::string configFileName(argv[1]); - std::filesystem::path configFile{configFileName}; - - if (std::filesystem::exists(configFile)) { + std::ifstream configFile(configFileName); + if (configFile.good()) { FemtoUniverseCutculator cut; cut.init(argv[1]); diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx index 984ab7d973e..4984b3283f4 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx @@ -14,6 +14,12 @@ /// \author Luca Barioglio, TU München, luca.barioglio@cern.ch /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + #include "DataFormatsParameters/GRPObject.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" @@ -22,11 +28,8 @@ #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include +#include using namespace o2; using namespace o2::analysis::femto_universe; @@ -36,49 +39,49 @@ using namespace o2::soa; namespace { -static constexpr int nCuts = 5; +static constexpr int NCuts = 5; static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; -static const float cutsTable[1][nCuts] = {{4.05f, 0.75f, 3.f, 3.f, 100.f}}; +static const float cutsTable[1][NCuts] = {{4.05f, 0.75f, 3.f, 3.f, 100.f}}; } // namespace -struct femtoUniverseDebugTrack { +struct FemtoUniverseDebugTrack { SliceCache cache; - Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nCuts, cutNames}, "Particle selections"}; - Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable> confCutTable{"confCutTable", {cutsTable[0], NCuts, cutNames}, "Particle selections"}; + Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; struct : o2::framework::ConfigurableGroup { - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; - 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 confPDGCodePartOne{"confPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + 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"}; } trackonefilter; 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 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 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"}; + 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 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 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"}; } generalPIDcuts; - // Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; - Configurable ConfPIDPartOne{"ConfPIDPartOne", 1, "Particle 1 - Read from cutCulator"}; - Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{3.5f, 3.f, 2.5f}, "This configurable needs to be the same as the one used in the producer task"}; - ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + // Configurable confCutPartOne{"confCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; + Configurable confPIDPartOne{"confPIDPartOne", 1, "Particle 1 - Read from cutCulator"}; + Configurable> confTrkPIDnSigmaMax{"confTrkPIDnSigmaMax", std::vector{3.5f, 3.f, 2.5f}, "This configurable needs to be the same as the one used in the producer task"}; + ConfigurableAxis confTempFitVarBins{"confDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; FemtoUniverseTrackSelection trackCuts; using FemtoFullParticles = soa::Join; - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(trackonefilter.ConfTrackSign)); // && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(trackonefilter.confTrackSign)); // && ((aod::femtouniverseparticle::cut & confCutPartOne) == confCutPartOne); Preslice perColReco = aod::femtouniverseparticle::fdCollisionId; using FemtoFullParticlesMC = soa::Join; - Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(trackonefilter.ConfTrackSign)); // && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(trackonefilter.confTrackSign)); // && ((aod::femtouniverseparticle::cut & confCutPartOne) == confCutPartOne); Preslice perColGen = aod::femtouniverseparticle::fdCollisionId; /// Histogramming for Event @@ -100,17 +103,17 @@ struct femtoUniverseDebugTrack { //|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 + // 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) < generalPIDcuts.ConfNsigmaTPCProton) { + if (std::abs(nsigmaTPCPr) < generalPIDcuts.confNsigmaTPCProton) { return true; } else { return false; } } else if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < generalPIDcuts.ConfNsigmaCombinedProton) { + if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < generalPIDcuts.confNsigmaCombinedProton) { return true; } else { return false; @@ -125,29 +128,29 @@ struct femtoUniverseDebugTrack { //|nsigma_combined| < 3 for p > 0.5 // using configurables: - // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) - // ConfNsigmaTPCKaon -> TPC Kaon Sigma for momentum < 0.5 - // ConfNsigmaCombinedKaon -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 + // confNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) + // confNsigmaTPCKaon -> TPC Kaon Sigma for momentum < 0.5 + // confNsigmaCombinedKaon -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 if (mom < 0.3) { // 0.0-0.3 - if (TMath::Abs(nsigmaTPCK) < 3.0) { + if (std::abs(nsigmaTPCK) < 3.0) { return true; } else { return false; } } else if (mom < 0.45) { // 0.30 - 0.45 - if (TMath::Abs(nsigmaTPCK) < 2.0) { + if (std::abs(nsigmaTPCK) < 2.0) { return true; } else { return false; } } else if (mom < 0.55) { // 0.45-0.55 - if (TMath::Abs(nsigmaTPCK) < 1.0) { + if (std::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)) { + if ((std::abs(nsigmaTOFK) < 3.0) && (std::abs(nsigmaTPCK) < 3.0)) { { return true; } @@ -155,7 +158,7 @@ struct femtoUniverseDebugTrack { return false; } } else if (mom > 1.5) { // 1.5 - - if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + if ((std::abs(nsigmaTOFK) < 2.0) && (std::abs(nsigmaTPCK) < 3.0)) { return true; } else { return false; @@ -171,17 +174,17 @@ struct femtoUniverseDebugTrack { //|nsigma_combined| < 3 for p > 0.5 // using configurables: - // ConfNsigmaTPCPion -> TPC Kaon Sigma for momentum < 0.5 - // ConfNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + // confNsigmaTPCPion -> TPC Kaon Sigma for momentum < 0.5 + // confNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 if (true) { if (mom < 0.5) { - if (TMath::Abs(nsigmaTPCPi) < generalPIDcuts.ConfNsigmaTPCPion) { + if (std::abs(nsigmaTPCPi) < generalPIDcuts.confNsigmaTPCPion) { return true; } else { return false; } } else if (mom > 0.5) { - if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < generalPIDcuts.ConfNsigmaCombinedPion) { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < generalPIDcuts.confNsigmaCombinedPion) { return true; } else { return false; @@ -193,7 +196,7 @@ struct femtoUniverseDebugTrack { bool IsParticleNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) { - switch (trackonefilter.ConfPDGCodePartOne) { + switch (trackonefilter.confPDGCodePartOne) { case 2212: // Proton case -2212: // anty Proton return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); @@ -216,9 +219,9 @@ struct femtoUniverseDebugTrack { void init(InitContext&) { eventHisto.init(&qaRegistry); - trackHisto.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, trackonefilter.ConfIsMC, trackonefilter.ConfPDGCodePartOne.value, true); - vPIDPartOne = ConfPIDPartOne.value; - kNsigma = ConfTrkPIDnSigmaMax.value; + trackHisto.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, trackonefilter.confIsMC, trackonefilter.confPDGCodePartOne.value, true); + vPIDPartOne = confPIDPartOne.value; + kNsigma = confTrkPIDnSigmaMax.value; } /// Porduce QA plots for sigle track selection in FemtoUniverse framework @@ -227,13 +230,13 @@ struct femtoUniverseDebugTrack { { eventHisto.fillQA(col); for (auto& part : groupPartsOne) { - // if (part.p() > ConfCutTable->get("MaxP") || part.pt() > ConfCutTable->get("MaxPt")) { + // if (part.p() > confCutTable->get("MaxP") || part.pt() > confCutTable->get("MaxPt")) { // continue; // } - // if (!isFullPIDSelected(part.pidCut(), part.p(), ConfCutTable->get("PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfCutTable->get("nSigmaTPC"), ConfCutTable->get("nSigmaTPCTOF"))) { + // if (!isFullPIDSelected(part.pidCut(), part.p(), confCutTable->get("PIDthr"), vPIDPartOne, confNspecies, kNsigma, confCutTable->get("nSigmaTPC"), confCutTable->get("nSigmaTPCTOF"))) { // continue; // } - if (trackonefilter.ConfIsTrackIdentified) { + if (trackonefilter.confIsTrackIdentified) { if (!IsParticleNSigma(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; } @@ -250,7 +253,7 @@ struct femtoUniverseDebugTrack { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); FillDebugHistos(col, groupPartsOne); } - PROCESS_SWITCH(femtoUniverseDebugTrack, processData, "Enable Debug processing for Monte Carlo", true); + PROCESS_SWITCH(FemtoUniverseDebugTrack, processData, "Enable Debug processing for Monte Carlo", true); /// process function when runnning over Monte Carlo with MC truth enabled @@ -262,13 +265,13 @@ struct femtoUniverseDebugTrack { auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); FillDebugHistos(col, groupPartsOne); } - PROCESS_SWITCH(femtoUniverseDebugTrack, processMC, "Enable Debug processing for Monte Carlo", false); + PROCESS_SWITCH(FemtoUniverseDebugTrack, processMC, "Enable Debug processing for Monte Carlo", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; return workflow; } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx index f2b17d05e88..865e4db500d 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx @@ -13,6 +13,7 @@ /// \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 +/// \author Katarzyna Gwiździel, WUT Warsaw, katarzyna.gwizdziel@cern.ch #include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" @@ -40,6 +41,10 @@ struct FemtoUniverseEfficiencyBase { Configurable confIsMCGen{"confIsMCGen", false, "Enable QA histograms for MC Gen"}; Configurable confIsMCReco{"confIsMCReco", false, "Enable QA histograms for MC Reco"}; + Configurable confDoPartNsigmaRejection{"confDoPartNsigmaRejection", false, "Enable particle nSigma rejection"}; + Configurable forceTof{"forceTof", false, "Enable to reject tracks without TOF for PID, set to false for processes with V0"}; + Configurable checkIfTofAvailable{"checkIfTofAvailable", false, "Enable to check if TOF is available for PID, set to false for processes with V0"}; + // Collisions Configurable confZVertex{"confZVertex", 10.f, "Event sel: Maximum z-Vertex (cm)"}; @@ -60,10 +65,23 @@ struct FemtoUniverseEfficiencyBase { 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 confNsigmaPrRejectPiNsigma{"confNsigmaPrRejectPiNsigma", 2.0, "Reject if a proton could be a pion within a givien nSigma value"}; + Configurable confNsigmaPrRejectKaNsigma{"confNsigmaPrRejectKaNsigma", 2.0, "Reject if a proton could be a kaon within a givien nSigma value"}; 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"}; + Configurable confNsigmaPiRejectKaNsigma{"confNsigmaPiRejectKaNsigma", 2.0, "Reject if a pion could be a kaon within a givien nSigma value"}; + Configurable confNsigmaPiRejectPrNsigma{"confNsigmaPiRejectPrNsigma", 2.0, "Reject if a pion could be a proton within a givien nSigma value"}; + Configurable confPDGCheckMCReco{"confPDGCheckMCReco", true, "Check PDG code of MC reco paricles"}; } ConfBothTracks; + struct : o2::framework::ConfigurableGroup { + Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Proton, o2::track::PID::Pion, o2::track::PID::Kaon}, "Trk sel: Particles species for PID, proton, pion, kaon"}; + Configurable> trkPidTPCMax{"trkPidTPCMax", std::vector{2., 3., 2.}, "maximum nSigma TPC"}; + Configurable> trkPidTOFMax{"trkPidTOFMax", std::vector{2., 3., 2.}, "maximum nSigma TOF"}; + Configurable trkPidTofPtThreshold{"trkPidTofPtThreshold", 0.6, "minimum pT after which TOF PID is applicable"}; + Configurable trkUsePassPIDSelection{"trkUsePassPIDSelection", false, "Set to true to use passPIDSelection function, if false then use isParticleNSigma"}; + } ConfTracksPid; + /// Lambda cuts Configurable confV0InvMassLowLimit{"confV0InvMassLowLimit", 1.10, "Lower limit of the V0 invariant mass"}; Configurable confV0InvMassUpLimit{"confV0InvMassUpLimit", 1.13, "Upper limit of the V0 invariant mass"}; @@ -75,10 +93,10 @@ struct FemtoUniverseEfficiencyBase { // Momentum thresholds for Run2 and Run3 Configurable confMomKaonRun2{"confMomKaonRun2", 0.4, "Momentum threshold for kaon identification using ToF (Run2)"}; Configurable confMomKaonRun3{"confMomKaonRun3", 0.3, "Momentum threshold for kaon identification using ToF (Run3)"}; - Configurable confMomKaon045{"confMomKaon045", 0.45, "Momentum threshold for kaon identification pT = 0.45 GeV/c"}; - Configurable confMomKaon055{"confMomKaon055", 0.55, "Momentum threshold for kaon identification pT = 0.55 GeV/c"}; - Configurable confMomKaon08{"confMomKaon08", 0.8, "Momentum threshold for kaon identification pT = 0.8 GeV/c"}; - Configurable confMomKaon15{"confMomKaon15", 1.5, "Momentum threshold for kaon identification pT = 1.5 GeV/c"}; + Configurable confMomKaon045{"confMomKaon045", 0.45, "Momentum threshold for kaon identification p = 0.45 GeV/c"}; + Configurable confMomKaon055{"confMomKaon055", 0.55, "Momentum threshold for kaon identification p = 0.55 GeV/c"}; + Configurable confMomKaon08{"confMomKaon08", 0.8, "Momentum threshold for kaon identification p = 0.8 GeV/c"}; + Configurable confMomKaon15{"confMomKaon15", 1.5, "Momentum threshold for kaon identification p = 1.5 GeV/c"}; // n sigma cuts for Run 2 Configurable confKaonNsigmaTPCbelow04Run2{"confKaonNsigmaTPCbelow04Run2", 2.0, "Reject kaons with pT below 0.4 if TPC n sigma is above this value."}; Configurable confKaonNsigmaTPCfrom04to045Run2{"confKaonNsigmaTPCfrom04to045Run2", 1.0, "Reject kaons within pT from 0.4 to 0.45 if TPC n sigma is above this value."}; @@ -98,6 +116,8 @@ struct FemtoUniverseEfficiencyBase { Configurable confMomKaonLF{"confMomKaonLF", 0.5, "Momentum threshold for kaon identification using TOF (LF selection)"}; Configurable confNSigmaTPCKaonLF{"confNSigmaTPCKaonLF", 3.0, "TPC Kaon Sigma as in LF"}; Configurable confNSigmaCombKaonLF{"confNSigmaCombKaonLF", 3.0, "TPC and TOF Kaon Sigma (combined) as in LF"}; + Configurable confNsigmaKaRejectPiNsigma{"confNsigmaKaRejectPiNsigma", 3.0, "Reject if a kaon could be a pion within a given nSigma value"}; + Configurable confNsigmaKaRejectPrNsigma{"confNsigmaKaRejectPrNsigma", 3.0, "Reject if a kaon could be a proton within a given nSigma value"}; } ConfKaonSelection; /// Deuteron configurables @@ -111,7 +131,7 @@ struct FemtoUniverseEfficiencyBase { /// 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 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"}; @@ -132,7 +152,7 @@ struct FemtoUniverseEfficiencyBase { /// 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 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"}; @@ -165,10 +185,12 @@ struct FemtoUniverseEfficiencyBase { { eventHisto.init(&qaRegistry); - registryCuts.add("part1/cutsVspT", ";#it{p}_{T} (GeV/c) ;Cut no.", {HistType::kTH2F, {{500, 0, 5}, {5, 0, 6}}}); + registryCuts.add("part1/cutsVspT", ";#it{p}_{T} (GeV/c) ;Cut no.", {HistType::kTH2F, {{500, 0, 5}, {7, 0, 7}}}); trackHistoPartOneGen.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarPDGBins, confIsMCGen, confPDGCodePartOne, false); trackHistoPartOneRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, confIsMCReco, confPDGCodePartOne, confIsDebug); registryMCOrigin.add("part1/hPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); + registryMCOrigin.add("part1/hTofMatchingPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); + registryMCOrigin.add("part1/hTpcPt", " ;#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}}}); registryPDG.add("part1/PDGvspTall", "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)) { @@ -182,10 +204,12 @@ struct FemtoUniverseEfficiencyBase { registryPDG.add("part2/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); registryPDG.add("part2/PDGvspTall", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); if (!confIsSame) { - registryCuts.add("part2/cutsVspT", ";#it{p}_{T} (GeV/c) ;Cut no.", {HistType::kTH2F, {{500, 0, 5}, {5, 0, 6}}}); + registryCuts.add("part2/cutsVspT", ";#it{p}_{T} (GeV/c) ;Cut no.", {HistType::kTH2F, {{500, 0, 5}, {7, 0, 7}}}); trackHistoPartTwoGen.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarPDGBins, confIsMCGen, confPDGCodePartTwo, false); trackHistoPartTwoRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, confIsMCReco, confPDGCodePartTwo, confIsDebug); registryMCOrigin.add("part2/hPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); + registryMCOrigin.add("part2/hTofMatchingPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); + registryMCOrigin.add("part2/hTpcPt", " ;#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"); @@ -196,22 +220,58 @@ struct FemtoUniverseEfficiencyBase { } } - bool isProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + bool isProtonNSigma(bool partHasTof, 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 (forceTof && !partHasTof) { + return false; + } + + if (mom <= ConfBothTracks.confMomProton) { if (std::abs(nsigmaTPCPr) < ConfBothTracks.confNsigmaTPCProton) { return true; } else { return false; } - } else { - if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.confNsigmaCombinedProton) { + } + if (mom > ConfBothTracks.confMomProton) { + if (checkIfTofAvailable && !partHasTof) { + return std::abs(nsigmaTPCPr) < ConfBothTracks.confNsigmaTPCProton; + } else if (checkIfTofAvailable && partHasTof) { + return std::sqrt(std::pow(nsigmaTPCPr, 2) + std::pow(nsigmaTOFPr, 2)) < ConfBothTracks.confNsigmaCombinedProton; + } else { + return std::sqrt(std::pow(nsigmaTPCPr, 2) + std::pow(nsigmaTOFPr, 2)) < ConfBothTracks.confNsigmaCombinedProton; + } + } + return false; + } + + bool isProtonNSigmaRejected(bool partHasTof, float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCKa, float nsigmaTOFKa) + { + if (forceTof && !partHasTof) { + return true; + } + + // if (mom <= ConfBothTracks.confMomProton || !partHasTof) { + if (mom <= ConfBothTracks.confMomProton || !partHasTof) { + if (std::abs(nsigmaTPCPi) < ConfBothTracks.confNsigmaPrRejectPiNsigma) { + return true; + } else if (std::abs(nsigmaTPCKa) < ConfBothTracks.confNsigmaPrRejectKaNsigma) { return true; } else { return false; } } - return false; + if (mom > ConfBothTracks.confMomProton && partHasTof) { + if (std::sqrt(std::pow(nsigmaTPCPi, 2) + std::pow(nsigmaTOFPi, 2)) < ConfBothTracks.confNsigmaPrRejectPiNsigma) { + return true; + } else if (std::sqrt(std::pow(nsigmaTPCKa, 2) + std::pow(nsigmaTOFKa, 2)) < ConfBothTracks.confNsigmaPrRejectKaNsigma) { + return true; + } else { + return false; + } + } else { + return false; + } } bool isKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) @@ -267,16 +327,48 @@ struct FemtoUniverseEfficiencyBase { } } - bool isKaonNSigmaLF(float mom, float nsigmaTPCK, float nsigmaTOFK) + bool isKaonNSigmaLF(bool partHasTof, float mom, float nsigmaTPCK, float nsigmaTOFK) { - if (mom < ConfKaonSelection.confMomKaonLF) { + if (forceTof && !partHasTof) { + return false; + } + + if (mom <= ConfKaonSelection.confMomKaonLF) { if (std::abs(nsigmaTPCK) < ConfKaonSelection.confNSigmaTPCKaonLF) { return true; } else { return false; } - } else if (mom >= ConfKaonSelection.confMomKaonLF) { - if (std::sqrt(nsigmaTPCK * nsigmaTPCK + nsigmaTOFK * nsigmaTOFK) < ConfKaonSelection.confNSigmaCombKaonLF) { + } else if (mom > ConfKaonSelection.confMomKaonLF) { + if (checkIfTofAvailable && !partHasTof) { + return std::abs(nsigmaTPCK) < ConfKaonSelection.confNSigmaTPCKaonLF; + } else if (checkIfTofAvailable && partHasTof) { + return std::sqrt(std::pow(nsigmaTPCK, 2) + std::pow(nsigmaTOFK, 2)) < ConfKaonSelection.confNSigmaCombKaonLF; + } else { + return std::sqrt(std::pow(nsigmaTPCK, 2) + std::pow(nsigmaTOFK, 2)) < ConfKaonSelection.confNSigmaCombKaonLF; + } + } else { + return false; + } + } + + bool isKaonNSigmaLFRejected(bool partHasTof, float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCPr, float nsigmaTOFPr) + { + if (forceTof && !partHasTof) { + return true; + } + + if (mom <= ConfKaonSelection.confMomKaonLF || !partHasTof) { + if (std::abs(nsigmaTPCPi) < ConfKaonSelection.confNsigmaKaRejectPiNsigma) { + return true; + } else if (std::abs(nsigmaTPCPr) < ConfKaonSelection.confNsigmaKaRejectPrNsigma) { + return true; + } + } + if (mom > ConfKaonSelection.confMomKaonLF && partHasTof) { + if (std::sqrt(std::pow(nsigmaTPCPi, 2) + std::pow(nsigmaTOFPi, 2)) < ConfKaonSelection.confNsigmaKaRejectPiNsigma) { + return true; + } else if (std::sqrt(std::pow(nsigmaTPCPr, 2) + std::pow(nsigmaTOFPr, 2)) < ConfKaonSelection.confNsigmaKaRejectPrNsigma) { return true; } else { return false; @@ -286,22 +378,55 @@ struct FemtoUniverseEfficiencyBase { } } - bool isPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + bool isPionNSigma(bool partHasTof, float mom, float nsigmaTPCPi, float nsigmaTOFPi) { - if (mom < ConfBothTracks.confMomPion) { + if (forceTof && !partHasTof) { + return false; + } + + if (mom <= ConfBothTracks.confMomPion) { if (std::abs(nsigmaTPCPi) < ConfBothTracks.confNsigmaTPCPion) { return true; } else { return false; } + } else if (mom > ConfBothTracks.confMomPion) { + if (checkIfTofAvailable && !partHasTof) { + return std::abs(nsigmaTPCPi) < ConfBothTracks.confNsigmaTPCPion; + } else if (checkIfTofAvailable && partHasTof) { + return std::sqrt(std::pow(nsigmaTPCPi, 2) + std::pow(nsigmaTOFPi, 2)) < ConfBothTracks.confNsigmaCombinedPion; + } else { + return std::sqrt(std::pow(nsigmaTPCPi, 2) + std::pow(nsigmaTOFPi, 2)) < ConfBothTracks.confNsigmaCombinedPion; + } } else { - if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.confNsigmaCombinedPion) { + return false; + } + } + + bool isPionNSigmaRejected(bool partHasTof, float mom, float nsigmaTPCKa, float nsigmaTOFKa, float nsigmaTPCPr, float nsigmaTOFPr) + { + if (forceTof && !partHasTof) { + return true; + } + + if (mom <= ConfBothTracks.confMomPion || !partHasTof) { + if (std::abs(nsigmaTPCKa) < ConfBothTracks.confNsigmaPiRejectKaNsigma) { + return true; + } else if (std::abs(nsigmaTPCPr) < ConfBothTracks.confNsigmaPiRejectPrNsigma) { + return true; + } + } + if (mom > ConfBothTracks.confMomPion && partHasTof) { + if (std::sqrt(std::pow(nsigmaTPCKa, 2) + std::pow(nsigmaTOFKa, 2)) < ConfBothTracks.confNsigmaPiRejectKaNsigma) { + return true; + } else if (std::sqrt(std::pow(nsigmaTPCPr, 2) + std::pow(nsigmaTOFPr, 2)) < ConfBothTracks.confNsigmaPiRejectPrNsigma) { return true; } else { return false; } + } else { + return false; } - return false; } bool isDeuteronNSigma(float mom, float nsigmaTPCDe, float nsigmaTOFDe) @@ -317,21 +442,21 @@ struct FemtoUniverseEfficiencyBase { } } - bool isParticleNSigma(int pdgCode, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCDe, float nsigmaTOFDe) + bool isParticleNSigma(int pdgCode, bool partHasTof, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK, float nsigmaTPCDe, float nsigmaTOFDe) { switch (pdgCode) { case 2212: // Proton case -2212: // anty Proton - return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + return isProtonNSigma(partHasTof, mom, nsigmaTPCPr, nsigmaTOFPr); break; case 211: // Pion case -211: // Pion- - return isPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + return isPionNSigma(partHasTof, mom, nsigmaTPCPi, nsigmaTOFPi); break; case 321: // Kaon+ case -321: // Kaon- if (isKaonLF) { - return isKaonNSigmaLF(mom, nsigmaTPCK, nsigmaTOFK); + return isKaonNSigmaLF(partHasTof, mom, nsigmaTPCK, nsigmaTOFK); } else { return isKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); } @@ -345,6 +470,74 @@ struct FemtoUniverseEfficiencyBase { } } + bool isParticleNSigmaRejected(int pdgCode, bool partHasTof, float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCKa, float nsigmaTOFKa, float nsigmaTPCPr, float nsigmaTOFPr) + { + switch (pdgCode) { + case 2212: // Proton + case -2212: // anty Proton + return isProtonNSigmaRejected(partHasTof, mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCKa, nsigmaTOFKa); + break; + case 211: // Pion + case -211: // Pion- + return isPionNSigmaRejected(partHasTof, mom, nsigmaTPCKa, nsigmaTOFKa, nsigmaTPCPr, nsigmaTOFPr); + break; + case 321: // Kaon+ + case -321: // Kaon- + if (isKaonLF) { + return isKaonNSigmaLFRejected(partHasTof, mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCPr, nsigmaTOFPr); + } else { + return false; // in case of non LF kaon selecion + } + break; + default: + return false; + } + } + + template + bool passPIDSelection(Atrack const& track, SpeciesContainer const mPIDspecies, + T1 const maxTPC, T2 const maxTOF, double ptThreshold = 0.75, bool tofForced = false, bool partHasTof = false) + { + // Ensure size consistency + if (mPIDspecies.value.size() != maxTPC.value.size() || mPIDspecies.value.size() != maxTOF.value.size()) { + LOGF(error, "Size of particle species and corresponding nSigma selection arrays should be the same"); + return false; // Early exit on error + } + + for (size_t speciesIndex = 0; speciesIndex < mPIDspecies.value.size(); ++speciesIndex) { + auto const& pid = mPIDspecies->at(speciesIndex); + auto nSigmaTPC = o2::aod::pidutils::tpcNSigma(pid, track); + + if (tofForced && !partHasTof) { + return false; + } + + if (speciesIndex == 0) { // First species logic + if (std::abs(nSigmaTPC) > maxTPC->at(speciesIndex)) { + return false; // TPC check failed + } + if (tofForced || (track.pt() > ptThreshold && partHasTof)) { + auto nSigmaTOF = o2::aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) > maxTOF->at(speciesIndex)) { + return false; // TOF check failed + } + } + } else { // Other species logic + if (std::abs(nSigmaTPC) < maxTPC->at(speciesIndex)) { // Check TPC nSigma first + if (partHasTof) { + auto nSigmaTOF = o2::aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) < maxTOF->at(speciesIndex)) { + return false; // Reject if both TPC and TOF are within thresholds + } + } else { + return false; // Reject if only TPC is within threshold and TOF is unavailable + } + } + } + } + return true; // Passed all checks + } + bool invMLambda(float invMassLambda, float invMassAntiLambda) { if ((invMassLambda < confV0InvMassLowLimit || invMassLambda > confV0InvMassUpLimit) && (invMassAntiLambda < confV0InvMassLowLimit || invMassAntiLambda > confV0InvMassUpLimit)) { @@ -398,17 +591,37 @@ struct FemtoUniverseEfficiencyBase { for (const auto& part : grouppartsOneMCRec) { // only partition + registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 0); + + if (part.partType() != confParticleTypePartOne) { + continue; + } registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 1); - 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), trackCuts.getNsigmaTPC(part, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(part, o2::track::PID::Deuteron))) { + if (part.sign() != confChargePart1) { continue; } registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 2); + if (!ConfTracksPid.trkUsePassPIDSelection) { + if (!isParticleNSigma(confPDGCodePartOne, static_cast(part.mLambda()), 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))) { + continue; + } + if (confDoPartNsigmaRejection && isParticleNSigmaRejected(confPDGCodePartOne, static_cast(part.mLambda()), part.p(), 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::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton))) { + continue; + } + } else { + if (!passPIDSelection(part, ConfTracksPid.trkPIDspecies, ConfTracksPid.trkPidTPCMax, ConfTracksPid.trkPidTOFMax, ConfTracksPid.trkPidTofPtThreshold, forceTof, static_cast(part.mLambda()))) { + continue; + } + } + + registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 3); + if (!part.has_fdMCParticle()) { continue; } - registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 3); + registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 4); const auto mcParticle = part.fdMCParticle(); @@ -418,29 +631,56 @@ struct FemtoUniverseEfficiencyBase { if (!(mcParticle.partOriginMCTruth() == aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrimary)) { continue; } - registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 4); + registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 5); - if (!(std::abs(mcParticle.pdgMCTruth()) == std::abs(confPDGCodePartOne))) { + if (ConfBothTracks.confPDGCheckMCReco && !(std::abs(mcParticle.pdgMCTruth()) == std::abs(confPDGCodePartOne))) { continue; } - registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 5); + registryCuts.fill(HIST("part1/cutsVspT"), part.pt(), 6); registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); registryMCOrigin.fill(HIST("part1/hPt"), mcParticle.pt()); + // TOF Matching efficiency + if (part.mLambda() == 1) { + registryMCOrigin.fill(HIST("part1/hTofMatchingPt"), mcParticle.pt()); + } else { + registryMCOrigin.fill(HIST("part1/hTpcPt"), mcParticle.pt()); + } } if (!confIsSame) { for (const auto& part : grouppartsTwoMCRec) { + registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 0); + + if (part.partType() != confParticleTypePartTwo) { + continue; + } registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 1); - 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), trackCuts.getNsigmaTPC(part, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(part, o2::track::PID::Deuteron))) { + + if (part.sign() != confChargePart2) { continue; } registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 2); + if (!ConfTracksPid.trkUsePassPIDSelection) { + if (!isParticleNSigma(confPDGCodePartTwo, static_cast(part.mLambda()), 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))) { + continue; + } + if (confDoPartNsigmaRejection && isParticleNSigmaRejected(confPDGCodePartTwo, static_cast(part.mLambda()), part.p(), 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::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton))) { + continue; + } + } else { + if (!passPIDSelection(part, ConfTracksPid.trkPIDspecies, ConfTracksPid.trkPidTPCMax, ConfTracksPid.trkPidTOFMax, ConfTracksPid.trkPidTofPtThreshold, forceTof, static_cast(part.mLambda()))) { + continue; + } + } + + registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 3); + if (!part.has_fdMCParticle()) { continue; } - registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 3); + registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 4); const auto mcParticle = part.fdMCParticle(); registryPDG.fill(HIST("part2/PDGvspTall"), part.pt(), mcParticle.pdgMCTruth()); @@ -449,15 +689,21 @@ struct FemtoUniverseEfficiencyBase { if (!(mcParticle.partOriginMCTruth() == aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrimary)) { continue; } - registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 4); + registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 5); - if (!(std::abs(mcParticle.pdgMCTruth()) == std::abs(confPDGCodePartTwo))) { + if (ConfBothTracks.confPDGCheckMCReco && !(std::abs(mcParticle.pdgMCTruth()) == std::abs(confPDGCodePartTwo))) { continue; } - registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 5); + registryCuts.fill(HIST("part2/cutsVspT"), part.pt(), 6); registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); registryMCOrigin.fill(HIST("part2/hPt"), mcParticle.pt()); + // TOF Matching efficiency + if (part.mLambda() == 1) { + registryMCOrigin.fill(HIST("part2/hTofMatchingPt"), mcParticle.pt()); + } else { + registryMCOrigin.fill(HIST("part2/hTpcPt"), mcParticle.pt()); + } } } } @@ -473,7 +719,7 @@ struct FemtoUniverseEfficiencyBase { { // part1 is track and part2 is Phi for (const 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), trackCuts.getNsigmaTPC(part, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(part, o2::track::PID::Deuteron))) { + if (part.partType() != confParticleTypePartOne || part.sign() != confChargePart1 || !isParticleNSigma(confPDGCodePartOne, static_cast(part.mLambda()), 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))) { continue; } trackHistoPartOneRec.fillQA(part); @@ -527,10 +773,10 @@ struct FemtoUniverseEfficiencyBase { 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 + if (confPDGCodePartOne > 0 && (!isProtonNSigma(static_cast(posChild.mLambda()), 0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Proton)) || !isPionNSigma(static_cast(posChild.mLambda()), 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 + if (confPDGCodePartOne < 0 && (!isProtonNSigma(static_cast(negChild.mLambda()), 0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Proton)) || !isPionNSigma(static_cast(negChild.mLambda()), 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; } @@ -561,10 +807,10 @@ struct FemtoUniverseEfficiencyBase { 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 + if (confPDGCodePartTwo > 0 && (!isProtonNSigma(static_cast(posChild.mLambda()), 0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Proton)) || !isPionNSigma(static_cast(posChild.mLambda()), 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 + if (confPDGCodePartTwo < 0 && (!isProtonNSigma(static_cast(negChild.mLambda()), 0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Proton)) || !isPionNSigma(static_cast(negChild.mLambda()), 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; } @@ -601,7 +847,7 @@ struct FemtoUniverseEfficiencyBase { /// Histogramming same event for (const 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), trackCuts.getNsigmaTPC(part, o2::track::PID::Deuteron), trackCuts.getNsigmaTOF(part, o2::track::PID::Deuteron))) { + if (part.partType() != confParticleTypePartOne || part.sign() != confChargePart1 || !isParticleNSigma(confPDGCodePartOne, static_cast(part.mLambda()), 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))) { continue; } @@ -623,10 +869,10 @@ struct FemtoUniverseEfficiencyBase { 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 + if (confPDGCodePartTwo > 0 && (!isProtonNSigma(static_cast(posChild.mLambda()), 0, trackCuts.getNsigmaTPC(posChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(posChild, o2::track::PID::Proton)) || !isPionNSigma(static_cast(posChild.mLambda()), 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 + if (confPDGCodePartTwo < 0 && (!isProtonNSigma(static_cast(negChild.mLambda()), 0, trackCuts.getNsigmaTPC(negChild, o2::track::PID::Proton), trackCuts.getNsigmaTOF(negChild, o2::track::PID::Proton)) || !isPionNSigma(static_cast(negChild.mLambda()), 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; } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx index 6f7a7d5db2b..04c9865a73c 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx @@ -15,10 +15,14 @@ /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch #include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + #include "Common/Core/EventMixing.h" + +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Framework/ASoAHelpers.h" + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index ffb5c8f56ea..715a3c1380a 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -22,6 +22,7 @@ #include "PWGCF/FemtoUniverse/Core/femtoUtils.h" #include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "CCDB/BasicCCDBManager.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" @@ -57,10 +58,6 @@ struct femtoUniversePairTaskTrackCascadeExtended { Configurable confCascInvMassLowLimit{"confCascInvMassLowLimit", 1.315, "Lower limit of the Casc invariant mass"}; Configurable confCascInvMassUpLimit{"confCascInvMassUpLimit", 1.325, "Upper limit of the Casc invariant mass"}; - // TODO: Add seperate selection for daughter particles - // Configurable confNSigmaTPCPion{"confNSigmaTPCPion", 4, "NSigmaTPCPion"}; - // Configurable confNSigmaTPCProton{"confNSigmaTPCProton", 4, "NSigmaTPCProton"}; - /// applying narrow cut Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; Configurable confEta{"confEta", 0.8, "Eta cut for the global track"}; @@ -109,6 +106,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { // Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + Configurable confCCDBEfficiency{"confCCDBEfficiency", "", "CCDB path to efficiency object"}; Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut); using FilteredFDCollisions = soa::Filtered; @@ -159,8 +157,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { std::set cascDuplicates; std::unique_ptr plocalEffFile; - std::unique_ptr plocalEffp1; - std::unique_ptr plocalEffp2; + std::unique_ptr pEffHistp1; + std::unique_ptr pEffHistp2; + + Service ccdb; // Table to select cascade daughters // Charges: = +--, +--, +-+, +-+ @@ -194,12 +194,26 @@ struct femtoUniversePairTaskTrackCascadeExtended { } } - bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle, bool hasTOF) { if (mom <= confmom) { return (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle); - } else { + } else if (hasTOF == 1) { return (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < confNsigmaCombinedParticle); + } else { + return false; + } + } + + template + bool isNSigmaCombinedBitmask(float mom, const T& part) + { + if (mom <= confmom) { + return ((part.pidCut() & (1u << confTrackChoicePartOne)) != 0); + } else if ((part.pidCut() & 512u) != 0) { + return ((part.pidCut() & (64u << confTrackChoicePartOne)) != 0); + } else { + return false; } } @@ -227,7 +241,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id]); + return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id], (part.pidCut() & 512u) != 0); } void init(InitContext const&) @@ -330,14 +344,30 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!plocalEffFile || plocalEffFile.get()->IsZombie()) LOGF(fatal, "Could not load efficiency histogram from %s", confLocalEfficiency.value.c_str()); if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { - 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 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); + pEffHistp1 = (confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); LOGF(info, "Loaded efficiency histograms for track-Cascade."); } else if (doprocessSameEventCasc || doprocessSameEventCascBitmask || doprocessMixedEventCasc || doprocessMixedEventCascBitmask) { - plocalEffp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); - plocalEffp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); + pEffHistp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); + pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(plocalEffFile.get()->Get("Cascade")) : std::unique_ptr(plocalEffFile.get()->Get("AntiCascade")); LOGF(info, "Loaded efficiency histograms for Cascade-Cascade."); } + } else if (!confCCDBEfficiency.value.empty()) { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { + pEffHistp1 = (confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrPlus", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/PrMinus", now)); // note: works only for protons for now + pEffHistp2 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); + LOGF(info, "Loaded efficiency histograms for track-Cascade from CCDB"); + } else if (doprocessSameEventCasc || doprocessSameEventCascBitmask || doprocessMixedEventCasc || doprocessMixedEventCascBitmask) { + pEffHistp1 = (confCascType1 == 0 || confCascType1 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); + pEffHistp2 = (confCascType2 == 0 || confCascType2 == 1) ? std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/Cascade", now)) : std::unique_ptr(ccdb->getForTimeStamp(confCCDBEfficiency.value + "/AntiCascade", now)); + LOGF(info, "Loaded efficiency histograms for Cascade-Cascade from CCDB."); + } } } @@ -442,13 +472,13 @@ struct femtoUniversePairTaskTrackCascadeExtended { rXiQA.fill(HIST("hInvMpTmult"), part.pt(), part.mLambda(), multCol); } - if constexpr (std::experimental::is_detected::value) { - for (const auto& part : groupPartsOne) { + for (const auto& part : groupPartsOne) { + if constexpr (std::experimental::is_detected::value) { /// PID plot for track particle const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne])) + if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) continue; if (part.mAntiLambda() > 0) { @@ -460,8 +490,18 @@ struct femtoUniversePairTaskTrackCascadeExtended { qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); trackHistoPartOneNeg.fillQA(part); } + } else { + if (!isNSigmaCombinedBitmask(part.p(), part)) { + continue; + } + if (part.mAntiLambda() > 0) { + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + trackHistoPartOneNeg.fillQA(part); + } } } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Cascade inv mass cut (mLambda stores Xi mass, mAntiLambda stores Omega mass) if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType1)) @@ -471,8 +511,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!isParticleCombined(p1, confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + if (!isNSigmaCombinedBitmask(p1.p(), p1)) { continue; + } } // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { @@ -505,8 +546,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { } } 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 (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); sameEventCont.setPair(p1, p2, multCol, confUse3D, weight); } } @@ -524,8 +565,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventBitmask, "Enable processing same event for track - cascade using bitmask for PID", false); /// cascade - cascade correlations + Preslice perFDPartsCasc = aod::femtouniversecascparticle::fdParticleId; + template - void doSameEventCasc(const FilteredFDCollision& col, const TableType& parts, PartitionType& partsTwo) + void doSameEventCasc(const FilteredFDCollision& col, const TableType& parts, PartitionType& partsTwo, const aod::FDCascParticles& cascs) { const auto& magFieldTesla = col.magField(); @@ -583,24 +626,28 @@ struct femtoUniversePairTaskTrackCascadeExtended { return; // track cleaning & checking for duplicate pairs if (!pairCleanerCasc.isCleanPair(p1, p2, parts)) { - // mark for rejection the cascades that share a daughter with other cascades - cascDuplicates.insert(p1.globalIndex()); - cascDuplicates.insert(p2.globalIndex()); + // mark for rejection the cascade that share a daughter with the other cascade and has a better cosPA value + auto groupedCasc1 = cascs.sliceBy(perFDPartsCasc, p1.globalIndex()); + auto groupedCasc2 = cascs.sliceBy(perFDPartsCasc, p2.globalIndex()); + if (groupedCasc1.size() <= 0 || groupedCasc2.size() <= 0) { + LOGF(warning, "Either cascade1 (%u) or cascade2 (%u) list is empty", groupedCasc1.size(), groupedCasc2.size()); // this should never happen but just for a sanity check + return; + } + if (std::abs(groupedCasc1.begin().cpaCasc() - 1) < std::abs(groupedCasc2.begin().cpaCasc() - 1)) { + cascDuplicates.insert(p1.globalIndex()); + } else { + cascDuplicates.insert(p2.globalIndex()); + } } }; - auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + auto pairProcessFunc = [&](auto& p1, auto& p2) -> bool { if (cascDuplicates.contains(p1.globalIndex()) || cascDuplicates.contains(p2.globalIndex())) - return; + return false; if (!invMCascade(p1.mLambda(), p1.mAntiLambda(), confCascType1)) - return; + return false; if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType2)) - return; - if (confIsCPR.value) { - if (pairCloseRejectionCasc.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { - return; - } - } + return false; const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 3 - parts.begin().globalIndex()); const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); @@ -608,18 +655,18 @@ struct femtoUniversePairTaskTrackCascadeExtended { /// Child particles must pass this condition to be selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild1, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType1][2])) - return; + return false; if (!isParticleTOF(posChild1, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType1][2])) - return; + return false; } else { if ((posChild1.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild1.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor1.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) - return; + return false; if (confUseStrangenessTOF) { if (((confCascType1 == 1 || confCascType1 == 3) && (p1.pidCut() & 7) != 7) || ((confCascType1 == 0 || confCascType1 == 2) && (p1.pidCut() & 56) != 56)) - return; + return false; } else { if ((posChild1.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild1.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0 || (bachelor1.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) - return; + return false; } } @@ -629,55 +676,54 @@ struct femtoUniversePairTaskTrackCascadeExtended { /// Child particles must pass this condition to be selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild2, CascChildTable[confCascType2][0]) || !isParticleTPC(negChild2, CascChildTable[confCascType2][1]) || !isParticleTPC(bachelor2, CascChildTable[confCascType2][2])) - return; + return false; if (!isParticleTOF(posChild2, CascChildTable[confCascType2][0]) || !isParticleTOF(negChild2, CascChildTable[confCascType2][1]) || !isParticleTOF(bachelor2, CascChildTable[confCascType2][2])) - return; + return false; } else { if ((posChild2.pidCut() & (1u << CascChildTable[confCascType2][0])) == 0 || (negChild2.pidCut() & (1u << CascChildTable[confCascType2][1])) == 0 || (bachelor2.pidCut() & (1u << CascChildTable[confCascType2][2])) == 0) - return; + return false; if (confUseStrangenessTOF) { if (((confCascType2 == 1 || confCascType2 == 3) && (p2.pidCut() & 7) != 7) || ((confCascType2 == 0 || confCascType2 == 2) && (p2.pidCut() & 56) != 56)) - return; + return false; } else { if ((posChild2.pidCut() & (8u << CascChildTable[confCascType2][0])) == 0 || (negChild2.pidCut() & (8u << CascChildTable[confCascType2][1])) == 0 || (bachelor2.pidCut() & (8u << CascChildTable[confCascType2][2])) == 0) - return; + return false; + } + } + + if (confIsCPR.value) { + if (pairCloseRejectionCasc.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + return false; } } 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 (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); sameEventCont.setPair(p1, p2, multCol, confUse3D, weight); + return true; }; + cascDuplicates.clear(); - if (confCascType1 == confCascType2) { - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairDuplicateCheckFunc(p1, p2); - } - /// Now build the combinations for identical cascades - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairProcessFunc(p1, p2); - } - } else { - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairDuplicateCheckFunc(p1, p2); - } - /// Now build the combinations for non-identical cascades - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairProcessFunc(p1, p2); - } + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairDuplicateCheckFunc(p1, p2); + } + /// Now build the combinations for cascades + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + if (!pairProcessFunc(p1, p2)) + pairProcessFunc(p2, p1); } } - void processSameEventCasc(const FilteredFDCollision& col, const FemtoFullParticles& parts) + void processSameEventCasc(const FilteredFDCollision& col, const FemtoFullParticles& parts, const aod::FDCascParticles& cascs) { - doSameEventCasc(col, parts, partsTwoFull); + doSameEventCasc(col, parts, partsTwoFull, cascs); } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCasc, "Enable processing same event for cascade - cascade", false); - void processSameEventCascBitmask(const FilteredFDCollision& col, const aod::FDParticles& parts) + void processSameEventCascBitmask(const FilteredFDCollision& col, const aod::FDParticles& parts, const aod::FDCascParticles& cascs) { - doSameEventCasc(col, parts, partsTwoBasic); + doSameEventCasc(col, parts, partsTwoBasic, cascs); } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCascBitmask, "Enable processing same event for cascade - cascade using bitmask for PID", false); @@ -709,8 +755,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!isParticleCombined(p1, confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + if (!isNSigmaCombinedBitmask(p1.p(), p1)) { continue; + } } const auto& posChild = parts.iteratorAt(p2.globalIndex() - 3 - parts.begin().globalIndex()); @@ -745,8 +792,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { } 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 (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); mixedEventCont.setPair(p1, p2, multCol, confUse3D, weight); } }; @@ -854,8 +901,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { } 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 (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); mixedEventCont.setPair(p1, p2, multCol, confUse3D, weight); } } @@ -1119,11 +1166,12 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (mcpart.pdgMCTruth() != kProton) continue; if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 64u) == 0) + if (!isNSigmaCombinedBitmask(part.p(), part)) { continue; + } } registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); @@ -1132,11 +1180,12 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (mcpart.pdgMCTruth() != kProtonBar) continue; if constexpr (std::experimental::is_detected::value) { - if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) continue; } else { - if ((part.pidCut() & 64u) == 0) + if (!isNSigmaCombinedBitmask(part.p(), part)) { continue; + } } registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx index 140a02d957d..8cde231fecb 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackD0.cxx @@ -10,11 +10,7 @@ // or submit itself to any jurisdiction. /// \file femtoUniversePairTaskTrackD0.cxx -/// \brief Tasks that reads the track tables and D0/D0bar mesons -/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de -/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de -/// \author Anton Riedel, TU München, anton.riedel@tum.de -/// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch +/// \brief Tasks that reads the track tables and D0/D0bar mesons and build track-D0 pairs /// \author Katarzyna Gwiździel, WUT Warsaw, katarzyna.gwizdziel@cern.ch #include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" @@ -93,13 +89,6 @@ struct FemtoUniversePairTaskTrackD0 { /// Table for both particles struct : o2::framework::ConfigurableGroup { - Configurable confNsigmaCombinedProton{"confNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined)"}; - Configurable confNsigmaTPCProton{"confNsigmaTPCProton", 3.0, "TPC Proton Sigma"}; - Configurable confNsigmaCombinedPion{"confNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined)"}; - Configurable confNsigmaTPCPion{"confNsigmaTPCPion", 3.0, "TPC Pion Sigma"}; - Configurable confNsigmaCombinedKaon{"confNsigmaCombinedKaon", 3.0, "TPC and TOF Kaon Sigma (combined)"}; - Configurable confNsigmaTPCKaon{"confNsigmaTPCKaon", 3.0, "TPC Kaon Sigma"}; - 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"}; @@ -117,9 +106,26 @@ struct FemtoUniversePairTaskTrackD0 { Configurable confTrackLowPtCut{"confTrackLowPtCut", 0.5, "Low pT cut of the track"}; Configurable confTrackHighPtCut{"confTrackHighPtCut", 2.5, "High pT cut of the track"}; Configurable confTrackEtaMax{"confTrackEtaMax", 0.8, "max. pseudorapidity of the track"}; - Configurable minPtPidTpcTofProton{"minPtPidTpcTofProton", 0.5, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; - Configurable minPtPidTpcTofPion{"minPtPidTpcTofPion", 0.5, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; - Configurable minPtPidTpcTofKaonLF{"minPtPidTpcTofKaonLF", 0.5, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; + // Particle identification + Configurable minMomPidTpcTofProton{"minMomPidTpcTofProton", 0.8, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; + Configurable minMomPidTpcTofPion{"minMomPidTpcTofPion", 0.7, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; + Configurable minMomPidTpcTofKaon{"minMomPidTpcTofKaon", 0.5, "Momentum threshold for change of the PID method (from using TPC to TPC and TOF)."}; + // Configurables with nSigma values for particle selection + Configurable confNsigmaCombinedProton{"confNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined)"}; + Configurable confNsigmaTPCProton{"confNsigmaTPCProton", 3.0, "TPC Proton Sigma"}; + Configurable confNsigmaCombinedPion{"confNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined)"}; + Configurable confNsigmaTPCPion{"confNsigmaTPCPion", 3.0, "TPC Pion Sigma"}; + Configurable confNsigmaCombinedKaon{"confNsigmaCombinedKaon", 3.0, "TPC and TOF Kaon Sigma (combined)"}; + Configurable confNsigmaTPCKaon{"confNsigmaTPCKaon", 3.0, "TPC Kaon Sigma"}; + // Configurable with nSigma values for particle rejection + Configurable confNsigmaPrRejectPiNsigma{"confNsigmaPrRejectPiNsigma", 2.0, "Reject if proton could be a pion within a givien nSigma value"}; + Configurable confNsigmaPrRejectKaNsigma{"confNsigmaPrRejectKaNsigma", 2.0, "Reject if proton could be a kaon within a givien nSigma value"}; + Configurable confNsigmaKaRejectPiNsigma{"confNsigmaKaRejectPiNsigma", 2.0, "Reject if kaon could be a pion within a givien nSigma value"}; + Configurable confNsigmaKaRejectPrNsigma{"confNsigmaKaRejectPrNsigma", 2.0, "Reject if kaon could be a proton within a givien nSigma value"}; + Configurable confNsigmaPiRejectKaNsigma{"confNsigmaPiRejectKaNsigma", 2.0, "Reject if pion could be a kaon within a givien nSigma value"}; + Configurable confNsigmaPiRejectPrNsigma{"confNsigmaPiRejectPrNsigma", 2.0, "Reject if pion could be a proton within a givien nSigma value"}; + // Configurable to enable particle rejection + Configurable confDoPartNsigmaRejection{"confDoPartNsigmaRejection", false, "Enable particle nSigma rejection"}; } ConfTrack; /// Particle 2 --- D0/D0bar meson @@ -153,6 +159,8 @@ struct FemtoUniversePairTaskTrackD0 { Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; Configurable confChooseD0trackCorr{"confChooseD0trackCorr", 0, "If 0 correlations with D0s, if 1 with D0bars"}; + // Correlated background for D0/D0bar candidates + Configurable fillCorrBkgs{"fillCorrBkgs", false, "Fill histograms with correlated background candidates"}; // Efficiency Configurable doEfficiencyCorr{"doEfficiencyCorr", false, "Apply efficiency corrections"}; @@ -272,24 +280,20 @@ struct FemtoUniversePairTaskTrackD0 { {"hEtaD0D0bar", ";#eta ;counts", {HistType::kTH1F, {{200, -1., 1.}}}}, {"hEtaD0", ";#eta ;counts", {HistType::kTH1F, {{200, -1., 1.}}}}, {"hEtaD0bar", ";#eta ;counts", {HistType::kTH1F, {{200, -1., 1.}}}}, - {"hDecayLengthD0", ";decay length (cm);counts", {HistType::kTH1F, {{800, 0., 4.}}}}, - {"hDecayLengthD0bar", ";decay length (cm);counts", {HistType::kTH1F, {{800, 0., 4.}}}}, {"hPtDaughters", ";#it{p}_{T} (GeV/#it{c});counts", {HistType::kTH1F, {{300, 0., 12.}}}}, - {"hSignDaughters", ";sign ;counts", {HistType::kTH1F, {{10, -2.5, 2.5}}}}, - {"hDCAxyDaughters", "; #it{DCA}_{xy} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}, - {"hDCAzDaughters", "; #it{DCA}_{z} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}}}; + {"hSignDaughters", ";sign ;counts", {HistType::kTH1F, {{10, -2.5, 2.5}}}}}}; // 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 { - if (mom < ConfTrack.minPtPidTpcTofProton) { - if (std::abs(nsigmaTPCPr) < ConfBothTracks.confNsigmaTPCProton) { + if (mom < ConfTrack.minMomPidTpcTofProton) { + if (std::abs(nsigmaTPCPr) < ConfTrack.confNsigmaTPCProton) { return true; } else { return false; } - } else if (mom > ConfTrack.minPtPidTpcTofProton) { - if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.confNsigmaCombinedProton) { + } else if (mom > ConfTrack.minMomPidTpcTofProton) { + if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfTrack.confNsigmaCombinedProton) { return true; } else { return false; @@ -298,16 +302,60 @@ struct FemtoUniversePairTaskTrackD0 { return false; } - bool isKaonNSigmaLF(float mom, float nsigmaTPCK, float nsigmaTOFK) + bool isProtonNSigmaRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCKa, float nsigmaTOFKa) { - if (mom < ConfTrack.minPtPidTpcTofKaonLF) { - if (std::abs(nsigmaTPCK) < ConfBothTracks.confNsigmaTPCKaon) { + if (mom < ConfTrack.minMomPidTpcTofProton) { + if (std::abs(nsigmaTPCPi) < ConfTrack.confNsigmaPrRejectPiNsigma) { + return true; + } else if (std::abs(nsigmaTPCKa) < ConfTrack.confNsigmaPrRejectKaNsigma) { + return true; + } + } + if (mom > ConfTrack.minMomPidTpcTofProton) { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfTrack.confNsigmaPrRejectPiNsigma) { + return true; + } else if (std::hypot(nsigmaTOFKa, nsigmaTPCKa) < ConfTrack.confNsigmaPrRejectKaNsigma) { return true; } else { return false; } - } else if (mom >= ConfTrack.minPtPidTpcTofKaonLF) { - if (std::sqrt(nsigmaTPCK * nsigmaTPCK + nsigmaTOFK * nsigmaTOFK) < ConfBothTracks.confNsigmaCombinedKaon) { + } else { + return false; + } + } + + bool isKaonNSigmaLF(float mom, float nsigmaTPCKa, float nsigmaTOFKa) + { + if (mom < ConfTrack.minMomPidTpcTofKaon) { + if (std::abs(nsigmaTPCKa) < ConfTrack.confNsigmaTPCKaon) { + return true; + } else { + return false; + } + } else if (mom > ConfTrack.minMomPidTpcTofKaon) { + if (std::hypot(nsigmaTOFKa, nsigmaTPCKa) < ConfTrack.confNsigmaCombinedKaon) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool isKaonNSigmaLFRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCPr, float nsigmaTOFPr) + { + if (mom < ConfTrack.minMomPidTpcTofKaon) { + if (std::abs(nsigmaTPCPi) < ConfTrack.confNsigmaKaRejectPiNsigma) { + return true; + } else if (std::abs(nsigmaTPCPr) < ConfTrack.confNsigmaKaRejectPrNsigma) { + return true; + } + } + if (mom > ConfTrack.minMomPidTpcTofKaon) { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfTrack.confNsigmaKaRejectPiNsigma) { + return true; + } else if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfTrack.confNsigmaKaRejectPrNsigma) { return true; } else { return false; @@ -319,35 +367,52 @@ struct FemtoUniversePairTaskTrackD0 { bool isPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) { - // using configurables: - // confNsigmaTPCPion -> TPC Pion Sigma for a given momentum - // confNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for a given momentum - if (true) { - if (mom < ConfTrack.minPtPidTpcTofPion) { - if (std::abs(nsigmaTPCPi) < ConfBothTracks.confNsigmaTPCPion) { - return true; - } else { - return false; - } - } else if (mom > ConfTrack.minPtPidTpcTofPion) { - if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.confNsigmaCombinedPion) { - return true; - } else { - return false; - } + if (mom < ConfTrack.minMomPidTpcTofPion) { + if (std::abs(nsigmaTPCPi) < ConfTrack.confNsigmaTPCPion) { + return true; + } else { + return false; + } + } else if (mom > ConfTrack.minMomPidTpcTofPion) { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfTrack.confNsigmaCombinedPion) { + return true; + } else { + return false; } } return false; } + bool isPionNSigmaRejected(float mom, float nsigmaTPCKa, float nsigmaTOFKa, float nsigmaTPCPr, float nsigmaTOFPr) + { + if (mom < ConfTrack.minMomPidTpcTofPion) { + if (std::abs(nsigmaTPCKa) < ConfTrack.confNsigmaPiRejectKaNsigma) { + return true; + } else if (std::abs(nsigmaTPCPr) < ConfTrack.confNsigmaPiRejectPrNsigma) { + return true; + } + } + if (mom > ConfTrack.minMomPidTpcTofPion) { + if (std::hypot(nsigmaTOFKa, nsigmaTPCKa) < ConfTrack.confNsigmaPiRejectKaNsigma) { + return true; + } else if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfTrack.confNsigmaPiRejectPrNsigma) { + return true; + } else { + return false; + } + } else { + return false; + } + } + bool isParticleNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) { switch (ConfTrack.confPDGCodeTrack) { case 2212: // Proton - case -2212: // anty Proton + case -2212: // Antiproton return isProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); break; - case 211: // Pion + case 211: // Pion+ case -211: // Pion- return isPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); break; @@ -360,6 +425,26 @@ struct FemtoUniversePairTaskTrackD0 { } } + bool isParticleNSigmaRejected(float mom, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCKa, float nsigmaTOFKa, float nsigmaTPCPr, float nsigmaTOFPr) + { + switch (ConfTrack.confPDGCodeTrack) { + case 2212: // Proton + case -2212: // Antiproton + return isProtonNSigmaRejected(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCKa, nsigmaTOFKa); + break; + case 211: // Pion+ + case -211: // Pion- + return isPionNSigmaRejected(mom, nsigmaTPCKa, nsigmaTOFKa, nsigmaTPCPr, nsigmaTOFPr); + break; + case 321: // Kaon+ + case -321: // Kaon- + return isKaonNSigmaLFRejected(mom, nsigmaTPCPi, nsigmaTOFPi, nsigmaTPCPr, nsigmaTOFPr); + break; + default: + return false; + } + } + void init(InitContext&) { efficiencyCalculator.init(); @@ -400,12 +485,15 @@ struct FemtoUniversePairTaskTrackD0 { qaRegistry.add("D0bar_neg_daugh/phi", "; #it{varphi}; Counts", kTH1F, {{200, 0, o2::constants::math::TwoPI}}); 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}}); + qaRegistry.add("Hadron/nSigmaTPCPr", "; #it{p} (GeV/#it{c}); n#sigma_{TPCPr}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFPr", "; #it{p} (GeV/#it{c}); n#sigma_{TOFPr}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaCombPr", "; #it{p} (GeV/#it{c}); n#sigma^{combined}_{Pr}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaTPCPi", "; #it{p} (GeV/#it{c}); n#sigma_{TPCPi}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFPi", "; #it{p} (GeV/#it{c}); n#sigma_{TOFPi}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaCombPi", "; #it{p} (GeV/#it{c}); n#sigma^{combined}_{Pi}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaTPCKa", "; #it{p} (GeV/#it{c}); n#sigma_{TPCKa}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaTOFKa", "; #it{p} (GeV/#it{c}); n#sigma_{TOFKa}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); + qaRegistry.add("Hadron/nSigmaCombKa", "; #it{p} (GeV/#it{c}); n#sigma^{combined}_{Ka}", kTH2F, {{100, 0, 10}, {200, -5.025, 5.025}}); // D0/D0bar histograms auto vbins = (std::vector)binsPt; @@ -468,6 +556,17 @@ struct FemtoUniversePairTaskTrackD0 { mcRecoRegistry.add("hMassVsPtD0barBkg", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); mcRecoRegistry.add("hMassVsPtD0barPrompt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); mcRecoRegistry.add("hMassVsPtD0barNonPrompt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + // Histograms for D0/D0bar correlated backgrounds + if (fillCorrBkgs) { + mcRecoRegistry.add("hMassVsPtD0ToPiKaPi", "2-prong candidates;inv. mass (#pi^{+} K^{-} #pi^{0}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0ToPiPi", "2-prong candidates;inv. mass (#pi^{+} #pi^{-}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0ToPiPiPi", "2-prong candidates;inv. mass (#pi^{+} #pi^{-} #pi^{0}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0ToKaKa", "2-prong candidates;inv. mass (K^{+} K^{-}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0barToPiKaPi", "2-prong candidates;inv. mass (#pi^{+} K^{-} #pi^{0}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0barToPiPi", "2-prong candidates;inv. mass (#pi^{+} #pi^{-}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0barToPiPiPi", "2-prong candidates;inv. mass (#pi^{+} #pi^{-} #pi^{0}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + mcRecoRegistry.add("hMassVsPtD0barToKaKa", "2-prong candidates;inv. mass (K^{+} K^{-}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {confInvMassBins, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + } // Histograms for identified hadrons mcRecoRegistry.add("hMcRecKpPt", "MC Reco K+;#it{p}_{T} (GeV/c); counts", {HistType::kTH1F, {{500, 0, 5}}}); mcRecoRegistry.add("hMcRecKpPtGenEtaGen", "MC Reco K+;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); @@ -812,6 +911,9 @@ struct FemtoUniversePairTaskTrackD0 { 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))) { continue; } + if (ConfTrack.confDoPartNsigmaRejection && isParticleNSigmaRejected(track.p(), 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), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton))) { + continue; + } } trackHistoPartTrack.fillQA(track); @@ -824,10 +926,13 @@ struct FemtoUniversePairTaskTrackD0 { qaRegistry.fill(HIST("Hadron/nSigmaTPCPi"), track.p(), tpcNSigmaPi); qaRegistry.fill(HIST("Hadron/nSigmaTOFPi"), track.p(), tofNSigmaPi); + qaRegistry.fill(HIST("Hadron/nSigmaCombPi"), track.p(), std::hypot(tpcNSigmaPi, tofNSigmaPi)); qaRegistry.fill(HIST("Hadron/nSigmaTPCKa"), track.p(), tpcNSigmaKa); qaRegistry.fill(HIST("Hadron/nSigmaTOFKa"), track.p(), tofNSigmaKa); + qaRegistry.fill(HIST("Hadron/nSigmaCombKa"), track.p(), std::hypot(tpcNSigmaKa, tofNSigmaKa)); qaRegistry.fill(HIST("Hadron/nSigmaTPCPr"), track.p(), tpcNSigmaPr); qaRegistry.fill(HIST("Hadron/nSigmaTOFPr"), track.p(), tofNSigmaPr); + qaRegistry.fill(HIST("Hadron/nSigmaCombPr"), track.p(), std::hypot(tpcNSigmaPr, tofNSigmaPr)); } } /// Now build the combinations @@ -836,6 +941,9 @@ struct FemtoUniversePairTaskTrackD0 { 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))) { continue; } + if (ConfTrack.confDoPartNsigmaRejection && isParticleNSigmaRejected(track.p(), 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), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton))) { + continue; + } } // Soft Pion Removal if (confRemoveSoftPions) { @@ -1033,6 +1141,9 @@ struct FemtoUniversePairTaskTrackD0 { 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))) { continue; } + if (ConfTrack.confDoPartNsigmaRejection && isParticleNSigmaRejected(track.p(), 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), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton))) { + continue; + } } // // Soft Pion Removal if (confRemoveSoftPions) { @@ -1388,6 +1499,17 @@ struct FemtoUniversePairTaskTrackD0 { } else { mcRecoRegistry.fill(HIST("hMassVsPtD0Bkg"), part.mLambda(), part.pt(), weight); } + if (fillCorrBkgs) { + if (part.sign() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0) { // D0 -> pi+K-pi0 + mcRecoRegistry.fill(HIST("hMassVsPtD0ToPiKaPi"), part.mLambda(), part.pt(), weight); + } else if (part.sign() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiPi) { // D0 -> pi+pi- + mcRecoRegistry.fill(HIST("hMassVsPtD0ToPiPi"), part.mLambda(), part.pt(), weight); + } else if (part.sign() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiPiPi0) { // D0 -> pi+pi-pi0 + mcRecoRegistry.fill(HIST("hMassVsPtD0ToPiPiPi"), part.mLambda(), part.pt(), weight); + } else if (part.sign() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToKK) { // D0 -> K+K- + mcRecoRegistry.fill(HIST("hMassVsPtD0ToKaKa"), part.mLambda(), part.pt(), weight); + } + } if (part.tpcNClsFound() == 0) { // prompt candidates mcRecoRegistry.fill(HIST("hMassVsPtD0Prompt"), part.mLambda(), part.pt(), weight); } else if (part.tpcNClsFound() == 1) { // non-prompt candidates @@ -1401,6 +1523,17 @@ struct FemtoUniversePairTaskTrackD0 { } else { mcRecoRegistry.fill(HIST("hMassVsPtD0barBkg"), part.mAntiLambda(), part.pt(), weight); } + if (fillCorrBkgs) { + if (part.sign() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0) { // D0 -> pi+K-pi0 + mcRecoRegistry.fill(HIST("hMassVsPtD0barToPiKaPi"), part.mLambda(), part.pt(), weight); + } else if (part.sign() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiPi) { // D0 -> pi+pi- + mcRecoRegistry.fill(HIST("hMassVsPtD0barToPiPi"), part.mLambda(), part.pt(), weight); + } else if (part.sign() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiPiPi0) { // D0 -> pi+pi-pi0 + mcRecoRegistry.fill(HIST("hMassVsPtD0barToPiPiPi"), part.mLambda(), part.pt(), weight); + } else if (part.sign() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToKK) { // D0 -> K+K- + mcRecoRegistry.fill(HIST("hMassVsPtD0barToKaKa"), part.mLambda(), part.pt(), weight); + } + } if (part.tpcNClsFound() == 0) { // prompt candidates mcRecoRegistry.fill(HIST("hMassVsPtD0barPrompt"), part.mAntiLambda(), part.pt(), weight); } else if (part.tpcNClsFound() == 1) { // non-prompt candidates diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx index f4eb45752dc..e672064bd59 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx @@ -16,24 +16,26 @@ /// \author Anton Riedel, TU München, anton.riedel@tum.de /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.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/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 using namespace o2; using namespace o2::analysis::femto_universe; diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx index dcecf711c08..5de02b3c346 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx @@ -65,22 +65,25 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { /// 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 ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; - - Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; - Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; - 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"}; + 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 confEtaMax{"confEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + + Configurable> confCutTable{"confCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable confNspecies{"confNspecies", 2, "Number of particle spieces with PID info"}; + 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"}; + Configurable confisIdenLCMS{"confisIdenLCMS", true, "Choosing identical or non-identical pairs in LCMS"}; + Configurable confIsWeight{"confIsWeight", false, "Fill quantum weight"}; + Configurable confisIdenPRF{"confisIdenPRF", false, "Choosing identical or non-identical pairs in PRF"}; } twotracksconfigs; SliceCache cache; using FemtoFullParticles = soa::Join; - Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.ConfEtaMax); // example filtering on configurable + Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax); // example filtering on configurable using FilteredFemtoFullParticles = soa::Filtered; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; @@ -90,18 +93,18 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { /// 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 ConfPtHighPart1{"ConfPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; - Configurable ConfChargePart1{"ConfChargePart1", 1, "Particle 1 sign"}; + 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 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 == as(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 == as(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 == as(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 == as(trackonefilter.confChargePart1) && aod::femtouniverseparticle::pt < trackonefilter.confPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.confPtLowPart1; // /// Histogramming for particle 1 @@ -109,19 +112,19 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { /// 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 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 ConfPtHighPart2{"ConfPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; - Configurable ConfChargePart2{"ConfChargePart2", -1, "Particle 2 sign"}; + Configurable confPtLowPart2{"confPtLowPart2", 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 == as(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 == as(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 == as(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 == as(tracktwofilter.confChargePart2)) && aod::femtouniverseparticle::pt < tracktwofilter.confPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.confPtLowPart2; /// Histogramming for particle 2 FemtoUniverseParticleHisto trackHistoPartTwo; @@ -134,53 +137,53 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { std::vector kNsigma; /// Event part - Configurable ConfV0MLow{"ConfV0MLow", 0.0, "Lower limit for V0M multiplicity"}; - Configurable ConfV0MHigh{"ConfV0MHigh", 25000.0, "Upper limit for V0M multiplicity"}; - Configurable ConfTPCOccupancyLow{"ConfTPCOccupancyLow", 0, "Lower limit for TPC occupancy"}; - Configurable ConfTPCOccupancyHigh{"ConfTPCOccupancyHigh", 500, "Higher limit for TPC occupancy"}; - Configurable ConfIsCent{"ConfIsCent", true, "Condition to choose centrality of multiplicity for mixing"}; - - Filter collfilter = (o2::aod::femtouniversecollision::multV0M > ConfV0MLow) && (o2::aod::femtouniversecollision::multV0M < ConfV0MHigh) && - (o2::aod::femtouniversecollision::occupancy >= ConfTPCOccupancyLow) && (o2::aod::femtouniversecollision::occupancy < ConfTPCOccupancyHigh); + Configurable confV0MLow{"confV0MLow", 0.0, "Lower limit for V0M multiplicity"}; + Configurable confV0MHigh{"confV0MHigh", 25000.0, "Upper limit for V0M multiplicity"}; + Configurable confTPCOccupancyLow{"confTPCOccupancyLow", 0, "Lower limit for TPC occupancy"}; + Configurable confTPCOccupancyHigh{"confTPCOccupancyHigh", 500, "Higher limit for TPC occupancy"}; + Configurable confIsCent{"confIsCent", true, "Condition to choose centrality of multiplicity for mixing"}; + + Filter collfilter = (o2::aod::femtouniversecollision::multV0M > confV0MLow) && (o2::aod::femtouniversecollision::multV0M < confV0MHigh) && + (o2::aod::femtouniversecollision::occupancy >= confTPCOccupancyLow) && (o2::aod::femtouniversecollision::occupancy < confTPCOccupancyHigh); using FilteredFDCollisions = soa::Filtered>; using FilteredFDCollision = FilteredFDCollisions::iterator; /// Particle part - ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confTempFitVarBins{"confDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; /// Correlation part - ConfigurableAxis ConfMultBins{"ConfMultBins", {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, 99999.f}, "Mixing bins - multiplicity or centrality"}; // \todo to be obtained from the hash task - ConfigurableAxis ConfMultKstarBins{"ConfMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; - ConfigurableAxis ConfKtKstarBins{"ConfKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; - 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 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 colBinningCent{{ConfVtxBins, ConfMultBins}, true}; - ColumnBinningPolicy colBinningNtr{{ConfVtxBins, ConfMultBins}, true}; - - ConfigurableAxis ConfkstarBins{"ConfkstarBins", {300, -1.5, 1.5}, "binning kstar"}; - ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; - ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; - Configurable ConfIsIden{"ConfIsIden", true, "Choosing identical or non-identical pairs"}; - Configurable ConfIsLCMS{"ConfIsLCMS", true, "Choosing LCMS or PRF"}; - Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; - 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"}; - Configurable ConfCPRdeltaPhiCutMin{"ConfCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; - Configurable ConfCPRdeltaEtaCutMax{"ConfCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; - 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 ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; - Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + ConfigurableAxis confMultBins{"confMultBins", {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, 99999.f}, "Mixing bins - multiplicity or centrality"}; // \todo to be obtained from the hash task + ConfigurableAxis confMultKstarBins{"confMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; + ConfigurableAxis confKtKstarBins{"confKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; + 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 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 colBinningCent{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningNtr{{confVtxBins, confMultBins}, true}; + + ConfigurableAxis confkstarBins{"confkstarBins", {300, -1.5, 1.5}, "binning kstar"}; + ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable confIsIden{"confIsIden", true, "Choosing identical or non-identical pairs"}; + Configurable confIsLCMS{"confIsLCMS", true, "Choosing LCMS or PRF"}; + Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; + 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"}; + Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; + Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; + 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 confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; 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 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"}; FemtoUniverseContainer sameEventCont1D; @@ -238,18 +241,18 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { //|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 + // 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 - if (mom < twotracksconfigs.ConfTOFPtMin) { - if (std::abs(nsigmaTPCPr) < twotracksconfigs.ConfNsigmaTPC) { + if (mom < twotracksconfigs.confTOFPtMin) { + if (std::abs(nsigmaTPCPr) < twotracksconfigs.confNsigmaTPC) { return true; } else { return false; } } else { - if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.ConfNsigmaCombined) { + if (std::hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.confNsigmaCombined) { return true; } else { return false; @@ -303,18 +306,18 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { //|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 + // 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 (std::abs(nsigmaTPCPi) < twotracksconfigs.ConfNsigmaTPC) { + if (mom < twotracksconfigs.confTOFPtMin) { + if (std::abs(nsigmaTPCPi) < twotracksconfigs.confNsigmaTPC) { return true; } else { return false; } } else { - if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.ConfNsigmaCombined) { + if (std::hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.confNsigmaCombined) { return true; } else { return false; @@ -327,7 +330,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { bool IsParticleNSigma(int8_t particle_number, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) { if (particle_number == 1) { - switch (trackonefilter.ConfPDGCodePartOne) { + switch (trackonefilter.confPDGCodePartOne) { case 2212: // Proton case -2212: // Antiproton return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); @@ -345,7 +348,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { } return false; } else if (particle_number == 2) { - switch (tracktwofilter.ConfPDGCodePartTwo) { + switch (tracktwofilter.confPDGCodePartTwo) { case 2212: // Proton case -2212: // Antiproton return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); @@ -371,64 +374,64 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { void init(InitContext&) { eventHisto.init(&qaRegistry); - trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, twotracksconfigs.ConfIsMC, trackonefilter.ConfPDGCodePartOne, true); + trackHistoPartOne.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, trackonefilter.confPDGCodePartOne, true); - trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, twotracksconfigs.ConfIsMC, tracktwofilter.ConfPDGCodePartTwo, true); + trackHistoPartTwo.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarBins, twotracksconfigs.confIsMC, tracktwofilter.confPDGCodePartTwo, true); MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - mass1 = pdg->Mass(trackonefilter.ConfPDGCodePartOne); - mass2 = pdg->Mass(tracktwofilter.ConfPDGCodePartTwo); + mass1 = pdg->Mass(trackonefilter.confPDGCodePartOne); + mass2 = pdg->Mass(tracktwofilter.confPDGCodePartTwo); if (cfgProcessPM) { if (!cfgProcessKtMt3DCF) { - sameEventCont.init(&resultRegistryPM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D, ConfIsIden); - mixedEventCont.init(&resultRegistryPM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D, ConfIsIden); - sameEventCont.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); - mixedEventCont.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + sameEventCont.init(&resultRegistryPM, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D, confIsIden); + mixedEventCont.init(&resultRegistryPM, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D, confIsIden); + sameEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else if (cfgProcessMultBins && cfgProcessKtMt3DCF) { - sameEventMultCont.init(&SameMultRegistryPM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); - mixedEventMultCont.init(&MixedMultRegistryPM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); + sameEventMultCont.init(&SameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); + mixedEventMultCont.init(&MixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); } } if (cfgProcessPP) { if (!cfgProcessKtMt3DCF) { - sameEventContPP.init(&resultRegistryPP, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D, ConfIsIden); - mixedEventContPP.init(&resultRegistryPP, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D, ConfIsIden); - sameEventContPP.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); - mixedEventContPP.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + sameEventContPP.init(&resultRegistryPP, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D, confIsIden); + mixedEventContPP.init(&resultRegistryPP, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D, confIsIden); + sameEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else if (cfgProcessMultBins && cfgProcessKtMt3DCF) { - sameEventMultContPP.init(&SameMultRegistryPP, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); - mixedEventMultContPP.init(&MixedMultRegistryPP, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); + sameEventMultContPP.init(&SameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); + mixedEventMultContPP.init(&MixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); } - sameEventCont1D.init(&resultRegistry1D, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); - sameEventCont1D.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); - mixedEventCont1D.init(&resultRegistry1D, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); - mixedEventCont1D.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + sameEventCont1D.init(&resultRegistry1D, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, confEtaBins, confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + sameEventCont1D.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventCont1D.init(&resultRegistry1D, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, confEtaBins, confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); + mixedEventCont1D.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } if (cfgProcessMM) { if (!cfgProcessKtMt3DCF) { - sameEventContMM.init(&resultRegistryMM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D, ConfIsIden); - mixedEventContMM.init(&resultRegistryMM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D, ConfIsIden); - sameEventContMM.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); - mixedEventContMM.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + sameEventContMM.init(&resultRegistryMM, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D, confIsIden); + mixedEventContMM.init(&resultRegistryMM, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D, confIsIden); + sameEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); + mixedEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else if (cfgProcessMultBins && cfgProcessKtMt3DCF) { - sameEventMultContMM.init(&SameMultRegistryMM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); - mixedEventMultContMM.init(&MixedMultRegistryMM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); + sameEventMultContMM.init(&SameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); + mixedEventMultContMM.init(&MixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, cfgProcessKtBins, cfgProcessKtMt3DCF); } } pairCleaner.init(&qaRegistry); - if (ConfIsCPR.value) { - pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiCutMin.value, ConfCPRdeltaPhiCutMax.value, ConfCPRdeltaEtaCutMin.value, ConfCPRdeltaEtaCutMax.value, ConfCPRChosenRadii.value, ConfCPRPlotPerRadii.value); + if (confIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value); } - vPIDPartOne = trackonefilter.ConfPIDPartOne.value; - vPIDPartTwo = tracktwofilter.ConfPIDPartTwo.value; - kNsigma = twotracksconfigs.ConfTrkPIDnSigmaMax.value; + vPIDPartOne = trackonefilter.confPIDPartOne.value; + vPIDPartTwo = tracktwofilter.confPIDPartTwo.value; + kNsigma = twotracksconfigs.confTrkPIDnSigmaMax.value; } template @@ -463,7 +466,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { continue; } trackHistoPartOne.fillQA(part); - trackHistoPartOne.fillQAMisIden(part, trackonefilter.ConfPDGCodePartOne); + trackHistoPartOne.fillQAMisIden(part, trackonefilter.confPDGCodePartOne); } } @@ -489,7 +492,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { continue; } - if (ConfIsCPR.value) { + if (confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } @@ -503,9 +506,9 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); if (!cfgProcessMultBins) { - sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); sameEventMultCont.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -522,7 +525,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { continue; } - if (ConfIsCPR.value) { + if (confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } @@ -541,29 +544,29 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); + k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); sameEventMultContPP.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } float weight = 1.0f; if constexpr (std::is_same::value) { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } else { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } } else { if (!cfgProcessMultBins) { - sameEventContPP.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + sameEventContPP.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); sameEventMultContPP.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } float weight = 1.0f; if constexpr (std::is_same::value) { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } else { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } } break; @@ -576,29 +579,29 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); + k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); sameEventMultContMM.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } float weight = 1.0f; if constexpr (std::is_same::value) { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } else { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } } else { if (!cfgProcessMultBins) { - sameEventContMM.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + sameEventContMM.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); sameEventMultContMM.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } float weight = 1.0f; if constexpr (std::is_same::value) { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } else { - sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, weight, ConfIsIden); + sameEventCont1D.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight, confIsIden); } } break; @@ -616,7 +619,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { void processSameEvent(FilteredFDCollision const& col, FilteredFemtoFullParticles const& parts) { - fillCollision(col, ConfIsCent); + fillCollision(col, confIsCent); auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); @@ -624,7 +627,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { bool fillQA = true; randgen = new TRandom2(0); - if (ConfIsCent) { + if (confIsCent) { if (cfgProcessPM) { doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 1, fillQA); } @@ -657,14 +660,14 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { FilteredFemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) { - fillCollision(col, ConfIsCent); + fillCollision(col, confIsCent); auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); bool fillQA = true; randgen = new TRandom2(0); - if (ConfIsCent) { + if (confIsCent) { if (cfgProcessPM) { doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 1, fillQA); } @@ -713,7 +716,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { continue; } - if (ConfIsCPR.value) { + if (confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { continue; } @@ -728,16 +731,16 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); mixedEventMultCont.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } else { if (!cfgProcessMultBins) { - mixedEventCont.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + mixedEventCont.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); mixedEventMultCont.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -748,16 +751,16 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); mixedEventMultContPP.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } else { if (!cfgProcessMultBins) { - mixedEventContPP.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + mixedEventContPP.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); mixedEventMultContPP.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -769,16 +772,16 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { if (rand > 0.5) { if (!cfgProcessMultBins) { - mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); mixedEventMultContMM.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } else { if (!cfgProcessMultBins) { - mixedEventContMM.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D, ConfIsIden); + mixedEventContMM.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { - std::vector k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + std::vector k3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); mixedEventMultContMM.fill3D(k3d[1], k3d[2], k3d[3], multCol, kT); } } @@ -799,7 +802,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { { randgen = new TRandom2(0); - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, ConfNEventsMix, -1, cols, cols)) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multV0M(); MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); @@ -841,7 +844,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { { randgen = new TRandom2(0); - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, ConfNEventsMix, -1, cols, cols)) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multV0M(); MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), multiplicityCol})); @@ -883,7 +886,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { { randgen = new TRandom2(0); - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, ConfNEventsMix, -1, cols, cols)) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multNtr(); MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); @@ -925,7 +928,7 @@ struct femtoUniversePairTaskTrackTrack3DMultKtExtended { { randgen = new TRandom2(0); - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, ConfNEventsMix, -1, cols, cols)) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { const int multiplicityCol = collision1.multNtr(); MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx index 06665491396..7760a8f2451 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx @@ -16,24 +16,24 @@ /// \author Anton Riedel, TU München, anton.riedel@tum.de /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch -#include -#include -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include -#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/FemtoUniverseTrackSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h" +#include +#include using namespace o2; using namespace o2::analysis::femto_universe; diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx index 7eee98d1f62..840f66fc56e 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKtExtended.cxx @@ -34,6 +34,8 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include "TRandom2.h" + #include #include @@ -173,7 +175,8 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; 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 confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Chosen CPR radii"}; + Configurable confRandomizeCPR{"confRandomizeCPR", false, "Fill Dete-Dphi histograms in random order: p1, p2 or p2, p1"}; Configurable isPairIdentical{"isPairIdentical", true, "'true' for identical particles, 'false' for non-identical particles"}; struct : o2::framework::ConfigurableGroup { @@ -230,6 +233,8 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { HistogramRegistry sphericityRegistry{"SphericityHisto", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + TRandom2* randgen; + /// TPC Pion/Kaon/Proton Sigma selection (general) bool isNSigma(float mom, float nsigmaTPC, float nsigmaTOF) { @@ -361,6 +366,7 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (doprocessFractionsMCTruth) { mixedMultRegistryPM.add("MCtruth/motherParticle", "pair fractions; part1 mother PDG; part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); + mixedMultRegistryPM.add("MCtruth/mcProcess", "pair ; part1 VMC physics code; part2 VMC physics code", {HistType::kTH2F, {{50, 0, 50}, {50, 0, 50}}}); } } @@ -371,6 +377,7 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (doprocessFractionsMCTruth) { mixedMultRegistryPP.add("MCtruth/motherParticle", "pair fractions; part1 mother PDG; part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); + mixedMultRegistryPP.add("MCtruth/mcProcess", "pair ; part1 VMC physics code; part2 VMC physics code", {HistType::kTH2F, {{50, 0, 50}, {50, 0, 50}}}); } sameEventContPP.init(&resultRegistryPP, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); mixedEventContPP.init(&resultRegistryPP, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); @@ -390,6 +397,7 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (doprocessFractionsMCTruth) { mixedMultRegistryMM.add("MCtruth/motherParticle", "pair fractions; part1 mother PDG; part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); + mixedMultRegistryMM.add("MCtruth/mcProcess", "pair ; part1 VMC physics code; part2 VMC physics code", {HistType::kTH2F, {{50, 0, 50}, {50, 0, 50}}}); } sameEventContMM.init(&resultRegistryMM, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); mixedEventContMM.init(&resultRegistryMM, confkstarBins, confMultBins, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); @@ -473,7 +481,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } @@ -503,7 +525,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } @@ -638,7 +674,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { continue; } } @@ -799,7 +849,21 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { } if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejection.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { return; } } @@ -882,40 +946,51 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { /// \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 - template + template void doFractionsMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int ContType) { - - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - - int pdgCodePartOne = static_cast(p1.pidCut()); - const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); - int pdgCodePartTwo = static_cast(p2.pidCut()); - const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); - switch (ContType) { - case 1: { + switch (ContType) { + case 1: { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + int pdgCodePartOne = static_cast(p1.pidCut()); + const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); + int pdgCodePartTwo = static_cast(p2.pidCut()); + const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { - continue; + mixedMultRegistryPM.fill(HIST("MCtruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); + mixedMultRegistryPM.fill(HIST("MCtruth/mcProcess"), p1.cut(), p2.cut()); } - mixedMultRegistryPM.fill(HIST("MCtruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); - break; } - case 2: { + break; + } + case 2: { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsOne))) { + int pdgCodePartOne = static_cast(p1.pidCut()); + const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); + int pdgCodePartTwo = static_cast(p2.pidCut()); + const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == trackonefilter.confPDGCodePartOne)) { - continue; + mixedMultRegistryPP.fill(HIST("MCtruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); + mixedMultRegistryPP.fill(HIST("MCtruth/mcProcess"), p1.cut(), p2.cut()); } - mixedMultRegistryPP.fill(HIST("MCtruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); - break; } - case 3: { + break; + } + case 3: { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { + int pdgCodePartOne = static_cast(p1.pidCut()); + const auto& pdgParticleOne = pdg->GetParticle(pdgCodePartOne); + int pdgCodePartTwo = static_cast(p2.pidCut()); + const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == tracktwofilter.confPDGCodePartTwo) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { - continue; + mixedMultRegistryMM.fill(HIST("MCtruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); + mixedMultRegistryMM.fill(HIST("MCtruth/mcProcess"), p1.cut(), p2.cut()); } - mixedMultRegistryMM.fill(HIST("MCtruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); } - default: - break; + break; } + default: + break; } } @@ -942,13 +1017,13 @@ struct FemtoUniversePairTaskTrackTrackMultKtExtended { auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); if (processPair.cfgProcessPM) { - doFractionsMCTruth(groupPartsOne, groupPartsTwo, 1); + doFractionsMCTruth(groupPartsOne, groupPartsTwo, 1); } if (processPair.cfgProcessPP) { - doFractionsMCTruth(groupPartsOne, groupPartsOne, 2); + doFractionsMCTruth(groupPartsOne, groupPartsOne, 2); } if (processPair.cfgProcessMM) { - doFractionsMCTruth(groupPartsTwo, groupPartsTwo, 3); + doFractionsMCTruth(groupPartsTwo, groupPartsTwo, 3); } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 4c6e9091fac..023a355abc6 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -56,6 +56,12 @@ static const float cutsTable[nPart][nCuts]{ {4.05f, 1.f, 3.f, 3.f, 100.f}}; } // namespace +enum PairType { + PlusMinus, + PlusPlus, + MinusMinus +}; + struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Service pdg; @@ -80,6 +86,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; + Configurable confIsCPRatITS{"confIsCPRatITS", false, "Close Pair check at ITS"}; Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0., "Delta Phi min cut for Close Pair Rejection"}; @@ -90,9 +97,17 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable> confCPRdeltaEtaCutMaxVector{"confCPRdeltaEtaCutMaxVector", std::vector{0.0, 0.0, 0.0, 0.0}, "Delta Eta max cut for Close Pair Rejection"}; Configurable> confCPRdeltaEtaCutMinVector{"confCPRdeltaEtaCutMinVector", std::vector{0.0, 0.0, 0.0, 0.0}, "Delta Eta min cut for Close Pair Rejection"}; Configurable confIsCPRkT{"confIsCPRkT", true, "kT dependent deltaEta-deltaPhi cut for Close Pair Rejection"}; + Configurable confTrkDCAxyMax{"confTrkDCAxyMax", 0.2, "Max DCA in xy "}; + Configurable confTrkDCAzMax{"confTrkDCAzMax", 0.2, "Max DCA in z "}; + Configurable confTrkTPCcRowsMin{"confTrkTPCcRowsMin", 80, "Min of TPC crossed rows"}; + Configurable confTrkTPCfClsMin{"confTrkTPCfClsMin", 0.83, "Min. fraction of crossed rows/findable TPC clusters"}; + Configurable confTrkTPCfracsClsMax{"confTrkTPCfracsClsMax", 1.0, "Max of fraction of TPC shared cluster "}; + Configurable confTrkTPCnClsMin{"confTrkTPCnClsMin", 80, "Min number of TPC clusters"}; + Configurable confTrkTPCsClsMax{"confTrkTPCsClsMax", 160, "Max number of TPC shared clusters"}; + Configurable confPairFracSharedTPCclsMin{"confPairFracSharedTPCclsMin", 0.0, "Min. fraction of TPC shared clusters between two closed tracks"}; + Configurable confPairFracSharedTPCclsMax{"confPairFracSharedTPCclsMax", 1.0, "Miax. fraction of TPC shared clusters between two closed tracks"}; Configurable confCPRChosenRadii{"confCPRChosenRadii", 0.80, "Delta Eta cut for Close Pair Rejection"}; Configurable confUseCCImCut{"confUseCCImCut", false, "Fill SH within specific quadrants of qout-qside"}; - Configurable confUseMinqTcut{"confUseMinqTcut", false, "Fill SH with min. qT cut"}; Configurable confMinqTcut{"confMinqTcut", 0.005, "Min. qT cut on filling SH"}; Configurable confUse1stand3rd{"confUse1stand3rd", false, "Use first and third quadrants of qout-qside"}; Configurable confUse2ndand4th{"confUse2ndand4th", false, "Use second and fourth quadrants of qout-qside"}; @@ -100,14 +115,23 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable confCPRDistMax{"confCPRDistMax", 0.0, "Max. radial seperation between two closed-pairs"}; Configurable confCPRFracMax{"confCPRFracMax", 0.0, "Max. allowed fraction bad to all TPC points of radial seperation between two closed-pairs"}; Configurable confCPRDphiAvgOrDist{"confCPRDphiAvgOrDist", true, "Close Pair Rejection by radial or angular seperation"}; + Configurable confIsCircularCut{"confIsCircularCut", true, "Close Pair Rejection within circular area"}; Configurable confIs1D{"confIs1D", true, "Filling 1D 2k* dist. in MC truth"}; - Configurable confIsIden{"confIsIden", true, "Choosing identical or non-identical pairs"}; + Configurable confisIdenLCMS{"confisIdenLCMS", true, "Choosing identical or non-identical pairs in LCMS"}; Configurable confIsWeight{"confIsWeight", true, "Fill quantum weight"}; + Configurable confisIdenPRF{"confisIdenPRF", false, "Choosing identical or non-identical pairs in PRF"}; } twotracksconfigs; using FemtoFullParticles = soa::Join; // Filters for selecting particles (both p1 and p2) - Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax); // example filtering on Configurable + Filter trackAdditionalfilter = ((nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.confEtaMax) && + (aod::track::dcaXY <= twotracksconfigs.confTrkDCAxyMax) && + (aod::track::dcaZ <= twotracksconfigs.confTrkDCAzMax) && + (aod::femtouniverseparticle::tpcNClsCrossedRows >= static_cast(twotracksconfigs.confTrkTPCcRowsMin)) && + (aod::femtouniverseparticle::tpcFractionSharedCls <= twotracksconfigs.confTrkTPCfracsClsMax) && + (aod::femtouniverseparticle::tpcNClsFound >= static_cast(twotracksconfigs.confTrkTPCnClsMin)) && + (aod::track::tpcNClsShared <= static_cast(twotracksconfigs.confTrkTPCsClsMax))); + using FilteredFemtoFullParticles = soa::Filtered; // using FilteredFemtoFullParticles = FemtoFullParticles; //if no filtering is applied uncomment this optionconfIsCPRkT using FemtoRecoParticles = soa::Join; @@ -185,7 +209,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { ConfigurableAxis confTempFitVarpTBins{"confTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; /// Correlation part - ConfigurableAxis confMultBinsCent{"confMultBinsCent", {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, 99999.f}, "Mixing bins - centrality"}; // \todo to be obtained from the hash task + ConfigurableAxis confMultBinsCent{"confMultBinsCent", {VARIABLE_WIDTH, 0.0f, 2.5f, 5.0f, 7.5f, 10.0f, 12.5f, 15.0f, 17.5f, 20.0f, 22.5f, 25.0f, 27.5f, 30.0f, 32.5f, 35.0f, 37.5f, 40.0f, 42.5f, 45.0f, 47.5f, 50.0f, 52.5f, 55.0f, 57.5f, 60.0f, 62.5f, 65.0f, 67.5f, 70.5f, 75.0f, 80.0f, 90.0f, 100.0f, 99999.f}, "Mixing bins - centrality"}; ConfigurableAxis confMultBinsMult{"confMultBinsMult", {VARIABLE_WIDTH, 0.0f, 400.0f, 800.0f, 1200.0f, 1600.0f, 2000.0f, 2500.0f, 3000.0f, 3500.0f, 4000.0f, 4500.0f, 5000.0f, 6000.0f, 7000.0f, 8000.0f, 9000.0f, 10000.0f, 11000.0f, 12000.0f, 13000.0f, 14000.0f, 15000.0f, 16000.0f, 17000.0f, 18000.0f, 99999.f}, "Mixing bins - centrality"}; ConfigurableAxis confMultKstarBins{"confMultKstarBins", {VARIABLE_WIDTH, 0.0f, 200.0f}, "Bins for kstar analysis in multiplicity or centrality bins (10 is maximum)"}; ConfigurableAxis confKtKstarBins{"confKtKstarBins", {VARIABLE_WIDTH, 0.1f, 0.2f, 0.3f, 0.4f}, "Bins for kstar analysis in kT bins"}; @@ -425,8 +449,8 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { sameEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); mixedEventCont.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else { - sameEventMultCont.init(&SameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax); - mixedEventMultCont.init(&MixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax); + sameEventMultCont.init(&SameMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultCont.init(&MixedMultRegistryPM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); } } @@ -437,8 +461,8 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { sameEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); mixedEventContPP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else { - sameEventMultContPP.init(&SameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax); - mixedEventMultContPP.init(&MixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax); + sameEventMultContPP.init(&SameMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContPP.init(&MixedMultRegistryPP, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); } sameEventCont1D_PP.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); sameEventCont1D_PP.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); @@ -453,8 +477,8 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { sameEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); mixedEventContMM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); } else { - sameEventMultContMM.init(&SameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax); - mixedEventMultContMM.init(&MixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax); + sameEventMultContMM.init(&SameMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); + mixedEventMultContMM.init(&MixedMultRegistryMM, confkstarBins, confMultKstarBins, confKtKstarBins, confLMax, twotracksconfigs.confIs1D); } sameEventCont1D_MM.init(&resultRegistry1D, confkstarBins, confMultBinsCent, confkTBins, confmTBins, confmultBins3D, confmTBins3D, twotracksconfigs.confEtaBins, twotracksconfigs.confPhiBins, twotracksconfigs.confIsMC, twotracksconfigs.confUse3D); sameEventCont1D_MM.setPDGCodes(trackonefilter.confPDGCodePartOne, tracktwofilter.confPDGCodePartTwo); @@ -495,11 +519,10 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// @param magFieldTesla magnetic field of the collision /// @param multCol multiplicity of the collision 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, PairType contType, bool fillQA) { - /// Histogramming same event - if ((ContType == 1 || ContType == 2) && fillQA) { + if ((contType == PairType::PlusMinus || contType == PairType::PlusPlus) && fillQA) { for (const auto& part : groupPartsOne) { 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::Electron))) { continue; @@ -509,7 +532,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } - if ((ContType == 1 || ContType == 3) && fillQA) { + if ((contType == PairType::PlusMinus || contType == PairType::MinusMinus) && fillQA) { for (const auto& part : groupPartsTwo) { 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::Electron))) { continue; @@ -518,7 +541,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } - if (ContType == 1) { + if (contType == PairType::PlusMinus) { /// Now build the combinations for non-identical particle pairs for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { @@ -537,19 +560,23 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (kT < firstRealElement || kT > lastElement) continue; + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } if (twotracksconfigs.confIsCPR.value) { - if (twotracksconfigs.confCPRFracMax.value) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } else { if (twotracksconfigs.confIsCPRkT) { - if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confCPRDphiAvgOrDist)) { + if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { continue; } } else { - if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confCPRDphiAvgOrDist)) { + if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { continue; } } @@ -560,7 +587,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } else { for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { @@ -580,18 +607,34 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (kT < firstRealElement || kT > lastElement) continue; + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + double rand; + rand = randgen->Rndm(); + + auto part1 = p1; + auto part2 = p2; + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + if (twotracksconfigs.confIsCPR.value) { - if (twotracksconfigs.confCPRFracMax.value) { - if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::same)) { continue; } } else { if (twotracksconfigs.confIsCPRkT) { - if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confCPRDphiAvgOrDist)) { + if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::same, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { continue; } } else { - if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confCPRDphiAvgOrDist)) { + if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::same, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { continue; } } @@ -599,51 +642,32 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } // track cleaning - if (!pairCleaner.isCleanPair(p1, p2, parts)) { + if (!pairCleaner.isCleanPair(part1, part2, parts)) { continue; } - double rand; - rand = randgen->Rndm(); - - auto part1 = p1; - auto part2 = p2; - - if (rand > 0.5) { - part1 = p2; - part2 = p1; - } - std::vector f3d; double kv; float outsideref = 0.0; - float qTmin = 0.0; - switch (ContType) { - case 2: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confIsIden); - qTmin = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2]); + switch (contType) { + case PairType::PlusPlus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); if (!twotracksconfigs.confUseCCImCut) { - if (!twotracksconfigs.confUseMinqTcut) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); - } else { - if (qTmin > twotracksconfigs.confMinqTcut) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); - } - } + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { if (twotracksconfigs.confUse1stand3rd) { if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } else if (twotracksconfigs.confUse2ndand4th) { if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - sameEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + sameEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); @@ -652,31 +676,24 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { break; } - case 3: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confIsIden); - qTmin = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2]); + case PairType::MinusMinus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); if (!twotracksconfigs.confUseCCImCut) { - if (!twotracksconfigs.confUseMinqTcut) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); - } else { - if (qTmin > twotracksconfigs.confMinqTcut) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); - } - } + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { if (twotracksconfigs.confUse1stand3rd) { if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } else if (twotracksconfigs.confUse2ndand4th) { if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - sameEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + sameEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); @@ -707,23 +724,23 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (confIsCent) { if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 1, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); } if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), 2, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); } if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 3, fillQA); + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); } } else { if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 1, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); } if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), 2, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); } if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 3, fillQA); + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); } } delete randgen; @@ -747,23 +764,23 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (confIsCent) { if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 1, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::PlusMinus, fillQA); } if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), 2, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multV0M(), PairType::PlusPlus, fillQA); } if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), 3, fillQA); + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multV0M(), PairType::MinusMinus, fillQA); } } else { if (cfgProcessPM) { - doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 1, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::PlusMinus, fillQA); } if (cfgProcessPP) { - doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), 2, fillQA); + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), PairType::PlusPlus, fillQA); } if (cfgProcessMM) { - doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 3, fillQA); + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), PairType::MinusMinus, fillQA); } } delete randgen; @@ -781,7 +798,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// @param magFieldTesla magnetic field of the collision /// @param multCol multiplicity of the collision template - void doSameEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, int ContType, bool fillQA) + void doSameEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, PairType contType, bool fillQA) { randgen = new TRandom2(0); @@ -821,7 +838,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { const auto& pdgParticleTwo = pdg->GetParticle(pdgCodePartTwo); if (pdgParticleOne && pdgParticleTwo && (pdgCodePartOne == trackonefilter.confPDGCodePartOne) && (pdgCodePartTwo == tracktwofilter.confPDGCodePartTwo)) { float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); - sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultCont.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } } else { @@ -846,25 +863,25 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { part2 = p1; } - switch (ContType) { - case 2: { + switch (contType) { + case PairType::PlusPlus: { if (twotracksconfigs.confIs1D) { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confIsIden, twotracksconfigs.confIsWeight); + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); float weight = f3d[5]; - sameEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + sameEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { - sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } break; } - case 3: { + case PairType::MinusMinus: { if (twotracksconfigs.confIs1D) { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confIsIden, twotracksconfigs.confIsWeight); + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); float weight = f3d[5]; - sameEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + sameEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { - sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confIsIden); + sameEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::same, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } break; } @@ -890,13 +907,13 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { auto thegroupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); bool fillQA = true; - int pairType = 0; + PairType pairType = PairType::PlusMinus; if (cfgProcessPM) { - pairType = 1; + pairType = PairType::PlusMinus; } else if (cfgProcessPP) { - pairType = 2; + pairType = PairType::PlusPlus; } else if (cfgProcessMM) { - pairType = 3; + pairType = PairType::MinusMinus; } if (confIsCent) { @@ -934,7 +951,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// \param magFieldTesla magnetic field of the collision /// \param multCol multiplicity of the collision template - void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, float magFieldTesla, int multCol, int ContType) + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, float magFieldTesla, int multCol, PairType contType) { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { @@ -954,70 +971,67 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (kT < firstRealElement || kT > lastElement) continue; + float pairFractionTPCsCls = static_cast((p1.tpcNClsShared() + p2.tpcNClsShared())) / static_cast((p1.tpcNClsFound() + p2.tpcNClsFound())); + if (pairFractionTPCsCls < twotracksconfigs.confPairFracSharedTPCclsMin.value || pairFractionTPCsCls >= twotracksconfigs.confPairFracSharedTPCclsMax.value) { + continue; + } + + double rand; + rand = randgen->Rndm(); + auto part1 = p1; + auto part2 = p2; + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + if (twotracksconfigs.confIsCPR.value) { - if (twotracksconfigs.confCPRFracMax.value) { - if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed)) { + if (twotracksconfigs.confIsCPRatITS && twotracksconfigs.confCPRFracMax.value) { + if (pairCloseRejection.isClosePairAtITS(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed)) { continue; } } else { if (twotracksconfigs.confIsCPRkT) { - if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::mixed, kT, twotracksconfigs.confCPRDphiAvgOrDist)) { + if (pairCloseRejection.isClosePairkT(p1, p2, femto_universe_container::EventType::mixed, kT, twotracksconfigs.confIsCircularCut, twotracksconfigs.confCPRDphiAvgOrDist, magFieldTesla, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax)) { continue; } } else { - if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confCPRDphiAvgOrDist)) { + if (pairCloseRejection.isClosePairFrac(part1, part2, magFieldTesla, femto_universe_container::EventType::mixed, twotracksconfigs.confCPRDphiAvgOrDist, twotracksconfigs.confCPRDistMax, twotracksconfigs.confCPRFracMax, twotracksconfigs.confIsCircularCut)) { continue; } } } } - double rand; - rand = randgen->Rndm(); - auto part1 = p1; - auto part2 = p2; - - if (rand > 0.5) { - part1 = p2; - part2 = p1; - } - std::vector f3d; double kv; float outsideref = 0.0; - float qTmin = 0.0; - switch (ContType) { - case 1: { - mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + switch (contType) { + case PairType::PlusMinus: { + mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); break; } - case 2: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confIsIden); - qTmin = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2]); + case PairType::PlusPlus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); if (!twotracksconfigs.confUseCCImCut) { - if (!twotracksconfigs.confUseMinqTcut) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); - } else { - if (qTmin > twotracksconfigs.confMinqTcut) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); - } - } + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { if (twotracksconfigs.confUse1stand3rd) { if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } else if (twotracksconfigs.confUse2ndand4th) { if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - mixedEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + mixedEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { @@ -1027,31 +1041,24 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { break; } - case 3: { - f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confIsIden); - qTmin = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2]); + case PairType::MinusMinus: { + f3d = FemtoUniverseMath::newpairfunc(part1, mass1, part2, mass2, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); if (!twotracksconfigs.confUseCCImCut) { - if (!twotracksconfigs.confUseMinqTcut) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); - } else { - if (qTmin > twotracksconfigs.confMinqTcut) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); - } - } + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } else { if (twotracksconfigs.confUse1stand3rd) { if ((f3d[1] >= outsideref && f3d[2] >= outsideref) || (f3d[1] < outsideref && f3d[2] < outsideref)) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } else if (twotracksconfigs.confUse2ndand4th) { if ((f3d[1] < outsideref && f3d[2] >= outsideref) || (f3d[1] >= outsideref && f3d[2] < outsideref)) { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } } } if (twotracksconfigs.confIsMC || twotracksconfigs.confUse3D) { float weight = 1.0f; - mixedEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + mixedEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } if (twotracksconfigs.confIsFillAngqLCMS) { kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); @@ -1073,6 +1080,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { FilteredFemtoFullParticles const&) { randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { @@ -1089,17 +1104,17 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (cfgProcessPM) { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessPP) { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessMM) { auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } } delete randgen; @@ -1113,6 +1128,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { FilteredFemtoFullParticles const&) { randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { @@ -1129,17 +1152,17 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (cfgProcessPM) { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessPP) { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessMM) { auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } } delete randgen; @@ -1155,6 +1178,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { o2::aod::FdMCParticles const&) { randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { @@ -1173,17 +1204,17 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (cfgProcessPM) { auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessPP) { auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessMM) { auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } } delete randgen; @@ -1199,6 +1230,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { o2::aod::FdMCParticles const&) { randgen = new TRandom2(0); + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { @@ -1217,17 +1256,17 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { if (cfgProcessPM) { auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessPP) { auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } if (cfgProcessMM) { auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); - doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, pairType); } } delete randgen; @@ -1245,7 +1284,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// \param magFieldTesla magnetic field of the collision /// \param multCol multiplicity of the collision template - void doMixedEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, int ContType) + void doMixedEventMCTruth(PartitionType groupPartsOne, PartitionType groupPartsTwo, int multCol, PairType contType) { randgen = new TRandom2(0); for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { @@ -1269,28 +1308,28 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { part1 = p2; part2 = p1; } - switch (ContType) { - case 1: { - mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + switch (contType) { + case PairType::PlusMinus: { + mixedEventMultCont.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); break; } - case 2: { + case PairType::PlusPlus: { if (twotracksconfigs.confIs1D) { float weight = 1.0; - mixedEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + mixedEventCont1D_PP.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { - mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + mixedEventMultContPP.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } break; } - case 3: { + case PairType::MinusMinus: { if (twotracksconfigs.confIs1D) { float weight = 1.0; - mixedEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confIsIden); + mixedEventCont1D_MM.setPair(part1, part2, multCol, twotracksconfigs.confUse3D, weight, twotracksconfigs.confisIdenLCMS); } else { - mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confIsIden); + mixedEventMultContMM.fillMultNumDen(part1, part2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, twotracksconfigs.confisIdenLCMS, twotracksconfigs.confIs1D, twotracksconfigs.confIsWeight, twotracksconfigs.confisIdenPRF); } break; } @@ -1308,13 +1347,13 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { void processMixedEventNtrMCTruth(o2::aod::FdCollisions const& cols, FemtoTruthParticles const&) { - int pairType = 0; + PairType pairType = PairType::PlusMinus; if (cfgProcessPM) { - pairType = 1; + pairType = PairType::PlusMinus; } else if (cfgProcessPP) { - pairType = 2; + pairType = PairType::PlusPlus; } else if (cfgProcessMM) { - pairType = 3; + pairType = PairType::MinusMinus; } for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningNtr, confNEventsMix, -1, cols, cols)) { @@ -1340,6 +1379,45 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } } PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventNtrMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEventCentMCTruth(o2::aod::FdCollisions const& cols, + FemtoTruthParticles const&) + { + PairType pairType = PairType::PlusMinus; + if (cfgProcessPM) { + pairType = PairType::PlusMinus; + } else if (cfgProcessPP) { + pairType = PairType::PlusPlus; + } else if (cfgProcessMM) { + pairType = PairType::MinusMinus; + } + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + + const int multiplicityCol = collision1.multV0M(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningNtr.getBin({collision1.posZ(), multiplicityCol})); + + if (cfgProcessPM) { + auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOneMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCTruth->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEventMCTruth(groupPartsOne, groupPartsTwo, multiplicityCol, pairType); + } + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackSpherHarMultKtExtended, processMixedEventCentMCTruth, "Enable processing MC Truth mixed events for multiplicity", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index 9c08064901f..c317199d716 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -22,12 +22,14 @@ #include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "CCDB/BasicCCDBManager.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "TRandom2.h" #include #include #include @@ -57,6 +59,8 @@ struct FemtoUniversePairTaskTrackV0Extended { using FemtoRecoParticles = soa::Join; Preslice perColMC = aod::femtouniverseparticle::fdCollisionId; + using FemtoBasicParticles = soa::Join; + /// 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"}; @@ -74,6 +78,8 @@ struct FemtoUniversePairTaskTrackV0Extended { Configurable confmom{"confmom", 0.5, "momentum threshold for particle identification using TOF"}; Configurable confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle momentum < confmom"}; + Configurable confNsigmaTPCDaughter{"confNsigmaTPCDaughter", 3.0, "TPC Sigma for daughter"}; + Configurable confNsigmaTOFParticle{"confNsigmaTOFParticle", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"}; Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle momentum > confmom"}; @@ -109,6 +115,12 @@ struct FemtoUniversePairTaskTrackV0Extended { Configurable confHPtPart2{"confHPtPart2", 4.0f, "higher limit for pt of particle 2"}; Configurable confLPtPart2{"confLPtPart2", 0.3f, "lower limit for pt of particle 2"}; Configurable confUseStrangenessTOF{"confUseStrangenessTOF", true, "Use strangeness TOF for cascade PID"}; + Configurable confHPtChildProton{"confHPtChildProton", 10.0f, "Higher limit for pt of children protons/antiprotons"}; + Configurable confLPtChildProton{"confLPtChildProton", 0.f, "Lower limit for pt of children protons/antiprotons"}; + Configurable confHPtChildPion{"confHPtChildPion", 10.0f, "Higher limit for pt of children pions"}; + Configurable confLPtChildPion{"confLPtChildPion", 0.f, "Lower limit for pt of children pions"}; + Configurable confV0DuplCosPA{"confV0DuplCosPA", false, "Use cosPA instead of inv. mass as a deciding factor in rejecting a V0 in V0V0 pairs"}; + Configurable confSeparateInvMassCheck{"confSeparateInvMassCheck", false, "Apply additional cut separate for mLambda and mAntiLambda"}; } ConfV0Selection; /// Partition for particle 2 using extended table @@ -139,6 +151,7 @@ struct FemtoUniversePairTaskTrackV0Extended { /// Correlation part // Configurable confTrackChoicePartTwo{"confTrackChoicePartTwo", 1, "0:Proton, 1:Pion, 2:Kaon"}; //not used Configurable confIsMC{"confIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"}; + Configurable confIsDebug{"confIsDebug", false, "Enable additional histograms (e.g. three-momentum)"}; 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"}; @@ -147,18 +160,23 @@ struct FemtoUniversePairTaskTrackV0Extended { ConfigurableAxis confkstarBins{"confkstarBins", {1500, 0., 6.}, "binning kstar"}; ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; - Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; - Configurable confRectV0V0CPR{"confRectV0V0CPR", true, "Enable rectangular CPR cut for V0-V0 pairs"}; - Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; - Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; - Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; - Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; - 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 confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; 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)"}; + ConfigurableAxis confMotherPDGBins{"confMotherPDGBins", {8001, -4000, 4000}, "Binning for the mothers' PDG code in pair fractions histogram"}; + + struct : o2::framework::ConfigurableGroup { + Configurable confIsCPR{"confIsCPR", true, "Close Pair Rejection"}; + Configurable confRectV0V0CPR{"confRectV0V0CPR", true, "Enable rectangular CPR cut for V0-V0 pairs"}; + Configurable confCPRPlotPerRadii{"confCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable confCPRdeltaPhiCutMax{"confCPRdeltaPhiCutMax", 0.0, "Delta Phi max cut for Close Pair Rejection"}; + Configurable confCPRdeltaPhiCutMin{"confCPRdeltaPhiCutMin", 0.0, "Delta Phi min cut for Close Pair Rejection"}; + Configurable confCPRdeltaEtaCutMax{"confCPRdeltaEtaCutMax", 0.0, "Delta Eta max cut for Close Pair Rejection"}; + 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 confRandomizeCPR{"confRandomizeCPR", false, "Fill Dete-Dphi histograms in random order: v01, v02 or v02, v01 - does not apply to track-V0"}; + } ConfCPR; // Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; @@ -167,6 +185,7 @@ struct FemtoUniversePairTaskTrackV0Extended { EfficiencyCorrection effCorrection{&effCorConfGroup}; static constexpr unsigned int V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; // Table to select the V0 children + static constexpr double v0InvMass[] = {1.115, 1.115, 0.497}; // Table to select invariant mass of V0s FemtoUniverseContainer sameEventCont; FemtoUniverseContainer mixedEventCont; @@ -183,36 +202,60 @@ struct FemtoUniversePairTaskTrackV0Extended { std::set v0Duplicates; std::unique_ptr plocalEffFile; - std::unique_ptr plocalEffp1; - std::unique_ptr plocalEffp2; + std::unique_ptr pEffHistp1; + std::unique_ptr pEffHistp2; + Service ccdb; + + TRandom2* randgen; - bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle, bool hasTOF) { if (mom <= confmom) { return (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle); - } else { + } else if (hasTOF == 1) { return (std::hypot(nsigmaTOFParticle, nsigmaTPCParticle) < confNsigmaCombinedParticle); + } else { + return false; } } - bool invMLambda(float invMassLambda, float invMassAntiLambda) + template + bool isNSigmaCombinedBitmask(float mom, const T& part) { - if ((invMassLambda < ConfV0Selection.confV0InvMassLowLimit || invMassLambda > ConfV0Selection.confV0InvMassUpLimit) && (invMassAntiLambda < ConfV0Selection.confV0InvMassLowLimit || invMassAntiLambda > ConfV0Selection.confV0InvMassUpLimit)) { + if (mom <= confmom) { + return ((part.pidCut() & (1u << ConfTrkSelection.confTrackChoicePartOne)) != 0); + } else if ((part.pidCut() & 512u) != 0) { + return ((part.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) != 0); + } else { return false; } + } + + bool invMLambda(float invMassLambda, float invMassAntiLambda, int V0Type) + { + if (ConfV0Selection.confSeparateInvMassCheck) { + const float pMass = V0Type ? invMassAntiLambda : invMassLambda; + if (pMass < ConfV0Selection.confV0InvMassLowLimit || pMass > ConfV0Selection.confV0InvMassUpLimit) { + return false; + } + } else { + if ((invMassLambda < ConfV0Selection.confV0InvMassLowLimit || invMassLambda > ConfV0Selection.confV0InvMassUpLimit) && (invMassAntiLambda < ConfV0Selection.confV0InvMassLowLimit || invMassAntiLambda > ConfV0Selection.confV0InvMassUpLimit)) { + return false; + } + } return true; } bool isNSigmaTPC(float nsigmaTPCParticle) { - if (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle) { + if (std::abs(nsigmaTPCParticle) < confNsigmaTPCDaughter) { return true; } else { return false; } } - bool isNSigmaTOF(float mom, float nsigmaTOFParticle, float hasTOF) + bool isNSigmaTOF(float mom, float nsigmaTOFParticle, bool hasTOF) { // Cut only on daughter tracks, that have TOF signal if (mom > confmom && hasTOF == 1) { @@ -232,7 +275,7 @@ struct FemtoUniversePairTaskTrackV0Extended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id]); + return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id], (part.pidCut() & 512u) != 0); } template @@ -270,6 +313,14 @@ struct FemtoUniversePairTaskTrackV0Extended { qaRegistry.add("V0Type2/hInvMassLambdaVsCent", "; Centrality; M_{#Lambda}; Entries", kTH2F, {confMultBins, {2000, 1.f, 3.f}}); qaRegistry.add("V0Type1/hInvMassAntiLambdaVsCent", "; Centrality; M_{#Lambda}; Entries", kTH2F, {confMultBins, {2000, 1.f, 3.f}}); qaRegistry.add("V0Type2/hInvMassAntiLambdaVsCent", "; Centrality; M_{#Lambda}; Entries", kTH2F, {confMultBins, {2000, 1.f, 3.f}}); + + if (confIsDebug) { + qaRegistry.add("SameEvent/hPtPosDaugh", "; #it{p}_{T}^{1} (GeV/c); #it{p}_{T}^{2} (GeV/c)", kTH2F, {{500, 0, 5}, {500, 0, 5}}); + qaRegistry.add("SameEvent/hPtNegDaugh", "; #it{p}_{T}^{1} (GeV/c); #it{p}_{T}^{2} (GeV/c)", kTH2F, {{500, 0, 5}, {500, 0, 5}}); + qaRegistry.add("SameEvent/hDaughMomPart1", "; #it{p}_{T}^{+} (GeV/c); #it{p}_{T}^{-} (GeV/c)", kTH2F, {{500, 0, 5}, {500, 0, 5}}); + qaRegistry.add("SameEvent/hDaughMomPart2", "; #it{p}_{T}^{+} (GeV/c); #it{p}_{T}^{-} (GeV/c)", kTH2F, {{500, 0, 5}, {500, 0, 5}}); + } + trackHistoV0Type1.init(&qaRegistry, ConfV0Selection.confV0TempFitVarpTBins, ConfV0Selection.confV0TempFitVarBins, confIsMC, ConfV0Selection.confV0PDGCodePartTwo, true, "V0Type1"); posChildV0Type1.init(&qaRegistry, ConfV0Selection.confChildTempFitVarpTBins, ConfV0Selection.confChildTempFitVarBins, false, 0, true, "posChildV0Type1"); negChildV0Type1.init(&qaRegistry, ConfV0Selection.confChildTempFitVarpTBins, ConfV0Selection.confChildTempFitVarBins, false, 0, true, "negChildV0Type1"); @@ -297,7 +348,10 @@ struct FemtoUniversePairTaskTrackV0Extended { 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}}}); - registryMCtruth.add("mothersTruth/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); + if (doprocessPairFractionsMCTruthV0 || doprocessPairFractionsMCTruth) { + registryMCtruth.add("mothersTruth/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); + registryMCtruth.add("mothersTruth/mcProcess", "pair ; part1 VMC physics code; part2 VMC physics code", {HistType::kTH2F, {{50, 0, 50}, {50, 0, 50}}}); + } // 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}}}); @@ -321,9 +375,10 @@ struct FemtoUniversePairTaskTrackV0Extended { 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}}}); - registryMCreco.add("mothersReco/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); - registryMCreco.add("mothersReco/motherParticlePDGCheck", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {{8001, -4000, 4000}, {8001, -4000, 4000}}}); - + if (doprocessPairFractions || doprocessPairFractionsV0) { + registryMCreco.add("mothersReco/motherParticle", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); + registryMCreco.add("mothersReco/motherParticlePDGCheck", "pair fractions;part1 mother PDG;part2 mother PDG", {HistType::kTH2F, {confMotherPDGBins, confMotherPDGBins}}); + } sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); sameEventCont.setPDGCodes(ConfTrkSelection.confTrkPDGCodePartOne, ConfV0Selection.confV0PDGCodePartTwo); mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); @@ -331,24 +386,40 @@ struct FemtoUniversePairTaskTrackV0Extended { pairCleaner.init(&qaRegistry); pairCleanerV0.init(&qaRegistry); - if (confIsCPR.value) { - 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 (ConfCPR.confIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPR.confCPRdeltaPhiCutMin.value, ConfCPR.confCPRdeltaPhiCutMax.value, ConfCPR.confCPRdeltaEtaCutMin.value, ConfCPR.confCPRdeltaEtaCutMax.value, ConfCPR.confCPRChosenRadii.value, ConfCPR.confCPRPlotPerRadii.value); + pairCloseRejectionV0.init(&resultRegistry, &qaRegistry, ConfCPR.confCPRdeltaPhiCutMin.value, ConfCPR.confCPRdeltaPhiCutMax.value, ConfCPR.confCPRdeltaEtaCutMin.value, ConfCPR.confCPRdeltaEtaCutMax.value, ConfCPR.confCPRChosenRadii.value, ConfCPR.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 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now - plocalEffp2 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { + pEffHistp1 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + pEffHistp2 = (ConfV0Selection.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 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); - plocalEffp2 = (ConfV0Selection.confV0Type2 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + } else if (doprocessSameEventV0 || doprocessSameEventV0Bitmask || doprocessMixedEventV0 || doprocessMixedEventV0Bitmask) { + pEffHistp1 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + pEffHistp2 = (ConfV0Selection.confV0Type2 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); LOGF(info, "Loaded efficiency histograms for V0-V0."); } + } else if (!effCorConfGroup.confEffCorCCDBPath.value.empty()) { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + if (doprocessSameEvent || doprocessSameEventBitmask || doprocessMixedEvent || doprocessMixedEventBitmask) { + pEffHistp1 = (ConfTrkSelection.confChargePart1 > 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/PrPlus", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/PrMinus", now)); // note: works only for protons for now + pEffHistp2 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", now)); + LOGF(info, "Loaded efficiency histograms for track-V0 from CCDB."); + } else if (doprocessSameEventV0 || doprocessSameEventV0Bitmask || doprocessMixedEventV0 || doprocessMixedEventV0Bitmask) { + pEffHistp1 = (ConfV0Selection.confV0Type1 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", now)); + pEffHistp2 = (ConfV0Selection.confV0Type2 == 0) ? std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/Lambda", now)) : std::unique_ptr(ccdb->getForTimeStamp(effCorConfGroup.confEffCorCCDBPath.value + "/AntiLambda", now)); + LOGF(info, "Loaded efficiency histograms for V0-V0 from CCDB."); + } } effCorrection.init(&qaRegistry, {static_cast(ConfV0Selection.confV0TempFitVarpTBins), {confEtaBins, -2, 2}, confMultBins}); @@ -370,12 +441,20 @@ struct FemtoUniversePairTaskTrackV0Extended { eventHisto.fillQA(col); + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + /// Histogramming same event for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } + /// Daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) @@ -399,7 +478,6 @@ struct FemtoUniversePairTaskTrackV0Extended { if ((posChild.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type1][0])) == 0 || (negChild.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type1][1])) == 0) continue; } - trackHistoPartTwo.fillQA(part); posChildHistos.fillQA(posChild); negChildHistos.fillQA(negChild); @@ -412,7 +490,7 @@ struct FemtoUniversePairTaskTrackV0Extended { const float tpcNSigmas[3] = {aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStoreKa())}; const float tofNSigmas[3] = {aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStoreKa())}; - if (!isNSigmaCombined(part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne], tofNSigmas[ConfTrkSelection.confTrackChoicePartOne])) + if (!isNSigmaCombined(part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne], tofNSigmas[ConfTrkSelection.confTrackChoicePartOne], (part.pidCut() & 512u) != 0)) continue; if (part.sign() > 0) { qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[ConfTrkSelection.confTrackChoicePartOne]); @@ -424,7 +502,7 @@ struct FemtoUniversePairTaskTrackV0Extended { trackHistoPartOneNeg.fillQA(part); } } else { - if ((part.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + if (!isNSigmaCombinedBitmask(part.p(), part)) continue; if (ConfTrkSelection.confChargePart1 > 0) trackHistoPartOnePos.fillQA(part); @@ -436,27 +514,26 @@ struct FemtoUniversePairTaskTrackV0Extended { /// Now build the combinations for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; /// PID using stored binned nsigma if constexpr (std::experimental::is_detected::value) { if (!isParticleCombined(p1, ConfTrkSelection.confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + if (!isNSigmaCombinedBitmask(p1.p(), p1)) continue; } // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - if (confIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { - continue; - } - } + const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } /// Daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { @@ -479,16 +556,21 @@ struct FemtoUniversePairTaskTrackV0Extended { } } + if (ConfCPR.confIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + 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 (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->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); } } - /// This function processes the same event for V0 - V0 template void doSameEventV0(FilteredFDCollision const& col, PartType const& parts, PartitionType& groupPartsTwo, [[maybe_unused]] MCParticles mcParts = nullptr) @@ -499,12 +581,18 @@ struct FemtoUniversePairTaskTrackV0Extended { eventHisto.fillQA(col); - /// Histogramming same event + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + + /// Histogramming same event for first V0 particle for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } /// Check daughters of first V0 particle if constexpr (std::experimental::is_detected::value) { @@ -512,9 +600,12 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) continue; + trackHistoV0Type1.fillQABase(part, HIST("V0Type1")); posChildV0Type1.fillQABase(posChild, HIST("posChildV0Type1")); negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); + qaRegistry.fill(HIST("V0Type1/hInvMassLambdaVsCent"), multCol, part.mLambda()); + qaRegistry.fill(HIST("V0Type1/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); } else { if ((posChild.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type1][0])) == 0 || (negChild.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type1][1])) == 0) continue; @@ -529,11 +620,20 @@ struct FemtoUniversePairTaskTrackV0Extended { posChildV0Type1.fillQABase(posChild, HIST("posChildV0Type1")); negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); } - qaRegistry.fill(HIST("V0Type1/hInvMassLambdaVsCent"), multCol, part.mLambda()); - qaRegistry.fill(HIST("V0Type1/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); if constexpr (isMC) { effCorrection.fillRecoHist(part, kLambda0); } + } + + /// Histogramming same event for second V0 particle + for (const auto& part : groupPartsTwo) { + if (!invMLambda(part.mLambda(), part.mAntiLambda(), ConfV0Selection.confV0Type2)) + continue; + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][1]) { + continue; + } /// Check daughters of second V0 particle if constexpr (std::experimental::is_detected::value) { @@ -541,25 +641,26 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type2][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type2][1])) continue; + trackHistoV0Type2.fillQABase(part, HIST("V0Type2")); posChildV0Type2.fillQABase(posChild, HIST("posChildV0Type2")); negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); + qaRegistry.fill(HIST("V0Type2/hInvMassLambdaVsCent"), multCol, part.mLambda()); + qaRegistry.fill(HIST("V0Type2/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); } else { - if ((posChild.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type1][0])) == 0 || (negChild.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type1][1])) == 0) + if ((posChild.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type2][0])) == 0 || (negChild.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type2][1])) == 0) continue; if (ConfV0Selection.confUseStrangenessTOF) { - if (((ConfV0Selection.confV0Type1 == 0) && (part.pidCut() & 3) != 3) || ((ConfV0Selection.confV0Type1 == 1) && (part.pidCut() & 12) != 12) || ((ConfV0Selection.confV0Type1 == 2) && (part.pidCut() & 48) != 48)) + if (((ConfV0Selection.confV0Type2 == 0) && (part.pidCut() & 3) != 3) || ((ConfV0Selection.confV0Type1 == 1) && (part.pidCut() & 12) != 12) || ((ConfV0Selection.confV0Type2 == 2) && (part.pidCut() & 48) != 48)) continue; } else { - if ((posChild.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type1][0])) == 0 || (negChild.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type1][1])) == 0) + if ((posChild.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type2][0])) == 0 || (negChild.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type2][1])) == 0) continue; } trackHistoV0Type2.fillQABase(part, HIST("V0Type2")); posChildV0Type2.fillQABase(posChild, HIST("posChildV0Type2")); negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); } - qaRegistry.fill(HIST("V0Type2/hInvMassLambdaVsCent"), multCol, part.mLambda()); - qaRegistry.fill(HIST("V0Type2/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); if constexpr (isMC) { effCorrection.fillRecoHist(part, kLambda0Bar); } @@ -567,72 +668,108 @@ struct FemtoUniversePairTaskTrackV0Extended { auto pairDuplicateCheckFunc = [&](auto& p1, auto& p2) -> void { // V0 inv mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) return; // V0 inv mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) return; + // track cleaning & checking for duplicate pairs if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { - // mark for rejection the cascades that share a daughter with other cascades - v0Duplicates.insert(p1.globalIndex()); - v0Duplicates.insert(p2.globalIndex()); + // mark for rejection the cascade that shares a daughter with another cascade and has an invariant mass further from default value + if (!ConfV0Selection.confV0DuplCosPA) { + if (std::abs(p1.mLambda() - v0InvMass[ConfV0Selection.confV0Type1]) < std::abs(p2.mLambda() - v0InvMass[ConfV0Selection.confV0Type2])) { + v0Duplicates.insert(p2.globalIndex()); + } else { + v0Duplicates.insert(p1.globalIndex()); + } + } else { + if (std::abs(p1.tempFitVar() - 1) < std::abs(p2.tempFitVar() - 1)) { + v0Duplicates.insert(p2.globalIndex()); + } else { + v0Duplicates.insert(p1.globalIndex()); + } + } } }; - auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + auto pairProcessFunc = [&](auto& p1, auto& p2) -> bool { if (v0Duplicates.contains(p1.globalIndex()) || v0Duplicates.contains(p2.globalIndex())) - return; + return false; // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) - return; + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) + return false; // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) - return; - if (confIsCPR.value) { - if (confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { - return; - } else if (!confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { - return; - } - } + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) + return false; + const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild1.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild1.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild1.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild1.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + return false; + } + /// p1 daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild1, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild1, V0ChildTable[ConfV0Selection.confV0Type1][1])) - return; + return false; if (!isParticleTOF(posChild1, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild1, V0ChildTable[ConfV0Selection.confV0Type1][1])) - return; + return false; } else { if ((posChild1.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type1][0])) == 0 || (negChild1.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type1][1])) == 0) - return; + return false; if (ConfV0Selection.confUseStrangenessTOF) { if (((ConfV0Selection.confV0Type1 == 0) && (p1.pidCut() & 3) != 3) || ((ConfV0Selection.confV0Type1 == 1) && (p1.pidCut() & 12) != 12) || ((ConfV0Selection.confV0Type1 == 2) && (p1.pidCut() & 48) != 48)) - return; + return false; } else { if ((posChild1.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type1][0])) == 0 || (negChild1.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type1][1])) == 0) - return; + return false; } } const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild2.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][0] || negChild2.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][1] || posChild2.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][0] || negChild2.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][1]) { + return false; + } + /// p2 daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild2, V0ChildTable[ConfV0Selection.confV0Type2][0]) || !isParticleTPC(negChild2, V0ChildTable[ConfV0Selection.confV0Type2][1])) - return; + return false; if (!isParticleTOF(posChild2, V0ChildTable[ConfV0Selection.confV0Type2][0]) || !isParticleTOF(negChild2, V0ChildTable[ConfV0Selection.confV0Type2][1])) - return; + return false; } else { if ((posChild2.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type2][0])) == 0 || (negChild2.pidCut() & (1u << V0ChildTable[ConfV0Selection.confV0Type2][1])) == 0) - return; + return false; if (ConfV0Selection.confUseStrangenessTOF) { if (((ConfV0Selection.confV0Type2 == 0) && (p2.pidCut() & 3) != 3) || ((ConfV0Selection.confV0Type2 == 1) && (p2.pidCut() & 12) != 12) || ((ConfV0Selection.confV0Type2 == 2) && (p2.pidCut() & 48) != 48)) - return; + return false; } else { if ((posChild2.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type2][0])) == 0 || (negChild2.pidCut() & (8u << V0ChildTable[ConfV0Selection.confV0Type2][1])) == 0) - return; + return false; + } + } + + if (ConfCPR.confIsCPR.value) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (ConfCPR.confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + return false; + } else if (!ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + return false; } } @@ -640,24 +777,35 @@ struct FemtoUniversePairTaskTrackV0Extended { sameEventCont.setPair(p1, p2, multCol, confUse3D); else sameEventCont.setPair(p1, p2, multCol, confUse3D); + return true; }; v0Duplicates.clear(); - if (ConfV0Selection.confV0Type1 == ConfV0Selection.confV0Type2) { - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairDuplicateCheckFunc(p1, p2); - } - /// Now build the combinations for identical V0s - for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairProcessFunc(p1, p2); - } - } else { - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairDuplicateCheckFunc(p1, p2); - } - /// Now build the combinations for non-identical V0s - for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { - pairProcessFunc(p1, p2); + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairDuplicateCheckFunc(p1, p2); + } + /// Now build the combinations for V0s + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + if (!pairProcessFunc(p1, p2)) { + if (pairProcessFunc(p2, p1) && confIsDebug) { + const auto& posChild1 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild1 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + const auto& posChild2 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild2 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); + qaRegistry.fill(HIST("SameEvent/hPtPosDaugh"), posChild1.pt(), posChild2.pt()); + qaRegistry.fill(HIST("SameEvent/hPtNegDaugh"), negChild1.pt(), negChild2.pt()); + qaRegistry.fill(HIST("SameEvent/hDaughMomPart1"), posChild1.pt(), negChild1.pt()); + qaRegistry.fill(HIST("SameEvent/hDaughMomPart2"), posChild2.pt(), negChild2.pt()); + } + } else if (confIsDebug) { + const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); + const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + qaRegistry.fill(HIST("SameEvent/hPtPosDaugh"), posChild1.pt(), posChild2.pt()); + qaRegistry.fill(HIST("SameEvent/hPtNegDaugh"), negChild1.pt(), negChild2.pt()); + qaRegistry.fill(HIST("SameEvent/hDaughMomPart1"), posChild1.pt(), negChild1.pt()); + qaRegistry.fill(HIST("SameEvent/hDaughMomPart2"), posChild2.pt(), negChild2.pt()); } } } @@ -745,7 +893,7 @@ struct FemtoUniversePairTaskTrackV0Extended { if ((ConfV0Selection.confV0Type1 == 0 && pdgCode2 != kLambda0) || (ConfV0Selection.confV0Type1 == 1 && pdgCode2 != kLambda0Bar)) continue; // track cleaning - if (confIsCPR.value) { + if (ConfCPR.confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { continue; } @@ -819,6 +967,9 @@ struct FemtoUniversePairTaskTrackV0Extended { ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); @@ -834,19 +985,23 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; /// PID using stored binned nsigma if constexpr (std::experimental::is_detected::value) { if (!isParticleCombined(p1, ConfTrkSelection.confTrackChoicePartOne)) continue; } else { - if ((p1.pidCut() & (64u << ConfTrkSelection.confTrackChoicePartOne)) == 0) + if (!isNSigmaCombinedBitmask(p1.p(), p1)) continue; } const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } + /// Daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) @@ -869,14 +1024,14 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - if (confIsCPR.value) { + if (ConfCPR.confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::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 (pEffHistp1) + weight = pEffHistp1.get()->GetBinContent(pEffHistp1->FindBin(p1.pt(), p1.eta())) * pEffHistp2.get()->GetBinContent(pEffHistp2->FindBin(p2.pt(), p2.eta())); if constexpr (std::is_same::value) mixedEventCont.setPair(p1, p2, multCol, confUse3D, weight); @@ -905,6 +1060,9 @@ struct FemtoUniversePairTaskTrackV0Extended { ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); @@ -920,16 +1078,21 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) { continue; } // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) { + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) { continue; } const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); + + if (posChild1.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild1.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild1.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild1.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } + /// Daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild1, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild1, V0ChildTable[ConfV0Selection.confV0Type1][1])) @@ -950,6 +1113,10 @@ struct FemtoUniversePairTaskTrackV0Extended { const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild2.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][0] || negChild2.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][1] || posChild2.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][0] || negChild2.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][1]) { + continue; + } + /// Daughters that do not pass this condition are not selected if constexpr (std::experimental::is_detected::value) { if (!isParticleTPC(posChild2, V0ChildTable[ConfV0Selection.confV0Type2][0]) || !isParticleTPC(negChild2, V0ChildTable[ConfV0Selection.confV0Type2][1])) @@ -972,10 +1139,24 @@ struct FemtoUniversePairTaskTrackV0Extended { if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { continue; } - if (confIsCPR.value) { - if (confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + if (ConfCPR.confIsCPR.value) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (ConfCPR.confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; - } else if (!confRectV0V0CPR && pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + } else if (!ConfCPR.confRectV0V0CPR && pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; } } @@ -1060,7 +1241,7 @@ struct FemtoUniversePairTaskTrackV0Extended { int pdgCode2 = static_cast(p2.pidCut()); if ((ConfV0Selection.confV0Type1 == 0 && pdgCode2 != kLambda0) || (ConfV0Selection.confV0Type1 == 1 && pdgCode2 != kLambda0Bar)) continue; - if (confIsCPR.value) { + if (ConfCPR.confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; } @@ -1178,6 +1359,9 @@ struct FemtoUniversePairTaskTrackV0Extended { ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { auto groupPartsOne = partsOneMCRecoFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMCRecoFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); @@ -1191,23 +1375,29 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type1)) continue; /// PID using stored binned nsigma if (!isParticleCombined(p1, ConfTrkSelection.confTrackChoicePartOne)) continue; - const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2); - const auto& negChild = parts.iteratorAt(p2.globalIndex() - 1); + const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { + continue; + } + /// Daughters that do not pass this condition are not selected if (!isParticleTPC(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) continue; + if (!isParticleTOF(posChild, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild, V0ChildTable[ConfV0Selection.confV0Type1][1])) + continue; // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - if (confIsCPR.value) { + if (ConfCPR.confIsCPR.value) { if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; } @@ -1239,6 +1429,9 @@ struct FemtoUniversePairTaskTrackV0Extended { ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + float v0DaughPtLowTable[3][2] = {{ConfV0Selection.confLPtChildProton, ConfV0Selection.confLPtChildPion}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildProton}, {ConfV0Selection.confLPtChildPion, ConfV0Selection.confLPtChildPion}}; + float v0DaughPtHighTable[3][2] = {{ConfV0Selection.confHPtChildProton, ConfV0Selection.confHPtChildPion}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildProton}, {ConfV0Selection.confHPtChildPion, ConfV0Selection.confHPtChildPion}}; + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { auto groupPartsOne = partsTwoMCRecoFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMCRecoFull->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); @@ -1252,32 +1445,58 @@ struct FemtoUniversePairTaskTrackV0Extended { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), ConfV0Selection.confV0Type1)) { continue; } // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) { + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), ConfV0Selection.confV0Type2)) { + continue; + } + + const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild1.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][0] || negChild1.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type1][1] || posChild1.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][0] || negChild1.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type1][1]) { 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 if (!isParticleTPC(posChild1, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTPC(negChild1, V0ChildTable[ConfV0Selection.confV0Type1][1])) continue; + if (!isParticleTOF(posChild1, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild1, V0ChildTable[ConfV0Selection.confV0Type1][1])) + continue; + + const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + if (posChild2.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][0] || negChild2.pt() < v0DaughPtLowTable[ConfV0Selection.confV0Type2][1] || posChild2.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][0] || negChild2.pt() > v0DaughPtHighTable[ConfV0Selection.confV0Type2][1]) { + continue; + } - const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 2); - const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 1); /// Daughters that do not pass this condition are not selected if (!isParticleTPC(posChild2, V0ChildTable[ConfV0Selection.confV0Type2][0]) || !isParticleTPC(negChild2, V0ChildTable[ConfV0Selection.confV0Type2][1])) continue; + if (!isParticleTOF(negChild2, V0ChildTable[ConfV0Selection.confV0Type1][0]) || !isParticleTOF(negChild2, V0ChildTable[ConfV0Selection.confV0Type1][1])) + continue; // track cleaning if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { continue; } - if (confIsCPR.value) { - if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + if (ConfCPR.confIsCPR.value) { + double rand; + auto part1 = p1; + auto part2 = p2; + + if (ConfCPR.confRandomizeCPR) { + randgen = new TRandom2(0); + rand = randgen->Rndm(); + + if (rand > 0.5) { + part1 = p2; + part2 = p1; + } + delete randgen; + } + if (pairCloseRejectionV0.isClosePair(part1, part2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { continue; } } @@ -1295,6 +1514,7 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; if ((ConfV0Selection.confV0Type2 == 0 && mcParticle2.pdgMCTruth() != kLambda0) || (ConfV0Selection.confV0Type2 == 1 && mcParticle2.pdgMCTruth() != kLambda0Bar)) continue; + registryMCreco.fill(HIST("mothersReco/motherParticlePDGCheck"), p1.motherPDG(), p2.motherPDG()); } }; @@ -1330,6 +1550,7 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; registryMCtruth.fill(HIST("mothersTruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); + registryMCtruth.fill(HIST("mothersTruth/mcProcess"), p1.cut(), p2.cut()); } }; @@ -1363,6 +1584,7 @@ struct FemtoUniversePairTaskTrackV0Extended { continue; registryMCtruth.fill(HIST("mothersTruth/motherParticle"), p1.tempFitVar(), p2.tempFitVar()); + registryMCtruth.fill(HIST("mothersTruth/mcProcess"), p1.cut(), p2.cut()); } }; @@ -1378,7 +1600,8 @@ struct FemtoUniversePairTaskTrackV0Extended { } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processPairFractionsMCTruthV0, "Process MC data to obtain pair fractions for V0V0 MC truth pairs", false); - void processMCReco(FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + template + void doMCReco(PartType const& parts, aod::FdMCParticles const& mcparts) { for (const auto& part : parts) { auto mcPartId = part.fdMCParticleId(); @@ -1388,54 +1611,111 @@ struct FemtoUniversePairTaskTrackV0Extended { // if (part.partType() == aod::femtouniverseparticle::ParticleType::kV0) { if (mcpart.pdgMCTruth() == kLambda0) { - 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 + if (!invMLambda(part.mLambda(), part.mAntiLambda(), 0)) + continue; + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if constexpr (std::experimental::is_detected::value) { + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, 0) || !isParticleTPC(negChild, 1)) + continue; + + if (!isParticleTOF(posChild, 0) || !isParticleTOF(negChild, 1)) + continue; + + } else { + if ((posChild.pidCut() & (1u << 0)) == 0 || (negChild.pidCut() & (1u << 1)) == 0) + continue; + + if (ConfV0Selection.confUseStrangenessTOF) { + if ((part.pidCut() & 3) != 3) + continue; + } else { + if ((posChild.pidCut() & (8u << 0)) == 0 || (negChild.pidCut() & (8u << 1)) == 0) + continue; } } + registryMCreco.fill(HIST("plus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // lambda + } else if (mcpart.pdgMCTruth() == kLambda0Bar) { - 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 + if (!invMLambda(part.mLambda(), part.mAntiLambda(), 1)) + continue; + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if constexpr (std::experimental::is_detected::value) { + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, 1) || !isParticleTPC(negChild, 0)) + continue; + + if (!isParticleTOF(posChild, 1) || !isParticleTOF(negChild, 0)) + continue; + + } else { + if ((posChild.pidCut() & (1u << 1)) == 0 || (negChild.pidCut() & (1u << 0)) == 0) + continue; + + if (ConfV0Selection.confUseStrangenessTOF) { + if ((part.pidCut() & 12) != 12) + continue; + } else { + if ((posChild.pidCut() & (8u << 1)) == 0 || (negChild.pidCut() & (8u << 0)) == 0) + continue; } } + registryMCreco.fill(HIST("minus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // anti-lambda } } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { - if (part.sign() > 0) { + if (part.mAntiLambda() > 0) { // mAntiLambda is the sign here registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == kPiPlus && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { + if (mcpart.pdgMCTruth() == kPiPlus) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), (part.pidCut() & 512u) != 0)) + continue; + } else { + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 128u) == 0) // 128 for pion combined + continue; + } else if ((part.pidCut() & 2u) == 0) { + continue; + } + } registryMCreco.fill(HIST("plus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPiPt"), mcpart.pt()); - } else if (mcpart.pdgMCTruth() == kProton && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { + } else if (mcpart.pdgMCTruth() == kProton) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) + continue; + } else { + if (!isNSigmaCombinedBitmask(part.p(), part)) + continue; + } registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); } - } - - if (part.sign() < 0) { + } else if (part.mAntiLambda() < 0) { registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == kPiMinus && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()))) { + if (mcpart.pdgMCTruth() == kPiMinus) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePi()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePi()), (part.pidCut() & 512u) != 0)) + continue; + } else { + if ((part.pidCut() & 512u) != 0) { + if ((part.pidCut() & 128u) == 0) // 128 for pion combined + continue; + } else if ((part.pidCut() & 2u) == 0) { + continue; + } + } registryMCreco.fill(HIST("minus/MCrecoPi"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPiPt"), mcpart.pt()); - } else if (mcpart.pdgMCTruth() == kProtonBar && isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()))) { + } else if (mcpart.pdgMCTruth() == kProtonBar) { + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), aod::pidtpc_tiny::binning::unPackInTable(part.tpcNSigmaStorePr()), aod::pidtof_tiny::binning::unPackInTable(part.tofNSigmaStorePr()), (part.pidCut() & 512u) != 0)) + continue; + } else { + if (!isNSigmaCombinedBitmask(part.p(), part)) + continue; + } registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); } @@ -1444,7 +1724,17 @@ struct FemtoUniversePairTaskTrackV0Extended { } } + void processMCReco(FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMCReco(parts, mcparts); + } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processMCReco, "Process MC reco data", false); + + void processMCRecoBitmask(FemtoBasicParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMCReco(parts, mcparts); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processMCRecoBitmask, "Process MC reco data using bitmask for PID", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx index afee000d7d6..cd31dc73b55 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx @@ -111,6 +111,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { Configurable confPDGCodeV0{"confPDGCodeV0", 3122, "V0 -- PDG code"}; Configurable confPDGCodePosChild{"confPDGCodePosChild", 2212, "Positive Child -- PDG code"}; Configurable confPDGCodeNegChild{"confPDGCodeNegChild", 211, "Negative Child -- PDG code"}; + Configurable confSeparateInvMassCheck{"confSeparateInvMassCheck", false, "Apply additional cut separate for mLambda and mAntiLambda"}; } V0configs; /// Partitioning for particle 2 @@ -159,12 +160,14 @@ struct FemtoUniversePairTaskTrackV0Helicity { 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 3D 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 3D plot: k* vs multiplicity vs mT (set to true in order to use)"}; - /// Helicity ranges (approximate) + /// Helicity ranges and configurables Configurable cfgProcessHel{"cfgProcessHel", true, "Process particle pairs from all helicity ranges"}; - Configurable cfgProcessHel1{"cfgProcessHel1", false, "Process particle pairs from the helicity range 1"}; // 1.0 > cosineTheta >= 0.1 + Configurable cfgProcessHel1{"cfgProcessHel1", false, "Process particle pairs from the helicity range 1"}; // 1.0 >= cosineTheta >= 0.1 Configurable cfgProcessHel2{"cfgProcessHel2", false, "Process particle pairs from the helicity range 2"}; // 0.1 > cosineTheta >= -0.1 Configurable cfgProcessHel3{"cfgProcessHel3", false, "Process particle pairs from the helicity range 3"}; // -0.1 > cosineTheta >= -0.5 Configurable cfgProcessHel4{"cfgProcessHel4", false, "Process particle pairs from the helicity range 4"}; // -0.5 > cosineTheta >= -1.0 + ConfigurableAxis confInvMassMotherpTBinsHel{"confInvMassMotherpTBinsHel", {5, 0, 5}, "pT binning in the pT vs. InvMassMother plot for helicity"}; + ConfigurableAxis confInvMassMotherBinsHel{"confInvMassMotherBinsHel", {1000, 0.8, 1.4}, "InvMassMother binning in the pT vs. InvMassMother plot for helicity"}; /// Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; @@ -218,10 +221,17 @@ struct FemtoUniversePairTaskTrackV0Helicity { } } - bool invMLambda(float invMassLambda, float invMassAntiLambda) + bool invMLambda(float invMassLambda, float invMassAntiLambda, int V0Type) { - if ((invMassLambda < V0configs.confV0InvMassLowLimit || invMassLambda > V0configs.confV0InvMassUpLimit) && (invMassAntiLambda < V0configs.confV0InvMassLowLimit || invMassAntiLambda > V0configs.confV0InvMassUpLimit)) { - return false; + if (V0configs.confSeparateInvMassCheck) { + const float pMass = V0Type ? invMassAntiLambda : invMassLambda; + if (pMass < V0configs.confV0InvMassLowLimit || pMass > V0configs.confV0InvMassUpLimit) { + return false; + } + } else { + if ((invMassLambda < V0configs.confV0InvMassLowLimit || invMassLambda > V0configs.confV0InvMassUpLimit) && (invMassAntiLambda < V0configs.confV0InvMassLowLimit || invMassAntiLambda > V0configs.confV0InvMassUpLimit)) { + return false; + } } return true; } @@ -287,6 +297,10 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.add("Theta/NegativeChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); thetaRegistry.add("Theta/NegativeChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); thetaRegistry.add("Theta/NegativeChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel1", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel2", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel3", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); + thetaRegistry.add("Theta/Mother/hInvMassMotherHel4", " ; p_{T} (GeV/#it{c}); M_{#Lambda};", kTH2F, {confInvMassMotherpTBinsHel, confInvMassMotherBinsHel}); /// 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}}}); @@ -427,7 +441,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { /// Histogramming same event for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), V0configs.confV0Type1)) continue; const auto& posChild = parts.iteratorAt(part.index() - 2); const auto& negChild = parts.iteratorAt(part.index() - 1); @@ -453,6 +467,15 @@ struct FemtoUniversePairTaskTrackV0Helicity { thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPt"), negChild.pt(), cosineTheta); thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaEta"), negChild.eta(), cosineTheta); thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPhi"), negChild.phi(), cosineTheta); + + if (cosineTheta <= 1.0 && cosineTheta >= 0.1) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel1"), part.pt(), part.mLambda()); + else if (cosineTheta < 0.1 && cosineTheta >= -0.1) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel2"), part.pt(), part.mLambda()); + else if (cosineTheta < -0.1 && cosineTheta >= -0.5) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel3"), part.pt(), part.mLambda()); + else if (cosineTheta < -0.5 && cosineTheta >= -1) + thetaRegistry.fill(HIST("Theta/Mother/hInvMassMotherHel4"), part.pt(), part.mLambda()); } for (const auto& part : groupPartsOne) { @@ -476,7 +499,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { /// Now build the combinations for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), V0configs.confV0Type1)) continue; /// PID using stored binned nsigma if (!isParticleCombined(p1, trackconfigs.confTrackChoicePartOne)) @@ -517,7 +540,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { } case 1: { - if (cosineTheta < 1.0 && cosineTheta >= 0.1) + if (cosineTheta <= 1.0 && cosineTheta >= 0.1) sameEventContHel1.setPair(p1, p2, multCol, confUse3D, weight); break; @@ -592,7 +615,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { /// Histogramming same event for (const auto& part : groupPartsTwo) { - if (!invMLambda(part.mLambda(), part.mAntiLambda())) + if (!invMLambda(part.mLambda(), part.mAntiLambda(), V0configs.confV0Type2)) continue; const auto& posChild = parts.iteratorAt(part.index() - 2); const auto& negChild = parts.iteratorAt(part.index() - 1); @@ -613,10 +636,10 @@ struct FemtoUniversePairTaskTrackV0Helicity { auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), V0configs.confV0Type2)) return; // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), V0configs.confV0Type2)) return; // track cleaning if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { @@ -773,7 +796,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), V0configs.confV0Type1)) continue; /// PID using stored binned nsigma if (!isParticleCombined(p1, trackconfigs.confTrackChoicePartOne)) @@ -815,7 +838,7 @@ struct FemtoUniversePairTaskTrackV0Helicity { } case 1: { - if (cosineTheta < 1.0 && cosineTheta >= 0.1) + if (cosineTheta <= 1.0 && cosineTheta >= 0.1) mixedEventContHel1.setPair(p1, p2, multCol, confUse3D, weight); break; @@ -907,11 +930,11 @@ struct FemtoUniversePairTaskTrackV0Helicity { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { // Lambda invariant mass cut for p1 - if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda(), V0configs.confV0Type2)) { continue; } // Lambda invariant mass cut for p2 - if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) { + if (!invMLambda(p2.mLambda(), p2.mAntiLambda(), V0configs.confV0Type2)) { continue; } diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldTrackSelection.h b/PWGCF/FemtoWorld/Core/FemtoWorldTrackSelection.h index 1853be4bd3c..22869bde36f 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldTrackSelection.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldTrackSelection.h @@ -18,14 +18,18 @@ #ifndef FEMTOWORLDTRACKSELECTION_H_ #define FEMTOWORLDTRACKSELECTION_H_ +#include "PWGCF/FemtoWorld/Core/FemtoWorldObjectSelection.h" #include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" -#include "Common/DataModel/TrackSelectionTables.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "PWGCF/FemtoWorld/Core/FemtoWorldObjectSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "ReconstructionDataFormats/PID.h" #include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" + #include #include @@ -278,7 +282,7 @@ class FemtoWorldTrackSelection : public FemtoWorldObjectSelection void FemtoWorldTrackSelection::init(HistogramRegistry* registry) diff --git a/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h b/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h index d112f11c2ab..923729d7e84 100644 --- a/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h +++ b/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h @@ -12,16 +12,19 @@ #ifndef PWGCF_FEMTOWORLD_DATAMODEL_FEMTOWORLDDERIVED_H_ #define PWGCF_FEMTOWORLD_DATAMODEL_FEMTOWORLDDERIVED_H_ -#include -#include "Framework/ASoA.h" -#include "MathUtils/Utils.h" -#include "Framework/DataTypes.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/DataTypes.h" #include "Framework/Expressions.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Centrality.h" +#include "MathUtils/Utils.h" + +#include namespace o2::aod { diff --git a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt index 4b4e045220a..90503ad0acd 100644 --- a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt @@ -53,3 +53,8 @@ o2physics_add_dpl_workflow(femto-world-efficiency-task-de SOURCES femtoWorldEfficiencyTaskDe.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-pair-lambda-antilambda + SOURCES femtoPairLambdaAntilambda.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx b/PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx new file mode 100644 index 00000000000..11c590b7002 --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/femtoPairLambdaAntilambda.cxx @@ -0,0 +1,279 @@ +// Copyright 2019-2025 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 FemtoPairLambdaAntilambda.cxx +/// \brief Tasks that computes correlation between two v0s +/// \author Anton Riedel, TU München, anton.riedel@cern.ch +/// \author Barbara Gawlik, WUT Warsaw, barbara.maria.gawlik@cern.ch + +#include "PWGCF/Femto/Core/closePairRejection.h" +#include "PWGCF/Femto/Core/collisionBuilder.h" +#include "PWGCF/Femto/Core/collisionHistManager.h" +#include "PWGCF/Femto/Core/modes.h" +#include "PWGCF/Femto/Core/pairBuilder.h" +#include "PWGCF/Femto/Core/pairHistManager.h" +#include "PWGCF/Femto/Core/particleCleaner.h" +#include "PWGCF/Femto/Core/partitions.h" +#include "PWGCF/Femto/Core/trackHistManager.h" +#include "PWGCF/Femto/Core/v0Builder.h" +#include "PWGCF/Femto/Core/v0HistManager.h" +#include "PWGCF/Femto/DataModel/FemtoTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/BinningPolicy.h" +#include "Framework/Configurable.h" +#include "Framework/Expressions.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/InitContext.h" +#include "Framework/OutputObjHeader.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +using namespace o2::analysis::femto; + +struct FemtoPairLambdaAntilambda { + + // setup tables + using FemtoCollisions = o2::soa::Join; + using FilteredFemtoCollisions = o2::soa::Filtered; + using FilteredFemtoCollision = FilteredFemtoCollisions::iterator; + + using FemtoCollisionsWithLabel = o2::soa::Join; + using FilteredFemtoCollisionsWithLabel = o2::soa::Filtered; + using FilteredFemtoCollisionWithLabel = FilteredFemtoCollisionsWithLabel::iterator; + + using FemtoTracks = o2::soa::Join; + using FemtoLambdas = o2::soa::Join; + using FemtoK0shorts = o2::soa::Join; + + using FemtoTracksWithLabel = o2::soa::Join; + using FemtoLambdasWithLabel = o2::soa::Join; + using FemtoK0shortsWithLabel = o2::soa::Join; + + o2::framework::SliceCache cache; + + // setup collisions + collisionbuilder::ConfCollisionSelection collisionSelection; + o2::framework::expressions::Filter collisionFilter = MAKE_COLLISION_FILTER(collisionSelection); + colhistmanager::ConfCollisionBinning confCollisionBinning; + + // setup for daughters + trackhistmanager::ConfV0PosDauBinning confPosDauBinning; + trackhistmanager::ConfV0NegDauBinning confNegDauBinning; + + // setup lambdas + v0builder::ConfLambdaSelection1 confLambdaSelection; + v0builder::ConfLambdaSelection2 confLambdaSelection2; + particlecleaner::ConfLambdaCleaner1 confLambdaCleaner; + v0histmanager::ConfLambdaBinning1 confLambdaBinning; + + o2::framework::Partition lambdaPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Partition lambdaPartition2 = MAKE_LAMBDA_PARTITION(confLambdaSelection2); + o2::framework::Preslice perColLambdas = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition lambdaWithLabelPartition = MAKE_LAMBDA_PARTITION(confLambdaSelection); + o2::framework::Partition lambdaWithLabelPartition2 = MAKE_LAMBDA_PARTITION(confLambdaSelection2); + o2::framework::Preslice perCollambdasWithLabel = o2::aod::femtobase::stored::fColId; + + // setup k0shorts + v0builder::ConfK0shortSelection1 confK0shortSelection; + particlecleaner::ConfK0shortCleaner1 confK0shortCleaner; + v0histmanager::ConfK0shortBinning1 confK0shortBinning; + + o2::framework::Partition k0shortPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColk0shorts = o2::aod::femtobase::stored::fColId; + + o2::framework::Partition k0shortWithLabelPartition = MAKE_K0SHORT_PARTITION(confK0shortSelection); + o2::framework::Preslice perColk0shortsWithLabel = o2::aod::femtobase::stored::fColId; + + // setup pairs + pairhistmanager::ConfPairBinning confPairBinning; + pairhistmanager::ConfPairCuts confPairCuts; + + pairbuilder::PairV0V0Builder< + v0histmanager::PrefixLambda1, + trackhistmanager::PrefixV01PosDaughter, + trackhistmanager::PrefixV01NegDaughter, + v0histmanager::PrefixLambda2, + trackhistmanager::PrefixV02PosDaughter, + trackhistmanager::PrefixV02NegDaughter, + pairhistmanager::PrefixV0V0Se, + pairhistmanager::PrefixV0V0Me, + closepairrejection::PrefixV0V0PosSe, + closepairrejection::PrefixV0V0NegSe, + closepairrejection::PrefixV0V0PosMe, + closepairrejection::PrefixV0V0NegMe, + modes::V0::kLambda, + modes::V0::kLambda> + pairLambdaLambdaBuilder; + + pairbuilder::PairV0V0Builder< + v0histmanager::PrefixK0short1, + trackhistmanager::PrefixV01PosDaughter, + trackhistmanager::PrefixV01NegDaughter, + v0histmanager::PrefixK0short2, + trackhistmanager::PrefixV02PosDaughter, + trackhistmanager::PrefixV02NegDaughter, + pairhistmanager::PrefixV0V0Se, + pairhistmanager::PrefixV0V0Me, + closepairrejection::PrefixV0V0PosSe, + closepairrejection::PrefixV0V0NegSe, + closepairrejection::PrefixV0V0PosMe, + closepairrejection::PrefixV0V0NegMe, + modes::V0::kK0short, + modes::V0::kK0short> + pairK0shortK0shortBuilder; + + // setup mixing + std::vector defaultVtxBins{10, -10, 10}; + std::vector defaultMultBins{50, 0, 200}; + std::vector defaultCentBins{10, 0, 100}; + o2::framework::ColumnBinningPolicy mixBinsVtxMult{{defaultVtxBins, defaultMultBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxCent{{defaultVtxBins, defaultCentBins}, true}; + o2::framework::ColumnBinningPolicy mixBinsVtxMultCent{{defaultVtxBins, defaultMultBins, defaultCentBins}, true}; + pairhistmanager::ConfMixing confMixing; + + o2::framework::HistogramRegistry hRegistry{"FemtoV0V0", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject}; + + // setup cpr + closepairrejection::ConfCprV0DaugherV0DaughterPos confCprPos; + closepairrejection::ConfCprV0DaugherV0DaughterNeg confCprNeg; + + void init(o2::framework::InitContext&) + { + + // TODO: implement lambda-k0short + bool processData = doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaSameEvent || doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortSameEvent; + bool processMc = doprocessLambdaLambdaSameEventMc || doprocessLambdaLambdaSameEventMc || doprocessK0shortK0shortSameEventMc || doprocessK0shortK0shortSameEventMc; + + if (processData && processMc) { + LOG(fatal) << "Both data and mc processing is enabled. Breaking..."; + } + + bool processLambdaLambda = doprocessLambdaLambdaSameEvent || doprocessLambdaLambdaMixedEvent || doprocessLambdaLambdaSameEventMc || doprocessLambdaLambdaMixedEventMc; + bool processK0shortK0short = doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent || doprocessK0shortK0shortSameEventMc || doprocessK0shortK0shortMixedEventMc; + + if (processLambdaLambda && processK0shortK0short) { + LOG(fatal) << "Both lambda-lambda and k0short-k0short processing is enabled. Breaking..."; + } + + // setup columnpolicy for binning + // default values are used during instantiation, so we need to explicity update them here + mixBinsVtxMult = {{confMixing.vtxBins, confMixing.multBins.value}, true}; + mixBinsVtxCent = {{confMixing.vtxBins.value, confMixing.centBins.value}, true}; + mixBinsVtxMultCent = {{confMixing.vtxBins.value, confMixing.multBins.value, confMixing.centBins.value}, true}; + + // setup histograms + std::map> colHistSpec; + std::map> trackHistSpec; + std::map> posDauSpec; + std::map> negDauSpec; + std::map> lambdaHistSpec; + std::map> k0shortHistSpec; + std::map> pairV0V0HistSpec; + std::map> cprHistSpecPos = closepairrejection::makeCprHistSpecMap(confCprPos); + std::map> cprHistSpecNeg = closepairrejection::makeCprHistSpecMap(confCprNeg); + + if (processData) { + colHistSpec = colhistmanager::makeColHistSpecMap(confCollisionBinning); + posDauSpec = trackhistmanager::makeTrackHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackHistSpecMap(confNegDauBinning); + if (processLambdaLambda) { + lambdaHistSpec = v0histmanager::makeV0HistSpecMap(confLambdaBinning); + pairV0V0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairLambdaLambdaBuilder.init(&hRegistry, confCollisionBinning, confLambdaSelection, confLambdaSelection2, confLambdaCleaner, confLambdaCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + + // setup for k0short + if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { + k0shortHistSpec = v0histmanager::makeV0HistSpecMap(confK0shortBinning); + pairV0V0HistSpec = pairhistmanager::makePairHistSpecMap(confPairBinning); + pairK0shortK0shortBuilder.init(&hRegistry, confCollisionBinning, confK0shortSelection, confK0shortSelection, confK0shortCleaner, confK0shortCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + } else { + colHistSpec = colhistmanager::makeColMcHistSpecMap(confCollisionBinning); + posDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confPosDauBinning); + negDauSpec = trackhistmanager::makeTrackMcHistSpecMap(confNegDauBinning); + if (processLambdaLambda) { + lambdaHistSpec = v0histmanager::makeV0McHistSpecMap(confLambdaBinning); + pairV0V0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairLambdaLambdaBuilder.init(&hRegistry, confCollisionBinning, confLambdaSelection, confLambdaSelection2, confLambdaCleaner, confLambdaCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, lambdaHistSpec, lambdaHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + + // setup for k0short + if (doprocessK0shortK0shortSameEvent || doprocessK0shortK0shortMixedEvent) { + k0shortHistSpec = v0histmanager::makeV0McHistSpecMap(confK0shortBinning); + pairV0V0HistSpec = pairhistmanager::makePairMcHistSpecMap(confPairBinning); + pairK0shortK0shortBuilder.init(&hRegistry, confCollisionBinning, confK0shortSelection, confK0shortSelection, confK0shortCleaner, confK0shortCleaner, confCprPos, confCprNeg, confMixing, confPairBinning, confPairCuts, colHistSpec, k0shortHistSpec, k0shortHistSpec, posDauSpec, negDauSpec, pairV0V0HistSpec, cprHistSpecPos, cprHistSpecNeg); + } + } + }; + + void processLambdaLambdaSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoLambdas const& lambdas) + { + pairLambdaLambdaBuilder.processSameEvent(col, tracks, lambdas, lambdaPartition, lambdaPartition2, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaSameEvent, "Enable processing same event processing for lambda-lambda", true); + + void processLambdaLambdaSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& lambdas, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairLambdaLambdaBuilder.processSameEvent(col, mcCols, tracks, lambdas, lambdaWithLabelPartition, lambdaWithLabelPartition2, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaSameEventMc, "Enable processing same event processing for lambda-lambda with mc information", false); + + void processLambdaLambdaMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoLambdas const& lambdas) + { + pairLambdaLambdaBuilder.processMixedEvent(cols, tracks, lambdas, lambdaPartition, lambdaPartition2, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaMixedEvent, "Enable processing mixed event processing for lambda-lambda", true); + + void processLambdaLambdaMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoLambdasWithLabel const& /*lambdas*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairLambdaLambdaBuilder.processMixedEvent(cols, mcCols, tracks, lambdaWithLabelPartition, lambdaWithLabelPartition2, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processLambdaLambdaMixedEventMc, "Enable processing mixed event processing for lambda-lambda with mc information", false); + + void processK0shortK0shortSameEvent(FilteredFemtoCollision const& col, FemtoTracks const& tracks, FemtoK0shorts const& k0shorts) + { + pairK0shortK0shortBuilder.processSameEvent(col, tracks, k0shorts, k0shortPartition, k0shortPartition, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortSameEvent, "Enable processing same event processing for k0short-k0short", false); + + void processK0shortK0shortSameEventMc(FilteredFemtoCollisionWithLabel const& col, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& k0shorts, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairK0shortK0shortBuilder.processSameEvent(col, mcCols, tracks, k0shorts, k0shortWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortSameEventMc, "Enable processing same event processing for k0short-k0short with mc information", false); + + void processK0shortK0shortMixedEvent(FilteredFemtoCollisions const& cols, FemtoTracks const& tracks, FemtoK0shorts const& k0shorts) + { + pairK0shortK0shortBuilder.processMixedEvent(cols, tracks, k0shorts, k0shortPartition, k0shortPartition, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortMixedEvent, "Enable processing mixed event processing for k0short-k0short", false); + + void processK0shortK0shortMixedEventMc(FilteredFemtoCollisionsWithLabel const& cols, o2::aod::FMcCols const& mcCols, FemtoTracksWithLabel const& tracks, FemtoK0shortsWithLabel const& /*k0shorts*/, o2::aod::FMcParticles const& mcParticles, o2::aod::FMcMothers const& mcMothers, o2::aod::FMcPartMoths const& mcPartonicMothers) + { + pairK0shortK0shortBuilder.processMixedEvent(cols, mcCols, tracks, k0shortWithLabelPartition, k0shortWithLabelPartition, mcParticles, mcMothers, mcPartonicMothers, cache, mixBinsVtxMult, mixBinsVtxCent, mixBinsVtxMultCent); + } + PROCESS_SWITCH(FemtoPairLambdaAntilambda, processK0shortK0shortMixedEventMc, "Enable processing mixed event processing for k0short-k0short with mc information", false); +}; + +o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) +{ + o2::framework::WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/Flow/TableProducer/zdcQVectors.cxx b/PWGCF/Flow/TableProducer/zdcQVectors.cxx index 9e902690923..8dd974cf75f 100644 --- a/PWGCF/Flow/TableProducer/zdcQVectors.cxx +++ b/PWGCF/Flow/TableProducer/zdcQVectors.cxx @@ -99,6 +99,7 @@ std::vector v(3, 0); // vx, vy, vz bool isSelected = true; std::vector cents; // centrality estimaters uint64_t timestamp = 0; +double rsTimestamp = 0; } // namespace o2::analysis::qvectortask @@ -156,6 +157,7 @@ struct ZdcQVectors { O2_DEFINE_CONFIGURABLE(cfgFillHistRegistry, bool, true, "Fill common registry with histograms"); O2_DEFINE_CONFIGURABLE(cfgFillCutAnalysis, bool, true, "Fill cut analysis with histograms"); O2_DEFINE_CONFIGURABLE(cfgFillNothing, bool, false, "Disable ALL Histograms -> ONLY use to reduce memory"); + O2_DEFINE_CONFIGURABLE(cfgNoGain, bool, false, "Do not apply gain correction to ZDC energy calibration"); O2_DEFINE_CONFIGURABLE(cfgCCDBdir_Shift, std::string, "Users/c/ckoster/ZDC/LHC23_PbPb_pass5/Shift", "CCDB directory for Shift ZDC"); @@ -228,7 +230,9 @@ struct ZdcQVectors { std::vector capCOORDS = {"X", "Y"}; AxisSpec axisPsiA = {100, -PI, PI, "#Psi_{1} ZNA"}; + AxisSpec axisPsiAShifted = {100, -PI, PI, "#Psi_{1} ZNA Shifted"}; AxisSpec axisPsiC = {100, -PI, PI, "#Psi_{1} ZNC"}; + AxisSpec axisPsiCShifted = {100, -PI, PI, "#Psi_{1} ZNC Shifted"}; // This is the only histogram that is AL~WA~YS filled. registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); @@ -304,12 +308,16 @@ struct ZdcQVectors { registry.add("QA/ZNA_Energy", "ZNA_Energy", kTProfile, {{8, 0, 8}}); registry.add("QA/ZNC_Energy", "ZNC_Energy", kTProfile, {{8, 0, 8}}); - registry.add("QA/psiZDCA", "psiZDCA", kTH2D, {axisPsiA, {100, 0, 100}}); - registry.add("QA/psiZDCA_shift", "psiZDCA_shift", kTH2D, {axisPsiA, {100, 0, 100}}); - registry.add("QA/psiZDCC", "psiZDCC", kTH2D, {axisPsiC, {100, 0, 100}}); - registry.add("QA/psiZDCC_shift", "psiZDCC_shift", kTH2D, {axisPsiC, {100, 0, 100}}); - registry.add("QA/psiZDCAC", "psiZDCAC", kTH2D, {axisPsiA, axisPsiC}); - registry.add("QA/psiZDCAC_shift", "psiZDCAC_shift", kTH2D, {axisPsiA, axisPsiC}); + registry.add("QA/shift/psiZDCA", "psiZDCA", kTH2D, {axisPsiA, {100, 0, 100}}); + registry.add("QA/shift/psiZDCA_shift", "psiZDCA_shift", kTH2D, {axisPsiA, {100, 0, 100}}); + registry.add("QA/shift/psiZDCC", "psiZDCC", kTH2D, {axisPsiC, {100, 0, 100}}); + registry.add("QA/shift/psiZDCC_shift", "psiZDCC_shift", kTH2D, {axisPsiC, {100, 0, 100}}); + registry.add("QA/shift/psiZDCAC", "psiZDCAC", kTH2D, {axisPsiA, axisPsiC}); + registry.add("QA/shift/psiZDCAC_shift", "psiZDCAC_shift", kTH2D, {axisPsiA, axisPsiC}); + + registry.add("QA/shift/DeltaPsiZDCA", "DeltaPsiZDCA", kTH2D, {axisPsiAShifted, axisPsiA}); + registry.add("QA/shift/DeltaPsiZDCC", "DeltaPsiZDCC", kTH2D, {axisPsiCShifted, axisPsiC}); + registry.add("QA/shift/DeltaPsiZDCAC", "DeltaPsiZDCAC", kTH2D, {axisPsiA, axisPsiC}); registry.add("QA/before/ZNA_pmC", "ZNA_pmC", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNA_pm1", "ZNA_pm1", kTProfile, {{1, 0, 1.}}); @@ -528,7 +536,7 @@ struct ZdcQVectors { } template - inline void fillCommonRegistry(double qxa, double qya, double qxc, double qyc, std::vector v, double centrality) + inline void fillCommonRegistry(double qxa, double qya, double qxc, double qyc, std::vector v, double centrality, double rsTimestamp) { // loop for filling multiple histograms with different naming patterns // Always fill the uncentered "raw" Q-vector histos! @@ -579,15 +587,15 @@ struct ZdcQVectors { registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_QXC_vs_vz"), v[2], qya * qxc); registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_QYC_vs_vz"), v[2], qxa * qyc); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qxa); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qya); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXC_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qxc); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYC_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qyc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_vs_timestamp"), rsTimestamp, qxa); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_vs_timestamp"), rsTimestamp, qya); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXC_vs_timestamp"), rsTimestamp, qxc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYC_vs_timestamp"), rsTimestamp, qyc); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_QXC_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qxa * qxc); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_QYC_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qya * qyc); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_QXC_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qya * qxc); - registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_QYC_vs_timestamp"), rescaleTimestamp(timestamp, runnumber), qxa * qyc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_QXC_vs_timestamp"), rsTimestamp, qxa * qxc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_QYC_vs_timestamp"), rsTimestamp, qya * qyc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_QXC_vs_timestamp"), rsTimestamp, qya * qxc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_QYC_vs_timestamp"), rsTimestamp, qxa * qyc); registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNA_Qx_vs_Centrality"), centrality, qxa); registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNA_Qy_vs_Centrality"), centrality, qya); @@ -679,7 +687,7 @@ struct ZdcQVectors { bin = h->GetXaxis()->FindBin(TString::Format("%i", runnumber)); } if (name.Contains("timestamp")) { - bin = h->GetXaxis()->FindBin(rescaleTimestamp(timestamp, runnumber)); + bin = h->GetXaxis()->FindBin(rsTimestamp); } calibConstant = h->GetBinContent(bin); } else if (hist->InheritsFrom("THnSparse")) { @@ -724,7 +732,6 @@ struct ZdcQVectors { std::vector centralities; auto cent = collision.centFT0C(); - centrality = cent; centralities.push_back(collision.centFT0C()); @@ -751,6 +758,7 @@ struct ZdcQVectors { v = {collision.posX(), collision.posY(), collision.posZ()}; cents = centralities; + centrality = cent; const auto& foundBC = collision.foundBC_as(); runnumber = foundBC.runNumber(); @@ -761,6 +769,7 @@ struct ZdcQVectors { registry.fill(HIST("hEventCount"), evSel_FilteredEvent); timestamp = foundBC.timestamp(); + rsTimestamp = rescaleTimestamp(timestamp, runnumber); if (!foundBC.has_zdc()) { isSelected = false; @@ -992,6 +1001,22 @@ struct ZdcQVectors { } } + if (cfgFillHistRegistry && !cfgFillNothing) { + registry.get(HIST("QA/before/ZNA_Qx"))->Fill(Form("%d", runnumber), q[0]); + registry.get(HIST("QA/before/ZNA_Qy"))->Fill(Form("%d", runnumber), q[1]); + registry.get(HIST("QA/before/ZNC_Qx"))->Fill(Form("%d", runnumber), q[2]); + registry.get(HIST("QA/before/ZNC_Qy"))->Fill(Form("%d", runnumber), q[3]); + + registry.get(HIST("QA/before/ZNA_Qx_noEq"))->Fill(Form("%d", runnumber), qNoEq[0]); + registry.get(HIST("QA/before/ZNA_Qy_noEq"))->Fill(Form("%d", runnumber), qNoEq[1]); + registry.get(HIST("QA/before/ZNC_Qx_noEq"))->Fill(Form("%d", runnumber), qNoEq[2]); + registry.get(HIST("QA/before/ZNC_Qy_noEq"))->Fill(Form("%d", runnumber), qNoEq[3]); + } + + if (cfgNoGain) { + q = qNoEq; + } + if (cal.calibfilesLoaded[1]) { v[0] = v[0] - getCorrection(vnames[0].Data()); v[1] = v[1] - getCorrection(vnames[1].Data()); @@ -1008,21 +1033,9 @@ struct ZdcQVectors { std::vector qRec(q); - if (cfgFillHistRegistry && !cfgFillNothing) { - registry.get(HIST("QA/before/ZNA_Qx"))->Fill(Form("%d", runnumber), q[0]); - registry.get(HIST("QA/before/ZNA_Qy"))->Fill(Form("%d", runnumber), q[1]); - registry.get(HIST("QA/before/ZNC_Qx"))->Fill(Form("%d", runnumber), q[2]); - registry.get(HIST("QA/before/ZNC_Qy"))->Fill(Form("%d", runnumber), q[3]); - - registry.get(HIST("QA/before/ZNA_Qx_noEq"))->Fill(Form("%d", runnumber), qNoEq[0]); - registry.get(HIST("QA/before/ZNA_Qy_noEq"))->Fill(Form("%d", runnumber), qNoEq[1]); - registry.get(HIST("QA/before/ZNC_Qx_noEq"))->Fill(Form("%d", runnumber), qNoEq[2]); - registry.get(HIST("QA/before/ZNC_Qy_noEq"))->Fill(Form("%d", runnumber), qNoEq[3]); - } - if (cal.atIteration == 0) { if (isSelected && cfgFillHistRegistry) - fillCommonRegistry(q[0], q[1], q[2], q[3], v, centrality); + fillCommonRegistry(q[0], q[1], q[2], q[3], v, centrality, rsTimestamp); spTableZDC(runnumber, cents, v, foundBC.timestamp(), q[0], q[1], q[2], q[3], isSelected, eventSelectionFlags); counter++; @@ -1030,7 +1043,7 @@ struct ZdcQVectors { return; } else { if (cfgFillHistRegistry) - fillCommonRegistry(q[0], q[1], q[2], q[3], v, centrality); + fillCommonRegistry(q[0], q[1], q[2], q[3], v, centrality, rsTimestamp); // vector of 4 std::vector corrQxA; @@ -1086,15 +1099,6 @@ struct ZdcQVectors { } } - if (isSelected && cfgFillHistRegistry && !cfgFillNothing) { - fillCommonRegistry(qRec[0], qRec[1], qRec[2], qRec[3], v, centrality); - registry.fill(HIST("QA/centrality_after"), centrality); - registry.get(HIST("QA/after/ZNA_Qx"))->Fill(Form("%d", runnumber), qRec[0]); - registry.get(HIST("QA/after/ZNA_Qy"))->Fill(Form("%d", runnumber), qRec[1]); - registry.get(HIST("QA/after/ZNC_Qx"))->Fill(Form("%d", runnumber), qRec[2]); - registry.get(HIST("QA/after/ZNC_Qy"))->Fill(Form("%d", runnumber), qRec[3]); - } - // do shift for psi. double psiZDCA = 1.0 * std::atan2(qRec[1], qRec[0]); double psiZDCC = 1.0 * std::atan2(qRec[3], qRec[2]); @@ -1164,12 +1168,15 @@ struct ZdcQVectors { psiZDCAshift = std::atan2(std::sin(psiZDCAshift), std::cos(psiZDCAshift)); if (cfgFillHistRegistry && !cfgFillNothing) { - registry.fill(HIST("QA/psiZDCA"), psiZDCA, centrality); - registry.fill(HIST("QA/psiZDCC"), psiZDCC, centrality); - registry.fill(HIST("QA/psiZDCAC"), psiZDCA, psiZDCC); - registry.fill(HIST("QA/psiZDCA_shift"), psiZDCAshift, centrality); - registry.fill(HIST("QA/psiZDCC_shift"), psiZDCCshift, centrality); - registry.fill(HIST("QA/psiZDCAC_shift"), psiZDCAshift, psiZDCCshift); + registry.fill(HIST("QA/shift/psiZDCA"), psiZDCA, centrality); + registry.fill(HIST("QA/shift/psiZDCC"), psiZDCC, centrality); + registry.fill(HIST("QA/shift/psiZDCAC"), psiZDCA, psiZDCC); + registry.fill(HIST("QA/shift/psiZDCA_shift"), psiZDCAshift, centrality); + registry.fill(HIST("QA/shift/psiZDCC_shift"), psiZDCCshift, centrality); + registry.fill(HIST("QA/shift/psiZDCAC_shift"), psiZDCAshift, psiZDCCshift); + registry.fill(HIST("QA/shift/DeltaPsiZDCA"), psiZDCAshift, psiZDCA); + registry.fill(HIST("QA/shift/DeltaPsiZDCC"), psiZDCCshift, psiZDCC); + registry.fill(HIST("QA/shift/DeltaPsiZDCAC"), psiZDCAshift - psiZDCA, psiZDCCshift - psiZDCC); } double qXaShift = std::hypot(qRec[1], qRec[0]) * std::cos(psiZDCAshift); @@ -1177,6 +1184,15 @@ struct ZdcQVectors { double qXcShift = std::hypot(qRec[2], qRec[3]) * std::cos(psiZDCCshift); double qYcShift = std::hypot(qRec[2], qRec[3]) * std::sin(psiZDCCshift); + if (isSelected && cfgFillHistRegistry && !cfgFillNothing) { + fillCommonRegistry(qRec[0], qRec[1], qRec[2], qRec[3], v, centrality, rsTimestamp); + registry.fill(HIST("QA/centrality_after"), centrality); + registry.get(HIST("QA/after/ZNA_Qx"))->Fill(Form("%d", runnumber), qXaShift); + registry.get(HIST("QA/after/ZNA_Qy"))->Fill(Form("%d", runnumber), qYaShift); + registry.get(HIST("QA/after/ZNC_Qx"))->Fill(Form("%d", runnumber), qXcShift); + registry.get(HIST("QA/after/ZNC_Qy"))->Fill(Form("%d", runnumber), qYcShift); + } + spTableZDC(runnumber, cents, v, foundBC.timestamp(), qXaShift, qYaShift, qXcShift, qYcShift, isSelected, eventSelectionFlags); qRec.clear(); diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index b1300623c73..cb080629efb 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -64,6 +64,11 @@ o2physics_add_dpl_workflow(flow-pid-cme PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(flow-zdc-energy + SOURCES flowZdcEnergy.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(flow-sp SOURCES flowSP.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore diff --git a/PWGCF/Flow/Tasks/flowEventPlane.cxx b/PWGCF/Flow/Tasks/flowEventPlane.cxx index 8287f3df49b..510ba5c5b89 100644 --- a/PWGCF/Flow/Tasks/flowEventPlane.cxx +++ b/PWGCF/Flow/Tasks/flowEventPlane.cxx @@ -13,6 +13,8 @@ /// \brief Flow calculation using event plane. /// \author Yash Patley +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" @@ -56,16 +58,18 @@ DECLARE_SOA_TABLE(ColSPExt, "AOD", "COLSPEXT", o2::soa::Index<>, colspext::Xc, colspext::Yc); -namespace trackidext +namespace tracksid { +DECLARE_SOA_COLUMN(IsCharged, isCharged, bool); DECLARE_SOA_COLUMN(IsPion, isPion, bool); DECLARE_SOA_COLUMN(IsKaon, isKaon, bool); DECLARE_SOA_COLUMN(IsProton, isProton, bool); -} // namespace trackidext -DECLARE_SOA_TABLE(TrackIdExt, "AOD", "TRACKIDEXT", o2::soa::Index<>, - trackidext::IsPion, - trackidext::IsKaon, - trackidext::IsProton); +} // namespace tracksid +DECLARE_SOA_TABLE(TracksId, "AOD", "TRACKSID", o2::soa::Index<>, + tracksid::IsCharged, + tracksid::IsPion, + tracksid::IsKaon, + tracksid::IsProton); } // namespace o2::aod enum GainClibCorr { @@ -102,9 +106,21 @@ enum ParticleType { kNPart }; +enum ResoType { + kPhi0 = 0, + kKStar +}; + +enum V0Type { + kK0S = 0, + kLambda, + kAntiLambda +}; + struct SpectatorPlaneTableProducer { // Table producer Produces colSPExtTable; + Produces tracksIdTable; // Configurables // Collisions @@ -147,6 +163,26 @@ struct SpectatorPlaneTableProducer { Configurable cCcdbUrl{"cCcdbUrl", "http://ccdb-test.cern.ch:8080", "url of ccdb"}; Configurable cCcdbPath{"cCcdbPath", "Users/y/ypatley/DFOO", "Path for ccdb-object"}; + // Tracks + Configurable cTrackMinPt{"cTrackMinPt", 0.1, "p_{T} minimum"}; + Configurable cTrackMaxPt{"cTrackMaxPt", 10.0, "p_{T} maximum"}; + Configurable cNEtaBins{"cNEtaBins", 7, "# of eta bins"}; + Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; + Configurable cTrackGlobal{"cTrackGlobal", true, "Global Track"}; + Configurable cTrackDcaXYCut{"cTrackDcaXYCut", 0.1, "DcaXY Cut"}; + Configurable cTrackDcaZCut{"cTrackDcaZCut", 1., "DcaXY Cut"}; + + // Track PID + Configurable cTpcElRejCutMin{"cTpcElRejCutMin", -3., "Electron Rejection Cut Minimum"}; + Configurable cTpcElRejCutMax{"cTpcElRejCutMax", 5., "Electron Rejection Cut Maximum"}; + Configurable cTpcNSigmaCut{"cTpcNSigmaCut", 2, "TPC NSigma Cut"}; + Configurable cTpcRejCut{"cTpcRejCut", 3, "TPC Rej Cut"}; + Configurable cTofNSigmaCut{"cTofNSigmaCut", 2, "TOF NSigma Cut"}; + Configurable cTofRejCut{"cTofRejCut", 3, "TOF Rej Cut"}; + Configurable cPionPtCut{"cPionPtCut", 0.6, "Pion TPC pT cutoff"}; + Configurable cKaonPtCut{"cKaonPtCut", 0.6, "Kaon TPC pT cutoff"}; + Configurable cProtonPtCut{"cProtonPtCut", 1.1, "Proton TPC pT cutoff"}; + // Initialize CCDB Service Service ccdbService; @@ -260,6 +296,9 @@ struct SpectatorPlaneTableProducer { histos.add("Checks/hYaYc", "Y^{A}_{1}Y^{C}_{1}", kTProfile, {axisCent}); histos.add("Checks/hXaYc", "X^{A}_{1}Y^{C}_{1}", kTProfile, {axisCent}); histos.add("Checks/hYaXc", "Y^{A}_{1}X^{C}_{1}", kTProfile, {axisCent}); + + // Directed flow QXY vector + histos.add("DF/hQaQc", "X^{A}_{1}X^{C}_{1} + Y^{A}_{1}Y^{C}_{1}", kTProfile, {axisCent}); } template @@ -568,10 +607,73 @@ struct SpectatorPlaneTableProducer { return true; } + // Track Selection + template + bool selectTrack(T const& track) + { + if (track.pt() <= cTrackMinPt || track.pt() >= cTrackMaxPt || std::abs(track.eta()) >= cTrackEtaCut) { + return false; + } + + if (cTrackGlobal && !track.isGlobalTrackWoDCA()) { + return false; + } + + if (std::abs(track.dcaXY()) >= cTrackDcaXYCut || std::abs(track.dcaZ()) >= cTrackDcaZCut) { + return false; + } + + return true; + } + + template + bool checkTrackPid(float const& ptCut, float const& trackPt, std::vector const& vTpcNsig, std::vector const& vTofNsig, bool const& tofFlag) + { + bool retFlag = false; + if (tofFlag) { + if (vTofNsig[part1] < cTofNSigmaCut && vTofNsig[part2] > cTofRejCut && vTofNsig[part3] > cTofRejCut && vTpcNsig[part1] < cTpcNSigmaCut) { + retFlag = true; + } + } else { + if (trackPt < ptCut && vTpcNsig[part1] < cTpcNSigmaCut && vTpcNsig[part2] > cTpcRejCut && vTpcNsig[part3] > cTpcRejCut) { + retFlag = true; + } + } + return retFlag; + } + + template + bool identifyTrack(T const& track) + { + // Electron rejection + if (std::abs(track.tpcNSigmaPi()) > cTpcRejCut && std::abs(track.tpcNSigmaKa()) > cTpcRejCut && std::abs(track.tpcNSigmaPr()) > cTpcRejCut && track.tpcNSigmaEl() > cTpcElRejCutMin && track.tpcNSigmaEl() < cTpcElRejCutMax) { + return false; + } + + // Pion, Kaon, Proton Identification + std::vector vPtCut = {cPionPtCut, cKaonPtCut, cProtonPtCut}; + std::vector vTpcNsig = {std::abs(track.tpcNSigmaPi()), std::abs(track.tpcNSigmaKa()), std::abs(track.tpcNSigmaPr())}; + std::vector vTofNsig = {std::abs(track.tofNSigmaPi()), std::abs(track.tofNSigmaKa()), std::abs(track.tofNSigmaPr())}; + bool retFlag = false; + + if (partType == kPi && checkTrackPid(vPtCut[kPi], track.pt(), vTpcNsig, vTofNsig, track.hasTOF())) { + retFlag = true; + } else if (partType == kKa && checkTrackPid(vPtCut[kKa], track.pt(), vTpcNsig, vTofNsig, track.hasTOF())) { + retFlag = true; + } else if (partType == kPr && checkTrackPid(vPtCut[kPr], track.pt(), vTpcNsig, vTofNsig, track.hasTOF())) { + retFlag = true; + } else { + return false; + } + + return retFlag; + } + using BCsRun3 = soa::Join; using CollisionsRun3 = soa::Join; + using Tracks = soa::Join; - void process(CollisionsRun3::iterator const& collision, BCsRun3 const&, aod::Zdcs const&) + void processSpectatorPlane(CollisionsRun3::iterator const& collision, BCsRun3 const&, aod::Zdcs const&) { // Analyze collision and get Spectator Plane Vector std::array vSP = {0., 0., 0., 0.}; @@ -593,40 +695,82 @@ struct SpectatorPlaneTableProducer { histos.fill(HIST("Checks/hYaYc"), cent, (vSP[kYa] * vSP[kYc])); histos.fill(HIST("Checks/hXaYc"), cent, (vSP[kXa] * vSP[kYc])); histos.fill(HIST("Checks/hYaXc"), cent, (vSP[kYa] * vSP[kXc])); + + // Directed flow QXY vector + float qac = (vSP[kXa] * vSP[kXc]) + (vSP[kYa] * vSP[kYc]); + histos.fill(HIST("DF/hQaQc"), cent, qac); } // Fill table colSPExtTable(colSPExtFlag, vSP[kXa], vSP[kYa], vSP[kXc], vSP[kYc]); } + + PROCESS_SWITCH(SpectatorPlaneTableProducer, processSpectatorPlane, "Spectator Plane Process", true); + + void processIdHadrons(Tracks const& tracks) + { + for (auto const& track : tracks) { + bool chargedFlag = selectTrack(track); + bool pionFlag = identifyTrack(track); + bool kaonFlag = identifyTrack(track); + bool protonFlag = identifyTrack(track); + tracksIdTable(chargedFlag, pionFlag, kaonFlag, protonFlag); + } + } + + PROCESS_SWITCH(SpectatorPlaneTableProducer, processIdHadrons, "Hadron Id Process", false); }; -struct IdHadronFlow { - // Table producer - Produces trackIdExtTable; +struct FlowEventPlane { + // Tracks + Configurable cNEtaBins{"cNEtaBins", 5, "# of eta bins"}; + + // Pi,Ka,Pr + Configurable cMinPtPi{"cMinPtPi", 0.2, "Pion min pT"}; + Configurable cMinPtKa{"cMinPtKa", 0.3, "Kaon min pT"}; + Configurable cMinPtPr{"cMinPtPr", 0.5, "Proton min pT"}; + // Resonance + Configurable cNRapBins{"cNRapBins", 5, "# of y bins"}; + Configurable cPhiInvMassBins{"cPhiInvMassBins", 500, "# of Phi mass bins"}; + Configurable cKStarInvMassBins{"cKStarInvMassBins", 200, "# of Phi mass bins"}; + Configurable cResRapCut{"cResRapCut", 0.5, "Resonance rapidity cut"}; + + // V0 // Tracks - Configurable cTrackMinPt{"cTrackMinPt", 0.1, "p_{T} minimum"}; - Configurable cTrackMaxPt{"cTrackMaxPt", 10.0, "p_{T} maximum"}; - Configurable cNEtaBins{"cNEtaBins", 7, "# of eta bins"}; + Configurable cTrackPtCut{"cTrackPtCut", 0.1, "p_{T} minimum"}; Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; - Configurable cTrackGlobal{"cTrackGlobal", true, "Global Track"}; - Configurable cTrackDcaXYCut{"cTrackDcaXYCut", 0.1, "DcaXY Cut"}; - Configurable cTrackDcaZCut{"cTrackDcaZCut", 1., "DcaXY Cut"}; - - // Track PID - Configurable cTpcNSigmaCut{"cTpcNSigmaCut", 2, "TPC NSigma Cut"}; - Configurable cTpcRejCut{"cTpcRejCut", 3, "TPC Rej Cut"}; - Configurable cTofNSigmaCut{"cTofNSigmaCut", 2, "TOF NSigma Cut"}; - Configurable cTofRejCut{"cTofRejCut", 3, "TOF Rej Cut"}; - Configurable cPionPtCut{"cPionPtCut", 0.6, "Pion TPC pT cutoff"}; - Configurable cKaonPtCut{"cKaonPtCut", 0.6, "Kaon TPC pT cutoff"}; - Configurable cProtonPtCut{"cProtonPtCut", 1.1, "Proton TPC pT cutoff"}; + Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 3.0, "TPC NSigma Selection Cut"}; + + // V0s + Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; + Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.01, "Minimum Proton DCAr to PV"}; + Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.1, "Minimum Pion DCAr to PV"}; + Configurable cDcaV0Dau{"cDcaV0Dau", 1., "DCA between V0 daughters"}; + Configurable cDcaV0ToPv{"cDcaV0ToPv", 0.1, "DCA V0 to PV"}; + Configurable cMinV0Radius{"cMinV0Radius", 0.5, "Minimum V0 radius from PV"}; + Configurable cK0ShortCTau{"cK0ShortCTau", 20.0, "Decay length cut K0Short"}; + Configurable cLambdaCTau{"cLambdaCTau", 30.0, "Decay length cut Lambda"}; + Configurable cK0ShortCosPA{"cK0ShortCosPA", 0.998, "K0Short CosPA"}; + Configurable cLambdaCosPA{"cLambdaCosPA", 0.998, "Lambda CosPA"}; + Configurable cK0SMassRej{"cK0SMassRej", 0.01, "Reject K0Short Candidates"}; + Configurable cArmPodSel{"cArmPodSel", 0.2, "Armentros-Podolanski Selection for K0S"}; + Configurable cV0RapCut{"cV0RapCut", 0.8, "V0 rap cut"}; + Configurable cK0SMinPt{"cK0SMinPt", 0.4, "K0S Min pT"}; + Configurable cK0SMaxPt{"cK0SMaxPt", 6.0, "K0S Max pT"}; + Configurable cLambdaMinPt{"cLambdaMinPt", 0.6, "Lambda Min pT"}; + Configurable cLambdaMaxPt{"cLambdaMaxPt", 6.0, "Lambda Max pT"}; // Histogram registry: an object to hold your histograms HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Global objects float cent = 0.; + std::array vSP = {0., 0., 0., 0.}; + std::map> mResoDauMass = {{kPhi0, {MassKaonCharged, MassKaonCharged}}, {kKStar, {MassPionCharged, MassKaonCharged}}}; + std::map mResoMass = {{kPhi0, MassPhi}, {kKStar, MassKaonCharged}}; + std::map mV0Ctau = {{kK0S, cK0ShortCTau}, {kLambda, cLambdaCTau}, {kAntiLambda, cLambdaCTau}}; + std::map mV0CosPA = {{kK0S, cK0ShortCosPA}, {kLambda, cLambdaCosPA}, {kAntiLambda, cLambdaCosPA}}; void init(InitContext const&) { @@ -643,238 +787,251 @@ struct IdHadronFlow { const AxisSpec axisTrackdEdx{360, 20, 200, "#frac{dE}{dx}"}; const AxisSpec axisTrackNSigma{161, -4.025, 4.025, {"n#sigma"}}; - // Create histograms - // Track QA - histos.add("TrackQA/hPtDcaXY", "DCA_{XY} vs p_{T}", kTH2F, {axisTrackPt, axisTrackDcaXY}); - histos.add("TrackQA/hPtDcaZ", "DCA_{Z} vs p_{T}", kTH2F, {axisTrackPt, axisTrackDcaZ}); - histos.add("TrackQA/hTrackTPCdEdX", "hTrackTPCdEdX", kTH2F, {axisTrackPt, axisTrackdEdx}); - - // Charged particle directed flow - histos.add("DF/hQaQc", "X^{A}_{1}X^{C}_{1} + Y^{A}_{1}Y^{C}_{1}", kTProfile, {axisCent}); - histos.add("DF/hAQu", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("DF/hCQu", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("DF/hAQuPos", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("DF/hCQuPos", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("DF/hAQuNeg", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("DF/hCQuNeg", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); - - // Identified particle - histos.add("PartId/Pion/hdEdX", "PartId/Pion/hdEdX", kTH2F, {axisTrackPt, axisTrackdEdx}); - histos.add("PartId/Pion/hTPCNSigma", "PartId/Pion/hTPCNSigma", kTH2F, {axisTrackPt, axisTrackNSigma}); - histos.add("PartId/Pion/hTOFNSigma", "PartId/Pion/hTOFNSigma", kTH2F, {axisTrackPt, axisTrackNSigma}); - histos.add("PartId/Pion/hAQuPos", "PartId/Pion/hAQuPos", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("PartId/Pion/hAQuNeg", "PartId/Pion/hAQuNeg", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("PartId/Pion/hCQuPos", "PartId/Pion/hCQuPos", kTProfile2D, {axisCent, axisTrackEta}); - histos.add("PartId/Pion/hCQuNeg", "PartId/Pion/hCQuNeg", kTProfile2D, {axisCent, axisTrackEta}); - histos.addClone("PartId/Pion/", "PartId/Kaon/"); - histos.addClone("PartId/Pion/", "PartId/Proton/"); - } - - // Track Selection - template - bool selectTrack(T const& track) - { - if (track.pt() <= cTrackMinPt || track.pt() >= cTrackMaxPt || std::abs(track.eta()) >= cTrackEtaCut) { - return false; - } - - if (cTrackGlobal && !track.isGlobalTrackWoDCA()) { - return false; - } + const AxisSpec axisTrackRap{cNRapBins, -0.5, 0.5, "y"}; + const AxisSpec axisPhiInvMass{cPhiInvMassBins, 0.99, 1.12, "M_{KK} (GeV/#it{c}^{2}"}; + const AxisSpec axisKStarInvMass{cKStarInvMassBins, 0.8, 1.2, "M_{#piK} (GeV/#it{c}^{2}"}; + const AxisSpec axisMomPID(80, 0, 4, "p_{T} (GeV/#it{c})"); + const AxisSpec axisNsigma(401, -10.025, 10.025, {"n#sigma"}); + const AxisSpec axisdEdx(360, 20, 200, "#frac{dE}{dx}"); + const AxisSpec axisTrackTofSignal(240, 0, 1.2, "#beta"); + const AxisSpec axisRadius(2000, 0, 200, "r(cm)"); + const AxisSpec axisCosPA(300, 0.97, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisDcaV0PV(1000, 0., 10., "dca (cm)"); + const AxisSpec axisDcaProngPV(5000, -50., 50., "dca (cm)"); + const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); + const AxisSpec axisCTau(2000, 0, 200, "c#tau (cm)"); + const AxisSpec axisAlpha(40, -1, 1, "#alpha"); + const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); + const AxisSpec axisLambdaInvMass(140, 1.08, 1.15, "M_{p#pi} (GeV/#it{c}^{2})"); + const AxisSpec axisK0ShortInvMass(200, 0.4, 0.6, "M_{#pi#pi} (GeV/#it{c}^{2})"); - if (std::abs(track.dcaXY()) > cTrackDcaXYCut || std::abs(track.dcaZ()) > cTrackDcaZCut) { - return false; + // Create histograms + // Charged particles + if (doprocessChargedFlow) { + histos.add("TrackQA/hPtDcaXY", "DCA_{XY} vs p_{T}", kTH2F, {axisTrackPt, axisTrackDcaXY}); + histos.add("TrackQA/hPtDcaZ", "DCA_{Z} vs p_{T}", kTH2F, {axisTrackPt, axisTrackDcaZ}); + histos.add("TrackQA/hTrackTPCdEdX", "hTrackTPCdEdX", kTH2F, {axisMomPID, axisdEdx}); + histos.add("DF/hAQu", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("DF/hCQu", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("DF/hAQuPos", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("DF/hCQuPos", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("DF/hAQuNeg", "u_{x}X^{A}_{1} + u_{y}Y^{A}_{1}", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("DF/hCQuNeg", "u_{x}X^{C}_{1} + u_{y}Y^{C}_{1}", kTProfile2D, {axisCent, axisTrackEta}); } - return true; - } - - template - bool checkTrackPid(float const& ptCut, float const& trackPt, std::vector const& vTpcNsig, std::vector const& vTofNsig, bool const& tofFlag) - { - bool retFlag = false; - if (tofFlag) { - if (vTofNsig[part1] < cTofNSigmaCut && vTofNsig[part2] > cTofRejCut && vTofNsig[part3] > cTofRejCut && vTpcNsig[part1] < cTpcNSigmaCut) { - retFlag = true; - } - } else { - if (trackPt < ptCut && vTpcNsig[part1] < cTpcNSigmaCut && vTpcNsig[part2] > cTpcRejCut && vTpcNsig[part3] > cTpcRejCut) { - retFlag = true; - } + // Identified hadrons + if (doprocessIdFlow) { + histos.add("PartId/Pion/hdEdX", "dE/dx vs pT", kTH2F, {axisMomPID, axisTrackdEdx}); + histos.add("PartId/Pion/hTOFSignal", "#beta_{TOF} vs p_{T}", kTH2F, {axisMomPID, axisTrackTofSignal}); + histos.add("PartId/Pion/hTPCNSigma", "n#sigma_{TPC} vs p_{T}", kTH2F, {axisMomPID, axisTrackNSigma}); + histos.add("PartId/Pion/hTOFNSigma", "n#sigma_{TOF} vs p_{T}", kTH2F, {axisMomPID, axisTrackNSigma}); + histos.add("PartId/Pion/hAQuPos", "PartId/Pion/hAQuPos", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("PartId/Pion/hAQuNeg", "PartId/Pion/hAQuNeg", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("PartId/Pion/hCQuPos", "PartId/Pion/hCQuPos", kTProfile2D, {axisCent, axisTrackEta}); + histos.add("PartId/Pion/hCQuNeg", "PartId/Pion/hCQuNeg", kTProfile2D, {axisCent, axisTrackEta}); + histos.addClone("PartId/Pion/", "PartId/Kaon/"); + histos.addClone("PartId/Pion/", "PartId/Proton/"); } - return retFlag; - } - - template - bool identifyTrack(T const& track) - { - std::vector vPtCut = {cPionPtCut, cKaonPtCut, cProtonPtCut}; - std::vector vTpcNsig = {std::abs(track.tpcNSigmaPi()), std::abs(track.tpcNSigmaKa()), std::abs(track.tpcNSigmaPr())}; - std::vector vTofNsig = {std::abs(track.tofNSigmaPi()), std::abs(track.tofNSigmaKa()), std::abs(track.tofNSigmaPr())}; - bool retFlag = false; - if (partType == kPi && checkTrackPid(vPtCut[kPi], track.pt(), vTpcNsig, vTofNsig, track.hasTOF())) { - retFlag = true; - } else if (partType == kKa && checkTrackPid(vPtCut[kKa], track.pt(), vTpcNsig, vTofNsig, track.hasTOF())) { - retFlag = true; - } else if (partType == kPr && checkTrackPid(vPtCut[kPr], track.pt(), vTpcNsig, vTofNsig, track.hasTOF())) { - retFlag = true; - } else { - return false; + // Resonance + if (doprocessResoFlow) { + histos.add("Reso/Phi/hSigCentEtaInvMass", "hUSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/hBkgCentEtaInvMass", "hLSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Sig/hQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Sig/hQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Bkg/hQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/Phi/Bkg/hQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackEta, axisPhiInvMass}); + histos.add("Reso/KStar/hSigCentEtaInvMass", "hUSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/hBkgCentEtaInvMass", "hLSCentEtaInvMass", kTH3F, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Sig/hQuA", "hKStarQuA", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Sig/hQuC", "hKStarQuC", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Bkg/hQuA", "hKStarQuA", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); + histos.add("Reso/KStar/Bkg/hQuC", "hKStarQuC", kTProfile3D, {axisCent, axisTrackEta, axisKStarInvMass}); } - return retFlag; - } - - template - void getIdHadronFlow(float const& cent, T const& track, float const& v1a, float const& v1c) - { - static constexpr std::string_view SubDir[] = {"Pion/", "Kaon/", "Proton/"}; - float tpcNsigma = 0., tofNsigma = 0.; - if (part == kPi) { - tpcNsigma = track.tpcNSigmaPi(); - tofNsigma = track.tofNSigmaPi(); - } else if (part == kKa) { - tpcNsigma = track.tpcNSigmaKa(); - tofNsigma = track.tofNSigmaKa(); - } else if (part == kPr) { - tpcNsigma = track.tpcNSigmaPr(); - tofNsigma = track.tofNSigmaPr(); - } else { - return; - } - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hdEdX"), track.pt(), track.tpcSignal()); - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hTPCNSigma"), track.pt(), tpcNsigma); - if (track.hasTOF()) { - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hTOFNSigma"), track.pt(), tofNsigma); - } - if (track.sign() > 0) { - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hAQuPos"), cent, track.eta(), v1a); - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hCQuPos"), cent, track.eta(), v1c); - } else { - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hAQuNeg"), cent, track.eta(), v1a); - histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hCQuNeg"), cent, track.eta(), v1c); + // Lambda + if (doprocessV0Flow) { + histos.add("V0/Lambda/QA/hQtVsAlpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("V0/Lambda/QA/hDcaV0Dau", "DCA between V0 daughters", kTH1F, {axisDcaDau}); + histos.add("V0/Lambda/QA/hDcaPosToPv", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("V0/Lambda/QA/hDcaNegToPv", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("V0/Lambda/QA/hDcaV0ToPv", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); + histos.add("V0/Lambda/QA/hCosPa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); + histos.add("V0/Lambda/QA/hRxy", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); + histos.add("V0/Lambda/QA/hCTau", "V_{0} c#tau", kTH1F, {axisCTau}); + histos.add("V0/Lambda/QA/hPosdEdXVsP", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("V0/Lambda/QA/hNegdEdXVsP", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("V0/Lambda/QA/hPosNsigPrVsP", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("V0/Lambda/QA/hNegNsigPrVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("V0/Lambda/QA/hPosNsigPiVsP", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("V0/Lambda/QA/hNegNsigPiVsP", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.addClone("V0/Lambda/", "V0/K0Short/"); + histos.add("V0/Lambda/hMassVsRap", "hMassVsRap", kTH3F, {axisCent, axisLambdaInvMass, axisTrackEta}); + histos.add("V0/Lambda/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); + histos.add("V0/Lambda/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackRap, axisLambdaInvMass}); + histos.addClone("V0/Lambda/", "V0/AntiLambda/"); + histos.add("V0/K0Short/hMassVsRap", "hMassVsRap", kTH3F, {axisCent, axisK0ShortInvMass, axisTrackEta}); + histos.add("V0/K0Short/Flow/hQuA", "hQuA", kTProfile3D, {axisCent, axisTrackRap, axisK0ShortInvMass}); + histos.add("V0/K0Short/Flow/hQuC", "hQuC", kTProfile3D, {axisCent, axisTrackRap, axisK0ShortInvMass}); } } - template - void fillTrackHist(T const& track) - { - histos.fill(HIST("TrackQA/hPtDcaZ"), track.pt(), track.dcaZ()); - histos.fill(HIST("TrackQA/hPtDcaXY"), track.pt(), track.dcaXY()); - } - - using CollisionsRun3 = soa::Join; - using Tracks = soa::Join; - - void processDummy(CollisionsRun3::iterator const&) {} - - PROCESS_SWITCH(IdHadronFlow, processDummy, "Dummy process", true); - - void processIdHadronFlow(CollisionsRun3::iterator const& collision, Tracks const& tracks) + template + bool selCollision(C const& collision, std::array& v) { // Check collision if (!collision.selColFlag()) { - return; + return false; } // Set centrality cent = collision.centFT0C(); // Flow vectors - std::array vSP = {0., 0., 0., 0.}; - vSP[kXa] = collision.xa(); - vSP[kYa] = collision.ya(); - vSP[kXc] = collision.xc(); - vSP[kYc] = collision.yc(); + v[kXa] = collision.xa(); + v[kYa] = collision.ya(); + v[kXc] = collision.xc(); + v[kYc] = collision.yc(); - // Directed flow QXY vector - float qac = (vSP[kXa] * vSP[kXc]) + (vSP[kYa] * vSP[kYc]); - histos.fill(HIST("DF/hQaQc"), cent, qac); + return true; + } - // Loop over tracks + template + void getIdFlow(T const& tracks) + { float ux = 0., uy = 0., v1a = 0., v1c = 0.; + float tpcNsigma = 0., tofNsigma = 0.; for (auto const& track : tracks) { - // Select track - if (!selectTrack(track)) { - trackIdExtTable(false, false, false); - continue; + static constexpr std::string_view SubDir[] = {"Pion/", "Kaon/", "Proton/"}; + if (part == kPi && track.pt() > cMinPtPi) { + tpcNsigma = track.tpcNSigmaPi(); + tofNsigma = track.tofNSigmaPi(); + } else if (part == kKa && track.pt() > cMinPtKa) { + tpcNsigma = track.tpcNSigmaKa(); + tofNsigma = track.tofNSigmaKa(); + } else if (part == kPr && track.pt() > cMinPtPr) { + tpcNsigma = track.tpcNSigmaPr(); + tofNsigma = track.tofNSigmaPr(); + } else { + return; + } + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hdEdX"), track.pt(), track.tpcSignal()); + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hTPCNSigma"), track.pt(), tpcNsigma); + if (track.hasTOF()) { + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hTOFSignal"), track.pt(), track.beta()); + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hTOFNSigma"), track.pt(), tofNsigma); } - // Fill track QA - fillTrackHist(track); - - // Get directed flow + // Directed flow ux = std::cos(track.phi()); uy = std::sin(track.phi()); v1a = ux * vSP[kXa] + uy * vSP[kYa]; v1c = ux * vSP[kXc] + uy * vSP[kYc]; - // Charged particle directed flow - histos.fill(HIST("DF/hAQu"), cent, track.eta(), v1a); - histos.fill(HIST("DF/hCQu"), cent, track.eta(), v1c); if (track.sign() > 0) { - histos.fill(HIST("DF/hAQuPos"), cent, track.eta(), v1a); - histos.fill(HIST("DF/hCQuPos"), cent, track.eta(), v1c); + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hAQuPos"), cent, track.eta(), v1a); + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hCQuPos"), cent, track.eta(), v1c); } else { - histos.fill(HIST("DF/hAQuNeg"), cent, track.eta(), v1a); - histos.fill(HIST("DF/hCQuNeg"), cent, track.eta(), v1c); + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hAQuNeg"), cent, track.eta(), v1a); + histos.fill(HIST("PartId/") + HIST(SubDir[part]) + HIST("hCQuNeg"), cent, track.eta(), v1c); } + } + } + + template + bool selV0DauTracks(V const& v0, T const& postrack, T const& negtrack) + { + // Kinematic selection + if (postrack.pt() <= cTrackPtCut || negtrack.pt() <= cTrackPtCut || std::abs(postrack.eta()) >= cTrackEtaCut || std::abs(negtrack.eta()) >= cTrackEtaCut) { + return false; + } - // Identified directed flow - if (identifyTrack(track)) { - trackIdExtTable(true, false, false); - getIdHadronFlow(cent, track, v1a, v1c); - } else if (identifyTrack(track)) { - trackIdExtTable(false, true, false); - getIdHadronFlow(cent, track, v1a, v1c); - } else if (identifyTrack(track)) { - trackIdExtTable(false, false, true); - getIdHadronFlow(cent, track, v1a, v1c); + // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda/K0Short daughters + if (part == kK0S) { + if (std::abs(v0.dcapostopv()) <= cMinDcaPionToPV || std::abs(v0.dcanegtopv()) <= cMinDcaPionToPV) { + return false; + } + } else if (part == kLambda) { + if (std::abs(v0.dcapostopv()) <= cMinDcaProtonToPV || std::abs(v0.dcanegtopv()) <= cMinDcaPionToPV) { + return false; } + } else if (part == kAntiLambda) { + if (std::abs(v0.dcapostopv()) <= cMinDcaPionToPV || std::abs(v0.dcanegtopv()) <= cMinDcaProtonToPV) { + return false; + } + } else { + return false; } - } - PROCESS_SWITCH(IdHadronFlow, processIdHadronFlow, "Identified hadron flow process", false); -}; -struct FlowEventPlane { - // Resonance - Configurable cNRapBins{"cNRapBins", 5, "# of y bins"}; - Configurable cNInvMassBins{"cNInvMassBins", 500, "# of m bins"}; - Configurable cResRapCut{"cResRapCut", 0.5, "Resonance rapidity cut"}; + // Daughter track PID [Dau1 = PosTrack, Dau2 = NegTrack] + float tpcNSigmaDau1 = 0., tpcNSigmaDau2 = 0.; + + switch (part) { + // Dau1 = Proton, Dau2 = Pion + case kLambda: + tpcNSigmaDau1 = postrack.tpcNSigmaPr(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPi(); + break; + + // Dau1 = Pion, Dau2 = Proton + case kAntiLambda: + tpcNSigmaDau1 = postrack.tpcNSigmaPi(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPr(); + break; + + // Dau1 = Pion, Dau2 = Pion + case kK0S: + tpcNSigmaDau1 = postrack.tpcNSigmaPi(); + tpcNSigmaDau2 = negtrack.tpcNSigmaPi(); + break; + } - // Histogram registry: an object to hold your histograms - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + if (std::abs(tpcNSigmaDau1) >= cTpcNsigmaCut || std::abs(tpcNSigmaDau2) >= cTpcNsigmaCut) { + return false; + } - // Global objects - float cent = 0.; + return true; + } - void init(InitContext const&) + template + void fillV0QAHist(C const& col, V const& v0, T const&) { - // Define axes - const AxisSpec axisCent{100, 0., 100, "FT0C%"}; + static constexpr std::string_view SubDir[] = {"V0/K0Short/QA/", "V0/Lambda/QA/", "V0/AntiLambda/QA/"}; - const AxisSpec axisXYac{600, -6, 6, "Q^{t}Q^{p}"}; - const AxisSpec axisV1{400, -4, 4, "v_{1}"}; - - const AxisSpec axisTrackPt{100, 0., 10., "p_{T} (GeV/#it{c})"}; - const AxisSpec axisTrackRap{cNRapBins, -0.5, 0.5, "y"}; - const AxisSpec axisInvMass{cNInvMassBins, 0.87, 1.12, "M_{KK} (GeV/#it{c}^{2}"}; + // daugthers + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); - // Create histograms - // Resonance - histos.add("Reso/Phi/hSigCentPtInvMass", "hUSCentPtInvMass", kTH3F, {axisCent, axisTrackPt, axisInvMass}); - histos.add("Reso/Phi/hBkgCentPtInvMass", "hLSCentPtInvMass", kTH3F, {axisCent, axisTrackPt, axisInvMass}); - histos.add("Reso/Phi/Sig/hPhiQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); - histos.add("Reso/Phi/Sig/hPhiQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); - histos.add("Reso/Phi/Bkg/hPhiQuA", "hPhiQuA", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); - histos.add("Reso/Phi/Bkg/hPhiQuC", "hPhiQuC", kTProfile3D, {axisCent, axisTrackRap, axisInvMass}); + // ctau + float mPDG = 0, ctau = 0; + if (part == kK0S) { + mPDG = MassKaonNeutral; + } else { + mPDG = MassLambda0; + } + ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * mPDG; + + histos.fill(HIST(SubDir[part]) + HIST("hQtVsAlpha"), v0.alpha(), v0.qtarm()); + histos.fill(HIST(SubDir[part]) + HIST("hDcaV0Dau"), v0.dcaV0daughters()); + histos.fill(HIST(SubDir[part]) + HIST("hDcaPosToPv"), v0.dcapostopv()); + histos.fill(HIST(SubDir[part]) + HIST("hDcaNegToPv"), v0.dcanegtopv()); + histos.fill(HIST(SubDir[part]) + HIST("hDcaV0ToPv"), v0.dcav0topv()); + histos.fill(HIST(SubDir[part]) + HIST("hCosPa"), v0.v0cosPA()); + histos.fill(HIST(SubDir[part]) + HIST("hRxy"), v0.v0radius()); + histos.fill(HIST(SubDir[part]) + HIST("hCTau"), ctau); + histos.fill(HIST(SubDir[part]) + HIST("hPosdEdXVsP"), postrack.tpcInnerParam(), postrack.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("hNegdEdXVsP"), negtrack.tpcInnerParam(), negtrack.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("hPosNsigPrVsP"), postrack.tpcInnerParam(), postrack.tpcNSigmaPr()); + histos.fill(HIST(SubDir[part]) + HIST("hNegNsigPrVsP"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPr()); + histos.fill(HIST(SubDir[part]) + HIST("hPosNsigPiVsP"), postrack.tpcInnerParam(), postrack.tpcNSigmaPi()); + histos.fill(HIST(SubDir[part]) + HIST("hNegNsigPiVsP"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPi()); } - template + template void getResoFlow(T const& tracks1, T const& tracks2, std::array const& vSP) { float ux = 0., uy = 0., v1a = 0., v1c = 0.; + std::array vMassDau = mResoDauMass.at(rt); for (auto const& [track1, track2] : soa::combinations(soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { // Discard same track if (track1.index() == track2.index()) { @@ -886,15 +1043,15 @@ struct FlowEventPlane { continue; } - // Apply rapidity acceptance + // Apply pseudo-rapidity acceptance std::array v = {track1.px() + track2.px(), track1.py() + track2.py(), track1.pz() + track2.pz()}; - if (RecoDecay::y(v, MassPhi) >= cResRapCut) { + if (std::abs(RecoDecay::eta(v)) >= cResRapCut) { continue; } - // Reconstruct phi meson + // Reconstruct resonance float p = RecoDecay::p((track1.px() + track2.px()), (track1.py() + track2.py()), (track1.pz() + track2.pz())); - float e = RecoDecay::e(track1.px(), track1.py(), track1.pz(), MassKaonCharged) + RecoDecay::e(track2.px(), track2.py(), track2.pz(), MassKaonCharged); + float e = RecoDecay::e(track1.px(), track1.py(), track1.pz(), vMassDau[0]) + RecoDecay::e(track2.px(), track2.py(), track2.pz(), vMassDau[1]); float m = std::sqrt(RecoDecay::m2(p, e)); // Get directed flow @@ -903,10 +1060,13 @@ struct FlowEventPlane { v1a = ux * vSP[kXa] + uy * vSP[kYa]; v1c = ux * vSP[kXc] + uy * vSP[kYc]; + // Histograms + static constexpr std::string_view SubDir[] = {"Reso/Phi/", "Reso/KStar/"}; + // Fill signal histogram - histos.fill(HIST("Reso/Phi/hSigCentPtInvMass"), cent, RecoDecay::pt(v), m); - histos.fill(HIST("Reso/Phi/Sig/hPhiQuA"), cent, RecoDecay::y(v, MassPhi), m, v1a); - histos.fill(HIST("Reso/Phi/Sig/hPhiQuC"), cent, RecoDecay::y(v, MassPhi), m, v1c); + histos.fill(HIST(SubDir[rt]) + HIST("hSigCentEtaInvMass"), cent, RecoDecay::eta(v), m); + histos.fill(HIST(SubDir[rt]) + HIST("Sig/hQuA"), cent, RecoDecay::eta(v), m, v1a); + histos.fill(HIST(SubDir[rt]) + HIST("Sig/hQuC"), cent, RecoDecay::eta(v), m, v1c); // Get background p = RecoDecay::p((track1.px() - track2.px()), (track1.py() - track2.py()), (track1.pz() - track2.pz())); @@ -920,52 +1080,151 @@ struct FlowEventPlane { v1c = ux * vSP[kXc] + uy * vSP[kYc]; // Fill bkg histogram - histos.fill(HIST("Reso/Phi/hBkgCentPtInvMass"), cent, RecoDecay::pt(v), m); - histos.fill(HIST("Reso/Phi/Bkg/hPhiQuA"), cent, RecoDecay::y(v, MassPhi), m, v1a); - histos.fill(HIST("Reso/Phi/Bkg/hPhiQuC"), cent, RecoDecay::y(v, MassPhi), m, v1c); + histos.fill(HIST(SubDir[rt]) + HIST("hBkgCentEtaInvMass"), cent, RecoDecay::eta(v), m); + histos.fill(HIST(SubDir[rt]) + HIST("Bkg/hQuA"), cent, RecoDecay::eta(v), m, v1a); + histos.fill(HIST(SubDir[rt]) + HIST("Bkg/hQuC"), cent, RecoDecay::eta(v), m, v1c); } } using CollisionsRun3 = soa::Join; - using Tracks = soa::Join; + using Tracks = soa::Join; + using TracksV0s = soa::Join; + // Partitions SliceCache cache; - Partition kaonTrackPartition = (aod::trackidext::isKaon == true); + Partition chargedTrackPartition = (aod::tracksid::isCharged == true); + Partition pionTrackPartition = (aod::tracksid::isCharged == true) && (aod::tracksid::isPion == true); + Partition kaonTrackPartition = (aod::tracksid::isCharged == true) && (aod::tracksid::isKaon == true); + Partition protonTrackPartition = (aod::tracksid::isCharged == true) && (aod::tracksid::isProton == true); void processDummy(CollisionsRun3::iterator const&) {} PROCESS_SWITCH(FlowEventPlane, processDummy, "Dummy process", true); - void processResoFlow(CollisionsRun3::iterator const& collision, Tracks const&) + void processChargedFlow(CollisionsRun3::iterator const& collision, Tracks const&) { // Check collision - if (!collision.selColFlag()) { + if (!selCollision(collision, vSP)) { return; } + // Loop over tracks + auto chargedTracks = chargedTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + float ux = 0., uy = 0., v1a = 0., v1c = 0.; + for (auto const& track : chargedTracks) { + // Fill track QA + histos.fill(HIST("TrackQA/hPtDcaZ"), track.pt(), track.dcaZ()); + histos.fill(HIST("TrackQA/hPtDcaXY"), track.pt(), track.dcaXY()); + histos.fill(HIST("TrackQA/hTrackTPCdEdX"), track.pt(), track.tpcSignal()); - // Set centrality - cent = collision.centFT0C(); + // Get directed flow + ux = std::cos(track.phi()); + uy = std::sin(track.phi()); + v1a = ux * vSP[kXa] + uy * vSP[kYa]; + v1c = ux * vSP[kXc] + uy * vSP[kYc]; - // Flow vectors - std::array vSP = {0., 0., 0., 0.}; - vSP[kXa] = collision.xa(); - vSP[kYa] = collision.ya(); - vSP[kXc] = collision.xc(); - vSP[kYc] = collision.yc(); + // Charged particle directed flow + histos.fill(HIST("DF/hAQu"), cent, track.eta(), v1a); + histos.fill(HIST("DF/hCQu"), cent, track.eta(), v1c); + if (track.sign() > 0) { + histos.fill(HIST("DF/hAQuPos"), cent, track.eta(), v1a); + histos.fill(HIST("DF/hCQuPos"), cent, track.eta(), v1c); + } else { + histos.fill(HIST("DF/hAQuNeg"), cent, track.eta(), v1a); + histos.fill(HIST("DF/hCQuNeg"), cent, track.eta(), v1c); + } + } + } + + PROCESS_SWITCH(FlowEventPlane, processChargedFlow, "Charged particle flow process", false); + + void processIdFlow(CollisionsRun3::iterator const& collision, Tracks const&) + { + if (!selCollision(collision, vSP)) { + return; + } + // Loop over tracks + auto pionTracks = pionTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto kaonTracks = kaonTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto protonTracks = protonTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + getIdFlow(pionTracks); + getIdFlow(kaonTracks); + getIdFlow(protonTracks); + } + + PROCESS_SWITCH(FlowEventPlane, processIdFlow, "Identified particle flow process", false); + + void processResoFlow(CollisionsRun3::iterator const& collision, Tracks const&) + { + if (!selCollision(collision, vSP)) { + return; + } // Track partitions + auto pionTracks = pionTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto kaonTracks = kaonTrackPartition->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); // Resonance flow - getResoFlow(kaonTracks, kaonTracks, vSP); + getResoFlow(kaonTracks, kaonTracks, vSP); + getResoFlow(pionTracks, kaonTracks, vSP); } PROCESS_SWITCH(FlowEventPlane, processResoFlow, "Resonance flow process", false); + + void processV0Flow(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, TracksV0s const& tracks) + { + if (!selCollision(collision, vSP)) { + return; + } + + // Loop over v0s + for (auto const& v0 : V0s) { + // Topological and kinematic selections + if (std::abs(v0.eta()) >= cV0RapCut || v0.dcaV0daughters() >= cDcaV0Dau || v0.dcav0topv() >= cDcaV0ToPv || v0.v0radius() <= cMinV0Radius || v0.v0Type() != cV0TypeSelection) { + continue; + } + + // Directed flow + float ux = std::cos(v0.phi()); + float uy = std::sin(v0.phi()); + float v1a = ux * vSP[kXa] + uy * vSP[kYa]; + float v1c = ux * vSP[kXc] + uy * vSP[kYc]; + + // Initialize selection objects + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + float ctauK0Short = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassKaonNeutral; + float ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda0; + + // K0Short + if (selV0DauTracks(v0, postrack, negtrack) && v0.v0cosPA() > mV0CosPA.at(kK0S) && ctauK0Short < mV0Ctau.at(kK0S) && v0.qtarm() >= cArmPodSel * std::abs(v0.alpha()) && v0.pt() >= cK0SMinPt && v0.pt() < cK0SMaxPt) { + fillV0QAHist(collision, v0, tracks); + histos.fill(HIST("V0/K0Short/hMassVsRap"), cent, v0.mK0Short(), v0.eta()); + histos.fill(HIST("V0/K0Short/Flow/hQuA"), cent, v0.eta(), v0.mK0Short(), v1a); + histos.fill(HIST("V0/K0Short/Flow/hQuC"), cent, v0.eta(), v0.mK0Short(), v1c); + } + + // Lambda + if (selV0DauTracks(v0, postrack, negtrack) && v0.v0cosPA() > mV0CosPA.at(kLambda) && ctauLambda < mV0Ctau.at(kLambda) && std::abs(v0.mK0Short() - MassK0Short) >= cK0SMassRej && v0.pt() >= cLambdaMinPt && v0.pt() < cLambdaMaxPt) { + fillV0QAHist(collision, v0, tracks); + histos.fill(HIST("V0/Lambda/hMassVsRap"), cent, v0.mLambda(), v0.eta()); + histos.fill(HIST("V0/Lambda/Flow/hQuA"), cent, v0.eta(), v0.mLambda(), v1a); + histos.fill(HIST("V0/Lambda/Flow/hQuC"), cent, v0.eta(), v0.mLambda(), v1c); + } + + // AntiLambda + if (selV0DauTracks(v0, postrack, negtrack) && v0.v0cosPA() > mV0CosPA.at(kAntiLambda) && ctauLambda < mV0Ctau.at(kAntiLambda) && std::abs(v0.mK0Short() - MassK0Short) >= cK0SMassRej && v0.pt() >= cLambdaMinPt && v0.pt() < cLambdaMaxPt) { + fillV0QAHist(collision, v0, tracks); + histos.fill(HIST("V0/AntiLambda/hMassVsRap"), cent, v0.mAntiLambda(), v0.eta()); + histos.fill(HIST("V0/AntiLambda/Flow/hQuA"), cent, v0.eta(), v0.mAntiLambda(), v1a); + histos.fill(HIST("V0/AntiLambda/Flow/hQuC"), cent, v0.eta(), v0.mAntiLambda(), v1c); + } + } + } + PROCESS_SWITCH(FlowEventPlane, processV0Flow, "Lambda flow process", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index 6711609edff..7ed06b21a6c 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -119,6 +119,8 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgcasc_v0cospa, float, 0.998f, "minimum cosine of pointing angle") O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0topv, float, 0.01f, "minimum daughter DCA to PV") O2_DEFINE_CONFIGURABLE(cfgcasc_dcabachtopv, float, 0.01f, "minimum bachelor DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcaLapitopv, float, 0.1f, "minimum pion from casc->Lambda->Pi DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcaLaprtopv, float, 0.1f, "minimum proton from casc->Lambda->Pr DCA to PV") O2_DEFINE_CONFIGURABLE(cfgcasc_dcacascdau, float, 0.3f, "maximum DCA among cascade daughters") O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0dau, float, 1.0f, "maximum DCA among V0 daughters") O2_DEFINE_CONFIGURABLE(cfgcasc_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") @@ -147,8 +149,10 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgCutPtPIDbachMin, float, 0.15f, "Minimal pT for daughter PID") O2_DEFINE_CONFIGURABLE(cfgCutPtPIDdauLaPrMin, float, 0.15f, "Minimal pT for daughter PID") O2_DEFINE_CONFIGURABLE(cfgCutPtPIDdauLaPiMin, float, 0.15f, "Minimal pT for daughter PID") + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "Minimal pT for daughter PID") // track quality selections for daughter track - O2_DEFINE_CONFIGURABLE(cfgITSNCls, int, 5, "check minimum number of ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgITSNCls, int, 3, "check minimum number of ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgChITSNCls, int, 5, "check minimum number of ITS clusters") O2_DEFINE_CONFIGURABLE(cfgTPCNCls, int, 50, "check minimum number of TPC hits") O2_DEFINE_CONFIGURABLE(cfgTPCCrossedRows, int, 70, "check minimum number of TPC crossed rows") O2_DEFINE_CONFIGURABLE(cfgCheckGlobalTrack, bool, false, "check global track") @@ -164,6 +168,7 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgDoNoCollInTimeRangeStandard, bool, true, "check kNoCollInTimeRangeStandard") O2_DEFINE_CONFIGURABLE(cfgDoIsGoodITSLayersAll, bool, true, "check kIsGoodITSLayersAll") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgDoZResAndNumContribCut, bool, true, "check kNoTimeFrameBorder") O2_DEFINE_CONFIGURABLE(cfgDoMultPVCut, bool, true, "do multNTracksPV vs cent cut") O2_DEFINE_CONFIGURABLE(cfgMultPVCut, std::vector, (std::vector{3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05}), "Used MultPVCut function parameter") O2_DEFINE_CONFIGURABLE(cfgDoV0AT0Acut, bool, true, "do V0A-T0A cut") @@ -211,11 +216,11 @@ struct FlowGfwOmegaXi { AxisSpec axisMultiplicity{{0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "Centrality (%)"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value) && (aod::track::pt > trkQualityOpts.cfgCutPtPOIMin.value) && (aod::track::pt < trkQualityOpts.cfgCutPtPOIMax.value) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value) && (aod::track::pt > trkQualityOpts.cfgCutPtPOIMin.value) && (aod::track::pt < trkQualityOpts.cfgCutPtPOIMax.value) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < trkQualityOpts.cfgCutDCAz.value); using TracksPID = soa::Join; - using AodTracks = soa::Filtered>; // tracks filter - using AodCollisions = soa::Filtered>; // collisions filter + using AodTracks = soa::Filtered>; // tracks filter + using AodCollisions = soa::Filtered>; // collisions filter using DaughterTracks = soa::Join; // Connect to ccdb @@ -363,15 +368,12 @@ struct FlowGfwOmegaXi { registry.add("hMult", "", {HistType::kTH1D, {cfgaxisNch}}); registry.add("hMultTPC", "", {HistType::kTH1D, {cfgaxisNch}}); registry.add("hCent", "", {HistType::kTH1D, {{90, 0, 90}}}); - registry.add("hCentvsNch", "", {HistType::kTH2D, {{18, 0, 90}, cfgaxisNch}}); - registry.add("MC/hCentvsNchMC", "", {HistType::kTH2D, {{18, 0, 90}, cfgaxisNch}}); - registry.add("hCentvsMultTPC", "", {HistType::kTH2D, {{18, 0, 90}, cfgaxisNch}}); - registry.add("MC/hCentvsMultTPCMC", "", {HistType::kTH2D, {{18, 0, 90}, cfgaxisNch}}); - registry.add("hNTracksPVvsCentrality", "", {HistType::kTH2D, {{5000, 0, 5000}, axisMultiplicity}}); + registry.add("hNTracksPVvsCentrality", "", {HistType::kTH2D, {{5000, 0, 5000}, {100, 0, 100}}}); + registry.add("hmultFV0AvsmultFT0A", "", {HistType::kTH2D, {{5000, 0, 5000}, {5000, 0, 5000}}}); registry.add("hPt", "", {HistType::kTH1D, {cfgaxisPt}}); + runNumbers = cfgRunNumbers; if (cfgOutputrunbyrun) { - runNumbers = cfgRunNumbers; for (const auto& runNumber : runNumbers) { if (cfgOutputQA) { std::vector> histosPhi(kCount_TH1Names); @@ -423,18 +425,35 @@ struct FlowGfwOmegaXi { // QA if (cfgOutputQA) { // V0 QA - registry.add("QAhisto/V0/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); - registry.add("QAhisto/V0/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); - registry.add("QAhisto/V0/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/V0/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/V0/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/V0/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/V0/hqaarm_podobefore", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); - registry.add("QAhisto/V0/hqaarm_podoafter", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); - registry.add("QAhisto/V0/hqadcapostoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcapostoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcanegtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcanegtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/K0s/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/K0s/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/K0s/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/K0s/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/K0s/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/K0s/hqaarm_podobefore", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); + registry.add("QAhisto/K0s/hqaarm_podoafter", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); + registry.add("QAhisto/K0s/hqadcapostoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqadcapostoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqadcanegtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hqadcanegtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/K0s/hphiposPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/K0s/hphinegPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + + registry.add("QAhisto/Lambda/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/Lambda/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/Lambda/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Lambda/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Lambda/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Lambda/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Lambda/hqadcaPrtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hqadcaPrtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hqadcaPitoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hqadcaPitoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Lambda/hphiposPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/Lambda/hphiposPr", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/Lambda/hphinegPi", "", {HistType::kTH1D, {cfgaxisPhi}}); + registry.add("QAhisto/Lambda/hphinegPr", "", {HistType::kTH1D, {cfgaxisPhi}}); // Cascade QA registry.add("QAhisto/Xi/hqaCascRadiusbefore", "", {HistType::kTH1D, {{200, -10, 10}}}); registry.add("QAhisto/Xi/hqaCascRadiusafter", "", {HistType::kTH1D, {{200, -10, 10}}}); @@ -446,10 +465,19 @@ struct FlowGfwOmegaXi { registry.add("QAhisto/Xi/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Xi/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Xi/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLaprtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLaprtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLapitoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Xi/hqadcaCascLapitoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Xi/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Xi/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Xi/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Xi/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Xi/hTOFnsigmaposPi", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Xi/hTOFnsigmaposPr", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Xi/hBachTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Xi/hLaPrTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Xi/hLaPiTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); registry.add("QAhisto/Omega/hqaCascRadiusbefore", "", {HistType::kTH1D, {{200, -10, 10}}}); registry.add("QAhisto/Omega/hqaCascRadiusafter", "", {HistType::kTH1D, {{200, -10, 10}}}); @@ -461,10 +489,19 @@ struct FlowGfwOmegaXi { registry.add("QAhisto/Omega/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Omega/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Omega/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLaprtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLaprtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLapitoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Omega/hqadcaCascLapitoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); registry.add("QAhisto/Omega/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("QAhisto/Omega/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Omega/hTOFnsigmaposPi", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Omega/hTOFnsigmaposPr", "", {HistType::kTH1D, {{1000, -100, 100}}}); + registry.add("QAhisto/Omega/hBachTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Omega/hLaPrTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); + registry.add("QAhisto/Omega/hLaPiTOFnsigmavsPt", "", {HistType::kTH2D, {{1000, -100, 100}, cfgaxisPt}}); } // cumulant of flow @@ -552,8 +589,10 @@ struct FlowGfwOmegaXi { if (cfgOutputV0) { registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassLambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassALambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassK0s", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassLambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassALambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); } // for local density correction if (cfgOutputLocDenWeights) { @@ -957,21 +996,23 @@ struct FlowGfwOmegaXi { return 0; } registry.fill(HIST("hEventCount"), 8.5); - float vtxz = -999; - if (collision.numContrib() > 1) { - vtxz = collision.posZ(); - float zRes = std::sqrt(collision.covZZ()); - double zResMin = 0.25; - int numContMax = 20; - if (zRes > zResMin && collision.numContrib() < numContMax) - vtxz = -999; - } - auto multNTracksPV = collision.multNTracksPV(); - auto occupancy = collision.trackOccupancyInTimeRange(); + float vtxz = collision.posZ(); + if (evtSeleOpts.cfgDoZResAndNumContribCut.value) { + if (collision.numContrib() > 1) { + float zRes = std::sqrt(collision.covZZ()); + double zResMin = 0.25; + int numContMax = 20; + if (zRes > zResMin && collision.numContrib() < numContMax) + vtxz = -999; + } + } if (std::fabs(vtxz) > cfgCutVertex) return false; + auto multNTracksPV = collision.multNTracksPV(); + auto occupancy = collision.trackOccupancyInTimeRange(); + registry.fill(HIST("hNTracksPVvsCentrality"), multNTracksPV, centrality); if (evtSeleOpts.cfgDoMultPVCut.value) { if (multNTracksPV < fMultPVCutLow->Eval(centrality)) @@ -987,6 +1028,7 @@ struct FlowGfwOmegaXi { registry.fill(HIST("hEventCount"), 10.5); // V0A T0A 5 sigma cut + registry.fill(HIST("hmultFV0AvsmultFT0A"), collision.multFV0A(), collision.multFT0A()); if (evtSeleOpts.cfgDoV0AT0Acut.value) { int nsigma = 5; if (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nsigma * fT0AV0ASigma->Eval(collision.multFT0A())) @@ -1005,7 +1047,7 @@ struct FlowGfwOmegaXi { return true; } - void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, soa::Join const& Cascades, aod::V0Datas const& V0s, DaughterTracks const&) + void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, soa::Join const& Cascades, soa::Join const& V0s, DaughterTracks const&) { o2::aod::ITSResponse itsResponse; int nTot = tracks.size(); @@ -1028,14 +1070,16 @@ struct FlowGfwOmegaXi { if (!eventSelected(collision, cent, interactionRate)) return; int matchedPosition = -1; - for (uint64_t idxPosition = 0; idxPosition < this->runNumbers.size(); idxPosition++) { - if (this->runNumbers[idxPosition] == runNumber) { - matchedPosition = idxPosition; - break; + if (cfgOutputrunbyrun) { + for (uint64_t idxPosition = 0; idxPosition < this->runNumbers.size(); idxPosition++) { + if (this->runNumbers[idxPosition] == runNumber) { + matchedPosition = idxPosition; + break; + } + } + if (matchedPosition == -1) { + return; } - } - if (matchedPosition == -1) { - return; } TH1D* hLocalDensity = new TH1D("hphi", "hphi", 400, -constants::math::TwoPI, constants::math::TwoPI); @@ -1056,7 +1100,7 @@ struct FlowGfwOmegaXi { if (!setCurrentParticleWeights(weff, wacc, track, vtxz, 0)) continue; } - if ((track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) || (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) || (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value)) + if ((track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) || (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) || (track.itsNCls() <= trkQualityOpts.cfgChITSNCls.value)) continue; registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hPhicorr"), track.phi(), wacc); @@ -1085,10 +1129,6 @@ struct FlowGfwOmegaXi { registry.fill(HIST("correction/hRunNumberPhiEtaVertex"), matchedPosition, track.phi(), track.eta(), vtxz); } } - if (cfgDoLocDenCorr) { - registry.fill(HIST("hCentvsNch"), cent, nch); - registry.fill(HIST("hCentvsMultTPC"), cent, nMultTPC); - } // fill GFW of V0 flow double lowpt = trkQualityOpts.cfgCutPtPIDDauMin.value; double bachPtcut = trkQualityOpts.cfgCutPtPIDbachMin.value; @@ -1102,6 +1142,7 @@ struct FlowGfwOmegaXi { // check tpc bool isK0s = false; bool isLambda = false; + bool isALambda = false; if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; if (v0negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) @@ -1109,7 +1150,7 @@ struct FlowGfwOmegaXi { // fill QA if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + registry.fill(HIST("QAhisto/K0s/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); } // check daughter ITS, TPC and TOF // K0short @@ -1117,12 +1158,12 @@ struct FlowGfwOmegaXi { if (v0.qtarm() / std::fabs(v0.alpha()) > v0BuilderOpts.cfgv0_ArmPodocut.value && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_mk0swindow.value && (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && + ((std::fabs(v0.tofNSigmaK0PiPlus()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaK0PiMinus()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[6]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { registry.fill(HIST("InvMassK0s_all"), v0.pt(), v0.mK0Short(), v0.eta(), cent); isK0s = true; if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); + registry.fill(HIST("QAhisto/K0s/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); } } } @@ -1130,27 +1171,44 @@ struct FlowGfwOmegaXi { if (v0.pt() > trkQualityOpts.cfgCutPtLambdaMin.value && v0.pt() < trkQualityOpts.cfgCutPtLambdaMax.value) { if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(v0posdau.tofNSigmaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && + ((std::fabs(v0.tofNSigmaLaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaLaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); isLambda = true; - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && - (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(v0negdau.tofNSigmaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)) && - ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { - registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - isLambda = true; + } + if (std::fabs(v0.mAntiLambda() - o2::constants::physics::MassLambda) < v0BuilderOpts.cfgv0_mlambdawindow.value && + (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(v0.tofNSigmaALaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0.tofNSigmaALaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(v0negdau)) < cfgNSigma[7]) || v0posdau.pt() > lowpt) && ((std::fabs(itsResponse.nSigmaITS(v0posdau)) < cfgNSigma[6]) || v0negdau.pt() > lowpt)) { + registry.fill(HIST("InvMassALambda_all"), v0.pt(), v0.mAntiLambda(), v0.eta(), cent); + isALambda = true; } } // fill QA before cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); + if (isK0s) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVbefore"), v0.dcanegtopv()); + } + if (isLambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcanegtopv()); + } + if (isALambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcapostopv()); + } } - if (!isK0s && !isLambda) + if (!isK0s && !isLambda && !isALambda) continue; // track quality check if (v0posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) @@ -1186,14 +1244,38 @@ struct FlowGfwOmegaXi { isK0s = false; if (isLambda && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_compmassrejK0s.value) isLambda = false; + if (isALambda && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0BuilderOpts.cfgv0_compmassrejK0s.value) + isALambda = false; // fill QA after cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + if (isK0s) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/K0s/hphiposPi"), v0posdau.phi()); + registry.fill(HIST("QAhisto/K0s/hphinegPi"), v0negdau.phi()); + } + if (isLambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hphiposPr"), v0posdau.phi()); + registry.fill(HIST("QAhisto/Lambda/hphinegPi"), v0negdau.phi()); + } + if (isALambda) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hphiposPi"), v0posdau.phi()); + registry.fill(HIST("QAhisto/Lambda/hphinegPr"), v0negdau.phi()); + } } if (isK0s) { if (cfgDoAccEffCorr) @@ -1224,7 +1306,7 @@ struct FlowGfwOmegaXi { registry.fill(HIST("correction/hRunNumberPhiEtaVertexK0s"), matchedPosition, v0.phi(), v0.eta(), vtxz); } } - if (isLambda) { + if (isLambda || isALambda) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); if (cfgDoLocDenCorr) { @@ -1237,10 +1319,16 @@ struct FlowGfwOmegaXi { registry.fill(HIST("MC/densityMCRecLambdaMultTPC"), v0.pt(), nMultTPC, density, v0.mLambda()); } } - registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); + if (isLambda) + registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); + if (isALambda) + registry.fill(HIST("InvMassALambda"), v0.pt(), v0.mAntiLambda(), v0.eta(), cent); registry.fill(HIST("hPhiLambda"), v0.phi()); registry.fill(HIST("hPhiLambdacorr"), v0.phi(), wacc); - fGFW->Fill(v0.eta(), fLambdaPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nLambdaPtBins), v0.phi(), wacc * weff * wloc, 16); + if (isLambda) + fGFW->Fill(v0.eta(), fLambdaPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nLambdaPtBins), v0.phi(), wacc * weff * wloc, 16); + if (isALambda) + fGFW->Fill(v0.eta(), fLambdaPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mAntiLambda()) - 1) * nLambdaPtBins), v0.phi(), wacc * weff * wloc, 16); if (cfgOutputNUAWeights) fWeightsLambda->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); if (cfgOutputrunbyrun) { @@ -1275,13 +1363,13 @@ struct FlowGfwOmegaXi { if (casc.pt() > trkQualityOpts.cfgCutPtOmegaMin.value && casc.pt() < trkQualityOpts.cfgCutPtOmegaMax.value) { if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaOmLaPi()) < cfgNSigma[3] || negdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); isOmega = true; } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPr()) < cfgNSigma[4] || negdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaOmLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaOmKa()) < cfgNSigma[5] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaOmLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[7]) || negdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[6]) || posdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); isOmega = true; @@ -1291,13 +1379,13 @@ struct FlowGfwOmegaXi { if (casc.pt() > trkQualityOpts.cfgCutPtXiMin.value && casc.pt() < trkQualityOpts.cfgCutPtXiMax.value) { if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || negdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPr()) < cfgNSigma[4] || posdau.pt() < dauLaPrPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); isXi = true; } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && - ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPr()) < cfgNSigma[4] || negdau.pt() < dauLaPrPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && + ((std::fabs(casc.tofNSigmaXiPi()) < cfgNSigma[3] || bachelor.pt() < bachPtcut) && (std::fabs(casc.tofNSigmaXiLaPi()) < cfgNSigma[3] || posdau.pt() < dauLaPiPtcut)) && ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() > bachPtcut) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[7]) || negdau.pt() > dauLaPrPtcut) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[6]) || posdau.pt() > dauLaPiPtcut)) { registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); isXi = true; @@ -1313,6 +1401,19 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Xi/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Xi/hqadcaCascdaubefore"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Xi/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPi"), casc.tofNSigmaXiLaPi()); + registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Xi/hLaPiTOFnsigmavsPt"), casc.tofNSigmaXiLaPi(), posdau.pt()); + } else { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Xi/hTOFnsigmaposPr"), casc.tofNSigmaXiLaPr()); + registry.fill(HIST("QAhisto/Xi/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Xi/hLaPrTOFnsigmavsPt"), casc.tofNSigmaXiLaPr(), posdau.pt()); + } } if (isOmega) { registry.fill(HIST("QAhisto/Omega/hqaCascRadiusbefore"), casc.cascradius()); @@ -1322,6 +1423,19 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Omega/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Omega/hqadcaCascdaubefore"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Omega/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Omega/hTOFnsigmaposPi"), casc.tofNSigmaXiLaPi()); + registry.fill(HIST("QAhisto/Omega/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Omega/hLaPiTOFnsigmavsPt"), casc.tofNSigmaXiLaPi(), posdau.pt()); + } else { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVbefore"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVbefore"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Omega/hTOFnsigmaposPr"), casc.tofNSigmaXiLaPr()); + registry.fill(HIST("QAhisto/Omega/hBachTOFnsigmavsPt"), casc.tofNSigmaXiPi(), bachelor.pt()); + registry.fill(HIST("QAhisto/Omega/hLaPrTOFnsigmavsPt"), casc.tofNSigmaXiLaPr(), posdau.pt()); + } } } @@ -1338,6 +1452,17 @@ struct FlowGfwOmegaXi { continue; if (std::fabs(casc.dcabachtopv()) < cascBuilderOpts.cfgcasc_dcabachtopv.value) continue; + if (casc.sign() > 0) { + if (std::fabs(casc.dcapostopv()) < cascBuilderOpts.cfgcasc_dcaLaprtopv.value) + continue; + if (std::fabs(casc.dcanegtopv()) < cascBuilderOpts.cfgcasc_dcaLapitopv.value) + continue; + } else { + if (std::fabs(casc.dcanegtopv()) < cascBuilderOpts.cfgcasc_dcaLaprtopv.value) + continue; + if (std::fabs(casc.dcapostopv()) < cascBuilderOpts.cfgcasc_dcaLapitopv.value) + continue; + } if (casc.dcacascdaughters() > cascBuilderOpts.cfgcasc_dcacascdau.value) continue; if (casc.dcaV0daughters() > cascBuilderOpts.cfgcasc_dcav0dau.value) @@ -1387,6 +1512,13 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Xi/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Xi/hqadcaCascdauafter"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Xi/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVafter"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVafter"), casc.dcanegtopv()); + } else { + registry.fill(HIST("QAhisto/Xi/hqadcaCascLaprtoPVafter"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Xi/hqadcaCascLapitoPVafter"), casc.dcapostopv()); + } } if (isOmega) { registry.fill(HIST("QAhisto/Omega/hqaCascRadiusafter"), casc.cascradius()); @@ -1396,6 +1528,13 @@ struct FlowGfwOmegaXi { registry.fill(HIST("QAhisto/Omega/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); registry.fill(HIST("QAhisto/Omega/hqadcaCascdauafter"), casc.dcacascdaughters()); registry.fill(HIST("QAhisto/Omega/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (casc.sign() > 0) { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVafter"), casc.dcapostopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVafter"), casc.dcanegtopv()); + } else { + registry.fill(HIST("QAhisto/Omega/hqadcaCascLaprtoPVafter"), casc.dcanegtopv()); + registry.fill(HIST("QAhisto/Omega/hqadcaCascLapitoPVafter"), casc.dcapostopv()); + } } } @@ -1580,7 +1719,6 @@ struct FlowGfwOmegaXi { return; cent = collision.centFT0C(); nMultTPC = collision.multTPC(); - registry.fill(HIST("MC/hCentvsMultTPCMC"), cent, nMultTPC); } if (cent < 0) return; @@ -1613,7 +1751,6 @@ struct FlowGfwOmegaXi { } } } - registry.fill(HIST("MC/hCentvsNchMC"), cent, nch); for (const auto& straGen : tracksGen) { if (!straGen.isPhysicalPrimary()) @@ -1738,10 +1875,6 @@ struct FlowGfwOmegaXi { } } - if (cfgDoLocDenCorr) { - registry.fill(HIST("hCentvsNch"), cent, nch); - } - for (const auto& casc : Cascades) { if (!casc.has_mcParticle()) continue; @@ -1931,6 +2064,7 @@ struct FlowGfwOmegaXi { auto v0MC = v0.mcParticle_as(); auto v0negdau = v0.negTrack_as(); auto v0posdau = v0.posTrack_as(); + int pdgCode{v0MC.pdgCode()}; if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; @@ -1939,12 +2073,27 @@ struct FlowGfwOmegaXi { // fill QA before cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + if (pdgCode == kK0Short) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVbefore"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0Bar) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVbefore"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVbefore"), v0.dcapostopv()); + } } // // track quality check if (v0posdau.itsNCls() <= trkQualityOpts.cfgITSNCls.value) @@ -1978,14 +2127,29 @@ struct FlowGfwOmegaXi { continue; // fill QA after cut if (cfgOutputQA) { - registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + if (pdgCode == kK0Short) { + registry.fill(HIST("QAhisto/K0s/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/K0s/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/K0s/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/K0s/hqadcapostoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/K0s/hqadcanegtoPVafter"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcanegtopv()); + } + if (pdgCode == kLambda0Bar) { + registry.fill(HIST("QAhisto/Lambda/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/Lambda/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/Lambda/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPrtoPVafter"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/Lambda/hqadcaPitoPVafter"), v0.dcapostopv()); + } } - int pdgCode{v0MC.pdgCode()}; double v0Pt{v0MC.pt()}; double v0Phi{v0MC.phi()}; double v0Eta{v0MC.eta()}; diff --git a/PWGCF/Flow/Tasks/flowGfwTask.cxx b/PWGCF/Flow/Tasks/flowGfwTask.cxx index 4190e2d1740..e0c6616828d 100644 --- a/PWGCF/Flow/Tasks/flowGfwTask.cxx +++ b/PWGCF/Flow/Tasks/flowGfwTask.cxx @@ -12,7 +12,7 @@ /// \file flowGfwTask.cxx /// \author Iris Likmeta (iris.likmeta@cern.ch) /// \since Mar 28, 2024 -/// \brief Multiparticle flow measurements with FT0 and ZDC +/// \brief Multiparticle flow measurements with FT0 #include "FlowContainer.h" #include "GFW.h" @@ -71,7 +71,7 @@ struct FlowGfwTask { 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(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") O2_DEFINE_CONFIGURABLE(cfgTrackSel, bool, false, "ITS and TPC cluster selection") @@ -80,12 +80,12 @@ struct FlowGfwTask { O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "Custom DCA Z cut") + O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 1.0f, "Custom DCA XY cut") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") - O2_DEFINE_CONFIGURABLE(cfgCentEstFt0c, bool, false, "Centrality estimator based on FT0C signal") + O2_DEFINE_CONFIGURABLE(cfgCentEstFt0c, bool, true, "Centrality estimator based on FT0C signal") O2_DEFINE_CONFIGURABLE(cfgCentEstFt0a, bool, false, "Centrality estimator based on FT0A signal") O2_DEFINE_CONFIGURABLE(cfgCentEstFt0m, bool, false, " A centrality estimator based on FT0A+FT0C signals.") O2_DEFINE_CONFIGURABLE(cfgCentEstFv0a, bool, false, "Centrality estimator based on FV0A signal") - O2_DEFINE_CONFIGURABLE(cfgCentEstFt0cVariant1, bool, false, "A variant of FT0C") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgEfficiencyPt, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgEfficiencyNch, std::string, "", "CCDB path to Nch efficiency object") @@ -93,20 +93,20 @@ struct FlowGfwTask { O2_DEFINE_CONFIGURABLE(cfgMagnetField, std::string, "GLO/Config/GRPMagField", "CCDB path to Magnet field object") O2_DEFINE_CONFIGURABLE(cfgDCAzPt, bool, false, "switch for DCAz pt dependent") O2_DEFINE_CONFIGURABLE(cfgTrackSelRun3ITSMatch, bool, false, "Track selection for ITS matches") - 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(cfgUseAdditionalEventCut, bool, true, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalTrackCut, bool, true, "Use additional track cut on phi") O2_DEFINE_CONFIGURABLE(cfgOccupancy, bool, false, "Bool for event selection on detector occupancy"); O2_DEFINE_CONFIGURABLE(cfgNoTimeFrameBorder, bool, false, "kNoTimeFrameBorder"); O2_DEFINE_CONFIGURABLE(cfgNoITSROFrameBorder, bool, false, "kNoITSROFrameBorder"); O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileup, bool, false, "kNoSameBunchPileup"); O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, false, "kIsGoodZvtxFT0vsPV"); - O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, false, "kIsVertexITSTPC"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "kIsVertexITSTPC"); O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, false, "kNoCollInTimeRangeStandard"); O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, false, "kIsGoodITSLayersAll") O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, false, "Use additional event cut on mult correlations"); O2_DEFINE_CONFIGURABLE(cfgV0AT0ANSigma, bool, false, "V0A T0A n sigma cut") O2_DEFINE_CONFIGURABLE(cfgNSigma, float, 5.0f, "N sigma cut") - O2_DEFINE_CONFIGURABLE(cfgGlobalTracks, bool, false, "Global tracks") + O2_DEFINE_CONFIGURABLE(cfgGlobalTracks, bool, true, "Global tracks") O2_DEFINE_CONFIGURABLE(cfgGlobalplusITS, bool, false, "Global and ITS tracks") O2_DEFINE_CONFIGURABLE(cfgGlobalonly, bool, false, "Global only tracks") O2_DEFINE_CONFIGURABLE(cfgITSonly, bool, false, "ITS only tracks") @@ -130,14 +130,6 @@ struct FlowGfwTask { ConfigurableAxis axisDCAz{"axisDCAz", {200, -2, 2}, "DCA_{z} (cm)"}; ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -1, 1}, "DCA_{xy} (cm)"}; - // Configurables for ZDC - Configurable nBinsAmp{"nBinsAmp", 1025, "nbinsAmp"}; - Configurable maxZN{"maxZN", 4099.5, "Max ZN signal"}; - Configurable maxZP{"maxZP", 3099.5, "Max ZP signal"}; - Configurable maxZEM{"maxZEM", 3099.5, "Max ZEM signal"}; - Configurable nBinsFit{"nBinsFit", 1000, "nbinsFit"}; - Configurable maxMultFT0{"maxMultFT0", 5000, "Max FT0 signal"}; - // Corrections TH1D* mEfficiency = nullptr; TH1D* mEfficiencyNch = nullptr; @@ -169,34 +161,58 @@ struct FlowGfwTask { kc26, kc28, kc22etagap, + kc22etagap02, + kc22etagap04, kc32, kc32etagap, + kc32etagap02, + kc32etagap04, kc34, kc34etagap, + kc34etagap02, + kc34etagap04, kc22Nch, kc24Nch, kc26Nch, kc28Nch, kc22Nchetagap, + kc22Nchetagap02, + kc22Nchetagap04, kc32Nch, kc32Nchetagap, + kc32Nchetagap02, + kc32Nchetagap04, kc34Nch, kc34Nchetagap, + kc34Nchetagap02, + kc34Nchetagap04, kc22Nch05, kc24Nch05, kc26Nch05, kc28Nch05, kc22Nch05etagap, + kc22Nch05etagap02, + kc22Nch05etagap04, kc32Nch05, kc32Nch05etagap, + kc32Nch05etagap02, + kc32Nch05etagap04, kc34Nch05, kc34Nch05etagap, + kc34Nch05etagap02, + kc34Nch05etagap04, kc22ft0c, kc22etagapft0c, + kc22etagap02ft0c, + kc22etagap04ft0c, kc32ft0c, kc32etagapft0c, + kc32etagap02ft0c, + kc32etagap04ft0c, kc34ft0c, kc34etagapft0c, + kc34etagap02ft0c, + kc34etagap04ft0c, // Count the total number of enum kCount_ExtraProfile @@ -223,7 +239,6 @@ struct FlowGfwTask { kCentFT0A, kCentFT0M, kCentFV0A, - kCentFT0CVariant1, kNoCentEstimators }; @@ -305,12 +320,10 @@ struct FlowGfwTask { registry.get(HIST("hCentEstimators"))->GetXaxis()->SetBinLabel(kCentFT0A + 1, "FT0A"); registry.get(HIST("hCentEstimators"))->GetXaxis()->SetBinLabel(kCentFT0M + 1, "FT0M"); registry.get(HIST("hCentEstimators"))->GetXaxis()->SetBinLabel(kCentFV0A + 1, "FV0A"); - registry.get(HIST("hCentEstimators"))->GetXaxis()->SetBinLabel(kCentFT0CVariant1 + 1, "FT0CVar1"); registry.add("hCentFT0C", "Uncorrected FT0C;Centrality FT0C ;Events", kTH1F, {axisCentrality}); registry.add("hCentFT0A", "Uncorrected FT0A;Centrality FT0A ;Events", kTH1F, {axisCentrality}); registry.add("hCentFT0M", "Uncorrected FT0M;Centrality FT0M ;Events", kTH1F, {axisCentrality}); registry.add("hCentFV0A", "Uncorrected FV0A;Centrality FV0A ;Events", kTH1F, {axisCentrality}); - registry.add("hCentFT0CVariant1", "Uncorrected FT0CVariant1;Centrality FT0CVariant1 ;Events", kTH1F, {axisCentrality}); // Before cuts registry.add("BeforeCut_globalTracks_centT0C", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); @@ -339,24 +352,6 @@ struct FlowGfwTask { registry.add("FT0AAmp", ";FT0A amplitude;Events", kTH1F, {axisFT0AAmp}); registry.add("FT0MAmp", ";FT0M amplitude;Events", kTH1F, {axisFT0MAmp}); - // ZDC plots - const AxisSpec axisEvent{3, 0., +3.0, ""}; - registry.add("hEventCounterForZDC", "Event counter", kTH1F, {axisEvent}); - registry.add("ZNAcoll", "ZNAcoll; ZNA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZN}}}); - registry.add("ZPAcoll", "ZPAcoll; ZPA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZP}}}); - registry.add("ZNCcoll", "ZNCcoll; ZNC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZN}}}); - registry.add("ZPCcoll", "ZPCcoll; ZPC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZP}}}); - registry.add("ZNvsFT0correl", "ZNvsFT0correl; FT0 amplitude; ZN", {HistType::kTH2F, {{{nBinsFit, 0., maxMultFT0}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - registry.add("ZDCAmp", "ZDC Amplitude; ZDC Amplitude; Events", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZP}}}); - registry.add("ZNAmp", "ZNA+ZNC Amplitude; ZN Amplitude; Events", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZN}}}); - registry.add("ZPAmp", "ZPA+ZPC Amplitude; ZP Amplitude; Events", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZP}}}); - registry.add("ZNvsZEMcoll", "ZNvsZEMcoll; ZEM; ZDC energy (GeV)", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZEM}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - registry.add("ZNvsZEMcoll05", "ZNvsZEMcoll; ZEM; ZDC energy (GeV)", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZEM}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - registry.add("ZNvsZEMcoll510", "ZNvsZEMcoll; ZEM; ZDC energy (GeV)", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZEM}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - registry.add("ZNvsZEMcoll1020", "ZNvsZEMcoll; ZEM; ZDC energy (GeV)", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZEM}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - registry.add("ZNvsZEMcoll2030", "ZNvsZEMcoll; ZEM; ZDC energy (GeV)", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZEM}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - registry.add("ZNvsZEMcollrest", "ZNvsZEMcoll; ZEM; ZDC energy (GeV)", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZEM}, {nBinsAmp, -0.5, 2. * maxZN}}}}); - // Track plots registry.add("Nch", "N_{ch} vs #Events;N_{ch};No. of Events", {HistType::kTH1D, {axisNch}}); registry.add("Nch05", "N_{ch 0-5%} vs #Events;N_{ch 0-5%};No. of Events", {HistType::kTH1D, {axisNch}}); @@ -381,7 +376,7 @@ struct FlowGfwTask { registry.add("hChi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); registry.add("hnTPCClu", "Number of found TPC clusters", {HistType::kTH1D, {{100, 40, 180}}}); registry.add("hnTPCCrossedRow", "Number of crossed TPC Rows", {HistType::kTH1D, {{100, 40, 180}}}); - registry.add("hDCAz", "DCAz after cuts", {HistType::kTH1D, {{100, -3, 3}}}); + registry.add("hDCAz", "DCAz after cuts; Pt", {HistType::kTH2D, {{100, -3, 3}, {50, 0, 10}}}); registry.add("hDCAxy", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{50, -1, 1}, {50, 0, 10}}}); // Additional Output histograms @@ -390,37 +385,61 @@ struct FlowGfwTask { registry.add("c26", ";Centrality (%) ; C_{2}{6}", {HistType::kTProfile, {axisCentrality}}); registry.add("c28", ";Centrality (%) ; C_{2}{8}", {HistType::kTProfile, {axisCentrality}}); registry.add("c22etagap", ";Centrality (%) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); + registry.add("c22etagap02", ";Centrality (%) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); + registry.add("c22etagap04", ";Centrality (%) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); registry.add("c32", ";Centrality (%) ; C_{3}{2} ", {HistType::kTProfile, {axisCentrality}}); registry.add("c32etagap", ";Centrality (%) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); + registry.add("c32etagap02", ";Centrality (%) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); + registry.add("c32etagap04", ";Centrality (%) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); registry.add("c34", ";Centrality (%) ; C_{3}{4} ", {HistType::kTProfile, {axisCentrality}}); registry.add("c34etagap", ";Centrality (%) ; C_{3}{4} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); + registry.add("c34etagap02", ";Centrality (%) ; C_{3}{4} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); + registry.add("c34etagap04", ";Centrality (%) ; C_{3}{4} (|#eta| < 0.8) ", {HistType::kTProfile, {axisCentrality}}); registry.add("c22Nch", ";N_{ch}(|#eta| < 0.8) ; C_{2}{2} ", {HistType::kTProfile, {axisNch}}); registry.add("c24Nch", ";N_{ch}(|#eta| < 0.8) ; C_{2}{4}", {HistType::kTProfile, {axisNch}}); registry.add("c26Nch", ";N_{ch}(|#eta| < 0.8) ; C_{2}{6}", {HistType::kTProfile, {axisNch}}); registry.add("c28Nch", ";N_{ch}(|#eta| < 0.8) ; C_{2}{8}", {HistType::kTProfile, {axisNch}}); registry.add("c22Nchetagap", ";N_ch(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + registry.add("c22Nchetagap02", ";N_ch(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + registry.add("c22Nchetagap04", ";N_ch(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); registry.add("c32Nch", ";N_{ch}(|#eta| < 0.8) ; C_{3}{2} ", {HistType::kTProfile, {axisNch}}); registry.add("c32Nchetagap", ";N_ch(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + registry.add("c32Nchetagap02", ";N_ch(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + registry.add("c32Nchetagap04", ";N_ch(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); registry.add("c34Nch", ";N_{ch}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); registry.add("c34Nchetagap", ";N_{ch}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); - - registry.add("c22Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{2} ", {HistType::kTProfile, {axisNch}}); - registry.add("c24Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{4}", {HistType::kTProfile, {axisNch}}); - registry.add("c26Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{6}", {HistType::kTProfile, {axisNch}}); - registry.add("c28Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{8}", {HistType::kTProfile, {axisNch}}); - registry.add("c22Nch05etagap", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); - registry.add("c32Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{2} ", {HistType::kTProfile, {axisNch}}); - registry.add("c32Nch05etagap", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); - registry.add("c34Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); - registry.add("c34Nch05etagap", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); + registry.add("c34Nchetagap02", ";N_{ch}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); + registry.add("c34Nchetagap04", ";N_{ch}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); + + // registry.add("c22Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{2} ", {HistType::kTProfile, {axisNch}}); + // registry.add("c24Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{4}", {HistType::kTProfile, {axisNch}}); + // registry.add("c26Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{6}", {HistType::kTProfile, {axisNch}}); + // registry.add("c28Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{8}", {HistType::kTProfile, {axisNch}}); + // registry.add("c22Nch05etagap", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + // registry.add("c22Nch05etagap02", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + // registry.add("c22Nch05etagap04", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + // registry.add("c32Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{2} ", {HistType::kTProfile, {axisNch}}); + // registry.add("c32Nch05etagap", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + // registry.add("c32Nch05etagap02", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + // registry.add("c32Nch05etagap04", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisNch}}); + // registry.add("c34Nch05", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); + // registry.add("c34Nch05etagap", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); + // registry.add("c34Nch05etagap02", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); + // registry.add("c34Nch05etagap04", ";N_{ch 0-5%}(|#eta| < 0.8) ; C_{3}{4} ", {HistType::kTProfile, {axisNch}}); registry.add("c22ft0c", ";FT0C Amplitude ; C_{2}{2} ", {HistType::kTProfile, {axisFT0CAmp}}); registry.add("c22etagapft0c", ";FT0C Amplitude ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); + // registry.add("c22etagap02ft0c", ";FT0C Amplitude ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); + // registry.add("c22etagap04ft0c", ";FT0C Amplitude ; C_{2}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); registry.add("c32ft0c", ";FT0C Amplitude ; C_{2}{2} ", {HistType::kTProfile, {axisFT0CAmp}}); registry.add("c32etagapft0c", ";FT0C Amplitude ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); + // registry.add("c32etagap02ft0c", ";FT0C Amplitude ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); + // registry.add("c32etagap04ft0c", ";FT0C Amplitude ; C_{3}{2} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); registry.add("c34ft0c", ";FT0C Amplitude ; C_{3}{4} ", {HistType::kTProfile, {axisFT0CAmp}}); registry.add("c34etagapft0c", ";FT0C Amplitude ; C_{3}{4} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); + // registry.add("c34etagap02ft0c", ";FT0C Amplitude ; C_{3}{4} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); + // registry.add("c34etagap04ft0c", ";FT0C Amplitude ; C_{3}{4} (|#eta| < 0.8) ", {HistType::kTProfile, {axisFT0CAmp}}); } // End doprocessData const AxisSpec axisZpos{48, -12., 12., "Vtx_{z} (cm)"}; @@ -480,37 +499,61 @@ struct FlowGfwTask { bootstrapArray[i][kc26] = registry.add(Form("BootstrapContainer_%d/c26", i), ";Centrality (%) ; C_{2}{6}", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc28] = registry.add(Form("BootstrapContainer_%d/c28", i), ";Centrality (%) ; C_{2}{8}", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc22etagap] = registry.add(Form("BootstrapContainer_%d/c22etagap", i), ";Centrality (%) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); + bootstrapArray[i][kc22etagap02] = registry.add(Form("BootstrapContainer_%d/c22etagap02", i), ";Centrality (%) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); + bootstrapArray[i][kc22etagap04] = registry.add(Form("BootstrapContainer_%d/c22etagap04", i), ";Centrality (%) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc32] = registry.add(Form("BootstrapContainer_%d/c32", i), ";Centrality (%) ; C_{3}{2}", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc32etagap] = registry.add(Form("BootstrapContainer_%d/c32etagap", i), ";Centrality (%) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); + bootstrapArray[i][kc32etagap02] = registry.add(Form("BootstrapContainer_%d/c32etagap02", i), ";Centrality (%) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); + bootstrapArray[i][kc32etagap04] = registry.add(Form("BootstrapContainer_%d/c32etagap04", i), ";Centrality (%) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc34] = registry.add(Form("BootstrapContainer_%d/c34", i), ";Centrality (%) ; C_{3}{4}", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc34etagap] = registry.add(Form("BootstrapContainer_%d/c34etagap", i), ";Centrality (%) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); + bootstrapArray[i][kc34etagap02] = registry.add(Form("BootstrapContainer_%d/c34etagap02", i), ";Centrality (%) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); + bootstrapArray[i][kc34etagap04] = registry.add(Form("BootstrapContainer_%d/c34etagap04", i), ";Centrality (%) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisCentrality}}); bootstrapArray[i][kc22Nch] = registry.add(Form("BootstrapContainer_%d/c22Nch", i), ";N_ch(|#eta| < 0.8) ; C_{2}{2}", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc24Nch] = registry.add(Form("BootstrapContainer_%d/c24Nch", i), ";N_ch(|#eta| < 0.8) ; C_{2}{4}", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc26Nch] = registry.add(Form("BootstrapContainer_%d/c26Nch", i), ";N_ch(|#eta| < 0.8) ; C_{2}{6}", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc28Nch] = registry.add(Form("BootstrapContainer_%d/c28Nch", i), ";N_ch(|#eta| < 0.8) ; C_{2}{8}", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc22Nchetagap] = registry.add(Form("BootstrapContainer_%d/c22Nchetagap", i), ";N_ch(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + bootstrapArray[i][kc22Nchetagap02] = registry.add(Form("BootstrapContainer_%d/c22Nchetagap02", i), ";N_ch(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + bootstrapArray[i][kc22Nchetagap04] = registry.add(Form("BootstrapContainer_%d/c22Nchetagap04", i), ";N_ch(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc32Nch] = registry.add(Form("BootstrapContainer_%d/c32Nch", i), ";N_ch(|#eta| < 0.8) ; C_{3}{2}", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc32Nchetagap] = registry.add(Form("BootstrapContainer_%d/c32Nchetagap", i), ";N_ch(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + bootstrapArray[i][kc32Nchetagap02] = registry.add(Form("BootstrapContainer_%d/c32Nchetagap02", i), ";N_ch(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + bootstrapArray[i][kc32Nchetagap04] = registry.add(Form("BootstrapContainer_%d/c32Nchetagap04", i), ";N_ch(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc34Nch] = registry.add(Form("BootstrapContainer_%d/c34Nch", i), ";N_ch(|#eta| < 0.8) ; C_{3}{4}", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc34Nchetagap] = registry.add(Form("BootstrapContainer_%d/c34Nchetagap", i), ";N_ch(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); - - bootstrapArray[i][kc22Nch05] = registry.add(Form("BootstrapContainer_%d/c22Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{2}", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc24Nch05] = registry.add(Form("BootstrapContainer_%d/c24Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{4}", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc26Nch05] = registry.add(Form("BootstrapContainer_%d/c26Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{6}", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc28Nch05] = registry.add(Form("BootstrapContainer_%d/c28Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{8}", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc22Nch05etagap] = registry.add(Form("BootstrapContainer_%d/c22Nch05etagap", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc32Nch05] = registry.add(Form("BootstrapContainer_%d/c32Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{2}", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc32Nch05etagap] = registry.add(Form("BootstrapContainer_%d/c32Nch05etagap", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc34Nch05] = registry.add(Form("BootstrapContainer_%d/c34Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{4}", {HistType::kTProfile, {axisNch}}); - bootstrapArray[i][kc34Nch05etagap] = registry.add(Form("BootstrapContainer_%d/c34Nch05etagap", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + bootstrapArray[i][kc34Nchetagap02] = registry.add(Form("BootstrapContainer_%d/c34Nchetagap02", i), ";N_ch(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + bootstrapArray[i][kc34Nchetagap04] = registry.add(Form("BootstrapContainer_%d/c34Nchetagap04", i), ";N_ch(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + + // bootstrapArray[i][kc22Nch05] = registry.add(Form("BootstrapContainer_%d/c22Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{2}", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc24Nch05] = registry.add(Form("BootstrapContainer_%d/c24Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{4}", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc26Nch05] = registry.add(Form("BootstrapContainer_%d/c26Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{6}", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc28Nch05] = registry.add(Form("BootstrapContainer_%d/c28Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{8}", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc22Nch05etagap] = registry.add(Form("BootstrapContainer_%d/c22Nch05etagap", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc22Nch05etagap02] = registry.add(Form("BootstrapContainer_%d/c22Nch05etagap02", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc22Nch05etagap04] = registry.add(Form("BootstrapContainer_%d/c22Nch05etagap04", i), ";N_ch05(|#eta| < 0.8) ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc32Nch05] = registry.add(Form("BootstrapContainer_%d/c32Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{2}", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc32Nch05etagap] = registry.add(Form("BootstrapContainer_%d/c32Nch05etagap", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc32Nch05etagap02] = registry.add(Form("BootstrapContainer_%d/c32Nch05etagap02", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc32Nch05etagap04] = registry.add(Form("BootstrapContainer_%d/c32Nch05etagap04", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc34Nch05] = registry.add(Form("BootstrapContainer_%d/c34Nch05", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{4}", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc34Nch05etagap] = registry.add(Form("BootstrapContainer_%d/c34Nch05etagap", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc34Nch05etagap02] = registry.add(Form("BootstrapContainer_%d/c34Nch05etagap02", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); + // bootstrapArray[i][kc34Nch05etagap04] = registry.add(Form("BootstrapContainer_%d/c34Nch05etagap04", i), ";N_ch05(|#eta| < 0.8) ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisNch}}); bootstrapArray[i][kc22ft0c] = registry.add(Form("BootstrapContainer_%d/c22ftoc", i), ";FT0C Amplitude ; C_{2}{2}", {HistType::kTProfile, {axisFT0CAmp}}); bootstrapArray[i][kc22etagapft0c] = registry.add(Form("BootstrapContainer_%d/c22etagapftoc", i), ";FT0C Amplitude ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); + // bootstrapArray[i][kc22etagap02ft0c] = registry.add(Form("BootstrapContainer_%d/c22etagapftoc02", i), ";FT0C Amplitude ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); + // bootstrapArray[i][kc22etagap04ft0c] = registry.add(Form("BootstrapContainer_%d/c22etagapftoc04", i), ";FT0C Amplitude ; C_{2}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); bootstrapArray[i][kc32ft0c] = registry.add(Form("BootstrapContainer_%d/c32ftoc", i), ";FT0C Amplitude ; C_{3}{2}", {HistType::kTProfile, {axisFT0CAmp}}); bootstrapArray[i][kc32etagapft0c] = registry.add(Form("BootstrapContainer_%d/c32etagapftoc", i), ";FT0C Amplitude ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); + // bootstrapArray[i][kc32etagap02ft0c] = registry.add(Form("BootstrapContainer_%d/c32etagapftoc02", i), ";FT0C Amplitude ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); + // bootstrapArray[i][kc32etagap04ft0c] = registry.add(Form("BootstrapContainer_%d/c32etagapftoc04", i), ";FT0C Amplitude ; C_{3}{2} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); bootstrapArray[i][kc34ft0c] = registry.add(Form("BootstrapContainer_%d/c34ftoc", i), ";FT0C Amplitude ; C_{3}{4}", {HistType::kTProfile, {axisFT0CAmp}}); bootstrapArray[i][kc34etagapft0c] = registry.add(Form("BootstrapContainer_%d/c34ftocetagap", i), ";FT0C Amplitude ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); + // bootstrapArray[i][kc34etagap02ft0c] = registry.add(Form("BootstrapContainer_%d/c34ftocetagap02", i), ";FT0C Amplitude ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); + // bootstrapArray[i][kc34etagap04ft0c] = registry.add(Form("BootstrapContainer_%d/c34ftocetagap04", i), ";FT0C Amplitude ; C_{3}{4} (|#eta| < 0.8)", {HistType::kTProfile, {axisFT0CAmp}}); } o2::framework::AxisSpec axis = axisPt; @@ -531,9 +574,16 @@ struct FlowGfwTask { delete oba; fGFW->AddRegion("full", -0.8, 0.8, 1, 1); // eta region -0.8 to 0.8 - fGFW->AddRegion("refN10", -0.8, -0.5, 1, 1); + + fGFW->AddRegion("refN10", -0.8, -0.5, 1, 1); // delta eta 1 fGFW->AddRegion("refP10", 0.5, 0.8, 1, 1); + fGFW->AddRegion("refN02", -0.8, -0.1, 1, 1); // delta eta 0.2 + fGFW->AddRegion("refP02", 0.1, 0.8, 1, 1); + + fGFW->AddRegion("refN04", -0.8, -0.2, 1, 1); // delta eta 0.4 + fGFW->AddRegion("refP04", 0.2, 0.8, 1, 1); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {2 -2}", "ChFull22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {2 2 -2 -2}", "ChFull24", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {2 2 2 -2 -2 -2}", "ChFull26", kFALSE)); @@ -543,6 +593,15 @@ struct FlowGfwTask { corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {3} refP10 {-3}", "Ch10Gap32", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {3 3 -3 -3}", "ChFull34", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN10 {3 3} refP10 {-3 -3}", "Ch10Gap34", kFALSE)); + + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN02 {2} refP02 {-2}", "Ch02Gap22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN02 {3} refP02 {-3}", "Ch02Gap32", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN02 {3 3} refP02 {-3 -3}", "Ch02Gap34", kFALSE)); + + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {2} refP04 {-2}", "Ch04Gap22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {3} refP04 {-3}", "Ch04Gap32", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN04 {3 3} refP04 {-3 -3}", "Ch04Gap34", kFALSE)); + fGFW->CreateRegions(); // finalize the initialization if (cfgUseAdditionalEventCut) { @@ -824,22 +883,18 @@ struct FlowGfwTask { if (cfgDCAzPt && (std::fabs(track.dcaZ()) > (0.004f + 0.013f / track.pt()))) return false; - if (cfgTrackSel) { + if (cfgTrackSel) { // is set to zero and choose type of tracks on configuration return myTrackSel.IsSelected(track); } else if (cfgGlobalplusITS) { - return ((track.tpcNClsFound() >= cfgCutTPCclu) || (track.itsNCls() >= cfgCutITSclu)); - } else if (cfgGlobalonly) { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu)); - } else if (cfgITSonly) { - return ((track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.tpcChi2NCl() < cfgCutChi2prTPCcls) && (track.itsNCls() >= cfgCutITSclu)); } else if (cfgGlobalTracks) { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.tpcChi2NCl() < cfgCutChi2prTPCcls) && (track.itsNCls() >= cfgCutITSclu)); } else { return false; } } - // Apply process filters GlobalTracks + // Apply process filters Global+ITS_only sample Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex && (aod::cent::centFT0C > cfgMinCentFT0C) && (aod::cent::centFT0C < cfgMaxCentFT0C); Filter trackFilter = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && ncheckbit(aod::track::trackCutFlag, TrackSelectionITS) && @@ -847,9 +902,9 @@ struct FlowGfwTask { ncheckbit(aod::track::trackCutFlag, TrackSelectionTPC), true) && ifnode(dcaZ > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, TrackSelectionDCAXYonly), ncheckbit(aod::track::trackCutFlag, TrackSelectionDCA)) && - (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::dcaXY) < cfgCutDCAxy); - void processData(Colls::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, aod::FT0s const&, aod::Zdcs const&, BCsRun3 const&) + void processData(Colls::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, aod::FT0s const&, BCsRun3 const&) { registry.fill(HIST("hEventCount"), kFILTERED); if (!collision.sel8()) @@ -882,11 +937,6 @@ struct FlowGfwTask { registry.fill(HIST("hCentEstimators"), kCentFV0A); registry.fill(HIST("hCentFV0A"), centrality); } - if (cfgCentEstFt0cVariant1) { - centrality = collision.centFT0CVariant1(); - registry.fill(HIST("hCentEstimators"), kCentFT0CVariant1); - registry.fill(HIST("hCentFT0CVariant1"), centrality); - } // fill event QA before cuts registry.fill(HIST("BeforeCut_globalTracks_centT0C"), collision.centFT0C(), tracks.size()); @@ -910,25 +960,21 @@ struct FlowGfwTask { return; } + // Use for c22 vs ft0 amplitude + double ft0aAmp = 0; + double ft0cAmp = 0; + double ft0mAmp = 0; const auto& foundBC = collision.foundBC_as(); - if (foundBC.has_zdc()) { - registry.fill(HIST("hEventCounterForZDC"), 1); - - // FT0 amplitude to use in fine binning - double ft0aAmp = 0; - double ft0cAmp = 0; - double ft0mAmp = 0; - - if (foundBC.has_ft0()) { - for (const auto& amplitude : foundBC.ft0().amplitudeA()) { - ft0aAmp += amplitude; - } - for (const auto& amplitude : foundBC.ft0().amplitudeC()) { - ft0cAmp += amplitude; - } - } else { - ft0aAmp = ft0cAmp = -999; + if (foundBC.has_ft0()) { + for (const auto& amplitude : foundBC.ft0().amplitudeA()) { + ft0aAmp += amplitude; } + for (const auto& amplitude : foundBC.ft0().amplitudeC()) { + ft0cAmp += amplitude; + } + } else { + ft0aAmp = ft0cAmp = -999; + } registry.fill(HIST("FT0AAmp"), ft0aAmp); registry.fill(HIST("FT0CAmp"), ft0cAmp); @@ -936,52 +982,6 @@ struct FlowGfwTask { ft0mAmp = ft0aAmp + ft0cAmp; registry.fill(HIST("FT0MAmp"), ft0mAmp); - // ZDC amplitude to use in fine binning - const auto& zdcread = foundBC.zdc(); - auto aZNA = zdcread.amplitudeZNA(); - auto aZNC = zdcread.amplitudeZNC(); - auto aZPA = zdcread.amplitudeZPA(); - auto aZPC = zdcread.amplitudeZPC(); - auto aZEM1 = zdcread.amplitudeZEM1(); - auto aZEM2 = zdcread.amplitudeZEM2(); - - registry.fill(HIST("ZNAcoll"), aZNA); - registry.fill(HIST("ZNCcoll"), aZNC); - registry.fill(HIST("ZPAcoll"), aZPA); - registry.fill(HIST("ZPCcoll"), aZPC); - - registry.fill(HIST("ZNvsFT0correl"), (ft0aAmp + ft0cAmp) / 100., aZNC + aZNA); - - double aZDC = aZNC + aZNA + aZPA + aZPC; - registry.fill(HIST("ZDCAmp"), aZDC); - registry.fill(HIST("ZNAmp"), aZNC + aZNA); - registry.fill(HIST("ZPAmp"), aZPA + aZPC); - - registry.fill(HIST("ZNvsZEMcoll"), aZEM1 + aZEM2, aZNA + aZNC); - - // Draft notation for centrality limits - float zero = 0, five = 5, ten = 10, twenty = 20, thirty = 30; - if (centrality >= zero && centrality <= five) { - registry.fill(HIST("ZNvsZEMcoll05"), aZEM1 + aZEM2, aZNA + aZNC); - } else if (centrality > five && centrality <= ten) { - registry.fill(HIST("ZNvsZEMcoll510"), aZEM1 + aZEM2, aZNA + aZNC); - } else if (centrality > ten && centrality <= twenty) { - registry.fill(HIST("ZNvsZEMcoll1020"), aZEM1 + aZEM2, aZNA + aZNC); - } else if (centrality > twenty && centrality <= thirty) { - registry.fill(HIST("ZNvsZEMcoll2030"), aZEM1 + aZEM2, aZNA + aZNC); - } else { - registry.fill(HIST("ZNvsZEMcollrest"), aZEM1 + aZEM2, aZNA + aZNC); - } - } // End of ZDC - - // Use for c22 vs ft0 amplitude - double ft0cAmp = 0; - if (foundBC.has_ft0()) { - for (const auto& amplitude : foundBC.ft0().amplitudeC()) { - ft0cAmp += amplitude; - } - } - float vtxz = collision.posZ(); float lRandom = fRndm->Rndm(); registry.fill(HIST("hVtxZ"), vtxz); @@ -1050,7 +1050,7 @@ struct FlowGfwTask { registry.fill(HIST("hChi2prTPCcls"), track.tpcChi2NCl()); registry.fill(HIST("hnTPCClu"), track.tpcNClsFound()); registry.fill(HIST("hnTPCCrossedRow"), track.tpcNClsCrossedRows()); - registry.fill(HIST("hDCAz"), track.dcaZ()); + registry.fill(HIST("hDCAz"), track.dcaZ(), track.pt()); registry.fill(HIST("hDCAxy"), track.dcaXY(), track.pt()); } @@ -1105,6 +1105,13 @@ struct FlowGfwTask { fillProfile(corrconfigs.at(7), HIST("c34"), centrality); fillProfile(corrconfigs.at(8), HIST("c34etagap"), centrality); + fillProfile(corrconfigs.at(9), HIST("c22etagap02"), centrality); + fillProfile(corrconfigs.at(10), HIST("c32etagap02"), centrality); + fillProfile(corrconfigs.at(11), HIST("c34etagap02"), centrality); + fillProfile(corrconfigs.at(12), HIST("c22etagap04"), centrality); + fillProfile(corrconfigs.at(13), HIST("c32etagap04"), centrality); + fillProfile(corrconfigs.at(14), HIST("c34etagap04"), centrality); + fillProfile(corrconfigs.at(0), HIST("c22Nch"), nch); fillProfile(corrconfigs.at(1), HIST("c24Nch"), nch); fillProfile(corrconfigs.at(2), HIST("c26Nch"), nch); @@ -1115,18 +1122,32 @@ struct FlowGfwTask { fillProfile(corrconfigs.at(7), HIST("c34Nch"), nch); fillProfile(corrconfigs.at(8), HIST("c34Nchetagap"), nch); + fillProfile(corrconfigs.at(9), HIST("c22Nchetagap02"), nch); + fillProfile(corrconfigs.at(10), HIST("c32Nchetagap02"), nch); + fillProfile(corrconfigs.at(11), HIST("c34Nchetagap02"), nch); + fillProfile(corrconfigs.at(12), HIST("c22Nchetagap04"), nch); + fillProfile(corrconfigs.at(13), HIST("c32Nchetagap04"), nch); + fillProfile(corrconfigs.at(14), HIST("c34Nchetagap04"), nch); + // 0-5% centrality Nch float zero = 0, five = 5; if (centrality >= zero && centrality <= five) { - fillProfile(corrconfigs.at(0), HIST("c22Nch05"), nch); - fillProfile(corrconfigs.at(1), HIST("c24Nch05"), nch); - fillProfile(corrconfigs.at(2), HIST("c26Nch05"), nch); - fillProfile(corrconfigs.at(3), HIST("c28Nch05"), nch); - fillProfile(corrconfigs.at(4), HIST("c22Nch05etagap"), nch); - fillProfile(corrconfigs.at(5), HIST("c32Nch05"), nch); - fillProfile(corrconfigs.at(6), HIST("c32Nch05etagap"), nch); - fillProfile(corrconfigs.at(7), HIST("c34Nch05"), nch); - fillProfile(corrconfigs.at(8), HIST("c34Nch05etagap"), nch); + // fillProfile(corrconfigs.at(0), HIST("c22Nch05"), nch); + // fillProfile(corrconfigs.at(1), HIST("c24Nch05"), nch); + // fillProfile(corrconfigs.at(2), HIST("c26Nch05"), nch); + // fillProfile(corrconfigs.at(3), HIST("c28Nch05"), nch); + // fillProfile(corrconfigs.at(4), HIST("c22Nch05etagap"), nch); + // fillProfile(corrconfigs.at(5), HIST("c32Nch05"), nch); + // fillProfile(corrconfigs.at(6), HIST("c32Nch05etagap"), nch); + // fillProfile(corrconfigs.at(7), HIST("c34Nch05"), nch); + // fillProfile(corrconfigs.at(8), HIST("c34Nch05etagap"), nch); + + // fillProfile(corrconfigs.at(9), HIST("c22Nch05etagap02"), nch); + // fillProfile(corrconfigs.at(10), HIST("c32Nch05etagap02"), nch); + // fillProfile(corrconfigs.at(11), HIST("c34Nch05etagap02"), nch); + // fillProfile(corrconfigs.at(12), HIST("c22Nch05etagap04"), nch); + // fillProfile(corrconfigs.at(13), HIST("c32Nch05etagap04"), nch); + // fillProfile(corrconfigs.at(14), HIST("c34Nch05etagap04"), nch); } // C22, C32 and C34 vs FT0C amplitude @@ -1137,6 +1158,13 @@ struct FlowGfwTask { fillProfile(corrconfigs.at(7), HIST("c34ft0c"), ft0cAmp); fillProfile(corrconfigs.at(8), HIST("c34etagapft0c"), ft0cAmp); + // fillProfile(corrconfigs.at(9), HIST("c22etagap02ft0c"), ft0cAmp); + // fillProfile(corrconfigs.at(10), HIST("c32etagap02ft0c"), ft0cAmp); + // fillProfile(corrconfigs.at(11), HIST("c34etagap02ft0c"), ft0cAmp); + // fillProfile(corrconfigs.at(12), HIST("c22etagap04ft0c"), ft0cAmp); + // fillProfile(corrconfigs.at(13), HIST("c32etagap04ft0c"), ft0cAmp); + // fillProfile(corrconfigs.at(14), HIST("c34etagap04ft0c"), ft0cAmp); + // Filling Bootstrap Samples int sampleIndex = static_cast(cfgNbootstrap * lRandom); fillProfile(corrconfigs.at(0), bootstrapArray[sampleIndex][kc22], centrality); @@ -1149,6 +1177,13 @@ struct FlowGfwTask { fillProfile(corrconfigs.at(7), bootstrapArray[sampleIndex][kc34], centrality); fillProfile(corrconfigs.at(8), bootstrapArray[sampleIndex][kc34etagap], centrality); + // fillProfile(corrconfigs.at(9), bootstrapArray[sampleIndex][kc22etagap02], centrality); + // fillProfile(corrconfigs.at(10), bootstrapArray[sampleIndex][kc32etagap02], centrality); + // fillProfile(corrconfigs.at(11), bootstrapArray[sampleIndex][kc34etagap02], centrality); + // fillProfile(corrconfigs.at(12), bootstrapArray[sampleIndex][kc22etagap04], centrality); + // fillProfile(corrconfigs.at(13), bootstrapArray[sampleIndex][kc32etagap04], centrality); + // fillProfile(corrconfigs.at(14), bootstrapArray[sampleIndex][kc34etagap04], centrality); + fillProfile(corrconfigs.at(0), bootstrapArray[sampleIndex][kc22Nch], nch); fillProfile(corrconfigs.at(1), bootstrapArray[sampleIndex][kc24Nch], nch); fillProfile(corrconfigs.at(2), bootstrapArray[sampleIndex][kc26Nch], nch); @@ -1159,16 +1194,30 @@ struct FlowGfwTask { fillProfile(corrconfigs.at(7), bootstrapArray[sampleIndex][kc34Nch], nch); fillProfile(corrconfigs.at(8), bootstrapArray[sampleIndex][kc34Nchetagap], nch); + fillProfile(corrconfigs.at(9), bootstrapArray[sampleIndex][kc22Nchetagap02], nch); + fillProfile(corrconfigs.at(10), bootstrapArray[sampleIndex][kc32Nchetagap02], nch); + fillProfile(corrconfigs.at(11), bootstrapArray[sampleIndex][kc34Nchetagap02], nch); + fillProfile(corrconfigs.at(12), bootstrapArray[sampleIndex][kc22Nchetagap04], nch); + fillProfile(corrconfigs.at(13), bootstrapArray[sampleIndex][kc32Nchetagap04], nch); + fillProfile(corrconfigs.at(14), bootstrapArray[sampleIndex][kc34Nchetagap04], nch); + if (centrality >= zero && centrality <= five) { - fillProfile(corrconfigs.at(0), bootstrapArray[sampleIndex][kc22Nch05], nch); - fillProfile(corrconfigs.at(1), bootstrapArray[sampleIndex][kc24Nch05], nch); - fillProfile(corrconfigs.at(2), bootstrapArray[sampleIndex][kc26Nch05], nch); - fillProfile(corrconfigs.at(3), bootstrapArray[sampleIndex][kc28Nch05], nch); - fillProfile(corrconfigs.at(4), bootstrapArray[sampleIndex][kc22Nch05etagap], nch); - fillProfile(corrconfigs.at(5), bootstrapArray[sampleIndex][kc32Nch05], nch); - fillProfile(corrconfigs.at(6), bootstrapArray[sampleIndex][kc32Nch05etagap], nch); - fillProfile(corrconfigs.at(7), bootstrapArray[sampleIndex][kc34Nch05], nch); - fillProfile(corrconfigs.at(8), bootstrapArray[sampleIndex][kc34Nch05etagap], nch); + // fillProfile(corrconfigs.at(0), bootstrapArray[sampleIndex][kc22Nch05], nch); + // fillProfile(corrconfigs.at(1), bootstrapArray[sampleIndex][kc24Nch05], nch); + // fillProfile(corrconfigs.at(2), bootstrapArray[sampleIndex][kc26Nch05], nch); + // fillProfile(corrconfigs.at(3), bootstrapArray[sampleIndex][kc28Nch05], nch); + // fillProfile(corrconfigs.at(4), bootstrapArray[sampleIndex][kc22Nch05etagap], nch); + // fillProfile(corrconfigs.at(5), bootstrapArray[sampleIndex][kc32Nch05], nch); + // fillProfile(corrconfigs.at(6), bootstrapArray[sampleIndex][kc32Nch05etagap], nch); + // fillProfile(corrconfigs.at(7), bootstrapArray[sampleIndex][kc34Nch05], nch); + // fillProfile(corrconfigs.at(8), bootstrapArray[sampleIndex][kc34Nch05etagap], nch); + + // fillProfile(corrconfigs.at(9), bootstrapArray[sampleIndex][kc22Nch05etagap02], nch); + // fillProfile(corrconfigs.at(10), bootstrapArray[sampleIndex][kc32Nch05etagap02], nch); + // fillProfile(corrconfigs.at(11), bootstrapArray[sampleIndex][kc34Nch05etagap02], nch); + // fillProfile(corrconfigs.at(12), bootstrapArray[sampleIndex][kc22Nch05etagap04], nch); + // fillProfile(corrconfigs.at(13), bootstrapArray[sampleIndex][kc32Nch05etagap04], nch); + // fillProfile(corrconfigs.at(14), bootstrapArray[sampleIndex][kc34Nch05etagap04], nch); registry.fill(HIST("Nch05"), nch); } @@ -1183,13 +1232,20 @@ struct FlowGfwTask { fillProfile(corrconfigs.at(7), bootstrapArray[sampleIndex][kc34ft0c], ft0cAmp); fillProfile(corrconfigs.at(8), bootstrapArray[sampleIndex][kc34etagapft0c], ft0cAmp); + // fillProfile(corrconfigs.at(9), bootstrapArray[sampleIndex][kc22etagap02ft0c], ft0cAmp); + // fillProfile(corrconfigs.at(10), bootstrapArray[sampleIndex][kc32etagap02ft0c], ft0cAmp); + // fillProfile(corrconfigs.at(11), bootstrapArray[sampleIndex][kc34etagap02ft0c], ft0cAmp); + // fillProfile(corrconfigs.at(12), bootstrapArray[sampleIndex][kc22etagap04ft0c], ft0cAmp); + // fillProfile(corrconfigs.at(13), bootstrapArray[sampleIndex][kc32etagap04ft0c], ft0cAmp); + // fillProfile(corrconfigs.at(14), bootstrapArray[sampleIndex][kc34etagap04ft0c], ft0cAmp); + // Filling Flow Container for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { fillFC(corrconfigs.at(l_ind), centrality, lRandom); } } // End of process - PROCESS_SWITCH(FlowGfwTask, processData, "Process analysis for Run 3 data", false); + PROCESS_SWITCH(FlowGfwTask, processData, "Process analysis for Run 3 data", true); using TheFilteredMyTracks = soa::Filtered; using TheFilteredMyCollisions = soa::Filtered; diff --git a/PWGCF/Flow/Tasks/flowMc.cxx b/PWGCF/Flow/Tasks/flowMc.cxx index e370a7a9847..28e1e2e49bc 100644 --- a/PWGCF/Flow/Tasks/flowMc.cxx +++ b/PWGCF/Flow/Tasks/flowMc.cxx @@ -78,7 +78,7 @@ struct FlowMc { O2_DEFINE_CONFIGURABLE(cfgFlowEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgCentVsIPTruth, std::string, "", "CCDB path to centrality vs IP truth") O2_DEFINE_CONFIGURABLE(cfgIsGlobalTrack, bool, false, "Use global tracks instead of hasTPC&&hasITS") - O2_DEFINE_CONFIGURABLE(cfgK0Lambda0Enabled, bool, true, "Add K0 and Lambda0") + O2_DEFINE_CONFIGURABLE(cfgK0Lambda0Enabled, bool, false, "Add K0 and Lambda0, for bulk particle efficiency please keep off") O2_DEFINE_CONFIGURABLE(cfgFlowCumulantEnabled, bool, false, "switch of calculating flow") O2_DEFINE_CONFIGURABLE(cfgFlowCumulantNbootstrap, int, 30, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, false, "Use track density efficiency correction") diff --git a/PWGCF/Flow/Tasks/flowSP.cxx b/PWGCF/Flow/Tasks/flowSP.cxx index 4ea5937776d..2880cd75b7b 100644 --- a/PWGCF/Flow/Tasks/flowSP.cxx +++ b/PWGCF/Flow/Tasks/flowSP.cxx @@ -69,10 +69,10 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgEvtRCTFlagCheckerLimitAcceptAsBad, bool, false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"); } rctFlags; - // struct : ConfigurableGroup { // <-- change all to evsels.Selection // event selection configurable group O2_DEFINE_CONFIGURABLE(cfgEvSelsUseAdditionalEventCut, bool, true, "Bool to enable Additional Event Cut"); O2_DEFINE_CONFIGURABLE(cfgEvSelsMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); + O2_DEFINE_CONFIGURABLE(cfgEvSelsMinOccupancy, int, 0, "Minimum occupancy of selected events"); O2_DEFINE_CONFIGURABLE(cfgEvSelsNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); O2_DEFINE_CONFIGURABLE(cfgEvSelsNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); @@ -81,7 +81,6 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgEvSelsIsVertexITSTPC, bool, true, "Selects collisions with at least one ITS-TPC track"); O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodITSLayersAll, bool, true, "Cut time intervals with dead ITS staves"); O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodITSLayer0123, bool, true, "Cut time intervals with dead ITS staves"); - // } evSels; // QA Plots O2_DEFINE_CONFIGURABLE(cfgFillEventQA, bool, false, "Fill histograms for event QA"); @@ -89,6 +88,8 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgFillPIDQA, bool, false, "Fill histograms for PID QA"); O2_DEFINE_CONFIGURABLE(cfgFillEventPlaneQA, bool, false, "Fill histograms for Event Plane QA"); O2_DEFINE_CONFIGURABLE(cfgFillQABefore, bool, false, "Fill QA histograms before cuts, only for processData"); + O2_DEFINE_CONFIGURABLE(cfgFillMeanPT, bool, false, "Fill histograms for mean PX/PT"); + O2_DEFINE_CONFIGURABLE(cfgUseCentAveragePt, bool, false, "Use in 1% centrality intervals and not ecent average"); // Flags to make and fill histograms O2_DEFINE_CONFIGURABLE(cfgFillGeneralV1Histos, bool, true, "Fill histograms for vn analysis"); O2_DEFINE_CONFIGURABLE(cfgFillMixedHarmonics, bool, true, "Flag to make and fill histos for mixed harmonics"); @@ -119,14 +120,16 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, true, "Fill NUA weights"); O2_DEFINE_CONFIGURABLE(cfgFillWeightsPOS, bool, true, "Fill NUA weights only for positive charges"); O2_DEFINE_CONFIGURABLE(cfgFillWeightsNEG, bool, true, "Fill NUA weights only for negative charges"); - O2_DEFINE_CONFIGURABLE(cfguseNUA1D, bool, false, "Use 1D NUA weights (only phi)"); - O2_DEFINE_CONFIGURABLE(cfguseNUA2D, bool, true, "Use 2D NUA weights (phi and eta)"); - O2_DEFINE_CONFIGURABLE(cfguseNUE2D, bool, true, "Use 2D NUE weights (pt and eta)"); + O2_DEFINE_CONFIGURABLE(cfgUseNUA1D, bool, false, "Use 1D NUA weights (only phi)"); + O2_DEFINE_CONFIGURABLE(cfgUseNUA2D, bool, true, "Use 2D NUA weights (phi and eta)"); + O2_DEFINE_CONFIGURABLE(cfgUseNUE2D, bool, true, "Use 2D NUE weights"); + O2_DEFINE_CONFIGURABLE(cfgUseNUE2Deta, bool, true, "Use 2D NUE weights TRUE: (pt and eta) FALSE: (pt and centrality)"); // Additional track Selections O2_DEFINE_CONFIGURABLE(cfgTrackSelsUseAdditionalTrackCut, bool, false, "Bool to enable Additional Track Cut"); O2_DEFINE_CONFIGURABLE(cfgTrackSelsDoDCApt, bool, false, "Apply Pt dependent DCAz cut"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCApt1, float, 0.1, "DcaZ < a * b / pt^1.1 -> this sets a"); - O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCApt2, float, 0.035, "DcaZ < a * b / pt^1.1 -> this sets b"); + O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCApt1, float, 0.1, "DcaZ < const + (a * b) / pt^1.1 -> this sets a"); + O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCApt2, float, 0.035, "DcaZ < const + (a * b) / pt^1.1 -> this sets b"); + O2_DEFINE_CONFIGURABLE(cfgTrackSelsDCAptConsMin, float, 0.1, "DcaZ < const + (a * b) / pt^1.1 -> this sets const"); O2_DEFINE_CONFIGURABLE(cfgTrackSelsPIDNsigma, float, 2.0, "nSigma cut for PID"); O2_DEFINE_CONFIGURABLE(cfgTrackSelDoTrackQAvsCent, bool, true, "Do track selection QA plots as function of centrality"); // harmonics for v coefficients @@ -139,21 +142,24 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/Default", "ccdb dir for NUE corrections (pt)"); O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE2D, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass5/NUE/2D", "ccdb dir for NUE 2D corrections (eta, pt)"); O2_DEFINE_CONFIGURABLE(cfgCCDBdir_centrality, std::string, "", "ccdb dir for Centrality corrections"); + O2_DEFINE_CONFIGURABLE(cfgCCDBdir_meanPt, std::string, "", "ccdb dir for Mean Pt corrections"); // Confogirable axis ConfigurableAxis axisCentrality{"axisCentrality", {20, 0, 100}, "Centrality bins for vn "}; ConfigurableAxis axisNch = {"axisNch", {400, 0, 4000}, "Global N_{ch}"}; ConfigurableAxis axisMultpv = {"axisMultpv", {400, 0, 4000}, "N_{ch} (PV)"}; // Configurables containing vector - Configurable> cfgEvSelsMultPv{"cfgEvSelsMultPv", std::vector{2228.05, -75.5988, 0.976695, -0.00585275, 1.40738e-05, 3795.65, -136.988, 2.12393, -0.017028, 5.78679e-05}, "Multiplicity cuts (PV) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; - Configurable> cfgEvSelsMult{"cfgEvSelsMult", std::vector{1308.86, -41.9314, 0.488423, -0.00248178, 4.71554e-06, 2973.55, -103.092, 1.47673, -0.0106685, 3.29348e-05}, "Multiplicity cuts (Global) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; + Configurable> cfgEvSelsMultPv{"cfgEvSelsMultPv", std::vector{2223.49, -75.1444, 0.963572, -0.00570399, 1.34877e-05, 3790.99, -137.064, 2.13044, -0.017122, 5.82834e-05}, "Multiplicity cuts (PV) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; + Configurable> cfgEvSelsMult{"cfgEvSelsMult", std::vector{1301.56, -41.4615, 0.478224, -0.00239449, 4.46966e-06, 2967.6, -102.927, 1.47488, -0.0106534, 3.28622e-05}, "Multiplicity cuts (Global) first 5 parameters cutLOW last 5 cutHIGH (Default is +-2sigma pass5) "}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgEvSelsVtxZ; Filter trackFilter = nabs(aod::track::eta) < cfgTrackSelsEta && aod::track::pt > cfgTrackSelsPtmin&& aod::track::pt < cfgTrackSelsPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && nabs(aod::track::dcaXY) < cfgTrackSelsDCAxy&& nabs(aod::track::dcaZ) < cfgTrackSelsDCAz; Filter trackFilterMC = nabs(aod::mcparticle::eta) < cfgTrackSelsEta && aod::mcparticle::pt > cfgTrackSelsPtmin&& aod::mcparticle::pt < cfgTrackSelsPtmax; using GeneralCollisions = soa::Join; - using UnfilteredTracks = soa::Join; + using UnfilteredTracksPID = soa::Join; + using UnfilteredTracks = soa::Join; using UsedTracks = soa::Filtered; + using UsedTracksPID = soa::Filtered; using ZDCCollisions = soa::Filtered>; // For MC Reco and Gen @@ -187,10 +193,12 @@ struct FlowSP { TProfile* hcorrQQy = nullptr; TProfile* hEvPlaneRes = nullptr; TH1D* hCentrality = nullptr; + TProfile2D* hMeanPt = nullptr; bool clQQ = false; bool clEvPlaneRes = false; bool clCentrality = false; + bool clMeanPt = false; } cfg; @@ -198,6 +206,7 @@ struct FlowSP { std::vector> wacc = {{{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}, {{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}, {{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}}; // int for part species, float for weight vector for kIncl, kPos, kNeg std::vector> weff = {{{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}, {{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}, {{0, 1.0}, {1, 1.0}, {2, 1.0}, {3, 1.0}}}; // int for part species, float for weight vector for kIncl, kPos, kNeg double centWeight = 1.0; + double meanPtWeight = 1.0; double ux = 0; double uy = 0; double uxMH = 0; @@ -218,6 +227,14 @@ struct FlowSP { double vy = 0; double vz = 0; int charge = 0; + double relPt = 1.; + double psiA = 0; + double psiC = 0; + double psiFull = 0; + double trackPxA = 0; + double trackPxC = 0; + double meanPxA = 0; + double meanPxC = 0; } spm; OutputObj fWeights{GFWWeights("weights")}; @@ -328,6 +345,8 @@ struct FlowSP { AxisSpec axisNsigma = {100, -10, 10, "Nsigma for TPC and TOF"}; AxisSpec axisdEdx = {300, 0, 300, "dEdx for PID"}; AxisSpec axisBeta = {150, 0, 1.5, "Beta for PID"}; + AxisSpec axisCharge = {3, 0, 3, "Charge: 0 = inclusive, 1 = positive, 2 = negative"}; + AxisSpec axisPx = {1000, -0.05, 0.05, "p_{x} (GeV/c)"}; std::vector ptbinning = {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}; AxisSpec axisPt = {ptbinning, "#it{p}_{T} GeV/#it{c}"}; @@ -336,6 +355,8 @@ struct FlowSP { rctChecker.init(rctFlags.cfgEvtRCTFlagCheckerLabel, rctFlags.cfgEvtRCTFlagCheckerZDCCheck, rctFlags.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + histos.add("hCentrality", "Centrality; Centrality (%); ", {HistType::kTH1D, {axisCent}}); + histos.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_FilteredEvent + 1, "Filtered events"); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_RCTFlagsZDC + 1, "RCT Flags ZDC"); @@ -410,6 +431,7 @@ struct FlowSP { histos.add("QA/after/PsiA_vs_Vz", "", {HistType::kTH2D, {axisPhiPlane, axisVz}}); histos.add("QA/after/PsiC_vs_Vz", "", {HistType::kTH2D, {axisPhiPlane, axisVz}}); histos.add("QA/after/PsiFull_vs_Vz", "", {HistType::kTH2D, {axisPhiPlane, axisVz}}); + // histos.add("QA/after/DeltaPsivsPx", "", {HistType::kTH3D, {axisCent, axisPhiPlane, axisPx}}); } if (cfgFillQABefore) { @@ -417,7 +439,7 @@ struct FlowSP { } } - if (doprocessData || doprocessMCReco) { + if (doprocessData || doprocessMCReco || doprocessDataPID) { if (cfgFillTrackQA) { histos.add("incl/QA/after/pt_phi", "", {HistType::kTH2D, {axisPt, axisPhiMod}}); @@ -428,6 +450,7 @@ struct FlowSP { histos.add("incl/QA/after/hSharedClusters_pt", "", {HistType::kTH2D, {axisPt, axisShCl}}); histos.add("incl/QA/after/hCrossedRows_pt", "", {HistType::kTH2D, {axisPt, axisCl}}); histos.add("incl/QA/after/hCrossedRows_vs_SharedClusters", "", {HistType::kTH2D, {axisCl, axisShCl}}); + histos.add("incl/QA/after/hMeanPtEta", "", {HistType::kTProfile2D, {axisEta, axisCent}}); if (cfgTrackSelDoTrackQAvsCent) { histos.add("incl/QA/after/hPt_Eta", "", kTH3D, {axisPt, axisEta, axisCent}); @@ -443,7 +466,7 @@ struct FlowSP { histos.addClone("incl/QA/after/", "incl/QA/before/"); } - if (cfgFillPIDQA) { + if (cfgFillPIDQA && doprocessDataPID) { histos.add("hPIDcounts", "", kTH2D, {{{4, 0, 4}, axisPt}}); histos.get(HIST("hPIDcounts"))->GetXaxis()->SetBinLabel(1, "UFO"); histos.get(HIST("hPIDcounts"))->GetXaxis()->SetBinLabel(2, "Pion"); @@ -483,6 +506,10 @@ struct FlowSP { histos.addClone("incl/pion/", "incl/proton/"); } + if (cfgFillEventQA) { + histos.add("QA/hCentFull", " ; Centrality (%); ", {HistType::kTH1D, {axisCent}}); + } + if (doprocessMCReco) { registry.add("trackMCReco/after/hIsPhysicalPrimary", "", {HistType::kTH2D, {{2, 0, 2}, axisCentrality}}); registry.add("trackMCReco/hTrackSize_unFiltered", "", {HistType::kTH2D, {{100, 0, 200000}, axisCentrality}}); @@ -498,6 +525,7 @@ struct FlowSP { registry.addClone("trackMCReco/after/incl/", "trackMCReco/after/neg/"); registry.addClone("trackMCReco/after/", "trackMCReco/before/"); } + if (doprocessData) { registry.add("QQCorrelations/qAqCX", "", kTProfile, {axisCent}); registry.add("QQCorrelations/qAqCY", "", kTProfile, {axisCent}); @@ -508,42 +536,47 @@ struct FlowSP { if (cfgFillGeneralV1Histos) { // track properties per centrality and per eta, pt bin + registry.add("incl/vnCodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnAodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnC", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnA", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnCSetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnASetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); } - if (cfgFillPID) { - registry.add("incl/pion/vnC", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/vnA", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + if (cfgFillMeanPT) { + registry.add("incl/meanPT/meanRelPtA", "", kTProfile2D, {axisEtaVn, axisCentrality}); + registry.add("incl/meanPT/meanRelPtC", "", kTProfile2D, {axisEtaVn, axisCentrality}); - if (cfgFillEventPlane) { - registry.add("incl/pion/vnA_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/vnC_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/vnFull_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - } + registry.add("incl/meanPT/hMeanPtEtaCent", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1A", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1Aodd", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1Codd", "", kTProfile2D, {axisEtaVn, axisCent}); + registry.add("incl/meanPT/hMeanPtCent", "", kTProfile, {axisCent}); + + registry.add("incl/meanPT/ptV1A3D", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C3D", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + + registry.add("incl/meanPT/ptV1A3Dx", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C3Dx", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + + registry.add("incl/meanPT/ptV1A3Dy", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + registry.add("incl/meanPT/ptV1C3Dy", "", kTProfile3D, {axisPt, axisEtaVn, axisCent}); + + registry.add("incl/meanPT/meanPxA", "", kTH3D, {axisCent, axisPhiPlane, axisPx}); + registry.add("incl/meanPT/meanPxC", "", kTH3D, {axisCent, axisPhiPlane, axisPx}); } if (cfgFillXandYterms) { registry.add("incl/vnAx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnAy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnCx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/vnCy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - if (cfgFillPID) { - registry.add("incl/pion/vnAx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/vnAy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/vnCx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/vnCy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - } } if (cfgFillMixedHarmonics) { registry.add("incl/MH/vnAxCxUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/MH/vnAyCyUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/MH/vnAxCyUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); registry.add("incl/MH/vnAyCxUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - if (cfgFillPID) { - registry.add("incl/pion/MH/vnAxCxUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/MH/vnAyCyUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/MH/vnAxCyUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - registry.add("incl/pion/MH/vnAyCxUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); - } } if (cfgFillEventPlane) { registry.add("incl/vnA_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); @@ -560,21 +593,53 @@ struct FlowSP { histos.add("QA/hCosPhiASinsPhiC", "hCosPhiASinsPhiC; Centrality(%); #LT Cos(#Psi^{A})Sin(#Psi^{C})#GT", kTProfile, {axisCent}); histos.add("QA/hFullEvPlaneRes", "hFullEvPlaneRes; Centrality(%); -#LT Cos(#Psi^{A} - #Psi^{C})#GT ", kTProfile, {axisCent}); } - if (cfgFillEventQA) { - histos.add("QA/hCentFull", " ; Centrality (%); ", {HistType::kTH1D, {axisCent}}); - } - } // end of doprocessData - if (cfgFillChargeDependence || cfgFillPID) { - registry.addClone("incl/pion/", "incl/proton/"); - registry.addClone("incl/pion/", "incl/kaon/"); + + } // end of doProcessData + + if (cfgFillChargeDependence || cfgFillChargeDependenceQA) { + LOGF(info, "Cloning charge dependence histograms"); registry.addClone("incl/", "pos/"); registry.addClone("incl/", "neg/"); - } - if (cfgFillPIDQA || cfgFillChargeDependenceQA) { + histos.addClone("incl/", "pos/"); histos.addClone("incl/", "neg/"); } + if (doprocessDataPID) { + if (cfgFillGeneralV1Histos) { + registry.add("incl/pion/vnCodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnAodd", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnC", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnA", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnCSetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/vnASetPlane", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + } + + if (cfgFillEventPlane) { + registry.add("incl/pion/vnA_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnC_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnFull_EP", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + } + if (cfgFillXandYterms) { + registry.add("incl/pion/vnAx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnAy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnCx", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/vnCy", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + } + if (cfgFillMixedHarmonics) { + registry.add("incl/pion/MH/vnAxCxUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/MH/vnAyCyUx_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/MH/vnAxCyUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + registry.add("incl/pion/MH/vnAyCxUy_MH", "", kTProfile3D, {axisPt, axisEtaVn, axisCentrality}); + } + registry.addClone("incl/pion/", "incl/proton/"); + registry.addClone("incl/pion/", "incl/kaon/"); + if (cfgFillChargeDependence) { + registry.addClone("incl/", "pos/"); + registry.addClone("incl/", "neg/"); + } + } + } else if (doprocessMCGen) { registry.add("trackMCGen/nCollReconstructedPerMcCollision", "", {HistType::kTH1D, {{10, -5, 5}}}); registry.add("trackMCGen/after/incl/hPt_hadron", "", {HistType::kTH3D, {axisPt, axisEta, axisCentrality}}); @@ -710,7 +775,7 @@ struct FlowSP { int nWeights = 3; - if (cfguseNUA1D) { + if (cfgUseNUA1D) { if (cfgCCDB_NUA.value.empty() == false) { TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights"))); @@ -724,7 +789,7 @@ struct FlowSP { } else { LOGF(info, "cfgCCDB_NUA empty! No corrections loaded"); } - } else if (cfguseNUA2D) { + } else if (cfgUseNUA2D) { if (cfgCCDB_NUA.value.empty() == false) { TH3D* hNUA2D = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); if (!hNUA2D) { @@ -754,9 +819,9 @@ struct FlowSP { // Get Efficiency correction if (cfgCCDB_NUE2D.value.empty() == false) { TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUE2D, timestamp); - cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency2D"))); - cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency2D_pos"))); - cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency2D_neg"))); + cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); + cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_pos"))); + cfg.mEfficiency2D.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency_neg"))); int sizeEff = cfg.mEfficiency2D.size(); if (sizeEff < nWeights) LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCCDB_NUE.value.c_str()); @@ -769,14 +834,21 @@ struct FlowSP { } // From Generic Framework - bool setCurrentParticleWeights(int pID, int spec, const float& phi, const float& eta, const float& pt, const float& vtxz) + bool setCurrentParticleWeights(int pID, int spec, const float& phi, const float& eta, const float& pt, const float& vtxz, const float& centrality) { float eff = 1.; int sizeEff = cfg.mEfficiency.size(); if (sizeEff > pID) { - if (cfguseNUE2D) { - int binx = cfg.mEfficiency2D[pID]->GetXaxis()->FindBin(eta); - int biny = cfg.mEfficiency2D[pID]->GetYaxis()->FindBin(pt); + if (cfgUseNUE2D) { + int binx; + int biny; + if (cfgUseNUE2Deta) { + biny = cfg.mEfficiency2D[pID]->GetYaxis()->FindBin(pt); + binx = cfg.mEfficiency2D[pID]->GetXaxis()->FindBin(eta); + } else { + binx = cfg.mEfficiency2D[pID]->GetXaxis()->FindBin(pt); + biny = cfg.mEfficiency2D[pID]->GetYaxis()->FindBin(centrality); + } eff = cfg.mEfficiency2D[pID]->GetBinContent(binx, biny); } else { eff = cfg.mEfficiency[pID]->GetBinContent(cfg.mEfficiency[pID]->FindBin(pt)); @@ -789,14 +861,14 @@ struct FlowSP { spm.weff[pID][spec] = 1. / eff; - if (cfguseNUA1D) { + if (cfgUseNUA1D) { int sizeAcc = cfg.mAcceptance.size(); if (sizeAcc > pID) { spm.wacc[pID][spec] = cfg.mAcceptance[pID]->getNUA(phi, eta, vtxz); } else { spm.wacc[pID][spec] = 1; } - } else if (cfguseNUA2D) { + } else if (cfgUseNUA2D) { if (cfg.mAcceptance2D.size() > 0) { spm.wacc[pID][spec] = getNUA2D(cfg.mAcceptance2D[0], eta, phi, vtxz); } else { @@ -820,7 +892,7 @@ struct FlowSP { // Occupancy if (cfgEvSelsDoOccupancySel) { auto occupancy = collision.trackOccupancyInTimeRange(); - if (occupancy > cfgEvSelsMaxOccupancy) { + if (occupancy > cfgEvSelsMaxOccupancy || occupancy < cfgEvSelsMinOccupancy) { return 0; } histos.fill(HIST("hEventCount"), evSel_occupancy); @@ -929,12 +1001,12 @@ struct FlowSP { if (track.dcaZ() > cfgTrackSelsDCAz) return false; - if (cfgTrackSelsDoDCApt && std::fabs(track.dcaZ()) > (cfgTrackSelsDCApt1 * cfgTrackSelsDCApt2) / (std::pow(track.pt(), 1.1))) + if (cfgTrackSelsDoDCApt && std::fabs(track.dcaZ()) > (cfgTrackSelsDCAptConsMin + (cfgTrackSelsDCApt1 * cfgTrackSelsDCApt2) / (std::pow(track.pt(), 1.1)))) return false; histos.fill(HIST("hTrackCount"), trackSel_DCAz); - if (track.tpcNClsFound() < cfgTrackSelsNcls) + if (track.tpcNClsCrossedRows() < cfgTrackSelsNcls) return false; histos.fill(HIST("hTrackCount"), trackSel_NCls); @@ -1007,6 +1079,7 @@ struct FlowSP { histos.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/PsiA_vs_Vz"), psiA, collision.posZ(), spm.centWeight); histos.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/PsiC_vs_Vz"), psiC, collision.posZ(), spm.centWeight); histos.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/PsiFull_vs_Vz"), psiFull, collision.posZ(), spm.centWeight); + // histos.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/DeltaPsivsPx"), spm.centrality, psiA - psiC - constants::math::PI, track.px(), spm.centWeight); } } return; @@ -1016,10 +1089,18 @@ struct FlowSP { inline void fillHistograms(TrackObject track) { double weight = spm.wacc[ct][pt] * spm.weff[ct][pt] * spm.centWeight; + int scale = 1.0; + int minusQ = -1.0; + if (track.eta() < 0) + scale = -1.0; if (cfgFillGeneralV1Histos) { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnAodd"), track.pt(), track.eta(), spm.centrality, scale * (spm.uy * spm.qyA + spm.ux * spm.qxA) / std::sqrt(std::fabs(spm.corrQQ)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnCodd"), track.pt(), track.eta(), spm.centrality, scale * (spm.uy * spm.qyC + spm.ux * spm.qxC) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnA"), track.pt(), track.eta(), spm.centrality, (spm.uy * spm.qyA + spm.ux * spm.qxA) / std::sqrt(std::fabs(spm.corrQQ)), weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnC"), track.pt(), track.eta(), spm.centrality, (spm.uy * spm.qyC + spm.ux * spm.qxC) / std::sqrt(std::fabs(spm.corrQQ)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnCSetPlane"), track.pt(), track.eta(), spm.centrality, (spm.uy + spm.ux) / std::sqrt(std::fabs(spm.corrQQ)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnASetPlane"), track.pt(), track.eta(), spm.centrality, (minusQ * spm.ux - spm.uy) / std::sqrt(std::fabs(spm.corrQQ)), weight); } if (cfgFillMixedHarmonics) { @@ -1041,6 +1122,25 @@ struct FlowSP { registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnC_EP"), track.pt(), track.eta(), spm.centrality, spm.vnC, weight); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("vnFull_EP"), track.pt(), track.eta(), spm.centrality, spm.vnFull, weight); } + + if (cfgFillMeanPT) { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/hMeanPtEtaCent"), track.eta(), spm.centrality, track.pt(), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/hMeanPtCent"), spm.centrality, track.pt(), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A"), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C"), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1Aodd"), track.eta(), spm.centrality, track.pt() * scale * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1Codd"), track.eta(), spm.centrality, track.pt() * scale * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3D"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3D"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)), weight); + + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3Dx"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQx)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3Dx"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQx)) * spm.meanPtWeight)), weight); + + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1A3Dy"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyA) / (std::sqrt(std::fabs(spm.corrQQy)) * spm.meanPtWeight)), weight); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("meanPT/ptV1C3Dy"), track.pt(), track.eta(), spm.centrality, track.pt() * ((spm.uy * spm.qyC) / (std::sqrt(std::fabs(spm.corrQQy)) * spm.meanPtWeight)), weight); + } } template @@ -1066,24 +1166,26 @@ struct FlowSP { histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAxy_pt"), track.pt(), track.dcaXY(), spm.wacc[ct][par] * spm.weff[ct][par]); histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAz_pt"), track.pt(), track.dcaZ(), spm.wacc[ct][par] * spm.weff[ct][par]); histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hSharedClusters_pt"), track.pt(), track.tpcFractionSharedCls(), spm.wacc[ct][par] * spm.weff[ct][par]); - histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hCrossedRows_pt"), track.pt(), track.tpcNClsFound(), spm.wacc[ct][par] * spm.weff[ct][par]); - histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hCrossedRows_vs_SharedClusters"), track.tpcNClsFound(), track.tpcFractionSharedCls(), spm.wacc[ct][par] * spm.weff[ct][par]); + histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hCrossedRows_pt"), track.pt(), track.tpcNClsCrossedRows(), spm.wacc[ct][par] * spm.weff[ct][par]); + histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hCrossedRows_vs_SharedClusters"), track.tpcNClsCrossedRows(), track.tpcFractionSharedCls(), spm.wacc[ct][par] * spm.weff[ct][par]); + histos.fill(HIST(Charge[ct]) + HIST(Species[par]) + HIST("QA/") + HIST(Time[ft]) + HIST("hMeanPtEta"), track.eta(), spm.centrality, track.pt(), spm.wacc[ct][par] * spm.weff[ct][par]); } template inline void fillPIDQA(TrackObject track) { - if (!cfgFillPIDQA || !cfgFillTrackQA) + if (!cfgFillTrackQA) return; - - histos.fill(HIST(Charge[ct]) + HIST("pion/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaPi()); - histos.fill(HIST(Charge[ct]) + HIST("pion/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTPC_pt"), track.pt(), track.tpcNSigmaPi()); - histos.fill(HIST(Charge[ct]) + HIST("kaon/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaKa()); - histos.fill(HIST(Charge[ct]) + HIST("kaon/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTPC_pt"), track.pt(), track.tpcNSigmaKa()); - histos.fill(HIST(Charge[ct]) + HIST("proton/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaPr()); - histos.fill(HIST(Charge[ct]) + HIST("proton/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTPC_pt"), track.pt(), track.tpcNSigmaPr()); - histos.fill(HIST(Charge[ct]) + HIST("QA/") + HIST(Time[ft]) + HIST("hdEdxTPC_pt"), track.pt(), track.tpcSignal()); - histos.fill(HIST(Charge[ct]) + HIST("QA/") + HIST(Time[ft]) + HIST("hBetaTOF_pt"), track.pt(), track.beta()); + if constexpr (framework::has_type_v) { + histos.fill(HIST(Charge[ct]) + HIST("pion/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaPi()); + histos.fill(HIST(Charge[ct]) + HIST("pion/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTPC_pt"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST(Charge[ct]) + HIST("kaon/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaKa()); + histos.fill(HIST(Charge[ct]) + HIST("kaon/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTPC_pt"), track.pt(), track.tpcNSigmaKa()); + histos.fill(HIST(Charge[ct]) + HIST("proton/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTOF_pt"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST(Charge[ct]) + HIST("proton/") + HIST("QA/") + HIST(Time[ft]) + HIST("hNsigmaTPC_pt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST(Charge[ct]) + HIST("QA/") + HIST(Time[ft]) + HIST("hdEdxTPC_pt"), track.pt(), track.tpcSignal()); + histos.fill(HIST(Charge[ct]) + HIST("QA/") + HIST(Time[ft]) + HIST("hBetaTOF_pt"), track.pt(), track.beta()); + } } template @@ -1196,6 +1298,9 @@ struct FlowSP { return; histos.fill(HIST("hEventCount"), evSel_isSelectedZDC); + // Always fill centrality histogram after event selections! + histos.fill(HIST("hCentrality"), spm.centrality); + spm.qxA = collision.qxA(); spm.qyA = collision.qyA(); spm.qxC = collision.qxC(); @@ -1204,11 +1309,11 @@ struct FlowSP { spm.vz = collision.posZ(); float vtxz = collision.posZ(); - double psiA = 1.0 * std::atan2(spm.qyA, spm.qxA); - double psiC = 1.0 * std::atan2(spm.qyC, spm.qxC); + spm.psiA = 1.0 * std::atan2(spm.qyA, spm.qxA); + spm.psiC = 1.0 * std::atan2(spm.qyC, spm.qxC); // https://twiki.cern.ch/twiki/pub/ALICE/DirectedFlowAnalysisNote/vn_ZDC_ALICE_INT_NOTE_version02.pdf - double psiFull = 1.0 * std::atan2(spm.qyA + spm.qyC, spm.qxA + spm.qxC); + spm.psiFull = 1.0 * std::atan2(spm.qyA + spm.qyC, spm.qxA + spm.qxC); // always fill these histograms! registry.fill(HIST("QQCorrelations/qAqCXY"), spm.centrality, spm.qxA * spm.qxC + spm.qyA * spm.qyC); @@ -1222,14 +1327,14 @@ struct FlowSP { histos.fill(HIST("QA/hCentFull"), spm.centrality, 1); } if (cfgFillEventPlaneQA) { - histos.fill(HIST("QA/hSPplaneA"), psiA, 1); - histos.fill(HIST("QA/hSPplaneC"), psiC, 1); - histos.fill(HIST("QA/hSPplaneFull"), psiFull, 1); - histos.fill(HIST("QA/hCosPhiACosPhiC"), spm.centrality, std::cos(psiA) * std::cos(psiC)); - histos.fill(HIST("QA/hSinPhiASinPhiC"), spm.centrality, std::sin(psiA) * std::sin(psiC)); - histos.fill(HIST("QA/hSinPhiACosPhiC"), spm.centrality, std::sin(psiA) * std::cos(psiC)); - histos.fill(HIST("QA/hCosPhiASinsPhiC"), spm.centrality, std::cos(psiA) * std::sin(psiC)); - histos.fill(HIST("QA/hFullEvPlaneRes"), spm.centrality, -1 * std::cos(psiA - psiC)); + histos.fill(HIST("QA/hSPplaneA"), spm.psiA, 1); + histos.fill(HIST("QA/hSPplaneC"), spm.psiC, 1); + histos.fill(HIST("QA/hSPplaneFull"), spm.psiFull, 1); + histos.fill(HIST("QA/hCosPhiACosPhiC"), spm.centrality, std::cos(spm.psiA) * std::cos(spm.psiC)); + histos.fill(HIST("QA/hSinPhiASinPhiC"), spm.centrality, std::sin(spm.psiA) * std::sin(spm.psiC)); + histos.fill(HIST("QA/hSinPhiACosPhiC"), spm.centrality, std::sin(spm.psiA) * std::cos(spm.psiC)); + histos.fill(HIST("QA/hCosPhiASinsPhiC"), spm.centrality, std::cos(spm.psiA) * std::sin(spm.psiC)); + histos.fill(HIST("QA/hFullEvPlaneRes"), spm.centrality, -1 * std::cos(spm.psiA - spm.psiC)); } if (spm.centrality > cfgCentMax || spm.centrality < cfgCentMin) @@ -1266,24 +1371,41 @@ struct FlowSP { evPlaneRes = std::sqrt(evPlaneRes); } + spm.centWeight = 1.; if (cfgCCDBdir_centrality.value.empty() == false) { if (!cfg.clCentrality) { cfg.hCentrality = ccdb->getForTimeStamp(cfgCCDBdir_centrality.value, bc.timestamp()); cfg.clCentrality = true; } - spm.centWeight = cfg.hCentrality->GetBinContent(cfg.hCentrality->FindBin(spm.centrality)); - if (spm.centWeight < 0) - LOGF(fatal, "Centrality weight cannot be negative.. abort for (%.2f)", spm.centrality); + double centW = cfg.hCentrality->GetBinContent(cfg.hCentrality->FindBin(spm.centrality)); + if (centW < 0) { + spm.centWeight = 1. / centW; + } else { + LOGF(fatal, "Centrality weight cannot be negative .. setting to 0. for (%.2f)", spm.centrality); + spm.centWeight = 0.; + } } fillEventQA(collision, tracks); - for (const auto& track : tracks) { + TProfile* meanPTMap = new TProfile("meanPTMap", "meanPTMap", 8, -0.8, 0.8); + TProfile* meanPTMapPos = new TProfile("meanPTMapPos", "meanPTMapPos", 8, -0.8, 0.8); + TProfile* meanPTMapNeg = new TProfile("meanPTMapNeg", "meanPTMapNeg", 8, -0.8, 0.8); - ParticleType trackPID = (cfgFillPID || cfgFillPIDQA) ? getTrackPID(track) : kUnidentified; + TProfile* relPxA = new TProfile("relPxA", "relPxA", 8, -0.8, 0.8); + TProfile* relPxC = new TProfile("relPxC", "relPxC", 8, -0.8, 0.8); + + TProfile* relPxANeg = new TProfile("relPxANeg", "relPxANeg", 8, -0.8, 0.8); + TProfile* relPxAPos = new TProfile("relPxAPos", "relPxAPos", 8, -0.8, 0.8); + + TProfile* relPxCNeg = new TProfile("relPxCNeg", "relPxCNeg", 8, -0.8, 0.8); + TProfile* relPxCPos = new TProfile("relPxCPos", "relPxCPos", 8, -0.8, 0.8); + + double sumPxAEvent = 0; + int meanPxEventCount = 0; + double sumPxCEvent = 0; - if (cfgFillPIDQA) - histos.fill(HIST("hPIDcounts"), trackPID, track.pt()); + for (const auto& track : tracks) { if (track.sign() == 0) continue; @@ -1294,26 +1416,28 @@ struct FlowSP { if (cfgFillQABefore) { fillAllQA(track); - if (cfgFillPIDQA) { - switch (trackPID) { - case kPions: - fillAllQA(track); - break; - case kKaons: - fillAllQA(track); - break; - case kProtons: - fillAllQA(track); - break; - default: /* do nothing */ - break; - } - } } if (!trackSelected(track, field)) continue; + spm.meanPtWeight = 1.0; + if (cfgCCDBdir_meanPt.value.empty() == false) { + if (!cfg.clMeanPt) { + cfg.hMeanPt = ccdb->getForTimeStamp(cfgCCDBdir_meanPt.value, bc.timestamp()); + cfg.clMeanPt = true; + } + int etaBin = cfg.hMeanPt->GetXaxis()->FindBin(track.eta()); + int centBin = cfg.hMeanPt->GetYaxis()->FindBin(spm.centrality); + double weight = cfg.hMeanPt->GetBinContent(etaBin, centBin); + if (weight > 0) { + spm.meanPtWeight = 1.0 / weight; + } else { + LOGF(info, "MeanPt cannot be negative or 0.. (weight = 1/meanPt) -> setting to 0. for (%.2f, %.2f)", track.eta(), spm.centrality); + spm.meanPtWeight = 0.0; + } + } + // constrain angle to 0 -> [0,0+2pi] auto phi = RecoDecay::constrainAngle(track.phi(), 0); @@ -1333,29 +1457,14 @@ struct FlowSP { } // Set weff and wacc for inclusive, negative and positive hadrons - if (!setCurrentParticleWeights(kInclusive, kUnidentified, phi, track.eta(), track.pt(), vtxz)) + if (!setCurrentParticleWeights(kInclusive, kUnidentified, phi, track.eta(), track.pt(), vtxz, spm.centrality)) continue; - if (!setCurrentParticleWeights(spm.charge, kUnidentified, phi, track.eta(), track.pt(), vtxz)) + if (!setCurrentParticleWeights(spm.charge, kUnidentified, phi, track.eta(), track.pt(), vtxz, spm.centrality)) continue; histos.fill(HIST("hTrackCount"), trackSel_ParticleWeights); fillAllQA(track); - if (cfgFillPIDQA) { - switch (trackPID) { - case kPions: - fillAllQA(track); - break; - case kKaons: - fillAllQA(track); - break; - case kProtons: - fillAllQA(track); - break; - default: /* do nothing */ - break; - } - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spm.ux = std::cos(cfgHarm * phi); @@ -1365,9 +1474,14 @@ struct FlowSP { spm.uyMH = std::sin(cfgHarmMixed * phi); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spm.vnA = std::cos(cfgHarm * (phi - psiA)) / evPlaneRes; - spm.vnC = std::cos(cfgHarm * (phi - psiC)) / evPlaneRes; - spm.vnFull = std::cos(cfgHarm * (phi - psiFull)) / evPlaneRes; + spm.vnA = std::cos(cfgHarm * (phi - spm.psiA)) / evPlaneRes; + spm.vnC = std::cos(cfgHarm * (phi - spm.psiC)) / evPlaneRes; + spm.vnFull = std::cos(cfgHarm * (phi - spm.psiFull)) / evPlaneRes; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + spm.meanPxA = track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)); + spm.meanPxC = track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / (std::sqrt(std::fabs(spm.corrQQ)) * spm.meanPtWeight)); fillHistograms(track); @@ -1382,62 +1496,310 @@ struct FlowSP { } } - if (cfgFillPID) { + double drelPxA = track.pt() * ((spm.uy * spm.qyA + spm.ux * spm.qxA) / std::sqrt(std::fabs(spm.corrQQ))); + double drelPxC = track.pt() * ((spm.uy * spm.qyC + spm.ux * spm.qxC) / std::sqrt(std::fabs(spm.corrQQ))); + + double weightIncl = spm.wacc[kInclusive][kUnidentified] * spm.weff[kInclusive][kUnidentified] * spm.centWeight; + double weightPos = spm.wacc[kPositive][kUnidentified] * spm.weff[kPositive][kUnidentified] * spm.centWeight; + double weightNeg = spm.wacc[kNegative][kUnidentified] * spm.weff[kNegative][kUnidentified] * spm.centWeight; + + sumPxAEvent += spm.meanPxA * weightIncl; + sumPxCEvent += spm.meanPxC * weightIncl; + meanPxEventCount += weightIncl; + + meanPTMap->Fill(track.eta(), track.pt(), weightIncl); + relPxA->Fill(track.eta(), drelPxA, weightIncl); + relPxC->Fill(track.eta(), drelPxC, weightIncl); + + if (spm.charge == kPositive) { + meanPTMapPos->Fill(track.eta(), track.pt(), weightPos); + relPxAPos->Fill(track.eta(), drelPxA, weightPos); + relPxCPos->Fill(track.eta(), drelPxC, weightPos); + } + + if (spm.charge == kNegative) { + meanPTMapNeg->Fill(track.eta(), track.pt(), weightNeg); + relPxANeg->Fill(track.eta(), drelPxA, weightNeg); + relPxCNeg->Fill(track.eta(), drelPxC, weightNeg); + } + + } // end of track loop + + double meanPxAEvent = sumPxAEvent / meanPxEventCount; + double meanPxCEvent = sumPxCEvent / meanPxEventCount; + + registry.fill(HIST("incl/meanPT/meanPxA"), spm.centrality, spm.psiA - spm.psiC, meanPxAEvent); + registry.fill(HIST("incl/meanPT/meanPxC"), spm.centrality, spm.psiA - spm.psiC, meanPxCEvent); + + // Now we want to fill the final relPt histogram + // Loop over all eta and fill bins + if (cfgFillMeanPT) { + int nBinsEta = 8; + for (int etabin = 1; etabin <= nBinsEta; etabin++) { + // eta bin is 1 --> Find centbin!! + double eta = meanPTMap->GetXaxis()->GetBinCenter(etabin); + double meanPt = meanPTMap->GetBinContent(etabin); + double meanPtPos = meanPTMapPos->GetBinContent(etabin); + double meanPtNeg = meanPTMapNeg->GetBinContent(etabin); + + double drelPxA = relPxA->GetBinContent(etabin); + double drelPxANeg = relPxANeg->GetBinContent(etabin); + double drelPxAPos = relPxAPos->GetBinContent(etabin); + + double drelPxC = relPxC->GetBinContent(etabin); + double drelPxCNeg = relPxCNeg->GetBinContent(etabin); + double drelPxCPos = relPxCPos->GetBinContent(etabin); + + if (meanPt != 0) { + registry.fill(HIST("incl/meanPT/meanRelPtA"), eta, spm.centrality, drelPxA / meanPt, spm.centWeight); + registry.fill(HIST("incl/meanPT/meanRelPtC"), eta, spm.centrality, drelPxC / meanPt, spm.centWeight); + + if (cfgFillChargeDependence) { + registry.fill(HIST("neg/meanPT/meanRelPtA"), eta, spm.centrality, drelPxANeg / meanPtNeg, spm.centWeight); + registry.fill(HIST("pos/meanPT/meanRelPtA"), eta, spm.centrality, drelPxAPos / meanPtPos, spm.centWeight); + registry.fill(HIST("neg/meanPT/meanRelPtC"), eta, spm.centrality, drelPxCNeg / meanPtNeg, spm.centWeight); + registry.fill(HIST("pos/meanPT/meanRelPtC"), eta, spm.centrality, drelPxCPos / meanPtPos, spm.centWeight); + } + } + } + } + + delete meanPTMap; + delete meanPTMapPos; + delete meanPTMapNeg; + delete relPxA; + delete relPxANeg; + delete relPxAPos; + delete relPxC; + delete relPxCNeg; + delete relPxCPos; + } + + PROCESS_SWITCH(FlowSP, processData, "Process analysis for non-derived data", true); + + void processDataPID(ZDCCollisions::iterator const& collision, aod::BCsWithTimestamps const&, UsedTracksPID const& tracks) + { + + histos.fill(HIST("hEventCount"), evSel_FilteredEvent); + auto bc = collision.bc_as(); + int standardMagField = 99999; + auto field = (cfgMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfgMagField; + + if (bc.runNumber() != cfg.lastRunNumber) { + cfg.correctionsLoaded = false; + cfg.clCentrality = false; + cfg.lastRunNumber = bc.runNumber(); + cfg.mAcceptance.clear(); + LOGF(info, "Size of mAcceptance: %i (should be 0)", (int)cfg.mAcceptance.size()); + } + + if (cfgFillQABefore) + fillEventQA(collision, tracks); + + loadCorrections(bc.timestamp()); + + spm.centrality = collision.centFT0C(); + + if (cfgCentFT0Cvariant1) + spm.centrality = collision.centFT0CVariant1(); + if (cfgCentFT0M) + spm.centrality = collision.centFT0M(); + if (cfgCentFV0A) + spm.centrality = collision.centFV0A(); + if (cfgCentNGlobal) + spm.centrality = collision.centNGlobal(); + + if (!eventSelected(collision, tracks.size())) + return; + + if (!collision.isSelected()) // selected by ZDCQVectors task (checks signal in ZDC) --> only possible in data not MC + return; + histos.fill(HIST("hEventCount"), evSel_isSelectedZDC); + + // Always fill centrality histogram after event selections! + histos.fill(HIST("hCentrality"), spm.centrality); + + spm.qxA = collision.qxA(); + spm.qyA = collision.qyA(); + spm.qxC = collision.qxC(); + spm.qyC = collision.qyC(); + + spm.vz = collision.posZ(); + + spm.psiA = 1.0 * std::atan2(spm.qyA, spm.qxA); + spm.psiC = 1.0 * std::atan2(spm.qyC, spm.qxC); + + // https://twiki.cern.ch/twiki/pub/ALICE/DirectedFlowAnalysisNote/vn_ZDC_ALICE_INT_NOTE_version02.pdf + spm.psiFull = 1.0 * std::atan2(spm.qyA + spm.qyC, spm.qxA + spm.qxC); + + if (spm.centrality > cfgCentMax || spm.centrality < cfgCentMin) + return; + + // Load correlations and SP resolution needed for Scalar Product and event plane methods. + // Only load once! + // If not loaded set to 1 + + if (cfgCCDBdir_QQ.value.empty() == false) { + if (!cfg.clQQ) { + TList* hcorrList = ccdb->getForTimeStamp(cfgCCDBdir_QQ.value, bc.timestamp()); + cfg.hcorrQQ = reinterpret_cast(hcorrList->FindObject("qAqCXY")); + cfg.hcorrQQx = reinterpret_cast(hcorrList->FindObject("qAqCX")); + cfg.hcorrQQy = reinterpret_cast(hcorrList->FindObject("qAqCY")); + cfg.clQQ = true; + } + spm.corrQQ = cfg.hcorrQQ->GetBinContent(cfg.hcorrQQ->FindBin(spm.centrality)); + spm.corrQQx = cfg.hcorrQQx->GetBinContent(cfg.hcorrQQx->FindBin(spm.centrality)); + spm.corrQQy = cfg.hcorrQQy->GetBinContent(cfg.hcorrQQy->FindBin(spm.centrality)); + } + + double evPlaneRes = 1.; + if (cfgCCDBdir_SP.value.empty() == false) { + if (!cfg.clEvPlaneRes) { + cfg.hEvPlaneRes = ccdb->getForTimeStamp(cfgCCDBdir_SP.value, bc.timestamp()); + cfg.clEvPlaneRes = true; + } + evPlaneRes = cfg.hEvPlaneRes->GetBinContent(cfg.hEvPlaneRes->FindBin(spm.centrality)); + if (evPlaneRes < 0) + LOGF(fatal, " > 0 for centrality %.2f! Cannot determine resolution.. Change centrality ranges!!!", spm.centrality); + evPlaneRes = std::sqrt(evPlaneRes); + } + + spm.centWeight = 1.; + if (cfgCCDBdir_centrality.value.empty() == false) { + if (!cfg.clCentrality) { + cfg.hCentrality = ccdb->getForTimeStamp(cfgCCDBdir_centrality.value, bc.timestamp()); + cfg.clCentrality = true; + } + double centW = cfg.hCentrality->GetBinContent(cfg.hCentrality->FindBin(spm.centrality)); + if (centW < 0) { + spm.centWeight = 1. / centW; + } else { + LOGF(fatal, "Centrality weight cannot be negative .. setting to 0. for (%.2f)", spm.centrality); + spm.centWeight = 0.; + } + } + + fillEventQA(collision, tracks); + + for (const auto& track : tracks) { + + ParticleType trackPID = (cfgFillPID || cfgFillPIDQA) ? getTrackPID(track) : kUnidentified; + + histos.fill(HIST("hPIDcounts"), trackPID, track.pt()); + + if (track.sign() == 0) + continue; + + histos.fill(HIST("hTrackCount"), trackSel_ZeroCharge); + + spm.charge = ((track.sign() > 0)) ? kPositive : kNegative; + + if (cfgFillQABefore) { switch (trackPID) { case kPions: - fillHistograms(track); + fillAllQA(track); break; case kKaons: - fillHistograms(track); + fillAllQA(track); break; case kProtons: - fillHistograms(track); + fillAllQA(track); break; default: /* do nothing */ break; } - if (cfgFillChargeDependence) { - switch (spm.charge) { - case kPositive: { - switch (trackPID) { - case kPions: - fillHistograms(track); - break; - case kKaons: - fillHistograms(track); - break; - case kProtons: - fillHistograms(track); - break; - default: /* do nothing */ - break; - } - break; + } + + if (!trackSelected(track, field)) + continue; + + // constrain angle to 0 -> [0,0+2pi] + auto phi = RecoDecay::constrainAngle(track.phi(), 0); + + switch (trackPID) { + case kPions: + fillAllQA(track); + break; + case kKaons: + fillAllQA(track); + break; + case kProtons: + fillAllQA(track); + break; + default: /* do nothing */ + break; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + spm.ux = std::cos(cfgHarm * phi); + spm.uy = std::sin(cfgHarm * phi); + + spm.uxMH = std::cos(cfgHarmMixed * phi); + spm.uyMH = std::sin(cfgHarmMixed * phi); + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + spm.vnA = std::cos(cfgHarm * (phi - spm.psiA)) / evPlaneRes; + spm.vnC = std::cos(cfgHarm * (phi - spm.psiC)) / evPlaneRes; + spm.vnFull = std::cos(cfgHarm * (phi - spm.psiFull)) / evPlaneRes; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + fillHistograms(track); + + switch (trackPID) { + case kPions: + fillHistograms(track); + break; + case kKaons: + fillHistograms(track); + break; + case kProtons: + fillHistograms(track); + break; + default: /* do nothing */ + break; + } + + if (cfgFillChargeDependence) { + switch (spm.charge) { + case kPositive: { + switch (trackPID) { + case kPions: + fillHistograms(track); + break; + case kKaons: + fillHistograms(track); + break; + case kProtons: + fillHistograms(track); + break; + default: /* do nothing */ + break; } - case kNegative: { - switch (trackPID) { - case kPions: - fillHistograms(track); - break; - case kKaons: - fillHistograms(track); - break; - case kProtons: - fillHistograms(track); - break; - default: /* do nothing */ - break; - } - break; + break; + } + case kNegative: { + switch (trackPID) { + case kPions: + fillHistograms(track); + break; + case kKaons: + fillHistograms(track); + break; + case kProtons: + fillHistograms(track); + break; + default: /* do nothing */ + break; } + break; } } - } // end of fillPID - + } } // end of track loop } - PROCESS_SWITCH(FlowSP, processData, "Process analysis for non-derived data", true); + PROCESS_SWITCH(FlowSP, processDataPID, "Process analysis for non-derived data with PID", false); void processMCReco(CC const& collision, aod::BCsWithTimestamps const&, TCs const& tracks, FilteredTCs const& filteredTracks, aod::McParticles const&) { diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 86105b509e7..53b84b5f849 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -59,6 +59,7 @@ using namespace o2::framework::expressions; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; static constexpr double LongArrayDouble[4][2] = {{-2.0, -2.0}, {-2.0, -2.0}, {-2.0, -2.0}, {-2.0, -2.0}}; +static constexpr float TrackCutArray[6][2] = {{2.5f, 2.5f}, {50.0f, 50.0f}, {70.0f, 70.0f}, {5.0f, 5.0f}, {2.0f, 2.0f}, {7.0f, 7.0f}}; struct FlowTask { @@ -77,11 +78,20 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgEtaVnPt, float, 0.4, "eta range for pt in vn-pt correlations") Configurable> cfgPtPtGaps{"cfgPtPtGaps", {LongArrayDouble[0], 4, 2, {"subevent 1", "subevent 2", "subevent 3", "subevent 4"}, {"etamin", "etamax"}}, "{etamin,etamax} for all ptpt-subevents"}; O2_DEFINE_CONFIGURABLE(cfgEtaGapPtPtEnabled, bool, false, "switch of subevent pt-pt correlations") - O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") - O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") - O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") + Configurable> cfgTrackCuts{"cfgTrackCuts", {TrackCutArray[0], 6, 2, {"chi2 per TPCcls", "TPC cluster", "TPC crossed rows", "ITS cluster", "DCAz", "DCAxy Nsigma"}, {"Nch", "Observable"}}, "separate Nch and observable track selections"}; + enum TrackCut { + // enum for labelledArray track selection + kChi2prTPCcls = 0, // max chi2 per TPC clusters + kTPCclu, // minimum TPC found clusters + kTPCCrossedRows, // minimum TPC crossed rows + kITSclu, // minimum ITS found clusters + kDCAz, // max DCA to vertex z + kDCAxyNSigma // 0: disable; Cut on number of sigma deviations from expected DCA in the transverse direction, nsigma=7 is the same with global track + }; + enum TrackCutGroup { + kTrCutNch = 0, + kTrCutObs = 1 + }; // Additional events selection flags O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") @@ -104,12 +114,6 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") O2_DEFINE_CONFIGURABLE(cfgUseNchCorrected, bool, false, "Use Nch-corrected for flow observables, you also need to set cfgUseNch to true") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 30, "Number of subsamples") - O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") - O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeightsRefPt, bool, false, "NUA weights are filled in ref pt bins") - O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeightsRunbyRun, bool, false, "NUA weights are filled run-by-run") - 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(cfgUseSmallMemory, bool, false, "Use small memory mode") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, false, "Use track density efficiency correction") O2_DEFINE_CONFIGURABLE(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgUsePtRef, bool, true, "Use refernce pt range for pt container (if you are checking the spectra, you need to extent it)") @@ -117,7 +121,25 @@ struct FlowTask { 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"}; Configurable cfgUserPtVnCorrConfig{"cfgUserPtVnCorrConfig", {{"refP {2} refN {-2}", "refP {3} refN {-3}"}, {"ChGap22", "ChGap32"}, {0, 0}, {3, 3}}, "Configurations for vn-pt correlations"}; - Configurable> cfgRunRemoveList{"cfgRunRemoveList", std::vector{-1}, "excluded run numbers"}; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") + O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeightsRefPt, bool, false, "NUA weights are filled in ref pt bins") + O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeightsRunbyRun, bool, false, "NUA weights are filled run-by-run") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyForNch, std::string, "", "CCDB path to efficiency object, only for Nch correction") + O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(cfgUseSmallMemory, bool, false, "Use small memory mode") + O2_DEFINE_CONFIGURABLE(cfgConsistentEventFlag, int, 0, "Flag to select consistent events - 0: off, 1: v2{2} gap calculable, 2: v2{4} full calculable, 4: v2{4} gap calculable, 8: v2{4} 3sub calculable") + Configurable> cfgConsistentEventVector{"cfgConsistentEventVector", std::vector{-0.8, -0.5, -0.4, 0.4, 0.5, 0.8}, "eta regions: left(min,max), mid(min,max), right(min,max)"}; + Configurable> cfgRunRemoveList{"cfgRunRemoveList", std::vector{-1}, "excluded run numbers"}; + } cfgUserIO; + struct AcceptedTracks { + int nNeg; + int nMid; + int nPos; + int nFull; + }; + struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, false, "V0A T0A 5 sigma cut") Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; @@ -160,9 +182,17 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgTPCPhiCutPtMin, float, 2.0f, "start point of phi-pt cut") TF1* fPhiCutLow = nullptr; TF1* fPhiCutHigh = nullptr; + // Functional form of pt-dependent DCAxy cut + TF1* fPtDepDCAxy = nullptr; + TF1* fPtDepDCAxyForNch = nullptr; + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunc, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + } cfgFuncParas; + + struct : ConfigurableGroup { // for deltaPt/ vs centrality O2_DEFINE_CONFIGURABLE(cfgDptDisEnable, bool, false, "Produce deltaPt/meanPt vs centrality") O2_DEFINE_CONFIGURABLE(cfgDptDisSelectionSwitch, int, 0, "0: disable, 1: use low cut, 2:use high cut") + O2_DEFINE_CONFIGURABLE(cfgDptDisEtaGapQA, float, 0.5, "QA plot for pT dis in eta gap") TH1D* hEvAvgMeanPt = nullptr; TH1D* fDptDisCutLow = nullptr; TH1D* fDptDisCutHigh = nullptr; @@ -170,13 +200,16 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgDptDisCutLow, std::string, "", "CCDB path to dpt lower boundary") O2_DEFINE_CONFIGURABLE(cfgDptDisCutHigh, std::string, "", "CCDB path to dpt higher boundary") ConfigurableAxis cfgDptDisAxisNormal{"cfgDptDisAxisNormal", {200, -1., 1.}, "normalized axis"}; - // Functional form of pt-dependent DCAxy cut - TF1* fPtDepDCAxy = nullptr; - O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 0, "0: disable; Cut on number of sigma deviations from expected DCA in the transverse direction, nsigma=7 is the same with global track"); - O2_DEFINE_CONFIGURABLE(cfgDCAxy, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); - } cfgFuncParas; + // for v02(pT) + O2_DEFINE_CONFIGURABLE(cfgV02Enabled, bool, false, "Produce v02(pT)") + O2_DEFINE_CONFIGURABLE(cfgV02CorrIndex, int, 8, "correlation index for n(pT)*corr") + O2_DEFINE_CONFIGURABLE(cfgV02FracEtaMin, float, -0.4, "minimum eta for particle fraction") + O2_DEFINE_CONFIGURABLE(cfgV02FracEtaMax, float, 0.4, "max eta for particle fraction") + std::vector nPt; // fraction of particles in each pT bin in one event + std::vector> listNptV2; + std::vector> listPtX; + } cfgAdditionObs; - 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 axisIndependent{"axisIndependent", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "X axis for histograms"}; ConfigurableAxis axisNch{"axisNch", {4000, 0, 4000}, "N_{ch}"}; @@ -184,7 +217,7 @@ struct FlowTask { ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -1, 1}, "DCA_{xy} (cm)"}; Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVertex) && (aod::cent::centFT0C > cfgCentFT0CMin) && (aod::cent::centFT0C < cfgCentFT0CMax); - Filter trackFilter = ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter trackFilter = ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax); using FilteredCollisions = soa::Filtered>; using FilteredTracks = soa::Filtered>; // Filter for MCcollisions @@ -198,6 +231,7 @@ struct FlowTask { // Corrections TH1D* mEfficiency = nullptr; + TH1D* mEfficiencyForNch = nullptr; GFWWeights* mAcceptance = nullptr; bool correctionsLoaded = false; @@ -309,7 +343,7 @@ struct FlowTask { registry.add("MCGen/MChMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); registry.add("MCGen/MChCent", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); } - if (!cfgUseSmallMemory) { + if (!cfgUserIO.cfgUseSmallMemory) { registry.add("BeforeSel8_globalTracks_centT0C", "before sel8;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); registry.add("BeforeCut_globalTracks_centT0C", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); registry.add("BeforeCut_PVTracks_centT0C", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); @@ -328,13 +362,14 @@ struct FlowTask { registry.add("centFT0CVar_centFT0C", "after cut;Centrality T0C;Centrality T0C Var", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); registry.add("centFT0M_centFT0C", "after cut;Centrality T0C;Centrality T0M", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); registry.add("centFV0A_centFT0C", "after cut;Centrality T0C;Centrality V0A", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); + registry.add("hEtaPtCent", "after cut;#eta;p_{T};Centrality;", {HistType::kTH3D, {{16, -0.8, 0.8}, axisPt, {10, 0, 100}}}); } // Track QA registry.add("hPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); registry.add("hPhiWeighted", "corrected #phi distribution", {HistType::kTH1D, {axisPhi}}); registry.add("hEta", "#eta distribution", {HistType::kTH1D, {axisEta}}); - registry.add("hPt", "p_{T} distribution before cut", {HistType::kTH1D, {axisPtHist}}); - registry.add("hPtRef", "p_{T} distribution after cut", {HistType::kTH1D, {axisPtHist}}); + registry.add("hPt", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); + registry.add("hPtRef", "p_{T} distribution for refernce particle", {HistType::kTH1D, {axisPt}}); registry.add("pt_phi_bef", "before cut;p_{T};#phi_{modn}", {HistType::kTH2D, {axisPt, cfgFuncParas.axisPhiMod}}); registry.add("pt_phi_aft", "after cut;p_{T};#phi_{modn}", {HistType::kTH2D, {axisPt, cfgFuncParas.axisPhiMod}}); registry.add("hChi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); @@ -359,13 +394,17 @@ struct FlowTask { registry.add("c22_gap08_trackMeanPt", "", {HistType::kTProfile, {axisIndependent}}); registry.add("PtVariance_partA_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); registry.add("PtVariance_partB_WithinGap08", "", {HistType::kTProfile, {axisIndependent}}); - if (cfgFuncParas.cfgDptDisEnable) { - registry.add("hNormDeltaPt_X", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgFuncParas.cfgDptDisAxisNormal, axisIndependent}}); + if (cfgAdditionObs.cfgDptDisEnable) { + registry.add("hNormDeltaPt_X", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgAdditionObs.cfgDptDisAxisNormal, axisIndependent}}); + registry.add("hNormDeltaPt_X_afterCut", "; #delta p_{T}/[p_{T}]; X", {HistType::kTH2D, {cfgAdditionObs.cfgDptDisAxisNormal, axisIndependent}}); + registry.add("hPt_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); + registry.add("hPtA_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); + registry.add("hPtB_afterDptCut", "p_{T} distribution", {HistType::kTH1D, {axisPt}}); } if (doprocessMCGen) { registry.add("MCGen/MChPhi", "#phi distribution", {HistType::kTH1D, {axisPhi}}); registry.add("MCGen/MChEta", "#eta distribution", {HistType::kTH1D, {axisEta}}); - registry.add("MCGen/MChPt", "p_{T} distribution after cut", {HistType::kTH1D, {axisPtHist}}); + registry.add("MCGen/MChPt", "p_{T} distribution after cut", {HistType::kTH1D, {axisPt}}); registry.add("hMeanPtWithinGap08_MC", "mean p_{T}", {HistType::kTProfile, {axisIndependent}}); for (auto i = 0; i < cfgNbootstrap; i++) { bootstrapArray[i][kMeanPtWithinGap08_MC] = registry.add(Form("BootstrapContainer_%d/hMeanPtWithinGap08_MC", i), "", {HistType::kTProfile, {axisIndependent}}); @@ -377,10 +416,21 @@ struct FlowTask { double* ptBins = &(axis.binEdges)[0]; fPtAxis = new TAxis(nPtBins, ptBins); - if (cfgOutputNUAWeights) { + if (cfgUserIO.cfgOutputNUAWeights) { fWeights->setPtBins(nPtBins, ptBins); fWeights->init(true, false); } + if (cfgAdditionObs.cfgV02Enabled) { + cfgAdditionObs.nPt.resize(fPtAxis->GetNbins()); + cfgAdditionObs.listNptV2.resize(cfgNbootstrap + 1); + cfgAdditionObs.listPtX.resize(cfgNbootstrap + 1); + cfgAdditionObs.listNptV2[0] = registry.add(Form("V02/hNptV2"), "", {HistType::kTProfile2D, {axisIndependent, axisPt}}); + cfgAdditionObs.listPtX[0] = registry.add(Form("V02/hPt_X"), "", {HistType::kTH2D, {axisIndependent, axisPt}}); + for (auto ibo = 0; ibo < cfgNbootstrap; ibo++) { + cfgAdditionObs.listNptV2[ibo + 1] = registry.add(Form("V02/hNptV2_%d", ibo), "", {HistType::kTProfile2D, {axisIndependent, axisPt}}); + cfgAdditionObs.listPtX[ibo + 1] = registry.add(Form("V02/hPt_X_%d", ibo), ";p_{T};X", {HistType::kTH2D, {axisIndependent, axisPt}}); + } + } // add in FlowContainer to Get boostrap sample automatically TObjArray* oba = new TObjArray(); @@ -434,9 +484,20 @@ struct FlowTask { oba->Add(new TNamed(Form("Ch10Gap24_pt_%i", i + 1), "Ch10Gap24_pTDiff")); std::vector userDefineGFWCorr = cfgUserDefineGFWCorr; std::vector userDefineGFWName = cfgUserDefineGFWName; + if (userDefineGFWName.size() != userDefineGFWCorr.size()) { + LOGF(fatal, "The GFWConfig names you provided are NOT matching with configurations. userDefineGFWName.size(): %d, userDefineGFWCorr.size(): %d", userDefineGFWName.size(), userDefineGFWCorr.size()); + } + LOGF(info, "User adding FlowContainer Array:"); if (!userDefineGFWCorr.empty() && !userDefineGFWName.empty()) { for (uint i = 0; i < userDefineGFWName.size(); i++) { - oba->Add(new TNamed(userDefineGFWName.at(i).c_str(), userDefineGFWName.at(i).c_str())); + if (userDefineGFWCorr.at(i).find("poi") != std::string::npos) { + LOGF(info, "%d: pT-diff array %s", i, userDefineGFWName.at(i).c_str()); + for (auto iPt = 0; iPt < fPtAxis->GetNbins(); iPt++) + oba->Add(new TNamed(Form("%s_pt_%i", userDefineGFWName.at(i).c_str(), iPt + 1), Form("%s_pTDiff", userDefineGFWName.at(i).c_str()))); + } else { + LOGF(info, "%d: %s", i, userDefineGFWName.at(i).c_str()); + oba->Add(new TNamed(userDefineGFWName.at(i).c_str(), userDefineGFWName.at(i).c_str())); + } } } fFC->SetName("FlowContainer"); @@ -532,6 +593,10 @@ struct FlowTask { 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)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN10 refN10 | olN10 {2 2} refP10 {-2 -2}", "Ch10Gap24", kTRUE)); + LOGF(info, "Embedded GFW CorrelatorConfig:"); + for (auto icorr = 0; icorr < static_cast(corrconfigs.size()); icorr++) { + LOGF(info, "corrconfigs.at(%d): %s", icorr, corrconfigs.at(icorr).Head.c_str()); + } if (!userDefineGFWCorr.empty() && !userDefineGFWName.empty()) { LOGF(info, "User adding GFW CorrelatorConfig:"); // attentaion: here we follow the index of cfgUserDefineGFWCorr @@ -541,11 +606,11 @@ struct FlowTask { break; } if (userDefineGFWCorr.at(i).find("poi") != std::string::npos) { - LOGF(info, "%d: enable pt-Diff for %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(), kTRUE)); + LOGF(info, "corrconfigs.at(%d): enable pt-Diff for %s %s", corrconfigs.size() - 1, userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str()); } else { - 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)); + LOGF(info, "corrconfigs.at(%d): %s %s", corrconfigs.size() - 1, userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str()); } } } @@ -637,10 +702,15 @@ struct FlowTask { funcV4->SetParameters(0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10); } - if (cfgFuncParas.cfgDCAxyNSigma) { - cfgFuncParas.fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgFuncParas.cfgDCAxy->c_str()), 0.001, 1000); - cfgFuncParas.fPtDepDCAxy->SetParameter(0, cfgFuncParas.cfgDCAxyNSigma); - LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgFuncParas.cfgDCAxy->c_str())); + if (cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutObs]) { + cfgFuncParas.fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgFuncParas.cfgDCAxyFunc->c_str()), 0.001, 1000); + cfgFuncParas.fPtDepDCAxy->SetParameter(0, cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutObs]); + LOGF(info, "DCAxy pt-dependence function: %s", Form("%0.1f * %s", cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutObs], cfgFuncParas.cfgDCAxyFunc->c_str())); + } + if (cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch]) { + cfgFuncParas.fPtDepDCAxyForNch = new TF1("ptDepDCAxyForNch", Form("[0]*%s", cfgFuncParas.cfgDCAxyFunc->c_str()), 0.001, 1000); + cfgFuncParas.fPtDepDCAxyForNch->SetParameter(0, cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch]); + LOGF(info, "DCAxy pt-dependence function for Nch: %s", Form("%0.1f * %s", cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch], cfgFuncParas.cfgDCAxyFunc->c_str())); } } @@ -686,6 +756,25 @@ struct FlowTask { return; } + void fillNptV2Profile(const GFW::CorrConfig& corrconf, const std::vector& npt, const double& cent, const int& isample) + { + double dnx, val; + dnx = fGFW->Calculate(corrconf, 0, kTRUE).real(); + if (dnx == 0) + return; + if (!corrconf.pTDif) { + val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; + if (std::fabs(val) < 1) { + for (auto iPt = 0; iPt < fPtAxis->GetNbins(); iPt++) { + auto pt = fPtAxis->GetBinCenter(iPt + 1); + cfgAdditionObs.listNptV2[isample]->Fill(cent, pt, val * npt[iPt], dnx); + } + } + return; + } + return; + } + template void fillFC(const GFW::CorrConfig& corrconf, const double& cent, const double& rndm) { @@ -759,41 +848,48 @@ struct FlowTask { { if (correctionsLoaded) return; - if (cfgAcceptance.value.empty() == false) { - mAcceptance = ccdb->getForTimeStamp(cfgAcceptance, timestamp); + if (cfgUserIO.cfgAcceptance.value.empty() == false) { + mAcceptance = ccdb->getForTimeStamp(cfgUserIO.cfgAcceptance, timestamp); if (mAcceptance) - LOGF(info, "Loaded acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance); + LOGF(info, "Loaded acceptance weights from %s (%p)", cfgUserIO.cfgAcceptance.value.c_str(), (void*)mAcceptance); else - LOGF(warning, "Could not load acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance); + LOGF(warning, "Could not load acceptance weights from %s (%p)", cfgUserIO.cfgAcceptance.value.c_str(), (void*)mAcceptance); } - if (cfgEfficiency.value.empty() == false) { - mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfgUserIO.cfgEfficiency.value.empty() == false) { + mEfficiency = ccdb->getForTimeStamp(cfgUserIO.cfgEfficiency, timestamp); if (mEfficiency == nullptr) { - LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgUserIO.cfgEfficiency.value.c_str()); } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)mEfficiency); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgUserIO.cfgEfficiency.value.c_str(), (void*)mEfficiency); } - if (cfgFuncParas.cfgDptDisEnable && cfgFuncParas.cfgDptDishEvAvgMeanPt.value.empty() == false) { - cfgFuncParas.hEvAvgMeanPt = ccdb->getForTimeStamp(cfgFuncParas.cfgDptDishEvAvgMeanPt, timestamp); - if (cfgFuncParas.hEvAvgMeanPt == nullptr) { - LOGF(fatal, "Could not load mean pT histogram from %s", cfgFuncParas.cfgDptDishEvAvgMeanPt.value.c_str()); + if (cfgUserIO.cfgEfficiencyForNch.value.empty() == false) { + mEfficiencyForNch = ccdb->getForTimeStamp(cfgUserIO.cfgEfficiencyForNch, timestamp); + if (mEfficiencyForNch == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgUserIO.cfgEfficiencyForNch.value.c_str()); } - LOGF(info, "Loaded mean pT histogram from %s (%p)", cfgFuncParas.cfgDptDishEvAvgMeanPt.value.c_str(), (void*)cfgFuncParas.hEvAvgMeanPt); + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgUserIO.cfgEfficiencyForNch.value.c_str(), (void*)mEfficiencyForNch); } - if (cfgFuncParas.cfgDptDisEnable && cfgFuncParas.cfgDptDisSelectionSwitch > kNoDptCut) { - if (cfgFuncParas.cfgDptDisCutLow.value.empty() == false) { - cfgFuncParas.fDptDisCutLow = ccdb->getForTimeStamp(cfgFuncParas.cfgDptDisCutLow, timestamp); - if (cfgFuncParas.fDptDisCutLow == nullptr) { - LOGF(fatal, "Could not load dptDis low cut histogram from %s", cfgFuncParas.cfgDptDisCutLow.value.c_str()); + if (cfgAdditionObs.cfgDptDisEnable && cfgAdditionObs.cfgDptDishEvAvgMeanPt.value.empty() == false) { + cfgAdditionObs.hEvAvgMeanPt = ccdb->getForTimeStamp(cfgAdditionObs.cfgDptDishEvAvgMeanPt, timestamp); + if (cfgAdditionObs.hEvAvgMeanPt == nullptr) { + LOGF(fatal, "Could not load mean pT histogram from %s", cfgAdditionObs.cfgDptDishEvAvgMeanPt.value.c_str()); + } + LOGF(info, "Loaded mean pT histogram from %s (%p)", cfgAdditionObs.cfgDptDishEvAvgMeanPt.value.c_str(), (void*)cfgAdditionObs.hEvAvgMeanPt); + } + if (cfgAdditionObs.cfgDptDisEnable && cfgAdditionObs.cfgDptDisSelectionSwitch > kNoDptCut) { + if (cfgAdditionObs.cfgDptDisCutLow.value.empty() == false) { + cfgAdditionObs.fDptDisCutLow = ccdb->getForTimeStamp(cfgAdditionObs.cfgDptDisCutLow, timestamp); + if (cfgAdditionObs.fDptDisCutLow == nullptr) { + LOGF(fatal, "Could not load dptDis low cut histogram from %s", cfgAdditionObs.cfgDptDisCutLow.value.c_str()); } - LOGF(info, "Loaded dptDis low cut histogram from %s (%p)", cfgFuncParas.cfgDptDisCutLow.value.c_str(), (void*)cfgFuncParas.fDptDisCutLow); + LOGF(info, "Loaded dptDis low cut histogram from %s (%p)", cfgAdditionObs.cfgDptDisCutLow.value.c_str(), (void*)cfgAdditionObs.fDptDisCutLow); } - if (cfgFuncParas.cfgDptDisCutHigh.value.empty() == false) { - cfgFuncParas.fDptDisCutHigh = ccdb->getForTimeStamp(cfgFuncParas.cfgDptDisCutHigh, timestamp); - if (cfgFuncParas.fDptDisCutHigh == nullptr) { - LOGF(fatal, "Could not load dptDis high cut histogram from %s", cfgFuncParas.cfgDptDisCutHigh.value.c_str()); + if (cfgAdditionObs.cfgDptDisCutHigh.value.empty() == false) { + cfgAdditionObs.fDptDisCutHigh = ccdb->getForTimeStamp(cfgAdditionObs.cfgDptDisCutHigh, timestamp); + if (cfgAdditionObs.fDptDisCutHigh == nullptr) { + LOGF(fatal, "Could not load dptDis high cut histogram from %s", cfgAdditionObs.cfgDptDisCutHigh.value.c_str()); } - LOGF(info, "Loaded dptDis high cut histogram from %s (%p)", cfgFuncParas.cfgDptDisCutHigh.value.c_str(), (void*)cfgFuncParas.fDptDisCutHigh); + LOGF(info, "Loaded dptDis high cut histogram from %s (%p)", cfgAdditionObs.cfgDptDisCutHigh.value.c_str(), (void*)cfgAdditionObs.fDptDisCutHigh); } } correctionsLoaded = true; @@ -817,6 +913,19 @@ struct FlowTask { return true; } + bool setNchEffWeights(float& eff_nch, float pt) + { + float effNch = 1.; + if (mEfficiencyForNch) + effNch = mEfficiencyForNch->GetBinContent(mEfficiencyForNch->FindBin(pt)); + else + effNch = 1.0; + if (effNch == 0) + return false; + eff_nch = 1. / effNch; + return true; + } + template bool eventSelected(TCollision collision, const int multTrk, const float centrality) { @@ -933,9 +1042,17 @@ struct FlowTask { template bool trackSelected(TTrack track) { - if (cfgFuncParas.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxy->Eval(track.pt()))) + if (cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutObs] && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxy->Eval(track.pt()))) + return false; + return ((track.tpcNClsFound() >= cfgTrackCuts->getData()[kTPCclu][kTrCutObs]) && (track.tpcNClsCrossedRows() >= cfgTrackCuts->getData()[kTPCCrossedRows][kTrCutObs]) && (track.itsNCls() >= cfgTrackCuts->getData()[kITSclu][kTrCutObs]) && (track.tpcChi2NCl() < cfgTrackCuts->getData()[kChi2prTPCcls][kTrCutObs]) && (std::fabs(track.dcaZ()) < cfgTrackCuts->getData()[kDCAz][kTrCutObs])); + } + + template + bool trackSelectedForNch(TTrack track) + { + if (cfgTrackCuts->getData()[kDCAxyNSigma][kTrCutNch] && (std::fabs(track.dcaXY()) > cfgFuncParas.fPtDepDCAxyForNch->Eval(track.pt()))) return false; - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgTrackCuts->getData()[kTPCclu][kTrCutNch]) && (track.tpcNClsCrossedRows() >= cfgTrackCuts->getData()[kTPCCrossedRows][kTrCutNch]) && (track.itsNCls() >= cfgTrackCuts->getData()[kITSclu][kTrCutNch]) && (track.tpcChi2NCl() < cfgTrackCuts->getData()[kChi2prTPCcls][kTrCutNch]) && (std::fabs(track.dcaZ()) < cfgTrackCuts->getData()[kDCAz][kTrCutNch])); } template @@ -1013,7 +1130,7 @@ struct FlowTask { void processData(FilteredCollisions::iterator const& collision, aod::BCsWithTimestamps const&, FilteredTracks const& tracks) { registry.fill(HIST("hEventCount"), 0.5); - if (!cfgUseSmallMemory && tracks.size() >= 1) { + if (!cfgUserIO.cfgUseSmallMemory && tracks.size() >= 1) { registry.fill(HIST("BeforeSel8_globalTracks_centT0C"), collision.centFT0C(), tracks.size()); } if (!collision.sel8()) @@ -1023,12 +1140,12 @@ struct FlowTask { registry.fill(HIST("hEventCount"), 1.5); auto bc = collision.bc_as(); int currentRunNumber = bc.runNumber(); - for (const auto& ExcludedRun : cfgRunRemoveList.value) { + for (const auto& ExcludedRun : cfgUserIO.cfgRunRemoveList.value) { if (currentRunNumber == ExcludedRun) { return; } } - if (cfgOutputNUAWeightsRunbyRun && currentRunNumber != lastRunNumber) { + if (cfgUserIO.cfgOutputNUAWeightsRunbyRun && currentRunNumber != lastRunNumber) { lastRunNumber = currentRunNumber; if (std::find(runNumbers.begin(), runNumbers.end(), currentRunNumber) == runNumbers.end()) { // if run number is not in the preconfigured list, create new output histograms for this run @@ -1043,7 +1160,7 @@ struct FlowTask { } registry.fill(HIST("hEventCount"), 2.5); - if (!cfgUseSmallMemory) { + if (!cfgUserIO.cfgUseSmallMemory) { 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()); @@ -1058,12 +1175,14 @@ struct FlowTask { return; registry.fill(HIST("hEventCount"), 3.5); float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNbootstrap * lRandom); float vtxz = collision.posZ(); registry.fill(HIST("hVtxZ"), vtxz); registry.fill(HIST("hMult"), tracks.size()); registry.fill(HIST("hCent"), cent); fGFW->Clear(); fFCpt->clearVector(); + cfgAdditionObs.nPt.clear(); if (cfgGetInteractionRate) { initHadronicRate(bc); double hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), mRunNumber, "ZNC hadronic") * 1.e-3; // @@ -1076,7 +1195,7 @@ struct FlowTask { registry.fill(HIST("hEventCount"), 4.5); // fill event QA - if (!cfgUseSmallMemory) { + if (!cfgUserIO.cfgUseSmallMemory) { 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()); @@ -1090,8 +1209,9 @@ struct FlowTask { } // track weights - float weff = 1, wacc = 1; + float weff = 1, wacc = 1, weffForNch = 1; double weffEvent = 0; + double weffEventFrac = 0; double ptSum = 0., ptSum_Gap08 = 0.; double weffEventWithinGap08 = 0., weffEventSquareWithinGap08 = 0.; double sumPtsquareWsquareWithinGap08 = 0., sumPtWsquareWithinGap08 = 0.; @@ -1104,6 +1224,11 @@ struct FlowTask { // magnet field dependence cut magnetfield = getMagneticField(bc.timestamp()); } + AcceptedTracks acceptedTracks{0, 0, 0, 0}; + std::vector consistentEventVector = cfgUserIO.cfgConsistentEventVector; + if (cfgUserIO.cfgConsistentEventFlag) + LOGF(info, "consistentEventVector.size = %u", consistentEventVector.size()); + std::vector> ptEtaVec; double psi2Est = 0, psi3Est = 0, psi4Est = 0; float wEPeff = 1; @@ -1134,6 +1259,9 @@ struct FlowTask { } for (const auto& track : tracks) { + if (trackSelectedForNch(track) && setNchEffWeights(weffForNch, track.pt())) { + nTracksCorrected += weffForNch; + } if (!trackSelected(track)) continue; if (cfgFuncParas.cfgShowTPCsectorOverlap && !rejectionTPCoverlap(track, magnetfield)) @@ -1141,16 +1269,16 @@ struct FlowTask { bool withinPtPOI = (cfgCutPtPOIMin < track.pt()) && (track.pt() < cfgCutPtPOIMax); // within POI pT range bool withinPtRef = (cfgCutPtRefMin < track.pt()) && (track.pt() < cfgCutPtRefMax); // within RF pT range bool withinEtaGap08 = (std::abs(track.eta()) < cfgCutEta); - if (cfgOutputNUAWeights) { - if (cfgOutputNUAWeightsRefPt) { + if (cfgUserIO.cfgOutputNUAWeights) { + if (cfgUserIO.cfgOutputNUAWeightsRefPt) { if (withinPtRef) { fWeights->fill(track.phi(), track.eta(), vtxz, track.pt(), cent, 0); - if (cfgOutputNUAWeightsRunbyRun) + if (cfgUserIO.cfgOutputNUAWeightsRunbyRun) th3sPerRun[currentRunNumber]->Fill(track.phi(), track.eta(), collision.posZ()); } } else { fWeights->fill(track.phi(), track.eta(), vtxz, track.pt(), cent, 0); - if (cfgOutputNUAWeightsRunbyRun) + if (cfgUserIO.cfgOutputNUAWeightsRunbyRun) th3sPerRun[currentRunNumber]->Fill(track.phi(), track.eta(), collision.posZ()); } } @@ -1169,6 +1297,18 @@ struct FlowTask { } } registry.fill(HIST("hPt"), track.pt()); + if (cfgAdditionObs.cfgDptDisEnable) + ptEtaVec.push_back({track.pt(), track.eta()}); + if (!cfgUserIO.cfgUseSmallMemory) { + registry.fill(HIST("hEtaPtCent"), track.eta(), track.pt(), cent); + } + if (cfgAdditionObs.cfgV02Enabled && track.eta() >= cfgAdditionObs.cfgV02FracEtaMin && track.eta() <= cfgAdditionObs.cfgV02FracEtaMax) { + cfgAdditionObs.listPtX[0]->Fill(independent, track.pt(), weff); + cfgAdditionObs.listPtX[sampleIndex + 1]->Fill(independent, track.pt(), weff); + if ((fPtAxis->FindBin(track.pt()) - 1) < fPtAxis->GetNbins()) // sanity check to avoid out of range error + cfgAdditionObs.nPt[fPtAxis->FindBin(track.pt()) - 1] += weff; + weffEventFrac += weff; + } if (withinPtRef) { registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hPhiWeighted"), track.phi(), wacc); @@ -1183,7 +1323,6 @@ struct FlowTask { registry.fill(HIST("hDCAxy"), track.dcaXY(), track.pt()); weffEvent += weff; ptSum += weff * track.pt(); - nTracksCorrected += weff; if (withinEtaGap08) { ptSum_Gap08 += weff * track.pt(); sumPtWsquareWithinGap08 += weff * weff * track.pt(); @@ -1192,6 +1331,15 @@ struct FlowTask { weffEventSquareWithinGap08 += weff * weff; } } + if (cfgUserIO.cfgConsistentEventFlag && consistentEventVector.size() == 6) { // o2-linter: disable=magic-number (size match) + acceptedTracks.nFull += 1; + if (track.eta() > consistentEventVector[0] && track.eta() < consistentEventVector[1]) + acceptedTracks.nNeg += 1; + if (track.eta() > consistentEventVector[2] && track.eta() < consistentEventVector[3]) + acceptedTracks.nMid += 1; + if (track.eta() > consistentEventVector[4] && track.eta() < consistentEventVector[5]) + acceptedTracks.nPos += 1; + } if (withinPtRef) fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); if (withinPtPOI) @@ -1208,18 +1356,45 @@ struct FlowTask { independent = nTracksCorrected; } - if (cfgFuncParas.cfgDptDisEnable) { + if (cfgUserIO.cfgConsistentEventFlag) { + if (cfgUserIO.cfgConsistentEventFlag & 1) { + if (!acceptedTracks.nPos || !acceptedTracks.nNeg) + return; + } else if (cfgUserIO.cfgConsistentEventFlag & 2) { + if (acceptedTracks.nFull < 4) // o2-linter: disable=magic-number (at least four tracks in full acceptance) + return; + } else if (cfgUserIO.cfgConsistentEventFlag & 4) { + if (acceptedTracks.nPos < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in each subevent) + return; + } + if (cfgUserIO.cfgConsistentEventFlag & 8) { + if (acceptedTracks.nPos < 2 || acceptedTracks.nMid < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in all three subevents) + return; + } + } + + if (cfgAdditionObs.cfgDptDisEnable) { double meanPt = ptSum / weffEvent; - double deltaPt = meanPt - cfgFuncParas.hEvAvgMeanPt->GetBinContent(cfgFuncParas.hEvAvgMeanPt->FindBin(independent)); + double deltaPt = meanPt - cfgAdditionObs.hEvAvgMeanPt->GetBinContent(cfgAdditionObs.hEvAvgMeanPt->FindBin(independent)); double normDeltaPt = deltaPt / meanPt; registry.fill(HIST("hNormDeltaPt_X"), normDeltaPt, independent, weffEvent); - if (cfgFuncParas.cfgDptDisSelectionSwitch == kLowDptCut && normDeltaPt > cfgFuncParas.fDptDisCutLow->GetBinContent(cfgFuncParas.fDptDisCutLow->FindBin(independent))) { + if (cfgAdditionObs.cfgDptDisSelectionSwitch == kLowDptCut && normDeltaPt > cfgAdditionObs.fDptDisCutLow->GetBinContent(cfgAdditionObs.fDptDisCutLow->FindBin(independent))) { // only keep low 10% dpt event return; - } else if (cfgFuncParas.cfgDptDisSelectionSwitch == kHighDptCut && normDeltaPt < cfgFuncParas.fDptDisCutHigh->GetBinContent(cfgFuncParas.fDptDisCutHigh->FindBin(independent))) { + } else if (cfgAdditionObs.cfgDptDisSelectionSwitch == kHighDptCut && normDeltaPt < cfgAdditionObs.fDptDisCutHigh->GetBinContent(cfgAdditionObs.fDptDisCutHigh->FindBin(independent))) { // only keep high 10% dpt event return; } + registry.fill(HIST("hNormDeltaPt_X_afterCut"), normDeltaPt, independent, weffEvent); + if (ptEtaVec.size() > 0) { + for (auto trptEta : ptEtaVec) { + registry.fill(HIST("hPt_afterDptCut"), trptEta.first); + if (trptEta.second < -1. * cfgAdditionObs.cfgDptDisEtaGapQA) + registry.fill(HIST("hPtA_afterDptCut"), trptEta.first); + if (trptEta.second > cfgAdditionObs.cfgDptDisEtaGapQA) + registry.fill(HIST("hPtB_afterDptCut"), trptEta.first); + } + } } double weffEventDiffWithGap08 = weffEventWithinGap08 * weffEventWithinGap08 - weffEventSquareWithinGap08; @@ -1229,7 +1404,6 @@ struct FlowTask { } if (weffEventWithinGap08) registry.fill(HIST("hMeanPtWithinGap08"), independent, ptSum_Gap08 / weffEventWithinGap08, 1.0); - int sampleIndex = static_cast(cfgNbootstrap * lRandom); if (weffEventWithinGap08) bootstrapArray[sampleIndex][kMeanPtWithinGap08]->Fill(independent, ptSum_Gap08 / weffEventWithinGap08, 1.0); // c22_gap8 * pt_withGap8 @@ -1245,6 +1419,15 @@ struct FlowTask { weffEventDiffWithGap08); } + // v02 + if (cfgAdditionObs.cfgV02Enabled && weffEventFrac > 0) { + for (auto ipt = 0; ipt < fPtAxis->GetNbins(); ipt++) { + cfgAdditionObs.nPt[ipt] /= weffEventFrac; + } + fillNptV2Profile(corrconfigs.at(cfgAdditionObs.cfgV02CorrIndex), cfgAdditionObs.nPt, independent, 0); + fillNptV2Profile(corrconfigs.at(cfgAdditionObs.cfgV02CorrIndex), cfgAdditionObs.nPt, independent, sampleIndex + 1); + } + // Filling Flow Container for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { fillFC(corrconfigs.at(l_ind), independent, lRandom); diff --git a/PWGCF/Flow/Tasks/flowZdcEnergy.cxx b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx new file mode 100644 index 00000000000..87f129a6b8f --- /dev/null +++ b/PWGCF/Flow/Tasks/flowZdcEnergy.cxx @@ -0,0 +1,294 @@ +// 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 flowZdcEnergy.cxx +/// \author Kegang Xiong +/// \since 03/2026 +/// \brief Study ZDC energy observables versus centrality for Run 2 / Run 3. + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" + +#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 flowZdcEnergy { + + struct : ConfigurableGroup{ + O2_DEFINE_CONFIGURABLE(cfgUseEvsel, bool, true, "whether to enable event selection") + O2_DEFINE_CONFIGURABLE(cfgCentMin, float, 0.f, "Minimum centrality for selected events") + O2_DEFINE_CONFIGURABLE(cfgCentMax, float, 90.f, "Maximum centrality for selected events") + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10.f, "Accepted z-vertex range")} evsel; + + O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8f, "Maximum track #eta") + O2_DEFINE_CONFIGURABLE(cfgPtMin, float, 0.2f, "Minimum track #P_{t}") + O2_DEFINE_CONFIGURABLE(cfgPtMax, float, 10.0f, "Maximum track #P_{t}") + O2_DEFINE_CONFIGURABLE(cfgDcaXYMax, float, 0.2f, "Maximum DCAxy") + O2_DEFINE_CONFIGURABLE(cfgDcaZMax, float, 2.0f, "Maximum DCAz") + + ConfigurableAxis axisCent{"axisCent", {90, 0, 90}, "Centrality (%)"}; + ConfigurableAxis axisMult{"axisMult", {100, 0, 100000}, "Multiplicity"}; + ConfigurableAxis axisMultDivided{"axisMultDivided", {30, 0, 15000}, "Multiplicity bins for ZN energy"}; + ConfigurableAxis axisPt{"axisPt", {100, 0, 15}, "#P_{t}"}; + ConfigurableAxis axisEta{"axisEta", {64, -1.6, 1.6}, "#eta"}; + ConfigurableAxis axisEnergy{"axisEnergy", {300, 0, 300}, "Energy"}; + ConfigurableAxis axisRescaledDiff{"axisRescaledDiff", {400, -1, 1}, "(EA-EC)/(EA+EC)"}; + + // Event counter bins + enum SelectionCriteria : uint8_t { + kAllEvents = 0, + kSeln, + kZvtx, + kCentrality, + kBCHasZDC, + kSelectedZDC, + kNSelections + }; + + Service ccdb; + HistogramRegistry registry{"registry"}; + + Filter trackFilter = nabs(aod::track::eta) < cfgEtaMax && aod::track::pt > cfgPtMin&& aod::track::pt < cfgPtMax&& nabs(aod::track::dcaXY) < cfgDcaXYMax&& nabs(aod::track::dcaZ) < cfgDcaZMax; + using UsedTracks = soa::Filtered>; + // Run 3 + using CollisionsRun3 = soa::Join; + using BCsRun3 = soa::Join; + // Run 2 + using CollisionsRun2 = soa::Join; + using BCsRun2 = soa::Join; + + void init(InitContext const&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + auto now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + ccdb->setCreatedNotAfter(now); + + registry.add("QA/hEventCount", "Event counter;Selection;Events", {HistType::kTH1D, {{kNSelections, 0, kNSelections}}}); + auto hCount = registry.get(HIST("QA/hEventCount")); + hCount->GetXaxis()->SetBinLabel(kAllEvents + 1, "All events"); + hCount->GetXaxis()->SetBinLabel(kSeln + 1, "Sel7/8"); + hCount->GetXaxis()->SetBinLabel(kZvtx + 1, "Zvtx"); + hCount->GetXaxis()->SetBinLabel(kCentrality + 1, "Centrality"); + hCount->GetXaxis()->SetBinLabel(kBCHasZDC + 1, "BC has ZDC"); + hCount->GetXaxis()->SetBinLabel(kSelectedZDC + 1, "Selected ZDC"); + + registry.add("QA/hCentrality", "", {HistType::kTH1D, {axisCent}}); + registry.add("QA/hMultiplicity", "", {HistType::kTH1D, {axisMult}}); + registry.add("QA/hMultiplicity_TPC", "", {HistType::kTH1D, {axisMult}}); + registry.add("QA/hPt", "", {HistType::kTH1D, {axisPt}}); + registry.add("QA/hEta", "", {HistType::kTH1D, {axisEta}}); + + registry.add("hEnergyWithCent_ZNA_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_Common", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_RescaledDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); + registry.add("hEnergyWithCent_ZNA_1", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_2", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_3", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_4", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_1", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_2", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_3", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_4", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNA_SumSectors", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_ZNC_SumSectors", "", {HistType::kTH2D, {axisEnergy, axisCent}}); + registry.add("hEnergyWithCent_RescaledSumDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisCent}}); + + registry.add("hEnergyWithMult_ZNA_Common", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNC_Common", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_RescaledDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNA_1", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNA_2", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNA_3", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNA_4", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNC_1", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNC_2", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNC_3", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNC_4", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNA_SumSectors", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_ZNC_SumSectors", "", {HistType::kTH2D, {axisEnergy, axisMultDivided}}); + registry.add("hEnergyWithMult_RescaledSumDiff", "", {HistType::kTH2D, {axisRescaledDiff, axisMultDivided}}); + } + + // Helper: event selection + template + bool acceptEvent(TCollision const& collision, bool UseEvsel, float centrality, const int runmode) + { + if (!UseEvsel) { + registry.fill(HIST("QA/hEventCount"), kAllEvents); + } else { + registry.fill(HIST("QA/hEventCount"), kAllEvents); + if (runmode == 2 && !collision.sel7()) { + return false; + } + if (runmode == 3 && !collision.sel8()) { + return false; + } + registry.fill(HIST("QA/hEventCount"), kSeln); + if (std::abs(collision.posZ()) > evsel.cfgVtxZ) { + return false; + } + registry.fill(HIST("QA/hEventCount"), kZvtx); + if (centrality < evsel.cfgCentMin || centrality > evsel.cfgCentMax) { + return false; + } + registry.fill(HIST("QA/hEventCount"), kCentrality); + } + return true; + } + + // Helper: fill ZDC observables + template + void fillZDCObservables(TCollision const& collision, float centrality, float multiTPC) + { + const auto& foundBC = collision.template foundBC_as(); + if (!foundBC.has_zdc()) { + return; + } + registry.fill(HIST("QA/hEventCount"), kBCHasZDC); + + const auto& zdc = foundBC.zdc(); + if (zdc.energyCommonZNA() <= 1.f || zdc.energyCommonZNC() <= 1.f) { + return; + } + registry.fill(HIST("QA/hEventCount"), kSelectedZDC); + + const float energyCommonZNA = zdc.energyCommonZNA(); + const float energyCommonZNC = zdc.energyCommonZNC(); + const float energySectorZNA1 = zdc.energySectorZNA()[0]; + const float energySectorZNA2 = zdc.energySectorZNA()[1]; + const float energySectorZNA3 = zdc.energySectorZNA()[2]; + const float energySectorZNA4 = zdc.energySectorZNA()[3]; + const float energySectorZNC1 = zdc.energySectorZNC()[0]; + const float energySectorZNC2 = zdc.energySectorZNC()[1]; + const float energySectorZNC3 = zdc.energySectorZNC()[2]; + const float energySectorZNC4 = zdc.energySectorZNC()[3]; + + const float sumEnergyZNA = energySectorZNA1 + energySectorZNA2 + energySectorZNA3 + energySectorZNA4; + const float sumEnergyZNC = energySectorZNC1 + energySectorZNC2 + energySectorZNC3 + energySectorZNC4; + + const float commonDen = energyCommonZNA + energyCommonZNC; + const float sumDen = sumEnergyZNA + sumEnergyZNC; + + registry.fill(HIST("hEnergyWithCent_ZNA_Common"), energyCommonZNA, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_Common"), energyCommonZNC, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_1"), energySectorZNA1, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_2"), energySectorZNA2, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_3"), energySectorZNA3, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_4"), energySectorZNA4, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_1"), energySectorZNC1, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_2"), energySectorZNC2, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_3"), energySectorZNC3, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_4"), energySectorZNC4, centrality); + registry.fill(HIST("hEnergyWithCent_ZNA_SumSectors"), sumEnergyZNA, centrality); + registry.fill(HIST("hEnergyWithCent_ZNC_SumSectors"), sumEnergyZNC, centrality); + + registry.fill(HIST("hEnergyWithMult_ZNA_Common"), energyCommonZNA, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNC_Common"), energyCommonZNC, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNA_1"), energySectorZNA1, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNA_2"), energySectorZNA2, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNA_3"), energySectorZNA3, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNA_4"), energySectorZNA4, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNC_1"), energySectorZNC1, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNC_2"), energySectorZNC2, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNC_3"), energySectorZNC3, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNC_4"), energySectorZNC4, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNA_SumSectors"), sumEnergyZNA, multiTPC); + registry.fill(HIST("hEnergyWithMult_ZNC_SumSectors"), sumEnergyZNC, multiTPC); + + if (commonDen > 1.e-6f) { + registry.fill(HIST("hEnergyWithCent_RescaledDiff"), (energyCommonZNA - energyCommonZNC) / commonDen, centrality); + registry.fill(HIST("hEnergyWithMult_RescaledDiff"), (energyCommonZNA - energyCommonZNC) / commonDen, multiTPC); + } + if (sumDen > 1.e-6f) { + registry.fill(HIST("hEnergyWithCent_RescaledSumDiff"), (sumEnergyZNA - sumEnergyZNC) / sumDen, centrality); + registry.fill(HIST("hEnergyWithMult_RescaledSumDiff"), (sumEnergyZNA - sumEnergyZNC) / sumDen, multiTPC); + } + } + + // Run 3 process + void processRun3(CollisionsRun3::iterator const& collision, + UsedTracks const& tracks, + BCsRun3 const&, + aod::Zdcs const&) + { + const float centrality = collision.centFT0C(); + const float multi = collision.multFT0C(); + const float multiTPC = collision.multTPC(); + + if (!acceptEvent(collision, evsel.cfgUseEvsel, centrality, 3)) { + return; + } + registry.fill(HIST("QA/hCentrality"), centrality); + registry.fill(HIST("QA/hMultiplicity"), multi); + registry.fill(HIST("QA/hMultiplicity_TPC"), multiTPC); + fillZDCObservables(collision, centrality, multiTPC); + + for (const auto& track : tracks) { + registry.fill(HIST("QA/hPt"), track.pt()); + registry.fill(HIST("QA/hEta"), track.eta()); + } + } + + // Run 2 process + void processRun2(CollisionsRun2::iterator const& collision, + UsedTracks const& tracks, + BCsRun2 const&, + aod::Zdcs const&) + { + const float centrality = collision.centRun2V0M(); + const float multi = collision.multFV0M(); + const float multiTPC = collision.multTPC(); + + if (!acceptEvent(collision, evsel.cfgUseEvsel, centrality, 2)) { + return; + } + registry.fill(HIST("QA/hCentrality"), centrality); + registry.fill(HIST("QA/hMultiplicity"), multi); + registry.fill(HIST("QA/hMultiplicity_TPC"), multiTPC); + fillZDCObservables(collision, centrality, multiTPC); + + for (const auto& track : tracks) { + registry.fill(HIST("QA/hPt"), track.pt()); + registry.fill(HIST("QA/hEta"), track.eta()); + } + } + + // Process switches + PROCESS_SWITCH(flowZdcEnergy, processRun3, "Process Run 3 data", true); + PROCESS_SWITCH(flowZdcEnergy, processRun2, "Process Run 2 data", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 3e541dbf76b..a0a424172dd 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -21,20 +21,15 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" #include -#include "TList.h" -#include #include #include #include -#include -#include #include #include @@ -54,13 +49,12 @@ struct FlowZdcTask { O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") Configurable eventSelection{"eventSelection", 1, "event selection"}; - Configurable maxZp{"maxZp", 125.5, "Max ZP signal"}; Configurable maxZem{"maxZem", 3099.5, "Max ZEM signal"}; // for ZDC info and analysis Configurable nBinsAmp{"nBinsAmp", 1025, "nbinsAmp"}; Configurable nBinsADC{"nBinsADC", 1000, "nbinsADC"}; - Configurable nBinsCent{"nBinsCent", 90, "nBinsCent"}; Configurable maxZn{"maxZn", 125.5, "Max ZN signal"}; + Configurable maxZp{"maxZp", 125.5, "Max ZP signal"}; // configs for process QA Configurable nBinsNch{"nBinsNch", 2501, "N bins Nch (|eta|<0.8)"}; Configurable nBinsAmpFT0{"nBinsAmpFT0", 100, "N bins FT0 amp"}; @@ -72,14 +66,22 @@ struct FlowZdcTask { Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; Configurable maxNch{"maxNch", 2500, "Max Nch (|eta|<0.8)"}; Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; - Configurable minTdcZn{"minTdcZn", -4.0, "minimum TDC for ZN"}; - Configurable maxTdcZn{"maxTdcZn", -4.0, "maximum TDC for ZN"}; + Configurable nBinsCent{"nBinsCent", 10, "nBinsCent"}; + Configurable minTdcZn{"minTdcZn", 4.0, "minimum TDC for ZN"}; + Configurable maxTdcZn{"maxTdcZn", 4.0, "maximum TDC for ZN"}; Configurable minTdcZp{"minTdcZp", -4.0, "minimum TDC for ZP"}; Configurable maxTdcZp{"maxTdcZp", -4.0, "maximum TDC for ZP"}; - Configurable cfgCollisionEnergy{"cfgCollisionEnergy", 2.68, "cfgCollisionEnergy"}; Configurable applyZdcCorrection{"applyZdcCorrection", false, "Apply ZP correction?"}; Configurable zpaCoeff{"zpaCoeff", 0.021f, "Coefficient a in zpa correction"}; Configurable zpcCoeff{"zpcCoeff", 0.021f, "Coefficient b in zpc correction"}; + Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; + Configurable posYcut{"posYcut", +10.0, "y-vertex position cut"}; + Configurable posXcut{"posXcut", +10.0, "x-vertex position cut"}; + Configurable minEta{"minEta", -0.8, "minimum eta"}; + Configurable maxEta{"maxEta", +0.8, "maximum eta"}; + Configurable minT0CcentCut{"minT0CcentCut", 0.0, "Min T0C Cent. cut"}; + Configurable maxT0CcentCut{"maxT0CcentCut", 90.0, "Max T0C Cent. cut"}; + Configurable maxCent{"maxCent", 90.0, "Max T0C cent"}; // event selection Configurable isNoCollInTimeRangeStrict{"isNoCollInTimeRangeStrict", true, "isNoCollInTimeRangeStrict?"}; Configurable isNoCollInTimeRangeStandard{"isNoCollInTimeRangeStandard", false, "isNoCollInTimeRangeStandard?"}; @@ -87,12 +89,11 @@ struct FlowZdcTask { Configurable isNoCollInRofStandard{"isNoCollInRofStandard", false, "isNoCollInRofStandard?"}; Configurable isNoHighMultCollInPrevRof{"isNoHighMultCollInPrevRof", true, "isNoHighMultCollInPrevRof?"}; Configurable isNoCollInTimeRangeNarrow{"isNoCollInTimeRangeNarrow", false, "isNoCollInTimeRangeNarrow?"}; - Configurable isOccupancyCut{"isOccupancyCut", true, "Occupancy cut?"}; + Configurable isOccupancyCut{"isOccupancyCut", false, "Occupancy cut?"}; Configurable isApplyFT0CbasedOccupancy{"isApplyFT0CbasedOccupancy", false, "T0C Occu cut?"}; Configurable isTDCcut{"isTDCcut", false, "Use TDC cut?"}; + Configurable isApplyRadialCut{"isApplyRadialCut", false, "Use cut on X and Y?"}; Configurable useMidRapNchSel{"useMidRapNchSel", false, "Use mid-rapidity Nch selection"}; - Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; - Configurable correctNch{"correctNch", true, "Correct also Nch"}; Configurable nSigmaNchCut{"nSigmaNchCut", 1., "nSigma Nch selection"}; Configurable minNchSel{"minNchSel", 5., "min Nch Selection"}; @@ -104,16 +105,8 @@ struct FlowZdcTask { Configurable maxPtSpectra{"maxPtSpectra", 50., "maximum pt of the tracks"}; Configurable zemCut{"zemCut", 100., "ZEM cut"}; // axis configs - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {3500, 0, 3500}, "centrality axis for histograms"}; - ConfigurableAxis axisZN{"axisZN", {5000, 0, 500}, "axisZN"}; - ConfigurableAxis axisZP{"axisZP", {5000, 0, 500}, "axisZP"}; ConfigurableAxis axisCent{"axisCent", {10, 0, 100}, "axisCent"}; ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12}, "pT binning"}; - Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; - Configurable minEta{"minEta", -0.8, "minimum eta"}; - Configurable maxEta{"maxEta", +0.8, "maximum eta"}; - Configurable minT0CcentCut{"minT0CcentCut", 0.0, "Min T0C Cent. cut"}; - Configurable maxT0CcentCut{"maxT0CcentCut", 90.0, "Max T0C Cent. cut"}; using ColEvents = soa::Join; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -167,26 +160,14 @@ struct FlowZdcTask { const AxisSpec axisZpos{48, -12., 12., "Vtx_{z} (cm)"}; const AxisSpec axisEta{40, -1., +1., "#eta"}; const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec axisVtxZ{40, -20, 20, "Vertex Z", "VzAxis"}; // create histograms histos.add("hEventCounter", "Event counter", kTH1F, {axisEvent}); histos.add("zPos", ";;Entries;", kTH1F, {axisZpos}); - histos.add("hZNvsFT0Ccent", - "ZN Energy vs FT0C Centrality", - kTH2F, - {axisCent, axisZN}); - histos.add("hZPvsFT0Ccent", - "ZP Energy vs FT0C Centrality;Centrality [%];ZP Energy", - kTH2F, - {axisCent, axisZP}); histos.add("hNchvsNPV", ";NPVTracks (|#eta|<1);N_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsNch, -0.5, maxNch}, {nBinsNch, -0.5, maxNch}}}); histos.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); - histos.add("NchUncorrected", ";#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{300, 0., 3000.}}); - histos.add("ZNamp", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ExcludedEvtVsFT0M", ";T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9);Entries;", kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0}}); histos.add("ExcludedEvtVsNch", ";#it{N}_{ch} (|#eta|<0.8);Entries;", kTH1F, {{300, 0, 3000}}); histos.add("Nch", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);", kTH1F, {{nBinsNch, minNch, maxNch}}); histos.add("EtaVsPhi", ";#eta;#varphi", kTH2F, {{{axisEta}, {100, -0.1 * PI, +2.1 * PI}}}); @@ -214,48 +195,33 @@ struct FlowZdcTask { xAxis->SetBinLabel(15, "has T0?"); xAxis->SetBinLabel(16, "Within TDC cut?"); - if (doprocessZdcCollAssoc) { // Check if the process function for ZDCCollAssoc is enabled - histos.add("ZNAcoll", "ZNAcoll; ZNA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); - histos.add("ZNCcoll", "ZNCcoll; ZNC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); - histos.add("ZPCcoll", "ZPCcoll; ZPC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); - histos.add("ZPAcoll", "ZPAcoll; ZPA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); - histos.add("ZEM1coll", "ZEM1coll; ZEM1 amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZem}}}); - histos.add("ZEM2coll", "ZEM2coll; ZEM2 amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZem}}}); - histos.add("ZNvsZEMcoll", "ZNvsZEMcoll; ZEM; ZNA+ZNC", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZem}, {nBinsAmp, -0.5, 2. * maxZn}}}}); - histos.add("ZNAvsZNCcoll", "ZNAvsZNCcoll; ZNC; ZNA", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZn}, {nBinsAmp, -0.5, maxZn}}}}); - histos.add("ZDC_energy_vs_ZEM", "ZDCvsZEM; ZEM; ZNA+ZNC+ZPA+ZPC", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZem}, {nBinsAmp, -0.5, 2. * maxZn}}}}); - // common energies information for ZDC - histos.add("ZNCenergy", "common sum ZN energy side c", kTH1F, {axisZN}); - histos.add("ZNAenergy", "common sum ZN energy side a", kTH1F, {axisZN}); - histos.add("ZPCenergy", "common sum ZP energy side c", kTH1F, {axisZP}); - histos.add("ZPAenergy", "common sum ZP energy side a", kTH1F, {axisZP}); - histos.add("ZNenergy", "common sum zn (a + c sides) energy", kTH1F, {axisZN}); - histos.add("ZPenergy", "common sum zp energy (a + c sides)", kTH1F, {axisZP}); - histos.add("hZNvsFT0CAmp", "ZN Energy vs FT0C Amplitude", kTH2F, {{nBinsAmpFT0, 0., maxAmpFT0}, axisZN}); - histos.add("hZPvsFT0CAmp", "ZP Energy vs FT0C Amplitude", kTH2F, {{nBinsAmpFT0, 0., maxAmpFT0}, axisZP}); - histos.add("hZNvsMult", "ZN Energy vs Multiplicity", kTH2F, {axisMultiplicity, axisZN}); - histos.add("hZPvsMult", "ZP Energy vs Multiplicity", kTH2F, {axisMultiplicity, axisZP}); - } - if (doprocessQA) { histos.add("ZNVsFT0A", ";T0A (#times 1/100);ZNA+ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0C", ";T0C (#times 1/100);ZNA+ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("CommonZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC Common Energy;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZNVsCent", ";T0C cent;ZNA + ZNC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZPVsFT0A", ";T0A (#times 1/100);ZPA+ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPVsFT0C", ";T0C (#times 1/100);ZPA+ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPVsFT0M", ";T0A+T0C (#times 1/100);ZPA+ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("ZPVsCent", ";T0C cent;ZPA + ZPC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("CommonZPVsFT0M", ";T0A+T0C (#times 1/100);ZPA+ZPC Common Energy;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZNAVsFT0A", ";T0A (#times 1/100);ZNA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNAVsFT0C", ";T0C (#times 1/100);ZNA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZNAVsCent", ";T0C cent;ZNA Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNAVsFT0M", ";T0A+T0C (#times 1/100);ZNA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0A", ";T0A (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0C", ";T0C (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsFT0M", ";T0A+T0C (#times 1/100);ZNC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("ZNCVsCent", ";T0C cent;ZNC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZPAVsFT0A", ";T0A (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPAVsFT0C", ";T0C (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPAVsFT0M", ";T0A+T0C (#times 1/100);ZPA Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("ZPAVsCent", ";T0C cent;ZPA Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPCVsFT0A", ";T0A (#times 1/100);ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPCVsFT0C", ";T0C (#times 1/100);ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZPCVsFT0M", ";T0A+T0C (#times 1/100);ZPC Amplitude;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0M}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("ZPCVsCent", ";T0C cent;ZPC Amplitude;", kTH2F, {{{nBinsCent, 0., maxCent}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZN", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ZNA", ";ZNA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ZPA", ";ZPA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); @@ -269,10 +235,10 @@ struct FlowZdcTask { histos.add("ZPAVsZPC", ";ZPC;ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZNAVsZPA", ";ZPA;ZNA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCVsZPC", ";ZPC;ZNC;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("ZNASector", ";ZNA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZPASector", ";ZPA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); - histos.add("ZNCSector", ";ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZPCSector", ";ZPC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("CommonZNAVsZNC", ";Common ZNC;Common ZNA", kTH2F, {{{nBinsZDC, -0.5, maxZn}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("CommonZPAVsZPC", ";Common ZPC;Common ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZp}}}); + histos.add("CommonZNAVsZPA", ";Common ZPA;Common ZNA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); + histos.add("CommonZNCVsZPC", ";Common ZPC;Common ZNC;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNCcvsZNCsum", ";ZNC common;ZNC sum towers;", kTH2F, {{{30, -0.5, maxZn}, {30, -0.5, maxZn}}}); histos.add("ZNAcvsZNAsum", ";ZNA common;ZNA sum towers;", kTH2F, {{{30, -0.5, maxZn}, {30, -0.5, maxZn}}}); histos.add("ZPCcvsZPCsum", ";ZPC common;ZPC sum towers;", kTH2F, {{{30, -0.5, maxZp}, {30, -0.5, maxZp}}}); @@ -302,22 +268,20 @@ struct FlowZdcTask { histos.add("NchVsITStracks", ";ITS tracks nCls >= 5;TITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{300, -0.5, 5999.5}, {nBinsNch, minNch, maxNch}}}); histos.add("ZNCVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); histos.add("ZNAVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); + histos.add("ZPAVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZPA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); + histos.add("ZPCVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZPA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); histos.add("ZNVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA+ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); - histos.add("ZNDifVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA-ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {100, -50., 50.}}}); - histos.add("ZPAvsCent", ";centFT0C;ZPA", kTH2F, {{{axisCent}, {nBinsZDC, -0.5, maxZp}}}); - histos.add("ZPCvsCent", ";centFT0C;ZPC", kTH2F, {{{axisCent}, {nBinsZDC, -0.5, maxZp}}}); - histos.add("hZPASectorvsGlbTrack", ";Global Tracks (ITS + TPC);ZPA Sector Energy", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); - histos.add("hZPCSectorvsGlbTrack", ";Global Tracks (ITS + TPC);ZPC Sector Energy", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); - histos.add("hZNASectorvsGlbTrack", ";Global Tracks (ITS + TPC);ZNA Sector Energy", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); - histos.add("hZNCSectorvsGlbTrack", ";Global Tracks (ITS + TPC);ZNC Sector Energy", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); - histos.add("hZPSectorvsGlbTrack", ";Global Tracks (ITS + TPC);(ZPA + ZPC) Sector Energy", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); - histos.add("hZNSectorvsGlbTrack", ";Global Tracks (ITS + TPC);(ZNA + ZNC) Sector Energy", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); + histos.add("ZPVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZPA+ZPC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZp}}}); } if (doprocessZdc) { histos.add("ampZna", ";ZNA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ampZpa", ";ZPA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); histos.add("ampZnc", ";ZNC Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ampZpc", ";ZPC Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("commonZna", ";ZNA Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); + histos.add("commonZpa", ";ZPA Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("commonZnc", ";ZNC Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); + histos.add("commonZpc", ";ZPC Common;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); histos.add("ampZEM1", ";ZEM1 Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZem}}); histos.add("ampZEM2", ";ZEM2 Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZem}}); histos.add("ZnVsZem", "ZnVsZEM; ZEM; ZNA + ZNC", kTH2F, {{{nBinsZDC, -0.5, maxZem}, {nBinsZDC, -0.5, maxZn}}}); @@ -325,10 +289,6 @@ struct FlowZdcTask { histos.add("ZpaVsZpc", "ZPAvsZPC; ZPC; ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZp}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZnaVsZpa", "ZNAvsZPA; ZNA; ZPA;", kTH2F, {{{nBinsZDC, -0.5, maxZn}, {nBinsZDC, -0.5, maxZp}}}); histos.add("ZncVsZpc", "ZNCvsZPC; ZNC; ZPC;", kTH2F, {{{nBinsZDC, -0.5, maxZn}, {nBinsZDC, -0.5, maxZp}}}); - histos.add("ZnccVsZncSum", "ZNCcVsZNCsum; ZNCC ADC; ZNCsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZn}, {nBinsADC, -0.5, 3. * maxZn}}}); - histos.add("ZnacVsZnaSum", "ZNAcVsZNAsum; ZNAC ADC; ZNAsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZn}, {nBinsADC, -0.5, 3. * maxZn}}}); - histos.add("ZpacVsZpaSum", "ZPAcVsZPAsum; ZPAC ADC; ZPAsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZp}, {nBinsADC, -0.5, 3. * maxZp}}}); - histos.add("ZpccVsZpcSum", "ZPCcVsZPCsum; ZPCC ADC; ZPCsum", kTH2F, {{{nBinsADC, -0.5, 3. * maxZp}, {nBinsADC, -0.5, 3. * maxZp}}}); histos.add("ZncVsTdc", "ZNCvsTDC; ZNC Amp; ZNC TDC", kTH2F, {{{480, -13.5, 11.45}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZnaVsTdc", "ZNAvsTDC; ZNA Amp; ZNA TDC", kTH2F, {{{480, -13.5, 11.45}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZpcVsTdc", "ZPCvsTDC; ZPC Amp; ZPC TDC", kTH2F, {{{480, -13.5, 11.45}, {nBinsZDC, -0.5, maxZp}}}); @@ -426,6 +386,10 @@ struct FlowZdcTask { return false; } histos.fill(HIST("hEventCounter"), EvCutLabel::VtxZ); + if (isApplyRadialCut) { + if (std::fabs(col.posX()) > posXcut && (std::fabs(col.posY()) > posYcut)) + return false; + } return true; } @@ -433,7 +397,6 @@ struct FlowZdcTask { void processQA(ColEvSels::iterator const& collision, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FV0As const& /*fv0as*/, aod::FT0s const& /*ft0s*/, TheFilteredTracks const& tracks) { const auto& foundBC = collision.foundBC_as(); - const auto cent = collision.centFT0C(); if (!isEventSelected(collision)) { return; } @@ -442,6 +405,7 @@ struct FlowZdcTask { } histos.fill(HIST("hEventCounter"), EvCutLabel::Zdc); auto zdc = foundBC.zdc(); + auto cent = collision.centFT0C(); float aT0A = 0., aT0C = 0., aV0A = 0.; if (foundBC.has_ft0()) { @@ -458,102 +422,7 @@ struct FlowZdcTask { aV0A += amplitude; } } - float tZNA{zdc.timeZNA()}; - float tZNC{zdc.timeZNC()}; - float tZPA{zdc.timeZPA()}; - float tZPC{zdc.timeZPC()}; const double normT0M{(aT0A + aT0C) / 100.}; - float znA = zdc.amplitudeZNA() / cfgCollisionEnergy; - float znC = zdc.amplitudeZNC() / cfgCollisionEnergy; - float zpA = zdc.amplitudeZPA() / cfgCollisionEnergy; - float zpC = zdc.amplitudeZPC() / cfgCollisionEnergy; - if (applyZdcCorrection) { - const float a = zpaCoeff; - const float b = zpcCoeff; - zpA = zpA - a * znA; - zpC = zpC - b * znC; - } - float commonSumZnc = zdc.energyCommonZNC() / cfgCollisionEnergy; - float commonSumZna = zdc.energyCommonZNA() / cfgCollisionEnergy; - float commonSumZpc = zdc.energyCommonZPC() / cfgCollisionEnergy; - float commonSumZpa = zdc.energyCommonZPA() / cfgCollisionEnergy; - float aZEM1{zdc.amplitudeZEM1()}; - float aZEM2{zdc.amplitudeZEM2()}; - float sumZEMs{aZEM1 + aZEM2}; - float tZEM1{zdc.timeZEM1()}; - float tZEM2{zdc.timeZEM2()}; - float sumZNs{znA + znC}; - float sumZNC = ((zdc.energySectorZNC())[0] + (zdc.energySectorZNC())[1] + (zdc.energySectorZNC())[2] + (zdc.energySectorZNC())[3]) / cfgCollisionEnergy; - float sumZNA = ((zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]) / cfgCollisionEnergy; - float sumZPC = ((zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]) / cfgCollisionEnergy; - float sumZPA = ((zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]) / cfgCollisionEnergy; - float sumSectZN = (sumZNC + sumZNA); - float sumSectZP = (sumZPC + sumZPA); - - if (sumZEMs > zemCut) { - if (isTDCcut) { - if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) { - histos.fill(HIST("ZNA"), znA); - histos.fill(HIST("ZNACommon"), commonSumZna); - histos.fill(HIST("ZNASector"), sumZNA); - } - if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) { - histos.fill(HIST("ZNC"), znC); - histos.fill(HIST("ZNCCommon"), commonSumZnc); - histos.fill(HIST("ZNCSector"), sumZNC); - } - if ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) { - histos.fill(HIST("ZPA"), zpA); - histos.fill(HIST("ZPACommon"), commonSumZpa); - histos.fill(HIST("ZPASector"), sumZPA); - } - if ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) { - histos.fill(HIST("ZPC"), zpC); - histos.fill(HIST("ZPCCommon"), commonSumZpc); - histos.fill(HIST("ZPCSector"), sumZPC); - } - if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn))) - histos.fill(HIST("ZNVsZEM"), sumZEMs, sumZNs); - if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn))) { - histos.fill(HIST("ZNAVsZNC"), znC, znA); - histos.fill(HIST("ZN"), znA + znC); - } - if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) - histos.fill(HIST("ZNAVsZPA"), zpA, znA); - if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) - histos.fill(HIST("ZNCVsZPC"), zpC, znC); - if (((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) && ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp))) - histos.fill(HIST("ZPAVsZPC"), zpC, zpA); - } else { - histos.fill(HIST("ZNA"), znA); - histos.fill(HIST("ZNC"), znC); - histos.fill(HIST("ZPA"), zpA); - histos.fill(HIST("ZPC"), zpC); - histos.fill(HIST("ZNVsZEM"), sumZEMs, sumZNs); - histos.fill(HIST("ZNAVsZNC"), znC, znA); - histos.fill(HIST("ZNAVsZPA"), zpA, znA); - histos.fill(HIST("ZNCVsZPC"), zpC, znC); - histos.fill(HIST("ZPAVsZPC"), zpC, zpA); - histos.fill(HIST("ZNACommon"), commonSumZna); - histos.fill(HIST("ZNASector"), sumZNA); - histos.fill(HIST("ZNCCommon"), commonSumZnc); - histos.fill(HIST("ZNCSector"), sumZNC); - histos.fill(HIST("ZPACommon"), commonSumZpa); - histos.fill(HIST("ZPASector"), sumZPA); - histos.fill(HIST("ZPCCommon"), commonSumZpc); - histos.fill(HIST("ZPCSector"), sumZPC); - histos.fill(HIST("ZN"), znA + znC); - } - histos.fill(HIST("ZEM1"), aZEM1); - histos.fill(HIST("ZEM2"), aZEM2); - histos.fill(HIST("ZNCVstdccoll"), tZNC, znC); - histos.fill(HIST("ZNAVstdccoll"), tZNA, znA); - histos.fill(HIST("ZPCVstdccoll"), tZPC, zpC); - histos.fill(HIST("ZPAVstdccoll"), tZPA, zpA); - histos.fill(HIST("ZEM1Vstdc"), tZEM1, aZEM1); - histos.fill(HIST("ZEM2Vstdc"), tZEM2, aZEM2); - histos.fill(HIST("debunch"), tZNA - tZNC, tZNA + tZNC); - } float et = 0., meanpt = 0.; int itsTracks = 0, glbTracks = 0; for (const auto& track : tracks) { @@ -623,48 +492,6 @@ struct FlowZdcTask { histos.fill(HIST("zPos"), collision.posZ()); histos.fill(HIST("T0Ccent"), collision.centFT0C()); histos.fill(HIST("GlbTracks"), glbTracks); - - if (sumZEMs > zemCut) { - histos.fill(HIST("ZNVsFT0C"), aT0C / 100., znA + znC); - histos.fill(HIST("ZNVsFT0M"), (aT0A + aT0C) / 100., znA + znC); - histos.fill(HIST("ZPVsFT0A"), aT0A / 100., zpA + zpC); - histos.fill(HIST("ZPVsFT0C"), aT0C / 100., zpA + zpC); - histos.fill(HIST("ZPVsFT0M"), (aT0A + aT0C) / 100., zpA + zpC); - histos.fill(HIST("ZPAVsFT0A"), aT0A / 100., zpA); - histos.fill(HIST("ZPAVsFT0C"), aT0C / 100., zpA); - histos.fill(HIST("ZPAVsFT0M"), (aT0A + aT0C) / 100., zpA); - histos.fill(HIST("ZPCVsFT0A"), aT0A / 100., zpC); - histos.fill(HIST("ZPCVsFT0C"), aT0C / 100., zpC); - histos.fill(HIST("ZPCVsFT0M"), (aT0A + aT0C) / 100., zpC); - histos.fill(HIST("ZNCVsFT0A"), aT0A / 100., znC); - histos.fill(HIST("ZNCVsFT0C"), aT0C / 100., znC); - histos.fill(HIST("ZNCVsFT0M"), (aT0A + aT0C) / 100., znC); - histos.fill(HIST("ZNAVsFT0A"), aT0A / 100., znA); - histos.fill(HIST("ZNAVsFT0C"), aT0C / 100., znA); - histos.fill(HIST("ZNAVsFT0M"), (aT0A + aT0C) / 100., znA); - histos.fill(HIST("ZPAvsCent"), cent, zpA); - histos.fill(HIST("ZPCvsCent"), cent, zpC); - if (std::isfinite(zpA) && !std::isnan(zpA) && cent >= minT0CcentCut && cent < maxT0CcentCut && glbTracks >= minNch && glbTracks < maxNch) { - histos.fill(HIST("hZPASectorvsGlbTrack"), glbTracks, sumZPA); - } - if (std::isfinite(zpC) && !std::isnan(zpC) && cent >= minT0CcentCut && cent < maxT0CcentCut && glbTracks >= minNch && glbTracks < maxNch) { - histos.fill(HIST("hZPCSectorvsGlbTrack"), glbTracks, sumZPC); - } - histos.fill(HIST("hZNASectorvsGlbTrack"), glbTracks, sumZNA); - histos.fill(HIST("hZNCSectorvsGlbTrack"), glbTracks, sumZNC); - histos.fill(HIST("hZPSectorvsGlbTrack"), glbTracks, sumSectZP); - histos.fill(HIST("hZNSectorvsGlbTrack"), glbTracks, sumSectZN); - // ZDC Correlations - histos.fill(HIST("ZNAVsNch"), glbTracks, znA); - histos.fill(HIST("ZNCVsNch"), glbTracks, znC); - histos.fill(HIST("ZNVsNch"), glbTracks, sumZNs); - histos.fill(HIST("ZNDifVsNch"), glbTracks, znA - znC); - histos.fill(HIST("ZNCcvsZNCsum"), sumZNC, zdc.energyCommonZNC()); - histos.fill(HIST("ZNAcvsZNAsum"), sumZNA, zdc.energyCommonZNA()); - histos.fill(HIST("ZPCcvsZPCsum"), sumZPC, zdc.energyCommonZPC()); - histos.fill(HIST("ZPAcvsZPAsum"), sumZPA, zdc.energyCommonZPA()); - } - histos.fill(HIST("ampFT0C"), aT0C / 100.); histos.fill(HIST("ampFT0A"), aT0A / 100.); histos.fill(HIST("ampFT0M"), (aT0A + aT0C) / 100.); @@ -680,178 +507,160 @@ struct FlowZdcTask { if (glbTracks >= minNchSel) { histos.fill(HIST("NchVsMeanPt"), glbTracks, meanpt / glbTracks); } - } - - void processZdcCollAssoc( - AodCollisions::iterator const& collision, - AodTracks const& tracks, - BCsRun3 const& /*bcs*/, - aod::Zdcs const& /*zdcs*/, - aod::FT0s const& /*ft0s*/) - { - if (!isEventSelected(collision)) { - return; - } - const auto& foundBC = collision.foundBC_as(); - if (!foundBC.has_zdc()) { - return; - } - int nTot = tracks.size(); - double ft0aAmp = 0; - double ft0cAmp = 0; - if (collision.has_foundFT0()) { - auto ft0 = collision.foundFT0(); - for (const auto& amplitude : ft0.amplitudeA()) { - ft0aAmp += amplitude; - } - for (const auto& amplitude : ft0.amplitudeC()) { - ft0cAmp += amplitude; - } + float tZNA{zdc.timeZNA()}; + float tZNC{zdc.timeZNC()}; + float tZPA{zdc.timeZPA()}; + float tZPC{zdc.timeZPC()}; + float znA = zdc.amplitudeZNA(); + float znC = zdc.amplitudeZNC(); + float zpA = zdc.amplitudeZPA(); + float zpC = zdc.amplitudeZPC(); + float commonSumZnc = zdc.energyCommonZNC(); + float commonSumZna = zdc.energyCommonZNA(); + float commonSumZpc = zdc.energyCommonZPC(); + float commonSumZpa = zdc.energyCommonZPA(); + if (applyZdcCorrection) { + const float a = zpaCoeff; + const float b = zpcCoeff; + zpA = zpA - a * znA; + commonSumZpa = commonSumZpa - a * commonSumZna; + zpC = zpC - b * znC; + commonSumZpc = commonSumZpc - b * commonSumZnc; } - const double normT0M{(ft0aAmp + ft0aAmp) / 100.}; - - const auto& zdcread = foundBC.zdc(); - const auto cent = collision.centFT0C(); - - // ZDC data and histogram filling - float znA = zdcread.amplitudeZNA() / cfgCollisionEnergy; - float znC = zdcread.amplitudeZNC() / cfgCollisionEnergy; - float zpA = zdcread.amplitudeZPA() / cfgCollisionEnergy; - float zpC = zdcread.amplitudeZPC() / cfgCollisionEnergy; - float tZNA{zdcread.timeZNA()}; - float tZNC{zdcread.timeZNC()}; - float tZPA{zdcread.timeZPA()}; - float tZPC{zdcread.timeZPC()}; - float tZDCdif{tZNC + tZPC - tZNA - tZPA}; - float tZDCsum{tZNC + tZPC + tZNA + tZPA}; - float sumZNC = ((zdcread.energySectorZNC())[0] + (zdcread.energySectorZNC())[1] + (zdcread.energySectorZNC())[2] + (zdcread.energySectorZNC())[3]) / cfgCollisionEnergy; - float sumZNA = ((zdcread.energySectorZNA())[0] + (zdcread.energySectorZNA())[1] + (zdcread.energySectorZNA())[2] + (zdcread.energySectorZNA())[3]) / cfgCollisionEnergy; - float sumZPC = ((zdcread.energySectorZPC())[0] + (zdcread.energySectorZPC())[1] + (zdcread.energySectorZPC())[2] + (zdcread.energySectorZPC())[3]) / cfgCollisionEnergy; - float sumZPA = ((zdcread.energySectorZPA())[0] + (zdcread.energySectorZPA())[1] + (zdcread.energySectorZPA())[2] + (zdcread.energySectorZPA())[3]) / cfgCollisionEnergy; - float sumZDC = sumZPA + sumZPC + sumZNA + sumZNC; - float sumZEM = zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(); + float aZEM1{zdc.amplitudeZEM1()}; + float aZEM2{zdc.amplitudeZEM2()}; + float sumZEMs{aZEM1 + aZEM2}; + float tZEM1{zdc.timeZEM1()}; + float tZEM2{zdc.timeZEM2()}; float sumZNs{znA + znC}; - float sumZPs{zpA + zpC}; - // TDC cut - if (isTDCcut) { - if (std::sqrt(std::pow(tZDCdif, 2.) + std::pow(tZDCsum, 2.)) > tdcCut) { - return; - } - histos.fill(HIST("hEventCounter"), EvCutLabel::Tdc); - } - // common energies - float commonSumZnc = zdcread.energyCommonZNC() / cfgCollisionEnergy; - float commonSumZna = zdcread.energyCommonZNA() / cfgCollisionEnergy; - float commonSumZpc = zdcread.energyCommonZPC() / cfgCollisionEnergy; - float commonSumZpa = zdcread.energyCommonZPA() / cfgCollisionEnergy; - float sumZN = (sumZNC) + (sumZNA); - float sumZP = (sumZPC) + (sumZPA); - int itsTracks = 0, glbTracks = 0; - for (const auto& track : tracks) { - // Track Selection - if (track.hasITS()) { - itsTracks++; - } - if (!track.isGlobalTrack()) { - continue; - } - if ((track.pt() < minPt) || (track.pt() > maxPt)) { - continue; - } - histos.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); - histos.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); - histos.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); - glbTracks++; - } - bool skipEvent{false}; - if (useMidRapNchSel) { - auto hMeanNch = ccdb->getForTimeStamp(paTHmeanNch.value, foundBC.timestamp()); - auto hSigmaNch = ccdb->getForTimeStamp(paTHsigmaNch.value, foundBC.timestamp()); - if (!hMeanNch) { - LOGF(info, "hMeanNch NOT LOADED!"); - return; - } - if (!hSigmaNch) { - LOGF(info, "hSigmaNch NOT LOADED!"); - return; - } - const int binT0M{hMeanNch->FindBin(normT0M)}; - const double meanNch{hMeanNch->GetBinContent(binT0M)}; - const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; - const double nSigmaSelection{nSigmaNchCut * sigmaNch}; - const double diffMeanNch{meanNch - glbTracks}; - if (!(std::abs(diffMeanNch) < nSigmaSelection)) { - histos.fill(HIST("ExcludedEvtVsFT0M"), normT0M); - histos.fill(HIST("ExcludedEvtVsNch"), glbTracks); + if (sumZEMs > zemCut) { + if (isTDCcut) { + if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) { + histos.fill(HIST("ZNA"), znA); + histos.fill(HIST("ZNACommon"), commonSumZna); + histos.fill(HIST("ZNAVsFT0A"), aT0A / 100., znA); + histos.fill(HIST("ZNAVsFT0C"), aT0C / 100., znA); + histos.fill(HIST("ZNAVsFT0M"), (aT0A + aT0C) / 100., znA); + histos.fill(HIST("ZNAVsCent"), cent, znA); + histos.fill(HIST("ZNAVsNch"), glbTracks, znA); + } + if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) { + histos.fill(HIST("ZNC"), znC); + histos.fill(HIST("ZNCCommon"), commonSumZnc); + histos.fill(HIST("ZNCVsFT0A"), aT0A / 100., znC); + histos.fill(HIST("ZNCVsFT0C"), aT0C / 100., znC); + histos.fill(HIST("ZNCVsFT0M"), (aT0A + aT0C) / 100., znC); + histos.fill(HIST("ZNCVsCent"), cent, znC); + histos.fill(HIST("ZNCVsNch"), glbTracks, znC); + } + if ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) { + histos.fill(HIST("ZPA"), zpA); + histos.fill(HIST("ZPACommon"), commonSumZpa); + histos.fill(HIST("ZPAVsFT0A"), aT0A / 100., zpA); + histos.fill(HIST("ZPAVsFT0C"), aT0C / 100., zpA); + histos.fill(HIST("ZPAVsFT0M"), (aT0A + aT0C) / 100., zpA); + histos.fill(HIST("ZPAVsCent"), cent, zpA); + histos.fill(HIST("ZPAVsNch"), glbTracks, zpA); + } + if ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) { + histos.fill(HIST("ZPC"), zpC); + histos.fill(HIST("ZPCCommon"), commonSumZpc); + histos.fill(HIST("ZPCVsFT0A"), aT0A / 100., zpC); + histos.fill(HIST("ZPCVsFT0C"), aT0C / 100., zpC); + histos.fill(HIST("ZPCVsFT0M"), (aT0A + aT0C) / 100., zpC); + histos.fill(HIST("ZPCVsCent"), cent, zpC); + histos.fill(HIST("ZPCVsNch"), glbTracks, zpC); + } + if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn))) + histos.fill(HIST("ZNVsZEM"), sumZEMs, sumZNs); + if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn))) { + histos.fill(HIST("ZNAVsZNC"), znC, znA); + histos.fill(HIST("CommonZNAVsZNC"), commonSumZnc, commonSumZna); + histos.fill(HIST("ZN"), znA + znC); + histos.fill(HIST("ZNVsFT0C"), aT0C / 100., znA + znC); + histos.fill(HIST("ZNVsFT0M"), (aT0A + aT0C) / 100., znA + znC); + histos.fill(HIST("CommonZNVsFT0M"), (aT0A + aT0C) / 100., commonSumZna + commonSumZnc); + histos.fill(HIST("ZNVsCent"), cent, znA + znC); + histos.fill(HIST("ZNVsNch"), glbTracks, znA + znC); + } + if (((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) && ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp))) { + histos.fill(HIST("ZPAVsZPC"), zpC, zpA); + histos.fill(HIST("CommonZPAVsZPC"), commonSumZpc, commonSumZpa); + histos.fill(HIST("ZPVsFT0A"), aT0A / 100., zpA + zpC); + histos.fill(HIST("ZPVsFT0C"), aT0C / 100., zpA + zpC); + histos.fill(HIST("ZPVsFT0M"), (aT0A + aT0C) / 100., zpA + zpC); + histos.fill(HIST("CommonZPVsFT0M"), (aT0A + aT0C) / 100., commonSumZpa + commonSumZpc); + histos.fill(HIST("ZPVsCent"), cent, zpA + zpC); + histos.fill(HIST("ZPVsNch"), glbTracks, zpA + zpC); + } + if (((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) && ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp))) { + histos.fill(HIST("ZNAVsZPA"), zpA, znA); + histos.fill(HIST("CommonZNAVsZPA"), commonSumZpa, commonSumZna); + } + if (((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) && ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp))) { + histos.fill(HIST("ZNCVsZPC"), zpC, znC); + histos.fill(HIST("CommonZNCVsZPC"), commonSumZpc, commonSumZnc); + } } else { - skipEvent = true; - } - } - // Skip event based on number of Nch sigmas - if (!skipEvent) { - return; - } - std::vector vecOneOverEff; - auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); - if (!efficiency) { - return; - } - // Calculates the Nch multiplicity - for (const auto& track : tracks) { - // Track Selection - if (!track.isGlobalTrack()) { - continue; - } - if ((track.pt() < minPt) || (track.pt() > maxPt)) { - continue; - } - - float pt{track.pt()}; - float effValue{1.0}; - if (applyEff) { - effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); - } - if (effValue > 0.) { - vecOneOverEff.emplace_back(1. / effValue); + histos.fill(HIST("ZNA"), znA); + histos.fill(HIST("ZNC"), znC); + histos.fill(HIST("ZPA"), zpA); + histos.fill(HIST("ZPC"), zpC); + histos.fill(HIST("ZNVsZEM"), sumZEMs, sumZNs); + histos.fill(HIST("ZNAVsZNC"), znC, znA); + histos.fill(HIST("ZNAVsZPA"), zpA, znA); + histos.fill(HIST("ZNCVsZPC"), zpC, znC); + histos.fill(HIST("ZPAVsZPC"), zpC, zpA); + histos.fill(HIST("CommonZPAVsZPC"), commonSumZpc, commonSumZpa); + histos.fill(HIST("CommonZNAVsZNC"), commonSumZnc, commonSumZna); + histos.fill(HIST("CommonZNAVsZPA"), commonSumZpa, commonSumZna); + histos.fill(HIST("CommonZNCVsZPC"), commonSumZpc, commonSumZnc); + histos.fill(HIST("ZNACommon"), commonSumZna); + histos.fill(HIST("ZNCCommon"), commonSumZnc); + histos.fill(HIST("ZPACommon"), commonSumZpa); + histos.fill(HIST("ZPCCommon"), commonSumZpc); + histos.fill(HIST("ZN"), znA + znC); + histos.fill(HIST("ZPVsFT0A"), aT0A / 100., zpA + zpC); + histos.fill(HIST("ZPVsFT0C"), aT0C / 100., zpA + zpC); + histos.fill(HIST("ZPVsFT0M"), (aT0A + aT0C) / 100., zpA + zpC); + histos.fill(HIST("CommonZPVsFT0M"), (aT0A + aT0C) / 100., commonSumZpa + commonSumZpc); + histos.fill(HIST("ZPAVsFT0A"), aT0A / 100., zpA); + histos.fill(HIST("ZPAVsFT0C"), aT0C / 100., zpA); + histos.fill(HIST("ZPAVsFT0M"), (aT0A + aT0C) / 100., zpA); + histos.fill(HIST("ZNVsFT0C"), aT0C / 100., znA + znC); + histos.fill(HIST("ZNVsFT0M"), (aT0A + aT0C) / 100., znA + znC); + histos.fill(HIST("CommonZNVsFT0M"), (aT0A + aT0C) / 100., commonSumZna + commonSumZnc); + histos.fill(HIST("ZPCVsFT0A"), aT0A / 100., zpC); + histos.fill(HIST("ZPCVsFT0C"), aT0C / 100., zpC); + histos.fill(HIST("ZPCVsFT0M"), (aT0A + aT0C) / 100., zpC); + histos.fill(HIST("ZNCVsFT0A"), aT0A / 100., znC); + histos.fill(HIST("ZNCVsFT0C"), aT0C / 100., znC); + histos.fill(HIST("ZNCVsFT0M"), (aT0A + aT0C) / 100., znC); + histos.fill(HIST("ZNAVsFT0A"), aT0A / 100., znA); + histos.fill(HIST("ZNAVsFT0C"), aT0C / 100., znA); + histos.fill(HIST("ZNAVsFT0M"), (aT0A + aT0C) / 100., znA); + histos.fill(HIST("ZNAVsCent"), cent, znA); + histos.fill(HIST("ZNCVsCent"), cent, znC); + histos.fill(HIST("ZPVsCent"), cent, zpA + zpC); + histos.fill(HIST("ZPAVsCent"), cent, zpA); + histos.fill(HIST("ZPCVsCent"), cent, zpC); + histos.fill(HIST("ZPAVsNch"), glbTracks, zpA); + histos.fill(HIST("ZPCVsNch"), glbTracks, zpC); + histos.fill(HIST("ZNVsNch"), glbTracks, znA + znC); + histos.fill(HIST("ZNCVsNch"), glbTracks, znC); + histos.fill(HIST("ZNAVsNch"), glbTracks, znA); } + histos.fill(HIST("ZEM1"), aZEM1); + histos.fill(HIST("ZEM2"), aZEM2); + histos.fill(HIST("ZNCVstdccoll"), tZNC, znC); + histos.fill(HIST("ZNAVstdccoll"), tZNA, znA); + histos.fill(HIST("ZPCVstdccoll"), tZPC, zpC); + histos.fill(HIST("ZPAVstdccoll"), tZPA, zpA); + histos.fill(HIST("ZEM1Vstdc"), tZEM1, aZEM1); + histos.fill(HIST("ZEM2Vstdc"), tZEM2, aZEM2); + histos.fill(HIST("debunch"), tZNA - tZNC, tZNA + tZNC); } - - double nchMult{0.}; - nchMult = std::accumulate(vecOneOverEff.begin(), vecOneOverEff.end(), 0); - if (!applyEff) - nchMult = static_cast(glbTracks); - if (applyEff && !correctNch) - nchMult = static_cast(glbTracks); - if (nchMult < minNchSel) { - return; - } - histos.get(HIST("ZNvsZEMcoll"))->Fill(zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(), zdcread.amplitudeZNA() + zdcread.amplitudeZNC()); - histos.get(HIST("ZNAvsZNCcoll"))->Fill(zdcread.amplitudeZNC(), zdcread.amplitudeZNA()); - histos.get(HIST("ZEM1coll"))->Fill(zdcread.amplitudeZEM1()); - histos.get(HIST("ZEM2coll"))->Fill(zdcread.amplitudeZEM2()); - histos.fill(HIST("ZNenergy"), sumZN); - histos.fill(HIST("ZPenergy"), sumZP); - histos.fill(HIST("ZNCenergy"), commonSumZnc); - histos.fill(HIST("ZNAenergy"), commonSumZna); - histos.fill(HIST("ZPAenergy"), commonSumZpa); - histos.fill(HIST("ZPCenergy"), commonSumZpc); - histos.fill(HIST("hZNvsFT0Ccent"), cent, sumZN); - histos.fill(HIST("hZPvsFT0Ccent"), cent, sumZP); - histos.fill(HIST("hZNvsFT0CAmp"), ft0cAmp, sumZN); - histos.fill(HIST("hZPvsFT0CAmp"), ft0cAmp, sumZP); - histos.fill(HIST("hZNvsMult"), nTot, sumZN); - histos.fill(HIST("hZPvsMult"), nTot, sumZP); - histos.fill(HIST("Nch"), nchMult); - histos.fill(HIST("ZNamp"), sumZNs); - histos.fill(HIST("NchVsZN"), nchMult, sumZNs); - histos.fill(HIST("NchVsZP"), nchMult, sumZPs); - histos.fill(HIST("NITSTacksVsZN"), itsTracks, sumZNs); - histos.fill(HIST("NITSTacksVsZP"), itsTracks, sumZPs); - histos.fill(HIST("T0MVsZN"), normT0M, sumZNs); - histos.fill(HIST("T0MVsZP"), normT0M, sumZPs); - histos.fill(HIST("NchUncorrected"), glbTracks); - histos.get(HIST("ZDC_energy_vs_ZEM"))->Fill(sumZEM, sumZDC); } void processZdc( @@ -863,18 +672,14 @@ struct FlowZdcTask { const auto& foundBC = collision.foundBC_as(); if (foundBC.has_zdc()) { const auto& zdc = foundBC.zdc(); - auto znA = zdc.amplitudeZNA() / cfgCollisionEnergy; - auto znC = zdc.amplitudeZNC() / cfgCollisionEnergy; - auto zpA = zdc.amplitudeZPA() / cfgCollisionEnergy; - auto zpC = zdc.amplitudeZPC() / cfgCollisionEnergy; - float sumZNC = ((zdc.energySectorZNC())[0] + (zdc.energySectorZNC())[1] + (zdc.energySectorZNC())[2] + (zdc.energySectorZNC())[3]) / cfgCollisionEnergy; - float sumZNA = ((zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]) / cfgCollisionEnergy; - float sumZPC = ((zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]) / cfgCollisionEnergy; - float sumZPA = ((zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]) / cfgCollisionEnergy; - float commonSumZnc = zdc.energyCommonZNC() / cfgCollisionEnergy; - float commonSumZna = zdc.energyCommonZNA() / cfgCollisionEnergy; - float commonSumZpc = zdc.energyCommonZPC() / cfgCollisionEnergy; - float commonSumZpa = zdc.energyCommonZPA() / cfgCollisionEnergy; + auto znA = zdc.amplitudeZNA(); + auto znC = zdc.amplitudeZNC(); + auto zpA = zdc.amplitudeZPA(); + auto zpC = zdc.amplitudeZPC(); + float commonSumZnc = zdc.energyCommonZNC(); + float commonSumZna = zdc.energyCommonZNA(); + float commonSumZpc = zdc.energyCommonZPC(); + float commonSumZpa = zdc.energyCommonZPA(); float aZEM1 = zdc.amplitudeZEM1(); float aZEM2 = zdc.amplitudeZEM2(); float sumZEMs = aZEM1 + aZEM2; @@ -883,29 +688,41 @@ struct FlowZdcTask { auto tZPA = zdc.timeZPA(); auto tZPC = zdc.timeZPC(); if (isTDCcut) { - if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) + if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) { histos.fill(HIST("ampZna"), znA); - if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) + histos.fill(HIST("commonZna"), commonSumZna); + } + if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) { histos.fill(HIST("ampZnc"), znC); - if ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) + histos.fill(HIST("commonZnc"), commonSumZnc); + } + if ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp)) { histos.fill(HIST("ampZpa"), zpA); - if ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) + histos.fill(HIST("commonZpa"), commonSumZpa); + } + if ((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) { histos.fill(HIST("ampZpc"), zpC); + histos.fill(HIST("commonZpc"), commonSumZpc); + } if (((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) && ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn))) histos.fill(HIST("ZnVsZem"), sumZEMs, znC + znA); if (((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) && ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn))) histos.fill(HIST("ZnaVsZnc"), znA, znC); if (((tZPC >= minTdcZp) && (tZPC <= maxTdcZp)) && ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp))) histos.fill(HIST("ZpaVsZpc"), zpA, zpC); - if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn)) + if ((tZNA >= minTdcZn) && (tZNA <= maxTdcZn) && ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp))) histos.fill(HIST("ZnaVsZpa"), znA, zpA); - if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn)) + if ((tZNC >= minTdcZn) && (tZNC <= maxTdcZn) && ((tZPA >= minTdcZp) && (tZPA <= maxTdcZp))) histos.fill(HIST("ZncVsZpc"), znC, zpC); } else { histos.fill(HIST("ampZna"), znA); histos.fill(HIST("ampZnc"), znC); histos.fill(HIST("ampZpa"), zpA); histos.fill(HIST("ampZpc"), zpC); + histos.fill(HIST("commonZna"), commonSumZna); + histos.fill(HIST("commonZnc"), commonSumZnc); + histos.fill(HIST("commonZpa"), commonSumZpa); + histos.fill(HIST("commonZpc"), commonSumZpc); histos.fill(HIST("ZnVsZem"), sumZEMs, znC + znA); histos.fill(HIST("ZnaVsZnc"), znA, znC); histos.fill(HIST("ZpaVsZpc"), zpA, zpC); @@ -914,10 +731,6 @@ struct FlowZdcTask { } histos.fill(HIST("ampZEM1"), aZEM1); histos.fill(HIST("ampZEM2"), aZEM2); - histos.fill(HIST("ZnccVsZncSum"), sumZNC, commonSumZnc); - histos.fill(HIST("ZnacVsZnaSum"), sumZNA, commonSumZna); - histos.fill(HIST("ZpccVsZpcSum"), sumZPC, commonSumZpc); - histos.fill(HIST("ZpacVsZpaSum"), sumZPA, commonSumZpa); histos.fill(HIST("ZncVsTdc"), zdc.timeZNC(), znC); histos.fill(HIST("ZnaVsTdc"), zdc.timeZNA(), znA); histos.fill(HIST("ZpcVsTdc"), zdc.timeZPC(), zpC); @@ -929,7 +742,6 @@ struct FlowZdcTask { } PROCESS_SWITCH(FlowZdcTask, processQA, "Process QA", true); - PROCESS_SWITCH(FlowZdcTask, processZdcCollAssoc, "Processing ZDC w. collision association", false); PROCESS_SWITCH(FlowZdcTask, processZdc, "Process ZDC without corrections or associations", true); }; // end of struct function diff --git a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx index 90f25ca9ff6..0266e81304d 100644 --- a/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx +++ b/PWGCF/Flow/Tasks/pidFlowPtCorr.cxx @@ -66,6 +66,7 @@ using namespace o2::framework::expressions; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct PidFlowPtCorr { + // configurable O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") @@ -103,47 +104,84 @@ struct PidFlowPtCorr { O2_DEFINE_CONFIGURABLE(cfgCutmaxIR, float, 3000, "cut max IR") } evtSeleOpts; - O2_DEFINE_CONFIGURABLE(cfgCasc_rapidity, float, 0.5, "rapidity") + struct : ConfigurableGroup { + std::string prefix = "dcaCutOpts"; + TF1* fPtDepDCAxy = nullptr; + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 0, "0: disable; Cut on number of sigma deviations from expected DCA in the transverse direction, nsigma=7 is the same with global track"); + O2_DEFINE_CONFIGURABLE(cfgDCAxy, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut") + } dcaCutOpts; + O2_DEFINE_CONFIGURABLE(cfgNSigmapid, std::vector, (std::vector{3, 3, 3, 9, 9, 9, 9, 9, 9}), "tpc, tof and its NSigma for Pion Proton Kaon") - O2_DEFINE_CONFIGURABLE(cfgMeanPtcent, std::vector, (std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), "mean Pt in different cent bin") - O2_DEFINE_CONFIGURABLE(cfgAcceptancePath, std::vector, (std::vector{"Users/f/fcui/NUA/NUAREFPartical", "Users/f/fcui/NUA/NUAK0s", "Users/f/fcui/NUA/NUALambda", "Users/f/fcui/NUA/NUAXi", "Users/f/fcui/NUA/NUAOmega"}), "CCDB path to acceptance object") - O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") + + struct : ConfigurableGroup { + std::string prefix = "correctionPathOpts"; + O2_DEFINE_CONFIGURABLE(cfgAcceptancePath, std::vector, (std::vector{"Users/f/fcui/NUA/NUAREFPartical", "Users/f/fcui/NUA/NUAK0s", "Users/f/fcui/NUA/NUALambda", "Users/f/fcui/NUA/NUAXi", "Users/f/fcui/NUA/NUAOmega"}), "CCDB path to acceptance object") + + O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiency2DPath, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency(pt, cent) object") + O2_DEFINE_CONFIGURABLE(cfgPidEfficiencyPath, std::vector, (std::vector{"PathtoRef"}), "Pi, Ka, Pr, CCDB path to PID efficiency(pt, cent) object") + + O2_DEFINE_CONFIGURABLE(cfgEfficiencyPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgEfficiency2DPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "CCDB path to efficiency(pt, cent) object") + O2_DEFINE_CONFIGURABLE(cfgPidEfficiencyPath4ITSOnly, std::vector, (std::vector{"PathtoRef"}), "Pi, Ka, Pr, CCDB path to PID efficiency(pt, cent) object") + + O2_DEFINE_CONFIGURABLE(cfgNUEOption, int, 1, "do NUE, 1: use 1D eff, 2: Using Eff(pt, cent), 3: use pid 1D eff, 4: use pid 2D eff, other: dont do NUE") + } correctionPathOpts; + O2_DEFINE_CONFIGURABLE(cfgRunNumbers, std::vector, (std::vector{544095, 544098, 544116, 544121, 544122, 544123, 544124}), "Preconfigured run numbers") O2_DEFINE_CONFIGURABLE(cfgEtaGap, float, 0.4, "eta gap for cumulant calculation, note that gap is -0.4 ~ 0.4 total 0.8, note that eta range for meanpt calculation needs to be within etagap") O2_DEFINE_CONFIGURABLE(cfgFlowNbootstrap, int, 30, "Number of subsamples for bootstrap") // switch - O2_DEFINE_CONFIGURABLE(cfgDoAccEffCorr, bool, false, "do acc and eff corr") - O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr") - O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") - O2_DEFINE_CONFIGURABLE(cfgOutputrunbyrun, bool, false, "Fill and output NUA weights run by run") - O2_DEFINE_CONFIGURABLE(cfgOutPutMC, bool, false, "Fill MC graphs, note that if the processMCgen is open,this MUST be open") - O2_DEFINE_CONFIGURABLE(cfgOutputLocDenWeights, bool, false, "Fill and output local density weights") - O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "do QA") + struct : ConfigurableGroup { + std::string prefix = "switchsOpts"; + O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr"); + O2_DEFINE_CONFIGURABLE(cfgOutputrunbyrun, bool, false, "OPEN IF USE FUNCTION(fillcorrectiongraph) Fill and output NUA weights run by run"); + O2_DEFINE_CONFIGURABLE(cfgOutPutMC, bool, false, "Fill MC graphs, note that if the processMCgen is open,this MUST be open"); + O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "OPEN IF USE FUNCTION(detectorPidQa) do QA"); + O2_DEFINE_CONFIGURABLE(cfgDebugMyCode, bool, false, "output some graph for code debug"); + O2_DEFINE_CONFIGURABLE(cfgOutPutPtSpectra, bool, false, "output pt spectra for data, MC and RECO"); + O2_DEFINE_CONFIGURABLE(cfgCheck2MethodDiff, bool, false, "check difference between v2' && v2''"); + O2_DEFINE_CONFIGURABLE(cfgUseITSOnly4MeanPt, bool, false, "use ITS only to calculate mean pt"); + O2_DEFINE_CONFIGURABLE(cfgClosureTest, int, 0, "choose (val) percent particle from charged to pass Pion PID selection"); + } switchsOpts; /** * @brief cfg for PID pt range * @details default datas are from run2, note that separate pi-k and k-p needs to use difference pt range */ // separate pi and k - O2_DEFINE_CONFIGURABLE(cfgPtMin4ITSPiKa, float, 0.2, "pt min for ITS to separate pi and k"); - O2_DEFINE_CONFIGURABLE(cfgPtMax4ITSPiKa, float, 0.8, "pt max for ITS to separate pi and k"); - O2_DEFINE_CONFIGURABLE(cfgPtMin4TOFPiKa, float, 0.5, "pt min for TOF to separate pi and k"); - O2_DEFINE_CONFIGURABLE(cfgPtMax4TOFPiKa, float, 3.0, "pt max for TOF to separate pi and k"); - O2_DEFINE_CONFIGURABLE(cfgPtMin4TPCPiKa, float, 0.2, "pt min for TPC to separate pi and k"); - O2_DEFINE_CONFIGURABLE(cfgPtMax4TPCPiKa, float, 0.6, "pt max for TPC to separate pi and k"); - // end separate pi and k - - // separate k-p - O2_DEFINE_CONFIGURABLE(cfgPtMin4ITSKaPr, float, 0.4, "pt min for ITS to separate k and p"); - O2_DEFINE_CONFIGURABLE(cfgPtMax4ITSKaPr, float, 1.4, "pt max for ITS to separate k and p"); - O2_DEFINE_CONFIGURABLE(cfgPtMin4TOFKaPr, float, 0.6, "pt min for TOF to separate k and p"); - O2_DEFINE_CONFIGURABLE(cfgPtMax4TOFKaPr, float, 3.0, "pt max for TOF to separate k and p"); - O2_DEFINE_CONFIGURABLE(cfgPtMin4TPCKaPr, float, 0.2, "pt min for TPC to separate k and p"); - O2_DEFINE_CONFIGURABLE(cfgPtMax4TPCKaPr, float, 1.0, "pt max for TPC to separate k and p"); + struct : ConfigurableGroup { + std::string prefix = "pidPtRangeOpts"; + O2_DEFINE_CONFIGURABLE(cfgPtMin4ITSPiKa, float, 0.2, "pt min for ITS to separate pi and k"); + O2_DEFINE_CONFIGURABLE(cfgPtMax4ITSPiKa, float, 0.8, "pt max for ITS to separate pi and k"); + O2_DEFINE_CONFIGURABLE(cfgPtMin4TOFPiKa, float, 0.5, "pt min for TOF to separate pi and k"); + O2_DEFINE_CONFIGURABLE(cfgPtMax4TOFPiKa, float, 3.0, "pt max for TOF to separate pi and k"); + O2_DEFINE_CONFIGURABLE(cfgPtMin4TPCPiKa, float, 0.2, "pt min for TPC to separate pi and k"); + O2_DEFINE_CONFIGURABLE(cfgPtMax4TPCPiKa, float, 0.6, "pt max for TPC to separate pi and k"); + // end separate pi and k + + // separate k-p + O2_DEFINE_CONFIGURABLE(cfgPtMin4ITSKaPr, float, 0.4, "pt min for ITS to separate k and p"); + O2_DEFINE_CONFIGURABLE(cfgPtMax4ITSKaPr, float, 1.4, "pt max for ITS to separate k and p"); + O2_DEFINE_CONFIGURABLE(cfgPtMin4TOFKaPr, float, 0.6, "pt min for TOF to separate k and p"); + O2_DEFINE_CONFIGURABLE(cfgPtMax4TOFKaPr, float, 3.0, "pt max for TOF to separate k and p"); + O2_DEFINE_CONFIGURABLE(cfgPtMin4TPCKaPr, float, 0.2, "pt min for TPC to separate k and p"); + O2_DEFINE_CONFIGURABLE(cfgPtMax4TPCKaPr, float, 1.0, "pt max for TPC to separate k and p"); + } pidPtRangeOpts; // end separate k-p // end cfg for PID pt range + struct : ConfigurableGroup { + std::string prefix = "particleAbundanceOpts"; + ConfigurableAxis cfgaxisAbundancePi{"cfgaxisAbundancePi", {100, 0, 1100}, "axis for Abundance Pi"}; + ConfigurableAxis cfgaxisAbundanceKa{"cfgaxisAbundanceKa", {100, 0, 200}, "axis for Abundance ka"}; + ConfigurableAxis cfgaxisAbundancePr{"cfgaxisAbundancePr", {100, 0, 50}, "axis for Abundance Pr"}; + + O2_DEFINE_CONFIGURABLE(cfgOutPutAbundanceDis, bool, false, "out put hists for pid particle Abundance QA"); + } particleAbundanceOpts; + ConfigurableAxis cfgaxisVertex{"cfgaxisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis cfgaxisPhi{"cfgaxisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; ConfigurableAxis cfgaxisEta{"cfgaxisEta", {40, -1., 1.}, "eta axis for histograms"}; @@ -158,23 +196,44 @@ struct PidFlowPtCorr { Configurable> cfgTrackDensityV3P{"cfgTrackDensityV3P", std::vector{0.0174056, 0.000703329, -1.45044e-05, 1.91991e-07, -1.62137e-09}, "parameter of v2(cent) for track density efficiency correction"}; Configurable> cfgTrackDensityV4P{"cfgTrackDensityV4P", std::vector{0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10}, "parameter of v2(cent) for track density efficiency correction"}; + struct : ConfigurableGroup { + std::string prefix = "meanptC22GraphOpts"; + ConfigurableAxis cfgaxisBootstrap{"cfgaxisBootstrap", {30, 0, 30}, "cfgaxisBootstrap"}; + } meanptC22GraphOpts; + AxisSpec axisMultiplicity{{0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90}, "Centrality (%)"}; + // configurable + + // filter // filter and using + // data Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + Filter trackFilter = (nabs(aod::track::eta) < trkQualityOpts.cfgCutEta.value); using TracksPID = soa::Join; - using AodTracks = soa::Filtered>; // tracks filter - using AodCollisions = soa::Filtered>; // collisions filter + // data tracks filter + using AodTracks = soa::Filtered>; + // data collisions filter + using AodCollisions = soa::Filtered>; + // MC Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; using FilteredMcCollisions = soa::Filtered; - Filter particleFilter = nabs(aod::mcparticle::eta) < trkQualityOpts.cfgCutEta.value; - using FilteredMcParticles = soa::Filtered>; + Filter particleFilter = (nabs(aod::mcparticle::eta) < trkQualityOpts.cfgCutEta.value); + using FilteredMcParticles = soa::Filtered; + + using FilteredTracksWithMCLabel = soa::Filtered>; + using FilteredCollisionsWithMCLabel = soa::Filtered>; // end using and filter + // filter + + // others + + Preslice perCollision = aod::track::collisionId; + // Connect to ccdb Service ccdb; ctpRateFetcher rateFetcher; @@ -183,7 +242,6 @@ struct PidFlowPtCorr { // Define output HistogramRegistry registry{"registry"}; - OutputObj fWeightsREF{GFWWeights("weightsREF")}; // val used for bootstrap TRandom3* fRndm = new TRandom3(0); @@ -196,11 +254,11 @@ struct PidFlowPtCorr { // define global variables GFW* fGFW = new GFW(); // GFW class used from main src std::vector corrconfigs; + std::vector cfgAcceptance; - std::vector cfgEfficiency; + std::vector cfgMultPVCutPara; std::vector cfgNSigma; - std::vector cfgMeanPt; std::vector runNumbers; std::map>> th1sList; std::map>> th3sList; @@ -211,6 +269,7 @@ struct PidFlowPtCorr { kProton, kNumberOfParticles }; + enum OutputTH1Names { // here are TProfiles for vn-pt correlations that are not implemented in GFW hPhi = 0, @@ -223,8 +282,20 @@ struct PidFlowPtCorr { kCount_TH3Names }; + enum MyFunctionName { + funcProcessData = 0, + funcDetectorPidQA, + funcFillCorrectionGraph, + funcProcessReco, + funcProcessSim, + funcNumber + }; + + // graphs for NUE / NUA std::vector mAcceptance; - std::vector mEfficiency; + std::vector mEfficiency; + std::vector mEfficiency4ITSOnly; + bool correctionsLoaded = false; TF1* fMultPVCutLow = nullptr; @@ -244,16 +315,42 @@ struct PidFlowPtCorr { TF1* funcV3; TF1* funcV4; + // hists for debug + struct { + std::shared_ptr hPtEffWeight = 0; + std::shared_ptr hPtCentEffWeight = 0; + std::shared_ptr hRunNumberPhiEtaVertexWeight = 0; + } debugHist; + // end hist for debug + + // hists for QA runbyrun + struct qaHist { + TH1* hPhiRunByRunBefore = 0; + TH1* hPhiRunByRunAfter = 0; + + TH2* hITSnclsVsPhi = 0; + TH2* hITSChi2VsPhi = 0; + + qaHist(TH1* hPhiRunByRunBefore, TH1* hPhiRunByRunAfter, TH2* hITSnclsVsPhi, TH2* hITSChi2VsPhi) + : hPhiRunByRunBefore(hPhiRunByRunBefore), hPhiRunByRunAfter(hPhiRunByRunAfter), hITSnclsVsPhi(hITSnclsVsPhi), hITSChi2VsPhi(hITSChi2VsPhi) + { + } + }; + std::vector qaHistVector; + // end hists for QA runbyrun + + // others + void init(InitContext const&) // Initialization { + // init and add lots of graphs according to switch ccdb->setURL(cfgurl.value); ccdb->setCaching(true); ccdb->setCreatedNotAfter(cfgnolaterthan.value); - cfgAcceptance = cfgAcceptancePath; - cfgEfficiency = cfgEfficiencyPath; + cfgAcceptance = correctionPathOpts.cfgAcceptancePath.value; + cfgNSigma = cfgNSigmapid; - cfgMeanPt = cfgMeanPtcent; cfgMultPVCutPara = evtSeleOpts.cfgMultPVCut; // Set the pt, mult and phi Axis; @@ -265,6 +362,12 @@ struct PidFlowPtCorr { int nMultBins = axisMult.binEdges.size() - 1; fMultAxis = new TAxis(nMultBins, &(axisMult.binEdges)[0]); + if (dcaCutOpts.cfgDCAxyNSigma) { + dcaCutOpts.fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", dcaCutOpts.cfgDCAxy->c_str()), 0.001, 1000); + dcaCutOpts.fPtDepDCAxy->SetParameter(0, dcaCutOpts.cfgDCAxyNSigma); + LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", dcaCutOpts.cfgDCAxy->c_str())); + } + // Add some output objects to the histogram registry registry.add("hPhi", "", {HistType::kTH1D, {cfgaxisPhi}}); registry.add("hPhicorr", "", {HistType::kTH1D, {cfgaxisPhi}}); @@ -281,8 +384,10 @@ struct PidFlowPtCorr { registry.add("hEtaPhiVtxzREF", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, {20, -10, 10}}}); registry.add("hNTracksPVvsCentrality", "", {HistType::kTH2D, {{5000, 0, 5000}, axisMultiplicity}}); + registry.add("hNchUnCorrectedVSNchCorrected", "", {HistType::kTH2D, {cfgaxisNch, cfgaxisNch}}); + runNumbers = cfgRunNumbers; // TPC vs TOF vs its, comparation graphs, check the PID performance in difference pt - if (cfgOutputQA) { + if (switchsOpts.cfgOutputQA.value) { registry.add("DetectorPidPerformace/TPCvsTOF/Pi", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); registry.add("DetectorPidPerformace/TPCvsTOF/Pr", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); registry.add("DetectorPidPerformace/TPCvsTOF/Ka", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); @@ -294,16 +399,73 @@ struct PidFlowPtCorr { registry.add("DetectorPidPerformace/ITSvsTOF/Pi", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); registry.add("DetectorPidPerformace/ITSvsTOF/Pr", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); registry.add("DetectorPidPerformace/ITSvsTOF/Ka", "", {HistType::kTH3D, {{600, -30, 30}, {600, -30, 30}, cfgaxisPt}}); - } // end TPC vs TOF vs its graph add + // end TPC vs TOF vs its, comparation graphs + + // run by run QA hists + /** + * @brief create QA hist for each run + * @note include: + * 1. hPhi before collision cut + * 2. hPhi after collision cut + * > graph below are after collision cut < + * 3. ITS ncls vs Phi + * 4. ITS chi2 vs Phi + * @param runNumbers + */ + for (const auto& oneRun : runNumbers) { + TH1* hPhiRunByRunBefore = registry.add(Form("RunByRunQA%d/hPhiBefore", oneRun), "", {HistType::kTH1D, {cfgaxisPhi}}).get(); + TH1* hPhiRunByRunAfter = registry.add(Form("RunByRunQA%d/hPhiAfter", oneRun), "", {HistType::kTH1D, {cfgaxisPhi}}).get(); + + TH2* hITSnclsVsPhi = registry.add(Form("RunByRunQA%d/hITSnclsVsPhi", oneRun), "", {HistType::kTH2D, {cfgaxisPhi, {8, 0, 8}}}).get(); + TH2* hITSChi2VsPhi = registry.add(Form("RunByRunQA%d/hITSChi2VsPhi", oneRun), "", {HistType::kTH2D, {cfgaxisPhi, {100, 0, 10}}}).get(); + + qaHistVector.emplace_back(qaHist(hPhiRunByRunBefore, hPhiRunByRunAfter, hITSnclsVsPhi, hITSChi2VsPhi)); + } + // end run by run QA hists + } // cfgoutputqa - if (cfgOutPutMC) { + if (switchsOpts.cfgOutPutMC.value) { // hist for NUE correction - registry.add("correction/hCentPtMC", "", {HistType::kTH2D, {axisMultiplicity, cfgaxisPt}}); - registry.add("correction/hCentPtData", "", {HistType::kTH2D, {axisMultiplicity, cfgaxisPt}}); + registry.add("correction/hPtCentMcRec", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGen", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + // ITS only + registry.add("correction/hPtCentMcRec4ITSOnly", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + // hist for Pi eff + registry.add("correction/hPtCentMcRecPi", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGenPi", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + // hist for Ka eff + registry.add("correction/hPtCentMcRecKa", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGenKa", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + // hist for Pr eff + registry.add("correction/hPtCentMcRecPr", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("correction/hPtCentMcGenPr", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); } // cfgoutputMC - runNumbers = cfgRunNumbers; - if (cfgOutputrunbyrun) { + // debug hists + if (switchsOpts.cfgDebugMyCode.value) { + debugHist.hPtEffWeight = registry.add("debug/hPtEffWeight", "", {HistType::kTH1D, {cfgaxisPt}}); + debugHist.hPtCentEffWeight = registry.add("debug/hPtCentEffWeight", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + debugHist.hRunNumberPhiEtaVertexWeight = registry.add("debug/hRunNumberPhiEtaVertexWeight", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); + for (uint64_t idx = 1; idx <= runNumbers.size(); idx++) { + registry.get(HIST("debug/hRunNumberPhiEtaVertexWeight"))->GetAxis(0)->SetBinLabel(idx, std::to_string(runNumbers[idx - 1]).c_str()); + } + } // cfgdebugmycode + + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.add("ptSpectra/hPtCentData", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("ptSpectra/hCentEventCountData", "", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("ptSpectra/hCentEventCountMcGen", "", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("ptSpectra/hCentEventCountMcRec", "", {HistType::kTH1D, {axisMultiplicity}}); + + registry.add("ptSpectra/hPtCentData4ITSOnly", "", {HistType::kTH2D, {cfgaxisPt, axisMultiplicity}}); + + registry.add("c22PrimeVsc22/Pi", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); + registry.add("c22PrimeVsc22/Ka", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); + registry.add("c22PrimeVsc22/Pr", "", {HistType::kTH2D, {{100, 0., 0.01}, {100, 0., 0.01}}}); + } // cfgoutputptspectra + + if (switchsOpts.cfgOutputrunbyrun.value) { // hist for NUA registry.add("correction/hRunNumberPhiEtaVertex", "", {HistType::kTHnSparseF, {cfgaxisRun, cfgaxisPhi, cfgaxisEta, cfgaxisVertex}}); // set "correction/hRunNumberPhiEtaVertex" axis0 label @@ -313,25 +475,42 @@ struct PidFlowPtCorr { // end set "correction/hRunNumberPhiEtaVertex" axis0 label } // cfgooutputrunbyrun + if (particleAbundanceOpts.cfgOutPutAbundanceDis) { + registry.add("abundance/hNumOfPiEventCount", "", {HistType::kTH1D, {particleAbundanceOpts.cfgaxisAbundancePi}}); + registry.add("abundance/hNumOfKaEventCount", "", {HistType::kTH1D, {particleAbundanceOpts.cfgaxisAbundanceKa}}); + registry.add("abundance/hNumOfPrEventCount", "", {HistType::kTH1D, {particleAbundanceOpts.cfgaxisAbundancePr}}); + } + // set bin label for hEventCount - registry.add("hEventCount", "", {HistType::kTH1D, {{14, 0, 14}}}); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "after kTVXinTRD"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "after kNoTimeFrameBorder"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "after kNoITSROFrameBorder"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "after kDoNoSameBunchPileup"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "after kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "after kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(9, "after kIsGoodITSLayersAll"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(10, "after MultPVCut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(11, "after TPC occupancy cut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(12, "after V0AT0Acut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(13, "after IRmincut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(14, "after IRmaxcut"); + // processdata + registry.add("hEventCount/processData", "", {HistType::kTH1D, {{14, 0, 14}}}); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(1, "Filtered event"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(2, "after sel8"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(3, "after kTVXinTRD"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(4, "after kNoTimeFrameBorder"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(5, "after kNoITSROFrameBorder"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(6, "after kDoNoSameBunchPileup"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(7, "after kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(8, "after kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(9, "after kIsGoodITSLayersAll"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(10, "after MultPVCut"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(11, "after TPC occupancy cut"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(12, "after V0AT0Acut"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(13, "after IRmincut"); + registry.get(HIST("hEventCount/processData"))->GetXaxis()->SetBinLabel(14, "after IRmaxcut"); + // detector pid QA + registry.addClone("hEventCount/processData", "hEventCount/detectorPidQA"); + // fillcorrectiongraph + registry.addClone("hEventCount/processData", "hEventCount/fillCorrectionGraph"); + // processReco + registry.addClone("hEventCount/processData", "hEventCount/processReco"); + // processSim + registry.addClone("hEventCount/processData", "hEventCount/processSim"); + registry.add("hInteractionRate", "", {HistType::kTH1D, {{1000, 0, 1000}}}); // end set bin label for eventcount + // flow container setup // cumulant of flow // fill TObjArray for charged TObjArray* oba4Ch = new TObjArray(); @@ -378,6 +557,37 @@ struct PidFlowPtCorr { registry.add("ka/c22dmeanpt", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile2D, {axisMultiplicity, cfgaxisMeanPt}}); registry.add("pr/c22dmeanpt", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile2D, {axisMultiplicity, cfgaxisMeanPt}}); + // init tprofile3d for <2'> - meanpt + // charged + registry.add("meanptCentNbs/hCharged", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + // end charged + + // pid + registry.add("meanptCentNbs/hChargedPionWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedPionFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPion", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + + if (switchsOpts.cfgClosureTest.value != 0) { + registry.add("meanptCentNbs/hPionMeanptWeightC22pure", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanptWeightMeanpt", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hPionMeanptWeightC22prime", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + } + + registry.add("meanptCentNbs/hChargedKaonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedKaonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hKaon", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hKaonMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + + registry.add("meanptCentNbs/hChargedProtonWithNpair", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hChargedProtonFull", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hProton", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + registry.add("meanptCentNbs/hProtonMeanptWeightPidflow", "", {HistType::kTProfile3D, {cfgaxisMeanPt, axisMultiplicity, meanptC22GraphOpts.cfgaxisBootstrap}}); + // end pid + // end init tprofile3d for <2'> - meanpt + + // fgfw set up and correlation config setup // Data stored in fGFW double etaMax = trkQualityOpts.cfgCutEta.value; double etaGap = cfgEtaGap; @@ -438,7 +648,7 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN refN | olKaN {2 2} refP {-2 -2}", "Kaon0gap24a", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaP refP | olKaP {2 2} refN {-2 -2}", "Kaon0gap24b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN refN | olPrN {2 2} refP {-2 -2}", "Prot0gap24a", kFALSE)); // 15 - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPaP {2 2} refN {-2 -2}", "Prot0gap24b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPrP {2 2} refN {-2 -2}", "Prot0gap24b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {3} refP08 {-3}", "Pion08gap32a", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiP08 {3} refN08 {-3}", "Pion08gap32b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {3} refP08 {-3}", "Kaon08gap32a", kFALSE)); @@ -450,7 +660,7 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN refN | olKaN {3 3} refP {-3 -3}", "Kaon0gap34a", kFALSE)); // 25 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaP refP | olKaP {3 3} refN {-3 -3}", "Kaon0gap34b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN refN | olPrN {3 3} refP {-3 -3}", "Prot0gap34a", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPaP {3 3} refN {-3 -3}", "Prot0gap34b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP refP | olPrP {3 3} refN {-3 -3}", "Prot0gap34b", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN08 {2} poiPiP08 {-2}", "PiPi08gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {2} poiKaP08 {-2}", "KaKa08gap22", kFALSE)); // 30 @@ -459,8 +669,16 @@ struct PidFlowPtCorr { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN08 {3} poiKaP08 {-3}", "KaKa08gap22", kFALSE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN08 {3} poiPrP08 {-3}", "PrPr08gap22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiN {2} refP {-2}", "Pion0gap22a", kFALSE)); // 35 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPiP {2} refN {-2}", "Pion0gap22b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaN {2} refP {-2}", "Kaon0gap22a", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiKaP {2} refN {-2}", "Kaon0gap22b", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrN {2} refP {-2}", "Prot0gap22a", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPrP {2} refN {-2}", "Prot0gap22b", kFALSE)); // 40 + fGFW->CreateRegions(); // finalize the initialization + // params // 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]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); fMultPVCutLow->SetParameters(cfgMultPVCutPara[0], cfgMultPVCutPara[1], cfgMultPVCutPara[2], cfgMultPVCutPara[3], cfgMultPVCutPara[4], cfgMultPVCutPara[5], cfgMultPVCutPara[6], cfgMultPVCutPara[7], cfgMultPVCutPara[8], cfgMultPVCutPara[9]); @@ -472,16 +690,10 @@ struct PidFlowPtCorr { 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); - // fWeight output - if (cfgOutputNUAWeights) { - fWeightsREF->setPtBins(nPtBins, &(axisPt.binEdges)[0]); - fWeightsREF->init(true, false); - } - std::vector pTEffBins = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0}; hFindPtBin = new TH1D("hFindPtBin", "hFindPtBin", pTEffBins.size() - 1, &pTEffBins[0]); funcEff.resize(pTEffBins.size() - 1); - // LHC24g3 Eff + std::vector f1p0 = cfgTrackDensityP0; std::vector f1p1 = cfgTrackDensityP1; for (uint ifunc = 0; ifunc < pTEffBins.size() - 1; ifunc++) { @@ -499,6 +711,8 @@ struct PidFlowPtCorr { funcV4->SetParameters(v4para[0], v4para[1], v4para[2], v4para[3], v4para[4]); } + // pid utils function + /** * @brief Identify whether the input track is a Pion * @@ -511,6 +725,13 @@ struct PidFlowPtCorr { template bool isPion(TrackObject const& track) { + if (switchsOpts.cfgClosureTest.value != 0) { + float rnd4test = fRndm->Rndm() * 100; + if (rnd4test < switchsOpts.cfgClosureTest.value) { + return true; + } + } // closure test + bool resultPion = true; // Declare ITSResponse object internally to get ITS Sigma @@ -522,19 +743,19 @@ struct PidFlowPtCorr { const float pt = track.pt(); // ITS detector check (pi-k separation pt range) - if (pt > cfgPtMin4ITSPiKa && pt < cfgPtMax4ITSPiKa) { + if (pt > pidPtRangeOpts.cfgPtMin4ITSPiKa.value && pt < pidPtRangeOpts.cfgPtMax4ITSPiKa.value) { resultPion &= (itsSigma < cfgNSigma[6]); } // end ITS // TOF detector check (pi-k separation pt range) - if (pt > cfgPtMin4TOFPiKa && pt < cfgPtMax4TOFPiKa) { + if (pt > pidPtRangeOpts.cfgPtMin4TOFPiKa.value && pt < pidPtRangeOpts.cfgPtMax4TOFPiKa.value) { resultPion &= (tofSigma < cfgNSigma[3]); } // end TOF // TPC detector check (pi-k separation pt range) - if (pt > cfgPtMin4TPCPiKa && pt < cfgPtMax4TPCPiKa) { + if (pt > pidPtRangeOpts.cfgPtMin4TPCPiKa.value && pt < pidPtRangeOpts.cfgPtMax4TPCPiKa.value) { resultPion &= (tpcSigma < cfgNSigma[0]); } // end TPC @@ -565,19 +786,19 @@ struct PidFlowPtCorr { const float pt = track.pt(); // ITS detector check (k-p separation pt range) - if (pt > cfgPtMin4ITSKaPr && pt < cfgPtMax4ITSKaPr) { + if (pt > pidPtRangeOpts.cfgPtMin4ITSKaPr.value && pt < pidPtRangeOpts.cfgPtMax4ITSKaPr.value) { resultProton &= (itsSigma < cfgNSigma[7]); } // end ITS // TOF detector check (k-p separation pt range) - if (pt > cfgPtMin4TOFKaPr && pt < cfgPtMax4TOFKaPr) { + if (pt > pidPtRangeOpts.cfgPtMin4TOFKaPr.value && pt < pidPtRangeOpts.cfgPtMax4TOFKaPr.value) { resultProton &= (tofSigma < cfgNSigma[4]); } // end TOF // TPC detector check (k-p separation pt range) - if (pt > cfgPtMin4TPCKaPr && pt < cfgPtMax4TPCKaPr) { + if (pt > pidPtRangeOpts.cfgPtMin4TPCKaPr.value && pt < pidPtRangeOpts.cfgPtMax4TPCKaPr.value) { resultProton &= (tpcSigma < cfgNSigma[1]); } // end TPC @@ -609,19 +830,19 @@ struct PidFlowPtCorr { const float pt = track.pt(); // ITS detector check (overlap of pi-k and k-p separation pt ranges) - if (pt > cfgPtMin4ITSKaPr && pt > cfgPtMin4ITSPiKa && pt < cfgPtMax4ITSKaPr && pt < cfgPtMax4ITSPiKa) { + if (pt > pidPtRangeOpts.cfgPtMin4ITSKaPr.value && pt > pidPtRangeOpts.cfgPtMin4ITSPiKa.value && pt < pidPtRangeOpts.cfgPtMax4ITSKaPr.value && pt < pidPtRangeOpts.cfgPtMax4ITSPiKa.value) { resultKaon &= (itsSigma < cfgNSigma[8]); } // end ITS // TOF detector check (overlap of pi-k and k-p separation pt ranges) - if (pt > cfgPtMin4TOFKaPr && pt > cfgPtMin4TOFPiKa && pt < cfgPtMax4TOFKaPr && pt < cfgPtMax4TOFPiKa) { + if (pt > pidPtRangeOpts.cfgPtMin4TOFKaPr.value && pt > pidPtRangeOpts.cfgPtMin4TOFPiKa.value && pt < pidPtRangeOpts.cfgPtMax4TOFKaPr.value && pt < pidPtRangeOpts.cfgPtMax4TOFPiKa.value) { resultKaon &= (tofSigma < cfgNSigma[5]); } // end TOF // TPC detector check (overlap of pi-k and k-p separation pt ranges) - if (pt > cfgPtMin4TPCKaPr && pt > cfgPtMin4TPCPiKa && pt < cfgPtMax4TPCKaPr && pt < cfgPtMax4TPCPiKa) { + if (pt > pidPtRangeOpts.cfgPtMin4TPCKaPr.value && pt > pidPtRangeOpts.cfgPtMin4TPCPiKa.value && pt < pidPtRangeOpts.cfgPtMax4TPCKaPr.value && pt < pidPtRangeOpts.cfgPtMax4TPCPiKa.value) { resultKaon &= (tpcSigma < cfgNSigma[2]); } // end TPC @@ -629,14 +850,197 @@ struct PidFlowPtCorr { return resultKaon; } - void fillFC(MyParticleType type, const GFW::CorrConfig& corrconf, const double& cent, const double& rndm, const char* tarName) + // pid util function + + // other utils + + double getPidC22InOneEvent(const GFW::CorrConfig& corrconfA, const GFW::CorrConfig& corrconfB) + { + double NpairA = fGFW->Calculate(corrconfA, 0, true).real(); + double NpairB = fGFW->Calculate(corrconfB, 0, true).real(); + + if (NpairA == 0 && NpairB == 0) + return 0; + + double ChC22A = NpairA ? fGFW->Calculate(corrconfA, 0, false).real() / NpairA : 0.; + double ChC22B = NpairB ? fGFW->Calculate(corrconfB, 0, false).real() / NpairB : 0.; + + double ChC22 = (ChC22A * NpairA + ChC22B * NpairB) / (NpairA + NpairB); + + return ChC22; + } + + /** + * @brief get stable particle + * @note stable particle include + * 1. pi + * 2. Ka + * 3. proton + * 4. electron + * 5. muon + * + * @param pdg + * @return true stable + * @return false unstable + */ + bool isStable(int pdg) + { + switch (std::abs(pdg)) { + case PDG_t::kPiPlus: + case PDG_t::kKPlus: + case PDG_t::kProton: + case PDG_t::kElectron: + case PDG_t::kMuonMinus: + return true; + break; + default: + return false; + break; + } + + return false; + } + + // other utils + + // fgfw filling helpers + + /** + * @brief this function is used to fill fFCCh4PtC22 + * @details weight is nch * npair + * + * @param cent + * @param ptSum + * @param nch + * @param rndm + */ + void fillFC4PtC22(const double& cent, const double& ptSum, const double& nch, const double& rndm) + { + double dnx, val; + + dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + return; + + // <2> + val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + if (std::fabs(val) >= 1) + return; + + registry.fill(HIST("meanptCentNbs/hCharged"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, val, nch * dnx); + registry.fill(HIST("meanptCentNbs/hChargedMeanpt"), ptSum / nch, cent, rndm * cfgFlowNbootstrap, ptSum / nch, nch * dnx * val); + } + + /** + * @brief note that the graph's x axis is pid meanpt, for <2'> weight is nPid * npairPID, for <2> weight is nPid * npair + * + * @param cent + * @param rndm + * @param type + * @param pidPtSum + * @param nPid + */ + void fillFC4PtC22(const double& cent, const double& rndm, MyParticleType type, const double& pidPtSum, const double& nPid) + { + // <2> + double dnx, val; + + dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + return; + + // <2> + val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + if (std::fabs(val) >= 1) + return; + + double pidc22 = 0; + double npairPid = 0; + switch (type) { + case MyParticleType::kPion: + pidc22 = getPidC22InOneEvent(corrconfigs.at(5), corrconfigs.at(6)); + if (pidc22 == 0) + return; + + npairPid = fGFW->Calculate(corrconfigs.at(5), 0, kTRUE).real() + fGFW->Calculate(corrconfigs.at(6), 0, kTRUE).real(); + if (npairPid == 0) + return; + + registry.fill(HIST("meanptCentNbs/hPion"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); + registry.fill(HIST("meanptCentNbs/hChargedPionFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); + registry.fill(HIST("meanptCentNbs/hChargedPionWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + + if (switchsOpts.cfgClosureTest.value != 0) { + double npair4c22pure = fGFW->Calculate(corrconfigs.at(29), 0, kTRUE).real(); + if (npair4c22pure > 1e-3) + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightC22pure"), + pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, + pidPtSum / nPid, + nPid * npairPid * fGFW->Calculate(corrconfigs.at(29), 0, kFALSE).real() / npair4c22pure); + + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightMeanpt"), + pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, + pidPtSum / nPid, + nPid * npairPid * pidPtSum / nPid); + registry.fill(HIST("meanptCentNbs/hPionMeanptWeightC22prime"), + pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, + pidPtSum / nPid, + nPid * npairPid * pidc22); + } + + break; + // end pion + + case MyParticleType::kKaon: + pidc22 = getPidC22InOneEvent(corrconfigs.at(7), corrconfigs.at(8)); + if (pidc22 == 0) + return; + + npairPid = fGFW->Calculate(corrconfigs.at(7), 0, kTRUE).real() + fGFW->Calculate(corrconfigs.at(8), 0, kTRUE).real(); + if (npairPid == 0) + return; + + registry.fill(HIST("meanptCentNbs/hKaon"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); + registry.fill(HIST("meanptCentNbs/hChargedKaonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); + registry.fill(HIST("meanptCentNbs/hChargedKaonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + registry.fill(HIST("meanptCentNbs/hKaonMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + + break; + // end kaon + + case MyParticleType::kProton: + pidc22 = getPidC22InOneEvent(corrconfigs.at(9), corrconfigs.at(10)); + if (pidc22 == 0) + return; + + npairPid = fGFW->Calculate(corrconfigs.at(9), 0, kTRUE).real() + fGFW->Calculate(corrconfigs.at(10), 0, kTRUE).real(); + if (npairPid == 0) + return; + + registry.fill(HIST("meanptCentNbs/hProton"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidc22, nPid * npairPid); + registry.fill(HIST("meanptCentNbs/hChargedProtonFull"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx * nPid); + registry.fill(HIST("meanptCentNbs/hChargedProtonWithNpair"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, val, dnx); + registry.fill(HIST("meanptCentNbs/hProtonMeanptWeightPidflow"), pidPtSum / nPid, cent, rndm * cfgFlowNbootstrap, pidPtSum / nPid, nPid * npairPid * pidc22 * pidc22 / val); + + break; + // end proton + + default: + return; + break; + } + // end switch particle type + } + + bool fillFC(MyParticleType type, const GFW::CorrConfig& corrconf, const double& cent, const double& rndm, const char* tarName) { double dnx, val; // calculate #sum exp{i * 0 (#phi_{i} - #phi_{j})} == N_{pairs} // note that weight is ignored in the formula but not in the calculation, for c24 is similar dnx = fGFW->Calculate(corrconf, 0, kTRUE).real(); if (dnx == 0) - return; + return false; if (!corrconf.pTDif) { // #sum exp{i * 2 * (#phi_{i} - #phi_{j})} / N_{pairs} == < 2 > val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; @@ -644,27 +1048,27 @@ struct PidFlowPtCorr { // NOTE that dnx is WEIGHT switch (type) { case MyParticleType::kCharged: - this->fFCCh->FillProfile(tarName, cent, val, dnx, rndm); + fFCCh->FillProfile(tarName, cent, val, dnx, rndm); break; case MyParticleType::kPion: - this->fFCPi->FillProfile(tarName, cent, val, dnx, rndm); + fFCPi->FillProfile(tarName, cent, val, dnx, rndm); break; case MyParticleType::kKaon: - this->fFCKa->FillProfile(tarName, cent, val, dnx, rndm); + fFCKa->FillProfile(tarName, cent, val, dnx, rndm); break; case MyParticleType::kProton: - this->fFCPr->FillProfile(tarName, cent, val, dnx, rndm); + fFCPr->FillProfile(tarName, cent, val, dnx, rndm); break; default: LOGF(warning, "particle not found"); break; } - return; + return true; } } - return; + return true; } /** @@ -706,17 +1110,17 @@ struct PidFlowPtCorr { if (std::fabs(val) < 1) { switch (type) { case MyParticleType::kCharged: - this->fFCCh->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCCh->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); break; case MyParticleType::kPion: - this->fFCPi->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCPi->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); break; case MyParticleType::kKaon: - this->fFCKa->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCKa->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); break; case MyParticleType::kProton: - this->fFCPr->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); + fFCPr->FillProfile(tarName, cent, val * (ptSum / nch), dnx * nch, rndm); break; default: @@ -768,11 +1172,22 @@ struct PidFlowPtCorr { return; } + // fill fgfw helper + + // correction apply functions + + /** + * @brief load NUE(1D) NUE(2D) NUA graphs + * @note if u write more than one path in cfg, the graph would not load, that's the strange way to close NUE/NUA corr separatly + * + * @param timestamp + */ void loadCorrections(uint64_t timestamp) { if (correctionsLoaded) return; int nspecies = 1; + // load NUA if (cfgAcceptance.size() == static_cast(nspecies)) { for (int i = 0; i <= nspecies - 1; i++) { mAcceptance.push_back(ccdb->getForTimeStamp(cfgAcceptance[i], timestamp)); @@ -782,80 +1197,441 @@ struct PidFlowPtCorr { else LOGF(warning, "Could not load acceptance weights"); } - if (cfgEfficiency.size() == static_cast(nspecies)) { - for (int i = 0; i <= nspecies - 1; i++) { - mEfficiency.push_back(ccdb->getForTimeStamp(cfgEfficiency[i], timestamp)); - } - if (mEfficiency.size() == static_cast(nspecies)) - LOGF(info, "Loaded efficiency histogram"); - else - LOGF(fatal, "Could not load efficiency histogram"); - } + // end load NUA + + /// @note dont modify load NUA!, just modify NUE + // here needs to load 2 NUE graph selected from 6 ccdb path + /// @note when using eff 2D, convert TH1* to (TH2D *) + // pid eff is not available now... + std::vector effPath1D = correctionPathOpts.cfgEfficiencyPath.value; + std::vector effPath2D = correctionPathOpts.cfgEfficiency2DPath.value; + std::vector effPathPid = correctionPathOpts.cfgPidEfficiencyPath.value; + + std::vector effPath1D4ITSOnly = correctionPathOpts.cfgEfficiencyPath4ITSOnly.value; + std::vector effPath2D4ITSOnly = correctionPathOpts.cfgEfficiency2DPath4ITSOnly.value; + std::vector effPathPid4ITSOnly = correctionPathOpts.cfgPidEfficiencyPath4ITSOnly.value; + + switch (correctionPathOpts.cfgNUEOption.value) { + case 1: // use 1D eff + // load 1d eff for global track + if (effPath1D.size() != static_cast(1)) { + LOGF(warning, "eff path 1d size != 1, skip eff 1d load"); + break; + } + mEfficiency.push_back(ccdb->getForTimeStamp(effPath1D[0], timestamp)); + if (mEfficiency.size() == static_cast(1)) { + LOGF(info, "Loaded efficiency histogram"); + } else { + LOGF(fatal, "Could not load efficiency histogram"); + } + // end load 1d eff for global track + + // load 1d eff for ITS only + if (effPath1D4ITSOnly.size() != static_cast(1)) { + LOGF(warning, "eff path for its 1d size != 1, skip its eff 1d load"); + break; + } + mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPath1D4ITSOnly[0], timestamp)); + if (mEfficiency4ITSOnly.size() == static_cast(1)) { + LOGF(info, "Loaded ITS only efficiency histogram"); + } else { + LOGF(fatal, "Could not load ITS only efficiency histogram"); + } + // end load 1d eff for its only + + break; + // end use 1d eff + + case 2: // Use 2D eff + // load 2d eff for global track + if (effPath2D.size() != static_cast(1)) { + LOGF(warning, "eff path 2d size != 1, skip eff 2d load"); + break; + } + mEfficiency.push_back(ccdb->getForTimeStamp(effPath2D[0], timestamp)); + if (mEfficiency.size() == static_cast(1)) { + LOGF(info, "Loaded 2D efficiency histogram"); + } else { + LOGF(fatal, "Could not load 2D efficiency histogram"); + } + // end load 2d eff for global track + + // load 2d eff for ITS only + if (effPath2D4ITSOnly.size() != static_cast(1)) { + LOGF(warning, "eff path for its 2d size != 1, skip its eff 2d load"); + break; + } + mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPath2D4ITSOnly[0], timestamp)); + if (mEfficiency4ITSOnly.size() == static_cast(1)) { + LOGF(info, "Loaded ITS only 2D efficiency histogram"); + } else { + LOGF(fatal, "Could not load ITS only 2D efficiency histogram"); + } + // end load 2d eff for its only + + break; + // end use 2d eff + + case 3: // use pid 1D eff + // load pid 1d eff for ITS + global track + if (effPathPid.size() != static_cast(3)) { + LOGF(warning, "eff path pid 1d size != 3, skip pid eff 1d load"); + break; + } + for (int i = 0; i < 3; i++) { + mEfficiency.push_back(ccdb->getForTimeStamp(effPathPid[i], timestamp)); + } + if (mEfficiency.size() == static_cast(3)) { + LOGF(info, "Loaded PID efficiency histogram"); + } else { + LOGF(fatal, "Could not load PID efficiency histogram"); + } + // end load pid 1d eff for ITS + global track + + // load pid 1d eff for ITS only + if (effPathPid4ITSOnly.size() != static_cast(3)) { + LOGF(warning, "eff path for its pid 1d size != 3, skip its pid eff 1d load"); + break; + } + for (int i = 0; i < 3; i++) { + mEfficiency4ITSOnly.push_back(ccdb->getForTimeStamp(effPathPid4ITSOnly[i], timestamp)); + } + if (mEfficiency4ITSOnly.size() == static_cast(3)) { + LOGF(info, "Loaded ITS only PID efficiency histogram"); + } else { + LOGF(fatal, "Could not load ITS only PID efficiency histogram"); + } + // end load pid 1d eff for its only + + break; + // end use pid 1d eff + + default: // not do NUE + break; + } // end switch load eff + correctionsLoaded = true; } template - bool setCurrentParticleWeights(float& weight_nue, float& weight_nua, TrackObject track, float vtxz, int ispecies) + bool setParticleNUAWeight(float& weight_nua, TrackObject& track, float vtxz) { - float eff = 1.; - int nspecies = 1; - if (mEfficiency.size() == static_cast(nspecies)) - eff = mEfficiency[ispecies]->GetBinContent(mEfficiency[ispecies]->FindBin(track.pt())); - else - eff = 1.0; - if (eff == 0) - return false; - weight_nue = 1. / eff; - if (mAcceptance.size() == static_cast(nspecies)) - weight_nua = mAcceptance[ispecies]->getNUA(track.phi(), track.eta(), vtxz); + if (mAcceptance.size() == static_cast(1)) + weight_nua = mAcceptance[0]->getNUA(track.phi(), track.eta(), vtxz); else weight_nua = 1; return true; } - // event selection + /** + * @brief Set the Particle Nue Weight, for global track and ITS track, use different eff path + * + * @tparam TrackObject + * @param weight_nue + * @param track + * @param cent + * @param isGlobalTrack + * @return true weight setted succesfully, note that weight == 1 also return true; + * @return false eff got from graph == 0 + */ + template + bool setParticleNUEWeight(float& weight_nue, TrackObject& track, double cent, bool isGlobalTrack) + { + float eff = 1.; + + uint64_t sizeOfEffVec = mEfficiency.size(); + uint64_t sizeOfEffVec4ITS = mEfficiency4ITSOnly.size(); + + TH2* eff2D = 0; + TH2* eff2D4ITS = 0; + + /// @note 1. size check 2. load eff 3. dividezero check + switch (correctionPathOpts.cfgNUEOption.value) { + case 1: // 1d + if (sizeOfEffVec != 1) + break; + if (sizeOfEffVec4ITS != 1) + break; + + if (isGlobalTrack) + eff = mEfficiency[0]->GetBinContent(mEfficiency[0]->FindBin(track.pt())); + else + eff = mEfficiency4ITSOnly[0]->GetBinContent(mEfficiency4ITSOnly[0]->FindBin(track.pt())); + + if (eff == 0.) + return false; + + break; + // end 1d + + case 2: // 2d + if (sizeOfEffVec != 1) + break; + if (sizeOfEffVec4ITS != 1) + break; + + eff2D = dynamic_cast(mEfficiency[0]); + eff2D4ITS = dynamic_cast(mEfficiency4ITSOnly[0]); + + if (!eff2D || !eff2D4ITS) { + LOGF(warning, "failed while converting TH1 to TH2! skip eff apply"); + break; + } + + if (isGlobalTrack) { + int ptBin = eff2D->GetXaxis()->FindBin(track.pt()); + int centBin = eff2D->GetYaxis()->FindBin(cent); + eff = eff2D->GetBinContent(ptBin, centBin); + } else { + int ptBin = eff2D4ITS->GetXaxis()->FindBin(track.pt()); + int centBin = eff2D4ITS->GetYaxis()->FindBin(cent); + eff = eff2D4ITS->GetBinContent(ptBin, centBin); + } + + if (eff == 0.) + return false; + + break; + // end 2d + + /// @todo add pid NUE eff + case 3: // pid + if (sizeOfEffVec != 3) + break; + if (sizeOfEffVec4ITS != 3) + break; + + break; + // end pid + + default: + break; + } + + weight_nue = 1. / eff; + return true; + } + + // correction apply function + + // track cut functions + + /** + * @brief cut MC particles + * @note include + * 1. eta cut + * 2. pt cut + * 3. stable partccle + * + * @tparam mcParticle + * @param particle + * @return true + * @return false + */ + template + bool particleSelected(mcParticle& particle) + { + // eta + if (std::fabs(particle.eta()) > trkQualityOpts.cfgCutEta.value) + return false; + // pt + if (particle.pt() < trkQualityOpts.cfgCutPtMin.value) + return false; + if (particle.pt() > trkQualityOpts.cfgCutPtMax.value) + return false; + // stable particle + if (!isStable(particle.pdgCode())) + return false; + + return true; + } + + /** + * @brief global track selection, cut for specified detector is not include + * @note include: 1. dcaxy + * 2. pt cut + * 3. eta + * 4. dcaz + * + * + * @tparam TTrack + * @param track + * @return true pass selection + * @return false reject track + */ + template + bool trackSelectedGlobal(TTrack& track) + { + // dca xy cut + // note that z cut is in filter + if (dcaCutOpts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > dcaCutOpts.fPtDepDCAxy->Eval(track.pt()))) + return false; + + // pt + if (!((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value))) + return false; + + // eta + if (std::fabs(track.eta()) > trkQualityOpts.cfgCutEta.value) + return false; + + // dca z + if (std::fabs(track.dcaZ()) > dcaCutOpts.cfgCutDCAz.value) + return false; + + return true; + } + + /** + * @brief cut for ITS, include: + * 1. its n cluster + * 2. its chi2 + * + * @tparam TTrack + * @param track + * @return true + * @return false + */ + template + bool trackSelected4ITS(TTrack& track) + { + // its ncls cut + if (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + return false; + + // its chi2 + if (track.itsChi2NCl() > trkQualityOpts.cfgITSChi2NDF.value) + return false; + + return true; + } + + /** + * @brief cut for TPC, include + * 1. TPC cross rows + * 2. tpc n cluster + * 3. tpc chi2 + * + * @tparam TTrack + * @param track + * @return true + * @return false + */ + template + bool trackSelected4TPC(TTrack& track) + { + // tpc crossedrows cut + if (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) + return false; + // tpc ncls cut + if (track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) + return false; + // tpc chi2 + if (track.tpcChi2NCl() > cfgCutChi2prTPCcls) + return false; + + return true; + } + + // track cut + + // event selection functions + + /** + * @brief fill eventCount for different function + * + * @param funcName + * @param position + */ + void fillEventCountHelper(MyFunctionName funcName, double position) + { + switch (funcName) { + case MyFunctionName::funcProcessData: + registry.fill(HIST("hEventCount/processData"), position); + break; + case MyFunctionName::funcDetectorPidQA: + registry.fill(HIST("hEventCount/detectorPidQA"), position); + break; + case MyFunctionName::funcFillCorrectionGraph: + registry.fill(HIST("hEventCount/fillCorrectionGraph"), position); + break; + case MyFunctionName::funcProcessReco: + registry.fill(HIST("hEventCount/processReco"), position); + break; + case MyFunctionName::funcProcessSim: + registry.fill(HIST("hEventCount/processSim"), position); + break; + + default: + LOGF(warning, "could not find event count graph"); + break; + } + } + + /** + * @brief collision selection + * @note include: 1. TRD triggered + * 2. collisions close to Time Frame borders + * 3. ITS ROF border + * 4. pile up + * 5. mathc z of PV by tracks and z of PV from FT0 A-C + * 6. no collisions in specified time range + * 7. good ITS layer + * 8. vz cut && multiplicity cut + * 9. occupacy cut + * 10. V0A T0A 5 sigma cut + * 11. interaction rate + * + * @tparam TCollision + * @param collision + * @param centrality + * @param interactionRate + * @param functionName need to fill graph in different function, dont fill the same graph! + * @return true + * @return false + */ template - bool eventSelected(TCollision collision, const float centrality, float interactionRate = -1) + bool eventSelected(TCollision& collision, const float centrality, float interactionRate = -1, MyFunctionName funcName = MyFunctionName::funcProcessData) { if (evtSeleOpts.cfgDoTVXinTRD.value && collision.alias_bit(kTVXinTRD)) { // TRD triggered return false; } - registry.fill(HIST("hEventCount"), 2.5); + fillEventCountHelper(funcName, 2.5); if (evtSeleOpts.cfgDoNoTimeFrameBorder.value && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { // reject collisions close to Time Frame borders // https://its.cern.ch/jira/browse/O2-4623 return false; } - registry.fill(HIST("hEventCount"), 3.5); + fillEventCountHelper(funcName, 3.5); if (evtSeleOpts.cfgDoNoITSROFrameBorder.value && !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; } - registry.fill(HIST("hEventCount"), 4.5); + fillEventCountHelper(funcName, 4.5); if (evtSeleOpts.cfgDoNoSameBunchPileup.value && !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; } - registry.fill(HIST("hEventCount"), 5.5); + fillEventCountHelper(funcName, 5.5); if (evtSeleOpts.cfgDoIsGoodZvtxFT0vsPV.value && !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; } - registry.fill(HIST("hEventCount"), 6.5); + fillEventCountHelper(funcName, 6.5); if (evtSeleOpts.cfgDoNoCollInTimeRangeStandard.value && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { // no collisions in specified time range return 0; } - registry.fill(HIST("hEventCount"), 7.5); + fillEventCountHelper(funcName, 7.5); if (evtSeleOpts.cfgDoIsGoodITSLayersAll.value && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { // cut time intervals with dead ITS staves return 0; } - registry.fill(HIST("hEventCount"), 8.5); + fillEventCountHelper(funcName, 8.5); float vtxz = -999; if (collision.numContrib() > 1) { vtxz = collision.posZ(); @@ -878,11 +1654,11 @@ struct PidFlowPtCorr { if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) return false; } - registry.fill(HIST("hEventCount"), 9.5); + fillEventCountHelper(funcName, 9.5); if (occupancy > evtSeleOpts.cfgCutOccupancyHigh.value) return 0; - registry.fill(HIST("hEventCount"), 10.5); + fillEventCountHelper(funcName, 10.5); // V0A T0A 5 sigma cut if (evtSeleOpts.cfgDoV0AT0Acut.value) { @@ -890,21 +1666,26 @@ struct PidFlowPtCorr { if (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nsigma * fT0AV0ASigma->Eval(collision.multFT0A())) return 0; } - registry.fill(HIST("hEventCount"), 11.5); + fillEventCountHelper(funcName, 11.5); registry.fill(HIST("hInteractionRate"), interactionRate); if (interactionRate > 0 && interactionRate < evtSeleOpts.cfgCutminIR.value) return false; - registry.fill(HIST("hEventCount"), 12.5); + fillEventCountHelper(funcName, 12.5); if (interactionRate > evtSeleOpts.cfgCutmaxIR.value) return false; - registry.fill(HIST("hEventCount"), 13.5); + fillEventCountHelper(funcName, 13.5); return true; } + // event selection + + // main functions + void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks) { + // sub region, init // init float rndm = fRndm->Rndm(); int nTot = tracks.size(); @@ -915,19 +1696,24 @@ struct PidFlowPtCorr { // end init // collision cut - // include : 1.track.size 2.collision.sel8 3.this->evenSelected - registry.fill(HIST("hEventCount"), 0.5); + // include : 1.track.size 2.collision.sel8 3. evenSelected + registry.fill(HIST("hEventCount/processData"), 0.5); if (nTot < 1) return; fGFW->Clear(); const auto cent = collision.centFT0C(); if (!collision.sel8()) return; - registry.fill(HIST("hEventCount"), 1.5); + registry.fill(HIST("hEventCount/processData"), 1.5); if (!eventSelected(collision, cent, interactionRate)) return; // end collision cut + // pt spectra + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.fill(HIST("ptSpectra/hCentEventCountData"), cent); + } // switchsOpts.cfgOutPutPtSpectra.value + // correction loadCorrections(bc.timestamp()); float vtxz = collision.posZ(); @@ -940,7 +1726,7 @@ struct PidFlowPtCorr { double psi2Est = 0, psi3Est = 0, psi4Est = 0; float wEPeff = 1; double v2 = 0, v3 = 0, v4 = 0; - if (cfgDoLocDenCorr) { + if (switchsOpts.cfgDoLocDenCorr.value) { double q2x = 0, q2y = 0; double q3x = 0, q3y = 0; double q4x = 0, q4y = 0; @@ -964,20 +1750,138 @@ struct PidFlowPtCorr { v4 = funcV4->Eval(cent); } // cfgDoLocDenCorr - float weff = 1; - float wacc = 1; double ptSum = 0; double ptSumw2 = 0; double nch = 0; double nchSquare = 0; double ptSquareSum = 0; - // fill GFW ref flow + double nchCorrectedPassed = 0; + double nchPassedSelection = 0; + + if (switchsOpts.cfgDebugMyCode.value) { + LOGF(info, "===================================="); + } + + // val for pid particles + double pionPtSum = 0; + double kaonPtSum = 0; + double protonPtSum = 0; + + double nPionWeighted = 0; + double nKaonWeighted = 0; + double nProtonWeighted = 0; + + double pionPtSumw2 = 0; + double kaonPtSumw2 = 0; + double protonPtSumw2 = 0; + + double nPionSquare = 0; + double nKaonSquare = 0; + double nProtonSquare = 0; + + double pionPtSquareSum = 0; + double kaonPtSquareSum = 0; + double protonPtSquareSum = 0; + // end val for pid particles + + /// @note calculate pt + /// use ITS only for (const auto& track : tracks) { - if (cfgDoAccEffCorr) { - if (!setCurrentParticleWeights(weff, wacc, track, vtxz, 0)) + float weff = 1; + + // do nue + if (switchsOpts.cfgUseITSOnly4MeanPt.value) + setParticleNUEWeight(weff, track, cent, false); + else + setParticleNUEWeight(weff, track, cent, true); + // end do nue + + // track cut ITS only + if (!trackSelectedGlobal(track)) + continue; + if (!track.hasITS()) + continue; + if (!trackSelected4ITS(track)) + continue; + + if (switchsOpts.cfgUseITSOnly4MeanPt.value) { + if (track.hasTPC()) + continue; + } else { + if (!track.hasTPC()) + continue; + if (!trackSelected4TPC(track)) continue; - } // cfgDoAccEffCorr - if (cfgDoLocDenCorr) { + } + // end track cut its only + + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.fill(HIST("ptSpectra/hPtCentData4ITSOnly"), track.pt(), cent); + } + + // calculate ncharged(nch with weight) and pt + if (std::fabs(track.eta()) < trkQualityOpts.cfgRangeEta.value) { + nch += weff; + nchSquare += weff * weff; + ptSum += weff * track.pt(); + ptSumw2 += weff * weff * track.pt(); + ptSquareSum += weff * weff * track.pt() * track.pt(); + + if (isPion(track)) { + nPionWeighted += weff; + nPionSquare += weff * weff; + pionPtSum += weff * track.pt(); + pionPtSumw2 += weff * weff * track.pt(); + pionPtSquareSum += weff * weff * track.pt() * track.pt(); + } + if (isKaon(track)) { + nKaonWeighted += weff; + nKaonSquare += weff * weff; + kaonPtSum += weff * track.pt(); + kaonPtSumw2 += weff * weff * track.pt(); + kaonPtSquareSum += weff * weff * track.pt() * track.pt(); + } + if (isProton(track)) { + nProtonWeighted += weff; + nProtonSquare += weff * weff; + protonPtSum += weff * track.pt(); + protonPtSumw2 += weff * weff * track.pt(); + protonPtSquareSum += weff * weff * track.pt() * track.pt(); + } + } + // end calculate nch and pt + + nchCorrectedPassed += weff; + nchPassedSelection += 1; + + if (weff == 1. && switchsOpts.cfgDebugMyCode.value) { + LOGF(info, "weff is 1, if nue opt is open and this message appears a lot, check!"); + } + } + // end pt calculation using ITS only + + if (switchsOpts.cfgDebugMyCode.value) { + LOGF(info, Form("its only track num %f", nchPassedSelection)); + } + + int totalGlobalTrack = 0; + // calculate number of pid particle + int numOfPi = 0; + int numOfKa = 0; + int numOfPr = 0; + + /// @note fill v2 flow + // use global track + for (const auto& track : tracks) { + float weff = 1; + float wacc = 1; + + // do NUE && NUA + setParticleNUAWeight(wacc, track, vtxz); + setParticleNUEWeight(weff, track, cent, true); + // end do NUE && NUA + + if (switchsOpts.cfgDoLocDenCorr.value) { bool withinPtRef = (trkQualityOpts.cfgCutPtMin.value < track.pt()) && (track.pt() < trkQualityOpts.cfgCutPtMax.value); if (withinPtRef) { double fphi = v2 * std::cos(2 * (track.phi() - psi2Est)) + v3 * std::cos(3 * (track.phi() - psi3Est)) + v4 * std::cos(4 * (track.phi() - psi4Est)); @@ -993,14 +1897,68 @@ struct PidFlowPtCorr { } } // cfgDoLocDenCorr - // track cut - if (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (switchsOpts.cfgDebugMyCode.value) { + // pt eff weight graph + { + int ptBin = debugHist.hPtEffWeight->GetXaxis()->FindBin(track.pt()); + debugHist.hPtEffWeight->SetBinContent(ptBin, weff); + } + // end pt eff weight graph + + // pt eff 2D weight graph + { + int ptBin = debugHist.hPtCentEffWeight->GetXaxis()->FindBin(track.pt()); + int centBin = debugHist.hPtCentEffWeight->GetYaxis()->FindBin(cent); + debugHist.hPtCentEffWeight->SetBinContent(ptBin, centBin, weff); + } + // end pt eff 2D weight graph + + // THn wacc graph + { + // loop the vector, find the place to put (phi eta Vz) + int matchedPosition = -1; + for (uint64_t idxPosition = 0; idxPosition < runNumbers.size(); idxPosition++) { + if (runNumbers[idxPosition] == runNumber) { + matchedPosition = idxPosition; + break; + } + } + if (matchedPosition == -1) { + return; + } + // end find place to put run data + + int phiBin = debugHist.hRunNumberPhiEtaVertexWeight->GetAxis(1)->FindBin(track.phi()); + int etaBin = debugHist.hRunNumberPhiEtaVertexWeight->GetAxis(2)->FindBin(track.eta()); + int vzBin = debugHist.hRunNumberPhiEtaVertexWeight->GetAxis(3)->FindBin(vtxz); + int Bins[4] = {matchedPosition + 1, phiBin, etaBin, vzBin}; + debugHist.hRunNumberPhiEtaVertexWeight->SetBinContent(Bins, wacc); + } + // end thn wacc graph + } // cfgDebugMycode + + // track cut, global + ITS + TPC + if (!trackSelectedGlobal(track)) + continue; + if (!track.hasITS()) + continue; + if (!track.hasTPC()) continue; - if (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) + if (!trackSelected4ITS(track)) continue; - if (track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) + if (!trackSelected4TPC(track)) continue; + // end track cut + totalGlobalTrack++; + + if (switchsOpts.cfgDebugMyCode.value && weff == 1.) { + LOGF(info, "weff for global track is 1, if NUE is open and this appears a lot, check!"); + } + + if (switchsOpts.cfgDebugMyCode.value && wacc == 1.) { + LOGF(info, "wacc for global track is 1, if NUA is open and this appears alot, check!"); + } // fill QA hist registry.fill(HIST("hPhi"), track.phi()); @@ -1010,47 +1968,50 @@ struct PidFlowPtCorr { registry.fill(HIST("hPt"), track.pt()); // end fill QA hist - // track pt cut - if (!((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value))) - continue; - // end track pt cut + // pt spectra + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.fill(HIST("ptSpectra/hPtCentData"), track.pt(), cent); + } // fill GFW // bit mask 1: fill CHARGED PARTICLES fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) - if (this->isPion(track)) { + if (isPion(track)) { // bitmask 18: 0010010 fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 18); // fill PIONS and overlap Pions + numOfPi++; } - if (this->isKaon(track)) { + if (isKaon(track)) { // bitmask 36: 0100100 fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 36); // fill KAONS and overlap Kaons + numOfKa++; } - if (this->isProton(track)) { + if (isProton(track)) { // bitmask 72: 1001000 fGFW->Fill(track.eta(), 0, track.phi(), wacc * weff, 72); // fill PROTONS and overlap Protons + numOfPr++; } // end fill GFW + } // end track loop for v2 calculation - if (cfgOutputNUAWeights) - fWeightsREF->fill(track.phi(), track.eta(), vtxz, track.pt(), cent, 0); + // sub region, fill graphs after 2 loop on all tracks + if (particleAbundanceOpts.cfgOutPutAbundanceDis) { + registry.fill(HIST("abundance/hNumOfPiEventCount"), numOfPi); + registry.fill(HIST("abundance/hNumOfKaEventCount"), numOfKa); + registry.fill(HIST("abundance/hNumOfPrEventCount"), numOfPr); + } // outputabundacedis - // calculate ncharged(nch with weight) and pt - if (std::fabs(track.eta()) < trkQualityOpts.cfgRangeEta.value) { - nch += weff; - nchSquare += weff * weff; - ptSum += weff * track.pt(); - ptSumw2 += weff * weff * track.pt(); - ptSquareSum += weff * weff * track.pt() * track.pt(); - } - // end calculate nch and pt - } // end track loop + if (switchsOpts.cfgDebugMyCode.value) { + LOGF(info, Form("global track num %d", totalGlobalTrack)); + } + + registry.fill(HIST("hNchUnCorrectedVSNchCorrected"), nchPassedSelection, nchCorrectedPassed); // fill hist using fGFW if (nch > 0) { @@ -1060,12 +2021,12 @@ struct PidFlowPtCorr { fillFC(MyParticleType::kCharged, corrconfigs.at(3), cent, rndm, "c32"); fillFC(MyParticleType::kCharged, corrconfigs.at(4), cent, rndm, "c34"); - fillFC(MyParticleType::kPion, corrconfigs.at(5), cent, rndm, "c22"); - fillFC(MyParticleType::kPion, corrconfigs.at(6), cent, rndm, "c22"); - fillFC(MyParticleType::kKaon, corrconfigs.at(7), cent, rndm, "c22"); - fillFC(MyParticleType::kKaon, corrconfigs.at(8), cent, rndm, "c22"); - fillFC(MyParticleType::kProton, corrconfigs.at(9), cent, rndm, "c22"); - fillFC(MyParticleType::kProton, corrconfigs.at(10), cent, rndm, "c22"); + fillFC(MyParticleType::kPion, corrconfigs.at(35), cent, rndm, "c22Full"); + fillFC(MyParticleType::kPion, corrconfigs.at(36), cent, rndm, "c22Full"); + fillFC(MyParticleType::kKaon, corrconfigs.at(37), cent, rndm, "c22Full"); + fillFC(MyParticleType::kKaon, corrconfigs.at(38), cent, rndm, "c22Full"); + fillFC(MyParticleType::kProton, corrconfigs.at(39), cent, rndm, "c22Full"); + fillFC(MyParticleType::kProton, corrconfigs.at(40), cent, rndm, "c22Full"); fillFC(MyParticleType::kPion, corrconfigs.at(11), cent, rndm, "c24"); fillFC(MyParticleType::kPion, corrconfigs.at(12), cent, rndm, "c24"); @@ -1088,13 +2049,26 @@ struct PidFlowPtCorr { fillFC(MyParticleType::kProton, corrconfigs.at(27), cent, rndm, "c34"); fillFC(MyParticleType::kProton, corrconfigs.at(28), cent, rndm, "c34"); - fillFC(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, "c22pure"); - fillFC(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, "c22pure"); - fillFC(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, "c22pure"); + bool filledPi = fillFC(MyParticleType::kPion, corrconfigs.at(29), cent, rndm, "c22pure"); + bool filledKa = fillFC(MyParticleType::kKaon, corrconfigs.at(30), cent, rndm, "c22pure"); + bool filledPr = fillFC(MyParticleType::kProton, corrconfigs.at(31), cent, rndm, "c22pure"); + fillFC(MyParticleType::kPion, corrconfigs.at(32), cent, rndm, "c32pure"); fillFC(MyParticleType::kKaon, corrconfigs.at(33), cent, rndm, "c32pure"); fillFC(MyParticleType::kProton, corrconfigs.at(34), cent, rndm, "c32pure"); + if (filledPi || !switchsOpts.cfgCheck2MethodDiff.value) { + fillFC(MyParticleType::kPion, corrconfigs.at(5), cent, rndm, "c22"); + fillFC(MyParticleType::kPion, corrconfigs.at(6), cent, rndm, "c22"); + } + if (filledKa || !switchsOpts.cfgCheck2MethodDiff.value) { + fillFC(MyParticleType::kKaon, corrconfigs.at(7), cent, rndm, "c22"); + fillFC(MyParticleType::kKaon, corrconfigs.at(8), cent, rndm, "c22"); + } + if (filledPr || !switchsOpts.cfgCheck2MethodDiff.value) { + fillFC(MyParticleType::kProton, corrconfigs.at(9), cent, rndm, "c22"); + fillFC(MyParticleType::kProton, corrconfigs.at(10), cent, rndm, "c22"); + } fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(0), cent, rndm, nch, nch, "c22TrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(1), cent, rndm, nch, nch, "c24TrackWeight"); fillFCvnpt(MyParticleType::kCharged, corrconfigs.at(2), cent, rndm, nch, nch, "c22FullTrackWeight"); @@ -1127,18 +2101,96 @@ struct PidFlowPtCorr { fillProfilePOIvnpt(corrconfigs.at(9), HIST("pr/c22dmeanpt"), cent, ptSum, nch); fillProfilePOIvnpt(corrconfigs.at(10), HIST("pr/c22dmeanpt"), cent, ptSum, nch); - this->fFCCh->FillProfile("hMeanPt", cent, (ptSum / nch), nch, rndm); + fillFC4PtC22(cent, ptSum, nch, rndm); + if (nPionWeighted > 0) + fillFC4PtC22(cent, rndm, MyParticleType::kPion, pionPtSum, nPionWeighted); + + if (nKaonWeighted > 0) + fillFC4PtC22(cent, rndm, MyParticleType::kKaon, kaonPtSum, nKaonWeighted); + + if (nProtonWeighted > 0) + fillFC4PtC22(cent, rndm, MyParticleType::kProton, protonPtSum, nProtonWeighted); + + if (switchsOpts.cfgOutPutPtSpectra.value) { + // charged calculation + double NpairCharged = fGFW->Calculate(corrconfigs.at(0), 0, true).real(); + double chargedC22 = NpairCharged > 0 ? fGFW->Calculate(corrconfigs.at(0), 0, false).real() / NpairCharged : 0; + // end charged calculation + + // pi + double pidChargedC22Pi = getPidC22InOneEvent(corrconfigs.at(5), corrconfigs.at(6)); + if (pidChargedC22Pi > 0 && chargedC22 > 0) + registry.fill(HIST("c22PrimeVsc22/Pi"), pidChargedC22Pi, chargedC22); + // end pi + + // Ka + double pidKaonC22 = getPidC22InOneEvent(corrconfigs.at(7), corrconfigs.at(8)); + if (pidKaonC22 > 0 && chargedC22 > 0) + registry.fill(HIST("c22PrimeVsc22/Ka"), pidKaonC22, chargedC22); + // end Ka + + // Pr + double pidProtonC22 = getPidC22InOneEvent(corrconfigs.at(9), corrconfigs.at(10)); + if (pidProtonC22 > 0 && chargedC22 > 0) + registry.fill(HIST("c22PrimeVsc22/Pr"), pidProtonC22, chargedC22); + // end Pr + } + + fFCCh->FillProfile("hMeanPt", cent, (ptSum / nch), nch, rndm); + + if (nPionWeighted > 0) + fFCPi->FillProfile("hMeanPt", cent, (pionPtSum / nPionWeighted), nPionWeighted, rndm); + + if (nKaonWeighted > 0) + fFCKa->FillProfile("hMeanPt", cent, (kaonPtSum / nKaonWeighted), nKaonWeighted, rndm); + + if (nProtonWeighted > 0) + fFCPr->FillProfile("hMeanPt", cent, (protonPtSum / nProtonWeighted), nProtonWeighted, rndm); double nchDiff = nch * nch - nchSquare; - if (nchDiff) { - this->fFCCh->FillProfile("ptSquareAve", cent, - (ptSum * ptSum - ptSquareSum) / nchDiff, - nchDiff, rndm); - - this->fFCCh->FillProfile("ptAve", cent, - (nch * ptSum - ptSumw2) / nchDiff, - nchDiff, rndm); + if (nchDiff > 1e-3) { + fFCCh->FillProfile("ptSquareAve", cent, + (ptSum * ptSum - ptSquareSum) / nchDiff, + nchDiff, rndm); + + fFCCh->FillProfile("ptAve", cent, + (nch * ptSum - ptSumw2) / nchDiff, + nchDiff, rndm); + } + + double pionDiff = nPionWeighted * nPionWeighted - nPionSquare; + if (pionDiff > 1e-3) { + fFCPi->FillProfile("ptSquareAve", cent, + (pionPtSum * pionPtSum - pionPtSquareSum) / pionDiff, + pionDiff, rndm); + + fFCPi->FillProfile("ptAve", cent, + (nPionWeighted * pionPtSum - pionPtSumw2) / pionDiff, + pionDiff, rndm); } + + double kaonDiff = nKaonWeighted * nKaonWeighted - nKaonSquare; + if (kaonDiff > 1e-3) { + fFCKa->FillProfile("ptSquareAve", cent, + (kaonPtSum * kaonPtSum - kaonPtSquareSum) / kaonDiff, + kaonDiff, rndm); + + fFCKa->FillProfile("ptAve", cent, + (nKaonWeighted * kaonPtSum - kaonPtSumw2) / kaonDiff, + kaonDiff, rndm); + } + + double protonDiff = nProtonWeighted * nProtonWeighted - nProtonSquare; + if (protonDiff > 1e-3) { + fFCPr->FillProfile("ptSquareAve", cent, + (protonPtSum * protonPtSum - protonPtSquareSum) / protonDiff, + protonDiff, rndm); + + fFCPr->FillProfile("ptAve", cent, + (nProtonWeighted * protonPtSum - protonPtSumw2) / protonDiff, + protonDiff, rndm); + } + } // end fill hist using fillProfile } PROCESS_SWITCH(PidFlowPtCorr, processData, "", true); @@ -1160,23 +2212,24 @@ struct PidFlowPtCorr { // end init // collision cut - // include : 1.track.size 2.collision.sel8 3.this->evenSelected + // include : 1.track.size 2.collision.sel8 3. evenSelected + registry.fill(HIST("hEventCount/fillCorrectionGraph"), 0.5); if (nTot < 1) return; fGFW->Clear(); const auto cent = collision.centFT0C(); if (!collision.sel8()) return; - - if (!eventSelected(collision, cent, interactionRate)) + registry.fill(HIST("hEventCount/fillCorrectionGraph"), 1.5); + if (!eventSelected(collision, cent, interactionRate, MyFunctionName::funcFillCorrectionGraph)) return; // end collision cut // loop the vector, find the place to put (phi eta Vz) // if the run number is new, create one int matchedPosition = -1; - for (uint64_t idxPosition = 0; idxPosition < this->runNumbers.size(); idxPosition++) { - if (this->runNumbers[idxPosition] == runNumber) { + for (uint64_t idxPosition = 0; idxPosition < runNumbers.size(); idxPosition++) { + if (runNumbers[idxPosition] == runNumber) { matchedPosition = idxPosition; break; } @@ -1189,11 +2242,15 @@ struct PidFlowPtCorr { // loop all the track for (const auto& track : tracks) { // track cut - if (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (!trackSelectedGlobal(track)) + continue; + if (!track.hasITS()) continue; - if (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) + if (!track.hasTPC()) continue; - if (track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) + if (!trackSelected4ITS(track)) + continue; + if (!trackSelected4TPC(track)) continue; // end track cut @@ -1206,7 +2263,8 @@ struct PidFlowPtCorr { PROCESS_SWITCH(PidFlowPtCorr, fillCorrectionGraph, "", true); /** - * @brief this main function is used to check the PID performance of ITS TOC TPC + * @brief this main function is used to check the PID performance of ITS TOC TPC, also used to do QA + * @note open switch outputQA if use it * * @param collision * @param tracks @@ -1219,29 +2277,61 @@ struct PidFlowPtCorr { auto bc = collision.bc_as(); int runNumber = bc.runNumber(); double interactionRate = rateFetcher.fetch(ccdb.service, bc.timestamp(), runNumber, "ZNC hadronic") * 1.e-3; + // end init + // loop the vector, find the place to put + int matchedPosition = -1; + for (uint64_t idxPosition = 0; idxPosition < runNumbers.size(); idxPosition++) { + if (runNumbers[idxPosition] == runNumber) { + matchedPosition = idxPosition; + break; + } + } + if (matchedPosition == -1) { + return; + } + // end find place to put run data + + // fill some QA graph before collision cut + for (const auto& track : tracks) { + qaHistVector[matchedPosition].hPhiRunByRunBefore->Fill(track.phi()); + } + // end fill some QA graph before collision cut + + // collision cut + registry.fill(HIST("hEventCount/detectorPidQA"), 0.5); if (nTot < 1) return; fGFW->Clear(); const auto cent = collision.centFT0C(); if (!collision.sel8()) return; - - if (!eventSelected(collision, cent, interactionRate)) + registry.fill(HIST("hEventCount/detectorPidQA"), 1.5); + if (!eventSelected(collision, cent, interactionRate, MyFunctionName::funcDetectorPidQA)) return; // loadCorrections(bc.timestamp()); // end cut and correction + // fill some QA graph after collision cut + for (const auto& track : tracks) { + qaHistVector[matchedPosition].hPhiRunByRunAfter->Fill(track.phi()); + qaHistVector[matchedPosition].hITSnclsVsPhi->Fill(track.phi(), track.itsNCls()); + qaHistVector[matchedPosition].hITSChi2VsPhi->Fill(track.phi(), track.itsChi2NCl()); + } + // end fill some QA graph after collision cut + // start filling graphs for (const auto& track : tracks) { // track cut - if (!((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value))) + if (!trackSelectedGlobal(track)) continue; - if (track.itsNCls() <= trkQualityOpts.cfgITSNCls.value) + if (!track.hasITS()) continue; - if (track.tpcNClsCrossedRows() <= trkQualityOpts.cfgTPCCrossedRows.value) + if (!track.hasTPC()) continue; - if (track.tpcNClsFound() <= trkQualityOpts.cfgTPCNCls.value) + if (!trackSelected4ITS(track)) + continue; + if (!trackSelected4TPC(track)) continue; // end track cut @@ -1265,17 +2355,101 @@ struct PidFlowPtCorr { PROCESS_SWITCH(PidFlowPtCorr, detectorPidQA, "", true); /** - * @brief this function is used to loop mc events - * @note implemented: - * 1.fill mc pt hist to calculate efficiency(correction/hCentPtMC, correction/hCentPtData) + * @brief this function is used to fill Reco particles in order to calculate pt eff + * @note Efficiency = Efficiency(pt, cent) + * + * @param collision + * @param tracks + */ + void processReco(FilteredCollisionsWithMCLabel::iterator const& collision, + aod::BCsWithTimestamps const&, + FilteredTracksWithMCLabel const& tracks, + aod::McParticles const&, + aod::McCollisions const&) + { + // init && cut + registry.fill(HIST("hEventCount/processReco"), 0.5); + if (tracks.size() <= 0) + return; + if (!collision.sel8()) + return; + registry.fill(HIST("hEventCount/processReco"), 1.5); + + const auto cent = collision.centFT0C(); + auto bc = collision.bc_as(); + int runNumber = bc.runNumber(); + double interactionRate = rateFetcher.fetch(ccdb.service, bc.timestamp(), runNumber, "ZNC hadronic") * 1.e-3; + + if (!eventSelected(collision, cent, interactionRate, MyFunctionName::funcProcessReco)) + return; + // end init && cut + + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.fill(HIST("ptSpectra/hCentEventCountMcRec"), cent); + } // cfgoutputptspectra + + // loop tracks + for (const auto& track : tracks) { + // track cut + if (!trackSelectedGlobal(track)) + continue; + // end track cut + + // loop track's matched MC particle + if (track.has_mcParticle()) { + auto mcParticle = track.mcParticle(); + // fill graph + if (particleSelected(mcParticle)) { + /// @note global track, fill rec hist + if (track.hasITS() && track.hasTPC() && trackSelected4ITS(track) && trackSelected4TPC(track)) { + // graph for all particles + registry.fill(HIST("correction/hPtCentMcRec"), track.pt(), cent); + + // identify particle and fill graph + if (isPion(track)) { + registry.fill(HIST("correction/hPtCentMcRecPi"), track.pt(), cent); + } + if (isKaon(track)) { + registry.fill(HIST("correction/hPtCentMcRecKa"), track.pt(), cent); + } + if (isProton(track)) { + registry.fill(HIST("correction/hPtCentMcRecPr"), track.pt(), cent); + } + // end identify particle and fill graph + } + // end global track, fill rec hist + + /// @note ITS track. fill rec hist + if (track.hasITS() && !track.hasTPC() && trackSelected4ITS(track)) { + registry.fill(HIST("correction/hPtCentMcRec4ITSOnly"), track.pt(), cent); + } + // end ITS track. fill rec hist + } + // end fill graph + } + // end loop track's matched MC particle + } + // end loop tracks + } + PROCESS_SWITCH(PidFlowPtCorr, processReco, "function used to do pt eff, NOTE (OutPutMc, processReco, processSim) should be open", true); + + /** + * @brief this function is used to calculate pt eff * + * @param mcCollision + * @param collisions + * @param mcParticles */ - void processMCGen(FilteredMcCollisions::iterator const&, - aod::BCsWithTimestamps const&, - FilteredMcParticles const& mcParticles, - soa::SmallGroups> const& collisions, - AodTracks const&) + void processSim(FilteredMcCollisions::iterator const&, + aod::BCsWithTimestamps const&, + soa::SmallGroups> const& collisions, + FilteredMcParticles const& mcParticles, + FilteredTracksWithMCLabel const& tracks) { + registry.fill(HIST("hEventCount/processSim"), 0.5); + if (collisions.size() <= 0) + return; + // cut && init // loop all the collisions reco matched to MC double cent = -1; @@ -1285,39 +2459,52 @@ struct PidFlowPtCorr { double interactionRate = rateFetcher.fetch(ccdb.service, bc.timestamp(), runNumber, "ZNC hadronic") * 1.e-3; cent = oneColl.centFT0C(); + auto groupedTracks = tracks.sliceBy(perCollision, oneColl.globalIndex()); + if (groupedTracks.size() <= 0) + continue; + // collision cut if (!oneColl.sel8()) - return; - if (!eventSelected(oneColl, cent, interactionRate)) - return; - // end collision cut - } - // end loop all the collisions reco matched to MC - // end cut && init + continue; + registry.fill(HIST("hEventCount/processSim"), 1.5); - // loop all the particle - for (const auto& mcPart : mcParticles) { - // track cut - if (!mcPart.isPhysicalPrimary()) + if (!eventSelected(oneColl, cent, interactionRate, MyFunctionName::funcProcessSim)) continue; - // end track cut + // end collision cut - registry.fill(HIST("correction/hCentPtMC"), cent, mcPart.pt()); + if (switchsOpts.cfgOutPutPtSpectra.value) { + registry.fill(HIST("ptSpectra/hCentEventCountMcGen"), cent); + } // cfgoutputptspectra - // loop real track - if (mcPart.has_tracks()) { - auto const& tracks = mcPart.tracks_as(); - for (const auto& track : tracks) { - // track select - // end track select - registry.fill(HIST("correction/hCentPtData"), cent, track.pt()); + // loop mc particles + for (const auto& mcParticle : mcParticles) { + // fill graph + if (particleSelected(mcParticle) && mcParticle.isPhysicalPrimary()) { + // graph for all particles + registry.fill(HIST("correction/hPtCentMcGen"), mcParticle.pt(), cent); + + // identify particle and fill graph + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) { + registry.fill(HIST("correction/hPtCentMcGenPi"), mcParticle.pt(), cent); + } + if (std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus) { + registry.fill(HIST("correction/hPtCentMcGenKa"), mcParticle.pt(), cent); + } + if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton) { + registry.fill(HIST("correction/hPtCentMcGenPr"), mcParticle.pt(), cent); + } + // end identify particle and fill graph } + // end fill graph } - // end loop real track + // end loop mc particles } - // end loop all the particle + // end loop all the collisions reco matched to MC + // end cut && init } - PROCESS_SWITCH(PidFlowPtCorr, processMCGen, "", true); + PROCESS_SWITCH(PidFlowPtCorr, processSim, "function used to do pt eff, NOTE (OutPutMc, processReco, processSim) should be open", true); + + // main function }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/GenericFramework/Core/FlowContainer.cxx b/PWGCF/GenericFramework/Core/FlowContainer.cxx index 532eb35c80c..338c6de9cf1 100644 --- a/PWGCF/GenericFramework/Core/FlowContainer.cxx +++ b/PWGCF/GenericFramework/Core/FlowContainer.cxx @@ -422,7 +422,7 @@ TH1D* FlowContainer::GetCorrXXVsPt(const char* order, double lminmulti, double l TProfile* profY = rhProfSub->ProfileY("profY", minm, maxm); TH1D* histY = ProfToHist(profY); TH1D* hist = new TH1D("temphist", "temphist", fNbinsPt, fbinsPt); - for (int ibin = 1; ibin < hist->GetNbinsX(); ibin++) { + for (int ibin = 1; ibin <= hist->GetNbinsX(); ibin++) { TString bLabel = rhProfSub->GetYaxis()->GetBinLabel(ibin + ybn1 - 1); hist->GetXaxis()->SetBinLabel(ibin, bLabel.Data()); hist->SetBinContent(ibin, histY->GetBinContent(ibin + ybn1 - 1)); diff --git a/PWGCF/GenericFramework/Core/FlowPtContainer.cxx b/PWGCF/GenericFramework/Core/FlowPtContainer.cxx index b8189636987..f527b05d6af 100644 --- a/PWGCF/GenericFramework/Core/FlowPtContainer.cxx +++ b/PWGCF/GenericFramework/Core/FlowPtContainer.cxx @@ -699,8 +699,9 @@ void FlowPtContainer::fillSubeventPtProfiles(const double& centmult, const doubl } ++subIndex; } - if (valid) + if (valid) { dynamic_cast(fSubList->At(histCounter))->FillProfile(centmult, val, (fEventWeight == EventWeight::UnityWeight) ? 1.0 : dn, rn); + } ++histCounter; } return; @@ -907,16 +908,18 @@ void FlowPtContainer::fillCMSubeventProfiles(const double& centmult, const doubl for (int im = 1; im <= mpar; im++) { indOffset += im; } + + std::vector validMpar = {0, 0, 0}; // 0th order correlation cmDenSub[0].push_back(1.); cmValSub[0].push_back(1.); cmDenSub[nSubevents - 1].push_back(1.); cmValSub[nSubevents - 1].push_back(1.); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)]); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)]); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 0)]); - cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] + 8 * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(3, 0)] + 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 0)] - 6 * insub[0][getVectorIndex(4, 0)]); + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)]); // cmDensub[0][1] = sum w + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)]); // cmDensub[0][2] = sum wi wj + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 0)]); // cmDensub[0][3] = sum wi wj wk + cmDenSub[0].push_back(insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] + 8 * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(3, 0)] + 3 * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 0)] - 6 * insub[0][getVectorIndex(4, 0)]); // cmDensub[0][4] = sum wi wj wk wl cmDenSub[nSubevents - 1].push_back(insub[nSubevents - 1][getVectorIndex(1, 0)]); cmDenSub[nSubevents - 1].push_back(insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 0)]); @@ -932,65 +935,68 @@ void FlowPtContainer::fillCMSubeventProfiles(const double& centmult, const doubl dynamic_cast(fSubCMList->At(indOffset + 0))->FillProfile(centmult, cmValSub[nSubevents - 1][1], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][1], rn); } - if (mpar < 2) - return; - if (insub[0][getVectorIndex(2, 0)] != 0 && cmDenSub[0][2] != 0) { - cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 2)])); - dynamic_cast(fSubCMList->At(1))->FillProfile(centmult, cmValSub[0][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); - cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 1)])); - dynamic_cast(fSubCMList->At(2))->FillProfile(centmult, cmValSub[0][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); - } - if (insub[nSubevents - 1][getVectorIndex(2, 0)] != 0 && cmDenSub[nSubevents - 1][2] != 0) { - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 2)])); - dynamic_cast(fSubCMList->At(indOffset + 1))->FillProfile(centmult, cmValSub[nSubevents - 1][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 1)])); - dynamic_cast(fSubCMList->At(indOffset + 2))->FillProfile(centmult, cmValSub[nSubevents - 1][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); - } - - if (mpar < 3) - return; - if (insub[0][getVectorIndex(3, 0)] != 0 && cmDenSub[0][3] != 0) { - cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 3)])); - dynamic_cast(fSubCMList->At(3))->FillProfile(centmult, cmValSub[0][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); - cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 2)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)])); - dynamic_cast(fSubCMList->At(4))->FillProfile(centmult, cmValSub[0][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); - cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 1)] - insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)])); - dynamic_cast(fSubCMList->At(5))->FillProfile(centmult, cmValSub[0][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); - } - if (insub[nSubevents - 1][getVectorIndex(3, 0)] != 0 && cmDenSub[nSubevents - 1][3] != 0) { - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 3)])); - dynamic_cast(fSubCMList->At(indOffset + 3))->FillProfile(centmult, cmValSub[nSubevents - 1][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 2)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)])); - dynamic_cast(fSubCMList->At(indOffset + 4))->FillProfile(centmult, cmValSub[nSubevents - 1][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 1)] - insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)])); - dynamic_cast(fSubCMList->At(indOffset + 5))->FillProfile(centmult, cmValSub[nSubevents - 1][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + if (mpar >= 2) { + if (insub[0][getVectorIndex(2, 0)] != 0 && cmDenSub[0][2] != 0) { + cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 2)])); + dynamic_cast(fSubCMList->At(1))->FillProfile(centmult, cmValSub[0][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); + cmValSub[0].push_back(1 / cmDenSub[0][2] * (insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 1)] - insub[0][getVectorIndex(2, 1)])); + dynamic_cast(fSubCMList->At(2))->FillProfile(centmult, cmValSub[0][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][2], rn); + } + if (insub[nSubevents - 1][getVectorIndex(2, 0)] != 0 && cmDenSub[nSubevents - 1][2] != 0) { + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 2)])); + dynamic_cast(fSubCMList->At(indOffset + 1))->FillProfile(centmult, cmValSub[nSubevents - 1][2], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][2] * (insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - insub[nSubevents - 1][getVectorIndex(2, 1)])); + dynamic_cast(fSubCMList->At(indOffset + 2))->FillProfile(centmult, cmValSub[nSubevents - 1][3], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][2], rn); + } + validMpar[0] = true; } - if (mpar < 4) - return; - if (insub[0][getVectorIndex(4, 0)] != 0 && cmDenSub[0][4] != 0) { - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 2)] + 8 * insub[0][getVectorIndex(3, 3)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(4, 4)])); - dynamic_cast(fSubCMList->At(6))->FillProfile(centmult, cmValSub[0][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 1)] + 6 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 2)] - 6 * insub[0][getVectorIndex(4, 3)])); - dynamic_cast(fSubCMList->At(7))->FillProfile(centmult, cmValSub[0][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 2)] - 4 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 2)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 1)] - 6 * insub[0][getVectorIndex(4, 2)])); - dynamic_cast(fSubCMList->At(8))->FillProfile(centmult, cmValSub[0][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 0)] + 2 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 0)] + 6 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(4, 1)])); - dynamic_cast(fSubCMList->At(9))->FillProfile(centmult, cmValSub[0][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); - } - if (insub[nSubevents - 1][getVectorIndex(4, 0)] != 0 && cmDenSub[nSubevents - 1][4] != 0) { - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 2)] + 8 * insub[nSubevents - 1][getVectorIndex(3, 3)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 4)])); - dynamic_cast(fSubCMList->At(indOffset + 6))->FillProfile(centmult, cmValSub[nSubevents - 1][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 6 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 2)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 3)])); - dynamic_cast(fSubCMList->At(indOffset + 7))->FillProfile(centmult, cmValSub[nSubevents - 1][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(2, 2)] - 4 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 2)])); - dynamic_cast(fSubCMList->At(indOffset + 8))->FillProfile(centmult, cmValSub[nSubevents - 1][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); - cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 0)] + 6 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 1)])); - dynamic_cast(fSubCMList->At(indOffset + 9))->FillProfile(centmult, cmValSub[nSubevents - 1][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + if (mpar >= 3) { + if (insub[0][getVectorIndex(3, 0)] != 0 && cmDenSub[0][3] != 0) { + cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 3)])); + dynamic_cast(fSubCMList->At(3))->FillProfile(centmult, cmValSub[0][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); + cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(3, 2)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)])); + dynamic_cast(fSubCMList->At(4))->FillProfile(centmult, cmValSub[0][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); + cmValSub[0].push_back(1 / cmDenSub[0][3] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] + 2 * insub[0][getVectorIndex(3, 1)] - insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)])); + dynamic_cast(fSubCMList->At(5))->FillProfile(centmult, cmValSub[0][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][3], rn); + } + if (insub[nSubevents - 1][getVectorIndex(3, 0)] != 0 && cmDenSub[nSubevents - 1][3] != 0) { + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 3)])); + dynamic_cast(fSubCMList->At(indOffset + 3))->FillProfile(centmult, cmValSub[nSubevents - 1][4], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 2)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)])); + dynamic_cast(fSubCMList->At(indOffset + 4))->FillProfile(centmult, cmValSub[nSubevents - 1][5], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][3] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(3, 1)] - insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)])); + dynamic_cast(fSubCMList->At(indOffset + 5))->FillProfile(centmult, cmValSub[nSubevents - 1][6], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][3], rn); + } + validMpar[1] = true; + } + if (mpar >= 4) { + if (insub[0][getVectorIndex(4, 0)] != 0 && cmDenSub[0][4] != 0) { + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 2)] + 8 * insub[0][getVectorIndex(3, 3)] * insub[0][getVectorIndex(1, 1)] - 6 * insub[0][getVectorIndex(4, 4)])); + dynamic_cast(fSubCMList->At(6))->FillProfile(centmult, cmValSub[0][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 1)] + 3 * insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(2, 1)] + 6 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 2)] - 6 * insub[0][getVectorIndex(4, 3)])); + dynamic_cast(fSubCMList->At(7))->FillProfile(centmult, cmValSub[0][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 2)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 1)] + insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(2, 2)] - 4 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 2)] * insub[0][getVectorIndex(1, 0)] + 4 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 1)] + 2 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 1)] - 6 * insub[0][getVectorIndex(4, 2)])); + dynamic_cast(fSubCMList->At(8))->FillProfile(centmult, cmValSub[0][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + cmValSub[0].push_back(1 / cmDenSub[0][4] * (insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(1, 0)] * insub[0][getVectorIndex(1, 0)] - 3 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(2, 0)] * insub[0][getVectorIndex(1, 0)] + 3 * insub[0][getVectorIndex(2, 1)] * insub[0][getVectorIndex(2, 0)] + 2 * insub[0][getVectorIndex(1, 1)] * insub[0][getVectorIndex(3, 0)] + 6 * insub[0][getVectorIndex(3, 1)] * insub[0][getVectorIndex(1, 0)] - 6 * insub[0][getVectorIndex(4, 1)])); + dynamic_cast(fSubCMList->At(9))->FillProfile(centmult, cmValSub[0][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][4], rn); + } + if (insub[nSubevents - 1][getVectorIndex(4, 0)] != 0 && cmDenSub[nSubevents - 1][4] != 0) { + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 2)] + 8 * insub[nSubevents - 1][getVectorIndex(3, 3)] * insub[nSubevents - 1][getVectorIndex(1, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 4)])); + dynamic_cast(fSubCMList->At(indOffset + 6))->FillProfile(centmult, cmValSub[nSubevents - 1][7], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(2, 1)] + 6 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 2)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 3)])); + dynamic_cast(fSubCMList->At(indOffset + 7))->FillProfile(centmult, cmValSub[nSubevents - 1][8], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(2, 2)] - 4 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 2)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 4 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 1)] + 2 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 1)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 2)])); + dynamic_cast(fSubCMList->At(indOffset + 8))->FillProfile(centmult, cmValSub[nSubevents - 1][9], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + cmValSub[nSubevents - 1].push_back(1 / cmDenSub[nSubevents - 1][4] * (insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 3 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] * insub[nSubevents - 1][getVectorIndex(1, 0)] + 3 * insub[nSubevents - 1][getVectorIndex(2, 1)] * insub[nSubevents - 1][getVectorIndex(2, 0)] + 2 * insub[nSubevents - 1][getVectorIndex(1, 1)] * insub[nSubevents - 1][getVectorIndex(3, 0)] + 6 * insub[nSubevents - 1][getVectorIndex(3, 1)] * insub[nSubevents - 1][getVectorIndex(1, 0)] - 6 * insub[nSubevents - 1][getVectorIndex(4, 1)])); + dynamic_cast(fSubCMList->At(indOffset + 9))->FillProfile(centmult, cmValSub[nSubevents - 1][10], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[nSubevents - 1][4], rn); + } + validMpar[2] = true; } - // Fill cross terms for (int m = 2; m <= 4; ++m) { + if (!validMpar[m - 2]) + continue; for (int first = 1; first < m; ++first) { for (int second = first; second < m; ++second) { if (first > second) @@ -999,8 +1005,9 @@ void FlowPtContainer::fillCMSubeventProfiles(const double& centmult, const doubl for (int third = 1; third < m; ++third) { if (third > fourth) continue; - if (insub[0][getVectorIndex(m, 0)] != 0 && insub[nSubevents - 1][getVectorIndex(m, 0)] != 0 && cmDenSub[0][m] * cmDenSub[nSubevents - 1][m] != 0) + if (insub[0][getVectorIndex(m, 0)] != 0 && insub[nSubevents - 1][getVectorIndex(m, 0)] != 0 && cmDenSub[0][m] * cmDenSub[nSubevents - 1][m] != 0) { dynamic_cast(fSubCMList->FindObject(Form("cm%i_%i%isub1_%i%isub2", m, first, second, third, fourth)))->FillProfile(centmult, cmValSub[0][second * (second - 1) / 2 + second - first + 1] * cmValSub[nSubevents - 1][fourth * (fourth - 1) / 2 + fourth - third + 1], (fEventWeight == EventWeight::UnityWeight) ? 1.0 : cmDenSub[0][m] * cmDenSub[nSubevents - 1][m], rn); + } } } } diff --git a/PWGCF/GenericFramework/Tasks/CMakeLists.txt b/PWGCF/GenericFramework/Tasks/CMakeLists.txt index 338f173aa73..6238192e1be 100644 --- a/PWGCF/GenericFramework/Tasks/CMakeLists.txt +++ b/PWGCF/GenericFramework/Tasks/CMakeLists.txt @@ -18,3 +18,7 @@ o2physics_add_dpl_workflow(flow-gfw-light-ions SOURCES flowGfwLightIons.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(flow-gfw-v02 + SOURCES flowGfwV02.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index f0242a8a1b6..e43730e8212 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -22,19 +22,30 @@ #include "GFWWeights.h" #include "GFWWeightsList.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" #include #include #include @@ -46,6 +57,7 @@ #include #include +#include #include #include #include @@ -77,67 +89,153 @@ std::vector centbinning(90); int nBootstrap = 10; GFWRegions regions; GFWCorrConfigs configs; +GFWCorrConfigs configsV02; +GFWCorrConfigs configsV0; std::vector multGlobalCorrCutPars; std::vector multPVCorrCutPars; +std::vector multGlobalPVCorrCutPars; +std::vector multGlobalV0ACutPars; +std::vector multGlobalT0ACutPars; } // namespace o2::analysis::gfw +template +auto projectMatrix(Array2D const& mat, std::array& array1, std::array& array2, std::array& array3) +{ + for (auto j = 0; j < static_cast(mat.cols); ++j) { + array1[j] = mat(0, j); + array2[j] = mat(1, j); + array3[j] = mat(2, j); + } + return; +} +template +auto readMatrix(Array2D const& mat, P& array) +{ + for (auto i = 0; i < static_cast(mat.rows); ++i) { + for (auto j = 0; j < static_cast(mat.cols); ++j) { + array[i][j] = mat(i, j); + } + } + + return; +} + +static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; +static constexpr int LongArrayInt[3][20] = {{1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1}, {2, 2, 2, -2, -2, -2, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1}, {3, 3, 3, -3, -3, -3, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1}}; + struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgMpar, int, 8, "Highest order of pt-pt correlations") O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Do correlations as function of Nch") + O2_DEFINE_CONFIGURABLE(cfgUseNchCorrection, int, 1, "Use correction for Nch; 0: Use size of tracks table, 1: Use efficiency-corrected Nch values, 2: Use uncorrected Nch values"); O2_DEFINE_CONFIGURABLE(cfgFillWeights, bool, false, "Fill NUA weights") O2_DEFINE_CONFIGURABLE(cfgRunByRun, bool, false, "Fill histograms on a run-by-run basis") 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(cfgMultCut, bool, false, "Use additional event cut on mult correlations"); O2_DEFINE_CONFIGURABLE(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgUsePID, bool, true, "Enable PID information") O2_DEFINE_CONFIGURABLE(cfgUseGapMethod, bool, false, "Use gap method in vn-pt calculations") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUsePIDEfficiencies, bool, false, "Use species dependent efficiencies") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") - O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); - O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); - O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 70, "Cut on number of TPC clusters found"); - O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); - O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); - O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); - O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); O2_DEFINE_CONFIGURABLE(cfgPtmin, float, 0.2, "minimum pt (GeV/c)"); O2_DEFINE_CONFIGURABLE(cfgPtmax, float, 10, "maximum pt (GeV/c)"); O2_DEFINE_CONFIGURABLE(cfgEta, float, 0.8, "eta cut"); O2_DEFINE_CONFIGURABLE(cfgEtaPtPt, float, 0.4, "eta cut for pt-pt correlations"); + O2_DEFINE_CONFIGURABLE(cfgEtaNch, float, 0.4, "eta cut for nch selection"); + O2_DEFINE_CONFIGURABLE(cfgUsePIDTotal, bool, false, "use fraction of PID total"); O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); + O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 50, "Cut on number of TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); + O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgTPCSectorCut, bool, false, "Cut on pt-phi distribution"); + } cfgTrackCuts; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodITSLayersAll, bool, true, "kIsGoodITSLayersAll"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInRofStandard, bool, true, "kNoCollInRofStandard"); + O2_DEFINE_CONFIGURABLE(cfgNoHighMultCollInPrevRof, bool, true, "kNoHighMultCollInPrevRof"); + O2_DEFINE_CONFIGURABLE(cfgNoITSROFrameBorder, bool, true, "kNoITSROFrameBorder"); + O2_DEFINE_CONFIGURABLE(cfgNoTimeFrameBorder, bool, true, "kNoTimeFrameBorder"); + O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "kTVXinTRD - Use kTVXinTRD (reject TRD triggered events)"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "kIsVertexITSTPC - Selects collisions with at least one ITS-TPC track"); + } cfgEventCutFlags; O2_DEFINE_CONFIGURABLE(cfgOccupancySelection, int, 2000, "Max occupancy selection, -999 to disable"); - O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); - O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); - O2_DEFINE_CONFIGURABLE(cfgIsGoodITSLayersAll, bool, true, "kIsGoodITSLayersAll"); - 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 event 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"); O2_DEFINE_CONFIGURABLE(cfgMagField, float, 99999, "Configurable magnetic field; default CCDB will be queried"); - O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5, "pt cut on TOF for PID"); O2_DEFINE_CONFIGURABLE(cfgUseDensityDependentCorrection, bool, false, "Use density dependent efficiency correction based on Run 2 measurements"); Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; - Configurable> cfgMultGlobalCutPars{"cfgMultGlobalCutPars", std::vector{2272.16, -76.6932, 1.01204, -0.00631545, 1.59868e-05, 136.336, -4.97006, 0.121199, -0.0015921, 7.66197e-06}, "Global multiplicity cut parameter values"}; - Configurable> cfgMultPVCutPars{"cfgMultPVCutPars", std::vector{3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05}, "PV multiplicity cut parameter values"}; - O2_DEFINE_CONFIGURABLE(cfgMultCorrHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); - O2_DEFINE_CONFIGURABLE(cfgMultCorrLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + struct : ConfigurableGroup { + Configurable> cfgMultGlobalCutPars{"cfgMultGlobalCutPars", std::vector{2272.16, -76.6932, 1.01204, -0.00631545, 1.59868e-05, 136.336, -4.97006, 0.121199, -0.0015921, 7.66197e-06}, "Global vs FT0C multiplicity cut parameter values"}; + Configurable> cfgMultPVCutPars{"cfgMultPVCutPars", std::vector{3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05}, "PV vs FT0C multiplicity cut parameter values"}; + Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.223013, 0.715849, 0.664242, 0.0829653, -0.000503733, 1.21185e-06}, "Global vs PV multiplicity cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultCorrHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCorrCutFunction, std::string, "[0] + [1]*x + 3*([2] + [3]*x + [4]*x*x + [5]*x*x*x)", "Functional for global vs pv multiplicity correlation cut"); + } cfgMultCorrCuts; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgMultGlobalASideCorrCutFunction, std::string, "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x + [10]*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", "Functional for global vs V0A multiplicity low correlation cut"); + Configurable> cfgMultGlobalV0ACutPars{"cfgMultGlobalV0ACutPars", std::vector{567.785, 172.715, 0.77888, -0.00693466, 1.40564e-05, 679.853, 66.8068, -0.444332, 0.00115002, -4.92064e-07}, "Global vs FV0A multiplicity cut parameter values"}; + Configurable> cfgMultGlobalT0ACutPars{"cfgMultGlobalT0ACutPars", std::vector{241.618, 61.8402, 0.348049, -0.00306078, 6.20357e-06, 315.235, 29.1491, -0.188639, 0.00044528, -9.08912e-08}, "Global vs FT0A multiplicity cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgGlobalV0ALowSigma, float, -3, "Number of sigma deviations below expected value in global vs V0A correlation"); + O2_DEFINE_CONFIGURABLE(cfgGlobalV0AHighSigma, float, 4, "Number of sigma deviations above expected value in global vs V0A correlation"); + O2_DEFINE_CONFIGURABLE(cfgGlobalT0ALowSigma, float, -3., "Number of sigma deviations below expected value in global vs T0A correlation"); + O2_DEFINE_CONFIGURABLE(cfgGlobalT0AHighSigma, float, 4, "Number of sigma deviations above expected value in global vs T0A correlation"); + } cfgGlobalAsideCorrCuts; + struct : ConfigurableGroup { + Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"pos_pi", "pos_ka", "pos_pr", "neg_pi", "neg_ka", "neg_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; + Configurable> resonanceCuts{"resonanceCuts", {LongArrayFloat[0], 3, 11, {"K0", "Lambda", "Phi"}, {"cos_PAs", "massMin", "massMax", "PosTrackPt", "NegTrackPt", "DCAPosToPVMin", "DCANegToPVMin", "Lifetime", "RadiusMin", "RadiusMax", "Rapidity"}}, "Labeled array (float) for various cuts on resonances"}; + Configurable> resonanceSwitches{"resonanceSwitches", {LongArrayInt[0], 3, 6, {"K0", "Lambda", "Phi"}, {"UseParticle", "UseCosPA", "NMassBins", "DCABetDaug", "UseProperLifetime", "UseV0Radius"}}, "Labeled array (int) for various cuts on resonances"}; + O2_DEFINE_CONFIGURABLE(cfgUseLsPhi, bool, true, "Use LikeSign for Phi v2") + O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") + O2_DEFINE_CONFIGURABLE(cfgFakeKaonCut, float, 0.1f, "Maximum difference in measured momentum and TPC inner ring momentum of particle") + O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts") + O2_DEFINE_CONFIGURABLE(cfgTPCNsigmaCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") + O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5, "pt cut on TOF for PID"); + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") + O2_DEFINE_CONFIGURABLE(cfgK0SignalMin, float, 0.48, "Minimum cut on K0 mT signal"); + O2_DEFINE_CONFIGURABLE(cfgK0SignalMax, float, 0.51, "Maximum cut on K0 mT signal"); + O2_DEFINE_CONFIGURABLE(cfgLambdaSignalMin, float, 1.1, "Minimum cut on Lambda mT signal"); + O2_DEFINE_CONFIGURABLE(cfgLambdaSignalMax, float, 1.3, "Maximum cut on Lambda mT signal"); + O2_DEFINE_CONFIGURABLE(cfgK0SideBand1Min, float, 0.44, "Minimum cut on K0 side band 1"); + O2_DEFINE_CONFIGURABLE(cfgK0SideBand1Max, float, 0.47, "Maximum cut on K0 side band 1"); + O2_DEFINE_CONFIGURABLE(cfgK0SideBand2Min, float, 0.52, "Minimum cut on K0 side band 2"); + O2_DEFINE_CONFIGURABLE(cfgK0SideBand2Max, float, 0.56, "Maximum cut on K0 side band 2"); + O2_DEFINE_CONFIGURABLE(cfgLambdaSideBand1Min, float, 1.0, "Minimum cut on Lambda side band 1"); + O2_DEFINE_CONFIGURABLE(cfgLambdaSideBand1Max, float, 1.05, "Maximum cut on Lambda side band 1"); + O2_DEFINE_CONFIGURABLE(cfgLambdaSideBand2Min, float, 1.4, "Minimum cut on Lambda side band 2"); + O2_DEFINE_CONFIGURABLE(cfgLambdaSideBand2Max, float, 1.6, "Maximum cut on Lambda side band 2"); + } cfgPIDCuts; 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, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90}}, "Configuration for binning"}; Configurable cfgRegions{"cfgRegions", {{"refN", "refP", "refFull"}, {-0.8, 0.4, -0.8}, {-0.4, 0.8, 0.8}, {0, 0, 0}, {1, 1, 1}}, "Configurations for GFW regions"}; Configurable cfgCorrConfig{"cfgCorrConfig", {{"refP {2} refN {-2}", "refP {3} refN {-3}", "refP {4} refN {-4}", "refFull {2 -2}", "refFull {2 2 -2 -2}"}, {"ChGap22", "ChGap32", "ChGap42", "ChFull22", "ChFull24"}, {0, 0, 0, 0, 0}, {15, 1, 1, 0, 0}}, "Configurations for each correlation to calculate"}; + Configurable cfgCorrConfigV02{"cfgCorrConfigV02", {{"refP {2} refN {-2}", "refP {3} refN {-3}", "refP {4} refN {-4}"}, {"ChGap22", "ChGap32", "ChGap42"}, {1, 1, 1}, {0, 0, 0}}, "Configurations for each radial flow correlation to calculate"}; + Configurable cfgCorrConfigV0{"cfgCorrConfigV0", {{"refP {2} refN {-2}", "refP {3} refN {-3}", "refP {4} refN {-4}"}, {"ChGap22", "ChGap32", "ChGap42"}, {1, 1, 1}, {0, 0, 0}}, "Configurations for each radial flow correlation to calculate"}; + + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; - // #include "PWGCF/TwoParticleCorrelations/TableProducer/Productions/skimmingconf_20221115.cxx" // NOLINT // Connect to ccdb Service ccdb; + o2::aod::ITSResponse itsResponse; + struct Config { TH1D* mEfficiency = nullptr; + std::vector mPIDEfficiencies; std::vector mAcceptance; bool correctionsLoaded = false; } cfg; @@ -148,6 +246,12 @@ struct FlowGenericFramework { OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; HistogramRegistry registry{"registry"}; + std::array, 3> resoCutVals; + std::array, 3> resoSwitchVals; + std::array tofNsigmaCut; + std::array itsNsigmaCut; + std::array tpcNsigmaCut; + // QA outputs std::map>> th1sList; std::map>> th3sList; @@ -167,6 +271,7 @@ struct FlowGenericFramework { hNUApi, hNUAka, hNUApr, + hPtPhiMult, kCount_TH3Names }; enum CentEstimators { @@ -174,7 +279,97 @@ struct FlowGenericFramework { kCentFT0CVariant1, kCentFT0M, kCentFV0A, - kCentNTPV + kCentNTPV, + kCentNGlobal, + kCentMFT + }; + std::map centNamesMap = {{kCentFT0C, "FT0C"}, {kCentFT0CVariant1, "FT0C variant1"}, {kCentFT0M, "FT0M"}, {kCentFV0A, "FV0A"}, {kCentNTPV, "NTPV"}, {kCentNGlobal, "NGlobal"}, {kCentMFT, "MFT"}}; + + enum EventSelFlags { + kFilteredEvent = 1, + kSel8, + kOccupancy, + kTVXinTRD, + kNoSameBunchPileup, + kIsGoodZvtxFT0vsPV, + kNoCollInTimeRangeStandard, + kNoCollInRofStandard, + kNoHighMultCollInPrevRof, + kNoTimeFrameBorder, + kNoITSROFrameBorder, + kIsVertexITSTPC, + kIsGoodITSLayersAll, + kMultCuts, + kTrackCent + }; + struct EventCut { + bool enabled; + int histBin; + int flag; // just store the enum + }; + std::vector eventcutflags = { + {cfgEventCutFlags.cfgNoSameBunchPileupCut, kNoSameBunchPileup, o2::aod::evsel::kNoSameBunchPileup}, + {cfgEventCutFlags.cfgIsGoodZvtxFT0vsPV, kIsGoodZvtxFT0vsPV, o2::aod::evsel::kIsGoodZvtxFT0vsPV}, + {cfgEventCutFlags.cfgNoCollInTimeRangeStandard, kNoCollInTimeRangeStandard, o2::aod::evsel::kNoCollInTimeRangeStandard}, + {cfgEventCutFlags.cfgNoCollInRofStandard, kNoCollInRofStandard, o2::aod::evsel::kNoCollInRofStandard}, + {cfgEventCutFlags.cfgNoHighMultCollInPrevRof, kNoHighMultCollInPrevRof, o2::aod::evsel::kNoHighMultCollInPrevRof}, + {cfgEventCutFlags.cfgNoTimeFrameBorder, kNoTimeFrameBorder, o2::aod::evsel::kIsVertexITSTPC}, + {cfgEventCutFlags.cfgNoITSROFrameBorder, kNoITSROFrameBorder, o2::aod::evsel::kIsGoodITSLayersAll}, + {cfgEventCutFlags.cfgIsVertexITSTPC, kIsVertexITSTPC, o2::aod::evsel::kNoTimeFrameBorder}, + {cfgEventCutFlags.cfgIsGoodITSLayersAll, kIsGoodITSLayersAll, o2::aod::evsel::kNoITSROFrameBorder}, + }; + enum Particles { + PIONS, + KAONS, + PROTONS + }; + enum ParticleIDs { + CHARGEDID, + PIONID, + KAONID, + PROTONID, + SPECIESCOUNT + }; + enum OutputSpecies { + K0 = 0, + LAMBDA = 1, + PHI = 2, + ANLAMBDA = 3, + REF = 4, + kCount_OutputSpecies + }; + enum ParticleCuts { + kCosPA = 0, + kMassMin, + kMassMax, + kPosTrackPt, + kNegTrackPt, + kDCAPosToPVMin, + kDCANegToPVMin, + kLifeTime, + kRadiusMin, + kRadiusMax, + kRapidity + }; + enum ParticleSwitches { + kUseParticle = 0, + kUseCosPA, + kMassBins, + kDCABetDaug, + kUseProperLifetime, + kUseV0Radius + }; + enum V0Selection { + kFillCandidate = 0, + kFillDaughterPt, + kFillMassCut, + kFillRapidityCut, + kFillDCAtoPV, + kFillDCAxDaughters, + kFillV0Radius, + kFillCosPA, + kFillProperLifetime, + kFillDaughterTrackSelection }; // Define global variables @@ -182,6 +377,9 @@ struct FlowGenericFramework { GFW* fGFW = new GFW(); std::vector corrconfigs; + std::vector corrconfigsV02; + std::vector corrconfigsV0; + TRandom3* fRndm = new TRandom3(0); TAxis* fPtAxis; int lastRun = -1; @@ -204,18 +402,24 @@ struct FlowGenericFramework { DensityCorr() : psi2Est(0.), psi3Est(0.), psi4Est(0.), v2(0.), v3(0.), v4(0.), density(0) {} }; - // Event selection cuts - Alex - TF1* fPhiCutLow = nullptr; - TF1* fPhiCutHigh = nullptr; + // Event selection cuts - multiplicity correlation TF1* fMultPVCutLow = nullptr; TF1* fMultPVCutHigh = nullptr; TF1* fMultCutLow = nullptr; TF1* fMultCutHigh = nullptr; - TF1* fMultMultPVCut = nullptr; + TF1* fMultPVGlobalCutHigh = nullptr; + TF1* fMultGlobalV0ACutLow = nullptr; + TF1* fMultGlobalV0ACutHigh = nullptr; + TF1* fMultGlobalT0ACutLow = nullptr; + TF1* fMultGlobalT0ACutHigh = nullptr; + + // Track selection - pt-phi cuts + TF1* fPhiCutLow = nullptr; + TF1* fPhiCutHigh = nullptr; void init(InitContext const&) { - LOGF(info, "flowGenericFramework::init()"); + LOGF(info, "FlowGenericFramework::init()"); o2::analysis::gfw::regions.SetNames(cfgRegions->GetNames()); o2::analysis::gfw::regions.SetEtaMin(cfgRegions->GetEtaMin()); o2::analysis::gfw::regions.SetEtaMax(cfgRegions->GetEtaMax()); @@ -227,6 +431,16 @@ struct FlowGenericFramework { o2::analysis::gfw::configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); o2::analysis::gfw::regions.Print(); o2::analysis::gfw::configs.Print(); + o2::analysis::gfw::configsV02.SetCorrs(cfgCorrConfigV02->GetCorrs()); + o2::analysis::gfw::configsV02.SetHeads(cfgCorrConfigV02->GetHeads()); + o2::analysis::gfw::configsV02.SetpTDifs(cfgCorrConfigV02->GetpTDifs()); + o2::analysis::gfw::configsV02.SetpTCorrMasks(cfgCorrConfigV02->GetpTCorrMasks()); + o2::analysis::gfw::configsV02.Print(); + o2::analysis::gfw::configsV0.SetCorrs(cfgCorrConfigV0->GetCorrs()); + o2::analysis::gfw::configsV0.SetHeads(cfgCorrConfigV0->GetHeads()); + o2::analysis::gfw::configsV0.SetpTDifs(cfgCorrConfigV0->GetpTDifs()); + o2::analysis::gfw::configsV0.SetpTCorrMasks(cfgCorrConfigV0->GetpTCorrMasks()); + o2::analysis::gfw::configsV0.Print(); o2::analysis::gfw::ptbinning = cfgGFWBinning->GetPtBinning(); o2::analysis::gfw::ptpoilow = cfgGFWBinning->GetPtPOImin(); o2::analysis::gfw::ptpoiup = cfgGFWBinning->GetPtPOImax(); @@ -244,34 +458,23 @@ struct FlowGenericFramework { o2::analysis::gfw::nchup = cfgGFWBinning->GetNchMax(); o2::analysis::gfw::centbinning = cfgGFWBinning->GetCentBinning(); cfgGFWBinning->Print(); - o2::analysis::gfw::multGlobalCorrCutPars = cfgMultGlobalCutPars; - o2::analysis::gfw::multPVCorrCutPars = cfgMultPVCutPars; + o2::analysis::gfw::multGlobalCorrCutPars = cfgMultCorrCuts.cfgMultGlobalCutPars; + o2::analysis::gfw::multPVCorrCutPars = cfgMultCorrCuts.cfgMultPVCutPars; + o2::analysis::gfw::multGlobalPVCorrCutPars = cfgMultCorrCuts.cfgMultGlobalPVCutPars; + o2::analysis::gfw::multGlobalV0ACutPars = cfgGlobalAsideCorrCuts.cfgMultGlobalV0ACutPars; + o2::analysis::gfw::multGlobalT0ACutPars = cfgGlobalAsideCorrCuts.cfgMultGlobalT0ACutPars; + + projectMatrix(cfgPIDCuts.nSigmas->getData(), tpcNsigmaCut, tofNsigmaCut, itsNsigmaCut); + readMatrix(cfgPIDCuts.resonanceCuts->getData(), resoCutVals); + readMatrix(cfgPIDCuts.resonanceSwitches->getData(), resoSwitchVals); + printResoCuts(); AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgEta, cfgEta, "#eta"}; AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgVtxZ, cfgVtxZ, "Vtx_{z} (cm)"}; AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; - std::string sCentralityEstimator; - switch (cfgCentEstimator) { - case kCentFT0C: - sCentralityEstimator = "FT0C"; - break; - case kCentFT0CVariant1: - sCentralityEstimator = "FT0C variant 1"; - break; - case kCentFT0M: - sCentralityEstimator = "FT0M"; - break; - case kCentFV0A: - sCentralityEstimator = "FV0A"; - break; - case kCentNTPV: - sCentralityEstimator = "NTPV"; - break; - default: - sCentralityEstimator = "FT0C"; - } - sCentralityEstimator += " centrality (%)"; + std::string sCentralityEstimator = centNamesMap[cfgCentEstimator] + " centrality (%)"; AxisSpec centAxis = {o2::analysis::gfw::centbinning, sCentralityEstimator.c_str()}; std::vector nchbinning; int nchskip = (o2::analysis::gfw::nchup - o2::analysis::gfw::nchlow) / o2::analysis::gfw::nchbins; @@ -280,13 +483,16 @@ struct FlowGenericFramework { } AxisSpec nchAxis = {nchbinning, "N_{ch}"}; AxisSpec bAxis = {200, 0, 20, "#it{b}"}; - AxisSpec t0cAxis = {70, 0, 70000, "N_{ch} (T0C)"}; - AxisSpec t0aAxis = {200, 0, 200, "N_{ch}"}; - AxisSpec multpvAxis = {4000, 0, 4000, "N_{ch} (PV)"}; + AxisSpec t0cAxis = {1000, 0, 50000, "N_{ch} (T0C)"}; + AxisSpec t0aAxis = {1800, 0, 180000, "N_{ch} (T0A)"}; + AxisSpec v0aAxis = {1800, 0, 180000, "N_{ch} (V0A)"}; + AxisSpec multpvAxis = {3500, 0, 3500, "N_{ch} (PV)"}; + AxisSpec occAxis = {500, 0, 5000, "occupancy"}; AxisSpec multAxis = (doprocessOnTheFly && !cfgUseNch) ? bAxis : (cfgUseNch) ? nchAxis : centAxis; AxisSpec dcaZAXis = {200, -2, 2, "DCA_{z} (cm)"}; AxisSpec dcaXYAXis = {200, -1, 1, "DCA_{xy} (cm)"}; + AxisSpec singleCount = {1, 0, 1}; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -307,6 +513,7 @@ struct FlowGenericFramework { if (doprocessMCReco || doprocessData || doprocessRun2) { registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registry.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); + registry.add("trackQA/before/pt_phi", "", {HistType::kTH2D, {ptAxis, phiModAxis}}); registry.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment", {HistType::kTH1D, {{100, 0., 5.}}}); registry.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track", {HistType::kTH1D, {{100, 0., 50.}}}); registry.add("trackQA/before/nTPCClusters", "Number of found TPC clusters", {HistType::kTH1D, {{100, 40, 180}}}); @@ -316,29 +523,47 @@ struct FlowGenericFramework { registry.addClone("trackQA/before/", "trackQA/after/"); registry.add("trackQA/after/pt_ref", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); registry.add("trackQA/after/pt_poi", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); - - registry.add("eventQA/before/centrality", "", {HistType::kTH1D, {centAxis}}); - registry.add("eventQA/before/multiplicity", "", {HistType::kTH1D, {nchAxis}}); - 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.add("trackQA/after/Nch_corrected", "", {HistType::kTH1D, {nchAxis}}); + registry.add("trackQA/after/Nch_uncorrected", "", {HistType::kTH1D, {nchAxis}}); + + registry.add("eventQA/before/centrality", "; centrality (%); Counts", {HistType::kTH1D, {centAxis}}); + registry.add("eventQA/before/multiplicity", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}}); + registry.add("eventQA/before/globalTracks_centT0C", "; FT0C centrality (%); N_{global}", {HistType::kTH2D, {centAxis, nchAxis}}); + registry.add("eventQA/before/PVTracks_centT0C", "; FT0C centrality (%); N_{PV}", {HistType::kTH2D, {centAxis, multpvAxis}}); + registry.add("eventQA/before/globalTracks_PVTracks", "; N_{PV}; N_{global}", {HistType::kTH2D, {multpvAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multT0A", "; multT0A; N_{global}", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multV0A", "; multV0A; N_{global}", {HistType::kTH2D, {v0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "; multV0A; multT0A", {HistType::kTH2D, {t0aAxis, v0aAxis}}); + registry.add("eventQA/before/multT0C_centT0C", "; multT0C; FT0C centrality (%)", {HistType::kTH2D, {centAxis, t0cAxis}}); + registry.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}}); registry.addClone("eventQA/before/", "eventQA/after/"); - registry.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{11, 0, 11}}}); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(2, "sel8"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(3, "occupancy"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(4, "kTVXinTRD"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(8, "kIsVertexITSTPC"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(9, "kIsGoodITSLayersAll"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(10, "after Mult cuts"); - registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(11, "has track + within cent"); + registry.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{15, 0.5, 15.5}}}); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kFilteredEvent, "Filtered event"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kSel8, "sel8"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kOccupancy, "occupancy"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kTVXinTRD, "kTVXinTRD"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoSameBunchPileup, "kNoSameBunchPileup"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsGoodZvtxFT0vsPV, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollInTimeRangeStandard, "kNoCollInTimeRangeStandard"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollInRofStandard, "kNoCollInRofStandard"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoHighMultCollInPrevRof, "kNoHighMultCollInPrevRof"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoTimeFrameBorder, "kNoTimeFrameBorder"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoITSROFrameBorder, "kNoITSROFrameBorder"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsVertexITSTPC, "kIsVertexITSTPC"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsGoodITSLayersAll, "kIsGoodITSLayersAll"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kMultCuts, "after Mult cuts"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kTrackCent, "has track + within cent"); + + registry.add("npt_ch", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_pi", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_ka", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_pr", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_K0_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_K0_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_K0_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_Lambda_sig", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_Lambda_sb1", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("npt_Lambda_sb2", "; #it{p}_{T} (GeV/#it{c}; ; centrality (%); fraction)", {HistType::kTProfile2D, {ptAxis, centAxis}}); if (!cfgRunByRun) { if (cfgUsePID) { @@ -351,6 +576,65 @@ struct FlowGenericFramework { registry.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); } } + + AxisSpec axisK0Mass = {resoSwitchVals[K0][kMassBins], resoCutVals[K0][kMassMin], resoCutVals[K0][kMassMax]}; + AxisSpec axisLambdaMass = {resoSwitchVals[LAMBDA][kMassBins], resoCutVals[LAMBDA][kMassMin], resoCutVals[LAMBDA][kMassMax]}; + + // QA histograms for V0s + if (resoSwitchVals[K0][kUseParticle]) { + registry.add("K0/PiPlusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registry.add("K0/PiMinusTPC_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registry.add("K0/PiPlusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registry.add("K0/PiMinusTOF_K0", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registry.add("K0/hK0Phi", "", {HistType::kTH1D, {phiAxis}}); + registry.add("K0/hK0Eta", "", {HistType::kTH1D, {etaAxis}}); + registry.add("K0/hK0Mass_sparse", "", {HistType::kTHnSparseF, {{axisK0Mass, ptAxis, nchAxis}}}); + registry.add("K0/hK0s", "", {HistType::kTH1D, {singleCount}}); + registry.add("K0/hK0s_corrected", "", {HistType::kTH1D, {singleCount}}); + + registry.add("K0/hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{10, 0.5, 10.5}}}); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillCandidate, "K0 candidates"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDaughterPt, "Daughter pt"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillMassCut, "Mass cut"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillRapidityCut, "Rapidity cut"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDCAtoPV, "DCA to PV"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDCAxDaughters, "DCA between daughters"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillV0Radius, "V0radius"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillCosPA, "CosPA"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillProperLifetime, "Proper lifetime"); + registry.get(HIST("K0/hK0Count"))->GetXaxis()->SetBinLabel(kFillDaughterTrackSelection, "Daughter track selection"); + } + + if (resoSwitchVals[LAMBDA][kUseParticle]) { + registry.add("Lambda/PrPlusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registry.add("Lambda/PiMinusTPC_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registry.add("Lambda/PrPlusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registry.add("Lambda/PiMinusTOF_L", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registry.add("Lambda/hLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); + registry.add("Lambda/hLambdaEta", "", {HistType::kTH1D, {etaAxis}}); + registry.add("Lambda/hLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); + registry.add("Lambda/PiPlusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registry.add("Lambda/PrMinusTPC_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTPC}}}); + registry.add("Lambda/PiPlusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registry.add("Lambda/PrMinusTOF_AL", "", {HistType::kTH2D, {{ptAxis, axisNsigmaTOF}}}); + registry.add("Lambda/hAntiLambdaPhi", "", {HistType::kTH1D, {phiAxis}}); + registry.add("Lambda/hAntiLambdaEta", "", {HistType::kTH1D, {etaAxis}}); + registry.add("Lambda/hAntiLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, ptAxis, nchAxis}}}); + registry.add("Lambda/hLambdas", "", {HistType::kTH1D, {singleCount}}); + registry.add("Lambda/hLambdas_corrected", "", {HistType::kTH1D, {singleCount}}); + + registry.add("Lambda/hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{10, 0.5, 10.5}}}); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillCandidate, "Lambda candidates"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDaughterPt, "Daughter pt"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillMassCut, "Mass cut"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillRapidityCut, "Rapidity cut"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDCAtoPV, "DCA to PV"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDCAxDaughters, "DCA between daughters"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillV0Radius, "V0radius"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillCosPA, "CosPA"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillProperLifetime, "Proper lifetime"); + registry.get(HIST("Lambda/hLambdaCount"))->GetXaxis()->SetBinLabel(kFillDaughterTrackSelection, "Daughter track selection"); + } } if (o2::analysis::gfw::regions.GetSize() < 0) @@ -363,9 +647,25 @@ struct FlowGenericFramework { } if (corrconfigs.empty()) LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); + + // Radial flow configs + for (auto i = 0; i < o2::analysis::gfw::configsV02.GetSize(); ++i) { + corrconfigsV02.push_back(fGFW->GetCorrelatorConfig(o2::analysis::gfw::configsV02.GetCorrs()[i], o2::analysis::gfw::configsV02.GetHeads()[i], o2::analysis::gfw::configsV02.GetpTDifs()[i])); + } + if (corrconfigsV02.empty()) + LOGF(error, "Radial (V02) configuration contains vectors of different size - check the GFWCorrConfig configurable"); + for (auto i = 0; i < o2::analysis::gfw::configsV0.GetSize(); ++i) { + corrconfigsV0.push_back(fGFW->GetCorrelatorConfig(o2::analysis::gfw::configsV0.GetCorrs()[i], o2::analysis::gfw::configsV0.GetHeads()[i], o2::analysis::gfw::configsV0.GetpTDifs()[i])); + } + if (corrconfigsV0.empty()) + LOGF(error, "Radial (V0) configuration contains vectors of different size - check the GFWCorrConfig configurable"); + fGFW->CreateRegions(); TObjArray* oba = new TObjArray(); addConfigObjectsToObjArray(oba, corrconfigs); + addConfigObjectsToObjArray(oba, corrconfigsV02); + addConfigObjectsToObjArray(oba, corrconfigsV0); + if (doprocessData || doprocessRun2 || doprocessMCReco) { fFC->SetName("FlowContainer"); fFC->SetXAxis(fPtAxis); @@ -377,20 +677,60 @@ struct FlowGenericFramework { fFCgen->Initialize(oba, multAxis, cfgNbootstrap); } delete oba; + fFCpt->setUseCentralMoments(cfgUseCentralMoments); fFCpt->setUseGapMethod(cfgUseGapMethod); fFCpt->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); - // Event selection - Alex - if (cfgUseAdditionalEventCut) { - fMultPVCutLow = new TF1("fMultPVCutLow", cfgMultCorrLowCutFunction->c_str(), 0, 100); + + // Multiplicity correlation cuts + if (cfgMultCut) { + fMultPVCutLow = new TF1("fMultPVCutLow", cfgMultCorrCuts.cfgMultCorrLowCutFunction->c_str(), 0, 100); fMultPVCutLow->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); - fMultPVCutHigh = new TF1("fMultPVCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultPVCutHigh = new TF1("fMultPVCutHigh", cfgMultCorrCuts.cfgMultCorrHighCutFunction->c_str(), 0, 100); fMultPVCutHigh->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); - fMultCutLow = new TF1("fMultCutLow", cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultCutLow = new TF1("fMultCutLow", cfgMultCorrCuts.cfgMultCorrLowCutFunction->c_str(), 0, 100); fMultCutLow->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); - fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrCuts.cfgMultCorrHighCutFunction->c_str(), 0, 100); fMultCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + fMultPVGlobalCutHigh = new TF1("fMultPVGlobalCutHigh", cfgMultCorrCuts.cfgMultGlobalPVCorrCutFunction->c_str(), 0, nchbinning.back()); + fMultPVGlobalCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalPVCorrCutPars[0])); + + LOGF(info, "Global V0A function: %s in range 0-%g", cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->c_str(), v0aAxis.binEdges.back()); + fMultGlobalV0ACutLow = new TF1("fMultGlobalV0ACutLow", cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->c_str(), 0, v0aAxis.binEdges.back()); + for (std::size_t i = 0; i < o2::analysis::gfw::multGlobalV0ACutPars.size(); ++i) + fMultGlobalV0ACutLow->SetParameter(i, o2::analysis::gfw::multGlobalV0ACutPars[i]); + fMultGlobalV0ACutLow->SetParameter(o2::analysis::gfw::multGlobalV0ACutPars.size(), cfgGlobalAsideCorrCuts.cfgGlobalV0ALowSigma); + for (int i = 0; i < fMultGlobalV0ACutLow->GetNpar(); ++i) + LOGF(info, "fMultGlobalV0ACutLow par %d = %g", i, fMultGlobalV0ACutLow->GetParameter(i)); + + fMultGlobalV0ACutHigh = new TF1("fMultGlobalV0ACutHigh", cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->c_str(), 0, v0aAxis.binEdges.back()); + for (std::size_t i = 0; i < o2::analysis::gfw::multGlobalV0ACutPars.size(); ++i) + fMultGlobalV0ACutHigh->SetParameter(i, o2::analysis::gfw::multGlobalV0ACutPars[i]); + fMultGlobalV0ACutHigh->SetParameter(o2::analysis::gfw::multGlobalV0ACutPars.size(), cfgGlobalAsideCorrCuts.cfgGlobalV0AHighSigma); + for (int i = 0; i < fMultGlobalV0ACutHigh->GetNpar(); ++i) + LOGF(info, "fMultGlobalV0ACutHigh par %d = %g", i, fMultGlobalV0ACutHigh->GetParameter(i)); + + LOGF(info, "Global T0A function: %s", cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->c_str()); + fMultGlobalT0ACutLow = new TF1("fMultGlobalT0ACutLow", cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->c_str(), 0, t0aAxis.binEdges.back()); + for (std::size_t i = 0; i < o2::analysis::gfw::multGlobalT0ACutPars.size(); ++i) + fMultGlobalT0ACutLow->SetParameter(i, o2::analysis::gfw::multGlobalT0ACutPars[i]); + fMultGlobalT0ACutLow->SetParameter(o2::analysis::gfw::multGlobalT0ACutPars.size(), cfgGlobalAsideCorrCuts.cfgGlobalT0ALowSigma); + for (int i = 0; i < fMultGlobalT0ACutLow->GetNpar(); ++i) + LOGF(info, "fMultGlobalT0ACutLow par %d = %g", i, fMultGlobalT0ACutLow->GetParameter(i)); + + fMultGlobalT0ACutHigh = new TF1("fMultGlobalT0ACutHigh", cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->c_str(), 0, t0aAxis.binEdges.back()); + for (std::size_t i = 0; i < o2::analysis::gfw::multGlobalT0ACutPars.size(); ++i) + fMultGlobalT0ACutHigh->SetParameter(i, o2::analysis::gfw::multGlobalT0ACutPars[i]); + fMultGlobalT0ACutHigh->SetParameter(o2::analysis::gfw::multGlobalT0ACutPars.size(), cfgGlobalAsideCorrCuts.cfgGlobalT0AHighSigma); + for (int i = 0; i < fMultGlobalT0ACutHigh->GetNpar(); ++i) + LOGF(info, "fMultGlobalT0ACutHigh par %d = %g", i, fMultGlobalT0ACutHigh->GetParameter(i)); + } + + if (cfgTrackCuts.cfgTPCSectorCut) { + fPhiCutLow = new TF1("fPhiCutLow", "0.06/x+pi/18.0-0.06", 0, 100); + fPhiCutHigh = new TF1("fPhiCutHigh", "0.1/x+pi/18.0+0.06", 0, 100); } + // Density dependent corrections if (cfgUseDensityDependentCorrection) { std::vector pTEffBins = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0}; hFindPtBin = new TH1D("hFindPtBin", "hFindPtBin", pTEffBins.size() - 1, &pTEffBins[0]); @@ -413,6 +753,70 @@ struct FlowGenericFramework { static constexpr std::string_view FillTimeName[] = {"before/", "after/"}; + void printResoCuts() + { + auto printTable = [](const auto& lbl, const auto& valuesMatrix, const std::string& title) { + LOGF(info, "===== %s =====", title.c_str()); + + size_t nRows = lbl.labels_rows.size(); + size_t nCols = lbl.labels_cols.size(); + + // Compute column widths: max of header or value string length + std::vector colWidths(nCols); + for (size_t c = 0; c < nCols; ++c) { + size_t maxValLen = 0; + for (size_t r = 0; r < nRows; ++r) { + std::ostringstream oss; + oss << std::fixed << std::setprecision(2) << valuesMatrix[r][c]; + maxValLen = std::max(maxValLen, oss.str().length()); + } + colWidths[c] = std::max(lbl.labels_cols[c].size(), maxValLen); + } + + // Determine row label width + size_t rowLabelWidth = 0; + for (const auto& rowName : lbl.labels_rows) + rowLabelWidth = std::max(rowLabelWidth, rowName.size()); + rowLabelWidth += 2; // for ": " + + // Print header + std::ostringstream header; + header << std::setw(rowLabelWidth) << " "; + for (size_t c = 0; c < nCols; ++c) + header << std::setw(colWidths[c]) << lbl.labels_cols[c] << " "; + LOGF(info, "%s", header.str().c_str()); + + // Print rows + for (size_t r = 0; r < nRows; ++r) { + std::ostringstream line; + line << std::setw(rowLabelWidth) << (lbl.labels_rows[r] + ":"); + for (size_t c = 0; c < nCols; ++c) { + line << std::setw(colWidths[c]) << std::fixed << std::setprecision(2) << valuesMatrix[r][c] << " "; + } + LOGF(info, "%s", line.str().c_str()); + } + }; + + // ----- nSigma PID ----- + // Map arrays into a 2D vector + std::vector> nSigmaVals = { + std::vector(tpcNsigmaCut.begin(), tpcNsigmaCut.end()), + std::vector(tofNsigmaCut.begin(), tofNsigmaCut.end()), + std::vector(itsNsigmaCut.begin(), itsNsigmaCut.end())}; + printTable(cfgPIDCuts.nSigmas.value, nSigmaVals, "nSigma PID Cuts"); + + // ----- Resonance Cuts ----- + std::vector> resoCutsVals(resoCutVals.size()); + for (size_t r = 0; r < resoCutVals.size(); ++r) + resoCutsVals[r] = std::vector(resoCutVals[r].begin(), resoCutVals[r].end()); + printTable(cfgPIDCuts.resonanceCuts.value, resoCutsVals, "Resonance Cuts"); + + // ----- Resonance Switches ----- + std::vector> resoSwitchValsF(resoSwitchVals.size()); + for (size_t r = 0; r < resoSwitchVals.size(); ++r) + resoSwitchValsF[r] = std::vector(resoSwitchVals[r].begin(), resoSwitchVals[r].end()); + printTable(cfgPIDCuts.resonanceSwitches.value, resoSwitchValsF, "Resonance Switches"); + } enum QAFillTime { kBefore, kAfter @@ -469,11 +873,21 @@ struct FlowGenericFramework { } } if (!cfgEfficiency.value.empty()) { - cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); - if (cfg.mEfficiency == nullptr) { - LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.value.c_str()); + if (!cfgUsePIDEfficiencies) { + cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfg.mEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); + } else { + std::vector species = {"ch", "pi", "ka", "pr"}; + for (const auto& sp : species) { + cfg.mPIDEfficiencies.push_back(ccdb->getForTimeStamp(cfgEfficiency.value + "/" + sp, timestamp)); + if (cfg.mPIDEfficiencies.back() == nullptr) + LOGF(fatal, "Could not load PID efficiency histograms from %s", cfgEfficiency.value + "/" + sp); + LOGF(info, "Loaded PID efficiency histogram from %s", cfgEfficiency.value + "/" + sp); + } } - LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); } cfg.correctionsLoaded = true; } @@ -488,11 +902,15 @@ struct FlowGenericFramework { } template - double getEfficiency(TTrack track) + double getEfficiency(TTrack track, int pidIndex = 0) { //-1 ref, 0 ch, 1 pi, 2 ka, 3 pr double eff = 1.; - if (cfg.mEfficiency) - eff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(track.pt())); + if (!cfgUsePIDEfficiencies) { + if (cfg.mEfficiency) + eff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(track.pt())); + } else { + eff = cfg.mPIDEfficiencies[pidIndex]->GetBinContent(cfg.mPIDEfficiencies[pidIndex]->FindBin(track.pt())); + } if (eff == 0) return -1.; else @@ -509,83 +927,116 @@ struct FlowGenericFramework { float nsigma = 3.0; // Choose which nSigma to use - std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; - if (track.pt() >= cfgTofPtCut && !track.hasTOF()) - return -1; + std::array nSigmaToUse = (track.pt() > cfgPIDCuts.cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; + if (track.pt() > cfgPIDCuts.cfgTofPtCut && !track.hasTOF()) + return 0; + const int numSpecies = 3; + int pidCount = 0; // Select particle with the lowest nsigma - const int nspecies = 3; - for (int i = 0; i < nspecies; ++i) { + for (int i = 0; i < numSpecies; ++i) { if (std::abs(nSigmaToUse[i]) < nsigma) { + if (pidCount > 0 && cfgPIDCuts.cfgUseStrictPID) + return 0; // more than one particle with low nsigma + + pidCount++; pid = i; - nsigma = std::abs(nSigmaToUse[i]); + if (!cfgPIDCuts.cfgUseStrictPID) + nsigma = std::abs(nSigmaToUse[i]); } } + + return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton + } + + template + int getNsigmaPIDAssymmetric(TTrack track) + { + // Computing Nsigma arrays for pion, kaon, and protons + std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; + int pid = -1; + + std::array nSigmaToUse = cfgPIDCuts.cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::array detectorNsigmaCut = cfgPIDCuts.cfgUseItsPID ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS + + bool isPion, isKaon, isProton; + bool isDetectedPion = nSigmaToUse[0] < detectorNsigmaCut[0] && nSigmaToUse[0] > detectorNsigmaCut[0 + 3]; + bool isDetectedKaon = nSigmaToUse[1] < detectorNsigmaCut[1] && nSigmaToUse[1] > detectorNsigmaCut[1 + 3]; + bool isDetectedProton = nSigmaToUse[2] < detectorNsigmaCut[2] && nSigmaToUse[2] > detectorNsigmaCut[2 + 3]; + + bool isTofPion = nSigmaTOF[0] < tofNsigmaCut[0] && nSigmaTOF[0] > tofNsigmaCut[0 + 3]; + bool isTofKaon = nSigmaTOF[1] < tofNsigmaCut[1] && nSigmaTOF[1] > tofNsigmaCut[1 + 3]; + bool isTofProton = nSigmaTOF[2] < tofNsigmaCut[2] && nSigmaTOF[2] > tofNsigmaCut[2 + 3]; + + if (track.pt() > cfgPIDCuts.cfgTofPtCut && !track.hasTOF()) { + return 0; + } else if (track.pt() > cfgPIDCuts.cfgTofPtCut && track.hasTOF()) { + isPion = isTofPion && isDetectedPion; + isKaon = isTofKaon && isDetectedKaon; + isProton = isTofProton && isDetectedProton; + } else { + isPion = isDetectedPion; + isKaon = isDetectedKaon; + isProton = isDetectedProton; + } + + if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { + return 0; // more than one particle satisfy the criteria + } + + if (isPion) { + pid = PIONS; + } else if (isKaon) { + pid = KAONS; + } else if (isProton) { + pid = PROTONS; + } else { + return 0; // no particle satisfies the criteria + } + return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton } template - bool eventSelected(TCollision collision, const int& multTrk, const float& centrality, const int& run) + bool eventSelected(TCollision collision, const int multTrk, const float& centrality, const int run) { - if (cfgTVXinTRD) { + // Cut on trigger alias + if (cfgEventCutFlags.cfgTVXinTRD) { if (collision.alias_bit(kTVXinTRD)) { // TRD triggered // "CMTVX-B-NOPF-TRD,minbias_TVX" - return 0; - } - registry.fill(HIST("eventQA/eventSel"), 3.5); - if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(3.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("eventQA/eventSel"), 4.5); - if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(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; + return false; } - registry.fill(HIST("eventQA/eventSel"), 5.5); + registry.fill(HIST("eventQA/eventSel"), kTVXinTRD); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(5.5); + th1sList[run][hEventSel]->Fill(kTVXinTRD); } - if (cfgNoCollInTimeRangeStandard) { - if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { - // Rejection of the collisions which have other events nearby - return 0; - } - registry.fill(HIST("eventQA/eventSel"), 6.5); + // Cut on event selection flags + for (const auto& cut : eventcutflags) { + if (!cut.enabled) + continue; + if (!collision.selection_bit(cut.flag)) + return false; + registry.fill(HIST("eventQA/eventSel"), cut.histBin); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(6.5); + th1sList[run][hEventSel]->Fill(cut.histBin); } - - 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; - } - registry.fill(HIST("eventQA/eventSel"), 7.5); - if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(7.5); + // Cut on vertex + if (!selectVertex(collision)) + return false; + // Cut on multiplicity correlations - data driven + if (cfgMultCut) { + if (!selectMultiplicityCorrelation(collision, multTrk, centrality, run)) + return false; } + return true; + } - if (cfgIsGoodITSLayersAll) { - if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { - return 0; - } - registry.fill(HIST("eventQA/eventSel"), 8.5); - if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(8.5); - } + template + bool selectVertex(TCollision collision) + { float vtxz = -999; if (collision.numContrib() > 1) { vtxz = collision.posZ(); @@ -595,44 +1046,82 @@ struct FlowGenericFramework { if (zRes > minZRes && collision.numContrib() < minNContrib) vtxz = -999; } - // auto multV0A = collision.multFV0A(); - // auto multT0A = collision.multFT0A(); - // auto multT0C = collision.multFT0C(); + if (vtxz > o2::analysis::gfw::vtxZup || vtxz < o2::analysis::gfw::vtxZlow) + return false; + else + return true; + } + + template + bool selectMultiplicityCorrelation(TCollision collision, const int multTrk, const float& centrality, const int run) + { auto multNTracksPV = collision.multNTracksPV(); + 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; + if (multTrk > fMultPVGlobalCutHigh->Eval(collision.multNTracksPV())) + return false; - if (vtxz > o2::analysis::gfw::vtxZup || vtxz < o2::analysis::gfw::vtxZlow) - return 0; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFV0A()) < fMultGlobalV0ACutLow->Eval(multTrk)) + return false; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFV0A()) > fMultGlobalV0ACutHigh->Eval(multTrk)) + return false; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFT0A()) < fMultGlobalT0ACutLow->Eval(multTrk)) + return false; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFT0A()) > fMultGlobalT0ACutHigh->Eval(multTrk)) + return false; + registry.fill(HIST("eventQA/eventSel"), kMultCuts); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kMultCuts); + return true; + } - 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("eventQA/eventSel"), 9.5); - if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(9.5); + template + bool trackSelected(TTrack track, const int field) + { + if (cfgTrackCuts.cfgTPCSectorCut) { + double phimodn = track.phi(); + if (field < 0) // for negative polarity field + phimodn = o2::constants::math::TwoPI - phimodn; + if (track.sign() < 0) // for negative charge + phimodn = o2::constants::math::TwoPI - phimodn; + if (phimodn < 0) + LOGF(warning, "phi < 0: %g", phimodn); + + phimodn += o2::constants::math::PI / 18.0; // to center gap in the middle + phimodn = fmod(phimodn, o2::constants::math::PI / 9.0); + if (cfgFillQA) + registry.fill(HIST("trackQA/before/pt_phi"), track.pt(), phimodn); + if (phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt())) + return false; // reject track + if (cfgFillQA) + registry.fill(HIST("trackQA/after/pt_phi"), track.pt(), phimodn); } - return 1; + if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgTrackCuts.cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) + return false; + return ((track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgNTPCXrows) && (track.tpcNClsFound() >= cfgTrackCuts.cfgNTPCCls) && (track.itsNCls() >= cfgTrackCuts.cfgMinNITSCls)); } template - bool trackSelected(TTrack track) + bool nchSelected(TTrack track) { - if (cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) + if (std::fabs(track.dcaXY()) > (0.0105f + 0.0035f / track.pt())) return false; - return ((track.tpcNClsCrossedRows() >= cfgNTPCXrows) && (track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); + return ((track.tpcNClsCrossedRows() >= 70) && (track.tpcNClsFound() >= 50) && (track.itsNCls() >= 5)); // o2-linter: disable=magic-number (hard coded default cuts) } + enum DataType { kReco, kGen }; template - void fillWeights(const TTrack track, const double vtxz, const int& pid_index, const int& run) + void fillWeights(const TTrack track, const double vtxz, const int pid_index, const int run) { if (cfgUsePID) { double ptpidmins[] = {o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoilow, 0.3, 0.5}; // min pt for ch, pi, ka, pr @@ -673,13 +1162,15 @@ struct FlowGenericFramework { return; } - void createRunByRunHistograms(const int& run) + void createRunByRunHistograms(const int run) { AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec phiModAxis = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgEta, cfgEta, "#eta"}; AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgVtxZ, cfgVtxZ, "Vtx_{z} (cm)"}; AxisSpec nchAxis = {o2::analysis::gfw::nchbins, o2::analysis::gfw::nchlow, o2::analysis::gfw::nchup, "N_{ch}"}; AxisSpec centAxis = {o2::analysis::gfw::centbinning, "Centrality (%)"}; + AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; std::vector> histos(kCount_TH1Names); histos[hPhi] = registry.add(Form("%d/phi", run), "", {HistType::kTH1D, {phiAxis}}); histos[hEta] = registry.add(Form("%d/eta", run), "", {HistType::kTH1D, {etaAxis}}); @@ -709,18 +1200,40 @@ struct FlowGenericFramework { } else { histos3d[hNUAref] = registry.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); } + histos3d[hPtPhiMult] = registry.add(Form("%d/pt_phi_mult", run), "", {HistType::kTH3D, {ptAxis, phiModAxis, (cfgUseNch) ? nchAxis : centAxis}}); th3sList.insert(std::make_pair(run, histos3d)); return; } + struct AcceptedTracks { + explicit AcceptedTracks(std::size_t nptbins) + : pidtotal{0, 0, 0}, + nch(nptbins, 0.f), + npi(nptbins, 0.f), + nka(nptbins, 0.f), + npr(nptbins, 0.f) + { + } + + float total = 0; + unsigned int totaluncorr = 0; + + std::vector pidtotal; + std::vector nch; + std::vector npi; + std::vector nka; + std::vector npr; + }; + template - void fillOutputContainers(const float& centmult, const double& rndm) + void fillOutputContainers(const float& centmult, const double& rndm, AcceptedTracks acceptedtracks) { fFCpt->calculateCorrelations(); fFCpt->fillPtProfiles(centmult, rndm); fFCpt->fillCMProfiles(centmult, rndm); if (!cfgUseGapMethod) fFCpt->fillVnPtStdProfiles(centmult, rndm); + for (uint l_ind = 0; l_ind < corrconfigs.size(); ++l_ind) { if (!corrconfigs.at(l_ind).pTDif) { auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), 0, kTRUE).real(); @@ -729,8 +1242,9 @@ struct FlowGenericFramework { auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; if (std::abs(val) < 1) { (dt == kGen) ? fFCgen->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, dnx, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, dnx, rndm); - if (cfgUseGapMethod) + if (cfgUseGapMethod) { fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); + } } continue; } @@ -743,20 +1257,78 @@ struct FlowGenericFramework { (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, dnx, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, dnx, rndm); } } + + double chtotal = (cfgUseNchCorrection) ? acceptedtracks.total : acceptedtracks.totaluncorr; + // calculate fractions + std::vector> inputs = {acceptedtracks.nch, acceptedtracks.npi, acceptedtracks.nka, acceptedtracks.npr}; + std::vector> fractions; + fractions.reserve(inputs.size()); + int pidcounter = 0; + for (auto& vec : inputs) { // o2-linter: disable=const-ref-in-for-loop (modified through transform) + fractions.emplace_back(); + fractions.back().reserve(vec.size()); + + double total = chtotal; + if (cfgUsePIDTotal) + total = (pidcounter) ? acceptedtracks.pidtotal[pidcounter - 1] : chtotal; + + if (total == 0.) { + ++pidcounter; + continue; + } + std::transform(vec.begin(), vec.end(), + std::back_inserter(fractions.back()), + [&](double x) { return x / total; }); + ++pidcounter; + } + + for (std::size_t i = 0; i < fractions[0].size(); ++i) + registry.fill(HIST("npt_ch"), fPtAxis->GetBinCenter(i + 1), centmult, fractions[0][i]); + for (std::size_t i = 0; i < fractions[1].size(); ++i) + registry.fill(HIST("npt_pi"), fPtAxis->GetBinCenter(i + 1), centmult, fractions[1][i]); + for (std::size_t i = 0; i < fractions[2].size(); ++i) + registry.fill(HIST("npt_ka"), fPtAxis->GetBinCenter(i + 1), centmult, fractions[2][i]); + for (std::size_t i = 0; i < fractions[3].size(); ++i) + registry.fill(HIST("npt_pr"), fPtAxis->GetBinCenter(i + 1), centmult, fractions[3][i]); + + if (corrconfigsV02.size() < SPECIESCOUNT) // + return; + + for (uint l_ind = 0; l_ind < SPECIESCOUNT; ++l_ind) { + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; + if (std::abs(val) < 1) + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * fractions[l_ind][i - 1], dnx, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centmult, val * fractions[l_ind][i - 1], dnx, rndm); + } + } + + if (corrconfigsV0.size() < SPECIESCOUNT) + return; + if (fFCpt->corrDen[0] == 0.) + return; + for (uint l_ind = 0; l_ind < SPECIESCOUNT; ++l_ind) { + double mpt = fFCpt->corrNum[1] / fFCpt->corrDen[1]; + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * fractions[l_ind][i - 1], 1., rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centmult, mpt * fractions[l_ind][i - 1], 1., rndm); + } + } return; } - template - void processCollision(TCollision collision, TTracks tracks, const float& centrality, const int& run) + template + void processCollision(TCollision collision, TTracks tracks, TV0s v0s, const float& centrality, const int field, const int run) { if (tracks.size() < 1) return; if (dt != kGen && (centrality < o2::analysis::gfw::centbinning.front() || centrality > o2::analysis::gfw::centbinning.back())) return; if (dt != kGen) { - registry.fill(HIST("eventQA/eventSel"), 10.5); + registry.fill(HIST("eventQA/eventSel"), kTrackCent); if (cfgRunByRun) - th1sList[run][hEventSel]->Fill(10.5); + th1sList[run][hEventSel]->Fill(kTrackCent); } float vtxz = collision.posZ(); if (dt != kGen && cfgRunByRun) { @@ -766,8 +1338,8 @@ struct FlowGenericFramework { } fGFW->Clear(); fFCpt->clearVector(); - float lRandom = fRndm->Rndm(); + float lRandom = fRndm->Rndm(); // be cautious, this only works for Pb-Pb // esimate the Event plane and vn for this event DensityCorr densitycorrections; @@ -802,16 +1374,118 @@ struct FlowGenericFramework { densitycorrections.v4 = v4; densitycorrections.density = tracks.size(); } - + // process tracks + AcceptedTracks acceptedTracks(o2::analysis::gfw::ptbinning.size() - 1); for (const auto& track : tracks) { - processTrack(track, vtxz, run, densitycorrections); + processTrack(track, vtxz, field, run, densitycorrections, acceptedTracks); + } + registry.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total); + registry.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.totaluncorr); + + int multiplicity = 0; + switch (cfgUseNchCorrection) { + case 0: + multiplicity = tracks.size(); + break; + case 1: + multiplicity = acceptedTracks.total; + break; + case 2: + multiplicity = acceptedTracks.totaluncorr; + break; + default: + multiplicity = tracks.size(); + break; } + if (!cfgFillWeights) - fillOutputContainers
((cfgUseNch) ? tracks.size() : centrality, lRandom); + fillOutputContainers
((cfgUseNch) ? multiplicity : centrality, lRandom, acceptedTracks); + + std::vector> nptResonances(6, std::vector(o2::analysis::gfw::ptbinning.size())); + // Process V0s + for (const auto& v0 : v0s) { + if (resoSwitchVals[K0][kUseParticle]) { + double weff = 1; + if (selectK0(collision, v0, centrality, weff)) { + int ptBinIndex = fPtAxis->FindBin(v0.pt()) - 1; + if (!(ptBinIndex < 0 || ptBinIndex >= static_cast(o2::analysis::gfw::ptbinning.size()))) { + if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand1Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand1Max) + nptResonances[0][ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + if (v0.mK0Short() > cfgPIDCuts.cfgK0SignalMin && v0.mK0Short() < cfgPIDCuts.cfgK0SignalMax) + nptResonances[1][ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + if (v0.mK0Short() > cfgPIDCuts.cfgK0SideBand2Min && v0.mK0Short() < cfgPIDCuts.cfgK0SideBand2Max) + nptResonances[2][ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + } + } + } + // Add lambdabar + if (resoSwitchVals[LAMBDA][kUseParticle]) { + double weff = 1.; + if (selectLambda(collision, v0, centrality, weff)) { + int ptBinIndex = fPtAxis->FindBin(v0.pt()) - 1; + if (!(ptBinIndex < 0 || ptBinIndex >= static_cast(o2::analysis::gfw::ptbinning.size()))) { + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand1Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand1Max) + nptResonances[3][ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSignalMin && v0.mLambda() < cfgPIDCuts.cfgLambdaSignalMax) + nptResonances[4][ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + if (v0.mLambda() > cfgPIDCuts.cfgLambdaSideBand2Min && v0.mLambda() < cfgPIDCuts.cfgLambdaSideBand2Max) + nptResonances[5][ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + } + } + } + } + double chtotal = (cfgUseNchCorrection) ? acceptedTracks.total : acceptedTracks.totaluncorr; + // calculate fractions + std::vector> fractions_resonances = nptResonances; + int pidcounter = 0; + for (auto& vec : fractions_resonances) { // o2-linter: disable=const-ref-in-for-loop (modified through transform) + double total = chtotal; + if (cfgUsePIDTotal) + total = (pidcounter) ? std::accumulate(vec.begin(), vec.end(), 0.f) : chtotal; + + if (total == 0.) { + ++pidcounter; + continue; + } + std::transform(vec.begin(), vec.end(), vec.begin(), + [&](float x) { return x / total; }); + ++pidcounter; + } + for (std::size_t i = 0; i < fractions_resonances[0].size(); ++i) + registry.fill(HIST("npt_K0_sb1"), fPtAxis->GetBinCenter(i + 1), centrality, fractions_resonances[0][i]); + for (std::size_t i = 0; i < fractions_resonances[2].size(); ++i) + registry.fill(HIST("npt_K0_sb2"), fPtAxis->GetBinCenter(i + 1), centrality, fractions_resonances[2][i]); + for (std::size_t i = 0; i < fractions_resonances[1].size(); ++i) + registry.fill(HIST("npt_K0_sig"), fPtAxis->GetBinCenter(i + 1), centrality, fractions_resonances[1][i]); + for (std::size_t i = 0; i < fractions_resonances[3].size(); ++i) + registry.fill(HIST("npt_Lambda_sb1"), fPtAxis->GetBinCenter(i + 1), centrality, fractions_resonances[3][i]); + for (std::size_t i = 0; i < fractions_resonances[5].size(); ++i) + registry.fill(HIST("npt_Lambda_sb2"), fPtAxis->GetBinCenter(i + 1), centrality, fractions_resonances[5][i]); + for (std::size_t i = 0; i < fractions_resonances[4].size(); ++i) + registry.fill(HIST("npt_Lambda_sig"), fPtAxis->GetBinCenter(i + 1), centrality, fractions_resonances[4][i]); + for (uint l_ind = 4; l_ind < corrconfigsV02.size(); ++l_ind) { + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigsV02.at(l_ind), i - 1, kFALSE).real() / dnx; + if (std::abs(val) < 1) + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * fractions_resonances[l_ind - 4][i - 1], dnx, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV02.at(l_ind).Head.c_str(), i), centrality, val * fractions_resonances[l_ind - 4][i - 1], dnx, lRandom); + } + } + for (uint l_ind = 4; l_ind < corrconfigsV0.size(); ++l_ind) { + double dn = fFCpt->corrDen[1]; + if (dn == 0.) + continue; + double mpt = fFCpt->corrNum[1] / dn; + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * fractions_resonances[l_ind - 4][i - 1], 1.0, lRandom) : fFC->FillProfile(Form("%s_pt_%i", corrconfigsV0.at(l_ind).Head.c_str(), i), centrality, mpt * fractions_resonances[l_ind - 4][i - 1], 1.0, lRandom); + } + } } template - inline void processTrack(TTrack const& track, const float& vtxz, const int& run, DensityCorr densitycorrections) + inline void processTrack(TTrack const& track, const float& vtxz, const int field, const int run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) { if constexpr (framework::has_type_v) { if (track.mcParticleId() < 0 || !(track.has_mcParticle())) @@ -826,17 +1500,47 @@ struct FlowGenericFramework { if (mcParticle.eta() < o2::analysis::gfw::etalow || mcParticle.eta() > o2::analysis::gfw::etaup || mcParticle.pt() < o2::analysis::gfw::ptlow || mcParticle.pt() > o2::analysis::gfw::ptup) return; - if (!trackSelected(track)) + // Select tracks with nominal cuts always + if (!nchSelected(track)) + return; + + double weffCh = getEfficiency(track, 0); + if (std::abs(track.eta()) < cfgEtaNch) { + if (weffCh > 0) + acceptedTracks.total += (cfgUseNchCorrection) ? weffCh : 1.0; + ++acceptedTracks.totaluncorr; + } + + if (!trackSelected(track, field)) return; int pidIndex = 0; if (cfgUsePID) { if (std::abs(mcParticle.pdgCode()) == kPiPlus) - pidIndex = 1; + pidIndex = PIONID; if (std::abs(mcParticle.pdgCode()) == kKPlus) - pidIndex = 2; + pidIndex = KAONID; if (std::abs(mcParticle.pdgCode()) == kProton) - pidIndex = 3; + pidIndex = PROTONID; + } + + if (std::abs(track.eta()) < cfgEtaNch) { + double weff = getEfficiency(track, pidIndex); + + if (pidIndex && weff > 0) + acceptedTracks.pidtotal[pidIndex - 1] += weff; + + int ptBinIndex = fPtAxis->FindBin(track.pt()) - 1; + if (!(ptBinIndex < 0 || ptBinIndex >= static_cast(o2::analysis::gfw::ptbinning.size()))) { + if (weffCh > 0) + acceptedTracks.nch[ptBinIndex] += (cfgUseNchCorrection) ? weffCh : 1.0; + if (pidIndex == PIONID && weff > 0) + acceptedTracks.npi[ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + if (pidIndex == KAONID && weff > 0) + acceptedTracks.nka[ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + if (pidIndex == PROTONID && weff > 0) + acceptedTracks.npr[ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + } } if (cfgFillWeights) { @@ -873,6 +1577,25 @@ struct FlowGenericFramework { pidIndex = 3; } + if (std::abs(track.eta()) < cfgEtaNch) { + ++acceptedTracks.total; + ++acceptedTracks.totaluncorr; + + if (pidIndex) + acceptedTracks.pidtotal[pidIndex - 1] += 1; + int ptBinIndex = fPtAxis->FindBin(track.pt()) - 1; + + if (!(ptBinIndex < 0 || ptBinIndex >= static_cast(o2::analysis::gfw::ptbinning.size()))) { + acceptedTracks.nch[ptBinIndex] += 1.0; + if (pidIndex == PIONID) + acceptedTracks.npi[ptBinIndex] += 1.0; + if (pidIndex == KAONID) + acceptedTracks.nka[ptBinIndex] += 1.0; + if (pidIndex == PROTONID) + acceptedTracks.npr[ptBinIndex] += 1.0; + } + } + fillPtSums(track, vtxz); fillGFW(track, vtxz, pidIndex, densitycorrections); @@ -881,15 +1604,45 @@ struct FlowGenericFramework { } else { if (cfgFillQA) fillTrackQA(track, vtxz); - - if (!trackSelected(track)) + // Select tracks with nominal cuts always + if (!nchSelected(track)) return; - int pidIndex = 0; - if (cfgUsePID) { - // pid_index = getBayesPIDIndex(track); - pidIndex = getNsigmaPID(track); + double weffCh = getEfficiency(track, 0); + if (std::abs(track.eta()) < cfgEtaNch) { + if (weffCh > 0) + acceptedTracks.total += (cfgUseNchCorrection) ? weffCh : 1.0; + ++acceptedTracks.totaluncorr; + } + + if (!trackSelected(track, field)) + return; + // int pidIndex = 0; + // if (cfgUsePID) Need PID for v02 + int pidIndex = getNsigmaPID(track); + + if (std::abs(track.eta()) < cfgEtaNch) { + double weff = getEfficiency(track, pidIndex); + if (pidIndex && weff > 0) + acceptedTracks.pidtotal[pidIndex - 1] += weff; + + int ptBinIndex = fPtAxis->FindBin(track.pt()) - 1; + + if (!(ptBinIndex < 0 || ptBinIndex >= static_cast(o2::analysis::gfw::ptbinning.size()))) { + if (weffCh > 0) + acceptedTracks.nch[ptBinIndex] += (cfgUseNchCorrection) ? weffCh : 1.0; + if (pidIndex == PIONID && weff > 0) { + acceptedTracks.npi[ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + } + if (pidIndex == KAONID && weff > 0) { + acceptedTracks.nka[ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + } + if (pidIndex == PROTONID && weff > 0) { + acceptedTracks.npr[ptBinIndex] += (cfgUseNchCorrection) ? weff : 1.0; + } + } } + if (cfgFillWeights) { fillWeights(track, vtxz, pidIndex, run); } else { @@ -906,6 +1659,204 @@ struct FlowGenericFramework { } } + template + bool selectionV0Daughter(TTrack const& track, int pid) + { + if (!(track.itsNCls() > cfgTrackCuts.cfgMinNITSCls)) + return 0; + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < cfgTrackCuts.cfgNTPCCls) + return false; + if (!(track.tpcNClsCrossedRows() > cfgTrackCuts.cfgNTPCXrows)) + return 0; + + if (cfgPIDCuts.cfgUseOnlyTPC) { + if (pid == PIONS && std::abs(track.tpcNSigmaPi()) > cfgPIDCuts.cfgTPCNsigmaCut) + return false; + if (pid == KAONS && std::abs(track.tpcNSigmaKa()) > cfgPIDCuts.cfgTPCNsigmaCut) + return false; + if (pid == PROTONS && std::abs(track.tpcNSigmaPr()) > cfgPIDCuts.cfgTPCNsigmaCut) + return false; + } else { + int partIndex = cfgPIDCuts.cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPID(track); + int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton + if (pidIndex != pid) + return false; + } + + return true; + } + + template + bool selectK0(TCollision const& collision, TV0 const& v0, const double& centrality, double& weff) + { + + double massK0s = v0.mK0Short(); + + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + registry.fill(HIST("K0/hK0Count"), kFillCandidate); + if (postrack.pt() < resoCutVals[K0][kPosTrackPt] || negtrack.pt() < resoCutVals[K0][kNegTrackPt]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillDaughterPt); + if (massK0s < resoCutVals[K0][kMassMin] && massK0s > resoCutVals[K0][kMassMax]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillMassCut); + // Rapidity correction + if (v0.yK0Short() > resoCutVals[K0][kRapidity]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillRapidityCut); + // DCA cuts for K0short + if (std::abs(v0.dcapostopv()) < resoCutVals[K0][kDCAPosToPVMin] || std::abs(v0.dcanegtopv()) < resoCutVals[K0][kDCANegToPVMin]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillDCAtoPV); + if (std::abs(v0.dcaV0daughters()) > resoSwitchVals[K0][kDCABetDaug]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillDCAxDaughters); + // v0 radius cuts + if (resoSwitchVals[K0][kUseV0Radius] && (v0.v0radius() < resoCutVals[K0][kRadiusMin] || v0.v0radius() > resoCutVals[K0][kRadiusMax])) + return false; + registry.fill(HIST("K0/hK0Count"), kFillV0Radius); + // cosine pointing angle cuts + if (v0.v0cosPA() < resoCutVals[K0][kCosPA]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillCosPA); + // Proper lifetime + if (resoSwitchVals[K0][kUseProperLifetime] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > resoCutVals[K0][kLifeTime]) + return false; + registry.fill(HIST("K0/hK0Count"), kFillProperLifetime); + if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PIONS)) + return false; + registry.fill(HIST("K0/hK0Count"), kFillDaughterTrackSelection); + + registry.fill(HIST("K0/hK0Mass_sparse"), massK0s, v0.pt(), centrality); + registry.fill(HIST("K0/hK0Phi"), v0.phi()); + registry.fill(HIST("K0/hK0Eta"), v0.eta()); + registry.fill(HIST("K0/PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); + registry.fill(HIST("K0/PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); + registry.fill(HIST("K0/PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registry.fill(HIST("K0/PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); + + registry.fill(HIST("K0/hK0s"), 1); + if (cfgUsePIDEfficiencies) { + double weffDaughter1 = getEfficiency(postrack, 1); + double weffDaughter2 = getEfficiency(negtrack, 1); + weff = weffDaughter1 * weffDaughter2; + if (weff > 0) + registry.fill(HIST("K0/hK0s_corrected"), weff); + } + + return true; + } + + template + bool selectLambda(TCollision const& collision, TV0 const& v0, const double& centrality, double& weff) + { + bool isL = false; // Is lambda candidate + bool isAL = false; // Is anti-lambda candidate + + double mlambda = v0.mLambda(); + double mantilambda = v0.mAntiLambda(); + + // separate the positive and negative V0 daughters + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + registry.fill(HIST("Lambda/hLambdaCount"), kFillCandidate); + if (postrack.pt() < resoCutVals[LAMBDA][kPosTrackPt] || negtrack.pt() < resoCutVals[LAMBDA][kNegTrackPt]) + return false; + + registry.fill(HIST("Lambda/hLambdaCount"), kFillDaughterPt); + if (mlambda > resoCutVals[LAMBDA][kMassMin] && mlambda < resoCutVals[LAMBDA][kMassMax]) + isL = true; + if (mantilambda > resoCutVals[LAMBDA][kMassMin] && mantilambda < resoCutVals[LAMBDA][kMassMax]) + isAL = true; + + if (!isL && !isAL) { + return false; + } + registry.fill(HIST("Lambda/hLambdaCount"), kFillMassCut); + + // Rapidity correction + if (v0.yLambda() > resoCutVals[LAMBDA][kRapidity]) + return false; + registry.fill(HIST("Lambda/hLambdaCount"), kFillRapidityCut); + // DCA cuts for lambda and antilambda + if (isL) { + if (std::abs(v0.dcapostopv()) < resoCutVals[LAMBDA][kDCAPosToPVMin] || std::abs(v0.dcanegtopv()) < resoCutVals[LAMBDA][kDCANegToPVMin]) + return false; + } + if (isAL) { + if (std::abs(v0.dcapostopv()) < resoCutVals[LAMBDA][kDCANegToPVMin] || std::abs(v0.dcanegtopv()) < resoCutVals[LAMBDA][kDCAPosToPVMin]) + return false; + } + registry.fill(HIST("Lambda/hLambdaCount"), kFillDCAtoPV); + if (std::abs(v0.dcaV0daughters()) > resoSwitchVals[LAMBDA][kDCABetDaug]) + return false; + registry.fill(HIST("Lambda/hLambdaCount"), kFillDCAxDaughters); + // v0 radius cuts + if (resoSwitchVals[LAMBDA][kUseV0Radius] && (v0.v0radius() < resoCutVals[LAMBDA][kRadiusMin] || v0.v0radius() > resoCutVals[LAMBDA][kRadiusMax])) + return false; + registry.fill(HIST("Lambda/hLambdaCount"), kFillV0Radius); + // cosine pointing angle cuts + if (v0.v0cosPA() < resoCutVals[LAMBDA][kCosPA]) + return false; + registry.fill(HIST("Lambda/hLambdaCount"), kFillCosPA); + // Proper lifetime + if (resoSwitchVals[LAMBDA][kUseProperLifetime] && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[LAMBDA][kLifeTime]) + return false; + registry.fill(HIST("Lambda/hLambdaCount"), kFillProperLifetime); + if (isL) { + if (!selectionV0Daughter(postrack, PROTONS) || !selectionV0Daughter(negtrack, PIONS)) + return false; + } + if (isAL) { + if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PROTONS)) + return false; + } + registry.fill(HIST("Lambda/hLambdaCount"), kFillDaughterTrackSelection); + + if (isL) { + registry.fill(HIST("Lambda/hLambdaMass_sparse"), mlambda, v0.pt(), centrality); + registry.fill(HIST("Lambda/hLambdaPhi"), v0.phi()); + registry.fill(HIST("Lambda/hLambdaEta"), v0.eta()); + registry.fill(HIST("Lambda/PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); + registry.fill(HIST("Lambda/PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); + registry.fill(HIST("Lambda/PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registry.fill(HIST("Lambda/PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); + + registry.fill(HIST("Lambda/hLambdas"), 1); + if (cfgUsePIDEfficiencies) { + double weffDaughter1 = getEfficiency(postrack, 3); + double weffDaughter2 = getEfficiency(negtrack, 1); + weff = weffDaughter1 * weffDaughter2; + if (weff > 0) + registry.fill(HIST("Lambda/hLambdas_corrected"), weff); + } + } + if (isAL) { + registry.fill(HIST("Lambda/hAntiLambdaMass_sparse"), mantilambda, v0.pt(), centrality); + registry.fill(HIST("Lambda/hAntiLambdaPhi"), v0.phi()); + registry.fill(HIST("Lambda/hAntiLambdaEta"), v0.eta()); + registry.fill(HIST("Lambda/PiPlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); + registry.fill(HIST("Lambda/PiPlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); + registry.fill(HIST("Lambda/PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); + registry.fill(HIST("Lambda/PrMinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); + + registry.fill(HIST("Lambda/hLambdas"), 1); + if (cfgUsePIDEfficiencies) { + double weffDaughter1 = getEfficiency(postrack, 1); + double weffDaughter2 = getEfficiency(negtrack, 3); + weff = weffDaughter1 * weffDaughter2; + if (weff > 0) + registry.fill(HIST("Lambda/hLambdas_corrected"), weff); + } + } + return true; + } + template inline void fillPtSums(TTrack track, const double& vtxz) { @@ -913,9 +1864,8 @@ struct FlowGenericFramework { double weff = (dt == kGen) ? 1. : getEfficiency(track); if (weff < 0) return; - if (std::abs(track.eta()) < cfgEtaPtPt) { + if (std::abs(track.eta()) < cfgEtaPtPt) fFCpt->fill(weff, track.pt()); - } if (!cfgUseGapMethod) { std::complex q2p = {weff * wacc * std::cos(2 * track.phi()), weff * wacc * std::sin(2 * track.phi())}; std::complex q2n = {weff * wacc * std::cos(-2 * track.phi()), weff * wacc * std::sin(-2 * track.phi())}; @@ -935,6 +1885,7 @@ struct FlowGenericFramework { bool withinPtNch = (track.pt() > ptmins[0] && track.pt() < ptmaxs[0]); if (!withinPtPOI && !withinPtRef) return; + double waccRef = (dt == kGen) ? 1. : getAcceptance(track, vtxz, 0); double waccPOI = (dt == kGen) ? 1. : withinPtPOI ? getAcceptance(track, vtxz, pid_index + 1) : getAcceptance(track, vtxz, 0); // @@ -955,7 +1906,7 @@ struct FlowGenericFramework { bool withinPtPOI = (track.pt() > o2::analysis::gfw::ptpoilow && track.pt() < o2::analysis::gfw::ptpoiup); if (!withinPtPOI && !withinPtRef) return; - double weff = (dt == kGen) ? 1. : getEfficiency(track); + double weff = (dt == kGen) ? 1. : getEfficiency(track, 0); if (weff < 0) return; if (cfgUseDensityDependentCorrection && withinPtRef && dt != kGen) { @@ -1005,6 +1956,29 @@ struct FlowGenericFramework { } } + template + float getCentrality(TCollision collision) + { + switch (cfgCentEstimator) { + case kCentFT0C: + return collision.centFT0C(); + case kCentFT0CVariant1: + return collision.centFT0CVariant1(); + case kCentFT0M: + return collision.centFT0M(); + case kCentFV0A: + return collision.centFV0A(); + case kCentNTPV: + return collision.centNTPV(); + case kCentNGlobal: + return collision.centNGlobal(); + case kCentMFT: + return collision.centMFT(); + default: + return collision.centFT0C(); + } + } + template inline void fillEventQA(CollisionObject collision, TracksObject tracks) { @@ -1019,11 +1993,21 @@ struct FlowGenericFramework { } o2::framework::expressions::Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZ; - o2::framework::expressions::Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::itsChi2NCl < cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgDCAz; + o2::framework::expressions::Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::itsChi2NCl < cfgTrackCuts.cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgTrackCuts.cfgDCAz; + + using GFWCollisions = soa::Filtered>; + // using GFWTracks = soa::Filtered>; + using GFWTracks = soa::Filtered>; - using GFWTracks = soa::Filtered>; + SliceCache cache; + Partition posTracks = aod::track::signed1Pt > 0.0f; + Partition negTracks = aod::track::signed1Pt < 0.0f; - void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + double massKaPlus = o2::constants::physics::MassKPlus; + double massLambda = o2::constants::physics::MassLambda; + double massK0Short = o2::constants::physics::MassK0Short; + + void processData(GFWCollisions::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks, aod::V0Datas const& v0s) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -1044,57 +2028,49 @@ struct FlowGenericFramework { } if (!cfgFillWeights && !cfgRunByRun) loadCorrections(bc); + registry.fill(HIST("eventQA/eventSel"), 0.5); if (cfgRunByRun) th1sList[run][hEventSel]->Fill(0.5); + if (!collision.sel8()) return; + registry.fill(HIST("eventQA/eventSel"), 1.5); if (cfgRunByRun) th1sList[run][hEventSel]->Fill(1.5); + + float centrality = getCentrality(collision); + if (cfgDoOccupancySel) { int occupancy = collision.trackOccupancyInTimeRange(); + registry.fill(HIST("eventQA/before/occ_mult_cent"), occupancy, tracks.size(), centrality); if (occupancy < 0 || occupancy > cfgOccupancySelection) return; + registry.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); } registry.fill(HIST("eventQA/eventSel"), 2.5); if (cfgRunByRun) th1sList[run][hEventSel]->Fill(2.5); - float centrality; - switch (cfgCentEstimator) { - case kCentFT0C: - centrality = collision.centFT0C(); - break; - case kCentFT0CVariant1: - centrality = collision.centFT0CVariant1(); - break; - case kCentFT0M: - centrality = collision.centFT0M(); - break; - case kCentFV0A: - centrality = collision.centFV0A(); - break; - case kCentNTPV: - centrality = collision.centNTPV(); - break; - default: - centrality = collision.centFT0C(); - } if (cfgFillQA) fillEventQA(collision, tracks); registry.fill(HIST("eventQA/before/centrality"), centrality); registry.fill(HIST("eventQA/before/multiplicity"), tracks.size()); - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), centrality, run)) + if (!eventSelected(collision, tracks.size(), centrality, run)) return; if (cfgFillQA) fillEventQA(collision, tracks); registry.fill(HIST("eventQA/after/centrality"), centrality); registry.fill(HIST("eventQA/after/multiplicity"), tracks.size()); - processCollision(collision, tracks, centrality, run); + + // Get magnetic field polarity + auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; // o2-linter: disable=magic-number (hard coded default cut) + + processCollision(collision, tracks, v0s, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processData, "Process analysis for non-derived data", true); - void processMCReco(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) + void processMCReco(GFWCollisions::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&, aod::V0Datas const& v0s) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -1103,45 +2079,69 @@ struct FlowGenericFramework { if (cfgRunByRun) createRunByRunHistograms(run); } + + registry.fill(HIST("eventQA/eventSel"), 0.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(0.5); + if (!collision.sel8()) return; - const auto centrality = collision.centFT0C(); + + registry.fill(HIST("eventQA/eventSel"), 1.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(1.5); + + const auto centrality = getCentrality(collision); + + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + registry.fill(HIST("eventQA/before/occ_mult_cent"), occupancy, tracks.size(), centrality); + if (occupancy < 0 || occupancy > cfgOccupancySelection) + return; + registry.fill(HIST("eventQA/after/occ_mult_cent"), occupancy, tracks.size(), centrality); + } + registry.fill(HIST("eventQA/eventSel"), 2.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(2.5); + if (cfgFillQA) fillEventQA(collision, tracks); - if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), centrality, run)) + if (!eventSelected(collision, tracks.size(), centrality, run)) return; if (cfgFillQA) fillEventQA(collision, tracks); if (!cfgFillWeights) loadCorrections(bc); - processCollision(collision, tracks, centrality, run); + + auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; // o2-linter: disable=magic-number (hard coded default cut) + processCollision(collision, tracks, v0s, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processMCReco, "Process analysis for MC reconstructed events", false); o2::framework::expressions::Filter mcCollFilter = nabs(aod::mccollision::posZ) < cfgVtxZ; - void processMCGen(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles) + void processMCGen(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, aod::V0Datas const& v0s) { if (collisions.size() != 1) return; float centrality = -1; for (const auto& collision : collisions) { - centrality = collision.centFT0C(); + centrality = getCentrality(collision); } int run = 0; - processCollision(mcCollision, particles, centrality, run); + processCollision(mcCollision, particles, v0s, centrality, -999, run); } PROCESS_SWITCH(FlowGenericFramework, processMCGen, "Process analysis for MC generated events", false); - void processOnTheFly(soa::Filtered::iterator const& mcCollision, aod::McParticles const& mcParticles) + void processOnTheFly(soa::Filtered::iterator const& mcCollision, aod::McParticles const& mcParticles, aod::V0Datas const& v0s) { int run = 0; registry.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); - processCollision(mcCollision, mcParticles, mcCollision.impactParameter(), run); + processCollision(mcCollision, mcParticles, v0s, mcCollision.impactParameter(), -999, run); } PROCESS_SWITCH(FlowGenericFramework, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); - void processRun2(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + void processRun2(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks, aod::V0Datas const& v0s) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -1155,7 +2155,9 @@ struct FlowGenericFramework { const auto centrality = collision.centRun2V0M(); if (!cfgFillWeights) loadCorrections(bc); - processCollision(collision, tracks, centrality, run); + + auto field = (cfgMagField == 99999) ? getMagneticField(bc.timestamp()) : cfgMagField; // o2-linter: disable=magic-number (hard coded default cut) + processCollision(collision, tracks, v0s, centrality, field, run); } PROCESS_SWITCH(FlowGenericFramework, processRun2, "Process analysis for Run 2 converted data", false); }; diff --git a/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx b/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx new file mode 100644 index 00000000000..b921074a4f8 --- /dev/null +++ b/PWGCF/GenericFramework/Tasks/flowGfwV02.cxx @@ -0,0 +1,1204 @@ +// 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 flowGfwV02.cxx +/// \brief Skeleton copy of flowGfwLightIons with empty function bodies +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + +#include "FlowContainer.h" +#include "FlowPtContainer.h" +#include "GFW.h" +#include "GFWConfig.h" +#include "GFWCumulant.h" +#include "GFWPowerArray.h" +#include "GFWWeights.h" +#include "GFWWeightsList.h" + +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/JCorran/DataModel/JCatalyst.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; +static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; + +namespace o2::analysis::gfw +{ +std::vector ptbinning = {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}; +float ptpoilow = 0.2, ptpoiup = 10.0; +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; +float vtxZlow = -10.0, vtxZup = 10.0; +int phibins = 72; +float philow = 0.0; +float phiup = o2::constants::math::TwoPI; +int nchbins = 300; +float nchlow = 0; +float nchup = 3000; +std::vector centbinning(90); +int nBootstrap = 10; +std::vector> etagapsPtPt; +GFWRegions regions; +GFWCorrConfigs configs; +std::vector multGlobalCorrCutPars; +std::vector multPVCorrCutPars; +std::vector multGlobalPVCorrCutPars; +} // namespace o2::analysis::gfw + +struct FlowGfwV02 { + O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") + O2_DEFINE_CONFIGURABLE(cfgMpar, int, 4, "Highest order of pt-pt correlations") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + O2_DEFINE_CONFIGURABLE(cfgCentralityFactor, double, 1., "Correction factor for testing centrality robustness"); + 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(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(cfgPIDEfficiency, bool, false, "Use PID efficiency for efficiency calculation") + O2_DEFINE_CONFIGURABLE(cfgFixedMultMin, int, 1, "Minimum for fixed nch range"); + O2_DEFINE_CONFIGURABLE(cfgFixedMultMax, int, 3000, "Maximum for fixed nch range"); + O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") + O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get dEdx histograms for pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); + O2_DEFINE_CONFIGURABLE(cfgNormalizeByCharged, bool, true, "Enable or disable the normalization by charged particles"); + O2_DEFINE_CONFIGURABLE(cfgConsistentEventFlag, int, 15, "Flag for consistent event selection"); + O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, true, "Use additional event cut on mult correlations"); + + // Event selection cuts + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); + O2_DEFINE_CONFIGURABLE(cfgIsGoodITSLayersAll, bool, true, "kIsGoodITSLayersAll"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInTimeRangeStandard, bool, true, "kNoCollInTimeRangeStandard"); + O2_DEFINE_CONFIGURABLE(cfgNoCollInRofStandard, bool, true, "kNoCollInRofStandard"); + O2_DEFINE_CONFIGURABLE(cfgNoHighMultCollInPrevRof, bool, true, "kNoHighMultCollInPrevRof"); + O2_DEFINE_CONFIGURABLE(cfgNoITSROFrameBorder, bool, true, "kNoITSROFrameBorder"); + O2_DEFINE_CONFIGURABLE(cfgNoTimeFrameBorder, bool, true, "kNoTimeFrameBorder"); + O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "kTVXinTRD - Use kTVXinTRD (reject TRD triggered events)"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "kIsVertexITSTPC - Selects collisions with at least one ITS-TPC track"); + } cfgEventCutFlags; + + struct : ConfigurableGroup { + Configurable> cfgMultGlobalCutPars{"cfgMultGlobalCutPars", std::vector{2272.16, -76.6932, 1.01204, -0.00631545, 1.59868e-05, 136.336, -4.97006, 0.121199, -0.0015921, 7.66197e-06}, "Global vs FT0C multiplicity cut parameter values"}; + Configurable> cfgMultPVCutPars{"cfgMultPVCutPars", std::vector{3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05}, "PV vs FT0C multiplicity cut parameter values"}; + Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.223013, 0.715849, 0.664242, 0.0829653, -0.000503733, 1.21185e-06}, "Global vs PV multiplicity cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultCorrHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCorrCutFunction, std::string, "[0] + [1]*x + 3*([2] + [3]*x + [4]*x*x + [5]*x*x*x)", "Functional for global vs pv multiplicity correlation cut"); + } cfgMultCorrCuts; + + // Track selection cuts + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + O2_DEFINE_CONFIGURABLE(cfgDCAxy, std::string, "(0.0026+0.005/(x^1.01))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); + O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 50, "Cut on number of TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); + O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgPtMin, float, 0.2, "minimum pt (GeV/c)"); + O2_DEFINE_CONFIGURABLE(cfgPtMax, float, 10, "maximum pt (GeV/c)"); + O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 0.8, "eta cut"); + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); + O2_DEFINE_CONFIGURABLE(cfgOccupancySelection, int, 2000, "Max occupancy selection, -999 to disable"); + } cfgTrackCuts; + + struct : ConfigurableGroup { + ConfigurableAxis cfgAxisPt{"cfgAxisPt", {VARIABLE_WIDTH, 0.2f, 0.5f, 1.f, 1.5f, 2.f, 3.f, 4.f, 6.f, 10.f}, "pt axis for histograms"}; + ConfigurableAxis cfgAxisNsigmaTPC{"cfgAxisNsigmaTPC", {80, -5.f, 5.f}, "nsigmaTPC axis"}; + ConfigurableAxis cfgAxisNsigmaTOF{"cfgAxisNsigmaTOF", {80, -5.f, 5.f}, "nsigmaTOF axis"}; + ConfigurableAxis cfgAxisNsigmaITS{"cfgAxisNsigmaITS", {80, -5.f, 5.f}, "nsigmaITS axis"}; + ConfigurableAxis cfgAxisTpcSignal{"cfgAxisTpcSignal", {250, 0.f, 250.f}, "dEdx axis for TPC"}; + ConfigurableAxis cfgAxisSigma{"cfgAxisSigma", {200, 0, 20}, "sigma axis for TPC"}; + } cfgPIDHistograms; + + // GFW binning + Configurable cfgGFWBinning{"cfgGFWBinning", {40, 16, 72, 300, 0, 3000, 0.2, 10.0, 0.2, 5.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}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90}}, "Configuration for binning"}; + Configurable cfgRegions{"cfgRegions", {{"refN", "refP", "refFull", "refMid", "piP", "kaP", "prP"}, {-0.8, 0.5, -0.8, -0.4, 0.5, 0.5, 0.5}, {-0.5, 0.8, 0.8, 0.4, 0.8, 0.8, 0.8}, {0, 0, 0, 0, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1}}, "Configurations for GFW regions"}; + + Configurable cfgCorrConfig{"cfgCorrConfig", {{"refP {2} refN {-2}", "piP {2} refN {-2}", "kaP {2} refN {-2}", "prP {2} refN {-2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}", "refFull {2 -2}"}, {"ChGap22", "PiGap22", "KaGap22", "PrGap22", "ChFull22", "nchCh", "nchPi", "nchKa", "nchPr", "v02ptCh", "v02ptPi", "v02ptKa", "v02ptPr"}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {15, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, "Configurations for each correlation to calculate"}; + Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; + + struct : ConfigurableGroup { + Configurable cfgZvtxMax{"cfgZvtxMax", 10.0f, "Maximum primary vertex cut applied for the events."}; + Configurable cfgMultMin{"cfgMultMin", 10, "Minimum number of particles required for the event to have."}; + } cfgEventCuts; + + // // Filters to be applied to the received data. + // // The analysis assumes the data has been subjected to a QA of its selection, + // // and thus only the final distributions of the data for analysis are saved. + o2::framework::expressions::Filter collFilter = (nabs(aod::collision::posZ) < cfgEventCuts.cfgZvtxMax); + o2::framework::expressions::Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (aod::track::pt < cfgTrackCuts.cfgPtMax) && nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::itsChi2NCl < cfgTrackCuts.cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgTrackCuts.cfgDCAz; + + // Connect to ccdb + Service ccdb; + + struct Config { + TH1D* mEfficiency[4] = {nullptr, nullptr, nullptr, nullptr}; + GFWWeights* mAcceptance; + bool correctionsLoaded = false; + } cfg; + + // Define output + OutputObj fFC{FlowContainer("FlowContainer")}; + HistogramRegistry registry{"registry"}; + + enum CentEstimators { + kCentFT0C = 0, + kCentFT0CVariant1, + kCentFT0M, + kCentFV0A, + kCentNTPV, + kCentNGlobal, + kCentMFT + }; + std::map centNamesMap = {{kCentFT0C, "FT0C"}, {kCentFT0CVariant1, "FT0C variant1"}, {kCentFT0M, "FT0M"}, {kCentFV0A, "FV0A"}, {kCentNTPV, "NTPV"}, {kCentNGlobal, "NGlobal"}, {kCentMFT, "MFT"}}; + + enum EventSelFlags { + kFilteredEvent = 1, + kSel8, + kOccupancy, + kTVXinTRD, + kNoSameBunchPileup, + kIsGoodZvtxFT0vsPV, + kNoCollInTimeRangeStandard, + kNoCollInRofStandard, + kNoHighMultCollInPrevRof, + kNoTimeFrameBorder, + kNoITSROFrameBorder, + kIsVertexITSTPC, + kIsGoodITSLayersAll, + kMultCuts, + kTrackCent + }; + + std::unique_ptr fGFW{std::make_unique()}; + std::unique_ptr fRndm{std::make_unique(0)}; + std::unique_ptr fSecondAxis{nullptr}; + std::vector corrconfigs; + int lastRun = -1; + + // region indices for consistency flag + int posRegionIndex = -1; + int negRegionIndex = -1; + int fullRegionIndex = -1; + int midRegionIndex = -1; + // PID + + struct PIDState { + o2::aod::ITSResponse itsResponse; + std::array tofNsigmaCut; + std::array itsNsigmaCut; + std::array tpcNsigmaCut; + TH1D* hPtMid[4] = {nullptr, nullptr, nullptr, nullptr}; + }; + PIDState pidStates; + + // Event selection cuts - Alex + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fMultPVGlobalCutHigh = nullptr; + TF1* fMultGlobalV0ACutLow = nullptr; + TF1* fMultGlobalV0ACutHigh = nullptr; + TF1* fMultGlobalT0ACutLow = nullptr; + TF1* fMultGlobalT0ACutHigh = nullptr; + + TF1* fPtDepDCAxy = nullptr; + + using GFWTracks = soa::Filtered>; + + enum PIDIndex { + PidCharged = 0, + PidPions, + PidKaons, + PidProtons + }; + enum PiKpArrayIndex { + IndPionUp = 0, + IndKaonUp, + IndProtonUp, + IndPionLow, + IndKaonLow, + IndProtonLow + }; + enum DetectorType { + kTPC = 0, + kTOF, + kITS + }; + + void init(InitContext const&) + { + + pidStates.tpcNsigmaCut[IndPionUp] = nSigmas->getData()[IndPionUp][kTPC]; + pidStates.tpcNsigmaCut[IndKaonUp] = nSigmas->getData()[IndKaonUp][kTPC]; + pidStates.tpcNsigmaCut[IndProtonUp] = nSigmas->getData()[IndProtonUp][kTPC]; + pidStates.tpcNsigmaCut[IndPionLow] = nSigmas->getData()[IndPionLow][kTPC]; + pidStates.tpcNsigmaCut[IndKaonLow] = nSigmas->getData()[IndKaonLow][kTPC]; + pidStates.tpcNsigmaCut[IndProtonLow] = nSigmas->getData()[IndProtonLow][kTPC]; + + pidStates.tofNsigmaCut[IndPionUp] = nSigmas->getData()[IndPionUp][kTOF]; + pidStates.tofNsigmaCut[IndKaonUp] = nSigmas->getData()[IndKaonUp][kTOF]; + pidStates.tofNsigmaCut[IndProtonUp] = nSigmas->getData()[IndProtonUp][kTOF]; + pidStates.tofNsigmaCut[IndPionLow] = nSigmas->getData()[IndPionLow][kTOF]; + pidStates.tofNsigmaCut[IndKaonLow] = nSigmas->getData()[IndKaonLow][kTOF]; + pidStates.tofNsigmaCut[IndProtonLow] = nSigmas->getData()[IndProtonLow][kTOF]; + + pidStates.itsNsigmaCut[IndPionUp] = nSigmas->getData()[IndPionUp][kITS]; + pidStates.itsNsigmaCut[IndKaonUp] = nSigmas->getData()[IndKaonUp][kITS]; + pidStates.itsNsigmaCut[IndProtonUp] = nSigmas->getData()[IndProtonUp][kITS]; + pidStates.itsNsigmaCut[IndPionLow] = nSigmas->getData()[IndPionLow][kITS]; + pidStates.itsNsigmaCut[IndKaonLow] = nSigmas->getData()[IndKaonLow][kITS]; + pidStates.itsNsigmaCut[IndProtonLow] = nSigmas->getData()[IndProtonLow][kITS]; + + if (cfgGetNsigmaQA) { + if (cfgUseItsPID) { + registry.add("QA_PID/before/TofItsNsigma", "", {HistType::kTHnSparseD, {cfgPIDHistograms.cfgAxisNsigmaITS, cfgPIDHistograms.cfgAxisNsigmaTOF, cfgPIDHistograms.cfgAxisPt}}); + } else { + registry.add("QA_PID/before/TofTpcNsigma_pions", "", {HistType::kTHnSparseD, {cfgPIDHistograms.cfgAxisNsigmaTPC, cfgPIDHistograms.cfgAxisNsigmaTOF, cfgPIDHistograms.cfgAxisPt}}); + registry.add("QA_PID/before/TofTpcNsigma_kaons", "", {HistType::kTHnSparseD, {cfgPIDHistograms.cfgAxisNsigmaTPC, cfgPIDHistograms.cfgAxisNsigmaTOF, cfgPIDHistograms.cfgAxisPt}}); + registry.add("QA_PID/before/TofTpcNsigma_protons", "", {HistType::kTHnSparseD, {cfgPIDHistograms.cfgAxisNsigmaTPC, cfgPIDHistograms.cfgAxisNsigmaTOF, cfgPIDHistograms.cfgAxisPt}}); + } + + registry.add("QA_PID/before/TpcdEdx_ptwise_pions", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisTpcSignal, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/ExpTpcdEdx_ptwise_pions", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisTpcSignal, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/ExpSigma_ptwise_pions", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisSigma, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/TpcdEdx_ptwise_kaons", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisTpcSignal, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/ExpTpcdEdx_ptwise_kaons", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisTpcSignal, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/ExpSigma_ptwise_kaons", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisSigma, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/TpcdEdx_ptwise_protons", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisTpcSignal, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/ExpTpcdEdx_ptwise_protons", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisTpcSignal, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.add("QA_PID/before/ExpSigma_ptwise_protons", "", {HistType::kTHnSparseD, {{cfgPIDHistograms.cfgAxisPt, cfgPIDHistograms.cfgAxisSigma, cfgPIDHistograms.cfgAxisNsigmaTOF}}}); + registry.addClone("QA_PID/before/", "QA_PID/after/"); + } + + o2::analysis::gfw::regions.SetNames(cfgRegions->GetNames()); + o2::analysis::gfw::regions.SetEtaMin(cfgRegions->GetEtaMin()); + o2::analysis::gfw::regions.SetEtaMax(cfgRegions->GetEtaMax()); + o2::analysis::gfw::regions.SetpTDifs(cfgRegions->GetpTDifs()); + o2::analysis::gfw::regions.SetBitmasks(cfgRegions->GetBitmasks()); + o2::analysis::gfw::configs.SetCorrs(cfgCorrConfig->GetCorrs()); + o2::analysis::gfw::configs.SetHeads(cfgCorrConfig->GetHeads()); + o2::analysis::gfw::configs.SetpTDifs(cfgCorrConfig->GetpTDifs()); + o2::analysis::gfw::configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); + o2::analysis::gfw::regions.Print(); + o2::analysis::gfw::configs.Print(); + o2::analysis::gfw::ptbinning = cfgGFWBinning->GetPtBinning(); + o2::analysis::gfw::ptpoilow = cfgGFWBinning->GetPtPOImin(); + o2::analysis::gfw::ptpoiup = cfgGFWBinning->GetPtPOImax(); + o2::analysis::gfw::ptreflow = cfgGFWBinning->GetPtRefMin(); + o2::analysis::gfw::ptrefup = cfgGFWBinning->GetPtRefMax(); + o2::analysis::gfw::ptlow = cfgTrackCuts.cfgPtMin; + o2::analysis::gfw::ptup = cfgTrackCuts.cfgPtMax; + o2::analysis::gfw::etabins = cfgGFWBinning->GetEtaBins(); + o2::analysis::gfw::vtxZbins = cfgGFWBinning->GetVtxZbins(); + o2::analysis::gfw::phibins = cfgGFWBinning->GetPhiBins(); + o2::analysis::gfw::philow = 0.0f; + o2::analysis::gfw::phiup = o2::constants::math::TwoPI; + o2::analysis::gfw::nchbins = cfgGFWBinning->GetNchBins(); + o2::analysis::gfw::nchlow = cfgGFWBinning->GetNchMin(); + o2::analysis::gfw::nchup = cfgGFWBinning->GetNchMax(); + o2::analysis::gfw::centbinning = cfgGFWBinning->GetCentBinning(); + cfgGFWBinning->Print(); + o2::analysis::gfw::multGlobalCorrCutPars = cfgMultCorrCuts.cfgMultGlobalCutPars; + o2::analysis::gfw::multPVCorrCutPars = cfgMultCorrCuts.cfgMultPVCutPars; + o2::analysis::gfw::multGlobalPVCorrCutPars = cfgMultCorrCuts.cfgMultGlobalPVCutPars; + + // Initialise pt spectra histograms for different particles + pidStates.hPtMid[PidCharged] = new TH1D("hPtMid_charged", "hPtMid_charged", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidPions] = new TH1D("hPtMid_pions", "hPtMid_pions", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidKaons] = new TH1D("hPtMid_kaons", "hPtMid_kaons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidProtons] = new TH1D("hPtMid_protons", "hPtMid_protons", o2::analysis::gfw::ptbinning.size() - 1, &o2::analysis::gfw::ptbinning[0]); + pidStates.hPtMid[PidCharged]->SetDirectory(nullptr); + pidStates.hPtMid[PidPions]->SetDirectory(nullptr); + pidStates.hPtMid[PidKaons]->SetDirectory(nullptr); + pidStates.hPtMid[PidProtons]->SetDirectory(nullptr); + + AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgTrackCuts.cfgEtaMax, cfgTrackCuts.cfgEtaMax, "#eta"}; + AxisSpec vtxAxis = {o2::analysis::gfw::vtxZbins, -cfgEventCuts.cfgZvtxMax, cfgEventCuts.cfgZvtxMax, "Vtx_{z} (cm)"}; + AxisSpec ptAxis = {o2::analysis::gfw::ptbinning, "#it{p}_{T} GeV/#it{c}"}; + + std::string sCentralityEstimator = "FT0C centrality (%)"; + AxisSpec centAxis = {o2::analysis::gfw::centbinning, sCentralityEstimator.c_str()}; + + std::vector nchbinning; + int nchskip = (o2::analysis::gfw::nchup - o2::analysis::gfw::nchlow) / o2::analysis::gfw::nchbins; + for (int i = 0; i <= o2::analysis::gfw::nchbins; ++i) { + nchbinning.push_back(nchskip * i + o2::analysis::gfw::nchlow + 0.5); + } + AxisSpec nchAxis = {nchbinning, "N_{ch}"}; + AxisSpec t0cAxis = {1000, 0, 10000, "N_{ch} (T0C)"}; + AxisSpec t0aAxis = {300, 0, 30000, "N_{ch} (T0A)"}; + AxisSpec v0aAxis = {800, 0, 80000, "N_{ch} (V0A)"}; + AxisSpec multpvAxis = {600, 0, 600, "N_{ch} (PV)"}; + AxisSpec dcaZAxis = {200, -2, 2, "DCA_{z} (cm)"}; + AxisSpec dcaXYAxis = {200, -0.5, 0.5, "DCA_{xy} (cm)"}; + + registry.add("v02pt", "", {HistType::kTProfile2D, {ptAxis, centAxis}}); + registry.add("nchMid", "", {HistType::kTProfile2D, {ptAxis, centAxis}}); + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + int ptbins = o2::analysis::gfw::ptbinning.size() - 1; + fSecondAxis = std::make_unique(ptbins, &o2::analysis::gfw::ptbinning[0]); + + // QA histograms + registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAxis, dcaZAxis}}); + registry.add("trackQA/before/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, ptAxis}}); + registry.add("trackQA/after/pt_ref", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); + registry.add("trackQA/after/pt_poi", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + registry.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment; #chi^{2}/TPC cluster", {HistType::kTH1D, {{100, 0., 5.}}}); + registry.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track; #chi^{2}/ITS cluster", {HistType::kTH1D, {{100, 0., 50.}}}); + registry.add("trackQA/before/nTPCClusters", "Number of found TPC clusters; TPC N_{cls}; Counts", {HistType::kTH1D, {{100, 40, 180}}}); + registry.add("trackQA/before/nITSClusters", "Number of found ITS clusters; ITS N_{cls}; Counts", {HistType::kTH1D, {{100, 0, 20}}}); + registry.add("trackQA/before/nTPCCrossedRows", "Number of crossed TPC Rows; TPC X-rows; Counts", {HistType::kTH1D, {{100, 40, 180}}}); + registry.addClone("trackQA/before/", "trackQA/after/"); + + registry.add("eventQA/before/globalTracks_centT0C", "", {HistType::kTH2D, {centAxis, nchAxis}}); + registry.add("eventQA/before/PVTracks_centT0C", "", {HistType::kTH2D, {centAxis, multpvAxis}}); + registry.add("eventQA/before/multT0C_centT0C", "", {HistType::kTH2D, {centAxis, t0cAxis}}); + + registry.add("eventQA/before/centT0M_centT0C", "", {HistType::kTH2D, {centAxis, centAxis}}); + registry.add("eventQA/before/centV0A_centT0C", "", {HistType::kTH2D, {centAxis, centAxis}}); + registry.add("eventQA/before/centGlobal_centT0C", "", {HistType::kTH2D, {centAxis, centAxis}}); + registry.add("eventQA/before/centNTPV_centT0C", "", {HistType::kTH2D, {centAxis, centAxis}}); + registry.add("eventQA/before/centMFT_centT0C", "", {HistType::kTH2D, {centAxis, centAxis}}); + + 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, {v0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "", {HistType::kTH2D, {t0aAxis, v0aAxis}}); + + registry.add("eventQA/before/multiplicity", "", {HistType::kTH1D, {nchAxis}}); + registry.add("eventQA/before/centrality", "", {HistType::kTH1D, {centAxis}}); + registry.addClone("eventQA/before/", "eventQA/after/"); + + // Event selection histograms + registry.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{15, 0.5, 15.5}}}); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kFilteredEvent, "Filtered event"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kSel8, "sel8"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kOccupancy, "occupancy"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kTVXinTRD, "kTVXinTRD"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoSameBunchPileup, "kNoSameBunchPileup"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsGoodZvtxFT0vsPV, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollInTimeRangeStandard, "kNoCollInTimeRangeStandard"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollInRofStandard, "kNoCollInRofStandard"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoHighMultCollInPrevRof, "kNoHighMultCollInPrevRof"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoTimeFrameBorder, "kNoTimeFrameBorder"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoITSROFrameBorder, "kNoITSROFrameBorder"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsVertexITSTPC, "kIsVertexITSTPC"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kIsGoodITSLayersAll, "kIsGoodITSLayersAll"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kMultCuts, "after Mult cuts"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kTrackCent, "has track + within cent"); + + if (o2::analysis::gfw::regions.GetSize() < 0) + LOGF(error, "Configuration contains vectors of different size - check the GFWRegions configurable"); + for (auto i(0); i < o2::analysis::gfw::regions.GetSize(); ++i) { + fGFW->AddRegion(o2::analysis::gfw::regions.GetNames()[i], o2::analysis::gfw::regions.GetEtaMin()[i], o2::analysis::gfw::regions.GetEtaMax()[i], (o2::analysis::gfw::regions.GetpTDifs()[i]) ? ptbins + 1 : 1, o2::analysis::gfw::regions.GetBitmasks()[i]); + } + for (auto i = 0; i < o2::analysis::gfw::configs.GetSize(); ++i) { + corrconfigs.push_back(fGFW->GetCorrelatorConfig(o2::analysis::gfw::configs.GetCorrs()[i], o2::analysis::gfw::configs.GetHeads()[i], o2::analysis::gfw::configs.GetpTDifs()[i])); + } + if (corrconfigs.empty()) + LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); + fGFW->CreateRegions(); + TObjArray* oba = new TObjArray(); + addConfigObjectsToObjArray(oba, corrconfigs); + LOGF(info, "Number of correlators: %d", oba->GetEntries()); + fFC->SetName("FlowContainer"); + fFC->SetXAxis(fSecondAxis.get()); + fFC->Initialize(oba, centAxis, cfgNbootstrap); + delete oba; + + if (cfgConsistentEventFlag) { + posRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refP"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + negRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refN"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + fullRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refFull"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + midRegionIndex = [&]() { + auto begin = cfgRegions->GetNames().begin(); + auto end = cfgRegions->GetNames().end(); + auto it = std::find(begin, end, "refMid"); + return (it != end) ? std::distance(begin, it) : -1; + }(); + } + + if (cfgUseAdditionalEventCut) { + fMultPVCutLow = new TF1("fMultPVCutLow", cfgMultCorrCuts.cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultPVCutLow->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); + fMultPVCutHigh = new TF1("fMultPVCutHigh", cfgMultCorrCuts.cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultPVCutHigh->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); + fMultCutLow = new TF1("fMultCutLow", cfgMultCorrCuts.cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultCutLow->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrCuts.cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + fMultPVGlobalCutHigh = new TF1("fMultPVGlobalCutHigh", cfgMultCorrCuts.cfgMultGlobalPVCorrCutFunction->c_str(), 0, nchbinning.back()); + fMultPVGlobalCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalPVCorrCutPars[0])); + } + // Set DCAxy cut + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgTrackCuts.cfgDCAxy->c_str()), 0.001, 100); + fPtDepDCAxy->SetParameter(0, cfgTrackCuts.cfgDCAxyNSigma); + } + + static constexpr std::string_view FillTimeName[] = {"before/", "after/"}; + enum QAFillTime { + kBefore, + kAfter + }; + + void addConfigObjectsToObjArray(TObjArray* oba, const std::vector& configs) + { + for (auto it = configs.begin(); it != configs.end(); ++it) { + if (it->pTDif) { + std::string suffix = "_ptDiff"; + for (auto i = 0; i < fSecondAxis->GetNbins(); ++i) { + std::string index = Form("_pt_%i", i + 1); + oba->Add(new TNamed(it->Head.c_str() + index, it->Head.c_str() + suffix)); + } + } else { + oba->Add(new TNamed(it->Head.c_str(), it->Head.c_str())); + } + } + } + + template + int getNsigmaPID(TTrack track) + { + // Computing Nsigma arrays for pion, kaon, and protons + std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + std::array nSigmaITS = {pidStates.itsResponse.nSigmaITS(track), pidStates.itsResponse.nSigmaITS(track), pidStates.itsResponse.nSigmaITS(track)}; + int pid = -1; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton + + std::array nSigmaToUse = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::array detectorNsigmaCut = cfgUseItsPID ? pidStates.itsNsigmaCut : pidStates.tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS + + bool isPion, isKaon, isProton; + bool isDetectedPion = nSigmaToUse[IndPionUp] < detectorNsigmaCut[IndPionUp] && nSigmaToUse[IndPionUp] > detectorNsigmaCut[IndPionLow]; + bool isDetectedKaon = nSigmaToUse[IndKaonUp] < detectorNsigmaCut[IndKaonUp] && nSigmaToUse[IndKaonUp] > detectorNsigmaCut[IndKaonLow]; + bool isDetectedProton = nSigmaToUse[IndProtonUp] < detectorNsigmaCut[IndProtonUp] && nSigmaToUse[IndProtonUp] > detectorNsigmaCut[IndProtonLow]; + + bool isTofPion = nSigmaTOF[IndPionUp] < pidStates.tofNsigmaCut[IndPionUp] && nSigmaTOF[IndPionUp] > pidStates.tofNsigmaCut[IndPionLow]; + bool isTofKaon = nSigmaTOF[IndKaonUp] < pidStates.tofNsigmaCut[IndKaonUp] && nSigmaTOF[IndKaonUp] > pidStates.tofNsigmaCut[IndKaonLow]; + bool isTofProton = nSigmaTOF[IndProtonUp] < pidStates.tofNsigmaCut[IndProtonUp] && nSigmaTOF[IndProtonUp] > pidStates.tofNsigmaCut[IndProtonLow]; + + if (track.pt() > cfgTofPtCut && !track.hasTOF()) { + return -1; + } else if (track.pt() > cfgTofPtCut && track.hasTOF()) { + isPion = isTofPion && isDetectedPion; + isKaon = isTofKaon && isDetectedKaon; + isProton = isTofProton && isDetectedProton; + } else { + isPion = isDetectedPion; + isKaon = isDetectedKaon; + isProton = isDetectedProton; + } + + if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { + return -1; // more than one particle satisfy the criteria + } + + if (isPion) { + pid = PidPions; + } else if (isKaon) { + pid = PidKaons; + } else if (isProton) { + pid = PidProtons; + } else { + return -1; // no particle satisfies the criteria + } + + return pid; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton + } + + void loadCorrections(aod::BCsWithTimestamps::iterator const& bc) + { + uint64_t timestamp = bc.timestamp(); + if (cfg.correctionsLoaded) + return; + if (!cfgAcceptance.value.empty()) { + cfg.mAcceptance = ccdb->getForTimeStamp(cfgAcceptance.value, timestamp); + } + if (!cfgEfficiency.value.empty()) { + cfg.mEfficiency[PidCharged] = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfg.mEfficiency[PidCharged] == nullptr) { + LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency[PidCharged]); + } + if (cfgPIDEfficiency) { + const std::array pidStrings = {"ch", "pi", "ka", "pr"}; + for (int i = 1; i < 4; i++) { + + cfg.mEfficiency[i] = ccdb->getForTimeStamp(cfgEfficiency.value + pidStrings[i], timestamp); + if (cfg.mEfficiency[i] == nullptr) { + LOGF(fatal, "Could not load PID efficiency histogram from %s", cfgEfficiency.value + pidStrings[i].c_str()); + } + LOGF(info, "Loaded PID efficiency histogram from %s (%p)", cfgEfficiency.value + pidStrings[i].c_str(), (void*)cfg.mEfficiency[i]); + } + } + cfg.correctionsLoaded = true; + } + + void loadCorrections(int runnumber) + { + if (cfg.correctionsLoaded) + return; + if (!cfgAcceptance.value.empty()) { + cfg.mAcceptance = ccdb->getForRun(cfgAcceptance.value, runnumber); + } + if (!cfgEfficiency.value.empty()) { + cfg.mEfficiency[PidCharged] = ccdb->getForRun(cfgEfficiency.value, runnumber); + } + cfg.correctionsLoaded = true; + } + + template + double getJTrackAcceptance(TTrack track) + { + double wacc = 1; + if constexpr (requires { track.weightNUA(); }) + wacc = 1. / track.weightNUA(); + return wacc; + } + + template + double getJTrackEfficiency(TTrack track) + { + double eff = 1.; + if constexpr (requires { track.weightEff(); }) + eff = track.weightEff(); + return eff; + } + + template + double getAcceptance(TTrack track, const double& vtxz) + { + double wacc = 1; + if (cfg.mAcceptance) + wacc = cfg.mAcceptance->getNUA(track.phi(), track.eta(), vtxz); + return wacc; + } + + template + double getEfficiency(TTrack track, const int& pid = PidCharged) + { + double eff = 1.; + if (cfg.mEfficiency[pid]) + eff = cfg.mEfficiency[pid]->GetBinContent(cfg.mEfficiency[pid]->FindBin(track.pt())); + if (eff == 0) + return -1.; + else + return 1. / eff; + } + + template + bool eventSelected(TCollision collision, const int& multTrk, const float& centrality) + { + if (cfgEventCutFlags.cfgTVXinTRD) { + if (collision.alias_bit(kTVXinTRD)) { + // TRD triggered + // "CMTVX-B-NOPF-TRD,minbias_TVX" + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kTVXinTRD); + } + if (cfgEventCutFlags.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("eventQA/eventSel"), kNoSameBunchPileup); + } + if (cfgEventCutFlags.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("eventQA/eventSel"), kIsGoodZvtxFT0vsPV); + } + if (cfgEventCutFlags.cfgNoCollInTimeRangeStandard) { + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // Rejection of the collisions which have other events nearby + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kNoCollInTimeRangeStandard); + } + + if (cfgEventCutFlags.cfgNoCollInRofStandard) { + if (!collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // Rejection of the collisions which have other events nearby + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kNoCollInRofStandard); + } + + if (cfgEventCutFlags.cfgNoHighMultCollInPrevRof) { + if (!collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // Rejection of the collisions which have other events nearby + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kNoHighMultCollInPrevRof); + } + + if (cfgEventCutFlags.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; + } + registry.fill(HIST("eventQA/eventSel"), kIsVertexITSTPC); + } + + if (cfgEventCutFlags.cfgIsGoodITSLayersAll) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kIsGoodITSLayersAll); + } + + if (cfgEventCutFlags.cfgNoTimeFrameBorder) { + if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kNoTimeFrameBorder); + } + + if (cfgEventCutFlags.cfgNoITSROFrameBorder) { + if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kNoITSROFrameBorder); + } + + float vtxz = -999; + if (collision.numContrib() > 1) { + vtxz = collision.posZ(); + float zRes = std::sqrt(collision.covZZ()); + float minZRes = 0.25; + int minNContrib = 20; + if (zRes > minZRes && collision.numContrib() < minNContrib) + vtxz = -999; + } + auto multNTracksPV = collision.multNTracksPV(); + + if (vtxz > o2::analysis::gfw::vtxZup || vtxz < o2::analysis::gfw::vtxZlow) + return 0; + + 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; + if (multTrk > fMultPVGlobalCutHigh->Eval(collision.multNTracksPV())) + return 0; + registry.fill(HIST("eventQA/eventSel"), kMultCuts); + } + return 1; + } + + // Define the data type + enum DataType { + kReco, + kGen + }; + + int getPIDIndex(const std::string& corrconfig) + { + if (boost::ifind_first(corrconfig, "pi")) + return PidPions; + if (boost::ifind_first(corrconfig, "ka")) + return PidKaons; + if (boost::ifind_first(corrconfig, "pr")) + return PidProtons; + return PidCharged; + } + + GFW::CorrConfig getRelevantCorrName(const int& pidInd) + { + if (pidInd == PidPions) + return fGFW->GetCorrelatorConfig("piP {2} refN {-2}", "PiGap22", kFALSE); + if (pidInd == PidKaons) + return fGFW->GetCorrelatorConfig("kaP {2} refN {-2}", "KaGap22", kFALSE); + if (pidInd == PidProtons) + return fGFW->GetCorrelatorConfig("prP {2} refN {-2}", "PrGap22", kFALSE); + return fGFW->GetCorrelatorConfig("refP {2} refN {-2}", "ChGap22", kFALSE); + } + + template + void fillOutputContainers(const float& centmult, const double& rndm, const int& /*run*/ = 0) + { + for (uint l_ind = 0; l_ind < corrconfigs.size(); ++l_ind) { + if (!corrconfigs.at(l_ind).pTDif) { + auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), 0, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigs.at(l_ind), 0, kFALSE).real() / dnx; + + if (std::abs(val) < 1) { + fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm); + } + continue; + } + + // Fill pt profiles for different particles + int pidInd = getPIDIndex(corrconfigs.at(l_ind).Head.c_str()); + + // Find the corresponding non-pT-differential correlation configuration + GFW::CorrConfig corrName = getRelevantCorrName(pidInd); // May be used later for QA + + auto dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + double ebyeWeight = (cfgUseMultiplicityFlowWeights) ? dnx : 1.0; + for (int i = 1; i <= fSecondAxis->GetNbins(); i++) { + if (corrconfigs.at(l_ind).Head.find("nch") != std::string::npos) { + ebyeWeight = 1.0; + val = 1.0; + } + double ptFraction = 0; + int normIndex = (cfgNormalizeByCharged) ? PidCharged : pidInd; // Configured to normalize by charged particles or the selected particle + if (pidStates.hPtMid[normIndex]->Integral() > 0) { + ptFraction = pidStates.hPtMid[pidInd]->GetBinContent(i) / pidStates.hPtMid[normIndex]->Integral(); + if (std::abs(val) < 1.01) + fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val * ptFraction, ebyeWeight, rndm); + } + } + } + // Fill the profiles for each pT bin + auto dnx = fGFW->Calculate(corrconfigs.at(0), 0, kTRUE).real(); + if (dnx == 0) + return; + auto val = fGFW->Calculate(corrconfigs.at(0), 0, kFALSE).real() / dnx; + for (int i = 1; i <= fSecondAxis->GetNbins(); i++) { + double ptFraction = 0; + if (pidStates.hPtMid[PidCharged]->Integral() > 0) { + ptFraction = pidStates.hPtMid[PidCharged]->GetBinContent(i) / pidStates.hPtMid[PidCharged]->Integral(); + if (std::abs(val) < 1) + registry.fill(HIST("v02pt"), fSecondAxis->GetBinCenter(i), centmult, val * ptFraction, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0); + registry.fill(HIST("nchMid"), fSecondAxis->GetBinCenter(i), centmult, ptFraction); + } + } + return; + } + + struct XAxis { + float centrality; + int64_t multiplicity; + double time; + }; + + struct AcceptedTracks { + int nPos; + int nNeg; + int nFull; + int nMid; + }; + + template + void processCollision(TCollision collision, TTracks tracks, const XAxis& xaxis, const int& run) + { + float vtxz = collision.posZ(); + if (tracks.size() < 1) + return; + if (xaxis.centrality >= 0 && (xaxis.centrality < o2::analysis::gfw::centbinning.front() || xaxis.centrality > o2::analysis::gfw::centbinning.back())) + return; + if (xaxis.multiplicity < cfgFixedMultMin || xaxis.multiplicity > cfgFixedMultMax) + return; + fGFW->Clear(); + pidStates.hPtMid[PidCharged]->Reset(); + pidStates.hPtMid[PidPions]->Reset(); + pidStates.hPtMid[PidKaons]->Reset(); + pidStates.hPtMid[PidProtons]->Reset(); + + float lRandom = fRndm->Rndm(); + + // Loop over tracks and check if they are accepted + AcceptedTracks acceptedTracks{0, 0, 0, 0}; + for (const auto& track : tracks) { + processTrack(track, vtxz, xaxis.multiplicity, run, acceptedTracks); + if (track.eta() > -0.4 && track.eta() < 0.4) + pidStates.hPtMid[PidCharged]->Fill(track.pt(), getEfficiency(track, PidCharged)); + // If PID is identified, fill pt spectrum for the corresponding particle + int pidInd = getNsigmaPID(track); + if (pidInd != -1 && track.eta() > -0.4 && track.eta() < 0.4) { + if (cfgPIDEfficiency) + pidStates.hPtMid[pidInd]->Fill(track.pt(), getEfficiency(track, pidInd)); + else + pidStates.hPtMid[pidInd]->Fill(track.pt(), getEfficiency(track, PidCharged)); // Default to charged particles if PID efficiency is not used + } + } + if (cfgConsistentEventFlag & 1) + if (!acceptedTracks.nPos || !acceptedTracks.nNeg) + return; + if (cfgConsistentEventFlag & 2) + if (acceptedTracks.nFull < 4) // o2-linter: disable=magic-number (at least four tracks in full acceptance) + return; + if (cfgConsistentEventFlag & 4) + if (acceptedTracks.nPos < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in each subevent) + return; + if (cfgConsistentEventFlag & 8) + if (acceptedTracks.nPos < 2 || acceptedTracks.nMid < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in all three subevents) + return; + // Fill output containers + fillOutputContainers
(xaxis.centrality, lRandom, run); + } + + template + void fillAcceptedTracks(TTrack track, AcceptedTracks& acceptedTracks) + { + if (posRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[posRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[posRegionIndex]) + ++acceptedTracks.nPos; + if (negRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[negRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[negRegionIndex]) + ++acceptedTracks.nNeg; + if (fullRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[fullRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[fullRegionIndex]) + ++acceptedTracks.nFull; + if (midRegionIndex >= 0 && track.eta() > o2::analysis::gfw::regions.GetEtaMin()[midRegionIndex] && track.eta() < o2::analysis::gfw::regions.GetEtaMax()[midRegionIndex]) + ++acceptedTracks.nMid; + } + + template + bool trackSelected(TTrack track) + { + if (cfgTrackCuts.cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > fPtDepDCAxy->Eval(track.pt()))) + return false; + return ((track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgNTPCXrows) && (track.tpcNClsFound() >= cfgTrackCuts.cfgNTPCCls) && (track.itsNCls() >= cfgTrackCuts.cfgMinNITSCls)); + } + + template + float getCentrality(TCollision collision) + { + switch (cfgCentEstimator) { + case kCentFT0C: + return cfgCentralityFactor * collision.centFT0C(); + case kCentFT0CVariant1: + return cfgCentralityFactor * collision.centFT0CVariant1(); + case kCentFT0M: + return cfgCentralityFactor * collision.centFT0M(); + case kCentFV0A: + return cfgCentralityFactor * collision.centFV0A(); + case kCentNTPV: + return cfgCentralityFactor * collision.centNTPV(); + case kCentNGlobal: + return cfgCentralityFactor * collision.centNGlobal(); + case kCentMFT: + return cfgCentralityFactor * collision.centMFT(); + default: + return cfgCentralityFactor * collision.centFT0C(); + } + } + + template + inline void processTrack(TTrack const& track, const float& vtxz, const int& multiplicity, const int& /*run*/, AcceptedTracks& acceptedTracks) + { + + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/before/nch_pt"), multiplicity, track.pt()); + } + + if (cfgGetNsigmaQA) + fillPidQA(track, getNsigmaPID(track)); + + if (!trackSelected(track)) + return; + + fillGFW(track, vtxz); // Fill GFW + fillAcceptedTracks(track, acceptedTracks); // Fill accepted tracks + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/after/nch_pt"), multiplicity, track.pt()); + } + + if (cfgGetNsigmaQA) + fillPidQA(track, getNsigmaPID(track)); + } + + template + inline void fillGFW(TTrack track, const double& vtxz) + { + int pidInd = getNsigmaPID(track); + + bool withinPtRef = (track.pt() > o2::analysis::gfw::ptreflow && track.pt() < o2::analysis::gfw::ptrefup); + bool withinPtPOI = (track.pt() > o2::analysis::gfw::ptpoilow && track.pt() < o2::analysis::gfw::ptpoiup); + + if (!withinPtPOI && !withinPtRef) + return; + double weff = getEfficiency(track, PidCharged); + if (weff < 0) + return; + + double wacc = getAcceptance(track, vtxz); + + // Fill cumulants for different particles + // ***Need to add proper weights for each particle!*** + if (withinPtRef) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 1); + if (withinPtPOI && pidInd == PidPions) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, PidPions + 1); + if (withinPtPOI && pidInd == PidKaons) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, PidKaons + 1); + if (withinPtPOI && pidInd == PidProtons) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, PidProtons + 1); + return; + } + + template + inline void fillPidQA(TTrack track, const int& pid) + { + // Fill Nsigma QA + if (!cfgUseItsPID) { + if (ft == kBefore) { + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TofTpcNsigma_pions"), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + if (cfgGetdEdx) { + double tpcExpSignalPi = track.tpcSignal() - (track.tpcNSigmaPi() * track.tpcExpSigmaPi()); + + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TpcdEdx_ptwise_pions"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpTpcdEdx_ptwise_pions"), track.pt(), tpcExpSignalPi, track.tofNSigmaPi()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpSigma_ptwise_pions"), track.pt(), track.tpcExpSigmaPi(), track.tofNSigmaPi()); + } + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TofTpcNsigma_kaons"), track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + if (cfgGetdEdx) { + double tpcExpSignalKa = track.tpcSignal() - (track.tpcNSigmaKa() * track.tpcExpSigmaKa()); + + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TpcdEdx_ptwise_kaons"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpTpcdEdx_ptwise_kaons"), track.pt(), tpcExpSignalKa, track.tofNSigmaKa()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpSigma_ptwise_kaons"), track.pt(), track.tpcExpSigmaKa(), track.tofNSigmaKa()); + } + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TofTpcNsigma_protons"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + if (cfgGetdEdx) { + double tpcExpSignalPr = track.tpcSignal() - (track.tpcNSigmaPr() * track.tpcExpSigmaPr()); + + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TpcdEdx_ptwise_protons"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpTpcdEdx_ptwise_protons"), track.pt(), tpcExpSignalPr, track.tofNSigmaPr()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpSigma_ptwise_protons"), track.pt(), track.tpcExpSigmaPr(), track.tofNSigmaPr()); + } + } else if (ft == kAfter) { + if (pid == PidPions) { + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TofTpcNsigma_pions"), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + if (cfgGetdEdx) { + double tpcExpSignalPi = track.tpcSignal() - (track.tpcNSigmaPi() * track.tpcExpSigmaPi()); + + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TpcdEdx_ptwise_pions"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpTpcdEdx_ptwise_pions"), track.pt(), tpcExpSignalPi, track.tofNSigmaPi()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpSigma_ptwise_pions"), track.pt(), track.tpcExpSigmaPi(), track.tofNSigmaPi()); + } + } + if (pid == PidKaons) { + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TofTpcNsigma_kaons"), track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + if (cfgGetdEdx) { + double tpcExpSignalKa = track.tpcSignal() - (track.tpcNSigmaKa() * track.tpcExpSigmaKa()); + + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TpcdEdx_ptwise_kaons"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpTpcdEdx_ptwise_kaons"), track.pt(), tpcExpSignalKa, track.tofNSigmaKa()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpSigma_ptwise_kaons"), track.pt(), track.tpcExpSigmaKa(), track.tofNSigmaKa()); + } + } + if (pid == PidProtons) { + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TofTpcNsigma_protons"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + if (cfgGetdEdx) { + double tpcExpSignalPr = track.tpcSignal() - (track.tpcNSigmaPr() * track.tpcExpSigmaPr()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("TpcdEdx_ptwise_protons"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpTpcdEdx_ptwise_protons"), track.pt(), tpcExpSignalPr, track.tofNSigmaPr()); + registry.fill(HIST("QA_PID/") + HIST(FillTimeName[ft]) + HIST("ExpSigma_ptwise_protons"), track.pt(), track.tpcExpSigmaPr(), track.tofNSigmaPr()); + } + } + } + } + } + + template + inline void fillTrackQA(TTrack track, const float vtxz) + { + double wacc = getAcceptance(track, vtxz); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("phi_eta_vtxZ"), track.phi(), track.eta(), vtxz, (ft == kAfter) ? wacc : 1.0); + + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_dcaXY_dcaZ"), track.pt(), track.dcaXY(), track.dcaZ()); + + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("chi2prTPCcls"), track.tpcChi2NCl()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("chi2prITScls"), track.itsChi2NCl()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nTPCClusters"), track.tpcNClsFound()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nITSClusters"), track.itsNCls()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nTPCCrossedRows"), track.tpcNClsCrossedRows()); + + if (ft == kAfter) { + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_ref"), track.pt()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_poi"), track.pt()); + } + return; + } + template + inline void fillEventQA(TCollision collision, XAxis xaxis) + { + if constexpr (framework::has_type_v) { + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_centT0C"), collision.centFT0C(), xaxis.multiplicity); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("centT0M_centT0C"), collision.centFT0C(), collision.centFT0M()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("centV0A_centT0C"), collision.centFT0C(), collision.centFV0A()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("centGlobal_centT0C"), collision.centFT0C(), collision.centNGlobal()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("centNTPV_centT0C"), collision.centFT0C(), collision.centNTPV()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("centMFT_centT0C"), collision.centFT0C(), collision.centMFT()); + } + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_PVTracks"), collision.multNTracksPV(), xaxis.multiplicity); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_multT0A"), collision.multFT0A(), xaxis.multiplicity); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_multV0A"), collision.multFV0A(), xaxis.multiplicity); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); + return; + } + + double getTimeSinceStartOfFill(uint64_t, int) { return 0.0; } + + void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + LOGF(info, "run = %d", run); + } + loadCorrections(bc); + + registry.fill(HIST("eventQA/eventSel"), kFilteredEvent); + if (!collision.sel8()) + return; + registry.fill(HIST("eventQA/eventSel"), kSel8); + registry.fill(HIST("eventQA/eventSel"), kOccupancy); // Add occupancy selection later + + const XAxis xaxis{getCentrality(collision), tracks.size(), -1.0}; + if (cfgFillQA) { + fillEventQA(collision, xaxis); + registry.fill(HIST("eventQA/before/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/before/multiplicity"), xaxis.multiplicity); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision, xaxis.multiplicity, xaxis.centrality)) + return; + if (cfgFillQA) + fillEventQA(collision, xaxis); + + registry.fill(HIST("eventQA/after/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/after/multiplicity"), xaxis.multiplicity); + processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwV02, processData, "Process analysis for non-derived data", true); + + void processCFDerived(aod::CFCollision const& collision, soa::Filtered const& tracks) + { + int run = collision.runNumber(); + if (run != lastRun) { + lastRun = run; + LOGF(info, "run = %d", run); + } + loadCorrections(run); + const XAxis xaxis{collision.multiplicity(), tracks.size(), -1.0}; + + registry.fill(HIST("eventQA/after/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/after/multiplicity"), xaxis.multiplicity); + + // processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwV02, processCFDerived, "Process analysis for CF derived data", false); + void processCFDerivedCorrected(aod::CFCollision const& collision, soa::Filtered> const& tracks) + { + int run = collision.runNumber(); + if (run != lastRun) { + lastRun = run; + LOGF(info, "run = %d", run); + } + const XAxis xaxis{collision.multiplicity(), tracks.size(), -1.0}; + registry.fill(HIST("eventQA/after/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/after/multiplicity"), xaxis.multiplicity); + // processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwV02, processCFDerivedCorrected, "Process analysis for CF derived data with corrections", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGCF/JCorran/Core/FlowJHistManager.h b/PWGCF/JCorran/Core/FlowJHistManager.h index fa3984b499f..3d70dd15ebc 100644 --- a/PWGCF/JCorran/Core/FlowJHistManager.h +++ b/PWGCF/JCorran/Core/FlowJHistManager.h @@ -239,7 +239,7 @@ class FlowJHistManager if (mode == 1) { // 'Weight' distributions are defined only for After/. mHistRegistryQA->fill(HIST(MCentClasses[cBin]) + HIST("After/histPtCorrected"), - track.pt(), 1. / weightNUE); + track.pt(), weightNUE); // extractEfficiency() from processMCEfficiency of correlations.cxx gives 1/eff mHistRegistryQA->fill(HIST(MCentClasses[cBin]) + HIST("After/histPhiCorrected"), track.phi(), 1. / weightNUA); diff --git a/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx b/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx index 111e1f8e92b..380de913181 100644 --- a/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/flowJSPCAnalysis.cxx @@ -8,15 +8,19 @@ // 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 the calculation of SPC with filtered data. -// \author Maxim Virta (maxim.virta@cern.ch), Cindy Mordasini (cindy.mordasini@cern.ch) +/// +/// \file flowJSPCAnalysis.cxx +/// \brief Task for the calculation of SPC with filtered data. +/// \author Maxim Virta (maxim.virta@cern.ch), Cindy Mordasini (cindy.mordasini@cern.ch), Neelkamal Mallick (neelkamal.mallick@cern.ch) // Standard headers. +#include +#include + #include +#include #include #include -#include // O2 headers. // // The first two are mandatory. @@ -46,6 +50,8 @@ 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}; + using MyCollisions = soa::Join().weightNUA()); template using HasWeightEff = decltype(std::declval().weightEff()); + template + using HasTrackType = decltype(std::declval().trackType()); HistogramRegistry qaHistRegistry{"qaHistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; FlowJHistManager histManager; @@ -84,12 +92,20 @@ struct flowJSPCAnalysis { Configurable cfgMultMin{"cfgMultMin", 10, "Minimum number of particles required for the event to have."}; } cfgEventCuts; + O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 0, "Track selection bitmask to use as defined in the filterCorrelations.cxx task"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") + O2_DEFINE_CONFIGURABLE(cfgMultCutFormula, std::string, "", "Multiplicity correlations cut formula. A result greater than zero results in accepted event. Parameters: [cFT0C] FT0C centrality, [mFV0A] V0A multiplicity, [mGlob] global track multiplicity, [mPV] PV track multiplicity, [cFT0M] FT0M centrality") + // // Filters to be applied to the received data. // // The analysis assumes the data has been subjected to a QA of its selection, // // and thus only the final distributions of the data for analysis are saved. Filter collFilter = (nabs(aod::collision::posZ) < cfgEventCuts.cfgZvtxMax); + Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (aod::track::pt < cfgTrackCuts.cfgPtMax) && (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax); - Filter cftrackFilter = (aod::cftrack::pt > cfgTrackCuts.cfgPtMin) && (aod::cftrack::pt < cfgTrackCuts.cfgPtMax); // eta cuts done by jfluc + Filter cftrackFilter = (nabs(aod::cftrack::eta) < cfgTrackCuts.cfgEtaMax) && (aod::cftrack::pt > cfgTrackCuts.cfgPtMin) && (aod::cftrack::pt < cfgTrackCuts.cfgPtMax) && ncheckbit(aod::track::trackType, as(cfgTrackBitMask)); + + std::unique_ptr multCutFormula; + std::array multCutFormulaParamIndex; void init(InitContext const&) { @@ -103,6 +119,26 @@ struct flowJSPCAnalysis { histManager.setHistRegistryQA(&qaHistRegistry); histManager.setDebugLog(false); histManager.createHistQA(); + + if (!cfgMultCutFormula.value.empty()) { + multCutFormula = std::make_unique("multCutFormula", cfgMultCutFormula.value.c_str()); + std::fill_n(multCutFormulaParamIndex.begin(), std::size(multCutFormulaParamIndex), ~0u); + std::array pars = {"cFT0C", "mFV0A", "mPV", "mGlob", "cFT0M"}; // must correspond the order of MultiplicityEstimators + for (uint i = 0, n = multCutFormula->GetNpar(); i < n; ++i) { + auto m = std::find(pars.begin(), pars.end(), multCutFormula->GetParName(i)); + if (m == pars.end()) { + LOGF(warning, "Unknown parameter in cfgMultCutFormula: %s", multCutFormula->GetParName(i)); + continue; + } + const uint estIdx = std::distance(pars.begin(), m); + if ((cfgMultCorrelationsMask.value & (1u << estIdx)) == 0) { + LOGF(warning, "The centrality/multiplicity estimator %s is not available to be used in cfgMultCutFormula. Ensure cfgMultCorrelationsMask is correct and matches the CFMultSets in derived data.", m->c_str()); + } else { + multCutFormulaParamIndex[estIdx] = i; + LOGF(info, "Multiplicity cut parameter %s in use.", m->c_str()); + } + } + } } template @@ -119,6 +155,7 @@ struct flowJSPCAnalysis { int cBin = histManager.getCentBin(cent); spcHistograms.fill(HIST("FullCentrality"), cent); int nTracks = tracks.size(); + double wNUA = 1.0; double wEff = 1.0; for (const auto& track : tracks) { @@ -135,6 +172,11 @@ struct flowJSPCAnalysis { if constexpr (std::experimental::is_detected::value) { spcAnalysis.fillQAHistograms(cBin, track.phi(), 1. / track.weightNUA()); } + if constexpr (std::experimental::is_detected::value) { + if (track.trackType() != cfgTrackBitMask.value) { + LOGF(warning, "trackType %d (expected %d) is passed to the analysis", track.trackType(), cfgTrackBitMask.value); + } + } } } @@ -146,6 +188,20 @@ struct flowJSPCAnalysis { spcAnalysis.calculateCorrelators(cBin); } + template + bool passOutlier(CollType const& collision) + { + if (cfgMultCutFormula.value.empty()) + return true; + for (uint i = 0; i < aod::cfmultset::NMultiplicityEstimators; ++i) { + if ((cfgMultCorrelationsMask.value & (1u << i)) == 0 || multCutFormulaParamIndex[i] == ~0u) + continue; + auto estIndex = std::popcount(static_cast(cfgMultCorrelationsMask.value & ((1u << i) - 1))); + multCutFormula->SetParameter(multCutFormulaParamIndex[i], collision.multiplicities()[estIndex]); + } + return multCutFormula->Eval() > 0.0f; + } + void processJDerived(aod::JCollision const& collision, soa::Filtered const& tracks) { analyze(collision, tracks); @@ -164,11 +220,21 @@ struct flowJSPCAnalysis { } PROCESS_SWITCH(flowJSPCAnalysis, processCFDerived, "Process CF derived data", false); - void processCFDerivedCorrected(aod::CFCollision const& collision, soa::Filtered> const& tracks) + void processCFDerivedCorrected(soa::Filtered::iterator const& collision, soa::Filtered> const& tracks) { analyze(collision, tracks); } PROCESS_SWITCH(flowJSPCAnalysis, processCFDerivedCorrected, "Process CF derived data with corrections", true); + + void processCFDerivedMultSetCorrected(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) + { + if (std::popcount(static_cast(cfgMultCorrelationsMask.value)) != static_cast(collision.multiplicities().size())) + LOGF(fatal, "Multiplicity selections (cfgMultCorrelationsMask = 0x%x) do not match the size of the table column (%ld).", cfgMultCorrelationsMask.value, collision.multiplicities().size()); + if (!passOutlier(collision)) + return; + analyze(collision, tracks); + } + PROCESS_SWITCH(flowJSPCAnalysis, processCFDerivedMultSetCorrected, "Process CF derived data with corrections and multiplicity sets", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx index 452ddd72abb..5a85b8eb58e 100644 --- a/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx +++ b/PWGCF/JCorran/Tasks/jEPFlowAnalysis.cxx @@ -18,6 +18,7 @@ #include "Common/Core/EventPlaneHelper.h" #include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -29,6 +30,8 @@ #include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" +#include + #include #include @@ -38,8 +41,9 @@ using namespace o2::framework::expressions; using namespace std; using MyCollisions = soa::Join; -using MyCollisionsWithSC = soa::Join; -using MyTracks = aod::Tracks; +using MyTracks = soa::Join; +using MyCollisionsMC = soa::Join; +using MyTracksMC = soa::Join; struct jEPFlowAnalysis { @@ -50,9 +54,17 @@ struct jEPFlowAnalysis { Service ccdb; o2::ccdb::CcdbApi ccdbApi; + 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; + // Set Configurables here struct : ConfigurableGroup { - Configurable cfgPtMin{"cfgPtMin", 0.2f, "Minimum pT used for track selection."}; + Configurable cfgPtMin{"cfgPtMin", 0.2f, "Minimum pT used for track seletion."}; Configurable cfgEtaMax{"cfgEtaMax", 1.f, "Maximum eta used for track selection."}; } cfgTrackCuts; @@ -61,10 +73,23 @@ struct jEPFlowAnalysis { 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"}; + Configurable cfgEffCor{"cfgEffCor", false, "flag for efficiency correction"}; + Configurable cfgEffCorDir{"cfgEffCorDir", "Users/n/nmallick/Run3OO/Eff/LHC25h3b_FT0C", "path for efficiency correction"}; + + Configurable cfgTrkSelFlag{"cfgTrkSelFlag", true, "flag for track selection"}; + Configurable cfgSystStudy{"cfgSystStudy", false, "flag for syst study"}; + Configurable cfgITSNCls{"cfgITSNCls", 5, "minimum number of its clusters"}; + Configurable cfgTPCNclsCR{"cfgTPCNclsCR", 70, "minimum number of tpc cluster crossed rows"}; + Configurable cfgTPCChi2{"cfgTPCChi2", 4.0, "maximum TPC chi2"}; + Configurable cfgITSChi2{"cfgITSChi2", 36.0, "maximum ITS chi2"}; + Configurable cfgdcaZ{"cfgdcaZ", 2.0, "maximum dca z"}; + Configurable cfgdcaXY0{"cfgdcaXY0", 0.0105, "maximum constant dca xy"}; + Configurable cfgdcaXY1{"cfgdcaXY1", 0.035, "maximum pt deepdent dca xy"}; + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "Total number of detectors in qVectorsTable"}; Configurable cfgnMode{"cfgnMode", 1, "the number of modulations"}; - Configurable cfgShiftCorr{"cfgShiftCorr", false, "additional shift correction"}; + Configurable cfgManShiftCorr{"cfgManShiftCorr", false, "additional shift correction"}; Configurable cfgShiftPath{"cfgShiftPath", "Users/j/junlee/Qvector/QvecCalib/Shift", "Path for Shift"}; Configurable cfgVertexZ{"cfgVertexZ", 10.0, "Maximum vertex Z selection"}; @@ -77,6 +102,12 @@ struct jEPFlowAnalysis { ConfigurableAxis cfgAxisCos{"cfgAxisCos", {102, -1.02, 1.02}, ""}; ConfigurableAxis cfgAxisQvec{"cfgAxisQvec", {200, -5.0, 5.0}, ""}; + ConfigurableAxis cfgAxisCentMC{"cfgAxisCentMC", {5, 0, 100}, ""}; + ConfigurableAxis cfgAxisVtxZMC{"cfgAxisVtxZMC", {20, -10, 10}, ""}; + ConfigurableAxis cfgAxisEtaMC{"cfgAxisEtaMC", {20, -1, 1}, ""}; + ConfigurableAxis cfgAxisPhiMC{"cfgAxisPhiMC", {36, 0, constants::math::PI * 2.0}, ""}; + ConfigurableAxis cfgAxisPtMC{"cfgAxisPtMC", {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.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 12.0, 15.0, 30.0, 50.0, 70.0, 100.0}, ""}; + Filter trackFilter = (aod::track::pt > cfgTrackCuts.cfgPtMin) && (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaMax); int detId; @@ -87,9 +118,13 @@ struct jEPFlowAnalysis { int currentRunNumber = -999; int lastRunNumber = -999; + float cent; + std::vector shiftprofile{}; std::string fullCCDBShiftCorrPath; + THn* effMap = nullptr; + template int getdetId(const T& name) { @@ -112,8 +147,176 @@ struct jEPFlowAnalysis { } } + template + bool eventSel(const Col& coll) + { + if (std::abs(coll.posZ()) > cfgVertexZ) + return false; + switch (cfgEvtSel) { + case 0: // Sel8 + if (!coll.sel8()) + return false; + break; + case 1: // PbPb standard + if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + break; + case 2: // PbPb with pileup + if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || + !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + break; + case 3: // Small systems (OO, NeNe, pp) + if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + break; + } + // Check occupancy + if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) + return false; + + return true; + } + + template + uint8_t trackSel(const Trk& track) + { + uint8_t tracksel = 0; + if (!track.isGlobalTrack()) { + tracksel += 1; + } + if (track.itsNCls() <= cfgITSNCls && cfgSystStudy) { + tracksel += 2; + } + if (track.tpcNClsCrossedRows() <= cfgTPCNclsCR && cfgSystStudy) { + tracksel += 4; + } + if (track.tpcChi2NCl() >= cfgTPCChi2 && cfgSystStudy) { + tracksel += 8; + } + if (track.itsChi2NCl() >= cfgITSChi2 && cfgSystStudy) { + tracksel += 16; + } + if (std::abs(track.dcaZ()) >= cfgdcaZ && cfgSystStudy) { + tracksel += 32; + } + if (std::abs(track.dcaXY()) >= cfgdcaXY0 + cfgdcaXY1 / std::pow(track.pt(), 1.1) && cfgSystStudy) { + tracksel += 64; + } + + return tracksel; + } + + template + void fillvn(const Col& coll, const Trk& tracks) + { + float eps[3] = {0.}; + float qx_shifted[3] = {0.}; + float qy_shifted[3] = {0.}; + + for (int i = 0; i < cfgnMode; i++) { // loop over different harmonic orders + harmInd = cfgnTotalSystem * 4 * (i) + 3; // harmonic index to access corresponding Q-vector as all Q-vectors are in same vector + eps[0] = helperEP.GetEventPlane(coll.qvecRe()[4 * detId + harmInd], coll.qvecIm()[4 * detId + harmInd], i + 2); + eps[1] = helperEP.GetEventPlane(coll.qvecRe()[4 * refAId + harmInd], coll.qvecIm()[4 * refAId + harmInd], i + 2); + eps[2] = helperEP.GetEventPlane(coll.qvecRe()[4 * refBId + harmInd], coll.qvecIm()[4 * refBId + harmInd], i + 2); + + auto deltapsiDet = 0.0; + auto deltapsiRefA = 0.0; + auto deltapsiRefB = 0.0; + + float weight = 1.0; + + qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd]; + qy_shifted[0] = coll.qvecIm()[4 * detId + harmInd]; + qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd]; + qy_shifted[1] = coll.qvecIm()[4 * refAId + harmInd]; + qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd]; + qy_shifted[2] = coll.qvecIm()[4 * refBId + harmInd]; + + if (cfgManShiftCorr) { + constexpr int kShiftBins = 10; + for (int ishift = 1; ishift <= kShiftBins; ishift++) { + auto coeffshiftxDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 0.5, ishift - 0.5)); + auto coeffshiftyDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 1.5, ishift - 0.5)); + auto coeffshiftxRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 0.5, ishift - 0.5)); + auto coeffshiftyRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 1.5, ishift - 0.5)); + auto coeffshiftxRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 0.5, ishift - 0.5)); + auto coeffshiftyRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 1.5, ishift - 0.5)); + + deltapsiDet += ((2. / (1.0 * ishift)) * (-coeffshiftxDet * std::cos(ishift * static_cast(i + 2) * eps[0]) + coeffshiftyDet * std::sin(ishift * static_cast(i + 2) * eps[0]))) / static_cast(i + 2); + deltapsiRefA += ((2. / (1.0 * ishift)) * (-coeffshiftxRefA * std::cos(ishift * static_cast(i + 2) * eps[1]) + coeffshiftyRefA * std::sin(ishift * static_cast(i + 2) * eps[1]))) / static_cast(i + 2); + deltapsiRefB += ((2. / (1.0 * ishift)) * (-coeffshiftxRefB * std::cos(ishift * static_cast(i + 2) * eps[2]) + coeffshiftyRefB * std::sin(ishift * static_cast(i + 2) * eps[2]))) / static_cast(i + 2); + } + + eps[0] += deltapsiDet; + eps[1] += deltapsiRefA; + eps[2] += deltapsiRefB; + + qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::cos(deltapsiDet) - coll.qvecIm()[4 * detId + harmInd] * std::sin(deltapsiDet); + qy_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::sin(deltapsiDet) + coll.qvecIm()[4 * detId + harmInd] * std::cos(deltapsiDet); + qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::cos(deltapsiRefA) - coll.qvecIm()[4 * refAId + harmInd] * std::sin(deltapsiRefA); + qy_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::sin(deltapsiRefA) + coll.qvecIm()[4 * refAId + harmInd] * std::cos(deltapsiRefA); + qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::cos(deltapsiRefB) - coll.qvecIm()[4 * refBId + harmInd] * std::sin(deltapsiRefB); + qy_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::sin(deltapsiRefB) + coll.qvecIm()[4 * refBId + harmInd] * std::cos(deltapsiRefB); + } + float resNumA = helperEP.GetResolution(eps[0], eps[1], i + 2); + float resNumB = helperEP.GetResolution(eps[0], eps[2], i + 2); + float resDenom = helperEP.GetResolution(eps[1], eps[2], i + 2); + + epFlowHistograms.fill(HIST("EpDet"), i + 2, cent, eps[0]); + epFlowHistograms.fill(HIST("EpRefA"), i + 2, cent, eps[1]); + epFlowHistograms.fill(HIST("EpRefB"), i + 2, cent, eps[2]); + + epFlowHistograms.fill(HIST("EpResDetRefA"), i + 2, cent, resNumA); + epFlowHistograms.fill(HIST("EpResDetRefB"), i + 2, cent, resNumB); + epFlowHistograms.fill(HIST("EpResRefARefB"), i + 2, cent, resDenom); + + epFlowHistograms.fill(HIST("EpResQvecDetRefAxx"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); + epFlowHistograms.fill(HIST("EpResQvecDetRefAxy"), i + 2, cent, qx_shifted[1] * qy_shifted[0] - qx_shifted[0] * qy_shifted[1]); + epFlowHistograms.fill(HIST("EpResQvecDetRefBxx"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecDetRefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[0] - qx_shifted[0] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecRefARefBxx"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); + epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[1] - qx_shifted[1] * qy_shifted[2]); + + for (const auto& track : tracks) { + if (cfgTrkSelFlag && trackSel(track)) + continue; + + if (cfgEffCor) { + weight = getEfficiencyCorrection(effMap, track.eta(), track.pt(), cent, coll.posZ()); + } + + float vn = std::cos((i + 2) * (track.phi() - eps[0])); + float vnSin = std::sin((i + 2) * (track.phi() - eps[0])); + + epFlowHistograms.fill(HIST("vncos"), i + 2, cent, track.pt(), vn, weight); + epFlowHistograms.fill(HIST("vnsin"), i + 2, cent, track.pt(), vnSin, weight); + + epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]), weight); + } + } + } + + double getEfficiencyCorrection(THn* eff, float eta, float pt, float multiplicity, float posZ) + { + int effVars[4]; + effVars[0] = eff->GetAxis(0)->FindBin(eta); + effVars[1] = eff->GetAxis(1)->FindBin(pt); + effVars[2] = eff->GetAxis(2)->FindBin(multiplicity); + effVars[3] = eff->GetAxis(3)->FindBin(posZ); + + return eff->GetBinContent(effVars); + } + void init(InitContext const&) { + 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()); + detId = getdetId(cfgDetName); refAId = getdetId(cfgRefAName); refBId = getdetId(cfgRefBName); @@ -127,6 +330,12 @@ struct jEPFlowAnalysis { AxisSpec axisCos{cfgAxisCos, "cos"}; AxisSpec axisQvec{cfgAxisQvec, "Qvec"}; + AxisSpec axisCentMC{cfgAxisCentMC, "cent"}; + AxisSpec axisVtxZMC{cfgAxisVtxZMC, "vtxz"}; + AxisSpec axisEtaMC{cfgAxisEtaMC, "eta"}; + AxisSpec axisPhiMC{cfgAxisPhiMC, "phi"}; + AxisSpec axisPtMC{cfgAxisPtMC, "pt"}; + epFlowHistograms.add("EpDet", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); epFlowHistograms.add("EpRefA", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); epFlowHistograms.add("EpRefB", "", {HistType::kTH3F, {axisMod, axisCent, axisEvtPl}}); @@ -150,127 +359,33 @@ struct jEPFlowAnalysis { epFlowHistograms.add("hCentrality", "", {HistType::kTH1F, {axisCent}}); epFlowHistograms.add("hVertex", "", {HistType::kTH1F, {axisVertex}}); - } - - void processWithSC(MyCollisionsWithSC::iterator const& coll, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) - { - if (cfgAddEvtSel) { - if (std::abs(coll.posZ()) > cfgVertexZ) - return; - switch (cfgEvtSel) { - case 0: // Sel8 - if (!coll.sel8()) - return; - break; - case 1: // PbPb standard - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 2: // PbPb with pileup - if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || - !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 3: // Small systems (OO, NeNe, pp) - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - default: - LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); - } - // Check occupancy - if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) - return; - } - float cent = coll.cent(); - epFlowHistograms.fill(HIST("hCentrality"), cent); - epFlowHistograms.fill(HIST("hVertex"), coll.posZ()); - float eps[3] = {0.}; - - if (coll.qvecAmp()[detId] < 1e-5 || coll.qvecAmp()[refAId] < 1e-5 || coll.qvecAmp()[refBId] < 1e-5) - return; - - for (int i = 0; i < cfgnMode; i++) { // loop over different harmonic orders - harmInd = cfgnTotalSystem * i; // harmonic index to access corresponding Q-vector as all Q-vectors are in same vector - eps[0] = helperEP.GetEventPlane(coll.qvecShiftedRe()[detId + harmInd], coll.qvecShiftedIm()[detId + harmInd], i + 2); - eps[1] = helperEP.GetEventPlane(coll.qvecShiftedRe()[refAId + harmInd], coll.qvecShiftedIm()[refAId + harmInd], i + 2); - eps[2] = helperEP.GetEventPlane(coll.qvecShiftedRe()[refBId + harmInd], coll.qvecShiftedIm()[refBId + harmInd], i + 2); - - float resNumA = helperEP.GetResolution(eps[0], eps[1], i + 2); - float resNumB = helperEP.GetResolution(eps[0], eps[2], i + 2); - float resDenom = helperEP.GetResolution(eps[1], eps[2], i + 2); - - epFlowHistograms.fill(HIST("EpDet"), i + 2, cent, eps[0]); - epFlowHistograms.fill(HIST("EpRefA"), i + 2, cent, eps[1]); - epFlowHistograms.fill(HIST("EpRefB"), i + 2, cent, eps[2]); - - epFlowHistograms.fill(HIST("EpResDetRefA"), i + 2, cent, resNumA); - epFlowHistograms.fill(HIST("EpResDetRefB"), i + 2, cent, resNumB); - epFlowHistograms.fill(HIST("EpResRefARefB"), i + 2, cent, resDenom); - - epFlowHistograms.fill(HIST("EpResQvecDetRefAxx"), i + 2, cent, coll.qvecShiftedRe()[detId + harmInd] * coll.qvecShiftedRe()[refAId + harmInd] + coll.qvecShiftedIm()[detId + harmInd] * coll.qvecShiftedIm()[refAId + harmInd]); - epFlowHistograms.fill(HIST("EpResQvecDetRefAxy"), i + 2, cent, coll.qvecShiftedRe()[refAId + harmInd] * coll.qvecShiftedIm()[detId + harmInd] - coll.qvecShiftedRe()[detId + harmInd] * coll.qvecShiftedIm()[refAId + harmInd]); - epFlowHistograms.fill(HIST("EpResQvecDetRefBxx"), i + 2, cent, coll.qvecShiftedRe()[detId + harmInd] * coll.qvecShiftedRe()[refBId + harmInd] + coll.qvecShiftedIm()[detId + harmInd] * coll.qvecShiftedIm()[refBId + harmInd]); - epFlowHistograms.fill(HIST("EpResQvecDetRefBxy"), i + 2, cent, coll.qvecShiftedRe()[refBId + harmInd] * coll.qvecShiftedIm()[detId + harmInd] - coll.qvecShiftedRe()[detId + harmInd] * coll.qvecShiftedIm()[refBId + harmInd]); - epFlowHistograms.fill(HIST("EpResQvecRefARefBxx"), i + 2, cent, coll.qvecShiftedRe()[refAId + harmInd] * coll.qvecShiftedRe()[refBId + harmInd] + coll.qvecShiftedIm()[refAId + harmInd] * coll.qvecShiftedIm()[refBId + harmInd]); - epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, coll.qvecShiftedRe()[refBId + harmInd] * coll.qvecShiftedIm()[refAId + harmInd] - coll.qvecShiftedRe()[refAId + harmInd] * coll.qvecShiftedIm()[refBId + harmInd]); - - float weight = 1.0; - - for (const auto& track : tracks) { - float vn = std::cos((i + 2) * (track.phi() - eps[0])); - float vnSin = std::sin((i + 2) * (track.phi() - eps[0])); - - epFlowHistograms.fill(HIST("vncos"), i + 2, cent, track.pt(), vn * weight); - epFlowHistograms.fill(HIST("vnsin"), i + 2, cent, track.pt(), vnSin * weight); - - epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), (std::cos(track.phi() * static_cast(i + 2)) * coll.qvecShiftedRe()[detId + harmInd] + std::sin(track.phi() * static_cast(i + 2)) * coll.qvecShiftedIm()[detId + harmInd]) * weight); - epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), (std::sin(track.phi() * static_cast(i + 2)) * coll.qvecShiftedRe()[detId + harmInd] - std::cos(track.phi() * static_cast(i + 2)) * coll.qvecShiftedIm()[detId + harmInd]) * weight); - } - } + epFlowHistograms.add("MC/hPartGen", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); + epFlowHistograms.add("MC/hPartRecPr", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); + epFlowHistograms.add("MC/hPartRec", "", {kTHnSparseF, {cfgAxisCentMC, cfgAxisVtxZMC, cfgAxisEtaMC, cfgAxisPhiMC, cfgAxisPtMC}}); } - PROCESS_SWITCH(jEPFlowAnalysis, processWithSC, "process with shift-corrected qvectors", false); void processDefault(MyCollisions::iterator const& coll, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) { if (cfgAddEvtSel) { - if (std::abs(coll.posZ()) > cfgVertexZ) + if (!eventSel(coll)) return; - switch (cfgEvtSel) { - case 0: // Sel8 - if (!coll.sel8()) - return; - break; - case 1: // PbPb standard - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 2: // PbPb with pileup - if (!coll.sel8() || !coll.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) || - !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - case 3: // Small systems (OO, NeNe, pp) - if (!coll.sel8() || !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - break; - default: - LOGF(warning, "Event selection flag was not found, continuing without basic event selections!\n"); + } + + if (cfgEffCor) { + auto bc = coll.bc_as(); + currentRunNumber = bc.runNumber(); + if (currentRunNumber != lastRunNumber) { + effMap = ccdb->getForTimeStamp>(cfgEffCorDir, bc.timestamp()); + lastRunNumber = currentRunNumber; } - // Check occupancy - if (coll.trackOccupancyInTimeRange() > cfgMaxOccupancy || coll.trackOccupancyInTimeRange() < cfgMinOccupancy) - return; } - float cent = coll.cent(); + cent = coll.cent(); epFlowHistograms.fill(HIST("hCentrality"), cent); epFlowHistograms.fill(HIST("hVertex"), coll.posZ()); - float eps[3] = {0.}; - float qx_shifted[3] = {0.}; - float qy_shifted[3] = {0.}; - if (cfgShiftCorr) { + if (cfgManShiftCorr) { auto bc = coll.bc_as(); currentRunNumber = bc.runNumber(); if (currentRunNumber != lastRunNumber) { @@ -289,77 +404,82 @@ struct jEPFlowAnalysis { if (coll.qvecAmp()[detId] < 1e-5 || coll.qvecAmp()[refAId] < 1e-5 || coll.qvecAmp()[refBId] < 1e-5) return; - for (int i = 0; i < cfgnMode; i++) { // loop over different harmonic orders - harmInd = cfgnTotalSystem * 4 * (i) + 3; // harmonic index to access corresponding Q-vector as all Q-vectors are in same vector - eps[0] = helperEP.GetEventPlane(coll.qvecRe()[4 * detId + harmInd], coll.qvecIm()[4 * detId + harmInd], i + 2); - eps[1] = helperEP.GetEventPlane(coll.qvecRe()[4 * refAId + harmInd], coll.qvecIm()[4 * refAId + harmInd], i + 2); - eps[2] = helperEP.GetEventPlane(coll.qvecRe()[4 * refBId + harmInd], coll.qvecIm()[4 * refBId + harmInd], i + 2); - - auto deltapsiDet = 0.0; - auto deltapsiRefA = 0.0; - auto deltapsiRefB = 0.0; + fillvn(coll, tracks); + } + PROCESS_SWITCH(jEPFlowAnalysis, processDefault, "default process", true); - float weight = 1.0; + void processMCRec(MyCollisionsMC::iterator const& coll, MyTracksMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) + { + if (!coll.has_mcCollision()) { + return; + } - if (cfgShiftCorr) { - constexpr int kShiftBins = 10; - for (int ishift = 1; ishift <= kShiftBins; ishift++) { - auto coeffshiftxDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 0.5, ishift - 0.5)); - auto coeffshiftyDet = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * detId + 1.5, ishift - 0.5)); - auto coeffshiftxRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 0.5, ishift - 0.5)); - auto coeffshiftyRefA = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refAId + 1.5, ishift - 0.5)); - auto coeffshiftxRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 0.5, ishift - 0.5)); - auto coeffshiftyRefB = shiftprofile.at(i)->GetBinContent(shiftprofile.at(i)->FindBin(cent, 2.0 * refBId + 1.5, ishift - 0.5)); + if (cfgAddEvtSel) { + if (!eventSel(coll)) + return; + } - deltapsiDet += ((2. / (1.0 * ishift)) * (-coeffshiftxDet * std::cos(ishift * static_cast(i + 2) * eps[0]) + coeffshiftyDet * std::sin(ishift * static_cast(i + 2) * eps[0]))) / static_cast(i + 2); - deltapsiRefA += ((2. / (1.0 * ishift)) * (-coeffshiftxRefA * std::cos(ishift * static_cast(i + 2) * eps[1]) + coeffshiftyRefA * std::sin(ishift * static_cast(i + 2) * eps[1]))) / static_cast(i + 2); - deltapsiRefB += ((2. / (1.0 * ishift)) * (-coeffshiftxRefB * std::cos(ishift * static_cast(i + 2) * eps[2]) + coeffshiftyRefB * std::sin(ishift * static_cast(i + 2) * eps[2]))) / static_cast(i + 2); - } + float cent = coll.centFT0C(); - eps[0] += deltapsiDet; - eps[1] += deltapsiRefA; - eps[2] += deltapsiRefB; + if (cfgEffCor) { + auto bc = coll.bc_as(); + currentRunNumber = bc.runNumber(); + if (currentRunNumber != lastRunNumber) { + effMap = ccdb->getForTimeStamp>(cfgEffCorDir, bc.timestamp()); + lastRunNumber = currentRunNumber; + } + } - qx_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::cos(deltapsiDet) - coll.qvecIm()[4 * detId + harmInd] * std::sin(deltapsiDet); - qy_shifted[0] = coll.qvecRe()[4 * detId + harmInd] * std::sin(deltapsiDet) + coll.qvecIm()[4 * detId + harmInd] * std::cos(deltapsiDet); - qx_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::cos(deltapsiRefA) - coll.qvecIm()[4 * refAId + harmInd] * std::sin(deltapsiRefA); - qy_shifted[1] = coll.qvecRe()[4 * refAId + harmInd] * std::sin(deltapsiRefA) + coll.qvecIm()[4 * refAId + harmInd] * std::cos(deltapsiRefA); - qx_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::cos(deltapsiRefB) - coll.qvecIm()[4 * refBId + harmInd] * std::sin(deltapsiRefB); - qy_shifted[2] = coll.qvecRe()[4 * refBId + harmInd] * std::sin(deltapsiRefB) + coll.qvecIm()[4 * refBId + harmInd] * std::cos(deltapsiRefB); + for (auto trk : tracks) { + if (!trk.has_mcParticle()) { + continue; } - float resNumA = helperEP.GetResolution(eps[0], eps[1], i + 2); - float resNumB = helperEP.GetResolution(eps[0], eps[2], i + 2); - float resDenom = helperEP.GetResolution(eps[1], eps[2], i + 2); + if (trackSel(trk)) { + continue; + } - epFlowHistograms.fill(HIST("EpDet"), i + 2, cent, eps[0]); - epFlowHistograms.fill(HIST("EpRefA"), i + 2, cent, eps[1]); - epFlowHistograms.fill(HIST("EpRefB"), i + 2, cent, eps[2]); + epFlowHistograms.fill(HIST("MC/hPartRec"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); + auto mctrk = trk.mcParticle(); + if (mctrk.isPhysicalPrimary()) { + epFlowHistograms.fill(HIST("MC/hPartRecPr"), cent, coll.posZ(), trk.eta(), trk.phi(), trk.pt()); + } + } + } + PROCESS_SWITCH(jEPFlowAnalysis, processMCRec, "process for MC", false); - epFlowHistograms.fill(HIST("EpResDetRefA"), i + 2, cent, resNumA); - epFlowHistograms.fill(HIST("EpResDetRefB"), i + 2, cent, resNumB); - epFlowHistograms.fill(HIST("EpResRefARefB"), i + 2, cent, resDenom); + void processMCGen(MyCollisionsMC::iterator const& coll, aod::McParticles const& mcParticles, aod::McCollisions const&) + { + if (!coll.has_mcCollision()) + return; + const auto mcColl = coll.mcCollision(); - epFlowHistograms.fill(HIST("EpResQvecDetRefAxx"), i + 2, cent, qx_shifted[0] * qx_shifted[1] + qy_shifted[0] * qy_shifted[1]); - epFlowHistograms.fill(HIST("EpResQvecDetRefAxy"), i + 2, cent, qx_shifted[1] * qy_shifted[0] - qx_shifted[0] * qy_shifted[1]); - epFlowHistograms.fill(HIST("EpResQvecDetRefBxx"), i + 2, cent, qx_shifted[0] * qx_shifted[2] + qy_shifted[0] * qy_shifted[2]); - epFlowHistograms.fill(HIST("EpResQvecDetRefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[0] - qx_shifted[0] * qy_shifted[2]); - epFlowHistograms.fill(HIST("EpResQvecRefARefBxx"), i + 2, cent, qx_shifted[1] * qx_shifted[2] + qy_shifted[1] * qy_shifted[2]); - epFlowHistograms.fill(HIST("EpResQvecRefARefBxy"), i + 2, cent, qx_shifted[2] * qy_shifted[1] - qx_shifted[1] * qy_shifted[2]); + if (cfgAddEvtSel) { + if (std::abs(mcColl.posZ()) > cfgVertexZ) { + return; + } + } - for (const auto& track : tracks) { - float vn = std::cos((i + 2) * (track.phi() - eps[0])); - float vnSin = std::sin((i + 2) * (track.phi() - eps[0])); + float cent = coll.centFT0C(); - epFlowHistograms.fill(HIST("vncos"), i + 2, cent, track.pt(), vn * weight); - epFlowHistograms.fill(HIST("vnsin"), i + 2, cent, track.pt(), vnSin * weight); + for (auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.eta()) > cfgTrackCuts.cfgEtaMax) + continue; - epFlowHistograms.fill(HIST("SPvnxx"), i + 2, cent, track.pt(), (std::cos(track.phi() * static_cast(i + 2)) * qx_shifted[0] + std::sin(track.phi() * static_cast(i + 2)) * qy_shifted[0]) * weight); - epFlowHistograms.fill(HIST("SPvnxy"), i + 2, cent, track.pt(), (std::sin(track.phi() * static_cast(i + 2)) * qx_shifted[0] - std::cos(track.phi() * static_cast(i + 2)) * qy_shifted[0]) * weight); + auto* p = TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode()); + if (p) { + if (std::abs(p->Charge()) < 1e-1) { + continue; + } } + + if (!mcParticle.isPhysicalPrimary()) + continue; + + epFlowHistograms.fill(HIST("MC/hPartGen"), cent, mcColl.posZ(), mcParticle.eta(), mcParticle.phi(), mcParticle.pt()); } } - PROCESS_SWITCH(jEPFlowAnalysis, processDefault, "default process", true); + PROCESS_SWITCH(jEPFlowAnalysis, processMCGen, "process for MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx b/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx index 4b14c8ba049..9fbea5ed78a 100644 --- a/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx +++ b/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx @@ -11,7 +11,7 @@ /// /// \file jflucWeightsLoader.cxx /// \brief Task to load the NUA and NUE weights from local files or CCDB. -/// \author Jasper Parkkila (jparkkil@cern.ch), Maxim Virta (maxim.virta@cern.ch) +/// \author Jasper Parkkila (jparkkil@cern.ch), Maxim Virta (maxim.virta@cern.ch), Neelkamal Mallick (neelkamal.mallick@cern.ch) /// \since May 2024 /// The weights are loaded from the local files or CCDB and stored in the JWeights table. @@ -24,6 +24,7 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" @@ -36,6 +37,7 @@ #include #include +#include using namespace o2; using namespace o2::framework; @@ -49,6 +51,20 @@ struct JflucWeightsLoader { O2_DEFINE_CONFIGURABLE(cfgPathPhiWeights, std::string, "Users/m/mavirta/corrections/NUA/LHC23zzh", "Local (local://) or CCDB path for the phi acceptance correction histogram"); O2_DEFINE_CONFIGURABLE(cfgPathEffWeights, std::string, "Users/m/mavirta/corrections/NUE/LHC23zzh", "Local (local://) or CCDB path for the efficiency correction histogram"); O2_DEFINE_CONFIGURABLE(cfgForRunNumber, bool, false, "Get CCDB object by run"); + O2_DEFINE_CONFIGURABLE(cfgPtMin, float, 0.2f, "Minimum pT used for track selection."); + O2_DEFINE_CONFIGURABLE(cfgPtMax, float, 5.0f, "Maximum pT used for track selection."); + O2_DEFINE_CONFIGURABLE(cfgEtaMax, float, 1.0f, "Maximum eta used for track selection."); + O2_DEFINE_CONFIGURABLE(cfgMinMultiplicity, int, 5, "Minimum number of particles required for the event to have."); + O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 0, "Track selection bitmask to use as defined in the filterCorrelations.cxx task"); + + ConfigurableAxis cfgAxisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 2.0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 100.1}, "multiplicity / centrality axis for histograms"}; + ConfigurableAxis cfgAxisPhi{"axisPhi", {50, 0.0, o2::constants::math::TwoPI}, "phi axis for histograms"}; + ConfigurableAxis cfgAxisEta{"axisEta", {40, -2.0, 2.0}, "eta axis for histograms"}; + ConfigurableAxis cfgAxisZVertex{"axisZVertex", {20, -10.0, 10.0}, "zvertex axis for histograms"}; + + HistogramRegistry qaHistRegistry{"qaHistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + Filter derivedTracks = (nabs(aod::cftrack::eta) < cfgEtaMax) && (aod::cftrack::pt > cfgPtMin) && (aod::cftrack::pt < cfgPtMax) && ncheckbit(aod::track::trackType, as(cfgTrackBitMask)); THnF* ph = 0; TFile* pf = 0; @@ -98,60 +114,73 @@ struct JflucWeightsLoader { void init(InitContext const&) { - if (!doprocessLoadWeights && !doprocessLoadWeightsCF) { + if (!doprocessLoadWeights && !doprocessLoadWeightsCF && !doprocessJNUACreatorCFDerived) { return; } if (doprocessLoadWeights && doprocessLoadWeightsCF) LOGF(fatal, "Only one of JTracks or CFTracks processing can be enabled at a time."); - // NUA corrections from local file or CCDB - if (cfgPathPhiWeights.value.substr(0, 8) == "local://") { - LOGF(info, "Using NUA corrections locally from: %s", cfgPathPhiWeights.value.substr(8).c_str()); - pf = new TFile(cfgPathPhiWeights.value.substr(8).c_str(), "read"); - if (!pf->IsOpen()) { - delete pf; - pf = 0; - LOGF(fatal, "NUA correction weights file not found: %s", cfgPathPhiWeights.value.substr(8).c_str()); - } - useNUAFromCCDB = false; - } else if (cfgPathPhiWeights.value == "") { - LOGF(info, "No NUA corrections provided."); - useNUAFromCCDB = false; - } else { - LOGF(info, "Assuming NUA corrections from CCDB."); - useNUAFromCCDB = true; - ccdb->setURL(ccdbURL.data()); // default CCDB URL - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - } - - // Efficiency corrections from local file or CCDB - if (cfgPathEffWeights.value.substr(0, 8) == "local://") { - LOGF(info, "Using efficiency corrections locally from: %s", cfgPathEffWeights.value.substr(8).c_str()); - pfeff = new TFile(cfgPathEffWeights.value.substr(8).c_str(), "read"); - if (!pfeff->IsOpen()) { - delete pfeff; - pfeff = 0; - LOGF(fatal, "Efficiency correction weights file not found: %s", cfgPathEffWeights.value.substr(8).c_str()); + if (doprocessLoadWeights || doprocessLoadWeightsCF) { + // NUA corrections from local file or CCDB + if (cfgPathPhiWeights.value.substr(0, 8) == "local://") { + LOGF(info, "Using NUA corrections locally from: %s", cfgPathPhiWeights.value.substr(8).c_str()); + pf = new TFile(cfgPathPhiWeights.value.substr(8).c_str(), "read"); + if (!pf->IsOpen()) { + delete pf; + pf = 0; + LOGF(fatal, "NUA correction weights file not found: %s", cfgPathPhiWeights.value.substr(8).c_str()); + } + useNUAFromCCDB = false; + } else if (cfgPathPhiWeights.value == "") { + LOGF(info, "No NUA corrections provided."); + useNUAFromCCDB = false; } else { - LOGF(info, "Loaded efficiency correction histogram locally."); - } - useEffFromCCDB = false; - } else if (cfgPathEffWeights.value == "") { - LOGF(info, "No efficiency corrections provided."); - useEffFromCCDB = false; - } else { - LOGF(info, "Assuming efficiency corrections from CCDB."); - useEffFromCCDB = true; - // If NUA corrections are from CCDB, use the same CCDB URL for efficiency corrections - if (!useNUAFromCCDB) { + LOGF(info, "Assuming NUA corrections from CCDB."); + useNUAFromCCDB = true; ccdb->setURL(ccdbURL.data()); // default CCDB URL ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); } + + // Efficiency corrections from local file or CCDB + if (cfgPathEffWeights.value.substr(0, 8) == "local://") { + LOGF(info, "Using efficiency corrections locally from: %s", cfgPathEffWeights.value.substr(8).c_str()); + pfeff = new TFile(cfgPathEffWeights.value.substr(8).c_str(), "read"); + if (!pfeff->IsOpen()) { + delete pfeff; + pfeff = 0; + LOGF(fatal, "Efficiency correction weights file not found: %s", cfgPathEffWeights.value.substr(8).c_str()); + } else { + LOGF(info, "Loaded efficiency correction histogram locally."); + } + useEffFromCCDB = false; + } else if (cfgPathEffWeights.value == "") { + LOGF(info, "No efficiency corrections provided."); + useEffFromCCDB = false; + } else { + LOGF(info, "Assuming efficiency corrections from CCDB."); + useEffFromCCDB = true; + // If NUA corrections are from CCDB, use the same CCDB URL for efficiency corrections + if (!useNUAFromCCDB) { + ccdb->setURL(ccdbURL.data()); // default CCDB URL + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + } + } // doprocessLoadWeights || doprocessLoadWeightsCF + + if (doprocessJNUACreatorCFDerived) { + qaHistRegistry.add("trackType", "trackType;trackType;counts", HistType::kTH1F, {{65, -0.5, 64.5}}); + const AxisSpec axisMult{cfgAxisMultiplicity, "multiplicity/centrality"}; + const AxisSpec axisType{2, -0.5, 1.5, "type"}; // 0 = all charged hadrons (matches loader partType) + const AxisSpec axisPhi{cfgAxisPhi, "#varphi"}; + const AxisSpec axisEta{cfgAxisEta, "#eta"}; + const AxisSpec axisZVertex{cfgAxisZVertex, "z_{vtx} [cm]"}; + + qaHistRegistry.add("NUACreation/h_phietaz", "(NUA) mult, type, phi, eta, z", HistType::kTHnF, {axisMult, axisType, axisPhi, axisEta, axisZVertex}); } } @@ -215,6 +244,7 @@ struct JflucWeightsLoader { // NUA corrections are a function of multiplicity, partType, phi, eta, and z-vertex const double nuaCoords[] = {collision.multiplicity(), static_cast(partType), track.phi(), track.eta(), collision.posZ()}; phiWeight = ph->GetBinContent(ph->GetBin(nuaCoords)); + phiWeight = phiWeight == 0. ? 1.0f : phiWeight; // avoid division by zero later } else { phiWeight = 1.0f; } @@ -227,7 +257,6 @@ struct JflucWeightsLoader { } else { effWeight = 1.0f; } - outputT(phiWeight, effWeight); } } @@ -251,6 +280,31 @@ struct JflucWeightsLoader { loadWeights(output2p, collision, tracks2p); } PROCESS_SWITCH(JflucWeightsLoader, processLoadWeightsCF2Prong, "Load weights histograms for CF derived 2-prong tracks data table", false); + + // Create NUA histograms from CF derived data to be used in this loader + void processJNUACreatorCFDerived(aod::CFCollision const& collision, soa::Filtered const& tracks) + { + + if (tracks.size() < cfgMinMultiplicity) { + return; // reject if not enough tracks + } + + const auto multiplicity = collision.multiplicity(); // this comes from the filterCorrelations.cxx task + const float multAxisUpper = AxisSpec(cfgAxisMultiplicity, "").binEdges.back(); + if (multiplicity < 0. || multiplicity > multAxisUpper) { + return; + } + + const float posZ = collision.posZ(); + // Fill NUA histogram with same coordinate order as loader: (mult, partType, phi, eta, z) + // partType = 0 for all charged hadrons (matches loader where partType is always 0 for now) + for (auto& track : tracks) { + qaHistRegistry.fill(HIST("NUACreation/h_phietaz"), multiplicity, 0.0f, track.phi(), track.eta(), posZ); + qaHistRegistry.fill(HIST("trackType"), track.trackType()); + } + } + + PROCESS_SWITCH(JflucWeightsLoader, processJNUACreatorCFDerived, "Create NUA histograms from CF derived data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index c1274b6788c..9f9304d4d1e 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -143,8 +143,9 @@ struct : ConfigurableGroup { Configurable> cfBookParticleHistograms{"cfBookParticleHistograms", {"1-Phi", "1-Pt", "1-Eta", "1-Charge", "1-tpcNClsFindable", "1-tpcNClsShared", "1-itsChi2NCl", "1-tpcNClsFound", "1-tpcNClsCrossedRows", "1-itsNCls", "1-itsNClsInnerBarrel", "1-tpcCrossedRowsOverFindableCls", "1-tpcFoundOverFindableCls", "1-tpcFractionSharedCls", "1-tpcChi2NCl", "1-dcaXY", "1-dcaZ", "0-PDG"}, "Book (1) or do not book (0) particle histogram"}; Configurable cfFillParticleHistograms2D{"cfFillParticleHistograms2D", false, "if false, all 2D particle histograms are not filled. if kTRUE, the ones for which fBookParticleHistograms2D[...] is kTRUE, are filled"}; Configurable> cfBookParticleHistograms2D{"cfBookParticleHistograms2D", {"1-Phi_vs_Pt", "1-Phi_vs_Eta"}, "Book (1) or do not book (0) 2D particle histograms"}; - Configurable cfRebinSparse{"cfRebinSparse", 1, "used only for all fixed-length bins which are implemented directly for sparse histograms (i.e. not inherited from results histograms)"}; - Configurable> cfBookParticleSparseHistograms{"cfBookParticleSparseHistograms", {"0-DWPhi", "0-DWPt", "0-DWEta"}, "Book (1) or do not book (0) particular category of sparse histograms"}; + Configurable> cfRebinSparse{"cfRebinSparse", {1., 1., 1., 1., 1., 1.}, "Ordering is the same as in eDiffPhiWeights. To make bins factor 2 finer use 0.5, to make bins factor 5 coarser use 5."}; + Configurable> cfBookParticleSparseHistograms{"cfBookParticleSparseHistograms", {"0-DWPhi", "0-DWPt", "0-DWEta", "0-DWCharge"}, "Book (1) or do not book (0) particular category of sparse histograms"}; + Configurable cfFillParticleSparseHistogramsBeforeCuts{"cfFillParticleSparseHistogramsBeforeCuts", false, "I need sparse histograms before cuts only when testing pt and eta weights, in internal validation"}; // TBI 20250223 add eventually configurable for FillParticleSparseHistogramsDimension } cf_ph; @@ -156,7 +157,7 @@ struct : ConfigurableGroup { Configurable> cfPhi{"cfPhi", {0.0, o2::constants::math::TwoPI}, "phi range: {min, max}[rad], with convention: min <= phi < max"}; Configurable> cfPt{"cfPt", {0.2, 5.0}, "pt range: {min, max}[GeV], with convention: min <= pt < max"}; Configurable> cfEta{"cfEta", {-0.8, 0.8}, "eta range: {min, max}, with convention: min <= eta < max"}; - Configurable> cfCharge{"cfCharge", {-1.5, 1.5}, "particle charge. {-1.5,0} = only negative, {0,1.5} = only positive"}; + Configurable> cfCharge{"cfCharge", {-2.0, 2.0}, "particle charge. {-2.0,0} = only negative, {0,2.0} = only positive (keep in sync with res.fResultsProBinEdges[AFO_CHARGE])"}; Configurable> cftpcNClsFindable{"cftpcNClsFindable", {-1000., 1000.}, "tpcNClsFindable range: {min, max}, with convention: min <= cftpcNClsFindable < max"}; Configurable> cftpcNClsShared{"cftpcNClsShared", {-1000., 1000.}, "tpcNClsShared range: {min, max}, with convention: min <= cftpcNClsShared < max"}; Configurable> cfitsChi2NCl{"cfitsChi2NCl", {-1000., 36.}, "itsChi2NCl range: {min, max}, with convention: min <= cfitsChi2NCl < max"}; @@ -230,8 +231,9 @@ struct : ConfigurableGroup { Configurable cfUseDiffPhiPtWeights{"cfUseDiffPhiPtWeights", false, "use or not differential phi(pt) weights"}; Configurable cfUseDiffPhiEtaWeights{"cfUseDiffPhiEtaWeights", false, "use or not differential phi(eta) weights"}; Configurable> cfWhichDiffPhiWeights{"cfWhichDiffPhiWeights", {"1-wPhi", "1-wPt", "1-wEta", "1-wCharge", "1-wCentrality", "1-wVertexZ"}, "use (1) or do not use (0) differential phi weight for particular dimension. If only phi is set to 1, integrated phi weights are used. If phi is set to 0, ALL dimensions are switched off (yes!)"}; - Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"0-wPt", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; - Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"0-wEta", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"0-wPt", "0-wEta", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"0-wEta", "0-wPt", "0-wCharge", "0-wCentrality"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffChargeWeights{"cfWhichDiffChargeWeights", {"0-wCharge", "0-wPt", "0-wEta", "0-wCentrality"}, "use (1) or do not use (0) differential charge weight for particular dimension. If only charge is set to 1, integrated charge weights are used. If charge is set to 0, ALL dimensions are switched off (yes!)"}; Configurable cfFileWithWeights{"cfFileWithWeights", "/home/abilandz/DatasetsO2/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" } cf_pw; @@ -251,9 +253,9 @@ struct : ConfigurableGroup { // *) Toy NUA: struct : ConfigurableGroup { - Configurable> cfApplyNUAPDF{"cfApplyNUAPDF", {0, 0, 0}, "Apply (1) or do not apply (0) NUA on variable, ordering is the same as in enum eNUAPDF (phi, pt, eta)"}; - Configurable> cfUseDefaultNUAPDF{"cfUseDefaultNUAPDF", {1, 1, 1}, "Use (1) or do not use (0) default NUA profile, ordering is the same as in enum eNUAPDF (phi, pt, eta)"}; - Configurable> cfCustomNUAPDFHistNames{"cfCustomNUAPDFHistNames", {"a", "bb", "ccc"}, "the names of histograms holding custom NUA in an external file."}; + Configurable> cfApplyNUAPDF{"cfApplyNUAPDF", {0, 0, 0, 0}, "Apply (1) or do not apply (0) NUA on variable, ordering is the same as in enum eNUAPDF (phi, pt, eta, charge)"}; + Configurable> cfUseDefaultNUAPDF{"cfUseDefaultNUAPDF", {1, 1, 1, 1}, "Use (1) or do not use (0) default NUA profile, ordering is the same as in enum eNUAPDF (phi, pt, eta, charge)"}; + Configurable> cfCustomNUAPDFHistNames{"cfCustomNUAPDFHistNames", {"a", "bb", "ccc", "dddd"}, "the names of histograms holding custom NUA in an external file."}; Configurable cfFileWithCustomNUA{"cfFileWithCustomNUA", "/home/abilandz/DatasetsO2/customNUA.root", "path to external ROOT file which holds all histograms with custom NUA"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" } cf_nua; @@ -262,7 +264,7 @@ struct : ConfigurableGroup { Configurable cfUseInternalValidation{"cfUseInternalValidation", false, "perform internal validation using flow analysis on-the-fly"}; Configurable cfInternalValidationForceBailout{"cfInternalValidationForceBailout", false, "force bailout (use only locally, since there is no graceful exit (yet))"}; Configurable cfnEventsInternalValidation{"cfnEventsInternalValidation", 0, "number of events simulated on-the-fly for internal validation"}; - Configurable cfHarmonicsOptionInternalValidation{"cfHarmonicsOptionInternalValidation", "constant", "for internal validation, supported options are \"constant\", \"correlated\" and \"persistent\""}; + Configurable cfHarmonicsOptionInternalValidation{"cfHarmonicsOptionInternalValidation", "constant", "for internal validation, supported options are \"constant\", \"correlated\", \"persistent\", \"ptDependent\", \"ptEtaDependent\", and \"ptEtaChargeDependent\""}; Configurable cfRescaleWithTheoreticalInput{"cfRescaleWithTheoreticalInput", false, "if kTRUE, all correlators are rescaled with theoretical input, so that all results in profiles are 1"}; Configurable cfRandomizeReactionPlane{"cfRandomizeReactionPlane", true, "set to false only when validating against theoretical value the non-isotropic correlators"}; Configurable> cfInternalValidationAmplitudes{"cfInternalValidationAmplitudes", {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09}, "{v1, v2, v3, v4, ...} + has an effect only in combination with cfHarmonicsOptionInternalValidation = \"constant\". Max number of vn's is gMaxHarmonic."}; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index fff7cd5fdee..32df4c726ee 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -21,7 +21,9 @@ // General remarks: // 0. Starting with C++11, it's possible to initialize data members at declaration, so I do it here // 1. Use //! 0. Set to <=0 to ignore. - bool fUseStopwatch = false; // do some basing profiling with TStopwatch for where the execution time is going - TStopwatch* fTimer[eTimer_N] = {NULL}; // stopwatch, global (overal execution time) and local - float fFloatingPointPrecision = 1.e-6; // two floats are the same if abs(f1 - f2) < fFloatingPointPrecision (there is configurable for it) - int fSequentialBailout = 0; // if fSequentialBailout > 0, then each fSequentialBailout events the function BailOut() is called. Can be used for real analysis and for IV. - bool fUseSpecificCuts = false; // apply after DefaultCuts() also hardwired analysis-specific cuts, determined via tc.fWhichSpecificCuts - TString fWhichSpecificCuts = ""; // determine which set of analysis-specific cuts will be applied after DefaultCuts(). Use in combination with tc.fUseSpecificCuts - TString fSkipTheseRuns = ""; // comma-separated list of runs which will be skipped during analysis in hl (a.k.a. "bad runs") - bool fSkipRun = false; // based on the content of fWhichSpecificCuts, skip or not the current run - TDatabasePDG* fDatabasePDG = NULL; // booked only when MC info is available. There is a standard memory blow-up when booked, therefore I need to request also fUseDatabasePDG = true - // TBI 20250625 replace eventually with the service O2DatabasePDG, when memory consumption problem is resolved - bool fUseSetBinLabel = false; // until SetBinLabel(...) large memory consumption is resolved, do not use hist->SetBinLabel(...), see ROOT Forum - // See also local executable PostprocessLabels.C - bool fUseClone = false; // until Clone(...) large memory consumption is resolved, do not use hist->Clone(...), see ROOT Forum - bool fUseFormula = false; // until TFormula large memory consumption is resolved, do not use, see ROOT Forum - bool fUseDatabasePDG = false; // I use it at the moment only to retreive charge for MC particle from its PDG code, because there is no direct getter mcParticle.sign() - // But most likely I will use it to retrieve other particle proprties from PDG table. There is a standard memory blow-up when used. -} tc; // "tc" labels an instance of this group of variables. + bool fUseStopwatch = false; // do some basing profiling with TStopwatch for where the execution time is going + TStopwatch* fTimer[eTimer_N] = {NULL}; // stopwatch, global (overal execution time) and local + float fFloatingPointPrecision = 1.e-6; // two floats are the same if abs(f1 - f2) < fFloatingPointPrecision (there is configurable for it) + int fSequentialBailout = 0; // if fSequentialBailout > 0, then each fSequentialBailout events the function BailOut() is called. Can be used for real analysis and for IV. + bool fUseSpecificCuts = false; // apply after DefaultCuts() also hardwired analysis-specific cuts, determined via tc.fWhichSpecificCuts + TString fWhichSpecificCuts = ""; // determine which set of analysis-specific cuts will be applied after DefaultCuts(). Use in combination with tc.fUseSpecificCuts + TString fSkipTheseRuns = ""; // comma-separated list of runs which will be skipped during analysis in hl (a.k.a. "bad runs") + bool fSkipRun = false; // based on the content of fWhichSpecificCuts, skip or not the current run + bool fCalculateAsFunctionOf[eAsFunctionOf_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + // Example: tc.fCalculateAsFunctionOf[AFO_PT] = mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT] + // || es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] + bool fCalculate2DAsFunctionOf[eAsFunctionOf2D_N] = {false}; //! See example above for 1D case + enum for 2D details + bool fCalculate3DAsFunctionOf[eAsFunctionOf3D_N] = {false}; //! See example above for 1D case + enum for 3D details + TDatabasePDG* fDatabasePDG = NULL; // booked only when MC info is available. There is a standard memory blow-up when booked, therefore I need to request also fUseDatabasePDG = true + // TBI 20250625 replace eventually with the service O2DatabasePDG, when memory consumption problem is resolved + bool fUseSetBinLabel = false; // until SetBinLabel(...) large memory consumption is resolved, do not use hist->SetBinLabel(...), see ROOT Forum + // See also local executable PostprocessLabels.C + bool fUseClone = false; // until Clone(...) large memory consumption is resolved, do not use hist->Clone(...), see ROOT Forum + bool fUseFormula = false; // until TFormula large memory consumption is resolved, do not use, see ROOT Forum + bool fUseDatabasePDG = false; // I use it at the moment only to retreive charge for MC particle from its PDG code, because there is no direct getter mcParticle.sign() + // But most likely I will use it to retrieve other particle proprties from PDG table. There is a standard memory blow-up when used. +} tc; // "tc" labels an instance of this group of variables. // *) Event-by-event quantities: struct EventByEventQuantities { @@ -95,7 +103,8 @@ struct EventByEventQuantities { // Results "vs. mult" are plotted against fMultiplicity, whatever it is set to. // Use configurable cfMultiplicityEstimator[eMultiplicityEstimator] to define what is this multiplicity, by default it is "SelectedTracks" float fReferenceMultiplicity = 0.; // reference multiplicity, calculated outside of my code. Can be "MultTPC", "MultFV0M", etc. - // Use configurable cfReferenceMultiplicityEstimator[eReferenceMultiplicityEstimator]" to define what is this multiplicity, by default it is "TBI 20241123 I do not know yet which estimator is best for ref. mult." + // Use configurable cfReferenceMultiplicityEstimator[eReferenceMultiplicityEstimator]" to define what is this multiplicity, + // by default it is "TBI 20241123 I do not know yet which estimator is best for ref. mult." float fCentrality = 0.; // event-by-event centrality, in reconstructed data. Value of the default centrality estimator, set via configurable cfCentralityEstimator float fCentralitySim = 0.; // event-by-event centrality, in simulated data. Calculated directly from IP at the moment, eventually I will access it from o2::aod::hepmcheavyion::Centrality float fOccupancy = 0.; // event-by-event occupancy. Value of the default occupancy estimator, set via configurable cfOccupancyEstimator. @@ -103,10 +112,20 @@ struct EventByEventQuantities { float fInteractionRate = 0.; // event-by-event interaction rate float fCurrentRunDuration = 0.; // how many seconds after start of run this collision was taken, i.e. seconds after start of run (SOR) float fVz = 0.; // vertex z position + float fVzSim = 0.; // vertex z position, in simulated data float fFT0CAmplitudeOnFoundBC = 0.; // TBI20250331 finalize the comment here float fImpactParameter = 0.; // calculated only for simulated/generated data } ebye; // "ebye" is a common label for objects in this struct +// *) Particle-by-particle quantities: +// Remark: Here I define all particle quantities, that I need across several member functions. +struct ParticleByParticleQuantities { + double fPhi = 0.; // azimuthal angle + double fPt = 0.; // transverse momentum + double fEta = 0.; // pseudorapidity + double fCharge = -44.; // particle charge. Yes, never initialize charge to 0. +} pbyp; + // *) QA: // Remark 1: I keep new histograms in this group, until I need them permanently in the analysis. Then, they are moved to EventHistograms or ParticleHistograms (yes, even if they are 2D). // Remark 2: All 2D histograms book as TH2F, due to "stmem error" in terminate (see .cxx for further details) @@ -226,18 +245,24 @@ struct ParticleHistograms { TString fParticleHistogramsName2D[eParticleHistograms2D_N] = {""}; // name of particle histogram 2D, determined programatically from two 1D, in the format "%s_vs_%s" // **) n-dimensional sparse histograms: - THnSparse* fParticleSparseHistograms[eDiffWeightCategory_N][2] = {{NULL}}; //! [ category of sparse histograms - see enum eDiffWeightCategory ][reco,sim] - // Remark 0: I anticipate I will need this only for differential particle weights, - // therefore I couple it with eDiffWeightCategory_N - // Remark 1: I fill these histograms only AFTER cuts, therefore no need for extra dimension - bool fBookParticleSparseHistograms[eDiffWeightCategory_N] = {false}; // fill or not specific category of sparse histograms + THnSparse* fParticleSparseHistograms[eDiffWeightCategory_N][2][2] = {{{NULL}}}; //! [ category of sparse histograms - see enum eDiffWeightCategory ][reco,sim][before, after particle cuts] + // Remark 0: I anticipate I will need this only for differential particle weights, + // therefore I couple it with eDiffWeightCategory_N + // Remark 1: I fill these histograms only AFTER cuts, therefore no need for extra dimension + bool fBookParticleSparseHistograms[eDiffWeightCategory_N] = {false}; // fill or not specific category of sparse histograms + + bool fFillParticleSparseHistogramsBeforeCuts = false; // by default, I fill sparse histograms only after the cuts. In rare cases, e.g. in internal validation + // when I am developing pT and eta weights, I calculate them from the ratio [sim][before] / [sim][after], + // therefore in that case I need to fill sparse also before cuts. As of 20251124, this is the only case when it's justified + // to fill sparse also before cuts + // bool fFillParticleSparseHistogramsDimension[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{true}}; // fill or not the specific dimension of a category of sparse histograms TBI 20250223 implement this eventually TString fParticleSparseHistogramsName[eDiffWeightCategory_N] = {""}; // name of particle sparse histogram, determined programatically from requested axes TString fParticleSparseHistogramsTitle[eDiffWeightCategory_N] = {""}; // title of particle sparse histogram, determined programatically from requested axes int fParticleSparseHistogramsNBins[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{0}}; // number of bins. I do not have min and max, because for sparse I use BinEdges, see below TArrayD* fParticleSparseHistogramsBinEdges[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{NULL}}; // arrays holding bin edges, see the usage of SetBinEdges for sparse histograms TString fParticleSparseHistogramsAxisTitle[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{""}}; // axis title - int fRebinSparse = 1; // used only for all fixed-length bins which are implemented directly for sparse histograms (i.e. not inherited from results histograms) + float fRebinSparse[eDiffWeightCategory_N][gMaxNumberSparseDimensions] = {{1.}}; // used only for all fixed-length bins which are implemented directly for sparse histograms (i.e. not inherited from results histograms) } ph; // "ph" labels an instance of group of histograms "ParticleHistograms" // *) Particle cuts: @@ -260,12 +285,14 @@ struct ParticleCuts { // *) Q-vectors: struct Qvector { - TList* fQvectorList = NULL; // list to hold all Q-vector objects - TProfile* fQvectorFlagsPro = NULL; // profile to hold all flags for Q-vector - bool fCalculateQvectors = true; // to calculate or not to calculate Q-vectors, that's a Boolean... - // Does NOT apply to Qa, Qb, etc., vectors, needed for eta separ. - TComplex fQ[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! generic Q-vector - TComplex fQvector[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! "integrated" Q-vector + TList* fQvectorList = NULL; // list to hold all Q-vector objects + TProfile* fQvectorFlagsPro = NULL; // profile to hold all flags for Q-vector + bool fCalculateQvectors = true; // to calculate or not to calculate Q-vectors, that's a Boolean... + // Does NOT apply to Qa, Qb, etc., vectors, needed for eta separ. + TComplex fQ[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! generic Q-vector, legacy code (TBI 20250718 remove, and switch to line below eventually) + // std::vector>> fQ; // generic Q-vector + TComplex fQvector[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! integrated Q-vector, legacy code (TBI 20250718 remove, and switch to line below eventually) + // std::vector>> fQvector; // dynamically allocated integrated Q-vector => it has to be done this way, to optimize memory usage bool fCalculateqvectorsKineAny = false; // by default, it's off. It's set to true automatically if any of kine correlators is requested, // either for Correlations, Test0, EtaSeparations, etc. @@ -275,7 +302,7 @@ struct Qvector { std::vector>>>> fqvector; // dynamically allocated differential q-vector => it has to be done this way, to optimize memory usage // dimensions: [eqvectorKine_N][gMaxNoBinsKine][gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] std::vector fNumberOfKineBins = {0}; // for each kine vector which was requested in this analysis, here I calculate and store the corresponding number of kine bins - std::vector> fqvectorEntries; // dynamically allocated number of entries for differential q-vector => it has to be done this way, to optimize memory usage + std::vector> fqvectorEntries; // dynamically allocated number of entries for differential q-vector => it has to be done this way, to optimize memory usage. Dimensions: [eqvectorKine_N][gMaxNoBinsKine] // q-vectors for eta separations: TComplex fQabVector[2][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{TComplex(0., 0.)}}}; //! integrated [-eta or +eta][harmonic][eta separation] @@ -316,9 +343,10 @@ struct ParticleWeights { bool fUseDiffPhiWeights[eDiffPhiWeights_N] = {false}; // use differential phi weights, see enum eDiffPhiWeights for supported dimensions bool fUseDiffPtWeights[eDiffPtWeights_N] = {false}; // use differential pt weights, see enum eDiffPtWeights for supported dimensions bool fUseDiffEtaWeights[eDiffEtaWeights_N] = {false}; // use differential eta weights, see enum eDiffEtaWeights for supported dimensions + bool fUseDiffChargeWeights[eDiffChargeWeights_N] = {false}; // use differential charge weights, see enum eDiffChargeWeights for supported dimensions // ... int fDWdimension[eDiffWeightCategory_N] = {0}; // dimension of differential weight for each category in current analysis - TArrayD* fFindBinVector[eDiffWeightCategory_N] = {NULL}; // this is the vector I use to find bin TBI 20250224 finalie description + TArrayD* fFindBinVector[eDiffWeightCategory_N] = {NULL}; // this is the vector I use to find bin when I obtain weights with sparse histograms TString fFileWithWeights = ""; // path to external ROOT file which holds all particle weights bool fParticleWeightsAreFetched = false; // ensures that particle weights are fetched only once @@ -372,7 +400,7 @@ struct InternalValidation { // Remember that for each real event, I do fnEventsInternalValidation events on-the-fly. // Can be used in combination with setting fSequentialBailout > 0. unsigned int fnEventsInternalValidation = 0; // how many on-the-fly events will be sampled for each real event, for internal validation - TString* fHarmonicsOptionInternalValidation = NULL; // "constant", "correlated" or "persistent", see .cxx for full documentation + TString* fHarmonicsOptionInternalValidation = NULL; // "constant", "correlated", "persistent", "ptDependent", "ptEtaDependent", "ptEtaChargeDependent", see .cxx for full documentation bool fRescaleWithTheoreticalInput = false; // if true, all measured correlators are rescaled with theoretical input, so that in profiles everything is at 1 bool fRandomizeReactionPlane = true; // if true, RP is randomized e-by-e. I need false basically only when validating against theoretical input non-isotropic correlators TArrayD* fInternalValidationVnPsin[2] = {NULL}; // 0 = { v1, v2, ... }, 1 = { Psi1, Psi2, ... } @@ -429,7 +457,7 @@ struct Results { // This is in addition TProfile2D* fResultsPro2D[eAsFunctionOf2D_N] = {NULL}; //!SetBinLabel(...) eUseClone, // Use or not ->Clone() eUseFormula, // Use or not class TFormula eUseDatabasePDG, // Use or not class TDatabasePDG @@ -57,7 +57,7 @@ enum eProcess { eProcessSim_Run1, // Run 1, only simulated eProcessTest, // minimum subscription to the tables, for testing purposes eProcessQA, // maximum subscription to the tables, for QA purposes. Basically: eProcessRec + otherwise unnecessary tables - eProcessHepMChi, // special subscription when I extract info from the table HepMCHeavyIons TBI 20250429 merge this case eventualyl with RecSim cases + eProcessHepMChi, // special subscription when I extract info from the table HepMCHeavyIons TBI 20250429 merge this case eventually with RecSim cases // Generic flags, calculated and set from individual flags above in DefaultConfiguration(), AFTER process switch was taken into account: eGenericRec, // generic "Rec" case, eTest is treated for the time being as "Rec". eQA is also in this category eGenericRecSim, // generic "RecSim" case @@ -107,6 +107,7 @@ enum eDiffWeightCategory { eDWPhi = 0, // corresponds to eDiffPhiWeights structure, here the fundamental 0-th axis never to be projected out is "phi" eDWPt, // corresponds to eDiffPtWeights structure, here the fundamental 0-th axis never to be projected out is "pt" eDWEta, // corresponds to eDiffEtaWeights structure, here the fundamental 0-th axis never to be projected out is "eta" + eDWCharge, // corresponds to eDiffChargeWeights structure, here the fundamental 0-th axis never to be projected out is "charge" // ... eDiffWeightCategory_N }; @@ -121,8 +122,9 @@ enum eDiffPhiWeights { eDiffPhiWeights_N }; -enum eDiffPtWeights { +enum eDiffPtWeights { // if i add new entry here, or in eDiffPhiWeights and eDiffEtaWeights, I need to update also GetParticleWeights() + FillQvectorFromSparse() + WeightFromSparse() wPtPtAxis = 0, + wPtEtaAxis, wPtChargeAxis, wPtCentralityAxis, eDiffPtWeights_N @@ -130,17 +132,26 @@ enum eDiffPtWeights { enum eDiffEtaWeights { wEtaEtaAxis = 0, + wEtaPtAxis, wEtaChargeAxis, wEtaCentralityAxis, eDiffEtaWeights_N }; +enum eDiffChargeWeights { + wChargeChargeAxis = 0, + wChargePtAxis, + wChargeEtaAxis, + wChargeCentralityAxis, + eDiffChargeWeights_N +}; + enum eVnPsin { eVn = 0, ePsin = 1 }; enum eEventHistograms { eNumberOfEvents = 0, // Total events = eNumberOfEvents + eBefore, Selected events = eNumberOfEvents + eAfter - eTotalMultiplicity, // TBI 20241123 I define it as tracks.size(), but most likely this I do not need this + eTotalMultiplicity, // TBI 20241123 I define it as tracks.size(), but most likely I do not need this eMultiplicity, // see documentation for ebye.fMultiplicity eReferenceMultiplicity, // see documentation for ebye.fReferenceMultiplicity eCentrality, // default centrality estimator @@ -359,6 +370,7 @@ enum eNUAPDF { ePhiNUAPDF = 0, ePtNUAPDF, eEtaNUAPDF, + eChargeNUAPDF, eNUAPDF_N }; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h index bd4bca81735..09b8968976a 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h @@ -632,7 +632,7 @@ void defaultConfiguration() pw.fUseDiffWeights[wPHIPT] = cf_pw.cfUseDiffPhiPtWeights; // TBI 20250222 obsolete pw.fUseDiffWeights[wPHIETA] = cf_pw.cfUseDiffPhiEtaWeights; // TBI 20250222 obsolete - // **) Differential phi weights: + // **) Differential multidimensional phi weights: auto lWhichDiffPhiWeights = cf_pw.cfWhichDiffPhiWeights.value; if (lWhichDiffPhiWeights.size() != eDiffPhiWeights_N) { LOGF(info, "\033[1;31m lWhichDiffPhiWeights.size() = %d\033[0m", lWhichDiffPhiWeights.size()); @@ -657,7 +657,7 @@ void defaultConfiguration() } } - // **) Differential pt weights: + // **) Differential multidimensional pt weights: auto lWhichDiffPtWeights = cf_pw.cfWhichDiffPtWeights.value; if (lWhichDiffPtWeights.size() != eDiffPtWeights_N) { LOGF(info, "\033[1;31m lWhichDiffPtWeights.size() = %d\033[0m", lWhichDiffPtWeights.size()); @@ -667,6 +667,8 @@ void defaultConfiguration() for (int dpw = 0; dpw < eDiffPtWeights_N; dpw++) { // "differential pt weight" if (TString(lWhichDiffPtWeights[dpw]).Contains("wPt")) { pw.fUseDiffPtWeights[wPtPtAxis] = Alright(lWhichDiffPtWeights[dpw]); // if I pass "1-Pt" => true, "0-Pt" => false + } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wEta")) { + pw.fUseDiffPtWeights[wPtEtaAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCharge")) { pw.fUseDiffPtWeights[wPtChargeAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCentrality")) { @@ -676,7 +678,7 @@ void defaultConfiguration() } } - // **) Differential eta weights: + // **) Differential multidimensional eta weights: auto lWhichDiffEtaWeights = cf_pw.cfWhichDiffEtaWeights.value; if (lWhichDiffEtaWeights.size() != eDiffEtaWeights_N) { LOGF(info, "\033[1;31m lWhichDiffEtaWeights.size() = %d\033[0m", lWhichDiffEtaWeights.size()); @@ -686,6 +688,8 @@ void defaultConfiguration() for (int dpw = 0; dpw < eDiffEtaWeights_N; dpw++) { // "differential eta weight" if (TString(lWhichDiffEtaWeights[dpw]).Contains("wEta")) { pw.fUseDiffEtaWeights[wEtaEtaAxis] = Alright(lWhichDiffEtaWeights[dpw]); // if I pass "1-Eta" => true, "0-Eta" => false + } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wPt")) { + pw.fUseDiffEtaWeights[wEtaPtAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCharge")) { pw.fUseDiffEtaWeights[wEtaChargeAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCentrality")) { @@ -695,6 +699,33 @@ void defaultConfiguration() } } + // **) Differential multidimensional charge weights: + auto lWhichDiffChargeWeights = cf_pw.cfWhichDiffChargeWeights.value; + if (lWhichDiffChargeWeights.size() != eDiffChargeWeights_N) { + LOGF(info, "\033[1;31m lWhichDiffChargeWeights.size() = %d\033[0m", lWhichDiffChargeWeights.size()); + LOGF(info, "\033[1;31m eDiffChargeWeights_N = %d\033[0m", static_cast(eDiffChargeWeights_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfWhichDiffChargeWeights, and number of entries in enum eDiffChargeWeights_N \n \033[0m", __FUNCTION__, __LINE__); + } + for (int dpw = 0; dpw < eDiffChargeWeights_N; dpw++) { // "differential charge weight" + if (TString(lWhichDiffChargeWeights[dpw]).Contains("wCharge")) { + pw.fUseDiffChargeWeights[wChargeChargeAxis] = Alright(lWhichDiffChargeWeights[dpw]); // if I pass "1-Charge" => true, "0-Charge" => false + } else if (TString(lWhichDiffChargeWeights[dpw]).Contains("wPt")) { + pw.fUseDiffChargeWeights[wChargePtAxis] = Alright(lWhichDiffChargeWeights[dpw]) && pw.fUseDiffChargeWeights[wChargeChargeAxis]; + } else if (TString(lWhichDiffChargeWeights[dpw]).Contains("wEta")) { + pw.fUseDiffChargeWeights[wChargeEtaAxis] = Alright(lWhichDiffChargeWeights[dpw]) && pw.fUseDiffChargeWeights[wChargeChargeAxis]; + } else if (TString(lWhichDiffChargeWeights[dpw]).Contains("wCentrality")) { + pw.fUseDiffChargeWeights[wChargeCentralityAxis] = Alright(lWhichDiffChargeWeights[dpw]) && pw.fUseDiffChargeWeights[wChargeChargeAxis]; + } else { + LOGF(fatal, "\033[1;31m%s at line %d : The setting %s in configurable cfWhichDiffChargeWeights is not supported yet. See enum eDiffChargeWeights . \n \033[0m", __FUNCTION__, __LINE__, TString(lWhichDiffChargeWeights[dpw]).Data()); + } + } + + // **) Only for debugging purposes, print all enabled weights: + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s at line %d : printing current status of all weights flags\033[0m", __FUNCTION__, __LINE__); + PrintAllWeightsFlags(); + } // if (tc.fVerbose) { + // **) File holding all particle weights: pw.fFileWithWeights = cf_pw.cfFileWithWeights; @@ -722,9 +753,10 @@ void defaultConfiguration() nua.fApplyNUAPDF[ePhiNUAPDF] = static_cast(lApplyNUAPDF[ePhiNUAPDF]); nua.fApplyNUAPDF[ePtNUAPDF] = static_cast(lApplyNUAPDF[ePtNUAPDF]); nua.fApplyNUAPDF[eEtaNUAPDF] = static_cast(lApplyNUAPDF[eEtaNUAPDF]); + nua.fApplyNUAPDF[eChargeNUAPDF] = static_cast(lApplyNUAPDF[eChargeNUAPDF]); // **) Execute the lines below, only if toy NUA (either default or custom) is requested for at least one kine variable: - if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF]) { + if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { auto lUseDefaultNUAPDF = (std::vector)cf_nua.cfUseDefaultNUAPDF; if (lUseDefaultNUAPDF.size() != eNUAPDF_N) { @@ -735,11 +767,13 @@ void defaultConfiguration() nua.fUseDefaultNUAPDF[ePhiNUAPDF] = static_cast(lUseDefaultNUAPDF[ePhiNUAPDF]); nua.fUseDefaultNUAPDF[ePtNUAPDF] = static_cast(lUseDefaultNUAPDF[ePtNUAPDF]); nua.fUseDefaultNUAPDF[eEtaNUAPDF] = static_cast(lUseDefaultNUAPDF[eEtaNUAPDF]); + nua.fUseDefaultNUAPDF[eChargeNUAPDF] = static_cast(lUseDefaultNUAPDF[eChargeNUAPDF]); // **) Execute the lines below, only if custom toy NUA is requested in at least one kine variable: if (!((nua.fApplyNUAPDF[ePhiNUAPDF] && nua.fUseDefaultNUAPDF[ePhiNUAPDF]) || (nua.fApplyNUAPDF[ePtNUAPDF] && nua.fUseDefaultNUAPDF[ePtNUAPDF]) || - (nua.fApplyNUAPDF[eEtaNUAPDF] && nua.fUseDefaultNUAPDF[eEtaNUAPDF]))) { + (nua.fApplyNUAPDF[eEtaNUAPDF] && nua.fUseDefaultNUAPDF[eEtaNUAPDF]) || + (nua.fApplyNUAPDF[eChargeNUAPDF] && nua.fUseDefaultNUAPDF[eChargeNUAPDF]))) { // If the above conditon is true, as least one NUA is requested and is not default, i.e. it's custom NUA obtained from external file, which was requested to be used. // TBI 20240501 Can I simplify the logic above, it's a bit cryptic... @@ -777,9 +811,16 @@ void defaultConfiguration() LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } } - } // if (!(nua.fUseDefaultNUAPDF[ePhiNUAPDF] || nua.fUseDefaultNUAPDF[ePtNUAPDF] || nua.fUseDefaultNUAPDF[eEtaNUAPDF])) { + if (!nua.fUseDefaultNUAPDF[eChargeNUAPDF]) { + nua.fCustomNUAPDFHistNames[eChargeNUAPDF] = new TString(lCustomNUAPDFHistNames[eChargeNUAPDF]); + this->GetHistogramWithCustomNUA(nua.fFileWithCustomNUA.Data(), eChargeNUAPDF); + if (!nua.fCustomNUAPDF[eChargeNUAPDF]) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + } + } // if (!(nua.fUseDefaultNUAPDF[ePhiNUAPDF] || nua.fUseDefaultNUAPDF[ePtNUAPDF] || nua.fUseDefaultNUAPDF[eEtaNUAPDF] || nua.fUseDefaultNUAPDF[eChargeNUAPDF])) { - } // if ( nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] ) { + } // if ( nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { // *) Internal validation: iv.fUseInternalValidation = cf_iv.cfUseInternalValidation; @@ -788,6 +829,13 @@ void defaultConfiguration() iv.fRescaleWithTheoreticalInput = cf_iv.cfRescaleWithTheoreticalInput; iv.fRandomizeReactionPlane = cf_iv.cfRandomizeReactionPlane; iv.fHarmonicsOptionInternalValidation = new TString(cf_iv.cfHarmonicsOptionInternalValidation); + // **) Cut counters are not supported in IV (as of 20250728): + if (iv.fUseInternalValidation) { + pc.fUseParticleCutCounterAbsolute = false; + pc.fUseParticleCutCounterSequential = false; + ec.fUseEventCutCounterAbsolute = false; + ec.fUseEventCutCounterSequential = false; + } // *) Results histograms: // **) Fixed-length or variable-length binning: @@ -998,6 +1046,9 @@ void defaultConfiguration() ph.fParticleSparseHistogramsName[eDWEta] = "fParticleSparseHistograms_DWEta"; ph.fParticleSparseHistogramsTitle[eDWEta] = "sparse histogram for differential #eta weights,"; + ph.fParticleSparseHistogramsName[eDWCharge] = "fParticleSparseHistograms_DWCharge"; + ph.fParticleSparseHistogramsTitle[eDWCharge] = "sparse histogram for differential charge weights,"; + // ... // ** Eta separations: @@ -1103,6 +1154,20 @@ void defaultConfiguration() } } + // In terms of above settings, define automatically general fCalculateAsFunctionOf flags: + // 1D: + for (int AFO_1D = 0; AFO_1D < eAsFunctionOf_N; AFO_1D++) { + tc.fCalculateAsFunctionOf[AFO_1D] = mupa.fCalculateCorrelationsAsFunctionOf[AFO_1D] || t0.fCalculateTest0AsFunctionOf[AFO_1D] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_1D]; + } + // 2D: + for (int AFO_2D = 0; AFO_2D < eAsFunctionOf2D_N; AFO_2D++) { + tc.fCalculate2DAsFunctionOf[AFO_2D] = t0.fCalculate2DTest0AsFunctionOf[AFO_2D]; // TBI 20260212 for the time being, I support 2D only for Test0 + } + // 3D: + for (int AFO_3D = 0; AFO_3D < eAsFunctionOf3D_N; AFO_3D++) { + tc.fCalculate3DAsFunctionOf[AFO_3D] = t0.fCalculate3DTest0AsFunctionOf[AFO_3D]; // TBI 20260212 for the time being, I support 3D only for Test0 + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -1111,6 +1176,31 @@ void defaultConfiguration() //============================================================ +void PrintAllWeightsFlags() +{ + // Simple utility function, to print current status of all weights flags. + + LOGF(info, "\033[1;33m Which multidimensional phi weights will be used (the ordering is the same as in enum eDiffPhiWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffPhiWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffPhiWeights[dpw]); + } + LOGF(info, "\033[1;33m Which multidimensional pt weights will be used (the ordering is the same as in enum eDiffPtWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffPtWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffPtWeights[dpw]); + } + LOGF(info, "\033[1;33m Which multidimensional eta weights will be used (the ordering is the same as in enum eDiffEtaWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffEtaWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffEtaWeights[dpw]); + } + LOGF(info, "\033[1;33m Which multidimensional charge weights will be used (the ordering is the same as in enum eDiffChargeWeights):\033[0m"); + for (int dpw = 0; dpw < eDiffChargeWeights_N; dpw++) { + LOGF(info, "\033[1;33m %d \033[0m", pw.fUseDiffChargeWeights[dpw]); + } + +} // void PrintAllWeightsFlags() + +//============================================================ + bool Alright(TString s) { // Simple utility function, which for a string formatted "0-someName" returns false, and for "1-someName" returns true. @@ -1289,7 +1379,33 @@ void defaultBooking() ph.fBookParticleHistograms2D[ePhiEta] = Alright(lBookParticleHistograms2D[ePhiEta]) && ph.fFillParticleHistograms2D; // e) Particle sparse histograms: - ph.fRebinSparse = cf_ph.cfRebinSparse; + auto lRebinSparse = (std::vector)cf_ph.cfRebinSparse; + + ph.fRebinSparse[eDWPhi][wPhiPhiAxis] = lRebinSparse[wPhiPhiAxis]; + ph.fRebinSparse[eDWPhi][wPhiPtAxis] = lRebinSparse[wPhiPtAxis]; + ph.fRebinSparse[eDWPhi][wPhiEtaAxis] = lRebinSparse[wPhiEtaAxis]; + ph.fRebinSparse[eDWPhi][wPhiChargeAxis] = lRebinSparse[wPhiChargeAxis]; + ph.fRebinSparse[eDWPhi][wPhiCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + ph.fRebinSparse[eDWPhi][wPhiVertexZAxis] = lRebinSparse[wPhiVertexZAxis]; + // ... + + ph.fRebinSparse[eDWPt][wPtPtAxis] = lRebinSparse[wPhiPtAxis]; // yes, wPhiPtAxis is on the RHS, becase I defined ordering of cfRebinSparse by using ordering in eDiffPhiWeights + ph.fRebinSparse[eDWPt][wPtEtaAxis] = lRebinSparse[wPhiEtaAxis]; + ph.fRebinSparse[eDWPt][wPtChargeAxis] = lRebinSparse[wPhiChargeAxis]; + ph.fRebinSparse[eDWPt][wPtCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + // ... + + ph.fRebinSparse[eDWEta][wEtaEtaAxis] = lRebinSparse[wPhiEtaAxis]; // yes, wPhiEtaAxis is on the RHS, becase I defined ordering of cfRebinSparse by using ordering in eDiffPhiWeights + ph.fRebinSparse[eDWEta][wEtaPtAxis] = lRebinSparse[wPhiPtAxis]; + ph.fRebinSparse[eDWEta][wEtaChargeAxis] = lRebinSparse[wPhiChargeAxis]; + ph.fRebinSparse[eDWEta][wEtaCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + // ... + + ph.fRebinSparse[eDWCharge][wChargeChargeAxis] = lRebinSparse[wPhiChargeAxis]; // yes, wPhiChargeAxis is on the RHS, becase I defined ordering of cfRebinSparse by using ordering in eDiffPhiWeights + ph.fRebinSparse[eDWCharge][wChargePtAxis] = lRebinSparse[wPhiPtAxis]; + ph.fRebinSparse[eDWCharge][wChargeEtaAxis] = lRebinSparse[wPhiEtaAxis]; + ph.fRebinSparse[eDWCharge][wChargeCentralityAxis] = lRebinSparse[wPhiCentralityAxis]; + // ... // *) Categories of sparse histograms: auto lBookParticleSparseHistograms = cf_ph.cfBookParticleSparseHistograms.value; // fill or not particulat category of sparse histograms @@ -1299,6 +1415,8 @@ void defaultBooking() LOGF(fatal, "in function \033[1;31m%s at line %d Mismatch in the number of flags in configurable cfBookParticleSparseHistograms, and number of entries in enum eDiffWeightCategory_N \n \033[0m", __FUNCTION__, __LINE__); } + ph.fFillParticleSparseHistogramsBeforeCuts = cf_ph.cfFillParticleSparseHistogramsBeforeCuts; + // *) Insanity check on the content and ordering in the initialization in configurable cfBookParticleSparseHistograms: // TBI 20241109 I do not need this in fact, I can automate initialization even without ordering in configurable, but it feels with the ordering enforced, it's much safer. // Algorithm: From [01]-DWPhi I tokenize with respect to "-" the 2nd field, and check if e.g. fParticleSparseHistogramsName_DWPhi ends with it. @@ -1316,6 +1434,7 @@ void defaultBooking() ph.fBookParticleSparseHistograms[eDWPhi] = Alright(lBookParticleSparseHistograms[eDWPhi]); ph.fBookParticleSparseHistograms[eDWPt] = Alright(lBookParticleSparseHistograms[eDWPt]); ph.fBookParticleSparseHistograms[eDWEta] = Alright(lBookParticleSparseHistograms[eDWEta]); + ph.fBookParticleSparseHistograms[eDWCharge] = Alright(lBookParticleSparseHistograms[eDWCharge]); // f) QA: @@ -1548,8 +1667,11 @@ void defaultBinning() // Default binning for all histograms. // TBI 20240114 If some of these values are going to change frequently, add support for them in MuPa-Configurables.h, - // in the same way I did it for defaultCuts(). - // At the moment, I added to configurables support only for binning of sparse histograms, because there memory managment is critical. + // in the same way I did it for defaultCuts(). + // TBI 20260223 If ever I will add also support for variable-length binning for control histograms, re-think first what I did in the + // booking of sparse histograms, because the code there hinges on the usage of fixed-length binning and the usage of + // configurable cfRebinSparse. But I doubt I will even need here variable-length binning, I have always rebin in such a way + // all control histograms in offline postprocessing. // a) Default binning for event histograms; // b) Default binning for particle histograms 1D; @@ -1625,11 +1747,11 @@ void defaultBinning() ph.fParticleHistogramsBins[ePt][0] = 2000; ph.fParticleHistogramsBins[ePt][1] = 0.; - ph.fParticleHistogramsBins[ePt][2] = 200.; + ph.fParticleHistogramsBins[ePt][2] = 20.; - ph.fParticleHistogramsBins[eEta][0] = 500; - ph.fParticleHistogramsBins[eEta][1] = -5.; - ph.fParticleHistogramsBins[eEta][2] = 5.; + ph.fParticleHistogramsBins[eEta][0] = 400; + ph.fParticleHistogramsBins[eEta][1] = -2.; + ph.fParticleHistogramsBins[eEta][2] = 2.; ph.fParticleHistogramsBins[eCharge][0] = 7; ph.fParticleHistogramsBins[eCharge][1] = -3.5; // anticipating I might be storing charge of Delta++, etc. @@ -1774,6 +1896,7 @@ void defaultBinning() // *) Binning vs. particle charge => binning is always the same nBins = 2 in (-2.,2), so that the center of bins is at +/- 1: // Therefore, I shall never initialize or set for ill-defined cases the charge to 0., because when filling, that one will go to bin for +1 charge ("lower boundary included"). + // Keep in sync with Configurable> cfCharge{ ... res.fResultsProBinEdges[AFO_CHARGE] = new TArrayD(3); res.fResultsProBinEdges[AFO_CHARGE]->AddAt(-2., 0); res.fResultsProBinEdges[AFO_CHARGE]->AddAt(0., 1); @@ -2838,7 +2961,7 @@ void insanityChecksBeforeBooking() } // **) Enforce that if the fixed number of randomly selected tracks is used that Toy NUA is disabled: - if (tc.fFixedNumberOfRandomlySelectedTracks > 0 && (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF])) { + if (tc.fFixedNumberOfRandomlySelectedTracks > 0 && (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF])) { LOGF(fatal, "\033[1;31m%s at line %d : Not supported at the moment: use FixedNumberOfRandomlySelectedTracks + Toy NUA enabled.\nI cannot in an easy way ensure that ParticleCuts behave exactly the same in the Main and Banishment loops, because e.g. I call consequtively for same partcile gRandom->Uniform(...) in ParticleCuts, and that can't work.\033[0m", __FUNCTION__, __LINE__); } @@ -2932,6 +3055,9 @@ void insanityChecksBeforeBooking() if (eDiffEtaWeights_N > gMaxNumberSparseDimensions) { LOGF(fatal, "\033[1;31m%s at line %d : set eDiffEtaWeights_N = %d is bigger than gMaxNumberSparseDimensions = %d\033[0m", __FUNCTION__, __LINE__, static_cast(eDiffEtaWeights_N), gMaxNumberSparseDimensions); } + if (eDiffChargeWeights_N > gMaxNumberSparseDimensions) { + LOGF(fatal, "\033[1;31m%s at line %d : set eDiffChargeWeights_N = %d is bigger than gMaxNumberSparseDimensions = %d\033[0m", __FUNCTION__, __LINE__, static_cast(eDiffChargeWeights_N), gMaxNumberSparseDimensions); + } // ** For simulated data when fDatabasePDG is NOT used, I have to disable cut on charge, since that info is not available: if ((tc.fProcess[eGenericRecSim] || tc.fProcess[eGenericSim]) && pc.fUseParticleCuts[eCharge] && !tc.fUseDatabasePDG) { @@ -3206,7 +3332,10 @@ void insanityChecksBeforeBooking() if (!(iv.fHarmonicsOptionInternalValidation->EqualTo("constant", TString::kIgnoreCase) || iv.fHarmonicsOptionInternalValidation->EqualTo("correlated", TString::kIgnoreCase) || - iv.fHarmonicsOptionInternalValidation->EqualTo("persistent", TString::kIgnoreCase))) { + iv.fHarmonicsOptionInternalValidation->EqualTo("persistent", TString::kIgnoreCase) || + iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent", TString::kIgnoreCase) || + iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent", TString::kIgnoreCase) || + iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent", TString::kIgnoreCase))) { LOGF(fatal, "\033[1;31m%s at line %d : fHarmonicsOptionInternalValidation = %s is not supported. \033[0m", __FUNCTION__, __LINE__, iv.fHarmonicsOptionInternalValidation->Data()); } @@ -3218,6 +3347,18 @@ void insanityChecksBeforeBooking() LOGF(fatal, "\033[1;31m%s at line %d : in IV eMultiplicityEstimator cannot be set to \"ReferenceMultiplicity\" (yet) \033[0m", __FUNCTION__, __LINE__); } + if (!tc.fCalculateAsFunctionOf[AFO_PT] && pc.fUseParticleCuts[ePt]) { + LOGF(fatal, "\033[1;31m%s at line %d : in IV you do not calculate vs pt, but the cut on pt is on in IV\033[0m", __FUNCTION__, __LINE__); + } + + if (!tc.fCalculateAsFunctionOf[AFO_ETA] && pc.fUseParticleCuts[eEta]) { + LOGF(fatal, "\033[1;31m%s at line %d : in IV you do not calculate vs eta, but the cut on eta is on in IV\033[0m", __FUNCTION__, __LINE__); + } + + if (!tc.fCalculateAsFunctionOf[AFO_CHARGE] && pc.fUseParticleCuts[eCharge]) { + LOGF(fatal, "\033[1;31m%s at line %d : in IV you do not calculate vs charge, but the cut on charge is on in IV\033[0m", __FUNCTION__, __LINE__); + } + } // if (iv.fUseInternalValidation) { // h) Insanity checks on results histograms: @@ -3249,6 +3390,7 @@ void insanityChecksAfterBooking() // a) Insanity checks on booking; // b) Insanity checks on internal validation; + // c) Insanity checks on results histograms; // ... if (tc.fVerbose) { @@ -3277,6 +3419,15 @@ void insanityChecksAfterBooking() if (iv.fRescaleWithTheoreticalInput && iv.fHarmonicsOptionInternalValidation->EqualTo("persistent")) { LOGF(fatal, "\033[1;31m%s at line %d : rescaling with theoretical input doesn't make sanse for fHarmonicsOptionInternalValidation = \"persistent\". \033[0m", __FUNCTION__, __LINE__); } + if (iv.fRescaleWithTheoreticalInput && iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent")) { + LOGF(fatal, "\033[1;31m%s at line %d : rescaling with theoretical input doesn't make sanse for fHarmonicsOptionInternalValidation = \"ptDependent\". \033[0m", __FUNCTION__, __LINE__); + } + if (iv.fRescaleWithTheoreticalInput && iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { + LOGF(fatal, "\033[1;31m%s at line %d : rescaling with theoretical input doesn't make sanse for fHarmonicsOptionInternalValidation = \"ptEtaDependent\". \033[0m", __FUNCTION__, __LINE__); + } + if (iv.fRescaleWithTheoreticalInput && iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + LOGF(fatal, "\033[1;31m%s at line %d : rescaling with theoretical input doesn't make sanse for fHarmonicsOptionInternalValidation = \"ptEtaChargeDependent\". \033[0m", __FUNCTION__, __LINE__); + } // **) Print a warning if this histogram is not booked: if (!eh.fEventHistograms[eNumberOfEvents][eSim][eAfter]) { @@ -3285,6 +3436,25 @@ void insanityChecksAfterBooking() } // end of if (iv.fUseInternalValidation) { + // c) Insanity checks on results histograms: + for (int AFO_1D = 0; AFO_1D < eAsFunctionOf_N; AFO_1D++) { + if (tc.fCalculateAsFunctionOf[AFO_1D] && !res.fResultsPro[AFO_1D]) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_1D = %d , fResultsPro profiles are not booked for this case \033[0m", __FUNCTION__, __LINE__, AFO_1D); + } + } + + for (int AFO_2D = 0; AFO_2D < eAsFunctionOf2D_N; AFO_2D++) { + if (tc.fCalculate2DAsFunctionOf[AFO_2D] && !res.fResultsPro2D[AFO_2D]) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_2D = %d , fResultsPro2D profiles are not booked for this case \033[0m", __FUNCTION__, __LINE__, AFO_2D); + } + } + + for (int AFO_3D = 0; AFO_3D < eAsFunctionOf3D_N; AFO_3D++) { + if (tc.fCalculate3DAsFunctionOf[AFO_3D] && !res.fResultsPro3D[AFO_3D]) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_3D = %d , fResultsPro3D profiles are not booked for this case \033[0m", __FUNCTION__, __LINE__, AFO_3D); + } + } + // ... if (tc.fVerbose) { @@ -3308,7 +3478,7 @@ void purgeAfterBooking() StartFunction(__FUNCTION__); } - return; // TBI 20250625 the code below is not ready yet, because I still use these 2D and 3D histos in in FillqvectorNdim(...) + return; // TBI 20250625 the code below is not ready yet, because I still use these 2D and 3D histos in FillqvectorNdim(...) // a) Purge results histograms and related objects: if (!res.fSaveResultsHistograms) { @@ -4947,8 +5117,8 @@ void bookParticleHistograms() // a) Book the profile holding flags; // b) Book specific particle histograms 1D; // c) Book specific particle histograms 2D; - // e) Default binning for particle sparse histograms (yes, here, see comments below); - // d) Book specific particle sparse histograms (n-dimensions). + // d) Default binning for particle sparse histograms (yes, here, see comments below); + // e) Book specific particle sparse histograms (n-dimensions). if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -5102,23 +5272,31 @@ void bookParticleHistograms() // eParticleHistograms // d) Default binning for particle sparse histograms: - // Remark 0: This requires the special treatment, because I re-use in some cases bins from results histograns. - // Therefore, I can do all this only after bookResultsHistograms() was already called. + // Remark 0: I am using binning from particle or event control histograms, and I can optionally make it coarser or finer via configurable array fRebinSparse. + // It is important to vary fRebinSparse as a part of systematics. Note that I can do additional rebinning offline when making weights, so keep it here + // as fine as possible. // Remark 1: I anticipate I will need them only when I need to calculate differential weights, therefore I couple them intentionally // with enum's for differential weights from very beginning. - // Remark 2: Whenever possible, I re-use binning from results histograms. + // Remark 2: Do NOT re-use binning from results histograms, here the bin widths cannot be varied as a part of systematics (see Remark 0 above); // Remark 3: For variable-length binning, for each dimension of THnSparse, I have to call SetBinEdges (see below). // Therefore, to facilitate the whole procedure, fixed-length bins which I implemented directly (e.g. for phi dimension, which I do not have in results histograms), // I convert also in arrays. For fixed-length bins in results histograms I do NOT have to do that, because for that case I call GetArray() in any case, which is // doing such conversion automatically. + // TBI 20260223 I didn't really check variable-length binning for sparse extensively, use only fixed-length binning for the time being. + // Remark 4: If I do not need particular dimension in sparse histogram, e.g. pt, in the config simply set + // "cfFixedLengthPtBins": {"values": ["1", "0.2", "5.0"]}, + // where lower and upper pt boundary must be the same as in the pt cut, defined via + // "cfPt": {"values": ["0.2","5.0"]}, + // Keep this convention in sync with what I am doing in the macro MakeWeightsFromSparse(...) + // Remark 5: Do not mix below eh.fEventHistograms and ph.fParticleHistograms // **) eDiffWeightCategory = eDWPhi: TAxis* lAxis = NULL; // local helper TAxis, to convert in one line the booking of fixed-length array into array of corresponding bin edges - // ***) phi-axis for diff phi weights: at the moment I support only fixed-length binning, which optionally can be made finer or coarser with ph.fRebinSparse configurable: - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis] = static_cast(180. / ph.fRebinSparse); - lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis], 0., o2::constants::math::TwoPI); + // ***) phi-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis] = static_cast(ph.fParticleHistogramsBins[ePhi][0] / ph.fRebinSparse[eDWPhi][wPhiPhiAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis], ph.fParticleHistogramsBins[ePhi][1], ph.fParticleHistogramsBins[ePhi][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPhiAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPhiAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPhiAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); @@ -5127,170 +5305,207 @@ void bookParticleHistograms() delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPhiAxis] = FancyFormatting("Phi"); - // ***) pt-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_PT]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_PT] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis] = res.fResultsPro[AFO_PT]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_PT]->GetXaxis(); + // ***) pt-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWPhi][wPhiPtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPtAxis] = FancyFormatting("Pt"); - // ***) eta-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_ETA]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_ETA] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis] = res.fResultsPro[AFO_ETA]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_ETA]->GetXaxis(); + // ***) eta-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWPhi][wPhiEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiEtaAxis] = FancyFormatting("Eta"); - // ***) charge-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CHARGE]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + // ***) charge-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWPhi][wPhiChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CENTRALITY]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + // ***) centrality-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWPhi][wPhiCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. - // ***) VertexZ-axis for diff phi weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_VZ]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_VZ] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis] = res.fResultsPro[AFO_VZ]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_VZ]->GetXaxis(); + // ***) VertexZ-axis for diff phi weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis] = static_cast(eh.fEventHistogramsBins[eVertexZ][0] / ph.fRebinSparse[eDWPhi][wPhiVertexZAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis], eh.fEventHistogramsBins[eVertexZ][1], eh.fEventHistogramsBins[eVertexZ][2]); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) - ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiVertexZAxis] = "VertexZ"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiVertexZAxis] = "VertexZ"; // ... // **) eDiffWeightCategory = eDWPt: - // ***) pt-axis for diff pt weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_PT]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_PT] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis] = res.fResultsPro[AFO_PT]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_PT]->GetXaxis(); + // ***) pt-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWPt][wPtPtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtPtAxis] = FancyFormatting("Pt"); - // ***) charge-axis for diff pt weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CHARGE]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + // ***) eta-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWPt][wPtEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtEtaAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } - ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtEtaAxis] = FancyFormatting("Eta"); + + // ***) charge-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWPt][wPtChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff pt weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CENTRALITY]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + // ***) centrality-axis for diff pt weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWPt][wPtCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. // ... // **) eDiffWeightCategory = eDWEta: - // ***) eta-axis for diff eta weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_ETA]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_ETA] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis] = res.fResultsPro[AFO_ETA]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_ETA]->GetXaxis(); + // ***) eta-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWEta][wEtaEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaEtaAxis] = FancyFormatting("Eta"); - // ***) charge-axis for diff eta weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CHARGE]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + // ***) pt-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaPtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWEta][wEtaPtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaPtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaPtAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaPtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } - ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaPtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaPtAxis] = FancyFormatting("Pt"); + + // ***) charge-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWEta][wEtaChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff eta weights - I re-use binning from results histograms: - if (!res.fResultsPro[AFO_CENTRALITY]) { - LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); - } - ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); - lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + // ***) centrality-axis for diff eta weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWEta][wEtaCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); } ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin - // delete lAxis; // I do not need to delete here, only when new TAxis(...) + delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. // ... + // **) eDiffWeightCategory = eDWCharge: + + // ***) charge-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeChargeAxis] = static_cast(ph.fParticleHistogramsBins[eCharge][0] / ph.fRebinSparse[eDWCharge][wChargeChargeAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeChargeAxis], ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeChargeAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargeChargeAxis] = FancyFormatting("charge"); + + // ***) pt-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargePtAxis] = static_cast(ph.fParticleHistogramsBins[ePt][0] / ph.fRebinSparse[eDWCharge][wChargePtAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargePtAxis], ph.fParticleHistogramsBins[ePt][1], ph.fParticleHistogramsBins[ePt][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargePtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargePtAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargePtAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargePtAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargePtAxis] = FancyFormatting("Pt"); + + // ***) eta-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeEtaAxis] = static_cast(ph.fParticleHistogramsBins[eEta][0] / ph.fRebinSparse[eDWCharge][wChargeEtaAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeEtaAxis], ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeEtaAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeEtaAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeEtaAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargeEtaAxis] = FancyFormatting("Eta"); + + // ***) centrality-axis for diff charge weights - at the moment I support only fixed-length binning from control histograms, which optionally can be made finer or coarser with cfRebinSparse configurable: + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeCentralityAxis] = static_cast(eh.fEventHistogramsBins[eCentrality][0] / ph.fRebinSparse[eDWCharge][wChargeCentralityAxis]); + lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeCentralityAxis], eh.fEventHistogramsBins[eCentrality][1], eh.fEventHistogramsBins[eCentrality][2]); + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWCharge][wChargeCentralityAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWCharge][wChargeCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + delete lAxis; + ph.fParticleSparseHistogramsAxisTitle[eDWCharge][wChargeCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. + + // ... + // e) Book specific particle sparse histograms (n-dimensions): if (ph.fBookParticleSparseHistograms[eDWPhi]) { BookParticleSparseHistograms(eDWPhi); @@ -5304,6 +5519,10 @@ void bookParticleHistograms() BookParticleSparseHistograms(eDWEta); } + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + BookParticleSparseHistograms(eDWCharge); + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -5335,6 +5554,10 @@ void BookParticleSparseHistograms(eDiffWeightCategory dwc) nDimensions = static_cast(eDiffEtaWeights_N); break; } + case eDWCharge: { + nDimensions = static_cast(eDiffChargeWeights_N); + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This differential weight category, dwc = %d, is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(dwc)); break; @@ -5353,17 +5576,28 @@ void BookParticleSparseHistograms(eDiffWeightCategory dwc) if (Skip(rs)) { continue; } - // Remark: Here I have a bit unusual convention for the name and title, but okay... - ph.fParticleSparseHistograms[dwc][rs] = new THnSparseF(TString::Format("%s[%s]", ph.fParticleSparseHistogramsName[dwc].Data(), gc.srs[rs].Data()), TString::Format("__RUN_NUMBER__, %s, %s", gc.srsLong[rs].Data(), ph.fParticleSparseHistogramsTitle[dwc].Data()), nDimensions, nBins->GetArray(), NULL, NULL); - // *) For each dimension set bin edges, axis title, etc.: - for (int d = 0; d < nDimensions; d++) { - ph.fParticleSparseHistograms[dwc][rs]->SetBinEdges(d, ph.fParticleSparseHistogramsBinEdges[dwc][d]->GetArray()); - ph.fParticleSparseHistograms[dwc][rs]->GetAxis(d)->SetTitle(ph.fParticleSparseHistogramsAxisTitle[dwc][d].Data()); - } + for (int ba = 0; ba < 2; ba++) // before/after cuts + { + + if (eBefore == ba && !ph.fFillParticleSparseHistogramsBeforeCuts) { + continue; + } + + // Remark: Here I have a bit unusual convention for the name and title, but okay... + ph.fParticleSparseHistograms[dwc][rs][ba] = new THnSparseF(TString::Format("%s[%s][%s]", ph.fParticleSparseHistogramsName[dwc].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), TString::Format("__RUN_NUMBER__, %s, %s, %s", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data(), ph.fParticleSparseHistogramsTitle[dwc].Data()), nDimensions, nBins->GetArray(), NULL, NULL); + + // *) For each dimension set bin edges, axis title, etc.: + for (int d = 0; d < nDimensions; d++) { + ph.fParticleSparseHistograms[dwc][rs][ba]->SetBinEdges(d, ph.fParticleSparseHistogramsBinEdges[dwc][d]->GetArray()); + ph.fParticleSparseHistograms[dwc][rs][ba]->GetAxis(d)->SetTitle(ph.fParticleSparseHistogramsAxisTitle[dwc][d].Data()); + } + + // *) Finally, add the fully configured THnSparse to its TList: + ph.fParticleHistogramsList->Add(ph.fParticleSparseHistograms[dwc][rs][ba]); + + } // for (int ba = 0; ba < 2; ba++) // before/after cuts - // *) Finally, add the fully configured THnSparse to its TList: - ph.fParticleHistogramsList->Add(ph.fParticleSparseHistograms[dwc][rs]); } // for (int rs = 0; rs < 2; rs++) // reco/sim // *) Clean up: @@ -5878,7 +6112,7 @@ void bookWeightsHistograms() } // a) Book the profile holding flags: - pw.fWeightsFlagsPro = new TProfile("fWeightsFlagsPro", "flags for particle weights", 13, 0., 13.); + pw.fWeightsFlagsPro = new TProfile("fWeightsFlagsPro", "flags for particle weights", 23, 0., 23.); pw.fWeightsFlagsPro->SetStats(false); pw.fWeightsFlagsPro->SetLineColor(eColor); pw.fWeightsFlagsPro->SetFillColor(eFillColor); @@ -5892,7 +6126,7 @@ void bookWeightsHistograms() pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(4, "(w_{#varphi})_{| p_{T}}"); // TBI 20241019 not sure if this is the final notation, keep in sync with void SetDiffWeightsHist(...) pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(5, "(w_{#varphi})_{| #eta}"); // TBI 20241019 not sure if this is the final notation, keep in sync with void SetDiffWeightsHist(...) - // **) differential phi weights using sparse: + // **) differential phi weights using sparse (keep in sync with enum eDiffPhiWeights): pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(6, "(w_{#varphi})_{phi axis (sparse)}"); pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(7, "(w_{#varphi})_{p_{T} axis (sparse)}"); pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(8, "(w_{#varphi})_{#eta axis (sparse)}"); @@ -5900,11 +6134,23 @@ void bookWeightsHistograms() pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(10, "(w_{#varphi})_{centrality axis (sparse)}"); pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(11, "(w_{#varphi})_{VertexZ axis (sparse)}"); - // **) differential pt weights using sparse: + // **) differential pt weights using sparse (keep in sync with enum eDiffPtWeights): pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(12, "(w_{p_{T}})_{pt axis (sparse)}"); - - // **) differential eta weights using sparse: - pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(13, "(w_{#eta})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(13, "(w_{p_{T}})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(14, "(w_{p_{T}})_{charge axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(15, "(w_{p_{T}})_{centrality axis (sparse)}"); + + // **) differential eta weights using sparse (keep in sync with enum eDiffEtaWeights): + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(16, "(w_{#eta})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(17, "(w_{#eta})_{pt axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(18, "(w_{#eta})_{charge axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(19, "(w_{#eta})_{centrality axis (sparse)}"); + + // **) differential charge weights using sparse (keep in sync with enum eDiffChargeWeights): + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(20, "(w_{charge})_{charge axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(21, "(w_{charge})_{pt axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(22, "(w_{charge})_{eta axis (sparse)}"); + pw.fWeightsFlagsPro->GetXaxis()->SetBinLabel(23, "(w_{charge})_{centrality axis (sparse)}"); } else { @@ -5917,7 +6163,7 @@ void bookWeightsHistograms() yAxisTitle += TString::Format("%d:(w_{#varphi})_{| p_{T}}; ", 4); yAxisTitle += TString::Format("%d:(w_{#varphi})_{| #eta}; ", 5); - // **) differential phi weights using sparse: + // **) differential phi weights using sparse (keep in sync with enum eDiffPhiWeights): yAxisTitle += TString::Format("%d:(w_{#varphi})_{phi axis (sparse)}; ", 6); yAxisTitle += TString::Format("%d:(w_{#varphi})_{p_{T} axis (sparse)}; ", 7); yAxisTitle += TString::Format("%d:(w_{#varphi})_{#eta axis (sparse)}; ", 8); @@ -5925,11 +6171,23 @@ void bookWeightsHistograms() yAxisTitle += TString::Format("%d:(w_{#varphi})_{centrality axis (sparse)}; ", 10); yAxisTitle += TString::Format("%d:(w_{#varphi})_{VertexZ axis (sparse)}; ", 11); - // **) differential pt weights using sparse: + // **) differential pt weights using sparse (keep in sync with enum eDiffPtWeights): yAxisTitle += TString::Format("%d:(w_{p_{T}})_{pt axis (sparse)}; ", 12); - - // **) differential eta weights using sparse: - yAxisTitle += TString::Format("%d:(w_{#eta})_{eta axis (sparse)}; ", 13); + yAxisTitle += TString::Format("%d:(w_{p_{T}})_{eta axis (sparse)}; ", 13); + yAxisTitle += TString::Format("%d:(w_{p_{T}})_{charge axis (sparse)}; ", 14); + yAxisTitle += TString::Format("%d:(w_{p_{T}})_{centrality axis (sparse)}; ", 15); + + // **) differential eta weights using sparse (keep in sync with enum eDiffEtaWeights): + yAxisTitle += TString::Format("%d:(w_{#eta})_{eta axis (sparse)}; ", 16); + yAxisTitle += TString::Format("%d:(w_{#eta})_{pt axis (sparse)}; ", 17); + yAxisTitle += TString::Format("%d:(w_{#eta})_{charge axis (sparse)}; ", 18); + yAxisTitle += TString::Format("%d:(w_{#eta})_{centrality axis (sparse)}; ", 19); + + // **) differential charge weights using sparse (keep in sync with enum eDiffChargeWeights): + yAxisTitle += TString::Format("%d:(w_{charge})_{charge axis (sparse)}; ", 20); + yAxisTitle += TString::Format("%d:(w_{charge})_{pt axis (sparse)}; ", 21); + yAxisTitle += TString::Format("%d:(w_{charge})_{eta axis (sparse)}; ", 22); + yAxisTitle += TString::Format("%d:(w_{charge})_{centrality axis (sparse)}; ", 23); // ... @@ -5986,23 +6244,43 @@ void bookWeightsHistograms() if (pw.fUseDiffPtWeights[wPtPtAxis]) { pw.fWeightsFlagsPro->Fill(11.5, 1.); } - if (pw.fUseDiffPhiWeights[wPtChargeAxis]) { + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { pw.fWeightsFlagsPro->Fill(12.5, 1.); } - if (pw.fUseDiffPhiWeights[wPtCentralityAxis]) { + if (pw.fUseDiffPtWeights[wPtChargeAxis]) { pw.fWeightsFlagsPro->Fill(13.5, 1.); } + if (pw.fUseDiffPtWeights[wPtCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(14.5, 1.); + } // **) differential eta weights using sparse: if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - pw.fWeightsFlagsPro->Fill(14.5, 1.); - } - if (pw.fUseDiffPhiWeights[wEtaChargeAxis]) { pw.fWeightsFlagsPro->Fill(15.5, 1.); } - if (pw.fUseDiffPhiWeights[wEtaCentralityAxis]) { + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { pw.fWeightsFlagsPro->Fill(16.5, 1.); } + if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + pw.fWeightsFlagsPro->Fill(17.5, 1.); + } + if (pw.fUseDiffEtaWeights[wEtaCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(18.5, 1.); + } + + // **) differential charge weights using sparse: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + pw.fWeightsFlagsPro->Fill(19.5, 1.); + } + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + pw.fWeightsFlagsPro->Fill(20.5, 1.); + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + pw.fWeightsFlagsPro->Fill(21.5, 1.); + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(22.5, 1.); + } pw.fWeightsList->Add(pw.fWeightsFlagsPro); @@ -6324,20 +6602,22 @@ void bookNUAHistograms() } // a) Book the profile holding flags: - nua.fNUAFlagsPro = new TProfile("fNUAFlagsPro", "flags for Toy NUA", 6, 0.5, 6.5); + nua.fNUAFlagsPro = new TProfile("fNUAFlagsPro", "flags for Toy NUA", 8, 0.5, 8.5); nua.fNUAFlagsPro->SetStats(false); nua.fNUAFlagsPro->SetLineColor(eColor); nua.fNUAFlagsPro->SetFillColor(eFillColor); nua.fNUAFlagsPro->GetXaxis()->SetLabelSize(0.03); - // TBI 20240429 the binning below is a bit fragile, but ok... + // TBI 20260312 the binning below is a bit fragile, but ok... if (tc.fUseSetBinLabel) { nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + ePhiNUAPDF), "fApplyNUAPDF[phi]"); nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + ePtNUAPDF), "fApplyNUAPDF[pt]"); nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + eEtaNUAPDF), "fApplyNUAPDF[eta]"); - nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(4 + ePhiNUAPDF), "fUseDefaultNUAPDF[phi]"); - nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(4 + ePtNUAPDF), "fUseDefaultNUAPDF[pt]"); - nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(4 + eEtaNUAPDF), "fUseDefaultNUAPDF[eta]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(1 + eChargeNUAPDF), "fApplyNUAPDF[charge]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + ePhiNUAPDF), "fUseDefaultNUAPDF[phi]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + ePtNUAPDF), "fUseDefaultNUAPDF[pt]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + eEtaNUAPDF), "fUseDefaultNUAPDF[eta]"); + nua.fNUAFlagsPro->GetXaxis()->SetBinLabel(static_cast(5 + eChargeNUAPDF), "fUseDefaultNUAPDF[charge]"); // ... @@ -6349,9 +6629,11 @@ void bookNUAHistograms() yAxisTitle += TString::Format("%d:fApplyNUAPDF[phi]; ", static_cast(1 + ePhiNUAPDF)); yAxisTitle += TString::Format("%d:fApplyNUAPDF[pt]; ", static_cast(1 + ePtNUAPDF)); yAxisTitle += TString::Format("%d:fApplyNUAPDF[eta]; ", static_cast(1 + eEtaNUAPDF)); - yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[phi]; ", static_cast(4 + ePhiNUAPDF)); - yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[pt]; ", static_cast(4 + ePtNUAPDF)); - yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[eta]; ", static_cast(4 + eEtaNUAPDF)); + yAxisTitle += TString::Format("%d:fApplyNUAPDF[charge]; ", static_cast(1 + eChargeNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[phi]; ", static_cast(5 + ePhiNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[pt]; ", static_cast(5 + ePtNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[eta]; ", static_cast(5 + eEtaNUAPDF)); + yAxisTitle += TString::Format("%d:fUseDefaultNUAPDF[charge]; ", static_cast(5 + eChargeNUAPDF)); // ... @@ -6378,26 +6660,32 @@ void bookNUAHistograms() if (nua.fApplyNUAPDF[eEtaNUAPDF]) { nua.fNUAFlagsPro->Fill(static_cast(1 + eEtaNUAPDF), 1.); } + if (nua.fApplyNUAPDF[eChargeNUAPDF]) { + nua.fNUAFlagsPro->Fill(static_cast(1 + eChargeNUAPDF), 1.); + } if (nua.fUseDefaultNUAPDF[ePhiNUAPDF]) { - nua.fNUAFlagsPro->Fill(static_cast(4 + ePhiNUAPDF), 1.); + nua.fNUAFlagsPro->Fill(static_cast(5 + ePhiNUAPDF), 1.); } if (nua.fUseDefaultNUAPDF[ePtNUAPDF]) { - nua.fNUAFlagsPro->Fill(static_cast(4 + ePtNUAPDF), 1.); + nua.fNUAFlagsPro->Fill(static_cast(5 + ePtNUAPDF), 1.); } if (nua.fUseDefaultNUAPDF[eEtaNUAPDF]) { - nua.fNUAFlagsPro->Fill(static_cast(4 + eEtaNUAPDF), 1.); + nua.fNUAFlagsPro->Fill(static_cast(5 + eEtaNUAPDF), 1.); + } + if (nua.fUseDefaultNUAPDF[eChargeNUAPDF]) { + nua.fNUAFlagsPro->Fill(static_cast(5 + eChargeNUAPDF), 1.); } nua.fNUAList->Add(nua.fNUAFlagsPro); - if (!(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF])) { + if (!(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF])) { return; } // b) Common local labels: - TString sVariable[eNUAPDF_N] = {"#varphi", "p_{t}", "#eta"}; // has to be in sync with the ordering of enum eNUAPDF + TString sVariable[eNUAPDF_N] = {"#varphi", "p_{t}", "#eta", "charge"}; // has to be in sync with the ordering of enum eNUAPDF // c) Histograms: - for (int pdf = 0; pdf < eNUAPDF_N; pdf++) // use pdfs for NUA in (phi, pt, eta, ...) + for (int pdf = 0; pdf < eNUAPDF_N; pdf++) // use pdfs for NUA in (phi, pt, eta, charge, ...) { if (!nua.fCustomNUAPDF[pdf]) // yes, because these histos are cloned from the external ones, see void SetNUAPDF(TH1D* const hist, const char* variable); { @@ -6444,15 +6732,30 @@ void bookNUAHistograms() if (!nua.fApplyNUAPDF[eEtaNUAPDF]) { continue; } - // Define default detector acceptance in pseudorapidity: One sectors, with probability < 1. - double dSector[2] = {2.0, 2.5}; // sector is defined as 0.5 < eta < 1.0 - double dProbability = 0.5; // probability, so after being set this way, only 50% of particles in that sector are reconstructed + // Define default detector acceptance in pseudorapidity: One sector, with probability < 1. + double dSector[2] = {0.2, 0.6}; // sector is defined as 0.2 < eta < 0.6 + double dProbability = 0.2; // probability, so after being set this way, only 20% of particles in that sector are reconstructed nua.fDefaultNUAPDF[eEtaNUAPDF] = new TF1(TString::Format("fDefaultNUAPDF[%d]", eEtaNUAPDF), "1.-(x>=[0])*(1.-[2]) + (x>=[1])*(1.-[2])", ph.fParticleHistogramsBins[eEta][1], ph.fParticleHistogramsBins[eEta][2]); nua.fDefaultNUAPDF[eEtaNUAPDF]->SetParameter(0, dSector[0]); nua.fDefaultNUAPDF[eEtaNUAPDF]->SetParameter(1, dSector[1]); nua.fDefaultNUAPDF[eEtaNUAPDF]->SetParameter(2, dProbability); nua.fNUAList->Add(nua.fDefaultNUAPDF[eEtaNUAPDF]); + } else if (sVariable[pdf].EqualTo("charge")) { + + // *) default NUA for charge pdf: + if (!nua.fApplyNUAPDF[eChargeNUAPDF]) { + continue; + } + // Define default detector acceptance in charge: Particles with negative charge, I take with probability 50% + double dSector[2] = {-1., 0.}; // nua sector is defined for charge in the range -1. < charge < 0. + double dProbability = 0.5; // probability, so after being set this way, only 50% of particles in that sector are reconstructed + nua.fDefaultNUAPDF[eChargeNUAPDF] = new TF1(TString::Format("fDefaultNUAPDF[%d]", eChargeNUAPDF), "1.-(x>=[0])*(1.-[2]) + (x>=[1])*(1.-[2])", + ph.fParticleHistogramsBins[eCharge][1], ph.fParticleHistogramsBins[eCharge][2]); + nua.fDefaultNUAPDF[eChargeNUAPDF]->SetParameter(0, dSector[0]); + nua.fDefaultNUAPDF[eChargeNUAPDF]->SetParameter(1, dSector[1]); + nua.fDefaultNUAPDF[eChargeNUAPDF]->SetParameter(2, dProbability); + nua.fNUAList->Add(nua.fDefaultNUAPDF[eChargeNUAPDF]); } else { LOGF(fatal, "\033[1;31m%s at line %d : pdf = %s is not supported (yet)\n \033[0m", __FUNCTION__, __LINE__, sVariable[pdf].Data()); } @@ -6467,7 +6770,7 @@ void bookNUAHistograms() nua.fNUAList->Add(nua.fCustomNUAPDF[pdf]); } // if(!nua.fCustomNUAPDF[pdf]) - // Get the max values of pdfs, so that later in Accept(...) there is no loss of efficiency, when would need to calculate the same thing for each particle: + // Get the max values of pdfs, so that later in Accept(...) there is no loss of efficiency, when I would need to calculate the same thing for each particle: if (!nua.fUseDefaultNUAPDF[pdf] && nua.fCustomNUAPDF[pdf]) { // pdf is a loop variable // custom, user-provided pdf via TH1D object: nua.fMaxValuePDF[pdf] = nua.fCustomNUAPDF[pdf]->GetMaximum(); @@ -6476,7 +6779,7 @@ void bookNUAHistograms() nua.fMaxValuePDF[pdf] = nua.fDefaultNUAPDF[pdf]->GetMaximum(ph.fParticleHistogramsBins[pdf][1], ph.fParticleHistogramsBins[pdf][2]); } - } // for(int pdf=0;pdf check further // *) Set and propagate some fake run number; // *) Fetch the weights for this particular run number. Do it only once; @@ -6693,21 +6999,29 @@ void InternalValidation() } // differential pt weights: - if (pw.fUseDiffPhiWeights[wPtPtAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential pt weights by setting 0-wPt in config. - // On the other hand, it doesn't make sense to calculate differential pt weights without having pt axis. - // At any point I shall be able to fall back to integrated pt weights, that corresponds to the case wheh "1-wPt" and all others are "0-w..." + if (pw.fUseDiffPtWeights[wPtPtAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential pt weights by setting 0-wPt in config. + // On the other hand, it doesn't make sense to calculate differential pt weights without having pt axis. + // At any point I shall be able to fall back to integrated pt weights, that corresponds to the case wheh "1-wPt" and all others are "0-w..." GetParticleWeights(); pw.fParticleWeightsAreFetched = true; } // differential eta weights: - if (pw.fUseDiffPhiWeights[wEtaEtaAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential eta weights by setting 0-wEta in config. + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential eta weights by setting 0-wEta in config. // On the other hand, it doesn't make sense to calculate differential eta weights without having eta axis. // At any point I shall be able to fall back to integrated eta weights, that corresponds to the case wheh "1-wEta" and all others are "0-w..." GetParticleWeights(); pw.fParticleWeightsAreFetched = true; } + // differential charge weights: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential Charge weights by setting 0-wCharge in config. + // On the other hand, it doesn't make sense to calculate differential charge weights without having charge axis. + // At any point I shall be able to fall back to integrated charge weights, that corresponds to the case wheh "1-wCharge" and all others are "0-w..." + GetParticleWeights(); + pw.fParticleWeightsAreFetched = true; + } + } // if (!pw.fParticleWeightsAreFetched) { // a) Fourier like p.d.f. for azimuthal angles and flow amplitudes: @@ -6716,7 +7030,7 @@ void InternalValidation() if (iv.fHarmonicsOptionInternalValidation->EqualTo("constant")) { // For this option, vn's and psin's are constant for all simulated events, therefore I can configure fPhiPDF outside of loop over events. - // Remark: The last parameter [18] is a random reaction plane, keep in sync with fPhiPDF->SetParameter(18,fReactionPlane); below + // Remark: The last parameter [18] is a random reaction plane, keep in sync with fPhiPDF->SetParameter(18,fReactionPlane); below. // Keep also in sync with const int gMaxHarmonic = 9; in *GlobalConstants.h fPhiPDF = new TF1("fPhiPDF", "1 + 2.*[0]*std::cos(x-[1]-[18]) + 2.*[2]*std::cos(2.*(x-[3]-[18])) + 2.*[4]*std::cos(3.*(x-[5]-[18])) + 2.*[6]*std::cos(4.*(x-[7]-[18])) + 2.*[8]*std::cos(5.*(x-[9]-[18])) + 2.*[10]*std::cos(6.*(x-[11]-[18])) + 2.*[12]*std::cos(7.*(x-[13]-[18])) + 2.*[14]*std::cos(8.*(x-[15]-[18])) + 2.*[16]*std::cos(9.*(x-[17]-[18]))", 0., o2::constants::math::TwoPI); for (int h = 0; h < gMaxHarmonic; h++) { @@ -6745,7 +7059,7 @@ void InternalValidation() LOGF(info, "Remark: Parameter [18] at the moment is reaction plane.\n"); } // if (tc.fVerbose) { - } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("correlated")) { // if(iv.fHarmonicsOptionInternalValidation->EqualTo("constant")) + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("correlated")) { // For this option, three selected vn's (v1,v2,v3) are correlated, and all psin's are set to zero, for simplicity. // Remark: The last parameter [3] is a random reaction plane, keep in sync with fPhiPDF->SetParameter(3,fReactionPlane); below // Keep also in sync with const int gMaxHarmonic = 9; in *GlobalConstants.h @@ -6767,7 +7081,7 @@ void InternalValidation() // check for example message 'W-TF3::GetRandom3: function:fvnPDF has 27000 negative values: abs assumed' in the log file // All the amplitudes v1, v2 and v3, and RP are determined e-b-e, and then set in fPhiPDF below - } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("persistent")) { // if(iv.fHarmonicsOptionInternalValidation->EqualTo("persistent")) + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("persistent")) { // For this option, three selected vn's (v1,v2,v3) are correlated in the same way as in "correlated" case, but in addition, the persistent // non-vanishing correlation among SPCs Psi1, Psi2 and Psi3 is introduced, in the same way as in arXiv:1901.06968, Sec. II D. @@ -6795,7 +7109,58 @@ void InternalValidation() fvnPDF = new TF3("fvnPDF", "x + 2.*y - 3.*z", 0.07, 0.08, 0.06, 0.07, 0.05, 0.06); // v1 \in [0.07,0.08], v2 \in [0.06,0.07], v3 \in [0.05,0.06] // check for example message 'W-TF3::GetRandom3: function:fvnPDF has 27000 negative values: abs assumed' in the log file // All the amplitudes v1, v2 and v3, and symmetry planes Psi_{1}, Psi_{2} and Psi_{3} are determined e-b-e, and then set in fPhiPDF below - } // else if(fHarmonicsOptionInternalValidation->EqualTo("persistent")) + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent")) { + // For this option, one selected vn harmonic (v2) depends on pT, in the same way as defined in Eq. (32) in arXiv:1312.3572 + // I still use constant v1 = 0.04 and v3 = 0.06 in this example + one common reaction plane. + // For v2(pT), I am simply porting the legacy code from the class AliFlowEventSimpleMakerOnTheFly.cxx class from AliPhysics + + // Azimuthal angles are sampled from this pdf: + fPhiPDF = new TF1("fPhiPDF", "1 + 2.*[1]*std::cos(x-[0]) + 2.*[2]*std::cos(2.*(x-[0])) + 2.*[3]*std::cos(3.*(x-[0]))", 0., o2::constants::math::TwoPI); + // With this parameterization, I have: + // [0] => RP + // [1] => v1 + // [2] => v2(pt) + // [3] => v3 + fPhiPDF->SetParName(0, "RP"); + fPhiPDF->SetParName(1, "v_{1}"); + fPhiPDF->SetParName(2, "v_{2}(pt)"); + fPhiPDF->SetParName(3, "v_{3}"); + + // Set constant parameters here: + fPhiPDF->SetParameter(1, 0.04); // v1 = 0.04 = const in this parameterization + fPhiPDF->SetParameter(3, 0.06); // v3 = 0.06 = const in this parameterization + // Amplitude v2(pt) and reaction plane are pbyp set ebye in the loop below + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent") || iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + // a) "ptEtaDependent": + // For this option, one selected vn harmonic (v2) depends both on pT and eta. + // pt dependence is the same as defined in Eq. (32) in arXiv:1312.3572 + // eta dependence is defined as 0.4 - (1/4) eta^2, so that v2(eta) = 0.24 at eta = +-0.8, and v2(eta) = 0.4 at eta = 0 (keep in sync with details below, when I am sampling pt and eta) + // to increase significance, I multiply by factor of 2 the sampled v2(pt,eta) (see the formula below when sampling) + // I still use constant v1 = 0.04 and v3 = 0.06 in this example + one common reaction plane. + + // b) "ptEtaChargeDependent": + // For this option, one selected vn harmonic (v2) depends on pT, eta and charge. + // pt and eta dependence, and all other settings are the same as in the option "ptEtaDependent" + // The only difference in this option that for particles with positive charge, I downscale their v2 by 25%, i.e. v2(positive) = 0.75 v2 (negative), everything else is the same. + // Therefore, I can use the same config here both for "ptEtaDependent" and "ptEtaChargeDependent", the charge dependence I introduce later in the loop below + + // Azimuthal angles are sampled from this pdf: + fPhiPDF = new TF1("fPhiPDF", "1 + 2.*[1]*std::cos(x-[0]) + 2.*[2]*std::cos(2.*(x-[0])) + 2.*[3]*std::cos(3.*(x-[0]))", 0., o2::constants::math::TwoPI); + // With this parameterization, I have: + // [0] => RP + // [1] => v1 + // [2] => v2(pt) + // [3] => v3 + fPhiPDF->SetParName(0, "RP"); + fPhiPDF->SetParName(1, "v_{1}"); + fPhiPDF->SetParName(2, "v_{2}(pt,eta)"); + fPhiPDF->SetParName(3, "v_{3}"); + + // Set constant parameters here: + fPhiPDF->SetParameter(1, 0.04); // v1 = 0.04 = const in this parameterization + fPhiPDF->SetParameter(3, 0.06); // v3 = 0.06 = const in this parameterization + // Amplitude v2(pt,eta) for option "ptEtaDependent" and amplitude v2(pt,eta,charge) for option "ptEtaChargeDependent", and reaction plane are pbyp set ebye in the loop below + } // b) Loop over on-the-fly events: double v1 = 0., v2 = 0., v3 = 0.; @@ -6817,7 +7182,12 @@ void InternalValidation() fPhiPDF->SetParameter(18, fReactionPlane); } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("correlated")) { fPhiPDF->SetParameter(3, fReactionPlane); - } // Remark: I do not need here anything for option "persistent", because RP is not used for that case. See below how 3 symmetry planes are introduced with persistent correlation + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent")) { + fPhiPDF->SetParameter(0, fReactionPlane); + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent") || iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + fPhiPDF->SetParameter(0, fReactionPlane); + } + // Remark: I do not need here anything for option "persistent", because RP is not used for that case. See below how 3 symmetry planes are introduced with persistent correlation ebye.fCentrality = static_cast(gRandom->Uniform(0., 100.)); // this is perfectly fine for this exercise ebye.fOccupancy = static_cast(gRandom->Uniform(0., 10000.)); // this is perfectly fine for this exercise @@ -6874,11 +7244,6 @@ void InternalValidation() } // if(fHarmonicsOptionInternalValidation->EqualTo("persistent")) // b3) Loop over particles: - double dPhi = 0.; - double dPt = 0.; - double dEta = 0.; - double dCharge = -44.; // it has to be double, because below I use e.g. double kineArr[2] = {dPt, dCharge}; - // *) Define min and max ranges for sampling: double dPt_min = res.fResultsPro[AFO_PT]->GetXaxis()->GetBinLowEdge(1); // yes, low edge of first bin is pt min double dPt_max = res.fResultsPro[AFO_PT]->GetXaxis()->GetBinLowEdge(1 + res.fResultsPro[AFO_PT]->GetNbinsX()); // yes, low edge of overflow bin is max pt @@ -6886,15 +7251,14 @@ void InternalValidation() double dEta_max = res.fResultsPro[AFO_ETA]->GetXaxis()->GetBinLowEdge(1 + res.fResultsPro[AFO_ETA]->GetNbinsX()); // yes, low edge of overflow bin is max eta for (int p = 0; p < nMult; p++) { - // Particle angle: - dPhi = fPhiPDF->GetRandom(); + // Remark 0: I have to sample first pt, eta, charge, only then phi, because I allow the possibility that some harmonics depend on kinematics, e.g. v2(pt) or v2(pt,eta), etc. + // Remark 1: To increase performance, sample pt, eta or charge only if requested. - // *) To increase performance, sample pt, eta or charge only if requested: if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] || t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ] || t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { - dPt = gRandom->Uniform(dPt_min, dPt_max); + pbyp.fPt = gRandom->Uniform(dPt_min, dPt_max); } if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA] || es.fCalculateEtaSeparations || @@ -6902,41 +7266,127 @@ void InternalValidation() t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ] || t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { // Yes, I have to use here es.fCalculateEtaSeparations , and not some differential flag, like for pt case above - dEta = gRandom->Uniform(dEta_min, dEta_max); + pbyp.fEta = gRandom->Uniform(dEta_min, dEta_max); } if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE] || t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { - dCharge = (1 == gRandom->Integer(2) ? 1 : -1); // gRandom->Integer(2) samples either 0 or 1, then I cast 0 into -1 - if (tc.fInsanityCheckForEachParticle && std::abs(dCharge) != 1) { - LOGF(fatal, "\033[1;31m%s at line %d : dCharge = %d\033[0m", __FUNCTION__, __LINE__, dCharge); + pbyp.fCharge = (1 == gRandom->Integer(2) ? 1 : -1); // gRandom->Integer(2) samples either 0 or 1, then I cast 0 into -1 + if (tc.fInsanityCheckForEachParticle && std::abs(pbyp.fCharge) != 1) { + LOGF(fatal, "\033[1;31m%s at line %d : pbyp.fCharge = %d\033[0m", __FUNCTION__, __LINE__, pbyp.fCharge); + } + } + + // Finalize configuration of p.d.f. for azimuthal angles if harmonics are depending on particle kine variables: + if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptDependent")) { + float fV2vsPtCutOff = 2.0; // TBI 20250729 I could add configurables for these 2 variables at some point, otherwise, simply hardwire the constants in the expression below + float fV2vsPtMax = 0.3; + // v2(pt): for pt < fV2vsPtCutOff v2 increases linearly, for pt >= fV2vsPtCutOff v2 = fV2vsPtMax, see Eq. (32) in arXiv:1312.3572 + pbyp.fPt < fV2vsPtCutOff ? fPhiPDF->SetParameter(2, pbyp.fPt * fV2vsPtMax / fV2vsPtCutOff) : fPhiPDF->SetParameter(2, fV2vsPtMax); + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent") || iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + float fV2vsPtCutOff = 2.0; // TBI 20250729 I could add configurables for these 2 variables at some point, otherwise, simply hardwire the constants in the expression below + float fV2vsPtMax = 0.3; // TBI 20250729 I shall NOT use f to name these two variables, rename eventually + // pt dependence: for pt < fV2vsPtCutOff v2 increases linearly, for pt >= fV2vsPtCutOff v2 = fV2vsPtMax, see Eq. (32) in arXiv:1312.3572 + // eta dependence is defined as 0.4 - (1/4) eta^2, so that v2(eta) = 0.24 at eta = +-0.8, and v2(eta) = 0.40 at eta = 0 (keep in sync with details above) + // to increase significance, I multiply by factor of 2 the sampled v2(pt,eta) + float v2 = 0.; // this is the actual v2(pt,eta) for the current particle + pbyp.fPt < fV2vsPtCutOff ? v2 = 2. * (pbyp.fPt * fV2vsPtMax / fV2vsPtCutOff) * (0.4 - (1. / 4.) * pbyp.fEta * pbyp.fEta) : v2 = 2. * fV2vsPtMax * (0.4 - (1. / 4.) * pbyp.fEta * pbyp.fEta); + if (v2 < 0. || v2 > 0.5) { + LOGF(fatal, "\033[1;31m%s at line %d : v2 = %f\033[0m", __FUNCTION__, __LINE__, v2); + } + if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaDependent")) { + fPhiPDF->SetParameter(2, v2); // set v2(pt,eta) for this particle + } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("ptEtaChargeDependent")) { + if (pbyp.fCharge > 0.) { + v2 *= 0.75; // trim down by 25% only v2 of positive particles in this toy model + } + fPhiPDF->SetParameter(2, v2); // set v2(pt,eta,charge) for this particle } } + // Finally, sample particle angle: + pbyp.fPhi = fPhiPDF->GetRandom(); + // *) Fill few selected particle histograms before cuts here directly: // Remark: I do not call FillParticleHistograms(track, eBefore), as I do not want to bother to make here full 'track' object, etc., just to fill simple kine info: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) { // 1D: - !ph.fParticleHistograms[ePhi][eSim][eBefore] ? true : ph.fParticleHistograms[ePhi][eSim][eBefore]->Fill(dPhi); - !ph.fParticleHistograms[ePt][eSim][eBefore] ? true : ph.fParticleHistograms[ePt][eSim][eBefore]->Fill(dPt); - !ph.fParticleHistograms[eEta][eSim][eBefore] ? true : ph.fParticleHistograms[eEta][eSim][eBefore]->Fill(dEta); - !ph.fParticleHistograms[eCharge][eSim][eBefore] ? true : ph.fParticleHistograms[eCharge][eSim][eBefore]->Fill(dCharge); + !ph.fParticleHistograms[ePhi][eSim][eBefore] ? true : ph.fParticleHistograms[ePhi][eSim][eBefore]->Fill(pbyp.fPhi); + !ph.fParticleHistograms[ePt][eSim][eBefore] ? true : ph.fParticleHistograms[ePt][eSim][eBefore]->Fill(pbyp.fPt); + !ph.fParticleHistograms[eEta][eSim][eBefore] ? true : ph.fParticleHistograms[eEta][eSim][eBefore]->Fill(pbyp.fEta); + !ph.fParticleHistograms[eCharge][eSim][eBefore] ? true : ph.fParticleHistograms[eCharge][eSim][eBefore]->Fill(pbyp.fCharge); // 2D: - !ph.fParticleHistograms2D[ePhiPt][eSim][eBefore] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][eBefore]->Fill(dPhi, dPt); - !ph.fParticleHistograms2D[ePhiEta][eSim][eBefore] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][eBefore]->Fill(dPhi, dEta); + !ph.fParticleHistograms2D[ePhiPt][eSim][eBefore] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][eBefore]->Fill(pbyp.fPhi, pbyp.fPt); + !ph.fParticleHistograms2D[ePhiEta][eSim][eBefore] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][eBefore]->Fill(pbyp.fPhi, pbyp.fEta); + + // nD (THnSparse): + if (ph.fFillParticleSparseHistogramsBeforeCuts) { + // **) eDWPhi : here the fundamental 0-th axis never to be projected out is "phi" + if (ph.fBookParticleSparseHistograms[eDWPhi]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPhiWeights + double vector[eDiffPhiWeights_N] = {pbyp.fPhi, pbyp.fPt, pbyp.fEta, pbyp.fCharge, ebye.fCentrality, ebye.fVz}; + ph.fParticleSparseHistograms[eDWPhi][eSim][eBefore]->Fill(vector); + } + // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" + if (ph.fBookParticleSparseHistograms[eDWPt]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights + double vector[eDiffPtWeights_N] = {pbyp.fPt, pbyp.fEta, pbyp.fCharge, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWPt][eSim][eBefore]->Fill(vector); + } + // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" + if (ph.fBookParticleSparseHistograms[eDWEta]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights + double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWEta][eSim][eBefore]->Fill(vector); + } + + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + double vector[eDiffChargeWeights_N] = {pbyp.fCharge, pbyp.fPt, pbyp.fEta, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWCharge][eSim][eBefore]->Fill(vector); + } + + } // ph.fFillParticleSparseHistogramsBeforeCuts + } // if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) + + // *) Particle cuts (only support for elementary kinematics (pt, eta, charge) and Toy NUA is provided, for the time being): + // *) Pt: + if (pc.fUseParticleCuts[ePt]) { + if (pbyp.fPt < pc.fdParticleCuts[ePt][eMin] || pbyp.fPt > pc.fdParticleCuts[ePt][eMax] || std::abs(pbyp.fPt - pc.fdParticleCuts[ePt][eMax]) < tc.fFloatingPointPrecision) { + continue; + } } - // *) Particle cuts (only support for Toy NUA is provided, for the time being): - // NUA: - if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { + // *) Eta: + if (pc.fUseParticleCuts[eEta]) { + if (pbyp.fEta < pc.fdParticleCuts[eEta][eMin] || pbyp.fEta > pc.fdParticleCuts[eEta][eMax] || std::abs(pbyp.fEta - pc.fdParticleCuts[eEta][eMax]) < tc.fFloatingPointPrecision) { + continue; + } + } + + // *) Charge: + if (pc.fUseParticleCuts[eCharge]) { + if (pbyp.fCharge < pc.fdParticleCuts[eCharge][eMin] || pbyp.fCharge > pc.fdParticleCuts[eCharge][eMax]) { + // With first condition, I always throw away neutral particles => not needed here, see how I sample above. + // I can use safely == here, because track.sign() returns short int. + continue; + } + } + + // *) NUA: + if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(pbyp.fPhi, ePhiNUAPDF)) { continue; } - if (nua.fApplyNUAPDF[ePtNUAPDF] && !Accept(dPt, ePtNUAPDF)) { + if (nua.fApplyNUAPDF[ePtNUAPDF] && !Accept(pbyp.fPt, ePtNUAPDF)) { continue; } - if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { + if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(pbyp.fEta, eEtaNUAPDF)) { + continue; + } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(pbyp.fCharge, eChargeNUAPDF)) { continue; } @@ -6944,94 +7394,61 @@ void InternalValidation() // Remark: I do not call FillParticleHistograms(track, eAfter), as I do not want to bother to make here full 'track' object, etc., just to fill simple kine info: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) { // 1D: - !ph.fParticleHistograms[ePhi][eSim][eAfter] ? true : ph.fParticleHistograms[ePhi][eSim][eAfter]->Fill(dPhi); - !ph.fParticleHistograms[ePt][eSim][eAfter] ? true : ph.fParticleHistograms[ePt][eSim][eAfter]->Fill(dPt); - !ph.fParticleHistograms[eEta][eSim][eAfter] ? true : ph.fParticleHistograms[eEta][eSim][eAfter]->Fill(dEta); - !ph.fParticleHistograms[eCharge][eSim][eAfter] ? true : ph.fParticleHistograms[eCharge][eSim][eAfter]->Fill(dCharge); + !ph.fParticleHistograms[ePhi][eSim][eAfter] ? true : ph.fParticleHistograms[ePhi][eSim][eAfter]->Fill(pbyp.fPhi); + !ph.fParticleHistograms[ePt][eSim][eAfter] ? true : ph.fParticleHistograms[ePt][eSim][eAfter]->Fill(pbyp.fPt); + !ph.fParticleHistograms[eEta][eSim][eAfter] ? true : ph.fParticleHistograms[eEta][eSim][eAfter]->Fill(pbyp.fEta); + !ph.fParticleHistograms[eCharge][eSim][eAfter] ? true : ph.fParticleHistograms[eCharge][eSim][eAfter]->Fill(pbyp.fCharge); // 2D: - !ph.fParticleHistograms2D[ePhiPt][eSim][eAfter] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][eAfter]->Fill(dPhi, dPt); - !ph.fParticleHistograms2D[ePhiEta][eSim][eAfter] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][eAfter]->Fill(dPhi, dEta); - } + !ph.fParticleHistograms2D[ePhiPt][eSim][eAfter] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][eAfter]->Fill(pbyp.fPhi, pbyp.fPt); + !ph.fParticleHistograms2D[ePhiEta][eSim][eAfter] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][eAfter]->Fill(pbyp.fPhi, pbyp.fEta); + // nD (THnSparse): + // **) eDWPhi : here the fundamental 0-th axis never to be projected out is "phi" + if (ph.fBookParticleSparseHistograms[eDWPhi]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPhiWeights + double vector[eDiffPhiWeights_N] = {pbyp.fPhi, pbyp.fPt, pbyp.fEta, pbyp.fCharge, ebye.fCentrality, ebye.fVz}; + ph.fParticleSparseHistograms[eDWPhi][eSim][eAfter]->Fill(vector); + } + // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" + if (ph.fBookParticleSparseHistograms[eDWPt]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights + double vector[eDiffPtWeights_N] = {pbyp.fPt, pbyp.fEta, pbyp.fCharge, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWPt][eSim][eAfter]->Fill(vector); + } + // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" + if (ph.fBookParticleSparseHistograms[eDWEta]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights + double vector[eDiffEtaWeights_N] = {pbyp.fEta, pbyp.fPt, pbyp.fCharge, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWEta][eSim][eAfter]->Fill(vector); + } + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + double vector[eDiffChargeWeights_N] = {pbyp.fCharge, pbyp.fPt, pbyp.fEta, ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWCharge][eSim][eAfter]->Fill(vector); + } + } // if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) // Remark: Keep in sync all calls and flags below with the ones in MainLoopOverParticles(). // *) Integrated Q-vectors: if (qv.fCalculateQvectors || es.fCalculateEtaSeparations) { - this->FillQvector(dPhi, dPt, dEta); // all 3 arguments are passed by reference + // This is now the new approach, with sparse histograms: + // **) particle arguments are passed by reference + // **) event observables (centrality, vertex z, ...), I do not need to pass as arguments, as I have data members for them (ebye.fCentrality, ebye.Vz, ...) + // **) I decide within FillQvectorFromSparse(...) whether and which weights are used. So yes, I use this one, despite its name, even when weights are NOT used + // (there is no real performance penalty) + // **) Legacy function FillQvector(...) is obsolete as of 20250714, since I can get both integrated and differential wights from sparse histograms. + this->FillQvectorFromSparse(); } // *) Differential q-vectors (keep in sync with the code in MainLoopOverParticles(...)): - // ** 1D: - // ***) pt dependence: - if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT]) && !es.fCalculateEtaSeparations) { - // In this branch I do not need eta separation, so the lighter call can be executed: - double kineArr[1] = {dPt}; - this->FillqvectorNdim(dPhi, kineArr, 1, PTq); - } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { - // In this branch I do need eta separation, so the heavier call must be executed: - double kineArr[1] = {dPt}; - this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); - } - - // ***) eta dependence: - if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[1] = {dEta}; - this->FillqvectorNdim(dPhi, kineArr, 1, ETAq); - } - - // ***) charge dependence: - if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE]) && !es.fCalculateEtaSeparations) { - // In this branch I do not need eta separation, so the lighter call can be executed: - double kineArr[1] = {dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq); - } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) { - // In this branch I do need eta separation, so the heavier call must be executed: - double kineArr[1] = {dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq, dEta); - } - - // ... - - // ** 2D: - // ***) pt-eta dependence: - if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[2] = {dPt, dEta}; - this->FillqvectorNdim(dPhi, kineArr, 2, PT_ETAq); - } - - // ***) pt-charge dependence: - if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) && !es.fCalculateEtaSeparations) { - // In this branch I do not need eta separation, so the lighter call can be executed: - double kineArr[2] = {dPt, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq); - } else if (es.fCalculateEtaSeparations && false) { // && TBI 20250623 finalize, replace "false" with 2D flag for (pt,charge) with eta separation case - // In this branch I do need eta separation, so the heavier call must be executed: - double kineArr[2] = {dPt, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq, dEta); - } - - // ***) eta-charge dependence: - if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[2] = {dEta, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 2, ETA_CHARGEq); - } - - // ... + // TBI 20260210 I need here a flag if this calculus is needed at all - // ** 3D: - // ***) pt-eta-charge dependence: - if (qv.fCalculateQvectors && (t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[3] = {dPt, dEta, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 3, PT_ETA_CHARGEq); - } + this->Fillqvectors(); // within this function, i call FillqvectorFromSparse(...), for each differential q-vector separately // *) Fill nested loops containers: if (nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) { - this->FillNestedLoopsContainers(ebye.fSelectedTracks, dPhi, dPt, dEta); // all 4 arguments are passed by reference + this->FillNestedLoopsContainers(ebye.fSelectedTracks); } // *) Counter of selected tracks in the current event: @@ -7117,8 +7534,8 @@ bool Accept(const double& value, int var) // Given the acceptance profile for this observable, accept or not that observable for the analysis. // Use in Toy NUA studies. - // Remark: var corresponds to the field in enum eNUAPDF { ePhiNUAPDF, ePtNUAPDF, eEtaNUAPDF }; - // Therefore, always call this function as e.g. Accept(someAngle, ePhiNUAPDF) or Accept(somePt, ePtNUAPDF) + // Remark: var corresponds to the field in enum eNUAPDF { ePhiNUAPDF, ePtNUAPDF, eEtaNUAPDF, eChargeNUAPDF }; + // Therefore, always call this function as e.g. Accept(someAngle, ePhiNUAPDF) or Accept(somePt, ePtNUAPDF), etc. if (tc.fVerboseForEachParticle) { LOGF(info, "\033[1;32m%s\033[0m", __FUNCTION__); @@ -7541,7 +7958,7 @@ void bookResultsHistograms() // TBI 20250518 I book 1D case always for the time being, because I also use their binning to book particle sparse histograms. // There should not be any big memory penalty for 1D case - // if (!(t0.fCalculateTest0AsFunctionOf[v] || mupa.fCalculateCorrelationsAsFunctionOf[v] || es.fCalculateEtaSeparationsAsFunctionOf[v])) { + // if (!(tc.fCalculateAsFunctionOf[v])) { // // TBI 20250518 do I need here also some check for the nested loops? // continue; // } @@ -7864,7 +8281,7 @@ void Preprocess(T1 const& collision, T2 const& bcs) pw.fParticleWeightsAreFetched = true; } - // differential particle weights using sparse histogreams: + // differential particle weights using sparse histograms: if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffPtWeights[wEtaEtaAxis]) { // Yes, I check only the first flag. This way, I can e.g. switch off all differential phi weights by setting 0-wPhi in config. // On the other hand, it doesn't make sense to calculate differential phi weights without having phi axis. @@ -8079,14 +8496,17 @@ void PropagateRunNumber() { for (int rs = 0; rs < 2; rs++) // reco/sim { - if (!ph.fParticleSparseHistograms[t][rs]) { - continue; - } - histTitle = ph.fParticleSparseHistograms[t][rs]->GetTitle(); - if (histTitle.Contains("__RUN_NUMBER__")) { - histTitle.ReplaceAll("__RUN_NUMBER__", tc.fRunNumber.Data()); // it replaces in-place - ph.fParticleSparseHistograms[t][rs]->SetTitle(histTitle.Data()); - } + for (int ba = 0; ba < 2; ba++) // before/after cuts + { + if (!ph.fParticleSparseHistograms[t][rs][ba]) { + continue; + } + histTitle = ph.fParticleSparseHistograms[t][rs][ba]->GetTitle(); + if (histTitle.Contains("__RUN_NUMBER__")) { + histTitle.ReplaceAll("__RUN_NUMBER__", tc.fRunNumber.Data()); // it replaces in-place + ph.fParticleSparseHistograms[t][rs][ba]->SetTitle(histTitle.Data()); + } + } // for (int ba = 0; ba < 2; ba++) // before/after cuts } // for(int rs=0;rs<2;rs++) // reco/sim } // for (int t = 0; t < eDiffWeightCategory; t++) // category, see enum eDiffWeightCategory @@ -8301,6 +8721,7 @@ void ResetEventByEventQuantities() ebye.fInteractionRate = 0.; ebye.fCurrentRunDuration = 0.; ebye.fVz = 0.; + ebye.fVzSim = 0.; ebye.fFT0CAmplitudeOnFoundBC = 0.; ebye.fImpactParameter = 0.; // I can reset it here to 0., as long as I am calculating it from collision.mcCollision().impactParameter() . If I calculate it from hep.impactParameter(), i need to re-think @@ -8313,7 +8734,8 @@ void ResetEventByEventQuantities() for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { for (int wp = 0; wp < gMaxCorrelator + 1; wp++) // weight power { - qv.fQvector[h][wp] = TComplex(0., 0.); + qv.fQvector[h][wp] = TComplex(0., 0.); // legacy code (TBI 20250718 remove, and switch to line below eventually) + // qv.fQvector[h][wp] = {0., 0.}; // yes, this is the right notation for complex numbers } } } // if (qv.fCalculateQvectors) @@ -10352,7 +10774,7 @@ bool ParticleCuts(T const& track, eCutModus cutModus) // *) Particle cuts on Test case; // *) Toy NUA. - // 44:ParticleCuts + // :pc if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); @@ -10897,7 +11319,9 @@ bool ParticleCuts(T const& track, eCutModus cutModus) // ------------------------------------------------------------------------- // *) Toy NUA: - if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF]) { + // TBI 20250718 Check if can optimize here something by using new global pbyp.fPhi, pbyp.fPt, etc, variables. Most likely yes, since I would avoid calling again track.phi(), etc. + // But I do not use Toy NUA in any case for real large-scale data analysis. + if (nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { // Remark: I do not for the time being add Toy NUA cuts to particle cut counters, since in this case I can inspect direcly from phi, pt and eta distributions. @@ -10905,12 +11329,14 @@ bool ParticleCuts(T const& track, eCutModus cutModus) double dPhi = 0.; double dPt = 0.; double dEta = 0.; + double dCharge = 0.; // *) Apply Toy NUA on info available in reconstructed (and the corresponding MC truth simulated track); if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { dPhi = track.phi(); dPt = track.pt(); dEta = track.eta(); + dCharge = track.sign(); // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -10922,6 +11348,9 @@ bool ParticleCuts(T const& track, eCutModus cutModus) if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { return false; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(dCharge, eChargeNUAPDF)) { + return false; + } // ... and corresponding MC truth simulated ( see https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/mcHistograms.cxx ): if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { @@ -10933,6 +11362,12 @@ bool ParticleCuts(T const& track, eCutModus cutModus) dPhi = mcParticle.phi(); dPt = mcParticle.pt(); dEta = mcParticle.eta(); + // special treatment for charge, because there is no getter mcParticle.sign() + dCharge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + dCharge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -10944,6 +11379,9 @@ bool ParticleCuts(T const& track, eCutModus cutModus) if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { return false; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(dCharge, eChargeNUAPDF)) { + return false; + } } // if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { } // if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { @@ -10954,6 +11392,12 @@ bool ParticleCuts(T const& track, eCutModus cutModus) dPhi = track.phi(); dPt = track.pt(); dEta = track.eta(); + // special treatment for charge, because there is no getter mcParticle.sign() + dCharge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(track.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + dCharge = tc.fDatabasePDG->GetParticle(track.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -10965,9 +11409,12 @@ bool ParticleCuts(T const& track, eCutModus cutModus) if (nua.fApplyNUAPDF[eEtaNUAPDF] && !Accept(dEta, eEtaNUAPDF)) { return false; } + if (nua.fApplyNUAPDF[eChargeNUAPDF] && !Accept(dCharge, eChargeNUAPDF)) { + return false; + } } // if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { - } // if(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF]) { + } // if(nua.fApplyNUAPDF[ePhiNUAPDF] || nua.fApplyNUAPDF[ePtNUAPDF] || nua.fApplyNUAPDF[eEtaNUAPDF] || nua.fApplyNUAPDF[eChargeNUAPDF]) { return true; @@ -11091,26 +11538,32 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) } // if (ph.fFillParticleHistograms2D) { // nD (THnSparse): - if (ba == eAfter) { // yes, I feel sparse histograms only AFTER cuts for the time being + if (ba == eAfter || (eBefore == ba && ph.fFillParticleSparseHistogramsBeforeCuts)) { // **) eDWPhi : here the fundamental 0-th axis never to be projected out is "phi" if (ph.fBookParticleSparseHistograms[eDWPhi]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPhiWeights double vector[eDiffPhiWeights_N] = {track.phi(), track.pt(), track.eta(), static_cast(track.sign()), ebye.fCentrality, ebye.fVz}; - ph.fParticleSparseHistograms[eDWPhi][eRec]->Fill(vector, weight); + ph.fParticleSparseHistograms[eDWPhi][eRec][ba]->Fill(vector, weight); } // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights - double vector[eDiffPtWeights_N] = {track.pt(), static_cast(track.sign()), ebye.fCentrality}; - ph.fParticleSparseHistograms[eDWPt][eRec]->Fill(vector, weight); + double vector[eDiffPtWeights_N] = {track.pt(), track.eta(), static_cast(track.sign()), ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWPt][eRec][ba]->Fill(vector, weight); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights - double vector[eDiffEtaWeights_N] = {track.eta(), static_cast(track.sign()), ebye.fCentrality}; - ph.fParticleSparseHistograms[eDWEta][eRec]->Fill(vector, weight); + double vector[eDiffEtaWeights_N] = {track.eta(), track.pt(), static_cast(track.sign()), ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWEta][eRec][ba]->Fill(vector, weight); } - } // if (ba == eAfter) { + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + double vector[eDiffChargeWeights_N] = {static_cast(track.sign()), track.pt(), track.eta(), ebye.fCentrality}; + ph.fParticleSparseHistograms[eDWCharge][eRec][ba]->Fill(vector, weight); + } + } // if (ba == eAfter ... ) { // QA: if (qa.fFillQAParticleHistograms2D) { @@ -11233,7 +11686,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) } // if(ph.fFillParticleHistograms2D) { // nD (THnSparse): - if (ba == eAfter) { // yes, I feel sparse histograms only AFTER cuts for the time being + if (ba == eAfter || (eBefore == ba && ph.fFillParticleSparseHistogramsBeforeCuts)) { // **) eDWPhi : here the fundamental 0-th axis never to be projected out is "phi" if (ph.fBookParticleSparseHistograms[eDWPhi]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPhiWeights @@ -11246,7 +11699,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) } double vector[eDiffPhiWeights_N] = {mcParticle.phi(), mcParticle.pt(), mcParticle.eta(), charge, ebye.fCentralitySim, 0.}; // TBI 20250611 I do nothing for vertex z, I could trivially extend ebye.fVz also for "sim" dimension => I set it to 0 temporarily here, until that's done. - ph.fParticleSparseHistograms[eDWPhi][eSim]->Fill(vector, weight); + ph.fParticleSparseHistograms[eDWPhi][eSim][ba]->Fill(vector, weight); } // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { @@ -11258,8 +11711,8 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL charge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks } - double vector[eDiffPtWeights_N] = {mcParticle.pt(), charge, ebye.fCentralitySim}; - ph.fParticleSparseHistograms[eDWPt][eSim]->Fill(vector, weight); + double vector[eDiffPtWeights_N] = {mcParticle.pt(), mcParticle.eta(), charge, ebye.fCentralitySim}; + ph.fParticleSparseHistograms[eDWPt][eSim][ba]->Fill(vector, weight); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { @@ -11271,10 +11724,24 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL charge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks } - double vector[eDiffEtaWeights_N] = {mcParticle.eta(), charge, ebye.fCentralitySim}; - ph.fParticleSparseHistograms[eDWEta][eSim]->Fill(vector, weight); + double vector[eDiffEtaWeights_N] = {mcParticle.eta(), mcParticle.pt(), charge, ebye.fCentralitySim}; + ph.fParticleSparseHistograms[eDWEta][eSim][ba]->Fill(vector, weight); + } + // **) eDWCharge : here the fundamental 0-th axis never to be projected out is "charge" + if (ph.fBookParticleSparseHistograms[eDWCharge]) { + // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffChargeWeights + + // special treatment for charge, because there is no getter mcParticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(mcParticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + double vector[eDiffChargeWeights_N] = {charge, mcParticle.pt(), mcParticle.eta(), ebye.fCentralitySim}; + ph.fParticleSparseHistograms[eDWCharge][eSim][ba]->Fill(vector, weight); } - } // if (ba == eAfter) { + + } // if (ba == eAfter ... ) { } // if constexpr (rs == eRecAndSim || rs == eRecAndSim_Run2 || rs == eRecAndSim_Run1) { } // if constexpr (rs == eRec || rs == eRecAndSim || rs == eRec_Run2 || rs == eRecAndSim_Run2 || rs == eRec_Run1 || rs == eRecAndSim_Run1) { @@ -11283,7 +11750,8 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // b) Fill only simulated (common to Run 3, Run 2 and Run 1): // Remark #1: This branch is relevant when processing ONLY simulated data at generator level. - // Remark #2: In this branch, 'track' is always TracksSim = aod::McParticles, see https://aliceo2group.github.io/analysis-framework/docs/datamodel/ao2dTables.html#montecarlo + // Remark #2: In this branch, 'track' is always TracksSim = aod::McParticles, see https://aliceo2group.github.io/analysis-framework/docs/datamodel/ao2dTables.html#montecarlo . + // Remark #3: This code is completely irrelevant for InternalValidation(), because few selected histos I fill directly there. if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { // 1D: if (ph.fFillParticleHistograms) { @@ -11723,6 +12191,9 @@ void CalculateKineCorrelations(eAsFunctionOf AFO_variable) { // Calculate analytically differential multiparticle correlations from Q-vectors. + // TBI 20250702 I need declare this function obsolete, and move to CalculateKineCorrelationsNdim, see what I did in CalculateKineTest0Ndim + // After that, finalize this function and add the standard support for kine calculus. + if (tc.fVerbose) { StartFunction(__FUNCTION__); } @@ -11928,7 +12399,7 @@ void CalculateTest0() // Insanity check on weight: if (!(weight > 0.)) { - LOGF(fatal, "\033[1;31m%s at line %d : weight = %f => Is perhaps order of correlator bigger than the number of particles? t0.fTest0Labels[mo][mi]->Data() = %s \033[0m", __FUNCTION__, __LINE__, weight, t0.fTest0Labels[mo][mi]->Data()); + LOGF(fatal, "\033[1;31m%s at line %d : weight = %f, correlation = %f, ebye.fSelectedTracks = %d => Is perhaps order of correlator bigger than the number of particles? t0.fTest0Labels[mo][mi]->Data() = %s \033[0m", __FUNCTION__, __LINE__, weight, correlation, ebye.fSelectedTracks, t0.fTest0Labels[mo][mi]->Data()); } // e-b-e sanity check: @@ -12339,7 +12810,7 @@ void CalculateKineTest0Ndim(eqvectorKine kineVarChoice, int Ndim) Trace(__FUNCTION__, __LINE__); } - // *) Check if this bin is overflow or underflow: + // *) Check if this bin is overflow or underflow, or otherwise if it's empty: // Well, I already checked that when filling fqvector, if this global bin is overflow or underflow, qvector and number of entries shall be empty for that bin, so I am checking for that: if (0 == qv.fqvectorEntries[kineVarChoice][b]) { if (tc.fVerbose) { @@ -12348,17 +12819,19 @@ void CalculateKineTest0Ndim(eqvectorKine kineVarChoice, int Ndim) continue; } - // *) Ensures that in each bin of interest, I have the same cut on number of particles, like in integrated analysis: - /* TBI 20250603 not sure any longer if I can use this code: - // 1. if i do not use it, I allow possibility that correlations are calculated even when that makes no sense (two few particles for that correlators) - // 2. if I use it, I will not be able to get exactly the same result after rebinning (or ironing out some dimensions) as in integrated analysis - // => re-think - if ((qv.fqvectorEntries[kineVarChoice][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqvectorEntries[kineVarChoice][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqvectorEntries[kineVarChoice][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { + // *) Ensures that in each kine bin, I have the same cut on number of particles, like in integrated analysis: + // Remarks: + // 1. if I do not use this cut here, I allow possibility that correlations are calculated in a given kine bin even when that makes no sense + // (two few particles for that particular correlators); + // 2. if I use it, I will not be able to get exactly the same result after rebinning (or ironing out some dimensions) as in integrated analysis. But this is + // how it is in any case, because paticles from different kine bins are never directly correlated in kine analysis. Therefore, even in principle, I cannot + // cross-check integrated results for correlations, by rebinning the final kine results. + if (qv.fqvectorEntries[kineVarChoice][b] < ec.fdEventCuts[eMultiplicity][eMin] || qv.fqvectorEntries[kineVarChoice][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqvectorEntries[kineVarChoice][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision) { if (tc.fVerbose) { - LOGF(info, "\033[1;31m%s eMultiplicity cut in global bin = %d, for kineVarChoice = %d (%s), there are only %d selected particles in this bin\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), qv.fqvectorEntries[kineVarChoice][b]); + LOGF(info, "\033[1;31m%s eMultiplicity cut in kine bin = %b, for kineVarChoice = %d (%s), there are only %d selected particles in this kine bin\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), qv.fqvectorEntries[kineVarChoice][b]); } + continue; } - */ // *) Re-initialize Q-vector to be q-vector in this bin: // After that, I can call all standard Q-vector functions again: @@ -12368,6 +12841,10 @@ void CalculateKineTest0Ndim(eqvectorKine kineVarChoice, int Ndim) } } + // TBI 20250702 Do I need to do some separate insanity check for the case when Q is identically 0? + // Most likely not, as all such cases shall already be covered with previous two checks above. + // I leave it like this, unless proven otherwise. + if (tc.fVerbose) { // TBI 20250701 temporary check, remove eventually Trace(__FUNCTION__, __LINE__); } @@ -12956,16 +13433,7 @@ void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) // *) Uniform loop over linearized global bins for all kine variables: for (int b = 0; b < nBins; b++) { // yes, "< nBins", not "<= nBins", because b runs over all regular bins + 2 (therefore, including underflow and overflow already) - // TBI 20241206 Do I need to adapt and apply this cut, also for Qa and Qb? If so, most likely I would need to apply it on sum, i.e. on entries in Qa + Qb - // - // // *) Ensures that in each bin of interest, I have the same cut on number of particles, like in integrated analysis: - // if ((qv.fqvectorEntries[qvKine][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqvectorEntries[qvKine][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqvectorEntries[qvKine][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { - // if (tc.fVerbose) { - // LOGF(info, "\033[1;31m%s eMultiplicity cut in bin = %d, for qvKine = %d\033[0m", __FUNCTION__, b, static_cast(qvKine)); - // } - // } - - // Calculate differential 2-p correlations with eta separations from Qa (-eta, index [0]) and Qb (+eta, index [1]) vectors: + // Calculate differential 2-p correlations for all requested harmonics, and all eta separations from Qa (-eta, index [0]) and Qb (+eta, index [1]) vectors: double correlation = 0.; double weight = 0.; for (int h = 0; h < gMaxHarmonic; h++) { @@ -12974,10 +13442,31 @@ void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) } for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (!(std::abs(qv.fqabVector[0][kineVarChoice][b][h][e]) > 0. && std::abs(qv.fqabVector[1][kineVarChoice][b][h][e]) > 0.)) { + + // *) Check if this bin is overflow or underflow, or otherwise if it's empty: + if (!(qv.fmab[0][kineVarChoice][b][e] > 0. && qv.fmab[1][kineVarChoice][b][e] > 0.)) { + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s no entries in kine bin = %b, for kineVarChoice = %d (%s), and for eta separation index = %d. Just skipping this kine bin (this is most likely underflow or overflow global kine bin)\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), e); + } continue; } - if (!(qv.fmab[0][kineVarChoice][b][e] > 0. && qv.fmab[1][kineVarChoice][b][e] > 0.)) { + + // *) Ensures that in each kine bin, with eta separations, I have the same cut on number of particles, like in integrated analysis: + // 1. see corrresponding remarks in CalculateKineTest0Ndim( ... ); + // 2. note that here I apply the cut on the sum A + B (it's safe, because corner cases when mult. is 0 in A or in B, is already removed with previous cut here) + + if ((qv.fmab[0][kineVarChoice][b][e] + qv.fmab[1][kineVarChoice][b][e]) < ec.fdEventCuts[eMultiplicity][eMin] || + (qv.fmab[0][kineVarChoice][b][e] + qv.fmab[1][kineVarChoice][b][e]) > ec.fdEventCuts[eMultiplicity][eMax] || + std::abs(qv.fmab[0][kineVarChoice][b][e] + qv.fmab[1][kineVarChoice][b][e] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision) { + + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s eMultiplicity cut in kine bin = %b, for kineVarChoice = %d (%s), and for eta separation index = %d. There are only %d selected particles in both eta separated intervals in this kine bin\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), e, qv.fqvectorEntries[kineVarChoice][b]); + } + continue; + } + + // *) Finally, skip kine bins, with eta separations, for which either qa or qb is zero: + if (!(std::abs(qv.fqabVector[0][kineVarChoice][b][h][e]) > 0. && std::abs(qv.fqabVector[1][kineVarChoice][b][h][e]) > 0.)) { continue; } @@ -13024,7 +13513,7 @@ void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) //============================================================ -void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, const double& dPt, const double& dEta) +void FillNestedLoopsContainers(const int& particleIndex) { // Fill into the nested loop containers the current particle. @@ -13045,7 +13534,7 @@ void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, con // *) Fill container for angles: if (nl.ftaNestedLoops[0]) { - nl.ftaNestedLoops[0]->AddAt(dPhi, particleIndex); // remember that the 2nd argument here must start from 0 + nl.ftaNestedLoops[0]->AddAt(pbyp.fPhi, particleIndex); // remember that the 2nd argument here must start from 0 } // *) Fill container for weights: @@ -13056,23 +13545,44 @@ void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, con double wPhi = 1.; double wPt = 1.; double wEta = 1.; - if (pw.fUseWeights[wPHI]) { - wPhi = Weight(dPhi, wPHI); + double wCharge = 1.; + + if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a common boolean for this category + wPhi = WeightFromSparse(eDWPhi); + } + + if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a common boolean for this category + wPt = WeightFromSparse(eDWPt); + } + + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a common boolean for this category + wEta = WeightFromSparse(eDWEta); + } + + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, 0th axis serves as a common boolean for this category + wCharge = WeightFromSparse(eDWCharge); } - if (pw.fUseWeights[wPT]) { - wPt = Weight(dPt, wPT); + + if (pw.fUseWeights[wPHI]) { // TBI 20260216 obsolete, remove eventually + wPhi = Weight(pbyp.fPhi, wPHI); + } + + if (pw.fUseWeights[wPT]) { // TBI 20260216 obsolete, remove eventually + wPt = Weight(pbyp.fPt, wPT); } - if (pw.fUseWeights[wETA]) { - wEta = Weight(dEta, wETA); + + if (pw.fUseWeights[wETA]) { // TBI 20260216 obsolete, remove eventually + wEta = Weight(pbyp.fEta, wETA); } - nl.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta, particleIndex); // remember that the 2nd argument here must start from 0 + + nl.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta * wCharge, particleIndex); // remember that the 2nd argument here must start from 0 } if (tc.fVerbose) { ExitFunction(__FUNCTION__); } -} // void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, const double& dPt, const double& dEta) +} // void FillNestedLoopsContainers(const int& particleIndex) //============================================================ @@ -13506,8 +14016,7 @@ TComplex Three(int n1, int n2, int n3) TComplex Four(int n1, int n2, int n3, int n4) { - // Generic four-particle correlation - // . + // Generic four-particle correlation . TComplex four = Q(n1, 1) * Q(n2, 1) * Q(n3, 1) * Q(n4, 1) - @@ -13800,7 +14309,7 @@ void SetDiffWeightsSparse(THnSparseF* const sparse, eDiffWeightCategory dwc) // Finally: // sparse->SetDirectory(0); I cannot use this for sparse - pw.fDiffWeightsSparse[dwc] = reinterpret_cast(sparse); + pw.fDiffWeightsSparse[dwc] = reinterpret_cast(sparse); // TBI 20250702 why I am casting here in fact, 'sparse' is already THnSparseF... if (!pw.fDiffWeightsSparse[dwc]) { LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); @@ -13815,30 +14324,126 @@ void SetDiffWeightsSparse(THnSparseF* const sparse, eDiffWeightCategory dwc) // Finally, add to corresponding TList: pw.fWeightsList->Add(pw.fDiffWeightsSparse[dwc]); - // TBI 20250530 check this code snippet - do I need it? - // // Cosmetics: TBI 20240216 do I really want to overwrite initial cosmetics, perhaps this shall go better into MakeWeights.C ? - // // Or I could move all this to GetHistogramWithWeights, where in any case I am setting e.g. histogram title, etc. - // TString sVariable[eDiffWeights_N] = {"#varphi", "#varphi"}; // yes, for the time being, x-axis is always phi - // TString sWeights[eDiffWeights_N] = {"(w_{#varphi})_{| p_{T}}", "(w_{#varphi})_{| #eta}"}; - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetStats(false); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetXaxis()->SetTitle(sVariable[whichDiffWeight].Data()); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetYaxis()->SetTitle(sWeights[whichDiffWeight].Data()); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetFillColor(eFillColor); - // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetLineColor(eColor); - // pw.fWeightsList->Add(pw.fDiffWeightsSparse[whichDiffWeight][bin]); // This is working at the moment, because I am fetching all weights in Preprocess(), which is called after init() - // // But if eventually it will be possible to fetch run number programatically in init(), I will have to re-think this line. - - // // Flag: - // if (!pw.fUseDiffWeights[whichDiffWeight]) // yes, set it only once to true, for all bins - // { - // pw.fUseDiffWeights[whichDiffWeight] = true; - // } + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } - // if (tc.fVerbose) { - // ExitFunction(__FUNCTION__); - // } +} // void SetDiffWeightsSparse(THnSparseF* const sparse, eDiffWeightCategory dwc) + +//============================================================ + +void insanitizeDiffWeightsSparse(THnSparseF* const sparse) +{ + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis in sparse histograms is compatible with the cuts i used for variable on that axis. + + // TBI 20260223 : I am doing one unnecessary extra check in each if statement below to prevent rounding problem - check this further + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + if (!sparse) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + + int nDim = sparse->GetNdimensions(); + for (int d = 0; d < nDim; d++) { + + // get title for this axis: + std::string axisTitle = sparse->GetAxis(d)->GetTitle(); + + // insanity check on the title: + if (axisTitle.empty()) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d of sparse %s has an empty title \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName()); + } + + // check all supported observables: + if (!axisTitle.compare("#varphi")) { // I have to negate, becase compare() returns 0 if strings are equal + keep in sync hardwired string here with what i have in FancyFormatting(...) + + // check lower boundary: + if ((pc.fdParticleCuts[ePhi][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[ePhi][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#varphi) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[ePhi][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[ePhi][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[ePhi][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#varphi) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[ePhi][eMax]); + } + + } else if (!axisTitle.compare("p_{T}")) { + + // check lower boundary: + if ((pc.fdParticleCuts[ePt][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[ePt][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (p_{T}) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[ePt][eMin]); + } -} // void SetDiffWeightsSparse(THnSparseF* const sparse) + // check upper boundary: + if ((pc.fdParticleCuts[ePt][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[ePt][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (p_{T}) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[ePt][eMax]); + } + + } else if (!axisTitle.compare("#eta")) { + + // check lower boundary: + if ((pc.fdParticleCuts[eEta][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[eEta][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#eta) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[eEta][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[eEta][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[eEta][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (#eta) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[eEta][eMax]); + } + + } else if (!axisTitle.compare("Charge") || !axisTitle.compare("charge")) { + + // check lower boundary: + if ((pc.fdParticleCuts[eCharge][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - pc.fdParticleCuts[eCharge][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Charge) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), pc.fdParticleCuts[eCharge][eMin]); + } + + // check upper boundary: + if ((pc.fdParticleCuts[eCharge][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - pc.fdParticleCuts[eCharge][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Charge) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some particles I won't be able to fetch weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), pc.fdParticleCuts[eCharge][eMax]); + } + + } else if (!axisTitle.find("Centrality")) { // I have to use here find() instead, because title also contains centrality estimator name, e.g. "Centality (FT0C)" + + // check lower boundary: + if ((ec.fdEventCuts[eCentrality][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - ec.fdEventCuts[eCentrality][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Centrality) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some events I won't be able to fetch particle weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), ec.fdEventCuts[eCentrality][eMin]); + } + + // check upper boundary: + if ((ec.fdEventCuts[eCentrality][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - ec.fdEventCuts[eCentrality][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (Centrality) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some events I won't be able to fetch particles weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), ec.fdEventCuts[eCentrality][eMax]); + } + + } else if (!(axisTitle.compare("V_{z}")) || !(axisTitle.compare("VertexZ"))) { // TBI 20260217 I use indeed "VertexZ" for the time being, not sure why I didn't use here also FancyFormatting. But it doesn't hurt to add check for both + + // check lower boundary: + if ((ec.fdEventCuts[eVertexZ][eMin] < sparse->GetAxis(d)->GetBinLowEdge(1)) && (std::abs(sparse->GetAxis(d)->GetBinLowEdge(1) - ec.fdEventCuts[eVertexZ][eMin]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (V_{z} or VertexZ) of sparse %s has lower boundary %f, while lower cut on that variable is %f. This means that for some events I won't be able to fetch particle weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinLowEdge(1), ec.fdEventCuts[eVertexZ][eMin]); + } + + // check upper boundary: + if ((ec.fdEventCuts[eVertexZ][eMax] > sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins())) && (std::abs(sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()) - ec.fdEventCuts[eVertexZ][eMax]) > tc.fFloatingPointPrecision)) { + LOGF(fatal, "\033[1;31m%s at line %d : axis %d (V_{z} or VertexZ) of sparse %s has upper boundary %f, while upper cut on that variable is %f. This means that for some events I won't be able to fetch particles weights from this sparse. \033[0m", __FUNCTION__, __LINE__, d, sparse->GetName(), sparse->GetAxis(d)->GetBinUpEdge(sparse->GetAxis(d)->GetNbins()), ec.fdEventCuts[eVertexZ][eMax]); + } + + // ... add in the same way check for any other variable + + } else { + LOGF(fatal, "\033[1;31m%s at line %d : axisTitle = %s of sparse = %s is not supported yet in this function \033[0m", __FUNCTION__, __LINE__, axisTitle.data(), sparse->GetName()); + } + + } // for(int d = 0; d < nDim; d++) { + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void insanitizeDiffWeightsSparse(THnSparseF* const sparse) //============================================================ @@ -14194,12 +14799,12 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN // Remark 1: "whichCategory" always indicates the default x-axis (0th dimension), for instance for "differential phi weights" it's "phi" - // Remark 2: "whichDimensions" is formatted as follows: __..., for instance "pt_cent", if weights are calculated differentially as a function of pt and centrality - // If empty, that is also fine, I am fetching integrated weights, for instance integrated phi-weights. + // Remark 2: "whichDimensions" is formatted as follows: __..., for instance "pt_cent", if weights are calculated differentially as a function of pt and centrality. + // If empty, that is also fine, I am fetching integrated weights, for instance integrated phi weights. - // Remark 3: The nameing convention for sparse histogram in the output file is: __multiparticle-correlations-a-b_ + // Remark 3: The naming convention for sparse histogram in the output file is: __multiparticle-correlations-a-b_ // a) I allow possibility that "multiparticle-correlations-a-b_" is not present in the name - // b) In HL, fTaskName is typically subwagon name. Therefoere, it's mandatory that for a given subwagon in HL, BOTH subwagon name and fTaskName are set to the same name + // b) In HL, fTaskName is typically subwagon name. Therefore, it's mandatory that for a given subwagon in HL, BOTH subwagon name and fTaskName are set to the same name // TBI 20250215 If I can get within my task at run time subwagon name, I can automate this step. Check if that is possible // TBI 20240504: Here I can keep const char* variable , i.e. no need to switch to enums, because this function is called only once, at init. @@ -14233,15 +14838,14 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN // b) Basic protection for arguments: // Remark: below I do one more specific check. - if (!(TString(whichCategory).EqualTo("phi"))) { // TBI 20250215 I could in the future extend support to differential pT weights, etc. + if (!(TString(whichCategory).EqualTo("phi") || TString(whichCategory).EqualTo("pt") || TString(whichCategory).EqualTo("eta") || TString(whichCategory).EqualTo("charge"))) { LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } if (TString(whichDimensions).EqualTo("")) { LOGF(warning, "\033[1;33m%s at line %d : whichDimensions is empty, accessing only integrated %s weights\033[0m", __FUNCTION__, __LINE__, whichCategory); } - // c) Determine from filePath if the file in on a local machine, or in home - // dir AliEn, or in CCDB: + // c) Determine from filePath if the file in on a local machine, or in home dir AliEn, or in CCDB: // Algorithm: If filePath begins with "/alice/cern.ch/" then it's in home // dir AliEn. If filePath begins with "/alice-ccdb.cern.ch/" then it's in // CCDB. Therefore, files in AliEn and CCDB must be specified with abs path, @@ -14369,23 +14973,23 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN } else { sparseHistName = TString::Format("%s_%s_multiparticle-correlations-a-b", whichCategory, whichDimensions); } - // *) If not empty, I still need to appent TaskName (i.e. the cut name): + // *) If not empty, I still need to append TaskName (i.e. the cut name): if (!TString(tc.fTaskName).EqualTo("")) { sparseHistName += tc.fTaskName.Data(); } // 1. fetch histogram directly from this list: const char* whichCategory, const char* whichDimensions - LOGF(info, "\033[1;33m%s at line %d : fetching directly from the list sparse histogram with name = %s\033[0m", __FUNCTION__, __LINE__, sparseHistName.Data()); + LOGF(info, "\033[1;33m%s at line %d : fetching directly from the list sparse histogram with the name \"%s\"\033[0m", __FUNCTION__, __LINE__, sparseHistName.Data()); sparseHist = reinterpret_cast(listWithRuns->FindObject(sparseHistName.Data())); if (!sparseHist) { - // try once again by chopping off "multiparticle-correlations-a-b_" from name: + // try once again by chopping off "multiparticle-correlations-a-b_" from the name: TString tmp = sparseHistName; // yes, because "ReplaceAll" below replaces in-place, and I will need sparseHistName unmodified still later sparseHist = reinterpret_cast(listWithRuns->FindObject(tmp.ReplaceAll("multiparticle-correlations-a-b_", ""))); } // 2. if the previous search failed, descend recursively into the nested lists: if (!sparseHist) { - LOGF(info, "\033[1;33m%s at line %d : previous attempt failed, fetching instead recursively sparse histogram with name = %s\033[0m", __FUNCTION__, __LINE__, sparseHistName.Data()); + LOGF(info, "\033[1;33m%s at line %d : previous attempt failed, fetching instead recursively sparse histogram with the name \"%s\"\033[0m", __FUNCTION__, __LINE__, sparseHistName.Data()); sparseHist = reinterpret_cast(GetObjectFromList(listWithRuns, sparseHistName.Data())); if (!sparseHist) { // try once again by chopping off "multiparticle-correlations-a-b_" from name: @@ -14395,6 +14999,8 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN } if (!sparseHist) { + LOGF(info, "\033[1;33m%s at line %d : filePath = \"%s\"\033[0m", __FUNCTION__, __LINE__, filePath); + LOGF(info, "\033[1;33m%s at line %d : runNumber = \"%s\"\033[0m", __FUNCTION__, __LINE__, runNumber); listWithRuns->ls(); LOGF(fatal, "\033[1;31m%s at line %d : couldn't fetch sparse histogram with name = %s from this list\033[0m", __FUNCTION__, __LINE__, sparseHistName.Data()); } @@ -14451,7 +15057,7 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN // TBI 20241021 if I need to split hist title across two lines, use this technique: // hist->SetTitle(Form("#splitline{#scale[0.6]{%s}}{#scale[0.4]{%s}}",hist->GetTitle(),filePath)); - // h) Clone histogram and delete baseList (realising back the memory): + // h) Clone histogram and delete baseList (releasing back the memory): // Remark: Yes, I have to clone here. THnSparseF* sparseHistClone = reinterpret_cast(sparseHist->Clone()); delete baseList; // release back the memory @@ -15440,28 +16046,31 @@ double Weight(const double& value, eWeights whichWeight) // value, integrated [p //============================================================ -double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge, eDiffWeightCategory dwc) +double WeightFromSparse(eDiffWeightCategory dwc) { // Determine differential multidimensional particle weight using sparse histograms. if (tc.fVerbose) { StartFunction(__FUNCTION__); - } + LOGF(info, "\033[1;31m dwc = %d\033[0m", static_cast(dwc)); + LOGF(info, "\033[1;31m%s at line %d : printing current status of all weights flags\033[0m", __FUNCTION__, __LINE__); + PrintAllWeightsFlags(); + } // if (tc.fVerbose) { - // *) Reduce dimensionality is possible, i.e. look up only the dimensions in THnSparse which were requested in this analysis: + // *) Reduce dimensionality if possible, i.e. look up only the dimensions in sparse histogram which were requested in this analysis: int dim = 1; // yes, because dimension 0 is always reserved for each category switch (dwc) { case eDWPhi: { // Remember that ordering here has to resemble ordering in eDiffPhiWeights - pw.fFindBinVector[dwc]->AddAt(dPhi, 0); // special treatment for phi in eDWPhi category + pw.fFindBinVector[dwc]->AddAt(pbyp.fPhi, 0); // special treatment for phi in eDWPhi category if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { - pw.fFindBinVector[dwc]->AddAt(dPt, dim++); + pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, dim++); } if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { - pw.fFindBinVector[dwc]->AddAt(dEta, dim++); + pw.fFindBinVector[dwc]->AddAt(pbyp.fEta, dim++); } if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { - pw.fFindBinVector[dwc]->AddAt(dCharge, dim++); + pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, dim++); } if (pw.fUseDiffPhiWeights[wPhiCentralityAxis]) { pw.fFindBinVector[dwc]->AddAt(ebye.fCentrality, dim++); @@ -15473,20 +16082,47 @@ double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEt break; } case eDWPt: { - pw.fFindBinVector[dwc]->AddAt(dPt, 0); // special treatment for pt in eDWPt category + pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, 0); // special treatment for pt in eDWPt category // Remember that ordering here has to resemble ordering in eDiffPtWeights - // if(pw.fUseDiffPtWeights[...]) { - // pw.fFindBinVector[dwc]->AddAt(..., dim++); // skeleton for next dimension - // } + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fEta, dim++); + } + if (pw.fUseDiffPtWeights[wPtChargeAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, dim++); + } + if (pw.fUseDiffPtWeights[wPtCentralityAxis]) { + pw.fFindBinVector[dwc]->AddAt(ebye.fCentrality, dim++); + } // ... break; } case eDWEta: { - pw.fFindBinVector[dwc]->AddAt(dEta, 0); // special treatment for eta in eDWEta category + pw.fFindBinVector[dwc]->AddAt(pbyp.fEta, 0); // special treatment for eta in eDWEta category // Remember that ordering here has to resemble ordering in eDiffEtaWeights - // if(pw.fUseDiffEtaWeights[...]) { - // pw.fFindBinVector[dwc]->AddAt(..., dim++); // skeleton for next dimension - // } + if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, dim++); + } + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, dim++); + } + if (pw.fUseDiffEtaWeights[wEtaCentralityAxis]) { + pw.fFindBinVector[dwc]->AddAt(ebye.fCentrality, dim++); + } + // ... + break; + } + case eDWCharge: { + pw.fFindBinVector[dwc]->AddAt(pbyp.fCharge, 0); // special treatment for charge in eDWCharge category + // Remember that ordering here has to resemble ordering in eDiffChargeWeights + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fPt, dim++); + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + pw.fFindBinVector[dwc]->AddAt(pbyp.fEta, dim++); + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + pw.fFindBinVector[dwc]->AddAt(ebye.fCentrality, dim++); + } // ... break; } @@ -15519,7 +16155,7 @@ double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEt // If I decide to implement this, remember e.g. for 2D case that all bins of type (0,1), (0,2) ... are underflow of first variable, // and all bins of type (1,0), (2,0), ... are underflow of second variable. Analogously for overflow. // Each of these cases, however, have different global bin! - // Total number of linearized global bins for N-dimensional sparse = (N_1 + 2) * (N_2 + 2) * ... (N_N + 2), + // Total number of linearized global bins for N-dimensional sparse = (N_1 + 2) * (N_2 + 2) * ... * (N_N + 2), // where N_1 is number of bins in first dimension, etc. The offset + 2 in each case counts underflow and overflow. // Mapping between 2D bins and linearized global bins goes as follows (for an example 2 x 3 histogram): // 0,0 => 0 @@ -15531,8 +16167,8 @@ double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEt // ... // 2,4 => 18 // 3,4 => 19 - // So, for 2 x 3 histogram, there are (2+2) * (3+2) = 20 linearized global bins. - // Remember that I need to loop first over y dimensions, then nest inside the loop over x dimension, to achieve loop over global bins in consequtive order. + // So, for 2 x 3 histogram, there are (2+2) * (3+2) = 20 linearized global bins, indexed from 0 to 19. + // Remember that I need to loop first over y dimension, then nest inside the loop over x dimension, to achieve loop over global bins in consequtive order. Yes! double weight = pw.fDiffWeightsSparse[dwc]->GetBinContent(bin); @@ -15542,15 +16178,17 @@ double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEt return weight; -} // double WeightFromSparse(...) +} // double WeightFromSparse(eDiffWeightCategory dwc) //============================================================ double DiffWeight(const double& valueY, const double& valueX, eqvectorKine variableX) { - // Determine differential particle weight y(x). For the time being, "y = phi" always, but this can be generalized. + // !!! OBSOLETE FUNCTION !!! + + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250520, this is an obsolete function, use double WeightFromSparse(...) instead !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); - // TBI 20250520 This function is now obsolete, use WeightFromSparse(...) instead. + // Determine differential particle weight y(x). For the time being, "y = phi" always, but this can be generalized. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -15647,7 +16285,8 @@ void GetParticleWeights() // b) Differential weights; => TBI 20250225 this is now obsolete and superseeded with c), where I use more general approach with sparse histograms // c) Differential phi weights using sparse histograms; // d) Differential pt weights using sparse histograms; - // e) Differential eta weights using sparse histograms. + // e) Differential eta weights using sparse histograms; + // f) Differential charge weights using sparse histograms. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -15683,7 +16322,7 @@ void GetParticleWeights() // b) Differential weights: // differential phi(pt) weights: - if (pw.fUseDiffWeights[wPHIPT]) { + if (pw.fUseDiffWeights[wPHIPT]) { // TBI 20260217 obsolete branch, remove eventually TH1D* phiptWeights = NULL; int nPtBins = res.fResultsPro[AFO_PT]->GetXaxis()->GetNbins(); for (int b = 0; b < nPtBins; b++) { @@ -15712,7 +16351,7 @@ void GetParticleWeights() } // if (pw.fUseDiffWeights[wPHIPT]) { // differential phi(eta) weights: - if (pw.fUseDiffWeights[wPHIETA]) { + if (pw.fUseDiffWeights[wPHIETA]) { // TBI 20260217 obsolete branch, remove eventually TH1D* phietaWeights = NULL; int nEtaBins = res.fResultsPro[AFO_ETA]->GetXaxis()->GetNbins(); for (int b = 0; b < nEtaBins; b++) { @@ -15764,14 +16403,17 @@ void GetParticleWeights() } // ... - // TBI-today ... check if particles weights are avaiable for the phase window I have selected for each dimension with cuts - THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); if (!diffWeightsSparse) { LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"phi\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); } - // okay, just use this sparse histogram with weights: + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + + // Okay, just use this sparse histogram with weights: SetDiffWeightsSparse(diffWeightsSparse, eDWPhi); } // if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { @@ -15782,16 +16424,28 @@ void GetParticleWeights() TString whichCategory = "pt"; // differential pt weights TString whichDimensions = ""; // differential pt weights as a function of particular dimension - // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights - // ... TBI 20250222 proceed here in the same way as above for phi weights - - // TBI-today ... check if particles weights are avaiable for the phase window I have selected for each dimension with cuts + // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights. + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + whichDimensions += "_eta"; + } + if (pw.fUseDiffPtWeights[wPtChargeAxis]) { + whichDimensions += "_charge"; + } + if (pw.fUseDiffPtWeights[wPtCentralityAxis]) { + whichDimensions += "_centrality"; + } + // ... THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); if (!diffWeightsSparse) { LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"pt\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); } + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + // okay, just use this sparse histogram with weights: SetDiffWeightsSparse(diffWeightsSparse, eDWPt); @@ -15803,21 +16457,66 @@ void GetParticleWeights() TString whichCategory = "eta"; // differential eta weights TString whichDimensions = ""; // differential eta weights as a function of particular dimension - // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights - // ... TBI 20250222 proceed here in the same way as above for phi weights - - // TBI-today ... check if particles weights are avaiable for the phase window I have selected for each dimension with cuts + // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights. + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + whichDimensions += "_pt"; + } + if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + whichDimensions += "_charge"; + } + if (pw.fUseDiffEtaWeights[wEtaCentralityAxis]) { + whichDimensions += "_centrality"; + } + // ... THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); if (!diffWeightsSparse) { - LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"pt\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); + LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"eta\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); } + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + // okay, just use this sparse histogram with weights: SetDiffWeightsSparse(diffWeightsSparse, eDWEta); } // if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + // f) Differential charge weights using sparse histograms: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, remember that flag for charge axis serves also as a common boolean to switch off all differential charge weights + + TString whichCategory = "charge"; // differential charge weights + + TString whichDimensions = ""; // differential charge weights as a function of particular dimension + // Remark: the naming convention hardwired here for axes dimensions have to be in sync with what I have in the macro to make these weights. + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + whichDimensions += "_pt"; + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + whichDimensions += "_eta"; + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + whichDimensions += "_centrality"; + } + // ... + + THnSparseF* diffWeightsSparse = GetSparseHistogramWithWeights(pw.fFileWithWeights.Data(), tc.fRunNumber.Data(), whichCategory.Data(), whichDimensions.Data()); + if (!diffWeightsSparse) { + LOGF(fatal, "\033[1;31m%s at line %d : diffWeightsSparse for category \"charge\" is NULL. Check the external file %s with particle weights\033[0m", __FUNCTION__, __LINE__, pw.fFileWithWeights.Data()); + } + + // Check if particle weights are avaiable for the phase window I have selected for each dimension with cuts. + // Basically, I check whether range of each axis is compatible with the cuts i used for variable on that axis. + // Since GetParticleWeights() is called only once, this check is also performed only once. + insanitizeDiffWeightsSparse(diffWeightsSparse); + + // okay, just use this sparse histogram with weights: + SetDiffWeightsSparse(diffWeightsSparse, eDWCharge); + + } // if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -16046,6 +16745,9 @@ void EventCounterForDryRun(eEventCounterForDryRun eVar) const char* FancyFormatting(const char* name) { // Simple utility function to convert ordinary name into fancier formatting. + // If I change something in the formatting here, check if that fancy formatting was hardwired elsewhere, e.g. in void insanitizeDiffWeightsSparse(...) + + // :ff // Examples: // 1. use LaTeX syntax (as supported by ROOT!), for the case when it's possible (e.g. "Phi" => "#{varphi}"); @@ -17571,6 +18273,22 @@ void ExitFunction(const char* functionName) //============================================================ +void printEnvironment() +{ + // Print the content of selected environment variables. + + LOGF(info, ""); + LOGF(info, "Environment variables:"); + LOGF(info, " O2_ROOT = %s", std::getenv("O2_ROOT")); + LOGF(info, " O2PHYSICS_ROOT = %s", std::getenv("O2PHYSICS_ROOT")); + LOGF(info, " ROOT_RELEASE = %s", std::getenv("ROOT_RELEASE")); + LOGF(info, " ROOTSYS = %s", std::getenv("ROOTSYS")); + LOGF(info, ""); + +} // void printEnvironment() + +//============================================================ + void BailOut(bool finalBailout = false) { // Use only locally - bail out if maximum number of events was reached, and dump all results by that point in a local ROOT file. @@ -17658,12 +18376,15 @@ void BailOut(bool finalBailout = false) void FillQvector(const double& dPhi, const double& dPt, const double& dEta) { + // !!! OBSOLETE FUNCTION (as of 20250714) !!! + + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250714, this is an obsolete function, use FillQvectorFromSparse(...) instead (yes, use it also when particles weights are NOT needed) !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + + return; + // Fill integrated Q-vector. // Example usage: this->FillQvector(dPhi, dPt, dEta); - // TBI 20240430 I could optimize further, and have a bare version of this function when weights are NOT used. - // But since usage of weights amounts to checking a few simple booleans here, I do not anticipate any big gain in efficiency... - if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); LOGF(info, "\033[1;32m dPhi = %f\033[0m", dPhi); @@ -17707,8 +18428,10 @@ void FillQvector(const double& dPhi, const double& dPt, const double& dEta) if (pw.fUseWeights[wPHI] || pw.fUseWeights[wPT] || pw.fUseWeights[wETA]) { wToPowerP = std::pow(wPhi * wPt * wEta, wp); qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // Q-vector with weights + // Remark: If ever I will re-use this code, see how I implemented it in void FillQvectorFromSparse() } else { qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights + // Remark: If ever I will re-use this code, see how I implemented it in void FillQvectorFromSparse() } } // for(int wp=0;wp 0.)) { - LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); - LOGF(error, "dPhi = %f", dPhi); + LOGF(error, "\033[1;33m%s at line %d : wPhi is not positive\033[0m", __FUNCTION__, __LINE__); + LOGF(error, "pbyp.fPhi = %f", pbyp.fPhi); if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { - LOGF(fatal, "dPt = %f", dPt); + LOGF(fatal, "pbyp.fPt = %f", pbyp.fPt); } if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { - LOGF(fatal, "dEta = %f", dEta); + LOGF(fatal, "pbyp.fEta = %f", pbyp.fEta); } if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { - LOGF(fatal, "dCharge = %f", dCharge); + LOGF(fatal, "pbyp.fCharge = %f", pbyp.fCharge); } if (pw.fUseDiffPhiWeights[wPhiCentralityAxis]) { - LOGF(fatal, "ebye.Centrality = %f", ebye.fCentrality); + LOGF(fatal, "ebye.fCentrality = %f", ebye.fCentrality); } if (pw.fUseDiffPhiWeights[wPhiVertexZAxis]) { - LOGF(fatal, "ebye.Vz = %f", ebye.fVz); + LOGF(fatal, "ebye.fVz = %f", ebye.fVz); } LOGF(fatal, "Multidimensional weight for enabled dimensions is wPhi = %f", wPhi); } } // if(pw.fUseDiffPhiWeights[wPhiPhiAxis]) // *) Multidimensional pt weights: - if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a comon boolean for this category - wPt = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPt); // TBI 20250224 not sure if this is the right/best approach - // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because - // for them I have ebye data members + if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a common boolean for this category + wPt = WeightFromSparse(eDWPt); if (!(wPt > 0.)) { - LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); - LOGF(error, "dPt = %f", dPt); - if (pw.fUseDiffPtWeights[wPtPtAxis]) { - LOGF(fatal, "dPt = %f", dPt); + LOGF(error, "\033[1;33m%s at line %d : wPt is not positive\033[0m", __FUNCTION__, __LINE__); + LOGF(error, "pbyp.fPt = %f", pbyp.fPt); + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + LOGF(fatal, "pbyp.fEta = %f", pbyp.fEta); + } + if (pw.fUseDiffPtWeights[wPtChargeAxis]) { + LOGF(fatal, "pbyp.fCharge = %f", pbyp.fCharge); + } + if (pw.fUseDiffPtWeights[wPtCentralityAxis]) { + LOGF(fatal, "ebye.fCentrality = %f", ebye.fCentrality); } LOGF(fatal, "Multidimensional weight for enabled dimensions is wPt = %f", wPt); } } // if(pw.fUseDiffPtWeights[wPtPtAxis]) // *) Multidimensional eta weights: - if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a comon boolean for this category - wEta = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWEta); // TBI 20250224 not sure if this is the right/best approach - // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because - // for them I have ebye data members + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a common boolean for this category + wEta = WeightFromSparse(eDWEta); if (!(wEta > 0.)) { - LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); - LOGF(error, "dEta = %f", dEta); - if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - LOGF(fatal, "dEta = %f", dEta); + LOGF(error, "\033[1;33m%s at line %d : wEta is not positive\033[0m", __FUNCTION__, __LINE__); + LOGF(error, "pbyp.fEta = %f", pbyp.fEta); + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + LOGF(fatal, "pbyp.fPt = %f", pbyp.fPt); + } + if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + LOGF(fatal, "pbyp.fCharge = %f", pbyp.fCharge); + } + if (pw.fUseDiffEtaWeights[wEtaCentralityAxis]) { + LOGF(fatal, "ebye.fCentrality = %f", ebye.fCentrality); } LOGF(fatal, "Multidimensional weight for enabled dimensions is wEta = %f", wEta); } } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) + // *) Multidimensional charge weights: + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, 0th axis serves as a common boolean for this category + wCharge = WeightFromSparse(eDWCharge); + if (!(wCharge > 0.)) { + LOGF(error, "\033[1;33m%s at line %d : wCharge is not positive\033[0m", __FUNCTION__, __LINE__); + LOGF(error, "pbyp.fCharge = %f", pbyp.fCharge); + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + LOGF(fatal, "pbyp.fPt = %f", pbyp.fPt); + } + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + LOGF(fatal, "pbyp.fEta = %f", pbyp.fEta); + } + if (pw.fUseDiffChargeWeights[wChargeCentralityAxis]) { + LOGF(fatal, "ebye.fCentrality = %f", ebye.fCentrality); + } + LOGF(fatal, "Multidimensional weight for enabled dimensions is wCharge = %f", wCharge); + } + } // if(pw.fUseDiffChargeWeights[wChargeChargeAxis]) + if (qv.fCalculateQvectors) { for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - wToPowerP = std::pow(wPhi * wPt * wEta, wp); - qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // Q-vector with weights + if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis] || pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wToPowerP = std::pow(wPhi * wPt * wEta * wCharge, wp); + qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // Q-vector with weights, legacy code (TBI 20251027 remove this line) + // qv.fQvector[h][wp] += std::complex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // Q-vector with weights, new code + // TBI 20251028 I have to keep it this way for the time being, otherwise I have to change all over the place, e.g. in TComplex Q(int n, int wp), etc. } else { - qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights + qv.fQvector[h][wp] += TComplex(std::cos(h * pbyp.fPhi), std::sin(h * pbyp.fPhi)); // bare Q-vector without weights, legacy code (TBI 20251027 remove this line) + // qv.fQvector[h][wp] += std::complex(std::cos(h * pbyp.fPhi), std::sin(h * pbyp.fPhi)); // bare Q-vector without weights, new code + // TBI 20251028 I have to keep it this way for the time being, otherwise I have to change all over the place, e.g. in TComplex Q(int n, int wp), etc. } } // for(int wp=0;wp (but it's a major modification, see the comment above within if (qv.fCalculateQvectors) ) } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation - } else if (dEta > 0.) { + } else if (pbyp.fEta > 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fMab[1][e] += wPhi * wPt * wEta; + if (pbyp.fEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fMab[1][e] += wPhi * wPt * wEta * wCharge; for (int h = 0; h < gMaxHarmonic; h++) { { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); + qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * wCharge * std::cos((h + 1) * pbyp.fPhi), wPhi * wPt * wEta * wCharge * std::sin((h + 1) * pbyp.fPhi)); + // TBI 20251028 Replace TComplex with std::complex (but it's a major modification, see the comment above within if (qv.fCalculateQvectors) ) + // Remark: I can hardwire linear weights like this only for 2-p correlations } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation @@ -17882,7 +18634,7 @@ void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& ExitFunction(__FUNCTION__); } -} // void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) +} // void FillQvectorFromSparse() //============================================================ @@ -17890,7 +18642,9 @@ void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine ki { // !!! OBSOLETE FUNCTION (as of 20250527) !!! - LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250527, this is an obsolete function, use FillqvectorNdim(...) and FillqvectorNdimFromSparse(...) instead !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250527, this is an obsolete function, use Fillqvectors() instead (yes, plural!) + its helper function(s) !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + + return; // Fill differential q-vector, in generic kinematic variable. Here "kine" originally meant vs. pt or vs. eta, now it's general. // Example usage #1: this->Fillqvector(dPhi, dPt, PTq); // differential q-vectors without using eta separations @@ -17899,6 +18653,7 @@ void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine ki // Remark: As of 20250527, this function is obsolete, and it's superseeded by more general functions: // a) void FillqvectorNdim(...) (without particle weights) // b) void FillqvectorNdimFromSparse(...) (with particle weights) + // Remark: As of 20251027, FillqvectorNdim(...) and FillqvectorNdimFromSparse(...) are also obsolete, use instead Fillqvectors() (yes, plural!) + its helper function(s) if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); @@ -18243,14 +18998,22 @@ TString StringKineMap(eqvectorKine kineVarChoice) void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvectorKine kineVarChoice, const double& dEta = 0.) { - // Fill differential q-vector in N dimensions, calculated vs. N generic kinematic variables, - // and using only the unit particle weights (for non-unit weights, there is FillqvectorNdimFromSparse(...)). - // Here "kine" originally meant vs. pt or vs. eta, now it's general. + // !!! OBSOLETE FUNCTION (as of 20250717) !!! + + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250717, this is an obsolete function, use Fillqvectors(...) and its helper function FillqvectorFromSparse(...) instead !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + + return; + + // Fill differential q-vector in N dimensions, calculated vs. N generic kinematic variables. + // I use this function both when unit and non-unit particle weights are used (there is no really a big performance penalty, i.e. I do not need bare version only for unit weights). + // Here "kine" originally meant vs. pt or vs. eta, now it's general, also multi-dimensional (i.e. "kine" is a "global bin"). // For more than 1 dimension, e.g. vs. (pt, eta), "kineVarChoice" corresponds to linearized 2D case, in an analogy with "global bin" structure for multidimensional histograms. // Remark 0: "kineVarValues" is now an array, e.g. for qvector vs. (pt, eta), it holds pt and eta of a particle. Ndim is dimensionality of that array. - // Remark 1: The last argument "dEta" is meant to be used only for fqabVector (I need dEta of particle to decide whether particle is added to qa or qb) - // Remark 2: "bin" is always mean to be "linearized global bin", therefore I changed indexing here from "bin-1" to "bin" + // Remark 1: The last argument "dEta" is meant to be used only for fqabVector (I need dEta of particle to decide whether particle is added to qa or qb). + // Remark 2: "bin" is always meant to be "linearized global bin", therefore I changed indexing here from "bin-1" to "bin". + // Remark 3: Whether or not non-unit weights are used, is determined automatically below with flags pw.fUseDiffPhiWeights, pw.fUseDiffPtWeights, etc., which in turn + // are configured in the JSON // Example - the standard 1D case: // double kineArr[1] = {dPt}; @@ -18283,7 +19046,7 @@ void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvect if (res.fResultsPro[AFO_var]) { bin = res.fResultsPro[AFO_var]->FindBin(kineVarValues[0]); // this is linearized 'global bin', for 1D it's the same as ordinary bin - // TBI 20250528 check if the check below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + // TBI 20250528 check if the test below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. if (res.fResultsPro[AFO_var]->IsBinUnderflow(bin) || res.fResultsPro[AFO_var]->IsBinOverflow(bin)) { LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d (%s), kineVarValues[0] = %f is in bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), kineVarValues[0], bin); } @@ -18296,7 +19059,7 @@ void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvect if (res.fResultsPro2D[AFO_var]) { bin = res.fResultsPro2D[AFO_var]->FindBin(kineVarValues[0], kineVarValues[1]); // this is linearized 'global bin' - // TBI 20250528 check if the check below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + // TBI 20250528 check if the test below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. if (res.fResultsPro2D[AFO_var]->IsBinUnderflow(bin) || res.fResultsPro2D[AFO_var]->IsBinOverflow(bin)) { LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d (%s), kineVarValues[0] = %f, kineVarValues[1] = %f is in global bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), kineVarValues[0], kineVarValues[1], bin); } @@ -18309,7 +19072,7 @@ void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvect if (res.fResultsPro3D[AFO_var]) { bin = res.fResultsPro3D[AFO_var]->FindBin(kineVarValues[0], kineVarValues[1], kineVarValues[2]); // this is linearized 'global bin' - // TBI 20250528 check if the check below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + // TBI 20250528 check if the test below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. if (res.fResultsPro3D[AFO_var]->IsBinUnderflow(bin) || res.fResultsPro3D[AFO_var]->IsBinOverflow(bin)) { LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d (%s), kineVarValues[0] = %f, kineVarValues[1] = %f, kineVarValues[2] = %f is in global bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), kineVarValues[0], kineVarValues[1], kineVarValues[2], bin); } @@ -18326,98 +19089,135 @@ void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvect } // switch (Ndim) - // zzzzzzzzzzzzzzzzzzzzzz + // TBI 20250715 I need to review and most likely redesign the code below - but since this function is now obsolete, it's irrelevant + return; // TBI 20250716 remove eventually, here is just a protection against using the code below - /* + // Particle weights from sparse histograms: + // Remark: Keep in sync with corresponding implementation in FillQvectorFromSparse + double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights + double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights + double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights + double wToPowerP = 1.; // weight raised to power p - // *) Mapping between enum's "eqvectorKine" on one side, and "eAsFunctionOf", "eWeights" and "eDiffWeights" on the other: - // TBI 20240212 I could promote this also to a member function, if I need it elsewhere. Or I could use TExMap? - eAsFunctionOf AFO_var = eAsFunctionOf_N; // this local variable determines the enum "eAsFunctionOf" which corresponds to enum "eqvectorKine" - eWeights AFO_weight = eWeights_N; // this local variable determines the enum "eWeights" which corresponds to enum "eqvectorKine" - eDiffWeights AFO_diffWeight = eDiffWeights_N; // this local variable determines the enum "eDiffWeights" which corresponds to enum "eqvectorKine" + // *) Multidimensional phi weights: + if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a common boolean for this category switch (kineVarChoice) { case PTq: { - AFO_var = AFO_PT; - AFO_weight = wPT; - AFO_diffWeight = wPHIPT; // TBI 20250215 this is now obsolete, see the comment in enum + // wPhi = WeightFromSparse(dPhi, kineVarValues[0], 0., 0., eDWPhi); break; } case ETAq: { - AFO_var = AFO_ETA; - AFO_weight = wETA; - AFO_diffWeight = wPHIETA; // TBI 20250215 this is now obsolete, see the comment in enum + // wPhi = WeightFromSparse(dPhi, 0., kineVarValues[0], 0., eDWPhi); break; } case CHARGEq: { - AFO_var = AFO_CHARGE; - AFO_weight = wCHARGE; - AFO_diffWeight = wPHICHARGE; // TBI 20250215 this is now obsolete, see the comment in enum + // wPhi = WeightFromSparse(dPhi, 0., 0., kineVarValues[0], eDWPhi); + break; + } + case PT_ETAq: { + // wPhi = WeightFromSparse(dPhi, kineVarValues[0], kineVarValues[1], 0., eDWPhi); + break; + } + case PT_CHARGEq: { + // wPhi = WeightFromSparse(dPhi, kineVarValues[0], 0., kineVarValues[1], eDWPhi); + break; + } + case ETA_CHARGEq: { + // wPhi = WeightFromSparse(dPhi, 0., kineVarValues[0], kineVarValues[1], eDWPhi); break; } + case PT_ETA_CHARGEq: { + // wPhi = WeightFromSparse(dPhi, kineVarValues[0], kineVarValues[1], kineVarValues[2], eDWPhi); + break; + } + + // ... + default: { - LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); break; } - } // switch(kineVarChoice) + } - // *) Insanity checks on above settings: - if (AFO_var == eAsFunctionOf_N) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == eAsFunctionOf_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + // last argument is enum eDiffWeightCategory. Event quantities, e.g. centrality and vz, I do not need to pass, because + // for them I have ebye data members + if (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); + LOGF(error, "dPhi = %f", dPhi); + LOGF(fatal, "Multidimensional weight for enabled dimensions is wPhi = %f", wPhi); } - if (AFO_weight == eWeights_N) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_weight == eWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } // if(pw.fUseDiffPhiWeights[wPhiPhiAxis]) + + // *) Multidimensional pt weights: + if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a common boolean for this category + switch (kineVarChoice) { + case PTq: { + // wPt = WeightFromSparse(dPhi, kineVarValues[0], 0., 0., eDWPt); + break; + } + case CHARGEq: { + // wPt = WeightFromSparse(dPhi, 0., 0., kineVarValues[0], eDWPt); + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } } - if (AFO_diffWeight == eDiffWeights_N) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_diffWeight == eDiffWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + + if (!(wPt > 0.)) { + LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); + // LOGF(error, "dPt = %f", dPt); + LOGF(fatal, "Multidimensional weight for enabled dimensions is wPt = %f", wPt); } + } // if(pw.fUseDiffPtWeights[wPtPtAxis]) - // *) Get the desired bin number: - int bin = -1; - if (res.fResultsPro[AFO_var]) { - bin = res.fResultsPro[AFO_var]->FindBin(kineVarValue); // this 'bin' starts from 1, i.e. this is genuine histogram bin - if (0 >= bin || res.fResultsPro[AFO_var]->GetNbinsX() < bin) { // either underflow or overflow is hit, meaning that histogram is booked in narrower range than cuts - LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d, bin = %d, kineVarValue = %f \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), bin, kineVarValue); + // *) Multidimensional eta weights: + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a common boolean for this category + switch (kineVarChoice) { + case ETAq: { + // wEta = WeightFromSparse(dPhi, 0., kineVarValues[0], 0., eDWEta); + break; + } + case CHARGEq: { + // wEta = WeightFromSparse(dPhi, 0., 0., kineVarValues[0], eDWEta); + break; } - } - */ - /* - // *) Get all integrated kinematic weights: - double wToPowerP = 1.; // weight raised to power p - double kineVarWeight = 1.; // e.g. this can be integrated pT or eta weight - if (pw.fUseWeights[AFO_weight]) { - kineVarWeight = Weight(kineVarValue, AFO_weight); // corresponding e.g. pt or eta weight - if (!(kineVarWeight > 0.)) { - LOGF(fatal, "\033[1;31m%s at line %d : kineVarWeight is not positive \033[0m", __FUNCTION__, __LINE__); - // TBI 20240212 or could I just skip this particle? - } - } // if(fUseWeights[AFO_weight]) { - - // *) Get all differential phi-weights for this kinematic variable: - // Remark: special treatment is justified for phi-weights, because q-vector is defined in terms of phi-weights. - double diffPhiWeightsForThisKineVar = 1.; - if (pw.fUseDiffWeights[AFO_diffWeight]) { - diffPhiWeightsForThisKineVar = DiffWeight(dPhi, kineVarValue, kineVarChoice); // corresponding differential phi weight as a function of e.g. pt or eta - if (!(diffPhiWeightsForThisKineVar > 0.)) { - LOGF(fatal, "\033[1;31m%s at line %d : diffPhiWeightsForThisKineVar is not positive \033[0m", __FUNCTION__, __LINE__); - // TBI 20240212 or could I just skip this particle? - } - } // if(pw.fUseDiffWeights[AFO_diffWeight]) { + // ... - */ + default: { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + } + + if (!(wEta > 0.)) { + LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); + // LOGF(error, "dEta = %f", dEta); + LOGF(fatal, "Multidimensional weight for enabled dimensions is wEta = %f", wEta); + } + } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) // *) Finally, fill differential q-vector in that linearized "global bin": for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + wToPowerP = std::pow(wPhi * wPt * wEta, wp); + qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // q-vector with weights + } else { + qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights + } } // for(int wp=0;wpAddAt(dPhi, qv.fqvectorEntries[kineVarChoice][bin]); - nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(1, qv.fqvectorEntries[kineVarChoice][bin]); // TBI 20250529 bare, without weights. Otherwise, adapt and use the line below - // nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(diffPhiWeightsForThisKineVar * kineVarWeight, qv.fqvectorEntries[kineVarChoice][bin]); // TBI 20250527 temporarily commented out + nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(wPhi * wPt * wEta, qv.fqvectorEntries[kineVarChoice][bin]); } // *) Multiplicity counter in this bin: @@ -18427,31 +19227,31 @@ void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvect if (es.fCalculateEtaSeparations && qv.fCalculateqvectorsKineEtaSeparations[kineVarChoice]) { // yes, I have decoupled this one from if (qv.fCalculateQvectors) if (kineVarChoice == ETAq || kineVarChoice == PT_ETAq || kineVarChoice == ETA_CHARGEq || kineVarChoice == PT_ETA_CHARGEq) { - LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice == %s . This doesn't make any sense in this context => eta separations cannot be used for differential vectors vs. eta (either 1D or 2D or 3D case). \033[0m", __FUNCTION__, __LINE__, StringKineMap(kineVarChoice).Data()); // _22 + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice == %s . This doesn't make any sense in this context => eta separations cannot be used for differential vectors vs. eta (either 1D or 2D or 3D case). \033[0m", __FUNCTION__, __LINE__, StringKineMap(kineVarChoice).Data()); } if (dEta < 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (dEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fmab[0][kineVarChoice][bin][e] += 1.; // diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation + if (dEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fmab[0][kineVarChoice][bin][e] += wPhi * wPt * wEta; // Remark: I can hardwire linear weight like this only for 2-p correlation for (int h = 0; h < gMaxHarmonic; h++) { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fqabVector[0][kineVarChoice][bin][h][e] += std::complex(std::cos((h + 1) * dPhi), std::sin((h + 1) * dPhi)); // bare q_ab-vector without weights + qv.fqabVector[0][kineVarChoice][bin][h][e] += std::complex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation } else if (dEta > 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fmab[1][kineVarChoice][bin][e] += 1.; // diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation + if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fmab[1][kineVarChoice][bin][e] += wPhi * wPt * wEta; // Remark: I can hardwire linear weight like this only for 2-p correlation for (int h = 0; h < gMaxHarmonic; h++) { { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fqabVector[1][kineVarChoice][bin][h][e] += std::complex(std::cos((h + 1) * dPhi), std::sin((h + 1) * dPhi)); // bare q_ab-vector without weights + qv.fqabVector[1][kineVarChoice][bin][h][e] += std::complex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation @@ -18467,6 +19267,334 @@ void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvect //============================================================ +void Fillqvectors() +{ + // In this function, I fill all requested differential q-vectors, by calling for each requested case a helper function FillqvectorFromSparse(...). + + // :fqv + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + LOGF(info, "\033[1;32m pbyp.fPhi = %f\033[0m", pbyp.fPhi); + LOGF(info, "\033[1;32m pbyp.fPt = %f\033[0m", pbyp.fPt); + LOGF(info, "\033[1;32m pbyp.fEta = %f\033[0m", pbyp.fEta); + LOGF(info, "\033[1;32m pbyp.fCharge = %f\033[0m", pbyp.fCharge); + } + + // *) Local variables: + int bin = -1; // global kine bin + double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights + double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights + double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights + double wCharge = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffChargeWeights + + /* // TBT + // TBI 20250528 check if the test below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + if (res.fResultsPro[AFO_ETA]->IsBinUnderflow(bin) || res.fResultsPro[AFO_ETA]->IsBinOverflow(bin)) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = eta, kineVarValue = %f is in bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, pbyp.fEta, bin); + } + */ + + // ** 1D: + + // ***) pt dependence: + if (tc.fCalculateAsFunctionOf[AFO_PT]) { + + // ****) determine global kine bin: + bin = res.fResultsPro[AFO_PT]->FindBin(pbyp.fPt); // I already checked before that res.fResultsPro[AFO_PT] is not NULL in insanityChecksAfterBooking() + + // ****) determine all supported particle weights: + // w_phi(pt): + if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + // w_pt(pt): + if (pw.fUseDiffPtWeights[wPtPtAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(pt): + if (pw.fUseDiffEtaWeights[wEtaPtAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(pt): + if (pw.fUseDiffChargeWeights[wChargePtAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(PTq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pT) filled for global bin to which this pT corresponds + + } // if(tc.fCalculateAsFunctionOf[AFO_PT]) + + // ***) eta dependence: + if (tc.fCalculateAsFunctionOf[AFO_ETA]) { + + // ****) determine global kine bin: + bin = res.fResultsPro[AFO_ETA]->FindBin(pbyp.fEta); + + // ****) determine all supported particle weights: + // w_phi(eta): + if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + // w_pt(eta): + if (pw.fUseDiffPtWeights[wPtEtaAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(eta): + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(eta): + if (pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(ETAq, bin, wPhi * wPt * wEta * wCharge); // weighted q(eta) filled for global bin to which this eta corresponds + + } // if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA]) + + // ***) charge dependence: + if (tc.fCalculateAsFunctionOf[AFO_CHARGE]) { + + // ****) determine global kine bin: + bin = res.fResultsPro[AFO_CHARGE]->FindBin(pbyp.fCharge); + + // ****) determine all supported particle weights: + // w_phi(charge): + if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + // w_pt(charge): + if (pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(charge): + if (pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(charge): + if (pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(charge) filled for global bin to which this charge corresponds + + } // if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE]) + + // ... + + // ** 2D: + + // ***) pt-eta dependence: + if (tc.fCalculate2DAsFunctionOf[AFO_PT_ETA]) { + + bin = res.fResultsPro2D[AFO_PT_ETA]->FindBin(pbyp.fPt, pbyp.fEta); + + // ****) determine all supported particle weights: + // w_phi(pt,eta): + if (pw.fUseDiffPhiWeights[wPhiPtAxis] && pw.fUseDiffPhiWeights[wPhiEtaAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + + // w_pt(pt,eta): + if (pw.fUseDiffPtWeights[wPtPtAxis] && pw.fUseDiffPtWeights[wPtEtaAxis]) { + wPt = WeightFromSparse(eDWPt); + } + + // w_eta(pt,eta): + if (pw.fUseDiffEtaWeights[wEtaPtAxis] && pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + wEta = WeightFromSparse(eDWEta); + } + + // w_charge(pt,eta): + if (pw.fUseDiffChargeWeights[wChargePtAxis] && pw.fUseDiffChargeWeights[wChargeEtaAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(PT_ETAq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pt,eta) filled for global bin to which this (pt,eta) corresponds + + } // if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA]) + + // ***) pt-charge dependence: + if (tc.fCalculate2DAsFunctionOf[AFO_PT_CHARGE]) { + + // ****) determine global kine bin: + bin = res.fResultsPro2D[AFO_PT_CHARGE]->FindBin(pbyp.fPt, pbyp.fCharge); + + // ****) determine all supported particle weights: + // w_phi(pt,charge): + if (pw.fUseDiffPhiWeights[wPhiPtAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + // w_pt(pt,charge): + if (pw.fUseDiffPtWeights[wPtPtAxis] && pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(pt,charge): + if (pw.fUseDiffEtaWeights[wEtaPtAxis] && pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(pt,charge): + if (pw.fUseDiffChargeWeights[wChargePtAxis] && pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(PT_CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pt,charge) filled for global bin to which this (pt,charge) corresponds + + } // if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) + + // ***) eta-charge dependence: + if (tc.fCalculate2DAsFunctionOf[AFO_ETA_CHARGE]) { + + // ****) determine global kine bin: + bin = res.fResultsPro2D[AFO_ETA_CHARGE]->FindBin(pbyp.fEta, pbyp.fCharge); + + // ****) determine all supported particle weights: + // w_phi(eta,charge): + if (pw.fUseDiffPhiWeights[wPhiEtaAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + // w_pt(eta,charge): + if (pw.fUseDiffPtWeights[wPtEtaAxis] && pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(eta,charge): + if (pw.fUseDiffEtaWeights[wEtaEtaAxis] && pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(eta,charge): + if (pw.fUseDiffChargeWeights[wChargeEtaAxis] && pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(ETA_CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(eta,charge) filled in global bin to which this (eta,charge) corresponds + + } // if (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE]) + + // ... + + // ** 3D: + + // ***) pt-eta-charge dependence: + if (tc.fCalculate3DAsFunctionOf[AFO_PT_ETA_CHARGE]) { + + // ****) determine global kine bin: + bin = res.fResultsPro3D[AFO_PT_ETA_CHARGE]->FindBin(pbyp.fPt, pbyp.fEta, pbyp.fCharge); + + // ****) determine all supported particle weights: + // w_phi(pt,eta,charge): + if (pw.fUseDiffPhiWeights[wPhiPtAxis] && pw.fUseDiffPhiWeights[wPhiEtaAxis] && pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + wPhi = WeightFromSparse(eDWPhi); + } + // w_pt(pt,eta,charge): + if (pw.fUseDiffPtWeights[wPtPtAxis] && pw.fUseDiffPtWeights[wPtEtaAxis] && pw.fUseDiffPtWeights[wPtChargeAxis]) { + wPt = WeightFromSparse(eDWPt); + } + // w_eta(pt,eta,charge): + if (pw.fUseDiffEtaWeights[wEtaPtAxis] && pw.fUseDiffEtaWeights[wEtaEtaAxis] && pw.fUseDiffEtaWeights[wEtaChargeAxis]) { + wEta = WeightFromSparse(eDWEta); + } + // w_charge(pt,eta,charge): + if (pw.fUseDiffChargeWeights[wChargePtAxis] && pw.fUseDiffChargeWeights[wChargeEtaAxis] && pw.fUseDiffChargeWeights[wChargeChargeAxis]) { + wCharge = WeightFromSparse(eDWCharge); + } + + // ****) finally, fill: + FillqvectorFromSparse(PT_ETA_CHARGEq, bin, wPhi * wPt * wEta * wCharge); // weighted q(pt,eta,charge) filled in global bin to which this (pt,eta,charge) corresponds + } + + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + +} // void Fillqvectors() + +//============================================================ + +void FillqvectorFromSparse(const eqvectorKine& kineVarChoice, const int& bin, const double& dWeight) +{ + // TBI 20260211 add a comment + document few example use cases + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + LOGF(info, "\033[1;32m kineVarChoice = %d (%s)\033[0m", static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data()); + LOGF(info, "\033[1;32m bin = %d\033[0m", bin); + LOGF(info, "\033[1;32m dWeight = %f\033[0m", dWeight); + } + + // *) Finally, fill differential q-vector in that linearized "global bin": + double wToPowerP = 1.; // weight raised to power p + + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis] || pw.fUseDiffChargeWeights[wChargeChargeAxis]) { // yes, because the first enum serves as a boolean for that category + wToPowerP = std::pow(dWeight, wp); // dWeight = wPhi * wPt * wEta * wcharge + qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(wToPowerP * std::cos(h * pbyp.fPhi), wToPowerP * std::sin(h * pbyp.fPhi)); // q-vector with weights + } else { + qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(std::cos(h * pbyp.fPhi), std::sin(h * pbyp.fPhi)); // bare q-vector without weights + } + } // for(int wp=0;wpAddAt(pbyp.fPhi, qv.fqvectorEntries[kineVarChoice][bin]); + nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(dWeight, qv.fqvectorEntries[kineVarChoice][bin]); // dWeight = wPhi * wPt * wEta * wCharge + } + + // *) Multiplicity counter in this bin: + qv.fqvectorEntries[kineVarChoice][bin]++; // count number of particles in this differential bin in this event + + // *) Usage of eta separations in differential correlations: + if (es.fCalculateEtaSeparations && qv.fCalculateqvectorsKineEtaSeparations[kineVarChoice]) { // yes, I have decoupled this one from if (qv.fCalculateQvectors) + + if (kineVarChoice == ETAq || kineVarChoice == PT_ETAq || kineVarChoice == ETA_CHARGEq || kineVarChoice == PT_ETA_CHARGEq) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice == %s . This doesn't make any sense in this context => eta separations cannot be used for differential vectors vs. eta (either 1D or 2D or 3D case). \033[0m", __FUNCTION__, __LINE__, StringKineMap(kineVarChoice).Data()); + } + + if (pbyp.fEta < 0.) { + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (pbyp.fEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fmab[0][kineVarChoice][bin][e] += dWeight; // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation + for (int h = 0; h < gMaxHarmonic; h++) { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + qv.fqabVector[0][kineVarChoice][bin][h][e] += std::complex(dWeight * std::cos((h + 1) * pbyp.fPhi), dWeight * std::sin((h + 1) * pbyp.fPhi)); // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation + } + } // for (int h = 0; h < gMaxHarmonic; h++) { + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation + } else if (pbyp.fEta > 0.) { + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (pbyp.fEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fmab[1][kineVarChoice][bin][e] += dWeight; // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation + for (int h = 0; h < gMaxHarmonic; h++) { + { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + qv.fqabVector[1][kineVarChoice][bin][h][e] += std::complex(dWeight * std::cos((h + 1) * pbyp.fPhi), dWeight * std::sin((h + 1) * pbyp.fPhi)); // dWeight = wPhi * wPt * wEta * wCharge => Remark: I can hardwire linear weight like this only for 2-p correlation + } + } // for (int h = 0; h < gMaxHarmonic; h++) { + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation + } + } + } // if(es.fCalculateEtaSeparations) + + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + +} // void FillqvectorFromSparse(eqvectorKine kineVarChoice, const int& bin, const double& dWeight) + +//============================================================ + void CalculateEverything() { // Calculate everything for selected events and particles. @@ -18604,6 +19732,8 @@ void MainLoopOverParticles(T const& tracks) { // This is the main loop over particles, in which Q-vectors (both integrated and differential) and particle histograms are filled, particle cuts applied, etc. + // :mm + // Remark #1: // *) To process only reconstructed Run 3, use processRec(...), i.e. set field "processRec": "true" in json config // *) To process both reconstructed and simulated Run 3, use processRecSim(...), i.e. set field "processRecSim": "true" in json config @@ -18625,12 +19755,6 @@ void MainLoopOverParticles(T const& tracks) StartFunction(__FUNCTION__); } - // *) Declare local kinematic variables: - double dPhi = 0.; // azimuthal angle - double dPt = 0.; // transverse momentum - double dEta = 0.; // pseudorapidity - double dCharge = -44.; // particle charge. Yes, never initialize charge to 0. - // *) If random access of tracks from collection is requested, use Fisher-Yates algorithm to generate random indices: if (tc.fUseFisherYates) { if (tc.fRandomIndices) { @@ -18685,104 +19809,34 @@ void MainLoopOverParticles(T const& tracks) FillParticleHistograms(track, eAfter); } - // *) Intitialize local kinematic variables: + // *) Intitialize global (yes, as of 20250718, I promoted 'em to data members, to gain efficiency) kinematic variables: // Remark: for "eRecSim" processing, kinematics is taken from "reconstructed". - dPhi = track.phi(); - dPt = track.pt(); - dEta = track.eta(); - dCharge = track.sign(); + pbyp.fPhi = track.phi(); + pbyp.fPt = track.pt(); + pbyp.fEta = track.eta(); + pbyp.fCharge = track.sign(); // Remark: Keep in sync all calls and flags below with the ones in InternalValidation(). // *) Integrated Q-vectors: if (qv.fCalculateQvectors || es.fCalculateEtaSeparations) { - if (!(pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffPtWeights[wEtaEtaAxis])) { - // legacy integrated weights: - this->FillQvector(dPhi, dPt, dEta); // all 3 arguments are passed by reference - } else { - // this is now the new approach, with sparse histograms: - this->FillQvectorFromSparse(dPhi, dPt, dEta, dCharge); // particle arguments are passed by reference. - // Event observables (centrality, vertex z, ...), I do not need to pass as arguments, - // as I have data members for them (ebye.fCentrality, ebye.Vz, ...) - } + // This is now the new approach, with sparse histograms: + // **) particle arguments are passed by reference + // **) event observables (centrality, vertex z, ...), I do not need to pass as arguments, as I have data members for them (ebye.fCentrality, ebye.Vz, ...) + // **) I decide within FillQvectorFromSparse(...) whether and which weights are used. So yes, I use this one, despite its name, even when weights are NOT used + // (there is no real performance penalty) + // **) Legacy function FillQvector(...) is obsolete as of 20250714, since I can get both integrated and differential weights from sparse histograms + this->FillQvectorFromSparse(); } // *) Differential q-vectors (keep in sync with the code in InternalValidation()): - // ** 1D: - // ***) pt dependence: - if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT]) && !es.fCalculateEtaSeparations) { - // In this branch I do not need eta separation, so the lighter call can be executed: - double kineArr[1] = {dPt}; - this->FillqvectorNdim(dPhi, kineArr, 1, PTq); - } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { - // In this branch I do need eta separation, so the heavier call must be executed: - double kineArr[1] = {dPt}; - this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); - } - - // ***) eta dependence: - if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[1] = {dEta}; - this->FillqvectorNdim(dPhi, kineArr, 1, ETAq); - } - - // ***) charge dependence: - if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE]) && !es.fCalculateEtaSeparations) { - // In this branch I do not need eta separation, so the lighter call can be executed: - double kineArr[1] = {dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq); - } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) { - // In this branch I do need eta separation, so the heavier call must be executed: - double kineArr[1] = {dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq, dEta); - } - - // ... - - // ** 2D: - // ***) pt-eta dependence: - if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[2] = {dPt, dEta}; - this->FillqvectorNdim(dPhi, kineArr, 2, PT_ETAq); - } - - // ***) pt-charge dependence: - if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) && !es.fCalculateEtaSeparations) { - // In this branch I do not need eta separation, so the lighter call can be executed: - double kineArr[2] = {dPt, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq); - } else if (es.fCalculateEtaSeparations) { // && TBI 20250527 finalize by checking if 2D pt_charge with eta separations was requested - // In this branch I do need eta separation, so the heavier call must be executed: - // double kineArr[2] = {dPt, dCharge}; - // this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq, dEta); // TBI 20250620 enable when I finalize else if above - - if (tc.fVerboseForEachParticle) { // TBI 20250627 temporary here I use this switch, otherwise logs in HL are too heavy - LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! This branch is not finalized yet, i need to implement 2D objects also for eta separations, but it's unlikely I will ever need that in pracice. If I ever add it, just finalize the if statement above, and comment in two lines above !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); - } - } - - // ***) eta-charge dependence: - if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[2] = {dEta, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 2, ETA_CHARGEq); - } + // TBI 20260210 I need here a flag if this calculus is needed at all - // ... - - // ** 3D: - // ***) pt-eta-charge dependence: - if (qv.fCalculateQvectors && (t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE])) { - // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - double kineArr[3] = {dPt, dEta, dCharge}; - this->FillqvectorNdim(dPhi, kineArr, 3, PT_ETA_CHARGEq); - } + this->Fillqvectors(); // within this function, i call FillqvectorFromSparse(...), for each differential q-vector separately // *) Fill nested loops containers (integrated => I fill kine containers for nested loops in FillqvectorNdim(...)): if (nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) { - this->FillNestedLoopsContainers(ebye.fSelectedTracks, dPhi, dPt, dEta); // all 4 arguments are passed by reference + this->FillNestedLoopsContainers(ebye.fSelectedTracks); // all 4 arguments are passed by reference => not true any longer, I have now 4 pbyp data members } // *) Counter of selected tracks in the current event: @@ -18824,12 +19878,19 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) // All analysis workflow is defined step-by-step here, via dedicated function calls. // The order of function calls obviously matters. + // :ss + if (tc.fVerbose) { StartFunction(__FUNCTION__); } // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Print environment: + if (tc.fVerbose) { + printEnvironment(); + } + // *) Dry run: if (tc.fDryRun) { EventCounterForDryRun(eFill); @@ -18890,7 +19951,7 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) // *) Fill event histograms before event cuts: if (eh.fFillEventHistograms || qa.fFillQAEventHistograms2D || qa.fFillQAParticleEventHistograms2D) { - // Remark: I do not above the flag fFillQACorrelationsVsHistograms2D, because as a part of QA I calculate <2> only after cuts in any case + // Remark: I do not check above the flag fFillQACorrelationsVsHistograms2D, because as a part of QA I calculate <2> only after cuts in any case FillEventHistograms(collision, tracks, eBefore); } @@ -18967,11 +20028,28 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) tc.fTimer[eGlobal]->Continue(); // yes } + // *) Print environment: + if (tc.fVerbose) { + printEnvironment(); + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } - // memStatus (summary): Last update: 20250602 + // memStatus (summary): Status at 20260218 (wf-13.sh + file 2023/LHC23zzh/544116/apass5/0140/o2_ctf_run00544116_orbit0034437888_tf0000000601_epn103/008/AO2D.root) + // Remark: disable sequential bailout before doing this test (yes!) + all of UseSetBinLabel, ... UseDatabasetPDG + // ~47K (dry run with 1D objects booked) + // ~61K (all object declaration besides kine objects (diff. q-vectors and eta separations) + all calculus and 1D histograms filled, trivial labels) + // ~61K (all object declaration + 1D kine objects (diff. q-vectors in coarse kine bins: 2 bins in pt and 2 in eta) + all calculus and 1D histograms filled, standard labels) + // ~61K (all object declaration + 1D kine objects (diff. q-vectors in fine kine bins: 16 bins in pt and 10 in eta) + all calculus and 1D histograms filled, standard labels) + // ~62K (all object declaration + 1D kine objects (diff. q-vectors in fine kine bins: 16 bins in pt and 10 in eta) + all calculus and 1D histograms filled, Set_0 labels + // + all 3 sparse histograms only after the cuts) + // ~80K (all object declaration + 1D kine objects (diff. q-vectors in fine kine bins: 16 bins in pt and 10 in eta) + all calculus and 1D histograms filled, Set_0 labels + // + all 3 sparse histograms before and after the cuts) + // ~102K (all object declaration + 1D + 2D + 3D kine objects (diff. q-vectors in fine kine bins: same as above) + all calculus and 1D histograms filled, Set_0 labels) + + // memStatus (summary): Status at 20250602 // Remark: disable sequential bailout before doing this test (yes!) + all of UseSetBinLabel, ... UseDatabasetPDG // ~46K (skeleton - literally) // ~50K (dry run with 1D objects booked) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx index 3f7953f5f11..2149497f2fc 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx @@ -145,6 +145,9 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to bool oldHistAddStatus = TH1::AddDirectoryStatus(); TH1::AddDirectory(kFALSE); + // *) Print environment (here I always print it, in Steer(...) only if verbose is set to true): + printEnvironment(); + // *) Default configuration, booking, binning and cuts: insanityChecksOnDefinitionsOfConfigurables(); // values passed via configurables are insanitized here. Nothing is initialized yet via configurables in this method defaultConfiguration(); // here default values from configurables are taken into account @@ -217,8 +220,11 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to // H) Process both converted reconstructed and corresponding MC truth simulated Run 1 data; // I) Process only converted simulated Run 1 data. - // For testing purposes I have processTest(...) - // J) Process data with minimum subscription to the tables. + // For testing purposes, enhanced QA, etc., I have: + // J) Process data with minimum subscription to the tables; + // K) Process data with more than necessary subscriptions to the tables, only for QA purposes; + // L) Process extra Monte Carlo info the from table HepMCHeavyIons. + // ... // ------------------------------------------- diff --git a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx index 71ef13716a8..f74b90da6c3 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx @@ -43,7 +43,6 @@ struct ThreeParticleCorrelations { // Analysis parameters float centMin = 0.0, centMax = 90.0; - float v0PtMin = 0.6, v0PtMax = 12.0; float v0EtaMax = 0.72; float trackPtMin = 0.2, trackPtMax = 3.0; float trackEtaMax = 0.8; @@ -64,6 +63,8 @@ struct ThreeParticleCorrelations { // V0 filter parameters struct : ConfigurableGroup { std::string prefix = "V0Selection"; + Configurable v0PtMin{"v0PtMin", 0.6, "Minimum V0 transverse momentum"}; + Configurable v0PtMax{"v0PtMax", 12.0, "Maximum V0 transverse momentum"}; Configurable tpcNCrossedRows{"tpcNCrossedRows", 70.0, "Minimum number of TPC crossed rows"}; Configurable decayR{"decayR", 1.2, "Minimum V0 decay radius (cm)"}; Configurable ctau{"ctau", 30.0, "Maximum V0 proper lifetime (cm)"}; @@ -76,6 +77,14 @@ struct ThreeParticleCorrelations { // Track filter parameters float pionPtMin = 0.3, pionPtMax = 2.3, kaonPtMin = 0.5, kaonPtMax = 2.3, protonPtMin = 0.6; float pionPtMid1 = 1.6, pionPtMid2 = 2.0, kaonPtMid1 = 1.5, kaonPtMid2 = 2.0, protonPtMid = 2.3; + struct : ConfigurableGroup { + std::string prefix = "TrackSelection"; + Configurable chi2PerClusterTPC{"chi2PerClusterTPC", 4.0, "Maximum TPC goodness-of-fit Chi2 per cluster"}; + Configurable chi2PerClusterITS{"chi2PerClusterITS", 36.0, "Maximum ITS goodness-of-fit Chi2 per cluster"}; + Configurable dcaZ{"dcaZ", 2.0, "Maximum longitudinal DCA (cm)"}; + Configurable nSigmaTPCvar{"nSigmaTPCvar", 0.0, "Variation in the TPC nSigma"}; + Configurable nSigmaTOFvar{"nSigmaTOFvar", 0.0, "Variation in the TOF nSigma"}; + } trackSelGroup; // RD filter parameters float dEtaMax = 0.05, dEtaMin = 0.023; @@ -111,7 +120,7 @@ struct ThreeParticleCorrelations { // Table aliases - Data using MyFilteredCollisions = soa::Filtered>; using MyFilteredCollision = MyFilteredCollisions::iterator; - using MyFilteredTracks = soa::Filtered>; @@ -124,15 +133,15 @@ struct ThreeParticleCorrelations { using MCRecCollisions = soa::Join; using MyFilteredMCRecCollisions = soa::Filtered; using MyMCV0s = soa::Join; - using MyFilteredMCTracks = soa::Filtered>; // Partitions Partition mcTracks = aod::mcparticle::pt > trackPtMin&& aod::mcparticle::pt < trackPtMax; - Partition mcV0s = aod::mcparticle::pt > v0PtMin&& aod::mcparticle::pt < v0PtMax&& nabs(aod::mcparticle::eta) < v0EtaMax; + Partition mcV0s = aod::mcparticle::pt > v0SelGroup.v0PtMin&& aod::mcparticle::pt < v0SelGroup.v0PtMax&& nabs(aod::mcparticle::eta) < v0EtaMax; Partition mcTriggers = ((aod::mcparticle::pdgCode == static_cast(kLambda0) || aod::mcparticle::pdgCode == static_cast(kLambda0Bar)) && - aod::mcparticle::pt > v0PtMin && aod::mcparticle::pt < v0PtMax && nabs(aod::mcparticle::eta) < v0EtaMax); + aod::mcparticle::pt > v0SelGroup.v0PtMin && aod::mcparticle::pt < v0SelGroup.v0PtMax && nabs(aod::mcparticle::eta) < v0EtaMax); Partition mcAssociates = (((aod::mcparticle::pdgCode == static_cast(kPiPlus) || aod::mcparticle::pdgCode == static_cast(kPiMinus)) && aod::mcparticle::pt > pionPtMin && aod::mcparticle::pt < pionPtMax) || ((aod::mcparticle::pdgCode == static_cast(kKPlus) || aod::mcparticle::pdgCode == static_cast(kKMinus)) && aod::mcparticle::pt > kaonPtMin && aod::mcparticle::pt < kaonPtMax) || ((aod::mcparticle::pdgCode == static_cast(kProton) || aod::mcparticle::pdgCode == static_cast(kProtonBar)) && aod::mcparticle::pt > protonPtMin)); @@ -185,6 +194,8 @@ struct ThreeParticleCorrelations { void init(InitContext const&) { + TH1::SetDefaultSumw2(true); + // Bins of variable width std::vector fineCentBins = {0.0, 2.0, 4.0, 7.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 60.0, 70.0, 80.0, 90.0}; @@ -250,6 +261,12 @@ struct ThreeParticleCorrelations { rQARegistry.add("hTOFPion", "hTOFPion", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); rQARegistry.add("hTOFKaon", "hTOFKaon", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); rQARegistry.add("hTOFProton", "hTOFProton", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); + rQARegistry.add("hTPCPion_MC", "hTPCPion_MC", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); + rQARegistry.add("hTPCKaon_MC", "hTPCKaon_MC", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); + rQARegistry.add("hTPCProton_MC", "hTPCProton_MC", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); + rQARegistry.add("hTOFPion_MC", "hTOFPion_MC", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); + rQARegistry.add("hTOFKaon_MC", "hTOFKaon_MC", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); + rQARegistry.add("hTOFProton_MC", "hTOFProton_MC", {HistType::kTH3D, {{trackPtAxis}, {1001, -50.05, 50.05}, {2, -2, 2}}}); rQARegistry.add("hInvMassLambda", "hInvMassLambda", {HistType::kTH3D, {{lambdaInvMassAxis}, {v0PtAxis}, {centralityAxis}}}); rQARegistry.add("hInvMassAntiLambda", "hInvMassAntiLambda", {HistType::kTH3D, {{lambdaInvMassAxis}, {v0PtAxis}, {centralityAxis}}}); @@ -266,6 +283,8 @@ struct ThreeParticleCorrelations { rPhiStarRegistry.add("hSEPhiStarMean_SS", "hSEPhiStarMean_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_SSP", "hSEPhiStarMean_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_SSN", "hSEPhiStarMean_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarRadial_OS", "hSEPhiStarRadial_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {170, 0.8, 2.5}}}); + rPhiStarRegistry.add("hSEPhiStarRadial_SS", "hSEPhiStarRadial_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {170, 0.8, 2.5}}}); rPhiStarRegistry.add("hMEPhiStarIR_OS", "hMEPhiStarIR_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarIR_SS", "hMEPhiStarIR_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); @@ -275,6 +294,8 @@ struct ThreeParticleCorrelations { rPhiStarRegistry.add("hMEPhiStarMean_SS", "hMEPhiStarMean_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarMean_SSP", "hMEPhiStarMean_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarMean_SSN", "hMEPhiStarMean_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarRadial_OS", "hMEPhiStarRadial_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {170, 0.8, 2.5}}}); + rPhiStarRegistry.add("hMEPhiStarRadial_SS", "hMEPhiStarRadial_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {170, 0.8, 2.5}}}); // Efficiency rMCRegistry.add("hGenerated", "hGenerated", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); @@ -318,39 +339,39 @@ struct ThreeParticleCorrelations { rMCRegistry.add("hTrueSelectProtonN", "hTrueSelectProtonN", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); // Correlations - rSECorrRegistry.add("hSameLambdaPion_SGNL", "Same-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaPion_SB", "Same-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaKaon_SGNL", "Same-event #Lambda - K correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaKaon_SB", "Same-event #Lambda - K correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaProton_SGNL", "Same-event #Lambda - p correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaProton_SB", "Same-event #Lambda - p correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaPion_MC", "Same-event #Lambda - #pi correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaKaon_MC", "Same-event #Lambda - K correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaProton_MC", "Same-event #Lambda - p correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - - rSECorrRegistry.add("hSameLambdaPion_leftSB", "Same-event #Lambda - #pi correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaPion_rightSB", "Same-event #Lambda - #pi correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaKaon_leftSB", "Same-event #Lambda - K correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaKaon_rightSB", "Same-event #Lambda - K correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaProton_leftSB", "Same-event #Lambda - p correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rSECorrRegistry.add("hSameLambdaProton_rightSB", "Same-event #Lambda - p correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - - rMECorrRegistry.add("hMixLambdaPion_SGNL", "Mixed-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaPion_SB", "Mixed-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaKaon_SGNL", "Mixed-event #Lambda - K correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaKaon_SB", "Mixed-event #Lambda - K correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaProton_SGNL", "Mixed-event #Lambda - p correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaProton_SB", "Mixed-event #Lambda - p correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaPion_MC", "Mixed-event #Lambda - #pi correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaKaon_MC", "Mixed-event #Lambda - K correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaProton_MC", "Mixed-event #Lambda - p correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - - rMECorrRegistry.add("hMixLambdaPion_leftSB", "Mixed-event #Lambda - #pi correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaPion_rightSB", "Mixed-event #Lambda - #pi correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaKaon_leftSB", "Mixed-event #Lambda - K correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaKaon_rightSB", "Mixed-event #Lambda - K correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaProton_leftSB", "Mixed-event #Lambda - p correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); - rMECorrRegistry.add("hMixLambdaProton_rightSB", "Mixed-event #Lambda - p correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}); + rSECorrRegistry.add("hSameLambdaPion_SGNL", "Same-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaPion_SB", "Same-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaKaon_SGNL", "Same-event #Lambda - K correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaKaon_SB", "Same-event #Lambda - K correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaProton_SGNL", "Same-event #Lambda - p correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaProton_SB", "Same-event #Lambda - p correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaPion_MC", "Same-event #Lambda - #pi correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaKaon_MC", "Same-event #Lambda - K correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaProton_MC", "Same-event #Lambda - p correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + + rSECorrRegistry.add("hSameLambdaPion_leftSB", "Same-event #Lambda - #pi correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaPion_rightSB", "Same-event #Lambda - #pi correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaKaon_leftSB", "Same-event #Lambda - K correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaKaon_rightSB", "Same-event #Lambda - K correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaProton_leftSB", "Same-event #Lambda - p correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rSECorrRegistry.add("hSameLambdaProton_rightSB", "Same-event #Lambda - p correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + + rMECorrRegistry.add("hMixLambdaPion_SGNL", "Mixed-event #Lambda - #pi correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaPion_SB", "Mixed-event #Lambda - #pi correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaKaon_SGNL", "Mixed-event #Lambda - K correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaKaon_SB", "Mixed-event #Lambda - K correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaProton_SGNL", "Mixed-event #Lambda - p correlator (SGNL region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaProton_SB", "Mixed-event #Lambda - p correlator (SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaPion_MC", "Mixed-event #Lambda - #pi correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaKaon_MC", "Mixed-event #Lambda - K correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaProton_MC", "Mixed-event #Lambda - p correlator (MC)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + + rMECorrRegistry.add("hMixLambdaPion_leftSB", "Mixed-event #Lambda - #pi correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaPion_rightSB", "Mixed-event #Lambda - #pi correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaKaon_leftSB", "Mixed-event #Lambda - K correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaKaon_rightSB", "Mixed-event #Lambda - K correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaProton_leftSB", "Mixed-event #Lambda - p correlator (Left SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); + rMECorrRegistry.add("hMixLambdaProton_rightSB", "Mixed-event #Lambda - p correlator (Right SB region)", {HistType::kTHnSparseF, {{dPhiAxis}, {dEtaAxis}, {centralityAxis}, {zvtxAxis}, {2, -2, 2}, {2, -2, 2}}}, true); ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -766,16 +787,28 @@ struct ThreeParticleCorrelations { rMCRegistry.fill(HIST("hReconstructed"), track.pt(), track.eta(), collision.centFT0C()); if (particle.pdgCode() == kPiPlus) { // Pos pions rMCRegistry.fill(HIST("hRecPionP"), track.pt(), track.eta(), collision.centFT0C()); + rQARegistry.fill(HIST("hTPCPion_MC"), track.pt(), track.tpcNSigmaPi(), track.sign()); + rQARegistry.fill(HIST("hTOFPion_MC"), track.pt(), track.tofNSigmaPi(), track.sign()); } else if (particle.pdgCode() == kPiMinus) { // Neg pions rMCRegistry.fill(HIST("hRecPionN"), track.pt(), track.eta(), collision.centFT0C()); + rQARegistry.fill(HIST("hTPCPion_MC"), track.pt(), track.tpcNSigmaPi(), track.sign()); + rQARegistry.fill(HIST("hTOFPion_MC"), track.pt(), track.tofNSigmaPi(), track.sign()); } else if (particle.pdgCode() == kKPlus) { // Pos kaons rMCRegistry.fill(HIST("hRecKaonP"), track.pt(), track.eta(), collision.centFT0C()); + rQARegistry.fill(HIST("hTPCKaon_MC"), track.pt(), track.tpcNSigmaKa(), track.sign()); + rQARegistry.fill(HIST("hTOFKaon_MC"), track.pt(), track.tofNSigmaKa(), track.sign()); } else if (particle.pdgCode() == kKMinus) { // Neg kaons rMCRegistry.fill(HIST("hRecKaonN"), track.pt(), track.eta(), collision.centFT0C()); + rQARegistry.fill(HIST("hTPCKaon_MC"), track.pt(), track.tpcNSigmaKa(), track.sign()); + rQARegistry.fill(HIST("hTOFKaon_MC"), track.pt(), track.tofNSigmaKa(), track.sign()); } else if (particle.pdgCode() == kProton) { // Pos protons rMCRegistry.fill(HIST("hRecProtonP"), track.pt(), track.eta(), collision.centFT0C()); + rQARegistry.fill(HIST("hTPCProton_MC"), track.pt(), track.tpcNSigmaPr(), track.sign()); + rQARegistry.fill(HIST("hTOFProton_MC"), track.pt(), track.tofNSigmaPr(), track.sign()); } else if (particle.pdgCode() == kProtonBar) { // Neg protons rMCRegistry.fill(HIST("hRecProtonN"), track.pt(), track.eta(), collision.centFT0C()); + rQARegistry.fill(HIST("hTPCProton_MC"), track.pt(), track.tpcNSigmaPr(), track.sign()); + rQARegistry.fill(HIST("hTOFProton_MC"), track.pt(), track.tofNSigmaPr(), track.sign()); } if (trackFilters(track)) { @@ -1027,7 +1060,7 @@ struct ThreeParticleCorrelations { { // Kinematic cuts - if (v0.pt() <= v0PtMin || v0.pt() >= v0PtMax || std::abs(v0.eta()) >= v0EtaMax) { + if (v0.pt() <= v0SelGroup.v0PtMin || v0.pt() >= v0SelGroup.v0PtMax || std::abs(v0.eta()) >= v0EtaMax) { return false; } @@ -1078,26 +1111,33 @@ struct ThreeParticleCorrelations { bool trackFilters(const TrackCand& track) // Track filter { + if (track.tpcChi2NCl() > trackSelGroup.chi2PerClusterTPC || track.itsChi2NCl() > trackSelGroup.chi2PerClusterITS) { + return false; + } + if (track.dcaZ() > trackSelGroup.dcaZ) { + return false; + } + if (!track.hasTOF()) { return false; } if (trackPID(track)[0] == pionID) { // Pions - if (std::abs(track.tpcNSigmaPi()) >= nSigma4) { + if (std::abs(track.tpcNSigmaPi()) >= nSigma4 + trackSelGroup.nSigmaTPCvar) { // TPC return false; } if (track.pt() < pionPtMin) { return false; } else if (track.pt() > pionPtMin && track.pt() < pionPtMid1) { - if (std::abs(track.tofNSigmaPi()) >= nSigma4) { + if (std::abs(track.tofNSigmaPi()) >= nSigma4 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > pionPtMid1 && track.pt() < pionPtMid2) { - if (track.tofNSigmaPi() <= -nSigma4 || track.tofNSigmaPi() >= nSigma2) { + if (track.tofNSigmaPi() <= -nSigma4 - trackSelGroup.nSigmaTOFvar || track.tofNSigmaPi() >= nSigma2 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > pionPtMid2 && track.pt() < pionPtMax) { - if (track.tofNSigmaPi() <= -nSigma4 || track.tofNSigmaPi() >= nSigma0) { + if (track.tofNSigmaPi() <= -nSigma4 - trackSelGroup.nSigmaTOFvar || track.tofNSigmaPi() >= nSigma0 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > pionPtMax) { @@ -1105,21 +1145,21 @@ struct ThreeParticleCorrelations { } } else if (trackPID(track)[0] == kaonID) { // Kaons - if (std::abs(track.tpcNSigmaKa()) >= nSigma4) { + if (std::abs(track.tpcNSigmaKa()) >= nSigma4 + trackSelGroup.nSigmaTPCvar) { // TPC return false; } if (track.pt() < kaonPtMin) { return false; } else if (track.pt() > kaonPtMin && track.pt() < kaonPtMid1) { - if (std::abs(track.tofNSigmaKa()) >= nSigma4) { + if (std::abs(track.tofNSigmaKa()) >= nSigma4 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > kaonPtMid1 && track.pt() < kaonPtMid2) { - if (track.tofNSigmaKa() <= -nSigma1 || track.tofNSigmaKa() >= nSigma4) { + if (track.tofNSigmaKa() <= -nSigma1 - trackSelGroup.nSigmaTOFvar || track.tofNSigmaKa() >= nSigma4 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > kaonPtMid2 && track.pt() < kaonPtMax) { - if (track.tofNSigmaKa() <= nSigma0 || track.tofNSigmaKa() >= nSigma4) { + if (track.tofNSigmaKa() <= nSigma0 - trackSelGroup.nSigmaTOFvar || track.tofNSigmaKa() >= nSigma4 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > kaonPtMax) { @@ -1127,17 +1167,17 @@ struct ThreeParticleCorrelations { } } else if (trackPID(track)[0] == protonID) { // Protons - if (std::abs(track.tpcNSigmaPr()) >= nSigma4) { + if (std::abs(track.tpcNSigmaPr()) >= nSigma4 + trackSelGroup.nSigmaTPCvar) { // TPC return false; } if (track.pt() < protonPtMin) { return false; } else if (track.pt() > protonPtMin && track.pt() < protonPtMid) { - if (std::abs(track.tofNSigmaPr()) >= nSigma4) { + if (std::abs(track.tofNSigmaPr()) >= nSigma4 + trackSelGroup.nSigmaTOFvar) { return false; } } else if (track.pt() > protonPtMid) { - if (track.tofNSigmaPr() <= -nSigma2 || track.tofNSigmaPr() >= nSigma4) { + if (track.tofNSigmaPr() <= -nSigma2 - trackSelGroup.nSigmaTOFvar || track.tofNSigmaPr() >= nSigma4 + trackSelGroup.nSigmaTOFvar) { return false; } } @@ -1229,7 +1269,7 @@ struct ThreeParticleCorrelations { for (double r = rMin; r <= rMax; r += 0.01) { dPhiStar = RecoDecay::constrainAngle(dPhi + std::asin(phaseProton * r) - std::asin(phaseTrack * r), -constants::math::PIHalf); - if (r == rMin) { + if (r == rMin) { // TPC inner radius if (!Mix) { // Same-event if (proton.sign() * track.sign() == -1) { // OS (Electric charge) rPhiStarRegistry.fill(HIST("hSEPhiStarIR_OS"), dPhiStar, dEta); @@ -1262,6 +1302,21 @@ struct ThreeParticleCorrelations { } } + if (!Mix) { // Same-event + if (proton.sign() * track.sign() == -1) { // OS (Electric charge) + rPhiStarRegistry.fill(HIST("hSEPhiStarRadial_OS"), dPhiStar, r); + } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + rPhiStarRegistry.fill(HIST("hSEPhiStarRadial_SS"), dPhiStar, r); + } + + } else { // Mixed-event + if (proton.sign() * track.sign() == -1) { // OS (Electric charge) + rPhiStarRegistry.fill(HIST("hMEPhiStarRadial_OS"), dPhiStar, r); + } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + rPhiStarRegistry.fill(HIST("hMEPhiStarRadial_SS"), dPhiStar, r); + } + } + dPhiStarMean += (dPhiStar / 170); } // End of the TPC radius loop diff --git a/PWGCF/TableProducer/dptDptFilter.cxx b/PWGCF/TableProducer/dptDptFilter.cxx index 0378692eb71..dd703f3b3c3 100644 --- a/PWGCF/TableProducer/dptDptFilter.cxx +++ b/PWGCF/TableProducer/dptDptFilter.cxx @@ -128,7 +128,7 @@ static constexpr float MultiplicityUpperLimitBase[11][8] = { }; /* helpers for the multiplicity/centrality correlations exclusion formulae */ -static const std::string multiplicityCentralityCorrelationsFormulaBase[11][1] = { +static const std::string multiplicityCentralityCorrelationsFormulaBase[11][1] = { // NOLINT /* no system */ {""}, /* pp Run2 */ {""}, /* pPb Run2 */ {""}, @@ -142,7 +142,7 @@ static const std::string multiplicityCentralityCorrelationsFormulaBase[11][1] = /* pO Run3 */ {""}}; /* helpers for the system type assignment */ -static const std::string periodsOnSystemType[11][1] = { +static const std::string periodsOnSystemType[11][1] = { // NOLINT /* no system */ {""}, /* pp Run2 */ {""}, /* pPb Run2 */ {""}, @@ -316,8 +316,8 @@ struct Multiplicity { MultEst classestimator = kV0M; - static constexpr float kForMultiplicityPtLowLimit = 0.001f; - static constexpr float kForMultiplicityPtHighLimit = 50.0f; + static constexpr float KForMultiplicityPtLowLimit = 0.001f; + static constexpr float KForMultiplicityPtHighLimit = 50.0f; float multiplicityClass = -1.0; float multiplicity = 0.0; bool inelgth0 = false; @@ -353,7 +353,7 @@ struct Multiplicity { void setMultiplicityPercentiles(TList* list) { - LOGF(info, "setMultiplicityPercentiles()", "From list %s", list->GetName()); + LOGF(info, "setMultiplicityPercentiles(). From list %s", list->GetName()); fhV0MMultPercentile = reinterpret_cast(list->FindObject("V0MCentMult")); fhCL1MultPercentile = reinterpret_cast(list->FindObject("CL1MCentMult")); fhCL1EtaGapMultPercentile = reinterpret_cast(list->FindObject("CL1EtaGapMCentMult")); @@ -385,7 +385,7 @@ struct Multiplicity { case kProton: /* not clear if we should use IsPhysicalPrimary here */ /* TODO: adapt to FT0M Run 3 and other estimators */ - if (kForMultiplicityPtLowLimit < p.pt() && p.pt() < kForMultiplicityPtHighLimit) { + if (KForMultiplicityPtLowLimit < p.pt() && p.pt() < KForMultiplicityPtHighLimit) { if (p.eta() < 1.0f && -1.0f < p.eta()) { inelgth0 = true; } @@ -434,24 +434,28 @@ struct Multiplicity { if (fhCL1EtaGapMultiplicity != nullptr) { fhCL1EtaGapMultiplicity->Fill(cl1EtaGapM, dNchdEta); } + /* if there is not calibration assign 50% mutltiplicity */ + if (fhV0MMultPercentile == nullptr && fhCL1MultPercentile == nullptr && fhCL1EtaGapMultPercentile == nullptr) { + multiplicityClass = 50; + } switch (classestimator) { case kV0M: if (fhV0MMultPercentile != nullptr) { multiplicityClass = fhV0MMultPercentile->GetBinContent(fhV0MMultPercentile->FindFixBin(v0am + v0cm)); - multiplicity = v0am + v0cm; } + multiplicity = v0am + v0cm; break; case kCL1: if (fhCL1MultPercentile != nullptr) { multiplicityClass = fhCL1MultPercentile->GetBinContent(fhCL1MultPercentile->FindFixBin(cl1m)); - multiplicity = cl1m; } + multiplicity = cl1m; break; case kCL1GAP: if (fhCL1EtaGapMultPercentile != nullptr) { multiplicityClass = fhCL1EtaGapMultPercentile->GetBinContent(fhCL1EtaGapMultPercentile->FindFixBin(cl1EtaGapM)); - multiplicity = cl1EtaGapM; } + multiplicity = cl1EtaGapM; break; default: break; @@ -541,8 +545,10 @@ struct DptDptFilter { Configurable url{"url", "http://ccdb-test.cern.ch:8080", "The CCDB url for the input file"}; Configurable pathNameCorrections{"pathNameCorrections", "", "The CCDB path for the corrections file. Default \"\", i.e. don't load from CCDB"}; Configurable pathNamePID{"pathNamePID", "", "The CCDB path for the PID adjusts file. Default \"\", i.e. don't load from CCDB"}; + Configurable pathNameOTF{"pathNameOTF", "", "The CCDB path for the OTF configuration file. Default \"\", i.e. don't load from CCDB"}; Configurable dateCorrections{"dateCorrections", "20220307", "The CCDB date for the corrections input file"}; Configurable datePID{"datePID", "20220307", "The CCDB date for the PID adjustments input file"}; + Configurable dateOTF{"dateOTF", "20260306", "The CCDB date for the OTF configuration file"}; Configurable suffix{"suffix", "", "Dataset period suffix for metadata discrimination"}; } cfginputfile; Configurable cfgFullDerivedData{"cfgFullDerivedData", false, "Produce the full derived data for external storage. Default false"}; @@ -591,9 +597,12 @@ struct DptDptFilter { Produces gencollisionsinfo; Multiplicity multiplicity; + std::string otfGenerator; + Service ccdb; + bool storedCcdbInfo = false; Preslice perCollision = aod::track::collisionId; - void init(InitContext const&) + void init(InitContext& initContext) { using namespace dptdptfilter; @@ -639,10 +648,25 @@ struct DptDptFilter { triggerSelectionFlags = getTriggerSelection(cfgEventSelection.triggSel.value.c_str()); traceCollId0 = cfgTraceCollId0; - /* get the system type */ - fSystem = getSystemType(cfgSystemForPeriod.value); - fLhcRun = multRunForSystemMap.at(fSystem); + /* get the data type and the system type */ fDataType = getDataType(cfgDataType); + if (fDataType != kOnTheFly) { + fSystem = getSystemType(cfgSystemForPeriod.value); + fLhcRun = multRunForSystemMap.at(fSystem); + } else { + std::string tmpstr; + getTaskOptionValue(initContext, "generator-task", "configFile", tmpstr, false); + TString fullPath = tmpstr; + auto tokens = fullPath.Tokenize("/"); + if (tokens->GetEntries() > 0) { + otfGenerator = TString(tokens->At(tokens->GetEntries() - 1)->GetName()).ReplaceAll(".ini", ""); + } else { + /* let's take it from the time being from the data type string */ + otfGenerator = TString(cfgDataType).ReplaceAll("OnTheFlyMC_", ""); + } + delete tokens; + LOGF(info, "The generator configuration file: %s", otfGenerator.c_str()); + } /* the multiplicities outliers exclusion */ multiplicityCentralityCorrelationsExclusion = getExclusionFormula(cfgEventSelection.multiplicitiesExclusionFormula->getData()[fSystem][0].c_str()); @@ -674,9 +698,9 @@ struct DptDptFilter { fhVertexZA = new TH1F("VertexZA", "Vertex Z; z_{vtx}", zvtxbins, zvtxlow, zvtxup); /* helpers for the multiplicity/centrality axes definition */ -#define DPTDPTCENTRALITYAXIS 105, -0.5f, 104.5f +#define DPTDPTCENTRALITYAXIS 105, 0.f, 105.0f #define DPTDPTFWMULTIPLICITYAXIS(est) 1000, 0.0f, cfgEventSelection.multiplicityUpperLimit->getData()[fSystem][est] -#define DPTDPTMULTIPLICITYAXIS(est) cfgEventSelection.multiplicityUpperLimit->getData()[fSystem][est] + 1, -0.5f, cfgEventSelection.multiplicityUpperLimit->getData()[fSystem][est] + 0.5f +#define DPTDPTMULTIPLICITYAXIS(est) cfgEventSelection.multiplicityUpperLimit->getData()[fSystem][est] + 1, 0.0f, cfgEventSelection.multiplicityUpperLimit->getData()[fSystem][est] + 1.0f std::string_view multestimator = getCentMultEstimatorName(fCentMultEstimator); fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", DPTDPTCENTRALITYAXIS); @@ -762,6 +786,23 @@ struct DptDptFilter { fOutputList->Add(fhTrueVertexZAA); } } + /* initialize access to the CCDB */ + ccdb->setURL(cfginputfile.url); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + void getCCDBInformation() + { + /* let's get a potential OTF configuration */ + if ((cfginputfile.dateOTF.value.length() > 0) && (cfginputfile.pathNameOTF.value.length() > 0) && !storedCcdbInfo) { + LOGF(info, "Getting information for OTF configuration from %s, at %s", cfginputfile.pathNameOTF.value.c_str(), cfginputfile.dateOTF.value.c_str()); + TList* otfinfo = getCCDBInput(ccdb, cfginputfile.pathNameOTF.value.c_str(), cfginputfile.dateOTF.value.c_str(), true, otfGenerator); + if (otfinfo != nullptr) { + multiplicity.setMultiplicityPercentiles(otfinfo); + } + storedCcdbInfo = true; + } } template @@ -1052,6 +1093,8 @@ void DptDptFilter::processOnTheFlyGeneratorLevel(aod::McCollision const& mccolli fhTrueVertexZB->Fill(mccollision.posZ()); /* we assign a default value for the time being */ float centormult = 50.0f; + /* ask for configuration */ + getCCDBInformation(); if (isEventSelected(mccollision, centormult)) { acceptedEvent = true; multiplicity.extractMultiplicity(mcparticles); @@ -1200,13 +1243,13 @@ struct DptDptFilterTracks { tpcExcluder = TpcExcludeTrack(tpcExclude); tpcExcluder.setCuts(pLowCut, pUpCut, nLowCut, nUpCut); - /* self configure system type and data type */ - o2::framework::LabeledArray tmpLabeledArray = {}; - getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgSystemForPeriod", tmpLabeledArray, false); - fSystem = getSystemType(tmpLabeledArray); + /* self configure data type and system */ std::string tmpstr; getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgDataType", tmpstr, false); fDataType = getDataType(tmpstr); + o2::framework::LabeledArray tmpLabeledArray = {}; + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgSystemForPeriod", tmpLabeledArray, false); + fSystem = getSystemType(tmpLabeledArray); /* required ambiguous tracks checks? */ if (dofilterDetectorLevelWithoutPIDAmbiguous || dofilterDetectorLevelWithPIDAmbiguous || dofilterDetectorLevelWithFullPIDAmbiguous || diff --git a/PWGCF/TableProducer/dptDptFilter.h b/PWGCF/TableProducer/dptDptFilter.h index 1d431bbde3f..9c51fbbf60a 100644 --- a/PWGCF/TableProducer/dptDptFilter.h +++ b/PWGCF/TableProducer/dptDptFilter.h @@ -809,6 +809,23 @@ struct DptDptTrackSelection { bool requirePvContributor = false; }; +SystemType fSystem = SystemNoSystem; +MultRunType fLhcRun = MultRunRUN1RUN2; +DataType fDataType = kData; +CentMultEstimatorType fCentMultEstimator = CentMultV0M; +OccupancyEstimationType fOccupancyEstimation = OccupancyNOOCC; /* the occupancy estimator to use */ + +float fMinOccupancy = 0.0f; /* the minimum allowed occupancy */ +float fMaxOccupancy = 1e6f; /* the maximum allowed occupancy */ + +/* adaptations for the pp nightly checks */ +analysis::CheckRangeCfg traceDCAOutliers; +bool traceOutOfSpeciesParticles = false; +int recoIdMethod = 0; +float particleMaxDCAxy = 999.9f; +float particleMaxDCAZ = 999.9f; +bool traceCollId0 = false; + inline TList* getCCDBInput(auto& ccdb, const char* ccdbpath, const char* ccdbdate, bool periodInPath = false, const std::string& suffix = "") { std::tm cfgtm = {}; @@ -826,13 +843,20 @@ inline TList* getCCDBInput(auto& ccdb, const char* ccdbpath, const char* ccdbdat return tmpStr; }; - std::string actualPeriod = cleanPeriod(metadataInfo.get("LPMProductionTag")); + std::string actualPeriod; + if (fDataType != kOnTheFly) { + actualPeriod = cleanPeriod(metadataInfo.get("LPMProductionTag")); + } else { + actualPeriod = suffix; + } std::string actualPath = ccdbpath; if (periodInPath) { actualPath = actualPath + "/" + actualPeriod; } - if (suffix.length() > 0) { - actualPeriod = actualPeriod + "_" + suffix; + if (fDataType != kOnTheFly) { + if (suffix.length() > 0) { + actualPeriod = actualPeriod + "_" + suffix; + } } TList* lst = nullptr; @@ -846,23 +870,6 @@ inline TList* getCCDBInput(auto& ccdb, const char* ccdbpath, const char* ccdbdat return lst; } -SystemType fSystem = SystemNoSystem; -MultRunType fLhcRun = MultRunRUN1RUN2; -DataType fDataType = kData; -CentMultEstimatorType fCentMultEstimator = CentMultV0M; -OccupancyEstimationType fOccupancyEstimation = OccupancyNOOCC; /* the occupancy estimator to use */ - -float fMinOccupancy = 0.0f; /* the minimum allowed occupancy */ -float fMaxOccupancy = 1e6f; /* the maximum allowed occupancy */ - -/* adaptations for the pp nightly checks */ -analysis::CheckRangeCfg traceDCAOutliers; -bool traceOutOfSpeciesParticles = false; -int recoIdMethod = 0; -float particleMaxDCAxy = 999.9f; -float particleMaxDCAZ = 999.9f; -bool traceCollId0 = false; - inline std::bitset<32> getTriggerSelection(std::string_view const& triggstr) { std::bitset<32> flags; @@ -896,27 +903,31 @@ inline std::bitset<32> getTriggerSelection(std::string_view const& triggstr) inline SystemType getSystemType(auto const& periodsForSysType) { - auto period = metadataInfo.get("LPMProductionTag"); - auto anchoredPeriod = metadataInfo.get("AnchorProduction"); - bool checkAnchor = anchoredPeriod.length() > 0; - - for (SystemType sT = SystemNoSystem; sT < SystemNoOfSystems; ++sT) { - const std::string& periods = periodsForSysType[static_cast(sT)][0]; - auto contains = [periods](auto const& period) { - if (periods.find(period) != std::string::npos) { - return true; - } - return false; - }; - if (periods.length() > 0) { - if (contains(period) || (checkAnchor && contains(anchoredPeriod))) { - LOGF(info, "DptDptCorrelations::getSystemType(). Assigned system type %s for period %s", systemExternalNamesMap.at(static_cast(sT)).data(), period.c_str()); - return sT; + if (fDataType != kOnTheFly) { + auto period = metadataInfo.get("LPMProductionTag"); + auto anchoredPeriod = metadataInfo.get("AnchorProduction"); + bool checkAnchor = anchoredPeriod.length() > 0; + + for (SystemType sT = SystemNoSystem; sT < SystemNoOfSystems; ++sT) { + const std::string& periods = periodsForSysType[static_cast(sT)][0]; + auto contains = [periods](auto const& period) { + if (periods.find(period) != std::string::npos) { + return true; + } + return false; + }; + if (periods.length() > 0) { + if (contains(period) || (checkAnchor && contains(anchoredPeriod))) { + LOGF(info, "DptDptCorrelations::getSystemType(). Assigned system type %s for period %s", systemExternalNamesMap.at(static_cast(sT)).data(), period.c_str()); + return sT; + } } } + LOGF(fatal, "DptDptCorrelations::getSystemType(). No system type for period: %s", period.c_str()); + return SystemPbPb; + } else { + return SystemNeNeRun3; } - LOGF(fatal, "DptDptCorrelations::getSystemType(). No system type for period: %s", period.c_str()); - return SystemPbPb; } /// \brief Type of data according to the configuration string @@ -933,7 +944,7 @@ inline DataType getDataType(std::string const& datastr) return kMC; } else if (datastr == "FastMC") { return kFastMC; - } else if (datastr == "OnTheFlyMC") { + } else if (datastr.starts_with("OnTheFlyMC")) { return kOnTheFly; } else { LOGF(fatal, "DptDptCorrelations::getDataType(). Wrong type of dat: %d", datastr.c_str()); diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index 0197160a5e1..c57427a92c5 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -236,7 +236,8 @@ struct Filter2Prong { if (c.isSelD0bar() > 0) { output2ProngTracks(cfcollisions.begin().globalIndex(), - prongCFId[0], prongCFId[1], c.pt(), c.eta(), c.phi(), hfHelper.invMassD0barToKPi(c), aod::cf2prongtrack::D0barToKPi); + prongCFId[0], prongCFId[1], c.pt(), c.eta(), c.phi(), hfHelper.invMassD0barToKPi(c), + c.isSelD0() > 0 ? aod::cf2prongtrack::D0barToKPi : aod::cf2prongtrack::D0barToKPiExclusive); if constexpr (std::experimental::is_detected::value) { mlvecd.clear(); for (const float val : c.mlProbD0()) @@ -288,7 +289,7 @@ struct Filter2Prong { } } output2ProngMcParts(prongCFId[0], prongCFId[1], - (mcParticle.pdgCode() >= 0 ? aod::cf2prongtrack::D0ToPiK : aod::cf2prongtrack::D0barToKPi) | ((mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) ? aod::cf2prongmcpart::Prompt : 0)); + (mcParticle.pdgCode() >= 0 ? aod::cf2prongtrack::D0ToPiK : aod::cf2prongtrack::D0barToKPiExclusive) | ((mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) ? aod::cf2prongmcpart::Prompt : 0)); } } PROCESS_SWITCH(Filter2Prong, processMC, "Process MC 2-prong daughters", false); diff --git a/PWGCF/TableProducer/filterCorrelations.cxx b/PWGCF/TableProducer/filterCorrelations.cxx index 889c18034b2..6ceaaa6c815 100644 --- a/PWGCF/TableProducer/filterCorrelations.cxx +++ b/PWGCF/TableProducer/filterCorrelations.cxx @@ -20,12 +20,17 @@ #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "MathUtils/detail/TypeTruncation.h" +#include +#include +#include #include +#include #include // required for is_detected #include @@ -85,6 +90,9 @@ struct FilterCF { O2_DEFINE_CONFIGURABLE(nsigmaCutITSProton, float, 3, "proton nsigma ITS") O2_DEFINE_CONFIGURABLE(dcaxymax, float, 999.f, "maximum dcaxy of tracks") O2_DEFINE_CONFIGURABLE(dcazmax, float, 999.f, "maximum dcaz of tracks") + O2_DEFINE_CONFIGURABLE(enablePtDepDCAxy, bool, false, "Enable pT-dependent DCAxy cut: |DCAxy| < a + b/pT") + O2_DEFINE_CONFIGURABLE(dcaXyConst, float, 0.004f, "Constant term 'a' for pT-dependent DCAxy cut: |DCAxy| < a + b/pT (cm)") + O2_DEFINE_CONFIGURABLE(dcaXySlope, float, 0.013f, "Slope term 'b' for pT-dependent DCAxy cut: |DCAxy| < a + b/pT (cm x GeV/c)") O2_DEFINE_CONFIGURABLE(itsnclusters, int, 5, "minimum number of ITS clusters for tracks") O2_DEFINE_CONFIGURABLE(tpcncrossedrows, int, 80, "minimum number of TPC crossed rows for tracks") O2_DEFINE_CONFIGURABLE(tpcnclusters, int, 50, "minimum number of TPC clusters found") @@ -105,6 +113,8 @@ struct FilterCF { OutputObj yields{TH3F("yields", "centrality vs pT vs eta", 100, 0, 100, 40, 0, 20, 100, -2, 2)}; OutputObj etaphi{TH3F("etaphi", "centrality vs eta vs phi", 100, 0, 100, 100, -2, 2, 200, 0, 2 * M_PI)}; + HistogramRegistry registrytrackQA{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + Produces outputCollisions; Produces outputTracks; @@ -125,6 +135,22 @@ struct FilterCF { std::vector mcReconstructedCache; std::vector mcParticleLabelsCache; + void init(InitContext&) + { + if (doprocessTrackQA) { + registrytrackQA.add("zvtx", "Z Vertex position; posz (cm); Events", HistType::kTH1F, {{100, -12, 12}}); + registrytrackQA.add("eta", "eta distribution; eta; arb. units", HistType::kTH1F, {{100, -2, 2}}); + registrytrackQA.add("pT", "pT distribution; #it{p}_{T} (GeV/#it{c}); arb. units", HistType::kTH1F, {{1000, 0, 30}}); + registrytrackQA.add("ptdcaxy", "pT vs DCAxy; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", HistType::kTH2F, {{100, 0, 10}, {200, -1, 1}}); + registrytrackQA.add("ptdcaz", "pT vs DCAz; #it{p}_{T} (GeV/#it{c}); DCA_{z} (cm)", HistType::kTH2F, {{100, 0, 10}, {600, -3.0, 3.0}}); + registrytrackQA.add("tpcxrows", "TPC crossed rows; TPC X-rows; Counts", HistType::kTH1F, {{180, 0, 180}}); + registrytrackQA.add("tpcnclst", "TPC found clusters; TPC N_{cls}; Counts", HistType::kTH1F, {{180, 0, 180}}); + registrytrackQA.add("itsnclst", "ITS clusters; ITS N_{cls}; Counts", HistType::kTH1F, {{10, 0, 10}}); + registrytrackQA.add("chi2tpc", "Chi2 per TPC cluster; #chi^{2}/TPC cluster; Counts", HistType::kTH1F, {{100, 0, 10}}); + registrytrackQA.add("chi2its", "Chi2 per ITS cluster; #chi^{2}/ITS cluster; Counts", HistType::kTH1F, {{60, 0, 60}}); + } + } + template bool keepCollision(TCollision& collision) { @@ -150,8 +176,8 @@ struct FilterCF { return isMultSelected && collision.sel8() && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) && collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); else return false; - } else if (cfgTrigger == 13) { // relevant for OO/NeNe - return isMultSelected && collision.sel8() && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (cfgTrigger == 13) { // relevant for pO/OO/NeNe --recommended by Physics Board on 27.01.2026 + return isMultSelected && collision.sel8() && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); } return false; } @@ -242,6 +268,14 @@ struct FilterCF { return 0; } + inline float getMaxDCAxy(float pt) + { + if (!enablePtDepDCAxy) { + return dcaxymax; // Use constant cut if pT-dependent cut is disabled + } + return dcaXyConst + dcaXySlope / pt; // a + b/pT + } + template using HasMultTables = decltype(std::declval().multNTracksPV()); @@ -280,7 +314,8 @@ struct FilterCF { if (cfgTransientTables) outputCollRefs(collision.globalIndex()); for (auto& track : tracks) { - if ((std::abs(track.dcaXY()) > dcaxymax) || (std::abs(track.dcaZ()) > dcazmax)) { + float maxDCAxy = getMaxDCAxy(track.pt()); + if ((std::abs(track.dcaXY()) > maxDCAxy) || (std::abs(track.dcaZ()) > dcazmax)) { continue; } @@ -311,6 +346,35 @@ struct FilterCF { } PROCESS_SWITCH(FilterCF, processDataMults, "Process data with multiplicity sets", false); + void processTrackQA(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) + { + if (!keepCollision(collision)) { + return; + } + registrytrackQA.fill(HIST("zvtx"), collision.posZ()); + for (const auto& track : tracks) { + if (!track.isGlobalTrack()) { + continue; // trackQA for global tracks only + } + float maxDCAxy = getMaxDCAxy(track.pt()); + if ((std::abs(track.dcaXY()) > maxDCAxy) || (std::abs(track.dcaZ()) > dcazmax)) { + continue; + } + registrytrackQA.fill(HIST("eta"), track.eta()); + registrytrackQA.fill(HIST("pT"), track.pt()); + registrytrackQA.fill(HIST("ptdcaxy"), track.pt(), track.dcaXY()); + registrytrackQA.fill(HIST("ptdcaz"), track.pt(), track.dcaZ()); + registrytrackQA.fill(HIST("tpcxrows"), track.tpcNClsCrossedRows()); + registrytrackQA.fill(HIST("tpcnclst"), track.tpcNClsFound()); + registrytrackQA.fill(HIST("itsnclst"), track.itsNCls()); + if (track.tpcNClsFound() > 0) + registrytrackQA.fill(HIST("chi2tpc"), track.tpcChi2NCl()); + if (track.itsNCls() > 0) + registrytrackQA.fill(HIST("chi2its"), track.itsChi2NCl()); + } + } + PROCESS_SWITCH(FilterCF, processTrackQA, "Process track QA", false); + /// \brief Process MC data for a given set of MC collisions and associated particles and tracks /// \param mcCollisions The collection of MC collisions /// \param allParticles The collection of all MC particles @@ -526,6 +590,9 @@ struct MultiplicitySelector { if (doprocessFT0CVariant1) { enabledFunctions++; } + if (doprocessFT0CVariant2) { + enabledFunctions++; + } if (doprocessFT0A) { enabledFunctions++; } @@ -571,6 +638,14 @@ struct MultiplicitySelector { } PROCESS_SWITCH(MultiplicitySelector, processFT0CVariant1, "Select FT0CVariant1 centrality as multiplicity", false); + void processFT0CVariant2(aod::CentFT0CVariant2s const& centralities) + { + for (auto& c : centralities) { + output(c.centFT0CVariant2()); + } + } + PROCESS_SWITCH(MultiplicitySelector, processFT0CVariant2, "Select FT0CVariant2 centrality as multiplicity", false); + void processFT0A(aod::CentFT0As const& centralities) { for (auto& c : centralities) { diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 5a63485f389..0460b80886f 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -86,6 +86,7 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value (suggested: 0.02)"); O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, int, 0, "0 = OFF and 1 = ON for local efficiency"); + O2_DEFINE_CONFIGURABLE(cfgDropStepRECO, bool, false, "choice to drop step RECO if efficiency correction is used") O2_DEFINE_CONFIGURABLE(cfgCentBinsForMC, int, 0, "0 = OFF and 1 = ON for data like multiplicity/centrality bins for MC steps"); O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 0, "BitMask for track selection systematics; refer to the enum TrackSelectionCuts in filtering task"); O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") @@ -108,6 +109,7 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgPtDepMLbkg, std::vector, {}, "pT interval for ML training") O2_DEFINE_CONFIGURABLE(cfgPtCentDepMLbkgSel, std::vector, {}, "Bkg ML selection") + O2_DEFINE_CONFIGURABLE(cfgPtCentDepMLpromptSel, std::vector, {}, "Prompt ML selection") ConfigurableAxis axisVertex{"axisVertex", {7, -7, 7}, "vertex axis for histograms"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; @@ -133,7 +135,7 @@ struct CorrelationTask { // Track filters Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); - Filter cfTrackFilter = (nabs(aod::cftrack::eta) < cfgCutEta) && (aod::cftrack::pt > cfgCutPt) && ((aod::track::trackType & (uint8_t)cfgTrackBitMask) == (uint8_t)cfgTrackBitMask); + Filter cfTrackFilter = (nabs(aod::cftrack::eta) < cfgCutEta) && (aod::cftrack::pt > cfgCutPt) && ncheckbit(aod::track::trackType, as(cfgTrackBitMask)); // MC filters Filter cfMCCollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; @@ -173,8 +175,14 @@ struct CorrelationTask { void init(o2::framework::InitContext&) { - if ((doprocessSame2ProngDerivedML || doprocessSame2Prong2ProngML || doprocessMixed2ProngDerivedML || doprocessMixed2Prong2ProngML) && (cfgPtDepMLbkg->empty() || cfgPtCentDepMLbkgSel->empty())) - LOGF(fatal, "cfgPtDepMLbkg or cfgPtCentDepMLbkgSel can not be empty when ML 2-prong selections are used."); + if (doprocessSame2ProngDerivedML || doprocessSame2Prong2ProngML || doprocessMixed2ProngDerivedML || doprocessMixed2Prong2ProngML || doprocessMCEfficiency2ProngML || doprocessMCReflection2ProngML) { + if (cfgPtDepMLbkg->empty() || cfgPtCentDepMLbkgSel->empty()) + LOGF(fatal, "cfgPtDepMLbkg or cfgPtCentDepMLbkgSel can not be empty when ML 2-prong selections are used."); + if (cfgPtDepMLbkg->size() != cfgPtCentDepMLbkgSel->size()) + LOGF(fatal, "cfgPtDepMLbkg and cfgPtCentDepMLbkgSel must be same size."); + if (!cfgPtCentDepMLpromptSel->empty() && cfgPtCentDepMLpromptSel->size() != cfgPtDepMLbkg->size()) + LOGF(fatal, "cfgPtDepMLbkg and cfgPtCentDepMLpromptSel must be same size."); + } registry.add("yields", "multiplicity/centrality vs pT vs eta", {HistType::kTH3F, {{100, 0, 100, "/multiplicity/centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); registry.add("etaphi", "multiplicity/centrality vs eta vs phi", {HistType::kTH3F, {{100, 0, 100, "multiplicity/centrality"}, {100, -2, 2, "#eta"}, {200, 0, o2::constants::math::TwoPI, "#varphi"}}}); if (doprocessSame2ProngDerived || doprocessSame2ProngDerivedML || doprocessSame2Prong2Prong || doprocessSame2Prong2ProngML || doprocessMCSameDerived2Prong) { @@ -189,6 +197,12 @@ struct CorrelationTask { registry.add("invMassTwoPartDEta", "2D 2-prong invariant mass (GeV/c^2)", {HistType::kTHnSparseF, {axisSpecMass, axisSpecMass, axisPtTrigger, axisPtAssoc, axisDeltaEta}}); } } + if (doprocessMCReflection2ProngML) { + const AxisSpec& a = AxisSpec(axisInvMass); + AxisSpec axisSpecMass = {1000, a.binEdges[0], a.binEdges[a.getNbins()]}; + registry.add("invMassSignal", "2-prong invariant mass (GeV/c^2)", {HistType::kTH3F, {axisSpecMass, axisPtTrigger, axisMultiplicity}}); + registry.add("invMassReflected", "2-prong invariant mass (GeV/c^2)", {HistType::kTH3F, {axisSpecMass, axisPtTrigger, axisMultiplicity}}); + } if (doprocessSameDerivedMultSet) { if (cfgMultCorrelationsMask == 0) LOGF(fatal, "cfgMultCorrelationsMask can not be 0 when MultSet process functions are in use."); @@ -281,7 +295,7 @@ struct CorrelationTask { if (!cfgEfficiencyAssociated.value.empty()) efficiencyAssociatedCache.reserve(512); - if (doprocessMCEfficiency2Prong || doprocessMCEfficiency2ProngML) { + if (doprocessMCEfficiency2Prong || doprocessMCEfficiency2ProngML || doprocessMCReflection2ProngML) { p2indexCache.reserve(16); if (cfgMcTriggerPDGs->empty()) LOGF(fatal, "At least one PDG code in {} is to be selected to process 2-prong efficiency.", cfgMcTriggerPDGs.name); @@ -319,7 +333,15 @@ struct CorrelationTask { { auto it = std::lower_bound(cfgPtDepMLbkg->begin(), cfgPtDepMLbkg->end(), track.pt()); int idx = std::distance(cfgPtDepMLbkg->begin(), it) - 1; - return !((track.decay() == 0 && track.mlProbD0()[0] > cfgPtCentDepMLbkgSel->at(idx)) || (track.decay() == 1 && track.mlProbD0bar()[0] > cfgPtCentDepMLbkgSel->at(idx))); + return (track.decay() != aod::cf2prongtrack::D0ToPiK || + (track.mlProbD0()[0] < cfgPtCentDepMLbkgSel->at(idx) && // not background + (cfgPtCentDepMLpromptSel->empty() || + track.mlProbD0()[1] > cfgPtCentDepMLpromptSel->at(idx)))) && // prompt + + ((track.decay() != aod::cf2prongtrack::D0barToKPi && track.decay() != aod::cf2prongtrack::D0barToKPiExclusive) || + (track.mlProbD0bar()[0] < cfgPtCentDepMLbkgSel->at(idx) && // not background + (cfgPtCentDepMLpromptSel->empty() || + track.mlProbD0bar()[1] > cfgPtCentDepMLpromptSel->at(idx)))); // prompt } template @@ -564,7 +586,7 @@ struct CorrelationTask { } if constexpr (std::experimental::is_detected::value) { - if (((track1.mcDecay() != aod::cf2prongtrack::D0ToPiK) && (track1.mcDecay() != aod::cf2prongtrack::D0barToKPi)) || (track1.decay() & aod::cf2prongmcpart::Prompt) == 0) + if (((track1.mcDecay() != aod::cf2prongtrack::D0ToPiK) && (track1.mcDecay() != aod::cf2prongtrack::D0barToKPiExclusive)) || (!cfgPtCentDepMLpromptSel->empty() && (track1.decay() & aod::cf2prongmcpart::Prompt) == 0)) continue; } else if constexpr (std::experimental::is_detected::value) { if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(track1.decay()))) == 0u) { @@ -647,7 +669,7 @@ struct CorrelationTask { // If decay attributes are found for the second track/particle, we assume 2p-2p correlation if constexpr (std::experimental::is_detected::value) { - if ((((track2.mcDecay()) != aod::cf2prongtrack::D0ToPiK) && ((track2.mcDecay()) != aod::cf2prongtrack::D0barToKPi)) || (track2.decay() & aod::cf2prongmcpart::Prompt) == 0) + if ((((track2.mcDecay()) != aod::cf2prongtrack::D0ToPiK) && ((track2.mcDecay()) != aod::cf2prongtrack::D0barToKPiExclusive)) || (!cfgPtCentDepMLpromptSel->empty() && (track2.decay() & aod::cf2prongmcpart::Prompt) == 0)) continue; } else if constexpr (std::experimental::is_detected::value) { if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(track2.decay()))) == 0u) { @@ -856,10 +878,14 @@ struct CorrelationTask { else fillQA(collision, multiplicity, tracks1); - same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + const bool hasEfficiency = (cfg.mEfficiencyAssociated != nullptr || cfg.mEfficiencyTrigger != nullptr); + const bool fillReco = !(cfgDropStepRECO && hasEfficiency); - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (fillReco) { + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + } + if (hasEfficiency) { same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); } @@ -982,19 +1008,28 @@ struct CorrelationTask { LOGF(info, "processMixedDerived: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), collision1.globalIndex(), collision1.posZ(), collision1.multiplicity(), collision2.globalIndex(), collision2.posZ(), collision2.multiplicity()); } + bool hasEfficiencyMixed = (cfg.mEfficiencyAssociated != nullptr || cfg.mEfficiencyTrigger != nullptr); + bool fillRecoMixed = !(cfgDropStepRECO && hasEfficiencyMixed); + if (it.isNewWindow()) { loadEfficiency(collision1.timestamp()); + hasEfficiencyMixed = (cfg.mEfficiencyAssociated != nullptr || cfg.mEfficiencyTrigger != nullptr); + fillRecoMixed = !(cfgDropStepRECO && hasEfficiencyMixed); - mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepReconstructed); + if (fillRecoMixed) { + mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepReconstructed); + } } // LOGF(info, "Tracks: %d and %d entries", tracks1.size(), tracks2.size()); registry.fill(HIST("eventcount_mixed"), bin); registry.fill(HIST("trackcount_mixed"), bin, tracks1.size(), tracks2.size()); - fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); + if (fillRecoMixed) { + fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); + } - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (hasEfficiencyMixed) { if (it.isNewWindow()) { mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepCorrected); } @@ -1140,6 +1175,8 @@ struct CorrelationTask { } for (const auto& track : groupedTracks) { + if (cfgTrackBitMask > 0 && (track.trackType() & (uint8_t)cfgTrackBitMask) != (uint8_t)cfgTrackBitMask) + continue; if (track.has_cfMCParticle()) { const auto& mcParticle = track.cfMCParticle(); if ((doprocessMCEfficiency2Prong || doprocessMCEfficiency2ProngML) && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end()) @@ -1158,7 +1195,7 @@ struct CorrelationTask { } PROCESS_SWITCH(CorrelationTask, processMCEfficiency, "MC: Extract efficiencies", false); - template + template void processMCEfficiency2ProngT(soa::Filtered::iterator const& mcCollision, soa::Join const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const&, p2type const& p2tracks, Preslice& perCollision2Prong) { auto multiplicity = mcCollision.multiplicity(); @@ -1174,11 +1211,16 @@ struct CorrelationTask { p2indexCache.clear(); for (const auto& mcParticle : mcParticles) { if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end()) { - if (((mcParticle.mcDecay() != aod::cf2prongtrack::D0ToPiK) && (mcParticle.mcDecay() != aod::cf2prongtrack::D0barToKPi)) || (mcParticle.decay() & aod::cf2prongmcpart::Prompt) == 0) + if ((mcParticle.mcDecay() != aod::cf2prongtrack::D0ToPiK) && (mcParticle.mcDecay() != aod::cf2prongtrack::D0barToKPiExclusive)) continue; // wrong decay channel + if constexpr (!reflectionSpec) { + if (!cfgPtCentDepMLpromptSel->empty() && (mcParticle.decay() & aod::cf2prongmcpart::Prompt) == 0) + continue; + } if (mcParticle.cfParticleDaugh0Id() < 0 && mcParticle.cfParticleDaugh1Id() < 0) continue; // daughters not found - same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); + if constexpr (!reflectionSpec) + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); p2indexCache.push_back(mcParticle.globalIndex()); } } @@ -1186,14 +1228,17 @@ struct CorrelationTask { auto grouped2ProngTracks = p2tracks.sliceBy(perCollision2Prong, collision.globalIndex()); for (const auto& p2track : grouped2ProngTracks) { - if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(p2track.decay()))) == 0u) - continue; + if constexpr (!reflectionSpec) { + if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(p2track.decay()))) == 0u) + continue; + } // Check if the mc particles of the prongs are found. if constexpr (std::experimental::is_detected::value) { if (!passMLScore(p2track)) continue; } - same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); + if constexpr (!reflectionSpec) + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); auto fillMC2p = [&](const aod::CFTracksWithLabel::iterator& p) -> bool { if (!p.has_cfMCParticle()) return false; @@ -1204,7 +1249,15 @@ struct CorrelationTask { if (m == p2indexCache.end()) return false; const auto& mcParticle = mcParticles.iteratorAt(*m - mcParticles.begin().globalIndex()); - same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); + if constexpr (!reflectionSpec) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); + } else { + if ((mcParticle.mcDecay() == aod::cf2prongtrack::D0barToKPiExclusive && (p2track.decay() == aod::cf2prongtrack::D0barToKPiExclusive || p2track.decay() == aod::cf2prongtrack::D0barToKPi)) || + (mcParticle.mcDecay() == aod::cf2prongtrack::D0ToPiK && p2track.decay() == aod::cf2prongtrack::D0ToPiK)) + registry.fill(HIST("invMassSignal"), p2track.invMass(), p2track.pt(), multiplicity); + else // one particle may be filled into both histograms through duplicates + registry.fill(HIST("invMassReflected"), p2track.invMass(), p2track.pt(), multiplicity); + } return true; }; if (p2track.has_cfTrackProng0()) { @@ -1218,7 +1271,8 @@ struct CorrelationTask { } // fake track - same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); + if constexpr (!reflectionSpec) + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); } } } @@ -1226,17 +1280,23 @@ struct CorrelationTask { Preslice perCollision2Prong = aod::cftrack::cfCollisionId; void processMCEfficiency2Prong(soa::Filtered::iterator const& mcCollision, soa::Join const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const& tracks, aod::CF2ProngTracks const& p2tracks) { - processMCEfficiency2ProngT(mcCollision, mcParticles, collisions, tracks, p2tracks, perCollision2Prong); + processMCEfficiency2ProngT(mcCollision, mcParticles, collisions, tracks, p2tracks, perCollision2Prong); } PROCESS_SWITCH(CorrelationTask, processMCEfficiency2Prong, "MC: Extract efficiencies for 2-prong particles", false); Preslice> perCollision2ProngML = aod::cftrack::cfCollisionId; void processMCEfficiency2ProngML(soa::Filtered::iterator const& mcCollision, soa::Join const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const& tracks, soa::Join const& p2tracks) { - processMCEfficiency2ProngT(mcCollision, mcParticles, collisions, tracks, p2tracks, perCollision2ProngML); + processMCEfficiency2ProngT(mcCollision, mcParticles, collisions, tracks, p2tracks, perCollision2ProngML); } PROCESS_SWITCH(CorrelationTask, processMCEfficiency2ProngML, "MC: Extract efficiencies for 2-prong particles with ML scores", false); + void processMCReflection2ProngML(soa::Filtered::iterator const& mcCollision, soa::Join const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const& tracks, soa::Join const& p2tracks) + { + processMCEfficiency2ProngT(mcCollision, mcParticles, collisions, tracks, p2tracks, perCollision2ProngML); + } + PROCESS_SWITCH(CorrelationTask, processMCReflection2ProngML, "MC: Extract reflection distributions for 2-prong particles with ML scores", false); + template void processMCSameDerivedT(soa::Filtered::iterator const& mcCollision, Particles1 const& mcParticles1, Particles2 const& mcParticles2, soa::SmallGroups const& collisions) { diff --git a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h index f9b79242ac0..8dd31e82aa1 100644 --- a/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h +++ b/PWGCF/TwoParticleCorrelations/DataModel/LongRangeDerived.h @@ -34,16 +34,16 @@ DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float); //! sum of am DECLARE_SOA_COLUMN(GapSide, gapSide, uint8_t); // 0 for side A, 1 for side C, 2 for both sides } // namespace lrcorrcolltable -DECLARE_SOA_TABLE(CollLRTables, "AOD", "COLLLRTABLE", +DECLARE_SOA_TABLE(LRCollisions, "AOD", "LRCOLLISION", o2::soa::Index<>, bc::RunNumber, lrcorrcolltable::Zvtx, lrcorrcolltable::Multiplicity, lrcorrcolltable::Centrality, timestamp::Timestamp); -using CollLRTable = CollLRTables::iterator; +using LRCollision = LRCollisions::iterator; -DECLARE_SOA_TABLE(UpcCollLRTables, "AOD", "UPCCOLLLRTABLE", +DECLARE_SOA_TABLE(UpcLRCollisions, "AOD", "UPCLRCOLLISION", o2::soa::Index<>, bc::GlobalBC, bc::RunNumber, @@ -52,30 +52,30 @@ DECLARE_SOA_TABLE(UpcCollLRTables, "AOD", "UPCCOLLLRTABLE", lrcorrcolltable::TotalFT0AmplitudeA, lrcorrcolltable::TotalFT0AmplitudeC, lrcorrcolltable::TotalFV0AmplitudeA); -using UpcCollLRTable = UpcCollLRTables::iterator; +using UpcLRCollision = UpcLRCollisions::iterator; -DECLARE_SOA_TABLE(UpcSgCollLRTables, "AOD", "UPCSGCOLLLRTABLE", +DECLARE_SOA_TABLE(UpcSgLRCollisions, "AOD", "UPCSGLRCOLLISION", lrcorrcolltable::GapSide); -using UpcSgCollLRTable = UpcSgCollLRTables::iterator; +using UpcSgLRCollision = UpcSgLRCollisions::iterator; namespace lrcorrzdctable { -DECLARE_SOA_INDEX_COLUMN(UpcCollLRTable, upcCollLRTable); +DECLARE_SOA_INDEX_COLUMN(UpcLRCollision, upcLRCollision); DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); } // namespace lrcorrzdctable -DECLARE_SOA_TABLE(ZdcLRTables, "AOD", "ZDCLRTABLE", +DECLARE_SOA_TABLE(LRZdcs, "AOD", "LRZDC", o2::soa::Index<>, - lrcorrzdctable::UpcCollLRTableId, + lrcorrzdctable::UpcLRCollisionId, lrcorrzdctable::EnergyCommonZNA, lrcorrzdctable::EnergyCommonZNC); -using ZdcLRTable = ZdcLRTables::iterator; +using LRZdc = LRZdcs::iterator; namespace lrcorrtrktable { -DECLARE_SOA_INDEX_COLUMN(CollLRTable, collLRTable); -DECLARE_SOA_INDEX_COLUMN(UpcCollLRTable, upcCollLRTable); +DECLARE_SOA_INDEX_COLUMN(LRCollision, lrCollision); +DECLARE_SOA_INDEX_COLUMN(UpcLRCollision, upcLRCollision); DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); @@ -99,36 +99,36 @@ enum V0TrackPid { }; } // namespace lrcorrtrktable -DECLARE_SOA_TABLE(TrkLRTables, "AOD", "TRKLRTABLE", +DECLARE_SOA_TABLE(LRMidTracks, "AOD", "LRMIDTRACK", o2::soa::Index<>, - lrcorrtrktable::CollLRTableId, + lrcorrtrktable::LRCollisionId, lrcorrtrktable::Pt, lrcorrtrktable::Eta, lrcorrtrktable::Phi, lrcorrtrktable::TrackType); -using TrkLRTable = TrkLRTables::iterator; +using LRMidTrack = LRMidTracks::iterator; -DECLARE_SOA_TABLE(Ft0aLRTables, "AOD", "FT0ALRTABLE", +DECLARE_SOA_TABLE(LRFt0aTracks, "AOD", "LRFT0ATRACK", o2::soa::Index<>, - lrcorrtrktable::CollLRTableId, + lrcorrtrktable::LRCollisionId, lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using Ft0aLRTable = Ft0aLRTables::iterator; +using LRFt0aTrack = LRFt0aTracks::iterator; -DECLARE_SOA_TABLE(Ft0cLRTables, "AOD", "FT0CLRTABLE", +DECLARE_SOA_TABLE(LRFt0cTracks, "AOD", "LRFT0CTRACK", o2::soa::Index<>, - lrcorrtrktable::CollLRTableId, + lrcorrtrktable::LRCollisionId, lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using Ft0cLRTable = Ft0cLRTables::iterator; +using LRFt0cTrack = LRFt0cTracks::iterator; -DECLARE_SOA_TABLE(V0TrkLRTables, "AOD", "V0TRKLRTABLE", +DECLARE_SOA_TABLE(LRV0Tracks, "AOD", "LRV0TRACK", o2::soa::Index<>, - lrcorrtrktable::CollLRTableId, + lrcorrtrktable::LRCollisionId, lrcorrtrktable::IdPos, lrcorrtrktable::IdNeg, lrcorrtrktable::Pt, @@ -136,54 +136,54 @@ DECLARE_SOA_TABLE(V0TrkLRTables, "AOD", "V0TRKLRTABLE", lrcorrtrktable::Phi, lrcorrtrktable::InvMass, lrcorrtrktable::V0Type); -using V0TrkLRTable = V0TrkLRTables::iterator; +using LRV0Track = LRV0Tracks::iterator; -DECLARE_SOA_TABLE(MftTrkLRTables, "AOD", "MFTTRKLRTABLE", +DECLARE_SOA_TABLE(LRMftTracks, "AOD", "LRMFTTRACK", o2::soa::Index<>, - lrcorrtrktable::CollLRTableId, + lrcorrtrktable::LRCollisionId, lrcorrtrktable::Pt, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using MftTrkLRTable = MftTrkLRTables::iterator; +using LRMftTrack = LRMftTracks::iterator; -DECLARE_SOA_TABLE(MftBestTrkLRTables, "AOD", "MFTBESTTRKLRTABLE", +DECLARE_SOA_TABLE(LRMftBestTracks, "AOD", "LRMFTBESTTRACK", o2::soa::Index<>, - lrcorrtrktable::CollLRTableId, + lrcorrtrktable::LRCollisionId, lrcorrtrktable::Pt, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using MftBestTrkLRTable = MftBestTrkLRTables::iterator; +using LRMftBestTrack = LRMftBestTracks::iterator; -DECLARE_SOA_TABLE(TrkLRUpcTables, "AOD", "TRKLRUPCTABLE", +DECLARE_SOA_TABLE(UpcLRMidTracks, "AOD", "UPCLRMIDTRACK", o2::soa::Index<>, - lrcorrtrktable::UpcCollLRTableId, + lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::Pt, lrcorrtrktable::Eta, lrcorrtrktable::Phi, lrcorrtrktable::TrackType); -using TrkLRUpcTable = TrkLRUpcTables::iterator; +using UpcLRMidTrack = UpcLRMidTracks::iterator; -DECLARE_SOA_TABLE(Ft0aLRUpcTables, "AOD", "FT0ALRUpcTABLE", +DECLARE_SOA_TABLE(UpcLRFt0aTracks, "AOD", "UPCLRFT0ATRACK", o2::soa::Index<>, - lrcorrtrktable::UpcCollLRTableId, + lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using Ft0aLRUpcTable = Ft0aLRUpcTables::iterator; +using UpcLRFt0aTrack = UpcLRFt0aTracks::iterator; -DECLARE_SOA_TABLE(Ft0cLRUpcTables, "AOD", "FT0CLRUpcTABLE", +DECLARE_SOA_TABLE(UpcLRFt0cTracks, "AOD", "UPCLRFT0CTRACK", o2::soa::Index<>, - lrcorrtrktable::UpcCollLRTableId, + lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::ChannelID, lrcorrtrktable::Amplitude, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using Ft0cLRUpcTable = Ft0cLRUpcTables::iterator; +using UpcLRFt0cTrack = UpcLRFt0cTracks::iterator; -DECLARE_SOA_TABLE(V0TrkLRUpcTables, "AOD", "V0TRKLRUPCTABLE", +DECLARE_SOA_TABLE(UpcLRV0Tracks, "AOD", "UPCLRV0TRACK", o2::soa::Index<>, - lrcorrtrktable::UpcCollLRTableId, + lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::IdPos, lrcorrtrktable::IdNeg, lrcorrtrktable::Pt, @@ -191,23 +191,23 @@ DECLARE_SOA_TABLE(V0TrkLRUpcTables, "AOD", "V0TRKLRUPCTABLE", lrcorrtrktable::Phi, lrcorrtrktable::InvMass, lrcorrtrktable::V0Type); -using V0TrkLRUpcTable = V0TrkLRUpcTables::iterator; +using UpcLRV0Track = UpcLRV0Tracks::iterator; -DECLARE_SOA_TABLE(MftTrkLRUpcTables, "AOD", "MFTTRKLRUPCTABLE", +DECLARE_SOA_TABLE(UpcLRMftTracks, "AOD", "UPCLRMFTTRACK", o2::soa::Index<>, - lrcorrtrktable::UpcCollLRTableId, + lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::Pt, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using MftTrkLRUpcTable = MftTrkLRUpcTables::iterator; +using UpcLRMftTrack = UpcLRMftTracks::iterator; -DECLARE_SOA_TABLE(MftBestTrkLRUpcTables, "AOD", "MFTBESTTRKLRUPCTABLE", +DECLARE_SOA_TABLE(UpcLRMftBestTracks, "AOD", "UPCLRMFTBESTTRACK", o2::soa::Index<>, - lrcorrtrktable::UpcCollLRTableId, + lrcorrtrktable::UpcLRCollisionId, lrcorrtrktable::Pt, lrcorrtrktable::Eta, lrcorrtrktable::Phi); -using MftBestTrkLRUpcTable = MftBestTrkLRUpcTables::iterator; +using UpcLRMftBestTrack = UpcLRMftBestTracks::iterator; } // namespace o2::aod diff --git a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx index a7d90746265..816eb4da038 100644 --- a/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx +++ b/PWGCF/TwoParticleCorrelations/TableProducer/longrangeMaker.cxx @@ -233,24 +233,24 @@ struct LongrangeMaker { cfgSgCuts = (SGCutParHolder)sgCuts; } - Produces collisionLRTable; - Produces tracksLRTable; - Produces ft0aLRTable; - Produces ft0cLRTable; - Produces mftLRTable; - Produces mftbestLRTable; - Produces v0LRTable; - - Produces outupccol; - Produces outsgupccol; - Produces outzdctable; - - Produces tracksLRUpcTable; - Produces ft0aLRUpcTable; - Produces ft0cLRUpcTable; - Produces mftLRUpcTable; - Produces mftbestLRUpcTable; - Produces v0LRUpcTable; + Produces lrcollision; + Produces lrmidtracks; + Produces lrft0atracks; + Produces lrft0ctracks; + Produces lrmfttracks; + Produces lrmftbesttracks; + Produces lrv0tracks; + + Produces upclrcollision; + Produces upcsglrcollision; + Produces lrzdcs; + + Produces upclrmidtracks; + Produces upclrft0atracks; + Produces upclrft0ctracks; + Produces upclrmfttracks; + Produces upclrmftbesttracks; + Produces upclrv0tracks; Filter fTracksEta = nabs(aod::track::eta) < cfgtrksel.cfgEtaCut; Filter fTracksPt = (aod::track::pt > cfgtrksel.cfgPtCutMin) && (aod::track::pt < cfgtrksel.cfgPtCutMax); @@ -273,7 +273,7 @@ struct LongrangeMaker { auto centrality = selColCent(col); auto bc = col.bc_as(); - collisionLRTable(bc.runNumber(), col.posZ(), multiplicity, centrality, bc.timestamp()); + lrcollision(bc.runNumber(), col.posZ(), multiplicity, centrality, bc.timestamp()); // track loop for (const auto& track : tracks) { @@ -281,13 +281,13 @@ struct LongrangeMaker { continue; if (!myTrackFilter.IsSelected(track)) continue; - tracksLRTable(collisionLRTable.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); + lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); if (getTrackPID(track) == PionTrackN) - tracksLRTable(collisionLRTable.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpPion); + lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpPion); if (getTrackPID(track) == KaonTrackN) - tracksLRTable(collisionLRTable.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpKaon); + lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpKaon); if (getTrackPID(track) == ProtonTrackN) - tracksLRTable(collisionLRTable.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpProton); + lrmidtracks(lrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpProton); } // ft0 loop @@ -298,14 +298,14 @@ struct LongrangeMaker { float ampl = ft0.amplitudeA()[iCh]; auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); - ft0aLRTable(collisionLRTable.lastIndex(), chanelid, ampl, eta, phi); + lrft0atracks(lrcollision.lastIndex(), chanelid, ampl, eta, phi); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh]; float ampl = ft0.amplitudeC()[iCh]; auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); - ft0cLRTable(collisionLRTable.lastIndex(), chanelid, ampl, eta, phi); + lrft0ctracks(lrcollision.lastIndex(), chanelid, ampl, eta, phi); } } @@ -315,7 +315,7 @@ struct LongrangeMaker { continue; auto phi = track.phi(); o2::math_utils::bringTo02Pi(phi); - mftLRTable(collisionLRTable.lastIndex(), track.pt(), track.eta(), phi); + lrmfttracks(lrcollision.lastIndex(), track.pt(), track.eta(), phi); } if (retracks.size() > 0) { @@ -329,7 +329,7 @@ struct LongrangeMaker { } auto phi = track.phi(); o2::math_utils::bringTo02Pi(phi); - mftbestLRTable(collisionLRTable.lastIndex(), track.pt(), track.eta(), phi); + lrmftbesttracks(lrcollision.lastIndex(), track.pt(), track.eta(), phi); } } @@ -344,8 +344,8 @@ struct LongrangeMaker { // K0short if (isSelectK0s(col, v0)) { // candidate is K0s - v0LRTable(collisionLRTable.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); + lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); } // Lambda and Anti-Lambda @@ -355,13 +355,13 @@ struct LongrangeMaker { // Note: candidate compatible with Lambda and Anti-Lambda hypothesis are counted twice (once for each hypothesis) if (lambdaTag) { // candidate is Lambda massV0 = v0.mLambda(); - v0LRTable(collisionLRTable.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); + lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); } if (antilambdaTag) { // candidate is Anti-lambda massV0 = v0.mAntiLambda(); - v0LRTable(collisionLRTable.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); + lrv0tracks(lrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); } // end of Lambda and Anti-Lambda processing } } // process function @@ -398,13 +398,13 @@ struct LongrangeMaker { upchelpers::FITInfo fitInfo{}; udhelpers::getFITinfo(fitInfo, newbc, bcs, ft0s, fv0as, fdds); auto multiplicity = countNTracks(tracks); - outupccol(bc.globalBC(), bc.runNumber(), col.posZ(), multiplicity, fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFV0A); - outsgupccol(issgevent); + upclrcollision(bc.globalBC(), bc.runNumber(), col.posZ(), multiplicity, fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFV0A); + upcsglrcollision(issgevent); if (newbc.has_zdc()) { auto zdc = newbc.zdc(); - outzdctable(outupccol.lastIndex(), zdc.energyCommonZNA(), zdc.energyCommonZNC()); + lrzdcs(upclrcollision.lastIndex(), zdc.energyCommonZNA(), zdc.energyCommonZNC()); } else { - outzdctable(outupccol.lastIndex(), -999, -999); + lrzdcs(upclrcollision.lastIndex(), -999, -999); } // track loop @@ -413,13 +413,13 @@ struct LongrangeMaker { continue; if (!myTrackFilter.IsSelected(track)) continue; - tracksLRUpcTable(outupccol.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); + upclrmidtracks(upclrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpCharge); if (getTrackPID(track) == PionTrackN) - tracksLRUpcTable(outupccol.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpPion); + upclrmidtracks(upclrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpPion); if (getTrackPID(track) == KaonTrackN) - tracksLRUpcTable(outupccol.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpKaon); + upclrmidtracks(upclrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpKaon); if (getTrackPID(track) == ProtonTrackN) - tracksLRUpcTable(outupccol.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpProton); + upclrmidtracks(upclrcollision.lastIndex(), track.pt(), track.eta(), track.phi(), aod::lrcorrtrktable::kSpProton); } // ft0 loop @@ -430,14 +430,14 @@ struct LongrangeMaker { float ampl = ft0.amplitudeA()[iCh]; auto phi = getPhiFT0(chanelid, 0); auto eta = getEtaFT0(chanelid, 0); - ft0aLRUpcTable(outupccol.lastIndex(), chanelid, ampl, eta, phi); + upclrft0atracks(upclrcollision.lastIndex(), chanelid, ampl, eta, phi); } for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { auto chanelid = ft0.channelC()[iCh]; float ampl = ft0.amplitudeC()[iCh]; auto phi = getPhiFT0(chanelid, 1); auto eta = getEtaFT0(chanelid, 1); - ft0cLRUpcTable(outupccol.lastIndex(), chanelid, ampl, eta, phi); + upclrft0ctracks(upclrcollision.lastIndex(), chanelid, ampl, eta, phi); } } @@ -447,7 +447,7 @@ struct LongrangeMaker { continue; auto phi = track.phi(); o2::math_utils::bringTo02Pi(phi); - mftLRUpcTable(outupccol.lastIndex(), track.pt(), track.eta(), phi); + upclrmfttracks(upclrcollision.lastIndex(), track.pt(), track.eta(), phi); } if (retracks.size() > 0) { @@ -461,7 +461,7 @@ struct LongrangeMaker { } auto phi = track.phi(); o2::math_utils::bringTo02Pi(phi); - mftbestLRUpcTable(outupccol.lastIndex(), track.pt(), track.eta(), phi); + upclrmftbesttracks(upclrcollision.lastIndex(), track.pt(), track.eta(), phi); } } @@ -476,8 +476,8 @@ struct LongrangeMaker { // K0short if (isSelectK0s(col, v0)) { // candidate is K0s - v0LRUpcTable(outupccol.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); + upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::lrcorrtrktable::kSpK0short); } // Lambda and Anti-Lambda @@ -487,13 +487,13 @@ struct LongrangeMaker { // Note: candidate compatible with Lambda and Anti-Lambda hypothesis are counted twice (once for each hypothesis) if (lambdaTag) { // candidate is Lambda massV0 = v0.mLambda(); - v0LRUpcTable(outupccol.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); + upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpLambda); } if (antilambdaTag) { // candidate is Anti-lambda massV0 = v0.mAntiLambda(); - v0LRUpcTable(outupccol.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), - v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); + upclrv0tracks(upclrcollision.lastIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::lrcorrtrktable::kSpALambda); } // end of Lambda and Anti-Lambda processing } } // SG events diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index ed419b638d6..0a12a77b2fe 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -86,4 +86,25 @@ o2physics_add_dpl_workflow(two-particle-correlation-pp o2physics_add_dpl_workflow(flow-decorrelation SOURCES flowDecorrelation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2Physics::GFWCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(eta-dihadron + SOURCES etaDihadron.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2Physics::GFWCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(nuclei-balance + SOURCES nucleibalance.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdacascadecorrelation + SOURCES Lambdacascadecorrelation.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(particle-origin-analysis + SOURCES particleOriginAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) + diff --git a/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx new file mode 100644 index 00000000000..dfcb3182d43 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/Lambdacascadecorrelation.cxx @@ -0,0 +1,3704 @@ +// 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 Lambdacascadecorrelation.cxx +/// \brief Correlation-balance functions of multistrange baryons +/// \author Oveis Sheibani + +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "TDatabasePDG.h" +#include "TPDGCode.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::constants::math; +using namespace o2::soa; + +// use parameters + cov mat non-propagated, aux info + (extension propagated) +using FullTracksExt = soa::Join; +using FullTracksExtIU = soa::Join; +using FullTracksExtWithPID = soa::Join; +using FullTracksExtIUWithPID = soa::Join; + +namespace o2::aod +{ +namespace cascadeflags +{ +DECLARE_SOA_COLUMN(IsSelected, isSelected, int); //~! +} // namespace cascadeflags +DECLARE_SOA_TABLE(CascadeFlags, "AOD", "CASCADEFLAGS", //! + cascadeflags::IsSelected); +using CascDataExtSelected = soa::Join; +} // namespace o2::aod + +using MyCollisions = soa::Join; +using MyCollisionsMult = soa::Join; +using MyCascades = soa::Filtered; +using LabeledCascades = soa::Join; + +namespace o2::aod +{ +namespace lambdacollision +{ +DECLARE_SOA_COLUMN(Cent, cent, float); +DECLARE_SOA_COLUMN(Mult, mult, float); +DECLARE_SOA_COLUMN(RefCollId, refCollId, int64_t); // <--- 1. Add this line +} // namespace lambdacollision +DECLARE_SOA_TABLE(LambdaCollisions, "AOD", "LAMBDACOLS", o2::soa::Index<>, + lambdacollision::Cent, + lambdacollision::Mult, + lambdacollision::RefCollId, // <--- 2. Add this line + aod::collision::PosX, + aod::collision::PosY, + aod::collision::PosZ); +using LambdaCollision = LambdaCollisions::iterator; + +namespace lambdamcgencollision +{ +DECLARE_SOA_COLUMN(RefMcCollId, refMcCollId, int64_t); // original McCollision global index +} +DECLARE_SOA_TABLE(LambdaMcGenCollisions, "AOD", "LMCGENCOLS", o2::soa::Index<>, + lambdacollision::Cent, + lambdacollision::Mult, + lambdamcgencollision::RefMcCollId, + 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(Px, px, float); +DECLARE_SOA_COLUMN(Py, py, float); +DECLARE_SOA_COLUMN(Pz, pz, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Rap, rap, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(PosTrackId, posTrackId, int64_t); +DECLARE_SOA_COLUMN(NegTrackId, negTrackId, int64_t); +DECLARE_SOA_COLUMN(CosPA, cosPA, float); +DECLARE_SOA_COLUMN(DcaDau, dcaDau, float); +DECLARE_SOA_COLUMN(V0Type, v0Type, int8_t); +DECLARE_SOA_COLUMN(V0PrmScd, v0PrmScd, int8_t); +DECLARE_SOA_COLUMN(CorrFact, corrFact, float); +} // namespace lambdatrack +DECLARE_SOA_TABLE(LambdaTracks, "AOD", "LAMBDATRACKS", o2::soa::Index<>, + lambdatrack::LambdaCollisionId, + lambdatrack::Px, + lambdatrack::Py, + lambdatrack::Pz, + lambdatrack::Pt, + lambdatrack::Eta, + lambdatrack::Phi, + lambdatrack::Rap, + lambdatrack::Mass, + lambdatrack::PosTrackId, + lambdatrack::NegTrackId, + lambdatrack::CosPA, + lambdatrack::DcaDau, + lambdatrack::V0Type, + lambdatrack::V0PrmScd, + lambdatrack::CorrFact); +using LambdaTrack = LambdaTracks::iterator; + +namespace lambdatrackext +{ +DECLARE_SOA_COLUMN(LambdaSharingDaughter, lambdaSharingDaughter, bool); +DECLARE_SOA_COLUMN(LambdaSharingDauIds, lambdaSharingDauIds, std::vector); +DECLARE_SOA_COLUMN(TrueLambdaFlag, trueLambdaFlag, bool); +} // namespace lambdatrackext +DECLARE_SOA_TABLE(LambdaTracksExt, "AOD", "LAMBDATRACKSEXT", + lambdatrackext::LambdaSharingDaughter, + lambdatrackext::LambdaSharingDauIds, + lambdatrackext::TrueLambdaFlag); + +using LambdaTrackExt = LambdaTracksExt::iterator; + +namespace lambdamcgentrack +{ +DECLARE_SOA_INDEX_COLUMN(LambdaMcGenCollision, lambdaMcGenCollision); +} +DECLARE_SOA_TABLE(LambdaMcGenTracks, "AOD", "LMCGENTRACKS", o2::soa::Index<>, + lambdamcgentrack::LambdaMcGenCollisionId, + o2::aod::mcparticle::Px, + o2::aod::mcparticle::Py, + o2::aod::mcparticle::Pz, + lambdatrack::Pt, + lambdatrack::Eta, + lambdatrack::Phi, + lambdatrack::Rap, + lambdatrack::Mass, + lambdatrack::PosTrackId, + lambdatrack::NegTrackId, + lambdatrack::V0Type, + lambdatrack::CosPA, + lambdatrack::DcaDau, + lambdatrack::V0PrmScd, + lambdatrack::CorrFact); +using LambdaMcGenTrack = LambdaMcGenTracks::iterator; + +} // namespace o2::aod + +enum CollisionLabels { + kTotColBeforeHasMcCollision = 1, + kTotCol, + kPassSelCol +}; + +enum TrackLabels { + kTracksBeforeHasMcParticle = 1, + kAllV0Tracks, + kV0KShortMassRej, + kNotLambdaNotAntiLambda, + kV0IsBothLambdaAntiLambda, + kNotLambdaAfterSel, + kV0IsLambdaOrAntiLambda, + kPassV0DauTrackSel, + kPassV0KinCuts, + kPassV0TopoSel, + kAllSelPassed, + kPrimaryLambda, + kSecondaryLambda, + kLambdaDauNotMcParticle, + kLambdaNotPrPiMinus, + kAntiLambdaNotAntiPrPiPlus, + kPassTrueLambdaSel, + kEffCorrPtCent, + kEffCorrPtRapCent, + kNoEffCorr, + kPFCorrPtCent, + kPFCorrPtRapCent, + kNoPFCorr, + kGenTotAccLambda, + kGenLambdaNoDau, + kGenLambdaToPrPi +}; + +enum CentEstType { + kCentFT0M = 0, + kCentFV0A +}; + +enum RunType { + kRun3 = 0, + kRun2 +}; + +enum ParticleType { + kLambda = 0, + kAntiLambda +}; + +enum ParticlePairType { + kLambdaAntiLambda = 0, + kLambdaLambda, + kAntiLambdaAntiLambda +}; + +enum ShareDauLambda { + kUniqueLambda = 0, + kLambdaShareDau +}; + +enum RecGenType { + kRec = 0, + kGen +}; + +enum DMCType { + kData = 0, + kMC +}; + +enum CorrHistDim { + OneDimCorr = 1, + TwoDimCorr, + ThreeDimCorr +}; + +enum PrmScdType { + kPrimary = 0, + kSecondary +}; + +enum PrmScdPairType { + kPP = 0, + kPS, + kSP, + kSS +}; + +struct LambdaTableProducer { + + Produces lambdaCollisionTable; + Produces lambdaTrackTable; + Produces lambdaMCGenCollisionTable; + Produces lambdaMCGenTrackTable; + + // Collisions + Configurable cCentEstimator{"cCentEstimator", 0, "Centrality Estimator : 0-FT0M, 1-FV0A"}; + Configurable cMinZVtx{"cMinZVtx", -10.0, "Min VtxZ cut"}; + Configurable cMaxZVtx{"cMaxZVtx", 10.0, "Max VtxZ cut"}; + Configurable cMinMult{"cMinMult", 0., "Minumum Multiplicity"}; + Configurable cMaxMult{"cMaxMult", 100.0, "Maximum Multiplicity"}; + Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; + Configurable cInt7Trig{"cInt7Trig", false, "kINT7 MB Trigger"}; + Configurable cSel7Trig{"cSel7Trig", false, "Sel7 (V0A + V0C) Selection Run2"}; + Configurable cTriggerTvxSel{"cTriggerTvxSel", false, "Trigger Time and Vertex Selection"}; + Configurable cTFBorder{"cTFBorder", false, "Timeframe Border Selection"}; + Configurable cNoItsROBorder{"cNoItsROBorder", false, "No ITSRO Border Cut"}; + Configurable cItsTpcVtx{"cItsTpcVtx", false, "ITS+TPC Vertex Selection"}; + Configurable cPileupReject{"cPileupReject", false, "Pileup rejection"}; + Configurable cZVtxTimeDiff{"cZVtxTimeDiff", false, "z-vtx time diff selection"}; + Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; + + // Tracks + Configurable cTrackMinPt{"cTrackMinPt", 0.15, "p_{T} minimum"}; + Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} maximum"}; + Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; + Configurable cMinTpcCrossedRows{"cMinTpcCrossedRows", 70, "TPC Min Crossed Rows"}; + Configurable cMinTpcCROverCls{"cMinTpcCROverCls", 0.8, "Tpc Min Crossed Rows Over Findable Clusters"}; + Configurable cMaxTpcSharedClusters{"cMaxTpcSharedClusters", 0.4, "Tpc Max Shared Clusters"}; + Configurable cMaxChi2Tpc{"cMaxChi2Tpc", 4, "Max Chi2 Tpc"}; + Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 3.0, "TPC NSigma Selection Cut"}; + Configurable cRemoveAmbiguousTracks{"cRemoveAmbiguousTracks", false, "Remove Ambiguous Tracks"}; + + // V0s + Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.02, "Minimum Proton DCAr to PV"}; + Configurable cMinDcaPionToPV{"cMinDcaPionToPV", 0.06, "Minimum Pion DCAr to PV"}; + Configurable cMinV0DcaDaughters{"cMinV0DcaDaughters", 0., "Minimum DCA between V0 daughters"}; + Configurable cMaxV0DcaDaughters{"cMaxV0DcaDaughters", 1., "Maximum DCA between V0 daughters"}; + Configurable cMinDcaV0ToPV{"cMinDcaV0ToPV", 0.0, "Minimum DCA V0 to PV"}; + Configurable cMaxDcaV0ToPV{"cMaxDcaV0ToPV", 999.0, "Maximum DCA V0 to PV"}; + Configurable cMinV0TransRadius{"cMinV0TransRadius", 0.5, "Minimum V0 radius from PV"}; + Configurable cMaxV0TransRadius{"cMaxV0TransRadius", 999.0, "Maximum V0 radius from PV"}; + Configurable cMinV0CTau{"cMinV0CTau", 0.0, "Minimum ctau"}; + Configurable cMaxV0CTau{"cMaxV0CTau", 30.0, "Maximum ctau"}; + Configurable cMinV0CosPA{"cMinV0CosPA", 0.995, "Minimum V0 CosPA to PV"}; + Configurable cKshortRejMassWindow{"cKshortRejMassWindow", 0.01, "Reject K0Short Candidates"}; + Configurable cKshortRejFlag{"cKshortRejFlag", true, "K0short Mass Rej Flag"}; + + // V0s kinmatic acceptance + Configurable cMinV0Mass{"cMinV0Mass", 1.10, "V0 Mass Min"}; + Configurable cMaxV0Mass{"cMaxV0Mass", 1.12, "V0 Mass Min"}; + Configurable cMinV0Pt{"cMinV0Pt", 0.8, "Minimum V0 pT"}; + Configurable cMaxV0Pt{"cMaxV0Pt", 4.2, "Minimum V0 pT"}; + Configurable cMaxV0Rap{"cMaxV0Rap", 0.5, "|rap| cut"}; + Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Do Eta Analysis"}; + Configurable cV0TypeSelFlag{"cV0TypeSelFlag", false, "V0 Type Selection Flag"}; + Configurable cV0TypeSelection{"cV0TypeSelection", 1, "V0 Type Selection"}; + + // V0s MC + Configurable cHasMcFlag{"cHasMcFlag", true, "Has Mc Tag"}; + Configurable cSelectTrueLambda{"cSelectTrueLambda", true, "Select True Lambda"}; + Configurable cSelMCPSV0{"cSelMCPSV0", true, "Select Primary/Secondary V0"}; + Configurable cCheckRecoDauFlag{"cCheckRecoDauFlag", true, "Check for reco daughter PID"}; + Configurable cGenPrimaryLambda{"cGenPrimaryLambda", true, "Primary Generated Lambda"}; + Configurable cGenSecondaryLambda{"cGenSecondaryLambda", false, "Secondary Generated Lambda"}; + Configurable cGenDecayChannel{"cGenDecayChannel", true, "Gen Level Decay Channel Flag"}; + Configurable cRecoMomResoFlag{"cRecoMomResoFlag", false, "Check effect of momentum space smearing on balance function"}; + + // Efficiency Correction + Configurable cCorrectionFlag{"cCorrectionFlag", false, "Correction Flag"}; + Configurable cGetEffFact{"cGetEffFact", false, "Get Efficiency Factor Flag"}; + Configurable cGetPrimFrac{"cGetPrimFrac", false, "Get Primary Fraction Flag"}; + Configurable cCorrFactHist{"cCorrFactHist", 0, "Efficiency Factor Histogram"}; + Configurable cPrimFracHist{"cPrimFracHist", 0, "Primary Fraction Histogram"}; + + // CCDB + Configurable cUrlCCDB{"cUrlCCDB", "http://ccdb-test.cern.ch:8080", "url of ccdb"}; + Configurable cPathCCDB{"cPathCCDB", "Users/y/ypatley/lambda_corr_fact", "Path for ccdb-object"}; + + // Initialize CCDB Service + Service ccdb; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // initialize corr_factor objects + std::vector> vCorrFactStrings = {{"hEffVsPtCentLambda", "hEffVsPtCentAntiLambda"}, + {"hEffVsPtYCentLambda", "hEffVsPtYCentAntiLambda"}, + {"hEffVsPtEtaCentLambda", "hEffVsPtEtaCentAntiLambda"}}; + + // initialize corr_factor objects + std::vector> vPrimFracStrings = {{"hPrimFracVsPtCentLambda", "hPrimFracVsPtCentAntiLambda"}, + {"hPrimFracVsPtYCentLambda", "hPrimFracVsPtYCentAntiLambda"}, + {"hPrimFracVsPtEtaCentLambda", "hPrimFracVsPtEtaCentAntiLambda"}}; + + // Initialize Global Variables + float cent = 0., mult = 0.; + float pt = 0., eta = 0., rap = 0., phi = 0.; + + void init(InitContext const&) + { + // Set CCDB url + ccdb->setURL(cUrlCCDB.value); + ccdb->setCaching(true); + + // initialize axis specifications + const AxisSpec axisCols(5, 0.5, 5.5, ""); + const AxisSpec axisTrks(30, 0.5, 30.5, ""); + const AxisSpec axisCent(100, 0, 100, "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(140, 1.08, 1.15, "M_{p#pi} (GeV/#it{c}^{2})"); + const AxisSpec axisV0Pt(100., 0., 10., "p_{T} (GeV/#it{c})"); + const AxisSpec axisV0Rap(48, -1.2, 1.2, "y"); + const AxisSpec axisV0Eta(48, -1.2, 1.2, "#eta"); + const AxisSpec axisV0Phi(36, 0., TwoPI, "#phi (rad)"); + + const AxisSpec axisRadius(2000, 0, 200, "r(cm)"); + const AxisSpec axisCosPA(300, 0.97, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisDcaV0PV(1000, 0., 10., "dca (cm)"); + const AxisSpec axisDcaProngPV(5000, -50., 50., "dca (cm)"); + const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); + const AxisSpec axisCTau(2000, 0, 200, "c#tau (cm)"); + const AxisSpec axisGCTau(2000, 0, 200, "#gammac#tau (cm)"); + const AxisSpec axisAlpha(40, -1, 1, "#alpha"); + const AxisSpec axisQtarm(40, 0, 0.4, "q_{T}"); + + const AxisSpec axisTrackPt(40, 0, 4, "p_{T} (GeV/#it{c})"); + const AxisSpec axisTrackDCA(200, -1, 1, "dca_{XY} (cm)"); + 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("Events/h1f_collisions_info", "# of Collisions", kTH1F, {axisCols}); + histos.add("Events/h1f_collision_posZ", "V_{z}-distribution", kTH1F, {axisVz}); + + // QA + histos.add("Tracks/h1f_tracks_info", "# of tracks", kTH1F, {axisTrks}); + histos.add("Tracks/h2f_armpod_before_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("Tracks/h2f_armpod_after_sel", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("Tracks/h1f_lambda_pt_vs_invm", "p_{T} vs M_{#Lambda}", kTH2F, {axisV0Mass, axisV0Pt}); + histos.add("Tracks/h1f_antilambda_pt_vs_invm", "p_{T} vs M_{#bar{#Lambda}}", kTH2F, {axisV0Mass, axisV0Pt}); + + // QA Lambda + histos.add("QA/Lambda/h2f_qt_vs_alpha", "Armentros-Podolanski Plot", kTH2F, {axisAlpha, axisQtarm}); + histos.add("QA/Lambda/h1f_dca_V0_daughters", "DCA between V0 daughters", kTH1F, {axisDcaDau}); + histos.add("QA/Lambda/h1f_dca_pos_to_PV", "DCA positive prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("QA/Lambda/h1f_dca_neg_to_PV", "DCA negative prong to PV", kTH1F, {axisDcaProngPV}); + histos.add("QA/Lambda/h1f_dca_V0_to_PV", "DCA V0 to PV", kTH1F, {axisDcaV0PV}); + histos.add("QA/Lambda/h1f_V0_cospa", "cos(#theta_{PA})", kTH1F, {axisCosPA}); + histos.add("QA/Lambda/h1f_V0_radius", "V_{0} Decay Radius in XY plane", kTH1F, {axisRadius}); + histos.add("QA/Lambda/h1f_V0_ctau", "V_{0} c#tau", kTH1F, {axisCTau}); + histos.add("QA/Lambda/h1f_V0_gctau", "V_{0} #gammac#tau", kTH1F, {axisGCTau}); + + histos.add("QA/Lambda/h1f_pos_prong_pt", "Pos-Prong p_{T}", kTH1F, {axisTrackPt}); + histos.add("QA/Lambda/h1f_neg_prong_pt", "Neg-Prong p_{T}", kTH1F, {axisTrackPt}); + histos.add("QA/Lambda/h1f_pos_prong_eta", "Pos-Prong #eta-distribution", kTH1F, {axisV0Eta}); + histos.add("QA/Lambda/h1f_neg_prong_eta", "Neg-Prong #eta-distribution", kTH1F, {axisV0Eta}); + histos.add("QA/Lambda/h1f_pos_prong_phi", "Pos-Prong #phi-distribution", kTH1F, {axisV0Phi}); + histos.add("QA/Lambda/h1f_neg_prong_phi", "Neg-Prong #phi-distribution", kTH1F, {axisV0Phi}); + + histos.add("QA/Lambda/h2f_pos_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); + histos.add("QA/Lambda/h2f_neg_prong_dcaXY_vs_pt", "DCA vs p_{T}", kTH2F, {axisTrackPt, axisTrackDCA}); + histos.add("QA/Lambda/h2f_pos_prong_dEdx_vs_p", "TPC Signal Pos-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("QA/Lambda/h2f_neg_prong_dEdx_vs_p", "TPC Signal Neg-Prong", kTH2F, {axisMomPID, axisdEdx}); + histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pr_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA/Lambda/h2f_pos_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Pos Prong", kTH2F, {axisMomPID, axisNsigma}); + histos.add("QA/Lambda/h2f_neg_prong_tpc_nsigma_pi_vs_p", "TPC n#sigma Neg Prong", kTH2F, {axisMomPID, axisNsigma}); + + // Kinematic Histograms + histos.add("McRec/Lambda/hPt", "Transverse Momentum", kTH1F, {axisV0Pt}); + histos.add("McRec/Lambda/hEta", "Pseudorapidity", kTH1F, {axisV0Eta}); + histos.add("McRec/Lambda/hRap", "Rapidity", kTH1F, {axisV0Rap}); + histos.add("McRec/Lambda/hPhi", "Azimuthal Angle", kTH1F, {axisV0Phi}); + + // QA Anti-Lambda + histos.addClone("QA/Lambda/", "QA/AntiLambda/"); + histos.addClone("McRec/Lambda/", "McRec/AntiLambda/"); + + // MC Generated Histograms + if (doprocessMCRun3 || doprocessMCRun2 || doprocessMCRecoRun3 || doprocessMCRecoRun2) { + // McReco Histos + histos.add("Tracks/h2f_tracks_pid_before_sel", "PIDs", kTH2F, {axisPID, axisV0Pt}); + histos.add("Tracks/h2f_tracks_pid_after_sel", "PIDs", kTH2F, {axisPID, axisV0Pt}); + histos.add("Tracks/h2f_lambda_mothers_pdg", "PIDs", kTH2F, {axisPID, axisV0Pt}); + + // McGen Histos + histos.add("McGen/h1f_collision_recgen", "# of Reco Collision Associated to One Mc Generator Collision", kTH1F, {axisMult}); + histos.add("McGen/h1f_collisions_info", "# of collisions", kTH1F, {axisCols}); + histos.add("McGen/h2f_collision_posZ", "V_{z}-distribution", kTH2F, {axisVz, axisVz}); + histos.add("McGen/h2f_collision_cent", "FT0M Centrality", kTH2F, {axisCent, axisCent}); + histos.add("McGen/h1f_lambda_daughter_PDG", "PDG Daughters", kTH1F, {axisPID}); + histos.add("McGen/h1f_antilambda_daughter_PDG", "PDG Daughters", kTH1F, {axisPID}); + + histos.addClone("McRec/", "McGen/"); + + histos.add("McGen/Lambda/Proton/hPt", "Proton p_{T}", kTH1F, {axisTrackPt}); + histos.add("McGen/Lambda/Proton/hEta", "Proton #eta", kTH1F, {axisV0Eta}); + histos.add("McGen/Lambda/Proton/hRap", "Proton y", kTH1F, {axisV0Rap}); + histos.add("McGen/Lambda/Proton/hPhi", "Proton #phi", kTH1F, {axisV0Phi}); + + histos.addClone("McGen/Lambda/Proton/", "McGen/Lambda/Pion/"); + histos.addClone("McGen/Lambda/Proton/", "McGen/AntiLambda/Proton/"); + histos.addClone("McGen/Lambda/Pion/", "McGen/AntiLambda/Pion/"); + + // set bin lables specific to MC + histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotColBeforeHasMcCollision, "kTotColBeforeHasMcCollision"); + histos.get(HIST("McGen/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + histos.get(HIST("McGen/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kTracksBeforeHasMcParticle, "kTracksBeforeHasMcParticle"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPrimaryLambda, "kPrimaryLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kSecondaryLambda, "kSecondaryLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kLambdaDauNotMcParticle, "kLambdaDauNotMcParticle"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kLambdaNotPrPiMinus, "kLambdaNotPrPiMinus"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAntiLambdaNotAntiPrPiPlus, "kAntiLambdaNotAntiPrPiPlus"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassTrueLambdaSel, "kPassTrueLambdaSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kGenTotAccLambda, "kGenTotAccLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kGenLambdaNoDau, "kGenLambdaNoDau"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kGenLambdaToPrPi, "kGenLambdaToPrPi"); + } + + // set bin labels + histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + histos.get(HIST("Events/h1f_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllV0Tracks, "kAllV0Tracks"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0KShortMassRej, "kV0KShortMassRej"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaNotAntiLambda, "kNotLambdaNotAntiLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsBothLambdaAntiLambda, "kV0IsBothLambdaAntiLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotLambdaAfterSel, "kNotLambdaAfterSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kV0IsLambdaOrAntiLambda, "kV0IsLambdaOrAntiLambda"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0DauTrackSel, "kPassV0DauTrackSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0KinCuts, "kPassV0KinCuts"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPassV0TopoSel, "kPassV0TopoSel"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllSelPassed, "kAllSelPassed"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kEffCorrPtCent, "kEffCorrPtCent"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kEffCorrPtRapCent, "kEffCorrPtRapCent"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNoEffCorr, "kNoEffCorr"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPFCorrPtCent, "kPFCorrPtCent"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kPFCorrPtRapCent, "kPFCorrPtRapCent"); + histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNoPFCorr, "kNoPFCorr"); + } + + template + bool selCollision(C const& col) + { + // VtxZ Selection + if (col.posZ() <= cMinZVtx || col.posZ() >= cMaxZVtx) { + return false; + } + + if constexpr (run == kRun3) { // Run3 Min-Bias Trigger + // select centrality estimator + if (cCentEstimator == kCentFT0M) { + cent = col.centFT0M(); + } else if (cCentEstimator == kCentFV0A) { + cent = col.centFV0A(); + } + if (cSel8Trig && !col.sel8()) { + return false; + } + } else { // Run2 Min-Bias Trigger + cent = col.centRun2V0M(); + if (cInt7Trig && !col.alias_bit(kINT7)) { + return false; + } + if (cSel7Trig && !col.sel7()) { + return false; + } + } + + if (cent <= cMinMult || cent >= cMaxMult) { // select centrality percentile class + return false; + } + + if (cTriggerTvxSel && !col.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (cTFBorder && !col.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (cNoItsROBorder && !col.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (cItsTpcVtx && !col.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (cPileupReject && !col.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (cZVtxTimeDiff && !col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (cIsGoodITSLayers && !col.selection_bit(aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + + // Set Multiplicity + mult = col.multNTracksPV(); + + return true; + } + + // Kinematic Selection + bool kinCutSelection(float const& pt, float const& rap, float const& ptMin, float const& ptMax, float const& rapMax) + { + if (pt <= ptMin || pt >= ptMax || rap >= rapMax) { + return false; + } + + return true; + } + + // Track Selection + template + bool selTrack(T const& track) + { + if (!kinCutSelection(track.pt(), std::abs(track.eta()), cTrackMinPt, cTrackMaxPt, cTrackEtaCut)) { + return false; + } + + if (track.tpcNClsCrossedRows() <= cMinTpcCrossedRows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < cMinTpcCROverCls) { + return false; + } + + if (track.tpcNClsShared() > cMaxTpcSharedClusters) { + return false; + } + + if (track.tpcChi2NCl() > cMaxChi2Tpc) { + return false; + } + + return true; + } + + // Daughter Track Selection + template + bool selDaughterTracks(V const& v0, T const&, ParticleType const& v0Type) + { + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); + + if (!selTrack(posTrack) || !selTrack(negTrack)) { + return false; + } + + // Apply DCA Selection on Daughter Tracks Based on Lambda/AntiLambda daughters + float dcaProton = 0., dcaPion = 0.; + if (v0Type == kLambda) { + dcaProton = std::abs(v0.dcapostopv()); + dcaPion = std::abs(v0.dcanegtopv()); + } else if (v0Type == kAntiLambda) { + dcaPion = std::abs(v0.dcapostopv()); + dcaProton = std::abs(v0.dcanegtopv()); + } + + if (dcaProton < cMinDcaProtonToPV || dcaPion < cMinDcaPionToPV) { + return false; + } + + return true; + } + + template + bool topoCutSelection(C const& col, V const& v0, T const&) + { + // DCA + if (v0.dcaV0daughters() <= cMinV0DcaDaughters || v0.dcaV0daughters() >= cMaxV0DcaDaughters) { + return false; + } + + if (v0.dcav0topv() <= cMinDcaV0ToPV || v0.dcav0topv() >= cMaxDcaV0ToPV) { + return false; + } + + if (v0.v0radius() <= cMinV0TransRadius || v0.v0radius() >= cMaxV0TransRadius) { + return false; + } + + // ctau + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + if (ctau <= cMinV0CTau || ctau >= cMaxV0CTau) { + return false; + } + + // cosine of pointing angle + if (v0.v0cosPA() <= cMinV0CosPA) { + return false; + } + + // all selection criterion passed (Return True) + return true; + } + + template + bool selLambdaDauWithTpcPid(T const& postrack, T const& negtrack) + { + bool returnFlag = false; + float tpcNSigmaPr = 0., tpcNSigmaPi = 0.; + + switch (part) { + // postrack = Proton, negtrack = Pion + case kLambda: + tpcNSigmaPr = postrack.tpcNSigmaPr(); + tpcNSigmaPi = negtrack.tpcNSigmaPi(); + break; + + // negtrack = Proton, postrack = Pion + case kAntiLambda: + tpcNSigmaPr = negtrack.tpcNSigmaPr(); + tpcNSigmaPi = postrack.tpcNSigmaPi(); + break; + } + + if (std::abs(tpcNSigmaPr) < cTpcNsigmaCut && std::abs(tpcNSigmaPi) < cTpcNsigmaCut) { + returnFlag = true; + } + + return returnFlag; + } + + template + bool selLambdaMassWindow(V const& v0, T const&, ParticleType& v0type) + { + // Kshort mass rejection hypothesis + if (cKshortRejFlag && (std::abs(v0.mK0Short() - MassK0Short) <= cKshortRejMassWindow)) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kV0KShortMassRej); + return false; + } + + // initialize daughter tracks + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + // initialize selection flags + bool lambdaFlag = false, antiLambdaFlag = false; + + // get v0 track as lambda + if ((v0.mLambda() > cMinV0Mass && v0.mLambda() < cMaxV0Mass) && (selLambdaDauWithTpcPid(postrack, negtrack))) { + lambdaFlag = true; + v0type = kLambda; + } + + // get v0 track as anti-lambda + if ((v0.mAntiLambda() > cMinV0Mass && v0.mAntiLambda() < cMaxV0Mass) && (selLambdaDauWithTpcPid(postrack, negtrack))) { + antiLambdaFlag = true; + v0type = kAntiLambda; + } + + if (!lambdaFlag && !antiLambdaFlag) { // neither Lambda nor Anti-Lambda + histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaNotAntiLambda); + return false; + } else if (lambdaFlag && antiLambdaFlag) { // check if the track is identified as lambda and anti-lambda both (DISCARD THIS TRACK) + histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsBothLambdaAntiLambda); + return false; + } + + if (lambdaFlag || antiLambdaFlag) { + return true; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kNotLambdaAfterSel); + + return false; + } + + template + bool selV0Particle(C const& col, V const& v0, T const& tracks, ParticleType& v0Type) + { + // Apply Lambda Mass Hypothesis + if (!selLambdaMassWindow(v0, tracks, v0Type)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kV0IsLambdaOrAntiLambda); + + // Apply Daughter Track Selection + if (!selDaughterTracks(v0, tracks, v0Type)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0DauTrackSel); + + // Apply Kinematic Selection + float rap = 0.; + if (!cDoEtaAnalysis) { + rap = std::abs(v0.yLambda()); + } else { + rap = std::abs(v0.eta()); + } + + if (!kinCutSelection(v0.pt(), rap, cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0KinCuts); + + // Apply Topological Selection + if (!topoCutSelection(col, v0, tracks)) { + return false; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassV0TopoSel); + + // All Selection Criterion Passed + return true; + } + + template + bool hasAmbiguousDaughters(V const& v0, T const&) + { + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); + + auto posTrackCompCols = posTrack.compatibleCollIds(); + auto negTrackCompCols = negTrack.compatibleCollIds(); + + // Check if daughter tracks belongs to more than one collision (Ambiguous Tracks) + if (posTrackCompCols.size() > 1 || negTrackCompCols.size() > 1) { + return true; + } + + // Check if compatible collision index matches the track collision index + if (((posTrackCompCols.size() != 0) && (posTrackCompCols[0] != posTrack.collisionId())) || + ((negTrackCompCols.size() != 0) && (negTrackCompCols[0] != negTrack.collisionId()))) { + return true; + } + + // Pass as not ambiguous + return false; + } + + template + PrmScdType isPrimaryV0(V const& v0) + { + auto mcpart = v0.template mcParticle_as(); + + // check for secondary lambda + if (!mcpart.isPhysicalPrimary()) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kSecondaryLambda); + return kSecondary; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPrimaryLambda); + return kPrimary; + } + + template + bool selTrueMcRecLambda(V const& v0, T const&) + { + auto mcpart = v0.template mcParticle_as(); + + // check if Lambda/AntiLambda + if (std::abs(mcpart.pdgCode()) != kLambda0) { + return false; + } + + // Check for daughters + if (cCheckRecoDauFlag) { + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + // check if the daughters have corresponding mcparticle + if (!postrack.has_mcParticle() || !negtrack.has_mcParticle()) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kLambdaDauNotMcParticle); + return false; + } + + auto mcpostrack = postrack.template mcParticle_as(); + auto mcnegtrack = negtrack.template mcParticle_as(); + + if (mcpart.pdgCode() == kLambda0) { + if (mcpostrack.pdgCode() != kProton || mcnegtrack.pdgCode() != kPiMinus) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kLambdaNotPrPiMinus); + return false; + } + } else if (mcpart.pdgCode() == kLambda0Bar) { + if (mcpostrack.pdgCode() != kPiPlus || mcnegtrack.pdgCode() != kProtonBar) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kAntiLambdaNotAntiPrPiPlus); + return false; + } + } + } + + return true; + } + + template + float getCorrectionFactors(V const& v0) + { + // Check for efficiency correction flag + if (!cCorrectionFlag) { + return 1.; + } + + // Get from CCDB + auto ccdbObj = ccdb->getForTimeStamp(cPathCCDB.value, -1); + + // Check CCDB Object + if (!ccdbObj) { + LOGF(warning, "CCDB OBJECT NOT FOUND"); + return 1.; + } + + // initialize efficiency factor and primary fraction values + float effCorrFact = 1., primFrac = 1.; + float rap = (cDoEtaAnalysis) ? v0.eta() : v0.yLambda(); + + // Get Efficiency Factor + if (cGetEffFact) { + TObject* objEff = reinterpret_cast(ccdbObj->FindObject(Form("%s", vCorrFactStrings[cCorrFactHist][part].c_str()))); + TH1F* histEff = reinterpret_cast(objEff->Clone()); + if (histEff->GetDimension() == TwoDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtCent); + effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt())); + } else if (histEff->GetDimension() == ThreeDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kEffCorrPtRapCent); + effCorrFact = histEff->GetBinContent(histEff->FindBin(cent, v0.pt(), rap)); + } else { + histos.fill(HIST("Tracks/h1f_tracks_info"), kNoEffCorr); + LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); + effCorrFact = 1.; + } + delete histEff; + } + + // Get Primary Fraction + // (The dimension of this could be different than efficiency because of large errors !!!) + if (cGetPrimFrac) { + TObject* objPrm = reinterpret_cast(ccdbObj->FindObject(Form("%s", vPrimFracStrings[cPrimFracHist][part].c_str()))); + TH1F* histPrm = reinterpret_cast(objPrm->Clone()); + if (histPrm->GetDimension() == TwoDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kPFCorrPtCent); + primFrac = histPrm->GetBinContent(histPrm->FindBin(cent, v0.pt())); + } else if (histPrm->GetDimension() == ThreeDimCorr) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kPFCorrPtRapCent); + primFrac = histPrm->GetBinContent(histPrm->FindBin(cent, v0.pt(), rap)); + } else { + histos.fill(HIST("Tracks/h1f_tracks_info"), kNoPFCorr); + LOGF(warning, "CCDB OBJECT IS NOT A HISTOGRAM !!!"); + primFrac = 1.; + } + delete histPrm; + } + + return primFrac * effCorrFact; + } + + template + void fillLambdaMothers(V const& v0, T const&) + { + auto mcpart = v0.template mcParticle_as(); + auto lambdaMothers = mcpart.template mothers_as(); + histos.fill(HIST("Tracks/h2f_lambda_mothers_pdg"), lambdaMothers[0].pdgCode(), v0.pt()); + } + + template + void fillLambdaQAHistos(C const& col, V const& v0, T const&) + { + static constexpr std::string_view SubDir[] = {"QA/Lambda/", "QA/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 + float e = RecoDecay::e(v0.px(), v0.py(), v0.pz(), mass); + float gamma = e / mass; + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + float gctau = ctau * gamma; + + histos.fill(HIST(SubDir[part]) + HIST("h2f_qt_vs_alpha"), v0.alpha(), v0.qtarm()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_daughters"), v0.dcaV0daughters()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_pos_to_PV"), v0.dcapostopv()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_neg_to_PV"), v0.dcanegtopv()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_dca_V0_to_PV"), v0.dcav0topv()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_cospa"), v0.v0cosPA()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_radius"), v0.v0radius()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_ctau"), ctau); + histos.fill(HIST(SubDir[part]) + HIST("h1f_V0_gctau"), gctau); + + histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_pt"), postrack.pt()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_eta"), postrack.eta()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_pos_prong_phi"), postrack.phi()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_pt"), negtrack.pt()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_eta"), negtrack.eta()); + histos.fill(HIST(SubDir[part]) + HIST("h1f_neg_prong_phi"), negtrack.phi()); + + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dcaXY_vs_pt"), postrack.pt(), postrack.dcaXY()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dcaXY_vs_pt"), negtrack.pt(), negtrack.dcaXY()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_dEdx_vs_p"), postrack.tpcInnerParam(), postrack.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_dEdx_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcSignal()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_tpc_nsigma_pr_vs_p"), postrack.tpcInnerParam(), postrack.tpcNSigmaPr()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pr_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPr()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_pos_prong_tpc_nsigma_pi_vs_p"), postrack.tpcInnerParam(), postrack.tpcNSigmaPi()); + histos.fill(HIST(SubDir[part]) + HIST("h2f_neg_prong_tpc_nsigma_pi_vs_p"), negtrack.tpcInnerParam(), negtrack.tpcNSigmaPi()); + } + + // Fill Lambda Kinematic Histograms + template + void fillKinematicHists(float const& pt, float const& eta, float const& y, float const& phi) + { + static constexpr std::string_view SubDirRG[] = {"McRec/", "McGen/"}; + static constexpr std::string_view SubDirPart[] = {"Lambda/", "AntiLambda/"}; + + histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hPt"), pt); + histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hEta"), eta); + histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hRap"), y); + histos.fill(HIST(SubDirRG[rg]) + HIST(SubDirPart[part]) + HIST("hPhi"), phi); + } + + // Reconstructed Level Tables + template + void fillLambdaRecoTables(C const& collision, V const& v0tracks, T const& tracks) + { + // Total Collisions + histos.fill(HIST("Events/h1f_collisions_info"), kTotCol); + + // Select Collision (Only for Data... McRec has been selected already !!!) + if constexpr (dmc == kData) { + if (!selCollision(collision)) { + return; + } + } + + histos.fill(HIST("Events/h1f_collisions_info"), kPassSelCol); + histos.fill(HIST("Events/h1f_collision_posZ"), collision.posZ()); + + // Fill Collision Table + // lambdaCollisionTable(cent, mult, collision.posX(), collision.posY(), collision.posZ()); + lambdaCollisionTable(cent, mult, collision.globalIndex(), collision.posX(), collision.posY(), collision.posZ()); + + // initialize v0track objects + ParticleType v0Type = kLambda; + PrmScdType v0PrmScdType = kPrimary; + float mass = 0., corr_fact = 1.; + + for (auto const& v0 : v0tracks) { + // check for corresponding MCGen Particle + if constexpr (dmc == kMC) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kTracksBeforeHasMcParticle); + if (!v0.has_mcParticle()) { + continue; + } + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kAllV0Tracks); + histos.fill(HIST("Tracks/h2f_armpod_before_sel"), v0.alpha(), v0.qtarm()); + + // Select V0 Particle as Lambda/AntiLambda + if (!selV0Particle(collision, v0, tracks, v0Type)) { + continue; + } + + // Select V0 Type Selection + if (cV0TypeSelFlag && v0.v0Type() != cV0TypeSelection) { + continue; + } + + // we have v0 as lambda + histos.fill(HIST("Tracks/h1f_tracks_info"), kAllSelPassed); + + // Remove lambda with ambiguous daughters (Only for run3) + if constexpr (run == kRun3) { + if (cRemoveAmbiguousTracks && hasAmbiguousDaughters(v0, tracks)) { + continue; + } + } + + // Get Lambda mass and kinematic variables + mass = (v0Type == kLambda) ? v0.mLambda() : v0.mAntiLambda(); + pt = v0.pt(); + eta = v0.eta(); + rap = v0.yLambda(); + phi = v0.phi(); + + // do MC analysis + if constexpr (dmc == kMC) { + histos.fill(HIST("Tracks/h2f_tracks_pid_before_sel"), v0.mcParticle().pdgCode(), v0.pt()); + + // Get Primary/Secondary Lambda + if (cSelMCPSV0) { + v0PrmScdType = isPrimaryV0(v0); + } + + // check for true Lambda/Anti-Lambda + if (cSelectTrueLambda && !selTrueMcRecLambda(v0, tracks)) { + continue; + } + + // get mothers information + if (v0PrmScdType == kSecondary) { + fillLambdaMothers(v0, tracks); + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kPassTrueLambdaSel); + histos.fill(HIST("Tracks/h2f_tracks_pid_after_sel"), v0.mcParticle().pdgCode(), v0.pt()); + + if (cRecoMomResoFlag) { + auto mc = v0.template mcParticle_as(); + pt = mc.pt(); + eta = mc.eta(); + rap = mc.y(); + phi = mc.phi(); + float y = (cDoEtaAnalysis) ? eta : rap; + // apply kinematic selection (On Truth) + if (!kinCutSelection(pt, std::abs(y), cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { + continue; + } + } + } + + histos.fill(HIST("Tracks/h2f_armpod_after_sel"), v0.alpha(), v0.qtarm()); + + // get correction factors + corr_fact = (v0Type == kLambda) ? getCorrectionFactors(v0) : getCorrectionFactors(v0); + + // fill lambda qa + if (v0Type == kLambda) { + histos.fill(HIST("Tracks/h1f_lambda_pt_vs_invm"), mass, v0.pt()); + fillLambdaQAHistos(collision, v0, tracks); + fillKinematicHists(v0.pt(), v0.eta(), v0.yLambda(), v0.phi()); + } else { + histos.fill(HIST("Tracks/h1f_antilambda_pt_vs_invm"), mass, v0.pt()); + fillLambdaQAHistos(collision, v0, tracks); + fillKinematicHists(v0.pt(), v0.eta(), v0.yLambda(), v0.phi()); + } + + // Fill Lambda/AntiLambda Table + lambdaTrackTable(lambdaCollisionTable.lastIndex(), v0.px(), v0.py(), v0.pz(), + pt, eta, phi, rap, mass, v0.template posTrack_as().index(), v0.template negTrack_as().index(), + v0.v0cosPA(), v0.dcaV0daughters(), (int8_t)v0Type, v0PrmScdType, corr_fact); + } + } + + // MC Generater Level Tables + template + void fillLambdaMcGenTables(C const& mcCollision, M const& mcParticles) + { + // Fill McGen Collision Table + lambdaMCGenCollisionTable(cent, mult, mcCollision.globalIndex(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + + // initialize track objects + ParticleType v0Type = kLambda; + PrmScdType v0PrmScdType = kPrimary; + float rap = 0.; + + for (auto const& mcpart : mcParticles) { + // check for Lambda first + if (mcpart.pdgCode() == kLambda0) { + v0Type = kLambda; + } else if (mcpart.pdgCode() == kLambda0Bar) { + v0Type = kAntiLambda; + } else { + continue; + } + + // check for Primary Lambda/AntiLambda + if (mcpart.isPhysicalPrimary()) { + v0PrmScdType = kPrimary; + } else { + v0PrmScdType = kSecondary; + } + + // Decide Eta/Rap + if (!cDoEtaAnalysis) { + rap = mcpart.y(); + } else { + rap = mcpart.eta(); + } + + // Apply Kinematic Acceptance + if (!kinCutSelection(mcpart.pt(), std::abs(rap), cMinV0Pt, cMaxV0Pt, cMaxV0Rap)) { + continue; + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kGenTotAccLambda); + + // get daughter track info and check for decay channel flag + if (!mcpart.has_daughters()) { + histos.fill(HIST("Tracks/h1f_tracks_info"), kGenLambdaNoDau); + continue; + } + auto dautracks = mcpart.template daughters_as(); + std::vector daughterPDGs, daughterIDs; + std::vector vDauPt, vDauEta, vDauRap, vDauPhi; + for (auto const& dautrack : dautracks) { + daughterPDGs.push_back(dautrack.pdgCode()); + daughterIDs.push_back(dautrack.globalIndex()); + vDauPt.push_back(dautrack.pt()); + vDauEta.push_back(dautrack.eta()); + vDauRap.push_back(dautrack.y()); + vDauPhi.push_back(dautrack.phi()); + } + if (cGenDecayChannel) { // check decay channel + if (v0Type == kLambda) { + if (daughterPDGs[0] != kProton || daughterPDGs[1] != kPiMinus) { + continue; + } + } else if (v0Type == kAntiLambda) { + if (daughterPDGs[0] != kProtonBar || daughterPDGs[1] != kPiPlus) { + continue; + } + } + } + + histos.fill(HIST("Tracks/h1f_tracks_info"), kGenLambdaToPrPi); + + if (v0Type == kLambda) { + histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[0]); + histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), daughterPDGs[1]); + histos.fill(HIST("McGen/h1f_lambda_daughter_PDG"), mcpart.pdgCode()); + histos.fill(HIST("McGen/Lambda/Proton/hPt"), vDauPt[0]); + histos.fill(HIST("McGen/Lambda/Proton/hEta"), vDauEta[0]); + histos.fill(HIST("McGen/Lambda/Proton/hRap"), vDauRap[0]); + histos.fill(HIST("McGen/Lambda/Proton/hPhi"), vDauPhi[0]); + histos.fill(HIST("McGen/Lambda/Pion/hPt"), vDauPt[1]); + histos.fill(HIST("McGen/Lambda/Pion/hEta"), vDauEta[1]); + histos.fill(HIST("McGen/Lambda/Pion/hRap"), vDauRap[1]); + histos.fill(HIST("McGen/Lambda/Pion/hPhi"), vDauPhi[1]); + fillKinematicHists(mcpart.pt(), mcpart.eta(), mcpart.y(), mcpart.phi()); + } else { + histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[0]); + histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), daughterPDGs[1]); + histos.fill(HIST("McGen/h1f_antilambda_daughter_PDG"), mcpart.pdgCode()); + histos.fill(HIST("McGen/AntiLambda/Pion/hPt"), vDauPt[0]); + histos.fill(HIST("McGen/AntiLambda/Pion/hEta"), vDauEta[0]); + histos.fill(HIST("McGen/AntiLambda/Pion/hRap"), vDauRap[0]); + histos.fill(HIST("McGen/AntiLambda/Pion/hPhi"), vDauPhi[0]); + histos.fill(HIST("McGen/AntiLambda/Proton/hPt"), vDauPt[1]); + histos.fill(HIST("McGen/AntiLambda/Proton/hEta"), vDauEta[1]); + histos.fill(HIST("McGen/AntiLambda/Proton/hRap"), vDauRap[1]); + histos.fill(HIST("McGen/AntiLambda/Proton/hPhi"), vDauPhi[1]); + fillKinematicHists(mcpart.pt(), mcpart.eta(), mcpart.y(), mcpart.phi()); + } + + // Fill Lambda McGen Table + lambdaMCGenTrackTable(lambdaMCGenCollisionTable.lastIndex(), mcpart.px(), mcpart.py(), mcpart.pz(), + mcpart.pt(), mcpart.eta(), mcpart.phi(), mcpart.y(), RecoDecay::m(mcpart.p(), mcpart.e()), + daughterIDs[0], daughterIDs[1], (int8_t)v0Type, -999., -999., v0PrmScdType, 1.); + } + } + + template + void analyzeMcRecoGen(M const& mcCollision, C const& collisions, V const& V0s, T const& tracks, P const& mcParticles) + { + // Number of Rec Collisions Associated to the McGen Collision + int nRecCols = collisions.size(); + if (nRecCols != 0) { + histos.fill(HIST("McGen/h1f_collision_recgen"), nRecCols); + } + + // Always fill gen tables so processMCGenXi/Omega has entries. + // selCollision sets cent/mult as a side-effect — works for both Run2 and Run3. + cent = 0.f; + mult = 0.f; + if (nRecCols >= 1 && + collisions.begin().has_mcCollision() && + collisions.begin().mcCollisionId() == mcCollision.globalIndex()) { + selCollision(collisions.begin()); // sets cent and mult + } + fillLambdaMcGenTables(mcCollision, mcParticles); + + // Reco tables only for clean 1-to-1 matched collisions + if (nRecCols != 1) { + return; + } + histos.fill(HIST("McGen/h1f_collisions_info"), kTotCol); + if (!collisions.begin().has_mcCollision() || !selCollision(collisions.begin()) || collisions.begin().mcCollisionId() != mcCollision.globalIndex()) { + return; + } + histos.fill(HIST("McGen/h1f_collisions_info"), kPassSelCol); + histos.fill(HIST("McGen/h2f_collision_posZ"), mcCollision.posZ(), collisions.begin().posZ()); + auto v0Tracks = V0s.sliceBy(perCollision, collisions.begin().globalIndex()); + fillLambdaRecoTables(collisions.begin(), v0Tracks, tracks); + } + + SliceCache cache; + Preslice> perCollision = aod::v0data::collisionId; + + using CollisionsRun3 = soa::Join; + using CollisionsRun2 = soa::Join; + using Tracks = soa::Join; + using TracksRun2 = soa::Join; + using TracksMC = soa::Join; + using TracksMCRun2 = soa::Join; + using McV0Tracks = soa::Join; + + void processDataRun3(CollisionsRun3::iterator const& collision, aod::V0Datas const& V0s, Tracks const& tracks) + { + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processDataRun3, "Process for Run3 DATA", true); + + void processDataRun2(CollisionsRun2::iterator const& collision, aod::V0Datas const& V0s, TracksRun2 const& tracks) + { + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processDataRun2, "Process for Run2 DATA", false); + + void processMCRecoRun3(soa::Join::iterator const& collision, aod::McCollisions const&, + McV0Tracks const& V0s, TracksMC const& tracks, aod::McParticles const&) + { + // check collision + if (!selCollision(collision)) { + return; + } + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processMCRecoRun3, "Process for Run3 McReco DATA", false); + + void processMCRecoRun2(soa::Join::iterator const& collision, aod::McCollisions const&, + McV0Tracks const& V0s, TracksMCRun2 const& tracks, aod::McParticles const&) + { + // check collision + if (!selCollision(collision)) { + return; + } + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processMCRecoRun2, "Process for Run2 McReco DATA", false); + + void processMCRun3(aod::McCollisions::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + McV0Tracks const& V0s, TracksMC const& tracks, + aod::McParticles const& mcParticles) + { + analyzeMcRecoGen(mcCollision, collisions, V0s, tracks, mcParticles); + } + + PROCESS_SWITCH(LambdaTableProducer, processMCRun3, "Process for Run3 MC RecoGen", false); + + void processMCRun2(aod::McCollisions::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + McV0Tracks const& V0s, TracksMCRun2 const& tracks, + aod::McParticles const& mcParticles) + { + analyzeMcRecoGen(mcCollision, collisions, V0s, tracks, mcParticles); + } + + PROCESS_SWITCH(LambdaTableProducer, processMCRun2, "Process for Run2 MC RecoGen", false); + + // Gen-only: fills LambdaMcGenCollisions + LambdaMcGenTracks without touching reco tables. + // Use alongside processMCRecoRun3 (which fills reco tables only). + void processMCGenOnlyRun3(aod::McCollisions::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + aod::McParticles const& mcParticles) + { + // Try to obtain centrality from a matched reco collision + cent = 0.f; + mult = 0.f; + if (collisions.size() >= 1) { + auto firstReco = collisions.begin(); + if (firstReco.has_mcCollision() && + firstReco.mcCollisionId() == mcCollision.globalIndex()) { + selCollision(firstReco); // sets cent and mult + } + } + fillLambdaMcGenTables(mcCollision, mcParticles); + } + + PROCESS_SWITCH(LambdaTableProducer, processMCGenOnlyRun3, "Gen-only Run3 (no reco tables)", false); +}; + +struct LambdaTracksExtProducer { + + Produces lambdaTrackExtTable; + + // Configurables + Configurable cAcceptAllLambda{"cAcceptAllLambda", false, "Accept all Lambda"}; + Configurable cRejAllLambdaShaDau{"cRejAllLambdaShaDau", true, "Reject all Lambda sharing daughters"}; + Configurable cSelLambdaMassPdg{"cSelLambdaMassPdg", false, "Select Lambda closest to Pdg Mass"}; + Configurable cSelLambdaTScore{"cSelLambdaTScore", false, "Select Lambda based on t-score"}; + Configurable cA{"cA", 0.6, "a * |lambdaMass - lambdaPdgMass|"}; + Configurable cB{"cB", 0.6, "b * DcaPrPi"}; + Configurable cC{"cC", 0.6, "c * Cos(theta_{PA})"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + // Axis Specifications + const AxisSpec axisMult(10, 0, 10); + const AxisSpec axisMass(100, 1.06, 1.16, "Inv Mass (GeV/#it{c}^{2})"); + const AxisSpec axisCPA(100, 0.995, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); + const AxisSpec axisDEta(320, -1.6, 1.6, "#Delta#eta"); + const AxisSpec axisDPhi(640, -PIHalf, 3. * PIHalf, "#Delta#varphi"); + + // Histograms Booking + histos.add("h1i_totlambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h1i_totantilambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h1i_lambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h1i_antilambda_mult", "Multiplicity", kTH1I, {axisMult}); + histos.add("h2d_n2_etaphi_LaP_LaM", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); + histos.add("h2d_n2_etaphi_LaP_LaP", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); + histos.add("h2d_n2_etaphi_LaM_LaM", "#rho_{2}^{SharePair}", kTH2D, {axisDEta, axisDPhi}); + + // InvMass, DcaDau and CosPA + histos.add("Reco/h1f_lambda_invmass", "M_{p#pi}", kTH1F, {axisMass}); + histos.add("Reco/h1f_lambda_cospa", "cos(#theta_{PA})", kTH1F, {axisCPA}); + histos.add("Reco/h1f_lambda_dcadau", "DCA_{p#pi} at V0 Decay Vertex", kTH1F, {axisDcaDau}); + histos.add("Reco/h1f_antilambda_invmass", "M_{p#pi}", kTH1F, {axisMass}); + histos.add("Reco/h1f_antilambda_cospa", "cos(#theta_{PA})", kTH1F, {axisCPA}); + histos.add("Reco/h1f_antilambda_dcadau", "DCA_{p#pi} at V0 Decay Vertex", kTH1F, {axisDcaDau}); + + histos.addClone("Reco/", "SharingDau/"); + } + + template + void fillHistos(T const& track) + { + static constexpr std::string_view SubDir[] = {"Reco/", "SharingDau/"}; + + if (track.v0Type() == kLambda) { + histos.fill(HIST(SubDir[sd]) + HIST("h1f_lambda_invmass"), track.mass()); + histos.fill(HIST(SubDir[sd]) + HIST("h1f_lambda_dcadau"), track.dcaDau()); + histos.fill(HIST(SubDir[sd]) + HIST("h1f_lambda_cospa"), track.cosPA()); + } else { + histos.fill(HIST(SubDir[sd]) + HIST("h1f_antilambda_invmass"), track.mass()); + histos.fill(HIST(SubDir[sd]) + HIST("h1f_antilambda_dcadau"), track.dcaDau()); + histos.fill(HIST(SubDir[sd]) + HIST("h1f_antilambda_cospa"), track.cosPA()); + } + } + + void process(aod::LambdaCollisions::iterator const&, aod::LambdaTracks const& tracks) + { + + int nTotLambda = 0, nTotAntiLambda = 0, nSelLambda = 0, nSelAntiLambda = 0; + + for (auto const& lambda : tracks) { + bool lambdaMinDeltaMassFlag = true, lambdaMinTScoreFlag = true; + bool lambdaSharingDauFlag = false, trueLambdaFlag = false; + std::vector vSharedDauLambdaIndex; + float tLambda = 0., tTrack = 0.; + + if (lambda.v0Type() == kLambda) { + ++nTotLambda; + } else if (lambda.v0Type() == kAntiLambda) { + ++nTotAntiLambda; + } + + tLambda = (cA * std::abs(lambda.mass() - MassLambda0)) + (cB * lambda.dcaDau()) + (cC * std::abs(lambda.cosPA() - 1.)); + + for (auto const& track : tracks) { + // check lambda index (don't analyze same lambda track !!!) + if (lambda.index() == track.index()) { + continue; + } + + // check if lambda shares daughters with any other track + if (lambda.posTrackId() == track.posTrackId() || lambda.negTrackId() == track.negTrackId()) { + vSharedDauLambdaIndex.push_back(track.index()); + lambdaSharingDauFlag = true; + + // Fill DEta-DPhi Histogram + if ((lambda.v0Type() == kLambda && track.v0Type() == kAntiLambda) || (lambda.v0Type() == kAntiLambda && track.v0Type() == kLambda)) { + histos.fill(HIST("h2d_n2_etaphi_LaP_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); + } else if (lambda.v0Type() == kLambda && track.v0Type() == kLambda) { + histos.fill(HIST("h2d_n2_etaphi_LaP_LaP"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); + } else if (lambda.v0Type() == kAntiLambda && track.v0Type() == kAntiLambda) { + histos.fill(HIST("h2d_n2_etaphi_LaM_LaM"), lambda.eta() - track.eta(), RecoDecay::constrainAngle((lambda.phi() - track.phi()), -PIHalf)); + } + + // decision based on mass closest to PdgMass of Lambda + if (std::abs(lambda.mass() - MassLambda0) > std::abs(track.mass() - MassLambda0)) { + lambdaMinDeltaMassFlag = false; + } + + // decisions based on t-score + tTrack = (cA * std::abs(track.mass() - MassLambda0)) + (cB * track.dcaDau()) + (cC * std::abs(track.cosPA() - 1.)); + if (tLambda > tTrack) { + lambdaMinTScoreFlag = false; + } + } + } + + // fill QA histograms + if (lambdaSharingDauFlag) { + fillHistos(lambda); + } else { + fillHistos(lambda); + } + + if (cAcceptAllLambda) { // Accept all lambda + trueLambdaFlag = true; + } else if (cRejAllLambdaShaDau && !lambdaSharingDauFlag) { // Reject all lambda sharing daughter + trueLambdaFlag = true; + } else if (cSelLambdaMassPdg && lambdaMinDeltaMassFlag) { // Select lambda closest to pdg mass + trueLambdaFlag = true; + } else if (cSelLambdaTScore && lambdaMinTScoreFlag) { // Select lambda based on t-score + trueLambdaFlag = true; + } + + // Multiplicity of selected lambda + if (trueLambdaFlag) { + if (lambda.v0Type() == kLambda) { + ++nSelLambda; + } else if (lambda.v0Type() == kAntiLambda) { + ++nSelAntiLambda; + } + } + + // fill LambdaTrackExt table + lambdaTrackExtTable(lambdaSharingDauFlag, vSharedDauLambdaIndex, trueLambdaFlag); + } + + // fill multiplicity histograms + if (nTotLambda != 0) { + histos.fill(HIST("h1i_totlambda_mult"), nTotLambda); + } + + if (nTotAntiLambda != 0) { + histos.fill(HIST("h1i_totantilambda_mult"), nTotAntiLambda); + } + + if (nSelLambda != 0) { + histos.fill(HIST("h1i_lambda_mult"), nSelLambda); + } + + if (nSelAntiLambda != 0) { + histos.fill(HIST("h1i_antilambda_mult"), nSelAntiLambda); + } + } +}; + +struct LambdaR2Correlation { + // Global Configurables + Configurable cNPtBins{"cNPtBins", 34, "N pT Bins"}; + Configurable cMinPt{"cMinPt", 0.8, "pT Min"}; + Configurable cMaxPt{"cMaxPt", 4.2, "pT Max"}; + Configurable cNRapBins{"cNRapBins", 20, "N Rapidity Bins"}; + Configurable cMinRap{"cMinRap", -0.5, "Minimum Rapidity"}; + Configurable cMaxRap{"cMaxRap", 0.5, "Maximum Rapidity"}; + Configurable cNPhiBins{"cNPhiBins", 36, "N Phi Bins"}; + Configurable cAnaSecondaries{"cAnaSecondaries", false, "Analysze Secondaries"}; + Configurable cAnaPairs{"cAnaPairs", false, "Analyze Pairs Flag"}; + Configurable cAnaSecondaryPairs{"cAnaSecondaryPairs", false, "Analyze Secondary Pairs Flag"}; + + // Eta/Rap Analysis + Configurable cDoEtaAnalysis{"cDoEtaAnalysis", false, "Eta/Rap Analysis Flag"}; + + // Centrality Axis + ConfigurableAxis cMultBins{"cMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 30.0f, 50.f, 80.0f, 100.f}, "Variable Mult-Bins"}; + + // 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 = TwoPI; + float rapbinwidth = 0.; + float phibinwidth = 0.; + float q = 0., e = 0., qinv = 0.; + float cent = 0.; + + void init(InitContext const&) + { + // Set Density Histogram Attributes + nrapbins = static_cast(cNRapBins); + kminrap = static_cast(cMinRap); + kmaxrap = static_cast(cMaxRap); + nphibins = static_cast(cNPhiBins); + + rapbinwidth = (kmaxrap - kminrap) / nrapbins; + phibinwidth = (kmaxphi - kminphi) / nphibins; + + int knrapphibins = static_cast(cNRapBins) * static_cast(cNPhiBins); + float kminrapphi = 0.; + float kmaxrapphi = knrapphibins; + + const AxisSpec axisCheck(1, 0, 1, ""); + const AxisSpec axisPosZ(220, -11, 11, "V_{z} (cm)"); + const AxisSpec axisCent(cMultBins, "FT0M (%)"); + const AxisSpec axisChMult(200, 0, 200, "N_{ch}"); + const AxisSpec axisMult(10, 0, 10, "N_{#Lambda}"); + const AxisSpec axisMass(100, 1.06, 1.16, "M_{#Lambda} (GeV/#it{c}^{2})"); + const AxisSpec axisPt(cNPtBins, cMinPt, cMaxPt, "p_{T} (GeV/#it{c})"); + const AxisSpec axisEta(cNRapBins, cMinRap, cMaxRap, "#eta"); + const AxisSpec axisRap(cNRapBins, cMinRap, cMaxRap, "y"); + const AxisSpec axisPhi(cNPhiBins, 0., TwoPI, "#varphi (rad)"); + const AxisSpec axisRapPhi(knrapphibins, kminrapphi, kmaxrapphi, "y #varphi"); + const AxisSpec axisQinv(100, 0, 10, "q_{inv} (GeV/#it{c})"); + + // Create Histograms. + // Event + histos.add("Event/Reco/h1f_collision_posz", "V_{Z} Distribution", kTH1F, {axisPosZ}); + histos.add("Event/Reco/h1f_ft0m_mult_percentile", "FT0M (%)", kTH1F, {axisCent}); + histos.add("Event/Reco/h2f_Mult_vs_Centrality", "N_{ch} vs FT0M(%)", kTH2F, {axisCent, axisChMult}); + histos.add("Event/Reco/h2f_lambda_mult", "#Lambda - Multiplicity", kTH2F, {axisCent, axisMult}); + histos.add("Event/Reco/h2f_antilambda_mult", "#bar{#Lambda} - Multiplicity", kTH2F, {axisCent, axisMult}); + + // Efficiency Histograms + // Single Particle Efficiencies + histos.add("Reco/Primary/Efficiency/h2f_n1_centpt_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPt}); + histos.add("Reco/Primary/Efficiency/h2f_n1_centpt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPt}); + histos.add("Reco/Primary/Efficiency/h3f_n1_centpteta_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPt, axisEta}); + histos.add("Reco/Primary/Efficiency/h3f_n1_centpteta_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPt, axisEta}); + histos.add("Reco/Primary/Efficiency/h3f_n1_centptrap_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPt, axisRap}); + histos.add("Reco/Primary/Efficiency/h3f_n1_centptrap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPt, axisRap}); + + // Single and Two Particle Densities + // 1D Histograms + histos.add("Reco/Primary/h3f_n1_centmasspt_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisMass, axisPt}); + histos.add("Reco/Primary/h3f_n1_centmasspt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisMass, axisPt}); + histos.add("Reco/Primary/h2f_n1_pt_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPt}); + histos.add("Reco/Primary/h2f_n1_pt_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPt}); + histos.add("Reco/Primary/h2f_n1_eta_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisEta}); + histos.add("Reco/Primary/h2f_n1_eta_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisEta}); + histos.add("Reco/Primary/h2f_n1_rap_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisRap}); + histos.add("Reco/Primary/h2f_n1_rap_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisRap}); + histos.add("Reco/Primary/h2f_n1_phi_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisPhi}); + histos.add("Reco/Primary/h2f_n1_phi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisPhi}); + + // rho1 for R2 RapPhi + histos.add("Reco/Primary/h3f_n1_rapphi_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisRap, axisPhi}); + histos.add("Reco/Primary/h3f_n1_rapphi_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisPhi}); + + // rho1 for Q_{inv} + histos.add("Reco/Primary/h3f_n1_pteta_LaP", "#rho_{1}^{#Lambda}", kTH3F, {axisCent, axisPt, axisEta}); + histos.add("Reco/Primary/h3f_n1_pteta_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH3F, {axisCent, axisPt, axisEta}); + + // Clone Singles Primary/Secondary Histogram + if (cAnaSecondaries) { + histos.addClone("Reco/Primary/", "Reco/Secondary/"); + } + + if (cAnaPairs) { + // rho2 for numerator of R2 + histos.add("Reco/PP/h3f_n2_raprap_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisRap}); + histos.add("Reco/PP/h3f_n2_raprap_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisRap, axisRap}); + histos.add("Reco/PP/h3f_n2_raprap_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisRap, axisRap}); + histos.add("Reco/PP/h3f_n2_phiphi_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); + histos.add("Reco/PP/h3f_n2_phiphi_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisPhi, axisPhi}); + histos.add("Reco/PP/h3f_n2_phiphi_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisPhi, axisPhi}); + + // rho2 for R2 Rap1Phi1Rap2Phi2 + histos.add("Reco/PP/h3f_n2_rapphi_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/PP/h3f_n2_rapphi_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + histos.add("Reco/PP/h3f_n2_rapphi_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH3F, {axisCent, axisRapPhi, axisRapPhi}); + + // rho2 for R2 Qinv + histos.add("Reco/PP/h2f_n2_qinv_LaP_LaM", "#rho_{2}^{#Lambda#bar{#Lambda}}", kTH2F, {axisCent, axisQinv}); + histos.add("Reco/PP/h2f_n2_qinv_LaP_LaP", "#rho_{2}^{#Lambda#Lambda}", kTH2F, {axisCent, axisQinv}); + histos.add("Reco/PP/h2f_n2_qinv_LaM_LaM", "#rho_{2}^{#bar{#Lambda}#bar{#Lambda}}", kTH2F, {axisCent, axisQinv}); + + // Clone Pairs Histograms + if (cAnaSecondaryPairs) { + histos.addClone("Reco/PP/", "Reco/PS/"); + histos.addClone("Reco/PP/", "Reco/SP/"); + histos.addClone("Reco/PP/", "Reco/SS/"); + } + } + + // MCGen + if (doprocessMCGen) { + histos.addClone("Event/Reco/", "Event/McGen/"); + histos.addClone("Reco/", "McGen/"); + } + } + + template + void fillPairHistos(U& p1, U& p2) + { + static constexpr std::string_view SubDirRecGen[] = {"Reco/", "McGen/"}; + static constexpr std::string_view SubDirPrmScd[] = {"PP/", "PS/", "SP/", "SS/"}; + static constexpr std::string_view SubDirHist[] = {"LaP_LaM", "LaP_LaP", "LaM_LaM"}; + + float rap1 = (cDoEtaAnalysis) ? p1.eta() : p1.rap(); + float rap2 = (cDoEtaAnalysis) ? p2.eta() : p2.rap(); + + int rapbin1 = static_cast((rap1 - kminrap) / rapbinwidth); + int rapbin2 = static_cast((rap2 - kminrap) / rapbinwidth); + + int phibin1 = static_cast(p1.phi() / phibinwidth); + int phibin2 = static_cast(p2.phi() / phibinwidth); + + float corfac = p1.corrFact() * p2.corrFact(); + + // fill rho2 histograms + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_raprap_") + HIST(SubDirHist[part_pair]), cent, rap1, rap2, corfac); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_phiphi_") + HIST(SubDirHist[part_pair]), cent, p1.phi(), p2.phi(), corfac); + + 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(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h3f_n2_rapphi_") + HIST(SubDirHist[part_pair]), cent, rapphix + 0.5, rapphiy + 0.5, corfac); + } + + // qinv histograms + q = RecoDecay::p((p1.px() - p2.px()), (p1.py() - p2.py()), (p1.pz() - p2.pz())); + e = RecoDecay::e(p1.px(), p1.py(), p1.pz(), MassLambda0) - RecoDecay::e(p2.px(), p2.py(), p2.pz(), MassLambda0); + qinv = std::sqrt(-RecoDecay::m2(q, e)); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[psp]) + HIST("h2f_n2_qinv_") + HIST(SubDirHist[part_pair]), cent, qinv, corfac); + } + + template + void analyzeSingles(T const& tracks) + { + static constexpr std::string_view SubDirRecGen[] = {"Reco/", "McGen/"}; + static constexpr std::string_view SubDirPrmScd[] = {"Primary/", "Secondary/"}; + static constexpr std::string_view SubDirHist[] = {"LaP", "LaM"}; + + int ntrk = 0; + + for (auto const& track : tracks) { + // count tracks + ++ntrk; + + // Efficiency Plots + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("Efficiency/h2f_n1_centpt_") + HIST(SubDirHist[part]), cent, track.pt()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("Efficiency/h3f_n1_centpteta_") + HIST(SubDirHist[part]), cent, track.pt(), track.eta()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("Efficiency/h3f_n1_centptrap_") + HIST(SubDirHist[part]), cent, track.pt(), track.rap()); + + // QA Plots + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h3f_n1_centmasspt_") + HIST(SubDirHist[part]), cent, track.mass(), track.pt()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h2f_n1_pt_") + HIST(SubDirHist[part]), cent, track.pt(), track.corrFact()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h2f_n1_eta_") + HIST(SubDirHist[part]), cent, track.eta(), track.corrFact()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h2f_n1_phi_") + HIST(SubDirHist[part]), cent, track.phi(), track.corrFact()); + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h2f_n1_rap_") + HIST(SubDirHist[part]), cent, track.rap(), track.corrFact()); + + // Rho1 for N1RapPhi + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h3f_n1_rapphi_") + HIST(SubDirHist[part]), cent, track.rap(), track.phi(), track.corrFact()); + + // Rho1 for Q_{inv} Bkg Estimation + histos.fill(HIST(SubDirRecGen[rec_gen]) + HIST(SubDirPrmScd[pst]) + HIST("h3f_n1_pteta_") + HIST(SubDirHist[part]), cent, track.pt(), track.eta(), track.corrFact()); + } + + // fill multiplicity histograms + if (ntrk != 0) { + if (part == kLambda) { + histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h2f_lambda_mult"), cent, ntrk); + } else { + histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h2f_antilambda_mult"), cent, ntrk); + } + } + } + + template + void analyzePairs(T const& trks_1, T const& trks_2) + { + for (auto const& trk_1 : trks_1) { + for (auto const& trk_2 : trks_2) { + // check for same index for Lambda-Lambda / AntiLambda-AntiLambda + if (samelambda && ((trk_1.index() == trk_2.index()))) { + continue; + } + fillPairHistos(trk_1, trk_2); + } + } + } + + using LambdaCollisions = aod::LambdaCollisions; + using LambdaTracks = soa::Join; + + // using MyCascades = aod::CascDataExt; // ← NOT CascDatas. NEVER CascDatas. + using MyCascades = soa::Filtered; + + SliceCache cache; + Partition partPrimLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + Partition partPrimAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + Partition partSecdLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); + Partition partSecdAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrackext::trueLambdaFlag == true) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); + + void processDataReco(LambdaCollisions::iterator const& collision, LambdaTracks const&) + { + histos.fill(HIST("Event/Reco/h1f_collision_posz"), collision.posZ()); + histos.fill(HIST("Event/Reco/h1f_ft0m_mult_percentile"), collision.cent()); + histos.fill(HIST("Event/Reco/h2f_Mult_vs_Centrality"), collision.cent(), collision.mult()); + + cent = collision.cent(); + + auto lambdaPrimTracks = partPrimLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto antiLambdaPrimTracks = partPrimAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto lambdaSecdTracks = partSecdLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + auto antiLambdaSecdTracks = partSecdAntiLambdaTracks->sliceByCached(aod::lambdatrack::lambdaCollisionId, collision.globalIndex(), cache); + + analyzeSingles(lambdaPrimTracks); + analyzeSingles(antiLambdaPrimTracks); + + if (cAnaSecondaries) { + analyzeSingles(lambdaSecdTracks); + analyzeSingles(antiLambdaSecdTracks); + } + + if (cAnaPairs) { + // Primary Pairs Only + analyzePairs(lambdaPrimTracks, antiLambdaPrimTracks); + analyzePairs(lambdaPrimTracks, lambdaPrimTracks); + analyzePairs(antiLambdaPrimTracks, antiLambdaPrimTracks); + + // Secondary Pairs + if (cAnaSecondaryPairs) { + analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaPrimTracks, lambdaSecdTracks); + analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, lambdaPrimTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, lambdaSecdTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); + } + } + } + + PROCESS_SWITCH(LambdaR2Correlation, processDataReco, "Process for Data and MCReco", true); + + using LambdaMcGenCollisions = aod::LambdaMcGenCollisions; + using LambdaMcGenTracks = aod::LambdaMcGenTracks; + + SliceCache cachemc; + Partition partMcPrimLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + Partition partMcPrimAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kPrimary); + Partition partMcSecdLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); + Partition partMcSecdAntiLambdaTracks = (aod::lambdatrack::v0Type == (int8_t)kAntiLambda) && (aod::lambdatrack::v0PrmScd == (int8_t)kSecondary); + + void processMCGen(LambdaMcGenCollisions::iterator const& mcgencol, LambdaMcGenTracks const&) + { + histos.fill(HIST("Event/McGen/h1f_collision_posz"), mcgencol.posZ()); + histos.fill(HIST("Event/McGen/h1f_ft0m_mult_percentile"), mcgencol.cent()); + histos.fill(HIST("Event/McGen/h2f_Mult_vs_Centrality"), mcgencol.cent(), mcgencol.mult()); + + cent = mcgencol.cent(); + + auto lambdaPrimTracks = partMcPrimLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); + auto antiLambdaPrimTracks = partMcPrimAntiLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); + auto lambdaSecdTracks = partMcSecdLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); + auto antiLambdaSecdTracks = partMcSecdAntiLambdaTracks->sliceByCached(aod::lambdamcgentrack::lambdaMcGenCollisionId, mcgencol.globalIndex(), cachemc); + + analyzeSingles(lambdaPrimTracks); + analyzeSingles(antiLambdaPrimTracks); + + if (cAnaSecondaries) { + analyzeSingles(lambdaSecdTracks); + analyzeSingles(antiLambdaSecdTracks); + } + + if (cAnaPairs) { + // Primary Pairs Only + analyzePairs(lambdaPrimTracks, antiLambdaPrimTracks); + analyzePairs(lambdaPrimTracks, lambdaPrimTracks); + analyzePairs(antiLambdaPrimTracks, antiLambdaPrimTracks); + + // Secondary Pairs + if (cAnaSecondaryPairs) { + analyzePairs(lambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaPrimTracks, lambdaSecdTracks); + analyzePairs(antiLambdaPrimTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, lambdaPrimTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaPrimTracks); + analyzePairs(lambdaSecdTracks, antiLambdaSecdTracks); + analyzePairs(lambdaSecdTracks, lambdaSecdTracks); + analyzePairs(antiLambdaSecdTracks, antiLambdaSecdTracks); + } + } + } + + PROCESS_SWITCH(LambdaR2Correlation, processMCGen, "Process for MC Generated", false); +}; + +struct CascadeSelector { + + Service ccdb; + Service pdgDB; + + Produces cascflags; + + // Configurables + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "CCDB url"}; + Configurable useTrigger{"useTrigger", false, "Use trigger selection on skimmed data"}; + Configurable triggerList{"triggerList", "fDoubleXi, fDoubleOmega, fOmegaXi", "List of triggers used to select events"}; + Configurable doTFBorderCut{"doTFBorderCut", true, "Switch to apply TimeframeBorderCut event selection"}; + Configurable doSel8{"doSel8", true, "Switch to apply sel8 event selection"}; + Configurable doNoSameBunchPileUp{"doNoSameBunchPileUp", true, "Switch to apply NoSameBunchPileUp event selection"}; + Configurable INEL{"INEL", 0, "Number of charged tracks within |eta| < 1 has to be greater than value"}; + Configurable maxVertexZ{"maxVertexZ", 10., "Maximum value of z coordinate of PV"}; + Configurable etaCascades{"etaCascades", 0.8, "min/max of eta for cascades"}; + Configurable doCompetingMassCut{"doCompetingMassCut", true, "Switch to apply a competing mass cut for the Omega's"}; + Configurable competingMassWindow{"competingMassWindow", 0.01, "Mass window for the competing mass cut"}; + + // Tracklevel + Configurable tpcNsigmaBachelor{"tpcNsigmaBachelor", 3, "TPC NSigma bachelor"}; + Configurable tpcNsigmaProton{"tpcNsigmaProton", 3, "TPC NSigma proton <- lambda"}; + Configurable tpcNsigmaPion{"tpcNsigmaPion", 3, "TPC NSigma pion <- lambda"}; + Configurable minTPCCrossedRows{"minTPCCrossedRows", 80, "min N TPC crossed rows"}; // TODO: finetune! 80 > 159/2, so no split tracks? + Configurable minITSClusters{"minITSClusters", 4, "minimum number of ITS clusters"}; + Configurable etaTracks{"etaTracks", 1.0, "min/max of eta for tracks"}; + Configurable tpcChi2{"tpcChi2", 4, "TPC Chi2"}; + Configurable itsChi2{"itsChi2", 36, "ITS Chi2"}; + + // Selection criteria - compatible with core wagon autodetect - copied from cascadeanalysis.cxx + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + Configurable v0setting_cospa{"v0setting_cospa", 0.995, "v0setting_cospa"}; + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 1.0, "v0setting_dcav0dau"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.1, "v0setting_dcapostopv"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.1, "v0setting_dcanegtopv"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "v0setting_radius"}; + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.95, "cascadesetting_cospa"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "cascadesetting_dcacascdau"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.05, "cascadesetting_dcabachtopv"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.9, "cascadesetting_cascradius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "cascadesetting_v0masswindow"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "cascadesetting_mindcav0topv"}; + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + // TODO: variables as function of Omega mass, only do Xi for now + ConfigurableAxis radiusAxis = {"radiusAxis", {100, 0.0f, 50.0f}, "cm"}; + ConfigurableAxis cpaAxis = {"cpaAxis", {100, 0.95f, 1.0f}, "CPA"}; + ConfigurableAxis vertexAxis = {"vertexAxis", {100, -10.0f, 10.0f}, "cm"}; + ConfigurableAxis dcaAxis = {"dcaAxis", {100, 0.0f, 2.0f}, "cm"}; + ConfigurableAxis invXiMassAxis = {"invXiMassAxis", {100, 1.28f, 1.38f}, "Inv. Mass (GeV/c^{2})"}; + ConfigurableAxis invOmegaMassAxis = {"invOmegaMassAxis", {100, 1.62f, 1.72f}, "Inv. Mass (GeV/c^{2})"}; + ConfigurableAxis ptAxis = {"ptAxis", {150, 0, 15}, "#it{p}_{T}"}; + ConfigurableAxis rapidityAxis{"rapidityAxis", {100, -1.f, 1.f}, "y"}; + ConfigurableAxis invLambdaMassAxis{"invLambdaMassAxis", {100, 1.07f, 1.17f}, "Inv. Mass (GeV/c^{2})"}; + AxisSpec itsClustersAxis{8, -0.5, 7.5, "number of ITS clusters"}; + AxisSpec tpcRowsAxis{160, -0.5, 159.5, "TPC crossed rows"}; + HistogramRegistry registry{ + "registry", + { + // basic selection variables + {"hV0Radius", "hV0Radius", {HistType::kTH3F, {radiusAxis, invXiMassAxis, ptAxis}}}, + {"hCascRadius", "hCascRadius", {HistType::kTH3F, {radiusAxis, invXiMassAxis, ptAxis}}}, + {"hV0CosPA", "hV0CosPA", {HistType::kTH3F, {cpaAxis, invXiMassAxis, ptAxis}}}, + {"hCascCosPA", "hCascCosPA", {HistType::kTH3F, {cpaAxis, invXiMassAxis, ptAxis}}}, + {"hDCAPosToPV", "hDCAPosToPV", {HistType::kTH3F, {vertexAxis, invXiMassAxis, ptAxis}}}, + {"hDCANegToPV", "hDCANegToPV", {HistType::kTH3F, {vertexAxis, invXiMassAxis, ptAxis}}}, + {"hDCABachToPV", "hDCABachToPV", {HistType::kTH3F, {vertexAxis, invXiMassAxis, ptAxis}}}, + {"hDCAV0ToPV", "hDCAV0ToPV", {HistType::kTH3F, {vertexAxis, invXiMassAxis, ptAxis}}}, + {"hDCAV0Dau", "hDCAV0Dau", {HistType::kTH3F, {dcaAxis, invXiMassAxis, ptAxis}}}, + {"hDCACascDau", "hDCACascDau", {HistType::kTH3F, {dcaAxis, invXiMassAxis, ptAxis}}}, + {"hLambdaMass", "hLambdaMass", {HistType::kTH3F, {invLambdaMassAxis, invXiMassAxis, ptAxis}}}, + + {"hMassXiMinus", "hMassXiMinus", {HistType::kTH3F, {invXiMassAxis, ptAxis, rapidityAxis}}}, + {"hMassXiPlus", "hMassXiPlus", {HistType::kTH3F, {invXiMassAxis, ptAxis, rapidityAxis}}}, + {"hMassOmegaMinus", "hMassOmegaMinus", {HistType::kTH3F, {invOmegaMassAxis, ptAxis, rapidityAxis}}}, + {"hMassOmegaPlus", "hMassOmegaPlus", {HistType::kTH3F, {invOmegaMassAxis, ptAxis, rapidityAxis}}}, + + // // invariant mass per cut, start with Xi + // {"hMassXi0", "Xi inv mass before selections", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + // {"hMassXi1", "Xi inv mass after TPCnCrossedRows cut", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + // {"hMassXi2", "Xi inv mass after ITSnClusters cut", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + // {"hMassXi3", "Xi inv mass after topo cuts", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + // {"hMassXi4", "Xi inv mass after V0 daughters PID cut", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + // {"hMassXi5", "Xi inv mass after bachelor PID cut", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + + // ITS & TPC clusters, with Xi inv mass + {"hTPCnCrossedRowsPos", "hTPCnCrossedRowsPos", {HistType::kTH3F, {tpcRowsAxis, invXiMassAxis, ptAxis}}}, + {"hTPCnCrossedRowsNeg", "hTPCnCrossedRowsNeg", {HistType::kTH3F, {tpcRowsAxis, invXiMassAxis, ptAxis}}}, + {"hTPCnCrossedRowsBach", "hTPCnCrossedRowsBach", {HistType::kTH3F, {tpcRowsAxis, invXiMassAxis, ptAxis}}}, + {"hITSnClustersPos", "hITSnClustersPos", {HistType::kTH3F, {itsClustersAxis, invXiMassAxis, ptAxis}}}, + {"hITSnClustersNeg", "hITSnClustersNeg", {HistType::kTH3F, {itsClustersAxis, invXiMassAxis, ptAxis}}}, + {"hITSnClustersBach", "hITSnClustersBach", {HistType::kTH3F, {itsClustersAxis, invXiMassAxis, ptAxis}}}, + {"hTPCChi2Pos", "hTPCChi2Pos", {HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Pos"}}}}, + {"hTPCChi2Neg", "hTPCChi2Neg", {HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Neg"}}}}, + {"hTPCChi2Bach", "hTPCChi2Bach", {HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Bach"}}}}, + {"hITSChi2Pos", "hITSChi2Pos", {HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Pos"}}}}, + {"hITSChi2Neg", "hITSChi2Neg", {HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Neg"}}}}, + {"hITSChi2Bach", "hITSChi2Bach", {HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Bach"}}}}, + + {"hTriggerQA", "hTriggerQA", {HistType::kTH1F, {{2, -0.5, 1.5, "Trigger y/n"}}}}, + }, + }; + + // Keep track of which selections the candidates pass + void init(InitContext const&) + { + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + + auto h = registry.add("hSelectionStatus", "hSelectionStatus", HistType::kTH1I, {{10, 0, 10, "status"}}); + h->GetXaxis()->SetBinLabel(1, "All"); + h->GetXaxis()->SetBinLabel(2, "nTPC OK"); + h->GetXaxis()->SetBinLabel(3, "nITS OK"); + h->GetXaxis()->SetBinLabel(4, "track Chi2 OK"); + h->GetXaxis()->SetBinLabel(5, "Topo OK"); + h->GetXaxis()->SetBinLabel(6, "Track eta OK"); + h->GetXaxis()->SetBinLabel(7, "Cascade eta OK"); + h->GetXaxis()->SetBinLabel(8, "V0 PID OK"); + h->GetXaxis()->SetBinLabel(9, "Bach PID OK"); + + auto hEventSel = registry.add("hEventSel", "hEventSel", HistType::kTH1I, {{10, 0, 10, "selection criteria"}}); + hEventSel->GetXaxis()->SetBinLabel(1, "All"); + hEventSel->GetXaxis()->SetBinLabel(2, "sel8"); + hEventSel->GetXaxis()->SetBinLabel(3, "INEL0"); + hEventSel->GetXaxis()->SetBinLabel(4, "V_z"); + hEventSel->GetXaxis()->SetBinLabel(5, "NoSameBunchPileUp"); + hEventSel->GetXaxis()->SetBinLabel(6, "Selected events"); + + if (doprocessRecMC) { + // only create the rec matched to gen histograms if relevant + registry.add("truerec/hV0Radius", "hV0Radius", HistType::kTH1F, {radiusAxis}); + registry.add("truerec/hCascRadius", "hCascRadius", HistType::kTH1F, {radiusAxis}); + registry.add("truerec/hV0CosPA", "hV0CosPA", HistType::kTH1F, {cpaAxis}); + registry.add("truerec/hCascCosPA", "hCascCosPA", HistType::kTH1F, {cpaAxis}); + registry.add("truerec/hDCAPosToPV", "hDCAPosToPV", HistType::kTH1F, {vertexAxis}); + registry.add("truerec/hDCANegToPV", "hDCANegToPV", HistType::kTH1F, {vertexAxis}); + registry.add("truerec/hDCABachToPV", "hDCABachToPV", HistType::kTH1F, {vertexAxis}); + registry.add("truerec/hDCAV0ToPV", "hDCAV0ToPV", HistType::kTH1F, {vertexAxis}); + registry.add("truerec/hDCAV0Dau", "hDCAV0Dau", HistType::kTH1F, {dcaAxis}); + registry.add("truerec/hDCACascDau", "hDCACascDau", HistType::kTH1F, {dcaAxis}); + registry.add("truerec/hLambdaMass", "hLambdaMass", HistType::kTH1F, {invLambdaMassAxis}); + registry.add("truerec/hTPCnCrossedRowsPos", "hTPCnCrossedRowsPos", HistType::kTH1F, {tpcRowsAxis}); + registry.add("truerec/hTPCnCrossedRowsNeg", "hTPCnCrossedRowsNeg", HistType::kTH1F, {tpcRowsAxis}); + registry.add("truerec/hTPCnCrossedRowsBach", "hTPCnCrossedRowsBach", HistType::kTH1F, {tpcRowsAxis}); + registry.add("truerec/hITSnClustersPos", "hITSnClustersPos", HistType::kTH1F, {itsClustersAxis}); + registry.add("truerec/hITSnClustersNeg", "hITSnClustersNeg", HistType::kTH1F, {itsClustersAxis}); + registry.add("truerec/hITSnClustersBach", "hITSnClustersBach", HistType::kTH1F, {itsClustersAxis}); + registry.add("truerec/hTPCChi2Pos", "hTPCChi2Pos", HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Pos"}}); + registry.add("truerec/hTPCChi2Neg", "hTPCChi2Neg", HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Neg"}}); + registry.add("truerec/hTPCChi2Bach", "hTPCChi2Bach", HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Bach"}}); + registry.add("truerec/hITSChi2Pos", "hITSChi2Pos", HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Pos"}}); + registry.add("truerec/hITSChi2Neg", "hITSChi2Neg", HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Neg"}}); + registry.add("truerec/hITSChi2Bach", "hITSChi2Bach", HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Bach"}}); + registry.add("truerec/hXiMinus", "hXiMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("truerec/hXiPlus", "hXiPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("truerec/hOmegaMinus", "hOmegaMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("truerec/hOmegaPlus", "hOmegaPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); + } + + if (doprocessGenMC) { + // only create the MC gen histograms if relevant + registry.add("gen/hXiMinus", "hXiMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("gen/hXiPlus", "hXiPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("gen/hOmegaMinus", "hOmegaMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("gen/hOmegaPlus", "hOmegaPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); + + registry.add("genwithrec/hXiMinus", "hXiMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("genwithrec/hXiPlus", "hXiPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("genwithrec/hOmegaMinus", "hOmegaMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); + registry.add("genwithrec/hOmegaPlus", "hOmegaPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); + + registry.add("genwithrec/hNevents", "hNevents", HistType::kTH1F, {{1, 0, 1, "N generated events with reconstructed event"}}); + registry.add("gen/hNevents", "hNevents", HistType::kTH1F, {{1, 0, 1, "N generated events"}}); + } + } + + template + bool eventSelection(TCollision const& collision, bool fillHistos) + { + + if (fillHistos) + registry.fill(HIST("hEventSel"), 0); + if (doSel8 && !collision.sel8()) { + if (fillHistos) + registry.fill(HIST("hEventSel"), 1); + return false; + } else if (collision.multNTracksPVeta1() <= INEL) { + if (fillHistos) + registry.fill(HIST("hEventSel"), 2); + return false; + } else if (std::abs(collision.posZ()) > maxVertexZ) { + if (fillHistos) + registry.fill(HIST("hEventSel"), 3); + return false; + } else if (doNoSameBunchPileUp && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (fillHistos) + registry.fill(HIST("hEventSel"), 4); + return false; + } + // passes all selections + if (fillHistos) + registry.fill(HIST("hEventSel"), 5); + return true; + } + + template + void fillMatchedHistos(LabeledCascades::iterator rec, int flag, TCollision collision) + { + if (flag == 0) + return; + if (!rec.has_mcParticle()) + return; + auto gen = rec.mcParticle(); + if (!gen.isPhysicalPrimary()) + return; + int genpdg = gen.pdgCode(); + if ((flag < 3 && std::abs(genpdg) == 3312) || (flag > 1 && std::abs(genpdg) == 3334)) { + // if casc is consistent with Xi and has matched gen Xi OR cand is consistent with Omega and has matched gen omega + // have to do this in case we reco true Xi with only Omega hypothesis (or vice versa) (very unlikely) + registry.fill(HIST("truerec/hV0Radius"), rec.v0radius()); + registry.fill(HIST("truerec/hCascRadius"), rec.cascradius()); + registry.fill(HIST("truerec/hV0CosPA"), rec.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("truerec/hCascCosPA"), rec.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("truerec/hDCAPosToPV"), rec.dcapostopv()); + registry.fill(HIST("truerec/hDCANegToPV"), rec.dcanegtopv()); + registry.fill(HIST("truerec/hDCABachToPV"), rec.dcabachtopv()); + registry.fill(HIST("truerec/hDCAV0ToPV"), rec.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("truerec/hDCAV0Dau"), rec.dcaV0daughters()); + registry.fill(HIST("truerec/hDCACascDau"), rec.dcacascdaughters()); + registry.fill(HIST("truerec/hLambdaMass"), rec.mLambda()); + registry.fill(HIST("truerec/hITSnClustersPos"), rec.posTrack_as().itsNCls()); + registry.fill(HIST("truerec/hITSnClustersNeg"), rec.negTrack_as().itsNCls()); + registry.fill(HIST("truerec/hITSnClustersBach"), rec.bachelor_as().itsNCls()); + registry.fill(HIST("truerec/hTPCnCrossedRowsPos"), rec.posTrack_as().tpcNClsCrossedRows()); + registry.fill(HIST("truerec/hTPCnCrossedRowsNeg"), rec.negTrack_as().tpcNClsCrossedRows()); + registry.fill(HIST("truerec/hTPCnCrossedRowsBach"), rec.bachelor_as().tpcNClsCrossedRows()); + registry.fill(HIST("truerec/hITSChi2Pos"), rec.posTrack_as().itsChi2NCl()); + registry.fill(HIST("truerec/hITSChi2Neg"), rec.negTrack_as().itsChi2NCl()); + registry.fill(HIST("truerec/hITSChi2Bach"), rec.bachelor_as().itsChi2NCl()); + registry.fill(HIST("truerec/hTPCChi2Pos"), rec.posTrack_as().tpcChi2NCl()); + registry.fill(HIST("truerec/hTPCChi2Neg"), rec.negTrack_as().tpcChi2NCl()); + registry.fill(HIST("truerec/hTPCChi2Bach"), rec.bachelor_as().tpcChi2NCl()); + switch (genpdg) { // is matched so we can use genpdg + case 3312: + registry.fill(HIST("truerec/hXiMinus"), rec.pt(), rec.yXi()); + break; + case -3312: + registry.fill(HIST("truerec/hXiPlus"), rec.pt(), rec.yXi()); + break; + case 3334: + registry.fill(HIST("truerec/hOmegaMinus"), rec.pt(), rec.yOmega()); + break; + case -3334: + registry.fill(HIST("truerec/hOmegaPlus"), rec.pt(), rec.yOmega()); + break; + } + } + } + + template + int processCandidate(TCascade const& casc, TCollision const& collision) + { + // these are the tracks: + auto bachTrack = casc.template bachelor_as(); + auto posTrack = casc.template posTrack_as(); + auto negTrack = casc.template negTrack_as(); + + // topo variables before cuts: + registry.fill(HIST("hV0Radius"), casc.v0radius(), casc.mXi(), casc.pt()); + registry.fill(HIST("hCascRadius"), casc.cascradius(), casc.mXi(), casc.pt()); + registry.fill(HIST("hV0CosPA"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.mXi(), casc.pt()); + registry.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.mXi(), casc.pt()); + registry.fill(HIST("hDCAPosToPV"), casc.dcapostopv(), casc.mXi(), casc.pt()); + registry.fill(HIST("hDCANegToPV"), casc.dcanegtopv(), casc.mXi(), casc.pt()); + registry.fill(HIST("hDCABachToPV"), casc.dcabachtopv(), casc.mXi(), casc.pt()); + registry.fill(HIST("hDCAV0ToPV"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), casc.mXi(), casc.pt()); + registry.fill(HIST("hDCAV0Dau"), casc.dcaV0daughters(), casc.mXi(), casc.pt()); + registry.fill(HIST("hDCACascDau"), casc.dcacascdaughters(), casc.mXi(), casc.pt()); + registry.fill(HIST("hLambdaMass"), casc.mLambda(), casc.mXi(), casc.pt()); + + registry.fill(HIST("hITSnClustersPos"), posTrack.itsNCls(), casc.mXi(), casc.pt()); + registry.fill(HIST("hITSnClustersNeg"), negTrack.itsNCls(), casc.mXi(), casc.pt()); + registry.fill(HIST("hITSnClustersBach"), bachTrack.itsNCls(), casc.mXi(), casc.pt()); + registry.fill(HIST("hTPCnCrossedRowsPos"), posTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt()); + registry.fill(HIST("hTPCnCrossedRowsNeg"), negTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt()); + registry.fill(HIST("hTPCnCrossedRowsBach"), bachTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt()); + registry.fill(HIST("hITSChi2Pos"), posTrack.itsChi2NCl()); + registry.fill(HIST("hITSChi2Neg"), negTrack.itsChi2NCl()); + registry.fill(HIST("hITSChi2Bach"), bachTrack.itsChi2NCl()); + registry.fill(HIST("hTPCChi2Pos"), posTrack.tpcChi2NCl()); + registry.fill(HIST("hTPCChi2Neg"), negTrack.tpcChi2NCl()); + registry.fill(HIST("hTPCChi2Bach"), bachTrack.tpcChi2NCl()); + + registry.fill(HIST("hSelectionStatus"), 0); // all the cascade before selections + // registry.fill(HIST("hMassXi0"), casc.mXi(), casc.pt()); + + // TPC N crossed rows todo: check if minTPCCrossedRows > 50 + if (posTrack.tpcNClsCrossedRows() < minTPCCrossedRows || negTrack.tpcNClsCrossedRows() < minTPCCrossedRows || bachTrack.tpcNClsCrossedRows() < minTPCCrossedRows) + return 0; + + registry.fill(HIST("hSelectionStatus"), 1); // passes nTPC crossed rows + // registry.fill(HIST("hMassXi1"), casc.mXi(), casc.pt()); + + // ITS N clusters todo: check if minITSClusters > 0 + if (posTrack.itsNCls() < minITSClusters || negTrack.itsNCls() < minITSClusters || bachTrack.itsNCls() < minITSClusters) + return 0; + + registry.fill(HIST("hSelectionStatus"), 2); // passes nITS clusters + // registry.fill(HIST("hMassXi2"), casc.mXi(), casc.pt()); + + // Chi2 cuts + if (posTrack.itsChi2NCl() > itsChi2 || negTrack.itsChi2NCl() > itsChi2 || bachTrack.itsChi2NCl() > itsChi2) + return 0; + if (posTrack.tpcChi2NCl() > tpcChi2 || negTrack.tpcChi2NCl() > tpcChi2 || bachTrack.tpcChi2NCl() > tpcChi2) + return 0; + + registry.fill(HIST("hSelectionStatus"), 3); // passes Chi2 cuts + + //// TOPO CUTS //// TODO: improve! + double pvx = collision.posX(); + double pvy = collision.posY(); + double pvz = collision.posZ(); + if (casc.v0radius() < v0setting_radius || + casc.cascradius() < cascadesetting_cascradius || + casc.v0cosPA(pvx, pvy, pvz) < v0setting_cospa || + casc.casccosPA(pvx, pvy, pvz) < cascadesetting_cospa || + casc.dcav0topv(pvx, pvy, pvz) < cascadesetting_mindcav0topv || + std::abs(casc.mLambda() - 1.115683) > cascadesetting_v0masswindow) + return 0; // It failed at least one topo selection + + registry.fill(HIST("hSelectionStatus"), 4); // passes topo + // registry.fill(HIST("hMassXi3"), casc.mXi(), casc.pt()); + + if (std::abs(posTrack.eta()) > etaTracks || std::abs(negTrack.eta()) > etaTracks || std::abs(bachTrack.eta()) > etaTracks) + return 0; + + registry.fill(HIST("hSelectionStatus"), 5); // passes track eta + + if (std::abs(casc.eta()) > etaCascades) + return 0; + + registry.fill(HIST("hSelectionStatus"), 6); // passes candidate eta + + // TODO: TOF (for pT > 2 GeV per track?) + + //// TPC PID //// + // Lambda check + if (casc.sign() < 0) { + // Proton check: + if (std::abs(posTrack.tpcNSigmaPr()) > tpcNsigmaProton) + return 0; + // Pion check: + if (std::abs(negTrack.tpcNSigmaPi()) > tpcNsigmaPion) + return 0; + } else { + // Proton check: + if (std::abs(negTrack.tpcNSigmaPr()) > tpcNsigmaProton) + return 0; + // Pion check: + if (std::abs(posTrack.tpcNSigmaPi()) > tpcNsigmaPion) + return 0; + } + registry.fill(HIST("hSelectionStatus"), 7); // passes V0 daughters PID + // registry.fill(HIST("hMassXi4"), casc.mXi(), casc.pt()); + + // setting selection flag based on bachelor PID (and competing mass cut for omega's) + int flag = 0; + if (std::abs(bachTrack.tpcNSigmaPi()) < tpcNsigmaBachelor) + flag = 1; + if (std::abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor && (!doCompetingMassCut || std::abs(pdgDB->Mass(3312) - casc.mXi()) > competingMassWindow)) + flag = 3 - flag; // 3 if only consistent with omega, 2 if consistent with both + + switch (flag) { + case 1: // only Xi + registry.fill(HIST("hSelectionStatus"), 8); // passes bach PID + if (casc.sign() < 0) { + registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt(), casc.yXi()); + } else { + registry.fill(HIST("hMassXiPlus"), casc.mXi(), casc.pt(), casc.yXi()); + } + break; + case 2: // Xi or Omega + registry.fill(HIST("hSelectionStatus"), 8); // passes bach PID + if (casc.sign() < 0) { + registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt(), casc.yXi()); + registry.fill(HIST("hMassOmegaMinus"), casc.mOmega(), casc.pt(), casc.yOmega()); + } else { + registry.fill(HIST("hMassXiPlus"), casc.mXi(), casc.pt(), casc.yXi()); + registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt(), casc.yOmega()); + } + break; + case 3: // only Omega + registry.fill(HIST("hSelectionStatus"), 8); // passes bach PID + if (casc.sign() < 0) { + registry.fill(HIST("hMassOmegaMinus"), casc.mOmega(), casc.pt(), casc.yOmega()); + } else { + registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt(), casc.yOmega()); + } + break; + } + + return flag; + + } // processCandidate + + void processGenMC(aod::McCollision const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) + { + // evsel + if (INEL >= 0 && !pwglf::isINELgtNmc(mcParticles, INEL, pdgDB)) + return; + if (std::abs(mcCollision.posZ()) > maxVertexZ) + return; + + registry.fill(HIST("gen/hNevents"), 0); + + for (auto const& mcPart : mcParticles) { + if (!mcPart.isPhysicalPrimary()) + continue; + if (std::abs(mcPart.eta()) > etaCascades) + continue; + + switch (mcPart.pdgCode()) { + case 3312: + registry.fill(HIST("gen/hXiMinus"), mcPart.pt(), mcPart.y()); + break; + case -3312: + registry.fill(HIST("gen/hXiPlus"), mcPart.pt(), mcPart.y()); + break; + case 3334: + registry.fill(HIST("gen/hOmegaMinus"), mcPart.pt(), mcPart.y()); + break; + case -3334: + registry.fill(HIST("gen/hOmegaPlus"), mcPart.pt(), mcPart.y()); + break; + } + } + + // Do the same thing, but now making sure there is at least one matched reconstructed event: + if (collisions.size() < 1) { + return; + } else { + bool evSel = false; // will be true if at least one rec. collision passes evsel + for (auto const& collision : collisions) { + // can be more than 1 rec. collisions due to event splitting + evSel = eventSelection(collision, false); + if (evSel) // exit loop if we find 1 rec. event that passes evsel + break; + } + if (evSel) { + // N gen events with a reconstructed event + registry.fill(HIST("genwithrec/hNevents"), 0); + + for (auto const& mcPart : mcParticles) { + if (!mcPart.isPhysicalPrimary()) + continue; + if (std::abs(mcPart.eta()) > etaCascades) + continue; + + switch (mcPart.pdgCode()) { + case 3312: + registry.fill(HIST("genwithrec/hXiMinus"), mcPart.pt(), mcPart.y()); + break; + case -3312: + registry.fill(HIST("genwithrec/hXiPlus"), mcPart.pt(), mcPart.y()); + break; + case 3334: + registry.fill(HIST("genwithrec/hOmegaMinus"), mcPart.pt(), mcPart.y()); + break; + case -3334: + registry.fill(HIST("genwithrec/hOmegaPlus"), mcPart.pt(), mcPart.y()); + break; + } + } + } + } + } // processGen + + // wrappers for data/MC processes on reco level + void processRecData(MyCollisions::iterator const& collision, aod::CascDataExt const& Cascades, FullTracksExtIUWithPID const&, aod::BCsWithTimestamps const&) + { + bool evSel = eventSelection(collision, true); + // do not skip the collision if event selection fails - this will lead to the cascadeFlag table having less entries than the Cascade table, and therefor not joinable. + for (auto const& casc : Cascades) { + if (!evSel) { + cascflags(0); + continue; + } + int flag = processCandidate(casc, collision); + cascflags(flag); + } + } + + void processRecMC(MyCollisions::iterator const& collision, LabeledCascades const& Cascades, FullTracksExtIUWithPID const&, aod::BCsWithTimestamps const&, aod::McParticles const&) + { + bool evSel = eventSelection(collision, true); + // do not skip the collision if event selection fails - this will lead to the cascadeFlag table having less entries than the Cascade table, and therefor not joinable. + for (auto const& casc : Cascades) { + if (!evSel) { + cascflags(0); + continue; + } + int flag = processCandidate(casc, collision); + cascflags(flag); + // do mc matching here + fillMatchedHistos(casc, flag, collision); // if sign < 0 then pdg > 0 + } + } + + PROCESS_SWITCH(CascadeSelector, processRecData, "Process rec data", true); + PROCESS_SWITCH(CascadeSelector, processRecMC, "Process rec MC", false); + PROCESS_SWITCH(CascadeSelector, processGenMC, "Process gen MC", false); +}; // struct + +struct CascadeCorrelations { + Service ccdb; + + // Configurables + Configurable maxRapidity{"maxRapidity", 0.5, "|y| < maxRapidity"}; + 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{"ccdbUrl", "http://alice-ccdb.cern.ch", "CCDB url"}; + Configurable useTrigger{"useTrigger", false, "Use trigger selection on skimmed data"}; + Configurable triggerList{"triggerList", "fDoubleXi, fDoubleOmega, fOmegaXi", "List of triggers used to select events"}; + Configurable efficiencyCCDBPath{"efficiencyCCDBPath", "Users/r/rspijker/test/EffTest", "Path of the efficiency corrections"}; + Configurable doTFBorderCut{"doTFBorderCut", true, "Switch to apply TimeframeBorderCut event selection"}; + Configurable doSel8{"doSel8", true, "Switch to apply sel8 event selection"}; + + ConfigurableAxis radiusAxis = {"radiusAxis", {100, 0.0f, 50.0f}, "cm"}; + ConfigurableAxis cpaAxis = {"cpaAxis", {100, 0.95f, 1.0f}, "CPA"}; + ConfigurableAxis invMassAxis = {"invMassAxis", {1000, 1.0f, 2.0f}, "Inv. Mass (GeV/c^{2})"}; + ConfigurableAxis deltaPhiAxis = {"deltaPhiAxis", {180, -PIHalf, 3 * PIHalf}, "#Delta#varphi"}; // 180 is divisible by 18 (tpc sectors) and 20 (run 2 binning) + ConfigurableAxis ptAxis = {"ptAxis", {150, 0, 15}, "#it{p}_{T}"}; + ConfigurableAxis vertexAxis = {"vertexAxis", {200, -10.0f, 10.0f}, "cm"}; + ConfigurableAxis dcaAxis = {"dcaAxis", {100, 0.0f, 2.0f}, "cm"}; + ConfigurableAxis multiplicityAxis{"multiplicityAxis", {100, 0, 100}, "Multiplicity (centFT0M?)"}; + ConfigurableAxis invLambdaMassAxis{"invLambdaMassAxis", {100, 1.07f, 1.17f}, "Inv. Mass (GeV/c^{2})"}; + AxisSpec signAxis{3, -1.5, 1.5, "sign of cascade"}; + AxisSpec deltaYAxis{40, -2.f, 2.f, "#Delta y"}; + AxisSpec rapidityAxis{100, -1.f, 1.f, "y"}; + AxisSpec selectionFlagAxis{4, -0.5f, 3.5f, "Selection flag of casc candidate"}; + AxisSpec itsClustersAxis{8, -0.5, 7.5, "number of ITS clusters"}; + AxisSpec tpcRowsAxis{160, -0.5, 159.5, "TPC crossed rows"}; + + // initialize efficiency maps + TH1D* hEffXiMin; + TH1D* hEffXiPlus; + TH1D* hEffOmegaMin; + TH1D* hEffOmegaPlus; + + // used in MC closure test + Service pdgDB; + o2::pwglf::ParticleCounter mCounter; + + 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")); + } + + mCounter.mPdgDatabase = pdgDB.service; + mCounter.mSelectPrimaries = true; + } + + double getEfficiency(TH1* h, double pT, double y = 0) + { + // This function returns 1 / eff + double eff = h->GetBinContent(h->FindFixBin(pT, y)); + if (eff == 0) + return 0; + else + return 1. / eff; + } + + bool autoCorrelation(std::array triggerTracks, std::array assocTracks) + { + // function that loops over 2 arrays of track indices, checking for common elements + for (int triggerTrack : triggerTracks) { + for (int assocTrack : assocTracks) { + if (triggerTrack == assocTrack) + return true; + } + } + return false; + } + + HistogramRegistry registry{ + "registry", + { + // inv mass + {"hMassXiMinus", "hMassXiMinus", {HistType::kTH3F, {{200, 1.24, 1.44, "Inv. Mass (GeV/c^{2})"}, ptAxis, rapidityAxis}}}, + {"hMassXiPlus", "hMassXiPlus", {HistType::kTH3F, {{200, 1.24, 1.44, "Inv. Mass (GeV/c^{2})"}, ptAxis, rapidityAxis}}}, + {"hMassOmegaMinus", "hMassOmegaMinus", {HistType::kTH3F, {{200, 1.6, 1.8, "Inv. Mass (GeV/c^{2})"}, ptAxis, rapidityAxis}}}, + {"hMassOmegaPlus", "hMassOmegaPlus", {HistType::kTH3F, {{200, 1.6, 1.8, "Inv. Mass (GeV/c^{2})"}, ptAxis, rapidityAxis}}}, + // efficiency corrected inv mass + {"hMassXiEffCorrected", "hMassXiEffCorrected", {HistType::kTHnSparseF, {invMassAxis, signAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, + {"hMassOmegaEffCorrected", "hMassOmegaEffCorrected", {HistType::kTHnSparseF, {invMassAxis, signAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, + + // trigger QA + {"hTriggerQA", "hTriggerQA", {HistType::kTH1F, {{2, -0.5, 1.5, "Trigger y/n"}}}}, + + // basic selection variables (after cuts) + {"hV0Radius", "hV0Radius", {HistType::kTH1F, {radiusAxis}}}, + {"hCascRadius", "hCascRadius", {HistType::kTH1F, {radiusAxis}}}, + {"hV0CosPA", "hV0CosPA", {HistType::kTH1F, {cpaAxis}}}, + {"hCascCosPA", "hCascCosPA", {HistType::kTH1F, {cpaAxis}}}, + {"hDCAPosToPV", "hDCAPosToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCANegToPV", "hDCANegToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCABachToPV", "hDCABachToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCAV0ToPV", "hDCAV0ToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCAV0Dau", "hDCAV0Dau", {HistType::kTH1F, {dcaAxis}}}, + {"hDCACascDau", "hDCACascDau", {HistType::kTH1F, {dcaAxis}}}, + {"hLambdaMass", "hLambdaMass", {HistType::kTH1F, {invLambdaMassAxis}}}, + {"hTPCnCrossedRowsPos", "hTPCnCrossedRowsPos", {HistType::kTH1F, {tpcRowsAxis}}}, + {"hTPCnCrossedRowsNeg", "hTPCnCrossedRowsNeg", {HistType::kTH1F, {tpcRowsAxis}}}, + {"hTPCnCrossedRowsBach", "hTPCnCrossedRowsBach", {HistType::kTH1F, {tpcRowsAxis}}}, + {"hITSnClustersPos", "hITSnClustersPos", {HistType::kTH1F, {itsClustersAxis}}}, + {"hITSnClustersNeg", "hITSnClustersNeg", {HistType::kTH1F, {itsClustersAxis}}}, + {"hITSnClustersBach", "hITSnClustersBach", {HistType::kTH1F, {itsClustersAxis}}}, + + {"hSelectionFlag", "hSelectionFlag", {HistType::kTH1I, {selectionFlagAxis}}}, + {"hAutoCorrelation", "hAutoCorrelation", {HistType::kTH1I, {{4, -0.5f, 3.5f, "Types of SS autocorrelation"}}}}, + {"hAutoCorrelationOS", "hAutoCorrelationOS", {HistType::kTH1I, {{2, -1.f, 1.f, "Charge of OS autocorrelated track"}}}}, + {"hPhi", "hPhi", {HistType::kTH1F, {{180, 0, TwoPI, "#varphi"}}}}, + {"hEta", "hEta", {HistType::kTH1F, {{100, -2, 2, "#eta"}}}}, + {"hRapidityXi", "hRapidityXi", {HistType::kTH1F, {rapidityAxis}}}, + {"hRapidityOmega", "hRapidityOmega", {HistType::kTH1F, {rapidityAxis}}}, + + // correlation histos + {"hDeltaPhiSS", "hDeltaPhiSS", {HistType::kTH1F, {deltaPhiAxis}}}, + {"hDeltaPhiOS", "hDeltaPhiOS", {HistType::kTH1F, {deltaPhiAxis}}}, + + {"hXiXi", "hXiXi", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"hXiOm", "hXiOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"hOmOm", "hOmOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + + // 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/hMEQA", "hMEQA", {HistType::kTH1I, {{2, 0, 2, "QA for exceptions in ME (this histogram should have 0 entries!)"}}}}, + {"MixedEvents/hMEAutoCorrelation", "hMEAutoCorrelation", {HistType::kTH1I, {{4, -0.5f, 3.5f, "Types of SS autocorrelation"}}}}, + {"MixedEvents/hMEAutoCorrelationOS", "hMEAutoCorrelationOS", {HistType::kTH1I, {{2, -1.f, 1.f, "Charge of OS autocorrelated track"}}}}, + + {"MixedEvents/hMEXiXi", "hMEXiXi", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"MixedEvents/hMEXiOm", "hMEXiOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"MixedEvents/hMEOmOm", "hMEOmOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + + // MC closure + {"MC/hMCPlusMinus", "hMCPlusMinus", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, vertexAxis, multiplicityAxis}}, true}, + {"MC/hMCPlusPlus", "hMCPlusPlus", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, vertexAxis, multiplicityAxis}}, true}, + {"MC/hMCMinusPlus", "hMCMinusPlus", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, vertexAxis, multiplicityAxis}}, true}, + {"MC/hMCMinusMinus", "hMCMinusMinus", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, vertexAxis, multiplicityAxis}}, true}, + + {"MC/hGenMultNoReco", "hGenMultNoReco", {HistType::kTH1I, {{100, 0, 100, "Number of generated charged primaries"}}}}, + {"MC/hGenMultOneReco", "hGenMultOneReco", {HistType::kTH1I, {{100, 0, 100, "Number of generated charged primaries"}}}}, + {"MC/hSplitEvents", "hSplitEvents", {HistType::kTH1I, {{10, 0, 10, "Number of rec. events per gen event"}}}}, + + // debug + {"MC/hPhi", "hPhi", {HistType::kTH1F, {{180, 0, TwoPI}}}}, + {"MC/hEta", "hEta", {HistType::kTH1F, {{100, -2, 2}}}}, + {"MC/hRapidity", "hRapidity", {HistType::kTH1F, {{100, -2, 2}}}}, + }, + }; + + // cascade filter + Filter cascadeSelector = aod::cascadeflags::isSelected > 0; + + // Warning: it is not possible to use this axis as configurable due to a bug - however, default values are sensible. + SliceCache cache; + 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"}; + // ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100, 1000}, "Mixing bins - multiplicity"}; + // using BinningType = ColumnBinningPolicy; + // BinningType colBinning{{axisVtxZ, axisMult}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{axisVtxZ}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. + + void processSameEvent(MyCollisionsMult::iterator const& collision, MyCascades const& Cascades, FullTracksExtIU const&, aod::BCsWithTimestamps const&) + { + + double weight; + // Some QA on the cascades + for (auto const& casc : Cascades) { + if (casc.isSelected() <= 2) { // not exclusively an Omega --> consistent with Xi or both + if (casc.sign() < 0) { + registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt(), casc.yXi()); + weight = getEfficiency(hEffXiMin, casc.pt(), casc.yXi()); + } else { + registry.fill(HIST("hMassXiPlus"), casc.mXi(), casc.pt(), casc.yXi()); + weight = getEfficiency(hEffXiPlus, casc.pt(), casc.yXi()); + } + // LOGF(info, "casc pt %f, weight %f", casc.pt(), weight); + registry.fill(HIST("hMassXiEffCorrected"), casc.mXi(), casc.sign(), casc.pt(), casc.yXi(), collision.posZ(), collision.centFT0M(), weight); + registry.fill(HIST("hRapidityXi"), casc.yXi()); + } + if (casc.isSelected() >= 2) { // consistent with Omega or both + if (casc.sign() < 0) { + registry.fill(HIST("hMassOmegaMinus"), casc.mOmega(), casc.pt(), casc.yOmega()); + weight = getEfficiency(hEffOmegaMin, casc.pt(), casc.yOmega()); + } else { + registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt(), casc.yOmega()); + weight = getEfficiency(hEffOmegaPlus, casc.pt(), casc.yOmega()); + } + registry.fill(HIST("hMassOmegaEffCorrected"), casc.mOmega(), casc.sign(), casc.pt(), casc.yOmega(), collision.posZ(), collision.centFT0M(), weight); + registry.fill(HIST("hRapidityOmega"), casc.yOmega()); + } + registry.fill(HIST("hV0Radius"), casc.v0radius()); + registry.fill(HIST("hCascRadius"), casc.cascradius()); + registry.fill(HIST("hV0CosPA"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCAPosToPV"), casc.dcapostopv()); + registry.fill(HIST("hDCANegToPV"), casc.dcanegtopv()); + registry.fill(HIST("hDCABachToPV"), casc.dcabachtopv()); + registry.fill(HIST("hDCAV0ToPV"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCAV0Dau"), casc.dcaV0daughters()); + registry.fill(HIST("hDCACascDau"), casc.dcacascdaughters()); + registry.fill(HIST("hLambdaMass"), casc.mLambda()); + registry.fill(HIST("hITSnClustersPos"), casc.posTrack_as().itsNCls()); + registry.fill(HIST("hITSnClustersNeg"), casc.negTrack_as().itsNCls()); + registry.fill(HIST("hITSnClustersBach"), casc.bachelor_as().itsNCls()); + registry.fill(HIST("hTPCnCrossedRowsPos"), casc.posTrack_as().tpcNClsCrossedRows()); + registry.fill(HIST("hTPCnCrossedRowsNeg"), casc.negTrack_as().tpcNClsCrossedRows()); + registry.fill(HIST("hTPCnCrossedRowsBach"), casc.bachelor_as().tpcNClsCrossedRows()); + + registry.fill(HIST("hSelectionFlag"), casc.isSelected()); + registry.fill(HIST("hPhi"), casc.phi()); + registry.fill(HIST("hEta"), casc.eta()); + } // casc loop + + for (auto& [c0, c1] : combinations(Cascades, Cascades)) { // combinations automatically applies strictly upper in case of 2 identical tables + // Define the trigger as the particle with the highest pT. As we can't swap the cascade tables themselves, we swap the addresses and later dereference them + auto* triggerAddress = &c0; + auto* assocAddress = &c1; + if (assocAddress->pt() > triggerAddress->pt()) { + std::swap(triggerAddress, assocAddress); + } + auto trigger = *triggerAddress; + auto assoc = *assocAddress; + + // autocorrelation check + std::array triggerTracks = {trigger.posTrackId(), trigger.negTrackId(), trigger.bachelorId()}; + std::array assocTracks = {assoc.posTrackId(), assoc.negTrackId(), assoc.bachelorId()}; + if (autoCorrelation(triggerTracks, assocTracks)) + continue; + + // calculate angular correlations + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); + + double invMassXiTrigg = trigger.mXi(); + double invMassOmTrigg = trigger.mOmega(); + double invMassXiAssoc = assoc.mXi(); + double invMassOmAssoc = assoc.mOmega(); + + double weightTrigg = 1.; + double weightAssoc = 1.; + + if (trigger.isSelected() <= 2 && std::abs(trigger.yXi()) < maxRapidity) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && std::abs(assoc.yXi()) < maxRapidity) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("hXiXi"), dphi, trigger.yXi() - assoc.yXi(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.centFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hXiOm"), dphi, trigger.yXi() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.centFT0M(), weightTrigg * weightAssoc); + } + } + if (trigger.isSelected() >= 2 && std::abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && std::abs(assoc.yXi()) < maxRapidity) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + // if Omega-Xi, fill the Xi-Omega histogram (flip the trigger/assoc and dphy,dy signs) + registry.fill(HIST("hXiOm"), RecoDecay::constrainAngle(assoc.phi() - trigger.phi(), -PIHalf), -(trigger.yOmega() - assoc.yXi()), assoc.sign(), trigger.sign(), assoc.pt(), trigger.pt(), invMassXiAssoc, invMassOmTrigg, collision.posZ(), collision.centFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hOmOm"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.centFT0M(), weightTrigg * weightAssoc); + } + } + + // QA plots + if (trigger.sign() * assoc.sign() < 0) { + registry.fill(HIST("hDeltaPhiOS"), dphi); + } else { + registry.fill(HIST("hDeltaPhiSS"), dphi); + } + } // correlations + } // process same event + + void processMixedEvent(MyCollisionsMult const& collisions, MyCascades const& Cascades, FullTracksExtIU const&) + { + auto cascadesTuple = std::make_tuple(Cascades); + SameKindPair pair{colBinning, nMixedEvents, -1, collisions, cascadesTuple, &cache}; + + for (auto const& [col1, cascades1, col2, cascades2] : pair) { + if (!col1.sel8() || !col2.sel8()) + continue; + if (std::abs(col1.posZ()) > zVertexCut || std::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()); + + for (auto& [casc1, casc2] : combinations(CombinationsFullIndexPolicy(cascades1, cascades2))) { + // specify FullIndexPolicy since the cascades are from different collisions + auto* triggerAddress = &casc1; + auto* assocAddress = &casc2; + if (assocAddress->pt() > triggerAddress->pt()) { + std::swap(triggerAddress, assocAddress); + } + auto trigger = *triggerAddress; + auto assoc = *assocAddress; + + if (trigger.collisionId() == assoc.collisionId()) { + registry.fill(HIST("hMEQA"), 1.5); + continue; + } + + std::array triggerTracks = {trigger.posTrackId(), trigger.negTrackId(), trigger.bachelorId()}; + std::array assocTracks = {assoc.posTrackId(), assoc.negTrackId(), assoc.bachelorId()}; + if (autoCorrelation(triggerTracks, assocTracks)) + continue; + + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); + + double invMassXiTrigg = trigger.mXi(); + double invMassOmTrigg = trigger.mOmega(); + double invMassXiAssoc = assoc.mXi(); + double invMassOmAssoc = assoc.mOmega(); + + double weightTrigg = 1.; + double weightAssoc = 1.; + + if (trigger.isSelected() <= 2 && std::abs(trigger.yXi()) < maxRapidity) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && std::abs(assoc.yXi()) < maxRapidity) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiXi"), dphi, trigger.yXi() - assoc.yXi(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.centFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiOm"), dphi, trigger.yXi() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.centFT0M(), weightTrigg * weightAssoc); + } + } + if (trigger.isSelected() >= 2 && std::abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && std::abs(assoc.yXi()) < maxRapidity) { // assoc Xi + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + // if Omega-Xi, fill the Xi-Omega histogram (flip the trigger/assoc and dphy,dy signs) + registry.fill(HIST("MixedEvents/hMEXiOm"), RecoDecay::constrainAngle(assoc.phi() - trigger.phi(), -PIHalf), -(trigger.yOmega() - assoc.yXi()), assoc.sign(), trigger.sign(), assoc.pt(), trigger.pt(), invMassXiAssoc, invMassOmTrigg, col1.posZ(), col1.centFT0M(), weightTrigg * weightAssoc); + } + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega + if (doEfficiencyCorrection) + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEOmOm"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.centFT0M(), weightTrigg * weightAssoc); + } + } + + // QA plots + if (trigger.sign() * assoc.sign() < 0) { + registry.fill(HIST("MixedEvents/hMEDeltaPhiOS"), dphi); + } else { + registry.fill(HIST("MixedEvents/hMEDeltaPhiSS"), dphi); + } + } // correlations + } // collisions + } // process mixed events + + Configurable etaGenCascades{"etaGenCascades", 0.8, "min/max of eta for generated cascades"}; + Filter genCascadesFilter = nabs(aod::mcparticle::pdgCode) == 3312; + + void processMC(aod::McCollision const&, soa::SmallGroups> const& collisions, soa::Filtered const& genCascades, aod::McParticles const& mcParticles) + { + // Let's do some logic on matched reconstructed collisions - if there less or more than one, fill some QA and skip the rest + double FT0mult = -1; // non-sensible default value just in case + double vtxz = -999.; // non-sensible default value just in case + if (collisions.size() < 1) { + registry.fill(HIST("MC/hSplitEvents"), 0); + registry.fill(HIST("MC/hGenMultNoReco"), mCounter.countFT0A(mcParticles) + mCounter.countFT0C(mcParticles)); + return; + } else if (collisions.size() == 1) { + registry.fill(HIST("MC/hSplitEvents"), 1); + registry.fill(HIST("MC/hGenMultOneReco"), mCounter.countFT0A(mcParticles) + mCounter.countFT0C(mcParticles)); + for (auto const& collision : collisions) { // not really a loop, as there is only one collision + FT0mult = collision.centFT0M(); + vtxz = collision.posZ(); + } + } else if (collisions.size() > 1) { + registry.fill(HIST("MC/hSplitEvents"), collisions.size()); + return; + } + + // QA + for (auto& casc : genCascades) { + if (!casc.isPhysicalPrimary()) + continue; + registry.fill(HIST("MC/hPhi"), casc.phi()); + registry.fill(HIST("MC/hEta"), casc.eta()); + registry.fill(HIST("MC/hRapidity"), casc.y()); + } + + for (auto& [c0, c1] : combinations(genCascades, genCascades)) { // combinations automatically applies strictly upper in case of 2 identical tables + // Define the trigger as the particle with the highest pT. As we can't swap the cascade tables themselves, we swap the addresses and later dereference them + auto* triggerAddress = &c0; + auto* assocAddress = &c1; + if (assocAddress->pt() > triggerAddress->pt()) { + std::swap(triggerAddress, assocAddress); + } + auto trigger = *triggerAddress; + auto assoc = *assocAddress; + + if (!trigger.isPhysicalPrimary() || !assoc.isPhysicalPrimary()) + continue; // require the cascades to be primaries + if (std::abs(trigger.eta()) > etaGenCascades) + continue; // only apply eta cut to trigger - trigger normalization still valid without introducing 2-particle-acceptance effects + + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); + + if (trigger.pdgCode() < 0) { // anti-trigg --> Plus + if (assoc.pdgCode() < 0) { // anti-assoc --> Plus + registry.fill(HIST("MC/hMCPlusPlus"), dphi, trigger.y() - assoc.y(), trigger.pt(), assoc.pt(), vtxz, FT0mult); + } else { // assoc --> Minus + registry.fill(HIST("MC/hMCPlusMinus"), dphi, trigger.y() - assoc.y(), trigger.pt(), assoc.pt(), vtxz, FT0mult); + } + } else { // trig --> Minus + if (assoc.pdgCode() < 0) { // anti-assoc --> Plus + registry.fill(HIST("MC/hMCMinusPlus"), dphi, trigger.y() - assoc.y(), trigger.pt(), assoc.pt(), vtxz, FT0mult); + } else { + registry.fill(HIST("MC/hMCMinusMinus"), dphi, trigger.y() - assoc.y(), trigger.pt(), assoc.pt(), vtxz, FT0mult); + } + } + } + } + + PROCESS_SWITCH(CascadeCorrelations, processSameEvent, "Process same events", true); + PROCESS_SWITCH(CascadeCorrelations, processMixedEvent, "Process mixed events", true); + PROCESS_SWITCH(CascadeCorrelations, processMC, "Process MC", false); + +}; // struct + +// Branch data structs for TTree filling — plain POD, no O2 framework types. +// Stored via a single raw pointer (1 StructToTuple slot) from the task struct. +namespace lxicorr +{ +struct CascBranches { + float pt, rap, mass; + int sign; + float cascCosPA, v0CosPA; + float cascRadius, v0Radius; + float dcaV0Dau, dcaCascDau; + float dcaV0ToPV, dcaPosToPV, dcaNegToPV, dcaBachToPV; + float cent, pvZ; + // MC truth-matching (filled only in MC mode; default = no match) + int pdgCode{0}; // PDG of matched McParticle (0 = no match = background) + bool isPhysPrim{false}; +}; + +// Holds branch data for both Xi and Omega — one raw pointer covers both. +// Gen-level branches — kinematics + truth only, no topology +struct GenBranches { + float pt, rap, cent, pvZ; + int pdgCode; + bool isPhysPrim; +}; + +// Single pointer covers all four branch sets — 1 StructToTuple slot +struct BranchPair { + CascBranches xi{}; + CascBranches om{}; + GenBranches xiGen{}; + GenBranches omGen{}; +}; + +inline void connectBranches(TTree* t, CascBranches* b) +{ + t->Branch("pt", &b->pt); + t->Branch("rap", &b->rap); + t->Branch("mass", &b->mass); + t->Branch("sign", &b->sign); + t->Branch("cascCosPA", &b->cascCosPA); + t->Branch("v0CosPA", &b->v0CosPA); + t->Branch("cascRadius", &b->cascRadius); + t->Branch("v0Radius", &b->v0Radius); + t->Branch("dcaV0Dau", &b->dcaV0Dau); + t->Branch("dcaCascDau", &b->dcaCascDau); + t->Branch("dcaV0ToPV", &b->dcaV0ToPV); + t->Branch("dcaPosToPV", &b->dcaPosToPV); + t->Branch("dcaNegToPV", &b->dcaNegToPV); + t->Branch("dcaBachToPV", &b->dcaBachToPV); + t->Branch("cent", &b->cent); + t->Branch("pvZ", &b->pvZ); + t->Branch("pdgCode", &b->pdgCode); + t->Branch("isPhysPrim", &b->isPhysPrim); +} + +inline void connectGenBranches(TTree* t, GenBranches* b) +{ + t->Branch("pt", &b->pt); + t->Branch("rap", &b->rap); + t->Branch("pdgCode", &b->pdgCode); + t->Branch("isPhysPrim", &b->isPhysPrim); + t->Branch("cent", &b->cent); + t->Branch("pvZ", &b->pvZ); +} +} // namespace lxicorr + +struct LambdaXiCorrelation { + + // --- Configurables --- + Configurable maxY{"maxY", 0.5, "Max |y| for Lambda, Xi and Omega"}; + Configurable useEff{"useEff", false, "Apply Lambda efficiency correction"}; + // Omega bachelor kaon PID cut (kept separate from Xi pion cut for physics correctness) + Configurable tpcNsigmaBachKaon{"tpcNsigmaBachKaon", 3.0f, "TPC NSigma bachelor kaon (Omega selection)"}; + // FT0M centrality bins — same variable-width defaults as LambdaR2Correlation + ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0.0f, 10.0f, 30.0f, 50.0f, 80.0f, 100.0f}, "FT0M centrality (%)"}; + Configurable saveCascTree{"saveCascTree", false, "Save TTree of cascade topological variables into AnalysisResults.root"}; + + // --- Outputs --- + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // Direct OutputObj members → framework registers and writes these into + // AnalysisResults.root under the "CascadeTrees" folder automatically. + // setObject() is called in init() when saveCascTree is true. + OutputObj treeXi{"XiCandidates", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj treeOmega{"OmegaCandidates", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj treeXiGen{"XiCandidatesGen", OutputObjHandlingPolicy::AnalysisObject}; + OutputObj treeOmegaGen{"OmegaCandidatesGen", OutputObjHandlingPolicy::AnalysisObject}; + // Single raw pointer covers all four branch sets — 1 StructToTuple slot + lxicorr::BranchPair* bp{nullptr}; + + // --- Data Slicing Definitions --- + using GoodLambdas = soa::Join; + Partition goodLambda = aod::lambdatrackext::trueLambdaFlag == true; + + Preslice lambdasPerCollision = aod::lambdatrack::lambdaCollisionId; + Preslice cascadesPerCollision = aod::cascdata::collisionId; + Preslice labeledCascPerCollision = aod::cascdata::collisionId; + // Gen-level lambda slicing: use HashBy (unsorted-safe) via o2::framework::expressions + // Simple approach: iterate all and match by collision index inline (no cache needed) + + using LambdaCollisionsExt = aod::LambdaCollisions; + + // Gen Xi/Omega: PDG filtering is done inline inside each process function. + // (Two Filter declarations on the same table within one struct are AND-ed, + // so |pdg|==3312 AND |pdg|==3334 would always be false.) + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + + // --- R2 Calculation Helper --- + // R2 = (N_events * Pair_Yield) / (Single_Yield_1 * Single_Yield_2) - 1 + static TH2* calculateR2(TH2* hPairs, TH1* hSinglesTrig, TH1* hSinglesAssoc, double nEvents) + { + if (!hPairs || !hSinglesTrig || !hSinglesAssoc || nEvents <= 0) + return nullptr; + + TH2* hR2 = reinterpret_cast(hPairs->Clone(Form("%s_R2", hPairs->GetName()))); + hR2->Reset(); + + double nS1 = hSinglesTrig->Integral(); + double nS2 = hSinglesAssoc->Integral(); + + if (nS1 > 0 && nS2 > 0) { + hR2->Add(hPairs); + hR2->Scale(nEvents / (nS1 * nS2)); + + for (int i = 1; i <= hR2->GetNbinsX(); i++) { + for (int j = 1; j <= hR2->GetNbinsY(); j++) { + double content = hR2->GetBinContent(i, j); + hR2->SetBinContent(i, j, content - 1.0); + } + } + } + return hR2; + } + + void init(InitContext const&) + { + // --- 1. Axis Definitions --- + const AxisSpec dphi{72, -PIHalf, 3 * PIHalf, "#Delta#varphi"}; + const AxisSpec dy{40, -2.0f, 2.0f, "#Delta y"}; + const AxisSpec cent{centAxis, "FT0M (%)"}; + const AxisSpec pt{100, 0, 10, "p_{T} (GeV/c)"}; + const AxisSpec rap{100, -1.0, 1.0, "y"}; + const AxisSpec massLam{100, 1.09, 1.14, "M_{p#pi} (GeV/c^{2})"}; + const AxisSpec massXi{100, 1.28, 1.36, "M_{#Lambda#pi} (GeV/c^{2})"}; + const AxisSpec massOm{100, 1.62, 1.72, "M_{#LambdaK} (GeV/c^{2})"}; + const AxisSpec radius{100, 0, 100, "Radius (cm)"}; + const AxisSpec cpa{100, 0.9, 1.0, "Cos(PA)"}; + const AxisSpec dca{100, 0.0, 5.0, "DCA (cm)"}; + const AxisSpec pvDca{100, -10.0, 10.0, "DCA to PV (cm)"}; + // Fixed AxisSpec (not ConfigurableAxis) so bin edges cannot be misconfigured at runtime + const AxisSpec tpcRows{160, -0.5, 159.5, "TPC crossed rows"}; + + // --- 2. Histograms --- + histos.add("Event/hEventCount", "Event Counter", kTH1F, {{1, 0, 1, "Count"}}); + + // Singles: Lambda + histos.add("Singles/Lambda/hPt", "Lambda p_{T}", kTH1F, {pt}); + histos.add("Singles/AntiLambda/hPt", "AntiLambda p_{T}", kTH1F, {pt}); + + histos.add("Singles/Lambda/hPtVsMass", "Lambda p_{T} vs Mass", kTH2F, {massLam, pt}); + histos.add("Singles/AntiLambda/hPtVsMass", "AntiLambda p_{T} vs Mass", kTH2F, {massLam, pt}); + + // Singles: Xi & QA + histos.add("QA/Xi/hRadius", "Xi Radius", kTH1F, {radius}); + histos.add("QA/Xi/hCosPA", "Xi CosPA", kTH1F, {cpa}); + histos.add("QA/Xi/hDCAV0Dau", "DCA V0 Daughters", kTH1F, {dca}); + histos.add("QA/Xi/hDCACascDau", "DCA Casc Daughters", kTH1F, {dca}); + histos.add("QA/Xi/hDCAV0ToPV", "DCA V0 to PV", kTH1F, {pvDca}); + histos.add("QA/Xi/hDCAPosToPV", "DCA Pos to PV", kTH1F, {pvDca}); + histos.add("QA/Xi/hDCANegToPV", "DCA Neg to PV", kTH1F, {pvDca}); + histos.add("QA/Xi/hDCABachToPV", "DCA Bach to PV", kTH1F, {pvDca}); + + // Cascade track QA — TPC crossed rows per daughter (fixed AxisSpec, immune to config override) + histos.add("QA/Casc/hTPCRowsPos", "TPC crossed rows (pos)", kTH1F, {tpcRows}); + histos.add("QA/Casc/hTPCRowsNeg", "TPC crossed rows (neg)", kTH1F, {tpcRows}); + histos.add("QA/Casc/hTPCRowsBach", "TPC crossed rows (bach)", kTH1F, {tpcRows}); + + histos.add("Singles/XiMinus/hPtVsMass", "Xi^{-} p_{T} vs Mass", kTH2F, {massXi, pt}); + histos.add("Singles/XiPlus/hPtVsMass", "Xi^{+} p_{T} vs Mass", kTH2F, {massXi, pt}); + histos.add("Singles/XiMinus/hRap", "Xi^{-} Rapidity", kTH1F, {rap}); + histos.add("Singles/XiPlus/hRap", "Xi^{+} Rapidity", kTH1F, {rap}); + + // --- Omega QA --- + histos.add("QA/Om/hRadius", "Omega Radius", kTH1F, {radius}); + histos.add("QA/Om/hCosPA", "Omega CosPA", kTH1F, {cpa}); + histos.add("QA/Om/hDCAV0Dau", "DCA V0 Daughters", kTH1F, {dca}); + histos.add("QA/Om/hDCACascDau", "DCA Casc Daughters", kTH1F, {dca}); + histos.add("QA/Om/hDCAV0ToPV", "DCA V0 to PV", kTH1F, {pvDca}); + histos.add("QA/Om/hDCAPosToPV", "DCA Pos to PV", kTH1F, {pvDca}); + histos.add("QA/Om/hDCANegToPV", "DCA Neg to PV", kTH1F, {pvDca}); + histos.add("QA/Om/hDCABachToPV", "DCA Bach to PV", kTH1F, {pvDca}); + + // Singles: Omega + histos.add("Singles/OmegaMinus/hPtVsMass", "Omega^{-} p_{T} vs Mass", kTH2F, {massOm, pt}); + histos.add("Singles/OmegaPlus/hPtVsMass", "Omega^{+} p_{T} vs Mass", kTH2F, {massOm, pt}); + histos.add("Singles/OmegaMinus/hRap", "Omega^{-} Rapidity", kTH1F, {rap}); + histos.add("Singles/OmegaPlus/hRap", "Omega^{+} Rapidity", kTH1F, {rap}); + + // Pairs: Xi (R2 inputs) + histos.add("Pairs/Lam_XiM/hDeltaPhiDeltaY", "L-Xi-", kTH3F, {cent, dphi, dy}); + histos.add("Pairs/Lam_XiP/hDeltaPhiDeltaY", "L-Xi+", kTH3F, {cent, dphi, dy}); + histos.add("Pairs/AntiLam_XiM/hDeltaPhiDeltaY", "AL-Xi-", kTH3F, {cent, dphi, dy}); + histos.add("Pairs/AntiLam_XiP/hDeltaPhiDeltaY", "AL-Xi+", kTH3F, {cent, dphi, dy}); + + // Pairs: Omega (R2 inputs) + histos.add("Pairs/Lam_OmM/hDeltaPhiDeltaY", "L-Om-", kTH3F, {cent, dphi, dy}); + histos.add("Pairs/Lam_OmP/hDeltaPhiDeltaY", "L-Om+", kTH3F, {cent, dphi, dy}); + histos.add("Pairs/AntiLam_OmM/hDeltaPhiDeltaY", "AL-Om-", kTH3F, {cent, dphi, dy}); + histos.add("Pairs/AntiLam_OmP/hDeltaPhiDeltaY", "AL-Om+", kTH3F, {cent, dphi, dy}); + + // --- MC Gen-level histograms (mirror reco under McGen/) --- + // Singles: gen Lambda + histos.add("McGen/Singles/Lambda/hPt", "Gen #Lambda p_{T}", kTH1F, {pt}); + histos.add("McGen/Singles/AntiLambda/hPt", "Gen #bar{#Lambda} p_{T}", kTH1F, {pt}); + + // Singles: gen Xi + histos.add("McGen/Singles/XiMinus/hPtVsRap", "Gen #Xi^{-} p_{T} vs y", kTH2F, {rap, pt}); + histos.add("McGen/Singles/XiPlus/hPtVsRap", "Gen #Xi^{+} p_{T} vs y", kTH2F, {rap, pt}); + + // Singles: gen Omega + histos.add("McGen/Singles/OmegaMinus/hPtVsRap", "Gen #Omega^{-} p_{T} vs y", kTH2F, {rap, pt}); + histos.add("McGen/Singles/OmegaPlus/hPtVsRap", "Gen #Omega^{+} p_{T} vs y", kTH2F, {rap, pt}); + + // Pairs: gen Lam-Xi + histos.add("McGen/Pairs/Lam_XiM/hDeltaPhiDeltaY", "Gen L-Xi-", kTH3F, {cent, dphi, dy}); + histos.add("McGen/Pairs/Lam_XiP/hDeltaPhiDeltaY", "Gen L-Xi+", kTH3F, {cent, dphi, dy}); + histos.add("McGen/Pairs/AntiLam_XiM/hDeltaPhiDeltaY", "Gen AL-Xi-", kTH3F, {cent, dphi, dy}); + histos.add("McGen/Pairs/AntiLam_XiP/hDeltaPhiDeltaY", "Gen AL-Xi+", kTH3F, {cent, dphi, dy}); + + // Pairs: gen Lam-Omega + histos.add("McGen/Pairs/Lam_OmM/hDeltaPhiDeltaY", "Gen L-Om-", kTH3F, {cent, dphi, dy}); + histos.add("McGen/Pairs/Lam_OmP/hDeltaPhiDeltaY", "Gen L-Om+", kTH3F, {cent, dphi, dy}); + histos.add("McGen/Pairs/AntiLam_OmM/hDeltaPhiDeltaY", "Gen AL-Om-", kTH3F, {cent, dphi, dy}); + histos.add("McGen/Pairs/AntiLam_OmP/hDeltaPhiDeltaY", "Gen AL-Om+", kTH3F, {cent, dphi, dy}); + + // --- 3. Efficiency map production histograms --- + // Axis definitions for efficiency maps (coarser binning to avoid empty bins) + const AxisSpec effCent{cent}; + const AxisSpec effPt{50, 0, 10, "p_{T} (GeV/c)"}; + const AxisSpec effRap{20, -1.0, 1.0, "y"}; + + // Generator-level denominator: all physical-primary Xi/Omega in acceptance + histos.add("Eff/Gen/XiMinus/hCentPtRap", "Gen #Xi^{-}", kTH3F, {effCent, effPt, effRap}); + histos.add("Eff/Gen/XiPlus/hCentPtRap", "Gen #Xi^{+}", kTH3F, {effCent, effPt, effRap}); + histos.add("Eff/Gen/OmegaMinus/hCentPtRap", "Gen #Omega^{-}", kTH3F, {effCent, effPt, effRap}); + histos.add("Eff/Gen/OmegaPlus/hCentPtRap", "Gen #Omega^{+}", kTH3F, {effCent, effPt, effRap}); + // Reco-level numerator: truth-matched reco Xi/Omega (physical-primary) + histos.add("Eff/Reco/XiMinus/hCentPtRap", "Reco #Xi^{-}", kTH3F, {effCent, effPt, effRap}); + histos.add("Eff/Reco/XiPlus/hCentPtRap", "Reco #Xi^{+}", kTH3F, {effCent, effPt, effRap}); + histos.add("Eff/Reco/OmegaMinus/hCentPtRap", "Reco #Omega^{-}", kTH3F, {effCent, effPt, effRap}); + histos.add("Eff/Reco/OmegaPlus/hCentPtRap", "Reco #Omega^{+}", kTH3F, {effCent, effPt, effRap}); + + // TTree setup — only allocates when saveCascTree is enabled. + // OutputObj are direct task members, so the framework automatically + // writes them into AnalysisResults.root under their own folder. + if (saveCascTree) { + bp = new lxicorr::BranchPair{}; + treeXi.setObject(new TTree("XiCandidates", "Xi topological variables")); + treeOmega.setObject(new TTree("OmegaCandidates", "Omega topological variables")); + lxicorr::connectBranches(treeXi.object.get(), &bp->xi); + lxicorr::connectBranches(treeOmega.object.get(), &bp->om); + treeXiGen.setObject(new TTree("XiCandidatesGen", "Xi gen-level kinematics")); + treeOmegaGen.setObject(new TTree("OmegaCandidatesGen", "Omega gen-level kinematics")); + lxicorr::connectGenBranches(treeXiGen.object.get(), &bp->xiGen); + lxicorr::connectGenBranches(treeOmegaGen.object.get(), &bp->omGen); + } + } + + // --- Analysis Functions --- + + template + void analyzeSinglesLambda(T const& tracks) + { + for (const auto& track : tracks) { + if (std::abs(track.rap()) > maxY) + continue; + + float w = useEff ? track.corrFact() : 1.0f; + bool isAnti = (track.v0Type() == 1); + + if (!isAnti) { + histos.fill(HIST("Singles/Lambda/hPt"), track.pt(), w); + histos.fill(HIST("Singles/Lambda/hPtVsMass"), track.mass(), track.pt(), w); + } else { + histos.fill(HIST("Singles/AntiLambda/hPt"), track.pt(), w); + histos.fill(HIST("Singles/AntiLambda/hPtVsMass"), track.mass(), track.pt(), w); + } + } + } + + template + void analyzeSinglesXi(T const& cascades, F const& flagsStart, float pvX, float pvY, float pvZ, float centVal) + { + for (const auto& casc : cascades) { + if ((flagsStart + casc.globalIndex()).isSelected() == 0) + continue; + + float xiY = RecoDecay::y(std::array{casc.px(), casc.py(), casc.pz()}, MassXi0); + if (std::abs(xiY) > maxY) + continue; + + // QA Filling + histos.fill(HIST("QA/Xi/hRadius"), casc.cascradius()); + histos.fill(HIST("QA/Xi/hCosPA"), casc.casccosPA(pvX, pvY, pvZ)); + histos.fill(HIST("QA/Xi/hDCAV0Dau"), casc.dcaV0daughters()); + histos.fill(HIST("QA/Xi/hDCACascDau"), casc.dcacascdaughters()); + histos.fill(HIST("QA/Xi/hDCAV0ToPV"), casc.dcav0topv(pvX, pvY, pvZ)); + histos.fill(HIST("QA/Xi/hDCAPosToPV"), casc.dcapostopv()); + histos.fill(HIST("QA/Xi/hDCANegToPV"), casc.dcanegtopv()); + histos.fill(HIST("QA/Xi/hDCABachToPV"), casc.dcabachtopv()); + + if (casc.sign() < 0) { + histos.fill(HIST("Singles/XiMinus/hPtVsMass"), casc.mXi(), casc.pt()); + histos.fill(HIST("Singles/XiMinus/hRap"), xiY); + } else { + histos.fill(HIST("Singles/XiPlus/hPtVsMass"), casc.mXi(), casc.pt()); + histos.fill(HIST("Singles/XiPlus/hRap"), xiY); + } + + // MC: fill efficiency numerator for truth-matched primary Xi + if constexpr (IsMC) { + if (casc.has_mcParticle()) { + auto mcpart = casc.mcParticle(); + if (std::abs(mcpart.pdgCode()) == 3312 && mcpart.isPhysicalPrimary()) { + if (mcpart.pdgCode() == 3312) + histos.fill(HIST("Eff/Reco/XiMinus/hCentPtRap"), centVal, casc.pt(), xiY); + else + histos.fill(HIST("Eff/Reco/XiPlus/hCentPtRap"), centVal, casc.pt(), xiY); + } + } + } + + if (bp) { + auto& b = bp->xi; + b.pt = casc.pt(); + b.rap = xiY; + b.mass = casc.mXi(); + b.sign = casc.sign(); + b.cascCosPA = casc.casccosPA(pvX, pvY, pvZ); + b.v0CosPA = casc.v0cosPA(pvX, pvY, pvZ); + b.cascRadius = casc.cascradius(); + b.v0Radius = casc.v0radius(); + b.dcaV0Dau = casc.dcaV0daughters(); + b.dcaCascDau = casc.dcacascdaughters(); + b.dcaV0ToPV = casc.dcav0topv(pvX, pvY, pvZ); + b.dcaPosToPV = casc.dcapostopv(); + b.dcaNegToPV = casc.dcanegtopv(); + b.dcaBachToPV = casc.dcabachtopv(); + b.cent = centVal; + b.pvZ = pvZ; + // MC truth matching + if constexpr (IsMC) { + if (casc.has_mcParticle()) { + auto mcpart = casc.mcParticle(); + b.pdgCode = mcpart.pdgCode(); + b.isPhysPrim = mcpart.isPhysicalPrimary(); + } else { + b.pdgCode = 0; + b.isPhysPrim = false; + } + } else { + b.pdgCode = 0; + b.isPhysPrim = false; + } + treeXi->Fill(); + } + } + } + + // Omega singles: kaon bachelor PID cut distinguishes Omega from Xi + template + void analyzeSinglesOmega(T const& cascades, F const& flagsStart, float pvX, float pvY, float pvZ, float centVal) + { + for (const auto& casc : cascades) { + if ((flagsStart + casc.globalIndex()).isSelected() == 0) + continue; + + float omY = RecoDecay::y(std::array{casc.px(), casc.py(), casc.pz()}, MassOmegaMinus); + if (std::abs(omY) > maxY) + continue; + + // Require kaon bachelor PID — NSigma lives on the track, not the cascade row + auto bachTrack = casc.template bachelor_as(); + if (std::abs(bachTrack.tpcNSigmaKa()) > tpcNsigmaBachKaon) + continue; + + // QA Filling (mirrors Xi QA under QA/Om/) + histos.fill(HIST("QA/Om/hRadius"), casc.cascradius()); + histos.fill(HIST("QA/Om/hCosPA"), casc.casccosPA(pvX, pvY, pvZ)); + histos.fill(HIST("QA/Om/hDCAV0Dau"), casc.dcaV0daughters()); + histos.fill(HIST("QA/Om/hDCACascDau"), casc.dcacascdaughters()); + histos.fill(HIST("QA/Om/hDCAV0ToPV"), casc.dcav0topv(pvX, pvY, pvZ)); + histos.fill(HIST("QA/Om/hDCAPosToPV"), casc.dcapostopv()); + histos.fill(HIST("QA/Om/hDCANegToPV"), casc.dcanegtopv()); + histos.fill(HIST("QA/Om/hDCABachToPV"), casc.dcabachtopv()); + + if (casc.sign() < 0) { + histos.fill(HIST("Singles/OmegaMinus/hPtVsMass"), casc.mOmega(), casc.pt()); + histos.fill(HIST("Singles/OmegaMinus/hRap"), omY); + } else { + histos.fill(HIST("Singles/OmegaPlus/hPtVsMass"), casc.mOmega(), casc.pt()); + histos.fill(HIST("Singles/OmegaPlus/hRap"), omY); + } + + // MC: fill efficiency numerator for truth-matched primary Omega + if constexpr (IsMC) { + if (casc.has_mcParticle()) { + auto mcpart = casc.mcParticle(); + if (std::abs(mcpart.pdgCode()) == 3334 && mcpart.isPhysicalPrimary()) { + if (mcpart.pdgCode() == 3334) + histos.fill(HIST("Eff/Reco/OmegaMinus/hCentPtRap"), centVal, casc.pt(), omY); + else + histos.fill(HIST("Eff/Reco/OmegaPlus/hCentPtRap"), centVal, casc.pt(), omY); + } + } + } + + if (bp) { + auto& b = bp->om; + b.pt = casc.pt(); + b.rap = omY; + b.mass = casc.mOmega(); + b.sign = casc.sign(); + b.cascCosPA = casc.casccosPA(pvX, pvY, pvZ); + b.v0CosPA = casc.v0cosPA(pvX, pvY, pvZ); + b.cascRadius = casc.cascradius(); + b.v0Radius = casc.v0radius(); + b.dcaV0Dau = casc.dcaV0daughters(); + b.dcaCascDau = casc.dcacascdaughters(); + b.dcaV0ToPV = casc.dcav0topv(pvX, pvY, pvZ); + b.dcaPosToPV = casc.dcapostopv(); + b.dcaNegToPV = casc.dcanegtopv(); + b.dcaBachToPV = casc.dcabachtopv(); + b.cent = centVal; + b.pvZ = pvZ; + // MC truth matching + if constexpr (IsMC) { + if (casc.has_mcParticle()) { + auto mcpart = casc.mcParticle(); + b.pdgCode = mcpart.pdgCode(); + b.isPhysPrim = mcpart.isPhysicalPrimary(); + } else { + b.pdgCode = 0; + b.isPhysPrim = false; + } + } else { + b.pdgCode = 0; + b.isPhysPrim = false; + } + treeOmega->Fill(); + } + } + } + + template + void analyzePairs(L const& lambdas, C const& cascades, F const& flagsStart, float centVal) + { + for (const auto& lam : lambdas) { + if (std::abs(lam.rap()) > maxY) + continue; + float wLam = useEff ? lam.corrFact() : 1.0f; + bool isAntiLam = (lam.v0Type() == 1); + + for (const auto& casc : cascades) { + if ((flagsStart + casc.globalIndex()).isSelected() == 0) + continue; + + float xiY = RecoDecay::y(std::array{casc.px(), casc.py(), casc.pz()}, MassXi0); + if (std::abs(xiY) > maxY) + continue; + + float dphi = RecoDecay::constrainAngle(casc.phi() - lam.phi(), -PIHalf); + float dy = xiY - lam.rap(); + + bool isXiPlus = (casc.sign() > 0); + + if (!isAntiLam && !isXiPlus) + histos.fill(HIST("Pairs/Lam_XiM/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + else if (!isAntiLam && isXiPlus) + histos.fill(HIST("Pairs/Lam_XiP/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + else if (isAntiLam && !isXiPlus) + histos.fill(HIST("Pairs/AntiLam_XiM/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + else if (isAntiLam && isXiPlus) + histos.fill(HIST("Pairs/AntiLam_XiP/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + } + } + } + + // Omega pair loop: same structure as Xi pairs but uses Omega mass for rapidity + kaon PID + template + void analyzeOmegaPairs(L const& lambdas, C const& cascades, F const& flagsStart, float centVal) + { + for (const auto& lam : lambdas) { + if (std::abs(lam.rap()) > maxY) + continue; + float wLam = useEff ? lam.corrFact() : 1.0f; + bool isAntiLam = (lam.v0Type() == 1); + + for (const auto& casc : cascades) { + if ((flagsStart + casc.globalIndex()).isSelected() == 0) + continue; + + auto bachTrack = casc.template bachelor_as(); + if (std::abs(bachTrack.tpcNSigmaKa()) > tpcNsigmaBachKaon) + continue; + + float omY = RecoDecay::y(std::array{casc.px(), casc.py(), casc.pz()}, MassOmegaMinus); + if (std::abs(omY) > maxY) + continue; + + float dphi = RecoDecay::constrainAngle(casc.phi() - lam.phi(), -PIHalf); + float dy = omY - lam.rap(); + + bool isOmPlus = (casc.sign() > 0); + + if (!isAntiLam && !isOmPlus) + histos.fill(HIST("Pairs/Lam_OmM/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + else if (!isAntiLam && isOmPlus) + histos.fill(HIST("Pairs/Lam_OmP/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + else if (isAntiLam && !isOmPlus) + histos.fill(HIST("Pairs/AntiLam_OmM/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + else if (isAntiLam && isOmPlus) + histos.fill(HIST("Pairs/AntiLam_OmP/hDeltaPhiDeltaY"), centVal, dphi, dy, wLam); + } + } + } + + void processXi(LambdaCollisionsExt::iterator const& lambdacoll, + GoodLambdas const& /*lambdas*/, + aod::CascDataExt const& cascades, + aod::CascadeFlags const& cascflags) + { + histos.fill(HIST("Event/hEventCount"), 0.5); + + auto lambdasInThisEvent = goodLambda->sliceBy(lambdasPerCollision, lambdacoll.globalIndex()); + const int64_t refCollisionIndex = lambdacoll.refCollId(); + auto cascadesInThisEvent = cascades.sliceBy(cascadesPerCollision, refCollisionIndex); + + float pvX = lambdacoll.posX(); + float pvY = lambdacoll.posY(); + float pvZ = lambdacoll.posZ(); + + auto flagsStart = cascflags.begin(); + + analyzeSinglesLambda(lambdasInThisEvent); + float centVal = lambdacoll.cent(); + analyzeSinglesXi(cascadesInThisEvent, flagsStart, pvX, pvY, pvZ, centVal); + analyzePairs(lambdasInThisEvent, cascadesInThisEvent, flagsStart, centVal); + } + PROCESS_SWITCH(LambdaXiCorrelation, processXi, "Λ–Ξ correlation", true); + + void processOmega(LambdaCollisionsExt::iterator const& lambdacoll, + GoodLambdas const& /*lambdas*/, + aod::CascDataExt const& cascades, + aod::CascadeFlags const& cascflags, + FullTracksExtIUWithPID const& /*tracks*/) + { + histos.fill(HIST("Event/hEventCount"), 0.5); + + auto lambdasInThisEvent = goodLambda->sliceBy(lambdasPerCollision, lambdacoll.globalIndex()); + const int64_t refCollisionIndex = lambdacoll.refCollId(); + auto cascadesInThisEvent = cascades.sliceBy(cascadesPerCollision, refCollisionIndex); + + float pvX = lambdacoll.posX(); + float pvY = lambdacoll.posY(); + float pvZ = lambdacoll.posZ(); + + auto flagsStart = cascflags.begin(); + + analyzeSinglesLambda(lambdasInThisEvent); + float centVal = lambdacoll.cent(); + analyzeSinglesOmega(cascadesInThisEvent, flagsStart, pvX, pvY, pvZ, centVal); + analyzeOmegaPairs(lambdasInThisEvent, cascadesInThisEvent, flagsStart, centVal); + } + PROCESS_SWITCH(LambdaXiCorrelation, processOmega, "Λ–Ω correlation", false); + + // --------------------------------------------------------------------------- + // MC Reco-level with truth matching: Λ–Ξ + // Same as processXi but cascades carry McCascLabels → tree gets pdgCode/isPhysPrim. + // --------------------------------------------------------------------------- + void processMCRecoXi(LambdaCollisionsExt::iterator const& lambdacoll, + GoodLambdas const& /*lambdas*/, + LabeledCascades const& cascades, + aod::CascadeFlags const& cascflags, + aod::McParticles const& /*mcparts*/) + { + histos.fill(HIST("Event/hEventCount"), 0.5); + + auto lambdasInThisEvent = goodLambda->sliceBy(lambdasPerCollision, lambdacoll.globalIndex()); + const int64_t refCollisionIndex = lambdacoll.refCollId(); + auto cascadesInThisEvent = cascades.sliceBy(labeledCascPerCollision, refCollisionIndex); + + float pvX = lambdacoll.posX(); + float pvY = lambdacoll.posY(); + float pvZ = lambdacoll.posZ(); + + auto flagsStart = cascflags.begin(); + + analyzeSinglesLambda(lambdasInThisEvent); + float centVal = lambdacoll.cent(); + analyzeSinglesXi(cascadesInThisEvent, flagsStart, pvX, pvY, pvZ, centVal); + analyzePairs(lambdasInThisEvent, cascadesInThisEvent, flagsStart, centVal); + } + PROCESS_SWITCH(LambdaXiCorrelation, processMCRecoXi, "MC reco Λ–Ξ (truth-tagged tree)", false); + + // --------------------------------------------------------------------------- + // MC Reco-level with truth matching: Λ–Ω + // Same as processOmega but cascades carry McCascLabels → tree gets pdgCode/isPhysPrim. + // --------------------------------------------------------------------------- + void processMCRecoOmega(LambdaCollisionsExt::iterator const& lambdacoll, + GoodLambdas const& /*lambdas*/, + LabeledCascades const& cascades, + aod::CascadeFlags const& cascflags, + FullTracksExtIUWithPID const& /*tracks*/, + aod::McParticles const& /*mcparts*/) + { + histos.fill(HIST("Event/hEventCount"), 0.5); + + auto lambdasInThisEvent = goodLambda->sliceBy(lambdasPerCollision, lambdacoll.globalIndex()); + const int64_t refCollisionIndex = lambdacoll.refCollId(); + auto cascadesInThisEvent = cascades.sliceBy(labeledCascPerCollision, refCollisionIndex); + + float pvX = lambdacoll.posX(); + float pvY = lambdacoll.posY(); + float pvZ = lambdacoll.posZ(); + + auto flagsStart = cascflags.begin(); + + analyzeSinglesLambda(lambdasInThisEvent); + float centVal = lambdacoll.cent(); + analyzeSinglesOmega(cascadesInThisEvent, flagsStart, pvX, pvY, pvZ, centVal); + analyzeOmegaPairs(lambdasInThisEvent, cascadesInThisEvent, flagsStart, centVal); + } + PROCESS_SWITCH(LambdaXiCorrelation, processMCRecoOmega, "MC reco Λ–Ω (truth-tagged tree)", false); + + // --------------------------------------------------------------------------- + // MC Gen-level: Λ–Ξ truth correlation (closure test) + // Loops over generator-level primary Λ from LambdaMcGenTracks and + // generator-level Ξ from McParticles (inline PDG == ±3312 check). + // McParticles are sliced per McCollision using the stored refMcCollId. + // No reconstruction, no PID cuts — pure truth-level R2. + // --------------------------------------------------------------------------- + void processMCGenXi(aod::LambdaMcGenCollisions::iterator const& mcgencol, + aod::LambdaMcGenTracks const& genLambdasAll, + aod::McParticles const& allMcParts) + { + int32_t thisColId = mcgencol.globalIndex(); + histos.fill(HIST("Event/hEventCount"), 0.5); + float centVal = mcgencol.cent(); + + // Slice McParticles to only those belonging to this McCollision + int64_t mcCollId = mcgencol.refMcCollId(); + auto genXis = allMcParts.sliceBy(mcParticlesPerMcCollision, mcCollId); + + // Fill gen Lambda singles — filter by collision ID inline + for (const auto& lam : genLambdasAll) { + if (lam.lambdaMcGenCollisionId() != thisColId) + continue; + if (lam.v0Type() != (int8_t)kLambda || lam.v0PrmScd() != (int8_t)kPrimary) + continue; + if (std::abs(lam.rap()) > maxY) + continue; + histos.fill(HIST("McGen/Singles/Lambda/hPt"), lam.pt()); + } + for (const auto& lam : genLambdasAll) { + if (lam.lambdaMcGenCollisionId() != thisColId) + continue; + if (lam.v0Type() != (int8_t)kAntiLambda || lam.v0PrmScd() != (int8_t)kPrimary) + continue; + if (std::abs(lam.rap()) > maxY) + continue; + histos.fill(HIST("McGen/Singles/AntiLambda/hPt"), lam.pt()); + } + + // Fill gen Xi singles (inline PDG filter) + for (const auto& xi : genXis) { + if (std::abs(xi.pdgCode()) != 3312) + continue; // inline PDG filter + if (!xi.isPhysicalPrimary()) + continue; + float xiY = RecoDecay::y(std::array{xi.px(), xi.py(), xi.pz()}, MassXi0); + if (std::abs(xiY) > maxY) + continue; + if (xi.pdgCode() == 3312) + histos.fill(HIST("McGen/Singles/XiMinus/hPtVsRap"), xiY, xi.pt()); + else if (xi.pdgCode() == -3312) + histos.fill(HIST("McGen/Singles/XiPlus/hPtVsRap"), xiY, xi.pt()); + + // Efficiency denominator: all physical-primary gen Xi in acceptance + if (xi.pdgCode() == 3312) + histos.fill(HIST("Eff/Gen/XiMinus/hCentPtRap"), centVal, xi.pt(), xiY); + else + histos.fill(HIST("Eff/Gen/XiPlus/hCentPtRap"), centVal, xi.pt(), xiY); + + if (bp) { + auto& b = bp->xiGen; + b.pt = xi.pt(); + b.rap = xiY; + b.pdgCode = xi.pdgCode(); + b.isPhysPrim = xi.isPhysicalPrimary(); + b.cent = centVal; + b.pvZ = mcgencol.posZ(); + treeXiGen->Fill(); + } + } + + // Fill gen Lam-Xi pairs + auto fillGenXiPairs = [&](bool isAntiLam) { + int8_t wantType = isAntiLam ? (int8_t)kAntiLambda : (int8_t)kLambda; + for (const auto& lam : genLambdasAll) { + if (lam.lambdaMcGenCollisionId() != thisColId) + continue; + if (lam.v0Type() != wantType || lam.v0PrmScd() != (int8_t)kPrimary) + continue; + if (std::abs(lam.rap()) > maxY) + continue; + for (const auto& xi : genXis) { + if (std::abs(xi.pdgCode()) != 3312) + continue; // inline PDG filter + if (!xi.isPhysicalPrimary()) + continue; + float xiY = RecoDecay::y(std::array{xi.px(), xi.py(), xi.pz()}, MassXi0); + if (std::abs(xiY) > maxY) + continue; + float dphi = RecoDecay::constrainAngle(xi.phi() - lam.phi(), -PIHalf); + float dy = xiY - lam.rap(); + bool isXiPlus = (xi.pdgCode() == -3312); + if (!isAntiLam && !isXiPlus) + histos.fill(HIST("McGen/Pairs/Lam_XiM/hDeltaPhiDeltaY"), centVal, dphi, dy); + else if (!isAntiLam && isXiPlus) + histos.fill(HIST("McGen/Pairs/Lam_XiP/hDeltaPhiDeltaY"), centVal, dphi, dy); + else if (isAntiLam && !isXiPlus) + histos.fill(HIST("McGen/Pairs/AntiLam_XiM/hDeltaPhiDeltaY"), centVal, dphi, dy); + else + histos.fill(HIST("McGen/Pairs/AntiLam_XiP/hDeltaPhiDeltaY"), centVal, dphi, dy); + } + } + }; + fillGenXiPairs(false); + fillGenXiPairs(true); + } + PROCESS_SWITCH(LambdaXiCorrelation, processMCGenXi, "MC gen-level Λ–Ξ closure", false); + + // --------------------------------------------------------------------------- + // MC Gen-level: Λ–Ω truth correlation (closure test) + // Same structure as processMCGenXi but uses |PDG| == 3334 (Omega). + // No kaon PID cut needed — truth level. + // --------------------------------------------------------------------------- + void processMCGenOmega(aod::LambdaMcGenCollisions::iterator const& mcgencol, + aod::LambdaMcGenTracks const& genLambdasAll, + aod::McParticles const& allMcParts) + { + int32_t thisColId = mcgencol.globalIndex(); + histos.fill(HIST("Event/hEventCount"), 0.5); + float centVal = mcgencol.cent(); + + // Slice McParticles to only those belonging to this McCollision + int64_t mcCollId = mcgencol.refMcCollId(); + auto genOmegas = allMcParts.sliceBy(mcParticlesPerMcCollision, mcCollId); + + // Fill gen Lambda singles — filter by collision ID inline + for (const auto& lam : genLambdasAll) { + if (lam.lambdaMcGenCollisionId() != thisColId) + continue; + if (lam.v0Type() != (int8_t)kLambda || lam.v0PrmScd() != (int8_t)kPrimary) + continue; + if (std::abs(lam.rap()) > maxY) + continue; + histos.fill(HIST("McGen/Singles/Lambda/hPt"), lam.pt()); + } + for (const auto& lam : genLambdasAll) { + if (lam.lambdaMcGenCollisionId() != thisColId) + continue; + if (lam.v0Type() != (int8_t)kAntiLambda || lam.v0PrmScd() != (int8_t)kPrimary) + continue; + if (std::abs(lam.rap()) > maxY) + continue; + histos.fill(HIST("McGen/Singles/AntiLambda/hPt"), lam.pt()); + } + + // Fill gen Omega singles (inline PDG filter) + for (const auto& om : genOmegas) { + if (std::abs(om.pdgCode()) != 3334) + continue; // inline PDG filter + if (!om.isPhysicalPrimary()) + continue; + float omY = RecoDecay::y(std::array{om.px(), om.py(), om.pz()}, MassOmegaMinus); + if (std::abs(omY) > maxY) + continue; + if (om.pdgCode() == 3334) + histos.fill(HIST("McGen/Singles/OmegaMinus/hPtVsRap"), omY, om.pt()); + else if (om.pdgCode() == -3334) + histos.fill(HIST("McGen/Singles/OmegaPlus/hPtVsRap"), omY, om.pt()); + + // Efficiency denominator: all physical-primary gen Omega in acceptance + if (om.pdgCode() == 3334) + histos.fill(HIST("Eff/Gen/OmegaMinus/hCentPtRap"), centVal, om.pt(), omY); + else + histos.fill(HIST("Eff/Gen/OmegaPlus/hCentPtRap"), centVal, om.pt(), omY); + + if (bp) { + auto& b = bp->omGen; + b.pt = om.pt(); + b.rap = omY; + b.pdgCode = om.pdgCode(); + b.isPhysPrim = om.isPhysicalPrimary(); + b.cent = centVal; + b.pvZ = mcgencol.posZ(); + treeOmegaGen->Fill(); + } + } + + // Fill gen Lam-Omega pairs + auto fillGenOmPairs = [&](bool isAntiLam) { + int8_t wantType = isAntiLam ? (int8_t)kAntiLambda : (int8_t)kLambda; + for (const auto& lam : genLambdasAll) { + if (lam.lambdaMcGenCollisionId() != thisColId) + continue; + if (lam.v0Type() != wantType || lam.v0PrmScd() != (int8_t)kPrimary) + continue; + if (std::abs(lam.rap()) > maxY) + continue; + for (const auto& om : genOmegas) { + if (std::abs(om.pdgCode()) != 3334) + continue; // inline PDG filter + if (!om.isPhysicalPrimary()) + continue; + float omY = RecoDecay::y(std::array{om.px(), om.py(), om.pz()}, MassOmegaMinus); + if (std::abs(omY) > maxY) + continue; + float dphi = RecoDecay::constrainAngle(om.phi() - lam.phi(), -PIHalf); + float dy = omY - lam.rap(); + bool isOmPlus = (om.pdgCode() == -3334); + if (!isAntiLam && !isOmPlus) + histos.fill(HIST("McGen/Pairs/Lam_OmM/hDeltaPhiDeltaY"), centVal, dphi, dy); + else if (!isAntiLam && isOmPlus) + histos.fill(HIST("McGen/Pairs/Lam_OmP/hDeltaPhiDeltaY"), centVal, dphi, dy); + else if (isAntiLam && !isOmPlus) + histos.fill(HIST("McGen/Pairs/AntiLam_OmM/hDeltaPhiDeltaY"), centVal, dphi, dy); + else + histos.fill(HIST("McGen/Pairs/AntiLam_OmP/hDeltaPhiDeltaY"), centVal, dphi, dy); + } + } + }; + fillGenOmPairs(false); + fillGenOmPairs(true); + } + PROCESS_SWITCH(LambdaXiCorrelation, processMCGenOmega, "MC gen-level Λ–Ω closure", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + // adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + // adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc) + + }; +} diff --git a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx index 489c99bdbff..1497bf7520e 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/corrSparse.cxx @@ -9,34 +9,51 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file corrSparse.cxx +/// \file CorrSparse.cxx /// \brief Provides a sparse with usefull two particle correlation info /// \author Thor Jensen (thor.kjaersgaard.jensen@cern.ch) -#include -#include "TRandom3.h" -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWCumulant.h" +#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "PWGCF/GenericFramework/Core/GFWWeights.h" +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/StepTHn.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "CommonConstants/MathConstants.h" #include "Common/Core/RecoDecay.h" - +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "DataFormatsParameters/GRPObject.h" + +#include "CommonConstants/MathConstants.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsCommonDataFormats/AlignParam.h" +#include "FT0Base/Geometry.h" +#include "FV0Base/Geometry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" +#include + +#include "TRandom3.h" + +#include +#include using namespace o2; using namespace o2::framework; @@ -55,26 +72,126 @@ DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY", // define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; +// static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; +// static constexpr int LongArrayInt[3][20] = {{1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1}, {2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1}, {3, 3, 3, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1}}; + struct CorrSparse { Service ccdb; + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgQaCheck, bool, false, "Fill QA histograms for multiplicity and zVtx for events used in the analysis") + + struct : ConfigurableGroup{ + O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") + O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") + + } cfgTrackCuts; + + struct : ConfigurableGroup{ + + O2_DEFINE_CONFIGURABLE(processFV0, bool, true, "Process FV0 correlations") + O2_DEFINE_CONFIGURABLE(processFT0A, bool, true, "Process FT0A correlations") + O2_DEFINE_CONFIGURABLE(processFT0C, bool, true, "Process FT0C correlations") + O2_DEFINE_CONFIGURABLE(processMFT, bool, true, "Process MFT correlations") + O2_DEFINE_CONFIGURABLE(withGain, bool, false, "Use gain for FT0A and FT0C") + + } cfgDetectorConfig; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgPtCutMinMFT, float, 0.5f, "minimum accepted MFT track pT") + O2_DEFINE_CONFIGURABLE(cfgPtCutMaxMFT, float, 10.0f, "maximum accepted MFT track pT") + O2_DEFINE_CONFIGURABLE(etaMftTrackMin, float, -3.6, "Minimum eta for MFT track") + O2_DEFINE_CONFIGURABLE(etaMftTrackMax, float, -2.5, "Maximum eta for MFT track") + O2_DEFINE_CONFIGURABLE(nClustersMftTrack, int, 5, "Minimum number of clusters for MFT track") + Configurable cutBestCollisionId{"cutBestCollisionId", 0, "cut on the best collision Id used in a filter"}; + Configurable etaMftTrackMaxFilter{"etaMftTrackMaxFilter", -2.0f, "Maximum value for the eta of MFT tracks when used in filter"}; + Configurable etaMftTrackMinFilter{"etaMftTrackMinFilter", -3.9f, "Minimum value for the eta of MFT tracks when used in filter"}; + Configurable mftMaxDCAxy{"mftMaxDCAxy", 2.0f, "Cut on dcaXY for MFT tracks"}; + Configurable mftMaxDCAz{"mftMaxDCAz", 2.0f, "Cut on dcaZ for MFT tracks"}; + } cfgMftConfig; + + struct : ConfigurableGroup{ + O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 10, "Maximum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoITSROFrameBorder, bool, false, "reject events at ITS ROF border") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoTimeFrameBorder, bool, false, "reject events at TF border") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "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") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayer0123, bool, true, "cut time intervals with dead ITS layers 0,1,2,3") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelOccupancy, bool, true, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + + } cfgEventSelection; + + struct : ConfigurableGroup{ + + O2_DEFINE_CONFIGURABLE(cfgRejectFT0AInside, bool, false, "Rejection of inner ring channels of the FT0A detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0AOutside, bool, false, "Rejection of outer ring channels of the FT0A detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0CInside, bool, false, "Rejection of inner ring channels of the FT0C detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0COutside, bool, false, "Rejection of outer ring channels of the FT0C detector") + O2_DEFINE_CONFIGURABLE(cfgRemapFT0ADeadChannels, bool, false, "If true, remap FT0A channels 60-63 to amplitudes from 92-95 respectively") + O2_DEFINE_CONFIGURABLE(cfgRemapFT0CDeadChannels, bool, false, "If true, remap FT0C channels 177->145, 176->144, 178->146, 179->147, 139->115")} cfgFITConfig; + O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") - O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision") - O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 10, "Maximum multiplicity for collision") O2_DEFINE_CONFIGURABLE(cfgMergingCut, float, 0.02, "Merging cut on track merge") O2_DEFINE_CONFIGURABLE(cfgApplyTwoTrackEfficiency, bool, true, "Apply two track efficiency for tpc tpc") O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") - O2_DEFINE_CONFIGURABLE(etaMftTrackMin, float, -3.6, "Minimum eta for MFT track") - O2_DEFINE_CONFIGURABLE(etaMftTrackMax, float, -2.5, "Maximum eta for MFT track") - O2_DEFINE_CONFIGURABLE(nClustersMftTrack, int, 5, "Minimum number of clusters for MFT track") O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") - - Configurable processMFT{"processMFT", true, "Associate particle from MFT"}; + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultT0CCutEnabled, bool, false, "Enable Global multiplicity vs T0C centrality cut") + Configurable> cfgMultT0CCutPars{"cfgMultT0CCutPars", std::vector{143.04, -4.58368, 0.0766055, -0.000727796, 2.86153e-06, 23.3108, -0.36304, 0.00437706, -4.717e-05, 1.98332e-07}, "Global multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultPVT0CCutEnabled, bool, false, "Enable PV multiplicity vs T0C centrality cut") + Configurable> cfgMultPVT0CCutPars{"cfgMultPVT0CCutPars", std::vector{195.357, -6.15194, 0.101313, -0.000955828, 3.74793e-06, 30.0326, -0.43322, 0.00476265, -5.11206e-05, 2.13613e-07}, "PV multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultMultPVHighCutFunction, std::string, "[0]+[1]*x + 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultPVLowCutFunction, std::string, "[0]+[1]*x - 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCutEnabled, bool, false, "Enable global multiplicity vs PV multiplicity cut") + Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.140809, 0.734344, 2.77495, 0.0165935}, "PV multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultMultV0AHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 4.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ACutEnabled, bool, false, "Enable global multiplicity vs V0A multiplicity cut") + Configurable> cfgMultMultV0ACutPars{"cfgMultMultV0ACutPars", std::vector{534.893, 184.344, 0.423539, -0.00331436, 5.34622e-06, 871.239, 53.3735, -0.203528, 0.000122758, 5.41027e-07}, "Global multiplicity vs V0A multiplicity cut parameter values"}; + std::vector multT0CCutPars; + std::vector multPVT0CCutPars; + std::vector multGlobalPVCutPars; + std::vector multMultV0ACutPars; + TF1* fMultPVT0CCutLow = nullptr; + TF1* fMultPVT0CCutHigh = nullptr; + TF1* fMultT0CCutLow = nullptr; + TF1* fMultT0CCutHigh = nullptr; + TF1* fMultGlobalPVCutLow = nullptr; + TF1* fMultGlobalPVCutHigh = nullptr; + TF1* fMultMultV0ACutLow = nullptr; + TF1* fMultMultV0ACutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + } cfgFuncParas; + + Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; + Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; + Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; + Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; SliceCache cache; SliceCache cacheNch; @@ -83,8 +200,24 @@ struct CorrSparse { ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {72, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt axis for histograms"}; + ConfigurableAxis axisAmbiguity{"axisAmbiguity", {100, 0, 100}, "MFT track ambiguity axis for histograms"}; + + ConfigurableAxis axisEtaMft{"axisEtaMFT", {40, -3.6, -2.4}, "eta axis for MFT tracks in histograms"}; + ConfigurableAxis axisEtaFt0a{"axisEtaFT0A", {40, 3.5, 4.9}, "eta axis for FT0A in histograms"}; + ConfigurableAxis axisEtaFt0c{"axisEtaFT0C", {40, -3.3, -2.1}, "eta axis for FT0C in histograms"}; + ConfigurableAxis axisEtaFv0{"axisEtaFV0", {40, 2.2, 5.1}, "eta axis for FV0 in histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; - ConfigurableAxis axisDeltaEta{"axisDeltaEta", {48, -2.4, 2.4}, "delta eta axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {48, -1.6, 1.6}, "delta eta axis for histograms"}; + ConfigurableAxis axisDeltaEtaTpcMft{"axisDeltaEtaTPCMFT", {48, 1.6, 4.6}, "delta eta axis for TPC-MFT histograms"}; + ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTPCFV0", {48, -1.7, -5.9}, "delta eta axis for TPC-FV0 histograms"}; + ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTPCFT0A", {48, -5.7, -2.7}, "delta eta axis for TPC-FT0A histograms"}; + ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTPCFT0C", {48, 1.3, 4.1}, "delta eta axis for TPC-FT0C histograms"}; + ConfigurableAxis axisDeltaEtaMftFt0c{"axisDeltaEtaMFTFT0C", {48, -2.0, 0.6}, "delta eta axis for MFT-FT0C histograms"}; + ConfigurableAxis axisDeltaEtaMftFt0a{"axisDeltaEtaMFTFT0A", {48, -8.5, -5.9}, "delta eta axis for MFT-FT0A histograms"}; + ConfigurableAxis axisDeltaEtaMftFv0{"axisDeltaEtaMFTFV0", {48, -8.6, -4.7}, "delta eta axis for MFT-FV0 histograms"}; + ConfigurableAxis axisDeltaEtaFt0s{"axisDeltaEtaFT0S", {48, -8.6, 5.0}, "delta eta axis for FT0S histograms"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; 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 axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 15, 20, 25, 30, 35, 40, 50, 60, 80, 100}, "multiplicity / centrality axis for histograms"}; @@ -96,83 +229,729 @@ struct CorrSparse { ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; + ConfigurableAxis axisAmplitudeFt0a{"axisAmplitudeFt0a", {5000, 0, 1000}, "FT0A amplitude"}; + ConfigurableAxis axisChannelFt0aAxis{"axisChannelFt0aAxis", {96, 0.0, 96.0}, "FT0A channel"}; + + Configurable cfgGainEqPath{"cfgGainEqPath", "Analysis/EventPlane/GainEq", "CCDB path for gain equalization constants"}; + Configurable cfgCorrLevel{"cfgCorrLevel", 1, "calibration step: 0 = no corr, 1 = gain corr"}; + ConfigurableAxis cfgaxisFITamp{"cfgaxisFITamp", {1000, 0, 5000}, ""}; + AxisSpec axisFit{cfgaxisFITamp, "fit amplitude"}; + AxisSpec axisChID = {220, 0, 220}; + // make the filters and cuts. - Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::evsel::sel8) == true; - Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (cfgPtCutMin < aod::track::pt) && (cfgPtCutMax > aod::track::pt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut); + Filter trackFilter = (nabs(aod::track::eta) < cfgTrackCuts.cfgEtaCut) && (cfgTrackCuts.cfgPtCutMin < aod::track::pt) && (cfgTrackCuts.cfgPtCutMax > aod::track::pt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t)true)) && (aod::track::tpcChi2NCl < cfgTrackCuts.cfgCutChi2prTPCcls) && (aod::track::dcaZ < cfgTrackCuts.cfgCutDCAz); + + Filter mftTrackEtaFilter = ((aod::fwdtrack::eta < cfgMftConfig.etaMftTrackMaxFilter) && (aod::fwdtrack::eta > cfgMftConfig.etaMftTrackMinFilter)); + + // Filters below will be used for uncertainties + Filter mftTrackCollisionIdFilter = (aod::fwdtrack::bestCollisionId >= 0); + Filter mftTrackDcaXYFilter = (nabs(aod::fwdtrack::bestDCAXY) < cfgMftConfig.mftMaxDCAxy); + // Filter mftTrackDcaZFilter = (nabs(aod::fwdtrack::bestDCAZ) < cfgMftConfig.mftMaxDCAz); + + // using AodCollisions = soa::Filtered>; // aod::CentFT0Cs + // using AodTracks = soa::Filtered>; + + using AodCollisions = soa::Filtered>; + using AodTracks = soa::Filtered>; + using FilteredMftTracks = soa::Filtered; + using Reassociated2DMftTracks = aod::BestCollisionsFwd; + + Preslice perColGlobal = aod::track::collisionId; + + // FT0 geometry + o2::ft0::Geometry ft0Det; + o2::fv0::Geometry* fv0Det{}; + static constexpr uint64_t Ft0IndexA = 96; + std::vector* offsetFT0; + std::vector* offsetFV0; + + std::vector cstFT0RelGain{}; + + // Corrections + TH3D* mEfficiency = nullptr; + TH1D* mCentralityWeight = nullptr; + bool correctionsLoaded = false; // Define the outputs - OutputObj same{Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; - OutputObj mixed{Form("mixedEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; HistogramRegistry registry{"registry"}; - using AodCollisions = soa::Filtered>; // aod::CentFT0Cs - using AodTracks = soa::Filtered>; + // Define Global variables + + enum EventCutTypes { + kFilteredEvents = 0, + kAfterSel8, + kUseNoTimeFrameBorder, + kUseNoITSROFrameBorder, + kUseNoSameBunchPileup, + kUseGoodZvtxFT0vsPV, + kUseNoCollInTimeRangeStandard, + kUseGoodITSLayersAll, + kUseGoodITSLayer0123, + kUseNoCollInRofStandard, + kUseNoHighMultCollInPrevRof, + kUseOccupancy, + kUseMultCorrCut, + kUseT0AV0ACut, + kUseVertexITSTPC, + kUseTVXinTRD, + kNEventCuts + }; + + enum EventType { + SameEvent = 1, + MixedEvent = 3 + }; + + enum FITIndex { + kFT0A = 0, + kFT0C, + kFV0 + }; + + enum DetectorChannels { + kFT0AInnerRingMin = 0, + kFT0AInnerRingMax = 31, + kFT0AOuterRingMin = 32, + kFT0AOuterRingMax = 95, + kFT0CInnerRingMin = 96, + kFT0CInnerRingMax = 143, + kFT0COuterRingMin = 144, + kFT0COuterRingMax = 207 + }; + + std::array, 16> eventCuts; void init(InitContext&) { + + const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; + const AxisSpec axisEta{40, -1., 1., "#eta"}; + const AxisSpec axisEtaFull{90, -4., 5., "#eta"}; + ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); + fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); LOGF(info, "Starting init"); + // Event Counter + if ((doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameMFTFIT || doprocessSameTpcMftReassociated2D || doprocessSameMftReassociated2DFIT || doprocessSameFT0s) && cfgUseAdditionalEventCut) { + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kNoITSROFrameBorder"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(4, "kNoTimeFrameBorder"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kIsGoodITSLayer0123"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kIsGoodITSLayersAll"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoCollInRofStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "occupancy"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "MultCorrelation"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); + } + + if (doprocessSameTpcMftReassociated2D || doprocessSameMftReassociated2DFIT) { + registry.add("hEventCountMftReassoc", "Number of Events;; Count", {HistType::kTH1D, {{4, 0, 4}}}); + registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(1, "all MFT tracks"); + registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(2, "MFT tracks after selection"); + registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(3, "ambiguous MFT tracks"); + registry.get(HIST("hEventCountMftReassoc"))->GetXaxis()->SetBinLabel(4, "non-ambiguous MFT tracks"); + + registry.add("ReassociatedMftTracks", "Reassociated MFT tracks", {HistType::kTH1D, {{2, 0, 2}}}); + registry.get(HIST("ReassociatedMftTracks"))->GetXaxis()->SetBinLabel(1, "Not Reassociated MFT tracks"); + registry.get(HIST("ReassociatedMftTracks"))->GetXaxis()->SetBinLabel(2, "Reassociated MFT tracks"); + } + // Make histograms to check the distributions after cuts - registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution - registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); - registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); - registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); - registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); - registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); - registry.add("Nch_used", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event - registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + if (doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameMFTFIT || doprocessSameTpcMftReassociated2D || doprocessSameMftReassociated2DFIT || doprocessSameFT0s) { + registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); + if (doprocessSameMFTFIT) { + registry.add("Eta", "EtaMFT", {HistType::kTH1D, {axisEtaMft}}); + } + if (doprocessSameTpcFIT || doprocessSameTpcMft || doprocessSameTPC || doprocessSameTpcMftReassociated2D) { + registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); + } + registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); + registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); + registry.add("pTCorrected", "pTCorrected", {HistType::kTH1D, {axisPtTrigger}}); + registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("Nch_used", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event + registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); + + if (doprocessSameTpcFIT || doprocessSameMFTFIT || doprocessSameMftReassociated2DFIT || doprocessSameFT0s) { + registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); + registry.add("FV0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); + registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisFit}}); + registry.add("EtaPhi", "", {HistType::kTH2F, {axisEtaFull, axisPhi}}); + } + } + + if (doprocessSameTpcFIT) { + + if (cfgDetectorConfig.processFT0A) { + registry.add("deltaEta_deltaPhi_same_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0a}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + if (cfgDetectorConfig.processFT0C) { + registry.add("deltaEta_deltaPhi_same_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + if (cfgDetectorConfig.processFV0) { + registry.add("deltaEta_deltaPhi_same_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_same_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + } + + if (doprocessSameMFTFIT || doprocessSameMftReassociated2DFIT) { + + if (cfgDetectorConfig.processFT0A) { + registry.add("deltaEta_deltaPhi_same_MFT_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFt0a}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_MFT_FT0A", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFt0a}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + if (cfgDetectorConfig.processFT0C) { + registry.add("deltaEta_deltaPhi_same_MFT_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_MFT_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFt0c}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + if (cfgDetectorConfig.processFV0) { + registry.add("deltaEta_deltaPhi_same_MFT_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFv0}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_MFT_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaMftFv0}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + registry.add("Assoc_amp_same", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + } + } + + if (doprocessSameTpcMft || doprocessSameTpcMftReassociated2D) { + registry.add("deltaEta_deltaPhi_same_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } + + if (doprocessSameTPC) { + registry.add("deltaEta_deltaPhi_same_TPC_TPC", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_TPC", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } - registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + if (doprocessSameFT0s) { + registry.add("deltaEta_deltaPhi_same_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0s}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0s}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event - std::vector corrAxis = {{axisSample, "Sample"}, - {axisVertex, "z-vtx (cm)"}, - {axisPtTrigger, "p_{T} (GeV/c)"}, - {axisPtAssoc, "p_{T} (GeV/c)"}, - {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEta, "#Delta#eta"}}; + LOGF(info, "Initializing correlation container"); + + std::vector corrAxisTpcFt0c = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; + std::vector effAxis = { - {axisVertexEfficiency, "z-vtx (cm)"}, - {axisPtEfficiency, "p_{T} (GeV/c)"}, {axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}, }; + std::vector userAxis; - same.setObject(new CorrelationContainer(Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); - mixed.setObject(new CorrelationContainer(Form("mixedEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("mixedEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + // Correlation axis For TPC-FIT + + std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; + std::vector corrAxisTpcFv0 = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFv0, "#Delta#eta"}}; + + // correlation axis for TPC-TPC + std::vector corrAxisTpcTpc = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEta, "#Delta#eta"}}; + + // Correlation axis For TPC-MFT + std::vector corrAxisTpcMft = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcMft, "#Delta#eta"}}; + + // Correlation axis For MFT-FIT + std::vector corrAxisMftFt0a = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaMftFt0a, "#Delta#eta"}}; + std::vector corrAxisMftFt0c = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaMftFt0c, "#Delta#eta"}}; + std::vector corrAxisMftFv0 = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaMftFv0, "#Delta#eta"}}; + + std::vector corrAxisFT0s = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaFt0s, "#Delta#eta"}}; + + if (doprocessSameTpcFIT) { + if (cfgDetectorConfig.processFT0A) { + same.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFT0C) { + same.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFV0) { + same.setObject(new CorrelationContainer("sameEvent_TPC_FV0", "sameEvent_TPC_FV0", corrAxisTpcFv0, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FV0", "mixedEvent_TPC_FV0", corrAxisTpcFv0, effAxis, userAxis)); + } + } + + if (doprocessSameMFTFIT) { + if (cfgDetectorConfig.processFT0A) { + same.setObject(new CorrelationContainer("sameEvent_MFT_FT0A", "sameEvent_MFT_FT0A", corrAxisMftFt0a, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_FT0A", "mixedEvent_MFT_FT0A", corrAxisMftFt0a, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFT0C) { + same.setObject(new CorrelationContainer("sameEvent_MFT_FT0C", "sameEvent_MFT_FT0C", corrAxisMftFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_FT0C", "mixedEvent_MFT_FT0C", corrAxisMftFt0c, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFV0) { + same.setObject(new CorrelationContainer("sameEvent_MFT_FV0", "sameEvent_MFT_FV0", corrAxisMftFv0, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_FV0", "mixedEvent_MFT_FV0", corrAxisMftFv0, effAxis, userAxis)); + } + } + + if (doprocessSameMftReassociated2DFIT) { + if (cfgDetectorConfig.processFT0A) { + same.setObject(new CorrelationContainer("sameEvent_MFT_Reassociated2D_FT0A", "sameEvent_MFT_Reassociated2D_FT0A", corrAxisMftFt0a, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_Reassociated2D_FT0A", "mixedEvent_MFT_Reassociated2D_FT0A", corrAxisMftFt0a, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFT0C) { + same.setObject(new CorrelationContainer("sameEvent_MFT_Reassociated2D_FT0C", "sameEvent_MFT_Reassociated2D_FT0C", corrAxisMftFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_Reassociated2D_FT0C", "mixedEvent_MFT_Reassociated2D_FT0C", corrAxisMftFt0c, effAxis, userAxis)); + } + if (cfgDetectorConfig.processFV0) { + same.setObject(new CorrelationContainer("sameEvent_MFT_Reassociated2D_FV0", "sameEvent_MFT_Reassociated2D_FV0", corrAxisMftFv0, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_MFT_Reassociated2D_FV0", "mixedEvent_MFT_Reassociated2D_FV0", corrAxisMftFv0, effAxis, userAxis)); + } + } + + if (doprocessSameTPC) { + same.setObject(new CorrelationContainer("sameEvent_TPC_TPC", "sameEvent_TPC_TPC", corrAxisTpcTpc, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_TPC", "mixedEvent_TPC_TPC", corrAxisTpcTpc, effAxis, userAxis)); + } + + if (doprocessSameTpcMft) { + same.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + } + + if (doprocessSameTpcMftReassociated2D) { + same.setObject(new CorrelationContainer("sameEvent_TPC_MFT_Reassociated2D", "sameEvent_TPC_MFT_Reassociated2D", corrAxisTpcMft, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_MFT_Reassociated2D", "mixedEvent_TPC_MFT_Reassociated2D", corrAxisTpcMft, effAxis, userAxis)); + } + + if (doprocessSameFT0s) { + same.setObject(new CorrelationContainer("sameEvent_FT0A_FT0C", "sameEvent_FT0A_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + } + LOGF(info, "End of init"); } - enum EventType { - SameEvent = 1, - MixedEvent = 3 - }; TRandom3* gRandom = new TRandom3(); - template - bool isAcceptedMftTrack(TTrackAssoc const& mftTrack) + template + bool eventSelected(TCollision collision, const int multTrk, const bool fillCounter) + { + registry.fill(HIST("hEventCountSpecific"), 0.5); + if (cfgEventSelection.cfgEvSelkNoSameBunchPileup && !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; + } + if (fillCounter && cfgEventSelection.cfgEvSelkNoSameBunchPileup) + registry.fill(HIST("hEventCountSpecific"), 1.5); + if (cfgEventSelection.cfgEvSelkNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return 0; + } + if (fillCounter && cfgEventSelection.cfgEvSelkNoITSROFrameBorder) + registry.fill(HIST("hEventCountSpecific"), 2.5); + if (cfgEventSelection.cfgEvSelkNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return 0; + } + if (fillCounter && cfgEventSelection.cfgEvSelkNoTimeFrameBorder) + registry.fill(HIST("hEventCountSpecific"), 3.5); + if (cfgEventSelection.cfgEvSelkIsGoodZvtxFT0vsPV && !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; + } + if (fillCounter && cfgEventSelection.cfgEvSelkIsGoodZvtxFT0vsPV) + registry.fill(HIST("hEventCountSpecific"), 4.5); + if (cfgEventSelection.cfgEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // no collisions in specified time range + return 0; + } + if (fillCounter && cfgEventSelection.cfgEvSelkNoCollInTimeRangeStandard) + registry.fill(HIST("hEventCountSpecific"), 5.5); + + if (cfgEventSelection.cfgEvSelkIsGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // from Jan 9 2025 AOT meeting + // cut time intervals with dead ITS staves + return 0; + } + if (fillCounter && cfgEventSelection.cfgEvSelkIsGoodITSLayer0123) + registry.fill(HIST("hEventCountSpecific"), 6.5); + + if (cfgEventSelection.cfgEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // from Jan 9 2025 AOT meeting + // cut time intervals with dead ITS staves + return 0; + } + + if (fillCounter && cfgEventSelection.cfgEvSelkIsGoodITSLayersAll) + registry.fill(HIST("hEventCountSpecific"), 7.5); + + if (cfgEventSelection.cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // no other collisions in this Readout Frame with per-collision multiplicity above threshold + return 0; + } + if (fillCounter && cfgEventSelection.cfgEvSelkNoCollInRofStandard) + registry.fill(HIST("hEventCountSpecific"), 8.5); + if (cfgEventSelection.cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // veto an event if FT0C amplitude in previous ITS ROF is above threshold + return 0; + } + if (fillCounter && cfgEventSelection.cfgEvSelkNoHighMultCollInPrevRof) + registry.fill(HIST("hEventCountSpecific"), 9.5); + auto occupancy = collision.trackOccupancyInTimeRange(); + if (cfgEventSelection.cfgEvSelOccupancy && (occupancy < cfgEventSelection.cfgCutOccupancyLow || occupancy > cfgEventSelection.cfgCutOccupancyHigh)) + return 0; + if (fillCounter && cfgEventSelection.cfgEvSelOccupancy) + registry.fill(HIST("hEventCountSpecific"), 10.5); + + auto multNTracksPV = collision.multNTracksPV(); + + if (cfgFuncParas.cfgMultGlobalPVCutEnabled) { + if (multTrk < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) + return 0; + if (multTrk > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) + return 0; + } + if (cfgFuncParas.cfgMultMultV0ACutEnabled) { + if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(multTrk)) + return 0; + if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(multTrk)) + return 0; + } + + if (fillCounter && cfgEventSelection.cfgEvSelMultCorrelation) + registry.fill(HIST("hEventCountSpecific"), 11.5); + + // V0A T0A 5 sigma cut + float sigma = 5.0; + if (cfgEventSelection.cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + if (fillCounter && cfgEventSelection.cfgEvSelV0AT0ACut) + registry.fill(HIST("hEventCountSpecific"), 12.5); + + return 1; + } + + double getPhiFV0(uint64_t chno) + { + o2::fv0::Point3Dsimple chPos{}; + int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + if (isChnoInLeft) { + chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + (*offsetFV0)[0].getX(), chPos.y + (*offsetFV0)[0].getY()); + } else { + chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + (*offsetFV0)[1].getX(), chPos.y + (*offsetFV0)[1].getY()); + } + } + + double getPhiFT0(uint64_t chno, int i) + { + // offsetFT0[0]: FT0A, offsetFT0[1]: FT0C + if (i > 1 || i < 0) { + LOGF(fatal, "kFIT Index %d out of range", i); + } + + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(chno); + return RecoDecay::phi(chPos.X() + (*offsetFT0)[i].getX(), chPos.Y() + (*offsetFT0)[i].getY()); + } + + double getEtaFV0(uint64_t chno) + { + + int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + o2::fv0::Point3Dsimple chPos{}; + chPos = fv0Det->getReadoutCenter(chno); + + float offsetX, offsetY, offsetZ; + + if (isChnoInLeft) { + offsetX = (*offsetFV0)[0].getX(); + offsetY = (*offsetFV0)[0].getY(); + offsetZ = (*offsetFV0)[0].getZ(); + } else { + offsetX = (*offsetFV0)[1].getX(); + offsetY = (*offsetFV0)[1].getY(); + offsetZ = (*offsetFV0)[1].getZ(); + } + + auto x = chPos.x + offsetX; + auto y = chPos.y + offsetY; + auto z = chPos.z + offsetZ; + + auto r = std::sqrt(x * x + y * y); + auto theta = std::atan2(r, z); + + return -std::log(std::tan(0.5 * theta)); + } + + double getEtaFT0(uint64_t chno, int i) + { + // offsetFT0[0]: FT0A, offsetFT0[1]: FT0C + if (i > 1 || i < 0) { + LOGF(fatal, "kFIT Index %d out of range", i); + } + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(chno); + auto x = chPos.X() + (*offsetFT0)[i].getX(); + auto y = chPos.Y() + (*offsetFT0)[i].getY(); + auto z = chPos.Z() + (*offsetFT0)[i].getZ(); + if (chno >= Ft0IndexA) { + z = -z; + } + auto r = std::sqrt(x * x + y * y); + auto theta = std::atan2(r, z); + return -std::log(std::tan(0.5 * theta)); + } + + template + bool isAcceptedMftTrack(TTrack const& mftTrack) { // cut on the eta of MFT tracks - if (mftTrack.eta() < etaMftTrackMin || mftTrack.eta() > etaMftTrackMax) { + if (mftTrack.eta() < cfgMftConfig.etaMftTrackMin || mftTrack.eta() > cfgMftConfig.etaMftTrackMax) { return false; } // cut on the number of clusters of the reconstructed MFT track - if (mftTrack.nClusters() < nClustersMftTrack) { + if (mftTrack.nClusters() < cfgMftConfig.nClustersMftTrack) { + return false; + } + + if (mftTrack.pt() < cfgMftConfig.cfgPtCutMinMFT || mftTrack.pt() > cfgMftConfig.cfgPtCutMaxMFT) { + return false; + } + + return true; + } + + template + bool isAmbiguousMftTrack(TTrack const& mftTrack, bool fillHistogram) + { + if (mftTrack.ambDegree() > 1) { + if (fillHistogram) { + registry.fill(HIST("hEventCountMftReassoc"), 2.5); // fill histogram for events with at least one ambiguous track); + } return false; } + registry.fill(HIST("hEventCountMftReassoc"), 3.5); // fill histogram for events without ambiguous tracks + return true; + } + + void loadAlignParam(uint64_t timestamp) + { + offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", timestamp); + offsetFV0 = ccdb->getForTimeStamp>("FV0/Calib/Align", timestamp); + if (offsetFT0 == nullptr) { + LOGF(fatal, "Could not load FT0/Calib/Align for timestamp %d", timestamp); + } + if (offsetFV0 == nullptr) { + LOGF(fatal, "Could not load FV0/Calib/Align for timestamp %d", timestamp); + } + } + + void loadGain(aod::BCsWithTimestamps::iterator const& bc) + { + cstFT0RelGain.clear(); + cstFT0RelGain = {}; + std::string fullPath; + + auto timestamp = bc.timestamp(); + constexpr int ChannelsFT0 = 208; + if (cfgCorrLevel == 0) { + for (auto i{0u}; i < ChannelsFT0; i++) { + cstFT0RelGain.push_back(1.); + } + } else { + fullPath = cfgGainEqPath; + fullPath += "/FT0"; + const auto objft0Gain = ccdb->getForTimeStamp>(fullPath, timestamp); + if (!objft0Gain) { + for (auto i{0u}; i < ChannelsFT0; i++) { + cstFT0RelGain.push_back(1.); + } + } else { + cstFT0RelGain = *(objft0Gain); + } + } + } + + template + void getChannelWithGain(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType) + { + if (fitType == kFT0C) { + id = ft0.channelC()[iCh]; + id = id + Ft0IndexA; + ampl = ft0.amplitudeC()[iCh]; + registry.fill(HIST("FT0Amp"), id, ampl); + ampl = ampl / cstFT0RelGain[id]; + registry.fill(HIST("FT0AmpCorrect"), id, ampl); + } else if (fitType == kFT0A) { + id = ft0.channelA()[iCh]; + ampl = ft0.amplitudeA()[iCh]; + registry.fill(HIST("FT0Amp"), id, ampl); + ampl = ampl / cstFT0RelGain[id]; + registry.fill(HIST("FT0AmpCorrect"), id, ampl); + } else { + LOGF(fatal, "Cor Index %d out of range", fitType); + } + } + + void loadCorrection(uint64_t timestamp) + { + if (correctionsLoaded) { + return; + } + if (cfgEfficiency.value.empty() == false) { + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); + mEfficiency = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { + 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); + } + if (cfgCentralityWeight.value.empty() == false) { + mCentralityWeight = ccdb->getForTimeStamp(cfgCentralityWeight, timestamp); + if (mCentralityWeight == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCentralityWeight.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgCentralityWeight.value.c_str(), (void*)mCentralityWeight); + } + correctionsLoaded = true; + } + bool getEfficiencyCorrection(float& weight_nue, float eta, float pt, float posZ) + { + float eff = 1.; + if (mEfficiency) { + int etaBin = mEfficiency->GetXaxis()->FindBin(eta); + int ptBin = mEfficiency->GetYaxis()->FindBin(pt); + int zBin = mEfficiency->GetZaxis()->FindBin(posZ); + eff = mEfficiency->GetBinContent(etaBin, ptBin, zBin); + } else { + eff = 1.0; + } + if (eff == 0) + return false; + weight_nue = 1. / eff; return true; } + template + void getChannelFT0(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType) + { + if (fitType == kFT0C) { + id = ft0.channelC()[iCh]; + id = id + Ft0IndexA; + ampl = ft0.amplitudeC()[iCh]; + } else if (fitType == kFT0A) { + id = ft0.channelA()[iCh]; + ampl = ft0.amplitudeA()[iCh]; + } else { + LOGF(fatal, "Cor Index %d out of range", fitType); + } + registry.fill(HIST("FT0Amp"), id, ampl); + } + + template + void getChannelFV0(TFT0s const& fv0, std::size_t const& iCh, int& id, float& ampl) + { + id = fv0.channel()[iCh]; + ampl = fv0.amplitude()[iCh]; + registry.fill(HIST("FV0Amp"), id, ampl); + } + + template + bool trackSelected(TTrack track) + { + return ((track.tpcNClsFound() >= cfgTrackCuts.cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgTrackCuts.cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgTrackCuts.cfgCutITSclu)); + } + int getMagneticField(uint64_t timestamp) { // Get the magnetic field @@ -192,23 +971,32 @@ struct CorrSparse { template void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms. { - - registry.fill(HIST("Nch"), tracks.size()); registry.fill(HIST("zVtx"), collision.posZ()); + registry.fill(HIST("Nch"), tracks.size()); + + float weff1 = 1.0; + float zvtx = collision.posZ(); for (auto const& track1 : tracks) { - if (processMFT) { - if constexpr (std::is_same_v) { - if (!isAcceptedMftTrack(track1)) { - continue; - } + if constexpr (std::is_same_v) { + if (!isAcceptedMftTrack(track1)) { + continue; + } + } else { + if (!trackSelected(track1)) { + continue; + } + if (!getEfficiencyCorrection(weff1, track1.eta(), track1.pt(), zvtx)) { + continue; } } registry.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); registry.fill(HIST("Eta"), track1.eta()); + registry.fill(HIST("EtaCorrected"), track1.eta(), weff1); registry.fill(HIST("pT"), track1.pt()); + registry.fill(HIST("pTCorrected"), track1.pt(), weff1); } } @@ -236,30 +1024,438 @@ struct CorrSparse { return dPhiStar; } - // - template - void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + // Correlations for detectors and TPC + + ////////////////////////////// + //////////MFT/TPC-FIT//////// + //////////////////////////// + template + void fillCorrelationsFIT(TTracks tracks1, TTracksAssociated tracks2, FITs const&, float posZ, int system, int corType, float multiplicity) { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + float triggerWeight = 1.0f; // loop over all tracks - for (auto const& track1 : tracks1) { + if (cfgQaCheck) { if (system == SameEvent) { - registry.fill(HIST("Nch_used"), tracks1.size()); - registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt()); + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); } + } - for (auto const& track2 : tracks2) { + for (auto const& track1 : tracks1) { + + if constexpr (std::is_same_v) { + + if (!isAcceptedMftTrack(track1)) { + continue; + } + } else { + if (!trackSelected(track1)) { + continue; + } + + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + } + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + } + + // if using FV0A for correlations / using FV0A as associated particles + if constexpr (std::is_same_v) { + + std::size_t channelSize = tracks2.channel().size(); + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int channelID = 0; + float amplitude = 0.; + + getChannelFV0(tracks2, iCh, channelID, amplitude); + + auto phi = getPhiFV0(channelID); + auto eta = getEtaFV0(channelID); + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - phi, -PIHalf); + float deltaEta = track1.eta() - eta; + + if (system == SameEvent) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + + } else if (system == MixedEvent) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FV0"), deltaPhi, deltaEta, amplitude); + } else { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FV0"), deltaPhi, deltaEta, amplitude); + } + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude); + } + } + } + + // if using FT0A and FT0C for correlations / using FT0A and FT0C as associated particles + if constexpr (std::is_same_v) { + + std::size_t channelSize = 0; + if (corType == kFT0C) { + channelSize = tracks2.channelC().size(); + } else if (corType == kFT0A) { + channelSize = tracks2.channelA().size(); + } else { + LOGF(fatal, "Cor Index %d out of range", corType); + } + + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int channelID = 0; + float amplitude = 0.; + if (cfgDetectorConfig.withGain) { + getChannelWithGain(tracks2, iCh, channelID, amplitude, corType); + } else { + getChannelFT0(tracks2, iCh, channelID, amplitude, corType); + } + + // reject depending on FT0C/FT0A rings + if (corType == kFT0C) { + if ((cfgFITConfig.cfgRejectFT0CInside && (channelID >= kFT0CInnerRingMin && channelID <= kFT0CInnerRingMax)) || (cfgFITConfig.cfgRejectFT0COutside && (channelID >= kFT0COuterRingMin && channelID <= kFT0COuterRingMax))) + continue; + } + if (corType == kFT0A) { + if ((cfgFITConfig.cfgRejectFT0AInside && (channelID >= kFT0AInnerRingMin && channelID <= kFT0AInnerRingMax)) || (cfgFITConfig.cfgRejectFT0AOutside && (channelID >= kFT0AOuterRingMin && channelID <= kFT0AOuterRingMax))) + continue; + } + + auto phi = getPhiFT0(channelID, corType); + auto eta = getEtaFT0(channelID, corType); + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - phi, -PIHalf); + float deltaEta = track1.eta() - eta; + + if (system == SameEvent) { + if (corType == kFT0A) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + } + if (corType == kFT0C) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else { + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + } + } else if (system == MixedEvent) { + if (corType == kFT0A) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0A"), deltaPhi, deltaEta, amplitude); + } else { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, amplitude); + } + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude); + } + if (corType == kFT0C) { + if (cfgDetectorConfig.processMFT) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0C"), deltaPhi, deltaEta, amplitude); + } else { + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, amplitude); + } + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, amplitude); + } + } + } + } + } + } + ////////////////////////// + //////////MFT-Reassociated///////// + ////////////////////////// + + template + void fillCorrelationsMftReassociatedFIT(TTracks tracks1, TTracksAssociated tracks2, FITs const&, float posZ, int system, int corType, float multiplicity, bool cutAmbiguousTracks) + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + float triggerWeight = 1.0f; + + // loop over all tracks + if (cfgQaCheck) { + + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } + } + + for (auto const& track1 : tracks1) { + + auto reassociatedMftTrack = track1.template mfttrack_as(); + + if (!isAcceptedMftTrack(reassociatedMftTrack)) { + continue; + } + + if (isAmbiguousMftTrack(track1, false)) { + if (cutAmbiguousTracks) { + continue; + } + } + + if (system == SameEvent) { + + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, reassociatedMftTrack.pt(), triggerWeight); + } + + if constexpr (std::is_same_v) { + + std::size_t channelSize = tracks2.channel().size(); + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int channelID = 0; + float amplitude = 0.; + + getChannelFV0(tracks2, iCh, channelID, amplitude); + + auto phi = getPhiFV0(channelID); + auto eta = getEtaFV0(channelID); + + float deltaPhi = RecoDecay::constrainAngle(reassociatedMftTrack.phi() - phi, -PIHalf); + float deltaEta = reassociatedMftTrack.eta() - eta; + + if (system == SameEvent) { + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FV0"), deltaPhi, deltaEta, amplitude * triggerWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude); + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FV0"), deltaPhi, deltaEta, amplitude); + } + } + } + + // if using FT0A and FT0C for correlations / using FT0A and FT0C as associated particles + if constexpr (std::is_same_v) { + + std::size_t channelSize = 0; + if (corType == kFT0C) { + channelSize = tracks2.channelC().size(); + } else if (corType == kFT0A) { + channelSize = tracks2.channelA().size(); + } else { + LOGF(fatal, "Cor Index %d out of range", corType); + } + + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int channelID = 0; + float amplitude = 0.; + getChannelWithGain(tracks2, iCh, channelID, amplitude, corType); + + // reject depending on FT0C/FT0A rings + if (corType == kFT0C) { + if ((cfgFITConfig.cfgRejectFT0CInside && (channelID >= kFT0CInnerRingMin && channelID <= kFT0CInnerRingMax)) || (cfgFITConfig.cfgRejectFT0COutside && (channelID >= kFT0COuterRingMin && channelID <= kFT0COuterRingMax))) + continue; + } + if (corType == kFT0A) { + if ((cfgFITConfig.cfgRejectFT0AInside && (channelID >= kFT0AInnerRingMin && channelID <= kFT0AInnerRingMax)) || (cfgFITConfig.cfgRejectFT0AOutside && (channelID >= kFT0AOuterRingMin && channelID <= kFT0AOuterRingMax))) + continue; + } + + auto phi = getPhiFT0(channelID, corType); + auto eta = getEtaFT0(channelID, corType); + + float deltaPhi = RecoDecay::constrainAngle(reassociatedMftTrack.phi() - phi, -PIHalf); + float deltaEta = reassociatedMftTrack.eta() - eta; + + if (system == SameEvent) { + if (corType == kFT0A) { + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0A"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + if (corType == kFT0C) { + registry.fill(HIST("Assoc_amp_same"), channelID, amplitude); + same->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_MFT_FT0C"), deltaPhi, deltaEta, amplitude * triggerWeight); + } + } else if (system == MixedEvent) { + if (corType == kFT0A) { + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude); + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0A"), deltaPhi, deltaEta, amplitude); + } + if (corType == kFT0C) { + registry.fill(HIST("Assoc_amp_mixed"), channelID, amplitude); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, reassociatedMftTrack.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta, amplitude); + registry.fill(HIST("deltaEta_deltaPhi_mixed_MFT_FT0C"), deltaPhi, deltaEta, amplitude); + } + } + } + } + } + } + + template + void fillCorrelationsMftReassociatedTracks(TTracks tracks1, TTracksAssoc tracks2, float multiplicity, float posZ, int system, int magneticField, bool cutAmbiguousTracks) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + float triggerWeight = 1.0f; + + auto loopCounter = 0; + if (cfgQaCheck) { + + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } + } + // loop over all tracks + for (auto const& track1 : tracks1) { + + loopCounter++; + + if (!trackSelected(track1)) + continue; + + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + } + + for (auto const& track2 : tracks2) { + + if (!cutAmbiguousTracks && system == SameEvent && (loopCounter == 1)) { + registry.fill(HIST("hEventCountMftReassoc"), 0.5); // fill histogram for events with at least one reassociated track); + } + + auto reassociatedMftTrack = track2.template mfttrack_as(); + + if (!isAcceptedMftTrack(reassociatedMftTrack)) { + continue; + } + + if (!cutAmbiguousTracks && system == SameEvent && (loopCounter == 1)) { + registry.fill(HIST("hEventCountMftReassoc"), 1.5); // fill histogram for events with at least one reassociated track after track selection); + } + + if (isAmbiguousMftTrack(track2, (!cutAmbiguousTracks && system == SameEvent && (loopCounter == 1)))) { + + if (SameEvent && (loopCounter == 1)) { + registry.fill(HIST("ReassociatedMftTracks"), 0.5); + } + if (cutAmbiguousTracks) { + continue; + } + } + + if (reassociatedMftTrack.collisionId() != track2.bestCollisionId()) { + if (SameEvent && (loopCounter == 1)) { + registry.fill(HIST("ReassociatedMftTracks"), 1.5); + } + } + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - reassociatedMftTrack.phi(), -PIHalf); + float deltaEta = track1.eta() - reassociatedMftTrack.eta(); + + if (cfgApplyTwoTrackEfficiency && std::abs(deltaEta) < cfgMergingCut) { + + double dPhiStarHigh = getDPhiStar(track1, reassociatedMftTrack, cfgRadiusHigh, magneticField); + double dPhiStarLow = getDPhiStar(track1, reassociatedMftTrack, cfgRadiusLow, magneticField); + + const double kLimit = 3.0 * cfgMergingCut; + + bool bIsBelow = false; + + if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { + for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { + double dPhiStar = getDPhiStar(track1, reassociatedMftTrack, rad, magneticField); + if (std::abs(dPhiStar) < kLimit) { + bIsBelow = true; + break; + } + } + if (bIsBelow) + continue; + } + } + + // fill the right sparse and histograms + if (system == SameEvent) { + + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_MFT"), deltaPhi, deltaEta); + } else if (system == MixedEvent) { + + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), reassociatedMftTrack.pt(), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_MFT"), deltaPhi, deltaEta); + } + } + } + } + + /////////////////////////////////////// + //////////TPC-TPC and TPC-MFT///////// + ///////////////////////////////////// + template + void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, float multiplicity, int system, int magneticField) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + + if (cfgQaCheck) { + if (system == SameEvent) { + registry.fill(HIST("Nch_used"), multiplicity); + registry.fill(HIST("zVtx_used"), posZ); + } + } + // loop over all tracks + for (auto const& track1 : tracks1) { + + if constexpr (std::is_same_v) { + if (!isAcceptedMftTrack(track1)) { + continue; + } + } else { + if (!trackSelected(track1)) + continue; + + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + } + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + } + + for (auto const& track2 : tracks2) { + + if constexpr (std::is_same_v) { + if (!isAcceptedMftTrack(track2)) { + continue; + } + } else { + if (!trackSelected(track2)) + continue; - if (processMFT) { - if constexpr (std::is_same_v) { - if (!isAcceptedMftTrack(track2)) { - continue; - } - } - } else { if (track1.pt() <= track2.pt()) continue; // skip if the trigger pt is less than the associate pt } @@ -291,48 +1487,442 @@ struct CorrSparse { // fill the right sparse and histograms if (system == SameEvent) { - - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); - registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta); + if (cfgDetectorConfig.processMFT) { + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_MFT"), deltaPhi, deltaEta); + } else { + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_TPC"), deltaPhi, deltaEta); + } } else if (system == MixedEvent) { + if (cfgDetectorConfig.processMFT) { + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_MFT"), deltaPhi, deltaEta); + } else { + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_TPC"), deltaPhi, deltaEta); + } + } + } + } + } + + template + void fillCorrelationsFT0s(TFT0s const& ft01, TFT0s const& ft02, float posZ, int multiplicity, int system, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + if (cfgQaCheck) { + if (system == SameEvent) { + registry.fill(HIST("zVtx_used"), posZ); + registry.fill(HIST("Nch"), multiplicity); + registry.fill(HIST("Nch_used_ft0c"), ft02.channelC().size()); + registry.fill(HIST("Nch_used_ft0a"), ft01.channelA().size()); + } + } + + float triggerWeight = 1.0f; + std::size_t channelASize = ft01.channelA().size(); + std::size_t channelCSize = ft02.channelC().size(); + // loop over all tracks + for (std::size_t iChA = 0; iChA < channelASize; iChA++) { + + int chanelAid = 0; + float amplA = 0.; + if (cfgDetectorConfig.withGain) { + getChannelWithGain(ft01, iChA, chanelAid, amplA, kFT0A); + } else { + getChannelFT0(ft01, iChA, chanelAid, amplA, kFT0A); + } + auto phiA = getPhiFT0(chanelAid, kFT0A); + auto etaA = getEtaFT0(chanelAid, kFT0A); + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, 0.5, eventWeight * amplA); + } - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); - registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta); + for (std::size_t iChC = 0; iChC < channelCSize; iChC++) { + int chanelCid = 0; + float amplC = 0.; + if (cfgDetectorConfig.withGain) { + getChannelWithGain(ft02, iChC, chanelCid, amplC, kFT0C); + } else { + getChannelFT0(ft02, iChC, chanelCid, amplC, kFT0C); + } + auto phiC = getPhiFT0(chanelCid, kFT0C); + auto etaC = getEtaFT0(chanelCid, kFT0C); + float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); + float deltaEta = etaA - etaC; + + // fill the right sparse and histograms + if (system == SameEvent) { + registry.fill(HIST("deltaEta_deltaPhi_same_FT0A_FT0C"), deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("deltaEta_deltaPhi_mixed_FT0A_FT0C"), deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); } } } } + ////////////////////////////////////// + ////// Same event processing ///////// + ////////////////////////////////////// + + //////////////////////////////////// + /////////// Fwrd-Bwrd ///////////// + //////////////////////////////////// - void processSame(AodCollisions::iterator const& collision, AodTracks const& tracks, aod::MFTTracks const& mfts, aod::BCsWithTimestamps const&) + void processSameMFTFIT(AodCollisions::iterator const& collision, AodTracks const& tpctracks, aod::MFTTracks const& mfts, aod::FT0s const& ft0as, aod::FV0As const& fv0as, aod::BCsWithTimestamps const&) { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + if (cfgUseAdditionalEventCut && !eventSelected(collision, tpctracks.size(), true)) + return; + + if (!collision.has_foundFT0()) + return; + loadAlignParam(bc.timestamp()); + if (cfgDetectorConfig.withGain) { + loadGain(bc); + } + + loadCorrection(bc.timestamp()); + + if ((tpctracks.size() < cfgEventSelection.cfgMinMult || tpctracks.size() >= cfgEventSelection.cfgMaxMult)) { + return; + } + if (mfts.size() == 0) { + return; + } + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, mfts); + const auto& multiplicity = tpctracks.size(); + + if (cfgDetectorConfig.processFV0) { + if (collision.has_foundFV0()) { + same->fillEvent(mfts.size(), CorrelationContainer::kCFStepReconstructed); + const auto& fv0 = collision.foundFV0(); + fillCorrelationsFIT(mfts, fv0, fv0as, collision.posZ(), SameEvent, kFV0, multiplicity); + } + } + if (cfgDetectorConfig.processFT0C) { + if (collision.has_foundFT0()) { + same->fillEvent(mfts.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsFIT(mfts, ft0, ft0as, collision.posZ(), SameEvent, kFT0C, multiplicity); + } + } + if (cfgDetectorConfig.processFT0A) { + if (collision.has_foundFT0()) { + same->fillEvent(mfts.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsFIT(mfts, ft0, ft0as, collision.posZ(), SameEvent, kFT0A, multiplicity); + } + } + } + PROCESS_SWITCH(CorrSparse, processSameMFTFIT, "Process same event for MFT-FIT correlation", true); + + void processSameMftReassociated2DFIT(AodCollisions::iterator const& collision, AodTracks const& tpctracks, + soa::SmallGroups const& reassociatedMftTracks, + FilteredMftTracks const&, + aod::FT0s const& ft0as, aod::FV0As const& fv0as, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + + auto bc = collision.bc_as(); + + if (cfgUseAdditionalEventCut && !eventSelected(collision, tpctracks.size(), true)) + return; + + if (!collision.has_foundFT0()) + return; + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); - if (processMFT) { - fillYield(collision, mfts); + if ((tpctracks.size() < cfgEventSelection.cfgMinMult || tpctracks.size() >= cfgEventSelection.cfgMaxMult)) { + return; + } + if (reassociatedMftTracks.size() == 0) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + const auto& multiplicity = tpctracks.size(); - if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { - return; + if (cfgDetectorConfig.processFV0) { + if (collision.has_foundFV0()) { + same->fillEvent(reassociatedMftTracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& fv0 = collision.foundFV0(); + fillCorrelationsMftReassociatedFIT(reassociatedMftTracks, fv0, fv0as, collision.posZ(), SameEvent, kFV0, multiplicity, false); + } + } + if (cfgDetectorConfig.processFT0C) { + if (collision.has_foundFT0()) { + same->fillEvent(reassociatedMftTracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsMftReassociatedFIT(reassociatedMftTracks, ft0, ft0as, collision.posZ(), SameEvent, kFT0C, multiplicity, false); + } + } + if (cfgDetectorConfig.processFT0A) { + if (collision.has_foundFT0()) { + same->fillEvent(reassociatedMftTracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsMftReassociatedFIT(reassociatedMftTracks, ft0, ft0as, collision.posZ(), SameEvent, kFT0A, multiplicity, false); } + } + } + PROCESS_SWITCH(CorrSparse, processSameMftReassociated2DFIT, "Process same event for MFT-FIT correlation with reassociated tracks", false); - fillCorrelations(tracks, mfts, collision.posZ(), SameEvent, getMagneticField(bc.timestamp())); + ///////////////////////// + ////////Mid-Mid////////// + //////////////////////// - } else { - fillYield(collision, tracks); + void processSameTPC(AodCollisions::iterator const& collision, AodTracks const& tracks, aod::BCsWithTimestamps const&) + { + + auto bc = collision.bc_as(); + + if (!collision.sel8()) + return; + + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) + return; + + loadCorrection(bc.timestamp()); + + fillYield(collision, tracks); + + if (tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + fillCorrelations(tracks, tracks, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp())); + } + PROCESS_SWITCH(CorrSparse, processSameTPC, "Process same event for TPC-TPC correlation", false); + + ///////////////////// + ////////back-Mid-Fwrd////// + ///////////////////// + + void processSameTpcFIT(AodCollisions::iterator const& collision, AodTracks const& tracks, aod::FT0s const& ft0as, aod::FV0As const& fv0as, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) + return; + if (!collision.has_foundFT0() && !collision.has_foundFV0()) + return; + + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); + + if ((tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult)) { + return; + } + + loadAlignParam(bc.timestamp()); + if (cfgDetectorConfig.withGain) { + loadGain(bc); + } + + loadCorrection(bc.timestamp()); + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, tracks); + + const auto& multiplicity = tracks.size(); + + if (cfgDetectorConfig.processFV0) { + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& fv0 = collision.foundFV0(); + fillCorrelationsFIT(tracks, fv0, fv0as, collision.posZ(), SameEvent, kFV0, multiplicity); + } + if (cfgDetectorConfig.processFT0C) { + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsFIT(tracks, ft0, ft0as, collision.posZ(), SameEvent, kFT0C, multiplicity); + } + if (cfgDetectorConfig.processFT0A) { + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& ft0 = collision.foundFT0(); + fillCorrelationsFIT(tracks, ft0, ft0as, collision.posZ(), SameEvent, kFT0A, multiplicity); + } + } + PROCESS_SWITCH(CorrSparse, processSameTpcFIT, "process for forward or backwards correlations with TPC", false); + + void processSameTpcMft(AodCollisions::iterator const& collision, AodTracks const& tracks, aod::MFTTracks const& mfts, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + + auto bc = collision.bc_as(); + + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) + return; + + loadCorrection(bc.timestamp()); + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + fillYield(collision, tracks); + + if (tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult) { + return; + } + + fillCorrelations(tracks, mfts, collision.posZ(), tracks.size(), SameEvent, getMagneticField(bc.timestamp())); + } + PROCESS_SWITCH(CorrSparse, processSameTpcMft, "Process same event for TPC-MFT correlation", false); + + void processSameTpcMftReassociated2D(AodCollisions::iterator const& collision, AodTracks const& tracks, + soa::SmallGroups const& reassociatedMftTracks, + FilteredMftTracks const&, + aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + + auto bc = collision.bc_as(); + + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), true)) + return; + + loadCorrection(bc.timestamp()); + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + fillYield(collision, tracks); + + if (tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult) { + return; + } + + fillCorrelationsMftReassociatedTracks(tracks, reassociatedMftTracks, tracks.size(), collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), false); + } + PROCESS_SWITCH(CorrSparse, processSameTpcMftReassociated2D, "Process same event for TPC-MFT correlation with reassociated tracks", false); + + void processSameFT0s(AodCollisions::iterator const& collision, AodTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + + auto bc = collision.bc_as(); + + if (cfgUseAdditionalEventCut && !eventSelected(collision, 0, true)) + return; + + if (!collision.has_foundFT0()) + return; + + loadAlignParam(bc.timestamp()); + if (cfgDetectorConfig.withGain) { + loadGain(bc); + } + loadCorrection(bc.timestamp()); + + if ((tracks.size() < cfgEventSelection.cfgMinMult || tracks.size() >= cfgEventSelection.cfgMaxMult)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + const auto& ft0s = collision.foundFT0(); + auto multiplicity = tracks.size(); - if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { - return; + fillCorrelationsFT0s(ft0s, ft0s, collision.posZ(), multiplicity, SameEvent, 1.0f); + } + PROCESS_SWITCH(CorrSparse, processSameFT0s, "Process same event for FT0 correlation", false); + //////////////////////////////////// + ////// Mixed event processing ////// + //////////////////////////////////// + + ///////////////////////////////////////// + ////////////// Fwrd- Bwrd////////////// + //////////////////////////////////////// + + void processMixedMFTFIT(AodCollisions const& collisions, AodTracks const& tpctracks, aod::MFTTracks const& mfts, aod::FT0s const& ft0as, aod::FV0As const& fv0as, aod::BCsWithTimestamps const&) + { + + auto getTracksSize = [&tpctracks, this](AodCollisions::iterator const& collision) { + auto associatedTracks = tpctracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {vtxMix, multMix}, true}; + + auto tracksTuple = std::make_tuple(mfts, mfts); + Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pair.begin(); it != pair.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; + } + + auto slicedtracks = tpctracks.sliceBy(perColGlobal, collision1.globalIndex()); + auto multiplicity = slicedtracks.size(); + + if ((multiplicity < cfgEventSelection.cfgMinMult || multiplicity >= cfgEventSelection.cfgMaxMult)) + continue; + + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) + continue; + + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) + continue; + + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + + loadCorrection(bc.timestamp()); + + if (cfgDetectorConfig.processFT0A) { + if (!collision1.has_foundFT0() && !collision2.has_foundFT0()) + continue; + + const auto& ft0 = collision2.foundFT0(); + fillCorrelationsFIT(tracks1, ft0, ft0as, collision1.posZ(), MixedEvent, kFT0A, multiplicity); } + if (cfgDetectorConfig.processFT0C) { + if (!collision1.has_foundFT0() && !collision2.has_foundFT0()) + continue; - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp())); + const auto& ft0 = collision2.foundFT0(); + fillCorrelationsFIT(tracks1, ft0, ft0as, collision1.posZ(), MixedEvent, kFT0C, multiplicity); + } + if (cfgDetectorConfig.processFV0) { + if (collision1.has_foundFV0() && collision2.has_foundFV0()) { + const auto& fv0 = collision2.foundFV0(); + fillCorrelationsFIT(tracks1, fv0, fv0as, collision1.posZ(), MixedEvent, kFV0, multiplicity); + } + } } } - PROCESS_SWITCH(CorrSparse, processSame, "Process same event", true); + PROCESS_SWITCH(CorrSparse, processMixedMFTFIT, "Process mixed events for MFT-FIT correlation", true); - // the process for filling the mixed events - void processMixed(AodCollisions const& collisions, AodTracks const& tracks, aod::MFTTracks const& MFTtracks, aod::BCsWithTimestamps const&) + ///////////////////////////// + //////////Mid-Mid/////////// + //////////////////////////// + + void processMixedTpcTpc(AodCollisions const& collisions, AodTracks const& tracks, aod::BCsWithTimestamps const&) { auto getTracksSize = [&tracks, this](AodCollisions::iterator const& collision) { @@ -345,40 +1935,186 @@ struct CorrSparse { MixedBinning binningOnVtxAndMult{{getTracksSize}, {vtxMix, multMix}, true}; - if (processMFT) { + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { - auto tracksTuple = std::make_tuple(tracks, MFTtracks); - Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); + if (!collision1.sel8() || !collision2.sel8()) + continue; - if ((tracks1.size() < cfgMinMult || tracks1.size() >= cfgMaxMult)) - continue; + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; + } + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + + loadCorrection(bc.timestamp()); + + if ((tracks1.size() < cfgEventSelection.cfgMinMult || tracks1.size() >= cfgEventSelection.cfgMaxMult)) + continue; + + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) + continue; + + fillCorrelations(tracks1, tracks2, collision1.posZ(), tracks1.size(), MixedEvent, getMagneticField(bc.timestamp())); + } + } + PROCESS_SWITCH(CorrSparse, processMixedTpcTpc, "Process mixed events for TPC-TPC correlation", false); + + ////////////////////////////// + /////// back-Mid-Fwrd /////// + ///////////////////////////// + + void processMixedTpcFIT(AodCollisions const& collisions, AodTracks const& tracks, aod::FV0As const& fv0as, aod::FT0s const& ft0as, aod::BCsWithTimestamps const&) + { + auto getTracksSize = [&tracks, this](AodCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {vtxMix, multMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pair.begin(); it != pair.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (!collision1.sel8() || !collision2.sel8()) + continue; - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp())); + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; } - } else { - auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - auto bc = collision1.bc_as(); - if ((tracks1.size() < cfgMinMult || tracks1.size() >= cfgMaxMult)) - continue; + if ((tracks1.size() < cfgEventSelection.cfgMinMult || tracks1.size() >= cfgEventSelection.cfgMaxMult)) + continue; - if ((tracks2.size() < cfgMinMult || tracks2.size() >= cfgMaxMult)) - continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) + continue; + + if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + continue; - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp())); + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + + auto multiplicity = tracks1.size(); + + if (cfgDetectorConfig.processFT0A) { + const auto& ft0 = collision2.foundFT0(); + fillCorrelationsFIT(tracks1, ft0, ft0as, collision1.posZ(), MixedEvent, kFT0A, multiplicity); + } + if (cfgDetectorConfig.processFT0C) { + const auto& ft0 = collision2.foundFT0(); + fillCorrelationsFIT(tracks1, ft0, ft0as, collision1.posZ(), MixedEvent, kFT0C, multiplicity); + } + if (cfgDetectorConfig.processFV0) { + const auto& fv0 = collision2.foundFV0(); + fillCorrelationsFIT(tracks1, fv0, fv0as, collision1.posZ(), MixedEvent, kFV0, multiplicity); } } } + PROCESS_SWITCH(CorrSparse, processMixedTpcFIT, "Process mixed events for TPC-FIT correlation", false); - PROCESS_SWITCH(CorrSparse, processMixed, "Process mixed events", true); -}; + void processMixedTpcMFT(AodCollisions const& collisions, AodTracks const& tracks, aod::MFTTracks const& MFTtracks, aod::BCsWithTimestamps const&) + { + + auto getTracksSize = [&tracks, this](AodCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {vtxMix, multMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, MFTtracks); + Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; + } + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + + loadCorrection(bc.timestamp()); + + if ((tracks1.size() < cfgEventSelection.cfgMinMult || tracks1.size() >= cfgEventSelection.cfgMaxMult)) + continue; + + fillCorrelations(tracks1, tracks2, collision1.posZ(), tracks1.size(), MixedEvent, getMagneticField(bc.timestamp())); + } + } + PROCESS_SWITCH(CorrSparse, processMixedTpcMFT, "Process mixed events for TPC-MFT correlation", false); + + void processMixedFT0s(AodCollisions const& collisions, AodTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) + { + + auto getTracksSize = [&tracks, this](AodCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {vtxMix, multMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pair{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pair.begin(); it != pair.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (collision1.globalIndex() == collision2.globalIndex()) { + continue; + } + + if ((tracks1.size() < cfgEventSelection.cfgMinMult || tracks1.size() >= cfgEventSelection.cfgMaxMult)) + continue; + + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), false)) + continue; + + if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + continue; + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + + auto multiplicity = tracks1.size(); + + const auto& ft0_1 = collision1.foundFT0(); + const auto& ft0_2 = collision2.foundFT0(); + fillCorrelationsFT0s(ft0_1, ft0_2, collision1.posZ(), multiplicity, MixedEvent, 1.0f); + } + } + PROCESS_SWITCH(CorrSparse, processMixedFT0s, "Process mixed events for FT0 correlation", false); +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index b76a0d454cb..1398bfa374c 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -100,6 +100,7 @@ struct DiHadronCor { O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") O2_DEFINE_CONFIGURABLE(cfgUsePtOrder, bool, true, "enable trigger pT < associated pT cut") O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, true, "enable trigger pT < associated pT cut in mixed event") + O2_DEFINE_CONFIGURABLE(cfgUseCFStepAll, bool, true, "Filling kCFStepAll") O2_DEFINE_CONFIGURABLE(cfgSoloPtTrack, bool, false, "Skip trigger tracks that are alone in their pT bin for same process") O2_DEFINE_CONFIGURABLE(cfgSingleSoloPtTrack, bool, false, "Skip associated tracks that are alone in their pT bin for same process, works only if cfgSoloPtTrack is enabled") struct : ConfigurableGroup { @@ -1061,8 +1062,10 @@ struct DiHadronCor { } } - same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + if (cfgUseCFStepAll) { + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + } if (collisions.size() == 0) { return; @@ -1117,7 +1120,8 @@ struct DiHadronCor { eventWeight = 1.0f / it.currentWindowNeighbours(); } - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + if (cfgUseCFStepAll) + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); if (groupedCollisions.size() == 0) { continue; @@ -1150,8 +1154,10 @@ struct DiHadronCor { } } - same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + if (cfgUseCFStepAll) { + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + } same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); @@ -1187,7 +1193,8 @@ struct DiHadronCor { eventWeight = 1.0f / it.currentWindowNeighbours(); } - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + if (cfgUseCFStepAll) + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/etaDihadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/etaDihadron.cxx new file mode 100644 index 00000000000..bc34cfb35c4 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/etaDihadron.cxx @@ -0,0 +1,1203 @@ +// 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 etaDihadron.cxx +/// \brief di-hadron correlation for O-O, Pb-Pb collisions +/// \author Zhiyong Lu (zhiyong.lu@cern.ch), Martijn Laarhoven (martijn.laarhoven@cern.ch) +/// \since May/03/2025 + +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWCumulant.h" +#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "PWGCF/GenericFramework/Core/GFWWeights.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/MathConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include + +#include "TF1.h" +#include "TRandom3.h" +#include + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// define the filtered collisions and tracks +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +struct EtaDihadron { + Service ccdb; + + O2_DEFINE_CONFIGURABLE(cfgCutVtxZ, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "maximum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") + O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") + O2_DEFINE_CONFIGURABLE(cfgCutMerging, float, 0.0, "Merging cut on track merge") + O2_DEFINE_CONFIGURABLE(cfgSelCollByNch, bool, true, "Select collisions by Nch or centrality") + O2_DEFINE_CONFIGURABLE(cfgCutMultMin, int, 0, "Minimum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgCutMultMax, int, 10, "Maximum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgCutCentMin, float, 60.0f, "Minimum centrality for collision") + O2_DEFINE_CONFIGURABLE(cfgCutCentMax, float, 80.0f, "Maximum centrality for collision") + O2_DEFINE_CONFIGURABLE(cfgMixEventNumMin, int, 5, "Minimum number of events to mix") + O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + O2_DEFINE_CONFIGURABLE(cfgCentTableUnavailable, bool, false, "if a dataset does not provide centrality information") + O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoITSROFrameBorder, bool, false, "reject events at ITS ROF border") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoTimeFrameBorder, bool, false, "reject events at TF border") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "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") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") + O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") + O2_DEFINE_CONFIGURABLE(cfgEvSelOccupancy, bool, true, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 2000, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgCentralityWeight, std::string, "", "CCDB path to centrality weight object") + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") + O2_DEFINE_CONFIGURABLE(cfgVerbosity, bool, false, "Verbose output") + O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrder, bool, true, "enable trigger pT < associated pT cut") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, true, "enable trigger pT < associated pT cut in mixed event") + O2_DEFINE_CONFIGURABLE(cfgSoloPtTrack, bool, false, "Skip trigger tracks that are alone in their pT bin for same process") + O2_DEFINE_CONFIGURABLE(cfgSingleSoloPtTrack, bool, false, "Skip associated tracks that are alone in their pT bin for same process, works only if cfgSoloPtTrack is enabled") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultT0CCutEnabled, bool, false, "Enable Global multiplicity vs T0C centrality cut") + Configurable> cfgMultT0CCutPars{"cfgMultT0CCutPars", std::vector{143.04, -4.58368, 0.0766055, -0.000727796, 2.86153e-06, 23.3108, -0.36304, 0.00437706, -4.717e-05, 1.98332e-07}, "Global multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultPVT0CCutEnabled, bool, false, "Enable PV multiplicity vs T0C centrality cut") + Configurable> cfgMultPVT0CCutPars{"cfgMultPVT0CCutPars", std::vector{195.357, -6.15194, 0.101313, -0.000955828, 3.74793e-06, 30.0326, -0.43322, 0.00476265, -5.11206e-05, 2.13613e-07}, "PV multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultMultPVHighCutFunction, std::string, "[0]+[1]*x + 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultPVLowCutFunction, std::string, "[0]+[1]*x - 5.*([2]+[3]*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultGlobalPVCutEnabled, bool, false, "Enable global multiplicity vs PV multiplicity cut") + Configurable> cfgMultGlobalPVCutPars{"cfgMultGlobalPVCutPars", std::vector{-0.140809, 0.734344, 2.77495, 0.0165935}, "PV multiplicity vs T0C centrality cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultMultV0AHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 4.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ALowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); + O2_DEFINE_CONFIGURABLE(cfgMultMultV0ACutEnabled, bool, false, "Enable global multiplicity vs V0A multiplicity cut") + Configurable> cfgMultMultV0ACutPars{"cfgMultMultV0ACutPars", std::vector{534.893, 184.344, 0.423539, -0.00331436, 5.34622e-06, 871.239, 53.3735, -0.203528, 0.000122758, 5.41027e-07}, "Global multiplicity vs V0A multiplicity cut parameter values"}; + std::vector multT0CCutPars; + std::vector multPVT0CCutPars; + std::vector multGlobalPVCutPars; + std::vector multMultV0ACutPars; + TF1* fMultPVT0CCutLow = nullptr; + TF1* fMultPVT0CCutHigh = nullptr; + TF1* fMultT0CCutLow = nullptr; + TF1* fMultT0CCutHigh = nullptr; + TF1* fMultGlobalPVCutLow = nullptr; + TF1* fMultGlobalPVCutHigh = nullptr; + TF1* fMultMultV0ACutLow = nullptr; + TF1* fMultMultV0ACutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + } cfgFuncParas; + + SliceCache cache; + + ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity axis for histograms"}; + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "centrality axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt axis for histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {48, -2.4, 2.4}, "delta eta axis for histograms"}; + ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {VARIABLE_WIDTH, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, "eta trigger axis for histograms"}; + ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {VARIABLE_WIDTH, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, "eta associated axis for histograms"}; + ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; + ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity / centrality axis for mixed event histograms"}; + ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; + + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt axis for efficiency histograms"}; + + // make the filters and cuts. + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVtxZ); + 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) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + using FilteredCollisions = soa::Filtered>; + using FilteredTracks = soa::Filtered>; + using FilteredTracksWithMCLabels = soa::Filtered>; + + // Filter for MCParticle + Filter particleFilter = (nabs(aod::mcparticle::eta) < cfgCutEta) && (aod::mcparticle::pt > cfgCutPtMin) && (aod::mcparticle::pt < cfgCutPtMax); + using FilteredMcParticles = soa::Filtered; + + // Filter for MCcollisions + Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVtxZ; + using FilteredMcCollisions = soa::Filtered; + + using SmallGroupMcCollisions = soa::SmallGroups>; + + Preslice perCollision = aod::track::collisionId; + PresliceUnsorted collisionPerMCCollision = aod::mccollisionlabel::mcCollisionId; + + // Corrections + TH3D* mEfficiency = nullptr; + TH1D* mCentralityWeight = nullptr; + bool correctionsLoaded = false; + + // Define the outputs + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; + HistogramRegistry registry{"registry"}; + + // define global variables + TRandom3* gRandom = new TRandom3(); + enum CentEstimators { + kCentFT0C = 0, + kCentFT0CVariant1, + kCentFT0M, + kCentFV0A, + // Count the total number of enum + kCount_CentEstimators + }; + enum EventType { + SameEvent = 1, + MixedEvent = 3 + }; + + // persistent caches + std::vector efficiencyAssociatedCache; + + void init(InitContext&) + { + if (cfgCentTableUnavailable && !cfgSelCollByNch) { + LOGF(fatal, "Centrality table is unavailable, cannot select collisions by centrality"); + } + const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; + const AxisSpec axisEta{40, -1., 1., "#eta"}; + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + LOGF(info, "Starting init"); + + // Event Counter + if (doprocessSame && cfgUseAdditionalEventCut) { + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kNoITSROFrameBorder"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(4, "kNoTimeFrameBorder"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kIsGoodITSLayersAll"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kNoCollInRofStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoHighMultCollInPrevRof"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "occupancy"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "MultCorrelation"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "cfgEvSelV0AT0ACut"); + } + + if (cfgEvSelMultCorrelation) { + cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; + cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; + cfgFuncParas.multGlobalPVCutPars = cfgFuncParas.cfgMultGlobalPVCutPars; + cfgFuncParas.multMultV0ACutPars = cfgFuncParas.cfgMultMultV0ACutPars; + cfgFuncParas.fMultPVT0CCutLow = new TF1("fMultPVT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutLow->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); + cfgFuncParas.fMultPVT0CCutHigh = new TF1("fMultPVT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultPVT0CCutHigh->SetParameters(&(cfgFuncParas.multPVT0CCutPars[0])); + + cfgFuncParas.fMultT0CCutLow = new TF1("fMultT0CCutLow", cfgFuncParas.cfgMultCentLowCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutLow->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); + cfgFuncParas.fMultT0CCutHigh = new TF1("fMultT0CCutHigh", cfgFuncParas.cfgMultCentHighCutFunction->c_str(), 0, 100); + cfgFuncParas.fMultT0CCutHigh->SetParameters(&(cfgFuncParas.multT0CCutPars[0])); + + cfgFuncParas.fMultGlobalPVCutLow = new TF1("fMultGlobalPVCutLow", cfgFuncParas.cfgMultMultPVLowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutLow->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); + cfgFuncParas.fMultGlobalPVCutHigh = new TF1("fMultGlobalPVCutHigh", cfgFuncParas.cfgMultMultPVHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultGlobalPVCutHigh->SetParameters(&(cfgFuncParas.multGlobalPVCutPars[0])); + + cfgFuncParas.fMultMultV0ACutLow = new TF1("fMultMultV0ACutLow", cfgFuncParas.cfgMultMultV0ALowCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutLow->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); + cfgFuncParas.fMultMultV0ACutHigh = new TF1("fMultMultV0ACutHigh", cfgFuncParas.cfgMultMultV0AHighCutFunction->c_str(), 0, 4000); + cfgFuncParas.fMultMultV0ACutHigh->SetParameters(&(cfgFuncParas.multMultV0ACutPars[0])); + + cfgFuncParas.fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + cfgFuncParas.fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); + cfgFuncParas.fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + cfgFuncParas.fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); + } + + std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); + // Make histograms to check the distributions after cuts + if (doprocessSame) { + registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); + registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); + registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); + registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); + registry.add("pT", "pT", {HistType::kTH1D, {axisPt}}); + registry.add("pTCorrected", "pTCorrected", {HistType::kTH1D, {axisPt}}); + registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("Nch_used", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event + registry.add("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); + registry.add("CentralityWeighted", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); + registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); // histogram to see how many events are in the same and mixed event + registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); + } + if (cfgSoloPtTrack && doprocessSame) { + registry.add("Nch_final_eta", "eta", {HistType::kTH1D, {axisEtaTrigger}}); + registry.add("Solo_tracks_trigger", "eta", {HistType::kTH1D, {axisEtaTrigger}}); + if (!cfgSingleSoloPtTrack) { + registry.add("Solo_tracks_assoc", "eta", {HistType::kTH1D, {axisEtaAssoc}}); + } + } + + registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + if (doprocessMCSame && doprocessOntheflySame) { + LOGF(fatal, "Full simulation and on-the-fly processing of same event not supported"); + } + if (doprocessMCMixed && doprocessOntheflyMixed) { + LOGF(fatal, "Full simulation and on-the-fly processing of mixed event not supported"); + } + if (doprocessMCSame || doprocessOntheflySame) { + registry.add("MCTrue/MCeventcount", "MCeventcount", {HistType::kTH1F, {{5, 0, 5, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(2, "same all"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(3, "same reco"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(4, "mixed all"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(5, "mixed reco"); + registry.add("MCTrue/MCCentrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); + registry.add("MCTrue/MCNch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("MCTrue/MCzVtx", "MCzVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("MCTrue/MCPhi", "MCPhi", {HistType::kTH1D, {axisPhi}}); + registry.add("MCTrue/MCEta", "MCEta", {HistType::kTH1D, {axisEta}}); + registry.add("MCTrue/MCpT", "MCpT", {HistType::kTH1D, {axisPt}}); + registry.add("MCTrue/MCTrig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); + registry.add("MCTrue/MCdeltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution + registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); + } + if (doprocessMCEfficiency) { + registry.add("MCEffeventcount", "bin", {HistType::kTH1F, {{5, 0, 5, "bin"}}}); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(2, "MC"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(3, "Reco Primary"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(4, "Reco All"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(5, "Fake"); + } + + LOGF(info, "Initializing correlation container"); + std::vector corrAxis = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEta, "#Delta#eta"}}; + std::vector effAxis = { + {axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}, + }; + std::vector userAxis; + + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + + LOGF(info, "End of init"); + } + + int getMagneticField(uint64_t timestamp) + { + // Get the magnetic field + static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("/GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + template + float getCentrality(TCollision const& collision) + { + float cent; + switch (cfgCentEstimator) { + case kCentFT0C: + cent = collision.centFT0C(); + break; + case kCentFT0CVariant1: + cent = collision.centFT0CVariant1(); + break; + case kCentFT0M: + cent = collision.centFT0M(); + break; + case kCentFV0A: + cent = collision.centFV0A(); + break; + default: + cent = collision.centFT0C(); + } + return cent; + } + + template + bool trackSelected(TTrack track) + { + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); + } + + template + bool genTrackSelected(TTrack track) + { + if (!track.isPhysicalPrimary()) { + return false; + } + if (!track.producedByGenerator()) { + return false; + } + if (std::abs(track.eta()) > cfgCutEta) { + return false; + } + if (std::abs(track.pt()) < cfgCutPtMin || std::abs(track.pt()) > cfgCutPtMax) { + return false; + } + return true; + } + + void loadCorrection(uint64_t timestamp) + { + if (correctionsLoaded) { + return; + } + if (cfgEfficiency.value.empty() == false) { + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiency.value.c_str(), "READ"); + mEfficiency = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { + 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); + } + if (cfgCentralityWeight.value.empty() == false) { + mCentralityWeight = ccdb->getForTimeStamp(cfgCentralityWeight, timestamp); + if (mCentralityWeight == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgCentralityWeight.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgCentralityWeight.value.c_str(), (void*)mCentralityWeight); + } + correctionsLoaded = true; + } + + bool getEfficiencyCorrection(float& weight_nue, float eta, float pt, float posZ) + { + float eff = 1.; + if (mEfficiency) { + int etaBin = mEfficiency->GetXaxis()->FindBin(eta); + int ptBin = mEfficiency->GetYaxis()->FindBin(pt); + int zBin = mEfficiency->GetZaxis()->FindBin(posZ); + eff = mEfficiency->GetBinContent(etaBin, ptBin, zBin); + } else { + eff = 1.0; + } + if (eff == 0) + return false; + weight_nue = 1. / eff; + return true; + } + + bool getCentralityWeight(float& weightCent, const float centrality) + { + float weight = 1.; + if (mCentralityWeight) + weight = mCentralityWeight->GetBinContent(mCentralityWeight->FindBin(centrality)); + else + weight = 1.0; + if (weight == 0) + return false; + weightCent = weight; + return true; + } + + // fill multiple histograms + template + void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms. + { + float weff1 = 1; + float vtxz = collision.posZ(); + for (auto const& track1 : tracks) { + if (!trackSelected(track1)) + continue; + if (!getEfficiencyCorrection(weff1, track1.eta(), track1.pt(), vtxz)) + continue; + registry.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); + registry.fill(HIST("Eta"), track1.eta()); + registry.fill(HIST("EtaCorrected"), track1.eta(), weff1); + registry.fill(HIST("pT"), track1.pt()); + registry.fill(HIST("pTCorrected"), track1.pt(), weff1); + } + } + + template + float getDPhiStar(TTrack const& track1, TTrackAssoc const& track2, float radius, int magField) + { + float charge1 = track1.sign(); + float charge2 = track2.sign(); + + float phi1 = track1.phi(); + float phi2 = track2.phi(); + + float pt1 = track1.pt(); + float pt2 = track2.pt(); + + int fbSign = (magField > 0) ? 1 : -1; + + float dPhiStar = phi1 - phi2 - charge1 * fbSign * std::asin(0.075 * radius / pt1) + charge2 * fbSign * std::asin(0.075 * radius / pt2); + + if (dPhiStar > constants::math::PI) + dPhiStar = constants::math::TwoPI - dPhiStar; + if (dPhiStar < -constants::math::PI) + dPhiStar = -constants::math::TwoPI - dPhiStar; + + return dPhiStar; + } + + template + void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + // Cache efficiency for particles (too many FindBin lookups) + if (mEfficiency) { + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(tracks2.size()); + for (const auto& track2 : tracks2) { + float weff = 1.; + getEfficiencyCorrection(weff, track2.eta(), track2.pt(), posZ); + efficiencyAssociatedCache.push_back(weff); + } + } + + if (system == SameEvent) { + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), tracks1.size()); + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + + if (!trackSelected(track1)) + continue; + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + if (system == SameEvent) { + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); + } + + for (auto const& track2 : tracks2) { + + if (!trackSelected(track2)) + continue; + if (mEfficiency) { + associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; + } + + if (!cfgUsePtOrder && track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + if (cfgUsePtOrder && system == SameEvent && track1.pt() <= track2.pt()) + continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt + if (cfgUsePtOrder && system == MixedEvent && cfgUsePtOrderInMixEvent && track1.pt() <= track2.pt()) + continue; // For pt-differential correlations in mixed events, skip if the trigger pt is less than the associate pt + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); + float deltaEta = track1.eta() - track2.eta(); + + if (std::abs(deltaEta) < cfgCutMerging) { + + double dPhiStarHigh = getDPhiStar(track1, track2, cfgRadiusHigh, magneticField); + double dPhiStarLow = getDPhiStar(track1, track2, cfgRadiusLow, magneticField); + + const double kLimit = 3.0 * cfgCutMerging; + + bool bIsBelow = false; + + if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { + for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { + double dPhiStar = getDPhiStar(track1, track2, rad, magneticField); + if (std::abs(dPhiStar) < kLimit) { + bIsBelow = true; + break; + } + } + if (bIsBelow) + continue; + } + } + + // fill the right sparse and histograms + if (system == SameEvent) { + + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } else if (system == MixedEvent) { + + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + } + } + } + + template + void fillCorrelationsExcludeSoloTracks(TTracks tracks1, TTracksAssoc tracks2, float posZ, int magneticField, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + std::vector tracksSkipIndices; + std::vector tracks2SkipIndices; + + findBiasedTracks(tracks1, tracksSkipIndices, posZ); + if (!cfgSingleSoloPtTrack) { // only look for the solo pt tracks if we want to skip both + findBiasedTracks(tracks2, tracks2SkipIndices, posZ); + } + + // Cache efficiency for particles (too many FindBin lookups) + if (mEfficiency) { + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(tracks2.size()); + for (const auto& track2 : tracks2) { + float weff = 1.; + getEfficiencyCorrection(weff, track2.eta(), track2.pt(), posZ); + efficiencyAssociatedCache.push_back(weff); + } + } + + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), tracks1.size()); + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + + if (!trackSelected(track1)) + continue; + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + + registry.fill(HIST("Nch_final_eta"), track1.eta()); + + if (std::find(tracksSkipIndices.begin(), tracksSkipIndices.end(), track1.globalIndex()) != tracksSkipIndices.end()) { + registry.fill(HIST("Solo_tracks_trigger"), track1.eta()); + continue; // Skip the track1 if it is alone in pt bin + } + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); + + for (auto const& track2 : tracks2) { + + if (!trackSelected(track2)) + continue; + if (mEfficiency) { + associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; + } + if (!cfgUsePtOrder && track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + if (cfgUsePtOrder && track1.pt() <= track2.pt()) + continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt + if (!cfgSingleSoloPtTrack) { // avoid skipping the second track if we only want one + if (std::find(tracks2SkipIndices.begin(), tracks2SkipIndices.end(), track2.globalIndex()) != tracks2SkipIndices.end()) { + registry.fill(HIST("Solo_tracks_assoc"), track2.eta()); + continue; // Skip the track2 if it is alone in pt bin + } + } + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); + float deltaEta = track1.eta() - track2.eta(); + + if (std::abs(deltaEta) < cfgCutMerging) { + + double dPhiStarHigh = getDPhiStar(track1, track2, cfgRadiusHigh, magneticField); + double dPhiStarLow = getDPhiStar(track1, track2, cfgRadiusLow, magneticField); + + const double kLimit = 3.0 * cfgCutMerging; + + bool bIsBelow = false; + + if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { + for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { + double dPhiStar = getDPhiStar(track1, track2, rad, magneticField); + if (std::abs(dPhiStar) < kLimit) { + bIsBelow = true; + break; + } + } + if (bIsBelow) + continue; + } + } + + // fill the right sparse and histograms + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + } + } + + template + void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track1.isPhysicalPrimary()) + continue; + if (doprocessOntheflySame && !genTrackSelected(track1)) + continue; + + if (system == SameEvent && (doprocessMCSame || doprocessOntheflySame)) + registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); + + for (auto const& track2 : tracks2) { + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track2.isPhysicalPrimary()) + continue; + if (doprocessOntheflyMixed && !genTrackSelected(track2)) + continue; + + if (!cfgUsePtOrder && track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + if (cfgUsePtOrder && system == SameEvent && track1.pt() <= track2.pt()) + continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt + if (cfgUsePtOrder && system == MixedEvent && cfgUsePtOrderInMixEvent && track1.pt() <= track2.pt()) + continue; // For pt-differential correlations in mixed events, skip if the trigger pt is less than the associate pt + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); + float deltaEta = track1.eta() - track2.eta(); + + // fill the right sparse and histograms + if (system == SameEvent) { + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + if (doprocessMCSame || doprocessOntheflySame) + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } else if (system == MixedEvent) { + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + if (doprocessMCMixed || doprocessOntheflyMixed) + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + } + } + } + + template + bool eventSelected(TCollision collision, const int multTrk, const float centrality, const bool fillCounter) + { + registry.fill(HIST("hEventCountSpecific"), 0.5); + if (cfgEvSelkNoSameBunchPileup && !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; + } + if (fillCounter && cfgEvSelkNoSameBunchPileup) + registry.fill(HIST("hEventCountSpecific"), 1.5); + if (cfgEvSelkNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return 0; + } + if (fillCounter && cfgEvSelkNoITSROFrameBorder) + registry.fill(HIST("hEventCountSpecific"), 2.5); + if (cfgEvSelkNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return 0; + } + if (fillCounter && cfgEvSelkNoTimeFrameBorder) + registry.fill(HIST("hEventCountSpecific"), 3.5); + if (cfgEvSelkIsGoodZvtxFT0vsPV && !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; + } + if (fillCounter && cfgEvSelkIsGoodZvtxFT0vsPV) + registry.fill(HIST("hEventCountSpecific"), 4.5); + if (cfgEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // no collisions in specified time range + return 0; + } + if (fillCounter && cfgEvSelkNoCollInTimeRangeStandard) + registry.fill(HIST("hEventCountSpecific"), 5.5); + if (cfgEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // from Jan 9 2025 AOT meeting + // cut time intervals with dead ITS staves + return 0; + } + if (fillCounter && cfgEvSelkIsGoodITSLayersAll) + registry.fill(HIST("hEventCountSpecific"), 6.5); + if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // no other collisions in this Readout Frame with per-collision multiplicity above threshold + return 0; + } + if (fillCounter && cfgEvSelkNoCollInRofStandard) + registry.fill(HIST("hEventCountSpecific"), 7.5); + if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // veto an event if FT0C amplitude in previous ITS ROF is above threshold + return 0; + } + if (fillCounter && cfgEvSelkNoHighMultCollInPrevRof) + registry.fill(HIST("hEventCountSpecific"), 8.5); + auto occupancy = collision.trackOccupancyInTimeRange(); + if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) + return 0; + if (fillCounter && cfgEvSelOccupancy) + registry.fill(HIST("hEventCountSpecific"), 9.5); + + auto multNTracksPV = collision.multNTracksPV(); + if (cfgEvSelMultCorrelation) { + if (cfgFuncParas.cfgMultPVT0CCutEnabled && !cfgCentTableUnavailable) { + if (multNTracksPV < cfgFuncParas.fMultPVT0CCutLow->Eval(centrality)) + return 0; + if (multNTracksPV > cfgFuncParas.fMultPVT0CCutHigh->Eval(centrality)) + return 0; + } + if (cfgFuncParas.cfgMultT0CCutEnabled && !cfgCentTableUnavailable) { + if (multTrk < cfgFuncParas.fMultT0CCutLow->Eval(centrality)) + return 0; + if (multTrk > cfgFuncParas.fMultT0CCutHigh->Eval(centrality)) + return 0; + } + if (cfgFuncParas.cfgMultGlobalPVCutEnabled) { + if (multTrk < cfgFuncParas.fMultGlobalPVCutLow->Eval(multNTracksPV)) + return 0; + if (multTrk > cfgFuncParas.fMultGlobalPVCutHigh->Eval(multNTracksPV)) + return 0; + } + if (cfgFuncParas.cfgMultMultV0ACutEnabled) { + if (collision.multFV0A() < cfgFuncParas.fMultMultV0ACutLow->Eval(multTrk)) + return 0; + if (collision.multFV0A() > cfgFuncParas.fMultMultV0ACutHigh->Eval(multTrk)) + return 0; + } + } + if (fillCounter && cfgEvSelMultCorrelation) + registry.fill(HIST("hEventCountSpecific"), 10.5); + + // V0A T0A 5 sigma cut + float sigma = 5.0; + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + if (fillCounter && cfgEvSelV0AT0ACut) + registry.fill(HIST("hEventCountSpecific"), 11.5); + + return 1; + } + + void findBiasedTracks(FilteredTracks const& tracks, std::vector& tracksSkipIndices, float posZ) + { + // Find the tracks that are alone in their pT bin + tracksSkipIndices.clear(); + static const std::vector& ptBins = axisPt.value; + static const size_t nPtBins = ptBins.size() - 1; + + std::vector numberOfTracksInBin(nPtBins, 0); + std::vector firstTrackIndex(nPtBins, -1); + + float triggerWeight = 1.0f; + + // Count tracks per bin and remember the first track id in each bin + for (const auto& track : tracks) { + if (!trackSelected(track)) + continue; + if (!getEfficiencyCorrection(triggerWeight, track.eta(), track.pt(), posZ)) + continue; + double pt = track.pt(); + auto binEdgeIt = std::upper_bound(ptBins.begin(), ptBins.end(), pt); + if (binEdgeIt == ptBins.begin() || binEdgeIt == ptBins.end()) + continue; // skip pt bins out of range + + size_t binIndex = static_cast(std::distance(ptBins.begin(), binEdgeIt) - 1); + + if (numberOfTracksInBin[binIndex] == 0) { + firstTrackIndex[binIndex] = track.globalIndex(); + } + ++numberOfTracksInBin[binIndex]; + } + + // Collect track ids for bins that have exactly one track + for (size_t i = 0; i < nPtBins; ++i) { + if (numberOfTracksInBin[i] == 1) { + tracksSkipIndices.push_back(firstTrackIndex[i]); + } + } + } + + void processSame(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + float cent = -1.; + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + return; + loadCorrection(bc.timestamp()); + if (!cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); + + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, tracks); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + if (!cfgSoloPtTrack) { + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent, weightCent); + } else { + fillCorrelationsExcludeSoloTracks(tracks, tracks, collision.posZ(), getMagneticField(bc.timestamp()), cent, weightCent); + } + } + PROCESS_SWITCH(EtaDihadron, processSame, "Process same event", true); + + // the process for filling the mixed events + void processMixed(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) + { + + auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + float cent1 = -1; + float cent2 = -1; + if (!cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + continue; + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + auto bc = collision1.bc_as(); + loadCorrection(bc.timestamp()); + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1, eventWeight * weightCent); + } + } + + PROCESS_SWITCH(EtaDihadron, processMixed, "Process mixed events", true); + + int getSpecies(int pdgCode) + { + switch (std::abs(pdgCode)) { + case PDG_t::kPiPlus: // pion + return 0; + case PDG_t::kKPlus: // Kaon + return 1; + case PDG_t::kProton: // proton + return 2; + default: // NOTE. The efficiency histogram is hardcoded to contain 4 species. Anything special will have the last slot. + return 3; + } + } + + void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) + { + registry.fill(HIST("MCEffeventcount"), 0.5); + if (cfgSelCollByNch && (mcParticles.size() < cfgCutMultMin || mcParticles.size() >= cfgCutMultMax)) { + return; + } + // Primaries + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCEffeventcount"), 1.5); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); + } + } + for (const auto& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + if (cfgVerbosity) { + LOGF(info, " Reconstructed collision at vtx-z = %f", collision.posZ()); + LOGF(info, " which has %d tracks", groupedTracks.size()); + } + + for (const auto& track : groupedTracks) { + if (track.has_mcParticle()) { + auto mcParticle = track.mcParticle(); + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCEffeventcount"), 2.5); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); + } + registry.fill(HIST("MCEffeventcount"), 3.5); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); + } else { + // fake track + registry.fill(HIST("MCEffeventcount"), 4.5); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, track.eta(), track.pt(), 0, 0., mcCollision.posZ()); + } + } + } + } + PROCESS_SWITCH(EtaDihadron, processMCEfficiency, "MC: Extract efficiencies", false); + + void processMCSame(FilteredMcCollisions::iterator const& mcCollision, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + if (cfgVerbosity) { + LOGF(info, "processMCSame. MC collision: %d, particles: %d, collisions: %d", mcCollision.globalIndex(), mcParticles.size(), collisions.size()); + } + + float cent = -1; + if (!cfgCentTableUnavailable) { + for (const auto& collision : collisions) { + cent = getCentrality(collision); + } + } + + if (cfgSelCollByNch && (mcParticles.size() < cfgCutMultMin || mcParticles.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + if (!cfgCentTableUnavailable) + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), mcParticles.size()); + registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), mcParticle.phi()); + registry.fill(HIST("MCTrue/MCEta"), mcParticle.eta()); + registry.fill(HIST("MCTrue/MCpT"), mcParticle.pt()); + } + } + + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + + if (collisions.size() == 0) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), 2.5); + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + } + PROCESS_SWITCH(EtaDihadron, processMCSame, "Process MC same event", false); + + void processMCMixed(FilteredMcCollisions const& mcCollisions, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + if (cfgVerbosity > 0) { + LOGF(info, "Found %d related collisions", groupedCollisions.size()); + } + float cent = -1; + if (!cfgCentTableUnavailable) { + for (const auto& collision : groupedCollisions) { + cent = getCentrality(collision); + } + } + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && groupedCollisions.size() != 0 && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) + continue; + + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + + if (groupedCollisions.size() == 0) { + continue; + } + + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + } + } + PROCESS_SWITCH(EtaDihadron, processMCMixed, "Process MC mixed events", false); + + void processOntheflySame(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles) + { + if (cfgVerbosity) { + LOGF(info, "processOntheflySame. MC collision: %d, particles: %d", mcCollision.globalIndex(), mcParticles.size()); + } + + if (cfgSelCollByNch && (mcParticles.size() < cfgCutMultMin || mcParticles.size() >= cfgCutMultMax)) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + registry.fill(HIST("MCTrue/MCNch"), mcParticles.size()); + registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), mcParticle.phi()); + registry.fill(HIST("MCTrue/MCEta"), mcParticle.eta()); + registry.fill(HIST("MCTrue/MCpT"), mcParticle.pt()); + } + } + + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + } + PROCESS_SWITCH(EtaDihadron, processOntheflySame, "Process on-the-fly same event", false); + + void processOntheflyMixed(aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + { + auto getTracksSize = [&mcParticles, this](aod::McCollisions::iterator const& mcCollision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + } + } + PROCESS_SWITCH(EtaDihadron, processOntheflyMixed, "Process on-the-fly mixed events", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx index 36a4c0fef24..692a6583f5c 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/flowDecorrelation.cxx @@ -28,9 +28,6 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/MathConstants.h" @@ -46,7 +43,6 @@ #include "Framework/RunningWorkflowInfo.h" #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" #include @@ -55,6 +51,7 @@ #include #include +#include #include using namespace o2; @@ -63,17 +60,12 @@ using namespace o2::framework::expressions; // define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; -// template for labelled array -static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; - struct FlowDecorrelation { Service ccdb; - o2::aod::ITSResponse itsResponse; O2_DEFINE_CONFIGURABLE(cfgCutVtxZ, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "minimum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta cut") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutTPCCrossedRows, float, 70.0f, "minimum TPC crossed rows") @@ -95,6 +87,7 @@ struct FlowDecorrelation { O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "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") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayer0123, bool, false, "cut time intervals with dead ITS staves (layers 0-3 only, for pp)") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") @@ -107,6 +100,24 @@ struct FlowDecorrelation { O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") O2_DEFINE_CONFIGURABLE(cfgDrawEtaPhiDis, bool, false, "draw eta-phi distribution for detectors in used") + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(nClustersMftTrack, int, 5, "Minimum number of clusters for MFT track") + O2_DEFINE_CONFIGURABLE(cfgCutChi2Mft, float, -1.0f, "max chi2 of MFT track") + O2_DEFINE_CONFIGURABLE(cfgCutTrackTimeMft, float, -1.0f, "max deviation of MFT track wrt. bc in ns"); + } cfgMftCuts; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgRejectFT0AInside, bool, false, "Rejection of inner ring channels of the FT0A detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0AOutside, bool, false, "Rejection of outer ring channels of the FT0A detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0CInside, bool, false, "Rejection of inner ring channels of the FT0C detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0COutside, bool, false, "Rejection of outer ring channels of the FT0C detector"); + } cfgFt0RingRejections; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgEtaTpcCut, float, 0.8f, "Eta cut of TPC MC particles") + O2_DEFINE_CONFIGURABLE(cfgMinEtaFt0cCut, float, -3.4f, "Min eta cut of FT0C MC particles") + O2_DEFINE_CONFIGURABLE(cfgMaxEtaFt0cCut, float, -2.0f, "Max eta cut of FT0C MC particles") + O2_DEFINE_CONFIGURABLE(cfgUseFt0cStructure, bool, true, "Use the true structure of FT0C in MC-true"); + O2_DEFINE_CONFIGURABLE(cfgUseCFStepAll, bool, true, "Use CFStepAll in addition to primry"); + } cfgMcTrue; struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -137,24 +148,19 @@ struct FlowDecorrelation { TF1* fT0AV0AMean = nullptr; TF1* fT0AV0ASigma = nullptr; } cfgFuncParas; - struct : ConfigurableGroup { - O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") - O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") - O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") - Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"pos_pi", "pos_ka", "pos_pr", "neg_pi", "neg_ka", "neg_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; - } cfgPIDConfig; SliceCache cache; - ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity axis for histograms"}; - ConfigurableAxis axisEta{"axisEta", {VARIABLE_WIDTH, -4.9, -3.3, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta axis for histograms"}; + ConfigurableAxis axisEta{"axisEta", {70, -5.0, 5.0}, "eta axis for histograms"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEtaTpcFt0a{"axisDeltaEtaTpcFt0a", {32, -5.8, -2.6}, "delta eta axis, -5.8~-2.6 for TPC-FT0A,"}; ConfigurableAxis axisDeltaEtaTpcFt0c{"axisDeltaEtaTpcFt0c", {32, 1.2, 4.2}, "delta eta axis, 1.2~4.2 for TPC-FT0C"}; - ConfigurableAxis axisDeltaEtaFt0aFt0c{"axisDeltaEtaFt0aFt0c", {32, -1.5, 3.0}, "delta eta axis"}; - ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {VARIABLE_WIDTH, -4.9, -3.3, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta trigger axis for histograms"}; - ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {VARIABLE_WIDTH, -4.9, -3.3, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta associated axis for histograms"}; + ConfigurableAxis axisDeltaEtaFt0aFt0c{"axisDeltaEtaFt0aFt0c", {32, 4.2, 8.2}, "delta eta axis, 4.2~8.2 for FT0A-FT0C"}; + ConfigurableAxis axisDeltaEtaTpcMft{"axisDeltaEtaTpcMft", {32, 1.3, 4.8}, "delta eta axis, 1.3~4.8 for TPC-MFT"}; + ConfigurableAxis axisDeltaEtaTpcFv0{"axisDeltaEtaTpcFv0", {32, -6.1, -1.2}, "delta eta axis for TPC-FV0 histograms"}; + ConfigurableAxis axisEtaTrigger{"axisEtaTrigger", {VARIABLE_WIDTH, -3.4, -2.0, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta trigger axis for histograms"}; + ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {VARIABLE_WIDTH, -3.3, -2.1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 3.5, 4.9}, "eta associated axis for histograms"}; ConfigurableAxis axisVtxMix{"axisVtxMix", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "vertex axis for mixed event histograms"}; ConfigurableAxis axisMultMix{"axisMultMix", {VARIABLE_WIDTH, 0, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260}, "multiplicity / centrality axis for mixed event histograms"}; ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; @@ -172,14 +178,27 @@ struct FlowDecorrelation { AxisSpec axisChID = {220, 0, 220}; // make the filters and cuts. Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVtxZ); - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == static_cast(true))) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter trackFilter = (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == static_cast(true))) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz); using FilteredCollisions = soa::Filtered>; - using FilteredTracks = soa::Filtered>; + using FilteredTracks = soa::Filtered>; + + Filter particleFilter = (nabs(aod::mcparticle::eta) < cfgMcTrue.cfgEtaTpcCut || ((aod::mcparticle::eta > cfgMcTrue.cfgMinEtaFt0cCut) && (aod::mcparticle::eta < cfgMcTrue.cfgMaxEtaFt0cCut))) && (aod::mcparticle::pt > cfgCutPtMin) && (aod::mcparticle::pt < cfgCutPtMax); + using FilteredMcParticles = soa::Filtered; + + // Filter for MCcollisions + Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVtxZ; + using FilteredMcCollisions = soa::Filtered; + + using SmallGroupMcCollisions = soa::SmallGroups>; + + PresliceUnsorted collisionPerMCCollision = aod::mccollisionlabel::mcCollisionId; // FT0 geometry o2::ft0::Geometry ft0Det; + o2::fv0::Geometry* fv0Det{}; static constexpr uint64_t Ft0IndexA = 96; std::vector* offsetFT0; + std::vector* offsetFV0; std::vector cstFT0RelGain{}; // Corrections @@ -188,12 +207,8 @@ struct FlowDecorrelation { bool correctionsLoaded = false; // Define the outputs - OutputObj sameTpcFt0a{"sameEvent_TPC_FT0A"}; - OutputObj mixedTpcFt0a{"mixedEvent_TPC_FT0A"}; - OutputObj sameTpcFt0c{"sameEvent_TPC_FT0C"}; - OutputObj mixedTpcFt0c{"mixedEvent_TPC_FT0C"}; - OutputObj sameFt0aFt0c{"sameEvent_FT0A_FT0C"}; - OutputObj mixedFt0aFt0c{"mixedEvent_FT0A_FT0C"}; + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; HistogramRegistry registry{"registry"}; // define global variables @@ -212,7 +227,8 @@ struct FlowDecorrelation { }; enum FITIndex { kFT0A = 0, - kFT0C = 1 + kFT0C = 1, + kFV0 = 2 }; enum ParticleNsigma { kPionUp = 0, @@ -222,20 +238,21 @@ struct FlowDecorrelation { kKaonLow, kProtonLow }; - enum PIDIndex { - kCharged = 0, - kPions, - kKaons, - kProtons, - kK0, - kLambda, - kPhi - }; enum DetectorType { kTPC = 0, kTOF, kITS }; + enum DetectorChannels { + kFT0AInnerRingMin = 0, + kFT0AInnerRingMax = 31, + kFT0AOuterRingMin = 32, + kFT0AOuterRingMax = 95, + kFT0CInnerRingMin = 96, + kFT0CInnerRingMax = 143, + kFT0COuterRingMin = 144, + kFT0COuterRingMax = 207 + }; std::array tofNsigmaCut; std::array itsNsigmaCut; std::array tpcNsigmaCut; @@ -248,39 +265,18 @@ struct FlowDecorrelation { const AxisSpec axisPhi{72, 0.0, constants::math::TwoPI, "#varphi"}; const AxisSpec axisEta{40, -1., 1., "#eta"}; const AxisSpec axisEtaFull{90, -4., 5., "#eta"}; + const AxisSpec axisCentrality{20, 0., 100., "cent"}; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); + fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); LOGF(info, "Starting init"); - - // filling tpc nSigmas array - tpcNsigmaCut[kPionUp] = cfgPIDConfig.nSigmas->getData()[kTPC][kPionUp]; - tpcNsigmaCut[kKaonUp] = cfgPIDConfig.nSigmas->getData()[kTPC][kKaonUp]; - tpcNsigmaCut[kProtonUp] = cfgPIDConfig.nSigmas->getData()[kTPC][kProtonUp]; - tpcNsigmaCut[kPionLow] = cfgPIDConfig.nSigmas->getData()[kTPC][kPionLow]; - tpcNsigmaCut[kKaonLow] = cfgPIDConfig.nSigmas->getData()[kTPC][kKaonLow]; - tpcNsigmaCut[kProtonLow] = cfgPIDConfig.nSigmas->getData()[kTPC][kProtonLow]; - // filling tof nSigmas array - tofNsigmaCut[kPionUp] = cfgPIDConfig.nSigmas->getData()[kTOF][kPionUp]; - tofNsigmaCut[kKaonUp] = cfgPIDConfig.nSigmas->getData()[kTOF][kKaonUp]; - tofNsigmaCut[kProtonUp] = cfgPIDConfig.nSigmas->getData()[kTOF][kProtonUp]; - tofNsigmaCut[kPionLow] = cfgPIDConfig.nSigmas->getData()[kTOF][kPionLow]; - tofNsigmaCut[kKaonLow] = cfgPIDConfig.nSigmas->getData()[kTOF][kKaonLow]; - tofNsigmaCut[kProtonLow] = cfgPIDConfig.nSigmas->getData()[kTOF][kProtonLow]; - // filling its nSigmas array - itsNsigmaCut[kPionUp] = cfgPIDConfig.nSigmas->getData()[kITS][kPionUp]; - itsNsigmaCut[kKaonUp] = cfgPIDConfig.nSigmas->getData()[kITS][kKaonUp]; - itsNsigmaCut[kProtonUp] = cfgPIDConfig.nSigmas->getData()[kITS][kProtonUp]; - itsNsigmaCut[kPionLow] = cfgPIDConfig.nSigmas->getData()[kITS][kPionLow]; - itsNsigmaCut[kKaonLow] = cfgPIDConfig.nSigmas->getData()[kITS][kKaonLow]; - itsNsigmaCut[kProtonLow] = cfgPIDConfig.nSigmas->getData()[kITS][kProtonLow]; - // Event Counter - if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) && cfgUseAdditionalEventCut) { - registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); + if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) && cfgUseAdditionalEventCut) { + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kNoITSROFrameBorder"); @@ -288,13 +284,30 @@ struct FlowDecorrelation { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInTimeRangeStandard"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "occupancy"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "MultCorrelation"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "cfgEvSelV0AT0ACut"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kIsGoodITSLayer0123"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoCollInRofStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "occupancy"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "MultCorrelation"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); + } + if (doprocessMcSameTpcFt0c) { + registry.add("MCTrue/MCeventcount", "MCeventcount", {HistType::kTH1F, {{5, 0, 5, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(2, "same all"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(3, "same reco"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(4, "mixed all"); + registry.get(HIST("MCTrue/MCeventcount"))->GetXaxis()->SetBinLabel(5, "mixed reco"); + registry.add("MCTrue/MCCentrality", "cent", {HistType::kTH1D, {axisCentrality}}); + registry.add("MCTrue/MCNch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("MCTrue/MCzVtx", "MCzVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("MCTrue/MCPhi", "MCPhi", {HistType::kTH1D, {axisPhi}}); + registry.add("MCTrue/MCEta", "MCEta", {HistType::kTH1D, {axisEtaFull}}); + registry.add("MCTrue/MCEtaTrueShape", "MCEta", {HistType::kTH1D, {axisEtaFull}}); + registry.add("MCTrue/MCpT", "MCpT", {HistType::kTH1D, {axisPtEfficiency}}); + registry.add("MCTrue/MCTrig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtEfficiency}}}); + registry.add("MCTrue/MCdeltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); // check to see the delta eta and delta phi distribution + registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFt0c}}); } - if (cfgEvSelMultCorrelation) { cfgFuncParas.multT0CCutPars = cfgFuncParas.cfgMultT0CCutPars; cfgFuncParas.multPVT0CCutPars = cfgFuncParas.cfgMultPVT0CCutPars; @@ -328,7 +341,7 @@ struct FlowDecorrelation { std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); // Make histograms to check the distributions after cuts - if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) { + if (doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c || doprocessSameTpcMft || doprocessSameTpcFv0) { registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); registry.add("EtaCorrected", "EtaCorrected", {HistType::kTH1D, {axisEta}}); @@ -338,6 +351,8 @@ struct FlowDecorrelation { registry.add("CentralityWeighted", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); // histogram to see how many events are in the same and mixed event registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("pTCorrected", "pTCorrected", {HistType::kTH1D, {axisPtEfficiency}}); + registry.add("pT", "pT", {HistType::kTH1D, {axisPtEfficiency}}); registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); registry.add("FT0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); registry.add("FT0AmpCorrect", "", {HistType::kTH2F, {axisChID, axisFit}}); @@ -362,30 +377,48 @@ struct FlowDecorrelation { if (doprocessSameFt0aFt0c) { registry.add("deltaEta_deltaPhi_same_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0aFt0c}}); // check to see the delta eta and delta phi distribution registry.add("deltaEta_deltaPhi_mixed_FT0A_FT0C", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaFt0aFt0c}}); + registry.add("Assoc_amp_same_FT0A_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed_FT0A_FT0C", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); registry.add("Trig_hist_FT0A_FT0C", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); } + if (doprocessSameTpcMft) { + registry.add("deltaEta_deltaPhi_same_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_MFT", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcMft}}); + registry.add("Trig_hist_TPC_MFT", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); + } + if (doprocessSameTpcFv0) { + registry.add("deltaEta_deltaPhi_same_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed_TPC_FV0", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEtaTpcFv0}}); + registry.add("Assoc_amp_same_TPC_FV0", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Assoc_amp_mixed_TPC_FV0", "", {HistType::kTH2D, {axisChannelFt0aAxis, axisAmplitudeFt0a}}); + registry.add("Trig_hist_TPC_FV0", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisEtaTrigger}}}); + registry.add("FV0Amp", "", {HistType::kTH2F, {axisChID, axisFit}}); + } registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event LOGF(info, "Initializing correlation container"); - std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, - {axisVertex, "z-vtx (cm)"}, - {axisEtaTrigger, "#eta"}, - {axisEtaAssoc, "#eta"}, - {axisDeltaPhi, "#Delta#varphi (rad)"}, - {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; std::vector effAxis = { {axisEtaEfficiency, "#eta"}, {axisPtEfficiency, "p_{T} (GeV/c)"}, {axisVertexEfficiency, "z-vtx (cm)"}, }; std::vector userAxis; + + std::vector corrAxisTpcFt0a = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFt0a, "#Delta#eta"}}; + std::vector corrAxisTpcFt0c = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisEtaTrigger, "#eta"}, {axisEtaAssoc, "#eta"}, {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaTpcFt0c, "#Delta#eta"}}; + std::vector corrAxisFt0aFt0c = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisEtaTrigger, "#eta"}, @@ -393,22 +426,109 @@ struct FlowDecorrelation { {axisDeltaPhi, "#Delta#varphi (rad)"}, {axisDeltaEtaFt0aFt0c, "#Delta#eta"}}; + std::vector corrAxisTpcMft = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcMft, "#Delta#eta"}}; + + std::vector corrAxisTpcFv0 = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisEtaTrigger, "#eta"}, + {axisEtaAssoc, "#eta"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisDeltaEtaTpcFv0, "#Delta#eta"}}; + if (doprocessSameTpcFt0a) { - sameTpcFt0a.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); - mixedTpcFt0a.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + same.setObject(new CorrelationContainer("sameEvent_TPC_FT0A", "sameEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0A", "mixedEvent_TPC_FT0A", corrAxisTpcFt0a, effAxis, userAxis)); } if (doprocessSameTpcFt0c) { - sameTpcFt0c.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); - mixedTpcFt0c.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + same.setObject(new CorrelationContainer("sameEvent_TPC_FT0C", "sameEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FT0C", "mixedEvent_TPC_FT0C", corrAxisTpcFt0c, effAxis, userAxis)); } if (doprocessSameFt0aFt0c) { - sameFt0aFt0c.setObject(new CorrelationContainer("sameEvent_FT0A_FT0C", "sameEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); - mixedFt0aFt0c.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + same.setObject(new CorrelationContainer("sameEvent_FT0A_FT0C", "sameEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); + } + if (doprocessSameTpcMft) { + same.setObject(new CorrelationContainer("sameEvent_TPC_MFT", "sameEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_MFT", "mixedEvent_TPC_MFT", corrAxisTpcMft, effAxis, userAxis)); + } + if (doprocessSameTpcFv0) { + same.setObject(new CorrelationContainer("sameEvent_TPC_FV0", "sameEvent_TPC_FV0", corrAxisTpcFv0, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FV0", "mixedEvent_TPC_FV0", corrAxisTpcFv0, effAxis, userAxis)); + } + if (doprocessMcSameTpcFt0c) { + same.setObject(new CorrelationContainer("sameEvent_TPC_FV0", "sameEvent_TPC_FV0", corrAxisTpcFt0c, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent_TPC_FV0", "mixedEvent_TPC_FV0", corrAxisTpcFt0c, effAxis, userAxis)); } - LOGF(info, "End of init"); } + template + bool isAcceptedMftTrack(TTrackAssoc const& mftTrack) + { + // cut on the number of clusters of the reconstructed MFT track + if (mftTrack.nClusters() < cfgMftCuts.nClustersMftTrack) + return false; + + if (cfgMftCuts.cfgCutChi2Mft > 0. && mftTrack.chi2() > cfgMftCuts.cfgCutChi2Mft) + return false; + + if (cfgMftCuts.cfgCutTrackTimeMft > 0. && std::abs(mftTrack.trackTime()) > cfgMftCuts.cfgCutTrackTimeMft) + return false; + + return true; + } + + double getPhiFV0(uint64_t chno) + { + o2::fv0::Point3Dsimple chPos{}; + int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + if (isChnoInLeft) { + chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + (*offsetFV0)[0].getX(), chPos.y + (*offsetFV0)[0].getY()); + } else { + chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + (*offsetFV0)[1].getX(), chPos.y + (*offsetFV0)[1].getY()); + } + } + + double getEtaFV0(uint64_t chno) + { + + int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; + bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + o2::fv0::Point3Dsimple chPos{}; + chPos = fv0Det->getReadoutCenter(chno); + + float offsetX, offsetY, offsetZ; + + if (isChnoInLeft) { + offsetX = (*offsetFV0)[0].getX(); + offsetY = (*offsetFV0)[0].getY(); + offsetZ = (*offsetFV0)[0].getZ(); + } else { + offsetX = (*offsetFV0)[1].getX(); + offsetY = (*offsetFV0)[1].getY(); + offsetZ = (*offsetFV0)[1].getZ(); + } + + auto x = chPos.x + offsetX; + auto y = chPos.y + offsetY; + auto z = chPos.z + offsetZ; + + auto r = std::sqrt(x * x + y * y); + auto theta = std::atan2(r, z); + + return -std::log(std::tan(0.5 * theta)); + } + double getPhiFT0(uint64_t chno, int i) { // offsetFT0[0]: FT0A, offsetFT0[1]: FT0C @@ -468,64 +588,16 @@ struct FlowDecorrelation { return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); } - template - int getNsigmaPID(TTrack track) - { - // Computing Nsigma arrays for pion, kaon, and protons - std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; - std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; - std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; - int pid = -1; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton - - std::array nSigmaToUse = cfgPIDConfig.cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS - std::array detectorNsigmaCut = cfgPIDConfig.cfgUseItsPID ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS - - bool isPion = false; - bool isKaon = false; - bool isProton = false; - bool isDetectedPion = nSigmaToUse[kPionUp] < detectorNsigmaCut[kPionUp] && nSigmaToUse[kPionUp] > detectorNsigmaCut[kPionLow]; - bool isDetectedKaon = nSigmaToUse[kKaonUp] < detectorNsigmaCut[kKaonUp] && nSigmaToUse[kKaonUp] > detectorNsigmaCut[kKaonLow]; - bool isDetectedProton = nSigmaToUse[kProtonUp] < detectorNsigmaCut[kProtonUp] && nSigmaToUse[kProtonUp] > detectorNsigmaCut[kProtonLow]; - - bool isTofPion = nSigmaTOF[kPionUp] < tofNsigmaCut[kPionUp] && nSigmaTOF[kPionUp] > tofNsigmaCut[kPionLow]; - bool isTofKaon = nSigmaTOF[kKaonUp] < tofNsigmaCut[kKaonUp] && nSigmaTOF[kKaonUp] > tofNsigmaCut[kKaonLow]; - bool isTofProton = nSigmaTOF[kProtonUp] < tofNsigmaCut[kProtonUp] && nSigmaTOF[kProtonUp] > tofNsigmaCut[kProtonLow]; - - if (track.pt() > cfgPIDConfig.cfgTofPtCut && !track.hasTOF()) { - return -1; - } else if (track.pt() > cfgPIDConfig.cfgTofPtCut && track.hasTOF()) { - isPion = isTofPion && isDetectedPion; - isKaon = isTofKaon && isDetectedKaon; - isProton = isTofProton && isDetectedProton; - } else { - isPion = isDetectedPion; - isKaon = isDetectedKaon; - isProton = isDetectedProton; - } - - if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { - return -1; // more than one particle satisfy the criteria - } - - if (isPion) { - pid = kPions; - } else if (isKaon) { - pid = kKaons; - } else if (isProton) { - pid = kProtons; - } else { - return -1; // no particle satisfies the criteria - } - - return pid; // -1 = not identified, 1 = pion, 2 = kaon, 3 = proton - } - void loadAlignParam(uint64_t timestamp) { offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", timestamp); + offsetFV0 = ccdb->getForTimeStamp>("FV0/Calib/Align", timestamp); if (offsetFT0 == nullptr) { LOGF(fatal, "Could not load FT0/Calib/Align for timestamp %d", timestamp); } + if (offsetFV0 == nullptr) { + LOGF(fatal, "Could not load FV0/Calib/Align for timestamp %d", timestamp); + } } void loadGain(aod::BCsWithTimestamps::iterator const& bc) @@ -625,6 +697,8 @@ struct FlowDecorrelation { registry.fill(HIST("Phi"), RecoDecay::constrainAngle(track1.phi(), 0.0)); registry.fill(HIST("Eta"), track1.eta()); registry.fill(HIST("EtaCorrected"), track1.eta(), weff1); + registry.fill(HIST("pT"), track1.pt()); + registry.fill(HIST("pTCorrected"), track1.pt(), weff1); } } @@ -636,21 +710,29 @@ struct FlowDecorrelation { id = id + Ft0IndexA; ampl = ft0.amplitudeC()[iCh]; registry.fill(HIST("FT0Amp"), id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; + ampl = ampl / cstFT0RelGain[id]; registry.fill(HIST("FT0AmpCorrect"), id, ampl); } else if (fitType == kFT0A) { id = ft0.channelA()[iCh]; ampl = ft0.amplitudeA()[iCh]; registry.fill(HIST("FT0Amp"), id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; + ampl = ampl / cstFT0RelGain[id]; registry.fill(HIST("FT0AmpCorrect"), id, ampl); } else { LOGF(fatal, "Cor Index %d out of range", fitType); } } + template + void getChannelFV0(TFT0s const& fv0, std::size_t const& iCh, int& id, float& ampl) + { + id = fv0.channel()[iCh]; + ampl = fv0.amplitude()[iCh]; + registry.fill(HIST("FV0Amp"), id, ampl); + } + template - void fillCorrelationsTPCFT0(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelationsTPCFIT(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { if (system == SameEvent) { if (!cfgCentTableUnavailable) @@ -666,35 +748,41 @@ struct FlowDecorrelation { if (!trackSelected(track1)) continue; - if (cfgPIDConfig.cfgPIDParticle && getNsigmaPID(track1) != cfgPIDConfig.cfgPIDParticle) - continue; // if PID is selected, check if the track has the right PID if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { - if (corType == kFT0C) { + if (corType == kFT0C) registry.fill(HIST("Trig_hist_TPC_FT0C"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); - } else if (corType == kFT0A) { + else if (corType == kFT0A) registry.fill(HIST("Trig_hist_TPC_FT0A"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); - } - if (cfgDrawEtaPhiDis && corType == kFT0A) { + if (cfgDrawEtaPhiDis && corType == kFT0A) registry.fill(HIST("EtaPhi"), track1.eta(), track1.phi(), eventWeight * triggerWeight); - } } std::size_t channelSize = 0; - if (corType == kFT0C) { - channelSize = ft0.channelC().size(); - } else if (corType == kFT0A) { + if (corType == kFT0A) channelSize = ft0.channelA().size(); - } else { + else if (corType == kFT0C) + channelSize = ft0.channelC().size(); + else LOGF(fatal, "Cor Index %d out of range", corType); - } + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { int chanelid = 0; float ampl = 0.; getChannel(ft0, iCh, chanelid, ampl, corType); - auto phi = getPhiFT0(chanelid, corType); - auto eta = getEtaFT0(chanelid, corType); + if (corType == kFT0C) { + if ((cfgFt0RingRejections.cfgRejectFT0CInside && (chanelid >= kFT0CInnerRingMin && chanelid <= kFT0CInnerRingMax)) || (cfgFt0RingRejections.cfgRejectFT0COutside && (chanelid >= kFT0COuterRingMin && chanelid <= kFT0COuterRingMax))) { + continue; + } + } else if (corType == kFT0A) { + if ((cfgFt0RingRejections.cfgRejectFT0AInside && (chanelid >= kFT0AInnerRingMin && chanelid <= kFT0AInnerRingMax)) || (cfgFt0RingRejections.cfgRejectFT0AOutside && (chanelid >= kFT0AOuterRingMin && chanelid <= kFT0AOuterRingMax))) { + continue; + } + } + double phi = getPhiFT0(chanelid, corType); + double eta = getEtaFT0(chanelid, corType); + if (cfgDrawEtaPhiDis && system == SameEvent) { registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); } @@ -704,21 +792,21 @@ struct FlowDecorrelation { if (system == SameEvent) { if (corType == kFT0A) { registry.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); - sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { registry.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); - sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } else if (system == MixedEvent) { if (corType == kFT0A) { registry.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); - mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { registry.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); - mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } @@ -727,41 +815,107 @@ struct FlowDecorrelation { } template - void fillCorrelationsFT0AFT0C(TFT0s const& ft0Col1, TFT0s const& ft0Col2, float posZ, int system, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelationsFT0AFT0C(TFT0s const& ft0Trig, TFT0s const& ft0Assoc, float posZ, int multTrk, int system, float cent, float eventWeight) { + if (system == SameEvent) { + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), multTrk); + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + for (std::size_t iChA = 0; iChA < ft0Trig.channelA().size(); iChA++) { + int channelIdA = 0; + float amplA = 0.f; + getChannel(ft0Trig, iChA, channelIdA, amplA, kFT0A); + if ((cfgFt0RingRejections.cfgRejectFT0AInside && (channelIdA >= kFT0AInnerRingMin && channelIdA <= kFT0AInnerRingMax)) || (cfgFt0RingRejections.cfgRejectFT0AOutside && (channelIdA >= kFT0AOuterRingMin && channelIdA <= kFT0AOuterRingMax))) { + continue; + } + + const double phiA = getPhiFT0(channelIdA, kFT0A); + const double etaA = getEtaFT0(channelIdA, kFT0A); + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist_FT0A_FT0C"), fSampleIndex, posZ, etaA, eventWeight * amplA); + } + + for (std::size_t iChC = 0; iChC < ft0Assoc.channelC().size(); iChC++) { + int channelIdC = 0; + float amplC = 0.f; + getChannel(ft0Assoc, iChC, channelIdC, amplC, kFT0C); + if ((cfgFt0RingRejections.cfgRejectFT0CInside && (channelIdC >= kFT0CInnerRingMin && channelIdC <= kFT0CInnerRingMax)) || (cfgFt0RingRejections.cfgRejectFT0COutside && (channelIdC >= kFT0COuterRingMin && channelIdC <= kFT0COuterRingMax))) { + continue; + } + + const double phiC = getPhiFT0(channelIdC, kFT0C); + const double etaC = getEtaFT0(channelIdC, kFT0C); + + const float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); + const float deltaEta = etaA - etaC; + const float pairWeight = amplA * amplC * eventWeight; + + if (system == SameEvent) { + registry.fill(HIST("Assoc_amp_same_FT0A_FT0C"), channelIdC, amplC); + same->getPairHist()->Fill(step, fSampleIndex, posZ, etaA, etaC, deltaPhi, deltaEta, pairWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_FT0A_FT0C"), deltaPhi, deltaEta, pairWeight); + } else if (system == MixedEvent) { + registry.fill(HIST("Assoc_amp_mixed_FT0A_FT0C"), channelIdC, amplC); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, etaA, etaC, deltaPhi, deltaEta, pairWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed_FT0A_FT0C"), deltaPhi, deltaEta, pairWeight); + } + } + } + } + + template + void fillCorrelationsTPCFV0(TTracks tracks1, TFT0s const& fv0, float posZ, int system, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + if (system == SameEvent) { + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), tracks1.size()); + } + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); float triggerWeight = 1.0f; - std::size_t channelASize = ft0Col1.channelA().size(); - std::size_t channelCSize = ft0Col2.channelC().size(); // loop over all tracks - for (std::size_t iChA = 0; iChA < channelASize; iChA++) { - - int chanelAid = 0; - float amplA = 0.; - getChannel(ft0Col1, iChA, chanelAid, amplA, kFT0A); - auto phiA = getPhiFT0(chanelAid, kFT0A); - auto etaA = getEtaFT0(chanelAid, kFT0A); + for (auto const& track1 : tracks1) { + if (!trackSelected(track1)) + continue; + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; if (system == SameEvent) { - registry.fill(HIST("Trig_hist_FT0A_FT0C"), fSampleIndex, posZ, 0.5, eventWeight * amplA); + registry.fill(HIST("Trig_hist_TPC_FV0"), fSampleIndex, posZ, track1.eta(), eventWeight * triggerWeight); } - for (std::size_t iChC = 0; iChC < channelCSize; iChC++) { - int chanelCid = 0; - float amplC = 0.; - getChannel(ft0Col2, iChC, chanelCid, amplC, kFT0C); - auto phiC = getPhiFT0(chanelCid, kFT0C); - auto etaC = getEtaFT0(chanelCid, kFT0C); - float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); - float deltaEta = etaA - etaC; + std::size_t channelSize = 0; + channelSize = fv0.channel().size(); + + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int chanelid = 0; + float ampl = 0.; + getChannelFV0(fv0, iCh, chanelid, ampl); + + double phi = getPhiFV0(chanelid); + double eta = getEtaFV0(chanelid); + + if (cfgDrawEtaPhiDis && system == SameEvent) { + registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); + } + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - phi, -PIHalf); + float deltaEta = track1.eta() - eta; // fill the right sparse and histograms if (system == SameEvent) { - sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); - registry.fill(HIST("deltaEta_deltaPhi_same_FT0A_FT0C"), deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + registry.fill(HIST("Assoc_amp_same_TPC_FV0"), chanelid, ampl); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FV0"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } else if (system == MixedEvent) { - mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); - registry.fill(HIST("deltaEta_deltaPhi_mixed_FT0A_FT0C"), deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + registry.fill(HIST("Assoc_amp_mixed_TPC_FV0"), chanelid, ampl); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), eta, deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FV0"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); } } } @@ -808,23 +962,29 @@ struct FlowDecorrelation { } if (fillCounter && cfgEvSelkIsGoodITSLayersAll) registry.fill(HIST("hEventCountSpecific"), 6.5); + if (cfgEvSelkIsGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // for pp: cut time intervals with dead ITS staves on layers 0-3 only + return 0; + } + if (fillCounter && cfgEvSelkIsGoodITSLayer0123) + registry.fill(HIST("hEventCountSpecific"), 7.5); if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { // no other collisions in this Readout Frame with per-collision multiplicity above threshold return 0; } if (fillCounter && cfgEvSelkNoCollInRofStandard) - registry.fill(HIST("hEventCountSpecific"), 7.5); + registry.fill(HIST("hEventCountSpecific"), 8.5); if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { // veto an event if FT0C amplitude in previous ITS ROF is above threshold return 0; } if (fillCounter && cfgEvSelkNoHighMultCollInPrevRof) - registry.fill(HIST("hEventCountSpecific"), 8.5); + registry.fill(HIST("hEventCountSpecific"), 9.5); auto occupancy = collision.trackOccupancyInTimeRange(); if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) return 0; if (fillCounter && cfgEvSelOccupancy) - registry.fill(HIST("hEventCountSpecific"), 9.5); + registry.fill(HIST("hEventCountSpecific"), 10.5); auto multNTracksPV = collision.multNTracksPV(); if (cfgEvSelMultCorrelation) { @@ -854,18 +1014,36 @@ struct FlowDecorrelation { } } if (fillCounter && cfgEvSelMultCorrelation) - registry.fill(HIST("hEventCountSpecific"), 10.5); + registry.fill(HIST("hEventCountSpecific"), 11.5); // V0A T0A 5 sigma cut float sigma = 5.0; if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (fillCounter && cfgEvSelV0AT0ACut) - registry.fill(HIST("hEventCountSpecific"), 11.5); + registry.fill(HIST("hEventCountSpecific"), 12.5); return 1; } + bool ft0cCollisionCourse(float eta, float phi, float vtxZ) + { + double theta = 2 * std::atan(std::exp(-eta)); + double vx = std::sin(theta) * std::cos(phi); // veloctiy component along x + double vy = std::sin(theta) * std::sin(phi); // veloctiy component along y + double vz = std::cos(theta); // veloctiy component along z + + double x = vx * ((-83.44 - vtxZ) / vz); // location of particle on x at FT0C distance from vertex + double y = vy * ((-83.44 - vtxZ) / vz); // location of particle on x at FT0C distance from vertex + + if (std::abs(x) < 24 && (std::abs(y) > 6.825 && std::abs(y) < 18.25)) + return true; + else if (std::abs(y) < 24 && (std::abs(x) > 6.675 && std::abs(x) < 18.175)) + return true; + else + return false; + } + void processSameTpcFt0a(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) { if (!collision.sel8()) @@ -901,9 +1079,9 @@ struct FlowDecorrelation { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); - sameTpcFt0a->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); const auto& ft0 = collision.foundFT0(); - fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, kFT0A, cent, weightCent); + fillCorrelationsTPCFIT(tracks, ft0, collision.posZ(), SameEvent, kFT0A, cent, weightCent); } PROCESS_SWITCH(FlowDecorrelation, processSameTpcFt0a, "Process same event for TPC-FT0 correlation", true); @@ -966,7 +1144,7 @@ struct FlowDecorrelation { if (!cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0 = collision2.foundFT0(); - fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0A, cent1, eventWeight * weightCent); + fillCorrelationsTPCFIT(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0A, cent1, eventWeight * weightCent); } } PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFt0a, "Process mixed events for TPC-FT0A correlation", true); @@ -1006,9 +1184,9 @@ struct FlowDecorrelation { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); - sameTpcFt0c->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); const auto& ft0 = collision.foundFT0(); - fillCorrelationsTPCFT0(tracks, ft0, collision.posZ(), SameEvent, kFT0C, cent, weightCent); + fillCorrelationsTPCFIT(tracks, ft0, collision.posZ(), SameEvent, kFT0C, cent, weightCent); } PROCESS_SWITCH(FlowDecorrelation, processSameTpcFt0c, "Process same event for TPC-FT0C correlation", false); @@ -1071,7 +1249,7 @@ struct FlowDecorrelation { if (!cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); const auto& ft0 = collision2.foundFT0(); - fillCorrelationsTPCFT0(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0C, cent1, eventWeight * weightCent); + fillCorrelationsTPCFIT(tracks1, ft0, collision1.posZ(), MixedEvent, kFT0C, cent1, eventWeight * weightCent); } } PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFt0c, "Process mixed events for TPC-FT0C correlation", false); @@ -1093,8 +1271,14 @@ struct FlowDecorrelation { loadAlignParam(bc.timestamp()); loadGain(bc); loadCorrection(bc.timestamp()); + if (!cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); - // should have the same event to TPC-FT0A/C correlations if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { return; } @@ -1102,16 +1286,167 @@ struct FlowDecorrelation { return; } - sameFt0aFt0c->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + registry.fill(HIST("eventcount"), SameEvent); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); const auto& ft0 = collision.foundFT0(); - fillCorrelationsFT0AFT0C(ft0, ft0, collision.posZ(), SameEvent, weightCent); + fillCorrelationsFT0AFT0C(ft0, ft0, collision.posZ(), tracks.size(), SameEvent, cent, weightCent); } PROCESS_SWITCH(FlowDecorrelation, processSameFt0aFt0c, "Process same event for FT0A-FT0C correlation", false); - // the process for filling the mixed events void processMixedFt0aFt0c(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FT0s const&, aod::BCsWithTimestamps const&) { + auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + float cent1 = -1; + float cent2 = -1; + if (!cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + continue; + + if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + continue; + + registry.fill(HIST("eventcount"), MixedEvent); + auto bc = collision1.bc_as(); + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + loadGain(bc); + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + const auto& ft0Trig = collision1.foundFT0(); + const auto& ft0Assoc = collision2.foundFT0(); + fillCorrelationsFT0AFT0C(ft0Trig, ft0Assoc, collision1.posZ(), tracks1.size(), MixedEvent, cent1, eventWeight * weightCent); + } + } + PROCESS_SWITCH(FlowDecorrelation, processMixedFt0aFt0c, "Process mixed events for FT0A-FT0C correlation", false); + + template + void fillCorrelationsTPCMFT(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + if (system == SameEvent) { + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality_used"), cent); + registry.fill(HIST("Nch_used"), tracks1.size()); + } + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + // loop over all tracks + for (auto const& track1 : tracks1) { + + if (!trackSelected(track1)) + continue; + if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) + continue; + + if (system == SameEvent) { + registry.fill(HIST("Trig_hist_TPC_MFT"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); + } + + for (auto const& track2 : tracks2) { + + if (!isAcceptedMftTrack(track2)) + continue; + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); + float deltaEta = track1.eta() - track2.eta(); + + if (system == SameEvent) { + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_same_TPC_MFT"), deltaPhi, deltaEta, eventWeight * triggerWeight); + } else if (system == MixedEvent) { + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.eta(), track2.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_MFT"), deltaPhi, deltaEta, eventWeight * triggerWeight); + } + } + } + } + + void processSameTpcMft(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::MFTTracks const& mfts, aod::BCsWithTimestamps const&) + { + float cent = -1.; + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + + if (!collision.sel8()) + return; + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + return; + + auto bc = collision.bc_as(); + loadAlignParam(bc.timestamp()); + + loadGain(bc); + loadCorrection(bc.timestamp()); + + if (!cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + + fillYield(collision, tracks); + + fillCorrelationsTPCMFT(tracks, mfts, collision.posZ(), SameEvent, cent, weightCent); + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + } + PROCESS_SWITCH(FlowDecorrelation, processSameTpcMft, "Process same events for TPC-MFT correlation", false); + + void processMixedTpcMft(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::MFTTracks const& MFTtracks, aod::BCsWithTimestamps const&) + { auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); auto mult = associatedTracks.size(); @@ -1124,18 +1459,24 @@ struct FlowDecorrelation { auto tracksTuple = std::make_tuple(tracks, tracks); Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { auto& [collision1, tracks1, collision2, tracks2] = *it; - // should have the same event to TPC-FT0A/C correlations if (!collision1.sel8() || !collision2.sel8()) continue; if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) continue; if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) continue; + float cent1 = -1; float cent2 = -1; + + if (!cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } if (!cfgCentTableUnavailable) { cent1 = getCentrality(collision1); cent2 = getCentrality(collision2); @@ -1144,14 +1485,125 @@ struct FlowDecorrelation { continue; if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) continue; + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) continue; if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) continue; - if (!(collision1.has_foundFT0() && collision2.has_foundFT0())) + registry.fill(HIST("eventcount"), MixedEvent); + + auto bc = collision1.bc_as(); + + loadAlignParam(bc.timestamp()); + loadCorrection(bc.timestamp()); + + float eventWeight = 1.0f; + + if (cfgUseEventWeights) + eventWeight = 1.0f / it.currentWindowNeighbours(); + + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) + getCentralityWeight(weightCent, cent1); + + auto mftTracks2 = MFTtracks.sliceByCached(o2::aod::fwdtrack::collisionId, collision2.globalIndex(), cache); + + fillCorrelationsTPCMFT(tracks1, mftTracks2, collision1.posZ(), MixedEvent, 10., eventWeight * weightCent); + } + } + PROCESS_SWITCH(FlowDecorrelation, processMixedTpcMft, "Process same events for TPC-MFT correlation", false); + + void processSameTpcFv0(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::FV0As const&, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + float cent = -1.; + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) { + cent = getCentrality(collision); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + return; + if (!collision.has_foundFV0()) + return; + loadAlignParam(bc.timestamp()); + loadGain(bc); + loadCorrection(bc.timestamp()); + + if (!cfgCentTableUnavailable) { + getCentralityWeight(weightCent, cent); + registry.fill(HIST("Centrality"), cent); + registry.fill(HIST("CentralityWeighted"), cent, weightCent); + } + registry.fill(HIST("Nch"), tracks.size()); + registry.fill(HIST("zVtx"), collision.posZ()); + + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + fillYield(collision, tracks); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + + same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); + const auto& fv0 = collision.foundFV0(); + fillCorrelationsTPCFV0(tracks, fv0, collision.posZ(), SameEvent, cent, weightCent); + } + PROCESS_SWITCH(FlowDecorrelation, processSameTpcFv0, "Process same events for TPC-FV0 correlation", false); + + void processMixedTpcFv0(FilteredCollisions const& collisions, FilteredTracks const& tracks, aod::FV0As const&, aod::BCsWithTimestamps const&) + { + auto getTracksSize = [&tracks, this](FilteredCollisions::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(tracks, tracks); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + if (!collision1.sel8() || !collision2.sel8()) + continue; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) continue; + float cent1 = -1; + float cent2 = -1; + if (!cfgCentTableUnavailable) { + cent1 = getCentrality(collision1); + cent2 = getCentrality(collision2); + } + if (cfgUseAdditionalEventCut && !eventSelected(collision1, tracks1.size(), cent1, false)) + continue; + if (cfgUseAdditionalEventCut && !eventSelected(collision2, tracks2.size(), cent2, false)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent1 < cfgCutCentMin || cent1 >= cfgCutCentMax)) + continue; + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent2 < cfgCutCentMin || cent2 >= cfgCutCentMax)) + continue; + + if (!(collision1.has_foundFV0() && collision2.has_foundFV0())) + continue; + + registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin auto bc = collision1.bc_as(); loadAlignParam(bc.timestamp()); loadCorrection(bc.timestamp()); @@ -1162,12 +1614,154 @@ struct FlowDecorrelation { float weightCent = 1.0f; if (!cfgCentTableUnavailable) getCentralityWeight(weightCent, cent1); - const auto& ft0Col1 = collision1.foundFT0(); - const auto& ft0Col2 = collision2.foundFT0(); - fillCorrelationsFT0AFT0C(ft0Col1, ft0Col2, collision1.posZ(), MixedEvent, eventWeight * weightCent); + const auto& fv0 = collision2.foundFV0(); + fillCorrelationsTPCFV0(tracks1, fv0, collision1.posZ(), MixedEvent, cent1, eventWeight * weightCent); } } - PROCESS_SWITCH(FlowDecorrelation, processMixedFt0aFt0c, "Process mixed events for FT0A-FT0C correlation", false); + PROCESS_SWITCH(FlowDecorrelation, processMixedTpcFv0, "Process mixed events for TPC-FV0 correlation", false); + + template + void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + + float triggerWeight = 1.0f; + float associatedWeight = 1.0f; + // loop over all FT0C tracks + for (auto const& track1 : tracks1) { + + if (!cfgMcTrue.cfgUseFt0cStructure) { + if (std::abs(track1.eta()) < 0.9) + continue; + } else if (!ft0cCollisionCourse(track1.eta(), track1.phi(), posZ)) { + continue; + } + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track1.isPhysicalPrimary()) + continue; + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && system == SameEvent) + registry.fill(HIST("MCTrue/MCEtaTrueShape"), track1.eta()); + + if (system == SameEvent && doprocessMcSameTpcFt0c) + registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); + + // loop over all TPC tracks + for (auto const& track2 : tracks2) { + + if (std::abs(track2.eta()) > 0.9) + continue; + + if (step >= CorrelationContainer::kCFStepTrackedOnlyPrim && !track2.isPhysicalPrimary()) + continue; + + if (track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + + float deltaPhi = RecoDecay::constrainAngle(track2.phi() - track1.phi(), -PIHalf); + float deltaEta = track2.eta() - track1.eta(); + + // fill the right sparse and histograms + if (system == SameEvent) { + same->getPairHist()->Fill(step, fSampleIndex, posZ, track2.eta(), track1.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } else if (system == MixedEvent) { + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track2.eta(), track1.eta(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + } + } + } + } + + void processMcSameTpcFt0c(FilteredMcCollisions::iterator const& mcCollision, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + float cent = -1; + if (!cfgCentTableUnavailable) { + for (const auto& collision : collisions) { + cent = getCentrality(collision); + } + } + + if (cfgSelCollByNch && (mcParticles.size() < cfgCutMultMin || mcParticles.size() >= cfgCutMultMax)) { + return; + } + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) { + return; + } + + registry.fill(HIST("MCTrue/MCeventcount"), SameEvent); // because its same event i put it in the 1 bin + if (!cfgCentTableUnavailable) + registry.fill(HIST("MCTrue/MCCentrality"), cent); + registry.fill(HIST("MCTrue/MCNch"), mcParticles.size()); + registry.fill(HIST("MCTrue/MCzVtx"), mcCollision.posZ()); + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCTrue/MCPhi"), mcParticle.phi()); + registry.fill(HIST("MCTrue/MCEta"), mcParticle.eta()); + registry.fill(HIST("MCTrue/MCpT"), mcParticle.pt()); + } + } + if (cfgMcTrue.cfgUseCFStepAll) { + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + } + + registry.fill(HIST("MCTrue/MCeventcount"), 2.5); + same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); + } + PROCESS_SWITCH(FlowDecorrelation, processMcSameTpcFt0c, "Process MC same event", false); + + void processMcMixed(FilteredMcCollisions const& mcCollisions, FilteredMcParticles const& mcParticles, SmallGroupMcCollisions const& collisions) + { + auto getTracksSize = [&mcParticles, this](FilteredMcCollisions::iterator const& mcCollision) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), this->cache); + auto mult = associatedTracks.size(); + return mult; + }; + + using MixedBinning = FlexibleBinningPolicy, o2::aod::mccollision::PosZ, decltype(getTracksSize)>; + + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairs{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + if (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) + continue; + + if (cfgSelCollByNch && (tracks2.size() < cfgCutMultMin || tracks2.size() >= cfgCutMultMax)) + continue; + + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + + float cent = -1; + if (!cfgCentTableUnavailable) { + for (const auto& collision : groupedCollisions) { + cent = getCentrality(collision); + } + } + + if (!cfgSelCollByNch && !cfgCentTableUnavailable && (cent < cfgCutCentMin || cent >= cfgCutCentMax)) + continue; + + registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + + if (cfgMcTrue.cfgUseCFStepAll) { + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + } + + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); + } + } + PROCESS_SWITCH(FlowDecorrelation, processMcMixed, "Process MC mixed events", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx index df89d74512b..e0eefb67fad 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaSpinPolarization.cxx @@ -1634,16 +1634,33 @@ struct LambdaSpinPolarization { float dphi = RecoDecay::constrainAngle(p1.phi() - p2.phi(), -PI); float dR = std::sqrt(drap * drap + dphi * dphi); - // Get Lambda-Proton four-momentum std::array l1 = {p1.px(), p1.py(), p1.pz(), MassLambda0}; std::array l2 = {p2.px(), p2.py(), p2.pz(), MassLambda0}; + + std::array llpair = { + l1[0] + l2[0], + l1[1] + l2[1], + l1[2] + l2[2], + l1[3] + l2[3]}; + std::array pr1 = {p1.prPx(), p1.prPy(), p1.prPz(), MassProton}; std::array pr2 = {p2.prPx(), p2.prPy(), p2.prPz(), MassProton}; - std::array v1, v2; - getBoostVector(l1, v1, cInvBoostFlag); - getBoostVector(l2, v2, cInvBoostFlag); - boost(pr1, v1); - boost(pr2, v2); + + std::array vPair; + getBoostVector(llpair, vPair, cInvBoostFlag); + + boost(l1, vPair); + boost(l2, vPair); + + boost(pr1, vPair); + boost(pr2, vPair); + + std::array v1_pair, v2_pair; + getBoostVector(l1, v1_pair, cInvBoostFlag); + getBoostVector(l2, v2_pair, cInvBoostFlag); + + boost(pr1, v1_pair); + boost(pr2, v2_pair); std::array pr1tv = {pr1[0], pr1[1], pr1[2]}; std::array pr2tv = {pr2[0], pr2[1], pr2[2]}; @@ -1676,7 +1693,7 @@ struct LambdaSpinPolarization { continue; } - // Kinematic matching with named constants + // Kinematic matching float deltaPt = std::abs(trk_1.pt() - trk_2.pt()); float deltaPhi = std::abs(RecoDecay::constrainAngle(trk_1.phi() - trk_2.phi(), -PI)); float deltaRap = std::abs(trk_1.rap() - trk_2.rap()); @@ -1718,7 +1735,7 @@ struct LambdaSpinPolarization { analyzePairs(antiLambdaTracks, antiLambdaTracks); } - PROCESS_SWITCH(LambdaSpinPolarization, processDataReco, "Process for Data and MCReco", false); + PROCESS_SWITCH(LambdaSpinPolarization, processDataReco, "Process for Data and MCReco", true); struct GetMultiplicity { float operator()(auto const& col) const @@ -1766,7 +1783,7 @@ struct LambdaSpinPolarization { } } - PROCESS_SWITCH(LambdaSpinPolarization, processDataRecoMixed, "Process for Data and MCReco for Mixed events", true); + PROCESS_SWITCH(LambdaSpinPolarization, processDataRecoMixed, "Process for Data and MCReco for Mixed events", false); void processDataRecoMixEvent(LambdaCollisions::iterator const& collision, LambdaTracks const& tracks) { diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx index 8ed7e03dce3..93210a7968b 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longRangeDihadronCor.cxx @@ -17,6 +17,7 @@ #include "PWGCF/Core/CorrelationContainer.h" #include "PWGCF/Core/PairCuts.h" #include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" #include "PWGCF/GenericFramework/Core/GFWCumulant.h" #include "PWGCF/GenericFramework/Core/GFWPowerArray.h" @@ -54,7 +55,10 @@ #include "TRandom3.h" #include +#include +#include #include +#include #include using namespace o2; @@ -64,7 +68,7 @@ using namespace o2::framework::expressions; // define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; // template for labelled array -static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; +static constexpr float LongArrayFloat[3][6] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3}}; struct LongRangeDihadronCor { Service ccdb; @@ -95,6 +99,7 @@ struct LongRangeDihadronCor { O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "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") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayer0123, bool, false, "cut time intervals with dead ITS staves (layers 0-3 only, for pp)") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") @@ -107,12 +112,6 @@ struct LongRangeDihadronCor { O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") O2_DEFINE_CONFIGURABLE(cfgDrawEtaPhiDis, bool, false, "draw eta-phi distribution for detectors in used") - O2_DEFINE_CONFIGURABLE(cfgRejectFT0AInside, bool, false, "Rejection of inner ring channels of the FT0A detector") - O2_DEFINE_CONFIGURABLE(cfgRejectFT0AOutside, bool, false, "Rejection of outer ring channels of the FT0A detector") - O2_DEFINE_CONFIGURABLE(cfgRejectFT0CInside, bool, false, "Rejection of inner ring channels of the FT0C detector") - O2_DEFINE_CONFIGURABLE(cfgRejectFT0COutside, bool, false, "Rejection of outer ring channels of the FT0C detector") - O2_DEFINE_CONFIGURABLE(cfgRemapFT0ADeadChannels, bool, false, "If true, remap FT0A channels 60-63 to amplitudes from 92-95 respectively") - O2_DEFINE_CONFIGURABLE(cfgRemapFT0CDeadChannels, bool, false, "If true, remap FT0C channels 177->145, 176->144, 178->146, 179->147, 139->115") struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); O2_DEFINE_CONFIGURABLE(cfgMultCentLowCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x - 3.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -147,8 +146,30 @@ struct LongRangeDihadronCor { O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") - Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"pos_pi", "pos_ka", "pos_pr", "neg_pi", "neg_ka", "neg_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; + Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"upCut_pi", "upCut_ka", "upCut_pr", "lowCut_pi", "lowCut_ka", "lowCut_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; } cfgPIDConfig; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(cfgRejectFT0AInside, bool, false, "Rejection of inner ring channels of the FT0A detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0AOutside, bool, false, "Rejection of outer ring channels of the FT0A detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0CInside, bool, false, "Rejection of inner ring channels of the FT0C detector") + O2_DEFINE_CONFIGURABLE(cfgRejectFT0COutside, bool, false, "Rejection of outer ring channels of the FT0C detector") + O2_DEFINE_CONFIGURABLE(cfgMirrorFT0ADeadChannels, bool, false, "If true, mirror FT0A channels 60-63 to amplitudes from 92-95 respectively") + O2_DEFINE_CONFIGURABLE(cfgMirrorFT0CDeadChannels, bool, false, "If true, mirror FT0C channels 177->145, 176->144, 178->146, 179->147, 139->115") + O2_DEFINE_CONFIGURABLE(cfgRunbyRunAmplitudeFT0, bool, false, "Produce run-by-run FT0 amplitude distribution"); + } cfgFwdConfig; + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(gfwOutput, bool, false, "produce cumulant results, off by default"); + O2_DEFINE_CONFIGURABLE(gfwNbootstrap, int, 30, "Number of subsamples") + O2_DEFINE_CONFIGURABLE(gfwAcceptance, std::string, "", "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(gfwUseNch, bool, false, "use multiplicity as x axis"); + ConfigurableAxis gfwAxisIndependent{"gfwAxisIndependent", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "X axis for histograms"}; + Configurable> gfwCorr{"gfwCorr", std::vector{"TPC {2} FT0A {-2}"}, "User defined GFW CorrelatorConfig"}; + Configurable> gfwName{"gfwName", std::vector{"TpcFt0A22"}, "User defined GFW Name"}; + GFW* fGFW = new GFW(); + std::vector corrconfigs; + TAxis* fPtAxis; + TRandom3* fRndm = new TRandom3(0); + } cfgCumulantConfig; SliceCache cache; @@ -191,6 +212,7 @@ struct LongRangeDihadronCor { // Corrections TH3D* mEfficiency = nullptr; TH1D* mCentralityWeight = nullptr; + GFWWeights* mAcceptance = nullptr; bool correctionsLoaded = false; // Define the outputs @@ -201,6 +223,8 @@ struct LongRangeDihadronCor { OutputObj sameFt0aFt0c{"sameEvent_FT0A_FT0C"}; OutputObj mixedFt0aFt0c{"mixedEvent_FT0A_FT0C"}; HistogramRegistry registry{"registry"}; + OutputObj fFC{FlowContainer("FlowContainer")}; + OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; // define global variables TRandom3* gRandom = new TRandom3(); @@ -252,22 +276,23 @@ struct LongRangeDihadronCor { kFT0COuterRingMin = 144, kFT0COuterRingMax = 207 }; - enum MirroringConstants { - kFT0AOuterMirror = 32, - kFT0AInnerMirror = 16, - kFT0COuterMirror = 32, - kFT0CInnerMirror = 24 - }; enum DeadChannels { - kFT0ARemapChannelStart = 92, - kFT0ARemapChannelEnd = 95, - kFT0CRemapChannelStart = 144, - kFT0CRemapChannelEnd = 147, - kFT0CRemapChannelInnerRing = 115 + kFT0AMirrorChannelStart = 92, + kFT0AMirrorChannelEnd = 95, + kFT0CMirrorChannelStart = 144, + kFT0CMirrorChannelEnd = 147, + kFT0CMirrorChannelInnerRing = 115 + }; + enum DataType { + kReco, + kGen }; std::array tofNsigmaCut; std::array itsNsigmaCut; std::array tpcNsigmaCut; + int lastRunNumber = -1; + std::vector runNumbers; + std::map> histAmpCorrectPerRun; // map of TH3 histograms for all runs void init(InitContext&) { @@ -309,7 +334,7 @@ struct LongRangeDihadronCor { // Event Counter if ((doprocessSameTpcFt0a || doprocessSameTpcFt0c || doprocessSameFt0aFt0c) && cfgUseAdditionalEventCut) { - registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{12, 0, 12}}}); + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{13, 0, 13}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kNoITSROFrameBorder"); @@ -317,11 +342,12 @@ struct LongRangeDihadronCor { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInTimeRangeStandard"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "occupancy"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "MultCorrelation"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "cfgEvSelV0AT0ACut"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "kIsGoodITSLayer0123"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "kNoCollInRofStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(11, "occupancy"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(12, "MultCorrelation"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(13, "cfgEvSelV0AT0ACut"); } if (cfgEvSelMultCorrelation) { @@ -437,9 +463,85 @@ struct LongRangeDihadronCor { mixedFt0aFt0c.setObject(new CorrelationContainer("mixedEvent_FT0A_FT0C", "mixedEvent_FT0A_FT0C", corrAxisFt0aFt0c, effAxis, userAxis)); } + if (cfgCumulantConfig.gfwOutput && doprocessSameTpcFt0a && doprocessSameTpcFt0c) { + LOGF(fatal, "If you enable gfwOutput, you can only enable processSameTpcFt0a or processSameTpcFt0c, NOT both."); + } + if (cfgCumulantConfig.gfwOutput) { + o2::framework::AxisSpec axis = axisPt; + int nPtBins = axis.binEdges.size() - 1; + double* ptBins = &(axis.binEdges)[0]; + cfgCumulantConfig.fPtAxis = new TAxis(nPtBins, ptBins); + + std::vector userDefineGFWCorr = cfgCumulantConfig.gfwCorr; + std::vector userDefineGFWName = cfgCumulantConfig.gfwName; + TObjArray* oba = new TObjArray(); + if (userDefineGFWName.size() != userDefineGFWCorr.size()) { + LOGF(fatal, "The GFWConfig names you provided are NOT matching with configurations. userDefineGFWName.size(): %d, userDefineGFWCorr.size(): %d", userDefineGFWName.size(), userDefineGFWCorr.size()); + } + LOGF(info, "User adding FlowContainer Array:"); + if (!userDefineGFWCorr.empty() && !userDefineGFWName.empty()) { + for (uint i = 0; i < userDefineGFWName.size(); i++) { + if (userDefineGFWCorr.at(i).find("poi") != std::string::npos) { + LOGF(info, "%d: pT-diff array %s", i, userDefineGFWName.at(i).c_str()); + for (auto iPt = 0; iPt < cfgCumulantConfig.fPtAxis->GetNbins(); iPt++) + oba->Add(new TNamed(Form("%s_pt_%i", userDefineGFWName.at(i).c_str(), iPt + 1), Form("%s_pTDiff", userDefineGFWName.at(i).c_str()))); + } else { + LOGF(info, "%d: %s", i, userDefineGFWName.at(i).c_str()); + oba->Add(new TNamed(userDefineGFWName.at(i).c_str(), userDefineGFWName.at(i).c_str())); + } + } + } + fFC->SetName("FlowContainer"); + fFC->SetXAxis(cfgCumulantConfig.fPtAxis); + fFC->Initialize(oba, cfgCumulantConfig.gfwAxisIndependent, cfgCumulantConfig.gfwNbootstrap); + fFCgen->SetName("FlowContainer_gen"); + fFCgen->SetXAxis(cfgCumulantConfig.fPtAxis); + fFCgen->Initialize(oba, cfgCumulantConfig.gfwAxisIndependent, cfgCumulantConfig.gfwNbootstrap); + + cfgCumulantConfig.fGFW->AddRegion("TPC", -0.8, 0.8, 1, 1); + cfgCumulantConfig.fGFW->AddRegion("TPCpoi", -0.8, 0.8, 1 + cfgCumulantConfig.fPtAxis->GetNbins(), 2); + cfgCumulantConfig.fGFW->AddRegion("TPCol", -0.8, 0.8, 1 + cfgCumulantConfig.fPtAxis->GetNbins(), 4); + cfgCumulantConfig.fGFW->AddRegion("FT0A", 3.5, 4.9, 1, 1); + cfgCumulantConfig.fGFW->AddRegion("FT0C", -3.3, -2.1, 1, 1); + cfgCumulantConfig.fGFW->AddRegion("FV0", 2.2, 5.1, 1, 1); + + if (!userDefineGFWCorr.empty() && !userDefineGFWName.empty()) { + LOGF(info, "User adding GFW CorrelatorConfig:"); + // attentaion: here we follow the index of cfgUserDefineGFWCorr + for (uint 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; + } + if (userDefineGFWCorr.at(i).find("poi") != std::string::npos) { + cfgCumulantConfig.corrconfigs.push_back(cfgCumulantConfig.fGFW->GetCorrelatorConfig(userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str(), kTRUE)); + LOGF(info, "corrconfigs.at(%d): enable pt-Diff for %s %s", cfgCumulantConfig.corrconfigs.size() - 1, userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str()); + } else { + cfgCumulantConfig.corrconfigs.push_back(cfgCumulantConfig.fGFW->GetCorrelatorConfig(userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str(), kFALSE)); + LOGF(info, "corrconfigs.at(%d): %s %s", cfgCumulantConfig.corrconfigs.size() - 1, userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str()); + } + } + } + + cfgCumulantConfig.fGFW->CreateRegions(); + } + LOGF(info, "End of init"); } + void createOutputObjectsForRun(int runNumber) + { + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0) { + if (histAmpCorrectPerRun.find(runNumber) != histAmpCorrectPerRun.end()) { + LOGF(info, "you are trying to create QA hist again, please make sure you are not filling it twice"); + } + const AxisSpec axisFit{1000, 0, 5000, "FIT amplitude"}; + const AxisSpec axisChID{220, 0, 220, "FIT channel"}; + std::shared_ptr histFT0AmpCorrect = registry.add(Form("%d/FT0AmpCorrect", runNumber), "FIT channel;FIT amplitude", {HistType::kTH2F, {axisChID, axisFit}}); + histAmpCorrectPerRun.insert(std::make_pair(runNumber, histFT0AmpCorrect)); + } + } + double getPhiFT0(uint64_t chno, int i) { // offsetFT0[0]: FT0A, offsetFT0[1]: FT0C @@ -609,6 +711,13 @@ struct LongRangeDihadronCor { } LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgCentralityWeight.value.c_str(), (void*)mCentralityWeight); } + if (cfgCumulantConfig.gfwOutput && cfgCumulantConfig.gfwAcceptance.value.empty() == false) { + mAcceptance = ccdb->getForTimeStamp(cfgCumulantConfig.gfwAcceptance, timestamp); + if (mAcceptance) + LOGF(info, "Loaded acceptance weights from %s (%p)", cfgCumulantConfig.gfwAcceptance.value.c_str(), (void*)mAcceptance); + else + LOGF(warning, "Could not load acceptance weights from %s (%p)", cfgCumulantConfig.gfwAcceptance.value.c_str(), (void*)mAcceptance); + } correctionsLoaded = true; } @@ -642,6 +751,80 @@ struct LongRangeDihadronCor { return true; } + bool getAcceptanceWeight(float& weight_nua, float phi, float eta, float vtxz) + { + if (mAcceptance) + weight_nua = mAcceptance->getNUA(phi, eta, vtxz); + else + weight_nua = 1; + return true; + } + + template + void fillProfile(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const double& cent) + { + double dnx, val; + dnx = cfgCumulantConfig.fGFW->Calculate(corrconf, 0, kTRUE).real(); + if (dnx == 0) + return; + if (!corrconf.pTDif) { + val = cfgCumulantConfig.fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; + if (std::fabs(val) < 1) + registry.fill(tarName, cent, val, dnx); + return; + } + return; + } + + template + void fillFC(const GFW::CorrConfig& corrconf, const double& cent, const double& rndm) + { + double dnx, val; + dnx = cfgCumulantConfig.fGFW->Calculate(corrconf, 0, kTRUE).real(); + if (!corrconf.pTDif) { + if (dnx == 0) + return; + val = cfgCumulantConfig.fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; + if (std::fabs(val) < 1) { + (dt == kGen) ? fFCgen->FillProfile(corrconf.Head.c_str(), cent, val, dnx, rndm) : fFC->FillProfile(corrconf.Head.c_str(), cent, val, dnx, rndm); + } + return; + } + for (auto i = 1; i <= cfgCumulantConfig.fPtAxis->GetNbins(); i++) { + dnx = cfgCumulantConfig.fGFW->Calculate(corrconf, i - 1, kTRUE).real(); + if (dnx == 0) + continue; + val = cfgCumulantConfig.fGFW->Calculate(corrconf, i - 1, kFALSE).real() / dnx; + if (std::fabs(val) < 1) { + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconf.Head.c_str(), i), cent, val, dnx, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconf.Head.c_str(), i), cent, val, dnx, rndm); + } + } + return; + } + + template + void fillGFWFT0(TFT0s const& ft0, int corType) + { + std::size_t channelSize = 0; + if (corType == kFT0C) { + channelSize = ft0.channelC().size(); + } else if (corType == kFT0A) { + channelSize = ft0.channelA().size(); + } else { + LOGF(fatal, "Cor Index %d out of range", corType); + } + for (std::size_t iCh = 0; iCh < channelSize; iCh++) { + int chanelid = 0; + float ampl = 0.; + getChannel(ft0, iCh, chanelid, ampl, corType, MixedEvent + 1); + auto phi = getPhiFT0(chanelid, corType); + auto eta = getEtaFT0(chanelid, corType); + for (float ihit = 0; ihit < ampl; ihit++) { + cfgCumulantConfig.fGFW->Fill(eta, 1, phi, 1., 1); + } + } + } + // fill multiple histograms template void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms. @@ -662,51 +845,55 @@ struct LongRangeDihadronCor { } template - void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType) + void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, float& ampl, int fitType, int system) { if (fitType == kFT0C) { id = ft0.channelC()[iCh]; id = id + Ft0IndexA; ampl = ft0.amplitudeC()[iCh]; - if (cfgRemapFT0CDeadChannels) { - if (id == kFT0CRemapChannelInnerRing) { - int dead_id = id + kFT0CInnerMirror; - registry.fill(HIST("FT0Amp"), dead_id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; - registry.fill(HIST("FT0AmpCorrect"), dead_id, ampl); - } else if (id >= kFT0CRemapChannelStart && id <= kFT0CRemapChannelEnd) { - int dead_id = id + kFT0COuterMirror; - registry.fill(HIST("FT0Amp"), dead_id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; - registry.fill(HIST("FT0AmpCorrect"), dead_id, ampl); - } - } - if ((cfgRejectFT0CInside && (id >= kFT0CInnerRingMin && id <= kFT0CInnerRingMax)) || (cfgRejectFT0COutside && (id >= kFT0COuterRingMin && id <= kFT0COuterRingMax))) + if ((cfgFwdConfig.cfgRejectFT0CInside && (id >= kFT0CInnerRingMin && id <= kFT0CInnerRingMax)) || (cfgFwdConfig.cfgRejectFT0COutside && (id >= kFT0COuterRingMin && id <= kFT0COuterRingMax))) ampl = 0.; - registry.fill(HIST("FT0Amp"), id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; - registry.fill(HIST("FT0AmpCorrect"), id, ampl); + if (system == SameEvent) + registry.fill(HIST("FT0Amp"), id, ampl); + ampl = ampl / cstFT0RelGain[id]; + if (system == SameEvent) { + registry.fill(HIST("FT0AmpCorrect"), id, ampl); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0) + histAmpCorrectPerRun[lastRunNumber]->Fill(id, ampl); + } } else if (fitType == kFT0A) { id = ft0.channelA()[iCh]; ampl = ft0.amplitudeA()[iCh]; - if (cfgRemapFT0ADeadChannels) { - if (id >= kFT0ARemapChannelStart && id <= kFT0ARemapChannelEnd) { - int dead_id = id - kFT0AOuterMirror; - registry.fill(HIST("FT0Amp"), dead_id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; - registry.fill(HIST("FT0AmpCorrect"), dead_id, ampl); - } - } - if ((cfgRejectFT0AInside && (id >= kFT0AInnerRingMin && id <= kFT0AInnerRingMax)) || (cfgRejectFT0AOutside && (id >= kFT0AOuterRingMin && id <= kFT0AOuterRingMax))) + if ((cfgFwdConfig.cfgRejectFT0AInside && (id >= kFT0AInnerRingMin && id <= kFT0AInnerRingMax)) || (cfgFwdConfig.cfgRejectFT0AOutside && (id >= kFT0AOuterRingMin && id <= kFT0AOuterRingMax))) ampl = 0.; - registry.fill(HIST("FT0Amp"), id, ampl); - ampl = ampl / cstFT0RelGain[iCh]; - registry.fill(HIST("FT0AmpCorrect"), id, ampl); + if (system == SameEvent) + registry.fill(HIST("FT0Amp"), id, ampl); + ampl = ampl / cstFT0RelGain[id]; + if (system == SameEvent) { + registry.fill(HIST("FT0AmpCorrect"), id, ampl); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0) + histAmpCorrectPerRun[lastRunNumber]->Fill(id, ampl); + } } else { LOGF(fatal, "Cor Index %d out of range", fitType); } } + bool isMirrorId(int id, int corType) + { + if (corType == kFT0A) { + if (id >= kFT0AMirrorChannelStart && id <= kFT0AMirrorChannelEnd) + return true; + } + if (corType == kFT0C) { + if (id == kFT0CMirrorChannelInnerRing) + return true; + else if (id >= kFT0CMirrorChannelStart && id <= kFT0CMirrorChannelEnd) + return true; + } + return false; + } + template void fillCorrelationsTPCFT0(TTracks tracks1, TFT0s const& ft0, float posZ, int system, int corType, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { @@ -750,11 +937,24 @@ struct LongRangeDihadronCor { for (std::size_t iCh = 0; iCh < channelSize; iCh++) { int chanelid = 0; float ampl = 0.; - getChannel(ft0, iCh, chanelid, ampl, corType); + getChannel(ft0, iCh, chanelid, ampl, corType, system); + if (corType == kFT0C) { + if ((cfgFwdConfig.cfgRejectFT0CInside && (chanelid >= kFT0CInnerRingMin && chanelid <= kFT0CInnerRingMax)) || (cfgFwdConfig.cfgRejectFT0COutside && (chanelid >= kFT0COuterRingMin && chanelid <= kFT0COuterRingMax))) + continue; + } else if (corType == kFT0A) { + if ((cfgFwdConfig.cfgRejectFT0AInside && (chanelid >= kFT0AInnerRingMin && chanelid <= kFT0AInnerRingMax)) || (cfgFwdConfig.cfgRejectFT0AOutside && (chanelid >= kFT0AOuterRingMin && chanelid <= kFT0AOuterRingMax))) + continue; + } + bool mirrorChannel = false; + if ((corType == kFT0A && cfgFwdConfig.cfgMirrorFT0ADeadChannels) || (corType == kFT0C && cfgFwdConfig.cfgMirrorFT0CDeadChannels)) + mirrorChannel = isMirrorId(chanelid, corType); + auto phi = getPhiFT0(chanelid, corType); auto eta = getEtaFT0(chanelid, corType); if (cfgDrawEtaPhiDis && system == SameEvent) { registry.fill(HIST("EtaPhi"), eta, phi, ampl * eventWeight); + if (mirrorChannel) + registry.fill(HIST("EtaPhi"), eta, 4 * PIHalf - phi, ampl * eventWeight); } float deltaPhi = RecoDecay::constrainAngle(track1.phi() - phi, -PIHalf); float deltaEta = track1.eta() - eta; @@ -762,22 +962,30 @@ struct LongRangeDihadronCor { if (system == SameEvent) { if (corType == kFT0A) { registry.fill(HIST("Assoc_amp_same_TPC_FT0A"), chanelid, ampl); - sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + sameTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { registry.fill(HIST("Assoc_amp_same_TPC_FT0C"), chanelid, ampl); - sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + sameTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); } } else if (system == MixedEvent) { if (corType == kFT0A) { registry.fill(HIST("Assoc_amp_mixed_TPC_FT0A"), chanelid, ampl); - mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0A"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + mixedTpcFt0a->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); } else if (corType == kFT0C) { registry.fill(HIST("Assoc_amp_mixed_TPC_FT0C"), chanelid, ampl); - mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_TPC_FT0C"), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), deltaPhi, deltaEta, ampl * eventWeight * triggerWeight); + if (mirrorChannel) + mixedTpcFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track1.pt(), RecoDecay::constrainAngle(track1.phi() - phi - 2 * PIHalf, -PIHalf), deltaEta, ampl * eventWeight * triggerWeight); } } } @@ -797,10 +1005,14 @@ struct LongRangeDihadronCor { int chanelAid = 0; float amplA = 0.; - getChannel(ft0Col1, iChA, chanelAid, amplA, kFT0A); + getChannel(ft0Col1, iChA, chanelAid, amplA, kFT0A, system); auto phiA = getPhiFT0(chanelAid, kFT0A); auto etaA = getEtaFT0(chanelAid, kFT0A); + bool mirrorChannelA = false; + if (cfgFwdConfig.cfgMirrorFT0ADeadChannels) + mirrorChannelA = isMirrorId(chanelAid, kFT0A); + if (system == SameEvent) { registry.fill(HIST("Trig_hist_FT0A_FT0C"), fSampleIndex, posZ, 0.5, eventWeight * amplA); } @@ -808,18 +1020,37 @@ struct LongRangeDihadronCor { for (std::size_t iChC = 0; iChC < channelCSize; iChC++) { int chanelCid = 0; float amplC = 0.; - getChannel(ft0Col2, iChC, chanelCid, amplC, kFT0C); + getChannel(ft0Col2, iChC, chanelCid, amplC, kFT0C, system); auto phiC = getPhiFT0(chanelCid, kFT0C); auto etaC = getEtaFT0(chanelCid, kFT0C); float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); float deltaEta = etaA - etaC; + + bool mirrorChannelC = false; + if (cfgFwdConfig.cfgMirrorFT0CDeadChannels) + mirrorChannelC = isMirrorId(chanelCid, kFT0C); + // fill the right sparse and histograms if (system == SameEvent) { - sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_same_FT0A_FT0C"), deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + if (mirrorChannelA) { + sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, RecoDecay::constrainAngle(phiA + 2 * PIHalf - phiC, -PIHalf), deltaEta, amplA * amplC * eventWeight * triggerWeight); + if (mirrorChannelC) + sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + } + if (mirrorChannelC) + sameFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, RecoDecay::constrainAngle(phiA - phiC - 2 * PIHalf, -PIHalf), deltaEta, amplA * amplC * eventWeight * triggerWeight); } else if (system == MixedEvent) { - mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); registry.fill(HIST("deltaEta_deltaPhi_mixed_FT0A_FT0C"), deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + if (mirrorChannelA) { + mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, RecoDecay::constrainAngle(phiA + 2 * PIHalf - phiC, -PIHalf), deltaEta, amplA * amplC * eventWeight * triggerWeight); + if (mirrorChannelC) + mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, deltaPhi, deltaEta, amplA * amplC * eventWeight * triggerWeight); + } + if (mirrorChannelC) + mixedFt0aFt0c->getPairHist()->Fill(step, fSampleIndex, posZ, 0.5, 0.5, RecoDecay::constrainAngle(phiA - phiC - 2 * PIHalf, -PIHalf), deltaEta, amplA * amplC * eventWeight * triggerWeight); } } } @@ -866,23 +1097,29 @@ struct LongRangeDihadronCor { } if (fillCounter && cfgEvSelkIsGoodITSLayersAll) registry.fill(HIST("hEventCountSpecific"), 6.5); + if (cfgEvSelkIsGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // for pp: cut time intervals with dead ITS staves on layers 0-3 only + return 0; + } + if (fillCounter && cfgEvSelkIsGoodITSLayer0123) + registry.fill(HIST("hEventCountSpecific"), 7.5); if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { // no other collisions in this Readout Frame with per-collision multiplicity above threshold return 0; } if (fillCounter && cfgEvSelkNoCollInRofStandard) - registry.fill(HIST("hEventCountSpecific"), 7.5); + registry.fill(HIST("hEventCountSpecific"), 8.5); if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { // veto an event if FT0C amplitude in previous ITS ROF is above threshold return 0; } if (fillCounter && cfgEvSelkNoHighMultCollInPrevRof) - registry.fill(HIST("hEventCountSpecific"), 8.5); + registry.fill(HIST("hEventCountSpecific"), 9.5); auto occupancy = collision.trackOccupancyInTimeRange(); if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) return 0; if (fillCounter && cfgEvSelOccupancy) - registry.fill(HIST("hEventCountSpecific"), 9.5); + registry.fill(HIST("hEventCountSpecific"), 10.5); auto multNTracksPV = collision.multNTracksPV(); if (cfgEvSelMultCorrelation) { @@ -912,14 +1149,14 @@ struct LongRangeDihadronCor { } } if (fillCounter && cfgEvSelMultCorrelation) - registry.fill(HIST("hEventCountSpecific"), 10.5); + registry.fill(HIST("hEventCountSpecific"), 11.5); // V0A T0A 5 sigma cut float sigma = 5.0; if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (fillCounter && cfgEvSelV0AT0ACut) - registry.fill(HIST("hEventCountSpecific"), 11.5); + registry.fill(HIST("hEventCountSpecific"), 12.5); return 1; } @@ -949,6 +1186,40 @@ struct LongRangeDihadronCor { registry.fill(HIST("Nch"), tracks.size()); registry.fill(HIST("zVtx"), collision.posZ()); + if (cfgCumulantConfig.gfwOutput) { + cfgCumulantConfig.fGFW->Clear(); + float lRandom = cfgCumulantConfig.fRndm->Rndm(); + float weff = 1, wacc = 1; + float independent = cent; + if (cfgCumulantConfig.gfwUseNch) + independent = static_cast(tracks.size()); + + // fill TPC Q-vector + for (const auto& track : tracks) { + if (!trackSelected(track)) + continue; + bool withinPtPOI = (0.2 < track.pt()) && (track.pt() < 10.0); // o2-linter: disable=magic-number (within POI pT range) + bool withinPtRef = (0.2 < track.pt()) && (track.pt() < 3.0); // o2-linter: disable=magic-number (within RF pT range) + getAcceptanceWeight(wacc, track.phi(), track.eta(), collision.posZ()); + if (!getEfficiencyCorrection(weff, track.eta(), track.pt(), collision.posZ())) + continue; + if (withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); + if (withinPtPOI) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 2); + if (withinPtPOI && withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 4); + } + // fill FT0 Q-vector + const auto& ft0 = collision.foundFT0(); + fillGFWFT0(ft0, kFT0A); + + // Filling Flow Container + for (uint l_ind = 0; l_ind < cfgCumulantConfig.corrconfigs.size(); l_ind++) { + fillFC(cfgCumulantConfig.corrconfigs.at(l_ind), independent, lRandom); + } + } + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { return; } @@ -956,6 +1227,21 @@ struct LongRangeDihadronCor { return; } + int currentRunNumber = bc.runNumber(); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0 && currentRunNumber != lastRunNumber) { + lastRunNumber = currentRunNumber; + if (std::find(runNumbers.begin(), runNumbers.end(), currentRunNumber) == runNumbers.end()) { + // if run number is not in the preconfigured list, create new output histograms for this run + createOutputObjectsForRun(currentRunNumber); + runNumbers.push_back(currentRunNumber); + LOGF(info, "Created Run-by-run objects in processSameTpcFt0a"); + } + if (histAmpCorrectPerRun.find(currentRunNumber) == histAmpCorrectPerRun.end()) { + LOGF(fatal, "RunNumber %d not found in histAmpCorrectPerRun", currentRunNumber); + return; + } + } + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); @@ -1054,6 +1340,40 @@ struct LongRangeDihadronCor { registry.fill(HIST("Nch"), tracks.size()); registry.fill(HIST("zVtx"), collision.posZ()); + if (cfgCumulantConfig.gfwOutput) { + cfgCumulantConfig.fGFW->Clear(); + float lRandom = cfgCumulantConfig.fRndm->Rndm(); + float weff = 1, wacc = 1; + float independent = cent; + if (cfgCumulantConfig.gfwUseNch) + independent = static_cast(tracks.size()); + + // fill TPC Q-vector + for (const auto& track : tracks) { + if (!trackSelected(track)) + continue; + bool withinPtPOI = (0.2 < track.pt()) && (track.pt() < 10.0); // o2-linter: disable=magic-number (within POI pT range) + bool withinPtRef = (0.2 < track.pt()) && (track.pt() < 3.0); // o2-linter: disable=magic-number (within RF pT range) + getAcceptanceWeight(wacc, track.phi(), track.eta(), collision.posZ()); + if (!getEfficiencyCorrection(weff, track.eta(), track.pt(), collision.posZ())) + continue; + if (withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 1); + if (withinPtPOI) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 2); + if (withinPtPOI && withinPtRef) + cfgCumulantConfig.fGFW->Fill(track.eta(), cfgCumulantConfig.fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 4); + } + // fill FT0 Q-vector + const auto& ft0 = collision.foundFT0(); + fillGFWFT0(ft0, kFT0C); + + // Filling Flow Container + for (uint l_ind = 0; l_ind < cfgCumulantConfig.corrconfigs.size(); l_ind++) { + fillFC(cfgCumulantConfig.corrconfigs.at(l_ind), independent, lRandom); + } + } + if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { return; } @@ -1061,6 +1381,21 @@ struct LongRangeDihadronCor { return; } + int currentRunNumber = bc.runNumber(); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0 && currentRunNumber != lastRunNumber) { + lastRunNumber = currentRunNumber; + if (std::find(runNumbers.begin(), runNumbers.end(), currentRunNumber) == runNumbers.end()) { + // if run number is not in the preconfigured list, create new output histograms for this run + createOutputObjectsForRun(currentRunNumber); + runNumbers.push_back(currentRunNumber); + LOGF(info, "Created Run-by-run objects in processSameTpcFt0c"); + } + if (histAmpCorrectPerRun.find(currentRunNumber) == histAmpCorrectPerRun.end()) { + LOGF(fatal, "RunNumber %d not found in histAmpCorrectPerRun", currentRunNumber); + return; + } + } + registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); @@ -1160,6 +1495,21 @@ struct LongRangeDihadronCor { return; } + int currentRunNumber = bc.runNumber(); + if (cfgFwdConfig.cfgRunbyRunAmplitudeFT0 && currentRunNumber != lastRunNumber) { + lastRunNumber = currentRunNumber; + if (std::find(runNumbers.begin(), runNumbers.end(), currentRunNumber) == runNumbers.end()) { + // if run number is not in the preconfigured list, create new output histograms for this run + createOutputObjectsForRun(currentRunNumber); + runNumbers.push_back(currentRunNumber); + LOGF(info, "Created Run-by-run objects in processSameFt0aFt0c"); + } + if (histAmpCorrectPerRun.find(currentRunNumber) == histAmpCorrectPerRun.end()) { + LOGF(fatal, "RunNumber %d not found in histAmpCorrectPerRun", currentRunNumber); + return; + } + } + sameFt0aFt0c->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); const auto& ft0 = collision.foundFT0(); fillCorrelationsFT0AFT0C(ft0, ft0, collision.posZ(), SameEvent, weightCent); diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx index 7a2af04602f..9d759b1695a 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangecorrDerived.cxx @@ -84,6 +84,7 @@ struct LongrangecorrDerived { Configurable cfgPidMask{"cfgPidMask", 0, "Selection bitmask for the TPC particle"}; Configurable cfgV0Mask{"cfgV0Mask", 0, "Selection bitmask for the V0 particle"}; Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "Vertex Z range to consider"}; + Configurable isUseCentEst{"isUseCentEst", false, "Centrality based classification"}; Configurable cfgFv0Cut{"cfgFv0Cut", 50.0f, "FV0A threshold"}; Configurable cfgFt0aCut{"cfgFt0aCut", 100.0f, "FT0A threshold"}; @@ -116,35 +117,35 @@ struct LongrangecorrDerived { OutputObj same{"sameEvent"}; OutputObj mixed{"mixedEvent"}; - using CollsTable = aod::CollLRTables; - using TrksTable = aod::TrkLRTables; - using MftTrksTable = aod::MftTrkLRTables; - using Ft0aTrksTable = aod::Ft0aLRTables; - using Ft0cTrksTable = aod::Ft0cLRTables; - using MftbestTrksTable = aod::MftBestTrkLRTables; - using V0TrksTable = aod::V0TrkLRTables; - - using UpcCollsTable = soa::Join; - using TrksUpcTable = aod::TrkLRUpcTables; - using MftTrksUpcTable = aod::MftTrkLRUpcTables; - using Ft0aTrksUpcTable = aod::Ft0aLRUpcTables; - using Ft0cTrksUpcTable = aod::Ft0cLRUpcTables; - using MftbestTrksUpcTable = aod::MftBestTrkLRUpcTables; - using V0TrksUpcTable = aod::V0TrkLRUpcTables; - - Preslice perColTpc = aod::lrcorrtrktable::collLRTableId; - Preslice perColMft = aod::lrcorrtrktable::collLRTableId; - Preslice perColMftbest = aod::lrcorrtrktable::collLRTableId; - Preslice perColFt0a = aod::lrcorrtrktable::collLRTableId; - Preslice perColFt0c = aod::lrcorrtrktable::collLRTableId; - Preslice perColV0 = aod::lrcorrtrktable::collLRTableId; - - Preslice perUpcColTpc = aod::lrcorrtrktable::upcCollLRTableId; - Preslice perUpcColMft = aod::lrcorrtrktable::upcCollLRTableId; - Preslice perUpcColMftbest = aod::lrcorrtrktable::upcCollLRTableId; - Preslice perUpcColFt0a = aod::lrcorrtrktable::upcCollLRTableId; - Preslice perUpcColFt0c = aod::lrcorrtrktable::upcCollLRTableId; - Preslice perUpcColV0 = aod::lrcorrtrktable::upcCollLRTableId; + using CollsTable = aod::LRCollisions; + using TrksTable = aod::LRMidTracks; + using MftTrksTable = aod::LRMftTracks; + using Ft0aTrksTable = aod::LRFt0aTracks; + using Ft0cTrksTable = aod::LRFt0cTracks; + using MftbestTrksTable = aod::LRMftBestTracks; + using V0TrksTable = aod::LRV0Tracks; + + using UpcCollsTable = soa::Join; + using TrksUpcTable = aod::UpcLRMidTracks; + using MftTrksUpcTable = aod::UpcLRMftTracks; + using Ft0aTrksUpcTable = aod::UpcLRFt0aTracks; + using Ft0cTrksUpcTable = aod::UpcLRFt0cTracks; + using MftbestTrksUpcTable = aod::UpcLRMftBestTracks; + using V0TrksUpcTable = aod::UpcLRV0Tracks; + + Preslice perColTpc = aod::lrcorrtrktable::lrCollisionId; + Preslice perColMft = aod::lrcorrtrktable::lrCollisionId; + Preslice perColMftbest = aod::lrcorrtrktable::lrCollisionId; + Preslice perColFt0a = aod::lrcorrtrktable::lrCollisionId; + Preslice perColFt0c = aod::lrcorrtrktable::lrCollisionId; + Preslice perColV0 = aod::lrcorrtrktable::lrCollisionId; + + Preslice perUpcColTpc = aod::lrcorrtrktable::upcLRCollisionId; + Preslice perUpcColMft = aod::lrcorrtrktable::upcLRCollisionId; + Preslice perUpcColMftbest = aod::lrcorrtrktable::upcLRCollisionId; + Preslice perUpcColFt0a = aod::lrcorrtrktable::upcLRCollisionId; + Preslice perUpcColFt0c = aod::lrcorrtrktable::upcLRCollisionId; + Preslice perUpcColV0 = aod::lrcorrtrktable::upcLRCollisionId; void init(InitContext const&) { @@ -163,6 +164,7 @@ struct LongrangecorrDerived { mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); histos.add("hMultiplicity", "hMultiplicity", kTH1D, {axisMultiplicity}); + histos.add("hCentrality", "hCentrality", kTH1D, {axisMultiplicity}); histos.add("hVertexZ", "hVertexZ", kTH1D, {axisVtxZ}); histos.add("hGapSide", "hGapSide", kTH1I, {{5, -0.5, 4.5}}); @@ -190,6 +192,9 @@ struct LongrangecorrDerived { void fillCollQA(TCollision const& col) { histos.fill(HIST("hMultiplicity"), col.multiplicity()); + if constexpr (std::experimental::is_detected::value) { + histos.fill(HIST("hCentrality"), col.centrality()); + } histos.fill(HIST("hVertexZ"), col.zvtx()); } @@ -246,6 +251,8 @@ struct LongrangecorrDerived { using HasUpc = decltype(std::declval().gapSide()); template using HasFt0 = decltype(std::declval().channelID()); + template + using HasCent = decltype(std::declval().centrality()); template void fillCorrHist(TTarget target, TTriggers const& triggers, TAssocs const& assocs, bool mixing, float vz, float multiplicity, float eventWeight) @@ -295,7 +302,16 @@ struct LongrangecorrDerived { return; } fillCollQA(col); - fillCorrHist(same, triggers, assocs, false, col.zvtx(), col.multiplicity(), 1.0); + auto multiplicity = 1.0f; + if constexpr (std::experimental::is_detected::value) { + if (isUseCentEst) + multiplicity = col.centrality(); + else + multiplicity = col.multiplicity(); + } else { + multiplicity = col.multiplicity(); + } + fillCorrHist(same, triggers, assocs, false, col.zvtx(), multiplicity, 1.0); } // process same template @@ -309,7 +325,16 @@ struct LongrangecorrDerived { } else { (void)this; } - return col.multiplicity(); + auto multiplicity = 1.0f; + if constexpr (std::experimental::is_detected::value) { + if (isUseCentEst) + multiplicity = col.centrality(); + else + multiplicity = col.multiplicity(); + } else { + multiplicity = col.multiplicity(); + } + return multiplicity; }; using MixedBinning = FlexibleBinningPolicy, aod::lrcorrcolltable::Zvtx, decltype(getMultiplicity)>; MixedBinning binningOnVtxAndMult{{getMultiplicity}, {axisVtxZME, axisMultME}, true}; @@ -325,7 +350,16 @@ struct LongrangecorrDerived { } } float eventweight = 1.0f / it.currentWindowNeighbours(); - fillCorrHist(mixed, tracks1, tracks2, true, col1.zvtx(), col1.multiplicity(), eventweight); + auto multiplicity = 1.0f; + if constexpr (std::experimental::is_detected::value) { + if (isUseCentEst) + multiplicity = col1.centrality(); + else + multiplicity = col1.multiplicity(); + } else { + multiplicity = col1.multiplicity(); + } + fillCorrHist(mixed, tracks1, tracks2, true, col1.zvtx(), multiplicity, eventweight); } // pair loop } // process mixed diff --git a/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx new file mode 100644 index 00000000000..c905bda396d --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/nucleibalance.cxx @@ -0,0 +1,2765 @@ +// 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 nucleibalance.cxx +/// \brief task for the balance function and correlations for nuclei for O2 analysis. First part is inspired from PWGCF/Tasks/correlations.cxx +/// \author Sushanta Tripathy + +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace constants::math; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +static constexpr float PairCutOff = -1.f; +static constexpr float CfgPairCutDefaults[1][5] = {{PairCutOff, PairCutOff, PairCutOff, PairCutOff, PairCutOff}}; + +struct Nucleibalance { + SliceCache cache; + + // Configuration + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 7.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPt, float, 0.5f, "Minimal pT for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutMCPt, float, 0.5f, "Minimal pT for MC particles (AO2D-MC mode)") + O2_DEFINE_CONFIGURABLE(cfgCutMCEta, float, 0.8f, "Eta range for MC particles (AO2D-MC mode)") + O2_DEFINE_CONFIGURABLE(cfgUseFT0M, int, 1, "Use FT0M centrality (0-100) as multiplicity axis (1=ON, 0=use Ntracks/multiplicity())") + // Track-quality options (AO2D mode). Default selection corresponds to global tracks. + O2_DEFINE_CONFIGURABLE(cfgTPCNClsMin, int, 70, "Minimum number of TPC clusters (tpcNClsFound) in AO2D mode") + O2_DEFINE_CONFIGURABLE(cfgDcaXYMax, float, 0.1f, "Max |DCA_{xy}| to PV (cm) in AO2D mode") + O2_DEFINE_CONFIGURABLE(cfgDcaZMax, float, 0.2f, "Max |DCA_{z}| to PV (cm) in AO2D mode") + O2_DEFINE_CONFIGURABLE(chi2pertpccluster, float, 2.5f, "Maximum Chi2/cluster for the TPC track segment in AO2D mode") + O2_DEFINE_CONFIGURABLE(chi2peritscluster, float, 36.f, "Maximum Chi2/cluster for the ITS track segment in AO2D mode") + O2_DEFINE_CONFIGURABLE(itsnclusters, int, 5, "Minimum number of ITS clusters in AO2D mode") + + O2_DEFINE_CONFIGURABLE(cfgPtOrder, int, 1, "Only consider pairs for which pT,1 < pT,2 (0 = OFF, 1 = ON)"); + O2_DEFINE_CONFIGURABLE(cfgTriggerCharge, int, 0, "Select on charge of trigger particle: 0 = all; 1 = positive; -1 = negative"); + O2_DEFINE_CONFIGURABLE(cfgAssociatedCharge, int, 0, "Select on charge of associated particle: 0 = all charged; 1 = positive; -1 = negative"); + O2_DEFINE_CONFIGURABLE(cfgPairCharge, int, 0, "Select on charge of particle pair: 0 = all; 1 = like sign; -1 = unlike sign"); + + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCut, float, -1, "Two track cut: -1 = off; >0 otherwise distance value (suggested: 0.02)"); + O2_DEFINE_CONFIGURABLE(cfgTwoTrackCutMinRadius, float, 0.8f, "Two track cut: radius in m from which two track cuts are applied"); + O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, int, 0, "0 = OFF and 1 = ON for local efficiency"); + O2_DEFINE_CONFIGURABLE(cfgCentBinsForMC, int, 0, "0 = OFF and 1 = ON for data like multiplicity/centrality bins for MC steps"); + O2_DEFINE_CONFIGURABLE(cfgTrackBitMask, uint16_t, 1, "BitMask for track selection systematics; refer to the enum TrackSelectionCuts in filtering task (default=1 selects global tracks)"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") + O2_DEFINE_CONFIGURABLE(cfgMultCutFormula, std::string, "", "Multiplicity correlations cut formula. A result greater than zero results in accepted event. Parameters: [cFT0C] FT0C centrality, [mFV0A] V0A multiplicity, [mGlob] global track multiplicity, [mPV] PV track multiplicity") + + // PID and species selection for AO2D-based correlations (pi, K, p, d) + O2_DEFINE_CONFIGURABLE(cfgUseTPCOnlyPID, int, 1, "Use only TPC PID (1 = TPC only, 0 = require both TPC and TOF when available)"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCPi, float, 3.0f, "|n#sigma^{TPC}_{#pi}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCKa, float, 3.0f, "|n#sigma^{TPC}_{K}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCPr, float, 3.0f, "|n#sigma^{TPC}_{p}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTPCDe, float, 3.0f, "|n#sigma^{TPC}_{d}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFPi, float, 3.0f, "|n#sigma^{TOF}_{#pi}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFKa, float, 3.0f, "|n#sigma^{TOF}_{K}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFPr, float, 3.0f, "|n#sigma^{TOF}_{p}| cut"); + O2_DEFINE_CONFIGURABLE(cfgNsigmaTOFDe, float, 3.0f, "|n#sigma^{TOF}_{d}| cut"); + + // Species choice for trigger/associated in the BF: + // 0 = pion, 1 = kaon, 2 = proton, 3 = deuteron, -1 = all charged tracks + O2_DEFINE_CONFIGURABLE(cfgTriggerSpecies, int, 3, "Trigger species for BF: 0 = #pi, 1 = K, 2 = p, 3 = d, -1 = all charged tracks"); + O2_DEFINE_CONFIGURABLE(cfgAssociatedSpecies, int, 2, "Associated species for BF: 0 = #pi, 1 = K, 2 = p, 3 = d, -1 = all charged tracks"); + + // Suggested values: Photon: 0.004; K0 and Lambda: 0.005 + Configurable> cfgPairCut{"cfgPairCut", {CfgPairCutDefaults[0], 5, {"Photon", "K0", "Lambda", "Phi", "Rho"}}, "Pair cuts on various particles"}; + + O2_DEFINE_CONFIGURABLE(cfgEfficiencyTrigger, std::string, "", "CCDB path to efficiency object for trigger particles") + O2_DEFINE_CONFIGURABLE(cfgEfficiencyAssociated, std::string, "", "CCDB path to efficiency object for associated particles") + + O2_DEFINE_CONFIGURABLE(cfgNoMixedEvents, int, 5, "Number of mixed events per event") + + O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 1, "Verbosity level (0 = major, 1 = per collision)") + + O2_DEFINE_CONFIGURABLE(cfgMcTriggerPDGs, std::vector, {}, "MC PDG codes to use exclusively as trigger particles and exclude from associated particles. Empty = no selection.") + + ConfigurableAxis axisVertex{"axisVertex", {7, -7, 7}, "vertex axis for histograms"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -2, 2}, "delta eta axis for histograms"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}, "pt associated axis for histograms"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity / centrality axis for histograms"}; + + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {10, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; + ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; + + Configurable cfgTrigger{"cfgTrigger", 4, "Event trigger selection: 0=none, 1=sel8, 2=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 3=sel8+occupancy+(kNoCollInTimeRangeStandard)+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 4=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV)"}; + Configurable cfgMinOcc{"cfgMinOcc", 0, "minimum occupancy selection (for cfgTrigger==3)"}; + Configurable cfgMaxOcc{"cfgMaxOcc", 3000, "maximum occupancy selection (for cfgTrigger==3)"}; + + // Named trigger codes to avoid magic numbers in keepCollisionAO2D + // ---- Ion/nucleus PDG encoding helpers (10LZZZAAAI) ---- + // Note: these are *format* constants (not particle PDG species codes) + static constexpr int IonCodeThreshold = 1000000000; // 10^9 + static constexpr int IonZDivisor = 10000; + static constexpr int IonZModulo = 1000; + static constexpr int PdgElectron = static_cast(PDG_t::kElectron); + static constexpr int PdgMuon = static_cast(PDG_t::kMuonMinus); + static constexpr int PdgPion = static_cast(PDG_t::kPiPlus); + static constexpr int PdgKaon = static_cast(PDG_t::kKPlus); + static constexpr int PdgProton = static_cast(PDG_t::kProton); + static constexpr int TriggerNone = 0; + static constexpr int TriggerSel8 = 1; + static constexpr int TriggerSel8Quality = 2; + static constexpr int TriggerSel8OccQuality = 3; + static constexpr int TriggerSel8NoSbpZvtx = 4; + template + bool keepCollisionAO2D(TCollision const& collision) const + { + if (cfgTrigger.value == TriggerNone) { + return true; + } else if (cfgTrigger.value == TriggerSel8) { + return collision.sel8(); + } else if (cfgTrigger.value == TriggerSel8Quality) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (cfgTrigger.value == TriggerSel8OccQuality) { + const int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < cfgMinOcc.value || occupancy >= cfgMaxOcc.value) { + return false; + } + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (cfgTrigger.value == TriggerSel8NoSbpZvtx) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); + } + + LOGF(warn, "Invalid cfgTrigger=%d. Accepting all collisions.", cfgTrigger.value); + return true; + } + + template + float eventMultiplicityFT0MOrFallback(TCollision const& collision, float fallback) const + { + if (cfgUseFT0M.value == 0) { + return fallback; + } + + // Prefer FT0M centrality if present in this collision table + if constexpr (requires { collision.centFT0M(); }) { + const float v = collision.centFT0M(); + if (v >= 0.f) { + return v; // expected 0..100 + } + } + + // Some tables may expose a validity bit + if constexpr (requires { collision.centFT0MValid(); }) { + if (collision.centFT0MValid()) { + if constexpr (requires { collision.centFT0M(); }) { + return collision.centFT0M(); + } + } + } + + return fallback; + } + + static int chargeFromPdg(int pdg) + { + const int apdg = std::abs(pdg); + + // Ions/nuclei: PDG code format 10LZZZAAAI -> Z is encoded in digits [7..5] + if (apdg >= IonCodeThreshold) { + const int z = (apdg / IonZDivisor) % IonZModulo; + return (pdg >= 0) ? z : -z; + } + + // Common charged hadrons/leptons (extend if needed) + switch (apdg) { + case PdgElectron: // e + case PdgMuon: // mu + case PdgPion: // pi + case PdgKaon: // K + case PdgProton: // p + return (pdg >= 0) ? 1 : -1; + default: + return 0; + } + } + + // This filter is applied to AOD and derived data (column names are identical) + Filter collisionZVtxFilter = nabs(aod::collision::posZ) < cfgCutVertex; + // This filter is only applied to AOD + Filter collisionVertexTypeFilter = (aod::collision::flags & static_cast(aod::collision::CollisionFlagsRun2::Run2VertexerTracks)) == static_cast(aod::collision::CollisionFlagsRun2::Run2VertexerTracks); + + // Track filters + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPt) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + Filter cfTrackFilter = (nabs(aod::cftrack::eta) < cfgCutEta) && (aod::cftrack::pt > cfgCutPt) && ((aod::track::trackType & (uint8_t)cfgTrackBitMask) == (uint8_t)cfgTrackBitMask); + + // MC filters + Filter cfMCCollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; + Filter cfMCParticleFilter = (nabs(aod::cfmcparticle::eta) < cfgCutEta) && (aod::cfmcparticle::pt > cfgCutPt); // && (aod::cfmcparticle::sign != 0); //check the sign manually, some specials may be neutral + + // Output definitions + OutputObj same{"sameEvent"}; + OutputObj mixed{"mixedEvent"}; + + // persistent caches + std::vector efficiencyAssociatedCache; + + std::unique_ptr multCutFormula; + std::array multCutFormulaParamIndex; + + struct Config { + bool mPairCuts = false; + THn* mEfficiencyTrigger = nullptr; + THn* mEfficiencyAssociated = nullptr; + bool efficiencyLoaded = false; + } cfg; + + HistogramRegistry registry{"registry"}; + PairCuts mPairCuts; + + Service ccdb; + + // AO2D-based tracks with PID for pi / K / p / d + using TracksPID = soa::Join; + using TracksPIDFiltered = soa::Filtered; + + using TracksPIDMC = soa::Join; + + using CollisionsAO2DMC = soa::Join; + + // group MC particles by MC collision + Preslice mcParticlesPerCollision = aod::mcparticle::mcCollisionId; + + // Helper: access a row of a soa::Join by row index (operator[] is not available for joins) + template + static auto trackAt(TTracks const& tracks, uint32_t idx) + { + if constexpr (requires { tracks.iteratorAt(idx); }) { + return tracks.iteratorAt(idx); + } else { + return tracks.rawIteratorAt(idx); + } + } + + // Helper: AO2D track-quality selection (default: global tracks) + template + bool passTrackQualityAO2D(const TTrack& trk) const + { + // Default: require global tracks when the column exists + if constexpr (requires { trk.isGlobalTrack(); }) { + if (!trk.isGlobalTrack()) { + return false; + } + } else if constexpr (requires { trk.isGlobalTrackSDD(); }) { + // fallback (older tables) + if (!trk.isGlobalTrackSDD()) { + return false; + } + } + + if constexpr (requires { trk.itsNCls(); }) { + if (itsnclusters.value > 0 && trk.itsNCls() < itsnclusters.value) { + return false; + } + } + + if constexpr (requires { trk.tpcNClsFound(); }) { + if (cfgTPCNClsMin.value > 0 && trk.tpcNClsFound() < cfgTPCNClsMin.value) { + return false; + } + } + + if constexpr (requires { trk.tpcChi2NCl(); }) { + if (chi2pertpccluster.value > 0.f && trk.tpcChi2NCl() > chi2pertpccluster.value) { + return false; + } + } + + if constexpr (requires { trk.itsChi2NCl(); }) { + if (chi2peritscluster.value > 0.f && trk.itsChi2NCl() > chi2peritscluster.value) { + return false; + } + } + + if constexpr (requires { trk.dcaXY(); }) { + if (cfgDcaXYMax.value > 0.f && std::abs(trk.dcaXY()) > cfgDcaXYMax.value) { + return false; + } + } + + if constexpr (requires { trk.dcaZ(); }) { + if (cfgDcaZMax.value > 0.f && std::abs(trk.dcaZ()) > cfgDcaZMax.value) { + return false; + } + } + + return true; + } + + struct SimpleTrack { + float eta; + float phi; + float pt; + int charge; + }; + + struct MixEventEntry { + float multiplicity; + float zvtx; + std::vector triggerTracks; + std::vector associatedTracks; + }; + + // Very simple mixing buffer: keep last cfgNoMixedEvents events + std::deque mMixEvents; + std::deque mMixEventsMC; + + // Preslice to group AO2D tracks by collision + + using DerivedCollisions = soa::Filtered; + using DerivedTracks = soa::Filtered; + using DerivedTracksWithRefs = soa::Filtered>; + + void init(o2::framework::InitContext&) + { + // --- HISTOGRAMS --- + registry.add("yields", "multiplicity/centrality vs pT vs eta", {HistType::kTH3F, {{100, 0, 100, "/multiplicity/centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); + registry.add("etaphi", "multiplicity/centrality vs eta vs phi", {HistType::kTH3F, {{100, 0, 100, "multiplicity/centrality"}, {100, -2, 2, "#eta"}, {200, 0, o2::constants::math::TwoPI, "#varphi"}}}); + + if (doprocessSameDerivedMultSet) { + if (cfgMultCorrelationsMask == 0) + LOGF(fatal, "cfgMultCorrelationsMask can not be 0 when MultSet process functions are in use."); + std::vector multAxes; + if (cfgMultCorrelationsMask & aod::cfmultset::CentFT0C) + multAxes.emplace_back(100, 0, 100, "FT0C centrality"); + if (cfgMultCorrelationsMask & aod::cfmultset::MultFV0A) + multAxes.emplace_back(1000, 0, 100000, "V0A multiplicity"); + if (cfgMultCorrelationsMask & aod::cfmultset::MultNTracksPV) + multAxes.emplace_back(100, 0, 1000, "Nch PV"); + if (cfgMultCorrelationsMask & aod::cfmultset::MultNTracksGlobal) + multAxes.emplace_back(100, 0, 1000, "Nch Global"); + registry.add("multCorrelations", "Multiplicity correlations", {HistType::kTHnSparseF, multAxes}); + } + registry.add("multiplicity", "event multiplicity", {HistType::kTH1F, {{1000, 0, 100, "/multiplicity/centrality"}}}); + registry.add("yvspt", "y vs pT", {HistType::kTH2F, {{100, -1, 1, "y"}, {100, 0, 20, "p_{T}"}}}); // y vs pT for all tracks (control histogram) + + const int maxMixBin = AxisSpec(axisMultiplicity).getNbins() * AxisSpec(axisVertex).getNbins(); + // The bin numbers for the control histograms (eventcount_*) come from getBin(...) and are the following: #mult_bin * #number_of_z_bins + #zbin + registry.add("eventcount_same", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("eventcount_mixed", "bin", {HistType::kTH1F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}}}); + registry.add("trackcount_same", "bin", {HistType::kTH2F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}, {10, -0.5, 9.5}}}); + registry.add("trackcount_mixed", "bin", {HistType::kTH3F, {{maxMixBin + 2, -2.5, -0.5 + maxMixBin, "bin"}, {10, -0.5, 9.5}, {10, -0.5, 9.5}}}); + + mPairCuts.SetHistogramRegistry(®istry); + + if (cfgPairCut->get("Photon") > 0 || cfgPairCut->get("K0") > 0 || cfgPairCut->get("Lambda") > 0 || cfgPairCut->get("Phi") > 0 || cfgPairCut->get("Rho") > 0) { + mPairCuts.SetPairCut(PairCuts::Photon, cfgPairCut->get("Photon")); + mPairCuts.SetPairCut(PairCuts::K0, cfgPairCut->get("K0")); + mPairCuts.SetPairCut(PairCuts::Lambda, cfgPairCut->get("Lambda")); + mPairCuts.SetPairCut(PairCuts::Phi, cfgPairCut->get("Phi")); + mPairCuts.SetPairCut(PairCuts::Rho, cfgPairCut->get("Rho")); + cfg.mPairCuts = true; + } + + if (cfgTwoTrackCut > 0) { + mPairCuts.SetTwoTrackCuts(cfgTwoTrackCut, cfgTwoTrackCutMinRadius); + } + + // --- OBJECT INIT --- + + if (!cfgMultCutFormula.value.empty()) { + multCutFormula = std::make_unique("multCutFormula", cfgMultCutFormula.value.c_str()); + std::fill_n(multCutFormulaParamIndex.begin(), std::size(multCutFormulaParamIndex), ~0u); + std::array pars = {"cFT0C", "mFV0A", "mPV", "mGlob"}; // must correspond the order of MultiplicityEstimators + for (uint i = 0, n = multCutFormula->GetNpar(); i < n; ++i) { + auto m = std::find(pars.begin(), pars.end(), multCutFormula->GetParName(i)); + if (m == pars.end()) { + + LOGF(warning, "Unknown parameter in cfgMultCutFormula: %s", multCutFormula->GetParName(i)); + continue; + } + if ((cfgMultCorrelationsMask.value & (1u << i)) == 0) { + LOGF(warning, "The centrality/multiplicity estimator %s is not available to be used in cfgMultCutFormula. Ensure cfgMultCorrelationsMask is correct and matches the CFMultSets in derived data."); + } else { + multCutFormulaParamIndex[std::distance(pars.begin(), m)] = i; + LOGF(info, "Multiplicity cut parameter %s in use.", m->c_str()); + } + } + } + + std::vector corrAxis = {{axisDeltaEta, "#Delta#eta"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisMultiplicity, "multiplicity / centrality"}, + {axisDeltaPhi, "#Delta#varphi (rad)"}, + {axisVertex, "z-vtx (cm)"}}; + std::vector effAxis = {{axisEtaEfficiency, "#eta"}, + {axisPtEfficiency, "p_{T} (GeV/c)"}, + {axisVertexEfficiency, "z-vtx (cm)"}}; + std::vector userAxis; + std::vector userMixingAxis; + + same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); + mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userMixingAxis)); + + same->setTrackEtaCut(cfgCutEta); + mixed->setTrackEtaCut(cfgCutEta); + + if (!cfgEfficiencyAssociated.value.empty()) + efficiencyAssociatedCache.reserve(512); + + // o2-ccdb-upload -p Users/jgrosseo/correlations/LHC15o -f /tmp/correction_2011_global.root -k correction + + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // TODO must become global parameter from the train creation time + } + + int getMagneticField(uint64_t timestamp) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + static o2::parameters::GRPObject* grpo = nullptr; + // static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + // grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + template + using HasMultSet = decltype(std::declval().multiplicities()); + + template + void fillQA(const TCollision& /*collision*/, float multiplicity, const TTracks& tracks) + { + registry.fill(HIST("multiplicity"), multiplicity); + for (const auto& track1 : tracks) { + registry.fill(HIST("yields"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("etaphi"), multiplicity, track1.eta(), track1.phi()); + } + } + + template + using HasInvMass = decltype(std::declval().invMass()); + template + using HasPDGCode = decltype(std::declval().pdgCode()); + + template + void fillQA(const TCollision& collision, float multiplicity, const TTracks1& tracks1, const TTracks2& tracks2) + { + for (const auto& track1 : tracks1) { + registry.fill(HIST("yieldsTrigger"), multiplicity, track1.pt(), track1.eta()); + registry.fill(HIST("etaphiTrigger"), multiplicity, track1.eta(), track1.phi()); + } + fillQA(collision, multiplicity, tracks2); + } + + template + bool checkObject(TTrack& track) + { + if constexpr (step <= CorrelationContainer::kCFStepAnaTopology) { + return track.isPhysicalPrimary(); + } else if constexpr (step == CorrelationContainer::kCFStepTrackedOnlyPrim) { + return track.isPhysicalPrimary() && (track.flags() & aod::cfmcparticle::kReconstructed); + } else if constexpr (step == CorrelationContainer::kCFStepTracked) { + return (track.flags() & aod::cfmcparticle::kReconstructed); + } + + return true; + } + + template + void fillCorrelations(TTarget target, TTracks1& tracks1, TTracks2& tracks2, float multiplicity, float posZ, int magField, float eventWeight) + { + // Helper lambda for pair charge selection + auto passPairCharge = [this](auto const& t1, auto const& t2) { + if (cfgPairCharge.value == 0) { + return true; + } + + int q1 = 0; + int q2 = 0; + + if constexpr (requires { t1.sign(); }) { + q1 = t1.sign(); + } else if constexpr (requires { t1.charge(); }) { + q1 = t1.charge(); + } else if constexpr (requires { t1.pdgCode(); }) { + q1 = chargeFromPdg(t1.pdgCode()); + } + + if constexpr (requires { t2.sign(); }) { + q2 = t2.sign(); + } else if constexpr (requires { t2.charge(); }) { + q2 = t2.charge(); + } else if constexpr (requires { t2.pdgCode(); }) { + q2 = chargeFromPdg(t2.pdgCode()); + } + + if (q1 == 0 || q2 == 0) { + // If we cannot determine both charges, reject the pair for pair-charge selections + return false; + } + + const int pairSign = q1 * q2; + if (cfgPairCharge.value == 1) { // like-sign pairs only + return pairSign > 0; + } + if (cfgPairCharge.value == -1) { // unlike-sign pairs only + return pairSign < 0; + } + + return true; + }; + + // Cache efficiency for particles (too many FindBin lookups) + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if (cfg.mEfficiencyAssociated) { + efficiencyAssociatedCache.clear(); + efficiencyAssociatedCache.reserve(tracks2.size()); + for (const auto& track : tracks2) { + efficiencyAssociatedCache.push_back(getEfficiencyCorrection(cfg.mEfficiencyAssociated, track.eta(), track.pt(), multiplicity, posZ)); + } + } + } + + for (const auto& track1 : tracks1) { + // LOGF(info, "Track %f | %f | %f %d %d", track1.eta(), track1.phi(), track1.pt(), track1.isGlobalTrack(), track1.isGlobalTrackSDD()); + + if constexpr (step <= CorrelationContainer::kCFStepTracked) { + if (!checkObject(track1)) { + continue; + } + } + + float triggerWeight = eventWeight; + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if (cfg.mEfficiencyTrigger) { + triggerWeight *= getEfficiencyCorrection(cfg.mEfficiencyTrigger, track1.eta(), track1.pt(), multiplicity, posZ); + } + } + + target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, triggerWeight); + + for (const auto& track2 : tracks2) { + if constexpr (std::is_same::value) { + if (track1.globalIndex() == track2.globalIndex()) { + // LOGF(info, "Track identical: %f | %f | %f || %f | %f | %f", track1.eta(), track1.phi(), track1.pt(), track2.eta(), track2.phi(), track2.pt()); + continue; + } + } + if constexpr (step <= CorrelationContainer::kCFStepTracked) { + if (!checkObject(track2)) { + continue; + } + } + + // Pair charge selection + if (!passPairCharge(track1, track2)) { + continue; + } + + if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) { + continue; + } + + if constexpr (std::is_same::value) { + if constexpr (step >= CorrelationContainer::kCFStepReconstructed) { + if (cfg.mPairCuts && mPairCuts.conversionCuts(track1, track2)) { + continue; + } + if (cfgTwoTrackCut > 0 && mPairCuts.twoTrackCut(track1, track2, magField)) { + continue; + } + } + } + + float associatedWeight = triggerWeight; + if constexpr (step == CorrelationContainer::kCFStepCorrected) { + if (cfg.mEfficiencyAssociated) { + associatedWeight *= efficiencyAssociatedCache[track2.filteredIndex()]; + } + } + + float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -o2::constants::math::PIHalf); + target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, associatedWeight); + } + } + } + + void loadEfficiency(uint64_t timestamp) + { + if (cfg.efficiencyLoaded) { + return; + } + if (cfgEfficiencyTrigger.value.empty() == false) { + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyTrigger = TFile::Open(cfgEfficiencyTrigger.value.c_str(), "READ"); + cfg.mEfficiencyTrigger = reinterpret_cast(fEfficiencyTrigger->Get("ccdb_object")); + } else { + cfg.mEfficiencyTrigger = ccdb->getForTimeStamp>(cfgEfficiencyTrigger, timestamp); + } + if (cfg.mEfficiencyTrigger == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiencyTrigger.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram for trigger particles from %s (%p)", cfgEfficiencyTrigger.value.c_str(), (void*)cfg.mEfficiencyTrigger); + } + if (cfgEfficiencyAssociated.value.empty() == false) { + if (cfgLocalEfficiency > 0) { + TFile* fEfficiencyAssociated = TFile::Open(cfgEfficiencyAssociated.value.c_str(), "READ"); + cfg.mEfficiencyAssociated = reinterpret_cast(fEfficiencyAssociated->Get("ccdb_object")); + } else { + cfg.mEfficiencyAssociated = ccdb->getForTimeStamp>(cfgEfficiencyAssociated, timestamp); + } + if (cfg.mEfficiencyAssociated == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for associated particles from %s", cfgEfficiencyAssociated.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram for associated particles from %s (%p)", cfgEfficiencyAssociated.value.c_str(), (void*)cfg.mEfficiencyAssociated); + } + cfg.efficiencyLoaded = true; + } + + double getEfficiencyCorrection(THn* eff, float eta, float pt, float multiplicity, float posZ) + { + int effVars[4]; + effVars[0] = eff->GetAxis(0)->FindBin(eta); + effVars[1] = eff->GetAxis(1)->FindBin(pt); + effVars[2] = eff->GetAxis(2)->FindBin(multiplicity); + effVars[3] = eff->GetAxis(3)->FindBin(posZ); + return eff->GetBinContent(effVars); + } + + template + bool passPIDForSpecies(const TTrack& trk, int species) + { + // -1 means "all charged tracks" + if (species < 0) { + return trk.sign() != 0; + } + + const bool useTPCOnly = (cfgUseTPCOnlyPID.value != 0); + + switch (species) { + case 0: { // pion + if (cfgNsigmaTPCPi.value > 0.f && std::abs(trk.tpcNSigmaPi()) > cfgNsigmaTPCPi.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFPi.value > 0.f && std::abs(trk.tofNSigmaPi()) > cfgNsigmaTOFPi.value) { + return false; + } + return trk.sign() != 0; + } + case 1: { // kaon + if (cfgNsigmaTPCKa.value > 0.f && std::abs(trk.tpcNSigmaKa()) > cfgNsigmaTPCKa.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFKa.value > 0.f && std::abs(trk.tofNSigmaKa()) > cfgNsigmaTOFKa.value) { + return false; + } + return trk.sign() != 0; + } + case 2: { // proton + if (cfgNsigmaTPCPr.value > 0.f && std::abs(trk.tpcNSigmaPr()) > cfgNsigmaTPCPr.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFPr.value > 0.f && std::abs(trk.tofNSigmaPr()) > cfgNsigmaTOFPr.value) { + return false; + } + return trk.sign() != 0; + } + case 3: { // deuteron + if (cfgNsigmaTPCDe.value > 0.f && std::abs(trk.tpcNSigmaDe()) > cfgNsigmaTPCDe.value) { + return false; + } + if (!useTPCOnly && cfgNsigmaTOFDe.value > 0.f && std::abs(trk.tofNSigmaDe()) > cfgNsigmaTOFDe.value) { + return false; + } + return trk.sign() != 0; + } + default: + return false; + } + } + + // Simple correlation filler writing directly into CorrelationContainer + void fillCorrelationsSimple(OutputObj& target, + CorrelationContainer::CFStep step, + const std::vector& triggers, + const std::vector& associates, + float multiplicity, + float posZ, + float eventWeight) + { + auto* trigHist = target->getTriggerHist(); + auto* pairHist = target->getPairHist(); + + for (auto const& t : triggers) { + trigHist->Fill(step, t.pt, multiplicity, posZ, eventWeight); + + for (auto const& a : associates) { + if (cfgPtOrder != 0 && a.pt >= t.pt) { + continue; + } + // Pair charge selection + if (cfgPairCharge.value != 0) { + const int pairSign = t.charge * a.charge; + if (cfgPairCharge.value == 1 && pairSign <= 0) { + continue; // keep only like-sign pairs + } + if (cfgPairCharge.value == -1 && pairSign >= 0) { + continue; // keep only unlike-sign pairs + } + } + float deltaPhi = RecoDecay::constrainAngle(t.phi - a.phi, -o2::constants::math::PIHalf); + float deltaEta = t.eta - a.eta; + pairHist->Fill(step, + deltaEta, + a.pt, + t.pt, + multiplicity, + deltaPhi, + posZ, + eventWeight); + } + } + } + template + void processSameDerivedPIDT(CollType const& collision, TCFTracks const& tracks, TracksPID const& tracksAll) + { + if (cfgVerbosity > 0) { + LOGF(info, "processSameDerivedPIDT: Tracks for collision: %d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks.size(), collision.posZ(), collision.multiplicity()); + } + + loadEfficiency(collision.timestamp()); + + const auto multiplicity = eventMultiplicityFT0MOrFallback(collision, collision.multiplicity()); + + using BinningTypeDerived = ColumnBinningPolicy; + BinningTypeDerived configurableBinningDerived{{axisVertex, axisMultiplicity}, true}; + int bin = configurableBinningDerived.getBin({collision.posZ(), multiplicity}); + registry.fill(HIST("eventcount_same"), bin); + registry.fill(HIST("trackcount_same"), bin, tracks.size()); + + // Kinematic QA + fillQA(collision, multiplicity, tracks); + + // PID-selected trigger/associate lists via CFTrackRefs -> AO2D TracksPID + std::vector triggerTracks; + std::vector associatedTracks; + triggerTracks.reserve(tracks.size()); + associatedTracks.reserve(tracks.size()); + + for (auto const& cftrk : tracks) { + const auto trk = trackAt(tracksAll, cftrk.trackId()); + if (trk.sign() == 0) { + continue; + } + + if (passPIDForSpecies(trk, cfgTriggerSpecies.value)) { + if (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value) { + triggerTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value)) { + if (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value) { + associatedTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + } + + if (triggerTracks.empty() || associatedTracks.empty()) { + return; + } + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + } + } + + void processSameDerivedPID(DerivedCollisions::iterator const& collision, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processSameDerivedPIDT(collision, tracks, tracksAll); + } + PROCESS_SWITCH(Nucleibalance, processSameDerivedPID, "Process same event on derived data with PID via CFTrackRefs", false); + + void processSameDerivedMultSetPID(soa::Filtered>::iterator const& collision, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processSameDerivedPIDT(collision, tracks, tracksAll); + } + PROCESS_SWITCH(Nucleibalance, processSameDerivedMultSetPID, "Process same event on derived data with multiplicity sets and PID via CFTrackRefs", false); + // AO2D-based processing: same + mixed events with PID-selected pi, p, d + void processAO2D(soa::Join::iterator const& collision, + TracksPID const& tracksAll) + { + // Event selection on vertex + if (std::abs(collision.posZ()) > cfgCutVertex) { + return; + } + + // Event selection (cfgTrigger) -- AO2D only + if (!keepCollisionAO2D(collision)) { + return; + } + + const auto thisCollIndex = collision.globalIndex(); + + // Per-event containers + std::vector eventTracks; // all selected tracks for multiplicity / QA + std::vector triggerTracks; // PID + charge selected triggers + std::vector associatedTracks; // PID + charge selected associates + + // Loop over all tracks and select those belonging to this collision + for (auto const& trk : tracksAll) { + if (trk.collisionId() != thisCollIndex) { + continue; + } + + // Kinematic cuts + if (std::abs(trk.eta()) > cfgCutEta || trk.pt() < cfgCutPt) { + continue; + } + + // Track-quality cuts (default: global tracks) + if (!passTrackQualityAO2D(trk)) { + continue; + } + + // Save for multiplicity / QA (keep charge even if neutral) + eventTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), static_cast(trk.sign())}); + + if (trk.sign() == 0) { + continue; + } + + // Trigger selection: PID + charge + if (passPIDForSpecies(trk, cfgTriggerSpecies.value)) { + if (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value) { + triggerTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + } + + // Associated selection: PID + charge + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value)) { + if (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value) { + associatedTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + } + } + + if (triggerTracks.empty() || associatedTracks.empty()) { + return; + } + + const float multiplicity = + eventMultiplicityFT0MOrFallback(collision, static_cast(eventTracks.size())); + + // QA on tracks for this event (AO2D-based) + registry.fill(HIST("multiplicity"), multiplicity); + for (const auto& t : eventTracks) { + registry.fill(HIST("yields"), multiplicity, t.pt, t.eta); + registry.fill(HIST("etaphi"), multiplicity, t.eta, t.phi); + } + + // -------------------------- + // SAME-EVENT CORRELATIONS + // -------------------------- + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + + // Optional efficiency-corrected step (if you configure efficiencies) + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (!cfg.efficiencyLoaded) { + // For AO2D only, the timestamp is not crucial if you use local efficiency files + loadEfficiency(0); + } + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(same, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + associatedTracks, + multiplicity, + collision.posZ(), + 1.0f); + } + + // -------------------------- + // MIXED-EVENT CORRELATIONS + // -------------------------- + for (auto const& prev : mMixEvents) { + if (prev.triggerTracks.empty() || prev.associatedTracks.empty()) { + continue; + } + + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + prev.associatedTracks, + prev.multiplicity, + prev.zvtx, + 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + prev.associatedTracks, + prev.multiplicity, + prev.zvtx, + 1.0f); + } + } + + // -------------------------- + // UPDATE MIXING BUFFER + // -------------------------- + MixEventEntry entry; + entry.multiplicity = multiplicity; + entry.zvtx = collision.posZ(); + entry.triggerTracks = std::move(triggerTracks); + entry.associatedTracks = std::move(associatedTracks); + + mMixEvents.push_front(std::move(entry)); + if (mMixEvents.size() > static_cast(cfgNoMixedEvents.value)) { + mMixEvents.pop_back(); + } + } + + PROCESS_SWITCH(Nucleibalance, processAO2D, + "Process AO2D: same- and mixed-event correlations with PID", true); + + // AO2D-MC processing: reconstructed correlations + MC efficiency (truth vs reco) + void processAO2DMC(CollisionsAO2DMC::iterator const& collision, + TracksPIDMC const& tracksAll, + aod::McCollisions const& /*mcCollisions*/, + aod::McParticles const& mcParticles) + { + if (std::abs(collision.posZ()) > cfgCutVertex) { + return; + } + if (!keepCollisionAO2D(collision)) { + return; + } + + // Resolve MC collision index + int mcCollIdx = -1; + if constexpr (requires { collision.has_mcCollision(); }) { + if (!collision.has_mcCollision()) { + return; + } + } + if constexpr (requires { collision.mcCollisionId(); }) { + mcCollIdx = collision.mcCollisionId(); + } else if constexpr (requires { collision.mcCollision().globalIndex(); }) { + mcCollIdx = collision.mcCollision().globalIndex(); + } + if (mcCollIdx < 0) { + return; + } + + const auto thisCollIndex = collision.globalIndex(); + + std::vector eventTracks; + std::vector triggerTracks; + std::vector associatedTracks; + + for (auto const& trk : tracksAll) { + if (trk.collisionId() != thisCollIndex) { + continue; + } + if (std::abs(trk.eta()) > cfgCutEta || trk.pt() < cfgCutPt) { + continue; + } + if (!passTrackQualityAO2D(trk)) { + continue; + } + + eventTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), static_cast(trk.sign())}); + + if (trk.sign() == 0) { + continue; + } + + if (passPIDForSpecies(trk, cfgTriggerSpecies.value) && + (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value)) { + triggerTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value) && + (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value)) { + associatedTracks.push_back(SimpleTrack{trk.eta(), trk.phi(), trk.pt(), trk.sign()}); + } + } + + if (triggerTracks.empty() || associatedTracks.empty()) { + return; + } + + const float multiplicity = + eventMultiplicityFT0MOrFallback(collision, static_cast(eventTracks.size())); + + // ---- MC efficiency filling (AO2D-MC) ---- + auto groupedMcParticles = mcParticles.sliceBy(mcParticlesPerCollision, mcCollIdx); + + for (auto const& mcPart : groupedMcParticles) { + if (std::abs(mcPart.eta()) > cfgCutMCEta || mcPart.pt() < cfgCutMCPt) { + continue; + } + if (mcPart.isPhysicalPrimary() && chargeFromPdg(mcPart.pdgCode()) != 0) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, + mcPart.eta(), mcPart.pt(), + getSpecies(mcPart.pdgCode()), + multiplicity, collision.posZ()); + } + } + + for (auto const& trk : tracksAll) { + if (trk.collisionId() != thisCollIndex) { + continue; + } + if (std::abs(trk.eta()) > cfgCutEta || trk.pt() < cfgCutPt) { + continue; + } + if (!passTrackQualityAO2D(trk)) { + continue; + } + + if constexpr (requires { trk.has_mcParticle(); trk.mcParticle(); }) { + if (trk.has_mcParticle()) { + const auto mcPart = trk.mcParticle(); + if (mcPart.isPhysicalPrimary()) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, + mcPart.eta(), mcPart.pt(), + getSpecies(mcPart.pdgCode()), + multiplicity, collision.posZ()); + } + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, + mcPart.eta(), mcPart.pt(), + getSpecies(mcPart.pdgCode()), + multiplicity, collision.posZ()); + } else { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, + trk.eta(), trk.pt(), + 0, multiplicity, collision.posZ()); + } + } + } + + // ---- QA ---- + registry.fill(HIST("multiplicity"), multiplicity); + for (const auto& t : eventTracks) { + registry.fill(HIST("yields"), multiplicity, t.pt, t.eta); + registry.fill(HIST("etaphi"), multiplicity, t.eta, t.phi); + } + + // ---- Same-event ---- + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(same, CorrelationContainer::kCFStepReconstructed, + triggerTracks, associatedTracks, + multiplicity, collision.posZ(), 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (!cfg.efficiencyLoaded) { + loadEfficiency(0); + } + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(same, CorrelationContainer::kCFStepCorrected, + triggerTracks, associatedTracks, + multiplicity, collision.posZ(), 1.0f); + } + + // ---- Mixed-event ---- + for (auto const& prev : mMixEventsMC) { + if (prev.triggerTracks.empty() || prev.associatedTracks.empty()) { + continue; + } + + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsSimple(mixed, CorrelationContainer::kCFStepReconstructed, + triggerTracks, prev.associatedTracks, + prev.multiplicity, prev.zvtx, 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + mixed->fillEvent(prev.multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelationsSimple(mixed, CorrelationContainer::kCFStepCorrected, + triggerTracks, prev.associatedTracks, + prev.multiplicity, prev.zvtx, 1.0f); + } + } + + MixEventEntry entry; + entry.multiplicity = multiplicity; + entry.zvtx = collision.posZ(); + entry.triggerTracks = std::move(triggerTracks); + entry.associatedTracks = std::move(associatedTracks); + + mMixEventsMC.push_front(std::move(entry)); + if (mMixEventsMC.size() > static_cast(cfgNoMixedEvents.value)) { + mMixEventsMC.pop_back(); + } + } + + PROCESS_SWITCH(Nucleibalance, processAO2DMC, + "Process AO2D-MC: reconstructed correlations + MC efficiency via labels", false); + + template + void processSameDerivedT(CollType const& collision, TTracks1 const& tracks1, TTracks2 const& tracks2) + { + using BinningTypeDerived = ColumnBinningPolicy; + BinningTypeDerived configurableBinningDerived{{axisVertex, axisMultiplicity}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. + if (cfgVerbosity > 0) { + LOGF(info, "processSameDerivedT: Tracks for collision: %d/%d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks1.size(), tracks2.size(), collision.posZ(), collision.multiplicity()); + } + loadEfficiency(collision.timestamp()); + + const auto multiplicity = eventMultiplicityFT0MOrFallback(collision, collision.multiplicity()); + int field = 0; + if (cfgTwoTrackCut > 0) { + field = getMagneticField(collision.timestamp()); + } + + int bin = configurableBinningDerived.getBin({collision.posZ(), multiplicity}); + registry.fill(HIST("eventcount_same"), bin); + registry.fill(HIST("trackcount_same"), bin, tracks1.size()); + + fillQA(collision, multiplicity, tracks1); + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); + } + } + + void processSameDerived(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks) + { + processSameDerivedT(collision, tracks, tracks); + } + PROCESS_SWITCH(Nucleibalance, processSameDerived, "Process same event on derived data", false); + + void processSameDerivedMultSet(soa::Filtered>::iterator const& collision, soa::Filtered const& tracks) + { + processSameDerivedT(collision, tracks, tracks); + } + PROCESS_SWITCH(Nucleibalance, processSameDerivedMultSet, "Process same event on derived data with multiplicity sets", false); + + template + void processMixedDerivedT(CollType const& collisions, TrackTypes&&... tracks) + { + auto getMultiplicity = + [this](auto& col) { + (void)this; // fix compile error on unused 'this' capture + return eventMultiplicityFT0MOrFallback(col, col.multiplicity()); + }; + + using BinningTypeDerived = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getMultiplicity)>; + BinningTypeDerived configurableBinningDerived{{getMultiplicity}, {axisVertex, axisMultiplicity}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. + // Strictly upper categorised collisions, for cfgNoMixedEvents combinations per bin, skipping those in entry -1 + auto tracksTuple = std::make_tuple(std::forward(tracks)...); + using TA = std::tuple_element<0, decltype(tracksTuple)>::type; + using TB = std::tuple_element - 1, decltype(tracksTuple)>::type; + Pair pairs{configurableBinningDerived, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + float multiplicity = getMultiplicity(collision1); + int bin = configurableBinningDerived.getBin(std::tuple(collision1.posZ(), multiplicity)); + float eventWeight = 1.0f / it.currentWindowNeighbours(); + int field = 0; + if (cfgTwoTrackCut > 0) { + field = getMagneticField(collision1.timestamp()); + } + + if (cfgVerbosity > 0) { + LOGF(info, "processMixedDerived: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), collision1.globalIndex(), collision1.posZ(), collision1.multiplicity(), collision2.globalIndex(), collision2.posZ(), collision2.multiplicity()); + } + + if (it.isNewWindow()) { + loadEfficiency(collision1.timestamp()); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + } + + // LOGF(info, "Tracks: %d and %d entries", tracks1.size(), tracks2.size()); + + registry.fill(HIST("eventcount_mixed"), bin); + registry.fill(HIST("trackcount_mixed"), bin, tracks1.size(), tracks2.size()); + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), field, eventWeight); + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + } + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), field, eventWeight); + } + } + } + + void processMixedDerived(DerivedCollisions const& collisions, DerivedTracks const& tracks) + { + processMixedDerivedT(collisions, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerived, "Process mixed events on derived data", false); + + void processMixedDerivedMultSet(soa::Filtered> const& collisions, DerivedTracks const& tracks) + { + processMixedDerivedT(collisions, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerivedMultSet, "Process mixed events on derived data with multiplicity sets", false); + + // Mixed-event processing on derived data with PID via CFTrackRefs -> AO2D TracksPID + template + void processMixedDerivedPIDT(CollType const& collisions, TracksPID const& tracksAll, TrackTypes&&... tracks) + { + auto getMultiplicity = + [this](auto& col) { + (void)this; + return eventMultiplicityFT0MOrFallback(col, col.multiplicity()); + }; + + using BinningTypeDerived = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getMultiplicity)>; + BinningTypeDerived configurableBinningDerived{{getMultiplicity}, {axisVertex, axisMultiplicity}, true}; + + auto tracksTuple = std::make_tuple(std::forward(tracks)...); + using TA = std::tuple_element<0, decltype(tracksTuple)>::type; + using TB = std::tuple_element - 1, decltype(tracksTuple)>::type; + Pair pairs{configurableBinningDerived, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + + for (auto it = pairs.begin(); it != pairs.end(); ++it) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + + const float multiplicity = getMultiplicity(collision1); + const int bin = configurableBinningDerived.getBin(std::tuple(collision1.posZ(), multiplicity)); + const float eventWeight = 1.0f / it.currentWindowNeighbours(); + + if (cfgVerbosity > 0) { + LOGF(info, "processMixedDerivedPID: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", + bin, it.isNewWindow(), it.currentWindowNeighbours(), + collision1.globalIndex(), collision1.posZ(), collision1.multiplicity(), + collision2.globalIndex(), collision2.posZ(), collision2.multiplicity()); + } + + if (it.isNewWindow()) { + loadEfficiency(collision1.timestamp()); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + } + + registry.fill(HIST("eventcount_mixed"), bin); + registry.fill(HIST("trackcount_mixed"), bin, tracks1.size(), tracks2.size()); + + std::vector triggerTracks; + std::vector associatedTracks; + triggerTracks.reserve(tracks1.size()); + associatedTracks.reserve(tracks2.size()); + + // Triggers from collision1 + for (auto const& cftrk : tracks1) { + const auto trk = trackAt(tracksAll, cftrk.trackId()); + if (trk.sign() == 0) { + continue; + } + if (passPIDForSpecies(trk, cfgTriggerSpecies.value)) { + if (cfgTriggerCharge.value == 0 || trk.sign() == cfgTriggerCharge.value) { + triggerTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + } + + // Associates from collision2 + for (auto const& cftrk : tracks2) { + const auto trk = trackAt(tracksAll, cftrk.trackId()); + if (trk.sign() == 0) { + continue; + } + if (passPIDForSpecies(trk, cfgAssociatedSpecies.value)) { + if (cfgAssociatedCharge.value == 0 || trk.sign() == cfgAssociatedCharge.value) { + associatedTracks.push_back(SimpleTrack{cftrk.eta(), cftrk.phi(), cftrk.pt(), trk.sign()}); + } + } + } + + if (!triggerTracks.empty() && !associatedTracks.empty()) { + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepReconstructed, + triggerTracks, + associatedTracks, + multiplicity, + collision1.posZ(), + eventWeight); + } + + if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); + } + if (!triggerTracks.empty() && !associatedTracks.empty()) { + fillCorrelationsSimple(mixed, + CorrelationContainer::kCFStepCorrected, + triggerTracks, + associatedTracks, + multiplicity, + collision1.posZ(), + eventWeight); + } + } + } + } + + void processMixedDerivedPID(DerivedCollisions const& collisions, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processMixedDerivedPIDT(collisions, tracksAll, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerivedPID, "Process mixed events on derived data with PID via CFTrackRefs", false); + + void processMixedDerivedMultSetPID(soa::Filtered> const& collisions, + DerivedTracksWithRefs const& tracks, + TracksPID const& tracksAll) + { + processMixedDerivedPIDT(collisions, tracksAll, tracks); + } + PROCESS_SWITCH(Nucleibalance, processMixedDerivedMultSetPID, "Process mixed events on derived data with multiplicity sets and PID via CFTrackRefs", false); + + int getSpecies(int pdgCode) + { + switch (pdgCode) { + case PdgPion: // pion + case -PdgPion: + return 0; + case PdgKaon: // Kaon + case -PdgKaon: + return 1; + case PdgProton: // proton + case -PdgProton: + return 2; + } + if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), pdgCode) != cfgMcTriggerPDGs->end()) + return 4; + else + return 3; + } + + // NOTE SmallGroups includes soa::Filtered always + Preslice perCollision = aod::cftrack::cfCollisionId; + void processMCEfficiency(soa::Filtered::iterator const& mcCollision, aod::CFMcParticles const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const& tracks) + { + if (cfgVerbosity > 0) { + LOGF(info, "MC collision at vtx-z = %f with %d mc particles and %d reconstructed collisions", mcCollision.posZ(), mcParticles.size(), collisions.size()); + } + + auto multiplicity = mcCollision.multiplicity(); + if (cfgCentBinsForMC > 0) { + if (collisions.size() == 0) { + return; + } + for (const auto& collision : collisions) { + multiplicity = collision.multiplicity(); + } + } + // Primaries + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary() && mcParticle.sign() != 0) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + } + } + for (const auto& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + if (cfgVerbosity > 0) { + LOGF(info, " Reconstructed collision at vtx-z = %f", collision.posZ()); + LOGF(info, " which has %d tracks", groupedTracks.size()); + } + + for (const auto& track : groupedTracks) { + if (track.has_cfMCParticle()) { + const auto& mcParticle = track.cfMCParticle(); + if (mcParticle.isPhysicalPrimary()) { + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + } + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + // LOGF(info, "Filled track %d", track.globalIndex()); + } else { + // fake track + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, track.eta(), track.pt(), 0, multiplicity, mcCollision.posZ()); + } + } + } + } + PROCESS_SWITCH(Nucleibalance, processMCEfficiency, "MC: Extract efficiencies", false); + + template + void processMCSameDerivedT(soa::Filtered::iterator const& mcCollision, Particles1 const& mcParticles1, Particles2 const& mcParticles2, soa::SmallGroups const& collisions) + { + if (cfgVerbosity > 0) { + LOGF(info, "processMCSameDerivedT. MC collision: %d, particles1: %d, particles2: %d, collisions: %d", mcCollision.globalIndex(), mcParticles1.size(), mcParticles2.size(), collisions.size()); + } + + auto multiplicity = mcCollision.multiplicity(); + if (cfgCentBinsForMC > 0) { + if (collisions.size() == 0) { + return; + } + for (const auto& collision : collisions) { + multiplicity = collision.multiplicity(); + } + } + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + if (collisions.size() == 0) { + return; + } + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepVertex); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepTrackedOnlyPrim); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + same->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); + + // NOTE kCFStepReconstructed and kCFStepCorrected are filled in processSameDerived + // This also means that if a MC collision had several reconstructed vertices (collisions), all of them are filled + } + + // NOTE SmallGroups includes soa::Filtered always + void processMCSameDerived(soa::Filtered::iterator const& mcCollision, soa::Filtered const& mcParticles, soa::SmallGroups const& collisions) // TODO. For mixed no need to check the daughters since the events are different + { + processMCSameDerivedT(mcCollision, mcParticles, mcParticles, collisions); + } + PROCESS_SWITCH(Nucleibalance, processMCSameDerived, "Process MC same event on derived data", false); + + PresliceUnsorted collisionPerMCCollision = aod::cfcollision::cfMcCollisionId; + template + void processMCMixedDerivedT(soa::Filtered const& mcCollisions, soa::Filtered const& collisions, ParticleTypes&&... particles) + { + bool useMCMultiplicity = (cfgCentBinsForMC == 0); + auto getMultiplicity = + [&collisions, &useMCMultiplicity, this](auto& col) { + if (useMCMultiplicity) + return col.multiplicity(); + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, col.globalIndex()); + if (groupedCollisions.size() == 0) + return -1.0f; + return groupedCollisions.begin().multiplicity(); + }; + + using BinningTypeMCDerived = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getMultiplicity)>; + BinningTypeMCDerived configurableBinning{{getMultiplicity}, {axisVertex, axisMultiplicity}, true}; + + // Strictly upper categorised collisions, for cfgNoMixedEvents combinations per bin, skipping those in entry -1 + auto tuple = std::make_tuple(std::forward(particles)...); + using TA = std::tuple_element<0, decltype(tuple)>::type; + using TB = std::tuple_element - 1, decltype(tuple)>::type; + Pair, TA, TB, BinningTypeMCDerived> pairs{configurableBinning, cfgNoMixedEvents, -1, mcCollisions, tuple, &cache}; // -1 is the number of the bin to skip + + for (auto it = pairs.begin(); it != pairs.end(); it++) { + auto& [collision1, tracks1, collision2, tracks2] = *it; + float eventWeight = 1.0f / it.currentWindowNeighbours(); + + float multiplicity = getMultiplicity(collision1); + if (cfgVerbosity > 0) { + int bin = configurableBinning.getBin(std::tuple(collision1.posZ(), multiplicity)); + LOGF(info, "processMCMixedDerived: Mixed collisions bin: %d pair: [%d, %d] %d (%.3f, %.3f), %d (%.3f, %.3f)", bin, it.isNewWindow(), it.currentWindowNeighbours(), collision1.globalIndex(), collision1.posZ(), getMultiplicity(collision1), collision2.globalIndex(), collision2.posZ(), getMultiplicity(collision2)); + } + + // STEP 0 + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + } + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + // check if collision1 has at least one reconstructed collision + auto groupedCollisions = collisions.sliceBy(collisionPerMCCollision, collision1.globalIndex()); + if (cfgVerbosity > 0) { + LOGF(info, "Found %d related collisions", groupedCollisions.size()); + } + if (groupedCollisions.size() == 0) { + continue; + } + + // STEP 2, 4, 5 + if (it.isNewWindow()) { + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepVertex); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepTrackedOnlyPrim); + mixed->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + } + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + fillCorrelations(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), 0, eventWeight); + + // NOTE kCFStepReconstructed and kCFStepCorrected are filled in processMixedDerived + // This also means that if a MC collision had several reconstructed vertices (collisions), all of them are filled + } + } + + void processMCMixedDerived(soa::Filtered const& mcCollisions, soa::Filtered const& mcParticles, soa::Filtered const& collisions) + { + processMCMixedDerivedT(mcCollisions, collisions, mcParticles); + } + PROCESS_SWITCH(Nucleibalance, processMCMixedDerived, "Process MC mixed events on derived data", false); +}; + +// Lambda* proxy analysis task based on deuteron proxy +struct Lambdastarproxy { + // ---- Ion/nucleus PDG encoding helpers (10LZZZAAAI) ---- + // Note: these are *format* constants (not particle PDG species codes) + static constexpr int IonCodeThreshold = 1000000000; // 10^9 + static constexpr int IonZDivisor = 10000; + static constexpr int IonZModulo = 1000; + // ---- Common PDG codes (use named values; avoid explicit literals) ---- + static constexpr int PdgElectron = static_cast(PDG_t::kElectron); + static constexpr int PdgMuon = static_cast(PDG_t::kMuonMinus); + static constexpr int PdgPion = static_cast(PDG_t::kPiPlus); + static constexpr int PdgKaon = static_cast(PDG_t::kKPlus); + static constexpr int PdgProton = static_cast(PDG_t::kProton); + // ---- Named defaults to avoid magic numbers (o2-linter) ---- + static constexpr float CutVertexDefault = 10.f; + static constexpr float CutPtMinDefault = 0.5f; + static constexpr float CutEtaMaxDefault = 0.8f; + + static constexpr float CutMCPtMinDefault = 0.1f; + static constexpr float CutMCEtaMaxDefault = 0.8f; + static constexpr int FillMCTruthDefault = 1; + + static constexpr float NsigmaTPCDefault = 3.f; + static constexpr float NsigmaTOFDefault = 3.f; + + static constexpr bool RequireGlobalTrackDefault = true; + static constexpr int TPCNClsMinDefault = 70; + static constexpr float DcaXYMaxDefault = 0.1f; + static constexpr float DcaZMaxDefault = 0.2f; + static constexpr float Chi2PerTPCClusterDefault = 2.5f; + static constexpr float Chi2PerITSClusterDefault = 36.f; + static constexpr int ITSNClustersDefault = 5; + + static constexpr int TriggerDefault = 4; + // Named trigger codes + static constexpr int TriggerNone = 0; + static constexpr int TriggerSel8 = 1; + static constexpr int TriggerSel8Quality = 2; + static constexpr int TriggerSel8OccQuality = 3; + static constexpr int TriggerSel8NoSbpZvtx = 4; + static constexpr int MinOccDefault = 0; + static constexpr int MaxOccDefault = 3000; + + static constexpr int NoMixedEventsDefault = 5; + static constexpr float MixZvtxMaxDefault = 2.0f; + static constexpr float MixMultMaxDefault = 50.0f; + + static constexpr float ProxyMomentumScale = 0.5f; + static constexpr float TofBetaMin = 0.01f; + static constexpr float TofBetaMax = 1.2f; + static constexpr double Half = 0.5; + // Basic configuration for event and track selection + Configurable lstarCutVertex{"lstarCutVertex", float{CutVertexDefault}, "Accepted z-vertex range (cm)"}; + Configurable lstarCutPtMin{"lstarCutPtMin", float{CutPtMinDefault}, "Minimal pT for tracks (GeV/c)"}; + Configurable lstarCutEtaMax{"lstarCutEtaMax", float{CutEtaMaxDefault}, "Max |eta| for tracks"}; + + // MC truth + Configurable lstarCutMCPtMin{"lstarCutMCPtMin", float{CutMCPtMinDefault}, "Minimal pT for MC particles (GeV/c)"}; + Configurable lstarCutMCEtaMax{"lstarCutMCEtaMax", float{CutMCEtaMaxDefault}, "Max |eta| for MC particles"}; + Configurable lstarFillMCTruth{"lstarFillMCTruth", int{FillMCTruthDefault}, "Fill MC truth and reco-matching QA (AO2D-MC mode)"}; + + // PID cuts + Configurable lstarCutNsigmaTPCPi{"lstarCutNsigmaTPCPi", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{#pi}| cut"}; + Configurable lstarCutNsigmaTOFPi{"lstarCutNsigmaTOFPi", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{#pi}| cut"}; + Configurable lstarCutNsigmaTPCPr{"lstarCutNsigmaTPCPr", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{p}| cut"}; + Configurable lstarCutNsigmaTOFPr{"lstarCutNsigmaTOFPr", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{p}| cut"}; + Configurable lstarCutNsigmaTPCKaon{"lstarCutNsigmaTPCKaon", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{K}| cut"}; + Configurable lstarCutNsigmaTOFKaon{"lstarCutNsigmaTOFKaon", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{K}| cut"}; + Configurable lstarCutNsigmaTPCDe{"lstarCutNsigmaTPCDe", float{NsigmaTPCDefault}, "|nSigma^{TPC}_{d}| cut"}; + Configurable lstarCutNsigmaTOFDe{"lstarCutNsigmaTOFDe", float{NsigmaTOFDefault}, "|nSigma^{TOF}_{d}| cut"}; + + // Track quality + Configurable lstarRequireGlobalTrack{"lstarRequireGlobalTrack", bool{RequireGlobalTrackDefault}, "Require global tracks (default)"}; + Configurable lstarTPCNClsMin{"lstarTPCNClsMin", int{TPCNClsMinDefault}, "Minimum number of TPC clusters (tpcNClsFound)"}; + Configurable lstarDcaXYMax{"lstarDcaXYMax", float{DcaXYMaxDefault}, "Max |DCA_{xy}| to PV (cm)"}; + Configurable lstarDcaZMax{"lstarDcaZMax", float{DcaZMaxDefault}, "Max |DCA_{z}| to PV (cm)"}; + Configurable lstarChi2PerTPCCluster{"lstarChi2PerTPCCluster", float{Chi2PerTPCClusterDefault}, "Maximum Chi2/cluster for the TPC track segment"}; + Configurable lstarChi2PerITSCluster{"lstarChi2PerITSCluster", float{Chi2PerITSClusterDefault}, "Maximum Chi2/cluster for the ITS track segment"}; + Configurable lstarITSNClusters{"lstarITSNClusters", int{ITSNClustersDefault}, "Minimum number of ITS clusters"}; + + // Trigger + occupancy + Configurable lstarCfgTrigger{"lstarCfgTrigger", int{TriggerDefault}, "Event trigger selection: 0=none, 1=sel8, 2=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 3=sel8+occupancy+(kNoCollInTimeRangeStandard)+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV+kIsGoodITSLayersAll), 4=sel8+(kNoSameBunchPileup+kIsGoodZvtxFT0vsPV)"}; + Configurable lstarMinOcc{"lstarMinOcc", int{MinOccDefault}, "minimum occupancy selection (for cfgTrigger==3)"}; + Configurable lstarMaxOcc{"lstarMaxOcc", int{MaxOccDefault}, "maximum occupancy selection (for cfgTrigger==3)"}; + Configurable lstarUseFT0M{"lstarUseFT0M", 1, "Use FT0M centrality (0-100) as multiplicity axis (1=ON, 0=use Ntracks)"}; + + // --- Mixed-event configuration for pK / proxy invariant-mass background (AO2D only) --- + Configurable lstarNoMixedEvents{"lstarNoMixedEvents", int{NoMixedEventsDefault}, "Number of previous events kept for mixed-event background"}; + Configurable lstarMixZvtxMax{"lstarMixZvtxMax", float{MixZvtxMaxDefault}, "Max |Δzvtx| (cm) for event mixing"}; + Configurable lstarMixMultMax{"lstarMixMultMax", float{MixMultMaxDefault}, "Max |Δmult| for event mixing"}; + Configurable lstarEnablePidQA{"lstarEnablePidQA", 0, "Enable PID QA histograms (dE/dx, TOF #beta, proxy invariant-mass QA, etc.): 1 = ON, 0 = OFF"}; + Configurable lstarEnableSparse{"lstarEnableSparse", 1, "Enable THnSparse invariant-mass histograms (#Lambda^{*} pK and proxy); 1 = ON, 0 = OFF"}; + Configurable lstarLambdaAbsYMax{"lstarLambdaAbsYMax", 0.5f, "Max |y_{pK}| (or y_{proxy K}) for #Lambda^{*} candidates"}; + + struct KaonCand { + float px, py, pz; + int charge; + int tid; + }; + struct ProxyCand { + float px, py, pz; + int charge; + int tid; + }; + struct ProtonCand { + float px, py, pz; + int charge; + int tid; + }; + + // Helpers for invariant-mass kinematics + static float phiFromPxPy(float px, float py) + { + return std::atan2(py, px); + } + + static float rapidityFromEPz(double e, double pz) + { + const double num = e + pz; + const double den = e - pz; + if (num <= 0.0 || den <= 0.0) { + return 0.f; + } + return static_cast(Half * std::log(num / den)); + } + + // Mixed-event pool entry for pK / proxy background (AO2D only) + struct LStarMixEventEntry { + float mult = 0.f; + float zvtx = 0.f; + std::vector kaons; + std::vector proxies; + }; + + // Keep last N events for event-mixing + std::deque mLStarMixEvents; + + template + bool keepCollisionAO2D(TCollision const& collision) const + { + if (lstarCfgTrigger.value == TriggerNone) { + return true; + } else if (lstarCfgTrigger.value == TriggerSel8) { + return collision.sel8(); + } else if (lstarCfgTrigger.value == TriggerSel8Quality) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (lstarCfgTrigger.value == TriggerSel8OccQuality) { + const int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < lstarMinOcc.value || occupancy >= lstarMaxOcc.value) { + return false; + } + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && + collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) && + collision.selection_bit(aod::evsel::kIsGoodITSLayersAll); + } else if (lstarCfgTrigger.value == TriggerSel8NoSbpZvtx) { + return collision.sel8() && + collision.selection_bit(aod::evsel::kNoSameBunchPileup) && + collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); + } + + LOGF(warn, "Invalid lstarCfgTrigger=%d. Accepting all collisions.", lstarCfgTrigger.value); + return true; + } + + template + float eventMultiplicityFT0MOrFallback(TCollision const& collision, float fallback) const + { + if (lstarUseFT0M.value == 0) { + return fallback; + } + + if constexpr (requires { collision.centFT0M(); }) { + const float v = collision.centFT0M(); + if (v >= 0.f) { + return v; + } + } + + if constexpr (requires { collision.centFT0MValid(); }) { + if (collision.centFT0MValid()) { + if constexpr (requires { collision.centFT0M(); }) { + return collision.centFT0M(); + } + } + } + + return fallback; + } + + static int chargeFromPdg(int pdg) + { + const int apdg = std::abs(pdg); + + // Ions/nuclei: PDG code format 10LZZZAAAI -> Z is encoded in digits [7..5] + if (apdg >= IonCodeThreshold) { + const int z = (apdg / IonZDivisor) % IonZModulo; + return (pdg >= 0) ? z : -z; + } + + switch (apdg) { + case PdgElectron: // e + case PdgMuon: // mu + case PdgPion: // pi + case PdgKaon: // K + case PdgProton: // p + return (pdg >= 0) ? 1 : -1; + default: + return 0; + } + } + + // Histogram registry for this task + HistogramRegistry histos{"lstarRegistry"}; + + // Filters + Filter collisionZVtxFilter = nabs(aod::collision::posZ) < lstarCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < lstarCutEtaMax) && (aod::track::pt > lstarCutPtMin); + + // Tracks with PID information from TPC and TOF services for all relevant species + // NOTE: aod::TracksExtra is needed for TPC dE/dx (tpcSignal) + using TracksWithPID = soa::Join; + template + bool passTrackQuality(const TTrack& trk) const + { + if (lstarRequireGlobalTrack.value) { + if constexpr (requires { trk.isGlobalTrack(); }) { + if (!trk.isGlobalTrack()) { + return false; + } + } else if constexpr (requires { trk.isGlobalTrackSDD(); }) { + if (!trk.isGlobalTrackSDD()) { + return false; + } + } + } + + if constexpr (requires { trk.itsNCls(); }) { + if (lstarITSNClusters.value > 0 && trk.itsNCls() < lstarITSNClusters.value) { + return false; + } + } + + if constexpr (requires { trk.tpcNClsFound(); }) { + if (lstarTPCNClsMin.value > 0 && trk.tpcNClsFound() < lstarTPCNClsMin.value) { + return false; + } + } + + if constexpr (requires { trk.tpcChi2NCl(); }) { + if (lstarChi2PerTPCCluster.value > 0.f && trk.tpcChi2NCl() > lstarChi2PerTPCCluster.value) { + return false; + } + } + + if constexpr (requires { trk.itsChi2NCl(); }) { + if (lstarChi2PerITSCluster.value > 0.f && trk.itsChi2NCl() > lstarChi2PerITSCluster.value) { + return false; + } + } + + if constexpr (requires { trk.dcaXY(); }) { + if (lstarDcaXYMax.value > 0.f && std::abs(trk.dcaXY()) > lstarDcaXYMax.value) { + return false; + } + } + + if constexpr (requires { trk.dcaZ(); }) { + if (lstarDcaZMax.value > 0.f && std::abs(trk.dcaZ()) > lstarDcaZMax.value) { + return false; + } + } + + return true; + } + using CollisionsWithEvSel = soa::Join; + using FilteredCollisions = soa::Filtered; + using FilteredTracks = soa::Filtered; + + // AO2D-MC variants (for truth QA and reco->MC matching) + using CollisionsWithEvSelMC = soa::Join; + using FilteredCollisionsMC = soa::Filtered; + + using TracksWithPIDMC = soa::Join; + using FilteredTracksMC = soa::Filtered; + + Preslice mcParticlesPerCollision = aod::mcparticle::mcCollisionId; + + void init(o2::framework::InitContext&) + { + AxisSpec massAxis{200, 1.4, 1.9, "M_{pK} (GeV/c^{2})"}; + AxisSpec ptAxis{100, 0., 10., "p_{T} (GeV/c)"}; + AxisSpec nsAxis{100, -10., 10., "n#sigma"}; + AxisSpec pAxis{100, 0., 10., "p (GeV/c)"}; + AxisSpec etaAxis{80, -2., 2., "#eta"}; + AxisSpec phiAxis{64, 0., o2::constants::math::TwoPI, "#varphi"}; + AxisSpec centAxis{100, 0., 100., "multiplicity/centrality"}; + + AxisSpec pdgAxis{10001, -5000.5, 5000.5, "PDG code"}; + + AxisSpec dEdxAxis{400, 0., 200., "TPC dE/dx (arb. units)"}; + AxisSpec betaAxis{160, 0., 1.6, "#beta_{TOF}"}; + + // Invariant-mass spectra + histos.add("hInvMassPKUnlike", + "pK invariant mass (unlike-sign);M_{pK} (GeV/c^{2});Counts", + HistType::kTH1F, {massAxis}); + histos.add("hInvMassPKLike", + "pK invariant mass (like-sign);M_{pK} (GeV/c^{2});Counts", + HistType::kTH1F, {massAxis}); + + // Invariant-mass vs pair pT (use p_{T} of pK system) + histos.add("hInvMassPKUnlikeVsPt", + "pK invariant mass vs p_{T} (unlike-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts", + HistType::kTH2F, {massAxis, ptAxis}); + histos.add("hInvMassPKLikeVsPt", + "pK invariant mass vs p_{T} (like-sign);M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);Counts", + HistType::kTH2F, {massAxis, ptAxis}); + + // THnSparse for invariant-mass analysis (mass, pT, y, phi) + if (lstarEnableSparse.value != 0) { + histos.add("hLambdaStarPKUnlikeSparse", + "#Lambda^{*}(1520) pK unlike-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{pK}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + + histos.add("hLambdaStarPKLikeSparse", + "#Lambda^{*}(1520) pK like-sign candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{pK}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + + histos.add("hLambdaStarPKMixedSparse", + "#Lambda^{*}(1520) pK mixed-event candidates;M_{pK} (GeV/c^{2});p_{T}^{pK} (GeV/c);y_{pK};#varphi_{pK}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{pK} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{pK} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{pK}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{pK}"}, centAxis}); + + // THnSparse for deuteron-proxy invariant-mass analysis (mass, pT, y, phi) + histos.add("hLambdaStarProxySparse", + "#Lambda^{*}(1520) deuteron-proxy candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis}); + + histos.add("hLambdaStarProxyMixedSparse", + "#Lambda^{*}(1520) deuteron-proxy mixed-event candidates;M_{p_{proxy}K} (GeV/c^{2});p_{T}^{p_{proxy}K} (GeV/c);y_{p_{proxy}K};#varphi_{p_{proxy}K}", + HistType::kTHnSparseF, + {AxisSpec{400, 1.3, 1.9, "M_{p_{proxy}K} (GeV/c^{2})"}, + AxisSpec{100, 0., 10., "p_{T}^{p_{proxy}K} (GeV/c)"}, + AxisSpec{60, -1.5, 1.5, "y_{p_{proxy}K}"}, + AxisSpec{64, -3.2, 3.2, "#varphi_{p_{proxy}K}"}, centAxis}); + } + + // Deuteron-proxy invariant mass (p_{proxy} from d/2 combined with K) + histos.add("hDeuteronProxyMass", + "#Lambda^{*} proxy invariant mass from (d/2 + K);M_{p_{proxy}K} (GeV/c^{2});Counts", + HistType::kTH1F, {massAxis}); + + // TPC dE/dx vs total momentum + histos.add("hTPCdEdxVsP", + "TPC dE/dx vs p;p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + + // TOF #beta vs total momentum + histos.add("hTOFBetaVsP", + "TOF #beta vs p;p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + + // --- Per-species PID QA (tagged) --- + histos.add("hTPCdEdxVsP_Pi", + "TPC dE/dx vs p (tagged #pi);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + histos.add("hTPCdEdxVsP_K", + "TPC dE/dx vs p (tagged K);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + histos.add("hTPCdEdxVsP_P", + "TPC dE/dx vs p (tagged p);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + histos.add("hTPCdEdxVsP_D", + "TPC dE/dx vs p (tagged d);p (GeV/c);dE/dx (arb. units);Counts", + HistType::kTH2F, {pAxis, dEdxAxis}); + + histos.add("hTOFBetaVsP_Pi", + "TOF #beta vs p (tagged #pi);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + histos.add("hTOFBetaVsP_K", + "TOF #beta vs p (tagged K);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + histos.add("hTOFBetaVsP_P", + "TOF #beta vs p (tagged p);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + histos.add("hTOFBetaVsP_D", + "TOF #beta vs p (tagged d);p (GeV/c);#beta_{TOF};Counts", + HistType::kTH2F, {pAxis, betaAxis}); + + // --- MC QA (AO2D-MC mode) --- + histos.add("hMcPrimariesPtEta", + "MC charged physical primaries; p_{T} (GeV/c); #eta; Counts", + HistType::kTH2F, {ptAxis, etaAxis}); + + histos.add("hRecoMatchedPdg", + "Reco tracks matched to MC (PDG); PDG code; Counts", + HistType::kTH1F, {pdgAxis}); + + histos.add("hRecoFakePtEta", + "Reco tracks without MC label (fakes / unmatched); p_{T} (GeV/c); #eta; Counts", + HistType::kTH2F, {ptAxis, etaAxis}); + + // Deuteron-proxy kinematics and PID QA + histos.add("hDeuteronProxyPt", + "Deuteron proxy p_{T};p_{T} (GeV/c);Counts", + HistType::kTH1F, {ptAxis}); + histos.add("hDeuteronProxyEta", + "Deuteron proxy #eta;#eta;Counts", + HistType::kTH1F, {etaAxis}); + histos.add("hDeuteronProxyPhi", + "Deuteron proxy #varphi;#varphi;Counts", + HistType::kTH1F, {phiAxis}); + + histos.add("hNsigmaTPCDeuteron", + "TPC n#sigma_{d};n#sigma^{TPC}_{d};Counts", + HistType::kTH1F, {nsAxis}); + histos.add("hNsigmaTOFDeuteron", + "TOF n#sigma_{d};n#sigma^{TOF}_{d};Counts", + HistType::kTH1F, {nsAxis}); + + histos.add("hNsigmaTPCDeuteronVsP", + "TPC n#sigma_{d} vs p; p (GeV/c); n#sigma^{TPC}_{d};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + histos.add("hNsigmaTOFDeuteronVsP", + "TOF n#sigma_{d} vs p; p (GeV/c); n#sigma^{TOF}_{d};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + + // Kaon kinematics and PID QA + histos.add("hKaonPt", + "Kaon p_{T};p_{T} (GeV/c);Counts", + HistType::kTH1F, {ptAxis}); + histos.add("hKaonEta", + "Kaon #eta;#eta;Counts", + HistType::kTH1F, {etaAxis}); + histos.add("hKaonPhi", + "Kaon #varphi;#varphi;Counts", + HistType::kTH1F, {phiAxis}); + + histos.add("hNsigmaTPCKaon", + "TPC n#sigma_{K};n#sigma^{TPC}_{K};Counts", + HistType::kTH1F, {nsAxis}); + histos.add("hNsigmaTOFKaon", + "TOF n#sigma_{K};n#sigma^{TOF}_{K};Counts", + HistType::kTH1F, {nsAxis}); + + histos.add("hNsigmaTPCKaonVsP", + "TPC n#sigma_{K} vs p; p (GeV/c); n#sigma^{TPC}_{K};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + histos.add("hNsigmaTOFKaonVsP", + "TOF n#sigma_{K} vs p; p (GeV/c); n#sigma^{TOF}_{K};Counts", + HistType::kTH2F, {pAxis, nsAxis}); + } + + // AO2D-MC QA: truth primaries + reco-to-MC matching sanity plots + void processMCQA(FilteredCollisionsMC::iterator const& collision, + FilteredTracksMC const& tracks, + aod::McParticles const& mcParticles) + { + if (lstarFillMCTruth.value == 0) { + return; + } + + // Same basic event selection as AO2D reco + if (!keepCollisionAO2D(collision)) { + return; + } + if (std::abs(collision.posZ()) > lstarCutVertex.value) { + return; + } + + // Require a linked MC collision + if constexpr (requires { collision.has_mcCollision(); }) { + if (!collision.has_mcCollision()) { + return; + } + } + + int mcCollIdx = -1; + if constexpr (requires { collision.mcCollisionId(); }) { + mcCollIdx = collision.mcCollisionId(); + } else if constexpr (requires { collision.mcCollision().globalIndex(); }) { + mcCollIdx = collision.mcCollision().globalIndex(); + } + if (mcCollIdx < 0) { + return; + } + + // --- Truth QA: charged physical primaries --- + auto truth = mcParticles.sliceBy(mcParticlesPerCollision, mcCollIdx); + for (auto const& mcPart : truth) { + if (!mcPart.isPhysicalPrimary()) { + continue; + } + if (mcPart.pt() < lstarCutMCPtMin.value || std::abs(mcPart.eta()) > lstarCutMCEtaMax.value) { + continue; + } + if (chargeFromPdg(mcPart.pdgCode()) == 0) { + continue; + } + histos.fill(HIST("hMcPrimariesPtEta"), mcPart.pt(), mcPart.eta()); + } + + // --- Reco->MC matching QA --- + const auto collIdx = collision.globalIndex(); + for (auto const& trk : tracks) { + if (trk.collisionId() != collIdx) { + continue; + } + if (!passTrackQuality(trk)) { + continue; + } + + if constexpr (requires { trk.has_mcParticle(); trk.mcParticle(); }) { + if (trk.has_mcParticle()) { + const auto mcPart = trk.mcParticle(); + histos.fill(HIST("hRecoMatchedPdg"), mcPart.pdgCode()); + } else { + histos.fill(HIST("hRecoFakePtEta"), trk.pt(), trk.eta()); + } + } + } + } + + PROCESS_SWITCH(Lambdastarproxy, processMCQA, + "AO2D-MC: fill truth and reco-matching QA histograms", false); + + // Helper: fill TPC dE/dx vs total momentum if TPC signal is available + template + void fillTPCdEdxVsPIfAvailable(const TTrack& trk) + { + if (lstarEnablePidQA.value == 0) { + return; + } + // aod::TracksExtra provides tpcSignal(); keep the constexpr-guard for robustness + if constexpr (requires { trk.tpcSignal(); }) { + const float p = trk.p(); + histos.fill(HIST("hTPCdEdxVsP"), p, trk.tpcSignal()); + } + } + + // Helper: fill TOF beta vs total momentum if beta is available (and looks valid) + template + void fillTOFBetaVsPIfAvailable(const TTrack& trk) + { + if (lstarEnablePidQA.value == 0) { + return; + } + if constexpr (requires { trk.beta(); }) { + bool hasTof = true; + if constexpr (requires { trk.hasTOF(); }) { + hasTof = trk.hasTOF(); + } + const float beta = trk.beta(); + // Guard against default/invalid values for tracks without TOF match + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP"), trk.p(), beta); + } + } + } + + // --- Per-species PID QA helpers --- + template + static bool hasTOFMatch(const TTrack& trk) + { + if constexpr (requires { trk.hasTOF(); }) { + return trk.hasTOF(); + } + return true; // fallback: if column not present, assume available + } + + // Return: 0=#pi, 1=K, 2=p, 3=d, -1=unclassified + template + int classifyPidSpecies(const TTrack& trk) + { + const bool hasTof = hasTOFMatch(trk); + + auto score = [hasTof](float nsTPC, float nsTOF) { + return std::abs(nsTPC) + (hasTof ? std::abs(nsTOF) : 0.f); + }; + + float bestScore = 1e9f; + int best = -1; + + // pion + { + const float nsTPC = trk.tpcNSigmaPi(); + const float nsTOF = trk.tofNSigmaPi(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCPi.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFPi.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 0; + } + } + } + + // kaon + { + const float nsTPC = trk.tpcNSigmaKa(); + const float nsTOF = trk.tofNSigmaKa(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCKaon.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFKaon.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 1; + } + } + } + + // proton + { + const float nsTPC = trk.tpcNSigmaPr(); + const float nsTOF = trk.tofNSigmaPr(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCPr.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFPr.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 2; + } + } + } + + // deuteron + { + const float nsTPC = trk.tpcNSigmaDe(); + const float nsTOF = trk.tofNSigmaDe(); + const bool pass = (std::abs(nsTPC) < lstarCutNsigmaTPCDe.value) && (!hasTof || (std::abs(nsTOF) < lstarCutNsigmaTOFDe.value)); + if (pass) { + const float sc = score(nsTPC, nsTOF); + if (sc < bestScore) { + bestScore = sc; + best = 3; + } + } + } + + return best; + } + + // Helper to compute invariant mass from two 3-momenta and masses + static double invariantMass(float px1, float py1, float pz1, double m1, + float px2, float py2, float pz2, double m2) + { + const double e1 = std::sqrt(m1 * m1 + px1 * px1 + py1 * py1 + pz1 * pz1); + const double e2 = std::sqrt(m2 * m2 + px2 * px2 + py2 * py2 + pz2 * pz2); + const double ex = px1 + px2; + const double ey = py1 + py2; + const double ez = pz1 + pz2; + const double eTot = e1 + e2; + const double p2Tot = ex * ex + ey * ey + ez * ez; + const double m2Tot = eTot * eTot - p2Tot; + return m2Tot > 0. ? std::sqrt(m2Tot) : 0.; + } + + void process(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks) + { + // Event selection (cfgTrigger) -- AO2D only + if (!keepCollisionAO2D(collision)) { + return; + } + // physics masses (GeV/c^2) + constexpr double MassProton = o2::constants::physics::MassProton; + constexpr double MassKaonCharged = o2::constants::physics::MassKaonCharged; + + // --- Inclusive PID QA: keep #pi/K/p/d bands in TPC dE/dx and TOF beta plots --- + if (lstarEnablePidQA.value != 0) { + for (auto const& trk : tracks) { + if (trk.pt() < lstarCutPtMin.value || std::abs(trk.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trk)) { + continue; + } + if (trk.sign() == 0) { + continue; + } + // Inclusive PID QA + fillTPCdEdxVsPIfAvailable(trk); + fillTOFBetaVsPIfAvailable(trk); + + // Per-species PID-QA (tagged) histograms + const int sp = classifyPidSpecies(trk); + switch (sp) { + case 0: { // pion + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_Pi"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_Pi"), trk.p(), beta); + } + } + break; + } + + case 1: { // kaon + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_K"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_K"), trk.p(), beta); + } + } + break; + } + + case 2: { // proton + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_P"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_P"), trk.p(), beta); + } + } + break; + } + + case 3: { // deuteron + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_D"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_D"), trk.p(), beta); + } + } + break; + } + + default: + break; + } + } + } + + std::vector kaonCands; + std::vector proxyCands; + std::vector protonCands; + kaonCands.reserve(128); + proxyCands.reserve(32); + protonCands.reserve(128); + + float eventMultFallback = 0.f; // fallback mixing variable: number of selected charged tracks (after quality cuts) + + // Inclusive PID QA loop: count all selected charged tracks for fallback multiplicity + for (auto const& trk : tracks) { + if (trk.pt() < lstarCutPtMin.value || std::abs(trk.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trk)) { + continue; + } + if (trk.sign() == 0) { + continue; + } + eventMultFallback += 1.f; + if (lstarEnablePidQA.value == 0) { + continue; + } + // Inclusive PID QA + fillTPCdEdxVsPIfAvailable(trk); + fillTOFBetaVsPIfAvailable(trk); + + // Per-species PID-QA (tagged) histograms + const int sp = classifyPidSpecies(trk); + switch (sp) { + case 0: { // pion + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_Pi"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_Pi"), trk.p(), beta); + } + } + break; + } + case 1: { // kaon + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_K"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_K"), trk.p(), beta); + } + } + break; + } + case 2: { // proton + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_P"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_P"), trk.p(), beta); + } + } + break; + } + case 3: { // deuteron + if constexpr (requires { trk.tpcSignal(); }) { + histos.fill(HIST("hTPCdEdxVsP_D"), trk.p(), trk.tpcSignal()); + } + if constexpr (requires { trk.beta(); }) { + const bool hasTof = hasTOFMatch(trk); + const float beta = trk.beta(); + if (hasTof && beta > TofBetaMin && beta < TofBetaMax) { + histos.fill(HIST("hTOFBetaVsP_D"), trk.p(), beta); + } + } + break; + } + default: + break; + } + } + + // Compute event multiplicity (FT0M or fallback) + const float eventMult = eventMultiplicityFT0MOrFallback(collision, eventMultFallback); + + // Deuteron candidates -> proton-proxy candidates + for (auto const& trkD : tracks) { + if (trkD.pt() < lstarCutPtMin.value || std::abs(trkD.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trkD)) { + continue; + } + if (trkD.sign() == 0) { + continue; + } + + // PID for deuteron candidates + const float nsTPCDe = trkD.tpcNSigmaDe(); + const float nsTOFDe = trkD.tofNSigmaDe(); + const bool hasTofDe = hasTOFMatch(trkD); + const bool isDeuteron = (std::abs(nsTPCDe) < lstarCutNsigmaTPCDe.value) && + (!hasTofDe || (std::abs(nsTOFDe) < lstarCutNsigmaTOFDe.value)); + if (!isDeuteron) { + continue; + } + + // Deuteron kinematics + const float ptD = trkD.pt(); + const float etaD = trkD.eta(); + const float phiD = trkD.phi(); + const double pD = static_cast(ptD) * std::cosh(static_cast(etaD)); + + // QA histos for deuteron PID and kinematics + if (lstarEnablePidQA.value != 0) { + histos.fill(HIST("hDeuteronProxyPt"), ptD); + histos.fill(HIST("hDeuteronProxyEta"), etaD); + histos.fill(HIST("hDeuteronProxyPhi"), phiD); + histos.fill(HIST("hNsigmaTPCDeuteron"), nsTPCDe); + histos.fill(HIST("hNsigmaTOFDeuteron"), nsTOFDe); + histos.fill(HIST("hNsigmaTPCDeuteronVsP"), pD, nsTPCDe); + histos.fill(HIST("hNsigmaTOFDeuteronVsP"), pD, nsTOFDe); + } + + // build proton-proxy momentum from deuteron: p_p ≈ p_d / 2 + const float pxProxy = ProxyMomentumScale * ptD * std::cos(phiD); + const float pyProxy = ProxyMomentumScale * ptD * std::sin(phiD); + const float pzProxy = ProxyMomentumScale * ptD * std::sinh(etaD); + + proxyCands.push_back(ProxyCand{pxProxy, pyProxy, pzProxy, static_cast(trkD.sign()), static_cast(trkD.globalIndex())}); + } + + // Proton candidates (for genuine pK #Lambda^{*} reconstruction) + for (auto const& trkP : tracks) { + if (trkP.pt() < lstarCutPtMin.value || std::abs(trkP.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trkP)) { + continue; + } + if (trkP.sign() == 0) { + continue; + } + + const float nsTPCPr = trkP.tpcNSigmaPr(); + const float nsTOFPr = trkP.tofNSigmaPr(); + const bool hasTofPr = hasTOFMatch(trkP); + const bool isProton = (std::abs(nsTPCPr) < lstarCutNsigmaTPCPr.value) && + (!hasTofPr || (std::abs(nsTOFPr) < lstarCutNsigmaTOFPr.value)); + if (!isProton) { + continue; + } + + const float ptP = trkP.pt(); + const float etaP = trkP.eta(); + const float phiP = trkP.phi(); + + const float pxP = ptP * std::cos(phiP); + const float pyP = ptP * std::sin(phiP); + const float pzP = ptP * std::sinh(etaP); + + protonCands.push_back(ProtonCand{pxP, pyP, pzP, static_cast(trkP.sign()), static_cast(trkP.globalIndex())}); + } + + // Kaon candidates + for (auto const& trkK : tracks) { + if (trkK.pt() < lstarCutPtMin.value || std::abs(trkK.eta()) > lstarCutEtaMax.value) { + continue; + } + if (!passTrackQuality(trkK)) { + continue; + } + if (trkK.sign() == 0) { + continue; + } + + // PID for kaon candidates + const float nsTPCK = trkK.tpcNSigmaKa(); + const float nsTOFK = trkK.tofNSigmaKa(); + const bool hasTofK = hasTOFMatch(trkK); + const bool isKaon = (std::abs(nsTPCK) < lstarCutNsigmaTPCKaon.value) && + (!hasTofK || (std::abs(nsTOFK) < lstarCutNsigmaTOFKaon.value)); + if (!isKaon) { + continue; + } + + // Kaon kinematics + const float ptK = trkK.pt(); + const float etaK = trkK.eta(); + const float phiK = trkK.phi(); + const double pK = static_cast(ptK) * std::cosh(static_cast(etaK)); + + // Kaon QA + if (lstarEnablePidQA.value != 0) { + histos.fill(HIST("hKaonPt"), ptK); + histos.fill(HIST("hKaonEta"), etaK); + histos.fill(HIST("hKaonPhi"), phiK); + histos.fill(HIST("hNsigmaTPCKaon"), nsTPCK); + histos.fill(HIST("hNsigmaTOFKaon"), nsTOFK); + histos.fill(HIST("hNsigmaTPCKaonVsP"), pK, nsTPCK); + histos.fill(HIST("hNsigmaTOFKaonVsP"), pK, nsTOFK); + } + + const float pxK = ptK * std::cos(phiK); + const float pyK = ptK * std::sin(phiK); + const float pzK = ptK * std::sinh(etaK); + + kaonCands.push_back(KaonCand{pxK, pyK, pzK, static_cast(trkK.sign()), static_cast(trkK.globalIndex())}); + } + + if (proxyCands.empty() || kaonCands.empty()) { + // still update mixing buffer so that later events can mix with this one + LStarMixEventEntry entry; + entry.mult = eventMult; + entry.zvtx = collision.posZ(); + entry.kaons = std::move(kaonCands); + entry.proxies = std::move(proxyCands); + mLStarMixEvents.push_front(std::move(entry)); + if (mLStarMixEvents.size() > static_cast(lstarNoMixedEvents.value)) { + mLStarMixEvents.pop_back(); + } + return; + } + + // --- SAME-EVENT: genuine pK #Lambda^{*} candidates --- + for (auto const& pr : protonCands) { + for (auto const& k : kaonCands) { + if (pr.tid == k.tid) { + continue; + } + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, + k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); + const float phiPair = phiFromPxPy(pxTot, pyTot); + + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const float yPair = rapidityFromEPz(eTot, pzTot); + + if (std::abs(yPair) > lstarLambdaAbsYMax.value) { + continue; + } + + const bool unlikeSignPK = (pr.charge * k.charge) < 0; + if (unlikeSignPK) { + histos.fill(HIST("hInvMassPKUnlike"), mass); + histos.fill(HIST("hInvMassPKUnlikeVsPt"), mass, ptPair); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKUnlikeSparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } else { + histos.fill(HIST("hInvMassPKLike"), mass); + histos.fill(HIST("hInvMassPKLikeVsPt"), mass, ptPair); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarPKLikeSparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } + } + } + + // --- SAME-EVENT: proxy (d/2) + K --- + for (auto const& pr : proxyCands) { + for (auto const& k : kaonCands) { + if (pr.tid == k.tid) + continue; // sanity check: should never match, but just in case of bug in candidate-building logic + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); + const float phiPair = phiFromPxPy(pxTot, pyTot); + + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const float yPair = rapidityFromEPz(eTot, pzTot); + + // Inclusive invariant-mass spectrum for the #Lambda^{*} proxy (d/2 + K) + histos.fill(HIST("hDeuteronProxyMass"), mass); + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarProxySparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } + } + + // --- MIXED-EVENT: current proxies + previous-event kaons --- + for (auto const& prev : mLStarMixEvents) { + if (std::abs(prev.zvtx - collision.posZ()) > lstarMixZvtxMax.value) + continue; + if (std::abs(prev.mult - eventMult) > lstarMixMultMax.value) + continue; + if (prev.kaons.empty()) { + continue; + } + + for (auto const& pr : proxyCands) { + for (auto const& k : prev.kaons) { + // convention: mix for unlike-sign only (resonance background) + if ((pr.charge * k.charge) >= 0) { + continue; + } + if (pr.tid == k.tid) + continue; // sanity check: should never match, but just in case of bug in candidate-building logic + + const double mass = invariantMass(pr.px, pr.py, pr.pz, MassProton, k.px, k.py, k.pz, MassKaonCharged); + + const float pxTot = pr.px + k.px; + const float pyTot = pr.py + k.py; + const float pzTot = pr.pz + k.pz; + const float ptPair = std::sqrt(pxTot * pxTot + pyTot * pyTot); + const float phiPair = phiFromPxPy(pxTot, pyTot); + + const double eTot = std::sqrt(mass * mass + static_cast(pxTot) * pxTot + static_cast(pyTot) * pyTot + static_cast(pzTot) * pzTot); + const float yPair = rapidityFromEPz(eTot, pzTot); + + // Fill mixed-event THnSparse (proxy only) + if (lstarEnableSparse.value != 0) { + histos.fill(HIST("hLambdaStarProxyMixedSparse"), mass, ptPair, yPair, phiPair, eventMult); + } + } + } + } + + // --- Update mixing buffer with current event --- + LStarMixEventEntry entry; + entry.mult = eventMult; + entry.zvtx = collision.posZ(); + entry.kaons = std::move(kaonCands); + entry.proxies = std::move(proxyCands); + + mLStarMixEvents.push_front(std::move(entry)); + if (mLStarMixEvents.size() > static_cast(lstarNoMixedEvents.value)) { + mLStarMixEvents.pop_back(); + } + } + + PROCESS_SWITCH(Lambdastarproxy, process, "Lambda* proxy via (d/2)+K", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/TwoParticleCorrelations/Tasks/particleOriginAnalysis.cxx b/PWGCF/TwoParticleCorrelations/Tasks/particleOriginAnalysis.cxx new file mode 100644 index 00000000000..847ed0b46e0 --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/particleOriginAnalysis.cxx @@ -0,0 +1,454 @@ +// 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 particleOriginAnalysis.cxx +/// \brief Classifies filtered physical primary identified particles as prompt +/// (from string fragmentation) or from resonance decay by inspecting +/// the MC mother chain. Produces per-species prompt/decay fractions +/// and mother identity distributions vs pT and centrality. +/// Designed for generator-level MC studies of balance function +/// origin decomposition across collision systems. +/// Consumes the filtered tables produced by dptDptFilter. +/// \author victor.gonzalez.sebastian@gmail.com + +#include "PWGCF/Core/AnalysisConfigurableCuts.h" +#include "PWGCF/DataModel/DptDptFiltered.h" +#include "PWGCF/TableProducer/dptDptFilter.h" + +#include "Common/Core/TableHelper.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::soa; +using namespace o2::framework::expressions; + +#define FORMATSTRING(theformat, theparams...) TString::Format(theformat, theparams).Data() + +namespace particleorigintask +{ +using namespace o2::analysis::dptdptfilter; + +// ============================================================================ +// Compact encoding of the mother resonance identity +// ============================================================================ +enum MotherSpecies { + kMothPrompt = 0, ///< not from decay (prompt from hadronization) + kMothRho0, ///< rho0(770) - PDG 113 + kMothRhoCharged, ///< rho+/-(770) - PDG 213 + kMothOmega782, ///< omega(782) - PDG 223 + kMothEta, ///< eta - PDG 221 + kMothEtaPrime, ///< eta'(958) - PDG 331 + kMothKStar892Ch, ///< K*(892)+/- - PDG 323 + kMothKStar892_0, ///< K*(892)0 - PDG 313 + kMothPhi1020, ///< phi(1020) - PDG 333 + kMothDelta, ///< Delta(1232) all - PDG 1114,2114,2214,2224 + kMothSigmaStar, ///< Sigma*(1385) - PDG 3114,3214,3224 + kMothLambda1520, ///< Lambda(1520) - PDG 3124 + kMothF0_980, ///< f0(980) - PDG 9010221 + kMothOtherMeson, ///< other meson mothers + kMothOtherBaryon, ///< other baryon mothers + kNMotherSpecies +}; + +static const char* motherLabel[kNMotherSpecies] = { + "prompt", "#rho^{0}", "#rho^{#pm}", "#omega", "#eta", "#eta'", + "K*^{#pm}", "K*^{0}", "#phi", + "#Delta", "#Sigma*", "#Lambda(1520)", + "f_{0}(980)", "other meson", "other baryon"}; + +// PDG codes used from TPDGCode.h (ROOT): +// kRho770_0 (113), kRho770Plus (213), kLambda1520 (3124), +// kPiPlus (211), kKPlus (321), kProton (2212) +// PDG codes used from CommonConstants/PhysicsConstants.h (O2): +// o2::constants::physics::Pdg::kEta (221), kOmega (223), kEtaPrime (331), +// kK0Star892 (313), kKPlusStar892 (323), kPhi (333) +// PDG codes NOT in either header - defined here: +static constexpr int KPdgDeltaMinusMinus = 1114; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgDelta0 = 2114; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgDeltaPlus = 2214; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgDeltaPlusPlus = 2224; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgSigmaStarMinus = 3114; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgSigmaStar0 = 3214; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgSigmaStarPlus = 3224; // o2-linter: disable=pdg/explicit-code(not existing) +static constexpr int KPdgF0_980 = 9010221; // o2-linter: disable=pdg/explicit-code(not existing),name/function-variable(clashes with f0),name/constexpr-constant(clashes with f0) + +/// PDG codes below this threshold are mesons; at or above are baryons +static constexpr int KPdgBaryonThreshold = 1000; // o2-linter: disable=pdg/explicit-code(not a PDG code) + +/// \brief Encode absolute PDG code of a mother into compact bin index +inline int encodeMotherPDG(int absPdg) +{ + using namespace o2::constants::physics; + switch (absPdg) { + case kRho770_0: + return kMothRho0; + case kRho770Plus: /* kRho770Minus is just -213, we use abs */ + return kMothRhoCharged; + case Pdg::kOmega: + return kMothOmega782; + case Pdg::kEta: + return kMothEta; + case Pdg::kEtaPrime: + return kMothEtaPrime; + case Pdg::kKPlusStar892: + return kMothKStar892Ch; + case Pdg::kK0Star892: + return kMothKStar892_0; + case Pdg::kPhi: + return kMothPhi1020; + case KPdgDeltaMinusMinus: + case KPdgDelta0: + case KPdgDeltaPlus: + case KPdgDeltaPlusPlus: + return kMothDelta; + case KPdgSigmaStarMinus: + case KPdgSigmaStar0: + case KPdgSigmaStarPlus: + return kMothSigmaStar; + case kLambda1520: + return kMothLambda1520; + case KPdgF0_980: + return kMothF0_980; + default: + return (absPdg < KPdgBaryonThreshold) ? kMothOtherMeson : kMothOtherBaryon; + } +} + +/// PDG codes above this threshold correspond to hadrons (mesons and baryons). +/// Below are quarks (1-6), leptons (11-16), gauge bosons (21-25), and +/// special/internal generator codes. +static constexpr int KPdgHadronThreshold = 100; // o2-linter: disable=pdg/explicit-code(not a PDG code) + +// ============================================================================ +// Classification utilities +// ============================================================================ + +/// \brief Check if a mother is a beam or initial-state particle +/// using its status code rather than just its PDG code +inline bool isBeamParticle(auto const& mother) +{ + int status = mother.getGenStatusCode(); + // Pythia status codes 11-19: beam particles and event-setup entries + // HepMC status 4: beam particles + static constexpr int BEAMSTATUSCODEMIN = 11; + static constexpr int BEAMSTATUSCODEMAX = 19; + static constexpr int HEPMCBEAMSTATUSCODE = 4; + + return (status >= BEAMSTATUSCODEMIN && status <= BEAMSTATUSCODEMAX) || mother.getHepMCStatusCode() == HEPMCBEAMSTATUSCODE; +} + +/// \brief Classify a physical primary by its immediate mother +/// \return {isFromDecay, motherPdgCode} +template +inline std::pair classifyImmediate(McParticleObject const& particle, + McParticlesTable const& /*mcParticles*/) +{ + if (!particle.has_mothers()) { + return {false, 0}; + } + auto mother = particle.template mothers_first_as(); + int absMomPdg = std::abs(mother.pdgCode()); + if (absMomPdg > KPdgHadronThreshold && !isBeamParticle(mother)) { + return {true, mother.pdgCode()}; + } + return {false, 0}; +} + +/// \brief Trace back to the earliest hadronic ancestor +/// \return {isFromDecay, originalAncestorPdgCode} +template +inline std::pair classifyAncestor(McParticleObject const& particle, + McParticlesTable const& mcParticles) +{ + /* reuse classifyImmediate for the first step */ + auto [isFromDecay, immediatePdg] = classifyImmediate(particle, mcParticles); + if (!isFromDecay) { + return {false, 0}; + } + + /* the immediate mother is hadronic; now walk up to find the original resonance */ + auto current = particle.template mothers_first_as(); + int originalPdg = current.pdgCode(); + constexpr int KMaxDepth = 20; + for (int depth = 0; current.has_mothers() && depth < KMaxDepth; ++depth) { + auto grandparent = current.template mothers_first_as(); + if (std::abs(grandparent.pdgCode()) <= KPdgHadronThreshold || isBeamParticle(grandparent)) { + break; + } + originalPdg = grandparent.pdgCode(); + current = grandparent; + } + return {true, originalPdg}; +} + +} // namespace particleorigintask + +// ============================================================================ +// The analysis task +// ============================================================================ +struct ParticleOriginAnalysis { + + /* the histogram registry */ + HistogramRegistry registry{"ParticleOriginData", {}, OutputObjHandlingPolicy::AnalysisObject}; + + /* the species and track names from configuration */ + std::vector poinames; ///< the species of interest names + std::vector tnames; ///< the track names + + /* the number of track ids from configuration */ + size_t nch = 0; + + /* histogram pointers for direct access */ + /* per track id histograms: indexed by trackacceptedid */ + static constexpr int KNMo = particleorigintask::kNMotherSpecies; + + std::vector> fhPromptVsPt; ///< prompt counts vs pT, per track id + std::vector> fhDecayVsPt; ///< from-decay counts vs pT, per track id + std::vector> fhPromptVsCentVsPt; ///< prompt counts vs (cent, pT), per track id + std::vector> fhDecayVsCentVsPt; ///< from-decay counts vs (cent, pT), per track id + std::vector> fhMotherVsPtVsCent; ///< immediate mother (encoded) vs pT vs cent, per track id + std::vector> fhAncestorVsPtVsCent; ///< earliest ancestor (encoded) vs pT vs cent, per track id + std::vector> fhMotherPDG; ///< immediate mother |PDG| (fine, 1D safety net), per track id + std::vector> fhAncestorPDG; ///< earliest ancestor |PDG| (fine, 1D safety net), per track id + + void init(InitContext& initContext) + { + using namespace particleorigintask; + using namespace o2::analysis::dptdptfilter; + + /* self configure the binning from the filter task */ + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mPTbins", ptbins, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mPTmin", ptlow, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mPTmax", ptup, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mEtabins", etabins, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mEtamin", etalow, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mEtamax", etaup, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mZVtxbins", zvtxbins, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mZVtxmin", zvtxlow, false); + getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgBinning.mZVtxmax", zvtxup, false); + + /* self configure the desired species */ + o2::analysis::dptdptfilter::PIDSpeciesSelection pidselector; + std::vector cfgnames = {"cfgElectronPIDSelection", "cfgMuonPIDSelection", "cfgPionPIDSelection", "cfgKaonPIDSelection", "cfgProtonPIDSelection"}; + std::vector spids = {0, 1, 2, 3, 4}; + for (uint i = 0; i < cfgnames.size(); ++i) { + auto includeIt = [&pidselector, &initContext](int spid, auto name) { + bool mUseIt = false; + bool mExcludeIt = false; + if (getTaskOptionValue(initContext, "dpt-dpt-filter-tracks", TString::Format("%s.mUseIt", name.c_str()).Data(), mUseIt, false) && + getTaskOptionValue(initContext, "dpt-dpt-filter-tracks", TString::Format("%s.mExclude", name.c_str()).Data(), mExcludeIt, false)) { + if (mUseIt && !mExcludeIt) { + auto cfg = new o2::analysis::TrackSelectionPIDCfg(); + cfg->mUseIt = true; + cfg->mExclude = false; + pidselector.addSpecies(spid, cfg); + } + } + }; + includeIt(spids[i], cfgnames[i]); + } + uint nspecies = pidselector.getNSpecies(); + if (nspecies == 0) { + /* unidentified analysis */ + poinames.push_back(pidselector.getHadFName()); + tnames.push_back(std::string(TString::Format("%sP", pidselector.getHadFName()).Data())); + tnames.push_back(std::string(TString::Format("%sM", pidselector.getHadFName()).Data())); + LOGF(info, "Incorporated species name %s to the analysis", poinames[0].c_str()); + } else { + for (uint8_t ix = 0; ix < nspecies; ++ix) { + poinames.push_back(std::string(pidselector.getSpeciesFName(ix))); + tnames.push_back(std::string(TString::Format("%sP", pidselector.getSpeciesFName(ix)).Data())); + tnames.push_back(std::string(TString::Format("%sM", pidselector.getSpeciesFName(ix)).Data())); + LOGF(info, "Incorporated species name %s to the analysis", poinames[ix].c_str()); + } + } + nch = tnames.size(); + + /* self configure centrality/multiplicity ranges from the filter task */ + int nCentBins = 1; + std::vector centBinEdges = {0.0f, 100.0f}; + std::string centspec; + if (getTaskOptionValue(initContext, "dpt-dpt-filter", "cfgCentSpec", centspec, false)) { + LOGF(info, "Got the centralities specification: %s", centspec.c_str()); + auto tokens = TString(centspec.c_str()).Tokenize(","); + nCentBins = tokens->GetEntries(); + centBinEdges.clear(); + for (int i = 0; i < nCentBins; ++i) { + double cmmin = 0.0; + double cmmax = 0.0; + sscanf(tokens->At(i)->GetName(), "%lf-%lf", &cmmin, &cmmax); + if (i == 0) { + centBinEdges.push_back(cmmin); + } + centBinEdges.push_back(cmmax); + } + delete tokens; + } else { + LOGF(info, "No centralities specification. Setting it to: 0-100"); + } + + /* build the centrality axis with variable bin edges */ + const AxisSpec centAxis{centBinEdges, "centrality (%)"}; + const AxisSpec ptAxis{ptbins, ptlow, ptup, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec motherAxis{KNMo, -0.5f, KNMo - 0.5f, "mother species"}; + const AxisSpec pdgAxis{100, 0.5f, 100.5f, "species"}; + const AxisSpec zvtxAxis{zvtxbins, zvtxlow, zvtxup, "#it{z}_{vtx}"}; + + /* resize the histogram vectors */ + fhPromptVsPt.resize(nch, nullptr); + fhDecayVsPt.resize(nch, nullptr); + fhPromptVsCentVsPt.resize(nch, nullptr); + fhDecayVsCentVsPt.resize(nch, nullptr); + fhMotherVsPtVsCent.resize(nch, nullptr); + fhAncestorVsPtVsCent.resize(nch, nullptr); + fhMotherPDG.resize(nch, nullptr); + fhAncestorPDG.resize(nch, nullptr); + + /* per track id histograms */ + for (uint i = 0; i < nch; ++i) { + const char* tname = tnames[i].c_str(); + + fhPromptVsPt[i] = registry.add( + FORMATSTRING("PromptVsPt_%s", tname), + FORMATSTRING("Prompt %s;#it{p}_{T} (GeV/#it{c});counts", tname), + kTH1F, {ptAxis}); + + fhDecayVsPt[i] = registry.add( + FORMATSTRING("DecayVsPt_%s", tname), + FORMATSTRING("From decay %s;#it{p}_{T} (GeV/#it{c});counts", tname), + kTH1F, {ptAxis}); + + fhPromptVsCentVsPt[i] = registry.add( + FORMATSTRING("PromptVsCentVsPt_%s", tname), + FORMATSTRING("Prompt %s;centrality (%%);#it{p}_{T} (GeV/#it{c})", tname), + kTH2F, {centAxis, ptAxis}); + + fhDecayVsCentVsPt[i] = registry.add( + FORMATSTRING("DecayVsCentVsPt_%s", tname), + FORMATSTRING("From decay %s;centrality (%%);#it{p}_{T} (GeV/#it{c})", tname), + kTH2F, {centAxis, ptAxis}); + + fhMotherVsPtVsCent[i] = registry.add( + FORMATSTRING("MotherVsPtVsCent_%s", tname), + FORMATSTRING("Immediate mother of %s;mother;#it{p}_{T} (GeV/#it{c});centrality (%%)", tname), + kTH3F, {motherAxis, ptAxis, centAxis}); + + fhAncestorVsPtVsCent[i] = registry.add( + FORMATSTRING("AncestorVsPtVsCent_%s", tname), + FORMATSTRING("Earliest ancestor of %s;ancestor;#it{p}_{T} (GeV/#it{c});centrality (%%)", tname), + kTH3F, {motherAxis, ptAxis, centAxis}); + + /* label the encoded mother/ancestor axis */ + for (int im = 0; im < KNMo; ++im) { + fhMotherVsPtVsCent[i]->GetXaxis()->SetBinLabel(im + 1, motherLabel[im]); + fhAncestorVsPtVsCent[i]->GetXaxis()->SetBinLabel(im + 1, motherLabel[im]); + } + + fhMotherPDG[i] = registry.add( + FORMATSTRING("MotherPDG_%s", tname), + FORMATSTRING("Immediate mother PDG of %s from decay;PDG code;counts", tname), + kTH1F, {pdgAxis}); + + fhAncestorPDG[i] = registry.add( + FORMATSTRING("AncestorPDG_%s", tname), + FORMATSTRING("Earliest ancestor PDG of %s from decay;PDG code;counts", tname), + kTH1F, {pdgAxis}); + } + } + + /// \brief Fill the origin classification histograms for one accepted particle + /// \param tid the trackacceptedid from the filter + /// \param centmult the centrality/multiplicity percentile + /// \param pt the particle transverse momentum + /// \param isFromDecay true if immediate mother is a hadron + /// \param immediatePdg the PDG code of the immediate mother + /// \param isFromDecayFull true if earliest ancestor is a hadron + /// \param ancestorPdg the PDG code of the earliest hadronic ancestor + void fillOrigin(int tid, float centmult, float pt, + bool isFromDecay, int immediatePdg, + bool isFromDecayFull, int ancestorPdg) + { + using namespace particleorigintask; + + if (isFromDecay) { + fhDecayVsPt[tid]->Fill(pt); + fhDecayVsCentVsPt[tid]->Fill(centmult, pt); + int encodedMother = encodeMotherPDG(std::abs(immediatePdg)); + fhMotherVsPtVsCent[tid]->Fill(static_cast(encodedMother), pt, centmult); + fhMotherPDG[tid]->Fill(TString::Format("%d", immediatePdg).Data(), 1.0); + } else { + fhPromptVsPt[tid]->Fill(pt); + fhPromptVsCentVsPt[tid]->Fill(centmult, pt); + fhMotherVsPtVsCent[tid]->Fill(static_cast(kMothPrompt), pt, centmult); + } + if (isFromDecayFull) { + int encodedAncestor = encodeMotherPDG(std::abs(ancestorPdg)); + fhAncestorVsPtVsCent[tid]->Fill(static_cast(encodedAncestor), pt, centmult); + fhAncestorPDG[tid]->Fill(TString::Format("%d", ancestorPdg).Data(), 1.0); + } else { + fhAncestorVsPtVsCent[tid]->Fill(static_cast(kMothPrompt), pt, centmult); + } + } + + Filter onlyacceptedcollisions = (aod::dptdptfilter::collisionaccepted == uint8_t(true)); + + /// \brief Process: one accepted generator-level collision at a time + /// with its associated MC particles joined with filter information. + /// Follows the processGenLevelNotStored / processSame pattern. + void process(soa::Filtered>::iterator const& collision, + soa::Join const& particles) + { + using namespace particleorigintask; + using namespace o2::analysis::dptdptfilter; + + float centmult = collision.centmult(); + + for (auto const& particle : particles) { + int8_t tid = particle.trackacceptedid(); + if (tid < 0) { + /* particle not accepted */ + continue; + } + float pt = particle.pt(); + + /* classify origin using the McParticles mother chain */ + auto [isFromDecay, immediatePdg] = classifyImmediate(particle, particles); + auto [isFromDecayFull, ancestorPdg] = classifyAncestor(particle, particles); + + /* fill histograms indexed by trackacceptedid */ + fillOrigin(tid, centmult, pt, isFromDecay, immediatePdg, + isFromDecayFull, ancestorPdg); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx index 40e73e8ee0e..2ae92312225 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx @@ -118,7 +118,9 @@ struct PidDiHadron { O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 4 = kshort, 5 = lambda, 6 = phi, 0 for no PID") O2_DEFINE_CONFIGURABLE(cfgGetNsigmaQA, bool, true, "Get QA histograms for selection of pions, kaons, and protons") + O2_DEFINE_CONFIGURABLE(cfgGetdEdx, bool, true, "Get dEdx histograms for pions, kaons, and protons") O2_DEFINE_CONFIGURABLE(cfgUseAntiLambda, bool, true, "Use AntiLambda candidates for analysis") + O2_DEFINE_CONFIGURABLE(cfgPIDUseRejection, bool, true, "True: use exclusion exclusion criteria for PID determination, false: don't use exclusion") struct : ConfigurableGroup { O2_DEFINE_CONFIGURABLE(cfgMultCentHighCutFunction, std::string, "[0] + [1]*x + [2]*x*x + [3]*x*x*x + [4]*x*x*x*x + 10.*([5] + [6]*x + [7]*x*x + [8]*x*x*x + [9]*x*x*x*x)", "Functional for multiplicity correlation cut"); @@ -171,6 +173,7 @@ struct PidDiHadron { ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; ConfigurableAxis axisTpcSignal{"axisTpcSignal", {250, 0, 250}, "dEdx axis for TPC"}; + ConfigurableAxis axisSigma{"axisSigma", {200, 0, 20}, "sigma axis for TPC"}; Configurable> cfgUseEventCuts{"cfgUseEventCuts", {LongArrayInt[0], 15, 1, {"Filtered Events", "Sel8", "kNoTimeFrameBorder", "kNoITSROFrameBorder", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "kNoCollInTimeRangeStandard", "kIsGoodITSLayersAll", "kNoCollInRofStandard", "kNoHighMultCollInPrevRof", "Occupancy", "Multcorrelation", "T0AV0ACut", "kIsVertexITSTPC", "kTVXinTRD"}, {"EvCuts"}}, "Labeled array (int) for various cuts on resonances"}; Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 6, 3, {"UpCut_pi", "UpCut_ka", "UpCut_pr", "LowCut_pi", "LowCut_ka", "LowCut_pr"}, {"TPC", "TOF", "ITS"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; @@ -496,15 +499,22 @@ struct PidDiHadron { if (!cfgUseItsPID) { histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - } + + if (cfgGetdEdx) { + histos.add("TpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpSigma_ptwise", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); + + histos.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpSigma_ptwise_afterCut", "", {HistType::kTHnSparseD, {{axisPt, axisSigma, axisNsigmaTOF}}}); + } + } // TPC-TOF PID QA hists if (cfgUseItsPID) { histos.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPt}}}); histos.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{axisNsigmaITS, axisNsigmaTOF, axisPt}}}); - } - - histos.add("TpcdEdx_ptwise", "", {HistType::kTH2D, {{axisTpcSignal, axisPt}}}); - histos.add("TpcdEdx_ptwise_afterCut", "", {HistType::kTH2D, {{axisTpcSignal, axisPt}}}); - } + } // ITS-TOF PID QA hists + } // end of PID QA hists } if (cfgPIDParticle == kK0 || cfgPIDParticle == kLambda || cfgPIDParticle == kPhi) { @@ -526,6 +536,20 @@ struct PidDiHadron { histos.add("hNsigmaPionTrue", "hNsigmaPionTrue", {HistType::kTH1D, {axisPt}}); // All true pions from MC histos.add("hNsigmaKaonTrue", "hNsigmaKaonTrue", {HistType::kTH1D, {axisPt}}); // All true kaons from MC histos.add("hNsigmaProtonTrue", "hNsigmaProtonTrue", {HistType::kTH1D, {axisPt}}); // All true protons from MC + + histos.add("TpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + + histos.add("ExpTpcdEdx_ptwise_pi", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_ka", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("ExpTpcdEdx_ptwise_pr", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + + histos.add("TpcdEdx_ptwise_pi_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_ka_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + histos.add("TpcdEdx_ptwise_pr_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); + + histos.add("TpcdEdx_ptwise_all_physprim", "", {HistType::kTHnSparseD, {{axisPt, axisTpcSignal, axisNsigmaTOF}}}); } histos.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event @@ -671,7 +695,7 @@ struct PidDiHadron { isProton = isDetectedProton; } - if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { + if (cfgPIDUseRejection && ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton))) { return -1; // more than one particle satisfy the criteria } @@ -772,20 +796,44 @@ struct PidDiHadron { { switch (pid) { case 1: // For Pions - if (!cfgUseItsPID) + if (!cfgUseItsPID) { + if (cfgGetdEdx) { + double tpcExpSignalPi = track1.tpcSignal() - (track1.tpcNSigmaPi() * track1.tpcExpSigmaPi()); + + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPi()); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalPi, track1.tofNSigmaPi()); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaPi(), track1.tofNSigmaPi()); + } histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); + } if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPi(), track1.pt()); break; case 2: // For Kaons - if (!cfgUseItsPID) + if (!cfgUseItsPID) { + if (cfgGetdEdx) { + double tpcExpSignalKa = track1.tpcSignal() - (track1.tpcNSigmaKa() * track1.tpcExpSigmaKa()); + + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaKa()); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalKa, track1.tofNSigmaKa()); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaKa(), track1.tofNSigmaKa()); + } histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); + } if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaKa(), track1.pt()); break; case 3: // For Protons - if (!cfgUseItsPID) + if (!cfgUseItsPID) { + if (cfgGetdEdx) { + double tpcExpSignalPr = track1.tpcSignal() - (track1.tpcNSigmaPr() * track1.tpcExpSigmaPr()); + + histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPr()); + histos.fill(HIST("ExpTpcdEdx_ptwise_afterCut"), track1.pt(), tpcExpSignalPr, track1.tofNSigmaPr()); + histos.fill(HIST("ExpSigma_ptwise_afterCut"), track1.pt(), track1.tpcExpSigmaPr(), track1.tofNSigmaPr()); + } histos.fill(HIST("TofTpcNsigma_after"), track1.tpcNSigmaPr(), track1.tofNSigmaPr(), track1.pt()); + } if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPr(), track1.pt()); break; @@ -838,12 +886,36 @@ struct PidDiHadron { // Fill Nsigma QA if (cfgGetNsigmaQA && !cfgUseItsPID) { - if (cfgPIDParticle == kPions) + if (cfgPIDParticle == kPions) { histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaPi(), track1.tofNSigmaPi(), track1.pt()); - if (cfgPIDParticle == kKaons) + if (cfgGetdEdx) { + double tpcExpSignalPi = track1.tpcSignal() - (track1.tpcNSigmaPi() * track1.tpcExpSigmaPi()); + + histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPi()); + histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalPi, track1.tofNSigmaPi()); + histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaPi(), track1.tofNSigmaPi()); + } + } + if (cfgPIDParticle == kKaons) { histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa(), track1.pt()); - if (cfgPIDParticle == kProtons) + if (cfgGetdEdx) { + double tpcExpSignalKa = track1.tpcSignal() - (track1.tpcNSigmaKa() * track1.tpcExpSigmaKa()); + + histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaKa()); + histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalKa, track1.tofNSigmaKa()); + histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaKa(), track1.tofNSigmaKa()); + } + } + if (cfgPIDParticle == kProtons) { histos.fill(HIST("TofTpcNsigma_before"), track1.tpcNSigmaPr(), track1.tofNSigmaPr(), track1.pt()); + if (cfgGetdEdx) { + double tpcExpSignalPr = track1.tpcSignal() - (track1.tpcNSigmaPr() * track1.tpcExpSigmaPr()); + + histos.fill(HIST("TpcdEdx_ptwise"), track1.pt(), track1.tpcSignal(), track1.tofNSigmaPr()); + histos.fill(HIST("ExpTpcdEdx_ptwise"), track1.pt(), tpcExpSignalPr, track1.tofNSigmaPr()); + histos.fill(HIST("ExpSigma_ptwise"), track1.pt(), track1.tpcExpSigmaPr(), track1.tofNSigmaPr()); + } + } } if (cfgGetNsigmaQA && cfgUseItsPID) { if (cfgPIDParticle == kPions) @@ -854,18 +926,12 @@ struct PidDiHadron { histos.fill(HIST("TofItsNsigma_before"), itsResponse.nSigmaITS(track1), track1.tofNSigmaPr(), track1.pt()); } - if (cfgGetNsigmaQA) - histos.fill(HIST("TpcdEdx_ptwise"), track1.tpcSignal(), track1.pt()); - if (cfgPIDParticle && getNsigmaPID(track1) != cfgPIDParticle) continue; // if PID is selected, check if the track has the right PID if (cfgGetNsigmaQA) fillNsigmaAfterCut(track1, cfgPIDParticle); - if (cfgGetNsigmaQA) - histos.fill(HIST("TpcdEdx_ptwise_afterCut"), track1.tpcSignal(), track1.pt()); - if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { @@ -1514,9 +1580,24 @@ struct PidDiHadron { if (pidIndex == kProtons) histos.fill(HIST("hNsigmaProtonSelected"), track.pt()); + if (track.mcParticle().isPhysicalPrimary()) { + if (cfgPIDParticle == kPions) + histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + if (cfgPIDParticle == kKaons) + histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + if (cfgPIDParticle == kProtons) + histos.fill(HIST("TpcdEdx_ptwise_all_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + } + // Check the PDG code for the particles (MC truth) and match with analysed Nsigma PID if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kPiPlus) { histos.fill(HIST("hNsigmaPionTrue"), track.pt()); + histos.fill(HIST("TpcdEdx_ptwise_pi"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + if (track.mcParticle().isPhysicalPrimary()) + histos.fill(HIST("TpcdEdx_ptwise_pi_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPi()); + + double tpcExpSignalPi = track.tpcSignal() - (track.tpcNSigmaPi() * track.tpcExpSigmaPi()); + histos.fill(HIST("ExpTpcdEdx_ptwise_pi"), track.pt(), tpcExpSignalPi, track.tofNSigmaPi()); if (pidIndex == kPions) { histos.fill(HIST("hNsigmaPionTruePositives"), track.pt()); @@ -1525,6 +1606,12 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kKPlus) { histos.fill(HIST("hNsigmaKaonTrue"), track.pt()); + histos.fill(HIST("TpcdEdx_ptwise_ka"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + if (track.mcParticle().isPhysicalPrimary()) + histos.fill(HIST("TpcdEdx_ptwise_ka_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaKa()); + + double tpcExpSignalKa = track.tpcSignal() - (track.tpcNSigmaKa() * track.tpcExpSigmaKa()); + histos.fill(HIST("ExpTpcdEdx_ptwise_ka"), track.pt(), tpcExpSignalKa, track.tofNSigmaKa()); if (pidIndex == kKaons) { histos.fill(HIST("hNsigmaKaonTruePositives"), track.pt()); @@ -1533,12 +1620,17 @@ struct PidDiHadron { if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kProton) { histos.fill(HIST("hNsigmaProtonTrue"), track.pt()); + histos.fill(HIST("TpcdEdx_ptwise_pr"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + if (track.mcParticle().isPhysicalPrimary()) + histos.fill(HIST("TpcdEdx_ptwise_pr_physprim"), track.pt(), track.tpcSignal(), track.tofNSigmaPr()); + + double tpcExpSignalPr = track.tpcSignal() - (track.tpcNSigmaPr() * track.tpcExpSigmaPr()); + histos.fill(HIST("ExpTpcdEdx_ptwise_pr"), track.pt(), tpcExpSignalPr, track.tofNSigmaPr()); if (pidIndex == kProtons) { histos.fill(HIST("hNsigmaProtonTruePositives"), track.pt()); } } // Proton condition - } // end of tracks MC loop } // end of process MC PROCESS_SWITCH(PidDiHadron, processMC, "Process Monte Carlo", true); diff --git a/PWGDQ/Core/AnalysisCompositeCut.cxx b/PWGDQ/Core/AnalysisCompositeCut.cxx index 5ab08001953..cbf0f328283 100644 --- a/PWGDQ/Core/AnalysisCompositeCut.cxx +++ b/PWGDQ/Core/AnalysisCompositeCut.cxx @@ -11,6 +11,12 @@ #include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "AnalysisCut.h" + +#include + +#include + ClassImp(AnalysisCompositeCut) //____________________________________________________________________________ diff --git a/PWGDQ/Core/AnalysisCompositeCut.h b/PWGDQ/Core/AnalysisCompositeCut.h index f3d603909c4..a6b3f6afda4 100644 --- a/PWGDQ/Core/AnalysisCompositeCut.h +++ b/PWGDQ/Core/AnalysisCompositeCut.h @@ -14,10 +14,14 @@ // Cut class manipulating groups of cuts // -#ifndef AnalysisCompositeCut_H -#define AnalysisCompositeCut_H +#ifndef PWGDQ_CORE_ANALYSISCOMPOSITECUT_H_ +#define PWGDQ_CORE_ANALYSISCOMPOSITECUT_H_ #include "PWGDQ/Core/AnalysisCut.h" + +#include +#include + #include //_________________________________________________________________________ @@ -52,4 +56,4 @@ class AnalysisCompositeCut : public AnalysisCut ClassDef(AnalysisCompositeCut, 2); }; -#endif +#endif // PWGDQ_CORE_ANALYSISCOMPOSITECUT_H_ diff --git a/PWGDQ/Core/AnalysisCut.cxx b/PWGDQ/Core/AnalysisCut.cxx index ecb1ace04e6..a1dae4ce6b0 100644 --- a/PWGDQ/Core/AnalysisCut.cxx +++ b/PWGDQ/Core/AnalysisCut.cxx @@ -11,6 +11,10 @@ #include "PWGDQ/Core/AnalysisCut.h" +#include + +#include + #include #include diff --git a/PWGDQ/Core/AnalysisCut.h b/PWGDQ/Core/AnalysisCut.h index 6c7185b13ec..16f2916fe93 100644 --- a/PWGDQ/Core/AnalysisCut.h +++ b/PWGDQ/Core/AnalysisCut.h @@ -14,10 +14,14 @@ // Class for analysis cuts applied on the variables defined in the VarManager // -#ifndef AnalysisCut_H -#define AnalysisCut_H +#ifndef PWGDQ_CORE_ANALYSISCUT_H_ +#define PWGDQ_CORE_ANALYSISCUT_H_ #include +#include + +#include + #include //_________________________________________________________________________ @@ -176,4 +180,4 @@ inline bool AnalysisCut::IsSelected(float* values) return true; } -#endif +#endif // PWGDQ_CORE_ANALYSISCUT_H_ diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 0d50821a70e..09bb472266b 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -14,20 +14,27 @@ #include "PWGDQ/Core/CutsLibrary.h" #include "AnalysisCompositeCut.h" +#include "AnalysisCut.h" #include "VarManager.h" +#include +#include + #include +#include + +#include +#include #include +#include #include -#include +#include #include +#include #include -using std::cout; -using std::endl; - AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) { // @@ -3529,6 +3536,11 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("pairD0")) { + cut->AddCut(GetAnalysisCut("pairD0")); + return cut; + } + if (!nameStr.compare("pairD0HighPt1")) { cut->AddCut(GetAnalysisCut("pairLxyzProjected3sigma")); cut->AddCut(GetAnalysisCut("pairPtLow5")); @@ -3709,6 +3721,228 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + //--------------------------------------------------------------- + // ALICE 3 studies composite cuts + + if (!nameStr.compare("alice3StandardKine")) { + cut->AddCut(GetAnalysisCut("alice3StandardKine")); + return cut; + } + + if (!nameStr.compare("alice3KineSkim")) { + cut->AddCut(GetAnalysisCut("alice3KineSkim")); + return cut; + } + + if (!nameStr.compare("alice3TrackQuality")) { + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + return cut; + } + + if (!nameStr.compare("alice3TrackQualityTightDCA")) { + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + return cut; + } + + if (!nameStr.compare("alice3StandardTrack")) { + cut->AddCut(GetAnalysisCut("alice3StandardKine")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + return cut; + } + + if (!nameStr.compare("alice3StandardTrackTOFAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3KineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + return cut; + } + + if (!nameStr.compare("alice3StandardTrackRICHAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3KineRICHAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + return cut; + } + + if (!nameStr.compare("alice3TightDCATrack")) { + cut->AddCut(GetAnalysisCut("alice3StandardKine")); + cut->AddCut(GetAnalysisCut("alice3TrackQualityTightDCA")); + return cut; + } + + if (!nameStr.compare("alice3TightDCATrackTOFAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3KineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQualityTightDCA")); + return cut; + } + + if (!nameStr.compare("alice3TightDCATrackRICHAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3KineRICHAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQualityTightDCA")); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDEl")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDPi")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDPi")); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDKa")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDKa")); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDPr")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDPr")); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDEl")) { + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDPi")) { + cut->AddCut(GetAnalysisCut("alice3oTOFPIDPi")); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDKa")) { + cut->AddCut(GetAnalysisCut("alice3oTOFPIDKa")); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDPr")) { + cut->AddCut(GetAnalysisCut("alice3oTOFPIDPr")); + return cut; + } + + if (!nameStr.compare("alice3FullTOFPIDEl")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3FullTOFPIDPi")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDPi")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDPi")); + return cut; + } + + if (!nameStr.compare("alice3FullTOFPIDKa")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDKa")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDKa")); + return cut; + } + + if (!nameStr.compare("alice3FullTOFPIDPr")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDPr")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDPr")); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDEl")) { + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDPi")) { + cut->AddCut(GetAnalysisCut("alice3RICHPIDPi")); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDKa")) { + cut->AddCut(GetAnalysisCut("alice3RICHPIDKa")); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDPr")) { + cut->AddCut(GetAnalysisCut("alice3RICHPIDPr")); + return cut; + } + + if (!nameStr.compare("alice3RICHTOFPIDEl")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3RICHTOFPIDPi")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDPi")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDPi")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDPi")); + return cut; + } + + if (!nameStr.compare("alice3RICHTOFPIDKa")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDKa")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDKa")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDKa")); + return cut; + } + + if (!nameStr.compare("alice3RICHTOFPIDPr")) { + cut->AddCut(GetAnalysisCut("alice3iTOFPIDPr")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDPr")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDPr")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPID")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKine")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDTOFOnly")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDRICHOnly")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDTOFOnly")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKine")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDTOFAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineTOFAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + + if (!nameStr.compare("alice3DielectronPIDRICHAcceptance")) { + cut->AddCut(GetAnalysisCut("alice3JpsiKineRICHAcceptance")); + cut->AddCut(GetAnalysisCut("alice3TrackQuality")); + cut->AddCut(GetAnalysisCut("alice3iTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3oTOFPIDEl")); + cut->AddCut(GetAnalysisCut("alice3RICHPIDEl")); + return cut; + } + delete cut; LOGF(fatal, Form("Did not find cut %s. Returning nullptr", cutName)); return nullptr; @@ -3732,6 +3966,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("eventIsTVXTriggered")) { + cut->AddCut(VarManager::kIsTVXTriggered, 0.5, 1.5); + return cut; + } + if (!nameStr.compare("eventStandard")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); cut->AddCut(VarManager::kIsINT7, 0.5, 1.5); @@ -3794,6 +4033,19 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("eventSel8TriggerZNAZNC")) { + cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + cut->AddCut(VarManager::kIsTriggerZNAZNC, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("eventSel8TriggerZNAZNCNoPileUp")) { + cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); + cut->AddCut(VarManager::kIsTriggerZNAZNC, 0.5, 1.5); + cut->AddCut(VarManager::kIsNoSameBunch, 0.5, 1.5); + return cut; + } + if (!nameStr.compare("eventSel8NoSameBunchGoodZvtx")) { cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); cut->AddCut(VarManager::kIsNoSameBunch, 0.5, 1.5); @@ -4347,6 +4599,24 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("acceptance_pp13600")) { + cut->AddCut(VarManager::kMCY, -0.8, 0.8); + cut->AddCut(VarManager::kMCPt1, 1.0, 1000.0); + cut->AddCut(VarManager::kMCPt2, 1.0, 1000.0); + cut->AddCut(VarManager::kMCEta1, -0.8, 0.8); + cut->AddCut(VarManager::kMCEta2, -0.8, 0.8); + return cut; + } + + if (!nameStr.compare("acceptance_pp5360")) { + cut->AddCut(VarManager::kMCY, -0.9, 0.9); + cut->AddCut(VarManager::kMCPt1, 1.0, 1000.0); + cut->AddCut(VarManager::kMCPt2, 1.0, 1000.0); + cut->AddCut(VarManager::kMCEta1, -0.9, 0.9); + cut->AddCut(VarManager::kMCEta2, -0.9, 0.9); + return cut; + } + // --------------------------------------------------- // MC generated particle acceptance cuts @@ -6516,6 +6786,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("pairD0")) { + cut->AddCut(VarManager::kMass, 1.814, 1.914); + return cut; + } + if (!nameStr.compare("pairJpsi")) { cut->AddCut(VarManager::kMass, 2.8, 3.3); return cut; @@ -6732,6 +7007,156 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + //--------------------------------------------------------------- + // ALICE 3 Analysis Cuts + + if (!nameStr.compare("alice3KineSkim")) { + cut->AddCut(VarManager::kPt, 0.05, 1000.0); + cut->AddCut(VarManager::kEta, -4.0, 4.0); + return cut; + } + + if (!nameStr.compare("alice3StandardKine")) { + cut->AddCut(VarManager::kPt, 0.1, 1000.0); + cut->AddCut(VarManager::kEta, -2.5, 2.5); // Total tracker acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3KineTOFAcceptance")) { + cut->AddCut(VarManager::kPt, 0.1, 1000.0); + cut->AddCut(VarManager::kEta, -2.0, 2.0); // TOF acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3KineRICHAcceptance")) { + cut->AddCut(VarManager::kPt, 0.1, 1000.0); + cut->AddCut(VarManager::kEta, -0.8, 0.8); // RICH acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3JpsiKine")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -2.5, 2.5); // Total tracker acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3JpsiKineTOFAcceptance")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -2.0, 2.0); // TOF acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3JpsiKineRICHAcceptance")) { + cut->AddCut(VarManager::kPt, 1.0, 1000.0); + cut->AddCut(VarManager::kEta, -0.8, 0.8); // RICH acceptance in v3b geomety + return cut; + } + + if (!nameStr.compare("alice3TrackQuality")) { + cut->AddCut(VarManager::kIsReconstructed, 0.5, 1.5); + cut->AddCut(VarManager::kNSiliconHits, 6.0, 12.0); + cut->AddCut(VarManager::kTrackDCAxy, -3.0, 3.0); + cut->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3TrackQualityTightDCA")) { + cut->AddCut(VarManager::kIsReconstructed, 0.5, 1.5); + cut->AddCut(VarManager::kNSiliconHits, 6.0, 12.0); + cut->AddCut(VarManager::kTrackDCAxy, -1.0, 1.0); + cut->AddCut(VarManager::kTrackDCAz, -1.0, 1.0); + return cut; + } + + if (!nameStr.compare("alice3OTPIDEl")) { + cut->AddCut(VarManager::kOTnSigmaEl, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3OTPIDPi")) { + cut->AddCut(VarManager::kOTnSigmaPi, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3OTPIDKa")) { + cut->AddCut(VarManager::kOTnSigmaKa, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3OTPIDPr")) { + cut->AddCut(VarManager::kOTnSigmaPr, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDEl")) { + cut->AddCut(VarManager::kInnerTOFnSigmaEl, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDPi")) { + cut->AddCut(VarManager::kInnerTOFnSigmaPi, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDKa")) { + cut->AddCut(VarManager::kInnerTOFnSigmaKa, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3iTOFPIDPr")) { + cut->AddCut(VarManager::kInnerTOFnSigmaPr, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDEl")) { + cut->AddCut(VarManager::kOuterTOFnSigmaEl, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDEl")) { + cut->AddCut(VarManager::kOuterTOFnSigmaEl, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDPi")) { + cut->AddCut(VarManager::kOuterTOFnSigmaPi, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDKa")) { + cut->AddCut(VarManager::kOuterTOFnSigmaKa, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3oTOFPIDPr")) { + cut->AddCut(VarManager::kOuterTOFnSigmaPr, -3.0, 3.0); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDEl")) { + cut->AddCut(VarManager::kRICHnSigmaEl, -3.0, 3.0); + cut->AddCut(VarManager::kHasRICHSigEl, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDPi")) { + cut->AddCut(VarManager::kRICHnSigmaPi, -3.0, 3.0); + cut->AddCut(VarManager::kHasRICHSigPi, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDKa")) { + cut->AddCut(VarManager::kRICHnSigmaKa, -3.0, 3.0); + cut->AddCut(VarManager::kHasRICHSigKa, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("alice3RICHPIDPr")) { + cut->AddCut(VarManager::kRICHnSigmaPr, -3.0, 3.0); + cut->AddCut(VarManager::kHasRICHSigPr, 0.5, 1.5); + return cut; + } + delete cut; LOGF(fatal, Form("Did not find cut %s", cutName)); return nullptr; diff --git a/PWGDQ/Core/CutsLibrary.h b/PWGDQ/Core/CutsLibrary.h index b38577f3c2b..51508c3a929 100644 --- a/PWGDQ/Core/CutsLibrary.h +++ b/PWGDQ/Core/CutsLibrary.h @@ -17,9 +17,12 @@ #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" -#include "PWGDQ/Core/VarManager.h" + +#include #include +#include +#include #include // /////////////////////////////////////////////// @@ -98,8 +101,6 @@ // End of Cuts for CEFP // // /////////////////////////////////////////////// -#include "rapidjson/document.h" - namespace o2::aod { namespace dqcuts diff --git a/PWGDQ/Core/DQMlResponse.h b/PWGDQ/Core/DQMlResponse.h index 64bfe233cc7..9b72e1257b7 100644 --- a/PWGDQ/Core/DQMlResponse.h +++ b/PWGDQ/Core/DQMlResponse.h @@ -17,11 +17,16 @@ #ifndef PWGDQ_CORE_DQMLRESPONSE_H_ #define PWGDQ_CORE_DQMLRESPONSE_H_ +#include "PWGDQ/Core/VarManager.h" + #include "Tools/ML/MlResponse.h" +#include + +#include #include #include -#include +#include #include namespace o2::analysis diff --git a/PWGDQ/Core/HistogramManager.cxx b/PWGDQ/Core/HistogramManager.cxx index 4882b7d84f5..ae1c4be3022 100644 --- a/PWGDQ/Core/HistogramManager.cxx +++ b/PWGDQ/Core/HistogramManager.cxx @@ -11,28 +11,37 @@ #include "PWGDQ/Core/HistogramManager.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include #include -#include -#include #include +#include #include -#include -#include "Framework/Logger.h" using namespace std; -#include -#include +#include #include -#include -#include -#include -#include -#include -#include #include #include #include -#include +#include +#include +#include +#include +#include ClassImp(HistogramManager); diff --git a/PWGDQ/Core/HistogramManager.h b/PWGDQ/Core/HistogramManager.h index 4b1393b2eb7..94aa3ecec00 100644 --- a/PWGDQ/Core/HistogramManager.h +++ b/PWGDQ/Core/HistogramManager.h @@ -17,17 +17,20 @@ #ifndef PWGDQ_CORE_HISTOGRAMMANAGER_H_ #define PWGDQ_CORE_HISTOGRAMMANAGER_H_ -#include -#include -#include -#include -#include #include +#include +#include +#include +#include -#include +#include +#include + +#include +#include #include +#include #include -#include class HistogramManager : public TNamed { @@ -103,10 +106,10 @@ class HistogramManager : public TNamed std::map>> fVariablesMap; //! map holding identifiers for all variables needed by histograms // various - bool fUseDefaultVariableNames; //! toggle the usage of default variable names and units - uint64_t fBinsAllocated; //! number of allocated bins - TString* fVariableNames; //! variable names - TString* fVariableUnits; //! variable units + bool fUseDefaultVariableNames; //! toggle the usage of default variable names and units + uint64_t fBinsAllocated; //! number of allocated bins + TString* fVariableNames; //! variable names + TString* fVariableUnits; //! variable units void MakeAxisLabels(TAxis* ax, const char* labels); diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index df3bdc0470b..e198ea2d7af 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -13,11 +13,25 @@ // #include "PWGDQ/Core/HistogramsLibrary.h" +#include "HistogramManager.h" #include "VarManager.h" -#include "CommonConstants/MathConstants.h" +#include +#include + +#include +#include +#include + +#include +#include + +#include #include +#include +#include +#include #include void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* histClass, const char* groupName, const char* subGroupName) @@ -42,7 +56,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "TF_NMFTs", "Number of MFT tracks per TF", false, 1000, 0.0, 200000.0, VarManager::kTFNMFTs); } if (!groupStr.CompareTo("event")) { - if (!subGroupStr.Contains("generator")) { + if (!subGroupStr.Contains("generator") && !subGroupStr.Contains("pairing")) { hm->AddHistogram(histClass, "VtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ); hm->AddHistogram(histClass, "VtxZ_Run", "Vtx Z", true, 1, -0.5, 0.5, VarManager::kRunNo, 60, -15.0, 15.0, VarManager::kVtxZ, 1, 0, 1, VarManager::kNothing, "", "", "", VarManager::kNothing, VarManager::kNothing, false, true); hm->AddHistogram(histClass, "BC", "Event per BC", false, 3564, 0.0, 3564.0, VarManager::kBCOrbit); @@ -82,12 +96,17 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("vtxpp")) { hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); + hm->AddHistogram(histClass, "VtxNContrib_VtxNContribReal", "VtxNContrib_VtxNContribReal", false, 200, 0.0, 200.0, VarManager::kVtxNcontrib, 200, 0.0, 200.0, VarManager::kVtxNcontribReal); + hm->AddHistogram(histClass, "VtxNContribReal_kMultFT0C", "VtxNContribReal_kMultFT0C", false, 200, 0.0, 200.0, VarManager::kVtxNcontrib, 2500, 0.0, 25000, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "VtxNContribReal_kMultFT0A", "VtxNContribReal_kMultFT0A", false, 200, 0.0, 200.0, VarManager::kVtxNcontrib, 2500, 0.0, 25000, VarManager::kMultFT0A); } if (subGroupStr.Contains("vtxPbPb")) { hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 20000.0, VarManager::kVtxNcontrib); } if (subGroupStr.Contains("cent")) { hm->AddHistogram(histClass, "CentFT0C", "CentFT0C", false, 100, 0., 100., VarManager::kCentFT0C); + hm->AddHistogram(histClass, "CentFT0M", "CentFT0M", false, 100, 0., 100., VarManager::kCentFT0M); + hm->AddHistogram(histClass, "CentFT0M_VtxNContribReal", "CentFT0M_VtxNContribReal", false, 100, 0.0, 100.0, VarManager::kCentFT0M, 200, 0.0, 200.0, VarManager::kVtxNcontribReal); 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, 100, 0., 50000., VarManager::kMultTPC); hm->AddHistogram(histClass, "CentFT0C_Run", "Cent FT0C", true, 1, -0.5, 0.5, VarManager::kRunNo, 100, 0., 100., VarManager::kCentFT0C, 1, 0, 1, VarManager::kNothing, "", "", "", VarManager::kNothing, VarManager::kNothing, false, true); @@ -234,8 +253,8 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "MCVtxX_VtxY", "Vtx X vs Vtx Y", false, 200, -0.2, 0.2, VarManager::kMCVtxX, 200, -0.2, 0.2, VarManager::kMCVtxY); hm->AddHistogram(histClass, "MCVtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kMCVtxZ); hm->AddHistogram(histClass, "MCVtxZ_VtxX", "Vtx X vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kMCVtxZ, 200, -0.2, 0.2, VarManager::kMCVtxX); - 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); + hm->AddHistogram(histClass, "MCVtxZ_VtxY", "Vtx Y vs Vtx Z", false, 200, 15.0, 15.0, VarManager::kMCVtxZ, 200, -0.2, 0.2, VarManager::kMCVtxY); + hm->AddHistogram(histClass, "MCImpPar", "MC impact param", false, 200, 0.0, 20.0, VarManager::kMCEventImpParam); hm->AddHistogram(histClass, "MCCentrFT0C", "MC Centrality FT0C", false, 100, 0.0, 100.0, VarManager::kMCEventCentrFT0C); hm->AddHistogram(histClass, "MultMCNParticlesEta05", "MultMCNParticlesEta05", false, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta05); hm->AddHistogram(histClass, "MultMCNParticlesEta08", "MultMCNParticlesEta08", false, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta08); @@ -431,6 +450,161 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "energyCommonZNA_energyCommonZNC", "Common ZNA energy vs common ZNC energy", false, 1050, -10.0, 200.0, VarManager::kEnergyCommonZNA, 1050, -10.0, 200.0, VarManager::kEnergyCommonZNC); hm->AddHistogram(histClass, "energyCommonZNA_energyCommonZNC_lowRange", "Common ZNA energy vs common ZNC energy", false, 220, -2.0, 20.0, VarManager::kEnergyCommonZNA, 220, -2.0, 20.0, VarManager::kEnergyCommonZNC); } + if (subGroupStr.Contains("merging")) { + // 1D histograms + hm->AddHistogram(histClass, "BimodalCoeffUnbinned", "Bimodal coefficient unbinned", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalCoeffBinned", "Bimodal coefficient binned", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalCoeffBinnedTrim1", "Bimodal coefficient binned, trim 1", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalCoeffBinnedTrim2", "Bimodal coefficient binned, trim 2", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalCoeffBinnedTrim3", "Bimodal coefficient binned, trim 3", false, 1001, 0.0, 1.001, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzMean", "DCAz per event mean", false, 3000, -15.0, 15.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzMeanTrimmed1", "DCAz per event mean, trim 1", false, 3000, -15.0, 15.0, VarManager::kDCAzMeanBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzMeanTrimmed2", "DCAz per event mean, trim 2", false, 3000, -15.0, 15.0, VarManager::kDCAzMeanBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMeanTrimmed3", "DCAz per event mean, trim 3", false, 3000, -15.0, 15.0, VarManager::kDCAzMeanBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzRMS", "DCAz per event RMS", false, 3000, 0.0, 15.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "DCAzRMSTrimmed1", "DCAz per event RMS, trim 1", false, 3000, 0.0, 15.0, VarManager::kDCAzRMSBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzRMSTrimmed2", "DCAz per event RMS, trim 2", false, 3000, 0.0, 15.0, VarManager::kDCAzRMSBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzRMSTrimmed3", "DCAz per event RMS, trim 3", false, 3000, 0.0, 15.0, VarManager::kDCAzRMSBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzSkewness", "DCAz per event skewness", false, 1000, 0.0, 100.0, VarManager::kDCAzSkewness); + hm->AddHistogram(histClass, "DCAzKurtosis", "DCAz per event kurtosis", false, 1001, 0.0, 1.001, VarManager::kDCAzKurtosis); + hm->AddHistogram(histClass, "NPeaks", "Number of peaks in DCAz distribution per event", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaks); + hm->AddHistogram(histClass, "NPeaksTrimmed1", "Number of peaks in DCAz distribution per event, trim 1", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2", "Number of peaks in DCAz distribution per event, trim 2", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "NPeaksTrimmed3", "Number of peaks in DCAz distribution per event, trim 3", false, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed3); + hm->AddHistogram(histClass, "FracAbove100um", "Fraction of tracks with DCAz > 100 um", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove100um); + hm->AddHistogram(histClass, "FracAbove200um", "Fraction of tracks with DCAz > 200 um", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove200um); + hm->AddHistogram(histClass, "FracAbove500um", "Fraction of tracks with DCAz > 500 um", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove1mm", "Fraction of tracks with DCAz > 1 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove1mm); + hm->AddHistogram(histClass, "FracAbove2mm", "Fraction of tracks with DCAz > 2 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove2mm); + hm->AddHistogram(histClass, "FracAbove5mm", "Fraction of tracks with DCAz > 5 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + hm->AddHistogram(histClass, "FracAbove10mm", "Fraction of tracks with DCAz > 10 mm", false, 1000, 0.0, 1.0, VarManager::kDCAzFracAbove10mm); + // 2D histograms + // bimodality coefficients vs each other + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinned", "Bimodality unbinned vs binned", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinnedTrim1", "Bimodality unbinned vs binned, trim 1", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinnedTrim2", "Bimodality unbinned vs binned, trim 2", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityUnbinned_BimodalityBinnedTrim3", "Bimodality unbinned vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityBinned_BimodalityBinnedTrim1", "Bimodality binned vs binned, trim 1", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinned_BimodalityBinnedTrim2", "Bimodality binned vs binned, trim 2", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinned_BimodalityBinnedTrim3", "Bimodality binned vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_BimodalityBinnedTrim2", "Bimodality binned, trim 1 vs binned, trim 2", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_BimodalityBinnedTrim3", "Bimodality binned, trim 1 vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_BimodalityBinnedTrim3", "Bimodality binned, trim 2 vs binned, trim 3", false, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + // bimodality coefficients vs DCAz mean and RMS + hm->AddHistogram(histClass, "BimodalityUnbinned_DCAzMean", "Bimodality unbinned vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMean, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_DCAzMean", "Bimodality binned vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMean, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_DCAzMeanTrimmed1", "Bimodality binned, trim 1 vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_DCAzMeanTrimmed2", "Bimodality binned, trim 2 vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_DCAzMeanTrimmed3", "Bimodality binned, trim 3 vs DCAz mean", false, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed3, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_DCAzRMS", "Bimodality unbinned vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_DCAzRMS", "Bimodality binned vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_DCAzRMSTrimmed1", "Bimodality binned, trim 1 vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_DCAzRMSTrimmed2", "Bimodality binned, trim 2 vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_DCAzRMSTrimmed3", "Bimodality binned, trim 3 vs DCAz RMS", false, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed3, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + // bimodality coefficients vs number of peaks + hm->AddHistogram(histClass, "BimodalityUnbinned_NPeaks", "Bimodality unbinned vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaks, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_NPeaks", "Bimodality binned vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaks, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_NPeaks", "Bimodality binned, trim 1 vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_NPeaks", "Bimodality binned, trim 2 vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_NPeaks", "Bimodality binned, trim 3 vs number of peaks", false, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed3, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + // bimodality coefficients vs fraction of tracks above certain DCAz thresholds + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove100um", "Bimodality unbinned vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove100um", "Bimodality binned vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove100um", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove100um", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove100um", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 100 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove500um", "Bimodality unbinned vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove500um", "Bimodality binned vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove500um", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove500um", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove500um", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 500 um", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove2mm", "Bimodality unbinned vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove2mm", "Bimodality binned vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove2mm", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove2mm", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove2mm", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 2 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "BimodalityUnbinned_FracAbove10mm", "Bimodality unbinned vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_FracAbove10mm", "Bimodality binned vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_FracAbove10mm", "Bimodality binned, trim 1 vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_FracAbove10mm", "Bimodality binned, trim 2 vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_FracAbove10mm", "Bimodality binned, trim 3 vs fraction of tracks with DCAz > 10 mm", false, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + + // All the event merging vs centrality FT0C + hm->AddHistogram(histClass, "BimodalityUnbinned_CentFT0C", "Bimodality unbinned vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinned_CentFT0C", "Bimodality binned vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinned); + hm->AddHistogram(histClass, "BimodalityBinnedTrim1_CentFT0C", "Bimodality binned, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrim2_CentFT0C", "Bimodality binned, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "BimodalityBinnedTrim3_CentFT0C", "Bimodality binned, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzMean_CentFT0C", "DCAz per event mean vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzMeanTrimmed1_CentFT0C", "DCAz per event mean, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzMeanTrimmed2_CentFT0C", "DCAz per event mean, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMeanTrimmed3_CentFT0C", "DCAz per event mean, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, -2.0, 2.0, VarManager::kDCAzMeanBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzRMS_CentFT0C", "DCAz per event RMS vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "DCAzRMSTrimmed1_CentFT0C", "DCAz per event RMS, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed1); + hm->AddHistogram(histClass, "DCAzRMSTrimmed2_CentFT0C", "DCAz per event RMS, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzRMSTrimmed3_CentFT0C", "DCAz per event RMS, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 400, 0.0, 2.0, VarManager::kDCAzRMSBinnedTrimmed3); + hm->AddHistogram(histClass, "DCAzSkewness_CentFT0C", "DCAz per event skewness vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 1000, 0.0, 100.0, VarManager::kDCAzSkewness); + hm->AddHistogram(histClass, "DCAzKurtosis_CentFT0C", "DCAz per event kurtosis vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 1001, 0.0, 1.001, VarManager::kDCAzKurtosis); + hm->AddHistogram(histClass, "NPeaks_CentFT0C", "Number of peaks in DCAz distribution per event vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaks); + hm->AddHistogram(histClass, "NPeaksTrimmed1_CentFT0C", "Number of peaks in DCAz distribution per event, trim 1 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_CentFT0C", "Number of peaks in DCAz distribution per event, trim 2 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "NPeaksTrimmed3_CentFT0C", "Number of peaks in DCAz distribution per event, trim 3 vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 100.0, VarManager::kDCAzNPeaksTrimmed3); + hm->AddHistogram(histClass, "FracAbove100um_CentFT0C", "Fraction of tracks with DCAz > 100 um vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove100um); + hm->AddHistogram(histClass, "FracAbove200um_CentFT0C", "Fraction of tracks with DCAz > 200 um vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove200um); + hm->AddHistogram(histClass, "FracAbove500um_CentFT0C", "Fraction of tracks with DCAz > 500 um vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove1mm_CentFT0C", "Fraction of tracks with DCAz > 1 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove1mm); + hm->AddHistogram(histClass, "FracAbove2mm_CentFT0C", "Fraction of tracks with DCAz > 2 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove2mm); + hm->AddHistogram(histClass, "FracAbove5mm_CentFT0C", "Fraction of tracks with DCAz > 5 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + hm->AddHistogram(histClass, "FracAbove10mm_CentFT0C", "Fraction of tracks with DCAz > 10 mm vs centrality", false, 20, 0.0, 100.0, VarManager::kCentFT0C, 100, 0.0, 1.0, VarManager::kDCAzFracAbove10mm); + // histograms vs number of tracks with ITS + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksITS", "Bimodality unbinned vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksITS", "Bimodality binned, trimmed 1, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksITS", "Bimodality binned, trimmed 2, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksITS", "DCAz mean vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksITS", "DCAz RMS vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksITS", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksITS", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksITS", "Fraction of tracks with DCAz > 500 um vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksITS", "Fraction of tracks with DCAz > 5 mm vs number of tracks with ITS", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasITS, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + // histograms vs number of tracks with TPC + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksTPC", "Bimodality unbinned vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksTPC", "Bimodality binned, trimmed 1, vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksTPC", "Bimodality binned, trimmed 2, vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksTPC", "DCAz mean vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksTPC", "DCAz RMS vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksTPC", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with TPC", false, 100, 0.0, 1000.0, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksTPC", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with TPC", false, 100, 0.0, 1000.0, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksTPC", "Fraction of tracks with DCAz > 500 um vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksTPC", "Fraction of tracks with DCAz > 5 mm vs number of tracks with TPC", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTPC, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + // histograms vs number of tracks with TOF + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksTOF", "Bimodality unbinned vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksTOF", "Bimodality binned, trimmed 1, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksTOF", "Bimodality binned, trimmed 2, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksTOF", "DCAz mean vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksTOF", "DCAz RMS vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksTOF", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksTOF", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksTOF", "Fraction of tracks with DCAz > 500 um vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksTOF", "Fraction of tracks with DCAz > 5 mm vs number of tracks with TOF", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTOF, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + // histograms vs number of tracks with TRD + hm->AddHistogram(histClass, "BimodalityUnbinned_NTracksTRD", "Bimodality unbinned vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficient); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed1_NTracksTRD", "Bimodality binned, trimmed 1, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1); + hm->AddHistogram(histClass, "BimodalityBinnedTrimmed2_NTracksTRD", "Bimodality binned, trimmed 2, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2); + hm->AddHistogram(histClass, "DCAzMean_NTracksTRD", "DCAz mean vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzMean); + hm->AddHistogram(histClass, "DCAzRMS_NTracksTRD", "DCAz RMS vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzRMS); + hm->AddHistogram(histClass, "NPeaksTrimmed1_NTracksTRD", "Number of peaks in DCAz distribution per event, trim 1, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed1); + hm->AddHistogram(histClass, "NPeaksTrimmed2_NTracksTRD", "Number of peaks in DCAz distribution per event, trim 2, vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 50, 0.0, 50.0, VarManager::kDCAzNPeaksTrimmed2); + hm->AddHistogram(histClass, "FracAbove500um_NTracksTRD", "Fraction of tracks with DCAz > 500 um vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzFracAbove500um); + hm->AddHistogram(histClass, "FracAbove5mm_NTracksTRD", "Fraction of tracks with DCAz > 5 mm vs number of tracks with TRD", false, 100, 0.0, 1000.0, VarManager::kMultNTracksHasTRD, 100, 0.0, 1.0, VarManager::kDCAzFracAbove5mm); + } + if (subGroupStr.Contains("pairing")) { + if (subGroupStr.Contains("sameevent")) { + hm->AddHistogram(histClass, "NPairsPerEvent", "Number of track pairs per event", false, 100, 0.0, 100.0, VarManager::kNPairsPerEvent); + } + if (subGroupStr.Contains("mixedevent")) { + hm->AddHistogram(histClass, "NPairsPerEvent", "Number of track pairs per event", false, 500, 0.0, 500.0, VarManager::kNPairsPerEvent); + } + } } // end "event" if (!groupStr.CompareTo("two-collisions")) { @@ -888,6 +1062,46 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass", "", false, 500, 0.0, 5.0, VarManager::kMass); hm->AddHistogram(histClass, "Rapidity", "", false, 400, -4.0, 4.0, VarManager::kRap); } + if (subGroupStr.Contains("alice3tracks")) { + hm->AddHistogram(histClass, "IsReconstructed", "IsReconstructed", false, 2, 0.5, 1.5, VarManager::kIsReconstructed); + hm->AddHistogram(histClass, "nSiliconHits", "Num silicon hits", false, 12, 0.0, 12.0, VarManager::kNSiliconHits); + hm->AddHistogram(histClass, "Pt_vs_PtMC", "pT vs MC pT", false, 200, 0.0, 100.0, VarManager::kPt, 200, 0.0, 20.0, VarManager::kMCPt); + hm->AddHistogram(histClass, "Eta_vs_EtaMC", "#eta vs MC #eta", false, 150, -4.0, 4.0, VarManager::kEta, 150, -4.0, 4.0, VarManager::kMCEta); + hm->AddHistogram(histClass, "Phi_vs_PhiMC", "#varphi vs MC #varphi", false, 50, 0.0, 2. * o2::constants::math::PI, VarManager::kPhi, 50, 0.0, 2. * o2::constants::math::PI, VarManager::kMCPhi); + hm->AddHistogram(histClass, "Eta_DCAxy", "#eta vs DCA_{xy}", false, 80, -4.0, 4.0, VarManager::kEta, 400, -2.0, 2.0, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "Eta_DCAz", "#eta vs DCA_{z}", false, 80, -4.0, 4.0, VarManager::kEta, 800, -4.0, 4.0, VarManager::kTrackDCAz); + } + if (subGroupStr.Contains("resolutions")) { + hm->AddHistogram(histClass, "PtMC_vs_DeltaPt", "MC pT vs DeltaPt", false, 200, 0.0, 100.0, VarManager::kMCPt, 2000, -1.0, 1.0, VarManager::kDeltaPt); + hm->AddHistogram(histClass, "Pt_vs_DeltaPt", "pT vs pTRes", false, 200, 0.0, 100.0, VarManager::kPt, 2000, -1.0, 1.0, VarManager::kDeltaPt); + hm->AddHistogram(histClass, "EtaMC_vs_DeltaPt", "MC Eta vs DeltaPt", false, 200, -6.0, 6.0, VarManager::kMCEta, 2000, -1.0, 1.0, VarManager::kDeltaPt); + hm->AddHistogram(histClass, "Eta_vs_DeltaPt", "MC Eta vs DeltaPt", false, 200, -6.0, 6.0, VarManager::kEta, 2000, -1.0, 1.0, VarManager::kDeltaPt); + hm->AddHistogram(histClass, "PtMC_vs_Res", "MC pT vs DeltaPt", false, 200, 0.0, 100.0, VarManager::kMCPt, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "Pt_vs_Res", "pT vs pTRes", false, 200, 0.0, 100.0, VarManager::kPt, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "EtaMC_vs_Res", "MC Eta vs pTRes", false, 200, -6.0, 6.0, VarManager::kMCEta, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "Eta_vs_Res", "MC Eta vs pTRes", false, 200, -6.0, 6.0, VarManager::kEta, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "PtRes", "pT Resolution", false, 2000, -1.0, 1.0, VarManager::kPtResolution); + hm->AddHistogram(histClass, "EtaMC_vs_EtaRes", "MC eta vs EtaRes", false, 200, -6.0, 6.0, VarManager::kMCEta, 2000, -1.0, 1.0, VarManager::kEtaResolution); + } + if (subGroupStr.Contains("alice3tofpid")) { + hm->AddHistogram(histClass, "iTOFbeta_p", "iTOF #beta vs p", false, 100, 0.0, 10.0, VarManager::kP, 320, 0.0, 2.0, VarManager::kiTOFBeta); + hm->AddHistogram(histClass, "iTOFnSigEle_p", "iTOF n-#sigma(e) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kInnerTOFnSigmaEl); + hm->AddHistogram(histClass, "iTOFnSigPi_p", "iTOF n-#sigma(#pi) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kInnerTOFnSigmaPi); + hm->AddHistogram(histClass, "iTOFnSigKa_p", "iTOF n-#sigma(K) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kInnerTOFnSigmaKa); + hm->AddHistogram(histClass, "iTOFnSigPr_p", "iTOF n-#sigma(p) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kInnerTOFnSigmaPr); + + hm->AddHistogram(histClass, "oTOFbeta_p", "oTOF #beta vs p", false, 100, 0.0, 10.0, VarManager::kP, 320, 0.0, 2.0, VarManager::koTOFBeta); + hm->AddHistogram(histClass, "oTOFnSigEl_p", "oTOF n-#sigma(e) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kOuterTOFnSigmaEl); + hm->AddHistogram(histClass, "oTOFnSigPi_p", "oTOF n-#sigma(#pi) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kOuterTOFnSigmaPi); + hm->AddHistogram(histClass, "oTOFnSigKa_p", "oTOF n-#sigma(K) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kOuterTOFnSigmaKa); + hm->AddHistogram(histClass, "oTOFnSigPr_p", "oTOF n-#sigma(p) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kOuterTOFnSigmaPr); + } + if (subGroupStr.Contains("alice3richpid")) { + hm->AddHistogram(histClass, "RICHnSigEl_p", "RICH n-#sigma(e) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kRICHnSigmaEl); + hm->AddHistogram(histClass, "RICHnSigPi_p", "RICH n-#sigma(#pi) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kRICHnSigmaPi); + hm->AddHistogram(histClass, "RICHnSigKa_p", "RICH n-#sigma(K) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kRICHnSigmaKa); + hm->AddHistogram(histClass, "RICHnSigPr_p", "RICH n-#sigma(p) vs p", false, 100, 0.0, 10.0, VarManager::kP, 200, -10.0, 10.0, VarManager::kRICHnSigmaPr); + } if (subGroupStr.Contains("tpcpidvstofpid")) { hm->AddHistogram(histClass, "tpcNSigmaKa_tofNSigmaKa", "", false, 200, -10., 10., VarManager::kTPCnSigmaKa, 200, -10., 10., VarManager::kTOFnSigmaKa); hm->AddHistogram(histClass, "tpcNSigmaPi_tofNSigmaPi", "", false, 200, -10., 10., VarManager::kTPCnSigmaPi, 200, -10., 10., VarManager::kTOFnSigmaPi); @@ -971,35 +1185,30 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "YMC", "MC y", false, 50, -5.0, 5.0, VarManager::kMCY); hm->AddHistogram(histClass, "CentFT0CMC", "MC Cent. FT0C", false, 18, 0., 90., VarManager::kMCEventCentrFT0C); hm->AddHistogram(histClass, "PtMC_YMC", "MC pT vs MC y", false, 120, 0.0, 30.0, VarManager::kMCPt, 1000, -5.0, 5.0, VarManager::kMCY); - hm->AddHistogram(histClass, "PtMC_YMC_CentFT0CMC", "MC pT vs MC y vs MC Cent. FT0C", false, 120, 0.0, 30.0, VarManager::kMCPt, 1000, -5.0, 5.0, VarManager::kMCY, 18, 0., 90., VarManager::kMCEventCentrFT0C); + hm->AddHistogram(histClass, "PtMC_YMC_CentFT0CMC", "MC pT vs MC y vs MC Cent. FT0C", false, 120, 0.0, 30.0, VarManager::kMCPt, 1000, -5.0, 5.0, VarManager::kMCY, 20, 0., 100., VarManager::kMCEventCentrFT0C); hm->AddHistogram(histClass, "EtaMC_PtMC", "", false, 40, -2.0, 2.0, VarManager::kMCEta, 200, 0.0, 20.0, VarManager::kMCPt); hm->AddHistogram(histClass, "VzMC", "MC vz", false, 100, -15.0, 15.0, VarManager::kMCVz); hm->AddHistogram(histClass, "VzMC_VtxZMC", "MC vz vs MC vtxZ", false, 50, -15.0, 15.0, VarManager::kMCVz, 50, -15.0, 15.0, VarManager::kMCVtxZ); hm->AddHistogram(histClass, "Weight", "", false, 50, 0.0, 5.0, VarManager::kMCParticleWeight); hm->AddHistogram(histClass, "MCImpPar_CentFT0CMC", "MC impact param vs MC Cent. FT0C", false, 20, 0.0, 20.0, VarManager::kMCEventImpParam, 100, 0.0, 100.0, VarManager::kMCEventCentrFT0C); } + if (!groupStr.CompareTo("mctruth_mult")) { + hm->AddHistogram(histClass, "PtMC_MultEta05", "MC pT vs mult |#eta| < 0.5", false, 200, 0.0, 20.0, VarManager::kMCPt, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta05); + hm->AddHistogram(histClass, "PtMC_MultEta08", "MC pT vs mult |#eta| < 0.8", false, 200, 0.0, 20.0, VarManager::kMCPt, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta08); + hm->AddHistogram(histClass, "PtMC_MultEta10", "MC pT vs mult |#eta| < 1.0", false, 200, 0.0, 20.0, VarManager::kMCPt, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta10); + hm->AddHistogram(histClass, "EtaMC_MultEta05", "MC Eta vs mult |#eta| < 0.5", false, 40, -2.0, 2.0, VarManager::kMCEta, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta05); + hm->AddHistogram(histClass, "EtaMC_MultEta08", "MC Eta vs mult |#eta| < 0.8", false, 40, -2.0, 2.0, VarManager::kMCEta, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta08); + hm->AddHistogram(histClass, "EtaMC_MultEta10", "MC Eta vs mult |#eta| < 1.0", false, 40, -2.0, 2.0, VarManager::kMCEta, 150, 0.0, 150.0, VarManager::kMultMCNParticlesEta10); + } if (!groupStr.CompareTo("energy-correlator-gen")) { - hm->AddHistogram(histClass, "MCCostheta", "Cos#theta", false, 40, -1.0, 1.0, VarManager::kMCCosTheta, 0, 0, 0, -1, 0, 0, 0, -1, "", "", "", -1, VarManager::kMCWeight_before); - hm->AddHistogram(histClass, "MCHadronPdgCode", "MCHadronPdgCode", false, 6000, -3000, 3000, VarManager::kMCHadronPdgCode); - hm->AddHistogram(histClass, "MCMotherPdgCode", "MCMotherPdgCode", false, 6000, -3000, 3000, VarManager::kMCMotherPdgCode); - hm->AddHistogram(histClass, "MCPdgCode", "MCPdgCode", false, 1000, -1000, 1000, VarManager::kMCPdgCode); - hm->AddHistogram(histClass, "Coschi", "", false, 40, -1.0, 1.0, VarManager::kMCCosChi, 0, 0, 0, -1, 0, 0, 0, -1, "", "", "", -1, VarManager::kMCWeight); - hm->AddHistogram(histClass, "Pt_Hadron", "", false, 120, 0.0, 30.0, VarManager::kMCHadronPt); - hm->AddHistogram(histClass, "Eta_Hadron", "", false, 120, -2.0, 2.0, VarManager::kMCHadronEta); - hm->AddHistogram(histClass, "Phi_Hadron", "", false, 120, -2.0, 2.0, VarManager::kMCHadronPhi); - hm->AddHistogram(histClass, "DeltaEta", "", false, 20, -2.0, 2.0, VarManager::kMCdeltaeta); - hm->AddHistogram(histClass, "DeltaPhi", "", false, 50, -8.0, 8.0, VarManager::kMCdeltaphi); - hm->AddHistogram(histClass, "DeltaEta_DeltaPhi", "", false, 20, -2.0, 2.0, VarManager::kMCdeltaeta, 50, -8.0, 8.0, VarManager::kMCdeltaphi); - // for bkg - hm->AddHistogram(histClass, "DeltaPhi_randomPhi_trans", "", false, 50, -8.0, 8.0, VarManager::kMCdeltaphi_randomPhi_trans); - hm->AddHistogram(histClass, "DeltaPhi_randomPhi_toward", "", false, 50, -8.0, 8.0, VarManager::kMCdeltaphi_randomPhi_toward); - hm->AddHistogram(histClass, "DeltaPhi_randomPhi_away", "", false, 50, -8.0, 8.0, VarManager::kMCdeltaphi_randomPhi_away); - - hm->AddHistogram(histClass, "Coschi_randomPhi_trans", "", false, 40, -1.0, 1.0, VarManager::kMCCosChi_randomPhi_trans, 0, 0, 0, -1, 0, 0, 0, -1, "", "", "", -1, VarManager::kMCWeight_randomPhi_trans); - hm->AddHistogram(histClass, "Coschi_randomPhi_toward", "", false, 40, -1.0, 1.0, VarManager::kMCCosChi_randomPhi_toward, 0, 0, 0, -1, 0, 0, 0, -1, "", "", "", -1, VarManager::kMCWeight_randomPhi_toward); - hm->AddHistogram(histClass, "Coschi_randomPhi_away", "", false, 40, -1.0, 1.0, VarManager::kMCCosChi_randomPhi_away, 0, 0, 0, -1, 0, 0, 0, -1, "", "", "", -1, VarManager::kMCWeight_randomPhi_away); + double coschiBins[26]; + for (int i = 0; i < 26; i++) { + coschiBins[i] = -1.0 + 2.0 * TMath::Power(0.04 * i, 2.0); + } + hm->AddHistogram(histClass, "Coschi", "", false, 25, coschiBins, VarManager::kMCCosChi, 0, nullptr, -1, 0, nullptr, -1, "", "", "", -1, VarManager::kMCWeight); } + if (!groupStr.CompareTo("polarization-pseudoproper-gen")) { int varspTHE[3] = {VarManager::kMCPt, VarManager::kMCCosThetaHE, VarManager::kMCVertexingTauxyProjected}; int varspTCS[3] = {VarManager::kMCPt, VarManager::kMCCosThetaCS, VarManager::kMCVertexingTauxyProjected}; @@ -1030,6 +1239,29 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_MultFDDA", "Mass vs MultFDDA", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFDDA); hm->AddHistogram(histClass, "Mass_MultFDDC", "Mass vs MultFDDC", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFDDC); } + if (subGroupStr.Contains("mass_mult_pv")) { + double multAnalysisBins[4] = {0.0, 4.0, 8.0, 1000.0}; + + double multAnalsisMassBins[201] = {0.0}; + for (int i = 0; i <= 200; i++) { + multAnalsisMassBins[i] = 2.0 + i * 0.015; + } + + double multAnalysisPVBins[151] = {0.0}; + for (int i = 0; i <= 150; i++) { + multAnalysisPVBins[i] = i * 1.0; + } + + double multAnalysisFV0ABins[1001] = {0.0}; + for (int i = 0; i <= 1000; i++) { + multAnalysisFV0ABins[i] = i * 1.0; + } + + hm->AddHistogram(histClass, "Mass_VtxNcontribReal_Pt", "Mass vs VtxNcontribReal vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 150, multAnalysisPVBins, VarManager::kVtxNcontribReal, 3, multAnalysisBins, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_MultFV0A_Pt", "Mass vs MultFV0A vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 1000, multAnalysisFV0ABins, VarManager::kMultFV0A, 3, multAnalysisBins, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_MultFT0A_Pt", "Mass vs MultFT0A vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 1000, multAnalysisFV0ABins, VarManager::kMultFT0A, 3, multAnalysisBins, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_MultFT0C_Pt", "Mass vs MultFT0C vs Pt", false, 200, multAnalsisMassBins, VarManager::kMass, 1000, multAnalysisFV0ABins, VarManager::kMultFT0C, 3, multAnalysisBins, VarManager::kPt); + } if (subGroupStr.Contains("barrel")) { hm->AddHistogram(histClass, "Mass", "", false, 500, 0.0, 5.0, VarManager::kMass); hm->AddHistogram(histClass, "Mass_HighRange", "", false, 375, 0.0, 15.0, VarManager::kMass); @@ -1064,6 +1296,18 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_VtxNcontribReal_VtxZ", "Mass vs VtxNcontribReal vs VtxZ", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kVtxNcontribReal, 20, -10.0, 10.0, VarManager::kVtxZ); hm->AddHistogram(histClass, "VtxZ_VtxNcontribReal", "VtxZ vs VtxNcontribReal", false, 240, -12.0, 12.0, VarManager::kVtxZ, 200, 0, 200.0, VarManager::kVtxNcontribReal); } + if (subGroupStr.Contains("alice3barrel")) { + double pTBins[21] = { + 0.1, 0.5, 1.0, 1.25, 1.5, 2.0, 2.5, 3.0, + 4.0, 5.0, 6.5, 8.0, 10.0, 12.0, 15.0, 20.0, + 30.0, 40.0, 60.0, 80.0, 100.0}; + + double massBins[501]; + for (int i = 0; i < 501; i++) { + massBins[i] = 0.01 * (i); + } + hm->AddHistogram(histClass, "Mass_PtLong", "", false, 500, massBins, VarManager::kMass, 20, pTBins, VarManager::kPt); + } if (subGroupStr.Contains("dielectron-polarization-he-pbpb")) { int varsHEpbpb[5] = {VarManager::kMass, VarManager::kPt, VarManager::kCentFT0C, VarManager::kCosThetaHE, VarManager::kPhiHE}; int binspT[5] = {100, 30, 10, 10, 10}; @@ -1381,27 +1625,17 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("upsilon-polarization-he")) { int varspTHE[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaHE, VarManager::kPhiHE}; - int varsrapHE[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaHE, VarManager::kPhiHE}; int binspT[4] = {100, 20, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; - double xminpT[4] = {1., 0., -1., -3.14}; - double xmaxpT[4] = {15., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {15., 4.0, 1., +3.14}; + double xminpT[4] = {1., 0., -1., 0.}; + double xmaxpT[4] = {15., 20., 1., 2. * o2::constants::math::PI}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaHE_phiHE", "", 4, varspTHE, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_y_cosThetaHE_phiHE", "", 4, varsrapHE, binsy, xminy, xmaxy, 0, -1, kFALSE); } if (subGroupStr.Contains("upsilon-polarization-cs")) { int varspTCS[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaCS, VarManager::kPhiCS}; - int varsrapCS[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaCS, VarManager::kPhiCS}; int binspT[4] = {100, 20, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; - double xminpT[4] = {1., 0., -1., -3.14}; - double xmaxpT[4] = {15., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {15., 4.0, 1., +3.14}; + double xminpT[4] = {1., 0., -1., 0.}; + double xmaxpT[4] = {15., 20., 1., 2. * o2::constants::math::PI}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaCS_phiCS", "", 4, varspTCS, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_y_cosThetaCS_phiCS", "", 4, varsrapCS, binsy, xminy, xmaxy, 0, -1, kFALSE); } if (subGroupStr.Contains("dimuon-polarization-vp")) { int varspTVP[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosPhiVP, VarManager::kPhiVP}; @@ -1948,29 +2182,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h coschiBins[i] = -1.0 + 2.0 * TMath::Power(0.04 * i, 2.0); } - double deltaetaBins[21]; - for (int i = 0; i < 21; i++) { - deltaetaBins[i] = -2.0 + 0.2 * i; - } - - hm->AddHistogram(histClass, "dileptonmass", "", false, 125, 2.5, 3.5, VarManager::kdileptonmass); + hm->AddHistogram(histClass, "Coschi_unfolding", "", false, 25, coschiBins, VarManager::kMCCosChi_rec, 25, coschiBins, VarManager::kMCCosChi_gen); hm->AddHistogram(histClass, "Coschi", "", false, 25, coschiBins, VarManager::kCosChi, 0, nullptr, -1, 0, nullptr, -1, "", "", "", -1, VarManager::kECWeight); - hm->AddHistogram(histClass, "Pt_Hadron", ";P_{T}", false, 120, 0.0, 30.0, VarManager::kPtDau); - hm->AddHistogram(histClass, "Coschi_wo", "", false, 25, coschiBins, VarManager::kCosChi); - hm->AddHistogram(histClass, "Eta_Hadron", ";#eta", false, 120, -2.0, 2.0, VarManager::kEtaDau); - hm->AddHistogram(histClass, "Phi_Hadron", ";#phi", false, 120, -8, 8, VarManager::kPhiDau); - hm->AddHistogram(histClass, "DeltaEta_DeltaPhi_weight", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -2.0, 6.0, VarManager::kDeltaPhi, 0, 0, 0, -1, "", "", "", -1, VarManager::kEWeight_before); - hm->AddHistogram(histClass, "DeltaEta_DeltaPhi", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -2.0, 6.0, VarManager::kDeltaPhi); - hm->AddHistogram(histClass, "Coschi_DeltaEta", "", false, 25, coschiBins, VarManager::kCosChi, 20, deltaetaBins, VarManager::kDeltaEta, 0, nullptr, -1, "", "", "", -1, VarManager::kECWeight); - hm->AddHistogram(histClass, "Coschi_wo_DeltaEta", "", false, 25, coschiBins, VarManager::kCosChi, 20, deltaetaBins, VarManager::kDeltaEta); - // for bkg - hm->AddHistogram(histClass, "Coschi_randomPhi_trans", "", false, 25, coschiBins, VarManager::kCosChi_randomPhi_trans, 0, nullptr, -1, 0, nullptr, -1, "", "", "", -1, VarManager::kWeight_randomPhi_trans); - hm->AddHistogram(histClass, "Coschi_randomPhi_toward", "", false, 25, coschiBins, VarManager::kCosChi_randomPhi_toward, 0, nullptr, -1, 0, nullptr, -1, "", "", "", -1, VarManager::kWeight_randomPhi_toward); - hm->AddHistogram(histClass, "Coschi_randomPhi_away", "", false, 25, coschiBins, VarManager::kCosChi_randomPhi_away, 0, nullptr, -1, 0, nullptr, -1, "", "", "", -1, VarManager::kWeight_randomPhi_away); - - hm->AddHistogram(histClass, "Coschi_wo_randomPhi_trans", "", false, 25, coschiBins, VarManager::kCosChi_randomPhi_trans); - hm->AddHistogram(histClass, "Coschi_wo_randomPhi_toward", "", false, 25, coschiBins, VarManager::kCosChi_randomPhi_toward); - hm->AddHistogram(histClass, "Coschi_wo_randomPhi_away", "", false, 25, coschiBins, VarManager::kCosChi_randomPhi_away); + hm->AddHistogram(histClass, "DeltaEta_DeltaPhi_weight", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -2.0, 6.0, VarManager::kDeltaPhi, 0, 0, 0, -1, "", "", "", -1, VarManager::kPtDau); } } @@ -2337,7 +2551,7 @@ void o2::aod::dqhistograms::AddHistogramsFromJSON(HistogramManager* hm, const ch str += json[i]; } } - LOG(fatal) << "**** Parsing error is somewhere here: " << str.Data() << endl; + LOG(fatal) << "**** Parsing error is somewhere here: " << str.Data() << std::endl; return; } diff --git a/PWGDQ/Core/HistogramsLibrary.h b/PWGDQ/Core/HistogramsLibrary.h index 869fb3a85f3..99530b1cb6f 100644 --- a/PWGDQ/Core/HistogramsLibrary.h +++ b/PWGDQ/Core/HistogramsLibrary.h @@ -15,11 +15,7 @@ #ifndef PWGDQ_CORE_HISTOGRAMSLIBRARY_H_ #define PWGDQ_CORE_HISTOGRAMSLIBRARY_H_ -#include #include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/VarManager.h" -#include "CommonConstants/MathConstants.h" -#include "rapidjson/document.h" namespace o2::aod { @@ -29,7 +25,7 @@ void DefineHistograms(HistogramManager* hm, const char* histClass, const char* g template bool ValidateJSONHistogram(T hist); void AddHistogramsFromJSON(HistogramManager* hm, const char* json); -} +} // namespace dqhistograms } // namespace o2::aod #endif // PWGDQ_CORE_HISTOGRAMSLIBRARY_H_ diff --git a/PWGDQ/Core/MCProng.cxx b/PWGDQ/Core/MCProng.cxx index f2fffa9ba55..1e50a10fce2 100644 --- a/PWGDQ/Core/MCProng.cxx +++ b/PWGDQ/Core/MCProng.cxx @@ -11,10 +11,16 @@ #include "PWGDQ/Core/MCProng.h" -#include -#include +#include + +#include + #include +#include +#include #include +#include +#include ClassImp(MCProng); diff --git a/PWGDQ/Core/MCProng.h b/PWGDQ/Core/MCProng.h index cd42965d271..4677a995bc7 100644 --- a/PWGDQ/Core/MCProng.h +++ b/PWGDQ/Core/MCProng.h @@ -57,12 +57,13 @@ A few non-existent PYTHIA codes are used to select more than one PYTHIA code. #ifndef PWGDQ_CORE_MCPRONG_H_ #define PWGDQ_CORE_MCPRONG_H_ -#include "TNamed.h" -#include "TString.h" +#include -#include -#include +#include + +#include #include +#include class MCProng { diff --git a/PWGDQ/Core/MCSignal.cxx b/PWGDQ/Core/MCSignal.cxx index 7a234b65088..cb05a02b02c 100644 --- a/PWGDQ/Core/MCSignal.cxx +++ b/PWGDQ/Core/MCSignal.cxx @@ -9,11 +9,18 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include - #include "PWGDQ/Core/MCSignal.h" +#include "MCProng.h" + +#include + +#include + +#include +#include +#include + using std::cout; using std::endl; diff --git a/PWGDQ/Core/MCSignal.h b/PWGDQ/Core/MCSignal.h index 42fe0a0a050..f13f9657fbd 100644 --- a/PWGDQ/Core/MCSignal.h +++ b/PWGDQ/Core/MCSignal.h @@ -57,10 +57,11 @@ process(aod::McParticles const& mcTracks) { #define PWGDQ_CORE_MCSIGNAL_H_ #include "MCProng.h" -#include "TNamed.h" +#include + +#include #include -#include class MCSignal : public TNamed { diff --git a/PWGDQ/Core/MCSignalLibrary.cxx b/PWGDQ/Core/MCSignalLibrary.cxx index c1c2380c3a4..0bc89619d35 100644 --- a/PWGDQ/Core/MCSignalLibrary.cxx +++ b/PWGDQ/Core/MCSignalLibrary.cxx @@ -11,16 +11,24 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include -#include -// #include - #include "PWGDQ/Core/MCSignalLibrary.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/Logger.h" +#include "MCProng.h" +#include "MCSignal.h" + +#include +#include #include +#include + +#include +#include + +#include +#include +#include +#include using namespace o2::constants::physics; // using std::cout; diff --git a/PWGDQ/Core/MCSignalLibrary.h b/PWGDQ/Core/MCSignalLibrary.h index f244c7cbbfc..5b34271a574 100644 --- a/PWGDQ/Core/MCSignalLibrary.h +++ b/PWGDQ/Core/MCSignalLibrary.h @@ -18,9 +18,6 @@ #include "PWGDQ/Core/MCProng.h" #include "PWGDQ/Core/MCSignal.h" -#include "rapidjson/document.h" - -#include #include namespace o2::aod diff --git a/PWGDQ/Core/MixingHandler.cxx b/PWGDQ/Core/MixingHandler.cxx index 532b91ea9ac..5fd601f67d0 100644 --- a/PWGDQ/Core/MixingHandler.cxx +++ b/PWGDQ/Core/MixingHandler.cxx @@ -10,15 +10,18 @@ // or submit itself to any jurisdiction. #include "PWGDQ/Core/MixingHandler.h" + #include "PWGDQ/Core/VarManager.h" -#include -#include -using namespace std; +#include +#include +#include -#include -#include -#include +#include +#include + +#include +using namespace std; ClassImp(MixingHandler); diff --git a/PWGDQ/Core/MixingHandler.h b/PWGDQ/Core/MixingHandler.h index 12b4b4dcc1a..f73d5632895 100644 --- a/PWGDQ/Core/MixingHandler.h +++ b/PWGDQ/Core/MixingHandler.h @@ -17,15 +17,12 @@ #ifndef PWGDQ_CORE_MIXINGHANDLER_H_ #define PWGDQ_CORE_MIXINGHANDLER_H_ -#include "PWGDQ/Core/HistogramManager.h" #include "PWGDQ/Core/VarManager.h" #include -#include -#include -#include #include -#include + +#include #include diff --git a/PWGDQ/Core/MixingLibrary.cxx b/PWGDQ/Core/MixingLibrary.cxx index 37278b90971..28e453b5479 100644 --- a/PWGDQ/Core/MixingLibrary.cxx +++ b/PWGDQ/Core/MixingLibrary.cxx @@ -13,6 +13,16 @@ // #include "PWGDQ/Core/MixingLibrary.h" +#include "PWGDQ/Core/MixingHandler.h" +#include "PWGDQ/Core/VarManager.h" + +#include + +#include + +#include +#include + #include #include @@ -200,3 +210,46 @@ void o2::aod::dqmixing::SetUpMixing(MixingHandler* mh, const char* mixingVarible mh->AddMixingVariable(VarManager::kNTPCcontribLongA, fPileUpLimsHashing.size(), fPileUpLimsHashing); } } + +// Set up mixing hashing by json +void o2::aod::dqmixing::SetUpMixingFromJSON(MixingHandler* mh, const char* json) +{ + rapidjson::Document document; + + rapidjson::ParseResult ok = document.Parse(json); + if (!ok) { + LOG(fatal) << "JSON parse error"; + return; + } + + for (auto it = document.MemberBegin(); it != document.MemberEnd(); ++it) { + std::string nameStr = it->name.GetString(); + const auto& obj = it->value; + + LOG(info) << "Configuring mixing variable: " << nameStr; + + if (!obj.HasMember("var") || !obj.HasMember("LimsHashing")) { + LOG(fatal) << "Missing 'var' or 'LimsHashing' in " << nameStr; + continue; + } + + // read var + std::string varStr = obj["var"].GetString(); + + // read limits + const auto& lims = obj["LimsHashing"]; + std::vector limits; + limits.reserve(lims.Size()); + for (auto& v : lims.GetArray()) { + limits.push_back(v.GetFloat()); + } + + if (VarManager::fgVarNamesMap.find(varStr) == VarManager::fgVarNamesMap.end()) { + LOG(fatal) << "Bad variable (" << varStr << ") specified for this mixing setting"; + return; + } + + // set up mixing variable + mh->AddMixingVariable(VarManager::fgVarNamesMap[varStr], limits.size(), limits); + } +} diff --git a/PWGDQ/Core/MixingLibrary.h b/PWGDQ/Core/MixingLibrary.h index db7f92583df..2372c735cff 100644 --- a/PWGDQ/Core/MixingLibrary.h +++ b/PWGDQ/Core/MixingLibrary.h @@ -11,16 +11,22 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include + +#ifndef PWGDQ_CORE_MIXINGLIBRARY_H_ +#define PWGDQ_CORE_MIXINGLIBRARY_H_ + #include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/VarManager.h" namespace o2::aod { namespace dqmixing { void SetUpMixing(MixingHandler* mh, const char* mixingVarible); +void SetUpMixingFromJSON(MixingHandler* mh, const char* json); } // namespace dqmixing } // namespace o2::aod void o2::aod::dqmixing::SetUpMixing(MixingHandler* mh, const char* mixingVarible); +void o2::aod::dqmixing::SetUpMixingFromJSON(MixingHandler* mh, const char* json); + +#endif // PWGDQ_CORE_MIXINGLIBRARY_H_ diff --git a/PWGDQ/Core/MuonMatchingMlResponse.h b/PWGDQ/Core/MuonMatchingMlResponse.h index 236a4f48329..ee2f419a5f5 100644 --- a/PWGDQ/Core/MuonMatchingMlResponse.h +++ b/PWGDQ/Core/MuonMatchingMlResponse.h @@ -18,7 +18,9 @@ #include "Tools/ML/MlResponse.h" -#include +#include + +#include #include #include diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index ecbec0dc442..bbe9f08f28b 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -8,17 +8,39 @@ // 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 "PWGDQ/Core/VarManager.h" #include "Tools/KFparticle/KFUtilities.h" +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include + +#include + +#include +#include + #include -#include +#include +#include #include +#include +#include #include -using std::cout; -using std::endl; using namespace o2::constants::physics; ClassImp(VarManager); @@ -28,6 +50,7 @@ TString VarManager::fgVariableUnits[VarManager::kNVars] = {""}; std::map VarManager::fgVarNamesMap; bool VarManager::fgUsedVars[VarManager::kNVars] = {false}; bool VarManager::fgUsedKF = false; +bool VarManager::fgPVrecalKF = true; float VarManager::fgMagField = 0.5; float VarManager::fgzMatching = -77.5; float VarManager::fgzShiftFwd = 0.0; @@ -357,6 +380,193 @@ double VarManager::ComputePIDcalibration(int species, double nSigmaValue) } } +//__________________________________________________________________ +std::tuple VarManager::BimodalityCoefficientUnbinned(const std::vector& data) +{ + // Bimodality coefficient = (skewness^2 + 1) / kurtosis + // return a tuple including the coefficient, mean, RMS, skewness, and kurtosis + size_t n = data.size(); + if (n < 3) { + return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0); + } + float mean = std::accumulate(data.begin(), data.end(), 0.0) / n; + + float m2 = 0.0, m3 = 0.0, m4 = 0.0; + float diff, diff2; + for (float x : data) { + diff = x - mean; + diff2 = diff * diff; + m2 += diff2; + m3 += diff2 * diff; + m4 += diff2 * diff2; + } + + m2 /= n; + m3 /= n; + m4 /= n; + + if (m2 == 0.0) { + return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0); + } + + float stddev = std::sqrt(m2); + float skewness = m3 / (stddev * stddev * stddev); + float kurtosis = m4 / (m2 * m2); + + return std::make_tuple((skewness * skewness + 1.0) / kurtosis, mean, stddev, skewness, kurtosis); +} + +std::tuple VarManager::BimodalityCoefficientAndNPeaks(const std::vector& data, float binWidth, int trim, float min, float max) +{ + // Bimodality coefficient = (skewness^2 + 1) / kurtosis + // return a tuple including the coefficient, mean, RMS, skewness, and kurtosis + + // if the binWidth is < 0, use the unbinned calculation + if (binWidth < 0) { + // get the tuple from the unbinned calculation + auto result = BimodalityCoefficientUnbinned(data); + return std::make_tuple(std::get<0>(result), std::get<1>(result), std::get<2>(result), std::get<3>(result), std::get<4>(result), -1); + } + + // bin the data and put it in a vector + int nBins = static_cast((max - min) / binWidth); + std::vector counts(nBins, 0.0); + + for (float x : data) { + if (x < min || x >= max) { + continue; // skip out-of-range values + } + int bin = static_cast((x - min) / binWidth); + if (bin >= 0 && bin < nBins) { + counts[bin]++; + } + } + + // trim the distribution if requested, by requiring a minimum of "trim" counts in each bin + if (trim > 0) { + for (int i = 0; i < nBins; ++i) { + // if the count in the bin is less than the trim value, set it to zero + if (counts[i] < trim) { + // set the count to zero only if this is an isolated bin, + // i.e. if this count belongs to a peak, we want to keep it even if it has counts below the trim limit, as long as the whole peak is not below the trim limit + // check the previous bins until we find an empty bin or we reach the beginning of the histogram + int localPeakCount = counts[i]; + for (int j = i - 1; j >= 0; --j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + // check the next bins until we find an empty bin or we reach the end of the histogram + for (int j = i + 1; j < nBins; ++j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + if (localPeakCount < trim) { + counts[i] = 0; + } + } + } + } + if (trim < 0) { + // if trim is negative, then we remove all counts belonging to local peaks with an integrated count below 1/abs(trim) + for (int i = 0; i < nBins; ++i) { + if (counts[i] == 0) { + continue; // skip empty bins + } + // check the previous bins until we find an empty bin or we reach the beginning of the histogram + int localPeakCount = counts[i]; + for (int j = i - 1; j >= 0; --j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + // check the next bins until we find an empty bin or we reach the end of the histogram + for (int j = i + 1; j < nBins; ++j) { + if (counts[j] == 0) { + break; + } + localPeakCount += counts[j]; + } + if (localPeakCount < (1.0 / std::abs(trim)) * data.size()) { + // set all bins belonging to this local peak to zero + for (int j = i; j >= 0; --j) { + if (counts[j] == 0) { + break; + } + counts[j] = 0; + } + for (int j = i + 1; j < nBins; ++j) { + if (counts[j] == 0) { + break; + } + counts[j] = 0; + } + } + } + } + + // count the number of peaks + int nPeaks = 0; + bool inPeak = false; + for (int i = 0; i < nBins; ++i) { + if (counts[i] > 0) { + if (!inPeak) { + inPeak = true; + nPeaks++; + } + } else { + inPeak = false; + } + } + + // first compute the mean + float mean = 0.0; + float totalCounts = 0.0; + for (int i = 0; i < nBins; ++i) { + float binCenter = min + (i + 0.5) * binWidth; + mean += counts[i] * binCenter; + totalCounts += counts[i]; + } + + if (totalCounts == 0) { + return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0, nPeaks); + } + mean /= totalCounts; + + // then compute the second, third, and fourth central moments + float m2 = 0.0, m3 = 0.0, m4 = 0.0; + float diff, diff2, binCenter; + for (int i = 0; i < nBins; ++i) { + if (counts[i] == 0) { + continue; // skip empty bins + } + binCenter = min + (i + 0.5) * binWidth; + diff = binCenter - mean; + diff2 = diff * diff; + m2 += counts[i] * diff2; + m3 += counts[i] * diff2 * diff; + m4 += counts[i] * diff2 * diff2; + } + + m2 /= totalCounts; + m3 /= totalCounts; + m4 /= totalCounts; + + if (m2 == 0.0) { + return std::make_tuple(-1.0, -1.0, -1.0, -1.0, -1.0, nPeaks); + } + + float stddev = std::sqrt(m2); + float skewness = m3 / (stddev * stddev * stddev); + float kurtosis = m4 / (m2 * m2); // Pearson's kurtosis, not excess + + return std::make_tuple((skewness * skewness + 1.0) / kurtosis, mean, stddev, skewness, kurtosis, nPeaks); +} + //__________________________________________________________________ void VarManager::SetDefaultVarNames() { @@ -388,6 +598,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTimeFromSOR] = "min."; fgVariableNames[kBCOrbit] = "Bunch crossing"; fgVariableUnits[kBCOrbit] = ""; + fgVariableNames[kCollisionRandom] = "Random number (collision-level)"; + fgVariableUnits[kCollisionRandom] = ""; fgVariableNames[kIsPhysicsSelection] = "Physics selection"; fgVariableUnits[kIsPhysicsSelection] = ""; fgVariableNames[kVtxX] = "Vtx X "; @@ -576,6 +788,58 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kNTPCmedianTimeShortA] = "#mu s"; fgVariableNames[kNTPCmedianTimeShortC] = "# TPC-C pileup median time, short time range"; fgVariableUnits[kNTPCmedianTimeShortC] = "#mu s"; + fgVariableNames[kDCAzBimodalityCoefficient] = "Unbinned Bimodality Coeff of DCAz distribution"; + fgVariableUnits[kDCAzBimodalityCoefficient] = ""; + fgVariableNames[kDCAzBimodalityCoefficientBinned] = "Binned Bimodality Coeff of DCAz distribution"; + fgVariableUnits[kDCAzBimodalityCoefficientBinned] = ""; + fgVariableNames[kDCAzBimodalityCoefficientBinnedTrimmed1] = "Binned Bimodality Coeff of DCAz distribution (trimmed 1)"; + fgVariableUnits[kDCAzBimodalityCoefficientBinnedTrimmed1] = ""; + fgVariableNames[kDCAzBimodalityCoefficientBinnedTrimmed2] = "Binned Bimodality Coeff of DCAz distribution (trimmed 2)"; + fgVariableUnits[kDCAzBimodalityCoefficientBinnedTrimmed2] = ""; + fgVariableNames[kDCAzBimodalityCoefficientBinnedTrimmed3] = "Binned Bimodality Coeff of DCAz distribution (trimmed 3)"; + fgVariableUnits[kDCAzBimodalityCoefficientBinnedTrimmed3] = ""; + fgVariableNames[kDCAzMean] = "Mean of DCAz distribution"; + fgVariableUnits[kDCAzMean] = "cm"; + fgVariableNames[kDCAzMeanBinnedTrimmed1] = "Mean of DCAz distribution (trimmed 1)"; + fgVariableUnits[kDCAzMeanBinnedTrimmed1] = "cm"; + fgVariableNames[kDCAzMeanBinnedTrimmed2] = "Mean of DCAz distribution (trimmed 2)"; + fgVariableUnits[kDCAzMeanBinnedTrimmed2] = "cm"; + fgVariableNames[kDCAzMeanBinnedTrimmed3] = "Mean of DCAz distribution (trimmed 3)"; + fgVariableUnits[kDCAzMeanBinnedTrimmed3] = "cm"; + fgVariableNames[kDCAzRMS] = "RMS of DCAz distribution"; + fgVariableUnits[kDCAzRMS] = "cm"; + fgVariableNames[kDCAzRMSBinnedTrimmed1] = "RMS of DCAz distribution (trimmed 1)"; + fgVariableUnits[kDCAzRMSBinnedTrimmed1] = "cm"; + fgVariableNames[kDCAzRMSBinnedTrimmed2] = "RMS of DCAz distribution (trimmed 2)"; + fgVariableUnits[kDCAzRMSBinnedTrimmed2] = "cm"; + fgVariableNames[kDCAzRMSBinnedTrimmed3] = "RMS of DCAz distribution (trimmed 3)"; + fgVariableUnits[kDCAzRMSBinnedTrimmed3] = "cm"; + fgVariableNames[kDCAzSkewness] = "Skewness of DCAz distribution"; + fgVariableUnits[kDCAzSkewness] = ""; + fgVariableNames[kDCAzKurtosis] = "Kurtosis of DCAz distribution"; + fgVariableUnits[kDCAzKurtosis] = ""; + fgVariableNames[kDCAzFracAbove100um] = "Fraction of tracks with |DCAz| > 100 um"; + fgVariableUnits[kDCAzFracAbove100um] = ""; + fgVariableNames[kDCAzFracAbove200um] = "Fraction of tracks with |DCAz| > 200 um"; + fgVariableUnits[kDCAzFracAbove200um] = ""; + fgVariableNames[kDCAzFracAbove500um] = "Fraction of tracks with |DCAz| > 500 um"; + fgVariableUnits[kDCAzFracAbove500um] = ""; + fgVariableNames[kDCAzFracAbove1mm] = "Fraction of tracks with |DCAz| > 1 mm"; + fgVariableUnits[kDCAzFracAbove1mm] = ""; + fgVariableNames[kDCAzFracAbove2mm] = "Fraction of tracks with |DCAz| > 2 mm"; + fgVariableUnits[kDCAzFracAbove2mm] = ""; + fgVariableNames[kDCAzFracAbove5mm] = "Fraction of tracks with |DCAz| > 5 mm"; + fgVariableUnits[kDCAzFracAbove5mm] = ""; + fgVariableNames[kDCAzFracAbove10mm] = "Fraction of tracks with |DCAz| > 10 mm"; + fgVariableUnits[kDCAzFracAbove10mm] = ""; + fgVariableNames[kDCAzNPeaks] = "Number of peaks in DCAz distribution"; + fgVariableUnits[kDCAzNPeaks] = ""; + fgVariableNames[kDCAzNPeaksTrimmed1] = "Number of peaks in binned DCAz distribution (trimmed 1)"; + fgVariableUnits[kDCAzNPeaksTrimmed1] = ""; + fgVariableNames[kDCAzNPeaksTrimmed2] = "Number of peaks in binned DCAz distribution (trimmed 2)"; + fgVariableUnits[kDCAzNPeaksTrimmed2] = ""; + fgVariableNames[kDCAzNPeaksTrimmed3] = "Number of peaks in binned DCAz distribution (trimmed 3)"; + fgVariableUnits[kDCAzNPeaksTrimmed3] = ""; fgVariableNames[kPt] = "p_{T}"; fgVariableUnits[kPt] = "GeV/c"; fgVariableNames[kPt1] = "p_{T1}"; @@ -1193,6 +1457,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kR3SP] = ""; fgVariableNames[kR3EP] = "R_{3}^{EP} "; fgVariableUnits[kR3EP] = ""; + fgVariableNames[kNPairsPerEvent] = "number of pairs per event"; + fgVariableUnits[kNPairsPerEvent] = ""; fgVariableNames[kPairMass] = "mass"; fgVariableUnits[kPairMass] = "GeV/c2"; fgVariableNames[kPairMassDau] = "mass dilepton"; @@ -1301,6 +1567,12 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kPhiCharmHadron] = "rad."; fgVariableNames[kBdtCharmHadron] = "BDT score (charm hadron)"; fgVariableUnits[kBdtCharmHadron] = " "; + fgVariableNames[kDeltaPt] = "pT Reco - pT MC "; + fgVariableUnits[kDeltaPt] = "GeV/c"; + fgVariableNames[kPtResolution] = "Resolution (pT Reco - pT MC) / pT MC"; + fgVariableUnits[kPtResolution] = ""; + fgVariableNames[kEtaResolution] = "Resolution (eta Reco - eta MC)"; + fgVariableUnits[kEtaResolution] = ""; fgVariableNames[kIsDoubleGap] = "is double gap event"; fgVariableUnits[kIsDoubleGap] = ""; fgVariableNames[kIsSingleGapA] = "is single gap event side A"; @@ -1413,6 +1685,122 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kBBFDDCpf] = ""; fgVariableNames[kBGFDDCpf] = "FDDC BG pileup flag"; fgVariableUnits[kBGFDDCpf] = ""; + fgVariableNames[kMultDensity] = "dNdeta ALICE3"; + fgVariableUnits[kMultDensity] = ""; + fgVariableNames[kMultMCNParticlesEta40] = "Multiplicity_eta40"; + fgVariableUnits[kMultMCNParticlesEta40] = ""; + fgVariableNames[kMultMCNParticlesEta20] = "Multiplicity_eta20"; + fgVariableUnits[kMultMCNParticlesEta20] = ""; + fgVariableNames[kIsReconstructed] = "is track reconstructed"; + fgVariableUnits[kIsReconstructed] = ""; + fgVariableNames[kNSiliconHits] = "Number of hits in silicon layers"; + fgVariableUnits[kNSiliconHits] = ""; + fgVariableNames[kNTPCHits] = "Number of TPC hits"; + fgVariableUnits[kNTPCHits] = ""; + fgVariableNames[kOTTOTSignal] = "time over threshold signal in OT"; + fgVariableUnits[kOTTOTSignal] = ""; + fgVariableNames[kOTnSigmaEl] = "n #sigma_{e}^{OT}"; + fgVariableUnits[kOTnSigmaEl] = ""; + fgVariableNames[kOTnSigmaMu] = "n #sigma_{Mu}^{OT}"; + fgVariableUnits[kOTnSigmaMu] = ""; + fgVariableNames[kOTnSigmaPi] = "n #sigma_{Pi}^{OT}"; + fgVariableUnits[kOTnSigmaPi] = ""; + fgVariableNames[kOTnSigmaKa] = "n #sigma_{Ka}^{OT}"; + fgVariableUnits[kOTnSigmaKa] = ""; + fgVariableNames[kOTnSigmaPr] = "n #sigma_{Pr}^{OT}"; + fgVariableUnits[kOTnSigmaPr] = ""; + fgVariableNames[kOTnSigmaDe] = "n #sigma_{De}^{OT}"; + fgVariableUnits[kOTnSigmaDe] = ""; + fgVariableNames[kOTnSigmaTr] = "n #sigma_{Tr}^{OT}"; + fgVariableUnits[kOTnSigmaTr] = ""; + fgVariableNames[kOTnSigmaHe3] = "n #sigma_{He3}^{OT}"; + fgVariableUnits[kOTnSigmaHe3] = ""; + fgVariableNames[kOTnSigmaAl] = "n #sigma_{Al}^{OT}"; + fgVariableUnits[kOTnSigmaAl] = ""; + fgVariableNames[kHasRICHSig] = "Has signal in RICH barrel"; + fgVariableUnits[kHasRICHSig] = ""; + fgVariableNames[kHasRICHSigInGas] = "Has signal in RICH gas radiator"; + fgVariableUnits[kHasRICHSigInGas] = ""; + fgVariableNames[kHasRICHSigEl] = "Has El signal in RICH"; + fgVariableUnits[kHasRICHSigEl] = ""; + fgVariableNames[kHasRICHSigMu] = "Has Mu signal in RICH"; + fgVariableUnits[kHasRICHSigMu] = ""; + fgVariableNames[kHasRICHSigPi] = "Has Pi signal in RICH"; + fgVariableUnits[kHasRICHSigPi] = ""; + fgVariableNames[kHasRICHSigKa] = "Has Ka signal in RICH"; + fgVariableUnits[kHasRICHSigKa] = ""; + fgVariableNames[kHasRICHSigPr] = "Has Pr signal in RICH"; + fgVariableUnits[kHasRICHSigPr] = ""; + fgVariableNames[kHasRICHSigDe] = "Has De signal in RICH"; + fgVariableUnits[kHasRICHSigDe] = ""; + fgVariableNames[kHasRICHSigTr] = "Has Tr signal in RICH"; + fgVariableUnits[kHasRICHSigTr] = ""; + fgVariableNames[kHasRICHSigHe3] = "Has He3 signal in RICH"; + fgVariableUnits[kHasRICHSigHe3] = ""; + fgVariableNames[kHasRICHSigAl] = "Has Al signal in RICH"; + fgVariableUnits[kHasRICHSigAl] = ""; + fgVariableNames[kRICHnSigmaEl] = "n #sigma_{El}^{RHICH}"; + fgVariableUnits[kRICHnSigmaEl] = ""; + fgVariableNames[kRICHnSigmaMu] = "n #sigma_{Mu}^{RHICH}"; + fgVariableUnits[kRICHnSigmaMu] = ""; + fgVariableNames[kRICHnSigmaPi] = "n #sigma_{Pi}^{RHICH}"; + fgVariableUnits[kRICHnSigmaPi] = ""; + fgVariableNames[kRICHnSigmaKa] = "n #sigma_{Ka}^{RHICH}"; + fgVariableUnits[kRICHnSigmaKa] = ""; + fgVariableNames[kRICHnSigmaPr] = "n #sigma_{Pr}^{RHICH}"; + fgVariableUnits[kRICHnSigmaPr] = ""; + fgVariableNames[kRICHnSigmaDe] = "n #sigma_{De}^{RHICH}"; + fgVariableUnits[kRICHnSigmaDe] = ""; + fgVariableNames[kRICHnSigmaTr] = "n #sigma_{Tr}^{RHICH}"; + fgVariableUnits[kRICHnSigmaTr] = ""; + fgVariableNames[kRICHnSigmaHe3] = "n #sigma_{He3}^{RHICH}"; + fgVariableUnits[kRICHnSigmaHe3] = ""; + fgVariableNames[kRICHnSigmaAl] = "n #sigma_{Al}^{RHICH}"; + fgVariableUnits[kRICHnSigmaAl] = ""; + fgVariableNames[kTOFEventTime] = "Event time reconstructed with ALICE3 TOF"; + fgVariableUnits[kTOFEventTime] = "ns"; + fgVariableNames[kTOFEventTimeErr] = "Event time error reconstructed with ALICE3 TOF"; + fgVariableUnits[kTOFEventTimeErr] = "ns"; + fgVariableNames[koTOFBeta] = "oTOF #beta"; + fgVariableUnits[koTOFBeta] = ""; + fgVariableNames[kOuterTOFnSigmaEl] = "n #sigma_{El}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaEl] = ""; + fgVariableNames[kOuterTOFnSigmaMu] = "n #sigma_{Mu}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaMu] = ""; + fgVariableNames[kOuterTOFnSigmaPi] = "n #sigma_{Pi}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaPi] = ""; + fgVariableNames[kOuterTOFnSigmaKa] = "n #sigma_{Ka}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaKa] = ""; + fgVariableNames[kOuterTOFnSigmaPr] = "n #sigma_{Pr}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaPr] = ""; + fgVariableNames[kOuterTOFnSigmaDe] = "n #sigma_{De}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaDe] = ""; + fgVariableNames[kOuterTOFnSigmaTr] = "n #sigma_{Tr}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaTr] = ""; + fgVariableNames[kOuterTOFnSigmaHe3] = "n #sigma_{He3}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaHe3] = ""; + fgVariableNames[kOuterTOFnSigmaAl] = "n #sigma_{Al}^{oTOF}"; + fgVariableUnits[kOuterTOFnSigmaAl] = ""; + fgVariableNames[kiTOFBeta] = "iTOF #beta"; + fgVariableUnits[kiTOFBeta] = ""; + fgVariableNames[kInnerTOFnSigmaEl] = "n #sigma_{El}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaEl] = ""; + fgVariableNames[kInnerTOFnSigmaMu] = "n #sigma_{Mu}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaMu] = ""; + fgVariableNames[kInnerTOFnSigmaPi] = "n #sigma_{Pi}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaPi] = ""; + fgVariableNames[kInnerTOFnSigmaKa] = "n #sigma_{Ka}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaKa] = ""; + fgVariableNames[kInnerTOFnSigmaPr] = "n #sigma_{Pr}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaPr] = ""; + fgVariableNames[kInnerTOFnSigmaDe] = "n #sigma_{De}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaDe] = ""; + fgVariableNames[kInnerTOFnSigmaTr] = "n #sigma_{Tr}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaTr] = ""; + fgVariableNames[kInnerTOFnSigmaHe3] = "n #sigma_{He3}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaHe3] = ""; + fgVariableNames[kInnerTOFnSigmaAl] = "n #sigma_{Al}^{iTOF}"; + fgVariableUnits[kInnerTOFnSigmaAl] = ""; // Set the variables short names map. This is needed for dynamic configuration via JSON files fgVarNamesMap["kNothing"] = kNothing; @@ -1430,7 +1818,9 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kCollisionTimeRes"] = kCollisionTimeRes; fgVarNamesMap["kBC"] = kBC; fgVarNamesMap["kBCOrbit"] = kBCOrbit; + fgVarNamesMap["kCollisionRandom"] = kCollisionRandom; fgVarNamesMap["kIsPhysicsSelection"] = kIsPhysicsSelection; + fgVarNamesMap["kIsTVXTriggered"] = kIsTVXTriggered; fgVarNamesMap["kIsNoTFBorder"] = kIsNoTFBorder; fgVarNamesMap["kIsNoITSROFBorder"] = kIsNoITSROFBorder; fgVarNamesMap["kIsNoITSROFBorderRecomputed"] = kIsNoITSROFBorderRecomputed; @@ -1442,6 +1832,7 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kIsGoodITSLayer3"] = kIsGoodITSLayer3; fgVarNamesMap["kIsGoodITSLayer0123"] = kIsGoodITSLayer0123; fgVarNamesMap["kIsGoodITSLayersAll"] = kIsGoodITSLayersAll; + fgVarNamesMap["kIsTriggerZNAZNC"] = kIsTriggerZNAZNC; fgVarNamesMap["kIsINT7"] = kIsINT7; fgVarNamesMap["kIsEMC7"] = kIsEMC7; fgVarNamesMap["kIsINT7inMUON"] = kIsINT7inMUON; @@ -1513,6 +1904,32 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kNTPCmeanTimeShortC"] = kNTPCmeanTimeShortC; fgVarNamesMap["kNTPCmedianTimeShortA"] = kNTPCmedianTimeShortA; fgVarNamesMap["kNTPCmedianTimeShortC"] = kNTPCmedianTimeShortC; + fgVarNamesMap["kDCAzBimodalityCoefficient"] = kDCAzBimodalityCoefficient; + fgVarNamesMap["kDCAzBimodalityCoefficientBinned"] = kDCAzBimodalityCoefficientBinned; + fgVarNamesMap["kDCAzBimodalityCoefficientBinnedTrimmed1"] = kDCAzBimodalityCoefficientBinnedTrimmed1; + fgVarNamesMap["kDCAzBimodalityCoefficientBinnedTrimmed2"] = kDCAzBimodalityCoefficientBinnedTrimmed2; + fgVarNamesMap["kDCAzBimodalityCoefficientBinnedTrimmed3"] = kDCAzBimodalityCoefficientBinnedTrimmed3; + fgVarNamesMap["kDCAzMean"] = kDCAzMean; + fgVarNamesMap["kDCAzMeanBinnedTrimmed1"] = kDCAzMeanBinnedTrimmed1; + fgVarNamesMap["kDCAzMeanBinnedTrimmed2"] = kDCAzMeanBinnedTrimmed2; + fgVarNamesMap["kDCAzMeanBinnedTrimmed3"] = kDCAzMeanBinnedTrimmed3; + fgVarNamesMap["kDCAzRMS"] = kDCAzRMS; + fgVarNamesMap["kDCAzRMSBinnedTrimmed1"] = kDCAzRMSBinnedTrimmed1; + fgVarNamesMap["kDCAzRMSBinnedTrimmed2"] = kDCAzRMSBinnedTrimmed2; + fgVarNamesMap["kDCAzRMSBinnedTrimmed3"] = kDCAzRMSBinnedTrimmed3; + fgVarNamesMap["kDCAzSkewness"] = kDCAzSkewness; + fgVarNamesMap["kDCAzKurtosis"] = kDCAzKurtosis; + fgVarNamesMap["kDCAzFracAbove100um"] = kDCAzFracAbove100um; + fgVarNamesMap["kDCAzFracAbove200um"] = kDCAzFracAbove200um; + fgVarNamesMap["kDCAzFracAbove500um"] = kDCAzFracAbove500um; + fgVarNamesMap["kDCAzFracAbove1mm"] = kDCAzFracAbove1mm; + fgVarNamesMap["kDCAzFracAbove2mm"] = kDCAzFracAbove2mm; + fgVarNamesMap["kDCAzFracAbove5mm"] = kDCAzFracAbove5mm; + fgVarNamesMap["kDCAzFracAbove10mm"] = kDCAzFracAbove10mm; + fgVarNamesMap["kDCAzNPeaks"] = kDCAzNPeaks; + fgVarNamesMap["kDCAzNPeaksTrimmed1"] = kDCAzNPeaksTrimmed1; + fgVarNamesMap["kDCAzNPeaksTrimmed2"] = kDCAzNPeaksTrimmed2; + fgVarNamesMap["kDCAzNPeaksTrimmed3"] = kDCAzNPeaksTrimmed3; fgVarNamesMap["kMCEventGeneratorId"] = kMCEventGeneratorId; fgVarNamesMap["kMCEventSubGeneratorId"] = kMCEventSubGeneratorId; fgVarNamesMap["kMCVtxX"] = kMCVtxX; @@ -1672,6 +2089,7 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kTwoR2SP2"] = kTwoR2SP2; fgVarNamesMap["kTwoR2EP1"] = kTwoR2EP1; fgVarNamesMap["kTwoR2EP2"] = kTwoR2EP2; + fgVarNamesMap["kNPairsPerEvent"] = kNPairsPerEvent; fgVarNamesMap["kNEventWiseVariables"] = kNEventWiseVariables; fgVarNamesMap["kX"] = kX; fgVarNamesMap["kY"] = kY; @@ -1824,7 +2242,30 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kMCCosChi"] = kMCCosChi; fgVarNamesMap["kMCHadronPt"] = kMCHadronPt; fgVarNamesMap["kMCWeight_before"] = kMCWeight_before; + fgVarNamesMap["kMCdeltaeta"] = kMCdeltaeta; + fgVarNamesMap["kMCHadronPt"] = kMCHadronPt; + fgVarNamesMap["kMCHadronEta"] = kMCHadronEta; + fgVarNamesMap["kMCHadronPhi"] = kMCHadronPhi; + fgVarNamesMap["kMCWeight"] = kMCWeight; + fgVarNamesMap["kMCCosChi_randomPhi_toward"] = kMCCosChi_randomPhi_toward; + fgVarNamesMap["kMCWeight_randomPhi_toward"] = kMCWeight_randomPhi_toward; + fgVarNamesMap["kMCCosChi_randomPhi_away"] = kMCCosChi_randomPhi_away; + fgVarNamesMap["kMCWeight_randomPhi_away"] = kMCWeight_randomPhi_away; + fgVarNamesMap["kMCCosChi_randomPhi_trans"] = kMCCosChi_randomPhi_trans; + fgVarNamesMap["kMCWeight_randomPhi_trans"] = kMCWeight_randomPhi_trans; + fgVarNamesMap["kMCdeltaphi_randomPhi_toward"] = kMCdeltaphi_randomPhi_toward; + fgVarNamesMap["kMCdeltaphi_randomPhi_away"] = kMCdeltaphi_randomPhi_away; + fgVarNamesMap["kMCdeltaphi_randomPhi_trans"] = kMCdeltaphi_randomPhi_trans; + fgVarNamesMap["kMCCosChi_gen"] = kMCCosChi_gen; + fgVarNamesMap["kMCWeight_gen"] = kMCWeight_gen; + fgVarNamesMap["kMCdeltaeta_gen"] = kMCdeltaeta_gen; + fgVarNamesMap["kMCCosChi_rec"] = kMCCosChi_rec; + fgVarNamesMap["kMCWeight_rec"] = kMCWeight_rec; + fgVarNamesMap["kMCdeltaeta_rec"] = kMCdeltaeta_rec; fgVarNamesMap["kMCParticleWeight"] = kMCParticleWeight; + fgVarNamesMap["kMCCosTheta"] = kMCCosTheta; + fgVarNamesMap["kMCdeltaphi"] = kMCdeltaphi; + fgVarNamesMap["kMCJpsiPt"] = kMCJpsiPt; fgVarNamesMap["kMCPx"] = kMCPx; fgVarNamesMap["kMCPy"] = kMCPy; fgVarNamesMap["kMCPz"] = kMCPz; @@ -2045,6 +2486,16 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kPtDau"] = kPtDau; fgVarNamesMap["kEtaDau"] = kEtaDau; fgVarNamesMap["kPhiDau"] = kPhiDau; + fgVarNamesMap["kCosChi_randomPhi_trans"] = kCosChi_randomPhi_trans; + fgVarNamesMap["kCosChi_randomPhi_toward"] = kCosChi_randomPhi_toward; + fgVarNamesMap["kCosChi_randomPhi_away"] = kCosChi_randomPhi_away; + fgVarNamesMap["kWeight_randomPhi_trans"] = kWeight_randomPhi_trans; + fgVarNamesMap["kWeight_randomPhi_toward"] = kWeight_randomPhi_toward; + fgVarNamesMap["kWeight_randomPhi_away"] = kWeight_randomPhi_away; + fgVarNamesMap["kdeltaphi_randomPhi_trans"] = kdeltaphi_randomPhi_trans; + fgVarNamesMap["kdeltaphi_randomPhi_toward"] = kdeltaphi_randomPhi_toward; + fgVarNamesMap["kdeltaphi_randomPhi_away"] = kdeltaphi_randomPhi_away; + fgVarNamesMap["kdileptonmass"] = kdileptonmass; fgVarNamesMap["kNCorrelationVariables"] = kNCorrelationVariables; fgVarNamesMap["kQuadMass"] = kQuadMass; fgVarNamesMap["kQuadDefaultDileptonMass"] = kQuadDefaultDileptonMass; @@ -2102,4 +2553,58 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kBGFDDApf"] = kBGFDDApf; fgVarNamesMap["kBBFDDCpf"] = kBBFDDCpf; fgVarNamesMap["kBGFDDCpf"] = kBGFDDCpf; + fgVarNamesMap["kMultDensity"] = kMultDensity; + fgVarNamesMap["kMultMCNParticlesEta40"] = kMultMCNParticlesEta40; + fgVarNamesMap["kMultMCNParticlesEta20"] = kMultMCNParticlesEta20; + fgVarNamesMap["kIsReconstructed"] = kIsReconstructed; + fgVarNamesMap["kNSiliconHits"] = kNSiliconHits; + fgVarNamesMap["kNTPCHits"] = kNTPCHits; + fgVarNamesMap["kOTTOTSignal"] = kOTTOTSignal; + fgVarNamesMap["kOTnSigmaEl"] = kOTnSigmaEl; + fgVarNamesMap["kOTnSigmaMu"] = kOTnSigmaMu; + fgVarNamesMap["kOTnSigmaPi"] = kOTnSigmaPi; + fgVarNamesMap["kOTnSigmaKa"] = kOTnSigmaKa; + fgVarNamesMap["kOTnSigmaPr"] = kOTnSigmaPr; + fgVarNamesMap["kOTnSigmaDe"] = kOTnSigmaDe; + fgVarNamesMap["kOTnSigmaTr"] = kOTnSigmaTr; + fgVarNamesMap["kOTnSigmaHe3"] = kOTnSigmaHe3; + fgVarNamesMap["kOTnSigmaAl"] = kOTnSigmaAl; + fgVarNamesMap["kHasRICHSig"] = kHasRICHSig; + fgVarNamesMap["kHasRICHSigInGas"] = kHasRICHSigInGas; + fgVarNamesMap["kHasRICHSigEl"] = kHasRICHSigEl; + fgVarNamesMap["kHasRICHSigMu"] = kHasRICHSigMu; + fgVarNamesMap["kHasRICHSigPi"] = kHasRICHSigPi; + fgVarNamesMap["kHasRICHSigKa"] = kHasRICHSigKa; + fgVarNamesMap["kHasRICHSigPr"] = kHasRICHSigPr; + fgVarNamesMap["kHasRICHSigDe"] = kHasRICHSigDe; + fgVarNamesMap["kHasRICHSigTr"] = kHasRICHSigTr; + fgVarNamesMap["kHasRICHSigHe3"] = kHasRICHSigHe3; + fgVarNamesMap["kHasRICHSigAl"] = kHasRICHSigAl; + fgVarNamesMap["kRICHnSigmaEl"] = kRICHnSigmaEl; + fgVarNamesMap["kRICHnSigmaMu"] = kRICHnSigmaMu; + fgVarNamesMap["kRICHnSigmaPi"] = kRICHnSigmaPi; + fgVarNamesMap["kRICHnSigmaKa"] = kRICHnSigmaKa; + fgVarNamesMap["kRICHnSigmaPr"] = kRICHnSigmaPr; + fgVarNamesMap["kRICHnSigmaDe"] = kRICHnSigmaDe; + fgVarNamesMap["kRICHnSigmaTr"] = kRICHnSigmaTr; + fgVarNamesMap["kRICHnSigmaHe3"] = kRICHnSigmaHe3; + fgVarNamesMap["kRICHnSigmaAl"] = kRICHnSigmaAl; + fgVarNamesMap["kOuterTOFnSigmaEl"] = kOuterTOFnSigmaEl; + fgVarNamesMap["kOuterTOFnSigmaMu"] = kOuterTOFnSigmaMu; + fgVarNamesMap["kOuterTOFnSigmaPi"] = kOuterTOFnSigmaPi; + fgVarNamesMap["kOuterTOFnSigmaKa"] = kOuterTOFnSigmaKa; + fgVarNamesMap["kOuterTOFnSigmaPr"] = kOuterTOFnSigmaPr; + fgVarNamesMap["kOuterTOFnSigmaDe"] = kOuterTOFnSigmaDe; + fgVarNamesMap["kOuterTOFnSigmaTr"] = kOuterTOFnSigmaTr; + fgVarNamesMap["kOuterTOFnSigmaHe3"] = kOuterTOFnSigmaHe3; + fgVarNamesMap["kOuterTOFnSigmaAl"] = kOuterTOFnSigmaAl; + fgVarNamesMap["kInnerTOFnSigmaEl"] = kInnerTOFnSigmaEl; + fgVarNamesMap["kInnerTOFnSigmaMu"] = kInnerTOFnSigmaMu; + fgVarNamesMap["kInnerTOFnSigmaPi"] = kInnerTOFnSigmaPi; + fgVarNamesMap["kInnerTOFnSigmaKa"] = kInnerTOFnSigmaKa; + fgVarNamesMap["kInnerTOFnSigmaPr"] = kInnerTOFnSigmaPr; + fgVarNamesMap["kInnerTOFnSigmaDe"] = kInnerTOFnSigmaDe; + fgVarNamesMap["kInnerTOFnSigmaTr"] = kInnerTOFnSigmaTr; + fgVarNamesMap["kInnerTOFnSigmaHe3"] = kInnerTOFnSigmaHe3; + fgVarNamesMap["kInnerTOFnSigmaAl"] = kInnerTOFnSigmaAl; } diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 6097dcf3ef8..594317a5cd4 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -22,38 +22,45 @@ #endif #include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/Core/UPCHelpers.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" -#include "Common/Core/CollisionTypeHelper.h" #include "Common/Core/EventPlaneHelper.h" -#include "Common/Core/PID/PIDTOFParamService.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/fwdtrackUtilities.h" #include "Common/Core/trackUtilities.h" #include +#include #include #include #include +#include +#include +#include #include -#include #include #include +#include #include +#include #include +#include #include #include +#include #include #include +#include +#include #include -#include -#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include -#include -#include -#include -#include +#include +#include #include #include #include @@ -61,21 +68,21 @@ #include #include #include -#include -#include -#include +#include +#include +#include + +#include #include #include #include -#include #include +#include #include #include -using std::complex; -using std::cout; -using std::endl; +#include using SMatrix55 = ROOT::Math::SMatrix>; using SMatrix5 = ROOT::Math::SVector; @@ -206,7 +213,9 @@ class VarManager : public TObject kCollisionTimeRes, kBC, kBCOrbit, + kCollisionRandom, // random number generated per collision (if required, can be used to perform random selections at the collision level) kIsPhysicsSelection, + kIsTVXTriggered, // Is trigger TVX kIsNoTFBorder, // No time frame border kIsNoITSROFBorder, // No ITS read out frame border (from event selection) kIsNoITSROFBorderRecomputed, // No ITS read out frame border, computed here @@ -218,6 +227,7 @@ class VarManager : public TObject kIsGoodITSLayer3, // number of inactive chips on ITS layer 3 is below maximum allowed value kIsGoodITSLayer0123, // numbers of inactive chips on ITS layers 0-3 are below maximum allowed values kIsGoodITSLayersAll, // numbers of inactive chips on all ITS layers are below maximum allowed values + kIsTriggerZNAZNC, // trigger ZNA && ZNC kIsINT7, kIsEMC7, kIsINT7inMUON, @@ -291,6 +301,32 @@ class VarManager : public TObject kNTPCmeanTimeShortC, kNTPCmedianTimeShortA, kNTPCmedianTimeShortC, + kDCAzBimodalityCoefficient, + kDCAzMean, + kDCAzRMS, + kDCAzSkewness, + kDCAzKurtosis, + kDCAzBimodalityCoefficientBinned, + kDCAzBimodalityCoefficientBinnedTrimmed1, + kDCAzBimodalityCoefficientBinnedTrimmed2, + kDCAzBimodalityCoefficientBinnedTrimmed3, + kDCAzMeanBinnedTrimmed1, + kDCAzMeanBinnedTrimmed2, + kDCAzMeanBinnedTrimmed3, + kDCAzRMSBinnedTrimmed1, + kDCAzRMSBinnedTrimmed2, + kDCAzRMSBinnedTrimmed3, + kDCAzFracAbove100um, + kDCAzFracAbove200um, + kDCAzFracAbove500um, + kDCAzFracAbove1mm, + kDCAzFracAbove2mm, + kDCAzFracAbove5mm, + kDCAzFracAbove10mm, + kDCAzNPeaks, + kDCAzNPeaksTrimmed1, + kDCAzNPeaksTrimmed2, + kDCAzNPeaksTrimmed3, kMCEventGeneratorId, kMCEventSubGeneratorId, kMCVtxX, @@ -450,10 +486,11 @@ class VarManager : public TObject kV2ME_EP, kWV2ME_SP, kWV2ME_EP, - kTwoR2SP1, // Scalar product resolution of event1 for ME technique - kTwoR2SP2, // Scalar product resolution of event2 for ME technique - kTwoR2EP1, // Event plane resolution of event2 for ME technique - kTwoR2EP2, // Event plane resolution of event2 for ME technique + kTwoR2SP1, // Scalar product resolution of event1 for ME technique + kTwoR2SP2, // Scalar product resolution of event2 for ME technique + kTwoR2EP1, // Event plane resolution of event2 for ME technique + kTwoR2EP2, // Event plane resolution of event2 for ME technique + kNPairsPerEvent, // number of pairs per event in same-event or mixed-event pairing // Variables for event mixing with cumulant kV22m, @@ -655,11 +692,21 @@ class VarManager : public TObject kMCdeltaphi_randomPhi_away, kMCdeltaphi_randomPhi_trans, kMCWeight_before, + kMCCosChi_gen, + kMCWeight_gen, + kMCdeltaeta_gen, + kMCCosChi_rec, + kMCWeight_rec, + kMCdeltaeta_rec, // MC mother particle variables kMCMotherPdgCode, // MC pair variables + kMCPt1, + kMCEta1, + kMCPt2, + kMCEta2, kMCCosThetaHE, kMCPhiHE, kMCPhiTildeHE, @@ -691,6 +738,7 @@ class VarManager : public TObject kMCVertexingTauxy, kVertexingLzProjected, kVertexingLxyProjected, + kVertexingLxyProjectedRecalculatePV, kVertexingLxyzProjected, kMCVertexingLzProjected, kMCVertexingLxyProjected, @@ -698,6 +746,7 @@ class VarManager : public TObject kVertexingTauzProjected, kVertexingTauxyProjected, kVertexingTauxyProjectedPoleJPsiMass, + kVertexingTauxyProjectedPoleJPsiMassRecalculatePV, kVertexingTauxyProjectedNs, kVertexingTauxyzProjected, kMCVertexingTauzProjected, @@ -917,6 +966,11 @@ class VarManager : public TObject kPhiCharmHadron, kBdtCharmHadron, + // Resolution variables + kDeltaPt, + kPtResolution, + kEtaResolution, + // Index used to scan bit maps kBitMapIndex, @@ -958,6 +1012,67 @@ class VarManager : public TObject kNFiredChannelsFT0C, kNFiredChannelsFV0A, + // ALICE 3 Variables + kMultDensity, + kMultMCNParticlesEta40, + kMultMCNParticlesEta20, + kIsReconstructed, + kNSiliconHits, + kNTPCHits, + kOTTOTSignal, + kOTnSigmaEl, + kOTnSigmaMu, + kOTnSigmaPi, + kOTnSigmaKa, + kOTnSigmaPr, + kOTnSigmaDe, + kOTnSigmaTr, + kOTnSigmaHe3, + kOTnSigmaAl, + kHasRICHSig, + kHasRICHSigInGas, + kHasRICHSigEl, + kHasRICHSigMu, + kHasRICHSigPi, + kHasRICHSigKa, + kHasRICHSigPr, + kHasRICHSigDe, + kHasRICHSigTr, + kHasRICHSigHe3, + kHasRICHSigAl, + kRICHnSigmaEl, + kRICHnSigmaMu, + kRICHnSigmaPi, + kRICHnSigmaKa, + kRICHnSigmaPr, + kRICHnSigmaDe, + kRICHnSigmaTr, + kRICHnSigmaHe3, + kRICHnSigmaAl, + kTOFEventTime, + kTOFEventTimeErr, + kiTOFBeta, + koTOFBeta, + kOuterTOFnSigmaEl, + kOuterTOFnSigmaMu, + kOuterTOFnSigmaPi, + kOuterTOFnSigmaKa, + kOuterTOFnSigmaPr, + kOuterTOFnSigmaDe, + kOuterTOFnSigmaTr, + kOuterTOFnSigmaHe3, + kOuterTOFnSigmaAl, + kInnerTOFnSigmaEl, + kInnerTOFnSigmaMu, + kInnerTOFnSigmaPi, + kInnerTOFnSigmaKa, + kInnerTOFnSigmaPr, + kInnerTOFnSigmaDe, + kInnerTOFnSigmaTr, + kInnerTOFnSigmaHe3, + kInnerTOFnSigmaAl, + kA3Variables, + kNVars }; // end of Variables enumeration @@ -1033,6 +1148,12 @@ class VarManager : public TObject return false; } + // Flag to set PV recalculation via KF + static void SetPVrecalculationKF(const bool pvRecalKF) + { + fgPVrecalKF = pvRecalKF; + } + // Setup the collision system static void SetCollisionSystem(TString system, float energy); static void SetCollisionSystem(o2::parameters::GRPLHCIFData* grplhcif); @@ -1167,6 +1288,11 @@ class VarManager : public TObject } return deltaPsi; } + template + static o2::dataformats::VertexBase RecalculatePrimaryVertex(T const& track0, T const& track1, const T1& collision); + + static std::tuple BimodalityCoefficientUnbinned(const std::vector& data); + static std::tuple BimodalityCoefficientAndNPeaks(const std::vector& data, float binWidth, int trim = 0, float min = -15.0, float max = 15.0); template static o2::track::TrackParCovFwd FwdToTrackPar(const T& track, const C& cov); @@ -1183,6 +1309,8 @@ class VarManager : public TObject template static void FillEvent(T const& event, float* values = nullptr); template + static void FillEventTracks(T const& tracks, float* values = nullptr); + template static void FillTimeFrame(T const& tfTable, float* values = nullptr); template static void FillEventFlowResoFactor(T const& hs_sp, T const& hs_ep, float* values = nullptr); @@ -1207,7 +1335,7 @@ class VarManager : public TObject template static void FillTrackMC(const U& mcStack, T const& track, float* values = nullptr); template - static void FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* values = nullptr); + static void FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3); template static void FillPairPropagateMuon(T1 const& muon1, T2 const& muon2, const C& collision, float* values = nullptr); template @@ -1232,14 +1360,18 @@ class VarManager : public TObject static void FillQuadMC(T1 const& t1, T2 const& t2, T2 const& t3, float* values = nullptr); template static void FillPairVertexing(C const& collision, T const& t1, T const& t2, bool propToSV = false, float* values = nullptr); + template + static void FillPairVertexingRecomputePV(C const& /*collision*/, T const& t1, T const& t2, o2::dataformats::VertexBase pvRefitted, float* values = nullptr); template static void FillTripletVertexing(C const& collision, T const& t1, T const& t2, T const& t3, PairCandidateType tripletType, float* values = nullptr); template static void FillDileptonTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track, float* values); template static void FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float hadronMass = 0.0f); - template - static void FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, float* values = nullptr, bool applyFitMass = false, float sidebandMass = 0.0f); + template + static void FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, float* values = nullptr, float Translow = 1. / 3, float Transhigh = 2. / 3, bool applyFitMass = false, float sidebandMass = 0.0f); + template + static void FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values = nullptr, bool applyFitMass = false); template static void FillDileptonPhoton(T1 const& dilepton, T2 const& photon, float* values = nullptr); template @@ -1268,6 +1400,14 @@ class VarManager : public TObject static void FillBdtScore(const T& bdtScore, float* values = nullptr); template static void FillFIT(const T1& bc, const T2& bcs, const T3& ft0s, const T4& fv0as, const T5& fdds, float* values = nullptr); + template + static void FillPairAlice3(T1 const& t1, T2 const& t2, float* values = nullptr); + template + static void FillEventAlice3(T const& event, float* values = nullptr); + template + static void FillTrackAlice3(T const& track, float* values = nullptr); + template + static void FillResolutions(M const& mcTrack, T const& track, float* values = nullptr); static void SetCalibrationObject(CalibObjects calib, TObject* obj) { @@ -1338,6 +1478,7 @@ class VarManager : public TObject private: static bool fgUsedVars[kNVars]; // holds flags for when the corresponding variable is needed (e.g., in the histogram manager, in cuts, mixing handler, etc.) static bool fgUsedKF; + static bool fgPVrecalKF; static void SetVariableDependencies(); // toggle those variables on which other used variables might depend static float fgMagField; @@ -1386,7 +1527,7 @@ class VarManager : public TObject VarManager& operator=(const VarManager& c); VarManager(const VarManager& c); - ClassDef(VarManager, 5); + ClassDef(VarManager, 6); }; template @@ -1481,6 +1622,44 @@ KFPVertex VarManager::createKFPVertexFromCollision(const T& collision) return kfpVertex; } +template +o2::dataformats::VertexBase VarManager::RecalculatePrimaryVertex(T const& track0, T const& track1, const T1& collision) +{ + KFParticle trk0KF; + KFPTrack kfpTrack0 = createKFPTrackFromTrack(track0); + trk0KF = KFParticle(kfpTrack0, -11 * track0.sign()); + KFParticle trk1KF; + KFPTrack kfpTrack1 = createKFPTrackFromTrack(track1); + trk1KF = KFParticle(kfpTrack1, -11 * track1.sign()); + + KFParticle kVtx; + kVtx.Initialize(); + kVtx.Parameter(0) = collision.posX(); + kVtx.Parameter(1) = collision.posY(); + kVtx.Parameter(2) = collision.posZ(); + kVtx.Covariance(0) = collision.covXX(); + kVtx.Covariance(1) = collision.covXY(); + kVtx.Covariance(2) = collision.covYY(); + kVtx.Covariance(3) = collision.covXZ(); + kVtx.Covariance(4) = collision.covYZ(); + kVtx.Covariance(5) = collision.covZZ(); + kVtx.Chi2() = collision.chi2(); // FIX THIS! to be added in AliReducedEventInfo + kVtx.NDF() = 2 * collision.multNTracksPV() - 3; + // KFVertex kfpVertex(kVtx); // kfpVertex.Initialize(); + + if ((track0.flags() & o2::aod::track::PVContributor) > 0) { + trk0KF.SubtractFromVertex(kVtx); /*printf("track1 -> subtracting \n");*/ + } + if ((track1.flags() & o2::aod::track::PVContributor) > 0) { + trk1KF.SubtractFromVertex(kVtx); /*printf("track2 -> subtracting \n");*/ + } + + o2::math_utils::Point3D vtxXYZ(kVtx.Parameter(0), kVtx.Parameter(1), kVtx.Parameter(2)); + std::array vtxCov{kVtx.Covariance(0), kVtx.Covariance(1), kVtx.Covariance(2), kVtx.Covariance(3), kVtx.Covariance(4), kVtx.Covariance(5)}; + o2::dataformats::VertexBase primaryVertexRec = {std::move(vtxXYZ), std::move(vtxCov)}; + return primaryVertexRec; +} + template o2::dataformats::GlobalFwdTrack VarManager::PropagateMuon(const T& muon, const C& collision, const int endPoint) { @@ -1702,6 +1881,10 @@ void VarManager::FillEvent(T const& event, float* values) values[kTimestamp] = event.timestamp(); } + if (fgUsedVars[kCollisionRandom]) { + values[kCollisionRandom] = gRandom->Rndm(); + } + if constexpr ((fillMap & Collision) > 0) { // TODO: trigger info from the event selection requires a separate flag // so that it can be switched off independently of the rest of Collision variables (e.g. if event selection is not available) @@ -1718,9 +1901,15 @@ void VarManager::FillEvent(T const& event, float* values) if (fgUsedVars[kNoCollInTimeRangeStandard]) { values[kNoCollInTimeRangeStandard] = event.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); } + if (fgUsedVars[kIsTVXTriggered]) { + values[kIsTVXTriggered] = event.selection_bit(o2::aod::evsel::kIsTriggerTVX); + } if (fgUsedVars[kIsNoTFBorder]) { values[kIsNoTFBorder] = event.selection_bit(o2::aod::evsel::kNoTimeFrameBorder); } + if (fgUsedVars[kIsTriggerZNAZNC]) { + values[kIsTriggerZNAZNC] = event.selection_bit(o2::aod::evsel::kIsBBZNA) && event.selection_bit(o2::aod::evsel::kIsBBZNC); + } if (fgUsedVars[kIsNoSameBunch]) { values[kIsNoSameBunch] = event.selection_bit(o2::aod::evsel::kNoSameBunchPileup); } @@ -1884,6 +2073,9 @@ void VarManager::FillEvent(T const& event, float* values) if (fgUsedVars[kIsNoITSROFBorder]) { values[kIsNoITSROFBorder] = (event.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) > 0); } + if (fgUsedVars[kIsTVXTriggered]) { + values[kIsTVXTriggered] = (event.selection_bit(o2::aod::evsel::kIsTriggerTVX) > 0); + } if (fgUsedVars[kIsNoTFBorder]) { values[kIsNoTFBorder] = (event.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) > 0); } @@ -2136,6 +2328,9 @@ void VarManager::FillEvent(T const& event, float* values) values[kMCEventWeight] = event.weight(); values[kMCEventImpParam] = event.impactParameter(); values[kMCEventCentrFT0C] = event.centFT0C(); + values[kMultMCNParticlesEta05] = event.multMCNParticlesEta05(); + values[kMultMCNParticlesEta08] = event.multMCNParticlesEta08(); + values[kMultMCNParticlesEta10] = event.multMCNParticlesEta10(); } if constexpr ((fillMap & EventFilter) > 0 || (fillMap & RapidityGapFilter) > 0) { @@ -2180,9 +2375,175 @@ void VarManager::FillEvent(T const& event, float* values) values[kBGFDDCpf] = event.bgFDDCpf(); } + // check if the template T type includes the O2remerge table and if so, fill the corresponding variables + if constexpr (requires { event.dcazBimodalityCoefficient(); }) { + values[kDCAzBimodalityCoefficient] = event.dcazBimodalityCoefficient(); + values[kDCAzBimodalityCoefficientBinned] = event.dcazBimodalityCoefficientBinned(); + values[kDCAzBimodalityCoefficientBinnedTrimmed1] = event.dcazBimodalityCoefficientBinnedTrimmed1(); + values[kDCAzBimodalityCoefficientBinnedTrimmed2] = event.dcazBimodalityCoefficientBinnedTrimmed2(); + values[kDCAzBimodalityCoefficientBinnedTrimmed3] = event.dcazBimodalityCoefficientBinnedTrimmed3(); + values[kDCAzMean] = event.dcazMean(); + values[kDCAzMeanBinnedTrimmed1] = event.dcazMeanBinnedTrimmed1(); + values[kDCAzMeanBinnedTrimmed2] = event.dcazMeanBinnedTrimmed2(); + values[kDCAzMeanBinnedTrimmed3] = event.dcazMeanBinnedTrimmed3(); + values[kDCAzRMS] = event.dcazRMS(); + values[kDCAzRMSBinnedTrimmed1] = event.dcazRMSBinnedTrimmed1(); + values[kDCAzRMSBinnedTrimmed2] = event.dcazRMSBinnedTrimmed2(); + values[kDCAzRMSBinnedTrimmed3] = event.dcazRMSBinnedTrimmed3(); + values[kDCAzSkewness] = event.dcazSkewness(); + values[kDCAzKurtosis] = event.dcazKurtosis(); + values[kDCAzNPeaks] = event.dcazNPeaks(); + values[kDCAzNPeaksTrimmed1] = event.dcazNPeaksTrimmed1(); + values[kDCAzNPeaksTrimmed2] = event.dcazNPeaksTrimmed2(); + values[kDCAzNPeaksTrimmed3] = event.dcazNPeaksTrimmed3(); + values[kDCAzFracAbove100um] = event.dcazFracAbove100um(); + values[kDCAzFracAbove200um] = event.dcazFracAbove200um(); + values[kDCAzFracAbove500um] = event.dcazFracAbove500um(); + values[kDCAzFracAbove1mm] = event.dcazFracAbove1mm(); + values[kDCAzFracAbove2mm] = event.dcazFracAbove2mm(); + values[kDCAzFracAbove5mm] = event.dcazFracAbove5mm(); + values[kDCAzFracAbove10mm] = event.dcazFracAbove10mm(); + } + // FillEventDerived(values); } +template +void VarManager::FillEventTracks(T const& tracks, float* values) +{ + if (!values) { + values = fgValues; + } + + // compute event properties based on DCAz of the tracks + std::vector dcazValues; + for (const auto& track : tracks) { + if (!track.hasITS()) { + continue; // skip tracks without ITS information + } + if (!track.hasTPC()) { + continue; // skip tracks without TPC information + } + if (track.dcaZ() > 998) { + continue; // skip tracks without valid DCAz + } + dcazValues.push_back(track.dcaZ()); + } + + if (dcazValues.empty()) { + return; + } + + // compute the unbinned bimodality coefficient and related statistics + auto [bimodalityCoefficient, mean, stddev, skewness, kurtosis, nPeaks] = BimodalityCoefficientAndNPeaks(dcazValues, -1.0); + if (stddev > -1.0) { + values[kDCAzBimodalityCoefficient] = bimodalityCoefficient; + values[kDCAzMean] = mean; + values[kDCAzRMS] = stddev; + values[kDCAzSkewness] = skewness; + values[kDCAzKurtosis] = kurtosis; + values[kDCAzNPeaks] = nPeaks; + } else { + values[kDCAzBimodalityCoefficient] = -9999.0; + values[kDCAzMean] = -9999.0; + values[kDCAzRMS] = -9999.0; + values[kDCAzSkewness] = -9999.0; + values[kDCAzKurtosis] = -9999.0; + values[kDCAzNPeaks] = -9999.0; + } + // compute the binned bimodality coefficient and related statistics with a bin width of 50um + auto [bimodalityCoefficientBin, meanBin, stddevBin, skewnessBin, kurtosisBin, nPeaksBin] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005); + if (stddevBin > -1.0) { + values[kDCAzBimodalityCoefficientBinned] = bimodalityCoefficientBin; + } else { + values[kDCAzBimodalityCoefficientBinned] = -9999.0; + } + values[kDCAzNPeaks] = nPeaksBin; + // cout << "Bimodality coefficient binned: " << bimodalityCoefficientBin << ", mean: " << mean << ", stddev: " << stddev << ", skewness: " << skewness << ", kurtosis: " << kurtosis << ", nPeaks: " << nPeaksBin << endl; + // compute the binned bimodality coefficient and related statistics with a bin width of 50um and different trimming versions + // more then 3 counts per bin + auto [bimodalityCoefficientBinTrimmed1, meanBinTrimmed1, stddevBinTrimmed1, skewnessBinTrimmed1, kurtosisBinTrimmed1, nPeaksBinTrimmed1] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, 4); + if (stddevBinTrimmed1 > -1.0) { + values[kDCAzBimodalityCoefficientBinnedTrimmed1] = bimodalityCoefficientBinTrimmed1; + values[kDCAzMeanBinnedTrimmed1] = meanBinTrimmed1; + values[kDCAzRMSBinnedTrimmed1] = stddevBinTrimmed1; + } else { + values[kDCAzBimodalityCoefficientBinnedTrimmed1] = -9999.0; + values[kDCAzMeanBinnedTrimmed1] = -9999.0; + values[kDCAzRMSBinnedTrimmed1] = -9999.0; + } + values[kDCAzNPeaksTrimmed1] = nPeaksBinTrimmed1; + // cout << "Bimodality coefficient (trimmed 1): " << bimodalityCoefficientBinTrimmed1 << ", mean: " << meanBinTrimmed1 << ", stddev: " << stddevBinTrimmed1 << ", skewness: " << skewnessBinTrimmed1 << ", kurtosis: " << kurtosisBinTrimmed1 << ", nPeaks: " << nPeaksBinTrimmed1 << endl; + // more than 3% of the entries per peak + auto [bimodalityCoefficientBinTrimmed2, meanBinTrimmed2, stddevBinTrimmed2, skewnessBinTrimmed2, kurtosisBinTrimmed2, nPeaksBinTrimmed2] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, -100); + if (stddevBinTrimmed2 > -1.0) { + values[kDCAzBimodalityCoefficientBinnedTrimmed2] = bimodalityCoefficientBinTrimmed2; + values[kDCAzMeanBinnedTrimmed2] = meanBinTrimmed2; + values[kDCAzRMSBinnedTrimmed2] = stddevBinTrimmed2; + } else { + values[kDCAzBimodalityCoefficientBinnedTrimmed2] = -9999.0; + values[kDCAzMeanBinnedTrimmed2] = -9999.0; + values[kDCAzRMSBinnedTrimmed2] = -9999.0; + } + values[kDCAzNPeaksTrimmed2] = nPeaksBinTrimmed2; + // cout << "Bimodality coefficient (trimmed 2): " << bimodalityCoefficientBinTrimmed2 << ", mean: " << meanBinTrimmed2 << ", stddev: " << stddevBinTrimmed2 << ", skewness: " << skewnessBinTrimmed2 << ", kurtosis: " << kurtosisBinTrimmed2 << ", nPeaks: " << nPeaksBinTrimmed2 << endl; + // more than 5% of the entries per peak + auto [bimodalityCoefficientBinTrimmed3, meanBinTrimmed3, stddevBinTrimmed3, skewnessBinTrimmed3, kurtosisBinTrimmed3, nPeaksBinTrimmed3] = BimodalityCoefficientAndNPeaks(dcazValues, 0.005, -20); + if (stddevBinTrimmed3 > -1.0) { + values[kDCAzBimodalityCoefficientBinnedTrimmed3] = bimodalityCoefficientBinTrimmed3; + values[kDCAzMeanBinnedTrimmed3] = meanBinTrimmed3; + values[kDCAzRMSBinnedTrimmed3] = stddevBinTrimmed3; + } else { + values[kDCAzBimodalityCoefficientBinnedTrimmed3] = -9999.0; + values[kDCAzMeanBinnedTrimmed3] = -9999.0; + values[kDCAzRMSBinnedTrimmed3] = -9999.0; + } + values[kDCAzNPeaksTrimmed3] = nPeaksBinTrimmed3; + // cout << "Bimodality coefficient (trimmed 3): " << bimodalityCoefficientBinTrimmed3 << ", mean: " << meanBinTrimmed3 << ", stddev: " << stddevBinTrimmed3 << ", skewness: " << skewnessBinTrimmed3 << ", kurtosis: " << kurtosisBinTrimmed3 << ", nPeaks: " << nPeaksBinTrimmed3 << endl; + + // compute fraction of tracks with |DCAz| > 100um, 200um, 500um, 1mm, 2mm, 5mm, 10mm + // make a loop over the DCAz values and count how many are above each threshold + int counter100um = 0; + int counter200um = 0; + int counter500um = 0; + int counter1mm = 0; + int counter2mm = 0; + int counter5mm = 0; + int counter10mm = 0; + for (auto& d : dcazValues) { + double absD = std::abs(d); + if (absD > 0.01) { + counter100um++; + if (absD > 0.02) { + counter200um++; + if (absD > 0.05) { + counter500um++; + if (absD > 0.1) { + counter1mm++; + if (absD > 0.2) { + counter2mm++; + if (absD > 0.5) { + counter5mm++; + if (absD > 1.0) { + counter10mm++; + } + } + } + } + } + } + } + } + int totalTracks = static_cast(dcazValues.size()); + values[kDCAzFracAbove100um] = static_cast(counter100um) / totalTracks; + values[kDCAzFracAbove200um] = static_cast(counter200um) / totalTracks; + values[kDCAzFracAbove500um] = static_cast(counter500um) / totalTracks; + values[kDCAzFracAbove1mm] = static_cast(counter1mm) / totalTracks; + values[kDCAzFracAbove2mm] = static_cast(counter2mm) / totalTracks; + values[kDCAzFracAbove5mm] = static_cast(counter5mm) / totalTracks; + values[kDCAzFracAbove10mm] = static_cast(counter10mm) / totalTracks; +} + template void VarManager::FillEventFlowResoFactor(T const& hs_sp, T const& hs_ep, float* values) { @@ -2417,10 +2778,10 @@ void VarManager::FillTrack(T const& track, float* values) if (fgUsedVars[kM11REFoverMpsingle]) { float m = o2::constants::physics::MassMuon; ROOT::Math::PtEtaPhiMVector v(track.pt(), track.eta(), track.phi(), m); - complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); - complex Q42(values[kQ42XA], values[kQ42YA]); - complex Q23(values[kQ23XA], values[kQ23YA]); - complex P2(TMath::Cos(2 * v.Phi()), TMath::Sin(2 * v.Phi())); + std::complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); + std::complex Q42(values[kQ42XA], values[kQ42YA]); + std::complex Q23(values[kQ23XA], values[kQ23YA]); + std::complex P2(TMath::Cos(2 * v.Phi()), TMath::Sin(2 * v.Phi())); values[kM11REFoverMpsingle] = values[kMultSingleMuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kM1111REF]) || std::isinf(values[kM1111REF]) || std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF])) ? values[kM11REF] / values[kMultSingleMuons] : 0; values[kM1111REFoverMpsingle] = values[kMultSingleMuons] > 0 && !(std::isnan(values[kM1111REF]) || std::isinf(values[kM1111REF]) || std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF]) || std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF])) ? values[kM1111REF] / values[kMultSingleMuons] : 0; values[kCORR2REFbysinglemu] = std::isnan(values[kM11REFoverMpsingle]) || std::isinf(values[kM11REFoverMpsingle]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kM1111REFoverMpsingle]) || std::isinf(values[kM1111REFoverMpsingle]) || std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF]) ? 0 : values[kCORR2REF]; @@ -2941,7 +3302,7 @@ void VarManager::FillTrackCollisionMC(T1 const& track, T2 const& MotherTrack, C } template -void VarManager::FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* values) +void VarManager::FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* values, float Translow, float Transhigh) { // energy correlators float MassHadron; @@ -2981,20 +3342,21 @@ void VarManager::FillEnergyCorrelatorsMC(T const& track, T1 const& t1, float* va float randomPhi_toward = -o2::constants::math::PIHalf; float randomPhi_away = -o2::constants::math::PIHalf; - if ((deltaphi > -0.5 * TMath::Pi() && deltaphi < -1. / 3 * TMath::Pi()) || (deltaphi > 4. / 3 * TMath::Pi() && deltaphi < 1.5 * TMath::Pi()) || (deltaphi > 1. / 3 * TMath::Pi() && deltaphi < 2. / 3 * TMath::Pi())) { + float deltaphitrans = RecoDecay::constrainAngle(track.phi() - t1.phi(), -o2::constants::math::PI); + if ((deltaphitrans > -Transhigh * TMath::Pi() && deltaphitrans < -Translow * TMath::Pi()) || (deltaphitrans > Translow * TMath::Pi() && deltaphitrans < Transhigh * TMath::Pi())) { randomPhi_trans = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); randomPhi_toward = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); randomPhi_away = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); - ROOT::Math::PtEtaPhiMVector v2_randomPhi_trans(v2.pt(), v2.eta(), randomPhi_trans, o2::constants::physics::MassPionCharged); + ROOT::Math::PtEtaPhiMVector v2_randomPhi_trans(v2.pt(), v2.eta(), randomPhi_trans, MassHadron); values[kMCCosChi_randomPhi_trans] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_trans); values[kMCWeight_randomPhi_trans] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_trans) / v1.M(); - ROOT::Math::PtEtaPhiMVector v2_randomPhi_toward(v2.pt(), v2.eta(), randomPhi_toward, o2::constants::physics::MassPionCharged); + ROOT::Math::PtEtaPhiMVector v2_randomPhi_toward(v2.pt(), v2.eta(), randomPhi_toward, MassHadron); values[kMCCosChi_randomPhi_toward] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_toward); values[kMCWeight_randomPhi_toward] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_toward) / v1.M(); - ROOT::Math::PtEtaPhiMVector v2_randomPhi_away(v2.pt(), v2.eta(), randomPhi_away, o2::constants::physics::MassPionCharged); + ROOT::Math::PtEtaPhiMVector v2_randomPhi_away(v2.pt(), v2.eta(), randomPhi_away, MassHadron); values[kMCCosChi_randomPhi_away] = LorentzTransformJpsihadroncosChi("coschi", v1, v2_randomPhi_away); values[kMCWeight_randomPhi_away] = LorentzTransformJpsihadroncosChi("weight_boost", v1, v2_randomPhi_away) / v1.M(); @@ -3676,10 +4038,10 @@ void VarManager::FillPairME(T1 const& t1, T2 const& t2, float* values) values[kWV24ME] = (std::isnan(V22ME) || std::isinf(V22ME) || std::isnan(V24ME) || std::isinf(V24ME)) ? 0. : 1.0; if constexpr ((fillMap & ReducedEventQvectorExtra) > 0) { - complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); - complex Q42(values[kQ42XA], values[kQ42YA]); - complex Q23(values[kQ23XA], values[kQ23YA]); - complex P2(TMath::Cos(2 * v12.Phi()), TMath::Sin(2 * v12.Phi())); + std::complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); + std::complex Q42(values[kQ42XA], values[kQ42YA]); + std::complex Q23(values[kQ23XA], values[kQ23YA]); + std::complex P2(TMath::Cos(2 * v12.Phi()), TMath::Sin(2 * v12.Phi())); values[kM01POIME] = values[kMultDimuonsME] * values[kS11A]; values[kM0111POIME] = values[kMultDimuonsME] * (values[kS31A] - 3. * values[kS11A] * values[kS12A] + 2. * values[kS13A]); values[kCORR2POIME] = (P2 * conj(Q21)).real() / values[kM01POIME]; @@ -3747,6 +4109,10 @@ void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values) values[kMCEta] = v12.Eta(); values[kMCPhi] = v12.Phi(); values[kMCY] = -v12.Rapidity(); + values[kMCPt1] = t1.pt(); + values[kMCPt2] = t2.pt(); + values[kMCEta1] = t1.eta(); + values[kMCEta2] = t2.eta(); // polarization parameters bool useHE = fgUsedVars[kMCCosThetaHE] || fgUsedVars[kMCPhiHE]; // helicity frame @@ -4028,6 +4394,7 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, } Vec3D secondaryVertex; + o2::dataformats::VertexBase primaryVertexNew; if constexpr (eventHasVtxCov) { @@ -4042,6 +4409,7 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, if constexpr ((pairType == kDecayToEE || pairType == kDecayToKPi) && trackHasCov) { secondaryVertex = fgFitterTwoProngBarrel.getPCACandidate(); + // printf("secVtx (first) %f %f %f \n",secondaryVertex[0],secondaryVertex[1],secondaryVertex[2]); covMatrixPCA = fgFitterTwoProngBarrel.calcPCACovMatrixFlat(); auto chi2PCA = fgFitterTwoProngBarrel.getChi2AtPCACandidate(); auto trackParVar0 = fgFitterTwoProngBarrel.getTrack(0); @@ -4050,6 +4418,8 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, v1 = {trackParVar0.getPt(), trackParVar0.getEta(), trackParVar0.getPhi(), m1}; v2 = {trackParVar1.getPt(), trackParVar1.getEta(), trackParVar1.getPhi(), m2}; v12 = v1 + v2; + if (fgPVrecalKF) + primaryVertexNew = RecalculatePrimaryVertex(t1, t2, collision); } else if constexpr (pairType == kDecayToMuMu && muonHasCov) { // Get pca candidate from forward DCA fitter @@ -4107,9 +4477,15 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, values[kVertexingLxyProjected] = values[kVertexingLxyProjected] / TMath::Sqrt((v12.Px() * v12.Px()) + (v12.Py() * v12.Py())); values[kVertexingLxyzProjected] = ((secondaryVertex[0] - collision.posX()) * v12.Px()) + ((secondaryVertex[1] - collision.posY()) * v12.Py()) + ((secondaryVertex[2] - collision.posZ()) * v12.Pz()); values[kVertexingLxyzProjected] = values[kVertexingLxyzProjected] / TMath::Sqrt((v12.Px() * v12.Px()) + (v12.Py() * v12.Py()) + (v12.Pz() * v12.Pz())); + if (fgPVrecalKF) { + values[kVertexingLxyProjectedRecalculatePV] = (secondaryVertex[0] - primaryVertexNew.getX()) * v12.Px() + (secondaryVertex[1] - primaryVertexNew.getY()) * v12.Py(); + values[kVertexingLxyProjectedRecalculatePV] = values[kVertexingLxyProjectedRecalculatePV] / v12.Pt(); + } values[kVertexingTauxyProjected] = values[kVertexingLxyProjected] * v12.M() / (v12.Pt()); values[kVertexingTauxyProjectedPoleJPsiMass] = values[kVertexingLxyProjected] * o2::constants::physics::MassJPsi / (v12.Pt()); values[kVertexingTauxyProjectedNs] = values[kVertexingTauxyProjected] / o2::constants::physics::LightSpeedCm2NS; + if (fgPVrecalKF) + values[kVertexingTauxyProjectedPoleJPsiMassRecalculatePV] = values[kVertexingLxyProjectedRecalculatePV] * o2::constants::physics::MassJPsi / (v12.Pt()); values[kVertexingTauzProjected] = values[kVertexingLzProjected] * v12.M() / TMath::Abs(v12.Pz()); values[kVertexingTauxyzProjected] = values[kVertexingLxyzProjected] * v12.M() / (v12.P()); } @@ -4327,6 +4703,69 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, } } +template +void VarManager::FillPairVertexingRecomputePV(C const& /*collision*/, T const& t1, T const& t2, o2::dataformats::VertexBase pvRefitted, float* values) +{ + // recompute decay lenght variables using updated primary vertex + + // check at compile time that the event and cov matrix have the cov matrix + constexpr bool eventHasVtxCov = ((collFillMap & Collision) > 0 || (collFillMap & ReducedEventVtxCov) > 0); + constexpr bool trackHasCov = ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0); + constexpr bool muonHasCov = ((fillMap & MuonCov) > 0 || (fillMap & ReducedMuonCov) > 0); + + if (!values) { + values = fgValues; + } + + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + if constexpr (pairType == kDecayToKPi) { + m1 = o2::constants::physics::MassKaonCharged; + m2 = o2::constants::physics::MassPionCharged; + } + if constexpr (pairType == kDecayToMuMu && muonHasCov) { + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; + } + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), m2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + if (fgFitterTwoProngBarrel.getNCandidates() == 0) + return; + Vec3D secondaryVertex; + + if (!fgUsedKF) { // to be updated when seconday vertex is computed with KF + if constexpr (eventHasVtxCov) { + + if constexpr ((pairType == kDecayToEE || pairType == kDecayToKPi) && trackHasCov) { + // Get pca candidate from forward DCA fitter + // no need to re-compute secondary vertex (done already in FillPairVertexing) + secondaryVertex = fgFitterTwoProngBarrel.getPCACandidate(); + auto trackParVar0 = fgFitterTwoProngBarrel.getTrack(0); + auto trackParVar1 = fgFitterTwoProngBarrel.getTrack(1); + v1 = {trackParVar0.getPt(), trackParVar0.getEta(), trackParVar0.getPhi(), m1}; + v2 = {trackParVar1.getPt(), trackParVar1.getEta(), trackParVar1.getPhi(), m2}; + v12 = v1 + v2; + + } else if constexpr (pairType == kDecayToMuMu && muonHasCov) { + // Get pca candidate from forward DCA fitter + // no need to re-compute secondary vertex (done already in FillPairVertexing) + secondaryVertex = fgFitterTwoProngFwd.getPCACandidate(); + auto trackParVar0 = fgFitterTwoProngFwd.getTrack(0); + auto trackParVar1 = fgFitterTwoProngFwd.getTrack(1); + v1 = {trackParVar0.getPt(), trackParVar0.getEta(), trackParVar0.getPhi(), m1}; + v2 = {trackParVar1.getPt(), trackParVar1.getEta(), trackParVar1.getPhi(), m2}; + v12 = v1 + v2; + } + + values[kVertexingLxyProjectedRecalculatePV] = (secondaryVertex[0] - pvRefitted.getX()) * v12.Px() + (secondaryVertex[1] - pvRefitted.getY()) * v12.Py(); + values[kVertexingLxyProjectedRecalculatePV] = values[kVertexingLxyProjectedRecalculatePV] / v12.Pt(); + values[kVertexingTauxyProjectedPoleJPsiMassRecalculatePV] = values[kVertexingLxyProjectedRecalculatePV] * o2::constants::physics::MassJPsi / (v12.Pt()); + } + } +} + template void VarManager::FillTripletVertexing(C const& collision, T const& t1, T const& t2, T const& t3, VarManager::PairCandidateType tripletType, float* values) { @@ -4885,9 +5324,9 @@ void VarManager::FillQVectorFromGFW(C const& /*collision*/, A const& compA11, A values[kM11M1111REF] = values[kM11REF] * values[kM1111REF]; // For cumulants: A = Full TPC, B = Negative TPC, C = Positive TPC - complex QA(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); - complex QB(values[kQ2X0B] * S11B, values[kQ2Y0B] * S11B); - complex QC(values[kQ2X0C] * S11C, values[kQ2Y0C] * S11C); + std::complex QA(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); + std::complex QB(values[kQ2X0B] * S11B, values[kQ2Y0B] * S11B); + std::complex QC(values[kQ2X0C] * S11C, values[kQ2Y0C] * S11C); values[kM11REFetagap] = S11B * S11C; values[kCORR2REFetagap] = ((QB * conj(QC)).real()) / values[kM11REFetagap]; values[kCORR2REFetagap] = std::isnan(values[kM11REFetagap]) || std::isinf(values[kM11REFetagap]) || std::isnan(values[kCORR2REFetagap]) || std::isinf(values[kCORR2REFetagap]) ? 0 : values[kCORR2REFetagap]; @@ -5223,10 +5662,10 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) // kV4, kC4POI, kC4REF etc. if constexpr ((fillMap & ReducedEventQvectorExtra) > 0) { - complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); - complex Q42(values[kQ42XA], values[kQ42YA]); - complex Q23(values[kQ23XA], values[kQ23YA]); - complex P2(TMath::Cos(2 * v12.Phi()), TMath::Sin(2 * v12.Phi())); + std::complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); + std::complex Q42(values[kQ42XA], values[kQ42YA]); + std::complex Q23(values[kQ23XA], values[kQ23YA]); + std::complex P2(TMath::Cos(2 * v12.Phi()), TMath::Sin(2 * v12.Phi())); values[kM01POI] = values[kMultDimuons] * values[kS11A]; values[kM0111POI] = values[kMultDimuons] * (values[kS31A] - 3. * values[kS11A] * values[kS12A] + 2. * values[kS13A]); values[kCORR2POI] = (P2 * conj(Q21)).real() / values[kM01POI]; @@ -5248,8 +5687,8 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values[kM11M0111overMp] = values[kMultDimuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kM0111POI]) || std::isinf(values[kM0111POI]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kCORR4POI]) || std::isinf(values[kCORR4POI])) ? (values[kM11REF] * values[kM0111POI]) / values[kMultDimuons] : 0; values[kM11M01overMp] = values[kMultDimuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kM01POI]) || std::isinf(values[kM01POI]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kCORR2POI]) || std::isinf(values[kCORR2POI])) ? (values[kM11REF] * values[kM01POI]) / values[kMultDimuons] : 0; - complex P2plus(TMath::Cos(2 * v1.Phi()), TMath::Sin(2 * v1.Phi())); - complex P2minus(TMath::Cos(2 * v2.Phi()), TMath::Sin(2 * v2.Phi())); + std::complex P2plus(TMath::Cos(2 * v1.Phi()), TMath::Sin(2 * v1.Phi())); + std::complex P2minus(TMath::Cos(2 * v2.Phi()), TMath::Sin(2 * v2.Phi())); values[kM11REFoverMpplus] = values[kMultAntiMuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kM1111REF]) || std::isinf(values[kM1111REF]) || std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF])) ? values[kM11REF] / values[kMultAntiMuons] : 0; values[kM1111REFoverMpplus] = values[kMultAntiMuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kM1111REF]) || std::isinf(values[kM1111REF]) || std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF])) ? values[kM1111REF] / values[kMultAntiMuons] : 0; values[kM11REFoverMpminus] = values[kMultMuons] > 0 && !(std::isnan(values[kM11REF]) || std::isinf(values[kM11REF]) || std::isnan(values[kCORR2REF]) || std::isinf(values[kCORR2REF]) || std::isnan(values[kM1111REF]) || std::isinf(values[kM1111REF]) || std::isnan(values[kCORR4REF]) || std::isinf(values[kCORR4REF])) ? values[kM11REF] / values[kMultMuons] : 0; @@ -5355,9 +5794,16 @@ void VarManager::FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* } } -template -void VarManager::FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, float* values, bool applyFitMass, float sidebandMass) +template +void VarManager::FillEnergyCorrelatorTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, float* values, float Translow, float Transhigh, bool applyFitMass, float sidebandMass) { + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + + ROOT::Math::PtEtaPhiMVector v_lepton1(lepton1.pt(), lepton1.eta(), lepton1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v_lepton2(lepton2.pt(), lepton2.eta(), lepton2.phi(), m2); + ROOT::Math::PtEtaPhiMVector dilepton = v_lepton1 + v_lepton2; + float dileptonmass = o2::constants::physics::MassJPsi; if (applyFitMass) { dileptonmass = dilepton.mass(); @@ -5379,7 +5825,9 @@ void VarManager::FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, floa values[kEtaDau] = v2.eta(); values[kPhiDau] = RecoDecay::constrainAngle(v2.phi(), -o2::constants::math::PIHalf); - float deltaphi = RecoDecay::constrainAngle(v1.phi() - v2.phi(), -o2::constants::math::PIHalf); + float deltaphi = RecoDecay::constrainAngle(v1.phi() - v2.phi(), -o2::constants::math::PI); + values[kDeltaPhi] = RecoDecay::constrainAngle(v1.phi() - v2.phi(), -o2::constants::math::PIHalf); + values[kDeltaEta] = v1.eta() - v2.eta(); values[kCosChi_randomPhi_trans] = -999.9f; values[kCosChi_randomPhi_toward] = -999.9f; values[kCosChi_randomPhi_away] = -999.9f; @@ -5392,7 +5840,7 @@ void VarManager::FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, floa float randomPhi_toward = -o2::constants::math::PIHalf; float randomPhi_away = -o2::constants::math::PIHalf; - if ((deltaphi > -0.5 * TMath::Pi() && deltaphi < -1. / 3 * TMath::Pi()) || (deltaphi > 4. / 3 * TMath::Pi() && deltaphi < 1.5 * TMath::Pi()) || (deltaphi > 1. / 3 * TMath::Pi() && deltaphi < 2. / 3 * TMath::Pi())) { + if ((deltaphi > -Transhigh * TMath::Pi() && deltaphi < -Translow * TMath::Pi()) || (deltaphi > Translow * TMath::Pi() && deltaphi < Transhigh * TMath::Pi())) { randomPhi_trans = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); randomPhi_toward = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); randomPhi_away = gRandom->Uniform(-o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf); @@ -5415,6 +5863,49 @@ void VarManager::FillEnergyCorrelator(T1 const& dilepton, T2 const& hadron, floa } } } + +template +void VarManager::FillEnergyCorrelatorsUnfoldingTriple(T1 const& lepton1, T2 const& lepton2, T3 const& hadron, T4 const& track, T5 const& t1, float* values, bool applyFitMass) +{ + if (fgUsedVars[kMCCosChi_gen] || fgUsedVars[kMCWeight_gen] || fgUsedVars[kMCdeltaeta_gen] || fgUsedVars[kMCCosChi_rec] || fgUsedVars[kMCWeight_rec] || fgUsedVars[kMCdeltaeta_rec]) { + // energy correlators + + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + + ROOT::Math::PtEtaPhiMVector v_lepton1(lepton1.pt(), lepton1.eta(), lepton1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v_lepton2(lepton2.pt(), lepton2.eta(), lepton2.phi(), m2); + ROOT::Math::PtEtaPhiMVector dilepton = v_lepton1 + v_lepton2; + + float dileptonmass = o2::constants::physics::MassJPsi; + if (applyFitMass) { + dileptonmass = dilepton.mass(); + } + + float MassHadron; + if constexpr (pairType == kJpsiHadronMass) { + MassHadron = TMath::Sqrt(t1.e() * t1.e() - t1.p() * t1.p()); + } + if constexpr (pairType == kJpsiPionMass) { + MassHadron = o2::constants::physics::MassPionCharged; + } + ROOT::Math::PtEtaPhiMVector v1_gen(track.pt(), track.eta(), track.phi(), o2::constants::physics::MassJPsi); + ROOT::Math::PtEtaPhiMVector v2_gen(t1.pt(), t1.eta(), t1.phi(), MassHadron); + float E_boost_gen = LorentzTransformJpsihadroncosChi("weight_boost", v1_gen, v2_gen); + float CosChi_gen = LorentzTransformJpsihadroncosChi("coschi", v1_gen, v2_gen); + values[kMCCosChi_gen] = CosChi_gen; + values[kMCWeight_gen] = E_boost_gen / o2::constants::physics::MassJPsi; + values[kMCdeltaeta_gen] = track.eta() - t1.eta(); + + ROOT::Math::PtEtaPhiMVector v1_rec(dilepton.pt(), dilepton.eta(), dilepton.phi(), dileptonmass); + ROOT::Math::PtEtaPhiMVector v2_rec(hadron.pt(), hadron.eta(), hadron.phi(), o2::constants::physics::MassPionCharged); + values[kMCCosChi_rec] = LorentzTransformJpsihadroncosChi("coschi", v1_rec, v2_rec); + float E_boost_rec = LorentzTransformJpsihadroncosChi("weight_boost", v1_rec, v2_rec); + values[kMCWeight_rec] = E_boost_rec / v1_rec.M(); + values[kMCdeltaeta_rec] = dilepton.eta() - hadron.eta(); + } +} + template void VarManager::FillDileptonPhoton(T1 const& dilepton, T2 const& photon, float* values) { @@ -6055,4 +6546,495 @@ void VarManager::FillFIT(T1 const& bc, T2 const& bcs, T3 const& ft0s, T4 const& values[kBBFDDCpf] = static_cast(fitInfo.BBFDDCpf); values[kBGFDDCpf] = static_cast(fitInfo.BGFDDCpf); } + +template +void VarManager::FillEventAlice3(T const& event, float* values) +{ + if (!values) { + values = fgValues; + } + if constexpr ((fillMap & CollisionTimestamp) > 0) { + values[kTimestamp] = event.timestamp(); + } + + if constexpr ((fillMap & Collision) > 0) { + values[kVtxX] = event.posX(); + values[kVtxY] = event.posY(); + values[kVtxZ] = event.posZ(); + values[kVtxNcontrib] = event.numContrib(); + values[kVtxCovXX] = event.covXX(); + values[kVtxCovXY] = event.covXY(); + values[kVtxCovXZ] = event.covXZ(); + values[kVtxCovYY] = event.covYY(); + values[kVtxCovYZ] = event.covYZ(); + values[kVtxCovZZ] = event.covZZ(); + values[kVtxChi2] = event.chi2(); + values[kCollisionTime] = event.collisionTime(); + values[kCollisionTimeRes] = event.collisionTimeRes(); + } + + if constexpr ((fillMap & ReducedEvent) > 0) { + values[kRunNo] = -1; + values[kVtxX] = event.posX(); + values[kVtxY] = event.posY(); + values[kVtxZ] = event.posZ(); + values[kVtxNcontrib] = event.numContrib(); + values[kCollisionTime] = event.collisionTime(); + values[kCollisionTimeRes] = event.collisionTimeRes(); + } + if constexpr ((fillMap & ReducedEventVtxCov) > 0) { + values[kVtxCovXX] = event.covXX(); + values[kVtxCovXY] = event.covXY(); + values[kVtxCovXZ] = event.covXZ(); + values[kVtxCovYY] = event.covYY(); + values[kVtxCovYZ] = event.covYZ(); + values[kVtxCovZZ] = event.covZZ(); + values[kVtxChi2] = event.chi2(); + } + + 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(); + values[kMCEventTime] = event.t(); + values[kMCEventWeight] = event.weight(); + values[kMCEventImpParam] = event.impactParameter(); + } + + 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(); + values[kMCEventTime] = event.t(); + values[kMCEventWeight] = event.weight(); + values[kMCEventImpParam] = event.impactParameter(); + } +} + +template +void VarManager::FillTrackAlice3(T const& track, float* values) +{ + if (!values) { + values = fgValues; + } + + if constexpr ((fillMap & Track) > 0 || (fillMap & ReducedTrack) > 0) { + values[kPt] = track.pt(); + values[kSignedPt] = track.pt() * track.sign(); + if (fgUsedVars[kP]) { + values[kP] = track.p(); + } + if (fgUsedVars[kPx]) { + values[kPx] = track.px(); + } + if (fgUsedVars[kPy]) { + values[kPy] = track.py(); + } + if (fgUsedVars[kPz]) { + values[kPz] = track.pz(); + } + if (fgUsedVars[kInvPt]) { + values[kInvPt] = 1. / track.pt(); + } + values[kEta] = track.eta(); + values[kPhi] = track.phi(); + values[kCharge] = track.sign(); + + if (fgUsedVars[kPVContributor]) { + values[kPVContributor] = (track.flags() & o2::aod::track::PVContributor) > 0; + } + + if (fgUsedVars[kITSClusterMap]) { + values[kITSClusterMap] = track.itsClusterMap(); + } + + values[kIsReconstructed] = track.isReconstructed(); + values[kNSiliconHits] = track.nSiliconHits(); + values[kITSchi2] = track.itsChi2NCl(); + } + + // Quantities based on the barrel tables + if constexpr ((fillMap & TrackExtra) > 0 || (fillMap & ReducedTrackBarrel) > 0) { + + values[kTrackLength] = track.length(); + + if constexpr ((fillMap & ReducedTrackBarrel) > 0) { + values[kTrackDCAxy] = track.dcaXY(); + values[kTrackDCAz] = track.dcaZ(); + if constexpr ((fillMap & ReducedTrackBarrelCov) > 0) { + if (fgUsedVars[kTrackDCAsigXY]) { + values[kTrackDCAsigXY] = track.dcaXY() / std::sqrt(track.cYY()); + } + if (fgUsedVars[kTrackDCAsigZ]) { + values[kTrackDCAsigZ] = track.dcaZ() / std::sqrt(track.cZZ()); + } + if (fgUsedVars[kTrackDCAresXY]) { + values[kTrackDCAresXY] = std::sqrt(track.cYY()); + } + if (fgUsedVars[kTrackDCAresZ]) { + values[kTrackDCAresZ] = std::sqrt(track.cZZ()); + } + } + } + } + + // Quantities based on the barrel track selection table + if constexpr ((fillMap & TrackDCA) > 0) { + values[kTrackDCAxy] = track.dcaXY(); + values[kTrackDCAz] = track.dcaZ(); + if constexpr ((fillMap & TrackCov) > 0) { + if (fgUsedVars[kTrackDCAsigXY]) { + values[kTrackDCAsigXY] = track.dcaXY() / std::sqrt(track.cYY()); + } + if (fgUsedVars[kTrackDCAsigZ]) { + values[kTrackDCAsigZ] = track.dcaZ() / std::sqrt(track.cZZ()); + } + if (fgUsedVars[kTrackDCAresXY]) { + values[kTrackDCAresXY] = std::sqrt(track.cYY()); + } + if (fgUsedVars[kTrackDCAresZ]) { + values[kTrackDCAresZ] = std::sqrt(track.cZZ()); + } + } + } + + // Quantities based on the barrel covariance tables + if constexpr ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0) { + values[kTrackCYY] = track.cYY(); + values[kTrackCZZ] = track.cZZ(); + values[kTrackCSnpSnp] = track.cSnpSnp(); + values[kTrackCTglTgl] = track.cTglTgl(); + values[kTrackC1Pt21Pt2] = track.c1Pt21Pt2(); + } + + if constexpr ((fillMap & TrackPID) > 0 || (fillMap & ReducedTrackBarrelPID) > 0) { + + values[kHasRICHSig] = track.hasSig(); + values[kHasRICHSigInGas] = track.hasSigInGas(); + values[kHasRICHSigEl] = track.hasSigEl(); + values[kHasRICHSigMu] = track.hasSigMu(); + values[kHasRICHSigPi] = track.hasSigPi(); + values[kHasRICHSigKa] = track.hasSigKa(); + values[kHasRICHSigPr] = track.hasSigPr(); + values[kHasRICHSigDe] = track.hasSigDe(); + values[kHasRICHSigTr] = track.hasSigTr(); + values[kHasRICHSigHe3] = track.hasSigHe3(); + values[kHasRICHSigAl] = track.hasSigAl(); + values[kRICHnSigmaEl] = track.nSigmaElectronRich(); + values[kRICHnSigmaMu] = track.nSigmaMuonRich(); + values[kRICHnSigmaPi] = track.nSigmaPionRich(); + values[kRICHnSigmaKa] = track.nSigmaKaonRich(); + values[kRICHnSigmaPr] = track.nSigmaProtonRich(); + values[kRICHnSigmaDe] = track.nSigmaDeuteronRich(); + values[kRICHnSigmaTr] = track.nSigmaTritonRich(); + values[kRICHnSigmaHe3] = track.nSigmaHelium3Rich(); + values[kRICHnSigmaAl] = track.nSigmaAlphaRich(); + values[kTOFEventTime] = track.tofEventTime(); + values[kTOFEventTimeErr] = track.tofEventTimeErr(); + values[kiTOFBeta] = track.innerTOFTrackLengthReco() / (track.innerTOFTrackTimeReco() - track.tofEventTime()) * o2::constants::physics::invLightSpeedCm2PS; + values[koTOFBeta] = track.outerTOFTrackLengthReco() / (track.outerTOFTrackTimeReco() - track.tofEventTime()) * o2::constants::physics::invLightSpeedCm2PS; + values[kOuterTOFnSigmaEl] = track.nSigmaElectronOuterTOF(); + values[kOuterTOFnSigmaMu] = track.nSigmaMuonOuterTOF(); + values[kOuterTOFnSigmaPi] = track.nSigmaPionOuterTOF(); + values[kOuterTOFnSigmaKa] = track.nSigmaKaonOuterTOF(); + values[kOuterTOFnSigmaPr] = track.nSigmaProtonOuterTOF(); + values[kOuterTOFnSigmaDe] = track.nSigmaDeuteronOuterTOF(); + values[kOuterTOFnSigmaTr] = track.nSigmaTritonOuterTOF(); + values[kOuterTOFnSigmaHe3] = track.nSigmaHelium3OuterTOF(); + values[kOuterTOFnSigmaAl] = track.nSigmaAlphaOuterTOF(); + values[kInnerTOFnSigmaEl] = track.nSigmaElectronInnerTOF(); + values[kInnerTOFnSigmaMu] = track.nSigmaMuonInnerTOF(); + values[kInnerTOFnSigmaPi] = track.nSigmaPionInnerTOF(); + values[kInnerTOFnSigmaKa] = track.nSigmaKaonInnerTOF(); + values[kInnerTOFnSigmaPr] = track.nSigmaProtonInnerTOF(); + values[kInnerTOFnSigmaDe] = track.nSigmaDeuteronInnerTOF(); + values[kInnerTOFnSigmaTr] = track.nSigmaTritonInnerTOF(); + values[kInnerTOFnSigmaHe3] = track.nSigmaHelium3InnerTOF(); + values[kInnerTOFnSigmaAl] = track.nSigmaAlphaInnerTOF(); + } + + // Quantities based on the pair table(s) + if constexpr ((fillMap & Pair) > 0) { + values[kMass] = track.mass(); + ROOT::Math::PtEtaPhiMVector vpair(track.pt(), track.eta(), track.phi(), track.mass()); + values[kRap] = vpair.Rapidity(); + } + + // Derived quantities which can be computed based on already filled variables + FillTrackDerived(values); +} + +template +void VarManager::FillPairAlice3(T1 const& t1, T2 const& t2, float* values) +{ + if (!values) { + values = fgValues; + } + + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + if constexpr (pairType == kDecayToMuMu) { + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; + } + + if constexpr (pairType == kDecayToPiPi) { + m1 = o2::constants::physics::MassPionCharged; + m2 = o2::constants::physics::MassPionCharged; + } + + if constexpr (pairType == kDecayToKPi) { + m1 = o2::constants::physics::MassKaonCharged; + m2 = o2::constants::physics::MassPionCharged; + } + + if constexpr (pairType == kElectronMuon) { + m2 = o2::constants::physics::MassMuon; + } + + values[kCharge] = t1.sign() + t2.sign(); + values[kCharge1] = t1.sign(); + values[kCharge2] = t2.sign(); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), m2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + values[kMass] = v12.M(); + values[kPt] = v12.Pt(); + values[kEta] = v12.Eta(); + // 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; + + values[kPt1] = t1.pt(); + values[kEta1] = t1.eta(); + values[kPhi1] = t1.phi(); + values[kPt2] = t2.pt(); + values[kEta2] = t2.eta(); + values[kPhi2] = t2.phi(); + + 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[kDeltaEtaPair2]) { + values[kDeltaEtaPair2] = v1.Eta() - v2.Eta(); + } + + 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()); + values[kPsiPair] = (t1.sign() * fgMagField > 0.) ? TMath::ASin((v1.Theta() - v2.Theta()) / xipair) : TMath::ASin((v2.Theta() - v1.Theta()) / xipair); + } + + if (fgUsedVars[kOpeningAngle]) { + double scalar = v1.Px() * v2.Px() + v1.Py() * v2.Py() + v1.Pz() * v2.Pz(); + double Ptot12 = Ptot1 * Ptot2; + if (Ptot12 <= 0) { + values[kOpeningAngle] = 0.; + } else { + double arg = scalar / Ptot12; + if (arg > 1.) + arg = 1.; + if (arg < -1) + arg = -1; + values[kOpeningAngle] = TMath::ACos(arg); + } + } + + // polarization parameters + bool useHE = fgUsedVars[kCosThetaHE] || fgUsedVars[kPhiHE]; // helicity frame + bool useCS = fgUsedVars[kCosThetaCS] || fgUsedVars[kPhiCS]; // Collins-Soper frame + bool usePP = fgUsedVars[kCosThetaPP]; // production plane frame + bool useRM = fgUsedVars[kCosThetaRM]; // Random frame + + if (useHE || useCS || usePP || useRM) { + 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(fgBeamA).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam2_CM{(boostv12(fgBeamC).Vect()).Unit()}; + + // using positive sign convention for the first track + ROOT::Math::XYZVectorF v_CM = (t1.sign() > 0 ? v1_CM : v2_CM); + + if (useHE) { + ROOT::Math::XYZVectorF zaxis_HE{(v12.Vect()).Unit()}; + ROOT::Math::XYZVectorF yaxis_HE{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_HE{(yaxis_HE.Cross(zaxis_HE)).Unit()}; + if (fgUsedVars[kCosThetaHE]) + values[kCosThetaHE] = zaxis_HE.Dot(v_CM); + if (fgUsedVars[kPhiHE]) { + values[kPhiHE] = TMath::ATan2(yaxis_HE.Dot(v_CM), xaxis_HE.Dot(v_CM)); + if (values[kPhiHE] < 0) { + values[kPhiHE] += 2 * TMath::Pi(); // ensure phi is in [0, 2pi] + } + } + if (fgUsedVars[kPhiTildeHE]) { + if (fgUsedVars[kCosThetaHE] && fgUsedVars[kPhiHE]) { + if (values[kCosThetaHE] > 0) { + values[kPhiTildeHE] = values[kPhiHE] - 0.25 * TMath::Pi(); // phi_tilde = phi - pi/4 + if (values[kPhiTildeHE] < 0) { + values[kPhiTildeHE] += 2 * TMath::Pi(); // ensure phi_tilde is in [0, 2pi] + } + } else { + values[kPhiTildeHE] = values[kPhiHE] - 0.75 * TMath::Pi(); // phi_tilde = phi - 3pi/4 + if (values[kPhiTildeHE] < 0) { + values[kPhiTildeHE] += 2 * TMath::Pi(); // ensure phi_tilde is in [0, 2pi] + } + } + } else { + values[kPhiTildeHE] = -999; // not computable + } + } + } + + if (useCS) { + ROOT::Math::XYZVectorF zaxis_CS{(Beam1_CM - Beam2_CM).Unit()}; + ROOT::Math::XYZVectorF yaxis_CS{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_CS{(yaxis_CS.Cross(zaxis_CS)).Unit()}; + if (fgUsedVars[kCosThetaCS]) + values[kCosThetaCS] = zaxis_CS.Dot(v_CM); + if (fgUsedVars[kPhiCS]) { + values[kPhiCS] = TMath::ATan2(yaxis_CS.Dot(v_CM), xaxis_CS.Dot(v_CM)); + if (values[kPhiCS] < 0) { + values[kPhiCS] += 2 * TMath::Pi(); // ensure phi is in [0, 2pi] + } + } + if (fgUsedVars[kPhiTildeCS]) { + if (fgUsedVars[kCosThetaCS] && fgUsedVars[kPhiCS]) { + if (values[kCosThetaCS] > 0) { + values[kPhiTildeCS] = values[kPhiCS] - 0.25 * TMath::Pi(); // phi_tilde = phi - pi/4 + if (values[kPhiTildeCS] < 0) { + values[kPhiTildeCS] += 2 * TMath::Pi(); // ensure phi_tilde is in [0, 2pi] + } + } else { + values[kPhiTildeCS] = values[kPhiCS] - 0.75 * TMath::Pi(); // phi_tilde = phi - 3pi/4 + if (values[kPhiTildeCS] < 0) { + values[kPhiTildeCS] += 2 * TMath::Pi(); // ensure phi_tilde is in [0, 2pi] + } + } + } else { + values[kPhiTildeCS] = -999; // not computable + } + } + } + + if (usePP) { + ROOT::Math::XYZVector zaxis_PP = ROOT::Math::XYZVector(v12.Py(), -v12.Px(), 0.f); + ROOT::Math::XYZVector yaxis_PP{(v12.Vect()).Unit()}; + ROOT::Math::XYZVector xaxis_PP{(yaxis_PP.Cross(zaxis_PP)).Unit()}; + if (fgUsedVars[kCosThetaPP]) { + values[kCosThetaPP] = zaxis_PP.Dot(v_CM) / std::sqrt(zaxis_PP.Mag2()); + } + if (fgUsedVars[kPhiPP]) { + values[kPhiPP] = TMath::ATan2(yaxis_PP.Dot(v_CM), xaxis_PP.Dot(v_CM)); + if (values[kPhiPP] < 0) { + values[kPhiPP] += 2 * TMath::Pi(); // ensure phi is in [0, 2pi] + } + } + if (fgUsedVars[kPhiTildePP]) { + if (fgUsedVars[kCosThetaPP] && fgUsedVars[kPhiPP]) { + if (values[kCosThetaPP] > 0) { + values[kPhiTildePP] = values[kPhiPP] - 0.25 * TMath::Pi(); // phi_tilde = phi - pi/4 + if (values[kPhiTildePP] < 0) { + values[kPhiTildePP] += 2 * TMath::Pi(); // ensure phi_tilde is in [0, 2pi] + } + } else { + values[kPhiTildePP] = values[kPhiPP] - 0.75 * TMath::Pi(); // phi_tilde = phi - 3pi/4 + if (values[kPhiTildePP] < 0) { + values[kPhiTildePP] += 2 * TMath::Pi(); // ensure phi_tilde is in [0, 2pi] + } + } + } else { + values[kPhiTildePP] = -999; // not computable + } + } + } + + if (useRM) { + double randomCostheta = gRandom->Uniform(-1., 1.); + double randomPhi = gRandom->Uniform(0., 2. * TMath::Pi()); + ROOT::Math::XYZVectorF zaxis_RM(randomCostheta, std::sqrt(1 - randomCostheta * randomCostheta) * std::cos(randomPhi), std::sqrt(1 - randomCostheta * randomCostheta) * std::sin(randomPhi)); + if (fgUsedVars[kCosThetaRM]) + values[kCosThetaRM] = zaxis_RM.Dot(v_CM); + } + } + + if constexpr ((pairType == kDecayToEE) && ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0)) { + + if (fgUsedVars[kQuadDCAabsXY] || fgUsedVars[kQuadDCAsigXY] || fgUsedVars[kQuadDCAabsZ] || fgUsedVars[kQuadDCAsigZ] || fgUsedVars[kQuadDCAsigXYZ] || fgUsedVars[kSignQuadDCAsigXY]) { + // Quantities based on the barrel tables + double dca1XY = t1.dcaXY(); + double dca2XY = t2.dcaXY(); + double dca1Z = t1.dcaZ(); + double dca2Z = t2.dcaZ(); + 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); + } + } + } + if constexpr ((pairType == kDecayToMuMu) && ((fillMap & Muon) > 0 || (fillMap & ReducedMuon) > 0)) { + if (fgUsedVars[kQuadDCAabsXY]) { + double dca1X = t1.fwdDcaX(); + double dca1Y = t1.fwdDcaY(); + double dca1XY = std::sqrt(dca1X * dca1X + dca1Y * dca1Y); + double dca2X = t2.fwdDcaX(); + double dca2Y = t2.fwdDcaY(); + double dca2XY = std::sqrt(dca2X * dca2X + dca2Y * dca2Y); + values[kQuadDCAabsXY] = std::sqrt((dca1XY * dca1XY + dca2XY * dca2XY) / 2.); + } + } + if (fgUsedVars[kPairPhiv]) { + values[kPairPhiv] = calculatePhiV(t1, t2); + } +} + +template +void VarManager::FillResolutions(M const& mcTrack, T const& track, float* values) +{ + if (!values) { + values = fgValues; + } + + values[kDeltaPt] = track.pt() - mcTrack.pt(); + values[kPtResolution] = (track.pt() - mcTrack.pt()) / mcTrack.pt(); + + values[kEtaResolution] = track.eta() - mcTrack.eta(); +} + #endif // PWGDQ_CORE_VARMANAGER_H_ diff --git a/PWGDQ/DataModel/MchTrkEffTables.h b/PWGDQ/DataModel/MchTrkEffTables.h index 3fbecfb619c..a7aa5d1e323 100644 --- a/PWGDQ/DataModel/MchTrkEffTables.h +++ b/PWGDQ/DataModel/MchTrkEffTables.h @@ -17,7 +17,9 @@ #ifndef PWGDQ_DATAMODEL_MCHTRKEFFTABLES_H_ #define PWGDQ_DATAMODEL_MCHTRKEFFTABLES_H_ -#include "Framework/AnalysisDataModel.h" +#include + +#include namespace o2::aod { diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 95214a8f83e..71a15a1ddbd 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -20,14 +20,16 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "MathUtils/Utils.h" +#include +#include +#include #include +#include #include namespace o2::aod @@ -50,23 +52,49 @@ 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 -DECLARE_SOA_COLUMN(MCPosZ, mcPosZ, float); //! MC event position Z -DECLARE_SOA_COLUMN(NTPCoccupContribLongA, nTPCoccupContribLongA, int); //! TPC pileup occupancy on A side (long time range) -DECLARE_SOA_COLUMN(NTPCoccupContribLongC, nTPCoccupContribLongC, int); //! TPC pileup occupancy on C side (long time range) -DECLARE_SOA_COLUMN(NTPCoccupMeanTimeLongA, nTPCoccupMeanTimeLongA, float); //! TPC pileup mean time on A side (long time range) -DECLARE_SOA_COLUMN(NTPCoccupMeanTimeLongC, nTPCoccupMeanTimeLongC, float); //! TPC pileup mean time on C side (long time range) -DECLARE_SOA_COLUMN(NTPCoccupMedianTimeLongA, nTPCoccupMedianTimeLongA, float); //! TPC pileup median time on A side (long time range) -DECLARE_SOA_COLUMN(NTPCoccupMedianTimeLongC, nTPCoccupMedianTimeLongC, float); //! TPC pileup median time on C side (long time range) -DECLARE_SOA_COLUMN(NTPCoccupContribShortA, nTPCoccupContribShortA, int); //! TPC pileup occupancy on A side (short time range) -DECLARE_SOA_COLUMN(NTPCoccupContribShortC, nTPCoccupContribShortC, int); //! TPC pileup occupancy on C side (short time range) -DECLARE_SOA_COLUMN(NTPCoccupMeanTimeShortA, nTPCoccupMeanTimeShortA, float); //! TPC pileup mean time on A side (short time range) -DECLARE_SOA_COLUMN(NTPCoccupMeanTimeShortC, nTPCoccupMeanTimeShortC, float); //! TPC pileup mean time on C side (short time range) -DECLARE_SOA_COLUMN(NTPCoccupMedianTimeShortA, nTPCoccupMedianTimeShortA, float); //! TPC pileup median time on A side (short time range) -DECLARE_SOA_COLUMN(NTPCoccupMedianTimeShortC, nTPCoccupMedianTimeShortC, float); //! TPC pileup median time on C side (short time range) +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 +DECLARE_SOA_COLUMN(MCPosZ, mcPosZ, float); //! MC event position Z +DECLARE_SOA_COLUMN(NTPCoccupContribLongA, nTPCoccupContribLongA, int); //! TPC pileup occupancy on A side (long time range) +DECLARE_SOA_COLUMN(NTPCoccupContribLongC, nTPCoccupContribLongC, int); //! TPC pileup occupancy on C side (long time range) +DECLARE_SOA_COLUMN(NTPCoccupMeanTimeLongA, nTPCoccupMeanTimeLongA, float); //! TPC pileup mean time on A side (long time range) +DECLARE_SOA_COLUMN(NTPCoccupMeanTimeLongC, nTPCoccupMeanTimeLongC, float); //! TPC pileup mean time on C side (long time range) +DECLARE_SOA_COLUMN(NTPCoccupMedianTimeLongA, nTPCoccupMedianTimeLongA, float); //! TPC pileup median time on A side (long time range) +DECLARE_SOA_COLUMN(NTPCoccupMedianTimeLongC, nTPCoccupMedianTimeLongC, float); //! TPC pileup median time on C side (long time range) +DECLARE_SOA_COLUMN(NTPCoccupContribShortA, nTPCoccupContribShortA, int); //! TPC pileup occupancy on A side (short time range) +DECLARE_SOA_COLUMN(NTPCoccupContribShortC, nTPCoccupContribShortC, int); //! TPC pileup occupancy on C side (short time range) +DECLARE_SOA_COLUMN(NTPCoccupMeanTimeShortA, nTPCoccupMeanTimeShortA, float); //! TPC pileup mean time on A side (short time range) +DECLARE_SOA_COLUMN(NTPCoccupMeanTimeShortC, nTPCoccupMeanTimeShortC, float); //! TPC pileup mean time on C side (short time range) +DECLARE_SOA_COLUMN(NTPCoccupMedianTimeShortA, nTPCoccupMedianTimeShortA, float); //! TPC pileup median time on A side (short time range) +DECLARE_SOA_COLUMN(NTPCoccupMedianTimeShortC, nTPCoccupMedianTimeShortC, float); //! TPC pileup median time on C side (short time range) +DECLARE_SOA_COLUMN(DCAzBimodalityCoefficient, dcazBimodalityCoefficient, float); //! Bimodality coefficient of the DCAz distribution of the tracks in the event +DECLARE_SOA_COLUMN(DCAzBimodalityCoefficientBinned, dcazBimodalityCoefficientBinned, float); //! Bimodality coefficient of the DCAz distribution of the tracks in the event, binned +DECLARE_SOA_COLUMN(DCAzBimodalityCoefficientBinnedTrimmed1, dcazBimodalityCoefficientBinnedTrimmed1, float); //! Bimodality coefficient of the DCAz distribution of the tracks in the event, binned and trimmed 1 +DECLARE_SOA_COLUMN(DCAzBimodalityCoefficientBinnedTrimmed2, dcazBimodalityCoefficientBinnedTrimmed2, float); //! Bimodality coefficient of the DCAz distribution of the tracks in the event, binned and trimmed 2 +DECLARE_SOA_COLUMN(DCAzBimodalityCoefficientBinnedTrimmed3, dcazBimodalityCoefficientBinnedTrimmed3, float); //! Bimodality coefficient of the DCAz distribution of the tracks in the event, binned and trimmed 3 +DECLARE_SOA_COLUMN(DCAzMean, dcazMean, float); //! Mean of the DCAz distribution of the tracks in the event +DECLARE_SOA_COLUMN(DCAzMeanBinnedTrimmed1, dcazMeanBinnedTrimmed1, float); //! Mean of the DCAz distribution of the tracks in the event, binned and trimmed 1 +DECLARE_SOA_COLUMN(DCAzMeanBinnedTrimmed2, dcazMeanBinnedTrimmed2, float); //! Mean of the DCAz distribution of the tracks in the event, binned and trimmed 2 +DECLARE_SOA_COLUMN(DCAzMeanBinnedTrimmed3, dcazMeanBinnedTrimmed3, float); //! Mean of the DCAz distribution of the tracks in the event, binned and trimmed 3 +DECLARE_SOA_COLUMN(DCAzRMS, dcazRMS, float); //! RMS of the DCAz distribution of the tracks in the event +DECLARE_SOA_COLUMN(DCAzRMSBinnedTrimmed1, dcazRMSBinnedTrimmed1, float); //! RMS of the DCAz distribution of the tracks in the event, binned and trimmed 1 +DECLARE_SOA_COLUMN(DCAzRMSBinnedTrimmed2, dcazRMSBinnedTrimmed2, float); //! RMS of the DCAz distribution of the tracks in the event, binned and trimmed 2 +DECLARE_SOA_COLUMN(DCAzRMSBinnedTrimmed3, dcazRMSBinnedTrimmed3, float); //! RMS of the DCAz distribution of the tracks in the event, binned and trimmed 3 +DECLARE_SOA_COLUMN(DCAzSkewness, dcazSkewness, float); //! Skewness of the DCAz distribution of the tracks in the event +DECLARE_SOA_COLUMN(DCAzKurtosis, dcazKurtosis, float); //! Kurtosis of the DCAz distribution of the tracks in the event +DECLARE_SOA_COLUMN(DCAzFracAbove100um, dcazFracAbove100um, float); //! Fraction of tracks in the event with |DCAz| > 100um +DECLARE_SOA_COLUMN(DCAzFracAbove200um, dcazFracAbove200um, float); //! Fraction of tracks in the event with |DCAz| > 200um +DECLARE_SOA_COLUMN(DCAzFracAbove500um, dcazFracAbove500um, float); //! Fraction of tracks in the event with |DCAz| > 500um +DECLARE_SOA_COLUMN(DCAzFracAbove1mm, dcazFracAbove1mm, float); //! Fraction of tracks in the event with |DCAz| > 1mm +DECLARE_SOA_COLUMN(DCAzFracAbove2mm, dcazFracAbove2mm, float); //! Fraction of tracks in the event with |DCAz| > 2mm +DECLARE_SOA_COLUMN(DCAzFracAbove5mm, dcazFracAbove5mm, float); //! Fraction of tracks in the event with |DCAz| > 5mm +DECLARE_SOA_COLUMN(DCAzFracAbove10mm, dcazFracAbove10mm, float); //! Fraction of tracks in the event with |DCAz| > 10mm +DECLARE_SOA_COLUMN(DCAzNPeaks, dcazNPeaks, int); //! Number of peaks in the DCAz distribution of the tracks in the event +DECLARE_SOA_COLUMN(DCAzNPeaksTrimmed1, dcazNPeaksTrimmed1, int); //! Number of peaks in the binned DCAz distribution (trimmed 1) +DECLARE_SOA_COLUMN(DCAzNPeaksTrimmed2, dcazNPeaksTrimmed2, int); //! Number of peaks in the binned DCAz distribution (trimmed 2) +DECLARE_SOA_COLUMN(DCAzNPeaksTrimmed3, dcazNPeaksTrimmed3, int); //! Number of peaks in the binned DCAz distribution (trimmed 3) // Columns declared to guarantee the backward compatibility of the tables DECLARE_SOA_COLUMN(QvecBPosRe, qvecBPosRe, float); @@ -198,6 +226,16 @@ DECLARE_SOA_TABLE(ReducedEventsQvectorZN, "AOD", "REQVECTORZN", //! Event Q-v DECLARE_SOA_TABLE(ReducedEventsInfo, "AOD", "REDUCEVENTINFO", //! Main event index table reducedevent::CollisionId); +DECLARE_SOA_TABLE(ReducedEventsMergingTable, "AOD", "REMERGE", //! Collision merging quatities + reducedevent::DCAzBimodalityCoefficient, reducedevent::DCAzBimodalityCoefficientBinned, + reducedevent::DCAzBimodalityCoefficientBinnedTrimmed1, reducedevent::DCAzBimodalityCoefficientBinnedTrimmed2, reducedevent::DCAzBimodalityCoefficientBinnedTrimmed3, + reducedevent::DCAzMean, reducedevent::DCAzMeanBinnedTrimmed1, reducedevent::DCAzMeanBinnedTrimmed2, reducedevent::DCAzMeanBinnedTrimmed3, + reducedevent::DCAzRMS, reducedevent::DCAzRMSBinnedTrimmed1, reducedevent::DCAzRMSBinnedTrimmed2, reducedevent::DCAzRMSBinnedTrimmed3, + reducedevent::DCAzSkewness, reducedevent::DCAzKurtosis, + reducedevent::DCAzFracAbove100um, reducedevent::DCAzFracAbove200um, reducedevent::DCAzFracAbove500um, + reducedevent::DCAzFracAbove1mm, reducedevent::DCAzFracAbove2mm, reducedevent::DCAzFracAbove5mm, reducedevent::DCAzFracAbove10mm, + reducedevent::DCAzNPeaks, reducedevent::DCAzNPeaksTrimmed1, reducedevent::DCAzNPeaksTrimmed2, reducedevent::DCAzNPeaksTrimmed3); + // 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 @@ -664,8 +702,10 @@ DECLARE_SOA_COLUMN(Vy2, vy2, float); //! Y production vertex in cm DECLARE_SOA_COLUMN(Vz2, vz2, float); //! Z production vertex in cm DECLARE_SOA_COLUMN(Vt2, vt2, float); //! Production vertex time -DECLARE_SOA_COLUMN(IsAmbig1, isAmbig1, int); //! -DECLARE_SOA_COLUMN(IsAmbig2, isAmbig2, int); //! +DECLARE_SOA_COLUMN(IsAmbig1, isAmbig1, int); //! +DECLARE_SOA_COLUMN(IsAmbig2, isAmbig2, int); //! +DECLARE_SOA_COLUMN(IsCorrectAssoc1, isCorrectAssoc1, bool); //! +DECLARE_SOA_COLUMN(IsCorrectAssoc2, isCorrectAssoc2, bool); //! DECLARE_SOA_COLUMN(FwdDcaX1, fwdDcaX1, float); //! X component of forward DCA DECLARE_SOA_COLUMN(FwdDcaY1, fwdDcaY1, float); //! Y component of forward DCA @@ -831,6 +871,17 @@ DECLARE_SOA_TABLE(Dimuons, "AOD", "RTDIMUON", //! reducedpair::Rap, reducedpair::Y); +DECLARE_SOA_TABLE(ElectronMuons, "AOD", "RTELECTRONMUON", //! + 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, reducedpair::Tauz, @@ -902,6 +953,7 @@ DECLARE_SOA_TABLE(DimuonsAll, "AOD", "RTDIMUONALL", //! dilepton_track_index::Vx1, dilepton_track_index::Vy1, dilepton_track_index::Vz1, dilepton_track_index::Vt1, dilepton_track_index::Vx2, dilepton_track_index::Vy2, dilepton_track_index::Vz2, dilepton_track_index::Vt2, dilepton_track_index::IsAmbig1, dilepton_track_index::IsAmbig2, + dilepton_track_index::IsCorrectAssoc1, dilepton_track_index::IsCorrectAssoc2, reducedpair::U2Q2, reducedpair::U3Q3, reducedpair::R2EP_AB, diff --git a/PWGDQ/DataModel/ReducedTablesAlice3.h b/PWGDQ/DataModel/ReducedTablesAlice3.h new file mode 100644 index 00000000000..787d7d38793 --- /dev/null +++ b/PWGDQ/DataModel/ReducedTablesAlice3.h @@ -0,0 +1,335 @@ +// 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 ReducedTablesAlice3.h +/// +/// \brief Reduced DQ table definitions for ALICE 3 +/// +/// \author Alexander Tiekoetter (atiekoet@cern.ch) University of Muenster + +#ifndef PWGDQ_DATAMODEL_REDUCEDTABLESALICE3_H_ +#define PWGDQ_DATAMODEL_REDUCEDTABLESALICE3_H_ + +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "ALICE3/DataModel/OTFPIDTrk.h" +#include "ALICE3/DataModel/OTFRICH.h" +#include "ALICE3/DataModel/OTFTOF.h" + +#include +#include +#include + +#include +#include + +namespace o2::aod +{ +namespace reducedeventalice3 +{ +DECLARE_SOA_COLUMN(MultDensity, multDensity, float); +DECLARE_SOA_COLUMN(MCPosX, mcPosX, float); //! MC event position X +DECLARE_SOA_COLUMN(MCPosY, mcPosY, float); //! MC event position Y +DECLARE_SOA_COLUMN(MCPosZ, mcPosZ, float); //! MC event position Z +} // namespace reducedeventalice3 + +namespace reducedeventmcalice3 +{ +DECLARE_SOA_COLUMN(MultMCNParticlesEta05, multMCNParticlesEta05, float); +DECLARE_SOA_COLUMN(MultMCNParticlesEta08, multMCNParticlesEta08, float); +DECLARE_SOA_COLUMN(MultMCNParticlesEta10, multMCNParticlesEta10, float); +DECLARE_SOA_COLUMN(MultMCNParticlesEta20, multMCNParticlesEta20, float); +DECLARE_SOA_COLUMN(MultMCNParticlesEta40, multMCNParticlesEta40, float); +} // namespace reducedeventmcalice3 + +DECLARE_SOA_TABLE_STAGED(ReducedA3Events, "REA3EVENTS", //! Main event information table + o2::soa::Index<>, + collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, + collision::CollisionTime, collision::CollisionTimeRes, reducedeventalice3::MultDensity); + +DECLARE_SOA_TABLE(ReducedA3EventsVtxCov, "AOD", "REA3VTXCOV", //! Event vertex covariance matrix + collision::CovXX, collision::CovXY, collision::CovXZ, + collision::CovYY, collision::CovYZ, collision::CovZZ, collision::Chi2); + +DECLARE_SOA_TABLE(ReducedA3EventsInfo, "AOD", "REA3EVENTINFO", //! Main event index table + reducedevent::CollisionId); + +DECLARE_SOA_TABLE(ReducedA3MCEvents, "AOD", "REA3MCEVTS", //! Event level MC truth information + o2::soa::Index<>, + mccollision::GeneratorsID, reducedeventalice3::MCPosX, reducedeventalice3::MCPosY, reducedeventalice3::MCPosZ, + mccollision::T, mccollision::Weight, mccollision::ImpactParameter); + +using ReducedA3MCEvent = ReducedA3MCEvents::iterator; +using ReducedA3Event = ReducedA3Events::iterator; + +namespace reducedtrackalice3 +{ +// basic track information +DECLARE_SOA_INDEX_COLUMN(ReducedA3Event, reduceda3event); //! +DECLARE_SOA_INDEX_COLUMN(Track, track); //! +// ---- flags reserved for storing various information during filtering +DECLARE_SOA_BITMAP_COLUMN(FilteringFlags, filteringFlags, 64); //! +// ----------------------------------------------------- + +DECLARE_SOA_COLUMN(IsReconstructed, isReconstructed, bool); +DECLARE_SOA_COLUMN(NSiliconHits, nSiliconHits, int); +DECLARE_SOA_COLUMN(NTPCHits, nTPCHits, int); + +DECLARE_SOA_COLUMN(Pt, pt, float); //! +DECLARE_SOA_COLUMN(Eta, eta, float); //! +DECLARE_SOA_COLUMN(Phi, phi, float); //! +DECLARE_SOA_COLUMN(Sign, sign, int); //! +DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, int); //! +DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); //! +DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); //! +DECLARE_SOA_COLUMN(DetectorMap, detectorMap, uint8_t); //! Detector map: see enum DetectorMapEnum +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_DYNAMIC_COLUMN(HasITS, hasITS, //! Flag to check if track has a ITS match + [](uint8_t detectorMap) -> bool { return detectorMap & o2::aod::track::ITS; }); +DECLARE_SOA_DYNAMIC_COLUMN(HasTPC, hasTPC, //! Flag to check if track has a TPC match + [](uint8_t detectorMap) -> bool { return detectorMap & o2::aod::track::TPC; }); +DECLARE_SOA_DYNAMIC_COLUMN(HasTRD, hasTRD, //! Flag to check if track has a TRD match + [](uint8_t detectorMap) -> bool { return detectorMap & o2::aod::track::TRD; }); +DECLARE_SOA_DYNAMIC_COLUMN(HasTOF, hasTOF, //! Flag to check if track has a TOF measurement + [](uint8_t detectorMap) -> bool { return detectorMap & o2::aod::track::TOF; }); +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 reducedtrackalice3 + +// basic track information +DECLARE_SOA_TABLE(ReducedA3Tracks, "AOD", "REA3TRACK", //! + o2::soa::Index<>, reducedtrackalice3::ReducedA3EventId, reducedtrackalice3::FilteringFlags, + reducedtrackalice3::Pt, reducedtrackalice3::Eta, reducedtrackalice3::Phi, reducedtrackalice3::Sign, reducedtrackalice3::IsAmbiguous, + reducedtrackalice3::Px, + reducedtrackalice3::Py, + reducedtrackalice3::Pz, + reducedtrackalice3::P); + +DECLARE_SOA_TABLE(ReducedA3TracksBarrelCov, "AOD", "REA3BARRELCOV", //! + track::CYY, track::CZY, track::CZZ, track::CSnpY, track::CSnpZ, + track::CSnpSnp, track::CTglY, track::CTglZ, track::CTglSnp, track::CTglTgl, + track::C1PtY, track::C1PtZ, track::C1PtSnp, track::C1PtTgl, track::C1Pt21Pt2); + +namespace reducedA3trackMC +{ +DECLARE_SOA_INDEX_COLUMN(ReducedA3MCEvent, reducedA3MCEvent); //! +DECLARE_SOA_COLUMN(McReducedFlags, mcReducedFlags, uint16_t); //! Flags to hold compressed MC selection information +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother0, mother0, int, "ReducedA3MCTracks_Mother0"); //! Track index of the first mother +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Mother1, mother1, int, "ReducedA3MCTracks_Mother1"); //! Track index of the last mother +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter0, daughter0, int, "ReducedA3MCTracks_Daughter0"); //! Track index of the first daughter +DECLARE_SOA_SELF_INDEX_COLUMN_FULL(Daughter1, daughter1, int, "ReducedA3MCTracks_Daughter1"); //! Track index of the last daughter +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Mothers, mothers); //! Mother tracks (possible empty) array. Iterate over mcParticle.mothers_as()) +DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(Daughters, daughters); //! Daughter tracks (possibly empty) slice. Check for non-zero with mcParticle.has_daughters(). Iterate over mcParticle.daughters_as()) +DECLARE_SOA_COLUMN(Pt, pt, float); //! +DECLARE_SOA_COLUMN(Eta, eta, float); //! +DECLARE_SOA_COLUMN(Phi, phi, float); //! +DECLARE_SOA_COLUMN(E, e, float); //! +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); }); +DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! Particle rapidity + [](float pt, float eta, float e) -> float { + float pz = pt * std::sinh(eta); + if ((e - pz) > static_cast(1e-7)) { + return 0.5f * std::log((e + pz) / (e - pz)); + } else { + return -999.0f; + } + }); +} // namespace reducedA3trackMC + +// 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(ReducedA3MCTracks, "AOD", "REA3MCTRACK", //! MC track information (on disk) + o2::soa::Index<>, reducedA3trackMC::ReducedA3MCEventId, + mcparticle::PdgCode, mcparticle::StatusCode, mcparticle::Flags, + reducedA3trackMC::MothersIds, reducedA3trackMC::DaughtersIdSlice, + mcparticle::Weight, + reducedA3trackMC::Pt, reducedA3trackMC::Eta, reducedA3trackMC::Phi, reducedA3trackMC::E, + mcparticle::Vx, mcparticle::Vy, mcparticle::Vz, mcparticle::Vt, + reducedA3trackMC::McReducedFlags, + reducedA3trackMC::Px, + reducedA3trackMC::Py, + reducedA3trackMC::Pz, + reducedA3trackMC::P, + reducedA3trackMC::Y, + mcparticle::ProducedByGenerator, + mcparticle::FromBackgroundEvent, + mcparticle::GetGenStatusCode, + mcparticle::GetProcess, + mcparticle::GetHepMCStatusCode, + mcparticle::IsPhysicalPrimary); + +using ReducedA3MCTrack = ReducedA3MCTracks::iterator; + +namespace reduceda3barreltracklabel +{ +DECLARE_SOA_INDEX_COLUMN(ReducedA3MCTrack, reducedA3MCTrack); //! +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace reduceda3barreltracklabel + +// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with the track tables) +// The McParticleId points to the position of the MC truth track from the ReducedTracksMC table +DECLARE_SOA_TABLE(ReducedA3TracksBarrelLabels, "AOD", "REA3BARLA", //! + reduceda3barreltracklabel::ReducedA3MCTrackId, reduceda3barreltracklabel::McMask, reducedA3trackMC::McReducedFlags); + +using ReducedA3TrackBarrelLabel = ReducedA3TracksBarrelLabels::iterator; + +DECLARE_SOA_TABLE(ReducedA3TracksBarrel, "AOD", "REA3BARREL", + track::X, track::Alpha, track::IsWithinBeamPipe, + track::Y, track::Z, track::Snp, track::Tgl, track::Signed1Pt, + track::Flags, track::ITSClusterMap, track::ITSChi2NCl, + reducedtrackalice3::IsReconstructed, reducedtrackalice3::NSiliconHits, + reducedtrackalice3::NTPCHits, track::Length, reducedtrack::DcaXY, reducedtrack::DcaZ, + track::IsPVContributor); + +// barrel collision information (joined with ReducedTracks) allowing to connect different tables (cross PWGs) +DECLARE_SOA_TABLE(ReducedA3TracksBarrelInfo, "AOD", "REA3BARRELINFO", + reducedtrackalice3::CollisionId, collision::PosX, collision::PosY, collision::PosZ, reducedtrackalice3::TrackId); + +using ReducedA3Track = ReducedA3Tracks::iterator; +using ReducedA3TrackBarrel = ReducedA3TracksBarrel::iterator; +using ReducedA3TrackBarrelCov = ReducedA3TracksBarrelCov::iterator; +using ReducedA3TrackBarrelInfo = ReducedA3TracksBarrelInfo::iterator; + +namespace reducedeventlabela3 +{ +DECLARE_SOA_INDEX_COLUMN(ReducedA3MCEvent, reducedA3MCEvent); //! 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 reducedeventlabela3 + +DECLARE_SOA_TABLE(ReducedA3MCEventLabels, "AOD", "REA3MCCOLLBL", //! Table joined to the ReducedEvents table containing the MC index + reducedeventlabela3::ReducedA3MCEventId, reducedeventlabela3::McMask); + +using ReducedA3MCEventLabel = ReducedA3MCEventLabels::iterator; + +namespace reducedA3track_association +{ +DECLARE_SOA_INDEX_COLUMN(ReducedA3Event, reducedA3event); //! ReducedEvent index +DECLARE_SOA_INDEX_COLUMN(ReducedA3Track, reducedA3track); //! ReducedTrack index +} // namespace reducedA3track_association + +DECLARE_SOA_TABLE(ReducedA3TracksAssoc, "AOD", "REA3ASSOC", //! Table for reducedtrack-to-reducedcollision association + reducedA3track_association::ReducedA3EventId, + reducedA3track_association::ReducedA3TrackId); + +DECLARE_SOA_TABLE(ReducedA3PIDTOF, "AOD", "REA3PIDTOF", + upgrade_tof::TOFEventTime, + upgrade_tof::TOFEventTimeErr, + upgrade_tof::NSigmaElectronInnerTOF, + upgrade_tof::NSigmaMuonInnerTOF, + upgrade_tof::NSigmaPionInnerTOF, + upgrade_tof::NSigmaKaonInnerTOF, + upgrade_tof::NSigmaProtonInnerTOF, + upgrade_tof::NSigmaDeuteronInnerTOF, + upgrade_tof::NSigmaTritonInnerTOF, + upgrade_tof::NSigmaHelium3InnerTOF, + upgrade_tof::NSigmaAlphaInnerTOF, + upgrade_tof::InnerTOFTrackTimeReco, + upgrade_tof::InnerTOFTrackLengthReco, + upgrade_tof::NSigmaElectronOuterTOF, + upgrade_tof::NSigmaMuonOuterTOF, + upgrade_tof::NSigmaPionOuterTOF, + upgrade_tof::NSigmaKaonOuterTOF, + upgrade_tof::NSigmaProtonOuterTOF, + upgrade_tof::NSigmaDeuteronOuterTOF, + upgrade_tof::NSigmaTritonOuterTOF, + upgrade_tof::NSigmaHelium3OuterTOF, + upgrade_tof::NSigmaAlphaOuterTOF, + upgrade_tof::OuterTOFTrackTimeReco, + upgrade_tof::OuterTOFTrackLengthReco, + upgrade_tof::NSigmaInnerTOF, + upgrade_tof::NSigmaOuterTOF); + +DECLARE_SOA_TABLE(ReducedA3PIDRich, "AOD", "REA3PIDRICH", + upgrade_rich::NSigmaElectronRich, + upgrade_rich::NSigmaMuonRich, + upgrade_rich::NSigmaPionRich, + upgrade_rich::NSigmaKaonRich, + upgrade_rich::NSigmaProtonRich, + upgrade_rich::NSigmaDeuteronRich, + upgrade_rich::NSigmaTritonRich, + upgrade_rich::NSigmaHelium3Rich, + upgrade_rich::NSigmaAlphaRich, + upgrade_rich::NSigmaRich); + +DECLARE_SOA_TABLE(ReducedA3PIDRichSignals, "AOD", "REA3PIDRICHSIG", + upgrade_rich::HasSig, + upgrade_rich::HasSigInGas, + upgrade_rich::HasSigEl, + upgrade_rich::HasSigMu, + upgrade_rich::HasSigPi, + upgrade_rich::HasSigKa, + upgrade_rich::HasSigPr, + upgrade_rich::HasSigDe, + upgrade_rich::HasSigTr, + upgrade_rich::HasSigHe3, + upgrade_rich::HasSigAl); + +DECLARE_SOA_TABLE(ReducedA3PIDOT, "AOD", "REA3PIDOT", + upgrade::trk::TimeOverThresholdBarrel, + upgrade::trk::NSigmaTrkEl, + upgrade::trk::NSigmaTrkMu, + upgrade::trk::NSigmaTrkPi, + upgrade::trk::NSigmaTrkKa, + upgrade::trk::NSigmaTrkPr, + upgrade::trk::NSigmaTrkDe, + upgrade::trk::NSigmaTrkTr, + upgrade::trk::NSigmaTrkHe, + upgrade::trk::NSigmaTrkAl, + upgrade::trk::NSigmaTrk); + +} // namespace o2::aod + +#endif // PWGDQ_DATAMODEL_REDUCEDTABLESALICE3_H_ diff --git a/PWGDQ/Macros/dqFlowAccWeights.C b/PWGDQ/Macros/dqFlowAccWeights.C index 00cb5107d45..d4786089810 100644 --- a/PWGDQ/Macros/dqFlowAccWeights.C +++ b/PWGDQ/Macros/dqFlowAccWeights.C @@ -14,23 +14,25 @@ /// /// \author Chi ZHANG, CEA-Saclay, chi.zhang@cern.ch -#include -#include -#include -#include -#include -#include +#include "PWGCF/GenericFramework/Core/GFWWeights.h" + +#include +#include -#include #include -#include "Framework/Logger.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGCF/GenericFramework/Core/GFWWeights.h" +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace std; -void dqFlowAccWeights(int64 tmin = 1546300800000, int64 tmax = 1577833200000, std::string Period = "LHC23zzh_pass2", std::string SubDir = "d-q-event-qvector", std::string FileName = "AnalysisResults.root") +void dqFlowAccWeights(int64_t tmin = 1546300800000, int64_t tmax = 1577833200000, std::string Period = "LHC23zzh_pass2", std::string SubDir = "d-q-event-qvector", std::string FileName = "AnalysisResults.root") { if (tmax < tmin) { LOG(fatal) << "Wrong validity syntax!"; diff --git a/PWGDQ/Macros/evalMchTrackingEfficiency.cxx b/PWGDQ/Macros/evalMchTrackingEfficiency.cxx index 34610915850..c59afbb40b8 100644 --- a/PWGDQ/Macros/evalMchTrackingEfficiency.cxx +++ b/PWGDQ/Macros/evalMchTrackingEfficiency.cxx @@ -14,17 +14,20 @@ /// /// \author Zaida Conesa del Valle /// \author Andrea Tavira García -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include -#include "TFile.h" -#include "TDirectoryFile.h" -#include "THn.h" -#include "TH1F.h" -#include "TH2F.h" -#include "TAxis.h" -#include "TCanvas.h" -#include "TStyle.h" -#include "TLegend.h" +#include double computeEfficiencyPerChamber(THnF* hnf, int iAxis, int iCh, double binLimits[2]); double computeEfficiencyPerChamber(THnF* hnf, const int iAxis[3], int iCh, double binLimits[3][2]); diff --git a/PWGDQ/Macros/fit_library/CB2Pdf.cxx b/PWGDQ/Macros/fit_library/CB2Pdf.cxx index 7f2501825e3..05d13210aaa 100644 --- a/PWGDQ/Macros/fit_library/CB2Pdf.cxx +++ b/PWGDQ/Macros/fit_library/CB2Pdf.cxx @@ -11,13 +11,17 @@ /// \author Luca Micheletti , CERN -#include "Riostream.h" - #include "CB2Pdf.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" + +#include +#include +#include +#include + +#include +#include + #include -#include "TMath.h" ClassImp(CB2Pdf); diff --git a/PWGDQ/Macros/fit_library/CB2Pdf.h b/PWGDQ/Macros/fit_library/CB2Pdf.h index a9e3a87409e..23cb291dcdd 100644 --- a/PWGDQ/Macros/fit_library/CB2Pdf.h +++ b/PWGDQ/Macros/fit_library/CB2Pdf.h @@ -11,14 +11,16 @@ /// \author Luca Micheletti , CERN -#ifndef CB2PDF -#define CB2PDF +#ifndef PWGDQ_MACROS_FIT_LIBRARY_CB2PDF_H_ +#define PWGDQ_MACROS_FIT_LIBRARY_CB2PDF_H_ -#include "RooAbsPdf.h" -#include "RooRealProxy.h" -#include "RooCategoryProxy.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" +#include +#include +#include +#include + +#include +#include class CB2Pdf : public RooAbsPdf { @@ -51,4 +53,4 @@ class CB2Pdf : public RooAbsPdf ClassDef(CB2Pdf, 1) // Your description goes here... }; -#endif +#endif // PWGDQ_MACROS_FIT_LIBRARY_CB2PDF_H_ diff --git a/PWGDQ/Macros/fit_library/ExpPdf.cxx b/PWGDQ/Macros/fit_library/ExpPdf.cxx old mode 100755 new mode 100644 index 1841ccd7cbb..c4e0d0988c1 --- a/PWGDQ/Macros/fit_library/ExpPdf.cxx +++ b/PWGDQ/Macros/fit_library/ExpPdf.cxx @@ -11,13 +11,16 @@ /// \author Luca Micheletti , CERN -#include "Riostream.h" - #include "ExpPdf.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" + +#include +#include +#include + +#include +#include + #include -#include "TMath.h" ClassImp(ExpPdf); diff --git a/PWGDQ/Macros/fit_library/ExpPdf.h b/PWGDQ/Macros/fit_library/ExpPdf.h old mode 100755 new mode 100644 index 394c73c52e6..306b0aea210 --- a/PWGDQ/Macros/fit_library/ExpPdf.h +++ b/PWGDQ/Macros/fit_library/ExpPdf.h @@ -11,14 +11,16 @@ /// \author Luca Micheletti , CERN -#ifndef EXPPDF -#define EXPPDF +#ifndef PWGDQ_MACROS_FIT_LIBRARY_EXPPDF_H_ +#define PWGDQ_MACROS_FIT_LIBRARY_EXPPDF_H_ -#include "RooAbsPdf.h" -#include "RooRealProxy.h" -#include "RooCategoryProxy.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" +#include +#include +#include +#include + +#include +#include class ExpPdf : public RooAbsPdf { @@ -43,4 +45,4 @@ class ExpPdf : public RooAbsPdf ClassDef(ExpPdf, 1) // Your description goes here... }; -#endif +#endif // PWGDQ_MACROS_FIT_LIBRARY_EXPPDF_H_ diff --git a/PWGDQ/Macros/fit_library/GausPdf.cxx b/PWGDQ/Macros/fit_library/GausPdf.cxx old mode 100755 new mode 100644 index 84d303e3a2b..2ec58abc577 --- a/PWGDQ/Macros/fit_library/GausPdf.cxx +++ b/PWGDQ/Macros/fit_library/GausPdf.cxx @@ -11,13 +11,16 @@ /// \author Luca Micheletti , CERN -#include "Riostream.h" - #include "GausPdf.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" + +#include +#include +#include + +#include +#include + #include -#include "TMath.h" ClassImp(GausPdf); diff --git a/PWGDQ/Macros/fit_library/GausPdf.h b/PWGDQ/Macros/fit_library/GausPdf.h old mode 100755 new mode 100644 index 4edb19ff47c..80a1e956817 --- a/PWGDQ/Macros/fit_library/GausPdf.h +++ b/PWGDQ/Macros/fit_library/GausPdf.h @@ -11,14 +11,16 @@ /// \author Luca Micheletti , CERN -#ifndef GAUSPDF -#define GAUSPDF +#ifndef PWGDQ_MACROS_FIT_LIBRARY_GAUSPDF_H_ +#define PWGDQ_MACROS_FIT_LIBRARY_GAUSPDF_H_ -#include "RooAbsPdf.h" -#include "RooRealProxy.h" -#include "RooCategoryProxy.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" +#include +#include +#include +#include + +#include +#include class GausPdf : public RooAbsPdf { @@ -43,4 +45,4 @@ class GausPdf : public RooAbsPdf ClassDef(GausPdf, 1) // Your description goes here... }; -#endif +#endif // PWGDQ_MACROS_FIT_LIBRARY_GAUSPDF_H_ diff --git a/PWGDQ/Macros/fit_library/Pol4ExpPdf.cxx b/PWGDQ/Macros/fit_library/Pol4ExpPdf.cxx old mode 100755 new mode 100644 index 912406a3b0b..ff254cc02ae --- a/PWGDQ/Macros/fit_library/Pol4ExpPdf.cxx +++ b/PWGDQ/Macros/fit_library/Pol4ExpPdf.cxx @@ -11,13 +11,16 @@ /// \author Luca Micheletti , CERN -#include "Riostream.h" - #include "Pol4ExpPdf.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" + +#include +#include +#include + +#include +#include + #include -#include "TMath.h" ClassImp(Pol4ExpPdf); diff --git a/PWGDQ/Macros/fit_library/Pol4ExpPdf.h b/PWGDQ/Macros/fit_library/Pol4ExpPdf.h old mode 100755 new mode 100644 index 13cd8696c6c..67202dbe5ac --- a/PWGDQ/Macros/fit_library/Pol4ExpPdf.h +++ b/PWGDQ/Macros/fit_library/Pol4ExpPdf.h @@ -11,14 +11,17 @@ /// \author Luca Micheletti , CERN -#ifndef POL4EXPPDF -#define POL4EXPPDF +#ifndef PWGDQ_MACROS_FIT_LIBRARY_POL4EXPPDF_H_ +#define PWGDQ_MACROS_FIT_LIBRARY_POL4EXPPDF_H_ -#include "RooAbsPdf.h" -#include "RooRealProxy.h" -#include "RooCategoryProxy.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" +#include +#include +#include +#include +#include + +#include +#include TString nameParameters[] = {"p0", "p1", "p2", "p3", "p4", "p5", "N_bkg", "N_sig", "mean", "width"}; @@ -53,4 +56,4 @@ class Pol4ExpPdf : public RooAbsPdf ClassDef(Pol4ExpPdf, 1) // Your description goes here... }; -#endif +#endif // PWGDQ_MACROS_FIT_LIBRARY_POL4EXPPDF_H_ diff --git a/PWGDQ/Macros/fit_library/VWGPdf.cxx b/PWGDQ/Macros/fit_library/VWGPdf.cxx index 8cebc90b2f4..e935afb4150 100644 --- a/PWGDQ/Macros/fit_library/VWGPdf.cxx +++ b/PWGDQ/Macros/fit_library/VWGPdf.cxx @@ -11,13 +11,16 @@ /// \author Luca Micheletti , CERN -#include "Riostream.h" - #include "VWGPdf.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" + +#include +#include +#include + +#include +#include + #include -#include "TMath.h" ClassImp(VWGPdf); diff --git a/PWGDQ/Macros/fit_library/VWGPdf.h b/PWGDQ/Macros/fit_library/VWGPdf.h index 9077d43be71..3ed4f2f81e6 100644 --- a/PWGDQ/Macros/fit_library/VWGPdf.h +++ b/PWGDQ/Macros/fit_library/VWGPdf.h @@ -11,14 +11,16 @@ /// \author Luca Micheletti , CERN -#ifndef VWGPDF -#define VWGPDF +#ifndef PWGDQ_MACROS_FIT_LIBRARY_VWGPDF_H_ +#define PWGDQ_MACROS_FIT_LIBRARY_VWGPDF_H_ -#include "RooAbsPdf.h" -#include "RooRealProxy.h" -#include "RooCategoryProxy.h" -#include "RooAbsReal.h" -#include "RooAbsCategory.h" +#include +#include +#include +#include + +#include +#include class VWGPdf : public RooAbsPdf { @@ -45,4 +47,4 @@ class VWGPdf : public RooAbsPdf ClassDef(VWGPdf, 1) // Your description goes here... }; -#endif +#endif // PWGDQ_MACROS_FIT_LIBRARY_VWGPDF_H_ diff --git a/PWGDQ/TableProducer/generatedQuarkoniaMC.cxx b/PWGDQ/TableProducer/generatedQuarkoniaMC.cxx index 22d5d78e6f7..209af151241 100644 --- a/PWGDQ/TableProducer/generatedQuarkoniaMC.cxx +++ b/PWGDQ/TableProducer/generatedQuarkoniaMC.cxx @@ -17,47 +17,40 @@ // when dealing with derived data. #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" + +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/McCollisionExtra.h" -#include "Common/DataModel/Qvectors.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include #include +#include #include -#include -#include #include -#include +#include #include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; // simple bit checkers #define bitset(var, nbit) ((var) |= (1 << (nbit))) diff --git a/PWGDQ/TableProducer/tableMaker.cxx b/PWGDQ/TableProducer/tableMaker.cxx index 5eb39ddd4d4..f2938705e87 100644 --- a/PWGDQ/TableProducer/tableMaker.cxx +++ b/PWGDQ/TableProducer/tableMaker.cxx @@ -17,13 +17,7 @@ // The skimming can optionally produce just the barrel, muon, or both barrel and muon tracks // The event filtering (filterPP), centrality, and V0Bits (from v0-selector) can be switched on/off by selecting one // of the process functions -// C++ includes -#include -#include -#include -#include -#include -// other includes + #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" @@ -44,32 +38,37 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsGlobalTracking/RecoContainer.h" -#include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexerParams.h" -#include "DetectorsVertexing/VertexTrackMatcher.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Primitive2D.h" -#include "ReconstructionDataFormats/PrimaryVertex.h" -#include "ReconstructionDataFormats/VtxTrackIndex.h" -#include "ReconstructionDataFormats/VtxTrackRef.h" - -#include "TGeoGlobalMagField.h" - -using std::cout; -using std::endl; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGDQ/TableProducer/tableMakerJpsiHf.cxx b/PWGDQ/TableProducer/tableMakerJpsiHf.cxx index d5690ab7b78..c5569ae7e14 100644 --- a/PWGDQ/TableProducer/tableMakerJpsiHf.cxx +++ b/PWGDQ/TableProducer/tableMakerJpsiHf.cxx @@ -15,7 +15,6 @@ /// \author Fabrizio Grosa , CERN #include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" #include "PWGDQ/Core/HistogramManager.h" #include "PWGDQ/Core/HistogramsLibrary.h" @@ -24,13 +23,29 @@ #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "Common/DataModel/EventSelection.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include #include +#include #include #include diff --git a/PWGDQ/TableProducer/tableMakerMC.cxx b/PWGDQ/TableProducer/tableMakerMC.cxx index e2c529a5a7d..8a2d93f9f89 100644 --- a/PWGDQ/TableProducer/tableMakerMC.cxx +++ b/PWGDQ/TableProducer/tableMakerMC.cxx @@ -26,6 +26,7 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" @@ -35,22 +36,30 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" -#include "TList.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include #include #include #include diff --git a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx index 79e30c2fba8..39cee24788c 100644 --- a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx @@ -27,7 +27,8 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/TriggerAliases.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" @@ -37,24 +38,34 @@ #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" -#include "TList.h" +#include "Tools/ML/MlResponse.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include #include +#include #include #include #include @@ -70,6 +81,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; +using namespace o2::aod::rctsel; // Declare Joins used in the various process functions using MyBarrelTracks = soa::Join multPV; Produces multAll; Produces eventMClabels; + Produces mergingTable; Produces trackBarrelInfo; Produces trackBasic; @@ -178,6 +191,13 @@ struct TableMakerMC { Configurable fConfigMuonCutsJSON{"cfgMuonCutsJSON", "", "Additional list of muon cuts in JSON format"}; } fConfigCuts; + // RCT selection + struct : ConfigurableGroup { + Configurable fConfigUseRCT{"cfgUseRCT", false, "Enable event selection with RCT flags"}; + Configurable fCheckZDC{"cfgCheckZDC", false, "Check ZDC quality in the RCT flag checker"}; + Configurable fConfigRCTLabel{"cfgRCTLabel", "CBT", "RCT flag labels : CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo"}; + } fConfigRCT; + // MC signals to be skimmed Configurable fConfigMCSignals{"cfgMCsignals", "", "Comma separated list of MC signals"}; Configurable fConfigMCSignalsJSON{"cfgMCsignalsJSON", "", "Additional list of MC signals via JSON"}; @@ -208,6 +228,8 @@ struct TableMakerMC { Configurable fGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable fGrpMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fZShiftPath{"zShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable fUseRemoteZShift{"cfgUseRemoteZShift", false, "Enable getting Zshift from ccdb"}; + Configurable fManualZShift{"cfgManualZShift", 0.f, "Manual value for the Zshift for muons."}; Configurable fGrpMagPathRun2{"grpmagPathRun2", "GLO/GRP/GRP", "CCDB path of the GRPObject (Usage for Run 2)"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; } fConfigCCDB; @@ -261,6 +283,39 @@ struct TableMakerMC { std::array cutValues; std::vector cutDirMl; + // RCT flag checker + RCTFlagsChecker rctChecker{"CBT"}; + + // variables to store quantities needed for tagging collision merging candidates + struct { + std::map bimodalityCoeffDCAz; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision + std::map bimodalityCoeffDCAzBinned; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned + std::map bimodalityCoeffDCAzBinnedTrimmed1; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned and trimmed 1 + std::map bimodalityCoeffDCAzBinnedTrimmed2; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned and trimmed 2 + std::map bimodalityCoeffDCAzBinnedTrimmed3; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned and trimmed 3 + std::map meanDCAz; + std::map meanDCAzBinnedTrimmed1; + std::map meanDCAzBinnedTrimmed2; + std::map meanDCAzBinnedTrimmed3; + std::map rmsDCAz; + std::map rmsDCAzBinnedTrimmed1; + std::map rmsDCAzBinnedTrimmed2; + std::map rmsDCAzBinnedTrimmed3; + std::map skewnessDCAz; + std::map kurtosisDCAz; + std::map fraction100umDCAz; // fraction of tracks with |DCAz|>100um + std::map fraction200umDCAz; // fraction of tracks with |DCAz|>200um + std::map fraction500umDCAz; // fraction of tracks with |DCAz|>500um + std::map fraction1mmDCAz; // fraction of tracks with |DCAz|>1mm + std::map fraction2mmDCAz; // fraction of tracks with |DCAz|>2mm + std::map fraction5mmDCAz; // fraction of tracks with |DCAz|>5mm + std::map fraction10mmDCAz; // fraction of tracks with |DCAz|>10mm + std::map nPeaksDCAz; // number of peaks in the DCAz distribution of tracks associated to a collision + std::map nPeaksDCAzTrimmed1; // number of peaks in the binned DCAz distribution (trimmed 1) + std::map nPeaksDCAzTrimmed2; // number of peaks in the binned DCAz distribution (trimmed 2) + std::map nPeaksDCAzTrimmed3; // number of peaks in the binned DCAz distribution (trimmed 3) + } fCollMergingTag; + void init(o2::framework::InitContext& context) { // Check whether barrel or muon are enabled @@ -398,6 +453,10 @@ struct TableMakerMC { matchingMlResponse.cacheInputFeaturesIndices(fConfigVariousOptions.fInputFeatures.value); matchingMlResponse.init(); } + + if (fConfigRCT.fConfigUseRCT.value) { + rctChecker.init(fConfigRCT.fConfigRCTLabel, fConfigRCT.fCheckZDC.value); + } } void DefineCuts() @@ -456,6 +515,8 @@ struct TableMakerMC { Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; Preslice mfttrackIndicesPerCollision = aod::track_association::collisionId; + Preslice presliceBarrelTracksWithCov = aod::track_association::collisionId; + void skimMCCollisions(MyEventsMcWithMults const& mcCollisions) { // skim MC collisions @@ -566,6 +627,72 @@ struct TableMakerMC { } // end loop over mc stack } + template + void computeCollMergingTag(TEvents const& collisions, TTracks const& tracks, Preslice& preslice) + { + // this function uses the standard track - collision association to compute several quantities which could be related to collision merging + // clear the maps for this time frame + fCollMergingTag.bimodalityCoeffDCAz.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinned.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed1.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed2.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed3.clear(); + fCollMergingTag.meanDCAz.clear(); + fCollMergingTag.meanDCAzBinnedTrimmed1.clear(); + fCollMergingTag.meanDCAzBinnedTrimmed2.clear(); + fCollMergingTag.meanDCAzBinnedTrimmed3.clear(); + fCollMergingTag.rmsDCAz.clear(); + fCollMergingTag.rmsDCAzBinnedTrimmed1.clear(); + fCollMergingTag.rmsDCAzBinnedTrimmed2.clear(); + fCollMergingTag.rmsDCAzBinnedTrimmed3.clear(); + fCollMergingTag.skewnessDCAz.clear(); + fCollMergingTag.kurtosisDCAz.clear(); + fCollMergingTag.fraction100umDCAz.clear(); + fCollMergingTag.fraction200umDCAz.clear(); + fCollMergingTag.fraction500umDCAz.clear(); + fCollMergingTag.fraction1mmDCAz.clear(); + fCollMergingTag.fraction2mmDCAz.clear(); + fCollMergingTag.fraction5mmDCAz.clear(); + fCollMergingTag.fraction10mmDCAz.clear(); + fCollMergingTag.nPeaksDCAz.clear(); + fCollMergingTag.nPeaksDCAzTrimmed1.clear(); + fCollMergingTag.nPeaksDCAzTrimmed2.clear(); + fCollMergingTag.nPeaksDCAzTrimmed3.clear(); + + for (const auto& collision : collisions) { + // make a slice for this collision and compute the DCAz based event quantities + auto thisCollTracks = tracks.sliceBy(preslice, collision.globalIndex()); + VarManager::FillEventTracks(thisCollTracks); // fill the VarManager arrays with the information of the tracks associated to this collision, needed for the cuts and histograms + // add the computed variables to the maps with the collision index as key + fCollMergingTag.bimodalityCoeffDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficient]; + fCollMergingTag.bimodalityCoeffDCAzBinned[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinned]; + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1]; + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2]; + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3]; + fCollMergingTag.meanDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMean]; + fCollMergingTag.meanDCAzBinnedTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMeanBinnedTrimmed1]; + fCollMergingTag.meanDCAzBinnedTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMeanBinnedTrimmed2]; + fCollMergingTag.meanDCAzBinnedTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMeanBinnedTrimmed3]; + fCollMergingTag.rmsDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMS]; + fCollMergingTag.rmsDCAzBinnedTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMSBinnedTrimmed1]; + fCollMergingTag.rmsDCAzBinnedTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMSBinnedTrimmed2]; + fCollMergingTag.rmsDCAzBinnedTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMSBinnedTrimmed3]; + fCollMergingTag.skewnessDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzSkewness]; + fCollMergingTag.kurtosisDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzKurtosis]; + fCollMergingTag.fraction100umDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove100um]; + fCollMergingTag.fraction200umDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove200um]; + fCollMergingTag.fraction500umDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove500um]; + fCollMergingTag.fraction1mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove1mm]; + fCollMergingTag.fraction2mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove2mm]; + fCollMergingTag.fraction5mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove5mm]; + fCollMergingTag.fraction10mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove10mm]; + fCollMergingTag.nPeaksDCAz[collision.globalIndex()] = static_cast(VarManager::fgValues[VarManager::kDCAzNPeaks]); + fCollMergingTag.nPeaksDCAzTrimmed1[collision.globalIndex()] = static_cast(VarManager::fgValues[VarManager::kDCAzNPeaksTrimmed1]); + fCollMergingTag.nPeaksDCAzTrimmed2[collision.globalIndex()] = static_cast(VarManager::fgValues[VarManager::kDCAzNPeaksTrimmed2]); + fCollMergingTag.nPeaksDCAzTrimmed3[collision.globalIndex()] = static_cast(VarManager::fgValues[VarManager::kDCAzNPeaksTrimmed3]); + } + } + template void skimCollisions(TEvents const& collisions, BCsWithTimestamps const& /*bcs*/) { @@ -634,7 +761,7 @@ struct TableMakerMC { (reinterpret_cast(fStatsList->At(0)))->Fill(2.0, static_cast(o2::aod::evsel::kNsel)); // Apply the user specified event selection - if (!fEventCut->IsSelected(VarManager::fgValues)) { + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !(rctChecker(collision)))) { continue; } @@ -682,6 +809,17 @@ struct TableMakerMC { 0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0.0, 0.0, 0.0, 0.0); } + mergingTable(fCollMergingTag.bimodalityCoeffDCAz[collision.globalIndex()], fCollMergingTag.bimodalityCoeffDCAzBinned[collision.globalIndex()], + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed1[collision.globalIndex()], fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed2[collision.globalIndex()], fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed3[collision.globalIndex()], + fCollMergingTag.meanDCAz[collision.globalIndex()], fCollMergingTag.meanDCAzBinnedTrimmed1[collision.globalIndex()], fCollMergingTag.meanDCAzBinnedTrimmed2[collision.globalIndex()], fCollMergingTag.meanDCAzBinnedTrimmed3[collision.globalIndex()], + fCollMergingTag.rmsDCAz[collision.globalIndex()], fCollMergingTag.rmsDCAzBinnedTrimmed1[collision.globalIndex()], fCollMergingTag.rmsDCAzBinnedTrimmed2[collision.globalIndex()], fCollMergingTag.rmsDCAzBinnedTrimmed3[collision.globalIndex()], + fCollMergingTag.skewnessDCAz[collision.globalIndex()], fCollMergingTag.kurtosisDCAz[collision.globalIndex()], + fCollMergingTag.fraction100umDCAz[collision.globalIndex()], fCollMergingTag.fraction200umDCAz[collision.globalIndex()], + fCollMergingTag.fraction500umDCAz[collision.globalIndex()], fCollMergingTag.fraction1mmDCAz[collision.globalIndex()], + fCollMergingTag.fraction2mmDCAz[collision.globalIndex()], fCollMergingTag.fraction5mmDCAz[collision.globalIndex()], + fCollMergingTag.fraction10mmDCAz[collision.globalIndex()], fCollMergingTag.nPeaksDCAz[collision.globalIndex()], fCollMergingTag.nPeaksDCAzTrimmed1[collision.globalIndex()], + fCollMergingTag.nPeaksDCAzTrimmed2[collision.globalIndex()], fCollMergingTag.nPeaksDCAzTrimmed3[collision.globalIndex()]); + // add an element for this collision into the map fCollIndexMap[collision.globalIndex()] = event.lastIndex(); } @@ -1180,13 +1318,19 @@ struct TableMakerMC { } } else { fGrpMag = fCCDB->getForTimeStamp(fConfigCCDB.fGrpMagPath, bcs.begin().timestamp()); - auto* fZShift = fCCDB->getForTimeStamp>(fConfigCCDB.fZShiftPath, bcs.begin().timestamp()); if (fGrpMag != nullptr) { o2::base::Propagator::initFieldFromGRP(fGrpMag); VarManager::SetMagneticField(fGrpMag->getNominalL3Field()); } - if (fZShift != nullptr && !fZShift->empty()) { - VarManager::SetZShift((*fZShift)[0]); + if (fConfigCCDB.fUseRemoteZShift) { + auto* fZShift = fCCDB->getForTimeStamp>(fConfigCCDB.fZShiftPath, bcs.begin().timestamp()); + if (fZShift != nullptr && !fZShift->empty()) { + VarManager::SetZShift((*fZShift)[0]); + } else { + LOG(fatal) << "Could not retrieve Z-shift value from CCDB"; + } + } else { + VarManager::SetZShift(fConfigCCDB.fManualZShift.value); } if (fConfigVariousOptions.fPropMuon) { VarManager::SetupMuonMagField(); @@ -1498,6 +1642,7 @@ struct TableMakerMC { MyBarrelTracksWithCov const& tracksBarrel, aod::TrackAssoc const& trackAssocs, MyEventsMcWithMults const& mcCollisions, aod::McParticles const& mcParticles) { + computeCollMergingTag(collisions, tracksBarrel, presliceBarrelTracksWithCov); fullSkimming(collisions, bcs, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, mcCollisions, mcParticles, nullptr); } @@ -1505,6 +1650,7 @@ struct TableMakerMC { MyBarrelTracksWithCov const& tracksBarrel, aod::TrackAssoc const& trackAssocs, MyEventsMcWithMults const& mcCollisions, aod::McParticles const& mcParticles) { + computeCollMergingTag(collisions, tracksBarrel, presliceBarrelTracksWithCov); fullSkimming(collisions, bcs, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, mcCollisions, mcParticles, nullptr); } diff --git a/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx b/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx index 11634be2e0d..84d9a42bbbc 100644 --- a/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx +++ b/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx @@ -19,34 +19,37 @@ /// \author Zaida Conesa del Valle /// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TDatabasePDG.h" -// -#include "Common/DataModel/TrackSelectionTables.h" -// -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" -// -#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" #include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGDQ/DataModel/MchTrkEffTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 55dc0a539b3..3a32c5ca24a 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -17,14 +17,7 @@ // The skimming can optionally produce just the barrel, muon, or both barrel and muon tracks // The event filtering, centrality, and V0Bits (from v0-selector) can be switched on/off by selecting one // of the process functions -// C++ includes -#include -#include -#include -#include -#include -#include -// other includes + #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" @@ -34,49 +27,69 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/TriggerAliases.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "Common/Core/TableHelper.h" #include "Common/Core/Zorro.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FwdTrackReAlignTables.h" -#include "Common/DataModel/MftmchMatchingML.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsGlobalTracking/RecoContainer.h" -#include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexerParams.h" -#include "DetectorsVertexing/VertexTrackMatcher.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Primitive2D.h" -#include "ReconstructionDataFormats/PrimaryVertex.h" -#include "ReconstructionDataFormats/VtxTrackIndex.h" -#include "ReconstructionDataFormats/VtxTrackRef.h" - -#include "TGeoGlobalMagField.h" +#include "Tools/ML/MlResponse.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; +using namespace o2::aod::rctsel; Zorro zorro; @@ -174,6 +187,7 @@ struct TableMaker { Produces fit; Produces multPV; Produces multAll; + Produces mergingTable; Produces trackBarrelInfo; Produces trackBasic; Produces trackBarrel; @@ -204,6 +218,13 @@ struct TableMaker { Configurable fConfigMuonCutsJSON{"cfgMuonCutsJSON", "", "Additional list of muon cuts in JSON format"}; } fConfigCuts; + // RCT selection + struct : ConfigurableGroup { + Configurable fConfigUseRCT{"cfgUseRCT", false, "Enable event selection with RCT flags"}; + Configurable fCheckZDC{"cfgCheckZDC", false, "Check ZDC quality in the RCT flag checker"}; + Configurable fConfigRCTLabel{"cfgRCTLabel", "CBT", "RCT flag labels : CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo"}; + } fConfigRCT; + // Zorro selection struct : ConfigurableGroup { Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro"}; @@ -247,6 +268,8 @@ struct TableMaker { Configurable fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable fConfigGrpMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fZShiftPath{"zShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable fUseRemoteZShift{"cfgUseRemoteZShift", false, "Enable getting Zshift from ccdb"}; + Configurable fManualZShift{"cfgManualZShift", 0.f, "Manual value for the Zshift for muons."}; Configurable fConfigGrpMagPathRun2{"grpmagPathRun2", "GLO/GRP/GRP", "CCDB path of the GRPObject (Usage for Run 2)"}; } fConfigCCDB; @@ -312,6 +335,9 @@ struct TableMaker { std::array cutValues; std::vector cutDirMl; + // RCT flag checker + RCTFlagsChecker rctChecker{"CBT"}; + // FIXME: For now, the skimming is done using the Common track-collision association task, which does not allow to use // our own Filtered tracks. If the filter is very selective, then it may be worth to run the association in this workflow // using the Common/CollisionAssociation class @@ -361,6 +387,36 @@ struct TableMaker { std::map oContribLongC; } fOccup; + // variables to store quantities needed for tagging collision merging candidates + struct { + std::map bimodalityCoeffDCAz; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision + std::map bimodalityCoeffDCAzBinned; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned + std::map bimodalityCoeffDCAzBinnedTrimmed1; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned and trimmed 1 + std::map bimodalityCoeffDCAzBinnedTrimmed2; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned and trimmed 2 + std::map bimodalityCoeffDCAzBinnedTrimmed3; // Bimodality coefficient of the DCAz distribution of tracks associated to a collision, binned and trimmed 3 + std::map meanDCAz; + std::map meanDCAzBinnedTrimmed1; + std::map meanDCAzBinnedTrimmed2; + std::map meanDCAzBinnedTrimmed3; + std::map rmsDCAz; + std::map rmsDCAzBinnedTrimmed1; + std::map rmsDCAzBinnedTrimmed2; + std::map rmsDCAzBinnedTrimmed3; + std::map skewnessDCAz; + std::map kurtosisDCAz; + std::map fraction100umDCAz; // fraction of tracks with |DCAz|>100um + std::map fraction200umDCAz; // fraction of tracks with |DCAz|>200um + std::map fraction500umDCAz; // fraction of tracks with |DCAz|>500um + std::map fraction1mmDCAz; // fraction of tracks with |DCAz|>1mm + std::map fraction2mmDCAz; // fraction of tracks with |DCAz|>2mm + std::map fraction5mmDCAz; // fraction of tracks with |DCAz|>5mm + std::map fraction10mmDCAz; // fraction of tracks with |DCAz|>10mm + std::map nPeaksDCAz; // number of peaks in the DCAz distribution of tracks associated to a collision + std::map nPeaksDCAzTrimmed1; // number of peaks in the binned DCAz distribution (trimmed 1) + std::map nPeaksDCAzTrimmed2; // number of peaks in the binned DCAz distribution (trimmed 2) + std::map nPeaksDCAzTrimmed3; // number of peaks in the binned DCAz distribution (trimmed 3) + } fCollMergingTag; + void init(o2::framework::InitContext& context) { // CCDB configuration @@ -467,6 +523,10 @@ struct TableMaker { matchingMlResponse.cacheInputFeaturesIndices(fConfigVariousOptions.fInputFeatures.value); matchingMlResponse.init(); } + + if (fConfigRCT.fConfigUseRCT.value) { + rctChecker.init(fConfigRCT.fConfigRCTLabel, fConfigRCT.fCheckZDC.value); + } } void DefineCuts() @@ -814,20 +874,15 @@ struct TableMaker { // Function to compute the mu for pileup estimation, taken from EM code double calculateMu(const auto& bc) { - auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); - uint64_t timeStamp = bc.timestamp(); - std::map metadata; - mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); - auto bfilling = mLHCIFdata->getBunchFilling(); double nbc = bfilling.getFilledBCs().size(); double tvxRate; if (fConfigHistOutput.fConfigIrEstimator.value.empty()) { - tvxRate = mRateFetcher.fetch(&ccdbMgr, timeStamp, bc.runNumber(), "T0VTX"); + tvxRate = mRateFetcher.fetch(fCCDB.service, timeStamp, bc.runNumber(), "T0VTX"); } else { - tvxRate = mRateFetcher.fetch(&ccdbMgr, timeStamp, bc.runNumber(), fConfigHistOutput.fConfigIrEstimator.value); + tvxRate = mRateFetcher.fetch(fCCDB.service, timeStamp, bc.runNumber(), fConfigHistOutput.fConfigIrEstimator.value); } double nTriggersPerFilledBC = tvxRate / nbc / o2::constants::lhc::LHCRevFreq; @@ -835,6 +890,72 @@ struct TableMaker { return mu; } + template + void computeCollMergingTag(TEvents const& collisions, TTracks const& tracks, Preslice& preslice) + { + // This function uses the standard track-collision association to compute quantities related to collision merging + // clear the maps for this time frame + fCollMergingTag.bimodalityCoeffDCAz.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinned.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed1.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed2.clear(); + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed3.clear(); + fCollMergingTag.meanDCAz.clear(); + fCollMergingTag.meanDCAzBinnedTrimmed1.clear(); + fCollMergingTag.meanDCAzBinnedTrimmed2.clear(); + fCollMergingTag.meanDCAzBinnedTrimmed3.clear(); + fCollMergingTag.rmsDCAz.clear(); + fCollMergingTag.rmsDCAzBinnedTrimmed1.clear(); + fCollMergingTag.rmsDCAzBinnedTrimmed2.clear(); + fCollMergingTag.rmsDCAzBinnedTrimmed3.clear(); + fCollMergingTag.skewnessDCAz.clear(); + fCollMergingTag.kurtosisDCAz.clear(); + fCollMergingTag.fraction100umDCAz.clear(); + fCollMergingTag.fraction200umDCAz.clear(); + fCollMergingTag.fraction500umDCAz.clear(); + fCollMergingTag.fraction1mmDCAz.clear(); + fCollMergingTag.fraction2mmDCAz.clear(); + fCollMergingTag.fraction5mmDCAz.clear(); + fCollMergingTag.fraction10mmDCAz.clear(); + fCollMergingTag.nPeaksDCAz.clear(); + fCollMergingTag.nPeaksDCAzTrimmed1.clear(); + fCollMergingTag.nPeaksDCAzTrimmed2.clear(); + fCollMergingTag.nPeaksDCAzTrimmed3.clear(); + + for (const auto& collision : collisions) { + // make a slice for this collision and compute the DCAz based event quantities + auto thisCollTracks = tracks.sliceBy(preslice, collision.globalIndex()); + VarManager::FillEventTracks(thisCollTracks); // fill the VarManager arrays with the information of the tracks associated to this collision, needed for the cuts and histograms + // add the computed variables to the maps with the collision index as key + fCollMergingTag.bimodalityCoeffDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficient]; + fCollMergingTag.bimodalityCoeffDCAzBinned[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinned]; + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinnedTrimmed1]; + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinnedTrimmed2]; + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzBimodalityCoefficientBinnedTrimmed3]; + fCollMergingTag.meanDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMean]; + fCollMergingTag.meanDCAzBinnedTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMeanBinnedTrimmed1]; + fCollMergingTag.meanDCAzBinnedTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMeanBinnedTrimmed2]; + fCollMergingTag.meanDCAzBinnedTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzMeanBinnedTrimmed3]; + fCollMergingTag.rmsDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMS]; + fCollMergingTag.rmsDCAzBinnedTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMSBinnedTrimmed1]; + fCollMergingTag.rmsDCAzBinnedTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMSBinnedTrimmed2]; + fCollMergingTag.rmsDCAzBinnedTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzRMSBinnedTrimmed3]; + fCollMergingTag.skewnessDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzSkewness]; + fCollMergingTag.kurtosisDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzKurtosis]; + fCollMergingTag.fraction100umDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove100um]; + fCollMergingTag.fraction200umDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove200um]; + fCollMergingTag.fraction500umDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove500um]; + fCollMergingTag.fraction1mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove1mm]; + fCollMergingTag.fraction2mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove2mm]; + fCollMergingTag.fraction5mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove5mm]; + fCollMergingTag.fraction10mmDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzFracAbove10mm]; + fCollMergingTag.nPeaksDCAz[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzNPeaks]; + fCollMergingTag.nPeaksDCAzTrimmed1[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzNPeaksTrimmed1]; + fCollMergingTag.nPeaksDCAzTrimmed2[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzNPeaksTrimmed2]; + fCollMergingTag.nPeaksDCAzTrimmed3[collision.globalIndex()] = VarManager::fgValues[VarManager::kDCAzNPeaksTrimmed3]; + } + } + template void skimCollisions(TEvents const& collisions, TBCs const& bcs, TZdcs const& /*zdcs*/, @@ -977,6 +1098,7 @@ struct TableMaker { VarManager::fgValues[VarManager::kNTPCmedianTimeShortA] = fOccup.oMedianTimeShortA[collision.globalIndex()]; VarManager::fgValues[VarManager::kNTPCmedianTimeShortC] = fOccup.oMedianTimeShortC[collision.globalIndex()]; } + if (fDoDetailedQA) { fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); } @@ -995,7 +1117,7 @@ struct TableMaker { zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), fConfigZorro.fConfigZorroTrigMask.value); zorro.populateExternalHists(fCurrentRun, reinterpret_cast(fStatsList->At(kStatsZorroInfo)), reinterpret_cast(fStatsList->At(kStatsZorroSel))); - if (!fEventCut->IsSelected(VarManager::fgValues)) { + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !rctChecker(collision))) { continue; } @@ -1007,7 +1129,7 @@ struct TableMaker { continue; } } else { - if (!fEventCut->IsSelected(VarManager::fgValues)) { + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !rctChecker(collision))) { continue; } } @@ -1102,7 +1224,19 @@ struct TableMaker { fOccup.oMeanTimeShortA[collision.globalIndex()], fOccup.oMeanTimeShortC[collision.globalIndex()], fOccup.oMedianTimeShortA[collision.globalIndex()], fOccup.oMedianTimeShortC[collision.globalIndex()]); } - + mergingTable(fCollMergingTag.bimodalityCoeffDCAz[collision.globalIndex()], fCollMergingTag.bimodalityCoeffDCAzBinned[collision.globalIndex()], + fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed1[collision.globalIndex()], fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed2[collision.globalIndex()], fCollMergingTag.bimodalityCoeffDCAzBinnedTrimmed3[collision.globalIndex()], + fCollMergingTag.meanDCAz[collision.globalIndex()], fCollMergingTag.meanDCAzBinnedTrimmed1[collision.globalIndex()], fCollMergingTag.meanDCAzBinnedTrimmed2[collision.globalIndex()], fCollMergingTag.meanDCAzBinnedTrimmed3[collision.globalIndex()], + fCollMergingTag.rmsDCAz[collision.globalIndex()], fCollMergingTag.rmsDCAzBinnedTrimmed1[collision.globalIndex()], fCollMergingTag.rmsDCAzBinnedTrimmed2[collision.globalIndex()], fCollMergingTag.rmsDCAzBinnedTrimmed3[collision.globalIndex()], + fCollMergingTag.skewnessDCAz[collision.globalIndex()], fCollMergingTag.kurtosisDCAz[collision.globalIndex()], + fCollMergingTag.fraction100umDCAz[collision.globalIndex()], fCollMergingTag.fraction200umDCAz[collision.globalIndex()], + fCollMergingTag.fraction500umDCAz[collision.globalIndex()], fCollMergingTag.fraction1mmDCAz[collision.globalIndex()], + fCollMergingTag.fraction2mmDCAz[collision.globalIndex()], fCollMergingTag.fraction5mmDCAz[collision.globalIndex()], + fCollMergingTag.fraction10mmDCAz[collision.globalIndex()], + fCollMergingTag.nPeaksDCAz[collision.globalIndex()], fCollMergingTag.nPeaksDCAzTrimmed1[collision.globalIndex()], + fCollMergingTag.nPeaksDCAzTrimmed2[collision.globalIndex()], fCollMergingTag.nPeaksDCAzTrimmed3[collision.globalIndex()]); + + // fCollIndexMap[collision.globalIndex()] = event.lastIndex(); } } @@ -1560,13 +1694,22 @@ struct TableMaker { } } else { fGrpMag = fCCDB->getForTimeStamp(fConfigCCDB.fConfigGrpMagPath, bcs.begin().timestamp()); - auto* fZShift = fCCDB->getForTimeStamp>(fConfigCCDB.fZShiftPath, bcs.begin().timestamp()); if (fGrpMag != nullptr) { o2::base::Propagator::initFieldFromGRP(fGrpMag); VarManager::SetMagneticField(fGrpMag->getNominalL3Field()); } - if (fZShift != nullptr && !fZShift->empty()) { - VarManager::SetZShift((*fZShift)[0]); + if (fConfigCCDB.fUseRemoteZShift) { + auto* fZShift = fCCDB->getForTimeStamp>(fConfigCCDB.fZShiftPath, bcs.begin().timestamp()); + if (fZShift != nullptr && !fZShift->empty()) { + VarManager::SetZShift((*fZShift)[0]); + } else { + LOG(fatal) << "Could not retrieve Z-shift value from CCDB"; + } + } else { + VarManager::SetZShift(fConfigCCDB.fManualZShift.value); + } + if (fConfigHistOutput.fConfigFillBcStat) { + mLHCIFdata = fCCDB->getSpecific("GLO/Config/GRPLHCIF", bcs.begin().timestamp()); } if (fConfigVariousOptions.fPropMuon) { VarManager::SetupMuonMagField(); @@ -1763,6 +1906,8 @@ struct TableMaker { MyBarrelTracksWithCov const& tracksBarrel, TrackAssoc const& trackAssocs) { + computeOccupancyEstimators(collisions, tracksPosWithCov, tracksNegWithCov, presliceWithCov, bcs); + computeCollMergingTag(collisions, tracksBarrel, presliceWithCov); fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } @@ -1772,6 +1917,7 @@ struct TableMaker { TrackAssoc const& trackAssocs) { computeOccupancyEstimators(collisions, tracksPosWithCovNoTOF, tracksNegWithCovNoTOF, presliceWithCovNoTOF, bcs); + computeCollMergingTag(collisions, tracksBarrel, presliceWithCovNoTOF); fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } @@ -1781,6 +1927,7 @@ struct TableMaker { TrackAssoc const& trackAssocs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { computeOccupancyEstimators(collisions, tracksPosWithCov, tracksNegWithCov, presliceWithCov, bcs); + computeCollMergingTag(collisions, tracksBarrel, presliceWithCov); fullSkimming(collisions, bcs, zdcs, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, ft0s, fv0as, fdds); } @@ -1790,6 +1937,7 @@ struct TableMaker { TrackAssoc const& trackAssocs) { computeOccupancyEstimators(collisions, tracksPos, tracksNeg, preslice, bcs); + computeCollMergingTag(collisions, tracksBarrel, preslice); fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } @@ -1799,6 +1947,7 @@ struct TableMaker { TrackAssoc const& trackAssocs) { computeOccupancyEstimators(collisions, tracksPosNoTOF, tracksNegNoTOF, presliceNoTOF, bcs); + computeCollMergingTag(collisions, tracksBarrel, presliceNoTOF); fullSkimming(collisions, bcs, nullptr, tracksBarrel, nullptr, nullptr, trackAssocs, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); } diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index f052e2586a5..4bb0cf6d714 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(table-reader-with-assoc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(table-reader-with-assoc-direct + SOURCES tableReader_withAssoc_direct.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(efficiency SOURCES dqEfficiency.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore @@ -31,6 +36,11 @@ o2physics_add_dpl_workflow(efficiency-with-assoc o2physics_add_dpl_workflow(efficiency-with-assoc-direct SOURCES dqEfficiency_withAssoc_direct.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(energy-correlator-direct + SOURCES dqEnergyCorrelator_direct.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) @@ -116,7 +126,7 @@ o2physics_add_dpl_workflow(task-fwd-track-pid o2physics_add_dpl_workflow(quarkonia-to-hyperons SOURCES quarkoniaToHyperons.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2::Framework O2::DCAFitter KFParticle::KFParticle O2Physics::AnalysisCore O2Physics::MLCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(model-converter-mult-pv @@ -143,3 +153,13 @@ o2physics_add_dpl_workflow(qa-matching SOURCES qaMatching.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(mft-mch-matcher + SOURCES mftMchMatcher.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(muon-global-alignment + SOURCES muonGlobalAlignment.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2::MCHGeometryTransformer + COMPONENT_NAME Analysis) diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index 4312434c2e6..c3768b02918 100644 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -21,22 +21,31 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/TriggerAliases.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include #include #include #include @@ -47,7 +56,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; using namespace o2::soa; -using std::array; using MyEvents = soa::Join; diff --git a/PWGDQ/Tasks/MIDefficiency.cxx b/PWGDQ/Tasks/MIDefficiency.cxx index 3dcbcc4d595..26bca045c2b 100644 --- a/PWGDQ/Tasks/MIDefficiency.cxx +++ b/PWGDQ/Tasks/MIDefficiency.cxx @@ -18,25 +18,25 @@ /// /// \author Luca Quaglia - -// O2 physics classes #include "PWGDQ/DataModel/ReducedInfoTables.h" -// O2 -#include "DataFormatsMID/Track.h" //MID track from O2 -#include "Framework/Variant.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/CompletionPolicyHelpers.h" - -#include "MIDEfficiency/Efficiency.h" -#include "MIDBase/DetectorParameters.h" -#include "MIDBase/Mapping.h" +#include //MID track from O2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include using namespace o2; using namespace o2::aod; diff --git a/PWGDQ/Tasks/ModelConverterEventExtended.cxx b/PWGDQ/Tasks/ModelConverterEventExtended.cxx index ec0a6a0c4be..b73eb3ea581 100644 --- a/PWGDQ/Tasks/ModelConverterEventExtended.cxx +++ b/PWGDQ/Tasks/ModelConverterEventExtended.cxx @@ -14,18 +14,12 @@ // Task used to convert the data model from the old format to the new format. To avoid // the conflict with the old data model. -// other includes #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include -#include -#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGDQ/Tasks/ModelConverterMultPv.cxx b/PWGDQ/Tasks/ModelConverterMultPv.cxx index 088590435b8..e844a1bd104 100644 --- a/PWGDQ/Tasks/ModelConverterMultPv.cxx +++ b/PWGDQ/Tasks/ModelConverterMultPv.cxx @@ -14,17 +14,14 @@ // Task used to convert the data model from the old format to the new format. To avoid // the conflict with the old data model. -// other includes -#include -#include -#include -#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 +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGDQ/Tasks/ModelConverterReducedMCEvents.cxx b/PWGDQ/Tasks/ModelConverterReducedMCEvents.cxx index f4e28daee31..634c291cf9e 100644 --- a/PWGDQ/Tasks/ModelConverterReducedMCEvents.cxx +++ b/PWGDQ/Tasks/ModelConverterReducedMCEvents.cxx @@ -14,18 +14,12 @@ // Task used to convert the data model from the old format to the new format. To avoid // the conflict with the old data model. -// other includes #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include -#include -#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGDQ/Tasks/TagAndProbe.cxx b/PWGDQ/Tasks/TagAndProbe.cxx index 2a35b33b87e..b637ec64aad 100644 --- a/PWGDQ/Tasks/TagAndProbe.cxx +++ b/PWGDQ/Tasks/TagAndProbe.cxx @@ -12,57 +12,41 @@ /// \file TagAndProbe.cxx /// \brief Task Tag-And-Probe matching efficiency studies -#include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/AnalysisCut.h" -#include "PWGDQ/Core/CutsLibrary.h" #include "PWGDQ/Core/HistogramManager.h" #include "PWGDQ/Core/HistogramsLibrary.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/MixingLibrary.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TableHelper.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" -#include "ITSMFTBase/DPLAlpideParam.h" - -#include "TGeoGlobalMagField.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include -#include -#include #include -#include +#include + #include #include +#include #include #include #include #include -#include -#include #include -#include #include using std::cout; -using std::endl; using std::string; using namespace o2; diff --git a/PWGDQ/Tasks/dqCorrelation.cxx b/PWGDQ/Tasks/dqCorrelation.cxx index f6ba8f3bd39..890bdefe46b 100644 --- a/PWGDQ/Tasks/dqCorrelation.cxx +++ b/PWGDQ/Tasks/dqCorrelation.cxx @@ -13,48 +13,43 @@ // #include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" -#include "PWGCF/GenericFramework/Core/GFWCumulant.h" -#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" -#include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" -#include "PWGDQ/Core/CutsLibrary.h" -#include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/HistogramsLibrary.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/MixingLibrary.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" -#include "TProfile.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include -#include +#include +#include #include #include -#include +#include + +#include + +#include #include -#include +#include #include #include #include -using std::cout; -using std::endl; using std::string; using namespace o2; diff --git a/PWGDQ/Tasks/dqEfficiency.cxx b/PWGDQ/Tasks/dqEfficiency.cxx index 3f97216f52d..45e84b4c3e4 100644 --- a/PWGDQ/Tasks/dqEfficiency.cxx +++ b/PWGDQ/Tasks/dqEfficiency.cxx @@ -23,26 +23,29 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/GeometryManager.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include +#include + +#include #include -#include #include #include #include -using std::cout; -using std::endl; using std::string; using namespace o2; @@ -864,7 +867,8 @@ struct AnalysisSameEventPairing { t2.reducedMCTrack().pt(), t2.reducedMCTrack().eta(), t2.reducedMCTrack().phi(), t2.reducedMCTrack().e(), t1.reducedMCTrack().vx(), t1.reducedMCTrack().vy(), t1.reducedMCTrack().vz(), t1.reducedMCTrack().vt(), t2.reducedMCTrack().vx(), t2.reducedMCTrack().vy(), t2.reducedMCTrack().vz(), t2.reducedMCTrack().vt(), - t1.isAmbiguous(), t2.isAmbiguous(), -999., -999., -999., -999., -999., -999., -999., -999., -999., + t1.isAmbiguous(), t2.isAmbiguous(), true, true, + -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., VarManager::fgValues[VarManager::kVertexingPz], VarManager::fgValues[VarManager::kVertexingSV]); } diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 9a6babaee92..62d9bc01b32 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -26,28 +26,39 @@ #include "Common/Core/TableHelper.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include +#include +#include #include #include +#include + #include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include @@ -62,6 +73,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; +using namespace o2::common::core; // Some definitions namespace o2::aod @@ -961,7 +973,7 @@ struct AnalysisMuonSelection { for (auto& assoc : assocs) { auto event = assoc.template reducedevent_as(); - if (!event.isEventSelected_bit(0)) { + if (!event.has_reducedMCevent() || !event.isEventSelected_bit(0)) { // condition on reducedMCevent to avoid rec. events with no generated event muonSel(0); continue; } @@ -1325,6 +1337,7 @@ struct AnalysisSameEventPairing { Produces dileptonInfoList; Produces PromptNonPromptSepTable; Produces MCTruthTableEffi; + Produces dileptonPolarList; o2::base::MatLayerCylSet* fLUT = nullptr; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. @@ -1335,7 +1348,7 @@ struct AnalysisSameEventPairing { Configurable track{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable muon{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; Configurable pair{"cfgPairCuts", "", "Comma separated list of pair cuts, !!! Use only if you know what you are doing, otherwise leave empty"}; - Configurable MCgenAcc{"cfgMCGenAccCut", "", "cut for MC generated particles acceptance"}; + Configurable MCgenAcc{"cfgMCGenAccCuts", "", "Comma separated list of MC generated particles acceptance cuts, !!! Use only if you know what you are doing, otherwise leave empty"}; // TODO: Add pair cuts via JSON } fConfigCuts; @@ -1354,6 +1367,7 @@ struct AnalysisSameEventPairing { Configurable useRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; Configurable magField{"cfgMagField", 5.0f, "Manually set magnetic field"}; Configurable flatTables{"cfgFlatTables", false, "Produce a single flat tables with all relevant information of the pairs and single tracks"}; + Configurable polarTables{"cfgPolarTables", false, "Produce tables with dilepton polarization information"}; Configurable useKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; Configurable useAbsDCA{"cfgUseAbsDCA", false, "Use absolute DCA minimization instead of chi^2 minimization in secondary vertexing"}; Configurable propToPCA{"cfgPropToPCA", false, "Propagate tracks to secondary vertex"}; @@ -1368,6 +1382,7 @@ struct AnalysisSameEventPairing { Configurable genSignalsJSON{"cfgMCGenSignalsJSON", "", "Additional list of MC signals (generated) via JSON"}; Configurable recSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; Configurable recSignalsJSON{"cfgMCRecSignalsJSON", "", "Comma separated list of MC signals (reconstructed) via JSON"}; + Configurable finalStateSignals{"cfgBarrelMCFinalStateSignals", "eFromJpsi", "Comma separated list of MC signals (final state particles)"}; Configurable skimSignalOnly{"cfgSkimSignalOnly", false, "Configurable to select only matched candidates"}; } fConfigMC; @@ -1394,9 +1409,10 @@ struct AnalysisSameEventPairing { std::map> fMuonHistNamesMCmatched; std::vector fRecMCSignals; std::vector fGenMCSignals; + std::vector fFinalStateMCSignals; std::vector fPairCuts; - AnalysisCompositeCut fMCGenAccCut; + std::vector fMCGenAccCuts; bool fUseMCGenAccCut = false; uint32_t fTrackFilterMask; // mask for the track cuts required in this task to be applied on the barrel cuts produced upstream @@ -1485,16 +1501,6 @@ struct AnalysisSameEventPairing { } } - // get the mc generated acceptance cut - TString mcGenAccCutStr = fConfigCuts.MCgenAcc.value; - if (mcGenAccCutStr != "") { - AnalysisCut* cut = dqcuts::GetAnalysisCut(mcGenAccCutStr.Data()); - if (cut != nullptr) { - fMCGenAccCut.AddCut(cut); - } - fUseMCGenAccCut = true; - } - // check that the barrel track cuts array required in this task is not empty if (!trackCutsStr.IsNull()) { // tokenize and loop over the barrel cuts produced by the barrel track selection task @@ -1663,6 +1669,19 @@ struct AnalysisSameEventPairing { } // end loop over cuts } // end if (muonCutsStr) + // get the mc generated acceptance cuts + TString mcgenCutsStr = fConfigCuts.MCgenAcc.value; + if (!mcgenCutsStr.IsNull()) { + std::unique_ptr objArray(mcgenCutsStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + AnalysisCut* cut = dqcuts::GetAnalysisCut(objArray->At(icut)->GetName()); + if (cut != nullptr) { + fMCGenAccCuts.push_back(cut); + } + } + fUseMCGenAccCut = true; + } + // Add histogram classes for each specified MCsignal at the generator level // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function TString sigGenNamesStr = fConfigMC.genSignals.value; @@ -1686,6 +1705,16 @@ struct AnalysisSameEventPairing { } } + // define final state MC signals + TString sigFinalStateNamesStr = fConfigMC.finalStateSignals.value; + std::unique_ptr objFinalStateSigArray(sigFinalStateNamesStr.Tokenize(",")); + for (int isig = 0; isig < objFinalStateSigArray->GetEntries(); isig++) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objFinalStateSigArray->At(isig)->GetName()); + if (sig) { + fFinalStateMCSignals.push_back(sig); + } + } + if (isMCGen) { for (auto& sig : fGenMCSignals) { if (sig->GetNProngs() == 1) { @@ -1694,7 +1723,16 @@ struct AnalysisSameEventPairing { } else if (sig->GetNProngs() == 2) { histNames += Form("MCTruthGenPair_%s;", sig->GetName()); histNames += Form("MCTruthGenPairSel_%s;", sig->GetName()); + histNames += Form("MCTruthGenPseudoPolPair_%s;", sig->GetName()); + histNames += Form("MCTruthGenPseudoPolPairSel_%s;", sig->GetName()); fHasTwoProngGenMCsignals = true; + // for these pair level signals, also add histograms for each MCgenAcc cut if specified + if (fUseMCGenAccCut) { + for (auto& cut : fMCGenAccCuts) { + histNames += Form("MCTruthGenPairSel_%s_%s;", sig->GetName(), cut->GetName()); + histNames += Form("MCTruthGenPseudoPolPairSel_%s_%s;", sig->GetName(), cut->GetName()); + } + } } } } @@ -1806,11 +1844,14 @@ struct AnalysisSameEventPairing { dileptonMiniTreeGen.reserve(1); dileptonMiniTreeRec.reserve(1); } + if (fConfigOptions.polarTables.value) { + dileptonPolarList.reserve(1); + } constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); constexpr bool trackHasCov = ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelCov) > 0); for (auto& event : events) { - if (!event.isEventSelected_bit(0)) { + if (!event.has_reducedMCevent() || !event.isEventSelected_bit(0)) { // condition on reducedMCevent to avoid rec. events with no generated event continue; } uint8_t evSel = event.isEventSelected_raw(); @@ -1900,6 +1941,13 @@ struct AnalysisSameEventPairing { VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); } + if (fConfigOptions.polarTables.value && t1.has_reducedMCTrack() && t2.has_reducedMCTrack()) { + dileptonPolarList(VarManager::fgValues[VarManager::kCosThetaHE], VarManager::fgValues[VarManager::kPhiHE], VarManager::fgValues[VarManager::kPhiTildeHE], + VarManager::fgValues[VarManager::kCosThetaCS], VarManager::fgValues[VarManager::kPhiCS], VarManager::fgValues[VarManager::kPhiTildeCS], + VarManager::fgValues[VarManager::kCosThetaPP], VarManager::fgValues[VarManager::kPhiPP], VarManager::fgValues[VarManager::kPhiTildePP], + VarManager::fgValues[VarManager::kCosThetaRM], + VarManager::fgValues[VarManager::kCosThetaStarTPC], VarManager::fgValues[VarManager::kCosThetaStarFT0A], VarManager::fgValues[VarManager::kCosThetaStarFT0C]); + } } } } @@ -1990,6 +2038,7 @@ struct AnalysisSameEventPairing { t1.reducedMCTrack().vx(), t1.reducedMCTrack().vy(), t1.reducedMCTrack().vz(), t1.reducedMCTrack().vt(), t2.reducedMCTrack().vx(), t2.reducedMCTrack().vy(), t2.reducedMCTrack().vz(), t2.reducedMCTrack().vt(), (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)), (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)), + isCorrectAssoc_leg1, isCorrectAssoc_leg2, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, -999.0, VarManager::fgValues[VarManager::kMultDimuons], @@ -2140,29 +2189,26 @@ struct AnalysisSameEventPairing { PresliceUnsorted perReducedMcEvent = aod::reducedtrackMC::reducedMCeventId; template - void runMCGenWithGrouping(MyEventsVtxCovSelected const& events, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) + void runMCGen(MyEventsVtxCovSelected const& events, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { uint32_t mcDecision = 0; int isig = 0; + // Loop over all MC single particles to fill generator level histograms, disregarding of whether they belong to selected reconstructed events or not for (auto& mctrack : mcTracks) { - VarManager::FillTrackMC(mcTracks, mctrack); - // if we have a mc generated acceptance cut, apply it here - if (fUseMCGenAccCut) { - if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { - continue; - } - } - // NOTE: Signals are checked here mostly based on the skimmed MC stack, so depending on the requested signal, the stack could be incomplete. - // NOTE: However, the working model is that the decisions on MC signals are precomputed during skimming and are stored in the mcReducedFlags member. - // TODO: Use the mcReducedFlags to select signals for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, mctrack)) { + VarManager::FillTrackMC(mcTracks, mctrack); fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); } } } - // Fill Generated histograms taking into account selected collisions + // cout << "Filled single MC particle generator histograms." << endl; + + // make a vector of global indices of mc particles which fulfill the selected track-level signal definition (to speed up the two mc particle combinatorics) + std::vector FinalStateMcParticleIndices; + + // Now loop over reconstructed events to select only MC particles belonging to the same MC collision as the reconstructed event for (auto& event : events) { if (!event.isEventSelected_bit(0)) { continue; @@ -2171,22 +2217,21 @@ struct AnalysisSameEventPairing { continue; } - for (auto& track : mcTracks) { - if (track.reducedMCeventId() != event.reducedMCeventId()) { - continue; - } - VarManager::FillTrackMC(mcTracks, track); - // if we have a mc generated acceptance cut, apply it here - if (fUseMCGenAccCut) { - if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { - continue; - } - } + FinalStateMcParticleIndices.clear(); + + auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.reducedMCeventId()); + groupedMCTracks.bindInternalIndicesTo(&mcTracks); + + for (auto& track : groupedMCTracks) { auto track_raw = mcTracks.rawIteratorAt(track.globalIndex()); mcDecision = 0; isig = 0; for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, track_raw)) { + if (track.reducedMCeventId() != event.reducedMCeventId()) { // check that the mc track belongs to the same mc collision as the reconstructed event + continue; + } + VarManager::FillTrackMC(mcTracks, track); mcDecision |= (static_cast(1) << isig); fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); MCTruthTableEffi(VarManager::fgValues[VarManager::kMCPt], VarManager::fgValues[VarManager::kMCEta], VarManager::fgValues[VarManager::kMCY], VarManager::fgValues[VarManager::kMCPhi], VarManager::fgValues[VarManager::kMCVz], VarManager::fgValues[VarManager::kMCVtxZ], VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); @@ -2198,72 +2243,62 @@ struct AnalysisSameEventPairing { } isig++; } - } - } // end loop over reconstructed events - - if (fHasTwoProngGenMCsignals) { - for (auto& [t1, t2] : combinations(mcTracks, mcTracks)) { - auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); - auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); - if (t1_raw.reducedMCeventId() == t2_raw.reducedMCeventId()) { - for (auto& sig : fGenMCSignals) { - if (sig->GetNProngs() != 2) { // NOTE: 2-prong signals required here - continue; - } - if (sig->CheckSignal(true, t1_raw, t2_raw)) { - VarManager::FillPairMC(t1, t2); - if (fUseMCGenAccCut) { - if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { - continue; - } - } - fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig->GetName()), VarManager::fgValues); - } + for (auto& sig : fFinalStateMCSignals) { + if (sig->CheckSignal(true, track_raw)) { + FinalStateMcParticleIndices.push_back(track.globalIndex()); + break; // if one of the final state signals is matched, no need to check the others } } + // cout << "Filled single MC particle generator histograms for reconstructed event." << endl; } - } - for (auto& event : events) { - if (!event.isEventSelected_bit(0)) { - continue; - } - if (!event.has_reducedMCevent()) { - continue; - } - // CURRENTLY ONLY FOR 1-GENERATION 2-PRONG SIGNALS + if (fHasTwoProngGenMCsignals) { - auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.reducedMCeventId()); - groupedMCTracks.bindInternalIndicesTo(&mcTracks); - for (auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { - auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); - auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); - if (t1_raw.reducedMCeventId() == t2_raw.reducedMCeventId()) { + // loop over combinations of the selected mc particles to fill generator level pair histograms + for (auto& t1 : FinalStateMcParticleIndices) { + auto t1_raw = mcTracks.rawIteratorAt(t1); + for (auto& t2 : FinalStateMcParticleIndices) { + if (t2 <= t1) { + continue; // avoid double counting and self-pairing + } + // for (auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { + // cout << "Processing pair of mcTracks with globalIndices = " << t1.globalIndex() << ", " << t2.globalIndex() << endl; + auto t2_raw = mcTracks.rawIteratorAt(t2); + mcDecision = 0; isig = 0; for (auto& sig : fGenMCSignals) { if (sig->GetNProngs() != 2) { // NOTE: 2-prong signals required here continue; } + // cout << " Checking signal: " << sig->GetName() << endl; if (sig->CheckSignal(true, t1_raw, t2_raw)) { + // cout << " Signal matched!" << endl; mcDecision |= (static_cast(1) << isig); - VarManager::FillPairMC(t1, t2); + VarManager::FillPairMC(t1_raw, t2_raw); + // cout << " Filled VarManager for the pair." << endl; + fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s", sig->GetName()), VarManager::fgValues); + fHistMan->FillHistClass(Form("MCTruthGenPseudoPolPairSel_%s", sig->GetName()), VarManager::fgValues); + // Fill also acceptance cut histograms if requested if (fUseMCGenAccCut) { - if (!fMCGenAccCut.IsSelected(VarManager::fgValues)) { - continue; + for (auto& cut : fMCGenAccCuts) { + if (cut->IsSelected(VarManager::fgValues)) { + fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s_%s", sig->GetName(), cut->GetName()), VarManager::fgValues); + fHistMan->FillHistClass(Form("MCTruthGenPseudoPolPairSel_%s_%s", sig->GetName(), cut->GetName()), VarManager::fgValues); + } } } - fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s", sig->GetName()), VarManager::fgValues); if (useMiniTree.fConfigMiniTree) { // WARNING! To be checked - dileptonMiniTreeGen(mcDecision, -999, t1.pt(), t1.eta(), t1.phi(), t2.pt(), t2.eta(), t2.phi()); + dileptonMiniTreeGen(mcDecision, -999, t1_raw.pt(), t1_raw.eta(), t1_raw.phi(), t2_raw.pt(), t2_raw.eta(), t2_raw.phi()); } } isig++; } - } - } - } // end loop over reconstructed events - } + } // end loop over second mc particle + } // end loop over first mc particle + } + } // end loop over reconstructed events + // cout << "AnalysisSameEventPairing::runMCGen() completed" << endl; } void processAllSkimmed(MyEventsVtxCovSelected const& events, @@ -2285,7 +2320,7 @@ struct AnalysisSameEventPairing { MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); - runMCGenWithGrouping(events, mcEvents, mcTracks); + runMCGen(events, mcEvents, mcTracks); } void processBarrelOnlyWithCollSkimmed(MyEventsVtxCovSelected const& events, @@ -2293,10 +2328,7 @@ struct AnalysisSameEventPairing { MyBarrelTracksWithCovWithAmbiguitiesWithColl const& barrelTracks, ReducedMCEvents const& mcEvents, ReducedMCTracks const& mcTracks) { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, mcEvents, mcTracks); - // Feature replaced by processMCGen - /* if (fConfigMC.runMCGenPair) { - runMCGen(mcEvents, mcTracks); - }*/ + runMCGen(events, mcEvents, mcTracks); } void processMuonOnlySkimmed(MyEventsVtxCovSelected const& events, @@ -3588,6 +3620,7 @@ struct AnalysisDileptonTrack { Configurable fConfigMCGenDileptonLegEtaAbs{"cfgMCGenDileptonLegEtaAbs", 0.9f, "eta abs range for the dilepton leg"}; Configurable fConfigMCGenHadronEtaAbs{"cfgMCGenHadronEtaAbs", 0.9f, "eta abs range for the hadron"}; Configurable fConfigUseMCRapcut{"cfgUseMCRapcut", false, "Use Rap cut for dileptons used in the triplet vertexing(reconstructed)"}; + Configurable fConfigUseCorrectlyAssociatedMC{"cfgUseCorrectlyAssociatedMC", true, "Use only correctly associated track to construct triplet"}; Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. @@ -3978,6 +4011,9 @@ struct AnalysisDileptonTrack { uint32_t mcDecision = static_cast(0); size_t isig = 0; + bool isCorrectAssoc_lepton1 = false; + bool isCorrectAssoc_lepton2 = false; + bool isCorrectAssoc_assoc = false; for (auto dilepton : dileptons) { // get full track info of tracks based on the index @@ -3997,6 +4033,12 @@ struct AnalysisDileptonTrack { if (fConfigUseMCRapcut && abs(rap) > fConfigDileptonRapCutAbs) continue; + // Correct association + if (fConfigUseCorrectlyAssociatedMC) { + isCorrectAssoc_lepton1 = (lepton1MC.reducedMCevent() == event.reducedMCevent()); + isCorrectAssoc_lepton2 = (lepton2MC.reducedMCevent() == event.reducedMCevent()); + } + VarManager::FillTrack(dilepton, fValuesDilepton); // fill selected dilepton histograms for each specified selection @@ -4047,11 +4089,22 @@ struct AnalysisDileptonTrack { if (track.globalIndex() == dilepton.index0Id() || track.globalIndex() == dilepton.index1Id()) { continue; } + + auto trackMC = track.reducedMCTrack(); + if (fConfigUseCorrectlyAssociatedMC) { // check if correctly associated + isCorrectAssoc_assoc = (trackMC.reducedMCevent() == event.reducedMCevent()); + } + bool isCorrect_triplet = isCorrectAssoc_lepton1 && isCorrectAssoc_lepton2 && isCorrectAssoc_assoc; + if (fConfigUseCorrectlyAssociatedMC) { + if (!isCorrect_triplet) { + continue; + } + } + // compute needed quantities VarManager::FillDileptonHadron(dilepton, track, fValuesHadron); VarManager::FillDileptonTrackVertexing(event, lepton1, lepton2, track, fValuesHadron); - auto trackMC = track.reducedMCTrack(); mcDecision = 0; isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { @@ -4632,7 +4685,9 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char if (classStr.Contains("MCTruthGenPair")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_pair", histName); } - + if (classStr.Contains("MCTruthGenPseudoPolPair")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "polarization-pseudoproper-gen", histName); + } if (classStr.Contains("MCTruthGenSelBR")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_triple"); } else if (classStr.Contains("MCTruthGen")) { diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx index 44656cd7476..745e0833de4 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc_direct.cxx @@ -19,41 +19,52 @@ #include "PWGDQ/Core/HistogramsLibrary.h" #include "PWGDQ/Core/MCSignal.h" #include "PWGDQ/Core/MCSignalLibrary.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/MixingLibrary.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "Common/Core/PID/PIDTOFParamService.h" #include "Common/Core/TableHelper.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include +#include #include #include -#include +#include + +#include +#include +#include +#include +#include #include +#include #include #include #include @@ -68,13 +79,13 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; +using namespace o2::common::core; // Some definitions namespace o2::aod { namespace dqanalysisflags { -DECLARE_SOA_COLUMN(MixingHash, mixingHash, int); //! Hash used in event mixing //need to understand DECLARE_SOA_BITMAP_COLUMN(IsEventSelected, isEventSelected, 32); //! Event decision DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelected, isBarrelSelected, 32); //! Barrel track decisions DECLARE_SOA_COLUMN(BarrelAmbiguityInBunch, barrelAmbiguityInBunch, int8_t); //! Barrel track in-bunch ambiguity @@ -166,6 +177,7 @@ DECLARE_SOA_COLUMN(Ptee, ptee, float); DECLARE_SOA_COLUMN(Lxyee, lxyee, float); DECLARE_SOA_COLUMN(LxyeePoleMass, lxyeepolemass, float); DECLARE_SOA_COLUMN(Lzee, lzee, float); +DECLARE_SOA_COLUMN(LxyeePoleMassPVrecomputed, lxyeePoleMassPVrecomputed, float); DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0CJPsi2ee, float); DECLARE_SOA_COLUMN(PercentileFT0M, percentileFT0MJPsi2ee, float); @@ -182,12 +194,11 @@ DECLARE_SOA_COLUMN(OniaVz, oniaVz, float); DECLARE_SOA_COLUMN(OniaVtxZ, oniaVtxZ, float); } // namespace dqanalysisflags -DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents -DECLARE_SOA_TABLE(MixingHashes, "AOD", "DQANAMIXHASHA", dqanalysisflags::MixingHash); //! joinable to ReducedEvents +DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents //! joinable to ReducedEvents 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(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); //! joinable to ReducedTracksAssoc -DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); +DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, dqanalysisflags::Phiee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); DECLARE_SOA_TABLE(OniaMCTruth, "AOD", "MCTRUTHONIA", dqanalysisflags::OniaPt, dqanalysisflags::OniaEta, dqanalysisflags::OniaY, dqanalysisflags::OniaPhi, dqanalysisflags::OniaVz, dqanalysisflags::OniaVtxZ, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); /*DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTS", dqanalysisflags::IsMuonSelected); //! joinable to ReducedMuonsAssoc @@ -242,7 +253,6 @@ using MyMuonTracksWithCovWithAmbiguities = soa::Join; using MyEvents = soa::Join; using MyEventsSelected = soa::Join; -using MyEventsHashSelected = soa::Join; using MyBarrelTracksWithCov = soa::Join eventSel; - Produces hash; OutputObj fOutputList{"output"}; - Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; @@ -305,7 +313,6 @@ struct AnalysisEventSelection { 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"}; HistogramManager* fHistMan = nullptr; - MixingHandler* fMixHandler = nullptr; AnalysisCompositeCut* fEventCut; @@ -357,16 +364,6 @@ struct AnalysisEventSelection { 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()); - } - } - fCurrentRun = -1; fCCDB->setURL(fConfigCcdbUrl.value); fCCDB->setCaching(true); @@ -438,10 +435,6 @@ struct AnalysisEventSelection { auto& evIndices = fBCCollMap[bc.globalBC()]; evIndices.push_back(event.globalIndex()); } - if (fMixHandler != nullptr) { - int hh = fMixHandler->FindEventCategory(VarManager::fgValues); - hash(hh); - } } for (auto& event : mcEvents) { @@ -729,6 +722,13 @@ struct AnalysisTrackSelection { trackSel(0); continue; } + /// + auto track = tracks.rawIteratorAt(assoc.trackId()); + auto evFromTrack = events.rawIteratorAt(track.collisionId()); + if (!evFromTrack.isEventSelected_bit(0)) { + trackSel(0); + continue; + } // cout << "Processing association: event global index " << event.globalIndex() << endl; VarManager::ResetValues(VarManager::kNTFWiseVariables, VarManager::kNBarrelTrackVariables); @@ -739,10 +739,10 @@ struct AnalysisTrackSelection { } // cout << "Filled event observables for association" << endl; - auto track = tracks.rawIteratorAt(assoc.trackId()); VarManager::FillTrack(track); // compute quantities which depend on the associated collision, such as DCA - VarManager::FillTrackCollision(track, event); + if (track.collisionId() != event.globalIndex()) + VarManager::FillTrackCollision(track, event); // cout << "Filled track observables for association" << endl; bool isCorrectAssoc = false; @@ -1120,6 +1120,8 @@ struct AnalysisSameEventPairing { Configurable magField{"cfgMagField", 5.0f, "Manually set magnetic field"}; Configurable flatTables{"cfgFlatTables", false, "Produce a single flat tables with all relevant information of the pairs and single tracks"}; Configurable useKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable recomputePV{"cfgRecomputePV", false, "Recompute primary vertex using PVertexer to calculate unbiased pseudoproperDL"}; + Configurable removeDiamondConstrPV{"cfgRemoveDiamondPV", false, "remove diamond constrain for PV recomputation"}; Configurable useAbsDCA{"cfgUseAbsDCA", false, "Use absolute DCA minimization instead of chi^2 minimization in secondary vertexing"}; Configurable propToPCA{"cfgPropToPCA", false, "Propagate tracks to secondary vertex"}; Configurable corrFullGeo{"cfgCorrFullGeo", false, "Use full geometry to correct for MCS effects in track propagation"}; @@ -1152,6 +1154,11 @@ struct AnalysisSameEventPairing { HistogramManager* fHistMan; + // vectors needed for PV recomputation + std::vector pvContribGlobIDs; + std::vector pvContribTrackPars; + std::vector vec_useTrk_PVrefit; + // keep histogram class names in maps, so we don't have to buld their names in the pair loops std::map> fTrackHistNames; std::map> fBarrelHistNamesMCmatched; @@ -1462,6 +1469,7 @@ struct AnalysisSameEventPairing { histNames += Form("MCTruthGenSel_%s;", sig->GetName()); } else if (sig->GetNProngs() == 2) { histNames += Form("MCTruthGenPairSel_%s;", sig->GetName()); + histNames += Form("MCTruthGenPseudoPolPairSel_%s;", sig->GetName()); fHasTwoProngGenMCsignals = true; } } @@ -1502,9 +1510,12 @@ struct AnalysisSameEventPairing { cout << "AnalysisSameEventPairing::initParamsFromCCDB() called for timestamp " << timestamp << endl; if (fConfigOptions.useRemoteField.value) { o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(fConfigCCDB.grpMagPath, timestamp); + o2::base::MatLayerCylSet* lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(fCCDB->get(fConfigCCDB.lutPath)); float magField = 0.0; if (grpmag != nullptr) { magField = grpmag->getNominalL3Field(); + o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); } else { LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", timestamp); } @@ -1533,9 +1544,60 @@ struct AnalysisSameEventPairing { cout << "AnalysisSameEventPairing::initParamsFromCCDB() completed" << endl; } + template + bool refitPVWithPVertexer(Events const& collision, TTracks const& tracks, Tracks const& t1, Tracks const& t2, o2::dataformats::VertexBase& pvRefitted) + { + // --- build PV contributor list --- + pvContribGlobIDs.clear(); + pvContribTrackPars.clear(); + // int nMyPVContrib = 0; int nMyPVContribOrig = 0; + for (auto const& trk : tracks) { + // check if it is PV contributor + if (!trk.isPVContributor()) + continue; + // check if it contributes to the vtx of this collision + if (trk.collisionId() != collision.globalIndex()) + continue; + // nMyPVContribOrig++; + // --- remove t1 and t2 if they are PV contributors --- + if (trk.globalIndex() == t1.globalIndex() || trk.globalIndex() == t2.globalIndex()) + continue; + // add tracks and parameters to the list + pvContribGlobIDs.push_back(trk.globalIndex()); + pvContribTrackPars.push_back(getTrackParCov(trk)); + // nMyPVContrib++; + } + + // cout << "contributors from collision: " << collision.numContrib() << " - from refitting: before -> " << nMyPVContribOrig << " after -> " << nMyPVContrib << endl; + vec_useTrk_PVrefit.assign(pvContribGlobIDs.size(), true); + // --- build VertexBase from event collision --- + o2::dataformats::VertexBase Pvtx; + Pvtx.setX(collision.posX()); + Pvtx.setY(collision.posY()); + Pvtx.setZ(collision.posZ()); + Pvtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ()); + + // --- configure vertexer --- + o2::vertexing::PVertexer vertexer; + if (fConfigOptions.removeDiamondConstrPV) { + o2::conf::ConfigurableParam::updateFromString("pvertexer.useMeanVertexConstraint=false"); + } + vertexer.init(); + + bool PVrefit_doable = vertexer.prepareVertexRefit(pvContribTrackPars, Pvtx); + if (!PVrefit_doable) + return false; + + // --- do the refit --- + pvRefitted = vertexer.refitVertex(vec_useTrk_PVrefit, Pvtx); + + return true; + } + // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) template - void runSameEventPairing(TEvents const& events, BCsWithTimestamps const& bcs, Preslice>& preslice, soa::Join const& assocs, TTracks const& /*tracks*/, McCollisions const& /*mcEvents*/, McParticles const& /*mcTracks*/) + void runSameEventPairing(TEvents const& events, BCsWithTimestamps const& bcs, Preslice>& preslice, soa::Join const& assocs, TTracks const& tracks, McCollisions const& /*mcEvents*/, McParticles const& /*mcTracks*/) { cout << "AnalysisSameEventPairing::runSameEventPairing() called" << endl; if (events.size() == 0) { @@ -1646,6 +1708,17 @@ struct AnalysisSameEventPairing { } if constexpr (TTwoProngFitter) { VarManager::FillPairVertexing(event, t1, t2, fConfigOptions.propToPCA); + if (fConfigOptions.recomputePV) { + VarManager::SetPVrecalculationKF(false); + VarManager::ResetValues(VarManager::kVertexingLxyProjectedRecalculatePV, VarManager::kVertexingLxyProjectedRecalculatePV + 1); + VarManager::ResetValues(VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV, VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV + 1); + // cout << "primary vertex (before): x -> " << event.posX() << " y -> " << event.posY() << " z -> " << event.posZ() << endl; + o2::dataformats::VertexBase pvRefit; + bool ok = refitPVWithPVertexer(event, tracks, t1, t2, pvRefit); + if (ok) + VarManager::FillPairVertexingRecomputePV(event, t1, t2, pvRefit); + // cout << "primary vertex (after): ok -> " << ok << " x -> " << pvRefit.getX() << " y -> " << pvRefit.getY() << " z -> " << pvRefit.getZ() << endl; + } } if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); @@ -1784,7 +1857,7 @@ 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 & (static_cast(1) << isig)) { - PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], isAmbiInBunch, isAmbiOutOfBunch, isCorrect_pair, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], isAmbiInBunch, isAmbiOutOfBunch, isCorrect_pair, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); fHistMan->FillHistClass(histNamesMC[icut * fRecMCSignals.size() + isig][0].Data(), VarManager::fgValues); // matched signal /*if (fConfigOptions.fConfigMiniTree) { if constexpr (TPairType == VarManager::kDecayToMuMu) { @@ -2009,6 +2082,7 @@ struct AnalysisSameEventPairing { } } fHistMan->FillHistClass(Form("MCTruthGenPairSel_%s", sig->GetName()), VarManager::fgValues); + fHistMan->FillHistClass(Form("MCTruthGenPseudoPolPairSel_%s", sig->GetName()), VarManager::fgValues); if (fConfigOptions.fConfigMiniTree) { // WARNING! To be checked dileptonMiniTreeGen(mcDecision, -999, t1_raw.pt(), t1_raw.eta(), t1_raw.phi(), t2_raw.pt(), t2_raw.eta(), t2_raw.phi()); @@ -2060,10 +2134,8 @@ struct AnalysisDileptonTrack { Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; Configurable fConfigDileptonLowpTCut{"cfgDileptonLowpTCut", 0.0, "Low pT cut for dileptons used in the triplet vertexing"}; Configurable fConfigDileptonHighpTCut{"cfgDileptonHighpTCut", 1E5, "High pT cut for dileptons used in the triplet vertexing"}; - Configurable fConfigDileptonRapCutAbs{"cfgDileptonRapCutAbs", 1.0, "Rap cut for dileptons used in the triplet vertexing"}; Configurable fConfigHistogramSubgroups{"cfgDileptonTrackHistogramsSubgroups", "invmass,vertexing", "Comma separated list of dilepton-track histogram subgroups"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; - Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; Configurable fConfigPublishTripletTable{"cfgPublishTripletTable", false, "Publish the triplet tables, BmesonCandidates"}; } fConfigOptions; @@ -2125,8 +2197,6 @@ struct AnalysisDileptonTrack { MCSignal* fDileptonLegSignal; MCSignal* fHadronSignal; - NoBinningPolicy fHashBin; - void init(o2::framework::InitContext& context) { cout << "AnalysisDileptonTrack::init() called" << endl; @@ -2135,8 +2205,6 @@ struct AnalysisDileptonTrack { // bool isMuon = context.mOptions.get("processMuonSkimmed"); bool isMCGen = context.mOptions.get("processMCGen"); bool isDummy = context.mOptions.get("processDummy"); - bool isMCGen_energycorrelators = context.mOptions.get("processMCGenEnergyCorrelators") || context.mOptions.get("processMCGenEnergyCorrelatorsPion"); - bool isMCGen_energycorrelatorsME = context.mOptions.get("processMCGenEnergyCorrelatorsME") || context.mOptions.get("processMCGenEnergyCorrelatorsPionME"); if (isDummy) { if (isBarrel || isMCGen /*|| isBarrelAsymmetric*/ /*|| isMuon*/) { @@ -2382,6 +2450,7 @@ struct AnalysisDileptonTrack { // define dilepton histograms DefineHistograms(fHistMan, Form("DileptonsSelected_%s", pairLegCutName.Data()), "barrel,vertexing"); + // loop over track cuts and create dilepton - track histogram directories for (int iCutTrack = 0; iCutTrack < fNCuts; iCutTrack++) { @@ -2442,18 +2511,6 @@ struct AnalysisDileptonTrack { } } - if (isMCGen_energycorrelators) { - for (auto& sig : fGenMCSignals) { - DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_%s", sig->GetName()), ""); - } - } - - if (isMCGen_energycorrelatorsME) { - for (auto& sig : fGenMCSignals) { - DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), ""); - } - } - TString addHistsStr = fConfigOptions.fConfigAddJSONHistograms.value; if (addHistsStr != "") { dqhistograms::AddHistogramsFromJSON(fHistMan, addHistsStr.Data()); @@ -2521,11 +2578,6 @@ struct AnalysisDileptonTrack { if (dilepton.sign() != 0) { continue; } - // dilepton rap cut - float rap = dilepton.rap(); - if (fConfigMCOptions.fConfigUseMCRapcut && abs(rap) > fConfigOptions.fConfigDileptonRapCutAbs) { - continue; - } VarManager::FillTrack(dilepton, fValuesDilepton); @@ -2580,7 +2632,6 @@ struct AnalysisDileptonTrack { // compute needed quantities VarManager::FillDileptonHadron(dilepton, track, fValuesHadron); VarManager::FillDileptonTrackVertexing(event, lepton1, lepton2, track, fValuesHadron); - if (!track.has_mcParticle()) { continue; } @@ -2814,7 +2865,7 @@ struct AnalysisDileptonTrack { runDileptonHadron(event, groupedBarrelAssocs, tracks, groupedDitracks, mcEvents, mcTracks); } } - */ + */ /* Preslice muonAssocsPerCollision = aod::reducedtrack_association::reducedeventId; Preslice dimuonsPerCollision = aod::reducedpair::reducedeventId; @@ -2933,151 +2984,6 @@ struct AnalysisDileptonTrack { cout << "AnalysisDileptonTrack::processMCGen() completed" << endl; } - template - void runEnergyCorrelators(TEvent const& event, McParticles const& mcTracks) - { - auto groupedMCTracks = mcTracks.sliceBy(perReducedMcEvent, event.mcCollisionId()); - groupedMCTracks.bindInternalIndicesTo(&mcTracks); - for (auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { - auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); - // apply kinematic cuts for signal - if ((t1_raw.pt() < fConfigOptions.fConfigDileptonLowpTCut || t1_raw.pt() > fConfigOptions.fConfigDileptonHighpTCut)) { - continue; - } - if (abs(t1_raw.y()) > fConfigOptions.fConfigDileptonRapCutAbs) { - continue; - } - auto t2_raw = mcTracks.rawIteratorAt(t2.globalIndex()); - if (TMath::Abs(t2_raw.pdgCode()) == 443 || TMath::Abs(t2_raw.pdgCode()) == 11 || TMath::Abs(t2_raw.pdgCode()) == 22) { - continue; - } - if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { - continue; - } - if (t2_raw.getGenStatusCode() <= 0) { - continue; - } - for (auto& sig : fGenMCSignals) { - if (sig->CheckSignal(true, t1_raw)) { - VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues); - fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_%s", sig->GetName()), VarManager::fgValues); - } - } - } - } - - void processMCGenEnergyCorrelators(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - for (auto& event : events) { - if (!event.isEventSelected_bit(0)) { - continue; - } - if (!event.has_mcCollision()) { - continue; - } - runEnergyCorrelators(event, mcTracks); - } - } - - void processMCGenEnergyCorrelatorsPion(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - for (auto& event : events) { - if (!event.isEventSelected_bit(0)) { - continue; - } - if (!event.has_mcCollision()) { - continue; - } - runEnergyCorrelators(event, mcTracks); - } - } - - template - void runEnergyCorrelatorsMixedEvent(TEvent const& event1, TEvent const& event2, McParticles const& mcTracks) - { - auto groupedMCTracks1 = mcTracks.sliceBy(perReducedMcEvent, event1.mcCollisionId()); - auto groupedMCTracks2 = mcTracks.sliceBy(perReducedMcEvent, event2.mcCollisionId()); - groupedMCTracks1.bindInternalIndicesTo(&mcTracks); - groupedMCTracks2.bindInternalIndicesTo(&mcTracks); - for (auto& t1 : groupedMCTracks1) { - auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); - // apply kinematic cuts for signal - if ((t1_raw.pt() < fConfigOptions.fConfigDileptonLowpTCut || t1_raw.pt() > fConfigOptions.fConfigDileptonHighpTCut)) { - continue; - } - if (abs(t1_raw.y()) > fConfigOptions.fConfigDileptonRapCutAbs) { - continue; - } - // for the energy correlators - for (auto& t2 : groupedMCTracks2) { - auto t2_raw = groupedMCTracks2.rawIteratorAt(t2.globalIndex()); - if (TMath::Abs(t2_raw.pdgCode()) == 443 || TMath::Abs(t2_raw.pdgCode()) == 11 || TMath::Abs(t2_raw.pdgCode()) == 22) { - continue; - } - if (t2_raw.pt() < fConfigMCOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigMCOptions.fConfigMCGenHadronEtaAbs.value) { - continue; - } - if (t2_raw.getGenStatusCode() <= 0) { - continue; - } - for (auto& sig : fGenMCSignals) { - if (sig->CheckSignal(true, t1_raw)) { - VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues); - fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), VarManager::fgValues); - } - } - } - } - } - - void processMCGenEnergyCorrelatorsME(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - // loop over two event comibnations - for (auto& [event1, event2] : selfCombinations(fHashBin, fConfigOptions.fConfigMixingDepth.value, -1, events, events)) { - if (!event1.isEventSelected_bit(0) || !event2.isEventSelected_bit(0)) { - continue; - } - if (!event1.has_mcCollision() || !event2.has_mcCollision()) { - continue; - } - runEnergyCorrelatorsMixedEvent(event1, event2, mcTracks); - } - } - - void processMCGenEnergyCorrelatorsPionME(soa::Filtered const& events, - McCollisions const& /*mcEvents*/, McParticles const& mcTracks) - { - if (events.size() == 0) { - LOG(warning) << "No events in this TF, going to the next one ..."; - return; - } - // loop over two event comibnations - for (auto& [event1, event2] : selfCombinations(fHashBin, fConfigOptions.fConfigMixingDepth.value, -1, events, events)) { - if (!event1.isEventSelected_bit(0) || !event2.isEventSelected_bit(0)) { - continue; - } - if (!event1.has_mcCollision() || !event2.has_mcCollision()) { - continue; - } - runEnergyCorrelatorsMixedEvent(event1, event2, mcTracks); - } - } - void processDummy(MyEvents&) { // do nothing @@ -3087,10 +2993,6 @@ struct AnalysisDileptonTrack { // PROCESS_SWITCH(AnalysisDileptonTrack, processDstarToD0Pi, "Run barrel pairing of D0 daughters with pion candidate, using skimmed data", false); // PROCESS_SWITCH(AnalysisDileptonTrack, processMuonSkimmed, "Run muon dilepton-track pairing, using skimmed data", false); PROCESS_SWITCH(AnalysisDileptonTrack, processMCGen, "Loop over MC particle stack and fill generator level histograms", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelators, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelatorsPion, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelatorsME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); - PROCESS_SWITCH(AnalysisDileptonTrack, processMCGenEnergyCorrelatorsPionME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); PROCESS_SWITCH(AnalysisDileptonTrack, processDummy, "Dummy function", true); }; @@ -3167,6 +3069,9 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char if (classStr.Contains("MCTruthGenPair")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_pair", histName); } + if (classStr.Contains("MCTruthGenPseudoPolPair")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "polarization-pseudoproper-gen", histName); + } if (classStr.Contains("MCTruthGenSelBR")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_triple"); @@ -3179,7 +3084,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char // } if (classStr.Contains("DileptonsSelected")) { - dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", "barrel,vertexing"); + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); } if (classStr.Contains("DileptonTrack") && !classStr.Contains("ME")) { @@ -3201,10 +3106,5 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char if (classStr.Contains("DileptonHadronCorrelation")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-correlation"); } - - if (classStr.Contains("MCTruthEenergyCorrelators")) { - dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "energy-correlator-gen"); - } - } // end loop over histogram classes } diff --git a/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx new file mode 100644 index 00000000000..8815bfa32d9 --- /dev/null +++ b/PWGDQ/Tasks/dqEnergyCorrelator_direct.cxx @@ -0,0 +1,1030 @@ +// 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 +// Configurable workflow for running several DQ or other PWG analyses + +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/MCSignal.h" +#include "PWGDQ/Core/MCSignalLibrary.h" +#include "PWGDQ/Core/MixingHandler.h" +#include "PWGDQ/Core/VarManager.h" + +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::string; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +using MyEvents = soa::Join; +using MyBarrelTracksWithCov = soa::Join; + +// bit maps used for the Fill functions of the VarManager +constexpr static uint32_t gkEventFillMapWithMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult | VarManager::ObjTypes::CollisionMultExtra; +constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; + +// Forward declarations +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups); // defines histograms for all tasks + +struct AnalysisEnergyCorrelator { + OutputObj fOutputList{"output"}; + + struct : ConfigurableGroup { // Event selection configurables + Configurable> fConfigZBins{"cfgZBins", std::vector{-10.0, -5.0, 0.0, 5.0, 10.0}, "Z vertex bins for mixing"}; + Configurable> fConfigMultBins{"cfgMultBins", std::vector{0.0, 20.0, 40.0, 60.0, 100.0}, "Multiplicity bins for mixing"}; + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; + Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts in JSON"}; + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Event histograms"}; + Configurable fConfigAddEventMCHistogram{"cfgAddEventMCHistogram", "generator", "MC Event histograms"}; + Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; + Configurable fConfigEventfilterVtz{"cfgEventfilterVtz", 10.0, "Event filter Vtz"}; + Configurable fConfigEventQA{"cfgEventQA", false, "If true, fill Event QA histograms"}; + } fConfigEventOptions; + + struct : ConfigurableGroup { // Track selection configurables + Configurable fConfigTrackCuts{"cfgTrackCuts", "electronSelection1_ionut", "Comma separated list of barrel track cuts for electrons"}; + Configurable fConfigTrackCutsJSON{"cfgTrackCutsJSON", "", "Additional track cuts in JSON"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Track histograms"}; + Configurable fConfigTrackQA{"cfgTrackQA", false, "If true, fill Track QA histograms"}; + } fConfigTrackOptions; + + struct : ConfigurableGroup { // Pair selection configurables + Configurable fConfigJpsiMassMin{"cfgJpsiMassMin", 2.8, "J/psi mass minimum"}; + Configurable fConfigJpsiMassMax{"cfgJpsiMassMax", 3.3, "J/psi mass maximum"}; + Configurable fConfigJpsiPtMin{"cfgJpsiPtMin", 0.0, "J/psi pt minimum"}; + Configurable fConfigJpsiPtMax{"cfgJpsiPtMax", 100.0, "J/psi pt maximum"}; + Configurable fConfigJpsiRapMax{"cfgJpsiRapMax", 0.9, "J/psi rapidity maximum"}; + Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; + Configurable recSignals{"cfgMCRecSignals", "eeFromJpsi", "Comma separated list of MC signals (reconstructed)"}; + Configurable recSignalsJSON{"cfgMCRecSignalsJSON", "", "Comma separated list of MC signals (reconstructed) via JSON"}; + } fConfigPairOptions; + + struct : ConfigurableGroup { // Dilepton selection configurables + Configurable fConfigHadronCuts{"cfgHadronCuts", "NoPID", "Comma separated list of hadron track cuts"}; + Configurable fConfigHadronCutsJSON{"cfgHadronCutsJSON", "", "Additional hadron cuts in JSON"}; + Configurable fConfigApplyMassEC{"cfgApplyMassEC", false, "Apply fit mass for sideband for the energy correlator study"}; + Configurable> fConfigSavelessevents{"cfgSavelessevents", std::vector{1, 0}, "Save less events for the energy correlator study"}; + Configurable> fConfigTransRange{"cfgTransRange", std::vector{0.333333, 0.666667}, "Transverse region for the energy correlstor analysis"}; + Configurable fConfigAddDileptonHadronHistogram{"cfgAddDileptonHadronHistogram", "", "Dilepton-hadron histograms"}; + Configurable fConfigMCRecSignals{"cfgMCRecDileptonHadronSignals", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigMCGenSignals{"cfgMCGenDileptonHadronSignals", "", "Comma separated list of MC signals (generated)"}; + Configurable fConfigMCRecSignalsJSON{"cfgMCRecDileptonHadronSignalsJSON", "", "Additional list of MC signals (reconstructed) via JSON"}; + Configurable fConfigMCGenSignalsJSON{"cfgMCGenDileptonHadronSignalsJSON", "", "Comma separated list of MC signals (generated) via JSON"}; + Configurable fConfigMCGenHadronEtaAbs{"cfgMCGenHadronEtaAbs", 0.9f, "eta abs range for the hadron"}; + Configurable fConfigMCGenHadronPtMin{"cfgMCGenHadronPtMin", 0.1f, "minimum pt for the hadron"}; + Configurable fConfigContainlepton{"cfgContainlepton", false, "If true, require the hadron to contain the lepton in its decay tree for the energy correlator study"}; + Configurable fConfigUsePionMass{"cfgUsePionMass", false, "If true, use pion mass for the hadron in the energy correlator study"}; + } fConfigDileptonHadronOptions; + + // Histogram configurables + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON"}; + + // CCDB configurables + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "CCDB url"}; + Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "CCDB timestamp"}; + + // Member variables + HistogramManager* fHistMan = nullptr; + MixingHandler* fMixHandler = nullptr; + + AnalysisCompositeCut* fEventCut = nullptr; + std::vector fTrackCuts; // Electron cuts + std::vector fHadronCuts; // Hadron cuts + + std::vector fTrackCutNames; + std::vector fHadronCutNames; + std::vector fHistNamesReco; + + std::map> fTrackHistNames; + std::map> fBarrelHistNamesMCmatched; + std::map fSelMap; + + std::vector fRecMCSignals; // MC signals for reconstructed pairs + std::vector fGenMCSignals; + std::vector fRecMCTripleSignals; // MC signals for reconstructed triples + + Service fCCDB; + int fCurrentRun = -1; + + // Preslice for association table + Preslice preslice = aod::track_association::collisionId; + + using MixingBinning = ColumnBinningPolicy; + std::unique_ptr fMixingBinning; + + void init(o2::framework::InitContext& context) + { + std::vector zBins = fConfigEventOptions.fConfigZBins.value; + zBins.insert(zBins.begin(), VARIABLE_WIDTH); + + std::vector multBins = fConfigEventOptions.fConfigMultBins.value; + multBins.insert(multBins.begin(), VARIABLE_WIDTH); + + fMixingBinning = std::make_unique(std::array, 2>{zBins, multBins}, true); + + bool isBarrelME = context.mOptions.get("processBarrelMixedEvent"); + bool isMCGen_energycorrelators = context.mOptions.get("processMCGenEnergyCorrelators") || context.mOptions.get("processMCGenEnergyCorrelatorsPion"); + bool isMCGen_energycorrelatorsME = context.mOptions.get("processMCGenEnergyCorrelatorsME") || context.mOptions.get("processMCGenEnergyCorrelatorsPionME"); + + if (context.mOptions.get("processDummy")) { + return; + } + VarManager::SetDefaultVarNames(); + + // Setup Event Cuts + fEventCut = new AnalysisCompositeCut(true); + TString eventCutStr = fConfigEventOptions.fConfigEventCuts.value; + if (eventCutStr != "") { + AnalysisCut* cut = dqcuts::GetAnalysisCut(eventCutStr.Data()); + if (cut != nullptr) { + fEventCut->AddCut(cut); + } + } + // Additional cuts via JSON + TString eventCutJSONStr = fConfigEventOptions.fConfigEventCutsJSON.value; + if (eventCutJSONStr != "") { + std::vector jsonCuts = dqcuts::GetCutsFromJSON(eventCutJSONStr.Data()); + for (auto& cutIt : jsonCuts) { + fEventCut->AddCut(cutIt); + } + } + + // Setup Electron Track Cuts + TString trackCutStr = fConfigTrackOptions.fConfigTrackCuts.value; + if (!trackCutStr.IsNull()) { + std::unique_ptr objArrayTrack(trackCutStr.Tokenize(",")); + for (int icut = 0; icut < objArrayTrack->GetEntries(); ++icut) { + fTrackCuts.push_back(dqcuts::GetCompositeCut(objArrayTrack->At(icut)->GetName())); + fTrackCutNames.push_back(objArrayTrack->At(icut)->GetName()); + } + } + + TString trackCutsJSON = fConfigTrackOptions.fConfigTrackCutsJSON.value; + if (trackCutsJSON != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(trackCutsJSON.Data()); + for (auto& t : addTrackCuts) { + fTrackCuts.push_back(reinterpret_cast(t)); + fTrackCutNames.push_back(t->GetName()); + trackCutStr += Form(",%s", t->GetName()); + } + } + + // Setting the MC rec signal names + TString sigNamesStr = fConfigPairOptions.recSignals.value; + std::unique_ptr objRecSigArray(sigNamesStr.Tokenize(",")); + for (int isig = 0; isig < objRecSigArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objRecSigArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() != 2) { // NOTE: 2-prong signals required + continue; + } + fRecMCSignals.push_back(sig); + } + } + + TString sigNamesHadronStr = fConfigDileptonHadronOptions.fConfigMCRecSignals.value; + std::unique_ptr objRecSigTripleArray(sigNamesHadronStr.Tokenize(",")); + if (!sigNamesHadronStr.IsNull()) { + for (int isig = 0; isig < objRecSigTripleArray->GetEntries(); ++isig) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objRecSigTripleArray->At(isig)->GetName()); + if (sig) { + if (sig->GetNProngs() != 3) { + LOG(fatal) << "Signal at reconstructed level requested (" << sig->GetName() << ") " << "does not have 3 prongs! Fix it"; + } + fRecMCTripleSignals.push_back(sig); + } else { + LOG(fatal) << "Signal at reconstructed level requested (" << objRecSigTripleArray->At(isig)->GetName() << ") " << "could not be retrieved from the library! -> skipped"; + } + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsStr = fConfigPairOptions.recSignalsJSON.value; + if (addMCSignalsStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsStr.Data()); + for (auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() != 2) { // NOTE: only 2 prong signals + continue; + } + fRecMCSignals.push_back(mcIt); + } + } + + // Add the reco MCSignals from the JSON config + TString addMCTripleSignalsStr = fConfigDileptonHadronOptions.fConfigMCRecSignalsJSON.value; + if (addMCTripleSignalsStr != "") { + std::vector addMCTripleSignals = dqmcsignals::GetMCSignalsFromJSON(addMCTripleSignalsStr.Data()); + for (auto& mcIt : addMCTripleSignals) { + if (mcIt->GetNProngs() != 3) { + LOG(fatal) << "Signal at reconstructed level requested (" << mcIt->GetName() << ") " << "does not have 3 prongs! Fix it"; + } + fRecMCTripleSignals.push_back(mcIt); + } + } + + // Setup Hadron Cuts + TString hadronCutStr = fConfigDileptonHadronOptions.fConfigHadronCuts.value; + if (!hadronCutStr.IsNull()) { + std::unique_ptr objArrayHadron(hadronCutStr.Tokenize(",")); + for (int icut = 0; icut < objArrayHadron->GetEntries(); ++icut) { + TString cutName = objArrayHadron->At(icut)->GetName(); + fHadronCuts.push_back(dqcuts::GetCompositeCut(cutName.Data())); + fHadronCutNames.push_back(cutName); + } + } + TString hadronCutsJSON = fConfigDileptonHadronOptions.fConfigHadronCutsJSON.value; + if (hadronCutsJSON != "") { + std::vector addHadronCuts = dqcuts::GetCutsFromJSON(hadronCutsJSON.Data()); + for (auto& t : addHadronCuts) { + fHadronCuts.push_back(reinterpret_cast(t)); + fHadronCutNames.push_back(t->GetName()); + hadronCutStr += Form(",%s", t->GetName()); + } + } + + // Add histogram classes for each specified MCsignal at the generator level + // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function + TString sigGenNamesStr = fConfigDileptonHadronOptions.fConfigMCGenSignals.value; + std::unique_ptr objGenSigArray(sigGenNamesStr.Tokenize(",")); + for (int isig = 0; isig < objGenSigArray->GetEntries(); isig++) { + MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objGenSigArray->At(isig)->GetName()); + if (sig) { + fGenMCSignals.push_back(sig); + } + } + + // Add the MCSignals from the JSON config + TString addMCSignalsGenStr = fConfigDileptonHadronOptions.fConfigMCGenSignalsJSON.value; + if (addMCSignalsGenStr != "") { + std::vector addMCSignals = dqmcsignals::GetMCSignalsFromJSON(addMCSignalsGenStr.Data()); + for (auto& mcIt : addMCSignals) { + if (mcIt->GetNProngs() > 2) { // NOTE: only 2 prong signals + continue; + } + fGenMCSignals.push_back(mcIt); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); + + fHistMan = new HistogramManager("analysisHistos", "", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Setup Histograms + if (fConfigEventOptions.fConfigEventQA) { + DefineHistograms(fHistMan, "TimeFrameStats;Event_BeforeCuts;Event_AfterCuts;", fConfigEventOptions.fConfigAddEventHistogram.value.data()); + DefineHistograms(fHistMan, "EventsMC", fConfigEventOptions.fConfigAddEventMCHistogram.value.data()); // mc + } + + if (fConfigTrackOptions.fConfigTrackQA) { + TString histClasses = "AssocsBarrel_BeforeCuts;"; + // Configure histogram classes for each track cut; + // Add histogram classes for each track cut and for each requested MC signal (reconstructed tracks with MC truth) + for (auto& cut : fTrackCuts) { + TString nameStr = Form("AssocsBarrel_%s", cut->GetName()); + fHistNamesReco.push_back(nameStr); + histClasses += Form("%s;", nameStr.Data()); + } + DefineHistograms(fHistMan, histClasses.Data(), fConfigTrackOptions.fConfigAddTrackHistogram.value.data()); + } + TString histNames = ""; + // check that the barrel track cuts array required in this task is not empty + if (!trackCutStr.IsNull()) { + // tokenize and loop over the barrel cuts produced by the barrel track selection task + std::unique_ptr objArray(trackCutStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + // if the current barrel selection cut is required in this task, then switch on the corresponding bit in the mask + // and assign histogram directories + + // assign the pair hist directories for the current cut + std::vector names = { + Form("PairsBarrelSEPM_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEMM_%s", objArray->At(icut)->GetName())}; + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fTrackHistNames[icut] = names; + // assign hist directories for the MC matched pairs for each (track cut,MCsignal) combination + if (!sigNamesStr.IsNull()) { + for (size_t isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); + names = { + Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + Form("PairsBarrelSEPP_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + Form("PairsBarrelSEMM_%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 + } + } + DefineHistograms(fHistMan, histNames.Data(), fConfigPairOptions.fConfigAddSEPHistogram.value.data()); + } + + for (size_t iCutTrack = 0; iCutTrack < fTrackCutNames.size(); iCutTrack++) { + for (size_t iCutHadron = 0; iCutHadron < fHadronCutNames.size(); iCutHadron++) { + DefineHistograms(fHistMan, Form("DileptonTrack_%s_%s", fTrackCutNames[iCutTrack].Data(), fHadronCutNames[iCutHadron].Data()), fConfigDileptonHadronOptions.fConfigAddDileptonHadronHistogram.value.data()); + for (auto& sig : fRecMCTripleSignals) { + DefineHistograms(fHistMan, Form("DileptonTrackMCMatched_%s_%s_%s", fTrackCutNames[iCutTrack].Data(), fHadronCutNames[iCutHadron].Data(), sig->GetName()), fConfigDileptonHadronOptions.fConfigAddDileptonHadronHistogram.value.data()); + if (isBarrelME) { + DefineHistograms(fHistMan, Form("DileptonTrackMCMatchedME_%s_%s_%s", fTrackCutNames[iCutTrack].Data(), fHadronCutNames[iCutHadron].Data(), sig->GetName()), fConfigDileptonHadronOptions.fConfigAddDileptonHadronHistogram.value.data()); + } + } + } + } + + for (auto& sig : fGenMCSignals) { + if (sig->GetNProngs() == 1) { + if (isMCGen_energycorrelators) { + DefineHistograms(fHistMan, Form("MCTruthGenSel_%s", sig->GetName()), ""); + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_%s", sig->GetName()), ""); + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelators_Pion_%s", sig->GetName()), ""); + } + if (isMCGen_energycorrelatorsME) { + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), ""); + DefineHistograms(fHistMan, Form("MCTruthEenergyCorrelatorsME_Pion_%s", sig->GetName()), ""); + } + } + } + + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // aditional histograms via JSON + + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + + fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + } + + template + void runDileptonHadron(TTrack1 const& track1, TTrack2 const& track2, int iEleCut, + THadron const& hadron, TEvent const& event, aod::McParticles const& /*mcParticles*/) + { + VarManager::ResetValues(0, VarManager::kNVars); // reset variables before filling + VarManager::FillEvent(event); + VarManager::FillTrack(hadron); + VarManager::FillTrackCollision(hadron, event); + + // Check that hadron is not one of the dilepton legs + if (hadron.globalIndex() == track1.globalIndex() || hadron.globalIndex() == track2.globalIndex()) { + return; + } + + if (!track1.has_mcParticle() || !track2.has_mcParticle() || !hadron.has_mcParticle()) { + return; + } + auto hadronMC = hadron.mcParticle(); + auto lepton1MC = track1.mcParticle(); + auto lepton2MC = track2.mcParticle(); + uint32_t mcDecision = 0; + int isig = 0; + for (auto sig = fRecMCTripleSignals.begin(); sig != fRecMCTripleSignals.end(); sig++, isig++) { + if ((*sig)->CheckSignal(true, lepton1MC, lepton2MC, hadronMC)) { + mcDecision |= (static_cast(1) << isig); + } + } + auto motherParticle = lepton1MC.template mothers_first_as(); + // Fill dilepton-hadron variables + std::vector fTransRange = fConfigDileptonHadronOptions.fConfigTransRange; + VarManager::FillEnergyCorrelatorTriple(track1, track2, hadron, VarManager::fgValues, fTransRange[0], fTransRange[1], fConfigDileptonHadronOptions.fConfigApplyMassEC.value); + if (fConfigDileptonHadronOptions.fConfigUsePionMass.value) { + VarManager::FillEnergyCorrelatorsUnfoldingTriple(track1, track2, hadron, motherParticle, hadronMC, VarManager::fgValues, fConfigDileptonHadronOptions.fConfigApplyMassEC.value); + } else { + VarManager::FillEnergyCorrelatorsUnfoldingTriple(track1, track2, hadron, motherParticle, hadronMC, VarManager::fgValues, fConfigDileptonHadronOptions.fConfigApplyMassEC.value); + } + + int iHadronCut = 0; + for (auto hCut = fHadronCuts.begin(); hCut != fHadronCuts.end(); hCut++, iHadronCut++) { + if (!(*hCut)->IsSelected(VarManager::fgValues)) { + continue; + } + // Fill the corresponding histogram + if (!MixedEvent) { + fHistMan->FillHistClass( + Form("DileptonTrack_%s_%s", fTrackCutNames[iEleCut].Data(), fHadronCutNames[iHadronCut].Data()), + VarManager::fgValues); + } + for (uint32_t isig = 0; isig < fRecMCTripleSignals.size(); isig++) { + if (mcDecision & (static_cast(1) << isig)) { + if (!MixedEvent) { + fHistMan->FillHistClass(Form("DileptonTrackMCMatched_%s_%s_%s", fTrackCutNames[iEleCut].Data(), fHadronCutNames[iHadronCut].Data(), fRecMCTripleSignals[isig]->GetName()), VarManager::fgValues); + } + if (MixedEvent) { + fHistMan->FillHistClass(Form("DileptonTrackMCMatchedME_%s_%s_%s", fTrackCutNames[iEleCut].Data(), fHadronCutNames[iHadronCut].Data(), fRecMCTripleSignals[isig]->GetName()), VarManager::fgValues); + } + } // end loop over MC signals + } + } + } + + // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) + template + void runSameEventPairing(TTrack1 const& t1, TTrack2 const& t2, int iEleCut, aod::McParticles const& /*mcParticles*/) + { + std::map> histNames = fTrackHistNames; + std::map> histNamesMC = fBarrelHistNamesMCmatched; + int sign1 = t1.sign(); + int sign2 = t2.sign(); + uint32_t mcDecision = static_cast(0); + // run MC matching for this pair + int isig = 0; + mcDecision = 0; + for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { + if (t1.has_mcParticle() && t2.has_mcParticle()) { + if ((*sig)->CheckSignal(true, t1.mcParticle(), t2.mcParticle())) { + mcDecision |= (static_cast(1) << isig); + } + } + } // end loop over MC signals + + VarManager::FillPair(t1, t2); + + if (sign1 * sign2 < 0) { // +- pairs + fHistMan->FillHistClass(histNames[iEleCut][0].Data(), VarManager::fgValues); // reconstructed, unmatched + for (size_t isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[iEleCut * fRecMCSignals.size() + isig][0].Data(), VarManager::fgValues); // matched signal + } + } + } else { + if (sign1 > 0) { // ++ pairs + fHistMan->FillHistClass(histNames[iEleCut][1].Data(), VarManager::fgValues); + for (size_t isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[iEleCut * fRecMCSignals.size() + isig][1].Data(), VarManager::fgValues); + } + } + } else { // -- pairs + fHistMan->FillHistClass(histNames[iEleCut][2].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { // loop over MC signals + if (mcDecision & (static_cast(1) << isig)) { + fHistMan->FillHistClass(histNamesMC[iEleCut * fRecMCSignals.size() + isig][2].Data(), VarManager::fgValues); + } + } + } + } + } + + void processBarrel(MyEvents const& events, aod::TrackAssoc const& assocs, MyBarrelTracksWithCov const& /*tracks*/, soa::Join const& mcEvents, aod::McParticles const& mcParticles, BCsWithTimestamps const& bcs) + { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillTimeFrame(bcs); + VarManager::FillTimeFrame(events); + VarManager::FillTimeFrame(mcEvents); + + if (events.size() == 0) + return; + + // CCDB initialization + if (fCurrentRun != bcs.begin().runNumber()) { + fCurrentRun = bcs.begin().runNumber(); + } + + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("TimeFrameStats", VarManager::fgValues); + } + + for (auto& event : mcEvents) { + // Reset the fValues array and fill event observables + VarManager::FillEvent(event); + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("EventsMC", VarManager::fgValues); + } + } + + // Event loop + for (auto& event : events) { + // Fill event variables first + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEvent(event); + + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); + } + + // Event selection + if (!fEventCut->IsSelected(VarManager::fgValues)) + continue; + + if (fConfigEventOptions.fConfigEventQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + } + + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + + // Get associated tracks for this event + auto groupedAssocs = assocs.sliceBy(preslice, event.globalIndex()); + + // Triple loop: track1 (electron) x track2 (electron) x hadron + for (auto& a1 : groupedAssocs) { + auto t1 = a1.template track_as(); + + uint32_t filter1 = 0; + // Fill track variables + VarManager::FillTrack(t1); + VarManager::FillTrackCollision(t1, event); + if (t1.has_mcParticle()) { + VarManager::FillTrackMC(mcParticles, t1.mcParticle()); + } + + if (fConfigTrackOptions.fConfigTrackQA) { + fHistMan->FillHistClass("AssocsBarrel_BeforeCuts", VarManager::fgValues); + } + + // Apply electron cuts and fill histograms + int iCut1 = 0; + for (auto cut1 = fTrackCuts.begin(); cut1 != fTrackCuts.end(); cut1++, iCut1++) { + if ((*cut1)->IsSelected(VarManager::fgValues)) { + filter1 |= (static_cast(1) << iCut1); + if (fConfigTrackOptions.fConfigTrackQA) { + fHistMan->FillHistClass(fHistNamesReco[iCut1], VarManager::fgValues); + } + } + } + + // Check opposite charge with t2 + for (auto& a2 : groupedAssocs) { + auto t2 = a2.template track_as(); + + // Avoid double counting: use track globalIndex + if (t2.globalIndex() <= t1.globalIndex()) { + continue; + } + + // Fill track variables for t2 (only once per t2) + VarManager::FillTrack(t2); + VarManager::FillTrackCollision(t2, event); + + // Compute filter2: which cuts t2 passes + uint32_t filter2 = 0; + int iCut2 = 0; + for (auto cut2 = fTrackCuts.begin(); cut2 != fTrackCuts.end(); cut2++, iCut2++) { + if ((*cut2)->IsSelected(VarManager::fgValues)) { + filter2 |= (static_cast(1) << iCut2); + } + } + + // Both tracks must pass at least one common cut + uint32_t twoTrackFilter = filter1 & filter2; + if (!twoTrackFilter) { + continue; + } + + // Fill pair histograms for all cuts that both tracks pass + for (size_t iCut = 0; iCut < fTrackCuts.size(); iCut++) { + if (twoTrackFilter & (static_cast(1) << iCut)) { + runSameEventPairing(t1, t2, iCut, mcParticles); + } + } + + float mass = VarManager::fgValues[VarManager::kMass]; + float pt = VarManager::fgValues[VarManager::kPt]; + float rap = VarManager::fgValues[VarManager::kRap]; + + // Apply J/psi cuts + if (mass < fConfigPairOptions.fConfigJpsiMassMin.value || mass > fConfigPairOptions.fConfigJpsiMassMax.value || + pt < fConfigPairOptions.fConfigJpsiPtMin.value || pt > fConfigPairOptions.fConfigJpsiPtMax.value || + std::abs(rap) > fConfigPairOptions.fConfigJpsiRapMax.value) { + continue; + } + + if (t1.sign() * t2.sign() >= 0) { + continue; // Must be opposite charge + } + + // correlate J/psi with hadrons + for (auto& aHadron : groupedAssocs) { + auto hadron = aHadron.template track_as(); + // Process dilepton-hadron correlation for each common cut + for (size_t iCut = 0; iCut < fTrackCuts.size(); iCut++) { + if (twoTrackFilter & (static_cast(1) << iCut)) { + runDileptonHadron(t1, t2, iCut, hadron, event, mcParticles); + } + } + } // end hadron loop + } // end track2 loop + } // end track1 loop + } // end event loop + } + + Filter eventFilter = nabs(aod::collision::posZ) < fConfigEventOptions.fConfigEventfilterVtz && aod::evsel::sel8 == true; + void processBarrelMixedEvent(soa::Filtered& events, aod::TrackAssoc const& assocs, MyBarrelTracksWithCov const& /*tracks*/, aod::McCollisions const& /*mcCollisions*/, aod::McParticles const& mcParticles, BCsWithTimestamps const& bcs) + { + if (events.size() == 0) { + return; + } + + // CCDB initialization + if (fCurrentRun != bcs.begin().runNumber()) { + fCurrentRun = bcs.begin().runNumber(); + } + + fSelMap.clear(); + // Event loop + for (auto& event : events) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event); + if (event.has_mcCollision()) { + VarManager::FillEvent(event.mcCollision()); + } + bool decision = false; + if (fEventCut->IsSelected(VarManager::fgValues)) { + decision = true; + } + fSelMap[event.globalIndex()] = decision; + } + + for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + if (!fSelMap[event1.globalIndex()] || !fSelMap[event2.globalIndex()]) { + continue; + } + + // save less events if configured + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + + // Get associated tracks for this event + auto groupedAssocs1 = assocs.sliceBy(preslice, event1.globalIndex()); + if (groupedAssocs1.size() < 2) { + continue; // Need at least 2 tracks for pairing + } + auto groupedAssocs2 = assocs.sliceBy(preslice, event2.globalIndex()); + + // Triple loop: track1 (electron) x track2 (electron) x hadron + for (auto& a1 : groupedAssocs1) { + auto t1 = a1.template track_as(); + + uint32_t filter1 = 0; + // Fill track variables + VarManager::FillTrack(t1); + VarManager::FillTrackCollision(t1, event1); + + // Apply electron cuts and fill histograms + int iCut1 = 0; + for (auto cut1 = fTrackCuts.begin(); cut1 != fTrackCuts.end(); cut1++, iCut1++) { + if ((*cut1)->IsSelected(VarManager::fgValues)) { + filter1 |= (static_cast(1) << iCut1); + } + } + + // Check opposite charge with t2 + for (auto& a2 : groupedAssocs1) { + auto t2 = a2.template track_as(); + + // Avoid double counting: use track globalIndex + if (t2.globalIndex() <= t1.globalIndex()) + continue; + + // Fill track variables for t2 (only once per t2) + VarManager::FillTrack(t2); + VarManager::FillTrackCollision(t2, event1); + + // Compute filter2: which cuts t2 passes + uint32_t filter2 = 0; + int iCut2 = 0; + for (auto cut2 = fTrackCuts.begin(); cut2 != fTrackCuts.end(); cut2++, iCut2++) { + if ((*cut2)->IsSelected(VarManager::fgValues)) { + filter2 |= (static_cast(1) << iCut2); + } + } + + // Both tracks must pass at least one common cut + uint32_t twoTrackFilter = filter1 & filter2; + if (!twoTrackFilter) { + continue; + } + // Fill pair variables for cut + VarManager::FillPair(t1, t2, VarManager::fgValues); + float mass = VarManager::fgValues[VarManager::kMass]; + float pt = VarManager::fgValues[VarManager::kPt]; + float rap = VarManager::fgValues[VarManager::kRap]; + // Apply J/psi cuts + if (mass < fConfigPairOptions.fConfigJpsiMassMin.value || mass > fConfigPairOptions.fConfigJpsiMassMax.value || + pt < fConfigPairOptions.fConfigJpsiPtMin.value || pt > fConfigPairOptions.fConfigJpsiPtMax.value || + std::abs(rap) > fConfigPairOptions.fConfigJpsiRapMax.value) { + continue; + } + if (t1.sign() * t2.sign() >= 0) { + continue; // Must be opposite charge + } + // correlate J/psi with hadrons from different events + for (auto& aHadron : groupedAssocs2) { + auto hadron = aHadron.template track_as(); + // Process dilepton-hadron correlation for each common cut + for (size_t iCut = 0; iCut < fTrackCuts.size(); iCut++) { + if (twoTrackFilter & (static_cast(1) << iCut)) { + runDileptonHadron(t1, t2, iCut, hadron, event2, mcParticles); + } + } + } // end hadron loop + } // end track2 loop + } // end track1 loop + } // end event loop + } + + PresliceUnsorted perReducedMcEvent = aod::mcparticle::mcCollisionId; + template + void runEnergyCorrelators(TEvent const& event1, TEvent const& event2, McParticles const& mcTracks) + { + auto groupedMCTracks1 = mcTracks.sliceBy(perReducedMcEvent, event1.mcCollisionId()); + auto groupedMCTracks2 = mcTracks.sliceBy(perReducedMcEvent, event2.mcCollisionId()); + groupedMCTracks1.bindInternalIndicesTo(&mcTracks); + groupedMCTracks2.bindInternalIndicesTo(&mcTracks); + for (auto& t1 : groupedMCTracks1) { + auto t1_raw = mcTracks.rawIteratorAt(t1.globalIndex()); + for (auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, t1_raw)) { + if (t1.mcCollisionId() != event1.mcCollisionId()) { // check that the mc track belongs to the same mc collision as the reconstructed event + continue; + } + VarManager::FillTrackMC(mcTracks, t1_raw); + if (!MixedEvent && !PionMass) { + fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); + } + } + } + // apply kinematic cuts for signal + if ((t1_raw.pt() < fConfigPairOptions.fConfigJpsiPtMin || t1_raw.pt() > fConfigPairOptions.fConfigJpsiPtMax)) + continue; + if (std::abs(t1_raw.y()) > fConfigPairOptions.fConfigJpsiRapMax) + continue; + // for the energy correlators + for (auto& t2 : groupedMCTracks2) { + auto t2_raw = groupedMCTracks2.rawIteratorAt(t2.globalIndex()); + if (t2.mcCollisionId() != event2.mcCollisionId()) { // check that the mc track belongs to the same mc collision as the reconstructed event + continue; + } + if (!t2_raw.isPhysicalPrimary()) { + continue; + } + if (t2_raw.has_mothers()) { + auto mother_raw = t2_raw.template mothers_first_as(); + if (mother_raw.globalIndex() == t1_raw.globalIndex()) { + continue; + } + } + if (fConfigDileptonHadronOptions.fConfigContainlepton && std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton && std::abs(t2_raw.pdgCode()) != PDG_t::kElectron && std::abs(t2_raw.pdgCode()) != PDG_t::kMuonMinus) { + continue; + } + if (!fConfigDileptonHadronOptions.fConfigContainlepton && std::abs(t2_raw.pdgCode()) != PDG_t::kPiPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kKPlus && std::abs(t2_raw.pdgCode()) != PDG_t::kProton) { + continue; + } + if (t2_raw.pt() < fConfigDileptonHadronOptions.fConfigMCGenHadronPtMin.value || std::abs(t2_raw.eta()) > fConfigDileptonHadronOptions.fConfigMCGenHadronEtaAbs.value) { + continue; + } + std::vector fTransRange = fConfigDileptonHadronOptions.fConfigTransRange; + VarManager::FillEnergyCorrelatorsMC(t1_raw, t2_raw, VarManager::fgValues, fTransRange[0], fTransRange[1]); + for (auto& sig : fGenMCSignals) { + if (sig->CheckSignal(true, t1_raw)) { + if (!MixedEvent && !PionMass) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_%s", sig->GetName()), VarManager::fgValues); + } + if (MixedEvent && !PionMass) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_%s", sig->GetName()), VarManager::fgValues); + } + if (!MixedEvent && PionMass) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelators_Pion_%s", sig->GetName()), VarManager::fgValues); + } + if (MixedEvent && PionMass) { + fHistMan->FillHistClass(Form("MCTruthEenergyCorrelatorsME_Pion_%s", sig->GetName()), VarManager::fgValues); + } + } + } + } + } + } + + void processMCGenEnergyCorrelators(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + for (auto& event : events) { + // Fill event variables first + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event, event, mcTracks); + } + } + + void processMCGenEnergyCorrelatorsME(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + // loop over two event comibnations + for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + VarManager::FillEvent(event2); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event1.has_mcCollision() || !event2.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event1, event2, mcTracks); + } + } + + void processMCGenEnergyCorrelatorsPion(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + for (auto& event : events) { + // Fill event variables first + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event, event, mcTracks); + } + } + + void processMCGenEnergyCorrelatorsPionME(soa::Filtered& events, + McCollisions const& /*mcEvents*/, McParticles const& mcTracks) + { + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + // loop over two event comibnations + for (auto& [event1, event2] : selfCombinations(*fMixingBinning, fConfigEventOptions.fConfigMixingDepth.value, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + VarManager::FillEvent(event2); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + continue; + } + if (!event1.has_mcCollision() || !event2.has_mcCollision()) { + continue; + } + // saveless events for the energy correlator analysis + std::vector fSavelessevents = fConfigDileptonHadronOptions.fConfigSavelessevents.value; + if (fSavelessevents[0] > 1 && event1.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) { + continue; + } + runEnergyCorrelators(event1, event2, mcTracks); + } + } + + void processDummy(aod::Collisions const&) + { + // Do nothing + } + + PROCESS_SWITCH(AnalysisEnergyCorrelator, processBarrel, "Process barrel analysis", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processBarrelMixedEvent, "Run barrel dilepton-hadron mixed event pairing", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelators, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelatorsPion, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelatorsME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processMCGenEnergyCorrelatorsPionME, "Loop over MC particle stack and fill generator level histograms(energy correlators)", false); + PROCESS_SWITCH(AnalysisEnergyCorrelator, processDummy, "Dummy process function", true); +}; + +// Histogram definitions +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) +{ + 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 = histGroups; + // NOTE: The level of detail for histogramming can be controlled via configurables + if (classStr.Contains("TimeFrameStats")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "timeframe"); + } + if (classStr.Contains("Event")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "event", histName); + } + if ((classStr.Contains("Track") || classStr.Contains("Assoc")) && !classStr.Contains("Pairs")) { + if (classStr.Contains("Barrel")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + } + } + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + if (classStr.Contains("DileptonTrack")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-track", histName); + } + if (classStr.Contains("MCTruthEenergyCorrelators")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "energy-correlator-gen"); + } + if (classStr.Contains("MCTruthGenSel")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_track"); + } + } // end loop over histogram classes +} + +// Workflow definition +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGDQ/Tasks/dqFlow.cxx b/PWGDQ/Tasks/dqFlow.cxx index 52e3ca8c29c..547068bab36 100644 --- a/PWGDQ/Tasks/dqFlow.cxx +++ b/PWGDQ/Tasks/dqFlow.cxx @@ -16,42 +16,51 @@ /// o2-analysis-timestamp --aod-file AO2D.root -b | o2-analysis-event-selection -b | o2-analysis-multiplicity-table -b | o2-analysis-centrality-table -b | o2-analysis-fdd-converter -b | o2-analysis-trackselection -b | o2-analysis-trackextension -b | o2-analysis-pid-tpc-full -b | o2-analysis-pid-tof-full -b | o2-analysis-pid-tof-base -b | o2-analysis-pid-tof-beta -b | o2-analysis-dq-flow -b /// tested (June 2, 2022) on AO2D.root files from train production 242 -#include -#include -#include -#include -#include -#include -#include -#include -#include "CCDB/BasicCCDBManager.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 "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" #include "PWGCF/GenericFramework/Core/GFWCumulant.h" -#include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" -#include "PWGCF/GenericFramework/Core/GFWConfig.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include using std::complex; -using std::cout; -using std::endl; using std::pow; using std::string; @@ -59,7 +68,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; -using namespace o2::analysis; // Declarations of various short names using MyBcs = soa::Join; diff --git a/PWGDQ/Tasks/filterPP.cxx b/PWGDQ/Tasks/filterPP.cxx index 61065f3fc74..1bfa487594e 100644 --- a/PWGDQ/Tasks/filterPP.cxx +++ b/PWGDQ/Tasks/filterPP.cxx @@ -19,35 +19,35 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/TriggerAliases.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/filterTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include + +#include +#include +#include #include -#include #include #include #include #include -using std::cout; -using std::endl; using std::string; using namespace o2; diff --git a/PWGDQ/Tasks/filterPPwithAssociation.cxx b/PWGDQ/Tasks/filterPPwithAssociation.cxx index 850b5811d8a..5cce787ffd7 100644 --- a/PWGDQ/Tasks/filterPPwithAssociation.cxx +++ b/PWGDQ/Tasks/filterPPwithAssociation.cxx @@ -19,35 +19,33 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/TriggerAliases.h" -#include "Common/Core/CollisionAssociation.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/filterTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include +#include + +#include +#include +#include #include #include #include diff --git a/PWGDQ/Tasks/filterPbPb.cxx b/PWGDQ/Tasks/filterPbPb.cxx index f127a7f3c26..8132956aa5b 100644 --- a/PWGDQ/Tasks/filterPbPb.cxx +++ b/PWGDQ/Tasks/filterPbPb.cxx @@ -9,17 +9,27 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // + #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGUD/Core/SGCutParHolder.h" #include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/Core/UPCHelpers.h" -#include "CommonConstants/LHCConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Vertex.h" -#include +#include "Common/DataModel/EventSelection.h" -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include #include diff --git a/PWGDQ/Tasks/mchAlignRecord.cxx b/PWGDQ/Tasks/mchAlignRecord.cxx index c3dbce0865f..e2a9814bd20 100644 --- a/PWGDQ/Tasks/mchAlignRecord.cxx +++ b/PWGDQ/Tasks/mchAlignRecord.cxx @@ -16,58 +16,45 @@ #include "PWGDQ/Core/VarManager.h" -#include "Common/DataModel/EventSelection.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "CommonUtils/NameConf.h" -#include "DataFormatsMCH/Cluster.h" -#include "DataFormatsMCH/TrackMCH.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GRPGeomHelper.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsCommonDataFormats/AlignParam.h" -#include "DetectorsCommonDataFormats/DetID.h" -#include "DetectorsCommonDataFormats/DetectorNameConf.h" -#include "Framework/AnalysisTask.h" -#include "Framework/CallbackService.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" -#include "MCHAlign/Aligner.h" -#include "MCHBase/TrackerParam.h" -#include "MCHGeometryTransformer/Transformations.h" -#include "MCHTracking/Track.h" -#include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackFitter.h" -#include "MCHTracking/TrackParam.h" -#include "ReconstructionDataFormats/TrackMCHMID.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -#include -#include -#include -#include -#include -#include -#include +#include +#include + +#include +#include #include -#include -#include +#include +#include +#include +#include #include #include -#include #include using namespace o2; @@ -76,8 +63,6 @@ using namespace o2::framework::expressions; using namespace o2::aod; using namespace std; -using std::cout; -using std::endl; const int fgNCh = 10; const int fgNDetElemCh[fgNCh] = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26}; diff --git a/PWGDQ/Tasks/mftMchMatcher.cxx b/PWGDQ/Tasks/mftMchMatcher.cxx new file mode 100644 index 00000000000..321cacb238d --- /dev/null +++ b/PWGDQ/Tasks/mftMchMatcher.cxx @@ -0,0 +1,723 @@ +// 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 mftMchMatcher.cxx +/// \brief MFT-MCH matching tool for data preparation + +#include "PWGDQ/Core/VarManager.h" + +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod; + +using MyEvents = soa::Join; +using MyMuonsWithCov = soa::Join; +using MyMuonsMC = soa::Join; +using MyMFTs = aod::MFTTracks; +using MyMFTCovariances = aod::MFTTracksCov; +using MyMFTsMC = soa::Join; + +using MyMuon = MyMuonsWithCov::iterator; +using MyMuonMC = MyMuonsMC::iterator; +using MyMFT = MyMFTs::iterator; +using MyMFTCovariance = MyMFTCovariances::iterator; + +using namespace std; + +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix55Std = ROOT::Math::SMatrix; +using SMatrix5 = ROOT::Math::SVector; + +namespace o2::aod +{ +namespace fwdmatchcandidates +{ +DECLARE_SOA_COLUMN(XMCH, xMCH, float); +DECLARE_SOA_COLUMN(YMCH, yMCH, float); +DECLARE_SOA_COLUMN(PhiMCH, phiMCH, float); +DECLARE_SOA_COLUMN(TanlMCH, tanlMCH, float); +DECLARE_SOA_COLUMN(InvQPtMCH, invQPtMCH, float); +DECLARE_SOA_COLUMN(TimeMCH, timeMCH, float); +DECLARE_SOA_COLUMN(TimeResMCH, timeResMCH, float); +DECLARE_SOA_COLUMN(Chi2MCH, chi2MCH, float); +DECLARE_SOA_COLUMN(Rabs, rabs, float); +DECLARE_SOA_COLUMN(PDCA, pDCA, float); +DECLARE_SOA_COLUMN(McMaskMCH, mcMaskMCH, int); + +DECLARE_SOA_COLUMN(CXXMCH, cXXMCH, float); +DECLARE_SOA_COLUMN(CYYMCH, cYYMCH, float); +DECLARE_SOA_COLUMN(CPhiPhiMCH, cPhiPhiMCH, float); +DECLARE_SOA_COLUMN(CTglTglMCH, cTglTglMCH, float); +DECLARE_SOA_COLUMN(C1Pt1PtMCH, c1Pt1PtMCH, float); +DECLARE_SOA_COLUMN(CXYMCH, cXYMCH, float); +DECLARE_SOA_COLUMN(CPhiXMCH, cPhiXMCH, float); +DECLARE_SOA_COLUMN(CPhiYMCH, cPhiYMCH, float); +DECLARE_SOA_COLUMN(CTglXMCH, cTglXMCH, float); +DECLARE_SOA_COLUMN(CTglYMCH, cTglYMCH, float); +DECLARE_SOA_COLUMN(CTglPhiMCH, cTglPhiMCH, float); +DECLARE_SOA_COLUMN(C1PtXMCH, c1PtXMCH, float); +DECLARE_SOA_COLUMN(C1PtYMCH, c1PtYMCH, float); +DECLARE_SOA_COLUMN(C1PtPhiMCH, c1PtPhiMCH, float); +DECLARE_SOA_COLUMN(C1PtTglMCH, c1PtTglMCH, float); + +DECLARE_SOA_COLUMN(XMFT, xMFT, float); +DECLARE_SOA_COLUMN(YMFT, yMFT, float); +DECLARE_SOA_COLUMN(PhiMFT, phiMFT, float); +DECLARE_SOA_COLUMN(TanlMFT, tanlMFT, float); +DECLARE_SOA_COLUMN(InvQPtMFT, invQPtMFT, float); +DECLARE_SOA_COLUMN(TimeMFT, timeMFT, float); +DECLARE_SOA_COLUMN(TimeResMFT, timeResMFT, float); +DECLARE_SOA_COLUMN(Chi2MFT, chi2MFT, float); +DECLARE_SOA_COLUMN(McMaskMFT, mcMaskMFT, int); +DECLARE_SOA_COLUMN(MftClusterSizesAndTrackFlags, mftClusterSizesAndTrackFlags, uint64_t); + +DECLARE_SOA_COLUMN(CXXMFT, cXXMFT, float); +DECLARE_SOA_COLUMN(CYYMFT, cYYMFT, float); +DECLARE_SOA_COLUMN(CPhiPhiMFT, cPhiPhiMFT, float); +DECLARE_SOA_COLUMN(CTglTglMFT, cTglTglMFT, float); +DECLARE_SOA_COLUMN(C1Pt1PtMFT, c1Pt1PtMFT, float); +DECLARE_SOA_COLUMN(CXYMFT, cXYMFT, float); +DECLARE_SOA_COLUMN(CPhiYMFT, cPhiYMFT, float); +DECLARE_SOA_COLUMN(CPhiXMFT, cPhiXMFT, float); +DECLARE_SOA_COLUMN(CTglXMFT, cTglXMFT, float); +DECLARE_SOA_COLUMN(CTglYMFT, cTglYMFT, float); +DECLARE_SOA_COLUMN(CTglPhiMFT, cTglPhiMFT, float); +DECLARE_SOA_COLUMN(C1PtXMFT, c1PtXMFT, float); +DECLARE_SOA_COLUMN(C1PtYMFT, c1PtYMFT, float); +DECLARE_SOA_COLUMN(C1PtPhiMFT, c1PtPhiMFT, float); +DECLARE_SOA_COLUMN(C1PtTglMFT, c1PtTglMFT, float); + +DECLARE_SOA_COLUMN(Chi2Glob, chi2Glob, float); +DECLARE_SOA_COLUMN(Chi2Match, chi2Match, float); +DECLARE_SOA_COLUMN(IsAmbig, isAmbig, bool); +DECLARE_SOA_COLUMN(MFTMult, mftMult, int); +DECLARE_SOA_COLUMN(DCAX, dcaX, float); +DECLARE_SOA_COLUMN(DCAY, dcaY, float); +DECLARE_SOA_COLUMN(McMaskGlob, mcMaskGlob, int); +DECLARE_SOA_COLUMN(MatchLabel, matchLabel, int); +DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); +} // namespace fwdmatchcandidates + +DECLARE_SOA_TABLE(FwdMatchMLCandidates, "AOD", "FWDMLCAND", + fwdmatchcandidates::XMCH, + fwdmatchcandidates::YMCH, + fwdmatchcandidates::PhiMCH, + fwdmatchcandidates::TanlMCH, + fwdmatchcandidates::InvQPtMCH, + fwdmatchcandidates::TimeMCH, + fwdmatchcandidates::TimeResMCH, + fwdmatchcandidates::Chi2MCH, + fwdmatchcandidates::PDCA, + fwdmatchcandidates::Rabs, + fwdmatchcandidates::CXXMCH, + fwdmatchcandidates::CYYMCH, + fwdmatchcandidates::CPhiPhiMCH, + fwdmatchcandidates::CTglTglMCH, + fwdmatchcandidates::C1Pt1PtMCH, + fwdmatchcandidates::CXYMCH, + fwdmatchcandidates::CPhiYMCH, + fwdmatchcandidates::CPhiXMCH, + fwdmatchcandidates::CTglXMCH, + fwdmatchcandidates::CTglYMCH, + fwdmatchcandidates::CTglPhiMCH, + fwdmatchcandidates::C1PtXMCH, + fwdmatchcandidates::C1PtYMCH, + fwdmatchcandidates::C1PtPhiMCH, + fwdmatchcandidates::C1PtTglMCH, + fwdmatchcandidates::XMFT, + fwdmatchcandidates::YMFT, + fwdmatchcandidates::PhiMFT, + fwdmatchcandidates::TanlMFT, + fwdmatchcandidates::InvQPtMFT, + fwdmatchcandidates::TimeMFT, + fwdmatchcandidates::TimeResMFT, + fwdmatchcandidates::Chi2MFT, + fwdmatchcandidates::MftClusterSizesAndTrackFlags, + fwdmatchcandidates::CXXMFT, + fwdmatchcandidates::CYYMFT, + fwdmatchcandidates::CPhiPhiMFT, + fwdmatchcandidates::CTglTglMFT, + fwdmatchcandidates::C1Pt1PtMFT, + fwdmatchcandidates::CXYMFT, + fwdmatchcandidates::CPhiYMFT, + fwdmatchcandidates::CPhiXMFT, + fwdmatchcandidates::CTglXMFT, + fwdmatchcandidates::CTglYMFT, + fwdmatchcandidates::CTglPhiMFT, + fwdmatchcandidates::C1PtXMFT, + fwdmatchcandidates::C1PtYMFT, + fwdmatchcandidates::C1PtPhiMFT, + fwdmatchcandidates::C1PtTglMFT, + fwdmatchcandidates::Chi2Glob, + fwdmatchcandidates::Chi2Match, + fwdmatchcandidates::DCAX, + fwdmatchcandidates::DCAY, + fwdmatchcandidates::IsAmbig, + fwdmatchcandidates::MFTMult, + fwdmatchcandidates::McMaskMCH, + fwdmatchcandidates::McMaskMFT, + fwdmatchcandidates::McMaskGlob, + fwdmatchcandidates::MatchLabel, + fwdmatchcandidates::IsSignal); +} // namespace o2::aod + +struct mftMchMatcher { + Produces fwdMatchMLCandidates; + //// Variables for selecting muon tracks + Configurable fPMchLow{"cfgPMchLow", 0.0f, ""}; + Configurable fPtMchLow{"cfgPtMchLow", 0.7f, ""}; + Configurable fEtaMchLow{"cfgEtaMchLow", -4.0f, ""}; + Configurable fEtaMchUp{"cfgEtaMchUp", -2.5f, ""}; + Configurable fRabsLow{"cfgRabsLow", 17.6f, ""}; + Configurable fRabsUp{"cfgRabsUp", 89.5f, ""}; + Configurable fSigmaPdcaUp{"cfgPdcaUp", 6.f, ""}; + Configurable fTrackChi2MchUp{"cfgTrackChi2MchUp", 5.f, ""}; + Configurable fMatchingChi2MchMidUp{"cfgMatchingChi2MchMidUp", 999.f, ""}; + + //// Variables for selecting mft tracks + Configurable fEtaMFTLow{"cfgEtaMFTlow", -3.6f, ""}; + Configurable fEtaMFTUp{"cfgEtaMFTup", -2.5f, ""}; + Configurable fTrackChi2MFTUp{"cfgTrackChi2MFTUp", 10.f, ""}; + Configurable fPtMFTLow{"cfgPtMFTLow", 0.1f, ""}; + + //// Variables for matching configuration + Configurable fMaxCandidates{"cfgMaxCandidates", 0, ""}; + + Configurable fKeepBestMatch{"cfgKeepBestMatch", false, "Keep only the best match global muons in the skimming"}; + Configurable fzMatching{"cfgzMatching", -77.5f, "Plane for MFT-MCH matching"}; + + //// Variables for ccdb + 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"}; + + enum MuonMatchType { + kMatchTypeTrueLeading = 0, + kMatchTypeWrongLeading = 1, + kMatchTypeDecayLeading = 2, + kMatchTypeFakeLeading = 3, + kMatchTypeTrueNonLeading = 4, + kMatchTypeWrongNonLeading = 5, + kMatchTypeDecayNonLeading = 6, + kMatchTypeFakeNonLeading = 7, + kMatchTypeUndefined + }; + + double mBzAtMftCenter{0}; + o2::globaltracking::MatchGlobalFwd mExtrap; + + int mRunNumber{0}; // needed to detect if the run changed and trigger update of magnetic field + Service ccdbManager; + o2::ccdb::CcdbApi fCCDBApi; + + o2::parameters::GRPMagField* fGrpMag = nullptr; + + o2::globaltracking::MatchGlobalFwd mMatching; + + std::unordered_map mftCovIndexes; + + std::map fBestMatch; + + HistogramRegistry registry{"registry", {}}; + + template + bool pDCACut(const T& mchTrack, const C& collision, double nSigmaPDCA) + { + static const double sigmaPDCA23 = 80.; + static const double sigmaPDCA310 = 54.; + static const double relPRes = 0.0004; + static const double slopeRes = 0.0005; + + double thetaAbs = TMath::ATan(mchTrack.rAtAbsorberEnd() / 505.) * TMath::RadToDeg(); + + // propagate muon track to vertex + auto trackConv = VarManager::FwdToTrackPar(mchTrack, mchTrack); + o2::dataformats::GlobalFwdTrack track; + track.setParameters(trackConv.getParameters()); + track.setZ(trackConv.getZ()); + track.setCovariances(trackConv.getCovariances()); + auto mchTrackAtVertex = mMatching.FwdtoMCH(track); + o2::mch::TrackExtrap::extrapToVertex(mchTrackAtVertex, collision.posX(), collision.posY(), collision.posZ(), collision.covXX(), collision.covYY()); + + // double pUncorr = mchTrack.p(); + double p = mchTrackAtVertex.p(); + + double pDCA = mchTrack.pDca(); + double sigmaPDCA = (thetaAbs < 3) ? sigmaPDCA23 : sigmaPDCA310; + double nrp = nSigmaPDCA * relPRes * p; + double pResEffect = sigmaPDCA / (1. - nrp / (1. + nrp)); + double slopeResEffect = 535. * slopeRes * p; + double sigmaPDCAWithRes = TMath::Sqrt(pResEffect * pResEffect + slopeResEffect * slopeResEffect); + if (pDCA > nSigmaPDCA * sigmaPDCAWithRes) { + return false; + } + + return true; + } + + template + bool IsGoodMuon(const T& mchTrack, const C& collision, + double chi2Cut, + double pCut, + double pTCut, + std::array etaCut, + std::array rAbsCut, + double nSigmaPdcaCut) + { + // chi2 cut + if (mchTrack.chi2() > chi2Cut) + return false; + + // momentum cut + if (mchTrack.p() < pCut) { + return false; // skip low-momentum tracks + } + + // transverse momentum cut + if (mchTrack.pt() < pTCut) { + return false; // skip low-momentum tracks + } + + // Eta cut + double eta = mchTrack.eta(); + if ((eta < etaCut[0] || eta > etaCut[1])) { + return false; + } + + // RAbs cut + double rAbs = mchTrack.rAtAbsorberEnd(); + if ((rAbs < rAbsCut[0] || rAbs > rAbsCut[1])) { + return false; + } + + // pDCA cut + if (!pDCACut(mchTrack, collision, nSigmaPdcaCut)) { + return false; + } + + return true; + } + + template + bool IsGoodMFT(const T& mftTrack, + double chi2Cut, + double pTCut, + std::array etaCut) + { + // chi2 cut + if (mftTrack.chi2() > chi2Cut) + return false; + + // transverse momentum cut + if (mftTrack.pt() < pTCut) { + return false; // skip low-momentum tracks + } + + // Eta cut + double eta = mftTrack.eta(); + if ((eta < etaCut[0] || eta > etaCut[1])) { + return false; + } + + return true; + } + + template + void initCCDB(BC const& bc) + { + if (mRunNumber == bc.runNumber()) + return; + + fGrpMag = ccdbManager->getForTimeStamp(grpmagPath, bc.timestamp()); + + if (fGrpMag != nullptr) { + o2::base::Propagator::initFieldFromGRP(fGrpMag); + VarManager::SetMagneticField(fGrpMag->getNominalL3Field()); + VarManager::SetupMuonMagField(); + } + mRunNumber = bc.runNumber(); + } + + void init(o2::framework::InitContext&) + { + // Load geometry + ccdbManager->setURL(ccdburl); + ccdbManager->setCaching(true); + ccdbManager->setLocalObjectValidityChecking(); + fCCDBApi.init(ccdburl); + mRunNumber = 0; + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + LOGF(info, "Load geometry from CCDB"); + ccdbManager->get(geoPath); + } + + // int matchTypeMax = static_cast(kMatchTypeUndefined); + AxisSpec matchTypeAxis = {static_cast(kMatchTypeUndefined), 0, static_cast(kMatchTypeUndefined), ""}; + auto hMatchType = std::get>(registry.add("matchType", "Match type", {HistType::kTH1F, {matchTypeAxis}})); + hMatchType->GetXaxis()->SetBinLabel(1, "true (leading)"); + hMatchType->GetXaxis()->SetBinLabel(2, "wrong (leading)"); + hMatchType->GetXaxis()->SetBinLabel(3, "decay (leading)"); + hMatchType->GetXaxis()->SetBinLabel(4, "fake (leading)"); + hMatchType->GetXaxis()->SetBinLabel(5, "true (non leading)"); + hMatchType->GetXaxis()->SetBinLabel(6, "wrong (non leading)"); + hMatchType->GetXaxis()->SetBinLabel(7, "decay (non leading)"); + hMatchType->GetXaxis()->SetBinLabel(8, "fake (non leading)"); + } + + template + void fillBestMuonMatches(TMuons const& muons) + { + fBestMatch.clear(); + std::unordered_map> mCandidates; + for (const auto& muon : muons) { + if (static_cast(muon.trackType()) < 2) { + auto muonID = muon.matchMCHTrackId(); + auto chi2 = muon.chi2MatchMCHMFT(); + if (mCandidates.find(muonID) == mCandidates.end()) { + mCandidates[muonID] = {chi2, muon.globalIndex()}; + } else { + if (chi2 < mCandidates[muonID].first) { + mCandidates[muonID] = {chi2, muon.globalIndex()}; + } + } + } + } + for (auto& pairCand : mCandidates) { + fBestMatch[pairCand.second.second] = true; + } + } + + template + void fillMatchablePairs(TMUON const& muonTracks, + TMFT const& mftTracks, + std::vector>& matchablePairs) + { + static constexpr int muonPdgCode = 13; + + // outer loop on muon tracks + for (const auto& muonTrack : muonTracks) { + // only consider MCH standalone or MCH-MID matches + if (static_cast(muonTrack.trackType()) <= 2) { + continue; + } + + // only consider tracks associated to some collision + if (!muonTrack.has_collision()) { + continue; + } + auto muonCollisionId = muonTrack.collisionId(); + + // skip tracks that do not have an associated MC particle + if (!muonTrack.has_mcParticle()) { + continue; + } + // get the index associated to the MC particle + auto muonMcParticle = muonTrack.mcParticle(); + if (std::abs(muonMcParticle.pdgCode()) != muonPdgCode) { + continue; + } + + int64_t muonMcTrackIndex = muonMcParticle.globalIndex(); + + // inner loop on MFT tracks + for (const auto& mftTrack : mftTracks) { + // only consider MFT tracks associated to the same collision as the muon track + if (!mftTrack.has_collision()) { + continue; + } + auto mftCollisionId = mftTrack.collisionId(); + if (mftCollisionId != muonCollisionId) { + continue; + } + + // skip tracks that do not have an associated MC particle + if (!mftTrack.has_mcParticle()) { + continue; + } + // get the index associated to the MC particle + auto mftMcParticle = mftTrack.mcParticle(); + int64_t mftMcTrackIndex = mftMcParticle.globalIndex(); + + if (muonMcTrackIndex == mftMcTrackIndex) { + matchablePairs.emplace_back(std::make_pair(static_cast(muonTrack.globalIndex()), + static_cast(mftTrack.globalIndex()))); + } + } + } + } + + bool isPairedMuon(int64_t muonTrackId, const std::vector>& matchablePairs) + { + for (const auto& [id1, id2] : matchablePairs) { + if (muonTrackId == id1) + return true; + } + return false; + } + + template + bool isDecay(TMCH const& mchTrack, TMFTs const& mftTracks) + { + const auto& mchMcParticle = mchTrack.mcParticle(); + + const auto& mchMotherParticles = mchMcParticle.template mothers_as(); + if (mchMotherParticles.empty()) { + return false; + } + const auto& mchMotherParticle = mchMotherParticles[0]; + + // search for an MFT track that is associated to the MCH mother particle + for (const auto& mftTrack : mftTracks) { + // skip tracks that do not have an associated MC particle + if (!mftTrack.has_mcParticle()) + continue; + + if (mftTrack.mcParticle().globalIndex() == mchMotherParticle.globalIndex()) { + return true; + } + } + + return false; + } + + template + MuonMatchType getMatchType(const TMUON& muonTrack, + TMUONS const& /*muonTracks*/, + TMFTS const& mftTracks, + const std::vector>& matchablePairs, + bool isBestMatch) + { + MuonMatchType result{kMatchTypeUndefined}; + + if (static_cast(muonTrack.trackType()) > 2) { + return result; + } + + auto const& mchTrack = muonTrack.template matchMCHTrack_as(); + auto const& mftTrack = muonTrack.template matchMFTTrack_as(); + + if (!muonTrack.has_mcParticle() || !mftTrack.has_mcParticle()) { + return result; + } + + bool isPaired = isPairedMuon(mchTrack.globalIndex(), matchablePairs); + std::pair matchPair{mchTrack.globalIndex(), mftTrack.globalIndex()}; + bool isTrueMatch = std::find(matchablePairs.begin(), matchablePairs.end(), matchPair) != matchablePairs.end(); + + if (isPaired) { + if (isTrueMatch) { + result = (isBestMatch) ? kMatchTypeTrueLeading : kMatchTypeTrueNonLeading; + } else { + result = isBestMatch ? kMatchTypeWrongLeading : kMatchTypeWrongNonLeading; + } + } else if (isDecay(mchTrack, mftTracks)) { + result = isBestMatch ? kMatchTypeDecayLeading : kMatchTypeDecayNonLeading; + } else { + result = isBestMatch ? kMatchTypeFakeLeading : kMatchTypeFakeNonLeading; + } + + return result; + } + + void processMC(MyEvents const& collisions, + aod::BCsWithTimestamps const& bcs, + MyMuonsMC const& muonTracks, + MyMFTsMC const& mftTracks, + MyMFTCovariances const& mftCovs, + aod::McParticles const& /*mcParticles*/) + { + if (bcs.size() > 0) { + auto bc = bcs.begin(); + initCCDB(bc); + VarManager::SetMatchingPlane(fzMatching.value); + } + + fillBestMuonMatches(muonTracks); + + std::vector> matchablePairs; + fillMatchablePairs(muonTracks, mftTracks, matchablePairs); + + mftCovIndexes.clear(); + for (auto& mftTrackCov : mftCovs) { + mftCovIndexes[mftTrackCov.matchMFTTrackId()] = mftTrackCov.globalIndex(); + } + + fwdMatchMLCandidates.reserve(muonTracks.size()); + + for (auto muon : muonTracks) { + // only consider global MFT-MCH-MID matches + if (static_cast(muon.trackType()) != 0) { + continue; + } + + if (!muon.has_collision()) { + continue; + } + + bool isBestMatch = fBestMatch.find(muon.globalIndex()) != fBestMatch.end(); + + if (fKeepBestMatch && !isBestMatch) { + continue; + } + + const auto& collision = collisions.rawIteratorAt(muon.collisionId()); + auto bc_coll = collision.bc_as(); + + auto muontrack = muon.template matchMCHTrack_as(); + auto mfttrack = muon.template matchMFTTrack_as(); + auto const& mfttrackcov = mftCovs.rawIteratorAt(mftCovIndexes[mfttrack.globalIndex()]); + + auto muonTime = muontrack.trackTime() + bc_coll.globalBC() * o2::constants::lhc::LHCBunchSpacingNS; + auto mftTime = mfttrack.trackTime() + bc_coll.globalBC() * o2::constants::lhc::LHCBunchSpacingNS; + + o2::track::TrackParCovFwd mftprop = VarManager::FwdToTrackPar(mfttrack, mfttrackcov); + o2::track::TrackParCovFwd muonprop = VarManager::FwdToTrackPar(muontrack, muontrack); + if (fzMatching.value < 0.) { + mftprop = VarManager::PropagateFwd(mfttrack, mfttrackcov, fzMatching.value); + muonprop = VarManager::PropagateMuon(muontrack, collision, VarManager::kToMatching); + } + auto muonpropCov = muonprop.getCovariances(); + auto mftpropCov = mftprop.getCovariances(); + + if (!IsGoodMuon(muontrack, collision, fTrackChi2MchUp, fPMchLow, fPtMchLow, {fEtaMFTLow, fEtaMFTUp}, {fRabsLow, fRabsUp}, fSigmaPdcaUp)) { + continue; + } + + // at this level we consider all the matching candidates, regardless of the MFT tracks quality + // MFT track quality cuts should be applied only after having selected the best candidate + // if (!IsGoodMFT(mfttrack, fTrackChi2MFTUp, fPtMFTLow, {fEtaMFTLow, fEtaMFTUp})){ + // continue; + //} + + bool IsAmbig = (muon.compatibleCollIds().size() != 1); + int MFTMult = collision.mftNtracks(); + + auto matchType = getMatchType(muon, muonTracks, mftTracks, matchablePairs, isBestMatch); + bool isSignal = (matchType == kMatchTypeTrueLeading) || (matchType == kMatchTypeTrueNonLeading); + + registry.get(HIST("matchType"))->Fill(static_cast(matchType)); + + fwdMatchMLCandidates( + muonprop.getX(), + muonprop.getY(), + muonprop.getPhi(), + muonprop.getTgl(), + muonprop.getInvQPt(), + muonTime, + muontrack.trackTimeRes(), + muontrack.chi2(), + muontrack.pDca(), + muontrack.rAtAbsorberEnd(), + muonpropCov(0, 0), + muonpropCov(1, 1), + muonpropCov(2, 2), + muonpropCov(3, 3), + muonpropCov(4, 4), + muonpropCov(1, 0), + muonpropCov(2, 0), + muonpropCov(2, 1), + muonpropCov(3, 0), + muonpropCov(3, 1), + muonpropCov(3, 2), + muonpropCov(4, 0), + muonpropCov(4, 1), + muonpropCov(4, 2), + muonpropCov(4, 3), + mftprop.getX(), + mftprop.getY(), + mftprop.getPhi(), + mftprop.getTgl(), + mftprop.getInvQPt(), + mftTime, + mfttrack.trackTimeRes(), + mfttrack.chi2(), + mfttrack.mftClusterSizesAndTrackFlags(), + mftpropCov(0, 0), + mftpropCov(1, 1), + mftpropCov(2, 2), + mftpropCov(3, 3), + mftpropCov(4, 4), + mftpropCov(1, 0), + mftpropCov(2, 0), + mftpropCov(2, 1), + mftpropCov(3, 0), + mftpropCov(3, 1), + mftpropCov(3, 2), + mftpropCov(4, 0), + mftpropCov(4, 1), + mftpropCov(4, 2), + mftpropCov(4, 3), + muon.chi2(), + muon.chi2MatchMCHMFT(), + muon.fwdDcaX(), + muon.fwdDcaY(), + IsAmbig, + MFTMult, + muontrack.mcMask(), + mfttrack.mcMask(), + muon.mcMask(), + static_cast(matchType), + isSignal); + } + } + + PROCESS_SWITCH(mftMchMatcher, processMC, "process_MC", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGDQ/Tasks/muonDCA.cxx b/PWGDQ/Tasks/muonDCA.cxx index a607ad16b4b..bbb4b63db5e 100644 --- a/PWGDQ/Tasks/muonDCA.cxx +++ b/PWGDQ/Tasks/muonDCA.cxx @@ -16,13 +16,24 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include #include using namespace o2; diff --git a/PWGDQ/Tasks/muonGlobalAlignment.cxx b/PWGDQ/Tasks/muonGlobalAlignment.cxx new file mode 100644 index 00000000000..968bb3842a3 --- /dev/null +++ b/PWGDQ/Tasks/muonGlobalAlignment.cxx @@ -0,0 +1,1738 @@ +// 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 "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "rapidjson/document.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::mch; +using namespace o2::framework; +using namespace o2::aod; + +using namespace o2::aod::rctsel; + +using MyReducedMuons = soa::Join; +using MyReducedEvents = soa::Join; +using MyReducedEventsVtxCov = soa::Join; + +using MyCollisions = aod::Collisions; +using MyBCs = soa::Join; +using MyEvents = soa::Join; +using MyMuonsWithCov = soa::Join; +// using MyMuonsWithCov = aod::FwdTracks; +using MyMFTs = aod::MFTTracks; +using MyMFTCovariances = aod::MFTTracksCov; + +using MyCollision = MyCollisions::iterator; +using MyBC = MyBCs::iterator; +using MyMUON = MyMuonsWithCov::iterator; +using MyMFT = MyMFTs::iterator; +using MyMFTCovariance = MyMFTCovariances::iterator; + +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix5 = ROOT::Math::SVector; + +static o2::globaltracking::MatchGlobalFwd sExtrap; + +using o2::dataformats::GlobalFwdTrack; +using o2::track::TrackParCovFwd; + +struct muonGlobalAlignment { + //// Variables for selecting MCH and MFT tracks + Configurable fTrackChi2MchUp{"cfgTrackChi2MchUp", 5.f, ""}; + Configurable fPtMchLow{"cfgPtMchLow", 0.7f, ""}; + Configurable fEtaMftLow{"cfgEtaMftlow", -3.6f, ""}; + Configurable fEtaMftUp{"cfgEtaMftup", -2.5f, ""}; + Configurable fRabsLow{"cfgRabsLow", 17.6f, ""}; + Configurable fRabsUp{"cfgRabsUp", 89.5f, ""}; + Configurable fSigmaPdcaUp{"cfgPdcaUp", 6.f, ""}; + + Configurable fTrackNClustMftLow{"cfgTrackNClustMftLow", 7, ""}; + Configurable fTrackChi2MftUp{"cfgTrackChi2MftUp", 999.f, ""}; + + Configurable fMftMchResidualsPLow{"cfgMftMchResidualsPLow", 30.f, ""}; + Configurable fMftMchResidualsPtLow{"cfgMftMchResidualsPtLow", 4.f, ""}; + + Configurable fMftTracksMultiplicityMax{"cfgMftTracksMultiplicityMax", 0, "Maximum number of MFT tracks to be processed per event (zero means no limit)"}; + + Configurable fVertexZshift{"cfgVertexZshift", 0.0f, "Correction to the vertex z position"}; + + //// Variables for MFT alignment corrections + struct : ConfigurableGroup { + Configurable fEnableMFTAlignmentCorrections{"cfgEnableMFTAlignmentCorrections", false, ""}; + // slope corrections + Configurable fMFTAlignmentCorrXSlopeTop{"cfgMFTAlignmentCorrXSlopeTop", (-0.0006696 - 0.0005621) / 2.f, "MFT X slope correction - top half"}; + Configurable fMFTAlignmentCorrXSlopeBottom{"cfgMFTAlignmentCorrXSlopeBottom", (0.00105 + 0.001007) / 2.f, "MFT X slope correction - bottom half"}; + Configurable fMFTAlignmentCorrYSlopeTop{"cfgMFTAlignmentCorrYSlopeTop", (-0.002299 - 0.002442) / 2.f, "MFT Y slope correction - top half"}; + Configurable fMFTAlignmentCorrYSlopeBottom{"cfgMFTAlignmentCorrYSlopeBottom", (-0.0005339 - 0.0006921) / 2.f, "MFT Y slope correction - bottom half"}; + // offset corrections + Configurable fMFTAlignmentCorrXOffsetTop{"cfgMFTAlignmentCorrXOffsetTop", 0.f, "MFT X offset correction - top half"}; + Configurable fMFTAlignmentCorrXOffsetBottom{"cfgMFTAlignmentCorrXOffsetBottom", 0.f, "MFT X offset correction - bottom half"}; + Configurable fMFTAlignmentCorrYOffsetTop{"cfgMFTAlignmentCorrYOffsetTop", 0.f, "MFT Y offset correction - top half"}; + Configurable fMFTAlignmentCorrYOffsetBottom{"cfgMFTAlignmentCorrYOffsetBottom", 0.f, "MFT Y offset correction - bottom half"}; + } configMFTAlignmentCorrections; + + //// Variables for re-alignment setup + struct : ConfigurableGroup { + Configurable fEnableMCHRealign{"cfgEnableMCHRealign", true, "Enable re-alignment of MCH clusters and tracks"}; + Configurable fChamberResolutionX{"cfgChamberResolutionX", 0.4, "Chamber resolution along X configuration for refit"}; // 0.4cm pp, 0.2cm PbPb + Configurable fChamberResolutionY{"cfgChamberResolutionY", 0.4, "Chamber resolution along Y configuration for refit"}; // 0.4cm pp, 0.2cm PbPb + Configurable fSigmaCutImprove{"cfgSigmaCutImprove", 6., "Sigma cut for track improvement"}; + Configurable fMCHRealignCorrections{"cfgMCHRealignCorrections", "", "MCH DE positions/angles corrections in JSON format"}; + } configRealign; + + //// Variables for ccdb + struct : ConfigurableGroup { + 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 geoPathRealign{"geoPathRealign", "Users/j/jcastill/GeometryAlignedFix10Fix15ShiftCh1BNew2", "Path of the geometry file"}; + Configurable geoPathRealign{"geoPathRealign", "Users/j/jcastill/GeometryAlignedLoczzm4pLHC24anap1sR5a", "Path of the geometry file"}; + Configurable nolaterthan{"ccdb-no-later-than-ref", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object of reference basis"}; + Configurable nolaterthanRealign{"ccdb-no-later-than-new", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object of new basis"}; + } configCCDB; + + Configurable fRequireGoodRCT{"cfgRequireGoodRCT", true, "Require good detector flags in Run Condition Table"}; + + Configurable fEnableVertexShiftAnalysis{"cfgEnableVertexShiftAnalysis", true, "Enable the analysis of vertex shift"}; + Configurable fEnableMftDcaAnalysis{"cfgEnableMftDcaAnalysis", true, "Enable the analysis of DCA-based MFT alignment"}; + Configurable fEnableMftDcaExtraPlots{"cfgEnableMftDcaExtraPlots", false, "Enable additional plots for the analysis of DCA-based MFT alignment"}; + Configurable fEnableGlobalFwdDcaAnalysis{"cfgEnableGlobalFwdDcaAnalysis", true, "Enable the analysis of DCA-based MFT alignment using global forward tracks"}; + Configurable fEnableMftMchResidualsAnalysis{"cfgEnableMftMchResidualsAnalysis", true, "Enable the analysis of residuals between MFT tracks and MCH clusters"}; + Configurable fEnableMftMchResidualsExtraPlots{"cfgEnableMftMchResidualsExtraPlots", false, "Enable additional plots for the analysis of residuals between MFT tracks and MCH clusters"}; + + int mRunNumber{0}; // needed to detect if the run changed and trigger update of magnetic field + + Service ccdbManager; + o2::field::MagneticField* fieldB; + o2::ccdb::CcdbApi ccdbApi; + + // Derived version of mch::Track class that handles the associated clusters as internal objects and deletes them in the destructor + class TrackRealigned : public mch::Track + { + public: + TrackRealigned() = default; + ~TrackRealigned() + { + // delete the clusters associated to this track + for (const auto& par : *this) { + if (par.getClusterPtr()) { + delete par.getClusterPtr(); + } + } + } + }; + + geo::TransformationCreator transformation; + std::map transformRef; // reference geometry w.r.t track data + std::map transformNew; // new geometry + TGeoManager* geoNew = nullptr; + TGeoManager* geoRef = nullptr; + TrackFitter trackFitter; // Track fitter from MCH tracking library + double mImproveCutChi2; // Chi2 cut for track improvement. + + struct AlignmentCorrections { + double x{0}; + double y{0}; + double z{0}; + }; + std::map mMchAlignmentCorrections; + + Preslice perMuon = aod::fwdtrkcl::fwdtrackId; + + o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT_muon_glo", false, false, true}; + + double mBzAtMftCenter{0}; + + HistogramRegistry registry{"registry", {}}; + std::array mMftTrackEffNum; + std::array mMftTrackEffDen; + + // vector of all MFT-MCH(-MID) matching candidates associated to the same MCH(-MID) track, + // to be sorted in descending order with respect to the matching quality + // the map key is the MCH(-MID) track global index + using MatchingCandidates = std::map>; + + struct CollisionInfo { + uint64_t bc{0}; + // z position of the collision + double zVertex{0}; + // number of MFT tracks associated to the collision + int mftTracksMultiplicity{0}; + // vector of MFT track indexes + std::vector mftTracks; + // vector of MCH(-MID) track indexes + std::vector mchTracks; + // matching candidates + std::map> globalMuonTracks; + }; + + void InitCollisions(MyEvents const& collisions, + MyBCs const& bcs, + MyMuonsWithCov const& muonTracks, + std::map& collisionInfos) + { + // fill collision information for global muon tracks (MFT-MCH-MID matches) + for (auto muonTrack : muonTracks) { + if (!muonTrack.has_collision()) + continue; + + auto collision = collisions.rawIteratorAt(muonTrack.collisionId()); + + if (fRequireGoodRCT && !rctChecker(collision)) + continue; + + uint64_t collisionIndex = collision.globalIndex(); + + auto bc = bcs.rawIteratorAt(collision.bcId()); + + auto& collisionInfo = collisionInfos[collisionIndex]; + collisionInfo.bc = bc.globalBC(); + collisionInfo.zVertex = collision.posZ(); + + if (static_cast(muonTrack.trackType()) > 2) { + // standalone MCH or MCH-MID tracks + uint64_t mchTrackIndex = muonTrack.globalIndex(); + collisionInfo.mchTracks.push_back(mchTrackIndex); + } else { + // global muon tracks (MFT-MCH or MFT-MCH-MID) + uint64_t muonTrackIndex = muonTrack.globalIndex(); + auto const& mchTrack = muonTrack.template matchMCHTrack_as(); + uint64_t mchTrackIndex = mchTrack.globalIndex(); + + // check if a vector of global muon candidates is already available for the current MCH index + // if not, initialize a new one and add the current global muon track + // bool globalMuonTrackFound = false; + auto matchingCandidateIterator = collisionInfo.globalMuonTracks.find(mchTrackIndex); + if (matchingCandidateIterator != collisionInfo.globalMuonTracks.end()) { + matchingCandidateIterator->second.push_back(muonTrackIndex); + // globalMuonTrackFound = true; + } else { + collisionInfo.globalMuonTracks[mchTrackIndex].push_back(muonTrackIndex); + } + } + } + + // sort the vectors of matching candidates in ascending order based on the matching chi2 value + auto compareChi2 = [&muonTracks](uint64_t trackIndex1, uint64_t trackIndex2) -> bool { + auto const& track1 = muonTracks.rawIteratorAt(trackIndex1); + auto const& track2 = muonTracks.rawIteratorAt(trackIndex2); + + return (track1.chi2MatchMCHMFT() < track2.chi2MatchMCHMFT()); + }; + + for (auto& [collisionIndex, collisionInfo] : collisionInfos) { + for (auto& [mchIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { + std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareChi2); + } + } + } + + void InitCollisions(MyEvents const& collisions, + MyBCs const& bcs, + MyMuonsWithCov const& muonTracks, + MyMFTs const& mftTracks, + std::map& collisionInfos) + { + InitCollisions(collisions, bcs, muonTracks, collisionInfos); + + // fill collision information for MFT standalone tracks + for (auto mftTrack : mftTracks) { + if (!mftTrack.has_collision()) + continue; + + auto collision = collisions.rawIteratorAt(mftTrack.collisionId()); + uint64_t collisionIndex = collision.globalIndex(); + + auto bc = bcs.rawIteratorAt(collision.bcId()); + + uint64_t mftTrackIndex = mftTrack.globalIndex(); + + auto& collisionInfo = collisionInfos[collisionIndex]; + collisionInfo.bc = bc.globalBC(); + collisionInfo.zVertex = collision.posZ(); + + collisionInfo.mftTracks.push_back(mftTrackIndex); + } + } + + template + void initCCDB(BC const& bc) + { + if (mRunNumber == bc.runNumber()) + return; + + mRunNumber = bc.runNumber(); + ccdbManager->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + // auto grpmag = ccdbApi.retrieveFromTFileAny(grpmagPath, metadata, ts); + auto grpmag = ccdbManager->getForTimeStamp(configCCDB.grpmagPath, bc.timestamp()); + if (grpmag != nullptr) { + base::Propagator::initFieldFromGRP(grpmag); + TrackExtrap::setField(); + TrackExtrap::useExtrapV2(); + fieldB = static_cast(TGeoGlobalMagField::Instance()->GetField()); // for MFT + double centerMFT[3] = {0, 0, -61.4}; // or use middle point between Vtx and MFT? + mBzAtMftCenter = fieldB->getBz(centerMFT); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", bc.timestamp()); + } + + // Load geometry information from CCDB/local + LOGF(info, "Loading reference aligned geometry from CCDB no later than %d", configCCDB.nolaterthan.value); + ccdbManager->setCreatedNotAfter(configCCDB.nolaterthan); // this timestamp has to be consistent with what has been used in reco + geoRef = ccdbManager->getForTimeStamp(configCCDB.geoPath, bc.timestamp()); + ccdbManager->clearCache(configCCDB.geoPath); + + if (configRealign.fEnableMCHRealign && fEnableMftMchResidualsAnalysis) { + if (geoRef != nullptr) { + transformation = geo::transformationFromTGeoManager(*geoRef); + } else { + LOGF(fatal, "Reference aligned geometry object is not available in CCDB at timestamp=%llu", bc.timestamp()); + } + for (int i = 0; i < 156; i++) { + int iDEN = GetDetElemId(i); + transformRef[iDEN] = transformation(iDEN); + } + + LOGF(info, "Loading new aligned geometry from CCDB no later than %d", configCCDB.nolaterthanRealign.value); + ccdbManager->setCreatedNotAfter(configCCDB.nolaterthanRealign); // make sure this timestamp can be resolved regarding the reference one + geoNew = ccdbManager->getForTimeStamp(configCCDB.geoPathRealign, bc.timestamp()); + ccdbManager->clearCache(configCCDB.geoPathRealign); + if (geoNew != nullptr) { + transformation = geo::transformationFromTGeoManager(*geoNew); + } else { + LOGF(fatal, "New aligned geometry object is not available in CCDB at timestamp=%llu", bc.timestamp()); + } + for (int i = 0; i < 156; i++) { + int iDEN = GetDetElemId(i); + transformNew[iDEN] = transformation(iDEN); + } + } + } + + void init(o2::framework::InitContext&) + { + // Load geometry + ccdbManager->setURL(configCCDB.ccdburl); + ccdbManager->setCaching(true); + ccdbManager->setLocalObjectValidityChecking(); + ccdbApi.init(configCCDB.ccdburl); + mRunNumber = 0; + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + LOGF(info, "Load geometry from CCDB"); + ccdbManager->get(configCCDB.geoPath); + } + + // Configuration for track fitter + const auto& trackerParam = TrackerParam::Instance(); + trackFitter.setBendingVertexDispersion(trackerParam.bendingVertexDispersion); + trackFitter.setChamberResolution(configRealign.fChamberResolutionX, configRealign.fChamberResolutionY); + trackFitter.smoothTracks(true); + trackFitter.useChamberResolution(); + mImproveCutChi2 = 2. * configRealign.fSigmaCutImprove * configRealign.fSigmaCutImprove; + + // Fill table of MCH alignment corrections + rapidjson::Document document; + // Check that the json is parsed correctly + rapidjson::ParseResult jsonOk = document.Parse(configRealign.fMCHRealignCorrections.value.c_str()); + if (jsonOk) { + for (rapidjson::Value::ConstMemberIterator it = document.MemberBegin(); it != document.MemberEnd(); it++) { + LOG(info) << "DE" << it->name.GetString() << " alignment corrections:"; + LOG(info) << " x: " << it->value["x"].GetDouble(); + LOG(info) << " y: " << it->value["y"].GetDouble(); + LOG(info) << " z: " << it->value["z"].GetDouble(); + + mMchAlignmentCorrections[std::stoi(it->name.GetString())] = { + it->value["x"].GetDouble(), + it->value["y"].GetDouble(), + it->value["z"].GetDouble()}; + } + } else { + LOG(error) << "JSON parse error: " << rapidjson::GetParseErrorFunc(jsonOk.Code()) << " (" << jsonOk.Offset() << ")"; + } + + float mftLadderWidth = 1.7; + AxisSpec dcaxMFTAxis = {400, -0.5, 0.5, "DCA_{x} (cm)"}; + AxisSpec dcayMFTAxis = {400, -0.5, 0.5, "DCA_{y} (cm)"}; + AxisSpec dcaxMCHAxis = {400, -10.0, 10.0, "DCA_{x} (cm)"}; + AxisSpec dcayMCHAxis = {400, -10.0, 10.0, "DCA_{y} (cm)"}; + AxisSpec dcazAxis = {20, -10.0, 10.0, "v_{z} (cm)"}; + AxisSpec txAxis = {30 * 4, -mftLadderWidth * 15.f / 2.f, mftLadderWidth * 15.f / 2.f, "track_{x} (cm)"}; + AxisSpec tyAxis = {24 * 4, -12.f, 12.f, "track_{y} (cm)"}; + AxisSpec txFineAxis = {1500, -15.f, 15.f, "track_{x} (cm)"}; + AxisSpec tyFineAxis = {1500, -15.f, 15.f, "track_{y} (cm)"}; + AxisSpec vxAxis = {400, -0.5, 0.5, "vtx_{x} (cm)"}; + AxisSpec vyAxis = {400, -0.5, 0.5, "vtx_{y} (cm)"}; + AxisSpec vzAxis = {1000, -10.0, 10.0, "vtx_{z} (cm)"}; + AxisSpec phiAxis = {36, -180.0, 180.0, "#phi (degrees)"}; + AxisSpec sxAxis = {50, -0.25, 0.25, "x slope"}; + AxisSpec syAxis = {50, -0.25, 0.25, "y slope"}; + AxisSpec momAxis = {500, 0, 100.0, "p (GeV/c)"}; + AxisSpec nMftClustersAxis = {6, 5, 11, "# of clusters"}; + AxisSpec mftTrackTypeAxis = {2, 0, 2, "track type"}; + AxisSpec mftLayerAxis = {10, 0, 10, "layer"}; + AxisSpec trackChargeSignAxis = {2, 0, 0, "sign"}; + AxisSpec layersPatternAxis = {1024, 0, 1024, "layers pattern"}; + AxisSpec zshiftAxis = {21, -5.25, 5.25, "z shift (mm)"}; + AxisSpec chi2Axis = {500, 0, 500, "chi2"}; + + registry.add("vertex_y_vs_x", std::format("Vertex y vs. x").c_str(), {HistType::kTH2F, {vxAxis, vyAxis}}); + registry.add("vertex_z", std::format("Vertex z").c_str(), {HistType::kTH1F, {vzAxis}}); + + if (fEnableVertexShiftAnalysis || fEnableMftDcaAnalysis) { + registry.add("DCA/MFT/nTracksMFT", std::format("Number of MFT tracks per collision").c_str(), {HistType::kTH1F, {{100, 0, 1000, "# of MFT tracks"}}}); + registry.add("DCA/MFT/DCA_y_vs_x", std::format("DCA y vs. x").c_str(), {HistType::kTH2F, {dcaxMFTAxis, dcayMFTAxis}}); + } + + if (fEnableVertexShiftAnalysis) { + registry.add("DCA/MFT/DCA_x_vs_phi_vs_zshift", std::format("DCA(x) vs. #phi vs. z shift").c_str(), {HistType::kTH3F, {zshiftAxis, phiAxis, dcaxMFTAxis}}); + registry.add("DCA/MFT/DCA_y_vs_phi_vs_zshift", std::format("DCA(y) vs. #phi vs. z shift").c_str(), {HistType::kTH3F, {zshiftAxis, phiAxis, dcayMFTAxis}}); + + registry.add("DCA/MFT/DCA_x_vs_slopex_vs_zshift", std::format("DCA(x) vs. x slope vs. z shift").c_str(), {HistType::kTH3F, {zshiftAxis, sxAxis, dcaxMFTAxis}}); + registry.add("DCA/MFT/DCA_x_vs_slopey_vs_zshift", std::format("DCA(x) vs. y slope vs. z shift").c_str(), {HistType::kTH3F, {zshiftAxis, syAxis, dcaxMFTAxis}}); + registry.add("DCA/MFT/DCA_y_vs_slopex_vs_zshift", std::format("DCA(y) vs. x slope vs. z shift").c_str(), {HistType::kTH3F, {zshiftAxis, sxAxis, dcayMFTAxis}}); + registry.add("DCA/MFT/DCA_y_vs_slopey_vs_zshift", std::format("DCA(y) vs. y slope vs. z shift").c_str(), {HistType::kTH3F, {zshiftAxis, syAxis, dcayMFTAxis}}); + } + + if (fEnableMftDcaAnalysis) { + registry.add("DCA/MFT/DCA_x", "DCA(x) vs. vz, tx, ty, nclus", + HistType::kTHnSparseF, {dcaxMFTAxis, dcazAxis, txAxis, tyAxis, nMftClustersAxis}); + registry.add("DCA/MFT/DCA_y", "DCA(y) vs. vz, tx, ty, nclus", + HistType::kTHnSparseF, {dcayMFTAxis, dcazAxis, txAxis, tyAxis, nMftClustersAxis}); + + if (fEnableMftDcaExtraPlots) { + registry.add("DCA/MFT/layers", "Layers vs. tx, ty, nclus", + HistType::kTHnSparseF, {mftLayerAxis, txAxis, tyAxis, nMftClustersAxis}); + registry.add("DCA/MFT/trackChi2", "Track #chi^{2} vs. tx, ty, nclus, layer", + HistType::kTHnSparseF, {chi2Axis, txAxis, tyAxis, nMftClustersAxis}); + registry.add("DCA/MFT/trackMomentum", "Track momentum vs. tx, ty, nclus, layer", + HistType::kTHnSparseF, {momAxis, txAxis, tyAxis, nMftClustersAxis}); + + const int nMftLayers = 10; + for (int i = 0; i < nMftLayers; i++) { + mMftTrackEffNum[i] = registry.add((std::string("DCA/MFT/mftTrackEffNum_") + std::to_string(i)).c_str(), + (std::string("Track efficiency num. - layer ") + std::to_string(i)).c_str(), + HistType::kTH2F, {txFineAxis, tyFineAxis}); + mMftTrackEffDen[i] = registry.add((std::string("DCA/MFT/mftTrackEffDen_") + std::to_string(i)).c_str(), + (std::string("Track efficiency den. - layer ") + std::to_string(i)).c_str(), + HistType::kTH2F, {txFineAxis, tyFineAxis}); + } + } + } + + if (fEnableGlobalFwdDcaAnalysis) { + registry.add("DCA/GlobalFwd/DCA_x", "DCA(x) vs. vz, tx, ty, nclus", + HistType::kTHnSparseF, {dcaxMFTAxis, dcazAxis, txAxis, tyAxis, nMftClustersAxis}); + registry.add("DCA/GlobalFwd/DCA_y", "DCA(y) vs. vz, tx, ty, nclus", + HistType::kTHnSparseF, {dcayMFTAxis, dcazAxis, txAxis, tyAxis, nMftClustersAxis}); + } + + if (fEnableMftMchResidualsAnalysis) { + AxisSpec dxAxis = {600, -30.0, 30.0, "#Delta x (cm)"}; + AxisSpec dyAxis = {600, -30.0, 30.0, "#Delta y (cm)"}; + + registry.add("DCA/MCH/DCA_y_vs_x", std::format("DCA y vs. x").c_str(), {HistType::kTH2F, {dcaxMCHAxis, dcayMCHAxis}}); + registry.add("DCA/MCH/DCA_x_vs_sign_vs_quadrant_vs_mom", std::format("DCA(x) vs. p, quadrant, chargeSign").c_str(), {HistType::kTHnSparseF, {{20, 0, 100.0, "p (GeV/c)"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dcaxMCHAxis}}); + registry.add("DCA/MCH/DCA_y_vs_sign_vs_quadrant_vs_mom", std::format("DCA(y) vs. p, quadrant, chargeSign").c_str(), {HistType::kTHnSparseF, {{20, 0, 100.0, "p (GeV/c)"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dcayMCHAxis}}); + + registry.add("DCA/MCH/DCA_x_vs_sign_vs_quadrant_vs_mom_corr", std::format("DCA(x) vs. p, quadrant, chargeSign (with corrections)").c_str(), {HistType::kTHnSparseF, {{20, 0, 100.0, "p (GeV/c)"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dcaxMCHAxis}}); + registry.add("DCA/MCH/DCA_y_vs_sign_vs_quadrant_vs_mom_corr", std::format("DCA(y) vs. p, quadrant, chargeSign (with corrections)").c_str(), {HistType::kTHnSparseF, {{20, 0, 100.0, "p (GeV/c)"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dcayMCHAxis}}); + + registry.add("residuals/dx_vs_chamber", "Cluster x residual vs. chamber, quadrant, chargeSign", + {HistType::kTHnSparseF, {{10, 1, 11, "chamber"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dxAxis}}); + registry.add("residuals/dy_vs_chamber", "Cluster y residual vs. chamber, quadrant, chargeSign", + {HistType::kTHnSparseF, {{10, 1, 11, "chamber"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dyAxis}}); + + registry.add("residuals/dx_vs_de", "Cluster x residual vs. DE, quadrant, chargeSign, momentum", + {HistType::kTHnSparseF, {dxAxis, {getNumDE(), 0, static_cast(getNumDE()), "DE"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, {20, 0, 100.0, "p (GeV/c)"}}}); + registry.add("residuals/dy_vs_de", "Cluster y residual vs. DE, quadrant, chargeSign, momentum", + {HistType::kTHnSparseF, {dyAxis, {getNumDE(), 0, static_cast(getNumDE()), "DE"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, {20, 0, 100.0, "p (GeV/c)"}}}); + + registry.add("residuals/dx_vs_chamber_corr", "Cluster x residual vs. chamber, quadrant, chargeSign (with corrections)", + {HistType::kTHnSparseF, {{10, 1, 11, "chamber"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dxAxis}}); + registry.add("residuals/dy_vs_chamber_corr", "Cluster y residual vs. chamber, quadrant, chargeSign (with corrections)", + {HistType::kTHnSparseF, {{10, 1, 11, "chamber"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dyAxis}}); + + registry.add("residuals/dx_vs_de_corr", "Cluster x residual vs. DE, quadrant, chargeSign, momentum (with corrections)", + {HistType::kTHnSparseF, {dxAxis, {getNumDE(), 0, static_cast(getNumDE()), "DE"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, {20, 0, 100.0, "p (GeV/c)"}}}); + registry.add("residuals/dy_vs_de_corr", "Cluster y residual vs. DE, quadrant, chargeSign, momentum (with corrections)", + {HistType::kTHnSparseF, {dyAxis, {getNumDE(), 0, static_cast(getNumDE()), "DE"}, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, {20, 0, 100.0, "p (GeV/c)"}}}); + + if (fEnableMftMchResidualsExtraPlots) { + registry.add("DCA/MCH/DCA_x_vs_sign_vs_quadrant_vs_vz", std::format("DCA(x) vs. vz, quadrant, chargeSign").c_str(), {HistType::kTHnSparseF, {dcazAxis, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dcaxMCHAxis}}); + registry.add("DCA/MCH/DCA_y_vs_sign_vs_quadrant_vs_vz", std::format("DCA(y) vs. vz, quadrant, chargeSign").c_str(), {HistType::kTHnSparseF, {dcazAxis, {4, 0, 4, "quadrant"}, {2, 0, 2, "sign"}, dcayMCHAxis}}); + + registry.add("residuals/dphi_at_mft", "Track #Delta#phi at MFT", + {HistType::kTHnSparseF, {{200, -0.2f, 0.2f, "#Delta#phi"}, {80, -10.f, 10.f, "track_x (cm)"}, {80, -10.f, 10.f, "track_y (cm)"}, {2, 0, 2, "sign"}, {20, 0, 100.0, "p (GeV/c)"}}}); + } + } + } + + int GetDetElemId(int iDetElemNumber) + { + const int fgNCh = 10; + const int fgNDetElemCh[fgNCh] = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26}; + const int fgSNDetElemCh[fgNCh + 1] = {0, 4, 8, 12, 16, 34, 52, 78, 104, 130, 156}; + + // make sure detector number is valid + if (!(iDetElemNumber >= fgSNDetElemCh[0] && + iDetElemNumber < fgSNDetElemCh[10])) { + LOGF(fatal, "Invalid detector element number: %d", iDetElemNumber); + } + /// get det element number from ID + // get chamber and element number in chamber + int iCh = 0; + int iDet = 0; + for (int i = 1; i <= 10; i++) { + if (iDetElemNumber < fgSNDetElemCh[i]) { + iCh = i; + iDet = iDetElemNumber - fgSNDetElemCh[i - 1]; + break; + } + } + + // make sure detector index is valid + if (!(iCh > 0 && iCh <= 10 && iDet < fgNDetElemCh[iCh - 1])) { + LOGF(fatal, "Invalid detector element id: %d", 100 * iCh + iDet); + } + + // add number of detectors up to this chamber + return 100 * iCh + iDet; + } + + int getChamberIndex(int deId) + { + return (deId / 100) - 1; + } + + int getNumDEinChamber(int chIndex) + { + int nDE = 0; + switch (chIndex) { + case 0: + case 1: + case 2: + case 3: + nDE = 4; + break; + case 4: + case 5: + nDE = 18; + break; + case 6: + case 7: + case 8: + case 9: + nDE = 26; + break; + default: + break; + } + return nDE; + } + + int getNumDE() + { + static int nDE = -1; + if (nDE < 0) { + for (int c = 0; c < 10; c++) { + nDE += getNumDEinChamber(c); + } + } + + return nDE; + } + + int getDEindexInChamber(int deId) + { + return (deId - 100) % 100; + } + + int getChamberOffset(int chIndex) + { + int offset = 0; + for (int c = 0; c < chIndex; c++) { + offset += getNumDEinChamber(c); + } + return offset; + } + + int getDEindex(int deId) + { + auto idx = getDEindexInChamber(deId); + int offset = getChamberOffset(getChamberIndex(deId)); + + return idx + offset; + } + + int GetQuadrant(double phi) + { + if (phi >= 0 && phi < 90) { + return 0; + } + if (phi >= 90 && phi <= 180) { + return 1; + } + if (phi >= -180 && phi < -90) { + return 2; + } + if (phi >= -90 && phi < 0) { + return 3; + } + return -1; + } + + template + int GetQuadrant(const T& track) + { + double phi = track.phi() * 180 / TMath::Pi(); + return GetQuadrant(phi); + } + + template + static o2::mch::TrackParam FwdtoMCH(const T& fwdtrack) + { + using SMatrix55Std = ROOT::Math::SMatrix; + using SMatrix55Sym = ROOT::Math::SMatrix>; + + // Convert Forward Track parameters and covariances matrix to the + // MCH track format. + + // Parameter conversion + double alpha1, alpha3, alpha4, x2, x3, x4; + + x2 = fwdtrack.getPhi(); + x3 = fwdtrack.getTanl(); + x4 = fwdtrack.getInvQPt(); + + auto sinx2 = TMath::Sin(x2); + auto cosx2 = TMath::Cos(x2); + + alpha1 = cosx2 / x3; + alpha3 = sinx2 / x3; + alpha4 = x4 / TMath::Sqrt(x3 * x3 + sinx2 * sinx2); + + auto K = TMath::Sqrt(x3 * x3 + sinx2 * sinx2); + auto K3 = K * K * K; + + // Covariances matrix conversion + SMatrix55Std jacobian; + SMatrix55Sym covariances; + + covariances(0, 0) = fwdtrack.getCovariances()(0, 0); + covariances(0, 1) = fwdtrack.getCovariances()(0, 1); + covariances(0, 2) = fwdtrack.getCovariances()(0, 2); + covariances(0, 3) = fwdtrack.getCovariances()(0, 3); + covariances(0, 4) = fwdtrack.getCovariances()(0, 4); + + covariances(1, 1) = fwdtrack.getCovariances()(1, 1); + covariances(1, 2) = fwdtrack.getCovariances()(1, 2); + covariances(1, 3) = fwdtrack.getCovariances()(1, 3); + covariances(1, 4) = fwdtrack.getCovariances()(1, 4); + + covariances(2, 2) = fwdtrack.getCovariances()(2, 2); + covariances(2, 3) = fwdtrack.getCovariances()(2, 3); + covariances(2, 4) = fwdtrack.getCovariances()(2, 4); + + covariances(3, 3) = fwdtrack.getCovariances()(3, 3); + covariances(3, 4) = fwdtrack.getCovariances()(3, 4); + + covariances(4, 4) = fwdtrack.getCovariances()(4, 4); + + jacobian(0, 0) = 1; + + jacobian(1, 2) = -sinx2 / x3; + jacobian(1, 3) = -cosx2 / (x3 * x3); + + jacobian(2, 1) = 1; + + jacobian(3, 2) = cosx2 / x3; + jacobian(3, 3) = -sinx2 / (x3 * x3); + + jacobian(4, 2) = -x4 * sinx2 * cosx2 / K3; + jacobian(4, 3) = -x3 * x4 / K3; + jacobian(4, 4) = 1 / K; + // jacobian*covariances*jacobian^T + covariances = ROOT::Math::Similarity(jacobian, covariances); + + double cov[] = {covariances(0, 0), covariances(1, 0), covariances(1, 1), covariances(2, 0), covariances(2, 1), covariances(2, 2), covariances(3, 0), covariances(3, 1), covariances(3, 2), covariances(3, 3), covariances(4, 0), covariances(4, 1), covariances(4, 2), covariances(4, 3), covariances(4, 4)}; + double param[] = {fwdtrack.getX(), alpha1, fwdtrack.getY(), alpha3, alpha4}; + + o2::mch::TrackParam convertedTrack(fwdtrack.getZ(), param, cov); + return o2::mch::TrackParam(convertedTrack); + } + + static o2::dataformats::GlobalFwdTrack MCHtoFwd(const o2::mch::TrackParam& mchParam) + { + using SMatrix55Std = ROOT::Math::SMatrix; + using SMatrix55Sym = ROOT::Math::SMatrix>; + + // Convert a MCH Track parameters and covariances matrix to the + // Forward track format. Must be called after propagation though the absorber + + o2::dataformats::GlobalFwdTrack convertedTrack; + + // Parameter conversion + double alpha1, alpha3, alpha4, x2, x3, x4; + + alpha1 = mchParam.getNonBendingSlope(); + alpha3 = mchParam.getBendingSlope(); + alpha4 = mchParam.getInverseBendingMomentum(); + + x2 = TMath::ATan2(-alpha3, -alpha1); + x3 = -1. / TMath::Sqrt(alpha3 * alpha3 + alpha1 * alpha1); + x4 = alpha4 * -x3 * TMath::Sqrt(1 + alpha3 * alpha3); + + auto K = alpha1 * alpha1 + alpha3 * alpha3; + auto K32 = K * TMath::Sqrt(K); + auto L = TMath::Sqrt(alpha3 * alpha3 + 1); + + // Covariances matrix conversion + SMatrix55Std jacobian; + SMatrix55Sym covariances; + + covariances(0, 0) = mchParam.getCovariances()(0, 0); + covariances(0, 1) = mchParam.getCovariances()(0, 1); + covariances(0, 2) = mchParam.getCovariances()(0, 2); + covariances(0, 3) = mchParam.getCovariances()(0, 3); + covariances(0, 4) = mchParam.getCovariances()(0, 4); + + covariances(1, 1) = mchParam.getCovariances()(1, 1); + covariances(1, 2) = mchParam.getCovariances()(1, 2); + covariances(1, 3) = mchParam.getCovariances()(1, 3); + covariances(1, 4) = mchParam.getCovariances()(1, 4); + + covariances(2, 2) = mchParam.getCovariances()(2, 2); + covariances(2, 3) = mchParam.getCovariances()(2, 3); + covariances(2, 4) = mchParam.getCovariances()(2, 4); + + covariances(3, 3) = mchParam.getCovariances()(3, 3); + covariances(3, 4) = mchParam.getCovariances()(3, 4); + + covariances(4, 4) = mchParam.getCovariances()(4, 4); + + jacobian(0, 0) = 1; + + jacobian(1, 2) = 1; + + jacobian(2, 1) = -alpha3 / K; + jacobian(2, 3) = alpha1 / K; + + jacobian(3, 1) = alpha1 / K32; + jacobian(3, 3) = alpha3 / K32; + + jacobian(4, 1) = -alpha1 * alpha4 * L / K32; + jacobian(4, 3) = alpha3 * alpha4 * (1 / (TMath::Sqrt(K) * L) - L / K32); + jacobian(4, 4) = L / TMath::Sqrt(K); + + // jacobian*covariances*jacobian^T + covariances = ROOT::Math::Similarity(jacobian, covariances); + + // Set output + convertedTrack.setX(mchParam.getNonBendingCoor()); + convertedTrack.setY(mchParam.getBendingCoor()); + convertedTrack.setZ(mchParam.getZ()); + convertedTrack.setPhi(x2); + convertedTrack.setTanl(x3); + convertedTrack.setInvQPt(x4); + convertedTrack.setCharge(mchParam.getCharge()); + convertedTrack.setCovariances(covariances); + + return convertedTrack; + } + + bool RemoveTrack(mch::Track& track) + { + // Refit track with re-aligned clusters + bool removeTrack = false; + try { + trackFitter.fit(track, false); + } catch (std::exception const& e) { + removeTrack = true; + return removeTrack; + } + + auto itStartingParam = std::prev(track.rend()); + + while (true) { + + try { + trackFitter.fit(track, true, false, (itStartingParam == track.rbegin()) ? nullptr : &itStartingParam); + } catch (std::exception const&) { + removeTrack = true; + break; + } + + double worstLocalChi2 = -1.0; + + track.tagRemovableClusters(0x1F, false); + + auto itWorstParam = track.end(); + + for (auto itParam = track.begin(); itParam != track.end(); ++itParam) { + if (itParam->getLocalChi2() > worstLocalChi2) { + worstLocalChi2 = itParam->getLocalChi2(); + itWorstParam = itParam; + } + } + + if (worstLocalChi2 < mImproveCutChi2) { + break; + } + + if (!itWorstParam->isRemovable()) { + removeTrack = true; + track.removable(); + break; + } + + auto itNextParam = track.removeParamAtCluster(itWorstParam); + auto itNextToNextParam = (itNextParam == track.end()) ? itNextParam : std::next(itNextParam); + itStartingParam = track.rbegin(); + + if (track.getNClusters() < 10) { + removeTrack = true; + break; + } else { + while (itNextToNextParam != track.end()) { + if (itNextToNextParam->getClusterPtr()->getChamberId() != itNextParam->getClusterPtr()->getChamberId()) { + itStartingParam = std::make_reverse_iterator(++itNextParam); + break; + } + ++itNextToNextParam; + } + } + } + + if (!removeTrack) { + for (auto& param : track) { + param.setParameters(param.getSmoothParameters()); + param.setCovariances(param.getSmoothCovariances()); + } + } + + return removeTrack; + } + + template + bool IsGoodMFT(const T& mftTrack, + double chi2Cut, + int nClustersCut) + { + // chi2 cut + if (mftTrack.chi2() > chi2Cut) + return false; + + // number of clusters cut + if (mftTrack.nClusters() < nClustersCut) + return false; + + return true; + } + + template + bool IsGoodMFT(const T& mftTrack) + { + return IsGoodMFT(mftTrack, fTrackChi2MftUp, fTrackNClustMftLow); + } + + template + bool pDCACut(const T& mchTrack, const C& collision, double nSigmaPDCA) + { + static const double sigmaPDCA23 = 80.; + static const double sigmaPDCA310 = 54.; + static const double relPRes = 0.0004; + static const double slopeRes = 0.0005; + + double thetaAbs = TMath::ATan(mchTrack.rAtAbsorberEnd() / 505.) * TMath::RadToDeg(); + + // propagate muon track to vertex + auto mchTrackAtVertex = VarManager::PropagateMuon(mchTrack, collision, VarManager::kToVertex); + + // double pUncorr = mchTrack.p(); + double p = mchTrackAtVertex.getP(); + + double pDCA = mchTrack.pDca(); + double sigmaPDCA = (thetaAbs < 3) ? sigmaPDCA23 : sigmaPDCA310; + double nrp = nSigmaPDCA * relPRes * p; + double pResEffect = sigmaPDCA / (1. - nrp / (1. + nrp)); + double slopeResEffect = 535. * slopeRes * p; + double sigmaPDCAWithRes = TMath::Sqrt(pResEffect * pResEffect + slopeResEffect * slopeResEffect); + if (pDCA > nSigmaPDCA * sigmaPDCAWithRes) { + return false; + } + + return true; + } + + template + bool IsGoodMuon(const T& muonTrack, const C& collision, + double chi2Cut, + double pCut, + double pTCut, + std::array etaCut, + std::array rAbsCut, + double nSigmaPdcaCut) + { + auto const& mchTrack = (static_cast(muonTrack.trackType()) <= 2) ? muonTrack.template matchMCHTrack_as() : muonTrack; + + // chi2 cut + if (mchTrack.chi2() > chi2Cut) + return false; + + // momentum cut + if (mchTrack.p() < pCut) { + return false; // skip low-momentum tracks + } + + // transverse momentum cut + if (mchTrack.pt() < pTCut) { + return false; // skip low-momentum tracks + } + + // Eta cut + double eta = mchTrack.eta(); + if ((eta < etaCut[0] || eta > etaCut[1])) { + return false; + } + + // RAbs cut + double rAbs = mchTrack.rAtAbsorberEnd(); + if ((rAbs < rAbsCut[0] || rAbs > rAbsCut[1])) { + return false; + } + + // pDCA cut + if (!pDCACut(mchTrack, collision, nSigmaPdcaCut)) { + return false; + } + + return true; + } + + template + o2::dataformats::GlobalFwdTrack FwdToTrackPar(const T& track) + { + double chi2 = track.chi2(); + SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd trackparCov{track.z(), tpars, tcovs, chi2}; + o2::dataformats::GlobalFwdTrack fwdtrack; + fwdtrack.setParameters(trackparCov.getParameters()); + fwdtrack.setZ(trackparCov.getZ()); + fwdtrack.setCovariances(trackparCov.getCovariances()); + return fwdtrack; + } + + void TransformMFTPar(o2::mch::TrackParam& track) + { + // double zCH10 = -1437.6; + double z = track.getZ(); + // double dZ = zMCH - z; + double x = track.getNonBendingCoor(); + double y = track.getBendingCoor(); + double xSlope = track.getNonBendingSlope(); + double ySlope = track.getBendingSlope(); + + double xSlopeCorrection = (y > 0) ? configMFTAlignmentCorrections.fMFTAlignmentCorrXSlopeTop : configMFTAlignmentCorrections.fMFTAlignmentCorrXSlopeBottom; + double xCorrection = xSlopeCorrection * z + + ((y > 0) ? configMFTAlignmentCorrections.fMFTAlignmentCorrXOffsetTop : configMFTAlignmentCorrections.fMFTAlignmentCorrXOffsetBottom); + track.setNonBendingCoor(x + xCorrection); + track.setNonBendingSlope(xSlope + xSlopeCorrection); + + double ySlopeCorrection = (y > 0) ? configMFTAlignmentCorrections.fMFTAlignmentCorrYSlopeTop : configMFTAlignmentCorrections.fMFTAlignmentCorrYSlopeBottom; + double yCorrection = ySlopeCorrection * z + + ((y > 0) ? configMFTAlignmentCorrections.fMFTAlignmentCorrYOffsetTop : configMFTAlignmentCorrections.fMFTAlignmentCorrYOffsetBottom); + track.setBendingCoor(y + yCorrection); + track.setBendingSlope(ySlope + ySlopeCorrection); + /* + std::cout << std::format("[TOTO] MFT position: pos={:0.3f},{:0.3f}", x, y) << std::endl; + std::cout << std::format("[TOTO] MFT corrections: pos={:0.3f},{:0.3f} slope={:0.12f},{:0.12f} angle={:0.12f},{:0.12f}", + xCorrection, yCorrection, xSlopeCorrection, ySlopeCorrection, + std::atan2(xSlopeCorrection, 1), std::atan2(ySlopeCorrection, 1)) << std::endl; + */ + } + + void TransformMFT(o2::dataformats::GlobalFwdTrack& track) + { + auto mchTrack = FwdtoMCH(track); + + TransformMFTPar(mchTrack); + + auto transformedTrack = sExtrap.MCHtoFwd(mchTrack); + track.setParameters(transformedTrack.getParameters()); + track.setZ(transformedTrack.getZ()); + track.setCovariances(transformedTrack.getCovariances()); + } + + void TransformMFT(o2::track::TrackParCovFwd& fwdtrack) + { + o2::dataformats::GlobalFwdTrack track; + track.setParameters(fwdtrack.getParameters()); + track.setZ(fwdtrack.getZ()); + track.setCovariances(fwdtrack.getCovariances()); + + auto mchTrack = FwdtoMCH(track); + + TransformMFTPar(mchTrack); + + auto transformedTrack = sExtrap.MCHtoFwd(mchTrack); + fwdtrack.setParameters(transformedTrack.getParameters()); + fwdtrack.setZ(transformedTrack.getZ()); + fwdtrack.setCovariances(transformedTrack.getCovariances()); + } + + template + T UpdateTrackMomentum(const T& track, const double p, int sign) + { + double px = p * sin(M_PI / 2 - atan(track.tgl())) * cos(track.phi()); + double py = p * sin(M_PI / 2 - atan(track.tgl())) * sin(track.phi()); + double pt = std::sqrt(std::pow(px, 2) + std::pow(py, 2)); + + SMatrix5 tpars = {track.x(), track.y(), track.phi(), track.tgl(), sign / pt}; + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + + T newTrack; + newTrack.setParameters(tpars); + newTrack.setZ(track.z()); + newTrack.setCovariances(tcovs); + + return newTrack; + } + + template + T UpdateTrackMomentum(const T& track, const o2::mch::TrackParam& track4mom) + { + double px = track4mom.p() * sin(M_PI / 2 - atan(track.tgl())) * cos(track.phi()); + double py = track4mom.p() * sin(M_PI / 2 - atan(track.tgl())) * sin(track.phi()); + double pt = std::sqrt(std::pow(px, 2) + std::pow(py, 2)); + double sign = track4mom.getCharge(); + + SMatrix5 tpars = {track.x(), track.y(), track.phi(), track.tgl(), sign / pt}; + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + + T newTrack; + newTrack.setParameters(tpars); + newTrack.setZ(track.z()); + newTrack.setCovariances(tcovs); + + return track; + } + + void UpdateTrackMomentum(o2::mch::TrackParam& track, const o2::mch::TrackParam& track4mom) + { + double pRatio = track.p() / track4mom.p(); + double newInvBendMom = track.getInverseBendingMomentum() * pRatio; + track.setInverseBendingMomentum(newInvBendMom); + track.setCharge(track4mom.getCharge()); + } + + void UpdateTrackMomentum(o2::track::TrackParCovFwd& track, const o2::mch::TrackParam& track4mom) + { + auto newTrackMCH = FwdtoMCH(track); + UpdateTrackMomentum(newTrackMCH, track4mom); + auto newTrack = MCHtoFwd(newTrackMCH); + + track.setParameters(newTrack.getParameters()); + track.setZ(newTrack.getZ()); + track.setCovariances(newTrack.getCovariances()); + } + + o2::dataformats::GlobalFwdTrack PropagateMCHParam(mch::TrackParam mchTrack, const double z) + { + float absFront = -90.f; + float absBack = -505.f; + + if (mchTrack.getZ() < absBack && z > absFront) { + // extrapolation through the absorber in the upstream direction + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrack, z); + } else { + // all other cases + o2::mch::TrackExtrap::extrapToZCov(mchTrack, z); + } + + auto proptrack = MCHtoFwd(mchTrack); + o2::dataformats::GlobalFwdTrack propmuon; + propmuon.setParameters(proptrack.getParameters()); + propmuon.setZ(proptrack.getZ()); + propmuon.setCovariances(proptrack.getCovariances()); + + return propmuon; + } + + o2::dataformats::GlobalFwdTrack PropagateMCH(const o2::dataformats::GlobalFwdTrack& muon, const double z) + { + auto mchTrack = FwdtoMCH(muon); + return PropagateMCHParam(mchTrack, z); + } + + o2::dataformats::GlobalFwdTrack PropagateMCHRealigned(const mch::Track& muon, const double z) + { + mch::TrackParam trackParam = mch::TrackParam(muon.first()); + return PropagateMCHParam(trackParam, z); + } + + template + o2::dataformats::GlobalFwdTrack PropagateMCH(const T& muon, const double z) + { + 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 track; + track.setParameters(fwdtrack.getParameters()); + track.setZ(fwdtrack.getZ()); + track.setCovariances(fwdtrack.getCovariances()); + + return PropagateMCH(track, z); + } + + template + o2::dataformats::GlobalFwdTrack PropagateMFT(const TMFT& mftTrack, float z) + { + static double Bz = -10001; + double chi2 = mftTrack.chi2(); + SMatrix5 tpars = {mftTrack.x(), mftTrack.y(), mftTrack.phi(), mftTrack.tgl(), mftTrack.signed1Pt()}; + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{mftTrack.z(), tpars, tcovs, chi2}; + o2::dataformats::GlobalFwdTrack propmuon; + + // double propVec[3] = {}; + // propVec[0] = collision.posX() - mftTrack.x(); + // propVec[1] = collision.posY() - mftTrack.y(); + // propVec[2] = collision.posZ() - mftTrack.z(); + + // double centerZ[3] = {mftTrack.x() + propVec[0] / 2., + // mftTrack.y() + propVec[1] / 2., + // mftTrack.z() + propVec[2] / 2.}; + if (Bz < -10000) { + double centerZ[3] = {0, 0, (-45.f - 77.5f) / 2.f}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + Bz = field->getBz(centerZ); + } + fwdtrack.propagateToZ(z, Bz); + + propmuon.setParameters(fwdtrack.getParameters()); + propmuon.setZ(fwdtrack.getZ()); + propmuon.setCovariances(fwdtrack.getCovariances()); + + return propmuon; + } + + template + o2::dataformats::GlobalFwdTrack PropagateMFTToDCA(const TMFT& mftTrack, const C& collision, float zshift) + { + static double Bz = -10001; + double chi2 = mftTrack.chi2(); + double phiCorrDeg = 0; + double phiCorr = phiCorrDeg * TMath::Pi() / 180.f; + double tR = std::hypot(mftTrack.x(), mftTrack.y()); + double tphi = std::atan2(mftTrack.y(), mftTrack.x()); + double tx = std::cos(tphi + phiCorr) * tR; + double ty = std::sin(tphi + phiCorr) * tR; + SMatrix5 tpars = {tx, ty, mftTrack.phi() + phiCorr, mftTrack.tgl(), mftTrack.signed1Pt()}; + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{mftTrack.z(), tpars, tcovs, chi2}; + if (configMFTAlignmentCorrections.fEnableMFTAlignmentCorrections) { + TransformMFT(fwdtrack); + } + o2::dataformats::GlobalFwdTrack propmuon; + + // double propVec[3] = {}; + // propVec[0] = collision.posX() - mftTrack.x(); + // propVec[1] = collision.posY() - mftTrack.y(); + // propVec[2] = collision.posZ() - mftTrack.z(); + + // double centerZ[3] = {mftTrack.x() + propVec[0] / 2., + // mftTrack.y() + propVec[1] / 2., + // mftTrack.z() + propVec[2] / 2.}; + if (Bz < -10000) { + double centerZ[3] = {0, 0, -45.f / 2.f}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + Bz = field->getBz(centerZ); + } + fwdtrack.propagateToZ(collision.posZ() - zshift, Bz); + + propmuon.setParameters(fwdtrack.getParameters()); + propmuon.setZ(fwdtrack.getZ()); + propmuon.setCovariances(fwdtrack.getCovariances()); + + return propmuon; + } + + template + o2::dataformats::GlobalFwdTrack PropagateMFTToDCA(const TMFT& mftTrack, const TMUON& mchTrack, const C& collision, float zshift) + { + static double Bz = -10001; + double chi2 = mftTrack.chi2(); + double phiCorrDeg = 0; + double phiCorr = phiCorrDeg * TMath::Pi() / 180.f; + double tR = std::hypot(mftTrack.x(), mftTrack.y()); + double tphi = std::atan2(mftTrack.y(), mftTrack.x()); + double tx = std::cos(tphi + phiCorr) * tR; + double ty = std::sin(tphi + phiCorr) * tR; + SMatrix5 tpars = {tx, ty, mftTrack.phi() + phiCorr, mftTrack.tgl(), mftTrack.signed1Pt()}; + std::vector v1{0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd fwdtrack{mftTrack.z(), tpars, tcovs, chi2}; + if (configMFTAlignmentCorrections.fEnableMFTAlignmentCorrections) { + TransformMFT(fwdtrack); + } + + // extrapolation with MCH tools + auto mchTrackAtMFT = FwdtoMCH(FwdToTrackPar(mchTrack)); + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrackAtMFT, mftTrack.z()); + UpdateTrackMomentum(fwdtrack, mchTrackAtMFT); + + // double propVec[3] = {}; + // propVec[0] = collision.posX() - mftTrack.x(); + // propVec[1] = collision.posY() - mftTrack.y(); + // propVec[2] = collision.posZ() - mftTrack.z(); + + // double centerZ[3] = {mftTrack.x() + propVec[0] / 2., + // mftTrack.y() + propVec[1] / 2., + // mftTrack.z() + propVec[2] / 2.}; + if (Bz < -10000) { + double centerZ[3] = {0, 0, -45.f / 2.f}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + Bz = field->getBz(centerZ); + } + fwdtrack.propagateToZ(collision.posZ() - zshift, Bz); + + o2::dataformats::GlobalFwdTrack propmuon; + propmuon.setParameters(fwdtrack.getParameters()); + propmuon.setZ(fwdtrack.getZ()); + propmuon.setCovariances(fwdtrack.getCovariances()); + + return propmuon; + } + + template + o2::dataformats::GlobalFwdTrack PropagateMFTtoMCH(const TMFT& mftTrack, const o2::mch::TrackParam& mchTrackPar, const double z) + { + // extrapolation with MCH tools + auto mchTrackAtMFT = mchTrackPar; + o2::mch::TrackExtrap::extrapToVertexWithoutBranson(mchTrackAtMFT, mftTrack.z()); + + auto mftTrackPar = FwdToTrackPar(mftTrack); + if (configMFTAlignmentCorrections.fEnableMFTAlignmentCorrections) { + TransformMFT(mftTrackPar); + } + auto mftTrackProp = FwdtoMCH(mftTrackPar); + UpdateTrackMomentum(mftTrackProp, mchTrackAtMFT); + if (z < -505.f) { + o2::mch::TrackExtrap::extrapToZ(mftTrackProp, -466.f); + UpdateTrackMomentum(mftTrackProp, mchTrackPar); + } + o2::mch::TrackExtrap::extrapToZ(mftTrackProp, z); + + return MCHtoFwd(mftTrackProp); + } + + void FillDCAPlots(MyEvents const& collisions, + MyBCs const& bcs, + MyMuonsWithCov const& muonTracks, + MyMFTs const& mftTracks, + const std::map& collisionInfos) + { + // outer loop over collisions + for (auto& [collisionIndex, collisionInfo] : collisionInfos) { + auto const& collision = collisions.rawIteratorAt(collisionIndex); + const auto& bc = bcs.rawIteratorAt(collision.bcId()); + + // remove TF/ROF borders and ambiguous collisions + if (!bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || + !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + registry.get(HIST("vertex_y_vs_x"))->Fill(collision.posX(), collision.posY()); + registry.get(HIST("vertex_z"))->Fill(collision.posZ()); + + if (fEnableVertexShiftAnalysis || fEnableMftDcaAnalysis) { + registry.get(HIST("DCA/MFT/nTracksMFT"))->Fill(collisionInfo.mftTracks.size()); + } + + if (fEnableVertexShiftAnalysis || fEnableMftDcaAnalysis) { + // loop over MFT tracks + auto mftTrackIds = collisionInfo.mftTracks; + if (fMftTracksMultiplicityMax > 0 && mftTrackIds.size() > fMftTracksMultiplicityMax) { + auto rng = std::default_random_engine{}; + std::shuffle(std::begin(mftTrackIds), std::end(mftTrackIds), rng); + mftTrackIds.resize(fMftTracksMultiplicityMax); + } + + for (auto mftIndex : mftTrackIds) { + auto const& mftTrack = mftTracks.rawIteratorAt(mftIndex); + + if (mftTrack.isCA()) { + continue; + } + + bool isGoodMFT = IsGoodMFT(mftTrack, 999.f, 5); + if (!isGoodMFT) + continue; + + auto mftTrackAtDCA = PropagateMFTToDCA(mftTrack, collision, fVertexZshift); + double dcax = mftTrackAtDCA.getX() - collision.posX(); + double dcay = mftTrackAtDCA.getY() - collision.posY(); + double phi = mftTrack.phi() * 180 / TMath::Pi(); + int mftNclusters = mftTrack.nClusters(); + double chi2NDF = static_cast(mftNclusters) * 2 - 5; + + const int nMftLayers = 10; + std::array firedLayers; + for (int layer = 0; layer < nMftLayers; layer++) { + if ((mftTrack.mftClusterSizesAndTrackFlags() >> (layer * 6)) & 0x3F) { + firedLayers[layer] = true; + } else { + firedLayers[layer] = false; + } + } + + if (fEnableMftDcaAnalysis) { + const int nMftLayers = 10; + if (fEnableMftDcaExtraPlots) { + for (int i = 0; i < nMftLayers; i++) { + if (firedLayers[i]) { + registry.get(HIST("DCA/MFT/trackChi2"))->Fill(mftTrack.chi2() / chi2NDF, mftTrack.x(), mftTrack.y(), mftNclusters, i); + } + } + } + + if (mftTrack.chi2() <= fTrackChi2MftUp) { + registry.get(HIST("DCA/MFT/DCA_y_vs_x"))->Fill(dcax, dcay); + registry.get(HIST("DCA/MFT/DCA_x"))->Fill(dcax, collision.posZ(), mftTrack.x(), mftTrack.y(), mftNclusters); + registry.get(HIST("DCA/MFT/DCA_y"))->Fill(dcay, collision.posZ(), mftTrack.x(), mftTrack.y(), mftNclusters); + + if (fEnableMftDcaExtraPlots) { + if (mftNclusters >= 6) { + for (int i = 0; i < nMftLayers; i++) { + auto mftTrackAtLayer = PropagateMFT(mftTrack, o2::mft::constants::mft::LayerZCoordinate()[i]); + std::get>(mMftTrackEffDen[i])->Fill(mftTrackAtLayer.getX(), mftTrackAtLayer.getY()); + if (firedLayers[i]) { + std::get>(mMftTrackEffNum[i])->Fill(mftTrackAtLayer.getX(), mftTrackAtLayer.getY()); + registry.get(HIST("DCA/MFT/layers"))->Fill(i, mftTrack.x(), mftTrack.y(), mftNclusters); + } + } + } + for (int i = 0; i < nMftLayers; i++) { + if (firedLayers[i]) { + registry.get(HIST("DCA/MFT/trackMomentum"))->Fill(mftTrack.p(), mftTrack.x(), mftTrack.y(), mftNclusters, i); + } + } + } + } + } + + if (fEnableVertexShiftAnalysis) { + if (mftTrack.chi2() <= fTrackChi2MftUp && std::fabs(collision.posZ()) < 1.f && mftNclusters >= 6) { + float zshift[21] = {// in millimeters + -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, + 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0}; + for (int zi = 0; zi < 21; zi++) { + auto mftTrackAtDCAshifted = PropagateMFTToDCA(mftTrack, collision, zshift[zi] / 10.f); + double dcaxShifted = mftTrackAtDCAshifted.getX() - collision.posX(); + double dcayShifted = mftTrackAtDCAshifted.getY() - collision.posY(); + registry.get(HIST("DCA/MFT/DCA_x_vs_phi_vs_zshift"))->Fill(zshift[zi], phi, dcaxShifted); + registry.get(HIST("DCA/MFT/DCA_y_vs_phi_vs_zshift"))->Fill(zshift[zi], phi, dcayShifted); + + auto mftTrackAtDCAshiftedPar = FwdtoMCH(mftTrackAtDCAshifted); + auto slopex = mftTrackAtDCAshiftedPar.getNonBendingSlope(); + auto slopey = mftTrackAtDCAshiftedPar.getBendingSlope(); + registry.get(HIST("DCA/MFT/DCA_x_vs_slopex_vs_zshift"))->Fill(zshift[zi], slopex, dcaxShifted); + registry.get(HIST("DCA/MFT/DCA_x_vs_slopey_vs_zshift"))->Fill(zshift[zi], slopey, dcaxShifted); + registry.get(HIST("DCA/MFT/DCA_y_vs_slopex_vs_zshift"))->Fill(zshift[zi], slopex, dcayShifted); + registry.get(HIST("DCA/MFT/DCA_y_vs_slopey_vs_zshift"))->Fill(zshift[zi], slopey, dcayShifted); + } + } + } + } + } + + if (fEnableGlobalFwdDcaAnalysis) { + // loop over global muon tracks + for (auto& [muonIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { + auto const& muonTrack = muonTracks.rawIteratorAt(globalTracksVector[0]); + const auto& mchTrack = muonTrack.template matchMCHTrack_as(); + const auto& mftTrack = muonTrack.template matchMFTTrack_as(); + + if (muonTrack.chi2MatchMCHMFT() < 50) { + continue; + } + + if (globalTracksVector.size() > 1) { + auto const& muonTrack2 = muonTracks.rawIteratorAt(globalTracksVector[1]); + double dchi2 = muonTrack2.chi2MatchMCHMFT() - muonTrack.chi2MatchMCHMFT(); + + if (dchi2 < 50) { + continue; + } + } + + if (mftTrack.isCA()) { + continue; + } + + bool isGoodMFT = IsGoodMFT(mftTrack, fTrackChi2MftUp, 5); + if (!isGoodMFT) { + continue; + } + + bool isGoodMuon = IsGoodMuon(mchTrack, collision, fTrackChi2MchUp, 0.f, fPtMchLow, {fEtaMftLow, fEtaMftUp}, {fRabsLow, fRabsUp}, fSigmaPdcaUp); + if (!isGoodMuon) + continue; + + auto mftTrackAtDCA = PropagateMFTToDCA(mftTrack, mchTrack, collision, fVertexZshift); + double dcax = mftTrackAtDCA.getX() - collision.posX(); + double dcay = mftTrackAtDCA.getY() - collision.posY(); + int mftNclusters = mftTrack.nClusters(); + + if (mftTrack.chi2() <= fTrackChi2MftUp) { + registry.get(HIST("DCA/GlobalFwd/DCA_x"))->Fill(dcax, collision.posZ(), mftTrack.x(), mftTrack.y(), mftNclusters); + registry.get(HIST("DCA/GlobalFwd/DCA_y"))->Fill(dcay, collision.posZ(), mftTrack.x(), mftTrack.y(), mftNclusters); + } + } + } + } + } + + template + bool MchRealignTrack(const TMUON& mchTrack, const TCLUS& clusters, TrackRealigned& convertedTrack, bool applyCorrections) + { + // loop over attached clusters + int clIndex = -1; + auto clustersSliced = clusters.sliceBy(perMuon, mchTrack.globalIndex()); // Slice clusters by muon id + for (auto const& cluster : clustersSliced) { + clIndex += 1; + + int deId = cluster.deId(); + int chamber = deId / 100 - 1; + if (chamber < 0 || chamber > 9) { + continue; + } + + math_utils::Point3D local; + math_utils::Point3D master; + + master.SetXYZ(cluster.x(), cluster.y(), cluster.z()); + + if (configRealign.fEnableMCHRealign) { + // Transformation from reference geometry frame to new geometry frame + transformRef[cluster.deId()].MasterToLocal(master, local); + transformNew[cluster.deId()].LocalToMaster(local, master); + } + + if (applyCorrections) { + auto correctionsIt = mMchAlignmentCorrections.find(cluster.deId()); + if (correctionsIt != mMchAlignmentCorrections.end()) { + const auto& corrections = correctionsIt->second; + master.SetX(master.x() + corrections.x); + master.SetY(master.y() + corrections.y); + master.SetZ(master.z() + corrections.z); + } + } + + // realigned MCH cluster + mch::Cluster* clusterMCH = new mch::Cluster(); + clusterMCH->x = master.x(); + clusterMCH->y = master.y(); + clusterMCH->z = master.z(); + + uint32_t ClUId = mch::Cluster::buildUniqueId(static_cast(cluster.deId() / 100) - 1, cluster.deId(), clIndex); + clusterMCH->uid = ClUId; + clusterMCH->ex = cluster.isGoodX() ? 0.2 : 10.0; + clusterMCH->ey = cluster.isGoodY() ? 0.2 : 10.0; + + // Add transformed cluster into temporary variable + convertedTrack.createParamAtCluster(*clusterMCH); + } + + bool removable{false}; + // Refit the re-aligned track + if (convertedTrack.getNClusters() != 0) { + removable = RemoveTrack(convertedTrack); + } else { + LOGF(fatal, "Muon track %d has no associated clusters.", mchTrack.globalIndex()); + } + + return !removable; + } + + void FillResidualsPlots(MyEvents const& collisions, + MyBCs const& bcs, + MyMuonsWithCov const& muonTracks, + aod::FwdTrkCls const& clusters, + const std::map& collisionInfos) + { + if (!fEnableMftMchResidualsAnalysis) { + return; + } + + // loop over collisions + for (auto& [collisionIndex, collisionInfo] : collisionInfos) { + auto const& collision = collisions.rawIteratorAt(collisionIndex); + const auto& bc = bcs.rawIteratorAt(collision.bcId()); + + // remove TF/ROF borders and ambiguous collisions + if (!bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || + !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // loop over global muon tracks + for (auto& [muonIndex, globalTracksVector] : collisionInfo.globalMuonTracks) { + auto const& muonTrack = muonTracks.rawIteratorAt(globalTracksVector[0]); + const auto& mchTrack = muonTrack.template matchMCHTrack_as(); + const auto& mftTrack = muonTrack.template matchMFTTrack_as(); + int quadrantMch = GetQuadrant(mchTrack); + int posNeg = (mchTrack.sign() >= 0) ? 0 : 1; + + bool isGoodMuon = IsGoodMuon(mchTrack, collision, fTrackChi2MchUp, fMftMchResidualsPLow, fMftMchResidualsPtLow, {fEtaMftLow, fEtaMftUp}, {fRabsLow, fRabsUp}, fSigmaPdcaUp); + if (!isGoodMuon) + continue; + + bool isGoodMFT = IsGoodMFT(mftTrack, fTrackChi2MftUp, fTrackNClustMftLow); + if (!isGoodMFT) + continue; + + // refit MCH track if enabled + TrackRealigned convertedTrack; + bool convertedTrackOk = false; + if (configRealign.fEnableMCHRealign) { + convertedTrackOk = MchRealignTrack(mchTrack, clusters, convertedTrack, false); + } + + // apply alignment corrections if available + TrackRealigned convertedTrackWithCorr; + bool convertedTrackWithCorrOk = false; + if (!mMchAlignmentCorrections.empty()) { + convertedTrackWithCorrOk = MchRealignTrack(mchTrack, clusters, convertedTrackWithCorr, true); + } + + // loop over attached clusters + auto clustersSliced = clusters.sliceBy(perMuon, mchTrack.globalIndex()); // Slice clusters by muon id + for (auto const& cluster : clustersSliced) { + int deId = cluster.deId(); + int chamber = deId / 100 - 1; + if (chamber < 0 || chamber > 9) + continue; + int deIndex = getDEindex(deId); + + math_utils::Point3D local; + math_utils::Point3D master; + math_utils::Point3D masterWithCorr; + + master.SetXYZ(cluster.x(), cluster.y(), cluster.z()); + masterWithCorr.SetXYZ(cluster.x(), cluster.y(), cluster.z()); + + // apply realignment to MCH cluster + if (configRealign.fEnableMCHRealign) { + // Transformation from reference geometry frame to new geometry frame + transformRef[cluster.deId()].MasterToLocal(master, local); + transformNew[cluster.deId()].LocalToMaster(local, master); + transformNew[cluster.deId()].LocalToMaster(local, masterWithCorr); + } + + // apply alignment corrections to MCH cluster (if available) + if (!mMchAlignmentCorrections.empty()) { + auto correctionsIt = mMchAlignmentCorrections.find(cluster.deId()); + if (correctionsIt != mMchAlignmentCorrections.end()) { + const auto& corrections = correctionsIt->second; + masterWithCorr.SetX(masterWithCorr.x() + corrections.x); + masterWithCorr.SetY(masterWithCorr.y() + corrections.y); + masterWithCorr.SetZ(masterWithCorr.z() + corrections.z); + } + } + + // MFT-MCH residuals (MCH cluster is realigned if enabled) + // if the realignment is enabled and successful, the MFT track is extrpolated + // by taking the momentum from the MCH track refitted with the new alignment + if (!configRealign.fEnableMCHRealign || convertedTrackOk) { + auto mftTrackAtCluster = configRealign.fEnableMCHRealign ? PropagateMFTtoMCH(mftTrack, mch::TrackParam(convertedTrack.first()), master.z()) : PropagateMFTtoMCH(mftTrack, FwdtoMCH(FwdToTrackPar(mchTrack)), master.z()); + + std::array xPos{master.x(), mftTrackAtCluster.getX()}; + std::array yPos{master.y(), mftTrackAtCluster.getY()}; + + registry.get(HIST("residuals/dx_vs_chamber"))->Fill(chamber + 1, quadrantMch, posNeg, xPos[0] - xPos[1]); + registry.get(HIST("residuals/dy_vs_chamber"))->Fill(chamber + 1, quadrantMch, posNeg, yPos[0] - yPos[1]); + + registry.get(HIST("residuals/dx_vs_de"))->Fill(xPos[0] - xPos[1], deIndex, quadrantMch, posNeg, mchTrack.p()); + registry.get(HIST("residuals/dy_vs_de"))->Fill(yPos[0] - yPos[1], deIndex, quadrantMch, posNeg, mchTrack.p()); + } + + // MFT-MCH residuals with realigned and/or corrected MCH clusters + // if the alignment corrections are available and the refitting is successful, the MFT track is extrpolated + // by taking the momentum from the MCH track refitted with the alignment corrections and the new + // alignment (if realignment is enabled) + if (convertedTrackWithCorrOk) { + auto mftTrackAtClusterWithCorr = PropagateMFTtoMCH(mftTrack, mch::TrackParam(convertedTrackWithCorr.first()), masterWithCorr.z()); + + std::array xPos{masterWithCorr.x(), mftTrackAtClusterWithCorr.getX()}; + std::array yPos{masterWithCorr.y(), mftTrackAtClusterWithCorr.getY()}; + + registry.get(HIST("residuals/dx_vs_chamber_corr"))->Fill(chamber + 1, quadrantMch, posNeg, xPos[0] - xPos[1]); + registry.get(HIST("residuals/dy_vs_chamber_corr"))->Fill(chamber + 1, quadrantMch, posNeg, yPos[0] - yPos[1]); + + registry.get(HIST("residuals/dx_vs_de_corr"))->Fill(xPos[0] - xPos[1], deIndex, quadrantMch, posNeg, mchTrack.p()); + registry.get(HIST("residuals/dy_vs_de_corr"))->Fill(yPos[0] - yPos[1], deIndex, quadrantMch, posNeg, mchTrack.p()); + } + } + + if (!configRealign.fEnableMCHRealign || convertedTrackOk) { + auto mchTrackAtDCA = configRealign.fEnableMCHRealign ? PropagateMCHRealigned(convertedTrack, collision.posZ()) : PropagateMCH(mchTrack, collision.posZ()); + auto dcax = mchTrackAtDCA.getX() - collision.posX(); + auto dcay = mchTrackAtDCA.getY() - collision.posY(); + + registry.get(HIST("DCA/MCH/DCA_y_vs_x"))->Fill(dcax, dcay); + registry.get(HIST("DCA/MCH/DCA_x_vs_sign_vs_quadrant_vs_mom"))->Fill(mchTrack.p(), quadrantMch, posNeg, dcax); + registry.get(HIST("DCA/MCH/DCA_y_vs_sign_vs_quadrant_vs_mom"))->Fill(mchTrack.p(), quadrantMch, posNeg, dcay); + + if (fEnableMftMchResidualsExtraPlots) { + registry.get(HIST("DCA/MCH/DCA_x_vs_sign_vs_quadrant_vs_vz"))->Fill(collision.posZ(), quadrantMch, posNeg, dcax); + registry.get(HIST("DCA/MCH/DCA_y_vs_sign_vs_quadrant_vs_vz"))->Fill(collision.posZ(), quadrantMch, posNeg, dcay); + auto mchTrackAtMFT = configRealign.fEnableMCHRealign ? PropagateMCHRealigned(convertedTrack, mftTrack.z()) : PropagateMCH(mchTrack, mftTrack.z()); + double deltaPhi = mchTrackAtMFT.getPhi() - mftTrack.phi(); + registry.get(HIST("residuals/dphi_at_mft"))->Fill(deltaPhi, mftTrack.x(), mftTrack.y(), posNeg, mchTrackAtMFT.getP()); + } + } + + if (convertedTrackWithCorrOk) { + auto mchTrackAtDCA = PropagateMCHRealigned(convertedTrackWithCorr, collision.posZ()); + auto dcax = mchTrackAtDCA.getX() - collision.posX(); + auto dcay = mchTrackAtDCA.getY() - collision.posY(); + + registry.get(HIST("DCA/MCH/DCA_x_vs_sign_vs_quadrant_vs_mom_corr"))->Fill(mchTrack.p(), quadrantMch, posNeg, dcax); + registry.get(HIST("DCA/MCH/DCA_y_vs_sign_vs_quadrant_vs_mom_corr"))->Fill(mchTrack.p(), quadrantMch, posNeg, dcay); + } + } + } + } + + void processQA(MyEvents const& collisions, + MyBCs const& bcs, + MyMuonsWithCov const& muonTracks, + MyMFTs const& mftTracks, + // MyMFTCovariances const& mftCovariances, + aod::FwdTrkCls const& clusters) + { + auto bc = bcs.begin(); + if (mRunNumber != bc.runNumber()) { + initCCDB(bc); + LOGF(info, "Set field for muons"); + VarManager::SetupMuonMagField(); + mRunNumber = bc.runNumber(); + } + + std::map collisionInfos; + InitCollisions(collisions, bcs, muonTracks, mftTracks, collisionInfos); + + FillDCAPlots(collisions, bcs, muonTracks, mftTracks, collisionInfos); + + FillResidualsPlots(collisions, bcs, muonTracks, clusters, collisionInfos); + } + + PROCESS_SWITCH(muonGlobalAlignment, processQA, "process qa", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGDQ/Tasks/qaMatching.cxx b/PWGDQ/Tasks/qaMatching.cxx index dbff66e92ae..9611f690500 100644 --- a/PWGDQ/Tasks/qaMatching.cxx +++ b/PWGDQ/Tasks/qaMatching.cxx @@ -15,31 +15,72 @@ // #include "PWGDQ/Core/MuonMatchingMlResponse.h" #include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/DataModel/EventSelection.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "MFTTracking/Constants.h" - -#include +#include "Tools/ML/MlResponse.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include +#include + +#include #include +#include +#include +#include +#include +#include +#include +#include #include -#include #include #include +#include #include #include #include #include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::aod; @@ -95,6 +136,7 @@ struct qaMatching { double matchScoreProd{-1}; double matchChi2Prod{-1}; int matchRankingProd{-1}; + int mftMchMatchAttempts{0}; MuonMatchType matchType{kMatchTypeUndefined}; }; @@ -130,12 +172,6 @@ struct qaMatching { Configurable fMuonTaggingSigmaPdcaUp{"cfgMuonTaggingPdcaUp", 4.f, ""}; Configurable fMuonTaggingChi2DiffLow{"cfgMuonTaggingChi2DiffLow", 100.f, ""}; - /// Variables to event mixing criteria - Configurable fSaveMixedMatchingParamsRate{"cfgSaveMixedMatchingParamsRate", 0.002f, ""}; - Configurable fEventMaxDeltaNMFT{"cfgEventMaxDeltaNMFT", 1, ""}; - Configurable fEventMaxDeltaVtxZ{"cfgEventMaxDeltaVtxZ", 1.f, ""}; - Configurable fEventMinDeltaBc{"cfgEventMinDeltaBc", 500, ""}; - //// Variables for ccdb 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"}; @@ -151,8 +187,13 @@ struct qaMatching { Configurable fConfigGrpMagPath{"grpmagPath-", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; } fConfigCCDB; + struct : ConfigurableGroup { + Configurable fCreatePdgMomHistograms{"cfgCreatePdgMomHistograms", false, "create matching characteristics plots with particle mom PDG codes"}; + } fConfigQAs; + /// Variables for histograms configuration - Configurable fNCandidatesMax{"nCandidatesMax", 5, ""}; + Configurable fNCandidatesMax{"cfgNCandidatesMax", 5, "Number of matching candidates stored for each muon track"}; + Configurable fMftTrackMultiplicityMax{"cfgMftTrackMultiplicityMax", 1000, "Maximum number of MFT tracks per collision"}; double mBzAtMftCenter{0}; @@ -162,58 +203,107 @@ struct qaMatching { std::map mMatchingFunctionMap; ///< MFT-MCH Matching function // Chi2 matching interface - static constexpr int sChi2FunctionsNum = 3; + static constexpr int sChi2FunctionsNum = 5; struct : ConfigurableGroup { - std::array, sChi2FunctionsNum> fFunctionLabel{{ - {"cfgChi2FunctionLabel_0", std::string{"ProdAll"}, "Text label identifying this chi2 matching method"}, - {"cfgChi2FunctionLabel_1", std::string{"MatchXYPhiTanlMom"}, "Text label identifying this chi2 matching method"}, - {"cfgChi2FunctionLabel_2", std::string{"MatchXYPhiTanl"}, "Text label identifying this chi2 matching method"}, - }}; - std::array, sChi2FunctionsNum> fFunctionName{{{"cfgChi2FunctionNames_0", std::string{"prod"}, "Name of the chi2 matching function"}, - {"cfgChi2FunctionNames_1", std::string{"matchALL"}, "Name of the chi2 matching function"}, - {"cfgChi2FunctionNames_2", std::string{"matchXYPhiTanl"}, "Name of the chi2 matching function"}}}; - std::array, sChi2FunctionsNum> fMatchingScoreCut{{ - {"cfgChi2FunctionMatchingScoreCut_0", 0.f, "Minimum score value for selecting good matches"}, - {"cfgChi2FunctionMatchingScoreCut_1", 0.5f, "Minimum score value for selecting good matches"}, - {"cfgChi2FunctionMatchingScoreCut_2", 0.5f, "Minimum score value for selecting good matches"}, - }}; - std::array, sChi2FunctionsNum> fMatchingPlaneZ{{ - {"cfgChi2FunctionMatchingPlaneZ_0", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - {"cfgChi2FunctionMatchingPlaneZ_1", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - {"cfgChi2FunctionMatchingPlaneZ_2", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - }}; - std::array, sChi2FunctionsNum> fMatchingExtrapMethod{{ - {"cfgMatchingExtrapMethod_0", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - {"cfgMatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - {"cfgMatchingExtrapMethod_2", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - }}; + Configurable fFunctionLabel_1{"cfgChi2FunctionLabel_1", std::string{"ProdAll"}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_2{"cfgChi2FunctionLabel_2", std::string{"MatchXYPhiTanlMom"}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_3{"cfgChi2FunctionLabel_3", std::string{"MatchXYPhiTanl"}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_4{"cfgChi2FunctionLabel_4", std::string{""}, "Text label identifying this chi2 matching method"}; + Configurable fFunctionLabel_5{"cfgChi2FunctionLabel_5", std::string{""}, "Text label identifying this chi2 matching method"}; + std::array*, sChi2FunctionsNum> fFunctionLabel{ + &fFunctionLabel_1, &fFunctionLabel_2, &fFunctionLabel_3, &fFunctionLabel_4, &fFunctionLabel_5}; + + Configurable fFunctionNames_1{"cfgChi2FunctionNames_1", std::string{"prod"}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_2{"cfgChi2FunctionNames_2", std::string{"matchALL"}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_3{"cfgChi2FunctionNames_3", std::string{"matchXYPhiTanl"}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_4{"cfgChi2FunctionNames_4", std::string{""}, "Name of the chi2 matching function"}; + Configurable fFunctionNames_5{"cfgChi2FunctionNames_5", std::string{""}, "Name of the chi2 matching function"}; + std::array*, sChi2FunctionsNum> fFunctionName{ + &fFunctionNames_1, &fFunctionNames_2, &fFunctionNames_3, &fFunctionNames_4, &fFunctionNames_5}; + + Configurable fMatchingScoreCut_1{"cfgChi2FunctionMatchingScoreCut_1", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_2{"cfgChi2FunctionMatchingScoreCut_2", 0.5f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_3{"cfgChi2FunctionMatchingScoreCut_3", 0.5f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_4{"cfgChi2FunctionMatchingScoreCut_4", 0.5f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_5{"cfgChi2FunctionMatchingScoreCut_5", 0.5f, "Minimum score value for selecting good matches"}; + std::array*, sChi2FunctionsNum> fMatchingScoreCut{ + &fMatchingScoreCut_1, &fMatchingScoreCut_2, &fMatchingScoreCut_3, &fMatchingScoreCut_4, &fMatchingScoreCut_5}; + + Configurable fMatchingPlaneZ_1{"cfgChi2FunctionMatchingPlaneZ_1", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_2{"cfgChi2FunctionMatchingPlaneZ_2", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_3{"cfgChi2FunctionMatchingPlaneZ_3", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_4{"cfgChi2FunctionMatchingPlaneZ_4", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_5{"cfgChi2FunctionMatchingPlaneZ_5", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + std::array*, sChi2FunctionsNum> fMatchingPlaneZ{ + &fMatchingPlaneZ_1, &fMatchingPlaneZ_2, &fMatchingPlaneZ_3, &fMatchingPlaneZ_4, &fMatchingPlaneZ_5}; + + Configurable fMatchingExtrapMethod_1{"cfgChi2MatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_2{"cfgChi2MatchingExtrapMethod_2", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_3{"cfgChi2MatchingExtrapMethod_3", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_4{"cfgChi2MatchingExtrapMethod_4", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_5{"cfgChi2MatchingExtrapMethod_5", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + std::array*, sChi2FunctionsNum> fMatchingExtrapMethod{ + &fMatchingExtrapMethod_1, &fMatchingExtrapMethod_2, &fMatchingExtrapMethod_3, &fMatchingExtrapMethod_4, &fMatchingExtrapMethod_5}; } fConfigChi2MatchingOptions; // ML interface - static constexpr int sMLModelsNum = 2; + static constexpr int sMLModelsNum = 5; struct : ConfigurableGroup { - std::array, sMLModelsNum> fModelLabel{{ - {"cfgMLModelLabel_0", std::string{""}, "Text label identifying this group of ML models"}, - {"cfgMLModelLabel_1", std::string{""}, "Text label identifying this group of ML models"}, - }}; - std::array>, sMLModelsNum> fModelPathsCCDB{{{"cfgMLModelPathsCCDB_0", std::vector{"Users/m/mcoquet/MLTest"}, "Paths of models on CCDB"}, - {"cfgMLModelPathsCCDB_1", std::vector{}, "Paths of models on CCDB"}}}; - std::array>, sMLModelsNum> fInputFeatures{{{"cfgMLInputFeatures_0", std::vector{"chi2MCHMFT"}, "Names of ML model input features"}, - {"cfgMLInputFeatures_1", std::vector{}, "Names of ML model input features"}}}; - std::array>, sMLModelsNum> fModelNames{{{"cfgMLModelNames_0", std::vector{"model.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}, - {"cfgMLModelNames_1", std::vector{}, "ONNX file names for each pT bin (if not from CCDB full path)"}}}; - std::array, sMLModelsNum> fMatchingScoreCut{{ - {"cfgMLModelMatchingScoreCut_0", 0.f, "Minimum score value for selecting good matches"}, - {"cfgMLModelMatchingScoreCut_1", 0.f, "Minimum score value for selecting good matches"}, - }}; - std::array, sMLModelsNum> fMatchingPlaneZ{{ - {"cfgMLModelMatchingPlaneZ_0", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}, - {"cfgMLModelMatchingPlaneZ_1", 0.f, "Z position of the matching plane"}, - }}; - std::array, sMLModelsNum> fMatchingExtrapMethod{{ - {"cfgMatchingExtrapMethod_0", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - {"cfgMatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}, - }}; + Configurable fModelLabel_1{"cfgMLModelLabel_1", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_2{"cfgMLModelLabel_2", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_3{"cfgMLModelLabel_3", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_4{"cfgMLModelLabel_4", std::string{""}, "Text label identifying this group of ML models"}; + Configurable fModelLabel_5{"cfgMLModelLabel_5", std::string{""}, "Text label identifying this group of ML models"}; + std::array*, sMLModelsNum> fModelLabel{ + &fModelLabel_1, &fModelLabel_2, &fModelLabel_3, &fModelLabel_4, &fModelLabel_5}; + + Configurable fModelPathCCDB_1{"cfgMLModelPathCCDB_1", "Users/m/mcoquet/MLTest", "Paths of models on CCDB"}; + Configurable fModelPathCCDB_2{"cfgMLModelPathsCCDB_2", std::string{""}, "Paths of models on CCDB"}; + Configurable fModelPathCCDB_3{"cfgMLModelPathsCCDB_3", std::string{""}, "Paths of models on CCDB"}; + Configurable fModelPathCCDB_4{"cfgMLModelPathsCCDB_4", std::string{""}, "Paths of models on CCDB"}; + Configurable fModelPathCCDB_5{"cfgMLModelPathsCCDB_5", std::string{""}, "Paths of models on CCDB"}; + std::array*, sMLModelsNum> fModelPathCCDB{ + &fModelPathCCDB_1, &fModelPathCCDB_2, &fModelPathCCDB_3, &fModelPathCCDB_4, &fModelPathCCDB_5}; + + Configurable fModelName_1{"cfgMLModelName_1", "model.onnx", "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_2{"cfgMLModelNames_2", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_3{"cfgMLModelNames_3", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_4{"cfgMLModelNames_4", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable fModelName_5{"cfgMLModelNames_5", std::string{""}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + std::array*, sMLModelsNum> fModelName{ + &fModelName_1, &fModelName_2, &fModelName_3, &fModelName_4, &fModelName_5}; + + Configurable fInputFeatures_1{"cfgMLInputFeatures_1", "chi2MCHMFT", "Names of ML model input features"}; + Configurable fInputFeatures_2{"cfgMLInputFeatures_2", std::string{""}, "Names of ML model input features"}; + Configurable fInputFeatures_3{"cfgMLInputFeatures_3", std::string{""}, "Names of ML model input features"}; + Configurable fInputFeatures_4{"cfgMLInputFeatures_4", std::string{""}, "Names of ML model input features"}; + Configurable fInputFeatures_5{"cfgMLInputFeatures_5", std::string{""}, "Names of ML model input features"}; + std::array*, sMLModelsNum> fInputFeatures{ + &fInputFeatures_1, &fInputFeatures_2, &fInputFeatures_3, &fInputFeatures_4, &fInputFeatures_5}; + + Configurable fMatchingScoreCut_1{"cfgMLModelMatchingScoreCut_1", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_2{"cfgMLModelMatchingScoreCut_2", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_3{"cfgMLModelMatchingScoreCut_3", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_4{"cfgMLModelMatchingScoreCut_4", 0.f, "Minimum score value for selecting good matches"}; + Configurable fMatchingScoreCut_5{"cfgMLModelMatchingScoreCut_5", 0.f, "Minimum score value for selecting good matches"}; + std::array*, sMLModelsNum> fMatchingScoreCut{ + &fMatchingScoreCut_1, &fMatchingScoreCut_2, &fMatchingScoreCut_3, &fMatchingScoreCut_4, &fMatchingScoreCut_5}; + + Configurable fMatchingPlaneZ_1{"cfgMLModelMatchingPlaneZ_1", static_cast(o2::mft::constants::mft::LayerZCoordinate()[9]), "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_2{"cfgMLModelMatchingPlaneZ_2", 0.f, "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_3{"cfgMLModelMatchingPlaneZ_3", 0.f, "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_4{"cfgMLModelMatchingPlaneZ_4", 0.f, "Z position of the matching plane"}; + Configurable fMatchingPlaneZ_5{"cfgMLModelMatchingPlaneZ_5", 0.f, "Z position of the matching plane"}; + std::array*, sMLModelsNum> fMatchingPlaneZ{ + &fMatchingPlaneZ_1, &fMatchingPlaneZ_2, &fMatchingPlaneZ_3, &fMatchingPlaneZ_4, &fMatchingPlaneZ_5}; + + Configurable fMatchingExtrapMethod_1{"cfgMLMatchingExtrapMethod_1", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_2{"cfgMLMatchingExtrapMethod_2", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_3{"cfgMLMatchingExtrapMethod_3", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_4{"cfgMLMatchingExtrapMethod_4", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + Configurable fMatchingExtrapMethod_5{"cfgMLMatchingExtrapMethod_5", static_cast(0), "Method for MCH track extrapolation to maching plane"}; + std::array*, sMLModelsNum> fMatchingExtrapMethod{ + &fMatchingExtrapMethod_1, &fMatchingExtrapMethod_2, &fMatchingExtrapMethod_3, &fMatchingExtrapMethod_4, &fMatchingExtrapMethod_5}; } fConfigMlOptions; std::vector binsPtMl; @@ -297,20 +387,29 @@ struct qaMatching { struct EfficiencyPlotter { o2::framework::HistPtr p_num; o2::framework::HistPtr p_den; + o2::framework::HistPtr p_pdg_num; + o2::framework::HistPtr p_pdg_den; o2::framework::HistPtr pt_num; o2::framework::HistPtr pt_den; + o2::framework::HistPtr pt_pdg_num; + o2::framework::HistPtr pt_pdg_den; o2::framework::HistPtr phi_num; o2::framework::HistPtr phi_den; + o2::framework::HistPtr phi_pdg_num; + o2::framework::HistPtr phi_pdg_den; o2::framework::HistPtr eta_num; o2::framework::HistPtr eta_den; + o2::framework::HistPtr eta_pdg_num; + o2::framework::HistPtr eta_pdg_den; EfficiencyPlotter(std::string path, std::string title, - HistogramRegistry& registry) + HistogramRegistry& registry, bool createPdgMomHistograms) { AxisSpec pAxis = {100, 0, 100, "p (GeV/c)"}; AxisSpec pTAxis = {100, 0, 10, "p_{T} (GeV/c)"}; AxisSpec etaAxis = {100, -4, -2, "#eta"}; AxisSpec phiAxis = {90, -180, 180, "#phi (degrees)"}; + AxisSpec motherPDGAxis{1201, -600.5, 600.5, "Direct mother PDG"}; std::string histName; std::string histTitle; @@ -324,6 +423,16 @@ struct qaMatching { histTitle = title + " vs. p - den"; p_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {pAxis}}); + if (createPdgMomHistograms) { + histName = path + "p_pdg_num"; + histTitle = title + " vs. p vs pdg ID - num"; + p_pdg_num = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {pAxis, motherPDGAxis}}); + + histName = path + "p_pdg_den"; + histTitle = title + " vs. p vs pdg ID - den"; + p_pdg_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {pAxis, motherPDGAxis}}); + } + // pT dependence histName = path + "pt_num"; histTitle = title + " vs. p_{T} - num"; @@ -333,6 +442,16 @@ struct qaMatching { histTitle = title + " vs. p_{T} - den"; pt_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {pTAxis}}); + if (createPdgMomHistograms) { + histName = path + "pt_pdg_num"; + histTitle = title + " vs. p_{T} vs pdg ID - num"; + pt_pdg_num = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {pTAxis, motherPDGAxis}}); + + histName = path + "pt_pdg_den"; + histTitle = title + " vs. p_{T} vs pdg ID - den"; + pt_pdg_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {pTAxis, motherPDGAxis}}); + } + // eta dependence histName = path + "eta_num"; histTitle = title + " vs. #eta - num"; @@ -342,6 +461,16 @@ struct qaMatching { histTitle = title + " vs. #eta - den"; eta_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {etaAxis}}); + if (createPdgMomHistograms) { + histName = path + "eta_pdg_num"; + histTitle = title + " vs. #eta vs pdg ID - num"; + eta_pdg_num = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {etaAxis, motherPDGAxis}}); + + histName = path + "eta_pdg_den"; + histTitle = title + " vs. #eta vs pdg ID - den"; + eta_pdg_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {etaAxis, motherPDGAxis}}); + } + // phi dependence histName = path + "phi_num"; histTitle = title + " vs. #phi - num"; @@ -350,6 +479,16 @@ struct qaMatching { histName = path + "phi_den"; histTitle = title + " vs. #phi - den"; phi_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {phiAxis}}); + + if (createPdgMomHistograms) { + histName = path + "phi_pdg_num"; + histTitle = title + " vs. #phi vs pdg ID - num"; + phi_pdg_num = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {phiAxis, motherPDGAxis}}); + + histName = path + "phi_pdg_den"; + histTitle = title + " vs. #phi vs pdg ID - den"; + phi_pdg_den = registry.add(histName.c_str(), histTitle.c_str(), {HistType::kTH2F, {phiAxis, motherPDGAxis}}); + } } template @@ -368,6 +507,24 @@ struct qaMatching { std::get>(phi_num)->Fill(phi); } } + + // Study the PDG origin of particles and their effect on the purity score + template + void Fill(const T& track, int pdgCode, bool passed) + { + double phi = track.phi() * 180 / TMath::Pi(); + std::get>(p_pdg_den)->Fill(track.p(), pdgCode); + std::get>(pt_pdg_den)->Fill(track.pt(), pdgCode); + std::get>(eta_pdg_den)->Fill(track.eta(), pdgCode); + std::get>(phi_pdg_den)->Fill(phi, pdgCode); + + if (passed) { + std::get>(p_pdg_num)->Fill(track.p(), pdgCode); + std::get>(pt_pdg_num)->Fill(track.pt(), pdgCode); + std::get>(eta_pdg_num)->Fill(track.eta(), pdgCode); + std::get>(phi_pdg_num)->Fill(phi, pdgCode); + } + } }; struct MatchRankingHistos { @@ -376,29 +533,32 @@ struct qaMatching { o2::framework::HistPtr histVsPt; o2::framework::HistPtr histVsMcParticleDz; o2::framework::HistPtr histVsMftTrackMult; + o2::framework::HistPtr histVsMatchAttempts; o2::framework::HistPtr histVsMftTrackType; o2::framework::HistPtr histVsDeltaChi2; o2::framework::HistPtr histVsProdRanking; - MatchRankingHistos(std::string histName, std::string histTitle, HistogramRegistry* registry) + MatchRankingHistos(std::string histName, std::string histTitle, HistogramRegistry* registry, int mftMultMax, int numCandidates) { AxisSpec pAxis = {100, 0, 100, "p (GeV/c)"}; AxisSpec ptAxis = {100, 0, 10, "p_{T} (GeV/c)"}; - AxisSpec dzAxis = {100, 0, 50, "#Deltaz (cm)"}; - AxisSpec trackMultAxis = {100, 0, 1000, "MFT track mult."}; + AxisSpec dzAxis = {100, -1, 4, "#Deltaz (cm)"}; + AxisSpec trackMultAxis = {static_cast(mftMultMax) / 10, 0, static_cast(mftMultMax), "MFT track mult."}; + AxisSpec matchAttemptsAxis = {static_cast(mftMultMax) / 10, 0, static_cast(mftMultMax), "match attempts"}; AxisSpec trackTypeAxis = {2, 0, 2, "MFT track type"}; int matchTypeMax = static_cast(kMatchTypeUndefined); AxisSpec matchTypeAxis = {matchTypeMax, 0, static_cast(matchTypeMax), "match type"}; AxisSpec dchi2Axis = {100, 0, 100, "#Delta#chi^{2}"}; AxisSpec dqAxis = {3, -1.5, 1.5, "MFT #DeltaQ"}; - AxisSpec indexAxis = {6, 0, 6, "ranking index"}; - AxisSpec indexProdAxis = {6, 0, 6, "ranking index (production)"}; + AxisSpec indexAxis = {numCandidates + 1, 0, static_cast(numCandidates + 1), "ranking index"}; + AxisSpec indexProdAxis = {numCandidates + 1, 0, static_cast(numCandidates + 1), "ranking index (production)"}; hist = registry->add(histName.c_str(), histTitle.c_str(), {HistType::kTH1F, {indexAxis}}); histVsP = registry->add((histName + "VsP").c_str(), (histTitle + " vs. p").c_str(), {HistType::kTH2F, {pAxis, indexAxis}}); histVsPt = registry->add((histName + "VsPt").c_str(), (histTitle + " vs. p_{T}").c_str(), {HistType::kTH2F, {ptAxis, indexAxis}}); histVsMcParticleDz = registry->add((histName + "VsMcParticleDz").c_str(), (histTitle + " vs. MC particle #Deltaz").c_str(), {HistType::kTH2F, {dzAxis, indexAxis}}); histVsMftTrackMult = registry->add((histName + "VsMftTrackMult").c_str(), (histTitle + " vs. MFT track multiplicity").c_str(), {HistType::kTH2F, {trackMultAxis, indexAxis}}); + histVsMatchAttempts = registry->add((histName + "VsMatchAttempts").c_str(), (histTitle + " vs. MFT track multiplicity").c_str(), {HistType::kTH2F, {matchAttemptsAxis, indexAxis}}); histVsMftTrackType = registry->add((histName + "VsMftTrackType").c_str(), (histTitle + " vs. MFT track type").c_str(), {HistType::kTH2F, {trackTypeAxis, indexAxis}}); std::get>(histVsMftTrackType)->GetXaxis()->SetBinLabel(1, "Kalman"); std::get>(histVsMftTrackType)->GetXaxis()->SetBinLabel(2, "CA"); @@ -458,11 +618,14 @@ struct qaMatching { HistogramRegistry* registry; MatchingPlotter(std::string path, - HistogramRegistry* reg) - : fMatchingPurityPlotter(path + "matching-purity/", "Matching purity", *reg), - fPairingEfficiencyPlotter(path + "pairing-efficiency/", "Pairing efficiency", *reg), - fMatchingEfficiencyPlotter(path + "matching-efficiency/", "Matching efficiency", *reg), - fFakeMatchingEfficiencyPlotter(path + "fake-matching-efficiency/", "Fake matching efficiency", *reg) + HistogramRegistry* reg, + bool createPdgMomHistograms, + int mftMultMax, + int numCandidates) + : fMatchingPurityPlotter(path + "matching-purity/", "Matching purity", *reg, createPdgMomHistograms), + fPairingEfficiencyPlotter(path + "pairing-efficiency/", "Pairing efficiency", *reg, createPdgMomHistograms), + fMatchingEfficiencyPlotter(path + "matching-efficiency/", "Matching efficiency", *reg, createPdgMomHistograms), + fFakeMatchingEfficiencyPlotter(path + "fake-matching-efficiency/", "Fake matching efficiency", *reg, createPdgMomHistograms) { registry = reg; AxisSpec pAxis = {100, 0, 100, "p (GeV/c)"}; @@ -473,10 +636,10 @@ struct qaMatching { std::string histName = path + "matchRanking"; std::string histTitle = "True match ranking"; - fMatchRanking = std::make_unique(path + "matchRanking", "True match ranking", registry); - fMatchRankingGoodMCH = std::make_unique(path + "matchRankingGoodMCH", "True match ranking (good MCH tracks)", registry); - fMatchRankingPaired = std::make_unique(path + "matchRankingPaired", "True match ranking (paired MCH tracks)", registry); - fMatchRankingPairedGoodMCH = std::make_unique(path + "matchRankingPairedGoodMCH", "True match ranking (good paired MCH tracks)", registry); + fMatchRanking = std::make_unique(path + "matchRanking", "True match ranking", registry, mftMultMax, numCandidates); + fMatchRankingGoodMCH = std::make_unique(path + "matchRankingGoodMCH", "True match ranking (good MCH tracks)", registry, mftMultMax, numCandidates); + fMatchRankingPaired = std::make_unique(path + "matchRankingPaired", "True match ranking (paired MCH tracks)", registry, mftMultMax, numCandidates); + fMatchRankingPairedGoodMCH = std::make_unique(path + "matchRankingPairedGoodMCH", "True match ranking (good paired MCH tracks)", registry, mftMultMax, numCandidates); //- AxisSpec missedMatchAxis = {5, 0, 5, ""}; @@ -688,19 +851,19 @@ struct qaMatching { registry.add((histPath + "selectedMCHTracksAtMFTTrue").c_str(), "Selected MCH tracks position at MFT end - true", {HistType::kTH2F, {trackPositionXAtMFTAxis, trackPositionYAtMFTAxis}}); registry.add((histPath + "selectedMCHTracksAtMFTFake").c_str(), "Selected MCH tracks position at MFT end - fake", {HistType::kTH2F, {trackPositionXAtMFTAxis, trackPositionYAtMFTAxis}}); - fChi2MatchingPlotter = std::make_unique(histPath + "Prod/", ®istryMatching); + fChi2MatchingPlotter = std::make_unique(histPath + "Prod/", ®istryMatching, fConfigQAs.fCreatePdgMomHistograms, fMftTrackMultiplicityMax, fNCandidatesMax); int registryIndex = 0; for (const auto& [label, func] : matchingChi2Functions) { - fMatchingPlotters[label] = std::make_unique(histPath + label + "/", registryMatchingVec[registryIndex]); + fMatchingPlotters[label] = std::make_unique(histPath + label + "/", registryMatchingVec[registryIndex], fConfigQAs.fCreatePdgMomHistograms, fMftTrackMultiplicityMax, fNCandidatesMax); registryIndex += 1; } for (const auto& [label, response] : matchingMlResponses) { - fMatchingPlotters[label] = std::make_unique(histPath + label + "/", (registryMatchingVec[registryIndex])); + fMatchingPlotters[label] = std::make_unique(histPath + label + "/", (registryMatchingVec[registryIndex]), fConfigQAs.fCreatePdgMomHistograms, fMftTrackMultiplicityMax, fNCandidatesMax); registryIndex += 1; } - fTaggedMuonsMatchingPlotter = std::make_unique(histPath + "Tagged/", ®istryMatching); - fSelectedMuonsMatchingPlotter = std::make_unique(histPath + "Selected/", ®istryMatching); + fTaggedMuonsMatchingPlotter = std::make_unique(histPath + "Tagged/", ®istryMatching, fConfigQAs.fCreatePdgMomHistograms, fMftTrackMultiplicityMax, fNCandidatesMax); + fSelectedMuonsMatchingPlotter = std::make_unique(histPath + "Selected/", ®istryMatching, fConfigQAs.fCreatePdgMomHistograms, fMftTrackMultiplicityMax, fNCandidatesMax); } void CreateDimuonHistos() @@ -859,11 +1022,11 @@ struct qaMatching { // Matching functions InitMatchingFunctions(); for (size_t funcId = 0; funcId < sChi2FunctionsNum; funcId++) { - auto label = fConfigChi2MatchingOptions.fFunctionLabel[funcId].value; - auto funcName = fConfigChi2MatchingOptions.fFunctionName[funcId].value; - auto scoreMin = fConfigChi2MatchingOptions.fMatchingScoreCut[funcId].value; - auto matchingPlaneZ = fConfigChi2MatchingOptions.fMatchingPlaneZ[funcId].value; - auto extrapMethod = fConfigChi2MatchingOptions.fMatchingExtrapMethod[funcId].value; + auto label = fConfigChi2MatchingOptions.fFunctionLabel[funcId]->value; + auto funcName = fConfigChi2MatchingOptions.fFunctionName[funcId]->value; + auto scoreMin = fConfigChi2MatchingOptions.fMatchingScoreCut[funcId]->value; + auto matchingPlaneZ = fConfigChi2MatchingOptions.fMatchingPlaneZ[funcId]->value; + auto extrapMethod = fConfigChi2MatchingOptions.fMatchingExtrapMethod[funcId]->value; if (label == "" || funcName == "") break; @@ -883,20 +1046,20 @@ struct qaMatching { o2::framework::LabeledArray mycutsMl(cutValues.data(), 1, 1, std::vector{"pT bin 0"}, std::vector{"score"}); for (size_t modelId = 0; modelId < sMLModelsNum; modelId++) { - auto label = fConfigMlOptions.fModelLabel[modelId].value; - auto modelPaths = fConfigMlOptions.fModelPathsCCDB[modelId].value; - auto inputFeatures = fConfigMlOptions.fInputFeatures[modelId].value; - auto modelNames = fConfigMlOptions.fModelNames[modelId].value; - auto scoreMin = fConfigMlOptions.fMatchingScoreCut[modelId].value; - auto matchingPlaneZ = fConfigMlOptions.fMatchingPlaneZ[modelId].value; - auto extrapMethod = fConfigMlOptions.fMatchingExtrapMethod[modelId].value; - - if (label == "" || modelPaths.empty() || inputFeatures.empty() || modelNames.empty()) + auto label = fConfigMlOptions.fModelLabel[modelId]->value; + auto modelPath = fConfigMlOptions.fModelPathCCDB[modelId]->value; + auto inputFeatures = fConfigMlOptions.fInputFeatures[modelId]->value; + auto modelName = fConfigMlOptions.fModelName[modelId]->value; + auto scoreMin = fConfigMlOptions.fMatchingScoreCut[modelId]->value; + auto matchingPlaneZ = fConfigMlOptions.fMatchingPlaneZ[modelId]->value; + auto extrapMethod = fConfigMlOptions.fMatchingExtrapMethod[modelId]->value; + + if (label == "" || modelPath == "" || inputFeatures == "" || modelName == "") break; matchingMlResponses[label].configure(binsPtMl, mycutsMl, cutDirMl, 1); - matchingMlResponses[label].setModelPathsCCDB(modelNames, fCCDBApi, modelPaths, fConfigCCDB.fConfigNoLaterThan.value); - matchingMlResponses[label].cacheInputFeaturesIndices(inputFeatures); + matchingMlResponses[label].setModelPathsCCDB(std::vector{modelName}, fCCDBApi, std::vector{modelPath}, fConfigCCDB.fConfigNoLaterThan.value); + matchingMlResponses[label].cacheInputFeaturesIndices(std::vector{inputFeatures}); matchingMlResponses[label].init(); matchingScoreCuts[label] = scoreMin; @@ -908,7 +1071,7 @@ struct qaMatching { AxisSpec trackTypeAxis = {static_cast(nTrackTypes), 0.0, static_cast(nTrackTypes), "track type"}; registry.add("nTracksPerType", "Number of tracks per type", {HistType::kTH1F, {trackTypeAxis}}); - AxisSpec tracksMultiplicityAxis = {10000, 0, 10000, "tracks multiplicity"}; + AxisSpec tracksMultiplicityAxis = {fMftTrackMultiplicityMax, 0, static_cast(fMftTrackMultiplicityMax), "tracks multiplicity"}; registry.add("tracksMultiplicityMFT", "MFT tracks multiplicity", {HistType::kTH1F, {tracksMultiplicityAxis}}); registry.add("tracksMultiplicityMCH", "MCH tracks multiplicity", {HistType::kTH1F, {tracksMultiplicityAxis}}); @@ -1688,6 +1851,41 @@ struct qaMatching { return dimuon.M(); } + template + int GetMftMchMatchAttempts(EVT const& collisions, + BC const& bcs, + TMUON const& mchTrack, + TMFTS const& mftTracks) + { + if (!mchTrack.has_collision()) { + return 0; + } + const auto& collMch = collisions.rawIteratorAt(mchTrack.collisionId()); + const auto& bcMch = bcs.rawIteratorAt(collMch.bcId()); + + int attempts{0}; + for (const auto& mftTrack : mftTracks) { + if (!mftTrack.has_collision()) { + continue; + } + + const auto& collMft = collisions.rawIteratorAt(mftTrack.collisionId()); + const auto& bcMft = bcs.rawIteratorAt(collMft.bcId()); + + int64_t deltaBc = static_cast(bcMft.globalBC()) - static_cast(bcMch.globalBC()); + double deltaBcNS = o2::constants::lhc::LHCBunchSpacingNS * deltaBc; + double deltaTrackTime = mftTrack.trackTime() - mchTrack.trackTime() + deltaBcNS; + double trackTimeResTot = mftTrack.trackTimeRes() + mchTrack.trackTimeRes(); + + if (std::fabs(deltaTrackTime) > trackTimeResTot) { + continue; + } + attempts += 1; + } + + return attempts; + } + template void FillCollisions(EVT const& collisions, BC const& bcs, @@ -1702,6 +1900,9 @@ struct qaMatching { collisionIds.push_back(collision.globalIndex()); } + if (collisionIds.empty()) + return; + for (size_t cid = 1; cid < collisionIds.size() - 1; cid++) { const auto& collision = collisions.rawIteratorAt(collisionIds[cid]); int64_t collisionIndex = collision.globalIndex(); @@ -1766,6 +1967,7 @@ struct qaMatching { matchScore, matchChi2, -1, + 0, kMatchTypeUndefined}); } else { collisionInfo.matchingCandidates[mchTrackIndex].emplace_back(MatchingCandidate{ @@ -1779,6 +1981,7 @@ struct qaMatching { matchScore, matchChi2, -1, + 0, kMatchTypeUndefined}); } } @@ -1813,6 +2016,8 @@ struct qaMatching { for (auto& [mchIndex, globalTracksVector] : collisionInfo.matchingCandidates) { std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); + const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); + auto mftMchMatchAttempts = GetMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); int ranking = 1; for (auto& candidate : globalTracksVector) { const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); @@ -1820,6 +2025,7 @@ struct qaMatching { candidate.matchRanking = ranking; candidate.matchRankingProd = ranking; candidate.matchType = GetMatchType(muonTrack, muonTracks, mftTracks, collisionInfo.matchablePairs, ranking); + candidate.mftMchMatchAttempts = mftMchMatchAttempts; ranking += 1; } } @@ -1878,11 +2084,14 @@ struct qaMatching { mcParticleDz = collision.posZ() - mchMcParticle.vz(); } + int matchAttempts = globalTracksVector[0].mftMchMatchAttempts; + std::get>(plotter->fMatchRanking->hist)->Fill(trueMatchIndex); std::get>(plotter->fMatchRanking->histVsP)->Fill(mchMom, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRanking->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRanking->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -1894,6 +2103,7 @@ struct qaMatching { std::get>(plotter->fMatchRankingGoodMCH->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRankingGoodMCH->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRankingGoodMCH->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -1906,6 +2116,7 @@ struct qaMatching { std::get>(plotter->fMatchRankingPaired->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRankingPaired->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRankingPaired->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -1918,6 +2129,7 @@ struct qaMatching { std::get>(plotter->fMatchRankingPairedGoodMCH->histVsPt)->Fill(mchPt, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMcParticleDz)->Fill(mcParticleDz, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMftTrackMult)->Fill(mftTrackMult, trueMatchIndex); + std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMatchAttempts)->Fill(matchAttempts, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsMftTrackType)->Fill(mftTrackType, trueMatchIndex); std::get>(plotter->fMatchRankingPairedGoodMCH->histVsProdRanking)->Fill(trueMatchIndexProd, trueMatchIndex); if (dchi2 >= 0) @@ -2066,10 +2278,26 @@ struct qaMatching { // check if the matching candidate is a true one bool isTrueMatch = IsTrueGlobalMatching(muonTrack, matchablePairs); - if (verbose) + // ---- MC ancestry ---- + auto motherParticles = GetMotherParticles(muonTrack); + int motherPDG = 0; + if (motherParticles.size() > 1) { + motherPDG = motherParticles[1].first; + } + + if (verbose) { std::cout << std::format(" MCH track #{} -> Muon track #{}, isTrueMatch={}", mchIndex, globalTracksVector[0].globalTrackId, isTrueMatch) << std::endl; + std::cout << " MC ancestry (pdg): "; + for (auto const& [pdg, idx] : motherParticles) { + std::cout << "(" << pdg << ") "; + } + std::cout << std::endl; + } // fill matching purity plots plotter->fMatchingPurityPlotter.Fill(mchTrack, isTrueMatch); + if (fConfigQAs.fCreatePdgMomHistograms) { + plotter->fMatchingPurityPlotter.Fill(mchTrack, motherPDG, isTrueMatch); + } } // ==================================== @@ -2105,10 +2333,34 @@ struct qaMatching { } } + // ---- MC ancestry ---- + auto motherParticles = GetMotherParticles(mchTrack); + int motherPDG = 0; + if (motherParticles.size() > 1) { + motherPDG = motherParticles[1].first; + } + + if (verbose) { + std::cout << " MC ancestry (pdg): "; + for (auto const& [pdg, idx] : motherParticles) { + std::cout << "(" << pdg << ") "; + } + std::cout << std::endl; + } + // fill matching efficiency plots plotter->fPairingEfficiencyPlotter.Fill(mchTrack, goodMatchFound); + if (fConfigQAs.fCreatePdgMomHistograms) { + plotter->fPairingEfficiencyPlotter.Fill(mchTrack, motherPDG, goodMatchFound); + } plotter->fMatchingEfficiencyPlotter.Fill(mchTrack, (goodMatchFound && isTrueMatch)); + if (fConfigQAs.fCreatePdgMomHistograms) { + plotter->fMatchingEfficiencyPlotter.Fill(mchTrack, motherPDG, (goodMatchFound && isTrueMatch)); + } plotter->fFakeMatchingEfficiencyPlotter.Fill(mchTrack, (goodMatchFound && !isTrueMatch)); + if (fConfigQAs.fCreatePdgMomHistograms) { + plotter->fFakeMatchingEfficiencyPlotter.Fill(mchTrack, motherPDG, (goodMatchFound && !isTrueMatch)); + } } } @@ -2199,14 +2451,16 @@ struct qaMatching { } } - template + template void RunChi2Matching(C const& collisions, + BC const& bcs, TMUON const& muonTracks, - TMFT const& /*mftTracks*/, + TMFT const& mftTracks, CMFT const& mftCovs, std::string funcName, float matchingPlaneZ, int extrapMethod, + const std::vector>& matchablePairs, const MatchingCandidates& matchingCandidates, MatchingCandidates& newMatchingCandidates) { @@ -2296,15 +2550,29 @@ struct qaMatching { for (auto& [mchIndex, globalTracksVector] : newMatchingCandidates) { std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); + + const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); + auto mftMchMatchAttempts = GetMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); + int ranking = 1; + for (auto& candidate : globalTracksVector) { + const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); + + candidate.matchRanking = ranking; + candidate.matchType = GetMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + candidate.mftMchMatchAttempts = mftMchMatchAttempts; + ranking += 1; + } } } - template + template void RunChi2Matching(C const& collisions, + BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, CMFT const& mftCovs, std::string label, + const std::vector>& matchablePairs, const MatchingCandidates& matchingCandidates, MatchingCandidates& newMatchingCandidates) { @@ -2328,15 +2596,17 @@ struct qaMatching { auto matchingPlaneZ = matchingPlanesZ[label]; auto extrapMethod = matchingExtrapMethod[label]; - RunChi2Matching(collisions, muonTracks, mftTracks, mftCovs, funcName, matchingPlaneZ, extrapMethod, matchingCandidates, newMatchingCandidates); + RunChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, funcName, matchingPlaneZ, extrapMethod, matchablePairs, matchingCandidates, newMatchingCandidates); } - template + template void RunMLMatching(C const& collisions, + BC const& bcs, TMUON const& muonTracks, - TMFT const& /*mftTracks*/, + TMFT const& mftTracks, CMFT const& mftCovs, std::string label, + const std::vector>& matchablePairs, const MatchingCandidates& matchingCandidates, MatchingCandidates& newMatchingCandidates) { @@ -2425,12 +2695,25 @@ struct qaMatching { for (auto& [mchIndex, globalTracksVector] : newMatchingCandidates) { std::sort(globalTracksVector.begin(), globalTracksVector.end(), compareMatchingScore); + + const auto& mchTrack = muonTracks.rawIteratorAt(mchIndex); + auto mftMchMatchAttempts = GetMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks); + int ranking = 1; + for (auto& candidate : globalTracksVector) { + const auto& muonTrack = muonTracks.rawIteratorAt(candidate.globalTrackId); + + candidate.matchRanking = ranking; + candidate.matchType = GetMatchType(muonTrack, muonTracks, mftTracks, matchablePairs, ranking); + candidate.mftMchMatchAttempts = mftMchMatchAttempts; + ranking += 1; + } } } - template + template void ProcessCollisionMC(const CollisionInfo& collisionInfo, C const& collisions, + BC const& bcs, TMUON const& muonTracks, TMFT const& mftTracks, CMFT const& mftCovs) @@ -2444,7 +2727,7 @@ struct qaMatching { FillMatchingPlotsMC(collision, collisionInfo, muonTracks, mftTracks, collisionInfo.matchingCandidates, collisionInfo.matchingCandidates, collisionInfo.matchablePairs, fMatchingChi2ScoreMftMchLow, fChi2MatchingPlotter.get(), false); for (auto& [label, func] : matchingChi2Functions) { MatchingCandidates matchingCandidates; - RunChi2Matching(collisions, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchingCandidates, matchingCandidates); + RunChi2Matching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); auto* plotter = fMatchingPlotters.at(label).get(); double matchingScoreCut = matchingScoreCuts.at(label); @@ -2455,7 +2738,7 @@ struct qaMatching { // ML-based matching analysis for (auto& [label, mlResponse] : matchingMlResponses) { MatchingCandidates matchingCandidates; - RunMLMatching(collisions, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchingCandidates, matchingCandidates); + RunMLMatching(collisions, bcs, muonTracks, mftTracks, mftCovs, label, collisionInfo.matchablePairs, collisionInfo.matchingCandidates, matchingCandidates); auto* plotter = fMatchingPlotters.at(label).get(); double matchingScoreCut = matchingScoreCuts.at(label); @@ -2535,11 +2818,11 @@ struct qaMatching { } for (auto const& [collisionIndex, collisionInfo] : fCollisionInfos) { - ProcessCollisionMC(collisionInfo, collisions, muonTracks, mftTracks, mftCovs); + ProcessCollisionMC(collisionInfo, collisions, bcs, muonTracks, mftTracks, mftCovs); } } - PROCESS_SWITCH(qaMatching, processQAMC, "process qa MC", true); + PROCESS_SWITCH(qaMatching, processQAMC, "processQAMC", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGDQ/Tasks/quarkoniaToHyperons.cxx b/PWGDQ/Tasks/quarkoniaToHyperons.cxx index d4f5d394fbe..d4601569e86 100644 --- a/PWGDQ/Tasks/quarkoniaToHyperons.cxx +++ b/PWGDQ/Tasks/quarkoniaToHyperons.cxx @@ -32,37 +32,48 @@ #include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/strangenessBuilderHelper.h" #include "PWGUD/Core/SGSelector.h" -#include "Common/Core/TrackSelection.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Tools/ML/MlResponse.h" #include "Tools/ML/model.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include -#include +#include +#include #include #include +#include #include #include #include @@ -95,6 +106,8 @@ struct QuarkoniaToHyperons { // master analysis switches Configurable isPP{"isPP", true, "If running on pp collision, switch it on true"}; + Configurable doQA{"doQA", false, "Produce additional QA histograms?"}; + Configurable doPairPropagationToDCA{"doPairPropagationToDCA", false, "Propagate the hyperon pair to their DCA?"}; // for running over skimmed dataset Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "If running over skimmed data, switch it on true"}; @@ -126,6 +139,8 @@ struct QuarkoniaToHyperons { 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 maxZVtxPosition{"maxZVtxPosition", 10., "max Z vtx position (cm)"}; + Configurable buildK0sK0sPairs{"buildK0sK0sPairs", false, "Build K0s K0s from charmonia decay"}; Configurable buildLaLaBarPairs{"buildLaLaBarPairs", false, "Build Lambda antiLambda from charmonia decay"}; Configurable buildXiXiBarPairs{"buildXiXiBarPairs", false, "Build Xi antiXi from charmonia decay"}; @@ -288,12 +303,19 @@ struct QuarkoniaToHyperons { 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"}; + + // manual + Configurable useCustomMagField{"ccdbConfigurations.useCustomMagField", false, "Use custom magnetic field value"}; + Configurable useCustomRunNumber{"ccdbConfigurations.useCustomRunNumber", false, "Use custom run number"}; + Configurable customMagField{"ccdbConfigurations.customMagField", 5.0f, "Manually set magnetic field"}; + Configurable customRunNumber{"ccdbConfigurations.customRunNumber", 544122, "Manually set the run number "}; } ccdbConfigurations; Service ccdb; o2::ccdb::CcdbApi ccdbApi; int mRunNumber; std::map metadata; + float magField; Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; @@ -301,39 +323,56 @@ struct QuarkoniaToHyperons { static constexpr float defaultLifetimeCuts[1][2] = {{30., 20.}}; Configurable> lifetimecut{"lifetimecut", {defaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0S"}}, "lifetimecut"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.2f, 1.4f, 1.6f, 1.8f, 2.0f, 2.4f, 2.8f, 3.2f, 3.6f, 4.0f, 4.8f, 5.6f, 6.5f, 7.5f, 9.0f, 11.0f, 13.0f, 15.0f, 19.0f, 23.0f, 30.0f, 40.0f, 50.0f}, "pt axis for analysis"}; - ConfigurableAxis axisQuarkoniumMass{"axisQuarkoniumMass", {500, 2.600f, 4.000f}, "M (hyp. #bar{hyp.} ) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "Centrality"}; - ConfigurableAxis axisNch{"axisNch", {500, 0.0f, +5000.0f}, "Number of charged particles"}; - - ConfigurableAxis axisRawCentrality{"axisRawCentrality", {VARIABLE_WIDTH, 0.000f, 52.320f, 75.400f, 95.719f, 115.364f, 135.211f, 155.791f, 177.504f, 200.686f, 225.641f, 252.645f, 281.906f, 313.850f, 348.302f, 385.732f, 426.307f, 470.146f, 517.555f, 568.899f, 624.177f, 684.021f, 748.734f, 818.078f, 892.577f, 973.087f, 1058.789f, 1150.915f, 1249.319f, 1354.279f, 1465.979f, 1584.790f, 1710.778f, 1844.863f, 1985.746f, 2134.643f, 2291.610f, 2456.943f, 2630.653f, 2813.959f, 3006.631f, 3207.229f, 3417.641f, 3637.318f, 3865.785f, 4104.997f, 4354.938f, 4615.786f, 4885.335f, 5166.555f, 5458.021f, 5762.584f, 6077.881f, 6406.834f, 6746.435f, 7097.958f, 7462.579f, 7839.165f, 8231.629f, 8635.640f, 9052.000f, 9484.268f, 9929.111f, 10389.350f, 10862.059f, 11352.185f, 11856.823f, 12380.371f, 12920.401f, 13476.971f, 14053.087f, 14646.190f, 15258.426f, 15890.617f, 16544.433f, 17218.024f, 17913.465f, 18631.374f, 19374.983f, 20136.700f, 20927.783f, 21746.796f, 22590.880f, 23465.734f, 24372.274f, 25314.351f, 26290.488f, 27300.899f, 28347.512f, 29436.133f, 30567.840f, 31746.818f, 32982.664f, 34276.329f, 35624.859f, 37042.588f, 38546.609f, 40139.742f, 41837.980f, 43679.429f, 45892.130f, 400000.000f}, "raw centrality signal"}; // for QA - - ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "Occupancy"}; - - // topological variable QA axes - ConfigurableAxis axisDCAtoPV{"axisDCAtoPV", {20, 0.0f, 1.0f}, "DCA (cm)"}; - ConfigurableAxis axisDCAdau{"axisDCAdau", {20, 0.0f, 2.0f}, "DCA (cm)"}; - ConfigurableAxis axisDCAV0ToPV{"axisDCAV0ToPV", {20, 0.0f, 2.0f}, "DCA (cm)"}; - ConfigurableAxis axisPointingAngle{"axisPointingAngle", {20, 0.0f, 2.0f}, "pointing angle (rad)"}; - ConfigurableAxis axisRadius{"axisRadius", {20, 0.0f, 60.0f}, "Decay radius (cm)"}; - ConfigurableAxis axisProperLifeTime{"axisV0ProperLifeTime", {100, 0.0f, 50.0f}, "ProperLifeTime 2D radius (cm)"}; - ConfigurableAxis axisMassWindow{"axisMassWindow", {40, -0.020f, 0.020f}, "Inv. mass - PDG mass (GeV/#it{c}^{2})"}; - ConfigurableAxis axisK0Mass{"axisK0Mass", {500, 0.400f, 0.600f}, "K0Short mass (GeV/#it{c}^{2})"}; - ConfigurableAxis axisLambdaMass{"axisLambdaMass", {500, 1.098f, 1.198f}, "Lambda mass (GeV/#it{c}^{2})"}; - ConfigurableAxis axisXiMass{"axisXiMass", {500, 1.318f, 1.370f}, "Xi mass (GeV/#it{c}^{2})"}; - ConfigurableAxis axisOmegaMass{"axisOmegaMass", {500, 1.670f, 1.675f}, "Omega mass (GeV/#it{c}^{2})"}; - ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {200, -10.0f, 10.0f}, "N sigma TPC"}; - - // 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"}; - - // Track quality axes - ConfigurableAxis axisTPCrows{"axisTPCrows", {160, 0.0f, 160.0f}, "N TPC rows"}; - ConfigurableAxis axisITSclus{"axisITSclus", {7, 0.0f, 7.0f}, "N ITS Clusters"}; - - // UPC axes - ConfigurableAxis axisSelGap{"axisSelGap", {4, -1.5, 2.5}, "Gap side"}; + struct : ConfigurableGroup { + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.2f, 1.4f, 1.6f, 1.8f, 2.0f, 2.4f, 2.8f, 3.2f, 3.6f, 4.0f, 4.8f, 5.6f, 6.5f, 7.5f, 9.0f, 11.0f, 13.0f, 15.0f, 19.0f, 23.0f, 30.0f, 40.0f, 50.0f}, "pt axis for analysis"}; + ConfigurableAxis axisQuarkoniumMass{"axisQuarkoniumMass", {500, 2.600f, 4.000f}, "M (hyp. #bar{hyp.} ) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "Centrality"}; + ConfigurableAxis axisNch{"axisNch", {500, 0.0f, +5000.0f}, "Number of charged particles"}; + + ConfigurableAxis axisRawCentrality{"axisRawCentrality", {VARIABLE_WIDTH, 0.000f, 52.320f, 75.400f, 95.719f, 115.364f, 135.211f, 155.791f, 177.504f, 200.686f, 225.641f, 252.645f, 281.906f, 313.850f, 348.302f, 385.732f, 426.307f, 470.146f, 517.555f, 568.899f, 624.177f, 684.021f, 748.734f, 818.078f, 892.577f, 973.087f, 1058.789f, 1150.915f, 1249.319f, 1354.279f, 1465.979f, 1584.790f, 1710.778f, 1844.863f, 1985.746f, 2134.643f, 2291.610f, 2456.943f, 2630.653f, 2813.959f, 3006.631f, 3207.229f, 3417.641f, 3637.318f, 3865.785f, 4104.997f, 4354.938f, 4615.786f, 4885.335f, 5166.555f, 5458.021f, 5762.584f, 6077.881f, 6406.834f, 6746.435f, 7097.958f, 7462.579f, 7839.165f, 8231.629f, 8635.640f, 9052.000f, 9484.268f, 9929.111f, 10389.350f, 10862.059f, 11352.185f, 11856.823f, 12380.371f, 12920.401f, 13476.971f, 14053.087f, 14646.190f, 15258.426f, 15890.617f, 16544.433f, 17218.024f, 17913.465f, 18631.374f, 19374.983f, 20136.700f, 20927.783f, 21746.796f, 22590.880f, 23465.734f, 24372.274f, 25314.351f, 26290.488f, 27300.899f, 28347.512f, 29436.133f, 30567.840f, 31746.818f, 32982.664f, 34276.329f, 35624.859f, 37042.588f, 38546.609f, 40139.742f, 41837.980f, 43679.429f, 45892.130f, 400000.000f}, "raw centrality signal"}; // for QA + + ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "Occupancy"}; + + // topological variable QA axes + ConfigurableAxis axisDCAtoPV{"axisDCAtoPV", {20, 0.0f, 1.0f}, "DCA (cm)"}; + ConfigurableAxis axisDCAdau{"axisDCAdau", {20, 0.0f, 2.0f}, "DCA (cm)"}; + ConfigurableAxis axisDCAV0ToPV{"axisDCAV0ToPV", {20, 0.0f, 2.0f}, "DCA (cm)"}; + ConfigurableAxis axisPointingAngle{"axisPointingAngle", {20, 0.0f, 2.0f}, "pointing angle (rad)"}; + ConfigurableAxis axisRadius{"axisRadius", {20, 0.0f, 60.0f}, "Decay radius (cm)"}; + ConfigurableAxis axisProperLifeTime{"axisV0ProperLifeTime", {100, 0.0f, 50.0f}, "ProperLifeTime 2D radius (cm)"}; + ConfigurableAxis axisMassWindow{"axisMassWindow", {40, -0.020f, 0.020f}, "Inv. mass - PDG mass (GeV/#it{c}^{2})"}; + ConfigurableAxis axisK0Mass{"axisK0Mass", {500, 0.400f, 0.600f}, "K0Short mass (GeV/#it{c}^{2})"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {500, 1.098f, 1.198f}, "Lambda mass (GeV/#it{c}^{2})"}; + ConfigurableAxis axisXiMass{"axisXiMass", {500, 1.318f, 1.370f}, "Xi mass (GeV/#it{c}^{2})"}; + ConfigurableAxis axisOmegaMass{"axisOmegaMass", {500, 1.670f, 1.675f}, "Omega mass (GeV/#it{c}^{2})"}; + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {200, -10.0f, 10.0f}, "N sigma TPC"}; + + // 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"}; + + // Track quality axes + ConfigurableAxis axisTPCrows{"axisTPCrows", {160, 0.0f, 160.0f}, "N TPC rows"}; + ConfigurableAxis axisITSclus{"axisITSclus", {7, 0.0f, 7.0f}, "N ITS Clusters"}; + + // UPC axes + ConfigurableAxis axisSelGap{"axisSelGap", {4, -1.5, 2.5}, "Gap side"}; + + ConfigurableAxis axisHypPairRadius3D{"axisHypPairRadius3D", {500, 0, 2}, "Hyperon pair 3D distance to PV (cm)"}; + ConfigurableAxis axisHypPairRadius2D{"axisHypPairRadius2D", {500, 0, 1}, "Hyperon pair XY distance to PV (cm)"}; + ConfigurableAxis axisHypPairZ{"axisHypPairZ", {500, -2, 2}, "Hyperon pair longitudinal distance to PV (cm)"}; + ConfigurableAxis axisDCAHypPair{"axisDCAHypPair", {500, 0, 2}, "DCA between the hyperon pair (cm)"}; + ConfigurableAxis axisHypPairCosPA{"axisHypPairCosPA", {500, 0, 1}, "Hyperon pair cosine of pointing angle"}; + ConfigurableAxis axisHypPairOpAngle{"axisHypPairOpAngle", {360, 0, o2::constants::math::TwoPI}, "Hyperon pair momentum opening angle (rad)"}; + ConfigurableAxis axisHypPairEta{"axisHypPairEta", {20, -2, 2}, "Hyperon pair pseudo-rapidity"}; + ConfigurableAxis axisHypPairPhi{"axisHypPairPhi", {180, 0.0f, constants::math::TwoPI}, "Hyperon pair azimuthal angle (rad)"}; + } axes; + + o2::base::MatLayerCylSet* lut; // material LUT for DCA fitter + o2::vertexing::DCAFitterN<2> fitter; + + // helper object + o2::pwglf::strangenessBuilderHelper straHelper; // PDG database Service pdgDB; @@ -498,19 +537,19 @@ struct QuarkoniaToHyperons { histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(15, "Above max occup."); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{100, 0.0f, +100.0f}}); - histos.add("hCentralityVsNch", "hCentralityVsNch", kTH2F, {axisCentrality, axisNch}); + histos.add("hCentralityVsNch", "hCentralityVsNch", kTH2F, {axes.axisCentrality, axes.axisNch}); - histos.add("hEventOccupancy", "hEventOccupancy", kTH1F, {axisOccupancy}); - histos.add("hCentralityVsOccupancy", "hCentralityVsOccupancy", kTH2F, {axisCentrality, axisOccupancy}); + histos.add("hEventOccupancy", "hEventOccupancy", kTH1F, {axes.axisOccupancy}); + histos.add("hCentralityVsOccupancy", "hCentralityVsOccupancy", kTH2F, {axes.axisCentrality, axes.axisOccupancy}); if (!isPP) { histos.add("hGapSide", "Gap side; Entries", kTH1F, {{5, -0.5, 4.5}}); - histos.add("hSelGapSide", "Selected gap side; Entries", kTH1F, {axisSelGap}); - histos.add("hEventCentralityVsSelGapSide", ";Centrality (%); Selected gap side", kTH2F, {{100, 0.0f, +100.0f}, axisSelGap}); + histos.add("hSelGapSide", "Selected gap side; Entries", kTH1F, {axes.axisSelGap}); + histos.add("hEventCentralityVsSelGapSide", ";Centrality (%); Selected gap side", kTH2F, {{100, 0.0f, +100.0f}, axes.axisSelGap}); } // for QA and test purposes - auto hRawCentrality = histos.add("hRawCentrality", "hRawCentrality", kTH1F, {axisRawCentrality}); + auto hRawCentrality = histos.add("hRawCentrality", "hRawCentrality", kTH1F, {axes.axisRawCentrality}); for (int ii = 1; ii < 101; ii++) { float value = 100.5f - static_cast(ii); @@ -519,220 +558,340 @@ struct QuarkoniaToHyperons { // histograms versus mass if (buildK0sK0sPairs) { - histos.add("K0sK0s/h3dMassK0sK0s", "h3dMassK0sK0s", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("K0sK0s/h3dMassK0sK0s", "h3dMassK0sK0s", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); if (!isPP) { // Non-UPC info - histos.add("K0sK0s/h3dMassK0sK0sHadronic", "h3dMassK0sK0sHadronic", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("K0sK0s/h3dMassK0sK0sHadronic", "h3dMassK0sK0sHadronic", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); // UPC info - histos.add("K0sK0s/h3dMassK0sK0sSGA", "h3dMassK0sK0sSGA", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dMassK0sK0sSGC", "h3dMassK0sK0sSGC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dMassK0sK0sDG", "h3dMassK0sK0sDG", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("K0sK0s/h3dMassK0sK0sSGA", "h3dMassK0sK0sSGA", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dMassK0sK0sSGC", "h3dMassK0sK0sSGC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dMassK0sK0sDG", "h3dMassK0sK0sDG", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); } - histos.add("K0sK0s/h2dNbrOfK0ShortVsCentrality", "h2dNbrOfK0ShortVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("K0sK0s/h2dNbrOfK0ShortVsCentrality", "h2dNbrOfK0ShortVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); // QA plot // Candidates after K0s selections - histos.add("K0sK0s/K0s/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("K0sK0s/K0s/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("K0sK0s/K0s/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axisDCAdau}); - histos.add("K0sK0s/K0s/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("K0sK0s/K0s/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("K0sK0s/K0s/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("K0sK0s/K0s/hV0DecayLength", "hDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("K0sK0s/K0s/hV0InvMassWindow", "hInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("K0sK0s/K0s/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisLambdaMass, axisK0Mass}); - histos.add("K0sK0s/K0s/h2dArmenteros", "h2dArmenteros", kTH2F, {axisAPAlpha, axisAPQt}); - histos.add("K0sK0s/K0s/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("K0sK0s/K0s/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("K0sK0s/K0s/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("K0sK0s/K0s/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("K0sK0s/K0s/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("K0sK0s/K0s/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("K0sK0s/K0s/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axes.axisDCAdau}); + histos.add("K0sK0s/K0s/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("K0sK0s/K0s/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("K0sK0s/K0s/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("K0sK0s/K0s/hV0DecayLength", "hDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("K0sK0s/K0s/hV0InvMassWindow", "hInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("K0sK0s/K0s/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisLambdaMass, axes.axisK0Mass}); + histos.add("K0sK0s/K0s/h2dArmenteros", "h2dArmenteros", kTH2F, {axes.axisAPAlpha, axes.axisAPQt}); + histos.add("K0sK0s/K0s/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("K0sK0s/K0s/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("K0sK0s/K0s/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("K0sK0s/K0s/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); if (doMCAssociation) { - histos.add("K0sK0s/h3dInvMassTrueEtaC1S", "h3dInvMassTrueEtaC1S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTrueJPsi", "h3dInvMassTrueJPsi", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTrueChiC0", "h3dInvMassTrueChiC0", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTrueChiC1", "h3dInvMassTrueChiC1", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTrueHC", "h3dInvMassTrueHC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTrueChiC2", "h3dInvMassTrueChiC2", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("K0sK0s/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueEtaC1S", "h3dInvMassTrueEtaC1S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueJPsi", "h3dInvMassTrueJPsi", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueChiC0", "h3dInvMassTrueChiC0", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueChiC1", "h3dInvMassTrueChiC1", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueHC", "h3dInvMassTrueHC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueChiC2", "h3dInvMassTrueChiC2", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("K0sK0s/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + } + if (doQA) { + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPosDCAToPV", "h3dMassK0sK0sVsPosDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsNegDCAToPV", "h3dMassK0sK0sVsNegDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsDCAV0Daughters", "h3dMassK0sK0sVsDCAV0Daughters", kTH3F, {axes.axisDCAdau, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsDCAV0ToPV", "h3dMassK0sK0sVsDCAV0ToPV", kTH3F, {axes.axisDCAV0ToPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsV0PointingAngle", "h3dMassK0sK0sVsV0PointingAngle", kTH3F, {axes.axisPointingAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsV0Radius", "h3dMassK0sK0sVsV0Radius", kTH3F, {axes.axisRadius, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsDecayLength", "h3dMassK0sK0sVsDecayLength", kTH3F, {axes.axisProperLifeTime, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsInvMassWindow", "h3dMassK0sK0sVsInvMassWindow", kTH3F, {axes.axisMassWindow, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPosTPCNsigma", "h3dMassK0sK0sVsPosTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsNegTPCNsigma", "h3dMassK0sK0sVsNegTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPosITSclusters", "h3dMassK0sK0sVsPosITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsNegITSclusters", "h3dMassK0sK0sVsNegITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPosNbrCrossedRows", "h3dMassK0sK0sVsPosNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsNegNbrCrossedRows", "h3dMassK0sK0sVsNegNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairRadius3D", "h3dMassK0sK0sVsPairRadius3D", kTH3F, {axes.axisHypPairRadius3D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairRadius2D", "h3dMassK0sK0sVsPairRadius2D", kTH3F, {axes.axisHypPairRadius2D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairZ", "h3dMassK0sK0sVsPairZ", kTH3F, {axes.axisHypPairZ, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsDCAPair", "h3dMassK0sK0sVsDCAPair", kTH3F, {axes.axisDCAHypPair, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairCosPA", "h3dMassK0sK0sVsPairCosPA", kTH3F, {axes.axisHypPairCosPA, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairOpAngle", "h3dMassK0sK0sVsPairOpAngle", kTH3F, {axes.axisHypPairOpAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairEta", "h3dMassK0sK0sVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dMassK0sK0sVsPairPhi", "h3dMassK0sK0sVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/K0sK0s/h3dDeltaEtaK0sK0sVsPairEta", "h3dDeltaEtaK0sK0sVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisHypPairEta}); + histos.add("QA/K0sK0s/h3dDeltaPhiK0sK0sVsPairPhi", "h3dDeltaPhiK0sK0sVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisHypPairPhi}); } } if (buildLaLaBarPairs) { - histos.add("LaLaBar/h3dMassLaLabar", "h3dMassLaLabar", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("LaLaBar/h3dMassLaLabar", "h3dMassLaLabar", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); if (!isPP) { // Non-UPC info - histos.add("LaLaBar/h3dMassLaLabarHadronic", "h3dMassLaLabarHadronic", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("LaLaBar/h3dMassLaLabarHadronic", "h3dMassLaLabarHadronic", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); // UPC info - histos.add("LaLaBar/h3dMassLaLabarSGA", "h3dMassLaLabarSGA", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dMassLaLabarSGC", "h3dMassLaLabarSGC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dMassLaLabarDG", "h3dMassLaLabarDG", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("LaLaBar/h3dMassLaLabarSGA", "h3dMassLaLabarSGA", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dMassLaLabarSGC", "h3dMassLaLabarSGC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dMassLaLabarDG", "h3dMassLaLabarDG", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); } - histos.add("LaLaBar/h2dNbrOfLambdaVsCentrality", "h2dNbrOfLambdaVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); - histos.add("LaLaBar/h2dNbrOfAntiLambdaVsCentrality", "h2dNbrOfAntiLambdaVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("LaLaBar/h2dNbrOfLambdaVsCentrality", "h2dNbrOfLambdaVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("LaLaBar/h2dNbrOfAntiLambdaVsCentrality", "h2dNbrOfAntiLambdaVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); // QA plot // Candidates after Lambda selections - histos.add("LaLaBar/Lambda/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("LaLaBar/Lambda/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("LaLaBar/Lambda/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axisDCAdau}); - histos.add("LaLaBar/Lambda/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("LaLaBar/Lambda/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("LaLaBar/Lambda/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("LaLaBar/Lambda/hV0DecayLength", "hDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("LaLaBar/Lambda/hV0InvMassWindow", "hInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("LaLaBar/Lambda/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisLambdaMass, axisK0Mass}); - histos.add("LaLaBar/Lambda/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("LaLaBar/Lambda/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("LaLaBar/Lambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("LaLaBar/Lambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("LaLaBar/Lambda/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("LaLaBar/Lambda/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("LaLaBar/Lambda/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axes.axisDCAdau}); + histos.add("LaLaBar/Lambda/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("LaLaBar/Lambda/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("LaLaBar/Lambda/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("LaLaBar/Lambda/hV0DecayLength", "hDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("LaLaBar/Lambda/hV0InvMassWindow", "hInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("LaLaBar/Lambda/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisLambdaMass, axes.axisK0Mass}); + histos.add("LaLaBar/Lambda/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("LaLaBar/Lambda/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("LaLaBar/Lambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("LaLaBar/Lambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); // Candidates after AntiLambda selections - histos.add("LaLaBar/AntiLambda/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("LaLaBar/AntiLambda/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("LaLaBar/AntiLambda/hDCAV0Daughters", "hDCADaughters", kTH1F, {axisDCAdau}); - histos.add("LaLaBar/AntiLambda/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("LaLaBar/AntiLambda/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("LaLaBar/AntiLambda/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("LaLaBar/AntiLambda/hV0DecayLength", "hDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("LaLaBar/AntiLambda/hV0InvMassWindow", "hInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("LaLaBar/AntiLambda/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisLambdaMass, axisK0Mass}); - histos.add("LaLaBar/AntiLambda/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("LaLaBar/AntiLambda/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("LaLaBar/AntiLambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("LaLaBar/AntiLambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("LaLaBar/AntiLambda/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("LaLaBar/AntiLambda/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("LaLaBar/AntiLambda/hDCAV0Daughters", "hDCADaughters", kTH1F, {axes.axisDCAdau}); + histos.add("LaLaBar/AntiLambda/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("LaLaBar/AntiLambda/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("LaLaBar/AntiLambda/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("LaLaBar/AntiLambda/hV0DecayLength", "hDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("LaLaBar/AntiLambda/hV0InvMassWindow", "hInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("LaLaBar/AntiLambda/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisLambdaMass, axes.axisK0Mass}); + histos.add("LaLaBar/AntiLambda/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("LaLaBar/AntiLambda/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("LaLaBar/AntiLambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("LaLaBar/AntiLambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); if (doMCAssociation) { - histos.add("LaLaBar/h3dInvMassTrueEtaC1S", "h3dInvMassTrueEtaC1S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTrueJPsi", "h3dInvMassTrueJPsi", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTrueChiC0", "h3dInvMassTrueChiC0", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTrueChiC1", "h3dInvMassTrueChiC1", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTrueHC", "h3dInvMassTrueHC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTrueChiC2", "h3dInvMassTrueChiC2", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("LaLaBar/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueEtaC1S", "h3dInvMassTrueEtaC1S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueJPsi", "h3dInvMassTrueJPsi", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueChiC0", "h3dInvMassTrueChiC0", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueChiC1", "h3dInvMassTrueChiC1", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueHC", "h3dInvMassTrueHC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueChiC2", "h3dInvMassTrueChiC2", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("LaLaBar/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + } + if (doQA) { + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPosDCAToPV", "h3dMassLaLaBarVsPosDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsNegDCAToPV", "h3dMassLaLaBarVsNegDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsDCAV0Daughters", "h3dMassLaLaBarVsDCAV0Daughters", kTH3F, {axes.axisDCAdau, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsDCAV0ToPV", "h3dMassLaLaBarVsDCAV0ToPV", kTH3F, {axes.axisDCAV0ToPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsV0PointingAngle", "h3dMassLaLaBarVsV0PointingAngle", kTH3F, {axes.axisPointingAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsV0Radius", "h3dMassLaLaBarVsV0Radius", kTH3F, {axes.axisRadius, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsDecayLength", "h3dMassLaLaBarVsDecayLength", kTH3F, {axes.axisProperLifeTime, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsInvMassWindow", "h3dMassLaLaBarVsInvMassWindow", kTH3F, {axes.axisMassWindow, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPosTPCNsigma", "h3dMassLaLaBarVsPosTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsNegTPCNsigma", "h3dMassLaLaBarVsNegTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPosITSclusters", "h3dMassLaLaBarVsPosITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsNegITSclusters", "h3dMassLaLaBarVsNegITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPosNbrCrossedRows", "h3dMassLaLaBarVsPosNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsNegNbrCrossedRows", "h3dMassLaLaBarVsNegNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairRadius3D", "h3dMassLaLaBarVsPairRadius3D", kTH3F, {axes.axisHypPairRadius3D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairRadius2D", "h3dMassLaLaBarVsPairRadius2D", kTH3F, {axes.axisHypPairRadius2D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairZ", "h3dMassLaLaBarVsPairZ", kTH3F, {axes.axisHypPairZ, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsDCAPair", "h3dMassLaLaBarVsDCAPair", kTH3F, {axes.axisDCAHypPair, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairCosPA", "h3dMassLaLaBarVsPairCosPA", kTH3F, {axes.axisHypPairCosPA, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairOpAngle", "h3dMassLaLaBarVsPairOpAngle", kTH3F, {axes.axisHypPairOpAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairEta", "h3dMassLaLaBarVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dMassLaLaBarVsPairPhi", "h3dMassLaLaBarVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/LaLaBar/h3dDeltaEtaLaLaBarVsPairEta", "h3dDeltaEtaLaLaBarVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisHypPairEta}); + histos.add("QA/LaLaBar/h3dDeltaPhiLaLaBarVsPairPhi", "h3dDeltaPhiLaLaBarVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisHypPairPhi}); } } if (buildXiXiBarPairs) { - histos.add("XiXiBar/h3dMassXiXibar", "h3dMassXiXibar", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("XiXiBar/h3dMassXiXibar", "h3dMassXiXibar", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); if (!isPP) { // Non-UPC info - histos.add("XiXiBar/h3dMassXiXibarHadronic", "h3dMassXiXibarHadronic", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("XiXiBar/h3dMassXiXibarHadronic", "h3dMassXiXibarHadronic", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); // UPC info - histos.add("XiXiBar/h3dMassXiXibarSGA", "h3dMassXiXibarSGA", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dMassXiXibarSGC", "h3dMassXiXibarSGC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dMassXiXibarDG", "h3dMassXiXibarDG", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("XiXiBar/h3dMassXiXibarSGA", "h3dMassXiXibarSGA", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dMassXiXibarSGC", "h3dMassXiXibarSGC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dMassXiXibarDG", "h3dMassXiXibarDG", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); } - histos.add("XiXiBar/h2dNbrOfXiVsCentrality", "h2dNbrOfXiVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); - histos.add("XiXiBar/h2dNbrOfAntiXiVsCentrality", "h2dNbrOfAntiXiVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("XiXiBar/h2dNbrOfXiVsCentrality", "h2dNbrOfXiVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("XiXiBar/h2dNbrOfAntiXiVsCentrality", "h2dNbrOfAntiXiVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); // QA plot // Candidates after Xi selections - histos.add("XiXiBar/Xi/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("XiXiBar/Xi/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("XiXiBar/Xi/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("XiXiBar/Xi/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axisDCAdau}); - histos.add("XiXiBar/Xi/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axisDCAdau}); - histos.add("XiXiBar/Xi/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("XiXiBar/Xi/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("XiXiBar/Xi/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("XiXiBar/Xi/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axisPointingAngle}); - histos.add("XiXiBar/Xi/hCascRadius", "hCascRadius", kTH1F, {axisRadius}); - histos.add("XiXiBar/Xi/hCascDecayLength", "hCascDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("XiXiBar/Xi/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axisMassWindow}); - histos.add("XiXiBar/Xi/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("XiXiBar/Xi/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisXiMass, axisOmegaMass}); - histos.add("XiXiBar/Xi/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("XiXiBar/Xi/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("XiXiBar/Xi/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("XiXiBar/Xi/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("XiXiBar/Xi/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("XiXiBar/Xi/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("XiXiBar/Xi/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("XiXiBar/Xi/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("XiXiBar/Xi/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("XiXiBar/Xi/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axes.axisDCAdau}); + histos.add("XiXiBar/Xi/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axes.axisDCAdau}); + histos.add("XiXiBar/Xi/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("XiXiBar/Xi/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("XiXiBar/Xi/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("XiXiBar/Xi/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("XiXiBar/Xi/hCascRadius", "hCascRadius", kTH1F, {axes.axisRadius}); + histos.add("XiXiBar/Xi/hCascDecayLength", "hCascDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("XiXiBar/Xi/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("XiXiBar/Xi/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("XiXiBar/Xi/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisXiMass, axes.axisOmegaMass}); + histos.add("XiXiBar/Xi/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("XiXiBar/Xi/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("XiXiBar/Xi/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("XiXiBar/Xi/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("XiXiBar/Xi/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("XiXiBar/Xi/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); // Candidates after AntiXi selections - histos.add("XiXiBar/AntiXi/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("XiXiBar/AntiXi/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("XiXiBar/AntiXi/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("XiXiBar/AntiXi/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axisDCAdau}); - histos.add("XiXiBar/AntiXi/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axisDCAdau}); - histos.add("XiXiBar/AntiXi/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("XiXiBar/AntiXi/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("XiXiBar/AntiXi/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("XiXiBar/AntiXi/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axisPointingAngle}); - histos.add("XiXiBar/AntiXi/hCascRadius", "hCascRadius", kTH1F, {axisRadius}); - histos.add("XiXiBar/AntiXi/hCascDecayLength", "hCascDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("XiXiBar/AntiXi/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axisMassWindow}); - histos.add("XiXiBar/AntiXi/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("XiXiBar/AntiXi/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisXiMass, axisOmegaMass}); - histos.add("XiXiBar/AntiXi/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("XiXiBar/AntiXi/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("XiXiBar/AntiXi/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("XiXiBar/AntiXi/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("XiXiBar/AntiXi/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("XiXiBar/AntiXi/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("XiXiBar/AntiXi/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("XiXiBar/AntiXi/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("XiXiBar/AntiXi/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("XiXiBar/AntiXi/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axes.axisDCAdau}); + histos.add("XiXiBar/AntiXi/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axes.axisDCAdau}); + histos.add("XiXiBar/AntiXi/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("XiXiBar/AntiXi/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("XiXiBar/AntiXi/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("XiXiBar/AntiXi/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("XiXiBar/AntiXi/hCascRadius", "hCascRadius", kTH1F, {axes.axisRadius}); + histos.add("XiXiBar/AntiXi/hCascDecayLength", "hCascDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("XiXiBar/AntiXi/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("XiXiBar/AntiXi/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("XiXiBar/AntiXi/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisXiMass, axes.axisOmegaMass}); + histos.add("XiXiBar/AntiXi/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("XiXiBar/AntiXi/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("XiXiBar/AntiXi/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("XiXiBar/AntiXi/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("XiXiBar/AntiXi/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("XiXiBar/AntiXi/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); if (doMCAssociation) { - histos.add("XiXiBar/h3dInvMassTrueEtaC1S", "h3dInvMassTrueEtaC1S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTrueJPsi", "h3dInvMassTrueJPsi", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTrueChiC0", "h3dInvMassTrueChiC0", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTrueChiC1", "h3dInvMassTrueChiC1", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTrueHC", "h3dInvMassTrueHC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTrueChiC2", "h3dInvMassTrueChiC2", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("XiXiBar/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueEtaC1S", "h3dInvMassTrueEtaC1S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueJPsi", "h3dInvMassTrueJPsi", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueChiC0", "h3dInvMassTrueChiC0", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueChiC1", "h3dInvMassTrueChiC1", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueHC", "h3dInvMassTrueHC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueChiC2", "h3dInvMassTrueChiC2", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("XiXiBar/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + } + if (doQA) { + histos.add("QA/XiXiBar/h3dMassXiXiBarVsBachDCAToPV", "h3dMassXiXiBarVsBachDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPosDCAToPV", "h3dMassXiXiBarVsPosDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsNegDCAToPV", "h3dMassXiXiBarVsNegDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsDCACascDaughters", "h3dMassXiXiBarVsDCACascDaughters", kTH3F, {axes.axisDCAdau, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsDCAV0Daughters", "h3dMassXiXiBarVsDCAV0Daughters", kTH3F, {axes.axisDCAdau, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsDCAV0ToPV", "h3dMassXiXiBarVsDCAV0ToPV", kTH3F, {axes.axisDCAV0ToPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsV0PointingAngle", "h3dMassXiXiBarVsV0PointingAngle", kTH3F, {axes.axisPointingAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsV0Radius", "h3dMassXiXiBarVsV0Radius", kTH3F, {axes.axisRadius, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsCascPointingAngle", "h3dMassXiXiBarVsCascPointingAngle", kTH3F, {axes.axisPointingAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsCascRadius", "h3dMassXiXiBarVsCascRadius", kTH3F, {axes.axisRadius, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsDecayLength", "h3dMassXiXiBarVsDecayLength", kTH3F, {axes.axisProperLifeTime, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsV0InvMassWindow", "h3dMassXiXiBarVsV0InvMassWindow", kTH3F, {axes.axisMassWindow, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsCascInvMassWindow", "h3dMassXiXiBarVsCascInvMassWindow", kTH3F, {axes.axisMassWindow, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsBachTPCNsigma", "h3dMassXiXiBarVsBachTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPosTPCNsigma", "h3dMassXiXiBarVsPosTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsNegTPCNsigma", "h3dMassXiXiBarVsNegTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsBachITSclusters", "h3dMassXiXiBarVsBachITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPosITSclusters", "h3dMassXiXiBarVsPosITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsNegITSclusters", "h3dMassXiXiBarVsNegITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsBachNbrCrossedRows", "h3dMassXiXiBarVsBachNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPosNbrCrossedRows", "h3dMassXiXiBarVsPosNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsNegNbrCrossedRows", "h3dMassXiXiBarVsNegNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairRadius3D", "h3dMassXiXiBarVsPairRadius3D", kTH3F, {axes.axisHypPairRadius3D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairRadius2D", "h3dMassXiXiBarVsPairRadius2D", kTH3F, {axes.axisHypPairRadius2D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairZ", "h3dMassXiXiBarVsPairZ", kTH3F, {axes.axisHypPairZ, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsDCAPair", "h3dMassXiXiBarVsDCAPair", kTH3F, {axes.axisDCAHypPair, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairCosPA", "h3dMassXiXiBarVsPairCosPA", kTH3F, {axes.axisHypPairCosPA, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairOpAngle", "h3dMassXiXiBarVsPairOpAngle", kTH3F, {axes.axisHypPairOpAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairEta", "h3dMassXiXiBarVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dMassXiXiBarVsPairPhi", "h3dMassXiXiBarVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/XiXiBar/h3dDeltaEtaXiXiBarVsPairEta", "h3dDeltaEtaXiXiBarVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisHypPairEta}); + histos.add("QA/XiXiBar/h3dDeltaPhiXiXiBarVsPairPhi", "h3dDeltaPhiXiXiBarVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisHypPairPhi}); } } if (buildOmOmBarPairs) { - histos.add("OmOmBar/h3dMassOmOmbar", "h3dMassOmOmbar", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("OmOmBar/h3dMassOmOmbar", "h3dMassOmOmbar", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); if (!isPP) { // Non-UPC info - histos.add("OmOmBar/h3dMassOmOmbarHadronic", "h3dMassOmOmbarHadronic", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("OmOmBar/h3dMassOmOmbarHadronic", "h3dMassOmOmbarHadronic", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); // UPC info - histos.add("OmOmBar/h3dMassOmOmbarSGA", "h3dMassOmOmbarSGA", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("OmOmBar/h3dMassOmOmbarSGC", "h3dMassOmOmbarSGC", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("OmOmBar/h3dMassOmOmbarDG", "h3dMassOmOmbarDG", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("OmOmBar/h3dMassOmOmbarSGA", "h3dMassOmOmbarSGA", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("OmOmBar/h3dMassOmOmbarSGC", "h3dMassOmOmbarSGC", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("OmOmBar/h3dMassOmOmbarDG", "h3dMassOmOmbarDG", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); } - histos.add("OmOmBar/h2dNbrOfOmegaVsCentrality", "h2dNbrOfOmegaVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); - histos.add("OmOmBar/h2dNbrOfAntiOmegaVsCentrality", "h2dNbrOfAntiOmegaVsCentrality", kTH2F, {axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("OmOmBar/h2dNbrOfOmegaVsCentrality", "h2dNbrOfOmegaVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("OmOmBar/h2dNbrOfAntiOmegaVsCentrality", "h2dNbrOfAntiOmegaVsCentrality", kTH2F, {axes.axisCentrality, {10, -0.5f, 9.5f}}); // QA plot // Candidates after Omega selections - histos.add("OmOmBar/Omega/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("OmOmBar/Omega/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("OmOmBar/Omega/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("OmOmBar/Omega/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axisDCAdau}); - histos.add("OmOmBar/Omega/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axisDCAdau}); - histos.add("OmOmBar/Omega/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("OmOmBar/Omega/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("OmOmBar/Omega/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("OmOmBar/Omega/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axisPointingAngle}); - histos.add("OmOmBar/Omega/hCascRadius", "hCascRadius", kTH1F, {axisRadius}); - histos.add("OmOmBar/Omega/hCascDecayLength", "hCascDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("OmOmBar/Omega/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axisMassWindow}); - histos.add("OmOmBar/Omega/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("OmOmBar/Omega/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisXiMass, axisOmegaMass}); - histos.add("OmOmBar/Omega/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("OmOmBar/Omega/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("OmOmBar/Omega/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("OmOmBar/Omega/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("OmOmBar/Omega/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("OmOmBar/Omega/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("OmOmBar/Omega/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("OmOmBar/Omega/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("OmOmBar/Omega/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("OmOmBar/Omega/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axes.axisDCAdau}); + histos.add("OmOmBar/Omega/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axes.axisDCAdau}); + histos.add("OmOmBar/Omega/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("OmOmBar/Omega/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("OmOmBar/Omega/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("OmOmBar/Omega/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("OmOmBar/Omega/hCascRadius", "hCascRadius", kTH1F, {axes.axisRadius}); + histos.add("OmOmBar/Omega/hCascDecayLength", "hCascDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("OmOmBar/Omega/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("OmOmBar/Omega/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("OmOmBar/Omega/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisXiMass, axes.axisOmegaMass}); + histos.add("OmOmBar/Omega/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("OmOmBar/Omega/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("OmOmBar/Omega/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("OmOmBar/Omega/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("OmOmBar/Omega/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("OmOmBar/Omega/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); // Candidates after AntiOmega selections - histos.add("OmOmBar/AntiOmega/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("OmOmBar/AntiOmega/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("OmOmBar/AntiOmega/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axisDCAtoPV}); - histos.add("OmOmBar/AntiOmega/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axisDCAdau}); - histos.add("OmOmBar/AntiOmega/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axisDCAdau}); - histos.add("OmOmBar/AntiOmega/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axisDCAV0ToPV}); - histos.add("OmOmBar/AntiOmega/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axisPointingAngle}); - histos.add("OmOmBar/AntiOmega/hV0Radius", "hV0Radius", kTH1F, {axisRadius}); - histos.add("OmOmBar/AntiOmega/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axisPointingAngle}); - histos.add("OmOmBar/AntiOmega/hCascRadius", "hCascRadius", kTH1F, {axisRadius}); - histos.add("OmOmBar/AntiOmega/hCascDecayLength", "hCascDecayLength", kTH1F, {axisProperLifeTime}); - histos.add("OmOmBar/AntiOmega/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axisMassWindow}); - histos.add("OmOmBar/AntiOmega/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axisMassWindow}); - histos.add("OmOmBar/AntiOmega/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axisXiMass, axisOmegaMass}); - histos.add("OmOmBar/AntiOmega/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("OmOmBar/AntiOmega/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("OmOmBar/AntiOmega/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axisNsigmaTPC}); - histos.add("OmOmBar/AntiOmega/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("OmOmBar/AntiOmega/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); - histos.add("OmOmBar/AntiOmega/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axisTPCrows, axisITSclus}); + histos.add("OmOmBar/AntiOmega/hBachDCAToPV", "hBachDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("OmOmBar/AntiOmega/hPosDCAToPV", "hPosDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("OmOmBar/AntiOmega/hNegDCAToPV", "hNegDCAToPV", kTH1F, {axes.axisDCAtoPV}); + histos.add("OmOmBar/AntiOmega/hDCACascDaughters", "hDCACascDaughters", kTH1F, {axes.axisDCAdau}); + histos.add("OmOmBar/AntiOmega/hDCAV0Daughters", "hDCAV0Daughters", kTH1F, {axes.axisDCAdau}); + histos.add("OmOmBar/AntiOmega/hDCAV0ToPV", "hDCAV0ToPV", kTH1F, {axes.axisDCAV0ToPV}); + histos.add("OmOmBar/AntiOmega/hV0PointingAngle", "hV0PointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("OmOmBar/AntiOmega/hV0Radius", "hV0Radius", kTH1F, {axes.axisRadius}); + histos.add("OmOmBar/AntiOmega/hCascPointingAngle", "hCascPointingAngle", kTH1F, {axes.axisPointingAngle}); + histos.add("OmOmBar/AntiOmega/hCascRadius", "hCascRadius", kTH1F, {axes.axisRadius}); + histos.add("OmOmBar/AntiOmega/hCascDecayLength", "hCascDecayLength", kTH1F, {axes.axisProperLifeTime}); + histos.add("OmOmBar/AntiOmega/hV0InvMassWindow", "hV0InvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("OmOmBar/AntiOmega/hCascInvMassWindow", "hCascInvMassWindow", kTH1F, {axes.axisMassWindow}); + histos.add("OmOmBar/AntiOmega/h2dCompetingMassRej", "h2dCompetingMassRej", kTH2F, {axes.axisXiMass, axes.axisOmegaMass}); + histos.add("OmOmBar/AntiOmega/hBachTPCNsigma", "hBachTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("OmOmBar/AntiOmega/hPosTPCNsigma", "hPosTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("OmOmBar/AntiOmega/hNegTPCNsigma", "hNegTPCNsigma", kTH1F, {axes.axisNsigmaTPC}); + histos.add("OmOmBar/AntiOmega/h2dBachelorITSvsTPCpts", "h2dBachelorITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("OmOmBar/AntiOmega/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); + histos.add("OmOmBar/AntiOmega/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2F, {axes.axisTPCrows, axes.axisITSclus}); if (doMCAssociation) { - histos.add("OmOmBar/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); - histos.add("OmOmBar/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axisCentrality, axisPt, axisQuarkoniumMass}); + histos.add("OmOmBar/h3dInvMassTrueEtaC2S", "h3dInvMassTrueEtaC2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("OmOmBar/h3dInvMassTruePsi2S", "h3dInvMassTruePsi2S", kTH3F, {axes.axisCentrality, axes.axisPt, axes.axisQuarkoniumMass}); + } + if (doQA) { + histos.add("QA/OmOmBar/h3dMassOmOmBarVsBachDCAToPV", "h3dMassOmOmBarVsBachDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPosDCAToPV", "h3dMassOmOmBarVsPosDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsNegDCAToPV", "h3dMassOmOmBarVsNegDCAToPV", kTH3F, {axes.axisDCAtoPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsDCACascDaughters", "h3dMassOmOmBarVsDCACascDaughters", kTH3F, {axes.axisDCAdau, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsDCAV0Daughters", "h3dMassOmOmBarVsDCAV0Daughters", kTH3F, {axes.axisDCAdau, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsDCAV0ToPV", "h3dMassOmOmBarVsDCAV0ToPV", kTH3F, {axes.axisDCAV0ToPV, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsV0PointingAngle", "h3dMassOmOmBarVsV0PointingAngle", kTH3F, {axes.axisPointingAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsV0Radius", "h3dMassOmOmBarVsV0Radius", kTH3F, {axes.axisRadius, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsCascPointingAngle", "h3dMassOmOmBarVsCascPointingAngle", kTH3F, {axes.axisPointingAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsCascRadius", "h3dMassOmOmBarVsCascRadius", kTH3F, {axes.axisRadius, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsDecayLength", "h3dMassOmOmBarVsDecayLength", kTH3F, {axes.axisProperLifeTime, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsV0InvMassWindow", "h3dMassOmOmBarVsV0InvMassWindow", kTH3F, {axes.axisMassWindow, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsCascInvMassWindow", "h3dMassOmOmBarVsCascInvMassWindow", kTH3F, {axes.axisMassWindow, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsBachTPCNsigma", "h3dMassOmOmBarVsBachTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPosTPCNsigma", "h3dMassOmOmBarVsPosTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsNegTPCNsigma", "h3dMassOmOmBarVsNegTPCNsigma", kTH3F, {axes.axisNsigmaTPC, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsBachITSclusters", "h3dMassOmOmBarVsBachITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPosITSclusters", "h3dMassOmOmBarVsPosITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsNegITSclusters", "h3dMassOmOmBarVsNegITSclusters", kTH3F, {axes.axisITSclus, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsBachNbrCrossedRows", "h3dMassOmOmBarVsBachNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPosNbrCrossedRows", "h3dMassOmOmBarVsPosNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsNegNbrCrossedRows", "h3dMassOmOmBarVsNegNbrCrossedRows", kTH3F, {axes.axisTPCrows, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairRadius3D", "h3dMassOmOmBarVsPairRadius3D", kTH3F, {axes.axisHypPairRadius3D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairRadius2D", "h3dMassOmOmBarVsPairRadius2D", kTH3F, {axes.axisHypPairRadius2D, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairZ", "h3dMassOmOmBarVsPairZ", kTH3F, {axes.axisHypPairZ, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsDCAPair", "h3dMassOmOmBarVsDCAPair", kTH3F, {axes.axisDCAHypPair, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairCosPA", "h3dMassOmOmBarVsPairCosPA", kTH3F, {axes.axisHypPairCosPA, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairOpAngle", "h3dMassOmOmBarVsPairOpAngle", kTH3F, {axes.axisHypPairOpAngle, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairEta", "h3dMassOmOmBarVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dMassOmOmBarVsPairPhi", "h3dMassOmOmBarVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisQuarkoniumMass}); + histos.add("QA/OmOmBar/h3dDeltaEtaOmOmBarVsPairEta", "h3dDeltaEtaOmOmBarVsPairEta", kTH3F, {axes.axisHypPairEta, axes.axisPt, axes.axisHypPairEta}); + histos.add("QA/OmOmBar/h3dDeltaPhiOmOmBarVsPairPhi", "h3dDeltaPhiOmOmBarVsPairPhi", kTH3F, {axes.axisHypPairPhi, axes.axisPt, axes.axisHypPairPhi}); } } @@ -740,6 +899,38 @@ struct QuarkoniaToHyperons { zorroSummary.setObject(zorro.getZorroSummary()); } + // standards hardcoded in builder ... + // ...but can be changed easily since fitter is public + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxDXYIni(4.0f); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + fitter.setWeightedFinalPCA(false); + // LUT has to be loaded later + lut = nullptr; + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrLUT); + + // mag field has to be set later + fitter.setBz(-999.9f); // will NOT make sense if not changed + + // set V0 parameters in the helper + straHelper.v0selections.minCrossedRows = v0Selections.minTPCrows; + straHelper.v0selections.dcanegtopv = std::min(v0Selections.dcapiontopv.value, v0Selections.dcaprotontopv.value); + straHelper.v0selections.dcapostopv = std::min(v0Selections.dcapiontopv.value, v0Selections.dcaprotontopv.value); + straHelper.v0selections.v0cospa = v0Selections.v0cospa; + straHelper.v0selections.dcav0dau = v0Selections.dcav0dau; + straHelper.v0selections.v0radius = v0Selections.v0radius; + straHelper.v0selections.maxDaughterEta = v0Selections.daughterEtaCut; + + ccdb->setURL(ccdbConfigurations.ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + // inspect histogram sizes, please histos.print(); } @@ -747,17 +938,58 @@ struct QuarkoniaToHyperons { template // TCollision should be of the type: soa::Join::iterator or so void initCCDB(TCollision const& collision) { - if (mRunNumber == collision.runNumber()) { + if (mRunNumber == collision.runNumber() || (ccdbConfigurations.useCustomRunNumber && mRunNumber == ccdbConfigurations.customRunNumber)) { return; } - mRunNumber = collision.runNumber(); - if (cfgSkimmedProcessing) { - ccdb->setURL(ccdbConfigurations.ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); + mRunNumber = ccdbConfigurations.useCustomRunNumber ? ccdbConfigurations.customRunNumber : collision.runNumber(); + + if (doPairPropagationToDCA) { + // In case override, don't proceed, please - no CCDB access required + if (ccdbConfigurations.useCustomMagField) { + magField = ccdbConfigurations.customMagField; + o2::parameters::GRPMagField grpmag; + if (fabs(magField) > 1e-5) { + grpmag.setL3Current(30000.f / (magField / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + } else { + o2::parameters::GRPObject* grpo = ccdb->getForRun(ccdbConfigurations.grpPath, mRunNumber); + o2::parameters::GRPMagField* grpmag = 0x0; + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + magField = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for run " << mRunNumber << " with magnetic field of " << magField << " kZG"; + } else { + grpmag = ccdb->getForRun(ccdbConfigurations.grpmagPath, mRunNumber); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField and " << ccdbConfigurations.grpPath << " of object GRPObject for run " << mRunNumber; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + magField = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for run " << mRunNumber << " with magnetic field of " << magField << " kZG"; + } + } + + // load matLUT for this timestamp + if (!lut) { + LOG(info) << "Loading material look-up table for timestamp: " << mRunNumber; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->template getForRun(ccdbConfigurations.lutPath.value, mRunNumber)); + straHelper.lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->template getForRun(ccdbConfigurations.lutPath.value, mRunNumber)); + } else { + LOG(info) << "Material look-up table already in place. Not reloading."; + } + LOG(info) << "Setting global propagator material propagation LUT"; + o2::base::Propagator::Instance()->setMatLUT(lut); + o2::base::Propagator::Instance()->setMatLUT(straHelper.lut); + + fitter.setBz(magField); + straHelper.fitter.setBz(magField); + } + if (cfgSkimmedProcessing) { zorro.initCCDB(ccdb.service, collision.runNumber(), collision.timestamp(), cfgSkimmedTrigger.value); zorro.populateHistRegistry(histos, collision.runNumber()); } @@ -817,6 +1049,159 @@ struct QuarkoniaToHyperons { LOG(info) << "ML Models loaded."; } + // Taken from https://github.com/AliceO2Group/O2Physics/blob/master/PWGLF/TableProducer/Strangeness/sigma0builder.cxx#L319 + // Thanks Gianni! + // ______________________________________________________ + // Struct to store V0Pair properties + struct PairTopoInfo { + float X = -999.f; + float Y = -999.f; + float Z = -999.f; + std::array hyperonMomentum = {0.0f, 0.0f, 0.0f}; + std::array antiHyperonMomentum = {0.0f, 0.0f, 0.0f}; + float DCADau = -999.f; + float CosPA = -1.f; + float OpAngle = -999.f; + float Eta() const + { + return RecoDecay::eta(std::array{hyperonMomentum[0] + antiHyperonMomentum[0], hyperonMomentum[1] + antiHyperonMomentum[1], hyperonMomentum[2] + antiHyperonMomentum[2]}); + } + float Phi() const + { + return RecoDecay::phi(std::array{hyperonMomentum[0] + antiHyperonMomentum[0], hyperonMomentum[1] + antiHyperonMomentum[1]}); + } + }; + + template + PairTopoInfo propagateV0PairToDCA(float pvX, float pvY, float pvZ, TV0 const& v01, TV0 const& v02) + { + PairTopoInfo pairInfo; + + // Positions + ROOT::Math::XYZVector v01position(v01.x(), v01.y(), v01.z()); + ROOT::Math::XYZVector v02position(v02.x(), v02.y(), v02.z()); + + // Momenta + ROOT::Math::XYZVector v01momentum(v01.px(), v01.py(), v01.pz()); + ROOT::Math::XYZVector v02momentum(v02.px(), v02.py(), v02.pz()); + + // Momenta (normalized) + ROOT::Math::XYZVector v01momentumNorm(v01.px() / v01.p(), v01.py() / v01.p(), v01.pz() / v01.p()); + ROOT::Math::XYZVector v02momentumNorm(v02.px() / v02.p(), v02.py() / v02.p(), v02.pz() / v02.p()); + + // DCADau calculation (using full momenta for precision) + ROOT::Math::XYZVector posdiff = v02position - v01position; + ROOT::Math::XYZVector cross = v01momentum.Cross(v02momentum); + + float d = 1.0f - TMath::Power(v01momentumNorm.Dot(v02momentumNorm), 2); + float t = posdiff.Dot(v01momentumNorm - v01momentumNorm.Dot(v02momentumNorm) * v02momentumNorm) / d; + float s = -posdiff.Dot(v02momentumNorm - v01momentumNorm.Dot(v02momentumNorm) * v01momentumNorm) / d; + + ROOT::Math::XYZVector pointOn1 = v01position + t * v01momentumNorm; + ROOT::Math::XYZVector pointOn2 = v02position + s * v02momentumNorm; + ROOT::Math::XYZVector PCA = 0.5 * (pointOn1 + pointOn2); + + pairInfo.hyperonMomentum[0] = v01.px(); + pairInfo.hyperonMomentum[1] = v01.py(); + pairInfo.hyperonMomentum[2] = v01.pz(); + pairInfo.antiHyperonMomentum[0] = v02.px(); + pairInfo.antiHyperonMomentum[1] = v02.py(); + pairInfo.antiHyperonMomentum[2] = v02.pz(); + + // Calculate properties and fill struct + pairInfo.DCADau = (cross.Mag2() > 0) ? std::abs(posdiff.Dot(cross)) / cross.R() : 999.f; + + pairInfo.CosPA = RecoDecay::cpa( + std::array{pvX, pvY, pvZ}, + std::array{PCA.X(), PCA.Y(), PCA.Z()}, + std::array{v01.px() + v02.px(), + v01.py() + v02.py(), + v01.pz() + v02.pz()}); + + TVector3 hyp1Momentum(pairInfo.hyperonMomentum[0], pairInfo.hyperonMomentum[1], pairInfo.hyperonMomentum[2]); + TVector3 hyp2Momentum(pairInfo.antiHyperonMomentum[0], pairInfo.antiHyperonMomentum[1], pairInfo.antiHyperonMomentum[2]); + pairInfo.OpAngle = hyp1Momentum.Angle(hyp2Momentum); + + if (d < 1e-5f) { // Parallel or nearly parallel lines + pairInfo.X = pairInfo.Y = pairInfo.Z = -999.f; // should we use another dummy value? Perhaps 999.f? + return pairInfo; + } + + pairInfo.X = PCA.X(); + pairInfo.Y = PCA.Y(); + pairInfo.Z = PCA.Z(); + + return pairInfo; + } + + template + PairTopoInfo propagateCascPairToDCA(float pvX, float pvY, float pvZ, TCascade const& casc1, TCascade const& casc2) + { + PairTopoInfo pairInfo; + + const std::array vtxCasc1 = {casc1.x(), casc1.y(), casc1.z()}; + const std::array vtxCasc2 = {casc2.x(), casc2.y(), casc2.z()}; + + const std::array momCasc1 = {casc1.px(), casc1.py(), casc1.pz()}; + const std::array momCasc2 = {casc2.px(), casc2.py(), casc2.pz()}; + + const std::array covCasc1 = {999.}; + const std::array covCasc2 = {999.}; + + o2::track::TrackParCov cascTrack1(vtxCasc1, momCasc1, covCasc1, casc1.sign(), true); + cascTrack1.setPID(o2::track::PID::XiMinus); + // cascTrack1.setPID(o2::track::PID::OmegaMinus); + o2::track::TrackParCov cascTrack2(vtxCasc2, momCasc2, covCasc2, casc2.sign(), true); + cascTrack2.setPID(o2::track::PID::XiMinus); + // cascTrack2.setPID(o2::track::PID::OmegaMinus); + + // Move close to minima + int nCand = 0; + try { + nCand = fitter.process(cascTrack1, cascTrack2); + } catch (...) { + return pairInfo; + } + if (nCand == 0) { + return pairInfo; + } + + fitter.propagateTracksToVertex(); // propagate e and K to D vertex + if (!fitter.isPropagateTracksToVertexDone()) { + return pairInfo; + } + + auto lCasc1Track = fitter.getTrack(0); + auto lCasc2Track = fitter.getTrack(1); + + lCasc1Track.getPxPyPzGlo(pairInfo.hyperonMomentum); + lCasc2Track.getPxPyPzGlo(pairInfo.antiHyperonMomentum); + + // DCA between cascade daughters + pairInfo.DCADau = std::sqrt(fitter.getChi2AtPCACandidate()); + + // get decay vertex coordinates + const auto& vtx = fitter.getPCACandidate(); + pairInfo.X = vtx[0]; + pairInfo.Y = vtx[1]; + pairInfo.Z = vtx[2]; + + pairInfo.CosPA = RecoDecay::cpa( + std::array{pvX, pvY, pvZ}, + std::array{vtx[0], vtx[1], vtx[2]}, + std::array{pairInfo.hyperonMomentum[0] + pairInfo.antiHyperonMomentum[0], + pairInfo.hyperonMomentum[1] + pairInfo.antiHyperonMomentum[1], + pairInfo.hyperonMomentum[2] + pairInfo.antiHyperonMomentum[2]}); + + // Momenta + TVector3 casc1Momentum(pairInfo.hyperonMomentum[0], pairInfo.hyperonMomentum[1], pairInfo.hyperonMomentum[2]); + TVector3 casc2Momentum(pairInfo.antiHyperonMomentum[0], pairInfo.antiHyperonMomentum[1], pairInfo.antiHyperonMomentum[2]); + + pairInfo.OpAngle = casc1Momentum.Angle(casc2Momentum); + + return pairInfo; + } + template bool isEventAccepted(TCollision collision, bool fillHists) // check whether the collision passes our collision selections @@ -847,7 +1232,7 @@ struct QuarkoniaToHyperons { if (fillHists) histos.fill(HIST("hEventSelection"), 4 /* Not at TF border */); - if (std::abs(collision.posZ()) > 10.f) { + if (std::abs(collision.posZ()) > maxZVtxPosition) { return false; } if (fillHists) @@ -983,7 +1368,7 @@ struct QuarkoniaToHyperons { if (v0.dcaV0daughters() < v0Selections.dcav0dau) BITSET(bitMap, selDCAV0Dau); // DCA V0 to prim vtx - if (v0.dcav0topv() > v0Selections.dcav0topv) + if (v0.dcav0topv() < v0Selections.dcav0topv) BITSET(bitMap, selDCAV0ToPV); // @@ -1046,35 +1431,35 @@ struct QuarkoniaToHyperons { // // TOF PID in DeltaT // Positive track - if (std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); - if (std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) BITSET(bitMap, selTOFDeltaTPositivePionLambda); - if (std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) BITSET(bitMap, selTOFDeltaTPositivePionK0Short); // Negative track - if (std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); - if (std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) BITSET(bitMap, selTOFDeltaTNegativePionLambda); - if (std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) BITSET(bitMap, selTOFDeltaTNegativePionK0Short); // // TOF PID in NSigma // Positive track - if (std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) + if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); - if (std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) + if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) BITSET(bitMap, selTOFNSigmaPositivePionLambda); - if (std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) + if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) BITSET(bitMap, selTOFNSigmaPositivePionK0Short); // Negative track - if (std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) + if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); - if (std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) + if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) BITSET(bitMap, selTOFNSigmaNegativePionLambda); - if (std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) + if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) BITSET(bitMap, selTOFNSigmaNegativePionK0Short); // @@ -1321,18 +1706,18 @@ struct QuarkoniaToHyperons { if (isXi) { if (casc.sign() < 0) { - if (cascMC.pdgCode() != 3312 || cascMC.pdgCodePositive() != 2212 || cascMC.pdgCodeNegative() != -211 || cascMC.pdgCodeBachelor() != -211) + if (cascMC.pdgCode() != PDG_t::kXiMinus || cascMC.pdgCodePositive() != PDG_t::kProton || cascMC.pdgCodeNegative() != PDG_t::kPiMinus || cascMC.pdgCodeBachelor() != -PDG_t::kPiMinus) return false; } else { - if (cascMC.pdgCode() != -3312 || cascMC.pdgCodePositive() != 211 || cascMC.pdgCodeNegative() != -2212 || cascMC.pdgCodeBachelor() != 211) + if (cascMC.pdgCode() != PDG_t::kXiPlusBar || cascMC.pdgCodePositive() != PDG_t::kPiPlus || cascMC.pdgCodeNegative() != PDG_t::kProtonBar || cascMC.pdgCodeBachelor() != PDG_t::kPiPlus) return false; } } else { if (casc.sign() < 0) { - if (cascMC.pdgCode() != 3334 || cascMC.pdgCodePositive() != 2212 || cascMC.pdgCodeNegative() != -211 || cascMC.pdgCodeBachelor() != -321) + if (cascMC.pdgCode() != PDG_t::kOmegaMinus || cascMC.pdgCodePositive() != PDG_t::kProton || cascMC.pdgCodeNegative() != PDG_t::kPiMinus || cascMC.pdgCodeBachelor() != PDG_t::kKMinus) return false; } else { - if (cascMC.pdgCode() != -3334 || cascMC.pdgCodePositive() != 211 || cascMC.pdgCodeNegative() != -2212 || cascMC.pdgCodeBachelor() != 321) + if (cascMC.pdgCode() != PDG_t::kOmegaPlusBar || cascMC.pdgCodePositive() != PDG_t::kPiPlus || cascMC.pdgCodeNegative() != PDG_t::kProtonBar || cascMC.pdgCodeBachelor() != PDG_t::kKPlus) return false; } } @@ -1349,17 +1734,17 @@ struct QuarkoniaToHyperons { uint64_t bitMap = 0; // check for specific particle species - if (v0.pdgCode() == 310 && v0.pdgCodePositive() == 211 && v0.pdgCodeNegative() == -211) { + if (v0.pdgCode() == PDG_t::kK0Short && v0.pdgCodePositive() == PDG_t::kPiPlus && v0.pdgCodeNegative() == PDG_t::kPiMinus) { BITSET(bitMap, selConsiderK0Short); if (v0.isPhysicalPrimary()) BITSET(bitMap, selPhysPrimK0Short); } - if (v0.pdgCode() == 3122 && v0.pdgCodePositive() == 2212 && v0.pdgCodeNegative() == -211) { + if (v0.pdgCode() == PDG_t::kLambda0 && v0.pdgCodePositive() == PDG_t::kProton && v0.pdgCodeNegative() == PDG_t::kPiMinus) { BITSET(bitMap, selConsiderLambda); if (v0.isPhysicalPrimary()) BITSET(bitMap, selPhysPrimLambda); } - if (v0.pdgCode() == -3122 && v0.pdgCodePositive() == 211 && v0.pdgCodeNegative() == -2212) { + if (v0.pdgCode() == PDG_t::kLambda0Bar && v0.pdgCodePositive() == PDG_t::kPiPlus && v0.pdgCodeNegative() == PDG_t::kProtonBar) { BITSET(bitMap, selConsiderAntiLambda); if (v0.isPhysicalPrimary()) BITSET(bitMap, selPhysPrimAntiLambda); @@ -1440,7 +1825,7 @@ struct QuarkoniaToHyperons { } template - void fillQAplot(TCollision collision, THyperon hyperon, THyperon antiHyperon, int type) + void fillQAplot(TCollision collision, PairTopoInfo pair, THyperon hyperon, THyperon antiHyperon, float pt, float invmass, int type) { // fill QA information about hyperon - antihyperon pair if (type == 0) { if constexpr (requires { hyperon.mK0Short(); antiHyperon.mK0Short(); }) { // check if v0 information is available @@ -1483,6 +1868,33 @@ struct QuarkoniaToHyperons { histos.fill(HIST("K0sK0s/K0s/hNegTPCNsigma"), negTrackExtraAntiHyperon.tpcNSigmaPi()); histos.fill(HIST("K0sK0s/K0s/h2dPositiveITSvsTPCpts"), posTrackExtraAntiHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.itsNCls()); histos.fill(HIST("K0sK0s/K0s/h2dNegativeITSvsTPCpts"), negTrackExtraAntiHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.itsNCls()); + + if (doQA) { + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPosDCAToPV"), std::min(hyperon.dcapostopv(), antiHyperon.dcapostopv()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsNegDCAToPV"), std::min(hyperon.dcanegtopv(), antiHyperon.dcanegtopv()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsDCAV0Daughters"), std::max(hyperon.dcaV0daughters(), antiHyperon.dcaV0daughters()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsDCAV0ToPV"), std::max(hyperon.dcav0topv(), antiHyperon.dcav0topv()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsV0PointingAngle"), std::min(hyperon.v0cosPA(), antiHyperon.v0cosPA()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsV0Radius"), std::min(hyperon.v0radius(), antiHyperon.v0radius()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsDecayLength"), std::max(hyperonDecayLength, antiHyperonDecayLength), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsInvMassWindow"), std::max(std::abs(hyperon.mK0Short() - o2::constants::physics::MassK0Short), std::abs(antiHyperon.mK0Short() - o2::constants::physics::MassK0Short)), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPosTPCNsigma"), std::max(posTrackExtraHyperon.tpcNSigmaPi(), posTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsNegTPCNsigma"), std::max(negTrackExtraHyperon.tpcNSigmaPi(), negTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPosITSclusters"), std::min(posTrackExtraHyperon.itsNCls(), posTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsNegITSclusters"), std::min(negTrackExtraHyperon.itsNCls(), negTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPosNbrCrossedRows"), std::min(posTrackExtraHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsNegNbrCrossedRows"), std::min(negTrackExtraHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairRadius3D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y, pair.Z), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairRadius2D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairZ"), pair.Z, pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsDCAPair"), pair.DCADau, pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairCosPA"), pair.CosPA, pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairOpAngle"), pair.OpAngle, pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairEta"), pair.Eta(), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dMassK0sK0sVsPairPhi"), pair.Phi(), pt, invmass); + histos.fill(HIST("QA/K0sK0s/h3dDeltaEtaK0sK0sVsPairEta"), pair.Eta(), pt, hyperon.eta() - antiHyperon.eta()); + histos.fill(HIST("QA/K0sK0s/h3dDeltaPhiK0sK0sVsPairPhi"), pair.Phi(), pt, std::abs(hyperon.phi() - antiHyperon.phi())); + } } } if (type == 1) { @@ -1518,12 +1930,39 @@ struct QuarkoniaToHyperons { histos.fill(HIST("LaLaBar/AntiLambda/hV0PointingAngle"), antiHyperon.v0cosPA()); histos.fill(HIST("LaLaBar/AntiLambda/hV0Radius"), antiHyperon.v0radius()); histos.fill(HIST("LaLaBar/AntiLambda/hV0DecayLength"), antiHyperonDecayLength); - histos.fill(HIST("LaLaBar/AntiLambda/hV0InvMassWindow"), antiHyperon.mLambda() - o2::constants::physics::MassLambda0); - histos.fill(HIST("LaLaBar/AntiLambda/h2dCompetingMassRej"), antiHyperon.mLambda(), antiHyperon.mK0Short()); + histos.fill(HIST("LaLaBar/AntiLambda/hV0InvMassWindow"), antiHyperon.mAntiLambda() - o2::constants::physics::MassLambda0); + histos.fill(HIST("LaLaBar/AntiLambda/h2dCompetingMassRej"), antiHyperon.mAntiLambda(), antiHyperon.mK0Short()); histos.fill(HIST("LaLaBar/AntiLambda/hPosTPCNsigma"), posTrackExtraAntiHyperon.tpcNSigmaPi()); histos.fill(HIST("LaLaBar/AntiLambda/hNegTPCNsigma"), negTrackExtraAntiHyperon.tpcNSigmaPr()); histos.fill(HIST("LaLaBar/AntiLambda/h2dPositiveITSvsTPCpts"), posTrackExtraAntiHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.itsNCls()); histos.fill(HIST("LaLaBar/AntiLambda/h2dNegativeITSvsTPCpts"), negTrackExtraAntiHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.itsNCls()); + + if (doQA) { + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPosDCAToPV"), std::min(hyperon.dcapostopv(), antiHyperon.dcanegtopv()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsNegDCAToPV"), std::min(hyperon.dcanegtopv(), antiHyperon.dcapostopv()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsDCAV0Daughters"), std::max(hyperon.dcaV0daughters(), antiHyperon.dcaV0daughters()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsDCAV0ToPV"), std::max(hyperon.dcav0topv(), antiHyperon.dcav0topv()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsV0PointingAngle"), std::min(hyperon.v0cosPA(), antiHyperon.v0cosPA()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsV0Radius"), std::min(hyperon.v0radius(), antiHyperon.v0radius()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsDecayLength"), std::max(hyperonDecayLength, antiHyperonDecayLength), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsInvMassWindow"), std::max(std::abs(hyperon.mLambda() - o2::constants::physics::MassLambda0), std::abs(antiHyperon.mAntiLambda() - o2::constants::physics::MassLambda0)), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPosTPCNsigma"), std::max(posTrackExtraHyperon.tpcNSigmaPr(), negTrackExtraAntiHyperon.tpcNSigmaPr()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsNegTPCNsigma"), std::max(negTrackExtraHyperon.tpcNSigmaPi(), posTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPosITSclusters"), std::min(posTrackExtraHyperon.itsNCls(), negTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsNegITSclusters"), std::min(negTrackExtraHyperon.itsNCls(), posTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPosNbrCrossedRows"), std::min(posTrackExtraHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsNegNbrCrossedRows"), std::min(negTrackExtraHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairRadius3D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y, pair.Z), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairRadius2D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairZ"), pair.Z, pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsDCAPair"), pair.DCADau, pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairCosPA"), pair.CosPA, pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairOpAngle"), pair.OpAngle, pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairEta"), pair.Eta(), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dMassLaLaBarVsPairPhi"), pair.Phi(), pt, invmass); + histos.fill(HIST("QA/LaLaBar/h3dDeltaEtaLaLaBarVsPairEta"), pair.Eta(), pt, hyperon.eta() - antiHyperon.eta()); + histos.fill(HIST("QA/LaLaBar/h3dDeltaPhiLaLaBarVsPairPhi"), pair.Phi(), pt, std::abs(hyperon.phi() - antiHyperon.phi())); + } } } if (type == 2) { @@ -1581,6 +2020,41 @@ struct QuarkoniaToHyperons { histos.fill(HIST("XiXiBar/AntiXi/h2dBachelorITSvsTPCpts"), bachTrackExtraAntiHyperon.tpcCrossedRows(), bachTrackExtraAntiHyperon.itsNCls()); histos.fill(HIST("XiXiBar/AntiXi/h2dPositiveITSvsTPCpts"), posTrackExtraAntiHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.itsNCls()); histos.fill(HIST("XiXiBar/AntiXi/h2dNegativeITSvsTPCpts"), negTrackExtraAntiHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.itsNCls()); + + if (doQA) { + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsBachDCAToPV"), std::min(hyperon.dcabachtopv(), antiHyperon.dcabachtopv()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPosDCAToPV"), std::min(hyperon.dcapostopv(), antiHyperon.dcanegtopv()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsNegDCAToPV"), std::min(hyperon.dcanegtopv(), antiHyperon.dcapostopv()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsDCACascDaughters"), std::max(hyperon.dcacascdaughters(), antiHyperon.dcacascdaughters()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsDCAV0Daughters"), std::max(hyperon.dcaV0daughters(), antiHyperon.dcaV0daughters()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsDCAV0ToPV"), std::max(hyperon.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), antiHyperon.dcav0topv(collision.posX(), collision.posY(), collision.posZ())), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsV0PointingAngle"), std::min(hyperon.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), antiHyperon.v0cosPA(collision.posX(), collision.posY(), collision.posZ())), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsV0Radius"), std::min(hyperon.v0radius(), antiHyperon.v0radius()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsCascPointingAngle"), std::min(hyperon.casccosPA(collision.posX(), collision.posY(), collision.posZ()), antiHyperon.casccosPA(collision.posX(), collision.posY(), collision.posZ())), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsCascRadius"), std::min(hyperon.cascradius(), antiHyperon.cascradius()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsDecayLength"), std::max(hyperonDecayLength, antiHyperonDecayLength), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsV0InvMassWindow"), std::max(std::abs(hyperon.mLambda() - o2::constants::physics::MassLambda0), std::abs(antiHyperon.mLambda() - o2::constants::physics::MassLambda0)), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsCascInvMassWindow"), std::max(std::abs(hyperon.mXi() - o2::constants::physics::MassXiMinus), std::abs(antiHyperon.mXi() - o2::constants::physics::MassXiMinus)), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsBachTPCNsigma"), std::max(bachTrackExtraHyperon.tpcNSigmaPi(), bachTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPosTPCNsigma"), std::max(posTrackExtraHyperon.tpcNSigmaPr(), negTrackExtraAntiHyperon.tpcNSigmaPr()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsNegTPCNsigma"), std::max(negTrackExtraHyperon.tpcNSigmaPi(), posTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsBachITSclusters"), std::min(bachTrackExtraHyperon.itsNCls(), bachTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPosITSclusters"), std::min(posTrackExtraHyperon.itsNCls(), negTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsNegITSclusters"), std::min(negTrackExtraHyperon.itsNCls(), posTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsBachNbrCrossedRows"), std::min(bachTrackExtraHyperon.tpcCrossedRows(), bachTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPosNbrCrossedRows"), std::min(posTrackExtraHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsNegNbrCrossedRows"), std::min(negTrackExtraHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairRadius3D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y, pair.Z), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairRadius2D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairZ"), pair.Z, pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsDCAPair"), pair.DCADau, pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairCosPA"), pair.CosPA, pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairOpAngle"), pair.OpAngle, pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairEta"), pair.Eta(), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dMassXiXiBarVsPairPhi"), pair.Phi(), pt, invmass); + histos.fill(HIST("QA/XiXiBar/h3dDeltaEtaXiXiBarVsPairEta"), pair.Eta(), pt, hyperon.eta() - antiHyperon.eta()); + histos.fill(HIST("QA/XiXiBar/h3dDeltaPhiXiXiBarVsPairPhi"), pair.Phi(), pt, std::abs(hyperon.phi() - antiHyperon.phi())); + } } } if (type == 3) { @@ -1638,6 +2112,41 @@ struct QuarkoniaToHyperons { histos.fill(HIST("OmOmBar/AntiOmega/h2dBachelorITSvsTPCpts"), bachTrackExtraAntiHyperon.tpcCrossedRows(), bachTrackExtraAntiHyperon.itsNCls()); histos.fill(HIST("OmOmBar/AntiOmega/h2dPositiveITSvsTPCpts"), posTrackExtraAntiHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.itsNCls()); histos.fill(HIST("OmOmBar/AntiOmega/h2dNegativeITSvsTPCpts"), negTrackExtraAntiHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.itsNCls()); + + if (doQA) { + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsBachDCAToPV"), std::min(hyperon.dcabachtopv(), antiHyperon.dcabachtopv()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPosDCAToPV"), std::min(hyperon.dcapostopv(), antiHyperon.dcanegtopv()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsNegDCAToPV"), std::min(hyperon.dcanegtopv(), antiHyperon.dcapostopv()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsDCACascDaughters"), std::max(hyperon.dcacascdaughters(), antiHyperon.dcacascdaughters()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsDCAV0Daughters"), std::max(hyperon.dcaV0daughters(), antiHyperon.dcaV0daughters()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsDCAV0ToPV"), std::max(hyperon.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), antiHyperon.dcav0topv(collision.posX(), collision.posY(), collision.posZ())), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsV0PointingAngle"), std::min(hyperon.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), antiHyperon.v0cosPA(collision.posX(), collision.posY(), collision.posZ())), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsV0Radius"), std::min(hyperon.v0radius(), antiHyperon.v0radius()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsCascPointingAngle"), std::min(hyperon.casccosPA(collision.posX(), collision.posY(), collision.posZ()), antiHyperon.casccosPA(collision.posX(), collision.posY(), collision.posZ())), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsCascRadius"), std::min(hyperon.cascradius(), antiHyperon.cascradius()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsDecayLength"), std::max(hyperonDecayLength, antiHyperonDecayLength), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsV0InvMassWindow"), std::max(std::abs(hyperon.mLambda() - o2::constants::physics::MassLambda0), std::abs(antiHyperon.mLambda() - o2::constants::physics::MassLambda0)), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsCascInvMassWindow"), std::max(std::abs(hyperon.mOmega() - o2::constants::physics::MassOmegaMinus), std::abs(antiHyperon.mOmega() - o2::constants::physics::MassOmegaMinus)), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsBachTPCNsigma"), std::max(bachTrackExtraHyperon.tpcNSigmaPi(), bachTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPosTPCNsigma"), std::max(posTrackExtraHyperon.tpcNSigmaPr(), negTrackExtraAntiHyperon.tpcNSigmaPr()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsNegTPCNsigma"), std::max(negTrackExtraHyperon.tpcNSigmaPi(), posTrackExtraAntiHyperon.tpcNSigmaPi()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsBachITSclusters"), std::min(bachTrackExtraHyperon.itsNCls(), bachTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPosITSclusters"), std::min(posTrackExtraHyperon.itsNCls(), negTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsNegITSclusters"), std::min(negTrackExtraHyperon.itsNCls(), posTrackExtraAntiHyperon.itsNCls()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsBachNbrCrossedRows"), std::min(bachTrackExtraHyperon.tpcCrossedRows(), bachTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPosNbrCrossedRows"), std::min(posTrackExtraHyperon.tpcCrossedRows(), negTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsNegNbrCrossedRows"), std::min(negTrackExtraHyperon.tpcCrossedRows(), posTrackExtraAntiHyperon.tpcCrossedRows()), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairRadius3D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y, pair.Z), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairRadius2D"), RecoDecay::sqrtSumOfSquares(pair.X, pair.Y), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairZ"), pair.Z, pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsDCAPair"), pair.DCADau, pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairCosPA"), pair.CosPA, pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairOpAngle"), pair.OpAngle, pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairEta"), pair.Eta(), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dMassOmOmBarVsPairPhi"), pair.Phi(), pt, invmass); + histos.fill(HIST("QA/OmOmBar/h3dDeltaEtaOmOmBarVsPairEta"), pair.Eta(), pt, hyperon.eta() - antiHyperon.eta()); + histos.fill(HIST("QA/OmOmBar/h3dDeltaPhiOmOmBarVsPairPhi"), pair.Phi(), pt, std::abs(hyperon.phi() - antiHyperon.phi())); + } } } } @@ -1647,19 +2156,39 @@ struct QuarkoniaToHyperons { // fill information related to the quarkonium mother // type = 0 (Lambda), 1 (Xi), 2 (Omega) { - float pt = RecoDecay::pt(hyperon.px() + antiHyperon.px(), hyperon.py() + antiHyperon.py()); + PairTopoInfo pair; + if (doPairPropagationToDCA) { + if (type == 0 || type == 1) { + if constexpr (requires { hyperon.mK0Short(); antiHyperon.mK0Short(); }) { + pair = propagateV0PairToDCA(collision.posX(), collision.posY(), collision.posZ(), hyperon, antiHyperon); + } + } else { + if constexpr (requires { hyperon.dcabachtopv(); antiHyperon.dcabachtopv(); }) { // check if Cascade information is available + pair = propagateCascPairToDCA(collision.posX(), collision.posY(), collision.posZ(), hyperon, antiHyperon); + } + } + } else { + pair.hyperonMomentum[0] = hyperon.px(); + pair.hyperonMomentum[1] = hyperon.py(); + pair.hyperonMomentum[2] = hyperon.pz(); + pair.antiHyperonMomentum[0] = antiHyperon.px(); + pair.antiHyperonMomentum[1] = antiHyperon.py(); + pair.antiHyperonMomentum[2] = antiHyperon.pz(); + } + + float pt = RecoDecay::pt(pair.hyperonMomentum[0] + pair.antiHyperonMomentum[0], pair.hyperonMomentum[1] + pair.antiHyperonMomentum[1]); float invmass = -1; if (type == 0) - invmass = RecoDecay::m(std::array{std::array{hyperon.px(), hyperon.py(), hyperon.pz()}, std::array{antiHyperon.px(), antiHyperon.py(), antiHyperon.pz()}}, std::array{o2::constants::physics::MassKaonNeutral, o2::constants::physics::MassKaonNeutral}); + invmass = RecoDecay::m(std::array{pair.hyperonMomentum, pair.antiHyperonMomentum}, std::array{o2::constants::physics::MassKaonNeutral, o2::constants::physics::MassKaonNeutral}); if (type == 1) - invmass = RecoDecay::m(std::array{std::array{hyperon.px(), hyperon.py(), hyperon.pz()}, std::array{antiHyperon.px(), antiHyperon.py(), antiHyperon.pz()}}, std::array{o2::constants::physics::MassLambda0, o2::constants::physics::MassLambda0Bar}); + invmass = RecoDecay::m(std::array{pair.hyperonMomentum, pair.antiHyperonMomentum}, std::array{o2::constants::physics::MassLambda0, o2::constants::physics::MassLambda0Bar}); if (type == 2) - invmass = RecoDecay::m(std::array{std::array{hyperon.px(), hyperon.py(), hyperon.pz()}, std::array{antiHyperon.px(), antiHyperon.py(), antiHyperon.pz()}}, std::array{o2::constants::physics::MassXiMinus, o2::constants::physics::MassXiPlusBar}); + invmass = RecoDecay::m(std::array{pair.hyperonMomentum, pair.antiHyperonMomentum}, std::array{o2::constants::physics::MassXiMinus, o2::constants::physics::MassXiPlusBar}); if (type == 3) - invmass = RecoDecay::m(std::array{std::array{hyperon.px(), hyperon.py(), hyperon.pz()}, std::array{antiHyperon.px(), antiHyperon.py(), antiHyperon.pz()}}, std::array{o2::constants::physics::MassOmegaMinus, o2::constants::physics::MassOmegaPlusBar}); + invmass = RecoDecay::m(std::array{pair.hyperonMomentum, pair.antiHyperonMomentum}, std::array{o2::constants::physics::MassOmegaMinus, o2::constants::physics::MassOmegaPlusBar}); - float rapidity = RecoDecay::y(std::array{hyperon.px() + antiHyperon.px(), hyperon.py() + antiHyperon.py(), hyperon.pz() + antiHyperon.pz()}, invmass); + float rapidity = RecoDecay::y(std::array{pair.hyperonMomentum[0] + pair.antiHyperonMomentum[0], pair.hyperonMomentum[1] + pair.antiHyperonMomentum[1], pair.hyperonMomentum[2] + pair.antiHyperonMomentum[2]}, invmass); // rapidity cut on the quarkonium mother if (!doMCAssociation && std::fabs(rapidity) > rapidityCut) @@ -1723,7 +2252,7 @@ struct QuarkoniaToHyperons { else histos.fill(HIST("K0sK0s/h3dMassK0sK0sHadronic"), centrality, pt, invmass); } - fillQAplot(collision, hyperon, antiHyperon, type); + fillQAplot(collision, pair, hyperon, antiHyperon, pt, invmass, type); } if (type == 1) { if (doMCAssociation) { @@ -1779,7 +2308,7 @@ struct QuarkoniaToHyperons { else histos.fill(HIST("LaLaBar/h3dMassLaLabarHadronic"), centrality, pt, invmass); } - fillQAplot(collision, hyperon, antiHyperon, type); + fillQAplot(collision, pair, hyperon, antiHyperon, pt, invmass, type); } if (type == 2) { if (doMCAssociation) { @@ -1835,7 +2364,7 @@ struct QuarkoniaToHyperons { else histos.fill(HIST("XiXiBar/h3dMassXiXibarHadronic"), centrality, pt, invmass); } - fillQAplot(collision, hyperon, antiHyperon, type); + fillQAplot(collision, pair, hyperon, antiHyperon, pt, invmass, type); } if (type == 3) { if (doMCAssociation) { @@ -1873,7 +2402,7 @@ struct QuarkoniaToHyperons { else histos.fill(HIST("OmOmBar/h3dMassOmOmbarHadronic"), centrality, pt, invmass); } - fillQAplot(collision, hyperon, antiHyperon, type); + fillQAplot(collision, pair, hyperon, antiHyperon, pt, invmass, type); } } @@ -1985,7 +2514,7 @@ struct QuarkoniaToHyperons { for (const auto& collision : collisions) { // Fire up CCDB - if (cfgSkimmedProcessing || + if (cfgSkimmedProcessing || doPairPropagationToDCA || (mlConfigurations.useK0ShortScores && mlConfigurations.calculateK0ShortScores) || (mlConfigurations.useLambdaScores && mlConfigurations.calculateLambdaScores) || (mlConfigurations.useAntiLambdaScores && mlConfigurations.calculateAntiLambdaScores)) { @@ -1993,7 +2522,7 @@ struct QuarkoniaToHyperons { } if (!isEventAccepted(collision, true)) { - return; + continue; } if (cfgSkimmedProcessing) { @@ -2162,7 +2691,7 @@ struct QuarkoniaToHyperons { for (const auto& collision : collisions) { // Fire up CCDB - if (cfgSkimmedProcessing || + if (cfgSkimmedProcessing || doPairPropagationToDCA || (mlConfigurations.useK0ShortScores && mlConfigurations.calculateK0ShortScores) || (mlConfigurations.useLambdaScores && mlConfigurations.calculateLambdaScores) || (mlConfigurations.useAntiLambdaScores && mlConfigurations.calculateAntiLambdaScores)) { @@ -2170,7 +2699,7 @@ struct QuarkoniaToHyperons { } if (!isEventAccepted(collision, true)) { - return; + continue; } if (cfgSkimmedProcessing) { @@ -2188,6 +2717,7 @@ struct QuarkoniaToHyperons { selK0ShortIndices.clear(); selLambdaIndices.clear(); selAntiLambdaIndices.clear(); + for (std::size_t i = 0; i < nV0sThisColl; i++) { auto v0 = fullV0s.rawIteratorAt(v0sGrouped[collision.globalIndex()][i]); @@ -2201,14 +2731,17 @@ struct QuarkoniaToHyperons { float ptmc = RecoDecay::sqrtSumOfSquares(v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC()); float ymc = 1e-3; - if (v0MC.pdgCode() == 310) + if (v0MC.pdgCode() == PDG_t::kK0Short) ymc = RecoDecay::y(std::array{v0MC.pxPosMC() + v0MC.pxNegMC(), v0MC.pyPosMC() + v0MC.pyNegMC(), v0MC.pzPosMC() + v0MC.pzNegMC()}, o2::constants::physics::MassKaonNeutral); - else if (std::fabs(v0MC.pdgCode()) == 3122) + else if (std::abs(v0MC.pdgCode()) == PDG_t::kLambda0) 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(v0MC); + // selMap |= maskTopological | maskTrackProperties | maskLambdaSpecific; + // selMap |= maskTopological | maskTrackProperties | maskAntiLambdaSpecific; + // consider only associated candidates if asked to do so, disregard association if (!doMCAssociation) { selMap = selMap | (static_cast(1) << selConsiderK0Short) | (static_cast(1) << selConsiderLambda) | (static_cast(1) << selConsiderAntiLambda); @@ -2272,9 +2805,9 @@ struct QuarkoniaToHyperons { auto cascadeMC = cascade.cascMCCore_as>(); float ymc = 1e-3; - if (std::fabs(cascadeMC.pdgCode()) == 3312) + if (std::abs(cascadeMC.pdgCode()) == PDG_t::kXiMinus) ymc = RecoDecay::y(std::array{cascadeMC.pxMC(), cascadeMC.pyMC(), cascadeMC.pzMC()}, o2::constants::physics::MassXiMinus); - else if (std::fabs(cascadeMC.pdgCode()) == 3334) + else if (std::abs(cascadeMC.pdgCode()) == PDG_t::kOmegaMinus) ymc = RecoDecay::y(std::array{cascadeMC.pxMC(), cascadeMC.pyMC(), cascadeMC.pzMC()}, o2::constants::physics::MassOmegaMinus); if (buildXiXiBarPairs) { diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index 2b35db2611c..3c776e2a42d 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -22,36 +22,39 @@ #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/EventSelectionParams.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ITSMFTBase/DPLAlpideParam.h" - -#include "TGeoGlobalMagField.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include #include #include -#include -#include +#include + +#include +#include +#include #include #include #include +#include #include -using std::cout; -using std::endl; using std::string; using namespace o2; @@ -163,6 +166,7 @@ struct AnalysisEventSelection { 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 fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; 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!]"}; @@ -200,12 +204,18 @@ struct AnalysisEventSelection { } TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); - if (objArray->GetEntries() > 0) { + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); fMixHandler->Init(); - for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { - dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(fMixHandler, mixVarsJsonString.Data()); } } @@ -1540,6 +1550,7 @@ struct AnalysisSameEventPairing { -999., -999., -999., -999., -999., -999., -999., -999., t1.isAmbiguous(), t2.isAmbiguous(), + true, true, 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], diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index cbc1690aeaa..5cbc6a50c62 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -26,42 +26,48 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TableHelper.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" -#include "ITSMFTBase/DPLAlpideParam.h" - -#include "TGeoGlobalMagField.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include -#include -#include #include #include +#include +#include #include -#include #include +#include + #include +#include +#include #include #include +#include #include #include +#include #include #include -#include -#include #include #include +#include #include using std::cout; @@ -72,6 +78,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; +using namespace o2::common::core; // Some definitions namespace o2::aod @@ -150,6 +157,7 @@ DECLARE_SOA_COLUMN(Massee, massJPsi2ee, float); DECLARE_SOA_COLUMN(Ptee, ptJPsi2ee, float); DECLARE_SOA_COLUMN(Lxyee, lxyJPsi2ee, float); DECLARE_SOA_COLUMN(LxyeePoleMass, lxyJPsi2eePoleMass, float); +DECLARE_SOA_COLUMN(LRecalxyeePoleMass, lRecalxyeePoleMass, float); DECLARE_SOA_COLUMN(Lzee, lzJPsi2ee, float); DECLARE_SOA_COLUMN(AmbiguousInBunchPairs, AmbiguousJpsiPairsInBunch, bool); DECLARE_SOA_COLUMN(AmbiguousOutOfBunchPairs, AmbiguousJpsiPairsOutOfBunch, bool); @@ -189,12 +197,13 @@ DECLARE_SOA_TABLE(JPsiMuonCandidates, "AOD", "DQJPSIMUONA", dqanalysisflags::DeltaEta, dqanalysisflags::DeltaPhi, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, dqanalysisflags::Ptassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Phiassoc, dqanalysisflags::Ptleg1, dqanalysisflags::Etaleg1, dqanalysisflags::Phileg1, dqanalysisflags::Ptleg2, dqanalysisflags::Etaleg2, dqanalysisflags::Phileg2); -DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); +DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LRecalxyeePoleMass, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); } // namespace o2::aod // Declarations of various short names -using MyEvents = soa::Join; -using MyEventsMultExtra = soa::Join; +using MyEvents = soa::Join; +using MyEventsBasic = soa::Join; +using MyEventsMultExtra = soa::Join; using MyEventsMultExtraQVector = soa::Join; using MyEventsZdc = soa::Join; using MyEventsMultExtraZdc = soa::Join; @@ -275,6 +284,7 @@ struct AnalysisEventSelection { // 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 fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; @@ -306,7 +316,7 @@ struct AnalysisEventSelection { void init(o2::framework::InitContext& context) { - bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr"); + bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedBasic") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithMultExtraZdcFit") || context.mOptions.get("processSkimmedWithQvectorCentr"); bool isDummyEnabled = context.mOptions.get("processDummy"); if (isDummyEnabled) { @@ -355,12 +365,18 @@ struct AnalysisEventSelection { } TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; std::unique_ptr objArray(mixVarsString.Tokenize(",")); - if (objArray->GetEntries() > 0) { + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); fMixHandler->Init(); - for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { - dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(fMixHandler, mixVarsJsonString.Data()); } } @@ -527,6 +543,11 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processSkimmedBasic(MyEventsBasic const& events) + { + runEventSelection(events); + publishSelections(events); + } void processSkimmedWithZdc(MyEventsZdc const& events) { runEventSelection(events); @@ -552,12 +573,13 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } PROCESS_SWITCH(AnalysisEventSelection, processSkimmed, "Run event selection on DQ skimmed events", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedBasic, "Run event selection on DQ skimmed events with basic tables", 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, processSkimmedWithMultExtraZdc, "Run event selection on DQ skimmed events, with mult extra and ZDC", false); @@ -813,7 +835,7 @@ struct AnalysisTrackSelection { { runTrackSelection(assocs, events, tracks); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -1024,7 +1046,7 @@ struct AnalysisMuonSelection { { runMuonSelection(assocs, events, muons); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -1173,7 +1195,7 @@ struct AnalysisPrefilterSelection { } // end loop over combinations } - void processBarrelSkimmed(MyEvents const& events, soa::Join const& assocs, MyBarrelTracks const& tracks) + void processBarrelSkimmed(MyEventsBasic const& events, soa::Join const& assocs, MyBarrelTracks const& tracks) { fPrefilterMap.clear(); @@ -1206,7 +1228,7 @@ struct AnalysisPrefilterSelection { } } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -1224,6 +1246,7 @@ struct AnalysisSameEventPairing { Produces dielectronList; Produces dimuonList; + Produces electronmuonList; Produces dielectronsExtraList; Produces dielectronInfoList; Produces dimuonsExtraList; @@ -1302,6 +1325,7 @@ struct AnalysisSameEventPairing { std::map> fTrackMuonHistNames; std::vector fPairCuts; std::vector fTrackCuts; + std::vector fMuonCuts; std::map, uint32_t> fAmbiguousPairs; uint32_t fTrackFilterMask; // mask for the track cuts required in this task to be applied on the barrel cuts produced upstream @@ -1309,15 +1333,19 @@ struct AnalysisSameEventPairing { int fNCutsBarrel; int fNCutsMuon; int fNPairCuts; + int fNPairPerEvent; bool fEnableBarrelMixingHistos; bool fEnableBarrelHistos; bool fEnableMuonHistos; bool fEnableMuonMixingHistos; + bool fEnableBarrelMuonHistos; + // bool fEnableBarrelMuonMixingHistos; NoBinningPolicy hashBin; Preslice> trackAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + Preslice> trackEmuAssocsPerCollision = aod::reducedtrack_association::reducedeventId; Preslice> muonAssocsPerCollision = aod::reducedtrack_association::reducedeventId; void init(o2::framework::InitContext& context) @@ -1326,9 +1354,10 @@ struct AnalysisSameEventPairing { fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed") || context.mOptions.get("processMixingBarrelSkimmedFlow") || context.mOptions.get("processMixingBarrelWithQvectorCentrSkimmedNoCov"); fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMuonOnlySkimmedFlow") || context.mOptions.get("processMixingMuonSkimmed"); fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed"); + fEnableBarrelMuonHistos = context.mOptions.get("processElectronMuonSkimmed"); if (context.mOptions.get("processDummy")) { - if (fEnableBarrelHistos || fEnableBarrelMixingHistos || fEnableMuonHistos || fEnableMuonMixingHistos) { + if (fEnableBarrelHistos || fEnableBarrelMixingHistos || fEnableMuonHistos || fEnableMuonMixingHistos || fEnableBarrelMuonHistos) { LOG(fatal) << "No other processing tasks should be enabled if the processDummy is enabled!!"; } return; @@ -1339,6 +1368,7 @@ struct AnalysisSameEventPairing { TString histNames = ""; std::vector names; fTrackCuts.clear(); + fMuonCuts.clear(); // NOTE: Pair cuts are only applied on the histogram output. The produced pair tables do not have these cuts applied TString cutNamesStr = fConfigCuts.pair.value; @@ -1486,6 +1516,7 @@ struct AnalysisSameEventPairing { fNCutsMuon = objArray->GetEntries(); for (int icut = 0; icut < objArray->GetEntries(); ++icut) { TString tempStr = objArray->At(icut)->GetName(); + fMuonCuts.push_back(tempStr); if (objArrayMuonCuts->FindObject(tempStr.Data()) != nullptr) { fMuonFilterMask |= (static_cast(1) << icut); @@ -1568,38 +1599,49 @@ struct AnalysisSameEventPairing { VarManager::SetupMatLUTFwdDCAFitter(fLUT); } - /*if (context.mOptions.get("processElectronMuonSkimmed") || context.mOptions.get("processAllSkimmed")) { - TString cutNamesBarrel = fConfigCuts.track.value; - TString cutNamesMuon = fConfigCuts.muon.value; - if (!cutNamesBarrel.IsNull() && !cutNamesMuon.IsNull()) { - std::unique_ptr objArrayBarrel(cutNamesBarrel.Tokenize(",")); - std::unique_ptr objArrayMuon(cutNamesMuon.Tokenize(",")); - if (objArrayBarrel->GetEntries() == objArrayMuon->GetEntries()) { // one must specify equal number of barrel and muon cuts - for (int icut = 0; icut < objArrayBarrel->GetEntries(); ++icut) { // loop over track cuts - // no pair cuts - names = { - Form("PairsEleMuSEPM_%s_%s", objArrayBarrel->At(icut)->GetName(), objArrayMuon->At(icut)->GetName()), - Form("PairsEleMuSEPP_%s_%s", objArrayBarrel->At(icut)->GetName(), objArrayMuon->At(icut)->GetName()), - Form("PairsEleMuSEMM_%s_%s", objArrayBarrel->At(icut)->GetName(), objArrayMuon->At(icut)->GetName())}; - histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); - fTrackMuonHistNames.push_back(names); + if (fEnableBarrelMuonHistos) { + for (int iTrack = 0; iTrack < fNCutsBarrel; ++iTrack) { + TString trackCutName = fTrackCuts[iTrack]; + if (objArrayTrackCuts->FindObject(trackCutName.Data()) == nullptr) + continue; - TString cutNamesStr = fConfigCuts.pair.value; - if (!cutNamesStr.IsNull()) { // if pair cuts - std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); - for (int iPairCut = 0; iPairCut < objArrayPair->GetEntries(); ++iPairCut) { // loop over pair cuts - std::vector names = { - Form("PairsEleMuSEPM_%s_%s_%s", objArrayBarrel->At(icut)->GetName(), objArrayMuon->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), - Form("PairsEleMuSEPP_%s_%s_%s", objArrayBarrel->At(icut)->GetName(), objArrayMuon->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), - Form("PairsEleMuSEMM_%s_%s_%s", objArrayBarrel->At(icut)->GetName(), objArrayMuon->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName())}; - histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); - fTrackMuonHistNames.push_back(names); - } // end loop (pair cuts) - } // end if (pair cuts) - } // end loop (track cuts) - } // end if (equal number of cuts) - } // end if (track cuts) - }*/ + for (int iMuon = 0; iMuon < fNCutsMuon; ++iMuon) { + TString muonCutName = fMuonCuts[iMuon]; + if (objArrayMuonCuts->FindObject(muonCutName.Data()) == nullptr) + continue; + + names = { + Form("PairsEleMuSEPM_%s_%s", trackCutName.Data(), muonCutName.Data()), + Form("PairsEleMuSEPP_%s_%s", trackCutName.Data(), muonCutName.Data()), + Form("PairsEleMuSEMM_%s_%s", trackCutName.Data(), muonCutName.Data())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + int index = iTrack * fNCutsMuon + iMuon; + fTrackMuonHistNames[index] = names; + + // if (fEnableBarrelMuonMixingHistos) { + // names.push_back(Form("PairsBarrelMuonMEPM_%s_%s", trackCutName.Data(), muonCutName.Data())); + // names.push_back(Form("PairsBarrelMuonMEPP_%s_%s", trackCutName.Data(), muonCutName.Data())); + // names.push_back(Form("PairsBarrelMuonMEMM_%s_%s", trackCutName.Data(), muonCutName.Data())); + // histNames += Form("%s;%s;%s;", names[3].Data(), names[4].Data(), names[5].Data()); + // } + + TString cutNamesStr = fConfigCuts.pair.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + int nPairCuts = objArrayPair->GetEntries(); + for (int iPairCut = 0; iPairCut < nPairCuts; ++iPairCut) { + names = { + Form("PairsEleMuSEPM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsEleMuSEPP_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsEleMuSEMM_%s_%s_%s", trackCutName.Data(), muonCutName.Data(), objArrayPair->At(iPairCut)->GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + index = iTrack * (fNCutsMuon * nPairCuts) + iMuon * nPairCuts + iPairCut; + fTrackMuonHistNames[index] = names; + } + } + } + } + } if (fConfigQA) { fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); @@ -1607,8 +1649,14 @@ struct AnalysisSameEventPairing { fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); VarManager::SetCollisionSystem((TString)fConfigOptions.collisionSystem, fConfigOptions.centerMassEnergy); // set collision system and center of mass energy DefineHistograms(fHistMan, histNames.Data(), fConfigAddSEPHistogram.value.data()); // define all histograms - dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + if (fEnableBarrelHistos) { + DefineHistograms(fHistMan, "PairingSEQA", "sameevent-pairing"); // histograms for QA of the pairing + }; + if (fEnableBarrelMixingHistos) { + DefineHistograms(fHistMan, "PairingMEQA", "mixedevent-pairing"); // histograms for QA of the pairing + }; + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } } @@ -1715,6 +1763,7 @@ struct AnalysisSameEventPairing { constexpr bool eventHasQvectorCentr = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); constexpr bool trackHasCov = ((TTrackFillMap & VarManager::ObjTypes::TrackCov) > 0 || (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelCov) > 0); bool isSelectedBDT = false; + fNPairPerEvent = 0; for (auto& event : events) { if (!event.isEventSelected_bit(0)) { @@ -1762,6 +1811,7 @@ struct AnalysisSameEventPairing { twoTrackFilter |= (static_cast(1) << 31); } + fNPairPerEvent++; VarManager::FillPair(t1, t2); // compute quantities which depend on the associated collision, such as DCA if (fConfigOptions.propTrack) { @@ -1921,6 +1971,7 @@ struct AnalysisSameEventPairing { -999., -999., -999., -999., -999., -999., -999., -999., (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)), (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)), + true, true, 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], @@ -1983,7 +2034,7 @@ struct AnalysisSameEventPairing { } } if (sign1 * sign2 < 0) { - PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); if constexpr (TPairType == VarManager::kDecayToMuMu) { fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); if (fConfigAmbiguousMuonHistograms) { @@ -2066,6 +2117,10 @@ struct AnalysisSameEventPairing { } } // end loop (cuts) } // end loop over pairs of track associations + VarManager::fgValues[VarManager::kNPairsPerEvent] = fNPairPerEvent; + if (fEnableBarrelHistos && fConfigQA) { + fHistMan->FillHistClass("PairingSEQA", VarManager::fgValues); + } } // end loop over events } @@ -2085,6 +2140,7 @@ struct AnalysisSameEventPairing { } auto t1 = a1.template reducedtrack_as(); auto t2 = a2.template reducedtrack_as(); + fNPairPerEvent++; VarManager::FillPairME(t1, t2); if constexpr ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0) { VarManager::FillPairVn(t1, t2); @@ -2149,6 +2205,7 @@ struct AnalysisSameEventPairing { -999., -999., -999., -999., -999., -999., -999., -999., (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)), (twoTrackFilter & (static_cast(1) << 30)) || (twoTrackFilter & (static_cast(1) << 31)), + true, true, 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], @@ -2249,7 +2306,129 @@ struct AnalysisSameEventPairing { auto assocs2 = assocs.sliceBy(preSlice, event2.globalIndex()); assocs2.bindExternalIndices(&events); + fNPairPerEvent = 0; runMixedPairing(assocs1, assocs2, tracks, tracks); + VarManager::fgValues[VarManager::kNPairsPerEvent] = fNPairPerEvent; + if (fEnableBarrelMixingHistos && fConfigQA) { + fHistMan->FillHistClass("PairingMEQA", VarManager::fgValues); + } + } // end event loop + } + + template + void runEmuSameEventPairing(TEvents const& events, Preslice& preslice1, TTrackAssocs const& assocs1, TTracks const& /*tracks1*/, Preslice& preslice2, TMuonAssocs const& assocs2, TMuons const& /*tracks2*/) + { + if (events.size() > 0) { + if (fCurrentRun != events.begin().runNumber()) { + initParamsFromCCDB(events.begin().timestamp(), events.begin().runNumber(), TTwoProngFitter); + fCurrentRun = events.begin().runNumber(); + } + } + + const auto& histNames = fTrackMuonHistNames; + int nPairCuts = (fPairCuts.size() > 0) ? fPairCuts.size() : 1; + + electronmuonList.reserve(1); + + uint32_t twoTrackFilter = 0; + int sign1 = 0; + int sign2 = 0; + + constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); + constexpr bool eventHasQvectorCentr = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); + + for (auto& event : events) { + if (!event.isEventSelected_bit(0)) + continue; + if (fConfigCuts.event && event.isEventSelected_bit(2)) + continue; + + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + + auto groupedAssocs1 = assocs1.sliceBy(preslice1, event.globalIndex()); + if (groupedAssocs1.size() == 0) + continue; + auto groupedAssocs2 = assocs2.sliceBy(preslice2, event.globalIndex()); + if (groupedAssocs2.size() == 0) + continue; + + // Custom combination policy + for (auto& [a1, a2] : o2::soa::combinations(soa::CombinationsFullIndexPolicy(groupedAssocs1, groupedAssocs2))) { + if (!(a1.isBarrelSelected_raw() & fTrackFilterMask)) + continue; + // if (!a1.isBarrelSelectedPrefilter_raw()) continue; + if (!(a2.isMuonSelected_raw() & fMuonFilterMask)) + continue; + + auto t1 = a1.template reducedtrack_as(); + auto t2 = a2.template reducedmuon_as(); + sign1 = t1.sign(); + sign2 = t2.sign(); + + twoTrackFilter = 0; + int minCuts = std::min(fNCutsBarrel, fNCutsMuon); + for (int i = 0; i < minCuts; ++i) { + if ((a1.isBarrelSelected_raw() & (1u << i)) && (a2.isMuonSelected_raw() & (1u << i))) { + twoTrackFilter |= (1u << i); + } + } + if (t1.barrelAmbiguityInBunch() > 1) + twoTrackFilter |= (1u << 28); + if (t1.barrelAmbiguityOutOfBunch() > 1) + twoTrackFilter |= (1u << 30); + if (t2.muonAmbiguityInBunch() > 1) + twoTrackFilter |= (1u << 29); + if (t2.muonAmbiguityOutOfBunch() > 1) + twoTrackFilter |= (1u << 31); + + VarManager::FillPair(t1, t2); + if (fConfigOptions.propTrack) { + VarManager::FillPairCollision(event, t1, t2); + } + if constexpr (eventHasQvector) { + VarManager::FillPairVn(t1, t2); + } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } + + electronmuonList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], + t1.sign() + t2.sign(), twoTrackFilter, 0); + + for (int iTrack = 0; iTrack < fNCutsBarrel; ++iTrack) { + if (!(a1.isBarrelSelected_raw() & (1u << iTrack))) + continue; + + for (int iMuon = 0; iMuon < fNCutsMuon; ++iMuon) { + if (!(a2.isMuonSelected_raw() & (1u << iMuon))) + continue; + + for (unsigned int iPairCut = 0; iPairCut < (fPairCuts.empty() ? 1 : fPairCuts.size()); iPairCut++) { + if (!fPairCuts.empty()) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!cut.IsSelected(VarManager::fgValues)) + continue; + } + int index = iTrack * (fNCutsMuon * nPairCuts) + iMuon * nPairCuts + iPairCut; + auto itHist = histNames.find(index); + if (itHist == histNames.end()) + continue; + if (sign1 * sign2 < 0) { // Opposite Sign + fHistMan->FillHistClass(itHist->second[0].Data(), VarManager::fgValues); + } else { // Like Sign + if (sign1 > 0) { + fHistMan->FillHistClass(itHist->second[1].Data(), VarManager::fgValues); + } else { + fHistMan->FillHistClass(itHist->second[2].Data(), VarManager::fgValues); + } + } + } // end pair cut loop + } // end muon cut loop + } // end barrel cut loop + + } // end combinations loop } // end event loop } @@ -2322,6 +2501,13 @@ struct AnalysisSameEventPairing { runSameEventPairing(events, muonAssocsPerCollision, muonAssocs, muons); } + void processElectronMuonSkimmed(MyEventsVtxCovSelected const& events, + soa::Join const& barrelAssocs, MyBarrelTracksWithCovWithAmbiguities const& barrelTracks, + soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) + { + runEmuSameEventPairing(events, trackEmuAssocsPerCollision, barrelAssocs, barrelTracks, muonAssocsPerCollision, muonAssocs, muons); + } + void processMixingAllSkimmed(soa::Filtered& events, soa::Join const& trackAssocs, MyBarrelTracksWithCov const& tracks, soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) @@ -2354,7 +2540,7 @@ struct AnalysisSameEventPairing { runSameSideMixing(events, muonAssocs, muons, muonAssocsPerCollision); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -2369,6 +2555,7 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmed, "Run muon only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmedMultExtra, "Run muon only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmedFlow, "Run muon only pairing, with skimmed tracks and flow", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processElectronMuonSkimmed, "Run electron-muon pairing, with skimmed tracks/muons", 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, processMixingBarrelSkimmedFlow, "Run barrel type mixing pairing, with flow, with skimmed tracks", false); @@ -2397,6 +2584,7 @@ struct AnalysisAsymmetricPairing { Configurable fConfigCommonTrackCuts{"cfgCommonTrackCuts", "", "Comma separated list of cuts to be applied to all legs"}; Configurable fConfigPairCuts{"cfgPairCuts", "", "Comma separated list of pair cuts"}; Configurable fConfigPairCutsJSON{"cfgPairCutsJSON", "", "Additional list of pair cuts in JSON format"}; + Configurable fConfigRemoveCollSplittingCandidates{"cfgRemoveCollSplittingCandidates", false, "If true, remove collision splitting candidates as determined by the event selection task upstream"}; 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"}; @@ -2749,6 +2937,9 @@ struct AnalysisAsymmetricPairing { if (!event.isEventSelected_bit(0)) { continue; } + if (fConfigRemoveCollSplittingCandidates.value && event.isEventSelected_bit(2)) { + continue; + } // Reset the fValues array VarManager::ResetValues(0, VarManager::kNVars); VarManager::FillEvent(event, VarManager::fgValues); @@ -2923,6 +3114,9 @@ struct AnalysisAsymmetricPairing { if (!event.isEventSelected_bit(0)) { continue; } + if (fConfigRemoveCollSplittingCandidates.value && event.isEventSelected_bit(2)) { + continue; + } // Reset the fValues array VarManager::ResetValues(0, VarManager::kNVars); VarManager::FillEvent(event, VarManager::fgValues); @@ -3092,7 +3286,7 @@ struct AnalysisAsymmetricPairing { runThreeProng(events, trackAssocsPerCollision, barrelAssocs, barrelTracks, VarManager::kTripleCandidateToPKPi); } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -3137,6 +3331,7 @@ struct AnalysisDileptonTrack { Configurable fConfigEnergycorrelator{"cfgEnergycorrelator", false, "Add some hist for energy correlator study"}; Configurable fConfigApplyMassEC{"cfgApplyMassEC", false, "Apply fit mass for sideband for the energy correlator study"}; Configurable> fConfigFitmassEC{"cfgTFitmassEC", std::vector{-0.541438, 2.8, 3.2}, "parameter from the fit fuction and fit range"}; + Configurable> fConfigTransRange{"cfgTransRange", std::vector{0.333333, 0.666667}, "Transverse region for the energy correlstor analysis"}; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. int fNCuts; // number of dilepton leg cuts @@ -3447,7 +3642,7 @@ struct AnalysisDileptonTrack { } // dilepton rap cut float rap = dilepton.rap(); - if (fConfigUseRapcut && abs(rap) > fConfigDileptonRapCutAbs) + if (fConfigUseRapcut && std::abs(rap) > fConfigDileptonRapCutAbs) continue; VarManager::FillTrack(dilepton, fValuesDilepton); @@ -3504,7 +3699,8 @@ struct AnalysisDileptonTrack { VarManager::FillDileptonTrackVertexing(event, lepton1, lepton2, track, fValuesHadron); // for the energy correlator analysis - VarManager::FillEnergyCorrelator(dilepton, track, fValuesHadron, fConfigApplyMassEC, fMassBkg->GetRandom()); + std::vector fTransRange = fConfigTransRange; + VarManager::FillEnergyCorrelatorTriple(lepton1, lepton2, track, fValuesHadron, fTransRange[0], fTransRange[1], fConfigApplyMassEC, fMassBkg->GetRandom()); // table to be written out for ML analysis BmesonsTable(event.runNumber(), event.globalIndex(), event.timestamp(), fValuesHadron[VarManager::kPairMass], dilepton.mass(), fValuesHadron[VarManager::kDeltaMass], fValuesHadron[VarManager::kPairPt], fValuesHadron[VarManager::kPairEta], fValuesHadron[VarManager::kPairPhi], fValuesHadron[VarManager::kPairRap], @@ -3661,7 +3857,7 @@ struct AnalysisDileptonTrack { void processBarrelMixedEvent(soa::Filtered& events, soa::Filtered> const& assocs, - MyBarrelTracksWithCov const&, soa::Filtered const& dileptons) + MyBarrelTracksWithCov const& tracks, soa::Filtered const& dileptons) { if (events.size() == 0) { return; @@ -3697,12 +3893,24 @@ struct AnalysisDileptonTrack { // loop over dileptons for (auto dilepton : evDileptons) { + // get full track info of tracks based on the index + auto lepton1 = tracks.rawIteratorAt(dilepton.index0Id()); + auto lepton2 = tracks.rawIteratorAt(dilepton.index1Id()); + // Check that the dilepton has zero charge + if (dilepton.sign() != 0) { + continue; + } + // dilepton rap cut + float rap = dilepton.rap(); + if (fConfigUseRapcut && std::abs(rap) > fConfigDileptonRapCutAbs) + continue; // compute dilepton - track quantities VarManager::FillDileptonHadron(dilepton, track, VarManager::fgValues); // for the energy correlator analysis - VarManager::FillEnergyCorrelator(dilepton, track, VarManager::fgValues, fConfigApplyMassEC, fMassBkg->GetRandom()); + std::vector fTransRange = fConfigTransRange; + VarManager::FillEnergyCorrelatorTriple(lepton1, lepton2, track, fValuesHadron, fTransRange[0], fTransRange[1], fConfigApplyMassEC, fMassBkg->GetRandom()); // loop over dilepton leg cuts and track cuts and fill histograms separately for each combination for (int icut = 0; icut < fNCuts; icut++) { @@ -3768,7 +3976,7 @@ struct AnalysisDileptonTrack { } // end event loop } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -4023,7 +4231,7 @@ struct AnalysisDileptonTrackTrack { } } - void processDummy(MyEvents&) + void processDummy(MyEventsBasic&) { // do nothing } @@ -4092,6 +4300,10 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); } + if (classStr.Contains("Pairing")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "event", histName); + } + if (classStr.Contains("Triplets")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); } diff --git a/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx new file mode 100644 index 00000000000..3fa16a5d80d --- /dev/null +++ b/PWGDQ/Tasks/tableReader_withAssoc_direct.cxx @@ -0,0 +1,1893 @@ +// 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 +// Configurable workflow for running several DQ or other PWG analyses + +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/MixingHandler.h" +#include "PWGDQ/Core/MixingLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/PID/PIDTOFParamService.h" +#include "Common/Core/TableHelper.h" +#include "Common/Core/Zorro.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; +using namespace o2::common::core; + +Zorro zorro; + +// Some definitions +namespace o2::aod +{ +namespace dqanalysisflags +{ +DECLARE_SOA_COLUMN(MixingHash, mixingHash, int); //! Hash used in event mixing +DECLARE_SOA_BITMAP_COLUMN(IsEventSelected, isEventSelected, 32); //! Event decision +DECLARE_SOA_BITMAP_COLUMN(IsBarrelSelected, isBarrelSelected, 32); //! Barrel track decisions +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(IsBarrelSelectedPrefilter, isBarrelSelectedPrefilter, 32); //! Barrel prefilter decisions + +// Bcandidate columns +DECLARE_SOA_COLUMN(RunNumber, runNumber, uint64_t); +DECLARE_SOA_COLUMN(EventIdx, eventIdx, uint64_t); +DECLARE_SOA_COLUMN(EventTimestamp, eventTimestamp, uint64_t); +DECLARE_SOA_COLUMN(massBcandidate, MBcandidate, float); +DECLARE_SOA_COLUMN(MassDileptonCandidate, massDileptonCandidate, float); +DECLARE_SOA_COLUMN(deltaMassBcandidate, deltaMBcandidate, float); +DECLARE_SOA_COLUMN(pTBcandidate, PtBcandidate, float); +DECLARE_SOA_COLUMN(EtaBcandidate, etaBcandidate, float); +DECLARE_SOA_COLUMN(PhiBcandidate, phiBcandidate, float); +DECLARE_SOA_COLUMN(RapBcandidate, rapBcandidate, float); +DECLARE_SOA_COLUMN(LxyBcandidate, lxyBcandidate, float); +DECLARE_SOA_COLUMN(LxyBcandidateErr, lxyBcandidateErr, float); +DECLARE_SOA_COLUMN(LxyzBcandidate, lxyzBcandidate, float); +DECLARE_SOA_COLUMN(LxyzBcandidateErr, lxyzBcandidateErr, float); +DECLARE_SOA_COLUMN(LzBcandidate, lzBcandidate, float); +DECLARE_SOA_COLUMN(LzBcandidateErr, lzBcandidateErr, float); +DECLARE_SOA_COLUMN(TauxyBcandidate, tauxyBcandidate, float); +DECLARE_SOA_COLUMN(TauxyBcandidateErr, tauxyBcandidateErr, float); +DECLARE_SOA_COLUMN(TauzBcandidate, tauzBcandidate, float); +DECLARE_SOA_COLUMN(TauzBcandidateErr, tauzBcandidateErr, float); +DECLARE_SOA_COLUMN(CosPBcandidate, cosPBcandidate, float); +DECLARE_SOA_COLUMN(Chi2Bcandidate, chi2Bcandidate, float); +DECLARE_SOA_COLUMN(GlobalIndexassoc, globalIndexassoc, uint64_t); +DECLARE_SOA_COLUMN(GlobalIndexleg1, globalIndexleg1, uint64_t); +DECLARE_SOA_COLUMN(GlobalIndexleg2, globalIndexleg2, uint64_t); +DECLARE_SOA_COLUMN(Ptassoc, ptassoc, float); +DECLARE_SOA_COLUMN(PINassoc, pINassoc, float); +DECLARE_SOA_COLUMN(Etaassoc, etaassoc, float); +DECLARE_SOA_COLUMN(Phiassoc, phiassoc, float); +DECLARE_SOA_COLUMN(Ptpair, ptpair, float); +DECLARE_SOA_COLUMN(Etapair, etapair, float); +DECLARE_SOA_COLUMN(Ptleg1, ptleg1, float); +DECLARE_SOA_COLUMN(PINleg1, pINleg1, float); +DECLARE_SOA_COLUMN(Etaleg1, etaleg1, float); +DECLARE_SOA_COLUMN(Phileg1, phileg1, float); +DECLARE_SOA_COLUMN(Ptleg2, ptleg2, float); +DECLARE_SOA_COLUMN(PINleg2, pINleg2, float); +DECLARE_SOA_COLUMN(Etaleg2, etaleg2, float); +DECLARE_SOA_COLUMN(Phileg2, phileg2, float); +DECLARE_SOA_COLUMN(TPCnsigmaKaassoc, tpcnsigmaKaassoc, float); +DECLARE_SOA_COLUMN(TPCnsigmaPiassoc, tpcnsigmaPiassoc, float); +DECLARE_SOA_COLUMN(TPCnsigmaPrassoc, tpcnsigmaPrassoc, float); +DECLARE_SOA_COLUMN(TOFnsigmaKaassoc, tofnsigmaKaassoc, float); +DECLARE_SOA_COLUMN(TPCnsigmaElleg1, tpcnsigmaElleg1, float); +DECLARE_SOA_COLUMN(TPCnsigmaPileg1, tpcnsigmaPileg1, float); +DECLARE_SOA_COLUMN(TPCnsigmaPrleg1, tpcnsigmaPrleg1, float); +DECLARE_SOA_COLUMN(TPCnsigmaElleg2, tpcnsigmaElleg2, float); +DECLARE_SOA_COLUMN(TPCnsigmaPileg2, tpcnsigmaPileg2, float); +DECLARE_SOA_COLUMN(TPCnsigmaPrleg2, tpcnsigmaPrleg2, float); +DECLARE_SOA_COLUMN(ITSClusterMapassoc, itsClusterMapassoc, uint8_t); +DECLARE_SOA_COLUMN(ITSClusterMapleg1, itsClusterMapleg1, uint8_t); +DECLARE_SOA_COLUMN(ITSClusterMapleg2, itsClusterMapleg2, uint8_t); +DECLARE_SOA_COLUMN(ITSChi2assoc, itsChi2assoc, float); +DECLARE_SOA_COLUMN(ITSChi2leg1, itsChi2leg1, float); +DECLARE_SOA_COLUMN(ITSChi2leg2, itsChi2leg2, float); +DECLARE_SOA_COLUMN(TPCNclsassoc, tpcNclsassoc, float); +DECLARE_SOA_COLUMN(TPCNclsleg1, tpcNclsleg1, float); +DECLARE_SOA_COLUMN(TPCNclsleg2, tpcNclsleg2, float); +DECLARE_SOA_COLUMN(TPCChi2assoc, tpcChi2assoc, float); +DECLARE_SOA_COLUMN(TPCChi2leg1, tpcChi2leg1, float); +DECLARE_SOA_COLUMN(TPCChi2leg2, tpcChi2leg2, float); +DECLARE_SOA_BITMAP_COLUMN(IsJpsiFromBSelected, isJpsiFromBSelected, 32); +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); + +DECLARE_SOA_COLUMN(Massee, massee, float); +DECLARE_SOA_COLUMN(Etaee, etaee, float); +DECLARE_SOA_COLUMN(Rapee, rapee, float); +DECLARE_SOA_COLUMN(Phiee, phiee, float); +DECLARE_SOA_COLUMN(Ptee, ptee, float); +DECLARE_SOA_COLUMN(Lxyee, lxyee, float); +DECLARE_SOA_COLUMN(LxyeePoleMass, lxyeepolemass, float); +DECLARE_SOA_COLUMN(Lzee, lzee, float); +DECLARE_SOA_COLUMN(LxyeePoleMassPVrecomputed, lxyeePoleMassPVrecomputed, float); +DECLARE_SOA_COLUMN(MultiplicityFT0A, multiplicityFT0AJPsi2ee, float); +DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0CJPsi2ee, float); +DECLARE_SOA_COLUMN(PercentileFT0M, percentileFT0MJPsi2ee, float); +DECLARE_SOA_COLUMN(MultiplicityNContrib, multiplicityNContribJPsi2ee, float); +DECLARE_SOA_COLUMN(AmbiguousInBunchPairs, AmbiguousJpsiPairsInBunch, bool); +DECLARE_SOA_COLUMN(AmbiguousOutOfBunchPairs, AmbiguousJpsiPairsOutOfBunch, bool); +DECLARE_SOA_COLUMN(Corrassoc, corrassoc, bool); +} // namespace dqanalysisflags + +DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTS", dqanalysisflags::IsEventSelected); +DECLARE_SOA_TABLE(MixingHashes, "AOD", "DQANAMIXHASHA", dqanalysisflags::MixingHash); +DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "DQANATRKCUTS", dqanalysisflags::IsBarrelSelected); +DECLARE_SOA_TABLE(BarrelAmbiguities, "AOD", "DQBARRELAMB", dqanalysisflags::BarrelAmbiguityInBunch, dqanalysisflags::BarrelAmbiguityOutOfBunch); +DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSelectedPrefilter); + +DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", + dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Etaee, dqanalysisflags::Rapee, + dqanalysisflags::Phiee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::LxyeePoleMassPVrecomputed, + dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, + dqanalysisflags::MultiplicityFT0A, dqanalysisflags::MultiplicityFT0C, dqanalysisflags::PercentileFT0M, dqanalysisflags::MultiplicityNContrib); + +DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", + dqanalysisflags::RunNumber, dqanalysisflags::EventIdx, dqanalysisflags::EventTimestamp, + dqanalysisflags::massBcandidate, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::deltaMassBcandidate, + dqanalysisflags::pTBcandidate, dqanalysisflags::EtaBcandidate, dqanalysisflags::PhiBcandidate, dqanalysisflags::RapBcandidate, + dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyBcandidateErr, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LxyzBcandidateErr, + dqanalysisflags::LzBcandidate, dqanalysisflags::LzBcandidateErr, dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauxyBcandidateErr, + dqanalysisflags::TauzBcandidate, dqanalysisflags::TauzBcandidateErr, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, + dqanalysisflags::GlobalIndexassoc, dqanalysisflags::GlobalIndexleg1, dqanalysisflags::GlobalIndexleg2, + dqanalysisflags::PINassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, + dqanalysisflags::PINleg1, dqanalysisflags::Etaleg1, dqanalysisflags::PINleg2, dqanalysisflags::Etaleg2, + dqanalysisflags::TPCnsigmaKaassoc, dqanalysisflags::TPCnsigmaPiassoc, dqanalysisflags::TPCnsigmaPrassoc, dqanalysisflags::TOFnsigmaKaassoc, + dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::TPCnsigmaPileg1, dqanalysisflags::TPCnsigmaPrleg1, + dqanalysisflags::TPCnsigmaElleg2, dqanalysisflags::TPCnsigmaPileg2, dqanalysisflags::TPCnsigmaPrleg2, + dqanalysisflags::ITSClusterMapassoc, dqanalysisflags::ITSClusterMapleg1, dqanalysisflags::ITSClusterMapleg2, + dqanalysisflags::ITSChi2assoc, dqanalysisflags::ITSChi2leg1, dqanalysisflags::ITSChi2leg2, + dqanalysisflags::TPCNclsassoc, dqanalysisflags::TPCNclsleg1, dqanalysisflags::TPCNclsleg2, + dqanalysisflags::TPCChi2assoc, dqanalysisflags::TPCChi2leg1, dqanalysisflags::TPCChi2leg2, + dqanalysisflags::IsJpsiFromBSelected, dqanalysisflags::IsBarrelSelected); +} // namespace o2::aod + +// Using definitions (data-only) +using MyEvents = soa::Join; +using MyEventsSelected = soa::Join; +using MyEventsHashSelected = soa::Join; + +using MyBarrelTracksWithCov = soa::Join; +using MyBarrelTracksWithCovNoTOF = soa::Join; +using MyBarrelTracksWithCovWithAmbiguities = soa::Join; + +using MyDielectronCandidates = soa::Join; + +// bit maps used for the Fill functions of the VarManager +constexpr static uint32_t gkEventFillMapWithMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult | VarManager::ObjTypes::CollisionMultExtra; +constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackPID; +constexpr static uint32_t gkTrackFillMapWithCovNoTOF = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackCov | VarManager::ObjTypes::TrackTPCPID | VarManager::ObjTypes::TrackTOFService; + +// Global function used to define needed histogram classes +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups); // defines histograms for all tasks + +template +void PrintBitMap(TMap map, int nbits) +{ + for (int i = 0; i < nbits; i++) { + cout << ((map & (TMap(1) << i)) > 0 ? "1" : "0"); + } +} + +// Enum containing the ordering of statistics histograms to be written in the QA file +enum ZorroStatHist { + kStatsZorroInfo = 0, + kStatsZorroSel +}; + +struct AnalysisEventSelection { + Produces eventSel; + Produces hash; + OutputObj fOutputList{"output"}; + OutputObj fStatsList{"Statistics"}; + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariablesJson{"cfgMixingVarsJSON", "", "Mixing configs in JSON format"}; + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; + Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Add event histograms defined via JSON formatting (see HistogramsLibrary)"}; + + Configurable fConfigSplitCollisionsDeltaZ{"cfgSplitCollisionsDeltaZ", 1.0, "maximum delta-z (cm) between two collisions to consider them as split candidates"}; + Configurable fConfigSplitCollisionsDeltaBC{"cfgSplitCollisionsDeltaBC", 100, "maximum delta-BC between two collisions to consider them as split candidates; do not apply if value is negative"}; + Configurable fConfigCheckSplitCollisions{"cfgCheckSplitCollisions", false, "If true, run the split collision check and fill histograms"}; + + // Zorro selection + struct : ConfigurableGroup { + Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro"}; + Configurable fConfigZorroTrigMask{"cfgZorroTriggerMask", "fDiMuon", "DQ Trigger masks: fSingleE,fLMeeIMR,fLMeeHMR,fDiElectron,fSingleMuLow,fSingleMuHigh,fDiMuon"}; + Configurable fConfigRunZorroSel{"cfgRunZorroSel", false, "Select events with trigger mask"}; + Configurable fBcTolerance{"cfgBcTolerance", 100, "Number of BCs of margin for software triggers"}; + Configurable fConfigCcdbPathZorro{"ccdb-path-zorro", "/Users/m/mpuccio/EventFiltering/OTS/Chunked/", "base path to the ccdb object for zorro"}; + } fConfigZorro; + + // RCT selection + struct : ConfigurableGroup { + Configurable fConfigUseRCT{"cfgUseRCT", false, "Enable event selection with RCT flags"}; + Configurable fCheckZDC{"cfgCheckZDC", false, "Check ZDC quality in the RCT flag checker"}; + Configurable fConfigRCTLabel{"cfgRCTLabel", "CBT", "RCT flag labels : CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo"}; + } fConfigRCT; + + // CCDB connection configurables + struct : ConfigurableGroup { + 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 fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable fConfigGrpMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fZShiftPath{"zShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable fConfigGrpMagPathRun2{"grpmagPathRun2", "GLO/GRP/GRP", "CCDB path of the GRPObject (Usage for Run 2)"}; + } fConfigCCDB; + + // TPC postcalibration related options + struct : ConfigurableGroup { + Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas(electrons, pions, protons)"}; + Configurable fConfigTPCpostCalibType{"cfgTPCpostCalibType", 1, "1: (TPCncls,pIN,eta) calibration typically for pp, 2: (eta,nPV,nLong,tLong) calibration typically for PbPb"}; + Configurable fConfigTPCuseInterpolatedCalib{"cfgTPCpostCalibUseInterpolation", true, "If true, use interpolated calibration values (default: true)"}; + Configurable fConfigComputeTPCpostCalibKaon{"cfgTPCpostCalibKaon", false, "If true, compute TPC post-calibrated n-sigmas for kaons"}; + Configurable fConfigIsOnlyforMaps{"cfgIsforMaps", false, "If true, run for postcalibration maps only"}; + Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; + } fConfigPostCalibTPC; + + Configurable fIsRun2{"cfgIsRun2", false, "Whether we analyze Run-2 or Run-3 data"}; + + // RCT flag checker + o2::aod::rctsel::RCTFlagsChecker rctChecker{"CBT"}; + + HistogramManager* fHistMan = nullptr; + MixingHandler* fMixHandler = nullptr; + + AnalysisCompositeCut* fEventCut; + + o2::parameters::GRPObject* fGrpMagRun2 = nullptr; // for run 2, we access the GRPObject from GLO/GRP/GRP + o2::parameters::GRPMagField* fGrpMag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField + + Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; + + 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 + int fCurrentRun; + + void init(o2::framework::InitContext& context) + { + cout << "AnalysisEventSelection::init() called" << endl; + if (context.mOptions.get("processDummy")) { + return; + } + VarManager::SetDefaultVarNames(); + + fEventCut = new AnalysisCompositeCut(true); + TString eventCutStr = fConfigEventCuts.value; + if (eventCutStr != "") { + AnalysisCut* cut = dqcuts::GetAnalysisCut(eventCutStr.Data()); + if (cut != nullptr) { + fEventCut->AddCut(cut); + } + } + + // Additional cuts via JSON + TString eventCutJSONStr = fConfigEventCutsJSON.value; + if (eventCutJSONStr != "") { + std::vector jsonCuts = dqcuts::GetCutsFromJSON(eventCutJSONStr.Data()); + for (auto& cutIt : jsonCuts) { + fEventCut->AddCut(cutIt); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + + if (fConfigQA) { + fHistMan = new HistogramManager("analysisHistos", "", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + DefineHistograms(fHistMan, "TimeFrameStats;Event_BeforeCuts;Event_AfterCuts;", fConfigAddEventHistogram.value.data()); + if (fConfigCheckSplitCollisions) { + DefineHistograms(fHistMan, "OutOfBunchCorrelations;SameBunchCorrelations;", ""); + } + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); + VarManager::SetUseVars(fHistMan->GetUsedVars()); + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + // Zorro information: kStatsZorroInfo + // Zorro trigger selection: kStatsZorroSel + fStatsList.setObject(new TList()); + fStatsList->SetOwner(kTRUE); + TH2D* histZorroInfo = new TH2D("ZorroInfo", "Zorro information", 1, -0.5, 0.5, 1, -0.5, 0.5); + fStatsList->AddAt(histZorroInfo, kStatsZorroInfo); + + TH2D* histZorroSel = new TH2D("ZorroSel", "trigger of interested", 1, -0.5, 0.5, 1, -0.5, 0.5); + fStatsList->AddAt(histZorroSel, kStatsZorroSel); + + TString mixVarsString = fConfigMixingVariables.value; + TString mixVarsJsonString = fConfigMixingVariablesJson.value; + std::unique_ptr objArray(mixVarsString.Tokenize(",")); + if (objArray->GetEntries() > 0 || mixVarsJsonString != "") { + fMixHandler = new MixingHandler("mixingHandler", "mixing handler"); + fMixHandler->Init(); + if (objArray->GetEntries() > 0) { + for (int iVar = 0; iVar < objArray->GetEntries(); ++iVar) { + dqmixing::SetUpMixing(fMixHandler, objArray->At(iVar)->GetName()); + } + } + if (mixVarsJsonString != "") { + dqmixing::SetUpMixingFromJSON(fMixHandler, mixVarsJsonString.Data()); + } + } + + fCurrentRun = -1; + fCCDB->setURL(fConfigCCDB.fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDB->setCreatedNotAfter(fConfigCCDB.fConfigNoLaterThan.value); + fCCDBApi.init(fConfigCCDB.fConfigCcdbUrl.value); + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + fCCDB->get(fConfigCCDB.fConfigGeoPath.value); + } + + if (fConfigRCT.fConfigUseRCT.value) { + rctChecker.init(fConfigRCT.fConfigRCTLabel, fConfigRCT.fCheckZDC.value); + } + + cout << "AnalysisEventSelection::init() completed" << endl; + } + + template + void runEventSelection(TEvents const& events, BCsWithTimestamps const& bcs) + { + cout << "AnalysisEventSelection::runEventSelection() called with " << events.size() << " events and " << bcs.size() << " BCs" << endl; + + if (bcs.size() > 0 && fCurrentRun != bcs.begin().runNumber()) { + if (fConfigPostCalibTPC.fConfigComputeTPCpostCalib) { + auto calibList = fCCDB->getForTimeStamp(fConfigCCDB.fConfigCcdbPathTPC.value, bcs.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 (fConfigPostCalibTPC.fConfigComputeTPCpostCalibKaon) { + VarManager::SetCalibrationObject(VarManager::kTPCKaonMean, calibList->FindObject("mean_map_kaon")); + VarManager::SetCalibrationObject(VarManager::kTPCKaonSigma, calibList->FindObject("sigma_map_kaon")); + } + if (fConfigPostCalibTPC.fConfigTPCpostCalibType == 2) { + VarManager::SetCalibrationObject(VarManager::kTPCElectronStatus, calibList->FindObject("status_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionStatus, calibList->FindObject("status_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonStatus, calibList->FindObject("status_map_proton")); + if (fConfigPostCalibTPC.fConfigComputeTPCpostCalibKaon) { + VarManager::SetCalibrationObject(VarManager::kTPCKaonStatus, calibList->FindObject("status_map_kaon")); + } + } + VarManager::SetCalibrationType(fConfigPostCalibTPC.fConfigTPCpostCalibType, fConfigPostCalibTPC.fConfigTPCuseInterpolatedCalib); + } + if (fIsRun2 == true) { + fGrpMagRun2 = fCCDB->getForTimeStamp(fConfigCCDB.fConfigGrpMagPathRun2, bcs.begin().timestamp()); + if (fGrpMagRun2 != nullptr) { + o2::base::Propagator::initFieldFromGRP(fGrpMagRun2); + } + } else { + fGrpMag = fCCDB->getForTimeStamp(fConfigCCDB.fConfigGrpMagPath, bcs.begin().timestamp()); + auto* fZShift = fCCDB->getForTimeStamp>(fConfigCCDB.fZShiftPath, bcs.begin().timestamp()); + if (fGrpMag != nullptr) { + o2::base::Propagator::initFieldFromGRP(fGrpMag); + VarManager::SetMagneticField(fGrpMag->getNominalL3Field()); + } + if (fZShift != nullptr && !fZShift->empty()) { + VarManager::SetZShift((*fZShift)[0]); + } + /*if (fConfigVariousOptions.fPropMuon) { + VarManager::SetupMuonMagField(); + }*/ + } + 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(); + } // end updating the CCDB quantities at change of run + + cout << "Filling TimeFrame statistics histograms" << endl; + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillTimeFrame(bcs); + VarManager::FillTimeFrame(events); + if (fConfigQA) { + fHistMan->FillHistClass("TimeFrameStats", VarManager::fgValues); + } + + fSelMap.clear(); + fBCCollMap.clear(); + + cout << "Starting event loop for event selection" << endl; + for (auto& event : events) { + auto bc = event.template bc_as(); + + VarManager::ResetValues(VarManager::kNTFWiseVariables, VarManager::kNEventWiseVariables); + VarManager::FillBC(bc); + VarManager::FillEvent(event); + + bool decision = false; + if (fConfigQA) { + fHistMan->FillHistClass("Event_BeforeCuts", VarManager::fgValues); + } + + if (fConfigZorro.fConfigRunZorro) { + zorro.setBaseCCDBPath(fConfigZorro.fConfigCcdbPathZorro.value); + zorro.setBCtolerance(fConfigZorro.fBcTolerance); + zorro.initCCDB(fCCDB.service, fCurrentRun, bc.timestamp(), fConfigZorro.fConfigZorroTrigMask.value); + zorro.populateExternalHists(fCurrentRun, reinterpret_cast(fStatsList->At(kStatsZorroInfo)), reinterpret_cast(fStatsList->At(kStatsZorroSel))); + + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !rctChecker(event))) { + continue; + } + + bool zorroSel = zorro.isSelected(bc.globalBC(), fConfigZorro.fBcTolerance, reinterpret_cast(fStatsList->At(kStatsZorroSel))); + if (fConfigZorro.fConfigRunZorroSel && (!zorroSel)) { + continue; + } + } else { + + if (!fEventCut->IsSelected(VarManager::fgValues) || (fConfigRCT.fConfigUseRCT.value && !rctChecker(event))) { + continue; + } + } + + decision = true; + if (fConfigQA) { + fHistMan->FillHistClass("Event_AfterCuts", VarManager::fgValues); + } + + fSelMap[event.globalIndex()] = decision; + if (fBCCollMap.find(bc.globalBC()) == fBCCollMap.end()) { + std::vector evIndices = {event.globalIndex()}; + fBCCollMap[bc.globalBC()] = evIndices; + } else { + auto& evIndices = fBCCollMap[bc.globalBC()]; + evIndices.push_back(event.globalIndex()); + } + if (fMixHandler != nullptr) { + int hh = fMixHandler->FindEventCategory(VarManager::fgValues); + hash(hh); + } + } + + cout << "AnalysisEventSelection::runEventSelection() completed" << endl; + } + + template + void publishSelections(TEvents const& events) + { + cout << "AnalysisEventSelection::publishSelections() called" << endl; + std::map collisionSplittingMap; // key: event global index, value: whether pileup event is a possible splitting + + // Reset the fValues array and fill event observables + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + + // loop over the BC map, get the collision vectors and make in-bunch and out of bunch 2-event correlations + for (auto bc1It = fBCCollMap.begin(); bc1It != fBCCollMap.end(); ++bc1It) { + uint64_t bc1 = bc1It->first; + auto const& bc1Events = bc1It->second; + + // same bunch event correlations, if more than 1 collisions in this bunch + if (bc1Events.size() > 1) { + for (auto ev1It = bc1Events.begin(); ev1It != bc1Events.end(); ++ev1It) { + auto ev1 = events.rawIteratorAt(*ev1It); + for (auto ev2It = std::next(ev1It); ev2It != bc1Events.end(); ++ev2It) { + auto ev2 = events.rawIteratorAt(*ev2It); + // compute 2-event quantities and mark the candidate split collisions + VarManager::FillTwoEvents(ev1, ev2); + if (TMath::Abs(VarManager::fgValues[VarManager::kTwoEvDeltaZ]) < fConfigSplitCollisionsDeltaZ) { // this is a possible collision split + collisionSplittingMap[*ev1It] = true; + collisionSplittingMap[*ev2It] = true; + } + if (fConfigQA) { + fHistMan->FillHistClass("SameBunchCorrelations", VarManager::fgValues); + } + } // end second event loop + } // end first event loop + } // end if BC1 events > 1 + + // loop over the following BCs in the TF + for (auto bc2It = std::next(bc1It); bc2It != fBCCollMap.end(); ++bc2It) { + uint64_t bc2 = bc2It->first; + if ((bc2 > bc1 ? bc2 - bc1 : bc1 - bc2) > fConfigSplitCollisionsDeltaBC) { + break; + } + auto const& bc2Events = bc2It->second; + + // loop over events in the first BC + for (auto ev1It : bc1Events) { + auto ev1 = events.rawIteratorAt(ev1It); + // loop over events in the second BC + for (auto ev2It : bc2Events) { + auto ev2 = events.rawIteratorAt(ev2It); + // compute 2-event quantities and mark the candidate split collisions + VarManager::FillTwoEvents(ev1, ev2); + if (TMath::Abs(VarManager::fgValues[VarManager::kTwoEvDeltaZ]) < fConfigSplitCollisionsDeltaZ) { // this is a possible collision split + collisionSplittingMap[ev1It] = true; + collisionSplittingMap[ev2It] = true; + } + if (fConfigQA) { + fHistMan->FillHistClass("OutOfBunchCorrelations", VarManager::fgValues); + } + } + } + } + } + + // publish the table + uint32_t evSel = static_cast(0); + for (auto& event : events) { + evSel = 0; + if (fSelMap[event.globalIndex()]) { // event passed the user cuts + evSel |= (static_cast(1) << 0); + } + auto bc = event.template bc_as(); + std::vector sameBunchEvents = fBCCollMap[bc.globalBC()]; + if (sameBunchEvents.size() > 1) { // event with in-bunch pileup + evSel |= (static_cast(1) << 1); + } + if (collisionSplittingMap.find(event.globalIndex()) != collisionSplittingMap.end()) { // event with possible fake in-bunch pileup (collision splitting) + evSel |= (static_cast(1) << 2); + } + eventSel(evSel); + } + cout << "AnalysisEventSelection::publishSelections() completed" << endl; + } + + void processDirect(MyEvents const& events, BCsWithTimestamps const& bcs) + { + cout << "AnalysisEventSelection::processDirect() called" << endl; + runEventSelection(events, bcs); + publishSelections(events); + cout << "AnalysisEventSelection::processDirect() completed" << endl; + } + + void processDummy(aod::Collisions&) {} + + PROCESS_SWITCH(AnalysisEventSelection, processDirect, "Run event selection on framework AO2Ds", false); + PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", true); +}; + +struct AnalysisTrackSelection { + + Produces trackSel; + Produces trackAmbiguities; + OutputObj fOutputList{"output"}; + + Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigCutsJSON{"cfgBarrelTrackCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + Configurable fConfigPublishAmbiguity{"cfgPublishAmbiguity", true, "If true, publish ambiguity table and fill QA histograms"}; + 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 grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + + Service fCCDB; + Service fTofResponse; + + HistogramManager* fHistMan; + std::vector fTrackCuts; + std::vector fHistNamesReco; + + int fCurrentRun; // current run (needed to detect run changes for loading CCDB parameters) + + 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) + + void init(o2::framework::InitContext& context) + { + cout << "AnalysisTrackSelection::init() called" << endl; + if (context.mOptions.get("processDummy")) + return; + + VarManager::SetDefaultVarNames(); + fCurrentRun = 0; + + // Setup track cuts + TString cutNamesStr = fConfigCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fTrackCuts.push_back(dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + + // Extra cuts from JSON + TString addTrackCutsStr = fConfigCutsJSON.value; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (auto& t : addTrackCuts) { + fTrackCuts.push_back(reinterpret_cast(t)); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + + // Setup histogram manager + if (fConfigQA) { + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // Configure histogram classes for each track cut; + TString histClasses = "TimeFrameStats;AssocsBarrel_BeforeCuts;"; + for (auto& cut : fTrackCuts) { + TString nameStr = Form("AssocsBarrel_%s", cut->GetName()); + fHistNamesReco.push_back(nameStr); + histClasses += Form("%s;", nameStr.Data()); + } + + DefineHistograms(fHistMan, histClasses.Data(), fConfigAddTrackHistogram.value.data()); + if (fConfigPublishAmbiguity) { + DefineHistograms(fHistMan, "TrackBarrel_AmbiguityInBunch;TrackBarrel_AmbiguityOutOfBunch;", "ambiguity"); + } + + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + fCCDB->setURL(fConfigCcdbUrl.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); + fTofResponse->initSetup(fCCDB, context); + + cout << "AnalysisTrackSelection::init() completed" << endl; + } + + template + void runTrackSelection(TrackAssoc const& assocs, BCsWithTimestamps const& bcs, TEvents const& events, TTracks const& tracks) + { + cout << "AnalysisTrackSelection::runTrackSelection() called" << endl; + // determine if TEvents table contains aod::Collisions + // bool hasCollisions = std::is_same::value; + + fNAssocsInBunch.clear(); + fNAssocsOutOfBunch.clear(); + + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillTimeFrame(events); + VarManager::FillTimeFrame(tracks); + if (fConfigQA) + fHistMan->FillHistClass("TimeFrameStats", VarManager::fgValues); + + 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")); + 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, bcs.begin().timestamp()); + if (grpmag != nullptr) { + VarManager::SetMagneticField(grpmag->getNominalL3Field()); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", bcs.begin().timestamp()); + } + fCurrentRun = bcs.begin().runNumber(); + } + + trackSel.reserve(assocs.size()); + trackAmbiguities.reserve(tracks.size()); + + cout << "Starting loop over track associations" << endl; + + for (auto& assoc : assocs) { + auto event = assoc.template collision_as(); + if (!event.isEventSelected_bit(0)) { + trackSel(0); + continue; + } + + /// + auto track = tracks.rawIteratorAt(assoc.trackId()); + auto evFromTrack = events.rawIteratorAt(track.collisionId()); + if (!evFromTrack.isEventSelected_bit(0)) { + trackSel(0); + continue; + } + + VarManager::ResetValues(VarManager::kNTFWiseVariables, VarManager::kNBarrelTrackVariables); + // fill event information which might be needed in histograms/cuts that combine track and event properties + VarManager::FillEvent(event); + + VarManager::FillTrack(track); + // compute quantities which depend on the associated collision, such as DCA + if (track.collisionId() != event.globalIndex()) + VarManager::FillTrackCollision(track, event); + + if (fConfigQA) + fHistMan->FillHistClass("AssocsBarrel_BeforeCuts", VarManager::fgValues); + + int iCut = 0; + uint32_t filterMap = static_cast(0); + for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); cut++, iCut++) { + if ((*cut)->IsSelected(VarManager::fgValues)) { + filterMap |= (static_cast(1) << iCut); + if (fConfigQA) { + fHistMan->FillHistClass(fHistNamesReco[iCut], VarManager::fgValues); + } + } + } // end loop over cuts + trackSel(filterMap); + + // count the number of associations per track + if (fConfigPublishAmbiguity && filterMap > 0) { + if (event.isEventSelected_bit(1)) { + // for this track, count the number of associated collisions with in-bunch pileup and out of bunch associations + 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 associations + + // QA the collision-track associations + // TODO: some tracks can be associated to both collisions that have in bunch pileup and collisions from different bunches + // So one could QA these tracks separately + if (fConfigPublishAmbiguity) { + if (fConfigQA) { + for (auto& [trackIdx, evIndices] : fNAssocsInBunch) { + if (evIndices.size() == 1) { + continue; + } + auto track = tracks.rawIteratorAt(trackIdx); + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + VarManager::FillTrack(track); + VarManager::fgValues[VarManager::kBarrelNAssocsInBunch] = static_cast(evIndices.size()); + fHistMan->FillHistClass("TrackBarrel_AmbiguityInBunch", VarManager::fgValues); + } // end loop over in-bunch ambiguous tracks + + for (auto& [trackIdx, evIndices] : fNAssocsOutOfBunch) { + if (evIndices.size() == 1) { + continue; + } + auto track = tracks.rawIteratorAt(trackIdx); + VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + VarManager::FillTrack(track); + VarManager::fgValues[VarManager::kBarrelNAssocsOutOfBunch] = static_cast(evIndices.size()); + fHistMan->FillHistClass("TrackBarrel_AmbiguityOutOfBunch", VarManager::fgValues); + } // end loop over out-of-bunch ambiguous tracks + } + + // publish the ambiguity table + for (auto& track : tracks) { + 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(); + } + trackAmbiguities(nInBunch, nOutOfBunch); + } + } + + cout << "AnalysisTrackSelection::runTrackSelection() completed" << endl; + } + + void processWithCov(TrackAssoc const& assocs, BCsWithTimestamps const& bcs, MyEventsSelected const& events, MyBarrelTracksWithCov const& tracks) + { + cout << "AnalysisTrackSelection::processWithCov() called" << endl; + runTrackSelection(assocs, bcs, events, tracks); + cout << "AnalysisTrackSelection::processWithCov() completed" << endl; + } + + void processWithCovTOFService(TrackAssoc const& assocs, BCsWithTimestamps const& bcs, MyEventsSelected const& events, MyBarrelTracksWithCovNoTOF const& tracks) + { + cout << "AnalysisTrackSelection::processWithCovTOFService() called" << endl; + fTofResponse->processSetup(bcs.iteratorAt(0)); + auto tracksWithTOFservice = soa::Attach(tracks); + runTrackSelection(assocs, bcs, events, tracksWithTOFservice); + cout << "AnalysisTrackSelection::processWithCovTOFService() completed" << endl; + } + + void processDummy(MyEvents&) {} + + PROCESS_SWITCH(AnalysisTrackSelection, processWithCov, "Run barrel track selection on DQ skimmed tracks w/ cov matrix associations", false); + PROCESS_SWITCH(AnalysisTrackSelection, processWithCovTOFService, "Run barrel track selection on DQ skimmed tracks w/ cov matrix associations, with TOF service", false); + PROCESS_SWITCH(AnalysisTrackSelection, processDummy, "Dummy function", true); +}; + +struct AnalysisPrefilterSelection { + Produces prefilter; // joinable with TracksAssoc + + // Configurables + 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", false, "Propagate tracks to associated collision to recalculate DCA and momentum vector"}; + + std::map fPrefilterMap; + AnalysisCompositeCut* fPairCut; + uint32_t fPrefilterMask; + int fPrefilterCutBit; + + Preslice trackAssocsPerCollision = aod::track_association::collisionId; + + void init(o2::framework::InitContext& context) + { + cout << "AnalysisPrefilterSelection::init() called" << endl; + if (context.mOptions.get("processDummy")) { + return; + } + + bool runPrefilter = true; + // get the list of track cuts to be prefiltered + TString trackCutsStr = fConfigTrackCuts.value; + TObjArray* objArrayTrackCuts = nullptr; + if (!trackCutsStr.IsNull()) { + objArrayTrackCuts = trackCutsStr.Tokenize(","); + if (objArrayTrackCuts == nullptr) { + runPrefilter = false; + } + } else { + LOG(warn) << " No track cuts to prefilter! Prefilter will not be run"; + runPrefilter = false; + } + // get the cut to be used as loose selection + TString prefilterTrackCutStr = fConfigPrefilterTrackCut.value; + if (prefilterTrackCutStr.IsNull()) { + LOG(warn) << " No prefilter loose selection specified! Prefilter will not be run"; + runPrefilter = false; + } + + fPrefilterMask = 0; + fPrefilterCutBit = -1; + if (runPrefilter) { + // get the list of cuts that were computed in the barrel track-selection task and create a bit mask + // to mark just the ones we want to apply a prefilter on + string trackCuts; + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", trackCuts, false); + TString allTrackCutsStr = trackCuts; + // check also the cuts added via JSON and add them to the string of cuts + getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", trackCuts, false); + TString addTrackCutsStr = trackCuts; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (auto& t : addTrackCuts) { + allTrackCutsStr += Form(",%s", t->GetName()); + } + } + + std::unique_ptr objArray(allTrackCutsStr.Tokenize(",")); + if (objArray == nullptr) { + LOG(fatal) << " Not getting any track cuts from the barrel-track-selection "; + } + if (objArray->FindObject(prefilterTrackCutStr.Data()) == nullptr) { + LOG(fatal) << " Prefilter track cut not among the cuts calculated by the track-selection task! "; + } + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + if (objArrayTrackCuts->FindObject(tempStr.Data()) != nullptr) { + fPrefilterMask |= (static_cast(1) << icut); + } + if (tempStr.CompareTo(fConfigPrefilterTrackCut.value) == 0) { + fPrefilterCutBit = icut; + } + } + // setup the prefilter pair cut + fPairCut = new AnalysisCompositeCut(true); + TString pairCutStr = fConfigPrefilterPairCut.value; + if (!pairCutStr.IsNull()) { + fPairCut = dqcuts::GetCompositeCut(pairCutStr.Data()); + } + } + if (fPrefilterMask == static_cast(0) || fPrefilterCutBit < 0) { + LOG(warn) << "No specified loose cut or track cuts for prefiltering. This task will do nothing."; + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetDefaultVarNames(); + + VarManager::SetupTwoProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, true); // TODO: get these parameters from Configurables + VarManager::SetupTwoProngFwdDCAFitter(5.0f, true, 200.0f, 1.0e-3f, 0.9f, true); + cout << "AnalysisPrefilterSelection::init() completed" << endl; + } + + template + void runPrefilter(MyEvents::iterator const& event, soa::Join const& assocs, T const& /*tracks*/) + { + // cout << "AnalysisPrefilterSelection::runPrefilter() called for event " << event.globalIndex() << " with " << assocs.size() << " track associations" << endl; + if (fPrefilterCutBit < 0 || fPrefilterMask == 0) { + return; + } + + for (auto& [assoc1, assoc2] : o2::soa::combinations(assocs, assocs)) { + auto track1 = assoc1.template track_as(); + auto track2 = assoc2.template track_as(); + + // NOTE: here we restrict to just pairs of opposite sign (conversions), but in principle this can be made + // a configurable and check also same-sign pairs (track splitting) + if (track1.sign() * track2.sign() > 0) { + continue; + } + + // here we check the cuts fulfilled by both tracks, for both the tight and loose selections + uint32_t track1Candidate = (assoc1.isBarrelSelected_raw() & fPrefilterMask); + uint32_t track2Candidate = (assoc2.isBarrelSelected_raw() & fPrefilterMask); + bool track1Loose = assoc1.isBarrelSelected_bit(fPrefilterCutBit); + bool track2Loose = assoc2.isBarrelSelected_bit(fPrefilterCutBit); + + if (!((track1Candidate > 0 && track2Loose) || (track2Candidate > 0 && track1Loose))) { + continue; + } + + // 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) { + fPrefilterMap[track1.globalIndex()] = track1Candidate; + } + if (fPrefilterMap.find(track2.globalIndex()) == fPrefilterMap.end() && track2Candidate > 0) { + fPrefilterMap[track2.globalIndex()] = track2Candidate; + } + } + } // end loop over combinations + // cout << "AnalysisPrefilterSelection::runPrefilter() completed for event " << event.globalIndex() << endl; + } + + void processBarrel(MyEvents const& events, soa::Join const& assocs, MyBarrelTracksWithCov const& tracks) + { + cout << "AnalysisPrefilterSelection::processBarrel() called" << endl; + fPrefilterMap.clear(); + + for (auto& event : events) { + auto groupedAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); + groupedAssocs.bindInternalIndicesTo(&assocs); + + if (groupedAssocs.size() > 1) { + runPrefilter(event, groupedAssocs, tracks); + } + } + + uint32_t mymap = -1; + // If cuts were not configured, then produce a map with all 1's and publish it for all associations + if (fPrefilterCutBit < 0 || fPrefilterMask == 0) { + for (int i = 0; i < assocs.size(); ++i) { + prefilter(mymap); + } + } else { + for (auto& assoc : assocs) { + // TODO: just use the index from the assoc (no need to cast the whole track) + // auto track = assoc.template track_as(); + mymap = -1; + // if (fPrefilterMap.find(track.globalIndex()) != fPrefilterMap.end()) { + if (fPrefilterMap.find(assoc.trackId()) != fPrefilterMap.end()) { + // NOTE: publish the bitwise negated bits (~), so there will be zeroes for cuts that failed the prefiltering and 1 everywhere else + // mymap = ~fPrefilterMap[track.globalIndex()]; + mymap = ~fPrefilterMap[assoc.trackId()]; + prefilter(mymap); + } else { + prefilter(mymap); // track did not pass the prefilter selections, so publish just 1's + } + } + } + cout << "AnalysisPrefilterSelection::processBarrel() completed" << endl; + } + + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisPrefilterSelection, processBarrel, "Run Prefilter selection on barrel tracks", false); + PROCESS_SWITCH(AnalysisPrefilterSelection, processDummy, "Do nothing", true); +}; + +struct AnalysisSameEventPairing { + Produces dielectronList; + Produces dielectronsExtraList; + Produces dielectronInfoList; + Produces dielectronAllList; + Produces dileptonInfoList; + Produces PromptNonPromptSepTable; + + o2::base::MatLayerCylSet* fLUT = nullptr; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + + OutputObj fOutputList{"output"}; + + // Histogram manager + HistogramManager* fHistMan = nullptr; + + // Config options + // ConfigOptions fConfigOptions; + + struct : ConfigurableGroup { + Configurable track{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable muon{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; + Configurable pair{"cfgPairCuts", "", "Comma separated list of pair cuts, !!! Use only if you know what you are doing, otherwise leave empty"}; + Configurable collSplitting{"cfgRemoveCollSplittingCandidates", false, "If true, remove collision splitting candidates as determined by the event selection task upstream"}; + Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; + Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + Configurable useRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; + Configurable magField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + Configurable flatTables{"cfgFlatTables", false, "Produce a single flat tables with all relevant information of the pairs and single tracks"}; + Configurable useKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable recomputePV{"cfgRecomputePV", false, "Recompute primary vertex using PVertexer to calculate unbiased pseudoproperDL"}; + Configurable removeDiamondConstrPV{"cfgRemoveDiamondPV", false, "remove diamond constrain for PV recomputation"}; + Configurable useAbsDCA{"cfgUseAbsDCA", false, "Use absolute DCA minimization instead of chi^2 minimization in secondary vertexing"}; + Configurable propToPCA{"cfgPropToPCA", false, "Propagate tracks to secondary vertex"}; + Configurable corrFullGeo{"cfgCorrFullGeo", false, "Use full geometry to correct for MCS effects in track propagation"}; + Configurable noCorr{"cfgNoCorrFwdProp", false, "Do not correct for MCS effects in track propagation"}; + Configurable collisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; + Configurable centerMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; + Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; + Configurable fConfigMiniTree{"cfgMiniTree", false, "Produce a single flat table with minimal information for analysis"}; + Configurable fConfigMiniTreeMinMass{"cfgMiniTreeMinMass", 2, "Min. mass cut for minitree"}; + Configurable fConfigMiniTreeMaxMass{"cfgMiniTreeMaxMass", 5, "Max. mass cut for minitree"}; + } fConfigOptions; + + struct : ConfigurableGroup { + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + 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"}; + } fConfigCCDB; + + Service fCCDB; + + // vectors needed for PV recomputation + std::vector pvContribGlobIDs; + std::vector pvContribTrackPars; + std::vector vec_useTrk_PVrefit; + + // keep histogram class names in maps, so we don't have to buld their names in the pair loops + std::map> fTrackHistNames; + std::map> fMuonHistNames; + + std::vector fPairCuts; + AnalysisCompositeCut fMCGenAccCut; + // bool fUseMCGenAccCut = false; + + uint32_t fTrackFilterMask; // mask for the track cuts required in this task to be applied on the barrel cuts produced upstream + uint32_t fMuonFilterMask; // mask for the muon cuts required in this task to be applied on the muon cuts produced upstream + int fNCutsBarrel; + int fNCutsMuon; + int fNPairCuts; + bool fHasTwoProngGenMCsignals = false; + + bool fEnableBarrelHistos; + + Preslice> trackAssocsPerCollision = aod::track_association::collisionId; + // Preslice> muonAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + + void init(o2::framework::InitContext& context) + { + cout << "AnalysisSameEventPairing::init() called" << endl; + if (context.mOptions.get("processDummy")) { + return; + } + VarManager::SetDefaultVarNames(); + + fEnableBarrelHistos = context.mOptions.get("processBarrelOnly"); + // fEnableMuonHistos = context.mOptions.get("processMuonOnlySkimmed"); + + // Keep track of all the histogram class names to avoid composing strings in the pairing loop + TString histNames = ""; + TString cutNamesStr = fConfigOptions.pair.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + fPairCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + + // get the list of cuts for tracks/muons, check that they were played by the barrel/muon selection tasks + // and make a mask for active cuts (barrel and muon selection tasks may run more cuts, needed for other analyses) + TString trackCutsStr = fConfigOptions.track.value; + TObjArray* objArrayTrackCuts = nullptr; + if (!trackCutsStr.IsNull()) { + objArrayTrackCuts = trackCutsStr.Tokenize(","); + } + /*TString muonCutsStr = fConfigOptions.muon.value; + TObjArray* objArrayMuonCuts = nullptr; + if (!muonCutsStr.IsNull()) { + objArrayMuonCuts = muonCutsStr.Tokenize(","); + }*/ + + // get the barrel track selection cuts + string tempCuts; + getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempCuts, false); + TString tempCutsStr = tempCuts; + // check also the cuts added via JSON and add them to the string of cuts + getTaskOptionValue(context, "analysis-track-selection", "cfgBarrelTrackCutsJSON", tempCuts, false); + TString addTrackCutsStr = tempCuts; + if (addTrackCutsStr != "") { + std::vector addTrackCuts = dqcuts::GetCutsFromJSON(addTrackCutsStr.Data()); + for (auto& t : addTrackCuts) { + tempCutsStr += Form(",%s", t->GetName()); + } + } + + // check that the barrel track cuts array required in this task is not empty + if (!trackCutsStr.IsNull()) { + // tokenize and loop over the barrel cuts produced by the barrel track selection task + std::unique_ptr objArray(tempCutsStr.Tokenize(",")); + fNCutsBarrel = objArray->GetEntries(); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + // if the current barrel selection cut is required in this task, then switch on the corresponding bit in the mask + // and assign histogram directories + if (objArrayTrackCuts->FindObject(tempStr.Data()) != nullptr) { + fTrackFilterMask |= (static_cast(1) << icut); + + if (fEnableBarrelHistos) { + // assign the pair hist directories for the current cut + std::vector names = { + Form("PairsBarrelSEPM_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), + Form("PairsBarrelSEMM_%s", objArray->At(icut)->GetName())}; + if (fConfigOptions.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()); + } + fTrackHistNames[icut] = names; + + // if there are pair cuts specified, assign hist directories for each barrel cut - pair cut combination + // NOTE: This could possibly lead to large histogram outputs. It is strongly advised to use pair cuts only + // if you know what you are doing. + TString cutNamesStr = fConfigOptions.pair.value; + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + fNPairCuts = objArrayPair->GetEntries(); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + names = { + Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsBarrelSEPP_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsBarrelSEMM_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + // NOTE: In the numbering scheme for the map key, we use the number of barrel cuts in the barrel-track selection task + fTrackHistNames[fNCutsBarrel + icut * fNPairCuts + iPairCut] = names; + } // end loop (pair cuts) + } // end if (pair cuts) + } // end if enableBarrelHistos + } + } + } + + /* + // get the muon track selection cuts + getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCuts", tempCuts, false); + tempCutsStr = tempCuts; + // check also the cuts added via JSON and add them to the string of cuts + getTaskOptionValue(context, "analysis-muon-selection", "cfgMuonCutsJSON", tempCuts, false); + TString addMuonCutsStr = tempCuts; + if (addMuonCutsStr != "") { + std::vector addMuonCuts = dqcuts::GetCutsFromJSON(addMuonCutsStr.Data()); + for (auto& t : addMuonCuts) { + tempCutsStr += Form(",%s", t->GetName()); + } + } + + // check that in this task we have specified muon cuts + if (!muonCutsStr.IsNull()) { + // loop over the muon cuts computed by the muon selection task and build a filter mask for those required in this task + std::unique_ptr objArray(tempCutsStr.Tokenize(",")); + fNCutsMuon = objArray->GetEntries(); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + TString tempStr = objArray->At(icut)->GetName(); + if (objArrayMuonCuts->FindObject(tempStr.Data()) != nullptr) { + // update the filter mask + fMuonFilterMask |= (static_cast(1) << icut); + + if (fEnableMuonHistos) { + // assign pair hist directories for each required muon cut + std::vector names = { + Form("PairsMuonSEPM_%s", objArray->At(icut)->GetName()), + Form("PairsMuonSEPP_%s", objArray->At(icut)->GetName()), + Form("PairsMuonSEMM_%s", objArray->At(icut)->GetName())}; + if (fConfigOptions.fConfigQA) { + // assign separate hist directories for ambiguous tracks + 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())); + } + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fMuonHistNames[icut] = names; + + // if there are specified pair cuts, assign hist dirs for each muon cut - pair cut combination + TString cutNamesStr = fConfigOptions.pair.value; + if (!cutNamesStr.IsNull()) { // if pair cuts + std::unique_ptr objArrayPair(cutNamesStr.Tokenize(",")); + fNPairCuts = objArrayPair->GetEntries(); + for (int iPairCut = 0; iPairCut < fNPairCuts; ++iPairCut) { // loop over pair cuts + names = { + Form("PairsMuonSEPM_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsMuonSEPP_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName()), + Form("PairsMuonSEMM_%s_%s", objArray->At(icut)->GetName(), objArrayPair->At(iPairCut)->GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + fMuonHistNames[fNCutsMuon + icut * fNCutsMuon + iPairCut] = names; + } // end loop (pair cuts) + } // end if (pair cuts) + + // assign hist directories for pairs matched to MC signals for each (muon cut, MCrec signal) combination + if (!sigNamesStr.IsNull()) { + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + auto sig = fRecMCSignals.at(isig); + names = { + Form("PairsMuonSEPM_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + Form("PairsMuonSEPP_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + Form("PairsMuonSEMM_%s_%s", objArray->At(icut)->GetName(), sig->GetName()), + }; + if (fConfigOptions.fConfigQA) { + names.push_back(Form("PairsMuonSEPMCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPMIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousInBunch_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousInBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousInBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunch_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunchCorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + names.push_back(Form("PairsMuonSEPM_ambiguousOutOfBunchIncorrectAssoc_%s_%s", objArray->At(icut)->GetName(), sig->GetName())); + } + for (auto& n : names) { + histNames += Form("%s;", n.Data()); + } + fMuonHistNamesMCmatched.try_emplace(icut * fRecMCSignals.size() + isig, names); + } // end loop over MC signals + } + } + } + } // end loop over cuts + } // end if (muonCutsStr) +*/ + + fCurrentRun = 0; + + fCCDB->setURL(fConfigCCDB.url.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + + if (fConfigOptions.noCorr) { + VarManager::SetupFwdDCAFitterNoCorr(); + } else if (fConfigOptions.corrFullGeo || (fConfigOptions.useKFVertexing && fConfigOptions.propToPCA)) { + if (!o2::base::GeometryManager::isGeometryLoaded()) { + fCCDB->get(fConfigCCDB.geoPath); + } + } else { + fLUT = o2::base::MatLayerCylSet::rectifyPtrFromFile(fCCDB->get(fConfigCCDB.lutPath)); + VarManager::SetupMatLUTFwdDCAFitter(fLUT); + } + + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + VarManager::SetCollisionSystem((TString)fConfigOptions.collisionSystem, fConfigOptions.centerMassEnergy); // set collision system and center of mass energy + + DefineHistograms(fHistMan, histNames.Data(), fConfigOptions.fConfigAddSEPHistogram.value.data()); // define all histograms + dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigOptions.fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + fOutputList.setObject(fHistMan->GetMainHistogramList()); + + cout << "AnalysisSameEventPairing::init() completed" << endl; + } + + void initParamsFromCCDB(uint64_t timestamp, bool withTwoProngFitter = true) + { + cout << "AnalysisSameEventPairing::initParamsFromCCDB() called for timestamp " << timestamp << endl; + if (fConfigOptions.useRemoteField.value) { + o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(fConfigCCDB.grpMagPath, timestamp); + o2::base::MatLayerCylSet* lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(fCCDB->get(fConfigCCDB.lutPath)); + float magField = 0.0; + if (grpmag != nullptr) { + magField = grpmag->getNominalL3Field(); + o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", timestamp); + } + if (withTwoProngFitter) { + if (fConfigOptions.useKFVertexing.value) { + VarManager::SetupTwoProngKFParticle(magField); + } else { + VarManager::SetupTwoProngDCAFitter(magField, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, fConfigOptions.useAbsDCA.value); // TODO: get these parameters from Configurables + VarManager::SetupTwoProngFwdDCAFitter(magField, true, 200.0f, 1.0e-3f, 0.9f, fConfigOptions.useAbsDCA.value); + } + } else { + VarManager::SetupTwoProngDCAFitter(magField, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, fConfigOptions.useAbsDCA.value); // needed because take in varmanager Bz from fgFitterTwoProngBarrel for PhiV calculations + } + } else { + if (withTwoProngFitter) { + if (fConfigOptions.useKFVertexing.value) { + VarManager::SetupTwoProngKFParticle(fConfigOptions.magField.value); + } else { + VarManager::SetupTwoProngDCAFitter(fConfigOptions.magField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, fConfigOptions.useAbsDCA.value); // TODO: get these parameters from Configurables + VarManager::SetupTwoProngFwdDCAFitter(fConfigOptions.magField.value, true, 200.0f, 1.0e-3f, 0.9f, fConfigOptions.useAbsDCA.value); + } + } else { + VarManager::SetupTwoProngDCAFitter(fConfigOptions.magField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, fConfigOptions.useAbsDCA.value); // needed because take in varmanager Bz from fgFitterTwoProngBarrel for PhiV calculations + } + } + cout << "AnalysisSameEventPairing::initParamsFromCCDB() completed" << endl; + } + + template + bool refitPVWithPVertexer(Events const& collision, TTracks const& tracks, Tracks const& t1, Tracks const& t2, o2::dataformats::VertexBase& pvRefitted) + { + // --- build PV contributor list --- + pvContribGlobIDs.clear(); + pvContribTrackPars.clear(); + // int nMyPVContrib = 0; int nMyPVContribOrig = 0; + for (auto const& trk : tracks) { + // check if it is PV contributor + if (!trk.isPVContributor()) + continue; + // check if it contributes to the vtx of this collision + if (trk.collisionId() != collision.globalIndex()) + continue; + // nMyPVContribOrig++; + // --- remove t1 and t2 if they are PV contributors --- + if (trk.globalIndex() == t1.globalIndex() || trk.globalIndex() == t2.globalIndex()) + continue; + // add tracks and parameters to the list + pvContribGlobIDs.push_back(trk.globalIndex()); + pvContribTrackPars.push_back(getTrackParCov(trk)); + // nMyPVContrib++; + } + + // cout << "contributors from collision: " << collision.numContrib() << " - from refitting: before -> " << nMyPVContribOrig << " after -> " << nMyPVContrib << endl; + vec_useTrk_PVrefit.assign(pvContribGlobIDs.size(), true); + // --- build VertexBase from event collision --- + o2::dataformats::VertexBase Pvtx; + Pvtx.setX(collision.posX()); + Pvtx.setY(collision.posY()); + Pvtx.setZ(collision.posZ()); + Pvtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ()); + + // --- configure vertexer --- + o2::vertexing::PVertexer vertexer; + if (fConfigOptions.removeDiamondConstrPV) { + o2::conf::ConfigurableParam::updateFromString("pvertexer.useMeanVertexConstraint=false"); + } + vertexer.init(); + + bool PVrefit_doable = vertexer.prepareVertexRefit(pvContribTrackPars, Pvtx); + if (!PVrefit_doable) + return false; + + // --- do the refit --- + pvRefitted = vertexer.refitVertex(vec_useTrk_PVrefit, Pvtx); + + return true; + } + + // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) + template + void runSameEventPairing(TEvents const& events, BCsWithTimestamps const& bcs, Preslice>& preslice, soa::Join const& assocs, TTracks const& tracks) + { + cout << "AnalysisSameEventPairing::runSameEventPairing() called" << endl; + if (events.size() == 0) { + LOG(warning) << "No events in this TF, going to the next one ..."; + return; + } + if (fCurrentRun != bcs.begin().runNumber()) { + initParamsFromCCDB(bcs.begin().timestamp(), TTwoProngFitter); + fCurrentRun = bcs.begin().runNumber(); + } + + TString cutNames = fConfigOptions.track.value; + std::map> histNames = fTrackHistNames; + int ncuts = fNCutsBarrel; + + uint32_t twoTrackFilter = 0; + int sign1 = 0; + int sign2 = 0; + + dielectronList.reserve(1); + // dimuonList.reserve(1); + dielectronsExtraList.reserve(1); + // dimuonsExtraList.reserve(1); + dielectronInfoList.reserve(1); + dileptonInfoList.reserve(1); + + if (fConfigOptions.flatTables.value) { + dielectronAllList.reserve(1); + // dimuonAllList.reserve(1); + } + + constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); + constexpr bool trackHasCov = ((TTrackFillMap & VarManager::ObjTypes::TrackCov) > 0); + + for (auto& event : events) { + if (!event.isEventSelected_bit(0)) + continue; + + if (fConfigOptions.collSplitting && event.isEventSelected_bit(2)) { + continue; + } + + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + + auto groupedAssocs = assocs.sliceBy(preslice, event.globalIndex()); + if (groupedAssocs.size() == 0) + continue; + + for (auto& [a1, a2] : o2::soa::combinations(groupedAssocs, groupedAssocs)) { + + if constexpr (TPairType == VarManager::kDecayToEE) { + + twoTrackFilter = a1.isBarrelSelected_raw() & a2.isBarrelSelected_raw() & a1.isBarrelSelectedPrefilter_raw() & a2.isBarrelSelectedPrefilter_raw() & fTrackFilterMask; + if (!twoTrackFilter) + continue; + + auto t1 = a1.template track_as(); + auto t2 = a2.template track_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) { + twoTrackFilter |= (static_cast(1) << 28); + } + if (t2.barrelAmbiguityInBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 29); + } + if (t1.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 30); + } + if (t2.barrelAmbiguityOutOfBunch() > 1) { + twoTrackFilter |= (static_cast(1) << 31); + } + + VarManager::FillPair(t1, t2); + // fill tables + dielectronList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], + t1.sign() + t2.sign(), twoTrackFilter, -1); + + dielectronInfoList(event.globalIndex(), t1.globalIndex(), t2.globalIndex()); + dileptonInfoList(event.globalIndex(), event.posX(), event.posY(), event.posZ()); + + if (fConfigOptions.fPropTrack) { + VarManager::FillPairCollision(event, t1, t2); + } + + if constexpr (TTwoProngFitter) { + VarManager::FillPairVertexing(event, t1, t2, fConfigOptions.propToPCA); + o2::dataformats::VertexBase pvRefit; + if (fConfigOptions.recomputePV) { + VarManager::SetPVrecalculationKF(false); + VarManager::ResetValues(VarManager::kVertexingLxyProjectedRecalculatePV, VarManager::kVertexingLxyProjectedRecalculatePV + 1); + VarManager::ResetValues(VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV, VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV + 1); + // cout << "primary vertex (before): x -> " << event.posX() << " y -> " << event.posY() << " z -> " << event.posZ() << endl; + o2::dataformats::VertexBase pvRefit; + bool ok = refitPVWithPVertexer(event, tracks, t1, t2, pvRefit); + if (ok) + VarManager::FillPairVertexingRecomputePV(event, t1, t2, pvRefit); + // cout << "primary vertex (after): ok -> " << ok << " x -> " << pvRefit.getX() << " y -> " << pvRefit.getY() << " z -> " << pvRefit.getZ() << endl; + } + } + + if constexpr (trackHasCov && TTwoProngFitter) { + dielectronsExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); + if (fConfigOptions.flatTables.value) { + dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), twoTrackFilter, -1, + // t1.pt(), t1.eta(), t1.phi(), t1.itsClusterMap(), t1.itsChi2NCl(), 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(), + t1.pt(), t1.eta(), t1.phi(), t1.itsClusterMap(), t1.itsChi2NCl(), t1.tpcNClsCrossedRows(), t1.tpcNClsFound(), t1.tpcChi2NCl(), t1.dcaXY(), t1.dcaZ(), t1.tpcSignal(), t1.tpcNSigmaEl(), t1.tpcNSigmaPi(), t1.tpcNSigmaPr(), -999.0, -999.0, -999.0, -999.0, + // t2.pt(), t2.eta(), t2.phi(), t2.itsClusterMap(), t2.itsChi2NCl(), 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(), + t2.pt(), t2.eta(), t2.phi(), t2.itsClusterMap(), t2.itsChi2NCl(), t2.tpcNClsCrossedRows(), t2.tpcNClsFound(), t2.tpcChi2NCl(), t2.dcaXY(), t2.dcaZ(), t2.tpcSignal(), t2.tpcNSigmaEl(), t2.tpcNSigmaPi(), t2.tpcNSigmaPr(), -999.0, -999.0, -999.0, -999.0, + 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], + VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjected], + VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); + } + } + + if constexpr (eventHasQvector) { + VarManager::FillPairVn(t1, t2); + } + } + // Fill normal histograms + bool isAmbiInBunch = (twoTrackFilter & (1 << 28)) || (twoTrackFilter & (1 << 29)); + bool isAmbiOutOfBunch = (twoTrackFilter & (1 << 30)) || (twoTrackFilter & (1 << 31)); + + for (int icut = 0; icut < ncuts; icut++) { // loop over cut definitions + if (twoTrackFilter & (static_cast(1) << icut)) { + if (sign1 * sign2 < 0) { // opposite sign pairs + fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); + PromptNonPromptSepTable(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kRap], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kVertexingTauxyProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMass], VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingTauxyProjectedPoleJPsiMassRecalculatePV], isAmbiInBunch, isAmbiOutOfBunch, VarManager::fgValues[VarManager::kMultFT0A], VarManager::fgValues[VarManager::kMultFT0C], VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kVtxNcontribReal]); + if (fConfigOptions.fConfigQA) { + if (isAmbiInBunch) { + fHistMan->FillHistClass(histNames[icut][3].Data(), VarManager::fgValues); + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(histNames[icut][3 + 3].Data(), VarManager::fgValues); + } + } + } else if (sign1 > 0) { // ++ pairs + fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); + if (fConfigOptions.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 (fConfigOptions.fConfigQA) { + if (isAmbiInBunch) { + fHistMan->FillHistClass(histNames[icut][5].Data(), VarManager::fgValues); + } + if (isAmbiOutOfBunch) { + fHistMan->FillHistClass(histNames[icut][5 + 3].Data(), VarManager::fgValues); + } + } + } + + // Pair cuts + for (unsigned int iPairCut = 0; iPairCut < fPairCuts.size(); iPairCut++) { + AnalysisCompositeCut cut = fPairCuts.at(iPairCut); + if (!cut.IsSelected(VarManager::fgValues)) + continue; // apply pair cuts + if (sign1 * sign2 < 0) { // opposite sign pairs + fHistMan->FillHistClass(histNames[ncuts + icut * fPairCuts.size() + iPairCut][0].Data(), VarManager::fgValues); + } else if (sign1 > 0) { // ++ pairs + fHistMan->FillHistClass(histNames[ncuts + icut * fPairCuts.size() + iPairCut][1].Data(), VarManager::fgValues); + } else { // -- pairs + fHistMan->FillHistClass(histNames[ncuts + icut * fPairCuts.size() + iPairCut][2].Data(), VarManager::fgValues); + } + } // end loop (pair cuts) + } + } // end loop (cuts) + } // end loop over pairs of track associations + } // end loop over events + + cout << "AnalysisSameEventPairing::runSameEventPairing() completed" << endl; + } + + void processBarrelOnly(MyEventsSelected const& events, BCsWithTimestamps const& bcs, + soa::Join const& barrelAssocs, + MyBarrelTracksWithCovWithAmbiguities const& barrelTracks) + { + cout << "AnalysisSameEventPairing::processBarrelOnly() called" << endl; + runSameEventPairing(events, bcs, trackAssocsPerCollision, barrelAssocs, barrelTracks); + cout << "AnalysisSameEventPairing::processBarrelOnly() completed" << endl; + } + + void processDummy(MyEvents&) { /* do nothing */ } + + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnly, "Run barrel only pairing", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // Initialize metadata for TOF response + o2::pid::tof::TOFResponseImpl::metadataInfo.initMetadata(cfgc); + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; + // adaptAnalysisTask(cfgc)}; +} + +void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) +{ + // + // 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 = histGroups; + // NOTE: The level of detail for histogramming can be controlled via configurables + if (classStr.Contains("TimeFrameStats")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "timeframe"); + } + if (classStr.Contains("Event")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "event", histName); + } + + if (classStr.Contains("SameBunchCorrelations") || classStr.Contains("OutOfBunchCorrelations")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "two-collisions", histName); + } + + if ((classStr.Contains("Track") || classStr.Contains("Assoc")) && !classStr.Contains("Pairs")) { + if (classStr.Contains("Barrel")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + if (classStr.Contains("PIDCalibElectron")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "postcalib_electron"); + } + if (classStr.Contains("PIDCalibPion")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "postcalib_pion"); + } + if (classStr.Contains("PIDCalibProton")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "postcalib_proton"); + } + if (classStr.Contains("Ambiguity")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "ambiguity"); + } + } + } + if (classStr.Contains("Muon") && !classStr.Contains("Pairs")) { + if (!classStr.Contains("Ambiguity")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + } else { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", "muon-ambiguity"); + } + } + + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + + if (classStr.Contains("Triplets")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", histName); + } + + if (classStr.Contains("DileptonsSelected")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "pair", "barrel,vertexing"); + } + + if (classStr.Contains("DileptonTrack") && !classStr.Contains("ME")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-track", histName); + } + + if (classStr.Contains("DileptonTrackME")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-track", "mixedevent"); + } + + if (classStr.Contains("HadronsSelected")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "track", histName); + } + + if (classStr.Contains("DileptonHadronInvMass")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-mass"); + } + + if (classStr.Contains("DileptonHadronCorrelation")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-correlation"); + } + + if (classStr.Contains("MCTruthEenergyCorrelators")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "energy-correlator-gen"); + } + } // end loop over histogram classes +} + +/* +struct AnalysisDileptonTrack { + int fCurrentRun = -1; + + // Preslice per associazioni e dileptoni + Preslice> trackAssocsPerCollision = aod::track_association::collisionId; + Preslice dielectronsPerCollision = aod::reducedpair::reducedeventId; + + // Configurazioni e istogrammi + // ConfigOptions fConfigOptions; + struct : ConfigurableGroup { + Configurable fConfigTrackCuts{"cfgTrackCuts", "kaonPID", "Comma separated list of track cuts to be correlated with the dileptons"}; + Configurable fConfigDileptonLowMass{"cfgDileptonLowMass", 2.8, "Low mass cut for the dileptons used in analysis"}; + Configurable fConfigDileptonHighMass{"cfgDileptonHighMass", 3.2, "High mass cut for the dileptons used in analysis"}; + Configurable fConfigDileptonLxyCut{"cfgDileptonLxyCut", 0.0, "Lxy cut for dileptons used in the triplet vertexing"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigDileptonLowpTCut{"cfgDileptonLowpTCut", 0.0, "Low pT cut for dileptons used in the triplet vertexing"}; + Configurable fConfigDileptonHighpTCut{"cfgDileptonHighpTCut", 1E5, "High pT cut for dileptons used in the triplet vertexing"}; + Configurable fConfigDileptonRapCutAbs{"cfgDileptonRapCutAbs", 1.0, "Rap cut for dileptons used in the triplet vertexing"}; + Configurable fConfigHistogramSubgroups{"cfgDileptonTrackHistogramsSubgroups", "invmass,vertexing", "Comma separated list of dilepton-track histogram subgroups"}; + Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; + Configurable fConfigPublishTripletTable{"cfgPublishTripletTable", false, "Publish the triplet tables, BmesonCandidates"}; + Configurable fConfigApplyMassEC{"cfgApplyMassEC", false, "Apply fit mass for sideband for the energy correlator study"}; + Configurable> fConfigSavelessevents{"cfgSavelessevents", std::vector{1, 0}, "Save less events for the energy correlator study"}; + } fConfigOptions; + + struct : ConfigurableGroup { + Configurable fConfigUseRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; + Configurable fConfigGRPmagPath{"cfgGrpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + 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 fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + } fConfigCCDBOptions; + + HistogramManager* fHistMan = nullptr; + + void processBarrel(soa::Filtered const& events, BCsWithTimestamps const& bcs, + soa::Join const& assocs, + MyBarrelTracksWithCov const& tracks, soa::Filtered const& dileptons) + { + std::cout << "AnalysisDileptonTrack::processBarrel() called" << std::endl; + + if (events.size() == 0) return; + + if (fCurrentRun != bcs.begin().runNumber()) { + initParamsFromCCDB(bcs.begin().timestamp()); + fCurrentRun = bcs.begin().runNumber(); + } + + for (auto& event : events) { + if (!event.isEventSelected_bit(0)) continue; + + std::vector fSavelessevents = fConfigOptions.fConfigSavelessevents; + if (fSavelessevents[0] > 1 && event.globalIndex() % fSavelessevents[0] == fSavelessevents[1]) continue; + + auto groupedBarrelAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); + auto groupedDielectrons = dileptons.sliceBy(dielectronsPerCollision, event.globalIndex()); + + runDileptonHadron( + event, bcs, groupedBarrelAssocs, tracks, groupedDielectrons); + } + + std::cout << "AnalysisDileptonTrack::processBarrel() completed" << std::endl; + } + + void processDummy(MyEvents&) { + // funzione dummy, non fa nulla + } + + void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) { + 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()); + + if (classStr.Contains("TimeFrameStats")) { + dqhistograms::DefineHistograms(histMan, classStr, "timeframe"); + } + if (classStr.Contains("Event")) { + dqhistograms::DefineHistograms(histMan, classStr, "event", histGroups); + } + if (classStr.Contains("Track") && !classStr.Contains("Pairs")) { + if (classStr.Contains("Barrel")) { + dqhistograms::DefineHistograms(histMan, classStr, "track", histGroups); + } + } + if (classStr.Contains("Pairs")) { + dqhistograms::DefineHistograms(histMan, classStr, "pair", histGroups); + } + if (classStr.Contains("DileptonTrack") && !classStr.Contains("ME")) { + dqhistograms::DefineHistograms(histMan, classStr, "dilepton-track", histGroups); + } + if (classStr.Contains("DileptonTrackME")) { + dqhistograms::DefineHistograms(histMan, classStr, "dilepton-track", "mixedevent"); + } + if (classStr.Contains("DileptonHadronInvMass")) { + dqhistograms::DefineHistograms(histMan, classStr, "dilepton-hadron-mass"); + } + if (classStr.Contains("DileptonHadronCorrelation")) { + dqhistograms::DefineHistograms(histMan, classStr, "dilepton-hadron-correlation"); + } + } + } + + PROCESS_SWITCH(AnalysisDileptonTrack, processBarrel, "Run barrel dilepton-track pairing, using skimmed data", false); + PROCESS_SWITCH(AnalysisDileptonTrack, processDummy, "Dummy function", true); +}; */ diff --git a/PWGDQ/Tasks/taskFwdTrackPid.cxx b/PWGDQ/Tasks/taskFwdTrackPid.cxx index 33b89b0e745..8f7febbbf28 100644 --- a/PWGDQ/Tasks/taskFwdTrackPid.cxx +++ b/PWGDQ/Tasks/taskFwdTrackPid.cxx @@ -13,41 +13,27 @@ /// \brief Task for the analysis of forward PID with MFT /// \author Luca Micheletti , INFN -#include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/AnalysisCut.h" -#include "PWGDQ/Core/CutsLibrary.h" #include "PWGDQ/Core/HistogramManager.h" #include "PWGDQ/Core/HistogramsLibrary.h" #include "PWGDQ/Core/MCSignal.h" #include "PWGDQ/Core/MCSignalLibrary.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/MixingLibrary.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/CCDB/EventSelectionParams.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ITSMFTBase/DPLAlpideParam.h" - -#include "TGeoGlobalMagField.h" -#include -#include +#include +#include +#include +#include +#include +#include + #include -#include +#include #include -#include -#include +#include + +#include #include #include #include diff --git a/PWGDQ/Tasks/taskJpsiHf.cxx b/PWGDQ/Tasks/taskJpsiHf.cxx index fcc78628b20..b41950b4056 100644 --- a/PWGDQ/Tasks/taskJpsiHf.cxx +++ b/PWGDQ/Tasks/taskJpsiHf.cxx @@ -15,18 +15,26 @@ /// \author Fabrizio Grosa , CERN #include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include #include #include #include diff --git a/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx b/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx index ff161fbafc1..999b46bd148 100644 --- a/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx +++ b/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx @@ -21,10 +21,18 @@ #include "PWGDQ/DataModel/MchTrkEffTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include #include #include diff --git a/PWGDQ/Tasks/v0selector.cxx b/PWGDQ/Tasks/v0selector.cxx index 4a809dc9b86..f464459adf0 100644 --- a/PWGDQ/Tasks/v0selector.cxx +++ b/PWGDQ/Tasks/v0selector.cxx @@ -23,40 +23,37 @@ #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include "Math/Vector4D.h" - -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include #include #include -#include #include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; /*using FullTracksExt = soa::Join +#include + +#include +#include #include #include @@ -356,3 +360,8 @@ void DielectronCut::IncludeITSsa(bool flag, float max) mMaxPtITSsa = max; LOG(info) << "Dielectron Cut, include ITSsa tracks: " << mIncludeITSsa << ", mMaxPtITSsa = " << mMaxPtITSsa; } +void DielectronCut::EnableTTCA(bool flag) +{ + mEnableTTCA = flag; + LOG(info) << "Dielectron Cut, enable TTCA: " << mEnableTTCA; +} diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 64bdd069f18..feba64b0410 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -17,24 +17,29 @@ #define PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/DataTypes.h" -#include "Framework/Logger.h" +#include "Common/Core/RecoDecay.h" -#include "Math/Vector4D.h" -#include "TNamed.h" +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include #include +#include +#include +#include #include -#include #include #include -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::dilepton::utils::pairutil; +#include class DielectronCut : public TNamed { @@ -67,6 +72,7 @@ class DielectronCut : public TNamed kITSNCls, kITSChi2NDF, kITSClusterSize, + kTTCA, kPrefilter, kNCuts }; @@ -108,9 +114,9 @@ class DielectronCut : public TNamed ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float dca_ee_3d = pairDCAQuadSum(dca3DinSigma(t1), dca3DinSigma(t2)); - float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), bz); - float opAng = getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); + float dca_ee_3d = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2)); + 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); + float opAng = o2::aod::pwgem::dilepton::utils::pairutil::getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); if (v12.M() < mMinMee || mMaxMee < v12.M()) { return false; @@ -170,7 +176,7 @@ class DielectronCut : public TNamed template bool IsSelectedTrack(TTrack const& track) const { - if (!track.hasITS()) { + if (!track.hasITS() || !track.hasTPC()) { return false; } @@ -210,6 +216,9 @@ class DielectronCut : public TNamed if (!IsSelectedTrack(track, DielectronCuts::kITSClusterSize)) { return false; } + if (!IsSelectedTrack(track, DielectronCuts::kTTCA)) { + 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); }); @@ -229,9 +238,9 @@ class DielectronCut : public TNamed return false; } - if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa - return false; - } + // if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa + // return false; + // } // TPC cuts if (track.hasTPC()) { @@ -254,7 +263,6 @@ class DielectronCut : public TNamed return false; } } - if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { return false; } @@ -414,6 +422,7 @@ class DielectronCut : public TNamed case DielectronCuts::kTrackPhiPositionRange: { float phiPosition = track.phi() + std::asin(-0.30282 * track.sign() * (mBz * 0.1) * mRefR / (2.f * track.pt())); + phiPosition = RecoDecay::constrainAngle(phiPosition, 0, 1U); // 0-2pi if (mMinTrackPhiPosition < 0.f && mMaxTrackPhiPosition < M_PI) { // threshold across 0 rad. o2::math_utils::bringToPMPi(phiPosition); @@ -454,7 +463,7 @@ class DielectronCut : public TNamed return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; case DielectronCuts::kDCA3Dsigma: - return mMinDca3D < dca3DinSigma(track) && dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg + return mMinDca3D < o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track) && o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg case DielectronCuts::kDCAxy: return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); @@ -471,6 +480,9 @@ class DielectronCut : public TNamed case DielectronCuts::kITSClusterSize: return mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; + case DielectronCuts::kTTCA: + return mEnableTTCA ? true : track.isAssociatedToMPC(); + case DielectronCuts::kPrefilter: return track.pfb() <= 0; @@ -539,11 +551,12 @@ class DielectronCut : public TNamed void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); void IncludeITSsa(bool flag, float maxpt); + void EnableTTCA(bool flag); - void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) - { - mPIDMlResponse = mlResponse; - } + // void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) + // { + // mPIDMlResponse = mlResponse; + // } void SetMLThresholds(const std::vector bins, const std::vector cuts) { @@ -611,7 +624,7 @@ class DielectronCut : public TNamed float mMinMeanClusterSizeITS{0.0}, mMaxMeanClusterSizeITS{1e10f}; // x cos(lmabda) // float mMinP_ITSClusterSize{0.0}, mMaxP_ITSClusterSize{0.0}; bool mIncludeITSsa{false}; - float mMaxPtITSsa{0.15}; + float mMaxPtITSsa{1e+10}; // pid cuts int mPIDScheme{-1}; @@ -629,6 +642,7 @@ class DielectronCut : public TNamed float mMinTOFNsigmaPi{-1e+10}, mMaxTOFNsigmaPi{+1e+10}; float mMinTOFNsigmaKa{-1e+10}, mMaxTOFNsigmaKa{+1e+10}; float mMinTOFNsigmaPr{-1e+10}, mMaxTOFNsigmaPr{+1e+10}; + bool mEnableTTCA{true}; // float mMinITSNsigmaEl{-1e+10}, mMaxITSNsigmaEl{+1e+10}; // float mMinITSNsigmaMu{-1e+10}, mMaxITSNsigmaMu{+1e+10}; @@ -638,7 +652,7 @@ class DielectronCut : public TNamed // float mMinP_ITSNsigmaKa{0.0}, mMaxP_ITSNsigmaKa{0.0}; // float mMinP_ITSNsigmaPr{0.0}, mMaxP_ITSNsigmaPr{0.0}; - o2::analysis::MlResponseDielectronSingleTrack* mPIDMlResponse{nullptr}; + // o2::analysis::MlResponseDielectronSingleTrack* mPIDMlResponse{nullptr}; std::vector mMLBins{}; // binning for a feature variable. e.g. tpcInnerParam std::vector mMLCuts{}; // threshold for each bin. mMLCuts.size() must be mMLBins.size()-1. diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 0d06f99065d..b5ba7dad68e 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -26,285 +26,311 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" - -#include "Math/Vector4D.h" -#include "TString.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include +#include + +#include #include #include -#include +#include +#include +#include #include #include #include +#include #include +#include #include #include -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 namespace o2::aod::pwgem::dilepton::utils::pairutil; +#include -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyElectrons = soa::Join; +using MyElectrons = o2::soa::Join; using MyElectron = MyElectrons::iterator; -using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectrons = o2::soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; -using MyMuons = soa::Join; +using MyMuons = o2::soa::Join; using MyMuon = MyMuons::iterator; -using FilteredMyMuons = soa::Filtered; +using FilteredMyMuons = o2::soa::Filtered; using FilteredMyMuon = FilteredMyMuons::iterator; -using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; -using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMFwdTrack>; +using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>; +using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMFwdTrack>; 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, kHFll:5"}; - 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"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable ndepth{"ndepth", 1000, "depth for event mixing"}; - Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "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 cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; - // Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; - Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; - Configurable cfgUseSignedDCA{"cfgUseSignedDCA", false, "flag to use signs in the DCA calculation"}; - Configurable cfgPolarizationFrame{"cfgPolarizationFrame", 0, "frame of polarization. 0:CS, 1:HX, else:FATAL"}; - - 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 ConfYllBins{"ConYllBins", {1, -1.f, 1.f}, "yll bins for output histograms"}; // pair rapidity - - // 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. - - ConfigurableAxis ConfSPBins{"ConfSPBins", {200, -5, 5}, "SP bins for flow analysis"}; - ConfigurableAxis ConfPolarizationCosThetaBins{"ConfPolarizationCosThetaBins", {20, -1.f, 1.f}, "cos(theta) bins for polarization analysis"}; - ConfigurableAxis ConfPolarizationPhiBins{"ConfPolarizationPhiBins", {1, -M_PI, M_PI}, "phi bins for polarization analysis"}; - ConfigurableAxis ConfPolarizationQuadMomBins{"ConfPolarizationQuadMomBins", {15, -0.5, 1}, "quadrupole moment bins for polarization analysis"}; // quardrupole moment <(3 x cos^2(theta) -1)/2> + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + o2::framework::Configurable cfgApplySPresolution{"cfgApplySPresolution", false, "flag to apply resolution correction for flow analysis"}; + o2::framework::Configurable spresoPath{"spresoPath", "Users/d/dsekihat/PWGEM/dilepton/Qvector/resolution/LHC23zzh/pass3/test", "Path to SP resolution file"}; + o2::framework::Configurable spresoHistName{"spresoHistName", "h1_R2_FT0M_BPos_BNeg", "histogram name of SP resolution file"}; + + o2::framework::Configurable cfgAnalysisType{"cfgAnalysisType", static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC), "kQC:0, kUPC:1, kFlowV2:2, kFlowV3:3, kPolarization:4, kHFll:5, kBootstrapv2:6"}; + o2::framework::Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5, FV0A:6"}; + o2::framework::Configurable cfgQvecEstimator{"cfgQvecEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5, FV0A:6"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; + o2::framework::Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; + o2::framework::Configurable ndepth{"ndepth", 1000, "depth for event mixing"}; + o2::framework::Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; + o2::framework::ConfigurableAxis ConfVtxBins{"ConfVtxBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfCentBins{"ConfCentBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -M_PI / 2, +M_PI / 2}, "Mixing bins - event plane angle"}; + o2::framework::ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {o2::framework::VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + o2::framework::Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + o2::framework::Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; + o2::framework::Configurable cfgUseSignedDCA{"cfgUseSignedDCA", false, "flag to use signs in the DCA calculation"}; + o2::framework::Configurable cfgPolarizationFrame{"cfgPolarizationFrame", 0, "frame of polarization. 0:CS, 1:HX, else:FATAL"}; + + o2::framework::ConfigurableAxis ConfMllBins{"ConfMllBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfPtllBins{"ConfPtllBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfYllBins{"ConYllBins", {1, -1.f, 1.f}, "yll bins for output histograms"}; // pair rapidity + + // o2::framework::ConfigurableAxis ConfMmumuBins{"ConfMmumuBins", {o2::framework::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. + + o2::framework::ConfigurableAxis ConfSPBins{"ConfSPBins", {200, -5, 5}, "SP bins for flow analysis"}; + o2::framework::ConfigurableAxis ConfPolarizationCosThetaBins{"ConfPolarizationCosThetaBins", {20, -1.f, 1.f}, "cos(theta) bins for polarization analysis"}; + o2::framework::ConfigurableAxis ConfPolarizationPhiBins{"ConfPolarizationPhiBins", {1, -M_PI, M_PI}, "phi bins for polarization analysis"}; + o2::framework::ConfigurableAxis ConfPolarizationQuadMomBins{"ConfPolarizationQuadMomBins", {15, -0.5, 1}, "quadrupole moment bins for polarization analysis"}; // quardrupole moment <(3 x cos^2(theta) -1)/2> + + o2::framework::Configurable cfgNumBootstrapSamples{"cfgNumBootstrapSamples", 1, "Number of Bootstrap Samples"}; EMEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - 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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + o2::framework::Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::framework::Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + o2::framework::Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + o2::framework::Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + o2::framework::Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; } eventcuts; DielectronCut fDielectronCut; - struct : ConfigurableGroup { + struct : o2::framework::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_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_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; - Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; - Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; - Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; - Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; - Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; - - Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; - Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply pair cut same as prefilter set in derived data"}; - Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; - Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; - 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "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_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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; - Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. - Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; - Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; - 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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; - Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; - Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + o2::framework::Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + o2::framework::Configurable cfg_min_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; + o2::framework::Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; + o2::framework::Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; + // o2::framework::Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + o2::framework::Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + o2::framework::Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + o2::framework::Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + // o2::framework::Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // o2::framework::Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + o2::framework::Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + // o2::framework::Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // o2::framework::Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + o2::framework::Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; // configuration for PID ML - Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - 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)"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + o2::framework::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"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dielectroncuts; DimuonCut fDimuonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; - - 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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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+6, "max chi2/ndf"}; - Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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"}; - Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; - Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -4.0, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", -2.5, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // o2::framework::Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + o2::framework::Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "zorroGroup"; - Configurable cfg_swt_name{"cfg_swt_name", "fLMeeIMR", "desired software trigger name"}; // 1 trigger per 1 task + o2::framework::Configurable cfg_swt_name{"cfg_swt_name", "fLMeeIMR", "desired software trigger name. 1 trigger per 1 task."}; // 1 trigger per 1 task o2::framework::Configurable ccdbPathSoftwareTrigger{"ccdbPathSoftwareTrigger", "EventFiltering/Zorro/", "ccdb path for ZORRO objects"}; - Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; + o2::framework::Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; } zorroGroup; + Zorro zorro; + int mToIidx = 0; + int mTOICounter = 0; + int mATCounter = 0; + o2::aod::rctsel::RCTFlagsChecker rctChecker; // o2::ccdb::CcdbApi ccdbApi; - Service ccdb; - Zorro zorro; + o2::framework::Service ccdb; int mRunNumber; float d_bz; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::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/"}; @@ -326,10 +352,13 @@ struct Dilepton { float beamP2 = 0.f; // beam momentum TH2D* h2sp_resolution = nullptr; - void init(InitContext& /*context*/) + void init(o2::framework::InitContext& /*context*/) { mRunNumber = 0; d_bz = 0; + mToIidx = 0; + mTOICounter = 0; + mATCounter = 0; ccdb->setURL(ccdburl); ccdb->setCaching(true); @@ -337,11 +366,11 @@ struct Dilepton { ccdb->setFatalWhenNull(false); rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); - if (ConfVtxBins.value[0] == VARIABLE_WIDTH) { + if (ConfVtxBins.value[0] == o2::framework::VARIABLE_WIDTH) { zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); zvtx_bin_edges.erase(zvtx_bin_edges.begin()); for (const auto& edge : zvtx_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfVtxBins.value[0]); @@ -354,11 +383,11 @@ struct Dilepton { } } - if (ConfCentBins.value[0] == VARIABLE_WIDTH) { + if (ConfCentBins.value[0] == o2::framework::VARIABLE_WIDTH) { cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); cent_bin_edges.erase(cent_bin_edges.begin()); for (const auto& edge : cent_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: cent_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: cent_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfCentBins.value[0]); @@ -371,11 +400,11 @@ struct Dilepton { } } - if (ConfEPBins.value[0] == VARIABLE_WIDTH) { + if (ConfEPBins.value[0] == o2::framework::VARIABLE_WIDTH) { ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); ep_bin_edges.erase(ep_bin_edges.begin()); for (const auto& edge : ep_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: ep_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: ep_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfEPBins.value[0]); @@ -389,11 +418,11 @@ struct Dilepton { } LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); - if (ConfOccupancyBins.value[0] == VARIABLE_WIDTH) { + if (ConfOccupancyBins.value[0] == o2::framework::VARIABLE_WIDTH) { occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); occ_bin_edges.erase(occ_bin_edges.begin()); for (const auto& edge : occ_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: occ_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: occ_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfOccupancyBins.value[0]); @@ -421,14 +450,23 @@ struct Dilepton { leptonM2 = o2::constants::physics::MassMuon; } - fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); + fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", o2::framework::kTH1D, {{10001, -0.5, 10000.5}}, true); + + if (doprocessTriggerAnalysis) { + LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", zorroGroup.cfg_swt_name.value.data()); + fRegistry.add("Event/trigger/hInspectedTVX", "inspected TVX;run number;N_{TVX}", o2::framework::kTProfile, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hScaler", "trigger counter before DS;run number;counter", o2::framework::kTProfile, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hSelection", "trigger counter after DS;run number;counter", o2::framework::kTProfile, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hAnalysedTrigger", Form("analysed trigger %s;run number;counter", zorroGroup.cfg_swt_name.value.data()), o2::framework::kTH1D, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hAnalysedToI", Form("analysed ToI %s;run number;counter", zorroGroup.cfg_swt_name.value.data()), o2::framework::kTH1D, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + } if (doprocessNorm) { fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); - fRegistry.add("Event/norm/hZvtx", "hZvtx;Z_{vtx} (cm)", kTH1D, {{100, -50, +50}}, false); + fRegistry.add("Event/norm/hZvtx", "hZvtx;Z_{vtx} (cm)", o2::framework::kTH1D, {{100, -50, +50}}, false); } if (doprocessBC) { - auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", kTH1D, {{6, -0.5f, 5.5f}}); + auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", o2::framework::kTH1D, {{6, -0.5f, 5.5f}}); hTVXCounter->GetXaxis()->SetBinLabel(1, "TVX"); hTVXCounter->GetXaxis()->SetBinLabel(2, "TVX && NoTFB"); hTVXCounter->GetXaxis()->SetBinLabel(3, "TVX && NoITSROFB"); @@ -482,8 +520,17 @@ struct Dilepton { if constexpr (isTriggerAnalysis) { zorro.setCCDBpath(zorroGroup.ccdbPathSoftwareTrigger); zorro.setBCtolerance(zorroGroup.bcMarginForSoftwareTrigger); // this does nothing. - zorro.initCCDB(ccdb.service, collision.runNumber(), collision.timestamp(), zorroGroup.cfg_swt_name.value); + mToIidx = zorro.initCCDB(ccdb.service, collision.runNumber(), collision.timestamp(), zorroGroup.cfg_swt_name.value)[0]; zorro.populateHistRegistry(fRegistry, collision.runNumber()); + + uint64_t nInspectedTVX = zorro.getInspectedTVX()->GetBinContent(1); + uint64_t nScalers = zorro.getScalers()->GetBinContent(zorro.getScalers()->GetXaxis()->FindBin(zorroGroup.cfg_swt_name.value.data())); + uint64_t nSelections = zorro.getSelections()->GetBinContent(zorro.getSelections()->GetXaxis()->FindBin(zorroGroup.cfg_swt_name.value.data())); + LOGF(info, "run number %d: total inspected TVX events = %llu, scalers = %llu, selections = %llu", collision.runNumber(), nInspectedTVX, nScalers, nSelections); + + fRegistry.fill(HIST("Event/trigger/hInspectedTVX"), collision.runNumber(), nInspectedTVX); + fRegistry.fill(HIST("Event/trigger/hScaler"), collision.runNumber(), nScalers); + fRegistry.fill(HIST("Event/trigger/hSelection"), collision.runNumber(), nSelections); } mRunNumber = collision.runNumber(); @@ -525,7 +572,7 @@ struct Dilepton { void addhistograms() { - const std::string qvec_det_names[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; + const std::string qvec_det_names[7] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg", "FV0A"}; std::string mass_axis_title = "m_{ll} (GeV/c^{2})"; std::string pair_pt_axis_title = "p_{T,ll} (GeV/c)"; @@ -552,27 +599,27 @@ struct Dilepton { } // 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}; - const AxisSpec axis_y{ConfYllBins, pair_y_axis_title}; + const o2::framework::AxisSpec axis_mass{ConfMllBins, mass_axis_title}; + const o2::framework::AxisSpec axis_pt{ConfPtllBins, pair_pt_axis_title}; + const o2::framework::AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; + const o2::framework::AxisSpec axis_y{ConfYllBins, pair_y_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, axis_y}, true); - fRegistry.add("Pair/same/uls/hDeltaEtaDeltaPhi", "#Delta#eta-#Delta#varphi between 2 tracks;#Delta#varphi (rad.);#Delta#eta;", kTH2D, {{180, -M_PI, M_PI}, {400, -2, +2}}, true); + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); + fRegistry.add("Pair/same/uls/hDeltaEtaDeltaPhi", "#Delta#eta-#Delta#varphi between 2 tracks;#Delta#varphi (rad.);#Delta#eta;", o2::framework::kTH2D, {{180, -M_PI, M_PI}, {400, -2, +2}}, 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, 1.0f}}, true); // phiv is only for dielectron - fRegistry.add("Pair/same/uls/hMvsOpAng", "m_{ee} vs. angle between 2 tracks;#omega (rad.);m_{ee} (GeV/c^{2})", kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); - fRegistry.add("Pair/same/uls/hDCA1vsDCA2", "DCA of leg1 vs. DCA of leg2;DCA1(#sigma);DCA2 (#sigma)", kTH2D, {{100, 0, 10.0}, {100, 0, 10}}, true); + fRegistry.add("Pair/same/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", o2::framework::kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); // phiv is only for dielectron + fRegistry.add("Pair/same/uls/hMvsOpAng", "m_{ee} vs. angle between 2 tracks;#omega (rad.);m_{ee} (GeV/c^{2})", o2::framework::kTH2D, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add("Pair/same/uls/hDCA1vsDCA2", "DCA of leg1 vs. DCA of leg2;DCA1(#sigma);DCA2 (#sigma)", o2::framework::kTH2D, {{200, -10, 10.0}, {200, -10, 10}}, 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::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 o2::framework::AxisSpec axis_aco{10, 0, 1.f, "#alpha = 1 - #frac{|#varphi_{l^{+}} - #varphi_{l^{-}}|}{#pi}"}; + const o2::framework::AxisSpec axis_asym_pt{10, 0, 1.f, "A = #frac{|p_{T,l^{+}} - p_{T,l^{-}}|}{|p_{T,l^{+}} + p_{T,l^{-}}|}"}; + const o2::framework::AxisSpec axis_dphi_e_ee{18, 0, M_PI, "#Delta#varphi = #varphi_{l} - #varphi_{ll} (rad.)"}; std::string frameName = "CS"; if (cfgPolarizationFrame == 0) { @@ -582,8 +629,8 @@ struct Dilepton { } else { LOG(fatal) << "set 0 or 1 to cfgPolarizationFrame!"; } - const AxisSpec axis_cos_theta{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; - fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_cos_theta}, true); + const o2::framework::AxisSpec axis_cos_theta{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_cos_theta}, true); fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); fRegistry.addClone("Pair/same/", "Pair/mix/"); @@ -594,13 +641,13 @@ struct Dilepton { nmod = 3; } - const AxisSpec axis_sp{ConfSPBins, Form("#vec{u}_{%d,ll} #upoint #vec{Q}_{%d}^{%s}", nmod, nmod, qvec_det_names[cfgQvecEstimator].data())}; + const o2::framework::AxisSpec axis_sp{ConfSPBins, Form("#vec{u}_{%d,ll} #upoint #vec{Q}_{%d}^{%s}", nmod, nmod, qvec_det_names[cfgQvecEstimator].data())}; - fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_sp}, true); + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_sp}, 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, axis_y}, true); + fRegistry.add("Pair/mix/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); fRegistry.addClone("Pair/mix/uls/", "Pair/mix/lspp/"); fRegistry.addClone("Pair/mix/uls/", "Pair/mix/lsmm/"); @@ -614,23 +661,34 @@ struct Dilepton { LOG(fatal) << "set 0 or 1 to cfgPolarizationFrame!"; } - const AxisSpec axis_cos_theta{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; - const AxisSpec axis_phi{ConfPolarizationPhiBins, Form("#varphi^{%s} (rad.)", frameName.data())}; - const AxisSpec axis_quadmom{ConfPolarizationQuadMomBins, Form("#frac{3 cos^{2}(#theta^{%s}) -1}{2}", frameName.data())}; - fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_cos_theta, axis_phi, axis_quadmom}, true); + const o2::framework::AxisSpec axis_cos_theta{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; + const o2::framework::AxisSpec axis_phi{ConfPolarizationPhiBins, Form("#varphi^{%s} (rad.)", frameName.data())}; + const o2::framework::AxisSpec axis_quadmom{ConfPolarizationQuadMomBins, Form("#frac{3 cos^{2}(#theta^{%s}) -1}{2}", frameName.data())}; + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_cos_theta, axis_phi, axis_quadmom}, 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{36, -M_PI / 2., 3. / 2. * M_PI, "#Delta#varphi = #varphi_{l1} - #varphi_{l2} (rad.)"}; // for kHFll - const AxisSpec axis_deta_ee{40, -2., 2., "#Delta#eta = #eta_{l1} - #eta_{l2}"}; - fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_dphi_ee, axis_deta_ee}, true); + const o2::framework::AxisSpec axis_dphi_ee{36, -M_PI / 2., 3. / 2. * M_PI, "#Delta#varphi = #varphi_{l1} - #varphi_{l2} (rad.)"}; // for kHFll + const o2::framework::AxisSpec axis_deta_ee{40, -2., 2., "#Delta#eta = #eta_{l1} - #eta_{l2}"}; + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_dphi_ee, axis_deta_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 if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kBootstrapv2)) { + nmod = 2; + const o2::framework::AxisSpec axis_sp{ConfSPBins, Form("#vec{u}_{%d,ll} #upoint #vec{Q}_{%d}^{%s}", nmod, nmod, qvec_det_names[cfgQvecEstimator].data())}; + const o2::framework::AxisSpec axis_bootstrap{cfgNumBootstrapSamples, 0.5, static_cast(cfgNumBootstrapSamples) + 0.5, "sample"}; // for bootstrap samples + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_sp, axis_bootstrap}, true); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lspp/"); + fRegistry.addClone("Pair/same/uls/", "Pair/same/lsmm/"); + fRegistry.add("Pair/mix/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); + fRegistry.addClone("Pair/mix/uls/", "Pair/mix/lspp/"); + fRegistry.addClone("Pair/mix/uls/", "Pair/mix/lsmm/"); + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistogramsBootstrap(&fRegistry, cfgNumBootstrapSamples); } else { // same as kQC to avoid seg. fault - fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); + fRegistry.add("Pair/same/uls/hs", "dilepton", o2::framework::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/"); @@ -644,8 +702,8 @@ struct Dilepton { } 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); + 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()), o2::framework::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()), o2::framework::kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); } void DefineEMEventCut() @@ -670,7 +728,6 @@ struct Dilepton { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -684,7 +741,7 @@ struct Dilepton { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); @@ -703,8 +760,8 @@ struct Dilepton { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -728,31 +785,6 @@ struct Dilepton { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } @@ -776,13 +808,15 @@ struct Dilepton { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); 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); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -824,7 +858,7 @@ struct Dilepton { } template - bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + bool fillPairInfo(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&, const std::vector weightvector) { if constexpr (ev_id == 0) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -841,13 +875,16 @@ struct Dilepton { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } } @@ -866,8 +903,8 @@ struct Dilepton { if (cfgApplyWeightTTCA) { weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; } + // 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); } - // 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); @@ -876,25 +913,25 @@ struct Dilepton { float pair_dca = 999.f; if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (cfgUseSignedDCA) { - pair_dca = pairDCASignQuadSum(dca3DinSigma(t1), dca3DinSigma(t2), t1.sign(), t2.sign()); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCASignQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2), t1.sign(), t2.sign()); } else { - pair_dca = pairDCAQuadSum(dca3DinSigma(t1), dca3DinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2)); } if (cfgDCAType == 1) { if (cfgUseSignedDCA) { - pair_dca = pairDCASignQuadSum(dcaXYinSigma(t1), dcaXYinSigma(t2), t1.sign(), t2.sign()); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCASignQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2), t1.sign(), t2.sign()); } else { - pair_dca = pairDCAQuadSum(dcaXYinSigma(t1), dcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2)); } } else if (cfgDCAType == 2) { if (cfgUseSignedDCA) { - pair_dca = pairDCASignQuadSum(dcaZinSigma(t1), dcaZinSigma(t2), t1.sign(), t2.sign()); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCASignQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2), t1.sign(), t2.sign()); } else { - pair_dca = pairDCAQuadSum(dcaZinSigma(t1), dcaZinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { - pair_dca = pairDCAQuadSum(fwdDcaXYinSigma(t1), fwdDcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t2)); } if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC)) { @@ -912,9 +949,9 @@ struct Dilepton { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsOpAng"), opAng, v12.M(), weight); if (cfgDCAType == 1) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDCA1vsDCA2"), dcaXYinSigma(t1), dcaXYinSigma(t2), weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDCA1vsDCA2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2), weight); } else if (cfgDCAType == 2) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDCA1vsDCA2"), dcaZinSigma(t1), dcaZinSigma(t2), weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDCA1vsDCA2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2), weight); } } } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ @@ -924,9 +961,9 @@ struct Dilepton { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsOpAng"), opAng, v12.M(), weight); if (cfgDCAType == 1) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDCA1vsDCA2"), dcaXYinSigma(t1), dcaXYinSigma(t2), weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDCA1vsDCA2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2), weight); } else if (cfgDCAType == 2) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDCA1vsDCA2"), dcaZinSigma(t1), dcaZinSigma(t2), weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDCA1vsDCA2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2), weight); } } } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- @@ -936,9 +973,9 @@ struct Dilepton { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsOpAng"), opAng, v12.M(), weight); if (cfgDCAType == 1) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDCA1vsDCA2"), dcaXYinSigma(t1), dcaXYinSigma(t2), weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDCA1vsDCA2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2), weight); } else if (cfgDCAType == 2) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDCA1vsDCA2"), dcaZinSigma(t1), dcaZinSigma(t2), weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDCA1vsDCA2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2), weight); } } } @@ -976,18 +1013,20 @@ struct Dilepton { std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q2fv0a = {collision.q2xfv0a(), collision.q2yfv0a()}; 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::array q3fv0a = {collision.q3xfv0a(), collision.q3yfv0a()}; 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}, {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}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg, q2fv0a}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg, q3fv0a}, // 3rd harmonics }; if constexpr (ev_id == 0) { @@ -1032,7 +1071,6 @@ struct Dilepton { } 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(), cos_thetaPol, phiPol, quadmom, weight); } - } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kHFll)) { float dphi = v1.Phi() - v2.Phi(); dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf); @@ -1046,6 +1084,51 @@ struct Dilepton { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), dphi, deta, weight); } + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kBootstrapv2)) { + 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 q2fv0a = {collision.q2xfv0a(), collision.q2yfv0a()}; + 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::array q3fv0a = {collision.q3xfv0a(), collision.q3yfv0a()}; + + 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}, {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}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg, q2fv0a}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg, q3fv0a}, // 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()); + for (int i = 0; i < cfgNumBootstrapSamples; i++) { + 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(), sp, i + 0.5, weightvector.at(i)); + } 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(), sp, i + 0.5, weightvector.at(i)); + } 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(), sp, i + 0.5, weightvector.at(i)); + } + } + } 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, 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 { // 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, v12.Rapidity(), weight); @@ -1065,9 +1148,9 @@ struct Dilepton { used_trackIds_per_col.emplace_back(t1.globalIndex()); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); } } } @@ -1075,9 +1158,9 @@ struct Dilepton { used_trackIds_per_col.emplace_back(t2.globalIndex()); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); } } } @@ -1086,9 +1169,9 @@ struct Dilepton { used_trackIds_per_col.emplace_back(t1.globalIndex()); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } } } @@ -1096,9 +1179,9 @@ struct Dilepton { used_trackIds_per_col.emplace_back(t2.globalIndex()); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } } } @@ -1107,47 +1190,54 @@ struct Dilepton { 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_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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 && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); - Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); - - Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfb >= static_cast(0)); - - 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 && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_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); + o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = o2::soa::Filtered; + + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::expressions::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 && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; + o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + + o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); + o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track; + o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + + o2::framework::Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); + o2::framework::Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); TEMH* emh_pos = nullptr; TEMH* emh_neg = nullptr; std::map, uint64_t> map_mixed_eventId_to_globalBC; + std::unordered_map map_best_match_globalmuon; std::vector used_trackIds_per_col; int ndf = 0; @@ -1160,7 +1250,7 @@ struct Dilepton { const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; float centrality = centralities[cfgCentEstimator]; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1170,20 +1260,22 @@ struct Dilepton { std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q2fv0a = {collision.q2xfv0a(), collision.q2yfv0a()}; 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()}; + std::array q3fv0a = {collision.q3xfv0a(), collision.q3yfv0a()}; + const float eventplanes_2_for_mix[7] = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg(), collision.ep2fv0a()}; 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 + {{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}}, // 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}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg, q2fv0a}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg, q3fv0a}, // 3rd harmonics }; if (nmod == 2) { @@ -1213,6 +1305,37 @@ struct Dilepton { if (!zorro.isSelected(collision.globalBC(), zorroGroup.bcMarginForSoftwareTrigger)) { // triggered event continue; } + + auto swt_bitset = zorro.getLastResult(); // this has to be called after zorro::isSelected + auto TOIcounter = zorro.getTOIcounters()[0]; // this has to be called after zorro::isSelected + auto ATcounter = zorro.getATcounters()[mToIidx]; // this has to be called after zorro::isSelected + + if (swt_bitset.test(mToIidx)) { + while (ATcounter > mATCounter) { + mATCounter++; + fRegistry.fill(HIST("Event/trigger/hAnalysedTrigger"), collision.runNumber()); + } + + while (TOIcounter > mTOICounter) { + fRegistry.fill(HIST("Event/trigger/hAnalysedToI"), collision.runNumber()); + mTOICounter++; // always incremented by 1 in zorro!! + } + // LOGF(info, "collision.globalIndex() = %d, collision.globalBC() = %llu, mTOICounter = %d, mATcounter = %d", collision.globalIndex(), collision.globalBC(), mTOICounter, mATCounter); + } + } + + std::vector bootstrapweights = {}; + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kBootstrapv2)) { // bootstrapping for accepted events + int randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + TRandom3 randomNumber(randomSeed); + for (int i = 0; i < cfgNumBootstrapSamples; i++) { + float poissonweight = 0.; + poissonweight = static_cast(randomNumber.PoissonD(1.0)); + bootstrapweights.push_back(poissonweight); + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfoBootstrap(&fRegistry, collision, i, poissonweight); + } + } else { + bootstrapweights.push_back(1.0); // to pass as non-empyt dummy to use } if (nmod == 2) { @@ -1234,20 +1357,20 @@ struct Dilepton { used_trackIds_per_col.reserve(posTracks_per_coll.size() + negTracks_per_coll.size()); int nuls = 0, nlspp = 0, nlsmm = 0; - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - bool is_pair_ok = fillPairInfo<0>(collision, pos, neg, cut, tracks); + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + bool is_pair_ok = fillPairInfo<0>(collision, pos, neg, cut, tracks, bootstrapweights); if (is_pair_ok) { nuls++; } } - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - bool is_pair_ok = fillPairInfo<0>(collision, pos1, pos2, cut, tracks); + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + bool is_pair_ok = fillPairInfo<0>(collision, pos1, pos2, cut, tracks, bootstrapweights); if (is_pair_ok) { nlspp++; } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- - bool is_pair_ok = fillPairInfo<0>(collision, neg1, neg2, cut, tracks); + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + bool is_pair_ok = fillPairInfo<0>(collision, neg1, neg2, cut, tracks, bootstrapweights); if (is_pair_ok) { nlsmm++; } @@ -1329,25 +1452,25 @@ struct Dilepton { for (const auto& pos : selected_posTracks_in_this_event) { // ULS mix for (const auto& neg : negTracks_from_event_pool) { - fillPairInfo<1>(collision, pos, neg, cut, nullptr); + fillPairInfo<1>(collision, pos, neg, cut, nullptr, bootstrapweights); } } for (const auto& neg : selected_negTracks_in_this_event) { // ULS mix for (const auto& pos : posTracks_from_event_pool) { - fillPairInfo<1>(collision, neg, pos, cut, nullptr); + fillPairInfo<1>(collision, neg, pos, cut, nullptr, bootstrapweights); } } for (const auto& pos1 : selected_posTracks_in_this_event) { // LS++ mix for (const auto& pos2 : posTracks_from_event_pool) { - fillPairInfo<1>(collision, pos1, pos2, cut, nullptr); + fillPairInfo<1>(collision, pos1, pos2, cut, nullptr, bootstrapweights); } } for (const auto& neg1 : selected_negTracks_in_this_event) { // LS-- mix for (const auto& neg2 : negTracks_from_event_pool) { - fillPairInfo<1>(collision, neg1, neg2, cut, nullptr); + fillPairInfo<1>(collision, neg1, neg2, cut, nullptr, bootstrapweights); } } } // end of loop over mixed event pool @@ -1363,7 +1486,7 @@ struct Dilepton { } // end of DF template - bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { @@ -1379,13 +1502,16 @@ struct Dilepton { if (!cut.IsSelectedTrack(t1) || !cut.IsSelectedTrack(t2)) { return false; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -1410,7 +1536,7 @@ struct Dilepton { for (const auto& collision : collisions) { initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1426,18 +1552,20 @@ struct Dilepton { std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; std::array q2bpos = {collision.q2xbpos(), collision.q2ybpos()}; std::array q2bneg = {collision.q2xbneg(), collision.q2ybneg()}; + std::array q2fv0a = {collision.q2xfv0a(), collision.q2yfv0a()}; 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::array q3fv0a = {collision.q3xfv0a(), collision.q3yfv0a()}; 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}, {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}, {999.f, 999.f}}, // 1st harmonics + {q2ft0m, q2ft0a, q2ft0c, q2btot, q2bpos, q2bneg, q2fv0a}, // 2nd harmonics + {q3ft0m, q3ft0a, q3ft0c, q3btot, q3bpos, q3bneg, q3fv0a}, // 3rd harmonics }; if (!fEMEventCut.IsSelected(collision)) { @@ -1454,17 +1582,17 @@ struct Dilepton { auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS if (isPairOK(pos, neg, cut, tracks)) { passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); } } - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (isPairOK(pos1, pos2, cut, tracks)) { passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (isPairOK(neg1, neg2, cut, tracks)) { passed_pairIds.emplace_back(std::make_pair(neg1.globalIndex(), neg2.globalIndex())); } @@ -1475,7 +1603,6 @@ struct Dilepton { for (const 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 (const auto& ambId1 : t1.ambiguousElectronsIds()) { @@ -1517,12 +1644,14 @@ struct Dilepton { runPairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(muons, fDimuonCut); 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, muons); } map_weight.clear(); + map_best_match_globalmuon.clear(); ndf++; } PROCESS_SWITCH(Dilepton, processAnalysis, "run dilepton analysis", true); @@ -1537,47 +1666,49 @@ struct Dilepton { runPairing(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(muons, fDimuonCut); 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, muons); } map_weight.clear(); + map_best_match_globalmuon.clear(); ndf++; } PROCESS_SWITCH(Dilepton, processTriggerAnalysis, "run dilepton analysis on triggered data", false); - void processNorm(aod::EMEventNormInfos const& collisions) + void processNorm(o2::aod::EMEventNormInfos const& collisions) { for (const auto& collision : collisions) { - if (collision.centFT0C() < cfgCentMin || cfgCentMax < collision.centFT0C()) { + if (collision.centFT0C() < eventcuts.cfgCentMin || eventcuts.cfgCentMax < collision.centFT0C()) { continue; } fRegistry.fill(HIST("Event/norm/hZvtx"), collision.posZ()); fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -1586,28 +1717,28 @@ struct Dilepton { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -1621,25 +1752,25 @@ struct Dilepton { } PROCESS_SWITCH(Dilepton, processNorm, "process normalization info", false); - void processBC(aod::EMBCs const& bcs) + void processBC(o2::aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h index 856d5d7f740..d93d829ecdb 100644 --- a/PWGEM/Dilepton/Core/DileptonHadronMPC.h +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -27,295 +27,307 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" - -#include "Math/Vector4D.h" -#include "TString.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include #include -#include +#include +#include +#include #include -#include #include #include +#include #include +#include #include #include -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 namespace o2::aod::pwgem::dilepton::utils::pairutil; +#include -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyElectrons = soa::Join; +using MyElectrons = o2::soa::Join; using MyElectron = MyElectrons::iterator; -using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectrons = o2::soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; -using MyMuons = soa::Join; +using MyMuons = o2::soa::Join; using MyMuon = MyMuons::iterator; -using FilteredMyMuons = soa::Filtered; +using FilteredMyMuons = o2::soa::Filtered; using FilteredMyMuon = FilteredMyMuons::iterator; -using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; -using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMFwdTrack>; -using MyEMH_track = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; // for charged track +using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>; +using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMFwdTrack>; +using MyEMH_track = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>; // for charged track template struct DileptonHadronMPC { // 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 cfgAnalysisType{"cfgAnalysisType", static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation), "kAzimuthalCorrelation:0, kCumulant:1"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable ndepth_lepton{"ndepth_lepton", 100, "depth for event mixing between lepton-lepton"}; - Configurable ndepth_hadron{"ndepth_hadron", 1, "depth for event mixing between hadron-hadron"}; - Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "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 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 + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + o2::framework::Configurable cfgAnalysisType{"cfgAnalysisType", static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation), "kAzimuthalCorrelation:0, kCumulant:1"}; + o2::framework::Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5, FV0A:6"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; + o2::framework::Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing between 2 leptons (i.e. R factor)"}; + o2::framework::Configurable ndepth_lepton{"ndepth_lepton", 100, "depth for event mixing between lepton-lepton"}; + o2::framework::Configurable ndepth_hadron{"ndepth_hadron", 10, "depth for event mixing between hadron-hadron"}; + o2::framework::Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; + o2::framework::ConfigurableAxis ConfVtxBins{"ConfVtxBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfCentBins{"ConfCentBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfEPBins{"ConfEPBins", {16, -M_PI / 2, +M_PI / 2}, "Mixing bins - event plane angle"}; + o2::framework::ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {o2::framework::VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; // 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 cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; + o2::framework::Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + o2::framework::Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; - 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.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.00}, "pTll bins for output histograms"}; - ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {VARIABLE_WIDTH, 0.0, 0.5, 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}, "DCAll bins for output histograms"}; + o2::framework::ConfigurableAxis ConfMllBins{"ConfMllBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfPtllBins{"ConfPtllBins", {o2::framework::VARIABLE_WIDTH, 0.00, 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.00}, "pTll bins for output histograms"}; + o2::framework::ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {o2::framework::VARIABLE_WIDTH, 0.0, 0.5, 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}, "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. - - ConfigurableAxis ConfPtHadronBins{"ConfPtHadronBins", {VARIABLE_WIDTH, 0.00, 0.15, 0.2, 0.3, 0.4, 0.50, 1.00, 2.00, 3.00, 4.00, 5.00}, "pT,h bins for output histograms"}; - ConfigurableAxis ConfYllBins{"ConfYllBins", {1, -1.f, 1.f}, "yll bins for output histograms"}; // pair rapidity - ConfigurableAxis ConfDEtaBins{"ConfDEtaBins", {120, -6, 6}, "deta bins for output histograms"}; - Configurable cfgNbinsDPhi{"cfgNbinsDPhi", 36, "nbins in dphi for output histograms"}; - Configurable cfgNbinsCosNDPhi{"cfgNbinsCosNDPhi", 200, "nbins in cos(n(dphi)) for output histograms"}; - Configurable cfgNmod{"cfgNmod", 2, "n-th harmonics"}; + o2::framework::ConfigurableAxis ConfPtHadronBins{"ConfPtHadronBins", {50, 0, 5}, "pT,h bins for output histograms"}; + o2::framework::ConfigurableAxis ConfYllBins{"ConfYllBins", {1, -1.f, 1.f}, "yll bins for output histograms"}; // pair rapidity + o2::framework::ConfigurableAxis ConfDEtaBins{"ConfDEtaBins", {120, -6, 6}, "deta bins for output histograms"}; + o2::framework::Configurable cfgNbinsDPhi{"cfgNbinsDPhi", 36, "nbins in dphi for output histograms"}; + o2::framework::Configurable cfgNbinsCosNDPhi{"cfgNbinsCosNDPhi", 200, "nbins in cos(n(dphi)) for output histograms"}; + o2::framework::Configurable cfgNmod{"cfgNmod", 2, "n-th harmonics"}; EMEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - 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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + o2::framework::Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::framework::Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + o2::framework::Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + o2::framework::Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + o2::framework::Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; } eventcuts; DielectronCut fDielectronCut; - struct : ConfigurableGroup { + struct : o2::framework::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_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_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; - Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; - Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; - Configurable cfg_apply_detadphiposition{"cfg_apply_detadphiposition", false, "flag to apply deta-dphi elliptic cut at certain radius"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; - - Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; - Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply pair cut same as prefilter set in derived data"}; - Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - 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 cfgRefR{"cfgRefR", 1.2, "reference R (in m) for extrapolation"}; // https://cds.cern.ch/record/1419204 - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; - 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_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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; - Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; - Configurable enableTTCA{"enableTTCA", false, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + o2::framework::Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + o2::framework::Configurable cfg_min_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; + o2::framework::Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; + o2::framework::Configurable cfg_apply_detadphiposition{"cfg_apply_detadphiposition", false, "flag to apply deta-dphi elliptic cut at certain radius"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + o2::framework::Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply pair cut same as prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfgRefR{"cfgRefR", 0.5, "reference R (in m) for extrapolation"}; // https://cds.cern.ch/record/1419204 + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + o2::framework::Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + o2::framework::Configurable enableTTCA{"enableTTCA", false, "Flag to enable or disable TTCA"}; // configuration for PID ML - Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - 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)"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + o2::framework::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"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dielectroncuts; DimuonCut fDimuonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; - - 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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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", 6, "min ncluster MFT"}; - Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 8, "min ncluster MCH"}; - Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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", false, "Flag to enable or disable TTCA"}; - Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; - Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -4.0, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", -2.5, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // o2::framework::Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + o2::framework::Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + o2::framework::Configurable enableTTCA{"enableTTCA", false, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; EMTrackCut fEMTrackCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "trackcut_group"; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for ref. track"}; - Configurable cfg_max_pt_track{"cfg_max_pt_track", 3.0, "max pT for ref. track"}; - Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for ref. track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for ref. track"}; - // Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.0, "min phi for ref. track"}; - // Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for ref. track"}; - // Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.5, "max dca XY for single track in cm"}; - // Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.5, "max dca Z for single track in cm"}; - Configurable cfg_track_bits{"cfg_track_bits", 5765, "required track bits"}; // default:645, loose:0, tight:778 + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for ref. track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 3.0, "max pT for ref. track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for ref. track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for ref. track"}; + // o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.0, "min phi for ref. track"}; + // o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for ref. track"}; + o2::framework::Configurable cfg_track_bits{"cfg_track_bits", 0, "required track bits"}; + o2::framework::Configurable cfg_reftrack_type{"cfg_reftrack_type", 0, "ref. track type for 2PC. 0:kCB, 1:kMFTsa"}; // this is unique in the derived data. Check which track type you store as aod::EMPrimaryTracks. } trackcuts; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "zorroGroup"; - Configurable cfg_swt_name{"cfg_swt_name", "fLMeeIMR", "desired software trigger name"}; // 1 trigger per 1 task + o2::framework::Configurable cfg_swt_name{"cfg_swt_name", "fLMeeIMR", "desired software trigger name"}; // 1 trigger per 1 task o2::framework::Configurable ccdbPathSoftwareTrigger{"ccdbPathSoftwareTrigger", "EventFiltering/Zorro/", "ccdb path for ZORRO objects"}; - Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; + o2::framework::Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; } zorroGroup; o2::aod::rctsel::RCTFlagsChecker rctChecker; // o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + o2::framework::Service ccdb; int mRunNumber; float d_bz; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; Zorro zorro; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::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; - void init(InitContext& /*context*/) + void init(o2::framework::InitContext& /*context*/) { mRunNumber = 0; d_bz = 0; @@ -326,11 +338,11 @@ struct DileptonHadronMPC { ccdb->setFatalWhenNull(false); rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); - if (ConfVtxBins.value[0] == VARIABLE_WIDTH) { + if (ConfVtxBins.value[0] == o2::framework::VARIABLE_WIDTH) { zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); zvtx_bin_edges.erase(zvtx_bin_edges.begin()); for (const auto& edge : zvtx_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: zvtx_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfVtxBins.value[0]); @@ -343,11 +355,11 @@ struct DileptonHadronMPC { } } - if (ConfCentBins.value[0] == VARIABLE_WIDTH) { + if (ConfCentBins.value[0] == o2::framework::VARIABLE_WIDTH) { cent_bin_edges = std::vector(ConfCentBins.value.begin(), ConfCentBins.value.end()); cent_bin_edges.erase(cent_bin_edges.begin()); for (const auto& edge : cent_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: cent_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: cent_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfCentBins.value[0]); @@ -360,12 +372,29 @@ struct DileptonHadronMPC { } } + if (ConfEPBins.value[0] == o2::framework::VARIABLE_WIDTH) { + ep_bin_edges = std::vector(ConfEPBins.value.begin(), ConfEPBins.value.end()); + ep_bin_edges.erase(ep_bin_edges.begin()); + for (const auto& edge : ep_bin_edges) { + LOGF(info, "o2::framework::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]); + } + } + LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); - if (ConfOccupancyBins.value[0] == VARIABLE_WIDTH) { + if (ConfOccupancyBins.value[0] == o2::framework::VARIABLE_WIDTH) { occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); occ_bin_edges.erase(occ_bin_edges.begin()); for (const auto& edge : occ_bin_edges) { - LOGF(info, "VARIABLE_WIDTH: occ_bin_edges = %f", edge); + LOGF(info, "o2::framework::VARIABLE_WIDTH: occ_bin_edges = %f", edge); } } else { int nbins = static_cast(ConfOccupancyBins.value[0]); @@ -396,11 +425,11 @@ struct DileptonHadronMPC { } if (doprocessTriggerAnalysis) { - LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", cfg_swt_name.value); - fRegistry.add("NormTrigger/hInspectedTVX", "inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); - fRegistry.add("NormTrigger/hScalers", "trigger counter before DS;run number;counter", kTProfile, {{80000, 520000.5, 600000.5}}, true); - fRegistry.add("NormTrigger/hSelections", "trigger counter after DS;run number;counter", kTProfile, {{80000, 520000.5, 600000.5}}, true); - auto hTriggerCounter = fRegistry.add("NormTrigger/hTriggerCounter", Form("trigger counter of %s;run number;", cfg_swt_name.value.data()), kTH2D, {{80000, 520000.5, 600000.5}, {2, -0.5, 1.5}}, false); + LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", zorroGroup.cfg_swt_name.value); + fRegistry.add("NormTrigger/hInspectedTVX", "inspected TVX;run number;N_{TVX}", o2::framework::kTProfile, {{80000, 520000.5, 600000.5}}, true); + fRegistry.add("NormTrigger/hScalers", "trigger counter before DS;run number;counter", o2::framework::kTProfile, {{80000, 520000.5, 600000.5}}, true); + fRegistry.add("NormTrigger/hSelections", "trigger counter after DS;run number;counter", o2::framework::kTProfile, {{80000, 520000.5, 600000.5}}, true); + auto hTriggerCounter = fRegistry.add("NormTrigger/hTriggerCounter", Form("trigger counter of %s;run number;", zorroGroup.cfg_swt_name.value.data()), o2::framework::kTH2D, {{80000, 520000.5, 600000.5}, {2, -0.5, 1.5}}, false); hTriggerCounter->GetYaxis()->SetBinLabel(1, "Analyzed Trigger"); hTriggerCounter->GetYaxis()->SetBinLabel(2, "Analyzed TOI"); } @@ -472,8 +501,10 @@ struct DileptonHadronMPC { void addhistograms() { + static constexpr std::string_view qvec_det_names[7] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg", "FV0A"}; // event info o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); + fRegistry.add("Event/after/hMultNTracksPV_RefTracks", "Track mult. correlation;N_{track}^{PV};N_{track} for ref. flow", o2::framework::kTH2D, {{501, -0.5, 500.5}, {501, -0.5, 500.5}}, false); std::string mass_axis_title = "m_{ll} (GeV/c^{2})"; std::string pair_pt_axis_title = "p_{T,ll} (GeV/c)"; @@ -507,55 +538,59 @@ struct DileptonHadronMPC { } // dilepton 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}; - const AxisSpec axis_y{ConfYllBins, pair_rapidity_axis_title}; + const o2::framework::AxisSpec axis_mass{ConfMllBins, mass_axis_title}; + const o2::framework::AxisSpec axis_pt{ConfPtllBins, pair_pt_axis_title}; + const o2::framework::AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; + const o2::framework::AxisSpec axis_y{ConfYllBins, pair_rapidity_axis_title}; // dilepton-hadron info - const AxisSpec axis_deta{ConfDEtaBins, deta_axis_title}; + const o2::framework::AxisSpec axis_deta{ConfDEtaBins, deta_axis_title}; // hadron-hadron info - const AxisSpec axis_deta_hh{60, -3, +3, "#Delta#eta = #eta_{h}^{ref1} - #eta_{h}^{ref2}"}; + const o2::framework::AxisSpec axis_deta_hh{40, -2, +2, "#Delta#eta = #eta_{h}^{ref1} - #eta_{h}^{ref2}"}; - const AxisSpec axis_pt_trg{ConfPtHadronBins, "p_{T,h} (GeV/c)"}; - const AxisSpec axis_eta_trg{40, -2, +2, "#eta_{h}"}; - const AxisSpec axis_phi_trg{36, 0, 2 * M_PI, "#varphi_{h} (rad.)"}; - fRegistry.add("Hadron/hs", "hadron", kTHnSparseD, {axis_pt_trg, axis_eta_trg, axis_phi_trg}, false); - fRegistry.add("Hadron/hTrackBit", "track bit", kTH1D, {{65536, -0.5, 65535.5}}, false); + const o2::framework::AxisSpec axis_pt_trg{ConfPtHadronBins, "p_{T,h} (GeV/c)"}; + const o2::framework::AxisSpec axis_eta_trg{40, -2, +2, "#eta_{h}"}; + const o2::framework::AxisSpec axis_phi_trg{36, 0, 2 * M_PI, "#varphi_{h} (rad.)"}; + fRegistry.add("Hadron/hs", "hadron", o2::framework::kTHnSparseD, {axis_pt_trg, axis_eta_trg, axis_phi_trg}, false); + fRegistry.add("Hadron/hTrackBit", "track bit", o2::framework::kTH1D, {{65536, -0.5, 65535.5}}, false); - fRegistry.add("Dilepton/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); + fRegistry.add("Dilepton/same/uls/hs", "dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y}, true); fRegistry.addClone("Dilepton/same/uls/", "Dilepton/same/lspp/"); fRegistry.addClone("Dilepton/same/uls/", "Dilepton/same/lsmm/"); fRegistry.addClone("Dilepton/same/", "Dilepton/mix/"); if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { - const AxisSpec axis_dphi{cfgNbinsDPhi, -M_PI / 2, 3 * M_PI / 2, dphi_axis_title}; + const o2::framework::AxisSpec axis_dphi{cfgNbinsDPhi, -M_PI / 2, 3 * M_PI / 2, dphi_axis_title}; // dilepton-hadron - fRegistry.add("DileptonHadron/same/uls/hs", "dilepton-hadron 2PC", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_deta, axis_dphi}, true); + fRegistry.add("DileptonHadron/same/uls/hs", "dilepton-hadron 2PC", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_deta, axis_dphi}, true); fRegistry.addClone("DileptonHadron/same/uls/", "DileptonHadron/same/lspp/"); fRegistry.addClone("DileptonHadron/same/uls/", "DileptonHadron/same/lsmm/"); - // fRegistry.addClone("DileptonHadron/same/", "DileptonHadron/mix/"); + fRegistry.addClone("DileptonHadron/same/", "DileptonHadron/mix/"); + fRegistry.add("DileptonHadron/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", o2::framework::kTH1D, {{10001, -0.5, 10000.5}}, true); // hadron-hadron - const AxisSpec axis_dphi_hh{90, -M_PI / 2, 3 * M_PI / 2, "#Delta#varphi = #varphi_{h}^{ref1} - #varphi_{h}^{ref2} (rad.)"}; - fRegistry.add("HadronHadron/same/hDEtaDPhi", "hadron-hadron 2PC", kTH2D, {axis_dphi_hh, axis_deta_hh}, true); + const o2::framework::AxisSpec axis_dphi_hh{90, -M_PI / 2, 3 * M_PI / 2, "#Delta#varphi = #varphi_{h}^{ref1} - #varphi_{h}^{ref2} (rad.)"}; + fRegistry.add("HadronHadron/same/hDEtaDPhi", "hadron-hadron 2PC", o2::framework::kTH2D, {axis_dphi_hh, axis_deta_hh}, true); fRegistry.addClone("HadronHadron/same/", "HadronHadron/mix/"); - fRegistry.add("HadronHadron/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); + fRegistry.add("HadronHadron/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", o2::framework::kTH1D, {{10001, -0.5, 10000.5}}, true); } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kCumulant)) { - const AxisSpec axis_cos_ndphi{cfgNbinsCosNDPhi, -1, +1, cosndphi_axis_title}; + const o2::framework::AxisSpec axis_cos_ndphi{cfgNbinsCosNDPhi, -1, +1, cosndphi_axis_title}; // dilepton-hadron - fRegistry.add("DileptonHadron/same/uls/hs", "dilepton-hadron 2PC", kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_deta, axis_cos_ndphi}, true); + fRegistry.add("DileptonHadron/same/uls/hs", "dilepton-hadron 2PC", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_dca, axis_y, axis_deta, axis_cos_ndphi}, true); fRegistry.addClone("DileptonHadron/same/uls/", "DileptonHadron/same/lspp/"); fRegistry.addClone("DileptonHadron/same/uls/", "DileptonHadron/same/lsmm/"); fRegistry.addClone("DileptonHadron/same/", "DileptonHadron/mix/"); // hadron-hadron - const AxisSpec axis_cosndphi_hh{cfgNbinsCosNDPhi, -1, +1, std::format("cos({0:d}(#varphi_{{h}}^{{ref1}} - #varphi_{{h}}^{{ref2}}))", cfgNmod.value)}; - fRegistry.add("HadronHadron/same/hDEtaCosNDPhi", "hadron-hadron 2PC", kTH2D, {axis_cosndphi_hh, axis_deta_hh}, true); + const o2::framework::AxisSpec axis_cosndphi_hh{cfgNbinsCosNDPhi, -1, +1, std::format("cos({0:d}(#varphi_{{h}}^{{ref1}} - #varphi_{{h}}^{{ref2}}))", cfgNmod.value)}; + fRegistry.add("HadronHadron/same/hDEtaCosNDPhi", "hadron-hadron 2PC", o2::framework::kTH2D, {axis_cosndphi_hh, axis_deta_hh}, true); } - fRegistry.add("Dilepton/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); + fRegistry.add("Dilepton/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", o2::framework::kTH1D, {{10001, -0.5, 10000.5}}, true); + + 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()), o2::framework::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()), o2::framework::kTH2F, {{110, 0, 110}, {180, -M_PI_2, +M_PI_2}}, false); } void DefineEMEventCut() @@ -580,7 +615,6 @@ struct DileptonHadronMPC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -613,8 +647,8 @@ struct DileptonHadronMPC { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(-1e+10, +1e+10); - fDielectronCut.IncludeITSsa(false, 0.15); + // fDielectronCut.SetRelDiffPin(-1e+10, +1e+10); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -637,31 +671,6 @@ struct DileptonHadronMPC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } @@ -685,13 +694,15 @@ struct DileptonHadronMPC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); 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); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } void DefineEMTrackCut() @@ -700,13 +711,11 @@ struct DileptonHadronMPC { fEMTrackCut.SetTrackPtRange(trackcuts.cfg_min_pt_track, trackcuts.cfg_max_pt_track); fEMTrackCut.SetTrackEtaRange(trackcuts.cfg_min_eta_track, trackcuts.cfg_max_eta_track); // fEMTrackCut.SetTrackPhiRange(trackcuts.cfg_min_phi_track, trackcuts.cfg_max_phi_track); - // fEMTrackCut.SetTrackMaxDcaXY(trackcuts.cfg_max_dcaxy); - // fEMTrackCut.SetTrackMaxDcaZ(trackcuts.cfg_max_dcaz); fEMTrackCut.SetTrackBit(trackcuts.cfg_track_bits); } - template - bool fillDilepton(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + template + bool fillDilepton(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut) { if constexpr (ev_id == 0) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -724,12 +733,19 @@ struct DileptonHadronMPC { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()]) { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } } @@ -756,14 +772,14 @@ struct DileptonHadronMPC { float pair_dca = 999.f; if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - pair_dca = pairDCAQuadSum(dca3DinSigma(t1), dca3DinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2)); if (cfgDCAType == 1) { - pair_dca = pairDCAQuadSum(dcaXYinSigma(t1), dcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2)); } else if (cfgDCAType == 2) { - pair_dca = pairDCAQuadSum(dcaZinSigma(t1), dcaZinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { - pair_dca = pairDCAQuadSum(fwdDcaXYinSigma(t1), fwdDcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t2)); } if (t1.sign() * t2.sign() < 0) { // ULS @@ -783,9 +799,9 @@ struct DileptonHadronMPC { used_trackIds_per_col.emplace_back(t1.globalIndex()); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), t1.cYY(), t1.cZY(), t1.cZZ())); } } } @@ -793,9 +809,9 @@ struct DileptonHadronMPC { used_trackIds_per_col.emplace_back(t2.globalIndex()); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), t2.cYY(), t2.cZY(), t2.cZZ())); } } } @@ -804,9 +820,9 @@ struct DileptonHadronMPC { used_trackIds_per_col.emplace_back(t1.globalIndex()); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), t1.cXX(), t1.cXY(), t1.cYY())); } } } @@ -814,9 +830,9 @@ struct DileptonHadronMPC { used_trackIds_per_col.emplace_back(t2.globalIndex()); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_pos->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + emh_neg->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMFwdTrack(t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), t2.cXX(), t2.cXY(), t2.cYY())); } } } @@ -825,8 +841,8 @@ struct DileptonHadronMPC { return true; } - template - bool fillDileptonHadron(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks, TRefTrack const& t3) + template + bool fillDileptonHadron(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TRefTrack const& t3) { // this function must be called, if dilepton passes the cut. @@ -841,20 +857,27 @@ struct DileptonHadronMPC { return false; } } - if (t1.trackId() == t3.trackId() || t2.trackId() == t3.trackId()) { - return false; - } + // if (t1.trackId() == t3.trackId() || t2.trackId() == t3.trackId()) { + // 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 (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()]) { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } if (!fEMTrackCut.IsSelected(t3)) { // for charged track @@ -873,11 +896,10 @@ struct DileptonHadronMPC { } float weight = 1.f; - if (cfgApplyWeightTTCA) { - weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; - } - if (ev_id == 1) { - weight = 1.f; + if constexpr (ev_id == 0) { + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; + } } ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), leptonM1); @@ -890,14 +912,14 @@ struct DileptonHadronMPC { float pair_dca = 999.f; if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - pair_dca = pairDCAQuadSum(dca3DinSigma(t1), dca3DinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2)); if (cfgDCAType == 1) { - pair_dca = pairDCAQuadSum(dcaXYinSigma(t1), dcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2)); } else if (cfgDCAType == 2) { - pair_dca = pairDCAQuadSum(dcaZinSigma(t1), dcaZinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { - pair_dca = pairDCAQuadSum(fwdDcaXYinSigma(t1), fwdDcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t2)); } if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { @@ -925,7 +947,7 @@ struct DileptonHadronMPC { } template - bool fillHadronHadron(TRefTrack const& t1, TRefTrack const& t2, TLeptons const& posLeptons, TLeptons const& negLeptons, TLeptonCut const& cut) + bool fillHadronHadron(TRefTrack const& t1, TRefTrack const& t2, TLeptons const&, TLeptons const&, TLeptonCut const&) { if constexpr (ev_id == 0) { if (!fEMTrackCut.IsSelected(t1) || !fEMTrackCut.IsSelected(t2)) { // for charged track @@ -934,36 +956,37 @@ struct DileptonHadronMPC { // Leptons should not be in reference track sample. if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - for (const auto& pos : posLeptons) { // leptons per collision - if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { - if (!cut.template IsSelectedTrack(pos)) { - continue; - } - } else { // cut based - if (!cut.template IsSelectedTrack(pos)) { - continue; - } - } - if (t1.trackId() == pos.trackId() || t2.trackId() == pos.trackId()) { - return false; - } - } // end of pos lepton loop - - for (const auto& neg : negLeptons) { // leptons per collision - if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { - if (!cut.template IsSelectedTrack(neg)) { - continue; - } - } else { // cut based - if (!cut.template IsSelectedTrack(neg)) { - continue; - } - } - if (t1.trackId() == neg.trackId() || t2.trackId() == neg.trackId()) { - return false; - } - } // end of neg lepton lopp - + if (trackcuts.cfg_reftrack_type == static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackType::kCB)) { + // for (const auto& pos : posLeptons) { // leptons per collision + // if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + // if (!cut.template IsSelectedTrack(pos)) { + // continue; + // } + // } else { // cut based + // if (!cut.template IsSelectedTrack(pos)) { + // continue; + // } + // } + // // if (t1.trackId() == pos.trackId() || t2.trackId() == pos.trackId()) { + // // return false; + // // } + // } // end of pos lepton loop + + // for (const auto& neg : negLeptons) { // leptons per collision + // if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + // if (!cut.template IsSelectedTrack(neg)) { + // continue; + // } + // } else { // cut based + // if (!cut.template IsSelectedTrack(neg)) { + // continue; + // } + // } + // // if (t1.trackId() == neg.trackId() || t2.trackId() == neg.trackId()) { + // // return false; + // // } + // } // end of neg lepton lopp + } } // end of if kDielectron } // end of if same event @@ -982,48 +1005,53 @@ struct DileptonHadronMPC { 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_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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 && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); - Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); - - Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfb >= static_cast(0)); - - 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 && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && 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); - - using RefTracks = soa::Join; + o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = o2::soa::Filtered; + + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::expressions::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 && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + + o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); + o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && 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; + o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + + o2::framework::Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); + o2::framework::Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); + + using RefTracks = o2::soa::Join; using RefTrack = RefTracks::iterator; - Preslice perCollision_track = aod::emprimarytrack::emeventId; - Filter refTrackFilter = trackcuts.cfg_min_pt_track < 1 / nabs(o2::aod::emprimarytrack::signed1Pt) && 1 / nabs(o2::aod::emprimarytrack::signed1Pt) < trackcuts.cfg_max_pt_track && trackcuts.cfg_min_eta_track < o2::aod::emprimarytrack::eta && o2::aod::emprimarytrack::eta < trackcuts.cfg_max_eta_track; - using FilteredRefTracks = soa::Filtered; + o2::framework::Preslice perCollision_track = o2::aod::emprimarytrack::emeventId; + o2::framework::expressions::Filter refTrackFilter = trackcuts.cfg_min_pt_track < 1 / nabs(o2::aod::emprimarytrack::signed1Pt) && 1 / nabs(o2::aod::emprimarytrack::signed1Pt) < trackcuts.cfg_max_pt_track && trackcuts.cfg_min_eta_track < o2::aod::emprimarytrack::eta && o2::aod::emprimarytrack::eta < trackcuts.cfg_max_eta_track; + using FilteredRefTracks = o2::soa::Filtered; using FilteredRefTrack = FilteredRefTracks::iterator; TEMH* emh_pos = nullptr; @@ -1034,19 +1062,24 @@ struct DileptonHadronMPC { std::vector used_trackIds_per_col; int ndf = 0; - template - void run2PC(TCollisions const& collisions, TLeptons const& posTracks, TLeptons const& negTracks, TPresilce const& perCollision, TCut const& cut, TAllTracks const& tracks, TRefTracks const& refTracks) + template + void run2PC(TCollisions const& collisions, TLeptons const& posTracks, TLeptons const& negTracks, TPresilce const& perCollision, TCut const& cut, TRefTracks const& refTracks) { for (const auto& collision : collisions) { initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; float centrality = centralities[cfgCentEstimator]; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } + const float eventplanes_2_for_mix[7] = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg(), collision.ep2fv0a()}; + float ep2 = eventplanes_2_for_mix[cfgEP2Estimator_for_Mix]; + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + if (!fEMEventCut.IsSelected(collision)) { continue; } @@ -1063,38 +1096,40 @@ struct DileptonHadronMPC { 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); auto refTracks_per_coll = refTracks.sliceBy(perCollision_track, collision.globalIndex()); + fRegistry.fill(HIST("Event/after/hMultNTracksPV_RefTracks"), collision.multNTracksPV(), refTracks_per_coll.size()); auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); used_trackIds_per_col.reserve(posTracks_per_coll.size() + negTracks_per_coll.size()); int nuls = 0, nlspp = 0, nlsmm = 0; - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - bool is_pair_ok = fillDilepton<0>(collision, pos, neg, cut, tracks); + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + bool is_pair_ok = fillDilepton<0>(collision, pos, neg, cut); if (is_pair_ok) { nuls++; for (const auto& refTrack : refTracks_per_coll) { - fillDileptonHadron<0>(pos, neg, cut, tracks, refTrack); + fillDileptonHadron<0>(pos, neg, cut, refTrack); } } } - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - bool is_pair_ok = fillDilepton<0>(collision, pos1, pos2, cut, tracks); + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + bool is_pair_ok = fillDilepton<0>(collision, pos1, pos2, cut); if (is_pair_ok) { nlspp++; for (const auto& refTrack : refTracks_per_coll) { - fillDileptonHadron<0>(pos1, pos2, cut, tracks, refTrack); + fillDileptonHadron<0>(pos1, pos2, cut, refTrack); } } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- - bool is_pair_ok = fillDilepton<0>(collision, neg1, neg2, cut, tracks); + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + bool is_pair_ok = fillDilepton<0>(collision, neg1, neg2, cut); if (is_pair_ok) { nlsmm++; for (const auto& refTrack : refTracks_per_coll) { - fillDileptonHadron<0>(neg1, neg2, cut, tracks, refTrack); + fillDileptonHadron<0>(neg1, neg2, cut, refTrack); } } } @@ -1112,11 +1147,14 @@ struct DileptonHadronMPC { // store ref tracks for mixed event in case of kAzimuthalCorrelation if (cfgDoMix && cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { - emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(track.pt(), track.eta(), track.phi(), 0.139)); + emh_ref->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(track.pt(), track.eta(), track.phi(), 0.139)); } // store ref tracks } } - for (const auto& [ref1, ref2] : combinations(CombinationsStrictlyUpperIndexPolicy(refTracks_per_coll, refTracks_per_coll))) { + // LOGF(info, "collision.globalIndex() = %d, collision.centFT0M() = %f, refTracks_per_coll.size() = %d", collision.globalIndex(), collision.centFT0M(), refTracks_per_coll.size()); + + for (const auto& [ref1, ref2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(refTracks_per_coll, refTracks_per_coll))) { + // TODO: remove lepton candidates from reference track sample in case of kCB. fillHadronHadron<0>(ref1, ref2, posTracks_per_coll, negTracks_per_coll, cut); } } @@ -1140,7 +1178,12 @@ struct DileptonHadronMPC { centbin = static_cast(cent_bin_edges.size()) - 2; } - int epbin = 0; + 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 = -1; if (cfgOccupancyEstimator == 0) { @@ -1189,25 +1232,25 @@ struct DileptonHadronMPC { for (const auto& pos : selected_posTracks_in_this_event) { // ULS mix for (const auto& neg : negTracks_from_event_pool) { - fillDilepton<1>(collision, pos, neg, cut, nullptr); + fillDilepton<1>(collision, pos, neg, cut); } } for (const auto& neg : selected_negTracks_in_this_event) { // ULS mix for (const auto& pos : posTracks_from_event_pool) { - fillDilepton<1>(collision, neg, pos, cut, nullptr); + fillDilepton<1>(collision, neg, pos, cut); } } for (const auto& pos1 : selected_posTracks_in_this_event) { // LS++ mix for (const auto& pos2 : posTracks_from_event_pool) { - fillDilepton<1>(collision, pos1, pos2, cut, nullptr); + fillDilepton<1>(collision, pos1, pos2, cut); } } for (const auto& neg1 : selected_negTracks_in_this_event) { // LS-- mix for (const auto& neg2 : negTracks_from_event_pool) { - fillDilepton<1>(collision, neg1, neg2, cut, nullptr); + fillDilepton<1>(collision, neg1, neg2, cut); } } } // end of loop over mixed event pool for lepton-lepton @@ -1216,6 +1259,89 @@ struct DileptonHadronMPC { auto selected_refTracks_in_this_event = emh_ref->GetTracksPerCollision(key_df_collision); auto collisionIds_in_mixing_pool_hadron = emh_ref->GetCollisionIdsFromEventPool(key_bin); + // for ULS and hadron mix + for (const auto& pos : selected_posTracks_in_this_event) { + for (const auto& neg : selected_negTracks_in_this_event) { + + for (const auto& mix_dfId_collisionId : collisionIds_in_mixing_pool_hadron) { + 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("DileptonHadron/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); + for (const auto& ref : refTracks_from_event_pool) { + fillDileptonHadron<1>(pos, neg, cut, ref); + } + + } // end of loop over mixed event pool for dilepton-hadron + } + } + + // for LS++ and hadron mix + for (size_t i1 = 0; i1 < selected_posTracks_in_this_event.size(); i1++) { + auto pos1 = selected_posTracks_in_this_event[i1]; + for (size_t i2 = i1 + 1; i2 < selected_posTracks_in_this_event.size(); i2++) { + auto pos2 = selected_posTracks_in_this_event[i2]; + + for (const auto& mix_dfId_collisionId : collisionIds_in_mixing_pool_hadron) { + 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("DileptonHadron/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); + for (const auto& ref : refTracks_from_event_pool) { + fillDileptonHadron<1>(pos1, pos2, cut, ref); + } + + } // end of loop over mixed event pool for dilepton-hadron + } + } + + // for LS-- and hadron mix + for (size_t i1 = 0; i1 < selected_negTracks_in_this_event.size(); i1++) { + auto neg1 = selected_negTracks_in_this_event[i1]; + for (size_t i2 = i1 + 1; i2 < selected_negTracks_in_this_event.size(); i2++) { + auto neg2 = selected_negTracks_in_this_event[i2]; + + for (const auto& mix_dfId_collisionId : collisionIds_in_mixing_pool_hadron) { + 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("DileptonHadron/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); + for (const auto& ref : refTracks_from_event_pool) { + fillDileptonHadron<1>(neg1, neg2, cut, ref); + } + + } // end of loop over mixed event pool for dilepton-hadron + } + } + for (const auto& mix_dfId_collisionId : collisionIds_in_mixing_pool_hadron) { int mix_dfId = mix_dfId_collisionId.first; int mix_collisionId = mix_dfId_collisionId.second; @@ -1252,8 +1378,8 @@ struct DileptonHadronMPC { } // end of DF - template - bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + template + bool isPairOK(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)) { @@ -1270,12 +1396,19 @@ struct DileptonHadronMPC { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()]) { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t2.globalIndex()]) { return false; } + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -1300,7 +1433,7 @@ struct DileptonHadronMPC { for (const auto& collision : collisions) { initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1314,18 +1447,18 @@ struct DileptonHadronMPC { auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - if (isPairOK(pos, neg, cut, tracks)) { + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (isPairOK(pos, neg, cut)) { passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); } } - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ - if (isPairOK(pos1, pos2, cut, tracks)) { + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + if (isPairOK(pos1, pos2, cut)) { passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- - if (isPairOK(neg1, neg2, cut, tracks)) { + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + if (isPairOK(neg1, neg2, cut)) { passed_pairIds.emplace_back(std::make_pair(neg1.globalIndex(), neg2.globalIndex())); } } @@ -1366,6 +1499,8 @@ struct DileptonHadronMPC { passed_pairIds.shrink_to_fit(); } + std::unordered_map map_best_match_globalmuon; + void processAnalysis(FilteredMyCollisions const& collisions, FilteredRefTracks const& refTracks, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -1373,15 +1508,17 @@ struct DileptonHadronMPC { if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); } - run2PC(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons, refTracks); + run2PC(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, refTracks); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); } - run2PC(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons, refTracks); + run2PC(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, refTracks); } map_weight.clear(); + map_best_match_globalmuon.clear(); ndf++; } PROCESS_SWITCH(DileptonHadronMPC, processAnalysis, "run dilepton analysis", true); @@ -1393,15 +1530,17 @@ struct DileptonHadronMPC { if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); } - run2PC(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons, refTracks); + run2PC(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, refTracks); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { auto muons = std::get<0>(std::tie(args...)); + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); } - run2PC(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons, refTracks); + run2PC(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, refTracks); } map_weight.clear(); + map_best_match_globalmuon.clear(); ndf++; } PROCESS_SWITCH(DileptonHadronMPC, processTriggerAnalysis, "run dilepton analysis on triggered data", false); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index c5b976f0405..83a56821628 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -24,66 +24,82 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TString.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include #include #include +#include +#include +#include +#include #include #include #include +#include +#include #include #include -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 namespace o2::aod::pwgem::dilepton::utils::pairutil; +#include -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyMCCollisions = soa::Join; +using MyMCCollisions = o2::soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = o2::soa::Join; using MyMCElectron = MyMCElectrons::iterator; -using FilteredMyMCElectrons = soa::Filtered; +using FilteredMyMCElectrons = o2::soa::Filtered; using FilteredMyMCElectron = FilteredMyMCElectrons::iterator; -using MyMCMuons = soa::Join; +using MyMCMuons = o2::soa::Join; using MyMCMuon = MyMCMuons::iterator; -using FilteredMyMCMuons = soa::Filtered; +using FilteredMyMCMuons = o2::soa::Filtered; using FilteredMyMCMuon = FilteredMyMCMuons::iterator; -using MySmearedElectrons = soa::Join; +using MySmearedElectrons = o2::soa::Join; using MySmearedElectron = MySmearedElectrons::iterator; -using MySmearedMuons = soa::Join; +using MySmearedMuons = o2::soa::Join; using MySmearedMuon = MySmearedMuons::iterator; // template @@ -91,223 +107,230 @@ template 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"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; - Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; - Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; - Configurable cfgFillUnfolding{"cfgFillUnfolding", false, "flag to fill histograms for unfolding"}; - Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; - Configurable cfgFillSeparateCharmHadronPairs{"cfgFillSeparateCharmHadronPairs", false, "flag to fill different ccbar pairs separately"}; - - 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 ConfDPtBins{"ConfDPtBins", {220, -1.0, +10.0}, "dpt bins for output histograms"}; - ConfigurableAxis ConfDCAllNarrowBins{"ConfDCAllNarrowBins", {200, 0.0, 10.0}, "narrow DCAll bins for output histograms"}; - ConfigurableAxis ConfTrackDCA{"ConfTrackDCA", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.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.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "DCA binning for single tacks"}; - - ConfigurableAxis ConfYllBins{"ConfYllBins", {1, -1.f, +1.f}, "yll 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. - - Configurable cfg_nbin_dphi_ee{"cfg_nbin_dphi_ee", 1, "number of bins for dphi_ee"}; // 36 - Configurable cfg_nbin_deta_ee{"cfg_nbin_deta_ee", 1, "number of bins for deta_ee"}; // 40 - // Configurable cfg_nbin_cos_theta_cs{"cfg_nbin_cos_theta_cs", 1, "number of bins for cos theta cs"}; // 10 - // Configurable cfg_nbin_phi_cs{"cfg_nbin_phi_cs", 1, "number of bins for phi cs"}; // 10 - Configurable cfg_nbin_aco{"cfg_nbin_aco", 1, "number of bins for acoplanarity"}; // 10 - Configurable cfg_nbin_asym_pt{"cfg_nbin_asym_pt", 1, "number of bins for pt asymmetry"}; // 10 - Configurable cfg_nbin_dphi_e_ee{"cfg_nbin_dphi_e_ee", 1, "number of bins for dphi_ee_e"}; // 18 - ConfigurableAxis ConfPolarizationCosThetaBins{"ConfPolarizationCosThetaBins", {1, -1.f, 1.f}, "cos(theta) bins for polarization analysis"}; - ConfigurableAxis ConfPolarizationPhiBins{"ConfPolarizationPhiBins", {1, -M_PI, M_PI}, "phi bins for polarization analysis"}; - Configurable cfgPolarizationFrame{"cfgPolarizationFrame", 0, "frame of polarization. 0:CS, 1:HX, else:FATAL"}; - ConfigurableAxis ConfPolarizationQuadMomBins{"ConfPolarizationQuadMomBins", {1, -0.5, 1}, "quadrupole moment bins for polarization analysis"}; // quardrupole moment <(3 x cos^2(theta) -1)/2> + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + o2::framework::Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + o2::framework::Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; + o2::framework::Configurable cfgFillUnfolding{"cfgFillUnfolding", false, "flag to fill histograms for unfolding"}; + o2::framework::Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + o2::framework::Configurable cfgFillSeparateCharmHadronPairs{"cfgFillSeparateCharmHadronPairs", false, "flag to fill different ccbar pairs separately"}; + + o2::framework::ConfigurableAxis ConfMllBins{"ConfMllBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfPtllBins{"ConfPtllBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfDCAllBins{"ConfDCAllBins", {o2::framework::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"}; + + o2::framework::ConfigurableAxis ConfDPtBins{"ConfDPtBins", {220, -1.0, +10.0}, "dpt bins for output histograms"}; + o2::framework::ConfigurableAxis ConfDCAllNarrowBins{"ConfDCAllNarrowBins", {200, 0.0, 10.0}, "narrow DCAll bins for output histograms"}; + o2::framework::ConfigurableAxis ConfTrackDCA{"ConfTrackDCA", {o2::framework::VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.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.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "DCA binning for single tacks"}; + + o2::framework::ConfigurableAxis ConfYllBins{"ConfYllBins", {1, -1.f, +1.f}, "yll bins for output histograms"}; + + // o2::framework::ConfigurableAxis ConfMmumuBins{"ConfMmumuBins", {o2::framework::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. + + o2::framework::Configurable cfg_nbin_dphi_ee{"cfg_nbin_dphi_ee", 1, "number of bins for dphi_ee"}; // 36 + o2::framework::Configurable cfg_nbin_deta_ee{"cfg_nbin_deta_ee", 1, "number of bins for deta_ee"}; // 40 + // o2::framework::Configurable cfg_nbin_cos_theta_cs{"cfg_nbin_cos_theta_cs", 1, "number of bins for cos theta cs"}; // 10 + // o2::framework::Configurable cfg_nbin_phi_cs{"cfg_nbin_phi_cs", 1, "number of bins for phi cs"}; // 10 + o2::framework::Configurable cfg_nbin_aco{"cfg_nbin_aco", 1, "number of bins for acoplanarity"}; // 10 + o2::framework::Configurable cfg_nbin_asym_pt{"cfg_nbin_asym_pt", 1, "number of bins for pt asymmetry"}; // 10 + o2::framework::Configurable cfg_nbin_dphi_e_ee{"cfg_nbin_dphi_e_ee", 1, "number of bins for dphi_ee_e"}; // 18 + o2::framework::ConfigurableAxis ConfPolarizationCosThetaBins{"ConfPolarizationCosThetaBins", {1, -1.f, 1.f}, "cos(theta) bins for polarization analysis"}; + o2::framework::ConfigurableAxis ConfPolarizationPhiBins{"ConfPolarizationPhiBins", {1, -M_PI, M_PI}, "phi bins for polarization analysis"}; + o2::framework::Configurable cfgPolarizationFrame{"cfgPolarizationFrame", 0, "frame of polarization. 0:CS, 1:HX, else:FATAL"}; + o2::framework::ConfigurableAxis ConfPolarizationQuadMomBins{"ConfPolarizationQuadMomBins", {1, -0.5, 1}, "quadrupole moment bins for polarization analysis"}; // quardrupole moment <(3 x cos^2(theta) -1)/2> EMEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", false, "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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + o2::framework::Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::framework::Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + o2::framework::Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + o2::framework::Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + o2::framework::Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; } eventcuts; DielectronCut fDielectronCut; - struct : ConfigurableGroup { + struct : o2::framework::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_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_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; - Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; - Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; - Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; - Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; - Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; - - Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; - Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply phiv cut inherited from prefilter"}; - Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; - Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; - 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "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_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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; - Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. - Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; - Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "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", -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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; - Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; - Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + o2::framework::Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + o2::framework::Configurable cfg_min_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; + o2::framework::Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; + o2::framework::Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; + // o2::framework::Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + o2::framework::Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply phiv cut inherited from prefilter"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + o2::framework::Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + o2::framework::Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + // o2::framework::Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // o2::framework::Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + o2::framework::Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif = 4, kPIDML = 5]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + // o2::framework::Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // o2::framework::Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + o2::framework::Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; // configuration for PID ML - Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - 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)"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + o2::framework::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"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dielectroncuts; DimuonCut fDimuonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; - - 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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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+6, "max chi2/ndf"}; - Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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"}; - Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; - Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; - Configurable rejectWrongMatch{"rejectWrongMatch", false, "flag to reject wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -4.0, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", -2.5, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // o2::framework::Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + o2::framework::Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + o2::framework::Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + o2::framework::Service ccdb; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int mRunNumber; float d_bz; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "mctrackcut_group"; - Configurable min_mcPt{"min_mcPt", 0.1, "min. MC pT for generated single lepton"}; - Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT for generated single lepton"}; - Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta for generated single lepton"}; - Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta for generated single lepton"}; + o2::framework::Configurable min_mcPt{"min_mcPt", 0.1, "min. MC pT for generated single lepton"}; + o2::framework::Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT for generated single lepton"}; + o2::framework::Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta for generated single lepton"}; + o2::framework::Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta for generated single lepton"}; } mctrackcuts; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; static constexpr std::string_view pair_sign_types[3] = {"uls/", "lspp/", "lsmm/"}; static constexpr std::string_view dilepton_source_types[20] = { @@ -340,8 +363,8 @@ struct DileptonMC { { // event info o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms(&fRegistry); - fRegistry.add("MCEvent/before/hZvtx", "mc vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); - fRegistry.add("MCEvent/before/hZvtx_rec", "rec. mc vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry.add("MCEvent/before/hZvtx", "mc vertex z; Z_{vtx} (cm)", o2::framework::kTH1F, {{100, -50, +50}}, false); + fRegistry.add("MCEvent/before/hZvtx_rec", "rec. mc vertex z; Z_{vtx} (cm)", o2::framework::kTH1F, {{100, -50, +50}}, false); fRegistry.addClone("MCEvent/before/", "MCEvent/after/"); std::string mass_axis_title = "m_{ll} (GeV/c^{2})"; @@ -366,17 +389,17 @@ struct DileptonMC { } // pair info - const AxisSpec axis_mass{ConfMllBins, mass_axis_title}; - const AxisSpec axis_pt{ConfPtllBins, pair_pt_axis_title}; - const AxisSpec axis_y{ConfYllBins, pair_y_axis_title}; - const AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; - const AxisSpec axis_pt_meson{ConfPtllBins, "p_{T}^{VM} (GeV/c)"}; // for omega, phi meson pT spectra - const AxisSpec axis_y_meson{ConfYllBins, "y^{VM}"}; // for omega, phi meson pT spectra - - const AxisSpec axis_dca_narrow{ConfDCAllNarrowBins, pair_dca_axis_title}; - const AxisSpec axis_dpt{ConfDPtBins, "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} (GeV/c)"}; - const AxisSpec axis_dca_track1{ConfTrackDCA, "DCA_{e,1}^{Z} (#sigma)"}; - const AxisSpec axis_dca_track2{ConfTrackDCA, "DCA_{e,2}^{Z} (#sigma)"}; + const o2::framework::AxisSpec axis_mass{ConfMllBins, mass_axis_title}; + const o2::framework::AxisSpec axis_pt{ConfPtllBins, pair_pt_axis_title}; + const o2::framework::AxisSpec axis_y{ConfYllBins, pair_y_axis_title}; + const o2::framework::AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; + const o2::framework::AxisSpec axis_pt_meson{ConfPtllBins, "p_{T}^{VM} (GeV/c)"}; // for omega, phi meson pT spectra + const o2::framework::AxisSpec axis_y_meson{ConfYllBins, "y^{VM}"}; // for omega, phi meson pT spectra + + const o2::framework::AxisSpec axis_dca_narrow{ConfDCAllNarrowBins, pair_dca_axis_title}; + const o2::framework::AxisSpec axis_dpt{ConfDPtBins, "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} (GeV/c)"}; + const o2::framework::AxisSpec axis_dca_track1{ConfTrackDCA, "DCA_{e,1}^{Z} (#sigma)"}; + const o2::framework::AxisSpec axis_dca_track2{ConfTrackDCA, "DCA_{e,2}^{Z} (#sigma)"}; std::string frameName = "CS"; if (cfgPolarizationFrame == 0) { @@ -387,17 +410,17 @@ struct DileptonMC { LOG(fatal) << "set 0 or 1 to cfgPolarizationFrame!"; } - const AxisSpec axis_dphi_ee{cfg_nbin_dphi_ee, -M_PI / 2., 3. / 2. * M_PI, "#Delta#varphi = #varphi_{l1} - #varphi_{l2} (rad.)"}; // for kHFll - const AxisSpec axis_deta_ee{cfg_nbin_deta_ee, -2., 2., "#Delta#eta = #eta_{l1} - #eta_{l2}"}; // for kHFll - const AxisSpec axis_cos_theta_pol{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; // for kPolarization, kUPC - const AxisSpec axis_phi_pol{ConfPolarizationPhiBins, Form("#varphi^{%s} (rad.)", frameName.data())}; // for kPolarization - const AxisSpec axis_quadmom{ConfPolarizationQuadMomBins, Form("#frac{3 cos^{2}(#theta^{%s}) -1}{2}", frameName.data())}; // for kPolarization - const AxisSpec axis_aco{cfg_nbin_aco, 0, 1.f, "#alpha = 1 - #frac{|#varphi_{l^{+}} - #varphi_{l^{-}}|}{#pi}"}; // for kUPC - const AxisSpec axis_asym_pt{cfg_nbin_asym_pt, 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{cfg_nbin_dphi_e_ee, 0, M_PI, "#Delta#varphi = #varphi_{l} - #varphi_{ll} (rad.)"}; // for kUPC + const o2::framework::AxisSpec axis_dphi_ee{cfg_nbin_dphi_ee, -M_PI / 2., 3. / 2. * M_PI, "#Delta#varphi = #varphi_{l1} - #varphi_{l2} (rad.)"}; // for kHFll + const o2::framework::AxisSpec axis_deta_ee{cfg_nbin_deta_ee, -2., 2., "#Delta#eta = #eta_{l1} - #eta_{l2}"}; // for kHFll + const o2::framework::AxisSpec axis_cos_theta_pol{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; // for kPolarization, kUPC + const o2::framework::AxisSpec axis_phi_pol{ConfPolarizationPhiBins, Form("#varphi^{%s} (rad.)", frameName.data())}; // for kPolarization + const o2::framework::AxisSpec axis_quadmom{ConfPolarizationQuadMomBins, Form("#frac{3 cos^{2}(#theta^{%s}) -1}{2}", frameName.data())}; // for kPolarization + const o2::framework::AxisSpec axis_aco{cfg_nbin_aco, 0, 1.f, "#alpha = 1 - #frac{|#varphi_{l^{+}} - #varphi_{l^{-}}|}{#pi}"}; // for kUPC + const o2::framework::AxisSpec axis_asym_pt{cfg_nbin_asym_pt, 0, 1.f, "A = #frac{|p_{T,l^{+}} - p_{T,l^{-}}|}{|p_{T,l^{+}} + p_{T,l^{-}}|}"}; // for kUPC + const o2::framework::AxisSpec axis_dphi_e_ee{cfg_nbin_dphi_e_ee, 0, M_PI, "#Delta#varphi = #varphi_{l} - #varphi_{ll} (rad.)"}; // for kUPC // generated info - fRegistry.add("Generated/sm/PromptPi0/uls/hs", "gen. dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee}, true); + fRegistry.add("Generated/sm/PromptPi0/uls/hs", "gen. dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee}, true); fRegistry.addClone("Generated/sm/PromptPi0/uls/", "Generated/sm/PromptPi0/lspp/"); fRegistry.addClone("Generated/sm/PromptPi0/uls/", "Generated/sm/PromptPi0/lsmm/"); @@ -417,7 +440,7 @@ struct DileptonMC { // fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Upsilon2S/"); // fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Upsilon3S/"); - fRegistry.add("Generated/ccbar/c2l_c2l/uls/hs", "generated dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee}, true); + fRegistry.add("Generated/ccbar/c2l_c2l/uls/hs", "generated dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee}, true); fRegistry.addClone("Generated/ccbar/c2l_c2l/uls/", "Generated/ccbar/c2l_c2l/lspp/"); fRegistry.addClone("Generated/ccbar/c2l_c2l/uls/", "Generated/ccbar/c2l_c2l/lsmm/"); @@ -461,7 +484,7 @@ struct DileptonMC { } // evaluate acceptance for polarization - fRegistry.add("Generated/VM/All/Phi/hs", "gen. VM #rightarrow ll", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_cos_theta_pol, axis_phi_pol, axis_quadmom}, true); + fRegistry.add("Generated/VM/All/Phi/hs", "gen. VM #rightarrow ll", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_cos_theta_pol, axis_phi_pol, axis_quadmom}, true); fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/Rho/"); fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/Omega/"); fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/PromptJPsi/"); @@ -469,7 +492,7 @@ struct DileptonMC { fRegistry.addClone("Generated/VM/All/", "Generated/VM/Acc/"); // reconstructed pair info - fRegistry.add("Pair/sm/Photon/uls/hs", "rec. dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); + fRegistry.add("Pair/sm/Photon/uls/hs", "rec. dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); fRegistry.addClone("Pair/sm/Photon/uls/", "Pair/sm/Photon/lspp/"); fRegistry.addClone("Pair/sm/Photon/uls/", "Pair/sm/Photon/lsmm/"); @@ -491,25 +514,25 @@ struct DileptonMC { // fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Upsilon3S/"); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - fRegistry.add("Pair/sm/Photon/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); - fRegistry.add("Pair/sm/Photon/uls/hMvsRxy", "m_{ee} vs. r_{xy};r_{xy}^{true} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{100, 0, 100}, {100, 0.0f, 1.0f}}, true); + fRegistry.add("Pair/sm/Photon/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", o2::framework::kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add("Pair/sm/Photon/uls/hMvsRxy", "m_{ee} vs. r_{xy};r_{xy}^{true} (cm);m_{ee} (GeV/c^{2})", o2::framework::kTH2F, {{100, 0, 100}, {100, 0.0f, 1.0f}}, true); for (const auto& strSign : pair_sign_types) { - fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hMvsPhiV", strSign), "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); - fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); - fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hMvsPhiV", strSign), "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", o2::framework::kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", o2::framework::kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", o2::framework::kTH2F, {axis_dca_track1, axis_dca_track2}, true); - fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hMvsPhiV", strSign), "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); - fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); - fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hMvsPhiV", strSign), "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", o2::framework::kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", o2::framework::kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", o2::framework::kTH2F, {axis_dca_track1, axis_dca_track2}, true); - fRegistry.add(std::format("Pair/sm/PromptJPsi/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); - fRegistry.add(std::format("Pair/sm/PromptJPsi/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); - fRegistry.add(std::format("Pair/sm/NonPromptJPsi/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); - fRegistry.add(std::format("Pair/sm/NonPromptJPsi/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + fRegistry.add(std::format("Pair/sm/PromptJPsi/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", o2::framework::kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/PromptJPsi/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", o2::framework::kTH2F, {axis_dca_track1, axis_dca_track2}, true); + fRegistry.add(std::format("Pair/sm/NonPromptJPsi/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", o2::framework::kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/NonPromptJPsi/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", o2::framework::kTH2F, {axis_dca_track1, axis_dca_track2}, true); } } - fRegistry.add("Pair/ccbar/c2l_c2l/uls/hs", "rec. dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); + fRegistry.add("Pair/ccbar/c2l_c2l/uls/hs", "rec. dilepton", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); fRegistry.addClone("Pair/ccbar/c2l_c2l/uls/", "Pair/ccbar/c2l_c2l/lspp/"); fRegistry.addClone("Pair/ccbar/c2l_c2l/uls/", "Pair/ccbar/c2l_c2l/lsmm/"); @@ -543,26 +566,26 @@ struct DileptonMC { } // for correlated bkg due to mis-identified hadrons, and true combinatorial bkg - fRegistry.add("Pair/corr_bkg_lh/uls/hs", "rec. bkg", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); + fRegistry.add("Pair/corr_bkg_lh/uls/hs", "rec. bkg", o2::framework::kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_pol, axis_phi_pol, axis_quadmom, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); fRegistry.addClone("Pair/corr_bkg_lh/uls/", "Pair/corr_bkg_lh/lspp/"); fRegistry.addClone("Pair/corr_bkg_lh/uls/", "Pair/corr_bkg_lh/lsmm/"); fRegistry.addClone("Pair/corr_bkg_lh/", "Pair/corr_bkg_hh/"); fRegistry.addClone("Pair/corr_bkg_lh/", "Pair/comb_bkg/"); if (doprocessGen_VM) { - fRegistry.add("Generated/VM/Omega/hPtY", "pT vs. y of #omega", kTH2D, {axis_y_meson, axis_pt_meson}, true); // for pT spectrum - fRegistry.add("Generated/VM/Phi/hPtY", "pT vs. y of #phi", kTH2D, {axis_y_meson, axis_pt_meson}, true); // for pT spectrum + fRegistry.add("Generated/VM/Omega/hPtY", "pT vs. y of #omega", o2::framework::kTH2D, {axis_y_meson, axis_pt_meson}, true); // for pT spectrum + fRegistry.add("Generated/VM/Phi/hPtY", "pT vs. y of #phi", o2::framework::kTH2D, {axis_y_meson, axis_pt_meson}, true); // for pT spectrum } if (cfgFillUnfolding) { // for 2D unfolding - const AxisSpec axis_mass_gen{ConfMllBins, "m_{ll}^{gen} (GeV/c^{2})"}; - const AxisSpec axis_pt_gen{ConfPtllBins, "p_{T,ll}^{gen} (GeV/c)"}; - const AxisSpec axis_mass_rec{ConfMllBins, "m_{ll}^{rec} (GeV/c^{2})"}; - const AxisSpec axis_pt_rec{ConfPtllBins, "p_{T,ll}^{rec} (GeV/c)"}; - fRegistry.add("Unfold/sm/uls/hsRM", "response matrix", kTHnSparseD, {axis_mass_gen, axis_pt_gen, axis_mass_rec, axis_pt_rec}, true); - fRegistry.add("Unfold/sm/uls/hMiss", "missing dilepton", kTH2D, {axis_mass_gen, axis_pt_gen}, true); // e.g. true eta is in acceptance, but reconstructed eta is out of acceptance. - fRegistry.add("Unfold/sm/uls/hFake", "fake dilepton", kTH2D, {axis_mass_rec, axis_pt_rec}, true); // e.g. true eta is out of acceptance, but reconstructed eta is in acceptance. + const o2::framework::AxisSpec axis_mass_gen{ConfMllBins, "m_{ll}^{gen} (GeV/c^{2})"}; + const o2::framework::AxisSpec axis_pt_gen{ConfPtllBins, "p_{T,ll}^{gen} (GeV/c)"}; + const o2::framework::AxisSpec axis_mass_rec{ConfMllBins, "m_{ll}^{rec} (GeV/c^{2})"}; + const o2::framework::AxisSpec axis_pt_rec{ConfPtllBins, "p_{T,ll}^{rec} (GeV/c)"}; + fRegistry.add("Unfold/sm/uls/hsRM", "response matrix", o2::framework::kTHnSparseD, {axis_mass_gen, axis_pt_gen, axis_mass_rec, axis_pt_rec}, true); + fRegistry.add("Unfold/sm/uls/hMiss", "missing dilepton", o2::framework::kTH2D, {axis_mass_gen, axis_pt_gen}, true); // e.g. true eta is in acceptance, but reconstructed eta is out of acceptance. + fRegistry.add("Unfold/sm/uls/hFake", "fake dilepton", o2::framework::kTH2D, {axis_mass_rec, axis_pt_rec}, true); // e.g. true eta is out of acceptance, but reconstructed eta is in acceptance. fRegistry.addClone("Unfold/sm/uls/", "Unfold/sm/lspp/"); fRegistry.addClone("Unfold/sm/uls/", "Unfold/sm/lsmm/"); fRegistry.addClone("Unfold/sm/", "Unfold/ccbar/"); @@ -580,7 +603,7 @@ struct DileptonMC { float leptonM1 = 0.f; float leptonM2 = 0.f; int pdg_lepton = 0; - void init(InitContext&) + void init(o2::framework::InitContext&) { if (doprocessAnalysis && doprocessAnalysis_Smeared) { LOGF(fatal, "Cannot enable doprocessAnalysis and doprocessAnalysis_Smeared at the same time. Please choose one."); @@ -613,7 +636,7 @@ struct DileptonMC { fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); } if (doprocessBC) { - auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", kTH1D, {{6, -0.5f, 5.5f}}); + auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", o2::framework::kTH1D, {{6, -0.5f, 5.5f}}); hTVXCounter->GetXaxis()->SetBinLabel(1, "TVX"); hTVXCounter->GetXaxis()->SetBinLabel(2, "TVX && NoTFB"); hTVXCounter->GetXaxis()->SetBinLabel(3, "TVX && NoITSROFB"); @@ -701,7 +724,6 @@ struct DileptonMC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -715,7 +737,7 @@ struct DileptonMC { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); @@ -734,8 +756,8 @@ struct DileptonMC { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -759,31 +781,6 @@ struct DileptonMC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } @@ -807,31 +804,33 @@ struct DileptonMC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); 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); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template int FindSMULS(TTrack const& t1mc, TTrack const& t2mc, TMCParticles const& mcparticles) { int arr[] = { - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 22, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 111, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 221, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 331, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 113, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 223, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 333, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 443, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 100443, mcparticles) - // FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 553, mcparticles), - // FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 100553, mcparticles), - // FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 200553, mcparticles) + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 22, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 111, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 221, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 331, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 113, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 223, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 333, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 443, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 100443, mcparticles) + // o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 553, mcparticles), + // o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 100553, mcparticles), + // o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 200553, mcparticles) }; int size = sizeof(arr) / sizeof(*arr); int max = *std::max_element(arr, arr + size); @@ -842,12 +841,12 @@ struct DileptonMC { int FindSMLSPP(TTrack const& t1mc, TTrack const& t2mc, TMCParticles const& mcparticles) { int arr[] = { - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 111, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 221, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 331, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 113, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 223, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 333, mcparticles)}; + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 111, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 221, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 331, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 113, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 223, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 333, mcparticles)}; int size = sizeof(arr) / sizeof(*arr); int max = *std::max_element(arr, arr + size); return max; @@ -857,12 +856,12 @@ struct DileptonMC { int FindSMLSMM(TTrack const& t1mc, TTrack const& t2mc, TMCParticles const& mcparticles) { int arr[] = { - FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 111, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 221, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 331, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 113, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 223, mcparticles), - FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 333, mcparticles)}; + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 111, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 221, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 331, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 113, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 223, mcparticles), + o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 333, mcparticles)}; int size = sizeof(arr) / sizeof(*arr); int max = *std::max_element(arr, arr + size); return max; @@ -1392,7 +1391,7 @@ struct DileptonMC { } template - bool fillTruePairInfo(TCollision const& collision, TMCCollisions const&, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks, TMCParticles const& mcparticles) + bool fillTruePairInfo(TCollision const& collision, TMCCollisions const&, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&, TMCParticles const& mcparticles) { auto t1mc = mcparticles.iteratorAt(t1.emmcparticleId()); auto t2mc = mcparticles.iteratorAt(t2.emmcparticleId()); @@ -1427,14 +1426,17 @@ struct DileptonMC { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } - if (dimuoncuts.rejectWrongMatch) { + + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } + if (dimuoncuts.acceptOnlyCorrectMatch) { if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() != t1.emmftmcparticleId()) { return false; } @@ -1442,6 +1444,14 @@ struct DileptonMC { return false; } } + if (dimuoncuts.acceptOnlyWrongMatch) { // reject correctly matched MFT-MCH-MID for bkg estimation + if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() == t1.emmftmcparticleId()) { + return false; + } + if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t2.emmcparticleId() == t2.emmftmcparticleId()) { + return false; + } + } if (!cut.IsSelectedPair(t1, t2)) { return false; @@ -1516,14 +1526,14 @@ struct DileptonMC { float pair_dca = 999.f; if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - pair_dca = pairDCAQuadSum(dca3DinSigma(t1), dca3DinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2)); if (cfgDCAType == 1) { - pair_dca = pairDCAQuadSum(dcaXYinSigma(t1), dcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2)); } else if (cfgDCAType == 2) { - pair_dca = pairDCAQuadSum(dcaZinSigma(t1), dcaZinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { - pair_dca = pairDCAQuadSum(fwdDcaXYinSigma(t1), fwdDcaXYinSigma(t2)); + pair_dca = o2::aod::pwgem::dilepton::utils::pairutil::pairDCAQuadSum(o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t2)); } 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); @@ -1548,10 +1558,10 @@ struct DileptonMC { o2::math_utils::bringToPMPi(phiPol); float quadmom = (3.f * std::pow(cos_thetaPol, 2) - 1.f) / 2.f; - if ((FindCommonMotherFrom2ProngsWithoutPDG(t1mc, t2mc) > 0 || IsHF(t1mc, t2mc, mcparticles) > 0) && is_pair_from_same_mcevent) { // for bkg study - if (std::abs(t1mc.pdgCode()) != pdg_lepton || std::abs(t2mc.pdgCode()) != pdg_lepton) { // hh or lh correlated bkg - if (std::abs(t1mc.pdgCode()) != pdg_lepton && std::abs(t2mc.pdgCode()) != pdg_lepton) { // hh correlated bkg - if (t1.sign() * t2.sign() < 0) { // ULS + if ((o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2ProngsWithoutPDG(t1mc, t2mc) > 0 || o2::aod::pwgem::dilepton::utils::mcutil::IsHF(t1mc, t2mc, mcparticles) > 0) && is_pair_from_same_mcevent) { // for bkg study + if (std::abs(t1mc.pdgCode()) != pdg_lepton || std::abs(t2mc.pdgCode()) != pdg_lepton) { // hh or lh correlated bkg + if (std::abs(t1mc.pdgCode()) != pdg_lepton && std::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(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(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(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); @@ -1589,7 +1599,7 @@ struct DileptonMC { return false; } int mother_id = std::max({FindSMULS(t1mc, t2mc, mcparticles), FindSMULS(t2mc, t1mc, mcparticles), FindSMLSPP(t1mc, t2mc, mcparticles), FindSMLSMM(t1mc, t2mc, mcparticles)}); - int hfee_type = IsHF(t1mc, t2mc, mcparticles); + int hfee_type = o2::aod::pwgem::dilepton::utils::mcutil::IsHF(t1mc, t2mc, mcparticles); if (mother_id < 0 && hfee_type < 0) { return false; } @@ -1602,21 +1612,21 @@ struct DileptonMC { float deltaPt2 = t2mc.pt() - t2.pt(); switch (std::abs(mcmother.pdgCode())) { case 111: - if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromCharm(mcmother, mcparticles) < 0 && o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 fillRecHistograms<1>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // prompt pi0 if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (t1.sign() * t2.sign() < 0) { // ULS fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } } else { // non-prompt pi0 @@ -1625,15 +1635,15 @@ struct DileptonMC { if (t1.sign() * t2.sign() < 0) { // ULS fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } } @@ -1664,18 +1674,18 @@ struct DileptonMC { } break; case 443: - if (IsFromBeauty(mcmother, mcparticles) > 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { fillRecHistograms<9>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // non-prompt J/psi if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (t1.sign() * t2.sign() < 0) { // ULS fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/uls/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lspp/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lsmm/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } } else { @@ -1683,19 +1693,19 @@ struct DileptonMC { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (t1.sign() * t2.sign() < 0) { // ULS fRegistry.fill(HIST("Pair/sm/PromptJPsi/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/PromptJPsi/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/uls/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ fRegistry.fill(HIST("Pair/sm/PromptJPsi/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/PromptJPsi/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/lspp/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- fRegistry.fill(HIST("Pair/sm/PromptJPsi/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); - fRegistry.fill(HIST("Pair/sm/PromptJPsi/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/lsmm/hDCAz1vsDCAz2"), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1), o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2)); } } } break; case 100443: - if (IsFromBeauty(mcmother, mcparticles) > 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { fillRecHistograms<11>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // non-prompt psi2S } else { fillRecHistograms<10>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // prompt psi2S @@ -1724,19 +1734,19 @@ struct DileptonMC { auto mp1 = mcparticles.iteratorAt(t1mc.mothersIds()[0]); auto mp2 = mcparticles.iteratorAt(t2mc.mothersIds()[0]); switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kCe_Ce): fillRecHistograms<15>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // c2l_c2l break; - case static_cast(EM_HFeeType::kBe_Be): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBe_Be): fillRecHistograms<16>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // b2l_b2l break; - case static_cast(EM_HFeeType::kBCe_BCe): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_BCe): fillRecHistograms<17>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // b2c2l_b2c2l break; - case static_cast(EM_HFeeType::kBCe_Be_SameB): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_Be_SameB): fillRecHistograms<18>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // b2c2l_b2l_sameb break; - case static_cast(EM_HFeeType::kBCe_Be_DiffB): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_Be_DiffB): fillRecHistograms<19>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); // b2c2l_b2l_diffb break; default: @@ -1758,7 +1768,7 @@ struct DileptonMC { } int mother_id = std::max({FindSMULS(t1, t2, mcparticles), FindSMULS(t2, t1, mcparticles), FindSMLSPP(t1, t2, mcparticles), FindSMLSMM(t1, t2, mcparticles)}); - int hfee_type = IsHF(t1, t2, mcparticles); + int hfee_type = o2::aod::pwgem::dilepton::utils::mcutil::IsHF(t1, t2, mcparticles); if (mother_id < 0 && hfee_type < 0) { return false; } @@ -1859,10 +1869,10 @@ struct DileptonMC { if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { switch (std::abs(mcmother.pdgCode())) { case 111: - if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 - fillGenHistograms<1>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // prompt pi0 - } else { // non-prompt pi0 - fillGenHistograms<2>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // non-prompt pi0 + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromCharm(mcmother, mcparticles) < 0 && o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 + fillGenHistograms<1>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // prompt pi0 + } else { // non-prompt pi0 + fillGenHistograms<2>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // non-prompt pi0 } break; case 221: @@ -1887,14 +1897,14 @@ struct DileptonMC { } break; case 443: - if (IsFromBeauty(mcmother, mcparticles) > 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { fillGenHistograms<9>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // non-prompt J/psi } else { fillGenHistograms<8>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // prompt J/psi } break; case 100443: - if (IsFromBeauty(mcmother, mcparticles) > 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { fillGenHistograms<11>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // non-prompt psi2S } else { fillGenHistograms<10>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // prompt psi2S @@ -1908,19 +1918,19 @@ struct DileptonMC { auto mp1 = mcparticles.iteratorAt(t1.mothersIds()[0]); auto mp2 = mcparticles.iteratorAt(t2.mothersIds()[0]); switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kCe_Ce): fillGenHistograms<15>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // c2l_c2l break; - case static_cast(EM_HFeeType::kBe_Be): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBe_Be): fillGenHistograms<16>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // b2l_b2l break; - case static_cast(EM_HFeeType::kBCe_BCe): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_BCe): fillGenHistograms<17>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // b2c2l_b2c2l break; - case static_cast(EM_HFeeType::kBCe_Be_SameB): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_Be_SameB): fillGenHistograms<18>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // b2c2l_b2l_sameb break; - case static_cast(EM_HFeeType::kBCe_Be_DiffB): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_Be_DiffB): fillGenHistograms<19>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, cos_thetaPol, phiPol, quadmom, aco, asym, std::fabs(dphi_e_ee), weight); // b2c2l_b2l_diffb break; default: @@ -2016,7 +2026,7 @@ struct DileptonMC { } break; case 443: - if (IsFromBeauty(mcParticle, mcParticles) > 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcParticle, mcParticles) > 0) { fRegistry.fill(HIST("Generated/VM/All/NonPromptJPsi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); if (isInAcceptance(v1.Pt(), v1.Eta()) && isInAcceptance(v2.Pt(), v2.Eta())) { fRegistry.fill(HIST("Generated/VM/Acc/NonPromptJPsi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); @@ -2043,7 +2053,7 @@ struct DileptonMC { for (const auto& collision : collisions) { initCCDB(collision); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -2062,15 +2072,15 @@ struct DileptonMC { 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 (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS fillTruePairInfo(collision, mccollisions, pos, neg, cut, tracks, mcparticles); } // end of ULS pair loop - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ fillTruePairInfo(collision, mccollisions, pos1, pos2, cut, tracks, mcparticles); } // end of LS++ pair loop - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- fillTruePairInfo(collision, mccollisions, neg1, neg2, cut, tracks, mcparticles); } // end of LS-- pair loop @@ -2091,7 +2101,7 @@ struct DileptonMC { auto collision = collisions.rawIteratorAt(mccollision.mpemeventId()); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } fRegistry.fill(HIST("MCEvent/before/hZvtx_rec"), mccollision.posZ()); @@ -2103,18 +2113,18 @@ struct DileptonMC { } fRegistry.fill(HIST("MCEvent/after/hZvtx"), mccollision.posZ()); - auto posTracks_per_coll = posTracksMC.sliceByCachedUnsorted(aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); - auto negTracks_per_coll = negTracksMC.sliceByCachedUnsorted(aod::emmcparticle::emmceventId, mccollision.globalIndex(), cache); + 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 (const auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [t1, t2] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS fillGenPairInfo(t1, t2, mcparticles); } // end of true ULS pair loop - for (const auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [t1, t2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ fillGenPairInfo(t1, t2, mcparticles); } // end of true LS++ pair loop - for (const auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [t1, t2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- fillGenPairInfo(t1, t2, mcparticles); } // end of true LS-- pair loop @@ -2133,7 +2143,7 @@ struct DileptonMC { } template - bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const&) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { @@ -2149,12 +2159,15 @@ struct DileptonMC { if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { return false; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { - return false; - } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + if (!map_best_match_globalmuon[t1.globalIndex()] || !map_best_match_globalmuon[t2.globalIndex()]) { return false; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + // return false; + // } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + // return false; + // } } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -2179,7 +2192,7 @@ struct DileptonMC { for (const auto& collision : collisions) { initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -2198,7 +2211,7 @@ struct DileptonMC { auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, neg] : combinations(o2::soa::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) { @@ -2214,7 +2227,7 @@ struct DileptonMC { passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); } } - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(o2::soa::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) { @@ -2230,7 +2243,7 @@ struct DileptonMC { passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [neg1, neg2] : combinations(o2::soa::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) { @@ -2388,7 +2401,7 @@ struct DileptonMC { return false; } int mother_id = std::max({FindSMULS(t1mc, t2mc, mcparticles), FindSMULS(t2mc, t1mc, mcparticles), FindSMLSPP(t1mc, t2mc, mcparticles), FindSMLSMM(t1mc, t2mc, mcparticles)}); - int hfee_type = IsHF(t1mc, t2mc, mcparticles); + int hfee_type = o2::aod::pwgem::dilepton::utils::mcutil::IsHF(t1mc, t2mc, mcparticles); if (mother_id < 0 && hfee_type < 0) { return false; } @@ -2426,19 +2439,19 @@ struct DileptonMC { } } else if (hfee_type > -1) { switch (hfee_type) { - case static_cast(EM_HFeeType::kCe_Ce): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kCe_Ce): fillHistogramsUnfolding<1>(t1, t2, mcparticles); break; - case static_cast(EM_HFeeType::kBe_Be): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBe_Be): fillHistogramsUnfolding<2>(t1, t2, mcparticles); break; - case static_cast(EM_HFeeType::kBCe_BCe): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_BCe): fillHistogramsUnfolding<2>(t1, t2, mcparticles); break; - case static_cast(EM_HFeeType::kBCe_Be_SameB): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_Be_SameB): fillHistogramsUnfolding<2>(t1, t2, mcparticles); break; - case static_cast(EM_HFeeType::kBCe_Be_DiffB): + case static_cast(o2::aod::pwgem::dilepton::utils::mcutil::EM_HFeeType::kBCe_Be_DiffB): fillHistogramsUnfolding<2>(t1, t2, mcparticles); break; default: @@ -2454,7 +2467,7 @@ struct DileptonMC { for (const auto& collision : collisions) { initCCDB(collision); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -2468,64 +2481,71 @@ struct DileptonMC { auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); // reconstructed pos tracks auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); // reconstructed neg tracks - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS fillPairUnfolding(pos, neg, tracks, cut, mcCollisions, mcparticles); } // end of ULS pairing - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ fillPairUnfolding(pos1, pos2, tracks, cut, mcCollisions, mcparticles); } // end of LS++ pairing - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- fillPairUnfolding(neg1, neg2, tracks, cut, mcCollisions, mcparticles); } // end of LS-- pairing } // end of collision loop } - SliceCache cache; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); - Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); - - Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfb >= static_cast(0)); - - Preslice perCollision_muon = aod::emprimarymuon::emeventId; - Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type; - 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_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - using FilteredMyCollisions = soa::Filtered; - - 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; - // PresliceUnsorted recColperMcCollision = aod::emmceventlabel::emmceventId; - - void processAnalysis(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, aod::EMMCParticles const& mcparticles, TLeptons const& leptons) + std::unordered_map map_best_match_globalmuon; + + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::expressions::Filter trackFilter_electron = nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc; + o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type; + o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = o2::soa::Filtered; + + o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); // reconstructed tracks + o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); // reconstructed tracks + o2::framework::Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); // reconstructed tracks + o2::framework::Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); // reconstructed tracks + + o2::framework::Partition positive_electronsMC = o2::aod::mcparticle::pdgCode == -11; // e+ + o2::framework::Partition negative_electronsMC = o2::aod::mcparticle::pdgCode == 11; // e- + o2::framework::Partition positive_muonsMC = o2::aod::mcparticle::pdgCode == -13; // mu+ + o2::framework::Partition negative_muonsMC = o2::aod::mcparticle::pdgCode == 13; // mu- + o2::framework::PresliceUnsorted perMcCollision = o2::aod::emmcparticle::emmceventId; + o2::framework::PresliceUnsorted perMcCollision_vm = o2::aod::emmcgenvectormeson::emmceventId; + // o2::framework::PresliceUnsorted recColperMcCollision = o2::aod::emmceventlabel::emmceventId; + + void processAnalysis(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, o2::aod::EMMCParticles const& mcparticles, TLeptons const& leptons) { // LOGF(info, "collisions.size() = %d, mccollisions.size() = %d, mcparticles.size() = %d", collisions.size(), mccollisions.size(), mcparticles.size()); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { @@ -2538,6 +2558,7 @@ struct DileptonMC { fillUnfolding(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, mcparticles); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(leptons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles); } @@ -2548,13 +2569,14 @@ struct DileptonMC { } } map_weight.clear(); + map_best_match_globalmuon.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- + o2::framework::Partition positive_electronsMC_smeared = o2::aod::mcparticle::pdgCode == -11; // e+ + o2::framework::Partition negative_electronsMC_smeared = o2::aod::mcparticle::pdgCode == 11; // e- + o2::framework::Partition positive_muonsMC_smeared = o2::aod::mcparticle::pdgCode == -13; // mu+ + o2::framework::Partition negative_muonsMC_smeared = o2::aod::mcparticle::pdgCode == 13; // mu- void processAnalysis_Smeared(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, TLeptons const& leptons, TSmeardMCParitlces const& mcparticles_smeared) { @@ -2569,6 +2591,7 @@ struct DileptonMC { fillUnfolding(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, mcparticles_smeared); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(leptons, fDimuonCut); if (cfgApplyWeightTTCA) { fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles_smeared); } @@ -2579,15 +2602,16 @@ struct DileptonMC { } } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(DileptonMC, processAnalysis_Smeared, "run dilepton mc analysis with smearing", false); - void processGen_VM(FilteredMyCollisions const& collisions, MyMCCollisions const&, aod::EMMCGenVectorMesons const& mcparticles) + void processGen_VM(FilteredMyCollisions const& collisions, MyMCCollisions const&, o2::aod::EMMCGenVectorMesons const& mcparticles) { // for oemga, phi efficiency for (const auto& collision : collisions) { float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -2634,32 +2658,32 @@ struct DileptonMC { } PROCESS_SWITCH(DileptonMC, processGen_VM, "process generated info for vector mesons", false); - void processNorm(aod::EMEventNormInfos const& collisions) + void processNorm(o2::aod::EMEventNormInfos const& collisions) { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -2668,28 +2692,28 @@ struct DileptonMC { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -2703,25 +2727,25 @@ struct DileptonMC { } PROCESS_SWITCH(DileptonMC, processNorm, "process normalization info", false); - void processBC(aod::EMBCs const& bcs) + void processBC(o2::aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Core/DileptonProducer.h b/PWGEM/Dilepton/Core/DileptonProducer.h index c206ac14d3f..fd4eb783f89 100644 --- a/PWGEM/Dilepton/Core/DileptonProducer.h +++ b/PWGEM/Dilepton/Core/DileptonProducer.h @@ -21,262 +21,262 @@ #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/EMFwdTrack.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/ML/MlResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" - -#include "Math/Vector4D.h" -#include "TString.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include #include -#include -#include +#include +#include +#include #include #include -#include #include +#include #include #include #include -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 namespace o2::aod::pwgem::dilepton::utils::pairutil; - -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyElectrons = soa::Join; +using MyElectrons = o2::soa::Join; using MyElectron = MyElectrons::iterator; -using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectrons = o2::soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; -using MyMuons = soa::Join; +using MyMuons = o2::soa::Join; using MyMuon = MyMuons::iterator; -using FilteredMyMuons = soa::Filtered; +using FilteredMyMuons = o2::soa::Filtered; using FilteredMyMuon = FilteredMyMuons::iterator; template struct DileptonProducer { - Produces eventTable; - Produces normTable; - Produces dileptonTable; + o2::framework::Produces eventTable; + o2::framework::Produces normTable; + o2::framework::Produces dileptonTable; // 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 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"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; - Configurable cfgStoreULS{"cfgStoreULS", true, "flag to store ULS pairs"}; - Configurable cfgStoreLS{"cfgStoreLS", true, "flag to store LS pairs"}; + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + o2::framework::Configurable cfgEP2Estimator_for_Mix{"cfgEP2Estimator_for_Mix", 3, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; + o2::framework::Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; + o2::framework::Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + o2::framework::Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; + o2::framework::Configurable cfgStoreULS{"cfgStoreULS", true, "flag to store ULS pairs"}; + o2::framework::Configurable cfgStoreLS{"cfgStoreLS", true, "flag to store LS pairs"}; EMEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - 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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + o2::framework::Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::framework::Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + o2::framework::Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + o2::framework::Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + o2::framework::Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; } eventcuts; DielectronCut fDielectronCut; - struct : ConfigurableGroup { + struct : o2::framework::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_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_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; - Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; - Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; - Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; - Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; - Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; - - Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; - Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply pair cut same as prefilter set in derived data"}; - Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h - - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; - Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; - 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "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_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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; - Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. - Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; - Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; - 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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; - Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; - Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pT"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pT"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -0.8, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", +0.8, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dca3d{"cfg_min_pair_dca3d", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dca3d{"cfg_max_pair_dca3d", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + o2::framework::Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + o2::framework::Configurable cfg_min_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; + o2::framework::Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; + o2::framework::Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; + o2::framework::Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; + // o2::framework::Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + o2::framework::Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply pair cut same as prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + o2::framework::Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + o2::framework::Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + // o2::framework::Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // o2::framework::Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + o2::framework::Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + // o2::framework::Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // o2::framework::Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + o2::framework::Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; // configuration for PID ML - Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - 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)"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + o2::framework::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"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dielectroncuts; DimuonCut fDimuonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; - Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; - Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; - - 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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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+6, "max chi2/ndf"}; - Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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"}; - Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; - Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 1e+10, "max mass"}; + o2::framework::Configurable cfg_min_pair_pt{"cfg_min_pair_pt", 0.0, "min pair pt"}; + o2::framework::Configurable cfg_max_pair_pt{"cfg_max_pair_pt", 1e+10, "max pair pt"}; + o2::framework::Configurable cfg_min_pair_y{"cfg_min_pair_y", -4.0, "min pair rapidity"}; + o2::framework::Configurable cfg_max_pair_y{"cfg_max_pair_y", -2.5, "max pair rapidity"}; + o2::framework::Configurable cfg_min_pair_dcaxy{"cfg_min_pair_dcaxy", 0.0, "min pair dca3d in sigma"}; + o2::framework::Configurable cfg_max_pair_dcaxy{"cfg_max_pair_dcaxy", 1e+10, "max pair dca3d in sigma"}; + o2::framework::Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; + o2::framework::Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; + o2::framework::Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + + o2::framework::Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + o2::framework::Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + o2::framework::Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + o2::framework::Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; - Service ccdb; + o2::framework::Service ccdb; int mRunNumber; float d_bz; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; std::mt19937 engine; float leptonM1 = 0.f; float leptonM2 = 0.f; - void init(InitContext& /*context*/) + void init(o2::framework::InitContext& /*context*/) { mRunNumber = 0; d_bz = 0; @@ -390,7 +390,7 @@ struct DileptonProducer { fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); - fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + // fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); // for track fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); @@ -409,8 +409,7 @@ struct DileptonProducer { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -513,18 +512,18 @@ struct DileptonProducer { float dca1 = 999.f, dca2 = 999.f; if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - dca1 = dca3DinSigma(t1); - dca2 = dca3DinSigma(t2); + dca1 = o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t1); + dca2 = o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(t2); if (cfgDCAType == 1) { - dca1 = dcaXYinSigma(t1); - dca2 = dcaXYinSigma(t2); + dca1 = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t1); + dca2 = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(t2); } else if (cfgDCAType == 2) { - dca1 = dcaZinSigma(t1); - dca2 = dcaZinSigma(t2); + dca1 = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t1); + dca2 = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(t2); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { - dca1 = fwdDcaXYinSigma(t1); - dca2 = fwdDcaXYinSigma(t2); + dca1 = o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t1); + dca2 = o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t2); } // fill table here @@ -536,42 +535,46 @@ struct DileptonProducer { return true; } - Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); - // Filter collisionFilter_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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 && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; - Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); - Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); - - Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && - ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), - o2::aod::emprimaryelectron::pfb >= static_cast(0)); - - 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 && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_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); + o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = o2::soa::Filtered; + + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::expressions::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 && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + o2::framework::expressions::Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + + o2::framework::Partition positive_electrons = o2::aod::emprimaryelectron::sign > int8_t(0); + o2::framework::Partition negative_electrons = o2::aod::emprimaryelectron::sign < int8_t(0); + + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && dimuoncuts.cfg_min_eta_track < o2::aod::fwdtrack::eta && o2::aod::fwdtrack::eta < dimuoncuts.cfg_max_eta_track; + o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + o2::framework::expressions::Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(0)); + o2::framework::Partition positive_muons = o2::aod::emprimarymuon::sign > int8_t(0); + o2::framework::Partition negative_muons = o2::aod::emprimarymuon::sign < int8_t(0); int ndf = 0; template @@ -601,7 +604,7 @@ struct DileptonProducer { int nuls = 0, nlspp = 0, nlsmm = 0; if (cfgStoreULS) { - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS bool is_pair_ok = fillPairInfo(collision, pos, neg, cut, tracks); if (is_pair_ok) { nuls++; @@ -609,13 +612,13 @@ struct DileptonProducer { } } if (cfgStoreLS) { - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ bool is_pair_ok = fillPairInfo(collision, pos1, pos2, cut, tracks); if (is_pair_ok) { nlspp++; } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- bool is_pair_ok = fillPairInfo(collision, neg1, neg2, cut, tracks); if (is_pair_ok) { nlsmm++; @@ -691,17 +694,17 @@ struct DileptonProducer { auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, neg] : combinations(o2::soa::CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS if (isPairOK(pos, neg, cut, tracks)) { passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); } } - for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (isPairOK(pos1, pos2, cut, tracks)) { passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); } } - for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [neg1, neg2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (isPairOK(neg1, neg2, cut, tracks)) { passed_pairIds.emplace_back(std::make_pair(neg1.globalIndex(), neg2.globalIndex())); } @@ -764,14 +767,14 @@ struct DileptonProducer { } PROCESS_SWITCH(DileptonProducer, processAnalysis, "run dilepton analysis", true); - void processNorm(aod::EMEventNormInfos const& collisions) + void processNorm(o2::aod::EMEventNormInfos const& collisions) { for (const auto& collision : collisions) { if (collision.centFT0C() < eventcuts.cfgCentMin || eventcuts.cfgCentMax < collision.centFT0C()) { continue; } - normTable(collision.selection_raw(), collision.rct_raw(), collision.posZint16(), collision.centFT0Cuint16()); + normTable(collision.selection_raw(), collision.rct_raw(), collision.posZint8(), collision.centFT0Muint8(), collision.centFT0Cuint8(), collision.centNTPVuint8() /*, collision.centNGlobaluint8()*/); } // end of collision loop } diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index c9cded44408..f3a67d06d4a 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -15,8 +15,11 @@ #include "PWGEM/Dilepton/Core/DimuonCut.h" -#include "Framework/Logger.h" +#include +#include + +#include #include ClassImp(DimuonCut); @@ -93,6 +96,11 @@ void DimuonCut::SetMatchingChi2MCHMFT(float min, float max) mMaxMatchingChi2MCHMFT = max; LOG(info) << "Dimuon Cut, set matching chi2 MFT-MCH range: " << mMinMatchingChi2MCHMFT << " - " << mMaxMatchingChi2MCHMFT; } +void DimuonCut::SetMaxMatchingChi2MCHMFTPtDep(std::function PtDepCut) +{ + mMaxMatchingChi2MCHMFTPtDep = PtDepCut; + LOG(info) << "Dimuon Cut, set matching chi2 MFT-MCH range: " << mMaxMatchingChi2MCHMFTPtDep(0.5); +} void DimuonCut::SetMatchingChi2MCHMID(float min, float max) { mMinMatchingChi2MCHMID = min; @@ -123,6 +131,11 @@ void DimuonCut::SetDCAxy(float min, float max) mMaxDcaXY = max; LOG(info) << "Dimuon Cut, set DCAxy range: " << mMinDcaXY << " - " << mMaxDcaXY; } +void DimuonCut::EnableTTCA(const bool flag) +{ + mEnableTTCA = flag; + LOG(info) << "Dimuon Cut, enable TTCA: " << mEnableTTCA; +} void DimuonCut::SetMaxPDCARabsDep(std::function RabsDepCut) { mMaxPDCARabsDep = RabsDepCut; diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index 80968cc9e81..4f009b456db 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. // -// Class for dimuon selection +// Class for dimuon selection // dummy comment // #ifndef PWGEM_DILEPTON_CORE_DIMUONCUT_H_ @@ -18,21 +18,22 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/DataTypes.h" -#include "Framework/Logger.h" -#include "MathUtils/Utils.h" +#include +#include +#include -#include "Math/Vector4D.h" -#include "TNamed.h" +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include -#include -#include -#include -#include +#include + +#include +#include +#include #include -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; +#include class DimuonCut : public TNamed { @@ -64,6 +65,7 @@ class DimuonCut : public TNamed kPDCA, kMFTHitMap, kDPtDEtaDPhiwrtMCHMID, + kTTCA, kNCuts }; @@ -91,8 +93,8 @@ 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 dca_xy_t1 = fwdDcaXYinSigma(t1); - float dca_xy_t2 = fwdDcaXYinSigma(t2); + float dca_xy_t1 = o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(t1); + float dca_xy_t2 = o2::aod::pwgem::dilepton::utils::emtrackutil::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()) { @@ -166,6 +168,9 @@ class DimuonCut : public TNamed if (!IsSelectedTrack(track, DimuonCuts::kRabs)) { return false; } + if (!IsSelectedTrack(track, DimuonCuts::kTTCA)) { + return false; + } if (mApplyMFTHitMap && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kMFTHitMap)) { return false; } @@ -202,16 +207,17 @@ class DimuonCut : public TNamed return track.nClusters() >= mMinNClustersMCHMID; case DimuonCuts::kChi2: - return track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) < mMaxChi2 : track.chi2() < mMaxChi2; + return track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? 0.f < track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) && track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) < mMaxChi2 : 0.f < track.chi2() && track.chi2() < mMaxChi2; case DimuonCuts::kChi2MFT: - return track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) < mMaxChi2MFT : true; + return track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? 0.f < track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) && track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) < mMaxChi2MFT : true; case DimuonCuts::kMatchingChi2MCHMFT: - return track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; + // return 0.f < track.chi2MatchMCHMFT() && track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; + return 0.f < track.chi2MatchMCHMFT() && track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFTPtDep(track.pt()); case DimuonCuts::kMatchingChi2MCHMID: - return track.chi2MatchMCHMID() < mMaxMatchingChi2MCHMID; + return 0.f < track.chi2MatchMCHMID() && track.chi2MatchMCHMID() < mMaxMatchingChi2MCHMID; case DimuonCuts::kPDCA: return track.pDca() < mMaxPDCARabsDep(track.rAtAbsorberEnd()); @@ -219,8 +225,11 @@ class DimuonCut : public TNamed case DimuonCuts::kRabs: return mMinRabs < track.rAtAbsorberEnd() && track.rAtAbsorberEnd() < mMaxRabs; + case DimuonCuts::kTTCA: + return mEnableTTCA ? true : track.isAssociatedToMPC(); + case DimuonCuts::kMFTHitMap: { - std::vector mftHitMap{checkMFTHitMap<0, 1>(track), checkMFTHitMap<2, 3>(track), checkMFTHitMap<4, 5>(track), checkMFTHitMap<6, 7>(track), checkMFTHitMap<8, 9>(track)}; + std::vector mftHitMap{o2::aod::pwgem::dilepton::utils::emtrackutil::checkMFTHitMap<0, 1>(track), o2::aod::pwgem::dilepton::utils::emtrackutil::checkMFTHitMap<2, 3>(track), o2::aod::pwgem::dilepton::utils::emtrackutil::checkMFTHitMap<4, 5>(track), o2::aod::pwgem::dilepton::utils::emtrackutil::checkMFTHitMap<6, 7>(track), o2::aod::pwgem::dilepton::utils::emtrackutil::checkMFTHitMap<8, 9>(track)}; for (const auto& iDisk : mRequiredMFTDisks) { if (!mftHitMap[iDisk]) { return false; @@ -259,6 +268,8 @@ class DimuonCut : public TNamed void SetMaxPDCARabsDep(std::function RabsDepCut); void SetMFTHitMap(bool flag, std::vector hitMap); void SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax); // this is relevant for global muons + void SetMaxMatchingChi2MCHMFTPtDep(std::function PtDepCut); + void EnableTTCA(bool flag); private: // pair cuts @@ -269,6 +280,7 @@ class DimuonCut : public TNamed bool mApplydEtadPhi{false}; // flag to apply deta, dphi cut between 2 tracks float mMinDeltaEta{0.f}; float mMinDeltaPhi{0.f}; + bool mEnableTTCA{true}; // kinematic cuts float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT @@ -284,6 +296,7 @@ class DimuonCut : public TNamed float mMinMatchingChi2MCHMFT{0.f}, mMaxMatchingChi2MCHMFT{1e10f}; // max matching chi2 between MCH-MFT float mMinMatchingChi2MCHMID{0.f}, mMaxMatchingChi2MCHMID{1e10f}; // max matching chi2 between MCH-MID std::function mMaxPDCARabsDep{}; // max pdca in xy plane as function of Rabs + std::function mMaxMatchingChi2MCHMFTPtDep{}; // max matching chi2 between MCH-MFT as function of pt float mMinRabs{17.6}, mMaxRabs{89.5}; float mMinDcaXY{0.0f}, mMaxDcaXY{1e10f}; diff --git a/PWGEM/Dilepton/Core/EMEventCut.cxx b/PWGEM/Dilepton/Core/EMEventCut.cxx index 58e3c5be4e8..fd418c45abb 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.cxx +++ b/PWGEM/Dilepton/Core/EMEventCut.cxx @@ -15,7 +15,9 @@ #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "Framework/Logger.h" +#include + +#include ClassImp(EMEventCut); diff --git a/PWGEM/Dilepton/Core/EMEventCut.h b/PWGEM/Dilepton/Core/EMEventCut.h index 8dc1b7ef961..b0450f5b575 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.h +++ b/PWGEM/Dilepton/Core/EMEventCut.h @@ -16,12 +16,11 @@ #ifndef PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ #define PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/TriggerAliases.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "TNamed.h" +#include -using namespace std; +#include class EMEventCut : public TNamed { @@ -116,52 +115,52 @@ class EMEventCut : public TNamed return collision.sel8(); case EMEventCuts::kFT0AND: - return collision.selection_bit(o2::aod::evsel::kIsTriggerTVX); + return collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX); case EMEventCuts::kZvtx: return mMinZvtx < collision.posZ() && collision.posZ() < mMaxZvtx; case EMEventCuts::kNoTFB: - return collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder); + return collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder); case EMEventCuts::kNoITSROFB: - return collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder); + return collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder); case EMEventCuts::kNoSameBunchPileup: - return collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + return collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup); case EMEventCuts::kIsVertexITSTPC: - return collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + return collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC); case EMEventCuts::kIsVertexTOFmatched: - return collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); + return collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched); case EMEventCuts::kIsGoodZvtxFT0vsPV: - return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + return collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV); case EMEventCuts::kNoCollInTimeRangeStandard: - return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + return collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard); case EMEventCuts::kNoCollInTimeRangeStrict: - return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict); + return collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict); case EMEventCuts::kNoCollInITSROFStandard: - return collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard); + return collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard); case EMEventCuts::kNoCollInITSROFStrict: - return collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict); + return collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict); case EMEventCuts::kNoHighMultCollInPrevRof: - return collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof); + return collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof); case EMEventCuts::kIsGoodITSLayer3: - return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3); + return collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3); case EMEventCuts::kIsGoodITSLayer0123: - return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123); + return collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123); case EMEventCuts::kIsGoodITSLayersAll: - return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + return collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll); default: return true; diff --git a/PWGEM/Dilepton/Core/EMTrackCut.cxx b/PWGEM/Dilepton/Core/EMTrackCut.cxx index 2ea7934a30b..fda35ac925f 100644 --- a/PWGEM/Dilepton/Core/EMTrackCut.cxx +++ b/PWGEM/Dilepton/Core/EMTrackCut.cxx @@ -15,15 +15,13 @@ #include "PWGEM/Dilepton/Core/EMTrackCut.h" -#include "Framework/Logger.h" +#include -#include -#include +#include -ClassImp(EMTrackCut); +#include -const std::pair> EMTrackCut::its_ib_any_Requirement = {1, {0, 1, 2}}; // hits on any ITS ib layers. -const std::pair> EMTrackCut::its_ib_1st_Requirement = {1, {0}}; // hit on 1st ITS ib layers. +ClassImp(EMTrackCut); void EMTrackCut::SetTrackPtRange(float minPt, float maxPt) { @@ -43,74 +41,6 @@ void EMTrackCut::SetTrackPhiRange(float minPhi, float maxPhi) mMaxTrackPhi = maxPhi; LOG(info) << "EMTrack Cut, set track phi range (rad.): " << mMinTrackPhi << " - " << mMaxTrackPhi; } -void EMTrackCut::SetMinNClustersTPC(int minNClustersTPC) -{ - mMinNClustersTPC = minNClustersTPC; - LOG(info) << "EMTrack Cut, set min N clusters TPC: " << mMinNClustersTPC; -} -void EMTrackCut::SetMinNCrossedRowsTPC(int minNCrossedRowsTPC) -{ - mMinNCrossedRowsTPC = minNCrossedRowsTPC; - LOG(info) << "EMTrack Cut, set min N crossed rows TPC: " << mMinNCrossedRowsTPC; -} -void EMTrackCut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC) -{ - mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; - LOG(info) << "EMTrack Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; -} -void EMTrackCut::SetMaxFracSharedClustersTPC(float max) -{ - mMaxFracSharedClustersTPC = max; - LOG(info) << "EMTrack Cut, set max fraction of shared clusters in TPC: " << mMaxFracSharedClustersTPC; -} -void EMTrackCut::SetChi2PerClusterTPC(float min, float max) -{ - mMinChi2PerClusterTPC = min; - mMaxChi2PerClusterTPC = max; - LOG(info) << "EMTrack Cut, set chi2 per cluster TPC range: " << mMinChi2PerClusterTPC << " - " << mMaxChi2PerClusterTPC; -} - -void EMTrackCut::SetNClustersITS(int min, int max) -{ - mMinNClustersITS = min; - mMaxNClustersITS = max; - LOG(info) << "EMTrack Cut, set N clusters ITS range: " << mMinNClustersITS << " - " << mMaxNClustersITS; -} -void EMTrackCut::SetChi2PerClusterITS(float min, float max) -{ - mMinChi2PerClusterITS = min; - mMaxChi2PerClusterITS = max; - LOG(info) << "EMTrack Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; -} - -void EMTrackCut::SetTrackMaxDcaXY(float maxDcaXY) -{ - mMaxDcaXY = maxDcaXY; - LOG(info) << "EMTrack Cut, set max DCA xy: " << mMaxDcaXY; -} -void EMTrackCut::SetTrackMaxDcaZ(float maxDcaZ) -{ - mMaxDcaZ = maxDcaZ; - LOG(info) << "EMTrack Cut, set max DCA z: " << mMaxDcaZ; -} - -void EMTrackCut::SetTrackMaxDcaXYPtDep(std::function ptDepCut) -{ - mMaxDcaXYPtDep = ptDepCut; - LOG(info) << "EMTrack Cut, set max DCA xy pt dep: " << mMaxDcaXYPtDep(1.0); -} - -void EMTrackCut::RequireITSibAny(bool flag) -{ - mRequireITSibAny = flag; - LOG(info) << "EMTrack Cut, require ITS ib any: " << mRequireITSibAny; -} - -void EMTrackCut::RequireITSib1st(bool flag) -{ - mRequireITSib1st = flag; - LOG(info) << "EMTrack Cut, require ITS ib 1st: " << mRequireITSib1st; -} void EMTrackCut::SetTrackBit(uint16_t bit) { diff --git a/PWGEM/Dilepton/Core/EMTrackCut.h b/PWGEM/Dilepton/Core/EMTrackCut.h index d70a009aaac..e338aaa2140 100644 --- a/PWGEM/Dilepton/Core/EMTrackCut.h +++ b/PWGEM/Dilepton/Core/EMTrackCut.h @@ -16,22 +16,11 @@ #ifndef PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ #define PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/DataTypes.h" -#include "Framework/Logger.h" +#include -#include "Math/Vector4D.h" -#include "TNamed.h" - -#include -#include -#include -#include -#include - -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; +#include class EMTrackCut : public TNamed { @@ -45,15 +34,6 @@ class EMTrackCut : public TNamed kTrackPtRange, kTrackEtaRange, kTrackPhiRange, - // kDCAxy, - // kDCAz, - // kTPCNCls, - // kTPCCrossedRows, - // kTPCCrossedRowsOverNCls, - // kTPCFracSharedClusters, - // kTPCChi2NDF, - // kITSNCls, - // kITSChi2NDF, kTrackBit, kNCuts }; @@ -61,70 +41,22 @@ class EMTrackCut : public TNamed template bool IsSelected(TTrack const& track) const { - // if (!track.hasITS() || !track.hasTPC()) { - // return false; - // } - if (!IsSelectedTrack(track, EMTrackCuts::kTrackPtRange)) { return false; } + if (!IsSelectedTrack(track, EMTrackCuts::kTrackEtaRange)) { return false; } + if (!IsSelectedTrack(track, EMTrackCuts::kTrackPhiRange)) { return false; } - // if (!IsSelectedTrack(track, EMTrackCuts::kDCAxy)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kDCAz)) { - // return false; - // } - if (!IsSelectedTrack(track, EMTrackCuts::kTrackBit)) { return false; } - // // ITS cuts - // if (!IsSelectedTrack(track, EMTrackCuts::kITSNCls)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kITSChi2NDF)) { - // 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, EMTrackCuts::kTPCNCls)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCCrossedRows)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCCrossedRowsOverNCls)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCFracSharedClusters)) { - // return false; - // } - // if (!IsSelectedTrack(track, EMTrackCuts::kTPCChi2NDF)) { - // return false; - // } - return true; } @@ -141,42 +73,8 @@ class EMTrackCut : public TNamed case EMTrackCuts::kTrackPhiRange: return track.phi() > mMinTrackPhi && track.phi() < mMaxTrackPhi; - // case EMTrackCuts::kDCAxy: - // return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); - - // case EMTrackCuts::kDCAz: - // return std::fabs(track.dcaZ()) < mMaxDcaZ; - - case EMTrackCuts::kTrackBit: { - // for (int i = 0; i < 10; i++) { - // if ((mTrackBit & (1 << i)) > 0 && !((track.trackBit() & (1 << i)) > 0)) { - // return false; - // } - // } - // return true; + case EMTrackCuts::kTrackBit: return (track.trackBit() & mTrackBit) >= mTrackBit; - } - - // case EMTrackCuts::kTPCNCls: - // return track.tpcNClsFound() >= mMinNClustersTPC; - - // case EMTrackCuts::kTPCCrossedRows: - // return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; - - // case EMTrackCuts::kTPCCrossedRowsOverNCls: - // return track.tpcCrossedRowsOverFindableCls() > mMinNCrossedRowsOverFindableClustersTPC; - - // case EMTrackCuts::kTPCFracSharedClusters: - // return track.tpcFractionSharedCls() < mMaxFracSharedClustersTPC; - - // case EMTrackCuts::kTPCChi2NDF: - // return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; - - // case EMTrackCuts::kITSNCls: - // return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; - - // case EMTrackCuts::kITSChi2NDF: - // return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; default: return false; @@ -187,47 +85,14 @@ class EMTrackCut : public TNamed 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 = 6.3f); - void SetMinNClustersTPC(int minNClustersTPC); - void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC); - void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC); - void SetMaxFracSharedClustersTPC(float max); - void SetChi2PerClusterTPC(float min, float max); - void SetNClustersITS(int min, int max); - void SetChi2PerClusterITS(float min, float max); - - 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 RequireITSibAny(bool flag); - void RequireITSib1st(bool flag); void SetTrackBit(uint16_t bits); private: - static const std::pair> its_ib_any_Requirement; - static const std::pair> its_ib_1st_Requirement; - - // kinematic cuts float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta float mMinTrackPhi{0.f}, mMaxTrackPhi{6.3}; // 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{0.f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster - float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters - float mMaxFracSharedClustersTPC{999.f}; // max ratio shared clusters / clusters in TPC - int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters - float mMinChi2PerClusterITS{0.f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster - bool mRequireITSibAny{true}; - bool mRequireITSib1st{false}; uint16_t mTrackBit{0}; - 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 - ClassDef(EMTrackCut, 1); }; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 7156dec925b..fc716d7798e 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -23,208 +23,227 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/Zorro.h" -#include "Tools/ML/MlResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TString.h" - -#include +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include #include +#include #include #include -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; +#include -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyElectrons = soa::Join; +using MyElectrons = o2::soa::Join; using MyElectron = MyElectrons::iterator; -using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectrons = o2::soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; -using MyMuons = soa::Join; +using MyMuons = o2::soa::Join; using MyMuon = MyMuons::iterator; -using FilteredMyMuons = soa::Filtered; +using FilteredMyMuons = o2::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 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", -1, "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 cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; - Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; - Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - - 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"}; - ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {VARIABLE_WIDTH, 0.0, 10.0}, "DCA3d bins in sigma for output histograms"}; - ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAxy bins in sigma for output histograms"}; - ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAz bins in sigma for output histograms"}; + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + + o2::framework::ConfigurableAxis ConfPtlBins{"ConfPtlBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfEtaBins{"ConfEtaBins", {20, -1, 1}, "eta bins for output histograms"}; + o2::framework::ConfigurableAxis ConfPhiBins{"ConfPhiBins", {36, 0, 2 * M_PI}, "phi bins for output histograms"}; + o2::framework::ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {o2::framework::VARIABLE_WIDTH, 0.0, 10.0}, "DCA3d bins in sigma for output histograms"}; + o2::framework::ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {o2::framework::VARIABLE_WIDTH, -10.0, 10.0}, "DCAxy bins in sigma for output histograms"}; + o2::framework::ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {o2::framework::VARIABLE_WIDTH, -10.0, 10.0}, "DCAz bins in sigma for output histograms"}; EMEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - 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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + o2::framework::Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::framework::Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + o2::framework::Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + o2::framework::Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + o2::framework::Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; } eventcuts; DielectronCut fDielectronCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "dielectroncut_group"; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max phi should be in 0-Pi"}; - Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; - 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "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_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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; - Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. - Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; - Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "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", -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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; - Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; - Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max phi should be in 0-Pi"}; + o2::framework::Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + o2::framework::Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + o2::framework::Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + o2::framework::Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + o2::framework::Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif = 4, kPIDML = 5]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + // o2::framework::Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // o2::framework::Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + o2::framework::Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; // configuration for PID ML - Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - 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)"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + o2::framework::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"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dielectroncuts; DimuonCut fDimuonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_max_pt_track{"cfg_max_pt_track", 1e+10, "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+6, "max chi2/ndf"}; - Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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"}; - Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; - Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + o2::framework::Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "min pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // o2::framework::Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + o2::framework::Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "zorroGroup"; - Configurable cfg_swt_name{"cfg_swt_name", "fLMeeIMR", "desired software trigger name"}; // 1 trigger per 1 task + o2::framework::Configurable cfg_swt_name{"cfg_swt_name", "fLMeeIMR", "desired software trigger name. 1 trigger per 1 task."}; // 1 trigger per 1 task o2::framework::Configurable ccdbPathSoftwareTrigger{"ccdbPathSoftwareTrigger", "EventFiltering/Zorro/", "ccdb path for ZORRO objects"}; - Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; + o2::framework::Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; } zorroGroup; - o2::aod::rctsel::RCTFlagsChecker rctChecker; - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; Zorro zorro; + int mToIidx = 0; + int mTOICounter = 0; + int mATCounter = 0; + + o2::aod::rctsel::RCTFlagsChecker rctChecker; + // o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service ccdb; + int mRunNumber = 0; + float d_bz = 0; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; // 1 HistogramRegistry can keep up to 512 histograms + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, false}; // 1 o2::framework::HistogramRegistry can keep up to 512 histograms static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; ~SingleTrackQC() {} @@ -235,89 +254,91 @@ struct SingleTrackQC { 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_phiposition{36, 0.0, 2 * M_PI, "#varphi_{e}^{*} (rad.)"}; - const AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; - const AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; - const AxisSpec axis_dcaZ{ConfDCAZBins, "DCA_{e}^{Z} (#sigma)"}; + const o2::framework::AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; + const o2::framework::AxisSpec axis_eta{ConfEtaBins, "#eta_{e}"}; + const o2::framework::AxisSpec axis_phi{ConfPhiBins, "#varphi_{e} (rad.)"}; + const o2::framework::AxisSpec axis_phiposition{36, 0.0, 2 * M_PI, "#varphi_{e}^{*} (rad.)"}; + const o2::framework::AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; + const o2::framework::AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; + const o2::framework::AxisSpec axis_dcaZ{ConfDCAZBins, "DCA_{e}^{Z} (#sigma)"}; // track info - fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ}, true); - fRegistry.add("Track/positive/hPhiPosition", Form("phi position at r_{xy} = %3.2f m", dielectroncuts.cfgRefR.value), kTH1F, {axis_phiposition}, false); - fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{4000, -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.f, 1.f}}, false); - fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.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}, {500, 0., 500}}, false); - fRegistry.add("Track/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);TPC N_{cls}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); - fRegistry.add("Track/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);TPC N_{CR}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); - fRegistry.add("Track/positive/hChi2TPC", "chi2/number of TPC clusters;TPC #chi^{2}/N_{CR}", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{in} (GeV/c);(p_{pv} - p_{in})/p_{in}", kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); - fRegistry.add("Track/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable;TPC N_{CR}/N_{cls}^{findable}", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable;TPC N_{cls}/N_{cls}^{findable}", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/positive/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/positive/hNclsITS", "number of ITS clusters;ITS N_{cls}", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/positive/hChi2ITS", "chi2/number of ITS clusters;ITS #chi^{2}/N_{cls}", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);TOF #chi^{2}", kTH2F, {{1000, 0, 10}, {100, 0, 10}}, 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/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/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, 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.add("Track/positive/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, 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}, {150, 0, 15}}, false); - fRegistry.add("Track/positive/hMeanClusterSizeITSib", "mean cluster size ITS inner barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); - fRegistry.add("Track/positive/hMeanClusterSizeITSob", "mean cluster size ITS outer barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); + fRegistry.add("Track/positive/hs", "rec. single electron", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ}, true); + fRegistry.add("Track/positive/hPhiPosition", Form("phi position at r_{xy} = %3.2f m", dielectroncuts.cfgRefR.value), o2::framework::kTH1F, {axis_phiposition}, false); + fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", o2::framework::kTH1F, {{4000, -20, 20}}, false); + fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", o2::framework::kTH2F, {{200, -1.0f, 1.0f}, {200, -1.f, 1.f}}, false); + fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", o2::framework::kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); + fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);TPC N_{cls}", o2::framework::kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);TPC N_{CR}", o2::framework::kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hChi2TPC", "chi2/number of TPC clusters;TPC #chi^{2}/N_{CR}", o2::framework::kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{in} (GeV/c);(p_{pv} - p_{in})/p_{in}", o2::framework::kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); + fRegistry.add("Track/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable;TPC N_{CR}/N_{cls}^{findable}", o2::framework::kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable;TPC N_{cls}/N_{cls}^{findable}", o2::framework::kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/positive/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", o2::framework::kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/positive/hNclsITS", "number of ITS clusters;ITS N_{cls}", o2::framework::kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/positive/hChi2ITS", "chi2/number of ITS clusters;ITS #chi^{2}/N_{cls}", o2::framework::kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/positive/hITSClusterMap", "ITS cluster map", o2::framework::kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);TOF #chi^{2}", o2::framework::kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); + + fRegistry.add("Track/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", o2::framework::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + + fRegistry.add("Track/positive/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", o2::framework::kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/positive/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + + fRegistry.add("Track/positive/hPIDForTracking", "PID for trackng", o2::framework::kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + fRegistry.add("Track/positive/hProbElBDT", "probability to be e from BDT;p_{in} (GeV/c);BDT score;", o2::framework::kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", o2::framework::kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); + fRegistry.add("Track/positive/hMeanClusterSizeITSib", "mean cluster size ITS inner barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda);", o2::framework::kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); + fRegistry.add("Track/positive/hMeanClusterSizeITSob", "mean cluster size ITS outer barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda);", o2::framework::kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, 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{50, -6, -1, "#eta_{#mu}"}; - const AxisSpec axis_phi{36, 0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; - const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; + const o2::framework::AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; + const o2::framework::AxisSpec axis_eta{ConfEtaBins, "#eta_{#mu}"}; + const o2::framework::AxisSpec axis_phi{ConfPhiBins, "#varphi_{#mu} (rad.)"}; + const o2::framework::AxisSpec axis_dca{ConfDCAXYBins, "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/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", kTH2F, {{180, 0, 2.f * M_PI}, {100, -6, -1}}, false); - fRegistry.add("Track/positive/hsDelta", "diff. between GL and associated SA;p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl};#Delta#eta;#Delta#varphi (rad.);", kTHnSparseF, {axis_pt, {100, -0.5, +0.5}, {100, -0.5, +0.5}, {90, -M_PI / 4, M_PI / 4}}, false); - fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -5, 5}}, 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, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, 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}, {500, 0, 500}}, false); - fRegistry.add("Track/positive/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); - fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); - fRegistry.add("Track/positive/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {200, -1, +1}}, false); - fRegistry.add("Track/positive/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {200, -1, +1}}, 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;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/positive/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("Track/positive/hChi2MFT", "chi2MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, 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.add("Track/positive/hs", "rec. single muon", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); + fRegistry.add("Track/positive/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", o2::framework::kTH2F, {{180, 0, 2.f * M_PI}, {80, -4, -2}}, false); + fRegistry.add("Track/positive/hsDelta", "diff. between GL and associated SA;p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl};#Delta#eta;#Delta#varphi (rad.);", o2::framework::kTHnSparseF, {axis_pt, {100, -0.5, +0.5}, {100, -0.5, +0.5}, {90, -M_PI / 4, M_PI / 4}}, false); + fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", o2::framework::kTH1F, {{1000, -5, 5}}, false); + fRegistry.add("Track/positive/hTrackType", "track type", o2::framework::kTH1F, {{6, -0.5f, 5.5}}, false); + fRegistry.add("Track/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", o2::framework::kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); + fRegistry.add("Track/positive/hDCAxySigma", "DCA x vs. y;DCA_{x} (#sigma);DCA_{y} (#sigma)", o2::framework::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)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); + fRegistry.add("Track/positive/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); + fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); + fRegistry.add("Track/positive/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", o2::framework::kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/positive/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", o2::framework::kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/positive/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", o2::framework::kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/positive/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", o2::framework::kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/positive/hNclsMCH", "number of MCH clusters", o2::framework::kTH1F, {{21, -0.5, 20.5}}, false); + fRegistry.add("Track/positive/hNclsMFT", "number of MFT clusters", o2::framework::kTH1F, {{11, -0.5, 10.5}}, false); + fRegistry.add("Track/positive/hPDCA", "pDCA;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", o2::framework::kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); + fRegistry.add("Track/positive/hChi2_Pt", "chi2;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("Track/positive/hChi2MFT_Pt", "chi2MFT;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMID_Pt", "chi2 match MCH-MID;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {200, 0.0f, 20}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {100, 0.0f, 50}}, false); + fRegistry.add("Track/positive/hMFTClusterMap", "MFT cluster map", o2::framework::kTH1F, {{1024, -0.5, 1023.5}}, false); + fRegistry.add("Track/positive/hdR_Chi2MatchMCHMFT", "dr vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;#DeltaR;", o2::framework::kTH2F, {{200, 0, 50}, {200, 0, 0.5}}, false); fRegistry.addClone("Track/positive/", "Track/negative/"); } } - int mRunNumber; - float d_bz; - void init(InitContext&) + void init(o2::framework::InitContext&) { ccdb->setURL(ccdburl); ccdb->setCaching(true); @@ -331,12 +352,24 @@ struct SingleTrackQC { addhistograms(); mRunNumber = 0; d_bz = 0; + mToIidx = 0; + mTOICounter = 0; + mATCounter = 0; + + if (doprocessQC_TriggeredData) { + LOGF(info, "Trigger analysis is enabled. Desired trigger name = %s", zorroGroup.cfg_swt_name.value.data()); + fRegistry.add("Event/trigger/hInspectedTVX", "inspected TVX;run number;N_{TVX}", o2::framework::kTProfile, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hScaler", "trigger counter before DS;run number;counter", o2::framework::kTProfile, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hSelection", "trigger counter after DS;run number;counter", o2::framework::kTProfile, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hAnalysedTrigger", Form("analysed trigger %s;run number;counter", zorroGroup.cfg_swt_name.value.data()), o2::framework::kTH1D, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + fRegistry.add("Event/trigger/hAnalysedToI", Form("analysed ToI %s;run number;counter", zorroGroup.cfg_swt_name.value.data()), o2::framework::kTH1D, {{100000, 500000.5, 600000.5}}, true); // extend X range in Run 4/5 + } if (doprocessNorm) { fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); } if (doprocessBC) { - auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", kTH1D, {{6, -0.5f, 5.5f}}); + auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", o2::framework::kTH1D, {{6, -0.5f, 5.5f}}); hTVXCounter->GetXaxis()->SetBinLabel(1, "TVX"); hTVXCounter->GetXaxis()->SetBinLabel(2, "TVX && NoTFB"); hTVXCounter->GetXaxis()->SetBinLabel(3, "TVX && NoITSROFB"); @@ -391,8 +424,17 @@ struct SingleTrackQC { if constexpr (isTriggerAnalysis) { zorro.setCCDBpath(zorroGroup.ccdbPathSoftwareTrigger); zorro.setBCtolerance(zorroGroup.bcMarginForSoftwareTrigger); // this does nothing. - zorro.initCCDB(ccdb.service, collision.runNumber(), collision.timestamp(), zorroGroup.cfg_swt_name.value); + mToIidx = zorro.initCCDB(ccdb.service, collision.runNumber(), collision.timestamp(), zorroGroup.cfg_swt_name.value)[0]; zorro.populateHistRegistry(fRegistry, collision.runNumber()); + + uint64_t nInspectedTVX = zorro.getInspectedTVX()->GetBinContent(1); + uint64_t nScalers = zorro.getScalers()->GetBinContent(zorro.getScalers()->GetXaxis()->FindBin(zorroGroup.cfg_swt_name.value.data())); + uint64_t nSelections = zorro.getSelections()->GetBinContent(zorro.getSelections()->GetXaxis()->FindBin(zorroGroup.cfg_swt_name.value.data())); + LOGF(info, "run number %d: total inspected TVX events = %llu, scalers = %llu, selections = %llu", collision.runNumber(), nInspectedTVX, nScalers, nSelections); + + fRegistry.fill(HIST("Event/trigger/hInspectedTVX"), collision.runNumber(), nInspectedTVX); + fRegistry.fill(HIST("Event/trigger/hScaler"), collision.runNumber(), nScalers); + fRegistry.fill(HIST("Event/trigger/hSelection"), collision.runNumber(), nSelections); } } @@ -418,7 +460,6 @@ struct SingleTrackQC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -441,7 +482,7 @@ struct SingleTrackQC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -465,31 +506,6 @@ struct SingleTrackQC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } @@ -506,13 +522,15 @@ struct SingleTrackQC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); 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); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -523,9 +541,9 @@ struct SingleTrackQC { weight = map_weight[track.globalIndex()]; } - float dca3D = dca3DinSigma(track); - float dcaXY = dcaXYinSigma(track); - float dcaZ = dcaZinSigma(track); + float dca3D = o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track); + float dcaXY = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(track); + float dcaZ = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(track); float phiPosition = track.phi() + std::asin(-0.30282 * track.sign() * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * track.pt())); o2::math_utils::bringTo02Pi(phiPosition); @@ -535,9 +553,9 @@ struct SingleTrackQC { 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"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/positive/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/positive/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/positive/hDCA3dRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaDca3D(track) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/positive/hNclsITS"), track.itsNCls()); fRegistry.fill(HIST("Track/positive/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); fRegistry.fill(HIST("Track/positive/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); @@ -554,6 +572,7 @@ struct SingleTrackQC { 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/hPIDForTracking"), track.pidForTracking()); fRegistry.fill(HIST("Track/positive/hProbElBDT"), track.tpcInnerParam(), track.probElBDT()); fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); @@ -574,9 +593,9 @@ struct SingleTrackQC { 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"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/negative/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/negative/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/negative/hDCA3dRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaDca3D(track) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/negative/hNclsITS"), track.itsNCls()); fRegistry.fill(HIST("Track/negative/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); fRegistry.fill(HIST("Track/negative/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); @@ -593,6 +612,7 @@ struct SingleTrackQC { 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/hPIDForTracking"), track.pidForTracking()); fRegistry.fill(HIST("Track/negative/hProbElBDT"), track.tpcInnerParam(), track.probElBDT()); fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); @@ -617,7 +637,7 @@ struct SingleTrackQC { if (cfgApplyWeightTTCA) { weight = map_weight[track.globalIndex()]; } - float dca_xy = fwdDcaXYinSigma(track); + float dca_xy = o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(track); float reldpt = (track.ptMatchedMCHMID() - track.pt()) / track.pt(); float deta = track.etaMatchedMCHMID() - track.eta(); @@ -631,20 +651,23 @@ struct SingleTrackQC { 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.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); + 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/hDCAxyRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/positive/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/positive/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/positive/hDCAx_Phi"), track.phi(), track.fwdDcaX()); + fRegistry.fill(HIST("Track/positive/hDCAy_Phi"), track.phi(), track.fwdDcaY()); fRegistry.fill(HIST("Track/positive/hNclsMCH"), track.nClusters()); fRegistry.fill(HIST("Track/positive/hNclsMFT"), track.nClustersMFT()); fRegistry.fill(HIST("Track/positive/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/positive/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); - fRegistry.fill(HIST("Track/positive/hChi2MFT"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); - fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/positive/hChi2_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); + fRegistry.fill(HIST("Track/positive/hChi2MFT_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); + fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMID_Pt"), track.pt(), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT_Pt"), track.pt(), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/positive/hMFTClusterMap"), track.mftClusterMap()); + fRegistry.fill(HIST("Track/positive/hdR_Chi2MatchMCHMFT"), track.chi2MatchMCHMFT(), std::sqrt(deta * deta + dphi * dphi)); } else { fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); fRegistry.fill(HIST("Track/negative/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); @@ -652,20 +675,23 @@ struct SingleTrackQC { 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.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); + 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/hDCAxyRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/negative/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/negative/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/negative/hDCAx_Phi"), track.phi(), track.fwdDcaX()); + fRegistry.fill(HIST("Track/negative/hDCAy_Phi"), track.phi(), track.fwdDcaY()); fRegistry.fill(HIST("Track/negative/hNclsMCH"), track.nClusters()); fRegistry.fill(HIST("Track/negative/hNclsMFT"), track.nClustersMFT()); fRegistry.fill(HIST("Track/negative/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/negative/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); - fRegistry.fill(HIST("Track/negative/hChi2MFT"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); - fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/negative/hChi2_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); + fRegistry.fill(HIST("Track/negative/hChi2MFT_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); + fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMID_Pt"), track.pt(), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT_Pt"), track.pt(), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/negative/hMFTClusterMap"), track.mftClusterMap()); + fRegistry.fill(HIST("Track/negative/hdR_Chi2MatchMCHMFT"), track.chi2MatchMCHMFT(), std::sqrt(deta * deta + dphi * dphi)); } } @@ -675,7 +701,7 @@ struct SingleTrackQC { for (const auto& collision : collisions) { initCCDB(collision); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -691,6 +717,23 @@ struct SingleTrackQC { if (!zorro.isSelected(collision.globalBC(), zorroGroup.bcMarginForSoftwareTrigger)) { // triggered event continue; } + + auto swt_bitset = zorro.getLastResult(); // this has to be called after zorro::isSelected + auto TOIcounter = zorro.getTOIcounters()[0]; // this has to be called after zorro::isSelected + auto ATcounter = zorro.getATcounters()[mToIidx]; // this has to be called after zorro::isSelected + + if (swt_bitset.test(mToIidx)) { + while (ATcounter > mATCounter) { + mATCounter++; + fRegistry.fill(HIST("Event/trigger/hAnalysedTrigger"), collision.runNumber()); + } + + while (TOIcounter > mTOICounter) { + fRegistry.fill(HIST("Event/trigger/hAnalysedToI"), collision.runNumber()); + mTOICounter++; // always incremented by 1 in zorro!! + } + // LOGF(info, "collision.globalIndex() = %d, collision.globalBC() = %llu, mTOICounter = %d, mATcounter = %d", collision.globalIndex(), collision.globalBC(), mTOICounter, mATCounter); + } } o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<1, -1>(&fRegistry, collision); @@ -717,9 +760,12 @@ struct SingleTrackQC { if (!cut.template IsSelectedTrack(track)) { continue; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } fillMuonInfo(track, collision); } // end of track loop @@ -736,7 +782,7 @@ struct SingleTrackQC { for (const auto& collision : collisions) { initCCDB(collision); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -773,9 +819,12 @@ struct SingleTrackQC { if (!cut.template IsSelectedTrack(track)) { continue; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } passed_trackIds.emplace_back(track.globalIndex()); } // end of track loop } @@ -811,21 +860,23 @@ struct SingleTrackQC { 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 && 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); + std::unordered_map map_best_match_globalmuon; - 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 && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && 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); + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::expressions::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; + o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, o2::aod::emprimaryelectron::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_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - using FilteredMyCollisions = soa::Filtered; + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_pt_track < o2::aod::fwdtrack::pt && o2::aod::fwdtrack::pt < dimuoncuts.cfg_max_pt_track && 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; + o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, o2::aod::emprimarymuon::isAssociatedToMPC == true); + + o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = o2::soa::Filtered; void processQC(FilteredMyCollisions const& collisions, Types const&... args) { @@ -837,13 +888,14 @@ struct SingleTrackQC { 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...)); + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, muons, perCollision_muon, fDimuonCut); } runQC(collisions, muons, perCollision_muon, fDimuonCut); } - map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQC, processQC, "run single track QC", true); @@ -857,41 +909,43 @@ struct SingleTrackQC { 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...)); + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(muons, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, muons, perCollision_muon, fDimuonCut); } runQC(collisions, muons, perCollision_muon, fDimuonCut); } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQC, processQC_TriggeredData, "run single track QC on triggered data", false); - void processNorm(aod::EMEventNormInfos const& collisions) + void processNorm(o2::aod::EMEventNormInfos const& collisions) { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -900,28 +954,28 @@ struct SingleTrackQC { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -935,25 +989,25 @@ struct SingleTrackQC { } PROCESS_SWITCH(SingleTrackQC, processNorm, "process normalization info", false); - void processBC(aod::EMBCs const& bcs) + void processBC(o2::aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 514e58694aa..f202e0b94e5 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -24,216 +24,231 @@ #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Tools/ML/MlResponse.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TString.h" - -#include +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include #include +#include #include #include -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; +#include -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyMCCollisions = soa::Join; +using MyMCCollisions = o2::soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = o2::soa::Join; using MyMCElectron = MyMCElectrons::iterator; -using FilteredMyMCElectrons = soa::Filtered; +using FilteredMyMCElectrons = o2::soa::Filtered; -using MyMCMuons = soa::Join; +using MyMCMuons = o2::soa::Join; using MyMCMuon = MyMCMuons::iterator; -using FilteredMyMCMuons = soa::Filtered; +using FilteredMyMCMuons = o2::soa::Filtered; -using MySmearedElectrons = soa::Join; +using MySmearedElectrons = o2::soa::Join; using MySmearedElectron = MySmearedElectrons::iterator; -using MySmearedMuons = soa::Join; +using MySmearedMuons = o2::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 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"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; - Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; - Configurable cfgFillQA{"cfgFillQA", false, "flag to fill QA histograms"}; - Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; - - 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"}; - ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {VARIABLE_WIDTH, 0.0, 10.0}, "DCA3d bins in sigma for output histograms"}; - ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAxy bins in sigma for output histograms"}; - ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, 10.0}, "DCAz bins in sigma for output histograms"}; + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + o2::framework::Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgFillQA{"cfgFillQA", false, "flag to fill QA histograms"}; + o2::framework::Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + o2::framework::Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + + o2::framework::ConfigurableAxis ConfPtlBins{"ConfPtlBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfEtaBins{"ConfEtaBins", {20, -1, 1}, "eta bins for output histograms"}; + o2::framework::ConfigurableAxis ConfPhiBins{"ConfPhiBins", {36, 0, 2 * M_PI}, "phi bins for output histograms"}; + o2::framework::ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {o2::framework::VARIABLE_WIDTH, 0.0, 10.0}, "DCA3d bins in sigma for output histograms"}; + o2::framework::ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {o2::framework::VARIABLE_WIDTH, -10.0, 10.0}, "DCAxy bins in sigma for output histograms"}; + o2::framework::ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {o2::framework::VARIABLE_WIDTH, -10.0, 10.0}, "DCAz bins in sigma for output histograms"}; EMEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", false, "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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", false, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + o2::framework::Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + o2::framework::Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + o2::framework::Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + o2::framework::Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::framework::Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + o2::framework::Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + o2::framework::Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + o2::framework::Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + o2::framework::Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + o2::framework::Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; } eventcuts; DielectronCut fDielectronCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "dielectroncut_group"; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; - Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; - 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "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_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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; - Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. - Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; - Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "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", -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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; - Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; - Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "min phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + o2::framework::Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 100, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; + o2::framework::Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; + o2::framework::Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + o2::framework::Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + o2::framework::Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + o2::framework::Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + o2::framework::Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif = 4, kPIDML = 5]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + // o2::framework::Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // o2::framework::Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + o2::framework::Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + o2::framework::Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks only for MC. switch ON only if needed."}; // configuration for PID ML - Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; - Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; - 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)"}; + o2::framework::Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + o2::framework::Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + o2::framework::Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20.f}, "Bin limits for ML application"}; + o2::framework::Configurable> cutsMl{"cutsMl", std::vector{0.98, 0.98, 0.9, 0.9, 0.95, 0.95, 0.8, 0.8}, "ML cuts per bin"}; + o2::framework::Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + o2::framework::Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + o2::framework::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"}; + o2::framework::Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + o2::framework::Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; } dielectroncuts; DimuonCut fDimuonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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+6, "max chi2/ndf"}; - Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; - Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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"}; - Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; - Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; - Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; - Configurable rejectWrongMatch{"rejectWrongMatch", false, "flag to reject wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable cfg_track_type{"cfg_track_type", 3, "muon track type [0: MFT-MCH-MID, 3: MCH-MID]"}; + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for single track"}; + o2::framework::Configurable cfg_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + o2::framework::Configurable cfg_min_eta_track{"cfg_min_eta_track", -4.0, "min eta for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", -2.5, "max eta for single track"}; + o2::framework::Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.f, "max phi for single track"}; + o2::framework::Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for single track"}; + o2::framework::Configurable cfg_min_ncluster_mft{"cfg_min_ncluster_mft", 5, "min ncluster MFT"}; + o2::framework::Configurable cfg_min_ncluster_mch{"cfg_min_ncluster_mch", 5, "min ncluster MCH"}; + o2::framework::Configurable cfg_max_chi2{"cfg_max_chi2", 1e+6, "max chi2/ndf"}; + o2::framework::Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // o2::framework::Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + o2::framework::Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2 for MCH-MID matching"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1e+10, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; + o2::framework::Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; + o2::framework::Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + o2::framework::Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + o2::framework::Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + o2::framework::Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + o2::framework::Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + o2::framework::Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + o2::framework::Service ccdb; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "mctrackcut_group"; - Configurable min_mcPt{"min_mcPt", 0.2, "min. MC pT for generated single lepton"}; - Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT single lepton"}; - Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta single lepton"}; - Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta single lepton"}; + o2::framework::Configurable min_mcPt{"min_mcPt", 0.2, "min. MC pT for generated single lepton"}; + o2::framework::Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT single lepton"}; + o2::framework::Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta single lepton"}; + o2::framework::Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta single lepton"}; } mctrackcuts; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; // 1 HistogramRegistry can keep up to 512 histograms + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::OutputObjHandlingPolicy::AnalysisObject, false, false}; // 1 o2::framework::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[8] = {"PromptLF/", "NonPromptLF/", "Photon/", "PromptJPsi/", "NonPromptJPsi/", "c2l/", "b2l/", "b2c2l/"}; @@ -243,22 +258,22 @@ struct SingleTrackQCMC { { // event info o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); - fRegistry.add("MCEvent/before/hZvtx", "mc vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); - fRegistry.add("MCEvent/before/hZvtx_rec", "rec. mc vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry.add("MCEvent/before/hZvtx", "mc vertex z; Z_{vtx} (cm)", o2::framework::kTH1F, {{100, -50, +50}}, false); + fRegistry.add("MCEvent/before/hZvtx_rec", "rec. mc vertex z; Z_{vtx} (cm)", o2::framework::kTH1F, {{100, -50, +50}}, false); fRegistry.addClone("MCEvent/before/", "MCEvent/after/"); 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_phiposition{36, 0.0, 2 * M_PI, "#varphi_{e}^{*} (rad.)"}; - const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; - const AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; - const AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; - const AxisSpec axis_dcaZ{ConfDCAZBins, "DCA_{e}^{Z} (#sigma)"}; + const o2::framework::AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; + const o2::framework::AxisSpec axis_eta{ConfEtaBins, "#eta_{e}"}; + const o2::framework::AxisSpec axis_phi{ConfPhiBins, "#varphi_{e} (rad.)"}; + const o2::framework::AxisSpec axis_phiposition{36, 0.0, 2 * M_PI, "#varphi_{e}^{*} (rad.)"}; + const o2::framework::AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; + const o2::framework::AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; + const o2::framework::AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; + const o2::framework::AxisSpec axis_dcaZ{ConfDCAZBins, "DCA_{e}^{Z} (#sigma)"}; // generated info - fRegistry.add("Generated/PromptLF/hs", "gen. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); + fRegistry.add("Generated/PromptLF/hs", "gen. single electron", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); fRegistry.addClone("Generated/PromptLF/", "Generated/NonPromptLF/"); fRegistry.addClone("Generated/PromptLF/", "Generated/PromptJPsi/"); fRegistry.addClone("Generated/PromptLF/", "Generated/NonPromptJPsi/"); @@ -267,32 +282,33 @@ struct SingleTrackQCMC { fRegistry.addClone("Generated/PromptLF/", "Generated/b2c2l/"); // track info - fRegistry.add("Track/PromptLF/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); + fRegistry.add("Track/PromptLF/positive/hs", "rec. single electron", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); if (fillGenValuesForRec) { - fRegistry.add("Track/PromptLF/positive/hsGenRec", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); + fRegistry.add("Track/PromptLF/positive/hsGenRec", "rec. single electron", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); } if (cfgFillQA) { - fRegistry.add("Track/PromptLF/positive/hPhiPosition", Form("phi position at r_{xy} = %3.2f m", dielectroncuts.cfgRefR.value), kTH1F, {axis_phiposition}, false); - fRegistry.add("Track/PromptLF/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{4000, -20, 20}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.f, 1.f}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/PromptLF/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/PromptLF/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);;TPC N_{cls}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); - fRegistry.add("Track/PromptLF/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);;TPC N_{CR}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/PromptLF/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/PromptLF/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/PromptLF/positive/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/PromptLF/positive/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/PromptLF/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{in} (GeV/c);(p_{pv} - p_{in})/p_{in}", kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);chi2", kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); - fRegistry.add("Track/PromptLF/positive/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/PromptLF/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/PromptLF/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/PromptLF/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.add("Track/PromptLF/positive/hPhiPosition", Form("phi position at r_{xy} = %3.2f m", dielectroncuts.cfgRefR.value), o2::framework::kTH1F, {axis_phiposition}, false); + fRegistry.add("Track/PromptLF/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", o2::framework::kTH1F, {{4000, -20, 20}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", o2::framework::kTH2F, {{200, -1.0f, 1.0f}, {200, -1.f, 1.f}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", o2::framework::kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/PromptLF/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/PromptLF/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);TPC N_{cls}", o2::framework::kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/PromptLF/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);TPC N_{CR}", o2::framework::kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2TPC", "chi2/number of TPC clusters;TPC #chi^{2}/N_{CR}", o2::framework::kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable;TPC N_{CR}/N_{cls}^{findable}", o2::framework::kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/PromptLF/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable;TPC N_{cls}/N_{cls}^{findable}", o2::framework::kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/PromptLF/positive/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", o2::framework::kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/PromptLF/positive/hNclsITS", "number of ITS clusters;ITS N_{cls}", o2::framework::kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2ITS", "chi2/number of ITS clusters;ITS #chi^{2}/N_{cls}", o2::framework::kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{in} (GeV/c);(p_{pv} - p_{in})/p_{in}", o2::framework::kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);TOF #chi^{2}", o2::framework::kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hITSClusterMap", "ITS cluster map", o2::framework::kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/PromptLF/positive/hPIDForTracking", "PID for trackng", o2::framework::kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", o2::framework::kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", o2::framework::kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", o2::framework::kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); } fRegistry.addClone("Track/PromptLF/positive/", "Track/PromptLF/negative/"); fRegistry.addClone("Track/PromptLF/", "Track/NonPromptLF/"); @@ -302,32 +318,32 @@ struct SingleTrackQCMC { fRegistry.addClone("Track/PromptLF/", "Track/c2l/"); fRegistry.addClone("Track/PromptLF/", "Track/b2l/"); fRegistry.addClone("Track/PromptLF/", "Track/b2c2l/"); - fRegistry.add("Track/Photon/positive/hProdVtx", "production vertex of e from #gamma;p_{T,e}^{rec} (GeV/c);r_{xy}^{gen} (cm);", kTH2F, {axis_pt, {100, 0, 100}}, false); + fRegistry.add("Track/Photon/positive/hProdVtx", "production vertex of e from #gamma;p_{T,e}^{rec} (GeV/c);r_{xy}^{gen} (cm);", o2::framework::kTH2F, {axis_pt, {100, 0, 100}}, false); fRegistry.addClone("Track/Photon/positive/hProdVtx", "Track/Photon/negative/hProdVtx"); 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/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/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, 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/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); - fRegistry.add("Track/PID/positive/hMeanClusterSizeITSib", "mean cluster size ITS inner barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); - fRegistry.add("Track/PID/positive/hMeanClusterSizeITSob", "mean cluster size ITS outer barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); + fRegistry.add("Track/PID/positive/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", o2::framework::kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/PID/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", o2::framework::kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); + fRegistry.add("Track/PID/positive/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", o2::framework::kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("Track/PID/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", o2::framework::kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); + fRegistry.add("Track/PID/positive/hMeanClusterSizeITSib", "mean cluster size ITS inner barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda)", o2::framework::kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); + fRegistry.add("Track/PID/positive/hMeanClusterSizeITSob", "mean cluster size ITS outer barrel;p_{pv} (GeV/c); on ITS #times cos(#lambda)", o2::framework::kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, 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{50, -6, -1, "#eta_{#mu}"}; - const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; - const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; - const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; + const o2::framework::AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; + const o2::framework::AxisSpec axis_eta{ConfEtaBins, "#eta_{#mu}"}; + const o2::framework::AxisSpec axis_phi{ConfPhiBins, "#varphi_{#mu} (rad.)"}; + const o2::framework::AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; + const o2::framework::AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; // generated info - fRegistry.add("Generated/PromptLF/hs", "gen. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); + fRegistry.add("Generated/PromptLF/hs", "gen. single muon", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); fRegistry.addClone("Generated/PromptLF/", "Generated/NonPromptLF/"); fRegistry.addClone("Generated/PromptLF/", "Generated/PromptJPsi/"); fRegistry.addClone("Generated/PromptLF/", "Generated/NonPromptJPsi/"); @@ -336,34 +352,37 @@ struct SingleTrackQCMC { fRegistry.addClone("Generated/PromptLF/", "Generated/b2c2l/"); // track info - fRegistry.add("Track/PromptLF/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + fRegistry.add("Track/PromptLF/positive/hs", "rec. single muon", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); if (fillGenValuesForRec) { - fRegistry.add("Track/PromptLF/positive/hsGenRec", "gen. info of rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + fRegistry.add("Track/PromptLF/positive/hsGenRec", "gen. info of rec. single muon", o2::framework::kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); } if (cfgFillQA) { - fRegistry.add("Track/PromptLF/positive/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", kTH2F, {{180, 0, 2.f * M_PI}, {100, -6, -1}}, false); - fRegistry.add("Track/PromptLF/positive/hdEtadPhi", "#Delta#eta vs. #Delta#varphi between MFT-MCH-MID and MCH-MID;#varphi_{sa} - #varphi_{gl} (rad.);#eta_{sa} - #eta_{gl}", kTH2F, {{90, -M_PI / 4, M_PI / 4}, {100, -0.5, +0.5}}, false); - fRegistry.add("Track/PromptLF/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -5, 5}}, false); - fRegistry.add("Track/PromptLF/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxy", "DCAxy;DCA_{xy} (cm)", kTH1F, {{100, 0.f, 1.0f}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxy2DinSigma", "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/PromptLF/positive/hDCAxRes_Pt", "DCA_{x} resolution vs. pT;p_{T} (GeV/c);DCA_{x} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAx_PosZ", "DCA_{x} vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, 10}, {200, -1, +1}}, false); - fRegistry.add("Track/PromptLF/positive/hDCAy_PosZ", "DCA_{y} vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, 10}, {200, -1, +1}}, false); - fRegistry.add("Track/PromptLF/positive/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); - fRegistry.add("Track/PromptLF/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); - fRegistry.add("Track/PromptLF/positive/hPDCA", "pDCA;R at absorber (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2MFT", "chi2MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/PromptLF/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/PromptLF/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); - fRegistry.add("Track/PromptLF/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/PromptLF/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/PromptLF/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.add("Track/PromptLF/positive/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", o2::framework::kTH2F, {{180, 0, 2.f * M_PI}, {80, -4, -2}}, false); + fRegistry.add("Track/PromptLF/positive/hdEtadPhi", "#Delta#eta vs. #Delta#varphi between MFT-MCH-MID and MCH-MID;#varphi_{sa} - #varphi_{gl} (rad.);#eta_{sa} - #eta_{gl}", o2::framework::kTH2F, {{90, -M_PI / 4, M_PI / 4}, {100, -0.5, +0.5}}, false); + fRegistry.add("Track/PromptLF/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", o2::framework::kTH1F, {{1000, -5, 5}}, false); + fRegistry.add("Track/PromptLF/positive/hTrackType", "track type", o2::framework::kTH1F, {{6, -0.5f, 5.5}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxy", "DCAxy;DCA_{xy} (cm)", o2::framework::kTH1F, {{100, 0.f, 1.0f}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", o2::framework::kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxy2DinSigma", "DCA x vs. y;DCA_{x} (#sigma);DCA_{y} (#sigma)", o2::framework::kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxRes_Pt", "DCA_{x} resolution vs. pT;p_{T} (GeV/c);DCA_{x} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAyRes_Pt", "DCA_{y} resolution vs. pT;p_{T} (GeV/c);DCA_{y} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", o2::framework::kTH2F, {{200, 0, 10}, {500, 0, 500}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAx_PosZ", "DCA_{x} vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", o2::framework::kTH2F, {{200, -10, 10}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAy_PosZ", "DCA_{y} vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", o2::framework::kTH2F, {{200, -10, 10}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", o2::framework::kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/PromptLF/positive/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", o2::framework::kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("Track/PromptLF/positive/hNclsMCH", "number of MCH clusters", o2::framework::kTH1F, {{21, -0.5, 20.5}}, false); + fRegistry.add("Track/PromptLF/positive/hNclsMFT", "number of MFT clusters", o2::framework::kTH1F, {{11, -0.5, 10.5}}, false); + fRegistry.add("Track/PromptLF/positive/hPDCA", "pDCA;R at absorber (cm);p #times DCA (GeV/c #upoint cm)", o2::framework::kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2_Pt", "chi2;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2MFT_Pt", "chi2MFT;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2MatchMCHMID_Pt", "chi2 match MCH-MID;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {200, 0.0f, 20}}, false); + fRegistry.add("Track/PromptLF/positive/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);chi2/ndf", o2::framework::kTH2F, {{100, 0, 10}, {100, 0.0f, 50}}, false); + fRegistry.add("Track/PromptLF/positive/hMFTClusterMap", "MFT cluster map", o2::framework::kTH1F, {{1024, -0.5, 1023.5}}, false); + fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPtOverPtGen", "muon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", o2::framework::kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaEta", "muon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", o2::framework::kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + fRegistry.add("Track/PromptLF/positive/hPtGen_DeltaPhi", "muon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", o2::framework::kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); + fRegistry.add("Track/PromptLF/positive/hdR_Chi2MatchMCHMFT", "dr vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;#DeltaR;", o2::framework::kTH2F, {{200, 0, 50}, {200, 0, 0.5}}, false); } fRegistry.addClone("Track/PromptLF/positive/", "Track/PromptLF/negative/"); fRegistry.addClone("Track/PromptLF/", "Track/NonPromptLF/"); @@ -378,7 +397,7 @@ struct SingleTrackQCMC { bool fillGenValuesForRec = false; int pdg_lepton = 0; - void init(InitContext&) + void init(o2::framework::InitContext&) { if (doprocessQCMC && doprocessQCMC_Smeared) { LOGF(fatal, "Cannot enable processQCMC and processQCMC_Smeared at the same time. Please choose one."); @@ -410,7 +429,7 @@ struct SingleTrackQCMC { fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); } if (doprocessBC) { - auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", kTH1D, {{6, -0.5f, 5.5f}}); + auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", o2::framework::kTH1D, {{6, -0.5f, 5.5f}}); hTVXCounter->GetXaxis()->SetBinLabel(1, "TVX"); hTVXCounter->GetXaxis()->SetBinLabel(2, "TVX && NoTFB"); hTVXCounter->GetXaxis()->SetBinLabel(3, "TVX && NoITSROFB"); @@ -487,7 +506,6 @@ struct SingleTrackQCMC { fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -510,7 +528,8 @@ struct SingleTrackQCMC { fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); - fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, 1e+10); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -534,31 +553,6 @@ struct SingleTrackQCMC { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; - // const std::vector labelsClasses = {"Background", "Signal"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = 0.; - // cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } @@ -575,13 +569,15 @@ struct SingleTrackQCMC { fDimuonCut.SetNClustersMCHMID(dimuoncuts.cfg_min_ncluster_mch, 20); fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); - fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); 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); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); } template @@ -630,9 +626,9 @@ struct SingleTrackQCMC { void fillElectronInfo(TTrack const& track) { auto mctrack = track.template emmcparticle_as(); - float dca3D = dca3DinSigma(track); - float dcaXY = dcaXYinSigma(track); - float dcaZ = dcaZinSigma(track); + float dca3D = o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track); + float dcaXY = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaXYinSigma(track); + float dcaZ = o2::aod::pwgem::dilepton::utils::emtrackutil::dcaZinSigma(track); float phiPosition = track.phi() + std::asin(-0.30282 * track.sign() * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * track.pt())); o2::math_utils::bringTo02Pi(phiPosition); @@ -656,9 +652,9 @@ struct SingleTrackQCMC { 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"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyRes_Pt"), track.pt(), std::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(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyRes_Pt"), track.pt(), std::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(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCA3dRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaDca3D(track) * 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_Pt"), track.pt(), track.tpcNClsFound()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); @@ -672,6 +668,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDeltaPin"), track.tpcInnerParam(), (track.p() - track.tpcInnerParam()) / track.tpcInnerParam()); } 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/hPIDForTracking"), track.pidForTracking()); 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()); @@ -701,9 +698,9 @@ struct SingleTrackQCMC { 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"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyRes_Pt"), track.pt(), std::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(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyRes_Pt"), track.pt(), std::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(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCA3dRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaDca3D(track) * 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_Pt"), track.pt(), track.tpcNClsFound()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); @@ -717,6 +714,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDeltaPin"), track.tpcInnerParam(), (track.p() - track.tpcInnerParam()) / track.tpcInnerParam()); } 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/hPIDForTracking"), track.pidForTracking()); 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()); @@ -740,7 +738,7 @@ struct SingleTrackQCMC { void fillMuonInfo(TTrack const& track, TCollision const& collision) { auto mctrack = track.template emmcparticle_as(); - float dca_xy = fwdDcaXYinSigma(track); + float dca_xy = o2::aod::pwgem::dilepton::utils::emtrackutil::fwdDcaXYinSigma(track); float deta = track.etaMatchedMCHMID() - track.eta(); float dphi = track.phiMatchedMCHMID() - track.phi(); o2::math_utils::bringToPMPi(dphi); @@ -763,20 +761,23 @@ struct SingleTrackQCMC { 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"), std::sqrt(std::pow(track.fwdDcaX(), 2) + std::pow(track.fwdDcaY(), 2))); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy2D"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy2DinSigma"), track.fwdDcaX() / std::sqrt(track.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy2DinSigma"), 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/hDCAxyRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAx_Phi"), track.phi(), track.fwdDcaX()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAy_Phi"), track.phi(), track.fwdDcaY()); 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.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MFT"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); - 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/hChi2_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MFT_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMID_Pt"), track.pt(), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT_Pt"), track.pt(), 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/hdR_Chi2MatchMCHMFT"), track.chi2MatchMCHMFT(), std::sqrt(deta * deta + dphi * dphi)); 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()); @@ -793,20 +794,23 @@ struct SingleTrackQCMC { 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"), std::sqrt(std::pow(track.fwdDcaX(), 2) + std::pow(track.fwdDcaY(), 2))); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy2D"), track.fwdDcaX(), track.fwdDcaY()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy2DinSigma"), track.fwdDcaX() / std::sqrt(track.cXXatDCA()), track.fwdDcaY() / std::sqrt(track.cYYatDCA())); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxRes_Pt"), track.pt(), std::sqrt(track.cXXatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAyRes_Pt"), track.pt(), std::sqrt(track.cYYatDCA()) * 1e+4); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyRes_Pt"), track.pt(), sigmaFwdDcaXY(track) * 1e+4); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy2DinSigma"), 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/hDCAxyRes_Pt"), track.pt(), o2::aod::pwgem::dilepton::utils::emtrackutil::sigmaFwdDcaXY(track) * 1e+4); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAx_PosZ"), collision.posZ(), track.fwdDcaX()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAy_PosZ"), collision.posZ(), track.fwdDcaY()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAx_Phi"), track.phi(), track.fwdDcaX()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAy_Phi"), track.phi(), track.fwdDcaY()); 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.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MFT"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); - 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/hChi2_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MFT_Pt"), track.pt(), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2MFT() / (2.f * track.nClustersMFT() - 5.f) : 0); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMID_Pt"), track.pt(), track.chi2MatchMCHMID()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT_Pt"), track.pt(), 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/hdR_Chi2MatchMCHMFT"), track.chi2MatchMCHMFT(), std::sqrt(deta * deta + dphi * dphi)); 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()); @@ -820,7 +824,7 @@ struct SingleTrackQCMC { for (const auto& collision : collisions) { initCCDB(collision); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -873,10 +877,16 @@ struct SingleTrackQCMC { if (!cut.template IsSelectedTrack(track)) { continue; } - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } - if (dimuoncuts.rejectWrongMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() != track.emmftmcparticleId()) { + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } + if (dimuoncuts.acceptOnlyCorrectMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() != track.emmftmcparticleId()) { + continue; + } + if (dimuoncuts.acceptOnlyWrongMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() == track.emmftmcparticleId()) { continue; } } @@ -886,21 +896,21 @@ struct SingleTrackQCMC { if (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator()) { if (pdg_mother == 111 || pdg_mother == 221 || pdg_mother == 331 || pdg_mother == 113 || pdg_mother == 223 || pdg_mother == 333) { - if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromCharm(mcmother, mcparticles) < 0 && o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) < 0) { fillTrackInfo<0, TMCParticles>(track, collision); // PromptLF } else { fillTrackInfo<1, TMCParticles>(track, collision); // NonPromptLF } } else if (pdg_mother == 443) { - if (IsFromBeauty(mcmother, mcparticles) > 0) { // b is found in full decay chain. + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { // b is found in full decay chain. fillTrackInfo<4, TMCParticles>(track, collision); } else { fillTrackInfo<3, TMCParticles>(track, collision); } - } else if (isWeakDecayFromBeautyHadron(mctrack, mcparticles)) { // hb->l is found in full decay chain. + } else if (o2::aod::pwgem::dilepton::utils::mcutil::isWeakDecayFromBeautyHadron(mctrack, mcparticles)) { // hb->l is found in full decay chain. fillTrackInfo<6, TMCParticles>(track, collision); - } else if (isWeakDecayFromCharmHadron(mctrack, mcparticles)) { // hc->l is found in full decay chain. - if (IsFromBeauty(mcmother, mcparticles) > 0) { + } else if (o2::aod::pwgem::dilepton::utils::mcutil::isWeakDecayFromCharmHadron(mctrack, mcparticles)) { // hc->l is found in full decay chain. + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { fillTrackInfo<7, TMCParticles>(track, collision); // hb->hc->l is fond. } else { fillTrackInfo<5, TMCParticles>(track, collision); // prompt hc->l is found. @@ -932,7 +942,7 @@ struct SingleTrackQCMC { auto collision = collisions.rawIteratorAt(mccollision.mpemeventId()); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } fRegistry.fill(HIST("MCEvent/before/hZvtx_rec"), mccollision.posZ()); @@ -986,21 +996,21 @@ struct SingleTrackQCMC { } if (pdg_mother == 111 || pdg_mother == 221 || pdg_mother == 331 || pdg_mother == 113 || pdg_mother == 223 || pdg_mother == 333) { - if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromCharm(mcmother, mcparticles) < 0 && o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) < 0) { fRegistry.fill(HIST("Generated/PromptLF/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); } else { fRegistry.fill(HIST("Generated/NonPromptLF/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. + if (o2::aod::pwgem::dilepton::utils::mcutil::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 (isWeakDecayFromBeautyHadron(lepton, mcparticles)) { // hb->l is found + } else if (o2::aod::pwgem::dilepton::utils::mcutil::isWeakDecayFromBeautyHadron(lepton, mcparticles)) { // hb->l is found fRegistry.fill(HIST("Generated/b2l/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); - } else if (isWeakDecayFromCharmHadron(lepton, mcparticles)) { // hc->l is found in full decay chain. - if (IsFromBeauty(mcmother, mcparticles) > 0) { + } else if (o2::aod::pwgem::dilepton::utils::mcutil::isWeakDecayFromCharmHadron(lepton, mcparticles)) { // hc->l is found in full decay chain. + if (o2::aod::pwgem::dilepton::utils::mcutil::IsFromBeauty(mcmother, mcparticles) > 0) { fRegistry.fill(HIST("Generated/b2c2l/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); // hb->hc->l is found in full decay chain. } else { fRegistry.fill(HIST("Generated/c2l/hs"), pt, eta, phi, -lepton.pdgCode() / pdg_lepton); // prompt hc->l is found in full decay chain. @@ -1020,7 +1030,7 @@ struct SingleTrackQCMC { for (const auto& collision : collisions) { initCCDB(collision); float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (centralities[cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -1067,10 +1077,12 @@ struct SingleTrackQCMC { if (!cut.template IsSelectedTrack(track)) { continue; } - - if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + if (!map_best_match_globalmuon[track.globalIndex()]) { continue; } + // if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { + // continue; + // } passed_trackIds.emplace_back(track.globalIndex()); } // end of track loop } @@ -1106,29 +1118,30 @@ struct SingleTrackQCMC { passed_trackIds.shrink_to_fit(); } - SliceCache cache; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = 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); + std::unordered_map map_best_match_globalmuon; + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::expressions::Filter trackFilter_electron = 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; + o2::framework::expressions::Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + o2::framework::expressions::Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), true, 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_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); + o2::framework::Preslice perCollision_muon = o2::aod::emprimarymuon::emeventId; + o2::framework::expressions::Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type && dimuoncuts.cfg_min_phi_track < o2::aod::fwdtrack::phi && o2::aod::fwdtrack::phi < dimuoncuts.cfg_max_phi_track; + o2::framework::expressions::Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), true, 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_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - using FilteredMyCollisions = soa::Filtered; + o2::framework::expressions::Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + o2::framework::expressions::Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = o2::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; + o2::framework::Partition electronsMC = nabs(o2::aod::mcparticle::pdgCode) == 11; // e+, e- + o2::framework::Partition muonsMC = nabs(o2::aod::mcparticle::pdgCode) == 13; // mu+, mu- + o2::framework::PresliceUnsorted perMcCollision = o2::aod::emmcparticle::emmceventId; - // PresliceUnsorted recColperMcCollision = aod::emmceventlabel::emmceventId; + // o2::framework::PresliceUnsorted recColperMcCollision = o2::aod::emmceventlabel::emmceventId; - void processQCMC(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, aod::EMMCParticles const& mcparticles, TLeptons const& tracks) + void processQCMC(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, o2::aod::EMMCParticles const& mcparticles, TLeptons const& tracks) { if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { if (cfgApplyWeightTTCA) { @@ -1137,6 +1150,7 @@ struct SingleTrackQCMC { 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) { + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(tracks, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles); } @@ -1144,11 +1158,12 @@ struct SingleTrackQCMC { runGenInfo(collisions, muonsMC, mccollisions, mcparticles); } map_weight.clear(); + map_best_match_globalmuon.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- + o2::framework::Partition electronsMC_smeared = nabs(o2::aod::mcparticle::pdgCode) == 11; // e+, e- + o2::framework::Partition muonsMC_smeared = nabs(o2::aod::mcparticle::pdgCode) == 13; // mu+, mu- void processQCMC_Smeared(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, TLeptons const& tracks, TSmearedMCParticles const& mcparticles_smeared) { @@ -1159,6 +1174,7 @@ struct SingleTrackQCMC { 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) { + map_best_match_globalmuon = o2::aod::pwgem::dilepton::utils::emtrackutil::findBestMatchMap(tracks, fDimuonCut); if (cfgApplyWeightTTCA) { fillTrackWeightMap(collisions, tracks, perCollision_muon, fDimuonCut, mccollisions, mcparticles_smeared); } @@ -1166,35 +1182,36 @@ struct SingleTrackQCMC { runGenInfo(collisions, muonsMC_smeared, mccollisions, mcparticles_smeared); } map_weight.clear(); + map_best_match_globalmuon.clear(); } PROCESS_SWITCH(SingleTrackQCMC, processQCMC_Smeared, "run single track QC MC with smearing", false); - void processNorm(aod::EMEventNormInfos const& collisions) + void processNorm(o2::aod::EMEventNormInfos const& collisions) { for (const auto& collision : collisions) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); } if (collision.sel8()) { @@ -1203,28 +1220,28 @@ struct SingleTrackQCMC { if (std::fabs(collision.posZ()) < 10.0) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); } if (!fEMEventCut.IsSelected(collision)) { @@ -1238,25 +1255,25 @@ struct SingleTrackQCMC { } PROCESS_SWITCH(SingleTrackQCMC, processNorm, "process normalization info", false); - void processBC(aod::EMBCs const& bcs) + void processBC(o2::aod::EMBCs const& bcs) { for (const auto& bc : bcs) { - if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); } - if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); } if (rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); } - if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder) && rctChecker(bc)) { + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); } } diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 1be31d372bf..7768db5327c 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -16,7 +16,6 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" #include @@ -66,15 +65,99 @@ const std::unordered_map aliasLabels = { }; } // namespace pwgem::dilepton::swt -DECLARE_SOA_TABLE(EMBCs, "AOD", "EMBC", //! bc information for normalization - o2::soa::Index<>, evsel::Selection, evsel::Rct); -using EMBC = EMBCs::iterator; +namespace emevsel +{ +// Event selection criteria. See O2Physics/Common/CCDB/EventSelectionParams.h +enum EventSelectionFlags { + kIsTriggerTVX = 0, // FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level + kNoITSROFrameBorder, // bunch crossing is far from ITS RO Frame border + kNoTimeFrameBorder, // bunch crossing is far from Time Frame borders + kNoSameBunchPileup, // reject collisions in case of pileup with another collision in the same foundBC + kIsGoodZvtxFT0vsPV, // small difference between z-vertex from PV and from FT0 + kIsVertexITSTPC, // at least one ITS-TPC track (reject vertices built from ITS-only tracks) + kIsVertexTOFmatched, // at least one of vertex contributors is matched to TOF + kIsVertexTRDmatched, // at least one of vertex contributors is matched to TRD + kNoCollInTimeRangeNarrow, // no other collisions in specified time range (narrower than Strict) + kNoCollInTimeRangeStrict, // no other collisions in specified time range + kNoCollInTimeRangeStandard, // no other collisions in specified time range with per-collision multiplicity above threshold + kNoCollInRofStrict, // no other collisions in this Readout Frame + kNoCollInRofStandard, // no other collisions in this Readout Frame with per-collision multiplicity above threshold + kNoHighMultCollInPrevRof, // veto an event if FT0C amplitude in previous ITS ROF is above threshold + kIsGoodITSLayer3, // number of inactive chips on ITS layer 3 is below maximum allowed value + kIsGoodITSLayer0123, // numbers of inactive chips on ITS layers 0-3 are below maximum allowed values + kIsGoodITSLayersAll, // numbers of inactive chips on all ITS layers are below maximum allowed values + kNsel // counter +}; + +DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 32); //! Bitmask of selection flags +DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint32_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::emevsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::emevsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::emevsel::kNoITSROFrameBorder)); }); + +template +uint32_t reduceSelectionBit(TBC const& bc) +{ + // input should be o2::aod::BcSels or o2::aod::EvSels. + uint32_t bitMap = 0; + if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + SETBIT(bitMap, o2::aod::emevsel::kIsTriggerTVX); + } + if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + SETBIT(bitMap, o2::aod::emevsel::kNoTimeFrameBorder); + } + if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + SETBIT(bitMap, o2::aod::emevsel::kNoITSROFrameBorder); + } + if (bc.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + SETBIT(bitMap, o2::aod::emevsel::kNoSameBunchPileup); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodZvtxFT0vsPV); + } + if (bc.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + SETBIT(bitMap, o2::aod::emevsel::kIsVertexITSTPC); + } + if (bc.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + SETBIT(bitMap, o2::aod::emevsel::kIsVertexTRDmatched); + } + if (bc.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + SETBIT(bitMap, o2::aod::emevsel::kIsVertexTOFmatched); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStandard); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStrict); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeNarrow); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStandard); + } + if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStrict); + } + if (bc.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + SETBIT(bitMap, o2::aod::emevsel::kNoHighMultCollInPrevRof); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer3); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer0123); + } + if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayersAll); + } + return bitMap; +} + +} // namespace emevsel 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_BITMAP_COLUMN(SWTAliasTmp, swtaliastmp, 16); //! Bitmask of fired trigger aliases (see above for definitions) to be join to o2::aod::Collisions for skimming +DECLARE_SOA_BITMAP_COLUMN(SWTAlias, swtalias, 16); //! Bitmask of fired trigger aliases (see above for definitions) to be join to o2::aod::EMEvents for analysis DECLARE_SOA_COLUMN(NInspectedTVX, nInspectedTVX, uint64_t); //! the number of inspected TVX bcs per run DECLARE_SOA_COLUMN(NScalars, nScalers, std::vector); //! the number of triggered bcs before down scaling per run DECLARE_SOA_COLUMN(NSelections, nSelections, std::vector); //! the number of triggered bcs after down scaling per run @@ -129,12 +212,21 @@ DECLARE_SOA_COLUMN(Q4yBTot, q4ybtot, float); //! 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); //! MB event selection info -DECLARE_SOA_COLUMN(IsEoI, isEoI, bool); //! lepton or photon exists in MB event (not for CEFP) -DECLARE_SOA_COLUMN(PosX, posX, float); //! only for treeCreatetorML.cxx -DECLARE_SOA_COLUMN(PosY, posY, float); //! only for treeCreatetorML.cxx -DECLARE_SOA_COLUMN(PosZint16, posZint16, int16_t); //! this is only to reduce data size -DECLARE_SOA_COLUMN(CentFT0Cuint16, centFT0Cuint16, uint16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(IsSelected, isSelected, bool); //! MB event selection info +DECLARE_SOA_COLUMN(IsEoI, isEoI, bool); //! lepton or photon exists in MB event (not for CEFP) +DECLARE_SOA_COLUMN(PosX, posX, float); //! only for treeCreatetorML.cxx +DECLARE_SOA_COLUMN(PosY, posY, float); //! only for treeCreatetorML.cxx +DECLARE_SOA_COLUMN(PosZint16, posZint16, int16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Cuint16, centFT0Cuint16, uint16_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(PosZint8, posZint8, int8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Cuint8, centFT0Cuint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentNTPVuint8, centNTPVuint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentNGlobaluint8, centNGlobaluint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Muint8, centFT0Muint8, uint8_t); //! this is only to reduce data size +DECLARE_SOA_COLUMN(CentFT0Auint8, centFT0Auint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentFT0Cuint8, centFT0Cuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNTPVuint8, centNTPVuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNGlobaluint8, centNGlobaluint8, uint8_t); //! this is only to reduce data size DECLARE_SOA_DYNAMIC_COLUMN(PosZ, posZ, [](int16_t posZint16) -> float { return (posZint16 < 0 ? std::nextafter(posZint16 * 0.01f, -std::numeric_limits::infinity()) : std::nextafter(posZint16 * 0.01f, std::numeric_limits::infinity())); }); //! poZ is multiplied by 100 in createEMEventDileton.cxx DECLARE_SOA_DYNAMIC_COLUMN(CentFT0C, centFT0C, [](uint16_t centuint16) -> float { return std::nextafter(centuint16 * 0.002f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 500 in createEMEventDilepton.cxx @@ -162,6 +254,47 @@ DECLARE_SOA_DYNAMIC_COLUMN(EP4BNeg, ep4bneg, [](float q4x, float q4y) -> float { DECLARE_SOA_DYNAMIC_COLUMN(EP4BTot, ep4btot, [](float q4x, float q4y) -> float { return std::atan2(q4y, q4x) / 4.0; }); } // namespace emevent +namespace emeventnorm +{ +DECLARE_SOA_DYNAMIC_COLUMN(PosZ, posZ, [](int8_t posZint8) -> float { return (posZint8 < 0 ? std::nextafter(posZint8 * 0.5f, -std::numeric_limits::infinity()) : std::nextafter(posZint8 * 0.5f, std::numeric_limits::infinity())); }); //! posZ is multiplied by 2 in createEMEventDileton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0M, centFT0M, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0A, centFT0A, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0C, centFT0C, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentNTPV, centNTPV, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +DECLARE_SOA_DYNAMIC_COLUMN(CentNGlobal, centNGlobal, [](uint8_t centuint8) -> float { return centuint8 < 100 ? std::nextafter(centuint8 * 0.01f, std::numeric_limits::infinity()) : std::nextafter(centuint8 - 110.f, std::numeric_limits::infinity()); }); //! centrality is multiplied by 100 in createEMEventDilepton.cxx +} // namespace emeventnorm + +// namespace emcent +// { +// DECLARE_SOA_COLUMN(CentFT0Muint8, centFT0Muint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentFT0Auint8, centFT0Auint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentFT0Cuint8, centFT0Cuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNTPVuint8, centNTPVuint8, uint8_t); //! this is only to reduce data size +// DECLARE_SOA_COLUMN(CentNGlobaluint8, centNGlobaluint8, uint8_t); //! this is only to reduce data size +// +// DECLARE_SOA_EXPRESSION_COLUMN(CentFT0A, centFT0A, float, 1.f * centFT0Auint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentFT0M, centFT0M, float, 1.f * centFT0Muint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentFT0C, centFT0C, float, 1.f * centFT0Cuint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentNTPV, centNTPV, float, 1.f * centNTPVuint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// DECLARE_SOA_EXPRESSION_COLUMN(CentNGlobal, centNGlobal, float, 1.f * centNGlobaluint8); // this must be inverse of calculation in createEMEventDilepton.cxx +// +// // DECLARE_SOA_EXPRESSION_COLUMN(CentFT0A, centFT0A, float, (centFT0Auint8 < 100) ? std::nextafter((1.f * centFT0Auint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centFT0Auint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentFT0M, centFT0M, float, (centFT0Muint8 < 100) ? std::nextafter((1.f * centFT0Muint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centFT0Muint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentFT0C, centFT0C, float, (centFT0Cuint8 < 100) ? std::nextafter((1.f * centFT0Cuint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centFT0Cuint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentNTPV, centNTPV, float, (centNTPVuint8 < 100) ? std::nextafter((1.f * centNTPVuint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centNTPVuint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// // DECLARE_SOA_EXPRESSION_COLUMN(CentNGlobal, centNGlobal, float, (centNGlobaluint8 < 100) ? std::nextafter((1.f * centNGlobaluint8) / 100.f, std::numeric_limits::infinity()) : std::nextafter((1.f * centNGlobaluint8) - 110.f, std::numeric_limits::infinity())); // this must be inverse of calculation in createEMEventDilepton.cxx +// +// } // namespace emcent + +DECLARE_SOA_TABLE(EMBCs_000, "AOD", "EMBC", //! bc information for normalization + o2::soa::Index<>, evsel::Selection, evsel::Rct); + +DECLARE_SOA_TABLE_VERSIONED(EMBCs_001, "AOD", "EMBC", 1, //! bc information for normalization + o2::soa::Index<>, emevsel::Selection, evsel::Rct); + +using EMBCs = EMBCs_001; +using EMBC = EMBCs::iterator; + DECLARE_SOA_TABLE_VERSIONED(EMEvents_001, "AOD", "EMEVENT", 1, //! 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, @@ -182,14 +315,19 @@ DECLARE_SOA_TABLE_VERSIONED(EMEvents_004, "AOD", "EMEVENT", 4, //! Main event collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emevent::Sel8); -using EMEvents = EMEvents_004; +DECLARE_SOA_TABLE_VERSIONED(EMEvents_005, "AOD", "EMEVENT", 5, //! Main event information table + o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, bc::GlobalBC, emevsel::Selection, evsel::Rct, timestamp::Timestamp, + collision::PosZ, + collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emevsel::Sel8); + +using EMEvents = EMEvents_005; using EMEvent = EMEvents::iterator; DECLARE_SOA_TABLE_VERSIONED(EMEventsAlias_000, "AOD", "EMEVENTALIAS", 0, evsel::Alias) //! joinable to EMEvents using EMEventsAlias = EMEventsAlias_000; using EMEventAlias = EMEventsAlias::iterator; -DECLARE_SOA_TABLE(EMEventsXY, "AOD", "EMEVENTXY", emevent::PosX, emevent::PosY); // joinable to EMEvents, only for treeCreatetorML.cxx +DECLARE_SOA_TABLE(EMEventsXY, "AOD", "EMEVENTXY", collision::PosX, collision::PosY); // joinable to EMEvents using EMEventXY = EMEventsXY::iterator; DECLARE_SOA_TABLE(EMEventsCov, "AOD", "EMEVENTCOV", //! joinable to EMEvents @@ -199,15 +337,38 @@ 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 +DECLARE_SOA_TABLE(EMEventsMult_000, "AOD", "EMEVENTMULT", //! event multiplicity table, joinable to EMEvents mult::MultFT0A, mult::MultFT0C, mult::MultNTracksPV, mult::MultNTracksPVeta1, mult::MultNTracksPVetaHalf, mult::IsInelGt0, mult::IsInelGt1, mult::MultFT0M); + +DECLARE_SOA_TABLE_VERSIONED(EMEventsMult_001, "AOD", "EMEVENTMULT", 1, //! event multiplicity table, joinable to EMEvents + mult::MultFT0A, mult::MultFT0C, mult::MultNTracksPV, /*mult::MultNTracksGlobal,*/ + mult::MultFT0M); + +using EMEventsMult = EMEventsMult_001; using EMEventMult = EMEventsMult::iterator; -DECLARE_SOA_TABLE(EMEventsCent, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents +DECLARE_SOA_TABLE(EMEventsCent_000, "AOD", "EMEVENTCENT", //! event centrality table, joinable to EMEvents cent::CentFT0M, cent::CentFT0A, cent::CentFT0C); + +DECLARE_SOA_TABLE_VERSIONED(EMEventsCent_001, "AOD", "EMEVENTCENT", 1, //! event centrality table stored in AO2D + cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentNTPV /*, cent::CentNGlobal*/); + +using EMEventsCent = EMEventsCent_001; using EMEventCent = EMEventsCent::iterator; +// DECLARE_SOA_TABLE_VERSIONED(EMEventsCentBase_001, "AOD", "EMEVENTCENT", 1, //! event centrality table stored in AO2D +// emcent::CentFT0Muint8, emcent::CentFT0Auint8, emcent::CentFT0Cuint8, emcent::CentNTPVuint8, emcent::CentNGlobaluint8); +// +// using EMEventsCentBase = EMEventsCentBase_001; +// using EMEventCentBase = EMEventsCentBase::iterator; +// +// // Extended table with expression columns that can be used for o2::framework::expressions::Filter. +// DECLARE_SOA_EXTENDED_TABLE_USER(EMEventsCent, EMEventsCentBase, "EMCENTEXT", +// emcent::CentFT0M, emcent::CentFT0A, emcent::CentFT0C, emcent::CentNTPV, emcent::CentNGlobal); +// +// using EMEventCent = EMEventsCent::iterator; + DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec_000, "AOD", "EMEVENTQVEC", 0, //! 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, @@ -255,6 +416,38 @@ DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec_001, "AOD", "EMEVENTQVEC", 1, //! Mai using EMEventsQvec = EMEventsQvec_001; using EMEventQvec = EMEventsQvec::iterator; +DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec2_000, "AOD", "EMEVENTQVEC2", 0, //! Main event information table + emevent::Q2xFT0M, emevent::Q2yFT0M, emevent::Q2xFT0A, emevent::Q2yFT0A, emevent::Q2xFT0C, emevent::Q2yFT0C, + emevent::Q2xFV0A, emevent::Q2yFV0A, + emevent::Q2xBPos, emevent::Q2yBPos, emevent::Q2xBNeg, emevent::Q2yBNeg, emevent::Q2xBTot, emevent::Q2yBTot, + // Dynamic columns + emevent::EP2FT0M, + emevent::EP2FT0A, + emevent::EP2FT0C, + emevent::EP2FV0A, + emevent::EP2BPos, + emevent::EP2BNeg, + emevent::EP2BTot); + +using EMEventsQvec2 = EMEventsQvec2_000; +using EMEventQvec2 = EMEventsQvec2::iterator; + +DECLARE_SOA_TABLE_VERSIONED(EMEventsQvec3_000, "AOD", "EMEVENTQVEC3", 0, //! Main event information table + emevent::Q3xFT0M, emevent::Q3yFT0M, emevent::Q3xFT0A, emevent::Q3yFT0A, emevent::Q3xFT0C, emevent::Q3yFT0C, + emevent::Q3xFV0A, emevent::Q3yFV0A, + emevent::Q3xBPos, emevent::Q3yBPos, emevent::Q3xBNeg, emevent::Q3yBNeg, emevent::Q3xBTot, emevent::Q3yBTot, + // Dynamic columns + emevent::EP3FT0M, + emevent::EP3FT0A, + emevent::EP3FT0C, + emevent::EP3FV0A, + emevent::EP3BPos, + emevent::EP3BNeg, + emevent::EP3BTot); + +using EMEventsQvec3 = EMEventsQvec3_000; +using EMEventQvec3 = EMEventsQvec3::iterator; + DECLARE_SOA_TABLE(EMSWTriggerBits, "AOD", "EMSWTBIT", emevent::SWTAlias, o2::soa::Marker<1>); //! joinable to EMEvents using EMSWTriggerBit = EMSWTriggerBits::iterator; @@ -267,7 +460,7 @@ using EMSWTriggerATCounter = EMSWTriggerATCounters::iterator; DECLARE_SOA_TABLE(EMSWTriggerTOICounters, "AOD", "EMSWTTOI", emevent::IsAnalyzedToI, o2::soa::Marker<1>); //! independent table. Don't join anything. using EMSWTriggerTOICounter = EMSWTriggerTOICounters::iterator; -DECLARE_SOA_TABLE(EMSWTriggerBitsTMP, "AOD", "EMSWTBITTMP", emevent::SWTAliasTmp, o2::soa::Marker<2>); //! joinable to aod::Collisions +DECLARE_SOA_TABLE(EMSWTriggerBitsTMP, "AOD", "EMSWTBITTMP", emevent::SWTAliasTmp, o2::soa::Marker<2>); //! joinable to o2::aod::Collisions using EMSWTriggerBitTMP = EMSWTriggerBitsTMP::iterator; DECLARE_SOA_TABLE(EMSWTriggerInfosTMP, "AOD", "EMSWTINFOTMP", bc::RunNumber, emevent::NInspectedTVX, emevent::NScalars, emevent::NSelections, o2::soa::Marker<2>); @@ -283,14 +476,14 @@ DECLARE_SOA_TABLE(EMEventsProperty, "AOD", "EMEVENTPROP", //! joinable to EMEven 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 +DECLARE_SOA_TABLE(EMEventsNee, "AOD", "EMEVENTNEE", emevent::NeeULS, emevent::NeeLSpp, emevent::NeeLSmm); // joinable to EMEvents or o2::aod::Collisions using EMEventNee = EMEventsNee::iterator; -DECLARE_SOA_TABLE(EMEvSels, "AOD", "EMEVSEL", //! joinable to aod::Collisions +DECLARE_SOA_TABLE(EMEvSels, "AOD", "EMEVSEL", //! joinable to o2::aod::Collisions emevent::IsSelected); using EMEvSel = EMEvSels::iterator; -DECLARE_SOA_TABLE(EMEoIs, "AOD", "EMEOI", //! joinable to aod::Collisions in createEMEventDilepton.cxx +DECLARE_SOA_TABLE(EMEoIs, "AOD", "EMEOI", //! joinable to o2::aod::Collisions in createEMEventDilepton.cxx emevent::IsEoI); using EMEoI = EMEoIs::iterator; @@ -301,7 +494,12 @@ DECLARE_SOA_TABLE_VERSIONED(EMEventNormInfos_000, "AOD", "EMEVENTNORMINFO", 0, / DECLARE_SOA_TABLE_VERSIONED(EMEventNormInfos_001, "AOD", "EMEVENTNORMINFO", 1, //! event information for normalization o2::soa::Index<>, evsel::Selection, evsel::Rct, emevent::PosZint16, emevent::CentFT0Cuint16, emevent::Sel8, emevent::PosZ, emevent::CentFT0C, o2::soa::Marker<1>); -using EMEventNormInfos = EMEventNormInfos_001; + +DECLARE_SOA_TABLE_VERSIONED(EMEventNormInfos_002, "AOD", "EMEVENTNORMINFO", 2, //! event information for normalization + emevsel::Selection, evsel::Rct, emevent::PosZint8, emevent::CentFT0Muint8, emevent::CentFT0Cuint8, emevent::CentNTPVuint8, /*emevent::CentNGlobaluint8,*/ + emevsel::Sel8, emeventnorm::PosZ, emeventnorm::CentFT0M, emeventnorm::CentFT0C, emeventnorm::CentNTPV, /*emeventnorm::CentNTPV,*/ o2::soa::Marker<1>); + +using EMEventNormInfos = EMEventNormInfos_002; using EMEventNormInfo = EMEventNormInfos::iterator; namespace emmcevent @@ -337,8 +535,8 @@ 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_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); }); @@ -439,11 +637,11 @@ 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 +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 +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; @@ -650,7 +848,7 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_004, "AOD", "EMPRIMARYEL", 4, //! o2::soa::Index<>, emprimaryelectron::CollisionId, emprimaryelectron::TrackId, emprimaryelectron::Sign, track::Pt, track::Eta, track::Phi, - track::DcaXY, track::DcaZ, aod::track::CYY, aod::track::CZY, aod::track::CZZ, + track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TPCChi2NCl, track::TPCInnerParam, track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, @@ -682,7 +880,7 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_005, "AOD", "EMPRIMARYEL", 5, //! o2::soa::Index<>, emprimaryelectron::CollisionId, emprimaryelectron::TrackId, emprimaryelectron::Sign, track::Pt, track::Eta, track::Phi, - track::DcaXY, track::DcaZ, aod::track::CYY, aod::track::CZY, aod::track::CZZ, + track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusPID, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TPCChi2NCl, track::TPCInnerParam, track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, @@ -711,45 +909,80 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_005, "AOD", "EMPRIMARYEL", 5, //! emprimaryelectron::MeanClusterSizeITSib, emprimaryelectron::MeanClusterSizeITSob); -using EMPrimaryElectrons = EMPrimaryElectrons_005; +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_006, "AOD", "EMPRIMARYEL", 6, //! + o2::soa::Index<>, emprimaryelectron::CollisionId, + emprimaryelectron::TrackId, emprimaryelectron::Sign, + track::Pt, track::Eta, track::Phi, + track::DcaXY, track::DcaZ, o2::aod::track::CYY, o2::aod::track::CZY, o2::aod::track::CZZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusPID, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, /*pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr,*/ + track::ITSClusterSizes, track::ITSChi2NCl, track::TOFChi2, track::DetectorMap, /*track::Tgl,*/ + emprimaryelectron::IsAssociatedToMPC, emprimaryelectron::IsAmbiguous, emprimaryelectron::ProbElBDT, track::Flags, + mcpidtpc::DeDxTunedMc, + + // dynamic column + track::TPCNClsFound, + track::TPCNClsPID, + 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, + track::PIDForTracking, // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + track::IsPVContributor, + + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz, + emprimaryelectron::Tgl, + emprimaryelectron::MeanClusterSizeITS, + emprimaryelectron::MeanClusterSizeITSib, + emprimaryelectron::MeanClusterSizeITSob); + +using EMPrimaryElectrons = EMPrimaryElectrons_006; // iterators using EMPrimaryElectron = EMPrimaryElectrons::iterator; DECLARE_SOA_TABLE(EMPrimaryElectronsCov_000, "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>); + o2::aod::track::CYY, + o2::aod::track::CZY, + o2::aod::track::CZZ, + o2::aod::track::CSnpY, + o2::aod::track::CSnpZ, + o2::aod::track::CSnpSnp, + o2::aod::track::CTglY, + o2::aod::track::CTglZ, + o2::aod::track::CTglSnp, + o2::aod::track::CTglTgl, + o2::aod::track::C1PtY, + o2::aod::track::C1PtZ, + o2::aod::track::C1PtSnp, + o2::aod::track::C1PtTgl, + o2::aod::track::C1Pt21Pt2, o2::soa::Marker<1>); DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronsCov_001, "AOD", "EMPRIMARYELCOV", 1, //! - aod::track::X, - aod::track::Alpha, - aod::track::Y, - aod::track::Z, - aod::track::Snp, - 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); // CYY, CZY, CZZ, Tgl are in the main electron table. + o2::aod::track::X, + o2::aod::track::Alpha, + o2::aod::track::Y, + o2::aod::track::Z, + o2::aod::track::Snp, + o2::aod::track::CSnpY, + o2::aod::track::CSnpZ, + o2::aod::track::CSnpSnp, + o2::aod::track::CTglY, + o2::aod::track::CTglZ, + o2::aod::track::CTglSnp, + o2::aod::track::CTglTgl, + o2::aod::track::C1PtY, + o2::aod::track::C1PtZ, + o2::aod::track::C1PtSnp, + o2::aod::track::C1PtTgl, + o2::aod::track::C1Pt21Pt2); // CYY, CZY, CZZ, Tgl are in the main electron table. using EMPrimaryElectronsCov = EMPrimaryElectronsCov_001; // iterators @@ -772,18 +1005,19 @@ DECLARE_SOA_TABLE(EMAmbiguousElectronSelfIds, "AOD", "EMAMBELSELFID", emprimarye // iterators using EMAmbiguousElectronSelfId = EMAmbiguousElectronSelfIds::iterator; -DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBPI0", emprimaryelectron::PrefilterBitDerived); // To be joined with EMPrimaryElectrons table at analysis level. +DECLARE_SOA_TABLE(EMPrimaryElectronsPrefilterBitDerived, "AOD", "PRMELPFBDERIVED", emprimaryelectron::PrefilterBitDerived); // To be joined with EMPrimaryElectrons table at analysis level. // iterators using EMPrimaryElectronPrefilterBitDerived = EMPrimaryElectronsPrefilterBitDerived::iterator; namespace emprimarymuon { -DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! -DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! -DECLARE_SOA_COLUMN(FwdTrackId, fwdtrackId, int); //! -DECLARE_SOA_COLUMN(MFTTrackId, mfttrackId, int); //! -DECLARE_SOA_COLUMN(MCHTrackId, mchtrackId, int); //! -DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(GlobalMuonsWithSameMFT, globalMuonsWithSameMFT); //! self indices to global muons that have the same MFTTrackId +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(FwdTrackId, fwdtrackId, int); //! +DECLARE_SOA_COLUMN(MFTTrackId, mfttrackId, int); //! +DECLARE_SOA_COLUMN(MCHTrackId, mchtrackId, int); //! +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(GlobalMuonsWithSameMCHMID, globalMuonsWithSameMCHMID); //! self indices to global muons that have the same MCHTrackId +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(GlobalMuonsWithSameMFT, globalMuonsWithSameMFT); //! self indices to global muons that have the same MFTTrackId DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousMuons, ambiguousMuons); DECLARE_SOA_COLUMN(CXXatDCA, cXXatDCA, float); //! DCAx resolution squared at DCA DECLARE_SOA_COLUMN(CYYatDCA, cYYatDCA, float); //! DCAy resolution squared at DCA @@ -795,11 +1029,13 @@ DECLARE_SOA_COLUMN(EtaMatchedMCHMIDatMP, etaMatchedMCHMIDatMP, float); //! eta o DECLARE_SOA_COLUMN(PhiMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, float); //! phi of MCH-MID track in MFT-MCH-MID track at matching plane DECLARE_SOA_COLUMN(EtaMatchedMFTatMP, etaMatchedMFTatMP, float); //! eta of MFT track in MFT-MCH-MID track at matching plane DECLARE_SOA_COLUMN(PhiMatchedMFTatMP, phiMatchedMFTatMP, float); //! phi of MFT track in MFT-MCH-MID track at matching plane - -DECLARE_SOA_COLUMN(IsAssociatedToMPC, isAssociatedToMPC, bool); //! is associated to most probable collision -DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); //! is ambiguous -DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! -DECLARE_SOA_COLUMN(Chi2MFT, chi2MFT, float); //! chi2 of MFT standalone track +DECLARE_SOA_COLUMN(IsAssociatedToMPC, isAssociatedToMPC, bool); //! is associated to most probable collision +DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); //! is ambiguous +DECLARE_SOA_COLUMN(IsCorrectMatchMFTMCH, isCorrectMatchMFTMCH, bool); //! is correct match between MFT and MCH, only for MC +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! +DECLARE_SOA_COLUMN(Chi2MFT, chi2MFT, float); //! chi2 of MFT standalone track +DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! +DECLARE_SOA_DYNAMIC_COLUMN(Tgl, tgl, [](float eta) -> float { return std::tan(o2::constants::math::PIHalf - 2 * std::atan(std::exp(-eta))); }); 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); }); @@ -865,32 +1101,60 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryMuons_001, "AOD", "EMPRIMARYMU", 1, //! // dynamic column emprimarymuon::Signed1Pt, emprimarymuon::NClustersMFT, + fwdtrack::IsCA, + emprimarymuon::MFTClusterMap, + emprimarymuon::P, + emprimarymuon::Px, + emprimarymuon::Py, + emprimarymuon::Pz); + +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryMuons_002, "AOD", "EMPRIMARYMU", 2, //! + o2::soa::Index<>, emprimarymuon::CollisionId, + emprimarymuon::FwdTrackId, emprimarymuon::MFTTrackId, emprimarymuon::MCHTrackId, fwdtrack::TrackType, + fwdtrack::Pt, fwdtrack::Eta, fwdtrack::Phi, emprimarymuon::Sign, + fwdtrack::FwdDcaX, fwdtrack::FwdDcaY, o2::aod::fwdtrack::CXX, o2::aod::fwdtrack::CYY, o2::aod::fwdtrack::CXY, + emprimarymuon::PtMatchedMCHMID, emprimarymuon::EtaMatchedMCHMID, emprimarymuon::PhiMatchedMCHMID, + // emprimarymuon::EtaMatchedMCHMIDatMP, emprimarymuon::PhiMatchedMCHMIDatMP, + // emprimarymuon::EtaMatchedMFTatMP, emprimarymuon::PhiMatchedMFTatMP, + + fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, + fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, + fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, + fwdtrack::MFTClusterSizesAndTrackFlags, emprimarymuon::Chi2MFT, emprimarymuon::IsAssociatedToMPC, emprimarymuon::IsAmbiguous, + + // dynamic column + emprimarymuon::Signed1Pt, + emprimarymuon::Tgl, + emprimarymuon::NClustersMFT, + fwdtrack::IsCA, emprimarymuon::MFTClusterMap, emprimarymuon::P, emprimarymuon::Px, emprimarymuon::Py, emprimarymuon::Pz); -using EMPrimaryMuons = EMPrimaryMuons_001; +using EMPrimaryMuons = EMPrimaryMuons_002; // 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); +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryMuonsCov_002, "AOD", "EMPRIMARYMUCOV", 2, //! + fwdtrack::X, fwdtrack::Y, fwdtrack::Z, // at PV. Signed1Pt, Tgl and Phi are in EMPrimaryMuons table. + // o2::aod::fwdtrack::CXX, + // o2::aod::fwdtrack::CXY, + // o2::aod::fwdtrack::CYY, + o2::aod::fwdtrack::CPhiX, + o2::aod::fwdtrack::CPhiY, + o2::aod::fwdtrack::CPhiPhi, + o2::aod::fwdtrack::CTglX, + o2::aod::fwdtrack::CTglY, + o2::aod::fwdtrack::CTglPhi, + o2::aod::fwdtrack::CTglTgl, + o2::aod::fwdtrack::C1PtX, + o2::aod::fwdtrack::C1PtY, + o2::aod::fwdtrack::C1PtPhi, + o2::aod::fwdtrack::C1PtTgl, + o2::aod::fwdtrack::C1Pt21Pt2); +using EMPrimaryMuonsCov = EMPrimaryMuonsCov_002; // iterators using EMPrimaryMuonCov = EMPrimaryMuonsCov::iterator; @@ -902,10 +1166,20 @@ DECLARE_SOA_TABLE(EMAmbiguousMuonSelfIds, "AOD", "EMAMBMUSELFID", emprimarymuon: // iterators using EMAmbiguousMuonSelfId = EMAmbiguousMuonSelfIds::iterator; -DECLARE_SOA_TABLE(EMGlobalMuonSelfIds, "AOD", "EMGLMUSELFID", emprimarymuon::GlobalMuonsWithSameMFTIds); // To be joined with EMPrimaryMuons table at analysis level. +DECLARE_SOA_TABLE(EMGlobalMuonSelfIds_000, "AOD", "EMGLMUSELFID", emprimarymuon::GlobalMuonsWithSameMFTIds); // To be joined with EMPrimaryMuons table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(EMGlobalMuonSelfIds_001, "AOD", "EMGLMUSELFID", 1, emprimarymuon::GlobalMuonsWithSameMCHMIDIds, emprimarymuon::GlobalMuonsWithSameMFTIds); // To be joined with EMPrimaryMuons table at analysis level. +using EMGlobalMuonSelfIds = EMGlobalMuonSelfIds_001; // iterators using EMGlobalMuonSelfId = EMGlobalMuonSelfIds::iterator; +DECLARE_SOA_TABLE(EMPrimaryMuonsPrefilterBitDerived, "AOD", "PRMMUPFBDERIVED", emprimarymuon::PrefilterBitDerived); // To be joined with EMPrimaryMuons table at analysis level. +// iterators +using EMPrimaryMuonPrefilterBitDerived = EMPrimaryMuonsPrefilterBitDerived::iterator; + +DECLARE_SOA_TABLE(EMPrimaryMuonsMatchMC, "AOD", "EMMUONMATCHMC", emprimarymuon::IsCorrectMatchMFTMCH); // To be joined with EMPrimaryMuons table at analysis level. only for MC. +// iterators +using EMPrimaryMuonMatchMC = EMPrimaryMuonsMatchMC::iterator; + namespace oldemprimarytrack { DECLARE_SOA_COLUMN(Sign, sign, int8_t); @@ -927,8 +1201,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, [](float signed1Pt) -> short { return (si DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_000, "AOD", "EMPRIMARYTRACK", 0, //! primary charged track table for 2PC o2::soa::Index<>, emprimarytrack::CollisionId, emprimarytrack::TrackId, oldemprimarytrack::Sign, track::Pt, track::Eta, track::Phi, emprimarytrack::TrackBit); -DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_001, "AOD", "EMPRIMARYTRACK", 1, //! primary charged track table for 2PC - o2::soa::Index<>, emprimarytrack::CollisionId, emprimarytrack::TrackId, +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_001, "AOD", "EMPRIMARYTRACK", 1, //! primary charged track table for 2PC + o2::soa::Index<>, /*emprimarytrack::CollisionId,*/ /*emprimarytrack::TrackId,*/ emprimarytrack::Signed1Pt, emprimarytrack::Eta, emprimarytrack::Phi, emprimarytrack::TrackBit, // dynamic column emprimarytrack::Sign, emprimarytrack::Pt); @@ -955,9 +1229,9 @@ DECLARE_SOA_TABLE_VERSIONED(EMThinEvents_000, "AOD", "EMTHINEVENT", 0, //! Thin using EMThinEvents = EMThinEvents_000; using EMThinEvent = EMThinEvents::iterator; -DECLARE_SOA_TABLE_VERSIONED(EMThinEventNormInfos_000, "AOD", "EMTHINEVENTNORM", 0, //! event information for normalization - o2::soa::Index<>, evsel::Selection, evsel::Rct, emevent::PosZint16, emevent::CentFT0Cuint16, - emevent::Sel8, emevent::PosZ, emevent::CentFT0C, o2::soa::Marker<2>); +DECLARE_SOA_TABLE_VERSIONED(EMThinEventNormInfos_000, "AOD", "EMTHINEVENTNORM", 0, //! event information for normalization + o2::soa::Index<>, emevsel::Selection, evsel::Rct, emevent::PosZint8, emevent::CentFT0Muint8, emevent::CentFT0Cuint8, emevent::CentNTPVuint8, /*emevent::CentNGlobaluint8,*/ + emevsel::Sel8, emeventnorm::PosZ, emeventnorm::CentFT0M, emeventnorm::CentFT0C, emeventnorm::CentNTPV, /*emeventnorm::CentNGlobal,*/ o2::soa::Marker<2>); using EMThinEventNormInfos = EMThinEventNormInfos_000; using EMThinEventNormInfo = EMThinEventNormInfos::iterator; diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 876a0bf3d4f..6d877783a38 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -9,16 +9,14 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" +#include -#include +#include #ifndef PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ #define PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ @@ -55,6 +53,10 @@ DECLARE_SOA_COLUMN(TPCNClsPID, tpcNClsPID, uint8_t); //! DECLARE_SOA_COLUMN(IsForValidation, isForValidation, bool); //! DECLARE_SOA_COLUMN(Sign, sign, short); //! DECLARE_SOA_COLUMN(P, p, float); //! +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! +DECLARE_SOA_COLUMN(EtaGen, etaGen, float); //! +DECLARE_SOA_COLUMN(PhiGen, phiGen, float); //! + // DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { int total_cluster_size = 0, nl = 0; @@ -114,6 +116,39 @@ using EMPIDPi = EMPIDsPi::iterator; using EMPIDKa = EMPIDsKa::iterator; using EMPIDPr = EMPIDsPr::iterator; +namespace emmlfwdtrack +{ +DECLARE_SOA_COLUMN(PtMatchedMCHMID, ptMatchedMCHMID, float); //! pt of MCH-MID track in MFT-MCH-MID track at PV +DECLARE_SOA_COLUMN(EtaMatchedMCHMID, etaMatchedMCHMID, float); //! eta of MCH-MID track in MFT-MCH-MID track at PV +DECLARE_SOA_COLUMN(PhiMatchedMCHMID, phiMatchedMCHMID, float); //! phi of MCH-MID track in MFT-MCH-MID track at PV +DECLARE_SOA_COLUMN(XMatchedMCHMIDatMP, xMatchedMCHMIDatMP, float); //! x of MCH-MID track in MFT-MCH-MID track at matching plane +DECLARE_SOA_COLUMN(YMatchedMCHMIDatMP, yMatchedMCHMIDatMP, float); //! y of MCH-MID track in MFT-MCH-MID track at matching plane +DECLARE_SOA_COLUMN(XMatchedMFTatMP, xMatchedMFTatMP, float); //! x of MFT track in MFT-MCH-MID track at matching plane +DECLARE_SOA_COLUMN(YMatchedMFTatMP, yMatchedMFTatMP, float); //! y of MFT track in MFT-MCH-MID track at matching plane +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! +DECLARE_SOA_COLUMN(Chi2MFT, chi2MFT, float); //! chi2 of MFT standalone track +DECLARE_SOA_COLUMN(NClustersMFT, nClustersMFT, uint8_t); //! +DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); //! +DECLARE_SOA_COLUMN(IsCorrectMatchMFTMCH, isCorrectMatchMFTMCH, bool); //! +} // namespace emmlfwdtrack + +DECLARE_SOA_TABLE_VERSIONED(EMFwdTracksForML_000, "AOD", "EMFWDTRKML", 0, //! + o2::soa::Index<>, collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emmltrack::HadronicRate, + fwdtrack::TrackType, fwdtrack::Pt, fwdtrack::Eta, fwdtrack::Phi, emmlfwdtrack::Sign, + fwdtrack::FwdDcaX, fwdtrack::FwdDcaY, + emmlfwdtrack::PtMatchedMCHMID, emmlfwdtrack::EtaMatchedMCHMID, emmlfwdtrack::PhiMatchedMCHMID, + emmlfwdtrack::XMatchedMCHMIDatMP, emmlfwdtrack::YMatchedMCHMIDatMP, + emmlfwdtrack::XMatchedMFTatMP, emmlfwdtrack::YMatchedMFTatMP, + fwdtrack::NClusters, fwdtrack::PDca, fwdtrack::RAtAbsorberEnd, + fwdtrack::Chi2, fwdtrack::Chi2MatchMCHMID, fwdtrack::Chi2MatchMCHMFT, + // fwdtrack::MCHBitMap, fwdtrack::MIDBitMap, fwdtrack::MIDBoards, + fwdtrack::MFTClusterSizesAndTrackFlags, emmlfwdtrack::Chi2MFT, emmlfwdtrack::NClustersMFT, mcparticle::PdgCode, emmlfwdtrack::IsPrimary, emmlfwdtrack::IsCorrectMatchMFTMCH, + emmltrack::PtGen, emmltrack::EtaGen, emmltrack::PhiGen); + +using EMFwdTracksForML = EMFwdTracksForML_000; +// iterators +using EMFwdTrackForML = EMFwdTracksForML::iterator; + } // namespace o2::aod #endif // PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index 8ddc8073a16..617d07a86d1 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -21,6 +21,11 @@ o2physics_add_dpl_workflow(tree-creator-electron-ml-dda PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tree-creator-muon-ml + SOURCES treeCreatorMuonML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::GlobalTracking + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(skimmer-primary-electron SOURCES skimmerPrimaryElectron.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore @@ -36,11 +41,21 @@ o2physics_add_dpl_workflow(skimmer-primary-muon PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(skimmer-primary-muon-qc + SOURCES skimmerPrimaryMuonQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(skimmer-primary-track SOURCES skimmerPrimaryTrack.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(skimmer-primary-mfttrack + SOURCES skimmerPrimaryMFTTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(create-emevent-dilepton SOURCES createEMEventDilepton.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -81,3 +96,17 @@ o2physics_add_dpl_workflow(qvector-dummy-otf PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(qvector2-dummy-otf + SOURCES qVector2DummyOTF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvector3-dummy-otf + SOURCES qVector3DummyOTF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(prefilter-dimuon + SOURCES prefilterDimuon.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt index eea03e885e6..d3b100b2a31 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/Converters/CMakeLists.txt @@ -25,6 +25,11 @@ o2physics_add_dpl_workflow(event-converter4 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(event-converter5 + SOURCES eventConverter5.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(electron-converter2 SOURCES electronConverter2.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -45,6 +50,11 @@ o2physics_add_dpl_workflow(electron-converter5 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(electron-converter6 + SOURCES electronConverter6.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(track-converter1 SOURCES trackConverter1.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -55,6 +65,16 @@ o2physics_add_dpl_workflow(muon-converter1 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(muon-converter2 + SOURCES muonConverter2.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(muon-selfid-converter1 + SOURCES muonSelfIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(mcparticle-converter1 SOURCES mcParticleConverter1.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -70,3 +90,33 @@ o2physics_add_dpl_workflow(event-norm-converter1 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(event-norm-converter2 + SOURCES eventNormConverter2.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-mult-converter1 + SOURCES eventMultConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(event-cent-converter1 + SOURCES eventCentConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvec2-converter0 + SOURCES qvec2Converter0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvec3-converter0 + SOURCES qvec3Converter0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(bc-converter1 + SOURCES bcConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx b/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx similarity index 52% rename from PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx rename to PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx index a3a7b548894..33aed751377 100644 --- a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/bcConverter1.cxx @@ -11,26 +11,33 @@ // // ======================== // -// This code loops over photons and makes pairs for neutral mesons analyses. +// This code runs loop over ULS ee pars for virtual photon QC. // Please write to: daiki.sekihata@cern.ch -#include "PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Common/Core/RecoDecay.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct bcConverter1 { + Produces bc_001; + + void process(aod::EMBCs_000 const& bcs) + { + for (const auto& bc : bcs) { + bc_001(o2::aod::emevsel::reduceSelectionBit(bc), bc.rct_raw()); + } // end of bc loop + } +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"diphoton-hadron-mpc-pcmdalitzee"}), - }; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"bc-converter1"})}; } diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx index 4a3af5c4313..86ed8dde8bd 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter2.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx index 87e49f9fb5e..c543037fbd1 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter3.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx index dcca6b5edc1..e9bc1fd78b2 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter4.cxx @@ -16,9 +16,11 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx index 60ea4f0db2e..5367e71f597 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter5.cxx @@ -16,9 +16,11 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx b/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx new file mode 100644 index 00000000000..7506fe10688 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/electronConverter6.cxx @@ -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. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct electronConverter6 { + Produces track_006; + + void process(aod::EMPrimaryElectrons_005 const& tracks) + { + for (const auto& track : tracks) { + track_006(track.collisionId(), + track.trackId(), + track.sign(), + track.pt(), + track.eta(), + track.phi(), + track.dcaXY(), + track.dcaZ(), + track.cYY(), + track.cZY(), + track.cZZ(), + track.tpcNClsFindable(), + track.tpcNClsFindableMinusFound(), + track.tpcNClsFindableMinusPID(), + track.tpcNClsFindableMinusCrossedRows(), + track.tpcNClsShared(), + track.tpcChi2NCl(), + track.tpcInnerParam(), + track.tpcSignal(), + track.tpcNSigmaEl(), + track.tpcNSigmaPi(), + track.tpcNSigmaKa(), + track.tpcNSigmaPr(), + track.beta(), + track.tofNSigmaEl(), + track.itsClusterSizes(), + track.itsChi2NCl(), + track.tofChi2(), + track.detectorMap(), + track.isAssociatedToMPC(), + track.isAmbiguous(), + track.probElBDT(), + 0, + track.mcTunedTPCSignal()); + } // end of track loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"electron-converter6"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx new file mode 100644 index 00000000000..ed040916f03 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventCentConverter1.cxx @@ -0,0 +1,47 @@ +// 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 "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventCentConverter1 { + Produces cent_001; + + void process(aod::EMEventsCent_000 const& collisions) + { + for (const auto& collision : collisions) { + cent_001( + collision.centFT0M(), + collision.centFT0A(), + collision.centFT0C(), + 105.f); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-cent-converter1"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx index 791876beb15..414241dea5c 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter2.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx index 77f3e070980..894d3d2984c 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter3.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx index 848c24a5c69..ff12b6a1405 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter4.cxx @@ -16,9 +16,10 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx new file mode 100644 index 00000000000..f4298c119c6 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventConverter5.cxx @@ -0,0 +1,114 @@ +// 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 "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventConverter5 { + Produces event_005; + + // template + // uint32_t reduceSelectionBit(TBC const& bc) + // { + // //input should be aod::BcSels or aod::EvSels. + // uint32_t bitMap = 0; + // if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsTriggerTVX); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoTimeFrameBorder); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoITSROFrameBorder); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoSameBunchPileup); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodZvtxFT0vsPV); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsVertexITSTPC); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsVertexTRDmatched); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsVertexTOFmatched); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStandard); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeStandard); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInTimeRangeNarrow); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStandard); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoCollInRofStrict); + // } + // if (bc.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // SETBIT(bitMap, o2::aod::emevsel::kNoHighMultCollInPrevRof); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer3); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayer0123); + // } + // if (bc.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // SETBIT(bitMap, o2::aod::emevsel::kIsGoodITSLayersAll); + // } + // return bitMap; + // } + + void process004to005(aod::EMEvents_004 const& collisions) + { + for (const auto& collision : collisions) { + event_005( + collision.globalIndex(), + collision.runNumber(), + collision.globalBC(), + o2::aod::emevsel::reduceSelectionBit(collision), + collision.rct_raw(), + collision.timestamp(), + collision.posZ(), + collision.numContrib(), + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange()); + } // end of collision loop + } + PROCESS_SWITCH(eventConverter5, process004to005, "convert from 004 into 005", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-converter5"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx new file mode 100644 index 00000000000..c1c8cd61a2a --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventMultConverter1.cxx @@ -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. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventMultConverter1 { + Produces mult_001; + + void process(aod::EMEventsMult_000 const& collisions) + { + for (const auto& collision : collisions) { + mult_001( + collision.multFT0A(), + collision.multFT0C(), + collision.multNTracksPV()); + } // end of mult row loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-mult-converter1"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx index 2965c836239..f51122a77a2 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter1.cxx @@ -16,9 +16,11 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include + +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx new file mode 100644 index 00000000000..79dc86b136c --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/eventNormConverter2.cxx @@ -0,0 +1,61 @@ +// 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 "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventNormConverter2 { + Produces event_002; + + void process(aod::EMEventNormInfos_001 const& collisions) + { + for (const auto& collision : collisions) { + + int8_t posZint8 = static_cast(collision.posZ() * 2.f); + if (posZint8 == 0) { + if (collision.posZ() < 0.f) { + posZint8 = -1; + } else { + posZint8 = +1; + } + } + + event_002( + o2::aod::emevsel::reduceSelectionBit(collision), + collision.rct_raw(), + posZint8, + 105 + 110, + collision.centFT0C() < 1.f ? static_cast(collision.centFT0C() * 100.f) : static_cast(collision.centFT0C() + 110.f), + 105 + 110); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"event-norm-converter2"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx index 5f219f459ca..92df1709c3d 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/mcParticleConverter1.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx index 527faf7c723..d0f5596f445 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/muonConverter1.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.cxx new file mode 100644 index 00000000000..7bc2a63916b --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/muonConverter2.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. +// +// ======================== +// +// This code produces muon table 001 from 000. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct muonConverter2 { + Produces muon_002; + + void process(aod::EMPrimaryMuons_001 const& muons) + { + for (const auto& muon : muons) { + muon_002( + muon.collisionId(), + muon.fwdtrackId(), muon.mfttrackId(), muon.mchtrackId(), muon.trackType(), + muon.pt(), muon.eta(), muon.phi(), muon.sign(), + muon.fwdDcaX(), muon.fwdDcaY(), muon.cXXatDCA(), muon.cYYatDCA(), muon.cXYatDCA(), + muon.ptMatchedMCHMID(), muon.etaMatchedMCHMID(), muon.phiMatchedMCHMID(), + muon.nClusters(), muon.pDca(), muon.rAtAbsorberEnd(), + muon.chi2(), muon.chi2MatchMCHMID(), muon.chi2MatchMCHMFT(), + muon.mchBitMap(), muon.midBitMap(), muon.midBoards(), + muon.mftClusterSizesAndTrackFlags(), muon.chi2MFT(), muon.isAssociatedToMPC(), muon.isAmbiguous()); + } // end of muon loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"muon-converter2"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx new file mode 100644 index 00000000000..031c853b12d --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/muonSelfIdConverter1.cxx @@ -0,0 +1,45 @@ +// 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 muon table 001 from 000. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct muonSelfIdConverter1 { + Produces muon_001; + + void process(aod::EMGlobalMuonSelfIds_000 const& muons) + { + for (const auto& muon : muons) { + muon_001(std::vector{}, muon.globalMuonsWithSameMFTIds()); + } // end of muon loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"muon-selfid-converter1"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx new file mode 100644 index 00000000000..340b74077c9 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/qvec2Converter0.cxx @@ -0,0 +1,50 @@ +// 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 converts q vector table into qvec2 table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct qvec2Converter0 { + Produces qvec2_000; + + void process(aod::EMEventsQvec_001 const& collisions) + { + for (const auto& collision : collisions) { + qvec2_000( + collision.q2xft0m(), collision.q2yft0m(), + collision.q2xft0a(), collision.q2yft0a(), + collision.q2xft0c(), collision.q2yft0c(), + collision.q2xfv0a(), collision.q2yfv0a(), + collision.q2xbpos(), collision.q2ybpos(), + collision.q2xbneg(), collision.q2ybneg(), + collision.q2xbtot(), collision.q2ybtot()); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvec2-converter0"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx b/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx new file mode 100644 index 00000000000..2775c7275f7 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/Converters/qvec3Converter0.cxx @@ -0,0 +1,50 @@ +// 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 converts q vector table into qvec3 table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct qvec3Converter0 { + Produces qvec3_000; + + void process(aod::EMEventsQvec_001 const& collisions) + { + for (const auto& collision : collisions) { + qvec3_000( + collision.q3xft0m(), collision.q3yft0m(), + collision.q3xft0a(), collision.q3yft0a(), + collision.q3xft0c(), collision.q3yft0c(), + collision.q3xfv0a(), collision.q3yfv0a(), + collision.q3xbpos(), collision.q3ybpos(), + collision.q3xbneg(), collision.q3ybneg(), + collision.q3xbtot(), collision.q3ybtot()); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvec3-converter0"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx b/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx index c6f7bfce634..bcdce816813 100644 --- a/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx +++ b/PWGEM/Dilepton/TableProducer/Converters/trackConverter1.cxx @@ -16,9 +16,9 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -32,12 +32,13 @@ struct trackConverter1 { void process(aod::EMPrimaryTracks_000 const& tracks) { for (const auto& track : tracks) { - track_001(track.collisionId(), - track.trackId(), - track.sign() / track.pt(), - track.eta(), - track.phi(), - track.trackBit()); + track_001( + // track.collisionId(), + // track.trackId(), + track.sign() / track.pt(), + track.eta(), + track.phi(), + track.trackBit()); } // end of track loop } }; diff --git a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx index 1b4044f4bf3..2e95f21f5c2 100644 --- a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx @@ -11,20 +11,26 @@ // // ======================== // -// This code produces reduced events for photon analyses. +// This code produces reduced mc info for dilepton analyses. // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "Common/Core/TableHelper.h" +#include "Common/DataModel/EventSelection.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include #include #include @@ -39,7 +45,6 @@ struct AssociateMCInfoDilepton { enum SubSystem { kElectron = 0x1, kFwdMuon = 0x2, - kPCM = 0x4, }; using MyCollisionsMC = soa::Join; @@ -51,15 +56,14 @@ struct AssociateMCInfoDilepton { Produces mceventlabels; Produces emmcparticles; Produces emmcgenvms; - Produces v0legmclabels; Produces emprimaryelectronmclabels; Produces emprimarymuonmclabels; Produces emmftmclabels; Produces emdummydata; Configurable n_dummy_loop{"n_dummy_loop", 0, "for loop runs over n times"}; - Configurable down_scaling_omega{"down_scaling_omega", 1.1, "down scaling factor to store omega"}; - Configurable down_scaling_phi{"down_scaling_phi", 1.1, "down scaling factor to store phi"}; + 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.5, "min eta to store generated information"}; // smearing is applied at analysis stage. set wider value. Configurable max_eta_gen_primary{"max_eta_gen_primary", +1.5, "max eta to store generated information"}; // smearing is applied at analysis stage. set wider value. Configurable min_eta_gen_primary_fwd{"min_eta_gen_primary_fwd", -6.0, "min eta to store generated information"}; // smearing is applied at analysis stage. set wider value. @@ -130,7 +134,6 @@ struct AssociateMCInfoDilepton { 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; @@ -140,7 +143,7 @@ struct AssociateMCInfoDilepton { 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, TMFTTracks const&, TPCMs const& v0photons, TPCMLegs const&, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) + void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const& mcCollisions, aod::McParticles const& mcTracks, TTracks const& o2tracks, TFwdTracks const& o2fwdtracks, TMFTTracks const&, TPCMs const&, TPCMLegs const&, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) { // temporary variables used for the indexing of the skimmed MC stack std::map fNewLabels; @@ -359,68 +362,68 @@ struct AssociateMCInfoDilepton { } // end of mc collision loop - if constexpr (static_cast(system & kPCM)) { - for (const 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 (const 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 & kPCM)) { + // for (const 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 (const 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()); @@ -683,23 +686,6 @@ struct AssociateMCInfoDilepton { skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, o2mfttracks, 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, MFTTracksMC const& o2mfttracks, 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, o2mfttracks, 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, 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, nullptr, v0photons, v0legs, nullptr, nullptr); - } - void processGenDummy(MyCollisionsMC const&) { for (int i = 0; i < n_dummy_loop; i++) { @@ -718,9 +704,6 @@ struct AssociateMCInfoDilepton { 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, processGenDummy, "produce dummy data", false); PROCESS_SWITCH(AssociateMCInfoDilepton, processDummy, "processDummy", true); }; diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx index 608fd8afaf9..f268cdb066f 100644 --- a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -14,7 +14,6 @@ /// \author Daiki Sekihata, daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" @@ -29,13 +28,12 @@ #include #include #include +#include #include #include -#include #include -#include #include #include @@ -46,28 +44,32 @@ using namespace o2::framework::expressions; using namespace o2::soa; using MyBCs = soa::Join; +// using MyMults = soa::Join; +using MyCents = soa::Join; // centrality table has dependency on multiplicity table. 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 = soa::Join; +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 MyCollisionsWithSWT_Cent = soa::Join; +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; +using MyCollisionsMC_Cent = soa::Join; +using MyCollisionsMC_Cent_Qvec = soa::Join; struct CreateEMEventDilepton { - Produces embc; + Produces embc; Produces event; Produces eventXY; // Produces eventcov; Produces event_mult; Produces event_cent; - Produces event_qvec; + // Produces event_qvec; + Produces event_qvec2; + Produces event_qvec3; Produces event_norm_info; enum class EMEventType : int { @@ -79,7 +81,7 @@ struct CreateEMEventDilepton { // // CCDB options // Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - HistogramRegistry registry{"registry"}; + HistogramRegistry registry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; void init(o2::framework::InitContext&) { // ccdb->setURL(ccdburl); @@ -87,9 +89,15 @@ struct CreateEMEventDilepton { // ccdb->setLocalObjectValidityChecking(); // ccdb->setFatalWhenNull(false); - auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{7, 0.5f, 7.5f}}); + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1D, {{7, 0.5f, 7.5f}}); hEventCounter->GetXaxis()->SetBinLabel(1, "all"); hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); + + registry.add("hCentFT0M", "hCentFT0M;centrality FT0M (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentFT0A", "hCentFT0A;centrality FT0A (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentFT0C", "hCentFT0C;centrality FT0C (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentNTPV", "hCentNTPV;centrality NTPV (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); + registry.add("hCentNGlobal", "hCentNGlobal;centrality NGlobal (%);Number of collisions", kTH1F, {{110, 0, 110}}, false); } ~CreateEMEventDilepton() {} @@ -102,7 +110,8 @@ struct CreateEMEventDilepton { { for (const auto& bc : bcs) { if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - embc(bc.selection_raw(), bc.rct_raw()); // TVX is fired. + embc(o2::aod::emevsel::reduceSelectionBit(bc), bc.rct_raw()); // TVX is fired. + // embc(bc.selection_raw(), bc.rct_raw()); // TVX is fired. } } // end of bc loop @@ -118,20 +127,24 @@ struct CreateEMEventDilepton { auto bc = collision.template bc_as(); // use this for Zorro if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - int16_t posZint16 = static_cast(collision.posZ() * 100.f); - if (posZint16 == 0) { + int8_t posZint8 = static_cast(collision.posZ() * 2.f); + if (posZint8 == 0) { if (collision.posZ() < 0.f) { - posZint16 = -1; + posZint8 = -1; } else { - posZint16 = +1; + posZint8 = +1; } } if constexpr (eventtype == EMEventType::kEvent) { - event_norm_info(collision.selection_raw(), collision.rct_raw(), posZint16, static_cast(105.f * 500.f)); + event_norm_info(o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), posZint8, static_cast(105.f + 110.f), static_cast(105.f + 110.f), static_cast(105.f + 110.f) /*, static_cast(105.f + 110.f)*/); } else if constexpr (eventtype == EMEventType::kEvent_Cent || eventtype == EMEventType::kEvent_Cent_Qvec) { - event_norm_info(collision.selection_raw(), collision.rct_raw(), posZint16, static_cast(collision.centFT0C() * 500.f)); + uint8_t centFT0Muint8 = collision.centFT0M() < 1.f ? static_cast(collision.centFT0M() * 100.f) : static_cast(collision.centFT0M() + 110.f); + uint8_t centFT0Cuint8 = collision.centFT0C() < 1.f ? static_cast(collision.centFT0C() * 100.f) : static_cast(collision.centFT0C() + 110.f); + uint8_t centNTPVuint8 = collision.centNTPV() < 1.f ? static_cast(collision.centNTPV() * 100.f) : static_cast(collision.centNTPV() + 110.f); + // uint8_t centNGlobaluint8 = collision.centNGlobal() < 1.f ? static_cast(collision.centNGlobal() * 100.f) : static_cast(collision.centNGlobal() + 110.f); + event_norm_info(o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), posZint8, centFT0Muint8, centFT0Cuint8, centNTPVuint8 /*, centNGlobaluint8*/); } else { - event_norm_info(collision.selection_raw(), collision.rct_raw(), posZint16, static_cast(105.f * 500.f)); + event_norm_info(o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), posZint8, static_cast(105.f + 110.f), static_cast(105.f + 110.f), static_cast(105.f + 110.f) /*, static_cast(105.f + 110.f)*/); } } @@ -147,14 +160,11 @@ struct CreateEMEventDilepton { if (collision.swtaliastmp_raw() == 0) { continue; } - // else { - // emswtbit(collision.swtaliastmp_raw()); - // } } registry.fill(HIST("hEventCounter"), 2); - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), + event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), o2::aod::emevsel::reduceSelectionBit(collision), collision.rct_raw(), bc.timestamp(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -162,20 +172,36 @@ struct CreateEMEventDilepton { // eventcov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); + event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV() /*, collision.multNTracksGlobal()*/); if constexpr (eventtype == EMEventType::kEvent) { - event_cent(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, 999.f, 999.f, 999.f, 999.f); + event_cent(105.f, 105.f, 105.f, 105.f); + event_qvec2(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_qvec3(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( + // 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, 999.f, 999.f, 999.f, 999.f); } else if constexpr (eventtype == EMEventType::kEvent_Cent) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); - 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, 999.f, 999.f, 999.f, 999.f); + registry.fill(HIST("hCentFT0M"), collision.centFT0M()); + registry.fill(HIST("hCentFT0A"), collision.centFT0A()); + registry.fill(HIST("hCentFT0C"), collision.centFT0C()); + registry.fill(HIST("hCentNTPV"), collision.centNTPV()); + registry.fill(HIST("hCentNGlobal"), collision.centFT0M()); + + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV() /*, collision.centNGlobal()*/); + event_qvec2(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_qvec3(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( + // 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, 999.f, 999.f, 999.f, 999.f); } else if constexpr (eventtype == EMEventType::kEvent_Cent_Qvec) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); + registry.fill(HIST("hCentFT0M"), collision.centFT0M()); + registry.fill(HIST("hCentFT0A"), collision.centFT0A()); + registry.fill(HIST("hCentFT0C"), collision.centFT0C()); + registry.fill(HIST("hCentNTPV"), collision.centNTPV()); + registry.fill(HIST("hCentNGlobal"), collision.centFT0M()); + + event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV() /*, collision.centNGlobal()*/); float q2xft0m = 999.f, q2yft0m = 999.f, q2xft0a = 999.f, q2yft0a = 999.f, q2xft0c = 999.f, q2yft0c = 999.f, q2xfv0a = 999.f, q2yfv0a = 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, q3xfv0a = 999.f, q3yfv0a = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; @@ -188,14 +214,16 @@ struct CreateEMEventDilepton { q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xfv0a = collision.qvecFV0AReVec()[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], q2yfv0a = collision.qvecFV0AImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; } - event_qvec( - q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xfv0a, q2yfv0a, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, - q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xfv0a, q3yfv0a, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); + // event_qvec(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xfv0a, q2yfv0a, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, + // q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xfv0a, q3yfv0a, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); + event_qvec2(q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xfv0a, q2yfv0a, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot); + event_qvec3(q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xfv0a, q3yfv0a, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); } else { - event_cent(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, 999.f, 999.f, 999.f, 999.f); + 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, 999.f, 999.f, 999.f, 999.f); + event_qvec2(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_qvec3(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 @@ -264,16 +292,14 @@ struct CreateEMEventDilepton { PROCESS_SWITCH(CreateEMEventDilepton, processDummy, "processDummy", true); }; struct AssociateDileptonToEMEvent { - Produces v0kfeventid; Produces prmeleventid; Produces prmmueventid; Produces prmtrackeventid; - Preslice perCollision_pcm = aod::v0photonkf::collisionId; PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; PresliceUnsorted perCollision_mu = aod::emprimarymuon::collisionId; - Preslice perCollision_track = aod::emprimarytrack::collisionId; - // Preslice perCollision_track = aod::track::collisionId; + // Preslice perCollision_track = aod::emprimarytrack::collisionId; + Preslice perCollision_track = aod::track::collisionId; void init(o2::framework::InitContext&) {} @@ -293,11 +319,6 @@ struct AssociateDileptonToEMEvent { // 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); @@ -308,15 +329,13 @@ struct AssociateDileptonToEMEvent { fillEventId(collisions, tracks, prmmueventid, perCollision_mu); } - void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) - // void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTrackEMEventIdsTMP const& tracks) + void processChargedTrack(aod::EMEvents const& collisions, soa::Join const& tracks) { fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); } void processDummy(aod::EMEvents const&) {} - PROCESS_SWITCH(AssociateDileptonToEMEvent, processPCM, "process indexing for PCM", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processElectron, "process indexing for electrons", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processFwdMuon, "process indexing for forward muons", false); PROCESS_SWITCH(AssociateDileptonToEMEvent, processChargedTrack, "process indexing for charged tracks", false); diff --git a/PWGEM/Dilepton/TableProducer/dielectronProducer.cxx b/PWGEM/Dilepton/TableProducer/dielectronProducer.cxx index ed9b5047afc..945ac2853c9 100644 --- a/PWGEM/Dilepton/TableProducer/dielectronProducer.cxx +++ b/PWGEM/Dilepton/TableProducer/dielectronProducer.cxx @@ -15,10 +15,12 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/Core/DileptonProducer.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/TableProducer/dimuonProducer.cxx b/PWGEM/Dilepton/TableProducer/dimuonProducer.cxx index 32cd1bafa72..ed298d39c39 100644 --- a/PWGEM/Dilepton/TableProducer/dimuonProducer.cxx +++ b/PWGEM/Dilepton/TableProducer/dimuonProducer.cxx @@ -15,10 +15,12 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/Core/DileptonProducer.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/TableProducer/eventSelection.cxx b/PWGEM/Dilepton/TableProducer/eventSelection.cxx index 89acb23000c..7c857fd6743 100644 --- a/PWGEM/Dilepton/TableProducer/eventSelection.cxx +++ b/PWGEM/Dilepton/TableProducer/eventSelection.cxx @@ -14,13 +14,24 @@ // This code produces event selection table for PWG-EM. // 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 "Common/CCDB/RCTSelectionFlags.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" +// +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/Dilepton/TableProducer/filterEoI.cxx b/PWGEM/Dilepton/TableProducer/filterEoI.cxx index 2300cbfb458..31bf18c40a3 100644 --- a/PWGEM/Dilepton/TableProducer/filterEoI.cxx +++ b/PWGEM/Dilepton/TableProducer/filterEoI.cxx @@ -17,15 +17,26 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "Common/Core/TableHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::common::core; struct filterEoI { enum SubSystem { diff --git a/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx b/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx new file mode 100644 index 00000000000..aa8ab7bdc85 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/prefilterDimuon.cxx @@ -0,0 +1,479 @@ +// 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 information on prefilter for dimuons. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include +#include +#include +#include + +#include + +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::pairutil; + +struct prefilterDimuon { + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; + + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; + + Produces pfb_derived; + + // // 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", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + } eventcuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "dimuoncut_group"; + + // for deta-dphi prefilter + Configurable cfg_apply_detadphi_uls{"cfg_apply_detadphi_uls", false, "flag to apply generator deta-dphi elliptic cut in ULS"}; // region to be rejected + Configurable cfg_apply_detadphi_ls{"cfg_apply_detadphi_ls", false, "flag to apply generator deta-dphi elliptic cut in LS"}; // region to be rejected + Configurable cfg_min_deta_ls{"cfg_min_deta_ls", 0.04, "deta between 2 electrons (elliptic cut)"}; // region to be rejected + Configurable cfg_min_dphi_ls{"cfg_min_dphi_ls", 0.2, "dphi between 2 electrons (elliptic cut)"}; // region to be rejected + Configurable cfg_min_deta_uls{"cfg_min_deta_uls", 0.04, "deta between 2 electrons (elliptic cut)"}; // region to be rejected + Configurable cfg_min_dphi_uls{"cfg_min_dphi_uls", 0.2, "dphi between 2 electrons (elliptic cut)"}; // region to be rejected + + 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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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+6, "max chi2/ndf"}; + Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + 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"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + } dimuoncuts; + + // o2::ccdb::CcdbApi ccdbApi; + // Service ccdb; + // int mRunNumber; + // float d_bz; + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + void init(InitContext& /*context*/) + { + DefineEMEventCut(); + DefineDimuonCut(); + 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)); + // } + // o2::base::Propagator::initFieldFromGRP(&grpmag); + // 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) { + // 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 = collision.runNumber(); + // } + + ~prefilterDimuon() {} + + void addhistograms() + { + const AxisSpec axis_mass{380, 0.2, 4, "m_{#mu#mu} (GeV/c^{2})"}; + const AxisSpec axis_pair_pt{100, 0, 10, "p_{T,#mu#mu} (GeV/c)"}; + + // for pair + fRegistry.add("Pair/before/uls/hMvsPt", "m_{#mu#mu} vs. p_{T,#mu#mu}", kTH2D, {axis_mass, axis_pair_pt}, true); + fRegistry.add("Pair/before/uls/hDeltaEtaDeltaPhi", "#Delta#eta-#Delta#varphi between 2 tracks;#Delta#varphi (rad.);#Delta#eta;", kTH2D, {{180, -M_PI, M_PI}, {400, -2, +2}}, true); + fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); + fRegistry.addClone("Pair/before/uls/", "Pair/before/lsmm/"); + fRegistry.addClone("Pair/before/", "Pair/after/"); + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // don't apply pair cut in prefilter! + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, dimuoncuts.cfg_max_pt_track); + 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, 20); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < dimuoncuts.cfg_border_pt_for_chi2mchmft ? dimuoncuts.cfg_max_matching_chi2_mftmch_lowPt : dimuoncuts.cfg_max_matching_chi2_mftmch_highPt); }); + 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); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(dimuoncuts.enableTTCA); + } + + std::unordered_map map_best_match_globalmuon; + std::unordered_map map_pfb; // map track.globalIndex -> prefilter bit + + SliceCache cache; + Preslice perCollision_track = aod::emprimarymuon::emeventId; + Partition posTracks = o2::aod::emprimarymuon::sign > int8_t(0); + Partition negTracks = o2::aod::emprimarymuon::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); + Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + void processPFB(FilteredMyCollisions const& collisions, MyTracks const& tracks) + { + map_best_match_globalmuon = findBestMatchMap(tracks, fDimuonCut); + + for (const auto& track : tracks) { + map_pfb[track.globalIndex()] = 0; + } // end of track loop + + for (const auto& collision : collisions) { + // initCCDB(collision); + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + bool is_cent_ok = true; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + is_cent_ok = false; + } + + 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); + + if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { + for (const auto& pos : posTracks_per_coll) { + map_pfb[pos.globalIndex()] = 0; + } + for (const auto& neg : negTracks_per_coll) { + map_pfb[neg.globalIndex()] = 0; + } + continue; + } + + // 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 (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (!fDimuonCut.IsSelectedTrack(pos) || !fDimuonCut.IsSelectedTrack(neg)) { + continue; + } + if (!map_best_match_globalmuon[pos.globalIndex()] || !map_best_match_globalmuon[neg.globalIndex()]) { + continue; + } + + // don't apply pair cut when you produce prefilter bit. + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/uls/hDeltaEtaDeltaPhi"), dphi, deta); + + if (dimuoncuts.cfg_apply_detadphi_uls && std::pow(deta / dimuoncuts.cfg_min_deta_uls, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi_uls, 2) < 1.f) { + map_pfb[pos.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + map_pfb[neg.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + } + } // end of ULS pairing + + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + if (!fDimuonCut.IsSelectedTrack(pos1) || !fDimuonCut.IsSelectedTrack(pos2)) { + continue; + } + if (!map_best_match_globalmuon[pos1.globalIndex()] || !map_best_match_globalmuon[pos2.globalIndex()]) { + continue; + } + // don't apply pair cut when you produce prefilter bit. + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/before/lspp/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/lspp/hDeltaEtaDeltaPhi"), dphi, deta); + + if (dimuoncuts.cfg_apply_detadphi_ls && std::pow(deta / dimuoncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi_ls, 2) < 1.f) { + map_pfb[pos1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + map_pfb[pos2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + } + } // end of LS++ pairing + + for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + if (!fDimuonCut.IsSelectedTrack(neg1) || !fDimuonCut.IsSelectedTrack(neg2)) { + continue; + } + if (!map_best_match_globalmuon[neg1.globalIndex()] || !map_best_match_globalmuon[neg2.globalIndex()]) { + continue; + } + // don't apply pair cut when you produce prefilter bit. + + ROOT::Math::PtEtaPhiMVector v1(neg1.pt(), neg1.eta(), neg1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg2.pt(), neg2.eta(), neg2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/before/lsmm/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/before/lsmm/hDeltaEtaDeltaPhi"), dphi, deta); + + if (dimuoncuts.cfg_apply_detadphi_ls && std::pow(deta / dimuoncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi_ls, 2) < 1.f) { + map_pfb[neg1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + map_pfb[neg2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + } + } // end of LS-- pairing + + } // end of collision loop + + for (const auto& track : tracks) { + // LOGF(info, "map_pfb[%d] = %d", track.globalIndex(), map_pfb[track.globalIndex()]); + pfb_derived(map_pfb[track.globalIndex()]); + } // end of track loop + + // check pfb. + for (const auto& collision : collisions) { + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + 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); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + if (!fDimuonCut.IsSelectedTrack(pos) || !fDimuonCut.IsSelectedTrack(neg)) { + continue; + } + if (!map_best_match_globalmuon[pos.globalIndex()] || !map_best_match_globalmuon[neg.globalIndex()]) { + continue; + } + if (map_pfb[pos.globalIndex()] != 0 || map_pfb[neg.globalIndex()] != 0) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos.sign() * v1.Pt() > neg.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/after/uls/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/uls/hDeltaEtaDeltaPhi"), dphi, deta); + } + + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + if (!fDimuonCut.IsSelectedTrack(pos1) || !fDimuonCut.IsSelectedTrack(pos2)) { + continue; + } + if (!map_best_match_globalmuon[pos1.globalIndex()] || !map_best_match_globalmuon[pos2.globalIndex()]) { + continue; + } + if (map_pfb[pos1.globalIndex()] != 0 || map_pfb[pos2.globalIndex()] != 0) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/after/lspp/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/lspp/hDeltaEtaDeltaPhi"), dphi, deta); + } + + for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + if (!fDimuonCut.IsSelectedTrack(neg1) || !fDimuonCut.IsSelectedTrack(neg2)) { + continue; + } + if (!map_best_match_globalmuon[neg1.globalIndex()] || !map_best_match_globalmuon[neg2.globalIndex()]) { + continue; + } + if (map_pfb[neg1.globalIndex()] != 0 || map_pfb[neg2.globalIndex()] != 0) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(neg1.pt(), neg1.eta(), neg1.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(neg2.pt(), neg2.eta(), neg2.phi(), o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float deta = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Eta() - v2.Eta() : v2.Eta() - v1.Eta(); + float dphi = neg1.sign() * v1.Pt() > neg2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); + o2::math_utils::bringToPMPi(dphi); + + fRegistry.fill(HIST("Pair/after/lsmm/hMvsPt"), v12.M(), v12.Pt()); + fRegistry.fill(HIST("Pair/after/lsmm/hDeltaEtaDeltaPhi"), dphi, deta); + } + + } // end of collision loop + map_pfb.clear(); + map_best_match_globalmuon.clear(); + } // end of process + PROCESS_SWITCH(prefilterDimuon, processPFB, "produce prefilter bit", false); + + void processDummy(MyTracks const& tracks) + { + for (int i = 0; i < tracks.size(); i++) { + pfb_derived(0); + } + } + PROCESS_SWITCH(prefilterDimuon, processDummy, "dummy", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"prefilter-dimuon"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx b/PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx new file mode 100644 index 00000000000..3c892ed0e1a --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/qVector2DummyOTF.cxx @@ -0,0 +1,47 @@ +// 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 on-the-fly dummy qvector table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct qVector2DummyOTF { + Produces event_qvec2; + + void init(InitContext&) {} + ~qVector2DummyOTF() {} + + void process(aod::EMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + event_qvec2(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 process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvector2-dummy-otf"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx b/PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx new file mode 100644 index 00000000000..67f6d5f810c --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/qVector3DummyOTF.cxx @@ -0,0 +1,47 @@ +// 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 on-the-fly dummy qvector table. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct qVector3DummyOTF { + Produces event_qvec3; + + void init(InitContext&) {} + ~qVector3DummyOTF() {} + + void process(aod::EMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + event_qvec3(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 process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvector3-dummy-otf"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/qVectorDummyOTF.cxx b/PWGEM/Dilepton/TableProducer/qVectorDummyOTF.cxx index 31dc12982d5..bfac1ecf3f3 100644 --- a/PWGEM/Dilepton/TableProducer/qVectorDummyOTF.cxx +++ b/PWGEM/Dilepton/TableProducer/qVectorDummyOTF.cxx @@ -16,9 +16,10 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx b/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx index d1836d97ad0..0dcca6318c1 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx @@ -16,15 +16,23 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Common/Core/TableHelper.h" #include "Common/Core/Zorro.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include #include #include diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index f28cf0b8755..e9fe1653412 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -19,52 +19,103 @@ #include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Tools/ML/MlResponse.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include +#include +#include +#include #include #include #include #include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; +using namespace o2::common::core; using MyCollisions = soa::Join; using MyCollisionsWithSWT = soa::Join; using MyTracks = soa::Join; + aod::pidTOFFullEl, /*aod::pidTOFFullMu,*/ aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFbeta, aod::TOFSignal, aod::TOFEvTime>; using MyTrack = MyTracks::iterator; using MyTracksMC = soa::Join; using MyTrackMC = MyTracksMC::iterator; +namespace o2::aod +{ +namespace pwgem::dilepton::recalculatedtofpid +{ +DECLARE_SOA_COLUMN(BetaRecalculated, betaRecalculated, float); +DECLARE_SOA_COLUMN(TOFNSigmaElRecalculated, tofNSigmaElRecalculated, float); +} // namespace pwgem::dilepton::recalculatedtofpid + +DECLARE_SOA_TABLE(EMTOFNSigmas, "AOD", "EMTOFNSIGMA", // make std::map in your tasks later. // Don't store this table in the derived data. + o2::aod::emprimaryelectron::CollisionId, o2::aod::emprimaryelectron::TrackId, + o2::aod::pwgem::dilepton::recalculatedtofpid::BetaRecalculated, o2::aod::pwgem::dilepton::recalculatedtofpid::TOFNSigmaElRecalculated); + +using EMTOFNSigma = EMTOFNSigmas::iterator; + +namespace pwgem::dilepton::mlpid +{ +DECLARE_SOA_COLUMN(BDTScore, bdtScore, float); +} // namespace pwgem::dilepton::mlpid + +DECLARE_SOA_TABLE(EMMLPIDs, "AOD", "EMMLPID", // make std::map in your tasks later. // Don't store this table in the derived data. + o2::aod::emprimaryelectron::CollisionId, o2::aod::emprimaryelectron::TrackId, o2::aod::pwgem::dilepton::mlpid::BDTScore); +using EMMLPID = EMMLPIDs::iterator; + +} // namespace o2::aod + struct skimmerPrimaryElectron { SliceCache cache; Preslice perCol = o2::aod::track::collisionId; Produces emprimaryelectrons; Produces emprimaryelectronscov; + Produces emtofs; + Produces emmlpids; + // 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"}; @@ -81,6 +132,8 @@ struct skimmerPrimaryElectron { Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; + Configurable minchi2tpc{"minchi2tpc", 0.0, "min. chi2/NclsTPC"}; + Configurable minchi2its{"minchi2its", 0.0, "min. chi2/NclsITS"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; Configurable minpt{"minpt", 0.15, "min pt for ITS-TPC track"}; @@ -101,20 +154,20 @@ struct skimmerPrimaryElectron { Configurable min_pin_for_pion_rejection{"min_pin_for_pion_rejection", 0.0, "pion rejection is applied above this pin"}; // this is used only in TOFreq Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; - Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; Configurable minNelectron{"minNelectron", 0, "min number of electron candidates per collision"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks only for MC. switch ON only if needed."}; + Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", false, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; // configuration for PID ML Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; - Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; - Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; - Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; - Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.95, 0.95, 0.7, 0.7, 0.8, 0.8, 0.7, 0.7}, "ML cuts per bin"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"tpcInnerParam", "tpcNClsFound", "tpcChi2NCl", "tpcNSigmaEl", "tofNSigmaEl", "meanClusterSizeITSobCos"}, "Names of ML model input features"}; + Configurable nameBinningFeature{"nameBinningFeature", "tpcInnerParam", "Names of ML model binning feature"}; 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)"}; @@ -131,8 +184,9 @@ struct skimmerPrimaryElectron { const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; o2::base::MatLayerCylSet* lut = nullptr; o2::ccdb::CcdbApi ccdbApi; + Service mTOFResponse; - void init(InitContext&) + void init(InitContext& initContext) { mRunNumber = 0; d_bz = 0; @@ -143,6 +197,9 @@ struct skimmerPrimaryElectron { ccdb->setFatalWhenNull(false); ccdbApi.init(ccdburl); + LOGF(info, "intializing TOFResponse"); + mTOFResponse->initSetup(ccdb, initContext); + 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, {{4000, -20, 20}}, false); @@ -171,9 +228,9 @@ struct skimmerPrimaryElectron { 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/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/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); fRegistry.add("Track/hMeanClusterSizeITSib", "mean cluster size ITSib;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); fRegistry.add("Track/hMeanClusterSizeITSob", "mean cluster size ITSob;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); @@ -204,6 +261,7 @@ struct skimmerPrimaryElectron { mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); mlResponseSingleTrack.init(enableOptimizations.value); + mlResponseSingleTrack.useReassociatedTOF(useTOFNSigmaDeltaBC.value); } // end of PID ML } @@ -279,7 +337,8 @@ struct skimmerPrimaryElectron { } } - if (requireTOF && !(track.hasTOF() && std::fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl)) { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + if (requireTOF && !(track.hasTOF() && std::fabs(tofNSigmaEl) < maxTOFNsigmaEl)) { return false; } @@ -287,7 +346,7 @@ struct skimmerPrimaryElectron { return false; } - if (track.itsChi2NCl() < 0.f || maxchi2its < track.itsChi2NCl()) { + if (track.itsChi2NCl() < minchi2its || maxchi2its < track.itsChi2NCl()) { return false; } if (track.itsNCls() < min_ncluster_its) { @@ -302,7 +361,7 @@ struct skimmerPrimaryElectron { } if (track.hasTPC()) { - if (track.tpcChi2NCl() < 0.f || maxchi2tpc < track.tpcChi2NCl()) { + if (track.tpcChi2NCl() < minchi2tpc || maxchi2tpc < track.tpcChi2NCl()) { return false; } @@ -356,10 +415,6 @@ struct skimmerPrimaryElectron { return false; } - if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && maxpt_itssa < trackParCov.getPt()) { - return false; - } - int total_cluster_size = 0, nl = 0; for (unsigned int layer = 0; layer < 7; layer++) { int cluster_size_per_layer = track.itsClsSizeInLayer(layer); @@ -377,38 +432,23 @@ struct skimmerPrimaryElectron { } template - bool isElectron(TCollision const& collision, TTrack const& track, float& probaEl) + void fillMLPIDTable(TCollision const& collision, TTrack const& track) { - probaEl = 1.f; - if (includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { - return true; - } - if (usePIDML) { - if (!isElectron_TOFif(track)) { - return false; - } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); auto trackParCov = getTrackParCov(track); trackParCov.setPID(o2::track::PID::Electron); - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); - if (!isPropOK) { - return false; - } - std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision); - float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision); - - // std::vector outputs = {}; - // bool isSelected = mlResponseSingleTrack.isSelectedMl(inputFeatures, binningFeature, outputs); // 0: hadron, 1:electron - // probaEl = outputs[1]; - // outputs.clear(); - // outputs.shrink_to_fit(); - // std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision); - // float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision); + // mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + // mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + // bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + // if (!isPropOK) { + // probaEl = 0.0; + // return false; + // } + std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; if (pbin < 0) { @@ -418,25 +458,67 @@ struct skimmerPrimaryElectron { } // LOGF(info, "track.tpcInnerParam() = %f (GeV/c), pbin = %d", track.tpcInnerParam(), pbin); - probaEl = mlResponseSingleTrack.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron - return probaEl > cutsMl.value[pbin]; - // return isSelected; + float probaEl = mlResponseSingleTrack.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron + mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; + emmlpids(collision.globalIndex(), track.globalIndex(), probaEl); + } else { + mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = 1.0; + emmlpids(collision.globalIndex(), track.globalIndex(), 1.0); + } + } + + template + bool isElectron(TCollision const& collision, TTrack const& track) + { + if (usePIDML) { + if (isElectron_TOFif(track, collision)) { + auto trackParCov = getTrackParCov(track); + // trackParCov.setPID(o2::track::PID::Electron); + // o2::dataformats::DCA mDcaInfoCov; + // mDcaInfoCov.set(999, 999, 999, 999, 999); + // mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + // mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + // bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + // if (!isPropOK) { + // probaEl = 0.0; + // return false; + // } + // std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + + int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(binsMl.value.size()) - 2; + } + // LOGF(info, "track.tpcInnerParam() = %f (GeV/c), pbin = %d", track.tpcInnerParam(), pbin); + + return mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] > cutsMl.value[pbin]; + } else { + return false; + } } else { - return isElectron_TPChadrej(track) || isElectron_TOFreq(track); + return isElectron_TPChadrej(track, collision) || isElectron_TOFreq(track, collision); } } - template - bool isElectron_TOFif(TTrack const& track) + template + bool isElectron_TOFif(TTrack const& track, TCollision const& collision) { + // collisionId must be collisionId after reassociation. + // track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCascade.globalBC()) + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; bool is_EL_TPC = minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl; - bool is_EL_TOF = track.hasTOF() ? (std::fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl) : true; // TOFif + bool is_EL_TOF = track.hasTOF() ? (std::fabs(tofNSigmaEl) < maxTOFNsigmaEl) : true; // TOFif return is_EL_TPC && is_EL_TOF; } - template - bool isElectron_TPChadrej(TTrack const& track) + template + bool isElectron_TPChadrej(TTrack const& track, TCollision const& collision) { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { return false; } @@ -449,23 +531,25 @@ struct skimmerPrimaryElectron { if (minTPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < maxTPCNsigmaPr) { return false; } - if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(track.tofNSigmaEl()))) { + if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(tofNSigmaEl))) { return false; } return true; } - template - bool isElectron_TOFreq(TTrack const& track) + template + bool isElectron_TOFreq(TTrack const& track, TCollision const& collision) { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi && (min_pin_for_pion_rejection < track.tpcInnerParam() && track.tpcInnerParam() < max_pin_for_pion_rejection)) { return false; } - return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && std::fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl; + return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && std::fabs(tofNSigmaEl) < maxTOFNsigmaEl; } template - void fillTrackTable(TCollision const& collision, TTrack const& track, const float probaEl) + 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()) { o2::dataformats::DCA mDcaInfoCov; @@ -486,6 +570,10 @@ struct skimmerPrimaryElectron { float phi_recalc = trackParCov.getPhi(); o2::math_utils::bringTo02Pi(phi_recalc); + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float beta = mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + float probaEl = mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())]; + bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); float mcTunedTPCSignal = 0.f; if constexpr (isMC) { @@ -498,10 +586,10 @@ struct skimmerPrimaryElectron { track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusPID(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(),*/ + beta, tofNSigmaEl, track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), - isAssociatedToMPC, false, probaEl, mcTunedTPCSignal); + isAssociatedToMPC, false, probaEl, track.flags(), mcTunedTPCSignal); emprimaryelectronscov( trackParCov.getX(), @@ -581,12 +669,12 @@ struct skimmerPrimaryElectron { 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"), trackParCov.getP(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFbeta"), trackParCov.getP(), beta); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), 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()); + // 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()); fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), trackParCov.getP(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))); fRegistry.fill(HIST("Track/hMeanClusterSizeITSib"), trackParCov.getP(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(trackParCov.getTgl()))); fRegistry.fill(HIST("Track/hMeanClusterSizeITSob"), trackParCov.getP(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(trackParCov.getTgl()))); @@ -595,23 +683,108 @@ struct skimmerPrimaryElectron { } } + template + void calculateTOFNSigmaWithReassociation(TCollisions const& collisions, TBCs const&, TTracks const& tracks, TTrackAssoc const& trackIndices) + { + if (useTOFNSigmaDeltaBC) { + if constexpr (withTTCA) { + for (const auto& collision : collisions) { + if (mapCollisionTime.find(collision.globalIndex()) == mapCollisionTime.end()) { + continue; + } + auto bcCollision = collision.template bc_as(); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + + if (track.hasTOF() && track.has_collision()) { // TTCA may use orphan tracks. + auto bcTrack = track.template collision_as().template bc_as(); + float tofNSigmaEl = mTOFResponse->nSigma(track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()), track.tofExpMom(), track.length(), track.p(), track.eta(), mapCollisionTime[collision.globalIndex()], mapCollisionTimeError[collision.globalIndex()]); + float beta = track.length() / (track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCollision.globalBC()) - mapCollisionTime[collision.globalIndex()]) / (TMath::C() * 1e+2 * 1e-12); + mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = tofNSigmaEl; + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = beta; + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } else { + mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } // end of track loop + } // end of collision loop + } else { + for (const auto& collision : collisions) { + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } // end of track loop + } // end of collision loop + } else { + if constexpr (withTTCA) { + for (const auto& collision : collisions) { + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } // end of track loop + } // end of collision loop + } else { + for (const auto& collision : collisions) { + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.hasITS() || !track.hasTPC()) { // apply only minimal cut + continue; + } + mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.tofNSigmaEl(); + mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())] = track.beta(); + emtofs(collision.globalIndex(), track.globalIndex(), mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + } + } // end of track loop + } // end of collision loop + } + } + Preslice trackIndicesPerCollision = aod::track_association::collisionId; std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::itsChi2NCl < maxchi2its && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Filter trackFilter = 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 MyFilteredTracks = soa::Filtered; - Partition posTracks = o2::aod::track::signed1Pt > 0.f; - Partition negTracks = o2::aod::track::signed1Pt < 0.f; + Partition posTracks = o2::aod::track::signed1Pt > 0.f; + Partition negTracks = o2::aod::track::signed1Pt < 0.f; - std::map, float> mapProbEl; // map pair(collisionId, trackId) -> probaEl std::unordered_multimap multiMapTracksPerCollision; // collisionId -> trackIds + std::unordered_map mapCollisionTime; + std::unordered_map mapCollisionTimeError; + + std::map, float> mapProbaEl; // map pair(collisionId, trackId) -> probaEl + std::map, float> mapTOFNsigmaReassociated; // map pair(collisionId, trackId) -> tof n sigma + std::map, float> mapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta + // ---------- for data ---------- - void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const& bcs, MyFilteredTracks const& tracks) { stored_trackIds.reserve(tracks.size()); + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, nullptr); + for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -622,14 +795,13 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -643,22 +815,39 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); } PROCESS_SWITCH(skimmerPrimaryElectron, processRec_SA, "process reconstructed info only", true); // standalone - void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) + void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const& bcs, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) { stored_trackIds.reserve(tracks.size() * 2); + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + // LOGF(info, "track.collisionId() = %d, track.tofEvTime() = %f, track.tofEvTimeErr() = %f", track.collisionId(), track.tofEvTime(), track.tofEvTimeErr()); + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices); + for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -671,14 +860,13 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -692,21 +880,28 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); } 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) + void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const& bcs, MyFilteredTracks const& tracks) { stored_trackIds.reserve(tracks.size()); + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, nullptr); for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); @@ -722,14 +917,13 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } @@ -744,21 +938,35 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); } 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) + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const& bcs, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) { stored_trackIds.reserve(tracks.size() * 2); + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + // LOGF(info, "track.collisionId() = %d, track.tofEvTime() = %f, track.tofEvTimeErr() = %f", track.collisionId(), track.tofEvTime(), track.tofEvTimeErr()); + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices); for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); @@ -775,14 +983,13 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -796,26 +1003,33 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); } 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, aod::McParticles const&) + 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& bcs, MyFilteredTracksMC const& tracks, aod::McParticles const&) { stored_trackIds.reserve(tracks.size()); + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, nullptr); for (const auto& collision : collisions) { if (!collision.has_mcCollision()) { @@ -830,14 +1044,13 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -851,21 +1064,35 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); } PROCESS_SWITCH(skimmerPrimaryElectron, 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, aod::McParticles const&) + void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const& bcs, MyTracksMC const& tracks, aod::TrackAssoc const& trackIndices, aod::McParticles const&) { stored_trackIds.reserve(tracks.size() * 2); + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + // LOGF(info, "track.collisionId() = %d, track.tofEvTime() = %f, track.tofEvTimeErr() = %f", track.collisionId(), track.tofEvTime(), track.tofEvTimeErr()); + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } + calculateTOFNSigmaWithReassociation(collisions, bcs, tracks, trackIndices); for (const auto& collision : collisions) { if (!collision.has_mcCollision()) { @@ -882,14 +1109,13 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { auto track = trackId.template track_as(); - float probaEl = 1.0; + fillMLPIDTable(collision, track); if (!checkTrack(collision, track)) { continue; } - if (!isElectron(collision, track, probaEl)) { + if (!isElectron(collision, track)) { continue; } - mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())] = probaEl; multiMapTracksPerCollision.insert(std::make_pair(collision.globalIndex(), track.globalIndex())); } } // end of collision loop @@ -903,15 +1129,19 @@ struct skimmerPrimaryElectron { auto range_electrons = multiMapTracksPerCollision.equal_range(collision.globalIndex()); for (auto it = range_electrons.first; it != range_electrons.second; it++) { auto track = tracks.rawIteratorAt(it->second); - fillTrackTable(collision, track, mapProbEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fillTrackTable(collision, track); } } } // end of collision loop - mapProbEl.clear(); + mapProbaEl.clear(); multiMapTracksPerCollision.clear(); stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); } PROCESS_SWITCH(skimmerPrimaryElectron, processMC_TTCA, "process reconstructed info only", false); // with TTCA }; @@ -937,23 +1167,38 @@ struct prefilterPrimaryElectron { Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable max_dcaxy{"max_dcaxy", 1.0, "DCAxy To PV for loose track sample"}; Configurable max_dcaz{"max_dcaz", 1.0, "DCAz To PV for loose track sample"}; - Configurable minpt{"minpt", 0.1, "min pt for ITS-TPC track"}; - Configurable maxeta{"maxeta", 1.2, "eta acceptance for loose track sample"}; + Configurable minpt{"minpt", 0.01, "min pt for ITS-TPC track"}; + Configurable maxeta{"maxeta", 0.9, "eta acceptance for loose track sample"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; - Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + Configurable mincrossedrows{"mincrossedrows", 40, "min crossed rows"}; + Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 0.7f, "max fraction of shared clusters in TPC"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 36.0, "max chi2/NclsITS"}; - Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; + Configurable min_ncluster_its{"min_ncluster_its", 2, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; + Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 3.0, "max. TOF n sigma for electron inclusion"}; // TOFif + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 0, "max. TPC n sigma for pion exclusion"}; + Configurable minTPCNsigmaPi{"minTPCNsigmaPi", 0, "min. TPC n sigma for pion exclusion"}; + Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", 0, "max. TPC n sigma for kaon exclusion"}; + Configurable minTPCNsigmaKa{"minTPCNsigmaKa", 0, "min. TPC n sigma for kaon exclusion"}; + Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", 0, "max. TPC n sigma for proton exclusion"}; + Configurable minTPCNsigmaPr{"minTPCNsigmaPr", 0, "min. TPC n sigma for proton exclusion"}; + Configurable min_pin_for_pion_rejection{"min_pin_for_pion_rejection", 0.0, "pion rejection is applied above this pin"}; // this is used only in TOFreq + Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; + // Configurable useTOFNSigmaDeltaBC{"useTOFNSigmaDeltaBC", false, "Flag to shift delta BC for TOF n sigma (only with TTCA)"}; + + Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; + Configurable> binsMl{"binsMl", std::vector{0.1, 0.15, 0.2, 0.25, 0.4, 0.8, 1.6, 2.0, 20}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.85, 0.85, 0.6, 0.6, 0.7, 0.7, 0.6, 0.6}, "ML cuts per bin"}; + Configurable nameBinningFeature{"nameBinningFeature", "tpcInnerParam", "Names of ML model binning feature"}; + o2::analysis::MlResponseO2Track mlResponseSingleTrack; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; const std::vector max_mee_vec{0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14}; @@ -966,7 +1211,7 @@ struct prefilterPrimaryElectron { const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; o2::base::MatLayerCylSet* lut = nullptr; - void init(InitContext&) + void init(InitContext& initContext) { mRunNumber = 0; d_bz = 0; @@ -979,13 +1224,52 @@ struct prefilterPrimaryElectron { if (!doprocessDummy && fillQAHistogram) { addHistograms(); } + + // BDT files are inherited from skimmer-primary-electron task above. + getTaskOptionValue(initContext, "skimmer-primary-electron", "usePIDML", usePIDML.value, true); + // getTaskOptionValue(initContext, "skimmer-primary-electron", "useTOFNSigmaDeltaBC", useTOFNSigmaDeltaBC.value, true); + + if (usePIDML) { + getTaskOptionValue(initContext, "skimmer-primary-electron", "binsMl.value", binsMl.value, true); + // getTaskOptionValue(initContext, "skimmer-primary-electron", "cutsMl.value", cutsMl.value, true); + getTaskOptionValue(initContext, "skimmer-primary-electron", "nameBinningFeature", nameBinningFeature.value, true); + } + + if (usePIDML) { + static constexpr int nClassesMl = 2; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; + const uint32_t nBinsMl = binsMl.value.size() - 1; + const std::vector labelsBins(nBinsMl, "bin"); + double cutsMlArr[nBinsMl][nClassesMl]; + for (uint32_t i = 0; i < nBinsMl; i++) { + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = cutsMl.value[i]; + } + o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + mlResponseSingleTrack.configure(binsMl.value, cutsMl, cutDirMl, nClassesMl); + + // if (loadModelsFromCCDB) { + // ccdbApi.init(ccdburl); + // mlResponseSingleTrack.setModelPathsCCDB(onnxFileNames.value, ccdbApi, onnxPathsCCDB.value, timestampCCDB.value); + // } else { + // mlResponseSingleTrack.setModelPathsLocal(onnxFileNames.value); + // } + // mlResponseSingleTrack.cacheInputFeaturesIndices(namesInputFeatures); + mlResponseSingleTrack.cacheBinningIndex(nameBinningFeature); + // mlResponseSingleTrack.init(enableOptimizations.value); + // mlResponseSingleTrack.useReassociatedTOF(useTOFNSigmaDeltaBC.value); + } // end of PID ML } void addHistograms() { fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {80, -2.0f, 2.0f}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {40, -1.0f, 1.0f}}, false); fRegistry.add("Track/hTPCNsigmaEl", "loose track TPC PID", kTH2F, {{1000, 0.f, 10}, {100, -5, +5}}); + fRegistry.add("Track/hTOFNsigmaEl", "loose track TOF PID", kTH2F, {{1000, 0.f, 10}, {100, -5, +5}}); + fRegistry.add("Track/hProbElBDT", "BDT score", kTH2F, {{1000, 0.f, 10}, {100, 0, 1}}); fRegistry.add("Pair/before/uls/hMvsPt", "mass vs. pT;m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{500, 0, 0.5}, {100, 0, 1}}); fRegistry.add("Pair/before/uls/hMvsPhiV", "mass vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0.f, M_PI}, {100, 0, 0.1}}); fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); @@ -1053,7 +1337,7 @@ struct prefilterPrimaryElectron { template bool checkTrack(TCollision const& collision, TTrack const& track) { - if (!track.hasITS()) { + if (!track.hasITS() || !track.hasTPC()) { return false; } if (track.itsChi2NCl() > maxchi2its) { @@ -1066,29 +1350,24 @@ struct prefilterPrimaryElectron { return false; } - if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { + // if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + // return false; + // } + + if (track.tpcNClsFound() < min_ncluster_tpc) { return false; } - - if (track.hasTPC()) { - if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { - 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 (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { - return false; - } - if (track.tpcChi2NCl() > maxchi2tpc) { - return false; - } + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; } o2::dataformats::DCA mDcaInfoCov; @@ -1128,6 +1407,87 @@ struct prefilterPrimaryElectron { return true; } + template + bool isElectron(TCollision const& collision, TTrack const& track) + { + if (usePIDML) { + if (isElectron_TOFif(track, collision)) { + auto trackParCov = getTrackParCov(track); + // trackParCov.setPID(o2::track::PID::Electron); + // o2::dataformats::DCA mDcaInfoCov; + // mDcaInfoCov.set(999, 999, 999, 999, 999); + // mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + // mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + // bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + // if (!isPropOK) { + // probaEl = 0.0; + // return false; + // } + // std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision, mapTOFBetaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())], mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + + int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(binsMl.value.size()) - 2; + } + // LOGF(info, "track.tpcInnerParam() = %f (GeV/c), pbin = %d", track.tpcInnerParam(), pbin); + + return mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())] > cutsMl.value[pbin]; + } else { + return false; + } + } else { + return isElectron_TPChadrej(track, collision) || isElectron_TOFreq(track, collision); + } + } + + template + bool isElectron_TOFif(TTrack const& track, TCollision const& collision) + { + // collisionId must be collisionId after reassociation. + // track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCascade.globalBC()) + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + bool is_EL_TPC = minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl; + bool is_EL_TOF = track.hasTOF() ? (std::fabs(tofNSigmaEl) < maxTOFNsigmaEl) : true; // TOFif + return is_EL_TPC && is_EL_TOF; + } + + template + bool isElectron_TPChadrej(TTrack const& track, TCollision const& collision) + { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + return false; + } + if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi && track.tpcInnerParam() < max_pin_for_pion_rejection) { + return false; + } + if (minTPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < maxTPCNsigmaKa) { + return false; + } + if (minTPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < maxTPCNsigmaPr) { + return false; + } + if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(tofNSigmaEl))) { + return false; + } + return true; + } + + template + bool isElectron_TOFreq(TTrack const& track, TCollision const& collision) + { + float tofNSigmaEl = mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]; + + if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi && (min_pin_for_pion_rejection < track.tpcInnerParam() && track.tpcInnerParam() < max_pin_for_pion_rejection)) { + return false; + } + return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && std::fabs(tofNSigmaEl) < maxTOFNsigmaEl; + } + template bool reconstructPC(TCollision const& collision, TTrack1 const& ele, TTrack2 const& pos) { @@ -1175,9 +1535,13 @@ struct prefilterPrimaryElectron { } } + std::map, float> mapProbaEl; // map pair(collisionId, trackId) -> probaEl + std::map, float> mapTOFNsigmaReassociated; // map pair(collisionId, trackId) -> tof n sigma + std::map, float> mapTOFBetaReassociated; // map pair(collisionId, trackId) -> tof beta + Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Filter trackFilter = o2::aod::track::itsChi2NCl < maxchi2its && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Filter trackFilter = 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 MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; @@ -1185,8 +1549,16 @@ struct prefilterPrimaryElectron { Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0); Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0); - void processPrefilter_TTCA(MyCollisions 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, aod::EMTOFNSigmas const& emtofs, aod::EMMLPIDs const& emmlpids) { + for (const auto& emtof : emtofs) { + mapTOFNsigmaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.tofNSigmaElRecalculated(); + mapTOFBetaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.betaRecalculated(); + } + for (const auto& emmlpid : emmlpids) { + mapProbaEl[std::make_pair(emmlpid.collisionId(), emmlpid.trackId())] = emmlpid.bdtScore(); + } + std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit for (const auto& collision : collisions) { @@ -1210,9 +1582,15 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, track)) { continue; } + if (!isElectron(collision, track)) { + continue; + } if (fillQAHistogram) { fRegistry.fill(HIST("Track/hPt"), track.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), track.globalIndex())]); + fRegistry.fill(HIST("Track/hProbElBDT"), track.tpcInnerParam(), mapProbaEl[std::make_pair(collision.globalIndex(), track.globalIndex())]); } if (track.sign() > 0) { posTracks_per_coll.emplace_back(track); @@ -1251,11 +1629,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), ele.tpcInnerParam(), ele.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[empos.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1298,11 +1671,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), pos.tpcInnerParam(), pos.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[emele.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1413,11 +1781,22 @@ struct prefilterPrimaryElectron { } // end of collision loop pfb_map.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); + mapProbaEl.clear(); } PROCESS_SWITCH(prefilterPrimaryElectron, processPrefilter_TTCA, "process prefilter with TTCA", false); - void processPrefilter_SA(MyCollisions 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, aod::EMTOFNSigmas const& emtofs, aod::EMMLPIDs const& emmlpids) { + for (const auto& emtof : emtofs) { + mapTOFNsigmaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.tofNSigmaElRecalculated(); + mapTOFBetaReassociated[std::make_pair(emtof.collisionId(), emtof.trackId())] = emtof.betaRecalculated(); + } + for (const auto& emmlpid : emmlpids) { + mapProbaEl[std::make_pair(emmlpid.collisionId(), emmlpid.trackId())] = emmlpid.bdtScore(); + } + std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit for (const auto& collision : collisions) { @@ -1437,18 +1816,30 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, pos)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, pos)) { + continue; + } if (fillQAHistogram) { fRegistry.fill(HIST("Track/hPt"), pos.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), pos.phi(), pos.eta()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), pos.tpcInnerParam(), pos.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), pos.tpcInnerParam(), mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), pos.globalIndex())]); + fRegistry.fill(HIST("Track/hProbElBDT"), pos.tpcInnerParam(), mapProbaEl[std::make_pair(collision.globalIndex(), pos.globalIndex())]); } } for (const auto& neg : negTracks_per_coll) { if (!checkTrack(collision, neg)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, neg)) { + continue; + } if (fillQAHistogram) { fRegistry.fill(HIST("Track/hPt"), neg.pt()); fRegistry.fill(HIST("Track/hEtaPhi"), neg.phi(), neg.eta()); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), neg.tpcInnerParam(), neg.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), neg.tpcInnerParam(), mapTOFNsigmaReassociated[std::make_pair(collision.globalIndex(), neg.globalIndex())]); + fRegistry.fill(HIST("Track/hProbElBDT"), neg.tpcInnerParam(), mapProbaEl[std::make_pair(collision.globalIndex(), neg.globalIndex())]); } } @@ -1457,6 +1848,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, ele)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, ele)) { + continue; + } if (empos.trackId() == ele.globalIndex()) { continue; } @@ -1469,11 +1863,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), ele.tpcInnerParam(), ele.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[empos.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1491,6 +1880,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, pos)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, pos)) { + continue; + } if (emele.trackId() == pos.globalIndex()) { continue; } @@ -1503,11 +1895,6 @@ struct prefilterPrimaryElectron { fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); } - if (v12.M() < max_mee_vec.at(static_cast(max_mee_vec.size()) - 1)) { - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), pos.tpcInnerParam(), pos.tpcNSigmaEl()); - } - } for (int i = 0; i < static_cast(max_mee_vec.size()); i++) { if (v12.M() < max_mee_vec.at(i)) { pfb_map[emele.globalIndex()] |= (uint8_t(1) << (static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV) + i)); @@ -1525,6 +1912,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, pos)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, pos)) { + continue; + } if (empos.trackId() == pos.globalIndex()) { continue; } @@ -1544,6 +1934,9 @@ struct prefilterPrimaryElectron { if (!checkTrack(collision, ele)) { // track cut is applied to loose sample continue; } + if (!isElectron(collision, ele)) { + continue; + } if (emele.trackId() == ele.globalIndex()) { continue; } @@ -1586,6 +1979,9 @@ struct prefilterPrimaryElectron { } // end of collision loop pfb_map.clear(); + mapTOFNsigmaReassociated.clear(); + mapTOFBetaReassociated.clear(); + mapProbaEl.clear(); } PROCESS_SWITCH(prefilterPrimaryElectron, processPrefilter_SA, "process prefilter standalone", false); @@ -1624,6 +2020,7 @@ struct associateAmbiguousElectron { }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + o2::pid::tof::TOFResponseImpl::metadataInfo.initMetadata(cfgc); return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-electron"}), adaptAnalysisTask(cfgc, TaskName{"prefilter-primary-electron"}), diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx index 5a22177b664..3815e0bc335 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectronQC.cxx @@ -16,32 +16,48 @@ #include "PWGEM/Dilepton/Utils/MlResponseO2Track.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" -// #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Tools/ML/MlResponse.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include +#include +#include #include -#include -#include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; @@ -79,13 +95,14 @@ struct skimmerPrimaryElectronQC { struct : ConfigurableGroup { std::string prefix = "trackcut"; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 40, "min. crossed rows"}; + Configurable mincrossedrows{"mincrossedrows", 0, "min. crossed rows"}; Configurable min_ncluster_its{"min_ncluster_its", 2, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 0, "min ncluster itsib"}; - Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.0, "min. TPC Ncr/Nf ratio"}; Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; - Configurable maxchi2its{"maxchi2its", 36.0, "max. chi2/NclsITS"}; + Configurable maxchi2tpc{"maxchi2tpc", 1e+10, "max. chi2/NclsTPC"}; + Configurable minchi2tpc{"minchi2tpc", -1e+10, "min. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 1e+10, "max. chi2/NclsITS"}; // actual maximum is 36 in the reconstruction. Configurable minchi2its{"minchi2its", -1e+10, "min. chi2/NclsITS"}; Configurable minpt{"minpt", 0.05, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; @@ -98,9 +115,9 @@ struct skimmerPrimaryElectronQC { struct : ConfigurableGroup { std::string prefix = "tighttrackcut"; - Configurable min_ncluster_tpc_pid{"min_ncluster_tpc_pid", 60, "min ncluster tpc used for PID"}; + Configurable min_ncluster_tpc_pid{"min_ncluster_tpc_pid", 0, "min ncluster tpc used for PID"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 100, "min. crossed rows"}; + Configurable mincrossedrows{"mincrossedrows", 120, "min. crossed rows"}; Configurable min_ncluster_its{"min_ncluster_its", 5, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 3, "min ncluster itsib"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; @@ -116,8 +133,10 @@ struct skimmerPrimaryElectronQC { } tighttrackcut; Configurable storeOnlyTrueElectronMC{"storeOnlyTrueElectronMC", false, "Flag to store only true electron in MC"}; - Configurable maxMee{"maxMee", 0.005, "max mee for pi0 -> ee"}; - Configurable maxPhiV{"maxPhiV", M_PI / 2, "max phiv for pi0 -> ee"}; + Configurable minMee{"minMee", 0.000, "min mee for pi0 -> ee or gamma -> ee"}; + Configurable maxMee{"maxMee", 0.005, "max mee for pi0 -> ee or gamma -> ee"}; + Configurable minPhiV{"minPhiV", 0.f, "min phiv for pi0 -> ee or gamma -> ee"}; + Configurable maxPhiV{"maxPhiV", M_PI / 2, "max phiv for pi0 -> ee or gamma -> ee"}; // configuration for PID ML Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; @@ -311,7 +330,7 @@ struct skimmerPrimaryElectronQC { } if (track.hasTPC()) { - if (track.tpcChi2NCl() < 0.f || trackcut.maxchi2tpc < track.tpcChi2NCl()) { + if (track.tpcChi2NCl() < trackcut.minchi2tpc || trackcut.maxchi2tpc < track.tpcChi2NCl()) { return false; } @@ -456,142 +475,138 @@ struct skimmerPrimaryElectronQC { 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()) { - mDcaInfoCov.set(999, 999, 999, 999, 999); - auto trackParCov = getTrackParCov(track); - trackParCov.setPID(o2::track::PID::Electron); - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); - if (!isPropOK) { - return; - } - float dcaXY = mDcaInfoCov.getY(); - float dcaZ = mDcaInfoCov.getZ(); - - float pt_recalc = trackParCov.getPt(); - float eta_recalc = trackParCov.getEta(); - float phi_recalc = trackParCov.getPhi(); - o2::math_utils::bringTo02Pi(phi_recalc); - - bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); - float mcTunedTPCSignal = 0.f; - if constexpr (isMC) { - mcTunedTPCSignal = track.mcTunedTPCSignal(); - } + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(o2::track::PID::Electron); + mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + bool isPropOK = o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + if (!isPropOK) { + return; + } + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); - float probaEl = 1.0; - if (usePIDML) { - std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision); - float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision); + float pt_recalc = trackParCov.getPt(); + float eta_recalc = trackParCov.getEta(); + float phi_recalc = trackParCov.getPhi(); + o2::math_utils::bringTo02Pi(phi_recalc); - int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; - if (pbin < 0) { - pbin = 0; - } else if (static_cast(binsMl.value.size()) - 2 < pbin) { - pbin = static_cast(binsMl.value.size()) - 2; - } - probaEl = mlResponseSingleTrack.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron + bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); + float mcTunedTPCSignal = 0.f; + if constexpr (isMC) { + mcTunedTPCSignal = track.mcTunedTPCSignal(); + } + + float probaEl = 1.0; + if (usePIDML) { + std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision); + + int pbin = lower_bound(binsMl.value.begin(), binsMl.value.end(), binningFeature) - binsMl.value.begin() - 1; + if (pbin < 0) { + pbin = 0; + } else if (static_cast(binsMl.value.size()) - 2 < pbin) { + pbin = static_cast(binsMl.value.size()) - 2; } + probaEl = mlResponseSingleTrack.getModelOutput(inputFeatures, pbin)[1]; // 0: hadron, 1:electron + } + + emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), + pt_recalc, eta_recalc, phi_recalc, + dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusPID(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(),*/ + track.itsClusterSizes(), + track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), + // trackParCov.getTgl(), + isAssociatedToMPC, false, probaEl, track.flags(), mcTunedTPCSignal); + + emprimaryelectronscov( + trackParCov.getX(), + trackParCov.getAlpha(), + trackParCov.getY(), + trackParCov.getZ(), + trackParCov.getSnp(), + // trackParCov.getTgl(), + // trackParCov.getSigmaY2(), + // trackParCov.getSigmaZY(), + // trackParCov.getSigmaZ2(), + trackParCov.getSigmaSnpY(), + trackParCov.getSigmaSnpZ(), + trackParCov.getSigmaSnp2(), + trackParCov.getSigmaTglY(), + trackParCov.getSigmaTglZ(), + trackParCov.getSigmaTglSnp(), + trackParCov.getSigmaTgl2(), + trackParCov.getSigma1PtY(), + trackParCov.getSigma1PtZ(), + trackParCov.getSigma1PtSnp(), + trackParCov.getSigma1PtTgl(), + trackParCov.getSigma1Pt2()); - emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), - pt_recalc, eta_recalc, phi_recalc, - dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), - track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusPID(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(),*/ - track.itsClusterSizes(), - track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), - // trackParCov.getTgl(), - isAssociatedToMPC, false, probaEl, mcTunedTPCSignal); - - emprimaryelectronscov( - trackParCov.getX(), - trackParCov.getAlpha(), - trackParCov.getY(), - trackParCov.getZ(), - trackParCov.getSnp(), - // trackParCov.getTgl(), - // trackParCov.getSigmaY2(), - // trackParCov.getSigmaZY(), - // trackParCov.getSigmaZ2(), - trackParCov.getSigmaSnpY(), - trackParCov.getSigmaSnpZ(), - trackParCov.getSigmaSnp2(), - trackParCov.getSigmaTglY(), - trackParCov.getSigmaTglZ(), - trackParCov.getSigmaTglSnp(), - trackParCov.getSigmaTgl2(), - trackParCov.getSigma1PtY(), - trackParCov.getSigma1PtZ(), - trackParCov.getSigma1PtSnp(), - trackParCov.getSigma1PtTgl(), - trackParCov.getSigma1Pt2()); - - stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); - - if (fillQAHistogram) { - int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 0; layer < 7; layer++) { - int cluster_size_per_layer = track.itsClsSizeInLayer(layer); - if (cluster_size_per_layer > 0) { - nl++; - } - total_cluster_size += cluster_size_per_layer; + if (fillQAHistogram) { + int total_cluster_size = 0, nl = 0; + for (unsigned int layer = 0; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl++; } + total_cluster_size += cluster_size_per_layer; + } - int total_cluster_size_ib = 0, nl_ib = 0; - for (unsigned int layer = 0; layer < 3; layer++) { - int cluster_size_per_layer = track.itsClsSizeInLayer(layer); - if (cluster_size_per_layer > 0) { - nl_ib++; - } - total_cluster_size_ib += cluster_size_per_layer; + int total_cluster_size_ib = 0, nl_ib = 0; + for (unsigned int layer = 0; layer < 3; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl_ib++; } + total_cluster_size_ib += cluster_size_per_layer; + } - int total_cluster_size_ob = 0, nl_ob = 0; - for (unsigned int layer = 3; layer < 7; layer++) { - int cluster_size_per_layer = track.itsClsSizeInLayer(layer); - if (cluster_size_per_layer > 0) { - nl_ob++; - } - total_cluster_size_ob += cluster_size_per_layer; + int total_cluster_size_ob = 0, nl_ob = 0; + for (unsigned int layer = 3; layer < 7; layer++) { + int cluster_size_per_layer = track.itsClsSizeInLayer(layer); + if (cluster_size_per_layer > 0) { + nl_ob++; } - - 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 / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, std::sqrt(trackParCov.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/hChi2TOF"), track.tofChi2()); - fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTPCdEdxMC"), track.tpcInnerParam(), mcTunedTPCSignal); - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - 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"), trackParCov.getP(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - 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()); - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), trackParCov.getP(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))); - fRegistry.fill(HIST("Track/hMeanClusterSizeITSib"), trackParCov.getP(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(trackParCov.getTgl()))); - fRegistry.fill(HIST("Track/hMeanClusterSizeITSob"), trackParCov.getP(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(trackParCov.getTgl()))); - fRegistry.fill(HIST("Track/hProbElBDT"), track.tpcInnerParam(), probaEl); + total_cluster_size_ob += 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 / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, std::sqrt(trackParCov.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/hChi2TOF"), track.tofChi2()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + fRegistry.fill(HIST("Track/hTPCdEdxMC"), track.tpcInnerParam(), mcTunedTPCSignal); + fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + 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"), trackParCov.getP(), track.beta()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); + 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()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), trackParCov.getP(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSib"), trackParCov.getP(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(trackParCov.getTgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSob"), trackParCov.getP(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(trackParCov.getTgl()))); + fRegistry.fill(HIST("Track/hProbElBDT"), track.tpcInnerParam(), probaEl); } } @@ -629,15 +644,20 @@ struct skimmerPrimaryElectronQC { if (fillQAHistogram) { fRegistry.fill(HIST("Pair/hMvsPhiV"), phiv, mee); } - if (mee < maxMee && phiv < maxPhiV) { + if ((minMee < mee && mee < maxMee) && (minPhiV < phiv && phiv < maxPhiV)) { return true; } else { return false; } } - std::vector> stored_trackIds; - Filter trackFilter = trackcut.minpt < o2::aod::track::pt && nabs(o2::aod::track::eta) < trackcut.maxeta && o2::aod::track::itsChi2NCl < trackcut.maxchi2its && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + // Filter trackFilter = trackcut.minpt < o2::aod::track::pt && nabs(o2::aod::track::eta) < trackcut.maxeta && o2::aod::track::itsChi2NCl < trackcut.maxchi2its && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Filter trackFilter_kine = trackcut.minpt < o2::aod::track::pt && nabs(o2::aod::track::eta) < trackcut.maxeta; + Filter trackFilter_its = o2::aod::track::itsChi2NCl < trackcut.maxchi2its; + Filter trackFilter_tpc = ifnode(trackcut.includeITSsa.node(), true, o2::aod::track::tpcChi2NCl < trackcut.maxchi2tpc); + Filter trackFilter_itstpc = ifnode(trackcut.includeITSsa.node(), ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS), ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC)); + Filter trackFilter_tpcpid = ifnode(trackcut.includeITSsa.node(), true, trackcut.minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < trackcut.maxTPCNsigmaEl); + using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; @@ -645,10 +665,8 @@ struct skimmerPrimaryElectronQC { // ---------- for data ---------- - void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -657,8 +675,8 @@ struct skimmerPrimaryElectronQC { continue; } - const auto& posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - const auto& negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + 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 (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { if ((checkTrackTight(collision, pos) && isElectronTight(pos)) && (checkTrack(collision, ele) && isElectron(ele))) { @@ -674,16 +692,11 @@ struct skimmerPrimaryElectronQC { } // end of ULS pairing } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryElectronQC, processRec, "process reconstructed info only", true); // standalone - void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -696,8 +709,8 @@ struct skimmerPrimaryElectronQC { continue; } - const auto& posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - const auto& negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + 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 (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { if ((checkTrackTight(collision, pos) && isElectronTight(pos)) && (checkTrack(collision, ele) && isElectron(ele))) { @@ -712,11 +725,7 @@ struct skimmerPrimaryElectronQC { } } // end of ULS pairing - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryElectronQC, processRec_SWT, "process reconstructed info only", false); // standalone with swt @@ -724,10 +733,8 @@ struct skimmerPrimaryElectronQC { using MyFilteredTracksMC = soa::Filtered; Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; - void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks, aod::McParticles const&) + void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const&, aod::McParticles const&) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { if (!collision.has_mcCollision()) { continue; @@ -738,8 +745,8 @@ struct skimmerPrimaryElectronQC { if (!collision.isSelected()) { continue; } - const auto& posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - const auto& negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + 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 (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { if ((checkTrackTight(collision, pos) && isElectronTight(pos)) && (checkTrack(collision, ele) && isElectron(ele))) { @@ -754,11 +761,7 @@ struct skimmerPrimaryElectronQC { } } // end of ULS pairing - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryElectronQC, processMC, "process reconstructed and MC info ", false); }; diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx new file mode 100644 index 00000000000..1cf936a061f --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMFTTrack.cxx @@ -0,0 +1,366 @@ +// 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 MFTsa tracks for reference flow. +/// \author daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +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::fwdtrackutils; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +struct skimmerPrimaryMFTTrack { + using MyCollisions = soa::Join; + using MyCollisionsWithSWT = soa::Join; + using MyCollisionsMC = soa::Join; + + using MyTracks = aod::MFTTracks; + using MyTrack = MyTracks::iterator; + using MyTracksMC = soa::Join; + using MyTrackMC = MyTracksMC::iterator; + + SliceCache cache; + Preslice perCol = o2::aod::fwdtrack::collisionId; + Produces emprimarytracks; + Produces prmtrackeventidtmp; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + + Configurable fillQAHistogram{"fillQAHistogram", true, "flag to fill QA histograms"}; + + Configurable cfgPtMin{"cfgPtMin", 0.1, "min pt for MFTsa track"}; + Configurable cfgPtMax{"cfgPtMax", 1e+10, "max pt for MFTsa track"}; + Configurable cfgEtaMin{"cfgEtaMin", -4, "min eta acceptance"}; + Configurable cfgEtaMax{"cfgEtaMax", -2, "max eta acceptance"}; + + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift from CCDB"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + int mRunNumber = 0; + float mBz = 0; + float mZShift = 0; + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + + void init(InitContext&) + { + mRunNumber = 0; + mBz = 0; + mZShift = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + + if (fillQAHistogram) { + fRegistry.add("MFT/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFT/hPtEta", "pT vs. #eta;#eta;p_{T} (GeV/c)", kTH2F, {{200, -4.f, -2.f}, {100, 0.0f, 10}}, false); + fRegistry.add("MFT/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{2000, -10, 10}}, false); + fRegistry.add("MFT/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {200, -4.0f, -2.0f}}, false); + fRegistry.add("MFT/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.1f, 0.1f}, {200, -0.1f, 0.1f}}, false); + fRegistry.add("MFT/hDCAxy", "DCA xy;DCA_{xy} (cm)", kTH1F, {{100, 0, 0.1f}}, false); + fRegistry.add("MFT/hDCAz", "DCA z;DCA_{z} (cm)", kTH1F, {{100, -0.05f, 0.05f}}, false); + fRegistry.add("MFT/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{100, 0, 0.1f}, {100, -0.05f, 0.05f}}, false); + fRegistry.add("MFT/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); + fRegistry.add("MFT/hChi2MFT", "chi2/ndf;chi2/ndf", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("MFT/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {200, -0.1, +0.1}}, false); + fRegistry.add("MFT/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {200, -0.1, +0.1}}, false); + fRegistry.add("MFT/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", kTH2F, {{180, 0, 2 * M_PI}, {200, -0.1, +0.1}}, false); + fRegistry.add("MFT/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", kTH2F, {{180, 0, 2 * M_PI}, {200, -0.1, +0.1}}, false); + } + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + LOGF(info, "mRunNumber = %d", mRunNumber); + 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(); + const double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + mBz = field->getBz(centerMFT); // Get field at centre of MFT + LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } + } + + template + bool checkTrack(TCollision const&, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + return true; + } + + template + void fillTrackTable(TCollision const& collision, TTrack const& mfttrack) + { + // propagate MFTsa track to PV + std::array dcaInfOrig{999.f, 999.f, 999.f}; + std::vector v1; // Temporary null vector for the computation of the covariance matrix + SMatrix55 tcovs(v1.begin(), v1.end()); + SMatrix5 tpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + o2::track::TrackParCovFwd trackPar{mfttrack.z() + mZShift, tpars, tcovs, mfttrack.chi2()}; + trackPar.propagateToDCAhelix(mBz, {collision.posX(), collision.posY(), collision.posZ()}, dcaInfOrig); + v1.clear(); + v1.shrink_to_fit(); + float dcaX = dcaInfOrig[0]; + float dcaY = dcaInfOrig[1]; + float dcaZ = dcaInfOrig[2]; + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + float pt = trackPar.getPt(); + float eta = trackPar.getEta(); + float phi = trackPar.getPhi(); + phi = RecoDecay::constrainAngle(phi, 0, 1U); + + if (pt < cfgPtMin || cfgPtMax < pt) { + return; + } + if (eta < cfgEtaMin || cfgEtaMax < eta) { + return; + } + + uint16_t trackBit = 0; + int ndf = 2 * mfttrack.nClusters() - 5; + + // As minimal cuts, following cuts are applied. The cut values are hardcoded on the purpose for consistent bit operation. + // Ncls MFT >= 5 + // chi2/ndf MFT < 4 + // |dcaXY| < 0.06 cm + + if (mfttrack.nClusters() < 5 || mfttrack.chi2() / ndf > 4.f || std::fabs(dcaXY) > 0.06) { + return; + } + + if (mfttrack.nClusters() >= 6) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kNclsMFT6)); + } + if (mfttrack.nClusters() >= 7) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kNclsMFT7)); + } + if (mfttrack.nClusters() >= 8) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kNclsMFT8)); + } + + if (mfttrack.chi2() / ndf < 3.f) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kChi2MFT3)); + } + if (mfttrack.chi2() / ndf < 2.f) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kChi2MFT2)); + } + + if (std::fabs(dcaXY) < 0.05) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kDCAxy005cm)); + } + if (std::fabs(dcaXY) < 0.04) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kDCAxy004cm)); + } + if (std::fabs(dcaXY) < 0.03) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kDCAxy003cm)); + } + if (std::fabs(dcaXY) < 0.02) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kDCAxy002cm)); + } + if (std::fabs(dcaXY) < 0.01) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefMFTTrackBit::kDCAxy001cm)); + } + + emprimarytracks(mfttrack.sign() / pt, eta, phi, trackBit); + prmtrackeventidtmp(collision.globalIndex()); + + if (fillQAHistogram) { + fRegistry.fill(HIST("MFT/hPt"), pt); + fRegistry.fill(HIST("MFT/hPtEta"), eta, pt); + fRegistry.fill(HIST("MFT/hQoverPt"), mfttrack.sign() / pt); + fRegistry.fill(HIST("MFT/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFT/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MFT/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MFT/hDCAz"), dcaZ); + fRegistry.fill(HIST("MFT/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("MFT/hNclsMFT"), mfttrack.nClusters()); + fRegistry.fill(HIST("MFT/hChi2MFT"), mfttrack.chi2() / ndf); + fRegistry.fill(HIST("MFT/hDCAx_PosZ"), collision.posZ(), dcaX); + fRegistry.fill(HIST("MFT/hDCAy_PosZ"), collision.posZ(), dcaY); + fRegistry.fill(HIST("MFT/hDCAx_Phi"), phi, dcaX); + fRegistry.fill(HIST("MFT/hDCAy_Phi"), phi, dcaY); + } + } + + // ---------- for data ---------- + + void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks) + { + + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { // events with at least 1 lepton for data reduction. + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!checkTrack(collision, track)) { + continue; + } + fillTrackTable(collision, track); + } + + } // end of collision loop + } + PROCESS_SWITCH(skimmerPrimaryMFTTrack, processRec, "process reconstructed info only", true); // standalone + + void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks) + { + + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { + continue; + } + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!checkTrack(collision, track)) { + continue; + } + fillTrackTable(collision, track); + } + + } // end of collision loop + } + PROCESS_SWITCH(skimmerPrimaryMFTTrack, processRec_SWT, "process reconstructed info only", false); // standalone with swt + + // ---------- for MC ---------- + + void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyTracksMC const& tracks) + { + + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { // events with at least 1 lepton for data reduction. + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!checkTrack(collision, track)) { + continue; + } + fillTrackTable(collision, track); + } + } // end of collision loop + } + PROCESS_SWITCH(skimmerPrimaryMFTTrack, processMC, "process reconstructed and MC info ", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-mfttrack"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 9de70407e65..382dc4a90df 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -14,35 +14,47 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Common/Core/TableHelper.h" #include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Math/SMatrix.h" -#include "Math/Vector4D.h" -#include "TGeoGlobalMagField.h" - +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include #include #include +#include #include #include #include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; @@ -63,38 +75,48 @@ struct skimmerPrimaryMuon { using MFTTracksMC = soa::Join; using MFTTrackMC = MFTTracksMC::iterator; - Produces emprimarymuons; + Produces emprimarymuons; Produces emprimarymuonscov; + Produces emprimarymuonsmatchmc; // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable fillQAHistograms{"fillQAHistograms", false, "flag to fill QA histograms"}; - Configurable minPt{"minPt", 0.1, "min pt for muon"}; + Configurable minPt{"minPt", 0.01, "min pt for muon"}; Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; Configurable minEtaSA{"minEtaSA", -4.0, "min. eta acceptance for MCH-MID"}; Configurable maxEtaSA{"maxEtaSA", -2.5, "max. eta acceptance for MCH-MID"}; - Configurable minEtaGL{"minEtaGL", -3.6, "min. eta acceptance for MFT-MCH-MID"}; - Configurable maxEtaGL{"maxEtaGL", -2.5, "max. eta acceptance for MFT-MCH-MID"}; - Configurable minRabsGL{"minRabsGL", 27.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. + Configurable minEtaGL{"minEtaGL", -1e+10, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEtaGL{"maxEtaGL", 0, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabsGL{"minRabsGL", 17.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. Configurable minRabs{"minRabs", 17.6, "min. R at absorber end"}; Configurable midRabs{"midRabs", 26.5, "middle R at absorber end for pDCA cut"}; Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; - Configurable maxDCAxy{"maxDCAxy", 1, "max. DCAxy for global muons"}; + Configurable maxDCAxy{"maxDCAxy", 1e+10, "max. DCAxy for global muons"}; Configurable maxPDCAforLargeR{"maxPDCAforLargeR", 324.f, "max. pDCA for large R at absorber end"}; Configurable maxPDCAforSmallR{"maxPDCAforSmallR", 594.f, "max. pDCA for small R at absorber end"}; - Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 50.f, "max. chi2 for MCH-MFT matching"}; - Configurable maxChi2SA{"maxChi2SA", 1e+6, "max. chi2 for standalone muon"}; - Configurable maxChi2GL{"maxChi2GL", 10, "max. chi2 for global muon"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 1e+10, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2SA{"maxChi2SA", 1e+10, "max. chi2 for standalone muon"}; + Configurable maxChi2GL{"maxChi2GL", 1e+10, "max. chi2 for global muon"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; Configurable minNmuon{"minNmuon", 0, "min number of muon candidates per collision"}; + Configurable maxDEta{"maxDEta", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable cfgApplyPreselectionInBestMatch{"cfgApplyPreselectionInBestMatch", false, "flag to apply preselection in find best match function"}; + + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; o2::ccdb::CcdbApi ccdbApi; Service ccdb; int mRunNumber = 0; float mBz = 0; + float mZShift = 0; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view muon_types[5] = {"MFTMCHMID/", "MFTMCHMIDOtherMatch/", "MFTMCH/", "MCHMID/", "MCH/"}; @@ -112,6 +134,7 @@ struct skimmerPrimaryMuon { } mRunNumber = 0; mBz = 0; + mZShift = 0; } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -134,6 +157,20 @@ struct skimmerPrimaryMuon { o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); mBz = field->getBz(centerMFT); // Get field at centre of MFT LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } } void addHistograms() @@ -145,29 +182,32 @@ struct skimmerPrimaryMuon { hMuonType->GetXaxis()->SetBinLabel(4, "MCH-MID"); hMuonType->GetXaxis()->SetBinLabel(5, "MCH standalone"); - fRegistry.add("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {60, -5.f, -2.f}}, false); - fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {60, -5.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{200, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); fRegistry.add("MFTMCHMID/hDeltaPt_Pt", "#Deltap_{T}/p_{T} vs. p_{T};p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl}", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/hDeltaEta_Pt", "#Delta#eta vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/hDeltaPhi_Pt", "#Delta#varphi vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); - fRegistry.add("MFTMCHMID/hDeltaEtaAtMP_Pt", "#Delta#eta vs. p_{T} at MP;p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); - fRegistry.add("MFTMCHMID/hDeltaPhiAtMP_Pt", "#Delta#varphi vs. p_{T} at MP;p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/hSign", "sign;sign", kTH1F, {{3, -1.5, +1.5}}, false); fRegistry.add("MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hChi2_Pt", "chi2;p_{T} (GeV/c);chi2/ndf", kTH2F, {{100, 0, 10}, {200, 0.0f, 20}}, false); + fRegistry.add("MFTMCHMID/hChi2MFT_Pt", "chi2 MFT;p_{T} (GeV/c);chi2 MFT/ndf", kTH2F, {{100, 0, 10}, {200, 0.0f, 20}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMID_Pt", "chi2 match MCH-MID;p_{T} (GeV/c);matching chi2 MCH-MID", kTH2F, {{100, 0, 10}, {200, 0.0f, 20}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T} (GeV/c);matching chi2 MCH-MFT", kTH2F, {{100, 0, 10}, {200, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1, 1}, {200, -1, +1}}, false); fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); fRegistry.add("MFTMCHMID/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{100, 0, 1}, {200, -0.1, 0.1}}, false); fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("MFTMCHMID/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); fRegistry.add("MFTMCHMID/hNmu", "#mu multiplicity;N_{#mu} per collision", kTH1F, {{21, -0.5, 20.5}}, false); + fRegistry.addClone("MFTMCHMID/", "MCHMID/"); fRegistry.add("MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); fRegistry.add("MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); @@ -188,6 +228,9 @@ struct skimmerPrimaryMuon { if (rAtAbsorberEnd < midRabs ? pDCA > maxPDCAforSmallR : pDCA > maxPDCAforLargeR) { return false; } + if (chi2_per_ndf < 0.f) { + return false; + } if (trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { if (eta < minEtaGL || maxEtaGL < eta) { @@ -219,10 +262,6 @@ struct skimmerPrimaryMuon { template bool fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, TMFTTracksCov const& mftCovs, const bool isAmbiguous) { - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { - return false; - } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. - if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. return false; } @@ -231,7 +270,7 @@ struct skimmerPrimaryMuon { return false; } - o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz); + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); float pt = propmuonAtPV.getPt(); float eta = propmuonAtPV.getEta(); float phi = propmuonAtPV.getPhi(); @@ -270,12 +309,20 @@ struct skimmerPrimaryMuon { int ndf_mchmft = 1; int ndf_mft = 1; - float etaMatchedMCHMIDatMP = 999.f; + // float etaMatchedMCHMIDatMP = 999.f; float phiMatchedMCHMIDatMP = 999.f; - float etaMatchedMFTatMP = 999.f; + // float etaMatchedMFTatMP = 999.f; float phiMatchedMFTatMP = 999.f; + float deta = 999.f; + float dphi = 999.f; + bool isCorrectMatchMFTMCH = true; // by default, it is true. it is evaluated for global muons in MC. + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + if (fwdtrack.chi2MatchMCHMFT() < 0.f || maxMatchingChi2MCHMFT < fwdtrack.chi2MatchMCHMFT()) { + return false; + } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. + // apply r-absorber cut here to minimize the number of calling propagateMuon. if (fwdtrack.rAtAbsorberEnd() < minRabsGL || maxRabs < fwdtrack.rAtAbsorberEnd()) { return false; @@ -288,11 +335,18 @@ struct skimmerPrimaryMuon { auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + if (mfttrack.chi2() < 0.f) { + return false; + } if constexpr (isMC) { - if (!mfttrack.has_mcParticle()) { + if (!mfttrack.has_mcParticle() || !mchtrack.has_mcParticle() || !fwdtrack.has_mcParticle()) { return false; } + // auto mcParticle_MFTMCHMID = fwdtrack.template mcParticle_as(); // this is identical to mcParticle_MCHMID + auto mcParticle_MCHMID = mchtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID + auto mcParticle_MFT = mfttrack.template mcParticle_as(); + isCorrectMatchMFTMCH = static_cast(mcParticle_MCHMID.globalIndex() == mcParticle_MFT.globalIndex()); } nClustersMFT = mfttrack.nClusters(); @@ -307,13 +361,13 @@ struct skimmerPrimaryMuon { return false; } - o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz); + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMID); - o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, matchingZ, mBz); + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); @@ -321,17 +375,17 @@ struct skimmerPrimaryMuon { if constexpr (withMFTCov) { auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); - auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, matchingZ, mBz); // propagated to matching plane - o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update - mftsaAtMP.propagateToZhelix(matchingZ, mBz); // propagated to matching plane - etaMatchedMFTatMP = mftsaAtMP.getEta(); + auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, matchingZ, mBz, mZShift); // propagated to matching plane + o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwdShift(mfttrack, mZShift, mfttrackcov); // values at innermost update + mftsaAtMP.propagateToZhelix(matchingZ, mBz); // propagated to matching plane + // etaMatchedMFTatMP = mftsaAtMP.getEta(); phiMatchedMFTatMP = mftsaAtMP.getPhi(); - etaMatchedMCHMIDatMP = muonAtMP.getEta(); + // etaMatchedMCHMIDatMP = muonAtMP.getEta(); phiMatchedMCHMIDatMP = muonAtMP.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMIDatMP); o2::math_utils::bringTo02Pi(phiMatchedMFTatMP); - o2::track::TrackParCovFwd mftsa = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update + o2::track::TrackParCovFwd mftsa = getTrackParCovFwdShift(mfttrack, mZShift, mfttrackcov); // values at innermost update o2::dataformats::GlobalFwdTrack globalMuonRefit = o2::aod::fwdtrackutils::refitGlobalMuonCov(propmuonAtPV_Matched, mftsa); // this is track at IU. auto globalMuon = o2::aod::fwdtrackutils::propagateTrackParCovFwd(globalMuonRefit, fwdtrack.trackType(), collision, propagationPoint::kToVertex, matchingZ, mBz); pt = globalMuon.getPt(); @@ -356,16 +410,24 @@ struct skimmerPrimaryMuon { sigma_dcaXY = dcaXY / dcaXYinSigma; } + deta = etaMatchedMCHMID - eta; + dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + + if (std::sqrt(std::pow(deta / maxDEta, 2) + std::pow(dphi / maxDPhi, 2)) > 1.f) { + return false; + } + if (refitGlobalMuon) { pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); } } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToRabs, matchingZ, mBz); // this is necessary only for MuonStandaloneTrack + o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToRabs, matchingZ, mBz, mZShift); // this is necessary only for MuonStandaloneTrack 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 - o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz); + o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); cXX = propmuonAtDCA.getSigma2X(); cYY = propmuonAtDCA.getSigma2Y(); cXY = propmuonAtDCA.getSigmaXY(); @@ -393,27 +455,25 @@ struct skimmerPrimaryMuon { if constexpr (fillTable) { float dpt = (ptMatchedMCHMID - pt) / pt; - float deta = etaMatchedMCHMID - eta; - float dphi = phiMatchedMCHMID - phi; - o2::math_utils::bringToPMPi(dphi); - float detaMP = etaMatchedMCHMIDatMP - etaMatchedMFTatMP; - float dphiMP = phiMatchedMCHMIDatMP - phiMatchedMFTatMP; - o2::math_utils::bringToPMPi(dphiMP); + // float detaMP = etaMatchedMCHMIDatMP - etaMatchedMFTatMP; + // float dphiMP = phiMatchedMCHMIDatMP - phiMatchedMFTatMP; + // o2::math_utils::bringToPMPi(dphiMP); bool isAssociatedToMPC = fwdtrack.collisionId() == collision.globalIndex(); // LOGF(info, "isAmbiguous = %d, isAssociatedToMPC = %d, fwdtrack.globalIndex() = %d, fwdtrack.collisionId() = %d, collision.globalIndex() = %d", isAmbiguous, isAssociatedToMPC, fwdtrack.globalIndex(), fwdtrack.collisionId(), collision.globalIndex()); emprimarymuons(collision.globalIndex(), fwdtrack.globalIndex(), fwdtrack.matchMFTTrackId(), fwdtrack.matchMCHTrackId(), fwdtrack.trackType(), pt, eta, phi, fwdtrack.sign(), dcaX, dcaY, cXX, cYY, cXY, ptMatchedMCHMID, etaMatchedMCHMID, phiMatchedMCHMID, - etaMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, etaMatchedMFTatMP, phiMatchedMFTatMP, + // etaMatchedMCHMIDatMP, phiMatchedMCHMIDatMP, etaMatchedMFTatMP, phiMatchedMFTatMP, fwdtrack.nClusters(), pDCA, rAtAbsorberEnd, fwdtrack.chi2(), fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), mftClusterSizesAndTrackFlags, chi2mft, isAssociatedToMPC, isAmbiguous); const auto& fwdcov = propmuonAtPV.getCovariances(); // covatiance matrix at PV emprimarymuonscov( - fwdcov(0, 0), - fwdcov(0, 1), fwdcov(1, 1), + propmuonAtPV.getX(), propmuonAtPV.getY(), propmuonAtPV.getZ(), + // fwdcov(0, 0), + // fwdcov(0, 1), fwdcov(1, 1), fwdcov(2, 0), fwdcov(2, 1), fwdcov(2, 2), fwdcov(3, 0), fwdcov(3, 1), fwdcov(3, 2), fwdcov(3, 3), fwdcov(4, 0), fwdcov(4, 1), fwdcov(4, 2), fwdcov(4, 3), fwdcov(4, 4)); @@ -426,6 +486,8 @@ struct skimmerPrimaryMuon { // // + emprimarymuonsmatchmc(isCorrectMatchMFTMCH); + if (fillQAHistograms) { fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { @@ -435,17 +497,15 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MFTMCHMID/hDeltaPt_Pt"), pt, dpt); fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); - fRegistry.fill(HIST("MFTMCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); - fRegistry.fill(HIST("MFTMCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); - fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft / ndf_mft); - fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/hChi2_Pt"), pt, fwdtrack.chi2() / ndf_mchmft); + fRegistry.fill(HIST("MFTMCHMID/hChi2MFT_Pt"), pt, chi2mft / ndf_mft); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); @@ -454,6 +514,10 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MFTMCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + fRegistry.fill(HIST("MFTMCHMID/hDCAx_PosZ"), collision.posZ(), dcaX); + fRegistry.fill(HIST("MFTMCHMID/hDCAy_PosZ"), collision.posZ(), dcaY); + fRegistry.fill(HIST("MFTMCHMID/hDCAx_Phi"), phi, dcaX); + fRegistry.fill(HIST("MFTMCHMID/hDCAy_Phi"), phi, dcaY); } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { fRegistry.fill(HIST("MCHMID/hPt"), pt); fRegistry.fill(HIST("MCHMID/hEtaPhi"), phi, eta); @@ -461,17 +525,15 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MCHMID/hDeltaPt_Pt"), pt, dpt); fRegistry.fill(HIST("MCHMID/hDeltaEta_Pt"), pt, deta); fRegistry.fill(HIST("MCHMID/hDeltaPhi_Pt"), pt, dphi); - fRegistry.fill(HIST("MCHMID/hDeltaEtaAtMP_Pt"), pt, detaMP); - fRegistry.fill(HIST("MCHMID/hDeltaPhiAtMP_Pt"), pt, dphiMP); fRegistry.fill(HIST("MCHMID/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MCHMID/hNclusters"), fwdtrack.nClusters()); fRegistry.fill(HIST("MCHMID/hNclustersMFT"), nClustersMFT); fRegistry.fill(HIST("MCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); - fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft / ndf_mft); - fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MCHMID/hChi2_Pt"), pt, fwdtrack.chi2()); + fRegistry.fill(HIST("MCHMID/hChi2MFT_Pt"), pt, chi2mft / ndf_mft); + fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); @@ -488,31 +550,87 @@ struct skimmerPrimaryMuon { std::unordered_map map_mfttrackcovs; std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; - template - void findBestMatchPerMCHMID(TMuons const& muons) + + template + void findBestMatchPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&) { - vec_min_chi2MatchMCHMFT.reserve(muons.size()); - for (const auto& muon : muons) { - if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - const auto& muons_per_MCHMID = muons.sliceBy(fwdtracksPerMCHTrack, muon.globalIndex()); - // LOGF(info, "stanadalone: muon.globalIndex() = %d, muon.chi2MatchMCHMFT() = %f", muon.globalIndex(), muon.chi2MatchMCHMFT()); - // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); - - float min_chi2MatchMCHMFT = 1e+10; - std::tuple tupleIds_at_min; - for (const auto& muon_tmp : muons_per_MCHMID) { - if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); - if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { - min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); - tupleIds_at_min = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); - } + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + return; + } + if constexpr (isMC) { + if (!fwdtrack.has_mcParticle()) { + return; + } + } + + const auto& muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); + // LOGF(info, "stanadalone: muon.globalIndex() = %d, muon.chi2MatchMCHMFT() = %f", muon.globalIndex(), muon.chi2MatchMCHMFT()); + // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = fwdtrack.p() * dcaXY_Matched; + + float min_chi2MatchMCHMFT = 1e+10; + std::tuple tupleIds_at_min_chi2mftmch; + for (const auto& muon_tmp : muons_per_MCHMID) { + if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + auto tupleId = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); + auto mchtrack = muon_tmp.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = muon_tmp.template matchMFTTrack_as(); // MFTsa + + if (muon_tmp.chi2() < 0.f || muon_tmp.chi2MatchMCHMFT() < 0.f || muon_tmp.chi2MatchMCHMID() < 0.f || mfttrack.chi2() < 0.f) { // reject negative chi2, i.e. wrong. + // LOGF(info, "reject: muon_tmp.globalIndex() = %d, muon_tmp.chi2MatchMCHMFT() = %f, muon_tmp.chi2MatchMCHMID() = %f, muon_tmp.chi2() = %f, mfttrack.chi2() = %f", muon_tmp.globalIndex(), muon_tmp.chi2MatchMCHMFT(), muon_tmp.chi2MatchMCHMID(), muon_tmp.chi2(), mfttrack.chi2()); + continue; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon_tmp, muon_tmp, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + if (refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + int ndf = 2 * (mchtrack.nClusters() + mfttrack.nClusters()) - 5; + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + if (cfgApplyPreselectionInBestMatch) { + if (!isSelected(pt, eta, muon_tmp.rAtAbsorberEnd(), pDCA, muon_tmp.chi2() / ndf, muon_tmp.trackType(), dcaXY)) { + continue; + } + if (std::sqrt(std::pow(deta / maxDEta, 2) + std::pow(dphi / maxDPhi, 2)) > 1.f) { + continue; + } + if (muon_tmp.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { + continue; } } - vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min); - // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); + + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { + min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); + tupleIds_at_min_chi2mftmch = tupleId; + } } - } // end of muon loop + } + vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min_chi2mftmch); + + // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); } SliceCache cache; @@ -523,9 +641,18 @@ struct skimmerPrimaryMuon { std::unordered_multimap multiMapSAMuonsPerCollision; // collisionId -> trackIds std::unordered_multimap multiMapGLMuonsPerCollision; // collisionId -> trackIds - void processRec_SA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) + void processRec_SA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop for (const auto& collision : collisions) { const auto& bc = collision.template bc_as(); @@ -541,9 +668,9 @@ struct skimmerPrimaryMuon { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } if (!fillFwdTrackTable(collision, fwdtrack, nullptr, false)) { continue; @@ -590,9 +717,18 @@ struct skimmerPrimaryMuon { } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_SA, "process reconstructed info", false); - void processRec_TTCA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processRec_TTCA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; for (const auto& fwdtrack : fwdtracks) { @@ -610,14 +746,17 @@ struct skimmerPrimaryMuon { } const auto& fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // LOGF(info, "collision.globalIndex() = %d, fwdtrackIdsThisCollision.size() = %d", collision.globalIndex(), fwdtrackIdsThisCollision.size()); for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { const auto& fwdtrack = fwdtrackId.template fwdtrack_as(); + // LOGF(info, "fwdtrack.globalIndex() = %d, fwdtrack.matchMCHTrackId() = %d, fwdtrack.matchMFTTrackId() = %d, fwdtrack.trackType() = %d", fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId(), fwdtrack.trackType()); if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { continue; @@ -665,88 +804,107 @@ struct skimmerPrimaryMuon { } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA, "process reconstructed info", false); - void processRec_TTCA_withMFTCov(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::MFTTracksCov const& mftCovs) + // void processRec_TTCA_withMFTCov(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::MFTTracksCov const& mftCovs) + // { + // for (const auto& mfttrackConv : mftCovs) { + // map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + // } + + // vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + // for (const auto& collision : collisions) { + // auto bc = collision.template bc_as(); + // initCCDB(bc); + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto fwdtrack = fwdtrackId.template fwdtrack_as(); + // findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + // } // end of fwdtrack loop + // } // end of collision loop + + // std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; + // for (const auto& fwdtrack : fwdtracks) { + // const auto& fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); + // mapAmb[fwdtrack.globalIndex()] = fwdtrackIdsPerFwdTrack.size() > 1; + // // LOGF(info, "fwdtrack.globalIndex() = %d, ntimes = %d, isAmbiguous = %d", fwdtrack.globalIndex(), fwdtrackIdsPerFwdTrack.size(), mapAmb[fwdtrack.globalIndex()]); + // } // end of fwdtrack loop + + // for (const auto& collision : collisions) { + // const auto& bc = collision.template bc_as(); + // initCCDB(bc); + + // if (!collision.isSelected()) { + // continue; + // } + + // const auto& fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // const auto& fwdtrack = fwdtrackId.template fwdtrack_as(); + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + + // // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // // continue; + // // } + + // if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + // continue; + // } + + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + // } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + // } + + // } // end of fwdtrack loop + // } // end of collision loop + + // for (const auto& collision : collisions) { + // int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + // int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + // if (fillQAHistograms) { + // fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + // fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + // } + // if (count_samuons >= minNmuon) { + // auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + // for (auto it = range_samuons.first; it != range_samuons.second; it++) { + // auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + // fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + // } + // } + // if (count_glmuons >= minNmuon) { + // auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + // for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + // auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + // fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + // } + // } + // } // end of collision loop + + // multiMapSAMuonsPerCollision.clear(); + // multiMapGLMuonsPerCollision.clear(); + // mapAmb.clear(); + // map_mfttrackcovs.clear(); + // vec_min_chi2MatchMCHMFT.clear(); + // vec_min_chi2MatchMCHMFT.shrink_to_fit(); + // } + // PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_withMFTCov, "process reconstructed info", false); + + void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&) { - for (const auto& mfttrackConv : mftCovs) { - map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); - } - findBestMatchPerMCHMID(fwdtracks); - - std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; - for (const auto& fwdtrack : fwdtracks) { - const auto& fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); - mapAmb[fwdtrack.globalIndex()] = fwdtrackIdsPerFwdTrack.size() > 1; - // LOGF(info, "fwdtrack.globalIndex() = %d, ntimes = %d, isAmbiguous = %d", fwdtrack.globalIndex(), fwdtrackIdsPerFwdTrack.size(), mapAmb[fwdtrack.globalIndex()]); - } // end of fwdtrack loop - + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); for (const auto& collision : collisions) { - const auto& bc = collision.template bc_as(); + auto bc = collision.template bc_as(); initCCDB(bc); - - if (!collision.isSelected()) { - continue; - } - - const auto& fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); - for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { - const auto& fwdtrack = fwdtrackId.template fwdtrack_as(); - if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - continue; - } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - - if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { - continue; - } - - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); - } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); - } - + const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop - for (const auto& collision : collisions) { - int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); - int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); - if (fillQAHistograms) { - fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); - fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); - } - if (count_samuons >= minNmuon) { - auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); - for (auto it = range_samuons.first; it != range_samuons.second; it++) { - auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); - } - } - if (count_glmuons >= minNmuon) { - auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); - for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { - auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); - } - } - } // end of collision loop - - multiMapSAMuonsPerCollision.clear(); - multiMapGLMuonsPerCollision.clear(); - mapAmb.clear(); - map_mfttrackcovs.clear(); - vec_min_chi2MatchMCHMFT.clear(); - vec_min_chi2MatchMCHMFT.shrink_to_fit(); - } - PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_withMFTCov, "process reconstructed info", false); - - void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) - { - findBestMatchPerMCHMID(fwdtracks); - for (const auto& collision : collisions) { const auto& bc = collision.template bc_as(); initCCDB(bc); @@ -764,9 +922,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } if (!fillFwdTrackTable(collision, fwdtrack, nullptr, false)) { continue; @@ -813,9 +971,18 @@ struct skimmerPrimaryMuon { } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_SA_SWT, "process reconstructed info only with standalone", false); - void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; for (const auto& fwdtrack : fwdtracks) { @@ -840,9 +1007,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { continue; @@ -890,90 +1057,107 @@ struct skimmerPrimaryMuon { } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_SWT, "process reconstructed info", false); - void processRec_TTCA_SWT_withMFTCov(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::MFTTracksCov const& mftCovs) + // void processRec_TTCA_SWT_withMFTCov(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::MFTTracksCov const& mftCovs) + // { + // for (const auto& mfttrackConv : mftCovs) { + // map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + // } + // vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + // for (const auto& collision : collisions) { + // auto bc = collision.template bc_as(); + // initCCDB(bc); + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto fwdtrack = fwdtrackId.template fwdtrack_as(); + // findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + // } // end of fwdtrack loop + // } // end of collision loop + + // std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; + // for (const auto& fwdtrack : fwdtracks) { + // auto fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); + // mapAmb[fwdtrack.globalIndex()] = fwdtrackIdsPerFwdTrack.size() > 1; + // // LOGF(info, "fwdtrack.globalIndex() = %d, ntimes = %d, isAmbiguous = %d", fwdtrack.globalIndex(), fwdtrackIdsPerFwdTrack.size(), mapAmb[fwdtrack.globalIndex()]); + // } // end of fwdtrack loop + + // for (const auto& collision : collisions) { + // auto bc = collision.template bc_as(); + // initCCDB(bc); + // if (!collision.isSelected()) { + // continue; + // } + // if (collision.swtaliastmp_raw() == 0) { + // continue; + // } + + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto fwdtrack = fwdtrackId.template fwdtrack_as(); + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + // // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // // continue; + // // } + + // if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + // continue; + // } + + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + // } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + // } + + // } // end of fwdtrack loop + // } // end of collision loop + + // for (const auto& collision : collisions) { + // int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + // int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + // if (fillQAHistograms) { + // fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + // fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + // } + // if (count_samuons >= minNmuon) { + // auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + // for (auto it = range_samuons.first; it != range_samuons.second; it++) { + // auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + // fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + // } + // } + // if (count_glmuons >= minNmuon) { + // auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + // for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + // auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + // fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + // } + // } + // } // end of collision loop + + // multiMapSAMuonsPerCollision.clear(); + // multiMapGLMuonsPerCollision.clear(); + // mapAmb.clear(); + // map_mfttrackcovs.clear(); + // vec_min_chi2MatchMCHMFT.clear(); + // vec_min_chi2MatchMCHMFT.shrink_to_fit(); + // } + // PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_SWT_withMFTCov, "process reconstructed info", false); + + void processMC_SA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const& mfttracks, aod::BCsWithTimestamps const&, aod::McParticles const&) { - for (const auto& mfttrackConv : mftCovs) { - map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); - } - findBestMatchPerMCHMID(fwdtracks); - - std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; - for (const auto& fwdtrack : fwdtracks) { - auto fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); - mapAmb[fwdtrack.globalIndex()] = fwdtrackIdsPerFwdTrack.size() > 1; - // LOGF(info, "fwdtrack.globalIndex() = %d, ntimes = %d, isAmbiguous = %d", fwdtrack.globalIndex(), fwdtrackIdsPerFwdTrack.size(), mapAmb[fwdtrack.globalIndex()]); - } // end of fwdtrack loop - + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); - if (!collision.isSelected()) { - continue; - } - if (collision.swtaliastmp_raw() == 0) { - continue; - } - - auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); - for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { - auto fwdtrack = fwdtrackId.template fwdtrack_as(); - if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - continue; - } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - - if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { - continue; - } - - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); - } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); - } - + auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop - for (const auto& collision : collisions) { - int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); - int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); - if (fillQAHistograms) { - fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); - fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); - } - if (count_samuons >= minNmuon) { - auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); - for (auto it = range_samuons.first; it != range_samuons.second; it++) { - auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); - } - } - if (count_glmuons >= minNmuon) { - auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); - for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { - auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); - } - } - } // end of collision loop - - multiMapSAMuonsPerCollision.clear(); - multiMapGLMuonsPerCollision.clear(); - mapAmb.clear(); - map_mfttrackcovs.clear(); - vec_min_chi2MatchMCHMFT.clear(); - vec_min_chi2MatchMCHMFT.shrink_to_fit(); - } - PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_SWT_withMFTCov, "process reconstructed info", false); - - void processMC_SA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&) - { - findBestMatchPerMCHMID(fwdtracks); - for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); @@ -992,9 +1176,9 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } if (!fillFwdTrackTable(collision, fwdtrack, nullptr, false)) { continue; @@ -1041,93 +1225,19 @@ struct skimmerPrimaryMuon { } PROCESS_SWITCH(skimmerPrimaryMuon, processMC_SA, "process reconstructed and MC info", false); - void processMC_TTCA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processMC_TTCA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McParticles const&) { - findBestMatchPerMCHMID(fwdtracks); - - std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; - for (const auto& fwdtrack : fwdtracks) { - auto fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); - mapAmb[fwdtrack.globalIndex()] = fwdtrackIdsPerFwdTrack.size() > 1; - // LOGF(info, "fwdtrack.globalIndex() = %d, ntimes = %d, isAmbiguous = %d", fwdtrack.globalIndex(), fwdtrackIdsPerFwdTrack.size(), mapAmb[fwdtrack.globalIndex()]); - } // end of fwdtrack loop - + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); - if (!collision.isSelected()) { - continue; - } - if (!collision.has_mcCollision()) { - continue; - } - auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { auto fwdtrack = fwdtrackId.template fwdtrack_as(); - if (!fwdtrack.has_mcParticle()) { - continue; - } - if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - continue; - } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - - if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { - continue; - } - - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); - } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); - } - + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop - for (const auto& collision : collisions) { - int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); - int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); - if (fillQAHistograms) { - fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); - fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); - } - if (count_samuons >= minNmuon) { - auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); - for (auto it = range_samuons.first; it != range_samuons.second; it++) { - auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); - } - } - if (count_glmuons >= minNmuon) { - auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); - for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { - auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); - } - } - } // end of collision loop - - multiMapSAMuonsPerCollision.clear(); - multiMapGLMuonsPerCollision.clear(); - mapAmb.clear(); - map_mfttrackcovs.clear(); - vec_min_chi2MatchMCHMFT.clear(); - vec_min_chi2MatchMCHMFT.shrink_to_fit(); - } - PROCESS_SWITCH(skimmerPrimaryMuon, processMC_TTCA, "process reconstructed and MC info", false); - - void processMC_TTCA_withMFTCov(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::MFTTracksCov const& mftCovs) - { - for (const auto& mfttrackConv : mftCovs) { - map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); - } - findBestMatchPerMCHMID(fwdtracks); - std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; for (const auto& fwdtrack : fwdtracks) { auto fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); @@ -1154,11 +1264,11 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } - if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + if (!fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()])) { continue; } @@ -1183,14 +1293,14 @@ struct skimmerPrimaryMuon { auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); for (auto it = range_samuons.first; it != range_samuons.second; it++) { auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); } } if (count_glmuons >= minNmuon) { auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { auto fwdtrack = fwdtracks.rawIteratorAt(it->second); - fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + fillFwdTrackTable(collision, fwdtrack, nullptr, mapAmb[fwdtrack.globalIndex()]); } } } // end of collision loop @@ -1202,11 +1312,104 @@ struct skimmerPrimaryMuon { vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); } - PROCESS_SWITCH(skimmerPrimaryMuon, processMC_TTCA_withMFTCov, "process reconstructed and MC with MFTCov info", false); + PROCESS_SWITCH(skimmerPrimaryMuon, processMC_TTCA, "process reconstructed and MC info", false); + + // void processMC_TTCA_withMFTCov(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::MFTTracksCov const& mftCovs, aod::McParticles const&) + // { + // for (const auto& mfttrackConv : mftCovs) { + // map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + // } + // vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + // for (const auto& collision : collisions) { + // auto bc = collision.template bc_as(); + // initCCDB(bc); + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto fwdtrack = fwdtrackId.template fwdtrack_as(); + // findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + // } // end of fwdtrack loop + // } // end of collision loop + + // std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; + // for (const auto& fwdtrack : fwdtracks) { + // auto fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); + // mapAmb[fwdtrack.globalIndex()] = fwdtrackIdsPerFwdTrack.size() > 1; + // // LOGF(info, "fwdtrack.globalIndex() = %d, ntimes = %d, isAmbiguous = %d", fwdtrack.globalIndex(), fwdtrackIdsPerFwdTrack.size(), mapAmb[fwdtrack.globalIndex()]); + // } // end of fwdtrack loop + + // for (const auto& collision : collisions) { + // auto bc = collision.template bc_as(); + // initCCDB(bc); + // if (!collision.isSelected()) { + // continue; + // } + // if (!collision.has_mcCollision()) { + // continue; + // } + + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto fwdtrack = fwdtrackId.template fwdtrack_as(); + // if (!fwdtrack.has_mcParticle()) { + // continue; + // } + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + // // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // // continue; + // // } + + // if (!fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()])) { + // continue; + // } + + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // multiMapGLMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + // } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // multiMapSAMuonsPerCollision.insert(std::make_pair(collision.globalIndex(), fwdtrack.globalIndex())); + // } + + // } // end of fwdtrack loop + // } // end of collision loop + + // for (const auto& collision : collisions) { + // int count_samuons = multiMapSAMuonsPerCollision.count(collision.globalIndex()); + // int count_glmuons = multiMapGLMuonsPerCollision.count(collision.globalIndex()); + // if (fillQAHistograms) { + // fRegistry.fill(HIST("MCHMID/hNmu"), count_samuons); + // fRegistry.fill(HIST("MFTMCHMID/hNmu"), count_glmuons); + // } + // if (count_samuons >= minNmuon) { + // auto range_samuons = multiMapSAMuonsPerCollision.equal_range(collision.globalIndex()); + // for (auto it = range_samuons.first; it != range_samuons.second; it++) { + // auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + // fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + // } + // } + // if (count_glmuons >= minNmuon) { + // auto range_glmuons = multiMapGLMuonsPerCollision.equal_range(collision.globalIndex()); + // for (auto it = range_glmuons.first; it != range_glmuons.second; it++) { + // auto fwdtrack = fwdtracks.rawIteratorAt(it->second); + // fillFwdTrackTable(collision, fwdtrack, mftCovs, mapAmb[fwdtrack.globalIndex()]); + // } + // } + // } // end of collision loop + + // multiMapSAMuonsPerCollision.clear(); + // multiMapGLMuonsPerCollision.clear(); + // mapAmb.clear(); + // map_mfttrackcovs.clear(); + // vec_min_chi2MatchMCHMFT.clear(); + // vec_min_chi2MatchMCHMFT.shrink_to_fit(); + // } + // PROCESS_SWITCH(skimmerPrimaryMuon, processMC_TTCA_withMFTCov, "process reconstructed and MC with MFTCov info", false); void processDummy(aod::Collisions const&) {} PROCESS_SWITCH(skimmerPrimaryMuon, processDummy, "process dummy", true); }; + struct associateAmbiguousMuon { Produces em_amb_muon_ids; @@ -1231,32 +1434,58 @@ struct associateAmbiguousMuon { } } }; -struct associateSameMFT { - Produces em_same_mft_ids; + +struct associateSameMuonElement { + Produces glmuon_same_ids; SliceCache cache; PresliceUnsorted perMFTTrack = o2::aod::emprimarymuon::mfttrackId; - std::vector self_Ids; + PresliceUnsorted perMCHTrack = o2::aod::emprimarymuon::mchtrackId; + std::vector selfIds_per_MFT; + std::vector selfIds_per_MCHMID; + // Multiple MCH-MID tracks can match with the same MFTsa. This function is to reject such global muons. void process(aod::EMPrimaryMuons const& muons) { for (const auto& muon : muons) { if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { auto muons_with_same_mfttrackId = muons.sliceBy(perMFTTrack, muon.mfttrackId()); - self_Ids.reserve(muons_with_same_mfttrackId.size()); + auto muons_with_same_mchtrackId = muons.sliceBy(perMCHTrack, muon.mchtrackId()); + selfIds_per_MFT.reserve(muons_with_same_mfttrackId.size()); + selfIds_per_MCHMID.reserve(muons_with_same_mchtrackId.size()); + // LOGF(info, "muons_with_same_mchtrackId.size() = %d, muons_with_same_mfttrackId.size() = %d", muons_with_same_mchtrackId.size(), muons_with_same_mfttrackId.size()); + for (const auto& global_muon : muons_with_same_mfttrackId) { + // LOGF(info, "same MFT: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. continue; } - if (global_muon.collisionId() == muon.collisionId()) { - self_Ids.emplace_back(global_muon.globalIndex()); + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MFT.emplace_back(global_muon.globalIndex()); } } - em_same_mft_ids(self_Ids); - self_Ids.clear(); - self_Ids.shrink_to_fit(); + + for (const auto& global_muon : muons_with_same_mchtrackId) { + // LOGF(info, "same MCH: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); + if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MCHMID.emplace_back(global_muon.globalIndex()); + } + } + + glmuon_same_ids(selfIds_per_MCHMID, selfIds_per_MFT); + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); } else { - em_same_mft_ids(std::vector{}); // empty for standalone muons + glmuon_same_ids(std::vector{}, std::vector{}); // empty for standalone muons + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); } } // end of muon loop } @@ -1266,5 +1495,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-muon"}), adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-muon"}), - adaptAnalysisTask(cfgc, TaskName{"associate-same-mft"})}; + adaptAnalysisTask(cfgc, TaskName{"associate-same-muon-element"})}; } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx new file mode 100644 index 00000000000..d5f410eafaa --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuonQC.cxx @@ -0,0 +1,797 @@ +// 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 muons. +/// \author daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include +#include +#include +#include +#include +#include + +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::fwdtrackutils; + +struct skimmerPrimaryMuonQC { + using MyCollisions = soa::Join; + using MyCollisionsWithSWT = soa::Join; + + using MyFwdTracks = soa::Join; // muon tracks are repeated. i.e. not exclusive. + using MyFwdTrack = MyFwdTracks::iterator; + + using MyFwdTracksMC = soa::Join; + using MyFwdTrackMC = MyFwdTracksMC::iterator; + + using MFTTracksMC = soa::Join; + using MFTTrackMC = MFTTracksMC::iterator; + + Produces emprimarymuons; + Produces emprimarymuonscov; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable fillQAHistograms{"fillQAHistograms", false, "flag to fill QA histograms"}; + + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + + struct : ConfigurableGroup { // tight cut + std::string prefix = "tagMuonCut"; + Configurable minPt{"minPt", 0.8, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEta{"minEta", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEta{"maxEta", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 27.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 0.06, "max. DCAxy for global muons"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 40.f, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 4.f, "max. chi2/ndf for global muon"}; + // Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + // Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable maxDEta{"maxDEta", 0.08, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 0.08, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } tagMuonCut; + + struct : ConfigurableGroup { // loose cut + std::string prefix = "probeMuonCut"; + Configurable minPt{"minPt", 0.01, "min pt for muon"}; + Configurable maxPt{"maxPt", 1e+10, "max pt for muon"}; + Configurable minEtaSA{"minEtaSA", -4.0, "min. eta acceptance for MFT-MCH"}; + Configurable maxEtaSA{"maxEtaSA", -2.5, "max. eta acceptance for MFT-MCH"}; + Configurable minEtaGL{"minEtaGL", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEtaGL{"maxEtaGL", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minRabs{"minRabs", 17.6, "min. R at absorber end for global muon (min. eta = -3.6)"}; // std::tan(2.f * std::atan(std::exp(- -3.6)) ) * -505. = 27.6 + Configurable midRabs{"midRabs", 26.5, "middle R at absorber end for pDCA cut"}; + Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; + Configurable maxDCAxy{"maxDCAxy", 1.f, "max. DCAxy for global muons"}; + Configurable maxPDCAforLargeR{"maxPDCAforLargeR", 324.f, "max. pDCA for large R at absorber end"}; + Configurable maxPDCAforSmallR{"maxPDCAforSmallR", 594.f, "max. pDCA for small R at absorber end"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 100, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 1e+10, "max. chi2/ndf for global muon"}; + // Configurable minNclsMFT{"minNclsMFT", 5, "min ncluster of MFT"}; + // Configurable minNclsMCH{"minNclsMCH", 5, "min ncluster of MCH"}; + Configurable maxDEta{"maxDEta", 1e+10, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable maxDPhi{"maxDPhi", 1e+10, "max. dphi between MFT-MCH-MID and MCH-MID"}; + } probeMuonCut; + + struct : ConfigurableGroup { + std::string prefix = "pairCuts"; + Configurable minMass{"minMass", 0.21, "min mass"}; + Configurable maxMass{"maxMass", 0.30, "max mass"}; + } pairCuts; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber = 0; + float mBz = 0; + float mZShift = 0; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + // static constexpr std::string_view muon_types[5] = {"MFTMCHMID/", "MFTMCHMIDOtherMatch/", "MFTMCH/", "MCHMID/", "MCH/"}; + + void init(InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + + if (fillQAHistograms) { + addHistograms(); + } + mRunNumber = 0; + mBz = 0; + mZShift = 0; + } + + 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(); + const double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + mBz = field->getBz(centerMFT); // Get field at centre of MFT + LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } + } + + void addHistograms() + { + // auto hMuonType = fRegistry.add("hMuonType", "muon type", kTH1F, {{5, -0.5f, 4.5f}}, false); + // 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("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{200, 0.0f, 10}}, false); + // fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); + // fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -4.f, -2.f}}, false); + // fRegistry.add("MFTMCHMID/hDeltaPt_Pt", "#Deltap_{T}/p_{T} vs. p_{T};p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl}", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + // fRegistry.add("MFTMCHMID/hDeltaEta_Pt", "#Delta#eta vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + // fRegistry.add("MFTMCHMID/hDeltaPhi_Pt", "#Delta#varphi vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + // fRegistry.add("MFTMCHMID/hSign", "sign;sign", kTH1F, {{3, -1.5, +1.5}}, false); + // fRegistry.add("MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); + // fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); + // fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); + // fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); + // fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2/ndf", kTH1F, {{200, 0.0f, 20}}, false); + // fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{200, 0.0f, 20}}, false); + // fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{200, 0.0f, 20}}, false); + // fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{200, 0.0f, 100}}, false); + // fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1, 1}, {200, -1, +1}}, false); + // fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); + // fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); + // fRegistry.add("MFTMCHMID/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{100, 0, 1}, {200, -0.1, 0.1}}, false); + // fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); + // fRegistry.add("MFTMCHMID/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + // fRegistry.add("MFTMCHMID/hNmu", "#mu multiplicity;N_{#mu} per collision", kTH1F, {{21, -0.5, 20.5}}, false); + + // fRegistry.addClone("MFTMCHMID/", "MCHMID/"); + // fRegistry.add("MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + // fRegistry.add("MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + // fRegistry.add("MFTMCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + // fRegistry.add("MCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + // fRegistry.add("MCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + // fRegistry.add("MCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + + fRegistry.add("Pair/uls/gl_gl/hMvsPt", "dimuon;m_{#mu#mu} (GeV/c^{2});p_{T,#mu} (GeV/c);", kTH2F, {{380, 0.2, 4.f}, {100, 0, 10}}, false); + fRegistry.add("Pair/uls/gl_sa/hMvsPt", "dimuon;m_{#mu#mu} (GeV/c^{2});p_{T,#mu} (GeV/c);", kTH2F, {{380, 0.2, 4.f}, {100, 0, 10}}, false); + } + + struct Muon { + int globalIndex = -1; + int collisionId = -1; + int matchMCHTrackId = -1; + int matchMFTTrackId = -1; + uint8_t trackType = 99; + int8_t sign = 0; + float pt = 0; + float eta = 0; + float phi = 0; + float dcaX = 0; // in cm + float dcaY = 0; // in cm + float dcaXY = 0; // in cm + float cXX = 0; + float cYY = 0; + float cXY = 0; + float rAtAbsorberEnd = 0; + float pDCA = 0; + float chi2ndf = 0; + float chi2MatchMCHMID = 0; + + // only for global muons + float ptMatchedMCHMID = 0; + float etaMatchedMCHMID = 0; + float phiMatchedMCHMID = 0; + float chi2MatchMCHMFT = 0; + float chi2mft = -999.f; + uint64_t mftClusterSizesAndTrackFlags = 0; + }; + + bool isSelected(Muon const& muon) + { + if (muon.pt < probeMuonCut.minPt || probeMuonCut.maxPt < muon.pt) { + return false; + } + + if (muon.rAtAbsorberEnd < probeMuonCut.minRabs || probeMuonCut.maxRabs < muon.rAtAbsorberEnd) { + return false; + } + + if (muon.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (muon.eta < probeMuonCut.minEtaGL || probeMuonCut.maxEtaGL < muon.eta) { + return false; + } + if (probeMuonCut.maxDCAxy < muon.dcaXY) { + return false; + } + if (probeMuonCut.maxMatchingChi2MCHMFT < muon.chi2MatchMCHMFT) { + return false; + } + } else if (muon.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (muon.eta < probeMuonCut.minEtaSA || probeMuonCut.maxEtaSA < muon.eta) { + return false; + } + if (muon.rAtAbsorberEnd < probeMuonCut.midRabs ? muon.pDCA > probeMuonCut.maxPDCAforSmallR : muon.pDCA > probeMuonCut.maxPDCAforLargeR) { + return false; + } + } else { + return false; + } + + return true; + } + + bool isSelectedTight(Muon const& muon) + { + if (muon.trackType != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { // tag muon should be tight. + return false; + } + + if (muon.pt < tagMuonCut.minPt || tagMuonCut.maxPt < muon.pt) { + return false; + } + + if (muon.rAtAbsorberEnd < tagMuonCut.minRabs || tagMuonCut.maxRabs < muon.rAtAbsorberEnd) { + return false; + } + + if (muon.chi2ndf < 0.f || tagMuonCut.maxChi2 < muon.chi2ndf) { + return false; + } + + if (muon.eta < tagMuonCut.minEta || tagMuonCut.maxEta < muon.eta) { + return false; + } + + if (tagMuonCut.maxDCAxy < muon.dcaXY) { + return false; + } + + if (tagMuonCut.maxMatchingChi2MCHMFT < muon.chi2MatchMCHMFT) { + return false; + } + + float deta = muon.etaMatchedMCHMID - muon.eta; + float dphi = muon.phiMatchedMCHMID - muon.phi; + // LOGF(info, "muon.trackType = %d, deta = %f, dphi = %f", muon.trackType, deta, dphi); + if (std::sqrt(std::pow(deta / tagMuonCut.maxDEta, 2) + std::pow(dphi / tagMuonCut.maxDPhi, 2)) > 1.f) { + return false; + } + + return true; + } + + template + bool fillMuonInfo(TCollision const& collision, TFwdTrack fwdtrack) + { + if (fwdtrack.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && fwdtrack.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + return false; + } + + if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return false; + } + + if (fwdtrack.chi2() < 0.f) { // this should never happen. only for protection. + return false; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + float rAtAbsorberEnd = fwdtrack.rAtAbsorberEnd(); // this works only for GlobalMuonTrack + float cXX = propmuonAtPV.getSigma2X(); + float cYY = propmuonAtPV.getSigma2Y(); + float cXY = propmuonAtPV.getSigmaXY(); + + float pDCA = propmuonAtPV.getP() * dcaXY; + int nClustersMFT = 0; + float ptMatchedMCHMID = propmuonAtPV.getPt(); + float etaMatchedMCHMID = propmuonAtPV.getEta(); + float phiMatchedMCHMID = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + float chi2mft = -999.f; + uint64_t mftClusterSizesAndTrackFlags = 0; + int ndf_mchmft = 1; + + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + if (fwdtrack.chi2MatchMCHMFT() < 0.f) { + return false; + } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. + + auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + if (mfttrack.chi2() < 0.f) { + return false; + } + + if constexpr (isMC) { + if (!mfttrack.has_mcParticle() || !mchtrack.has_mcParticle() || !fwdtrack.has_mcParticle()) { + return false; + } + // auto mcParticle_MFTMCHMID = fwdtrack.template mcParticle_as(); // this is identical to mcParticle_MCHMID + auto mcParticle_MCHMID = mchtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID + auto mcParticle_MFT = mfttrack.template mcParticle_as(); + } + + nClustersMFT = mfttrack.nClusters(); + mftClusterSizesAndTrackFlags = mfttrack.mftClusterSizesAndTrackFlags(); + ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; + chi2mft = mfttrack.chi2(); + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); + etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + pDCA = mchtrack.p() * dcaXY_Matched; + + if (refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToRabs, matchingZ, mBz, mZShift); // this is necessary only for MuonStandaloneTrack + 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 + ndf_mchmft = 1; // chi2 is already normalized by ndf for MCH-MID tracks. + + o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + cXX = propmuonAtDCA.getSigma2X(); + cYY = propmuonAtDCA.getSigma2Y(); + cXY = propmuonAtDCA.getSigmaXY(); + dcaX = propmuonAtDCA.getX() - collision.posX(); + dcaY = propmuonAtDCA.getY() - collision.posY(); + dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + pDCA = fwdtrack.p() * dcaXY; + } else { + return false; + } + + Muon muon; + muon.globalIndex = fwdtrack.globalIndex(); + muon.collisionId = collision.globalIndex(); + muon.trackType = fwdtrack.trackType(); + muon.sign = fwdtrack.sign(); + muon.pt = pt; + muon.eta = eta; + muon.phi = phi; + muon.dcaX = dcaX; + muon.dcaY = dcaY; + muon.dcaXY = dcaXY; + muon.cXX = cXX; + muon.cYY = cYY; + muon.cXY = cXY; + muon.rAtAbsorberEnd = rAtAbsorberEnd; + muon.pDCA = pDCA; + muon.chi2ndf = fwdtrack.chi2() / ndf_mchmft; + muon.ptMatchedMCHMID = ptMatchedMCHMID; + muon.etaMatchedMCHMID = etaMatchedMCHMID; + muon.phiMatchedMCHMID = phiMatchedMCHMID; + muon.chi2mft = chi2mft; + muon.matchMCHTrackId = fwdtrack.matchMCHTrackId(); + muon.matchMFTTrackId = fwdtrack.matchMFTTrackId(); + muon.mftClusterSizesAndTrackFlags = mftClusterSizesAndTrackFlags; + + vecMuons.emplace_back(muon); + return true; + } + + template + bool fillFwdTrackTable(TCollision const& collision, TMuon const& muon, TFwdTrack const& fwdtrack) + { + emprimarymuons(collision.globalIndex(), fwdtrack.globalIndex(), fwdtrack.matchMFTTrackId(), fwdtrack.matchMCHTrackId(), fwdtrack.trackType(), + muon.pt, muon.eta, muon.phi, fwdtrack.sign(), muon.dcaX, muon.dcaY, muon.cXX, muon.cYY, muon.cXY, muon.ptMatchedMCHMID, muon.etaMatchedMCHMID, muon.phiMatchedMCHMID, + fwdtrack.nClusters(), muon.pDCA, muon.rAtAbsorberEnd, fwdtrack.chi2(), fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), + fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), muon.mftClusterSizesAndTrackFlags, muon.chi2mft, true, false); + + // if (fillQAHistograms) { + // fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); + // fRegistry.fill(HIST("MFTMCHMID/hEtaPhi"), phi, eta); + // fRegistry.fill(HIST("MFTMCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + // fRegistry.fill(HIST("MFTMCHMID/hDeltaPt_Pt"), pt, dpt); + // fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); + // fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); + // fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); + // fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); + // fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); + // fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + // fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + // fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); + // fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft / ndf_mft); + // fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + // fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxyz"), dcaXY, dcaZ); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxyinSigma"), dcaXYinSigma); + // fRegistry.fill(HIST("MFTMCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MFTMCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MFTMCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MFTMCHMID/hDCAx_PosZ"), collision.posZ(), dcaX); + // fRegistry.fill(HIST("MFTMCHMID/hDCAy_PosZ"), collision.posZ(), dcaY); + // fRegistry.fill(HIST("MFTMCHMID/hDCAx_Phi"), phi, dcaX); + // fRegistry.fill(HIST("MFTMCHMID/hDCAy_Phi"), phi, dcaY); + // } else if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // fRegistry.fill(HIST("MCHMID/hPt"), pt); + // fRegistry.fill(HIST("MCHMID/hEtaPhi"), phi, eta); + // fRegistry.fill(HIST("MCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + // fRegistry.fill(HIST("MCHMID/hDeltaPt_Pt"), pt, dpt); + // fRegistry.fill(HIST("MCHMID/hDeltaEta_Pt"), pt, deta); + // fRegistry.fill(HIST("MCHMID/hDeltaPhi_Pt"), pt, dphi); + // fRegistry.fill(HIST("MCHMID/hSign"), fwdtrack.sign()); + // fRegistry.fill(HIST("MCHMID/hNclusters"), fwdtrack.nClusters()); + // fRegistry.fill(HIST("MCHMID/hNclustersMFT"), nClustersMFT); + // fRegistry.fill(HIST("MCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + // fRegistry.fill(HIST("MCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + // fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); + // fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft / ndf_mft); + // fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + // fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + // fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); + // fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); + // fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); + // fRegistry.fill(HIST("MCHMID/hDCAxyz"), dcaXY, dcaZ); + // fRegistry.fill(HIST("MCHMID/hDCAxyinSigma"), dcaXYinSigma); + // fRegistry.fill(HIST("MCHMID/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MCHMID/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um + // fRegistry.fill(HIST("MCHMID/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um + // } + // } + return true; + } + + SliceCache cache; + Preslice perCollision = o2::aod::fwdtrack::collisionId; + Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; + PresliceUnsorted fwdtrackIndicesPerFwdTrack = aod::track_association::fwdtrackId; + PresliceUnsorted fwdtracksPerMCHTrack = aod::fwdtrack::matchMCHTrackId; + + // Filter trackFilter = o2::aod::fwdtrack::trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) || o2::aod::fwdtrack::trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack); + // using filteredMyFwdTracks = soa::Filtered; + // Partition posTracks = o2::aod::fwdtrack::signed1Pt > 0.f; + // Partition negTracks = o2::aod::fwdtrack::signed1Pt < 0.f; + + std::vector vecMuons; + + void processRec(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) + { + vecMuons.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + + auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + fillMuonInfo(collision, fwdtrack); + } + + auto pos_muons_per_col = std::views::filter(vecMuons, [](Muon muon) { return muon.sign > 0; }); + auto neg_muons_per_col = std::views::filter(vecMuons, [](Muon muon) { return muon.sign < 0; }); + + // ULS + for (const auto& pos : pos_muons_per_col) { + if (!isSelectedTight(pos)) { // pos is tag, neg is probe + continue; + } + for (const auto& neg : neg_muons_per_col) { + if (!isSelected(neg)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(pos.pt, pos.eta, pos.phi, o2::constants::physics::MassMuon); // tag + ROOT::Math::PtEtaPhiMVector v2(neg.pt, neg.eta, neg.phi, o2::constants::physics::MassMuon); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + if (neg.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (pos.matchMCHTrackId == neg.matchMCHTrackId || pos.matchMFTTrackId == neg.matchMFTTrackId) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_gl/hMvsPt"), v12.M(), v2.Pt()); + } else if (neg.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (pos.matchMCHTrackId == neg.globalIndex) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_sa/hMvsPt"), v12.M(), v2.Pt()); + } + if (pairCuts.minMass < v12.M() && v12.M() < pairCuts.maxMass) { + fillFwdTrackTable(collision, neg, fwdtracks.rawIteratorAt(neg.globalIndex)); + } + } // end of neg + } // end of pos + + // ULS + for (const auto& neg : neg_muons_per_col) { + if (!isSelectedTight(neg)) { // neg is tag, pos is probe + continue; + } + for (const auto& pos : pos_muons_per_col) { + if (!isSelected(pos)) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(neg.pt, neg.eta, neg.phi, o2::constants::physics::MassMuon); // tag + ROOT::Math::PtEtaPhiMVector v2(pos.pt, pos.eta, pos.phi, o2::constants::physics::MassMuon); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + if (pos.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (pos.matchMCHTrackId == neg.matchMCHTrackId || pos.matchMFTTrackId == neg.matchMFTTrackId) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_gl/hMvsPt"), v12.M(), v2.Pt()); + } else if (pos.trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (neg.matchMCHTrackId == pos.globalIndex) { // this should not happen in ULS. only for protection. + continue; + } + fRegistry.fill(HIST("Pair/uls/gl_sa/hMvsPt"), v12.M(), v2.Pt()); + } + if (pairCuts.minMass < v12.M() && v12.M() < pairCuts.maxMass) { + fillFwdTrackTable(collision, pos, fwdtracks.rawIteratorAt(pos.globalIndex)); + } + } // end of pos + } // end of neg + + } // end of collision loop + + vecMuons.clear(); + vecMuons.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryMuonQC, processRec, "process reconstructed info", false); + + void processRec_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&) + { + vecMuons.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + const auto& bc = collision.template bc_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + // const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + // for (const auto& fwdtrack : fwdtracks_per_coll) { + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + + // if (!fillFwdTrackTable(collision, fwdtrack, false)) { + // continue; + // } + + // } // end of fwdtrack loop + } // end of collision loop + + vecMuons.clear(); + vecMuons.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryMuonQC, processRec_SWT, "process reconstructed info only with standalone", false); + + using filteredMyFwdTracksMC = soa::Filtered; + void processMC(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&, aod::McParticles const&) + { + vecMuons.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + if (!collision.isSelected()) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + + // auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + // for (const auto& fwdtrack : fwdtracks_per_coll) { + // if (!fwdtrack.has_mcParticle()) { + // continue; + // } + // if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + // continue; + // } + + // if (!fillFwdTrackTable(collision, fwdtrack, false)) { + // continue; + // } + + // } // end of fwdtrack loop + } // end of collision loop + + vecMuons.clear(); + vecMuons.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryMuonQC, processMC, "process reconstructed and MC info", false); + + void processDummy(aod::Collisions const&) {} + PROCESS_SWITCH(skimmerPrimaryMuonQC, processDummy, "process dummy", true); +}; +struct associateAmbiguousMuon { + Produces em_amb_muon_ids; + + SliceCache cache; + PresliceUnsorted perTrack = o2::aod::emprimarymuon::fwdtrackId; + std::vector ambmuon_self_Ids; + + void process(aod::EMPrimaryMuons const& muons) + { + for (const auto& muon : muons) { + auto muons_with_same_trackId = muons.sliceBy(perTrack, muon.fwdtrackId()); + ambmuon_self_Ids.reserve(muons_with_same_trackId.size()); + for (const auto& amb_muon : muons_with_same_trackId) { + if (amb_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + ambmuon_self_Ids.emplace_back(amb_muon.globalIndex()); + } + em_amb_muon_ids(ambmuon_self_Ids); + ambmuon_self_Ids.clear(); + ambmuon_self_Ids.shrink_to_fit(); + } + } +}; + +struct associateSameMuonElement { + Produces glmuon_same_ids; + + SliceCache cache; + PresliceUnsorted perMFTTrack = o2::aod::emprimarymuon::mfttrackId; + PresliceUnsorted perMCHTrack = o2::aod::emprimarymuon::mchtrackId; + std::vector selfIds_per_MFT; + std::vector selfIds_per_MCHMID; + + // Multiple MCH-MID tracks can match with the same MFTsa. This function is to reject such global muons. + void process(aod::EMPrimaryMuons const& muons) + { + for (const auto& muon : muons) { + if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + auto muons_with_same_mfttrackId = muons.sliceBy(perMFTTrack, muon.mfttrackId()); + auto muons_with_same_mchtrackId = muons.sliceBy(perMCHTrack, muon.mchtrackId()); + selfIds_per_MFT.reserve(muons_with_same_mfttrackId.size()); + selfIds_per_MCHMID.reserve(muons_with_same_mchtrackId.size()); + // LOGF(info, "muons_with_same_mchtrackId.size() = %d, muons_with_same_mfttrackId.size() = %d", muons_with_same_mchtrackId.size(), muons_with_same_mfttrackId.size()); + + for (const auto& global_muon : muons_with_same_mfttrackId) { + // LOGF(info, "same MFT: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); + if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MFT.emplace_back(global_muon.globalIndex()); + } + } + + for (const auto& global_muon : muons_with_same_mchtrackId) { + // LOGF(info, "same MCH: global_muon.globalIndex() = %d, global_muon.mchtrackId() = %d, global_muon.mfttrackId() = %d, global_muon.collisionId() = %d", global_muon.globalIndex(), global_muon.mchtrackId(), global_muon.mfttrackId(), global_muon.collisionId()); + if (global_muon.globalIndex() == muon.globalIndex()) { // don't store myself. + continue; + } + if (global_muon.collisionId() == muon.collisionId()) { // the same global muon is repeatedly stored and associated to different collisions if FTTCA is used. + selfIds_per_MCHMID.emplace_back(global_muon.globalIndex()); + } + } + + glmuon_same_ids(selfIds_per_MCHMID, selfIds_per_MFT); + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); + } else { + glmuon_same_ids(std::vector{}, std::vector{}); // empty for standalone muons + selfIds_per_MFT.clear(); + selfIds_per_MFT.shrink_to_fit(); + selfIds_per_MCHMID.clear(); + selfIds_per_MCHMID.shrink_to_fit(); + } + } // end of muon loop + } +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-muon-qc"}), + adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-muon"}), + adaptAnalysisTask(cfgc, TaskName{"associate-same-muon-element"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx index 7dba6b78b36..bc8402d6e7a 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx @@ -15,29 +15,38 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "Common/Core/TableHelper.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/PIDResponseITS.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" - +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include #include -#include -#include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; @@ -45,19 +54,19 @@ using namespace o2::framework::expressions; using namespace o2::constants::physics; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using MyCollisions = soa::Join; -using MyCollisionsWithSWT = soa::Join; +struct skimmerPrimaryTrack { + using MyCollisions = soa::Join; + using MyCollisionsWithSWT = soa::Join; -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; -using MyTracksMC = soa::Join; -using MyTrackMC = MyTracksMC::iterator; + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; + using MyTracksMC = soa::Join; + using MyTrackMC = MyTracksMC::iterator; -struct skimmerPrimaryTrack { SliceCache cache; Preslice perCol = o2::aod::track::collisionId; Produces emprimarytracks; - // Produces prmtrackeventidtmp; + Produces prmtrackeventidtmp; // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -212,10 +221,6 @@ struct skimmerPrimaryTrack { return false; } - if (track.tpcNClsFound() < 0) { - return false; - } - if (track.tpcNClsCrossedRows() < 50) { return false; } @@ -241,16 +246,10 @@ struct skimmerPrimaryTrack { if (std::fabs(dcaXY) > dca_xy_max || std::fabs(dcaZ) > dca_z_max) { return false; } - if (std::fabs(dcaZ) > 3.f) { - return false; - } if (std::fabs(trackParCov.getEta()) > maxeta || trackParCov.getPt() < minpt || maxpt < trackParCov.getPt()) { return false; } - if (trackParCov.getPt() > 5.f) { - return false; - } return true; } @@ -258,107 +257,103 @@ struct skimmerPrimaryTrack { 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()) { - o2::dataformats::DCA mDcaInfoCov; - mDcaInfoCov.set(999, 999, 999, 999, 999); - auto trackParCov = getTrackParCov(track); - trackParCov.setPID(track.pidForTracking()); - mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); - float dcaXY = mDcaInfoCov.getY(); - float dcaZ = mDcaInfoCov.getZ(); - - float pt = trackParCov.getPt(); - float eta = trackParCov.getEta(); - float phi = trackParCov.getPhi(); - o2::math_utils::bringTo02Pi(phi); - uint16_t trackBit = 0; - - // As minimal cuts, following cuts are applied. The cut values are hardcoded on the purpose for consistent bit operation. - // has info on ITS and TPC - // a hit on ITSib any - // Ncls ITS >= 4 - // chi2/Ncls ITS < 36 - // Ncr TPC >= 50 - // chi2/Ncls TPC < 5 - // Ncr/Nf ratio in TPC > 0.8 - - if (track.itsNCls() >= 5) { - trackBit |= static_cast(RefTrackBit::kNclsITS5); - } - if (track.itsNCls() >= 6) { - trackBit |= static_cast(RefTrackBit::kNclsITS6); - } + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); + mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); - if (track.tpcNClsCrossedRows() >= 70) { - trackBit |= static_cast(RefTrackBit::kNcrTPC70); - } - if (track.tpcNClsCrossedRows() >= 90) { - trackBit |= static_cast(RefTrackBit::kNcrTPC90); - } - if (track.tpcNClsFound() >= 50) { - trackBit |= static_cast(RefTrackBit::kNclsTPC50); - } - if (track.tpcNClsFound() >= 70) { - trackBit |= static_cast(RefTrackBit::kNclsTPC70); - } - if (track.tpcNClsFound() >= 90) { - trackBit |= static_cast(RefTrackBit::kNclsTPC90); - } - if (track.tpcChi2NCl() < 4.f) { - trackBit |= static_cast(RefTrackBit::kChi2TPC4); - } - if (track.tpcChi2NCl() < 3.f) { - trackBit |= static_cast(RefTrackBit::kChi2TPC3); - } - if (track.tpcFractionSharedCls() < 0.7) { - trackBit |= static_cast(RefTrackBit::kFracSharedTPC07); - } + float pt = trackParCov.getPt(); + float eta = trackParCov.getEta(); + float phi = trackParCov.getPhi(); + phi = RecoDecay::constrainAngle(phi, 0, 1U); + uint16_t trackBit = 0; + + // As minimal cuts, following cuts are applied. The cut values are hardcoded on the purpose for consistent bit operation. + // has info on ITS and TPC + // a hit on ITSib any + // Ncls ITS >= 4 + // chi2/Ncls ITS < 36 + // Ncr TPC >= 50 + // chi2/Ncls TPC < 5 + // Ncr/Nf ratio in TPC > 0.8 + + if (track.itsNCls() >= 5) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNclsITS5)); + } + if (track.itsNCls() >= 6) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNclsITS6)); + } - if (std::fabs(dcaZ) < 0.5) { - trackBit |= static_cast(RefTrackBit::kDCAz05cm); - } - if (std::fabs(dcaZ) < 0.3) { - trackBit |= static_cast(RefTrackBit::kDCAz03cm); - } + if (track.tpcNClsCrossedRows() >= 70) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNcrTPC70)); + } + if (track.tpcNClsCrossedRows() >= 90) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNcrTPC90)); + } + if (track.tpcNClsFound() >= 50) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNclsTPC50)); + } + if (track.tpcNClsFound() >= 70) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNclsTPC70)); + } + if (track.tpcNClsFound() >= 90) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kNclsTPC90)); + } + if (track.tpcChi2NCl() < 4.f) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kChi2TPC4)); + } + if (track.tpcChi2NCl() < 3.f) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kChi2TPC3)); + } - if (std::fabs(dcaXY) < 0.5) { - trackBit |= static_cast(RefTrackBit::kDCAxy05cm); - } - if (std::fabs(dcaXY) < 0.3) { - trackBit |= static_cast(RefTrackBit::kDCAxy03cm); - } + if (track.tpcFractionSharedCls() < 0.7) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kFracSharedTPC07)); + } - emprimarytracks(collision.globalIndex(), track.globalIndex(), track.sign() / pt, eta, phi, trackBit); - // prmtrackeventidtmp(collision.globalIndex()); - - stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); - - if (fillQAHistogram) { - fRegistry.fill(HIST("Track/hPt"), pt); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt); - fRegistry.fill(HIST("Track/hEtaPhi"), phi, eta); - fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt, std::sqrt(trackParCov.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/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - } + if (std::fabs(dcaZ) < 0.5) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kDCAz05cm)); + } + if (std::fabs(dcaZ) < 0.3) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kDCAz03cm)); + } + + if (std::fabs(dcaXY) < 0.5) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kDCAxy05cm)); + } + if (std::fabs(dcaXY) < 0.3) { + SETBIT(trackBit, static_cast(o2::aod::pwgem::dilepton::utils::emtrackutil::RefTrackBit::kDCAxy03cm)); + } + + emprimarytracks(/*collision.globalIndex(),*/ /*track.globalIndex(),*/ track.sign() / pt, eta, phi, trackBit); + prmtrackeventidtmp(collision.globalIndex()); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Track/hPt"), pt); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt); + fRegistry.fill(HIST("Track/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt, std::sqrt(trackParCov.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/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); } } Preslice trackIndicesPerCollision = aod::track_association::collisionId; - std::vector> stored_trackIds; Filter trackFilter = o2::aod::track::itsChi2NCl < 36.f && o2::aod::track::tpcChi2NCl < 5.f && 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 MyFilteredTracks = soa::Filtered; @@ -366,8 +361,6 @@ struct skimmerPrimaryTrack { void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -387,16 +380,11 @@ struct skimmerPrimaryTrack { } } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryTrack, processRec, "process reconstructed info only", true); // standalone void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -420,9 +408,6 @@ struct skimmerPrimaryTrack { } } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryTrack, processRec_SWT, "process reconstructed info only", false); // standalone with swt @@ -431,8 +416,6 @@ struct skimmerPrimaryTrack { using MyFilteredTracksMC = soa::Filtered; void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) { - stored_trackIds.reserve(tracks.size()); - for (const auto& collision : collisions) { if (!collision.has_mcCollision()) { continue; @@ -455,9 +438,6 @@ struct skimmerPrimaryTrack { fillTrackTable(collision, track); } } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryTrack, processMC, "process reconstructed and MC info ", false); }; diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx index f0aa4f1e9aa..63d41fe1424 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx @@ -18,8 +18,6 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -27,21 +25,33 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include "Math/Vector4D.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include + +#include +#include +#include +#include #include #include #include diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index 70a28bfc0d2..7e04ba0aa5e 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -15,41 +15,53 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/lmeeMLTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/CollisionTypeHelper.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/Core/Zorro.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include "Math/Vector4D.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include #include +#include +#include +#include #include #include +#include #include using namespace o2; @@ -58,15 +70,18 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; +struct TreeCreatorElectronMLDDA { + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; + + using MyBCs = soa::Join; + using MyBC = MyBCs::iterator; -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; -struct TreeCreatorElectronMLDDA { SliceCache cache; Produces emprimarytracks; // flat table containing collision + track information Produces empidel; @@ -99,10 +114,10 @@ struct TreeCreatorElectronMLDDA { {"V0/hTOFbeta_P_Ka", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, {"V0/hTOFbeta_P_Pr", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"Cascade/hRxy_Xi", "R_{xy} of cascade vs. mass;m_{#Lambda#pi};R_{xy} (cm)", {HistType::kTH2F, {{200, 1.2, 1.4}, {200, 0, 20.f}}}}, - {"Cascade/hRxy_Omega", "R_{xy} of cascade vs. mass;m_{#LambdaK};R_{xy} (cm)", {HistType::kTH2F, {{200, 1.6, 1.8}, {200, 0, 20.f}}}}, - {"Cascade/hCTau_Xi", "c#tau vs. mass;m_{#Lambda#pi};c#tau (cm)", {HistType::kTH2F, {{200, 1.2, 1.4}, {200, 0, 20.f}}}}, - {"Cascade/hCTau_Omega", "c#tau vs. mass;m_{#LambdaK};c#tau (cm)", {HistType::kTH2F, {{200, 1.6, 1.8}, {200, 0, 20.f}}}}, + // {"Cascade/hRxy_Xi", "R_{xy} of cascade vs. mass;m_{#Lambda#pi};R_{xy} (cm)", {HistType::kTH2F, {{200, 1.2, 1.4}, {200, 0, 20.f}}}}, + // {"Cascade/hRxy_Omega", "R_{xy} of cascade vs. mass;m_{#LambdaK};R_{xy} (cm)", {HistType::kTH2F, {{200, 1.6, 1.8}, {200, 0, 20.f}}}}, + // {"Cascade/hCTau_Xi", "c#tau vs. mass;m_{#Lambda#pi};c#tau (cm)", {HistType::kTH2F, {{200, 1.2, 1.4}, {200, 0, 20.f}}}}, + // {"Cascade/hCTau_Omega", "c#tau vs. mass;m_{#LambdaK};c#tau (cm)", {HistType::kTH2F, {{200, 1.6, 1.8}, {200, 0, 20.f}}}}, {"Cascade/hV0CosPA", "V0 cosine of pointing angle", {HistType::kTH1F, {{100, 0.99, 1.f}}}}, {"Cascade/hV0PCA", "V0 distance between 2 legs", {HistType::kTH1F, {{50, 0.f, 0.5}}}}, {"Cascade/hCosPA", "cascade cosine of pointing angle", {HistType::kTH1F, {{100, 0.99, 1.f}}}}, @@ -126,7 +141,7 @@ struct TreeCreatorElectronMLDDA { // Operation and minimisation criteria Configurable d_bz_input{"d_bz_input", -999, "bz field, -999 is automatic"}; Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; - Configurable irSource{"irSource", "ZNC hadronic", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; + Configurable cfgApplyBCShiftTOF{"cfgApplyBCShiftTOF", true, "apply bc shift for TOF n sigma of track from v0 or cascade"}; // for zorro Configurable cfg_swt_names{"cfg_swt_names", "fHighTrackMult,fHighFt0cFv0Mult", "comma-separated software trigger names"}; @@ -153,12 +168,13 @@ struct TreeCreatorElectronMLDDA { Configurable max_p_for_downscaling_kaon{"max_p_for_downscaling_kaon", 0.0, "max p to apply down scaling factor to store kaon"}; Configurable max_p_for_downscaling_proton{"max_p_for_downscaling_proton", 2.0, "max p to apply down scaling factor to store proton"}; Configurable store_ele_band_only{"store_ele_band_only", false, "flag to store tracks around electron band only to reduce output size"}; + Configurable reject_v0leg_with_itsib{"reject_v0leg_with_itsib", false, "flag to reject v0 leg with ITSib hits"}; struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "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"}; @@ -214,8 +230,6 @@ struct TreeCreatorElectronMLDDA { Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; Configurable cfg_min_chi2its{"cfg_min_chi2its", 0.0, "min chi2/NclsITS"}; // remove ITS afterburner Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY to PV for v0 legs in cm"}; - Configurable cfg_includeITSsa{"cfg_includeITSsa", false, "Flag to include ITSsa tracks"}; - Configurable cfg_max_pt_itssa{"cfg_max_pt_itssa", 0.15, "mix pt for ITSsa track"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -5, "min n sigma e in TPC"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +5, "max n sigma e in TPC"}; @@ -301,12 +315,15 @@ struct TreeCreatorElectronMLDDA { o2::dataformats::DCA mDcaInfoCov; o2::aod::rctsel::RCTFlagsChecker rctChecker; ctpRateFetcher mRateFetcher; + std::string irSourceForCptFetcher{""}; Zorro zorro; + Service mTOFResponse; + std::mt19937 engine; std::uniform_real_distribution dist01; - void init(InitContext&) + void init(InitContext& initContext) { mRunNumber = 0; d_bz = 0; @@ -316,6 +333,9 @@ struct TreeCreatorElectronMLDDA { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + LOGF(info, "intializing TOFResponse"); + mTOFResponse->initSetup(ccdb, initContext); + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); if (useMatCorrType == 1) { @@ -334,7 +354,8 @@ struct TreeCreatorElectronMLDDA { dist01 = std::uniform_real_distribution(0.0f, 1.0f); } - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + template + void initCCDB(TBC const& bc) { if (mRunNumber == bc.runNumber()) { return; @@ -393,6 +414,16 @@ struct TreeCreatorElectronMLDDA { 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"; } + + o2::parameters::GRPLHCIFData* grplhcif = ccdb.service->getSpecificForRun("GLO/Config/GRPLHCIF", bc.runNumber()); + auto collsys = o2::common::core::CollisionSystemType::getCollisionTypeFromGrp(grplhcif); + if (collsys == o2::common::core::CollisionSystemType::kCollSyspp || collsys == o2::common::core::CollisionSystemType::kCollSysOO) { + irSourceForCptFetcher = std::string("T0VTX"); + } else { + irSourceForCptFetcher = std::string("ZNC hadronic"); + } + LOGF(info, "irSourceForCptFetcher = %s", irSourceForCptFetcher.data()); + mRunNumber = bc.runNumber(); } @@ -417,7 +448,7 @@ struct TreeCreatorElectronMLDDA { template bool isSelectedV0Leg(TCollision const& collision, TTrack const& track) { - if (!track.hasITS()) { + if (!track.hasITS() || !track.hasTPC()) { return false; } @@ -431,29 +462,23 @@ struct TreeCreatorElectronMLDDA { return false; } - if (!v0cuts.cfg_includeITSsa && (!track.hasITS() || !track.hasTPC())) { + if (track.tpcNClsCrossedRows() < v0cuts.cfg_min_ncrossedrows_tpc) { return false; } - - if (track.hasTPC()) { - if (track.tpcNClsCrossedRows() < v0cuts.cfg_min_ncrossedrows_tpc) { - return false; - } - if (track.tpcNClsFound() < v0cuts.cfg_min_ncluster_tpc) { - return false; - } - if (track.tpcChi2NCl() > v0cuts.cfg_max_chi2tpc) { - return false; - } - if (track.tpcCrossedRowsOverFindableCls() < v0cuts.cfg_min_cr2findable_ratio_tpc) { - return false; - } - if (track.tpcFractionSharedCls() > v0cuts.cfg_max_frac_shared_clusters_tpc) { - return false; - } - if (track.tpcNClsPID() < v0cuts.cfg_min_ncluster_tpc_pid) { - return false; - } + if (track.tpcNClsFound() < v0cuts.cfg_min_ncluster_tpc) { + return false; + } + if (track.tpcChi2NCl() > v0cuts.cfg_max_chi2tpc) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < v0cuts.cfg_min_cr2findable_ratio_tpc) { + return false; + } + if (track.tpcFractionSharedCls() > v0cuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } + if (track.tpcNClsPID() < v0cuts.cfg_min_ncluster_tpc_pid) { + return false; } mDcaInfoCov.set(999, 999, 999, 999, 999); @@ -473,10 +498,6 @@ struct TreeCreatorElectronMLDDA { return false; } - if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && v0cuts.cfg_max_pt_itssa < track.pt()) { - return true; - } - return true; } @@ -536,89 +557,105 @@ struct TreeCreatorElectronMLDDA { return true; } - template - bool isElectron(TTrack const& track) + template + bool isElectron(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { - if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { - return true; - } + float tofNSigmaEl = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Electron)]; bool is_El_TPC = v0cuts.cfg_min_TPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < v0cuts.cfg_max_TPCNsigmaEl; - bool is_El_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < v0cuts.cfg_max_TOFNsigmaEl : true; // TOFif + bool is_El_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaEl < tofNSigmaEl && tofNSigmaEl < v0cuts.cfg_max_TOFNsigmaEl : true; // TOFif return is_El_TPC && is_El_TOF; } - template - bool isPion(TTrack const& track) + template + bool isPion(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { - if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { - return true; - } + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Pion)]; bool is_Pi_TPC = v0cuts.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0cuts.cfg_max_TPCNsigmaPi; - bool is_Pi_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaPi < track.tofNSigmaPi() && track.tofNSigmaPi() < v0cuts.cfg_max_TOFNsigmaPi : true; // TOFif + bool is_Pi_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < v0cuts.cfg_max_TOFNsigmaPi : true; // TOFif return is_Pi_TPC && is_Pi_TOF; } - template - bool isKaon(TTrack const& track) + template + bool isKaon(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { - if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { - return true; - } + float tofNSigmaKa = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Kaon)]; bool is_Ka_TPC = v0cuts.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < v0cuts.cfg_max_TPCNsigmaKa; - bool is_Ka_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < v0cuts.cfg_max_TOFNsigmaKa : true; // TOFif + bool is_Ka_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaKa < tofNSigmaKa && tofNSigmaKa < v0cuts.cfg_max_TOFNsigmaKa : true; // TOFif return is_Ka_TPC && is_Ka_TOF; } - template - bool isProton(TTrack const& track) + template + bool isProton(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { - if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { - return true; - } + float tofNSigmaPr = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Proton)]; bool is_Pr_TPC = v0cuts.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < v0cuts.cfg_max_TPCNsigmaPr; - bool is_Pr_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaPr < track.tofNSigmaPr() && track.tofNSigmaPr() < v0cuts.cfg_max_TOFNsigmaPr : true; // TOFif + bool is_Pr_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < v0cuts.cfg_max_TOFNsigmaPr : true; // TOFif return is_Pr_TPC && is_Pr_TOF; } - template - bool isElectronTight(TTrack const& track) + template + bool isElectronTight(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { + float tofNSigmaEl = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Electron)]; bool is_El_TPC = tightv0cuts.cfg_min_TPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < tightv0cuts.cfg_max_TPCNsigmaEl; - bool is_El_TOF = track.hasTOF() ? tightv0cuts.cfg_min_TOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < tightv0cuts.cfg_max_TOFNsigmaEl : true; // TOFif + bool is_El_TOF = track.hasTOF() ? tightv0cuts.cfg_min_TOFNsigmaEl < tofNSigmaEl && tofNSigmaEl < tightv0cuts.cfg_max_TOFNsigmaEl : true; // TOFif return is_El_TPC && is_El_TOF; } - template - bool isPionTight(TTrack const& track) + template + bool isPionTight(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { + float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Pion)]; bool is_Pi_TPC = tightv0cuts.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < tightv0cuts.cfg_max_TPCNsigmaPi; - bool is_Pi_TOF = track.hasTOF() ? tightv0cuts.cfg_min_TOFNsigmaPi < track.tofNSigmaPi() && track.tofNSigmaPi() < tightv0cuts.cfg_max_TOFNsigmaPi : true; // TOFif + bool is_Pi_TOF = track.hasTOF() ? tightv0cuts.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < tightv0cuts.cfg_max_TOFNsigmaPi : true; // TOFif + return is_Pi_TPC && is_Pi_TOF; + } + + bool isPionTight(const float tpcNSigmaPi, const float tofNSigmaPi, const bool hasTOF) + { + bool is_Pi_TPC = tightv0cuts.cfg_min_TPCNsigmaPi < tpcNSigmaPi && tpcNSigmaPi < tightv0cuts.cfg_max_TPCNsigmaPi; + bool is_Pi_TOF = hasTOF ? tightv0cuts.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < tightv0cuts.cfg_max_TOFNsigmaPi : true; // TOFif return is_Pi_TPC && is_Pi_TOF; } - template - bool isProtonTight(TTrack const& track) + template + bool isProtonTight(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) { + float tofNSigmaPr = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Proton)]; bool is_Pr_TPC = tightv0cuts.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < tightv0cuts.cfg_max_TPCNsigmaPr; - bool is_Pr_TOF = track.hasTOF() ? tightv0cuts.cfg_min_TOFNsigmaPr < track.tofNSigmaPr() && track.tofNSigmaPr() < tightv0cuts.cfg_max_TOFNsigmaPr : true; // TOFif + bool is_Pr_TOF = track.hasTOF() ? tightv0cuts.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < tightv0cuts.cfg_max_TOFNsigmaPr : true; // TOFif return is_Pr_TPC && is_Pr_TOF; } - template - bool isPionTightTOFreq(TTrack const& track) + bool isProtonTight(const float tpcNSigmaPr, const float tofNSigmaPr, const bool hasTOF) { - // only for K0S-> pi+ pi- - bool is_Pi_TPC = tightv0cuts.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < tightv0cuts.cfg_max_TPCNsigmaPi; - bool is_Pi_TOF = tightv0cuts.cfg_min_TOFNsigmaPi < track.tofNSigmaPi() && track.tofNSigmaPi() < tightv0cuts.cfg_max_TOFNsigmaPi && std::fabs(track.tofChi2()) < tightv0cuts.cfg_max_chi2tof; // TOFreq - return is_Pi_TPC && is_Pi_TOF; + bool is_Pr_TPC = tightv0cuts.cfg_min_TPCNsigmaPr < tpcNSigmaPr && tpcNSigmaPr < tightv0cuts.cfg_max_TPCNsigmaPr; + bool is_Pr_TOF = hasTOF ? tightv0cuts.cfg_min_TOFNsigmaPr < tofNSigmaPr && tofNSigmaPr < tightv0cuts.cfg_max_TOFNsigmaPr : true; // TOFif + return is_Pr_TPC && is_Pr_TOF; } + // template + // bool isPionTightTOFreq(TCollision const& collision, TTrack const& track, o2::track::PID::ID id) + // { + // float tofNSigmaPi = mapTOFNSigma[std::make_tuple(collision.globalIndex(), track.globalIndex(), id, o2::track::PID::Pion)]; + // bool is_Pi_TPC = tightv0cuts.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < tightv0cuts.cfg_max_TPCNsigmaPi; + // bool is_Pi_TOF = tightv0cuts.cfg_min_TOFNsigmaPi < tofNSigmaPi && tofNSigmaPi < tightv0cuts.cfg_max_TOFNsigmaPi && std::fabs(track.tofChi2()) < tightv0cuts.cfg_max_chi2tof; // TOFreq + // return is_Pi_TPC && is_Pi_TOF; + // } + template - void fillTrackTable(TCollision const& collision, TTrack const& track, const uint8_t pidlabel, const float hadronicRate) + void fillTrackTable(TCollision const& collision, TTrack const& track, const uint8_t pidlabel, const std::array tofNSigmas, const float beta, const float hadronicRate) { - if (store_ele_band_only && !isElectron(track)) { + bool is_El_TPC = v0cuts.cfg_min_TPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < v0cuts.cfg_max_TPCNsigmaEl; + bool is_El_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaEl < tofNSigmas[0] && tofNSigmas[0] < v0cuts.cfg_max_TOFNsigmaEl : true; // TOFif + if (store_ele_band_only && !(is_El_TPC && is_El_TOF)) { + return; + } + + if (reject_v0leg_with_itsib && track.itsNClsInnerBarrel() > 0) { return; } + mDcaInfoCov.set(999, 999, 999, 999, 999); auto trackParCov = getTrackParCov(track); // trackParCov.setPID(track.pidForTracking()); @@ -681,13 +718,13 @@ struct TreeCreatorElectronMLDDA { track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcNClsPID(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), - track.beta(), + beta, track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), pidlabel); - empidel(track.tpcNSigmaEl(), track.tofNSigmaEl()); - empidpi(track.tpcNSigmaPi(), track.tofNSigmaPi()); - empidka(track.tpcNSigmaKa(), track.tofNSigmaKa()); - empidpr(track.tpcNSigmaPr(), track.tofNSigmaPr()); + empidel(track.tpcNSigmaEl(), tofNSigmas[0]); + empidpi(track.tpcNSigmaPi(), tofNSigmas[1]); + empidka(track.tpcNSigmaKa(), tofNSigmas[2]); + empidpr(track.tpcNSigmaPr(), tofNSigmas[3]); stored_trackIds.emplace_back(track.globalIndex()); } @@ -775,6 +812,326 @@ struct TreeCreatorElectronMLDDA { return true; } + template + float recalculateTOFNSigmaTrackFromV0FromCascade(TCollision const& collision, TCascade const& cascade, const float massCascade, float& beta) + { + if (mapCollisionTime.find(cascade.collisionId()) == mapCollisionTime.end()) { + beta = -1.f; + return -999.f; + } + + auto track = sign > 0 ? cascade.template posTrack_as() : cascade.template negTrack_as(); + auto arrMomTrack = sign > 0 ? std::array{cascade.pxpos(), cascade.pypos(), cascade.pzpos()} : std::array{cascade.pxneg(), cascade.pyneg(), cascade.pzneg()}; + + if (!track.hasTOF() || !track.has_collision()) { + beta = -1.f; + return -999.f; + } + auto bcCascade = collision.template bc_as(); // collision in this function is the collision where this cascade belong. + + o2::track::TrackPar trackPar = o2::track::TrackPar({cascade.xlambda(), cascade.ylambda(), cascade.zlambda()}, arrMomTrack, sign, false); + auto collisionTrack = track.template collision_as(); + auto bcTrack = collisionTrack.template bc_as(); + double deltaTime = track.tofSignalInAnotherBC(bcTrack.globalBC(), bcCascade.globalBC()) - timeCascade(collision, cascade, massCascade) - timeV0inCascade(cascade); // in ps + + const o2::math_utils::Point3D trackVertex{collisionTrack.posX(), collisionTrack.posY(), collisionTrack.posZ()}; + o2::track::TrackLTIntegral ltIntegral; + bool successPropag = o2::base::Propagator::Instance()->propagateToDCA(trackVertex, trackPar, d_bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, nullptr, <Integral); + if (!successPropag) { + beta = -1.f; + return -999.f; + } + + float length = track.length() - ltIntegral.getL(); + if (length < 0.f) { + beta = -1.f; + return -999.f; + } + + beta = length / (deltaTime - mapCollisionTime[cascade.collisionId()]) / (TMath::C() * 1e+2 * 1e-12); + return mTOFResponse->nSigma(deltaTime, track.tofExpMom(), length, trackPar.getP(), trackPar.getEta(), mapCollisionTime[cascade.collisionId()], mapCollisionTimeError[cascade.collisionId()]); + } + + template + float recalculateTOFNSigmaBachelorFromCascade(TCollision const& collision, TCascade const& cascade, const float massCascade, float& beta) + { + if (mapCollisionTime.find(cascade.collisionId()) == mapCollisionTime.end()) { + beta = -1.f; + return -999.f; + } + + auto bachelor = cascade.template bachelor_as(); + if (!bachelor.hasTOF() || !bachelor.has_collision()) { + beta = -1.f; + return -999.f; + } + + auto bcCascade = collision.template bc_as(); // collision in this function is the collision where this cascade belong. + auto collisionBachelor = bachelor.template collision_as(); + auto bcBachelor = collisionBachelor.template bc_as(); + double deltaTime = bachelor.tofSignalInAnotherBC(bcBachelor.globalBC(), bcCascade.globalBC()) - timeCascade(collision, cascade, massCascade); // in ps + + o2::track::TrackPar bTrackPar = o2::track::TrackPar({cascade.x(), cascade.y(), cascade.z()}, {cascade.pxbach(), cascade.pybach(), cascade.pzbach()}, cascade.sign(), false); // at SV + const o2::math_utils::Point3D trackVertex{collisionBachelor.posX(), collisionBachelor.posY(), collisionBachelor.posZ()}; + o2::track::TrackLTIntegral ltIntegral; + bool successPropag = o2::base::Propagator::Instance()->propagateToDCA(trackVertex, bTrackPar, d_bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, nullptr, <Integral); + if (!successPropag) { + beta = -1.f; + return -999.f; + } + + float length = bachelor.length() - ltIntegral.getL(); + if (length < 0.f) { + beta = -1.f; + return -999.f; + } + + beta = length / (deltaTime - mapCollisionTime[cascade.collisionId()]) / (TMath::C() * 1e+2 * 1e-12); + return mTOFResponse->nSigma(deltaTime, bachelor.tofExpMom(), length, bTrackPar.getP(), bTrackPar.getEta(), mapCollisionTime[cascade.collisionId()], mapCollisionTimeError[cascade.collisionId()]); + } + + template + float recalculateTOFNSigmaLegFromV0(TCollision const& collision, TV0 const& v0, const float massV0, float& beta) + { + if (mapCollisionTime.find(v0.collisionId()) == mapCollisionTime.end()) { + beta = -1.f; + return -999.f; + } + + auto track = sign > 0 ? v0.template posTrack_as() : v0.template negTrack_as(); + if (!track.hasTOF() || !track.has_collision()) { + beta = -1.f; + return -999.f; + } + + auto bcV0 = collision.template bc_as(); // collision in this function is the collision where this v0 belong. + auto arrMomTrack = sign > 0 ? std::array{v0.pxpos(), v0.pypos(), v0.pzpos()} : std::array{v0.pxneg(), v0.pyneg(), v0.pzneg()}; + + auto collisionTrack = track.template collision_as(); + auto bcTrack = collisionTrack.template bc_as(); + double deltaTime = track.tofSignalInAnotherBC(bcTrack.globalBC(), bcV0.globalBC()) - timeV0(collision, v0, massV0); // in ps + + o2::track::TrackPar trackPar = o2::track::TrackPar({v0.x(), v0.y(), v0.z()}, arrMomTrack, track.sign(), false); // at SV + const o2::math_utils::Point3D trackVertex{collisionTrack.posX(), collisionTrack.posY(), collisionTrack.posZ()}; + o2::track::TrackLTIntegral ltIntegral; + bool successPropag = o2::base::Propagator::Instance()->propagateToDCA(trackVertex, trackPar, d_bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, nullptr, <Integral); + if (!successPropag) { + beta = -1.f; + return -999.f; + } + + float length = track.length() - ltIntegral.getL(); // in cm + if (length < 0.f) { + beta = -1.f; + return -999.f; + } + beta = length / (deltaTime - mapCollisionTime[v0.collisionId()]) / (TMath::C() * 1e+2 * 1e-12); + return mTOFResponse->nSigma(deltaTime, track.tofExpMom(), length, trackPar.getP(), trackPar.getEta(), mapCollisionTime[v0.collisionId()], mapCollisionTimeError[v0.collisionId()]); + + // use nSigma from O2Physics/Common/Core/PID/PIDTOFParamService.h + // static float nSigma(const float tofSignal, + // const float tofExpMom, + // const float length, + // const float momentum, + // const float eta, + // const float tofEvTime, + // const float tofEvTimeErr, + // const o2::pid::tof::TOFResoParamsV3& params = parameters); + } + + template + float timeV0inCascade(TCascade const& cascade) + { + float p = RecoDecay::sqrtSumOfSquares(cascade.pxlambda(), cascade.pylambda(), cascade.pzlambda()); + float length = std::hypot(cascade.xlambda() - cascade.x(), cascade.ylambda() - cascade.y(), cascade.zlambda() - cascade.z()); // cm + float velocity = TMath::C() * 1e+2 * 1e-12 * std::sqrt((p * p) / (p * p + o2::constants::physics::MassLambda * o2::constants::physics::MassLambda)); // cm/ps + return length / velocity; // ps + } + + template + float timeCascade(TCollision const& collision, TCascade const& cascade, const float massCascade) + { + float length = std::hypot(cascade.x() - collision.posX(), cascade.y() - collision.posY(), cascade.z() - collision.posZ()); // cm + float velocity = TMath::C() * 1e+2 * 1e-12 * std::sqrt((cascade.p() * cascade.p()) / (cascade.p() * cascade.p() + massCascade * massCascade)); // cm/ps + return length / velocity; // ps + } + + template + float timeV0(TCollision const& collision, TV0 const& v0, const float massV0) + { + float length = std::hypot(v0.x() - collision.posX(), v0.y() - collision.posY(), v0.z() - collision.posZ()); // cm + float velocity = TMath::C() * 1e+2 * 1e-12 * std::sqrt((v0.p() * v0.p()) / (v0.p() * v0.p() + massV0 * massV0)); // cm/ps + return length / velocity; // ps + } + + template + void calculateTOFNSigmasForV0sAndCascades(TCollisions const& collisions, TBCs const&, TV0s const& v0s, TCascades const& cascades, TTracks const& tracks) + { + for (const auto& track : tracks) { + if (mapCollisionTime.find(track.collisionId()) == mapCollisionTime.end()) { + mapCollisionTime[track.collisionId()] = track.tofEvTime(); + mapCollisionTimeError[track.collisionId()] = track.tofEvTimeErr(); + } + } // end of track loop + + for (const auto& collision : collisions) { + if (!isSelectedEvent(collision)) { + continue; + } + if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + + auto v0s_coll = v0s.sliceBy(perCollision_v0, collision.globalIndex()); + for (const auto& v0 : v0s_coll) { + auto pos = v0.template posTrack_as(); + auto neg = v0.template negTrack_as(); + + if (v0.dcaV0daughters() > v0cuts.cfg_max_dcadau) { + continue; + } + if (v0.v0cosPA() < v0cuts.cfg_min_cospa) { + continue; + } + if (pos.sign() * neg.sign() > 0) { + continue; + } + if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg)) { + continue; + } + + float beta = -1.f; + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : pos.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : pos.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassPhoton, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassKaonNeutral, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaLegFromV0(collision, v0, o2::constants::physics::MassLambda, beta) : neg.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : neg.beta(); + + } // end of v0 loop + + auto cascades_coll = cascades.sliceBy(perCollision_cascade, collision.globalIndex()); + for (const auto& cascade : cascades_coll) { + // Track casting + auto bachelor = cascade.template bachelor_as(); + auto pos = cascade.template posTrack_as(); + auto neg = cascade.template negTrack_as(); + if (pos.sign() * neg.sign() > 0) { + continue; + } + + if (!(cascadecuts.cfg_min_mass_lambda < cascade.mLambda() && cascade.mLambda() < cascadecuts.cfg_max_mass_lambda)) { + continue; + } + + if (cascade.cascradius() > cascade.v0radius()) { + continue; + } + + if (cascade.dcaV0daughters() > cascadecuts.cfg_max_dcadau_v0) { + continue; + } + if (cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadecuts.cfg_min_cospa_v0) { + continue; + } + if (cascade.v0radius() < cascadecuts.cfg_min_rxy_v0) { + continue; + } + + if (cascade.cascradius() < cascadecuts.cfg_min_rxy) { + continue; + } + + if (cascade.dcacascdaughters() > cascadecuts.cfg_max_dcadau) { + continue; + } + if (cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadecuts.cfg_min_cospa) { + continue; + } + + if (cascade.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascadecuts.cfg_min_dcaxy_v0) { + continue; + } + + if (!isSelectedV0LegTight(collision, pos) || !isSelectedV0LegTight(collision, neg) || !isSelectedV0Leg(collision, bachelor)) { + continue; + } + + float beta = -1.f; + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : bachelor.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::XiMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaEl(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaPi(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaKa(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? recalculateTOFNSigmaBachelorFromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : bachelor.tofNSigmaPr(); + mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)] = cfgApplyBCShiftTOF ? beta : bachelor.beta(); + + } // end of cascade loop + } // end of collision loop + } + + std::map, float> mapTOFNSigma; // map -> tof n sigma + std::map, float> mapTOFBeta; // map -> tof beta + //! 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. Filter v0Filter = o2::aod::v0data::v0Type == uint8_t(1) && o2::aod::v0data::v0cosPA > v0cuts.cfg_min_cospa&& o2::aod::v0data::dcaV0daughters v0cuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::v0data::dcanegtopv) > v0cuts.cfg_min_dcaxy_v0leg; using filteredV0s = soa::Filtered; @@ -782,53 +1139,55 @@ struct TreeCreatorElectronMLDDA { Filter cascadeFilter = o2::aod::cascdata::dcacascdaughters < cascadecuts.cfg_max_dcadau && nabs(o2::aod::cascdata::dcanegtopv) > cascadecuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::cascdata::dcanegtopv) > cascadecuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::cascdata::dcabachtopv) > cascadecuts.cfg_min_dcaxy_bachelor; using filteredCascades = soa::Filtered; - Filter collisionFilter_track_occupancy = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_ft0c_occupancy = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; - Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::evsel::sel8 == true; - using filteredMyCollisions = soa::Filtered; + // Filter collisionFilter_track_occupancy = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + // Filter collisionFilter_ft0c_occupancy = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + // Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + // Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::evsel::sel8 == true; + // using filteredMyCollisions = soa::Filtered; Preslice perCollision_v0 = o2::aod::v0data::collisionId; Preslice perCollision_cascade = o2::aod::cascdata::collisionId; Preslice perCollision_track = o2::aod::track::collisionId; - Partition posTracks = o2::aod::track::signed1Pt > 0.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; - Partition negTracks = o2::aod::track::signed1Pt < 0.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; std::vector stored_trackIds; - void processPID(filteredMyCollisions const& collisions, aod::BCsWithTimestamps const&, filteredV0s const& v0s, filteredCascades const& cascades, MyTracks const& tracks) + std::unordered_map mapCollisionTime; + std::unordered_map mapCollisionTimeError; + + // please don't apply Filter to collisions and tracks. + void processPID(MyCollisions const& collisions, MyBCs const& bcs, filteredV0s const& v0s, filteredCascades const& cascades, MyTracks const& tracks) { + initCCDB(bcs.iteratorAt(0)); + mTOFResponse->processSetup(bcs.iteratorAt(0)); // call this after initCCDB. + + calculateTOFNSigmasForV0sAndCascades(collisions, bcs, v0s, cascades, tracks); + stored_trackIds.reserve(tracks.size()); for (const auto& collision : collisions) { registry.fill(HIST("Event/hEventCounter"), 1.0); // all - auto bc = collision.template foundBC_as(); + auto bc = collision.template foundBC_as(); initCCDB(bc); if (!isSelectedEvent(collision)) { continue; } - - if (cfgUseZorro && !zorro.isSelected(bc.globalBC(), bcMarginForSoftwareTrigger)) { + if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + if (cfgUseZorro && !zorro.isSelected(bc.globalBC(), bcMarginForSoftwareTrigger)) { continue; } registry.fill(HIST("Event/hEventCounter"), 2.0); // selected registry.fill(HIST("Event/hNumContrib"), collision.numContrib()); - float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3; // kHz + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSourceForCptFetcher) * 1.e-3; // kHz auto v0s_coll = v0s.sliceBy(perCollision_v0, collision.globalIndex()); for (const auto& v0 : v0s_coll) { - // auto o2v0 = v0.template v0_as(); auto pos = v0.template posTrack_as(); auto neg = v0.template negTrack_as(); // LOGF(info, "v0.globalIndex() = %d, v0.collisionId() = %d, v0.posTrackId() = %d, v0.negTrackId() = %d", v0.globalIndex(), v0.collisionId(), v0.posTrackId(), v0.negTrackId()); - // LOGF(info, "is pos ITSsa = %d", pos.hasITS() && !pos.hasTPC() && !pos.hasTRD() && !pos.hasTOF()); - // LOGF(info, "is neg ITSsa = %d", neg.hasITS() && !neg.hasTPC() && !neg.hasTRD() && !neg.hasTOF()); if (v0.dcaV0daughters() > v0cuts.cfg_max_dcadau) { continue; @@ -850,65 +1209,98 @@ struct TreeCreatorElectronMLDDA { if (v0cuts.cfg_min_qt_strangeness < v0.qtarm()) { if (v0cuts.cfg_min_qt_k0s < v0.qtarm()) { if (!(v0cuts.cfg_min_mass_lambda_veto < v0.mLambda() && v0.mLambda() < v0cuts.cfg_max_mass_lambda_veto) && !(v0cuts.cfg_min_mass_lambda_veto < v0.mAntiLambda() && v0.mAntiLambda() < v0cuts.cfg_max_mass_lambda_veto)) { - if ((isPionTightTOFreq(pos) && isSelectedV0LegTight(collision, pos)) && (isPion(neg) && isSelectedV0Leg(collision, neg))) { + // if ((isPionTightTOFreq(collision, pos, o2::track::PID::K0) && isSelectedV0LegTight(collision, pos)) && (isPion(collision, neg, o2::track::PID::K0) && isSelectedV0Leg(collision, neg))) { + if ((isPionTight(collision, pos, o2::track::PID::K0) && isSelectedV0LegTight(collision, pos)) && (isPion(collision, neg, o2::track::PID::K0) && isSelectedV0Leg(collision, neg))) { registry.fill(HIST("V0/hMassK0Short"), v0.mK0Short()); if (v0cuts.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s) { registry.fill(HIST("V0/hTPCdEdx_P_Pi"), neg.tpcInnerParam(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pi"), neg.tpcInnerParam(), neg.beta()); - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), hadronicRate); + registry.fill(HIST("V0/hTOFbeta_P_Pi"), neg.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)]}; + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)], hadronicRate); } } - if (isPion(pos) && isSelectedV0Leg(collision, pos) && isPionTightTOFreq(neg) && isSelectedV0LegTight(collision, neg)) { + + // if (isPion(collision, pos, o2::track::PID::K0) && isSelectedV0Leg(collision, pos) && isPionTightTOFreq(collision, neg, o2::track::PID::K0) && isSelectedV0LegTight(collision, neg)) { + if (isPion(collision, pos, o2::track::PID::K0) && isSelectedV0Leg(collision, pos) && isPionTight(collision, neg, o2::track::PID::K0) && isSelectedV0LegTight(collision, neg)) { registry.fill(HIST("V0/hMassK0Short"), v0.mK0Short()); if (v0cuts.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s) { registry.fill(HIST("V0/hTPCdEdx_P_Pi"), pos.tpcInnerParam(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.tpcInnerParam(), pos.beta()); - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), hadronicRate); + registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Proton)]}; + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::K0, o2::track::PID::Pion)], hadronicRate); } } } // end of K0S } if (!(v0cuts.cfg_min_mass_k0s_veto < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s_veto)) { - if (isProton(pos) && isSelectedV0Leg(collision, pos) && isPionTight(neg) && isSelectedV0LegTight(collision, neg)) { + if (isProton(collision, pos, o2::track::PID::Lambda) && isSelectedV0Leg(collision, pos) && isPionTight(collision, neg, o2::track::PID::Lambda) && isSelectedV0LegTight(collision, neg)) { registry.fill(HIST("V0/hMassLambda"), v0.mLambda()); if (v0cuts.cfg_min_mass_lambda < v0.mLambda() && v0.mLambda() < v0cuts.cfg_max_mass_lambda) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), hadronicRate); registry.fill(HIST("V0/hTPCdEdx_P_Pr"), pos.tpcInnerParam(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.tpcInnerParam(), pos.beta()); + registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)]}; + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)], hadronicRate); } } // end of Lambda - if (isPionTight(pos) && isSelectedV0LegTight(collision, pos) && isProton(neg) && isSelectedV0Leg(collision, neg)) { + if (isPionTight(collision, pos, o2::track::PID::Lambda) && isSelectedV0LegTight(collision, pos) && isProton(collision, neg, o2::track::PID::Lambda) && isSelectedV0Leg(collision, neg)) { registry.fill(HIST("V0/hMassAntiLambda"), v0.mAntiLambda()); if (v0cuts.cfg_min_mass_lambda < v0.mAntiLambda() && v0.mAntiLambda() < v0cuts.cfg_max_mass_lambda) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), hadronicRate); registry.fill(HIST("V0/hTPCdEdx_P_Pr"), neg.tpcInnerParam(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.tpcInnerParam(), neg.beta()); + registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)]}; + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Lambda, o2::track::PID::Proton)], hadronicRate); } } // end of AntiLambda } } // end of stangeness - if (isElectronTight(pos) && isSelectedV0LegTight(collision, pos) && isElectron(neg) && isSelectedV0Leg(collision, neg)) { + if (isElectronTight(collision, pos, o2::track::PID::Photon) && isSelectedV0LegTight(collision, pos) && isElectron(collision, neg, o2::track::PID::Photon) && isSelectedV0Leg(collision, neg)) { registry.fill(HIST("V0/hMassGamma"), v0.mGamma()); registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); if (v0cuts.cfg_min_mass_photon < v0.mGamma() && v0.mGamma() < v0cuts.cfg_max_mass_photon) { registry.fill(HIST("V0/hXY_Gamma"), v0.x(), v0.y()); - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), hadronicRate); registry.fill(HIST("V0/hTPCdEdx_P_El"), neg.tpcInnerParam(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_El"), neg.tpcInnerParam(), neg.beta()); + registry.fill(HIST("V0/hTOFbeta_P_El"), neg.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)]}; + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), neg.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)], hadronicRate); } } // end of photon conversion - if (isElectron(pos) && isSelectedV0Leg(collision, pos) && isElectronTight(neg) && isSelectedV0LegTight(collision, neg)) { + if (isElectron(collision, pos, o2::track::PID::Photon) && isSelectedV0Leg(collision, pos) && isElectronTight(collision, neg, o2::track::PID::Photon) && isSelectedV0LegTight(collision, neg)) { registry.fill(HIST("V0/hMassGamma"), v0.mGamma()); registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); if (v0cuts.cfg_min_mass_photon < v0.mGamma() && v0.mGamma() < v0cuts.cfg_max_mass_photon) { registry.fill(HIST("V0/hXY_Gamma"), v0.x(), v0.y()); - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), hadronicRate); registry.fill(HIST("V0/hTPCdEdx_P_El"), pos.tpcInnerParam(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_El"), pos.tpcInnerParam(), pos.beta()); + registry.fill(HIST("V0/hTOFbeta_P_El"), pos.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Proton)]}; + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), pos.globalIndex(), o2::track::PID::Photon, o2::track::PID::Electron)], hadronicRate); } } // end of photon conversion @@ -924,16 +1316,6 @@ struct TreeCreatorElectronMLDDA { continue; } - if (bachelor.sign() < 0) { // Omega- -> L + K- -> p + pi- + K- - if (!isProtonTight(pos) || !isPionTight(neg)) { - continue; - } - } else { // Omegabar+ -> Lbar + K+ -> pbar + pi+ + K+ - if (!isProtonTight(neg) || !isPionTight(pos)) { - continue; - } - } - if (!(cascadecuts.cfg_min_mass_lambda < cascade.mLambda() && cascade.mLambda() < cascadecuts.cfg_max_mass_lambda)) { continue; } @@ -971,42 +1353,74 @@ struct TreeCreatorElectronMLDDA { continue; } + float beta = -1.f; + float tofNSigmaPiPosFromLambdaFromXi = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : pos.tofNSigmaPi(); + float tofNSigmaPrPosFromLambdaFromXi = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : pos.tofNSigmaPr(); + float tofNSigmaPiNegFromLambdaFromXi = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : neg.tofNSigmaPi(); + float tofNSigmaPrNegFromLambdaFromXi = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassXiMinus, beta) : neg.tofNSigmaPr(); + + float tofNSigmaPiPosFromLambdaFromOmega = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : pos.tofNSigmaPi(); + float tofNSigmaPrPosFromLambdaFromOmega = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : pos.tofNSigmaPr(); + float tofNSigmaPiNegFromLambdaFromOmega = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : neg.tofNSigmaPi(); + float tofNSigmaPrNegFromLambdaFromOmega = cfgApplyBCShiftTOF ? recalculateTOFNSigmaTrackFromV0FromCascade(collision, cascade, o2::constants::physics::MassOmegaMinus, beta) : neg.tofNSigmaPr(); + registry.fill(HIST("Cascade/hMassLambda"), cascade.mLambda()); registry.fill(HIST("Cascade/hV0PCA"), cascade.dcaV0daughters()); registry.fill(HIST("Cascade/hV0CosPA"), cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); registry.fill(HIST("Cascade/hPCA"), cascade.dcacascdaughters()); // distance between bachelor and V0. registry.fill(HIST("Cascade/hCosPA"), cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - float length = std::sqrt(std::pow(cascade.x() - collision.posX(), 2) + std::pow(cascade.y() - collision.posY(), 2) + std::pow(cascade.z() - collision.posZ(), 2)); - float mom = cascade.p(); - float ctauXi = length / mom * o2::constants::physics::MassXiMinus; // 4.91 cm in PDG - float ctauOmega = length / mom * o2::constants::physics::MassOmegaMinus; // 2.46 cm in PDG + // float length = std::sqrt(std::pow(cascade.x() - collision.posX(), 2) + std::pow(cascade.y() - collision.posY(), 2) + std::pow(cascade.z() - collision.posZ(), 2)); + // float mom = cascade.p(); + // float ctauXi = length / mom * o2::constants::physics::MassXiMinus; // 4.91 cm in PDG + // float ctauOmega = length / mom * o2::constants::physics::MassOmegaMinus; // 2.46 cm in PDG + + bool isLaProtonPiMinusFromXiMinus = isPionTight(neg.tpcNSigmaPi(), tofNSigmaPiNegFromLambdaFromXi, neg.hasTOF()) && isProtonTight(pos.tpcNSigmaPr(), tofNSigmaPrPosFromLambdaFromXi, pos.hasTOF()); + bool isALaAPrPiPlusFromXiPlus = isPionTight(pos.tpcNSigmaPi(), tofNSigmaPiPosFromLambdaFromXi, pos.hasTOF()) && isProtonTight(neg.tpcNSigmaPr(), tofNSigmaPrNegFromLambdaFromXi, neg.hasTOF()); - if (isPion(bachelor)) { + if (isPion(collision, bachelor, o2::track::PID::XiMinus) && (cascade.sign() < 0 ? isLaProtonPiMinusFromXiMinus : isALaAPrPiPlusFromXiPlus)) { registry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); registry.fill(HIST("Cascade/hMassPt_Xi"), cascade.mXi(), cascade.pt()); - registry.fill(HIST("Cascade/hRxy_Xi"), cascade.mXi(), cascade.cascradius()); - registry.fill(HIST("Cascade/hCTau_Xi"), cascade.mXi(), ctauXi); + // registry.fill(HIST("Cascade/hRxy_Xi"), cascade.mXi(), cascade.cascradius()); + // registry.fill(HIST("Cascade/hCTau_Xi"), cascade.mXi(), ctauXi); } - if (!(cascadecuts.cfg_min_mass_Xi_veto < cascade.mXi() && cascade.mXi() < cascadecuts.cfg_max_mass_Xi_veto) && isKaon(bachelor)) { // reject Xi candidates - registry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); - registry.fill(HIST("Cascade/hMassPt_Omega"), cascade.mOmega(), cascade.pt()); - registry.fill(HIST("Cascade/hRxy_Omega"), cascade.mOmega(), cascade.cascradius()); - registry.fill(HIST("Cascade/hCTau_Omega"), cascade.mOmega(), ctauOmega); - if (cascadecuts.cfg_min_mass_Omega < cascade.mOmega() && cascade.mOmega() < cascadecuts.cfg_max_mass_Omega) { // select Omega candidates - registry.fill(HIST("V0/hTPCdEdx_P_Ka"), bachelor.tpcInnerParam(), bachelor.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.tpcInnerParam(), bachelor.beta()); - fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon), hadronicRate); + + bool isLaProtonPiMinusFromOmegaMinus = isPionTight(neg.tpcNSigmaPi(), tofNSigmaPiNegFromLambdaFromOmega, neg.hasTOF()) && isProtonTight(pos.tpcNSigmaPr(), tofNSigmaPrPosFromLambdaFromOmega, pos.hasTOF()); + bool isALaAPrPiPlusFromOmegaPlus = isPionTight(pos.tpcNSigmaPi(), tofNSigmaPiPosFromLambdaFromOmega, pos.hasTOF()) && isProtonTight(neg.tpcNSigmaPr(), tofNSigmaPrNegFromLambdaFromOmega, neg.hasTOF()); + + if (!(cascadecuts.cfg_min_mass_Xi_veto < cascade.mXi() && cascade.mXi() < cascadecuts.cfg_max_mass_Xi_veto)) { // reject Xi candidates + if (isKaon(collision, bachelor, o2::track::PID::OmegaMinus) && (cascade.sign() < 0 ? isLaProtonPiMinusFromOmegaMinus : isALaAPrPiPlusFromOmegaPlus)) { + registry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); + registry.fill(HIST("Cascade/hMassPt_Omega"), cascade.mOmega(), cascade.pt()); + // registry.fill(HIST("Cascade/hRxy_Omega"), cascade.mOmega(), cascade.cascradius()); + // registry.fill(HIST("Cascade/hCTau_Omega"), cascade.mOmega(), ctauOmega); + if (cascadecuts.cfg_min_mass_Omega < cascade.mOmega() && cascade.mOmega() < cascadecuts.cfg_max_mass_Omega) { // select Omega candidates + registry.fill(HIST("V0/hTPCdEdx_P_Ka"), bachelor.tpcInnerParam(), bachelor.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.tpcInnerParam(), mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)]); + std::array tofNSigmas{ + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Electron)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Pion)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)], + mapTOFNSigma[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Proton)]}; + fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon), tofNSigmas, mapTOFBeta[std::make_tuple(collision.globalIndex(), bachelor.globalIndex(), o2::track::PID::OmegaMinus, o2::track::PID::Kaon)], hadronicRate); + } } } } // end of cascade loop } // end of collision loop stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); + + mapCollisionTime.clear(); + mapCollisionTimeError.clear(); + + mapTOFNSigma.clear(); + mapTOFBeta.clear(); + } // end of process // please choose only 1 process function. - void processDummy(filteredMyCollisions const&) {} + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(TreeCreatorElectronMLDDA, processPID, "produce ML input for single track level", true); // this is for eID with ITSsa. e/pi/k/p are selected by TOF, and these can be used for ITS-TPC PID. PROCESS_SWITCH(TreeCreatorElectronMLDDA, processDummy, "process dummy", false); @@ -1087,6 +1501,7 @@ struct MLTrackQC { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + o2::pid::tof::TOFResponseImpl::metadataInfo.initMetadata(cfgc); return WorkflowSpec{ adaptAnalysisTask(cfgc, TaskName{"tree-creator-ele-ml-dda"}), adaptAnalysisTask(cfgc, TaskName{"ml-track-qc"})}; diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx new file mode 100644 index 00000000000..9ece7b19407 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/treeCreatorMuonML.cxx @@ -0,0 +1,468 @@ +// 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 will create data table for inputs to machine learning for electrons. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/lmeeMLTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/CollisionTypeHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::constants::physics; +using namespace o2::aod::fwdtrackutils; + +struct TreeCreatorMuonML { + using MyCollisionsMC = soa::Join; + using MyCollisionMC = MyCollisionsMC::iterator; + + using MyFwdTracksMC = soa::Join; + using MyFwdTrackMC = MyFwdTracksMC::iterator; + + using MyMFTTracksMC = soa::Join; + using MyMFTTrackMC = MyMFTTracksMC::iterator; + + Produces mltable; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + // Configurable irSource{"irSource", "ZNC hadronic", "Estimator of the interaction rate (Recommended: pp/OO --> T0VTX, Pb-Pb --> ZNC hadronic)"}; + + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; + Configurable cfgDownSampling{"cfgDownSampling", 1.1, "down sampling for fake matches"}; + + struct : ConfigurableGroup { + std::string prefix = "eventCutGroup"; + Configurable cfgMinZvtx{"cfgMinZvtx", -10.f, "min. Zvtx of collision"}; + Configurable cfgMaxZvtx{"cfgMaxZvtx", +10.f, "max. Zvtx of collision"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border"}; + 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"}; + } eventCutGroup; + + struct : ConfigurableGroup { + std::string prefix = "glMuonCutGroup"; + Configurable minEta{"minEta", -3.6, "min. eta acceptance for MFT-MCH-MID"}; + Configurable maxEta{"maxEta", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 100.f, "max. chi2 for MCH-MFT matching"}; + Configurable maxChi2{"maxChi2", 20.f, "max. chi2 for global muon"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + } glMuonCutGroup; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + std::mt19937 engine; + std::uniform_real_distribution dist01; + + ctpRateFetcher mRateFetcher; + std::string irSourceForCptFetcher{""}; + + int mRunNumber = 0; + float mBz = 0; + float mZShift = 0; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view muon_types[5] = {"MFTMCHMID/", "MFTMCHMIDOtherMatch/", "MFTMCH/", "MCHMID/", "MCH/"}; + + void init(InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + + addHistograms(); + + mRunNumber = 0; + mBz = 0; + mZShift = 0; + + std::random_device seed_gen; + engine = std::mt19937(seed_gen()); + dist01 = std::uniform_real_distribution(0.0f, 1.0f); + } + + 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(); + const double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + mBz = field->getBz(centerMFT); // Get field at centre of MFT + LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } + + o2::parameters::GRPLHCIFData* grplhcif = ccdb.service->getSpecificForRun("GLO/Config/GRPLHCIF", bc.runNumber()); + auto collsys = o2::common::core::CollisionSystemType::getCollisionTypeFromGrp(grplhcif); + if (collsys == o2::common::core::CollisionSystemType::kCollSyspp || collsys == o2::common::core::CollisionSystemType::kCollSysOO) { + irSourceForCptFetcher = std::string("T0VTX"); + } else { + irSourceForCptFetcher = std::string("ZNC hadronic"); + } + LOGF(info, "irSourceForCptFetcher = %s", irSourceForCptFetcher.data()); + } + + void addHistograms() + { + auto hMuonType = fRegistry.add("hMuonType", "muon type", kTH1F, {{5, -0.5f, 4.5f}}, false); + 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("MFTMCHMID/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {60, -5.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {60, -5.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/hDeltaPt_Pt", "#Deltap_{T}/p_{T} vs. p_{T};p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl}", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hDeltaEta_Pt", "#Delta#eta vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hDeltaPhi_Pt", "#Delta#varphi vs. p_{T};p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hDeltaEtaAtMP_Pt", "#Delta#eta vs. p_{T} at MP;p_{T}^{gl} (GeV/c);#Delta#eta", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hDeltaPhiAtMP_Pt", "#Delta#varphi vs. p_{T} at MP;p_{T}^{gl} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hSign", "sign;sign", kTH1F, {{3, -1.5, +1.5}}, false); + fRegistry.add("MFTMCHMID/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); + fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); + fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); + fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1, 1}, {200, -1, +1}}, false); + fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); + fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); + fRegistry.add("MFTMCHMID/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{100, 0, 1}, {200, -0.1, 0.1}}, false); + fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("MFTMCHMID/hDCAx_PosZ", "DCAx vs. posZ;Z_{vtx} (cm);DCA_{x} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAy_PosZ", "DCAy vs. posZ;Z_{vtx} (cm);DCA_{y} (cm)", kTH2F, {{200, -10, +10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAx_Phi", "DCAx vs. #varphi;#varphi (rad.);DCA_{x} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hDCAy_Phi", "DCAy vs. #varphi;#varphi (rad.);DCA_{y} (cm)", kTH2F, {{90, 0, 2 * M_PI}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFTMCHMID/hNmu", "#mu multiplicity;N_{#mu} per collision", kTH1F, {{21, -0.5, 20.5}}, false); + fRegistry.add("MFTMCHMID/hdR_Chi2MatchMCHMFT", "dr vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;#DeltaR", kTH2F, {{200, 0, 50}, {200, 0, 0.5}}, false); + fRegistry.add("MFTMCHMID/hdR_Chi2", "dr vs. chi2;global chi2/ndf;#DeltaR", kTH2F, {{100, 0, 10}, {200, 0, 0.5}}, false); + fRegistry.add("MFTMCHMID/hChi2_Chi2MatchMCHMFT", "chi2 vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;global chi2/ndf", kTH2F, {{200, 0, 50}, {100, 0, 10}}, false); + + fRegistry.addClone("MFTMCHMID/", "MCHMID/"); + fRegistry.add("MFTMCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + fRegistry.add("MFTMCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + fRegistry.add("MFTMCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 500}}, false); + fRegistry.add("MCHMID/hDCAxResolutionvsPt", "DCA_{x} vs. p_{T};p_{T} (GeV/c);DCA_{x} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + fRegistry.add("MCHMID/hDCAyResolutionvsPt", "DCA_{y} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + fRegistry.add("MCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); + } + + template + bool isSelectedCollision(TCollision const& collision) + { + if (!(eventCutGroup.cfgMinZvtx < collision.posZ() && collision.posZ() < eventCutGroup.cfgMaxZvtx)) { + return false; + } + if (eventCutGroup.cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + if (eventCutGroup.cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (eventCutGroup.cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if (eventCutGroup.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (eventCutGroup.cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + return true; + } + + template + bool fillFwdTrackTable(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const&, TMFTTracks const&, TMFTTracksCov const& mftCovs, const float hadronicRate) + { + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + return false; + } + + auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + if (!mfttrack.has_mcParticle() || !mchtrack.has_mcParticle() || !fwdtrack.has_mcParticle()) { + return false; + } + float chi2 = fwdtrack.chi2() / (2.f * (mchtrack.nClusters() + mfttrack.nClusters()) - 5.f); + float chi2mft = mfttrack.chi2() / (2.f * mfttrack.nClusters() - 5.f); + + // auto mcParticle_MFTMCHMID = fwdtrack.template mcParticle_as(); // this is identical to mcParticle_MCHMID + auto mcParticle_MCHMID = mchtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID + auto mcParticle_MFT = mfttrack.template mcParticle_as(); + + int pdgCode = mcParticle_MCHMID.pdgCode(); + bool isPrimary = mcParticle_MCHMID.isPhysicalPrimary() || mcParticle_MCHMID.producedByGenerator(); + bool isMatched = (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) && (mcParticle_MFT.mcCollisionId() == mcParticle_MCHMID.mcCollisionId()); + + if (!isMatched && dist01(engine) > cfgDownSampling) { + return false; + } + + if (fwdtrack.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return false; + } + if (fwdtrack.chi2MatchMCHMFT() < 0.f || glMuonCutGroup.maxMatchingChi2MCHMFT < fwdtrack.chi2MatchMCHMFT()) { // this should never happen. only for protection. + return false; + } + if (fwdtrack.chi2() < 0.f || glMuonCutGroup.maxChi2 < chi2) { // this should never happen. only for protection. + return false; + } + if (mfttrack.chi2() < 0.f) { // this should never happen. only for protection. + return false; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, glMuonCutGroup.matchingZ, mBz, mZShift); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + // o2::math_utils::bringTo02Pi(phi); + phi = RecoDecay::constrainAngle(phi, 0, 1U); + + if (eta < glMuonCutGroup.minEta || glMuonCutGroup.maxEta < eta) { + return false; + } + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + // float dcaZ = propmuonAtPV.getZ() - collision.posZ(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, glMuonCutGroup.matchingZ, mBz, mZShift); + float ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + // o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + phiMatchedMCHMID = RecoDecay::constrainAngle(phiMatchedMCHMID, 0, 1U); + if (glMuonCutGroup.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, glMuonCutGroup.matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = mchtrack.p() * dcaXY_Matched; + float rAtAbsorberEnd = fwdtrack.rAtAbsorberEnd(); // this works only for GlobalMuonTrack + + float xMatchedMFTatMP = 999.f; + float yMatchedMFTatMP = 999.f; + float xMatchedMCHMIDatMP = 999.f; + float yMatchedMCHMIDatMP = 999.f; + + if constexpr (withMFTCov) { + auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); + o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwdShift(mfttrack, mZShift, mfttrackcov); // values at innermost update + mftsaAtMP.propagateToZhelix(glMuonCutGroup.matchingZ, mBz); // propagated to matching plane + xMatchedMFTatMP = mftsaAtMP.getX(); + yMatchedMFTatMP = mftsaAtMP.getY(); + + auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, glMuonCutGroup.matchingZ, mBz, mZShift); // propagated to matching plane + xMatchedMCHMIDatMP = muonAtMP.getX(); + yMatchedMCHMIDatMP = muonAtMP.getY(); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + + mltable(collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), hadronicRate, + fwdtrack.trackType(), pt, eta, phi, fwdtrack.sign(), dcaX, dcaY, ptMatchedMCHMID, etaMatchedMCHMID, phiMatchedMCHMID, + xMatchedMCHMIDatMP, yMatchedMCHMIDatMP, xMatchedMFTatMP, yMatchedMFTatMP, + fwdtrack.nClusters(), pDCA, rAtAbsorberEnd, chi2, fwdtrack.chi2MatchMCHMID(), fwdtrack.chi2MatchMCHMFT(), + // fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), + mfttrack.mftClusterSizesAndTrackFlags(), chi2mft, mfttrack.nClusters(), pdgCode, isPrimary, isMatched, + mcParticle_MCHMID.pt(), mcParticle_MCHMID.eta(), mcParticle_MCHMID.phi()); + + fRegistry.fill(HIST("hMuonType"), fwdtrack.trackType()); + fRegistry.fill(HIST("MFTMCHMID/hPt"), pt); + fRegistry.fill(HIST("MFTMCHMID/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFTMCHMID/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); + fRegistry.fill(HIST("MFTMCHMID/hDeltaEta_Pt"), pt, deta); + fRegistry.fill(HIST("MFTMCHMID/hDeltaPhi_Pt"), pt, dphi); + fRegistry.fill(HIST("MFTMCHMID/hSign"), fwdtrack.sign()); + fRegistry.fill(HIST("MFTMCHMID/hNclusters"), fwdtrack.nClusters()); + fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), mfttrack.nClusters()); + fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); + fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); + fRegistry.fill(HIST("MFTMCHMID/hChi2"), chi2); + fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MFTMCHMID/hDCAx_PosZ"), collision.posZ(), dcaX); + fRegistry.fill(HIST("MFTMCHMID/hDCAy_PosZ"), collision.posZ(), dcaY); + fRegistry.fill(HIST("MFTMCHMID/hDCAx_Phi"), phi, dcaX); + fRegistry.fill(HIST("MFTMCHMID/hDCAy_Phi"), phi, dcaY); + return true; + } + + SliceCache cache; + Preslice perCollision = o2::aod::fwdtrack::collisionId; + + std::unordered_map map_mfttrackcovs; + void processWithMFTCov(MyCollisionsMC const& collisions, aod::BCsWithTimestamps const&, MyFwdTracksMC const& fwdtracks, MyMFTTracksMC const& mfttracks, aod::MFTTracksCov const& mftCovs, aod::McParticles const&, aod::McCollisions const&) + { + for (const auto& mfttrackConv : mftCovs) { + map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + } + + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.has_mcCollision()) { + continue; + } + + if (!isSelectedCollision(collision)) { + continue; + } + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSourceForCptFetcher) * 1.e-3; // kHz + + auto fwdtracks_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_coll) { + if (!fwdtrack.has_mcParticle()) { + continue; + } + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + continue; + } + + fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, mftCovs, hadronicRate); + + } // end of fwdtrack loop + } // end of collision loop + + map_mfttrackcovs.clear(); + } + PROCESS_SWITCH(TreeCreatorMuonML, processWithMFTCov, "produce ML input for single track level", true); + + void processWithoutMFTCov(MyCollisionsMC const& collisions, aod::BCsWithTimestamps const&, MyFwdTracksMC const& fwdtracks, MyMFTTracksMC const& mfttracks, aod::McParticles const&, aod::McCollisions const&) + { + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.has_mcCollision()) { + continue; + } + + if (!isSelectedCollision(collision)) { + continue; + } + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSourceForCptFetcher) * 1.e-3; // kHz + + auto fwdtracks_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_coll) { + if (!fwdtrack.has_mcParticle()) { + continue; + } + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + continue; + } + + fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, nullptr, hadronicRate); + + } // end of fwdtrack loop + } // end of collision loop + } + PROCESS_SWITCH(TreeCreatorMuonML, processWithoutMFTCov, "produce ML input for single track level", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"tree-creator-muon-ml"})}; +} diff --git a/PWGEM/Dilepton/Tasks/CMakeLists.txt b/PWGEM/Dilepton/Tasks/CMakeLists.txt index 6ed13cb96b9..a32c3768bd5 100644 --- a/PWGEM/Dilepton/Tasks/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/CMakeLists.txt @@ -40,6 +40,16 @@ o2physics_add_dpl_workflow(create-resolution-map PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(create-resolution-map-derived + SOURCES createResolutionMapDerived.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(test-bremsstrahlung + SOURCES testBremsstrahlung.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(table-reader-barrel SOURCES tableReaderBarrel.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2Physics::PWGDQCore @@ -52,12 +62,12 @@ o2physics_add_dpl_workflow(event-qc o2physics_add_dpl_workflow(single-electron-qc SOURCES singleElectronQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils 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 + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(single-muon-qc @@ -72,12 +82,12 @@ o2physics_add_dpl_workflow(single-muon-qc-mc o2physics_add_dpl_workflow(dielectron SOURCES dielectron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dielectron-mc SOURCES dielectronMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dimuon @@ -92,7 +102,7 @@ o2physics_add_dpl_workflow(dimuon-mc o2physics_add_dpl_workflow(prefilter-dielectron SOURCES prefilterDielectron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(associate-mccollision-to-collision @@ -117,12 +127,12 @@ o2physics_add_dpl_workflow(tagging-hfe o2physics_add_dpl_workflow(dielectron-hadron-mpc SOURCES dielectronHadronMPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dimuon-hadron-mpc SOURCES dimuonHadronMPC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(mc-particle-predictions-otf @@ -144,3 +154,13 @@ o2physics_add_dpl_workflow(dilepton-polarization SOURCES dileptonPolarization.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(check-mc-template + SOURCES checkMCTemplate.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(check-mc-pair-template + SOURCES checkMCPairTemplate.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMDileptonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/Dilepton/Tasks/MCtemplates.cxx b/PWGEM/Dilepton/Tasks/MCtemplates.cxx index 3288bd2745e..d44dd156c62 100644 --- a/PWGEM/Dilepton/Tasks/MCtemplates.cxx +++ b/PWGEM/Dilepton/Tasks/MCtemplates.cxx @@ -13,29 +13,39 @@ // // Analysis task to generate Monte Carlo templates of different heavy-flavour dielectron sources // -#include -#include -#include -#include -#include -#include -#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/AnalysisCut.h" #include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" #include "PWGDQ/Core/MCSignal.h" #include "PWGDQ/Core/MCSignalLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -using std::cout; -using std::endl; +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + using std::string; using namespace o2; @@ -480,8 +490,8 @@ struct AnalysisSameEventPairing { } fBarrelHistNamesMCmatched.emplace_back(mcSigClasses); } // end loop over cuts - } // end if(cutNames.IsNull()) - } // end if processBarrel + } // end if(cutNames.IsNull()) + } // end if processBarrel // Add histogram classes for each specified MCsignal at the generator level // TODO: create a std::vector of hist classes to be used at Fill time, to avoid using Form in the process function @@ -577,7 +587,7 @@ struct AnalysisSameEventPairing { } } } // end loop over barrel track pairs - } // end runPairing + } // end runPairing template void runMCGenPair(TTracksMC const& groupedMCTracks) @@ -609,7 +619,7 @@ struct AnalysisSameEventPairing { } } } // end of true pairing loop - } // end runMCGen + } // end runMCGen // skimmed PresliceUnsorted perReducedMcEvent = aod::reducedtrackMC::reducedMCeventId; diff --git a/PWGEM/Dilepton/Tasks/associateMCcollision.cxx b/PWGEM/Dilepton/Tasks/associateMCcollision.cxx index eb0e7d3bf5c..9d66de55cd5 100644 --- a/PWGEM/Dilepton/Tasks/associateMCcollision.cxx +++ b/PWGEM/Dilepton/Tasks/associateMCcollision.cxx @@ -14,11 +14,21 @@ // This code produces a table with an index between mc collision and rec. collision. // Please write to: daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx new file mode 100644 index 00000000000..91ec19cdacd --- /dev/null +++ b/PWGEM/Dilepton/Tasks/checkMCPairTemplate.cxx @@ -0,0 +1,3339 @@ +// 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 + +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::constants::physics; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; +using namespace o2::aod::pwgem::dilepton::utils::pairutil; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCCollisions = soa::Join; +using MyMCCollision = MyMCCollisions::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 checkMCPairTemplate { + + // 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"}; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; + Configurable cfgFillUnfolding{"cfgFillUnfolding", false, "flag to fill histograms for unfolding"}; + Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + Configurable cfgFillSeparateCharmHadronPairs{"cfgFillSeparateCharmHadronPairs", false, "flag to fill different ccbar pairs separately"}; + Configurable cfgFillSeparateBeautyHadronPairs{"cfgFillSeparateBeautyHadronPairs", false, "flag to fill different bbbar pairs separately"}; + + 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 ConfDPtBins{"ConfDPtBins", {220, -1.0, +10.0}, "dpt bins for output histograms"}; + ConfigurableAxis ConfDCAllNarrowBins{"ConfDCAllNarrowBins", {200, 0.0, 10.0}, "narrow DCAll bins for output histograms"}; + ConfigurableAxis ConfTrackDCA{"ConfTrackDCA", {VARIABLE_WIDTH, -10, -9, -8, -7, -6, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.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.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "DCA binning for single tacks"}; + + ConfigurableAxis ConfYllBins{"ConfYllBins", {1, -1.f, +1.f}, "yll 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. + + Configurable cfg_nbin_dphi_ee{"cfg_nbin_dphi_ee", 1, "number of bins for dphi_ee"}; // 36 + Configurable cfg_nbin_deta_ee{"cfg_nbin_deta_ee", 1, "number of bins for deta_ee"}; // 40 + // Configurable cfg_nbin_cos_theta_cs{"cfg_nbin_cos_theta_cs", 1, "number of bins for cos theta cs"}; // 10 + // Configurable cfg_nbin_phi_cs{"cfg_nbin_phi_cs", 1, "number of bins for phi cs"}; // 10 + Configurable cfg_nbin_aco{"cfg_nbin_aco", 1, "number of bins for acoplanarity"}; // 10 + Configurable cfg_nbin_asym_pt{"cfg_nbin_asym_pt", 1, "number of bins for pt asymmetry"}; // 10 + Configurable cfg_nbin_dphi_e_ee{"cfg_nbin_dphi_e_ee", 1, "number of bins for dphi_ee_e"}; // 18 + ConfigurableAxis ConfPolarizationCosThetaBins{"ConfPolarizationCosThetaBins", {1, -1.f, 1.f}, "cos(theta) bins for polarization analysis"}; + ConfigurableAxis ConfPolarizationPhiBins{"ConfPolarizationPhiBins", {1, -M_PI, M_PI}, "phi bins for polarization analysis"}; + Configurable cfgPolarizationFrame{"cfgPolarizationFrame", 0, "frame of polarization. 0:CS, 1:HX, else:FATAL"}; + ConfigurableAxis ConfPolarizationQuadMomBins{"ConfPolarizationQuadMomBins", {1, -0.5, 1}, "quadrupole moment bins for polarization analysis"}; // quardrupole moment <(3 x cos^2(theta) -1)/2> + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + // for RCT + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + } 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_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_phiv{"cfg_min_phiv", 0.0, "min phiv (constant)"}; + Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv (constant)"}; + Configurable cfg_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut at PV"}; + Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 electrons (elliptic cut)"}; + Configurable cfg_min_dphi{"cfg_min_dphi", 0.2, "min dphi between 2 electrons (elliptic cut)"}; + Configurable cfg_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; + Configurable cfg_max_opang{"cfg_max_opang", 6.4, "max opening angle"}; + Configurable cfg_require_diff_sides{"cfg_require_diff_sides", false, "flag to require 2 tracks are from different sides."}; + + Configurable cfg_apply_cuts_from_prefilter{"cfg_apply_cuts_from_prefilter", false, "flag to apply prefilter set when producing derived data"}; + Configurable cfg_prefilter_bits{"cfg_prefilter_bits", 0, "prefilter bits [kNone : 0, kElFromPC : 1, kElFromPi0_20MeV : 2, kElFromPi0_40MeV : 4, kElFromPi0_60MeV : 8, kElFromPi0_80MeV : 16, kElFromPi0_100MeV : 32, kElFromPi0_120MeV : 64, kElFromPi0_140MeV : 128] Please consider logical-OR among them."}; // see PairUtilities.h + + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply phiv cut inherited from prefilter"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kMee : 1, kPhiV : 2, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "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.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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.2, "max dca XY for single track in cm"}; + Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "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_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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "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", -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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; + + // configuration for PID ML + Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + 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_apply_detadphi{"cfg_apply_detadphi", false, "flag to apply deta-dphi elliptic cut"}; + Configurable cfg_min_deta{"cfg_min_deta", 0.02, "min deta between 2 muons (elliptic cut)"}; + Configurable cfg_min_dphi{"cfg_min_dphi", 0.02, "min dphi between 2 muons (elliptic cut)"}; + + Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter set in derived data"}; + Configurable cfg_prefilter_bits_derived{"cfg_prefilter_bits_derived", 0, "prefilter bits [kNone : 0, kSplitOrMergedTrackLS : 4, kSplitOrMergedTrackULS : 8] Please consider logical-OR among them."}; // see PairUtilities.h + + 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_max_pt_track{"cfg_max_pt_track", 1e+10, "max 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+6, "max chi2/ndf"}; + Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "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"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + Configurable rejectWrongMatch{"rejectWrongMatch", false, "flag to reject wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + } dimuoncuts; + + o2::aod::rctsel::RCTFlagsChecker rctChecker; + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + 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 for generated single lepton"}; + Configurable max_mcPt{"max_mcPt", 1e+10, "max. MC pT for generated single lepton"}; + Configurable min_mcEta{"min_mcEta", -0.8, "max. MC eta for generated single lepton"}; + Configurable max_mcEta{"max_mcEta", +0.8, "max. MC eta for generated single lepton"}; + } mctrackcuts; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_cut_types[2] = {"before/", "after/"}; + static constexpr std::string_view pair_sign_types[3] = {"uls/", "lspp/", "lsmm/"}; + static constexpr std::string_view dilepton_source_types[23] = { + "sm/Photon/", // 0 + "sm/PromptPi0/", // 1 + "sm/NonPromptPi0/", // 2 + "sm/Eta/", // 3 + "sm/EtaPrime/", // 4 + "sm/Rho/", // 5 + "sm/Omega/", // 6 + "sm/Phi/", // 7 + "sm/PromptJPsi/", // 8 + "sm/NonPromptJPsi/", // 9 + "sm/PromptPsi2S/", // 10 + "sm/NonPromptPsi2S/", // 11 + "sm/Upsilon1S/", // 12 + "sm/Upsilon2S/", // 13 + "sm/Upsilon3S/", // 14 + "ccbar/c2l_c2l/", // 15 + "bbbar/b2l_b2l/", // 16 + "bbbar/b2c2l_b2c2l/", // 17 + "bbbar/b2c2l_b2l_sameb/", // 18 + "bbbar/b2c2l_b2l_diffb/", // 19 + "bbbar/b2cc2l_b2c2l/", // 20 + "bbbar/b2cc2l_b2cc2l/", // 21 + "bbbar/b2cc2ll/", // 22 + }; // unordered_map is better, but cannot be constexpr. + static constexpr std::string_view unfolding_dilepton_source_types[3] = {"sm/", "ccbar/", "bbbar/"}; + + ~checkMCPairTemplate() {} + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms(&fRegistry); + fRegistry.add("MCEvent/before/hZvtx", "mc vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry.add("MCEvent/before/hZvtx_rec", "rec. mc vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry.addClone("MCEvent/before/", "MCEvent/after/"); + + 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)"; + 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 (cfgDCAType == 1) { + pair_dca_axis_title = "DCA_{ee}^{XY} (#sigma)"; + } else if (cfgDCAType == 2) { + pair_dca_axis_title = "DCA_{ee}^{Z} (#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_y_axis_title = "y_{#mu#mu}"; + 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_y{ConfYllBins, pair_y_axis_title}; + const AxisSpec axis_dca{ConfDCAllBins, pair_dca_axis_title}; + const AxisSpec axis_pt_meson{ConfPtllBins, "p_{T}^{VM} (GeV/c)"}; // for omega, phi meson pT spectra + const AxisSpec axis_y_meson{ConfYllBins, "y^{VM}"}; // for omega, phi meson pT spectra + + const AxisSpec axis_dca_narrow{ConfDCAllNarrowBins, pair_dca_axis_title}; + const AxisSpec axis_dpt{ConfDPtBins, "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} (GeV/c)"}; + const AxisSpec axis_dca_track1{ConfTrackDCA, "DCA_{e,1}^{Z} (#sigma)"}; + const AxisSpec axis_dca_track2{ConfTrackDCA, "DCA_{e,2}^{Z} (#sigma)"}; + + std::string frameName = "CS"; + if (cfgPolarizationFrame == 0) { + frameName = "CS"; + } else if (cfgPolarizationFrame == 1) { + frameName = "HX"; + } else { + LOG(fatal) << "set 0 or 1 to cfgPolarizationFrame!"; + } + + const AxisSpec axis_dphi_ee{cfg_nbin_dphi_ee, -M_PI / 2., 3. / 2. * M_PI, "#Delta#varphi = #varphi_{l1} - #varphi_{l2} (rad.)"}; // for kHFll + const AxisSpec axis_deta_ee{cfg_nbin_deta_ee, -2., 2., "#Delta#eta = #eta_{l1} - #eta_{l2}"}; // for kHFll + const AxisSpec axis_cos_theta_pol{ConfPolarizationCosThetaBins, Form("cos(#theta^{%s})", frameName.data())}; // for kPolarization, kUPC + const AxisSpec axis_phi_pol{ConfPolarizationPhiBins, Form("#varphi^{%s} (rad.)", frameName.data())}; // for kPolarization + const AxisSpec axis_quadmom{ConfPolarizationQuadMomBins, Form("#frac{3 cos^{2}(#theta^{%s}) -1}{2}", frameName.data())}; // for kPolarization + const AxisSpec axis_aco{cfg_nbin_aco, 0, 1.f, "#alpha = 1 - #frac{|#varphi_{l^{+}} - #varphi_{l^{-}}|}{#pi}"}; // for kUPC + const AxisSpec axis_asym_pt{cfg_nbin_asym_pt, 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{cfg_nbin_dphi_e_ee, 0, M_PI, "#Delta#varphi = #varphi_{l} - #varphi_{ll} (rad.)"}; // for kUPC + + // generated info + fRegistry.add("Generated/sm/PromptPi0/uls/hs", "gen. dilepton", kTHnSparseD, {axis_mass, axis_pt}, true); + fRegistry.addClone("Generated/sm/PromptPi0/uls/", "Generated/sm/PromptPi0/lspp/"); + fRegistry.addClone("Generated/sm/PromptPi0/uls/", "Generated/sm/PromptPi0/lsmm/"); + + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/NonPromptPi0/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Eta/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/EtaPrime/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Rho/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Omega/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Omega2ll/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Phi/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Phi2ll/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/PromptJPsi/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/NonPromptJPsi/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/PromptPsi2S/"); + fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/NonPromptPsi2S/"); + // fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Upsilon1S/"); + // fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Upsilon2S/"); + // fRegistry.addClone("Generated/sm/PromptPi0/", "Generated/sm/Upsilon3S/"); + + fRegistry.add("Generated/ccbar/c2l_c2l/uls/hs", "generated dilepton", kTHnSparseD, {axis_mass, axis_pt}, true); + fRegistry.addClone("Generated/ccbar/c2l_c2l/uls/", "Generated/ccbar/c2l_c2l/lspp/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/uls/", "Generated/ccbar/c2l_c2l/lsmm/"); + + 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 + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2cc2l_b2c2l/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2cc2l_b2cc2l/"); + + // for charmed hadrons // create 28 combinations + static constexpr std::string_view charmed_mesons[] = {"Dplus", "D0", "Dsplus"}; // 411, 421, 431 + static constexpr std::string_view anti_charmed_mesons[] = {"Dminus", "D0bar", "Dsminus"}; + const int nm_c = sizeof(charmed_mesons) / sizeof(charmed_mesons[0]); + static constexpr std::string_view charmed_baryons[] = {"Lcplus", "Xicplus", "Xic0", "Omegac0"}; // 4122, 4232, 4132, 4332 + static constexpr std::string_view anti_charmed_baryons[] = {"Lcminus", "Xicminus", "Xic0bar", "Omegac0bar"}; + const int nb_c = sizeof(charmed_baryons) / sizeof(charmed_baryons[0]); + static constexpr std::string_view sum_charmed_mesons[] = {"Dpm", "D0", "Dspm"}; + static constexpr std::string_view sum_charmed_baryons[] = {"Lcpm", "Xicpm", "Xic0", "Omegac0"}; + + if (cfgFillSeparateCharmHadronPairs) { + for (int im = 0; im < nm_c; im++) { + fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/ccbar/%s_%s/", charmed_mesons[im].data(), anti_charmed_mesons[im].data())); + } + for (int ib = 0; ib < nb_c; ib++) { + fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/ccbar/%s_%s/", charmed_baryons[ib].data(), anti_charmed_baryons[ib].data())); + } + for (int im1 = 0; im1 < nm_c - 1; im1++) { + for (int im2 = im1 + 1; im2 < nm_c; im2++) { + fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/ccbar/%s_%s/", sum_charmed_mesons[im1].data(), sum_charmed_mesons[im2].data())); + } + } + for (int ib1 = 0; ib1 < nb_c - 1; ib1++) { + for (int ib2 = ib1 + 1; ib2 < nb_c; ib2++) { + fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/ccbar/%s_%s/", sum_charmed_baryons[ib1].data(), sum_charmed_baryons[ib2].data())); + } + } + for (int im = 0; im < nm_c; im++) { + for (int ib = 0; ib < nb_c; ib++) { + fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/ccbar/%s_%s/", sum_charmed_mesons[im].data(), sum_charmed_baryons[ib].data())); + } + } + } + + // static constexpr std::string_view beauty_mesons[] = {"Bplus", "B0", "Bs0"}; + // static constexpr std::string_view anti_beauty_mesons[] = {"Bminus", "B0bar", "Bs0bar"}; + // const int nm_b = sizeof(beauty_mesons) / sizeof(beauty_mesons[0]); + // static constexpr std::string_view beauty_baryons[] = {"Lb0"}; + // static constexpr std::string_view anti_beauty_baryons[] = {"Lb0bar"}; + // const int nb_b = sizeof(beauty_baryons) / sizeof(beauty_baryons[0]); + // static constexpr std::string_view sum_beauty_mesons[] = {"Bpm", "B0", "Bs0"}; + // static constexpr std::string_view sum_beauty_baryons[] = {"Lb0"}; + if (cfgFillSeparateBeautyHadronPairs) { + // // (Hb->l) (Hb->l) combinations + // for (int im = 0; im < nm_b; im++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/%s_%s/", beauty_mesons[im].data(), anti_beauty_mesons[im].data())); + // } + // for (int ib = 0; ib < nb_b; ib++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/%s_%s/", beauty_baryons[ib].data(), anti_beauty_baryons[ib].data())); + // } + // for (int im1 = 0; im1 < nm_b - 1; im1++) { + // for (int im2 = im1 + 1; im2 < nm_b; im2++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/%s_%s/", sum_beauty_mesons[im1].data(), sum_beauty_mesons[im2].data())); + // } + // } + // for (int ib1 = 0; ib1 < nb_b - 1; ib1++) { + // for (int ib2 = ib1 + 1; ib2 < nb_b; ib2++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/%s_%s/", sum_beauty_baryons[ib1].data(), sum_beauty_baryons[ib2].data())); + // } + // } + // for (int im = 0; im < nm_b; im++) { + // for (int ib = 0; ib < nb_b; ib++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/%s_%s/", sum_beauty_mesons[im].data(), sum_beauty_baryons[ib].data())); + // } + // } + // // (Hb->Hc->l) (Hb->Hc->l) combinations + // for (int im = 0; im < nm_b; im++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/b2%s2l_b2%s2l/", sum_charmed_mesons[im].data(), sum_charmed_mesons[im].data())); + // } + // for (int ib = 0; ib < nb_b; ib++) { + // fRegistry.addClone("Generated/ccbar/c2l_c2l/", Form("Generated/bbbar/b2%s2l_b2%s2l/", sum_charmed_baryons[ib].data(), sum_charmed_baryons[ib].data())); + // } + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l_Hc_ctau50/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l_Hc_ctau130/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l_Hc_ctau300/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau130/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau300/"); + fRegistry.addClone("Generated/ccbar/c2l_c2l/", "Generated/bbbar/b2c2l_b2c2l_Hc_ctau130_ctau300/"); + } + + // evaluate acceptance for polarization + fRegistry.add("Generated/VM/All/Phi/hs", "gen. VM #rightarrow ll", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_cos_theta_pol, axis_phi_pol, axis_quadmom}, true); + fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/Rho/"); + fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/Omega/"); + fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/PromptJPsi/"); + fRegistry.addClone("Generated/VM/All/Phi/", "Generated/VM/All/NonPromptJPsi/"); + fRegistry.addClone("Generated/VM/All/", "Generated/VM/Acc/"); + + // reconstructed pair info + fRegistry.add("Pair/sm/Photon/uls/hs", "rec. dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + + fRegistry.addClone("Pair/sm/Photon/uls/", "Pair/sm/Photon/lspp/"); + fRegistry.addClone("Pair/sm/Photon/uls/", "Pair/sm/Photon/lsmm/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/PromptPi0/"); + fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/NonPromptPi0/"); + 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/"); + // fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Upsilon1S/"); + // fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Upsilon2S/"); + // fRegistry.addClone("Pair/sm/Photon/", "Pair/sm/Upsilon3S/"); + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.add("Pair/sm/Photon/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add("Pair/sm/Photon/uls/hMvsRxy", "m_{ee} vs. r_{xy};r_{xy}^{true} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{100, 0, 100}, {100, 0.0f, 1.0f}}, true); + for (const auto& strSign : pair_sign_types) { + fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hMvsPhiV", strSign), "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/PromptPi0/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + + fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hMvsPhiV", strSign), "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/NonPromptPi0/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + + fRegistry.add(std::format("Pair/sm/PromptJPsi/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/PromptJPsi/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + fRegistry.add(std::format("Pair/sm/NonPromptJPsi/{0}hDeltaPtvsDCA", strSign), "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add(std::format("Pair/sm/NonPromptJPsi/{0}hDCAz1vsDCAz2", strSign), "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + } + } + + fRegistry.add("Pair/ccbar/c2l_c2l/uls/hs", "rec. dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.addClone("Pair/ccbar/c2l_c2l/uls/", "Pair/ccbar/c2l_c2l/lspp/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/uls/", "Pair/ccbar/c2l_c2l/lsmm/"); + + 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 + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/"); + + if (cfgFillSeparateCharmHadronPairs) { + for (int im = 0; im < nm_c; im++) { + fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/ccbar/%s_%s/", charmed_mesons[im].data(), anti_charmed_mesons[im].data())); + } + for (int ib = 0; ib < nb_c; ib++) { + fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/ccbar/%s_%s/", charmed_baryons[ib].data(), anti_charmed_baryons[ib].data())); + } + for (int im1 = 0; im1 < nm_c - 1; im1++) { + for (int im2 = im1 + 1; im2 < nm_c; im2++) { + fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/ccbar/%s_%s/", sum_charmed_mesons[im1].data(), sum_charmed_mesons[im2].data())); + } + } + for (int ib1 = 0; ib1 < nb_c - 1; ib1++) { + for (int ib2 = ib1 + 1; ib2 < nb_c; ib2++) { + fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/ccbar/%s_%s/", sum_charmed_baryons[ib1].data(), sum_charmed_baryons[ib2].data())); + } + } + for (int im = 0; im < nm_c; im++) { + for (int ib = 0; ib < nb_c; ib++) { + fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/ccbar/%s_%s/", sum_charmed_mesons[im].data(), sum_charmed_baryons[ib].data())); + } + } + } + + if (cfgFillSeparateBeautyHadronPairs) { + // // (Hb->l) (Hb->l) combinations + // for (int im = 0; im < nm_b; im++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/%s_%s/", beauty_mesons[im].data(), anti_beauty_mesons[im].data())); + // } + // for (int ib = 0; ib < nb_b; ib++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/%s_%s/", beauty_baryons[ib].data(), anti_beauty_baryons[ib].data())); + // } + // for (int im1 = 0; im1 < nm_b - 1; im1++) { + // for (int im2 = im1 + 1; im2 < nm_b; im2++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/%s_%s/", sum_beauty_mesons[im1].data(), sum_beauty_mesons[im2].data())); + // } + // } + // for (int ib1 = 0; ib1 < nb_b - 1; ib1++) { + // for (int ib2 = ib1 + 1; ib2 < nb_b; ib2++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/%s_%s/", sum_beauty_baryons[ib1].data(), sum_beauty_baryons[ib2].data())); + // } + // } + // for (int im = 0; im < nm_b; im++) { + // for (int ib = 0; ib < nb_b; ib++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/%s_%s/", sum_beauty_mesons[im].data(), sum_beauty_baryons[ib].data())); + // } + // } + // // (Hb->Hc->l) (Hb->Hc->l) combinations + // for (int im = 0; im < nm_b; im++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/b2%s2l_b2%s2l/", sum_charmed_mesons[im].data(), sum_charmed_mesons[im].data())); + // } + // for (int ib = 0; ib < nb_b; ib++) { + // fRegistry.addClone("Pair/ccbar/c2l_c2l/", Form("Pair/bbbar/b2%s2l_b2%s2l/", sum_charmed_baryons[ib].data(), sum_charmed_baryons[ib].data())); + // } + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/Hc_ctau50/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/Hc_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/Hc_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2c2l_b2c2l/Hc_ctau130_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/Hc_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/Hc_ctau50/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/Hc_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/Hc_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/Hc_ctau50_ctau130/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/Hc_ctau50_ctau300/"); + fRegistry.addClone("Pair/ccbar/c2l_c2l/", "Pair/bbbar/b2cc2ll/Hc_ctau130_ctau300/"); + } + + // for correlated bkg due to mis-identified hadrons, and true combinatorial bkg + fRegistry.add("Pair/corr_bkg_lh/uls/hs", "rec. bkg", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); + fRegistry.addClone("Pair/corr_bkg_lh/uls/", "Pair/corr_bkg_lh/lspp/"); + fRegistry.addClone("Pair/corr_bkg_lh/uls/", "Pair/corr_bkg_lh/lsmm/"); + fRegistry.addClone("Pair/corr_bkg_lh/", "Pair/corr_bkg_hh/"); + fRegistry.addClone("Pair/corr_bkg_lh/", "Pair/comb_bkg/"); + + if (doprocessGen_VM) { + fRegistry.add("Generated/VM/Omega/hPtY", "pT vs. y of #omega", kTH2D, {axis_y_meson, axis_pt_meson}, true); // for pT spectrum + fRegistry.add("Generated/VM/Phi/hPtY", "pT vs. y of #phi", kTH2D, {axis_y_meson, axis_pt_meson}, true); // for pT spectrum + } + + if (cfgFillUnfolding) { + // for 2D unfolding + const AxisSpec axis_mass_gen{ConfMllBins, "m_{ll}^{gen} (GeV/c^{2})"}; + const AxisSpec axis_pt_gen{ConfPtllBins, "p_{T,ll}^{gen} (GeV/c)"}; + const AxisSpec axis_mass_rec{ConfMllBins, "m_{ll}^{rec} (GeV/c^{2})"}; + const AxisSpec axis_pt_rec{ConfPtllBins, "p_{T,ll}^{rec} (GeV/c)"}; + fRegistry.add("Unfold/sm/uls/hsRM", "response matrix", kTHnSparseD, {axis_mass_gen, axis_pt_gen, axis_mass_rec, axis_pt_rec}, true); + fRegistry.add("Unfold/sm/uls/hMiss", "missing dilepton", kTH2D, {axis_mass_gen, axis_pt_gen}, true); // e.g. true eta is in acceptance, but reconstructed eta is out of acceptance. + fRegistry.add("Unfold/sm/uls/hFake", "fake dilepton", kTH2D, {axis_mass_rec, axis_pt_rec}, true); // e.g. true eta is out of acceptance, but reconstructed eta is in acceptance. + fRegistry.addClone("Unfold/sm/uls/", "Unfold/sm/lspp/"); + fRegistry.addClone("Unfold/sm/uls/", "Unfold/sm/lsmm/"); + fRegistry.addClone("Unfold/sm/", "Unfold/ccbar/"); + fRegistry.addClone("Unfold/sm/", "Unfold/bbbar/"); + } + } + + 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); + rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); + + 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; + } 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; + } + if (doprocessNorm) { + fRegistry.addClone("Event/before/hCollisionCounter", "Event/norm/hCollisionCounter"); + } + if (doprocessBC) { + auto hTVXCounter = fRegistry.add("BC/hTVXCounter", "TVX counter", kTH1D, {{6, -0.5f, 5.5f}}); + hTVXCounter->GetXaxis()->SetBinLabel(1, "TVX"); + hTVXCounter->GetXaxis()->SetBinLabel(2, "TVX && NoTFB"); + hTVXCounter->GetXaxis()->SetBinLabel(3, "TVX && NoITSROFB"); + hTVXCounter->GetXaxis()->SetBinLabel(4, "TVX && GoodRCT"); + hTVXCounter->GetXaxis()->SetBinLabel(5, "TVX && NoTFB && NoITSROFB"); + hTVXCounter->GetXaxis()->SetBinLabel(6, "TVX && NoTFB && NoITSROFB && GoodRCT"); + } + } + + 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 (std::fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + 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) { + 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 << " kG"; + } 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 << " kG"; + } + mRunNumber = collision.runNumber(); + fDielectronCut.SetTrackPhiPositionRange(dielectroncuts.cfg_min_phiposition_track, dielectroncuts.cfg_max_phiposition_track, dielectroncuts.cfgRefR, d_bz, dielectroncuts.cfg_mirror_phi_track); + + 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.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); + fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); + fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); + } + + 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.SetMaxMeePhiVDep([&](float phiv) { return dielectroncuts.cfg_phiv_intercept + phiv * dielectroncuts.cfg_phiv_slope; }, dielectroncuts.cfg_min_phiv, dielectroncuts.cfg_max_phiv); + fDielectronCut.ApplyPhiV(dielectroncuts.cfg_apply_phiv); + fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, false, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); + fDielectronCut.SetPairOpAng(dielectroncuts.cfg_min_opang, dielectroncuts.cfg_max_opang); + fDielectronCut.SetRequireDifferentSides(dielectroncuts.cfg_require_diff_sides); + + // for track + fDielectronCut.SetTrackPtRange(dielectroncuts.cfg_min_pt_track, dielectroncuts.cfg_max_pt_track); + fDielectronCut.SetTrackEtaRange(dielectroncuts.cfg_min_eta_track, +dielectroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(dielectroncuts.cfg_min_phi_track, dielectroncuts.cfg_max_phi_track, dielectroncuts.cfg_mirror_phi_track, dielectroncuts.cfg_reject_phi_track); + fDielectronCut.SetMinNClustersTPC(dielectroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(dielectroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetMaxFracSharedClustersTPC(dielectroncuts.cfg_max_frac_shared_clusters_tpc); + 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); + 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); + fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); + fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + + // 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.SetPinRangeForPionRejectionTPC(dielectroncuts.cfg_min_pin_pirejTPC, dielectroncuts.cfg_max_pin_pirejTPC); + + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + std::vector binsML{}; + binsML.reserve(dielectroncuts.binsMl.value.size()); + for (size_t i = 0; i < dielectroncuts.binsMl.value.size(); i++) { + binsML.emplace_back(dielectroncuts.binsMl.value[i]); + } + std::vector thresholdsML{}; + thresholdsML.reserve(dielectroncuts.cutsMl.value.size()); + for (size_t i = 0; i < dielectroncuts.cutsMl.value.size(); i++) { + thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); + } + fDielectronCut.SetMLThresholds(binsML, thresholdsML); + } // 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 + fDimuonCut.SetMindEtadPhi(dimuoncuts.cfg_apply_detadphi, dimuoncuts.cfg_min_deta, dimuoncuts.cfg_min_dphi); + + // for track + fDimuonCut.SetTrackType(dimuoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(dimuoncuts.cfg_min_pt_track, dimuoncuts.cfg_max_pt_track); + 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, 20); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetChi2MFT(0.f, dimuoncuts.cfg_max_chi2mft); + 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); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); + } + + template + int FindSMULS(TTrack const& t1mc, TTrack const& t2mc, TMCParticles const& mcparticles) + { + int arr[] = { + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 22, mcparticles), // photon + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 111, mcparticles), // pi0 + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 221, mcparticles), // eta + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 331, mcparticles), // eta' + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 113, mcparticles), // rho + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 223, mcparticles), // omega + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 333, mcparticles), // phi + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 443, mcparticles), // J/psi + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 100443, mcparticles) // psi(2S) + // FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 553, mcparticles), + // FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 100553, mcparticles), + // FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, pdg_lepton, 200553, mcparticles) + }; + int size = sizeof(arr) / sizeof(*arr); + int max = *std::max_element(arr, arr + size); + return max; + } + + template + int FindSMLSPP(TTrack const& t1mc, TTrack const& t2mc, TMCParticles const& mcparticles) + { + int arr[] = { + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 111, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 221, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 331, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 113, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 223, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, -pdg_lepton, -pdg_lepton, 333, mcparticles)}; + int size = sizeof(arr) / sizeof(*arr); + int max = *std::max_element(arr, arr + size); + return max; + } + + template + int FindSMLSMM(TTrack const& t1mc, TTrack const& t2mc, TMCParticles const& mcparticles) + { + int arr[] = { + FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 111, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 221, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 331, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 113, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 223, mcparticles), + FindCommonMotherFrom2Prongs(t1mc, t2mc, pdg_lepton, pdg_lepton, 333, 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(); + } + + return isInAcceptance(pt, eta); + + // if ((mctrackcuts.min_mcPt < pt && pt < mctrackcuts.max_mcPt) && (mctrackcuts.min_mcEta < eta && eta < mctrackcuts.max_mcEta)) { + // return true; + // } else { + // return false; + // } + } + + bool isInAcceptance(const float pt, const float 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 fillGenHistograms(const int sign1, const int sign2, const int pdgMotherC1, const int pdgMotherC2, const float mass, const float pt, const float weight) + { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/") + HIST(dilepton_source_types[sourceId]) + HIST("uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/") + HIST(dilepton_source_types[sourceId]) + HIST("lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/") + HIST(dilepton_source_types[sourceId]) + HIST("lsmm/hs"), mass, pt, weight); + } + + if (dilepton_source_types[sourceId].find("ccbar") != std::string_view::npos && cfgFillSeparateCharmHadronPairs) { + if (std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 411) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dplus_Dminus/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dplus_Dminus/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dplus_Dminus/lsmm/hs"), mass, pt, weight); + } + } else if (std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 421) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/D0_D0bar/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/D0_D0bar/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/D0_D0bar/lsmm/hs"), mass, pt, weight); + } + } else if (std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 431) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dsplus_Dsminus/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dsplus_Dsminus/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dsplus_Dsminus/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 421) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 421)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dpm_D0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dpm_D0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dpm_D0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 431) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 431)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dpm_Dspm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dpm_Dspm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dpm_Dspm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 431) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 431)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/D0_Dspm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/D0_Dspm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/D0_Dspm/lsmm/hs"), mass, pt, weight); + } + } else if (std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4122) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Lcplus_Lcminus/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Lcplus_Lcminus/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Lcplus_Lcminus/lsmm/hs"), mass, pt, weight); + } + } else if (std::abs(pdgMotherC1) == 4232 && std::abs(pdgMotherC2) == 4232) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Xicplus_Xicminus/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Xicplus_Xicminus/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Xicplus_Xicminus/lsmm/hs"), mass, pt, weight); + } + } else if (std::abs(pdgMotherC1) == 4132 && std::abs(pdgMotherC2) == 4132) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Xic0_Xic0bar/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Xic0_Xic0bar/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Xic0_Xic0bar/lsmm/hs"), mass, pt, weight); + } + } else if (std::abs(pdgMotherC1) == 4332 && std::abs(pdgMotherC2) == 4332) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Omegac0_Omegac0bar/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Omegac0_Omegac0bar/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Omegac0_Omegac0bar/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 4122 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Xicpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Xicpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Xicpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 4122 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Xic0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Xic0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Xic0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 4122 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Omegac0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Omegac0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Lcpm_Omegac0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 4232 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 4232 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Xicpm_Xic0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Xicpm_Xic0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Xicpm_Xic0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 4232 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 4232 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Xicpm_Omegac0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Xicpm_Omegac0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Xicpm_Omegac0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 4132 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 4132 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Xic0_Omegac0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Xic0_Omegac0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Xic0_Omegac0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4122) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4122)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dpm_Lcpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dpm_Lcpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dpm_Lcpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dpm_Xicpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dpm_Xicpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dpm_Xicpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dpm_Xic0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dpm_Xic0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dpm_Xic0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dpm_Omegac0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dpm_Omegac0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dpm_Omegac0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4122) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4122)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/D0_Lcpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/D0_Lcpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/D0_Lcpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/D0_Xicpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/D0_Xicpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/D0_Xicpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/D0_Xic0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/D0_Xic0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/D0_Xic0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/D0_Omegac0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/D0_Omegac0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/D0_Omegac0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4122) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4122)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dspm_Lcpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dspm_Lcpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dspm_Lcpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dspm_Xicpm/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dspm_Xicpm/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dspm_Xicpm/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dspm_Xic0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dspm_Xic0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dspm_Xic0/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/ccbar/Dspm_Omegac0/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/ccbar/Dspm_Omegac0/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/ccbar/Dspm_Omegac0/lsmm/hs"), mass, pt, weight); + } + } + } + + if (dilepton_source_types[sourceId].find("bbbar") != std::string_view::npos && cfgFillSeparateBeautyHadronPairs) { + // (Hb->l) (Hb->l)combinations + // if (std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kBPlus) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Bplus_Bminus/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Bplus_Bminus/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Bplus_Bminus/lsmm/hs"), mass, pt, weight); + // } + // } else if (std::abs(pdgMotherC1) == kB0 && std::abs(pdgMotherC2) == kB0) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/B0_B0bar/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/B0_B0bar/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/B0_B0bar/lsmm/hs"), mass, pt, weight); + // } + // } else if (std::abs(pdgMotherC1) == kBS && std::abs(pdgMotherC2) == kBS) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Bs0_Bs0bar/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Bs0_Bs0bar/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Bs0_Bs0bar/lsmm/hs"), mass, pt, weight); + // } + // } else if (std::abs(pdgMotherC1) == kLambdaB0 && std::abs(pdgMotherC2) == kLambdaB0) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Lb0_Lb0bar/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Lb0_Lb0bar/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Lb0_Lb0bar/lsmm/hs"), mass, pt, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kB0) || (std::abs(pdgMotherC2) == kBPlus && std::abs(pdgMotherC1) == kB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Bpm_B0/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Bpm_B0/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Bpm_B0/lsmm/hs"), mass, pt, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kLambdaB0) || (std::abs(pdgMotherC2) == kBPlus && std::abs(pdgMotherC1) == kLambdaB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Bpm_Lb0/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Bpm_Lb0/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Bpm_Lb0/lsmm/hs"), mass, pt, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kB0 && std::abs(pdgMotherC2) == kLambdaB0) || (std::abs(pdgMotherC2) == kB0 && std::abs(pdgMotherC1) == kLambdaB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/B0_Lb0/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/B0_Lb0/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/B0_Lb0/lsmm/hs"), mass, pt, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kBS) || (std::abs(pdgMotherC2) == kBPlus && std::abs(pdgMotherC1) == kBS)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Bpm_Bs0/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Bpm_Bs0/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Bpm_Bs0/lsmm/hs"), mass, pt, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kB0 && std::abs(pdgMotherC2) == kBS) || (std::abs(pdgMotherC2) == kB0 && std::abs(pdgMotherC1) == kBS)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/B0_Bs0/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/B0_Bs0/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/B0_Bs0/lsmm/hs"), mass, pt, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBS && std::abs(pdgMotherC2) == kLambdaB0) || (std::abs(pdgMotherC2) == kBS && std::abs(pdgMotherC1) == kLambdaB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/Bs0_Lb0/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/Bs0_Lb0/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/Bs0_Lb0/lsmm/hs"), mass, pt, weight); + // } + // } else if (std::abs(pdgMotherC1) == kD0 && std::abs(pdgMotherC2) == kD0) { // (Hb->Hc->l) (Hb->Hc->l) combinations + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/b2D02l_b2D02l/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/b2D02l_b2D02l/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/b2D02l_b2D02l/lsmm/hs"), mass, pt, weight); + // } + // } else if (std::abs(pdgMotherC1) == kDPlus && std::abs(pdgMotherC2) == kDPlus) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/b2Dpm2l_b2Dpm2l/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/b2Dpm2l_b2Dpm2l/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/b2Dpm2l_b2Dpm2l/lsmm/hs"), mass, pt, weight); + // } + // } else if (std::abs(pdgMotherC1) == kLambdaCPlus && std::abs(pdgMotherC2) == kLambdaCPlus) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Generated/bbbar/b2Lcpm2l_b2Lcpm2l/uls/hs"), mass, pt, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Generated/bbbar/b2Lcpm2l_b2Lcpm2l/lspp/hs"), mass, pt, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Generated/bbbar/b2Lcpm2l_b2Lcpm2l/lsmm/hs"), mass, pt, weight); + // } + // } + + if ((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau130/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau130/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau130/lsmm/hs"), mass, pt, weight); + } + } else if ((std::abs(pdgMotherC1) == kDPlus) && (std::abs(pdgMotherC2) == kDPlus)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau300/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau300/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau300/lsmm/hs"), mass, pt, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau130/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau130/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau130/lsmm/hs"), mass, pt, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau300/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau300/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau50_ctau300/lsmm/hs"), mass, pt, weight); + } + } else if (((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau130_ctau300/uls/hs"), mass, pt, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau130_ctau300/lspp/hs"), mass, pt, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Generated/bbbar/b2c2l_b2c2l_Hc_ctau130_ctau300/lsmm/hs"), mass, pt, weight); + } + } + } + } + + template + void fillRecHistograms(const int sign1, const int sign2, const int pdgMotherC1, const int pdgMotherC2, const float mass, const float pt, const float pair_dca, const float weight) + { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/") + HIST(dilepton_source_types[sourceId]) + HIST("uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/") + HIST(dilepton_source_types[sourceId]) + HIST("lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/") + HIST(dilepton_source_types[sourceId]) + HIST("lsmm/hs"), mass, pt, pair_dca, weight); + } + + if (dilepton_source_types[sourceId].find("ccbar") != std::string_view::npos && cfgFillSeparateCharmHadronPairs) { + if (std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 411) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dplus_Dminus/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dplus_Dminus/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dplus_Dminus/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 421) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/D0_D0bar/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/D0_D0bar/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/D0_D0bar/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 431) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dsplus_Dsminus/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dsplus_Dsminus/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dsplus_Dsminus/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 421) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 421)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dpm_D0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dpm_D0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dpm_D0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 431) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 431)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dpm_Dspm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dpm_Dspm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dpm_Dspm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 431) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 431)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/D0_Dspm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/D0_Dspm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/D0_Dspm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4122) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Lcplus_Lcminus/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Lcplus_Lcminus/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Lcplus_Lcminus/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == 4232 && std::abs(pdgMotherC2) == 4232) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Xicplus_Xicminus/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Xicplus_Xicminus/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Xicplus_Xicminus/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == 4132 && std::abs(pdgMotherC2) == 4132) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Xic0_Xic0bar/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Xic0_Xic0bar/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Xic0_Xic0bar/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == 4332 && std::abs(pdgMotherC2) == 4332) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Omegac0_Omegac0bar/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Omegac0_Omegac0bar/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Omegac0_Omegac0bar/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 4122 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Xicpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Xicpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Xicpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 4122 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Xic0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Xic0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Xic0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 4122 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 4122 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Omegac0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Omegac0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Lcpm_Omegac0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 4232 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 4232 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Xicpm_Xic0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Xicpm_Xic0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Xicpm_Xic0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 4232 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 4232 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Xicpm_Omegac0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Xicpm_Omegac0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Xicpm_Omegac0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 4132 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 4132 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Xic0_Omegac0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Xic0_Omegac0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Xic0_Omegac0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4122) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4122)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dpm_Lcpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dpm_Lcpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dpm_Lcpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dpm_Xicpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dpm_Xicpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dpm_Xicpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dpm_Xic0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dpm_Xic0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dpm_Xic0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 411 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 411 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dpm_Omegac0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dpm_Omegac0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dpm_Omegac0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4122) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4122)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/D0_Lcpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/D0_Lcpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/D0_Lcpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/D0_Xicpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/D0_Xicpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/D0_Xicpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/D0_Xic0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/D0_Xic0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/D0_Xic0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 421 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 421 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/D0_Omegac0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/D0_Omegac0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/D0_Omegac0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4122) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4122)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dspm_Lcpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dspm_Lcpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dspm_Lcpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4232) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4232)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dspm_Xicpm/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dspm_Xicpm/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dspm_Xicpm/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4132) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4132)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dspm_Xic0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dspm_Xic0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dspm_Xic0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == 431 && std::abs(pdgMotherC2) == 4332) || (std::abs(pdgMotherC2) == 431 && std::abs(pdgMotherC1) == 4332)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/ccbar/Dspm_Omegac0/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/ccbar/Dspm_Omegac0/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/ccbar/Dspm_Omegac0/lsmm/hs"), mass, pt, pair_dca, weight); + } + } + } + + if (dilepton_source_types[sourceId].find("bbbar") != std::string_view::npos && cfgFillSeparateBeautyHadronPairs) { + // (Hb->l) (Hb->l)combinations + // if (std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kBPlus) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Bplus_Bminus/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Bplus_Bminus/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Bplus_Bminus/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if (std::abs(pdgMotherC1) == kB0 && std::abs(pdgMotherC2) == kB0) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/B0_B0bar/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/B0_B0bar/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/B0_B0bar/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if (std::abs(pdgMotherC1) == kBS && std::abs(pdgMotherC2) == kBS) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Bs0_Bs0bar/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Bs0_Bs0bar/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Bs0_Bs0bar/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if (std::abs(pdgMotherC1) == kLambdaB0 && std::abs(pdgMotherC2) == kLambdaB0) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Lb0_Lb0bar/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Lb0_Lb0bar/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Lb0_Lb0bar/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kB0) || (std::abs(pdgMotherC2) == kBPlus && std::abs(pdgMotherC1) == kB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Bpm_B0/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Bpm_B0/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Bpm_B0/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kLambdaB0) || (std::abs(pdgMotherC2) == kBPlus && std::abs(pdgMotherC1) == kLambdaB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Bpm_Lb0/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Bpm_Lb0/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Bpm_Lb0/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kB0 && std::abs(pdgMotherC2) == kLambdaB0) || (std::abs(pdgMotherC2) == kB0 && std::abs(pdgMotherC1) == kLambdaB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/B0_Lb0/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/B0_Lb0/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/B0_Lb0/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBPlus && std::abs(pdgMotherC2) == kBS) || (std::abs(pdgMotherC2) == kBPlus && std::abs(pdgMotherC1) == kBS)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Bpm_Bs0/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Bpm_Bs0/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Bpm_Bs0/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kB0 && std::abs(pdgMotherC2) == kBS) || (std::abs(pdgMotherC2) == kB0 && std::abs(pdgMotherC1) == kBS)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/B0_Bs0/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/B0_Bs0/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/B0_Bs0/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if ((std::abs(pdgMotherC1) == kBS && std::abs(pdgMotherC2) == kLambdaB0) || (std::abs(pdgMotherC2) == kBS && std::abs(pdgMotherC1) == kLambdaB0)) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/Bs0_Lb0/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/Bs0_Lb0/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/Bs0_Lb0/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if (std::abs(pdgMotherC1) == kD0 && std::abs(pdgMotherC2) == kD0) { // (Hb->Hc->l) (Hb->Hc->l) combinations + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/b2D02l_b2D02l/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/b2D02l_b2D02l/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/b2D02l_b2D02l/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if (std::abs(pdgMotherC1) == kDPlus && std::abs(pdgMotherC2) == kDPlus) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/b2Dpm2l_b2Dpm2l/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/b2Dpm2l_b2Dpm2l/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/b2Dpm2l_b2Dpm2l/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } else if (std::abs(pdgMotherC1) == kLambdaCPlus && std::abs(pdgMotherC2) == kLambdaCPlus) { + // if (sign1 * sign2 < 0) { // ULS + // fRegistry.fill(HIST("Pair/bbbar/b2Lcpm2l_b2Lcpm2l/uls/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 > 0 && sign2 > 0) { // LS++ + // fRegistry.fill(HIST("Pair/bbbar/b2Lcpm2l_b2Lcpm2l/lspp/hs"), mass, pt, pair_dca, weight); + // } else if (sign1 < 0 && sign2 < 0) { // LS-- + // fRegistry.fill(HIST("Pair/bbbar/b2Lcpm2l_b2Lcpm2l/lsmm/hs"), mass, pt, pair_dca, weight); + // } + // } + + if (sourceId == 17) { // (Hb->Hc->l) (Hb->Hc->l) combinations categorized by Hc lifetime + if ((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == kDPlus && std::abs(pdgMotherC2) == kDPlus) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau50_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau130_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau130_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2c2l_b2c2l/Hc_ctau130_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } + } else if (sourceId == 20) { // (Hb->Hc+Hc->l) (Hb->Hc->l) combinations categorized by Hc lifetime + if ((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == kDPlus && std::abs(pdgMotherC2) == kDPlus) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau50_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2c2l/Hc_ctau130_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } + } else if (sourceId == 21) { // (Hb->Hc+Hc->l) (Hb->Hc+Hc->l) combinations categorized by Hc lifetime + if ((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == kDPlus && std::abs(pdgMotherC2) == kDPlus) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau50_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2l_b2cc2l/Hc_ctau130_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } + } else if (sourceId == 22) { // (Hb->Hc+Hc->l) (Hb->Hc+Hc->l) combinations categorized by Hc lifetime + if ((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if ((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (std::abs(pdgMotherC1) == kDPlus && std::abs(pdgMotherC2) == kDPlus) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50_ctau130/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50_ctau130/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50_ctau130/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kLambdaCPlus || std::abs(pdgMotherC1) == kXiC0) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kLambdaCPlus || std::abs(pdgMotherC2) == kXiC0) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau50_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } else if (((std::abs(pdgMotherC1) == kD0 || std::abs(pdgMotherC1) == kDS || std::abs(pdgMotherC1) == kXiCPlus) && (std::abs(pdgMotherC2) == kDPlus)) || ((std::abs(pdgMotherC2) == kD0 || std::abs(pdgMotherC2) == kDS || std::abs(pdgMotherC2) == kXiCPlus) && (std::abs(pdgMotherC1) == kDPlus))) { + if (sign1 * sign2 < 0) { // ULS + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau130_ctau300/uls/hs"), mass, pt, pair_dca, weight); + } else if (sign1 > 0 && sign2 > 0) { // LS++ + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau130_ctau300/lspp/hs"), mass, pt, pair_dca, weight); + } else if (sign1 < 0 && sign2 < 0) { // LS-- + fRegistry.fill(HIST("Pair/bbbar/b2cc2ll/Hc_ctau130_ctau300/lsmm/hs"), mass, pt, pair_dca, weight); + } + } + } + } + } + + template + bool fillTruePairInfo(TCollision const& collision, TMCCollisions const&, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks, TMCParticles const& mcparticles) + { + auto t1mc = mcparticles.iteratorAt(t1.emmcparticleId()); + auto t2mc = mcparticles.iteratorAt(t2.emmcparticleId()); + bool is_pair_from_same_mcevent = (t1mc.emmceventId() == t2mc.emmceventId()); + + auto mccollision1 = t1mc.template emmcevent_as(); + auto mccollision2 = t2mc.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision1.getSubGeneratorId() != cfgEventGeneratorType) { + return false; + } + if (cfgEventGeneratorType >= 0 && mccollision2.getSubGeneratorId() != cfgEventGeneratorType) { + return false; + } + if (!isInAcceptance(t1mc) || !isInAcceptance(t2mc)) { + return false; + } + + 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) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + if (!cut.IsSelectedPair(t1, t2, d_bz, 0.0)) { + 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 (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + return false; + } + if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + return false; + } + if (dimuoncuts.rejectWrongMatch) { + if (t1.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t1.emmcparticleId() != t1.emmftmcparticleId()) { + return false; + } + if (t2.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && t2.emmcparticleId() != t2.emmftmcparticleId()) { + return false; + } + } + + if (!cut.IsSelectedPair(t1, t2)) { + return false; + } + } + + 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 = t1mc.ptSmeared(); + eta1 = t1mc.etaSmeared(); + phi1 = t1mc.phiSmeared(); + pt2 = t2mc.ptSmeared(); + eta2 = t2mc.etaSmeared(); + phi2 = t2mc.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 = t1mc.ptSmeared_sa_muon(); + eta1 = t1mc.etaSmeared_sa_muon(); + phi1 = t1mc.phiSmeared_sa_muon(); + pt2 = t2mc.ptSmeared_sa_muon(); + eta2 = t2mc.etaSmeared_sa_muon(); + phi2 = t2mc.phiSmeared_sa_muon(); + } else if (dimuoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + pt1 = t1mc.ptSmeared_gl_muon(); + eta1 = t1mc.etaSmeared_gl_muon(); + phi1 = t1mc.phiSmeared_gl_muon(); + pt2 = t2mc.ptSmeared_gl_muon(); + eta2 = t2mc.etaSmeared_gl_muon(); + phi2 = t2mc.phiSmeared_gl_muon(); + } else { + pt1 = t1mc.pt(); + eta1 = t1mc.eta(); + phi1 = t1mc.phi(); + pt2 = t2mc.pt(); + eta2 = t2mc.eta(); + phi2 = t2mc.phi(); + } + } + } else { + pt1 = t1mc.pt(); + eta1 = t1mc.eta(); + phi1 = t1mc.phi(); + pt2 = t2mc.pt(); + eta2 = t2mc.eta(); + phi2 = t2mc.phi(); + } + + ROOT::Math::PtEtaPhiMVector v1mc(pt1, eta1, phi1, leptonM1); + ROOT::Math::PtEtaPhiMVector v2mc(pt2, eta2, phi2, leptonM2); + ROOT::Math::PtEtaPhiMVector v12mc = v1mc + v2mc; + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (v12mc.Rapidity() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < v12mc.Rapidity()) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (v12mc.Rapidity() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < v12mc.Rapidity()) { + return false; + } + } + + 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 pair_dca = 999.f; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + pair_dca = pairDCAQuadSum(dca3DinSigma(t1), dca3DinSigma(t2)); + if (cfgDCAType == 1) { + pair_dca = pairDCAQuadSum(dcaXYinSigma(t1), dcaXYinSigma(t2)); + } else if (cfgDCAType == 2) { + pair_dca = pairDCAQuadSum(dcaZinSigma(t1), dcaZinSigma(t2)); + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + pair_dca = pairDCAQuadSum(fwdDcaXYinSigma(t1), fwdDcaXYinSigma(t2)); + } + 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 deta = v1.Eta() - v2.Eta(); + // float dphi = v1.Phi() - v2.Phi(); + // o2::math_utils::bringToPMPi(dphi); + + // float aco = 1.f - std::fabs(dphi) / M_PI; + // float asym = std::fabs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + // float dphi_e_ee = v1.Phi() - v12.Phi(); + // o2::math_utils::bringToPMPi(dphi_e_ee); + // dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1); // shift dphi in [-pi/2, +3pi/2] rad. + + // std::array arrP1 = {t1.px(), t1.py(), t1.pz(), leptonM1}; + // std::array arrP2 = {t2.px(), t2.py(), t2.pz(), leptonM2}; + // float cos_thetaPol = 999, phiPol = 999.f; + // if (cfgPolarizationFrame == 0) { + // o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(arrP1, arrP2, beamE1, beamE2, beamP1, beamP2, t1.sign(), cos_thetaPol, phiPol); + // } else if (cfgPolarizationFrame == 1) { + // o2::aod::pwgem::dilepton::utils::pairutil::getAngleHX(arrP1, arrP2, beamE1, beamE2, beamP1, beamP2, t1.sign(), cos_thetaPol, phiPol); + // } + // o2::math_utils::bringToPMPi(phiPol); + // float quadmom = (3.f * std::pow(cos_thetaPol, 2) - 1.f) / 2.f; + + if ((FindCommonMotherFrom2ProngsWithoutPDG(t1mc, t2mc) > 0 || IsHF(t1mc, t2mc, mcparticles) > 0) && is_pair_from_same_mcevent) { // for bkg study + if (std::abs(t1mc.pdgCode()) != pdg_lepton || std::abs(t2mc.pdgCode()) != pdg_lepton) { // hh or lh correlated bkg + if (std::abs(t1mc.pdgCode()) != pdg_lepton && std::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(), 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(), 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(), pair_dca, weight); + } + } else { // lh correlated bkg + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/corr_bkg_lh/uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/corr_bkg_lh/lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/corr_bkg_lh/lsmm/hs"), v12.M(), v12.Pt(), 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(), pair_dca, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/comb_bkg/lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/comb_bkg/lsmm/hs"), v12.M(), v12.Pt(), pair_dca, weight); + } + } + + if (std::abs(t1mc.pdgCode()) != pdg_lepton || std::abs(t2mc.pdgCode()) != pdg_lepton) { + return false; + } + + if (!is_pair_from_same_mcevent) { + return false; + } + if (cfgRequireTrueAssociation && (t1mc.emmceventId() != collision.emmceventId() || t2mc.emmceventId() != collision.emmceventId())) { + return false; + } + int mother_id = std::max({FindSMULS(t1mc, t2mc, mcparticles), FindSMULS(t2mc, t1mc, mcparticles), FindSMLSPP(t1mc, t2mc, mcparticles), FindSMLSMM(t1mc, t2mc, mcparticles)}); + int hfee_type = IsHF(t1mc, t2mc, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + return false; + } + + if (mother_id > -1) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { + if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + float deltaPt1 = t1mc.pt() - t1.pt(); + float deltaPt2 = t2mc.pt() - t2.pt(); + switch (std::abs(mcmother.pdgCode())) { + case 111: + if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 + fillRecHistograms<1>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // prompt pi0 + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptPi0/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptPi0/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptPi0/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } + } + } else { // non-prompt pi0 + fillRecHistograms<2>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // non-prompt pi0 + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } + } + } + break; + case 221: + fillRecHistograms<3>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // eta + break; + case 331: + fillRecHistograms<4>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // eta' + break; + case 113: + fillRecHistograms<5>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // rho + break; + case 223: + fillRecHistograms<6>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // omega + if (mcmother.daughtersIds().size() == 2) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/sm/Omega2ll/uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); // omeag->ee + } + } + break; + case 333: + fillRecHistograms<7>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // phi + if (mcmother.daughtersIds().size() == 2) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/sm/Phi2ll/uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); // phi->ee + } + } + break; + case 443: + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fillRecHistograms<9>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // non-prompt J/psi + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } + } + } else { + fillRecHistograms<8>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // prompt J/psi + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Pair/sm/PromptJPsi/uls/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/uls/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Pair/sm/PromptJPsi/lspp/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/lspp/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Pair/sm/PromptJPsi/lsmm/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/lsmm/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } + } + } + break; + case 100443: + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fillRecHistograms<11>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // non-prompt psi2S + } else { + fillRecHistograms<10>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // prompt psi2S + } + break; + default: + break; + } + } else if (!(t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && !(t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + switch (std::abs(mcmother.pdgCode())) { + case 22: + fillRecHistograms<0>(t1.sign(), t2.sign(), 0, 0, v12.M(), v12.Pt(), pair_dca, weight); // photon conversion + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/Photon/uls/hMvsPhiV"), phiv, v12.M()); + float rxy_gen = std::sqrt(std::pow(t1mc.vx(), 2) + std::pow(t1mc.vy(), 2)); + fRegistry.fill(HIST("Pair/sm/Photon/uls/hMvsRxy"), rxy_gen, 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]); + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): + fillRecHistograms<15>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // c2l_c2l + break; + case static_cast(EM_HFeeType::kBe_Be): + fillRecHistograms<16>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2l_b2l + break; + case static_cast(EM_HFeeType::kBCe_BCe): + fillRecHistograms<17>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2c2l_b2c2l + break; + case static_cast(EM_HFeeType::kBCe_Be_SameB): + fillRecHistograms<18>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2c2l_b2l_sameb + break; + case static_cast(EM_HFeeType::kBCe_Be_DiffB): + fillRecHistograms<19>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2c2l_b2l_diffb + break; + case static_cast(EM_HFeeType::kBCCe_BCe): + fillRecHistograms<20>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2cc2l_b2c2l + break; + case static_cast(EM_HFeeType::kBCCe_BCCe): + fillRecHistograms<21>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2cc2l_b2cc2l + break; + case static_cast(EM_HFeeType::kBCCee): + fillRecHistograms<22>(t1.sign(), t2.sign(), mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), pair_dca, weight); // b2cc2ll + break; + default: + break; + } + } + } // end of HF evaluation + return true; + } + + template + bool fillGenPairInfo(TMCParticle const& t1, TMCParticle const& t2, TMCParticles const& mcparticles) + { + if (!t1.isPhysicalPrimary() && !t1.producedByGenerator()) { + return false; + } + if (!t2.isPhysicalPrimary() && !t2.producedByGenerator()) { + return false; + } + + int mother_id = std::max({FindSMULS(t1, t2, mcparticles), FindSMULS(t2, t1, mcparticles), FindSMLSPP(t1, t2, mcparticles), FindSMLSMM(t1, t2, mcparticles)}); + int hfee_type = IsHF(t1, t2, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + return false; + } + + 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; + + // float deta = v1.Eta() - v2.Eta(); + // float dphi = v1.Phi() - v2.Phi(); + // o2::math_utils::bringToPMPi(dphi); + + 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()) { + return false; + } + // if (dielectroncuts.cfg_apply_detadphi && std::pow(deta / dielectroncuts.cfg_min_deta, 2) + std::pow(dphi / dielectroncuts.cfg_min_dphi, 2) < 1.f) { + // 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()) { + return false; + } + // if (dimuoncuts.cfg_apply_detadphi && std::pow(deta / dimuoncuts.cfg_min_deta, 2) + std::pow(dphi / dimuoncuts.cfg_min_dphi, 2) < 1.f) { + // continue; + // } + } + + int sign1 = -t1.pdgCode() / pdg_lepton; + int sign2 = -t2.pdgCode() / pdg_lepton; + + // float aco = 1.f - std::fabs(dphi) / M_PI; + // float asym = std::fabs(v1.Pt() - v2.Pt()) / (v1.Pt() + v2.Pt()); + // float dphi_e_ee = v1.Phi() - v12.Phi(); + // o2::math_utils::bringToPMPi(dphi_e_ee); + // dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1); // shift dphi in [-pi/2, +3pi/2] rad. after deta-dphi cut. + + // std::array arrP1 = {static_cast(v1.Px()), static_cast(v1.Py()), static_cast(v1.Pz()), leptonM1}; + // std::array arrP2 = {static_cast(v2.Px()), static_cast(v2.Py()), static_cast(v2.Pz()), leptonM2}; + // float cos_thetaPol = 999, phiPol = 999.f; + // if (cfgPolarizationFrame == 0) { + // o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(arrP1, arrP2, beamE1, beamE2, beamP1, beamP2, -t1.pdgCode() / pdg_lepton, cos_thetaPol, phiPol); + // } else if (cfgPolarizationFrame == 1) { + // o2::aod::pwgem::dilepton::utils::pairutil::getAngleHX(arrP1, arrP2, beamE1, beamE2, beamP1, beamP2, -t1.pdgCode() / pdg_lepton, cos_thetaPol, phiPol); + // } + // o2::math_utils::bringToPMPi(phiPol); + // float quadmom = (3.f * std::pow(cos_thetaPol, 2) - 1.f) / 2.f; + + if (!isInAcceptance(t1) || !isInAcceptance(t2)) { + return false; + } + + float weight = 1.f; + if (mother_id > -1) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { + + switch (std::abs(mcmother.pdgCode())) { + case 111: + if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 + fillGenHistograms<1>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // prompt pi0 + } else { // non-prompt pi0 + fillGenHistograms<2>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // non-prompt pi0 + } + break; + case 221: + fillGenHistograms<3>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // eta + break; + case 331: + fillGenHistograms<4>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // eta' + break; + case 113: + fillGenHistograms<5>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // rho + break; + case 223: + fillGenHistograms<6>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // omega + if (mcmother.daughtersIds().size() == 2) { + fRegistry.fill(HIST("Generated/sm/Omega2ll/uls/hs"), v12.M(), v12.Pt(), weight); // omega->ee + } + break; + case 333: + fillGenHistograms<7>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // phi + if (mcmother.daughtersIds().size() == 2) { + fRegistry.fill(HIST("Generated/sm/Phi2ll/uls/hs"), v12.M(), v12.Pt()); // phi->ee + } + break; + case 443: + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fillGenHistograms<9>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // non-prompt J/psi + } else { + fillGenHistograms<8>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // prompt J/psi + } + break; + case 100443: + if (IsFromBeauty(mcmother, mcparticles) > 0) { + fillGenHistograms<11>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // non-prompt psi2S + } else { + fillGenHistograms<10>(sign1, sign2, 0, 0, v12.M(), v12.Pt(), weight); // prompt psi2S + } + 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): + fillGenHistograms<15>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // c2l_c2l + break; + case static_cast(EM_HFeeType::kBe_Be): + fillGenHistograms<16>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2l_b2l + break; + case static_cast(EM_HFeeType::kBCe_BCe): + fillGenHistograms<17>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2c2l_b2c2l + break; + case static_cast(EM_HFeeType::kBCe_Be_SameB): + fillGenHistograms<18>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2c2l_b2l_sameb + break; + case static_cast(EM_HFeeType::kBCe_Be_DiffB): + fillGenHistograms<19>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2c2l_b2l_diffb + break; + case static_cast(EM_HFeeType::kBCCe_BCe): + fillGenHistograms<20>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2cc2l_b2c2l + break; + case static_cast(EM_HFeeType::kBCCe_BCCe): + fillGenHistograms<21>(sign1, sign2, mp1.pdgCode(), mp2.pdgCode(), v12.M(), v12.Pt(), weight); // b2cc2l_b2cc2l + break; + default: + break; + } + } // end of HF evaluation + return false; + } + + template + bool fillGenParticleAcc(TMCParticle const& mcParticle, TMCParticles const& mcParticles) + { + if (!mcParticle.isPhysicalPrimary() && !mcParticle.producedByGenerator()) { + return false; + } + if (mcParticle.daughtersIds().size() < 2) { + return false; + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (mcParticle.y() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < mcParticle.y()) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (mcParticle.y() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < mcParticle.y()) { + return false; + } + } + + int pdg = mcParticle.pdgCode(); + if (std::abs(pdg) == 113 && mcParticle.daughtersIds().size() != 2) { // reject dalitz decay + return false; + } + if (std::abs(pdg) == 223 && mcParticle.daughtersIds().size() != 2) { // reject dalitz decay + return false; + } + if (std::abs(pdg) == 333 && mcParticle.daughtersIds().size() != 2) { // reject dalitz decay + return false; + } + // accept radiative decay of charmonia (ee + multiple gamma). + + // float pt1 = 0.f, eta1 = 0.f, phi1 = 0.f, sign1 = 0.f; + // float pt2 = 0.f, eta2 = 0.f, phi2 = 0.f, sign2 = 0.f; + std::vector> vDau; + vDau.reserve(mcParticle.daughtersIds().size()); + for (const auto& daughterId : mcParticle.daughtersIds()) { + auto dau = mcParticles.rawIteratorAt(daughterId); + if (std::abs(dau.pdgCode()) == pdg_lepton) { + vDau.emplace_back(std::array{dau.pt(), dau.eta(), dau.phi(), dau.pdgCode() > 0 ? -1.f : +1.f}); + } + } + if (vDau.size() != 2 || vDau[0][3] * vDau[1][3] > 0.f) { // decay objects must be ULS 2 leptons. + vDau.clear(); + vDau.shrink_to_fit(); + return false; + } + + // LOGF(info, "mcParticle.globalIndex() = %d, mcParticle.pdgCode() = %d, mcParticle.daughtersIds().size() = %d", mcParticle.globalIndex(), mcParticle.pdgCode(), mcParticle.daughtersIds().size()); + + ROOT::Math::PtEtaPhiMVector v1(vDau[0][0], vDau[0][1], vDau[0][2], leptonM1); + ROOT::Math::PtEtaPhiMVector v2(vDau[1][0], vDau[1][1], vDau[1][2], leptonM2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + std::array arrP1 = {static_cast(v1.Px()), static_cast(v1.Py()), static_cast(v1.Pz()), leptonM1}; + std::array arrP2 = {static_cast(v2.Px()), static_cast(v2.Py()), static_cast(v2.Pz()), leptonM2}; + float cos_thetaPol = 999, phiPol = 999.f; + if (cfgPolarizationFrame == 0) { + o2::aod::pwgem::dilepton::utils::pairutil::getAngleCS(arrP1, arrP2, beamE1, beamE2, beamP1, beamP2, vDau[0][3] > 0 ? 1 : -1, cos_thetaPol, phiPol); + } else if (cfgPolarizationFrame == 1) { + o2::aod::pwgem::dilepton::utils::pairutil::getAngleHX(arrP1, arrP2, beamE1, beamE2, beamP1, beamP2, vDau[0][3] > 0 ? 1 : -1, cos_thetaPol, phiPol); + } + o2::math_utils::bringToPMPi(phiPol); + float quadmom = (3.f * std::pow(cos_thetaPol, 2) - 1.f) / 2.f; + + float weight = 1.f; + switch (std::abs(mcParticle.pdgCode())) { + case 113: + fRegistry.fill(HIST("Generated/VM/All/Rho/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + if (isInAcceptance(v1.Pt(), v1.Eta()) && isInAcceptance(v2.Pt(), v2.Eta())) { + fRegistry.fill(HIST("Generated/VM/Acc/Rho/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + } + break; + case 223: + fRegistry.fill(HIST("Generated/VM/All/Omega/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + if (isInAcceptance(v1.Pt(), v1.Eta()) && isInAcceptance(v2.Pt(), v2.Eta())) { + fRegistry.fill(HIST("Generated/VM/Acc/Omega/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + } + break; + case 333: + fRegistry.fill(HIST("Generated/VM/All/Phi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + if (isInAcceptance(v1.Pt(), v1.Eta()) && isInAcceptance(v2.Pt(), v2.Eta())) { + fRegistry.fill(HIST("Generated/VM/Acc/Phi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + } + break; + case 443: + if (IsFromBeauty(mcParticle, mcParticles) > 0) { + fRegistry.fill(HIST("Generated/VM/All/NonPromptJPsi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + if (isInAcceptance(v1.Pt(), v1.Eta()) && isInAcceptance(v2.Pt(), v2.Eta())) { + fRegistry.fill(HIST("Generated/VM/Acc/NonPromptJPsi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + } + } else { + fRegistry.fill(HIST("Generated/VM/All/PromptJPsi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + if (isInAcceptance(v1.Pt(), v1.Eta()) && isInAcceptance(v2.Pt(), v2.Eta())) { + fRegistry.fill(HIST("Generated/VM/Acc/PromptJPsi/hs"), v12.M(), mcParticle.pt(), mcParticle.y(), cos_thetaPol, phiPol, quadmom, weight); + } + } + break; + default: + break; + } + + vDau.clear(); + vDau.shrink_to_fit(); + return false; + } + + template + void runTruePairing(TCollisions const& collisions, TMCLeptons const& posTracks, TMCLeptons const& negTracks, TPreslice const& perCollision, TCut const& cut, TAllTracks const& tracks, TMCCollisions const& mccollisions, TMCParticles const& mcparticles) + { + for (const 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, -1>(&fRegistry, collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(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 = 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 (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + fillTruePairInfo(collision, mccollisions, pos, neg, cut, tracks, mcparticles); + } // end of ULS pair loop + + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + fillTruePairInfo(collision, mccollisions, pos1, pos2, cut, tracks, mcparticles); + } // end of LS++ pair loop + + for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + fillTruePairInfo(collision, mccollisions, neg1, neg2, cut, tracks, mcparticles); + } // end of LS-- pair loop + + } // end of collision loop + } + + template + void runGenInfo(TCollisions const& collisions, TMCCollisions const& mccollisions, TMCLeptons const& posTracksMC, TMCLeptons const& negTracksMC, TMCParticles const& mcparticles) + { + for (const auto& mccollision : mccollisions) { + if (cfgEventGeneratorType >= 0 && mccollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + fRegistry.fill(HIST("MCEvent/before/hZvtx"), mccollision.posZ()); + if (mccollision.mpemeventId() < 0) { + continue; + } + auto collision = collisions.rawIteratorAt(mccollision.mpemeventId()); + + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + fRegistry.fill(HIST("MCEvent/before/hZvtx_rec"), mccollision.posZ()); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + fRegistry.fill(HIST("MCEvent/after/hZvtx"), mccollision.posZ()); + + 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 (const auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + fillGenPairInfo(t1, t2, mcparticles); + } // end of true ULS pair loop + + for (const auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + fillGenPairInfo(t1, t2, mcparticles); + } // end of true LS++ pair loop + + for (const auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + fillGenPairInfo(t1, t2, mcparticles); + } // end of true LS-- pair loop + + // acceptance for polarization of vector mesons + auto mcParticles_per_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + for (const auto& mcParticle : mcParticles_per_coll) { + if (!mcParticle.isPhysicalPrimary() && !mcParticle.producedByGenerator()) { + continue; + } + int pdg = std::abs(mcParticle.pdgCode()); + if (pdg == 113 || pdg == 223 || pdg == 333 || pdg == 443) { // select only VMs + fillGenParticleAcc(mcParticle, mcparticles); // VMs that decay into dilepton are stored in derived data. This is sufficient for polarization. + } + } // end of mc particle loop + } // end of collision loop + } + + template + bool isPairOK(TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + { + 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) || !cut.template IsSelectedTrack(t2)) { + 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 (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t1, cut, tracks)) { + return false; + } + if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + return false; + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.template IsSelectedPair(t1, t2, d_bz, 0.0)) { + 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 (const auto& collision : collisions) { + initCCDB(collision); + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(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 (const 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(pos, neg, cut, tracks)) { + passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), neg.globalIndex())); + } + } + for (const 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(pos1, pos2, cut, tracks)) { + passed_pairIds.emplace_back(std::make_pair(pos1.globalIndex(), pos2.globalIndex())); + } + } + for (const 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(neg1, neg2, cut, tracks)) { + 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 (const 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 (const auto& ambId1 : t1.ambiguousElectronsIds()) { + for (const 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 (const 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 (const auto& ambId1 : t1.ambiguousMuonsIds()) { + for (const 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(); + } + + template + bool isPairInAcc(TTrack const& t1, TTrack const& t2) + { + 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; + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if ((t1.pt() < dielectroncuts.cfg_min_pt_track || dielectroncuts.cfg_max_pt_track < t1.pt()) || (t2.pt() < dielectroncuts.cfg_min_pt_track || dielectroncuts.cfg_max_pt_track < t2.pt())) { + return false; + } + if ((t1.eta() < dielectroncuts.cfg_min_eta_track || dielectroncuts.cfg_max_eta_track < t1.eta()) || (t2.eta() < dielectroncuts.cfg_min_eta_track || dielectroncuts.cfg_max_eta_track < t2.eta())) { + return false; + } + if (v12.Rapidity() < dielectroncuts.cfg_min_pair_y || dielectroncuts.cfg_max_pair_y < v12.Rapidity()) { + return false; + } + return true; + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if ((t1.pt() < dimuoncuts.cfg_min_pt_track || dimuoncuts.cfg_max_pt_track < t1.pt()) || (t2.pt() < dimuoncuts.cfg_min_pt_track || dimuoncuts.cfg_max_pt_track < t2.pt())) { + return false; + } + if ((t1.eta() < dimuoncuts.cfg_min_eta_track || dimuoncuts.cfg_max_eta_track < t1.eta()) || (t2.eta() < dimuoncuts.cfg_min_eta_track || dimuoncuts.cfg_max_eta_track < t2.eta())) { + return false; + } + if (v12.Rapidity() < dimuoncuts.cfg_min_pair_y || dimuoncuts.cfg_max_pair_y < v12.Rapidity()) { + return false; + } + return true; + } else { + return false; + } + return true; + } + + template + void fillHistogramsUnfolding(TTrack const& t1, TTrack const& t2, TMCParticles const& mcparticles) + { + auto t1mc = mcparticles.iteratorAt(t1.emmcparticleId()); + auto t2mc = mcparticles.iteratorAt(t2.emmcparticleId()); + + ROOT::Math::PtEtaPhiMVector v1rec(t1.pt(), t1.eta(), t1.phi(), leptonM1); + ROOT::Math::PtEtaPhiMVector v2rec(t2.pt(), t2.eta(), t2.phi(), leptonM2); + ROOT::Math::PtEtaPhiMVector v12rec = v1rec + v2rec; + + ROOT::Math::PtEtaPhiMVector v1mc(t1mc.pt(), t1mc.eta(), t1mc.phi(), leptonM1); + ROOT::Math::PtEtaPhiMVector v2mc(t2mc.pt(), t2mc.eta(), t2mc.phi(), leptonM2); + ROOT::Math::PtEtaPhiMVector v12mc = v1mc + v2mc; + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; + } + + if (isPairInAcc(t1, t2) && isPairInAcc(t1mc, t2mc)) { // both rec and mc info are in acceptance. + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("uls/hsRM"), v12mc.M(), v12mc.Pt(), v12rec.M(), v12rec.Pt(), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("lspp/hsRM"), v12mc.M(), v12mc.Pt(), v12rec.M(), v12rec.Pt(), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("lsmm/hsRM"), v12mc.M(), v12mc.Pt(), v12rec.M(), v12rec.Pt(), weight); + } + } else if (!isPairInAcc(t1, t2) && isPairInAcc(t1mc, t2mc)) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("uls/hMiss"), v12mc.M(), v12mc.Pt(), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("lspp/hMiss"), v12mc.M(), v12mc.Pt(), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("lsmm/hMiss"), v12mc.M(), v12mc.Pt(), weight); + } + } else if (isPairInAcc(t1, t2) && !isPairInAcc(t1mc, t2mc)) { + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("uls/hFake"), v12rec.M(), v12rec.Pt(), weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("lspp/hFake"), v12rec.M(), v12rec.Pt(), weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("Unfold/") + HIST(unfolding_dilepton_source_types[sourceId]) + HIST("lsmm/hFake"), v12rec.M(), v12rec.Pt(), weight); + } + } + } + + template + bool fillPairUnfolding(TTrack const& t1, TTrack const& t2, TTracks const& tracks, TCut const& cut, TMCCollisions const&, TMCParticles const& mcparticles) + { + auto t1mc = mcparticles.iteratorAt(t1.emmcparticleId()); + auto mccollision_from_t1 = t1mc.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_t1.getSubGeneratorId() != cfgEventGeneratorType) { + return false; + } + + auto t2mc = mcparticles.iteratorAt(t2.emmcparticleId()); + auto mccollision_from_t2 = t2mc.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_t2.getSubGeneratorId() != cfgEventGeneratorType) { + return false; + } + + if ((std::abs(t1mc.pdgCode()) != pdg_lepton || std::abs(t2mc.pdgCode()) != pdg_lepton) || (t1mc.emmceventId() != t2mc.emmceventId())) { + return false; + } + if (t1mc.pdgCode() * t2mc.pdgCode() > 0) { // ULS + return false; + } + if (!((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator()))) { + return false; + } + int mother_id = std::max({FindSMULS(t1mc, t2mc, mcparticles), FindSMULS(t2mc, t1mc, mcparticles), FindSMLSPP(t1mc, t2mc, mcparticles), FindSMLSMM(t1mc, t2mc, mcparticles)}); + int hfee_type = IsHF(t1mc, t2mc, mcparticles); + if (mother_id < 0 && hfee_type < 0) { + return false; + } + + if (!isPairOK(t1, t2, cut, tracks)) { // without acceptance + return false; + } + + // ROOT::Math::PtEtaPhiMVector v1rec(t1.pt(), t1.eta(), t1.phi(), leptonM1); + // ROOT::Math::PtEtaPhiMVector v2rec(t2.pt(), t2.eta(), t2.phi(), leptonM2); + // ROOT::Math::PtEtaPhiMVector v12rec = v1rec + v2rec; + + // ROOT::Math::PtEtaPhiMVector v1mc(t1mc.pt(), t1mc.eta(), t1mc.phi(), leptonM1); + // ROOT::Math::PtEtaPhiMVector v2mc(t2mc.pt(), t2mc.eta(), t2mc.phi(), leptonM2); + // ROOT::Math::PtEtaPhiMVector v12mc = v1mc + v2mc; + + if (mother_id > -1) { + auto mcmother = mcparticles.iteratorAt(mother_id); + if (!(mcmother.isPhysicalPrimary() || mcmother.producedByGenerator())) { + return false; + } + switch (std::abs(mcmother.pdgCode())) { + case 111: + case 221: + case 331: + case 113: + case 223: + case 333: + case 443: + case 100443: + fillHistogramsUnfolding<0>(t1, t2, mcparticles); + break; + default: + break; + } + } else if (hfee_type > -1) { + switch (hfee_type) { + case static_cast(EM_HFeeType::kCe_Ce): + fillHistogramsUnfolding<1>(t1, t2, mcparticles); + break; + case static_cast(EM_HFeeType::kBe_Be): + fillHistogramsUnfolding<2>(t1, t2, mcparticles); + break; + case static_cast(EM_HFeeType::kBCe_BCe): + fillHistogramsUnfolding<2>(t1, t2, mcparticles); + break; + case static_cast(EM_HFeeType::kBCe_Be_SameB): + fillHistogramsUnfolding<2>(t1, t2, mcparticles); + break; + case static_cast(EM_HFeeType::kBCe_Be_DiffB): + fillHistogramsUnfolding<2>(t1, t2, mcparticles); + break; + default: + break; + } + } + return true; + } + + template + void fillUnfolding(TCollisions const& collisions, TTracks1 const& posTracks, TTracks2 const& negTracks, TPresilce const& perCollision, TCut const& cut, TAllTracks const& tracks, TMCCollisions const& mcCollisions, TMCParticles const& mcparticles) + { + for (const auto& collision : collisions) { + initCCDB(collision); + float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + + auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); // reconstructed pos tracks + auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); // reconstructed neg tracks + + for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + fillPairUnfolding(pos, neg, tracks, cut, mcCollisions, mcparticles); + } // end of ULS pairing + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + fillPairUnfolding(pos1, pos2, tracks, cut, mcCollisions, mcparticles); + } // end of LS++ pairing + for (const auto& [neg1, neg2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + fillPairUnfolding(neg1, neg2, tracks, cut, mcCollisions, mcparticles); + } // end of LS-- pairing + } // end of collision loop + } + + SliceCache cache; + Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Filter trackFilter_electron = nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter ttcaFilter_electron = ifnode(dielectroncuts.enableTTCA.node(), o2::aod::emprimaryelectron::isAssociatedToMPC == true || o2::aod::emprimaryelectron::isAssociatedToMPC == false, o2::aod::emprimaryelectron::isAssociatedToMPC == true); + Filter prefilter_derived_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter_derived.node() && dielectroncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimaryelectron::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfbderived >= static_cast(0)); + + Filter prefilter_electron = ifnode(dielectroncuts.cfg_apply_cuts_from_prefilter.node() && dielectroncuts.cfg_prefilter_bits.node() >= static_cast(1), + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_20MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_40MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_60MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_80MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_100MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_120MeV))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_140MeV))) <= static_cast(0), true), + o2::aod::emprimaryelectron::pfb >= static_cast(0)); + + Preslice perCollision_muon = aod::emprimarymuon::emeventId; + Filter trackFilter_muon = o2::aod::fwdtrack::trackType == dimuoncuts.cfg_track_type; + Filter ttcaFilter_muon = ifnode(dimuoncuts.enableTTCA.node(), o2::aod::emprimarymuon::isAssociatedToMPC == true || o2::aod::emprimarymuon::isAssociatedToMPC == false, o2::aod::emprimarymuon::isAssociatedToMPC == true); + Filter prefilter_derived_muon = ifnode(dimuoncuts.cfg_apply_cuts_from_prefilter_derived.node() && dimuoncuts.cfg_prefilter_bits_derived.node() >= static_cast(1), + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS))) <= static_cast(0), true) && + ifnode((dimuoncuts.cfg_prefilter_bits_derived.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) > static_cast(0), (o2::aod::emprimarymuon::pfbderived & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS))) <= static_cast(0), true), + o2::aod::emprimarymuon::pfbderived >= static_cast(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); + Filter collisionFilter_numContrib = cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < cfgNumContribMax; + Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + 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; + // PresliceUnsorted recColperMcCollision = aod::emmceventlabel::emmceventId; + + void processAnalysis(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, aod::EMMCParticles const& mcparticles, TLeptons const& leptons) + { + // LOGF(info, "collisions.size() = %d, mccollisions.size() = %d, mcparticles.size() = %d", collisions.size(), mccollisions.size(), mcparticles.size()); + 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, leptons, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, positive_electronsMC, negative_electronsMC, mcparticles); + if (cfgFillUnfolding) { + fillUnfolding(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, 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, leptons, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, positive_muonsMC, negative_muonsMC, mcparticles); + if (cfgFillUnfolding) { + fillUnfolding(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles); + } + } + map_weight.clear(); + } + PROCESS_SWITCH(checkMCPairTemplate, 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, MyMCCollisions const& mccollisions, TLeptons const& leptons, TSmeardMCParitlces const& mcparticles_smeared) + { + // LOGF(info, "collisions.size() = %d, mccollisions.size() = %d, mcparticles.size() = %d", collisions.size(), mccollisions.size(), mcparticles.size()); + 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, leptons, mccollisions, mcparticles_smeared); + runGenInfo(collisions, mccollisions, positive_electronsMC_smeared, negative_electronsMC_smeared, mcparticles_smeared); + if (cfgFillUnfolding) { + fillUnfolding(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, leptons, mccollisions, 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, leptons, mccollisions, mcparticles_smeared); + runGenInfo(collisions, mccollisions, positive_muonsMC_smeared, negative_muonsMC_smeared, mcparticles_smeared); + if (cfgFillUnfolding) { + fillUnfolding(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, leptons, mccollisions, mcparticles_smeared); + } + } + map_weight.clear(); + } + PROCESS_SWITCH(checkMCPairTemplate, processAnalysis_Smeared, "run dilepton mc analysis with smearing", false); + + void processGen_VM(FilteredMyCollisions const& collisions, MyMCCollisions const&, aod::EMMCGenVectorMesons const& mcparticles) + { + // for oemga, phi efficiency + for (const 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; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(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 (const 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 (std::abs(mctrack.pdgCode())) { + case 223: + fRegistry.fill(HIST("Generated/VM/Omega/hPtY"), mctrack.y(), mctrack.pt(), 1.f / mctrack.dsf()); + break; + case 333: + fRegistry.fill(HIST("Generated/VM/Phi/hPtY"), mctrack.y(), mctrack.pt(), 1.f / mctrack.dsf()); + break; + default: + break; + } + + } // end of mctracks per mccollision + } // end of collision loop + } + PROCESS_SWITCH(checkMCPairTemplate, processGen_VM, "process generated info for vector mesons", false); + + void processNorm(aod::EMEventNormInfos const& collisions) + { + for (const auto& collision : collisions) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 7.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 8.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTOFmatched)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 9.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 10.0); + } + if (std::fabs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 11.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 12.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 13.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 14.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 15.0); + } + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 16.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 17.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 18.0); + } + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), 19.0); + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + fRegistry.fill(HIST("Event/norm/hCollisionCounter"), o2::aod::pwgem::dilepton::utils::eventhistogram::nbin_ev); // accepted + } // end of collision loop + } + PROCESS_SWITCH(checkMCPairTemplate, processNorm, "process normalization info", false); + + void processBC(aod::EMBCs const& bcs) + { + for (const auto& bc : bcs) { + if (bc.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("BC/hTVXCounter"), 0.f); + + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("BC/hTVXCounter"), 1.f); + } + if (bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("BC/hTVXCounter"), 2.f); + } + if (rctChecker(bc)) { + fRegistry.fill(HIST("BC/hTVXCounter"), 3.f); + } + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("BC/hTVXCounter"), 4.f); + } + if (bc.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder) && bc.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder) && rctChecker(bc)) { + fRegistry.fill(HIST("BC/hTVXCounter"), 5.f); + } + } + } + } + PROCESS_SWITCH(checkMCPairTemplate, processBC, "process BC counter", false); + + void processDummy(FilteredMyCollisions const&) {} + PROCESS_SWITCH(checkMCPairTemplate, processDummy, "Dummy function", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"check-mc-pair-template"})}; +} diff --git a/PWGEM/Dilepton/Tasks/checkMCTemplate.cxx b/PWGEM/Dilepton/Tasks/checkMCTemplate.cxx new file mode 100644 index 00000000000..ad299df81f7 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/checkMCTemplate.cxx @@ -0,0 +1,889 @@ +// 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 check dca template for electrons/muons +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::fwdtrackutils; +using namespace o2::constants::physics; + +struct checkMCTemplate { + 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 lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + 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 cfg_require_true_mc_collision_association{"cfg_require_true_mc_collision_association", false, "flag to require true mc collision association"}; + Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; + + ConfigurableAxis ConfPtBins{"ConfPtBins", {100, 0, 10}, "pT bins for output histograms"}; + ConfigurableAxis ConfEtaCBBins{"ConfEtaCBBins", {20, -1.0, +1.0}, "eta bins at midrapidity for output histograms"}; + ConfigurableAxis ConfEtaFWDBins{"ConfEtaFWDBins", {40, -4, -2}, "eta bins at forward rapidity for output histograms"}; + ConfigurableAxis ConfPhiBins{"ConfPhiBins", {36, 0, 2.f * M_PI}, "phi bins at forward rapidity for output histograms"}; + + ConfigurableAxis ConfDCACBBins{"ConfDCACBBins", {1, 0, 10}, "dca bins for output histograms at midrapidity"}; + ConfigurableAxis ConfDCAFWDBins{"ConfDCAFWDBins", {1, 0, 10}, "dca bins for output histograms at fwd rapidity"}; + + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabelCB{"cfgRCTLabelCB", "CBT_hadronPID", "select 1 [CBT, CBT_hadron] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgRCTLabelFWDGL{"cfgRCTLabelFWDGL", "CBT_muon_glo", "select 1 [CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + // Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + // Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + // Configurable cfgRequirekNoCollInRofStandard{"cfgRequirekNoCollInRofStandard", false, "require no other collisions in this Readout Frame with per-collision multiplicity above threshold"}; + // Configurable cfgRequirekNoCollInRofStrict{"cfgRequirekNoCollInRofStrict", false, "require no other collisions in this Readout Frame"}; + // Configurable cfgRequirekNoHighMultCollInPrevRof{"cfgRequirekNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + // Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + // Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + // Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + } eventcuts; + + 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", -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_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 itsib"}; + 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + 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", true, "flag to require ITS ib 1st hit"}; + Configurable cfg_reject_fake_match_its_tpc{"cfg_reject_fake_match_its_tpc", false, "flag to reject fake match between ITS-TPC"}; + } electroncuts; + + struct : ConfigurableGroup { + std::string prefix = "muoncut_group"; + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.01, "min pT for single track"}; + Configurable cfg_min_eta_track_gl{"cfg_min_eta_track_gl", -5.5, "min eta for global muon track"}; + Configurable cfg_max_eta_track_gl{"cfg_max_eta_track_gl", -1.5, "max eta for global muon 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_gl{"cfg_max_chi2_gl", 4, "max chi2/ndf for global muon track"}; + Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+10, "max chi2/ndf for MFTsa track"}; + Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2/ndf for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mchmid{"cfg_max_matching_chi2_mchmid", 1e+10, "max chi2/ndf for MCH-MID matching"}; + Configurable cfg_max_dcaxy_gl{"cfg_max_dcaxy_gl", 0.1, "max dca XY for single track in cm"}; + Configurable cfg_min_rabs_gl{"cfg_min_rabs_gl", 27.6, "min Radius at the absorber end for global muon track"}; + Configurable cfg_max_rabs_gl{"cfg_max_rabs_gl", 89.5, "max Radius at the absorber end for global muon track"}; + Configurable cfg_mid_rabs{"cfg_mid_rabs", 26.5, "middle R at absorber end for pDCA cut"}; + Configurable cfg_max_pdca_forLargeR{"cfg_max_pdca_forLargeR", 324.f, "max. pDCA for large R at absorber end"}; + Configurable cfg_max_pdca_forSmallR{"cfg_max_pdca_forSmallR", 594.f, "max. pDCA for small R at absorber end"}; + Configurable cfg_max_reldpt{"cfg_max_reldpt", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_deta{"cfg_max_deta", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_dphi{"cfg_max_dphi", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to require MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{4}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable cfg_reject_fake_match_mft_mch{"cfg_reject_fake_match_mft_mch", false, "flag to reject fake match between MFT-MCH"}; + } muoncuts; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::aod::rctsel::RCTFlagsChecker rctCheckerCB; + o2::aod::rctsel::RCTFlagsChecker rctCheckerFWDGL; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber = 0; + float mBzMFT = 0; + float d_bz = 0; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::dataformats::VertexBase mVtx; + const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; + o2::base::MatLayerCylSet* lut = nullptr; + + ~checkMCTemplate() {} + + void init(o2::framework::InitContext&) + { + if (doprocessElectronSA && doprocessElectronTTCA) { + LOGF(fatal, "Cannot enable processElectronSA and processElectronTTCA at the same time. Please choose one."); + } + + if (doprocessMuonSA && doprocessMuonTTCA) { + LOGF(fatal, "Cannot enable processMuonSA and processMuonTTCA at the same time. Please choose one."); + } + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + rctCheckerCB.init(cfgRCTLabelCB.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); + rctCheckerFWDGL.init(cfgRCTLabelFWDGL.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); + + mRunNumber = 0; + d_bz = 0; + mBzMFT = 0; + + const AxisSpec axis_pt{ConfPtBins, "p_{T,l} (GeV/c)"}; + const AxisSpec axis_eta_cb{ConfEtaCBBins, "#eta_{l}"}; + const AxisSpec axis_eta_fwd{ConfEtaFWDBins, "#eta_{l}"}; + const AxisSpec axis_phi{ConfPhiBins, "#varphi_{l} (rad.)"}; + const AxisSpec axis_dca_fwd{ConfDCAFWDBins, "DCA_{l}^{XY} (#sigma)"}; + const AxisSpec axis_charge{3, -1.5, +1.5, "sign"}; + + std::string pair_dca_axis_title = "DCA_{l}^{3D} (#sigma)"; + if (cfgDCAType == 0) { + pair_dca_axis_title = "DCA_{l}^{3D} (#sigma)"; + } else if (cfgDCAType == 1) { + pair_dca_axis_title = "DCA_{l}^{XY} (#sigma)"; + } else if (cfgDCAType == 2) { + pair_dca_axis_title = "DCA_{l}^{Z} (#sigma)"; + } + const AxisSpec axis_dca_cb{ConfDCACBBins, pair_dca_axis_title}; + + registry.add("Electron/c2l/hs", "hs", kTHnSparseF, {axis_pt, axis_eta_cb, axis_phi, axis_dca_cb, axis_charge}, false); + registry.addClone("Electron/c2l/", "Electron/b2l/"); + registry.addClone("Electron/c2l/", "Electron/b2c2l/"); + registry.addClone("Electron/c2l/", "Electron/b2Dch2l/"); + registry.addClone("Electron/c2l/", "Electron/b2D02l/"); + registry.addClone("Electron/c2l/", "Electron/b2Ds2l/"); + registry.addClone("Electron/c2l/", "Electron/b2LambdaC2l/"); + registry.addClone("Electron/c2l/", "Electron/b2LXic02l/"); + registry.addClone("Electron/c2l/", "Electron/b2LXicch2l/"); + + registry.add("Muon/c2l/hs", "hs", kTHnSparseF, {axis_pt, axis_eta_fwd, axis_phi, axis_dca_fwd, axis_charge}, false); + registry.addClone("Muon/c2l/", "Muon/b2l/"); + registry.addClone("Muon/c2l/", "Muon/b2c2l/"); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // load matLUT for this timestamp + if (!lut) { + LOG(info) << "Loading material look-up table for timestamp: " << bc.timestamp(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->getForTimeStamp(lutPath, bc.timestamp())); + } else { + LOG(info) << "Material look-up table already in place. Not reloading."; + } + + // 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 (std::fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); + mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + mRunNumber = bc.runNumber(); + + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + o2::mch::TrackExtrap::setField(); + mBzMFT = d_bz; + LOGF(info, "Bz at center of MFT = %f kZG manually", mBzMFT); + } + + 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); + o2::base::Propagator::Instance()->setMatLUT(lut); + mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + // 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); + o2::base::Propagator::Instance()->setMatLUT(lut); + mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.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"; + } + + // 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(); + const double centerMFT[3] = {0, 0, -61.4}; + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + mBzMFT = field->getBz(centerMFT); // Get field at centre of MFT + LOGF(info, "Bz at center of MFT = %f kZG", mBzMFT); + mRunNumber = bc.runNumber(); + } + + template + bool isSelectedEvent(TCollision const& collision) + { + if (eventcuts.cfgRequireSel8 && !collision.sel8()) { + return false; + } + + if (collision.posZ() < eventcuts.cfgZvtxMin || eventcuts.cfgZvtxMax < collision.posZ()) { + 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.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + return false; + } + + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + return false; + } + + // if (eventcuts.cfgRequireNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // return false; + // } + + // if (eventcuts.cfgRequireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + // return false; + // } + + // if (eventcuts.cfgRequirekNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // return false; + // } + + // if (eventcuts.cfgRequirekNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + // return false; + // } + + // if (eventcuts.cfgRequirekNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // return false; + // } + + // if (eventcuts.cfgRequireGoodITSLayer3 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + // return false; + // } + + // if (eventcuts.cfgRequireGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + // return false; + // } + + // if (eventcuts.cfgRequireGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // return false; + // } + + return true; + } + + 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 isSelectedTrack(TTrack const& track, const float pt, const float eta, const float dcaXY, const float dcaZ) + { + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (track.itsChi2NCl() > electroncuts.cfg_max_chi2its) { + return false; + } + + if (track.itsNCls() < electroncuts.cfg_min_ncluster_its) { + return false; + } + if (track.itsNClsInnerBarrel() < electroncuts.cfg_min_ncluster_itsib) { + 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.tpcChi2NCl() > electroncuts.cfg_max_chi2tpc) { + 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; + } + + if (track.tpcFractionSharedCls() > electroncuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } + + if (std::fabs(dcaXY) > electroncuts.cfg_max_dcaxy || std::fabs(dcaZ) > electroncuts.cfg_max_dcaz) { + return false; + } + + if (pt < electroncuts.cfg_min_pt_track || std::fabs(eta) > electroncuts.cfg_max_eta_track) { + return false; + } + + return true; + } + + template + void fillMuon(TCollision const& collision, TMuon const& muon, TMCParticles const& mcParticles) + { + auto mcparticle = muon.template mcParticle_as(); + if (std::abs(mcparticle.pdgCode()) != 13 || !(mcparticle.isPhysicalPrimary() || mcparticle.producedByGenerator()) || !mcparticle.has_mothers()) { + return; + } + if (cfg_require_true_mc_collision_association && mcparticle.mcCollisionId() != collision.mcCollisionId()) { + return; + } + if (muon.trackType() != static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + return; + } + + if (std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(muon.globalIndex(), muon.matchMCHTrackId(), muon.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + return; + } + + if (muon.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. + return; + } + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon, muon, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT); + + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + // float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + float cXX = propmuonAtPV.getSigma2X(); + float cYY = propmuonAtPV.getSigma2Y(); + float cXY = propmuonAtPV.getSigmaXY(); + + float dca = 999.f; + float det = cXX * cYY - cXY * cXY; // determinanat + if (det < 0) { + dca = 999.f; + } else { + dca = std::sqrt(std::fabs((dcaX * dcaX * cYY + dcaY * dcaY * cXX - 2.f * dcaX * dcaY * cXY) / det / 2.f)); // dca xy in sigma + } + + // float rAtAbsorberEnd = muon.rAtAbsorberEnd(); // this works only for GlobalMuonTrack + // float pDCA = propmuonAtPV.getP() * dcaXY; + int nClustersMFT = 0; + float ptMatchedMCHMID = propmuonAtPV.getPt(); + float etaMatchedMCHMID = propmuonAtPV.getEta(); + float phiMatchedMCHMID = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + // mcparticle for global MFT-MCH-MID is identical to mcparticle of MCH-MID track. If not, mismatch. + auto mchtrack = muon.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = muon.template matchMFTTrack_as(); // MFTsa + if (!mchtrack.has_mcParticle() || !mfttrack.has_mcParticle()) { + return; + } + auto mcparticle_MCHMID = mchtrack.template mcParticle_as(); + auto mcparticle_MFT = mfttrack.template mcParticle_as(); + if (mcparticle.globalIndex() != mcparticle_MCHMID.globalIndex()) { // this should not happen. this is only for protection. + return; + } + if (muoncuts.cfg_reject_fake_match_mft_mch && mcparticle.globalIndex() != mcparticle_MFT.globalIndex()) { // evaluate mismatch + return; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT); + ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); + etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + if (muoncuts.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + // o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT); + // float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + // float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + // float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + // pDCA = mchtrack.p() * dcaXY_Matched; + // pDCA = propmuonAtPV.getP() * dcaXY; + + nClustersMFT = mfttrack.nClusters(); + float chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); + + if (nClustersMFT < muoncuts.cfg_min_ncluster_mft) { + return; + } + + if (chi2mft < 0.f || muoncuts.cfg_max_chi2mft < chi2mft) { + return; + } + + if (muon.chi2MatchMCHMFT() > muoncuts.cfg_max_matching_chi2_mftmch) { + return; + } + + float dpt = (ptMatchedMCHMID - pt) / pt; + if (std::fabs(dpt) > muoncuts.cfg_max_reldpt) { + return; + } + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + if (std::sqrt(std::pow(deta / muoncuts.cfg_max_deta, 2) + std::pow(dphi / muoncuts.cfg_max_dphi, 2)) > 1.f) { + return; + } + + if (muoncuts.requireMFTHitMap) { + std::vector hasMFTs{hasMFT<0, 1>(mfttrack), hasMFT<2, 3>(mfttrack), hasMFT<4, 5>(mfttrack), hasMFT<6, 7>(mfttrack), hasMFT<8, 9>(mfttrack)}; + for (int i = 0; i < static_cast(muoncuts.requiredMFTDisks->size()); i++) { + if (!hasMFTs[muoncuts.requiredMFTDisks->at(i)]) { + return; + } + } + } + + // fill histograms here + auto mcmother = mcparticle.template mothers_as()[0]; + + if (isWeakDecayFromBeautyHadron(mcparticle, mcParticles)) { // hb->l is found in full decay chain. + registry.fill(HIST("Muon/b2l/hs"), pt, eta, phi, dca, muon.sign()); + } else if (isWeakDecayFromCharmHadron(mcparticle, mcParticles)) { // hc->l is found in full decay chain. + if (IsFromBeauty(mcmother, mcParticles) > 0) { // hb->hc->l is fond. + registry.fill(HIST("Muon/b2c2l/hs"), pt, eta, phi, dca, muon.sign()); + } else { // prompt hc->l is found. + registry.fill(HIST("Muon/c2l/hs"), pt, eta, phi, dca, muon.sign()); + } + } + } + + template + bool hasMFT(T const& track) + { + // logical-OR + uint64_t mftClusterSizesAndTrackFlags = track.mftClusterSizesAndTrackFlags(); + uint16_t clmap = 0; + for (unsigned int layer = begin; layer <= end; layer++) { + if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3f) { + clmap |= (1 << layer); + } + } + return (clmap > 0); + } + + SliceCache cache; + Preslice perCollision_mid = o2::aod::track::collisionId; + Preslice perCollision_fwd = o2::aod::fwdtrack::collisionId; + PresliceUnsorted fwdtracksPerMCHTrack = aod::fwdtrack::matchMCHTrackId; + + using MyCollisions = Join; + using MyCollision = MyCollisions::iterator; + + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; + + using MyFwdTracks = soa::Join; + using MyFwdTrack = MyFwdTracks::iterator; + + using MyMFTTracks = soa::Join; + using MyMFTTrack = MyMFTTracks::iterator; + + template + void fillElectron(TCollision const& collision, TTrack const& track, TMCParticles const& mcParticles) + { + if (cfgRequireGoodRCT && !rctCheckerCB.checkTable(collision)) { + return; + } + auto mcparticle = track.template mcParticle_as(); + + if (std::abs(mcparticle.pdgCode()) != 11 || !(mcparticle.isPhysicalPrimary() || mcparticle.producedByGenerator()) || !mcparticle.has_mothers()) { + return; + } + if (electroncuts.cfg_reject_fake_match_its_tpc && o2::aod::pwgem::dilepton::utils::mcutil::hasFakeMatchITSTPC(track)) { + return; + } + if (cfg_require_true_mc_collision_association && mcparticle.mcCollisionId() != collision.mcCollisionId()) { + return; + } + + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(o2::track::PID::Electron); + mVtx.setPos({collision.posX(), collision.posY(), collision.posZ()}); + mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + + float pt = trackParCov.getPt(); + float eta = trackParCov.getEta(); + float phi = trackParCov.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + if (!isSelectedTrack(track, pt, eta, dcaXY, dcaZ)) { + return; + } + + float dca_sigma = 999.f; + if (cfgDCAType == 0) { + float det = trackParCov.getSigmaY2() * trackParCov.getSigmaZ2() - trackParCov.getSigmaZY() * trackParCov.getSigmaZY(); + if (det < 0) { + dca_sigma = 999.f; + } else { + float chi2 = (dcaXY * dcaXY * trackParCov.getSigmaZ2() + dcaZ * dcaZ * trackParCov.getSigmaY2() - 2. * dcaXY * dcaZ * trackParCov.getSigmaZY()) / det; + dca_sigma = std::sqrt(std::fabs(chi2) / 2.); + } + } else if (cfgDCAType == 1) { + dca_sigma = dcaXY / std::sqrt(trackParCov.getSigmaY2()); + } else if (cfgDCAType == 2) { + dca_sigma = dcaZ / std::sqrt(trackParCov.getSigmaZ2()); + } + + // fill histograms here + auto mcmother = mcparticle.template mothers_as()[0]; + + if (isWeakDecayFromBeautyHadron(mcparticle, mcParticles)) { // hb->l is found in full decay chain. + registry.fill(HIST("Electron/b2l/hs"), pt, eta, phi, dca_sigma, track.sign()); + } else if (isWeakDecayFromCharmHadron(mcparticle, mcParticles)) { // hc->l is found in full decay chain. + if (IsFromBeauty(mcmother, mcParticles) > 0) { // hb->hc->l is found. + registry.fill(HIST("Electron/b2c2l/hs"), pt, eta, phi, dca_sigma, track.sign()); + if (abs(mcparticle.pdgCode()) == kDPlus) + registry.fill(HIST("Electron/b2Dch2l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->D+->l + // if(abs(mcparticle.pdgCode()) == 413); registry.fill(HIST("Electron/b2DchStar2l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->D*+->l + if (abs(mcparticle.pdgCode()) == kD0) + registry.fill(HIST("Electron/b2D02l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->D0->l + if (abs(mcparticle.pdgCode()) == kDS) + registry.fill(HIST("Electron/b2Ds2l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->Ds->l + if (abs(mcparticle.pdgCode()) == kLambdaCPlus) + registry.fill(HIST("Electron/b2LambdaC2l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->LambdaC->l + if (abs(mcparticle.pdgCode()) == kXiC0) + registry.fill(HIST("Electron/b2Xic02l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->Xic0->l + if (abs(mcparticle.pdgCode()) == kXiCPlus) + registry.fill(HIST("Electron/b2Xicch2l/hs"), pt, eta, phi, dca_sigma, track.sign()); // hb->Xicch->l + } else { // prompt hc->l is found. + registry.fill(HIST("Electron/c2l/hs"), pt, eta, phi, dca_sigma, track.sign()); + } + } + } + + std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; + template + void findBestMatchPerMCHMID(TMuons const& muons) + { + vec_min_chi2MatchMCHMFT.reserve(muons.size()); + for (const auto& muon : muons) { + if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + const auto& muons_per_MCHMID = muons.sliceBy(fwdtracksPerMCHTrack, muon.globalIndex()); + // LOGF(info, "stanadalone: muon.globalIndex() = %d, muon.chi2MatchMCHMFT() = %f", muon.globalIndex(), muon.chi2MatchMCHMFT()); + // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); + + float min_chi2MatchMCHMFT = 1e+10; + std::tuple tupleIds_at_min; + for (const auto& muon_tmp : muons_per_MCHMID) { + if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { + min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); + tupleIds_at_min = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); + } + } + } + vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min); + // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); + } + } // end of muon loop + } + + void processElectronSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::McCollisions const&, aod::McParticles const& mcParticles) + { + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!isSelectedEvent(collision)) { + continue; + } + + if (!collision.has_mcCollision()) { + continue; + } + + float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; + if (centrality < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centrality) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCollision_mid, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!track.has_mcParticle()) { + continue; + } + + auto mctrack = track.template mcParticle_as(); + auto mccollision_from_mctrack = mctrack.template mcCollision_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + fillElectron(collision, track, mcParticles); + } // end of track loop + } // end of collision loop + } + PROCESS_SWITCH(checkMCTemplate, processElectronSA, "check mc template for electron at midrapidity", true); + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + void processElectronTTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const&, aod::TrackAssoc const& trackIndices, aod::McCollisions const&, aod::McParticles const& mcParticles) + { + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!isSelectedEvent(collision)) { + continue; + } + + if (!collision.has_mcCollision()) { + continue; + } + + float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; + if (centrality < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centrality) { + continue; + } + + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (const auto& trackId : trackIdsThisCollision) { + auto track = trackId.template track_as(); + if (!track.has_mcParticle()) { + continue; + } + auto mctrack = track.template mcParticle_as(); + auto mccollision_from_mctrack = mctrack.template mcCollision_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + fillElectron(collision, track, mcParticles); + } // end of track loop + } // end of collision loop + } + PROCESS_SWITCH(checkMCTemplate, processElectronTTCA, "check mc template for electron at midrapidity", false); + + void processMuonSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::McCollisions const&, aod::McParticles const& mcParticles) + { + findBestMatchPerMCHMID(fwdtracks); + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!isSelectedEvent(collision)) { + continue; + } + + if (!collision.has_mcCollision()) { + continue; + } + + float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; + if (centrality < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centrality) { + continue; + } + + const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision_fwd, collision.globalIndex()); + for (const auto& muon : fwdtracks_per_coll) { + if (!muon.has_mcParticle()) { + continue; + } + + auto mctrack = muon.template mcParticle_as(); + auto mccollision_from_mctrack = mctrack.template mcCollision_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + fillMuon(collision, muon, mcParticles); + } // end of standalone muon loop + + } // end of collision loop + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); + } + PROCESS_SWITCH(checkMCTemplate, processMuonSA, "check mc template for muon at forward rapidity", false); + + Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; + void processMuonTTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const& mcParticles) + { + findBestMatchPerMCHMID(fwdtracks); + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!isSelectedEvent(collision)) { + continue; + } + + if (!collision.has_mcCollision()) { + continue; + } + + float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; + if (centrality < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centrality) { + continue; + } + + auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + auto muon = fwdtrackId.template fwdtrack_as(); + if (!muon.has_mcParticle()) { + continue; + } + auto mctrack = muon.template mcParticle_as(); + auto mccollision_from_mctrack = mctrack.template mcCollision_as(); + if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + fillMuon(collision, muon, mcParticles); + } // end of fwdtrack loop + } // end of collision loop + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); + } + PROCESS_SWITCH(checkMCTemplate, processMuonTTCA, "check mc template for muon at forward rapidity", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"check-mc-template"})}; +} diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx index 5df5855d171..71d1d91139b 100644 --- a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -15,36 +15,46 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/Core/RecoDecay.h" #include "Common/Core/fwdtrackUtilities.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -#include +#include +#include +#include #include #include #include @@ -52,6 +62,8 @@ #include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -146,6 +158,8 @@ struct CreateResolutionMap { Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; + Configurable checkPIDforTracking{"checkPIDforTracking", false, "check for PID in tracking"}; + Configurable PartIdentifier{"PartIdentifier", 2, "Particle identifier for selected particle; 0: electron, 1: muon, 2: pion, 3: kaon, 4: proton, 5: deuteron, 6: triton, 7: helium3, 8: alpha"}; } electroncuts; struct : ConfigurableGroup { @@ -179,6 +193,7 @@ struct CreateResolutionMap { Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to require MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{4}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; + Configurable cfgApplyPreselectionInBestMatch{"cfgApplyPreselectionInBestMatch", false, "flag to apply preselection in find best match function"}; } muoncuts; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -497,6 +512,10 @@ struct CreateResolutionMap { } } + if (electroncuts.checkPIDforTracking && track.pidForTracking() != static_cast(std::abs(electroncuts.PartIdentifier))) { + return false; + } + return true; } @@ -556,7 +575,7 @@ struct CreateResolutionMap { if (muon.chi2MatchMCHMID() < 0.f) { // this should never happen. only for protection. return; } - o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon, muon, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT); + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon, muon, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); float pt = propmuonAtPV.getPt(); float eta = propmuonAtPV.getEta(); @@ -592,17 +611,17 @@ struct CreateResolutionMap { if (mcparticle.globalIndex() != mcparticle_MCHMID.globalIndex()) { // this should not happen. this is only for protection. return; } - if (cfg_reject_fake_match_mft_mch && mcparticle.globalIndex() != mcparticle_MFT.globalIndex()) { // evaluate mismatch + if (cfg_reject_fake_match_mft_mch && mcparticle_MCHMID.globalIndex() != mcparticle_MFT.globalIndex()) { // evaluate mismatch return; } - o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT); + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMID); - // o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT); + // o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT, 0.0); // float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); // float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); // float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); @@ -626,9 +645,9 @@ struct CreateResolutionMap { if constexpr (withMFTCov) { auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); - auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, muoncuts.matchingZ, mBzMFT); // propagated to matching plane - o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update - mftsaAtMP.propagateToZhelix(muoncuts.matchingZ, mBzMFT); // propagated to matching plane + auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, muoncuts.matchingZ, mBzMFT, 0.0); // propagated to matching plane + o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update + mftsaAtMP.propagateToZhelix(muoncuts.matchingZ, mBzMFT); // propagated to matching plane etaMatchedMFTatMP = mftsaAtMP.getEta(); phiMatchedMFTatMP = mftsaAtMP.getPhi(); etaMatchedMCHMIDatMP = muonAtMP.getEta(); @@ -680,12 +699,12 @@ struct CreateResolutionMap { } } else if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(muon, muon, collision, propagationPoint::kToRabs, muoncuts.matchingZ, mBzMFT); // this is necessary only for MuonStandaloneTrack + o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(muon, muon, collision, propagationPoint::kToRabs, muoncuts.matchingZ, mBzMFT, 0.0); // this is necessary only for MuonStandaloneTrack 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 - o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(muon, muon, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT); + o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(muon, muon, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT, 0.0); dcaX = propmuonAtDCA.getX() - collision.posX(); dcaY = propmuonAtDCA.getY() - collision.posY(); dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); @@ -874,31 +893,80 @@ struct CreateResolutionMap { } std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; - template - void findBestMatchPerMCHMID(TMuons const& muons) + template + void findBestMatchPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&) { - vec_min_chi2MatchMCHMFT.reserve(muons.size()); - for (const auto& muon : muons) { - if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - const auto& muons_per_MCHMID = muons.sliceBy(fwdtracksPerMCHTrack, muon.globalIndex()); - // LOGF(info, "stanadalone: muon.globalIndex() = %d, muon.chi2MatchMCHMFT() = %f", muon.globalIndex(), muon.chi2MatchMCHMFT()); - // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); - - float min_chi2MatchMCHMFT = 1e+10; - std::tuple tupleIds_at_min; - for (const auto& muon_tmp : muons_per_MCHMID) { - if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); - if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { - min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); - tupleIds_at_min = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); - } + if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + return; + } + if (!fwdtrack.has_mcParticle()) { + return; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, muoncuts.matchingZ, mBzMFT, 0.0); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = fwdtrack.p() * dcaXY_Matched; + + auto muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); + + float min_chi2MatchMCHMFT = 1e+10; + std::tuple tupleIds_at_min; + for (const auto& muon_tmp : muons_per_MCHMID) { + if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // LOGF(info, "muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId(), muon_tmp.chi2MatchMCHMFT()); + auto mchtrack = muon_tmp.template matchMCHTrack_as(); // MCH-MID + auto mfttrack = muon_tmp.template matchMFTTrack_as(); // MFTsa + + if (muon_tmp.chi2() < 0.f || muon_tmp.chi2MatchMCHMFT() < 0.f || muon_tmp.chi2MatchMCHMID() < 0.f || mfttrack.chi2() < 0.f) { // reject negative chi2, i.e. wrong. + continue; + } + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon_tmp, muon_tmp, collision, propagationPoint::kToVertex, muoncuts.matchingZ, mBzMFT, 0.0); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + if (muoncuts.refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + int ndf = 2 * (mchtrack.nClusters() + mfttrack.nClusters()) - 5; + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + if (muoncuts.cfgApplyPreselectionInBestMatch) { + if (!isSelectedMuon(pt, eta, muon_tmp.rAtAbsorberEnd(), pDCA, muon_tmp.chi2() / ndf, muon_tmp.trackType(), dcaXY)) { + continue; } + if (std::sqrt(std::pow(deta / muoncuts.cfg_max_deta, 2) + std::pow(dphi / muoncuts.cfg_max_dphi, 2)) > 1.f) { + continue; + } + if (muon_tmp.chi2MatchMCHMFT() > muoncuts.cfg_max_matching_chi2_mftmch) { + continue; + } + } + + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { + min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); + tupleIds_at_min = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); } - vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min); - // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); } - } // end of muon loop + } + vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min); + // LOGF(info, "min: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f", std::get<0>(tupleIds_at_min), std::get<1>(tupleIds_at_min), std::get<2>(tupleIds_at_min), min_chi2MatchMCHMFT); } void processElectronSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::McCollisions const&, aod::McParticles const&) @@ -976,9 +1044,19 @@ struct CreateResolutionMap { // 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 processMuonSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::McCollisions const&, aod::McParticles const&) + void processMuonSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::McCollisions const&, aod::McParticles const&) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template bc_as(); + initCCDB(bc); + const auto& fwdtracks_per_coll = fwdtracks.sliceBy(perCollision_fwd, collision.globalIndex()); + for (const auto& fwdtrack : fwdtracks_per_coll) { + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); + } // end of fwdtrack loop + } // end of collision loop + for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); initCCDB(bc); @@ -1016,51 +1094,18 @@ struct CreateResolutionMap { PROCESS_SWITCH(CreateResolutionMap, processMuonSA, "create resolution map for muon at forward rapidity", true); Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; - void processMuonTTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) + void processMuonTTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) { - findBestMatchPerMCHMID(fwdtracks); + vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); for (const auto& collision : collisions) { - auto bc = collision.template foundBC_as(); + auto bc = collision.template bc_as(); initCCDB(bc); - - if (!isSelectedEvent(collision)) { - continue; - } - - if (!collision.has_mcCollision()) { - continue; - } - - float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; - // auto mccollision = collision.template mcCollision_as(); - // registry.fill(HIST("Event/Muon/hImpPar_Centrality"), mccollision.impactParameter(), centrality); - auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { - auto muon = fwdtrackId.template fwdtrack_as(); - if (!muon.has_mcParticle()) { - continue; - } - auto mctrack = muon.template mcParticle_as(); - auto mccollision_from_mctrack = mctrack.template mcCollision_as(); - if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { - continue; - } - fillMuon(collision, muon, nullptr, centrality); + auto fwdtrack = fwdtrackId.template fwdtrack_as(); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop - vec_min_chi2MatchMCHMFT.clear(); - vec_min_chi2MatchMCHMFT.shrink_to_fit(); - } - PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA, "create resolution map for muon at forward rapidity", false); - - std::unordered_map map_mfttrackcovs; - void processMuonTTCA_withMFTCov(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::MFTTracksCov const& mftCovs, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) - { - for (const auto& mfttrackConv : mftCovs) { - map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); - } - findBestMatchPerMCHMID(fwdtracks); for (const auto& collision : collisions) { auto bc = collision.template foundBC_as(); @@ -1089,14 +1134,58 @@ struct CreateResolutionMap { if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { continue; } - fillMuon(collision, muon, mftCovs, centrality); + fillMuon(collision, muon, nullptr, centrality); } // end of fwdtrack loop } // end of collision loop - map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); } - PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA_withMFTCov, "create resolution map for muon at forward rapidity", false); + PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA, "create resolution map for muon at forward rapidity", false); + + std::unordered_map map_mfttrackcovs; + + // void processMuonTTCA_withMFTCov(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFwdTracks const& fwdtracks, MyMFTTracks const&, aod::MFTTracksCov const& mftCovs, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McCollisions const&, aod::McParticles const&) + // { + // for (const auto& mfttrackConv : mftCovs) { + // map_mfttrackcovs[mfttrackConv.matchMFTTrackId()] = mfttrackConv.globalIndex(); + // } + // findBestMatchPerMCHMID(fwdtracks); + + // for (const auto& collision : collisions) { + // auto bc = collision.template foundBC_as(); + // initCCDB(bc); + + // if (!isSelectedEvent(collision)) { + // continue; + // } + + // if (!collision.has_mcCollision()) { + // continue; + // } + + // float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}[cfgCentEstimator]; + // // auto mccollision = collision.template mcCollision_as(); + // // registry.fill(HIST("Event/Muon/hImpPar_Centrality"), mccollision.impactParameter(), centrality); + + // auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); + // for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { + // auto muon = fwdtrackId.template fwdtrack_as(); + // if (!muon.has_mcParticle()) { + // continue; + // } + // auto mctrack = muon.template mcParticle_as(); + // auto mccollision_from_mctrack = mctrack.template mcCollision_as(); + // if (cfgEventGeneratorType >= 0 && mccollision_from_mctrack.getSubGeneratorId() != cfgEventGeneratorType) { + // continue; + // } + // fillMuon(collision, muon, mftCovs, centrality); + // } // end of fwdtrack loop + // } // end of collision loop + // map_mfttrackcovs.clear(); + // vec_min_chi2MatchMCHMFT.clear(); + // vec_min_chi2MatchMCHMFT.shrink_to_fit(); + // } + // PROCESS_SWITCH(CreateResolutionMap, processMuonTTCA_withMFTCov, "create resolution map for muon at forward rapidity", false); void processGen(aod::McCollisions const& mcCollisions) { diff --git a/PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx b/PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx new file mode 100644 index 00000000000..a608e07d79a --- /dev/null +++ b/PWGEM/Dilepton/Tasks/createResolutionMapDerived.cxx @@ -0,0 +1,579 @@ +// 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 map for electrons/muons over derived data. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" + +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::soa; + +struct createResolutionMapDerived { + + Configurable cfgEventGeneratorType{"cfgEventGeneratorType", -1, "if positive, select event generator type. i.e. gap or signal"}; + Configurable cfg_require_true_mc_collision_association{"cfg_require_true_mc_collision_association", false, "flag to require true mc collision association"}; + + ConfigurableAxis ConfPtGenBins{"ConfPtGenBins", {VARIABLE_WIDTH, 0.00, 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}, "gen. pT bins for output histograms"}; + ConfigurableAxis ConfCentBins{"ConfCentBins", {VARIABLE_WIDTH, 0, 10, 30, 50, 110}, "centrality (%) bins for output histograms"}; + + ConfigurableAxis ConfEtaCBGenBins{"ConfEtaCBGenBins", {30, -1.5, +1.5}, "gen. eta bins at midrapidity for output histograms"}; + ConfigurableAxis ConfEtaFWDGenBins{"ConfEtaFWDGenBins", {40, -5.5, -1.5}, "gen. eta bins at forward rapidity for output histograms"}; + ConfigurableAxis ConfPhiGenBins{"ConfPhiGenBins", {36, 0, 2.f * M_PI}, "gen. phi bins at forward rapidity for output histograms"}; + Configurable cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + + ConfigurableAxis ConfRelDeltaPtCBBins{"ConfRelDeltaPtCBBins", {200, -1.f, +1.f}, "rel. dpt for output histograms at midrapidity"}; + ConfigurableAxis ConfRelDeltaPtFWDBins{"ConfRelDeltaPtFWDBins", {200, -1.f, +1.f}, "rel. dpt for output histograms at fwd rapidity"}; + + ConfigurableAxis ConfDeltaEtaCBBins{"ConfDeltaEtaCBBins", {200, -0.5f, +0.5f}, "deta bins for output histograms at midrapidity"}; + ConfigurableAxis ConfDeltaEtaFWDBins{"ConfDeltaEtaFWDBins", {200, -0.5f, +0.5f}, "deta bins for output histograms at fwd rapidity"}; + ConfigurableAxis ConfDeltaPhiBins{"ConfDeltaPhiBins", {200, -0.5f, +0.5f}, "dphi bins for output histograms"}; + + Configurable cfgFillTHnSparse{"cfgFillTHnSparse", true, "fill THnSparse for output"}; + Configurable cfgFillTH2{"cfgFillTH2", false, "fill TH2 for output"}; + + EMEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + + // for RCT + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT_hadronPID, CBT_muon_glo, CBT_muon]. see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb/OO"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + 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", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; + } eventcuts; + + DielectronCut fDielectronCut; + struct : ConfigurableGroup { + std::string prefix = "electroncut_group"; + + Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.05, "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", -2, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", +2, "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_mirror_phi_track{"cfg_mirror_phi_track", false, "mirror the phi cut around Pi, min and max Phi should be in 0-Pi"}; + Configurable cfg_reject_phi_track{"cfg_reject_phi_track", false, "reject the phi interval"}; + 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + 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_chi2tof{"cfg_max_chi2tof", 1e+10, "max chi2 TOF"}; + 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_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 cfgRefR{"cfgRefR", 0.50, "ref. radius (m) for calculating phi position"}; // 0.50 +/- 0.06 can be syst. unc. + Configurable cfg_min_phiposition_track{"cfg_min_phiposition_track", 0.f, "min phi position for single track at certain radius"}; + Configurable cfg_max_phiposition_track{"cfg_max_phiposition_track", 6.3, "max phi position for single track at certain radius"}; + Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between ITS and TPC"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between ITS and TPC"}; // this is only for MC study, as we don't know correct match in data. + + Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "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", -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 cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.f, "min. pin for pion rejection in TPC"}; + Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 1e+10, "max. pin for pion rejection in TPC"}; + Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + + Configurable checkPIDForTracking{"checkPIDForTracking", false, "check PID for tracking"}; + Configurable PartIdentifier{"PartIdentifier", 2, "Particle identifier for selected particle; 0: electron, 1: muon, 2: pion, 3: kaon, 4: proton, 5: deuteron, 6: triton, 7: helium3, 8: alpha"}; + + // configuration for PID ML + Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; + Configurable> cutsMl{"cutsMl", std::vector{0.95}, "ML cuts per bin"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature"}, "Names of ML model input features"}; + Configurable nameBinningFeature{"nameBinningFeature", "pt", "Names of ML model binning feature"}; + 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)"}; + } electroncuts; + + DimuonCut fDimuonCut; + struct : ConfigurableGroup { + std::string prefix = "muoncut_group"; + + Configurable cfg_track_type{"cfg_track_type", 0, "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_max_pt_track{"cfg_max_pt_track", 1e+10, "max pT for single track"}; + Configurable cfg_min_eta_track{"cfg_min_eta_track", -10, "min eta for single track"}; + Configurable cfg_max_eta_track{"cfg_max_eta_track", 0, "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+6, "max chi2/ndf"}; + Configurable cfg_max_chi2mft{"cfg_max_chi2mft", 1e+6, "max chi2/ndf"}; + // Configurable cfg_max_matching_chi2_mftmch{"cfg_max_matching_chi2_mftmch", 40, "max chi2 for MFT-MCH matching"}; + Configurable cfg_border_pt_for_chi2mchmft{"cfg_border_pt_for_chi2mchmft", 0, "border pt for different max chi2 for MFT-MCH matching"}; + Configurable cfg_max_matching_chi2_mftmch_lowPt{"cfg_max_matching_chi2_mftmch_lowPt", 8, "max chi2 for MFT-MCH matching for low pT"}; + Configurable cfg_max_matching_chi2_mftmch_highPt{"cfg_max_matching_chi2_mftmch_highPt", 40, "max chi2 for MFT-MCH matching for high pT"}; + 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"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; + Configurable acceptOnlyCorrectMatch{"acceptOnlyCorrectMatch", false, "flag to accept only correct match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + Configurable acceptOnlyWrongMatch{"acceptOnlyWrongMatch", false, "flag to accept only wrong match between MFT and MCH-MID"}; // this is only for MC study, as we don't know correct match in data. + } muoncuts; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::aod::rctsel::RCTFlagsChecker rctChecker; + + ~createResolutionMapDerived() {} + + void init(o2::framework::InitContext&) + { + rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); + + DefineEMEventCut(); + + if (doprocessElectron) { + DefineDielectronCut(); + } + if (doprocessMuon) { + DefineDimuonCut(); + } + addHistograms(); + } + + void addHistograms() + { + // registry.add("Event/Electron/hImpPar_Centrality", "true imapact parameter vs. estimated centrality;impact parameter (fm);centrality (%)", kTH2F, {{200, 0, 20}, {110, 0, 110}}, true); + // registry.add("Event/Electron/hImpPar_Centrality", "true imapact parameter vs. estimated centrality;impact parameter (fm);centrality (%)", kTH2F, {{200, 0, 20}, {110, 0, 110}}, true); + + if (doprocessGen) { + registry.add("Event/hGenID", "generator ID;generator ID;Number of mc collisions", kTH1F, {{7, -1.5, 5.5}}, true); + } + + const AxisSpec axis_cent{ConfCentBins, "centrality (%)"}; + const AxisSpec axis_pt_gen{ConfPtGenBins, "p_{T,l}^{gen} (GeV/c)"}; + const AxisSpec axis_eta_cb_gen{ConfEtaCBGenBins, "#eta_{l}^{gen}"}; + const AxisSpec axis_eta_fwd_gen{ConfEtaFWDGenBins, "#eta_{l}^{gen}"}; + const AxisSpec axis_phi_gen{ConfPhiGenBins, "#varphi_{l}^{gen} (rad.)"}; + const AxisSpec axis_dpt_cb{ConfRelDeltaPtCBBins, "(p_{T,l}^{gen} - p_{T,l}^{rec})/p_{T,l}^{gen}"}; + const AxisSpec axis_dpt_fwd{ConfRelDeltaPtFWDBins, "(p_{T,l}^{gen} - p_{T,l}^{rec})/p_{T,l}^{gen}"}; + const AxisSpec axis_deta_cb{ConfDeltaEtaCBBins, "#eta_{l}^{gen} - #eta_{l}^{rec}"}; + const AxisSpec axis_deta_fwd{ConfDeltaEtaFWDBins, "#eta_{l}^{gen} - #eta_{l}^{rec}"}; + const AxisSpec axis_dphi{ConfDeltaPhiBins, "#varphi_{l}^{gen} - #varphi_{l}^{rec} (rad.)"}; + const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true sign"}; + + if (doprocessElectron) { + registry.add("Electron/hPIDForTracking", "PID for trackng", kTH1F, {{9, -0.5, 8.5}}, false); // see numbering in O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + if (cfgFillTH2) { + registry.add("Electron/hPt", "rec. p_{T,e};p_{T,e} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("Electron/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{e} (rad.);#eta_{e}", kTH2F, {{90, 0, 2 * M_PI}, {40, -2, +2}}, false); + registry.add("Electron/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt_cb}}, true); + registry.add("Electron/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta_cb}}, 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); + } + if (cfgFillTHnSparse) { + registry.add("Electron/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_cb_gen, axis_phi_gen, axis_charge_gen, axis_dpt_cb, axis_deta_cb, axis_dphi}, true); + } + } + + if (doprocessMuon) { + if (muoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (cfgFillTH2) { + registry.add("GlobalMuon/hPt", "rec. p_{T,#mu};p_{T,#mu} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("GlobalMuon/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{#mu} (rad.);#eta_{#mu}", kTH2F, {{90, 0, 2 * M_PI}, {60, -6, 0}}, false); + registry.add("GlobalMuon/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt_fwd}}, true); + registry.add("GlobalMuon/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta_fwd}}, true); + registry.add("GlobalMuon/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("GlobalMuon/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + } + if (cfgFillTHnSparse) { + registry.add("GlobalMuon/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt_fwd, axis_deta_fwd, axis_dphi}, true); + } + } else if (muoncuts.cfg_track_type == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (cfgFillTH2) { + registry.add("StandaloneMuon/hPt", "rec. p_{T,#mu};p_{T,#mu} (GeV/c)", kTH1F, {{1000, 0, 10}}, false); + registry.add("StandaloneMuon/hEtaPhi", "rec. #eta vs. #varphi;#varphi_{#mu} (rad.);#eta_{#mu}", kTH2F, {{90, 0, 2 * M_PI}, {60, -6, 0}}, false); + registry.add("StandaloneMuon/Ptgen_RelDeltaPt", "resolution", kTH2F, {{axis_pt_gen}, {axis_dpt_fwd}}, true); + registry.add("StandaloneMuon/Ptgen_DeltaEta", "resolution", kTH2F, {{axis_pt_gen}, {axis_deta_fwd}}, true); + registry.add("StandaloneMuon/Ptgen_DeltaPhi_Pos", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + registry.add("StandaloneMuon/Ptgen_DeltaPhi_Neg", "resolution", kTH2F, {{axis_pt_gen}, {axis_dphi}}, true); + } + if (cfgFillTHnSparse) { + registry.add("StandaloneMuon/hs_reso", "8D resolution", kTHnSparseF, {axis_cent, axis_pt_gen, axis_eta_fwd_gen, axis_phi_gen, axis_charge_gen, axis_dpt_fwd, axis_deta_fwd, axis_dphi}, true); + } + } + } + } + + void DefineEMEventCut() + { + fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); + fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); + fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); + } + + void DefineDielectronCut() + { + fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); + + // for track + fDielectronCut.SetTrackPtRange(electroncuts.cfg_min_pt_track, electroncuts.cfg_max_pt_track); + fDielectronCut.SetTrackEtaRange(electroncuts.cfg_min_eta_track, +electroncuts.cfg_max_eta_track); + fDielectronCut.SetTrackPhiRange(electroncuts.cfg_min_phi_track, electroncuts.cfg_max_phi_track, electroncuts.cfg_mirror_phi_track, electroncuts.cfg_reject_phi_track); + fDielectronCut.SetMinNClustersTPC(electroncuts.cfg_min_ncluster_tpc); + fDielectronCut.SetMinNCrossedRowsTPC(electroncuts.cfg_min_ncrossedrows); + fDielectronCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDielectronCut.SetMaxFracSharedClustersTPC(electroncuts.cfg_max_frac_shared_clusters_tpc); + fDielectronCut.SetChi2PerClusterTPC(0.0, electroncuts.cfg_max_chi2tpc); + fDielectronCut.SetChi2PerClusterITS(0.0, electroncuts.cfg_max_chi2its); + fDielectronCut.SetNClustersITS(electroncuts.cfg_min_ncluster_its, 7); + fDielectronCut.SetMeanClusterSizeITS(electroncuts.cfg_min_its_cluster_size, electroncuts.cfg_max_its_cluster_size); + fDielectronCut.SetTrackMaxDcaXY(electroncuts.cfg_max_dcaxy); + fDielectronCut.SetTrackMaxDcaZ(electroncuts.cfg_max_dcaz); + fDielectronCut.RequireITSibAny(electroncuts.cfg_require_itsib_any); + fDielectronCut.RequireITSib1st(electroncuts.cfg_require_itsib_1st); + fDielectronCut.SetChi2TOF(0.0, electroncuts.cfg_max_chi2tof); + // fDielectronCut.SetRelDiffPin(electroncuts.cfg_min_rel_diff_pin, electroncuts.cfg_max_rel_diff_pin); + fDielectronCut.EnableTTCA(electroncuts.enableTTCA); + + // for eID + fDielectronCut.SetPIDScheme(electroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(electroncuts.cfg_min_TPCNsigmaEl, electroncuts.cfg_max_TPCNsigmaEl); + // fDielectronCut.SetTPCNsigmaMuRange(electroncuts.cfg_min_TPCNsigmaMu, electroncuts.cfg_max_TPCNsigmaMu); + fDielectronCut.SetTPCNsigmaPiRange(electroncuts.cfg_min_TPCNsigmaPi, electroncuts.cfg_max_TPCNsigmaPi); + fDielectronCut.SetTPCNsigmaKaRange(electroncuts.cfg_min_TPCNsigmaKa, electroncuts.cfg_max_TPCNsigmaKa); + fDielectronCut.SetTPCNsigmaPrRange(electroncuts.cfg_min_TPCNsigmaPr, electroncuts.cfg_max_TPCNsigmaPr); + fDielectronCut.SetTOFNsigmaElRange(electroncuts.cfg_min_TOFNsigmaEl, electroncuts.cfg_max_TOFNsigmaEl); + fDielectronCut.SetPinRangeForPionRejectionTPC(electroncuts.cfg_min_pin_pirejTPC, electroncuts.cfg_max_pin_pirejTPC); + + if (electroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut + std::vector binsML{}; + binsML.reserve(electroncuts.binsMl.value.size()); + for (size_t i = 0; i < electroncuts.binsMl.value.size(); i++) { + binsML.emplace_back(electroncuts.binsMl.value[i]); + } + std::vector thresholdsML{}; + thresholdsML.reserve(electroncuts.cutsMl.value.size()); + for (size_t i = 0; i < electroncuts.cutsMl.value.size(); i++) { + thresholdsML.emplace_back(electroncuts.cutsMl.value[i]); + } + fDielectronCut.SetMLThresholds(binsML, thresholdsML); + + // static constexpr int nClassesMl = 2; + // const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + // const std::vector labelsClasses = {"Background", "Signal"}; + // const uint32_t nBinsMl = electroncuts.binsMl.value.size() - 1; + // const std::vector labelsBins(nBinsMl, "bin"); + // double cutsMlArr[nBinsMl][nClassesMl]; + // for (uint32_t i = 0; i < nBinsMl; i++) { + // cutsMlArr[i][0] = 0.; + // cutsMlArr[i][1] = electroncuts.cutsMl.value[i]; + // } + // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; + + // mlResponseSingleTrack.configure(electroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); + // if (electroncuts.loadModelsFromCCDB) { + // ccdbApi.init(ccdburl); + // mlResponseSingleTrack.setModelPathsCCDB(electroncuts.onnxFileNames.value, ccdbApi, electroncuts.onnxPathsCCDB.value, electroncuts.timestampCCDB.value); + // } else { + // mlResponseSingleTrack.setModelPathsLocal(electroncuts.onnxFileNames.value); + // } + // mlResponseSingleTrack.cacheInputFeaturesIndices(electroncuts.namesInputFeatures); + // mlResponseSingleTrack.cacheBinningIndex(electroncuts.nameBinningFeature); + // mlResponseSingleTrack.init(electroncuts.enableOptimizations.value); + + } // end of PID ML + } + + void DefineDimuonCut() + { + fDimuonCut = DimuonCut("fDimuonCut", "fDimuonCut"); + + // for track + fDimuonCut.SetTrackType(muoncuts.cfg_track_type); + fDimuonCut.SetTrackPtRange(muoncuts.cfg_min_pt_track, muoncuts.cfg_max_pt_track); + fDimuonCut.SetTrackEtaRange(muoncuts.cfg_min_eta_track, muoncuts.cfg_max_eta_track); + fDimuonCut.SetTrackPhiRange(muoncuts.cfg_min_phi_track, muoncuts.cfg_max_phi_track); + fDimuonCut.SetNClustersMFT(muoncuts.cfg_min_ncluster_mft, 10); + fDimuonCut.SetNClustersMCHMID(muoncuts.cfg_min_ncluster_mch, 20); + fDimuonCut.SetChi2(0.f, muoncuts.cfg_max_chi2); + fDimuonCut.SetChi2MFT(0.f, muoncuts.cfg_max_chi2mft); + // fDimuonCut.SetMatchingChi2MCHMFT(0.f, muoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMaxMatchingChi2MCHMFTPtDep([&](float pt) { return (pt < muoncuts.cfg_border_pt_for_chi2mchmft ? muoncuts.cfg_max_matching_chi2_mftmch_lowPt : muoncuts.cfg_max_matching_chi2_mftmch_highPt); }); + fDimuonCut.SetMatchingChi2MCHMID(0.f, muoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, muoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(muoncuts.cfg_min_rabs, muoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(muoncuts.cfg_max_relDPt_wrt_matchedMCHMID, muoncuts.cfg_max_DEta_wrt_matchedMCHMID, muoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(muoncuts.requireMFTHitMap, muoncuts.requiredMFTDisks); + fDimuonCut.EnableTTCA(muoncuts.enableTTCA); + } + + template + void create(TCollisions const& collisions, TTracks const& tracks, TPerCollision const& perCollision, TCut const& cut) + { + for (const auto& collision : collisions) { + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + float centrality = std::array{collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV()}[eventcuts.cfgCentEstimator]; + if (centrality < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centrality) { + continue; + } + + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + return; + } + + auto tracks_per_coll = tracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!cut.IsSelectedTrack(track)) { + continue; + } + + auto mcParticle = track.template emmcparticle_as(); + auto mcCollision = mcParticle.template emmcevent_as(); + if (cfgEventGeneratorType >= 0 && mcCollision.getSubGeneratorId() != cfgEventGeneratorType) { + continue; + } + + if (cfg_require_true_mc_collision_association && mcParticle.emmceventId() != collision.emmceventId()) { + return; + } + + if constexpr (std::is_same_v, MyMCElectrons>) { + if (std::abs(mcParticle.pdgCode()) != 11) { + continue; + } + + if (electroncuts.acceptOnlyCorrectMatch && o2::aod::pwgem::dilepton::utils::mcutil::hasFakeMatchITSTPC(track)) { + continue; + } + if (electroncuts.acceptOnlyWrongMatch && !o2::aod::pwgem::dilepton::utils::mcutil::hasFakeMatchITSTPC(track)) { + continue; + } + + registry.fill(HIST("Electron/hPIDForTracking"), track.pidForTracking()); + if (electroncuts.checkPIDForTracking && track.pidForTracking() != static_cast(electroncuts.PartIdentifier)) { + continue; + } + + if (cfgFillTHnSparse) { + registry.fill(HIST("Electron/hs_reso"), centrality, mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), -mcParticle.pdgCode() / 11, (mcParticle.pt() - track.pt()) / mcParticle.pt(), mcParticle.eta() - track.eta(), mcParticle.phi() - track.phi()); + } + if (cfgFillTH2) { + registry.fill(HIST("Electron/hPt"), track.pt()); + registry.fill(HIST("Electron/hEtaPhi"), track.phi(), track.eta()); + registry.fill(HIST("Electron/Ptgen_RelDeltaPt"), mcParticle.pt(), (mcParticle.pt() - track.pt()) / mcParticle.pt()); + registry.fill(HIST("Electron/Ptgen_DeltaEta"), mcParticle.pt(), mcParticle.eta() - track.eta()); + if (mcParticle.pdgCode() == -11) { // positron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Pos"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } else if (mcParticle.pdgCode() == 11) { // electron + registry.fill(HIST("Electron/Ptgen_DeltaPhi_Neg"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } + } + } else if constexpr (std::is_same_v, MyMCMuons>) { + if (std::abs(mcParticle.pdgCode()) != 13) { + continue; + } + + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack)) { + if (muoncuts.acceptOnlyCorrectMatch) { + if (track.emmcparticleId() != track.emmftmcparticleId()) { + continue; + } + } + if (muoncuts.acceptOnlyWrongMatch) { // reject correctly matched MFT-MCH-MID for bkg estimation + if (track.emmcparticleId() == track.emmftmcparticleId()) { + continue; + } + } + + if (cfgFillTHnSparse) { + registry.fill(HIST("GlobalMuon/hs_reso"), centrality, mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), -mcParticle.pdgCode() / 13, (mcParticle.pt() - track.pt()) / mcParticle.pt(), mcParticle.eta() - track.eta(), mcParticle.phi() - track.phi()); + } + + if (cfgFillTH2) { + registry.fill(HIST("GlobalMuon/hPt"), track.pt()); + registry.fill(HIST("GlobalMuon/hEtaPhi"), track.phi(), track.eta()); + registry.fill(HIST("GlobalMuon/Ptgen_RelDeltaPt"), mcParticle.pt(), (mcParticle.pt() - track.pt()) / mcParticle.pt()); + registry.fill(HIST("GlobalMuon/Ptgen_DeltaEta"), mcParticle.pt(), mcParticle.eta() - track.eta()); + if (mcParticle.pdgCode() == -13) { // positive muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Pos"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } else if (mcParticle.pdgCode() == 13) { // negative muon + registry.fill(HIST("GlobalMuon/Ptgen_DeltaPhi_Neg"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } + } + } else if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { + if (cfgFillTHnSparse) { + registry.fill(HIST("StandaloneMuon/hs_reso"), centrality, mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), -mcParticle.pdgCode() / 13, (mcParticle.pt() - track.pt()) / mcParticle.pt(), mcParticle.eta() - track.eta(), mcParticle.phi() - track.phi()); + } + if (cfgFillTH2) { + registry.fill(HIST("StandaloneMuon/hPt"), track.pt()); + registry.fill(HIST("StandaloneMuon/hEtaPhi"), track.phi(), track.eta()); + registry.fill(HIST("StandaloneMuon/Ptgen_RelDeltaPt"), mcParticle.pt(), (mcParticle.pt() - track.pt()) / mcParticle.pt()); + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaEta"), mcParticle.pt(), mcParticle.eta() - track.eta()); + if (mcParticle.pdgCode() == -13) { // positive muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Pos"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } else if (mcParticle.pdgCode() == 13) { // negative muon + registry.fill(HIST("StandaloneMuon/Ptgen_DeltaPhi_Neg"), mcParticle.pt(), mcParticle.phi() - track.phi()); + } + } + } + } + } // end of track loop per collision + } // end of collisions + } + + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; + + using MyMCElectrons = soa::Join; + using MyMCElectron = MyMCElectrons::iterator; + + using MyMCMuons = soa::Join; + using MyMCMuon = MyMCMuons::iterator; + + SliceCache cache; + Preslice perCollision_mid = aod::emprimaryelectron::emeventId; + Preslice perCollision_fwd = aod::emprimarymuon::emeventId; + + Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); + Filter collisionFilter_numContrib = eventcuts.cfgNumContribMin <= o2::aod::collision::numContrib && o2::aod::collision::numContrib < eventcuts.cfgNumContribMax; + Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using filteredMyCollisions = soa::Filtered; + + template + void processReso(filteredMyCollisions const& collisions, TTracks const& tracks, aod::EMMCEvents const&, aod::EMMCParticles const&) + { + if constexpr (std::is_same_v, MyMCElectrons>) { + create(collisions, tracks, perCollision_mid, fDielectronCut); + } else if constexpr (std::is_same_v, MyMCMuons>) { + create(collisions, tracks, perCollision_fwd, fDimuonCut); + } + } + + PROCESS_SWITCH_FULL(createResolutionMapDerived, processReso, processElectron, "create resolution map for electrons at mid rapidity", false); + PROCESS_SWITCH_FULL(createResolutionMapDerived, processReso, processMuon, "create resolution map for global muons at fwd rapidity", false); // gl or sa can be selected in subwagons. + + void processGen(aod::EMMCEvents const& mcCollisions) + { + for (const auto& mccollision : mcCollisions) { + registry.fill(HIST("Event/hGenID"), mccollision.getSubGeneratorId()); + } + } + PROCESS_SWITCH(createResolutionMapDerived, processGen, "process generated info", true); + + void processDummy(aod::EMMCEvents const&) {} + PROCESS_SWITCH(createResolutionMapDerived, processDummy, "process dummy", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"create-resolution-map-derived"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dielectron.cxx b/PWGEM/Dilepton/Tasks/dielectron.cxx index c8fa31b0e3b..042831bff30 100644 --- a/PWGEM/Dilepton/Tasks/dielectron.cxx +++ b/PWGEM/Dilepton/Tasks/dielectron.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx b/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx index 42cfa2eac28..8e5d04d67c5 100644 --- a/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx +++ b/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx @@ -15,10 +15,12 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/Core/DileptonHadronMPC.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/dielectronMC.cxx b/PWGEM/Dilepton/Tasks/dielectronMC.cxx index 3c525c29c6e..794b8a48a45 100644 --- a/PWGEM/Dilepton/Tasks/dielectronMC.cxx +++ b/PWGEM/Dilepton/Tasks/dielectronMC.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx b/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx index 478b48982e1..3595dbf8354 100644 --- a/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx +++ b/PWGEM/Dilepton/Tasks/dileptonPolarization.cxx @@ -15,57 +15,63 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -// #include "PWGEM/Dilepton/Utils/EMFwdTrack.h" #include "PWGEM/Dilepton/Utils/EMTrack.h" -// #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -// #include "PWGEM/Dilepton/Utils/EventMixingHandler.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/Core/RecoDecay.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -// #include "DataFormatsParameters/GRPMagField.h" -// #include "DataFormatsParameters/GRPObject.h" -// #include "DetectorsBase/GeometryManager.h" -// #include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" - -#include "Math/Vector4D.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include #include #include -#include +#include +#include #include #include #include #include +#include #include #include #include #include +#include + 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 namespace o2::aod::pwgem::dilepton::utils::pairutil; struct DileptonPolarization { // 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 cfgPairType{"cfgPairType", 0, "0:dielectron, 1:dimuon"}; Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; diff --git a/PWGEM/Dilepton/Tasks/dimuon.cxx b/PWGEM/Dilepton/Tasks/dimuon.cxx index 51b92ab81b7..be0a7d8386b 100644 --- a/PWGEM/Dilepton/Tasks/dimuon.cxx +++ b/PWGEM/Dilepton/Tasks/dimuon.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx b/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx index 2e0cf5f5e59..c34d4ba1dbb 100644 --- a/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx +++ b/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx @@ -15,10 +15,12 @@ // Please write to: daiki.sekihata@cern.ch #include "PWGEM/Dilepton/Core/DileptonHadronMPC.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/dimuonMC.cxx b/PWGEM/Dilepton/Tasks/dimuonMC.cxx index f505c073dc3..58e003819ac 100644 --- a/PWGEM/Dilepton/Tasks/dimuonMC.cxx +++ b/PWGEM/Dilepton/Tasks/dimuonMC.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx index 907161d9de2..d223c5d2c1c 100644 --- a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx +++ b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx @@ -23,38 +23,42 @@ #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Common/CCDB/TriggerAliases.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Field/MagneticField.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "TGeoGlobalMagField.h" -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include -#include #include -#include +#include + +#include +#include +#include +#include +#include +#include #include -using std::cout; -using std::endl; using std::string; using namespace o2; diff --git a/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx b/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx index 9a552f407ae..6efc22b11c4 100644 --- a/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx +++ b/PWGEM/Dilepton/Tasks/evaluateAcceptance.cxx @@ -16,40 +16,35 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TableHelper.h" - -// #include "Common/Core/trackUtilities.h" -// #include "Common/DataModel/Centrality.h" -// #include "Common/DataModel/CollisionAssociationTables.h" -// #include "Common/DataModel/EventSelection.h" -// #include "Common/DataModel/Multiplicity.h" -// #include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPLHCIFData.h" - -// #include "DataFormatsCalibration/MeanVertexObject.h" -// #include "DataFormatsParameters/GRPMagField.h" -// #include "DataFormatsParameters/GRPObject.h" -// #include "DetectorsBase/GeometryManager.h" -// #include "DetectorsBase/Propagator.h" - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include #include -#include +#include #include +#include #include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; diff --git a/PWGEM/Dilepton/Tasks/eventQC.cxx b/PWGEM/Dilepton/Tasks/eventQC.cxx index c6fe4e3689c..4d52520d119 100644 --- a/PWGEM/Dilepton/Tasks/eventQC.cxx +++ b/PWGEM/Dilepton/Tasks/eventQC.cxx @@ -14,34 +14,47 @@ // This code is for event QC for PWG-EM. // Please write to: daiki.sekihata@cern.ch -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" - -#include "TString.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include +#include +#include +#include +#include #include #include +#include #include #include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx b/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx index 49d6a823d05..8a07ff873da 100644 --- a/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx +++ b/PWGEM/Dilepton/Tasks/lmeeHFCocktail.cxx @@ -18,14 +18,32 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Task.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" - -#include "Math/Vector4D.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include + +#include + +#include +#include +#include #include using namespace o2; diff --git a/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx b/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx index 1cac2727e98..56bd936d9f3 100644 --- a/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx +++ b/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx @@ -14,17 +14,38 @@ /// \analysis task for lmee light flavour cocktail /// \author Daniel Samitz, , SMI Vienna -#include -#include -#include - -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 517ac9c4aaa..d962d51b94d 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -13,37 +13,51 @@ /// \brief a task to study matching MFT-[MCH-MID] in MC /// \author daiki.sekihata@cern.ch -#include "TableHelper.h" - +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/RCTSelectionFlags.h" -#include "Common/Core/RecoDecay.h" #include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "TGeoGlobalMagField.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include #include #include +#include #include #include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; @@ -52,7 +66,7 @@ using namespace o2::constants::physics; using namespace o2::aod::fwdtrackutils; struct matchingMFT { - using MyCollisions = soa::Join; + using MyCollisions = soa::Join; using MyFwdTracks = soa::Join; using MyMFTTracks = soa::Join; @@ -65,6 +79,10 @@ struct matchingMFT { Configurable maxEtaSA{"maxEtaSA", -2.5, "max. eta acceptance for MCH-MID"}; Configurable minEtaGL{"minEtaGL", -3.6, "min. eta acceptance for MFT-MCH-MID"}; Configurable maxEtaGL{"maxEtaGL", -2.5, "max. eta acceptance for MFT-MCH-MID"}; + Configurable minPtMFTsa{"minPtMFTsa", 0.01, "min pt for MFTsa"}; + Configurable maxPtMFTsa{"maxPtMFTsa", 1e+10, "max pt for MFTsa"}; + Configurable minEtaMFTsa{"minEtaMFTsa", -3.6, "min. eta acceptance for MFTsa"}; + Configurable maxEtaMFTsa{"maxEtaMFTsa", -2.4, "max. eta acceptance for MFTsa"}; Configurable minRabs{"minRabs", 17.6, "min. R at absorber end"}; Configurable midRabs{"midRabs", 26.5, "middle R at absorber end for pDCA cut"}; Configurable maxRabs{"maxRabs", 89.5, "max. R at absorber end"}; @@ -78,28 +96,59 @@ struct matchingMFT { Configurable minNclustersMFT{"minNclustersMFT", 5, "min nclusters MFT"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + // for z shift for propagation + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift from CCDB"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0, "manual z-shift for propagation of global muon to PV"}; + Configurable requireTrueAssociation{"requireTrueAssociation", false, "flag to require true mc collision association"}; - Configurable maxRelDPt{"maxRelDPt", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable maxDEta{"maxDEta", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable maxDPhi{"maxDPhi", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; - Configurable maxDEtaMP{"maxDEtaMP", 1e+10f, "max. deta between MFT and MCH-MID at matching plane Z"}; - Configurable maxDPhiMP{"maxDPhiMP", 1e+10f, "max. dphi between MFT and MCH-MID at matching plane Z"}; + Configurable maxDXMP{"maxDXMP", 1e+10f, "max. dx between MFT and MCH-MID at matching plane Z"}; + Configurable maxDYMP{"maxDYMP", 1e+10f, "max. dy between MFT and MCH-MID at matching plane Z"}; Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to require MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; Configurable matchingZ{"matchingZ", -77.5, "z position where matching is performed"}; - Configurable cfgBestMatchFinder{"cfgBestMatchFinder", 0, "matching chi2:0, dr:1"}; - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", -1.f, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - - // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_muon_glo", "select 1 [CBT_muon, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + Configurable cfgApplyPreselectionInBestMatch{"cfgApplyPreselectionInBestMatch", false, "flag to apply preselection in find best match function"}; + + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", false, "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", 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 cfgRequireVertexTOFmatched{"cfgRequireVertexTOFmatched", false, "require Vertex TOFmatched in event cut"}; // ITS-TPC-TOF matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + + // Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + // Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + // Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + // Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + // Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + // Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + // Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + // Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + + // for RCT + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_muon_glo", "select 1 [CBT_muon, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2, NTPV:3, NGlobal:4"}; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + // Configurable cfgNumContribMin{"cfgNumContribMin", 0, "min. numContrib"}; + // Configurable cfgNumContribMax{"cfgNumContribMax", 65000, "max. numContrib"}; + } eventcuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -117,7 +166,7 @@ struct matchingMFT { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); ccdbApi.init(ccdburl); - rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); + rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); addHistograms(); } @@ -126,6 +175,7 @@ struct matchingMFT { Service ccdb; int mRunNumber = -1; float mBz = 0; + float mZShift = 0; template void initCCDB(TBC const& bc) @@ -148,6 +198,20 @@ struct matchingMFT { o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); mBz = field->getBz(centerMFT); // Get field at centre of MFT LOGF(info, "Bz at center of MFT = %f kZG", mBz); + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } } void addHistograms() @@ -163,6 +227,8 @@ struct matchingMFT { fRegistry.add("Event/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); fRegistry.add("Event/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); fRegistry.add("Event/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/hCentNTPV", "hCentNTPV;centrality NTPV (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/hCentNGlo", "hCentNGlo;centrality NGlo (%)", kTH1F, {{110, 0, 110}}, false); fRegistry.add("Event/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); fRegistry.add("Event/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); @@ -176,22 +242,22 @@ struct matchingMFT { const AxisSpec axis_pt{{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.5, 3, 3.5, 4, 4.5, 5, 6, 7, 8, 9, 10}, "p_{T}^{gl} (GeV/c)"}; fRegistry.add("MFTMCHMID/primary/correct/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -5.f, -1.f}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {80, -5.f, -1.f}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hEtaPhi_MatchedMCHMID", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); fRegistry.add("MFTMCHMID/primary/correct/hsDelta", "diff. between GL and associated SA;p_{T}^{gl} (GeV/c);(p_{T}^{sa} - p_{T}^{gl})/p_{T}^{gl};#eta^{sa} - #eta^{gl};#varphi^{sa} - #varphi^{gl} (rad.);", kTHnSparseF, {axis_pt, {200, -0.5, +0.5}, {200, -1, +1}, {90, -M_PI / 4, M_PI / 4}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hsDeltaAtMP", "diff. between MFT and MCH-MID;p_{T}^{gl} (GeV/c);#varphi^{MCH-MID} - #varphi^{MFT} (rad.);#eta^{MCH-MID} - #eta^{MFT};", kTHnSparseF, {axis_pt, {90, -M_PI / 4, M_PI / 4}, {200, -1, +1}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hsDeltaAtMP", "diff. XY between MFT and MCH-MID at MP;p_{T}^{gl} (GeV/c);X^{MCH-MID} - X^{MFT};Y^{MCH-MID} - Y^{MFT};", kTHnSparseF, {axis_pt, {100, -50, 50}, {100, -50, 50}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDiffCollId", "difference in collision index;collisionId_{TTCA} - collisionId_{MP}", kTH1F, {{41, -20.5, +20.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hSign", "sign;sign", kTH1F, {{3, -1.5, +1.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hNclusters", "Nclusters;Nclusters", kTH1F, {{21, -0.5f, 20.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {1000, 0.0f, 1000}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT", "chi2 MFT/ndf;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2_Pt", "chi2;p_{T,#mu} (GeV/c);chi2/ndf", kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT_Pt", "chi2 MFT/ndf;p_{T,#mu} (GeV/c);chi2 MFT/ndf", kTH2F, {{100, 0, 10}, {100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID_Pt", "chi2 match MCH-MID;p_{T,#mu} (GeV/c);chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT_Pt", "chi2 match MCH-MFT;p_{T,#mu} (GeV/c);chi2", kTH2F, {{100, 0, 10}, {100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.1, 0.1}, {200, -0.1, +0.1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); @@ -202,7 +268,9 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm);", kTH2F, {{100, 0, 1}, {200, -0.1, 0.1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hMCHBitMap", "MCH bit map;MCH bit map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hMIDBitMap", "MID bit map;MID bit map", kTH1F, {{256, -0.5, 255.5}}, false); - + fRegistry.add("MFTMCHMID/primary/correct/hdR_Chi2MatchMCHMFT", "dr vs. matching chi2 MCH-MFT;chi2 match MCH-MFT;#DeltaR;", kTH2F, {{200, 0, 50}, {200, 0, 0.5}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hCorrectAsocc", "correct fwdtrack-to-collision association", kTH1F, {{2, -0.5, +1.5}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hIsCA", "cellular automaton;p_{T,#mu} (GeV/c);isCA", kTH2F, {{100, 0, 10}, {2, -0.5, 1.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hProdVtxZ", "prod. vtx Z of muon;V_{z} (cm)", kTH1F, {{200, -100, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hRelDeltaPt", "pT resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 10}, {200, -1, +1}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDeltaEta_Pos", "#eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 10}, {400, -0.2, +0.2}}, false); @@ -211,6 +279,76 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hDeltaPhi_Neg", "#varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 10}, {400, -0.2, +0.2}}, false); fRegistry.addClone("MFTMCHMID/primary/correct/", "MFTMCHMID/primary/wrong/"); fRegistry.addClone("MFTMCHMID/primary/", "MFTMCHMID/secondary/"); + + fRegistry.add("MFT/primary/hPt", "pT;p_{T} (GeV/c)", kTH1D, {{1000, 0.0f, 10}}, false); + fRegistry.add("MFT/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2D, {{180, 0, 2 * M_PI}, {200, -4.f, -2.f}}, false); + fRegistry.add("MFT/primary/hXY", "inner most XY;X (cm);Y (cm)", kTH2D, {{300, -15, 15}, {300, -15, 15}}, false); + fRegistry.add("MFT/primary/hSign", "sign;sign", kTH1D, {{3, -1.5, +1.5}}, false); + fRegistry.add("MFT/primary/hChi2MFT", "chi2 MFT/ndf;chi2 MFT/ndf", kTH1D, {{100, 0.0f, 10}}, false); + fRegistry.add("MFT/primary/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1D, {{11, -0.5f, 10.5}}, false); + fRegistry.add("MFT/primary/hMFTClusterMap", "MFT cluster map", kTH1D, {{1024, -0.5, 1023.5}}, false); + fRegistry.add("MFT/primary/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2D, {{200, -0.1, 0.1}, {200, -0.1, +0.1}}, false); + fRegistry.add("MFT/primary/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1D, {{100, 0, 1}}, false); + fRegistry.add("MFT/primary/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm);", kTH2D, {{100, 0, 1}, {200, -0.1, 0.1}}, false); + fRegistry.add("MFT/primary/hProdVtxZ", "prod. vtx Z of track;V_{z} (cm)", kTH1D, {{200, -100, 100}}, false); + fRegistry.add("MFT/primary/hRelDeltaPt", "pT resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2D, {{200, 0, 10}, {1000, -1, +9}}, false); + fRegistry.add("MFT/primary/hDeltaEta_Pos", "#eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2D, {{200, 0, 10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFT/primary/hDeltaEta_Neg", "#eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2D, {{200, 0, 10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFT/primary/hDeltaPhi_Pos", "#varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2D, {{200, 0, 10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFT/primary/hDeltaPhi_Neg", "#varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2D, {{200, 0, 10}, {400, -0.2, +0.2}}, false); + fRegistry.add("MFT/primary/hCorrectAsocc", "correct mfttrack-to-collision association", kTH1F, {{2, -0.5, +1.5}}, false); + fRegistry.add("MFT/primary/hIsCA", "cellular automaton;p_{T,#mu} (GeV/c);isCA", kTH2F, {{100, 0, 10}, {2, -0.5, 1.5}}, false); + fRegistry.addClone("MFT/primary/", "MFT/secondary/"); + } + + template + bool isSelectedEvent(TCollision const& collision) + { + if (eventcuts.cfgRequireSel8 && !collision.sel8()) { + return false; + } + + if (collision.posZ() < eventcuts.cfgZvtxMin || eventcuts.cfgZvtxMax < collision.posZ()) { + 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.cfgRequireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (eventcuts.cfgRequireVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + + if (!(eventcuts.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + return false; + } + + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + return false; + } + + return true; } bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2_per_ndf, const uint8_t trackType, const float dcaXY) @@ -235,6 +373,7 @@ struct matchingMFT { if (chi2_per_ndf < 0.f || maxChi2GL < chi2_per_ndf) { return false; } + } else if (trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { if (eta < minEtaSA || maxEtaSA < eta) { return false; @@ -299,32 +438,40 @@ struct matchingMFT { // } template - void getDeltaEtaDeltaPhiAtMatchingPlane(TCollision const& collision, TFwdTrack const& fwdtrack, TMFTrackCov const& mftCovs, float& deta, float& dphi) + void getDxDyAtMatchingPlane(TCollision const& collision, TFwdTrack const& fwdtrack, TMFTrackCov const& mftCovs, float& dx, float& dy) { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - deta = 999.f; - dphi = 999.f; + dx = 999.f; + dy = 999.f; return; // do nothing } auto mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID - auto mfttrack = fwdtrack.template matchMFTTrack_as(); + auto mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa if (mchtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { - deta = 999.f; - dphi = 999.f; + dx = 999.f; + dy = 999.f; return; // do nothing } - o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, matchingZ, mBz); - auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); + auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, matchingZ, mBz, mZShift); // propagated to matching plane - auto muonAtMP = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToMatchingPlane, matchingZ, mBz); // propagated to matching plane - o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update - mftsaAtMP.propagateToZhelix(matchingZ, mBz); // propagated to matching plane - deta = muonAtMP.getEta() - mftsaAtMP.getEta(); - dphi = muonAtMP.getPhi() - mftsaAtMP.getPhi(); - o2::math_utils::bringToPMPi(dphi); + auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); + o2::track::TrackParCovFwd mftsaAtMP = getTrackParCovFwdShift(mfttrack, mZShift, mfttrackcov); // values at innermost update + mftsaAtMP.propagateToZhelix(matchingZ, mBz); // propagated to matching plane + dx = muonAtMP.getX() - mftsaAtMP.getX(); + dy = muonAtMP.getY() - mftsaAtMP.getY(); + // o2::math_utils::bringToPMPi(dphi); + + // float sigmaX = std::sqrt(muonAtMP.getSigma2X() + mftsaAtMP.getSigma2X()); + // float sigmaY = std::sqrt(muonAtMP.getSigma2Y() + mftsaAtMP.getSigma2Y()); + // dx /= sigmaX; + // dy /= sigmaY; + + // LOGF(info, "dx/sigmaX = %f, dy/sigmaY = %f", dx/sigmaX, dy/sigmaY); + // LOGF(info, "muonAtMP.getX() = %f, muonAtMP.getSigma2X() = %f, muonAtMP.getY() = %f, muonAtMP.getSigma2Y() = %f", muonAtMP.getX(), muonAtMP.getSigma2X() , muonAtMP.getY(), muonAtMP.getSigma2Y()); + // LOGF(info, "mftsaAtMP.getX() = %f, mftsaAtMP.getSigma2X() = %f, mftsaAtMP.getY() = %f, mftsaAtMP.getSigma2Y() = %f", mftsaAtMP.getX(), mftsaAtMP.getSigma2X() , mftsaAtMP.getY(), mftsaAtMP.getSigma2Y()); } template @@ -380,9 +527,9 @@ struct matchingMFT { bool isPrimary = mcParticle_MCHMID.isPhysicalPrimary() || mcParticle_MCHMID.producedByGenerator(); bool isMatched = (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) && (mcParticle_MFT.mcCollisionId() == mcParticle_MCHMID.mcCollisionId()); - o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz); - o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz); - o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, matchingZ, mBz); + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, mchtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); float pt = propmuonAtPV.getPt(); float eta = propmuonAtPV.getEta(); @@ -413,7 +560,7 @@ struct matchingMFT { float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); float pDCA = mchtrack.p() * dcaXY_Matched; // float pDCA = propmuonAtPV.getP() * dcaXY; - float dphiMP = 999.f, detaMP = 999.f; + float dxMP = 999.f, dyMP = 999.f; pt = propmuonAtPV.getPt(); eta = propmuonAtPV.getEta(); @@ -422,7 +569,7 @@ struct matchingMFT { if constexpr (withMFTCov) { auto mfttrackcov = mftCovs.rawIteratorAt(map_mfttrackcovs[mfttrack.globalIndex()]); - o2::track::TrackParCovFwd mftsa = getTrackParCovFwd(mfttrack, mfttrackcov); // values at innermost update + o2::track::TrackParCovFwd mftsa = getTrackParCovFwdShift(mfttrack, mZShift, mfttrackcov); // values at innermost update o2::dataformats::GlobalFwdTrack globalMuonRefit = o2::aod::fwdtrackutils::refitGlobalMuonCov(propmuonAtPV_Matched, mftsa); // this is track at IU. auto globalMuonAtPV = o2::aod::fwdtrackutils::propagateTrackParCovFwd(globalMuonRefit, fwdtrack.trackType(), collision, propagationPoint::kToVertex, matchingZ, mBz); @@ -446,8 +593,8 @@ struct matchingMFT { } sigma_dcaXY = dcaXY / dcaXYinSigma; - getDeltaEtaDeltaPhiAtMatchingPlane(collision, fwdtrack, mftCovs, detaMP, dphiMP); - o2::math_utils::bringToPMPi(dphiMP); + getDxDyAtMatchingPlane(collision, fwdtrack, mftCovs, dxMP, dyMP); + // o2::math_utils::bringToPMPi(dphiMP); } if (refitGlobalMuon) { @@ -462,13 +609,11 @@ struct matchingMFT { float deta = etaMatchedMCHMID - eta; float dphi = phiMatchedMCHMID - phi; o2::math_utils::bringToPMPi(dphi); + if (std::sqrt(std::pow(deta / maxDEta, 2) + std::pow(dphi / maxDPhi, 2)) > 1.f) { return; } - if (std::sqrt(std::pow(detaMP / maxDEtaMP, 2) + std::pow(dphiMP / maxDPhiMP, 2)) > 1.f) { - return; - } - if (std::fabs(dpt) > maxRelDPt) { + if (std::sqrt(std::pow(dxMP / maxDXMP, 2) + std::pow(dyMP / maxDYMP, 2)) > 1.f) { return; } @@ -492,7 +637,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hEtaPhi"), phi, eta); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hsDelta"), pt, dpt, deta, dphi); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hsDeltaAtMP"), pt, dphiMP, detaMP); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hsDeltaAtMP"), pt, dxMP, dyMP); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDiffCollId"), collision.globalIndex() - fwdtrack.collisionId()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hNclusters"), fwdtrack.nClusters()); @@ -500,10 +645,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy"), dcaXY); @@ -512,6 +657,8 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxyinSigma"), dcaXYinSigma); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMIDBitMap"), fwdtrack.midBitMap()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -530,7 +677,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hEtaPhi"), phi, eta); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hsDelta"), pt, dpt, deta, dphi); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hsDeltaAtMP"), pt, dphiMP, detaMP); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hsDeltaAtMP"), pt, dxMP, dyMP); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDiffCollId"), collision.globalIndex() - fwdtrack.collisionId()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hNclusters"), fwdtrack.nClusters()); @@ -538,10 +685,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxy"), dcaXY); @@ -550,6 +697,8 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxyinSigma"), dcaXYinSigma); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMIDBitMap"), fwdtrack.midBitMap()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -570,7 +719,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hEtaPhi"), phi, eta); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hsDelta"), pt, dpt, deta, dphi); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hsDeltaAtMP"), pt, dphiMP, detaMP); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hsDeltaAtMP"), pt, dxMP, dyMP); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDiffCollId"), collision.globalIndex() - fwdtrack.collisionId()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hNclusters"), fwdtrack.nClusters()); @@ -578,10 +727,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxy"), dcaXY); @@ -590,6 +739,8 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxyinSigma"), dcaXYinSigma); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMIDBitMap"), fwdtrack.midBitMap()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -608,7 +759,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hEtaPhi"), phi, eta); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hEtaPhi_MatchedMCHMID"), phiMatchedMCHMID, etaMatchedMCHMID); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hsDelta"), pt, dpt, deta, dphi); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hsDeltaAtMP"), pt, dphiMP, detaMP); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hsDeltaAtMP"), pt, dxMP, dyMP); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDiffCollId"), collision.globalIndex() - fwdtrack.collisionId()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hSign"), fwdtrack.sign()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hNclusters"), fwdtrack.nClusters()); @@ -616,10 +767,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MFT"), chi2mft); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2_Pt"), pt, fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MFT_Pt"), pt, chi2mft); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMID_Pt"), pt, fwdtrack.chi2MatchMCHMID()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMFT_Pt"), pt, fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxy2DinSigma"), dcaX / std::sqrt(cXX), dcaY / std::sqrt(cYY)); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxy"), dcaXY); @@ -628,6 +779,8 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxyinSigma"), dcaXYinSigma); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMCHBitMap"), fwdtrack.mchBitMap()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMIDBitMap"), fwdtrack.midBitMap()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hCorrectAsocc"), mcParticle_MCHMID.mcCollisionId() == collision.mcCollisionId()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hIsCA"), pt, mfttrack.isCA()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxResolutionvsPt"), pt, std::sqrt(cXX) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAyResolutionvsPt"), pt, std::sqrt(cYY) * 1e+4); // convert cm to um fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hDCAxyResolutionvsPt"), pt, sigma_dcaXY * 1e+4); // convert cm to um @@ -655,16 +808,17 @@ struct matchingMFT { fRegistry.fill(HIST("Event/hCentFT0A"), collision.centFT0A()); fRegistry.fill(HIST("Event/hCentFT0C"), collision.centFT0C()); fRegistry.fill(HIST("Event/hCentFT0M"), collision.centFT0M()); + fRegistry.fill(HIST("Event/hCentNTPV"), collision.centNTPV()); + fRegistry.fill(HIST("Event/hCentNGlo"), collision.centNGlobal()); fRegistry.fill(HIST("Event/hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); fRegistry.fill(HIST("Event/hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); } std::vector> vec_min_chi2MatchMCHMFT; // std::pair -> chi2MatchMCHMFT; - std::vector> vec_min_dr; // std::pair -> deta + dphi; - std::map, bool> mapCorrectMatch; + // std::map, bool> mapCorrectMatch; - template - void findBestMatchPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&, TMFTTracksCov const& mftCovs) + template + void findBestMatchPerMCHMID(TCollision const& collision, TFwdTrack const& fwdtrack, TFwdTracks const& fwdtracks, TMFTTracks const&) { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { return; @@ -674,95 +828,277 @@ struct matchingMFT { } std::tuple tupleIds_at_min_chi2mftmch; - std::tuple tupleIds_at_min_dr; float min_chi2MatchMCHMFT = 1e+10; - float min_dr = 1e+10; auto muons_per_MCHMID = fwdtracks.sliceBy(fwdtracksPerMCHTrack, fwdtrack.globalIndex()); // LOGF(info, "muons_per_MCHMID.size() = %d", muons_per_MCHMID.size()); + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + float etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); + float phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); + o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(fwdtrack, fwdtrack, collision, propagationPoint::kToDCA, matchingZ, mBz, mZShift); + float dcaX_Matched = propmuonAtDCA_Matched.getX() - collision.posX(); + float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); + float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); + float pDCA = fwdtrack.p() * dcaXY_Matched; + for (const auto& muon_tmp : muons_per_MCHMID) { if (muon_tmp.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - auto tupleId = std::make_tuple(muon_tmp.globalIndex(), muon_tmp.matchMCHTrackId(), muon_tmp.matchMFTTrackId()); auto mchtrack = muon_tmp.template matchMCHTrack_as(); // MCH-MID auto mfttrack = muon_tmp.template matchMFTTrack_as(); - if (!muon_tmp.has_mcParticle() || !mchtrack.has_mcParticle() || !mfttrack.has_mcParticle()) { + if (muon_tmp.chi2() < 0.f || muon_tmp.chi2MatchMCHMFT() < 0.f || muon_tmp.chi2MatchMCHMID() < 0.f || mfttrack.chi2() < 0.f) { // reject negative chi2, i.e. wrong. continue; } - float deta = 999.f, dphi = 999.f; - if constexpr (withMFTCov) { - getDeltaEtaDeltaPhiAtMatchingPlane(collision, muon_tmp, mftCovs, deta, dphi); + // LOGF(info, "muon_tmp.has_mcParticle() = %d, mchtrack.has_mcParticle() = %d, mfttrack.has_mcParticle() = %d", muon_tmp.has_mcParticle(), mchtrack.has_mcParticle(), mfttrack.has_mcParticle()); + + if (!muon_tmp.has_mcParticle() || !mchtrack.has_mcParticle() || !mfttrack.has_mcParticle()) { + continue; } - float dr = std::sqrt(deta * deta + dphi * dphi); // auto mcParticle_MFTMCHMID = muon_tmp.template mcParticle_as(); // this is identical to mcParticle_MCHMID auto mcParticle_MCHMID = mchtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID auto mcParticle_MFT = mfttrack.template mcParticle_as(); - // float chi2ndf = muon_tmp.chi2() / (2.f * (mchtrack.nClusters() + mfttrack.nClusters()) - 5.f); - if (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) { - mapCorrectMatch[tupleId] = true; + bool isPrimary = mcParticle_MCHMID.isPhysicalPrimary() || mcParticle_MCHMID.producedByGenerator(); + bool isMatched = (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) && (mcParticle_MFT.mcCollisionId() == mcParticle_MCHMID.mcCollisionId()); + + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(muon_tmp, muon_tmp, collision, propagationPoint::kToVertex, matchingZ, mBz, mZShift); + float pt = propmuonAtPV.getPt(); + float eta = propmuonAtPV.getEta(); + float phi = propmuonAtPV.getPhi(); + o2::math_utils::bringTo02Pi(phi); + if (refitGlobalMuon) { + pt = propmuonAtPV_Matched.getP() * std::sin(2.f * std::atan(std::exp(-eta))); + } + + float deta = etaMatchedMCHMID - eta; + float dphi = phiMatchedMCHMID - phi; + o2::math_utils::bringToPMPi(dphi); + float dr = std::sqrt(deta * deta + dphi * dphi); + float chi2ndf = muon_tmp.chi2() / (2.f * (mchtrack.nClusters() + mfttrack.nClusters()) - 5.f); + + float dcaX = propmuonAtPV.getX() - collision.posX(); + float dcaY = propmuonAtPV.getY() - collision.posY(); + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + if (isPrimary) { + if (isMatched) { + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hdR_Chi2MatchMCHMFT"), muon_tmp.chi2MatchMCHMFT(), dr); + } else { + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hdR_Chi2MatchMCHMFT"), muon_tmp.chi2MatchMCHMFT(), dr); + } } else { - mapCorrectMatch[tupleId] = false; + if (isMatched) { + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hdR_Chi2MatchMCHMFT"), muon_tmp.chi2MatchMCHMFT(), dr); + } else { + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hdR_Chi2MatchMCHMFT"), muon_tmp.chi2MatchMCHMFT(), dr); + } } + // if (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) { + // mapCorrectMatch[tupleId] = true; + // } else { + // mapCorrectMatch[tupleId] = false; + // } + // if (std::abs(mcParticle_MCHMID.pdgCode()) == 13 && mcParticle_MCHMID.isPhysicalPrimary()) { // if (mcParticle_MFT.globalIndex() == mcParticle_MCHMID.globalIndex()) { - // LOGF(info, "This is correct match between MFT and MCH-MID: muon_tmp.globalIndex() = %d, chi2/ndf = %f, matching chi2/ndf = %f, mcParticle.pt() = %f, mcParticle.eta() = %f, mcParticle.phi() = %f, reldpt = %f, deta = %f, dphi = %f, dr = %f", muon_tmp.globalIndex(), chi2ndf, muon_tmp.chi2MatchMCHMFT(), mcParticle_MCHMID.pt(), mcParticle_MCHMID.eta(), mcParticle_MCHMID.phi(), reldpt, deta, dphi, dr); + // LOGF(info, "This is correct match between MFT and MCH-MID: muon_tmp.globalIndex() = %d, chi2/ndf = %f, matching chi2/ndf = %f, mcParticle.pt() = %f, mcParticle.eta() = %f, mcParticle.phi() = %f, dr = %f", muon_tmp.globalIndex(), chi2ndf, muon_tmp.chi2MatchMCHMFT(), mcParticle_MCHMID.pt(), mcParticle_MCHMID.eta(), mcParticle_MCHMID.phi(), dr); // } else { - // LOGF(info, "This is wrong match between MFT and MCH-MID: muon_tmp.globalIndex() = %d, chi2/ndf = %f, matching chi2/ndf = %f , mcParticle.pt() = %f, mcParticle.eta() = %f, mcParticle.phi() = %f, reldpt = %f, deta = %f, dphi = %f, dr = %f" , muon_tmp.globalIndex(), chi2ndf, muon_tmp.chi2MatchMCHMFT(), mcParticle_MCHMID.pt(), mcParticle_MCHMID.eta(), mcParticle_MCHMID.phi(), reldpt, deta, dphi, dr); + // LOGF(info, "This is wrong match between MFT and MCH-MID: muon_tmp.globalIndex() = %d, chi2/ndf = %f, matching chi2/ndf = %f , mcParticle.pt() = %f, mcParticle.eta() = %f, mcParticle.phi() = %f, dr = %f" , muon_tmp.globalIndex(), chi2ndf, muon_tmp.chi2MatchMCHMFT(), mcParticle_MCHMID.pt(), mcParticle_MCHMID.eta(), mcParticle_MCHMID.phi(), dr); // } // } + if (cfgApplyPreselectionInBestMatch) { + if (!isSelected(pt, eta, muon_tmp.rAtAbsorberEnd(), pDCA, chi2ndf, fwdtrack.trackType(), dcaXY)) { + continue; + } + if (std::sqrt(std::pow(deta / maxDEta, 2) + std::pow(dphi / maxDPhi, 2)) > 1.f) { + continue; + } + if (muon_tmp.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { + continue; + } + } + if (0.f < muon_tmp.chi2MatchMCHMFT() && muon_tmp.chi2MatchMCHMFT() < min_chi2MatchMCHMFT) { min_chi2MatchMCHMFT = muon_tmp.chi2MatchMCHMFT(); tupleIds_at_min_chi2mftmch = tupleId; } - if (dr < min_dr) { - min_dr = dr; - tupleIds_at_min_dr = tupleId; - } - } // end of if global muon } // end of candidates loop vec_min_chi2MatchMCHMFT.emplace_back(tupleIds_at_min_chi2mftmch); - vec_min_dr.emplace_back(tupleIds_at_min_dr); // auto mcParticleTMP = fwdtrack.template mcParticle_as(); // this is identical to mcParticle_MFTMCHMID // if (std::abs(mcParticleTMP.pdgCode()) == 13 && mcParticleTMP.isPhysicalPrimary()) { // LOGF(info, "min chi2: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, muon_tmp.chi2MatchMCHMFT() = %f, correct match = %d", std::get<0>(tupleIds_at_min_chi2mftmch), std::get<1>(tupleIds_at_min_chi2mftmch), std::get<2>(tupleIds_at_min_chi2mftmch), min_chi2MatchMCHMFT, mapCorrectMatch[tupleIds_at_min_chi2mftmch]); - // LOGF(info, "min dr: muon_tmp.globalIndex() = %d, muon_tmp.matchMCHTrackId() = %d, muon_tmp.matchMFTTrackId() = %d, dr = %f, correct match = %d", std::get<0>(tupleIds_at_min_dr), std::get<1>(tupleIds_at_min_dr), std::get<2>(tupleIds_at_min_dr), min_dr, mapCorrectMatch[tupleIds_at_min_dr]); // } } + template + void fillMFTsa(TCollisions const& collisions, TMFTTracks const& mfttracks) + { + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { + continue; + } + + auto mftsaPerCollision = mfttracks.sliceBy(perCollision_MFT, collision.globalIndex()); + for (const auto& mfttrack : mftsaPerCollision) { + if (!mfttrack.has_mcParticle()) { + continue; + } + auto mcParticle = mfttrack.template mcParticle_as(); + + if (requireTrueAssociation && (mcParticle.mcCollisionId() != collision.mcCollisionId())) { + continue; + } + + bool isPrimary = mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator(); + float phiGen = mcParticle.phi(); + o2::math_utils::bringTo02Pi(phiGen); + + int ndf = 2 * mfttrack.nClusters() - 5; + + if (mfttrack.nClusters() < minNclustersMFT) { + continue; + } + + if (mfttrack.chi2() / ndf < 0 || maxChi2MFT < mfttrack.chi2() / ndf) { + continue; + } + + if (requireMFTHitMap) { + std::vector hasMFTs{hasMFT<0, 1>(mfttrack), hasMFT<2, 3>(mfttrack), hasMFT<4, 5>(mfttrack), hasMFT<6, 7>(mfttrack), hasMFT<8, 9>(mfttrack)}; + for (int i = 0; i < static_cast(requiredMFTDisks->size()); i++) { + if (!hasMFTs[requiredMFTDisks->at(i)]) { + return; + } + } + } + + // propagate MFTsa track to PV + std::array dcaInfOrig{999.f, 999.f, 999.f}; + std::vector v1; // Temporary null vector for the computation of the covariance matrix + SMatrix55 tcovs(v1.begin(), v1.end()); + SMatrix5 tpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + o2::track::TrackParCovFwd trackPar{mfttrack.z(), tpars, tcovs, mfttrack.chi2()}; + trackPar.propagateToDCAhelix(mBz, {collision.posX(), collision.posY(), collision.posZ()}, dcaInfOrig); + v1.clear(); + v1.shrink_to_fit(); + float dcaX = dcaInfOrig[0]; + float dcaY = dcaInfOrig[1]; + float dcaZ = dcaInfOrig[2]; + float dcaXY = std::sqrt(dcaX * dcaX + dcaY * dcaY); + + float pt = trackPar.getPt(); + float eta = trackPar.getEta(); + float phi = trackPar.getPhi(); + o2::math_utils::bringTo02Pi(phi); + + if (pt < minPtMFTsa || maxPtMFTsa < pt) { + continue; + } + if (eta < minEtaMFTsa || maxEtaMFTsa < eta) { + continue; + } + if (maxDCAxy < dcaXY) { + continue; + } + + if (isPrimary) { + fRegistry.fill(HIST("MFT/primary/hPt"), pt); + fRegistry.fill(HIST("MFT/primary/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFT/primary/hXY"), mfttrack.x(), mfttrack.y()); + fRegistry.fill(HIST("MFT/primary/hSign"), mfttrack.sign()); + fRegistry.fill(HIST("MFT/primary/hNclustersMFT"), mfttrack.nClusters()); + fRegistry.fill(HIST("MFT/primary/hChi2MFT"), mfttrack.chi2() / ndf); + fRegistry.fill(HIST("MFT/primary/hMFTClusterMap"), mftClusterMap(mfttrack)); + fRegistry.fill(HIST("MFT/primary/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MFT/primary/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MFT/primary/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("MFT/primary/hCorrectAsocc"), mcParticle.mcCollisionId() == collision.mcCollisionId()); + fRegistry.fill(HIST("MFT/primary/hIsCA"), pt, mfttrack.isCA()); + + fRegistry.fill(HIST("MFT/primary/hProdVtxZ"), mcParticle.vz()); + fRegistry.fill(HIST("MFT/primary/hRelDeltaPt"), mcParticle.pt(), (pt - mcParticle.pt()) / mcParticle.pt()); + if (mfttrack.sign() > 0) { + fRegistry.fill(HIST("MFT/primary/hDeltaEta_Pos"), mcParticle.pt(), eta - mcParticle.eta()); + fRegistry.fill(HIST("MFT/primary/hDeltaPhi_Pos"), mcParticle.pt(), phi - phiGen); + } else { + fRegistry.fill(HIST("MFT/primary/hDeltaEta_Neg"), mcParticle.pt(), eta - mcParticle.eta()); + fRegistry.fill(HIST("MFT/primary/hDeltaPhi_Neg"), mcParticle.pt(), phi - phiGen); + } + + } else { + fRegistry.fill(HIST("MFT/secondary/hPt"), pt); + fRegistry.fill(HIST("MFT/secondary/hEtaPhi"), phi, eta); + fRegistry.fill(HIST("MFT/secondary/hXY"), mfttrack.x(), mfttrack.y()); + fRegistry.fill(HIST("MFT/secondary/hSign"), mfttrack.sign()); + fRegistry.fill(HIST("MFT/secondary/hNclustersMFT"), mfttrack.nClusters()); + fRegistry.fill(HIST("MFT/secondary/hChi2MFT"), mfttrack.chi2() / ndf); + fRegistry.fill(HIST("MFT/secondary/hMFTClusterMap"), mftClusterMap(mfttrack)); + fRegistry.fill(HIST("MFT/secondary/hDCAxy2D"), dcaX, dcaY); + fRegistry.fill(HIST("MFT/secondary/hDCAxy"), dcaXY); + fRegistry.fill(HIST("MFT/secondary/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("MFT/secondary/hCorrectAsocc"), mcParticle.mcCollisionId() == collision.mcCollisionId()); + fRegistry.fill(HIST("MFT/secondary/hIsCA"), pt, mfttrack.isCA()); + + fRegistry.fill(HIST("MFT/secondary/hProdVtxZ"), mcParticle.vz()); + fRegistry.fill(HIST("MFT/secondary/hRelDeltaPt"), mcParticle.pt(), (pt - mcParticle.pt()) / mcParticle.pt()); + if (mfttrack.sign() > 0) { + fRegistry.fill(HIST("MFT/secondary/hDeltaEta_Pos"), mcParticle.pt(), eta - mcParticle.eta()); + fRegistry.fill(HIST("MFT/secondary/hDeltaPhi_Pos"), mcParticle.pt(), phi - phiGen); + } else { + fRegistry.fill(HIST("MFT/secondary/hDeltaEta_Neg"), mcParticle.pt(), eta - mcParticle.eta()); + fRegistry.fill(HIST("MFT/secondary/hDeltaPhi_Neg"), mcParticle.pt(), phi - phiGen); + } + } + + } // end of mfttrack loop + } // end of collision loop + } + SliceCache cache; PresliceUnsorted fwdtracksPerMCHTrack = aod::fwdtrack::matchMCHTrackId; PresliceUnsorted perMFTTrack = o2::aod::fwdtrack::matchMFTTrackId; Preslice perCollision = o2::aod::fwdtrack::collisionId; + Preslice perCollision_MFT = o2::aod::fwdtrack::collisionId; Preslice fwdtrackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted fwdtrackIndicesPerFwdTrack = aod::track_association::fwdtrackId; - Filter collisionFilter_evsel = o2::aod::evsel::sel8 == true && (cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < 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_evsel = eventcuts.cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < eventcuts.cfgZvtxMax; + Filter collisionFilter_centrality = (eventcuts.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < eventcuts.cfgCentMax) || (eventcuts.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < eventcuts.cfgCentMax); using FilteredMyCollisions = soa::Filtered; void processWithoutFTTCA(FilteredMyCollisions const& collisions, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::McParticles const&) { vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); - vec_min_dr.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); auto fwdtracks_per_coll = fwdtracks.sliceBy(perCollision, collision.globalIndex()); for (const auto& fwdtrack : fwdtracks_per_coll) { - findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks, nullptr); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop + // only for MFTsa + fillMFTsa(collisions, mfttracks); + for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); @@ -770,11 +1106,16 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + + if (!isSelectedEvent(collision)) { + continue; + } + + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } fRegistry.fill(HIST("Event/hCollisionCounter"), 1); @@ -787,15 +1128,9 @@ struct matchingMFT { continue; } - if (cfgBestMatchFinder == 0) { // chi2 - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - } else if (cfgBestMatchFinder == 1) { // dr - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_dr.begin(), vec_min_dr.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_dr.end()) { - continue; - } - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, nullptr); } // end of fwdtrack loop @@ -803,25 +1138,25 @@ struct matchingMFT { vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); - vec_min_dr.clear(); - vec_min_dr.shrink_to_fit(); } PROCESS_SWITCH(matchingMFT, processWithoutFTTCA, "process without FTTCA", false); void processWithFTTCA(FilteredMyCollisions const& collisions, MyFwdTracks const& fwdtracks, MyMFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices, aod::McParticles const&) { vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); - vec_min_dr.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { auto fwdtrack = fwdtrackId.template fwdtrack_as(); - findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks, nullptr); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop + // only for MFTsa + fillMFTsa(collisions, mfttracks); + for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); @@ -829,11 +1164,14 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + if (!isSelectedEvent(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } fRegistry.fill(HIST("Event/hCollisionCounter"), 1); @@ -846,15 +1184,9 @@ struct matchingMFT { continue; } - if (cfgBestMatchFinder == 0) { // chi2 - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - } else if (cfgBestMatchFinder == 1) { // dr - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_dr.begin(), vec_min_dr.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_dr.end()) { - continue; - } - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, nullptr); } // end of fwdtrack loop @@ -862,8 +1194,6 @@ struct matchingMFT { vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); - vec_min_dr.clear(); - vec_min_dr.shrink_to_fit(); } PROCESS_SWITCH(matchingMFT, processWithFTTCA, "process with FTTCA", true); @@ -876,7 +1206,6 @@ struct matchingMFT { } vec_min_chi2MatchMCHMFT.reserve(fwdtracks.size()); - vec_min_dr.reserve(fwdtracks.size()); for (const auto& collision : collisions) { auto bc = collision.template bc_as(); @@ -884,10 +1213,13 @@ struct matchingMFT { auto fwdtrackIdsThisCollision = fwdtrackIndices.sliceBy(fwdtrackIndicesPerCollision, collision.globalIndex()); for (const auto& fwdtrackId : fwdtrackIdsThisCollision) { auto fwdtrack = fwdtrackId.template fwdtrack_as(); - findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks, mftCovs); + findBestMatchPerMCHMID(collision, fwdtrack, fwdtracks, mfttracks); } // end of fwdtrack loop } // end of collision loop + // only for MFTsa + fillMFTsa(collisions, mfttracks); + for (const auto& collision : collisions) { auto bc = collision.template bc_as(); initCCDB(bc); @@ -895,11 +1227,14 @@ struct matchingMFT { if (!collision.has_mcCollision()) { continue; } - if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + if (!isSelectedEvent(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } - float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + float centralities[5] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), collision.centNGlobal()}; + if (centralities[eventcuts.cfgCentEstimator] < eventcuts.cfgCentMin || eventcuts.cfgCentMax < centralities[eventcuts.cfgCentEstimator]) { continue; } fRegistry.fill(HIST("Event/hCollisionCounter"), 1); @@ -912,15 +1247,10 @@ struct matchingMFT { continue; } - if (cfgBestMatchFinder == 0) { // chi2 - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { - continue; - } - } else if (cfgBestMatchFinder == 1) { // dr - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_dr.begin(), vec_min_dr.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_dr.end()) { - continue; - } - } + // if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && std::find(vec_min_chi2MatchMCHMFT.begin(), vec_min_chi2MatchMCHMFT.end(), std::make_tuple(fwdtrack.globalIndex(), fwdtrack.matchMCHTrackId(), fwdtrack.matchMFTTrackId())) == vec_min_chi2MatchMCHMFT.end()) { + // continue; + // } + fillHistograms(collision, fwdtrack, fwdtracks, mfttracks, mftCovs); } // end of fwdtrack loop } // end of collision loop @@ -928,8 +1258,6 @@ struct matchingMFT { map_mfttrackcovs.clear(); vec_min_chi2MatchMCHMFT.clear(); vec_min_chi2MatchMCHMFT.shrink_to_fit(); - vec_min_dr.clear(); - vec_min_dr.shrink_to_fit(); } PROCESS_SWITCH(matchingMFT, processWithFTTCA_withMFTCov, "process with FTTCA with MFTCov", false); }; diff --git a/PWGEM/Dilepton/Tasks/mcParticlePredictionsOTF.cxx b/PWGEM/Dilepton/Tasks/mcParticlePredictionsOTF.cxx index 9ec7f079712..e04151d9c35 100644 --- a/PWGEM/Dilepton/Tasks/mcParticlePredictionsOTF.cxx +++ b/PWGEM/Dilepton/Tasks/mcParticlePredictionsOTF.cxx @@ -15,9 +15,19 @@ /// \brief Task to build the predictions from the models based on the generated particles /// -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index 2b8d6a12321..b35ef08c80f 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -17,31 +17,44 @@ #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TString.h" - -#include +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include +#include #include #include #include #include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; @@ -50,13 +63,13 @@ using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; +struct prefilterDielectron { + using MyCollisions = soa::Join; + using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; -struct prefilterDielectron { Produces pfb_derived; // Configurables @@ -129,8 +142,8 @@ struct prefilterDielectron { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; 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_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; - Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; + // Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; + // Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; // Configurable cfgRefR{"cfgRefR", 1.2, "reference R (in m) for extrapolation"}; // https://cds.cern.ch/record/1419204 Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DielectronCut::PIDSchemes::kTPChadrejORTOFreq), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5, kTPChadrejORTOFreq_woTOFif : 6]"}; @@ -249,14 +262,13 @@ struct prefilterDielectron { fEMEventCut = EMEventCut("fEMEventCut", "fEMEventCut"); fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, +eventcuts.cfgZvtxMax); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); } - o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; void DefineDielectronCut() { fDielectronCut = DielectronCut("fDielectronCut", "fDielectronCut"); @@ -289,8 +301,9 @@ struct prefilterDielectron { fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); - fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + // fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); + fDielectronCut.EnableTTCA(dielectroncuts.enableTTCA); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); @@ -313,31 +326,6 @@ struct prefilterDielectron { thresholdsML.emplace_back(dielectroncuts.cutsMl.value[i]); } fDielectronCut.SetMLThresholds(binsML, thresholdsML); - - // static constexpr int nClassesMl = 2; - // const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - // const std::vector labelsClasses = {"Signal", "Background"}; - // const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; - // const std::vector labelsBins(nBinsMl, "bin"); - // double cutsMlArr[nBinsMl][nClassesMl]; - // for (uint32_t i = 0; i < nBinsMl; i++) { - // cutsMlArr[i][0] = dielectroncuts.cutsMl.value[i]; - // cutsMlArr[i][1] = 0.; - // } - // o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; - - // mlResponseSingleTrack.configure(dielectroncuts.binsMl.value, cutsMl, cutDirMl, nClassesMl); - // if (dielectroncuts.loadModelsFromCCDB) { - // ccdbApi.init(ccdburl); - // mlResponseSingleTrack.setModelPathsCCDB(dielectroncuts.onnxFileNames.value, ccdbApi, dielectroncuts.onnxPathsCCDB.value, dielectroncuts.timestampCCDB.value); - // } else { - // mlResponseSingleTrack.setModelPathsLocal(dielectroncuts.onnxFileNames.value); - // } - // mlResponseSingleTrack.cacheInputFeaturesIndices(dielectroncuts.namesInputFeatures); - // mlResponseSingleTrack.cacheBinningIndex(dielectroncuts.nameBinningFeature); - // mlResponseSingleTrack.init(dielectroncuts.enableOptimizations.value); - - // fDielectronCut.SetPIDMlResponse(&mlResponseSingleTrack); } // end of PID ML } @@ -356,11 +344,11 @@ struct prefilterDielectron { int ndf = 0; void processPFB(FilteredMyCollisions const& collisions, MyTracks const& tracks) { - for (auto& track : tracks) { + for (const auto& track : tracks) { map_pfb[track.globalIndex()] = 0; } // end of track loop - for (auto& collision : collisions) { + for (const auto& collision : collisions) { initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; bool is_cent_ok = true; @@ -372,10 +360,10 @@ struct prefilterDielectron { auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { - for (auto& pos : posTracks_per_coll) { + for (const auto& pos : posTracks_per_coll) { map_pfb[pos.globalIndex()] = 0; } - for (auto& neg : negTracks_per_coll) { + for (const auto& neg : negTracks_per_coll) { map_pfb[neg.globalIndex()] = 0; } continue; @@ -383,7 +371,7 @@ struct prefilterDielectron { // 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 + for (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS if (!fDielectronCut.IsSelectedTrack(pos) || !fDielectronCut.IsSelectedTrack(ele)) { continue; } @@ -417,7 +405,7 @@ struct prefilterDielectron { } } // end of ULS pairing - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (!fDielectronCut.IsSelectedTrack(pos1) || !fDielectronCut.IsSelectedTrack(pos2)) { continue; } @@ -441,7 +429,7 @@ struct prefilterDielectron { } } // end of LS++ pairing - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (!fDielectronCut.IsSelectedTrack(ele1) || !fDielectronCut.IsSelectedTrack(ele2)) { continue; } @@ -467,13 +455,13 @@ struct prefilterDielectron { } // end of collision loop - for (auto& track : tracks) { + for (const auto& track : tracks) { // LOGF(info, "map_pfb[%d] = %d", track.globalIndex(), map_pfb[track.globalIndex()]); pfb_derived(map_pfb[track.globalIndex()]); } // end of track loop // check pfb. - for (auto& collision : collisions) { + for (const auto& collision : collisions) { const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -486,7 +474,7 @@ struct prefilterDielectron { continue; } - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS + for (const auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS if (!fDielectronCut.IsSelectedTrack(pos) || !fDielectronCut.IsSelectedTrack(ele)) { continue; } @@ -507,7 +495,7 @@ struct prefilterDielectron { fRegistry.fill(HIST("Pair/after/uls/hDeltaEtaDeltaPhi"), dphi, deta); } - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ + for (const auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (!fDielectronCut.IsSelectedTrack(pos1) || !fDielectronCut.IsSelectedTrack(pos2)) { continue; } @@ -528,7 +516,7 @@ struct prefilterDielectron { fRegistry.fill(HIST("Pair/after/lspp/hDeltaEtaDeltaPhi"), dphi, deta); } - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- + for (const auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (!fDielectronCut.IsSelectedTrack(ele1) || !fDielectronCut.IsSelectedTrack(ele2)) { continue; } diff --git a/PWGEM/Dilepton/Tasks/singleElectronQC.cxx b/PWGEM/Dilepton/Tasks/singleElectronQC.cxx index 4a687e82217..e7dd129af66 100644 --- a/PWGEM/Dilepton/Tasks/singleElectronQC.cxx +++ b/PWGEM/Dilepton/Tasks/singleElectronQC.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx b/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx index da2617158ec..a6a5ece732d 100644 --- a/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx +++ b/PWGEM/Dilepton/Tasks/singleElectronQCMC.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/singleMuonQC.cxx b/PWGEM/Dilepton/Tasks/singleMuonQC.cxx index b9ccb722ea3..f0ebe6e2f23 100644 --- a/PWGEM/Dilepton/Tasks/singleMuonQC.cxx +++ b/PWGEM/Dilepton/Tasks/singleMuonQC.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx b/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx index 7b7176238c1..55365013453 100644 --- a/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx +++ b/PWGEM/Dilepton/Tasks/singleMuonQCMC.cxx @@ -14,11 +14,13 @@ // 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" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include +#include + +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/Dilepton/Tasks/smearing.cxx b/PWGEM/Dilepton/Tasks/smearing.cxx index 03d0b272f46..3d5a8668244 100644 --- a/PWGEM/Dilepton/Tasks/smearing.cxx +++ b/PWGEM/Dilepton/Tasks/smearing.cxx @@ -16,17 +16,26 @@ #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/MomentumSmearer.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include +#include +#include #include using namespace o2; diff --git a/PWGEM/Dilepton/Tasks/studyDCAFitter.cxx b/PWGEM/Dilepton/Tasks/studyDCAFitter.cxx index d1d6452a50a..7dc849507e2 100644 --- a/PWGEM/Dilepton/Tasks/studyDCAFitter.cxx +++ b/PWGEM/Dilepton/Tasks/studyDCAFitter.cxx @@ -17,7 +17,6 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" @@ -25,25 +24,35 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include -#include +#include +#include #include +#include #include #include diff --git a/PWGEM/Dilepton/Tasks/studyMCTruth.cxx b/PWGEM/Dilepton/Tasks/studyMCTruth.cxx index 4204a95a9c4..10c634aae02 100644 --- a/PWGEM/Dilepton/Tasks/studyMCTruth.cxx +++ b/PWGEM/Dilepton/Tasks/studyMCTruth.cxx @@ -14,20 +14,35 @@ // This code is to study MC truth. e.g. evet selection bias // Please write to: daiki.sekihata@cern.ch -#include -#include "Math/Vector4D.h" - -#include "Framework/StaticFor.h" -#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 "Common/DataModel/EventSelection.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx b/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx index 9787a5bae04..47eab1ebafb 100644 --- a/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx +++ b/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx @@ -14,7 +14,6 @@ #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/AnalysisCut.h" -#include "PWGDQ/Core/CutsLibrary.h" #include "PWGDQ/Core/HistogramManager.h" #include "PWGDQ/Core/HistogramsLibrary.h" #include "PWGDQ/Core/MixingHandler.h" @@ -24,34 +23,34 @@ #include "Common/CCDB/EventSelectionParams.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ITSMFTBase/DPLAlpideParam.h" - -#include "TGeoGlobalMagField.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include -#include -#include +#include + +#include +#include +#include #include #include #include #include -using std::cout; -using std::endl; using std::string; using namespace o2; diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index 02bce88073e..ea169455395 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -17,7 +17,6 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" @@ -25,29 +24,43 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include #include +#include +#include #include +#include #include +#include #include #include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; diff --git a/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx b/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx new file mode 100644 index 00000000000..e7268360d74 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/testBremsstrahlung.cxx @@ -0,0 +1,219 @@ +// 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 "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::soa; + +struct testBremsstrahlung { + 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 lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber = 0; + float d_bz = 0; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::dataformats::VertexBase mVtx; + const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; + o2::base::MatLayerCylSet* lut = nullptr; + + ~testBremsstrahlung() {} + + void init(o2::framework::InitContext&) + { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); + + mRunNumber = 0; + d_bz = 0; + + if (doprocessGen) { + registry.add("Event/hGenID", "generator ID;generator ID;Number of mc collisions", kTH1F, {{7, -1.5, 5.5}}, false); + registry.add("Photon/hXY", "prod. vtx. of #gamma^{bremss};X (cm);Y (cm)", kTH2D, {{400, -100, +100}, {400, -100, +100}}, false); + registry.add("Photon/hs", "kinetic var. at prod. vtx.;p_{T,#gamma}^{bremss} (GeV/c);#eta_{#gamma}^{bremss};#varphi_{#gamma}^{bremss} (rad.);", kTHnSparseD, {{100, 0, 1}, {40, -1, +1}, {72, 0, 2 * M_PI}}, false); + registry.add("Photon/hsDelta", "hsDelta;(p_{T,e}^{after} - p_{T,e}^{before})/p_{T,e}^{before};p_{T,e}^{before} (GeV/c);r_{xy}^{bremss} (cm);#varphi^{bremss} (rad.);z^{bremss} (cm);", kTHnSparseD, {{100, -1, 0}, {100, 0, 1}, {200, 0, 100}, {72, 0, 2 * M_PI}, {200, -100, +100}}, false); + } + } + + // void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + // { + // if (mRunNumber == bc.runNumber()) { + // return; + // } + + // // load matLUT for this timestamp + // if (!lut) { + // LOG(info) << "Loading material look-up table for timestamp: " << bc.timestamp(); + // lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->getForTimeStamp(lutPath, bc.timestamp())); + // } else { + // LOG(info) << "Material look-up table already in place. Not reloading."; + // } + + // // 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 (std::fabs(d_bz) > 1e-5) { + // grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + // } + // o2::base::Propagator::initFieldFromGRP(&grpmag); + // o2::base::Propagator::Instance()->setMatLUT(lut); + // mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + // mRunNumber = bc.runNumber(); + + // if (!o2::base::GeometryManager::isGeometryLoaded()) { + // ccdb->get(geoPath); + // } + // } + + // 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); + // o2::base::Propagator::Instance()->setMatLUT(lut); + // mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + // // 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); + // o2::base::Propagator::Instance()->setMatLUT(lut); + // mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.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(); + // } + + SliceCache cache; + Preslice perCollision_mid = o2::aod::track::collisionId; + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + + using MyCollisions = Join; + using MyCollision = MyCollisions::iterator; + + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; + + void processGen(aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + { + for (const auto& mcCollision : mcCollisions) { + registry.fill(HIST("Event/hGenID"), mcCollision.getSubGeneratorId()); + + auto mcParticles_per_collision = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); + // auto photons_per_collision = photons->sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + + for (const auto& mcParticle : mcParticles_per_collision) { + if (std::abs(mcParticle.pdgCode()) != 22) { + continue; + } + if (!mcParticle.has_mothers()) { // select seconday mcParticles + continue; + } + if (mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator()) { // select seconday mcParticles + continue; + } + + auto mother = mcParticle.template mothers_as()[0]; // to be primary electron + if (mother.eta() < -0.9 || 0.9 < mother.eta()) { + continue; + } + if (std::abs(mother.pdgCode()) != 11) { // select bremsstrahlung photon from primary electron + continue; + } + if (!(mother.isPhysicalPrimary() || mother.producedByGenerator())) { // select bremsstrahlung photon from primary electron + continue; + } + + registry.fill(HIST("Photon/hXY"), mcParticle.vx(), mcParticle.vy()); + registry.fill(HIST("Photon/hs"), mcParticle.pt(), mcParticle.eta(), mcParticle.phi() > 0 ? mcParticle.phi() : mcParticle.phi() + 2 * M_PI); + // int ndau = mother.daughtersIds()[1] - mother.daughtersIds()[0] + 1; + // LOGF(info, "ndau = %d", ndau); + + for (const auto& daughter : mother.daughters_as()) { + // LOGF(info, "mother.globalIndex() = %d, daughter.globalIndex() = %d, daughter.pdgCode() = %d", mother.globalIndex(), daughter.globalIndex(), daughter.pdgCode()); + if (std::abs(daughter.pdgCode()) == 11 && (!daughter.isPhysicalPrimary() && !daughter.producedByGenerator())) { + float reldpt = (daughter.pt() - mother.pt()) / mother.pt(); + float rxy = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); + float phi_bremss = RecoDecay::phi(daughter.vy(), daughter.vx()); + o2::math_utils::bringTo02Pi(phi_bremss); + registry.fill(HIST("Photon/hsDelta"), reldpt, mother.pt(), rxy, phi_bremss, daughter.vz()); + } + } + + } // end of mc particle per mc collision + + } // end of mc collision loop + } + PROCESS_SWITCH(testBremsstrahlung, processGen, "process generated info", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"test-bremsstrahlung"})}; +} diff --git a/PWGEM/Dilepton/Utils/EMFwdTrack.h b/PWGEM/Dilepton/Utils/EMFwdTrack.h index 7f59bb67a1d..3b8ec9ec18e 100644 --- a/PWGEM/Dilepton/Utils/EMFwdTrack.h +++ b/PWGEM/Dilepton/Utils/EMFwdTrack.h @@ -15,6 +15,9 @@ #ifndef PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ #define PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ +#include +#include + namespace o2::aod::pwgem::dilepton::utils { class EMFwdTrack @@ -51,9 +54,9 @@ class EMFwdTrack float e() const { return std::hypot(fPt * std::cosh(fEta), fMass); } // e2 = p2 + m2 float signed1Pt() const { return fCharge * 1.f / fPt; } - float cXXatDCA() const { return fCXX; } - float cXYatDCA() const { return fCXY; } - float cYYatDCA() const { return fCYY; } + float cXX() const { return fCXX; } + float cXY() const { return fCXY; } + float cYY() const { return fCYY; } protected: float fPt; @@ -68,5 +71,73 @@ class EMFwdTrack float fCYY; }; +class EMFwdTrackWithCov : public EMFwdTrack +{ + public: + EMFwdTrackWithCov(float pt, float eta, float phi, float mass, int8_t charge, float dcaX, float dcaY, float cXX, float cXY, float cYY, + float X = 0.f, float Y = 0.f, float Z = 0.f, float tgl = 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(pt, eta, phi, mass, charge, dcaX, dcaY, cXX, cXY, cYY) + { + fX = X; + fY = Y; + fZ = Z; + fTgl = tgl; + fCPhiX = cPhiX; + fCPhiY = cPhiY; + fCPhiPhi = cPhiPhi; + fCTglX = cTglX; + fCTglY = cTglY; + fCTglPhi = cTglPhi; + fCTglTgl = cTglTgl; + fC1PtX = c1PtX; + fC1PtY = c1PtY; + fC1PtPhi = c1PtPhi; + fC1PtTgl = c1PtTgl; + fC1Pt21Pt2 = c1Pt21Pt2; + fChi2 = chi2; + } + + ~EMFwdTrackWithCov() {} + + float x() const { return fX; } + float y() const { return fY; } + float z() const { return fZ; } + float tgl() const { return fTgl; } + float cPhiX() const { return fCPhiX; } + float cPhiY() const { return fCPhiY; } + float cPhiPhi() const { return fCPhiPhi; } + float cTglX() const { return fCTglX; } + float cTglY() const { return fCTglY; } + float cTglPhi() const { return fCTglPhi; } + float cTglTgl() const { return fCTglTgl; } + float c1PtX() const { return fC1PtX; } + float c1PtY() const { return fC1PtY; } + float c1PtPhi() const { return fC1PtPhi; } + float c1PtTgl() const { return fC1PtTgl; } + float c1Pt21Pt2() const { return fC1Pt21Pt2; } + float chi2() const { return fChi2; } + + protected: + float fX; + float fY; + float fZ; + float fTgl; + float fCPhiX; + float fCPhiY; + float fCPhiPhi; + float fCTglX; + float fCTglY; + float fCTglPhi; + float fCTglTgl; + float fC1PtX; + float fC1PtY; + float fC1PtPhi; + float fC1PtTgl; + float fC1Pt21Pt2; + float fChi2; // chi2 not chi2/ndf +}; + } // namespace o2::aod::pwgem::dilepton::utils #endif // PWGEM_DILEPTON_UTILS_EMFWDTRACK_H_ diff --git a/PWGEM/Dilepton/Utils/EMTrack.h b/PWGEM/Dilepton/Utils/EMTrack.h index d50e9d1fe2c..8efb0c78226 100644 --- a/PWGEM/Dilepton/Utils/EMTrack.h +++ b/PWGEM/Dilepton/Utils/EMTrack.h @@ -15,7 +15,13 @@ #ifndef PWGEM_DILEPTON_UTILS_EMTRACK_H_ #define PWGEM_DILEPTON_UTILS_EMTRACK_H_ -#include "Math/Vector4D.h" +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include + +#include namespace o2::aod::pwgem::dilepton::utils { @@ -75,11 +81,11 @@ class EMTrackWithCov : public EMTrack { public: EMTrackWithCov(float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, - 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 X = 0.f, float Y = 0.f, float Z = 0.f, float Alpha = 0.f, float Snp = 0.f, float Tgl = 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(pt, eta, phi, mass, charge, dcaXY, dcaZ) + float C1PtY = 0.f, float C1PtZ = 0.f, float C1PtSnp = 0.f, float C1PtTgl = 0.f, float C1Pt21Pt2 = 0.f) : EMTrack(pt, eta, phi, mass, charge, dcaXY, dcaZ, CYY, CZY, CZZ) { fX = X; fY = Y; diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index 5c5b21e6ea0..ba9953f48b1 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -15,33 +15,55 @@ #ifndef PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ -#include "Framework/DataTypes.h" -#include "Framework/Logger.h" +#include #include +#include +#include #include -#include -#include +#include //_______________________________________________________________________ namespace o2::aod::pwgem::dilepton::utils::emtrackutil { -enum class RefTrackBit : uint16_t { // This is not for leptons, but charged tracks for reference flow. - kNclsITS5 = 1, - kNclsITS6 = 2, - kNcrTPC70 = 4, - kNcrTPC90 = 8, - kNclsTPC50 = 16, // (not necessary, if ncr is used.) - kNclsTPC70 = 32, // (not necessary, if ncr is used.) - kNclsTPC90 = 64, // (not necessary, if ncr is used.) - kChi2TPC4 = 128, - kChi2TPC3 = 256, - kFracSharedTPC07 = 512, - kDCAxy05cm = 1024, // default is 1 cm - kDCAxy03cm = 2048, - kDCAz05cm = 4096, // default is 1cm - kDCAz03cm = 8192, +enum class RefTrackType : int { // charged tracks for reference flow. + kCB = 0, + kMFTsa = 1, +}; + +// This is not for leptons, but charged tracks for reference flow. +enum class RefTrackBit : int { + kNclsITS5 = 0, + kNclsITS6, + kNcrTPC70, + kNcrTPC90, + kNclsTPC50, // (not necessary, if ncr is used.) + kNclsTPC70, // (not necessary, if ncr is used.) + kNclsTPC90, // (not necessary, if ncr is used.) + kChi2TPC4, + kChi2TPC3, + kFracSharedTPC07, + kDCAxy05cm, // default is 1 cm + kDCAxy03cm, + kDCAz05cm, // default is 1cm + kDCAz03cm, + kNCuts, +}; + +// This is not for leptons, but charged tracks for reference flow. +enum class RefMFTTrackBit : int { + kNclsMFT6 = 0, // default is 5 + kNclsMFT7, + kNclsMFT8, + kChi2MFT3, // default is 4 + kChi2MFT2, + kDCAxy005cm, // default is 0.06 cm + kDCAxy004cm, + kDCAxy003cm, + kDCAxy002cm, + kDCAxy001cm, + kNCuts, }; //_______________________________________________________________________ @@ -86,9 +108,9 @@ float dcaZinSigma(T const& track) template float fwdDcaXYinSigma(T const& track) { - float cXX = track.cXXatDCA(); // in cm^2 - float cYY = track.cYYatDCA(); // in cm^2 - float cXY = track.cXYatDCA(); // in cm^2 + float cXX = track.cXX(); // in cm^2 + float cYY = track.cYY(); // in cm^2 + float cXY = track.cXY(); // in cm^2 float dcaX = track.fwdDcaX(); // in cm float dcaY = track.fwdDcaY(); // in cm float det = cXX * cYY - cXY * cXY; // determinant @@ -123,33 +145,72 @@ bool checkMFTHitMap(T const& track) return (clmap > 0); } //_______________________________________________________________________ -template +template bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) { - // this is only for muon at forward rapidity + // find the best glboal muon without pt, eta cut (ie. without single track acceptance cut) to keep possibility for unfolding. + + // this is only for global muons at forward rapidity + // Be careful! tracks are fwdtracks per DF. if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + bool isBestFromMCHMID2MFT = false; + bool isBestFromMFT2MCHMID = false; std::map map_chi2MCHMFT; + + // 1 MFTsa track can match several MCH-MID tracks. find best global muon per MFTsa. map_chi2MCHMFT[track.globalIndex()] = track.chi2MatchMCHMFT(); // add myself for (const auto& glmuonId : track.globalMuonsWithSameMFTIds()) { - const auto& candidate = tracks.rawIteratorAt(glmuonId); - if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { - if (cut.template IsSelectedTrack(candidate)) { + auto candidate = tracks.rawIteratorAt(glmuonId); + if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId() && candidate.mchtrackId() != track.mchtrackId()) { + if (cut.template IsSelectedTrack(candidate)) { map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); } } + } // end of glmuonId + + auto it0 = std::min_element(map_chi2MCHMFT.begin(), map_chi2MCHMFT.end(), [](decltype(map_chi2MCHMFT)::value_type& l, decltype(map_chi2MCHMFT)::value_type& r) -> bool { return l.second < r.second; }); // search for minimum matching-chi2 + if (it0->first == track.globalIndex()) { + isBestFromMFT2MCHMID = true; + } else { + isBestFromMFT2MCHMID = false; } - if (map_chi2MCHMFT.begin()->first == track.globalIndex()) { // search for minimum matching-chi2 - map_chi2MCHMFT.clear(); - return true; + map_chi2MCHMFT.clear(); + + // find best global muon per MCH-MID tracks. Keep in mind that there are 5 global muons per MCH-MID in pp/OO and 20 global muons per MCH-MID in PbPb. + map_chi2MCHMFT[track.globalIndex()] = track.chi2MatchMCHMFT(); // add myself + for (const auto& glmuonId : track.globalMuonsWithSameMCHMIDIds()) { + auto candidate = tracks.rawIteratorAt(glmuonId); + if (candidate.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && candidate.emeventId() == track.emeventId() && candidate.mfttrackId() != track.mfttrackId()) { + if (cut.template IsSelectedTrack(candidate)) { + map_chi2MCHMFT[candidate.globalIndex()] = candidate.chi2MatchMCHMFT(); + } + } + } // end of glmuonId + + auto it1 = std::min_element(map_chi2MCHMFT.begin(), map_chi2MCHMFT.end(), [](decltype(map_chi2MCHMFT)::value_type& l, decltype(map_chi2MCHMFT)::value_type& r) -> bool { return l.second < r.second; }); // search for minimum matching-chi2 + if (it1->first == track.globalIndex()) { + isBestFromMCHMID2MFT = true; } else { - map_chi2MCHMFT.clear(); - return false; + isBestFromMCHMID2MFT = false; } + map_chi2MCHMFT.clear(); + + return isBestFromMCHMID2MFT && isBestFromMFT2MCHMID; } else { return true; } } //_______________________________________________________________________ +template +std::unordered_map findBestMatchMap(TTracks const& tracks, TCut const& cut) +{ + std::unordered_map map; + for (const auto& track : tracks) { + map[track.globalIndex()] = isBestMatch(track, cut, tracks); + } + return map; +} +//_______________________________________________________________________ // template // float sigmaPt(T const& track) // { diff --git a/PWGEM/Dilepton/Utils/EventHistograms.h b/PWGEM/Dilepton/Utils/EventHistograms.h index 3f123920339..fc4061610eb 100644 --- a/PWGEM/Dilepton/Utils/EventHistograms.h +++ b/PWGEM/Dilepton/Utils/EventHistograms.h @@ -15,20 +15,28 @@ #ifndef PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ #define PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" + #include "Common/Core/RecoDecay.h" -#include "Framework/HistogramRegistry.h" +#include +#include + +#include + +#include +#include -using namespace o2::framework; +#include namespace o2::aod::pwgem::dilepton::utils::eventhistogram { const int nbin_ev = 21; template -void addEventHistograms(HistogramRegistry* fRegistry) +void addEventHistograms(o2::framework::HistogramRegistry* fRegistry) { // event info - auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1D, {{nbin_ev, 0.5, nbin_ev + 0.5}}, false); + auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", o2::framework::kTH1D, {{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"); @@ -51,187 +59,185 @@ void addEventHistograms(HistogramRegistry* fRegistry) hCollisionCounter->GetXaxis()->SetBinLabel(20, "Calibrated Q vector"); hCollisionCounter->GetXaxis()->SetBinLabel(21, "accepted"); - const AxisSpec axis_cent_ft0m{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, - "centrality FT0M (%)"}; - - const AxisSpec axis_cent_ft0a{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, - "centrality FT0A (%)"}; - - const AxisSpec axis_cent_ft0c{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, - "centrality FT0C (%)"}; - - fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1D, {{100, -50, +50}}, false); - fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1D, {{6001, -0.5, 6000.5}}, false); - fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1D, {{6001, -0.5, 6000.5}}, false); - fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2D, {{200, 0, 200000}, {60, 0, 60000}}, false); - fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1D, {{axis_cent_ft0a}}, false); - fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1D, {{axis_cent_ft0c}}, false); - fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1D, {{axis_cent_ft0m}}, false); - fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2D, {{110, 0, 110}, {600, 0, 6000}}, false); - fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2D, {{60, 0, 60000}, {600, 0, 6000}}, false); - fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2D, {{60, 0, 60000}, {200, 0, 20000}}, false); - fRegistry->add("Event/before/hNTracksPVvsOccupancy", "hNTracksPVvsOccupancy;N_{track} to PV;N_{track} in time range", kTH2D, {{600, 0, 6000}, {200, 0, 20000}}, false); - fRegistry->add("Event/before/hCorrOccupancy", "occupancy correlation;FT0C occupancy;track occupancy", kTH2D, {{200, 0, 200000}, {200, 0, 20000}}, false); + fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", o2::framework::kTH1D, {{100, -50, +50}}, false); + fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", o2::framework::kTH1D, {{6001, -0.5, 6000.5}}, false); + fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", o2::framework::kTH2D, {{200, 0, 200000}, {60, 0, 60000}}, false); + fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", o2::framework::kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", o2::framework::kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", o2::framework::kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentNTPV", "hCentNTPV;centrality NTPV (%)", o2::framework::kTH1D, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", o2::framework::kTH2D, {{110, 0, 110}, {600, 0, 6000}}, false); + fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", o2::framework::kTH2D, {{60, 0, 60000}, {600, 0, 6000}}, false); + fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", o2::framework::kTH2D, {{60, 0, 60000}, {200, 0, 20000}}, false); + fRegistry->add("Event/before/hNTracksPVvsOccupancy", "hNTracksPVvsOccupancy;N_{track} to PV;N_{track} in time range", o2::framework::kTH2D, {{600, 0, 6000}, {200, 0, 20000}}, false); + fRegistry->add("Event/before/hCorrOccupancy", "occupancy correlation;FT0C occupancy;track occupancy", o2::framework::kTH2D, {{200, 0, 200000}, {200, 0, 20000}}, false); if constexpr (nmod == 2) { - fRegistry->add("Event/before/hQ2xFT0M_CentFT0C", "hQ2xFT0M_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0M}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFT0M_CentFT0C", "hQ2yFT0M_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0M}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xFT0A_CentFT0C", "hQ2xFT0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFT0A_CentFT0C", "hQ2yFT0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xFT0C_CentFT0C", "hQ2xFT0C_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0C}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFT0C_CentFT0C", "hQ2yFT0C_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0C}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xFV0A_CentFT0C", "hQ2xFV0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FV0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yFV0A_CentFT0C", "hQ2yFV0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FV0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xBPos_CentFT0C", "hQ2xBPos_CentFT0C;centrality FT0C (%);Q_{2,x}^{BPos}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yBPos_CentFT0C", "hQ2yBPos_CentFT0C;centrality FT0C (%);Q_{2,y}^{BPos}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xBNeg_CentFT0C", "hQ2xBNeg_CentFT0C;centrality FT0C (%);Q_{2,x}^{BNeg}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yBNeg_CentFT0C", "hQ2yBNeg_CentFT0C;centrality FT0C (%);Q_{2,y}^{BNeg}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2xBTot_CentFT0C", "hQ2xBTot_CentFT0C;centrality FT0C (%);Q_{2,x}^{BTot}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ2yBTot_CentFT0C", "hQ2yBTot_CentFT0C;centrality FT0C (%);Q_{2,y}^{BTot}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xFT0M_CentFT0C", "hQ2xFT0M_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0M}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFT0M_CentFT0C", "hQ2yFT0M_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0M}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xFT0A_CentFT0C", "hQ2xFT0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFT0A_CentFT0C", "hQ2yFT0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xFT0C_CentFT0C", "hQ2xFT0C_CentFT0C;centrality FT0C (%);Q_{2,x}^{FT0C}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFT0C_CentFT0C", "hQ2yFT0C_CentFT0C;centrality FT0C (%);Q_{2,y}^{FT0C}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xFV0A_CentFT0C", "hQ2xFV0A_CentFT0C;centrality FT0C (%);Q_{2,x}^{FV0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yFV0A_CentFT0C", "hQ2yFV0A_CentFT0C;centrality FT0C (%);Q_{2,y}^{FV0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xBPos_CentFT0C", "hQ2xBPos_CentFT0C;centrality FT0C (%);Q_{2,x}^{BPos}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yBPos_CentFT0C", "hQ2yBPos_CentFT0C;centrality FT0C (%);Q_{2,y}^{BPos}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xBNeg_CentFT0C", "hQ2xBNeg_CentFT0C;centrality FT0C (%);Q_{2,x}^{BNeg}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yBNeg_CentFT0C", "hQ2yBNeg_CentFT0C;centrality FT0C (%);Q_{2,y}^{BNeg}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2xBTot_CentFT0C", "hQ2xBTot_CentFT0C;centrality FT0C (%);Q_{2,x}^{BTot}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ2yBTot_CentFT0C", "hQ2yBTot_CentFT0C;centrality FT0C (%);Q_{2,y}^{BTot}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hEP2FT0M_CentFT0C", "2nd harmonics event plane FT0M;centrality FT0C (%);#Psi_{2}^{FT0M} (rad.)", kTH2D, {{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.)", kTH2D, {{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.)", kTH2D, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP2FV0A_CentFT0C", "2nd harmonics event plane FV0A;centrality FT0C (%);#Psi_{2}^{FV0A} (rad.)", kTH2D, {{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.)", kTH2D, {{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.)", kTH2D, {{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.)", kTH2D, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2FT0M_CentFT0C", "2nd harmonics event plane FT0M;centrality FT0C (%);#Psi_{2}^{FT0M} (rad.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP2FV0A_CentFT0C", "2nd harmonics event plane FV0A;centrality FT0C (%);#Psi_{2}^{FV0A} (rad.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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 - fRegistry->add("Event/before/hPrfQ2FV0AQ2BPos_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BPos}", kTProfile, {{100, 0, 100}}, false); - fRegistry->add("Event/before/hPrfQ2FV0AQ2BNeg_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BNeg}", kTProfile, {{100, 0, 100}}, false); - fRegistry->add("Event/before/hPrfQ2FV0AQ2BTot_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BTot};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BTot}", kTProfile, {{100, 0, 100}}, false); - fRegistry->add("Event/before/hPrfQ2FV0AQ2FT0C_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{FT0C};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{FT0C}", kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + fRegistry->add("Event/before/hPrfQ2FT0MQ2BPos_CentFT0C", "Q_{2}^{FT0M} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FT0M} #upoint Q_{2}^{BPos}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + fRegistry->add("Event/before/hPrfQ2FV0AQ2BPos_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BPos};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BPos}", o2::framework::kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FV0AQ2BNeg_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BNeg}", o2::framework::kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FV0AQ2BTot_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{BTot};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{BTot}", o2::framework::kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ2FV0AQ2FT0C_CentFT0C", "Q_{2}^{FV0A} #upoint Q_{2}^{FT0C};centrality FT0C (%);Q_{2}^{FV0A} #upoint Q_{2}^{FT0C}", o2::framework::kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons } else if constexpr (nmod == 3) { - fRegistry->add("Event/before/hQ3xFT0M_CentFT0C", "hQ3xFT0M_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0M}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yFT0M_CentFT0C", "hQ3yFT0M_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0M}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3xFT0A_CentFT0C", "hQ3xFT0A_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yFT0A_CentFT0C", "hQ3yFT0A_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3xFT0C_CentFT0C", "hQ3xFT0C_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0C}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yFT0C_CentFT0C", "hQ3yFT0C_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0C}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3xFV0A_CentFT0C", "hQ3xFV0A_CentFT0C;centrality FT0C (%);Q_{3,x}^{FV0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yFV0A_CentFT0C", "hQ3yFV0A_CentFT0C;centrality FT0C (%);Q_{3,y}^{FV0A}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3xBPos_CentFT0C", "hQ3xBPos_CentFT0C;centrality FT0C (%);Q_{3,x}^{BPos}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yBPos_CentFT0C", "hQ3yBPos_CentFT0C;centrality FT0C (%);Q_{3,y}^{BPos}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3xBNeg_CentFT0C", "hQ3xBNeg_CentFT0C;centrality FT0C (%);Q_{3,x}^{BNeg}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yBNeg_CentFT0C", "hQ3yBNeg_CentFT0C;centrality FT0C (%);Q_{3,y}^{BNeg}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3xBTot_CentFT0C", "hQ3xBTot_CentFT0C;centrality FT0C (%);Q_{3,x}^{BTot}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hQ3yBTot_CentFT0C", "hQ3yBTot_CentFT0C;centrality FT0C (%);Q_{3,y}^{BTot}", kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xFT0M_CentFT0C", "hQ3xFT0M_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0M}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFT0M_CentFT0C", "hQ3yFT0M_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0M}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xFT0A_CentFT0C", "hQ3xFT0A_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFT0A_CentFT0C", "hQ3yFT0A_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xFT0C_CentFT0C", "hQ3xFT0C_CentFT0C;centrality FT0C (%);Q_{3,x}^{FT0C}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFT0C_CentFT0C", "hQ3yFT0C_CentFT0C;centrality FT0C (%);Q_{3,y}^{FT0C}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xFV0A_CentFT0C", "hQ3xFV0A_CentFT0C;centrality FT0C (%);Q_{3,x}^{FV0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yFV0A_CentFT0C", "hQ3yFV0A_CentFT0C;centrality FT0C (%);Q_{3,y}^{FV0A}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xBPos_CentFT0C", "hQ3xBPos_CentFT0C;centrality FT0C (%);Q_{3,x}^{BPos}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yBPos_CentFT0C", "hQ3yBPos_CentFT0C;centrality FT0C (%);Q_{3,y}^{BPos}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xBNeg_CentFT0C", "hQ3xBNeg_CentFT0C;centrality FT0C (%);Q_{3,x}^{BNeg}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yBNeg_CentFT0C", "hQ3yBNeg_CentFT0C;centrality FT0C (%);Q_{3,y}^{BNeg}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3xBTot_CentFT0C", "hQ3xBTot_CentFT0C;centrality FT0C (%);Q_{3,x}^{BTot}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); + fRegistry->add("Event/before/hQ3yBTot_CentFT0C", "hQ3yBTot_CentFT0C;centrality FT0C (%);Q_{3,y}^{BTot}", o2::framework::kTH2D, {{100, 0, 100}, {200, -10, +10}}, false); - fRegistry->add("Event/before/hEP3FT0M_CentFT0C", "3rd harmonics event plane FT0M;centrality FT0C (%);#Psi_{3}^{FT0M} (rad.)", kTH2D, {{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.)", kTH2D, {{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.)", kTH2D, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); - fRegistry->add("Event/before/hEP3FV0A_CentFT0C", "3rd harmonics event plane FV0A;centrality FT0C (%);#Psi_{3}^{FV0A} (rad.)", kTH2D, {{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.)", kTH2D, {{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.)", kTH2D, {{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.)", kTH2D, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3FT0M_CentFT0C", "3rd harmonics event plane FT0M;centrality FT0C (%);#Psi_{3}^{FT0M} (rad.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{100, 0, 100}, {36, -M_PI_2, +M_PI_2}}, false); + fRegistry->add("Event/before/hEP3FV0A_CentFT0C", "3rd harmonics event plane FV0A;centrality FT0C (%);#Psi_{3}^{FV0A} (rad.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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.)", o2::framework::kTH2D, {{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 - fRegistry->add("Event/before/hPrfQ3FV0AQ3BPos_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{BPos};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{BPos}", kTProfile, {{100, 0, 100}}, false); - fRegistry->add("Event/before/hPrfQ3FV0AQ3BNeg_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{BNeg};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{BNeg}", kTProfile, {{100, 0, 100}}, false); - fRegistry->add("Event/before/hPrfQ3FV0AQ3BTot_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{BTot};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{BTot}", kTProfile, {{100, 0, 100}}, false); - fRegistry->add("Event/before/hPrfQ3FV0AQ3FT0C_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{FT0C};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{FT0C}", kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + fRegistry->add("Event/before/hPrfQ3FT0MQ3BPos_CentFT0C", "Q_{3}^{FT0M} #upoint Q_{3}^{BPos};centrality FT0C (%);Q_{3}^{FT0M} #upoint Q_{3}^{BPos}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::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}", o2::framework::kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons + fRegistry->add("Event/before/hPrfQ3FV0AQ3BPos_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{BPos};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{BPos}", o2::framework::kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FV0AQ3BNeg_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{BNeg};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{BNeg}", o2::framework::kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FV0AQ3BTot_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{BTot};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{BTot}", o2::framework::kTProfile, {{100, 0, 100}}, false); + fRegistry->add("Event/before/hPrfQ3FV0AQ3FT0C_CentFT0C", "Q_{3}^{FV0A} #upoint Q_{3}^{FT0C};centrality FT0C (%);Q_{3}^{FV0A} #upoint Q_{3}^{FT0C}", o2::framework::kTProfile, {{100, 0, 100}}, false); // this is necessary for dimuons } fRegistry->addClone("Event/before/", "Event/after/"); } +void addEventHistogramsBootstrap(o2::framework::HistogramRegistry* fRegistry, int nsamples = 1) +{ + fRegistry->add("Event/bootstrap/hPoissonWeights", "Poisson Weights per sample;sample;weight", o2::framework::kTH2D, {{nsamples, 0.5, nsamples + 0.5}, {210, -1, 20}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0MQ2BPos_CentFT0C_bootstrap", "Q_{2}^{FT0M} #upoint Q_{2}^{BPos};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0M} #upoint Q_{2}^{BPos}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0MQ2BNeg_CentFT0C_bootstrap", "Q_{2}^{FT0M} #upoint Q_{2}^{BNeg};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0M} #upoint Q_{2}^{BNeg}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2BPosQ2BNeg_CentFT0C_bootstrap", "Q_{2}^{BPos} #upoint Q_{2}^{BNeg};centrality FT0C (%);bootstrap sample;Q_{2}^{BPos} #upoint Q_{2}^{BNeg}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0CQ2BPos_CentFT0C_bootstrap", "Q_{2}^{FT0C} #upoint Q_{2}^{BPos};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0C} #upoint Q_{2}^{BPos}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0CQ2BNeg_CentFT0C_bootstrap", "Q_{2}^{FT0C} #upoint Q_{2}^{BNeg};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0C} #upoint Q_{2}^{BNeg}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0CQ2BTot_CentFT0C_bootstrap", "Q_{2}^{FT0C} #upoint Q_{2}^{BTot};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0C} #upoint Q_{2}^{BTot}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0AQ2BPos_CentFT0C_bootstrap", "Q_{2}^{FT0A} #upoint Q_{2}^{BPos};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0A} #upoint Q_{2}^{BPos}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0AQ2BNeg_CentFT0C_bootstrap", "Q_{2}^{FT0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0A} #upoint Q_{2}^{BNeg}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0AQ2BTot_CentFT0C_bootstrap", "Q_{2}^{FT0A} #upoint Q_{2}^{BTot};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0A} #upoint Q_{2}^{BTot}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FT0AQ2FT0C_CentFT0C_bootstrap", "Q_{2}^{FT0A} #upoint Q_{2}^{FT0C};centrality FT0C (%);bootstrap sample;Q_{2}^{FT0A} #upoint Q_{2}^{FT0C}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FV0AQ2BPos_CentFT0C_bootstrap", "Q_{2}^{FV0A} #upoint Q_{2}^{BPos};centrality FT0C (%);bootstrap sample;Q_{2}^{FV0A} #upoint Q_{2}^{BPos}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FV0AQ2BNeg_CentFT0C_bootstrap", "Q_{2}^{FV0A} #upoint Q_{2}^{BNeg};centrality FT0C (%);bootstrap sample;Q_{2}^{FV0A} #upoint Q_{2}^{BNeg}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FV0AQ2BTot_CentFT0C_bootstrap", "Q_{2}^{FV0A} #upoint Q_{2}^{BTot};centrality FT0C (%);bootstrap sample;Q_{2}^{FV0A} #upoint Q_{2}^{BTot}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); + fRegistry->add("Event/bootstrap/hPrfQ2FV0AQ2FT0C_CentFT0C_bootstrap", "Q_{2}^{FV0A} #upoint Q_{2}^{FT0C};centrality FT0C (%);bootstrap sample;Q_{2}^{FV0A} #upoint Q_{2}^{FT0C}", o2::framework::kTProfile2D, {{100, 0, 100}, {nsamples, 0.5, nsamples + 0.5}}, false); +} + template -void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, const float /*weight*/ = 1.f) +void fillEventInfo(o2::framework::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)) { + if (collision.selection_bit(o2::aod::emevsel::kIsTriggerTVX)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); } - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoTimeFrameBorder)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (collision.selection_bit(o2::aod::emevsel::kNoITSROFrameBorder)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (collision.selection_bit(o2::aod::emevsel::kNoSameBunchPileup)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodZvtxFT0vsPV)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexITSTPC)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (collision.selection_bit(o2::aod::emevsel::kIsVertexTRDmatched)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); } - if (collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (collision.selection_bit(o2::aod::emevsel::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) { + if (std::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)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStandard)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 12.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInTimeRangeStrict)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 13.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStandard)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 14.0); } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (collision.selection_bit(o2::aod::emevsel::kNoCollInRofStrict)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 15.0); } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (collision.selection_bit(o2::aod::emevsel::kNoHighMultCollInPrevRof)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 16.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer3)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 17.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayer0123)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 18.0); } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (collision.selection_bit(o2::aod::emevsel::kIsGoodITSLayersAll)) { fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 19.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("hCentNTPV"), collision.centNTPV()); 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()); @@ -332,5 +338,32 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hPrfQ3FV0AQ3BTot_CentFT0C"), collision.centFT0C(), RecoDecay::dotProd(q3fv0a, q3btot)); } } +template +void fillEventInfoBootstrap(o2::framework::HistogramRegistry* fRegistry, TCollision const& collision, const int sample, const float weight) +{ + 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()}; + std::array q2btot = {collision.q2xbtot(), collision.q2ybtot()}; + + fRegistry->fill(HIST("Event/bootstrap/hPoissonWeights"), sample + 0.5, weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0MQ2BPos_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0m, q2bpos), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0MQ2BNeg_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0m, q2bneg), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2BPosQ2BNeg_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2bpos, q2bneg), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0CQ2BPos_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0c, q2bpos), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0CQ2BNeg_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0c, q2bneg), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0CQ2BTot_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0c, q2btot), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0AQ2BPos_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0a, q2bpos), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0AQ2BNeg_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0a, q2bneg), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0AQ2BTot_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0a, q2btot), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FT0AQ2FT0C_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2ft0a, q2ft0c), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FV0AQ2BPos_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2fv0a, q2bpos), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FV0AQ2BNeg_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2fv0a, q2bneg), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FV0AQ2BTot_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2fv0a, q2btot), weight); + fRegistry->fill(HIST("Event/bootstrap/hPrfQ2FV0AQ2FT0C_CentFT0C_bootstrap"), collision.centFT0C(), sample + 0.5, RecoDecay::dotProd(q2fv0a, q2ft0c), weight); +} } // namespace o2::aod::pwgem::dilepton::utils::eventhistogram #endif // PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ diff --git a/PWGEM/Dilepton/Utils/EventMixingHandler.h b/PWGEM/Dilepton/Utils/EventMixingHandler.h index 20b38399979..4698654be49 100644 --- a/PWGEM/Dilepton/Utils/EventMixingHandler.h +++ b/PWGEM/Dilepton/Utils/EventMixingHandler.h @@ -16,7 +16,6 @@ #define PWGEM_DILEPTON_UTILS_EVENTMIXINGHANDLER_H_ #include -#include #include namespace o2::aod::pwgem::dilepton::utils diff --git a/PWGEM/Dilepton/Utils/MCUtilities.h b/PWGEM/Dilepton/Utils/MCUtilities.h index 1026576a805..d0a9a69df0e 100644 --- a/PWGEM/Dilepton/Utils/MCUtilities.h +++ b/PWGEM/Dilepton/Utils/MCUtilities.h @@ -15,11 +15,11 @@ #ifndef PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ -#include "Framework/AnalysisDataModel.h" -#include "Framework/Logger.h" +#include +#include -#include #include +#include #include //_______________________________________________________________________ @@ -32,6 +32,9 @@ enum class EM_HFeeType : int { kBCe_BCe = 2, // ULS kBCe_Be_SameB = 3, // ULS kBCe_Be_DiffB = 4, // LS + kBCCe_BCe = 5, // ULS + kBCCe_BCCe = 6, // ULS + kBCCee = 7, // ULS }; //_______________________________________________________________________ @@ -461,6 +464,56 @@ int IsFromCharm(TMCParticle const& p, TMCParticles const& mcparticles) return -999; } //_______________________________________________________________________ +template +std::pair getBeautyHadronIDandNCharmHadronDaughters(T const& mcParticle, U const& mcParticles) +{ + if (!mcParticle.has_mothers()) { + return {-999, -999}; + } + if (!IsFromBeauty(mcParticle, mcParticles)) { + return {-999, -999}; + } + + auto mp = mcParticles.iteratorAt(mcParticle.mothersIds()[0]); + if (!isCharmMeson(mp) && !isCharmBaryon(mp)) { + return {-999, -999}; + } + + int motherid = mcParticle.mothersIds()[0]; // first mother index + while (motherid > -1) { + if (motherid < mcParticles.size()) { // protect against bad mother indices. why is this needed? + mp = mcParticles.iteratorAt(motherid); + if (std::abs(mp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 3] == '5' || std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 4] == '5')) { + // check if mp has two charm hadrons as daughters + if (mp.has_daughters()) { + const auto& daughtersIds = mp.daughtersIds(); + int count_charm_hadron = 0; + for (const auto& daughterId : daughtersIds) { + if (daughterId >= 0 && daughterId < mcParticles.size()) { + auto daughter = mcParticles.iteratorAt(daughterId); + if (isCharmMeson(daughter) || isCharmBaryon(daughter)) { + count_charm_hadron++; + } + } + } + return {motherid, count_charm_hadron}; + } else { + LOGF(debug, "Something went wrong: Did not find any daughter for the current mother! Can't be a mother if there are no daughters\n"); + } + return {-999, -999}; + } + if (mp.has_mothers()) { + motherid = mp.mothersIds()[0]; + } else { + return {-999, -999}; + } + } else { + LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid, mcParticles.size()); + } + } + return {-999, -999}; +} +//_______________________________________________________________________ template bool isFlavorOscillationB(TMCParticle const& mcParticle) { @@ -551,7 +604,7 @@ int find1stHadron(TMCParticle const& mcParticle, TMCParticles const& mcParticles return hadronId; } //_______________________________________________________________________ -template +template int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcparticles) { if (!p1.has_mothers() || !p2.has_mothers()) { @@ -661,7 +714,29 @@ 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::kBCe_BCe); // b->c->e and b->c->e, decay type = 1 + + if constexpr (!doMoreDifferentially) { + return static_cast(EM_HFeeType::kBCe_BCe); // default to b->c->e and b->c->e, decay type = 1 + } else { + int beauty_motherid1 = getBeautyHadronIDandNCharmHadronDaughters(p1, mcparticles).first; + int beauty_motherid2 = getBeautyHadronIDandNCharmHadronDaughters(p2, mcparticles).first; + int n_c_from_b1 = getBeautyHadronIDandNCharmHadronDaughters(p1, mcparticles).second; + int n_c_from_b2 = getBeautyHadronIDandNCharmHadronDaughters(p2, mcparticles).second; + if (n_c_from_b1 == 1 && n_c_from_b2 == 1) { + return static_cast(EM_HFeeType::kBCe_BCe); // b->c->e and b->c->e, decay type = 1 + } else if (n_c_from_b1 == 2 && n_c_from_b2 == 2) { + if (beauty_motherid1 == beauty_motherid2) { // same beauty hadron decays into 2 charm hadrons which then decay semileptonically + return static_cast(EM_HFeeType::kBCCee); // b->cc->ee, decay type = 7 + } else { + return static_cast(EM_HFeeType::kBCCe_BCCe); // b->cc->e and b->cc->e, decay type = 6 + } + } else if ((n_c_from_b1 == 1 && n_c_from_b2 == 2) || (n_c_from_b1 == 2 && n_c_from_b2 == 1)) { + return static_cast(EM_HFeeType::kBCCe_BCe); // b->cc->e and b->c->e, decay type = 5 + } else { + LOGF(debug, "Unexpected number of charm hadrons from beauty decay: n_c_from_b1 = %d, n_c_from_b2 = %d. Return kBCe_BCe as default.", n_c_from_b1, n_c_from_b2); + return static_cast(EM_HFeeType::kBCe_BCe); // default to b->c->e and b->c->e, decay type = 1 + } + } } if ((is_direct_from_b1 && is_c_from_b2) || (is_direct_from_b2 && is_c_from_b1)) { diff --git a/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h b/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h index 5ec9756b5a9..e16ddd1b9c3 100644 --- a/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h +++ b/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h @@ -19,7 +19,9 @@ #include "Tools/ML/MlResponse.h" -#include +#include + +#include #include #include diff --git a/PWGEM/Dilepton/Utils/MlResponseO2Track.h b/PWGEM/Dilepton/Utils/MlResponseO2Track.h index d898d9da5f6..0b1bdbbe2be 100644 --- a/PWGEM/Dilepton/Utils/MlResponseO2Track.h +++ b/PWGEM/Dilepton/Utils/MlResponseO2Track.h @@ -11,15 +11,16 @@ /// \file MlResponseO2Track.h /// \brief Class to compute the ML response for dielectron analyses at the single track level -/// \author Daniel Samitz , SMI Vienna -/// Elisa Meninno, , SMI Vienna +/// \author Daiki Sekihata #ifndef PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ #define PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ #include "Tools/ML/MlResponse.h" -#include +#include + +#include #include #include @@ -192,7 +193,7 @@ class MlResponseO2Track : public MlResponse virtual ~MlResponseO2Track() = default; template - float return_feature(uint8_t idx, T const& track, U const& trackParCov, V const& collision) + float return_feature(uint8_t idx, T const& track, U const& trackParCov, V const& collision, const float beta, const float tofNSigmaEl) { float inputFeature = 0.; switch (idx) { @@ -237,6 +238,14 @@ class MlResponseO2Track : public MlResponse CHECK_AND_FILL_DIELECTRON_COLLISION(trackOccupancyInTimeRange); CHECK_AND_FILL_DIELECTRON_COLLISION(ft0cOccupancyInTimeRange); } + + if (mUseReassociatedTOF) { // vector of map may be better. + if (idx == static_cast(InputFeaturesO2Track::tofNSigmaEl)) { + inputFeature = tofNSigmaEl; + } else if (idx == static_cast(InputFeaturesO2Track::beta)) { + inputFeature = beta; + } + } return inputFeature; } @@ -244,11 +253,11 @@ class MlResponseO2Track : public MlResponse /// \param track is the single track, \param collision is the collision /// \return inputFeatures vector template - std::vector getInputFeatures(T const& track, U const& trackParCov, V const& collision) + std::vector getInputFeatures(T const& track, U const& trackParCov, V const& collision, const float beta = -1.f, const float tofNSigmaEl = -999.f) { std::vector inputFeatures; for (const auto& idx : MlResponse::mCachedIndices) { - float inputFeature = return_feature(idx, track, trackParCov, collision); + float inputFeature = return_feature(idx, track, trackParCov, collision, beta, tofNSigmaEl); inputFeatures.emplace_back(inputFeature); } return inputFeatures; @@ -258,9 +267,9 @@ class MlResponseO2Track : public MlResponse /// \param track is the single track, \param collision is the collision /// \return binning variable template - float getBinningFeature(T const& track, U const& trackParCov, V const& collision) + float getBinningFeature(T const& track, U const& trackParCov, V const& collision, const float beta = -1.f, const float tofNSigmaEl = -999.f) { - return return_feature(mCachedIndexBinning, track, trackParCov, collision); + return return_feature(mCachedIndexBinning, track, trackParCov, collision, beta, tofNSigmaEl); } void cacheBinningIndex(std::string const& cfgBinningFeature) @@ -273,6 +282,8 @@ class MlResponseO2Track : public MlResponse } } + void useReassociatedTOF(const bool flag) { mUseReassociatedTOF = flag; } + protected: /// Method to fill the map of available input features void setAvailableInputFeatures() @@ -321,6 +332,7 @@ class MlResponseO2Track : public MlResponse } uint8_t mCachedIndexBinning; // index correspondance between configurable and available input features + bool mUseReassociatedTOF{false}; }; } // namespace o2::analysis diff --git a/PWGEM/Dilepton/Utils/MomentumSmearer.h b/PWGEM/Dilepton/Utils/MomentumSmearer.h index d0e73ee971f..59bb41f948c 100644 --- a/PWGEM/Dilepton/Utils/MomentumSmearer.h +++ b/PWGEM/Dilepton/Utils/MomentumSmearer.h @@ -15,12 +15,12 @@ #ifndef PWGEM_DILEPTON_UTILS_MOMENTUMSMEARER_H_ #define PWGEM_DILEPTON_UTILS_MOMENTUMSMEARER_H_ -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include #include #include #include @@ -28,15 +28,12 @@ #include #include #include +#include #include +#include #include -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; - class MomentumSmearer { public: @@ -576,7 +573,7 @@ class MomentumSmearer void setCcdbPathRes(TString ccdbPathRes) { fCcdbPathRes = ccdbPathRes; } void setCcdbPathEff(TString ccdbPathEff) { fCcdbPathEff = ccdbPathEff; } void setCcdbPathDCA(TString ccdbPathDCA) { fCcdbPathDCA = ccdbPathDCA; } - void setCcdb(Service ccdb) + void setCcdb(o2::framework::Service ccdb) { fCcdb = ccdb; fFromCcdb = true; @@ -645,7 +642,7 @@ class MomentumSmearer std::vector fVecDCA; int64_t fTimestamp; bool fFromCcdb = false; - Service fCcdb; + o2::framework::Service fCcdb; float fMinPtGen = -1.f; }; diff --git a/PWGEM/Dilepton/Utils/PairUtilities.h b/PWGEM/Dilepton/Utils/PairUtilities.h index 0758289bbee..693045306eb 100644 --- a/PWGEM/Dilepton/Utils/PairUtilities.h +++ b/PWGEM/Dilepton/Utils/PairUtilities.h @@ -18,14 +18,20 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include -#include "Math/GenVector/Boost.h" -#include "Math/SMatrix.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" +#include +#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector3Dfwd.h) +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include +#include +#include #include //_______________________________________________________________________ @@ -43,6 +49,7 @@ enum class DileptonAnalysisType : int { kFlowV3 = 3, kPolarization = 4, kHFll = 5, + kBootstrapv2 = 6, }; enum class DileptonHadronAnalysisType : int { diff --git a/PWGEM/PhotonMeson/Core/CMakeLists.txt b/PWGEM/PhotonMeson/Core/CMakeLists.txt index 7e4eac119f4..1eb9558356d 100644 --- a/PWGEM/PhotonMeson/Core/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Core/CMakeLists.txt @@ -19,7 +19,8 @@ o2physics_add_library(PWGEMPhotonMesonCore CutsLibrary.cxx HistogramsLibrary.cxx EMBitFlags.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore) + EMNonLin.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore KFParticle::KFParticle) o2physics_target_root_dictionary(PWGEMPhotonMesonCore HEADERS V0PhotonCut.h @@ -31,4 +32,5 @@ o2physics_target_root_dictionary(PWGEMPhotonMesonCore CutsLibrary.h HistogramsLibrary.h EMBitFlags.h + EMNonLin.h LINKDEF PWGEMPhotonMesonCoreLinkDef.h) diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx index aaf16551ba6..6aae90e5d3c 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx @@ -22,9 +22,9 @@ #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include +#include -#include +#include #include #include diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.h b/PWGEM/PhotonMeson/Core/CutsLibrary.h index bf4fcfe7037..5647908dd1a 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.h +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.h @@ -15,13 +15,12 @@ #ifndef PWGEM_PHOTONMESON_CORE_CUTSLIBRARY_H_ #define PWGEM_PHOTONMESON_CORE_CUTSLIBRARY_H_ -#include -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" namespace o2::aod { diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx index f129a1ba289..c0709362278 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx @@ -15,7 +15,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "Framework/Logger.h" +#include #include diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.h b/PWGEM/PhotonMeson/Core/DalitzEECut.h index c238b5bead3..293a52424c0 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.h +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.h @@ -20,8 +20,9 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include +#include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include @@ -33,8 +34,6 @@ #include #include -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; - class DalitzEECut : public TNamed { public: @@ -72,7 +71,7 @@ class DalitzEECut : public TNamed kTPConly = 1, }; - template + template bool IsSelected(TTrack1 const& t1, TTrack2 const& t2, float bz) const { if (!IsSelectedTrack(t1) || !IsSelectedTrack(t2)) { @@ -86,7 +85,7 @@ class DalitzEECut : public TNamed return true; } - template + 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); @@ -108,7 +107,7 @@ class DalitzEECut : public TNamed return true; } - template + template bool IsSelectedTrack(TTrack const& track, TCollision const& = 0) const { if (!track.hasITS()) { @@ -194,7 +193,7 @@ class DalitzEECut : public TNamed return true; } - template + template bool PassPID(T const& track) const { switch (mPIDScheme) { @@ -212,7 +211,7 @@ class DalitzEECut : public TNamed } } - template + template bool PassTPConly(T const& track) const { bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; @@ -220,7 +219,7 @@ class DalitzEECut : public TNamed return is_el_included_TPC && is_pi_excluded_TPC; } - template + template bool PassTOFif(T const& track) const { bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; @@ -229,7 +228,7 @@ class DalitzEECut : public TNamed return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } - template + template bool IsSelectedTrack(T const& track, const DalitzEECuts& cut) const { switch (cut) { @@ -255,7 +254,7 @@ class DalitzEECut : public TNamed return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; case DalitzEECuts::kDCA3Dsigma: - return mMinDca3D < dca3DinSigma(track) && dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg + return mMinDca3D < o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track) && o2::aod::pwgem::dilepton::utils::emtrackutil::dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg case DalitzEECuts::kDCAxy: return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); diff --git a/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h b/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h deleted file mode 100644 index 54381491765..00000000000 --- a/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h +++ /dev/null @@ -1,992 +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 DiphotonHadronMPC.h -/// \brief This code is to analyze diphoton-hadron correlation. Keep in mind that cumulant method does not require event mixing. -/// \author D. Sekihata, daiki.sekihata@cern.ch - -#ifndef PWGEM_PHOTONMESON_CORE_DIPHOTONHADRONMPC_H_ -#define PWGEM_PHOTONMESON_CORE_DIPHOTONHADRONMPC_H_ - -#include "PWGEM/Dilepton/Core/EMTrackCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include // IWYU pragma: keep -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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::photonmeson::photonpair; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::dilepton::utils; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyCollisionsWithSWT = soa::Join; -using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; - -using MyV0Photons = soa::Filtered>; -using MyV0Photon = MyV0Photons::iterator; - -using MyPrimaryElectrons = soa::Filtered>; -using MyPrimaryElectron = MyPrimaryElectrons::iterator; - -template -struct DiphotonHadronMPC { - - 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 cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - Configurable maxY{"maxY", 0.8, "maximum rapidity for diphoton"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable ndepth_photon{"ndepth_photon", 100, "depth for event mixing between photon-photon"}; - Configurable ndepth_hadron{"ndepth_hadron", 2, "depth for event mixing between hadron-hadron"}; - Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "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, 0.1, 1, 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 ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - - ConfigurableAxis ConfMggBins{"ConfMggBins", {200, 0.0, 0.8}, "mgg bins for output histograms"}; - ConfigurableAxis ConfPtggBins{"ConfPtggBins", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 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.00}, "pTgg bins for output histograms"}; - - ConfigurableAxis ConfPtHadronBins{"ConfPtHadronBins", {VARIABLE_WIDTH, 0.00, 0.15, 0.2, 0.3, 0.4, 0.50, 1.00, 2.00, 3.00, 4.00, 5.00}, "pT,h bins for output histograms"}; - ConfigurableAxis ConfDEtaBins{"ConfDEtaBins", {120, -6, 6}, "deta bins for output histograms"}; - Configurable cfgNbinsDPhi{"cfgNbinsDPhi", 36, "nbins in dphi for output histograms"}; - // Configurable cfgNbinsCosNDPhi{"cfgNbinsCosNDPhi", 100, "nbins in cos(n(dphi)) for output histograms"}; - // Configurable cfgNmod{"cfgNmod", 2, "n-th harmonics"}; - - EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - 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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - // for RCT - Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadronPID] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; - Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; - Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; - } 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_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT 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"}; - 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_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to V0"}; - - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.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"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; - } pcmcuts; - - 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", 0.04, "max mass"}; - Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; - 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_max_eta_track{"cfg_max_eta_track", 2.0, "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", 36.0, "max chi2/NclsITS"}; - Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.1, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.1, "max dca Z for single track in cm"}; - Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1e+10, "max DCA 3D in sigma"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 0.7, "max fraction of shared clusters in TPC"}; - Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to electron"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; - 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_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_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"}; - } dileptoncuts; - - EMTrackCut fEMTrackCut; - struct : ConfigurableGroup { - std::string prefix = "trackcut_group"; - Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.2, "min pT for ref. track"}; - Configurable cfg_max_pt_track{"cfg_max_pt_track", 3.0, "max pT for ref. track"}; - Configurable cfg_min_eta_track{"cfg_min_eta_track", -0.8, "min eta for ref. track"}; - Configurable cfg_max_eta_track{"cfg_max_eta_track", +0.8, "max eta for ref. track"}; - // Configurable cfg_min_phi_track{"cfg_min_phi_track", 0.0, "min phi for ref. track"}; - // Configurable cfg_max_phi_track{"cfg_max_phi_track", 6.3, "max phi for ref. track"}; - // Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.5, "max dca XY for single track in cm"}; - // Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.5, "max dca Z for single track in cm"}; - Configurable cfg_track_bits{"cfg_track_bits", 645, "required track bits"}; // default:645, loose:0, tight:778 - } trackcuts; - - o2::aod::rctsel::RCTFlagsChecker rctChecker; - 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::vector zvtx_bin_edges; - std::vector cent_bin_edges; - std::vector occ_bin_edges; - - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; - int mRunNumber; - float d_bz; - - void init(InitContext&) - { - 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()); - - LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); - occ_bin_edges = std::vector(ConfOccupancyBins.value.begin(), ConfOccupancyBins.value.end()); - occ_bin_edges.erase(occ_bin_edges.begin()); - - emh1 = new MyEMH(ndepth_photon); - emh2 = new MyEMH(ndepth_photon); - emh_diphoton = new MyEMH_track(ndepth_photon); - emh_ref = new MyEMH_track(ndepth_hadron); - - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); - addHistograms(); - - DefineEMEventCut(); - DefineEMTrackCut(); - DefinePCMCut(); - DefineDileptonCut(); - - fRegistry.add("Diphoton/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); - if (doprocessTriggerAnalysis) { - fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); - } - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - rctChecker.init(eventcuts.cfgRCTLabel.value, eventcuts.cfgCheckZDC.value, eventcuts.cfgTreatLimitedAcceptanceAsBad.value); - } - - 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 (std::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()); - } - } - - ~DiphotonHadronMPC() - { - delete emh1; - emh1 = 0x0; - delete emh2; - emh2 = 0x0; - delete emh_diphoton; - emh_diphoton = 0x0; - delete emh_ref; - emh_ref = 0x0; - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - used_dileptonIds_per_col.clear(); - used_dileptonIds_per_col.shrink_to_fit(); - used_diphotonIds_per_col.clear(); - used_diphotonIds_per_col.shrink_to_fit(); - - map_mixed_eventId_to_globalBC.clear(); - } - - void addHistograms() - { - std::string mass_axis_title = "m_{#gamma#gamma} (GeV/c^{2})"; - std::string pair_pt_axis_title = "p_{T,#gamma#gamma} (GeV/c)"; - std::string deta_axis_title = "#Delta#eta = #eta_{#gamma#gamma} - #eta_{h}"; - std::string dphi_axis_title = "#Delta#varphi = #varphi_{#gamma#gamma} - #varphi_{h} (rad.)"; - // std::string cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{#gamma#gamma}} - #varphi_{{h}}))", cfgNmod.value); - - if constexpr (pairtype == PairType::kPCMDalitzEE) { - mass_axis_title = "m_{ee#gamma} (GeV/c^{2})"; - pair_pt_axis_title = "p_{T,ee#gamma} (GeV/c)"; - deta_axis_title = "#Delta#eta = #eta_{ee#gamma} - #eta_{h}"; - dphi_axis_title = "#Delta#varphi = #varphi_{ee#gamma} - #varphi_{h} (rad.)"; - // cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{ee#gamma}} - #varphi_{{h}}))", cfgNmod.value); - } - - // diphoton info - const AxisSpec axis_mass{ConfMggBins, mass_axis_title}; - const AxisSpec axis_pt{ConfPtggBins, pair_pt_axis_title}; - - // diphoton-hadron info - const AxisSpec axis_deta{ConfDEtaBins, deta_axis_title}; - const AxisSpec axis_dphi{cfgNbinsDPhi, -o2::constants::math::PIHalf, +3 * o2::constants::math::PIHalf, dphi_axis_title}; - - const AxisSpec axis_pt_hadron{ConfPtHadronBins, "p_{T,h} (GeV/c)"}; - const AxisSpec axis_eta_hadron{40, -2, +2, "#eta_{h}"}; - const AxisSpec axis_phi_hadron{36, 0, o2::constants::math::TwoPI, "#varphi_{h} (rad.)"}; - - fRegistry.add("Hadron/hs", "hadron", kTHnSparseD, {axis_pt_hadron, axis_eta_hadron, axis_phi_hadron}, false); - fRegistry.add("Hadron/hTrackBit", "track bit", kTH1D, {{65536, -0.5, 65535.5}}, false); - - fRegistry.add("Diphoton/same/hs", "diphoton", kTHnSparseD, {axis_mass, axis_pt}, true); - fRegistry.addClone("Diphoton/same/", "Diphoton/mix/"); - - fRegistry.add("DiphotonHadron/same/hs", "diphoton-hadron 2PC", kTHnSparseD, {axis_mass, axis_pt, axis_deta, axis_dphi}, true); - fRegistry.addClone("DiphotonHadron/same/", "DiphotonHadron/mix/"); - - // hadron-hadron - const AxisSpec axis_deta_hh{60, -3, +3, "#Delta#eta = #eta_{h}^{ref1} - #eta_{h}^{ref2}"}; - const AxisSpec axis_dphi_hh{90, -o2::constants::math::PIHalf, +3 * o2::constants::math::PIHalf, "#Delta#varphi = #varphi_{h}^{ref1} - #varphi_{h}^{ref2} (rad.)"}; - // const AxisSpec axis_cosndphi_hh{cfgNbinsCosNDPhi, -1, +1, std::format("cos({0:d}(#varphi_{{h}}^{{ref1}} - #varphi_{{h}}^{{ref2}}))", cfgNmod.value)}; - fRegistry.add("HadronHadron/same/hDEtaDPhi", "hadron-hadron 2PC", kTH2D, {axis_dphi_hh, axis_deta_hh}, true); - fRegistry.addClone("HadronHadron/same/", "HadronHadron/mix/"); - } - - void DefineEMEventCut() - { - fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - } - - void DefinePCMCut() - { - fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); - - // for v0 - fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, pcmcuts.cfg_max_pt_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.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); - 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.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); - fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); - 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.SetNClustersITS(0, 7); - fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); - } - - 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.ApplyPhiV(dileptoncuts.cfg_apply_phiv); - 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.SetMaxFracSharedClustersTPC(dileptoncuts.cfg_max_frac_shared_clusters_tpc); - 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.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); - fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); - fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfg_max_dca3dsigma_track); // in sigma - fDileptonCut.IncludeITSsa(false, 0.15); - - // for eID - fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); - fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfg_min_TPCNsigmaEl, dileptoncuts.cfg_max_TPCNsigmaEl); - fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfg_min_TPCNsigmaPi, dileptoncuts.cfg_max_TPCNsigmaPi); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfg_min_TOFNsigmaEl, dileptoncuts.cfg_max_TOFNsigmaEl); - } - - void DefineEMTrackCut() - { - fEMTrackCut = EMTrackCut("fEMTrackCut", "fEMTrackCut"); - fEMTrackCut.SetTrackPtRange(trackcuts.cfg_min_pt_track, trackcuts.cfg_max_pt_track); - fEMTrackCut.SetTrackEtaRange(trackcuts.cfg_min_eta_track, trackcuts.cfg_max_eta_track); - // fEMTrackCut.SetTrackPhiRange(trackcuts.cfg_min_phi_track, trackcuts.cfg_max_phi_track); - // fEMTrackCut.SetTrackMaxDcaXY(trackcuts.cfg_max_dcaxy); - // fEMTrackCut.SetTrackMaxDcaZ(trackcuts.cfg_max_dcaz); - fEMTrackCut.SetTrackBit(trackcuts.cfg_track_bits); - } - - SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - 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); - - using RefTracks = soa::Join; - using RefTrack = RefTracks::iterator; - Preslice perCollision_track = aod::emprimarytrack::emeventId; - Filter refTrackFilter = trackcuts.cfg_min_pt_track < 1 / nabs(o2::aod::emprimarytrack::signed1Pt) && 1 / nabs(o2::aod::emprimarytrack::signed1Pt) < trackcuts.cfg_max_pt_track && trackcuts.cfg_min_eta_track < o2::aod::emprimarytrack::eta && o2::aod::emprimarytrack::eta < trackcuts.cfg_max_eta_track; - using FilteredRefTracks = soa::Filtered; - using FilteredRefTrack = FilteredRefTracks::iterator; - - using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; - MyEMH* emh1 = nullptr; - MyEMH* emh2 = nullptr; - using MyEMH_track = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; // for charged track - MyEMH_track* emh_diphoton = nullptr; - MyEMH_track* emh_ref = nullptr; - - std::vector used_photonIds_per_col; // - std::vector> used_dileptonIds_per_col; // - std::vector> used_diphotonIds_per_col; // - std::map, uint64_t> map_mixed_eventId_to_globalBC; - - template - void run2PC(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, - TRefTracks const& refTracks) - { - for (const auto& collision : collisions) { - initCCDB(collision); - int ndiphoton = 0; - - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - 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::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, 1.f); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, 1.f); // accepted - - 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 = 0; - - int occbin = -1; - if (cfgOccupancyEstimator == 0) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else if (cfgOccupancyEstimator == 1) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - 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); - - auto refTracks_per_collision = refTracks.sliceBy(perCollision_track, collision.globalIndex()); - - 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 == PairType::kPCMPCM) { // same kinds pairing - auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto photons2_per_collision = photons2.sliceBy(perCollision2, collision.globalIndex()); - - for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_per_collision, photons2_per_collision))) { - if (!cut1.template IsSelected(g1) || !cut2.template IsSelected(g2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/same/hs"), v12.M(), v12.Pt()); - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - - int npair = 0; // the number of diphoton-h pairs - for (const auto& track : refTracks_per_collision) { - if (pos1.trackId() == track.trackId() || ele1.trackId() == track.trackId()) { - continue; - } - if (pos2.trackId() == track.trackId() || ele2.trackId() == track.trackId()) { - continue; - } - - if (fEMTrackCut.IsSelected(track)) { - ROOT::Math::PtEtaPhiMVector v3(track.pt(), track.eta(), track.phi(), 0.139); - float deta = v12.Eta() - v3.Eta(); - float dphi = v12.Phi() - v3.Phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/same/hs"), v12.M(), v12.Pt(), deta, dphi); - npair++; - } - } // end of ref track loop - - if (npair > 0) { - std::tuple tuple_tmp_diphoton = std::make_tuple(g1.globalIndex(), g2.globalIndex(), -1); - if (std::find(used_diphotonIds_per_col.begin(), used_diphotonIds_per_col.end(), tuple_tmp_diphoton) == used_diphotonIds_per_col.end()) { - emh_diphoton->AddTrackToEventPool(key_df_collision, EMTrack(v12.Pt(), v12.Eta(), v12.Phi(), v12.M())); - used_diphotonIds_per_col.emplace_back(tuple_tmp_diphoton); - } - } - - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); - used_photonIds_per_col.emplace_back(g1.globalIndex()); - } - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g2.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g2.pt(), g2.eta(), g2.phi(), 0)); - used_photonIds_per_col.emplace_back(g2.globalIndex()); - } - ndiphoton++; - } // end of pairing loop - } else if constexpr (pairtype == PairType::kPCMDalitzEE) { - 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 (const 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 v_gamma(g1.pt(), g1.eta(), g1.phi(), 0.); - - for (const auto& [pos2, ele2] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { - - if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. - continue; - } - if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { - continue; - } - - if (!cut2.template IsSelectedTrack(pos2, collision) || !cut2.template IsSelectedTrack(ele2, collision)) { - continue; - } - - if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v_pos(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v_ele(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v_ee = v_pos + v_ele; - ROOT::Math::PtEtaPhiMVector veeg = v_gamma + v_pos + v_ele; - if (std::fabs(veeg.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/same/hs"), veeg.M(), veeg.Pt()); - - int npair = 0; // the number of diphoton-h pairs - for (const auto& track : refTracks_per_collision) { - if (pos1.trackId() == track.trackId() || ele1.trackId() == track.trackId()) { - continue; - } - if (pos2.trackId() == track.trackId() || ele2.trackId() == track.trackId()) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v3(track.pt(), track.eta(), track.phi(), 0.139); - float deta = veeg.Eta() - v3.Eta(); - float dphi = veeg.Phi() - v3.Phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/same/hs"), veeg.M(), veeg.Pt(), deta, dphi); - npair++; - - } // end of ref track loop - - if (npair > 0) { - std::tuple tuple_tmp_diphoton = std::make_tuple(g1.globalIndex(), pos2.trackId(), ele2.trackId()); - if (std::find(used_diphotonIds_per_col.begin(), used_diphotonIds_per_col.end(), tuple_tmp_diphoton) == used_diphotonIds_per_col.end()) { - emh_diphoton->AddTrackToEventPool(key_df_collision, EMTrack(veeg.Pt(), veeg.Eta(), veeg.Phi(), veeg.M())); - used_diphotonIds_per_col.emplace_back(tuple_tmp_diphoton); - } - } - - std::pair tuple_tmp_id2 = std::make_pair(pos2.trackId(), ele2.trackId()); - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); - used_photonIds_per_col.emplace_back(g1.globalIndex()); - } - if (std::find(used_dileptonIds_per_col.begin(), used_dileptonIds_per_col.end(), tuple_tmp_id2) == used_dileptonIds_per_col.end()) { - emh2->AddTrackToEventPool(key_df_collision, EMTrack(v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); - used_dileptonIds_per_col.emplace_back(tuple_tmp_id2); - } - ndiphoton++; - } // end of dielectron loop - } // end of g1 loop - } // end of pairing in same event - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - used_dileptonIds_per_col.clear(); - used_dileptonIds_per_col.shrink_to_fit(); - used_diphotonIds_per_col.clear(); - used_diphotonIds_per_col.shrink_to_fit(); - - if (ndiphoton > 0) { - emh_ref->ReserveNTracksPerCollision(key_df_collision, refTracks_per_collision.size()); - for (const auto& track : refTracks_per_collision) { - if (fEMTrackCut.IsSelected(track)) { - fRegistry.fill(HIST("Hadron/hs"), track.pt(), track.eta(), track.phi()); - fRegistry.fill(HIST("Hadron/hTrackBit"), track.trackBit()); - emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(track.pt(), track.eta(), track.phi(), 0.139)); - } - } - - for (const auto& [ref1, ref2] : combinations(CombinationsStrictlyUpperIndexPolicy(refTracks_per_collision, refTracks_per_collision))) { - if (fEMTrackCut.IsSelected(ref1) && fEMTrackCut.IsSelected(ref2)) { - float deta = ref1.eta() - ref2.eta(); - float dphi = ref1.phi() - ref2.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("HadronHadron/same/hDEtaDPhi"), dphi, deta); - } - } - } - - // 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 selected_refTracks_in_this_event = emh_ref->GetTracksPerCollision(key_df_collision); - auto selected_diphotons_in_this_event = emh_diphoton->GetTracksPerCollision(key_df_collision); - - auto collisionIds1_in_mixing_pool = emh1->GetCollisionIdsFromEventPool(key_bin); - auto collisionIds2_in_mixing_pool = emh2->GetCollisionIdsFromEventPool(key_bin); - auto collisionIdsRef_in_mixing_pool = emh_ref->GetCollisionIdsFromEventPool(key_bin); - auto collisionIdsDiphoton_in_mixing_pool = emh_diphoton->GetCollisionIdsFromEventPool(key_bin); - - if constexpr (pairtype == PairType::kPCMPCM) { // same kinds pairing - for (const 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("Diphoton/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 (const auto& g1 : selected_photons1_in_this_event) { - for (const 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.); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/mix/hs"), v12.M(), v12.Pt(), 1.f); - } - } - } // end of loop over mixed event pool between photon-photon - - for (const auto& mix_dfId_collisionId : collisionIdsRef_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); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); - for (const auto& trg : selected_diphotons_in_this_event) { - for (const auto& ref : refTracks_from_event_pool) { - float deta = trg.eta() - ref.eta(); - float dphi = trg.phi() - ref.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/mix/hs"), trg.mass(), trg.pt(), deta, dphi); - } - } - } // end of loop over mixed event pool between diphoton-hadron - - } else { // [photon1 from event1, photon2 from event2] and [photon1 from event2, photon2 from event1] - for (const auto& mix_dfId_collisionId : collisionIds2_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("Diphoton/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 (const auto& g1 : selected_photons1_in_this_event) { - for (const auto& g2 : photons2_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.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { //[photon from event1, dilepton from event2] and [photon from event2, dilepton from event1] - v2.SetM(g2.mass()); - } - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/mix/hs"), v12.M(), v12.Pt(), 1.f); - } - } - } // end of loop over mixed event pool between photon-photon - - for (const 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("Diphoton/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 (const auto& g1 : selected_photons2_in_this_event) { - for (const 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.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { //[photon from event1, dilepton from event2] and [photon from event2, dilepton from event1] - v1.SetM(g1.mass()); - } - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (std::fabs(v12.Rapidity()) > maxY) { - continue; - } - fRegistry.fill(HIST("Diphoton/mix/hs"), v12.M(), v12.Pt(), 1.f); - } - } - } // end of loop over mixed event pool between photon-photon - - for (const auto& mix_dfId_collisionId : collisionIdsRef_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); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); - for (const auto& trg : selected_diphotons_in_this_event) { - for (const auto& ref : refTracks_from_event_pool) { - float deta = trg.eta() - ref.eta(); - float dphi = trg.phi() - ref.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("DiphotonHadron/mix/hs"), trg.mass(), trg.pt(), deta, dphi); - } - } - } // end of loop over mixed event pool between diphoton-hadron - } - - // hadron-hadron mixed event - for (const auto& mix_dfId_collisionId : collisionIdsRef_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); - if (diffBC < ndiff_bc_mix) { - continue; - } - - auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); - for (const auto& ref1 : selected_refTracks_in_this_event) { - for (const auto& ref2 : refTracks_from_event_pool) { - float deta = ref1.eta() - ref2.eta(); - float dphi = ref1.phi() - ref2.phi(); - // o2::math_utils::bringTo02Pi(dphi); - dphi = RecoDecay::constrainAngle(dphi, -o2::constants::math::PIHalf, 1U); - fRegistry.fill(HIST("HadronHadron/mix/hDEtaDPhi"), dphi, deta); - } - } - } // end of loop over mixed event pool between hadron-hadron - - if (ndiphoton > 0) { - emh1->AddCollisionIdAtLast(key_bin, key_df_collision); - emh2->AddCollisionIdAtLast(key_bin, key_df_collision); - emh_diphoton->AddCollisionIdAtLast(key_bin, key_df_collision); - emh_ref->AddCollisionIdAtLast(key_bin, key_df_collision); - map_mixed_eventId_to_globalBC[key_df_collision] = collision.globalBC(); - } - - } // end of collision loop - } - - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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; - - Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); - Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); - - int ndf = 0; - void processAnalysis(FilteredMyCollisions const& collisions, FilteredRefTracks const& refTracks, Types const&... args) - { - // LOGF(info, "ndf = %d", ndf); - if constexpr (pairtype == PairType::kPCMPCM) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - run2PC(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, refTracks); - } 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()); - run2PC(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, refTracks); - } - ndf++; - } - PROCESS_SWITCH(DiphotonHadronMPC, processAnalysis, "process pair analysis", true); - - // using FilteredMyCollisionsWithSWT = soa::Filtered; - void processTriggerAnalysis(MyCollisionsWithSWT const& collisions, FilteredRefTracks const& refTracks, Types const&... args) - { - // LOGF(info, "ndf = %d", ndf); - if constexpr (pairtype == PairType::kPCMPCM) { - auto v0photons = std::get<0>(std::tie(args...)); - auto v0legs = std::get<1>(std::tie(args...)); - run2PC(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, refTracks); - } 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()); - run2PC(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, refTracks); - } - ndf++; - } - PROCESS_SWITCH(DiphotonHadronMPC, processTriggerAnalysis, "process pair analysis with software trigger", false); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(DiphotonHadronMPC, processDummy, "Dummy function", false); -}; -#endif // PWGEM_PHOTONMESON_CORE_DIPHOTONHADRONMPC_H_ diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.cxx b/PWGEM/PhotonMeson/Core/EMCPhotonCut.cxx index 1ccca2a2be7..3d911df19e3 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.cxx @@ -82,6 +82,12 @@ void EMCPhotonCut::SetUseSecondaryTM(bool flag) LOG(info) << "EM Photon Cluster Cut, using secondary TM cut is set to : " << mUseTM; } +void EMCPhotonCut::SetDoQA(bool flag) +{ + mDoQA = flag; + LOG(info) << "EM Photon Cluster Cut, QA is set to: " << mUseTM; +} + void EMCPhotonCut::print() const { LOG(info) << "EMCal Photon Cut:"; diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h index 3105ece21cd..3c262fcb540 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h @@ -19,18 +19,49 @@ #include "PWGEM/PhotonMeson/Core/EMBitFlags.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include #include +#include +#include +#include #include +#include + #include #include #include #include +#include #include +#include #include +template +concept is_optional_table = o2::soa::is_table || std::is_same_v; + +template +static constexpr bool HasPrimaries = !std::is_same_v; + +template +static constexpr bool HasSecondaries = !std::is_same_v; + +template +concept IsNonLinIterator = o2::soa::is_iterator && requires(T t) { + // Check that the *elements* of the container have the required methods: + { t.corrE() } -> std::same_as; + { t.corrPt() } -> std::same_as; +}; + +template +concept IsNonLinContainer = o2::soa::is_table && requires(T t) { + // Check that the *elements* of the container have the required methods: + { t.begin().corrE() } -> std::same_as; + { t.begin().corrPt() } -> std::same_as; +}; + template concept IsTrackIterator = o2::soa::is_iterator && requires(T t) { // Check that the *elements* of the container have the required methods: @@ -50,22 +81,26 @@ concept IsTrackContainer = o2::soa::is_table && requires(T t) { }; template -concept HasTrackMatching = requires(Cluster cluster) { - // requires that the following are valid calls: - { cluster.deltaEta() } -> std::convertible_to>; - { cluster.deltaPhi() } -> std::convertible_to>; - { cluster.trackpt() } -> std::convertible_to>; - { cluster.trackp() } -> std::convertible_to>; -}; +concept HasTrackMatching = + o2::soa::is_iterator && + requires(Cluster cluster) { + // requires that the following are valid calls: + { cluster.deltaEta() } -> std::convertible_to>; + { cluster.deltaPhi() } -> std::convertible_to>; + { cluster.trackpt() } -> std::convertible_to>; + { cluster.trackp() } -> std::convertible_to>; + }; template -concept HasSecondaryMatching = requires(Cluster cluster) { - // requires that the following are valid calls: - { cluster.deltaEtaSec() } -> std::convertible_to>; - { cluster.deltaPhiSec() } -> std::convertible_to>; - { cluster.trackptSec() } -> std::convertible_to>; - { cluster.trackpSec() } -> std::convertible_to>; -}; +concept HasSecondaryMatching = + o2::soa::is_iterator && + requires(Cluster cluster) { + // requires that the following are valid calls: + { cluster.deltaEtaSec() } -> std::convertible_to>; + { cluster.deltaPhiSec() } -> std::convertible_to>; + { cluster.trackptSec() } -> std::convertible_to>; + { cluster.trackpSec() } -> std::convertible_to>; + }; struct TrackMatchingParams { float a{0.01f}; @@ -79,7 +114,7 @@ class EMCPhotonCut : public TNamed EMCPhotonCut() = default; EMCPhotonCut(const char* name, const char* title) : TNamed(name, title) {} - enum class EMCPhotonCuts : int { + enum class EMCPhotonCuts : std::uint8_t { // cluster cut kDefinition = 0, kEnergy, @@ -92,9 +127,15 @@ class EMCPhotonCut : public TNamed kNCuts }; + enum class TrackType : std::uint8_t { + // cluster cut + kPrimary = 0, + kSecondary, + }; + static const char* mCutNames[static_cast(EMCPhotonCuts::kNCuts)]; - constexpr auto getClusterId(o2::soa::is_iterator auto const& t) const + static constexpr auto getClusterId(o2::soa::is_iterator auto const& t) { if constexpr (requires { t.emEmcClusterId(); }) { return t.emEmcClusterId(); @@ -105,6 +146,54 @@ class EMCPhotonCut : public TNamed } } + /// \brief add histograms to registry + /// \param fRegistry pointer to histogram registry + void addQAHistograms(o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + if (mDoQA && fRegistry != nullptr) { + const o2::framework::AxisSpec thAxisClusterEnergy{500, 0, 50, "#it{E}_{cls} (GeV)"}; + const o2::framework::AxisSpec thAxisMomentum{250, 0., 25., "#it{p}_{T} (GeV/#it{c})"}; + const o2::framework::AxisSpec thAxisDEta{200, -0.1, 0.1, "#Delta#eta"}; + const o2::framework::AxisSpec thAxisDPhi{200, -0.1, 0.1, "#Delta#varphi (rad)"}; + const o2::framework::AxisSpec thAxisEnergy{500, 0., 50., "#it{E} (GeV)"}; + const o2::framework::AxisSpec thAxisEta{320, -0.8, 0.8, "#eta"}; + const o2::framework::AxisSpec thAxisPhi{500, 0, o2::constants::math::TwoPI, "#varphi (rad)"}; + const o2::framework::AxisSpec thAxisNCell{51, -0.5, 50.5, "#it{N}_{cell}"}; + const o2::framework::AxisSpec thAxisM02{200, 0, 2.0, "#it{M}_{02}"}; + const o2::framework::AxisSpec thAxisTime{300, -150, +150, "#it{t}_{cls} (ns)"}; + const o2::framework::AxisSpec thAxisEoverP{400, 0, 10., "#it{E}_{cls}/#it{p}_{track} (#it{c})"}; + + fRegistry->add("QA/Cluster/before/hE", "E_{cluster};#it{E}_{cluster} (GeV);#it{N}_{cluster}", o2::framework::kTH1D, {thAxisClusterEnergy}, true); + fRegistry->add("QA/Cluster/before/hPt", "Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{cluster}", o2::framework::kTH1D, {thAxisClusterEnergy}, true); + fRegistry->add("QA/Cluster/before/hNgamma", "Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}", o2::framework::kTH1D, {{1001, -0.5f, 1000.5f}}, true); + fRegistry->add("QA/Cluster/before/hEtaPhi", "#eta vs #varphi;#eta;#varphi (rad.)", o2::framework::kTH2F, {thAxisEta, thAxisPhi}, true); + fRegistry->add("QA/Cluster/before/hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisNCell, thAxisClusterEnergy}, true); + fRegistry->add("QA/Cluster/before/hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisM02, thAxisClusterEnergy}, true); + fRegistry->add("QA/Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisTime, thAxisClusterEnergy}, true); + + fRegistry->addClone("QA/Cluster/before/", "QA/Cluster/after/"); + + auto hClusterQualityCuts = fRegistry->add("QA/Cluster/hClusterQualityCuts", "Energy at which clusters are removed by a given cut;;#it{E} (GeV)", o2::framework::kTH2F, {{static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts) + 2, -0.5, static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts) + 1.5}, thAxisClusterEnergy}, true); + hClusterQualityCuts->GetXaxis()->SetBinLabel(1, "In"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(2, "Definition"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(3, "Energy"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(4, "NCell"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(5, "M02"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(6, "Timing"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(7, "TM"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(8, "Sec. TM"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(9, "Exotic"); + hClusterQualityCuts->GetXaxis()->SetBinLabel(10, "Out"); + + fRegistry->add("QA/Cluster/hTrackdEtadPhi", "d#eta vs. d#varphi of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisDPhi}, true); + fRegistry->add("QA/Cluster/hTrackdEtaPt", "d#eta vs. track pT of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisMomentum}, true); + fRegistry->add("QA/Cluster/hTrackdPhiPt", "d#varphi vs. track pT of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDPhi, thAxisMomentum}, true); + fRegistry->add("QA/Cluster/hSecTrackdEtadPhi", "d#eta vs. d#varphi of matched secondary tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisDPhi}, true); + fRegistry->add("QA/Cluster/hSecTrackdEtaPt", "d#eta vs. track pT of matched secondary tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisMomentum}, true); + fRegistry->add("QA/Cluster/hSecTrackdPhiPt", "d#varphi vs. track pT of matched secondary tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDPhi, thAxisMomentum}, true); + } + } + /// \brief performs check if track is matched with given cluster /// \param cluster cluster to be checked /// \param emcmatchedtrack matched track iterator @@ -112,8 +201,7 @@ class EMCPhotonCut : public TNamed /// \param GetEtaCut lambda to get the eta cut value /// \param GetPhiCut lambda to get the phi cut value /// \param applyEoverP bool to check if E/p should be checked (for secondaries we do not check this!) - bool checkTrackMatching(o2::soa::is_iterator auto const& cluster, IsTrackIterator auto& emcmatchedtrack, o2::soa::RowViewSentinel const emcmatchedtrackEnd, - bool applyEoverP, auto GetEtaCut, auto GetPhiCut) const + bool checkTrackMatching(o2::soa::is_iterator auto const& cluster, IsTrackIterator auto& emcmatchedtrack, o2::soa::RowViewSentinel const emcmatchedtrackEnd, bool applyEoverP, auto GetEtaCut, auto GetPhiCut, o2::framework::HistogramRegistry* fRegistry = nullptr, TrackType trackType = TrackType::kPrimary) const { // advance to cluster while (emcmatchedtrack != emcmatchedtrackEnd && getClusterId(emcmatchedtrack) < cluster.globalIndex()) { @@ -129,14 +217,32 @@ class EMCPhotonCut : public TNamed } // iterate over tracks belonging to this cluster while (emcmatchedtrack != emcmatchedtrackEnd && getClusterId(emcmatchedtrack) == cluster.globalIndex()) { - auto dEta = std::fabs(emcmatchedtrack.deltaEta()); - auto dPhi = std::fabs(emcmatchedtrack.deltaPhi()); - auto trackpt = emcmatchedtrack.trackPt(); - auto trackp = emcmatchedtrack.trackP(); - bool fail = (dEta > GetEtaCut(trackpt)) || - (dPhi > GetPhiCut(trackpt)) || + const auto dEta = emcmatchedtrack.deltaEta(); + const auto dPhi = emcmatchedtrack.deltaPhi(); + const auto fdEta = std::fabs(emcmatchedtrack.deltaEta()); + const auto fdPhi = std::fabs(emcmatchedtrack.deltaPhi()); + const auto trackpt = emcmatchedtrack.trackPt(); + const auto trackp = emcmatchedtrack.trackP(); + bool fail = (fdEta > GetEtaCut(trackpt)) || + (fdPhi > GetPhiCut(trackpt)) || (applyEoverP && cluster.e() / trackp >= mMinEoverP); if (!fail) { + if (mDoQA && fRegistry != nullptr) { + switch (trackType) { + case TrackType::kPrimary: + fRegistry->fill(HIST("QA/Cluster/hTrackdEtadPhi"), dEta, dPhi); + fRegistry->fill(HIST("QA/Cluster/hTrackdEtaPt"), dEta, trackpt); + fRegistry->fill(HIST("QA/Cluster/hTrackdPhiPt"), dPhi, trackpt); + break; + case TrackType::kSecondary: + fRegistry->fill(HIST("QA/Cluster/hSecTrackdEtadPhi"), dEta, dPhi); + fRegistry->fill(HIST("QA/Cluster/hSecTrackdEtaPt"), dEta, trackpt); + fRegistry->fill(HIST("QA/Cluster/hSecTrackdPhiPt"), dPhi, trackpt); + break; + default: + break; + } + } return false; // cluster got a track matche to it } ++emcmatchedtrack; @@ -144,24 +250,79 @@ class EMCPhotonCut : public TNamed return true; // all tracks checked, cluster survives } + void fillBeforeClusterHistogram(o2::soa::is_iterator auto const& cluster, o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + + if (mDoQA == false || fRegistry == nullptr) { + return; + } + + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), 0, cluster.e()); + fRegistry->fill(HIST("QA/Cluster/before/hE"), cluster.e()); + fRegistry->fill(HIST("QA/Cluster/before/hPt"), cluster.pt()); + fRegistry->fill(HIST("QA/Cluster/before/hEtaPhi"), cluster.eta(), cluster.phi()); + fRegistry->fill(HIST("QA/Cluster/before/hNCell"), cluster.nCells(), cluster.e()); + fRegistry->fill(HIST("QA/Cluster/before/hM02"), cluster.m02(), cluster.e()); + fRegistry->fill(HIST("QA/Cluster/before/hTime"), cluster.time(), cluster.e()); + } + + void fillAfterClusterHistogram(o2::soa::is_iterator auto const& cluster, o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + + if (mDoQA == false || fRegistry == nullptr) { + return; + } + + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts) + 1, cluster.e()); + fRegistry->fill(HIST("QA/Cluster/after/hE"), cluster.e()); + fRegistry->fill(HIST("QA/Cluster/after/hPt"), cluster.pt()); + fRegistry->fill(HIST("QA/Cluster/after/hEtaPhi"), cluster.eta(), cluster.phi()); + fRegistry->fill(HIST("QA/Cluster/after/hNCell"), cluster.nCells(), cluster.e()); + fRegistry->fill(HIST("QA/Cluster/after/hM02"), cluster.m02(), cluster.e()); + fRegistry->fill(HIST("QA/Cluster/after/hTime"), cluster.time(), cluster.e()); + } + /// \brief check if given clusters survives all cuts /// \param flags EMBitFlags where results will be stored /// \param cluster cluster table to check /// \param matchedTracks matched primary tracks table /// \param matchedSecondaries matched secondary tracks table - void AreSelectedRunning(EMBitFlags& flags, o2::soa::is_table auto const& clusters, IsTrackContainer auto const& emcmatchedtracks, IsTrackContainer auto const& secondaries) const + /// \param fRegistry o2::framework::HistogramRegistry pointer of the main task + void AreSelectedRunning(EMBitFlags& flags, o2::soa::is_table auto const& clusters, IsTrackContainer auto const& emcmatchedtracks, IsTrackContainer auto const& secondaries, o2::framework::HistogramRegistry* fRegistry = nullptr) const { + if (clusters.size() <= 0) { + return; + } auto emcmatchedtrackIter = emcmatchedtracks.begin(); auto emcmatchedtrackEnd = emcmatchedtracks.end(); auto secondaryIter = secondaries.begin(); auto secondaryEnd = secondaries.end(); size_t iCluster = 0; + + const bool doQA = mDoQA && fRegistry != nullptr; + + nTotClusterPerColl = 0; + currentCollID = clusters.iteratorAt(0).pmeventId(); for (const auto& cluster : clusters) { - if (!IsSelectedRunning(cluster, emcmatchedtrackIter, emcmatchedtrackEnd, secondaryIter, secondaryEnd)) { + const auto collID = cluster.pmeventId(); + if (doQA) { + fillBeforeClusterHistogram(cluster, fRegistry); + } + if (!IsSelectedRunning(cluster, emcmatchedtrackIter, emcmatchedtrackEnd, secondaryIter, secondaryEnd, fRegistry)) { flags.set(iCluster); + } else if (doQA) { + fillAfterClusterHistogram(cluster, fRegistry); + } + if (collID != currentCollID) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/before/hNgamma"), nTotClusterPerColl); + } + nTotClusterPerColl = 0; + currentCollID = collID; } + ++nTotClusterPerColl; ++iCluster; - } + } // end of cluster loop } /// \brief check if given cluster survives all cuts @@ -171,32 +332,65 @@ class EMCPhotonCut : public TNamed /// \param secondaryIter current iterator of matched secondary tracks /// \param secondaryEnd end iterator of matched secondary tracks /// \return true if cluster survives all cuts else false - bool IsSelectedRunning(o2::soa::is_iterator auto const& cluster, IsTrackIterator auto& emcmatchedtrackIter, o2::soa::RowViewSentinel const emcmatchedtrackEnd, IsTrackIterator auto& secondaryIter, o2::soa::RowViewSentinel const secondaryEnd) const + bool IsSelectedRunning(o2::soa::is_iterator auto const& cluster, IsTrackIterator auto& emcmatchedtrackIter, o2::soa::RowViewSentinel const emcmatchedtrackEnd, IsTrackIterator auto& secondaryIter, o2::soa::RowViewSentinel const secondaryEnd, o2::framework::HistogramRegistry* fRegistry = nullptr) const { + const bool doQA = mDoQA && fRegistry != nullptr; if (!IsSelectedEMCalRunning(EMCPhotonCuts::kDefinition, cluster)) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kDefinition) + 1, cluster.e()); + } return false; } if (!IsSelectedEMCalRunning(EMCPhotonCuts::kEnergy, cluster)) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kEnergy) + 1, cluster.e()); + } return false; } if (!IsSelectedEMCalRunning(EMCPhotonCuts::kNCell, cluster)) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kNCell) + 1, cluster.e()); + } return false; } if (!IsSelectedEMCalRunning(EMCPhotonCuts::kM02, cluster)) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kM02) + 1, cluster.e()); + } return false; } if (!IsSelectedEMCalRunning(EMCPhotonCuts::kTiming, cluster)) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kTiming) + 1, cluster.e()); + } return false; } - if (mUseTM && (!IsSelectedEMCalRunning(EMCPhotonCuts::kTM, cluster, emcmatchedtrackIter, emcmatchedtrackEnd))) { + if (mUseTM && (!IsSelectedEMCalRunning(EMCPhotonCuts::kTM, cluster, emcmatchedtrackIter, emcmatchedtrackEnd, fRegistry))) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kTM) + 1, cluster.e()); + } return false; } - if (mUseSecondaryTM && (!IsSelectedEMCalRunning(EMCPhotonCuts::kSecondaryTM, cluster, secondaryIter, secondaryEnd))) { + if (mUseSecondaryTM && (!IsSelectedEMCalRunning(EMCPhotonCuts::kSecondaryTM, cluster, secondaryIter, secondaryEnd, fRegistry))) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kSecondaryTM) + 1, cluster.e()); + } return false; } if (!IsSelectedEMCalRunning(EMCPhotonCuts::kExotic, cluster)) { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCuts::kExotic) + 1, cluster.e()); + } return false; } + if (currentCollID == cluster.pmeventId()) { + ++nAccClusterPerColl; + } else { + if (doQA) { + fRegistry->fill(HIST("QA/Cluster/after/hNgamma"), nAccClusterPerColl); + } + nAccClusterPerColl = 0; + } return true; } @@ -211,7 +405,11 @@ class EMCPhotonCut : public TNamed return cluster.definition() == mDefinition; case EMCPhotonCuts::kEnergy: - return cluster.e() > mMinE; + if constexpr (IsNonLinIterator>) { + return cluster.corrE() > mMinE; + } else { + return cluster.e() > mMinE; + } case EMCPhotonCuts::kNCell: return cluster.nCells() >= mMinNCell; @@ -242,14 +440,14 @@ class EMCPhotonCut : public TNamed /// \param matchedTrackIter current iterator of matched primary or secondary tracks /// \param matchedTrackEnd end iterator of matched primary or secondary tracks /// \return true if cluster survives cut else false - bool IsSelectedEMCalRunning(const EMCPhotonCuts& cut, o2::soa::is_iterator auto const& cluster, IsTrackIterator auto& matchedTrackIter, o2::soa::RowViewSentinel const matchedTrackEnd) const + bool IsSelectedEMCalRunning(const EMCPhotonCuts& cut, o2::soa::is_iterator auto const& cluster, IsTrackIterator auto& matchedTrackIter, o2::soa::RowViewSentinel const matchedTrackEnd, o2::framework::HistogramRegistry* fRegistry = nullptr) const { switch (cut) { case EMCPhotonCuts::kTM: - return checkTrackMatching(cluster, matchedTrackIter, matchedTrackEnd, true, [this](float pt) { return GetTrackMatchingEta(pt); }, [this](float pt) { return GetTrackMatchingPhi(pt); }); + return checkTrackMatching(cluster, matchedTrackIter, matchedTrackEnd, true, [this](float pt) { return GetTrackMatchingEta(pt); }, [this](float pt) { return GetTrackMatchingPhi(pt); }, fRegistry, TrackType::kPrimary); case EMCPhotonCuts::kSecondaryTM: - return checkTrackMatching(cluster, matchedTrackIter, matchedTrackEnd, false, [this](float pt) { return GetSecTrackMatchingEta(pt); }, [this](float pt) { return GetSecTrackMatchingPhi(pt); }); + return checkTrackMatching(cluster, matchedTrackIter, matchedTrackEnd, false, [this](float pt) { return GetSecTrackMatchingEta(pt); }, [this](float pt) { return GetSecTrackMatchingPhi(pt); }, fRegistry, TrackType::kSecondary); default: return true; @@ -305,7 +503,11 @@ class EMCPhotonCut : public TNamed return cluster.definition() == mDefinition; case EMCPhotonCuts::kEnergy: - return cluster.e() > mMinE; + if constexpr (IsNonLinIterator) { + return cluster.corrE() > mMinE; + } else { + return cluster.e() > mMinE; + } case EMCPhotonCuts::kNCell: return cluster.nCells() >= mMinNCell; @@ -323,7 +525,9 @@ class EMCPhotonCut : public TNamed auto dPhi = std::fabs(emcmatchedtrack.deltaPhi()); auto trackpt = emcmatchedtrack.trackPt(); auto trackp = emcmatchedtrack.trackP(); - bool result = (dEta > GetTrackMatchingEta(trackpt)) || (dPhi > GetTrackMatchingPhi(trackpt)) || (cluster.e() / trackp >= mMinEoverP); + bool result = (dEta > GetTrackMatchingEta(trackpt)) || + (dPhi > GetTrackMatchingPhi(trackpt)) || + (cluster.e() / trackp >= mMinEoverP); if (!result) { return false; } @@ -333,7 +537,7 @@ class EMCPhotonCut : public TNamed auto dPhis = cluster.deltaPhi(); // std:vector auto trackspt = cluster.trackpt(); // std:vector auto tracksp = cluster.trackp(); // std:vector - int ntrack = tracksp.size(); + int ntrack = trackspt.size(); for (int itr = 0; itr < ntrack; itr++) { float dEta = std::fabs(dEtas[itr]); float dPhi = std::fabs(dPhis[itr]); @@ -353,8 +557,8 @@ class EMCPhotonCut : public TNamed auto dEta = std::fabs(emcmatchedtrack.deltaEta()); auto dPhi = std::fabs(emcmatchedtrack.deltaPhi()); auto trackpt = emcmatchedtrack.trackPt(); - auto trackp = emcmatchedtrack.trackP(); - bool result = (dEta > GetSecTrackMatchingEta(trackpt)) || (dPhi > GetSecTrackMatchingPhi(trackpt)) || (cluster.e() / trackp >= mMinEoverP); + bool result = (dEta > GetSecTrackMatchingEta(trackpt)) || + (dPhi > GetSecTrackMatchingPhi(trackpt)); if (!result) { return false; } @@ -363,8 +567,7 @@ class EMCPhotonCut : public TNamed auto dEtas = cluster.deltaEtaSec(); // std:vector auto dPhis = cluster.deltaPhiSec(); // std:vector auto trackspt = cluster.trackptSec(); // std:vector - auto tracksp = cluster.trackpSec(); // std:vector - int ntrack = tracksp.size(); + int ntrack = trackspt.size(); for (int itr = 0; itr < ntrack; itr++) { float dEta = std::fabs(dEtas[itr]); float dPhi = std::fabs(dPhis[itr]); @@ -426,6 +629,10 @@ class EMCPhotonCut : public TNamed /// \param flag flag to use secondary track matching void SetUseSecondaryTM(bool flag = false); + /// \brief Set flag to do QA + /// \param flag flag to do QA + void SetDoQA(bool flag = false); + /// \brief Set parameters for track matching delta eta = a + (pT + b)^c /// \param a a in a + (pT + b)^c /// \param b b in a + (pT + b)^c @@ -504,8 +711,13 @@ class EMCPhotonCut : public TNamed float mMaxTime{25.f}; ///< maximum cluster timing float mMinEoverP{1.75f}; ///< minimum cluster energy over track momentum ratio needed for the pair to be considered matched bool mUseExoticCut{true}; ///< flag to decide if the exotic cluster cut is to be checked or not - bool mUseTM{true}; ///< flag to decide if track matching cut is to be checek or not - bool mUseSecondaryTM{false}; ///< flag to decide if seconary track matching cut is to be checek or not + bool mUseTM{true}; ///< flag to decide if track matching cut is to be check or not + bool mUseSecondaryTM{false}; ///< flag to decide if seconary track matching cut is to be check or not + bool mDoQA{false}; ///< flag to decide if QA should be done or not + + mutable uint nTotClusterPerColl{0}; ///< running number of all cluster per collision used for QA + mutable uint nAccClusterPerColl{0}; ///< running number of accepted cluster per collision used for QA + mutable int currentCollID{-1}; ///< running collision ID of clusters used for QA TrackMatchingParams mTrackMatchingEtaParams = {-1.f, 0.f, 0.f}; TrackMatchingParams mTrackMatchingPhiParams = {-1.f, 0.f, 0.f}; diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.cxx b/PWGEM/PhotonMeson/Core/EMNonLin.cxx new file mode 100644 index 00000000000..5c44ecc9f0c --- /dev/null +++ b/PWGEM/PhotonMeson/Core/EMNonLin.cxx @@ -0,0 +1,55 @@ +// 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 EMNonLin.cxx +/// \brief Source file of NonLin class for photons. +/// \author M. Hemmer, marvin.hemmer@cern.ch + +#include "EMNonLin.h" + +#include +#include + +using namespace o2::pwgem::nonlin; + +float EMNonLin::getCorrectionFactor(float var, const Context& ctx) +{ + if (!ctx.params || var == 0.f) [[unlikely]] { + return 1.f; + } + + int maxIter = std::min(ctx.nIter, MaxIter - 1); + float scale = 1.f; // cumulative scale + float refVal = var; // reference value updated each iteration + + for (int i = 0; i <= maxIter; ++i) { + if (refVal == 0.f) { + break; + } + const auto& p = ctx.params[i]; + + // evaluate pol1 for each parameter at this centrality + float a = p.a0 + p.a1 * ctx.cent; + float b = p.b0 + p.b1 * ctx.cent; + float c = p.c0 + p.c1 * ctx.cent; + + // guard against c <= 0 which would make pow(x, -c) diverge + if (c <= 0.f) { + continue; + } + + float iterScale = a + b * std::pow(refVal, -c); + scale *= iterScale; + refVal = var * scale; // next iteration uses scaled original input + } + + return scale; +} diff --git a/PWGEM/PhotonMeson/Core/EMNonLin.h b/PWGEM/PhotonMeson/Core/EMNonLin.h new file mode 100644 index 00000000000..b6fa2594310 --- /dev/null +++ b/PWGEM/PhotonMeson/Core/EMNonLin.h @@ -0,0 +1,150 @@ +// 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 EMNonLin.h +/// \brief Header file of NonLin class for photons. +/// \author M. Hemmer, marvin.hemmer@cern.ch + +#ifndef PWGEM_PHOTONMESON_CORE_EMNONLIN_H_ +#define PWGEM_PHOTONMESON_CORE_EMNONLIN_H_ + +#include // IWYU pragma: keep (do not replace with TMatrixDfwd.h) +#include + +#include +#include + +namespace o2::pwgem::nonlin +{ + +constexpr int MaxCent = 100.f; + +/// \class EMNonLin +/// \brief Class to obtain non linear correction factors for PbPb. +/// Parameters are loaded from CCDB (TMatrixD: rows = iterations, cols = 6 pol1 coefficients). +/// Falls back to hardcoded static table if CCDB object is not available. +/// The correction is of type a + b * refVal^(-c), where a, b and c are themselves described by linear functions over centrality. +class EMNonLin +{ + public: + static constexpr int MaxIter = 2; // hard cap on iterations + static constexpr int PhotonN = 3; + static constexpr int NCols = 6; // a0, a1, b0, b1, c0, c1 + + enum class PhotonType : uint8_t { + kEMC = 0, + kPCM = 1, + kPHOS = 2 + }; + + struct NonLinParams { + float a0{1.f}, a1{0.f}; // pol1 params for a: asymptote + float b0{0.f}, b1{0.f}; // pol1 params for b: magnitude + float c0{0.f}, c1{0.f}; // pol1 params for c: exponent + }; + + struct Context { + const NonLinParams* params = nullptr; + int nIter = 0; + float cent = 0.f; + + /// \brief Sets parameters for the NonLin. Used with EMNonLin::resolveParams() + /// \param newParams pointer to new NonLinParams + void setParams(const NonLinParams* newParams) + { + params = newParams; + } + + /// \brief Sets iteration used for the NonLin. + /// \param iter iteration + void setIter(int iter) + { + nIter = (iter < 0 || iter >= MaxIter) ? MaxIter - 1 : iter; + } + + /// \brief Sets current centrality. + /// \param centrality centrality + void setCent(float centrality) + { + cent = (centrality >= MaxCent) ? MaxCent : centrality; + } + }; + + /// \brief Load parameters from a TMatrixD fetched from CCDB. + /// Rows = iterations, cols = {a0, a1, b0, b1, c0, c1}. + /// Overwrites the static fallback for this photon type. + /// \param mat pointer to TMatrixD from CCDB (may be nullptr) + /// \param type photon type to fill + void getFromCCDBObject(const TMatrixD* mat, PhotonType type) + { + int iType = static_cast(type); + if (!mat || mat->GetNcols() != NCols) { + mCCDBLoaded[iType] = false; + return; + } + int nIter = std::min(mat->GetNrows(), MaxIter); + for (int i = 0; i < nIter; ++i) { + mCCDBParams[iType][i] = { + static_cast((*mat)(i, 0)), static_cast((*mat)(i, 1)), + static_cast((*mat)(i, 2)), static_cast((*mat)(i, 3)), + static_cast((*mat)(i, 4)), static_cast((*mat)(i, 5))}; + } + mCCDBLoaded[iType] = true; + } + + /// \brief Compute the multiplicative correction factor for energy/pT. + /// \param par energy or pT of the photon + /// \param ctx context holding centrality, iteration level, and params pointer + static float getCorrectionFactor(float var, const Context& ctx); + + /// \brief Return pointer to the params array for a given photon type. + /// \returns CCDB-loaded params if available, otherwise the static fallback. + const NonLinParams* resolveParams(PhotonType type) const + { + int iType = static_cast(type); + return mCCDBLoaded[iType] ? &mCCDBParams[iType][0] : &FallbackTable[iType][0]; + } + + private: + NonLinParams mCCDBParams[PhotonN][MaxIter] = {}; // Runtime params loaded from CCDB (per photon type, per iteration) + bool mCCDBLoaded[PhotonN] = {false, false, false}; + + // ------------------------------------------------------- + // Static fallback tables (used when CCDB object is absent) + // ------------------------------------------------------- + static constexpr NonLinParams FallbackTable[PhotonN][MaxIter] = { + // kEMC + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPCM + {{1.f, 0.f, 0.010417f, -1.09508e-05f, 0.355795f, 0.00427618f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPHOS + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + }; + + static constexpr NonLinParams FallbackTableMC[PhotonN][MaxIter] = { + // kEMC + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPCM + {{1.f, 0.f, 0.010417f, -1.09508e-05f, 0.355795f, 0.00427618f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + // kPHOS + {{1.f, 0.f, 0.f, 0.f, 0.f, 0.f}, + {1.f, 0.f, 0.f, 0.f, 0.f, 0.f}}, + }; +}; + +} // namespace o2::pwgem::nonlin + +#endif // PWGEM_PHOTONMESON_CORE_EMNONLIN_H_ diff --git a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx index 285bf50eba4..316b01d9563 100644 --- a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx +++ b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.cxx @@ -13,11 +13,116 @@ // Class for em photon event selection // -#include "Framework/Logger.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include + +#include + ClassImp(EMPhotonEventCut); +void EMPhotonEventCut::SetRequireSel8(bool flag) +{ + mRequireSel8 = flag; + LOG(info) << "EM Event Cut, require sel8: " << mRequireSel8; +} + +void EMPhotonEventCut::SetRequireFT0AND(bool flag) +{ + mRequireFT0AND = flag; + LOG(info) << "EM Event Cut, require FT0AND: " << mRequireFT0AND; +} + +void EMPhotonEventCut::SetZvtxRange(float min, float max) +{ + mMinZvtx = min; + mMaxZvtx = max; + LOG(info) << "EM Event Cut, set z vtx range: " << mMinZvtx << " - " << mMaxZvtx; +} + +void EMPhotonEventCut::SetRequireNoTFB(bool flag) +{ + mRequireNoTFB = flag; + LOG(info) << "EM Event Cut, require No TF border: " << mRequireNoTFB; +} + +void EMPhotonEventCut::SetRequireNoITSROFB(bool flag) +{ + mRequireNoITSROFB = flag; + LOG(info) << "EM Event Cut, require No ITS ROF border: " << mRequireNoITSROFB; +} + +void EMPhotonEventCut::SetRequireNoSameBunchPileup(bool flag) +{ + mRequireNoSameBunchPileup = flag; + LOG(info) << "EM Event Cut, require No same bunch pileup: " << mRequireNoSameBunchPileup; +} + +void EMPhotonEventCut::SetRequireVertexITSTPC(bool flag) +{ + mRequireVertexITSTPC = flag; + LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC matched track: " << mRequireVertexITSTPC; +} + +void EMPhotonEventCut::SetRequireVertexTOFmatched(bool flag) +{ + mRequireVertexTOFmatched = flag; + LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC-TOF matched track: " << mRequireVertexTOFmatched; +} + +void EMPhotonEventCut::SetRequireGoodZvtxFT0vsPV(bool flag) +{ + mRequireGoodZvtxFT0vsPV = flag; + LOG(info) << "EM Event Cut, require good Zvtx between FT0 vs. PV: " << mRequireGoodZvtxFT0vsPV; +} + +void EMPhotonEventCut::SetRequireNoCollInTimeRangeStandard(bool flag) +{ + mRequireNoCollInTimeRangeStandard = flag; + LOG(info) << "EM Event Cut, require No collision in time range standard: " << mRequireNoCollInTimeRangeStandard; +} + +void EMPhotonEventCut::SetRequireNoCollInTimeRangeStrict(bool flag) +{ + mRequireNoCollInTimeRangeStrict = flag; + LOG(info) << "EM Event Cut, require No collision in time range strict: " << mRequireNoCollInTimeRangeStrict; +} +void EMPhotonEventCut::SetRequireNoCollInITSROFStandard(bool flag) +{ + mRequireNoCollInITSROFStandard = flag; + LOG(info) << "EM Event Cut, require No collision in ITS TOF standard: " << mRequireNoCollInITSROFStandard; +} + +void EMPhotonEventCut::SetRequireNoCollInITSROFStrict(bool flag) +{ + mRequireNoCollInITSROFStrict = flag; + LOG(info) << "EM Event Cut, require No collision in ITS ROF strict: " << mRequireNoCollInITSROFStrict; +} + +void EMPhotonEventCut::SetRequireNoHighMultCollInPrevRof(bool flag) +{ + mRequireNoHighMultCollInPrevRof = flag; + LOG(info) << "EM Event Cut, require No HM collision in previous ITS ROF: " << mRequireNoHighMultCollInPrevRof; +} + +void EMPhotonEventCut::SetRequireGoodITSLayer3(bool flag) +{ + mRequireGoodITSLayer3 = flag; + LOG(info) << "EM Event Cut, require GoodITSLayer3: " << mRequireGoodITSLayer3; +} + +void EMPhotonEventCut::SetRequireGoodITSLayer0123(bool flag) +{ + mRequireGoodITSLayer0123 = flag; + LOG(info) << "EM Event Cut, require GoodITSLayer0123: " << mRequireGoodITSLayer0123; +} + +void EMPhotonEventCut::SetRequireGoodITSLayersAll(bool flag) +{ + mRequireGoodITSLayersAll = flag; + LOG(info) << "EM Event Cut, require GoodITSLayersAll: " << mRequireGoodITSLayersAll; +} + void EMPhotonEventCut::SetRequireEMCReadoutInMB(bool flag) { mRequireEMCReadoutInMB = flag; diff --git a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h index 3b134ce882e..5b14aa8d2ef 100644 --- a/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h +++ b/PWGEM/PhotonMeson/Core/EMPhotonEventCut.h @@ -16,18 +16,38 @@ #ifndef PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ #define PWGEM_PHOTONMESON_CORE_EMPHOTONEVENTCUT_H_ -#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" -using namespace std; +#include -class EMPhotonEventCut : public EMEventCut +#include + +class EMPhotonEventCut : public TNamed { public: EMPhotonEventCut() = default; - EMPhotonEventCut(const char* name, const char* title) : EMEventCut(name, title) {} + EMPhotonEventCut(const char* name, const char* title) : TNamed(name, title) {} enum class EMPhotonEventCuts : int { - kEMCReadoutInMB = 0, + kSel8 = 0, + kFT0AND, + kZvtx, + kNoTFB, + kNoITSROFB, + kNoSameBunchPileup, + kIsVertexITSTPC, + kIsVertexTOFmatched, + kIsGoodZvtxFT0vsPV, + kNoCollInTimeRangeStandard, + kNoCollInTimeRangeStrict, + kNoCollInITSROFStandard, + kNoCollInITSROFStrict, + kNoHighMultCollInPrevRof, + kIsGoodITSLayer3, + kIsGoodITSLayer0123, + kIsGoodITSLayersAll, + kEMCReadoutInMB, kEMCHardwareTriggered, kNCuts }; @@ -35,7 +55,55 @@ class EMPhotonEventCut : public EMEventCut template bool IsSelected(T const& collision) const { - if (!EMEventCut::IsSelected(collision)) { + if (mRequireSel8 && !IsSelected(collision, EMPhotonEventCuts::kSel8)) { + return false; + } + if (mRequireFT0AND && !IsSelected(collision, EMPhotonEventCuts::kFT0AND)) { + return false; + } + if (!IsSelected(collision, EMPhotonEventCuts::kZvtx)) { + return false; + } + if (mRequireNoTFB && !IsSelected(collision, EMPhotonEventCuts::kNoTFB)) { + return false; + } + if (mRequireNoITSROFB && !IsSelected(collision, EMPhotonEventCuts::kNoITSROFB)) { + return false; + } + if (mRequireNoSameBunchPileup && !IsSelected(collision, EMPhotonEventCuts::kNoSameBunchPileup)) { + return false; + } + if (mRequireVertexITSTPC && !IsSelected(collision, EMPhotonEventCuts::kIsVertexITSTPC)) { + return false; + } + if (mRequireVertexTOFmatched && !IsSelected(collision, EMPhotonEventCuts::kIsVertexTOFmatched)) { + return false; + } + if (mRequireGoodZvtxFT0vsPV && !IsSelected(collision, EMPhotonEventCuts::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (mRequireNoCollInTimeRangeStandard && !IsSelected(collision, EMPhotonEventCuts::kNoCollInTimeRangeStandard)) { + return false; + } + if (mRequireNoCollInTimeRangeStrict && !IsSelected(collision, EMPhotonEventCuts::kNoCollInTimeRangeStrict)) { + return false; + } + if (mRequireNoCollInITSROFStandard && !IsSelected(collision, EMPhotonEventCuts::kNoCollInITSROFStandard)) { + return false; + } + if (mRequireNoCollInITSROFStrict && !IsSelected(collision, EMPhotonEventCuts::kNoCollInITSROFStrict)) { + return false; + } + if (mRequireNoHighMultCollInPrevRof && !IsSelected(collision, EMPhotonEventCuts::kNoHighMultCollInPrevRof)) { + return false; + } + if (mRequireGoodITSLayer3 && !IsSelected(collision, EMPhotonEventCuts::kIsGoodITSLayer3)) { + return false; + } + if (mRequireGoodITSLayer0123 && !IsSelected(collision, EMPhotonEventCuts::kIsGoodITSLayer0123)) { + return false; + } + if (mRequireGoodITSLayersAll && !IsSelected(collision, EMPhotonEventCuts::kIsGoodITSLayersAll)) { return false; } if (mRequireEMCReadoutInMB && !IsSelected(collision, EMPhotonEventCuts::kEMCReadoutInMB)) { @@ -51,6 +119,57 @@ class EMPhotonEventCut : public EMEventCut bool IsSelected(T const& collision, const EMPhotonEventCuts& cut) const { switch (cut) { + case EMPhotonEventCuts::kSel8: + return collision.sel8(); + + case EMPhotonEventCuts::kFT0AND: + return collision.selection_bit(o2::aod::evsel::kIsTriggerTVX); + + case EMPhotonEventCuts::kZvtx: + return mMinZvtx < collision.posZ() && collision.posZ() < mMaxZvtx; + + case EMPhotonEventCuts::kNoTFB: + return collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder); + + case EMPhotonEventCuts::kNoITSROFB: + return collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder); + + case EMPhotonEventCuts::kNoSameBunchPileup: + return collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + + case EMPhotonEventCuts::kIsVertexITSTPC: + return collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + + case EMPhotonEventCuts::kIsVertexTOFmatched: + return collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); + + case EMPhotonEventCuts::kIsGoodZvtxFT0vsPV: + return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + + case EMPhotonEventCuts::kNoCollInTimeRangeStandard: + return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + + case EMPhotonEventCuts::kNoCollInTimeRangeStrict: + return collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict); + + case EMPhotonEventCuts::kNoCollInITSROFStandard: + return collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard); + + case EMPhotonEventCuts::kNoCollInITSROFStrict: + return collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict); + + case EMPhotonEventCuts::kNoHighMultCollInPrevRof: + return collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof); + + case EMPhotonEventCuts::kIsGoodITSLayer3: + return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3); + + case EMPhotonEventCuts::kIsGoodITSLayer0123: + return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123); + + case EMPhotonEventCuts::kIsGoodITSLayersAll: + return collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + case EMPhotonEventCuts::kEMCReadoutInMB: return (collision.alias_bit(kTVXinEMC)); @@ -63,10 +182,44 @@ class EMPhotonEventCut : public EMEventCut } // Setters + void SetRequireSel8(bool flag); + void SetRequireFT0AND(bool flag); + void SetZvtxRange(float min, float max); + void SetRequireNoTFB(bool flag); + void SetRequireNoITSROFB(bool flag); + void SetRequireNoSameBunchPileup(bool flag); + void SetRequireVertexITSTPC(bool flag); + void SetRequireVertexTOFmatched(bool flag); + void SetRequireGoodZvtxFT0vsPV(bool flag); + void SetRequireNoCollInTimeRangeStandard(bool flag); + void SetRequireNoCollInTimeRangeStrict(bool flag); + void SetRequireNoCollInITSROFStandard(bool flag); + void SetRequireNoCollInITSROFStrict(bool flag); + void SetRequireNoHighMultCollInPrevRof(bool flag); + void SetRequireGoodITSLayer3(bool flag); + void SetRequireGoodITSLayer0123(bool flag); + void SetRequireGoodITSLayersAll(bool flag); void SetRequireEMCReadoutInMB(bool flag); void SetRequireEMCHardwareTriggered(bool flag); private: + bool mRequireSel8{false}; + bool mRequireFT0AND{true}; + float mMinZvtx{-10.f}, mMaxZvtx{+10.f}; + bool mRequireNoTFB{false}; + bool mRequireNoITSROFB{false}; + bool mRequireNoSameBunchPileup{false}; + bool mRequireVertexITSTPC{false}; + bool mRequireVertexTOFmatched{false}; + bool mRequireGoodZvtxFT0vsPV{false}; + bool mRequireNoCollInTimeRangeStandard{false}; + bool mRequireNoCollInTimeRangeStrict{false}; + bool mRequireNoCollInITSROFStandard{false}; + bool mRequireNoCollInITSROFStrict{false}; + bool mRequireNoHighMultCollInPrevRof{false}; + bool mRequireGoodITSLayer3{false}; + bool mRequireGoodITSLayer0123{false}; + bool mRequireGoodITSLayersAll{false}; bool mRequireEMCReadoutInMB{false}; bool mRequireEMCHardwareTriggered{false}; diff --git a/PWGEM/PhotonMeson/Core/EmMlResponse.h b/PWGEM/PhotonMeson/Core/EmMlResponse.h new file mode 100644 index 00000000000..8e1505b281f --- /dev/null +++ b/PWGEM/PhotonMeson/Core/EmMlResponse.h @@ -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. + +/// \file EmMlResponse.h +/// \brief Class to compute the ML response for EM-analysis selections +/// \author Isabel Kantak , University of Heidelberg + +#ifndef PWGEM_PHOTONMESON_CORE_EMMLRESPONSE_H_ +#define PWGEM_PHOTONMESON_CORE_EMMLRESPONSE_H_ + +#include "Tools/ML/MlResponse.h" + +namespace o2::analysis +{ + +template +class EmMlResponse : public MlResponse +{ + public: + /// Default constructor + EmMlResponse() = default; + /// Default destructor + virtual ~EmMlResponse() = default; +}; + +} // namespace o2::analysis + +#endif // PWGEM_PHOTONMESON_CORE_EMMLRESPONSE_H_ diff --git a/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h b/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h new file mode 100644 index 00000000000..72e3b364a46 --- /dev/null +++ b/PWGEM/PhotonMeson/Core/EmMlResponsePCM.h @@ -0,0 +1,211 @@ +// 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 EmMlResponsePCM.h +/// \brief Class to compute the ML response for PCM analysis selections +/// \author Isabel Kantak , University of Heidelberg + +#ifndef PWGEM_PHOTONMESON_CORE_EMMLRESPONSEPCM_H_ +#define PWGEM_PHOTONMESON_CORE_EMMLRESPONSEPCM_H_ + +#include "PWGEM/PhotonMeson/Core/EmMlResponse.h" + +#include "Tools/ML/MlResponse.h" + +#include +#include +#include + +// Fill the map of available input features +// the key is the feature's name (std::string) +// the value is the corresponding value in EnumInputFeatures +#define FILL_MAP_PCM(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesPCM::FEATURE) \ + } + +// Check if the index of mCachedIndices (index associated to a FEATURE) +// matches the entry in EnumInputFeatures associated to this FEATURE +// if so, the inputFeatures vector is filled with the FEATURE's value +// by calling the corresponding GETTER from OBJECT +#define CHECK_AND_FILL_VEC_PCM_FULL(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesPCM::FEATURE): { \ + inputFeatures.emplace_back(OBJECT.GETTER()); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_PCM_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER +#define CHECK_AND_FILL_VEC_PCM(GETTER) \ + case static_cast(InputFeaturesPCM::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesPCM : uint8_t { + v0PhotonCandidatefVx, + v0PhotonCandidatefVy, + v0PhotonCandidatefVz, + v0PhotonCandidatefDCAxyToPV, + v0PhotonCandidatefDCAzToPV, + v0PhotonCandidatefPCA, + v0PhotonCandidatefAlpha, + v0PhotonCandidatefQtArm, + v0PhotonCandidatefChiSquareNDF, + v0PhotonCandidatefCosPARZ, + v0PhotonCandidatefCosPAXY, + v0PhotonCandidatefCosPA, + v0PhotonCandidatefPsiPair, + v0PhotonCandidatefPhiV, + posV0LegfDCAXY, + posV0LegfDCAZ, + posV0LegfEta, + posV0LegfTPCNClsShared, + posV0LegfTPCNClsFindable, + posV0LegfTPCNClsFindableMinusFound, + posV0LegfTPCNClsFindableMinusCrossedRows, + posV0LegfTPCChi2NCl, + posV0LegfTPCSignal, + posV0LegfTPCNSigmaEl, + posV0LegfTPCNSigmaPi, + posV0LegfITSClusterSizes, + negV0LegfDCAXY, + negV0LegfDCAZ, + negV0LegfEta, + negV0LegfTPCNClsShared, + negV0LegfTPCNClsFindable, + negV0LegfTPCNClsFindableMinusFound, + negV0LegfTPCNClsFindableMinusCrossedRows, + negV0LegfTPCChi2NCl, + negV0LegfTPCSignal, + negV0LegfTPCNSigmaEl, + negV0LegfTPCNSigmaPi, + negV0LegfITSClusterSizes +}; + +template +class EmMlResponsePCM : public EmMlResponse +{ + public: + /// Default constructor + EmMlResponsePCM() = default; + /// Default destructor + virtual ~EmMlResponsePCM() = default; + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the V0photon candidate + /// \return inputFeatures vector + template + std::vector getInputFeatures(T1 const& candidate, T2 const& posLeg, T2 const& negLeg) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefVx, getConversionPointX); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefVy, getConversionPointY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefVz, getConversionPointZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefDCAxyToPV, getDcaXYToPV); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefDCAzToPV, getDcaZToPV); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefPCA, getPCA); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefAlpha, getAlpha); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefQtArm, getQt); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefChiSquareNDF, getChi2NDF); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefCosPARZ, getCosPARZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefCosPAXY, getCosPAXY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefCosPA, getCosPA); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefPsiPair, getPsiPair); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, v0PhotonCandidatefPhiV, getPhiV); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfDCAXY, getPosDcaXY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfDCAZ, getPosDcaZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfEta, getPosEta); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsShared, getPosTPCNClsShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsFindable, getPosTPCNClsFindable); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsFindableMinusFound, getPosTPCNClsFindableMinusShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCNClsFindableMinusCrossedRows, getPosTPCNClsFindableMinusCrossedRows); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCChi2NCl, getPosTPCChi2NCl); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfTPCSignal, getPosTPCSignal); + CHECK_AND_FILL_VEC_PCM_FULL(posLeg, posV0LegfTPCNSigmaEl, tpcNSigmaEl); + CHECK_AND_FILL_VEC_PCM_FULL(posLeg, posV0LegfTPCNSigmaPi, tpcNSigmaPi); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, posV0LegfITSClusterSizes, getPosITSClusterSizes); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfDCAXY, getEleDcaXY); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfDCAZ, getEleDcaZ); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfEta, getEleEta); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsShared, getEleTPCNClsShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsFindable, getEleTPCNClsFindable); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsFindableMinusFound, getEleTPCNClsFindableMinusShared); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCNClsFindableMinusCrossedRows, getEleTPCNClsFindableMinusCrossedRows); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCChi2NCl, getEleTPCChi2NCl); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfTPCSignal, getEleTPCSignal); + CHECK_AND_FILL_VEC_PCM_FULL(negLeg, negV0LegfTPCNSigmaEl, tpcNSigmaEl); + CHECK_AND_FILL_VEC_PCM_FULL(negLeg, negV0LegfTPCNSigmaPi, tpcNSigmaPi); + CHECK_AND_FILL_VEC_PCM_FULL(candidate, negV0LegfITSClusterSizes, getEleITSClusterSizes); + } + } + return inputFeatures; + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_PCM(v0PhotonCandidatefVx), + FILL_MAP_PCM(v0PhotonCandidatefVy), + FILL_MAP_PCM(v0PhotonCandidatefVz), + FILL_MAP_PCM(v0PhotonCandidatefDCAxyToPV), + FILL_MAP_PCM(v0PhotonCandidatefDCAzToPV), + FILL_MAP_PCM(v0PhotonCandidatefPCA), + FILL_MAP_PCM(v0PhotonCandidatefAlpha), + FILL_MAP_PCM(v0PhotonCandidatefQtArm), + FILL_MAP_PCM(v0PhotonCandidatefChiSquareNDF), + FILL_MAP_PCM(v0PhotonCandidatefCosPARZ), + FILL_MAP_PCM(v0PhotonCandidatefCosPAXY), + FILL_MAP_PCM(v0PhotonCandidatefCosPA), + FILL_MAP_PCM(v0PhotonCandidatefPsiPair), + FILL_MAP_PCM(v0PhotonCandidatefPhiV), + FILL_MAP_PCM(posV0LegfDCAXY), + FILL_MAP_PCM(posV0LegfDCAZ), + FILL_MAP_PCM(posV0LegfEta), + FILL_MAP_PCM(posV0LegfTPCNClsShared), + FILL_MAP_PCM(posV0LegfTPCNClsFindable), + FILL_MAP_PCM(posV0LegfTPCNClsFindableMinusFound), + FILL_MAP_PCM(posV0LegfTPCNClsFindableMinusCrossedRows), + FILL_MAP_PCM(posV0LegfTPCChi2NCl), + FILL_MAP_PCM(posV0LegfTPCSignal), + FILL_MAP_PCM(posV0LegfTPCNSigmaEl), + FILL_MAP_PCM(posV0LegfTPCNSigmaPi), + FILL_MAP_PCM(posV0LegfITSClusterSizes), + FILL_MAP_PCM(negV0LegfDCAXY), + FILL_MAP_PCM(negV0LegfDCAZ), + FILL_MAP_PCM(negV0LegfEta), + FILL_MAP_PCM(negV0LegfTPCNClsShared), + FILL_MAP_PCM(negV0LegfTPCNClsFindable), + FILL_MAP_PCM(negV0LegfTPCNClsFindableMinusFound), + FILL_MAP_PCM(negV0LegfTPCNClsFindableMinusCrossedRows), + FILL_MAP_PCM(negV0LegfTPCChi2NCl), + FILL_MAP_PCM(negV0LegfTPCSignal), + FILL_MAP_PCM(negV0LegfTPCNSigmaEl), + FILL_MAP_PCM(negV0LegfTPCNSigmaPi), + FILL_MAP_PCM(negV0LegfITSClusterSizes)}; + } +}; + +} // namespace o2::analysis + +#undef FILL_MAP_PCM +#undef CHECK_AND_FILL_VEC_PCM_FULL +#undef CHECK_AND_FILL_VEC_PCM + +#endif // PWGEM_PHOTONMESON_CORE_EMMLRESPONSEPCM_H_ diff --git a/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h b/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h new file mode 100644 index 00000000000..0b9cb24bbf5 --- /dev/null +++ b/PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h @@ -0,0 +1,109 @@ +// 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 MaterialBudgetWeights.h +/// \brief This code produces a table to retrieve material budget weights. The table is to be join with V0PhotonKF +/// \author Youssef El Mard (youssef.el.mard.bouziani@cern.ch) + +#ifndef PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ +#define PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ + +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +using MyV0PhotonsMB = o2::soa::Join; +using MyV0PhotonMB = MyV0PhotonsMB::iterator; + +struct MaterialBudgetWeights { + o2::framework::Produces omegaMBWeight; + + o2::framework::Configurable ccdbUrl{"ccdbUrl", "http://ccdb-test.cern.ch:8080", "CCDB url"}; + o2::framework::Configurable mbWeightsPath{"mbWeightsPath", "Users/y/yelmard/MaterialBudget/OmegaMBWeights", "Path of the mb weights"}; + + o2::ccdb::CcdbApi ccdbApi; + TH1F* hOmegaMBFromCCDB = nullptr; + + void init(o2::framework::InitContext&) + { + // Load CCDB object only when the real process is enabled + if (!doprocessMC) { + LOG(info) << "MaterialBudgetWeights: dummy mode enabled -> no CCDB query, will write weight=1"; + return; + } + + ccdbApi.init(ccdbUrl.value); + std::map metadata; + LOG(info) << "MaterialBudgetWeights: loading Omega MB histogram from CCDB at path: " << mbWeightsPath.value; + + hOmegaMBFromCCDB = ccdbApi.retrieveFromTFileAny(mbWeightsPath, metadata, -1); + + if (!hOmegaMBFromCCDB) { + LOG(fatal) << "MaterialBudgetWeights: CCDB object is missing. Path=" << mbWeightsPath.value; + } + } + + float computeMBWeight(float v0Rxy) + { + if (!hOmegaMBFromCCDB) { + return 1.f; + } + + int binMBWeight = hOmegaMBFromCCDB->FindBin(v0Rxy); + if (binMBWeight < 1 || binMBWeight > hOmegaMBFromCCDB->GetNbinsX()) { + LOG(debug) << "MaterialBudgetWeights: v0Rxy out of histogram range, returning 1"; + return 1.f; + } + + return hOmegaMBFromCCDB->GetBinContent(binMBWeight); + } + + // real process (weights from CCDB) + void processMC(MyV0PhotonMB const& v0) + { + static bool once = false; + if (!once) { + LOG(info) << "MaterialBudgetWeights: standard process running"; + once = true; + } + if (!hOmegaMBFromCCDB) { // histogram not loaded => behave like dummy + omegaMBWeight(1.f); + return; + } + omegaMBWeight(computeMBWeight(v0.v0radius())); + } + + // dummy process (always weight = 1) + void processDummy(MyV0PhotonMB const&) + { + static bool once = false; + if (!once) { + LOG(info) << "MaterialBudgetWeights: processDummy running"; + once = true; + } + omegaMBWeight(1.f); + } + + PROCESS_SWITCH(MaterialBudgetWeights, processMC, "Fill MB weights from CCDB", false); + PROCESS_SWITCH(MaterialBudgetWeights, processDummy, "Fill dummy MB weights (=1)", true); +}; + +#endif // PWGEM_PHOTONMESON_CORE_MATERIALBUDGETWEIGHTS_H_ diff --git a/PWGEM/PhotonMeson/Core/PairCut.cxx b/PWGEM/PhotonMeson/Core/PairCut.cxx index be8bee172c7..3ea3e06acec 100644 --- a/PWGEM/PhotonMeson/Core/PairCut.cxx +++ b/PWGEM/PhotonMeson/Core/PairCut.cxx @@ -13,9 +13,12 @@ // Class for track selection // -#include "Framework/Logger.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" +#include + +#include + ClassImp(PairCut); const char* PairCut::mCutNames[static_cast(PairCut::PairCuts::kNCuts)] = {"Asym"}; diff --git a/PWGEM/PhotonMeson/Core/PairCut.h b/PWGEM/PhotonMeson/Core/PairCut.h index 19ba27c79bf..c514d8946c8 100644 --- a/PWGEM/PhotonMeson/Core/PairCut.h +++ b/PWGEM/PhotonMeson/Core/PairCut.h @@ -16,15 +16,9 @@ #ifndef PWGEM_PHOTONMESON_CORE_PAIRCUT_H_ #define PWGEM_PHOTONMESON_CORE_PAIRCUT_H_ -#include -#include -#include -#include -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" #include "Rtypes.h" -#include "TNamed.h" -#include "TMath.h" + +#include class PairCut : public TNamed { diff --git a/PWGEM/PhotonMeson/Core/PhotonHBT.h b/PWGEM/PhotonMeson/Core/PhotonHBT.h deleted file mode 100644 index 08738ce8e07..00000000000 --- a/PWGEM/PhotonMeson/Core/PhotonHBT.h +++ /dev/null @@ -1,694 +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 PhotonHBT.h -/// \brief This code loops over v0 photons and makes pairs for photon HBT analysis. -/// \author Daiki Sekihata, daiki.sekihata@cern.ch - -#ifndef PWGEM_PHOTONMESON_CORE_PHOTONHBT_H_ -#define PWGEM_PHOTONMESON_CORE_PHOTONHBT_H_ - -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -// -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include // IWYU pragma: keep -#include -#include // IWYU pragma: keep -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace o2::aod::pwgem::photon::core::photonhbt -{ -enum class ggHBTPairType : int { - kPCMPCM = 0, -}; -} // namespace o2::aod::pwgem::photon::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; -using namespace o2::aod::pwgem::photon::core::photonhbt; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::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"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - 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", 594, "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, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; - ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - Configurable cfgUseLCMS{"cfgUseLCMS", true, "measure relative momentum in LCMS for 1D"}; // always in LCMS for 3D - - ConfigurableAxis ConfQBins{"ConfQBins", {60, 0, +0.3f}, "q bins for output histograms"}; - 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"}; - - EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - 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 cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; - Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; - Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; - } 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_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", 16.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_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - 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_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.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; - - struct : ConfigurableGroup { - std::string prefix = "ggpaircut_group"; - Configurable cfgMinDR_CosOA{"cfgMinDR_CosOA", -1, "min. dr/cosOA for kPCMPCM"}; - } ggpaircuts; - - ~PhotonHBT() - { - delete emh1; - emh1 = 0x0; - delete emh2; - emh2 = 0x0; - - map_mixed_eventId_to_globalBC.clear(); - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - } - - 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*/) - { - 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 (const 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 (const 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 (const 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]); - } - } - - LOGF(info, "cfgOccupancyEstimator = %d", cfgOccupancyEstimator.value); - 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 (const 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); - - o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); - DefineEMEventCut(); - DefinePCMCut(); - - addhistograms(); - - 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, {{10001, -0.5, 10000.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 (std::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 addhistograms() - { - // o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); - static constexpr 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, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, 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, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); - - // pair info - const AxisSpec axis_kt{ConfKtBins, "k_{T} (GeV/c)"}; - const AxisSpec axis_qinv{ConfQBins, "q_{inv} (GeV/c)"}; - const AxisSpec axis_qabs_lcms{ConfQBins, "|#bf{q}|^{LCMS} (GeV/c)"}; - const AxisSpec axis_qout{ConfQBins, "q_{out} (GeV/c)"}; // qout does not change between LAB and LCMS frame - const AxisSpec axis_qside{ConfQBins, "q_{side} (GeV/c)"}; // qside does not change between LAB and LCMS frame - const AxisSpec axis_qlong{ConfQBins, "q_{long} (GeV/c)"}; - - if (cfgDo3D) { // 3D - fRegistry.add("Pair/same/hs_3d", "diphoton correlation 3D LCMS", kTHnSparseD, {axis_qout, axis_qside, axis_qlong, axis_kt}, true); - } else { // 1D - if (cfgUseLCMS) { - fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D LCMS", kTHnSparseD, {axis_qabs_lcms, axis_kt}, true); - } else { - fRegistry.add("Pair/same/hs_1d", "diphoton correlation 1D", kTHnSparseD, {axis_qinv, axis_kt}, true); - } - } - - if constexpr (pairtype == ggHBTPairType::kPCMPCM) { - fRegistry.add("Pair/same/hDeltaRCosOA", "distance between 2 conversion points;#Deltar/cos(#theta_{op}/2) (cm)", kTH1D, {{100, 0, 100}}, true); // dr/cosOA of conversion points - } - - fRegistry.addClone("Pair/same/", "Pair/mix/"); - } - - void DefineEMEventCut() - { - fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); - fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); - fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); - fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); - fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); - fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); - fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); - fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); - } - - 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.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); - 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.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); - fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); - 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); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); - fV0PhotonCut.SetNClustersITS(0, 7); - fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); - } - - 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"), std::fabs(qout_lcms), std::fabs(qside_lcms), std::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 (cfgUseLCMS) { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), qabs_lcms, kt, weight); - } else { - fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("hs_1d"), qinv, 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 (const auto& collision : collisions) { - initCCDB(collision); - int ndiphoton = 0; - const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - 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::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); - 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 = -1; - if (cfgOccupancyEstimator == 0) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else if (cfgOccupancyEstimator == 1) { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.trackOccupancyInTimeRange()) - occ_bin_edges.begin() - 1; - } else { - occbin = lower_bound(occ_bin_edges.begin(), occ_bin_edges.end(), collision.ft0cOccupancyInTimeRange()) - 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); - - auto key_bin = std::make_tuple(zbin, centbin, epbin, occbin); - auto 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 (const 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 dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2) + std::pow(g1.vz() - g2.vz(), 2)); - ROOT::Math::XYZVector cp1(g1.vx(), g1.vy(), g1.vz()); - ROOT::Math::XYZVector cp2(g2.vx(), g2.vy(), g2.vz()); - float opa = std::acos(cp1.Dot(cp2) / (std::sqrt(cp1.Mag2()) * std::sqrt(cp2.Mag2()))); // opening angle between 2 conversion points - o2::math_utils::bringTo02Pi(opa); - if (opa > o2::constants::math::PI) { - opa -= o2::constants::math::PI; - } - float cosOA = std::cos(opa / 2.f); - if (dr / cosOA < ggpaircuts.cfgMinDR_CosOA) { - continue; - } - fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), dr / cosOA); - - fillPairHistogram<0>(collision, v1, v2, 1.f); - ndiphoton++; - - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - EMPair g1tmp = EMPair(g1.pt(), g1.eta(), g1.phi(), 0); - g1tmp.setConversionPointXYZ(g1.vx(), g1.vy(), g1.vz()); - emh1->AddTrackToEventPool(key_df_collision, g1tmp); - used_photonIds_per_col.emplace_back(g1.globalIndex()); - } - if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g2.globalIndex()) == used_photonIds_per_col.end()) { - EMPair g2tmp = EMPair(g2.pt(), g2.eta(), g2.phi(), 0); - g2tmp.setConversionPointXYZ(g2.vx(), g2.vy(), g2.vz()); - emh1->AddTrackToEventPool(key_df_collision, g2tmp); - used_photonIds_per_col.emplace_back(g2.globalIndex()); - } - } // end of pairing loop - } - - used_photonIds_per_col.clear(); - used_photonIds_per_col.shrink_to_fit(); - - // 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 (const 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 (const auto& g1 : selected_photons1_in_this_event) { - for (const 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.); - - float dr = std::sqrt(std::pow(g1.vx() - g2.vx(), 2) + std::pow(g1.vy() - g2.vy(), 2) + std::pow(g1.vz() - g2.vz(), 2)); - ROOT::Math::XYZVector cp1(g1.vx(), g1.vy(), g1.vz()); - ROOT::Math::XYZVector cp2(g2.vx(), g2.vy(), g2.vz()); - float opa = std::acos(cp1.Dot(cp2) / (std::sqrt(cp1.Mag2()) * std::sqrt(cp2.Mag2()))); // opening angle between 2 conversion points - o2::math_utils::bringTo02Pi(opa); - if (opa > o2::constants::math::PI) { - opa -= o2::constants::math::PI; - } - float cosOA = std::cos(opa / 2.f); - if (dr / cosOA < ggpaircuts.cfgMinDR_CosOA) { - continue; - } - fRegistry.fill(HIST("Pair/mix/hDeltaRCosOA"), dr / cosOA); - - fillPairHistogram<1>(collision, v1, v2, 1.f); - } - } - } // end of loop over mixed event pool - } - - 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 - } - - using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMPair>; - MyEMH* emh1 = nullptr; - MyEMH* emh2 = nullptr; - std::vector used_photonIds_per_col; // - std::map, uint64_t> map_mixed_eventId_to_globalBC; - - SliceCache cache; - Preslice perCollision_pcm = 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_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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); - } - ndf++; - } - PROCESS_SWITCH(PhotonHBT, processAnalysis, "pairing for analysis", false); - - void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(PhotonHBT, processDummy, "Dummy function", true); -}; - -#endif // PWGEM_PHOTONMESON_CORE_PHOTONHBT_H_ diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index b13ff0b8695..c89fc48990f 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -20,7 +20,9 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/NMHistograms.h" @@ -54,7 +56,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include @@ -68,6 +70,12 @@ #include #include +enum AlphaMesonCutOption { + Off = 0, + SpecificValue = 1, + PTDependent = 2 +}; + template struct Pi0EtaToGammaGamma { o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -90,6 +98,11 @@ struct Pi0EtaToGammaGamma { o2::framework::ConfigurableAxis ConfEPBins{"ConfEPBins", {o2::framework::VARIABLE_WIDTH, -o2::constants::math::PIHalf, -o2::constants::math::PIQuarter, 0.0f, +o2::constants::math::PIQuarter, +o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; o2::framework::ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {o2::framework::VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + o2::framework::Configurable cfgAlphaMesonCut{"cfgAlphaMesonCut", 0, "flag for photon energy asymmetry distribution cut: 0: no cut, 1: cut specific value, 2: cut depending on pT"}; + o2::framework::Configurable cfgAlphaMeson{"cfgAlphaMeson", 0.65, "photon energy asymmetry distribution parameter for specific value cut"}; + o2::framework::Configurable cfgAlphaMesonA{"cfgAlphaMesonA", 0.65, "photon energy asymmetry distribution parameter A for pT dependent cut (A * tanh(B*pT))"}; + o2::framework::Configurable cfgAlphaMesonB{"cfgAlphaMesonB", 1.2, "photon energy asymmetry distribution parameter B for pT dependent cut (A * tanh(B*pT))"}; + EMPhotonEventCut fEMEventCut; struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; @@ -140,6 +153,21 @@ struct Pi0EtaToGammaGamma { o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; o2::framework::Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; o2::framework::Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + + o2::framework::Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + o2::framework::Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + o2::framework::Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + o2::framework::Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + o2::framework::Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + o2::framework::Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + o2::framework::Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + o2::framework::Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + o2::framework::Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + o2::framework::Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + o2::framework::Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + o2::framework::Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + o2::framework::Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + o2::framework::Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; } pcmcuts; DalitzEECut fDileptonCut; @@ -210,16 +238,16 @@ struct Pi0EtaToGammaGamma { //--------------------------------------------------------------------------- // Preslices and partitions o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emeventId; - o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emeventId; - o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emeventId; - o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::pmeventId; + o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::pmeventId; + o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; o2::framework::PresliceOptional perEMCClusterMT = o2::aod::trackmatching::emEmcClusterId; o2::framework::PresliceOptional perEMCClusterMS = o2::aod::trackmatching::emEmcClusterId; - o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; - o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>* emh1 = nullptr; o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>* emh2 = nullptr; @@ -246,7 +274,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::v0photonkf::emeventId}; + static auto slice{o2::aod::v0photonkf::pmeventId}; return slice; } @@ -267,7 +295,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::emccluster::emeventId}; + static auto slice{o2::aod::emccluster::pmeventId}; return slice; } @@ -301,7 +329,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::phoscluster::emeventId}; + static auto slice{o2::aod::phoscluster::pmeventId}; return slice; } @@ -322,7 +350,7 @@ struct Pi0EtaToGammaGamma { static auto& perCollision() { - static auto slice{o2::aod::emprimaryelectron::emeventId}; + static auto slice{o2::aod::emprimaryelectronda::pmeventId}; return slice; } @@ -421,6 +449,7 @@ struct Pi0EtaToGammaGamma { 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"; } + fV0PhotonCut.SetD_Bz(d_bz); mRunNumber = collision.runNumber(); } @@ -482,6 +511,30 @@ struct Pi0EtaToGammaGamma { fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } } void DefineDileptonCut() @@ -668,7 +721,7 @@ struct Pi0EtaToGammaGamma { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -677,6 +730,7 @@ struct Pi0EtaToGammaGamma { } const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -734,8 +788,8 @@ struct Pi0EtaToGammaGamma { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceByCached(TDetectorTag1::perCollision(), collision.globalIndex(), cache); - 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); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if constexpr (std::is_same_v) { @@ -837,7 +891,35 @@ struct Pi0EtaToGammaGamma { continue; } - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), weight); + float alphaMeson = std::fabs(g1.e() - g2.e()) / (g1.e() + g2.e()); + float alphaCut = 999.f; + switch (static_cast(cfgAlphaMesonCut.value)) { + case AlphaMesonCutOption::Off: + break; + case AlphaMesonCutOption::SpecificValue: + alphaCut = cfgAlphaMeson; + break; + case AlphaMesonCutOption::PTDependent: { + alphaCut = cfgAlphaMesonA * std::tanh(cfgAlphaMesonB * v12.pt()); + break; + } + default: + LOGF(error, "Invalid option for alpha meson cut. No alpha cut will be applied."); + } + if (alphaMeson > alphaCut) { + continue; + } + + float wpair = weight; + + if constexpr (requires { g1.omegaMBWeight(); }) { + wpair *= g1.omegaMBWeight(); + } + if constexpr (requires { g2.omegaMBWeight(); }) { + wpair *= g2.omegaMBWeight(); + } + + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), wpair); if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { emh1->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); @@ -982,13 +1064,13 @@ struct Pi0EtaToGammaGamma { o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; o2::framework::expressions::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 = o2::soa::Filtered>; + // using FilteredMyCollisions = o2::soa::Filtered>; o2::framework::expressions::Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); o2::framework::expressions::Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); int ndf = 0; - void processAnalysis(o2::soa::Filtered> const& collisions, Types const&... args) + void processAnalysis(o2::soa::Filtered> const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { @@ -1024,8 +1106,8 @@ struct Pi0EtaToGammaGamma { } PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysis, "process pair analysis", true); - // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; - void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, Types const&... args) + // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; + void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { @@ -1052,7 +1134,7 @@ struct Pi0EtaToGammaGamma { } PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysisJJMC, "process pair analysis", false); - void processDummy(o2::aod::EMEvents const&) {} + void processDummy(o2::aod::PMEvents const&) {} PROCESS_SWITCH(Pi0EtaToGammaGamma, processDummy, "Dummy function", false); }; #endif // PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 586ea25c9e6..ee823b4f4b0 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -20,7 +20,9 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -49,7 +51,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include @@ -63,6 +65,12 @@ #include #include +enum AlphaMesonCutOption { + Off = 0, + SpecificValue = 1, + PTDependent = 2 +}; + template struct Pi0EtaToGammaGammaMC { o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -79,6 +87,11 @@ struct Pi0EtaToGammaGammaMC { o2::framework::Configurable fd_k0s_to_pi0{"fd_k0s_pi0", "1.0", "feed down correction to pi0"}; o2::framework::Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + o2::framework::Configurable cfgAlphaMesonCut{"cfgAlphaMesonCut", 0, "flag for photon energy asymmetry distribution cut: 0: no cut, 1: cut specific value, 2: cut depending on pT"}; + o2::framework::Configurable cfgAlphaMeson{"cfgAlphaMeson", 0.65, "photon energy asymmetry distribution parameter for specific value cut"}; + o2::framework::Configurable cfgAlphaMesonA{"cfgAlphaMesonA", 0.65, "photon energy asymmetry distribution parameter A for pT dependent cut (A * tanh(B*pT))"}; + o2::framework::Configurable cfgAlphaMesonB{"cfgAlphaMesonB", 1.2, "photon energy asymmetry distribution parameter B for pT dependent cut (A * tanh(B*pT))"}; + EMPhotonEventCut fEMEventCut; struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; @@ -129,6 +142,21 @@ struct Pi0EtaToGammaGammaMC { o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; o2::framework::Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; o2::framework::Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + + o2::framework::Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + o2::framework::Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + o2::framework::Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + o2::framework::Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + o2::framework::Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + o2::framework::Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + o2::framework::Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + o2::framework::Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + o2::framework::Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + o2::framework::Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + o2::framework::Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + o2::framework::Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + o2::framework::Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + o2::framework::Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; } pcmcuts; DalitzEECut fDileptonCut; @@ -269,6 +297,7 @@ struct Pi0EtaToGammaGammaMC { 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"; } + fV0PhotonCut.SetD_Bz(d_bz); mRunNumber = collision.runNumber(); } @@ -322,6 +351,30 @@ struct Pi0EtaToGammaGammaMC { fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } } void DefineDileptonCut() @@ -382,16 +435,16 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::SliceCache cache; - o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::emeventId; - o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::emeventId; - o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::emeventId; - o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectron::emeventId; + o2::framework::PresliceOptional>> perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::PresliceOptional> perCollision_emc = o2::aod::emccluster::pmeventId; + o2::framework::PresliceOptional> perCollision_phos = o2::aod::phoscluster::pmeventId; + o2::framework::PresliceOptional>> perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; o2::framework::PresliceOptional perEMCClusterMT = o2::aod::trackmatching::emEmcClusterId; o2::framework::PresliceOptional perEMCClusterMS = o2::aod::trackmatching::emEmcClusterId; - o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; - o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; + o2::framework::Partition>> electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track; //--------------------------------------------------------------------------- // In the following are tags defined which help to select the correct preslice and cuts @@ -399,7 +452,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::v0photonkf::emeventId}; + static auto slice{o2::aod::v0photonkf::pmeventId}; return slice; } @@ -420,7 +473,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::emccluster::emeventId}; + static auto slice{o2::aod::emccluster::pmeventId}; return slice; } @@ -454,7 +507,7 @@ struct Pi0EtaToGammaGammaMC { static auto& perCollision() { - static auto slice{o2::aod::phoscluster::emeventId}; + static auto slice{o2::aod::phoscluster::pmeventId}; return slice; } @@ -474,7 +527,7 @@ struct Pi0EtaToGammaGammaMC { struct DalitzEETag { static auto& perCollision() { - static auto slice{o2::aod::emprimaryelectron::emeventId}; + static auto slice{o2::aod::emprimaryelectronda::pmeventId}; return slice; } @@ -520,13 +573,12 @@ struct Pi0EtaToGammaGammaMC { { for (auto& collision : collisions) { initCCDB(collision); - if ((pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPHOSPHOS || pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) && !collision.alias_bit(triggerAliases::kTVXinPHOS)) { continue; } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -535,6 +587,7 @@ struct Pi0EtaToGammaGammaMC { } const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } @@ -594,8 +647,8 @@ struct Pi0EtaToGammaGammaMC { photonid1 = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); photonid2 = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kEMCEMC) { - auto cluster1mcparticle = mcparticles.iteratorAt(g1.emmcparticleId()); - auto cluster2mcparticle = mcparticles.iteratorAt(g2.emmcparticleId()); + auto cluster1mcparticle = mcparticles.iteratorAt(g1.emmcparticleIds()[0]); + auto cluster2mcparticle = mcparticles.iteratorAt(g2.emmcparticleIds()[0]); photonid1 = o2::aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(cluster1mcparticle, mcparticles, std::vector{111, 221}); photonid2 = o2::aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(cluster2mcparticle, mcparticles, std::vector{111, 221}); @@ -630,6 +683,34 @@ struct Pi0EtaToGammaGammaMC { continue; } + float alphaMeson = std::fabs(g1.e() - g2.e()) / (g1.e() + g2.e()); + float alphaCut = 999.f; + switch (static_cast(cfgAlphaMesonCut.value)) { + case AlphaMesonCutOption::Off: + break; + case AlphaMesonCutOption::SpecificValue: + alphaCut = cfgAlphaMeson; + break; + case AlphaMesonCutOption::PTDependent: { + alphaCut = cfgAlphaMesonA * std::tanh(cfgAlphaMesonB * v12.pt()); + break; + } + default: + LOGF(error, "Invalid option for alpha meson cut. No alpha cut will be applied."); + } + if (alphaMeson > alphaCut) { + continue; + } + + float wpair = weight; + + if constexpr (requires { g1.omegaMBWeight(); }) { + wpair *= g1.omegaMBWeight(); + } + if constexpr (requires { g2.omegaMBWeight(); }) { + wpair *= g2.omegaMBWeight(); + } + if (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kEMCEMC) { float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); if (openingAngle < emccuts.minOpenAngle) { @@ -639,9 +720,9 @@ struct Pi0EtaToGammaGammaMC { if (g1mc.globalIndex() == g2mc.globalIndex()) { if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == 111) - fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), weight); + fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), wpair); else if (o2::aod::pwgem::dilepton::utils::mcutil::getMotherPDGCode(g1mc, mcparticles) == 221) - fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), weight); + fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), wpair); continue; } @@ -650,20 +731,20 @@ struct Pi0EtaToGammaGammaMC { if (cfgRequireTrueAssociation && (pi0mc.emmceventId() != collision.emmceventId())) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, wpair); } else if (etaid > 0) { auto etamc = mcparticles.iteratorAt(etaid); if (cfgRequireTrueAssociation && (etamc.emmceventId() != collision.emmceventId())) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, wpair); } } // end of pairing loop } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { auto photons1_per_collision = photons1.sliceByCached(TDetectorTag1::perCollision(), collision.globalIndex(), cache); - 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); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if constexpr (std::is_same_v) { @@ -810,7 +891,7 @@ struct Pi0EtaToGammaGammaMC { } o2::framework::PresliceUnsorted perMcCollision = o2::aod::emmcparticle::emmceventId; - o2::framework::PresliceUnsorted> rec_perMcCollision = o2::aod::emmceventlabel::emmceventId; + o2::framework::PresliceUnsorted> rec_perMcCollision = o2::aod::emmceventlabel::emmceventId; template void runGenInfo(TCollisions const& collisions, TMCCollisions const& mccollisions, TMCParticles const& /*mcparticles*/) @@ -830,7 +911,7 @@ struct Pi0EtaToGammaGammaMC { } float weight = 1.f; - if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { + if constexpr (std::is_same_v, o2::soa::Filtered, o2::aod::EMEventsWeight>>>) { weight = collision.weight(); } @@ -858,12 +939,12 @@ struct Pi0EtaToGammaGammaMC { o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; o2::framework::expressions::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 = o2::soa::Filtered>; + // using FilteredMyCollisions = o2::soa::Filtered>; o2::framework::expressions::Filter prefilter_pcm = ifnode(pcmcuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::v0photonkf::pfbderived == static_cast(0), true); o2::framework::expressions::Filter prefilter_primaryelectron = ifnode(dileptoncuts.cfg_apply_cuts_from_prefilter_derived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); - void processAnalysis(o2::soa::Filtered> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) + void processAnalysis(o2::soa::Filtered> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { auto&& [v0photons, v0legs] = std::forward_as_tuple(args...); @@ -898,8 +979,8 @@ struct Pi0EtaToGammaGammaMC { } PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysis, "process pair analysis", true); - // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, aod::EMEventsWeight>>; - void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) + // using FilteredMyCollisionsWithJJMC = o2::soa::Filtered, o2::aod::EMEventsWeight>>; + void processAnalysisJJMC(o2::soa::Filtered, o2::aod::EMEventsWeight>> const& collisions, o2::soa::Join const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPCM) { auto&& [v0photons, v0legs] = std::forward_as_tuple(args...); @@ -944,7 +1025,7 @@ struct Pi0EtaToGammaGammaMC { } PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysisJJMC, "process pair analysis", false); - void processDummy(o2::aod::EMEvents const&) {} + void processDummy(o2::aod::PMEvents const&) {} PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processDummy, "Dummy function", false); }; #endif // PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0.h b/PWGEM/PhotonMeson/Core/TaggingPi0.h index 681b9d9938d..ee4f8fc8083 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0.h @@ -21,8 +21,8 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -48,7 +48,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include @@ -63,163 +63,155 @@ #include #include -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::photonmeson::photonpair; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::dilepton::utils; - -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyCollisionsWithJJMC = soa::Join; +using MyCollisionsWithJJMC = o2::soa::Join; using MyCollisionWithJJMC = MyCollisionsWithJJMC::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = o2::soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyPrimaryElectrons = soa::Join; +using MyPrimaryElectrons = o2::soa::Join; using MyPrimaryElectron = MyPrimaryElectrons::iterator; -using MyEMCClusters = soa::Join; +using MyEMCClusters = o2::soa::Join; using MyEMCCluster = MyEMCClusters::iterator; -using MyPHOSClusters = soa::Join; -using MyPHOSCluster = MyPHOSClusters::iterator; +// using MyPHOSClusters = o2::soa::Join; +// using MyPHOSCluster = MyPHOSClusters::iterator; -template +template struct TaggingPi0 { - 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 ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; - - Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; - Configurable ndepth{"ndepth", 100, "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, -o2::constants::math::PIHalf, -o2::constants::math::PIQuarter, 0.0f, +o2::constants::math::PIQuarter, +o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; - ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; - ConfigurableAxis ConfPtBins{"ConfPtBins", {100, 0, 10}, "pT bins for output histograms"}; + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + o2::framework::Configurable ndiff_bc_mix{"ndiff_bc_mix", 594, "difference in global BC required in mixed events"}; + + o2::framework::Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; + o2::framework::Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; + o2::framework::Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; + o2::framework::Configurable ndepth{"ndepth", 100, "depth for event mixing"}; + o2::framework::ConfigurableAxis ConfVtxBins{"ConfVtxBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfCentBins{"ConfCentBins", {o2::framework::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"}; + o2::framework::ConfigurableAxis ConfEPBins{"ConfEPBins", {o2::framework::VARIABLE_WIDTH, -o2::constants::math::PIHalf, -o2::constants::math::PIQuarter, 0.0f, +o2::constants::math::PIQuarter, +o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; + o2::framework::ConfigurableAxis ConfOccupancyBins{"ConfOccupancyBins", {o2::framework::VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + o2::framework::ConfigurableAxis ConfPtBins{"ConfPtBins", {100, 0, 10}, "pT bins for output histograms"}; + + using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>; EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::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 cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgRequireEMCReadoutInMB{"cfgRequireEMCReadoutInMB", false, "require the EMC to be read out in an MB collision (kTVXinEMC)"}; + o2::framework::Configurable cfgRequireEMCHardwareTriggered{"cfgRequireEMCHardwareTriggered", false, "require the EMC to be hardware triggered (kEMC7 or kDMC7)"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; } eventcuts; V0PhotonCut fV0PhotonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT 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"}; - 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_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - - 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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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"}; - Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + o2::framework::Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; + o2::framework::Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; + o2::framework::Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; + o2::framework::Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; + o2::framework::Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT for v0 photons at PV"}; + o2::framework::Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; + o2::framework::Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.8, "max eta for v0 photons at PV"}; + o2::framework::Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; + o2::framework::Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; + o2::framework::Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; + o2::framework::Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; + o2::framework::Configurable cfg_min_cospa{"cfg_min_cospa", 0.997, "min V0 CosPA"}; + o2::framework::Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; + o2::framework::Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; + o2::framework::Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; + + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 10, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + o2::framework::Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; + o2::framework::Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; } pcmcuts; DalitzEECut fDileptonCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { 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_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; - 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_max_eta_track{"cfg_max_eta_track", 0.8, "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", 0.05, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.05, "max dca Z for single track in cm"}; - Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; - 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_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_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"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 0.1, "max mass"}; + o2::framework::Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", 0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 70, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.05, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.05, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; } dileptoncuts; EMCPhotonCut fEMCCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "emccut_group"; - Configurable clusterDefinition{"clusterDefinition", "kV3Default", "Clusterizer to be selected, e.g. V3Default"}; - 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"}; - Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; + o2::framework::Configurable clusterDefinition{"clusterDefinition", "kV3Default", "Clusterizer to be selected, e.g. V3Default"}; + o2::framework::Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; + o2::framework::Configurable EMC_minTime{"EMC_minTime", -20., "Minimum cluster time for EMCal time cut"}; + o2::framework::Configurable EMC_maxTime{"EMC_maxTime", +25., "Maximum cluster time for EMCal time cut"}; + o2::framework::Configurable EMC_minM02{"EMC_minM02", 0.1, "Minimum M02 for EMCal M02 cut"}; + o2::framework::Configurable EMC_maxM02{"EMC_maxM02", 0.7, "Maximum M02 for EMCal M02 cut"}; + o2::framework::Configurable EMC_minE{"EMC_minE", 0.7, "Minimum cluster energy for EMCal energy cut"}; + o2::framework::Configurable EMC_minNCell{"EMC_minNCell", 1, "Minimum number of cells per cluster for EMCal NCell cut"}; + o2::framework::Configurable> EMC_TM_Eta{"EMC_TM_Eta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + o2::framework::Configurable> EMC_TM_Phi{"EMC_TM_Phi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + o2::framework::Configurable EMC_Eoverp{"EMC_Eoverp", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; + o2::framework::Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; + o2::framework::Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; } emccuts; - PHOSPhotonCut fPHOSCut; - struct : ConfigurableGroup { - std::string prefix = "phoscut_group"; - Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; - } phoscuts; + // PHOSPhotonCut fPHOSCut; + // struct : o2::framework::ConfigurableGroup { + // std::string prefix = "phoscut_group"; + // o2::framework::Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; + // } phoscuts; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::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/"}; @@ -229,11 +221,11 @@ struct TaggingPi0 { std::vector occ_bin_edges; o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + o2::framework::Service ccdb; int mRunNumber; float d_bz; - void init(InitContext&) + void init(o2::framework::InitContext&) { zvtx_bin_edges = std::vector(ConfVtxBins.value.begin(), ConfVtxBins.value.end()); zvtx_bin_edges.erase(zvtx_bin_edges.begin()); @@ -258,7 +250,7 @@ struct TaggingPi0 { DefinePCMCut(); DefineDileptonCut(); DefineEMCCut(); - DefinePHOSCut(); + // DefinePHOSCut(); mRunNumber = 0; d_bz = 0; @@ -325,20 +317,20 @@ struct TaggingPi0 { void addHistogrms() { TString mggTitle = "ee#gamma"; - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { mggTitle = "ee#gamma"; } else { mggTitle = "#gamma#gamma"; } - const AxisSpec axis_m{200, 0, 0.4, Form("m_{%s} (GeV/c^{2})", mggTitle.Data())}; - const AxisSpec axis_pt{ConfPtBins, "p_{T,#gamma} (GeV/c)"}; + const o2::framework::AxisSpec axis_m{200, 0, 0.4, Form("m_{%s} (GeV/c^{2})", mggTitle.Data())}; + const o2::framework::AxisSpec axis_pt{ConfPtBins, "p_{T,#gamma} (GeV/c)"}; - fRegistry.add("Photon/hPt", "p_{T,#gamma};p_{T,#gamma} (GeV/c)", kTH1D, {axis_pt}, true); - fRegistry.add("Photon/hEtaPhi", "#varphi vs. #eta;#varphi_{#gamma} (rad.);#eta_{#gamma}", kTH2D, {{90, 0, o2::constants::math::TwoPI}, {40, -1, +1}}, true); - fRegistry.add("Pair/same/hMvsPt", "mass vs. p_{T,#gamma}", kTH2D, {axis_m, axis_pt}, true); + fRegistry.add("Photon/hPt", "p_{T,#gamma};p_{T,#gamma} (GeV/c)", o2::framework::kTH1D, {axis_pt}, true); + fRegistry.add("Photon/hEtaPhi", "#varphi vs. #eta;#varphi_{#gamma} (rad.);#eta_{#gamma}", o2::framework::kTH2D, {{90, 0, o2::constants::math::TwoPI}, {40, -1, +1}}, true); + fRegistry.add("Pair/same/hMvsPt", "mass vs. p_{T,#gamma}", o2::framework::kTH2D, {axis_m, axis_pt}, true); fRegistry.addClone("Pair/same/", "Pair/mix/"); - fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", kTH1D, {{10001, -0.5, 10000.5}}, true); + fRegistry.add("Pair/mix/hDiffBC", "diff. global BC in mixed event;|BC_{current} - BC_{mixed}|", o2::framework::kTH1D, {{10001, -0.5, 10000.5}}, true); } void DefineEMEventCut() @@ -436,21 +428,20 @@ struct TaggingPi0 { fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); } - void DefinePHOSCut() - { - fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); - } + // void DefinePHOSCut() + // { + // fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); + // } - SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - Preslice perCollision_emc = aod::emccluster::emeventId; - Preslice perCollision_phos = aod::phoscluster::emeventId; + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::Preslice perCollision_emc = o2::aod::emccluster::pmeventId; + // o2::framework::Preslice perCollision_phos = o2::aod::phoscluster::pmeventId; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - 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); + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; + o2::framework::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); + o2::framework::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); - using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; MyEMH* emh1 = nullptr; MyEMH* emh2 = nullptr; std::vector used_photonIds_per_col; // @@ -533,10 +524,10 @@ struct TaggingPi0 { 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 == PairType::kPCMDalitzEE) { - auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); // PCM - auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); // positrons - auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); // electrons + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { + auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); // PCM + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); // positrons + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); // electrons for (const auto& g1 : photons1_per_collision) { if (!cut1.template IsSelected(g1)) { @@ -548,7 +539,7 @@ struct TaggingPi0 { fRegistry.fill(HIST("Photon/hPt"), v_gamma.Pt(), weight); fRegistry.fill(HIST("Photon/hEtaPhi"), v_gamma.Phi() > 0 ? v_gamma.Phi() : v_gamma.Phi() + o2::constants::math::TwoPI, v_gamma.Eta(), weight); - for (const auto& [pos2, ele2] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { + for (const auto& [pos2, ele2] : combinations(o2::soa::CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. continue; @@ -573,11 +564,11 @@ struct TaggingPi0 { std::pair tuple_tmp_id2 = std::make_pair(pos2.trackId(), ele2.trackId()); if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); + emh1->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); used_photonIds_per_col.emplace_back(g1.globalIndex()); } if (std::find(used_dileptonIds_per_col.begin(), used_dileptonIds_per_col.end(), tuple_tmp_id2) == used_dileptonIds_per_col.end()) { - emh2->AddTrackToEventPool(key_df_collision, EMTrack(v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); + emh2->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); used_dileptonIds_per_col.emplace_back(tuple_tmp_id2); } ndiphoton++; @@ -587,7 +578,7 @@ struct TaggingPi0 { auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); // PCM auto photons2_per_collision = photons2.sliceBy(perCollision2, collision.globalIndex()); // EMC or PHOS - for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photons1_per_collision, photons2_per_collision))) { + for (const auto& [g1, g2] : combinations(o2::soa::CombinationsFullIndexPolicy(photons1_per_collision, photons2_per_collision))) { if (!cut1.template IsSelected(g1) || !cut2.template IsSelected(g2)) { continue; } @@ -598,11 +589,11 @@ struct TaggingPi0 { fRegistry.fill(HIST("Pair/same/hMvsPt"), v12.M(), v1.Pt(), weight); if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g1.globalIndex()) == used_photonIds_per_col.end()) { - emh1->AddTrackToEventPool(key_df_collision, EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); + emh1->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(g1.pt(), g1.eta(), g1.phi(), 0)); used_photonIds_per_col.emplace_back(g1.globalIndex()); } if (std::find(used_photonIds_per_col.begin(), used_photonIds_per_col.end(), g2.globalIndex()) == used_photonIds_per_col.end()) { - emh2->AddTrackToEventPool(key_df_collision, EMTrack(g2.pt(), g2.eta(), g2.phi(), 0)); + emh2->AddTrackToEventPool(key_df_collision, o2::aod::pwgem::dilepton::utils::EMTrack(g2.pt(), g2.eta(), g2.phi(), 0)); used_photonIds_per_col.emplace_back(g2.globalIndex()); } ndiphoton++; @@ -648,7 +639,7 @@ struct TaggingPi0 { for (const auto& g2 : photons2_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.); - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { v2.SetM(g2.mass()); } ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; @@ -666,29 +657,29 @@ struct TaggingPi0 { } // end of collision loop } - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + o2::framework::expressions::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 = o2::soa::Filtered; int ndf = 0; void processAnalysis(FilteredMyCollisions const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::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); } - // else if constexpr (pairtype == PairType::kPCMEMC) { + // else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMEMC) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto emcclusters = std::get<2>(std::tie(args...)); // auto emcmatchedtracks = std::get<3>(std::tie(args...)); // runPairing(collisions, v0photons, emcclusters, v0legs, nullptr, perCollision_pcm, perCollision_emc, fV0PhotonCut, fEMCCut, emcmatchedtracks, nullptr); - // } else if constexpr (pairtype == PairType::kPCMPHOS) { + // } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto phosclusters = std::get<2>(std::tie(args...)); @@ -698,24 +689,24 @@ struct TaggingPi0 { } PROCESS_SWITCH(TaggingPi0, processAnalysis, "process pair analysis", true); - using FilteredMyCollisionsWithJJMC = soa::Filtered; + using FilteredMyCollisionsWithJJMC = o2::soa::Filtered; void processAnalysisJJMC(FilteredMyCollisionsWithJJMC const& collisions, Types const&... args) { // LOGF(info, "ndf = %d", ndf); - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::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); } - // else if constexpr (pairtype == PairType::kPCMEMC) { + // else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMEMC) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto emcclusters = std::get<2>(std::tie(args...)); // auto emcmatchedtracks = std::get<3>(std::tie(args...)); // runPairing(collisions, v0photons, emcclusters, v0legs, nullptr, perCollision_pcm, perCollision_emc, fV0PhotonCut, fEMCCut, emcmatchedtracks, nullptr); - // } else if constexpr (pairtype == PairType::kPCMPHOS) { + // } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto phosclusters = std::get<2>(std::tie(args...)); diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h index fb9ba22d87f..17b92c44852 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h @@ -21,8 +21,8 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -49,7 +49,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include @@ -61,173 +61,164 @@ #include #include -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::photonmeson::photonpair; -using namespace o2::aod::pwgem::photonmeson::utils::mcutil; -using namespace o2::aod::pwgem::dilepton::utils::mcutil; - -using MyCollisions = soa::Join; +using MyCollisions = o2::soa::Join; using MyCollision = MyCollisions::iterator; -using MyCollisionsWithJJMC = soa::Join; +using MyCollisionsWithJJMC = o2::soa::Join; using MyCollisionWithJJMC = MyCollisionsWithJJMC::iterator; -using MyMCCollisions = soa::Join; +using MyMCCollisions = o2::soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = o2::soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyEMCClusters = soa::Join; +using MyEMCClusters = o2::soa::Join; using MyEMCCluster = MyEMCClusters::iterator; -using MyPHOSClusters = soa::Join; -using MyPHOSCluster = MyEMCClusters::iterator; +// using MyPHOSClusters = o2::soa::Join; +// using MyPHOSCluster = MyEMCClusters::iterator; -using MyMCV0Legs = soa::Join; +using MyMCV0Legs = o2::soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = o2::soa::Join; using MyMCElectron = MyMCElectrons::iterator; -template +template struct TaggingPi0MC { - 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 cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - Configurable fd_k0s_to_pi0{"fd_k0s_pi0", "1.0", "feed down correction to pi0"}; - Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; - ConfigurableAxis ConfPtBins{"ConfPtBins", {100, 0, 10}, "pT bins for output histograms"}; + o2::framework::Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + o2::framework::Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + o2::framework::Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + o2::framework::Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + o2::framework::Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; + o2::framework::Configurable fd_k0s_to_pi0{"fd_k0s_pi0", "1.0", "feed down correction to pi0"}; + o2::framework::Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + o2::framework::ConfigurableAxis ConfPtBins{"ConfPtBins", {100, 0, 10}, "pT bins for output histograms"}; EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "eventcut_group"; - Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; - 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 cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; + o2::framework::Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + o2::framework::Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + o2::framework::Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + o2::framework::Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + o2::framework::Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; + o2::framework::Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; + o2::framework::Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + o2::framework::Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + o2::framework::Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + o2::framework::Configurable cfgRequireEMCReadoutInMB{"cfgRequireEMCReadoutInMB", false, "require the EMC to be read out in an MB collision (kTVXinEMC)"}; + o2::framework::Configurable cfgRequireEMCHardwareTriggered{"cfgRequireEMCHardwareTriggered", false, "require the EMC to be hardware triggered (kEMC7 or kDMC7)"}; + o2::framework::Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + o2::framework::Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + o2::framework::Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + o2::framework::Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; } eventcuts; V0PhotonCut fV0PhotonCut; - struct : ConfigurableGroup { + struct : o2::framework::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_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT 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"}; - 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_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - - 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_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + o2::framework::Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; + o2::framework::Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; + o2::framework::Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; + o2::framework::Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; + o2::framework::Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT for v0 photons at PV"}; + o2::framework::Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; + o2::framework::Configurable cfg_max_eta_v0{"cfg_max_eta_v0", 0.8, "max eta for v0 photons at PV"}; + o2::framework::Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; + o2::framework::Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; + o2::framework::Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; + o2::framework::Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; + o2::framework::Configurable cfg_min_cospa{"cfg_min_cospa", 0.997, "min V0 CosPA"}; + o2::framework::Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; + o2::framework::Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; + o2::framework::Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; + + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 10, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + o2::framework::Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; + o2::framework::Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; } pcmcuts; DalitzEECut fDileptonCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { 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_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; - 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_max_eta_track{"cfg_max_eta_track", 0.8, "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_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - 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", 0.05, "max dca XY for single track in cm"}; - Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.05, "max dca Z for single track in cm"}; - Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; - - Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; - 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_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_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"}; + o2::framework::Configurable cfg_min_mass{"cfg_min_mass", 0.0, "min mass"}; + o2::framework::Configurable cfg_max_mass{"cfg_max_mass", 0.1, "max mass"}; + o2::framework::Configurable cfg_apply_phiv{"cfg_apply_phiv", true, "flag to apply phiv cut"}; + o2::framework::Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; + o2::framework::Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; + o2::framework::Configurable cfg_phiv_slope{"cfg_phiv_slope", 0.0185, "slope for m vs. phiv"}; + o2::framework::Configurable cfg_phiv_intercept{"cfg_phiv_intercept", -0.0280, "intercept for m vs. phiv"}; + + o2::framework::Configurable cfg_min_pt_track{"cfg_min_pt_track", 0.1, "min pT for single track"}; + o2::framework::Configurable cfg_max_eta_track{"cfg_max_eta_track", 0.8, "max eta for single track"}; + o2::framework::Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + o2::framework::Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 5, "min ncluster its"}; + o2::framework::Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 70, "min ncrossed rows"}; + o2::framework::Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + o2::framework::Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + o2::framework::Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 0.05, "max dca XY for single track in cm"}; + o2::framework::Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.05, "max dca Z for single track in cm"}; + o2::framework::Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; + + o2::framework::Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; + o2::framework::Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + o2::framework::Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; + o2::framework::Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + o2::framework::Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; } dileptoncuts; EMCPhotonCut fEMCCut; - struct : ConfigurableGroup { + struct : o2::framework::ConfigurableGroup { std::string prefix = "emccut_group"; - Configurable clusterDefinition{"clusterDefinition", "kV3Default", "Clusterizer to be selected, e.g. V3Default"}; - 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"}; + o2::framework::Configurable clusterDefinition{"clusterDefinition", "kV3Default", "Clusterizer to be selected, e.g. V3Default"}; + o2::framework::Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; + o2::framework::Configurable EMC_minTime{"EMC_minTime", -20., "Minimum cluster time for EMCal time cut"}; + o2::framework::Configurable EMC_maxTime{"EMC_maxTime", +25., "Maximum cluster time for EMCal time cut"}; + o2::framework::Configurable EMC_minM02{"EMC_minM02", 0.1, "Minimum M02 for EMCal M02 cut"}; + o2::framework::Configurable EMC_maxM02{"EMC_maxM02", 0.7, "Maximum M02 for EMCal M02 cut"}; + o2::framework::Configurable EMC_minE{"EMC_minE", 0.7, "Minimum cluster energy for EMCal energy cut"}; + o2::framework::Configurable EMC_minNCell{"EMC_minNCell", 1, "Minimum number of cells per cluster for EMCal NCell cut"}; + o2::framework::Configurable> EMC_TM_Eta{"EMC_TM_Eta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + o2::framework::Configurable> EMC_TM_Phi{"EMC_TM_Phi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + o2::framework::Configurable EMC_Eoverp{"EMC_Eoverp", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; + o2::framework::Configurable EMC_UseExoticCut{"EMC_UseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; } emccuts; - PHOSPhotonCut fPHOSCut; - struct : ConfigurableGroup { - std::string prefix = "phoscut_group"; - Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; - } phoscuts; + // PHOSPhotonCut fPHOSCut; + // struct : o2::framework::ConfigurableGroup { + // std::string prefix = "phoscut_group"; + // o2::framework::Configurable cfg_min_Ecluster{"cfg_min_Ecluster", 0.3, "Minimum cluster energy for PHOS in GeV"}; + // } phoscuts; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::framework::HistogramRegistry fRegistry{"output", {}, o2::framework::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/"}; static constexpr std::string_view parnames[2] = {"Pi0/", "Eta/"}; o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + o2::framework::Service ccdb; int mRunNumber; float d_bz; TF1* f1fd_k0s_to_pi0; - void init(InitContext&) + void init(o2::framework::InitContext&) { o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); addHistogrms(); @@ -235,7 +226,7 @@ struct TaggingPi0MC { DefinePCMCut(); DefineDileptonCut(); DefineEMCCut(); - DefinePHOSCut(); + // DefinePHOSCut(); mRunNumber = 0; d_bz = 0; @@ -295,26 +286,26 @@ struct TaggingPi0MC { void addHistogrms() { TString mggTitle = "ee#gamma"; - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { mggTitle = "ee#gamma"; } else { mggTitle = "#gamma#gamma"; } - const AxisSpec axis_m{200, 0, 0.4, Form("m_{%s} (GeV/c^{2})", mggTitle.Data())}; - const AxisSpec axis_pt{ConfPtBins, "p_{T,#gamma} (GeV/c)"}; + const o2::framework::AxisSpec axis_m{200, 0, 0.4, Form("m_{%s} (GeV/c^{2})", mggTitle.Data())}; + const o2::framework::AxisSpec axis_pt{ConfPtBins, "p_{T,#gamma} (GeV/c)"}; - fRegistry.add("Photon/candidate/hPt", "photon candidates;p_{T,#gamma} (GeV/c)", kTH1D, {axis_pt}, true); // for purity - fRegistry.add("Photon/candidate/hEtaPhi", "#varphi vs. #eta;#varphi_{#gamma} (rad.);#eta_{#gamma}", kTH2D, {{90, 0, o2::constants::math::TwoPI}, {40, -1, +1}}, true); // for purity - fRegistry.add("Photon/primary/hPt", "photon;p_{T,#gamma} (GeV/c)", kTH1D, {axis_pt}, true); // for purity - fRegistry.add("Photon/primary/hEtaPhi", "#varphi vs. #eta;#varphi_{#gamma} (rad.);#eta_{#gamma}", kTH2D, {{90, 0, o2::constants::math::TwoPI}, {40, -1, +1}}, true); // for purity - fRegistry.addClone("Photon/primary/", "Photon/fromWD/"); // only for completeness - fRegistry.addClone("Photon/primary/", "Photon/fromHS/"); // only for completeness - fRegistry.addClone("Photon/primary/", "Photon/fromPi0/"); // for conditional acceptance, denominator + fRegistry.add("Photon/candidate/hPt", "photon candidates;p_{T,#gamma} (GeV/c)", o2::framework::kTH1D, {axis_pt}, true); // for purity + fRegistry.add("Photon/candidate/hEtaPhi", "#varphi vs. #eta;#varphi_{#gamma} (rad.);#eta_{#gamma}", o2::framework::kTH2D, {{90, 0, o2::constants::math::TwoPI}, {40, -1, +1}}, true); // for purity + fRegistry.add("Photon/primary/hPt", "photon;p_{T,#gamma} (GeV/c)", o2::framework::kTH1D, {axis_pt}, true); // for purity + fRegistry.add("Photon/primary/hEtaPhi", "#varphi vs. #eta;#varphi_{#gamma} (rad.);#eta_{#gamma}", o2::framework::kTH2D, {{90, 0, o2::constants::math::TwoPI}, {40, -1, +1}}, true); // for purity + fRegistry.addClone("Photon/primary/", "Photon/fromWD/"); // only for completeness + fRegistry.addClone("Photon/primary/", "Photon/fromHS/"); // only for completeness + fRegistry.addClone("Photon/primary/", "Photon/fromPi0/"); // for conditional acceptance, denominator - fRegistry.add("Pair/primary/hMvsPt", "mass vs. p_{T,#gamma} from #pi^{0}", kTH2D, {axis_m, axis_pt}, true); // for conditional acceptance, numerator - fRegistry.addClone("Pair/primary/", "Pair/fromWD/"); // only for completeness - fRegistry.addClone("Pair/primary/", "Pair/fromHS/"); // only for completeness + fRegistry.add("Pair/primary/hMvsPt", "mass vs. p_{T,#gamma} from #pi^{0}", o2::framework::kTH2D, {axis_m, axis_pt}, true); // for conditional acceptance, numerator + fRegistry.addClone("Pair/primary/", "Pair/fromWD/"); // only for completeness + fRegistry.addClone("Pair/primary/", "Pair/fromHS/"); // only for completeness } void DefineEMEventCut() @@ -412,19 +403,19 @@ struct TaggingPi0MC { fEMCCut.SetUseExoticCut(emccuts.EMC_UseExoticCut); } - void DefinePHOSCut() - { - fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); - } + // void DefinePHOSCut() + // { + // fPHOSCut.SetEnergyRange(phoscuts.cfg_min_Ecluster, 1e+10); + // } - SliceCache cache; - Preslice perCollision_pcm = aod::v0photonkf::emeventId; - Preslice perCollision_emc = aod::emccluster::emeventId; - Preslice perCollision_phos = aod::phoscluster::emeventId; + o2::framework::SliceCache cache; + o2::framework::Preslice perCollision_pcm = o2::aod::v0photonkf::pmeventId; + o2::framework::Preslice perCollision_emc = o2::aod::emccluster::pmeventId; + // o2::framework::Preslice perCollision_phos = o2::aod::phoscluster::pmeventId; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - 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); + o2::framework::Preslice perCollision_electron = o2::aod::emprimaryelectronda::pmeventId; + o2::framework::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); + o2::framework::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); template void runTruePairing(TCollisions const& collisions, @@ -459,10 +450,10 @@ struct TaggingPi0MC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, weight); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, weight); // accepted - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMDalitzEE) { 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); + auto positrons_per_collision = positrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = electrons->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& g1 : photons1_per_collision) { if (!cut1.template IsSelected(g1)) { @@ -477,7 +468,7 @@ struct TaggingPi0MC { auto ele1 = g1.template negTrack_as(); auto pos1mc = pos1.template emmcparticle_as(); auto ele1mc = ele1.template emmcparticle_as(); - int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); + int photonid1 = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); if (photonid1 < 0) { continue; } @@ -497,8 +488,8 @@ struct TaggingPi0MC { fRegistry.fill(HIST("Photon/fromPi0/hEtaPhi"), v_gamma.Phi() > 0 ? v_gamma.Phi() : v_gamma.Phi() + o2::constants::math::TwoPI, v_gamma.Eta(), weight); } } - } else if (IsFromWD(g1mc.template emmcevent_as(), g1mc, mcparticles) > 0) { - int motherid_strhad = IsFromWD(g1mc.template emmcevent_as(), g1mc, mcparticles); + } else if (o2::aod::pwgem::photonmeson::utils::mcutil::IsFromWD(g1mc.template emmcevent_as(), g1mc, mcparticles) > 0) { + int motherid_strhad = o2::aod::pwgem::photonmeson::utils::mcutil::IsFromWD(g1mc.template emmcevent_as(), g1mc, mcparticles); auto str_had = mcparticles.iteratorAt(motherid_strhad); float weight = 1.f; if (std::abs(str_had.pdgCode()) == 310 && f1fd_k0s_to_pi0 != nullptr) { @@ -511,8 +502,8 @@ struct TaggingPi0MC { fRegistry.fill(HIST("Photon/fromHS/hEtaPhi"), v_gamma.Phi() > 0 ? v_gamma.Phi() : v_gamma.Phi() + o2::constants::math::TwoPI, v_gamma.Eta(), weight); } - for (const auto& [pos2, ele2] : combinations(CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { // ULS - if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. + for (const auto& [pos2, ele2] : combinations(o2::soa::CombinationsFullIndexPolicy(positrons_per_collision, electrons_per_collision))) { // ULS + if (pos2.trackId() == ele2.trackId()) { // this is protection against pairing identical 2 tracks. continue; } if (pos1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) { @@ -529,7 +520,7 @@ struct TaggingPi0MC { auto pos2mc = mcparticles.iteratorAt(pos2.emmcparticleId()); auto ele2mc = mcparticles.iteratorAt(ele2.emmcparticleId()); - int pi0id = FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 111, mcparticles); + int pi0id = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 111, mcparticles); if (pi0id < 0) { continue; } @@ -543,8 +534,8 @@ struct TaggingPi0MC { if (pi0mc.isPhysicalPrimary() || pi0mc.producedByGenerator()) { fRegistry.fill(HIST("Pair/primary/hMvsPt"), veeg.M(), v_gamma.Pt(), weight); - } else if (IsFromWD(pi0mc.template emmcevent_as(), pi0mc, mcparticles) > 0) { - int motherid_strhad = IsFromWD(pi0mc.template emmcevent_as(), pi0mc, mcparticles); + } else if (o2::aod::pwgem::photonmeson::utils::mcutil::IsFromWD(pi0mc.template emmcevent_as(), pi0mc, mcparticles) > 0) { + int motherid_strhad = o2::aod::pwgem::photonmeson::utils::mcutil::IsFromWD(pi0mc.template emmcevent_as(), pi0mc, mcparticles); auto str_had = mcparticles.iteratorAt(motherid_strhad); float weight = 1.f; if (std::abs(str_had.pdgCode()) == 310 && f1fd_k0s_to_pi0 != nullptr) { @@ -561,7 +552,7 @@ struct TaggingPi0MC { auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); auto photons2_per_collision = photons2.sliceBy(perCollision2, collision.globalIndex()); - for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photons1_per_collision, photons2_per_collision))) { + for (const auto& [g1, g2] : combinations(o2::soa::CombinationsFullIndexPolicy(photons1_per_collision, photons2_per_collision))) { if (!cut1.template IsSelected(g1) || !cut2.template IsSelected(g2)) { continue; } @@ -577,27 +568,27 @@ struct TaggingPi0MC { } // end of collision loop } - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - 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; + o2::framework::expressions::Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + o2::framework::expressions::Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + o2::framework::expressions::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 = o2::soa::Filtered; - void processAnalysis(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, aod::EMMCParticles const& mcparticles, Types const&... args) + void processAnalysis(FilteredMyCollisions const& collisions, MyMCCollisions const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::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, mccollisions, mcparticles); } - // else if constexpr (pairtype == PairType::kPCMEMC) { + // else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMEMC) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto emcclusters = std::get<2>(std::tie(args...)); // auto emcmatchedtracks = std::get<3>(std::tie(args...)); // runPairing(collisions, v0photons, emcclusters, v0legs, nullptr, perCollision_pcm, perCollision_emc, fV0PhotonCut, fEMCCut, emcmatchedtracks, nullptr); - // } else if constexpr (pairtype == PairType::kPCMPHOS) { + // } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto phosclusters = std::get<2>(std::tie(args...)); @@ -606,23 +597,23 @@ struct TaggingPi0MC { } PROCESS_SWITCH(TaggingPi0MC, processAnalysis, "process pair analysis", true); - using FilteredMyCollisionsWithJJMC = soa::Filtered; - void processAnalysisJJMC(FilteredMyCollisionsWithJJMC const& collisions, MyMCCollisions const& mccollisions, aod::EMMCParticles const& mcparticles, Types const&... args) + using FilteredMyCollisionsWithJJMC = o2::soa::Filtered; + void processAnalysisJJMC(FilteredMyCollisionsWithJJMC const& collisions, MyMCCollisions const& mccollisions, o2::aod::EMMCParticles const& mcparticles, Types const&... args) { - if constexpr (pairtype == PairType::kPCMDalitzEE) { + if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::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, mccollisions, mcparticles); } - // else if constexpr (pairtype == PairType::kPCMEMC) { + // else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMEMC) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto emcclusters = std::get<2>(std::tie(args...)); // auto emcmatchedtracks = std::get<3>(std::tie(args...)); // runPairing(collisions, v0photons, emcclusters, v0legs, nullptr, perCollision_pcm, perCollision_emc, fV0PhotonCut, fEMCCut, emcmatchedtracks, nullptr); - // } else if constexpr (pairtype == PairType::kPCMPHOS) { + // } else if constexpr (pairtype == o2::aod::pwgem::photonmeson::photonpair::PairType::kPCMPHOS) { // auto v0photons = std::get<0>(std::tie(args...)); // auto v0legs = std::get<1>(std::tie(args...)); // auto phosclusters = std::get<2>(std::tie(args...)); diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h new file mode 100644 index 00000000000..af9acc7003a --- /dev/null +++ b/PWGEM/PhotonMeson/Core/V0PhotonCandidate.h @@ -0,0 +1,284 @@ +// 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 V0PhotonCandidate.h +/// \brief Getter functions for V0 photon candidate properties. +/// \author Isabel Kantak + +#ifndef PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ +#define PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ + +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include + +#include +#include + +enum CentType : uint8_t { + CentFT0M = 0, + CentFT0A = 1, + CentFT0C = 2 +}; + +struct V0PhotonCandidate { + + public: + // Empty Constructor + V0PhotonCandidate() = default; + // Set method for photonconversionbuilder + template + void setPhotonCandidate(const KFParticle& v0DecayVtx, const KFParticle& v0PV, const TTrack& pos, const KFParticle& posDecayVtx, const TTrack& ele, const KFParticle& eleDecayVtx, const auto& collision, float cospa, float cospaRZ, float cospaXY, float psipair, float phiv, CentType centType, auto posdcaXY, auto eledcaXY, auto posdcaZ, auto eledcaZ) + { + conversionPointx = v0DecayVtx.GetX(); + conversionPointy = v0DecayVtx.GetY(); + conversionPointz = v0DecayVtx.GetZ(); + px = v0PV.GetPx(); + py = v0PV.GetPy(); + pz = v0PV.GetPz(); + pT = RecoDecay::sqrtSumOfSquares(px, py); + + posPx = posDecayVtx.GetPx(); + posPy = posDecayVtx.GetPy(); + posPz = posDecayVtx.GetPz(); + elePx = eleDecayVtx.GetPx(); + elePy = eleDecayVtx.GetPy(); + elePz = eleDecayVtx.GetPz(); + posPT = RecoDecay::sqrtSumOfSquares(posPx, posPy); + elePT = RecoDecay::sqrtSumOfSquares(elePx, elePy); + posEta = RecoDecay::eta(std::array{posPx, posPy, posPz}); + eleEta = RecoDecay::eta(std::array{elePx, elePy, elePz}); + + posTPCNClsShared = pos.tpcNClsShared(); + posTPCNClsFindable = pos.tpcNClsFindable(); + posTPCNClsFindableMinusShared = pos.tpcNClsFindableMinusFound(); + posTPCNClsFindableMinusCrossedRows = pos.tpcNClsFindableMinusCrossedRows(); + posTPCChi2NCl = pos.tpcChi2NCl(); + posTPCSignal = pos.tpcSignal(); + posITSClusterSizes = pos.itsClusterSizes(); + eleTPCNClsShared = ele.tpcNClsShared(); + eleTPCNClsFindable = ele.tpcNClsFindable(); + eleTPCNClsFindableMinusShared = ele.tpcNClsFindableMinusFound(); + eleTPCNClsFindableMinusCrossedRows = ele.tpcNClsFindableMinusCrossedRows(); + eleTPCChi2NCl = ele.tpcChi2NCl(); + eleTPCSignal = ele.tpcSignal(); + eleITSClusterSizes = ele.itsClusterSizes(); + + chi2ndf = v0PV.GetChi2() / v0PV.GetNDF(); + pca = posDecayVtx.GetDistanceFromParticle(eleDecayVtx); + eta = RecoDecay::eta(std::array{px, py, pz}); + posEta = RecoDecay::eta(std::array{posPx, posPy, posPz}); + eleEta = RecoDecay::eta(std::array{elePx, elePy, elePz}); + + float v0mom = RecoDecay::sqrtSumOfSquares(v0DecayVtx.GetPx(), v0DecayVtx.GetPy(), v0DecayVtx.GetPz()); + float length = RecoDecay::sqrtSumOfSquares(v0DecayVtx.GetX() - collision.posX(), v0DecayVtx.GetY() - collision.posY(), v0DecayVtx.GetZ() - collision.posZ()); + float dcaXV0ToPV = (v0DecayVtx.GetX() - v0DecayVtx.GetPx() * cospa * length / v0mom) - collision.posX(); + float dcaYV0ToPV = (v0DecayVtx.GetY() - v0DecayVtx.GetPy() * cospa * length / v0mom) - collision.posY(); + float tmpSign = (dcaXV0ToPV * dcaYV0ToPV > 0.f) ? +1.f : -1.f; + + dcaXYV0ToPV = RecoDecay::sqrtSumOfSquares(dcaXV0ToPV, dcaYV0ToPV) * tmpSign; + dcaZV0ToPV = (v0DecayVtx.GetZ() - v0DecayVtx.GetPz() * cospa * length / v0mom) - collision.posZ(); + + alpha = v0_alpha(posPx, posPy, posPz, elePx, elePy, elePz); + qt = v0_qt(posPx, posPy, posPz, elePx, elePy, elePz); + + this->cospa = cospa; + this->cospaRZ = cospaRZ; + this->cospaXY = cospaXY; + this->psipair = psipair; + this->phiv = phiv; + this->centType = centType; + this->posdcaXY = posdcaXY; + this->eledcaXY = eledcaXY; + this->posdcaZ = posdcaZ; + this->eledcaZ = eledcaZ; + + switch (centType) { + case CentType::CentFT0A: + cent = collision.centFT0A(); + break; + case CentType::CentFT0C: + cent = collision.centFT0C(); + break; + case CentType::CentFT0M: + cent = collision.centFT0M(); + break; + } + } + + // Set-Method for V0PhotonCut + void setPhoton(const auto& v0, const auto& pos, const auto& ele, float cent, CentType centType) + { + conversionPointx = v0.vx(); + conversionPointy = v0.vy(); + conversionPointz = v0.vz(); + px = v0.px(); + py = v0.py(); + pz = v0.pz(); + pT = v0.pt(); + + posPx = pos.px(); + posPy = pos.py(); + posPz = pos.pz(); + elePx = ele.px(); + elePy = ele.py(); + elePz = ele.pz(); + posPT = pos.pt(); + elePT = ele.pt(); + posEta = pos.eta(); + eleEta = ele.eta(); + posdcaXY = pos.dcaXY(); + posdcaZ = pos.dcaZ(); + eledcaXY = ele.dcaXY(); + eledcaZ = ele.dcaZ(); + posTPCNClsShared = pos.tpcNClsShared(); + posTPCNClsFindable = pos.tpcNClsFindable(); + posTPCNClsFindableMinusShared = pos.tpcNClsFindableMinusFound(); + posTPCNClsFindableMinusCrossedRows = pos.tpcNClsFindableMinusCrossedRows(); + posTPCChi2NCl = pos.tpcChi2NCl(); + posTPCSignal = pos.tpcSignal(); + posITSClusterSizes = pos.itsClusterSizes(); + eleTPCNClsShared = ele.tpcNClsShared(); + eleTPCNClsFindable = ele.tpcNClsFindable(); + eleTPCNClsFindableMinusShared = ele.tpcNClsFindableMinusFound(); + eleTPCNClsFindableMinusCrossedRows = ele.tpcNClsFindableMinusCrossedRows(); + eleTPCChi2NCl = ele.tpcChi2NCl(); + eleTPCSignal = ele.tpcSignal(); + eleITSClusterSizes = ele.itsClusterSizes(); + + chi2ndf = v0.chiSquareNDF(); + pca = v0.pca(); + eta = v0.eta(); + + dcaXYV0ToPV = v0.dcaXYtopv(); + dcaZV0ToPV = v0.dcaZtopv(); + + cospa = v0.cospa(); + cospaRZ = v0.cospaRZ(); + cospaXY = v0.cospaXY(); + alpha = v0.alpha(); + qt = v0.qtarm(); + psipair = 999.f; // default if V0PhotonPhiVPsi table is not included + phiv = 999.f; // default if V0PhotonPhiVPsi table is not included + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + this->cent = cent; + this->centType = centType; + } + + // Getter functions + float getPosPt() const { return posPT; } + float getElePt() const { return elePT; } + float getChi2NDF() const { return chi2ndf; } + float getDcaXYToPV() const { return dcaXYV0ToPV; } + float getDcaZToPV() const { return dcaZV0ToPV; } + float getAlpha() const { return alpha; } + float getQt() const { return qt; } + float getPhiV() const { return phiv; } + float getPsiPair() const { return psipair; } + float getCosPA() const { return cospa; } + float getCosPARZ() const { return cospaRZ; } + float getCosPAXY() const { return cospaXY; } + float getEta() const { return eta; } + float getPosEta() const { return posEta; } + float getEleEta() const { return eleEta; } + float getConversionPointX() const { return conversionPointx; } + float getConversionPointY() const { return conversionPointy; } + float getConversionPointZ() const { return conversionPointz; } + float getPx() const { return px; } + float getPy() const { return py; } + float getPz() const { return pz; } + float getPt() const { return pT; } + float getPosPx() const { return posPx; } + float getPosPy() const { return posPy; } + float getPosPz() const { return posPz; } + float getElePx() const { return elePx; } + float getElePy() const { return elePy; } + float getElePz() const { return elePz; } + float getPosDcaXY() const { return posdcaXY; } + float getPosDcaZ() const { return posdcaZ; } + float getEleDcaXY() const { return eledcaXY; } + float getEleDcaZ() const { return eledcaZ; } + float getPosTPCNClsShared() const { return posTPCNClsShared; } + float getPosTPCNClsFindable() const { return posTPCNClsFindable; } + float getPosTPCNClsFindableMinusShared() const { return posTPCNClsFindableMinusShared; } + float getPosTPCNClsFindableMinusCrossedRows() const { return posTPCNClsFindableMinusCrossedRows; } + float getPosTPCChi2NCl() const { return posTPCChi2NCl; } + float getPosTPCSignal() const { return posTPCSignal; } + float getPosITSClusterSizes() const { return posITSClusterSizes; } + float getEleTPCNClsShared() const { return eleTPCNClsShared; } + float getEleTPCNClsFindable() const { return eleTPCNClsFindable; } + float getEleTPCNClsFindableMinusShared() const { return eleTPCNClsFindableMinusShared; } + float getEleTPCNClsFindableMinusCrossedRows() const { return eleTPCNClsFindableMinusCrossedRows; } + float getEleTPCChi2NCl() const { return eleTPCChi2NCl; } + float getEleTPCSignal() const { return eleTPCSignal; } + float getEleITSClusterSizes() const { return eleITSClusterSizes; } + float getCent() const { return cent; } + float getPCA() const { return pca; } + CentType getCentType() const { return centType; } + + private: + float conversionPointx{0.f}; + float conversionPointy{0.f}; + float conversionPointz{0.f}; + float px{0.f}; + float py{0.f}; + float pz{0.f}; + float posPx{0.f}; + float posPy{0.f}; + float posPz{0.f}; + float elePx{0.f}; + float elePy{0.f}; + float elePz{0.f}; + float pT{0.f}; + float posPT{0.f}; + float elePT{0.f}; + float dcaXYV0ToPV{0.f}; + float dcaZV0ToPV{0.f}; + float alpha{0.f}; + float qt{0.f}; + float phiv{0.f}; + float psipair{0.f}; + float cospa{0.f}; + float cospaRZ{0.f}; + float cospaXY{0.f}; + float chi2ndf{0.f}; + float cent{0.f}; + float pca{0.f}; + float eta{0.f}; + float posEta{0.f}; + float eleEta{0.f}; + float posdcaXY{0.f}; + float posdcaZ{0.f}; + float eledcaXY{0.f}; + float eledcaZ{0.f}; + float posTPCNClsShared{0.f}; + float posTPCNClsFindable{0.f}; + float posTPCNClsFindableMinusShared{0.f}; + float posTPCNClsFindableMinusCrossedRows{0.f}; + float posTPCChi2NCl{0.f}; + float posTPCSignal{0.f}; + float posITSClusterSizes{0.f}; + float eleTPCNClsShared{0.f}; + float eleTPCNClsFindable{0.f}; + float eleTPCNClsFindableMinusShared{0.f}; + float eleTPCNClsFindableMinusCrossedRows{0.f}; + float eleTPCChi2NCl{0.f}; + float eleTPCSignal{0.f}; + float eleITSClusterSizes{0.f}; + CentType centType{CentFT0C}; +}; + +#endif // PWGEM_PHOTONMESON_CORE_V0PHOTONCANDIDATE_H_ diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index bebd8df962c..e38aed371f9 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -15,14 +15,20 @@ #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" + #include +#include + #include #include #include #include +#include #include +#include ClassImp(V0PhotonCut); @@ -112,6 +118,28 @@ void V0PhotonCut::RejectITSib(bool flag) mRejectITSib = flag; LOG(info) << "V0 Photon Cut, reject photon on ITSib: " << mRejectITSib; } + +void V0PhotonCut::setTooCloseType(V0PhotonCut::TooCloseCuts type) +{ + mTooCloseType = type; + LOG(info) << "V0 Photon Cut, TooCloseV0 cut type: " << static_cast(mTooCloseType); +} +void V0PhotonCut::setMinV0DistSquared(float value) +{ + mMinV0DistSquared = value; + LOG(info) << "V0 Photon Cut, min V0 distance squared: " << mMinV0DistSquared; +} +void V0PhotonCut::setDeltaR(float value) +{ + mDeltaR = value; + LOG(info) << "V0 Photon Cut, delta R for too close V0: " << mDeltaR; +} +void V0PhotonCut::setMinOpeningAngle(float value) +{ + mMinOpeningAngle = value; + LOG(info) << "V0 Photon Cut, min opening angle for too close V0: " << mMinOpeningAngle; +} + void V0PhotonCut::SetTPCNsigmaElRange(float min, float max) { mMinTPCNsigmaEl = min; @@ -239,3 +267,116 @@ void V0PhotonCut::SetDisableTPConly(bool flag) mDisableTPConly = flag; LOG(info) << "V0 Photon Cut, disable TPC only track: " << mDisableTPConly; } + +void V0PhotonCut::SetApplyMlCuts(bool flag) +{ + mApplyMlCuts = flag; + LOG(info) << "V0 Photon Cut, set apply ML: " << mApplyMlCuts; +} + +void V0PhotonCut::SetUse2DBinning(bool flag) +{ + mUse2DBinning = flag; + LOG(info) << "V0 Photon Cut, set use 2D binning for ML: " << mUse2DBinning; +} + +void V0PhotonCut::SetCcdbUrl(const std::string& url) +{ + mCcdbUrl = url; + LOG(info) << "V0 Photon Cut, set CCDB URL: " << mCcdbUrl; +} + +void V0PhotonCut::SetMlModelPathsCCDB(const std::vector& modelPaths) +{ + mModelPathsCCDB = modelPaths; + LOG(info) << "V0 Photon Cut, set ML model paths CCDB with size:" << mModelPathsCCDB.size(); +} + +void V0PhotonCut::SetMlOnnxFileNames(const std::vector& onnxFileNamesVec) +{ + mOnnxFileNames = onnxFileNamesVec; + LOG(info) << "V0 Photon Cut, set ML ONNX file names with size:" << mOnnxFileNames.size(); +} + +void V0PhotonCut::SetMlTimestampCCDB(int timestamp) +{ + mTimestampCCDB = timestamp; + LOG(info) << "V0 Photon Cut, set ML timestamp CCDB: " << mTimestampCCDB; +} + +void V0PhotonCut::SetLoadMlModelsFromCCDB(bool flag) +{ + mLoadMlModelsFromCCDB = flag; + LOG(info) << "V0 Photon Cut, set load ML models from CCDB: " << mLoadMlModelsFromCCDB; +} + +void V0PhotonCut::SetBinsPtMl(const std::vector& binsPt) +{ + mBinsPtMl = binsPt; + LOG(info) << "V0 Photon Cut, set bins pT ML with size:" << mBinsPtMl.size(); +} + +void V0PhotonCut::SetBinsCentMl(const std::vector& binsCent) +{ + mBinsCentMl = binsCent; + LOG(info) << "V0 Photon Cut, set bins centrality ML with size:" << mBinsCentMl.size(); +} + +void V0PhotonCut::SetCutsMl(const std::vector& cuts) +{ + mCutsMlFlat = cuts; + LOG(info) << "V0 Photon Cut, set cuts ML with size:" << mCutsMlFlat.size(); +} + +void V0PhotonCut::SetNClassesMl(int nClasses) +{ + mNClassesMl = nClasses; + mOutputML.reserve(mNClassesMl); + LOG(info) << "V0 Photon Cut, set number of classes ML: " << mNClassesMl; +} + +void V0PhotonCut::SetNamesInputFeatures(const std::vector& featureNames) +{ + mNamesInputFeatures = featureNames; + mMlInputFeatures.reserve(mNamesInputFeatures.size()); + LOG(info) << "V0 Photon Cut, set ML input feature names with size:" << mNamesInputFeatures.size(); +} + +void V0PhotonCut::SetCentrality(float cent) +{ + mCent = cent; +} +void V0PhotonCut::SetD_Bz(float d_bz) +{ + mD_Bz = d_bz; +} + +void V0PhotonCut::SetCutDirMl(const std::vector& cutDirMl) +{ + mCutDirMl = cutDirMl; + LOG(info) << "V0 Photon Cut, set ML cut directions with size:" << mCutDirMl.size(); +} + +void V0PhotonCut::SetCentralityTypeMl(CentType centType) +{ + mCentralityTypeMl = centType; + LOG(info) << "V0 Photon Cut, set centrality type ML: " << mCentralityTypeMl << " (0: CentFT0M, 1: CentFT0A, 2: CentFT0C)"; +} + +void V0PhotonCut::SetLabelsBinsMl(const std::vector& labelsBins) +{ + mLabelsBinsMl = labelsBins; + LOG(info) << "V0 Photon Cut, set ML labels bins with size:" << mLabelsBinsMl.size(); +} + +void V0PhotonCut::SetLabelsCutScoresMl(const std::vector& labelsCutScores) +{ + mLabelsCutScoresMl = labelsCutScores; + LOG(info) << "V0 Photon Cut, set ML labels cut scores with size:" << mLabelsCutScoresMl.size(); +} + +void V0PhotonCut::setDoQA(bool flag) +{ + mDoQA = flag; + LOG(info) << "V0 Photon Cut, set do QA flag to: " << mDoQA; +} diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index 4c3033ba632..7ea0be9beb3 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -16,29 +16,161 @@ #ifndef PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ #define PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ +#include "PWGEM/PhotonMeson/Core/EMBitFlags.h" +#include "PWGEM/PhotonMeson/Core/EmMlResponsePCM.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Utils/TrackSelection.h" +#include +#include #include +#include +#include +#include +#include -#include +#include // IWYU pragma: keep +#include #include +#include + #include #include #include +#include +#include #include #include #include +#include +#include #include +#include + +namespace o2::analysis +{ -using namespace o2::pwgem::photonmeson; +// namespace per channel +namespace em_cuts_ml +{ +// direction of the cut +enum CutDirection { + CutGreater = 0, // require score < cut value + CutSmaller, // require score > cut value + CutNot // do not cut on score +}; + +static constexpr int NBins = 12; + +static constexpr int NBinsPt = 12; +static constexpr int NCutScores = 2; +// default values for the pT bin edges, offset by 1 from the bin numbers in cuts array +constexpr double BinsPt[NBinsPt + 1] = { + 0., + 0.25, + 0.5, + 0.75, + 1., + 1.5, + 2., + 4., + 6., + 10., + 20., + 50., + 100.}; +const auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; +static constexpr int NBinsCent = 11; +constexpr double BinsCent[NBinsCent + 1] = { + 0., + 5, + 10, + 20, + 30, + 40, + 50, + 60, + 70, + 80, + 90, + 100.}; +const auto vecBinsCent = std::vector{BinsCent, BinsCent + NBinsCent + 1}; + +// default values for the ML model paths, one model per pT bin +static const std::vector modelPaths = { + ""}; + +// default values for the cut directions +constexpr int CutDir[NCutScores] = {CutGreater, CutSmaller}; +const auto vecCutDir = std::vector{CutDir, CutDir + NCutScores}; + +// default values for the cuts +constexpr double Cuts[NBins][NCutScores] = { + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}, + {0.5, 0.5}}; + +// 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", + "pT bin 10", + "pT bin 11"}; +// labels +static const std::vector labelsCent = { + "Cent bin 0", + "Cent bin 1", + "Cent bin 2", + "Cent bin 3", + "Cent bin 4", + "Cent bin 5", + "Cent bin 6", + "Cent bin 7", + "Cent bin 8", + "Cent bin 9", + "Cent bin 10"}; + +// column labels +static const std::vector labelsCutScore = {"score background", "score primary photons"}; +} // namespace em_cuts_ml + +} // namespace o2::analysis + +namespace o2::analysis::em::v0 +{ + +template +concept IsNonLinIterator = o2::soa::is_iterator && requires(T t) { + // Check that the *elements* of the container have the required methods: + { t.corrPt() } -> std::same_as; +}; +} // namespace o2::analysis::em::v0 class V0PhotonCut : public TNamed { public: V0PhotonCut() = default; V0PhotonCut(const char* name, const char* title) : TNamed(name, title) {} + ~V0PhotonCut() override { delete mEmMlResponse; }; enum class V0PhotonCuts : int { // v0 cut @@ -55,6 +187,7 @@ class V0PhotonCut : public TNamed kRZLine, kOnWwireIB, kOnWwireOB, + kIsTooClose, // leg cut kTrackPtRange, kTrackEtaRange, @@ -78,80 +211,450 @@ class V0PhotonCut : public TNamed kNCuts }; + enum class TooCloseCuts : uint8_t { + kNoCut = 0, + kDistance3D = 1, + kRadAndAngle = 2 + }; + + /// \brief add histograms to registry + /// \param fRegistry pointer to histogram registry + void addQAHistograms(o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + if (mDoQA && fRegistry != nullptr) { + const o2::framework::AxisSpec thAxispT{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}; + const o2::framework::AxisSpec thAxisMomentum{250, 0., 25., "#it{p} (GeV/#it{c})"}; + const o2::framework::AxisSpec thAxisEta{320, -0.8, 0.8, "#eta"}; + const o2::framework::AxisSpec thAxisPhi{500, 0, o2::constants::math::TwoPI, "#varphi (rad)"}; + const o2::framework::AxisSpec thAxisNSigmaE{500, -10, 10, "#it{N#sigma}_{e} (a.u.)"}; + const o2::framework::AxisSpec thAxisNSigmaPi{500, -10, 10, "#it{N#sigma}_{#pi} (a.u.)"}; + const o2::framework::AxisSpec thAxisNClusTPC{152, 0., 152., "#it{N}_{cl., TPC}"}; + const o2::framework::AxisSpec thAxisNCrossedTPC{152, 0., 152., "#it{N}_{cr., TPC}"}; + const o2::framework::AxisSpec thAxisIDV0{1000, 0., 1000., "ID_{V0}"}; + const o2::framework::AxisSpec thAxisIDLeg{1000, 0., 1000., "ID_{Leg}"}; + const o2::framework::AxisSpec thAxisAlpha{250, -1., 1., "#alpha=(#it{p}^{+}_{L}-#it{p}^{-}_{L})/(#it{p}^{+}_{L}+#it{p}^{-}_{L})"}; + const o2::framework::AxisSpec thAxisQt{200, 0., 0.1, "#it{q}_{T} (GeV/#it{c})"}; + const o2::framework::AxisSpec thAxisConvX{320, -160., +160, "X (cm)"}; + const o2::framework::AxisSpec thAxisConvY{320, -160., +160, "Y (cm)"}; + const o2::framework::AxisSpec thAxisConvZ{180, -90., +90, "Z (cm)"}; + const o2::framework::AxisSpec thAxisConvR{200, 0., +100, "R (cm)"}; + const o2::framework::AxisSpec thAxisChi2{100, 0., +50, "#chi^{2}_{KF}/ndf"}; + const o2::framework::AxisSpec thAxisPsiPair{200, -0.1, +0.1, "#Psi_{pair}"}; + + fRegistry->add("QA/V0Photon/before/hE", "p_{T};#it{p}_{T} (GeV/#it{c});#it{N}_{#gamma}", o2::framework::kTH1D, {thAxispT}, true); + fRegistry->add("QA/V0Photon/before/hPt", "Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{#gamma}", o2::framework::kTH1D, {thAxispT}, true); + fRegistry->add("QA/V0Photon/before/hNgamma", "Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}", o2::framework::kTH1D, {{1001, -0.5f, 1000.5f}}, true); + fRegistry->add("QA/V0Photon/before/hEtaPhi", "#eta vs #varphi;#eta;#varphi (rad.)", o2::framework::kTH2F, {thAxisEta, thAxisPhi}, true); + fRegistry->add("QA/V0Photon/before/hAP", "Armenteros-Podolanski #alpha vs qT", o2::framework::kTH2F, {thAxisAlpha, thAxisQt}, true); + fRegistry->add("QA/V0Photon/before/hConvXY", "Conversion point XY", o2::framework::kTH2F, {thAxisConvX, thAxisConvY}, true); + fRegistry->add("QA/V0Photon/before/hConvZR", "Conversion point ZR", o2::framework::kTH2F, {thAxisConvZ, thAxisConvR}, true); + fRegistry->add("QA/V0Photon/before/hChi2", "Chi2/ndf from KFParticle;#chi^{2}_{KF}/ndf;counts", o2::framework::kTH1D, {thAxisChi2}, true); + + // TODO: add psi_pair once available + // fRegistry->add("QA/V0Photon/before/hPsiPair", "Psi pair;#Psi_{pair};counts", o2::framework::kTH1D, {thAxisPsiPair}, true); + + fRegistry->add("QA/V0Photon/before/Pos/NSigmaE", "NSigmaE of pos leg vs momentum", o2::framework::kTH2F, {thAxisMomentum, thAxisNSigmaE}, true); + fRegistry->add("QA/V0Photon/before/Pos/NSigmaPi", "NSigmaE of pos leg vs momentum", o2::framework::kTH2F, {thAxisMomentum, thAxisNSigmaPi}, true); + fRegistry->add("QA/V0Photon/before/Pos/hEtaPhi", "eta vs phi of pos leg", o2::framework::kTH2F, {thAxisEta, thAxisPhi}, true); + fRegistry->add("QA/V0Photon/before/Pos/hTPCHits", "NCluster vs NFindable TPC", o2::framework::kTH2F, {thAxisNClusTPC, thAxisNCrossedTPC}, true); + fRegistry->add("QA/V0Photon/before/Neg/NSigmaE", "NSigmaE of neg leg vs momentum", o2::framework::kTH2F, {thAxisMomentum, thAxisNSigmaE}, true); + fRegistry->add("QA/V0Photon/before/Neg/NSigmaPi", "NSigmaE of neg leg vs momentum", o2::framework::kTH2F, {thAxisMomentum, thAxisNSigmaPi}, true); + fRegistry->add("QA/V0Photon/before/Neg/hEtaPhi", "eta vs phi of neg leg", o2::framework::kTH2F, {thAxisEta, thAxisPhi}, true); + fRegistry->add("QA/V0Photon/before/Neg/hTPCHits", "NCluster vs NFindable TPC", o2::framework::kTH2F, {thAxisNClusTPC, thAxisNCrossedTPC}, true); + + fRegistry->addClone("QA/V0Photon/before/", "QA/V0Photon/after/"); + + auto hPhotonQualityCuts = fRegistry->add("QA/V0Photon/hPhotonQualityCuts", "pT at which v0 photons are removed by a given cut", o2::framework::kTH2F, {{static_cast(V0PhotonCut::V0PhotonCuts::kNCuts) + 2, -0.5, static_cast(V0PhotonCut::V0PhotonCuts::kNCuts) + 1.5}, thAxispT}, true); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(1, "In"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(2, "#it{M}_{ee}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(3, "#it{p}_{T}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(4, "#it{#eta}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(5, "AP"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(6, "#Psi_{pair}"); // currently not implemented! + hPhotonQualityCuts->GetXaxis()->SetBinLabel(7, "#Phi_{v}"); // currently not implemented! + hPhotonQualityCuts->GetXaxis()->SetBinLabel(8, "#it{R}_{xy}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(9, "CosPA"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(10, "PCA"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(11, "#chi^{2}_{KF}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(12, "RZ_{line}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(13, "Wire_{IB}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(14, "Wire_{OB}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(15, "IsTooClose"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(16, "#it{p}_{T,leg}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(17, "#it{#eta}_{leg}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(18, "#it{N}_{cl,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(19, "#it{N}_{cr,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(20, "#it{N}_{cr,TPC}/#it{N}_{cl,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(21, "FracSharedCl"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(22, "#chi^{2}_{TPC}/NDF"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(23, "#it{N#sigma}_{e,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(24, "#it{N#sigma}_{#pi,TPC}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(25, "DCA_{xy}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(26, "DCA_{z}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(27, "#it{N}_{cl,ITS}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(28, "#chi^{2}_{ITS}/NDF"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(29, "size_{ITS}"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(30, "ITSTPC"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(31, "ITSOnly"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(32, "TPCOnly"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(33, "TPCTRD"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(34, "TPCTOF"); + hPhotonQualityCuts->GetXaxis()->SetBinLabel(35, "Out"); + } + } + + template + void fillBeforePhotonHistogram(TV0 const& v0, TLeg1 const& pos, TLeg2 const& ele, o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + + if (mDoQA == false || fRegistry == nullptr) { + return; + } + + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), 0, v0.pt()); + fRegistry->fill(HIST("QA/V0Photon/before/hE"), v0.e()); + fRegistry->fill(HIST("QA/V0Photon/before/hPt"), v0.pt()); + fRegistry->fill(HIST("QA/V0Photon/before/hEtaPhi"), v0.eta(), v0.phi()); + fRegistry->fill(HIST("QA/V0Photon/before/hAP"), v0.alpha(), v0.qtarm()); + fRegistry->fill(HIST("QA/V0Photon/before/hConvXY"), v0.vx(), v0.vy()); + fRegistry->fill(HIST("QA/V0Photon/before/hConvZR"), v0.vz(), v0.v0radius()); + fRegistry->fill(HIST("QA/V0Photon/before/hChi2"), v0.chiSquareNDF()); + + // TODO: add psi_pair once available + // fRegistry->fill(HIST("QA/V0Photon/before/hPsiPair"), v0.psiPair()); + + fRegistry->fill(HIST("QA/V0Photon/before/Pos/NSigmaE"), pos.p(), pos.tpcNSigmaEl()); + fRegistry->fill(HIST("QA/V0Photon/before/Pos/NSigmaPi"), pos.p(), pos.tpcNSigmaPi()); + fRegistry->fill(HIST("QA/V0Photon/before/Pos/hEtaPhi"), pos.eta(), pos.phi()); + fRegistry->fill(HIST("QA/V0Photon/before/Pos/hTPCHits"), pos.tpcNClsFound(), pos.tpcNClsCrossedRows()); + fRegistry->fill(HIST("QA/V0Photon/before/Neg/NSigmaE"), ele.p(), ele.tpcNSigmaEl()); + fRegistry->fill(HIST("QA/V0Photon/before/Neg/NSigmaPi"), ele.p(), ele.tpcNSigmaPi()); + fRegistry->fill(HIST("QA/V0Photon/before/Neg/hEtaPhi"), ele.eta(), ele.phi()); + fRegistry->fill(HIST("QA/V0Photon/before/Neg/hTPCHits"), ele.tpcNClsFound(), ele.tpcNClsCrossedRows()); + } + + template + void fillAfterPhotonHistogram(TV0 const& v0, TLeg1 const& pos, TLeg2 const& ele, o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + + if (mDoQA == false || fRegistry == nullptr) { + return; + } + + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kNCuts) + 1, v0.pt()); + fRegistry->fill(HIST("QA/V0Photon/after/hE"), v0.e()); + fRegistry->fill(HIST("QA/V0Photon/after/hPt"), v0.pt()); + fRegistry->fill(HIST("QA/V0Photon/after/hEtaPhi"), v0.eta(), v0.phi()); + fRegistry->fill(HIST("QA/V0Photon/after/hAP"), v0.alpha(), v0.qtarm()); + fRegistry->fill(HIST("QA/V0Photon/after/hConvXY"), v0.vx(), v0.vy()); + fRegistry->fill(HIST("QA/V0Photon/after/hConvZR"), v0.vz(), v0.v0radius()); + fRegistry->fill(HIST("QA/V0Photon/after/hChi2"), v0.chiSquareNDF()); + + // TODO: add psi_pair once available + // fRegistry->fill(HIST("QA/V0Photon/after/hPsiPair"), v0.psiPair()); + + fRegistry->fill(HIST("QA/V0Photon/after/Pos/NSigmaE"), pos.p(), pos.tpcNSigmaEl()); + fRegistry->fill(HIST("QA/V0Photon/after/Pos/NSigmaPi"), pos.p(), pos.tpcNSigmaPi()); + fRegistry->fill(HIST("QA/V0Photon/after/Pos/hEtaPhi"), pos.eta(), pos.phi()); + fRegistry->fill(HIST("QA/V0Photon/after/Pos/hTPCHits"), pos.tpcNClsFound(), pos.tpcNClsCrossedRows()); + fRegistry->fill(HIST("QA/V0Photon/after/Neg/NSigmaE"), ele.p(), ele.tpcNSigmaEl()); + fRegistry->fill(HIST("QA/V0Photon/after/Neg/NSigmaPi"), ele.p(), ele.tpcNSigmaPi()); + fRegistry->fill(HIST("QA/V0Photon/after/Neg/hEtaPhi"), ele.eta(), ele.phi()); + fRegistry->fill(HIST("QA/V0Photon/after/Neg/hTPCHits"), ele.tpcNClsFound(), ele.tpcNClsCrossedRows()); + } + + /// \brief creates a mask for the V0s if they are too close to another V0 and have higher chi^2 + /// \param v0s V0 table + template + void createCloseV0CutMask(TV0 const& v0s) const + { + const bool useDistance3D = (mTooCloseType == TooCloseCuts::kDistance3D); + const float windowWidth = useDistance3D ? std::sqrt(mMinV0DistSquared) : mDeltaR; + const float cosMinAngle = std::cos(mMinOpeningAngle); + + int tableSize = v0s.size(); + std::vector rejectMask(tableSize, 0); + + if (mTooCloseType == TooCloseCuts::kNoCut) { + mRejectMask = rejectMask; + return; + } + + auto currentV0Iter = v0s.begin(); + auto otherV0Iter = v0s.begin(); + + int groupStart = 0; + while (groupStart < tableSize) { + + // --- find the end of this collision's group --- + int currentCollisionId = v0s.iteratorAt(groupStart).collisionId(); + int groupEnd = groupStart + 1; + while (groupEnd < tableSize && v0s.iteratorAt(groupEnd).collisionId() == currentCollisionId) { + groupEnd++; + } + + int groupSize = groupEnd - groupStart; + + std::vector> indexedRadii(groupSize); + for (int k = 0; k < groupSize; k++) { + currentV0Iter.setCursor(groupStart + k); + indexedRadii[k] = {groupStart + k, currentV0Iter.v0radius()}; + } + std::sort(indexedRadii.begin(), indexedRadii.end(), [](const auto& a, const auto& b) { + return a.second < b.second; + }); + // extract sorted indices and pre-sorted radii + std::vector sortedIndices(groupSize); + std::vector sortedRadii(groupSize); + for (int k = 0; k < groupSize; k++) { + sortedIndices[k] = indexedRadii[k].first; + sortedRadii[k] = indexedRadii[k].second; + } + + // --- sliding window within this group --- + int windowStart = 0; // reset per group + for (int i = 0; i < groupSize; i++) { + + float currentRadius = sortedRadii[i]; + while (windowStart < groupSize && sortedRadii[windowStart] < currentRadius - windowWidth) { + windowStart++; + } + + currentV0Iter.setCursor(sortedIndices[i]); + + float vx1 = currentV0Iter.vx(); + float vy1 = currentV0Iter.vy(); + float vz1 = currentV0Iter.vz(); + + float px1 = currentV0Iter.px(); + float py1 = currentV0Iter.py(); + float pz1 = currentV0Iter.pz(); + float chi2I = currentV0Iter.chiSquareNDF(); + + for (int j = windowStart; j < groupSize; j++) { + if (j == i) { + continue; + } + if (sortedRadii[j] > currentRadius + windowWidth) { + break; + } + + otherV0Iter.setCursor(sortedIndices[j]); + + bool tooClose = false; + if (useDistance3D) { + float dx = vx1 - otherV0Iter.vx(); + float dy = vy1 - otherV0Iter.vy(); + float dz = vz1 - otherV0Iter.vz(); + float distSquared = dx * dx + dy * dy + dz * dz; + tooClose = distSquared < mMinV0DistSquared; + } else { + float px2 = otherV0Iter.px(), py2 = otherV0Iter.py(), pz2 = otherV0Iter.pz(); + float dot = px1 * px2 + py1 * py2 + pz1 * pz2; + float mag1 = px1 * px1 + py1 * py1 + pz1 * pz1; + float mag2 = px2 * px2 + py2 * py2 + pz2 * pz2; + float denom = std::sqrt(mag1 * mag2); + if (denom > 0) { + float cosAngle = dot / denom; + cosAngle = std::clamp(cosAngle, -1.0f, 1.0f); + tooClose = cosAngle > cosMinAngle; + } + } + + if (tooClose) { + if (chi2I > otherV0Iter.chiSquareNDF()) { + rejectMask[sortedIndices[i]] = 1; + + } else { + rejectMask[sortedIndices[j]] = 1; + } + } + } + } + groupStart = groupEnd; + } + mRejectMask = rejectMask; + } + + /// \brief check if given v0 photon survives all cuts + /// \param flags EMBitFlags where results will be stored + /// \param v0s v0 photon table to check + template + void AreSelectedRunning(EMBitFlags& flags, TV0 const& v0s, o2::framework::HistogramRegistry* fRegistry = nullptr) const + { + if (v0s.size() <= 0) { + return; + } + + createCloseV0CutMask(v0s); + // auto legIter = legs.begin(); + // auto legEnd = legs.end(); + size_t iV0 = 0; + + const bool doQA = mDoQA && fRegistry != nullptr; + + uint nTotV0PerColl = 0; + currentCollID = v0s.iteratorAt(0).pmeventId(); + + for (const auto& v0 : v0s) { + const auto collID = v0.pmeventId(); + if (!IsSelected(v0, fRegistry)) { + flags.set(iV0); + } + if (collID != currentCollID) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/before/hNgamma"), nTotV0PerColl); + } + nTotV0PerColl = 0; + currentCollID = collID; + } + ++nTotV0PerColl; + ++iV0; + } + } + template - bool IsSelected(TV0 const& v0) const + bool IsSelected(TV0 const& v0, o2::framework::HistogramRegistry* fRegistry = nullptr) const { - if (!IsSelectedV0(v0, V0PhotonCuts::kV0PtRange)) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); + + const float v0Pt = v0.pt(); + + const auto doQA = mDoQA && fRegistry != nullptr; + + if (doQA) { + fillBeforePhotonHistogram(v0, pos, ele, fRegistry); + } + if (!IsSelectedV0(v0, V0PhotonCuts::kMee)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kMee) + 1, v0Pt); + } return false; } - if (!IsSelectedV0(v0, V0PhotonCuts::kV0EtaRange)) { + if (!IsSelectedV0(v0, V0PhotonCuts::kV0PtRange)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kV0PtRange) + 1, v0Pt); + } return false; } - if (!IsSelectedV0(v0, V0PhotonCuts::kMee)) { + if (!IsSelectedV0(v0, V0PhotonCuts::kV0EtaRange)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kV0EtaRange) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kAP)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kAP) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kPsiPair)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kPsiPair) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kPhiV)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kPhiV) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kRxy)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRxy) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kCosPA)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kCosPA) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kPCA)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kPCA) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kChi2KF)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kChi2KF) + 1, v0Pt); + } return false; } if (!IsSelectedV0(v0, V0PhotonCuts::kRZLine)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRZLine) + 1, v0Pt); + } return false; } if (mIsOnWwireIB && mIsOnWwireOB) { if (!IsSelectedV0(v0, V0PhotonCuts::kOnWwireIB) && !IsSelectedV0(v0, V0PhotonCuts::kOnWwireOB)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kOnWwireIB) + 1, v0Pt); + } return false; } } else if (mIsOnWwireIB) { if (!IsSelectedV0(v0, V0PhotonCuts::kOnWwireIB)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kOnWwireIB) + 1, v0Pt); + } return false; } } else if (mIsOnWwireOB) { if (!IsSelectedV0(v0, V0PhotonCuts::kOnWwireOB)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kOnWwireOB) + 1, v0Pt); + } return false; } } - auto pos = v0.template posTrack_as(); - auto ele = v0.template negTrack_as(); + if (!IsSelectedV0(v0, V0PhotonCuts::kIsTooClose)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kIsTooClose) + 1, v0Pt); + } + return false; + } - for (auto& track : {pos, ele}) { + for (const auto& track : {pos, ele}) { if (!IsSelectedTrack(track, V0PhotonCuts::kTrackPtRange)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTrackPtRange) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTrackEtaRange)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTrackEtaRange) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kDCAxy)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kDCAxy) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kDCAz)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kDCAz) + 1, v0Pt); + } return false; } if (!track.hasITS() && !track.hasTPC()) { // track has to be ITSonly or TPConly or ITS-TPC return false; } - if (mDisableITSonly && isITSonlyTrack(track)) { + if (mDisableITSonly && o2::pwgem::photonmeson::isITSonlyTrack(track)) { return false; } - if (mDisableTPConly && isTPConlyTrack(track)) { + if (mDisableTPConly && o2::pwgem::photonmeson::isTPConlyTrack(track)) { return false; } @@ -159,21 +662,21 @@ class V0PhotonCut : public TNamed auto hits_ib = std::count_if(its_ib_Requirement.second.begin(), its_ib_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); auto hits_ob = std::count_if(its_ob_Requirement.second.begin(), its_ob_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); bool its_ob_only = (hits_ib <= its_ib_Requirement.first) && (hits_ob >= its_ob_Requirement.first); - if (isITSonlyTrack(track) && !its_ob_only) { // ITSonly tracks should not have any ITSib hits. + if (o2::pwgem::photonmeson::isITSonlyTrack(track) && !its_ob_only) { // ITSonly tracks should not have any ITSib hits. return false; } auto hits_ob_itstpc = std::count_if(its_ob_Requirement_ITSTPC.second.begin(), its_ob_Requirement_ITSTPC.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); bool its_ob_only_itstpc = (hits_ib <= its_ib_Requirement.first) && (hits_ob_itstpc >= its_ob_Requirement_ITSTPC.first); - if (isITSTPCTrack(track) && !its_ob_only_itstpc) { // ITSTPC tracks should not have any ITSib hits. + if (o2::pwgem::photonmeson::isITSTPCTrack(track) && !its_ob_only_itstpc) { // ITSTPC tracks should not have any ITSib hits. return false; } } - if (track.hasITS() && !CheckITSCuts(track)) { + if (track.hasITS() && !CheckITSCuts(track, fRegistry, v0Pt)) { return false; } - if (track.hasTPC() && !CheckTPCCuts(track)) { + if (track.hasTPC() && !CheckTPCCuts(track, fRegistry, v0Pt)) { return false; } if (track.hasITS() && !track.hasTPC() && (track.hasTRD() || track.hasTOF())) { // remove ITS-TRD, ITS-TOF, ITS-TRD-TOF that are unrealistic tracks. @@ -185,61 +688,134 @@ class V0PhotonCut : public TNamed } if (mRequireITSonly && !IsSelectedTrack(track, V0PhotonCuts::kRequireITSonly)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRequireITSonly) + 1, v0Pt); + } return false; } if (mRequireITSTPC && !IsSelectedTrack(track, V0PhotonCuts::kRequireITSTPC)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRequireITSTPC) + 1, v0Pt); + } return false; } if (mRequireTPConly && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPConly)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRequireTPConly) + 1, v0Pt); + } return false; } if (mRequireTPCTRD && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPCTRD)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRequireTPCTRD) + 1, v0Pt); + } return false; } if (mRequireTPCTOF && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPCTOF)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kRequireTPCTOF) + 1, v0Pt); + } + return false; + } + } + if (mApplyMlCuts) { + if (mEmMlResponse == nullptr) { + LOG(error) << "EM ML Response is not initialized!"; + return false; + } + mIsSelectedMl = false; + mV0PhotonForMl.setPhoton(v0, pos, ele, mCent, mCentralityTypeMl); + mMlInputFeatures = mEmMlResponse->getInputFeatures(mV0PhotonForMl, pos, ele); + if (mUse2DBinning) { + mIsSelectedMl = mEmMlResponse->isSelectedMl(mMlInputFeatures, mV0PhotonForMl.getPt(), mV0PhotonForMl.getCent(), mOutputML); + } else { + mIsSelectedMl = mEmMlResponse->isSelectedMl(mMlInputFeatures, mV0PhotonForMl.getPt(), mOutputML); + } + if (!mIsSelectedMl) { return false; } + mMlBDTScores = std::span(mOutputML.data(), mOutputML.size()); + } + if (doQA) { + fillAfterPhotonHistogram(v0, pos, ele, fRegistry); + if (v0.pmeventId() != currentCollID) { + fRegistry->fill(HIST("QA/V0Photon/after/hNgamma"), nAccV0PerColl); + nAccV0PerColl = 0; + } + ++nAccV0PerColl; } return true; } template - bool CheckITSCuts(T const& track) const + bool CheckITSCuts(T const& track, o2::framework::HistogramRegistry* fRegistry = nullptr, const float v0Pt = 0.f) const { + const auto doQA = mDoQA && fRegistry != nullptr; if (!IsSelectedTrack(track, V0PhotonCuts::kITSNCls)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kITSNCls) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kITSChi2NDF)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kITSChi2NDF) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kITSClusterSize)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kITSClusterSize) + 1, v0Pt); + } return false; } return true; } template - bool CheckTPCCuts(T const& track) const + bool CheckTPCCuts(T const& track, o2::framework::HistogramRegistry* fRegistry = nullptr, const float v0Pt = 0.f) const { + const auto doQA = mDoQA && fRegistry != nullptr; if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNCls)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCNCls) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRows)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCCrossedRows) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRowsOverNCls)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCCrossedRowsOverNCls) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCFracSharedClusters)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCFracSharedClusters) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCChi2NDF)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCChi2NDF) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNsigmaEl)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCNsigmaEl) + 1, v0Pt); + } return false; } if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNsigmaPi)) { + if (doQA) { + fRegistry->fill(HIST("QA/V0Photon/hPhotonQualityCuts"), static_cast(V0PhotonCuts::kTPCNsigmaPi) + 1, v0Pt); + } return false; } return true; @@ -250,7 +826,11 @@ class V0PhotonCut : public TNamed { switch (cut) { case V0PhotonCuts::kV0PtRange: - return v0.pt() >= mMinV0Pt && v0.pt() <= mMaxV0Pt; + if constexpr (o2::analysis::em::v0::IsNonLinIterator) { + return v0.corrPt() >= mMinV0Pt && v0.corrPt() <= mMaxV0Pt; + } else { + return v0.pt() >= mMinV0Pt && v0.pt() <= mMaxV0Pt; + } case V0PhotonCuts::kV0EtaRange: return v0.eta() >= mMinV0Eta && v0.eta() <= mMaxV0Eta; @@ -259,13 +839,26 @@ class V0PhotonCut : public TNamed return v0.mGamma() < mMaxQt * 2.f; case V0PhotonCuts::kAP: - return pow(v0.alpha() / mMaxAlpha, 2) + pow(v0.qtarm() / mMaxQt, 2) < 1.0; + return std::pow(v0.alpha() / mMaxAlpha, 2) + std::pow(v0.qtarm() / mMaxQt, 2) < 1.0; - case V0PhotonCuts::kPsiPair: - return true; + // TODO: implement fully + case V0PhotonCuts::kPsiPair: { + if constexpr (requires { v0.psipair(); }) { + // return (std::fabs(v0.psipair() < 0.18f * std::exp( -0.55f * v0.chiSquareNDF()))); + return true; + } else { + return true; + } + } - case V0PhotonCuts::kPhiV: - return true; + // TODO: implement fully + case V0PhotonCuts::kPhiV: { + if constexpr (requires { v0.phiv(); }) { + return true; + } else { + return true; + } + } case V0PhotonCuts::kRxy: { if (v0.v0radius() < mMinRxy || mMaxRxy < v0.v0radius()) { @@ -297,24 +890,24 @@ class V0PhotonCut : public TNamed float y = v0.vy(); // cm, measured secondary vertex of gamma->ee float z = v0.vz(); // cm, measured secondary vertex of gamma->ee - float rxy = sqrt(x * x + y * y); + float rxy = std::sqrt(x * x + y * y); if (rxy < 7.0 || 14.0 < rxy) { return false; } - // r = 0.192 * z + 8.88 (cm) expected wire position in RZ plane.TMath::Tan(10.86 * TMath::DegToRad()) = 0.192 + // r = 0.192 * z + 8.88 (cm) expected wire position in RZ plane.TMath::Tan(10.86 * o2::constants::math::Deg2Rad) = 0.192 if (rxy > 0.192 * z + 14.0) { // upper limit return false; } - float dxy = std::fabs(1.0 * y - x * std::tan(-8.52 * TMath::DegToRad())) / sqrt(pow(1.0, 2) + pow(std::tan(-8.52 * TMath::DegToRad()), 2)); + float dxy = std::fabs(1.0 * y - x * std::tan(-8.52f * o2::constants::math::Deg2Rad)) / std::sqrt(std::pow(1.0, 2) + std::pow(std::tan(-8.52f * o2::constants::math::Deg2Rad), 2)); return !(dxy > margin_xy); } case V0PhotonCuts::kOnWwireOB: { - const float margin_xy = 1.0; // cm - const float rxy_exp = 30.8; // cm - const float x_exp = rxy_exp * std::cos(-1.3 * TMath::DegToRad()); // cm, expected position x of W wire - const float y_exp = rxy_exp * std::sin(-1.3 * TMath::DegToRad()); // cm, expected position y of W wire + const float margin_xy = 1.0; // cm + const float rxy_exp = 30.8; // cm + const float x_exp = rxy_exp * std::cos(-1.3f * o2::constants::math::Deg2Rad); // cm, expected position x of W wire + const float y_exp = rxy_exp * std::sin(-1.3f * o2::constants::math::Deg2Rad); // cm, expected position y of W wire // const float z_min = -47.0; // cm // const float z_max = +47.0; // cm float x = v0.vx(); // cm, measured secondary vertex of gamma->ee @@ -329,6 +922,12 @@ class V0PhotonCut : public TNamed float dxy = std::sqrt(std::pow(x - x_exp, 2) + std::pow(y - y_exp, 2)); return !(dxy > margin_xy); } + case V0PhotonCuts::kIsTooClose: { + if (mRejectMask.size() == 0) { + return true; + } + return (mRejectMask[v0.globalIndex()] == 0); + } default: return false; } @@ -379,32 +978,114 @@ class V0PhotonCut : public TNamed return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; case V0PhotonCuts::kITSClusterSize: { - if (!isITSonlyTrack(track)) { + if (!o2::pwgem::photonmeson::isITSonlyTrack(track)) { return true; } return mMinMeanClusterSizeITS < track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; } case V0PhotonCuts::kRequireITSTPC: - return isITSTPCTrack(track); + return o2::pwgem::photonmeson::isITSTPCTrack(track); case V0PhotonCuts::kRequireITSonly: - return isITSonlyTrack(track); + return o2::pwgem::photonmeson::isITSonlyTrack(track); case V0PhotonCuts::kRequireTPConly: - return isTPConlyTrack(track); + return o2::pwgem::photonmeson::isTPConlyTrack(track); case V0PhotonCuts::kRequireTPCTRD: - return isTPCTRDTrack(track); + return o2::pwgem::photonmeson::isTPCTRDTrack(track); case V0PhotonCuts::kRequireTPCTOF: - return isTPCTOFTrack(track); + return o2::pwgem::photonmeson::isTPCTOFTrack(track); default: return false; } } + void initV0MlModels(o2::ccdb::CcdbApi& ccdbApi) + { + if (mEmMlResponse == nullptr) { + mEmMlResponse = new o2::analysis::EmMlResponsePCM(); + } + if (mUse2DBinning) { + int binsNPt = static_cast(mBinsPtMl.size()) - 1; + int binsNCent = static_cast(mBinsCentMl.size()) - 1; + int binsN = binsNPt * binsNCent; + if (binsN * static_cast(mCutDirMl.size()) != static_cast(mCutsMlFlat.size())) { + LOG(fatal) << "Mismatch in number of bins and cuts provided for 2D ML application: binsN * mCutDirMl: " << int(binsN) * int(mCutDirMl.size()) << " bins vs. mCutsMlFlat: " << mCutsMlFlat.size() << " cuts"; + } + if (binsN != static_cast(mOnnxFileNames.size())) { + LOG(fatal) << "Mismatch in number of bins and ONNX files provided for 2D ML application: binsN " << binsN << " bins vs. mOnnxFileNames: " << mOnnxFileNames.size() << " ONNX files"; + } + if (binsN != static_cast(mLabelsBinsMl.size())) { + LOG(fatal) << "Mismatch in number of bins and labels provided for 2D ML application: binsN:" << binsN << " bins vs. mLabelsBinsMl: " << mLabelsBinsMl.size() << " labels"; + } + if (static_cast(mCutDirMl.size()) != mNClassesMl) { + LOG(fatal) << "Mismatch in number of classes and cut directions provided for 2D ML application: mNClassesMl: " << mNClassesMl << " classes vs. mCutDirMl: " << mCutDirMl.size() << " cut directions"; + } + if (static_cast(mLabelsCutScoresMl.size()) != mNClassesMl) { + LOG(fatal) << "Mismatch in number of labels for cut scores and number of classes provided for 2D ML application: mNClassesMl: " << mNClassesMl << " classes vs. mLabelsCutScoresMl: " << mLabelsCutScoresMl.size() << " labels"; + } + o2::framework::LabeledArray mCutsMl(mCutsMlFlat.data(), binsN, mNClassesMl, mLabelsBinsMl, mLabelsCutScoresMl); + mEmMlResponse->configure2D(mBinsPtMl, mBinsCentMl, mCutsMl, mCutDirMl, mNClassesMl); + } else { + int binsNPt = static_cast(mBinsPtMl.size()) - 1; + if (binsNPt * static_cast(mCutDirMl.size()) != static_cast(mCutsMlFlat.size())) { + LOG(fatal) << "Mismatch in number of pT bins and cuts provided for ML application: binsNPt * mCutDirMl:" << binsNPt * mCutDirMl.size() << " bins vs. mCutsMlFlat: " << mCutsMlFlat.size() << " cuts"; + } + if (binsNPt != static_cast(mOnnxFileNames.size())) { + LOG(fatal) << "Mismatch in number of pT bins and ONNX files provided for ML application: binsNPt " << binsNPt << " bins vs. mOnnxFileNames: " << mOnnxFileNames.size() << " ONNX files"; + } + if (binsNPt != static_cast(mLabelsBinsMl.size())) { + LOG(fatal) << "Mismatch in number of pT bins and labels provided for ML application: binsNPt:" << binsNPt << " bins vs. mLabelsBinsMl: " << mLabelsBinsMl.size() << " labels"; + } + if (mNClassesMl != static_cast(mCutDirMl.size())) { + LOG(fatal) << "Mismatch in number of classes and cut directions provided for ML application: mNClassesMl: " << mNClassesMl << " classes vs. mCutDirMl: " << mCutDirMl.size() << " cut directions"; + } + if (static_cast(mLabelsCutScoresMl.size()) != mNClassesMl) { + LOG(fatal) << "Mismatch in number of labels for cut scores and number of classes provided for ML application: mNClassesMl:" << mNClassesMl << " classes vs. mLabelsCutScoresMl: " << mLabelsCutScoresMl.size() << " labels"; + } + o2::framework::LabeledArray mCutsMl(mCutsMlFlat.data(), binsNPt, mNClassesMl, mLabelsBinsMl, mLabelsCutScoresMl); + mEmMlResponse->configure(mBinsPtMl, mCutsMl, mCutDirMl, mNClassesMl); + } + if (mLoadMlModelsFromCCDB) { + ccdbApi.init(mCcdbUrl); + mEmMlResponse->setModelPathsCCDB(mOnnxFileNames, ccdbApi, mModelPathsCCDB, mTimestampCCDB); + } else { + mEmMlResponse->setModelPathsLocal(mOnnxFileNames); + } + mEmMlResponse->cacheInputFeaturesIndices(mNamesInputFeatures); + mEmMlResponse->init(); + } + + const std::span getBDTValue() const + { + return mMlBDTScores; + } + + template + bool IsConversionPointInAcceptance(TMCPhoton const& mcphoton, float convRadius) const + { + // eta cut + if (mcphoton.eta() < mMinV0Eta || mcphoton.eta() > mMaxV0Eta) { + return false; + } + + // radius cut + if (convRadius < mMinRxy || mMaxRxy < convRadius) { + return false; + } + + // line cut + if (convRadius <= std::abs(mcphoton.vz()) * std::tan(2 * std::atan(std::exp(-mMaxV0Eta))) - mMaxMarginZ) { + return false; + } + + return true; + } + // Setters void SetV0PtRange(float minPt = 0.f, float maxPt = 1e10f); void SetV0EtaRange(float minEta = -1e10f, float maxEta = 1e10f); @@ -422,6 +1103,11 @@ class V0PhotonCut : public TNamed void SetOnWwireOB(bool flag = false); void RejectITSib(bool flag = false); + void setTooCloseType(V0PhotonCut::TooCloseCuts type); + void setMinV0DistSquared(float value); + void setDeltaR(float value); + void setMinOpeningAngle(float value); + void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); void SetMinNClustersTPC(int minNClustersTPC); @@ -448,6 +1134,27 @@ class V0PhotonCut : public TNamed void SetDisableITSonly(bool flag); void SetDisableTPConly(bool flag); + void SetApplyMlCuts(bool flag = false); + void SetUse2DBinning(bool flag = true); + void SetLoadMlModelsFromCCDB(bool flag = true); + void SetNClassesMl(int nClasses); + void SetMlTimestampCCDB(int timestamp); + void SetCentralityTypeMl(CentType centType); + void SetCentrality(float cent); + void SetD_Bz(float d_bz); + void SetCcdbUrl(const std::string& url = "http://alice-ccdb.cern.ch"); + void SetCutDirMl(const std::vector& cutDirMl); + void SetMlModelPathsCCDB(const std::vector& modelPaths); + void SetMlOnnxFileNames(const std::vector& onnxFileNamesVec); + void SetLabelsBinsMl(const std::vector& labelsBins); + void SetLabelsCutScoresMl(const std::vector& labelsCutScores); + void SetBinsPtMl(const std::vector& binsPt); + void SetBinsCentMl(const std::vector& binsCent); + void SetCutsMl(const std::vector& cutsMlFlat); + void SetNamesInputFeatures(const std::vector& namesInputFeaturesVec); + + void setDoQA(bool flag = false); + private: static const std::pair> its_ib_Requirement; static const std::pair> its_ob_Requirement; @@ -468,6 +1175,37 @@ class V0PhotonCut : public TNamed bool mIsOnWwireIB{false}; bool mIsOnWwireOB{false}; bool mRejectITSib{false}; + TooCloseCuts mTooCloseType{V0PhotonCut::TooCloseCuts::kRadAndAngle}; // for TooCloseV0Cut: either squared distance between conversion points OR opening angle and deltaR + float mMinV0DistSquared{1.}; // for TooCloseV0Cut: cut value when using squared distance between conversion points + float mDeltaR{6.}; // for TooCloseV0Cut: V0PhotonCut::TooCloseCuts::kRadAndAngle when deltaR < this -> compare chi2 + float mMinOpeningAngle{0.02}; // for TooCloseV0Cut: V0PhotonCut::TooCloseCuts::kRadAndAngle when opening angle < this -> compare chi2 + mutable std::vector mRejectMask{}; + + // ML cuts + bool mApplyMlCuts{false}; + bool mUse2DBinning{true}; + bool mLoadMlModelsFromCCDB{true}; + int mTimestampCCDB{-1}; + int mNClassesMl{static_cast(o2::analysis::em_cuts_ml::NCutScores)}; + float mCent{0.f}; + float mD_Bz{0.f}; + std::string mCcdbUrl{"http://alice-ccdb.cern.ch"}; + std::vector mCutDirMl{std::vector{o2::analysis::em_cuts_ml::vecCutDir}}; + std::vector mModelPathsCCDB{std::vector{"path_ccdb/BDT_PCM/"}}; + std::vector mOnnxFileNames{std::vector{"ModelHandler_onnx_PCM.onnx"}}; + std::vector mNamesInputFeatures{std::vector{"feature1", "feature2"}}; + std::vector mLabelsBinsMl{std::vector{"bin 0", "bin 1"}}; + std::vector mLabelsCutScoresMl{std::vector{o2::analysis::em_cuts_ml::labelsCutScore}}; + std::vector mBinsPtMl{std::vector{o2::analysis::em_cuts_ml::vecBinsPt}}; + std::vector mBinsCentMl{std::vector{o2::analysis::em_cuts_ml::vecBinsCent}}; + std::vector mCutsMlFlat{std::vector{0.5}}; + o2::analysis::EmMlResponsePCM* mEmMlResponse{nullptr}; + mutable bool mIsSelectedMl{false}; + mutable std::vector mOutputML{}; + mutable std::vector mMlInputFeatures{}; + mutable std::span mMlBDTScores{}; + CentType mCentralityTypeMl{CentType::CentFT0C}; + mutable V0PhotonCandidate mV0PhotonForMl; // pid cuts float mMinTPCNsigmaEl{-5}, mMaxTPCNsigmaEl{+5}; @@ -498,7 +1236,11 @@ class V0PhotonCut : public TNamed bool mDisableITSonly{false}; bool mDisableTPConly{false}; - ClassDef(V0PhotonCut, 2); + bool mDoQA{false}; ///< flag to decide if QA should be done or not + mutable uint nAccV0PerColl{0}; ///< running number of accepted v0 photons per collision used for QA + mutable int currentCollID{-1}; ///< running collision ID of v0 photon used for QA + + ClassDef(V0PhotonCut, 5); }; #endif // PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ diff --git a/PWGEM/PhotonMeson/DataModel/EventTables.h b/PWGEM/PhotonMeson/DataModel/EventTables.h new file mode 100644 index 00000000000..05e1541493b --- /dev/null +++ b/PWGEM/PhotonMeson/DataModel/EventTables.h @@ -0,0 +1,77 @@ +// 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 EventTables.h +/// \brief This header provides the table definitions to store photon meson event tables +/// \author Marvin Hemmer (marvin.hemmer@cern.ch) - Goethe University Frankfurt + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" + +#include + +#include + +#include +#include + +#ifndef PWGEM_PHOTONMESON_DATAMODEL_EVENTTABLES_H_ +#define PWGEM_PHOTONMESON_DATAMODEL_EVENTTABLES_H_ + +namespace o2::aod +{ + +namespace pmevsel +{ +// Event selection criteria. See O2Physics/Common/CCDB/EventSelectionParams.h +enum EventSelectionFlags { + kIsTriggerTVX = 0, // FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level + kNoITSROFrameBorder, // bunch crossing is far from ITS RO Frame border + kNoTimeFrameBorder, // bunch crossing is far from Time Frame borders + kNoSameBunchPileup, // reject collisions in case of pileup with another collision in the same foundBC + kIsGoodZvtxFT0vsPV, // small difference between z-vertex from PV and from FT0 + kIsVertexITSTPC, // at least one ITS-TPC track (reject vertices built from ITS-only tracks) + kIsVertexTOFmatched, // at least one of vertex contributors is matched to TOF + kIsVertexTRDmatched, // at least one of vertex contributors is matched to TRD + kNoCollInTimeRangeNarrow, // no other collisions in specified time range (narrower than Strict) + kNoCollInTimeRangeStrict, // no other collisions in specified time range + kNoCollInTimeRangeStandard, // no other collisions in specified time range with per-collision multiplicity above threshold + kNoCollInRofStrict, // no other collisions in this Readout Frame + kNoCollInRofStandard, // no other collisions in this Readout Frame with per-collision multiplicity above threshold + kNoHighMultCollInPrevRof, // veto an event if FT0C amplitude in previous ITS ROF is above threshold + kIsGoodITSLayer3, // number of inactive chips on ITS layer 3 is below maximum allowed value + kIsGoodITSLayer0123, // numbers of inactive chips on ITS layers 0-3 are below maximum allowed values + kIsGoodITSLayersAll, // numbers of inactive chips on all ITS layers are below maximum allowed values + kNsel // counter +}; + +DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 32); //! Bitmask of selection flags +DECLARE_SOA_DYNAMIC_COLUMN(Sel8, sel8, [](uint32_t selection_bit) -> bool { return (selection_bit & BIT(o2::aod::pmevsel::kIsTriggerTVX)) && (selection_bit & BIT(o2::aod::pmevsel::kNoTimeFrameBorder)) && (selection_bit & BIT(o2::aod::pmevsel::kNoITSROFrameBorder)); }); + +} // namespace pmevsel + +namespace pmevent +{ +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); + +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)); }); +} // namespace pmevent + +DECLARE_SOA_TABLE(PMEvents, "AOD", "PMEVENT", //! Main event information table + o2::soa::Index<>, pmevent::CollisionId, bc::RunNumber, bc::GlobalBC, evsel::Selection, evsel::Rct, timestamp::Timestamp, + collision::PosZ, + collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, pmevent::Sel8); + +using PMEvent = PMEvents::iterator; + +} // namespace o2::aod + +#endif // PWGEM_PHOTONMESON_DATAMODEL_EVENTTABLES_H_ diff --git a/PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h b/PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h index 15e66f8bd96..79219f35fa4 100644 --- a/PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h +++ b/PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h @@ -21,8 +21,7 @@ #include #include - -#include +#include #include #include diff --git a/PWGEM/PhotonMeson/DataModel/bcWiseTables.h b/PWGEM/PhotonMeson/DataModel/bcWiseTables.h index efd3f9a2007..4f64bf08fb0 100644 --- a/PWGEM/PhotonMeson/DataModel/bcWiseTables.h +++ b/PWGEM/PhotonMeson/DataModel/bcWiseTables.h @@ -19,8 +19,10 @@ #ifndef PWGEM_PHOTONMESON_DATAMODEL_BCWISETABLES_H_ #define PWGEM_PHOTONMESON_DATAMODEL_BCWISETABLES_H_ -#include "Framework/AnalysisDataModel.h" +#include +#include +#include #include namespace o2::aod diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index 5fee7952cfd..9ef4b45727b 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -14,6 +14,7 @@ /// \author D. Sekihata, daiki.sekihata@cern.ch; Marvin Hemmer (marvin.hemmer@cern.ch) - Goethe University Frankfurt #include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/CaloClusters.h" @@ -98,25 +99,25 @@ using V0LegMCLabel = V0LegMCLabels::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 -// 3. EMEMCClusterMCLabels: EM MC particle ID of largest contributor to cluster +// 3. EMEMCClusterMCLabels: Vector of EM MC particle ID of largest contributor to cluster namespace emcclustermclabel { -DECLARE_SOA_ARRAY_INDEX_COLUMN(EMMCParticle, emmcparticle); //! +DECLARE_SOA_ARRAY_INDEX_COLUMN(McParticle, emmcparticle) //! } // namespace emcclustermclabel // NOTE: MC labels. This table has one vector of global mc particle ids for each reconstructed emc cluster (joinable with emccluster table) DECLARE_SOA_TABLE(EMCClusterMCLabels, "AOD", "EMCClsMCLABEL", //! - emcclustermclabel::EMMCParticleIds); + emcclustermclabel::McParticleIds); using EMCClusterMCLabel = EMCClusterMCLabels::iterator; namespace ememcclustermclabel { -DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! +DECLARE_SOA_ARRAY_INDEX_COLUMN(EMMCParticle, emmcparticle); //! } // namespace ememcclustermclabel -// NOTE: MC labels. This table has one entry for each reconstructed emc cluster (joinable with emccluster table) +// NOTE: MC labels. This table has a vector of entries for each reconstructed emc cluster (joinable with emccluster table) DECLARE_SOA_TABLE(EMEMCClusterMCLabels, "AOD", "EMEMCClsMCLABEL", //! - ememcclustermclabel::EMMCParticleId); + ememcclustermclabel::EMMCParticleIds); using EMEMCClusterMCLabel = EMEMCClusterMCLabels::iterator; namespace v0leg @@ -253,7 +254,7 @@ 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 +DECLARE_SOA_TABLE(EMEventsNgPCM, "AOD", "EMEVENTNGPCM", emevent::NgPCM); // joinable to EMEvents or o2::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 @@ -263,6 +264,7 @@ using EMEventWeight = EMEventsWeight::iterator; namespace v0photonkf { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(V0Id, v0Id, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, V0Legs, "_Pos"); //! @@ -341,8 +343,9 @@ using V0PhotonsKF = V0PhotonsKF_001; // iterators using V0PhotonKF = V0PhotonsKF::iterator; -DECLARE_SOA_TABLE(V0KFEMEventIds, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId); // To be joined with V0PhotonsKF table at analysis level. -// iterators +DECLARE_SOA_TABLE(V0KFEMEventIds_000, "AOD", "V0KFEMEVENTID", v0photonkf::EMEventId); // To be joined with V0PhotonsKF table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(V0KFEMEventIds_001, "AOD", "V0KFEMEVENTID", 1, v0photonkf::PMEventId); // To be joined with V0PhotonsKF table at analysis level. +using V0KFEMEventIds = V0KFEMEventIds_001; using V0KFEMEventId = V0KFEMEventIds::iterator; DECLARE_SOA_TABLE(V0PhotonsKFCov, "AOD", "V0PHOTONKFCOV", //! To be joined with V0PhotonsKF table at analysis level. @@ -416,19 +419,32 @@ using EMPrimaryElectronsFromDalitz = EMPrimaryElectronsFromDalitz_001; // iterators using EMPrimaryElectronFromDalitz = EMPrimaryElectronsFromDalitz::iterator; -namespace v0photonsphiv +namespace emprimaryelectronda +{ +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! +} // namespace emprimaryelectronda + +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronDaEMEventIds_001, "AOD", "PRMELDAEVENTID", 1, emprimaryelectronda::PMEventId); // To be joined with EMPrimaryElectronsFromDalitz table at analysis level. +using EMPrimaryElectronDaEMEventIds = EMPrimaryElectronDaEMEventIds_001; +using EMPrimaryElectronDaEMEventId = EMPrimaryElectronDaEMEventIds::iterator; + +namespace v0photonsphivpsi { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(PhiV, phiv, float); //! -} // namespace v0photonsphiv -DECLARE_SOA_TABLE(V0PhotonsPhiV, "AOD", "V0PHOTONPHIV", //! - o2::soa::Index<>, v0photonsphiv::PhiV); +DECLARE_SOA_COLUMN(PsiPair, psipair, float); +} // namespace v0photonsphivpsi +DECLARE_SOA_TABLE(V0PhotonsPhiVPsi, "AOD", "V0PHOTONPHIVPSI", //! + o2::soa::Index<>, v0photonsphivpsi::PhiV, v0photonsphivpsi::PsiPair); // iterators -using V0PhotonsPhiV = V0PhotonsPhiV; +using V0PhotonsPhiVPsi = V0PhotonsPhiVPsi; namespace dalitzee { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, EMPrimaryElectrons, "_Pos"); //! DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, EMPrimaryElectrons, "_Neg"); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! @@ -450,13 +466,15 @@ DECLARE_SOA_TABLE(DalitzEEs, "AOD", "DALITZEE", //! // iterators using DalitzEE = DalitzEEs::iterator; -DECLARE_SOA_TABLE(DalitzEEEMEventIds, "AOD", "EEEMEVENTID", dalitzee::EMEventId); // To be joined with DalitzEEs table at analysis level. -// iterators +DECLARE_SOA_TABLE(DalitzEEEMEventIds_000, "AOD", "EEEMEVENTID", dalitzee::EMEventId); // To be joined with DalitzEEs table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(DalitzEEEMEventIds_001, "AOD", "EEEMEVENTID", 1, dalitzee::PMEventId); // To be joined with DalitzEEs table at analysis level. +using DalitzEEEMEventIds = DalitzEEEMEventIds_001; using DalitzEEEMEventId = DalitzEEEMEventIds::iterator; namespace pwgem::photon::swtinfo { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_INDEX_COLUMN_FULL(TriggerV0PhotonHighPt, triggerV0PhotonHighPt, int, V0PhotonsKF, "_TriggerV0PhotonHighPt"); //! high pT PCM trigger is fired by this v0 photon DECLARE_SOA_INDEX_COLUMN_FULL(TriggerV0PhotonPair, triggerV0PhotonPair, int, V0PhotonsKF, "_TriggerV0PhotonPair"); //! PCM+EE trigger is fired by this v0 photon and dielectron @@ -556,6 +574,7 @@ DECLARE_SOA_TABLE(McGammasTrue, "AOD", "MCGATRUE", namespace skimmedcluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! 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) @@ -572,6 +591,7 @@ DECLARE_SOA_COLUMN(NLM, nlm, int); //! numbe namespace emccluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_COLUMN(CoreEnergy, coreEnergy, float); //! cluster core energy (GeV) DECLARE_SOA_COLUMN(Time, time, float); //! cluster time (ns) DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag to mark cluster as exotic @@ -628,13 +648,15 @@ DECLARE_SOA_TABLE(EmEmcMTracks, "AOD", "EMEMCMTRACK", //! DECLARE_SOA_TABLE(EmEmcMSTracks, "AOD", "EMEMCMSTRACK", //! trackmatching::EmEmcClusterId, emctm::DeltaPhi, emctm::DeltaEta, emctm::TrackP, emctm::TrackPt); -DECLARE_SOA_TABLE(EMCEMEventIds, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. -// iterators +DECLARE_SOA_TABLE(EMCEMEventIds_000, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(EMCEMEventIds_001, "AOD", "EMCEMEVENTID", 1, emccluster::PMEventId); // To be joined with SkimEMCClusters table at analysis level. +using EMCEMEventIds = EMCEMEventIds_001; using EMCEMEventId = EMCEMEventIds::iterator; namespace phoscluster { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_INDEX_COLUMN(PMEvent, pmevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(MatchedTrack, matchedTrack, int, Tracks, "_Matched"); //! matched track index DECLARE_SOA_COLUMN(X, x, float); //! cluster hit position in ALICE global coordinate DECLARE_SOA_COLUMN(Y, y, float); //! cluster hit position in ALICE global coordinate @@ -669,8 +691,9 @@ DECLARE_SOA_TABLE(PHOSClusters, "AOD", "PHOSCLUSTERS", //! phoscluster::Phi); using PHOSCluster = PHOSClusters::iterator; -DECLARE_SOA_TABLE(PHOSEMEventIds, "AOD", "PHOSEMEVENTID", phoscluster::EMEventId); // To be joined with PHOSClusters table at analysis level. -// iterators +DECLARE_SOA_TABLE(PHOSEMEventIds_000, "AOD", "PHOSEMEVENTID", phoscluster::EMEventId); // To be joined with PHOSClusters table at analysis level. +DECLARE_SOA_TABLE_VERSIONED(PHOSEMEventIds_001, "AOD", "PHOSEMEVENTID", 1, phoscluster::PMEventId); // To be joined with PHOSClusters table at analysis level. +using PHOSEMEventIds = PHOSEMEventIds_001; using PHOSEMEventId = PHOSEMEventIds::iterator; namespace caloextra @@ -682,6 +705,28 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Cell, cell, int, Calos, ""); //! r DECLARE_SOA_TABLE(SkimEMCCells, "AOD", "SKIMEMCCELLS", //! table of link between skimmed EMCal clusters and their cells o2::soa::Index<>, caloextra::ClusterId, caloextra::CellId); //! using SkimEMCCell = SkimEMCCells::iterator; + +namespace nonlin +{ +DECLARE_SOA_COLUMN(CorrE, corrE, float); //! non lin corrected energy +DECLARE_SOA_COLUMN(CorrP, corrP, float); //! non lin corrected momentum +DECLARE_SOA_COLUMN(CorrPt, corrPt, float); //! non lin corrected transverse momentum +} // namespace nonlin + +DECLARE_SOA_TABLE(NonLinV0s, "AOD", "NONLINV0", //! table of non lin corrected values for V0 Photons (so far only pt) + nonlin::CorrPt); //! + +DECLARE_SOA_TABLE(NonLinEmcClusters, "AOD", "NONLINEMCCLUSTER", //! table of non lin corrected values for EMCal Photons (so far only E and pT) + nonlin::CorrE, nonlin::CorrPt); //! + +namespace v0photonMBweights +{ +DECLARE_SOA_COLUMN(OmegaMBWeight, omegaMBWeight, float); +} + +DECLARE_SOA_TABLE(V0PhotonOmegaMBWeights, "AOD", "V0PHOTONMBW", v0photonMBweights::OmegaMBWeight); // store MB weights. To be joined with V0PhotonsKF table at analysis level. + +using V0PhotonOmegaMBWeight = V0PhotonOmegaMBWeights::iterator; } // namespace o2::aod #endif // PWGEM_PHOTONMESON_DATAMODEL_GAMMATABLES_H_ diff --git a/PWGEM/PhotonMeson/DataModel/mcV0Tables.h b/PWGEM/PhotonMeson/DataModel/mcV0Tables.h index 16e8ee911ba..95b560a7501 100644 --- a/PWGEM/PhotonMeson/DataModel/mcV0Tables.h +++ b/PWGEM/PhotonMeson/DataModel/mcV0Tables.h @@ -15,7 +15,9 @@ #ifndef PWGEM_PHOTONMESON_DATAMODEL_MCV0TABLES_H_ #define PWGEM_PHOTONMESON_DATAMODEL_MCV0TABLES_H_ -#include "Framework/ASoA.h" +#include + +#include namespace o2::aod { diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index a4cf2e6b566..99bccdf5c49 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/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(skimmer-gamma-conversion SOURCES skimmerGammaConversion.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle @@ -21,7 +23,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 O2Physics::TPCDriftManager + PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore O2Physics::MLCore KFParticle::KFParticle O2Physics::TPCDriftManager COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(create-pcm @@ -63,3 +65,18 @@ o2physics_add_dpl_workflow(skimmer-dalitz-ee SOURCES skimmerDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(non-lin-producer + SOURCES nonLinProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pm-qvector-dummy-otf + SOURCES pmQvectorDummyOtf.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(material-budget-weights + SOURCES materialBudgetWeights.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::CCDB ROOT::Hist ROOT::Core + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt new file mode 100644 index 00000000000..63a2f1814c5 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/CMakeLists.txt @@ -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. + + +o2physics_add_dpl_workflow(v0photonid-converter1 + SOURCES v0photonIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(emcid-converter1 + SOURCES emcIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(phosid-converter1 + SOURCES phosIdConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(converter-emevent-pmevent + SOURCES converterEmeventPmevent.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx new file mode 100644 index 00000000000..cd159115d4f --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/converterEmeventPmevent.cxx @@ -0,0 +1,53 @@ +// 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 converterEmeventPmevent.cxx +/// \author Marvin Hemmer +/// \brief converter for EMEvents_004 to PMEvents + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct ConverterEmeventPmevent { + Produces pmEvents; + + void process(EMEvents_004 const& collisions) + { + for (const auto& collision : collisions) { + pmEvents( + collision.collisionId(), + collision.runNumber(), + collision.globalBC(), + collision.selection_raw(), + collision.rct_raw(), + collision.timestamp(), + collision.posZ(), + collision.numContrib(), + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange()); + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx similarity index 55% rename from PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx rename to PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx index 6f0dfff7c2f..9c7027076de 100644 --- a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx +++ b/PWGEM/PhotonMeson/TableProducer/Converters/emcIdConverter1.cxx @@ -8,27 +8,31 @@ // 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 photons and makes pairs for neutral mesons analyses. -// Please write to: daiki.sekihata@cern.ch -#include "PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct emcIdConverter1 { + Produces id_001; + + void process(aod::EMCEMEventIds_000 const& ids) + { + for (const auto& id : ids) { + id_001(id.emeventId()); + } // end of id loop + } +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"diphoton-hadron-mpc-pcmpcm"}), - }; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"emcid-converter1"})}; } diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx new file mode 100644 index 00000000000..d6d188abb96 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/phosIdConverter1.cxx @@ -0,0 +1,38 @@ +// 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 "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct phosIdConverter1 { + Produces id_001; + + void process(aod::PHOSEMEventIds_000 const& ids) + { + for (const auto& id : ids) { + id_001(id.emeventId()); + } // end of id loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"phosid-converter1"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx b/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx new file mode 100644 index 00000000000..c3b82a8b204 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/Converters/v0photonIdConverter1.cxx @@ -0,0 +1,38 @@ +// 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 "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct v0photonIdConverter1 { + Produces id_001; + + void process(aod::V0KFEMEventIds_000 const& ids) + { + for (const auto& id : ids) { + id_001(id.emeventId()); + } // end of id loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"v0photonid-converter1"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx index 885a2e85a38..0bfbe804e31 100644 --- a/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/associateMCinfoPhoton.cxx @@ -16,16 +16,36 @@ /// \author Daiki Sekihata (daiki.sekihata@cern.ch) /// +#include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include #include +#include #include using namespace o2; @@ -33,11 +53,12 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::constants::physics; using MyCollisionsMC = soa::Join; using TracksMC = soa::Join; using FwdTracksMC = soa::Join; -using MyEMCClusters = soa::Join; +using MyEMCClusters = soa::Join; struct AssociateMCInfoPhoton { enum SubSystem { @@ -60,6 +81,7 @@ struct AssociateMCInfoPhoton { 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"}; Configurable requireGammaGammaDecay{"requireGammaGammaDecay", false, "require gamma gamma decay for generated pi0 and eta meson"}; + Configurable cfg_max_eta_photon{"cfg_max_eta_gamma", 0.8, "max eta for photons at PV"}; HistogramRegistry registry{"EMMCEvent"}; @@ -71,27 +93,29 @@ struct AssociateMCInfoPhoton { // !!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++) { + for (int i = 0; i < 2; i++) { // o2-linter: disable=magic-number (just numbers for binning) 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++) { + for (int i = 2; i < 51; i++) { // o2-linter: disable=magic-number (just numbers for binning) 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++) { + for (int i = 51; i < 61; i++) { // o2-linter: disable=magic-number (just numbers for binning) 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++) { + for (int i = 61; i < 72; i++) { // o2-linter: disable=magic-number (just numbers for binning) ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c } const AxisSpec axisPt{ptbins, "p_{T} (GeV/c)"}; const AxisSpec axisRapidity{{0.0, +0.8, +0.9}, "rapidity |y|"}; - static constexpr std::string_view ParticleNames[9] = { + static constexpr uint NParticleNames = 9; + static constexpr std::string_view ParticleNames[NParticleNames] = { "Gamma", "Pi0", "Eta", "Omega", "Phi", "ChargedPion", "ChargedKaon", "K0S", "Lambda"}; - for (int i = 0; i < 9; i++) { + for (uint i = 0; i < NParticleNames; i++) { registry.add(Form("Generated/h2PtY_%s", ParticleNames[i].data()), Form("Generated %s", ParticleNames[i].data()), kTH2F, {axisPt, axisRapidity}, true); + registry.add(Form("Generated/h2PtY_Accepted_%s", ParticleNames[i].data()), Form("Generated %s", ParticleNames[i].data()), kTH2F, {axisPt, axisRapidity}, true); } // reserve space for generated vectors if that process enabled @@ -113,7 +137,7 @@ struct AssociateMCInfoPhoton { std::vector genEta; // primary, pt, y template - void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const&, aod::McParticles const& mcParticles, TTracks const& o2tracks, TFwdTracks const&, TPCMs const& v0photons, TPCMLegs const&, TPHOSs const&, TEMCs const& emcclusters, TEMPrimaryElectrons const& emprimaryelectrons) + void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles, TTracks const& o2tracks, TFwdTracks const&, TPCMs const& v0photons, TPCMLegs const& legs, TPHOSs const&, TEMCs const& emcclusters, TEMPrimaryElectrons const& emprimaryelectrons) { // temporary variables used for the indexing of the skimmed MC stack std::map fNewLabels; @@ -124,6 +148,21 @@ struct AssociateMCInfoPhoton { int fCounters[2] = {0, 0}; //! [0] - particle counter, [1] - event counter auto hBinFinder = registry.get(HIST("Generated/h2PtY_Gamma")); + // collision iterator from EMCal cluster + auto collisionIter = collisions.begin(); + + // mc particle iterator for photons + auto mcPhoton = mcParticles.begin(); + + // mc particles iterator for mother + auto motherParticle = mcParticles.begin(); + + // mc particles iterator for mother and other mc particles + auto mcParticleIter = mcParticles.begin(); + + // mc collision iter + auto mcCollisionIter = mcCollisions.begin(); + for (const auto& collision : collisions) { registry.fill(HIST("hEventCounter"), 1); @@ -142,29 +181,44 @@ struct AssociateMCInfoPhoton { std::fill(genPi0.begin(), genPi0.end(), 0); std::fill(genEta.begin(), genEta.end(), 0); - auto mcCollision = collision.mcCollision(); + mcCollisionIter.setCursor(collision.mcCollisionId()); // store mc particles - auto groupedMcParticles = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); + auto groupedMcParticles = mcParticles.sliceBy(perMcCollision, mcCollisionIter.globalIndex()); for (const auto& mcParticle : groupedMcParticles) { // store necessary information for denominator of efficiency if ((mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator()) && std::fabs(mcParticle.y()) < 0.9f && mcParticle.pt() < 20.f) { auto binNumber = hBinFinder->FindBin(mcParticle.pt(), std::fabs(mcParticle.y())); // caution: pack + + bool isMesonAccepted = false; + if (mcParticle.has_daughters()) { + auto lDaughters = mcParticle.daughters_as(); + + if (areTwoPhotonDaughtersAccepted(lDaughters, cfg_max_eta_photon)) { + isMesonAccepted = true; + } + } switch (std::abs(mcParticle.pdgCode())) { - case 22: + case PDG_t::kGamma: registry.fill(HIST("Generated/h2PtY_Gamma"), mcParticle.pt(), std::fabs(mcParticle.y())); genGamma[binNumber]++; break; - case 111: + case PDG_t::kPi0: if (requireGammaGammaDecay && !isGammaGammaDecay(mcParticle, mcParticles)) continue; registry.fill(HIST("Generated/h2PtY_Pi0"), mcParticle.pt(), std::fabs(mcParticle.y())); genPi0[binNumber]++; + if (isMesonAccepted) { + registry.fill(HIST("Generated/h2PtY_Accepted_Pi0"), mcParticle.pt(), std::fabs(mcParticle.y())); + } break; - case 221: + case Pdg::kEta: if (requireGammaGammaDecay && !isGammaGammaDecay(mcParticle, mcParticles)) continue; registry.fill(HIST("Generated/h2PtY_Eta"), mcParticle.pt(), std::fabs(mcParticle.y())); genEta[binNumber]++; + if (isMesonAccepted) { + registry.fill(HIST("Generated/h2PtY_Accepted_Eta"), mcParticle.pt(), std::fabs(mcParticle.y())); + } break; default: break; @@ -173,15 +227,15 @@ struct AssociateMCInfoPhoton { } // 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]; + if (!(fEventLabels.find(mcCollisionIter.globalIndex()) != fEventLabels.end())) { + mcevents(mcCollisionIter.globalIndex(), mcCollisionIter.generatorsID(), mcCollisionIter.posX(), mcCollisionIter.posY(), mcCollisionIter.posZ(), mcCollisionIter.impactParameter(), mcCollisionIter.eventPlaneAngle()); + fEventLabels[mcCollisionIter.globalIndex()] = fCounters[1]; fCounters[1]++; binnedGenPt(genGamma, genPi0, genEta); } // LOGF(info, "collision.globalIndex() = %d , mceventlabels.lastIndex() = %d", collision.globalIndex(), mceventlabels.lastIndex()); - mceventlabels(fEventLabels.find(mcCollision.globalIndex())->second, collision.mcMask()); + mceventlabels(fEventLabels.find(mcCollisionIter.globalIndex())->second, collision.mcMask()); for (const auto& mcParticle : groupedMcParticles) { // store necessary information for denominator of efficiency if (mcParticle.pt() < 1e-3 || std::fabs(mcParticle.vz()) > 250 || std::sqrt(std::pow(mcParticle.vx(), 2) + std::pow(mcParticle.vy(), 2)) > max_rxy_gen) { @@ -195,30 +249,30 @@ struct AssociateMCInfoPhoton { // Note that pi0 from weak decay gives producedByGenerator() = false // LOGF(info,"index = %d , mc track pdg = %d , producedByGenerator = %d , isPhysicalPrimary = %d", mcParticle.index(), mcParticle.pdgCode(), mcParticle.producedByGenerator(), mcParticle.isPhysicalPrimary()); - if (std::abs(pdg) == 11 && mcParticle.has_mothers() && !(mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator())) { // secondary electrons. i.e. ele/pos from photon conversions. - int motherid = mcParticle.mothersIds()[0]; // first mother index - auto mp = mcParticles.iteratorAt(motherid); + if (std::abs(pdg) == PDG_t::kElectron && mcParticle.has_mothers() && !(mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator())) { // secondary electrons. i.e. ele/pos from photon conversions. + int motherid = mcParticle.mothersIds()[0]; // first mother index + motherParticle.setCursor(motherid); if (std::sqrt(std::pow(mcParticle.vx(), 2) + std::pow(mcParticle.vy(), 2)) < std::fabs(mcParticle.vz()) * std::tan(2 * std::atan(std::exp(-max_eta_gen_secondary))) - margin_z_gen) { continue; } - if (mp.pdgCode() == 22 && (mp.isPhysicalPrimary() || mp.producedByGenerator()) && std::fabs(mp.eta()) < max_eta_gen_secondary) { + if (motherParticle.pdgCode() == PDG_t::kGamma && (motherParticle.isPhysicalPrimary() || motherParticle.producedByGenerator()) && std::fabs(motherParticle.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(mcParticle.globalIndex()) != fNewLabels.end())) { // store electron information. !!Not photon!! fNewLabels[mcParticle.globalIndex()] = fCounters[0]; fNewLabelsReversed[fCounters[0]] = mcParticle.globalIndex(); // fMCFlags[mcParticle.globalIndex()] = mcflags; - fEventIdx[mcParticle.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fEventIdx[mcParticle.globalIndex()] = fEventLabels.find(mcCollisionIter.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; + if (!(fNewLabels.find(motherParticle.globalIndex()) != fNewLabels.end())) { // store conversion photon + fNewLabels[motherParticle.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = motherParticle.globalIndex(); + // fMCFlags[motherParticle.globalIndex()] = mcflags; + fEventIdx[motherParticle.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second; fCounters[0]++; } } @@ -227,59 +281,66 @@ struct AssociateMCInfoPhoton { } // end of rec. collision loop - if constexpr (static_cast(system & kPCM)) { + if constexpr (static_cast(system & kPCM) && !std::is_same_v) { + // electron and positron iterators from the TPCMLegs table as well as the o2Track table + auto ele = legs.begin(); + auto pos = legs.begin(); + + auto o2TrackEle = o2tracks.begin(); + auto o2TrackPos = o2tracks.begin(); + auto o2TrackIter = o2tracks.begin(); for (const auto& v0 : v0photons) { - auto collisionFromV0 = collisions.iteratorAt(v0.collisionId()); - if (!collisionFromV0.has_mcCollision()) { + collisionIter.setCursor(v0.collisionId()); + if (!collisionIter.has_mcCollision()) { continue; } - auto mcCollisionFromV0 = collisionFromV0.mcCollision(); + mcCollisionIter.setCursor(collisionIter.mcCollisionId()); - auto ele = v0.template negTrack_as(); - auto pos = v0.template posTrack_as(); + ele.setCursor(v0.negTrackId()); + pos.setCursor(v0.posTrackId()); - auto o2TrackEle = o2tracks.iteratorAt(pos.trackId()); - auto o2TrackPos = o2tracks.iteratorAt(ele.trackId()); + o2TrackEle.setCursor(ele.trackId()); + o2TrackPos.setCursor(pos.trackId()); if (!o2TrackEle.has_mcParticle() || !o2TrackPos.has_mcParticle()) { continue; // If no MC particle is found, skip the v0 } for (const auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! - auto o2track = o2tracks.iteratorAt(leg.trackId()); - auto mcParticle = o2track.template mcParticle_as(); - // LOGF(info, "mcParticle.globalIndex() = %d, mcParticle.index() = %d", mcParticle.globalIndex(), mcParticle.index()); // these are exactly the same. + o2TrackIter.setCursor(leg.trackId()); + mcParticleIter.setCursor(o2TrackIter.mcParticleId()); + // LOGF(info, "mcParticleIter.globalIndex() = %d, mcParticleIter.index() = %d", mcParticleIter.globalIndex(), mcParticleIter.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(mcParticle.globalIndex()) != fNewLabels.end())) { - fNewLabels[mcParticle.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mcParticle.globalIndex(); - // fMCFlags[mcParticle.globalIndex()] = mcflags; - fEventIdx[mcParticle.globalIndex()] = fEventLabels.find(mcCollisionFromV0.globalIndex())->second; + if (!(fNewLabels.find(mcParticleIter.globalIndex()) != fNewLabels.end())) { + fNewLabels[mcParticleIter.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mcParticleIter.globalIndex(); + // fMCFlags[mcParticleIter.globalIndex()] = mcflags; + fEventIdx[mcParticleIter.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second; fCounters[0]++; } - v0legmclabels(fNewLabels.find(mcParticle.index())->second, o2track.mcMask()); + v0legmclabels(fNewLabels.find(mcParticleIter.index())->second, o2TrackIter.mcMask()); // Next, store mother-chain of this reconstructed track. int motherid = -999; // first mother index - if (mcParticle.has_mothers()) { - motherid = mcParticle.mothersIds()[0]; // first mother index + if (mcParticleIter.has_mothers()) { + motherid = mcParticleIter.mothersIds()[0]; // first mother index } while (motherid > -1) { if (motherid < mcParticles.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcParticles.iteratorAt(motherid); + motherParticle.setCursor(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(mcCollisionFromV0.globalIndex())->second; + if (!(fNewLabels.find(motherParticle.globalIndex()) != fNewLabels.end())) { + fNewLabels[motherParticle.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = motherParticle.globalIndex(); + // fMCFlags[motherParticle.globalIndex()] = mcflags; + fEventIdx[motherParticle.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second; fCounters[0]++; } - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index + if (motherParticle.has_mothers()) { + motherid = motherParticle.mothersIds()[0]; // first mother index } else { motherid = -999; } @@ -292,50 +353,51 @@ struct AssociateMCInfoPhoton { } if constexpr (static_cast(system & kElectron)) { + auto o2TrackIter = o2tracks.begin(); // auto emprimaryelectrons_coll = emprimaryelectrons.sliceBy(perCollisionEl, collision.globalIndex()); for (const auto& emprimaryelectron : emprimaryelectrons) { - auto collisionFromEl = collisions.iteratorAt(emprimaryelectron.collisionId()); - if (!collisionFromEl.has_mcCollision()) { + collisionIter.setCursor(emprimaryelectron.collisionId()); + if (!collisionIter.has_mcCollision()) { continue; } - auto mcCollisionFromEl = collisionFromEl.mcCollision(); + mcCollisionIter.setCursor(collisionIter.mcCollisionId()); - auto o2track = o2tracks.iteratorAt(emprimaryelectron.trackId()); - if (!o2track.has_mcParticle()) { + o2TrackIter.setCursor(emprimaryelectron.trackId()); + if (!o2TrackIter.has_mcParticle()) { continue; // If no MC particle is found, skip the dilepton } - auto mcParticle = o2track.template mcParticle_as(); + mcParticleIter.setCursor(o2TrackIter.mcParticleId()); // 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(mcParticle.globalIndex()) != fNewLabels.end())) { - fNewLabels[mcParticle.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mcParticle.globalIndex(); - // fMCFlags[mcParticle.globalIndex()] = mcflags; - fEventIdx[mcParticle.globalIndex()] = fEventLabels.find(mcCollisionFromEl.globalIndex())->second; + if (!(fNewLabels.find(mcParticleIter.globalIndex()) != fNewLabels.end())) { + fNewLabels[mcParticleIter.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mcParticleIter.globalIndex(); + // fMCFlags[mcParticleIter.globalIndex()] = mcflags; + fEventIdx[mcParticleIter.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second; fCounters[0]++; } - emprimaryelectronmclabels(fNewLabels.find(mcParticle.index())->second, o2track.mcMask()); + emprimaryelectronmclabels(fNewLabels.find(mcParticleIter.index())->second, o2TrackIter.mcMask()); // Next, store mother-chain of this reconstructed track. int motherid = -999; // first mother index - if (mcParticle.has_mothers()) { - motherid = mcParticle.mothersIds()[0]; // first mother index + if (mcParticleIter.has_mothers()) { + motherid = mcParticleIter.mothersIds()[0]; // first mother index } while (motherid > -1) { if (motherid < mcParticles.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcParticles.iteratorAt(motherid); + motherParticle.setCursor(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(mcCollisionFromEl.globalIndex())->second; + if (!(fNewLabels.find(motherParticle.globalIndex()) != fNewLabels.end())) { + fNewLabels[motherParticle.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = motherParticle.globalIndex(); + // fMCFlags[motherParticle.globalIndex()] = mcflags; + fEventIdx[motherParticle.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second; fCounters[0]++; } - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index + if (motherParticle.has_mothers()) { + motherid = motherParticle.mothersIds()[0]; // first mother index } else { motherid = -999; } @@ -350,61 +412,74 @@ struct AssociateMCInfoPhoton { if constexpr (static_cast(system & kEMC)) { // for emc photons // auto ememcclusters_coll = emcclusters.sliceBy(perCollisionEMC, collision.globalIndex()); for (const auto& emccluster : emcclusters) { - auto collisionFromEMC = collisions.iteratorAt(emccluster.collisionId()); - if (!collisionFromEMC.has_mcCollision()) { + collisionIter.setCursor(emccluster.collisionId()); + if (!collisionIter.has_mcCollision()) { continue; } - auto mcCollisionFromEMC = collisionFromEMC.mcCollision(); - - auto mcphoton = mcParticles.iteratorAt(emccluster.emmcparticleIds()[0]); + mcCollisionIter.setCursor(collisionIter.mcCollisionId()); - // 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(mcCollisionFromEMC.globalIndex())->second; - fCounters[0]++; + // TODO: test + if (emccluster.emmcparticleIds().size() <= 0) { + continue; } - ememcclustermclabels(fNewLabels.find(mcphoton.index())->second); + std::vector vEmcMcParticleIds; - // 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 < mcParticles.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcParticles.iteratorAt(motherid); + vEmcMcParticleIds.reserve(emccluster.emmcparticleIds().size()); - // 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(mcCollisionFromEMC.globalIndex())->second; - fCounters[0]++; - } + for (const auto& emcParticleId : emccluster.emmcparticleIds()) { + mcPhoton.setCursor(emcParticleId); - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index + // 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(mcCollisionIter.globalIndex())->second; + fCounters[0]++; + } + vEmcMcParticleIds.emplace_back(fNewLabels.find(mcPhoton.index())->second); + // 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 < mcParticles.size()) { // protect against bad mother indices. why is this needed? + motherParticle.setCursor(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(motherParticle.globalIndex()) != fNewLabels.end())) { + fNewLabels[motherParticle.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = motherParticle.globalIndex(); + fEventIdx[motherParticle.globalIndex()] = fEventLabels.find(mcCollisionIter.globalIndex())->second; + fCounters[0]++; + } + + if (motherParticle.has_mothers()) { + motherid = motherParticle.mothersIds()[0]; // first mother index + } else { + motherid = -999; + } } else { motherid = -999; } - } else { - motherid = -999; - } - } // end of mother chain loop + } // end of mother chain loop + + } // end of loop over mc particles of the current emc cluster + ememcclustermclabels(vEmcMcParticleIds); } // 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 mcParticle = mcParticles.iteratorAt(oldLabel); + mcParticleIter.setCursor(oldLabel); // uint16_t mcflags = fMCFlags.find(oldLabel)->second; std::vector mothers; - if (mcParticle.has_mothers()) { - for (const auto& m : mcParticle.mothersIds()) { + if (mcParticleIter.has_mothers()) { + for (const auto& m : mcParticleIter.mothersIds()) { if (m < mcParticles.size()) { // protect against bad mother indices if (fNewLabels.find(m) != fNewLabels.end()) { mothers.push_back(fNewLabels.find(m)->second); @@ -418,9 +493,9 @@ struct AssociateMCInfoPhoton { // Note that not all daughters from the original table are preserved in the skimmed MC stack std::vector daughters; - if (mcParticle.has_daughters()) { - // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mcParticle.pdgCode(), mcParticle.daughtersIds()[0], mcParticle.daughtersIds()[1], mcParticle.daughtersIds()[1] -mcParticle.daughtersIds()[0] +1); - for (int d = mcParticle.daughtersIds()[0]; d <= mcParticle.daughtersIds()[1]; ++d) { + if (mcParticleIter.has_daughters()) { + // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mcParticleIter.pdgCode(), mcParticleIter.daughtersIds()[0], mcParticleIter.daughtersIds()[1], mcParticleIter.daughtersIds()[1] -mcParticleIter.daughtersIds()[0] +1); + for (int d = mcParticleIter.daughtersIds()[0]; d <= mcParticleIter.daughtersIds()[1]; ++d) { // TODO: remove this check as soon as issues with MC production are fixed if (d < mcParticles.size()) { // protect against bad daughter indices // auto dau_tmp = mcParticles.iteratorAt(d); @@ -429,16 +504,16 @@ struct AssociateMCInfoPhoton { daughters.push_back(fNewLabels.find(d)->second); } } else { - LOG(info) << "Daughter label (" << d << ") exceeds the McParticles size (" << mcParticles.size() << ")"; - LOG(info) << " Check the MC generator"; + LOG(error) << "Daughter label (" << d << ") exceeds the McParticles size (" << mcParticles.size() << ")"; + LOG(error) << " Check the MC generator"; } } } - emmcparticles(fEventIdx.find(oldLabel)->second, mcParticle.pdgCode(), mcParticle.flags(), mcParticle.statusCode(), + emmcparticles(fEventIdx.find(oldLabel)->second, mcParticleIter.pdgCode(), mcParticleIter.flags(), mcParticleIter.statusCode(), mothers, daughters, - mcParticle.px(), mcParticle.py(), mcParticle.pz(), mcParticle.e(), - mcParticle.vx(), mcParticle.vy(), mcParticle.vz()); + mcParticleIter.px(), mcParticleIter.py(), mcParticleIter.pz(), mcParticleIter.e(), + mcParticleIter.vx(), mcParticleIter.vy(), mcParticleIter.vz()); } // end loop over labels fNewLabels.clear(); @@ -450,6 +525,21 @@ struct AssociateMCInfoPhoton { fCounters[1] = 0; } // end of skimmingMC + template + inline bool areTwoPhotonDaughtersAccepted(const Daughters& lDaughters, float maxEta) + { + if (lDaughters.size() != 2) { + return false; + } + + auto it0 = lDaughters.begin(); + auto it1 = it0; + ++it1; + + return (std::fabs(it0.eta()) < maxEta && + std::fabs(it1.eta()) < maxEta); + } + void processMC_PCM(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcParticles, TracksMC const& o2tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs) { skimmingMC(collisions, bcs, mccollisions, mcParticles, o2tracks, nullptr, v0photons, v0legs, nullptr, nullptr, nullptr); diff --git a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx index b193c642175..75838125d69 100644 --- a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx @@ -10,9 +10,7 @@ // or submit itself to any jurisdiction. /// /// \file bcWiseClusterSkimmer.cxx -/// /// \brief This task creates minimalistic skimmed tables containing EMC clusters and centrality information -/// /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt /// @@ -20,17 +18,39 @@ #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "PWGJE/DataModel/EMCALClusters.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DetectorsBase/GeometryManager.h" -#include "EMCALBase/Geometry.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include #include #include #include @@ -40,6 +60,7 @@ using namespace o2; using namespace o2::aod::emdownscaling; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; using MyCollisions = soa::Join; using MyMCCollisions = soa::Join; @@ -77,6 +98,7 @@ struct bcWiseClusterSkimmer { Configurable cfgRequireGoodRCTQuality{"cfgRequireGoodRCTQuality", false, "Only store BCs with good quality of T0 and EMC in RCT"}; Configurable cfgStoreMu{"cfgStoreMu", false, "Calculate and store mu (probablity of a TVX collision in the BC) per BC. Otherwise fill with 0"}; Configurable cfgStoreTime{"cfgStoreTime", false, "Calculate and store time since the start of fill. Otherwise fill with 0"}; + Configurable cfgOnlyCheckFirstTrueContributor{"cfgOnlyCheckFirstTrueContributor", false, "When storing MC cluster info only count as true if the leading contributor is from pi0/eta"}; ConfigurableAxis cfgMultiplicityBinning{"cfgMultiplicityBinning", {1000, 0, 10000}, "Binning used for the binning of the number of particles in the event"}; aod::rctsel::RCTFlagsChecker isFT0EMCGoodRCTChecker{aod::rctsel::kFT0Bad, aod::rctsel::kEMCBad}; @@ -144,30 +166,30 @@ struct bcWiseClusterSkimmer { } /// \brief Process EMCAL clusters (either ambigous or unique) - template + template void processClusters(Clusters const& clusters, const int bcID) { for (const auto& cluster : clusters) { clusterTable(bcID, - convertForStorage(cluster.definition(), kDefinition), - convertForStorage(cluster.energy(), kEnergy), - convertForStorage(cluster.eta(), kEta), - convertForStorage(cluster.phi(), kPhi), - convertForStorage(cluster.nCells(), kNCells), - convertForStorage(cluster.m02(), kM02), - convertForStorage(cluster.time(), kTime), + convertForStorage(cluster.definition(), Observable::kDefinition), + convertForStorage(cluster.energy(), Observable::kEnergy), + convertForStorage(cluster.eta(), Observable::kEta), + convertForStorage(cluster.phi(), Observable::kPhi), + convertForStorage(cluster.nCells(), Observable::kNCells), + convertForStorage(cluster.m02(), Observable::kM02), + convertForStorage(cluster.time(), Observable::kTime), cluster.isExotic()); } } - template + template void processClusterMCInfo(Clusters const& clusters, const int bcID, aod::McParticles const& mcParticles) { for (const auto& cluster : clusters) { float clusterInducerEnergy = 0.; int32_t mesonMCIndex = -1; - if (cluster.amplitudeA().size() > 0) { - int clusterInducerId = cluster.mcParticleIds()[0]; + for (size_t i = 0; i < cluster.amplitudeA().size(); i++) { + int clusterInducerId = cluster.mcParticleIds()[i]; auto clusterInducer = mcParticles.iteratorAt(clusterInducerId); clusterInducerEnergy = clusterInducer.e(); int daughterId = aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(clusterInducer, mcParticles, std::vector{111, 221}); @@ -176,15 +198,19 @@ struct bcWiseClusterSkimmer { if (mcParticles.iteratorAt(mesonMCIndex).pt() < cfgMinPtGen) mesonMCIndex = -1; } + if (mesonMCIndex != -1) + break; + if (cfgOnlyCheckFirstTrueContributor) + break; } bool isEta = false; if (mesonMCIndex >= 0) { - if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == 111) { + if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == PDG_t::kPi0) { if (fMapPi0Index.find(mesonMCIndex) != fMapPi0Index.end()) // Some pi0s might not be found (not gg decay or too large y) mesonMCIndex = fMapPi0Index[mesonMCIndex]; // If pi0 was stored in table, change index from the MC index to the pi0 index from this task else // If pi0 was not stored, treat photon as if not from pi0 mesonMCIndex = -1; - } else if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == 221) { + } else if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == Pdg::kEta) { isEta = true; if (fMapEtaIndex.find(mesonMCIndex) != fMapEtaIndex.end()) // Some etas might not be found (not gg decay or too large y) mesonMCIndex = fMapEtaIndex[mesonMCIndex]; // If eta was stored in table, change index from the MC index to the eta index from this task @@ -293,27 +319,27 @@ struct bcWiseClusterSkimmer { collisionTable(bcTable.lastIndex(), convertForStorage(collision.posZ(), kZVtx)); } - template - bool isGammaGammaDecay(TMCParticle mcParticle, TMCParticles mcParticles) + template + bool isGammaGammaDecay(TMCParticle const& mcParticle, TMCParticles const& mcParticles) { auto daughtersIds = mcParticle.daughtersIds(); if (daughtersIds.size() != 2) return false; for (const auto& daughterId : daughtersIds) { - if (mcParticles.iteratorAt(daughterId).pdgCode() != 22) + if (mcParticles.iteratorAt(daughterId).pdgCode() != PDG_t::kGamma) return false; } return true; } - template - bool isAccepted(TMCParticle mcParticle, TMCParticles mcParticles) + template + bool isAccepted(TMCParticle const& mcParticle, TMCParticles const& mcParticles) { auto daughtersIds = mcParticle.daughtersIds(); if (daughtersIds.size() != 2) return false; for (const auto& daughterId : daughtersIds) { - if (mcParticles.iteratorAt(daughterId).pdgCode() != 22) + if (mcParticles.iteratorAt(daughterId).pdgCode() != PDG_t::kGamma) return false; int iCellID = -1; try { @@ -375,11 +401,11 @@ struct bcWiseClusterSkimmer { bool isPrimary = mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator(); bool isFromWD = (aod::pwgem::photonmeson::utils::mcutil::IsFromWD(mcCollision, mcParticle, mcParticles)) > 0; - if (mcParticle.pdgCode() == 111) { - mcpi0Table(bc.globalIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); + if (mcParticle.pdgCode() == PDG_t::kPi0) { + mcpi0Table(bcTable.lastIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); fMapPi0Index[mcParticle.globalIndex()] = static_cast(mcpi0Table.lastIndex()); - } else if (mcParticle.pdgCode() == 221) { - mcetaTable(bc.globalIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); + } else if (mcParticle.pdgCode() == Pdg::kEta) { + mcetaTable(bcTable.lastIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); fMapEtaIndex[mcParticle.globalIndex()] = static_cast(mcetaTable.lastIndex()); } } diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index fe6726d4d98..01965fc08ae 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -13,6 +13,7 @@ /// \brief This code produces reduced events for photon analyses. /// \author Daiki Sekihata, daiki.sekihata@cern.ch +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" // #include "PWGJE/DataModel/Jet.h" @@ -24,9 +25,6 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Qvectors.h" -#include -#include -#include #include #include #include @@ -66,14 +64,14 @@ using MyCollisionsMCCentQvec = soa::Join; struct CreateEMEventPhoton { // Produces embc; - Produces event; + Produces event; Produces eventalias; // Produces eventCov; - Produces eventMult; - Produces eventCent; - Produces eventQvec; + Produces eventMult; + Produces eventCent; + Produces eventQvec; Produces emswtbit; - Produces event_norm_info; + Produces event_norm_info; Produces eventWeights; enum class EMEventType : int { @@ -359,16 +357,16 @@ struct CreateEMEventPhoton { }; struct AssociatePhotonToEMEvent { Produces v0kfeventid; - Produces prmeleventid; + Produces prmeleventid; Produces phoseventid; Produces emceventid; - Produces prmtrackeventid; + // Produces prmtrackeventid; Preslice perCollisionPCM = aod::v0photonkf::collisionId; PresliceUnsorted perCollisionEl = aod::emprimaryelectron::collisionId; Preslice perCollisionPHOS = aod::skimmedcluster::collisionId; Preslice perCollisionEMC = aod::skimmedcluster::collisionId; - Preslice perCollision_track = aod::emprimarytrack::collisionId; + // Preslice perCollision_track = aod::emprimarytrack::collisionId; void init(o2::framework::InitContext&) {} @@ -387,38 +385,38 @@ struct AssociatePhotonToEMEvent { // This struct is for both data and MC. // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventPhoton in MC. - void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) + void processPCM(aod::PMEvents const& collisions, aod::V0PhotonsKF const& photons) { fillEventId(collisions, photons, v0kfeventid, perCollisionPCM); } - void processElectronFromDalitz(aod::EMEvents const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) + void processElectronFromDalitz(aod::PMEvents const& collisions, aod::EMPrimaryElectronsFromDalitz const& tracks) { fillEventId(collisions, tracks, prmeleventid, perCollisionEl); } - void processPHOS(aod::EMEvents const& collisions, aod::PHOSClusters const& photons) + void processPHOS(aod::PMEvents const& collisions, aod::PHOSClusters const& photons) { fillEventId(collisions, photons, phoseventid, perCollisionPHOS); } - void processEMC(aod::EMEvents const& collisions, aod::SkimEMCClusters const& photons) + void processEMC(aod::PMEvents const& collisions, aod::SkimEMCClusters const& photons) { fillEventId(collisions, photons, emceventid, perCollisionEMC); } - void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) - { - fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); - } + // void processChargedTrack(aod::PMEvents const& collisions, aod::EMPrimaryTracks const& tracks) + // { + // fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); + // } - void processDummy(aod::EMEvents const&) {} + void processDummy(aod::PMEvents const&) {} PROCESS_SWITCH(AssociatePhotonToEMEvent, processPCM, "process pcm-event 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, processChargedTrack, "process indexing for charged tracks", false); + // PROCESS_SWITCH(AssociatePhotonToEMEvent, processChargedTrack, "process indexing for charged tracks", false); PROCESS_SWITCH(AssociatePhotonToEMEvent, processDummy, "process dummy", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/TableProducer/createPCM.cxx b/PWGEM/PhotonMeson/TableProducer/createPCM.cxx index 138a190f7cd..70457782ae6 100644 --- a/PWGEM/PhotonMeson/TableProducer/createPCM.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createPCM.cxx @@ -22,20 +22,30 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/TrackSelectionTables.h" #include #include #include #include #include +#include #include #include #include +#include #include +#include +#include +#include +#include #include #include #include +#include +#include +#include #include #include #include diff --git a/PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx b/PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx similarity index 54% rename from PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx rename to PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx index 0fde469c55c..a371d109e3e 100644 --- a/PWGEM/PhotonMeson/Tasks/PhotonHBTPCMPCM.cxx +++ b/PWGEM/PhotonMeson/TableProducer/materialBudgetWeights.cxx @@ -8,20 +8,21 @@ // 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 +/// +/// \file MaterialBudgetWeights.h +/// +/// \brief This code produces a table to retrieve material budget weights. The table is to be join with V0PhotonKF +/// +/// \author Youssef El Mard (youssef.el.mard.bouziani@cern.ch) + +#include "PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h" -#include "PWGEM/PhotonMeson/Core/PhotonHBT.h" +#include +#include -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"photon-hbt-pcmpcm"})}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.cxx new file mode 100644 index 00000000000..57a551a40c1 --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/nonLinProducer.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 nonLinProducer.cxx +/// \brief produces nonLin tables for PCM and EMCal +/// \author marvin.hemmer@cern.ch +/// dependencies: skimmer-gamma-calo + +#include "PWGEM/PhotonMeson/Core/EMNonLin.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with TMatrixDfwd.h) +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::emcdownscaling; +using namespace o2::pwgem::nonlin; + +struct NonLinProducer { + + enum CentralityEstimator : uint8_t { + None = 0, + CFT0A = 1, + CFT0C, + CFT0M, + NCentralityEstimators + }; + + Produces tableNonLinV0s; + Produces tableNonLinClusters; + + Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; + Configurable emcIteration{"emcIteration", 0, "iteration number of the non lin correction for EMCal. 0 means first iteration 1 means second and so on!"}; + Configurable pcmIteration{"pcmIteration", 0, "iteration number of the non lin correction for PCM. 0 means first iteration 1 means second and so on!"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathEmcal{"ccdbPathEmcal", "Users/m/mhemmer/EM/NonLin/EMC", "CCDB Path to Non Lin TMatrixD for EMCal"}; + Configurable ccdbPathPcm{"ccdbPathPcm", "Users/m/mhemmer/EM/NonLin/PCM", "CCDB Path to Non Lin TMatrixD for PCM"}; + + HistogramRegistry historeg{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + using EMCalPhotons = soa::Join; + using PcmPhotons = soa::Join; + + using Colls = soa::Join; + + EMNonLin emNonLinEMC; + EMNonLin emNonLinPCM; + + EMNonLin::Context emNonLinContextEMC; + EMNonLin::Context emNonLinContextPCM; + + o2::framework::Service ccdb; + + TMatrixD* emcalMatrix = nullptr; + TMatrixD* pcmMatrix = nullptr; + + void init(o2::framework::InitContext&) + { + historeg.add("QA/EMC/EIn", "Energy of EMC clusters before NonLin correction", gHistoSpecClusterE); + historeg.add("QA/EMC/EOut", "Energy of EMC clusters after NonLin correction", gHistoSpecClusterE); + + historeg.add("QA/EMC/PtIn", "Pt of EMC clusters before NonLin correction", gHistoSpecPt); + historeg.add("QA/EMC/PtOut", "Pt of EMC clusters after NonLin correction", gHistoSpecPt); + + historeg.add("QA/PCM/PtIn", "Pt of PCM photon before NonLin correction", gHistoSpecPt); + historeg.add("QA/PCM/PtOut", "Pt of PCM photon after NonLin correction", gHistoSpecPt); + + emNonLinContextEMC.setIter(emcIteration); + emNonLinContextPCM.setIter(pcmIteration); + + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (doprocessEMC) { + emcalMatrix = ccdb->getForTimeStamp(ccdbPathEmcal, collision.timestamp()); + emNonLinEMC.getFromCCDBObject(emcalMatrix, o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC); + emNonLinContextEMC.setParams(emNonLinEMC.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kEMC)); + } + if (doprocessPCM) { + pcmMatrix = ccdb->getForTimeStamp(ccdbPathPcm, collision.timestamp()); + emNonLinPCM.getFromCCDBObject(pcmMatrix, o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM); + emNonLinContextPCM.setParams(emNonLinPCM.resolveParams(o2::pwgem::nonlin::EMNonLin::PhotonType::kPCM)); + } + } + + /// Get the centrality + /// \param collision is the collision with the centrality information + template + float getCentrality(TCollision const& collision) + { + float cent = -999.; + switch (centEstimator) { + case CentralityEstimator::CFT0M: + cent = collision.centFT0M(); + break; + case CentralityEstimator::CFT0A: + cent = collision.centFT0A(); + break; + case CentralityEstimator::CFT0C: + cent = collision.centFT0C(); + break; + default: + LOG(warning) << "Centrality estimator not valid. Possible values are T0M, T0A, T0C. Fallback to T0C"; + cent = collision.centFT0C(); + break; + } + return cent; + } + + template + void runEMC(TClusters const& clusters, TCollisio& collision) + { + + int32_t collIndex = collision.globalIndex(); + float cent = getCentrality(collision); + emNonLinContextEMC.setCent(cent); + + for (const auto& cluster : clusters) { + + // check that we are at the correct collision + if (cluster.pmeventId() != collIndex) { + collIndex = cluster.pmeventId(); + collision.setCursor(collIndex); + cent = getCentrality(collision); + emNonLinContextEMC.setCent(cent); + } + + // fill before non lin histograms + historeg.fill(HIST("QA/EMC/EIn"), cluster.e()); + historeg.fill(HIST("QA/EMC/PtIn"), cluster.pt()); + + // get NonLin factor from class dependent on the centrality + float nonLinFactor = emNonLinEMC.getCorrectionFactor(cluster.e(), emNonLinContextEMC); + + float nonLinE = nonLinFactor * cluster.e(); + float nonLinPt = nonLinFactor * cluster.pt(); + + // fill after non lin histograms + historeg.fill(HIST("QA/EMC/EOut"), nonLinE); + historeg.fill(HIST("QA/EMC/PtOut"), nonLinPt); + + tableNonLinClusters(nonLinE, nonLinPt); + } + } + + template + void runPCM(TV0 const& v0s, TCollisio& collision) + { + + int32_t collIndex = collision.globalIndex(); + float cent = getCentrality(collision); + emNonLinContextPCM.setCent(cent); + for (const auto& v0 : v0s) { + + // check that we are at the correct collision + if (v0.pmeventId() != collIndex) { + collIndex = v0.pmeventId(); + collision.setCursor(collIndex); + cent = getCentrality(collision); + emNonLinContextPCM.setCent(cent); + } + + // fill before non lin histograms + historeg.fill(HIST("QA/PCM/PtIn"), v0.pt()); + + // get NonLin factor from class dependent on the centrality + float nonLinFactor = emNonLinPCM.getCorrectionFactor(v0.pt(), emNonLinContextPCM); + + float nonLinPt = nonLinFactor * v0.pt(); + + // fill after non lin histograms + historeg.fill(HIST("QA/PCM/PtOut"), nonLinPt); + + tableNonLinV0s(nonLinPt); + } + } + + void processEMC(Colls const& collisions, EMCalPhotons const& emcclusters) + { + + if (emcclusters.size() == 0) { + return; + } + + auto collision = collisions.begin(); + initCCDB(collision); + runEMC(emcclusters, collision); + } + PROCESS_SWITCH(NonLinProducer, processEMC, "Create Non Lin table for EMC.", false); + + void processPCM(Colls const& collisions, PcmPhotons const& pcmPhotons) + { + if (pcmPhotons.size() == 0) { + return; + } + auto collision = collisions.begin(); + initCCDB(collision); + runPCM(pcmPhotons, collision); + } + PROCESS_SWITCH(NonLinProducer, processPCM, "Create Non Lin table for PCM.", false); + + void processEMCDummy(EMCalPhotons::iterator const& emccluster) + { + tableNonLinClusters(emccluster.e(), emccluster.pt()); + } + PROCESS_SWITCH(NonLinProducer, processEMCDummy, "Create dummy Non Lin table for EMC.", true); + + void processPCMDummy(PcmPhotons::iterator const& pcmPhoton) + { + tableNonLinV0s(pcmPhoton.pt()); + } + PROCESS_SWITCH(NonLinProducer, processPCMDummy, "Createdumy Non Lin table for PCM.", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx index 5240f826855..1199b2415a2 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -14,7 +14,14 @@ /// \brief this task produces photon data table with KFParticle. /// \author Daiki Sekihata , Tokyo +#ifndef HomogeneousField +#define HomogeneousField // needed for KFParticle::SetField(magneticField); +#endif + #include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Core/EmMlResponsePCM.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "PWGEM/PhotonMeson/Utils/TrackSelection.h" @@ -22,11 +29,13 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/TPCVDriftManager.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Tools/KFparticle/KFUtilities.h" #include +#include #include #include #include @@ -37,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +54,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include @@ -71,7 +81,7 @@ using namespace o2::constants::physics; using namespace o2::pwgem::photonmeson; using std::array; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollisionsWithSWT = soa::Join; using MyCollisionsMC = soa::Join; @@ -89,7 +99,7 @@ struct PhotonConversionBuilder { Produces v0legs; Produces v0legsXYZ; Produces v0legsDeDxMC; - Produces v0photonsphiv; + Produces v0photonsphivpsi; // Produces v0photonskfcov; // Produces events_ngpcm; @@ -150,6 +160,30 @@ struct PhotonConversionBuilder { Configurable max_dcatopv_z_v0{"max_dcatopv_z_v0", +1e+10, "max. DCAz to PV for V0"}; Configurable reject_v0_on_itsib{"reject_v0_on_itsib", true, "flag to reject v0s on ITSib"}; + // PCM ML inference + Configurable applyPCMMl{"applyPCMMl", false, "Flag to apply ML selections"}; + Configurable use2DBinning{"use2DBinning", false, "Flag to enable/disable 2D binning for ML application"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable nClassesPCMMl{"nClassesPCMMl", static_cast(o2::analysis::em_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable centTypePCMMl{"centTypePCMMl", 2, "Centrality type for 2D ML application: FT0M:0, FT0A:1, FT0C:2"}; + Configurable> cutDirPCMMl{"cutDirPCMMl", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"path_ccdb/BDT_PCM/"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable> labelsBinsPCMMl{"labelsBinsPCMMl", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> labelsCutScoresPCMMl{"labelsCutScoresPCMMl", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> binsPtPCMMl{"binsPtPCMMl", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> binsCentPCMMl{"binsCentPCMMl", std::vector{0.0, 100.0}, "Centrality bin limits for ML application"}; + Configurable> cutsPCMMlFlat{"cutsPCMMlFlat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; + + Configurable propV0LegsRadius{"propV0LegsRadius", 60.f, "Radius to which the V0 legs are propagated to calculate psipair and phiV"}; + + o2::analysis::EmMlResponsePCM emMlResponse; + std::vector outputML; + V0PhotonCandidate v0photoncandidate; + o2::ccdb::CcdbApi ccdbApi; + int mRunNumber; float d_bz; float maxSnp; // max sine phi for propagation @@ -183,7 +217,7 @@ struct PhotonConversionBuilder { {"V0/hRxy_minX_ITSTPC_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/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}}}}, - {"V0/hPhiV", "#phi_{V}; #phi_{V} (rad.)", {HistType::kTH1F, {{500, 0.0f, 2 * M_PI}}}}, + {"V0/hPhiVPsiPair", "phiV vs. psi pair;#psi_{pair} (rad.);#phi_{V} (rad.)", {HistType::kTH2F, {{500, -o2::constants::math::PI, o2::constants::math::PI}, {500, 0.0f, o2::constants::math::TwoPI}}}}, {"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, o2::constants::math::TwoPI}, {200, -1, +1}}}}, {"V0Leg/hRelDeltaPt", "pT resolution;p_{T} (GeV/c);#Deltap_{T}/p_{T}", {HistType::kTH2F, {{1000, 0.f, 10.f}, {100, 0, 1}}}}, @@ -204,23 +238,92 @@ struct PhotonConversionBuilder { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - - if (useMatCorrType == MatCorrType::TGeo) { - LOGF(info, "TGeo correction requested, loading geometry"); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); - } - } - if (useMatCorrType == MatCorrType::LUT) { - LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + switch (useMatCorrType) { + case MatCorrType::TGeo: + LOGF(info, "TGeo correction requested, loading geometry"); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; + break; + case MatCorrType::LUT: + LOGF(info, "LUT correction requested, loading LUT"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + break; + default: + LOGF(info, "no correction requested, loading LUT by default!"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + break; } - if (useMatCorrType == MatCorrType::TGeo) { - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - } - if (useMatCorrType == MatCorrType::LUT) { - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + if (applyPCMMl) { + if (use2DBinning) { + int binsNPt = static_cast(binsPtPCMMl->size()) - 1; + int binsNCent = static_cast(binsCentPCMMl->size()) - 1; + int binsN = binsNPt * binsNCent; + if (binsN * static_cast(cutDirPCMMl->size()) != static_cast(cutsPCMMlFlat->size())) { + LOG(fatal) << "Mismatch in number of bins and cuts provided for 2D ML application: binsN * cutDirPCMMl: " << int(binsN) * int(cutDirPCMMl->size()) << " bins vs. cutsPCMMlFlat: " << cutsPCMMlFlat->size() << " cuts"; + } + if (binsN != static_cast(onnxFileNames->size())) { + LOG(fatal) << "Mismatch in number of bins and ONNX files provided for 2D ML application: binsN " << binsN << " bins vs. onnxFileNames: " << onnxFileNames->size() << " ONNX files"; + } + if (binsN != static_cast(labelsBinsPCMMl->size())) { + LOG(fatal) << "Mismatch in number of bins and labels provided for 2D ML application: binsN:" << binsN << " bins vs. labelsBinsPCMMl: " << labelsBinsPCMMl->size() << " labels"; + } + if (static_cast(cutDirPCMMl->size()) != nClassesPCMMl) { + LOG(fatal) << "Mismatch in number of classes and cut directions provided for 2D ML application: nClassesPCMMl: " << nClassesPCMMl << " classes vs. cutDirPCMMl: " << cutDirPCMMl->size() << " cut directions"; + } + if (static_cast(labelsCutScoresPCMMl->size()) != nClassesPCMMl) { + LOG(fatal) << "Mismatch in number of labels for cut scores and number of classes provided for 2D ML application: nClassesPCMMl: " << nClassesPCMMl << " classes vs. labelsCutScoresPCMMl: " << labelsCutScoresPCMMl->size() << " labels"; + } + LabeledArray cutsPCMMl(cutsPCMMlFlat->data(), binsN, nClassesPCMMl, labelsBinsPCMMl, labelsCutScoresPCMMl); + emMlResponse.configure2D(binsPtPCMMl, binsCentPCMMl, cutsPCMMl, cutDirPCMMl, nClassesPCMMl); + } else { + int binsNPt = static_cast(binsPtPCMMl->size()) - 1; + if (binsNPt * static_cast(cutDirPCMMl->size()) != static_cast(cutsPCMMlFlat->size())) { + LOG(fatal) << "Mismatch in number of pT bins and cuts provided for ML application: binsNPt * cutDirPCMMl:" << binsNPt * cutDirPCMMl->size() << " bins vs. cutsPCMMlFlat: " << cutsPCMMlFlat->size() << " cuts"; + } + if (binsNPt != static_cast(onnxFileNames->size())) { + LOG(fatal) << "Mismatch in number of pT bins and ONNX files provided for ML application: binsNPt " << binsNPt << " bins vs. onnxFileNames: " << onnxFileNames->size() << " ONNX files"; + } + if (binsNPt != static_cast(labelsBinsPCMMl->size())) { + LOG(fatal) << "Mismatch in number of pT bins and labels provided for ML application: binsNPt:" << binsNPt << " bins vs. labelsBinsPCMMl: " << labelsBinsPCMMl->size() << " labels"; + } + if (nClassesPCMMl != static_cast(cutDirPCMMl->size())) { + LOG(fatal) << "Mismatch in number of classes and cut directions provided for ML application: nClassesPCMMl: " << nClassesPCMMl << " classes vs. cutDirPCMMl: " << cutDirPCMMl->size() << " cut directions"; + } + if (static_cast(labelsCutScoresPCMMl->size()) != nClassesPCMMl) { + LOG(fatal) << "Mismatch in number of labels for cut scores and number of classes provided for ML application: nClassesPCMMl:" << nClassesPCMMl << " classes vs. labelsCutScoresPCMMl: " << labelsCutScoresPCMMl->size() << " labels"; + } + LabeledArray cutsPCMMl(cutsPCMMlFlat->data(), binsNPt, nClassesPCMMl, labelsBinsPCMMl, labelsCutScoresPCMMl); + emMlResponse.configure(binsPtPCMMl, cutsPCMMl, cutDirPCMMl, nClassesPCMMl); + } + if (loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + emMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + emMlResponse.setModelPathsLocal(onnxFileNames); + } + emMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + emMlResponse.init(); + if (nClassesPCMMl == 2) { + registry.add("V0/hBDTBackgroundScoreBeforeCutVsPt", "BDT background score before cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTBackgroundScoreAfterCutVsPt", "BDT background score after cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSignalScoreBeforeCutVsPt", "BDT signal score before cut vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSignalScoreAfterCutVsPt", "BDT signal score after cut vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + } else if (nClassesPCMMl == 3) { + registry.add("V0/hBDTBackgroundScoreBeforeCutVsPt", "BDT background score before cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTBackgroundScoreAfterCutVsPt", "BDT background score after cut vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTPrimaryPhotonScoreBeforeCutVsPt", "BDT primary photon score before cut vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTPrimaryPhotonScoreAfterCutVsPt", "BDT primary photon score after cut vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSecondaryPhotonScoreBeforeCutVsPt", "BDT secondary photon score before cut vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTSecondaryPhotonScoreAfterCutVsPt", "BDT secondary photon score after cut vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + } else { + registry.add("V0/hBDTScoreBeforeCutVsPt", "BDT score before cut vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + registry.add("V0/hBDTScoreAfterCutVsPt", "BDT score after cut vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + } } } @@ -384,17 +487,17 @@ struct PhotonConversionBuilder { return cospaRZ; } - template - void fillTrackTable(TTrack const& track, TShiftedTrack const& shiftedtrack, TKFParticle const& kfp, const float dcaXY, const float dcaZ) + template + void fillTrackTable(TTrack const& track, TShiftedTrack const& shiftedtrack, const float dcaXY, const float dcaZ) { v0legs(track.collisionId(), track.globalIndex(), track.sign(), - kfp.GetPx(), kfp.GetPy(), kfp.GetPz(), dcaXY, dcaZ, + shiftedtrack.GetPx(), shiftedtrack.GetPy(), shiftedtrack.GetPz(), dcaXY, dcaZ, track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap()); - v0legsXYZ(shiftedtrack.getX(), shiftedtrack.getY(), shiftedtrack.getZ()); + v0legsXYZ(shiftedtrack.GetX(), shiftedtrack.GetY(), shiftedtrack.GetZ()); if constexpr (isMC) { v0legsDeDxMC(track.mcTunedTPCSignal()); @@ -480,6 +583,37 @@ struct PhotonConversionBuilder { return; // RZ line cut } + float phiv = 999.f; + float psipair = 999.f; + float baseR = std::hypot(xyz[0], xyz[1]); + float offsetsR[3] = {propV0LegsRadius, 30.f, 10.f}; + bool pPropagatedSuccess = false; + bool nPropagatedSuccess = false; + auto pTrackProp = pTrack; + auto nTrackProp = nTrack; + for (float offsetR : offsetsR) { + pTrackProp = pTrack; + pTrackProp.setPID(o2::track::PID::Electron); + nTrackProp = nTrack; + nTrackProp.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, pTrackProp, 2.f, matCorr, &dcaInfo); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, nTrackProp, 2.f, matCorr, &dcaInfo); + pPropagatedSuccess = o2::base::Propagator::Instance()->propagateToR(pTrackProp, baseR + offsetR); + nPropagatedSuccess = o2::base::Propagator::Instance()->propagateToR(nTrackProp, baseR + offsetR); + if (pPropagatedSuccess && nPropagatedSuccess) { + KFPTrack kfp_track_posProp = createKFPTrackFromTrackParCov(pTrackProp, pos.sign(), pos.tpcNClsFound(), pos.tpcChi2NCl()); + KFPTrack kfp_track_eleProp = createKFPTrackFromTrackParCov(nTrackProp, ele.sign(), ele.tpcNClsFound(), ele.tpcChi2NCl()); + phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(kfp_track_posProp.GetPx(), kfp_track_posProp.GetPy(), kfp_track_posProp.GetPz(), kfp_track_eleProp.GetPx(), kfp_track_eleProp.GetPy(), kfp_track_eleProp.GetPz(), pos.sign(), ele.sign(), d_bz); + psipair = o2::aod::pwgem::dilepton::utils::pairutil::getPsiPair(kfp_track_posProp.GetPx(), kfp_track_posProp.GetPy(), kfp_track_posProp.GetPz(), kfp_track_eleProp.GetPx(), kfp_track_eleProp.GetPy(), kfp_track_eleProp.GetPz()); + break; + } else { + LOG(debug) << "Propagation to offset" << offsetR << " cm failed for " << (pPropagatedSuccess ? "negative" : "positive") << " track. Trying smaller offset."; + } + } + if (phiv == 999.f || psipair == 999.f) { + LOG(debug) << "Propagation failed for all radii (" << propV0LegsRadius << ", 30, 10 cm). Using default values for phiv and psipair (999.f)."; + } + 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, kPositron); @@ -590,87 +724,110 @@ struct PhotonConversionBuilder { kfp_pos_DecayVtx.TransportToPoint(xyz); // Don't set Primary Vertex kfp_ele_DecayVtx.TransportToPoint(xyz); // Don't set Primary Vertex - float pca_kf = kfp_pos_DecayVtx.GetDistanceFromParticle(kfp_ele_DecayVtx); + float cospaXYKF = cospaXY_KF(gammaKF_DecayVtx, KFPV); + float cospaRZKF = cospaRZ_KF(gammaKF_DecayVtx, KFPV); + CentType centType = static_cast(centTypePCMMl.value); + v0photoncandidate.setPhotonCandidate(gammaKF_DecayVtx, gammaKF_PV, pos, kfp_pos_DecayVtx, ele, kfp_ele_DecayVtx, collision, cospaXYKF, cospaRZKF, cospaXYKF, psipair, phiv, centType, posdcaXY, posdcaZ, eledcaXY, eledcaZ); + if (!ele.hasITS() && !pos.hasITS()) { // V0s with TPConly-TPConly if (max_r_itsmft_ss < rxy && rxy < maxX + margin_r_tpc) { - if (pca_kf > max_dcav0dau_tpc_inner_fc) { + if (v0photoncandidate.getPCA() > max_dcav0dau_tpc_inner_fc) { return; } } else { - if (pca_kf > max_dcav0dau_tpconly) { + if (v0photoncandidate.getPCA() > max_dcav0dau_tpconly) { return; } } } else { // V0s with ITS hits if (rxy < max_r_req_its) { - if (pca_kf > max_dcav0dau_itsibss) { + if (v0photoncandidate.getPCA() > max_dcav0dau_itsibss) { return; } } else { - if (pca_kf > max_dcav0dau_its) { + if (v0photoncandidate.getPCA() > max_dcav0dau_its) { return; } } } - 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 (isITSonlyTrack(pos) && pos_pt > maxpt_itsonly) { + if (isITSonlyTrack(pos) && v0photoncandidate.getPosPt() > maxpt_itsonly) { return; } - if (isITSonlyTrack(ele) && ele_pt > maxpt_itsonly) { + if (isITSonlyTrack(ele) && v0photoncandidate.getElePt() > maxpt_itsonly) { return; } - float chi2kf = gammaKF_DecayVtx.GetChi2() / gammaKF_DecayVtx.GetNDF(); - if (chi2kf > 6e+3) { // protection for uint16. + if (v0photoncandidate.getChi2NDF() > 6e+3) { // protection for uint16. return; } - // calculate DCAxy,z to PV - float v0mom = RecoDecay::sqrtSumOfSquares(gammaKF_DecayVtx.GetPx(), gammaKF_DecayVtx.GetPy(), gammaKF_DecayVtx.GetPz()); - float length = RecoDecay::sqrtSumOfSquares(gammaKF_DecayVtx.GetX() - collision.posX(), gammaKF_DecayVtx.GetY() - collision.posY(), gammaKF_DecayVtx.GetZ() - collision.posZ()); - float dca_x_v0_to_pv = (gammaKF_DecayVtx.GetX() - gammaKF_DecayVtx.GetPx() * cospa_kf * length / v0mom) - collision.posX(); - float dca_y_v0_to_pv = (gammaKF_DecayVtx.GetY() - gammaKF_DecayVtx.GetPy() * cospa_kf * length / v0mom) - collision.posY(); - float dca_z_v0_to_pv = (gammaKF_DecayVtx.GetZ() - gammaKF_DecayVtx.GetPz() * cospa_kf * length / v0mom) - collision.posZ(); - float sign_tmp = dca_x_v0_to_pv * dca_y_v0_to_pv > 0 ? +1.f : -1.f; - float dca_xy_v0_to_pv = RecoDecay::sqrtSumOfSquares(dca_x_v0_to_pv, dca_y_v0_to_pv) * sign_tmp; - if (std::fabs(dca_xy_v0_to_pv) > max_dcatopv_xy_v0 || std::fabs(dca_z_v0_to_pv) > max_dcatopv_z_v0) { + if (std::fabs(v0photoncandidate.getDcaXYToPV()) > max_dcatopv_xy_v0 || std::fabs(v0photoncandidate.getDcaZToPV()) > max_dcatopv_z_v0) { return; } - float alpha = v0_alpha(kfp_pos_DecayVtx.GetPx(), kfp_pos_DecayVtx.GetPy(), kfp_pos_DecayVtx.GetPz(), kfp_ele_DecayVtx.GetPx(), kfp_ele_DecayVtx.GetPy(), kfp_ele_DecayVtx.GetPz()); - float qt = v0_qt(kfp_pos_DecayVtx.GetPx(), kfp_pos_DecayVtx.GetPy(), kfp_pos_DecayVtx.GetPz(), kfp_ele_DecayVtx.GetPx(), kfp_ele_DecayVtx.GetPy(), kfp_ele_DecayVtx.GetPz()); - if (!checkAP(alpha, qt, max_alpha_ap, max_qt_ap)) { // store only photon conversions + if (!checkAP(v0photoncandidate.getAlpha(), v0photoncandidate.getQt(), max_alpha_ap, max_qt_ap)) { // store only photon conversions return; } - pca_map[std::make_tuple(v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex())] = pca_kf; - cospa_map[std::make_tuple(v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex())] = cospa_kf; - - 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); + pca_map[std::make_tuple(v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex())] = v0photoncandidate.getPCA(); + cospa_map[std::make_tuple(v0.globalIndex(), collision.globalIndex(), pos.globalIndex(), ele.globalIndex())] = v0photoncandidate.getCosPA(); + + if (applyPCMMl) { + bool isSelectedML = false; + std::vector mlInputFeatures = emMlResponse.getInputFeatures(v0photoncandidate, pos, ele); + if (use2DBinning) { + isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), v0photoncandidate.getCent(), outputML); + } else { + isSelectedML = emMlResponse.isSelectedMl(mlInputFeatures, v0photoncandidate.getPt(), outputML); + } + if (filltable) { + if (nClassesPCMMl == 2) { + registry.fill(HIST("V0/hBDTBackgroundScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSignalScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + } else if (nClassesPCMMl == 3) { + registry.fill(HIST("V0/hBDTPrimaryPhotonScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSecondaryPhotonScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + registry.fill(HIST("V0/hBDTBackgroundScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[2]); + } else { + registry.fill(HIST("V0/hBDTScoreBeforeCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + } + } + if (!isSelectedML) { + return; + } + if (filltable) { + if (nClassesPCMMl == 2) { + registry.fill(HIST("V0/hBDTBackgroundScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSignalScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + } else if (nClassesPCMMl == 3) { + registry.fill(HIST("V0/hBDTPrimaryPhotonScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + registry.fill(HIST("V0/hBDTSecondaryPhotonScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[1]); + registry.fill(HIST("V0/hBDTBackgroundScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[2]); + } else { + registry.fill(HIST("V0/hBDTScoreAfterCutVsPt"), v0photoncandidate.getPt(), outputML[0]); + } + } + } if (filltable) { - registry.fill(HIST("V0/hAP"), alpha, qt); + registry.fill(HIST("V0/hAP"), v0photoncandidate.getAlpha(), v0photoncandidate.getQt()); registry.fill(HIST("V0/hConversionPointXY"), gammaKF_DecayVtx.GetX(), gammaKF_DecayVtx.GetY()); registry.fill(HIST("V0/hConversionPointRZ"), gammaKF_DecayVtx.GetZ(), rxy); - registry.fill(HIST("V0/hPt"), v0pt); + registry.fill(HIST("V0/hPt"), v0photoncandidate.getPt()); registry.fill(HIST("V0/hEtaPhi"), v0phi, v0eta); - registry.fill(HIST("V0/hCosPA"), cospa_kf); - registry.fill(HIST("V0/hCosPA_Rxy"), rxy, cospa_kf); - registry.fill(HIST("V0/hPCA"), pca_kf); - 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(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive - registry.fill(HIST("V0/hPhiV"), phiv); - - float cospaXY_kf = cospaXY_KF(gammaKF_DecayVtx, KFPV); - float cospaRZ_kf = cospaRZ_KF(gammaKF_DecayVtx, KFPV); + registry.fill(HIST("V0/hCosPA"), v0photoncandidate.getCosPA()); + registry.fill(HIST("V0/hCosPA_Rxy"), rxy, v0photoncandidate.getCosPA()); + registry.fill(HIST("V0/hPCA"), v0photoncandidate.getPCA()); + registry.fill(HIST("V0/hPCA_CosPA"), v0photoncandidate.getCosPA(), v0photoncandidate.getPCA()); + registry.fill(HIST("V0/hPCA_Rxy"), rxy, v0photoncandidate.getPCA()); + registry.fill(HIST("V0/hDCAxyz"), v0photoncandidate.getDcaXYToPV(), v0photoncandidate.getDcaZToPV()); + registry.fill(HIST("V0/hPCA_diffX"), v0photoncandidate.getPCA(), std::min(pTrack.getX(), nTrack.getX()) - rxy); // trackiu.x() - rxy should be positive + registry.fill(HIST("V0/hPhiVPsiPair"), v0photoncandidate.getPsiPair(), v0photoncandidate.getPhiV()); + // LOGF(info, "cospa_kf = %f, cospaXY_kf = %f, cospaRZ_kf = %f", cospa_kf, cospaXY_kf, cospaRZ_kf); - registry.fill(HIST("V0/hCosPAXY_Rxy"), rxy, cospaXY_kf); - registry.fill(HIST("V0/hCosPARZ_Rxy"), rxy, cospaRZ_kf); + registry.fill(HIST("V0/hCosPAXY_Rxy"), rxy, cospaXYKF); + registry.fill(HIST("V0/hCosPARZ_Rxy"), rxy, cospaRZKF); for (const auto& leg : {kfp_pos_DecayVtx, kfp_ele_DecayVtx}) { float legpt = RecoDecay::sqrtSumOfSquares(leg.GetPx(), leg.GetPy()); @@ -698,15 +855,15 @@ struct PhotonConversionBuilder { 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, cospaXY_kf, cospaRZ_kf, - pca_kf, alpha, qt, chi2kf); - v0photonsphiv(phiv); + v0_sv.M(), v0photoncandidate.getDcaXYToPV(), v0photoncandidate.getDcaZToPV(), + cospa_kf, cospaXYKF, cospaRZKF, + v0photoncandidate.getPCA(), v0photoncandidate.getAlpha(), v0photoncandidate.getQt(), v0photoncandidate.getChi2NDF()); + v0photonsphivpsi(v0photoncandidate.getPhiV(), v0photoncandidate.getPsiPair()); // 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 + fillTrackTable(pos, kfp_pos_DecayVtx, posdcaXY, posdcaZ); // positive leg first + fillTrackTable(ele, kfp_ele_DecayVtx, eledcaXY, eledcaZ); // negative leg second } // end of fill table } diff --git a/PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx b/PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx new file mode 100644 index 00000000000..70a96f7ba8a --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/pmQvectorDummyOtf.cxx @@ -0,0 +1,49 @@ +// 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 pmQvectorDummyOtf.cxx +/// \author Marvin Hemmer +/// \brief This code produces on-the-fly dummy qvector table. + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct PmQvectorDummyOtf { + Produces eventQvecs; + + void init(InitContext&) {} + + void process(aod::PMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + eventQvecs( + 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, 999.f, 999.f, 999.f, 999.f); + } // end of collision loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx index c27bd6e64ab..f522e113386 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -13,20 +13,31 @@ /// \author daiki.sekihata@cern.ch #include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "Common/DataModel/PIDResponseTPC.h" + #include #include #include #include -#include +#include #include +#include #include +#include +#include +#include +#include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include #include +#include #include #include #include @@ -37,10 +48,10 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; using MyTracksCEFP = soa::Join; @@ -54,7 +65,7 @@ struct skimmerDalitzEE { }; SliceCache cache; - Preslice perCol = o2::aod::emprimaryelectron::emeventId; + Preslice perCol = o2::aod::emprimaryelectronda::pmeventId; SliceCache cache_cefp; PresliceUnsorted perCol_cefp = o2::aod::emprimaryelectron::collisionId; @@ -337,8 +348,8 @@ struct skimmerDalitzEE { continue; } - 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); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); fRegistry.fill(HIST("hNpos"), collision.centFT0C(), posTracks_per_coll.size()); fRegistry.fill(HIST("hNele"), collision.centFT0C(), negTracks_per_coll.size()); // LOGF(info, "collision.centFT0C() = %f, posTracks_per_coll.size() = %d, negTracks_per_coll.size() = %d", collision.centFT0C() , posTracks_per_coll.size(), negTracks_per_coll.size()); @@ -375,7 +386,7 @@ struct skimmerDalitzEE { } PROCESS_SWITCH(skimmerDalitzEE, processCEFP, "Process dalitz ee for CEFP", false); // for central event filter processing - void processOnlyNee(soa::Join const& collisions) + void processOnlyNee(soa::Join const& collisions) { for (auto& collision : collisions) { float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx index 0ebf6f374c8..c0b14051d74 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx @@ -22,38 +22,48 @@ // ************************** // runme like: o2-analysis-trackselection -b --aod-file ${sourceFile} --aod-writer-json ${writerFile} | o2-analysis-timestamp -b | o2-analysis-trackextension -b | o2-analysis-lf-lambdakzerobuilder -b | o2-analysis-pid-tpc -b | o2-analysis-em-skimmermc -b - -#include -#include -#include -#include - // todo: remove reduantant information in GammaConversionsInfoTrue + #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -// includes for the R recalculation -#include "Common/Core/trackUtilities.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Tools/KFparticle/KFUtilities.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "ReconstructionDataFormats/HelixHelper.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Math/Vector4D.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx index 509a949b0dd..e44600aafaa 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx @@ -20,11 +20,15 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h" -#include "TVector3.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPHOS.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerPHOS.cxx index ef825ca5578..0d50b530c08 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPHOS.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerPHOS.cxx @@ -13,13 +13,22 @@ /// dependencies: o2-analysis-calo-cluster /// \author daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/CaloClusters.h" -#include "PHOSBase/Geometry.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "Common/DataModel/CaloClusters.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx index cb3452dc177..5efa2817617 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx @@ -14,33 +14,46 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" -#include "Common/Core/trackUtilities.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" - -#include +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include #include +#include #include #include +#include + 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; diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 29cbae1336b..fe155e91fe1 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -91,6 +91,11 @@ o2physics_add_dpl_workflow(pi0eta-to-gammagamma-pcmpcm PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(pi0eta-to-gammagamma-pcmpcm-ml + SOURCES Pi0EtaToGammaGammaPCMPCMML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(pi0eta-to-gammagamma-pcmdalitzee SOURCES Pi0EtaToGammaGammaPCMDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore @@ -111,6 +116,11 @@ o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-pcmpcm PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-pcmpcm-ml + SOURCES Pi0EtaToGammaGammaMCPCMPCMML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-pcmdalitzee SOURCES Pi0EtaToGammaGammaMCPCMDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore @@ -121,11 +131,6 @@ o2physics_add_dpl_workflow(pi0eta-to-gammagamma-mc-emcemc PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(photon-hbt-pcmpcm - SOURCES PhotonHBTPCMPCM.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - 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 @@ -171,22 +176,11 @@ o2physics_add_dpl_workflow(tagging-pi0-mc-pcmdalitzee PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(diphoton-hadron-mpc-pcmpcm - SOURCES diphotonHadronMPCPCMPCM.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - - o2physics_add_dpl_workflow(compconvbuilder SOURCES compconvbuilder.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(diphoton-hadron-mpc-pcmdalitzee - SOURCES diphotonHadronMPCPCMDalitzEE.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(calib-task-emc SOURCES calibTaskEmc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::EMCALBase O2::EMCALCalib O2Physics::PWGEMPhotonMesonCore @@ -196,3 +190,13 @@ o2physics_add_dpl_workflow(test-task-emc SOURCES testTaskEmc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::EMCALBase O2::EMCALCalib O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(photon-reso-task + SOURCES photonResoTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::EMCALBase O2::EMCALCalib O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(photonhbt + SOURCES photonhbt.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx b/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx index 5002de0a133..3caa5e5b5aa 100644 --- a/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx +++ b/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx @@ -24,19 +24,34 @@ #include #include #include +#include #include #include +#include #include +#include #include +#include +#include +#include #include #include #include #include +#include #include +#include +#include +#include +#include #include +#include +#include +#include #include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx b/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx index 961f8b0dfe7..cd54adedfb3 100644 --- a/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx +++ b/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx @@ -16,9 +16,9 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx b/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx index 1607c30b94a..a8277d122db 100644 --- a/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx +++ b/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx @@ -16,9 +16,9 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/PhotonMeson/Tasks/HeavyNeutralMeson.cxx b/PWGEM/PhotonMeson/Tasks/HeavyNeutralMeson.cxx index 4e345a26c02..a92e1888049 100644 --- a/PWGEM/PhotonMeson/Tasks/HeavyNeutralMeson.cxx +++ b/PWGEM/PhotonMeson/Tasks/HeavyNeutralMeson.cxx @@ -17,9 +17,11 @@ /// #include "PWGEM/PhotonMeson/Utils/HNMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "Common/Core/TrackSelection.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseITS.h" @@ -27,22 +29,30 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector4D.h" -#include "TMath.h" -#include "TRandom3.h" - -#include "fairlogger/Logger.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include + +#include +#include +#include #include #include diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx index 298f05a1198..2ecfd14711d 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/EventSelectionParams.h" @@ -36,7 +37,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include @@ -70,10 +71,10 @@ using namespace o2::aod::pwgem::dilepton::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils; using o2::constants::math::TwoPI; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyCollisionsMC = soa::Join; +using MyCollisionsMC = soa::Join; using MyCollisionMC = MyCollisionsMC::iterator; using MyMCCollisions = soa::Join; @@ -82,7 +83,7 @@ using MyMCCollision = MyMCCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyPrimaryElectrons = soa::Filtered>; +using MyPrimaryElectrons = soa::Filtered>; using MyPrimaryElectron = MyPrimaryElectrons::iterator; using MyMCV0Legs = soa::Join; @@ -831,8 +832,8 @@ struct MaterialBudget { } SliceCache cache; - Preslice perCollision = aod::v0photonkf::emeventId; - Preslice perCollisionElectron = aod::emprimaryelectron::emeventId; + Preslice perCollision = aod::v0photonkf::pmeventId; + Preslice perCollisionElectron = aod::emprimaryelectronda::pmeventId; Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx index a2cea8bd2b3..463bc9045a8 100644 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx @@ -18,9 +18,12 @@ #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Common/Core/RecoDecay.h" // #include "PWGEM/Dilepton/Utils/MCUtilities.h" @@ -34,10 +37,9 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include -#include #include #include @@ -57,7 +59,7 @@ 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; @@ -227,7 +229,7 @@ struct MaterialBudgetMC { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision_pcm = aod::v0photonkf::emeventId; + Preslice perCollision_pcm = aod::v0photonkf::pmeventId; template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& tagcut, TCut2 const& probecut) diff --git a/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx b/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx index 556aa96bd6c..587546ff802 100644 --- a/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx @@ -19,28 +19,35 @@ #include "PWGEM/PhotonMeson/Utils/HNMUtilities.h" #include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "Common/Core/TrackSelection.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector4D.h" -#include "TMath.h" -#include "TRandom3.h" - -#include "fairlogger/Logger.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include +#include +#include #include #include diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx index e36da8a2556..573b8d0224e 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMDalitzEE.cxx @@ -28,7 +28,7 @@ using namespace o2::aod::pwgem::photonmeson::photonpair; using MyV0Photons = soa::Filtered>; using MyMCV0Legs = soa::Join; -using MyMCElectrons = soa::Filtered>; +using MyMCElectrons = soa::Filtered>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx index 62c57593fd0..9ec33da1389 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCM.cxx @@ -13,6 +13,7 @@ /// \brief This code loops over photons and makes pairs for neutral mesons analyses in MC for PCM-PCM. /// \author D. Sekihata, daiki.sekihata@cern.ch +#include "PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h" #include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -26,7 +27,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::photonpair; -using MyV0Photons = o2::soa::Filtered>; +using MyV0Photons = o2::soa::Filtered>; using MyMCV0Legs = soa::Join; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx new file mode 100644 index 00000000000..c5b06741e75 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMCPCMPCMML.cxx @@ -0,0 +1,37 @@ +// 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 Pi0EtaToGammaGammaMCPCMPCMML.cxx +/// \brief This code loops over photons and makes pairs for neutral mesons analyses in MC for PCM-PCM with additional ML-based photon cuts. +/// \author Isabel Kantak, isabel.kantak@cern.ch + +#include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::aod::pwgem::photonmeson::photonpair; + +using MyV0Photons = o2::soa::Filtered>; +using MyMCV0Legs = soa::Join; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-mc-pcmpcm"}), + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx index 27d1c1cca7d..810be128a00 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMDalitzEE.cxx @@ -18,7 +18,6 @@ #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include -#include #include #include @@ -29,7 +28,7 @@ using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::photonpair; using MyV0Photons = Filtered>; -using MyPrimaryElectrons = Filtered>; +using MyPrimaryElectrons = Filtered>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx index 6272af75da6..a19c2ac5be0 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCM.cxx @@ -13,6 +13,7 @@ /// \brief This code loops over photons and makes pairs for neutral mesons analyses for PCM-PCM. /// \author D. Sekihata, daiki.sekihata@cern.ch +#include "PWGEM/PhotonMeson/Core/MaterialBudgetWeights.h" #include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -26,7 +27,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::photonpair; -using MyV0Photons = o2::soa::Filtered>; +using MyV0Photons = o2::soa::Filtered>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.cxx new file mode 100644 index 00000000000..2d0fa9f2120 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaPCMPCMML.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. +// +/// \file Pi0EtaToGammaGammaPCMPCMML.cxx +/// \brief This code loops over photons and makes pairs for neutral mesons analyses for PCM-PCM with additional ML cuts to photons. +/// \author Isabel Kantak, isabel.kantak@cern.ch + +#include "PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::aod::pwgem::photonmeson::photonpair; + +using MyV0Photons = o2::soa::Filtered>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"pi0eta-to-gammagamma-pcmpcm"}), + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index 5d5972e3685..62d2e47a234 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -21,6 +21,7 @@ #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/TriggerAliases.h" @@ -53,7 +54,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; @@ -241,7 +242,7 @@ struct SinglePhoton { LOGF(info, "Number of EMCal cuts = %d", fEMCCuts.size()); } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::pmeventId; // Preslice perCollision_phos = aod::skimmedcluster::collisionId; // Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index b9aeedf9ffa..e8e083dca28 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -21,6 +21,7 @@ #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -52,7 +53,7 @@ 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; @@ -242,7 +243,7 @@ struct SinglePhotonMC { // LOGF(info, "Number of EMCal cuts = %d", fEMCCuts.size()); // } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::pmeventId; // Preslice perCollision_phos = aod::skimmedcluster::collisionId; // Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx index a2d09adcc0f..818eb101285 100644 --- a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx +++ b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx @@ -22,6 +22,7 @@ #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -42,6 +43,7 @@ #include #include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include @@ -65,15 +67,12 @@ using namespace o2::soa; 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; using MyV0Photon = MyV0Photons::iterator; -using MyDalitzEEs = soa::Join; -using MyDalitzEE = MyDalitzEEs::iterator; - struct TagAndProbe { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; @@ -248,7 +247,7 @@ struct TagAndProbe { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::pmeventId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0MCPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0MCPCMDalitzEE.cxx index ccdc4184568..89a84ccd2df 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0MCPCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0MCPCMDalitzEE.cxx @@ -14,16 +14,19 @@ // This code loops over photons and makes pairs for neutral mesons analyses. // Please write to: daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "PWGEM/PhotonMeson/Core/TaggingPi0MC.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include +#include using namespace o2; using namespace o2::aod; +using namespace o2::framework; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"tagging-pi0-mc-pcmdalitzee"}), + adaptAnalysisTask>(cfgc, TaskName{"tagging-pi0-mc-pcmdalitzee"}), }; } diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0PCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0PCMDalitzEE.cxx index 2292faef120..4b94c5b4f29 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0PCMDalitzEE.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0PCMDalitzEE.cxx @@ -14,16 +14,19 @@ // This code loops over photons and makes pairs for neutral mesons analyses. // Please write to: daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/TaggingPi0.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -using namespace o2; -using namespace o2::aod; +#include +#include + +using namespace o2::framework; +using namespace o2::aod::pwgem::photonmeson::photonpair; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask>(cfgc, TaskName{"tagging-pi0-pcmdalitzee"}), + adaptAnalysisTask>(cfgc, TaskName{"tagging-pi0-pcmdalitzee"}), }; } diff --git a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx index 91469523448..12b03c22cf4 100644 --- a/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx +++ b/PWGEM/PhotonMeson/Tasks/calibTaskEmc.cxx @@ -17,16 +17,15 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" -// -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include #include @@ -49,19 +48,18 @@ #include #include -#include -#include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include +#include + #include #include #include -#include -#include #include +#include #include #include #include @@ -73,6 +71,16 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; +enum QvecEstimator { + FT0M = 0, + FT0A = 1, + FT0C, + TPCPos, + TPCNeg, + TPCTot, + FV0A +}; + enum CentralityEstimator { None = 0, CFT0A = 1, @@ -93,25 +101,27 @@ enum Harmonics { kOctagonal = 8 }; -struct CalibTaskEmc { - static constexpr float MinEnergy = 0.7f; +enum class MapLevel { + kGood = 1, + kNoBad = 2, + kInEMC = 3, + kAll = 4 +}; +struct CalibTaskEmc { // configurable for flow Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable cfgDoRotation{"cfgDoRotation", false, "Flag to enable rotation background method"}; - Configurable cfgDownsampling{"cfgDownsampling", 1, "Calculate rotation background only for every collision"}; Configurable cfgEMCalMapLevelBackground{"cfgEMCalMapLevelBackground", 4, "Different levels of correction for the background, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: exclude bad channels, 1: remove edges)"}; Configurable cfgEMCalMapLevelSameEvent{"cfgEMCalMapLevelSameEvent", 4, "Different levels of correction for the same event, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: exclude bad channels, 1: remove edges)"}; - Configurable cfgRotAngle{"cfgRotAngle", std::move(const_cast(o2::constants::math::PIHalf)), "Angle used for the rotation method"}; Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; - Configurable cfgMaxAsymmetry{"cfgMaxAsymmetry", 0.1f, "Maximum allowed asymmetry for photon pairs used in calibration when using EMC-EMC."}; + Configurable cfgMaxAsymmetry{"cfgMaxAsymmetry", 0.1f, "Maximum allowed asymmetry for photon pairs used in calibration."}; // configurable axis ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {400, 0.0, 0.8}, ""}; - ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {100, 0., 20.}, ""}; ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {20, 0., 100.}, ""}; - ConfigurableAxis thnConfigAxisEnergyCalib{"thnConfigAxisEnergyCalib", {200, 0., 20.}, ""}; + ConfigurableAxis thnConfigAxisEnergyCalib{"thnConfigAxisEnergyCalib", {200, 0., 20.}, "Cluster energy axis for calibration"}; + ConfigurableAxis thnConfigAxisPtCalib{"thnConfigAxisPtCalib", {200, 0., 20.}, "Pt axis for calibration, mostly for PCM"}; EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { @@ -126,20 +136,17 @@ struct CalibTaskEmc { Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgRequireEMCReadoutInMB{"cfgRequireEMCReadoutInMB", true, "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 cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -1, "min. track occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -1, "min. FT0C occupancy"}; Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; Configurable cfgMinCent{"cfgMinCent", 0, "min. centrality (%)"}; Configurable cfgMaxCent{"cfgMaxCent", 90, "max. centrality (%)"}; Configurable onlyKeepWeightedEvents{"onlyKeepWeightedEvents", false, "flag to keep only weighted events (for JJ MCs) and remove all MB events (with weight = 1)"}; - Configurable cfgEnableQA{"cfgEnableQA", false, "flag to turn QA plots on/off"}; } eventcuts; EMCPhotonCut fEMCCut; struct : ConfigurableGroup { std::string prefix = "emccuts"; - Configurable clusterDefinition{"clusterDefinition", "kV3Default", "Clusterizer to be selected, e.g. V3Default"}; + Configurable clusterDefinition{"clusterDefinition", "kV3MostSplitSmallestTimeDiff", "Clusterizer to be selected, e.g. V3Default"}; Configurable cfgEMCminTime{"cfgEMCminTime", -25., "Minimum cluster time for EMCal time cut"}; Configurable cfgEMCmaxTime{"cfgEMCmaxTime", +30., "Maximum cluster time for EMCal time cut"}; Configurable cfgEMCminM02{"cfgEMCminM02", 0.1, "Minimum M02 for EMCal M02 cut"}; @@ -152,14 +159,14 @@ struct CalibTaskEmc { Configurable> emcSecTMPhi{"emcSecTMPhi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; Configurable cfgEMCEoverp{"cfgEMCEoverp", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; Configurable cfgEMCUseExoticCut{"cfgEMCUseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; - Configurable cfgEMCUseTM{"cfgEMCUseTM", true, "flag to use EMCal track matching cut or not"}; + Configurable cfgEMCUseTM{"cfgEMCUseTM", false, "flag to use EMCal track matching cut or not"}; Configurable emcUseSecondaryTM{"emcUseSecondaryTM", false, "flag to use EMCal secondary track matching cut or not"}; Configurable cfgEnableQA{"cfgEnableQA", false, "flag to turn QA plots on/off"}; } emccuts; - V0PhotonCut fPCMPhotonCut; + V0PhotonCut fV0PhotonCut; struct : o2::framework::ConfigurableGroup { - std::string prefix = "pcmcuts"; + std::string prefix = "PCMcuts"; o2::framework::Configurable requireV0WithITSTPC{"requireV0WithITSTPC", false, "flag to enforce V0s have ITS and TPC"}; o2::framework::Configurable requireV0WithITSOnly{"requireV0WithITSOnly", false, "flag to select V0s with ITSonly tracks"}; o2::framework::Configurable requireV0WithTPCOnly{"requireV0WithTPCOnly", false, "flag to select V0s with TPConly tracks"}; @@ -177,6 +184,11 @@ struct CalibTaskEmc { o2::framework::Configurable rejectV0onITSib{"rejectV0onITSib", true, "flag to reject V0s on ITSib"}; o2::framework::Configurable applyPrefilter{"applyPrefilter", false, "flag to apply prefilter to V0"}; + o2::framework::Configurable mTooCloseType{"mTooCloseType", 2, "type of cut for too close (0 = no, 1 = squared distance, 2 = opening angle + dR) "}; + o2::framework::Configurable mMinV0DistSquared{"mMinV0DistSquared", 4.f, "min squared distance for mTooCloseType == 1"}; + o2::framework::Configurable mDeltaR{"mDeltaR", 6.f, "deltaR for mTooCloseType == 2"}; + o2::framework::Configurable mMinOpeningAngle{"mMinOpeningAngle", 0.02, "min opening angle for mTooCloseType == 2"}; + o2::framework::Configurable minNClusterTPC{"minNClusterTPC", 0, "min NCluster TPC"}; o2::framework::Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 40, "min ncrossed rows in TPC"}; o2::framework::Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "min fraction of crossed rows over findable clusters in TPC"}; @@ -190,6 +202,7 @@ struct CalibTaskEmc { o2::framework::Configurable maxTPCNSigmaEl{"maxTPCNSigmaEl", +3.0f, "max. TPC n sigma for electron"}; o2::framework::Configurable disableITSOnly{"disableITSOnly", false, "flag to disable ITSonly tracks"}; o2::framework::Configurable disableTPCOnly{"disableTPCOnly", false, "flag to disable TPConly tracks"}; + o2::framework::Configurable doQA{"doQA", false, "flag to set QA flag."}; } pcmcuts; struct : ConfigurableGroup { @@ -203,69 +216,66 @@ struct CalibTaskEmc { struct : ConfigurableGroup { std::string prefix = "mixingConfig"; - ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -9.0f, -8.f, -7.0f, -6.f, -5.0f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f}, "Mixing bins - z-vertex"}; + 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 cfgCentBins{"cfgCentBins", {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}, "Mixing bins - centrality"}; Configurable cfgMixingDepth{"cfgMixingDepth", 2, "Mixing depth"}; } mixingConfig; + struct : ConfigurableGroup { + std::string prefix = "correctionConfig"; + Configurable cfgEnableNonLinEMC{"cfgEnableNonLinEMC", false, "flag to turn extra non linear energy calibration for EMCal on/off"}; + Configurable cfgEnableNonLinPCM{"cfgEnableNonLinPCM", false, "flag to turn extra non linear energy calibration for PCM on/off"}; + } correctionConfig; + SliceCache cache; o2::framework::Service ccdb; int runNow = 0; int runBefore = -1; - using EMCalPhotons = soa::Join; - using PCMPhotons = soa::Join; - using Colls = soa::Join; - - // for event mixing - using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, o2::aod::pwgem::dilepton::utils::EMTrack>; - MyEMH* emh1 = nullptr; - MyEMH* emh2 = nullptr; + Filter collisionFilter = (nabs(aod::collision::posZ) <= eventcuts.cfgZvtxMax) && (aod::evsel::ft0cOccupancyInTimeRange <= eventcuts.cfgFT0COccupancyMax) && (aod::evsel::ft0cOccupancyInTimeRange >= eventcuts.cfgFT0COccupancyMin); + using EMCalPhotons = soa::Join; + using PCMPhotons = soa::Join; + using FilteredCollsWithQvecs = soa::Filtered>; + using CollsWithQvecs = soa::Join; + using Colls = soa::Join; - PresliceOptional perCollisionEMC = aod::emccluster::emeventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emeventId; - - using BinningType = ColumnBinningPolicy; - BinningType binningOnPositions{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins}, true}; - Pair pairPCMEMC{binningOnPositions, mixingConfig.cfgMixingDepth, -1, &cache}; // indicates that mixingConfig.cfgMixingDepth events should be mixed and under/overflow (-1) to be ignored + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::pmeventId; + PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; + PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; o2::emcal::Geometry* emcalGeom; o2::emcal::BadChannelMap* mBadChannels; - // Constants for eta and phi ranges - double etaMin = -0.75, etaMax = 0.75; - int nBinsEta = 150; // 150 bins for eta - - double phiMin = 1.35, phiMax = 5.75; - int nBinsPhi = 440; // (440 bins = 0.01 step size covering most regions) + // Constants for eta and phi ranges for the look up table + static constexpr double EtaMin = -0.75, etaMax = 0.75; + static constexpr int NBinsEta = 150; // 150 bins for eta - std::vector lookupTable1D; - float epsilon = 1.e-8; + static constexpr double PhiMin = 1.35, phiMax = 5.75; + static constexpr int NBinsPhi = 440; // (440 bins = 0.01 step size covering most regions) - // static constexpr - static constexpr int64_t NMinPhotonRotBkg = 3; - static constexpr int64_t NMinPhotonRotBkgMixed = 2; + std::array lookupTable1D; // Usage when cfgEnableNonLin is enabled - std::unique_ptr fEMCalCorrectionFactor; // ("fEMCalCorrectionFactor","(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); + uint8_t nColl = 1; // To access the 1D array - inline int getIndex(int iEta, int iPhi) + static inline int getIndex(int iEta, int iPhi) { - return iEta * nBinsPhi + iPhi; + return iEta * NBinsPhi + iPhi; } // Function to access the lookup table inline int8_t checkEtaPhi1D(double eta, double phi) { - if (eta < etaMin || eta > etaMax || phi < phiMin || phi > phiMax) { + if (eta < EtaMin || eta > etaMax || phi < PhiMin || phi > phiMax) { return 3; // Out of bounds } // Compute indices directly - int iEta = static_cast((eta - etaMin) / ((etaMax - etaMin) / nBinsEta)); - int iPhi = static_cast((phi - phiMin) / ((phiMax - phiMin) / nBinsPhi)); + int iEta = static_cast((eta - EtaMin) / ((etaMax - EtaMin) / NBinsEta)); + int iPhi = static_cast((phi - PhiMin) / ((phiMax - PhiMin) / NBinsPhi)); return lookupTable1D[getIndex(iEta, iPhi)]; } @@ -288,6 +298,7 @@ struct CalibTaskEmc { void defineEMCCut() { fEMCCut = EMCPhotonCut("fEMCCut", "fEMCCut"); + fEMCCut.SetTrackMatchingEtaParams(emccuts.cfgEMCTMEta->at(0), emccuts.cfgEMCTMEta->at(1), emccuts.cfgEMCTMEta->at(2)); fEMCCut.SetTrackMatchingPhiParams(emccuts.cfgEMCTMPhi->at(0), emccuts.cfgEMCTMPhi->at(1), emccuts.cfgEMCTMPhi->at(2)); @@ -303,96 +314,114 @@ struct CalibTaskEmc { fEMCCut.SetClusterizer(emccuts.clusterDefinition); fEMCCut.SetUseTM(emccuts.cfgEMCUseTM.value); // disables or enables TM fEMCCut.SetUseSecondaryTM(emccuts.emcUseSecondaryTM.value); // disables or enables secondary TM + fEMCCut.SetDoQA(emccuts.cfgEnableQA.value); } void definePCMCut() { - fPCMPhotonCut = V0PhotonCut("fPCMPhotonCut", "fPCMPhotonCut"); + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); // for v0 - fPCMPhotonCut.SetV0PtRange(pcmcuts.minPtV0, pcmcuts.maxPtV0); - fPCMPhotonCut.SetV0EtaRange(pcmcuts.minEtaV0, pcmcuts.maxEtaV0); - fPCMPhotonCut.SetMinCosPA(pcmcuts.minCosPA); - fPCMPhotonCut.SetMaxPCA(pcmcuts.maxPCA); - fPCMPhotonCut.SetMaxChi2KF(pcmcuts.maxChi2KF); - fPCMPhotonCut.SetRxyRange(pcmcuts.minRV0, pcmcuts.maxRV0); - fPCMPhotonCut.SetAPRange(pcmcuts.maxAlphaAP, pcmcuts.maxQtAP); - fPCMPhotonCut.RejectITSib(pcmcuts.rejectV0onITSib); + fV0PhotonCut.SetV0PtRange(pcmcuts.minPtV0, pcmcuts.maxPtV0); + fV0PhotonCut.SetV0EtaRange(pcmcuts.minEtaV0, pcmcuts.maxEtaV0); + fV0PhotonCut.SetMinCosPA(pcmcuts.minCosPA); + fV0PhotonCut.SetMaxPCA(pcmcuts.maxPCA); + fV0PhotonCut.SetMaxChi2KF(pcmcuts.maxChi2KF); + fV0PhotonCut.SetRxyRange(pcmcuts.minRV0, pcmcuts.maxRV0); + fV0PhotonCut.SetAPRange(pcmcuts.maxAlphaAP, pcmcuts.maxQtAP); + fV0PhotonCut.RejectITSib(pcmcuts.rejectV0onITSib); + fV0PhotonCut.setTooCloseType(static_cast(pcmcuts.mTooCloseType.value)); + fV0PhotonCut.setMinV0DistSquared(pcmcuts.mMinV0DistSquared); + fV0PhotonCut.setDeltaR(pcmcuts.mDeltaR); + fV0PhotonCut.setMinOpeningAngle(pcmcuts.mMinOpeningAngle); // for track - fPCMPhotonCut.SetMinNClustersTPC(pcmcuts.minNClusterTPC); - fPCMPhotonCut.SetMinNCrossedRowsTPC(pcmcuts.minNCrossedRowsTPC); - fPCMPhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(pcmcuts.minNCrossedRowsOverFindableClustersTPC); - fPCMPhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.maxFracSharedClustersTPC); - fPCMPhotonCut.SetChi2PerClusterTPC(0.f, pcmcuts.macChi2TPC); - fPCMPhotonCut.SetTPCNsigmaElRange(pcmcuts.minTPCNSigmaEl, pcmcuts.maxTPCNSigmaEl); - fPCMPhotonCut.SetChi2PerClusterITS(0.f, pcmcuts.macChi2ITS); - fPCMPhotonCut.SetNClustersITS(pcmcuts.minNClusterITS, 7); - fPCMPhotonCut.SetMeanClusterSizeITSob(pcmcuts.minMeanClusterSizeITSob, pcmcuts.maxMeanClusterSizeITSob); - fPCMPhotonCut.SetDisableITSonly(pcmcuts.disableITSOnly); - fPCMPhotonCut.SetDisableTPConly(pcmcuts.disableTPCOnly); - fPCMPhotonCut.SetRequireITSTPC(pcmcuts.requireV0WithITSTPC); - fPCMPhotonCut.SetRequireITSonly(pcmcuts.requireV0WithITSOnly); - fPCMPhotonCut.SetRequireTPConly(pcmcuts.requireV0WithTPCOnly); + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.minNClusterTPC); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.minNCrossedRowsTPC); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(pcmcuts.minNCrossedRowsOverFindableClustersTPC); + fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.maxFracSharedClustersTPC); + fV0PhotonCut.SetChi2PerClusterTPC(0.f, pcmcuts.macChi2TPC); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.minTPCNSigmaEl, pcmcuts.maxTPCNSigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(0.f, pcmcuts.macChi2ITS); + fV0PhotonCut.SetNClustersITS(pcmcuts.minNClusterITS, 7); + fV0PhotonCut.SetMeanClusterSizeITSob(pcmcuts.minMeanClusterSizeITSob, pcmcuts.maxMeanClusterSizeITSob); + fV0PhotonCut.SetDisableITSonly(pcmcuts.disableITSOnly); + fV0PhotonCut.SetDisableTPConly(pcmcuts.disableTPCOnly); + fV0PhotonCut.SetRequireITSTPC(pcmcuts.requireV0WithITSTPC); + fV0PhotonCut.SetRequireITSonly(pcmcuts.requireV0WithITSOnly); + fV0PhotonCut.SetRequireTPConly(pcmcuts.requireV0WithTPCOnly); + + fV0PhotonCut.setDoQA(pcmcuts.doQA.value); } void init(InitContext&) { + defineEMEventCut(); defineEMCCut(); + fEMCCut.addQAHistograms(®istry); + definePCMCut(); + fV0PhotonCut.addQAHistograms(®istry); o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(®istry); const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, "#it{M}_{#gamma#gamma} (GeV/#it{c}^{2})"}; - const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality (%)"}; const AxisSpec thAxisTanThetaPhi{mesonConfig.thConfigAxisTanThetaPhi, "atan(#Delta#theta/#Delta#varphi)"}; - const AxisSpec thAxisClusterEnergy{thnConfigAxisPt, "#it{E} (GeV)"}; const AxisSpec thAxisEnergyCalib{thnConfigAxisEnergyCalib, "#it{E}_{clus} (GeV)"}; + const AxisSpec thnAxisPtCalib{thnConfigAxisPtCalib, "#it{p}_{T,#gamma} (GeV)"}; + const AxisSpec thnAxisPtCalibMeson{thnConfigAxisPtCalib, "#it{p}_{T,meson} (GeV)"}; const AxisSpec thAxisAlpha{100, -1., +1, "#alpha"}; const AxisSpec thAxisEnergy{1000, 0., 100., "#it{E}_{clus} (GeV)"}; + const AxisSpec thAxisEta{320, -0.8, 0.8, "#eta"}; + const AxisSpec thAxisPhi{500, 0, 2 * 3.14159, "phi"}; + const AxisSpec thAxisOpeningAngle{180, 0, o2::constants::math::PI, "opening angle (rad)"}; + + const AxisSpec thnAxisMixingVtx{mixingConfig.cfgVtxBins, "#it{z} (cm)"}; + const AxisSpec thnAxisMixingCent{mixingConfig.cfgCentBins, "Centrality (%)"}; + + if (doprocessEMCal || doprocessEMCalPCMC) { + registry.add("hSparsePi0", "m_{inv} vs E vs cent for same event", HistType::kTH3D, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); + registry.add("hOpeningAngleSE", "opening vs E vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thAxisEnergyCalib, thnAxisCent}); + } else if (doprocessPCM) { + registry.add("hSparsePi0", "m_{inv} vs p_T vs cent for same event", HistType::kTH3D, {thnAxisInvMass, thnAxisPtCalib, thnAxisCent}); + registry.add("hOpeningAngleSE", "opening vs p_T vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thnAxisPtCalib, thnAxisCent}); + } - registry.add("hSparseCalibSE", "THn for Calib same event", HistType::kTHnSparseF, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); - registry.add("hSparseCalibBack", "THn for Calib background", HistType::kTHnSparseF, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); - - auto hClusterCuts = registry.add("hClusterCuts", "hClusterCuts;;Counts", kTH1D, {{6, 0.5, 6.5}}, false); - hClusterCuts->GetXaxis()->SetBinLabel(1, "in"); - hClusterCuts->GetXaxis()->SetBinLabel(2, "opening angle"); - hClusterCuts->GetXaxis()->SetBinLabel(3, "#it{M}_{#gamma#gamma}"); - hClusterCuts->GetXaxis()->SetBinLabel(4, "#it{p}_{T}"); - hClusterCuts->GetXaxis()->SetBinLabel(5, "conversion cut"); - hClusterCuts->GetXaxis()->SetBinLabel(6, "out"); - - auto hClusterCutsMixed = registry.add("hClusterCutsMixed", "hClusterCutsMixed;;Counts", kTH1D, {{6, 0.5, 6.5}}, false); - hClusterCutsMixed->GetXaxis()->SetBinLabel(1, "in"); - hClusterCutsMixed->GetXaxis()->SetBinLabel(2, "opening angle"); - hClusterCutsMixed->GetXaxis()->SetBinLabel(3, "#it{M}_{#gamma#gamma}"); - hClusterCutsMixed->GetXaxis()->SetBinLabel(4, "#it{p}_{T}"); - hClusterCutsMixed->GetXaxis()->SetBinLabel(5, "conversion cut"); - hClusterCutsMixed->GetXaxis()->SetBinLabel(6, "out"); - - if (eventcuts.cfgEnableQA) { - auto hCollisionEMCCheck = registry.add("hCollisionEMCCheck", "collision counter;;Counts", kTH1D, {{7, 0.5, 7.5}}, false); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(1, "all"); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(2, "EMC MB Readout"); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(3, "has clusters"); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(4, "EMC MB Readout & has clusters"); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(5, "EMC MB Readout but no clusters"); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(6, "No EMC MB Readout but has clusters"); - hCollisionEMCCheck->GetXaxis()->SetBinLabel(7, "No EMC MB Readout and no clusters"); + if (doprocessEMCalMixed || doprocessEMCalPCMMixed) { + registry.add("hSparseBkgMix", "m_{inv} vs p_T vs cent for mixed event", HistType::kTH3D, {thnAxisInvMass, thAxisEnergyCalib, thnAxisCent}); + registry.add("hOpeningAngleME", "opening vs E vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thAxisEnergyCalib, thnAxisCent}); + } else if (doprocessPCMMixed) { + registry.add("hSparseBkgMix", "m_{inv} vs p_T vs cent for mixed event", HistType::kTH3D, {thnAxisInvMass, thnAxisPtCalib, thnAxisCent}); + registry.add("hOpeningAngleME", "opening vs p_T vs cent for same event", HistType::kTH3D, {thAxisOpeningAngle, thnAxisPtCalib, thnAxisCent}); } - if (emccuts.cfgEnableQA) { - registry.add("hEClusterBefore", "Histo for cluster energy before cuts", HistType::kTH1D, {thAxisClusterEnergy}); - registry.add("hEClusterAfter", "Histo for cluster energy after cuts", HistType::kTH1D, {thAxisClusterEnergy}); + if (doprocessEMCalMixed || doprocessEMCalPCMMixed || doprocessPCMMixed) { + registry.add("hMixingCount", "THn Event Mixing QA", HistType::kTH2D, {thnAxisMixingVtx, thnAxisMixingCent}); } - if (mesonConfig.cfgEnableQA) { - registry.add("hInvMassPt", "Histo for inv pair mass vs pt", HistType::kTH2D, {thnAxisInvMass, thnAxisPt}); - registry.add("hTanThetaPhi", "Histo for identification of conversion cluster", HistType::kTH2D, {thnAxisInvMass, thAxisTanThetaPhi}); - registry.add("hAlphaPt", "Histo of meson asymmetry vs pT", HistType::kTH2D, {thAxisAlpha, thnAxisPt}); - registry.add("hInvMassPtMixed", "Histo for inv pair mass vs pt for mixed event", HistType::kTH2D, {thnAxisInvMass, thnAxisPt}); - registry.add("hTanThetaPhiMixed", "Histo for identification of conversion cluster for mixed event", HistType::kTH2D, {thnAxisInvMass, thAxisTanThetaPhi}); - registry.add("hAlphaPtMixed", "Histo of meson asymmetry vs pT for mixed event", HistType::kTH2D, {thAxisAlpha, thnAxisPt}); + auto hMesonCuts = registry.add("hMesonCuts", "hMesonCuts;;Counts", kTH1D, {{6, 0.5, 6.5}}, false); + hMesonCuts->GetXaxis()->SetBinLabel(1, "in"); + hMesonCuts->GetXaxis()->SetBinLabel(2, "opening angle"); + hMesonCuts->GetXaxis()->SetBinLabel(3, "#it{M}_{#gamma#gamma}"); + hMesonCuts->GetXaxis()->SetBinLabel(4, "#it{p}_{T}"); + hMesonCuts->GetXaxis()->SetBinLabel(5, "conversion cut"); + hMesonCuts->GetXaxis()->SetBinLabel(6, "out"); + + auto hMesonCutsMixed = registry.add("hMesonCutsMixed", "hMesonCutsMixed;;Counts", kTH1D, {{6, 0.5, 6.5}}, false); + hMesonCutsMixed->GetXaxis()->SetBinLabel(1, "in"); + hMesonCutsMixed->GetXaxis()->SetBinLabel(2, "opening angle"); + hMesonCutsMixed->GetXaxis()->SetBinLabel(3, "#it{M}_{#gamma#gamma}"); + hMesonCutsMixed->GetXaxis()->SetBinLabel(4, "#it{p}_{T}"); + hMesonCutsMixed->GetXaxis()->SetBinLabel(5, "conversion cut"); + hMesonCutsMixed->GetXaxis()->SetBinLabel(6, "out"); + + if (mesonConfig.cfgEnableQA.value) { + registry.add("mesonQA/hInvMassPt", "Histo for inv pair mass vs pt", HistType::kTH2D, {thnAxisInvMass, thnAxisPtCalibMeson}); + registry.add("mesonQA/hTanThetaPhi", "Histo for identification of conversion cluster", HistType::kTH2D, {thnAxisInvMass, thAxisTanThetaPhi}); + registry.add("mesonQA/hAlphaPt", "Histo of meson asymmetry vs pT", HistType::kTH2D, {thAxisAlpha, thnAxisPtCalib}); + registry.add("mesonQA/hInvMassPtMixed", "Histo for inv pair mass vs pt for mixed event", HistType::kTH2D, {thnAxisInvMass, thnAxisPtCalibMeson}); + registry.add("mesonQA/hTanThetaPhiMixed", "Histo for identification of conversion cluster for mixed event", HistType::kTH2D, {thnAxisInvMass, thAxisTanThetaPhi}); + registry.add("mesonQA/hAlphaPtMixed", "Histo of meson asymmetry vs pT for mixed event", HistType::kTH2D, {thAxisAlpha, thnAxisPtCalib}); } ccdb->setURL(ccdbUrl); @@ -400,24 +429,41 @@ struct CalibTaskEmc { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - LOG(info) << "thnConfigAxisInvMass.value[1] = " << thnConfigAxisInvMass.value[1] << " thnConfigAxisInvMass.value.back() = " << thnConfigAxisInvMass.value.back(); - LOG(info) << "thnConfigAxisPt.value[1] = " << thnConfigAxisPt.value[1] << " thnConfigAxisPt.value.back() = " << thnConfigAxisPt.value.back(); - - fEMCalCorrectionFactor = std::make_unique("fEMCalCorrectionFactor", "(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); - fEMCalCorrectionFactor->SetParameters(-5.33426e-01, 1.40144e-02, -5.24434e-01); }; // end init /// Change radians to degree /// \param angle in radians /// \return angle in degree - float getAngleDegree(float angle) + static constexpr float getAngleDegree(float angle) + { + return angle * o2::constants::math::Rad2Deg; + } + + /// Fill THnSparse + /// \param mass is the invariant mass of the candidate + /// \param pt is the transverse momentum of the candidate + /// \param cent is the centrality of the collision + template + void fillThn(const float mass, const float pt, const float cent) + { + static constexpr std::string_view HistTypes[3] = {"hSparsePi0", "hSparseBkgRot", "hSparseBkgMix"}; + registry.fill(HIST(HistTypes[histType]), mass, pt, cent); + } + + /// Fill THnSparse + /// \param openingAngle opening angle between the two photons + /// \param pt is the transverse momentum of the candidate + /// \param cent is the centrality of the collision + template + void fillOpeningAngleHisto(const float openingAngle, const float pt, const float cent) { - return angle * 180.f * std::numbers::inv_pi_v; + static constexpr std::string_view HistTypes[3] = {"hOpeningAngleSE", "hOpeningAngleRot", "hOpeningAngleME"}; + registry.fill(HIST(HistTypes[histType]), openingAngle, pt, cent); } /// Get the centrality /// \param collision is the collision with the centrality information - template + template float getCentrality(TCollision const& collision) { float cent = -999.; @@ -484,349 +530,278 @@ struct CalibTaskEmc { return masked; } - template + template void initCCDB(TCollision const& collision) { // Load EMCal geometry emcalGeom = o2::emcal::Geometry::GetInstanceFromRunNumber(collision.runNumber()); // Load Bad Channel map mBadChannels = ccdb->getForTimeStamp("EMC/Calib/BadChannelMap", collision.timestamp()); - lookupTable1D = std::vector(nBinsEta * nBinsPhi, -1); - double binWidthEta = (etaMax - etaMin) / nBinsEta; - double binWidthPhi = (phiMax - phiMin) / nBinsPhi; - - for (int iEta = 0; iEta < nBinsEta; ++iEta) { - double etaCenter = etaMin + (iEta + 0.5) * binWidthEta; - for (int iPhi = 0; iPhi < nBinsPhi; ++iPhi) { - double phiCenter = phiMin + (iPhi + 0.5) * binWidthPhi; - try { - // Get the cell ID - int cellID = emcalGeom->GetAbsCellIdFromEtaPhi(etaCenter, phiCenter); - - // Check conditions for the cell - if (isTooCloseToEdge(cellID, 1)) { - lookupTable1D[getIndex(iEta, iPhi)] = 2; // Edge - } else if (isCellMasked(cellID)) { - lookupTable1D[getIndex(iEta, iPhi)] = 1; // Bad - } else { - lookupTable1D[getIndex(iEta, iPhi)] = 0; // Good + lookupTable1D.fill(-1); + double binWidthEta = (etaMax - EtaMin) / NBinsEta; + double binWidthPhi = (phiMax - PhiMin) / NBinsPhi; + + if (cfgEMCalMapLevelBackground.value >= static_cast(MapLevel::kAll) && cfgEMCalMapLevelSameEvent >= static_cast(MapLevel::kAll)) { + // in this case we do not want to check the clusters, so just say thery are all good. + lookupTable1D.fill(0); // good + } else { + for (int iEta = 0; iEta < NBinsEta; ++iEta) { + double etaCenter = EtaMin + (iEta + 0.5) * binWidthEta; + for (int iPhi = 0; iPhi < NBinsPhi; ++iPhi) { + double phiCenter = PhiMin + (iPhi + 0.5) * binWidthPhi; + try { + // Get the cell ID + int cellID = emcalGeom->GetAbsCellIdFromEtaPhi(etaCenter, phiCenter); + + // Check conditions for the cell + if (isTooCloseToEdge(cellID, 1)) { + lookupTable1D[getIndex(iEta, iPhi)] = 2; // Edge + } else if (isCellMasked(cellID)) { + lookupTable1D[getIndex(iEta, iPhi)] = 1; // Bad + } else { + lookupTable1D[getIndex(iEta, iPhi)] = 0; // Good + } + } catch (o2::emcal::InvalidPositionException& e) { + lookupTable1D[getIndex(iEta, iPhi)] = 3; // Outside geometry } - } catch (o2::emcal::InvalidPositionException& e) { - lookupTable1D[getIndex(iEta, iPhi)] = 3; // Outside geometry } } } } - /// \brief Calculate background using rotation background method for calib - template - void rotationBackgroundCalib(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photons_coll, unsigned int ig1, unsigned int ig2, TCollision const& collision) + /// Compute the scalar product + /// \param collision is the collision with the Q vector information and event plane + /// \param meson are the selected candidates + template + void runFlowAnalysis(TCollision const& collision, ROOT::Math::PtEtaPhiMVector const& meson, float photonCalibValue = 0.f) { - // if less than 3 clusters are present skip event since we need at least 3 clusters - if (photons_coll.size() < NMinPhotonRotBkg) { - return; - } float cent = getCentrality(collision); - int iCellIDPhoton1 = 0; - int iCellIDPhoton2 = 0; + float massCand = meson.M(); - ROOT::Math::AxisAngle rotationAxis(meson.Vect(), cfgRotAngle.value); - ROOT::Math::Rotation3D rotationMatrix(rotationAxis); - photon1 = rotationMatrix * photon1; - photon2 = rotationMatrix * photon2; + fillThn(massCand, photonCalibValue, cent); + return; + } - if (checkEtaPhi1D(photon1.Eta(), RecoDecay::constrainAngle(photon1.Phi())) >= cfgEMCalMapLevelBackground.value) { - iCellIDPhoton1 = -1; + /// \brief check if standard event cuts + FT0 occupancy + centrality + QVec good is + /// \param collision collision that will be checked + /// \return true if collision survives all checks, otherwise false + template + bool isFullEventSelected(TCollision const& collision, bool fillHisto = false) + { + if (fillHisto) { + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(®istry, collision); + } + if (!(fEMEventCut.IsSelected(collision))) { + // general event selection + return false; } - if (checkEtaPhi1D(photon2.Eta(), RecoDecay::constrainAngle(photon2.Phi())) >= cfgEMCalMapLevelBackground.value) { - iCellIDPhoton2 = -1; + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + // occupancy selection + return false; } - - if (iCellIDPhoton1 == -1 && iCellIDPhoton2 == -1) { - return; + float cent = getCentrality(collision); + if (cent < eventcuts.cfgMinCent || cent > eventcuts.cfgMaxCent) { + // event selection + return false; + } + if (fillHisto) { + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(®istry, collision); + registry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + registry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted } - for (const auto& photon : photons_coll) { - if (photon.globalIndex() == ig1 || photon.globalIndex() == ig2) { - // only combine rotated photons with other photons + return true; + } + + template + void runPairingLoop(TCollision const& collision, TPhotons1 const& photons1, TPhotons2 const& photons2, EMBitFlags const& flags1, EMBitFlags const& flags2) + { + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1, photons2))) { + if (!(flags1.test(g1.globalIndex())) || !(flags2.test(g2.globalIndex()))) { continue; } - if (!(fEMCCut.IsSelected(photon))) { + float asymmetry = (g1.e() - g2.e()) / (g1.e() + g2.e()); + if (std::fabs(asymmetry) > cfgMaxAsymmetry) { // only use symmetric decays continue; } - if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { + + // Cut edge clusters away, similar to rotation method to ensure same acceptance is used + if (cfgDistanceToEdge.value) { + if (checkEtaPhi1D(g1.eta(), RecoDecay::constrainAngle(g1.phi())) >= cfgEMCalMapLevelSameEvent.value) { + continue; + } + if (checkEtaPhi1D(g2.eta(), RecoDecay::constrainAngle(g2.phi())) >= cfgEMCalMapLevelSameEvent.value) { + continue; + } + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; + + float dTheta = v1.Theta() - v2.Theta(); + float dPhi = v1.Phi() - v2.Phi(); + float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); + + registry.fill(HIST("hMesonCuts"), 1); + if (openingAngle <= mesonConfig.minOpenAngle) { + registry.fill(HIST("hMesonCuts"), 2); continue; } - float energyCorrectionFactor = 1.f; - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(photon.e() > MinEnergy ? photon.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector photon3(energyCorrectionFactor * photon.pt(), photon.eta(), photon.phi(), 0.); - if (iCellIDPhoton1 >= 0) { - if (std::fabs((photon1.E() - photon3.E()) / (photon1.E() + photon3.E()) < cfgMaxAsymmetry)) { // only use symmetric decays - ROOT::Math::PtEtaPhiMVector mother1 = photon1 + photon3; - float openingAngle1 = std::acos(photon1.Vect().Dot(photon3.Vect()) / (photon1.P() * photon3.P())); - - if (openingAngle1 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon1.Theta() - photon3.Theta(); - float dPhi = photon1.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseCalibBack"), mother1.M(), mother1.E() / 2., cent); - } - } else { - registry.fill(HIST("hSparseCalibBack"), mother1.M(), mother1.E() / 2., cent); - } - } - } + if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { + registry.fill(HIST("hMesonCuts"), 3); + continue; } - if (iCellIDPhoton2 >= 0) { - if (std::fabs((photon2.E() - photon3.E()) / (photon2.E() + photon3.E()) < cfgMaxAsymmetry)) { // only use symmetric decays - ROOT::Math::PtEtaPhiMVector mother2 = photon2 + photon3; - float openingAngle2 = std::acos(photon2.Vect().Dot(photon3.Vect()) / (photon2.P() * photon3.P())); - - if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother2.M() && thnConfigAxisInvMass.value.back() >= mother2.M() && thnConfigAxisPt.value[1] <= mother2.Pt() && thnConfigAxisPt.value.back() >= mother2.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon2.Theta() - photon3.Theta(); - float dPhi = photon2.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseCalibBack"), mother2.M(), mother2.E() / 2., cent); - } - } else { - registry.fill(HIST("hSparseCalibBack"), mother2.M(), mother2.E() / 2., cent); - } - } - } + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), g1.corrPt()); + registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); + registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, g1.corrPt()); } - } // end of loop over third photon - return; + if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + registry.fill(HIST("hMesonCuts"), 5); + continue; + } + registry.fill(HIST("hMesonCuts"), 6); + float cent = getCentrality(collision); + fillOpeningAngleHisto<0>(openingAngle, vMeson.Pt(), cent); + runFlowAnalysis<0>(collision, vMeson, g1.e()); + } } - /// \brief Calculate background using rotation background method for calib - /// \param meson mother particle from photon1 & photon2 which defines rotation axis - /// \param photon1 first photon (EMC) which will be rotated - /// \param photon2 second photon (PCM) which will be rotated - /// \param photonsEMC sub table of EMC photons of current event which will be combined with rotated photon2 - /// \param photonsPCM sub table of PCM photons of current event which will be combined with rotated photon1 - /// \param ig1 index of photon1 - /// \param ig2 index of photon2 - /// \param cent current collisions centrality - template - void rotationBackgroundCalibEMCPCM(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotonEMC const& photonsEMC, TPhotonPCM const& photonsPCM, unsigned int ig1, unsigned int ig2, float cent) + // Pi0 from EMCal + void processEMCal(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { - // we need at least 2 clusters or 2 pcm photons for rotation - if (photonsEMC.size() < NMinPhotonRotBkgMixed || photonsPCM.size() < NMinPhotonRotBkgMixed) { + if (clusters.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; return; } - int iCellIDPhoton1 = 0; - int iCellIDPhoton2 = 0; - ROOT::Math::AxisAngle rotationAxis(meson.Vect(), cfgRotAngle.value); - ROOT::Math::Rotation3D rotationMatrix(rotationAxis); - photon1 = rotationMatrix * photon1; - photon2 = rotationMatrix * photon2; + EMBitFlags flags(clusters.size()); + fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds, ®istry); - if (checkEtaPhi1D(photon1.Eta(), RecoDecay::constrainAngle(photon1.Phi())) >= cfgEMCalMapLevelBackground.value) { - iCellIDPhoton1 = -1; - } + for (const auto& collision : collisions) { - if (iCellIDPhoton1 == -1 && iCellIDPhoton2 == -1) { - return; - } - // Combining with EMCal photons from event - if (photonsEMC.size() >= NMinPhotonRotBkgMixed) { - for (const auto& photon : photonsEMC) { - if (photon.globalIndex() == ig1) { - continue; - } - if (!(fEMCCut.IsSelected(photon))) { - continue; - } - if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { - continue; - } - float energyCorrectionFactor = 1.f; - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(photon.e() > MinEnergy ? photon.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector photon3(energyCorrectionFactor * photon.pt(), photon.eta(), photon.phi(), 0.); - if (iCellIDPhoton2 >= 0) { - ROOT::Math::PtEtaPhiMVector mother = photon2 + photon3; - float openingAngle2 = std::acos(photon2.Vect().Dot(photon3.Vect()) / (photon2.P() * photon3.P())); - - if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother.M() && thnConfigAxisInvMass.value.back() >= mother.M() && thnConfigAxisPt.value[1] <= mother.Pt() && thnConfigAxisPt.value.back() >= mother.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon2.Theta() - photon3.Theta(); - float dPhi = photon2.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseCalibBack"), mother.M(), mother.E() / 2., cent); - } - } else { - registry.fill(HIST("hSparseCalibBack"), mother.M(), mother.E() / 2., cent); - } - } - } - } // end of loop over third photon - } // check that we have at least 2 clusters + if (!isFullEventSelected(collision, true)) { + continue; + } + runNow = collision.runNumber(); + if (runNow != runBefore) { + initCCDB(collision); + runBefore = runNow; + } - // Combining with PCM photons from event - if (photonsPCM.size() >= NMinPhotonRotBkgMixed) { - for (const auto& photon : photonsPCM) { - if (photon.globalIndex() == ig2) { - continue; - } - if (!(fPCMPhotonCut.IsSelected(photon))) { - continue; - } - ROOT::Math::PtEtaPhiMVector photon3(photon.pt(), photon.eta(), photon.phi(), 0.); - if (iCellIDPhoton1 >= 0) { - ROOT::Math::PtEtaPhiMVector mother = photon1 + photon3; - float openingAngle2 = std::acos(photon1.Vect().Dot(photon3.Vect()) / (photon1.P() * photon3.P())); - - if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother.M() && thnConfigAxisInvMass.value.back() >= mother.M() && thnConfigAxisPt.value[1] <= mother.Pt() && thnConfigAxisPt.value.back() >= mother.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon1.Theta() - photon3.Theta(); - float dPhi = photon1.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseCalibBack"), mother.M(), mother.E() / 2., cent); - } - } else { - registry.fill(HIST("hSparseCalibBack"), mother.M(), mother.E() / 2., cent); - } - } - } - } // end of loop over third photon - } // check that we have at least 2 clusters - return; + auto photonsPerCollision = clusters.sliceBy(perCollisionEMC, collision.globalIndex()); + runPairingLoop(collision, photonsPerCollision, photonsPerCollision, flags, flags); + } // end of loop over collisions } + PROCESS_SWITCH(CalibTaskEmc, processEMCal, "Process EMCal Pi0 candidates", true); - // EMCal calibration same event - void processEMCalCalib(Colls const& collisions, EMCalPhotons const& clusters, PCMPhotons const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) + // Pi0 from EMCal + void processEMCalMixed(FilteredCollsWithQvecs const& collisions, EMCalPhotons const& clusters, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { - float energyCorrectionFactor = 1.f; - int nColl = 1; + if (clusters.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + EMBitFlags flags(clusters.size()); + fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds); - EMBitFlags emcFlags(clusters.size()); - fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + using BinningType = ColumnBinningPolicy; + BinningType binningMixedEvent{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins}, true}; - for (const auto& collision : collisions) { - auto photonsPerCollision = clusters.sliceBy(perCollisionEMC, collision.globalIndex()); - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(®istry, collision); - if (!(fEMEventCut.IsSelected(collision))) { + auto clustersTuple = std::make_tuple(clusters); + SameKindPair pair{binningMixedEvent, mixingConfig.cfgMixingDepth, -1, collisions, clustersTuple, &cache}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored + + for (const auto& [c1, clusters1, c2, clusters2] : pair) { + if (!(fEMEventCut.IsSelected(c1)) || !(fEMEventCut.IsSelected(c2))) { // general event selection continue; } - if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + if (!(eventcuts.cfgFT0COccupancyMin <= c1.ft0cOccupancyInTimeRange() && c1.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax) || !(eventcuts.cfgFT0COccupancyMin <= c2.ft0cOccupancyInTimeRange() && c2.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { // occupancy selection continue; } - float cent = getCentrality(collision); - if (cent < eventcuts.cfgMinCent || cent > eventcuts.cfgMaxCent) { + if (getCentrality(c1) < eventcuts.cfgMinCent || getCentrality(c1) > eventcuts.cfgMaxCent || getCentrality(c2) < eventcuts.cfgMinCent || getCentrality(c2) > eventcuts.cfgMaxCent) { // event selection continue; } - runNow = collision.runNumber(); + runNow = c1.runNumber(); if (runNow != runBefore) { - initCCDB(collision); + initCCDB(c1); runBefore = runNow; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(®istry, collision); - registry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted - registry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted - - if (emccuts.cfgEnableQA) { - for (const auto& photon : photonsPerCollision) { - registry.fill(HIST("hEClusterBefore"), photon.e()); // before cuts - if (!(fEMCCut.IsSelected(photon))) { - continue; - } - registry.fill(HIST("hEClusterAfter"), photon.e()); // accepted after cuts + registry.fill(HIST("hMixingCount"), c1.posZ(), getCentrality(c1)); + for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(clusters1, clusters2))) { + if (!(flags.test(g1.globalIndex())) || !(flags.test(g2.globalIndex()))) { + continue; } - } - for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photonsPerCollision, photonsPerCollision))) { - if (!(emcFlags.test(g1.globalIndex())) || !(emcFlags.test(g2.globalIndex()))) { + float asymmetry = (g1.e() - g2.e()) / (g1.e() + g2.e()); + if (std::fabs(asymmetry) > cfgMaxAsymmetry) { // only use symmetric decays continue; } - // Cut edge clusters away, similar to rotation method to ensure same acceptance is used if (cfgDistanceToEdge.value) { - if (checkEtaPhi1D(g1.eta(), RecoDecay::constrainAngle(g1.phi())) >= cfgEMCalMapLevelSameEvent.value) { + if (checkEtaPhi1D(g1.eta(), RecoDecay::constrainAngle(g1.phi())) >= cfgEMCalMapLevelBackground.value) { continue; } - if (checkEtaPhi1D(g2.eta(), RecoDecay::constrainAngle(g2.phi())) >= cfgEMCalMapLevelSameEvent.value) { + if (checkEtaPhi1D(g2.eta(), RecoDecay::constrainAngle(g2.phi())) >= cfgEMCalMapLevelBackground.value) { continue; } } - - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); float dPhi = v1.Phi() - v2.Phi(); float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); - registry.fill(HIST("hClusterCuts"), 1); + + registry.fill(HIST("hMesonCutsMixed"), 1); if (openingAngle <= mesonConfig.minOpenAngle) { - registry.fill(HIST("hClusterCuts"), 2); + registry.fill(HIST("hMesonCutsMixed"), 2); continue; } - if (cfgDoRotation) { - if (nColl % cfgDownsampling.value == 0) { - rotationBackgroundCalib(vMeson, v1, v2, photonsPerCollision, g1.globalIndex(), g2.globalIndex(), collision); - } - } if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { - registry.fill(HIST("hClusterCuts"), 3); - continue; - } - if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { - registry.fill(HIST("hClusterCuts"), 4); + registry.fill(HIST("hMesonCutsMixed"), 3); continue; } - if (mesonConfig.cfgEnableQA) { - registry.fill(HIST("hInvMassPt"), vMeson.M(), vMeson.Pt()); - registry.fill(HIST("hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), g1.corrPt()); + registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, g1.corrPt()); } if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hClusterCuts"), 5); + registry.fill(HIST("hMesonCutsMixed"), 5); continue; } - if (std::fabs((v1.E() - v2.E()) / (v1.E() + v2.E()) < cfgMaxAsymmetry)) { // only use symmetric decays - registry.fill(HIST("hClusterCuts"), 6); - registry.fill(HIST("hSparseCalibSE"), vMeson.M(), vMeson.E() / 2., getCentrality(collision)); - } - } - if (cfgDoRotation) { - if (nColl % cfgDownsampling.value == 0) { - nColl = 1; // reset counter - } else { - nColl++; - } + registry.fill(HIST("hMesonCutsMixed"), 6); + float cent = getCentrality(c1); + fillOpeningAngleHisto<2>(openingAngle, vMeson.Pt(), cent); + runFlowAnalysis<2>(c1, vMeson, g1.e()); } } } - PROCESS_SWITCH(CalibTaskEmc, processEMCalCalib, "Process EMCal calibration same event", true); + PROCESS_SWITCH(CalibTaskEmc, processEMCalMixed, "Process EMCal Pi0 mixed event candidates", false); - // EMCal calibration - void processEMCalPCMCalib(Colls const& collisions, EMCalPhotons const& clusters, PCMPhotons const& photons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) + // PCM-EMCal same event + void processEMCalPCMC(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, PCMPhotons const& photons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { - float energyCorrectionFactor = 1.f; - int nColl = 1; - + if (clusters.size() <= 0 && photons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } EMBitFlags emcFlags(clusters.size()); - fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + if (clusters.size() > 0) { + fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds, ®istry); + } + + EMBitFlags v0flags(photons.size()); + if (photons.size() > 0) { + fV0PhotonCut.AreSelectedRunning(v0flags, photons, ®istry); + } for (const auto& collision : collisions) { - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(®istry, collision); - if (!(fEMEventCut.IsSelected(collision))) { - // general event selection - continue; - } - if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { - // occupancy selection - continue; - } - float cent = getCentrality(collision); - if (cent < eventcuts.cfgMinCent || cent > eventcuts.cfgMaxCent) { - // event selection + + if (!isFullEventSelected(collision, true)) { continue; } runNow = collision.runNumber(); @@ -834,24 +809,12 @@ struct CalibTaskEmc { initCCDB(collision); runBefore = runNow; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(®istry, collision); - registry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted - registry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted auto photonsEMCPerCollision = clusters.sliceBy(perCollisionEMC, collision.globalIndex()); auto photonsPCMPerCollision = photons.sliceBy(perCollisionPCM, collision.globalIndex()); - if (emccuts.cfgEnableQA) { - for (const auto& photon : photonsEMCPerCollision) { - registry.fill(HIST("hEClusterBefore"), photon.e()); // before cuts - if (!(fEMCCut.IsSelected(photon))) { - continue; - } - registry.fill(HIST("hEClusterAfter"), photon.e()); // accepted after cuts - } - } for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photonsEMCPerCollision, photonsPCMPerCollision))) { - if (!(emcFlags.test(g1.globalIndex())) || !(fPCMPhotonCut.IsSelected(g2))) { + if (!(emcFlags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { continue; } @@ -863,65 +826,65 @@ struct CalibTaskEmc { } // EMCal photon v1 - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); // PCM photon v2s - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); float dPhi = v1.Phi() - v2.Phi(); float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); - registry.fill(HIST("hClusterCuts"), 1); + registry.fill(HIST("hMesonCuts"), 1); if (openingAngle <= mesonConfig.minOpenAngle) { - registry.fill(HIST("hClusterCuts"), 2); + registry.fill(HIST("hMesonCuts"), 2); continue; } - if (cfgDoRotation) { - if (nColl % cfgDownsampling.value == 0) { - rotationBackgroundCalibEMCPCM(vMeson, v1, v2, photonsEMCPerCollision, photonsPCMPerCollision, g1.globalIndex(), g2.globalIndex(), cent); - } - } if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { - registry.fill(HIST("hClusterCuts"), 3); - continue; - } - if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { - registry.fill(HIST("hClusterCuts"), 4); + registry.fill(HIST("hMesonCuts"), 3); continue; } - if (mesonConfig.cfgEnableQA) { - registry.fill(HIST("hInvMassPt"), vMeson.M(), vMeson.Pt()); - registry.fill(HIST("hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), g1.corrPt()); + registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); + registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), g1.corrPt()); } if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hClusterCuts"), 5); + registry.fill(HIST("hMesonCuts"), 5); continue; } - registry.fill(HIST("hSparseCalibSE"), vMeson.M(), vMeson.E() / 2., getCentrality(collision)); - } - if (cfgDoRotation) { - if (nColl % cfgDownsampling.value == 0) { - nColl = 1; // reset counter - } else { - nColl++; - } + float cent = getCentrality(collision); + fillOpeningAngleHisto<0>(openingAngle, vMeson.Pt(), cent); + runFlowAnalysis<0>(collision, vMeson, g1.corrE()); } } } - PROCESS_SWITCH(CalibTaskEmc, processEMCalPCMCalib, "Process EMCal calibration using PCM-EMC same event", true); + PROCESS_SWITCH(CalibTaskEmc, processEMCalPCMC, "Process neutral meson flow using PCM-EMC same event", false); - // EMCal calibration mixed event - void processEMCalCalibMixed(Colls const&, EMCalPhotons const& clusters, PCMPhotons const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) + // PCM-EMCal mixed event + void processEMCalPCMMixed(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, PCMPhotons const& pcmPhotons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { - float energyCorrectionFactor = 1.f; + if (clusters.size() <= 0 && pcmPhotons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + using BinningTypeMixed = ColumnBinningPolicy; + BinningTypeMixed binningOnPositions{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins}, true}; + + auto associatedTables = std::make_tuple(clusters, pcmPhotons); + + Pair pairPCMEMC{binningOnPositions, mixingConfig.cfgMixingDepth, -1, collisions, associatedTables, &cache}; // indicates that mixingConfig.cfgMixingDepth events should be mixed and under/overflow (-1) to be ignored + EMBitFlags emcFlags(clusters.size()); - fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + if (clusters.size() > 0) { + fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + } - SameKindPair pair{binningOnPositions, mixingConfig.cfgMixingDepth, -1, &cache}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored + EMBitFlags v0flags(pcmPhotons.size()); + if (pcmPhotons.size() > 0) { + fV0PhotonCut.AreSelectedRunning(v0flags, pcmPhotons); + } - for (const auto& [c1, clusters1, c2, clusters2] : pair) { + for (const auto& [c1, photonEMC, c2, photonPCM] : pairPCMEMC) { if (!(fEMEventCut.IsSelected(c1)) || !(fEMEventCut.IsSelected(c2))) { // general event selection continue; @@ -939,8 +902,9 @@ struct CalibTaskEmc { initCCDB(c1); runBefore = runNow; } - for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(clusters1, clusters2))) { - if (!(emcFlags.test(g1.globalIndex())) || !(emcFlags.test(g2.globalIndex()))) { + registry.fill(HIST("hMixingCount"), c1.posZ(), getCentrality(c1)); + for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photonEMC, photonPCM))) { + if (!(emcFlags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { continue; } // Cut edge clusters away, similar to rotation method to ensure same acceptance is used @@ -948,59 +912,125 @@ struct CalibTaskEmc { if (checkEtaPhi1D(g1.eta(), RecoDecay::constrainAngle(g1.phi())) >= cfgEMCalMapLevelBackground.value) { continue; } - if (checkEtaPhi1D(g2.eta(), RecoDecay::constrainAngle(g2.phi())) >= cfgEMCalMapLevelBackground.value) { - continue; - } } - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + + float photon1Pt = g1.corrPt(); + float photon2Pt = g2.corrPt(); + + ROOT::Math::PtEtaPhiMVector v1(photon1Pt, g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(photon2Pt, g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); float dPhi = v1.Phi() - v2.Phi(); float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); - registry.fill(HIST("hClusterCutsMixed"), 1); + registry.fill(HIST("hMesonCutsMixed"), 1); if (openingAngle <= mesonConfig.minOpenAngle) { - registry.fill(HIST("hClusterCutsMixed"), 2); + registry.fill(HIST("hMesonCutsMixed"), 2); continue; } if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { - registry.fill(HIST("hClusterCutsMixed"), 3); + registry.fill(HIST("hMesonCutsMixed"), 3); continue; } - if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { - registry.fill(HIST("hClusterCutsMixed"), 4); + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), photon1Pt); + registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), photon1Pt); + } + if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + registry.fill(HIST("hMesonCutsMixed"), 5); continue; } - if (mesonConfig.cfgEnableQA) { - registry.fill(HIST("hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); - registry.fill(HIST("hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + registry.fill(HIST("hMesonCutsMixed"), 6); + float cent = getCentrality(c1); + fillOpeningAngleHisto<2>(openingAngle, vMeson.Pt(), cent); + runFlowAnalysis<2>(c1, vMeson, g1.corrE()); + } + } + } + PROCESS_SWITCH(CalibTaskEmc, processEMCalPCMMixed, "Process neutral meson flow using PCM-EMC mixed event", false); + + // Pi0 from EMCal + void processPCM(CollsWithQvecs const& collisions, PCMPhotons const& photons, aod::V0Legs const&) + { + if (photons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + EMBitFlags v0flags(photons.size()); + fV0PhotonCut.AreSelectedRunning(v0flags, photons, ®istry); + for (const auto& collision : collisions) { + + if (!isFullEventSelected(collision, true)) { + continue; + } + runNow = collision.runNumber(); + if (runNow != runBefore) { + initCCDB(collision); + runBefore = runNow; + } + + auto photonsPerCollision = photons.sliceBy(perCollisionPCM, collision.globalIndex()); + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photonsPerCollision, photonsPerCollision))) { + if (!(v0flags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { + continue; } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hClusterCutsMixed"), 5); + + float photon1Pt = g1.corrPt(); + float photon2Pt = g2.corrPt(); + + float asymmetry = (photon1Pt - photon2Pt) / (photon1Pt + photon2Pt); + if (std::fabs(asymmetry) > cfgMaxAsymmetry) { // only use symmetric decays + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(photon1Pt, g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(photon2Pt, g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; + + float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); + + registry.fill(HIST("hMesonCuts"), 1); + if (openingAngle <= mesonConfig.minOpenAngle) { + registry.fill(HIST("hMesonCuts"), 2); + continue; + } + if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { + registry.fill(HIST("hMesonCuts"), 3); continue; } - if (std::fabs((v1.E() - v2.E()) / (v1.E() + v2.E()) < cfgMaxAsymmetry)) { // only use symmetric decays - registry.fill(HIST("hClusterCutsMixed"), 6); - registry.fill(HIST("hSparseCalibBack"), vMeson.M(), vMeson.E() / 2., getCentrality(c1)); + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), photon1Pt); + registry.fill(HIST("mesonQA/hAlphaPt"), asymmetry, photon1Pt); } + registry.fill(HIST("hMesonCuts"), 6); + float cent = getCentrality(collision); + fillOpeningAngleHisto<0>(openingAngle, vMeson.Pt(), cent); + runFlowAnalysis<0>(collision, vMeson, photon1Pt); } - } + } // end of loop over collisions } - PROCESS_SWITCH(CalibTaskEmc, processEMCalCalibMixed, "Process EMCal calibration mixed event", false); + PROCESS_SWITCH(CalibTaskEmc, processPCM, "Process PCM Pi0 candidates", false); - // EMCal calibration - void processEMCalPCMCalibMixed(Colls const&, EMCalPhotons const& clusters, PCMPhotons const&, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) + // PCM-EMCal mixed event + void processPCMMixed(FilteredCollsWithQvecs const& collisions, PCMPhotons const& pcmPhotons, aod::V0Legs const&) { - float energyCorrectionFactor = 1.f; - EMBitFlags emcFlags(clusters.size()); - fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + if (pcmPhotons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + using BinningType = ColumnBinningPolicy; + BinningType binningMixedEvent{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins}, true}; - for (const auto& [c1, photonEMC, c2, photonPCM] : pairPCMEMC) { + auto pcmPhotonTuple = std::make_tuple(pcmPhotons); + SameKindPair pair{binningMixedEvent, mixingConfig.cfgMixingDepth, -1, collisions, pcmPhotonTuple, &cache}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored + + EMBitFlags v0flags(pcmPhotons.size()); + fV0PhotonCut.AreSelectedRunning(v0flags, pcmPhotons); + + for (const auto& [c1, photon1, c2, photon2] : pair) { if (!(fEMEventCut.IsSelected(c1)) || !(fEMEventCut.IsSelected(c2))) { // general event selection continue; @@ -1018,52 +1048,47 @@ struct CalibTaskEmc { initCCDB(c1); runBefore = runNow; } - for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photonEMC, photonPCM))) { - if (!(emcFlags.test(g1.globalIndex())) || !(fPCMPhotonCut.IsSelected(g2))) { + registry.fill(HIST("hMixingCount"), c1.posZ(), getCentrality(c1)); + for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photon1, photon2))) { + if (!(v0flags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { continue; } - // Cut edge clusters away, similar to rotation method to ensure same acceptance is used - if (cfgDistanceToEdge.value) { - if (checkEtaPhi1D(g1.eta(), RecoDecay::constrainAngle(g1.phi())) >= cfgEMCalMapLevelBackground.value) { - continue; - } + + float photon1Pt = g1.corrPt(); + float photon2Pt = g2.corrPt(); + + float asymmetry = (photon1Pt - photon2Pt) / (photon1Pt + photon2Pt); + if (std::fabs(asymmetry) > cfgMaxAsymmetry) { // only use symmetric decays + continue; } - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + + ROOT::Math::PtEtaPhiMVector v1(photon1Pt, g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(photon2Pt, g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; - float dTheta = v1.Theta() - v2.Theta(); - float dPhi = v1.Phi() - v2.Phi(); float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); - registry.fill(HIST("hClusterCutsMixed"), 1); + registry.fill(HIST("hMesonCutsMixed"), 1); if (openingAngle <= mesonConfig.minOpenAngle) { - registry.fill(HIST("hClusterCutsMixed"), 2); + registry.fill(HIST("hMesonCutsMixed"), 2); continue; } if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { - registry.fill(HIST("hClusterCutsMixed"), 3); - continue; - } - if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { - registry.fill(HIST("hClusterCutsMixed"), 4); + registry.fill(HIST("hMesonCutsMixed"), 3); continue; } - if (mesonConfig.cfgEnableQA) { - registry.fill(HIST("hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); - registry.fill(HIST("hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); - registry.fill(HIST("hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); - } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hClusterCutsMixed"), 5); - continue; + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), photon1Pt); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), asymmetry, photon1Pt); } - registry.fill(HIST("hSparseCalibBack"), vMeson.M(), vMeson.E() / 2., getCentrality(c1)); + registry.fill(HIST("hMesonCutsMixed"), 6); + float cent = getCentrality(c1); + fillOpeningAngleHisto<2>(openingAngle, vMeson.Pt(), cent); + runFlowAnalysis<2>(c1, vMeson, photon1Pt); } } } - PROCESS_SWITCH(CalibTaskEmc, processEMCalPCMCalibMixed, "Process EMCal calibration with PCM-EMC mixed event", false); + PROCESS_SWITCH(CalibTaskEmc, processPCMMixed, "Process neutral meson flow using PCM-EMC mixed event", false); }; // End struct CalibTaskEmc diff --git a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx index 3a080016299..d7046d8832f 100644 --- a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx +++ b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx @@ -15,6 +15,7 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFStrangenessPIDTables.h" @@ -45,6 +46,7 @@ #include #include +using namespace std; using namespace o2; using namespace o2::framework; using namespace o2::aod; @@ -57,7 +59,7 @@ using MyV0Photons = soa::Join; using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; @@ -128,7 +130,7 @@ struct Compconvbuilder { } // Link V0-photons to their collision - Preslice perV0PhotonCollision = aod::v0photonkf::emeventId; + Preslice perV0PhotonCollision = aod::v0photonkf::pmeventId; void init(InitContext const& /*ctx*/) { @@ -656,7 +658,7 @@ struct Compconvbuilder { } } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollision = aod::v0photonkf::pmeventId; void processEMV0sMC(MyV0Photons const& v0s, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, MyCollisions const& collisions) { diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx index a0c6deb047d..c3f41633d9b 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -17,25 +17,44 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "Common/Core/RecoDecay.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TString.h" - +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include #include +#include #include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; @@ -43,10 +62,10 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; struct DalitzEEQC { @@ -332,7 +351,7 @@ struct DalitzEEQC { using FilteredMyCollisions = soa::Filtered; SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectron::emeventId; + Preslice perCollision_track = aod::emprimaryelectronda::pmeventId; Filter trackFilter = dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dileptoncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dileptoncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dileptoncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dileptoncuts.cfg_max_dcaz; Filter pidFilter = dileptoncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dileptoncuts.cfg_max_TPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < dileptoncuts.cfg_min_TPCNsigmaPi || dileptoncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using FilteredMyTracks = soa::Filtered; @@ -360,8 +379,8 @@ struct DalitzEEQC { 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); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, 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 diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx index 6b6ca3f6649..084b866da50 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -18,38 +18,55 @@ #include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" - -#include "Common/Core/RecoDecay.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TString.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + +#include +#include #include +#include #include +#include + 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::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyMCTracks = soa::Join; +using MyMCTracks = soa::Join; using MyMCTrack = MyMCTracks::iterator; struct DalitzEEQCMC { @@ -487,7 +504,7 @@ struct DalitzEEQCMC { std::vector used_trackIds; SliceCache cache; - Preslice perCollision_track = aod::emprimaryelectron::emeventId; + Preslice perCollision_track = aod::emprimaryelectronda::pmeventId; Filter trackFilter = dileptoncuts.cfg_min_pt_track < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfg_max_eta_track && o2::aod::track::tpcChi2NCl < dileptoncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dileptoncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dileptoncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dileptoncuts.cfg_max_dcaz; Filter pidFilter = dileptoncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dileptoncuts.cfg_max_TPCNsigmaEl && (o2::aod::pidtpc::tpcNSigmaPi < dileptoncuts.cfg_min_TPCNsigmaPi || dileptoncuts.cfg_max_TPCNsigmaPi < o2::aod::pidtpc::tpcNSigmaPi); using FilteredMyMCTracks = soa::Filtered; @@ -520,8 +537,8 @@ struct DalitzEEQCMC { 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); + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, 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 diff --git a/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx index efbc38d799c..1bc980ed4bc 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx @@ -11,26 +11,35 @@ // /// /// \file emcalBcWiseGammaGamma.cxx -/// /// \brief Task that extracts pi0s and eta mesons from BC wise derived data of EMCal clusters -/// /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) Goethe University Frankfurt /// #include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" -#include "CommonConstants/MathConstants.h" -#include "EMCALBase/Geometry.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Math/AxisAngle.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "TString.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/PhotonMeson/Tasks/emcalPi0Qc.cxx b/PWGEM/PhotonMeson/Tasks/emcalPi0Qc.cxx index f2aa922ec90..ae6192a9dbb 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalPi0Qc.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalPi0Qc.cxx @@ -28,6 +28,7 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" +#include #include #include #include @@ -40,36 +41,35 @@ #include #include +#include +#include +#include // IWYU pragma: keep +#include #include -#include #include -#include #include #include #include #include #include +#include #include #include #include #include -#include #include using namespace o2::framework; using namespace o2::framework::expressions; -using SelectedClusters = o2::soa::Filtered; using MyCollisions = o2::soa::Join; -using MyBCs = o2::soa::Join; -using SelectedAmbiguousClusters = o2::soa::Filtered; +using MyBCs = o2::soa::Join; struct Photon { - Photon(float eta_tmp, float phi_tmp, float energy_tmp, int clusid = 0) + Photon(float eta_tmp, float phi_tmp, float energy_tmp, int clusid = 0, uint8_t sm_tmp = 0) { eta = eta_tmp; phi = phi_tmp; - onDCal = (phi < 6 && phi > 4); energy = energy_tmp; theta = 2 * std::atan2(std::exp(-eta), 1); px = energy * std::sin(theta) * std::cos(phi); @@ -78,19 +78,22 @@ struct Photon { pt = std::sqrt(px * px + py * py); photon.SetPxPyPzE(px, py, pz, energy); id = clusid; + sm = sm_tmp; + onDCal = (phi < 6 && phi > 4); } - TLorentzVector photon; + ROOT::Math::PxPyPzEVector photon; float pt; float px; float py; float pz; float eta; float phi; - bool onDCal; // Checks whether photon is in phi region of the DCal, otherwise: EMCal float energy; float theta; int id; + uint8_t sm; + bool onDCal; // Checks whether photon is in phi region of the DCal, otherwise: EMCal }; struct Meson { @@ -101,11 +104,17 @@ struct Meson { } Photon pgamma1; Photon pgamma2; - TLorentzVector pMeson; + ROOT::Math::PxPyPzEVector pMeson; float getMass() const { return pMeson.M(); } float getPt() const { return pMeson.Pt(); } - float getOpeningAngle() const { return pgamma1.photon.Angle(pgamma2.photon.Vect()); } + float getOpeningAngle() const + { + float cosAngle = pgamma1.photon.Vect().Dot(pgamma2.photon.Vect()) / (pgamma1.photon.P() * pgamma2.photon.P()); + float angle = std::acos(std::clamp(cosAngle, -1.0f, 1.0f)); + return angle; + } + ROOT::Math::PxPyPzEVector getMathVector() const { return pMeson; } }; struct EventMixVec { @@ -156,8 +165,8 @@ struct EmcalPi0Qc { // 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); + // o2::aod::EMCALClusterDefinition clusDef = o2::aod::emcalcluster::getClusterDefinitionFromString(mClusterDefinition.value); + // Filter clusterDefinitionSelection = o2::aod::emcalcluster::definition == static_cast(clusDef); // define container for photons std::vector mPhotons; @@ -165,9 +174,17 @@ struct EmcalPi0Qc { // event mixing class EventMixVec evtMix; + o2::ccdb::CcdbApi ccdbApi; + int lastRunNumber = -1; // get the runnumber to obtain the SOR of the run to get t - SOR in (s) later + int64_t tsSOR = -1; + o2::aod::EMCALClusterDefinition clusDef = o2::aod::emcalcluster::kV3Default; + /// \brief Create output histograms and initialize geometry void init(InitContext const&) { + // init ccdb api + ccdbApi.init("https://alice-ccdb.cern.ch"); + // load geometry just in case we need it mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); @@ -175,20 +192,30 @@ struct EmcalPi0Qc { LOG(info) << "Creating histograms"; const AxisSpec bcAxis{3501, -0.5, 3500.5}; const AxisSpec energyAxis{makeClusterBinning(), "#it{E} (GeV)"}; + const AxisSpec collisionTimeAxis{1440, 0, 1440, "#it{t} - SOR (min)"}; + const AxisSpec clusterTimeAxis{1500, -600, 900, "t_{cl} (ns)"}; + const AxisSpec invmassAxis{invmassBinning, "#it{M}_{#gamma#gamma} (GeV/#it{c}^{2})"}; + const AxisSpec ptAxis{pTBinning, "#it{p}_{T} (GeV/#it{c})"}; + + if (doprocessCollision) { + mHistManager.add("events", "events;;#it{count}", HistType::kTH1F, {{7, 0.5, 7.5}}); + auto heventType = mHistManager.get(HIST("events")); + heventType->GetXaxis()->SetBinLabel(1, "All events"); + heventType->GetXaxis()->SetBinLabel(2, "sel8"); + heventType->GetXaxis()->SetBinLabel(3, "EMCal readout"); + heventType->GetXaxis()->SetBinLabel(4, "1+ Contributor"); + heventType->GetXaxis()->SetBinLabel(5, "z<10cm"); + heventType->GetXaxis()->SetBinLabel(6, "unique col"); + heventType->GetXaxis()->SetBinLabel(7, "EMCal cell>0"); + mHistManager.add("eventVertexZAll", "z-vertex of event (all events)", HistType::kTH1F, {{200, -20, 20}}); + mHistManager.add("eventVertexZSelected", "z-vertex of event (selected events)", HistType::kTH1F, {{200, -20, 20}}); + mHistManager.add("hEventPerTime", "number of events per time", HistType::kTH1F, {collisionTimeAxis}); + } - mHistManager.add("events", "events;;#it{count}", HistType::kTH1F, {{6, 0.5, 6.5}}); - auto heventType = mHistManager.get(HIST("events")); - heventType->GetXaxis()->SetBinLabel(1, "All events"); - heventType->GetXaxis()->SetBinLabel(2, "sel8 + readout"); - heventType->GetXaxis()->SetBinLabel(3, "1+ Contributor"); - heventType->GetXaxis()->SetBinLabel(4, "z<10cm"); - heventType->GetXaxis()->SetBinLabel(5, "unique col"); - heventType->GetXaxis()->SetBinLabel(6, "EMCAL cell>0"); - mHistManager.add("eventBCAll", "Bunch crossing ID of event (all events)", HistType::kTH1F, {bcAxis}); - mHistManager.add("eventBCSelected", "Bunch crossing ID of event (selected events)", HistType::kTH1F, {bcAxis}); - mHistManager.add("eventVertexZAll", "z-vertex of event (all events)", HistType::kTH1F, {{200, -20, 20}}); - mHistManager.add("eventVertexZSelected", "z-vertex of event (selected events)", HistType::kTH1F, {{200, -20, 20}}); - + if (doprocessAmbiguous) { + mHistManager.add("eventBCAll", "Bunch crossing ID of event (all events)", HistType::kTH1F, {bcAxis}); + mHistManager.add("eventBCSelected", "Bunch crossing ID of event (selected events)", HistType::kTH1F, {bcAxis}); + } // cluster properties for (const bool& iBeforeCuts : {false, true}) { const char* clusterDirectory = iBeforeCuts ? "ClustersBeforeCuts" : "ClustersAfterCuts"; @@ -204,17 +231,25 @@ struct EmcalPi0Qc { } // meson related histograms - mHistManager.add("invMassVsPt", "invariant mass and pT of meson candidates", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPtBackground", "invariant mass and pT of background meson candidates", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPtMixedBackground", "invariant mass and pT of mixed background meson candidates", HistType::kTH2F, {invmassBinning, pTBinning}); + mHistManager.add("invMassVsPt", "invariant mass and pT of meson candidates", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPtBackground", "invariant mass and pT of background meson candidates", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPtMixedBackground", "invariant mass and pT of mixed background meson candidates", HistType::kTH2F, {invmassAxis, ptAxis}); if (mSplitEMCalDCal) { - mHistManager.add("invMassVsPt_EMCal", "invariant mass and pT of meson candidates with both clusters on EMCal", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPtBackground_EMCal", "invariant mass and pT of background meson candidates with both clusters on EMCal", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPtMixedBackground_EMCal", "invariant mass and pT of mixed background meson candidates with both clusters on EMCal", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPt_DCal", "invariant mass and pT of meson candidates with both clusters on DCal", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPtBackground_DCal", "invariant mass and pT of background meson candidates with both clusters on DCal", HistType::kTH2F, {invmassBinning, pTBinning}); - mHistManager.add("invMassVsPtMixedBackground_DCal", "invariant mass and pT of mixed background meson candidates with both clusters on DCal", HistType::kTH2F, {invmassBinning, pTBinning}); + mHistManager.add("invMassVsPt_EMCal", "invariant mass and pT of meson candidates with both clusters on EMCal", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPtBackground_EMCal", "invariant mass and pT of background meson candidates with both clusters on EMCal", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPtMixedBackground_EMCal", "invariant mass and pT of mixed background meson candidates with both clusters on EMCal", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPt_DCal", "invariant mass and pT of meson candidates with both clusters on DCal", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPtBackground_DCal", "invariant mass and pT of background meson candidates with both clusters on DCal", HistType::kTH2F, {invmassAxis, ptAxis}); + mHistManager.add("invMassVsPtMixedBackground_DCal", "invariant mass and pT of mixed background meson candidates with both clusters on DCal", HistType::kTH2F, {invmassAxis, ptAxis}); + } + + // add histograms per supermodule + for (int ism = 0; ism < 20; ++ism) { + mHistManager.add(Form("clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM%d", ism), Form("Cluster time vs collision timestamp in Supermodule %d", ism), HistType::kTH2F, {clusterTimeAxis, collisionTimeAxis}); + mHistManager.add(Form("clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM%d", ism), Form("Cluster number of cells vs collision timestamp in Supermodule %d", ism), HistType::kTH2F, {{50, 0, 50}, collisionTimeAxis}); + mHistManager.add(Form("clusterM02VsTimeStamp/clusterM02VsTimeStampSM%d", ism), Form("Cluster M02 vs collision timestamp in Supermodule %d", ism), HistType::kTH2F, {{400, 0, 5}, collisionTimeAxis}); + mHistManager.add(Form("mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM%d", ism), Form("invariant mass vs collision timestamp in Supermodule %d", ism), HistType::kTH2F, {invmassAxis, collisionTimeAxis}); } if (mVetoBCID->length()) { @@ -237,69 +272,258 @@ struct EmcalPi0Qc { mSelectBCIDs.push_back(bcid); } } + clusDef = o2::aod::emcalcluster::getClusterDefinitionFromString(mClusterDefinition.value); + LOG(info) << "mDoEventSel = " << mDoEventSel.value; + LOG(info) << "mRequireCaloReadout = " << mRequireCaloReadout.value; + LOG(info) << "mRequireEMCalCells = " << mRequireEMCalCells.value; + LOG(info) << "mSplitEMCalDCal = " << mSplitEMCalDCal.value; + } + + template + void supermoduleHistHelperPhoton(float time, float m02, int NCell, float timeSinceSOR) + { + static constexpr std::string_view ClusterTimeHistSM[20] = {"clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM0", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM1", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM2", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM3", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM4", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM5", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM6", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM7", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM8", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM9", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM10", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM11", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM12", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM13", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM14", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM15", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM16", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM17", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM18", "clusterTimeVsTimeStamp/clusterTimeVsTimeStampSM19"}; + static constexpr std::string_view ClusterNcellHistSM[20] = {"clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM0", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM1", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM2", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM3", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM4", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM5", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM6", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM7", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM8", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM9", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM10", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM11", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM12", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM13", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM14", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM15", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM16", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM17", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM18", "clusterNcellVsTimeStamp/clusterNCellVsTimeStampSM19"}; + static constexpr std::string_view ClusterM02HistSM[20] = {"clusterM02VsTimeStamp/clusterM02VsTimeStampSM0", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM1", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM2", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM3", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM4", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM5", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM6", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM7", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM8", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM9", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM10", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM11", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM12", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM13", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM14", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM15", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM16", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM17", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM18", "clusterM02VsTimeStamp/clusterM02VsTimeStampSM19"}; + mHistManager.fill(HIST(ClusterTimeHistSM[supermoduleID]), time, timeSinceSOR); + mHistManager.fill(HIST(ClusterNcellHistSM[supermoduleID]), NCell, timeSinceSOR); + mHistManager.fill(HIST(ClusterM02HistSM[supermoduleID]), m02, timeSinceSOR); + } + + template + void supermoduleHistHelperMeson(float minv, float timeSinceSOR) + { + static constexpr std::string_view MesonInvMassHistSM[20] = {"mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM0", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM1", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM2", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM3", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM4", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM5", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM6", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM7", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM8", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM9", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM10", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM11", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM12", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM13", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM14", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM15", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM16", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM17", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM18", "mesonInvMassVsTimeStamp/mesonInvMassVsTimeStampSM19"}; + mHistManager.fill(HIST(MesonInvMassHistSM[supermoduleID]), minv, timeSinceSOR); + } + + void fillSupermoduleHistogramsPhoton(int supermoduleID, float time, float m02, int NCell, float timeSinceSOR) + { + // workaround to have the histogram names per supermodule + // handled as constexpr + switch (supermoduleID) { + case 0: + supermoduleHistHelperPhoton<0>(time, m02, NCell, timeSinceSOR); + break; + case 1: + supermoduleHistHelperPhoton<1>(time, m02, NCell, timeSinceSOR); + break; + case 2: + supermoduleHistHelperPhoton<2>(time, m02, NCell, timeSinceSOR); + break; + case 3: + supermoduleHistHelperPhoton<3>(time, m02, NCell, timeSinceSOR); + break; + case 4: + supermoduleHistHelperPhoton<4>(time, m02, NCell, timeSinceSOR); + break; + case 5: + supermoduleHistHelperPhoton<5>(time, m02, NCell, timeSinceSOR); + break; + case 6: + supermoduleHistHelperPhoton<6>(time, m02, NCell, timeSinceSOR); + break; + case 7: + supermoduleHistHelperPhoton<7>(time, m02, NCell, timeSinceSOR); + break; + case 8: + supermoduleHistHelperPhoton<8>(time, m02, NCell, timeSinceSOR); + break; + case 9: + supermoduleHistHelperPhoton<9>(time, m02, NCell, timeSinceSOR); + break; + case 10: + supermoduleHistHelperPhoton<10>(time, m02, NCell, timeSinceSOR); + break; + case 11: + supermoduleHistHelperPhoton<11>(time, m02, NCell, timeSinceSOR); + break; + case 12: + supermoduleHistHelperPhoton<12>(time, m02, NCell, timeSinceSOR); + break; + case 13: + supermoduleHistHelperPhoton<13>(time, m02, NCell, timeSinceSOR); + break; + case 14: + supermoduleHistHelperPhoton<14>(time, m02, NCell, timeSinceSOR); + break; + case 15: + supermoduleHistHelperPhoton<15>(time, m02, NCell, timeSinceSOR); + break; + case 16: + supermoduleHistHelperPhoton<16>(time, m02, NCell, timeSinceSOR); + break; + case 17: + supermoduleHistHelperPhoton<17>(time, m02, NCell, timeSinceSOR); + break; + case 18: + supermoduleHistHelperPhoton<18>(time, m02, NCell, timeSinceSOR); + break; + case 19: + supermoduleHistHelperPhoton<19>(time, m02, NCell, timeSinceSOR); + break; + default: + break; + } + } + + void fillSupermoduleHistogramsMeson(int supermoduleID, float minv, float timeSinceSOR) + { + // workaround to have the histogram names per supermodule + // handled as constexpr + switch (supermoduleID) { + case 0: + supermoduleHistHelperMeson<0>(minv, timeSinceSOR); + break; + case 1: + supermoduleHistHelperMeson<1>(minv, timeSinceSOR); + break; + case 2: + supermoduleHistHelperMeson<2>(minv, timeSinceSOR); + break; + case 3: + supermoduleHistHelperMeson<3>(minv, timeSinceSOR); + break; + case 4: + supermoduleHistHelperMeson<4>(minv, timeSinceSOR); + break; + case 5: + supermoduleHistHelperMeson<5>(minv, timeSinceSOR); + break; + case 6: + supermoduleHistHelperMeson<6>(minv, timeSinceSOR); + break; + case 7: + supermoduleHistHelperMeson<7>(minv, timeSinceSOR); + break; + case 8: + supermoduleHistHelperMeson<8>(minv, timeSinceSOR); + break; + case 9: + supermoduleHistHelperMeson<9>(minv, timeSinceSOR); + break; + case 10: + supermoduleHistHelperMeson<10>(minv, timeSinceSOR); + break; + case 11: + supermoduleHistHelperMeson<11>(minv, timeSinceSOR); + break; + case 12: + supermoduleHistHelperMeson<12>(minv, timeSinceSOR); + break; + case 13: + supermoduleHistHelperMeson<13>(minv, timeSinceSOR); + break; + case 14: + supermoduleHistHelperMeson<14>(minv, timeSinceSOR); + break; + case 15: + supermoduleHistHelperMeson<15>(minv, timeSinceSOR); + break; + case 16: + supermoduleHistHelperMeson<16>(minv, timeSinceSOR); + break; + case 17: + supermoduleHistHelperMeson<17>(minv, timeSinceSOR); + break; + case 18: + supermoduleHistHelperMeson<18>(minv, timeSinceSOR); + break; + case 19: + supermoduleHistHelperMeson<19>(minv, timeSinceSOR); + break; + default: + break; + } } - PresliceUnsorted perCollision = o2::aod::emcalcluster::collisionId; + PresliceUnsortedOptional perCollision = o2::aod::emcalcluster::collisionId; + PresliceOptional perCluster = o2::aod::emcalclustercell::emcalclusterId; /// \brief Process EMCAL clusters that are matched to a collisions - void processCollision(MyBCs const&, MyCollisions const& collisions, SelectedClusters const& clusters, o2::soa::Filtered const& cells) + void processCollision(MyBCs const& bcs, MyCollisions const& collisions, o2::aod::EMCALClusters const& clusters, o2::soa::Filtered const& cells, o2::aod::EMCALClusterCells const& clusterCells) { + + auto cellIter = cells.begin(); + auto bcIter = bcs.begin(); + int runNumber = bcIter.runNumber(); std::unordered_map cellGlobalBCs; // Build map of number of cells for corrected BCs using global BCs // used later in the determination whether a BC has EMC cell content (for speed reason) for (const auto& cell : cells) { - auto globalbcid = cell.bc_as().globalBC(); - auto found = cellGlobalBCs.find(globalbcid); - if (found != cellGlobalBCs.end()) { - found->second++; - } else { - cellGlobalBCs.insert(std::pair(globalbcid, 1)); - } + cellGlobalBCs[cell.bc_as().globalBC()]++; } for (const auto& collision : collisions) { mHistManager.fill(HIST("events"), 1); // Fill "All events" bin of event histogram - if (mDoEventSel && (!collision.sel8() || (mRequireCaloReadout && !collision.alias_bit(kTVXinEMC)))) { // Check sel8 and whether EMC was read out + if (mDoEventSel.value && (!collision.sel8())) { // Check sel8 + continue; + } + mHistManager.fill(HIST("events"), 2); // Fill sel8 + if (mRequireCaloReadout.value && !collision.alias_bit(kTVXinEMC)) { // Check whether EMC was read out continue; } - mHistManager.fill(HIST("events"), 2); // Fill sel8 + readout + mHistManager.fill(HIST("events"), 3); // Fill readout - if (mDoEventSel && collision.numContrib() < 0.5) { // Skip collisions without contributors + if (mDoEventSel.value && collision.numContrib() < 0.5) { // Skip collisions without contributors continue; } - mHistManager.fill(HIST("events"), 3); // Fill >1 vtx contr. bin of event histogram + mHistManager.fill(HIST("events"), 4); // Fill >1 vtx contr. bin of event histogram mHistManager.fill(HIST("eventVertexZAll"), collision.posZ()); if (mVertexCut > 0 && std::abs(collision.posZ()) > mVertexCut) { continue; } - mHistManager.fill(HIST("events"), 4); // Fill z-Vertex selected bin of event histogram + mHistManager.fill(HIST("events"), 5); // Fill z-Vertex selected bin of event histogram mHistManager.fill(HIST("eventVertexZSelected"), collision.posZ()); - if (mDoEventSel && collision.ambiguous()) { // Skip ambiguous collisions (those that are in BCs including multiple collisions) + if (mDoEventSel.value && collision.ambiguous()) { // Skip ambiguous collisions (those that are in BCs including multiple collisions) continue; } - mHistManager.fill(HIST("events"), 5); // Fill "One collision in BC" bin of event histogram + mHistManager.fill(HIST("events"), 6); // Fill "One collision in BC" bin of event histogram - if (mDoEventSel) { + if (mDoEventSel.value) { auto found = cellGlobalBCs.find(collision.foundBC_as().globalBC()); - if (mRequireEMCalCells && (found == cellGlobalBCs.end() || found->second == 0)) { // Skip collisions without any readout EMCal cells + if (mRequireEMCalCells.value && (found == cellGlobalBCs.end() || found->second == 0)) { // Skip collisions without any readout EMCal cells continue; } } - mHistManager.fill(HIST("events"), 6); // Fill at least one non0 cell in EMCal of event histogram (Selected) + mHistManager.fill(HIST("events"), 7); // Fill at least one non0 cell in EMCal of event histogram (Selected) - auto clustersPerColl = clusters.sliceBy(perCollision, collision.collisionId()); - processClusters(clustersPerColl); - processMesons(); + // Get BC and run number + int64_t foundBCId = collision.foundBCId(); + if (foundBCId >= 0) { + bcIter.setCursor(foundBCId); + } + runNumber = bcIter.runNumber(); + + // Fetch SOR only when run changes + if (runNumber != lastRunNumber) { + std::map headers, metadata; + headers = ccdbApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", runNumber), metadata, -1); + tsSOR = atol(headers["SOR"].c_str()); + // LOGP(info, "Run {} | SOR = {} ms", runNumber, tsSOR); + lastRunNumber = runNumber; + } + + // Time since SOR in minutes (bc.timestamp() is in ms) + float timeSinceSORMin = (bcIter.timestamp() - tsSOR) / 1000.0f / 60.f; + mHistManager.fill(HIST("hEventPerTime"), timeSinceSORMin); + + auto clustersPerColl = clusters.sliceBy(perCollision, collision.globalIndex()); + if (clustersPerColl.size() == 0) { + continue; + } + processClusters(clustersPerColl, clusterCells, cellIter, timeSinceSORMin); + processMesons(timeSinceSORMin); } } PROCESS_SWITCH(EmcalPi0Qc, processCollision, "Process clusters from collision", false); /// \brief Process EMCAL clusters that are not matched to a collision /// This is not needed for most users - void processAmbiguous(o2::aod::BCs::iterator const& bc, SelectedAmbiguousClusters const& clusters) + void processAmbiguous(o2::aod::BCs::iterator const& bc, o2::aod::EMCALAmbiguousClusters const& clusters) { LOG(debug) << "processAmbiguous"; // TODO: remove this loop and put it in separate process function that only takes care of ambiguous clusters @@ -321,42 +545,39 @@ struct EmcalPi0Qc { PROCESS_SWITCH(EmcalPi0Qc, processAmbiguous, "Process Ambiguous clusters", false); /// \brief Process EMCAL clusters that are matched to a collisions - template - void processClusters(Clusters const& clusters) + template + void processClusters(Clusters const& clusters, o2::aod::EMCALClusterCells const& clusterCells, Cell& cellIter, float timeSinceSOR = 0.f) { LOG(debug) << "processClusters"; // clear photon vector mPhotons.clear(); - int globalCollID = -1000; - - // loop over all clusters from accepted collision - // auto eventClusters = clusters.select(o2::aod::emcalcluster::bcId == theCollision.bc().globalBC()); for (const auto& cluster : clusters) { - - // o2::InteractionRecord eventIR; - auto collID = cluster.collisionId(); - if (globalCollID == -1000) - globalCollID = collID; - - if (globalCollID != collID) { - LOG(info) << "Something went wrong with the collision ID"; + if (static_cast(clusDef) != cluster.definition()) { + continue; } + auto cellsPerCluster = clusterCells.sliceBy(perCluster, cluster.globalIndex()); + auto cellsPerClusterIter = cellsPerCluster.begin(); + cellIter.setCursor(cellsPerClusterIter.caloId()); + auto [supermodule, module, phiInModule, etaInModule] = mGeometry->GetCellIndex(cellIter.cellNumber()); + fillClusterQAHistos(cluster); - if (clusterRejectedByCut(cluster)) + if (clusterRejectedByCut(cluster)) { continue; + } fillClusterQAHistos(cluster); // put clusters in photon vector - mPhotons.push_back(Photon(cluster.eta(), cluster.phi(), cluster.energy(), cluster.id())); + fillSupermoduleHistogramsPhoton(supermodule, cluster.time(), cluster.m02(), cluster.nCells(), timeSinceSOR); + mPhotons.push_back(Photon(cluster.eta(), cluster.phi(), cluster.energy(), cluster.id(), supermodule)); } } /// \brief Process EMCAL clusters that are not matched to a collisions - template + template void processAmbiguousClusters(Clusters const& clusters) { LOG(debug) << "processClusters"; @@ -379,33 +600,33 @@ struct EmcalPi0Qc { } /// \brief Fills the standard QA histograms for a given cluster - template + template void fillClusterQAHistos(Cluster const& cluster) { // In this implementation the cluster properties are directly loaded from the flat table, // in the future one should consider using the AnalysisCluster object to work with after loading. - static constexpr std::string_view kClusterQAHistEnergy[2] = {"ClustersBeforeCuts/clusterE", "ClustersAfterCuts/clusterE"}; - static constexpr std::string_view kClusterQAHistEnergySimpleBinning[2] = {"ClustersBeforeCuts/clusterE_SimpleBinning", "ClustersAfterCuts/clusterE_SimpleBinning"}; - static constexpr std::string_view kClusterQAHistTime[2] = {"ClustersBeforeCuts/clusterTime", "ClustersAfterCuts/clusterTime"}; - static constexpr std::string_view kClusterQAHistEtaPhi[2] = {"ClustersBeforeCuts/clusterEtaPhi", "ClustersAfterCuts/clusterEtaPhi"}; - static constexpr std::string_view kClusterQAHistM02[2] = {"ClustersBeforeCuts/clusterM02", "ClustersAfterCuts/clusterM02"}; - static constexpr std::string_view kClusterQAHistM20[2] = {"ClustersBeforeCuts/clusterM20", "ClustersAfterCuts/clusterM20"}; - static constexpr std::string_view kClusterQAHistNLM[2] = {"ClustersBeforeCuts/clusterNLM", "ClustersAfterCuts/clusterNLM"}; - static constexpr std::string_view kClusterQAHistNCells[2] = {"ClustersBeforeCuts/clusterNCells", "ClustersAfterCuts/clusterNCells"}; - static constexpr std::string_view kClusterQAHistDistanceToBadChannel[2] = {"ClustersBeforeCuts/clusterDistanceToBadChannel", "ClustersAfterCuts/clusterDistanceToBadChannel"}; - mHistManager.fill(HIST(kClusterQAHistEnergy[BeforeCuts]), cluster.energy()); - mHistManager.fill(HIST(kClusterQAHistEnergySimpleBinning[BeforeCuts]), cluster.energy()); - mHistManager.fill(HIST(kClusterQAHistTime[BeforeCuts]), cluster.time()); - mHistManager.fill(HIST(kClusterQAHistEtaPhi[BeforeCuts]), cluster.eta(), cluster.phi()); - mHistManager.fill(HIST(kClusterQAHistM02[BeforeCuts]), cluster.m02()); - mHistManager.fill(HIST(kClusterQAHistM20[BeforeCuts]), cluster.m20()); - mHistManager.fill(HIST(kClusterQAHistNLM[BeforeCuts]), cluster.nlm()); - mHistManager.fill(HIST(kClusterQAHistNCells[BeforeCuts]), cluster.nCells()); - mHistManager.fill(HIST(kClusterQAHistDistanceToBadChannel[BeforeCuts]), cluster.distanceToBadChannel()); + static constexpr std::string_view ClusterQAHistEnergy[2] = {"ClustersBeforeCuts/clusterE", "ClustersAfterCuts/clusterE"}; + static constexpr std::string_view ClusterQAHistEnergySimpleBinning[2] = {"ClustersBeforeCuts/clusterE_SimpleBinning", "ClustersAfterCuts/clusterE_SimpleBinning"}; + static constexpr std::string_view ClusterQAHistTime[2] = {"ClustersBeforeCuts/clusterTime", "ClustersAfterCuts/clusterTime"}; + static constexpr std::string_view ClusterQAHistEtaPhi[2] = {"ClustersBeforeCuts/clusterEtaPhi", "ClustersAfterCuts/clusterEtaPhi"}; + static constexpr std::string_view ClusterQAHistM02[2] = {"ClustersBeforeCuts/clusterM02", "ClustersAfterCuts/clusterM02"}; + static constexpr std::string_view ClusterQAHistM20[2] = {"ClustersBeforeCuts/clusterM20", "ClustersAfterCuts/clusterM20"}; + static constexpr std::string_view ClusterQAHistNLM[2] = {"ClustersBeforeCuts/clusterNLM", "ClustersAfterCuts/clusterNLM"}; + static constexpr std::string_view ClusterQAHistNCells[2] = {"ClustersBeforeCuts/clusterNCells", "ClustersAfterCuts/clusterNCells"}; + static constexpr std::string_view ClusterQAHistDistanceToBadChannel[2] = {"ClustersBeforeCuts/clusterDistanceToBadChannel", "ClustersAfterCuts/clusterDistanceToBadChannel"}; + mHistManager.fill(HIST(ClusterQAHistEnergy[BeforeCuts]), cluster.energy()); + mHistManager.fill(HIST(ClusterQAHistEnergySimpleBinning[BeforeCuts]), cluster.energy()); + mHistManager.fill(HIST(ClusterQAHistTime[BeforeCuts]), cluster.time()); + mHistManager.fill(HIST(ClusterQAHistEtaPhi[BeforeCuts]), cluster.eta(), cluster.phi()); + mHistManager.fill(HIST(ClusterQAHistM02[BeforeCuts]), cluster.m02()); + mHistManager.fill(HIST(ClusterQAHistM20[BeforeCuts]), cluster.m20()); + mHistManager.fill(HIST(ClusterQAHistNLM[BeforeCuts]), cluster.nlm()); + mHistManager.fill(HIST(ClusterQAHistNCells[BeforeCuts]), cluster.nCells()); + mHistManager.fill(HIST(ClusterQAHistDistanceToBadChannel[BeforeCuts]), cluster.distanceToBadChannel()); } /// \brief Return a boolean that states, whether a cluster should be rejected by the applied cluster cuts - template + template bool clusterRejectedByCut(Cluster const& cluster) { // apply basic cluster cuts @@ -432,7 +653,7 @@ struct EmcalPi0Qc { } /// \brief Process meson candidates, calculate invariant mass and pT and fill histograms - void processMesons() + void processMesons(float timeSinceSOR = 0.f) { LOG(debug) << "processMesons " << mPhotons.size(); @@ -449,6 +670,12 @@ struct EmcalPi0Qc { if (meson.getOpeningAngle() > mMinOpenAngleCut) { mHistManager.fill(HIST("invMassVsPt"), meson.getMass(), meson.getPt()); + uint8_t sm1 = mPhotons[ig1].sm; + uint8_t sm2 = mPhotons[ig2].sm; + if (sm1 == sm2) { + fillSupermoduleHistogramsMeson(sm1, meson.getMass(), timeSinceSOR); + } + if (mSplitEMCalDCal) { if (!mPhotons[ig1].onDCal && !mPhotons[ig2].onDCal) { mHistManager.fill(HIST("invMassVsPt_EMCal"), meson.getMass(), meson.getPt()); @@ -476,24 +703,28 @@ struct EmcalPi0Qc { } const double rotationAngle = o2::constants::math::PIHalf; // 0.78539816339; // rotaion angle 90° - TLorentzVector lvRotationPhoton1; // photon candidates which get rotated - TLorentzVector lvRotationPhoton2; // photon candidates which get rotated - TVector3 lvRotationPion; // rotation axis + ROOT::Math::PxPyPzEVector lvRotationPhoton1; // photon candidates which get rotated + ROOT::Math::PxPyPzEVector lvRotationPhoton2; // photon candidates which get rotated + ROOT::Math::PxPyPzEVector lvRotationPion; // rotation axis for (unsigned int ig3 = 0; ig3 < mPhotons.size(); ++ig3) { // continue if photons are identical if (ig3 == ig1 || ig3 == ig2) { continue; } - // calculate rotation axis - lvRotationPion = (meson.pMeson).Vect(); // initialize photons for rotation lvRotationPhoton1.SetPxPyPzE(mPhotons[ig1].px, mPhotons[ig1].py, mPhotons[ig1].pz, mPhotons[ig1].energy); lvRotationPhoton2.SetPxPyPzE(mPhotons[ig2].px, mPhotons[ig2].py, mPhotons[ig2].pz, mPhotons[ig2].energy); + lvRotationPion = meson.getMathVector(); + + // calculate rotation axis and matrix + lvRotationPion = lvRotationPhoton1 + lvRotationPhoton2; + ROOT::Math::AxisAngle rotationAxis(lvRotationPion.Vect(), rotationAngle); + ROOT::Math::Rotation3D rotationMatrix(rotationAxis); // rotate photons around rotation axis - lvRotationPhoton1.Rotate(rotationAngle, lvRotationPion); - lvRotationPhoton2.Rotate(rotationAngle, lvRotationPion); + lvRotationPhoton1 = rotationMatrix * lvRotationPhoton1; + lvRotationPhoton2 = rotationMatrix * lvRotationPhoton2; // initialize Photon objects for rotated photons Photon rotPhoton1(lvRotationPhoton1.Eta(), lvRotationPhoton1.Phi(), lvRotationPhoton1.E(), mPhotons[ig1].id); diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx index b7f632512c2..39af167b327 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -16,6 +16,8 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/ClusterHistograms.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -46,16 +48,15 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyEMCClusters = soa::Join; -using MyEMCCluster = MyEMCClusters::iterator; +using EMCalPhotons = soa::Join; +using EMCalPhoton = EMCalPhotons::iterator; struct EmcalQC { 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 { @@ -86,10 +87,14 @@ struct EmcalQC { Configurable maxM02{"maxM02", 0.7, "Maximum M02 for EMCal M02 cut"}; Configurable minClusterE{"minClusterE", 0.7, "Minimum cluster energy for EMCal energy cut"}; Configurable minNCell{"minNCell", 1, "Minimum number of cells per cluster for EMCal NCell cut"}; - Configurable> tmEta{"tmEta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; - Configurable> tmPhi{"tmPhi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> cfgEMCTMEta{"cfgEMCTMEta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> cfgEMCTMPhi{"cfgEMCTMPhi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> emcSecTMEta{"emcSecTMEta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> emcSecTMPhi{"emcSecTMPhi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; Configurable tmEoverP{"tmEoverP", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; Configurable useExoticCut{"useExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; + Configurable cfgEMCUseTM{"cfgEMCUseTM", false, "flag to use EMCal track matching cut or not"}; + Configurable emcUseSecondaryTM{"emcUseSecondaryTM", false, "flag to use EMCal secondary track matching cut or not"}; } emccuts; void defineEMEventCut() @@ -115,20 +120,28 @@ struct EmcalQC { fEMCCut.SetM02Range(emccuts.minM02, emccuts.maxM02); fEMCCut.SetTimeRange(emccuts.minClusterTime, emccuts.maxClusterTime); - fEMCCut.SetTrackMatchingEtaParams(emccuts.tmEta->at(0), emccuts.tmEta->at(1), emccuts.tmEta->at(2)); - fEMCCut.SetTrackMatchingPhiParams(emccuts.tmPhi->at(0), emccuts.tmPhi->at(1), emccuts.tmPhi->at(2)); + fEMCCut.SetUseExoticCut(emccuts.useExoticCut); + fEMCCut.SetTrackMatchingEtaParams(emccuts.cfgEMCTMEta->at(0), emccuts.cfgEMCTMEta->at(1), emccuts.cfgEMCTMEta->at(2)); + fEMCCut.SetTrackMatchingPhiParams(emccuts.cfgEMCTMPhi->at(0), emccuts.cfgEMCTMPhi->at(1), emccuts.cfgEMCTMPhi->at(2)); fEMCCut.SetMinEoverP(emccuts.tmEoverP); - fEMCCut.SetUseExoticCut(emccuts.useExoticCut); + fEMCCut.SetUseTM(emccuts.cfgEMCUseTM.value); // disables or enables TM + + fEMCCut.SetSecTrackMatchingEtaParams(emccuts.emcSecTMEta->at(0), emccuts.emcSecTMEta->at(1), emccuts.emcSecTMEta->at(2)); + fEMCCut.SetSecTrackMatchingPhiParams(emccuts.emcSecTMPhi->at(0), emccuts.emcSecTMPhi->at(1), emccuts.emcSecTMPhi->at(2)); + fEMCCut.SetUseSecondaryTM(emccuts.emcUseSecondaryTM.value); // disables or enables secondary TM } HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - std::vector zVtxBinEdges; + + SliceCache cache; + + PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; + PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; void init(InitContext&) { - zVtxBinEdges = std::vector(confVtxBins.value.begin(), confVtxBins.value.end()); - zVtxBinEdges.erase(zVtxBinEdges.begin()); defineEMCCut(); defineEMEventCut(); @@ -145,88 +158,184 @@ struct EmcalQC { o2::aod::pwgem::photonmeson::utils::clusterhistogram::addClusterHistograms(&fRegistry, cfgDo2DQA); } - Preslice perCollision = aod::emccluster::emeventId; - - void processQC(MyCollisions const& collisions, MyEMCClusters const& clusters) + bool isEventGood(MyCollision const& collision) { - for (const auto& collision : collisions) { - if (eventcuts.onlyKeepWeightedEvents && std::fabs(collision.weight() - 1.) < 1E-10) { - continue; - } - - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 1, collision.weight()); - if (!eventcuts.cfgRequireFT0AND || collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 2, collision.weight()); - if (std::abs(collision.posZ()) < eventcuts.cfgZvtxMax) { - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 3, collision.weight()); - if (!eventcuts.cfgRequireSel8 || collision.sel8()) { - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 4, collision.weight()); - if (!eventcuts.cfgRequireGoodZvtxFT0vsPV || collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 5, collision.weight()); - if (!eventcuts.cfgRequireNoSameBunchPileup || collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 6, collision.weight()); - if (!eventcuts.cfgRequireEMCReadoutInMB || collision.alias_bit(kTVXinEMC)) - fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 7, collision.weight()); + if (eventcuts.onlyKeepWeightedEvents && std::fabs(collision.weight() - 1.) < 1E-10) { + return false; + } + + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 1, collision.weight()); + if (!eventcuts.cfgRequireFT0AND || collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 2, collision.weight()); + if (std::abs(collision.posZ()) < eventcuts.cfgZvtxMax) { + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 3, collision.weight()); + if (!eventcuts.cfgRequireSel8 || collision.sel8()) { + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 4, collision.weight()); + if (!eventcuts.cfgRequireGoodZvtxFT0vsPV || collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 5, collision.weight()); + if (!eventcuts.cfgRequireNoSameBunchPileup || collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 6, collision.weight()); + if (!eventcuts.cfgRequireEMCReadoutInMB || collision.alias_bit(kTVXinEMC)) { + fRegistry.fill(HIST("Event/hEMCCollisionCounter"), 7, collision.weight()); } } } } } + } + + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, collision.weight()); + if (!fEMEventCut.IsSelected(collision)) { + return false; + } + if (!(eventcuts.cfgOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgOccupancyMax)) { + return false; + } + + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, collision.weight()); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, collision.weight()); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, collision.weight()); // accepted + return true; + } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, collision.weight()); - if (!fEMEventCut.IsSelected(collision)) { + template + void doClusterQA(MyCollision const& collision, TClusters const& clusters) + { + fRegistry.fill(HIST("Cluster/before/hNgamma"), clusters.size(), collision.weight()); + int ngAfter = 0; + for (const auto& cluster : clusters) { + // Fill the cluster properties before applying any cuts + if (!fEMCCut.IsSelectedEMCal(EMCPhotonCut::EMCPhotonCuts::kDefinition, cluster)) { continue; } - if (!(eventcuts.cfgOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgOccupancyMax)) { - continue; + 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 = false; + + survivesIsSelectedCuts = fEMCCut.IsSelected(cluster); + 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; + } } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, collision.weight()); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, collision.weight()); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, collision.weight()); // accepted + if (survivesIsSelectedCuts != survivesIsSelectedEMCalCuts) { + LOGF(info, "Cummulative application of IsSelectedEMCal cuts does not equal the IsSelected result"); + LOGF(info, "Cummulative application of IsSelectedEMCal resulted in %d", survivesIsSelectedEMCalCuts); + LOGF(info, "IsSelected resulted in %d", survivesIsSelectedCuts); + } - auto clustersPerColl = clusters.sliceBy(perCollision, collision.collisionId()); - fRegistry.fill(HIST("Cluster/before/hNgamma"), clustersPerColl.size(), collision.weight()); - int ngAfter = 0; - for (const auto& cluster : clustersPerColl) { - // Fill the cluster properties before applying any cuts - if (!fEMCCut.IsSelectedEMCal(EMCPhotonCut::EMCPhotonCuts::kDefinition, cluster)) + if (survivesIsSelectedCuts) { + o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<1>(&fRegistry, cluster, cfgDo2DQA, collision.weight()); + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts) + 1., cluster.e(), collision.weight()); + ++ngAfter; + } + } + fRegistry.fill(HIST("Cluster/after/hNgamma"), ngAfter, collision.weight()); + + return; + } + + template + void doClusterQA(MyCollision const& collision, TClusters const& clusters, TMatchedTracks const& primTracks, TMatchedSecondaries const& secTracks) + { + fRegistry.fill(HIST("Cluster/before/hNgamma"), clusters.size(), collision.weight()); + int ngAfter = 0; + for (const auto& cluster : clusters) { + // Fill the cluster properties before applying any cuts + if (!fEMCCut.IsSelectedEMCal(EMCPhotonCut::EMCPhotonCuts::kDefinition, cluster)) { + continue; + } + auto primTracksPerCluster = primTracks.sliceBy(perEMCClusterMT, cluster.globalIndex()); + auto secTracksPerCluster = secTracks.sliceBy(perEMCClusterMS, cluster.globalIndex()); + o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<0>(&fRegistry, cluster, cfgDo2DQA, collision.weight(), primTracksPerCluster, secTracksPerCluster); + + // 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 = false; + + survivesIsSelectedCuts = fEMCCut.IsSelected(cluster, primTracksPerCluster, secTracksPerCluster); + for (int icut = 0; icut < static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts); icut++) { // Loop through different cut observables + EMCPhotonCut::EMCPhotonCuts specificcut = static_cast(icut); + if (specificcut == EMCPhotonCut::EMCPhotonCuts::kTM || specificcut == EMCPhotonCut::EMCPhotonCuts::kSecondaryTM) { + // will do track matching cuts extra later or never depending on chosen process function continue; - o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<0>(&fRegistry, cluster, cfgDo2DQA, collision.weight()); + } + 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; + } + } - // Apply cuts one by one and fill in hClusterQualityCuts histogram - fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), 0., cluster.e(), collision.weight()); + if (!fEMCCut.IsSelectedEMCal(EMCPhotonCut::EMCPhotonCuts::kTM, cluster, primTracksPerCluster)) { // Check whether cluster passes this cluster requirement, if not, fill why in the next row + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCut::EMCPhotonCuts::kTM) + 1, cluster.e(), collision.weight()); + survivesIsSelectedEMCalCuts = false; + } + if (!fEMCCut.IsSelectedEMCal(EMCPhotonCut::EMCPhotonCuts::kSecondaryTM, cluster, secTracksPerCluster)) { // Check whether cluster passes this cluster requirement, if not, fill why in the next row + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCut::EMCPhotonCuts::kSecondaryTM) + 1, cluster.e(), collision.weight()); + survivesIsSelectedEMCalCuts = false; + } - // 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 + if (survivesIsSelectedCuts != survivesIsSelectedEMCalCuts) [[unlikely]] { + LOGF(info, "Cummulative application of IsSelectedEMCal cuts does not equal the IsSelected result"); + LOGF(info, "Cummulative application of IsSelectedEMCal resulted in %d", survivesIsSelectedEMCalCuts); + LOGF(info, "IsSelected resulted in %d", survivesIsSelectedCuts); + } - 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) { + o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<1>(&fRegistry, cluster, cfgDo2DQA, collision.weight(), primTracksPerCluster, secTracksPerCluster); + fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts) + 1., cluster.e(), collision.weight()); + ++ngAfter; + } + } + fRegistry.fill(HIST("Cluster/after/hNgamma"), ngAfter, collision.weight()); - if (survivesIsSelectedCuts != survivesIsSelectedEMCalCuts) { - LOGF(info, "Cummulative application of IsSelectedEMCal cuts does not equal the IsSelected result"); - } + return; + } - if (survivesIsSelectedCuts) { - o2::aod::pwgem::photonmeson::utils::clusterhistogram::fillClusterHistograms<1>(&fRegistry, cluster, cfgDo2DQA, collision.weight()); - fRegistry.fill(HIST("Cluster/hClusterQualityCuts"), static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts) + 1., cluster.e(), collision.weight()); - ngAfter++; - } + void processQC(MyCollisions const& collisions, EMCalPhotons const& clusters) + { + for (const auto& collision : collisions) { + + if (!isEventGood(collision)) { + continue; } - fRegistry.fill(HIST("Cluster/after/hNgamma"), ngAfter, collision.weight()); + + auto clustersPerColl = clusters.sliceBy(perCollisionEMC, collision.collisionId()); + doClusterQA(collision, clustersPerColl); + + } // end of collision loop + } // end of process + + void processQCTM(MyCollisions const& collisions, EMCalPhotons const& clusters, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) + { + for (const auto& collision : collisions) { + + if (!isEventGood(collision)) { + continue; + } + + auto clustersPerColl = clusters.sliceBy(perCollisionEMC, collision.collisionId()); + doClusterQA(collision, clustersPerColl, matchedPrims, matchedSeconds); + } // end of collision loop } // end of process void processDummy(MyCollisions const&) {} PROCESS_SWITCH(EmcalQC, processQC, "run EMCal QC", false); + PROCESS_SWITCH(EmcalQC, processQCTM, "run EMCal QC with track matching", false); PROCESS_SWITCH(EmcalQC, processDummy, "Dummy function", true); }; diff --git a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx index b9268ab3907..7c436bf018c 100644 --- a/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx +++ b/PWGEM/PhotonMeson/Tasks/gammaConversions.cxx @@ -16,6 +16,7 @@ #include "PWGEM/PhotonMeson/Tasks/gammaConversions.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h" @@ -619,8 +620,8 @@ struct GammaConversions { } } - Preslice perCollision = aod::v0photonkf::emeventId; - void processRec(aod::EMEvents::iterator const& theCollision, + Preslice perCollision = aod::v0photonkf::pmeventId; + void processRec(aod::PMEvents::iterator const& theCollision, V0DatasAdditional const& theV0s, aod::V0Legs const&) { @@ -645,7 +646,7 @@ struct GammaConversions { Preslice gperV0 = aod::gammamctrue::v0photonkfId; - void processMc(aod::EMEvents::iterator const& theCollision, + void processMc(aod::PMEvents::iterator const& theCollision, V0DatasAdditional const& theV0s, V0LegsWithMC const&, aod::V0DaughterMcParticles const&, diff --git a/PWGEM/PhotonMeson/Tasks/gammaConversionsTruthOnlyMc.cxx b/PWGEM/PhotonMeson/Tasks/gammaConversionsTruthOnlyMc.cxx index ae2ad0c548f..94ad627191a 100644 --- a/PWGEM/PhotonMeson/Tasks/gammaConversionsTruthOnlyMc.cxx +++ b/PWGEM/PhotonMeson/Tasks/gammaConversionsTruthOnlyMc.cxx @@ -20,10 +20,11 @@ #include #include +#include +#include +#include #include -#include - #include using namespace o2; diff --git a/PWGEM/PhotonMeson/Tasks/mcGeneratorStudies.cxx b/PWGEM/PhotonMeson/Tasks/mcGeneratorStudies.cxx index 889858359ed..fc390c4ce65 100644 --- a/PWGEM/PhotonMeson/Tasks/mcGeneratorStudies.cxx +++ b/PWGEM/PhotonMeson/Tasks/mcGeneratorStudies.cxx @@ -16,13 +16,16 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt /// -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "TDatabasePDG.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 3f8130abe0d..9530c9401da 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -14,27 +14,35 @@ /// \author Daiki Sekihata, daiki.sekihata@cern.ch #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include #include +#include +#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include #include @@ -46,16 +54,24 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyV0PhotonsML = soa::Join; +using MyV0PhotonML = MyV0PhotonsML::iterator; + struct PCMQC { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + 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"}; EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { @@ -106,8 +122,28 @@ struct PCMQC { 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"}; Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + Configurable cfg_dEdx_postcalibration{"cfg_dEdx_postcalibration", false, "flag to enable dEdx post calibration"}; + // for ML cuts + Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; } pcmcuts; + o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service ccdb; + int mRunNumber; + float d_bz; static constexpr std::string_view event_types[2] = {"before/", "after/"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -116,6 +152,54 @@ struct PCMQC { addhistograms(); DefineEMEventCut(); DefinePCMCut(); + + 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 (std::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"; + } + fV0PhotonCut.SetD_Bz(d_bz); + mRunNumber = collision.runNumber(); } void addhistograms() @@ -165,6 +249,22 @@ struct PCMQC { fRegistry.add("V0/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); + if (pcmcuts.cfg_apply_ml_cuts) { + if (pcmcuts.cfg_nclasses_ml == 2) { + fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else if (pcmcuts.cfg_nclasses_ml == 3) { + fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else { + fRegistry.add("V0/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); + fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } + } + // 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); @@ -183,6 +283,10 @@ struct PCMQC { 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)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + if (pcmcuts.cfg_dEdx_postcalibration) { + fRegistry.add("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Pos", "momentum of pos leg vs. conversion point of V0 vs. TPC n sigma pos vs. eta of pos leg; p (GeV/c); r_{xy} (cm); n #sigma_{e}^{TPC}; #eta", kTHnSparseF, {{200, 0, 20}, {100, 0, 100}, {500, -5, 5}, {200, -1, +1}}, false); + fRegistry.add("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Ele", "momentum of neg leg vs. conversion point of V0 vs. TPC n sigma el vs. eta of neg leg; p (GeV/c); r_{xy} (cm); n #sigma_{e}^{TPC}; #eta", kTHnSparseF, {{200, 0, 20}, {100, 0, 100}, {500, -5, 5}, {200, -1, +1}}, 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}, {80, -20, 20}}, false); @@ -235,6 +339,31 @@ struct PCMQC { fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for psi_pair calculation + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } } template @@ -302,6 +431,28 @@ struct PCMQC { o2::math_utils::bringTo02Pi(phi_cp); float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); fRegistry.fill(HIST("V0/hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); + + // BDT response histogram can be filled here when apply BDT is true + if (pcmcuts.cfg_apply_ml_cuts) { + const std::span& bdtValue = fV0PhotonCut.getBDTValue(); + float psipair = 999.f; + float phiv = 999.f; + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + fRegistry.fill(HIST("V0/hPhiVPsi"), psipair, phiv); + if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { + fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); + } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { + fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); + fRegistry.fill(HIST("V0/hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); + } else if (bdtValue.size() == 1) { + fRegistry.fill(HIST("V0/hBDTCutVsPt"), v0.pt(), bdtValue[0]); + } + } } template @@ -331,15 +482,18 @@ struct PCMQC { // fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); } - Preslice perCollision = aod::v0photonkf::emeventId; + Preslice perCollisionV0 = aod::v0photonkf::pmeventId; + Preslice perCollisionV0ML = aod::v0photonkf::pmeventId; 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_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; - void processQC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const&) + template + void process(FilteredMyCollisions const& collisions, TV0Photon const& v0photons, aod::V0Legs const&, TPerCollision const& perCollision) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { + initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -353,11 +507,12 @@ struct PCMQC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); int nv0 = 0; auto v0photons_coll = v0photons.sliceBy(perCollision, collision.globalIndex()); - for (auto& v0 : v0photons_coll) { - auto pos = v0.posTrack_as(); - auto ele = v0.negTrack_as(); + for (const auto& v0 : v0photons_coll) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); if (!fV0PhotonCut.IsSelected(v0)) { continue; @@ -366,15 +521,29 @@ struct PCMQC { for (auto& leg : {pos, ele}) { fillV0LegInfo(leg); } + if (pcmcuts.cfg_dEdx_postcalibration) { + fRegistry.fill(HIST("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Pos"), pos.p(), v0.v0radius(), pos.tpcNSigmaEl(), pos.eta()); + fRegistry.fill(HIST("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Ele"), ele.p(), v0.v0radius(), ele.tpcNSigmaEl(), ele.eta()); + } nv0++; } // end of v0 loop fRegistry.fill(HIST("V0/hNgamma"), nv0); } // end of collision loop + } + void processQC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::V0Legs const& v0legs) + { + process(collisions, v0photons, v0legs, perCollisionV0); } // end of process + void processQCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::V0Legs const& v0legs) + { + process(collisions, v0photonsML, v0legs, perCollisionV0ML); + } // end of ML process + void processDummy(MyCollisions const&) {} PROCESS_SWITCH(PCMQC, processQC, "run PCM QC", true); + PROCESS_SWITCH(PCMQC, processQCML, "run PCM QC with ML", false); PROCESS_SWITCH(PCMQC, processDummy, "Dummy function", false); }; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index f858ec60743..264808e451a 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -15,7 +15,9 @@ #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" @@ -23,22 +25,29 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include #include +#include +#include +#include +#include +#include #include #include #include #include #include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -52,15 +61,18 @@ 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 MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = o2::soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyV0PhotonsML = soa::Join; +using MyV0PhotonML = MyV0PhotonsML::iterator; + using MyMCV0Legs = soa::Join; using MyMCV0Leg = MyMCV0Legs::iterator; @@ -69,6 +81,11 @@ struct PCMQCMC { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + 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 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"}; @@ -123,8 +140,27 @@ struct PCMQCMC { 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"}; Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + // for ML cuts + Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; } pcmcuts; + o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service ccdb; + int mRunNumber; + float d_bz; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view event_types[2] = {"before/", "after/"}; static constexpr std::string_view mcphoton_types[5] = {"primary/", "fromWD/", "fromHS/", "fromPi0Dalitz/", "fromEtaDalitz/"}; @@ -134,6 +170,54 @@ struct PCMQCMC { DefineEMEventCut(); DefinePCMCut(); 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 (std::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"; + } + fV0PhotonCut.SetD_Bz(d_bz); + mRunNumber = collision.runNumber(); } void addhistograms() @@ -155,9 +239,9 @@ struct PCMQCMC { const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y_{#gamma}|"}; 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_ConversionPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1F, {axis_pt}, true); + fRegistry.add("Generated/hPt", "pT;p_{T} (GeV/c)", kTH1D, {axis_pt}, true); + fRegistry.add("Generated/hPtY", "Generated info", kTH2D, {axis_pt, axis_rapidity}, true); + fRegistry.add("Generated/hPt_ConversionPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1D, {axis_pt}, true); fRegistry.add("Generated/hY_ConversionPhoton", "converted photon y;rapidity y", kTH1F, {{40, -2.0f, 2.0f}}, true); fRegistry.add("Generated/hPhi_ConversionPhoton", "converted photon #varphi;#varphi (rad.)", kTH1F, {{180, 0, o2::constants::math::TwoPI}}, true); fRegistry.add("Generated/hXY", "conversion point in XY MC;V_{x} (cm);V_{y} (cm)", kTH2F, {{800, -100.0f, 100.0f}, {800, -100.0f, 100.0f}}, true); @@ -222,6 +306,21 @@ struct PCMQCMC { fRegistry.add("V0/primary/hXY_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_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); fRegistry.add("V0/primary/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); + if (pcmcuts.cfg_apply_ml_cuts) { + if (pcmcuts.cfg_nclasses_ml == 2) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else if (pcmcuts.cfg_nclasses_ml == 3) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else { + fRegistry.add("V0/primary/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } + } fRegistry.addClone("V0/primary/", "V0/fromWD/"); // from weak decay fRegistry.addClone("V0/primary/", "V0/fromHS/"); // from hadronic shower in detector materials fRegistry.addClone("V0/primary/", "V0/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay @@ -314,6 +413,31 @@ struct PCMQCMC { fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + CentType mCentralityTypeMlEnum; + mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for phiv calculation + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } } template @@ -394,6 +518,28 @@ struct PCMQCMC { o2::math_utils::bringTo02Pi(phi_cp); float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); + + // BDT response histogram can be filled here when apply BDT is true + if (pcmcuts.cfg_apply_ml_cuts) { + const std::span& bdtValue = fV0PhotonCut.getBDTValue(); + float psipair = 999.f; + float phiv = 999.f; + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVPsi"), psipair, phiv); + if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); + } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); + } else if (bdtValue.size() == 1) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTCutVsPt"), v0.pt(), bdtValue[0]); + } + } } template @@ -429,16 +575,18 @@ struct PCMQCMC { fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); } - + Preslice perCollisionV0 = aod::v0photonkf::pmeventId; + Preslice perCollisionV0ML = aod::v0photonkf::pmeventId; 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_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; - Preslice perCollision = aod::v0photonkf::emeventId; - void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const&, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const&) + template + void processMC(FilteredMyCollisions const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&, TPerCollision const& percollision) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { + initCCDB(collision); const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -452,11 +600,12 @@ struct PCMQCMC { fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - auto V0Photons_coll = v0photons.sliceBy(perCollision, collision.globalIndex()); + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); // set centrality for BDT response + auto V0Photons_coll = v0photons.sliceBy(percollision, collision.globalIndex()); int ng_primary = 0, ng_wd = 0, ng_hs = 0, nee_pi0 = 0, nee_eta = 0; - for (auto& v0 : V0Photons_coll) { - auto pos = v0.posTrack_as(); - auto ele = v0.negTrack_as(); + for (const auto& v0 : V0Photons_coll) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); auto posmc = pos.template emmcparticle_as(); auto elemc = ele.template emmcparticle_as(); @@ -468,7 +617,7 @@ struct PCMQCMC { fRegistry.fill(HIST("V0/candidate/hPt"), v0.pt()); fRegistry.fill(HIST("V0/candidate/hEtaPhi"), v0.phi(), v0.eta()); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fRegistry.fill(HIST("V0Leg/candidate/hPt"), leg.pt()); fRegistry.fill(HIST("V0Leg/candidate/hEtaPhi"), leg.phi(), leg.eta()); } @@ -488,19 +637,19 @@ struct PCMQCMC { if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { fillV0Info<0>(v0, mcphoton, elemc); - for (auto& leg : {pos, ele}) { + for (const 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}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<1>(leg); } ng_wd++; } else { fillV0Info<2>(v0, mcphoton, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<2>(leg); } ng_hs++; @@ -513,7 +662,7 @@ struct PCMQCMC { } if (mcpi0.isPhysicalPrimary() || mcpi0.producedByGenerator()) { fillV0Info<3>(v0, mcpi0, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<3>(leg); } nee_pi0++; @@ -525,7 +674,7 @@ struct PCMQCMC { } if (mceta.isPhysicalPrimary() || mceta.producedByGenerator()) { fillV0Info<4>(v0, mceta, elemc); - for (auto& leg : {pos, ele}) { + for (const auto& leg : {pos, ele}) { fillV0LegInfo<4>(leg); } nee_eta++; @@ -540,6 +689,16 @@ struct PCMQCMC { } // end of collision loop } // end of process + void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents, perCollisionV0); + } // end of QC process + + void processQCMCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents, perCollisionV0ML); + } // end of QC process with ML cuts + template void fillBinnedData(TBinnedData const& binned_data, const float weight = 1.f) { @@ -570,7 +729,7 @@ struct PCMQCMC { // 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) { + for (const auto& collision : collisions) { const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; @@ -586,12 +745,12 @@ struct PCMQCMC { // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); - for (auto& mctrack : mctracks_coll) { + for (const auto& mctrack : mctracks_coll) { if (std::fabs(mctrack.y()) > pcmcuts.cfg_max_eta_v0) { continue; } - if (std::abs(mctrack.pdgCode()) == 22 && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + if (std::abs(mctrack.pdgCode()) == PDG_t::kGamma && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { auto daughter = mcparticles.iteratorAt(mctrack.daughtersIds()[0]); // choose ele or pos. float rxy_gen_e = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); float phi_cp = std::atan2(daughter.vy(), daughter.vx()); @@ -621,6 +780,7 @@ struct PCMQCMC { PROCESS_SWITCH(PCMQCMC, processQCMC, "run PCM QC in MC", false); PROCESS_SWITCH(PCMQCMC, processGen, "run generated information", false); + PROCESS_SWITCH(PCMQCMC, processQCMCML, "run PCM QC in MC with ML cuts", false); PROCESS_SWITCH(PCMQCMC, processDummy, "Dummy function", true); }; diff --git a/PWGEM/PhotonMeson/Tasks/phosQC.cxx b/PWGEM/PhotonMeson/Tasks/phosQC.cxx index 4f5ef2ec075..56c7adb50b6 100644 --- a/PWGEM/PhotonMeson/Tasks/phosQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/phosQC.cxx @@ -17,16 +17,17 @@ #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "Common/CCDB/TriggerAliases.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include #include +#include #include #include +#include #include #include @@ -44,7 +45,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; struct phosQC { diff --git a/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx new file mode 100644 index 00000000000..a1ddbb8f3d7 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/photonResoTask.cxx @@ -0,0 +1,613 @@ +// 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 photonResoTask.cxx +/// \brief Analysis task for to obtain photon resolution histograms in MC +/// \author M. Hemmer, marvin.hemmer@cern.ch + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/EMBitFlags.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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; + +enum CentralityEstimator { + None = 0, + CFT0A = 1, + CFT0C, + CFT0M, + NCentralityEstimators +}; + +enum class MapLevel { + kGood = 1, + kNoBad = 2, + kInEMC = 3, + kAll = 4 +}; + +struct PhotonResoTask { + static constexpr float MinEnergy = 0.7f; + + o2::framework::Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + o2::framework::Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + o2::framework::Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + o2::framework::Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + // configurable axis + ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {400, 0.0, 0.8}, "invariant mass axis for the neutral meson"}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {100, 0., 20.}, "pT axis for the neutral meson"}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {20, 0., 100.}, "centrality axis for the current event"}; + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcuts"; + 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", true, "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 cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -1, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgMinCent{"cfgMinCent", 0, "min. centrality (%)"}; + Configurable cfgMaxCent{"cfgMaxCent", 90, "max. centrality (%)"}; + Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; + 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 = "emccuts"; + Configurable clusterDefinition{"clusterDefinition", "kV3MostSplitSmallestTimeDiff", "Clusterizer to be selected, e.g. V3Default"}; + Configurable cfgEMCminTime{"cfgEMCminTime", -25., "Minimum cluster time for EMCal time cut"}; + Configurable cfgEMCmaxTime{"cfgEMCmaxTime", +30., "Maximum cluster time for EMCal time cut"}; + Configurable cfgEMCminM02{"cfgEMCminM02", 0.1, "Minimum M02 for EMCal M02 cut"}; + Configurable cfgEMCmaxM02{"cfgEMCmaxM02", 0.7, "Maximum M02 for EMCal M02 cut"}; + Configurable cfgEMCminE{"cfgEMCminE", 0.7, "Minimum cluster energy for EMCal energy cut"}; + Configurable cfgEMCminNCell{"cfgEMCminNCell", 1, "Minimum number of cells per cluster for EMCal NCell cut"}; + Configurable> cfgEMCTMEta{"cfgEMCTMEta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> cfgEMCTMPhi{"cfgEMCTMPhi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> emcSecTMEta{"emcSecTMEta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable> emcSecTMPhi{"emcSecTMPhi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; + Configurable cfgEMCEoverp{"cfgEMCEoverp", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; + Configurable cfgEMCUseExoticCut{"cfgEMCUseExoticCut", true, "FLag to use the EMCal exotic cluster cut"}; + Configurable cfgEMCUseTM{"cfgEMCUseTM", false, "flag to use EMCal track matching cut or not"}; + Configurable emcUseSecondaryTM{"emcUseSecondaryTM", false, "flag to use EMCal secondary track matching cut or not"}; + Configurable cfgEnableQA{"cfgEnableQA", false, "flag to turn QA plots on/off"}; + } emccuts; + + V0PhotonCut fV0PhotonCut; + struct : o2::framework::ConfigurableGroup { + std::string prefix = "PCMcuts"; + o2::framework::Configurable requireV0WithITSTPC{"requireV0WithITSTPC", false, "flag to enforce V0s have ITS and TPC"}; + o2::framework::Configurable requireV0WithITSOnly{"requireV0WithITSOnly", false, "flag to select V0s with ITSonly tracks"}; + o2::framework::Configurable requireV0WithTPCOnly{"requireV0WithTPCOnly", false, "flag to select V0s with TPConly tracks"}; + o2::framework::Configurable minPtV0{"minPtV0", 0.1, "min pT for v0 photons at PV"}; + o2::framework::Configurable maxPtV0{"maxPtV0", 1e+10, "max pT for v0 photons at PV"}; + o2::framework::Configurable minEtaV0{"minEtaV0", -0.8, "min eta for v0 photons at PV"}; + o2::framework::Configurable maxEtaV0{"maxEtaV0", 0.8, "max eta for v0 photons at PV"}; + o2::framework::Configurable minRV0{"minRV0", 4.0, "min v0 radius"}; + o2::framework::Configurable maxRV0{"maxRV0", 90.0, "max v0 radius"}; + o2::framework::Configurable maxAlphaAP{"maxAlphaAP", 0.95, "max alpha for AP cut"}; + o2::framework::Configurable maxQtAP{"maxQtAP", 0.01, "max qT for AP cut"}; + o2::framework::Configurable minCosPA{"minCosPA", 0.999, "min V0 CosPA"}; + o2::framework::Configurable maxPCA{"maxPCA", 1.5, "max distance btween 2 legs"}; + o2::framework::Configurable maxChi2KF{"maxChi2KF", 1.e+10f, "max chi2/ndf with KF"}; + o2::framework::Configurable rejectV0onITSib{"rejectV0onITSib", true, "flag to reject V0s on ITSib"}; + o2::framework::Configurable applyPrefilter{"applyPrefilter", false, "flag to apply prefilter to V0"}; + + o2::framework::Configurable minNClusterTPC{"minNClusterTPC", 0, "min NCluster TPC"}; + o2::framework::Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 40, "min ncrossed rows in TPC"}; + o2::framework::Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "min fraction of crossed rows over findable clusters in TPC"}; + o2::framework::Configurable maxFracSharedClustersTPC{"maxFracSharedClustersTPC", 999.f, "max fraction of shared clusters in TPC"}; + o2::framework::Configurable minNClusterITS{"minNClusterITS", 0, "min NCluster ITS"}; + o2::framework::Configurable minMeanClusterSizeITSob{"minMeanClusterSizeITSob", 0.f, "min ITSob"}; + o2::framework::Configurable maxMeanClusterSizeITSob{"maxMeanClusterSizeITSob", 16.f, "max ITSob"}; + o2::framework::Configurable macChi2TPC{"macChi2TPC", 4.f, "max chi2/NclsTPC"}; + o2::framework::Configurable macChi2ITS{"macChi2ITS", 36.f, "max chi2/NclsITS"}; + o2::framework::Configurable minTPCNSigmaEl{"minTPCNSigmaEl", -3.0f, "min. TPC n sigma for electron"}; + o2::framework::Configurable maxTPCNSigmaEl{"maxTPCNSigmaEl", +3.0f, "max. TPC n sigma for electron"}; + o2::framework::Configurable disableITSOnly{"disableITSOnly", false, "flag to disable ITSonly tracks"}; + o2::framework::Configurable disableTPCOnly{"disableTPCOnly", false, "flag to disable TPConly tracks"}; + o2::framework::Configurable doQA{"doQA", false, "flag to set QA flag."}; + } pcmcuts; + + struct : ConfigurableGroup { + std::string prefix = "mesonConfig"; + Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle. Default value one EMCal cell"}; + Configurable cfgEnableQA{"cfgEnableQA", false, "flag to turn QA plots on/off"}; + } mesonConfig; + + struct : ConfigurableGroup { + std::string prefix = "mixingConfig"; + 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 cfgCentBins{"cfgCentBins", {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}, "Mixing bins - centrality"}; + ConfigurableAxis cfgEPBins{"cfgEPBins", {8, o2::constants::math::PIHalf, o2::constants::math::PIHalf}, "Mixing bins - event plane angle"}; + ConfigurableAxis cfgOccupancyBins{"cfgOccupancyBins", {VARIABLE_WIDTH, 0, 100, 500, 1000, 2000}, "Mixing bins - occupancy"}; + Configurable cfgMixingDepth{"cfgMixingDepth", 2, "Mixing depth"}; + } mixingConfig; + + struct : ConfigurableGroup { + std::string prefix = "rotationConfig"; + Configurable cfgDoRotation{"cfgDoRotation", false, "Flag to enable rotation background method."}; + Configurable cfgDownsampling{"cfgDownsampling", 1, "Calculate rotation background only for every collision."}; + Configurable cfgRotAngle{"cfgRotAngle", std::move(const_cast(o2::constants::math::PIHalf)), "Angle used for the rotation method."}; + Configurable cfgUseWeights{"cfgUseWeights", false, "Flag to enable weights for rotation background method."}; + } rotationConfig; + + struct : ConfigurableGroup { + std::string prefix = "correctionConfig"; + Configurable cfgSpresoPath{"cfgSpresoPath", "Users/m/mhemmer/EM/Flow/Resolution", "Path to SP resolution file"}; + Configurable cfgApplySPresolution{"cfgApplySPresolution", 0, "Apply resolution correction"}; + Configurable doEMCalCalib{"doEMCalCalib", 0, "Produce output for EMCal calibration"}; + Configurable cfgEnableNonLin{"cfgEnableNonLin", false, "flag to turn extra non linear energy calibration on/off"}; + } correctionConfig; + + SliceCache cache; + + using EMCalPhotons = soa::Join; + using PcmPhotons = soa::Join; + + using PcmMcLegs = soa::Join; + + using Colls = soa::Join; + + using McColls = o2::soa::Join; + using McParticles = EMMCParticles; + + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::pmeventId; + PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; + PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + o2::framework::Service ccdb; + int mRunNumber{-1}; + float dBz{0.f}; + + // Usage when cfgEnableNonLin is enabled + std::unique_ptr fEMCalCorrectionFactor; // ("fEMCalCorrectionFactor","(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); + float energyCorrectionFactor = 1.f; + + void defineEMEventCut() + { + 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); + } + + void defineEMCCut() + { + fEMCCut = EMCPhotonCut("fEMCCut", "fEMCCut"); + + fEMCCut.SetTrackMatchingEtaParams(emccuts.cfgEMCTMEta->at(0), emccuts.cfgEMCTMEta->at(1), emccuts.cfgEMCTMEta->at(2)); + fEMCCut.SetTrackMatchingPhiParams(emccuts.cfgEMCTMPhi->at(0), emccuts.cfgEMCTMPhi->at(1), emccuts.cfgEMCTMPhi->at(2)); + + fEMCCut.SetSecTrackMatchingEtaParams(emccuts.emcSecTMEta->at(0), emccuts.emcSecTMEta->at(1), emccuts.emcSecTMEta->at(2)); + fEMCCut.SetSecTrackMatchingPhiParams(emccuts.emcSecTMPhi->at(0), emccuts.emcSecTMPhi->at(1), emccuts.emcSecTMPhi->at(2)); + fEMCCut.SetMinEoverP(emccuts.cfgEMCEoverp); + + fEMCCut.SetMinE(emccuts.cfgEMCminE); + fEMCCut.SetMinNCell(emccuts.cfgEMCminNCell); + fEMCCut.SetM02Range(emccuts.cfgEMCminM02, emccuts.cfgEMCmaxM02); + fEMCCut.SetTimeRange(emccuts.cfgEMCminTime, emccuts.cfgEMCmaxTime); + fEMCCut.SetUseExoticCut(emccuts.cfgEMCUseExoticCut); + fEMCCut.SetClusterizer(emccuts.clusterDefinition); + fEMCCut.SetUseTM(emccuts.cfgEMCUseTM.value); // disables or enables TM + fEMCCut.SetUseSecondaryTM(emccuts.emcUseSecondaryTM.value); // disables or enables secondary TM + fEMCCut.SetDoQA(emccuts.cfgEnableQA.value); + } + + void definePCMCut() + { + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); + + // for v0 + fV0PhotonCut.SetV0PtRange(pcmcuts.minPtV0, pcmcuts.maxPtV0); + fV0PhotonCut.SetV0EtaRange(pcmcuts.minEtaV0, pcmcuts.maxEtaV0); + fV0PhotonCut.SetMinCosPA(pcmcuts.minCosPA); + fV0PhotonCut.SetMaxPCA(pcmcuts.maxPCA); + fV0PhotonCut.SetMaxChi2KF(pcmcuts.maxChi2KF); + fV0PhotonCut.SetRxyRange(pcmcuts.minRV0, pcmcuts.maxRV0); + fV0PhotonCut.SetAPRange(pcmcuts.maxAlphaAP, pcmcuts.maxQtAP); + fV0PhotonCut.RejectITSib(pcmcuts.rejectV0onITSib); + + // for track + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.minNClusterTPC); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.minNCrossedRowsTPC); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(pcmcuts.minNCrossedRowsOverFindableClustersTPC); + fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.maxFracSharedClustersTPC); + fV0PhotonCut.SetChi2PerClusterTPC(0.f, pcmcuts.macChi2TPC); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.minTPCNSigmaEl, pcmcuts.maxTPCNSigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(0.f, pcmcuts.macChi2ITS); + fV0PhotonCut.SetNClustersITS(pcmcuts.minNClusterITS, 7); + fV0PhotonCut.SetMeanClusterSizeITSob(pcmcuts.minMeanClusterSizeITSob, pcmcuts.maxMeanClusterSizeITSob); + fV0PhotonCut.SetDisableITSonly(pcmcuts.disableITSOnly); + fV0PhotonCut.SetDisableTPConly(pcmcuts.disableTPCOnly); + fV0PhotonCut.SetRequireITSTPC(pcmcuts.requireV0WithITSTPC); + fV0PhotonCut.SetRequireITSonly(pcmcuts.requireV0WithITSOnly); + fV0PhotonCut.SetRequireTPConly(pcmcuts.requireV0WithTPCOnly); + + fV0PhotonCut.setDoQA(pcmcuts.doQA.value); + } + + void init(InitContext&) + { + mRunNumber = 0; + dBz = 0; + + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + defineEMEventCut(); + defineEMCCut(); + fEMCCut.addQAHistograms(®istry); + definePCMCut(); + fV0PhotonCut.addQAHistograms(®istry); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(®istry); + + const AxisSpec thnAxisPtGen{thnConfigAxisPt, "#it{p}_{T,Gen} (GeV/#it{c})"}; + const AxisSpec thnAxisPtRec{thnConfigAxisPt, "#it{p}_{T,Rec} (GeV/#it{c})"}; + const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality (%)"}; + const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, "#it{M}_{#gamma#gamma} (GeV/#it{c}^{2})"}; + + const AxisSpec thnAxisEtaGen{280, -0.7, 0.7, "#it{#eta}_{Gen}"}; + const AxisSpec thnAxisEtaRec{280, -0.7, 0.7, "#it{#eta}_{Rec}"}; + + const AxisSpec thnAxisPhiGen{360, 0., o2::constants::math::TwoPI, "#it{#varphi}_{Gen} (rad)"}; + const AxisSpec thnAxisPhiRec{360, 0., o2::constants::math::TwoPI, "#it{#varphi}_{Rec} (rad)"}; + + registry.add("EMCal/hPhotonReso", "EMCal photon rec pT vs true pT vs cent", HistType::kTH3D, {thnAxisPtRec, thnAxisPtGen, thnAxisCent}); + registry.add("EMCal/hConvPhotonReso", "EMCal conversion photon rec pT vs true pT vs cent ", HistType::kTH3D, {thnAxisPtRec, thnAxisPtGen, thnAxisCent}); + + registry.add("EMCal/hPi0Reso", "EMCal pi0 rec pT vs true pT vs min vs cent ", HistType::kTHnSparseF, {thnAxisPtRec, thnAxisPtGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("EMCal/hEtaReso", "EMCal eta rec pT vs true pT vs min vs cent ", HistType::kTHnSparseF, {thnAxisPtRec, thnAxisPtGen, thnConfigAxisInvMass, thnAxisCent}); + + registry.add("EMCal/hPhotonResoEta", "EMCal photon rec eta vs true eta vs cent", HistType::kTH3D, {thnAxisEtaRec, thnAxisEtaGen, thnAxisCent}); + registry.add("EMCal/hConvPhotonResoEta", "EMCal conversion photon rec eta vs true eta vs cent ", HistType::kTH3D, {thnAxisEtaRec, thnAxisEtaGen, thnAxisCent}); + + registry.add("EMCal/hPi0ResoEta", "EMCal pi0 rec eta vs true eta vs min vs cent ", HistType::kTHnSparseF, {thnAxisEtaRec, thnAxisEtaGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("EMCal/hEtaResoEta", "EMCal eta rec eta vs true eta vs min vs cent ", HistType::kTHnSparseF, {thnAxisEtaRec, thnAxisEtaGen, thnConfigAxisInvMass, thnAxisCent}); + + registry.add("EMCal/hPhotonResoPhi", "EMCal photon rec phi vs true phi vs cent", HistType::kTH3D, {thnAxisPhiRec, thnAxisPhiGen, thnAxisCent}); + registry.add("EMCal/hConvPhotonResoPhi", "EMCal conversion photon rec phi vs true phi vs cent ", HistType::kTH3D, {thnAxisPhiRec, thnAxisPhiGen, thnAxisCent}); + + registry.add("EMCal/hPi0ResoPhi", "EMCal pi0 rec phi vs true phi vs min vs cent ", HistType::kTHnSparseF, {thnAxisPhiRec, thnAxisPhiGen, thnConfigAxisInvMass, thnAxisCent}); + registry.add("EMCal/hEtaResoPhi", "EMCal eta rec phi vs true phi vs min vs cent ", HistType::kTHnSparseF, {thnAxisPhiRec, thnAxisPhiGen, thnConfigAxisInvMass, thnAxisCent}); + + registry.add("PCM/hPhotonReso", "PCM photon rec pT vs true pT vs ", HistType::kTH3D, {thnAxisPtRec, thnAxisPtGen, thnAxisCent}); + + auto hMesonCuts = registry.add("hMesonCuts", "hMesonCuts;;Counts", kTH1D, {{6, 0.5, 6.5}}, false); + hMesonCuts->GetXaxis()->SetBinLabel(1, "in"); + hMesonCuts->GetXaxis()->SetBinLabel(2, "opening angle"); + hMesonCuts->GetXaxis()->SetBinLabel(3, "#it{M}_{#gamma#gamma}"); + hMesonCuts->GetXaxis()->SetBinLabel(4, "#it{p}_{T}"); + hMesonCuts->GetXaxis()->SetBinLabel(5, "conversion cut"); + hMesonCuts->GetXaxis()->SetBinLabel(6, "out"); + if (mesonConfig.cfgEnableQA.value) { + registry.add("mesonQA/hInvMassPt", "Histo for inv pair mass vs pt", HistType::kTH2D, {thnAxisInvMass, thnAxisPtRec}); + } + + fEMCalCorrectionFactor = std::make_unique("fEMCalCorrectionFactor", "(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); + fEMCalCorrectionFactor->SetParameters(-5.33426e-01, 1.40144e-02, -5.24434e-01); + }; // end init + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + auto run3GrpTimestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = nullptr; + o2::parameters::GRPMagField* grpmag = nullptr; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3GrpTimestamp); + if (grpo) { + // Fetch magnetic field from ccdb for current collision + dBz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3GrpTimestamp << " with magnetic field of " << dBz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3GrpTimestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3GrpTimestamp; + } + // Fetch magnetic field from ccdb for current collision + dBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3GrpTimestamp << " with magnetic field of " << dBz << " kZG"; + } + fV0PhotonCut.SetD_Bz(dBz); + mRunNumber = collision.runNumber(); + } + + /// Get the centrality + /// \param collision is the collision with the centrality information + template + float getCentrality(TCollision const& collision) + { + float cent = -999.; + switch (eventcuts.centEstimator) { + case CentralityEstimator::CFT0M: + cent = collision.centFT0M(); + break; + case CentralityEstimator::CFT0A: + cent = collision.centFT0A(); + break; + case CentralityEstimator::CFT0C: + cent = collision.centFT0C(); + break; + default: + LOG(warning) << "Centrality estimator not valid. Possible values are T0M, T0A, T0C. Fallback to T0C"; + cent = collision.centFT0C(); + break; + } + return cent; + } + + /// \brief check if standard event cuts + FT0 occupancy + centrality + QVec good is + /// \param collision collision that will be checked + /// \return true if collision survives all checks, otherwise false + template + bool isFullEventSelected(TCollision const& collision, bool fillHisto = false) + { + if (fillHisto) { + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(®istry, collision); + } + if (!(fEMEventCut.IsSelected(collision))) { + // general event selection + return false; + } + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + // occupancy selection + return false; + } + float cent = getCentrality(collision); + if (cent < eventcuts.cfgMinCent || cent > eventcuts.cfgMaxCent) { + // event selection + return false; + } + if (fillHisto) { + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(®istry, collision); + registry.fill(HIST("Event/before/hCollisionCounter"), 12.0); // accepted + registry.fill(HIST("Event/after/hCollisionCounter"), 12.0); // accepted + } + return true; + } + + // PCM-EMCal same event + void processPcmEmcal(Colls const& collisions, EMCalPhotons const& clusters, PcmPhotons const& photons, PcmMcLegs const& legs, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds, EMMCParticles const& mcParticles) + { + if (clusters.size() <= 0 && photons.size() < 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + EMBitFlags emcFlags(clusters.size()); + if (clusters.size() > 0) { + fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds, ®istry); + } + EMBitFlags v0flags(photons.size()); + if (photons.size() > 0) { + fV0PhotonCut.AreSelectedRunning(v0flags, photons, ®istry); + } + + // create iterators for photon mc particles + auto mcPhoton1 = mcParticles.begin(); + auto mcPhoton2 = mcParticles.begin(); + + // leg iterators for PCM + auto pos1 = legs.begin(); + auto ele1 = legs.begin(); + + // MC leg iterators for PCM + auto pos1mc = mcParticles.begin(); + auto ele1mc = mcParticles.begin(); + + for (const auto& collision : collisions) { + initCCDB(collision); + isFullEventSelected(collision, true); + + float cent = getCentrality(collision); + + auto photonsEMCPerCollision = clusters.sliceBy(perCollisionEMC, collision.globalIndex()); + auto photonsPCMPerCollision = photons.sliceBy(perCollisionPCM, collision.globalIndex()); + + for (const auto& photonEMC : photonsEMCPerCollision) { + if (!(emcFlags.test(photonEMC.globalIndex()))) { + continue; + } + if (photonEMC.emmcparticleIds().size() <= 0) { + // this is a cluster with just noise, skip + continue; + } + // we only want to look at the largest contribution + mcPhoton1.setCursor(photonEMC.emmcparticleIds()[0]); + + if (std::abs(mcPhoton1.pdgCode()) == PDG_t::kGamma) { + registry.fill(HIST("EMCal/hPhotonReso"), photonEMC.pt(), mcPhoton1.pt(), cent); + registry.fill(HIST("EMCal/hPhotonResoEta"), photonEMC.eta(), mcPhoton1.eta(), cent); + registry.fill(HIST("EMCal/hPhotonResoPhi"), photonEMC.phi(), mcPhoton1.phi(), cent); + } else if (std::abs(mcPhoton1.pdgCode()) == PDG_t::kElectron) { + if (!o2::aod::pwgem::photonmeson::utils::mcutil::isMotherPDG(mcPhoton1, PDG_t::kGamma)) { + continue; + } + registry.fill(HIST("EMCal/hConvPhotonReso"), photonEMC.pt(), mcPhoton1.pt(), cent); + registry.fill(HIST("EMCal/hConvPhotonResoEta"), photonEMC.eta(), mcPhoton1.eta(), cent); + registry.fill(HIST("EMCal/hConvPhotonResoPhi"), photonEMC.phi(), mcPhoton1.phi(), cent); + } + } + + for (const auto& photonPCM : photonsPCMPerCollision) { + if (!(v0flags.test(photonPCM.globalIndex()))) { + continue; + } + + pos1.setCursor(photonPCM.posTrackId()); + ele1.setCursor(photonPCM.negTrackId()); + + pos1mc.setCursor(pos1.emmcparticleId()); + ele1mc.setCursor(ele1.emmcparticleId()); + + const auto photonid1 = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcParticles); + + if (photonid1 < 0) { + continue; + } + + float trueConvRadius = std::hypot(ele1mc.vx(), ele1mc.vy()); + + mcPhoton1.setCursor(photonid1); + + if (!fV0PhotonCut.IsConversionPointInAcceptance(mcPhoton1, trueConvRadius)) { + continue; + } + + registry.fill(HIST("PCM/hPhotonReso"), photonPCM.pt(), mcPhoton1.pt(), cent); + + } // end of loop over pcm photons + + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photonsEMCPerCollision, photonsEMCPerCollision))) { + if (!(emcFlags.test(g1.globalIndex())) || !(emcFlags.test(g2.globalIndex()))) { + continue; + } + + if (correctionConfig.cfgEnableNonLin.value) { + energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); + } + if (correctionConfig.cfgEnableNonLin.value) { + energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); + } + + ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; + + float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); + + registry.fill(HIST("hMesonCuts"), 1); + if (openingAngle <= mesonConfig.minOpenAngle) { + registry.fill(HIST("hMesonCuts"), 2); + continue; + } + if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { + registry.fill(HIST("hMesonCuts"), 3); + continue; + } + if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { + registry.fill(HIST("hMesonCuts"), 4); + continue; + } + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), vMeson.Pt()); + } + + if (g1.emmcparticleIds().size() <= 0 || g2.emmcparticleIds().size() <= 0) { + // there is a cluster which is just noise, skip + continue; + } + + mcPhoton1.setCursor(g1.emmcparticleIds()[0]); + mcPhoton2.setCursor(g2.emmcparticleIds()[0]); + + int photonid1 = -1, photonid2 = -1, pi0id = -1, etaid = -1; + photonid1 = o2::aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(mcPhoton1, mcParticles, std::vector{111, 221}); + photonid2 = o2::aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(mcPhoton2, mcParticles, std::vector{111, 221}); + + if (photonid1 < 0 || photonid2 < 0) { + continue; + } + mcPhoton1.setCursor(photonid1); + mcPhoton2.setCursor(photonid2); + + pi0id = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(mcPhoton1, mcPhoton2, 22, 22, 111, mcParticles); + etaid = o2::aod::pwgem::dilepton::utils::mcutil::FindCommonMotherFrom2Prongs(mcPhoton1, mcPhoton2, 22, 22, 221, mcParticles); + + if (pi0id >= 0) { + const auto pi0mc = mcParticles.iteratorAt(pi0id); + registry.fill(HIST("EMCal/hPi0Reso"), vMeson.Pt(), pi0mc.pt(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hPi0ResoEta"), vMeson.Eta(), pi0mc.eta(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hPi0ResoPhi"), RecoDecay::constrainAngle(vMeson.Phi()), pi0mc.phi(), vMeson.M(), cent); + } + if (etaid >= 0) { + const auto etamc = mcParticles.iteratorAt(etaid); + registry.fill(HIST("EMCal/hEtaReso"), vMeson.Pt(), etamc.pt(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hEtaResoEta"), vMeson.Eta(), etamc.eta(), vMeson.M(), cent); + registry.fill(HIST("EMCal/hEtaResoPhi"), RecoDecay::constrainAngle(vMeson.Phi()), etamc.phi(), vMeson.M(), cent); + } + } + } + } + PROCESS_SWITCH(PhotonResoTask, processPcmEmcal, "Process for pcm and emcal photons", true); + +}; // End struct PhotonResoTask + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/PhotonMeson/Tasks/photonhbt.cxx b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx new file mode 100644 index 00000000000..43a37569823 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/photonhbt.cxx @@ -0,0 +1,2309 @@ +// 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 photonhbt.cxx +/// \brief V0 photon HBT analysis. +/// \author Daiki Sekihata, daiki.sekihata@cern.ch +/// Stefanie Mrozinski, stefanie.mrozinski@cern.ch + +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include // IWYU pragma: keep (do not replace with Math/Vector3Dfwd.h) +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// Single-photon track-type combo. +enum class V0Combo : int { + Inclusive = 0, + ItstpcItstpc = 1, + ItstpcTpconly = 2, + TpconlyTpconly = 3, +}; + +/// Photon-pair track-type combo. +enum class PairCombo : int { + Inclusive = 0, + IiXIi = 1, + IiXIt = 2, + IiXTt = 3, + ItXIt = 4, + ItXTt = 5, + TtXTt = 6, +}; + +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; + +// EMMCEventLabels needed for processMC truth-efficiency loop +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +// ─── MC truth classification types ──────────────────────────────────────────── + +struct PhotonMCInfo { + bool hasMC = false; + bool sameMother = false; + bool isTruePhoton = false; + int mcPosId = -1; + int mcNegId = -1; + int motherId = -1; + int motherPdg = 0; + bool isPhysicalPrimary = false; +}; + +enum class PairTruthType : uint8_t { + Unknown = 0, + TrueTrueDistinct, + TrueTrueSamePhoton, + SharedMcLeg, + TrueFake, + FakeFake, + Pi0Daughters, +}; + +static constexpr float kMinMagnitude = 1e-12f; +static constexpr float kMinCosine = 1e-12f; +static constexpr float kMinSigma = 1e-9; + +struct Photonhbt { + + template + static inline V0Combo classifyV0Combo(TGamma const& g) + { + const auto pos = g.template posTrack_as(); + const auto neg = g.template negTrack_as(); + const bool posII = pos.hasITS() && pos.hasTPC(); + const bool posTPC = !pos.hasITS() && pos.hasTPC(); + const bool negII = neg.hasITS() && neg.hasTPC(); + const bool negTPC = !neg.hasITS() && neg.hasTPC(); + if (posII && negII) + return V0Combo::ItstpcItstpc; + if ((posII && negTPC) || (posTPC && negII)) + return V0Combo::ItstpcTpconly; + if (posTPC && negTPC) + return V0Combo::TpconlyTpconly; + return V0Combo::Inclusive; + } + + static inline PairCombo classifyPairCombo(V0Combo c1, V0Combo c2) + { + const int i1 = static_cast(c1); + const int i2 = static_cast(c2); + if (i1 <= 0 || i2 <= 0) + return PairCombo::Inclusive; + const int lo = std::min(i1, i2); + const int hi = std::max(i1, i2); + static constexpr std::array, 4> kTable = { + {{0, 0, 0, 0}, {0, 1, 2, 3}, {0, 2, 4, 5}, {0, 3, 5, 6}}}; + return static_cast(kTable[lo][hi]); + } + + // ─── Configurables ──────────────────────────────────────────────────────── + + ConfigurableAxis confQBins{"confQBins", {60, 0, +0.3f}, "q bins for output histograms"}; + ConfigurableAxis confKtBins{"confKtBins", {VARIABLE_WIDTH, 0.0, 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}, "kT bins"}; + ConfigurableAxis confPtBins{"confPtBins", {100, 0.f, 2.f}, "pT bins (GeV/c)"}; + ConfigurableAxis confEtaBins{"confEtaBins", {80, -0.8f, 0.8f}, "eta bins"}; + ConfigurableAxis confPhiBins{"confPhiBins", {90, 0.f, o2::constants::math::TwoPI}, "phi bins (rad)"}; + ConfigurableAxis confDeltaEtaBins{"confDeltaEtaBins", {180, -1.6f, +1.6f}, "Delta-eta bins"}; + ConfigurableAxis confDeltaPhiBins{"confDeltaPhiBins", {180, -o2::constants::math::PI, o2::constants::math::PI}, "Delta-phi bins (rad)"}; + ConfigurableAxis confEllipseValBins{"confEllipseValBins", {200, 0.f, 10.f}, "ellipse value bins"}; + ConfigurableAxis confCosThetaBins{"confCosThetaBins", {100, 0.f, 1.f}, "cos(theta*) bins"}; + ConfigurableAxis confOpeningAngleBins{"confOpeningAngleBins", {100, 0.f, o2::constants::math::PI}, "opening angle bins (rad)"}; + ConfigurableAxis confRBins{"confRBins", {100, 0.f, 100.f}, "conversion radius bins (cm)"}; + ConfigurableAxis confDeltaRBins{"confDeltaRBins", {120, 0.f, 30.f}, "|R1-R2| bins (cm)"}; + ConfigurableAxis confDeltaR3DBins{"confDeltaR3DBins", {100, 0.f, 100.f}, "3D distance between conversion points (cm)"}; + ConfigurableAxis confDeltaRxyBins{"confDeltaRxyBins", {100, 0.f, 100.f}, "xy distance between conversion points (cm)"}; + ConfigurableAxis confZConvBins{"confZConvBins", {200, -100.f, 100.f}, "conversion z (cm)"}; + ConfigurableAxis confDeltaZBins{"confDeltaZBins", {200, -100.f, 100.f}, "#Deltaz bins (cm)"}; + ConfigurableAxis confOccupancyQA{"confOccupancyQA", {100, 0.f, 50000.f}, "occupancy"}; + ConfigurableAxis confCentQABins{"confCentQABins", {110, 0.f, 110.f}, "centrality (%)"}; + + // ─── Axis specs ──────────────────────────────────────────────────────────── + + const AxisSpec axisKt{confKtBins, "k_{T} (GeV/c)"}; + const AxisSpec axisQinv{confQBins, "q_{inv} (GeV/c)"}; + const AxisSpec axisQabsLcms{confQBins, "|#bf{q}|^{LCMS} (GeV/c)"}; + const AxisSpec axisQout{confQBins, "q_{out} (GeV/c)"}; + const AxisSpec axisQside{confQBins, "q_{side} (GeV/c)"}; + const AxisSpec axisQlong{confQBins, "q_{long} (GeV/c)"}; + const AxisSpec axisPt{confPtBins, "p_{T} (GeV/c)"}; + const AxisSpec axisEta{confEtaBins, "#eta"}; + const AxisSpec axisPhi{confPhiBins, "#phi (rad)"}; + const AxisSpec axisDeltaEta{confDeltaEtaBins, "#Delta#eta"}; + const AxisSpec axisDeltaPhi{confDeltaPhiBins, "#Delta#phi (rad)"}; + const AxisSpec axisEllipseVal{confEllipseValBins, "(#Delta#eta/#sigma_{#eta})^{2}+(#Delta#phi/#sigma_{#phi})^{2}"}; + const AxisSpec axisCosTheta{confCosThetaBins, "cos(#theta*)"}; + const AxisSpec axisOpeningAngle{confOpeningAngleBins, "Opening angle (rad)"}; + const AxisSpec axisR{confRBins, "R_{conv} (cm)"}; + const AxisSpec axisDeltaR{confDeltaRBins, "|R_{1}-R_{2}| (cm)"}; + const AxisSpec axisDeltaR3D{confDeltaR3DBins, "|#vec{r}_{1}-#vec{r}_{2}| (cm)"}; + const AxisSpec axisDeltaRxy{confDeltaRxyBins, "#Delta r_{xy} (cm)"}; + const AxisSpec axisZConv{confZConvBins, "z_{conv} (cm)"}; + const AxisSpec axisDeltaZ{confDeltaZBins, "#Delta z (cm)"}; + const AxisSpec axisOccupancy{confOccupancyQA, "occupancy"}; + const AxisSpec axisCentQA{confCentQABins, "centrality (%)"}; + + // ─── Configurables: QA flags ─────────────────────────────────────────────── + + struct : ConfigurableGroup { + std::string prefix = "qaflags_group"; + Configurable doPairQa{"doPairQa", true, "fill pair QA histograms at each cut step"}; + Configurable doSinglePhotonQa{"doSinglePhotonQa", true, "fill single-photon QA histograms (pT, eta, phi)"}; + Configurable cfgMaxQinvForQA{"cfgMaxQinvForQA", 0.1f, "fill per-step pair QA histograms only when q_inv < this value. Set <= 0 to disable."}; + Configurable cfgMaxQinvForFullRange{"cfgMaxQinvForFullRange", 0.3f, "fill full-range histograms only when q_inv < this value. Set <= 0 to disable."}; + Configurable cfgMaxQinvForMCQA{"cfgMaxQinvForMCQA", 0.3f, + "fill MC truth 1D histograms (hQinv, hKt, hDeltaEta, ...) only when q_inv < this value. " + "hDEtaDPhi is always filled (needs full sample). Set <= 0 to disable. Default 0.6 cuts " + "most combinatorics while covering well beyond the CF range for systematics."}; + } qaflags; + + // ─── HBT analysis mode ─────────────────────────────────────────────────────────── + struct : ConfigurableGroup { + std::string prefix = "hbtanalysis_group"; + Configurable cfgDo3D{"cfgDo3D", false, "enable 3D (qout,qside,qlong) analysis"}; + Configurable cfgDo2D{"cfgDo2D", false, "enable 2D (qout,qinv) projection (requires cfgDo3D)"}; + Configurable cfgUseLCMS{"cfgUseLCMS", false, "measure 1D relative momentum in LCMS"}; + } hbtanalysis; + + // ─── Event mixing ───────────────────────────────────────────────────────────── + struct : ConfigurableGroup { + std::string prefix = "mixing_group"; + Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; + Configurable ndepth{"ndepth", 100, "depth for event mixing"}; + Configurable ndiffBCMix{"ndiffBCMix", 594, "difference in global BC required for mixed events"}; + Configurable cfgEP2EstimatorForMix{"cfgEP2EstimatorForMix", 3, "FT0M:0, FT0A:1, FT0C:2, FV0A:3, BTot:4, BPos:5, BNeg:6"}; + Configurable cfgOccupancyEstimator{"cfgOccupancyEstimator", 0, "FT0C:0, Track:1"}; + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + + ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.f, -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.f, 5.f, 10.f, 20.f, 30.f, 40.f, 50.f, 60.f, 70.f, 80.f, 90.f, 100.f, 999.f}, "Mixing bins - centrality"}; + ConfigurableAxis confEPBinsBins{"confEPBinsBins", {16, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}, "Mixing bins - EP angle"}; + ConfigurableAxis confOccupancyBins{"confOccupancyBins", {VARIABLE_WIDTH, -1, 1e+10}, "Mixing bins - occupancy"}; + } mixing; + + // ─── Centrality slection ───────────────────────────────────────────────── + struct : ConfigurableGroup { + std::string prefix = "centralitySelection_group"; + Configurable cfgCentMin{"cfgCentMin", -1, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; + } centralitySelection; + + struct : ConfigurableGroup { + std::string prefix = "mctruth_group"; + Configurable cfgMCMaxQinv{"cfgMCMaxQinv", 0.3f, "..."}; + Configurable cfgMCMinKt{"cfgMCMinKt", 0.0f, "..."}; + Configurable cfgMCMaxKt{"cfgMCMaxKt", 0.7f, "..."}; + Configurable cfgDoTruthMix{"cfgDoTruthMix", false, "..."}; + Configurable cfgTruthMixDepth{"cfgTruthMixDepth", 10, "..."}; + Configurable cfgMCMinV0Pt{"cfgMCMinV0Pt", 0.1f, + "min pT for true photons in truth-efficiency loop (GeV/c); " + "0 = fall back to pcmcuts.cfgMinPtV0"}; + Configurable cfgMCMinLegPt{"cfgMCMinLegPt", 0.0f, "min pT for true e^{+}/e^{-} legs in truth-efficiency loop (GeV/c);"}; + } mctruth; + + struct : ConfigurableGroup { + std::string prefix = "mctruthSparse_group"; + Configurable cfgFillDEtaDPhiVsQinvTrueTrueDistinct{"cfgFillDEtaDPhiVsQinvTrueTrueDistinct", true, "fill hDEtaDPhiVsQinv for TrueTrueDistinct pairs"}; + Configurable cfgFillDEtaDPhiVsQinvTrueTrueSamePhoton{"cfgFillDEtaDPhiVsQinvTrueTrueSamePhoton", false, "fill hDEtaDPhiVsQinv for TrueTrueSamePhoton pairs"}; + Configurable cfgFillDEtaDPhiVsQinvSharedMcLeg{"cfgFillDEtaDPhiVsQinvSharedMcLeg", false, "fill hDEtaDPhiVsQinv for SharedMcLeg pairs"}; + Configurable cfgFillDEtaDPhiVsQinvTrueFake{"cfgFillDEtaDPhiVsQinvTrueFake", false, "fill hDEtaDPhiVsQinv for TrueFake pairs"}; + Configurable cfgFillDEtaDPhiVsQinvFakeFake{"cfgFillDEtaDPhiVsQinvFakeFake", true, "fill hDEtaDPhiVsQinv for FakeFake pairs"}; + Configurable cfgFillDEtaDPhiVsQinvPi0Daughters{"cfgFillDEtaDPhiVsQinvPi0Daughters", false, "fill hDEtaDPhiVsQinv for Pi0Daughters pairs"}; + Configurable cfgFillDRDZQinvTrueTrueDistinct{"cfgFillDRDZQinvTrueTrueDistinct", true, "fill hSparseDeltaRDeltaZQinv for TrueTrueDistinct pairs"}; + Configurable cfgFillDRDZQinvTrueTrueSamePhoton{"cfgFillDRDZQinvTrueTrueSamePhoton", false, "fill hSparseDeltaRDeltaZQinv for TrueTrueSamePhoton pairs"}; + Configurable cfgFillDRDZQinvSharedMcLeg{"cfgFillDRDZQinvSharedMcLeg", false, "fill hSparseDeltaRDeltaZQinv for SharedMcLeg pairs"}; + Configurable cfgFillDRDZQinvTrueFake{"cfgFillDRDZQinvTrueFake", false, "fill hSparseDeltaRDeltaZQinv for TrueFake pairs"}; + Configurable cfgFillDRDZQinvFakeFake{"cfgFillDRDZQinvFakeFake", true, "fill hSparseDeltaRDeltaZQinv for FakeFake pairs"}; + Configurable cfgFillDRDZQinvPi0Daughters{"cfgFillDRDZQinvPi0Daughters", false, "fill hSparseDeltaRDeltaZQinv for Pi0Daughters pairs"}; + } mctruthSparse; + + struct : ConfigurableGroup { + std::string prefix = "ggpaircut_group"; + Configurable cfgMinDRCosOA{"cfgMinDRCosOA", -1.f, "min. dr/cosOA; <0 = disabled"}; + Configurable cfgDoRCut{"cfgDoRCut", false, "apply |R1-R2| > cfgMinDeltaR cut"}; + Configurable cfgMinDeltaR{"cfgMinDeltaR", 0.f, "minimum |R1-R2| (cm)"}; + Configurable cfgDoZCut{"cfgDoZCut", false, "apply |DeltaZ| > cfgMinDeltaZ cut"}; + Configurable cfgMinDeltaZ{"cfgMinDeltaZ", 0.f, "minimum |DeltaZ| (cm)"}; + Configurable cfgDoEllipseCut{"cfgDoEllipseCut", false, "reject pairs inside ellipse in DeltaEta-DeltaPhi"}; + Configurable cfgEllipseSigEta{"cfgEllipseSigEta", 0.02f, "sigma_eta for ellipse cut"}; + Configurable cfgEllipseSigPhi{"cfgEllipseSigPhi", 0.02f, "sigma_phi for ellipse cut"}; + Configurable cfgEllipseR2{"cfgEllipseR2", 1.0f, "R^2 threshold: reject if ellipse value < R^2"}; + Configurable cfgMaxAsymmetry{"cfgMaxAsymmetry", -1.f, "max |p_{T, 1} - p_{T, 2}|/(p_{T, 1} + p_{T, 2}) asymmetry cut"}; + } ggpaircuts; + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", +10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require no TF border"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS ROF border"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx FT0 vs PV"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2.f, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000.f, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "no coll in time range std"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "no coll in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "no coll in ITS ROF std"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "no coll in ITS ROF strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "no HM coll in prev ROF"}; + Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "ITS layer 3 OK"}; + Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "ITS layers 0-3 OK"}; + Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "all ITS layers OK"}; + } eventcuts; + + V0PhotonCut fV0PhotonCut; + struct : ConfigurableGroup { + std::string prefix = "pcmcut_group"; + Configurable cfgRequireV0WithITSTPC{"cfgRequireV0WithITSTPC", false, "select V0s with ITS-TPC tracks"}; + Configurable cfgRequireV0WithITSOnly{"cfgRequireV0WithITSOnly", false, "select V0s with ITS-only tracks"}; + Configurable cfgRequireV0WithTPCOnly{"cfgRequireV0WithTPCOnly", false, "select V0s with TPC-only tracks"}; + Configurable cfgMinPtV0{"cfgMinPtV0", 0.1, "min pT for V0 photons at PV"}; + Configurable cfgMaxEtaV0{"cfgMaxEtaV0", 0.8, "max eta for V0 photons at PV"}; + Configurable cfgMinV0Radius{"cfgMinV0Radius", 16.0, "min V0 radius"}; + Configurable cfgMaxV0Radius{"cfgMaxV0Radius", 90.0, "max V0 radius"}; + Configurable cfgMaxAlphaAP{"cfgMaxAlphaAP", 0.95, "max alpha for AP cut"}; + Configurable cfgMaxQtAP{"cfgMaxQtAP", 0.01, "max qT for AP cut"}; + Configurable cfgMinCosPA{"cfgMinCosPA", 0.997, "min V0 CosPA"}; + Configurable cfgMaxPCA{"cfgMaxPCA", 3.0, "max distance between 2 legs"}; + Configurable cfgMaxChi2KF{"cfgMaxChi2KF", 1e+10, "max chi2/ndf with KF"}; + Configurable cfgRejectV0OnITSIB{"cfgRejectV0OnITSIB", true, "reject V0s on ITSib"}; + Configurable cfgDisableITSOnlyTrack{"cfgDisableITSOnlyTrack", false, "disable ITS-only tracks"}; + Configurable cfgDisableTPCOnlyTrack{"cfgDisableTPCOnlyTrack", false, "disable TPC-only tracks"}; + Configurable cfgMinNClusterTPC{"cfgMinNClusterTPC", 70, "min ncluster TPC"}; + Configurable cfgMinNCrossedRows{"cfgMinNCrossedRows", 70, "min crossed rows"}; + Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared TPC clusters"}; + Configurable cfgMaxChi2TPC{"cfgMaxChi2TPC", 4.0, "max chi2/NclsTPC"}; + Configurable cfgMaxChi2ITS{"cfgMaxChi2ITS", 36.0, "max chi2/NclsITS"}; + Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -3.5, "min TPC nsigma electron"}; + Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.5, "max TPC nsigma electron"}; + } pcmcuts; + + ~Photonhbt() + { + delete emh1; + emh1 = nullptr; + delete emh2; + emh2 = nullptr; + mapMixedEventIdToGlobalBC.clear(); + usedPhotonIdsPerCol.clear(); + truthGammaPool.clear(); + } + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + HistogramRegistry fRegistryPairQA{"outputPairQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + HistogramRegistry fRegistryPairMC{"outputPairMC", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + HistogramRegistry fRegistryMC{"outputMC", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::string_view event_pair_types[2] = {"same/", "mix/"}; + + std::mt19937 engine; + std::uniform_int_distribution dist01; + int mRunNumber{0}; + + std::vector ztxBinEdges; + std::vector centBinEdges; + std::vector epBinEgdes; + std::vector occBinEdges; + + inline bool isInsideEllipse(float deta, float dphi) const + { + if (!ggpaircuts.cfgDoEllipseCut.value) + return false; + const float sE = ggpaircuts.cfgEllipseSigEta.value; + const float sP = ggpaircuts.cfgEllipseSigPhi.value; + if (sE < kMinSigma || sP < kMinSigma) + return false; + return (deta / sE) * (deta / sE) + (dphi / sP) * (dphi / sP) < ggpaircuts.cfgEllipseR2.value; + } + + inline bool passRZCut(float deltaR, float deltaZ) const + { + if (ggpaircuts.cfgDoRCut.value && deltaR < ggpaircuts.cfgMinDeltaR.value) + return false; + if (ggpaircuts.cfgDoZCut.value && std::fabs(deltaZ) < ggpaircuts.cfgMinDeltaZ.value) + return false; + return true; + } + + inline bool passAsymmetryCut(float pt1, float pt2) const + { + if (ggpaircuts.cfgMaxAsymmetry.value < 0.f) { + return true; + } + + const float sum = pt1 + pt2; + if (sum < kMinSigma) { + return false; + } + return std::fabs(pt1 - pt2) / sum < ggpaircuts.cfgMaxAsymmetry.value; + } + + inline bool passQinvQAGate(float qinv) const + { + const float limit = qaflags.cfgMaxQinvForQA.value; + return (limit <= 0.f) || (qinv < limit); + } + + inline bool passQinvFullRangeGate(float qinv) const + { + const float limit = qaflags.cfgMaxQinvForFullRange.value; + return (limit <= 0.f) || (qinv < limit); + } + + inline bool passQinvMCQAGate(float qinv) const + { + const float limit = qaflags.cfgMaxQinvForMCQA.value; + return (limit <= 0.f) || (qinv < limit); + } + + static inline float computeCosTheta(const ROOT::Math::PtEtaPhiMVector& v1, + const ROOT::Math::PtEtaPhiMVector& v2) + { + ROOT::Math::PxPyPzEVector p1(v1), p2(v2); + ROOT::Math::PxPyPzEVector pair = p1 + p2; + ROOT::Math::Boost boost(-pair.BoostToCM()); + ROOT::Math::PxPyPzEVector p1cm = boost(p1); + ROOT::Math::XYZVector pairDir(pair.Px(), pair.Py(), pair.Pz()); + ROOT::Math::XYZVector p1cmDir(p1cm.Px(), p1cm.Py(), p1cm.Pz()); + if (pairDir.R() < kMinSigma || p1cmDir.R() < kMinSigma) + return -1.f; + return static_cast(pairDir.Unit().Dot(p1cmDir.Unit())); + } + + static void parseBins(const ConfigurableAxis& cfg, std::vector& edges) + { + if (cfg.value[0] == VARIABLE_WIDTH) { + edges = std::vector(cfg.value.begin(), cfg.value.end()); + edges.erase(edges.begin()); + } else { + const int n = static_cast(cfg.value[0]); + const float xmin = static_cast(cfg.value[1]); + const float xmax = static_cast(cfg.value[2]); + edges.resize(n + 1); + for (int i = 0; i <= n; ++i) + edges[i] = xmin + (xmax - xmin) / n * i; + } + } + + static int clampBin(int b, int nmax) { return std::clamp(b, 0, nmax); } + + static int binOf(const std::vector& edges, float val) + { + const int b = static_cast( + std::lower_bound(edges.begin(), edges.end(), val) - edges.begin()) - + 1; + return clampBin(b, static_cast(edges.size()) - 2); // + } + + template + static constexpr const char* qaPrefix() + { + if constexpr (ev_id == 0) { + if constexpr (step_id == 0) + return "Pair/same/QA/Before/"; + if constexpr (step_id == 1) + return "Pair/same/QA/AfterDRCosOA/"; + if constexpr (step_id == 2) // o2-linter: disable=magic-number (just counting the step of a cut) + return "Pair/same/QA/AfterRZ/"; + return "Pair/same/QA/AfterEllipse/"; + } else { + if constexpr (step_id == 0) + return "Pair/mix/QA/Before/"; + if constexpr (step_id == 1) + return "Pair/mix/QA/AfterDRCosOA/"; + if constexpr (step_id == 2) // o2-linter: disable=magic-number (just counting the step of a cut) + return "Pair/mix/QA/AfterRZ/"; + return "Pair/mix/QA/AfterEllipse/"; + } + } + + template + static constexpr const char* fullRangePrefix() + { + if constexpr (ev_id == 0) + return "Pair/same/FullRange/"; + return "Pair/mix/FullRange/"; + } + + void init(InitContext& /*context*/) + { + mRunNumber = 0; + parseBins(mixing.confVtxBins, ztxBinEdges); + parseBins(mixing.confCentBins, centBinEdges); + parseBins(mixing.confEPBinsBins, epBinEgdes); + parseBins(mixing.confOccupancyBins, occBinEdges); + emh1 = new MyEMH(mixing.ndepth); + emh2 = new MyEMH(mixing.ndepth); + o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(&fRegistry); + DefineEMEventCut(); + DefinePCMCut(); + addhistograms(); + std::random_device seedGen; + engine = std::mt19937(seedGen()); + dist01 = std::uniform_int_distribution(0, 1); + fRegistry.add("Pair/mix/hDiffBC", + "diff. global BC in mixed event;|BC_{current}-BC_{mixed}|", + kTH1D, {{10001, -0.5, 10000.5}}, true); + + // Print histogram counts and memory estimates for all registries + // LOGF(info, "=== photonhbt histogram summary ==="); + // fRegistry.print(); + // fRegistryPairQA.print(); + // fRegistryPairMC.print(); + // fRegistryMC.print(); + // LOGF(info, "==================================="); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) + return; + mRunNumber = collision.runNumber(); + } + + struct PairQAObservables { + ROOT::Math::PtEtaPhiMVector v1, v2, k12; + float x1 = 0.f, y1 = 0.f, z1 = 0.f, x2 = 0.f, y2 = 0.f, z2 = 0.f; + float r1 = 0.f, r2 = 0.f, dx = 0.f, dy = 0.f, dz = 0.f; + float deltaR = 0.f, deltaZ = 0.f, deltaRxy = 0.f, deltaR3D = 0.f; + float opa = 0.f, cosOA = 0.f, drOverCosOA = 0.f; + float deta = 0.f, dphi = 0.f, pairEta = 0.f, pairPhi = 0.f; + float kt = 0.f, qinv = 0.f, cosTheta = 0.f, openingAngle = 0.f; + bool valid = true; + }; + + struct TruthGamma { + int id = -1, posId = -1, negId = -1; + float eta = 0.f, phi = 0.f, pt = 0.f; + float rTrue = -1.f; + float legDRtrue = -1.f; + float legDEta = 0.f; // ← neu + float legDPhi = 0.f; // ← neu + float alphaTrue = 0.f; + }; + + std::map, std::deque>> truthGammaPool; + + void addSinglePhotonQAHistogramsForStep(const std::string& path) + { + fRegistryPairQA.add((path + "hEtaVsPhiPt").c_str(), "acceptance;#phi (rad);#eta", kTH3D, {axisPhi, axisEta, axisPt}, true); + fRegistryPairQA.add((path + "hRVsZConvPt").c_str(), "R_{conv} vs z_{conv};z_{conv} (cm);R_{conv} (cm)", kTH3D, {axisZConv, axisR, axisPt}, true); + } + + void addFullRangeHistograms(const std::string& path) + { + fRegistry.add((path + "hDeltaRVsQinv").c_str(), "|R_{1}-R_{2}| vs q_{inv};q_{inv} (GeV/c);|R_{1}-R_{2}| (cm)", kTH2D, {axisQinv, axisDeltaR}, true); + fRegistry.add((path + "hDeltaZVsQinv").c_str(), "#Delta z vs q_{inv};q_{inv} (GeV/c);#Delta z (cm)", kTH2D, {axisQinv, axisDeltaZ}, true); + fRegistry.add((path + "hDeltaR3DVsQinv").c_str(), "#Delta r_{3D} vs q_{inv};q_{inv} (GeV/c);#Delta r_{3D} (cm)", kTH2D, {axisQinv, axisDeltaR3D}, true); + fRegistry.add((path + "hQinvVsCent").c_str(), "q_{inv} vs centrality;centrality (%);q_{inv} (GeV/c)", kTH2D, {axisCentQA, axisQinv}, true); + fRegistry.add((path + "hQinvVsOccupancy").c_str(), "q_{inv} vs occupancy;occupancy;q_{inv} (GeV/c)", kTH2D, {axisOccupancy, axisQinv}, true); + fRegistry.add((path + "hSparseDeltaRDeltaZQinv").c_str(), "|R_{1}-R_{2}|,#Delta z,q_{inv}", kTHnSparseD, {axisDeltaR, axisDeltaZ, axisQinv}, true); + fRegistry.add((path + "hDeltaRCosOAVsQinv").c_str(), "#Delta r/cos(#theta_{op}/2) vs q_{inv};q_{inv} (GeV/c);#Delta r/cos(#theta_{op}/2) (cm)", kTH2D, {axisQinv, {100, 0, 100}}, true); + } + + template + inline void fillFullRangeQA(PairQAObservables const& obs, float cent, float occupancy) + { + constexpr auto base = fullRangePrefix(); + fRegistry.fill(HIST(base) + HIST("hDeltaRVsQinv"), obs.qinv, obs.deltaR); + fRegistry.fill(HIST(base) + HIST("hDeltaZVsQinv"), obs.qinv, obs.deltaZ); + fRegistry.fill(HIST(base) + HIST("hDeltaR3DVsQinv"), obs.qinv, obs.deltaR3D); + fRegistry.fill(HIST(base) + HIST("hQinvVsCent"), cent, obs.qinv); + fRegistry.fill(HIST(base) + HIST("hQinvVsOccupancy"), occupancy, obs.qinv); + fRegistry.fill(HIST(base) + HIST("hSparseDeltaRDeltaZQinv"), obs.deltaR, obs.deltaZ, obs.qinv); + } + + template + inline void fillFullRangeDeltaRCosOA(float qinv, float drOverCosOA) + { + constexpr auto base = fullRangePrefix(); + fRegistry.fill(HIST(base) + HIST("hDeltaRCosOAVsQinv"), qinv, drOverCosOA); + } + void addQAHistogramsForStep(const std::string& path) + { + // Ellipse + fRegistryPairQA.add((path + "hEllipseVal").c_str(), "(#Delta#eta/#sigma)^{2}+(#Delta#phi/#sigma)^{2};value;counts", kTH1D, {axisEllipseVal}, true); + + // Conversion point + fRegistryPairQA.add((path + "hR1VsR2").c_str(), "R_{1} vs R_{2};R_{1} (cm);R_{2} (cm)", kTH2D, {axisR, axisR}, true); + fRegistryPairQA.add((path + "hDeltaRxyKt").c_str(), "#Delta r_{xy} vs k_{T};#Delta r_{xy} (cm);k_{T} (GeV/c)", kTH2D, {axisDeltaRxy, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaR3DKt").c_str(), "#Delta r_{3D} vs k_{T};#Delta r_{3D} (cm);k_{T} (GeV/c)", kTH2D, {axisDeltaR3D, axisKt}, true); + + // Delta Eta QA + fRegistryPairQA.add((path + "hDeltaEtaDeltaRKt").c_str(), "#Delta#eta,|R_{1}-R_{2}|,k_{T}", kTHnSparseD, {axisDeltaEta, axisDeltaR, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaEtaDeltaZKt").c_str(), "#Delta#eta,#Delta z,k_{T}", kTHnSparseD, {axisDeltaEta, axisDeltaZ, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaEtaEtaKt").c_str(), "#Delta#eta,#eta_{pair},k_{T}", kTHnSparseD, {axisDeltaEta, axisEta, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaEtaPhiKt").c_str(), "#Delta#eta,#phi_{pair},k_{T}", kTHnSparseD, {axisDeltaEta, axisPhi, axisKt}, true); + + // Delta Phi QA + fRegistryPairQA.add((path + "hSparseDEtaDPhiKt").c_str(), "#Delta#eta,#Delta#phi,k_{T}", kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaPhiDeltaRKt").c_str(), "#Delta#phi,|R_{1}-R_{2}|,k_{T}", kTHnSparseD, {axisDeltaPhi, axisDeltaR, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaPhiDeltaZKt").c_str(), "#Delta#phi,#Delta z,k_{T}", kTHnSparseD, {axisDeltaPhi, axisDeltaZ, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaPhiPhiKt").c_str(), "#Delta#phi,#phi_{pair},k_{T}", kTHnSparseD, {axisDeltaPhi, axisPhi, axisKt}, true); + fRegistryPairQA.add((path + "hDeltaPhiEtaKt").c_str(), "#Delta#phi,#eta_{pair},k_{T}", kTHnSparseD, {axisDeltaPhi, axisEta, axisKt}, true); + + // Delta Eta Delta Phi Diagnostics + fRegistryPairQA.add((path + "hPhiVsEtaKt").c_str(), "#phi_{pair},#eta_{pair},k_{T}", kTHnSparseD, {axisPhi, axisEta, axisKt}, true); + fRegistryPairQA.add((path + "hSparseDeltaRDeltaZKt").c_str(), "|R_{1}-R_{2}|,#Delta z,k_{T}", kTHnSparseD, {axisDeltaR, axisDeltaZ, axisKt}, true); + } + + void addhistograms() + { + static constexpr std::string_view det[6] = {"FT0M", "FT0A", "FT0C", "BTot", "BPos", "BNeg"}; + fRegistry.add("Event/before/hEP2_CentFT0C_forMix", + Form("2nd harmonics EP for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", det[mixing.cfgEP2EstimatorForMix].data()), + kTH2D, {{110, 0, 110}, {180, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); + fRegistry.add("Event/after/hEP2_CentFT0C_forMix", + Form("2nd harmonics EP for mix;centrality FT0C (%%);#Psi_{2}^{%s} (rad.)", det[mixing.cfgEP2EstimatorForMix].data()), + kTH2D, {{110, 0, 110}, {180, -o2::constants::math::PIHalf, +o2::constants::math::PIHalf}}, false); + + addSinglePhotonQAHistogramsForStep("SinglePhoton/Before/"); + addSinglePhotonQAHistogramsForStep("SinglePhoton/AfterDRCosOA/"); + addSinglePhotonQAHistogramsForStep("SinglePhoton/AfterRZ/"); + addSinglePhotonQAHistogramsForStep("SinglePhoton/AfterEllipse/"); + + if (hbtanalysis.cfgDo3D) { + fRegistry.add("Pair/same/CF_3D", "diphoton correlation 3D LCMS", kTHnSparseD, {axisQout, axisQside, axisQlong, axisKt}, true); + if (hbtanalysis.cfgDo2D) + fRegistry.add("Pair/same/CF_2D", "diphoton correlation 2D (qout,qinv)", kTHnSparseD, {axisQout, axisQinv, axisKt}, true); + } else { + if (hbtanalysis.cfgUseLCMS) + fRegistry.add("Pair/same/CF_1D", "diphoton correlation 1D LCMS", kTH2D, {axisQabsLcms, axisKt}, true); + else + fRegistry.add("Pair/same/CF_1D", "diphoton correlation 1D (qinv)", kTH2D, {axisQinv, axisKt}, true); + } + + fRegistry.add("Pair/same/hDeltaRCosOA", "distance between 2 conversion points / cos(#theta_{op}/2);#Delta r / cos(#theta_{op}/2) (cm);counts", kTH1D, {{100, 0, 100}}, true); + fRegistry.add("Pair/same/hSparse_DEtaDPhi_kT", + "same-event (#Delta#eta,#Delta#phi,q_{inv},k_{T}) for efficiency reweighting;" + "#Delta#eta;#Delta#phi (rad);q_{inv} (GeV/c);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + + fRegistry.add("Pair/same/hPhi_lowerPtV0", "azimuthal angle of lower-p_{T} V0 in pair;#phi (rad);counts", kTH1D, {axisPhi}, true); + fRegistry.add("Pair/same/hSparse_DEtaDPhi_qinv_kT", "azimuthal angle of lower-p_{T} V0 in pair;#phi (rad);counts", kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisQinv, axisKt}, true); + + addQAHistogramsForStep("Pair/same/QA/Before/"); + addQAHistogramsForStep("Pair/same/QA/AfterDRCosOA/"); + addQAHistogramsForStep("Pair/same/QA/AfterRZ/"); + addQAHistogramsForStep("Pair/same/QA/AfterEllipse/"); + + addMCHistograms(); + fRegistryPairQA.addClone("Pair/same/QA/", "Pair/mix/QA/"); + fRegistryPairMC.addClone("Pair/same/MC/", "Pair/mix/MC/"); + addFullRangeHistograms("Pair/same/FullRange/"); + fRegistry.addClone("Pair/same/", "Pair/mix/"); + + fRegistry.add("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_sameSideV0_sameSideLegs", + "both V0 same #eta-side, all legs same side;" + "#Delta#eta;#Delta#phi (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + fRegistry.add("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_sameSideV0_mixedLegs", + "both V0 same #eta-side, legs mixed sides;" + "#Delta#eta;#Delta#phi (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + fRegistry.add("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_diffSideV0_matchingLegs", + "V0 on opposite #eta-sides, legs match their V0 side;" + "#Delta#eta;#Delta#phi (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + fRegistry.add("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_diffSideV0_crossedLegs", + "V0 on opposite #eta-sides, legs cross their V0 side;" + "#Delta#eta;#Delta#phi (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + } + + void DefineEMEventCut() + { + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(eventcuts.cfgZvtxMin, eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + fEMEventCut.SetRequireGoodITSLayer3(eventcuts.cfgRequireGoodITSLayer3); + fEMEventCut.SetRequireGoodITSLayer0123(eventcuts.cfgRequireGoodITSLayer0123); + fEMEventCut.SetRequireGoodITSLayersAll(eventcuts.cfgRequireGoodITSLayersAll); + } + + void DefinePCMCut() + { + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); + fV0PhotonCut.SetV0PtRange(pcmcuts.cfgMinPtV0, 1e10f); + fV0PhotonCut.SetV0EtaRange(-pcmcuts.cfgMaxEtaV0, +pcmcuts.cfgMaxEtaV0); + fV0PhotonCut.SetMinCosPA(pcmcuts.cfgMinCosPA); + fV0PhotonCut.SetMaxPCA(pcmcuts.cfgMaxPCA); + fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfgMaxChi2KF); + fV0PhotonCut.SetRxyRange(pcmcuts.cfgMinV0Radius, pcmcuts.cfgMaxV0Radius); + fV0PhotonCut.SetAPRange(pcmcuts.cfgMaxAlphaAP, pcmcuts.cfgMaxQtAP); + fV0PhotonCut.RejectITSib(pcmcuts.cfgRejectV0OnITSIB); + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfgMinNClusterTPC); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfgMinNCrossedRows); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfgMaxFracSharedClustersTPC); + fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfgMaxChi2TPC); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfgMinTPCNsigmaEl, pcmcuts.cfgMaxTPCNsigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfgMaxChi2ITS); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfgDisableITSOnlyTrack); + fV0PhotonCut.SetDisableTPConly(pcmcuts.cfgDisableTPCOnlyTrack); + fV0PhotonCut.SetNClustersITS(0, 7); + fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); + fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfgRequireV0WithITSTPC); + fV0PhotonCut.SetRequireITSonly(pcmcuts.cfgRequireV0WithITSOnly); + fV0PhotonCut.SetRequireTPConly(pcmcuts.cfgRequireV0WithTPCOnly); + } + + template + static constexpr const char* singlePhotonQAPrefix() + { + if constexpr (step_id == 0) + return "SinglePhoton/Before/"; + if constexpr (step_id == 1) + return "SinglePhoton/AfterDRCosOA/"; + if constexpr (step_id == 2) // o2-linter: disable=magic-number (just counting the step of a cut) + return "SinglePhoton/AfterRZ/"; + return "SinglePhoton/AfterEllipse/"; + } + + template + inline void fillSinglePhotonQAStep(TPhoton const& g) + { + if (!qaflags.doSinglePhotonQa) + return; + constexpr auto base = singlePhotonQAPrefix(); + const float r = std::sqrt(g.vx() * g.vx() + g.vy() * g.vy()); + fRegistryPairQA.fill(HIST(base) + HIST("hEtaVsPhiPt"), g.phi(), g.eta(), g.pt()); + fRegistryPairQA.fill(HIST(base) + HIST("hRVsZConvPt"), g.vz(), r, g.pt()); + } + + template + void fillPairHistogram(TCollision const& /*collision*/, + ROOT::Math::PtEtaPhiMVector v1, + ROOT::Math::PtEtaPhiMVector v2, + float weight = 1.f) + { + float rndm = std::pow(-1, dist01(engine) % 2); + auto k12 = 0.5 * (v1 + v2); + float kt = k12.Pt(); + float qinv = -(((v1 - v2) * rndm).M()); + ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); + ROOT::Math::XYZVector uv_long(0, 0, 1); + ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); + ROOT::Math::PxPyPzEVector v1c(v1), v2c(v2); + float beta_z = (v1 + v2).Beta() * std::cos((v1 + v2).Theta()); + ROOT::Math::Boost bst_z(0, 0, -beta_z); + auto q12_lcms = bst_z((v1c - v2c) * rndm); + auto q3_lcms = q12_lcms.Vect(); + float qabs_lcms = q3_lcms.R(); + float qout_lcms = q3_lcms.Dot(uv_out); + float qside_lcms = q3_lcms.Dot(uv_side); + float qlong_lcms = q3_lcms.Dot(uv_long); + if (hbtanalysis.cfgDo3D) { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("CF_3D"), + std::fabs(qout_lcms), std::fabs(qside_lcms), std::fabs(qlong_lcms), kt, weight); + if (hbtanalysis.cfgDo2D) + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("CF_2D"), + std::fabs(qout_lcms), std::fabs(qinv), kt, weight); + } else { + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("CF_1D"), + hbtanalysis.cfgUseLCMS ? qabs_lcms : qinv, kt, weight); + } + float deta_pair = v1.Eta() - v2.Eta(); + float dphi_pair = v1.Phi() - v2.Phi(); + dphi_pair = RecoDecay::constrainAngle(dphi_pair, -o2::constants::math::PI); + if constexpr (ev_id == 0) { + fRegistry.fill(HIST("Pair/same/hSparse_DEtaDPhi_qinv_kT"), deta_pair, dphi_pair, qinv, kt, weight); + } else { + fRegistry.fill(HIST("Pair/mix/hSparse_DEtaDPhi_qinv_kT"), deta_pair, dphi_pair, qinv, kt, weight); + } + } + + template + void fillPairHistogramMC(TCollision const& /*collision*/, + ROOT::Math::PtEtaPhiMVector v1, + ROOT::Math::PtEtaPhiMVector v2, + float weight = 1.f) + { + float rndm = std::pow(-1, dist01(engine) % 2); + auto k12 = 0.5 * (v1 + v2); + float kt = k12.Pt(); + float qinv = -(((v1 - v2) * rndm).M()); + ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); + ROOT::Math::XYZVector uv_long(0, 0, 1); + ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); + ROOT::Math::PxPyPzEVector v1c(v1), v2c(v2); + float beta_z = (v1 + v2).Beta() * std::cos((v1 + v2).Theta()); + ROOT::Math::Boost bst_z(0, 0, -beta_z); + auto q12_lcms = bst_z((v1c - v2c) * rndm); + auto q3_lcms = q12_lcms.Vect(); + float qabs_lcms = q3_lcms.R(); + float qout_lcms = q3_lcms.Dot(uv_out); + float qside_lcms = q3_lcms.Dot(uv_side); + float qlong_lcms = q3_lcms.Dot(uv_long); + constexpr auto mcDir = []() constexpr -> const char* { + if constexpr (ev_id == 0) { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/same/MC/TrueTrueDistinct/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/same/MC/TrueTrueSamePhoton/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/same/MC/SharedMcLeg/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/same/MC/TrueFake/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/same/MC/FakeFake/"; + return "Pair/same/MC/Pi0Daughters/"; + } else { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/mix/MC/TrueTrueDistinct/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/mix/MC/TrueTrueSamePhoton/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/mix/MC/SharedMcLeg/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/mix/MC/TrueFake/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/mix/MC/FakeFake/"; + return "Pair/mix/MC/Pi0Daughters/"; + } + }(); + if (hbtanalysis.cfgDo3D) { + fRegistryPairMC.fill(HIST(mcDir) + HIST("CF_3D"), + std::fabs(qout_lcms), std::fabs(qside_lcms), std::fabs(qlong_lcms), kt, weight); + if (hbtanalysis.cfgDo2D) + fRegistryPairMC.fill(HIST(mcDir) + HIST("CF_2D"), std::fabs(qout_lcms), std::fabs(qinv), kt, weight); + } else { + fRegistryPairMC.fill(HIST(mcDir) + HIST("CF_1D"), hbtanalysis.cfgUseLCMS ? qabs_lcms : qinv, kt, weight); + } + float deta_pair = v1.Eta() - v2.Eta(); + float dphi_pair = v1.Phi() - v2.Phi(); + dphi_pair = RecoDecay::constrainAngle(dphi_pair, -o2::constants::math::PI); + if constexpr (ev_id == 0) { + fRegistry.fill(HIST("Pair/same/hSparse_DEtaDPhi_qinv_kT"), deta_pair, dphi_pair, qinv, kt, weight); + } else { + fRegistry.fill(HIST("Pair/mix/hSparse_DEtaDPhi_qinv_kT"), deta_pair, dphi_pair, qinv, kt, weight); + } + } + + template + PairQAObservables buildPairQAObservables(TG1 const& g1, TG2 const& g2) + { + PairQAObservables o{}; + o.x1 = g1.vx(); + o.y1 = g1.vy(); + o.z1 = g1.vz(); + o.x2 = g2.vx(); + o.y2 = g2.vy(); + o.z2 = g2.vz(); + o.r1 = std::sqrt(o.x1 * o.x1 + o.y1 * o.y1); + o.r2 = std::sqrt(o.x2 * o.x2 + o.y2 * o.y2); + o.dx = o.x1 - o.x2; + o.dy = o.y1 - o.y2; + o.dz = o.z1 - o.z2; + o.deltaR = std::fabs(o.r1 - o.r2); + o.deltaZ = o.dz; + o.deltaRxy = std::sqrt(o.dx * o.dx + o.dy * o.dy); + o.deltaR3D = std::sqrt(o.dx * o.dx + o.dy * o.dy + o.dz * o.dz); + ROOT::Math::XYZVector cp1(o.x1, o.y1, o.z1), cp2(o.x2, o.y2, o.z2); + const float mag1 = std::sqrt(cp1.Mag2()), mag2 = std::sqrt(cp2.Mag2()); + if (mag1 < kMinMagnitude || mag2 < kMinMagnitude) { + o.valid = false; + return o; + } + float cosPA = static_cast(cp1.Dot(cp2) / (mag1 * mag2)); + cosPA = std::clamp(cosPA, -1.f, 1.f); + o.opa = std::acos(cosPA); + o2::math_utils::bringTo02Pi(o.opa); + if (o.opa > o2::constants::math::PI) + o.opa -= o2::constants::math::PI; + o.cosOA = std::cos(o.opa / 2.f); + o.drOverCosOA = (std::fabs(o.cosOA) < kMinCosine) ? 1e12f : (o.deltaR3D / o.cosOA); + o.v1 = ROOT::Math::PtEtaPhiMVector(g1.pt(), g1.eta(), g1.phi(), 0.f); + o.v2 = ROOT::Math::PtEtaPhiMVector(g2.pt(), g2.eta(), g2.phi(), 0.f); + o.k12 = 0.5f * (o.v1 + o.v2); + o.deta = g1.eta() - g2.eta(); + o.dphi = RecoDecay::constrainAngle(g1.phi() - g2.phi(), -o2::constants::math::PI); + o.pairEta = 0.5f * (g1.eta() + g2.eta()); + o.pairPhi = RecoDecay::constrainAngle(o.k12.Phi(), 0.f); + o.kt = o.k12.Pt(); + o.qinv = std::fabs((o.v1 - o.v2).M()); + o.cosTheta = std::fabs(computeCosTheta(o.v1, o.v2)); + o.openingAngle = o.opa; + return o; + } + + template + inline void fillPairQAStep(PairQAObservables const& o, float /*cent*/, float /*occupancy*/) + { + if (!qaflags.doPairQa) + return; + constexpr auto base = qaPrefix(); + + ///// Delta Eta QA + + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaEtaDeltaRKt"), o.deta, o.deltaR, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaEtaEtaKt"), o.deta, o.pairEta, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaEtaPhiKt"), o.deta, o.pairPhi, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaEtaDeltaZKt"), o.deta, o.deltaZ, o.kt); + + ///// Delta Phi QA + + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaPhiDeltaRKt"), o.dphi, o.deltaR, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaPhiDeltaZKt"), o.dphi, o.deltaZ, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hSparseDEtaDPhiKt"), o.deta, o.dphi, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaPhiPhiKt"), o.dphi, o.pairPhi, o.kt); + + // Delta Eta Dleta Phi Stuff + + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaPhiEtaKt"), o.dphi, o.pairEta, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hPhiVsEtaKt"), o.pairPhi, o.pairEta, o.kt); + + //// Delta R (Conversion point) QA + + fRegistryPairQA.fill(HIST(base) + HIST("hR1VsR2"), o.r1, o.r2); + fRegistryPairQA.fill(HIST(base) + HIST("hSparseDeltaRDeltaZKt"), o.deltaR, o.deltaZ, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaRxyKt"), o.deltaRxy, o.kt); + fRegistryPairQA.fill(HIST(base) + HIST("hDeltaR3DKt"), o.deltaR3D, o.kt); + + const float sE = ggpaircuts.cfgEllipseSigEta.value, sP = ggpaircuts.cfgEllipseSigPhi.value; + if (sE > kMinSigma && sP > kMinSigma) + fRegistryPairQA.fill(HIST(base) + HIST("hEllipseVal"), (o.deta / sE) * (o.deta / sE) + (o.dphi / sP) * (o.dphi / sP)); + } + + template + static PhotonMCInfo buildPhotonMCInfo(TPhoton const& g, TMCParticles const& mcParticles) + { + PhotonMCInfo info{}; + const auto pos = g.template posTrack_as(); + const auto neg = g.template negTrack_as(); + if (!pos.has_emmcparticle() || !neg.has_emmcparticle()) + return info; + info.hasMC = true; + info.mcPosId = pos.emmcparticleId(); + info.mcNegId = neg.emmcparticleId(); + const auto mcPos = pos.template emmcparticle_as(); + const auto mcNeg = neg.template emmcparticle_as(); + if (!mcPos.has_mothers() || !mcNeg.has_mothers()) + return info; + const int mothIdPos = mcPos.mothersIds()[0], mothIdNeg = mcNeg.mothersIds()[0]; + if (mothIdPos != mothIdNeg) + return info; + info.sameMother = true; + info.motherId = mothIdPos; + const auto mother = mcParticles.iteratorAt(mothIdPos); + info.motherPdg = mother.pdgCode(); + info.isTruePhoton = (info.motherPdg == kGamma); + info.isPhysicalPrimary = mother.isPhysicalPrimary(); + return info; + } + + static PairTruthType classifyPairTruth(PhotonMCInfo const& m1, PhotonMCInfo const& m2) + { + const bool t1 = m1.hasMC && m1.sameMother && m1.isTruePhoton; + const bool t2 = m2.hasMC && m2.sameMother && m2.isTruePhoton; + if (m1.hasMC && m2.hasMC) { + if ((m1.mcPosId >= 0 && (m1.mcPosId == m2.mcPosId || m1.mcPosId == m2.mcNegId)) || + (m1.mcNegId >= 0 && (m1.mcNegId == m2.mcPosId || m1.mcNegId == m2.mcNegId))) + return PairTruthType::SharedMcLeg; + } + if (!t1 && !t2) + return PairTruthType::FakeFake; + if (t1 != t2) + return PairTruthType::TrueFake; + if (m1.motherId >= 0 && m1.motherId == m2.motherId) + return PairTruthType::TrueTrueSamePhoton; + return PairTruthType::TrueTrueDistinct; + } + + enum class EtaTopology : uint8_t { + SameSideV0SameSideLegs = 0, ///< both V0 eta same sign; all 4 legs same sign + SameSideV0MixedLegs = 1, ///< both V0 eta same sign; legs not all on that sign + DiffSideV0MatchingLegs = 2, ///< V0s on opposite sides; each V0's legs match its own side + DiffSideV0CrossedLegs = 3, ///< V0s on opposite sides; legs do NOT match their V0's side + }; + + /// Classify the eta-side topology of a photon pair from the 6 raw eta values. + static EtaTopology classifyEtaTopology(float v1eta, float v2eta, + float pos1eta, float neg1eta, + float pos2eta, float neg2eta) + { + const bool v1pos = v1eta >= 0.f; + const bool v2pos = v2eta >= 0.f; + if (v1pos == v2pos) { // same-side V0s + const bool allSame = + ((pos1eta >= 0.f) == v1pos) && ((neg1eta >= 0.f) == v1pos) && + ((pos2eta >= 0.f) == v1pos) && ((neg2eta >= 0.f) == v1pos); + return allSame ? EtaTopology::SameSideV0SameSideLegs + : EtaTopology::SameSideV0MixedLegs; + } + // different-side V0s + const bool v1match = ((pos1eta >= 0.f) == v1pos) && ((neg1eta >= 0.f) == v1pos); + const bool v2match = ((pos2eta >= 0.f) == v2pos) && ((neg2eta >= 0.f) == v2pos); + return (v1match && v2match) ? EtaTopology::DiffSideV0MatchingLegs + : EtaTopology::DiffSideV0CrossedLegs; + } + + inline void fillEtaTopologyHisto(EtaTopology topo, float deta, float dphi, float kt) + { + switch (topo) { + case EtaTopology::SameSideV0SameSideLegs: + fRegistry.fill(HIST("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_sameSideV0_sameSideLegs"), + deta, dphi, kt); + break; + case EtaTopology::SameSideV0MixedLegs: + fRegistry.fill(HIST("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_sameSideV0_mixedLegs"), + deta, dphi, kt); + break; + case EtaTopology::DiffSideV0MatchingLegs: + fRegistry.fill(HIST("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_diffSideV0_matchingLegs"), + deta, dphi, kt); + break; + case EtaTopology::DiffSideV0CrossedLegs: + fRegistry.fill(HIST("Pair/same/EtaTopology/hSparse_DEtaDPhi_kT_diffSideV0_crossedLegs"), + deta, dphi, kt); + break; + } + } + + template + static bool isPi0DaughterPair(PhotonMCInfo const& m1, PhotonMCInfo const& m2, + TMCParticles const& mcParticles) + { + if (!m1.isTruePhoton || !m2.isTruePhoton || m1.motherId < 0 || m2.motherId < 0) + return false; + const auto ph1 = mcParticles.iteratorAt(m1.motherId); + const auto ph2 = mcParticles.iteratorAt(m2.motherId); + if (!ph1.has_mothers() || !ph2.has_mothers()) + return false; + const int gm1 = ph1.mothersIds()[0], gm2 = ph2.mothersIds()[0]; + if (gm1 != gm2) + return false; + return (std::abs(mcParticles.iteratorAt(gm1).pdgCode()) == kPi0); + } + + static constexpr std::string_view pairTruthLabel(PairTruthType t) + { + switch (t) { + case PairTruthType::TrueTrueDistinct: + return "TrueTrueDistinct/"; + case PairTruthType::TrueTrueSamePhoton: + return "TrueTrueSamePhoton/"; + case PairTruthType::SharedMcLeg: + return "SharedMcLeg/"; + case PairTruthType::TrueFake: + return "TrueFake/"; + case PairTruthType::FakeFake: + return "FakeFake/"; + case PairTruthType::Pi0Daughters: + return "Pi0Daughters/"; + default: + return "Unknown/"; + } + } + void addMCHistograms() + { + const AxisSpec axisTruthType{{0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5}, + "truth type (1=TrueTrueDistinct,2=TrueTrueSamePhoton,3=SharedMcLeg," + "4=TrueFake,5=FakeFake,6=Pi0Daughters)"}; + const AxisSpec axisDeltaEtaMC{90, -1.6f, +1.6f, "#Delta#eta"}; + const AxisSpec axisDeltaPhiMC{90, -o2::constants::math::PI, +o2::constants::math::PI, "#Delta#phi (rad)"}; + const AxisSpec axQinvMC{60, 0.f, 0.3f, "q_{inv}^{true} (GeV/c)"}; + const AxisSpec axRconv{180, 0.f, 90.f, "R_{conv}^{true} (cm)"}; + const AxisSpec axAlpha{100, -1.f, 1.f, "#alpha^{true}"}; + const AxisSpec axLegDR{100, 0.f, 0.3f, "leg #Delta R^{true}"}; + + // fRegistryPairMC — reco-level pair histograms, per MC truth type + + // Per-type CF + observables + static constexpr std::array kTypes = { + "TrueTrueDistinct/", "TrueTrueSamePhoton/", "SharedMcLeg/", + "TrueFake/", "FakeFake/", "Pi0Daughters/"}; + + for (const auto& label : kTypes) { + const std::string base = std::string("Pair/same/MC/") + std::string(label); + + // CF + if (hbtanalysis.cfgDo3D) { + fRegistryPairMC.add((base + "CF_3D").c_str(), "MC CF 3D LCMS", + kTHnSparseD, {axisQout, axisQside, axisQlong, axisKt}, true); + if (hbtanalysis.cfgDo2D) + fRegistryPairMC.add((base + "CF_2D").c_str(), "MC CF 2D", + kTHnSparseD, {axisQout, axisQinv, axisKt}, true); + } else { + fRegistryPairMC.add((base + "CF_1D").c_str(), + hbtanalysis.cfgUseLCMS ? "MC CF 1D LCMS" : "MC CF 1D (qinv)", + kTH2D, {hbtanalysis.cfgUseLCMS ? axisQabsLcms : axisQinv, axisKt}, true); + } + + // 1D observables + fRegistryPairMC.add((base + "hQinv").c_str(), "q_{inv};q_{inv} (GeV/c);counts", kTH1D, {axisQinv}, true); + fRegistryPairMC.add((base + "hDeltaR").c_str(), "|R_{1}-R_{2}|;|R_{1}-R_{2}| (cm);counts", kTH1D, {axisDeltaR}, true); + fRegistryPairMC.add((base + "hDeltaZ").c_str(), "#Delta z;#Delta z (cm);counts", kTH1D, {axisDeltaZ}, true); + fRegistryPairMC.add((base + "hDeltaR3D").c_str(), "#Delta r_{3D};#Delta r_{3D} (cm);counts", kTH1D, {axisDeltaR3D}, true); + + // 2D observables + fRegistryPairMC.add((base + "hDEtaDPhi").c_str(), "#Delta#eta vs #Delta#phi", kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairMC.add((base + "hDeltaRVsQinv").c_str(), "|R_{1}-R_{2}| vs q_{inv}", kTH2D, {axisQinv, axisDeltaR}, true); + fRegistryPairMC.add((base + "hDeltaZVsQinv").c_str(), "#Delta z vs q_{inv}", kTH2D, {axisQinv, axisDeltaZ}, true); + fRegistryPairMC.add((base + "hDeltaR3DVsQinv").c_str(), "#Delta r_{3D} vs q_{inv}", kTH2D, {axisQinv, axisDeltaR3D}, true); + + // Sparse (conditional) + fRegistryPairMC.add((base + "hSparse_DEtaDPhi_kT").c_str(), + "#Delta#eta,#Delta#phi,k_{T};#Delta#eta;#Delta#phi (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEtaMC, axisDeltaPhiMC, axisKt}, true); + + const bool addDEtaDPhiVsQinv = + (label == "TrueTrueDistinct/") ? mctruthSparse.cfgFillDEtaDPhiVsQinvTrueTrueDistinct.value + : (label == "TrueTrueSamePhoton/") ? mctruthSparse.cfgFillDEtaDPhiVsQinvTrueTrueSamePhoton.value + : (label == "SharedMcLeg/") ? mctruthSparse.cfgFillDEtaDPhiVsQinvSharedMcLeg.value + : (label == "TrueFake/") ? mctruthSparse.cfgFillDEtaDPhiVsQinvTrueFake.value + : (label == "FakeFake/") ? mctruthSparse.cfgFillDEtaDPhiVsQinvFakeFake.value + : mctruthSparse.cfgFillDEtaDPhiVsQinvPi0Daughters.value; + if (addDEtaDPhiVsQinv) + fRegistryPairMC.add((base + "hDEtaDPhiVsQinv").c_str(), + "#Delta#eta vs #Delta#phi vs q_{inv}", kTHnSparseD, + {axisDeltaEtaMC, axisDeltaPhiMC, axisQinv}, true); + + const bool addDRDZQinv = + (label == "TrueTrueDistinct/") ? mctruthSparse.cfgFillDRDZQinvTrueTrueDistinct.value + : (label == "TrueTrueSamePhoton/") ? mctruthSparse.cfgFillDRDZQinvTrueTrueSamePhoton.value + : (label == "SharedMcLeg/") ? mctruthSparse.cfgFillDRDZQinvSharedMcLeg.value + : (label == "TrueFake/") ? mctruthSparse.cfgFillDRDZQinvTrueFake.value + : (label == "FakeFake/") ? mctruthSparse.cfgFillDRDZQinvFakeFake.value + : mctruthSparse.cfgFillDRDZQinvPi0Daughters.value; + if (addDRDZQinv) + fRegistryPairMC.add((base + "hSparseDeltaRDeltaZQinv").c_str(), + "|R_{1}-R_{2}|,#Delta z,q_{inv}", kTHnSparseD, + {axisDeltaR, axisDeltaZ, axisQinv}, true); + } + + fRegistryPairMC.add("Pair/same/MC/hTruthTypeVsQinv", + "truth type vs q_{inv};q_{inv} (GeV/c);truth type", kTH2D, {axisQinv, axisTruthType}, true); + fRegistryPairMC.add("Pair/same/MC/hTruthTypeVsKt", + "truth type vs k_{T};k_{T} (GeV/c);truth type", kTH2D, {axisKt, axisTruthType}, true); + + fRegistryPairMC.add("Pair/same/MC/hDEtaDPhi_truePairs", + "true reco pairs (TrueTrueDistinct+SamePhoton+Pi0);" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairMC.add("Pair/same/MC/hDEtaDPhi_fakePairs", + "fake reco pairs (FakeFake+TrueFake+SharedMcLeg);" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairMC.add("Pair/same/MC/hSparse_DEtaDPhi_kT_truePairs", + "true pairs: #Delta#eta,#Delta#phi,k_{T};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEtaMC, axisDeltaPhiMC, axisKt}, true); + fRegistryPairMC.add("Pair/same/MC/hSparse_DEtaDPhi_kT_fakePairs", + "fake pairs: #Delta#eta,#Delta#phi,k_{T};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEtaMC, axisDeltaPhiMC, axisKt}, true); + fRegistryPairMC.add("Pair/same/MC/hSparse_DEtaDPhi_qinv_truePairs", + "true pairs: #Delta#eta,#Delta#phi,q_{inv};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);q_{inv} (GeV/c)", + kTHnSparseD, {axisDeltaEtaMC, axisDeltaPhiMC, axisQinv}, true); + fRegistryPairMC.add("Pair/same/MC/hSparse_DEtaDPhi_qinv_fakePairs", + "fake pairs: #Delta#eta,#Delta#phi,q_{inv};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);q_{inv} (GeV/c)", + kTHnSparseD, {axisDeltaEtaMC, axisDeltaPhiMC, axisQinv}, true); + + // ─── Pairs with missing MC label ───────────────────────────────────────── + if (hbtanalysis.cfgDo3D) { + fRegistryPairMC.add("Pair/same/MC/NoLabel/CF_3D", + "missing MC label — CF 3D LCMS", kTHnSparseD, {axisQout, axisQside, axisQlong, axisKt}, true); + if (hbtanalysis.cfgDo2D) + fRegistryPairMC.add("Pair/same/MC/NoLabel/CF_2D", + "missing MC label — CF 2D", kTHnSparseD, {axisQout, axisQinv, axisKt}, true); + } else { + fRegistryPairMC.add("Pair/same/MC/NoLabel/CF_1D", + hbtanalysis.cfgUseLCMS ? "missing MC label — CF 1D LCMS" : "missing MC label — CF 1D (qinv)", + kTH2D, {hbtanalysis.cfgUseLCMS ? axisQabsLcms : axisQinv, axisKt}, true); + } + fRegistryPairMC.add("Pair/same/MC/NoLabel/hDEtaDPhi", + "missing MC label: #Delta#eta vs #Delta#phi;" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryPairMC.add("Pair/same/MC/NoLabel/hQinv", + "missing MC label: q_{inv};q_{inv} (GeV/c);counts", kTH1D, {axisQinv}, true); + fRegistryPairMC.add("Pair/same/MC/NoLabel/hKt", + "missing MC label: k_{T};k_{T} (GeV/c);counts", kTH1D, {axisKt}, true); + + // fRegistryMC — truth-level histograms + + // ─── Truth-level CF + fRegistryMC.add("MC/TruthCF/hQinvVsKt_same", "truth-level same-event CF;k_{T} (GeV/c);q_{inv}^{true} (GeV/c)", kTH2D, {axisKt, axQinvMC}, true); + fRegistryMC.add("MC/TruthCF/hDEtaDPhi_same", + "truth-level same-event #Delta#eta vs #Delta#phi;" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + fRegistryMC.add("MC/TruthCF/hQinvVsKt_mix", "truth-level mixed-event CF;k_{T} (GeV/c);q_{inv}^{true} (GeV/c)", kTH2D, {axisKt, axQinvMC}, true); + fRegistryMC.add("MC/TruthCF/hDEtaDPhi_mix", + "truth-level mixed-event #Delta#eta vs #Delta#phi;" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad)", + kTH2D, {axisDeltaEta, axisDeltaPhi}, true); + + auto addStageHistos = [&](const char* suffix, const char* title, auto... axes) { + for (const auto& stage : {"truthConverted", "all4LegsThisColl", + "bothPhotonsBuilt", "bothPhotonsSelected"}) { + const std::string name = std::string("MC/TruthAO2D/") + suffix + std::string("_") + stage; + const std::string ttl = std::string(title) + std::string(" [") + stage + "]"; + fRegistryMC.add(name.c_str(), ttl.c_str(), kTHnD, {axes...}, true); + } + }; + auto addStageHistos2D = [&](const char* suffix, const char* title, auto ax1, auto ax2) { + for (const auto& stage : {"truthConverted", "all4LegsThisColl", + "bothPhotonsBuilt", "bothPhotonsSelected"}) { + const std::string name = std::string("MC/TruthAO2D/") + suffix + std::string("_") + stage; + fRegistryMC.add(name.c_str(), title, kTH2D, {ax1, ax2}, true); + } + }; + + addStageHistos("hSparse_DEtaDPhi_qinv", + "#Delta#eta,#Delta#phi,q_{inv}^{true};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);q_{inv}^{true} (GeV/c)", + axisDeltaEta, axisDeltaPhi, axQinvMC); + + addStageHistos("hSparse_DEtaDPhi_kT", + "#Delta#eta,#Delta#phi,k_{T};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);k_{T} (GeV/c)", + axisDeltaEta, axisDeltaPhi, axisKt); + + addStageHistos2D("hQinvVsKt", + "q_{inv}^{true} vs k_{T};k_{T} (GeV/c);q_{inv}^{true} (GeV/c)", + axisKt, axQinvMC); + + addStageHistos2D("hDEtaDPhi", + "#Delta#eta vs #Delta#phi;#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad)", + axisDeltaEta, axisDeltaPhi); + + // Rconv waterfall (nur converted + selected) + fRegistryMC.add("MC/TruthAO2D/hRconv1_vs_Rconv2_truthConverted", + "denominator: R_{conv,1} vs R_{conv,2};R_{conv,1}^{true} (cm);R_{conv,2}^{true} (cm)", + kTH2D, {axRconv, axRconv}, true); + fRegistryMC.add("MC/TruthAO2D/hRconv1_vs_Rconv2_bothPhotonsSelected", + "numerator: R_{conv,1} vs R_{conv,2};R_{conv,1}^{true} (cm);R_{conv,2}^{true} (cm)", + kTH2D, {axRconv, axRconv}, true); + fRegistryMC.add("MC/TruthAO2D/hMinRconv_vs_kT_truthConverted", + "denominator: min(R_{conv}) vs k_{T};k_{T} (GeV/c);min(R_{conv}^{true}) (cm)", + kTH2D, {axisKt, axRconv}, true); + fRegistryMC.add("MC/TruthAO2D/hMinRconv_vs_kT_bothPhotonsSelected", + "numerator: min(R_{conv}) vs k_{T};k_{T} (GeV/c);min(R_{conv}^{true}) (cm)", + kTH2D, {axisKt, axRconv}, true); + + // Stage waterfall summary + consistency + fRegistryMC.add("MC/TruthAO2D/hStage_vs_kT", + "efficiency waterfall;k_{T} (GeV/c);stage (0=converted,1=all4legs,2=bothBuilt,3=bothSel)", + kTH2D, {axisKt, AxisSpec{4, -0.5f, 3.5f, "stage"}}, true); + fRegistryMC.add("MC/TruthAO2D/hStageConsistency", + "stage consistency (expect all at 0);N(V0 built but legs not found);counts", + kTH1D, {AxisSpec{20, -0.5f, 19.5f, "N_{bad}"}}, true); + + // ─── Single-leg diagnostics ─────────────────────────────────────────────── + fRegistryMC.add("MC/LegDiag/hLegDRtrue_vs_pt_legFound", "leg found: #Delta R^{true} vs p_{T};p_{T,#gamma}^{true} (GeV/c);#Delta R_{e^{+}e^{-}}^{true}", kTH2D, {axisPt, axLegDR}, true); + fRegistryMC.add("MC/LegDiag/hLegDRtrue_vs_pt_legMissing", "leg missing: #Delta R^{true} vs p_{T};p_{T,#gamma}^{true} (GeV/c);#Delta R_{e^{+}e^{-}}^{true}", kTH2D, {axisPt, axLegDR}, true); + fRegistryMC.add("MC/LegDiag/hLegDEta_legFound_vs_pt", "leg found: |#Delta#eta| vs p_{T};p_{T,#gamma}^{true} (GeV/c);|#Delta#eta_{e^{+}e^{-}}|", kTH2D, {axisPt, AxisSpec{100, 0.f, 0.5f, "|#Delta#eta_{legs}|"}}, true); + fRegistryMC.add("MC/LegDiag/hLegDEta_legMissing_vs_pt", "leg missing: |#Delta#eta| vs p_{T};p_{T,#gamma}^{true} (GeV/c);|#Delta#eta_{e^{+}e^{-}}|", kTH2D, {axisPt, AxisSpec{100, 0.f, 0.5f, "|#Delta#eta_{legs}|"}}, true); + fRegistryMC.add("MC/LegDiag/hLegDPhi_legFound_vs_pt", "leg found: |#Delta#phi| vs p_{T};p_{T,#gamma}^{true} (GeV/c);|#Delta#phi_{e^{+}e^{-}}| (rad)", kTH2D, {axisPt, AxisSpec{100, 0.f, 0.5f, "|#Delta#phi_{legs}|"}}, true); + fRegistryMC.add("MC/LegDiag/hLegDPhi_legMissing_vs_pt", "leg missing: |#Delta#phi| vs p_{T};p_{T,#gamma}^{true} (GeV/c);|#Delta#phi_{e^{+}e^{-}}| (rad)", kTH2D, {axisPt, AxisSpec{100, 0.f, 0.5f, "|#Delta#phi_{legs}|"}}, true); + fRegistryMC.add("MC/LegDiag/hAlphaTrue_legFound_vs_pt", "leg found: #alpha^{true} vs p_{T};p_{T,#gamma}^{true} (GeV/c);#alpha^{true}", kTH2D, {axisPt, axAlpha}, true); + fRegistryMC.add("MC/LegDiag/hAlphaTrue_legMissing_vs_pt", "leg missing: #alpha^{true} vs p_{T};p_{T,#gamma}^{true} (GeV/c);#alpha^{true}", kTH2D, {axisPt, axAlpha}, true); + fRegistryMC.add("MC/LegDiag/hAlpha_vs_legDR_legMissing", "leg missing: #alpha^{true} vs #Delta R^{true};#Delta R_{e^{+}e^{-}}^{true};#alpha^{true}", kTH2D, {axLegDR, axAlpha}, true); + + // ─── Pair-level leg diagnostics ─────────────────────────────────────────── + fRegistryMC.add("MC/LegDiag/hNLegsPair_vs_kT", "N legs found per pair vs k_{T};k_{T} (GeV/c);N_{legs found} (0-4)", kTH2D, {axisKt, AxisSpec{5, -0.5f, 4.5f, "N_{legs found}"}}, true); + fRegistryMC.add("MC/LegDiag/hMissingLegPt_vs_kT", "missing leg p_{T}^{true} vs pair k_{T};k_{T} (GeV/c);p_{T,leg}^{true} (GeV/c)", kTH2D, {axisKt, AxisSpec{100, 0.f, 0.5f, "p_{T,leg}^{true} (GeV/c)"}}, true); + fRegistryMC.add("MC/LegDiag/hMissingLegRconv_vs_kT", "missing leg R_{conv}^{true} vs pair k_{T};k_{T} (GeV/c);R_{conv}^{true} (cm)", kTH2D, {axisKt, axisR}, true); + + // ─── Cross-built V0 pairs ───────────────────────────────────────────────── + fRegistryMC.add("MC/PairCrossBuild/hSparse_DEtaDPhi_kT", + "cross-built V0 pairs: #Delta#eta,#Delta#phi,k_{T};" + "#Delta#eta_{#gamma#gamma};#Delta#phi_{#gamma#gamma} (rad);k_{T} (GeV/c)", + kTHnSparseD, {axisDeltaEta, axisDeltaPhi, axisKt}, true); + fRegistryMC.add("MC/PairCrossBuild/hStageOut_vs_kT", + "cross-built pairs: N correctly built vs k_{T};" + "k_{T} (GeV/c);N photons correctly built (0/1/2)", + kTH2D, {axisKt, AxisSpec{3, -0.5f, 2.5f, "N correctly built"}}, true); + } + + template + inline void fillMCPairQATyped(PairQAObservables const& obs, bool doSparse, bool doMCQA) + { + constexpr auto base = []() constexpr -> const char* { + if constexpr (!IsMix) { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/same/MC/TrueTrueDistinct/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/same/MC/TrueTrueSamePhoton/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/same/MC/SharedMcLeg/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/same/MC/TrueFake/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/same/MC/FakeFake/"; + return "Pair/same/MC/Pi0Daughters/"; + } else { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/mix/MC/TrueTrueDistinct/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/mix/MC/TrueTrueSamePhoton/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/mix/MC/SharedMcLeg/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/mix/MC/TrueFake/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/mix/MC/FakeFake/"; + return "Pair/mix/MC/Pi0Daughters/"; + } + }(); + if (doMCQA) { + fRegistryPairMC.fill(HIST(base) + HIST("hDEtaDPhi"), obs.deta, obs.dphi); + fRegistryPairMC.fill(HIST(base) + HIST("hQinv"), obs.qinv); + fRegistryPairMC.fill(HIST(base) + HIST("hDeltaR"), obs.deltaR); + fRegistryPairMC.fill(HIST(base) + HIST("hDeltaZ"), obs.deltaZ); + fRegistryPairMC.fill(HIST(base) + HIST("hDeltaR3D"), obs.deltaR3D); + } + if (doSparse) + fRegistryPairMC.fill(HIST(base) + HIST("hSparse_DEtaDPhi_kT"), obs.deta, obs.dphi, obs.kt); + constexpr auto summaryDir = IsMix ? "Pair/mix/MC/" : "Pair/same/MC/"; + if (doMCQA) { + fRegistryPairMC.fill(HIST(summaryDir) + HIST("hTruthTypeVsQinv"), obs.qinv, static_cast(TruthT)); + fRegistryPairMC.fill(HIST(summaryDir) + HIST("hTruthTypeVsKt"), obs.kt, static_cast(TruthT)); + } + } + + template + inline void fillMCPairQA(PairTruthType truthType, PairQAObservables const& obs, bool doSparse, bool doMCQA) + { + switch (truthType) { + case PairTruthType::TrueTrueDistinct: + fillMCPairQATyped(obs, doSparse, doMCQA); + break; + case PairTruthType::TrueTrueSamePhoton: + fillMCPairQATyped(obs, doSparse, doMCQA); + break; + case PairTruthType::SharedMcLeg: + fillMCPairQATyped(obs, doSparse, doMCQA); + break; + case PairTruthType::TrueFake: + fillMCPairQATyped(obs, doSparse, doMCQA); + break; + case PairTruthType::FakeFake: + fillMCPairQATyped(obs, doSparse, doMCQA); + break; + case PairTruthType::Pi0Daughters: + fillMCPairQATyped(obs, doSparse, doMCQA); + break; + default: + break; + } + } + + template + inline void fillMCPairQAFullRangeTyped(PairQAObservables const& obs) + { + constexpr auto base = []() constexpr -> const char* { + if constexpr (!IsMix) { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/same/MC/TrueTrueDistinct/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/same/MC/TrueTrueSamePhoton/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/same/MC/SharedMcLeg/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/same/MC/TrueFake/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/same/MC/FakeFake/"; + return "Pair/same/MC/Pi0Daughters/"; + } else { + if constexpr (TruthT == PairTruthType::TrueTrueDistinct) + return "Pair/mix/MC/TrueTrueDistinct/"; + if constexpr (TruthT == PairTruthType::TrueTrueSamePhoton) + return "Pair/mix/MC/TrueTrueSamePhoton/"; + if constexpr (TruthT == PairTruthType::SharedMcLeg) + return "Pair/mix/MC/SharedMcLeg/"; + if constexpr (TruthT == PairTruthType::TrueFake) + return "Pair/mix/MC/TrueFake/"; + if constexpr (TruthT == PairTruthType::FakeFake) + return "Pair/mix/MC/FakeFake/"; + return "Pair/mix/MC/Pi0Daughters/"; + } + }(); + fRegistryPairMC.fill(HIST(base) + HIST("hDeltaRVsQinv"), obs.qinv, obs.deltaR); + fRegistryPairMC.fill(HIST(base) + HIST("hDeltaZVsQinv"), obs.qinv, obs.deltaZ); + fRegistryPairMC.fill(HIST(base) + HIST("hDeltaR3DVsQinv"), obs.qinv, obs.deltaR3D); + const bool fillDRDZ = ((TruthT == PairTruthType::TrueTrueDistinct) ? mctruthSparse.cfgFillDRDZQinvTrueTrueDistinct.value : (TruthT == PairTruthType::TrueTrueSamePhoton) ? mctruthSparse.cfgFillDRDZQinvTrueTrueSamePhoton.value + : (TruthT == PairTruthType::SharedMcLeg) ? mctruthSparse.cfgFillDRDZQinvSharedMcLeg.value + : (TruthT == PairTruthType::TrueFake) ? mctruthSparse.cfgFillDRDZQinvTrueFake.value + : (TruthT == PairTruthType::FakeFake) ? mctruthSparse.cfgFillDRDZQinvFakeFake.value + : mctruthSparse.cfgFillDRDZQinvPi0Daughters.value); + if (fillDRDZ) + fRegistryPairMC.fill(HIST(base) + HIST("hSparseDeltaRDeltaZQinv"), obs.deltaR, obs.deltaZ, obs.qinv); + const bool enabled = ((TruthT == PairTruthType::TrueTrueDistinct) ? mctruthSparse.cfgFillDEtaDPhiVsQinvTrueTrueDistinct.value : (TruthT == PairTruthType::TrueTrueSamePhoton) ? mctruthSparse.cfgFillDEtaDPhiVsQinvTrueTrueSamePhoton.value + : (TruthT == PairTruthType::SharedMcLeg) ? mctruthSparse.cfgFillDEtaDPhiVsQinvSharedMcLeg.value + : (TruthT == PairTruthType::TrueFake) ? mctruthSparse.cfgFillDEtaDPhiVsQinvTrueFake.value + : (TruthT == PairTruthType::FakeFake) ? mctruthSparse.cfgFillDEtaDPhiVsQinvFakeFake.value + : mctruthSparse.cfgFillDEtaDPhiVsQinvPi0Daughters.value); + if (enabled) + fRegistryPairMC.fill(HIST(base) + HIST("hDEtaDPhiVsQinv"), obs.deta, obs.dphi, obs.qinv); + } + + template + inline void fillMCPairQAFullRange(PairTruthType truthType, PairQAObservables const& obs) + { + switch (truthType) { + case PairTruthType::TrueTrueDistinct: + fillMCPairQAFullRangeTyped(obs); + break; + case PairTruthType::TrueTrueSamePhoton: + fillMCPairQAFullRangeTyped(obs); + break; + case PairTruthType::SharedMcLeg: + fillMCPairQAFullRangeTyped(obs); + break; + case PairTruthType::TrueFake: + fillMCPairQAFullRangeTyped(obs); + break; + case PairTruthType::FakeFake: + fillMCPairQAFullRangeTyped(obs); + break; + case PairTruthType::Pi0Daughters: + fillMCPairQAFullRangeTyped(obs); + break; + default: + break; + } + } + template + void fillPairHistogramNoLabel(TCollision const& /*collision*/, + ROOT::Math::PtEtaPhiMVector v1, + ROOT::Math::PtEtaPhiMVector v2) + { + float rndm = std::pow(-1, dist01(engine) % 2); + auto k12 = 0.5 * (v1 + v2); + float kt = k12.Pt(); + float qinv = -(((v1 - v2) * rndm).M()); + ROOT::Math::XYZVector uv_out(k12.Px() / k12.Pt(), k12.Py() / k12.Pt(), 0); + ROOT::Math::XYZVector uv_long(0, 0, 1); + ROOT::Math::XYZVector uv_side = uv_out.Cross(uv_long); + ROOT::Math::PxPyPzEVector v1c(v1), v2c(v2); + float beta_z = (v1 + v2).Beta() * std::cos((v1 + v2).Theta()); + ROOT::Math::Boost bst_z(0, 0, -beta_z); + auto q12_lcms = bst_z((v1c - v2c) * rndm); + auto q3_lcms = q12_lcms.Vect(); + float qabs_lcms = q3_lcms.R(); + float qout_lcms = q3_lcms.Dot(uv_out); + float qside_lcms = q3_lcms.Dot(uv_side); + float qlong_lcms = q3_lcms.Dot(uv_long); + if (hbtanalysis.cfgDo3D) { + fRegistryPairMC.fill(HIST("Pair/same/MC/NoLabel/CF_3D"), + std::fabs(qout_lcms), std::fabs(qside_lcms), std::fabs(qlong_lcms), kt); + if (hbtanalysis.cfgDo2D) + fRegistryPairMC.fill(HIST("Pair/same/MC/NoLabel/CF_2D"), std::fabs(qout_lcms), std::fabs(qinv), kt); + } else { + fRegistryPairMC.fill(HIST("Pair/same/MC/NoLabel/CF_1D"), hbtanalysis.cfgUseLCMS ? qabs_lcms : qinv, kt); + } + } + + 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 (const auto& collision : collisions) { + initCCDB(collision); + int ndiphoton = 0; + const float cent[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (cent[mixing.cfgCentEstimator] < centralitySelection.cfgCentMin || centralitySelection.cfgCentMax < cent[mixing.cfgCentEstimator]) + continue; + const std::array epArr = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), + collision.ep2fv0a(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg()}; + const float ep2 = epArr[mixing.cfgEP2EstimatorForMix]; + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); + if (!fEMEventCut.IsSelected(collision)) + continue; + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); + fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + const float occupancy = (mixing.cfgOccupancyEstimator == 1) + ? static_cast(collision.trackOccupancyInTimeRange()) + : collision.ft0cOccupancyInTimeRange(); + const float centForQA = cent[mixing.cfgCentEstimator]; + const int zbin = binOf(ztxBinEdges, collision.posZ()), centbin = binOf(centBinEdges, centForQA); + const int epbin = binOf(epBinEgdes, ep2), occbin = binOf(occBinEdges, occupancy); + auto keyBin = std::make_tuple(zbin, centbin, epbin, occbin); + auto keyDFCollision = std::make_pair(ndf, collision.globalIndex()); + auto photons1Coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2Coll = photons2.sliceBy(perCollision2, collision.globalIndex()); + if (qaflags.doSinglePhotonQa) + for (const auto& g : photons1Coll) + if (cut1.template IsSelected(g)) + fillSinglePhotonQAStep<0>(g); + std::unordered_set idsAfterDR, idsAfterRZ, idsAfterEllipse; + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1Coll, photons2Coll))) { + if (!cut1.template IsSelected(g1) || + !cut2.template IsSelected(g2)) + continue; + const auto pos1 = g1.template posTrack_as(), ele1 = g1.template negTrack_as(); + const auto pos2 = g2.template posTrack_as(), ele2 = g2.template negTrack_as(); + if (pos1.trackId() == pos2.trackId() || pos1.trackId() == ele2.trackId() || + ele1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) + continue; + if (!passAsymmetryCut(g1.pt(), g2.pt())) + continue; + auto obs = buildPairQAObservables(g1, g2); + + if (!obs.valid) + continue; + const bool doQA = passQinvQAGate(obs.qinv), doFR = passQinvFullRangeGate(obs.qinv); + if (doQA) + fillPairQAStep<0, 0>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeDeltaRCosOA<0>(obs.qinv, obs.drOverCosOA); + fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), obs.drOverCosOA); + if (obs.drOverCosOA < ggpaircuts.cfgMinDRCosOA) + continue; + idsAfterDR.insert(g1.globalIndex()); + idsAfterDR.insert(g2.globalIndex()); + if (doQA) + fillPairQAStep<0, 1>(obs, centForQA, occupancy); + if (!passRZCut(obs.deltaR, obs.deltaZ)) + continue; + idsAfterRZ.insert(g1.globalIndex()); + idsAfterRZ.insert(g2.globalIndex()); + if (doQA) + fillPairQAStep<0, 2>(obs, centForQA, occupancy); + if (isInsideEllipse(obs.deta, obs.dphi)) + continue; + idsAfterEllipse.insert(g1.globalIndex()); + idsAfterEllipse.insert(g2.globalIndex()); + if (doQA) + fillPairQAStep<0, 3>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeQA<0>(obs, centForQA, occupancy); + fillPairHistogram<0>(collision, obs.v1, obs.v2, 1.f); + ndiphoton++; + fRegistry.fill(HIST("Pair/same/hPhi_lowerPtV0"), + (g1.pt() < g2.pt()) ? g1.phi() : g2.phi()); + + fillEtaTopologyHisto( + classifyEtaTopology(g1.eta(), g2.eta(), + pos1.eta(), ele1.eta(), + pos2.eta(), ele2.eta()), + obs.deta, obs.dphi, obs.kt); + auto addToPool = [&](auto const& g) { + if (usedPhotonIdsPerCol.insert(g.globalIndex()).second) { + EMPair gtmp(g.pt(), g.eta(), g.phi(), 0.f); + gtmp.setConversionPointXYZ(g.vx(), g.vy(), g.vz()); + emh1->AddTrackToEventPool(keyDFCollision, gtmp); + } + }; + addToPool(g1); + addToPool(g2); + } + if (qaflags.doSinglePhotonQa) { + for (const auto& g : photons1Coll) { + if (cut1.template IsSelected(g)) { + const int gid = g.globalIndex(); + if (idsAfterDR.count(gid)) { + fillSinglePhotonQAStep<1>(g); + } + if (idsAfterRZ.count(gid)) { + fillSinglePhotonQAStep<2>(g); + } + if (idsAfterEllipse.count(gid)) { + fillSinglePhotonQAStep<3>(g); + } + } + } + } + usedPhotonIdsPerCol.clear(); + if (!mixing.cfgDoMix || ndiphoton == 0) + continue; + auto selectedPhotons = emh1->GetTracksPerCollision(keyDFCollision); + auto poolIDs = emh1->GetCollisionIdsFromEventPool(keyBin); + for (const auto& mixID : poolIDs) { + if (mixID.second == collision.globalIndex() && mixID.first == ndf) + continue; + const uint64_t bcMix = mapMixedEventIdToGlobalBC[mixID]; + const uint64_t diffBC = std::max(collision.globalBC(), bcMix) - std::min(collision.globalBC(), bcMix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < mixing.ndiffBCMix) + continue; + auto poolPhotons = emh1->GetTracksPerCollision(mixID); + for (const auto& g1 : selectedPhotons) + for (const auto& g2 : poolPhotons) { + if (!passAsymmetryCut(g1.pt(), g2.pt())) + continue; + auto obs = buildPairQAObservables(g1, g2); + if (!obs.valid) + continue; + const bool doQA = passQinvQAGate(obs.qinv), doFR = passQinvFullRangeGate(obs.qinv); + if (doQA) + fillPairQAStep<1, 0>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeDeltaRCosOA<1>(obs.qinv, obs.drOverCosOA); + fRegistry.fill(HIST("Pair/mix/hDeltaRCosOA"), obs.drOverCosOA); + if (obs.drOverCosOA < ggpaircuts.cfgMinDRCosOA) + continue; + if (doQA) + fillPairQAStep<1, 1>(obs, centForQA, occupancy); + if (!passRZCut(obs.deltaR, obs.deltaZ)) + continue; + if (doQA) + fillPairQAStep<1, 2>(obs, centForQA, occupancy); + if (isInsideEllipse(obs.deta, obs.dphi)) + continue; + if (doQA) + fillPairQAStep<1, 3>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeQA<1>(obs, centForQA, occupancy); + fillPairHistogram<1>(collision, obs.v1, obs.v2, 1.f); + fRegistry.fill(HIST("Pair/mix/hPhi_lowerPtV0"), + (g1.pt() < g2.pt()) ? g1.phi() : g2.phi()); + } + } + if (ndiphoton > 0) { + emh1->AddCollisionIdAtLast(keyBin, keyDFCollision); + emh2->AddCollisionIdAtLast(keyBin, keyDFCollision); + mapMixedEventIdToGlobalBC[keyDFCollision] = collision.globalBC(); + } + } + } + + template + void runPairingMC(TCollisions const& collisions, TPhotons const& photons, + TLegs const& /*legs*/, TMCParticles const& mcParticles, + TPreslice const& perCollision, TCut const& cut) + { + for (const auto& collision : collisions) { + initCCDB(collision); + int ndiphoton = 0; + const float cent[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (cent[mixing.cfgCentEstimator] < centralitySelection.cfgCentMin || centralitySelection.cfgCentMax < cent[mixing.cfgCentEstimator]) + continue; + const std::array epArr = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), + collision.ep2fv0a(), collision.ep2btot(), collision.ep2bpos(), collision.ep2bneg()}; + const float ep2 = epArr[mixing.cfgEP2EstimatorForMix]; + fRegistry.fill(HIST("Event/before/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, 1.f); + if (!fEMEventCut.IsSelected(collision)) + continue; + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, 1.f); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0); + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0); + fRegistry.fill(HIST("Event/after/hEP2_CentFT0C_forMix"), collision.centFT0C(), ep2); + const float occupancy = (mixing.cfgOccupancyEstimator == 1) + ? static_cast(collision.trackOccupancyInTimeRange()) + : collision.ft0cOccupancyInTimeRange(); + const float centForQA = cent[mixing.cfgCentEstimator]; + const int zbin = binOf(ztxBinEdges, collision.posZ()), centbin = binOf(centBinEdges, centForQA); + const int epbin = binOf(epBinEgdes, ep2), occbin = binOf(occBinEdges, occupancy); + auto keyBin = std::make_tuple(zbin, centbin, epbin, occbin); + auto keyDFCollision = std::make_pair(ndf, collision.globalIndex()); + auto photonsColl = photons.sliceBy(perCollision, collision.globalIndex()); + if (qaflags.doSinglePhotonQa) + for (const auto& g : photonsColl) + if (cut.template IsSelected(g)) + fillSinglePhotonQAStep<0>(g); + std::unordered_set idsAfterDR, idsAfterRZ, idsAfterEllipse; + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photonsColl, photonsColl))) { + if (!cut.template IsSelected(g1) || !cut.template IsSelected(g2)) + continue; + const auto pos1 = g1.template posTrack_as(), ele1 = g1.template negTrack_as(); + const auto pos2 = g2.template posTrack_as(), ele2 = g2.template negTrack_as(); + if (pos1.trackId() == pos2.trackId() || pos1.trackId() == ele2.trackId() || + ele1.trackId() == pos2.trackId() || ele1.trackId() == ele2.trackId()) + continue; + const auto mc1 = buildPhotonMCInfo(g1, mcParticles); + const auto mc2 = buildPhotonMCInfo(g2, mcParticles); + auto truthType = classifyPairTruth(mc1, mc2); + if (truthType == PairTruthType::TrueTrueDistinct && isPi0DaughterPair(mc1, mc2, mcParticles)) + truthType = PairTruthType::Pi0Daughters; + if (!passAsymmetryCut(g1.pt(), g2.pt())) + continue; + auto obs = buildPairQAObservables(g1, g2); + if (!obs.valid) + continue; + const bool doQA = passQinvQAGate(obs.qinv), doFR = passQinvFullRangeGate(obs.qinv); + if (doQA) + fillPairQAStep<0, 0>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeDeltaRCosOA<0>(obs.qinv, obs.drOverCosOA); + fRegistry.fill(HIST("Pair/same/hDeltaRCosOA"), obs.drOverCosOA); + if (obs.drOverCosOA < ggpaircuts.cfgMinDRCosOA) + continue; + idsAfterDR.insert(g1.globalIndex()); + idsAfterDR.insert(g2.globalIndex()); + if (doQA) + fillPairQAStep<0, 1>(obs, centForQA, occupancy); + if (!passRZCut(obs.deltaR, obs.deltaZ)) + continue; + idsAfterRZ.insert(g1.globalIndex()); + idsAfterRZ.insert(g2.globalIndex()); + if (doQA) + fillPairQAStep<0, 2>(obs, centForQA, occupancy); + if (isInsideEllipse(obs.deta, obs.dphi)) + continue; + idsAfterEllipse.insert(g1.globalIndex()); + idsAfterEllipse.insert(g2.globalIndex()); + if (doQA) + fillPairQAStep<0, 3>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeQA<0>(obs, centForQA, occupancy); + fillPairHistogram<0>(collision, obs.v1, obs.v2, 1.f); + fRegistry.fill(HIST("Pair/same/hPhi_lowerPtV0"), + (g1.pt() < g2.pt()) ? g1.phi() : g2.phi()); + + fillEtaTopologyHisto( + classifyEtaTopology(g1.eta(), g2.eta(), + pos1.eta(), ele1.eta(), + pos2.eta(), ele2.eta()), + obs.deta, obs.dphi, obs.kt); + ndiphoton++; + if (!mc1.hasMC || !mc2.hasMC) { + fillPairHistogramNoLabel(collision, obs.v1, obs.v2); + fRegistryPairMC.fill(HIST("Pair/same/MC/NoLabel/hDEtaDPhi"), obs.deta, obs.dphi); + fRegistryPairMC.fill(HIST("Pair/same/MC/NoLabel/hKt"), obs.kt); + fRegistryPairMC.fill(HIST("Pair/same/MC/NoLabel/hQinv"), obs.qinv); + } else { + const bool doMCQA = passQinvMCQAGate(obs.qinv); + fillMCPairQA(truthType, obs, doQA, doMCQA); + if (doFR) + fillMCPairQAFullRange(truthType, obs); + const bool isTruePair = (truthType == PairTruthType::TrueTrueDistinct || + truthType == PairTruthType::TrueTrueSamePhoton || + truthType == PairTruthType::Pi0Daughters); + if (isTruePair) { + fRegistryPairMC.fill(HIST("Pair/same/MC/hDEtaDPhi_truePairs"), obs.deta, obs.dphi); + if (doMCQA) { + fRegistryPairMC.fill(HIST("Pair/same/MC/hSparse_DEtaDPhi_kT_truePairs"), obs.deta, obs.dphi, obs.kt); + fRegistryPairMC.fill(HIST("Pair/same/MC/hSparse_DEtaDPhi_qinv_truePairs"), obs.deta, obs.dphi, obs.qinv); + } + } else { + fRegistryPairMC.fill(HIST("Pair/same/MC/hDEtaDPhi_fakePairs"), obs.deta, obs.dphi); + if (doMCQA) { + fRegistryPairMC.fill(HIST("Pair/same/MC/hSparse_DEtaDPhi_kT_fakePairs"), obs.deta, obs.dphi, obs.kt); + fRegistryPairMC.fill(HIST("Pair/same/MC/hSparse_DEtaDPhi_qinv_fakePairs"), obs.deta, obs.dphi, obs.qinv); + } + } + + switch (truthType) { + case PairTruthType::TrueTrueDistinct: + fillPairHistogramMC<0, PairTruthType::TrueTrueDistinct>(collision, obs.v1, obs.v2); + break; + case PairTruthType::TrueTrueSamePhoton: + fillPairHistogramMC<0, PairTruthType::TrueTrueSamePhoton>(collision, obs.v1, obs.v2); + break; + case PairTruthType::SharedMcLeg: + fillPairHistogramMC<0, PairTruthType::SharedMcLeg>(collision, obs.v1, obs.v2); + break; + case PairTruthType::TrueFake: + fillPairHistogramMC<0, PairTruthType::TrueFake>(collision, obs.v1, obs.v2); + break; + case PairTruthType::FakeFake: + fillPairHistogramMC<0, PairTruthType::FakeFake>(collision, obs.v1, obs.v2); + break; + case PairTruthType::Pi0Daughters: + fillPairHistogramMC<0, PairTruthType::Pi0Daughters>(collision, obs.v1, obs.v2); + break; + default: + break; + } + } + + auto addToPool = [&](auto const& g) { + if (usedPhotonIdsPerCol.insert(g.globalIndex()).second) { + EMPair gtmp(g.pt(), g.eta(), g.phi(), 0.f); + gtmp.setConversionPointXYZ(g.vx(), g.vy(), g.vz()); + emh1->AddTrackToEventPool(keyDFCollision, gtmp); + } + }; + addToPool(g1); + addToPool(g2); + } + if (qaflags.doSinglePhotonQa) { + for (const auto& g : photonsColl) { + if (cut.template IsSelected(g)) { + const int gid = g.globalIndex(); + if (idsAfterDR.count(gid)) { + fillSinglePhotonQAStep<1>(g); + } + if (idsAfterRZ.count(gid)) { + fillSinglePhotonQAStep<2>(g); + } + if (idsAfterEllipse.count(gid)) { + fillSinglePhotonQAStep<3>(g); + } + } + } + } + usedPhotonIdsPerCol.clear(); + if (!mixing.cfgDoMix || ndiphoton == 0) + continue; + auto selectedPhotons = emh1->GetTracksPerCollision(keyDFCollision); + auto poolIDs = emh1->GetCollisionIdsFromEventPool(keyBin); + for (const auto& mixID : poolIDs) { + if (mixID.second == collision.globalIndex() && mixID.first == ndf) + continue; + const uint64_t bcMix = mapMixedEventIdToGlobalBC[mixID]; + const uint64_t diffBC = std::max(collision.globalBC(), bcMix) - std::min(collision.globalBC(), bcMix); + fRegistry.fill(HIST("Pair/mix/hDiffBC"), diffBC); + if (diffBC < mixing.ndiffBCMix) + continue; + auto poolPhotons = emh1->GetTracksPerCollision(mixID); + for (const auto& g1 : selectedPhotons) + for (const auto& g2 : poolPhotons) { + if (!passAsymmetryCut(g1.pt(), g2.pt())) + continue; + auto obs = buildPairQAObservables(g1, g2); + + if (!obs.valid) + continue; + const bool doQA = passQinvQAGate(obs.qinv), doFR = passQinvFullRangeGate(obs.qinv); + if (doQA) + fillPairQAStep<1, 0>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeDeltaRCosOA<1>(obs.qinv, obs.drOverCosOA); + fRegistry.fill(HIST("Pair/mix/hDeltaRCosOA"), obs.drOverCosOA); + if (obs.drOverCosOA < ggpaircuts.cfgMinDRCosOA) + continue; + if (doQA) + fillPairQAStep<1, 1>(obs, centForQA, occupancy); + if (!passRZCut(obs.deltaR, obs.deltaZ)) + continue; + if (doQA) + fillPairQAStep<1, 2>(obs, centForQA, occupancy); + if (isInsideEllipse(obs.deta, obs.dphi)) + continue; + if (doQA) + fillPairQAStep<1, 3>(obs, centForQA, occupancy); + if (doFR) + fillFullRangeQA<1>(obs, centForQA, occupancy); + fillPairHistogram<1>(collision, obs.v1, obs.v2, 1.f); + fRegistry.fill(HIST("Pair/mix/hPhi_lowerPtV0"), + (g1.pt() < g2.pt()) ? g1.phi() : g2.phi()); + } + } + if (ndiphoton > 0) { + emh1->AddCollisionIdAtLast(keyBin, keyDFCollision); + emh2->AddCollisionIdAtLast(keyBin, keyDFCollision); + mapMixedEventIdToGlobalBC[keyDFCollision] = collision.globalBC(); + } + } + } + template + void runTruthEfficiency(TCollisions const& collisions, + TPhotons const& v0photons, + TLegs const& v0legs, + TMCParticles const& emmcParticles, + TMCEvents const& /*mcEvents*/, + TPresliceMCParts const& perMCCollision, + TPresliceLegs const& perCollisionLegs, + TCut const& cut) + { + auto wrapPhi = [](float dphi) -> float { + return RecoDecay::constrainAngle(dphi, -o2::constants::math::PI); + }; + + std::unordered_set mcIdsWithAnyV0Leg; + mcIdsWithAnyV0Leg.reserve(v0legs.size() * 2); + for (const auto& leg : v0legs) { + if (leg.has_emmcparticle()) + mcIdsWithAnyV0Leg.insert(leg.emmcparticleId()); + } + + for (const auto& collision : collisions) { + if (!fEMEventCut.IsSelected(collision)) + continue; + const float cent[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (cent[mixing.cfgCentEstimator] < centralitySelection.cfgCentMin || + centralitySelection.cfgCentMax < cent[mixing.cfgCentEstimator]) + continue; + if (!collision.has_emmcevent()) + continue; + + const int64_t thisCollisionId = collision.globalIndex(); + const int mcEventId = collision.template emmcevent_as().globalIndex(); + + auto recoPhotonsColl = v0photons.sliceBy(perCollisionPCM, thisCollisionId); + auto emmcPartsColl = emmcParticles.sliceBy(perMCCollision, mcEventId); + auto legsColl = v0legs.sliceBy(perCollisionLegs, thisCollisionId); + + std::unordered_set legIdsThisCollision; + legIdsThisCollision.reserve(legsColl.size()); + for (const auto& leg : legsColl) + if (leg.has_emmcparticle()) + legIdsThisCollision.insert(leg.emmcparticleId()); + + std::unordered_map> crossBuildMap; + + struct PhotonRecoInfo { + bool hasV0 = false, passesCut = false; + }; + std::unordered_map gammaRecoMap; + gammaRecoMap.reserve(recoPhotonsColl.size()); + + for (const auto& g : recoPhotonsColl) { + const auto pos = g.template posTrack_as(); + const auto neg = g.template negTrack_as(); + if (pos.collisionId() != thisCollisionId || neg.collisionId() != thisCollisionId) + continue; + if (!pos.has_emmcparticle() || !neg.has_emmcparticle()) + continue; + const auto mcPos = pos.template emmcparticle_as(); + const auto mcNeg = neg.template emmcparticle_as(); + if (!mcPos.has_mothers() || !mcNeg.has_mothers()) + continue; + const int posMotherId = mcPos.mothersIds()[0], negMotherId = mcNeg.mothersIds()[0]; + if (posMotherId != negMotherId) { + const auto posMother = emmcParticles.iteratorAt(posMotherId); + const auto negMother = emmcParticles.iteratorAt(negMotherId); + if (posMother.pdgCode() == kGamma && negMother.pdgCode() == kGamma) { + crossBuildMap[posMotherId].insert(negMotherId); + crossBuildMap[negMotherId].insert(posMotherId); + } + continue; + } + const int gammaId = posMotherId; + if (emmcParticles.iteratorAt(gammaId).pdgCode() != kGamma) + continue; + const bool passes = cut.template IsSelected, TLegs>(g); + auto& info = gammaRecoMap[gammaId]; + info.hasV0 = true; + info.passesCut = info.passesCut || passes; + } + + // ─── Build true gamma list ──────────────────────────────────────────────── + std::vector trueGammas; + trueGammas.reserve(32); + + for (const auto& g : emmcPartsColl) { + if (g.pdgCode() != kGamma) + continue; + if (!g.isPhysicalPrimary() && !g.producedByGenerator()) + continue; + if (std::fabs(g.eta()) > pcmcuts.cfgMaxEtaV0.value) + continue; + const float mcV0PtMin = (mctruth.cfgMCMinV0Pt.value > 0.f) + ? mctruth.cfgMCMinV0Pt.value + : pcmcuts.cfgMinPtV0.value; + if (g.pt() < mcV0PtMin) + continue; + if (!g.has_daughters()) + continue; + + int posId = -1, negId = -1; + float rTrue = -1.f; + for (const auto& dId : g.daughtersIds()) { + if (dId < 0) { + continue; + } + const auto d = emmcParticles.iteratorAt(dId); + if (d.pdgCode() == kElectron) { + posId = dId; + rTrue = std::sqrt(d.vx() * d.vx() + d.vy() * d.vy()); + } else if (d.pdgCode() == kPositron) { + negId = dId; + } + } + if (posId < 0 || negId < 0) { + continue; + } + + const auto mcPosE = emmcParticles.iteratorAt(posId); + const auto mcNegE = emmcParticles.iteratorAt(negId); + + if (mctruth.cfgMCMinLegPt.value > 0.f && + (static_cast(mcPosE.pt()) < mctruth.cfgMCMinLegPt.value || + static_cast(mcNegE.pt()) < mctruth.cfgMCMinLegPt.value)) + continue; + + const float deTrE = static_cast(mcPosE.eta() - mcNegE.eta()); + const float dpTrE = wrapPhi(static_cast(mcPosE.phi() - mcNegE.phi())); + const float legDRt = std::sqrt(deTrE * deTrE + dpTrE * dpTrE); + + const float pxG = static_cast(g.px()), pyG = static_cast(g.py()), + pzG = static_cast(g.pz()); + const float magG = std::sqrt(pxG * pxG + pyG * pyG + pzG * pzG); + float alphaTrue = 0.f; + if (magG > kMinSigma) { + const float ux = pxG / magG, uy = pyG / magG, uz = pzG / magG; + const float pLpos = static_cast(mcPosE.px()) * ux + + static_cast(mcPosE.py()) * uy + + static_cast(mcPosE.pz()) * uz; + const float pLneg = static_cast(mcNegE.px()) * ux + + static_cast(mcNegE.py()) * uy + + static_cast(mcNegE.pz()) * uz; + const float sumPL = pLpos + pLneg; + if (std::fabs(sumPL) > kMinSigma) + alphaTrue = (pLpos - pLneg) / sumPL; + } + + trueGammas.push_back({static_cast(g.globalIndex()), posId, negId, + static_cast(g.eta()), static_cast(g.phi()), + static_cast(g.pt()), rTrue, legDRt, + deTrE, + dpTrE, + alphaTrue}); + } + + { + int nBad = 0; + for (const auto& tg : trueGammas) { + const auto it = gammaRecoMap.find(tg.id); + if (it != gammaRecoMap.end() && it->second.hasV0 && + (mcIdsWithAnyV0Leg.count(tg.posId) == 0 || mcIdsWithAnyV0Leg.count(tg.negId) == 0)) + ++nBad; + } + fRegistryMC.fill(HIST("MC/TruthAO2D/hStageConsistency"), static_cast(nBad)); + } + + for (const auto& tg : trueGammas) { + const bool posFound = legIdsThisCollision.count(tg.posId) > 0; + const bool negFound = legIdsThisCollision.count(tg.negId) > 0; + const bool bothFound = posFound && negFound; + + for (const auto& [legId, legFound] : + std::initializer_list>{{tg.posId, posFound}, {tg.negId, negFound}}) { + if (legId < 0) + continue; + if (legFound) { + fRegistryMC.fill(HIST("MC/LegDiag/hLegDRtrue_vs_pt_legFound"), tg.pt, tg.legDRtrue); + fRegistryMC.fill(HIST("MC/LegDiag/hLegDEta_legFound_vs_pt"), tg.pt, std::fabs(tg.legDEta)); + fRegistryMC.fill(HIST("MC/LegDiag/hLegDPhi_legFound_vs_pt"), tg.pt, std::fabs(tg.legDPhi)); + } else { + fRegistryMC.fill(HIST("MC/LegDiag/hLegDRtrue_vs_pt_legMissing"), tg.pt, tg.legDRtrue); + fRegistryMC.fill(HIST("MC/LegDiag/hLegDEta_legMissing_vs_pt"), tg.pt, std::fabs(tg.legDEta)); + fRegistryMC.fill(HIST("MC/LegDiag/hLegDPhi_legMissing_vs_pt"), tg.pt, std::fabs(tg.legDPhi)); + } + } + + // ─── Armenteros-α diagnostics per photon ───────────────────────────── + if (bothFound) { + fRegistryMC.fill(HIST("MC/LegDiag/hAlphaTrue_legFound_vs_pt"), tg.pt, tg.alphaTrue); + } else { + // At least one leg missing + fRegistryMC.fill(HIST("MC/LegDiag/hAlphaTrue_legMissing_vs_pt"), tg.pt, tg.alphaTrue); + fRegistryMC.fill(HIST("MC/LegDiag/hAlpha_vs_legDR_legMissing"), tg.legDRtrue, tg.alphaTrue); + } + } + + // ─── Pair loop: efficiency ───────────────────────────────────── + for (size_t i = 0; i < trueGammas.size(); ++i) { + for (size_t j = i + 1; j < trueGammas.size(); ++j) { + const auto& g1 = trueGammas[i]; + const auto& g2 = trueGammas[j]; + const float deta = g1.eta - g2.eta; + const float dphi = wrapPhi(g1.phi - g2.phi); + const float px1 = g1.pt * std::cos(g1.phi), py1 = g1.pt * std::sin(g1.phi); + const float px2 = g2.pt * std::cos(g2.phi), py2 = g2.pt * std::sin(g2.phi); + const float kt = 0.5f * std::sqrt((px1 + px2) * (px1 + px2) + (py1 + py2) * (py1 + py2)); + + if (mctruth.cfgMCMinKt > 0.f && kt < mctruth.cfgMCMinKt) + continue; + if (mctruth.cfgMCMaxKt > 0.f && kt > mctruth.cfgMCMaxKt) + continue; + + const float e1 = g1.pt * std::cosh(g1.eta), e2 = g2.pt * std::cosh(g2.eta); + const float dot = e1 * e2 - (px1 * px2 + py1 * py2 + + g1.pt * std::sinh(g1.eta) * g2.pt * std::sinh(g2.eta)); + const float qinv_true = std::sqrt(std::max(0.f, 2.f * dot)); + + if (mctruth.cfgMCMaxQinv > 0.f && qinv_true > mctruth.cfgMCMaxQinv) + continue; + + auto it1 = gammaRecoMap.find(g1.id), it2 = gammaRecoMap.find(g2.id); + const bool g1Built = (it1 != gammaRecoMap.end()) && it1->second.hasV0; + const bool g2Built = (it2 != gammaRecoMap.end()) && it2->second.hasV0; + const bool g1Sel = (it1 != gammaRecoMap.end()) && it1->second.passesCut; + const bool g2Sel = (it2 != gammaRecoMap.end()) && it2->second.passesCut; + + const bool pairAll4LegsThisColl = + legIdsThisCollision.count(g1.posId) > 0 && legIdsThisCollision.count(g1.negId) > 0 && + legIdsThisCollision.count(g2.posId) > 0 && legIdsThisCollision.count(g2.negId) > 0; + + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_qinv_truthConverted"), deta, dphi, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_kT_truthConverted"), deta, dphi, kt); + fRegistryMC.fill(HIST("MC/TruthAO2D/hQinvVsKt_truthConverted"), kt, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hDEtaDPhi_truthConverted"), deta, dphi); + + if (pairAll4LegsThisColl) { + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_qinv_all4LegsThisColl"), deta, dphi, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_kT_all4LegsThisColl"), deta, dphi, kt); + fRegistryMC.fill(HIST("MC/TruthAO2D/hQinvVsKt_all4LegsThisColl"), kt, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hDEtaDPhi_all4LegsThisColl"), deta, dphi); + } + if (g1Built && g2Built) { + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_qinv_bothPhotonsBuilt"), deta, dphi, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_kT_bothPhotonsBuilt"), deta, dphi, kt); + fRegistryMC.fill(HIST("MC/TruthAO2D/hQinvVsKt_bothPhotonsBuilt"), kt, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hDEtaDPhi_bothPhotonsBuilt"), deta, dphi); + } + if (g1Sel && g2Sel) { + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_qinv_bothPhotonsSelected"), deta, dphi, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hSparse_DEtaDPhi_kT_bothPhotonsSelected"), deta, dphi, kt); + fRegistryMC.fill(HIST("MC/TruthAO2D/hQinvVsKt_bothPhotonsSelected"), kt, qinv_true); + fRegistryMC.fill(HIST("MC/TruthAO2D/hDEtaDPhi_bothPhotonsSelected"), deta, dphi); + } + + if (g1.rTrue >= 0.f && g2.rTrue >= 0.f) { + fRegistryMC.fill(HIST("MC/TruthAO2D/hRconv1_vs_Rconv2_truthConverted"), g1.rTrue, g2.rTrue); + if (g1Sel && g2Sel) + fRegistryMC.fill(HIST("MC/TruthAO2D/hRconv1_vs_Rconv2_bothPhotonsSelected"), g1.rTrue, g2.rTrue); + } + const float minRconv = (g1.rTrue >= 0.f && g2.rTrue >= 0.f) + ? std::min(g1.rTrue, g2.rTrue) + : (g1.rTrue >= 0.f ? g1.rTrue : g2.rTrue); + if (minRconv >= 0.f) { + fRegistryMC.fill(HIST("MC/TruthAO2D/hMinRconv_vs_kT_truthConverted"), kt, minRconv); + if (g1Sel && g2Sel) + fRegistryMC.fill(HIST("MC/TruthAO2D/hMinRconv_vs_kT_bothPhotonsSelected"), kt, minRconv); + } + + fRegistryMC.fill(HIST("MC/TruthAO2D/hStage_vs_kT"), kt, 0.f); + if (pairAll4LegsThisColl) + fRegistryMC.fill(HIST("MC/TruthAO2D/hStage_vs_kT"), kt, 1.f); + if (g1Built && g2Built) + fRegistryMC.fill(HIST("MC/TruthAO2D/hStage_vs_kT"), kt, 2.f); + if (g1Sel && g2Sel) + fRegistryMC.fill(HIST("MC/TruthAO2D/hStage_vs_kT"), kt, 3.f); + + const auto itCB = crossBuildMap.find(g1.id); + if (itCB != crossBuildMap.end() && itCB->second.count(g2.id) > 0) { + fRegistryMC.fill(HIST("MC/PairCrossBuild/hSparse_DEtaDPhi_kT"), deta, dphi, kt); + fRegistryMC.fill(HIST("MC/PairCrossBuild/hStageOut_vs_kT"), + kt, static_cast((g1Built ? 1 : 0) + (g2Built ? 1 : 0))); + } + + const int nLegsThisColl = + (legIdsThisCollision.count(g1.posId) > 0 ? 1 : 0) + + (legIdsThisCollision.count(g1.negId) > 0 ? 1 : 0) + + (legIdsThisCollision.count(g2.posId) > 0 ? 1 : 0) + + (legIdsThisCollision.count(g2.negId) > 0 ? 1 : 0); + fRegistryMC.fill(HIST("MC/LegDiag/hNLegsPair_vs_kT"), kt, static_cast(nLegsThisColl)); + + for (const auto& [tgRef, legId] : + std::initializer_list, int>>{ + {std::cref(g1), g1.posId}, {std::cref(g1), g1.negId}, {std::cref(g2), g2.posId}, {std::cref(g2), g2.negId}}) { + if (legId < 0 || legIdsThisCollision.count(legId) > 0) + continue; + const auto& tg_parent = tgRef.get(); + const float legPtTrue = static_cast(emmcParticles.iteratorAt(legId).pt()); + fRegistryMC.fill(HIST("MC/LegDiag/hMissingLegPt_vs_kT"), kt, legPtTrue); + if (tg_parent.rTrue >= 0.f) + fRegistryMC.fill(HIST("MC/LegDiag/hMissingLegRconv_vs_kT"), kt, tg_parent.rTrue); + } + } + } + + // ─── Truth-level CF mixing ──────────────────────────────────────────────── + if (mctruth.cfgDoTruthMix.value) { + for (size_t i = 0; i < trueGammas.size(); ++i) { + for (size_t j = i + 1; j < trueGammas.size(); ++j) { + const auto& g1 = trueGammas[i]; + const auto& g2 = trueGammas[j]; + if (!passAsymmetryCut(g1.pt, g2.pt)) + continue; + const float deta = g1.eta - g2.eta; + const float dphi = wrapPhi(g1.phi - g2.phi); + const float px1 = g1.pt * std::cos(g1.phi), py1 = g1.pt * std::sin(g1.phi); + const float px2 = g2.pt * std::cos(g2.phi), py2 = g2.pt * std::sin(g2.phi); + const float kt = 0.5f * std::sqrt((px1 + px2) * (px1 + px2) + (py1 + py2) * (py1 + py2)); + const float e1 = g1.pt * std::cosh(g1.eta), e2 = g2.pt * std::cosh(g2.eta); + const float dot = e1 * e2 - (px1 * px2 + py1 * py2 + + g1.pt * std::sinh(g1.eta) * g2.pt * std::sinh(g2.eta)); + const float qinv_true = std::sqrt(std::max(0.f, 2.f * dot)); + fRegistryMC.fill(HIST("MC/TruthCF/hQinvVsKt_same"), kt, qinv_true); + fRegistryMC.fill(HIST("MC/TruthCF/hDEtaDPhi_same"), deta, dphi); + } + } + + const float centForBin = cent[mixing.cfgCentEstimator.value]; + const std::array epArr = {collision.ep2ft0m(), collision.ep2ft0a(), collision.ep2ft0c(), + collision.ep2fv0a(), collision.ep2btot(), collision.ep2bpos(), + collision.ep2bneg()}; + const float ep2 = epArr[mixing.cfgEP2EstimatorForMix.value]; + const float occupancy = (mixing.cfgOccupancyEstimator.value == 1) + ? static_cast(collision.trackOccupancyInTimeRange()) + : collision.ft0cOccupancyInTimeRange(); + auto keyBin = std::make_tuple(binOf(ztxBinEdges, collision.posZ()), + binOf(centBinEdges, centForBin), + binOf(epBinEgdes, ep2), + binOf(occBinEdges, occupancy)); + + if (truthGammaPool.count(keyBin)) { + for (const auto& poolEvent : truthGammaPool[keyBin]) { + for (const auto& g1 : trueGammas) { + for (const auto& g2 : poolEvent) { + if (!passAsymmetryCut(g1.pt, g2.pt)) + continue; + const float deta = g1.eta - g2.eta; + const float dphi = wrapPhi(g1.phi - g2.phi); + const float px1 = g1.pt * std::cos(g1.phi), py1 = g1.pt * std::sin(g1.phi); + const float px2 = g2.pt * std::cos(g2.phi), py2 = g2.pt * std::sin(g2.phi); + const float kt = 0.5f * std::sqrt((px1 + px2) * (px1 + px2) + (py1 + py2) * (py1 + py2)); + const float e1 = g1.pt * std::cosh(g1.eta), e2 = g2.pt * std::cosh(g2.eta); + const float dot = e1 * e2 - (px1 * px2 + py1 * py2 + + g1.pt * std::sinh(g1.eta) * g2.pt * std::sinh(g2.eta)); + const float qinv_true = std::sqrt(std::max(0.f, 2.f * dot)); + fRegistryMC.fill(HIST("MC/TruthCF/hQinvVsKt_mix"), kt, qinv_true); + fRegistryMC.fill(HIST("MC/TruthCF/hDEtaDPhi_mix"), deta, dphi); + } + } + } + } + + if (!trueGammas.empty()) { + auto& poolBin = truthGammaPool[keyBin]; + poolBin.push_back(trueGammas); + if (static_cast(poolBin.size()) > mctruth.cfgTruthMixDepth.value) + poolBin.pop_front(); + } + } // end cfgDoTruthMix + } // end collision loop + } // end runTruthEfficiency + + using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler< + std::tuple, std::pair, EMPair>; + + MyEMH* emh1 = nullptr; + MyEMH* emh2 = nullptr; + std::unordered_set usedPhotonIdsPerCol; + std::map, uint64_t> mapMixedEventIdToGlobalBC; + + SliceCache cache; + Preslice perCollisionPCM = aod::v0photonkf::pmeventId; + PresliceUnsorted perCollisionV0Legs = aod::v0leg::collisionId; + PresliceUnsorted perMCCollisionEMMCParts = aod::emmcparticle::emmceventId; + + Filter collisionFilterCentrality = + (centralitySelection.cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < centralitySelection.cfgCentMax) || + (centralitySelection.cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < centralitySelection.cfgCentMax) || + (centralitySelection.cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < centralitySelection.cfgCentMax); + Filter collisionFilterOccupancyTrack = + eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && + o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilterOccupancyFT0c = + eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && + o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + + using FilteredMyCollisions = soa::Filtered; + int ndf = 0; + + void processAnalysis(FilteredMyCollisions const& collisions, + MyV0Photons const& v0photons, + aod::V0Legs const& v0legs) + { + runPairing(collisions, v0photons, v0photons, v0legs, v0legs, + perCollisionPCM, perCollisionPCM, fV0PhotonCut, fV0PhotonCut); + ndf++; + } + PROCESS_SWITCH(Photonhbt, processAnalysis, "pairing for analysis", true); + + void processMC(FilteredMyCollisions const& collisions, + MyV0Photons const& v0photons, + MyMCV0Legs const& v0legs, + aod::EMMCParticles const& mcParticles, + aod::EMMCEvents const& mcEvents) + { + + runPairingMC(collisions, v0photons, v0legs, mcParticles, + perCollisionPCM, fV0PhotonCut); + runTruthEfficiency(collisions, v0photons, v0legs, mcParticles, mcEvents, + perMCCollisionEMMCParts, perCollisionV0Legs, fV0PhotonCut); + + ndf++; + } + PROCESS_SWITCH(Photonhbt, processMC, "MC CF + truth efficiency maps for CF correction", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx index cfaa5371cac..4072a74e096 100644 --- a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" @@ -43,7 +44,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include @@ -59,13 +60,13 @@ using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photonmeson::photonpair; -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; struct prefilterPhoton { @@ -389,8 +390,8 @@ struct prefilterPhoton { } auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); if (!fEMEventCut.IsSelected(collision) || !is_cent_ok) { for (const auto& photon1 : photons1_per_collision) { @@ -537,8 +538,8 @@ struct prefilterPhoton { } auto photons1_per_collision = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); - auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectron::emeventId, collision.globalIndex(), cache); + auto positrons_per_collision = posTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); + auto electrons_per_collision = negTracks->sliceByCached(o2::aod::emprimaryelectronda::pmeventId, collision.globalIndex(), cache); for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_per_collision, photons1_per_collision))) { if (!cut1.template IsSelected(g1) || !cut1.template IsSelected(g2)) { @@ -600,8 +601,8 @@ struct prefilterPhoton { std::unordered_map map_pfb_ele; // map ele.globalIndex -> prefilter bit SliceCache cache; - Preslice perCollision_v0 = aod::v0photonkf::emeventId; - Preslice perCollision_electron = aod::emprimaryelectron::emeventId; + Preslice perCollision_v0 = aod::v0photonkf::pmeventId; + Preslice perCollision_electron = aod::emprimaryelectronda::pmeventId; 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_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; diff --git a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx index 10731a2de42..f7c5484084c 100644 --- a/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskFlowReso.cxx @@ -14,6 +14,7 @@ /// \author M. Hemmer, marvin.hemmer@cern.ch #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -118,7 +119,7 @@ struct TaskFlowReso { SliceCache cache; EventPlaneHelper epHelper; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using CollWithQvec = CollsWithQvecs::iterator; static constexpr std::size_t NQVecEntries = 6; diff --git a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx index 517c514987e..a6a6375cb4c 100644 --- a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx @@ -17,6 +17,7 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/GammaTablesRedux.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" @@ -49,7 +50,7 @@ #include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include #include @@ -59,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -111,8 +111,6 @@ enum class MapLevel { }; struct TaskPi0FlowEMC { - static constexpr float MinEnergy = 0.7f; - // configurable for flow Configurable harmonic{"harmonic", 2, "harmonic number"}; Configurable qvecDetector{"qvecDetector", 0, "Detector for Q vector estimation (FT0M: 0, FT0A: 1, FT0C: 2, TPC Pos: 3, TPC Neg: 4, TPC Tot: 5, FV0A: 6)"}; @@ -120,14 +118,10 @@ struct TaskPi0FlowEMC { Configurable qvecSubBDetector{"qvecSubBDetector", 4, "Sub B Detector for Q vector estimation for resolution (FT0M: 0, FT0A: 1, FT0C: 2, TPC Pos: 3, TPC Neg: 4, TPC Tot: 5, FV0A: 6)"}; Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3)"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable cfgDoRotation{"cfgDoRotation", false, "Flag to enable rotation background method"}; - Configurable cfgDownsampling{"cfgDownsampling", 1, "Calculate rotation background only for every collision"}; - Configurable cfgEMCalMapLevelBackground{"cfgEMCalMapLevelBackground", 4, "Different levels of correction for the background, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: exclude bad channels, 1: remove edges)"}; - Configurable cfgEMCalMapLevelSameEvent{"cfgEMCalMapLevelSameEvent", 4, "Different levels of correction for the same event, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: exclude bad channels, 1: remove edges)"}; - Configurable cfgRotAngle{"cfgRotAngle", std::move(const_cast(o2::constants::math::PIHalf)), "Angle used for the rotation method"}; + Configurable cfgEMCalMapLevelBackground{"cfgEMCalMapLevelBackground", 4, "Different levels of correction for the background, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: remove edges, 1: exclude bad channels)"}; + Configurable cfgEMCalMapLevelSameEvent{"cfgEMCalMapLevelSameEvent", 4, "Different levels of correction for the same event, the smaller number includes the level of the higher number (4: none, 3: only inside EMCal, 2: remove edges, 1: exclude bad channels)"}; Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; Configurable cfgDoM02{"cfgDoM02", false, "Flag to enable flow vs M02 for single photons"}; - Configurable cfgDoReverseScaling{"cfgDoReverseScaling", false, "Flag to reverse the scaling that is possibly applied during NonLin"}; Configurable cfgDoPlaneQA{"cfgDoPlaneQA", false, "Flag to enable QA plots comparing in and out of plane"}; Configurable cfgMaxQVector{"cfgMaxQVector", 20.f, "Maximum allowed absolute QVector value."}; Configurable cfgMaxAsymmetry{"cfgMaxAsymmetry", 0.1f, "Maximum allowed asymmetry for photon pairs used in calibration."}; @@ -215,6 +209,7 @@ struct TaskPi0FlowEMC { o2::framework::Configurable maxTPCNSigmaEl{"maxTPCNSigmaEl", +3.0f, "max. TPC n sigma for electron"}; o2::framework::Configurable disableITSOnly{"disableITSOnly", false, "flag to disable ITSonly tracks"}; o2::framework::Configurable disableTPCOnly{"disableTPCOnly", false, "flag to disable TPConly tracks"}; + o2::framework::Configurable doQA{"doQA", false, "flag to set QA flag."}; } pcmcuts; struct : ConfigurableGroup { @@ -236,6 +231,14 @@ struct TaskPi0FlowEMC { Configurable cfgMixingDepth{"cfgMixingDepth", 2, "Mixing depth"}; } mixingConfig; + struct : ConfigurableGroup { + std::string prefix = "rotationConfig"; + Configurable cfgDoRotation{"cfgDoRotation", false, "Flag to enable rotation background method."}; + Configurable cfgDownsampling{"cfgDownsampling", 1, "Calculate rotation background only for every collision."}; + Configurable cfgRotAngle{"cfgRotAngle", std::move(const_cast(o2::constants::math::PIHalf)), "Angle used for the rotation method."}; + Configurable cfgUseWeights{"cfgUseWeights", false, "Flag to enable weights for rotation background method."}; + } rotationConfig; + struct : ConfigurableGroup { std::string prefix = "correctionConfig"; Configurable cfgSpresoPath{"cfgSpresoPath", "Users/m/mhemmer/EM/Flow/Resolution", "Path to SP resolution file"}; @@ -253,16 +256,16 @@ struct TaskPi0FlowEMC { // Filter clusterFilter = aod::skimmedcluster::time >= emccuts.cfgEMCminTime && aod::skimmedcluster::time <= emccuts.cfgEMCmaxTime && aod::skimmedcluster::m02 >= emccuts.cfgEMCminM02 && aod::skimmedcluster::m02 <= emccuts.cfgEMCmaxM02 && aod::skimmedcluster::e >= emccuts.cfgEMCminE; Filter collisionFilter = (nabs(aod::collision::posZ) <= eventcuts.cfgZvtxMax) && (aod::evsel::ft0cOccupancyInTimeRange <= eventcuts.cfgFT0COccupancyMax) && (aod::evsel::ft0cOccupancyInTimeRange >= eventcuts.cfgFT0COccupancyMin); // using FilteredEMCalPhotons = soa::Filtered>; - using EMCalPhotons = soa::Join; - using PCMPhotons = soa::Join; - using FilteredCollsWithQvecs = soa::Filtered>; - using CollsWithQvecs = soa::Join; - using Colls = soa::Join; + using EMCalPhotons = soa::Join; + using PCMPhotons = soa::Join; + using FilteredCollsWithQvecs = soa::Filtered>; + using CollsWithQvecs = soa::Join; + using Colls = soa::Join; static constexpr std::size_t NQVecEntries = 6; - PresliceOptional perCollisionEMC = o2::aod::emccluster::emeventId; - PresliceOptional perCollisionPCM = aod::v0photonkf::emeventId; + PresliceOptional perCollisionEMC = o2::aod::emccluster::pmeventId; + PresliceOptional perCollisionPCM = aod::v0photonkf::pmeventId; PresliceOptional perEMCClusterMT = o2::aod::mintm::minClusterId; PresliceOptional perEMCClusterMS = o2::aod::mintm::minClusterId; @@ -282,15 +285,12 @@ struct TaskPi0FlowEMC { float epsilon = 1.e-8; // static constexpr - static constexpr int64_t NMinPhotonRotBkg = 3; + static constexpr int8_t NMinPhotonRotBkg = 3; - // Usage when cfgEnableNonLin is enabled - std::unique_ptr fEMCalCorrectionFactor; // ("fEMCalCorrectionFactor","(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); - float energyCorrectionFactor = 1.f; uint8_t nColl = 1; // To access the 1D array - inline int getIndex(int iEta, int iPhi) + static inline int getIndex(int iEta, int iPhi) { return iEta * NBinsPhi + iPhi; } @@ -343,6 +343,7 @@ struct TaskPi0FlowEMC { fEMCCut.SetClusterizer(emccuts.clusterDefinition); fEMCCut.SetUseTM(emccuts.cfgEMCUseTM.value); // disables or enables TM fEMCCut.SetUseSecondaryTM(emccuts.emcUseSecondaryTM.value); // disables or enables secondary TM + fEMCCut.SetDoQA(emccuts.cfgEnableQA.value); } void definePCMCut() @@ -374,6 +375,8 @@ struct TaskPi0FlowEMC { fV0PhotonCut.SetRequireITSTPC(pcmcuts.requireV0WithITSTPC); fV0PhotonCut.SetRequireITSonly(pcmcuts.requireV0WithITSOnly); fV0PhotonCut.SetRequireTPConly(pcmcuts.requireV0WithTPCOnly); + + fV0PhotonCut.setDoQA(pcmcuts.doQA.value); } void init(InitContext&) @@ -384,7 +387,9 @@ struct TaskPi0FlowEMC { defineEMEventCut(); defineEMCCut(); + fEMCCut.addQAHistograms(®istry); definePCMCut(); + fV0PhotonCut.addQAHistograms(®istry); o2::aod::pwgem::photonmeson::utils::eventhistogram::addEventHistograms(®istry); const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, "#it{M}_{#gamma#gamma} (GeV/#it{c}^{2})"}; @@ -410,7 +415,7 @@ struct TaskPi0FlowEMC { registry.add("hSparseBkgMixFlow", " vs m_{inv} vs p_T vs cent for mixed event", HistType::kTProfile3D, {thnAxisInvMass, thnAxisPt, thnAxisCent}); registry.add("hSparseBkgMix", "m_{inv} vs p_T vs cent for mixed event", HistType::kTH3D, {thnAxisInvMass, thnAxisPt, thnAxisCent}); - if (cfgDoRotation.value) { + if (rotationConfig.cfgDoRotation.value) { registry.add("hSparseBkgRotFlow", " vs m_{inv} vs p_T vs cent for rotation background", HistType::kTProfile3D, {thnAxisInvMass, thnAxisPt, thnAxisCent}); registry.add("hSparseBkgRot", "m_{inv} vs p_T vs cent for rotation background", HistType::kTH3D, {thnAxisInvMass, thnAxisPt, thnAxisCent}); } @@ -440,7 +445,7 @@ struct TaskPi0FlowEMC { registry.add("clusterQA/hEClusterAfter", "Histo for cluster energy after cuts", HistType::kTH1D, {thAxisClusterEnergy}); registry.add("clusterQA/hClusterEtaPhiBefore", "hClusterEtaPhiBefore", HistType::kTH2D, {thAxisPhi, thAxisEta}); registry.add("clusterQA/hClusterEtaPhiAfter", "hClusterEtaPhiAfter", HistType::kTH2D, {thAxisPhi, thAxisEta}); - if (cfgDoRotation.value) { + if (rotationConfig.cfgDoRotation.value) { registry.add("clusterQA/hClusterBackEtaPhiBefore", "hClusterBackEtaPhiBefore", HistType::kTH2D, {thAxisPhi, thAxisEta}); registry.add("clusterQA/hClusterBackEtaPhiAfter", "hClusterBackEtaPhiAfter", HistType::kTH2D, {thAxisPhi, thAxisEta}); } @@ -473,14 +478,12 @@ struct TaskPi0FlowEMC { LOG(info) << "thnConfigAxisInvMass.value[1] = " << thnConfigAxisInvMass.value[1] << " thnConfigAxisInvMass.value.back() = " << thnConfigAxisInvMass.value.back(); LOG(info) << "thnConfigAxisPt.value[1] = " << thnConfigAxisPt.value[1] << " thnConfigAxisPt.value.back() = " << thnConfigAxisPt.value.back(); - fEMCalCorrectionFactor = std::make_unique("fEMCalCorrectionFactor", "(1 + [0]/x + [1]/x^2) / (1 + [2]/x)", 0.3, 100.); - fEMCalCorrectionFactor->SetParameters(-5.33426e-01, 1.40144e-02, -5.24434e-01); }; // end init /// Change radians to degree /// \param angle in radians /// \return angle in degree - constexpr float getAngleDegree(float angle) + static constexpr float getAngleDegree(float angle) { return angle * o2::constants::math::Rad2Deg; } @@ -733,20 +736,24 @@ struct TaskPi0FlowEMC { } /// \brief Calculate background using rotation background method - 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, TCollision const& collision) + template + void rotationBackground(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photonsColl, unsigned int ig1, unsigned int ig2, TCollision const& collision) { // if less than 3 clusters are present skip event since we need at least 3 clusters - if (photons_coll.size() < NMinPhotonRotBkg) { + if (photonsColl.size() < NMinPhotonRotBkg) { return; } + float weight = 1.f; + if (rotationConfig.cfgUseWeights) { + weight = 1.f / (2.f * static_cast(photonsColl.size() - 2)); + } auto [xQVec, yQVec] = getQvec(collision, qvecDetector); float cent = getCentrality(collision); int iCellIDPhoton1 = 0; int iCellIDPhoton2 = 0; - ROOT::Math::AxisAngle rotationAxis(meson.Vect(), cfgRotAngle.value); + ROOT::Math::AxisAngle rotationAxis(meson.Vect(), rotationConfig.cfgRotAngle); ROOT::Math::Rotation3D rotationMatrix(rotationAxis); photon1 = rotationMatrix * photon1; photon2 = rotationMatrix * photon2; @@ -769,7 +776,7 @@ struct TaskPi0FlowEMC { if (iCellIDPhoton1 == -1 && iCellIDPhoton2 == -1) { return; } - for (const auto& photon : photons_coll) { + for (const auto& photon : photonsColl) { if (photon.globalIndex() == ig1 || photon.globalIndex() == ig2) { // only combine rotated photons with other photons continue; @@ -780,11 +787,7 @@ struct TaskPi0FlowEMC { if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { continue; } - float energyCorrectionFactor = 1.f; - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(photon.e() > MinEnergy ? photon.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector photon3(energyCorrectionFactor * photon.pt(), photon.eta(), photon.phi(), 0.); + ROOT::Math::PtEtaPhiMVector photon3(photon.corrPt(), photon.eta(), photon.phi(), 0.); if (iCellIDPhoton1 >= 0) { ROOT::Math::PtEtaPhiMVector mother1 = photon1 + photon3; float openingAngle1 = std::acos(photon1.Vect().Dot(photon3.Vect()) / (photon1.P() * photon3.P())); @@ -797,128 +800,157 @@ struct TaskPi0FlowEMC { } if (openingAngle1 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { - if (mesonConfig.enableTanThetadPhi) { + if (mesonConfig.enableTanThetadPhi.value) { float dTheta = photon1.Theta() - photon3.Theta(); float dPhi = photon1.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseBkgRotFlow"), mother1.M(), mother1.Pt(), cent, scalprodCand1); - registry.fill(HIST("hSparseBkgRot"), mother1.M(), mother1.Pt(), cent); + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + continue; } - } else { - registry.fill(HIST("hSparseBkgRotFlow"), mother1.M(), mother1.Pt(), cent, scalprodCand1); - registry.fill(HIST("hSparseBkgRot"), mother1.M(), mother1.Pt(), cent); } + registry.fill(HIST("hSparseBkgRotFlow"), mother1.M(), mother1.Pt(), cent, scalprodCand1, weight); + registry.fill(HIST("hSparseBkgRot"), mother1.M(), mother1.Pt(), cent, weight); } - } - if (iCellIDPhoton2 >= 0) { - ROOT::Math::PtEtaPhiMVector mother2 = photon2 + photon3; - float openingAngle2 = std::acos(photon2.Vect().Dot(photon3.Vect()) / (photon2.P() * photon3.P())); - float cosNPhi2 = std::cos(harmonic * mother2.Phi()); - float sinNPhi2 = std::sin(harmonic * mother2.Phi()); - float scalprodCand2 = cosNPhi2 * xQVec + sinNPhi2 * yQVec; + if (iCellIDPhoton2 >= 0) { + ROOT::Math::PtEtaPhiMVector mother2 = photon2 + photon3; + float openingAngle2 = std::acos(photon2.Vect().Dot(photon3.Vect()) / (photon2.P() * photon3.P())); + float cosNPhi2 = std::cos(harmonic * mother2.Phi()); + float sinNPhi2 = std::sin(harmonic * mother2.Phi()); + float scalprodCand2 = cosNPhi2 * xQVec + sinNPhi2 * yQVec; - if (correctionConfig.cfgApplySPresolution.value) { - scalprodCand2 = scalprodCand2 / h1SPResolution->GetBinContent(h1SPResolution->FindBin(cent + epsilon)); - } + if (correctionConfig.cfgApplySPresolution.value) { + scalprodCand2 = scalprodCand2 / h1SPResolution->GetBinContent(h1SPResolution->FindBin(cent + epsilon)); + } - if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother2.M() && thnConfigAxisInvMass.value.back() >= mother2.M() && thnConfigAxisPt.value[1] <= mother2.Pt() && thnConfigAxisPt.value.back() >= mother2.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon2.Theta() - photon3.Theta(); - float dPhi = photon2.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseBkgRotFlow"), mother2.M(), mother2.Pt(), cent, scalprodCand2); - registry.fill(HIST("hSparseBkgRot"), mother2.M(), mother2.Pt(), cent); + if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother2.M() && thnConfigAxisInvMass.value.back() >= mother2.M() && thnConfigAxisPt.value[1] <= mother2.Pt() && thnConfigAxisPt.value.back() >= mother2.Pt()) { + if (mesonConfig.enableTanThetadPhi.value) { + float dTheta = photon2.Theta() - photon3.Theta(); + float dPhi = photon2.Phi() - photon3.Phi(); + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + continue; + } } - } else { - registry.fill(HIST("hSparseBkgRotFlow"), mother2.M(), mother2.Pt(), cent, scalprodCand2); - registry.fill(HIST("hSparseBkgRot"), mother2.M(), mother2.Pt(), cent); + registry.fill(HIST("hSparseBkgRotFlow"), mother2.M(), mother2.Pt(), cent, scalprodCand2, weight); + registry.fill(HIST("hSparseBkgRot"), mother2.M(), mother2.Pt(), cent, weight); } - } + } // end of loop over third photon } - } // end of loop over third photon + } return; } - /// \brief Calculate background using rotation background method for calib - template - void rotationBackgroundCalib(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photons_coll, unsigned int ig1, unsigned int ig2, TCollision const& collision) + /// \brief Calculate background using rotation background method + /// \param meson meson candidate whos momentum is used as rotation axis + /// \param photonPCM first photon candidate (PCM) + /// \param photonEMC second photon candidate (EMC) + /// \param photonsCollPCM subtable of current collisions PCM photons + /// \param photonsCollEMC subtable of current collisions EMCal photons + /// \param giPCM global index of photonPCM + /// \param giEMC global index of photonEMC + /// \param collision current collision iterator + template + void rotationBackgroundPCMEMC(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photonPCM, ROOT::Math::PtEtaPhiMVector photonEMC, TPCMPhotons const& photonsCollPCM, TEMCPhotons const& photonsCollEMC, unsigned int giPCM, unsigned int giEMC, TCollision const& collision) { - // if less than 3 clusters are present skip event since we need at least 3 clusters - if (photons_coll.size() < NMinPhotonRotBkg) { + // if less than 3 photon candidates are present skip event since we need at least 3 candidates + if ((photonsCollEMC.size() + photonsCollPCM.size()) < NMinPhotonRotBkg) { return; } + float weight = 1.f; + if (rotationConfig.cfgUseWeights) { + weight = 1.f / static_cast(photonsCollPCM.size() + photonsCollEMC.size() - 2); + } + + auto [xQVec, yQVec] = getQvec(collision, qvecDetector); float cent = getCentrality(collision); - int iCellIDPhoton1 = 0; - int iCellIDPhoton2 = 0; + int iCellIDphotonPCM = 0; + int iCellIDphotonEMC = 0; - ROOT::Math::AxisAngle rotationAxis(meson.Vect(), cfgRotAngle.value); + ROOT::Math::AxisAngle rotationAxis(meson.Vect(), rotationConfig.cfgRotAngle); ROOT::Math::Rotation3D rotationMatrix(rotationAxis); - photon1 = rotationMatrix * photon1; - photon2 = rotationMatrix * photon2; + photonPCM = rotationMatrix * photonPCM; + photonEMC = rotationMatrix * photonEMC; - if (checkEtaPhi1D(photon1.Eta(), RecoDecay::constrainAngle(photon1.Phi())) >= cfgEMCalMapLevelBackground.value) { - iCellIDPhoton1 = -1; - } - if (checkEtaPhi1D(photon2.Eta(), RecoDecay::constrainAngle(photon2.Phi())) >= cfgEMCalMapLevelBackground.value) { - iCellIDPhoton2 = -1; + if (emccuts.cfgEnableQA.value) { + registry.fill(HIST("clusterQA/hClusterBackEtaPhiBefore"), RecoDecay::constrainAngle(photonEMC.Phi()), photonEMC.Eta()); // before check but after rotation } - if (iCellIDPhoton1 == -1 && iCellIDPhoton2 == -1) { + if (photonPCM.Eta() < pcmcuts.minEtaV0 || photonPCM.Eta() > pcmcuts.maxEtaV0) { + iCellIDphotonPCM = -1; + } + if (checkEtaPhi1D(photonEMC.Eta(), RecoDecay::constrainAngle(photonEMC.Phi())) >= cfgEMCalMapLevelBackground.value) { + iCellIDphotonEMC = -1; + } else if (emccuts.cfgEnableQA.value) { + registry.fill(HIST("clusterQA/hClusterBackEtaPhiAfter"), RecoDecay::constrainAngle(photonEMC.Phi()), photonEMC.Eta()); // after check + } + if (iCellIDphotonPCM == -1 && iCellIDphotonEMC == -1) { return; } - for (const auto& photon : photons_coll) { - if (photon.globalIndex() == ig1 || photon.globalIndex() == ig2) { - // only combine rotated photons with other photons - continue; - } - if (!(fEMCCut.IsSelected(photon))) { - continue; - } - if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { - continue; - } - float energyCorrectionFactor = 1.f; - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(photon.e() > MinEnergy ? photon.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector photon3(energyCorrectionFactor * photon.pt(), photon.eta(), photon.phi(), 0.); - if (iCellIDPhoton1 >= 0) { - if (std::fabs((photon1.E() - photon3.E()) / (photon1.E() + photon3.E()) < cfgMaxAsymmetry)) { // only use symmetric decays - ROOT::Math::PtEtaPhiMVector mother1 = photon1 + photon3; - float openingAngle1 = std::acos(photon1.Vect().Dot(photon3.Vect()) / (photon1.P() * photon3.P())); - - if (openingAngle1 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon1.Theta() - photon3.Theta(); - float dPhi = photon1.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseCalibBack"), mother1.M(), mother1.E() / 2., cent); - } - } else { - registry.fill(HIST("hSparseCalibBack"), mother1.M(), mother1.E() / 2., cent); + if (iCellIDphotonPCM > -1) { + for (const auto& photon : photonsCollEMC) { + if (photon.globalIndex() == giEMC) { + // only combine rotated photons with other photons + continue; + } + if (!(fEMCCut.IsSelected(photon))) { + continue; + } + if (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelBackground.value) { + continue; + } + ROOT::Math::PtEtaPhiMVector photon3(photon.corrPt(), photon.eta(), photon.phi(), 0.); + ROOT::Math::PtEtaPhiMVector mother1 = photonPCM + photon3; + float openingAngle = std::acos(photonPCM.Vect().Dot(photon3.Vect()) / (photonPCM.P() * photon3.P())); + float cosNPhi = std::cos(harmonic * mother1.Phi()); + float sinNPhi = std::sin(harmonic * mother1.Phi()); + float scalprodCand = cosNPhi * xQVec + sinNPhi * yQVec; + + if (correctionConfig.cfgApplySPresolution.value) { + scalprodCand = scalprodCand / h1SPResolution->GetBinContent(h1SPResolution->FindBin(cent + epsilon)); + } + if (openingAngle > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { + if (mesonConfig.enableTanThetadPhi.value) { + float dTheta = photonPCM.Theta() - photon3.Theta(); + float dPhi = photonPCM.Phi() - photon3.Phi(); + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + continue; } } + registry.fill(HIST("hSparseBkgRotFlow"), mother1.M(), mother1.Pt(), cent, scalprodCand, weight); + registry.fill(HIST("hSparseBkgRot"), mother1.M(), mother1.Pt(), cent, weight); } - } - if (iCellIDPhoton2 >= 0) { - if (std::fabs((photon2.E() - photon3.E()) / (photon2.E() + photon3.E()) < cfgMaxAsymmetry)) { // only use symmetric decays - ROOT::Math::PtEtaPhiMVector mother2 = photon2 + photon3; - float openingAngle2 = std::acos(photon2.Vect().Dot(photon3.Vect()) / (photon2.P() * photon3.P())); + } // end of loop over EMC photons + } // if(iCellIDphotonPCM > -1) + if (iCellIDphotonEMC > -1) { + for (const auto& photon : photonsCollPCM) { + if (photon.globalIndex() == giPCM) { + // only combine rotated photons with other photons + continue; + } + if (!(fV0PhotonCut.IsSelected(photon))) { + continue; + } + ROOT::Math::PtEtaPhiMVector photon3(photon.pt(), photon.eta(), photon.phi(), 0.); + ROOT::Math::PtEtaPhiMVector mother1 = photonEMC + photon3; + float openingAngle = std::acos(photonEMC.Vect().Dot(photon3.Vect()) / (photonEMC.P() * photon3.P())); + float cosNPhi = std::cos(harmonic * mother1.Phi()); + float sinNPhi = std::sin(harmonic * mother1.Phi()); + float scalprodCand = cosNPhi * xQVec + sinNPhi * yQVec; - if (openingAngle2 > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother2.M() && thnConfigAxisInvMass.value.back() >= mother2.M() && thnConfigAxisPt.value[1] <= mother2.Pt() && thnConfigAxisPt.value.back() >= mother2.Pt()) { - if (mesonConfig.enableTanThetadPhi) { - float dTheta = photon2.Theta() - photon3.Theta(); - float dPhi = photon2.Phi() - photon3.Phi(); - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { - registry.fill(HIST("hSparseCalibBack"), mother2.M(), mother2.E() / 2., cent); - } - } else { - registry.fill(HIST("hSparseCalibBack"), mother2.M(), mother2.E() / 2., cent); + if (correctionConfig.cfgApplySPresolution.value) { + scalprodCand = scalprodCand / h1SPResolution->GetBinContent(h1SPResolution->FindBin(cent + epsilon)); + } + if (openingAngle > mesonConfig.minOpenAngle && thnConfigAxisInvMass.value[1] <= mother1.M() && thnConfigAxisInvMass.value.back() >= mother1.M() && thnConfigAxisPt.value[1] <= mother1.Pt() && thnConfigAxisPt.value.back() >= mother1.Pt()) { + if (mesonConfig.enableTanThetadPhi.value) { + float dTheta = photonEMC.Theta() - photon3.Theta(); + float dPhi = photonEMC.Phi() - photon3.Phi(); + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi <= std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + continue; } } + registry.fill(HIST("hSparseBkgRotFlow"), mother1.M(), mother1.Pt(), cent, scalprodCand, weight); + registry.fill(HIST("hSparseBkgRot"), mother1.M(), mother1.Pt(), cent, weight); } - } - } // end of loop over third photon + } // end of loop over PCM photons + } // if(iCellIDphotonEMC > -1) return; } @@ -956,7 +988,7 @@ struct TaskPi0FlowEMC { /// \brief check if standard event cuts + FT0 occupancy + centrality + QVec good is /// \param collision collision that will be checked /// \return true if collision survives all checks, otherwise false - template + template bool isFullEventSelected(TCollision const& collision, bool fillHisto = false) { if (fillHisto) { @@ -987,7 +1019,7 @@ struct TaskPi0FlowEMC { return true; } - template + template void runPairingLoop(TCollision const& collision, TPhotons1 const& photons1, TPhotons2 const& photons2, EMBitFlags const& flags1, EMBitFlags const& flags2) { for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1, photons2))) { @@ -1004,15 +1036,8 @@ struct TaskPi0FlowEMC { continue; } } - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - } - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); - } - - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1024,7 +1049,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("hMesonCuts"), 2); continue; } - if (cfgDoRotation && nColl % cfgDownsampling.value == 0) { + if (rotationConfig.cfgDoRotation.value && nColl % rotationConfig.cfgDownsampling == 0) { rotationBackground(vMeson, v1, v2, photons1, g1.globalIndex(), g2.globalIndex(), collision); } if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { @@ -1040,7 +1065,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCuts"), 5); continue; } @@ -1052,15 +1077,16 @@ struct TaskPi0FlowEMC { // Pi0 from EMCal void processEMCal(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { + if (clusters.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } EMBitFlags flags(clusters.size()); - fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds); + fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds, ®istry); - if (cfgDoReverseScaling.value) { - energyCorrectionFactor = 1.0505f; - } for (const auto& collision : collisions) { - if (!isFullEventSelected(collision)) { + if (!isFullEventSelected(collision, true)) { continue; } runNow = collision.runNumber(); @@ -1073,7 +1099,7 @@ struct TaskPi0FlowEMC { if (emccuts.cfgEnableQA.value) { for (const auto& photon : photonsPerCollision) { - registry.fill(HIST("clusterQA/hEClusterBefore"), photon.e()); // before cuts + registry.fill(HIST("clusterQA/hEClusterBefore"), photon.corrE()); // before cuts registry.fill(HIST("clusterQA/hClusterEtaPhiBefore"), photon.phi(), photon.eta()); // before cuts if (!(fEMCCut.IsSelected(photon))) { continue; @@ -1081,31 +1107,31 @@ struct TaskPi0FlowEMC { if (cfgDistanceToEdge.value && (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelSameEvent.value)) { continue; } - registry.fill(HIST("clusterQA/hEClusterAfter"), photon.e()); // accepted after cuts + registry.fill(HIST("clusterQA/hEClusterAfter"), photon.corrE()); // accepted after cuts registry.fill(HIST("clusterQA/hClusterEtaPhiAfter"), photon.phi(), photon.eta()); // after cuts } } runPairingLoop(collision, photonsPerCollision, photonsPerCollision, flags, flags); - if (cfgDoRotation) { - if (nColl % cfgDownsampling.value == 0) { + if (rotationConfig.cfgDoRotation.value) { + if (nColl % rotationConfig.cfgDownsampling == 0) { nColl = 1; // reset counter } else { nColl++; } } - } + } // end of loop over collisions } PROCESS_SWITCH(TaskPi0FlowEMC, processEMCal, "Process EMCal Pi0 candidates", true); // Pi0 from EMCal void processEMCalMixed(FilteredCollsWithQvecs const& collisions, EMCalPhotons const& clusters, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { + if (clusters.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } EMBitFlags flags(clusters.size()); fEMCCut.AreSelectedRunning(flags, clusters, matchedPrims, matchedSeconds); - float energyCorrectionFactor = 1.f; - if (cfgDoReverseScaling.value) { - energyCorrectionFactor = 1.0505f; - } using BinningType = ColumnBinningPolicy>; BinningType binningMixedEvent{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins, mixingConfig.cfgEPBins}, true}; @@ -1149,14 +1175,8 @@ struct TaskPi0FlowEMC { continue; } } - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - if (correctionConfig.cfgEnableNonLin.value) { - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g2.e() > MinEnergy ? g2.e() : MinEnergy); - } - ROOT::Math::PtEtaPhiMVector v2(energyCorrectionFactor * g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1181,7 +1201,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCutsMixed"), 5); continue; } @@ -1195,15 +1215,23 @@ struct TaskPi0FlowEMC { // PCM-EMCal same event void processEMCalPCMC(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, PCMPhotons const& photons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { + if (clusters.size() <= 0 && photons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } EMBitFlags emcFlags(clusters.size()); - fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + if (clusters.size() > 0) { + fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds, ®istry); + } - if (cfgDoReverseScaling.value) { - energyCorrectionFactor = 1.0505f; + EMBitFlags v0flags(photons.size()); + if (photons.size() > 0) { + fV0PhotonCut.AreSelectedRunning(v0flags, photons, ®istry); } + for (const auto& collision : collisions) { - if (!isFullEventSelected(collision)) { + if (!isFullEventSelected(collision, true)) { continue; } runNow = collision.runNumber(); @@ -1225,7 +1253,7 @@ struct TaskPi0FlowEMC { } } for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photonsEMCPerCollision, photonsPCMPerCollision))) { - if (!(emcFlags.test(g1.globalIndex())) || !(fV0PhotonCut.IsSelected(g2))) { + if (!(emcFlags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { continue; } @@ -1237,10 +1265,9 @@ struct TaskPi0FlowEMC { } // EMCal photon v1 - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); // PCM photon v2s - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1251,6 +1278,9 @@ struct TaskPi0FlowEMC { registry.fill(HIST("hMesonCuts"), 2); continue; } + if (rotationConfig.cfgDoRotation.value) { + rotationBackgroundPCMEMC(vMeson, v2, v1, photonsPCMPerCollision, photonsEMCPerCollision, g2.globalIndex(), g1.globalIndex(), collision); + } if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { registry.fill(HIST("hMesonCuts"), 3); continue; @@ -1259,12 +1289,12 @@ struct TaskPi0FlowEMC { registry.fill(HIST("hMesonCuts"), 4); continue; } - if (mesonConfig.cfgEnableQA) { + if (mesonConfig.cfgEnableQA.value) { registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), vMeson.Pt()); registry.fill(HIST("mesonQA/hTanThetaPhi"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCuts"), 5); continue; } @@ -1277,6 +1307,11 @@ struct TaskPi0FlowEMC { // PCM-EMCal mixed event void processEMCalPCMMixed(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, PCMPhotons const& pcmPhotons, aod::V0Legs const&, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { + if (clusters.size() <= 0 && pcmPhotons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + using BinningTypeMixed = ColumnBinningPolicy>; BinningTypeMixed binningOnPositions{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins, mixingConfig.cfgEPBins}, true}; @@ -1284,9 +1319,16 @@ struct TaskPi0FlowEMC { Pair pairPCMEMC{binningOnPositions, mixingConfig.cfgMixingDepth, -1, collisions, associatedTables, &cache}; // indicates that mixingConfig.cfgMixingDepth events should be mixed and under/overflow (-1) to be ignored - float energyCorrectionFactor = 1.f; EMBitFlags emcFlags(clusters.size()); - fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + if (clusters.size() > 0) { + fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds, ®istry); + } + + EMBitFlags v0flags(pcmPhotons.size()); + if (pcmPhotons.size() > 0) { + fV0PhotonCut.AreSelectedRunning(v0flags, pcmPhotons, ®istry); + } + for (const auto& [c1, photonEMC, c2, photonPCM] : pairPCMEMC) { if (!(fEMEventCut.IsSelected(c1)) || !(fEMEventCut.IsSelected(c2))) { // general event selection @@ -1305,8 +1347,9 @@ struct TaskPi0FlowEMC { initCCDB(c1); runBefore = runNow; } + registry.fill(HIST("h3DMixingCount"), c1.posZ(), getCentrality(c1), c1.ep2ft0m()); for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photonEMC, photonPCM))) { - if (!(emcFlags.test(g1.globalIndex())) || !(fV0PhotonCut.IsSelected(g2))) { + if (!(emcFlags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { continue; } // Cut edge clusters away, similar to rotation method to ensure same acceptance is used @@ -1315,9 +1358,8 @@ struct TaskPi0FlowEMC { continue; } } - energyCorrectionFactor = fEMCalCorrectionFactor->Eval(g1.e() > MinEnergy ? g1.e() : MinEnergy); - ROOT::Math::PtEtaPhiMVector v1(energyCorrectionFactor * g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; float dTheta = v1.Theta() - v2.Theta(); @@ -1337,12 +1379,12 @@ struct TaskPi0FlowEMC { registry.fill(HIST("hMesonCutsMixed"), 4); continue; } - if (mesonConfig.cfgEnableQA) { + if (mesonConfig.cfgEnableQA.value) { registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); registry.fill(HIST("mesonQA/hTanThetaPhiMixed"), vMeson.M(), getAngleDegree(std::atan(dTheta / dPhi))); registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); } - if (mesonConfig.enableTanThetadPhi && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { + if (mesonConfig.enableTanThetadPhi.value && mesonConfig.minTanThetadPhi > std::fabs(getAngleDegree(std::atan(dTheta / dPhi)))) { registry.fill(HIST("hMesonCutsMixed"), 5); continue; } @@ -1356,6 +1398,13 @@ struct TaskPi0FlowEMC { // Pi0 from EMCal void processM02(CollsWithQvecs const& collisions, EMCalPhotons const& clusters, MinMTracks const& matchedPrims, MinMSTracks const& matchedSeconds) { + if (clusters.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + EMBitFlags emcFlags(clusters.size()); + fEMCCut.AreSelectedRunning(emcFlags, clusters, matchedPrims, matchedSeconds); + for (const auto& collision : collisions) { o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(®istry, collision); if (!(fEMEventCut.IsSelected(collision))) { @@ -1393,7 +1442,7 @@ struct TaskPi0FlowEMC { } auto matchedPrimsPerCluster = matchedPrims.sliceBy(perEMCClusterMT, photon.globalIndex()); auto matchedSecondsPerCluster = matchedSeconds.sliceBy(perEMCClusterMS, photon.globalIndex()); - if (!(fEMCCut.IsSelected(photon, matchedPrimsPerCluster, matchedSecondsPerCluster))) { + if (!(emcFlags.test(photon.globalIndex()))) { continue; } if (cfgDistanceToEdge.value && (checkEtaPhi1D(photon.eta(), RecoDecay::constrainAngle(photon.phi())) >= cfgEMCalMapLevelSameEvent.value)) { @@ -1405,7 +1454,6 @@ struct TaskPi0FlowEMC { } auto [xQVec, yQVec] = getQvec(collision, qvecDetector); - float cent = getCentrality(collision); float phiCand = photon.phi(); @@ -1426,6 +1474,133 @@ struct TaskPi0FlowEMC { } // processM02 PROCESS_SWITCH(TaskPi0FlowEMC, processM02, "Process single EMCal clusters as function of M02", false); + // Pi0 from EMCal + void processPCM(CollsWithQvecs const& collisions, PCMPhotons const& photons, aod::V0Legs const&) + { + if (photons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + EMBitFlags v0flags(photons.size()); + fV0PhotonCut.AreSelectedRunning(v0flags, photons, ®istry); + for (const auto& collision : collisions) { + + if (!isFullEventSelected(collision, true)) { + continue; + } + runNow = collision.runNumber(); + if (runNow != runBefore) { + initCCDB(collision); + runBefore = runNow; + } + + auto photonsPerCollision = photons.sliceBy(perCollisionPCM, collision.globalIndex()); + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photonsPerCollision, photonsPerCollision))) { + if (!(v0flags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; + + float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); + + registry.fill(HIST("hMesonCuts"), 1); + if (openingAngle <= mesonConfig.minOpenAngle) { + registry.fill(HIST("hMesonCuts"), 2); + continue; + } + if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { + registry.fill(HIST("hMesonCuts"), 3); + continue; + } + if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { + registry.fill(HIST("hMesonCuts"), 4); + continue; + } + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPt"), vMeson.M(), vMeson.Pt()); + registry.fill(HIST("mesonQA/hAlphaPt"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + } + registry.fill(HIST("hMesonCuts"), 6); + runFlowAnalysis<0>(collision, vMeson); + } + } // end of loop over collisions + } + PROCESS_SWITCH(TaskPi0FlowEMC, processPCM, "Process PCM Pi0 candidates", false); + + // PCM-EMCal mixed event + void processPCMMixed(FilteredCollsWithQvecs const& collisions, PCMPhotons const& pcmPhotons, aod::V0Legs const&) + { + + if (pcmPhotons.size() <= 0) { + LOG(info) << "Skipping DF because there are not photons!"; + return; + } + + using BinningType = ColumnBinningPolicy>; + BinningType binningMixedEvent{{mixingConfig.cfgVtxBins, mixingConfig.cfgCentBins, mixingConfig.cfgEPBins}, true}; + + auto pcmPhotonTuple = std::make_tuple(pcmPhotons); + SameKindPair pair{binningMixedEvent, mixingConfig.cfgMixingDepth, -1, collisions, pcmPhotonTuple, &cache}; // indicates that 5 events should be mixed and under/overflow (-1) to be ignored + + EMBitFlags v0flags(pcmPhotons.size()); + fV0PhotonCut.AreSelectedRunning(v0flags, pcmPhotons); + + for (const auto& [c1, photon1, c2, photon2] : pair) { + if (!(fEMEventCut.IsSelected(c1)) || !(fEMEventCut.IsSelected(c2))) { + // general event selection + continue; + } + if (!(eventcuts.cfgFT0COccupancyMin <= c1.ft0cOccupancyInTimeRange() && c1.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax) || !(eventcuts.cfgFT0COccupancyMin <= c2.ft0cOccupancyInTimeRange() && c2.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + // occupancy selection + continue; + } + if (getCentrality(c1) < eventcuts.cfgMinCent || getCentrality(c1) > eventcuts.cfgMaxCent || getCentrality(c2) < eventcuts.cfgMinCent || getCentrality(c2) > eventcuts.cfgMaxCent) { + // event selection + continue; + } + runNow = c1.runNumber(); + if (runNow != runBefore) { + initCCDB(c1); + runBefore = runNow; + } + registry.fill(HIST("h3DMixingCount"), c1.posZ(), getCentrality(c1), c1.ep2ft0m()); + for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photon1, photon2))) { + if (!(v0flags.test(g1.globalIndex())) || !(v0flags.test(g2.globalIndex()))) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(g1.corrPt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.corrPt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector vMeson = v1 + v2; + + float openingAngle = std::acos(v1.Vect().Dot(v2.Vect()) / (v1.P() * v2.P())); + + registry.fill(HIST("hMesonCutsMixed"), 1); + if (openingAngle <= mesonConfig.minOpenAngle) { + registry.fill(HIST("hMesonCutsMixed"), 2); + continue; + } + if (thnConfigAxisInvMass.value[1] > vMeson.M() || thnConfigAxisInvMass.value.back() < vMeson.M()) { + registry.fill(HIST("hMesonCutsMixed"), 3); + continue; + } + if (thnConfigAxisPt.value[1] > vMeson.Pt() || thnConfigAxisPt.value.back() < vMeson.Pt()) { + registry.fill(HIST("hMesonCutsMixed"), 4); + continue; + } + if (mesonConfig.cfgEnableQA.value) { + registry.fill(HIST("mesonQA/hInvMassPtMixed"), vMeson.M(), vMeson.Pt()); + registry.fill(HIST("mesonQA/hAlphaPtMixed"), (v1.E() - v2.E()) / (v1.E() + v2.E()), vMeson.Pt()); + } + registry.fill(HIST("hMesonCutsMixed"), 6); + runFlowAnalysis<2>(c1, vMeson); + } + } + } + PROCESS_SWITCH(TaskPi0FlowEMC, processPCMMixed, "Process neutral meson flow using PCM-EMC mixed event", false); + }; // End struct TaskPi0FlowEMC WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/Utils/ClusterHistograms.h b/PWGEM/PhotonMeson/Utils/ClusterHistograms.h index d4826f80ccb..dbaeebaf1a7 100644 --- a/PWGEM/PhotonMeson/Utils/ClusterHistograms.h +++ b/PWGEM/PhotonMeson/Utils/ClusterHistograms.h @@ -19,6 +19,7 @@ #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include +#include #include #include @@ -31,20 +32,36 @@ namespace o2::aod::pwgem::photonmeson::utils::clusterhistogram { inline void addClusterHistograms(o2::framework::HistogramRegistry* fRegistry, bool do2DQA) { + const o2::framework::AxisSpec thAxisMomentum{250, 0., 25., "#it{p}_{T} (GeV/#it{c})"}; + const o2::framework::AxisSpec thAxisDEta{200, -0.1, 0.1, "#Delta#eta"}; + const o2::framework::AxisSpec thAxisDPhi{200, -0.1, 0.1, "#Delta#varphi (rad)"}; + const o2::framework::AxisSpec thAxisEnergy{500, 0., 50., "#it{E} (GeV)"}; + const o2::framework::AxisSpec thAxisEta{320, -0.8, 0.8, "#eta"}; + const o2::framework::AxisSpec thAxisPhi{500, 0, o2::constants::math::TwoPI, "#varphi (rad)"}; + fRegistry->add("Cluster/before/hE", "E_{cluster};#it{E}_{cluster} (GeV);#it{N}_{cluster}", o2::framework::kTH1F, {{500, 0.0f, 50}}, true); fRegistry->add("Cluster/before/hPt", "Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{cluster}", o2::framework::kTH1F, {{500, 0.0f, 50}}, true); - fRegistry->add("Cluster/before/hNgamma", "Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}", o2::framework::kTH1F, {{51, -0.5f, 50.5f}}, true); - fRegistry->add("Cluster/before/hEtaPhi", "#eta vs #varphi;#eta;#varphi (rad.)", o2::framework::kTH2F, {{280, -0.7f, 0.7f}, {180, 0, o2::constants::math::TwoPI}}, true); + fRegistry->add("Cluster/before/hNgamma", "Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}", o2::framework::kTH1F, {{1001, -0.5f, 1000.5f}}, true); + fRegistry->add("Cluster/before/hEtaPhi", "#eta vs #varphi;#eta;#varphi (rad.)", o2::framework::kTH2F, {thAxisEta, thAxisPhi}, true); fRegistry->add("Cluster/before/hNTracks", "Number of tracks considered for TM;#it{N}_{tracks};#it{N}_{cluster}", o2::framework::kTH1F, {{20, -0.5f, 19.5}}, true); - fRegistry->add("Cluster/before/hTrackdEtadPhi", "d#eta vs. d#varphi of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {{200, -0.2f, 0.2f}, {200, -0.2f, 0.2f}}, true); + fRegistry->add("Cluster/before/hNSecTracks", "Number of secondary tracks considered for TM;#it{N}_{tracks};#it{N}_{cluster}", o2::framework::kTH1F, {{20, -0.5f, 19.5}}, true); + fRegistry->add("Cluster/before/hTrackdEtadPhi", "d#eta vs. d#varphi of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisDPhi}, true); + fRegistry->add("Cluster/before/hTrackdEtaPt", "d#eta vs. track pT of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisMomentum}, true); + fRegistry->add("Cluster/before/hTrackdPhiPt", "d#varphi vs. track pT of matched tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDPhi, thAxisMomentum}, true); + fRegistry->add("Cluster/before/hSecTrackdEtadPhi", "d#eta vs. d#varphi of matched secondary tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisDPhi}, true); + fRegistry->add("Cluster/before/hSecTrackdEtaPt", "d#eta vs. track pT of matched secondary tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDEta, thAxisMomentum}, true); + fRegistry->add("Cluster/before/hSecTrackdPhiPt", "d#varphi vs. track pT of matched secondary tracks;d#eta;d#varphi (rad.)", o2::framework::kTH2F, {thAxisDPhi, thAxisMomentum}, 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)", o2::framework::kTH2F, {{26, -0.5, 25.5}, {200, 0, 20}}, true); fRegistry->add("Cluster/before/hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {{200, 0, 2}, {200, 0, 20}}, true); fRegistry->add("Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {{300, -150, 150}, {200, 0, 20}}, true); - fRegistry->add("Cluster/before/hTrackdEta", "d#eta vs. E of matched tracks;d#eta;#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {{200, -0.2f, 0.2f}, {200, 0, 20}}, true); - fRegistry->add("Cluster/before/hTrackdPhi", "d#phi vs. E of matched tracks;d#varphi (rad.);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {{200, -0.2f, 0.2f}, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hTrackdEta", "d#eta vs. E of matched tracks;d#eta;#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisDEta, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hTrackdPhi", "d#phi vs. E of matched tracks;d#varphi (rad.);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisDPhi, {200, 0, 20}}, true); fRegistry->add("Cluster/before/hTrackEOverP", "Energy of cluster divided by momentum of matched tracks;#it{E}_{cluster}/#it{p}_{track} (#it{c});#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {{200, 0., 5.}, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hSecTrackdEta", "d#eta vs. E of matched tracks;d#eta;#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisDEta, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hSecTrackdPhi", "d#phi vs. E of matched tracks;d#varphi (rad.);#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {thAxisDPhi, {200, 0, 20}}, true); + fRegistry->add("Cluster/before/hSecTrackEOverP", "Energy of cluster divided by momentum of matched tracks;#it{E}_{cluster}/#it{p}_{track} (#it{c});#it{E}_{cluster} (GeV)", o2::framework::kTH2F, {{200, 0., 5.}, {200, 0, 20}}, true); } else { fRegistry->add("Cluster/before/hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{N}_{cluster}", o2::framework::kTH1F, {{26, -0.5, 25.5}}, true); fRegistry->add("Cluster/before/hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{N}_{cluster}", o2::framework::kTH1F, {{400, 0, 2}}, true); @@ -67,34 +84,105 @@ inline void addClusterHistograms(o2::framework::HistogramRegistry* fRegistry, bo fRegistry->addClone("Cluster/before/", "Cluster/after/"); } -template -inline void fillClusterHistograms(o2::framework::HistogramRegistry* fRegistry, TCluster cluster, bool do2DQA, float weight = 1.f) +inline void fillTrackQA1D( + o2::framework::HistogramRegistry* reg, + const auto& histbase, + float e, float p, float w) +{ + reg->fill(histbase + HIST("hTrackEOverP"), e / p, w); +} + +inline void fillTrackQA2D( + o2::framework::HistogramRegistry* reg, + const auto& histbase, + float e, float dEta, float dPhi, float p, float pt, float w) +{ + reg->fill(histbase + HIST("hTrackdEtadPhi"), dEta, dPhi, w); + reg->fill(histbase + HIST("hTrackEOverP"), e / p, e, w); + reg->fill(histbase + HIST("hTrackdEta"), dEta, e, w); + reg->fill(histbase + HIST("hTrackdPhi"), dPhi, e, w); + reg->fill(histbase + HIST("hTrackdEtaPt"), dEta, pt, w); + reg->fill(histbase + HIST("hTrackdPhiPt"), dPhi, pt, w); +} + +template +inline void fillClusterHistograms(o2::framework::HistogramRegistry* fRegistry, TCluster cluster, bool do2DQA, float weight = 1.f, TMatchedTracks const& primTracks = nullptr, TMatchedSecondaries const& secTracks = nullptr) { - static constexpr std::string_view kClusterTypes[2] = {"before/", "after/"}; - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hE"), cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hPt"), cluster.pt(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hEtaPhi"), cluster.eta(), cluster.phi(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hNTracks"), cluster.deltaEta().size(), weight); - for (size_t itrack = 0; itrack < cluster.deltaEta().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(kClusterTypes[cls_id]) + HIST("hTrackdEtadPhi"), cluster.deltaEta()[itrack], cluster.deltaPhi()[itrack], weight); + const auto e = cluster.e(); + const auto eta = cluster.eta(); + const auto phi = cluster.phi(); + + static constexpr std::string_view ClusterTypes[2] = {"Cluster/before/", "Cluster/after/"}; + + if constexpr (HasTrackMatching) { + for (size_t iTrack = 0; iTrack < cluster.deltaEta().size(); ++iTrack) { + const float dEta = cluster.deltaEta()[iTrack]; + const float dPhi = cluster.deltaPhi()[iTrack]; + const float p = cluster.trackp()[iTrack]; + const float pt = cluster.trackpt()[iTrack]; + + if (do2DQA) { + fillTrackQA2D(fRegistry, HIST(ClusterTypes[cls_id]), e, dEta, dPhi, p, pt, weight); + } else { + fillTrackQA1D(fRegistry, HIST(ClusterTypes[cls_id]), e, p, weight); + } + } } - if (do2DQA) { - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hNCell"), cluster.nCells(), cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hM02"), cluster.m02(), cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hTime"), cluster.time(), cluster.e(), weight); - for (size_t itrack = 0; itrack < cluster.deltaEta().size(); itrack++) { - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hTrackEOverP"), cluster.e() / cluster.trackp()[itrack], cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hTrackdEta"), cluster.deltaEta()[itrack], cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hTrackdPhi"), cluster.deltaPhi()[itrack], cluster.e(), weight); + + if constexpr (HasPrimaries && IsTrackContainer) { + for (const auto& primTrack : primTracks) { + if (do2DQA) { + fillTrackQA2D(fRegistry, HIST(ClusterTypes[cls_id]), e, primTrack.deltaEta(), primTrack.deltaPhi(), primTrack.trackP(), primTrack.trackPt(), weight); + } else { + fillTrackQA1D(fRegistry, HIST(ClusterTypes[cls_id]), e, primTrack.trackP(), weight); + } } - } else { - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hNCell"), cluster.nCells(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hM02"), cluster.m02(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hTime"), cluster.time(), weight); - for (size_t itrack = 0; itrack < cluster.deltaEta().size(); itrack++) { - fRegistry->fill(HIST("Cluster/") + HIST(kClusterTypes[cls_id]) + HIST("hTrackEOverP"), cluster.e() / cluster.trackp()[itrack], weight); + } + + if constexpr (HasSecondaries && IsTrackContainer) { + for (const auto& secTrack : secTracks) { + const auto trackP = secTrack.trackP(); + if (do2DQA) { + const auto dEta = secTrack.deltaEta(); + const auto dPhi = secTrack.deltaPhi(); + const auto trackPt = secTrack.trackPt(); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackdEtadPhi"), dEta, dPhi, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackEOverP"), e / trackP, e, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackdEta"), dEta, e, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackdPhi"), dPhi, e, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackdEtaPt"), dEta, trackPt, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackdPhiPt"), dPhi, trackPt, weight); + } else { + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hSecTrackEOverP"), e / trackP, weight); + } } } + + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hE"), e, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hPt"), cluster.pt(), weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hEtaPhi"), eta, phi, weight); + if constexpr (HasTrackMatching) { + // primary matched tracks are stored directly inside cluster + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hNTracks"), + cluster.deltaEta().size(), weight); + } else if constexpr (HasPrimaries && IsTrackContainer) { + // primary matched tracks are stored as their own table + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hNTracks"), primTracks.size(), weight); + } + if constexpr (HasSecondaries && IsTrackContainer) { + // secondary matched tracks are stored as their own table + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hNSecTracks"), secTracks.size(), weight); + } + + if (do2DQA) { + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hNCell"), cluster.nCells(), e, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hM02"), cluster.m02(), e, weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hTime"), cluster.time(), e, weight); + } else { + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hNCell"), cluster.nCells(), weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hM02"), cluster.m02(), weight); + fRegistry->fill(HIST(ClusterTypes[cls_id]) + HIST("hTime"), cluster.time(), weight); + } } } // namespace o2::aod::pwgem::photonmeson::utils::clusterhistogram diff --git a/PWGEM/PhotonMeson/Utils/EventHistograms.h b/PWGEM/PhotonMeson/Utils/EventHistograms.h index 5a00d9b6da9..dd4c3ca4ac6 100644 --- a/PWGEM/PhotonMeson/Utils/EventHistograms.h +++ b/PWGEM/PhotonMeson/Utils/EventHistograms.h @@ -19,6 +19,7 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" +#include #include #include @@ -28,10 +29,10 @@ namespace o2::aod::pwgem::photonmeson::utils::eventhistogram { -inline void addEventHistograms(o2::framework::HistogramRegistry* fRegistry) +inline void addEventHistograms(o2::framework::HistogramRegistry* fRegistry, bool useWeight = false) { // event info - auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", o2::framework::kTH1D, {{12, 0.5, 12.5}}, false); + auto hCollisionCounter = fRegistry->add("Event/before/hCollisionCounter", "collision counter;;Number of events", o2::framework::kTH1D, {{12, 0.5, 12.5}}, useWeight); hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); @@ -66,66 +67,66 @@ inline void addEventHistograms(o2::framework::HistogramRegistry* fRegistry) 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}, "centrality FT0C (%)"}; - fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", o2::framework::kTH1F, {{100, -50, +50}}, false); - fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", o2::framework::kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", o2::framework::kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", o2::framework::kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); - fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", o2::framework::kTH1F, {{axis_cent_ft0a}}, false); - fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", o2::framework::kTH1F, {{axis_cent_ft0c}}, false); - fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", o2::framework::kTH1F, {{axis_cent_ft0m}}, false); - fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", o2::framework::kTH2F, {{110, 0, 110}, {500, 0, 5000}}, false); - fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", o2::framework::kTH2F, {{60, 0, 60000}, {500, 0, 5000}}, false); - fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", o2::framework::kTH2F, {{60, 0, 60000}, {2000, 0, 20000}}, false); + fRegistry->add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", o2::framework::kTH1D, {{220, -11, +11}}, useWeight); + fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", o2::framework::kTH1F, {{6001, -0.5, 6000.5}}, useWeight); + fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", o2::framework::kTH1F, {{6001, -0.5, 6000.5}}, useWeight); + fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", o2::framework::kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, useWeight); + fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", o2::framework::kTH1F, {{axis_cent_ft0a}}, useWeight); + fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", o2::framework::kTH1F, {{axis_cent_ft0c}}, useWeight); + fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", o2::framework::kTH1F, {{axis_cent_ft0m}}, useWeight); + fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", o2::framework::kTH2F, {{110, 0, 110}, {500, 0, 5000}}, useWeight); + fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", o2::framework::kTH2F, {{60, 0, 60000}, {500, 0, 5000}}, useWeight); + fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", o2::framework::kTH2F, {{60, 0, 60000}, {500, 0, 10000}}, useWeight); fRegistry->addClone("Event/before/", "Event/after/"); } -template +template void fillEventInfo(o2::framework::HistogramRegistry* fRegistry, TCollision const& collision, float weight = 1.) { const float maxZ = 10.f; - static constexpr std::string_view kEventTypes[2] = {"before/", "after/"}; - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 1.0, weight); + static constexpr std::string_view EventTypes[2] = {"before/", "after/"}; + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 1.0, weight); if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 2.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 2.0, weight); } if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 3.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 3.0, weight); } if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 4.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 4.0, weight); } if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 5.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 5.0, weight); } if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 6.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 6.0, weight); } if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 7.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 7.0, weight); } if (collision.sel8()) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 8.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 8.0, weight); } if (std::abs(collision.posZ()) < maxZ) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 9.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 9.0, weight); } - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hZvtx"), collision.posZ(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hZvtx"), collision.posZ(), weight); if (collision.alias_bit(kTVXinEMC)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 10.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 10.0, weight); } if (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7)) { - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 11.0, weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCollisionCounter"), 11.0, weight); } - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCentFT0A"), collision.centFT0A(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCentFT0C"), collision.centFT0C(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCentFT0M"), collision.centFT0M(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV(), weight); - fRegistry->fill(HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCentFT0A"), collision.centFT0A(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCentFT0C"), collision.centFT0C(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCentFT0M"), collision.centFT0M(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV(), weight); + fRegistry->fill(HIST("Event/") + HIST(EventTypes[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange(), weight); } } // namespace o2::aod::pwgem::photonmeson::utils::eventhistogram diff --git a/PWGEM/PhotonMeson/Utils/HNMUtilities.h b/PWGEM/PhotonMeson/Utils/HNMUtilities.h index 9a3c7494c07..956529610a0 100644 --- a/PWGEM/PhotonMeson/Utils/HNMUtilities.h +++ b/PWGEM/PhotonMeson/Utils/HNMUtilities.h @@ -23,9 +23,10 @@ #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include +#include #include -#include // IWYU pragma: keep +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) #include #include @@ -139,7 +140,7 @@ inline int getSMNumber(float eta, float phi) } /// \brief Store photons from EMC clusters and V0s in a vector and possibly add a eta and phi offset for alignment of EMCal clusters -template +template void storeGammasInVector(C clusters, V v0s, std::vector& vPhotons, std::array EMCEtaShift, std::array EMCPhiShift) { vPhotons.clear(); diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 8164d846c02..9d766466a00 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -16,6 +16,8 @@ #ifndef PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ #define PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ +#include + #include #include @@ -26,7 +28,7 @@ //_______________________________________________________________________ namespace o2::aod::pwgem::photonmeson::utils::mcutil { -template +template bool IsPhysicalPrimary(TTrack const& mctrack) { // This is to check mctrack is ALICE physical primary. @@ -37,7 +39,7 @@ bool IsPhysicalPrimary(TTrack const& mctrack) } } //_______________________________________________________________________ -template +template int IsFromWD(TCollision const&, T const& mctrack, TMCs const& mcTracks) { // is this particle from weak decay? @@ -69,7 +71,7 @@ int IsFromWD(TCollision const&, T const& mctrack, TMCs const& mcTracks) return -1; } //_______________________________________________________________________ -template +template int IsXFromY(T const& mctrack, TMCs const& mcTracks, const int pdgX, const int pdgY) { // is photon from pi0? returns index of mother photon @@ -91,7 +93,7 @@ int IsXFromY(T const& mctrack, TMCs const& mcTracks, const int pdgX, const int p //_______________________________________________________________________ // Go up the decay chain of a mcparticle looking for a mother with the given pdg codes, if found return this mothers daughter // E.g. Find the gamma that was created in a pi0 or eta decay -template +template int FindMotherInChain(T const& mcparticle, TMCs const& mcparticles, TTargetPDGs const& motherpdgs, const int Depth = 50) // o2-linter: disable=pdg/explicit-code (false positive) { if (!mcparticle.has_mothers() || Depth < 1) { @@ -107,7 +109,7 @@ int FindMotherInChain(T const& mcparticle, TMCs const& mcparticles, TTargetPDGs } } //_______________________________________________________________________ -template +template int IsEleFromPC(T const& mctrack, TMCs const& mcTracks) { // is election from photon conversion? returns index of mother photon @@ -130,7 +132,7 @@ int IsEleFromPC(T const& mctrack, TMCs const& mcTracks) return -1; } //_______________________________________________________________________ -template +template bool IsInAcceptanceNonDerived(TMCParticle const& mcparticle, TMCParticles const& mcparticles, TTargetPDGs target_pdgs, const float ymin, const float ymax, const float phimin, const float phimax) { // contents in vector of daughter ID is different. @@ -181,7 +183,7 @@ bool IsInAcceptanceNonDerived(TMCParticle const& mcparticle, TMCParticles const& return true; } //_______________________________________________________________________ -template +template bool IsInAcceptance(TMCParticle const& mcparticle, TMCParticles const& mcparticles, TTargetPDGs target_pdgs, const float ymin, const float ymax, const float phimin, const float phimax) { if (mcparticle.y() < ymin || ymax < mcparticle.y()) { @@ -229,7 +231,7 @@ bool IsInAcceptance(TMCParticle const& mcparticle, TMCParticles const& mcparticl return true; } //_______________________________________________________________________ -template +template bool IsConversionPointInAcceptance(TMCPhoton const& mcphoton, const float max_r_gen, const float max_eta_gen, const float margin_z_mc, TMCParticles const& mcparticles) { if (std::abs(mcphoton.pdgCode()) != kGamma) { @@ -264,8 +266,8 @@ bool IsConversionPointInAcceptance(TMCPhoton const& mcphoton, const float max_r_ return true; } //_______________________________________________________________________ -template -bool isGammaGammaDecay(TMCParticle mcParticle, TMCParticles mcParticles) +template +bool isGammaGammaDecay(TMCParticle const& mcParticle, TMCParticles const& mcParticles) { auto daughtersIds = mcParticle.daughtersIds(); if (daughtersIds.size() != 2) { // o2-linter: disable=magic-number (2 is not that magic in this context) @@ -278,6 +280,26 @@ bool isGammaGammaDecay(TMCParticle mcParticle, TMCParticles mcParticles) } return true; } + +//_______________________________________________________________________ +// Go up the decay chain of a mcparticle looking for a mother with the given pdg codes, if found return true else false +// E.g. if electron cluster is coming from a photon return true, if primary electron return false +template +bool isMotherPDG(T& mcparticle, const int motherPDG, const int Depth = 10) // o2-linter: disable=pdg/explicit-code (false positive) +{ + if (!mcparticle.has_mothers() || Depth < 1) { + return false; + } + + int motherid = mcparticle.mothersIds()[0]; + mcparticle.setCursor(motherid); + if (mcparticle.pdgCode() != motherPDG) { + return true; // The mother has the required pdg code, so return its daughters global mc particle code. + } else { + return isMotherPDG(mcparticle, motherPDG, Depth - 1); + } +} + //_______________________________________________________________________ } // namespace o2::aod::pwgem::photonmeson::utils::mcutil //_______________________________________________________________________ diff --git a/PWGEM/PhotonMeson/Utils/NMHistograms.h b/PWGEM/PhotonMeson/Utils/NMHistograms.h index b04b8a67878..6eb784df2cf 100644 --- a/PWGEM/PhotonMeson/Utils/NMHistograms.h +++ b/PWGEM/PhotonMeson/Utils/NMHistograms.h @@ -18,6 +18,7 @@ #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include #include #include @@ -60,8 +61,8 @@ inline void addNMHistograms(o2::framework::HistogramRegistry* fRegistry, bool is fRegistry->add("Pair/Eta/hs_FromSameGamma", "Two clusters from same gamma that is a eta daughter (conversion)", o2::framework::kTHnSparseD, {axis_mass, axis_pt}, true); const o2::framework::AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y|"}; - fRegistry->add("Generated/Pi0/hPt", "pT;p_{T} (GeV/c)", o2::framework::kTH1F, {axis_pt}, true); - fRegistry->add("Generated/Pi0/hPtY", "Generated info", o2::framework::kTH2F, {axis_pt, axis_rapidity}, true); + fRegistry->add("Generated/Pi0/hPt", "pT;p_{T} (GeV/c)", o2::framework::kTH1D, {axis_pt}, true); + fRegistry->add("Generated/Pi0/hPtY", "Generated info", o2::framework::kTH2D, {axis_pt, axis_rapidity}, true); fRegistry->addClone("Generated/Pi0/", "Generated/Eta/"); fRegistry->get(HIST("Generated/Pi0/hPt"))->SetXTitle("p_{T} (GeV/c)"); @@ -76,7 +77,7 @@ inline void addNMHistograms(o2::framework::HistogramRegistry* fRegistry, bool is } } -template +template void fillTruePairInfo(o2::framework::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 = std::abs(mcparticle.pdgCode()); diff --git a/PWGEM/PhotonMeson/Utils/PairUtilities.h b/PWGEM/PhotonMeson/Utils/PairUtilities.h index 416d8d2e3b3..8a1ff20de88 100644 --- a/PWGEM/PhotonMeson/Utils/PairUtilities.h +++ b/PWGEM/PhotonMeson/Utils/PairUtilities.h @@ -18,6 +18,7 @@ #include "Common/Core/RecoDecay.h" #include +#include #include @@ -47,7 +48,7 @@ enum PairType { kNpair, }; -template +template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) { bool is_g1_selected = false; @@ -57,7 +58,7 @@ bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const return (is_g1_selected && is_g2_selected); } -template +template bool DoesV0LegMatchWithCluster(TV0Leg const& v0leg, TCluster const& cluster, const float max_deta, const float max_dphi, const float max_Ep_width) { float deta = v0leg.eta() - cluster.eta(); diff --git a/PWGEM/PhotonMeson/Utils/TrackSelection.h b/PWGEM/PhotonMeson/Utils/TrackSelection.h index 81803c9cee7..941a7ea2bc0 100644 --- a/PWGEM/PhotonMeson/Utils/TrackSelection.h +++ b/PWGEM/PhotonMeson/Utils/TrackSelection.h @@ -16,6 +16,8 @@ #ifndef PWGEM_PHOTONMESON_UTILS_TRACKSELECTION_H_ #define PWGEM_PHOTONMESON_UTILS_TRACKSELECTION_H_ +#include + #include #include @@ -30,7 +32,7 @@ namespace o2::pwgem::photonmeson * @param track track * @return true if has both */ -template +template inline bool isITSTPCTrack(TTrack const& track) { return track.hasITS() && track.hasTPC(); @@ -43,7 +45,7 @@ inline bool isITSTPCTrack(TTrack const& track) * @param track track * @return true if has both */ -template +template inline bool isTPCTRDTrack(TTrack const& track) { return !track.hasITS() && track.hasTPC() && track.hasTRD() && !track.hasTOF(); @@ -56,7 +58,7 @@ inline bool isTPCTRDTrack(TTrack const& track) * @param track track * @return true if has all */ -template +template inline bool isITSTPCTRDTrack(TTrack const& track) { return track.hasITS() && track.hasTPC() && track.hasTRD() && !track.hasTOF(); @@ -68,7 +70,7 @@ inline bool isITSTPCTRDTrack(TTrack const& track) * @param track track * @return true if has both */ -template +template inline bool isTPCTOFTrack(TTrack const& track) { return !track.hasITS() && track.hasTPC() && !track.hasTRD() && track.hasTOF(); @@ -80,7 +82,7 @@ inline bool isTPCTOFTrack(TTrack const& track) * @param track track * @return true if has all */ -template +template inline bool isTPCTRDTOFTrack(TTrack const& track) { return !track.hasITS() && track.hasTPC() && track.hasTRD() && track.hasTOF(); @@ -92,7 +94,7 @@ inline bool isTPCTRDTOFTrack(TTrack const& track) * @param track track * @return true if has all */ -template +template inline bool isITSTPCTRDTOFTrack(TTrack const& track) { return track.hasITS() && track.hasTPC() && track.hasTRD() && track.hasTOF(); @@ -105,7 +107,7 @@ inline bool isITSTPCTRDTOFTrack(TTrack const& track) * @param track track * @return true if tracks is TPC-only */ -template +template inline bool isTPConlyTrack(TTrack const& track) { return !track.hasITS() && track.hasTPC() && !track.hasTRD() && !track.hasTOF(); @@ -118,7 +120,7 @@ inline bool isTPConlyTrack(TTrack const& track) * @param track track * @return true if tracks is ITS-only */ -template +template inline bool isITSonlyTrack(TTrack const& track) { return track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF(); @@ -132,7 +134,7 @@ inline bool isITSonlyTrack(TTrack const& track) * @param track1 track from daughter 1 * @return true if V0 pairs are ITSTPC-tracks */ -template +template inline bool isITSTPC_ITSTPC(TTrack const& track0, TTrack const& track1) { return isITSTPCTrack(track0) && isITSTPCTrack(track1); @@ -146,7 +148,7 @@ inline bool isITSTPC_ITSTPC(TTrack const& track0, TTrack const& track1) * @param track1 track from daughter 1 * @return true if one is TPC-only and the other ITSTPC */ -template +template inline bool isITSTPC_TPConly(TTrack const& track0, TTrack const& track1) { return (isITSTPCTrack(track0) && isTPConlyTrack(track1)) || (isITSTPCTrack(track1) && isTPConlyTrack(track0)); @@ -160,7 +162,7 @@ inline bool isITSTPC_TPConly(TTrack const& track0, TTrack const& track1) * @param track1 track from daughter 1 * @return true if one is ITS-only and the other ITSTPC */ -template +template inline bool isITSTPC_ITSonly(TTrack const& track0, TTrack const& track1) { return (isITSTPCTrack(track0) && isITSonlyTrack(track1)) || (isITSTPCTrack(track1) && isITSonlyTrack(track0)); @@ -174,7 +176,7 @@ inline bool isITSTPC_ITSonly(TTrack const& track0, TTrack const& track1) * @param track1 track from daughter 1 * @return true if both are TPC-only tracks */ -template +template inline bool isTPConly_TPConly(TTrack const& track0, TTrack const& track1) { return isTPConlyTrack(track0) && isTPConlyTrack(track1); @@ -188,7 +190,7 @@ inline bool isTPConly_TPConly(TTrack const& track0, TTrack const& track1) * @param track1 track from daughter 1 * @return true if both are ITS-only tracks */ -template +template inline bool isITSonly_ITSonly(TTrack const& track0, TTrack const& track1) { return isITSonlyTrack(track0) && isITSonlyTrack(track1); @@ -202,7 +204,7 @@ inline bool isITSonly_ITSonly(TTrack const& track0, TTrack const& track1) * @param track1 track from daughter 1 * @return true if either one is ITS-only while the other one is TPC-only */ -template +template inline bool isTPConly_ITSonly(TTrack const& track0, TTrack const& track1) { return (isTPConlyTrack(track0) && isITSonlyTrack(track1)) || (isTPConlyTrack(track1) && isITSonlyTrack(track0)); @@ -215,7 +217,7 @@ inline bool isTPConly_ITSonly(TTrack const& track0, TTrack const& track1) * @param mc2 MCParticle 1 * @return true if the mother particle is the expected type and the same for both */ -template +template inline bool checkMCParticles(T const& mc1, T const& mc2) { if (std::abs(mc1.pdgCode()) != kElectron || std::abs(mc2.pdgCode()) != kElectron) { diff --git a/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h b/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h index 0fc655d8858..846168d774c 100644 --- a/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h +++ b/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h @@ -39,12 +39,23 @@ const std::vector eClusBins = {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200}; o2::framework::AxisSpec const gAxisEClus = {eClusBins, "#it{E}_{clus} (GeV)"}; +const std::vector pTBins = {0, 0.05, 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.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, + 4.9, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, + 9.5, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20}; +o2::framework::AxisSpec const gAxisPt = {pTBins, "#it{p}_{T} (GeV/#it{c})"}; + o2::framework::HistogramConfigSpec const gHistoSpecClusterTMdEtadPhi({o2::framework::HistType::kTH2F, {gAxisdEta, gAxisdPhi}}); o2::framework::HistogramConfigSpec const gHistoSpecClusterTMdEtaMT({o2::framework::HistType::kTH2F, {gAxisdEta, {10, 0.5, 10.5}}}); o2::framework::HistogramConfigSpec const gHistoSpecClusterTMdPhiMT({o2::framework::HistType::kTH2F, {gAxisdPhi, {10, 0.5, 10.5}}}); o2::framework::HistogramConfigSpec const gHistoSpecClusterTMdRMT({o2::framework::HistType::kTH2F, {gAxisdR, {10, 0.5, 10.5}}}); o2::framework::HistogramConfigSpec const gHistoSpecEtaPhi({o2::framework::HistType::kTH2F, {gAxisEta, gAxisPhi}}); o2::framework::HistogramConfigSpec const gHistoSpecClusterE({o2::framework::HistType::kTH1F, {gAxisEClus}}); +o2::framework::HistogramConfigSpec const gHistoSpecPt({o2::framework::HistType::kTH1F, {gAxisPt}}); o2::framework::HistogramConfigSpec const gHistoSpecClusterECuts({o2::framework::HistType::kTH2F, {gAxisEClus, {64, -0.5, 63.5}}}); o2::framework::HistogramConfigSpec const gHistoSpecTMEoverP({o2::framework::HistType::kTH2D, {gAxisEClus, gAxisEoverP}}); diff --git a/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h b/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h index 2eb11525278..0ef33364c80 100644 --- a/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h +++ b/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h @@ -19,28 +19,26 @@ #include #include -using namespace o2::framework; +o2::framework::AxisSpec const gAxis_zColl{800, -50.f, 50.f}; +o2::framework::AxisSpec const gAxis_pT{800, 0.f, 25.f}; +o2::framework::AxisSpec const gAxis_pT_armenteros{400, 0.f, 1.f}; +o2::framework::AxisSpec const gAxis_pT2d{400, 0.f, 25.f}; +o2::framework::AxisSpec const gAxis_eta{800, -o2::constants::math::PIHalf, o2::constants::math::PIHalf}; +o2::framework::AxisSpec const gAxis_eta2d{400, -o2::constants::math::PIHalf, o2::constants::math::PIHalf}; +o2::framework::AxisSpec const gAxis_phi{800, 0.f, o2::constants::math::TwoPI}; +o2::framework::AxisSpec const gAxis_r{800, 0.f, 200.f}; +o2::framework::AxisSpec const gAxis_r_extended{800, 0.f, 500.f}; +o2::framework::AxisSpec const gAxis_dr{200, -100.f, 100.f}; +o2::framework::AxisSpec const gAxis_r2d{400, 0.f, 250.f}; +o2::framework::AxisSpec const gAxis_z2d{1000, -250.f, 250.f}; +o2::framework::AxisSpec const gAxis_TPCdEdxSig{401, -10.025f, 10.025f}; +o2::framework::AxisSpec const gAxis_radRes{800, -o2::constants::math::PI, o2::constants::math::PI}; +o2::framework::AxisSpec const gAxis_xyz{2400, -300.f, 300.f}; +o2::framework::AxisSpec const gAxis_chi2{501, -1.f, 500.f}; +o2::framework::AxisSpec gAxis_pT_log{800, 0.01f, 25.f}; -AxisSpec const gAxis_zColl{800, -50.f, 50.f}; -AxisSpec const gAxis_pT{800, 0.f, 25.f}; -AxisSpec const gAxis_pT_armenteros{400, 0.f, 1.f}; -AxisSpec const gAxis_pT2d{400, 0.f, 25.f}; -AxisSpec const gAxis_eta{800, -o2::constants::math::PIHalf, o2::constants::math::PIHalf}; -AxisSpec const gAxis_eta2d{400, -o2::constants::math::PIHalf, o2::constants::math::PIHalf}; -AxisSpec const gAxis_phi{800, 0.f, o2::constants::math::TwoPI}; -AxisSpec const gAxis_r{800, 0.f, 200.f}; -AxisSpec const gAxis_r_extended{800, 0.f, 500.f}; -AxisSpec const gAxis_dr{200, -100.f, 100.f}; -AxisSpec const gAxis_r2d{400, 0.f, 250.f}; -AxisSpec const gAxis_z2d{1000, -250.f, 250.f}; -AxisSpec const gAxis_TPCdEdxSig{401, -10.025f, 10.025f}; -AxisSpec const gAxis_radRes{800, -o2::constants::math::PI, o2::constants::math::PI}; -AxisSpec const gAxis_xyz{2400, -300.f, 300.f}; -AxisSpec const gAxis_chi2{501, -1.f, 500.f}; -AxisSpec gAxis_pT_log{800, 0.01f, 25.f}; - -HistogramSpec const gHistoSpec_hCollisionZ_all_MCTrue{"hCollisionZ_all_MCTrue", "hCollisionZ_all_MCTrue;z (cm);counts", {HistType::kTH1F, {gAxis_zColl}}}; -HistogramSpec const gHistoSpec_hCollisionZ_MCTrue{"hCollisionZ_MCTrue", "hCollisionZ_MCTrue;z (cm);counts", {HistType::kTH1F, {gAxis_zColl}}}; -HistogramSpec const gHistoSpec_hCollisionZ_MCRec{"hCollisionZ_MCRec", "hCollisionZ_MCRec;z (cm);counts", {HistType::kTH1F, {gAxis_zColl}}}; +o2::framework::HistogramSpec const gHistoSpec_hCollisionZ_all_MCTrue{"hCollisionZ_all_MCTrue", "hCollisionZ_all_MCTrue;z (cm);counts", {o2::framework::HistType::kTH1F, {gAxis_zColl}}}; +o2::framework::HistogramSpec const gHistoSpec_hCollisionZ_MCTrue{"hCollisionZ_MCTrue", "hCollisionZ_MCTrue;z (cm);counts", {o2::framework::HistType::kTH1F, {gAxis_zColl}}}; +o2::framework::HistogramSpec const gHistoSpec_hCollisionZ_MCRec{"hCollisionZ_MCRec", "hCollisionZ_MCRec;z (cm);counts", {o2::framework::HistType::kTH1F, {gAxis_zColl}}}; #endif // PWGEM_PHOTONMESON_UTILS_GAMMACONVDEFINITIONS_H_ diff --git a/PWGEM/Tasks/phosAlign.cxx b/PWGEM/Tasks/phosAlign.cxx index 5e5856518af..4345280188c 100644 --- a/PWGEM/Tasks/phosAlign.cxx +++ b/PWGEM/Tasks/phosAlign.cxx @@ -9,33 +9,37 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CaloClusters.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PHOSBase/Geometry.h" -#include "ReconstructionDataFormats/TrackParametrization.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include #include +#include +#include #include -#include #include #include diff --git a/PWGEM/Tasks/phosCalibration.cxx b/PWGEM/Tasks/phosCalibration.cxx index 1116f47f0f2..5e62addf7dc 100644 --- a/PWGEM/Tasks/phosCalibration.cxx +++ b/PWGEM/Tasks/phosCalibration.cxx @@ -9,35 +9,42 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/CaloClusters.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + #include +#include #include -#include #include #include -#include "TFile.h" -#include "TGrid.h" -#include "TLorentzVector.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/CaloClusters.h" -#include "DataFormatsPHOS/Cell.h" -#include "DataFormatsPHOS/Cluster.h" -#include "DataFormatsPHOS/TriggerRecord.h" -#include "DataFormatsPHOS/BadChannelsMap.h" -#include "DataFormatsPHOS/CalibParams.h" -#include "PHOSBase/Geometry.h" -#include "PHOSReconstruction/Clusterer.h" - -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "CommonUtils/NameConf.h" -#include "CCDB/BasicCCDBManager.h" - -#include "CommonDataFormat/InteractionRecord.h" using namespace o2; using namespace o2::aod::evsel; diff --git a/PWGEM/Tasks/phosCellQA.cxx b/PWGEM/Tasks/phosCellQA.cxx index 710244c1a6d..178c812750b 100644 --- a/PWGEM/Tasks/phosCellQA.cxx +++ b/PWGEM/Tasks/phosCellQA.cxx @@ -9,26 +9,30 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include +#include #include -#include -#include -#include #include - -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/EventSelection.h" -#include "DataFormatsPHOS/Cell.h" -#include "DataFormatsPHOS/CalibParams.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" - -#include "PHOSBase/Geometry.h" -#include "CommonDataFormat/InteractionRecord.h" +#include /// \struct PHOS QA /// \brief Monitoring task for PHOS related quantities diff --git a/PWGEM/Tasks/phosCluQA.cxx b/PWGEM/Tasks/phosCluQA.cxx index e563dc3aebe..62d171a7690 100644 --- a/PWGEM/Tasks/phosCluQA.cxx +++ b/PWGEM/Tasks/phosCluQA.cxx @@ -9,26 +9,38 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/CaloClusters.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include #include +#include +#include #include #include #include #include -#include "Common/DataModel/CaloClusters.h" -#include "Common/DataModel/EventSelection.h" - -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "CommonUtils/NameConf.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" - -#include "PHOSBase/Geometry.h" -#include "CommonDataFormat/InteractionRecord.h" /// \struct PHOS QA /// \brief Monitoring task for PHOS related quantities diff --git a/PWGEM/Tasks/phosElId.cxx b/PWGEM/Tasks/phosElId.cxx index 062bbb6271b..0334b4084e7 100644 --- a/PWGEM/Tasks/phosElId.cxx +++ b/PWGEM/Tasks/phosElId.cxx @@ -16,8 +16,8 @@ /// \author Yeghishe Hambardzumyan, MIPT /// \since Apr, 2024 -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CaloClusters.h" #include "Common/DataModel/Centrality.h" @@ -28,27 +28,33 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PHOSBase/Geometry.h" -#include "ReconstructionDataFormats/TrackParametrization.h" - -#include "TF1.h" -#include "TPDGCode.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include diff --git a/PWGEM/Tasks/phosNbar.cxx b/PWGEM/Tasks/phosNbar.cxx index 51610ec9639..56447345bc0 100644 --- a/PWGEM/Tasks/phosNbar.cxx +++ b/PWGEM/Tasks/phosNbar.cxx @@ -8,30 +8,47 @@ // 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 "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CaloClusters.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "CommonUtils/NameConf.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PHOSBase/Geometry.h" -#include "ReconstructionDataFormats/Track.h" - -#include "TRandom.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include /// \struct phosNbar /// \brief account Nbar who's clusters appeared within PHOS diff --git a/PWGEM/Tasks/phosNonlin.cxx b/PWGEM/Tasks/phosNonlin.cxx index dd3ea3003fb..71abfb45208 100644 --- a/PWGEM/Tasks/phosNonlin.cxx +++ b/PWGEM/Tasks/phosNonlin.cxx @@ -14,31 +14,32 @@ /// \author Dmitri Peresunko /// +#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/CaloClusters.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PHOSBase/Geometry.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include +#include #include -#include +#include #include #include #include diff --git a/PWGEM/Tasks/phosPi0.cxx b/PWGEM/Tasks/phosPi0.cxx index 74536648380..4ba0bc81b40 100644 --- a/PWGEM/Tasks/phosPi0.cxx +++ b/PWGEM/Tasks/phosPi0.cxx @@ -14,31 +14,35 @@ /// \author Dmitri Peresunko /// +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/CaloClusters.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PHOSBase/Geometry.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include #include #include +#include #include -#include +#include #include #include #include diff --git a/PWGEM/Tasks/phosTrigQA.cxx b/PWGEM/Tasks/phosTrigQA.cxx index b0b0949cfb5..6cea670f118 100644 --- a/PWGEM/Tasks/phosTrigQA.cxx +++ b/PWGEM/Tasks/phosTrigQA.cxx @@ -9,28 +9,38 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/CaloClusters.h" +#include "Common/DataModel/EventSelection.h" +#include "EventFiltering/filterTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include #include +#include +#include #include #include #include #include -#include "Common/DataModel/CaloClusters.h" -#include "Common/DataModel/EventSelection.h" - -#include "Framework/ConfigParamSpec.h" -#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 "CommonUtils/NameConf.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" - -#include "PHOSBase/Geometry.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "EventFiltering/filterTables.h" /// \struct PHOS trigger QA /// \brief Monitoring task for PHOS related quantities diff --git a/PWGHF/ALICE3/TableProducer/CMakeLists.txt b/PWGHF/ALICE3/TableProducer/CMakeLists.txt index 5a5201102e3..5bbc40353ee 100644 --- a/PWGHF/ALICE3/TableProducer/CMakeLists.txt +++ b/PWGHF/ALICE3/TableProducer/CMakeLists.txt @@ -21,6 +21,11 @@ o2physics_add_dpl_workflow(candidate-creator-x PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-creator-xicc + SOURCES candidateCreatorXicc.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + # Candidate selectors o2physics_add_dpl_workflow(candidate-selector-chic-to-jpsi-gamma @@ -63,6 +68,11 @@ o2physics_add_dpl_workflow(candidate-selector-x-to-jpsi-pi-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-selector-xicc-to-p-k-pi-pi + SOURCES candidateSelectorXiccToPKPiPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + # Tree creators o2physics_add_dpl_workflow(tree-creator-chic-to-jpsi-gamma @@ -74,3 +84,8 @@ o2physics_add_dpl_workflow(tree-creator-x-to-jpsi-pi-pi SOURCES treeCreatorXToJpsiPiPi.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 + COMPONENT_NAME Analysis) diff --git a/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx b/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx index 117fc633098..b03c9bf6952 100644 --- a/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx @@ -22,11 +22,11 @@ #include "ALICE3/DataModel/ECAL.h" #include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" +#include +#include +#include +#include +#include #include #include @@ -44,7 +44,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Reconstruction of Chic candidates struct HfCandidateCreatorChic { diff --git a/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx b/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx index ee6317aaa27..f0dfb8d761c 100644 --- a/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx @@ -22,11 +22,11 @@ #include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" +#include +#include +#include +#include +#include #include #include @@ -44,7 +44,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Reconstruction of X candidates struct HfCandidateCreatorX { diff --git a/PWGHF/TableProducer/candidateCreatorXicc.cxx b/PWGHF/ALICE3/TableProducer/candidateCreatorXicc.cxx similarity index 99% rename from PWGHF/TableProducer/candidateCreatorXicc.cxx rename to PWGHF/ALICE3/TableProducer/candidateCreatorXicc.cxx index cde56b878aa..a605acdc7fc 100644 --- a/PWGHF/TableProducer/candidateCreatorXicc.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateCreatorXicc.cxx @@ -173,7 +173,6 @@ struct HfCandidateCreatorXicc { auto chi2PCA = df2.getChi2AtPCACandidate(); auto covMatrixPCA = df2.calcPCACovMatrixFlat(); - df2.propagateTracksToVertex(); df2.getTrack(0).getPxPyPzGlo(pvecxic); df2.getTrack(1).getPxPyPzGlo(pvecpion); @@ -185,7 +184,7 @@ struct HfCandidateCreatorXicc { trackParVarPi.propagateToDCA(primaryVertex, bz, &impactParameter1); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexXicc, 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.)); @@ -225,9 +224,9 @@ struct HfCandidateCreatorXiccMc { aod::TracksWMc const&, aod::McParticles const& mcParticles) { - int8_t sign = 0; - int8_t flag; - int8_t origin; + int8_t sign{}; + int8_t flag{}; + int8_t origin{}; // Match reconstructed candidates. for (const auto& candidate : candidates) { diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx index fab70fd5eb5..0c4b37e21c4 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx @@ -20,9 +20,9 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx index 0de3e010c44..5fb93e341f5 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx @@ -21,9 +21,9 @@ #include "ALICE3/DataModel/RICH.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include #include diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx index 00ef9b7d673..ab2e05c16e8 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx @@ -21,9 +21,9 @@ #include "ALICE3/DataModel/RICH.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include #include diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx index 7a8d6111ee0..474d0eda059 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx @@ -21,9 +21,9 @@ #include "ALICE3/DataModel/RICH.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include #include diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx index 5ca50181673..40f8aee3e01 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx @@ -24,8 +24,8 @@ #include "ALICE3/DataModel/RICH.h" #include "Common/Core/TrackSelectorPID.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" +#include +#include #include @@ -59,7 +59,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(isAlice3); } -#include "Framework/runDataProcessing.h" +#include /// Struct for applying J/ψ → e+ e−, μ+ μ− selection cuts struct HfCandidateSelectorJpsi { diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx index 509ba9bb813..1844f315f28 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx @@ -22,9 +22,9 @@ #include "ALICE3/DataModel/RICH.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx index 6bcc7fc438c..5fbde221894 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx @@ -22,9 +22,9 @@ #include "ALICE3/DataModel/RICH.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx index 222d8261259..69ef001ab57 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx @@ -21,9 +21,9 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include #include diff --git a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorXiccToPKPiPi.cxx similarity index 100% rename from PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx rename to PWGHF/ALICE3/TableProducer/candidateSelectorXiccToPKPiPi.cxx diff --git a/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx b/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx index 33af9544284..589d889fdcb 100644 --- a/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx +++ b/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx @@ -22,9 +22,9 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx b/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx index b4ebf84eac2..2a9c9c49faf 100644 --- a/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx +++ b/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx @@ -21,8 +21,8 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx b/PWGHF/ALICE3/TableProducer/treeCreatorXiccToPKPiPi.cxx similarity index 100% rename from PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx rename to PWGHF/ALICE3/TableProducer/treeCreatorXiccToPKPiPi.cxx diff --git a/PWGHF/ALICE3/Tasks/CMakeLists.txt b/PWGHF/ALICE3/Tasks/CMakeLists.txt index 140815e7585..c94c68a9587 100644 --- a/PWGHF/ALICE3/Tasks/CMakeLists.txt +++ b/PWGHF/ALICE3/Tasks/CMakeLists.txt @@ -53,3 +53,8 @@ o2physics_add_dpl_workflow(task-x SOURCES taskX.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-xicc + SOURCES taskXicc.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGHF/ALICE3/Tasks/taskChic.cxx b/PWGHF/ALICE3/Tasks/taskChic.cxx index f7331b7d417..f6ed3fbabe0 100644 --- a/PWGHF/ALICE3/Tasks/taskChic.cxx +++ b/PWGHF/ALICE3/Tasks/taskChic.cxx @@ -20,9 +20,9 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include @@ -38,7 +38,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// chi_c1(1P) analysis task struct HfTaskChic { diff --git a/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx b/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx index 546d7946394..a6a79fa2e23 100644 --- a/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx +++ b/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx @@ -19,10 +19,10 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx b/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx index a43dc94d436..ac528208830 100644 --- a/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx +++ b/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx @@ -19,10 +19,10 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx b/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx index 46387f053a6..23d160348d8 100644 --- a/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx +++ b/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx @@ -19,10 +19,10 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/ALICE3/Tasks/taskJpsi.cxx b/PWGHF/ALICE3/Tasks/taskJpsi.cxx index 9a20f6f42e9..9390751b7ee 100644 --- a/PWGHF/ALICE3/Tasks/taskJpsi.cxx +++ b/PWGHF/ALICE3/Tasks/taskJpsi.cxx @@ -20,9 +20,9 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include @@ -37,7 +37,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// jpsitoee analysis task struct HfTaskJpsi { diff --git a/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx b/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx index ec32c52976c..703ba304092 100644 --- a/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx +++ b/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx @@ -19,10 +19,10 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx b/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx index b22c531e621..ff8e2aad4a4 100644 --- a/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx +++ b/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx @@ -19,10 +19,10 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx b/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx index f0e819e3086..fe8c1a066f8 100644 --- a/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx +++ b/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx @@ -16,24 +16,29 @@ /// \author Henrique J C Zanoli , Utrecht University /// \author Nicolo' Jacazio , CERN -#include -#include - -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/DCA.h" - #include "ALICE3/DataModel/MID.h" #include "ALICE3/DataModel/RICH.h" #include "Common/Core/TrackSelectorPID.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/PIDResponseTOF.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -69,7 +74,7 @@ void customize(std::vector& workflowOptions) std::swap(workflowOptions, options); } -#include "Framework/runDataProcessing.h" +#include /// Task to QA the efficiency of a particular particle defined by particlePDG template diff --git a/PWGHF/ALICE3/Tasks/taskX.cxx b/PWGHF/ALICE3/Tasks/taskX.cxx index 2be307e0f92..2391634f8ce 100644 --- a/PWGHF/ALICE3/Tasks/taskX.cxx +++ b/PWGHF/ALICE3/Tasks/taskX.cxx @@ -21,9 +21,9 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include @@ -39,7 +39,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// X(3872) analysis task struct HfTaskX { diff --git a/PWGHF/D2H/Tasks/taskXicc.cxx b/PWGHF/ALICE3/Tasks/taskXicc.cxx similarity index 100% rename from PWGHF/D2H/Tasks/taskXicc.cxx rename to PWGHF/ALICE3/Tasks/taskXicc.cxx diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index 71cdc0ebffd..33ee20266f4 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -30,6 +30,7 @@ enum CentralityEstimator { FT0M, FV0A, NTracksPV, + FT0CVariant2, NCentralityEstimators }; @@ -43,6 +44,11 @@ concept HasFT0CCent = requires(T collision) { collision.centFT0C(); }; +template +concept HasFT0CVariant2Cent = requires(T collision) { + collision.centFT0CVariant2(); +}; + template concept HasFT0MCent = requires(T collision) { collision.centFT0M(); @@ -76,6 +82,15 @@ float getCentralityColl(const TCollision& collision) return collision.centFT0C(); } +/// Evaluate centrality/multiplicity percentile using FT0C variant 1 estimator +/// \param candidate is candidate +/// \return centrality/multiplicity percentile of the collision +template +float getCentralityColl(const TCollision& collision) +{ + return collision.centFT0CVariant2(); +} + /// Evaluate centrality/multiplicity percentile using FT0M estimator /// \param candidate is candidate /// \return centrality/multiplicity percentile of the collision @@ -144,6 +159,18 @@ float getCentralityColl(const TCollision& collision, const int centEstimator) } LOG(fatal) << "Collision does not have centFV0A()."; break; + case CentralityEstimator::NTracksPV: + if constexpr (HasNTracksPvCent) { + return collision.centNTPV(); + } + LOG(fatal) << "Collision does not have centNTPV()."; + break; + case CentralityEstimator::FT0CVariant2: + if constexpr (HasFT0CVariant2Cent) { + return collision.centFT0CVariant2(); + } + LOG(fatal) << "Collision does not have centFT0CVariant2()."; + break; default: LOG(fatal) << "Centrality estimator not valid. See CentralityEstimator for valid values."; break; diff --git a/PWGHF/Core/DecayChannelsLegacy.h b/PWGHF/Core/DecayChannelsLegacy.h index 675417d975b..0f0f8892a75 100644 --- a/PWGHF/Core/DecayChannelsLegacy.h +++ b/PWGHF/Core/DecayChannelsLegacy.h @@ -26,7 +26,8 @@ enum DecayType { OmegaczeroToXiPi, OmegaczeroToOmegaPi, OmegaczeroToOmegaK, - OmegaczeroToOmegaPiOneMu + OmegaczeroToOmegaPiOneMu, + XiczeroToOmegaK }; } // namespace hf_cand_xic0_omegac0 diff --git a/PWGHF/Core/HfMlResponseB0ToDPi.h b/PWGHF/Core/HfMlResponseB0ToDPi.h index 4874b56543b..354d295f7a6 100644 --- a/PWGHF/Core/HfMlResponseB0ToDPi.h +++ b/PWGHF/Core/HfMlResponseB0ToDPi.h @@ -22,6 +22,8 @@ #include "Tools/ML/MlResponse.h" +#include + #include #include diff --git a/PWGHF/Core/HfMlResponseLcToK0sP.h b/PWGHF/Core/HfMlResponseLcToK0sP.h index 4e6899bf3aa..1d90b015008 100644 --- a/PWGHF/Core/HfMlResponseLcToK0sP.h +++ b/PWGHF/Core/HfMlResponseLcToK0sP.h @@ -82,6 +82,7 @@ enum class InputFeaturesLcToK0sP : uint8_t { v0MK0Short, v0MGamma, ctV0, + decayLengthV0, dcaV0daughters, ptV0Pos, dcaPosToPV, @@ -136,6 +137,7 @@ class HfMlResponseLcToK0sP : public HfMlResponse CHECK_AND_FILL_VEC_LC_FULL(candidate, v0MGamma, mGamma); CHECK_AND_FILL_VEC_LC_HFHELPER(candidate, ctV0, ctV0K0s); // CHECK_AND_FILL_VEC_LC_HFHELPER(candidate, ctV0, ctV0Lambda); + CHECK_AND_FILL_VEC_LC(decayLengthV0); CHECK_AND_FILL_VEC_LC(dcaV0daughters); CHECK_AND_FILL_VEC_LC(ptV0Pos); CHECK_AND_FILL_VEC_LC_FULL(candidate, dcaPosToPV, dcapostopv); @@ -180,6 +182,7 @@ class HfMlResponseLcToK0sP : public HfMlResponse FILL_MAP_LC(v0MK0Short), FILL_MAP_LC(v0MGamma), FILL_MAP_LC(ctV0), + FILL_MAP_LC(decayLengthV0), FILL_MAP_LC(dcaV0daughters), FILL_MAP_LC(ptV0Pos), FILL_MAP_LC(dcaPosToPV), diff --git a/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h b/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h index ed78d100b07..d3afc762d83 100644 --- a/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h +++ b/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h @@ -16,7 +16,6 @@ #ifndef PWGHF_CORE_HFMLRESPONSEOMEGACTOOMEGAPI_H_ #define PWGHF_CORE_HFMLRESPONSEOMEGACTOOMEGAPI_H_ -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" #include "Tools/ML/MlResponse.h" diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 2a0917cdf97..17a223bcd20 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -67,16 +67,41 @@ static const std::vector labelsCutVarTrack = {"min_dcaxytoprimary", namespace hf_presel_pid { +static constexpr int NPidRows = 4; // number of PID channels / rows +static constexpr int NPidCuts = 6; // number of cuts per PID (TPC+TOF) // default values for the PID cuts for protons in the track-index-skim-creator -constexpr float CutsPid[5][6] = {{0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, - {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, - {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, - {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, - {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}}; +constexpr float CutsPid[NPidRows][NPidCuts] = {{0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, + {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, + {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}, + {0.f, 1000.f, 5.f, 0.f, 1000.f, 5.f}}; static const std::vector labelsCutsPid = {"minPtTpc", "maxPtTpc", "nSigmaMaxTpc", "minPtTof", "maxPtTof", "nSigmaMaxTof"}; -static const std::vector labelsRowsPid = {"ProtonInLcToPKPi", "ProtonInXicToPKPi", "ProtonInLcToPK0S", "KaonIn3Prongs", "DeuteronInCdToDeKPi"}; +static const std::vector labelsRowsPid = {"ProtonInLcToPKPi", "ProtonInXicToPKPi", "ProtonInLcToPK0S", "KaonIn3Prongs"}; } // namespace hf_presel_pid +namespace hf_presel_lightnuclei +{ + +static constexpr int NParticleRows = 4; // number of particles / rows +static constexpr int NVarCuts = 10; // number of cuts for each particles +static constexpr int NBetheBlochParams = 6; // number of parameters for Bethe-Bloch + +// default values for the track cuts for lightnuclei in the track-index-skim-creator +constexpr float CutsTrackQuality[NParticleRows][NVarCuts] = {{-4.f, 3.f, 5.f, 0.f, 100.f, 100.f, 0.83, 160.f, 1.f, 5.f}, + {-4.f, 3.f, 5.f, 0.f, 100.f, 100.f, 0.83, 160.f, 1.f, 5.f}, + {-4.f, 3.f, 5.f, 0.f, 100.f, 100.f, 0.83, 160.f, 1.f, 5.f}, + {-4.f, 3.f, 5.f, 0.f, 100.f, 100.f, 0.83, 160.f, 1.f, 5.f}}; +static const std::vector labelsCutsTrack = {"nSigmaMinIts", "minItsClusterSizes", "minItsCluster", "minItsIbCluster", "minTpcCluster", "minTpcRow", "minTpcCrossedOverFound", "maxTpcShared", "maxTpcFracShared", "maxTPCnSigmaBB"}; +static const std::vector labelsRowsNucleiType = {"Deutron", "Triton", "Helium3", "Alpha"}; + +constexpr float BetheBlochParams[NParticleRows][NBetheBlochParams] = {{5.39302, 7.859534, 0.004048, 2.323197, 1.609307, 0.09}, + {5.39302, 7.859534, 0.004048, 2.323197, 1.609307, 0.09}, + {-126.55736, -0.858569, 1.11164, 1.21032, 2.656374, 0.09}, + {-126.55736, -0.858569, 1.11164, 1.21032, 2.656374, 0.09}}; + +static const std::vector labelsBetheBlochParams = {"p0", "p1", "p2", "p3", "p4", "resolution"}; + +} // namespace hf_presel_lightnuclei + namespace hf_cuts_bdt_multiclass { static constexpr int NBinsPt = 1; @@ -739,7 +764,7 @@ static const std::vector labelsCutVar = {"pT Ka from Omegac"}; namespace hf_cuts_xic_to_xi_pi { -static constexpr int NBinsPt = 11; +static constexpr int NBinsPt = 12; static constexpr int NCutVars = 28; // default values for the pT bin edges (can be used to configure histogram axis) // offset by 1 from the bin numbers in cuts array @@ -755,22 +780,24 @@ constexpr double BinsPt[NBinsPt + 1] = { 10.0, 12.0, 16.0, - 24.0}; + 24.0, + 50.0}; const auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; // default values for the cuts -constexpr double Cuts[NBinsPt][NCutVars] = {{0.2, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 0 < pt < 1 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 1 < pt < 2 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 2 < pt < 3 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 3 < pt < 4 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 4 < pt < 5 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 5 < pt < 6 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 6 < pt < 8 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 8 < pt < 10 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 10 < pt < 12 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 12 < pt < 16 */ - {0.5, 0.99, 0.97, 0.99, 0.99, 0.1, 0.2, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}}; /* 16 < pt < 24 */ +constexpr double Cuts[NBinsPt][NCutVars] = {{0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 0 < pt < 1 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 1 < pt < 2 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 2 < pt < 3 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 3 < pt < 4 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 4 < pt < 5 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 5 < pt < 6 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 6 < pt < 8 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 8 < pt < 10 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 10 < pt < 12 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 12 < pt < 16 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}, /* 16 < pt < 24 */ + {0.2, 0.97, 0.97, 0.99, 0.99, 2.0, 1.0, 1.0, 0.04, 0.06, 0.06, 0.05, 0.3, 70, 60, 100, 120, 250, 250, 0.4, 100, 300, 0., 0., 1.5, 0., 0., 0.4}}; /* 24 < pt < 50 -> Implemented just for test*/ // row labels static const std::vector labelsPt = { @@ -784,11 +811,15 @@ static const std::vector labelsPt = { "pT bin 7", "pT bin 8", "pT bin 9", - "pT bin 10"}; + "pT bin 10", + "pT bin 11"}; // column labels -static const std::vector labelsCutVar = {"ptPiFromCharmBaryon", "cosPACasc", "cosPAV0", "cosPaCascToXic", "cosPaV0ToCasc", - "dcaCharmBaryonDau", "dcaCascDau", "dcaV0Dau", "dcaXYToPvCascDau", "dcaXYToPvV0Dau0", "dcaXYToPvV0Dau1", "kfDcaXYPiFromXic", "kfDcaXYCascToPv", +static const std::vector labelsCutVar = {"ptPiFromCharmBaryon", "cosPACasc", "cosPAV0", + "cosPaCascToXic", "cosPaV0ToCasc", + "dcaCharmBaryonDau", "dcaCascDau", "dcaV0Dau", + "dcaXYToPvCascDau", "dcaXYToPvV0Dau0", "dcaXYToPvV0Dau1", + "kfDcaXYPiFromXic", "kfDcaXYCascToPv", "chi2GeoXic", "chi2GeoCasc", "chi2GeoV0", "chi2TopoXicToPv", "chi2TopoPiFromXicToPv", "chi2TopoCascToPv", "chi2TopoV0ToPv", "chi2TopoV0ToCasc", "chi2TopoCascToXic", "cascldl", "v0ldl", "decayLenXYXic", "decayLenXYCasc", "decayLenXYLambda", "cTauXic"}; diff --git a/PWGHF/D2H/Core/DataCreationCharmReso.h b/PWGHF/D2H/Core/DataCreationCharmReso.h index 3914b37c283..475a5ecdbae 100644 --- a/PWGHF/D2H/Core/DataCreationCharmReso.h +++ b/PWGHF/D2H/Core/DataCreationCharmReso.h @@ -18,14 +18,24 @@ #ifndef PWGHF_D2H_CORE_DATACREATIONCHARMRESO_H_ #define PWGHF_D2H_CORE_DATACREATIONCHARMRESO_H_ +#ifndef HomogeneousField +#define HomogeneousField // needed for KFParticle::SetField(magneticField); +#endif + #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsMcMatching.h" +// +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" + #include "Common/Core/RecoDecay.h" +#include "Common/Core/TPCVDriftManager.h" #include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" #include #include @@ -34,11 +44,17 @@ #include #include #include +#include #include +#include #include #include +#include +#include +#include + #include #include @@ -47,8 +63,6 @@ #include #include #include -#include -#include #include namespace o2::analysis @@ -69,6 +83,7 @@ enum BachelorType : uint8_t { Lambda, AntiLambda, Track, + Gamma, NBachelorTypes }; @@ -83,6 +98,7 @@ enum PairingType : uint8_t { V0Only, TrackOnly, V0AndTrack, + GammaOnly, NPairingType }; @@ -110,6 +126,7 @@ struct HfResoCandidateV0 { float dcaV0ToPv = 1000.f; float dcaDau = 1000.f; float alpha = -1.f; + float qt = -1.f; float eta = -999.f; float radius = 0.f; float mK0Short = 0.f; @@ -123,6 +140,7 @@ struct HfResoVarContainer { float invMassD0 = 0.f; float invMassD0Bar = 0.f; float invMassReso = 0.f; + float invMassResoBar = 0.f; float ptReso = -1.f; int8_t signD = 0; std::array pVectorProng0 = {0.f, 0.f, 0.f}; @@ -150,14 +168,43 @@ struct HfResoConfigV0Cuts : o2::framework::ConfigurableGroup { o2::framework::Configurable propagateV0toPV{"propagateV0toPV", false, "Enable or disable V0 propagation to V0"}; }; +struct HfResoConfigGammaCuts : o2::framework::ConfigurableGroup { + std::string prefix = "gammas"; // JSON group name + o2::framework::Configurable etaMax{"etaMax", 0.8f, "maximum eta"}; + o2::framework::Configurable ptMin{"ptMin", 0.1f, "minimum pT"}; + o2::framework::Configurable ptMaxItsOnly{"ptMaxItsOnly", 0.3f, "maximum pT for ITS-only gammas"}; + o2::framework::Configurable etaMaxDau{"etaMaxDau", 1.f, "maximum eta gamma daughters"}; + o2::framework::Configurable trackNclusItsCut{"trackNclusItsCut", 0, "Minimum number of ITS clusters for gamma daughter"}; + o2::framework::Configurable trackNCrossedRowsTpc{"trackNCrossedRowsTpc", 50, "Minimum TPC crossed rows"}; + o2::framework::Configurable trackNsharedClusTpc{"trackNsharedClusTpc", 1000, "Maximum number of shared TPC clusters for gamma daughter"}; + o2::framework::Configurable trackFracMaxindableTpcCls{"trackFracMaxindableTpcCls", 0.8f, "Maximum fraction of findable TPC clusters for gamma daughter"}; + o2::framework::Configurable dcaDauIts{"dcaDauIts", 0.5f, "maximum DCA gamma daughters (ITS)"}; + o2::framework::Configurable dcaDauItsIb{"dcaDauItsIb", 1.0f, "maximum DCA gamma daughters (ITS IB)"}; + o2::framework::Configurable dcaDauTpc{"dcaDauTpc", 0.5f, "maximum DCA gamma daughters (TPC)"}; + o2::framework::Configurable dcaDauTpcInner{"dcaDauTpcInner", 1.0f, "maximum DCA gamma daughters (TPC inner)"}; + o2::framework::Configurable dcaMaxDauToPv{"dcaMaxDauToPv", 0.1f, "Maximum gamma daughter's DCA to PV"}; + o2::framework::Configurable dcaPv{"dcaPv", 1.f, "DCA gamma to PV"}; + o2::framework::Configurable cosPa{"cosPa", 0.99f, "gamma CosPA"}; + o2::framework::Configurable radiusMin{"radiusMin", 1.0f, "Minimum gamma radius accepted"}; + o2::framework::Configurable radiusMax{"radiusMax", 90.f, "Maximum gamma radius accepted"}; + o2::framework::Configurable alphaApMax{"alphaApMax", 0.95f, "Maximum alpha AP"}; + o2::framework::Configurable qtApMax{"qtApMax", 0.01f, "Maximum qt AP"}; + o2::framework::Configurable nSigmaTpcEl{"nSigmaTpcEl", 4.f, "N sigma TPC for electrons"}; + o2::framework::Configurable propagateGammatoPV{"propagateGammatoPV", false, "Enable or disable V0 propagation to V0"}; +}; + struct HfResoConfigSingleTrackCuts : o2::framework::ConfigurableGroup { std::string prefix = "singleTracks"; // JSON group name o2::framework::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"}; o2::framework::Configurable maxEta{"maxEta", 0.8, "maximum pseudorapidity for single tracks to be paired with D mesons"}; o2::framework::Configurable minPt{"minPt", 0.1, "minimum pT for single tracks to be paired with D mesons"}; + o2::framework::Configurable forceTOF{"forceTOF", false, "force TOF for single tracks to be paired with D mesons"}; o2::framework::Configurable maxNsigmaTpcPi{"maxNsigmaTpcPi", -1., "maximum pion NSigma in TPC for single tracks to be paired with D mesons; set negative to reject"}; o2::framework::Configurable maxNsigmaTpcKa{"maxNsigmaTpcKa", -1., "maximum kaon NSigma in TPC for single tracks to be paired with D mesons; set negative to reject"}; o2::framework::Configurable maxNsigmaTpcPr{"maxNsigmaTpcPr", 3., "maximum proton NSigma in TPC for single tracks to be paired with D mesons; set negative to reject"}; + o2::framework::Configurable maxNsigmaTofPi{"maxNsigmaTofPi", -1., "maximum pion NSigma in TOF for single tracks to be paired with D mesons; set negative to reject"}; + o2::framework::Configurable maxNsigmaTofKa{"maxNsigmaTofKa", -1., "maximum kaon NSigma in TOF for single tracks to be paired with D mesons; set negative to reject"}; + o2::framework::Configurable maxNsigmaTofPr{"maxNsigmaTofPr", -1., "maximum proton NSigma in TOF for single tracks to be paired with D mesons; set negative to reject"}; }; struct HfResoConfigQaPlots : o2::framework::ConfigurableGroup { @@ -198,10 +245,16 @@ void addHistograms(o2::framework::HistogramRegistry& registry) const o2::framework::AxisSpec axisDeltaMassToPi{500, 0.13, 1.13, "inv. mass (GeV/#it{c}^{2})"}; const o2::framework::AxisSpec axisDeltaMassToPr{500, 0.93, 1.93, "inv. mass (GeV/#it{c}^{2})"}; const o2::framework::AxisSpec axisDeltaMassToLambda{500, 1.05, 2.05, "inv. mass (GeV/#it{c}^{2})"}; + const o2::framework::AxisSpec axisDeltaMassToGamma{500, 0., 0.25, "inv. mass (GeV/#it{c}^{2})"}; const o2::framework::AxisSpec axisMassDsj{400, 0.49f, 0.89f, ""}; // Ds1 and Ds2Star legacy + const o2::framework::AxisSpec axisAlpha{100, -1.f, 1.f}; + const o2::framework::AxisSpec axisQt{100, 0.f, 0.25f}; + const o2::framework::AxisSpec axisRadius{450, 0.f, 90.f}; registry.add("hMassVsPtK0s", "K0^{s} candidates;#it{p}_{T} (GeV/#it{c});inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassKzero}}); registry.add("hMassVsPtLambda", "Lambda candidates;#it{p}_{T} (GeV/#it{c});inv. mass (p #pi^{#minus}) (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassLambda}}); + registry.add("hAP", "Aremnteros-Podolanski plot for V0 candidates;#it{#alpha};#it{q}_{T} (GeV/#it{c});entries", {o2::framework::HistType::kTH2D, {axisAlpha, axisQt}}); + registry.add("hV0Radius", "Radius of V0 candidates;#it{R} (cm);entries", {o2::framework::HistType::kTH1D, {axisRadius}}); registry.add("hdEdxVsP", "Tracks;#it{p} (GeV/#it{c});d#it{E}/d#it{x};entries", {o2::framework::HistType::kTH2D, {axisP, axisDeDx}}); if constexpr (DType == DMesonType::D0) { @@ -214,6 +267,7 @@ void addHistograms(o2::framework::HistogramRegistry& registry) registry.add("hMassD0K", "D0Kplus candidates; m_{D^{0}K^{+}} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToK}}); registry.add("hMassD0Proton", "D0Proton candidates; m_{D^{0}p} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); registry.add("hMassD0Lambda", "D0Lambda candidates; m_{D^{0}#Lambda} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); + registry.add("hMassD0Gamma", "D0Gamma candidates; m_{D^{0}#gamma} - m_{D^{0}} (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisDeltaMassToGamma}}); } else if constexpr (DType == DMesonType::Dplus) { const o2::framework::AxisSpec axisMassDplus{200, 1.7f, 2.1f, "inv. mass (GeV/#it{c}^{2})"}; registry.add("hMassVsPtDplusAll", "Dplus candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {o2::framework::HistType::kTH2D, {axisPt, axisMassDplus}}); @@ -292,6 +346,18 @@ float alphaAP(std::array const& momV0, std::array const& mom return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); } +/// Utility to compute qT +/// \param momDau0 is the momentum of first daughter +/// \param momDau1 is the momentum of second daughter +/// \return qtAP +//_______________________________________________________________________ +inline float qtAP(std::array const& momDau0, std::array const& momDau1) +{ + float momTot = RecoDecay::p2(momDau0[0] + momDau1[0], momDau0[1] + momDau1[1], momDau0[2] + momDau1[2]); + float dp = RecoDecay::dotProd(std::array{momDau1[0], momDau1[1], momDau1[2]}, std::array{momDau0[0] + momDau1[0], momDau0[1] + momDau1[1], momDau0[2] + momDau1[2]}); + return std::sqrt(RecoDecay::p2(momDau1[0], momDau1[1], momDau1[2]) - dp * dp / momTot); // qt of v0 +} + /// Utility to find DCA of V0 to Primary vertex /// \param x is the x-coordinate /// \param y is the y-coordinate @@ -397,6 +463,7 @@ bool buildAndSelectV0(const Coll& collision, const std::array& dDaughter v0.v0Type = {BIT(BachelorType::K0s) | BIT(BachelorType::Lambda) | BIT(BachelorType::AntiLambda)}; // for lambda hypotesys define if its lambda or anti-lambda v0.alpha = alphaAP(v0.mom, v0.momPos, v0.momNeg); + v0.qt = qtAP(v0.momPos, v0.momNeg); bool const matter = v0.alpha > 0; CLRBIT(v0.v0Type, matter ? BachelorType::AntiLambda : BachelorType::Lambda); auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; @@ -438,6 +505,195 @@ bool buildAndSelectV0(const Coll& collision, const std::array& dDaughter return true; } +/// Basic selection of V0 candidates +/// \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 cfgV0Cuts are the cuts to be applied to the V0 +/// \param v0 is the V0 candidate +/// \param matCorr is the material correction type to be used in the track propagation +/// \param bz is the magnetic field +/// \param vDriftMgr is the TPC velocity drift manager +/// \param rejectPairsWithCommonDaughter is a flag to activate rejection of pairs sharing a daughter track +/// \return a bitmap with mass hypotesis if passes all cuts +template +bool buildAndSelectGamma(const Coll& collision, const std::array& dDaughtersIds, const std::array& dauTracks, const Cuts& cfgGammaCuts, HfResoCandidateV0& v0, o2::base::Propagator::MatCorrType const& matCorr, o2::aod::common::TPCVDriftManager* vDriftMgr, bool rejectPairsWithCommonDaughter) +{ + const auto& trackPos = dauTracks[0]; + const auto& trackNeg = dauTracks[1]; + if (trackPos.sign() * trackNeg.sign() > 0) { // reject same sign pair + return false; + } + if (trackPos.globalIndex() == trackNeg.globalIndex()) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackPos) && !trackNeg.hasITS()) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackNeg) && !trackPos.hasITS()) { + return false; + } + + // single-tracks selection + if (!selectV0Daughter(trackPos, dDaughtersIds, cfgGammaCuts, rejectPairsWithCommonDaughter) || !selectV0Daughter(trackNeg, dDaughtersIds, cfgGammaCuts, rejectPairsWithCommonDaughter)) { + return false; + } + if ((trackPos.hasTPC() && std::abs(trackPos.tpcNSigmaEl()) > cfgGammaCuts.nSigmaTpcEl.value) || (trackNeg.hasTPC() && std::abs(trackNeg.tpcNSigmaEl()) > cfgGammaCuts.nSigmaTpcEl.value)) { + return false; + } + + std::array dcaInfo; + auto trackParPos = getTrackParCov(trackPos); + if (o2::pwgem::photonmeson::isTPConlyTrack(trackPos) && !vDriftMgr->moveTPCTrack(collision, trackPos, trackParPos)) { + LOGP(error, "failed correction for positive tpc track"); + return false; + } + auto trackParPropPos = trackParPos; + trackParPropPos.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParPropPos, 2.f, matCorr, &dcaInfo); + auto trackPosDcaXY = dcaInfo[0]; + + auto trackParNeg = getTrackParCov(trackNeg); + if (o2::pwgem::photonmeson::isTPConlyTrack(trackNeg) && !vDriftMgr->moveTPCTrack(collision, trackNeg, trackParNeg)) { + LOGP(error, "failed correction for negative tpc track"); + return false; + } + auto trackParPropNeg = trackParNeg; + trackParPropNeg.setPID(o2::track::PID::Electron); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParPropNeg, 2.f, matCorr, &dcaInfo); + auto trackNegDcaXY = dcaInfo[0]; + + // daughters DCA to V0's collision primary vertex + if (std::fabs(trackPosDcaXY) < cfgGammaCuts.dcaMaxDauToPv.value || std::fabs(trackNegDcaXY) < cfgGammaCuts.dcaMaxDauToPv.value) { + return false; + } + + float gammaVtx[3] = {0.f, 0.f, 0.f}; + Vtx_recalculationParCov(o2::base::Propagator::Instance(), trackParPropPos, trackParPropNeg, gammaVtx, matCorr); + float radiusXy = std::hypot(gammaVtx[0], gammaVtx[1]); + const float maxX{83.1f}; // max X for track IU + const float marginTpc{7.f}; // margin for r cut in cm + if (radiusXy > maxX + marginTpc) { + return false; + } + if (radiusXy < std::fabs(gammaVtx[2]) * std::tan(2 * std::atan(std::exp(-cfgGammaCuts.etaMax.value))) - marginTpc) { + return false; // RZ line cut + } + + // vertex reconstruction + KFPTrack kfpTrackPos = createKFPTrackFromTrackParCov(trackParPropPos, trackPos.sign(), trackPos.tpcNClsFound(), trackPos.tpcChi2NCl()); + KFPTrack kfpTrackNeg = createKFPTrackFromTrackParCov(trackParPropNeg, trackNeg.sign(), trackNeg.tpcNClsFound(), trackNeg.tpcChi2NCl()); + KFParticle kfPartPos(kfpTrackPos, kPositron); + KFParticle kfPartNeg(kfpTrackNeg, kElectron); + const KFParticle* gammaDaughters[2] = {&kfPartPos, &kfPartNeg}; + + KFParticle gamma; + gamma.SetConstructMethod(2); + gamma.Construct(gammaDaughters, 2); + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + KFParticle KFPV(kfpVertex); + + // Transport the gamma to the recalculated decay vertex + KFParticle gammaDecayVtx = gamma; // with respect to (0,0,0) + gammaDecayVtx.TransportToPoint(gammaVtx); + v0.cosPA = cpaFromKF(gammaDecayVtx, KFPV); + if (v0.cosPA < cfgGammaCuts.cosPa.value) { + return false; + } + + v0.pos = {gammaDecayVtx.GetX(), gammaDecayVtx.GetY(), gammaDecayVtx.GetZ()}; + v0.radius = std::hypot(gammaDecayVtx.GetX(), gammaDecayVtx.GetY()); + if (v0.radius > maxX + marginTpc) { + return false; + } + if (v0.radius < std::fabs(gammaDecayVtx.GetZ()) * std::tan(2 * std::atan(std::exp(-cfgGammaCuts.etaMax.value))) - marginTpc) { + return false; // RZ line cut + } + if (v0.radius < cfgGammaCuts.radiusMin.value || cfgGammaCuts.radiusMax.value < v0.radius) { + return false; + } + + const float minRadTpcOnly{16.f}; + if ((!trackNeg.hasITS() && !trackNeg.hasITS()) && v0.radius < minRadTpcOnly) { // TPConly tracks can detect conversion points larger than minRadTpcOnly. + return false; + } + + // Apply a topological constraint of the gamma to the PV. Parameters will be given at the primary vertex. + KFParticle gammaPvConstr = gamma; + gammaPvConstr.SetProductionVertex(KFPV); + v0.mom = RecoDecay::pVec(std::array{gammaPvConstr.GetPx(), gammaPvConstr.GetPy(), gammaPvConstr.GetPz()}); + v0.pT = std::hypot(v0.mom[0], v0.mom[1]); + if (v0.pT < cfgGammaCuts.ptMin.value) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackNeg) && o2::pwgem::photonmeson::isITSonlyTrack(trackPos) && v0.pT > cfgGammaCuts.ptMaxItsOnly.value) { + return false; + } + v0.eta = RecoDecay::eta(v0.mom); + if (std::abs(v0.eta) > cfgGammaCuts.etaMax.value) { + return false; + } + + KFParticle kfPartDecayVtxPos = kfPartPos; // Don't set Primary Vertex + KFParticle kfPartDecayVtxNeg = kfPartNeg; // Don't set Primary Vertex + kfPartDecayVtxPos.TransportToPoint(gammaVtx); // Don't set Primary Vertex + kfPartDecayVtxNeg.TransportToPoint(gammaVtx); // Don't set Primary Vertex + v0.dcaDau = kfPartDecayVtxPos.GetDistanceFromParticle(kfPartDecayVtxNeg); + v0.momPos = RecoDecay::pVec(std::array{kfPartDecayVtxPos.GetPx(), kfPartDecayVtxPos.GetPy(), kfPartDecayVtxPos.GetPz()}); + v0.momNeg = RecoDecay::pVec(std::array{kfPartDecayVtxNeg.GetPx(), kfPartDecayVtxNeg.GetPy(), kfPartDecayVtxNeg.GetPz()}); + float ptItsOnlyMax{0.15f}; + if (o2::pwgem::photonmeson::isITSonlyTrack(trackPos) && std::hypot(v0.momPos[0], v0.momPos[1]) > ptItsOnlyMax) { + return false; + } + if (o2::pwgem::photonmeson::isITSonlyTrack(trackNeg) && std::hypot(v0.momNeg[0], v0.momNeg[1]) > ptItsOnlyMax) { + return false; + } + + const float maxRItsMft{66.f}; + if (!trackNeg.hasITS() && !trackPos.hasITS()) { // V0s with TPConly-TPConly + if (maxRItsMft < v0.radius && v0.radius < maxX + marginTpc) { + if (v0.dcaDau > cfgGammaCuts.dcaDauTpcInner.value) { + return false; + } + } else { + if (v0.dcaDau > cfgGammaCuts.dcaDauTpc.value) { + return false; + } + } + } else { // V0s with ITS hits + if (v0.radius < minRadTpcOnly) { + if (v0.dcaDau > cfgGammaCuts.dcaDauItsIb.value) { + return false; + } + } else { + if (v0.dcaDau > cfgGammaCuts.dcaDauIts.value) { + return false; + } + } + } + + // v0 DCA to primary vertex + v0.dcaV0ToPv = calculateDCAStraightToPV( + v0.pos[0], v0.pos[1], v0.pos[2], + v0.momPos[0] + v0.momNeg[0], + v0.momPos[1] + v0.momNeg[1], + v0.momPos[2] + v0.momNeg[2], + collision.posX(), collision.posY(), collision.posZ()); + if (std::abs(v0.dcaV0ToPv) > cfgGammaCuts.dcaPv.value) { + return false; + } + + // distinguish V0 hypotheses + v0.alpha = alphaAP(v0.mom, v0.momPos, v0.momNeg); + v0.qt = qtAP(v0.momPos, v0.momNeg); + ; + if (!checkAP(v0.alpha, v0.qt, cfgGammaCuts.alphaApMax.value, cfgGammaCuts.qtApMax.value)) { // store only photon conversions + return false; + } + v0.v0Type = BIT(BachelorType::Gamma); + return true; +} + /// Basic selection of tracks /// \param track is the track /// \param dDaughtersIds are the IDs of the D meson daughter tracks @@ -476,9 +732,22 @@ bool isTrackSelected(const Tr& track, const std::array& dDaughtersIds, c if (!track.hasTPC()) { return false; } - bool const isPion = std::abs(track.tpcNSigmaPi()) < cfgSingleTrackCuts.maxNsigmaTpcPi.value; - bool const isKaon = std::abs(track.tpcNSigmaKa()) < cfgSingleTrackCuts.maxNsigmaTpcKa.value; - bool const isProton = std::abs(track.tpcNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTpcPr.value; + // --- TPC PID --- + bool isPionTPC = std::abs(track.tpcNSigmaPi()) < cfgSingleTrackCuts.maxNsigmaTpcPi.value; + bool isKaonTPC = std::abs(track.tpcNSigmaKa()) < cfgSingleTrackCuts.maxNsigmaTpcKa.value; + bool isProtonTPC = std::abs(track.tpcNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTpcPr.value; + + // --- TOF PID --- + bool hasTOF = track.hasTOF(); + bool isPionTOF = hasTOF ? std::abs(track.tofNSigmaPi()) < cfgSingleTrackCuts.maxNsigmaTofPi.value : false; + bool isKaonTOF = hasTOF ? std::abs(track.tofNSigmaKa()) < cfgSingleTrackCuts.maxNsigmaTofKa.value : false; + bool isProtonTOF = hasTOF ? std::abs(track.tofNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTofPr.value : false; + + // --- Combined logic --- + bool isPion = isPionTPC && (!cfgSingleTrackCuts.forceTOF.value || isPionTOF); + bool isKaon = isKaonTPC && (!cfgSingleTrackCuts.forceTOF.value || isKaonTOF); + bool isProton = isProtonTPC && (!cfgSingleTrackCuts.forceTOF.value || isProtonTOF); + return (isPion || isKaon || isProton); // we keep the track if is it compatible with at least one of the PID hypotheses selected } @@ -945,6 +1214,7 @@ void fillMcRecoInfoDTrack(PParticles const& particlesMc, /// \param tracksIU is the trackIU table /// \param particlesMc is the MC particle table /// \param hfRejMap is the event rejection map from the HF event selection util +/// \param bz is the magnetic field /// \param pdg is the O2DatabasePDG service /// \param registry is the histogram registry /// \param matCorr is the material correction type to be used in the track propagation @@ -957,7 +1227,8 @@ void fillMcRecoInfoDTrack(PParticles const& particlesMc, /// \param rowMcRecV0Reduced is the MC reco D-V0 reduced table to be filled /// \param rowMcRecTrkReduced is the MC reco D-track reduced table to be filled /// \param rowCandDmesMlReduced is the ML reduced table to be filled -template +/// \param vDriftMgr is the TPC velocity drift manager object +template void runDataCreation(Coll const& collision, CCands const& candsD, BBachV0s const& bachelorV0s, @@ -974,6 +1245,7 @@ void runDataCreation(Coll const& collision, DmesCuts const& cfgDmesCuts, TrkCuts const& cfgSingleTrackCuts, V0Cuts const& cfgV0Cuts, + GammaCuts const& cfgGammaCuts, QaConfig const& cfgQaPlots, bool rejectPairsWithCommonDaughter, TableCollRed& rowCollisionReduced, @@ -982,16 +1254,19 @@ void runDataCreation(Coll const& collision, TableTrkRed& rowTrkReduced, TableMcRecV0Red& rowMcRecV0Reduced, TableMcRecTrkRed& rowMcRecTrkReduced, - TableCandDMlRed& rowCandDmesMlReduced) + TableCandDMlRed& rowCandDmesMlReduced, + o2::aod::common::TPCVDriftManager* vDriftMgr = nullptr) { int const indexHfReducedCollision = rowCollisionReduced.lastIndex() + 1; // 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; + std::map selectedGammas; bool fillHfReducedCollision = false; constexpr bool DoTracks = PairType == PairingType::TrackOnly || PairType == PairingType::V0AndTrack; constexpr bool DoV0s = PairType == PairingType::V0Only || PairType == PairingType::V0AndTrack; + constexpr bool DoGammas = PairType == PairingType::GammaOnly; // loop on D candidates for (const auto& candD : candsD) { // initialize variables depending on D meson type @@ -1131,6 +1406,8 @@ void runDataCreation(Coll const& collision, getPxPyPz(trackParK0, candV0.mom); } // compute resonance invariant mass and filling of QA histograms + registry.fill(HIST("hAP"), candV0.alpha, candV0.qt); + registry.fill(HIST("hV0Radius"), candV0.radius); if (TESTBIT(candV0.v0Type, BachelorType::K0s)) { registry.fill(HIST("hMassVsPtK0s"), candV0.pT, candV0.mK0Short); if constexpr (DType == DMesonType::Dstar) { @@ -1416,6 +1693,70 @@ void runDataCreation(Coll const& collision, } } // end of loop on bachelor tracks } // end of do tracks + if constexpr (DoGammas) { + for (const auto& gamma : bachelorV0s) { + auto trackPos = tracksIU.rawIteratorAt(gamma.posTrackId()); + auto trackNeg = tracksIU.rawIteratorAt(gamma.negTrackId()); + // Apply selsection + auto gammaDauTracks = std::array{trackPos, trackNeg}; + HfResoCandidateV0 candGamma; + if (!buildAndSelectGamma(collision, prongIdsD, gammaDauTracks, cfgGammaCuts, candGamma, matCorr, vDriftMgr, rejectPairsWithCommonDaughter)) { + continue; + } + // Get single track variables + float chi2TpcDauGammaMax = -1.f; + int nItsClsDauGammaMin = 8, nTpcCrossRowsDauGammaMin = 200; + for (const auto& gammaTrack : gammaDauTracks) { + if (gammaTrack.itsNCls() < nItsClsDauGammaMin) { + nItsClsDauGammaMin = gammaTrack.itsNCls(); + } + if (gammaTrack.tpcNClsCrossedRows() < nTpcCrossRowsDauGammaMin) { + nTpcCrossRowsDauGammaMin = gammaTrack.tpcNClsCrossedRows(); + } + if (gammaTrack.tpcChi2NCl() > chi2TpcDauGammaMax) { + chi2TpcDauGammaMax = gammaTrack.tpcChi2NCl(); + } + } + // propagate gamma to primary vertex (if enabled) + if (cfgGammaCuts.propagateGammatoPV.value) { + std::array const pVecGammaOrig = {candGamma.mom[0], candGamma.mom[1], candGamma.mom[2]}; + std::array dcaInfo{}; + auto trackParGamma = o2::track::TrackPar(candGamma.pos, pVecGammaOrig, 0, true); + trackParGamma.setPID(o2::track::PID::Photon); + trackParGamma.setAbsCharge(0); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParGamma, 2.f, matCorr, &dcaInfo); + getPxPyPz(trackParGamma, candGamma.mom); + } + registry.fill(HIST("hAP"), candGamma.alpha, candGamma.qt); + registry.fill(HIST("hV0Radius"), candGamma.radius); + if constexpr (DType == DMesonType::D0) { + varUtils.invMassReso = RecoDecay::m(std::array{varUtils.pVectorProng0, varUtils.pVectorProng1, candGamma.mom}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassKPlus, o2::constants::physics::MassGamma}); + varUtils.invMassResoBar = RecoDecay::m(std::array{varUtils.pVectorProng0, varUtils.pVectorProng1, candGamma.mom}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassPionCharged, o2::constants::physics::MassGamma}); + varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, candGamma.mom)); + if (!cfgQaPlots.applyCutsForQaHistograms.value || + ((varUtils.invMassD0 > cfgQaPlots.cutMassDMin.value && varUtils.invMassD0 < cfgQaPlots.cutMassDMax.value) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin.value && varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax.value))) { + registry.fill(HIST("hMassD0Gamma"), varUtils.ptReso, varUtils.invMassReso - varUtils.invMassD0); + registry.fill(HIST("hMassD0Gamma"), varUtils.ptReso, varUtils.invMassResoBar - varUtils.invMassD0Bar); + } + } + // fill V0 table --> use same for V0s and gammas + // if information on V0 already stored, go to next V0 + if (!selectedGammas.count(gamma.globalIndex())) { + rowCandV0Reduced(trackPos.globalIndex(), trackNeg.globalIndex(), + indexHfReducedCollision, + candGamma.pos[0], candGamma.pos[1], candGamma.pos[2], + candGamma.momPos[0], candGamma.momPos[1], candGamma.momPos[2], + candGamma.momNeg[0], candGamma.momNeg[1], candGamma.momNeg[2], + candGamma.cosPA, + candGamma.dcaV0ToPv, + nItsClsDauGammaMin, nTpcCrossRowsDauGammaMin, chi2TpcDauGammaMax, + candGamma.v0Type); + selectedGammas[gamma.globalIndex()] = rowCandV0Reduced.lastIndex(); + } + fillHfCandD = true; + } // end of loop on V0 candidates + } // end of do gammas // fill D candidate table if (fillHfCandD) { // fill candDplus table only once per D candidate, only if at least one V0 is found if constexpr (DType == DMesonType::Dplus) { diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index f3fcbc188d1..09f8bcd2d1b 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -196,6 +196,7 @@ DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMin, tpcNClsCrossedRowsProngMin, int); DECLARE_SOA_COLUMN(TpcChi2NClProngMax, tpcChi2NClProngMax, float); //! maximum value of TPC chi2 for the decay daughter tracks DECLARE_SOA_COLUMN(PtProngMin, ptProngMin, float); //! minimum value of transverse momentum for the decay daughter tracks DECLARE_SOA_COLUMN(AbsEtaProngMin, absEtaProngMin, float); //! minimum value of absolute pseudorapidity for the decay daughter tracks +DECLARE_SOA_COLUMN(TrackType, trackType, uint8_t); //! particle type according to PID selection (pion, kaon, proton) // dynamic columns DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! transverse momentum @@ -846,6 +847,11 @@ DECLARE_SOA_TABLE(HfRedLbLcMls, "AOD", "HFREDLBLCML", //! Table with ML scores f using HfRedCandLb = soa::Join; +namespace hf_cand_mc_flag +{ +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! reconstruction level +} + namespace hf_b0_mc { // MC Rec @@ -873,9 +879,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedDpPis, "AOD", "HFMCRECREDDPPI", //! Table with reconstructed MC information on DPi(<-B0) pairs for reduced workflow hf_cand_b0_reduced::Prong0Id, hf_cand_b0_reduced::Prong1Id, - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagWrongCollision, - hf_cand_b0::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_b0_mc::PtMother); // try with extended table ? @@ -893,17 +899,17 @@ DECLARE_SOA_TABLE(HfMcCheckDpPis, "AOD", "HFMCCHECKDPPI", //! Table with reconst DECLARE_SOA_TABLE(HfMcRecRedDStarPis, "AOD", "HFMCRECREDDSTPI", //! Table with reconstructed MC information on DStarPi pairs for reduced workflow hf_cand_b0_reduced::ProngD0Id, hf_cand_b0_reduced::ProngBachPiId, - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagWrongCollision, - hf_cand_b0::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_b0_mc::PtMother); // Table with same size as HFCANDB0 DECLARE_SOA_TABLE(HfMcRecRedB0s, "AOD", "HFMCRECREDB0", //! Reconstruction-level MC information on B0 candidates for reduced workflow - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagMcDecayChanRec, - hf_cand_b0::FlagWrongCollision, - hf_cand_b0::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_b0_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstructed MC information on B0 candidates for MC checks in reduced workflow @@ -916,8 +922,8 @@ DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC information on B0 candidates for reduced workflow - hf_cand_b0::FlagMcMatchGen, - hf_cand_b0::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanRec, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, hf_b0_mc::EtaTrack, @@ -969,19 +975,19 @@ DECLARE_SOA_COLUMN(PdgCodeProng2, pdgCodeProng2, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with reconstructed MC information on D0Pi(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id, - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagWrongCollision, - hf_cand_bplus::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bplus_mc::PtMother); // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfMcRecRedJPKs, "AOD", "HFMCRECREDJPK", //! Table with reconstructed MC information on J/PsiK(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::JpsiId, hf_cand_bplus_reduced::BachKaId, - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::FlagWrongCollision, - hf_cand_bplus::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bplus_mc::PtMother); // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", @@ -995,10 +1001,10 @@ DECLARE_SOA_TABLE(HfMcCheckD0Pis, "AOD", "HFMCCHECKD0PI", //! Table with reconst // Table with same size as HFCANDBPLUS DECLARE_SOA_TABLE(HfMcRecRedBps, "AOD", "HFMCRECREDBP", //! Reconstruction-level MC information on B+ candidates for reduced workflow - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::FlagWrongCollision, - hf_cand_bplus::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bplus_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstructed MC information on B+ candidates for MC checks in reduced workflow @@ -1010,8 +1016,8 @@ DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC information on B+ candidates for reduced workflow - hf_cand_bplus::FlagMcMatchGen, - hf_cand_bplus::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanRec, hf_bplus_mc::PtTrack, hf_bplus_mc::YTrack, hf_bplus_mc::EtaTrack, @@ -1070,9 +1076,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow hf_cand_bs_reduced::Prong0Id, hf_cand_bs_reduced::Prong1Id, - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagWrongCollision, - hf_cand_bs::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bs_mc::PtMother); // table with results of reconstruction level MC matching @@ -1080,10 +1086,10 @@ DECLARE_SOA_TABLE(HfMcRecRedJPPhis, "AOD", "HFMCRECREDJPPHI", //! Table with rec hf_cand_bs_reduced::JpsiId, hf_cand_bs_reduced::Prong0PhiId, hf_cand_bs_reduced::Prong1PhiId, - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec, - hf_cand_bs::FlagWrongCollision, - hf_cand_bs::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bs_mc::PtMother); // try with extended table ? @@ -1099,10 +1105,10 @@ DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconst // Table with same size as HFCANDBS DECLARE_SOA_TABLE(HfMcRecRedBss, "AOD", "HFMCRECREDBS", //! Reconstruction-level MC information on Bs candidates for reduced workflow - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec, - hf_cand_bs::FlagWrongCollision, - hf_cand_bs::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_bs_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstructed MC information on Bs candidates for MC checks in reduced workflow @@ -1115,8 +1121,8 @@ DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC information on Bs candidates for reduced workflow - hf_cand_bs::FlagMcMatchGen, - hf_cand_bs::FlagMcDecayChanRec, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanRec, hf_bs_mc::PtTrack, hf_bs_mc::YTrack, hf_bs_mc::EtaTrack, @@ -1172,9 +1178,9 @@ DECLARE_SOA_COLUMN(PdgCodeProng3, pdgCodeProng3, int); //! Pdg code DECLARE_SOA_TABLE(HfMcRecRedLcPis, "AOD", "HFMCRECREDLCPI", //! Table with reconstructed MC information on LcPi(<-Lb) pairs for reduced workflow hf_cand_lb_reduced::Prong0Id, hf_cand_lb_reduced::Prong1Id, - hf_cand_lb::FlagMcMatchRec, - hf_cand_lb::FlagWrongCollision, - hf_cand_lb::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_lb_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckLcPis, "AOD", "HFMCCHECKLCPI", //! Table with reconstructed MC information on LcPi(<-Lb) pairs for MC checks in reduced workflow @@ -1188,9 +1194,9 @@ DECLARE_SOA_TABLE(HfMcCheckLcPis, "AOD", "HFMCCHECKLCPI", //! Table with reconst // Table with same size as HFCANDLc DECLARE_SOA_TABLE(HfMcRecRedLbs, "AOD", "HFMCRECREDLB", //! Reconstruction-level MC information on Lb candidates for reduced workflow - hf_cand_lb::FlagMcMatchRec, - hf_cand_lb::FlagWrongCollision, - hf_cand_lb::DebugMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagWrongCollision, + hf_cand_mc_flag::DebugMcRec, hf_lb_mc::PtMother); DECLARE_SOA_TABLE(HfMcCheckLbs, "AOD", "HFMCCHECKLB", //! Table with reconstructed MC information on Lb candidates for MC checks in reduced workflow @@ -1203,7 +1209,7 @@ DECLARE_SOA_TABLE(HfMcCheckLbs, "AOD", "HFMCCHECKLB", //! Table with reconstruct o2::soa::Marker<2>); DECLARE_SOA_TABLE(HfMcGenRedLbs, "AOD", "HFMCGENREDLB", //! Generation-level MC information on Lb candidates for reduced workflow - hf_cand_lb::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcMatchGen, hf_lb_mc::PtTrack, hf_lb_mc::YTrack, hf_lb_mc::EtaTrack, @@ -1553,7 +1559,7 @@ DECLARE_SOA_TABLE(Hf3PrV0McRec, "AOD", "HF3PRV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", @@ -1566,7 +1572,7 @@ DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", @@ -1579,7 +1585,7 @@ DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", @@ -1592,7 +1598,7 @@ DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", @@ -1605,7 +1611,7 @@ DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", @@ -1618,11 +1624,11 @@ DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level MC information on Ds-Resonances candidates for reduced workflow - hf_cand_b0::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcMatchGen, hf_reso_cand_reduced::Origin, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, @@ -1646,8 +1652,21 @@ DECLARE_SOA_TABLE(HfMcRecRedResos, "AOD", "HFMCRECREDRESO", //! Reconstruction-l hf_reso_cand_reduced::Origin, hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker<1>); + +//! Table with selected tracks for Hc analysis +DECLARE_SOA_TABLE(HcSelTracks, "AOD", "HCSELTRACKS", + o2::soa::Index<>, + // Indices + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + // Static + hf_track_vars_reduced::Px, + hf_track_vars_reduced::Py, + hf_track_vars_reduced::Pz, + hf_track_vars_reduced::Sign, + hf_track_vars_reduced::TrackType); } // namespace aod namespace soa diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.cxx b/PWGHF/D2H/Macros/HFInvMassFitter.cxx index 843712e2245..e56c9b87a28 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.cxx +++ b/PWGHF/D2H/Macros/HFInvMassFitter.cxx @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -55,153 +56,84 @@ using namespace RooFit; -ClassImp(HFInvMassFitter); - -HFInvMassFitter::HFInvMassFitter() : mHistoInvMass(nullptr), - mFitOption("L,E"), - mMinMass(0), - mMaxMass(5), - mTypeOfBkgPdf(Expo), - mTypeOfSgnPdf(SingleGaus), - mTypeOfReflPdf(1), - mMassParticle(TDatabasePDG::Instance()->GetParticle("D0")->Mass()), - mMass(1.865), - mMassLowLimit(0), - mMassUpLimit(0), - mMassReflLowLimit(0), - mMassReflUpLimit(0), - mSecMass(1.969), - mSigmaSgn(0.012), - mSecSigma(0.006), - mNSigmaForSidebands(4.), - mNSigmaForSgn(3.), - mSigmaSgnErr(0.), - mSigmaSgnDoubleGaus(0.025), - mFixedMean(kFALSE), - mBoundMean(kFALSE), - mBoundReflMean(kFALSE), - mFixedSigma(kFALSE), - mFixedSigmaDoubleGaus(kFALSE), - mBoundSigma(kFALSE), - mSigmaValue(0.012), - mParamSgn(0.1), - mFracDoubleGaus(0.2), - mFixedRawYield(-1.), - mFixedFracDoubleGaus(kFALSE), - mRatioDoubleGausSigma(0.), - mFixedRatioDoubleGausSigma(kFALSE), - mReflOverSgn(0), - mEnableReflections(kFALSE), - mRawYield(0), - mRawYieldErr(0), - mRawYieldCounted(0), - mRawYieldCountedErr(0), - mBkgYield(0), - mBkgYieldErr(0), - mSignificance(0), - mSignificanceErr(0), - mChiSquareOverNdfTotal(0), - mChiSquareOverNdfBkg(0), - mFixReflOverSgn(kFALSE), - mRooMeanSgn(nullptr), - mRooSigmaSgn(nullptr), - mRooSecSigmaSgn(nullptr), - mRooFracDoubleGaus(nullptr), - mSgnPdf(nullptr), - mBkgPdf(nullptr), - mReflPdf(nullptr), - mRooNSgn(nullptr), - mRooNBkg(nullptr), - mRooNRefl(nullptr), - mTotalPdf(nullptr), - mInvMassFrame(nullptr), - mReflFrame(nullptr), - mReflOnlyFrame(nullptr), - mResidualFrame(nullptr), - mResidualFrameForCalculation(nullptr), - mWorkspace(nullptr), - mIntegralHisto(0), - mIntegralBkg(0), - mIntegralSgn(0), - mHistoTemplateRefl(nullptr), - mDrawBgPrefit(kFALSE), - mHighlightPeakRegion(kFALSE) -{ - // default constructor -} - -HFInvMassFitter::HFInvMassFitter(const TH1* histoToFit, Double_t minValue, Double_t maxValue, Int_t fitTypeBkg, Int_t fitTypeSgn) : mHistoInvMass(nullptr), - mFitOption("L,E"), - mMinMass(minValue), - mMaxMass(maxValue), - mTypeOfBkgPdf(fitTypeBkg), - mTypeOfSgnPdf(fitTypeSgn), - mTypeOfReflPdf(1), - mMassParticle(TDatabasePDG::Instance()->GetParticle("D0")->Mass()), - mMass(1.865), - mMassLowLimit(0), - mMassUpLimit(0), - mMassReflLowLimit(0), - mMassReflUpLimit(0), - mSecMass(1.969), - mSigmaSgn(0.012), - mSecSigma(0.006), - mNSigmaForSidebands(3.), - mNSigmaForSgn(3.), - mSigmaSgnErr(0.), - mSigmaSgnDoubleGaus(0.025), - mFixedMean(kFALSE), - mBoundMean(kFALSE), - mBoundReflMean(kFALSE), - mFixedSigma(kFALSE), - mFixedSigmaDoubleGaus(kFALSE), - mBoundSigma(kFALSE), - mSigmaValue(0.012), - mParamSgn(0.1), - mFracDoubleGaus(0.2), - mFixedRawYield(-1.), - mFixedFracDoubleGaus(kFALSE), - mRatioDoubleGausSigma(0.), - mFixedRatioDoubleGausSigma(kFALSE), - mReflOverSgn(0), - mEnableReflections(kFALSE), - mRawYield(0), - mRawYieldErr(0), - mRawYieldCounted(0), - mRawYieldCountedErr(0), - mBkgYield(0), - mBkgYieldErr(0), - mSignificance(0), - mSignificanceErr(0), - mChiSquareOverNdfTotal(0), - mChiSquareOverNdfBkg(0), - mFixReflOverSgn(kFALSE), - mRooMeanSgn(nullptr), - mRooSigmaSgn(nullptr), - mRooSecSigmaSgn(nullptr), - mRooFracDoubleGaus(nullptr), - mSgnPdf(nullptr), - mBkgPdf(nullptr), - mReflPdf(nullptr), - mRooNSgn(nullptr), - mRooNBkg(nullptr), - mRooNRefl(nullptr), - mTotalPdf(nullptr), - mInvMassFrame(nullptr), - mReflFrame(nullptr), - mReflOnlyFrame(nullptr), - mResidualFrame(nullptr), - mResidualFrameForCalculation(nullptr), - mWorkspace(nullptr), - mIntegralHisto(0), - mIntegralBkg(0), - mIntegralSgn(0), - mHistoTemplateRefl(nullptr), - mDrawBgPrefit(kFALSE), - mHighlightPeakRegion(kFALSE) +HFInvMassFitter::HFInvMassFitter(TH1* histoToFit, + double minValue, + double maxValue, + int fitTypeBkg, + int fitTypeSgn) : mHistoInvMass(nullptr), + mFitOption("L,E"), + mMinMass(minValue), + mMaxMass(maxValue), + mTypeOfBkgPdf(fitTypeBkg), + mTypeOfSgnPdf(fitTypeSgn), + mTypeOfReflPdf(1), + mMassParticle(TDatabasePDG::Instance()->GetParticle("D0")->Mass()), + mMass(1.865), + mMassLowLimit(0), + mMassUpLimit(0), + mMassReflLowLimit(0), + mMassReflUpLimit(0), + mSecMass(1.969), + mSigmaSgn(0.012), + mSecSigma(0.006), + mNSigmaForSidebands(3.), + mNSigmaForSgn(3.), + mSigmaSgnErr(0.), + mSigmaSgnDoubleGaus(0.025), + mFixedMean(false), + mBoundMean(false), + mBoundReflMean(false), + mFixedSigma(false), + mFixedSigmaDoubleGaus(false), + mBoundSigma(false), + mSigmaValue(0.012), + mParamSgn(0.1), + mFracDoubleGaus(0.2), + mFixedRawYield(-1.), + mFixedFracDoubleGaus(false), + mRatioDoubleGausSigma(0.), + mFixedRatioDoubleGausSigma(false), + mReflOverSgn(0), + mEnableReflections(false), + mRawYield(0), + mRawYieldErr(0), + mRawYieldCounted(0), + mRawYieldCountedErr(0), + mBkgYield(0), + mBkgYieldErr(0), + mSignificance(0), + mSignificanceErr(0), + mChiSquareOverNdfTotal(0), + mChiSquareOverNdfBkg(0), + mFixReflOverSgn(false), + mRooMeanSgn(nullptr), + mRooSigmaSgn(nullptr), + mRooSecSigmaSgn(nullptr), + mRooFracDoubleGaus(nullptr), + mSgnPdf(nullptr), + mBkgPdf(nullptr), + mReflPdf(nullptr), + mRooNSgn(nullptr), + mRooNBkg(nullptr), + mRooNRefl(nullptr), + mTotalPdf(nullptr), + mInvMassFrame(nullptr), + mReflFrame(nullptr), + mReflOnlyFrame(nullptr), + mResidualFrame(nullptr), + mRatioFrame(nullptr), + mResidualFrameForCalculation(nullptr), + mWorkspace(nullptr), + mIntegralHisto(0), + mIntegralBkg(0), + mIntegralSgn(0), + mHistoTemplateRefl(nullptr), + mDrawBgPrefit(false), + mHighlightPeakRegion(false) { // standard constructor - mHistoInvMass = dynamic_cast(histoToFit->Clone(histoToFit->GetTitle())); + mHistoInvMass = histoToFit; + mHistoInvMass->SetName("mHistoInvMass"); mHistoInvMass->SetDirectory(nullptr); } @@ -265,7 +197,7 @@ void HFInvMassFitter::doFit() if (mTypeOfBkgPdf == NoBkg) { // MC mRooNSgn = new RooRealVar("mRooNSig", "number of signal", 0.3 * mIntegralHisto, 0., 1.2 * mIntegralHisto); // signal yield mTotalPdf = new RooAddPdf("mMCFunc", "MC fit function", RooArgList(*sgnPdf), RooArgList(*mRooNSgn)); // create total pdf - if (strcmp(mFitOption.Data(), "Chi2") == 0) { + if (strcmp(mFitOption.c_str(), "Chi2") == 0) { mTotalPdf->chi2FitTo(dataHistogram, Range("signal")); } else { mTotalPdf->fitTo(dataHistogram, Range("signal")); @@ -274,16 +206,19 @@ void HFInvMassFitter::doFit() mIntegralSgn = signalIntegralMc->getValV(); calculateSignal(mRawYield, mRawYieldErr); // calculate signal and signal error mTotalPdf->plotOn(mInvMassFrame, Name("Tot_c")); // plot total function - } else { // data + // Fit to data ratio + mRatioFrame = mass->frame(Title(Form("%s", mHistoInvMass->GetTitle()))); + calculateFitToDataRatio(); + } else { // data mBkgPdf = new RooAddPdf("mBkgPdf", "background fit function", RooArgList(*bkgPdf), RooArgList(*mRooNBkg)); if (mTypeOfSgnPdf == GausSec) { // two peak fit - if (strcmp(mFitOption.Data(), "Chi2") == 0) { + if (strcmp(mFitOption.c_str(), "Chi2") == 0) { mBkgPdf->chi2FitTo(dataHistogram, Range("SBL,SBR,SEC"), Save()); } else { mBkgPdf->fitTo(dataHistogram, Range("SBL,SBR,SEC"), Save()); } } else { // single peak fit - if (strcmp(mFitOption.Data(), "Chi2") == 0) { + if (strcmp(mFitOption.c_str(), "Chi2") == 0) { mBkgPdf->chi2FitTo(dataHistogram, Range("SBL,SBR"), Save()); } else { mBkgPdf->fitTo(dataHistogram, Range("SBL,SBR"), Save()); @@ -295,24 +230,23 @@ void HFInvMassFitter::doFit() mBkgPdf->plotOn(frameTemporary, Range("SBL", true), Name("Bkg_sidebands")); mChiSquareOverNdfBkg = frameTemporary->chiSquare("Bkg_sidebands", "data_for_bkgchi2"); // calculate reduced chi2 / NDF of background sidebands (pre-fit) delete frameTemporary; - RooAbsPdf* mBkgPdfPrefit{nullptr}; if (mDrawBgPrefit) { - mBkgPdfPrefit = dynamic_cast(mBkgPdf->Clone()); - mBkgPdfPrefit->plotOn(mInvMassFrame, Range("full"), Name("Bkg_c_prefit"), LineColor(kGray)); - delete mBkgPdfPrefit; + RooAbsPdf* bkgPdfPrefit = dynamic_cast(mBkgPdf->Clone()); + bkgPdfPrefit->plotOn(mInvMassFrame, Range("full"), Name("Bkg_c_prefit"), LineColor(kGray)); + delete bkgPdfPrefit; } // estimate signal yield RooAbsReal* bkgIntegral = mBkgPdf->createIntegral(*mass, NormSet(*mass), Range("bkg")); // bkg integral mIntegralBkg = bkgIntegral->getValV(); // fraction of BG's integral in "bkg" range out of that in "full" range (which is 1 by construction). Not an absolute value. - Double_t estimatedSignal; + double estimatedSignal{}; checkForSignal(estimatedSignal); // SIG's absolute integral in "bkg" range calculateBackground(mBkgYield, mBkgYieldErr); // BG's absolute integral in "bkg" range mRooNSgn = new RooRealVar("mNSgn", "number of signal", 0.3 * estimatedSignal, 0., 1.2 * estimatedSignal); // estimated signal yield if (mFixedRawYield > 0) { mRooNSgn->setVal(mFixedRawYield); // fixed signal yield - mRooNSgn->setConstant(kTRUE); + mRooNSgn->setConstant(true); } mSgnPdf = new RooAddPdf("mSgnPdf", "signal fit function", RooArgList(*sgnPdf), RooArgList(*mRooNSgn)); // create reflection template and fit to reflection @@ -324,7 +258,7 @@ void HFInvMassFitter::doFit() reflHistogram.plotOn(mReflOnlyFrame); mRooNRefl = new RooRealVar("mNRefl", "number of reflection", 0.5 * mHistoTemplateRefl->Integral(), 0, mHistoTemplateRefl->Integral()); RooAddPdf reflFuncTemp("reflFuncTemp", "template reflection fit function", RooArgList(*reflPdf), RooArgList(*mRooNRefl)); - if (strcmp(mFitOption.Data(), "Chi2") == 0) { + if (strcmp(mFitOption.c_str(), "Chi2") == 0) { reflFuncTemp.chi2FitTo(reflHistogram); } else { reflFuncTemp.fitTo(reflHistogram); @@ -332,10 +266,10 @@ void HFInvMassFitter::doFit() reflFuncTemp.plotOn(mReflOnlyFrame); mRooNRefl->setVal(mReflOverSgn * estimatedSignal); - mRooNRefl->setConstant(kTRUE); + mRooNRefl->setConstant(true); setReflFuncFixed(); // fix reflection pdf parameter mTotalPdf = new RooAddPdf("mTotalPdf", "background + signal + reflection fit function", RooArgList(*bkgPdf, *sgnPdf, *reflPdf), RooArgList(*mRooNBkg, *mRooNSgn, *mRooNRefl)); - if (strcmp(mFitOption.Data(), "Chi2") == 0) { + if (strcmp(mFitOption.c_str(), "Chi2") == 0) { mTotalPdf->chi2FitTo(dataHistogram); } else { mTotalPdf->fitTo(dataHistogram); @@ -355,7 +289,7 @@ void HFInvMassFitter::doFit() mSgnPdf->plotOn(mResidualFrame, Normalization(1.0, RooAbsReal::RelativeExpected), LineColor(kBlue)); } else { mTotalPdf = new RooAddPdf("mTotalPdf", "background + signal pdf", RooArgList(*bkgPdf, *sgnPdf), RooArgList(*mRooNBkg, *mRooNSgn)); - if (strcmp(mFitOption.Data(), "Chi2") == 0) { + if (strcmp(mFitOption.c_str(), "Chi2") == 0) { mTotalPdf->chi2FitTo(dataHistogram); } else { mTotalPdf->fitTo(dataHistogram); @@ -437,12 +371,12 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const // signal Gaussian if (mFixedMean) { mean.setVal(mMass); - mean.setConstant(kTRUE); + mean.setConstant(true); } RooRealVar sigma("sigma", "sigma for signal", mSigmaSgn, mSigmaSgn - 0.01, mSigmaSgn + 0.01); if (mFixedSigma) { sigma.setVal(mSigmaSgn); - sigma.setConstant(kTRUE); + sigma.setConstant(true); } if (mBoundSigma) { sigma.setMax(mSigmaSgn * (1 + mParamSgn)); @@ -459,18 +393,18 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const } if (mFixedSigma) { sigma.setVal(mSigmaSgn); - sigma.setConstant(kTRUE); + sigma.setConstant(true); } if (mFixedSigmaDoubleGaus) { sigmaDoubleGaus.setVal(mSigmaSgnDoubleGaus); - sigmaDoubleGaus.setConstant(kTRUE); + sigmaDoubleGaus.setConstant(true); } RooGaussian const gaus1("gaus1", "gaus1", mass, mean, sigma); RooGaussian const gaus2("gaus2", "gaus2", mass, mean, sigmaDoubleGaus); RooRealVar fracDoubleGaus("fracDoubleGaus", "frac of two gauss", mFracDoubleGaus, 0, 1.); if (mFixedFracDoubleGaus) { fracDoubleGaus.setVal(mFracDoubleGaus); - fracDoubleGaus.setConstant(kTRUE); + fracDoubleGaus.setConstant(true); } RooAbsPdf* sgnFuncDoubleGaus = new RooAddPdf("sgnFuncDoubleGaus", "signal pdf", RooArgList(gaus1, gaus2), fracDoubleGaus); workspace.import(*sgnFuncDoubleGaus); @@ -479,11 +413,11 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const RooRealVar ratio("ratio", "ratio of sigma12", mRatioDoubleGausSigma, 0, 10); if (mFixedSigma) { sigma.setVal(mSigmaSgn); - sigma.setConstant(kTRUE); + sigma.setConstant(true); } if (mFixedRatioDoubleGausSigma) { ratio.setVal(mRatioDoubleGausSigma); - ratio.setConstant(kTRUE); + ratio.setConstant(true); } if (mBoundSigma) { sigma.setMax(mSigmaSgn * (1 + mParamSgn)); @@ -495,7 +429,7 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const RooRealVar fracDoubleGausRatio("fracDoubleGausRatio", "fraction of two gauss ratio", 0.5, 0, 1.); if (mFixedFracDoubleGaus) { fracDoubleGausRatio.setVal(mFracDoubleGaus); - fracDoubleGausRatio.setConstant(kTRUE); + fracDoubleGausRatio.setConstant(true); } RooAbsPdf* sgnFuncGausRatio = new RooAddPdf("sgnFuncGausRatio", "signal pdf", RooArgList(gausRatio1, gausRatio2), fracDoubleGausRatio); workspace.import(*sgnFuncGausRatio); @@ -505,7 +439,7 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const RooRealVar sigmaSec("sigmaSec", "sigmaSec", mSecSigma, mSecSigma - 0.005, mSecSigma + 0.01); if (mFixedMean) { meanSec.setVal(mSecMass); - meanSec.setConstant(kTRUE); + meanSec.setConstant(true); } if (mBoundMean) { meanSec.setMax(mMassUpLimit); @@ -513,7 +447,7 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const } if (mFixedSigma) { sigmaSec.setVal(mSecSigma); - sigmaSec.setConstant(kTRUE); + sigmaSec.setConstant(true); } if (mBoundSigma) { sigmaSec.setMax(mSecSigma * (1 + mParamSgn)); @@ -566,7 +500,7 @@ void HFInvMassFitter::fillWorkspace(RooWorkspace& workspace) const } // draw fit output -void HFInvMassFitter::drawFit(TVirtualPad* pad, const std::vector& plotLabels, Bool_t writeParInfo) +void HFInvMassFitter::drawFit(TVirtualPad* pad, const std::vector& plotLabels, bool writeParInfo) { gStyle->SetOptStat(0); gStyle->SetCanvasColor(0); @@ -581,9 +515,9 @@ void HFInvMassFitter::drawFit(TVirtualPad* pad, const std::vector& textFitMetrics->AddText(Form("S = %.0f #pm %.0f ", mRawYield, mRawYieldErr)); textFitMetrics->AddText(Form("S_{count} = %.0f #pm %.0f ", mRawYieldCounted, mRawYieldCountedErr)); if (mTypeOfBkgPdf != NoBkg) { - textFitMetrics->AddText(Form("B (%d#sigma) = %.0f #pm %.0f", mNSigmaForSidebands, mBkgYield, mBkgYieldErr)); - textFitMetrics->AddText(Form("S/B (%d#sigma) = %.4g ", mNSigmaForSidebands, mRawYield / mBkgYield)); - textFitMetrics->AddText(Form("Significance (%d#sigma) = %.1f #pm %.1f ", mNSigmaForSidebands, mSignificance, mSignificanceErr)); + textFitMetrics->AddText(Form("B (%.1f#sigma) = %.0f #pm %.0f", mNSigmaForSidebands, mBkgYield, mBkgYieldErr)); + textFitMetrics->AddText(Form("S/B (%.1f#sigma) = %.4g ", mNSigmaForSidebands, mRawYield / mBkgYield)); + textFitMetrics->AddText(Form("Significance (%.1f#sigma) = %.1f #pm %.1f ", mNSigmaForSidebands, mSignificance, mSignificanceErr)); textFitMetrics->AddText(Form("#chi^{2} / ndf = %.3f", mChiSquareOverNdfTotal)); } if (mReflPdf != nullptr) { @@ -607,26 +541,13 @@ void HFInvMassFitter::drawFit(TVirtualPad* pad, const std::vector& textSignalPar->SetFillStyle(0); textSignalPar->SetTextColor(kBlue); textSignalPar->SetTextAlign(13); - if (mFixedMean) { - textSignalPar->AddText(Form("mean(fixed) = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); - } else { - textSignalPar->AddText(Form("mean(free) = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); - } + const std::string fixMeanStatus = mFixedMean ? "fixed" : "free"; + const std::string fixSigmaStatus = mFixedSigma ? "fixed" : "free"; + const std::string fixSigmaDoubleGausStatus = mFixedSigmaDoubleGaus ? "fixed" : "free"; + textSignalPar->AddText(Form("mean(%s) = %.3f #pm %.3f", fixMeanStatus.c_str(), mRooMeanSgn->getVal(), mRooMeanSgn->getError())); + textSignalPar->AddText(Form("sigma(%s) = %.3f #pm %.3f", fixSigmaStatus.c_str(), mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); if (mTypeOfSgnPdf == DoubleGaus) { - if (mFixedSigma) { - textSignalPar->AddText(Form("sigma(fixed) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); - } else { - textSignalPar->AddText(Form("sigma(free) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); - } - if (mFixedSigmaDoubleGaus) { - textSignalPar->AddText(Form("sigma 2(fixed) = %.3f #pm %.3f", mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); - } else { - textSignalPar->AddText(Form("sigma 2(free) = %.3f #pm %.3f", mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); - } - } else if (mFixedSigma) { - textSignalPar->AddText(Form("sigma(fixed) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); - } else { - textSignalPar->AddText(Form("sigma(free) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + textSignalPar->AddText(Form("sigma 2(%s) = %.3f #pm %.3f", fixSigmaDoubleGausStatus.c_str(), mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); } mInvMassFrame->addObject(textSignalPar); } @@ -654,11 +575,9 @@ void HFInvMassFitter::drawResidual(TVirtualPad* pad) textInfo->AddText(Form("S = %.0f #pm %.0f ", mRawYield, mRawYieldErr)); textInfo->AddText(Form("S_{count} = %.0f #pm %.0f ", mRawYieldCounted, mRawYieldCountedErr)); textInfo->AddText(Form("mean = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); + textInfo->AddText(Form("sigma = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); if (mTypeOfSgnPdf == DoubleGaus) { - textInfo->AddText(Form("sigma = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); textInfo->AddText(Form("sigma 2 = %.3f #pm %.3f", mRooSecSigmaSgn->getVal(), mRooSecSigmaSgn->getError())); - } else { - textInfo->AddText(Form("sigma = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); } mResidualFrame->addObject(textInfo); mResidualFrame->Draw(); @@ -691,10 +610,10 @@ void HFInvMassFitter::highlightPeakRegion(const RooPlot* plot, Color_t color, Wi } double const yMin = plot->GetMinimum(); double const yMax = plot->GetMaximum(); - const Double_t mean = mRooMeanSgn->getVal(); - const Double_t sigma = mRooSecSigmaSgn->getVal(); - const Double_t minForSgn = mean - mNSigmaForSidebands * sigma; - const Double_t maxForSgn = mean + mNSigmaForSidebands * sigma; + const double mean = mRooMeanSgn->getVal(); + const double sigma = mRooSecSigmaSgn->getVal(); + const double minForSgn = mean - mNSigmaForSidebands * sigma; + const double maxForSgn = mean + mNSigmaForSidebands * sigma; auto* leftLine = new TLine(minForSgn, yMin, minForSgn, yMax); auto* rightLine = new TLine(maxForSgn, yMin, maxForSgn, yMax); for (const auto& line : std::array{leftLine, rightLine}) { @@ -714,27 +633,27 @@ void HFInvMassFitter::drawReflection(TVirtualPad* pad) } // calculate signal yield via bin counting -void HFInvMassFitter::countSignal(Double_t& signal, Double_t& signalErr) const -{ - const Double_t mean = mRooMeanSgn->getVal(); - const Double_t sigma = mRooSecSigmaSgn->getVal(); - const Double_t minForSgn = mean - mNSigmaForSidebands * sigma; - const Double_t maxForSgn = mean + mNSigmaForSidebands * sigma; - const Int_t binForMinSgn = mHistoInvMass->FindBin(minForSgn); - const Int_t binForMaxSgn = mHistoInvMass->FindBin(maxForSgn); - const Double_t binForMinSgnUpperEdge = mHistoInvMass->GetBinLowEdge(binForMinSgn + 1); - const Double_t binForMaxSgnLowerEdge = mHistoInvMass->GetBinLowEdge(binForMaxSgn); - const Double_t binForMinSgnFraction = (binForMinSgnUpperEdge - minForSgn) / mHistoInvMass->GetBinWidth(binForMinSgn); - const Double_t binForMaxSgnFraction = (maxForSgn - binForMaxSgnLowerEdge) / mHistoInvMass->GetBinWidth(binForMaxSgn); - - Double_t sum = 0; +void HFInvMassFitter::countSignal(double& signal, double& signalErr) const +{ + const double mean = mRooMeanSgn->getVal(); + const double sigma = mRooSecSigmaSgn->getVal(); + const double minForSgn = mean - mNSigmaForSidebands * sigma; + const double maxForSgn = mean + mNSigmaForSidebands * sigma; + const int binForMinSgn = mHistoInvMass->FindBin(minForSgn); + const int binForMaxSgn = mHistoInvMass->FindBin(maxForSgn); + const double binForMinSgnUpperEdge = mHistoInvMass->GetBinLowEdge(binForMinSgn + 1); + const double binForMaxSgnLowerEdge = mHistoInvMass->GetBinLowEdge(binForMaxSgn); + const double binForMinSgnFraction = (binForMinSgnUpperEdge - minForSgn) / mHistoInvMass->GetBinWidth(binForMinSgn); + const double binForMaxSgnFraction = (maxForSgn - binForMaxSgnLowerEdge) / mHistoInvMass->GetBinWidth(binForMaxSgn); + + double sum = 0; sum += mHistoInvMass->GetBinContent(binForMinSgn) * binForMinSgnFraction; - for (Int_t iBin = binForMinSgn + 1; iBin <= binForMaxSgn - 1; iBin++) { + for (int iBin = binForMinSgn + 1; iBin <= binForMaxSgn - 1; iBin++) { sum += mHistoInvMass->GetBinContent(iBin); } sum += mHistoInvMass->GetBinContent(binForMaxSgn) * binForMaxSgnFraction; - Double_t bkg, errBkg; + double bkg{}, errBkg{}; calculateBackground(bkg, errBkg); signal = sum - bkg; @@ -742,46 +661,46 @@ void HFInvMassFitter::countSignal(Double_t& signal, Double_t& signalErr) const } // calculate signal yield -void HFInvMassFitter::calculateSignal(Double_t& signal, Double_t& errSignal) const +void HFInvMassFitter::calculateSignal(double& signal, double& errSignal) const { signal = mRooNSgn->getVal(); errSignal = mRooNSgn->getError(); } // calculate background yield -void HFInvMassFitter::calculateBackground(Double_t& bkg, Double_t& errBkg) const +void HFInvMassFitter::calculateBackground(double& bkg, double& errBkg) const { bkg = mRooNBkg->getVal() * mIntegralBkg; errBkg = mRooNBkg->getError() * mIntegralBkg; } // calculate significance -void HFInvMassFitter::calculateSignificance(Double_t& significance, Double_t& errSignificance) const +void HFInvMassFitter::calculateSignificance(double& significance, double& errSignificance) const { - Double_t signal, errSignal; + double signal{}, errSignal{}; calculateSignal(signal, errSignal); - Double_t bkg, errBkg; + double bkg{}, errBkg{}; calculateBackground(bkg, errBkg); - Double_t const sgnErrSquare = errSignal * errSignal; - Double_t const bkgErrSquare = errBkg * errBkg; - Double_t const totalSgnBkg = signal + bkg; + double const sgnErrSquare = errSignal * errSignal; + double const bkgErrSquare = errBkg * errBkg; + double const totalSgnBkg = signal + bkg; significance = signal / std::sqrt(signal + bkg); errSignificance = significance * std::sqrt((sgnErrSquare + bkgErrSquare) / (mNSigmaForSidebands * totalSgnBkg * totalSgnBkg) + (bkg / totalSgnBkg) * (sgnErrSquare / signal / signal)); } // estimate Signal -void HFInvMassFitter::checkForSignal(Double_t& estimatedSignal) +void HFInvMassFitter::checkForSignal(double& estimatedSignal) { - Double_t const minForSgn = mMass - 4 * mSigmaSgn; - Double_t const maxForSgn = mMass + 4 * mSigmaSgn; - Int_t const binForMinSgn = mHistoInvMass->FindBin(minForSgn); - Int_t const binForMaxSgn = mHistoInvMass->FindBin(maxForSgn); + double const minForSgn = mMass - 4 * mSigmaSgn; + double const maxForSgn = mMass + 4 * mSigmaSgn; + int const binForMinSgn = mHistoInvMass->FindBin(minForSgn); + int const binForMaxSgn = mHistoInvMass->FindBin(maxForSgn); - Double_t sum = 0; - for (Int_t i = binForMinSgn; i <= binForMaxSgn; i++) { + double sum = 0; + for (int i = binForMinSgn; i <= binForMaxSgn; i++) { sum += mHistoInvMass->GetBinContent(i); } - Double_t bkg, errBkg; + double bkg{}, errBkg{}; calculateBackground(bkg, errBkg); estimatedSignal = sum - bkg; } @@ -806,27 +725,27 @@ RooAbsPdf* HFInvMassFitter::createSignalFitFunction(RooWorkspace* workspace) { RooAbsPdf* sgnPdf{nullptr}; switch (mTypeOfSgnPdf) { - case 0: { + case SingleGaus: { sgnPdf = workspace->pdf("sgnFuncGaus"); mRooSigmaSgn = workspace->var("sigma"); mRooSecSigmaSgn = workspace->var("sigma"); mRooMeanSgn = workspace->var("mean"); } break; - case 1: { + case DoubleGaus: { sgnPdf = workspace->pdf("sgnFuncDoubleGaus"); mRooSigmaSgn = workspace->var("sigma"); mRooSecSigmaSgn = workspace->var("sigmaDoubleGaus"); mRooMeanSgn = workspace->var("mean"); mRooFracDoubleGaus = workspace->var("fracDoubleGaus"); } break; - case 2: { + case DoubleGausSigmaRatioPar: { sgnPdf = workspace->pdf("sgnFuncGausRatio"); mRooSigmaSgn = workspace->var("sigma"); mRooSecSigmaSgn = workspace->var("sigmaDoubleGausRatio"); mRooMeanSgn = workspace->var("mean"); mRooFracDoubleGaus = workspace->var("fracDoubleGausRatio"); } break; - case 3: { + case GausSec: { sgnPdf = workspace->pdf("sgnFuncDoublePeak"); mRooSigmaSgn = workspace->var("sigma"); mRooSecSigmaSgn = workspace->var("sigmaSec"); @@ -873,20 +792,22 @@ void HFInvMassFitter::plotRefl(RooAbsPdf* pdf) // Calculate fit to data ratio void HFInvMassFitter::calculateFitToDataRatio() const { - if (!mInvMassFrame) + if (!mInvMassFrame) { return; + } // Get the data and fit curves from the frame auto* dataHist = dynamic_cast(mInvMassFrame->findObject("data_c")); auto* fitCurve = dynamic_cast(mInvMassFrame->findObject("Tot_c")); // or the relevant fit curve - if (!dataHist || !fitCurve) + if (!dataHist || !fitCurve) { return; + } RooHist* ratioHist = new RooHist(); for (int i = 0; i < dataHist->GetN(); ++i) { - double x, dataY, dataErr; + double x{}, dataY{}, dataErr{}; dataHist->GetPoint(i, x, dataY); dataErr = dataHist->GetErrorY(i); @@ -908,53 +829,165 @@ void HFInvMassFitter::calculateFitToDataRatio() const void HFInvMassFitter::setReflFuncFixed() { switch (mTypeOfReflPdf) { - case 0: // exponential - { + case SingleGausRefl: { RooRealVar* meanRefl = mWorkspace->var("meanRefl"); RooRealVar* sigmaRefl = mWorkspace->var("sigmaRefl"); - meanRefl->setConstant(kTRUE); - sigmaRefl->setConstant(kTRUE); + meanRefl->setConstant(true); + sigmaRefl->setConstant(true); } break; - case 1: // poly1 - { + case DoubleGausRefl: { RooRealVar* meanRefl = mWorkspace->var("meanRefl"); RooRealVar* sigmaRefl = mWorkspace->var("sigmaRefl"); RooRealVar* meanReflDoubleGaus = mWorkspace->var("meanReflDoubleGaus"); RooRealVar* sigmaReflDoubleGaus = mWorkspace->var("sigmaReflDoubleGaus"); RooRealVar* fracRefl = mWorkspace->var("fracRefl"); - meanRefl->setConstant(kTRUE); - sigmaRefl->setConstant(kTRUE); - meanReflDoubleGaus->setConstant(kTRUE); - sigmaReflDoubleGaus->setConstant(kTRUE); - fracRefl->setConstant(kTRUE); + meanRefl->setConstant(true); + sigmaRefl->setConstant(true); + meanReflDoubleGaus->setConstant(true); + sigmaReflDoubleGaus->setConstant(true); + fracRefl->setConstant(true); } break; - case 2: { - RooRealVar* polyReflParam0 = mWorkspace->var("polyReflParam0"); - RooRealVar* polyReflParam1 = mWorkspace->var("polyReflParam1"); - RooRealVar* polyReflParam2 = mWorkspace->var("polyReflParam2"); - RooRealVar* polyReflParam3 = mWorkspace->var("polyReflParam3"); - polyReflParam0->setConstant(kTRUE); - polyReflParam1->setConstant(kTRUE); - polyReflParam2->setConstant(kTRUE); - polyReflParam3->setConstant(kTRUE); + case Poly3Refl: { + constexpr int NParsPoly3{4}; + std::array polyReflParam{nullptr}; + for (int iPar = 0; iPar < NParsPoly3; ++iPar) { + polyReflParam.at(iPar) = mWorkspace->var(Form("polyReflParam%d", iPar)); + polyReflParam.at(iPar)->setConstant(true); + } } break; - case 3: { - RooRealVar* polyReflParam0 = mWorkspace->var("polyReflParam0"); - RooRealVar* polyReflParam1 = mWorkspace->var("polyReflParam1"); - RooRealVar* polyReflParam2 = mWorkspace->var("polyReflParam2"); - RooRealVar* polyReflParam3 = mWorkspace->var("polyReflParam3"); - RooRealVar* polyReflParam4 = mWorkspace->var("polyReflParam4"); - RooRealVar* polyReflParam5 = mWorkspace->var("polyReflParam5"); - RooRealVar* polyReflParam6 = mWorkspace->var("polyReflParam6"); - polyReflParam0->setConstant(kTRUE); - polyReflParam1->setConstant(kTRUE); - polyReflParam2->setConstant(kTRUE); - polyReflParam3->setConstant(kTRUE); - polyReflParam4->setConstant(kTRUE); - polyReflParam5->setConstant(kTRUE); - polyReflParam6->setConstant(kTRUE); + case Poly6Refl: { + constexpr int NParsPoly6{7}; + std::array polyReflParam{nullptr}; + for (int iPar = 0; iPar < NParsPoly6; ++iPar) { + polyReflParam.at(iPar) = mWorkspace->var(Form("polyReflParam%d", iPar)); + polyReflParam.at(iPar)->setConstant(true); + } } break; default: break; } } + +void HFInvMassFitter::setHistogramForFit(TH1* histoToFit) +{ + delete mHistoInvMass; + mHistoInvMass = histoToFit; + mHistoInvMass->SetDirectory(nullptr); +} + +void HFInvMassFitter::setFitRange(double minValue, double maxValue) +{ + mMinMass = minValue; + mMaxMass = maxValue; +} + +void HFInvMassFitter::setFitFunctions(int fitTypeBkg, int fitTypeSgn) +{ + mTypeOfBkgPdf = fitTypeBkg; + mTypeOfSgnPdf = fitTypeSgn; +} + +void HFInvMassFitter::setSigmaLimit(double sigmaValue, double sigmaLimit) +{ + mSigmaValue = sigmaValue; + mParamSgn = sigmaLimit; +} + +void HFInvMassFitter::setInitialGaussianMean(double mean) +{ + mMass = mean; + mSecMass = mean; +} + +void HFInvMassFitter::setInitialGaussianSigma(double sigma) +{ + mSigmaSgn = sigma; + mSecSigma = sigma; +} + +void HFInvMassFitter::setFixGaussianMean(double mean) +{ + setInitialGaussianMean(mean); + mFixedMean = true; +} + +void HFInvMassFitter::setBoundGaussianMean(double mean, double meanLowLimit, double meanUpLimit) +{ + if (mean < meanLowLimit || + mean > meanUpLimit) { + printf("Invalid Gaussian mean limit!\n"); + } + setInitialGaussianMean(mean); + mMassLowLimit = meanLowLimit; + mMassUpLimit = meanUpLimit; + mBoundMean = true; +} + +void HFInvMassFitter::setBoundReflGausMean(double mean, double meanLowLimit, double meanUpLimit) +{ + if (mean < meanLowLimit || + mean > meanUpLimit) { + printf("Invalid Gaussian mean limit for reflection!\n"); + } + setInitialGaussianMean(mean); + mMassReflLowLimit = meanLowLimit; + mMassReflUpLimit = meanUpLimit; + mBoundReflMean = true; +} + +void HFInvMassFitter::setFixGaussianSigma(double sigma) +{ + setInitialGaussianSigma(sigma); + mFixedSigma = true; +} + +void HFInvMassFitter::setBoundGausSigma(double sigma, double sigmaLimit) +{ + setInitialGaussianSigma(sigma); + setSigmaLimit(sigma, sigmaLimit); + mBoundSigma = true; +} + +void HFInvMassFitter::setFixSecondGaussianSigma(double sigma) +{ + if (mTypeOfSgnPdf != DoubleGaus) { + printf("Fit type should be 2Gaus!\n"); + } + setInitialSecondGaussianSigma(sigma); + mFixedSigmaDoubleGaus = true; +} + +void HFInvMassFitter::setFixFrac2Gaus(double frac) +{ + if (mTypeOfSgnPdf != DoubleGaus && + mTypeOfSgnPdf != DoubleGausSigmaRatioPar) { + printf("Fit type should be 2Gaus or 2GausSigmaRatio!\n"); + } + setInitialFracDoubleGaus(frac); + mFixedFracDoubleGaus = true; +} + +void HFInvMassFitter::setFixRatioToGausSigma(double sigmaFrac) +{ + if (mTypeOfSgnPdf != DoubleGausSigmaRatioPar) { + printf("Fit type should be set to k2GausSigmaRatioPar!\n"); + } + setInitialRatioDoubleGausSigma(sigmaFrac); + mFixedRatioDoubleGausSigma = true; +} + +void HFInvMassFitter::setFixReflOverSgn(double reflOverSgn) +{ + setInitialReflOverSgn(reflOverSgn); + mFixReflOverSgn = true; +} + +void HFInvMassFitter::setTemplateReflections(TH1* histoRefl) +{ + if (histoRefl == nullptr) { + mEnableReflections = false; + return; + } + mHistoTemplateRefl = histoRefl; + mHistoTemplateRefl->SetName("mHistoTemplateRefl"); +} diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.h b/PWGHF/D2H/Macros/HFInvMassFitter.h index daa00ec0b09..28ee858bba6 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.h +++ b/PWGHF/D2H/Macros/HFInvMassFitter.h @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ class HFInvMassFitter : public TNamed NoBkg = 6, NTypesOfBkgPdf }; - std::vector namesOfBkgPdf{"bkgFuncExpo", "bkgFuncPoly1", "bkgFuncPoly2", "bkgFuncPow", "bkgFuncPowExpo", "bkgFuncPoly3"}; + std::array namesOfBkgPdf{"bkgFuncExpo", "bkgFuncPoly1", "bkgFuncPoly2", "bkgFuncPow", "bkgFuncPowExpo", "bkgFuncPoly3"}; enum TypeOfSgnPdf { SingleGaus = 0, DoubleGaus = 1, @@ -65,173 +65,73 @@ class HFInvMassFitter : public TNamed Poly6Refl = 3, NTypesOfReflPdf }; - std::vector namesOfReflPdf{"reflFuncGaus", "reflFuncDoubleGaus", "reflFuncPoly3", "reflFuncPoly6"}; - HFInvMassFitter(); - HFInvMassFitter(const TH1* histoToFit, Double_t minValue, Double_t maxValue, Int_t fitTypeBkg = Expo, Int_t fitTypeSgn = SingleGaus); + std::array namesOfReflPdf{"reflFuncGaus", "reflFuncDoubleGaus", "reflFuncPoly3", "reflFuncPoly6"}; + HFInvMassFitter() = delete; + HFInvMassFitter(TH1* histoToFit, double minValue, double maxValue, int fitTypeBkg = Expo, int fitTypeSgn = SingleGaus); ~HFInvMassFitter() override; - void setHistogramForFit(const TH1* histoToFit) - { - - delete mHistoInvMass; - - mHistoInvMass = dynamic_cast(histoToFit->Clone("mHistoInvMass")); - mHistoInvMass->SetDirectory(nullptr); - } + void setHistogramForFit(TH1* histoToFit); void setUseLikelihoodFit() { mFitOption = "L,E"; } void setUseChi2Fit() { mFitOption = "Chi2"; } - void setFitOption(TString opt) { mFitOption = opt.Data(); } + void setFitOption(const std::string& opt) { mFitOption = opt; } RooAbsPdf* createBackgroundFitFunction(RooWorkspace* w1) const; RooAbsPdf* createSignalFitFunction(RooWorkspace* w1); RooAbsPdf* createReflectionFitFunction(RooWorkspace* w1) const; - void setFitRange(Double_t minValue, Double_t maxValue) - { - mMinMass = minValue; - mMaxMass = maxValue; - } - void setFitFunctions(Int_t fitTypeBkg, Int_t fitTypeSgn) - { - mTypeOfBkgPdf = fitTypeBkg; - mTypeOfSgnPdf = fitTypeSgn; - } - void setSigmaLimit(Double_t sigmaValue, Double_t sigmaLimit) - { - mSigmaValue = sigmaValue; - mParamSgn = sigmaLimit; - } - void setParticlePdgMass(Double_t mass) { mMassParticle = mass; } - [[nodiscard]] Double_t getParticlePdgMass() const { return mMassParticle; } - void setInitialGaussianMean(Double_t mean) - { - mMass = mean; - mSecMass = mean; - } - void setInitialGaussianSigma(Double_t sigma) - { - mSigmaSgn = sigma; - mSecSigma = sigma; - } - void setInitialSecondGaussianSigma(Double_t sigma) { mSigmaSgnDoubleGaus = sigma; } - void setInitialFracDoubleGaus(Double_t frac) { mFracDoubleGaus = frac; } - void setInitialRatioDoubleGausSigma(Double_t fracSigma) { mRatioDoubleGausSigma = fracSigma; } - void setFixGaussianMean(Double_t mean) - { - setInitialGaussianMean(mean); - mFixedMean = kTRUE; - } - void setBoundGaussianMean(Double_t mean, Double_t meanLowLimit, Double_t meanUpLimit) - { - if (mean < meanLowLimit || - mean > meanUpLimit) { - printf("Invalid Gaussian mean limit!\n"); - } - setInitialGaussianMean(mean); - mMassLowLimit = meanLowLimit; - mMassUpLimit = meanUpLimit; - mBoundMean = kTRUE; - } - void setBoundReflGausMean(Double_t mean, Double_t meanLowLimit, Double_t meanUpLimit) - { - if (mean < meanLowLimit || - mean > meanUpLimit) { - printf("Invalid Gaussian mean limit for reflection!\n"); - } - setInitialGaussianMean(mean); - mMassReflLowLimit = meanLowLimit; - mMassReflUpLimit = meanUpLimit; - mBoundReflMean = kTRUE; - } - void setFixGaussianSigma(Double_t sigma) - { - setInitialGaussianSigma(sigma); - mFixedSigma = kTRUE; - } - void setBoundGausSigma(Double_t sigma, Double_t sigmaLimit) - { - setInitialGaussianSigma(sigma); - setSigmaLimit(sigma, sigmaLimit); - mBoundSigma = kTRUE; - } - void setFixSecondGaussianSigma(Double_t sigma) - { - if (mTypeOfSgnPdf != DoubleGaus) { - printf("Fit type should be 2Gaus!\n"); - } - setInitialSecondGaussianSigma(sigma); - mFixedSigmaDoubleGaus = kTRUE; - } - void setFixFrac2Gaus(Double_t frac) - { - if (mTypeOfSgnPdf != DoubleGaus && - mTypeOfSgnPdf != DoubleGausSigmaRatioPar) { - printf("Fit type should be 2Gaus or 2GausSigmaRatio!\n"); - } - setInitialFracDoubleGaus(frac); - mFixedFracDoubleGaus = kTRUE; - } - void setFixRatioToGausSigma(Double_t sigmaFrac) - { - if (mTypeOfSgnPdf != DoubleGausSigmaRatioPar) { - printf("Fit type should be set to k2GausSigmaRatioPar!\n"); - } - setInitialRatioDoubleGausSigma(sigmaFrac); - mFixedRatioDoubleGausSigma = kTRUE; - } - void setFixSignalYield(Double_t yield) { mFixedRawYield = yield; } - void setNumberOfSigmaForSidebands(Double_t numberOfSigma) { mNSigmaForSidebands = numberOfSigma; } + void setFitRange(double minValue, double maxValue); + void setFitFunctions(int fitTypeBkg, int fitTypeSgn); + void setSigmaLimit(double sigmaValue, double sigmaLimit); + void setParticlePdgMass(double mass) { mMassParticle = mass; } + [[nodiscard]] double getParticlePdgMass() const { return mMassParticle; } + void setInitialGaussianMean(double mean); + void setInitialGaussianSigma(double sigma); + void setInitialSecondGaussianSigma(double sigma) { mSigmaSgnDoubleGaus = sigma; } + void setInitialFracDoubleGaus(double frac) { mFracDoubleGaus = frac; } + void setInitialRatioDoubleGausSigma(double fracSigma) { mRatioDoubleGausSigma = fracSigma; } + void setFixGaussianMean(double mean); + void setBoundGaussianMean(double mean, double meanLowLimit, double meanUpLimit); + void setBoundReflGausMean(double mean, double meanLowLimit, double meanUpLimit); + void setFixGaussianSigma(double sigma); + void setBoundGausSigma(double sigma, double sigmaLimit); + void setFixSecondGaussianSigma(double sigma); + void setFixFrac2Gaus(double frac); + void setFixRatioToGausSigma(double sigmaFrac); + void setFixSignalYield(double yield) { mFixedRawYield = yield; } + void setNumberOfSigmaForSidebands(double numberOfSigma) { mNSigmaForSidebands = numberOfSigma; } void plotBkg(RooAbsPdf* mFunc, Color_t color = kRed); void plotRefl(RooAbsPdf* mFunc); void setReflFuncFixed(); void doFit(); - void setInitialReflOverSgn(Double_t reflOverSgn) { mReflOverSgn = reflOverSgn; } - void setFixReflOverSgn(Double_t reflOverSgn) - { - setInitialReflOverSgn(reflOverSgn); - mFixReflOverSgn = kTRUE; - } - void setTemplateReflections(const TH1* histoRefl) - { - if (histoRefl == nullptr) { - mEnableReflections = kFALSE; - return; - } - mHistoTemplateRefl = dynamic_cast(histoRefl->Clone("mHistoTemplateRefl")); - } - void setDrawBgPrefit(Bool_t value = true) { mDrawBgPrefit = value; } - void setHighlightPeakRegion(Bool_t value = true) { mHighlightPeakRegion = value; } - [[nodiscard]] Double_t getChiSquareOverNDFTotal() const { return mChiSquareOverNdfTotal; } - [[nodiscard]] Double_t getChiSquareOverNDFBkg() const { return mChiSquareOverNdfBkg; } - [[nodiscard]] Double_t getRawYield() const { return mRawYield; } - [[nodiscard]] Double_t getRawYieldError() const { return mRawYieldErr; } - [[nodiscard]] Double_t getRawYieldCounted() const { return mRawYieldCounted; } - [[nodiscard]] Double_t getRawYieldCountedError() const { return mRawYieldCountedErr; } - [[nodiscard]] Double_t getBkgYield() const { return mBkgYield; } - [[nodiscard]] Double_t getBkgYieldError() const { return mBkgYieldErr; } - [[nodiscard]] Double_t getSignificance() const { return mSignificance; } - [[nodiscard]] Double_t getSignificanceError() const { return mSignificanceErr; } - [[nodiscard]] Double_t getMean() const { return mRooMeanSgn->getVal(); } - [[nodiscard]] Double_t getMeanUncertainty() const { return mRooMeanSgn->getError(); } - [[nodiscard]] Double_t getSigma() const { return mRooSigmaSgn->getVal(); } - [[nodiscard]] Double_t getSigmaUncertainty() const { return mRooSigmaSgn->getError(); } - [[nodiscard]] Double_t getSecSigma() const { return mRooSecSigmaSgn->getVal(); } - [[nodiscard]] Double_t getSecSigmaUncertainty() const { return mRooSecSigmaSgn->getError(); } - [[nodiscard]] Double_t getFracDoubleGaus() const { return mRooFracDoubleGaus->getVal(); } - [[nodiscard]] Double_t getFracDoubleGausUncertainty() const { return mRooFracDoubleGaus->getError(); } - [[nodiscard]] Double_t getReflOverSig() const - - { - if (mReflPdf != nullptr) { - return mReflOverSgn; - } - return 0; - } - void calculateSignal(Double_t& signal, Double_t& signalErr) const; - void countSignal(Double_t& signal, Double_t& signalErr) const; - void calculateBackground(Double_t& bkg, Double_t& bkgErr) const; - void calculateSignificance(Double_t& significance, Double_t& significanceErr) const; - void checkForSignal(Double_t& estimatedSignal); + void setInitialReflOverSgn(double reflOverSgn) { mReflOverSgn = reflOverSgn; } + void setFixReflOverSgn(double reflOverSgn); + void setTemplateReflections(TH1* histoRefl); + void setDrawBgPrefit(bool value = true) { mDrawBgPrefit = value; } + void setHighlightPeakRegion(bool value = true) { mHighlightPeakRegion = value; } + [[nodiscard]] double getChiSquareOverNDFTotal() const { return mChiSquareOverNdfTotal; } + [[nodiscard]] double getChiSquareOverNDFBkg() const { return mChiSquareOverNdfBkg; } + [[nodiscard]] double getRawYield() const { return mRawYield; } + [[nodiscard]] double getRawYieldError() const { return mRawYieldErr; } + [[nodiscard]] double getRawYieldCounted() const { return mRawYieldCounted; } + [[nodiscard]] double getRawYieldCountedError() const { return mRawYieldCountedErr; } + [[nodiscard]] double getBkgYield() const { return mBkgYield; } + [[nodiscard]] double getBkgYieldError() const { return mBkgYieldErr; } + [[nodiscard]] double getSignificance() const { return mSignificance; } + [[nodiscard]] double getSignificanceError() const { return mSignificanceErr; } + [[nodiscard]] double getMean() const { return mRooMeanSgn->getVal(); } + [[nodiscard]] double getMeanUncertainty() const { return mRooMeanSgn->getError(); } + [[nodiscard]] double getSigma() const { return mRooSigmaSgn->getVal(); } + [[nodiscard]] double getSigmaUncertainty() const { return mRooSigmaSgn->getError(); } + [[nodiscard]] double getSecSigma() const { return mRooSecSigmaSgn->getVal(); } + [[nodiscard]] double getSecSigmaUncertainty() const { return mRooSecSigmaSgn->getError(); } + [[nodiscard]] double getFracDoubleGaus() const { return mRooFracDoubleGaus->getVal(); } + [[nodiscard]] double getFracDoubleGausUncertainty() const { return mRooFracDoubleGaus->getError(); } + [[nodiscard]] double getReflOverSig() const { return mReflPdf != nullptr ? mReflOverSgn : 0.; } + void calculateSignal(double& signal, double& signalErr) const; + void countSignal(double& signal, double& signalErr) const; + void calculateBackground(double& bkg, double& bkgErr) const; + void calculateSignificance(double& significance, double& significanceErr) const; + void checkForSignal(double& estimatedSignal); void calculateFitToDataRatio() const; - void drawFit(TVirtualPad* c, const std::vector& plotLabels, Bool_t writeParInfo = true); + void drawFit(TVirtualPad* c, const std::vector& plotLabels, bool writeParInfo = true); void drawResidual(TVirtualPad* c); void drawRatio(TVirtualPad* c); void drawReflection(TVirtualPad* c); @@ -243,77 +143,77 @@ class HFInvMassFitter : public TNamed void highlightPeakRegion(const RooPlot* plot, Color_t color = kGray + 1, Width_t width = 1, Style_t style = 2) const; TH1* mHistoInvMass; // histogram to fit - TString mFitOption; - Double_t mMinMass; // lower mass limit - Double_t mMaxMass; // upper mass limit - Int_t mTypeOfBkgPdf; // background fit function - Int_t mTypeOfSgnPdf; // signal fit function - Int_t mTypeOfReflPdf; // reflection fit function - Double_t mMassParticle; // pdg value of particle mass - Double_t mMass; /// signal gaussian mean value - Double_t mMassLowLimit; /// lower limit of the allowed mass range - Double_t mMassUpLimit; /// upper limit of the allowed mass range - Double_t mMassReflLowLimit; /// lower limit of the allowed mass range for reflection - Double_t mMassReflUpLimit; /// upper limit of the allowed mass range for reflection - Double_t mSecMass; /// Second peak mean value - Double_t mSigmaSgn; /// signal gaussian sigma - Double_t mSecSigma; /// Second peak gaussian sigma - Int_t mNSigmaForSidebands; /// number of sigmas to veto the signal peak - Int_t mNSigmaForSgn; /// number of sigmas to veto the signal peak - Double_t mSigmaSgnErr; /// uncertainty on signal gaussian sigma - Double_t mSigmaSgnDoubleGaus; /// signal 2gaussian sigma - Bool_t mFixedMean; /// switch for fix mean of gaussian - Bool_t mBoundMean; /// switch for bound mean of guassian - Bool_t mBoundReflMean; /// switch for bound mean of guassian for reflection - Bool_t mFixedSigma; /// fix sigma or not - Bool_t mFixedSigmaDoubleGaus; /// fix sigma of 2gaussian or not - Bool_t mBoundSigma; /// set bound sigma or not - Double_t mSigmaValue; /// value of sigma - Double_t mParamSgn; /// +/- range variation of bound Sigma of gaussian in % - Double_t mFracDoubleGaus; /// initialization for fraction of 2nd gaussian in case of k2Gaus or k2GausSigmaRatioPar - Double_t mFixedRawYield; /// initialization for raw yield - Bool_t mFixedFracDoubleGaus; /// switch for fixed fraction of 2nd gaussian in case of k2Gaus or k2GausSigmaRatioPar - Double_t mRatioDoubleGausSigma; /// initialization for ratio between two gaussian sigmas in case of k2GausSigmaRatioPar - Bool_t mFixedRatioDoubleGausSigma; /// switch for fixed ratio between two gaussian sigmas in case of k2GausSigmaRatioPar - Double_t mReflOverSgn; /// reflection/signal - Bool_t mEnableReflections; /// flag use/not use reflections - Double_t mRawYield; /// signal gaussian integral - Double_t mRawYieldErr; /// err on signal gaussian integral - Double_t mRawYieldCounted; /// signal gaussian integral evaluated via bin counting - Double_t mRawYieldCountedErr; /// err on signal gaussian integral evaluated via bin counting - Double_t mBkgYield; /// background - Double_t mBkgYieldErr; /// err on background - Double_t mSignificance; /// significance - Double_t mSignificanceErr; /// err on significance - Double_t mChiSquareOverNdfTotal; /// chi2/ndf of the total fit - Double_t mChiSquareOverNdfBkg; /// chi2/ndf of the background (sidebands) pre-fit - Bool_t mFixReflOverSgn; /// switch for fix refl/signal - RooRealVar* mRooMeanSgn; /// mean for gaussian of signal - RooRealVar* mRooSigmaSgn; /// sigma for gaussian of signal - RooRealVar* mRooSecSigmaSgn; /// second sigma for composite gaussian of signal - RooRealVar* mRooFracDoubleGaus; /// fraction of second gaussian for composite gaussian of signal - RooAbsPdf* mSgnPdf; /// signal fit function - RooAbsPdf* mBkgPdf; /// background fit function - RooAbsPdf* mReflPdf; /// reflection fit function - RooRealVar* mRooNSgn; /// total Signal fit function integral - RooRealVar* mRooNBkg; /// total background fit function integral - RooRealVar* mRooNRefl; /// total reflection fit function integral - RooAbsPdf* mTotalPdf; /// total fit function - RooPlot* mInvMassFrame; /// frame of mass - RooPlot* mReflFrame; /// reflection frame - RooPlot* mReflOnlyFrame; /// reflection frame plot on reflection only - RooPlot* mResidualFrame; /// residual frame - RooPlot* mRatioFrame; /// fit/data ratio frame + std::string mFitOption; + double mMinMass; // lower mass limit + double mMaxMass; // upper mass limit + int mTypeOfBkgPdf; // background fit function + int mTypeOfSgnPdf; // signal fit function + int mTypeOfReflPdf; // reflection fit function + double mMassParticle; // pdg value of particle mass + double mMass; /// signal gaussian mean value + double mMassLowLimit; /// lower limit of the allowed mass range + double mMassUpLimit; /// upper limit of the allowed mass range + double mMassReflLowLimit; /// lower limit of the allowed mass range for reflection + double mMassReflUpLimit; /// upper limit of the allowed mass range for reflection + double mSecMass; /// Second peak mean value + double mSigmaSgn; /// signal gaussian sigma + double mSecSigma; /// Second peak gaussian sigma + double mNSigmaForSidebands; /// number of sigmas to veto the signal peak + double mNSigmaForSgn; /// number of sigmas to veto the signal peak + double mSigmaSgnErr; /// uncertainty on signal gaussian sigma + double mSigmaSgnDoubleGaus; /// signal 2gaussian sigma + bool mFixedMean; /// switch for fix mean of gaussian + bool mBoundMean; /// switch for bound mean of guassian + bool mBoundReflMean; /// switch for bound mean of guassian for reflection + bool mFixedSigma; /// fix sigma or not + bool mFixedSigmaDoubleGaus; /// fix sigma of 2gaussian or not + bool mBoundSigma; /// set bound sigma or not + double mSigmaValue; /// value of sigma + double mParamSgn; /// +/- range variation of bound Sigma of gaussian in % + double mFracDoubleGaus; /// initialization for fraction of 2nd gaussian in case of k2Gaus or k2GausSigmaRatioPar + double mFixedRawYield; /// initialization for raw yield + bool mFixedFracDoubleGaus; /// switch for fixed fraction of 2nd gaussian in case of k2Gaus or k2GausSigmaRatioPar + double mRatioDoubleGausSigma; /// initialization for ratio between two gaussian sigmas in case of k2GausSigmaRatioPar + bool mFixedRatioDoubleGausSigma; /// switch for fixed ratio between two gaussian sigmas in case of k2GausSigmaRatioPar + double mReflOverSgn; /// reflection/signal + bool mEnableReflections; /// flag use/not use reflections + double mRawYield; /// signal gaussian integral + double mRawYieldErr; /// err on signal gaussian integral + double mRawYieldCounted; /// signal gaussian integral evaluated via bin counting + double mRawYieldCountedErr; /// err on signal gaussian integral evaluated via bin counting + double mBkgYield; /// background + double mBkgYieldErr; /// err on background + double mSignificance; /// significance + double mSignificanceErr; /// err on significance + double mChiSquareOverNdfTotal; /// chi2/ndf of the total fit + double mChiSquareOverNdfBkg; /// chi2/ndf of the background (sidebands) pre-fit + bool mFixReflOverSgn; /// switch for fix refl/signal + RooRealVar* mRooMeanSgn; /// mean for gaussian of signal + RooRealVar* mRooSigmaSgn; /// sigma for gaussian of signal + RooRealVar* mRooSecSigmaSgn; /// second sigma for composite gaussian of signal + RooRealVar* mRooFracDoubleGaus; /// fraction of second gaussian for composite gaussian of signal + RooAbsPdf* mSgnPdf; /// signal fit function + RooAbsPdf* mBkgPdf; /// background fit function + RooAbsPdf* mReflPdf; /// reflection fit function + RooRealVar* mRooNSgn; /// total Signal fit function integral + RooRealVar* mRooNBkg; /// total background fit function integral + RooRealVar* mRooNRefl; /// total reflection fit function integral + RooAbsPdf* mTotalPdf; /// total fit function + RooPlot* mInvMassFrame; /// frame of mass + RooPlot* mReflFrame; /// reflection frame + RooPlot* mReflOnlyFrame; /// reflection frame plot on reflection only + RooPlot* mResidualFrame; /// residual frame + RooPlot* mRatioFrame; /// fit/data ratio frame RooPlot* mResidualFrameForCalculation; - RooWorkspace* mWorkspace; /// workspace - Double_t mIntegralHisto; /// integral of histogram to fit - Double_t mIntegralBkg; /// integral of background fit function - Double_t mIntegralSgn; /// integral of signal fit function - TH1* mHistoTemplateRefl; /// reflection histogram - Bool_t mDrawBgPrefit; /// draw background after fitting the sidebands - Bool_t mHighlightPeakRegion; /// draw vertical lines showing the peak region (usually +- 3 sigma) + RooWorkspace* mWorkspace; /// workspace + double mIntegralHisto; /// integral of histogram to fit + double mIntegralBkg; /// integral of background fit function + double mIntegralSgn; /// integral of signal fit function + TH1* mHistoTemplateRefl; /// reflection histogram + bool mDrawBgPrefit; /// draw background after fitting the sidebands + bool mHighlightPeakRegion; /// draw vertical lines showing the peak region (usually +- 3 sigma) - ClassDef(HFInvMassFitter, 1); + ClassDefOverride(HFInvMassFitter, 1); }; #endif // PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ diff --git a/PWGHF/D2H/Macros/README.md b/PWGHF/D2H/Macros/README.md index f65de110419..27754633067 100644 --- a/PWGHF/D2H/Macros/README.md +++ b/PWGHF/D2H/Macros/README.md @@ -11,12 +11,12 @@ If you have O2Physics compilation you do not need to fulfill these dependencies ## How to run ### As a ROOT macro -The `runMassFitter.C` can be compiled as ROOT macro. +The `runMassFitter.C` can be executed as ROOT macro. ```bash cd path-to-o2physics-src/PWGHF/D2H/Macros source path-to-root-install/bin/thisroot.sh export ROOT_INCLUDE_PATH=$ROOT_INCLUDE_PATH:path-to-json-include -root -l -x -b -q "HFInvMassFitter.cxx" "runMassFitter.C(\"config_massfitter.json\")" +root -l -b -q -e ".L HFInvMassFitter.cxx" -x "runMassFitter.C(\"config_massfitter.json\")" ``` If you have O2Physics compilation and enter into its environment there is no need to set environment variables (skip lines 2-3 above). diff --git a/PWGHF/D2H/Macros/compute_fraction_cutvar.py b/PWGHF/D2H/Macros/compute_fraction_cutvar.py index 35f751419fd..0099185472b 100644 --- a/PWGHF/D2H/Macros/compute_fraction_cutvar.py +++ b/PWGHF/D2H/Macros/compute_fraction_cutvar.py @@ -37,8 +37,8 @@ def main(config): infile_rawy = ROOT.TFile.Open(os.path.join(cfg["rawyields"]["inputdir"], filename_rawy)) hist_rawy_name = cfg["rawyields"]["histoname"] hist_rawy.append(infile_rawy.Get(hist_rawy_name)) - if(hist_rawy[-1] is None): - sys.exit(f"Fatal error: Histogram with raw yield \"{hist_rawy_name}\" is absent. Exit.") + if not isinstance(hist_rawy[-1], ROOT.TH1): + sys.exit(f"\33[31mFatal error: Histogram with raw yield \"{hist_rawy_name}\" is absent. Exit.\33[0m") hist_rawy[-1].SetDirectory(0) infile_rawy.Close() @@ -47,31 +47,43 @@ def main(config): hist_effnp_name = cfg["efficiencies"]["histonames"]["nonprompt"] hist_effp.append(infile_eff.Get(hist_effp_name)) hist_effnp.append(infile_eff.Get(hist_effnp_name)) - if(hist_effp[-1] is None): - sys.exit(f"Fatal error: Histogram with efficiency for prompt \"{hist_effp_name}\" is absent. Exit.") - if(hist_effnp[-1] is None): - sys.exit(f"Fatal error: Histogram with efficiency for nonprompt \"{hist_effnp}\" is absent. Exit.") + if not isinstance(hist_effp[-1], ROOT.TH1): + sys.exit(f"\33[31mFatal error: Histogram with efficiency for prompt \"{hist_effp_name}\" is absent. Exit.\33[0m") + if not isinstance(hist_effnp[-1], ROOT.TH1): + sys.exit(f"\33[31mFatal error: Histogram with efficiency for nonprompt \"{hist_effnp}\" is absent. Exit.\33[0m") hist_effp[-1].SetDirectory(0) hist_effnp[-1].SetDirectory(0) infile_eff.Close() pt_bin_to_process = cfg.get("pt_bin_to_process", -1) if not isinstance(pt_bin_to_process, int): - sys.exit("Fatal error: pt_bin_to_process must be an integer value. Exit.") + sys.exit("\33[31mFatal error: pt_bin_to_process must be an integer value. Exit.") if (pt_bin_to_process != -1 and pt_bin_to_process < 1) or pt_bin_to_process > hist_rawy[0].GetNbinsX(): - sys.exit("Fatal error: pt_bin_to_process must be a positive value up to number of bins in raw yield histogram. Exit.") + sys.exit("\33[31mFatal error: pt_bin_to_process must be a positive value up to number of bins in raw yield histogram. Exit.") + + is_draw_title_rawy = cfg.get("is_draw_title", {}).get("rawy", True) + is_draw_title_eff = cfg.get("is_draw_title", {}).get("eff", False) + is_draw_title_frac = cfg.get("is_draw_title", {}).get("frac", False) + is_draw_title_cov = cfg.get("is_draw_title", {}).get("cov", False) + is_draw_title_unc = cfg.get("is_draw_title", {}).get("unc", True) + + is_save_canvas_as_macro_rawy = cfg.get("is_save_canvas_as_macro", {}).get("rawy", False) + is_save_canvas_as_macro_eff = cfg.get("is_save_canvas_as_macro", {}).get("eff", False) + is_save_canvas_as_macro_frac = cfg.get("is_save_canvas_as_macro", {}).get("frac", False) + is_save_canvas_as_macro_cov = cfg.get("is_save_canvas_as_macro", {}).get("cov", False) + is_save_canvas_as_macro_unc = cfg.get("is_save_canvas_as_macro", {}).get("unc", False) if cfg["central_efficiency"]["computerawfrac"]: infile_name = os.path.join(cfg["central_efficiency"]["inputdir"], cfg["central_efficiency"]["inputfile"]) infile_central_eff = ROOT.TFile.Open(infile_name) hist_central_effp_name = cfg["central_efficiency"]["histonames"]["prompt"] hist_central_effp = infile_central_eff.Get(hist_central_effp_name) - if(hist_central_effp is None): - sys.exit(f"Fatal error: Histogram with central efficiency for prompt \"{hist_central_effp_name}\" is absent. Exit.") + if not isinstance(hist_central_effp[-1], ROOT.TH1): + sys.exit(f"\33[31mFatal error: Histogram with central efficiency for prompt \"{hist_central_effp_name}\" is absent. Exit.\33[0m") hist_central_effnp_name = cfg["central_efficiency"]["histonames"]["nonprompt"] hist_central_effnp = infile_central_eff.Get(hist_central_effnp_name) - if(hist_central_effnp is None): - sys.exit(f"Fatal error: Histogram with central efficiency for nonprompt \"{hist_central_effnp_name}\" is absent. Exit.") + if not isinstance(hist_central_effnp[-1], ROOT.TH1): + sys.exit(f"\33[31mFatal error: Histogram with central efficiency for nonprompt \"{hist_central_effnp_name}\" is absent. Exit.\33[0m") hist_central_effp.SetDirectory(0) hist_central_effnp.SetDirectory(0) infile_central_eff.Close() @@ -171,10 +183,10 @@ def main(config): if cfg["minimisation"]["correlated"]: if not (np.all(rawy[1:] > rawy[:-1]) or np.all(rawy[1:] < rawy[:-1])): - print("WARNING! main(): the raw yield vector is not monotonous. Check the input for stability.") + print("\0\33[33mWARNING! main(): the raw yield vector is not monotonous. Check the input for stability.\0\33[0m") print(f"raw yield vector elements = {rawy}\n") if not (np.all(unc_rawy[1:] > unc_rawy[:-1]) or np.all(unc_rawy[1:] < unc_rawy[:-1])): - print("WARNING! main(): the raw yield uncertainties vector is not monotonous. Check the input for stability.") + print("\0\33[33mWARNING! main(): the raw yield uncertainties vector is not monotonous. Check the input for stability.\0\33[0m") print(f"raw yield uncertainties vector elements = {unc_rawy}\n") minimiser = CutVarMinimiser(rawy, effp, effnp, unc_rawy, unc_effp, unc_effnp) @@ -211,34 +223,49 @@ def main(config): hist_bin_title = f"bin # {ipt+1}; {pt_axis_title}#in ({pt_min}; {pt_max})" - canv_rawy, histos_rawy, leg_r = minimiser.plot_result(f"_pt{pt_min}_{pt_max}", hist_bin_title) + hist_bin_title_rawy = hist_bin_title if is_draw_title_rawy else "" + canv_rawy, histos_rawy, leg_r = minimiser.plot_result(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_rawy) output.cd() canv_rawy.Write() for _, hist in histos_rawy.items(): hist.Write() + if (is_save_canvas_as_macro_rawy): + canv_rawy.SaveAs(f"canv_rawy_{ipt+1}.C") - canv_unc, histos_unc, leg_unc = minimiser.plot_uncertainties(f"_pt{pt_min}_{pt_max}", hist_bin_title) + hist_bin_title_unc = hist_bin_title if is_draw_title_unc else "" + canv_unc, histos_unc, leg_unc = minimiser.plot_uncertainties(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_unc) output.cd() canv_unc.Write() for _, hist in histos_unc.items(): hist.Write() + if (is_save_canvas_as_macro_unc): + canv_unc.SaveAs(f"canv_unc_{ipt+1}.C") - canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt{pt_min}_{pt_max}", hist_bin_title) + hist_bin_title_eff = hist_bin_title if is_draw_title_eff else "" + canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_eff) output.cd() canv_eff.Write() for _, hist in histos_eff.items(): hist.Write() + if (is_save_canvas_as_macro_eff): + canv_eff.SaveAs(f"canv_eff_{ipt+1}.C") - canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt{pt_min}_{pt_max}", hist_bin_title) + hist_bin_title_frac = hist_bin_title if is_draw_title_frac else "" + canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_frac) output.cd() canv_frac.Write() for _, hist in histos_frac.items(): hist.Write() + if (is_save_canvas_as_macro_frac): + canv_frac.SaveAs(f"canv_frac_{ipt+1}.C") - canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt{pt_min}_{pt_max}", hist_bin_title) + hist_bin_title_cov = hist_bin_title if is_draw_title_cov else "" + canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt_{pt_min}_to_{pt_max}", hist_bin_title_cov) output.cd() canv_cov.Write() histo_cov.Write() + if (is_save_canvas_as_macro_cov): + canv_cov.SaveAs(f"canv_cov_{ipt+1}.C") else: print(f"Minimization for pT {pt_min}, {pt_max} not successful") canv_rawy = ROOT.TCanvas("c_rawy_minimization_error", "Minimization error", 500, 500) diff --git a/PWGHF/D2H/Macros/config_cutvar_example.json b/PWGHF/D2H/Macros/config_cutvar_example.json index 20466b37044..e1b768b807d 100644 --- a/PWGHF/D2H/Macros/config_cutvar_example.json +++ b/PWGHF/D2H/Macros/config_cutvar_example.json @@ -57,6 +57,20 @@ "minimisation": { "correlated": true }, + "is_draw_title": { + "rawy": true, + "frac": false, + "eff": false, + "cov": false, + "unc": true + }, + "is_save_canvas_as_macro": { + "rawy": false, + "frac": false, + "eff": false, + "cov": false, + "unc": false + }, "central_efficiency": { "computerawfrac": true, "inputdir": "path/to/central/efficiency", diff --git a/PWGHF/D2H/Macros/config_massfitter.json b/PWGHF/D2H/Macros/config_massfitter.json index 393fb8aa0f3..25dc9d50bcc 100644 --- a/PWGHF/D2H/Macros/config_massfitter.json +++ b/PWGHF/D2H/Macros/config_massfitter.json @@ -13,19 +13,19 @@ "hMass_T_0.70_0.90", "hMass_T_0.90_1.60" ], - "PromptHistoName": [ + "_PromptHistoName": [ "MC prompt histogram name array" ], - "FDHistoName": [ + "_FDHistoName": [ "MC FD histogram name array" ], - "ReflHistoName": [ + "_ReflHistoName": [ "MC reflection histogram name array" ], - "PromptSecPeakHistoName": [ + "_PromptSecPeakHistoName": [ "MC prompt second peak histogram name array" ], - "FDSecPeakHistoName": [ + "_FDSecPeakHistoName": [ "MC FD second peak histogram name array" ], "Particle": "LcToPKPi", @@ -123,7 +123,7 @@ 4 ], "InclSecPeak": false, - "UseLikelihood": false, + "UseLikelihood": true, "_UseLikelihood": [ "true: likelihood fit", "false: chi2 fit" @@ -157,6 +157,6 @@ "2 for DoubleGausSigmaRatioPar", "3 for GausSec" ], - "drawBgPrefit": true, - "highlightPeakRegion": true + "DrawBgPrefit": true, + "HighlightPeakRegion": true } diff --git a/PWGHF/D2H/Macros/cut_variation.py b/PWGHF/D2H/Macros/cut_variation.py index 3d862589836..f9b49f15710 100644 --- a/PWGHF/D2H/Macros/cut_variation.py +++ b/PWGHF/D2H/Macros/cut_variation.py @@ -79,15 +79,15 @@ def __check_input_consistency(self): """ if len(self.eff_prompt) != self.n_sets or len(self.eff_nonprompt) != self.n_sets: - print("ERROR: number of raw yields and efficiencies not consistent! Exit") + print("33[31mERROR: number of raw yields and efficiencies not consistent! Exit\033[0m") sys.exit() if len(self.unc_raw_yields) != self.n_sets: - print("ERROR: number of raw yields and raw-yield uncertainties not consistent! Exit") + print("33[31mERROR: number of raw yields and raw-yield uncertainties not consistent! Exit\033[0m") sys.exit() if len(self.unc_eff_prompt) != self.n_sets or len(self.unc_eff_nonprompt) != self.n_sets: - print("ERROR: number of raw yields and efficiency uncertainties not consistent! Exit") + print("33[31mERROR: number of raw yields and efficiency uncertainties not consistent! Exit\033[0m") sys.exit() def __initialise_objects(self): @@ -199,7 +199,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) if correlated: m_cov_sets_diag = np.diag(self.m_cov_sets) if not (np.all(m_cov_sets_diag[1:] > m_cov_sets_diag[:-1]) or np.all(m_cov_sets_diag[1:] < m_cov_sets_diag[:-1])): - print("WARNING! minimise_system(): the residual vector uncertainties elements are not monotonous. Check the input for stability.") + print("\033[33mWARNING! minimise_system(): the residual vector uncertainties elements are not monotonous. Check the input for stability.\033[0m") print(f"residual vector uncertainties elements = {np.sqrt(m_cov_sets_diag)}\n") # chi2 @@ -484,6 +484,7 @@ def plot_result(self, suffix="", title=""): - leg: ROOT.TLegend needed otherwise it is destroyed """ + suffix = suffix.replace(".", "_") set_global_style(padleftmargin=0.16, padbottommargin=0.12, padtopmargin=0.075, titleoffsety=1.6) @@ -604,6 +605,7 @@ def plot_cov_matrix(self, correlated=True, suffix="", title=""): - hist_corr_matrix: ROOT.TH2F histogram of correlation matrix """ + suffix = suffix.replace(".", "_") set_global_style( padleftmargin=0.14, @@ -667,6 +669,7 @@ def plot_efficiencies(self, suffix="", title=""): - leg: ROOT.TLegend needed otherwise it is destroyed """ + suffix = suffix.replace(".", "_") set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2, padtopmargin = 0.075) @@ -758,6 +761,7 @@ def plot_fractions(self, suffix="", title=""): - leg: ROOT.TLegend needed otherwise it is destroyed """ + suffix = suffix.replace(".", "_") set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2, padtopmargin = 0.075) @@ -844,6 +848,7 @@ def plot_uncertainties(self, suffix="", title=""): - leg: ROOT.TLegend needed otherwise it is destroyed """ + suffix = suffix.replace(".", "_") set_global_style(padleftmargin=0.16, padbottommargin=0.12, padtopmargin=0.075, titleoffsety=1.6) diff --git a/PWGHF/D2H/Macros/hf_analysis_utils.py b/PWGHF/D2H/Macros/hf_analysis_utils.py index 862dce80717..97d4fc16252 100644 --- a/PWGHF/D2H/Macros/hf_analysis_utils.py +++ b/PWGHF/D2H/Macros/hf_analysis_utils.py @@ -13,7 +13,7 @@ def make_list(object) -> list: """ Returns the object as a list if it is not a list already. """ - return object if isinstance(object, list) else list(object) + return object if isinstance(object, list) else [object] # pylint: disable=too-many-arguments diff --git a/PWGHF/D2H/Macros/runMassFitter.C b/PWGHF/D2H/Macros/runMassFitter.C index 101b638b05d..5937d12e0ba 100644 --- a/PWGHF/D2H/Macros/runMassFitter.C +++ b/PWGHF/D2H/Macros/runMassFitter.C @@ -38,46 +38,42 @@ #include #include -#include // for fclose +#include #include #include #include -#include // std::string -#include -#include // std::vector +#include +#include +#include #endif using namespace rapidjson; -int runMassFitter(const TString& configFileName = "config_massfitter.json"); +void runMassFitter(const std::string& configFileName = "config_massfitter.json"); -template -void readArray(const Value& jsonArray, std::vector& output) -{ - for (const auto* it = jsonArray.Begin(); it != jsonArray.End(); it++) { - auto value = it->template Get(); - output.emplace_back(value); - } -} +TFile* openFileWithNullptrCheck(const std::string& fileName, const std::string& option = "read"); -void parseStringArray(const Value& jsonArray, std::vector& output) -{ - size_t const arrayLength = jsonArray.Size(); - for (size_t i = 0; i < arrayLength; i++) { - if (jsonArray[i].IsString()) { - output.emplace_back(jsonArray[i].GetString()); - } - } -} +template +T* getObjectWithNullPtrCheck(TFile* fileIn, const std::string& objectName); + +template +T readJsonField(const Document& config, const std::string& fieldName, const T& defaultValue); + +template +T readJsonField(const Document& config, const std::string& fieldName); + +template +void readJsonVector(std::vector& vec, const Document& config, const std::string& fieldName, bool isRequired = false); void divideCanvas(TCanvas* c, int nSliceVarBins); + void setHistoStyle(TH1* histo, Color_t color = kBlack, Size_t markerSize = 1); -int runMassFitter(const TString& configFileName) +void runMassFitter(const std::string& configFileName) { // load config - FILE* configFile = fopen(configFileName.Data(), "r"); + FILE* configFile = fopen(configFileName.c_str(), "r"); if (configFile == nullptr) { throw std::runtime_error("ERROR: Missing configuration json file: " + configFileName); } @@ -88,13 +84,13 @@ int runMassFitter(const TString& configFileName) config.ParseStream(is); fclose(configFile); - Bool_t const isMc = config["IsMC"].GetBool(); - Bool_t const writeSignalPar = config["WriteSignalPar"].GetBool(); - TString const particleName = config["Particle"].GetString(); - TString const collisionSystem = config["CollisionSystem"].GetString(); - TString const inputFileName = config["InFileName"].GetString(); - TString const reflFileName = config["ReflFileName"].GetString(); - TString outputFileName = config["OutFileName"].GetString(); + bool const isMc = readJsonField(config, "IsMC"); + bool const writeSignalPar = readJsonField(config, "WriteSignalPar", true); + std::string const particleName = readJsonField(config, "Particle"); + std::string const collisionSystem = readJsonField(config, "CollisionSystem", ""); + std::string const inputFileName = readJsonField(config, "InFileName"); + std::string const reflFileName = readJsonField(config, "ReflFileName", ""); + TString outputFileName = readJsonField(config, "OutFileName", "mInvFit.root"); std::vector inputHistoName; std::vector promptHistoName; @@ -102,8 +98,6 @@ int runMassFitter(const TString& configFileName) std::vector reflHistoName; std::vector promptSecPeakHistoName; std::vector fdSecPeakHistoName; - TString sliceVarName; - TString sliceVarUnit; std::vector sliceVarMin; std::vector sliceVarMax; std::vector massMin; @@ -113,165 +107,152 @@ int runMassFitter(const TString& configFileName) std::vector fixSecondSigmaManual; std::vector fixFracDoubleGausManual; std::vector nRebin; - std::vector bkgFuncConfig; - std::vector sgnFuncConfig; - - const Value& inputHistoNameValue = config["InputHistoName"]; - parseStringArray(inputHistoNameValue, inputHistoName); - - const Value& promptHistoNameValue = config["PromptHistoName"]; - parseStringArray(promptHistoNameValue, promptHistoName); - - const Value& fdHistoNameValue = config["FDHistoName"]; - parseStringArray(fdHistoNameValue, fdHistoName); + std::vector bkgFunc; + std::vector sgnFunc; - const Value& reflHistoNameValue = config["ReflHistoName"]; - parseStringArray(reflHistoNameValue, reflHistoName); + readJsonVector(inputHistoName, config, "InputHistoName", true); + readJsonVector(promptHistoName, config, "PromptHistoName"); + readJsonVector(fdHistoName, config, "FDHistoName"); + readJsonVector(reflHistoName, config, "ReflHistoName"); + readJsonVector(promptSecPeakHistoName, config, "PromptSecPeakHistoName"); + readJsonVector(fdSecPeakHistoName, config, "FDSecPeakHistoName"); - const Value& promptSecPeakHistoNameValue = config["PromptSecPeakHistoName"]; - parseStringArray(promptSecPeakHistoNameValue, promptSecPeakHistoName); + const bool fixMean = readJsonField(config, "FixMean", false); + const std::string meanFile = readJsonField(config, "MeanFile", ""); + readJsonVector(fixMeanManual, config, "FixMeanManual"); - const Value& fdSecPeakHistoNameValue = config["FDSecPeakHistoName"]; - parseStringArray(fdSecPeakHistoNameValue, fdSecPeakHistoName); + const bool fixSigma = readJsonField(config, "FixSigma", false); + const std::string sigmaFile = readJsonField(config, "SigmaFile", ""); + readJsonVector(fixSigmaManual, config, "FixSigmaManual"); - const bool fixMean = config["FixMean"].GetBool(); - const std::string meanFile = config["MeanFile"].GetString(); + const bool fixSecondSigma = readJsonField(config, "FixSecondSigma", false); + const std::string secondSigmaFile = readJsonField(config, "SecondSigmaFile", ""); + readJsonVector(fixSecondSigmaManual, config, "FixSecondSigmaManual"); - const Value& fixMeanManualValue = config["FixMeanManual"]; - readArray(fixMeanManualValue, fixMeanManual); + const bool fixFracDoubleGaus = readJsonField(config, "FixFracDoubleGaus", false); + const std::string fracDoubleGausFile = readJsonField(config, "FracDoubleGausFile", ""); + readJsonVector(fixFracDoubleGausManual, config, "FixFracDoubleGausManual"); - const bool fixSigma = config["FixSigma"].GetBool(); - const std::string sigmaFile = config["SigmaFile"].GetString(); + const TString sliceVarName = readJsonField(config, "SliceVarName"); + const TString sliceVarUnit = readJsonField(config, "SliceVarUnit"); - const Value& fixSigmaManualValue = config["FixSigmaManual"]; - readArray(fixSigmaManualValue, fixSigmaManual); + readJsonVector(sliceVarMin, config, "SliceVarMin", true); + readJsonVector(sliceVarMax, config, "SliceVarMax", true); - const bool fixSecondSigma = config["FixSecondSigma"].GetBool(); - const std::string secondSigmaFile = config["SecondSigmaFile"].GetString(); + readJsonVector(massMin, config, "MassMin", true); + readJsonVector(massMax, config, "MassMax", true); - const Value& fixSecondSigmaManualValue = config["FixSecondSigmaManual"]; - readArray(fixSecondSigmaManualValue, fixSecondSigmaManual); + readJsonVector(nRebin, config, "Rebin", true); - const bool fixFracDoubleGaus = config["FixFracDoubleGaus"].GetBool(); - const std::string fracDoubleGausFile = config["FracDoubleGausFile"].GetString(); + bool const includeSecPeak = readJsonField(config, "InclSecPeak", false); + bool const useLikelihood = readJsonField(config, "UseLikelihood"); - const Value& fixFracDoubleGausManualValue = config["FixFracDoubleGausManual"]; - readArray(fixFracDoubleGausManualValue, fixFracDoubleGausManual); + readJsonVector(bkgFunc, config, "BkgFunc", true); + readJsonVector(sgnFunc, config, "SgnFunc", true); - sliceVarName = config["SliceVarName"].GetString(); - sliceVarUnit = config["SliceVarUnit"].GetString(); + const bool enableRefl = readJsonField(config, "EnableRefl", false); + const bool drawBgPrefit = readJsonField(config, "DrawBgPrefit", true); + const bool highlightPeakRegion = readJsonField(config, "HighlightPeakRegion", true); - const Value& sliceVarMinValue = config["SliceVarMin"]; - readArray(sliceVarMinValue, sliceVarMin); - - const Value& sliceVarMaxValue = config["SliceVarMax"]; - readArray(sliceVarMaxValue, sliceVarMax); - - const Value& massMinValue = config["MassMin"]; - readArray(massMinValue, massMin); - - const Value& massMaxValue = config["MassMax"]; - readArray(massMaxValue, massMax); - - const Value& rebinValue = config["Rebin"]; - readArray(rebinValue, nRebin); - - bool const includeSecPeak = config["InclSecPeak"].GetBool(); - bool const useLikelihood = config["UseLikelihood"].GetBool(); - - const Value& bkgFuncValue = config["BkgFunc"]; - readArray(bkgFuncValue, bkgFuncConfig); - - const Value& sgnFuncValue = config["SgnFunc"]; - readArray(sgnFuncValue, sgnFuncConfig); - - const bool enableRefl = config["EnableRefl"].GetBool(); - - const bool drawBgPrefit = config["drawBgPrefit"].GetBool(); - const bool highlightPeakRegion = config["highlightPeakRegion"].GetBool(); - - const unsigned int nSliceVarBins = sliceVarMin.size(); - std::vector bkgFunc(nSliceVarBins); - std::vector sgnFunc(nSliceVarBins); + const int nSliceVarBins = static_cast(sliceVarMin.size()); std::vector sliceVarLimits(nSliceVarBins + 1); - for (unsigned int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + auto checkVectorSize = [&](const auto& vec, const std::string& name = "", const bool isEmptyOk = false) { + if (vec.size() != static_cast(nSliceVarBins)) { + if (isEmptyOk && vec.empty()) { + return; + } + throw std::runtime_error("ERROR: inconsistent vector size for " + name + "! Exit"); + } + }; + + checkVectorSize(inputHistoName, "inputHistoName", true); + checkVectorSize(promptHistoName, "promptHistoName", true); + checkVectorSize(fdHistoName, "fdHistoName", true); + checkVectorSize(reflHistoName, "reflHistoName", true); + checkVectorSize(promptSecPeakHistoName, "promptSecPeakHistoName", true); + checkVectorSize(fdSecPeakHistoName, "fdSecPeakHistoName", true); + checkVectorSize(sliceVarMin, "sliceVarMin"); + checkVectorSize(sliceVarMax, "sliceVarMax"); + checkVectorSize(massMin, "massMin"); + checkVectorSize(massMax, "massMax"); + checkVectorSize(fixMeanManual, "fixMeanManual", true); + checkVectorSize(fixSigmaManual, "fixSigmaManual", true); + checkVectorSize(fixSecondSigmaManual, "fixSecondSigmaManual", true); + checkVectorSize(fixFracDoubleGausManual, "fixFracDoubleGausManual", true); + checkVectorSize(nRebin, "nRebin"); + checkVectorSize(bkgFunc, "bkgFunc"); + checkVectorSize(sgnFunc, "sgnFunc"); + + for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { sliceVarLimits[iSliceVar] = sliceVarMin[iSliceVar]; - sliceVarLimits[iSliceVar + 1] = sliceVarMax[iSliceVar]; - if (bkgFuncConfig[iSliceVar] < 0 || bkgFuncConfig[iSliceVar] >= HFInvMassFitter::NTypesOfBkgPdf) { + if (bkgFunc[iSliceVar] < 0 || bkgFunc[iSliceVar] >= HFInvMassFitter::NTypesOfBkgPdf) { throw std::runtime_error("ERROR: only Expo, Poly1, Poly2, Pow and PowEx background functions supported! Exit"); } - bkgFunc[iSliceVar] = bkgFuncConfig[iSliceVar]; - - if (sgnFuncConfig[iSliceVar] < 0 || sgnFuncConfig[iSliceVar] >= HFInvMassFitter::NTypesOfSgnPdf) { + if (isMc && bkgFunc[iSliceVar] != HFInvMassFitter::NoBkg) { + throw std::runtime_error("ERROR: in MC mode the background function must be NoBkg! Exit"); + } + if (sgnFunc[iSliceVar] < 0 || sgnFunc[iSliceVar] >= HFInvMassFitter::NTypesOfSgnPdf) { throw std::runtime_error("ERROR: only SingleGaus, DoubleGaus and DoubleGausSigmaRatioPar signal functions supported! Exit"); } - sgnFunc[iSliceVar] = sgnFuncConfig[iSliceVar]; } + sliceVarLimits[nSliceVarBins] = sliceVarMax[nSliceVarBins - 1]; + + struct DecayInfo { + std::string decayProducts; + std::string pdgName; + std::string decayFormulaLhs; + std::string decayFormulaRhs; + }; - std::map> particles{ - {"Dplus", {"K#pi#pi", "D+", "D^{+} #rightarrow K^{-}#pi^{+}#pi^{+} + c.c."}}, - {"D0", {"K#pi", "D0", "D^{0} #rightarrow K^{-}#pi^{+} + c.c."}}, - {"Ds", {"KK#pi", "D_s+", "D_{s}^{+} #rightarrow K^{-}K^{+}#pi^{+} + c.c."}}, - {"LcToPKPi", {"pK#pi", "Lambda_c+", "#Lambda_{c}^{+} #rightarrow pK^{-}#pi^{+} + c.c."}}, - {"LcToPK0s", {"pK^{0}_{s}", "Lambda_c+", "#Lambda_{c}^{+} #rightarrow pK^{0}_{s} + c.c."}}, - {"Dstar", {"D^{0}pi^{+}", "D*+", "D^{*+} #rightarrow D^{0}#pi^{+} + c.c."}}, - {"XicToXiPiPi", {"#Xi#pi#pi", "Xi_c+", "#Xi_{c}^{+} #rightarrow #Xi^{-}#pi^{+}#pi^{+} + c.c."}}}; - if (particles.find(particleName.Data()) == particles.end()) { + std::map particles{ + {"Dplus", {"K#pi#pi", "D+", "D^{+}", "K^{-}#pi^{+}#pi^{+}"}}, + {"D0", {"K#pi", "D0", "D^{0}", "K^{-}#pi^{+}"}}, + {"Ds", {"KK#pi", "D_s+", "D_{s}^{+}", "K^{-}K^{+}#pi^{+}"}}, + {"LcToPKPi", {"pK#pi", "Lambda_c+", "#Lambda_{c}^{+}", "pK^{-}#pi^{+}"}}, + {"LcToPK0s", {"pK^{0}_{s}", "Lambda_c+", "#Lambda_{c}^{+}", "pK^{0}_{s}"}}, + {"Dstar", {"D^{0}pi^{+}", "D*+", "D^{*+}", "D^{0}#pi^{+}"}}, + {"XicToXiPiPi", {"#Xi#pi#pi", "Xi_c+", "#Xi_{c}^{+}", "#Xi^{-}#pi^{+}#pi^{+}"}}}; + if (particles.find(particleName.c_str()) == particles.end()) { throw std::runtime_error("ERROR: only Dplus, D0, Ds, LcToPKPi, LcToPK0s, Dstar and XicToXiPiPi particles supported! Exit"); } - const auto& particleTuple = particles[particleName.Data()]; - const TString massAxisTitle = "#it{M}(" + std::get<0>(particleTuple) + ") (GeV/#it{c}^{2})"; - const double massPDG = TDatabasePDG::Instance()->GetParticle(std::get<1>(particleTuple).c_str())->Mass(); - const std::vector plotLabels = {std::get<2>(particleTuple), collisionSystem.Data()}; + const auto& particle = particles[particleName.c_str()]; + const std::string massAxisTitle = "#it{M}(" + particle.decayProducts + ") (GeV/#it{c}^{2})"; + const double massPDG = TDatabasePDG::Instance()->GetParticle(particle.pdgName.c_str())->Mass(); + const std::vector plotLabels = {(particle.decayFormulaLhs + " #rightarrow " + particle.decayFormulaRhs + " + c.c.").c_str(), collisionSystem}; // load inv-mass histograms - auto* inputFile = TFile::Open(inputFileName.Data()); - if ((inputFile == nullptr) || !inputFile->IsOpen()) { - return -1; - } + auto* inputFile = openFileWithNullptrCheck(inputFileName); - TFile* inputFileRefl = nullptr; - if (enableRefl) { - inputFileRefl = TFile::Open(reflFileName.Data()); - if ((inputFileRefl == nullptr) || !inputFileRefl->IsOpen()) { - return -1; - } - } + TFile* inputFileRefl = enableRefl ? openFileWithNullptrCheck(reflFileName) : nullptr; std::vector hMassSgn(nSliceVarBins); std::vector hMassRefl(nSliceVarBins); std::vector hMass(nSliceVarBins); - for (unsigned int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { if (!isMc) { - hMass[iSliceVar] = inputFile->Get(inputHistoName[iSliceVar].data()); + hMass[iSliceVar] = getObjectWithNullPtrCheck(inputFile, inputHistoName[iSliceVar]); if (enableRefl) { - hMassRefl[iSliceVar] = inputFileRefl->Get(reflHistoName[iSliceVar].data()); - if (hMassRefl[iSliceVar] == nullptr) { - throw std::runtime_error("ERROR: MC reflection histogram not found! Exit!"); - } - hMassSgn[iSliceVar] = inputFileRefl->Get(fdHistoName[iSliceVar].data()); - if (hMassSgn[iSliceVar] == nullptr) { - throw std::runtime_error("ERROR: MC prompt or FD histogram not found! Exit!"); - } - hMassSgn[iSliceVar]->Add(inputFileRefl->Get(promptHistoName[iSliceVar].data())); + hMassRefl[iSliceVar] = getObjectWithNullPtrCheck(inputFileRefl, reflHistoName[iSliceVar]); + hMassSgn[iSliceVar] = getObjectWithNullPtrCheck(inputFileRefl, fdHistoName[iSliceVar]); + hMassSgn[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFileRefl, promptHistoName[iSliceVar])); } } else { - hMass[iSliceVar] = inputFile->Get(promptHistoName[iSliceVar].data()); - hMass[iSliceVar]->Add(inputFile->Get(fdHistoName[iSliceVar].data())); + hMass[iSliceVar] = getObjectWithNullPtrCheck(inputFile, promptHistoName[iSliceVar]); + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, fdHistoName[iSliceVar])); if (includeSecPeak) { - hMass[iSliceVar]->Add(inputFile->Get(promptSecPeakHistoName[iSliceVar].data())); - hMass[iSliceVar]->Add(inputFile->Get(fdSecPeakHistoName[iSliceVar].data())); + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, promptSecPeakHistoName[iSliceVar])); + hMass[iSliceVar]->Add(getObjectWithNullPtrCheck(inputFile, fdSecPeakHistoName[iSliceVar])); } } - if (hMass[iSliceVar] == nullptr) { - throw std::runtime_error("ERROR: input histogram for fit not found! Exit!"); - } hMass[iSliceVar]->SetDirectory(nullptr); } inputFile->Close(); + if (enableRefl) { + inputFileRefl->Close(); + } // define output histos auto* hRawYieldsSignal = new TH1D("hRawYieldsSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield", nSliceVarBins, sliceVarLimits.data()); @@ -287,16 +268,24 @@ int runMassFitter(const TString& configFileName) auto* hRawYieldsSecSigma = new TH1D("hRawYieldsSecSigma", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", nSliceVarBins, sliceVarLimits.data()); auto* hRawYieldsFracDoubleGaus = new TH1D("hRawYieldsFracDoubleGaus", ";" + sliceVarName + "(" + sliceVarUnit + ");fraction of double gaussian", nSliceVarBins, sliceVarLimits.data()); - const Int_t nConfigsToSave = 6; - auto* hFitConfig = new TH2F("hfitConfig", "Fit Configurations", nConfigsToSave, 0, 6, nSliceVarBins, sliceVarLimits.data()); - const char* hFitConfigXLabel[nConfigsToSave] = {"mass min", "mass max", "rebin num", "fix sigma", "bkg func", "sgn func"}; + enum { + ConfigMassMin = 1, + ConfigMassMax, + ConfigNRebin, + ConfigFixSigma, + ConfigBkgFunc, + ConfigSgnFunc, + NConfigsToSave + }; + auto* hFitConfig = new TH2F("hfitConfig", "Fit Configurations", NConfigsToSave - 1, 0, NConfigsToSave - 1, nSliceVarBins, sliceVarLimits.data()); + const char* hFitConfigXLabel[NConfigsToSave - 1] = {"mass min", "mass max", "rebin num", "fix sigma", "bkg func", "sgn func"}; hFitConfig->SetStats(false); + for (int i = 0; i < NConfigsToSave - 1; i++) { + hFitConfig->GetXaxis()->SetBinLabel(i + 1, hFitConfigXLabel[i]); + } hFitConfig->LabelsDeflate("X"); hFitConfig->LabelsDeflate("Y"); hFitConfig->LabelsOption("v"); - for (int i = 0; i < nConfigsToSave; i++) { - hFitConfig->GetXaxis()->SetBinLabel(i + 1, hFitConfigXLabel[i]); - } setHistoStyle(hRawYieldsSignal); setHistoStyle(hRawYieldsSignalCounted); @@ -315,14 +304,11 @@ int runMassFitter(const TString& configFileName) TH1* histToFix = nullptr; if (isFix) { if (fixManual.empty()) { - auto* fixInputFile = TFile::Open(fixFileName.data()); - if (fixInputFile == nullptr) { - throw std::runtime_error("Cannot open file for fixed " + var); - } + auto* fixInputFile = openFileWithNullptrCheck(fixFileName); const std::string histName = "hRawYields" + var; - histToFix = fixInputFile->Get(histName.data()); + histToFix = getObjectWithNullPtrCheck(fixInputFile, histName); histToFix->SetDirectory(nullptr); - if (static_cast(histToFix->GetNbinsX()) != nSliceVarBins) { + if (histToFix->GetNbinsX() != nSliceVarBins) { throw std::runtime_error("Different number of bins for this analysis and histo for fixed " + var); } fixInputFile->Close(); @@ -336,261 +322,169 @@ int runMassFitter(const TString& configFileName) TH1* hSecondSigmaToFix = getHistToFix(fixSecondSigma, fixSecondSigmaManual, secondSigmaFile, "SecSigma"); TH1* hFracDoubleGausToFix = getHistToFix(fixFracDoubleGaus, fixFracDoubleGausManual, fracDoubleGausFile, "FracDoubleGaus"); - // fit histograms - - std::vector hMassForFit(nSliceVarBins); - std::vector hMassForRefl(nSliceVarBins); - std::vector hMassForSgn(nSliceVarBins); - - Int_t canvasSize[2] = {1920, 1080}; + int canvasSize[2] = {1920, 1080}; if (nSliceVarBins == 1) { canvasSize[0] = 500; canvasSize[1] = 500; } - Int_t const nCanvasesMax = 20; // do not put more than 20 bins per canvas to make them visible - const Int_t nCanvases = std::ceil(static_cast(nSliceVarBins) / nCanvasesMax); + int constexpr NCanvasesMax = 20; // do not put more than 20 bins per canvas to make them visible + const int nCanvases = std::ceil(static_cast(nSliceVarBins) / NCanvasesMax); std::vector canvasMass(nCanvases); std::vector canvasResiduals(nCanvases); std::vector canvasRatio(nCanvases); std::vector canvasRefl(nCanvases); for (int iCanvas = 0; iCanvas < nCanvases; iCanvas++) { - const int nPads = (nCanvases == 1) ? nSliceVarBins : nCanvasesMax; - canvasMass[iCanvas] = new TCanvas(Form("canvasMass%d", iCanvas), Form("canvasMass%d", iCanvas), - canvasSize[0], canvasSize[1]); + const int nPads = (nCanvases == 1) ? nSliceVarBins : NCanvasesMax; + canvasMass[iCanvas] = new TCanvas(Form("canvasMass%d", iCanvas), Form("canvasMass%d", iCanvas), canvasSize[0], canvasSize[1]); divideCanvas(canvasMass[iCanvas], nPads); - canvasResiduals[iCanvas] = - new TCanvas(Form("canvasResiduals%d", iCanvas), Form("canvasResiduals%d", iCanvas), canvasSize[0], canvasSize[1]); + canvasResiduals[iCanvas] = new TCanvas(Form("canvasResiduals%d", iCanvas), Form("canvasResiduals%d", iCanvas), canvasSize[0], canvasSize[1]); divideCanvas(canvasResiduals[iCanvas], nPads); - canvasRatio[iCanvas] = new TCanvas(Form("canvasRatio%d", iCanvas), Form("canvasRatio%d", iCanvas), - canvasSize[0], canvasSize[1]); + canvasRatio[iCanvas] = new TCanvas(Form("canvasRatio%d", iCanvas), Form("canvasRatio%d", iCanvas), canvasSize[0], canvasSize[1]); divideCanvas(canvasRatio[iCanvas], nPads); if (enableRefl) { - canvasRefl[iCanvas] = new TCanvas(Form("canvasRefl%d", iCanvas), Form("canvasRefl%d", iCanvas), - canvasSize[0], canvasSize[1]); + canvasRefl[iCanvas] = new TCanvas(Form("canvasRefl%d", iCanvas), Form("canvasRefl%d", iCanvas), canvasSize[0], canvasSize[1]); divideCanvas(canvasRefl[iCanvas], nPads); } } - for (unsigned int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { - const Int_t iCanvas = std::floor(static_cast(iSliceVar) / nCanvasesMax); + for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + const int iCanvas = std::floor(static_cast(iSliceVar) / NCanvasesMax); - hMassForFit[iSliceVar] = hMass[iSliceVar]->Rebin(nRebin[iSliceVar]); + hMass[iSliceVar]->Rebin(nRebin[iSliceVar]); TString const ptTitle = Form("%0.2f < " + sliceVarName + " < %0.2f " + sliceVarUnit, sliceVarMin[iSliceVar], sliceVarMax[iSliceVar]); - hMassForFit[iSliceVar]->SetTitle(Form("%s;%s;Counts per %0.1f MeV/#it{c}^{2}", - ptTitle.Data(), massAxisTitle.Data(), - hMassForFit[iSliceVar]->GetBinWidth(1) * 1000)); - hMassForFit[iSliceVar]->SetName(Form("MassForFit%d", iSliceVar)); + hMass[iSliceVar]->SetTitle(Form("%s;%s;Counts per %0.1f MeV/#it{c}^{2}", + ptTitle.Data(), massAxisTitle.c_str(), + hMass[iSliceVar]->GetBinWidth(1) * 1000)); + hMass[iSliceVar]->SetName(Form("MassForFit%d", iSliceVar)); if (enableRefl) { - hMassForRefl[iSliceVar] = hMassRefl[iSliceVar]->Rebin(nRebin[iSliceVar]); - hMassForSgn[iSliceVar] = hMassSgn[iSliceVar]->Rebin(nRebin[iSliceVar]); + hMassRefl[iSliceVar]->Rebin(nRebin[iSliceVar]); + hMassSgn[iSliceVar]->Rebin(nRebin[iSliceVar]); } - Double_t reflOverSgn = 0; + double reflOverSgn = 0; - if (isMc) { - HFInvMassFitter* massFitter; - massFitter = new HFInvMassFitter(hMassForFit[iSliceVar], massMin[iSliceVar], massMax[iSliceVar], HFInvMassFitter::NoBkg, sgnFunc[iSliceVar]); - massFitter->setDrawBgPrefit(drawBgPrefit); - massFitter->setHighlightPeakRegion(highlightPeakRegion); - massFitter->setInitialGaussianMean(massPDG); - massFitter->setParticlePdgMass(massPDG); - massFitter->setBoundGaussianMean(massPDG, 0.8 * massPDG, 1.2 * massPDG); - massFitter->doFit(); - - if (nSliceVarBins > 1) { - canvasMass[iCanvas]->cd(iSliceVar - nCanvasesMax * iCanvas + 1); - } else { - canvasMass[iCanvas]->cd(); - } - - massFitter->drawFit(gPad, plotLabels, writeSignalPar); - - const Double_t rawYield = massFitter->getRawYield(); - const Double_t rawYieldErr = massFitter->getRawYieldError(); - const Double_t rawYieldCounted = massFitter->getRawYieldCounted(); - const Double_t rawYieldCountedErr = massFitter->getRawYieldCountedError(); - const Double_t reducedChiSquareBkg = massFitter->getChiSquareOverNDFBkg(); - const Double_t reducedChiSquareTotal = massFitter->getChiSquareOverNDFTotal(); - const Double_t mean = massFitter->getMean(); - const Double_t meanErr = massFitter->getMeanUncertainty(); - const Double_t sigma = massFitter->getSigma(); - const Double_t sigmaErr = massFitter->getSigmaUncertainty(); - - hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); - hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); - hRawYieldsSignalCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); - hRawYieldsSignalCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); - hRawYieldsChiSquareBkg->SetBinContent(iSliceVar + 1, reducedChiSquareBkg); - hRawYieldsChiSquareBkg->SetBinError(iSliceVar + 1, 0.); - hRawYieldsChiSquareTotal->SetBinContent(iSliceVar + 1, reducedChiSquareTotal); - hRawYieldsChiSquareTotal->SetBinError(iSliceVar + 1, 0.); - hRawYieldsMean->SetBinContent(iSliceVar + 1, mean); - hRawYieldsMean->SetBinError(iSliceVar + 1, meanErr); - hRawYieldsSigma->SetBinContent(iSliceVar + 1, sigma); - hRawYieldsSigma->SetBinError(iSliceVar + 1, sigmaErr); - - if (sgnFunc[iSliceVar] != HFInvMassFitter::SingleGaus) { - const Double_t secSigma = massFitter->getSecSigma(); - const Double_t secSigmaErr = massFitter->getSecSigmaUncertainty(); - hRawYieldsSecSigma->SetBinContent(iSliceVar + 1, secSigma); - hRawYieldsSecSigma->SetBinError(iSliceVar + 1, secSigmaErr); - } - if (sgnFunc[iSliceVar] == HFInvMassFitter::DoubleGaus || sgnFunc[iSliceVar] == HFInvMassFitter::DoubleGausSigmaRatioPar) { - const Double_t fracDoubleGaus = massFitter->getFracDoubleGaus(); - const Double_t fracDoubleGausErr = massFitter->getFracDoubleGausUncertainty(); - hRawYieldsFracDoubleGaus->SetBinContent(iSliceVar + 1, fracDoubleGaus); - hRawYieldsFracDoubleGaus->SetBinError(iSliceVar + 1, fracDoubleGausErr); - } + HFInvMassFitter* massFitter = new HFInvMassFitter(hMass[iSliceVar], massMin[iSliceVar], massMax[iSliceVar], bkgFunc[iSliceVar], sgnFunc[iSliceVar]); + massFitter->setDrawBgPrefit(drawBgPrefit); + massFitter->setHighlightPeakRegion(highlightPeakRegion); + massFitter->setInitialGaussianMean(massPDG); + massFitter->setParticlePdgMass(massPDG); + massFitter->setBoundGaussianMean(massPDG, 0.8 * massPDG, 1.2 * massPDG); + if (useLikelihood) { + massFitter->setUseLikelihoodFit(); } else { - HFInvMassFitter* massFitter; - massFitter = new HFInvMassFitter(hMassForFit[iSliceVar], massMin[iSliceVar], massMax[iSliceVar], - bkgFunc[iSliceVar], sgnFunc[iSliceVar]); - massFitter->setDrawBgPrefit(drawBgPrefit); - massFitter->setHighlightPeakRegion(highlightPeakRegion); - massFitter->setInitialGaussianMean(massPDG); - massFitter->setParticlePdgMass(massPDG); - massFitter->setBoundGaussianMean(massPDG, 0.8 * massPDG, 1.2 * massPDG); - if (useLikelihood) { - massFitter->setUseLikelihoodFit(); - } + massFitter->setUseChi2Fit(); + } - auto setFixedValue = [&iSliceVar](bool const& isFix, std::vector const& fixManual, const TH1* histToFix, std::function setFunc, std::string const& var) -> void { - if (isFix) { - if (fixManual.empty()) { - setFunc(histToFix->GetBinContent(iSliceVar + 1)); - printf("*****************************\n"); - printf("FIXED %s: %f\n", var.data(), histToFix->GetBinContent(iSliceVar + 1)); - printf("*****************************\n"); - } else { - setFunc(fixManual[iSliceVar]); - printf("*****************************\n"); - printf("FIXED %s: %f\n", var.data(), fixManual[iSliceVar]); - printf("*****************************\n"); - } + auto setFixedValue = [&iSliceVar](bool const& isFix, std::vector const& fixManual, const TH1* histToFix, std::function setFunc, std::string const& var) -> void { + if (isFix) { + if (fixManual.empty() && histToFix == nullptr) { + throw std::runtime_error("Histogram to fix " + var + " is null while isFix==true and fixManual is empty"); } - }; - - setFixedValue(fixMean, fixMeanManual, hMeanToFix, std::bind(&HFInvMassFitter::setFixGaussianMean, massFitter, std::placeholders::_1), "MEAN"); - setFixedValue(fixSigma, fixSigmaManual, hSigmaToFix, std::bind(&HFInvMassFitter::setFixGaussianSigma, massFitter, std::placeholders::_1), "SIGMA"); - setFixedValue(fixSecondSigma, fixSecondSigmaManual, hSecondSigmaToFix, std::bind(&HFInvMassFitter::setFixSecondGaussianSigma, massFitter, std::placeholders::_1), "SECOND SIGMA"); - setFixedValue(fixFracDoubleGaus, fixFracDoubleGausManual, hFracDoubleGausToFix, std::bind(&HFInvMassFitter::setFixFrac2Gaus, massFitter, std::placeholders::_1), "FRAC DOUBLE GAUS"); - - if (enableRefl) { - reflOverSgn = hMassForSgn[iSliceVar]->Integral(hMassForSgn[iSliceVar]->FindBin(massMin[iSliceVar] * 1.0001), hMassForSgn[iSliceVar]->FindBin(massMax[iSliceVar] * 0.999)); - reflOverSgn = hMassForRefl[iSliceVar]->Integral(hMassForRefl[iSliceVar]->FindBin(massMin[iSliceVar] * 1.0001), hMassForRefl[iSliceVar]->FindBin(massMax[iSliceVar] * 0.999)) / reflOverSgn; - massFitter->setFixReflOverSgn(reflOverSgn); - massFitter->setTemplateReflections(hMassRefl[iSliceVar]); - } - - massFitter->doFit(); - - const double rawYield = massFitter->getRawYield(); - const double rawYieldErr = massFitter->getRawYieldError(); - const double rawYieldCounted = massFitter->getRawYieldCounted(); - const double rawYieldCountedErr = massFitter->getRawYieldCountedError(); - const double bkg = massFitter->getBkgYield(); - const double bkgErr = massFitter->getBkgYieldError(); - const double significance = massFitter->getSignificance(); - const double significanceErr = massFitter->getSignificanceError(); - const double reducedChiSquareBkg = massFitter->getChiSquareOverNDFBkg(); - const double reducedChiSquareTotal = massFitter->getChiSquareOverNDFTotal(); - const double mean = massFitter->getMean(); - const double meanErr = massFitter->getMeanUncertainty(); - const double sigma = massFitter->getSigma(); - const double sigmaErr = massFitter->getSigmaUncertainty(); - - hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); - hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); - hRawYieldsSignalCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); - hRawYieldsSignalCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); - hRawYieldsBkg->SetBinContent(iSliceVar + 1, bkg); - hRawYieldsBkg->SetBinError(iSliceVar + 1, bkgErr); - hRawYieldsSgnOverBkg->SetBinContent(iSliceVar + 1, rawYield / bkg); - hRawYieldsSgnOverBkg->SetBinError(iSliceVar + 1, rawYield / bkg * std::sqrt(rawYieldErr / rawYield * rawYieldErr / rawYield + bkgErr / bkg * bkgErr / bkg)); - hRawYieldsSignificance->SetBinContent(iSliceVar + 1, significance); - hRawYieldsSignificance->SetBinError(iSliceVar + 1, significanceErr); - hRawYieldsChiSquareBkg->SetBinContent(iSliceVar + 1, reducedChiSquareBkg); - hRawYieldsChiSquareBkg->SetBinError(iSliceVar + 1, 1.e-20); - hRawYieldsChiSquareTotal->SetBinContent(iSliceVar + 1, reducedChiSquareTotal); - hRawYieldsChiSquareTotal->SetBinError(iSliceVar + 1, 1.e-20); - hRawYieldsMean->SetBinContent(iSliceVar + 1, mean); - hRawYieldsMean->SetBinError(iSliceVar + 1, meanErr); - hRawYieldsSigma->SetBinContent(iSliceVar + 1, sigma); - hRawYieldsSigma->SetBinError(iSliceVar + 1, sigmaErr); - - if (sgnFunc[iSliceVar] != HFInvMassFitter::SingleGaus) { - const double secSigma = massFitter->getSecSigma(); - const double secSigmaErr = massFitter->getSecSigmaUncertainty(); - hRawYieldsSecSigma->SetBinContent(iSliceVar + 1, secSigma); - hRawYieldsSecSigma->SetBinError(iSliceVar + 1, secSigmaErr); - } - if (sgnFunc[iSliceVar] == HFInvMassFitter::DoubleGaus || sgnFunc[iSliceVar] == HFInvMassFitter::DoubleGausSigmaRatioPar) { - const double fracDoubleGaus = massFitter->getFracDoubleGaus(); - const double fracDoubleGausErr = massFitter->getFracDoubleGausUncertainty(); - hRawYieldsFracDoubleGaus->SetBinContent(iSliceVar + 1, fracDoubleGaus); - hRawYieldsFracDoubleGaus->SetBinError(iSliceVar + 1, fracDoubleGausErr); + const auto valueToFix = fixManual.empty() ? histToFix->GetBinContent(iSliceVar + 1) : fixManual[iSliceVar]; + setFunc(valueToFix); + printf("*****************************\n"); + printf("FIXED %s: %f\n", var.data(), valueToFix); + printf("*****************************\n"); } + }; + + setFixedValue(fixMean, fixMeanManual, hMeanToFix, std::bind(&HFInvMassFitter::setFixGaussianMean, massFitter, std::placeholders::_1), "MEAN"); + setFixedValue(fixSigma, fixSigmaManual, hSigmaToFix, std::bind(&HFInvMassFitter::setFixGaussianSigma, massFitter, std::placeholders::_1), "SIGMA"); + setFixedValue(fixSecondSigma, fixSecondSigmaManual, hSecondSigmaToFix, std::bind(&HFInvMassFitter::setFixSecondGaussianSigma, massFitter, std::placeholders::_1), "SECOND SIGMA"); + setFixedValue(fixFracDoubleGaus, fixFracDoubleGausManual, hFracDoubleGausToFix, std::bind(&HFInvMassFitter::setFixFrac2Gaus, massFitter, std::placeholders::_1), "FRAC DOUBLE GAUS"); + + if (!isMc && enableRefl) { + reflOverSgn = hMassSgn[iSliceVar]->Integral(hMassSgn[iSliceVar]->FindBin(massMin[iSliceVar] * 1.0001), hMassSgn[iSliceVar]->FindBin(massMax[iSliceVar] * 0.999)); + reflOverSgn = hMassRefl[iSliceVar]->Integral(hMassRefl[iSliceVar]->FindBin(massMin[iSliceVar] * 1.0001), hMassRefl[iSliceVar]->FindBin(massMax[iSliceVar] * 0.999)) / reflOverSgn; + massFitter->setFixReflOverSgn(reflOverSgn); + massFitter->setTemplateReflections(hMassRefl[iSliceVar]); + } - if (enableRefl) { - hReflectionOverSignal->SetBinContent(iSliceVar + 1, reflOverSgn); - if (nSliceVarBins > 1) { - canvasRefl[iCanvas]->cd(iSliceVar - nCanvasesMax * iCanvas + 1); - } else { - canvasRefl[iCanvas]->cd(); - } - massFitter->drawReflection(gPad); - canvasRefl[iCanvas]->Modified(); - canvasRefl[iCanvas]->Update(); - } + massFitter->doFit(); + auto drawOnCanvas = [&](std::vector& canvas, std::function drawer) { if (nSliceVarBins > 1) { - canvasMass[iCanvas]->cd(iSliceVar - nCanvasesMax * iCanvas + 1); + canvas[iCanvas]->cd(iSliceVar - NCanvasesMax * iCanvas + 1); } else { - canvasMass[iCanvas]->cd(); - } - massFitter->drawFit(gPad, plotLabels, writeSignalPar); - canvasMass[iCanvas]->Modified(); - canvasMass[iCanvas]->Update(); - - if (bkgFunc[iSliceVar] != HFInvMassFitter::NoBkg) { - if (nSliceVarBins > 1) { - canvasResiduals[iCanvas]->cd(iSliceVar - nCanvasesMax * iCanvas + 1); - } else { - canvasResiduals[iCanvas]->cd(); - } - massFitter->drawResidual(gPad); - canvasResiduals[iCanvas]->Modified(); - canvasResiduals[iCanvas]->Update(); - - if (nSliceVarBins > 1) { - canvasRatio[iCanvas]->cd(iSliceVar - nCanvasesMax * iCanvas + 1); - } else { - canvasRatio[iCanvas]->cd(); - } - massFitter->drawRatio(gPad); - canvasRatio[iCanvas]->Modified(); - canvasRatio[iCanvas]->Update(); + canvas[iCanvas]->cd(); } + drawer(); + canvas[iCanvas]->Modified(); + canvas[iCanvas]->Update(); + }; + + drawOnCanvas(canvasMass, [&]() { massFitter->drawFit(gPad, plotLabels, writeSignalPar); }); + drawOnCanvas(canvasRatio, [&]() { massFitter->drawRatio(gPad); }); + if (bkgFunc[iSliceVar] != HFInvMassFitter::NoBkg) { + drawOnCanvas(canvasResiduals, [&]() { massFitter->drawResidual(gPad); }); + } + if (enableRefl) { + drawOnCanvas(canvasRefl, [&]() { massFitter->drawReflection(gPad); }); } - hFitConfig->SetBinContent(1, iSliceVar + 1, massMin[iSliceVar]); - hFitConfig->SetBinContent(2, iSliceVar + 1, massMax[iSliceVar]); - hFitConfig->SetBinContent(3, iSliceVar + 1, nRebin[iSliceVar]); + const double rawYield = massFitter->getRawYield(); + const double rawYieldErr = massFitter->getRawYieldError(); + const double rawYieldCounted = massFitter->getRawYieldCounted(); + const double rawYieldCountedErr = massFitter->getRawYieldCountedError(); + const double bkg = massFitter->getBkgYield(); + const double bkgErr = massFitter->getBkgYieldError(); + const double significance = massFitter->getSignificance(); + const double significanceErr = massFitter->getSignificanceError(); + const double reducedChiSquareBkg = massFitter->getChiSquareOverNDFBkg(); + const double reducedChiSquareTotal = massFitter->getChiSquareOverNDFTotal(); + const double mean = massFitter->getMean(); + const double meanErr = massFitter->getMeanUncertainty(); + const double sigma = massFitter->getSigma(); + const double sigmaErr = massFitter->getSigmaUncertainty(); + + hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); + hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); + hRawYieldsSignalCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); + hRawYieldsSignalCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); + hRawYieldsBkg->SetBinContent(iSliceVar + 1, bkg); + hRawYieldsBkg->SetBinError(iSliceVar + 1, bkgErr); + hRawYieldsSgnOverBkg->SetBinContent(iSliceVar + 1, rawYield / bkg); + hRawYieldsSgnOverBkg->SetBinError(iSliceVar + 1, rawYield / bkg * std::sqrt(rawYieldErr / rawYield * rawYieldErr / rawYield + bkgErr / bkg * bkgErr / bkg)); + hRawYieldsSignificance->SetBinContent(iSliceVar + 1, significance); + hRawYieldsSignificance->SetBinError(iSliceVar + 1, significanceErr); + hRawYieldsChiSquareBkg->SetBinContent(iSliceVar + 1, reducedChiSquareBkg); + hRawYieldsChiSquareBkg->SetBinError(iSliceVar + 1, 1.e-20); + hRawYieldsChiSquareTotal->SetBinContent(iSliceVar + 1, reducedChiSquareTotal); + hRawYieldsChiSquareTotal->SetBinError(iSliceVar + 1, 1.e-20); + hRawYieldsMean->SetBinContent(iSliceVar + 1, mean); + hRawYieldsMean->SetBinError(iSliceVar + 1, meanErr); + hRawYieldsSigma->SetBinContent(iSliceVar + 1, sigma); + hRawYieldsSigma->SetBinError(iSliceVar + 1, sigmaErr); + hReflectionOverSignal->SetBinContent(iSliceVar + 1, reflOverSgn); + + if (sgnFunc[iSliceVar] != HFInvMassFitter::SingleGaus) { // TODO foresee DSCB and Voigt cases + const double secSigma = massFitter->getSecSigma(); + const double secSigmaErr = massFitter->getSecSigmaUncertainty(); + hRawYieldsSecSigma->SetBinContent(iSliceVar + 1, secSigma); + hRawYieldsSecSigma->SetBinError(iSliceVar + 1, secSigmaErr); + } + if (sgnFunc[iSliceVar] == HFInvMassFitter::DoubleGaus || sgnFunc[iSliceVar] == HFInvMassFitter::DoubleGausSigmaRatioPar) { + const double fracDoubleGaus = massFitter->getFracDoubleGaus(); + const double fracDoubleGausErr = massFitter->getFracDoubleGausUncertainty(); + hRawYieldsFracDoubleGaus->SetBinContent(iSliceVar + 1, fracDoubleGaus); + hRawYieldsFracDoubleGaus->SetBinError(iSliceVar + 1, fracDoubleGausErr); + } + + hFitConfig->SetBinContent(ConfigMassMin, iSliceVar + 1, massMin[iSliceVar]); + hFitConfig->SetBinContent(ConfigMassMax, iSliceVar + 1, massMax[iSliceVar]); + hFitConfig->SetBinContent(ConfigNRebin, iSliceVar + 1, nRebin[iSliceVar]); if (fixSigma) { - if (fixSigmaManual.empty()) { - hFitConfig->SetBinContent(4, iSliceVar + 1, hSigmaToFix->GetBinContent(iSliceVar + 1)); - } else { - hFitConfig->SetBinContent(4, iSliceVar + 1, fixSigmaManual[iSliceVar]); - } + const auto valueToFix = fixSigmaManual.empty() ? hSigmaToFix->GetBinContent(iSliceVar + 1) : fixSigmaManual[iSliceVar]; + hFitConfig->SetBinContent(ConfigFixSigma, iSliceVar + 1, valueToFix); } - hFitConfig->SetBinContent(5, iSliceVar + 1, bkgFuncConfig[iSliceVar]); - hFitConfig->SetBinContent(6, iSliceVar + 1, sgnFuncConfig[iSliceVar]); + hFitConfig->SetBinContent(ConfigBkgFunc, iSliceVar + 1, bkgFunc[iSliceVar]); + hFitConfig->SetBinContent(ConfigSgnFunc, iSliceVar + 1, sgnFunc[iSliceVar]); } // save output histograms @@ -606,7 +500,7 @@ int runMassFitter(const TString& configFileName) } } - for (unsigned int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { + for (int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { hMass[iSliceVar]->Write(); } hRawYieldsSignal->Write(); @@ -633,38 +527,20 @@ int runMassFitter(const TString& configFileName) TString outputFileRatio = outputFileName; outputFileRatio.ReplaceAll(".pdf", "_Ratio.pdf"); for (int iCanvas = 0; iCanvas < nCanvases; iCanvas++) { - if (iCanvas == 0 && nCanvases > 1) { - canvasMass[iCanvas]->SaveAs(Form("%s[", outputFileName.Data())); - } - canvasMass[iCanvas]->SaveAs(outputFileName.Data()); - if (iCanvas == nCanvases - 1 && nCanvases > 1) { - canvasMass[iCanvas]->SaveAs(Form("%s]", outputFileName.Data())); - } + const std::string printingBracket = nCanvases == 1 ? "" : iCanvas == 0 ? "(" + : iCanvas == nCanvases - 1 ? ")" + : ""; + canvasMass[iCanvas]->Print(Form("%s%s", outputFileName.Data(), printingBracket.c_str()), "pdf"); + canvasRatio[iCanvas]->Print(Form("%s%s", outputFileRatio.Data(), printingBracket.c_str()), "pdf"); if (!isMc) { - // residuals - if (iCanvas == 0 && nCanvases > 1) { - canvasResiduals[iCanvas]->SaveAs(Form("%s[", outputFileNameResidual.Data())); - } - canvasResiduals[iCanvas]->SaveAs(outputFileNameResidual.Data()); - if (iCanvas == nCanvases - 1 && nCanvases > 1) { - canvasResiduals[iCanvas]->SaveAs(Form("%s]", outputFileNameResidual.Data())); - } - // ratio - if (iCanvas == 0 && nCanvases > 1) { - canvasRatio[iCanvas]->SaveAs(Form("%s[", outputFileRatio.Data())); - } - canvasRatio[iCanvas]->SaveAs(outputFileRatio.Data()); - if (iCanvas == nCanvases - 1 && nCanvases > 1) { - canvasRatio[iCanvas]->SaveAs(Form("%s]", outputFileRatio.Data())); - } + canvasResiduals[iCanvas]->Print(Form("%s%s", outputFileNameResidual.Data(), printingBracket.c_str()), "pdf"); } } - return 0; } void setHistoStyle(TH1* histo, Color_t color, Size_t markerSize) { - histo->SetStats(kFALSE); + histo->SetStats(false); histo->SetMarkerSize(markerSize); histo->SetMarkerStyle(20); histo->SetLineWidth(2); @@ -679,10 +555,85 @@ void divideCanvas(TCanvas* canvas, int nSliceVarBins) canvas->Divide(nCols, nRows); } +TFile* openFileWithNullptrCheck(const std::string& fileName, const std::string& option) +{ + TFile* file = TFile::Open(fileName.c_str(), option.c_str()); + if (file == nullptr || file->IsZombie()) { + throw std::runtime_error("openFileWithNullptrCheck(): Cannot open file " + fileName); + } + return file; +} + +template +T* getObjectWithNullPtrCheck(TFile* fileIn, const std::string& objectName) +{ + T* ptr = fileIn->Get(objectName.c_str()); + if (ptr == nullptr) { + throw std::runtime_error("getObjectWithNullptrCheck() - object " + objectName + " in file " + fileIn->GetName() + " is missing"); + } + return ptr; +} + +template +constexpr bool AlwaysFalse = false; + +template +T getJsonValue(const Value& value) +{ + if constexpr (std::is_same_v, std::string>) { + return value.GetString(); + } else if constexpr (std::is_same_v, bool>) { + return value.GetBool(); + } else if constexpr (std::is_same_v, int>) { + return value.GetInt(); + } else if constexpr (std::is_same_v, double>) { + return value.GetDouble(); + } else { + static_assert(AlwaysFalse, "getJsonValue(): unsupported type!"); + return T(); + } +} + +template +T readJsonField(const Document& config, const std::string& fieldName, const T& defaultValue) +{ + if (!config.HasMember(fieldName.c_str())) { + return defaultValue; + } + const auto& value = config[fieldName.c_str()]; + return getJsonValue(value); +} + +template +T readJsonField(const Document& config, const std::string& fieldName) +{ + if (!config.HasMember(fieldName.c_str())) { + throw std::runtime_error("readJsonField(): missing field " + fieldName); + } + return readJsonField(config, fieldName, T()); +} + +template +void readJsonVector(std::vector& vec, const Document& config, const std::string& fieldName, const bool isRequired) +{ + if (!vec.empty()) { + throw std::runtime_error("readJsonVector(): vector is not empty!"); + } + if (config.HasMember(fieldName.c_str())) { + const Value& jsonArray = config[fieldName.c_str()]; + for (auto it = jsonArray.Begin(); it != jsonArray.End(); it++) { + vec.push_back(getJsonValue(*it)); + } + } else if (isRequired) { + throw std::runtime_error("readJsonVector(): missing required field " + fieldName); + } +} + int main(int argc, const char* argv[]) { if (argc == 1) { - throw std::runtime_error("Not enough arguments. Please use\n./runMassFitter configFileName"); + printf("Not enough arguments. Please use\n./runMassFitter configFileName\n"); + return 1; } const std::string configFileName = argv[1]; diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 19a4a7ae123..674bbeeb25c 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -72,17 +72,17 @@ o2physics_add_dpl_workflow(data-creator-charm-had-pi-reduced o2physics_add_dpl_workflow(data-creator-charm-reso-to-dstar-reduced SOURCES dataCreatorCharmResoToDstarReduced.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(data-creator-charm-reso-to-dplus-reduced SOURCES dataCreatorCharmResoToDplusReduced.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(data-creator-charm-reso-to-d0-reduced SOURCES dataCreatorCharmResoToD0Reduced.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(data-creator-jpsi-had-reduced @@ -90,6 +90,11 @@ o2physics_add_dpl_workflow(data-creator-jpsi-had-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(data-creator-hidden-charm-reduced + SOURCES dataCreatorHiddenCharmReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + # Converters o2physics_add_dpl_workflow(converter-reduced-3-prongs-ml diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index 49cff73feea..613bae38b31 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -192,8 +192,7 @@ struct HfCandidateCreatorB0Reduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate D and Pi to the B0 vertex - df3.propagateTracksToVertex(); + // get D and Pi tracks (propagated to the B0 vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df3.getTrack(0).getPxPyPzGlo(pVecD0); // momentum of D at the B0 vertex df3.getTrack(1).getPxPyPzGlo(pVecSoftPion); // momentum of SoftPi at the B0 vertex @@ -210,7 +209,7 @@ struct HfCandidateCreatorB0Reduced { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaBachPion); // get uncertainty of the decay length - float phi, theta; + float phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); @@ -299,8 +298,7 @@ struct HfCandidateCreatorB0Reduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate D and Pi to the B0 vertex - df2.propagateTracksToVertex(); + // get D and Pi tracks (propagated to the B0 vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of D at the B0 vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the B0 vertex @@ -314,7 +312,7 @@ struct HfCandidateCreatorB0Reduced { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); // get uncertainty of the decay length - float phi, theta; + float phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx index 444ee4b1afe..b3777ae9012 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx @@ -238,8 +238,7 @@ struct HfCandidateCreatorBToJpsiReduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate Jpsi daugthers and K to the B+ vertex - df3.propagateTracksToVertex(); + // get JPsi daughters and K tracks (propagated to the B+ vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df3.getTrack(0).getPxPyPzGlo(pVecDauPos); // momentum of positive Jpsi daughter at the B+ vertex df3.getTrack(1).getPxPyPzGlo(pVecDauNeg); // momentum of negative Jpsi daughter at the B+ vertex @@ -259,7 +258,7 @@ struct HfCandidateCreatorBToJpsiReduced { trackParCovLf0.propagateToDCA(primaryVertex, bz, &dcaKaon); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBplus, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); @@ -309,8 +308,7 @@ struct HfCandidateCreatorBToJpsiReduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate Jpsi and phi to the Bs vertex - df4.propagateTracksToVertex(); + // get JPsi daughters and K tracks (propagated to the Bs vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df4.getTrack(0).getPxPyPzGlo(pVecDauPos); // momentum of Jpsi at the B+ vertex df4.getTrack(1).getPxPyPzGlo(pVecDauNeg); // momentum of Jpsi at the B+ vertex @@ -332,7 +330,7 @@ struct HfCandidateCreatorBToJpsiReduced { trackParCovLf1.propagateToDCA(primaryVertex, bz, &dcaTrackLf1); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBs, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx index a5f5ba5779b..2ef89ce34c5 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx @@ -169,8 +169,7 @@ struct HfCandidateCreatorBplusReduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate D0 and Pi to the B+ vertex - df2.propagateTracksToVertex(); + // get D and Pi tracks (propagated to the B+ vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df2.getTrack(0).getPxPyPzGlo(pVecD0); // momentum of D0 at the B+ vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the B+ vertex @@ -184,7 +183,7 @@ struct HfCandidateCreatorBplusReduced { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBplus, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx index 3317b7383fa..8bed227e12d 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx @@ -169,8 +169,7 @@ struct HfCandidateCreatorBsReduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate Ds and Pi to the Bs vertex - df2.propagateTracksToVertex(); + // get Ds and Pi tracks (propagated to the B0 vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of Ds at the Bs vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the Bs vertex @@ -184,7 +183,7 @@ struct HfCandidateCreatorBsReduced { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); // get uncertainty of the decay length - float phi, theta; + float phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index 46fd5998702..b1affb1cbac 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -450,7 +450,7 @@ struct HfCandidateCreatorCharmResoReduced { registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); } } else if constexpr (DType == DMesonType::Dstar) { - float invMassD0; + float invMassD0{}; if (candD.sign() > 0) { invMassD = candD.invMassDstar(); invMassD0 = candD.invMassD0(); diff --git a/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx index 77b9457ecb2..1b43d988285 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx @@ -189,8 +189,7 @@ struct HfCandidateCreatorLbReduced { registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); - // propagate Lc and Pi to the Lb vertex - df2.propagateTracksToVertex(); + // get Lc and Pi tracks (propagated to the Lb vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df2.getTrack(0).getPxPyPzGlo(pVecLc); // momentum of Lc at the Lb vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the Lb vertex @@ -204,7 +203,7 @@ struct HfCandidateCreatorLbReduced { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); // get uncertainty of the decay length - float phi, theta; + float phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexLb, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 1975df6dd4d..880fd3f62e5 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -209,12 +209,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::HfEventSelectionMc hfEvSelMc; // CCDB service - Service ccdb; + Service ccdb{}; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber{}; // O2DatabasePDG service - Service pdg; + Service pdg{}; double massC{0.}; double massB{0.}; diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx index 5815c9cbedd..6526044e6d2 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToD0Reduced.cxx @@ -24,6 +24,7 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/TPCVDriftManager.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" @@ -86,6 +87,8 @@ struct HfDataCreatorCharmResoToD0Reduced { } cfgDmesCuts; // selection V0 HfResoConfigV0Cuts cfgV0Cuts; + // selection Gamma + HfResoConfigGammaCuts cfgGammaCuts; // selection single tracks HfResoConfigSingleTrackCuts cfgSingleTrackCuts; // QA histograms @@ -102,16 +105,17 @@ struct HfDataCreatorCharmResoToD0Reduced { // CCDB service o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + Service ccdb{}; double bz{0.}; int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. // material correction for track propagation o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::aod::common::TPCVDriftManager vDriftMgr; // O2DatabasePDG service - Service pdg; + Service pdg{}; // vertex fitter o2::vertexing::DCAFitterN<2> fitter; @@ -125,6 +129,7 @@ struct HfDataCreatorCharmResoToD0Reduced { using TracksWithPID = soa::Join; using TracksWithPIDAndMC = soa::Join; using TracksIUWithPID = soa::Join; + using TracksIUWithElPID = soa::Join; using TracksIUWithPIDAndMC = soa::Join; // Collisions MC using BCsInfo = soa::Join; @@ -216,7 +221,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -251,7 +256,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -289,7 +294,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -326,13 +331,48 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD2PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoToD0Reduced, processD0V0WithMl, "Process D0 candidates paired with V0s with ML info", false); + void processD0GammaWithMl(soa::Join const& collisions, + CandsD0FilteredWithMl const& candsD0, + aod::V0s const& v0s, + TracksIUWithElPID const& tracksIU, + aod::BCsWithTimestamps const&) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + int dummyTable{0}; + for (const auto& collision : collisions) { + const auto hfRejMap = o2::hf_evsel::getEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + if (rejectCollisionsWithBadEvSel && hfRejMap != 0) { + continue; + } + auto bc = collision.template bc_as(); + 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); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD2PrMl, &vDriftMgr); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoToD0Reduced, processD0GammaWithMl, "Process D0 candidates paired with gammas with ML info", false); + void processD0TrackWithMl(soa::Join const& collisions, CandsD0FilteredWithMl const& candsD0, aod::TrackAssoc const& trackIndices, @@ -361,7 +401,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -399,7 +439,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD2PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -439,7 +479,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -478,7 +518,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -520,7 +560,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -560,7 +600,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, dummyTable, rowHf2PrV0McRecReduced, dummyTable, hfCandD2PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -599,7 +639,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -640,7 +680,7 @@ struct HfDataCreatorCharmResoToD0Reduced { auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgGammaCuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD2Pr, hfCandV0, hfTrackNoParam, rowHf2PrV0McRecReduced, rowHf2PrTrkMcRecReduced, hfCandD2PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx index 597b49845c1..71c1f6b49cc 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDplusReduced.cxx @@ -102,7 +102,7 @@ struct HfDataCreatorCharmResoToDplusReduced { // CCDB service o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + Service ccdb{}; double bz{0.}; int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. @@ -111,7 +111,7 @@ struct HfDataCreatorCharmResoToDplusReduced { o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; // O2DatabasePDG service - Service pdg; + Service pdg{}; // vertex fitter o2::vertexing::DCAFitterN<2> fitter; @@ -215,7 +215,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -250,7 +250,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -288,7 +288,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -325,7 +325,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -360,7 +360,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -398,7 +398,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -437,7 +437,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -476,7 +476,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -518,7 +518,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -558,7 +558,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, dummyTable, rowHf3PrV0McRecReduced, dummyTable, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -597,7 +597,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, dummyTable, hfTrackNoParam, dummyTable, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -638,7 +638,7 @@ struct HfDataCreatorCharmResoToDplusReduced { auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandD3Pr, hfCandV0, hfTrackNoParam, rowHf3PrV0McRecReduced, rowHf3PrTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx index 785b8986eee..d8939b6a765 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoToDstarReduced.cxx @@ -101,7 +101,7 @@ struct HfDataCreatorCharmResoToDstarReduced { // CCDB service o2::ccdb::CcdbApi ccdbApi; - Service ccdb; + Service ccdb{}; double bz{0.}; int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. @@ -110,7 +110,7 @@ struct HfDataCreatorCharmResoToDstarReduced { o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; // O2DatabasePDG service - Service pdg; + Service pdg{}; // vertex fitter o2::vertexing::DCAFitterN<2> fitter; @@ -215,7 +215,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -251,7 +251,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -289,7 +289,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, dummyTable); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -326,7 +326,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -361,7 +361,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -399,7 +399,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, nullptr, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, dummyTable, dummyTable, hfCandD3PrMl); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -439,7 +439,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -478,7 +478,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -520,7 +520,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, dummyTable); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, dummyTable); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -560,7 +560,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, dummyTable, rowHfDstarV0McRecReduced, dummyTable, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -599,7 +599,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, dummyTable, hfTrackNoParam, dummyTable, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions @@ -640,7 +640,7 @@ struct HfDataCreatorCharmResoToDstarReduced { auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); + runDataCreation>(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, hfRejMap, bz, pdg, registry, matCorr, fitter, cfgDmesCuts, cfgSingleTrackCuts, cfgV0Cuts, cfgV0Cuts, cfgQaPlots, rejectPairsWithCommonDaughter, hfReducedCollision, hfCandDstar, hfCandV0, hfTrackNoParam, rowHfDstarV0McRecReduced, rowHfDstarTrkMcRecReduced, hfCandD3PrMl); } runMcGen(particlesMc, mcParticlesPerMcCollision, collInfos, colPerMcCollision, mcCollisions, hfEvSelMc, rejectCollisionsWithBadEvSel, registry, pdg, rowHfResoMcGenReduced, bcs); // handle normalization by the right number of collisions diff --git a/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx new file mode 100644 index 00000000000..2e9a00bd6b5 --- /dev/null +++ b/PWGHF/D2H/TableProducer/dataCreatorHiddenCharmReduced.cxx @@ -0,0 +1,318 @@ +// 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 dataCreatorHiddenCharmReduced.cxx +/// \brief Reduced data creator for hidden-charm analyses at midrapidity +/// +/// \author A. Palasciano, , INFN Bari +/// \author S. Politanò , CERN + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/Core/TPCVDriftManager.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; + +enum TrackType : uint8_t { + Pion = 0, + Kaon, + Proton +}; + +struct HfDataCreatorHiddenCharmReduced { + + Produces hfReducedCollision; + Produces hfCollisionCounter; + Produces hfTrackLite; + + struct : ConfigurableGroup { + // track quality + Configurable fillHistograms{"fillHistograms", true, "Fill proton QA histograms"}; + Configurable selectProtons{"selectProtons", true, "Select protons"}; + Configurable itsNClsMin{"itsNClsMin", 5, "Minimum number of ITS clusters"}; + Configurable tpcNClsFoundMin{"tpcNClsFoundMin", 50, "Minimum number of found TPC clusters"}; + Configurable tpcNClsCrossedRowsMin{"tpcNClsCrossedRowsMin", 80, "Minimum number of crossed TPC rows"}; + Configurable ptMinTrack{"ptMinTrack", 0.5, "Minimum proton-track pT"}; + Configurable etaMaxTrack{"etaMaxTrack", 0.8, "Maximum proton-track |eta|"}; + Configurable momForCombinedPid{"momForCombinedPid", 0.75f, "Momentum threshold above which combined TPC+TOF proton PID is used"}; + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "Track pT bin limits for DCA cuts"}; + Configurable> cutsTrack{"cutsTrack", {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 DCA selections per pT bin"}; + Configurable maxNsigmaTofPi{"maxNsigmaTofPi", 2.f, "Maximum pion n-sigma in TOF for proton rejection"}; + Configurable maxNsigmaTofKa{"maxNsigmaTofKa", 2.f, "Maximum kaon n-sigma in TOF for proton rejection"}; + Configurable maxNsigmaCombinedPr{"maxNsigmaCombinedPr", 3.f, "Maximum combined proton n-sigma from TPC and TOF"}; + Configurable maxNsigmaTpcPi{"maxNsigmaTpcPi", 2.f, "Maximum pion n-sigma in TPC for proton rejection"}; + Configurable maxNsigmaTpcKa{"maxNsigmaTpcKa", 2.f, "Maximum kaon n-sigma in TPC for proton rejection"}; + Configurable maxNsigmaTpcPr{"maxNsigmaTpcPr", 3.f, "Maximum proton n-sigma in TPC"}; + Configurable forceTOF{"forceTOF", false, "Require TOF PID information for proton selection"}; + } config; + + // Configurable (others) + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + Configurable doMcRecQa{"doMcRecQa", true, "Fill QA histograms for Mc matching"}; + Configurable rejectPairsWithCommonDaughter{"rejectPairsWithCommonDaughter", true, "flag to reject already at this stage the pairs that share a daughter track"}; + Configurable rejectCollisionsWithBadEvSel{"rejectCollisionsWithBadEvSel", true, "flag to reject collisions with bad event selection"}; + + o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; + + double bz{0.}; + int runNumber{0}; // needed to detect if the run changed and trigger update of calibrations etc. + + // material correction for track propagation + o2::base::MatLayerCylSet* lut{}; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + o2::aod::common::TPCVDriftManager vDriftMgr; + o2::ccdb::CcdbApi ccdbApi; + Service ccdb{}; + + using BCsInfo = soa::Join; + using TracksWithPID = soa::Join; + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + HistogramRegistry registry{"registry"}; + OutputObj zorroSummary{"zorroSummary"}; + + void init(InitContext& initContext) + { + // Configure CCDB access + ccdb->setURL(ccdbUrl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + ccdbApi.init(ccdbUrl); + runNumber = 0; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + if (config.fillHistograms) { + const AxisSpec axisPt{360, 0., 36., "#it{p}_{T}^{proton} (GeV/#it{c})"}; + const AxisSpec axisEta{100, -1., 1., "#eta"}; + const AxisSpec axisDca{400, -2., 2., "DCA_{xy} to primary vertex (cm)"}; + const AxisSpec axisNSigma{100, -5., 5., "n#sigma"}; + + registry.add("hPzVtx", "Z position of primary vertex for selected tracks;z_{vtx} (cm);entries", {HistType::kTH1D, {AxisSpec{200, -20., 20., "z_{vtx} (cm)"}}}); + registry.add("hPtNoCuts", "All associated tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPt}}); + registry.add("hPtCutsProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPt}}); + registry.add("hEtaCutsProton", "Selected proton tracks;#eta;entries", {HistType::kTH1D, {axisEta}}); + registry.add("hDCAToPrimXYVsPtCutsProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});DCA_{xy} to primary vertex (cm)", {HistType::kTH2D, {axisPt, axisDca}}); + registry.add("hNSigmaTPCProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TPC}", {HistType::kTH2D, {axisPt, axisNSigma}}); + registry.add("hNSigmaTOFProton", "Selected proton tracks;#it{p}_{T}^{track} (GeV/#it{c});n#sigma_{TOF}", {HistType::kTH2D, {axisPt, axisNSigma}}); + registry.add("hInvMass", "Invariant mass of selected proton with all other tracks in the event;#it{p}_{T}^{proton} (GeV/#it{c});invariant mass with other tracks (GeV/#it{c}^{2})", {HistType::kTH2D, {axisPt, AxisSpec{100, 2.85, 3.25, "invariant mass with other tracks (GeV/#it{c}^{2})"}}}); + } + + // init HF event selection helper + hfEvSel.init(registry, &zorroSummary); + + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name == "hf-data-creator-charm-reso-to-d0-reduced") { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } + } + + template + bool isSelectedPid(TTrack const& track) const + { + const float momForCombinedPid = config.momForCombinedPid.value; + const float maxNsigmaTpcPr = config.maxNsigmaTpcPr.value; + const float maxNsigmaTpcPi = config.maxNsigmaTpcPi.value; + const float maxNsigmaTpcKa = config.maxNsigmaTpcKa.value; + const float maxNsigmaCombinedPr = config.maxNsigmaCombinedPr.value; + const float maxNsigmaTofPi = config.maxNsigmaTofPi.value; + const float maxNsigmaTofKa = config.maxNsigmaTofKa.value; + const bool forceTOF = config.forceTOF.value; + + const float mom = std::hypot(track.px(), track.py(), track.pz()); + const float nSigmaTPCPr = track.tpcNSigmaPr(); + const float nSigmaTPCPi = track.tpcNSigmaPi(); + const float nSigmaTPCKa = track.tpcNSigmaKa(); + const bool hasTOF = track.hasTOF(); + if (!hasTOF && forceTOF) { + return false; + } + + bool isProton = false; + bool rejectAsPion = false; + bool rejectAsKaon = false; + + if (mom < momForCombinedPid || !hasTOF) { + isProton = std::abs(nSigmaTPCPr) < maxNsigmaTpcPr; + rejectAsPion = std::abs(nSigmaTPCPi) < maxNsigmaTpcPi; + rejectAsKaon = std::abs(nSigmaTPCKa) < maxNsigmaTpcKa; + } else { + const float nSigmaTOFPr = track.tofNSigmaPr(); + const float nSigmaTOFPi = track.tofNSigmaPi(); + const float nSigmaTOFKa = track.tofNSigmaKa(); + isProton = std::hypot(nSigmaTPCPr, nSigmaTOFPr) < maxNsigmaCombinedPr; + rejectAsPion = std::hypot(nSigmaTPCPi, nSigmaTOFPi) < maxNsigmaTofPi; + rejectAsKaon = std::hypot(nSigmaTPCKa, nSigmaTOFKa) < maxNsigmaTofKa; + } + return isProton && !rejectAsPion && !rejectAsKaon; + } + + template + bool isSelectedTrack(TTrack const& track) const + { + const int tpcNClsFoundMin = config.tpcNClsFoundMin.value; + const int tpcNClsCrossedRowsMin = config.tpcNClsCrossedRowsMin.value; + const int itsNClsMin = config.itsNClsMin.value; + const double etaMaxTrack = config.etaMaxTrack.value; + const double ptMinTrack = config.ptMinTrack.value; + + if (!track.isGlobalTrackWoDCA()) { + return false; + } + if (track.tpcNClsFound() < tpcNClsFoundMin) { + return false; + } + if (track.tpcNClsCrossedRows() < tpcNClsCrossedRowsMin) { + return false; + } + if (track.itsNCls() < itsNClsMin) { + return false; + } + if (std::abs(track.eta()) > etaMaxTrack) { + return false; + } + if (track.pt() < ptMinTrack) { + return false; + } + if (!isSelectedTrackDca(config.binsPtTrack, config.cutsTrack, track.pt(), track.dcaXY(), track.dcaZ())) { + return false; + } + return isSelectedPid(track); + } + + void processEtaCTrack(soa::Join const& collisions, + aod::TrackAssoc const& trackIndices, + TracksWithPID const& tracks, + aod::BCsWithTimestamps const&) + { + hfTrackLite.reserve(tracks.size()); + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + constexpr int NDaughtersCharmMeson = 2; + for (const auto& collision : collisions) { + const auto hfRejMap = o2::hf_evsel::getEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + if (rejectCollisionsWithBadEvSel && hfRejMap != 0) { + continue; + } + const auto thisCollId = collision.globalIndex(); + const auto trackIds = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + if (config.fillHistograms) { + registry.fill(HIST("hPzVtx"), collision.posZ()); + } + std::vector selectedTrackIds; + for (const auto& trkId : trackIds) { + auto trk = trkId.track_as(); + if (config.fillHistograms) { + registry.fill(HIST("hPtNoCuts"), trk.pt()); + } + if (!isSelectedTrack(trk)) { + continue; + } + std::array pVecProton{trk.pVector()}; + hfTrackLite(trk.globalIndex(), collision.globalIndex(), pVecProton[0], pVecProton[1], pVecProton[2], trk.sign(), static_cast(TrackType::Proton)); + selectedTrackIds.push_back(trk.globalIndex()); + if (config.fillHistograms) { + registry.fill(HIST("hPtCutsProton"), trk.pt()); + registry.fill(HIST("hEtaCutsProton"), trk.eta()); + registry.fill(HIST("hDCAToPrimXYVsPtCutsProton"), trk.pt(), trk.dcaXY()); + registry.fill(HIST("hNSigmaTPCProton"), trk.pt(), trk.tpcNSigmaPr()); + if (trk.hasTOF()) { + registry.fill(HIST("hNSigmaTOFProton"), trk.pt(), trk.tofNSigmaPr()); + } + } + } + if (selectedTrackIds.size() < NDaughtersCharmMeson) { + continue; + } + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); + for (size_t i = 0; i < selectedTrackIds.size(); ++i) { + auto t1 = tracks.rawIteratorAt(selectedTrackIds[i]); + std::array pVec1{t1.pVector()}; + for (size_t j = i + 1; j < selectedTrackIds.size(); ++j) { + auto t2 = tracks.rawIteratorAt(selectedTrackIds[j]); + if (t1.sign() * t2.sign() > 0) { + continue; + } + std::array pVec2{t2.pVector()}; + float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); + float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); + if (config.fillHistograms) { + registry.fill(HIST("hInvMass"), ptEtac, invMass); + } + } + } + } + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + + PROCESS_SWITCH(HfDataCreatorHiddenCharmReduced, processEtaCTrack, "EtaC -> p pbar reconstruction", true); +}; + +// struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{}; + workflow.push_back(adaptAnalysisTask(cfgc)); + return workflow; +} diff --git a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx index 7a991f3adad..c6ab8136c26 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx @@ -192,9 +192,9 @@ struct HfDataCreatorJpsiHadReduced { TrackSelectorEl selectorElectron; // CCDB service - Service ccdb; + Service ccdb{}; // O2DatabasePDG service - Service pdg; + Service pdg{}; using TracksPid = soa::Join; using TracksPidWithSel = soa::Join; @@ -803,8 +803,7 @@ struct HfDataCreatorJpsiHadReduced { // --------------------------------- // reconstruct J/Psi candidate secondary vertex - o2::track::TrackParCov const trackParCovJpsi{}; // FIXME: unused - std::array const pVecJpsi{}; // FIXME: unused + std::array pVecJpsi{}; registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::BeforeFit); try { if (df2.process(trackPosParCov, trackNegParCov) == 0) { @@ -858,12 +857,6 @@ struct HfDataCreatorJpsiHadReduced { if constexpr (DecChannel == DecayChannel::BplusToJpsiK) { registry.fill(HIST("hPtKaon"), trackParCovBach.getPt()); - // compute invariant mass square and apply selection - invMass2JpsiHad = RecoDecay::m2(std::array{pVecJpsi, pVecBach}, std::array{MassJPsi, MassKPlus}); - if ((invMass2JpsiHad < invMass2JpsiHadMin) || (invMass2JpsiHad > invMass2JpsiHadMax)) { - continue; - } - registry.fill(HIST("hMassJpsiKaon"), std::sqrt(invMass2JpsiHad)); registry.fill(HIST("hFitCandidatesBPlus"), SVFitting::BeforeFit); try { @@ -881,17 +874,23 @@ struct HfDataCreatorJpsiHadReduced { std::array pVecBPlus{}, pVec0{}, pVec1{}, pVec2{}; auto secondaryVertexBPlus = df3.getPCACandidate(); - df3.propagateTracksToVertex(); df3.getTrack(0).getPxPyPzGlo(pVec0); df3.getTrack(1).getPxPyPzGlo(pVec1); df3.getTrack(2).getPxPyPzGlo(pVec2); pVecBPlus = RecoDecay::pVec(pVec0, pVec1, pVec2); + pVecJpsi = RecoDecay::pVec(pVec0, pVec1); trackParCovBPlus = df3.createParentTrackParCov(); trackParCovBPlus.setAbsCharge(0); // to be sure if (!isBSelected(pVecBPlus, secondaryVertexBPlus, collision)) { continue; } + // compute invariant mass square and apply selection + invMass2JpsiHad = RecoDecay::m2(std::array{pVecJpsi, pVecBach}, std::array{MassJPsi, MassKPlus}); + if ((invMass2JpsiHad < invMass2JpsiHadMin) || (invMass2JpsiHad > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassJpsiKaon"), std::sqrt(invMass2JpsiHad)); // fill Kaon tracks table // if information on track already stored, go to next track @@ -969,12 +968,12 @@ struct HfDataCreatorJpsiHadReduced { std::array pVecBS{}, pVec0{}, pVec1{}, pVecPhi{}; auto secondaryVertexBS = df4.getPCACandidate(); - df4.propagateTracksToVertex(); df4.getTrack(0).getPxPyPzGlo(pVec0); df4.getTrack(1).getPxPyPzGlo(pVec1); df4.getTrack(2).getPxPyPzGlo(pVec2); df4.getTrack(3).getPxPyPzGlo(pVec3); pVecBS = RecoDecay::pVec(pVec0, pVec1, pVec2, pVec3); + pVecJpsi = RecoDecay::pVec(pVec0, pVec1); pVecPhi = RecoDecay::pVec(pVec2, pVec3); trackParCovBS = df4.createParentTrackParCov(); trackParCovBS.setAbsCharge(0); // to be sure diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 60935839fc9..608145a8e51 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -124,6 +124,11 @@ o2physics_add_dpl_workflow(task-omegac0-to-omega-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-pt-fluc-charm-hadrons + SOURCES taskPtFlucCharmHadrons.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-sigmac SOURCES taskSigmac.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -144,12 +149,12 @@ o2physics_add_dpl_workflow(task-xic-to-xi-pi-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(task-xicc - SOURCES taskXicc.cxx +o2physics_add_dpl_workflow(task-xic0-to-xi-pi + SOURCES taskXic0ToXiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(task-xic0-to-xi-pi - SOURCES taskXic0ToXiPi.cxx +o2physics_add_dpl_workflow(task-hidden-charm + SOURCES taskHiddenCharm.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/D2H/Tasks/taskB0.cxx b/PWGHF/D2H/Tasks/taskB0.cxx index 4fe85452d27..ca89758c2b9 100644 --- a/PWGHF/D2H/Tasks/taskB0.cxx +++ b/PWGHF/D2H/Tasks/taskB0.cxx @@ -64,7 +64,7 @@ struct HfTaskB0 { Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "Flag to enable DecayType histogram"}; // O2DatabasePDG service - Service pdg; + Service pdg{}; using TracksWithSel = soa::Join; diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 5e146308c45..16634591c5f 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -152,13 +152,13 @@ DECLARE_SOA_TABLE(HfRedCandB0Lites, "AOD", "HFREDCANDB0LITE", //! Table with som hf_cand_b0_lite::NSigTofPiBachelor, hf_cand_b0_lite::NSigTpcTofPiBachelor, // MC truth - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_b0_lite::FlagWrongCollision, hf_cand_b0_lite::PtGen); DECLARE_SOA_TABLE(HfRedB0McCheck, "AOD", "HFREDB0MCCHECK", //! Table with MC decay type check - hf_cand_3prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_b0_lite::FlagWrongCollision, hf_cand_b0_lite::MD, hf_cand_b0_lite::PtD, diff --git a/PWGHF/D2H/Tasks/taskBplus.cxx b/PWGHF/D2H/Tasks/taskBplus.cxx index 75712e018f0..f3223f55eba 100644 --- a/PWGHF/D2H/Tasks/taskBplus.cxx +++ b/PWGHF/D2H/Tasks/taskBplus.cxx @@ -70,7 +70,7 @@ struct HfTaskBplus { Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_d0_pi::vecBinsPt}, "pT bin limits"}; // O2DatabasePDG service - Service pdg; + Service pdg{}; Partition> selectedBPlusCandidates = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; Partition> selectedBPlusCandidatesMC = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx index bca08dbf154..5913760dcea 100644 --- a/PWGHF/D2H/Tasks/taskBplusReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -149,13 +149,13 @@ DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with som hf_cand_bplus_lite::NSigTofPiBachelor, hf_cand_bplus_lite::NSigTpcTofPiBachelor, // MC truth - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bplus_lite::FlagWrongCollision, hf_cand_bplus_lite::PtGen); DECLARE_SOA_TABLE(HfRedBpMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check - hf_cand_2prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_bplus_lite::FlagWrongCollision, hf_cand_bplus_lite::MD, hf_cand_bplus_lite::PtD, diff --git a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx index aa0ff931938..31fae6a389d 100644 --- a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -164,14 +164,14 @@ DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with som hf_cand_bplustojpsik_lite::NSigTofKaBachelor, hf_cand_bplustojpsik_lite::NSigTpcTofKaBachelor, // MC truth - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bplustojpsik_lite::FlagWrongCollision, hf_cand_bplustojpsik_lite::PtGen); // DECLARE_SOA_TABLE(HfRedBpMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check -// hf_cand_2prong::FlagMcMatchRec, +// hf_cand_mc_flag::FlagMcMatchRec, // hf_cand_bplustojpsik_lite::FlagWrongCollision, // hf_cand_bplustojpsik_lite::MJpsi, // hf_cand_bplustojpsik_lite::PtJpsi, diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx index b6beb8844ee..46b4dacec14 100644 --- a/PWGHF/D2H/Tasks/taskBs.cxx +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -64,7 +64,7 @@ struct HfTaskBs { // MC checks Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "Flag to enable DecayType histogram"}; - Service pdg; + Service pdg{}; using TracksWithSel = soa::Join; diff --git a/PWGHF/D2H/Tasks/taskBsReduced.cxx b/PWGHF/D2H/Tasks/taskBsReduced.cxx index 93b4485228a..703a527ffac 100644 --- a/PWGHF/D2H/Tasks/taskBsReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsReduced.cxx @@ -155,13 +155,13 @@ DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with som hf_cand_bs_lite::NSigTofPiProng1, hf_cand_bs_lite::NSigTpcTofPiProng1, // MC truth - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bs_lite::FlagWrongCollision, hf_cand_bs_lite::PtGen); DECLARE_SOA_TABLE(HfRedBsMcCheck, "AOD", "HFREDBSMCCHECK", //! Table with MC decay type check - hf_cand_3prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_bs_lite::FlagWrongCollision, hf_cand_bs_lite::MProng0, hf_cand_bs_lite::PtProng0, diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx index 2ff8dbe84e2..ab44c6f7dbe 100644 --- a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -189,14 +189,14 @@ DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with som hf_cand_bstojpsiphi_lite::NSigTofKaBachelor1, hf_cand_bstojpsiphi_lite::NSigTpcTofKaBachelor1, // MC truth - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec, - hf_cand_bs::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_bstojpsiphi_lite::FlagWrongCollision, hf_cand_bstojpsiphi_lite::PtGen); // DECLARE_SOA_TABLE(HfRedBsMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check -// hf_cand_2prong::FlagMcMatchRec, +// hf_cand_mc_flag::FlagMcMatchRec, // hf_cand_bstojpsiphi_lite::FlagWrongCollision, // hf_cand_bstojpsiphi_lite::MJpsi, // hf_cand_bstojpsiphi_lite::PtJpsi, diff --git a/PWGHF/D2H/Tasks/taskCd.cxx b/PWGHF/D2H/Tasks/taskCd.cxx index 266d2612552..fbe561566fd 100644 --- a/PWGHF/D2H/Tasks/taskCd.cxx +++ b/PWGHF/D2H/Tasks/taskCd.cxx @@ -23,9 +23,13 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include #include +#include #include #include #include @@ -41,6 +45,7 @@ #include #include +#include #include #include #include // std::vector @@ -70,6 +75,7 @@ DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Decay length in transverse plane (cm) DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine of pointing angle (3D) DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine of pointing angle in XY plane +DECLARE_SOA_COLUMN(Chi2PCA, chi2PCA, float); //! chi2PCA DECLARE_SOA_COLUMN(NSigmaTpcDe, nSigmaTpcDe, float); //! TPC nσ for deuteron hypothesis DECLARE_SOA_COLUMN(NSigmaTpcKa, nSigmaTpcKa, float); //! TPC nσ for kaon hypothesis DECLARE_SOA_COLUMN(NSigmaTpcPi, nSigmaTpcPi, float); //! TPC nσ for pion hypothesis @@ -80,7 +86,9 @@ DECLARE_SOA_COLUMN(NSigmaTofPi, nSigmaTofPi, float); //! TOF nσ for DECLARE_SOA_COLUMN(NItsClusters, nItsClusters, int8_t); //! Number of ITS clusters used in the track fit DECLARE_SOA_COLUMN(NItsNClusterSize, nItsNClusterSize, int8_t); //! Number of ITS clusters size used in the track fit DECLARE_SOA_COLUMN(NTpcClusters, nTpcClusters, int8_t); //! Number of TPC clusters used in the track fit -DECLARE_SOA_COLUMN(NTpcSignalsDe, nTpcSignalsDe, int8_t); //! Number of TPC signas +DECLARE_SOA_COLUMN(NTpcSignalsDe, nTpcSignalsDe, int8_t); //! Number of TPC signas for deuteron +DECLARE_SOA_COLUMN(NTpcSignalsPi, nTpcSignalsPi, int8_t); //! Number of TPC signas for pion +DECLARE_SOA_COLUMN(NTpcSignalsKa, nTpcSignalsKa, int8_t); //! Number of TPC signas for kaon DECLARE_SOA_COLUMN(NItsSignalsDe, nItsSignalsDe, int8_t); //! Number of ITS signas DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); //! Candidates falg DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality @@ -100,6 +108,7 @@ DECLARE_SOA_TABLE(HfCandCd, "AOD", "HFCANDCD", full::ImpactParameter2, full::DecayLength, full::Cpa, + full::Chi2PCA, full::NSigmaTpcDe, full::NSigmaItsDe, full::NSigmaTofDe, @@ -107,6 +116,8 @@ DECLARE_SOA_TABLE(HfCandCd, "AOD", "HFCANDCD", full::NItsNClusterSize, full::NTpcClusters, full::NTpcSignalsDe, + full::NTpcSignalsPi, + full::NTpcSignalsKa, full::NItsSignalsDe, full::CandidateSelFlag, full::Cent, @@ -131,7 +142,7 @@ struct HfTaskCd { using CdCandidates = soa::Filtered>; using HFTracks = soa::Join; - Filter filterSelectCandidates = aod::hf_sel_candidate_cd::isSelCdToDeKPi >= selectionFlagCd; + Filter filterSelectCandidates = aod::hf_sel_candidate_cd::isSelCdToDeKPi >= selectionFlagCd || aod::hf_sel_candidate_cd::isSelCdToPiKDe >= selectionFlagCd; Preslice candCdPerCollision = aod::hf_cand::collisionId; ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {72, 0, 36}, ""}; @@ -208,8 +219,10 @@ struct HfTaskCd { registry.add("Data/hNsigmaTPCDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{TPC}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaTOFDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{TOF}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaITSDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{ITS}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); - registry.add("Data/hTPCSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{ITS}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {2000, 0, 2000}}}); - registry.add("Data/hITSSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); n#sigma^{ITS}_{d}", {HistType::kTH2F, {{200, -10.f, 10.f}, {20, 0, 20}}}); + registry.add("Data/hTPCSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); TPC signals", {HistType::kTH2F, {{200, -10.f, 10.f}, {2000, 0, 2000}}}); + registry.add("Data/hTPCSignalPiVsP", "Pion;#it{p} (GeV/#it{c}); TPC signals", {HistType::kTH2F, {{200, -10.f, 10.f}, {2000, 0, 2000}}}); + registry.add("Data/hTPCSignalKaVsP", "Kaon;#it{p} (GeV/#it{c}); TPC signals", {HistType::kTH2F, {{200, -10.f, 10.f}, {2000, 0, 2000}}}); + registry.add("Data/hITSSignalDeVsP", "deuteron;#it{p} (GeV/#it{c}); ITS signals", {HistType::kTH2F, {{200, -10.f, 10.f}, {20, 0, 20}}}); registry.add("Data/hNsigmaTPCPiVsP", "Pion;#it{p} (GeV/#it{c});n#sigma^{TPC}_{pi};", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaTOFPiVsP", "Pion;#it{p} (GeV/#it{c});n#sigma^{TOF}_{pi};", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); registry.add("Data/hNsigmaTPCKaVsP", "Kaon;#it{p} (GeV/#it{c}); n#sigma^{TPC}_{Kaon}", {HistType::kTH2F, {{200, -10.f, 10.f}, {200, -6.f, 6.f}}}); @@ -348,6 +361,9 @@ struct HfTaskCd { int tpcNClusterDe = 0; float tpcSignalsDe = 0.f; + float tpcSignalsPi = 0.f; + float tpcSignalsKa = 0.f; + float itsSignalsDe = 0.f; float pSignedDe = -999.f; @@ -366,6 +382,8 @@ struct HfTaskCd { auto prong0Its = tracksWithItsPid.iteratorAt(candidate.prong0Id() - tracksWithItsPid.offset()); auto prong2Its = tracksWithItsPid.iteratorAt(candidate.prong2Id() - tracksWithItsPid.offset()); + tpcSignalsKa = prong1.tpcSignal(); + if (selDeKPi) { candFlag = 1; pSignedDe = prong0.p() * prong0.sign(); @@ -379,6 +397,7 @@ struct HfTaskCd { itsNClusterSizeDe = prong0.itsClusterSizes(); tpcNClusterDe = prong0.tpcNClsCrossedRows(); tpcSignalsDe = prong0.tpcSignal(); + tpcSignalsPi = prong2.tpcSignal(); itsSignalsDe = itsSignal(prong0); } else if (selPiKDe) { candFlag = -1; @@ -393,6 +412,7 @@ struct HfTaskCd { itsNClusterSizeDe = prong2.itsClusterSizes(); tpcNClusterDe = prong2.tpcNClsCrossedRows(); tpcSignalsDe = prong2.tpcSignal(); + tpcSignalsPi = prong0.tpcSignal(); itsSignalsDe = itsSignal(prong2); } @@ -401,6 +421,8 @@ struct HfTaskCd { registry.fill(HIST("Data/hNsigmaTOFDeVsP"), pSignedDe, nSigmaTofDe); registry.fill(HIST("Data/hNsigmaITSDeVsP"), pSignedDe, nSigmaItsDe); registry.fill(HIST("Data/hTPCSignalDeVsP"), pSignedDe, tpcSignalsDe); + registry.fill(HIST("Data/hTPCSignalPiVsP"), pSignedPi, tpcSignalsPi); + registry.fill(HIST("Data/hTPCSignalKaVsP"), prong1.p() * prong1.sign(), tpcSignalsKa); registry.fill(HIST("Data/hITSSignalDeVsP"), pSignedDe, itsSignalsDe); registry.fill(HIST("Data/hNsigmaTPCPiVsP"), pSignedPi, nSigmaTpcPi); registry.fill(HIST("Data/hNsigmaTOFPiVsP"), pSignedPi, nSigmaTofPi); @@ -418,6 +440,7 @@ struct HfTaskCd { candidate.impactParameter2(), decayLength, cpa, + chi2PCA, nSigmaTpcDe, nSigmaItsDe, nSigmaTofDe, @@ -425,6 +448,8 @@ struct HfTaskCd { itsNClusterSizeDe, tpcNClusterDe, tpcSignalsDe, + tpcSignalsPi, + tpcSignalsKa, itsSignalsDe, candFlag, cent, diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index b26c8cfc8c2..dcc88fbb5d9 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -65,6 +65,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; using namespace o2::hf_centrality; using namespace o2::hf_evsel; using namespace o2::analysis::hf_flow_utils; @@ -144,11 +145,6 @@ DECLARE_SOA_TABLE(HfLcPolBkg, "AOD", "HFLCPOLBKG", struct HfTaskCharmPolarisation { Produces rowCandLcBkg; - float massPi{0.f}; - float massProton{0.f}; - float massKaon{0.f}; - float massDstar{0.f}; - float massLc{0.f}; float bkgRotationAngleStep{0.f}; uint8_t nMassHypos{0u}; @@ -222,7 +218,7 @@ struct HfTaskCharmPolarisation { SliceCache cache; EventPlaneHelper epHelper; // event plane helper HfEventSelection hfEvSel; // event selection and monitoring - o2::framework::Service ccdb; + o2::framework::Service ccdb{}; using CollisionsWithMcLabels = soa::SmallGroups>; using CollisionsWithMcLabelsAndCent = soa::SmallGroups>; @@ -328,11 +324,6 @@ struct HfTaskCharmPolarisation { LOGP(fatal, "No background rotation supported for MC."); } - massPi = o2::constants::physics::MassPiPlus; - massProton = o2::constants::physics::MassProton; - massKaon = o2::constants::physics::MassKaonCharged; - massDstar = o2::constants::physics::MassDStar; - massLc = o2::constants::physics::MassLambdaCPlus; bkgRotationAngleStep = (nBkgRotations > 1) ? (maxRotAngleMultByPi - minRotAngleMultByPi) * constants::math::PI / (nBkgRotations - 1) : 0.; const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; @@ -611,6 +602,10 @@ struct HfTaskCharmPolarisation { hRecoPromptRandomAxes.insert(hRecoPromptRandomAxes.end(), {thnAxisDauToMuons}); std::vector hRecoNonPromptRandomAxes(hRandomaxes); hRecoNonPromptRandomAxes.insert(hRecoNonPromptRandomAxes.end(), {thnAxisDauToMuons, thnAxisPtB}); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + hRecoPromptRandomAxes.push_back(thnAxisCentrality); + hRecoNonPromptRandomAxes.push_back(thnAxisCentrality); + } registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptRandomAxes); registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptRandomAxes); if (activatePartRecoDstar) { @@ -642,8 +637,12 @@ struct HfTaskCharmPolarisation { registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, hRandomaxes); } if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { - std::vector const hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; - std::vector const hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + hgenPromptAxes.push_back(thnAxisCentrality); + hgenNonPromptAxes.push_back(thnAxisCentrality); + } registry.add("hGenPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); registry.add("hGenNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); if (activatePartRecoDstar) { @@ -668,6 +667,7 @@ struct HfTaskCharmPolarisation { if (nBkgRotations > 0) { hEPaxes.push_back(thnAxisIsRotatedCandidate); } + hEPaxes.push_back(thnAxisCentrality); registry.add("hEP", "THn for polarisation studies with cosThStar w.r.t. event plane axis and BDT scores", HistType::kTHnSparseF, hEPaxes); } } @@ -747,7 +747,7 @@ struct HfTaskCharmPolarisation { /// \param nMuons is the number of muons from daughter decays /// \param isPartRecoDstar is a flag indicating if it is a partly reconstructed Dstar meson (MC only) template - 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, int8_t nMuons, bool isPartRecoDstar) + 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, int8_t nMuons, bool isPartRecoDstar, float centrality = -999.f) { if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if constexpr (!DoMc) { // data @@ -800,19 +800,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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); } @@ -821,19 +821,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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); } @@ -844,19 +844,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -865,19 +865,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiHelicity"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -936,19 +936,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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); } @@ -957,19 +957,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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); } @@ -980,19 +980,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1001,19 +1001,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiProduction"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1072,19 +1072,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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); } @@ -1093,19 +1093,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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); } @@ -1116,19 +1116,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1137,19 +1137,19 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, nMuons, ptBhadMother); } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); if (activateTHnEulerPhiMonitor) { registry.fill(HIST("hRecNonPromptEulerPhiBeam"), invMassCharmHad, ptCharmHad, invMassKPiLc, phiEuler, resoChannelLc, charge); } @@ -1202,59 +1202,107 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, centrality); + } else { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, centrality); + } else { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + } } } } 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, 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, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(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*+ if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, centrality); + } else { + registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } else { // non-prompt if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother, centrality); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, resoChannelLc, absEtaMin, numItsClsMin, numTpcClsMin, charge); } } } @@ -1265,15 +1313,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, centrality); } } else { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], centrality); } } } @@ -1281,15 +1329,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, centrality); } } else { if (nBkgRotations > 0) { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate, centrality); } else { - registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, centrality); } } } @@ -1300,15 +1348,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } else { - registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } else { - registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); } } } @@ -1316,15 +1364,15 @@ struct HfTaskCharmPolarisation { if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ if (activateTrackingSys) { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); } } else { if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } else { - registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); } } } @@ -1344,76 +1392,78 @@ struct HfTaskCharmPolarisation { /// \param resoChannelLc indicates the Lc decay channel (direct, resonant) /// \param isPartRecoDstar is a flag indicating if it is a partly reconstructed Dstar->D0pi->Kpipipi0 meson (MC only) template - void fillGenHistos(float ptCharmHad, int numPvContributors, float rapCharmHad, float cosThetaStar, int8_t origin, float ptBhadMother, bool areDausInAcc, uint8_t resoChannelLc, int8_t charge, bool isPartRecoDstar) + void fillGenHistos(float ptCharmHad, int numPvContributors, float rapCharmHad, float cosThetaStar, int8_t origin, float ptBhadMother, bool areDausInAcc, uint8_t resoChannelLc, int8_t charge, bool isPartRecoDstar, float centrality = -999.f) { if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptHelicity"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptHelicity"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Production) { // Production if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptProduction"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptProduction"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Beam) { // Beam if (origin == RecoDecay::OriginType::Prompt) { // prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenNonPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } else { - registry.fill(HIST("hGenPartRecoNonPromptBeam"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + registry.fill(HIST("hGenPartRecoNonPromptBeam"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); } } } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::Random) { // Random - if (origin == RecoDecay::OriginType::Prompt) { // prompt - if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); - } else { - registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); - } - } else { // non-prompt + if (origin == RecoDecay::OriginType::Prompt) { if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); - } else { - registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); - } - } - } else if constexpr (CosThetaStarType == charm_polarisation::CosThetaStarType::EP) { // EP - if (origin == RecoDecay::OriginType::Prompt) { // prompt - if (!isPartRecoDstar) { - registry.fill(HIST("hGenPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); + } } else { - registry.fill(HIST("hGenPartRecoPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenPartRecoPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, areDausInAcc, resoChannelLc, charge); + } } } else { // non-prompt if (!isPartRecoDstar) { - registry.fill(HIST("hGenNonPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + } } else { - registry.fill(HIST("hGenPartRecoNonPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge, centrality); + } else { + registry.fill(HIST("hGenPartRecoNonPromptRandom"), ptCharmHad, numPvContributors, std::abs(rapCharmHad), cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + } } } } @@ -1438,8 +1488,8 @@ struct HfTaskCharmPolarisation { template bool isInSignalRegion(float invMass) { - float invMassMin; - float invMassMax; + float invMassMin{0.f}; + float invMassMax{0.f}; if constexpr (Channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ invMassMin = 0.142f; invMassMax = 0.15f; @@ -1527,10 +1577,11 @@ struct HfTaskCharmPolarisation { /// \param tracks are the reconstructed tracks /// \return true if candidate in signal region template - bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/, QVecs const* qVecs = nullptr) + bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/, float centrality = -999.f, QVecs const* qVecs = nullptr) { if constexpr (WithEp) { assert(qVecs && "EP analysis requested but qVecs == nullptr"); + assert(centrality && "EP analysis requested but centrality == nullptr"); } constexpr std::size_t NScores{3u}; @@ -1600,7 +1651,7 @@ struct HfTaskCharmPolarisation { // Dstar analysis // polarization measured from the soft-pion daughter (*) - massDau = massPi; // (*) + massDau = MassPiPlus; // (*) const float bkgRotAngle = (bkgRotationId > 0) ? minRotAngleMultByPi * constants::math::PI + bkgRotationAngleStep * (bkgRotationId - 1) : 0; std::array threeVecSoftPi{candidate.pxSoftPi() * std::cos(bkgRotAngle) - candidate.pySoftPi() * std::sin(bkgRotAngle), candidate.pxSoftPi() * std::sin(bkgRotAngle) + candidate.pySoftPi() * std::cos(bkgRotAngle), candidate.pzSoftPi()}; // we rotate the soft pion @@ -1615,13 +1666,13 @@ struct HfTaskCharmPolarisation { pyCharmHad = threeVecSoftPi[1] + threeVecD0Prong0[1] + threeVecD0Prong1[1]; pzCharmHad = threeVecSoftPi[2] + threeVecD0Prong0[2] + threeVecD0Prong1[2]; if (candidate.signSoftPi() > 0) { - invMassCharmHad = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1, threeVecSoftPi}, std::array{massPi, massKaon, massPi}); - invMassD0 = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1}, std::array{massPi, massKaon}); + invMassCharmHad = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1, threeVecSoftPi}, std::array{MassPiPlus, MassKaonCharged, MassPiPlus}); + invMassD0 = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1}, std::array{MassPiPlus, MassKaonCharged}); } else { - invMassCharmHad = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1, threeVecSoftPi}, std::array{massKaon, massPi, massPi}); - invMassD0 = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1}, std::array{massKaon, massPi}); + invMassCharmHad = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1, threeVecSoftPi}, std::array{MassKaonCharged, MassPiPlus, MassPiPlus}); + invMassD0 = RecoDecay::m(std::array{threeVecD0Prong0, threeVecD0Prong1}, std::array{MassKaonCharged, MassPiPlus}); } - rapidity = RecoDecay::y(std::array{pxCharmHad, pyCharmHad, pzCharmHad}, massDstar); + rapidity = RecoDecay::y(std::array{pxCharmHad, pyCharmHad, pzCharmHad}, MassDStar); } else { isRotatedCandidate = 0; pxDau = candidate.pxSoftPi(); @@ -1637,7 +1688,7 @@ struct HfTaskCharmPolarisation { invMassCharmHad = candidate.invMassAntiDstar(); invMassD0 = candidate.invMassD0Bar(); } - rapidity = candidate.y(massDstar); + rapidity = candidate.y(MassDStar); } invMassCharmHadForSparse = invMassCharmHad - invMassD0; @@ -1677,8 +1728,8 @@ struct HfTaskCharmPolarisation { pyCharmHad = candidate.py(); pzCharmHad = candidate.pz(); } - massDau = massProton; // (*) - rapidity = RecoDecay::y(candidate.pVector(), massLc); + massDau = MassProton; // (*) + rapidity = RecoDecay::y(candidate.pVector(), MassLambdaCPlus); /// mass-hypothesis-dependent variables float invMassPiKPi = 0.f; // bkg. from D+ -> K+pi-pi- @@ -1691,7 +1742,7 @@ struct HfTaskCharmPolarisation { pzDau = candidate.pzProng0(); if (bkgRotationId) { /// rotational background - pt of the kaon track rotated - invMassCharmHad = RecoDecay::m(std::array{threeVecLcProng0, threeVecLcRotatedProng1, threeVecLcProng2}, std::array{massProton, massKaon, massPi}); + invMassCharmHad = RecoDecay::m(std::array{threeVecLcProng0, threeVecLcRotatedProng1, threeVecLcProng2}, std::array{MassProton, MassKaonCharged, MassPiPlus}); invMassCharmHadForSparse = invMassCharmHad; } else { /// original candidate (kaon track not rotated) @@ -1725,7 +1776,7 @@ struct HfTaskCharmPolarisation { pzDau = candidate.pzProng2(); if (bkgRotationId) { /// rotational background - pt of the kaon track rotated - invMassCharmHad = RecoDecay::m(std::array{threeVecLcProng0, threeVecLcRotatedProng1, threeVecLcProng2}, std::array{massPi, massKaon, massProton}); + invMassCharmHad = RecoDecay::m(std::array{threeVecLcProng0, threeVecLcRotatedProng1, threeVecLcProng2}, std::array{MassPiPlus, MassKaonCharged, MassProton}); invMassCharmHadForSparse = invMassCharmHad; } else { /// original candidate (kaon track not rotated) @@ -1854,7 +1905,7 @@ struct HfTaskCharmPolarisation { if (activateTHnSparseCosThStarEP) { // EP float cosThetaStarEP = qVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(qVecNorm.Mag2()); - fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarEP, phiEP, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar); + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarEP, phiEP, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar, centrality); } } @@ -1880,7 +1931,11 @@ struct HfTaskCharmPolarisation { // random ROOT::Math::XYZVector const randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); 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, nMuons, partRecoDstar); + if (doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, -99.f, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar, centrality); + } else { + fillRecoHistos(invMassCharmHadForSparse, ptCharmHad, numPvContributors, rapidity, invMassD0, invMassKPiLc, cosThetaStarRandom, -99.f, outputMl, isRotatedCandidate, origin, ptBhadMother, resoChannelLc, absEtaTrackMin, numItsClsMin, numTpcClsMin, charge, nMuons, partRecoDstar); + } } /// Table for Lc->pKpi background studies @@ -2107,8 +2162,8 @@ struct HfTaskCharmPolarisation { std::array const dauPdgs = {kPiPlus, o2::constants::physics::Pdg::kD0}; RecoDecay::getDaughters(mcParticle, &listDaughters, dauPdgs, 1); - massDau = massPi; - massCharmHad = massDstar; + massDau = MassPiPlus; + massCharmHad = MassDStar; } else if constexpr (Channel == charm_polarisation::DecayChannel::LcToPKPi) { if (std::abs(mcParticle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { // this particle is not signal, skip return; @@ -2117,8 +2172,8 @@ struct HfTaskCharmPolarisation { resoChannelLc = mcParticle.flagMcDecayChanGen(); std::array const dauPdgs = {kProton, -kKPlus, kPiPlus}; RecoDecay::getDaughters(mcParticle, &listDaughters, dauPdgs, 2); - massDau = massProton; - massCharmHad = massLc; + massDau = MassProton; + massCharmHad = MassLambdaCPlus; /// electric charge from PDG code int const pdgCode = mcParticle.pdgCode(); @@ -2193,7 +2248,11 @@ struct HfTaskCharmPolarisation { if (activateTHnSparseCosThStarRandom) { ROOT::Math::XYZVector const randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); float const cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge, partRecoDstar); + if constexpr (WithCent) { + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge, partRecoDstar, *centrality); + } else { + fillGenHistos(ptCharmHad, numPvContributors, rapidity, cosThetaStarRandom, origin, ptBhadMother, areDauInAcc, resoChannelLc, charge, partRecoDstar); + } } } @@ -2339,7 +2398,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, &qVecs)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality, &qVecs)) { nCandsInSignalRegion++; } } @@ -2368,7 +2427,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, &qVecs)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality, &qVecs)) { nCandsInSignalRegion++; } } @@ -2403,7 +2462,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality)) { nCandsInSignalRegion++; } } @@ -2443,7 +2502,7 @@ struct HfTaskCharmPolarisation { for (const auto& dstarCandidate : groupedDstarCandidates) { nCands++; - if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, centrality)) { nCandsInSignalRegion++; } } diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index cc1cc58e992..16dbff833e4 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -94,6 +94,8 @@ struct HfTaskD0 { Configurable storeCentrality{"storeCentrality", false, "Flag to store centrality information"}; Configurable storeOccupancyAndIR{"storeOccupancyAndIR", false, "Flag to store occupancy information and interaction rate"}; Configurable storeTrackQuality{"storeTrackQuality", false, "Flag to store track quality information"}; + Configurable storeZdcEnergy{"storeZdcEnergy", false, "Flag to store ZDC energy info"}; + Configurable storeZdcTime{"storeZdcTime", false, "Flag to store ZDC time info"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -104,7 +106,7 @@ struct HfTaskD0 { ctpRateFetcher mRateFetcher; SliceCache cache; - Service ccdb; + Service ccdb{}; using D0Candidates = soa::Filtered>; using D0CandidatesMc = soa::Filtered>; @@ -121,6 +123,7 @@ struct HfTaskD0 { using CollisionsWithMcLabels = soa::Join; using CollisionsWithMcLabelsCent = soa::Join; using TracksSelQuality = soa::Join; + using TracksWPid = soa::Join; Filter filterD0Flag = (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK))) != static_cast(0); @@ -161,6 +164,7 @@ struct HfTaskD0 { ConfigurableAxis thnConfigAxisFV0A{"thnConfigAxisFV0A", {2001, -1.5, 1999.5}, "axis for FV0-A amplitude (a.u.)"}; ConfigurableAxis thnConfigAxisFDD{"thnConfigAxisFDD", {200, 0., 4000.}, "axis for FDD amplitude (a.u.)"}; ConfigurableAxis thnConfigAxisZN{"thnConfigAxisZN", {510, -1.5, 49.5}, "axis for ZN energy (a.u.)"}; + ConfigurableAxis thnConfigAxisTimeZN{"thnConfigAxisTimeZN", {700, -35., 35.}, "axis for ZN energy (a.u.)"}; HistogramRegistry registry{ "registry", @@ -248,7 +252,10 @@ struct HfTaskD0 { LOGP(fatal, "DCAFitterN and KFParticle can not be enabled at a time."); } if ((storeCentrality || storeOccupancyAndIR) && !(doprocessDataWithDCAFitterNCent || doprocessMcWithDCAFitterNCent || doprocessDataWithDCAFitterNMlCent || doprocessMcWithDCAFitterNMlCent || doprocessDataWithDCAFitterNWithUpc || doprocessDataWithDCAFitterNMlWithUpc)) { - LOGP(fatal, "Can't enable the storeCentrality and storeOccupancu without cent process or UPC process"); + LOGP(fatal, "Can't enable the storeCentrality and storeOccupancy without cent process or UPC process"); + } + if ((storeZdcEnergy || storeZdcTime) && !(doprocessDataWithDCAFitterNWithUpc || doprocessDataWithDCAFitterNMlWithUpc)) { + LOGP(fatal, "Can't enable the storeZdcEnergy and storeZdcTime without UPC process"); } auto vbins = (std::vector)binsPt; registry.add("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})"}}}); @@ -309,8 +316,10 @@ struct HfTaskD0 { const AxisSpec thnAxisFV0A{thnConfigAxisFV0A, "FV0-A amplitude"}; const AxisSpec thnAxisFDDA{thnConfigAxisFDD, "FDD-A amplitude"}; const AxisSpec thnAxisFDDC{thnConfigAxisFDD, "FDD-C amplitude"}; - const AxisSpec thnAxisZNA{thnConfigAxisZN, "ZNA energy"}; - const AxisSpec thnAxisZNC{thnConfigAxisZN, "ZNC energy"}; + const AxisSpec thnAxisEnergyZNA{thnConfigAxisZN, "ZNA energy"}; + const AxisSpec thnAxisEnergyZNC{thnConfigAxisZN, "ZNC energy"}; + const AxisSpec thnAxisTimeZNA{thnConfigAxisTimeZN, "ZNA Time"}; + const AxisSpec thnAxisTimeZNC{thnConfigAxisTimeZN, "ZNC Time"}; if (doprocessMcWithDCAFitterN || doprocessMcWithDCAFitterNCent || doprocessMcWithKFParticle || doprocessMcWithDCAFitterNMl || doprocessMcWithDCAFitterNMlCent || doprocessMcWithKFParticleMl) { std::vector axesAcc = {thnAxisGenPtD, thnAxisGenPtB, thnAxisY, thnAxisOrigin, thnAxisNumPvContr}; @@ -367,8 +376,15 @@ struct HfTaskD0 { axes.push_back(thnAxisFV0A); axes.push_back(thnAxisFDDA); axes.push_back(thnAxisFDDC); - axes.push_back(thnAxisZNA); - axes.push_back(thnAxisZNC); + axes.push_back(thnAxisNumPvContr); + if (storeZdcEnergy) { + axes.push_back(thnAxisEnergyZNA); + axes.push_back(thnAxisEnergyZNC); + } + if (storeZdcTime) { + axes.push_back(thnAxisTimeZNA); + axes.push_back(thnAxisTimeZNC); + } } if (applyMl) { @@ -380,8 +396,40 @@ struct HfTaskD0 { } registry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{2500, 0., 250}, {2500, 0., 250}}}); - registry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{200, 0., 20}, {200, 0., 20}}}); + registry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{200, 0., 200}, {1000, 0., 2000}}}); + registry.add("Data/zdc/timeZNA_vs_timeZNC", "ZNA vs ZNC time;ZNA Time;ZNC time", {HistType::kTH2F, {{700, -35., 35.}, {700, -35., 35.}}}); registry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap type;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); + registry.add("Data/hGapVsEtaTrack0", "UPC gap vs Eta;Gap type;Eta", {HistType::kTH2F, {{7, -1.5, 5.5}, {50, -1., 1.}}}); + registry.add("Data/hGapVsEtaTrack1", "UPC gap vs Eta;Gap type;Eta", {HistType::kTH2F, {{7, -1.5, 5.5}, {50, -1., 1.}}}); + + registry.add("Data/hTPCnSigProng0Pion_GapA", "Gap A Prong 0;P (GeV/c) ;TPC nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng1Kaon_GapA", "Gap A Prong 1;P (GeV/c) ;TPC nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng0Kaon_GapA", "Gap A Prong 0;P (GeV/c) ;TPC nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng1Pion_GapA", "Gap A Prong 1;P (GeV/c) ;TPC nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng0Pion_GapC", "Gap C Prong 0;P (GeV/c) ;TPC nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng1Kaon_GapC", "Gap C Prong 1;P (GeV/c) ;TPC nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng0Kaon_GapC", "Gap C Prong 0;P (GeV/c) ;TPC nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTPCnSigProng1Pion_GapC", "Gap C Prong 1;P (GeV/c) ;TPC nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + + registry.add("Data/hTOFnSigProng0Pion_GapA", "Gap A Prong 0;P (GeV/c) ;TOF nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng1Kaon_GapA", "Gap A Prong 1;P (GeV/c) ;TOF nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng0Kaon_GapA", "Gap A Prong 0;P (GeV/c) ;TOF nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng1Pion_GapA", "Gap A Prong 1;P (GeV/c) ;TOF nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng0Pion_GapC", "Gap C Prong 0;P (GeV/c) ;TOF nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng1Kaon_GapC", "Gap C Prong 1;P (GeV/c) ;TOF nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng0Kaon_GapC", "Gap C Prong 0;P (GeV/c) ;TOF nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + registry.add("Data/hTOFnSigProng1Pion_GapC", "Gap C Prong 1;P (GeV/c) ;TOF nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {120, -6., 6.}}}); + + registry.add("Data/hTpcTofnSigProng0Pion_GapA", "Gap A Prong 0;P (GeV/c) ;TpcTof nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng1Kaon_GapA", "Gap A Prong 1;P (GeV/c) ;TpcTof nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng0Kaon_GapA", "Gap A Prong 0;P (GeV/c) ;TpcTof nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng1Pion_GapA", "Gap A Prong 1;P (GeV/c) ;TpcTof nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng0Pion_GapC", "Gap C Prong 0;P (GeV/c) ;TpcTof nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng1Kaon_GapC", "Gap C Prong 1;P (GeV/c) ;TpcTof nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng0Kaon_GapC", "Gap C Prong 0;P (GeV/c) ;TpcTof nSigma Pion", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + registry.add("Data/hTpcTofnSigProng1Pion_GapC", "Gap C Prong 1;P (GeV/c) ;TpcTof nSigma Kaon", {HistType::kTH2F, {{100, 0, 50}, {50, 0., 10.}}}); + + registry.add("Data/hGapVsRap", "UPC gap vs Eta;Gap type;Eta", {HistType::kTH2F, {{7, -1.5, 5.5}, {50, -1., 1.}}}); hfEvSel.addHistograms(registry); @@ -404,7 +452,7 @@ struct HfTaskD0 { continue; } - float massD0, massD0bar; + float massD0{0.f}, massD0bar{0.f}; if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { massD0 = candidate.kfGeoMassD0(); massD0bar = candidate.kfGeoMassD0bar(); @@ -576,7 +624,8 @@ struct HfTaskD0 { BCsType const& bcs, aod::FT0s const& ft0s, aod::FV0As const& fv0as, - aod::FDDs const& fdds) + aod::FDDs const& fdds, + TracksWPid const&) { for (const auto& collision : collisions) { float centrality{-1.f}; @@ -589,13 +638,13 @@ struct HfTaskD0 { // Determine gap type using SGSelector with BC range checking const auto gapResult = hf_upc::determineGapType(collision, bcs, upcThresholds); const int gap = gapResult.value; + const auto numPvContributors = collision.numContrib(); // Use the BC with FIT activity if available from SGSelector auto bcForUPC = bc; if (gapResult.bc) { bcForUPC = *(gapResult.bc); } - // Get FIT information from the UPC BC upchelpers::FITInfo fitInfo{}; udhelpers::getFITinfo(fitInfo, bcForUPC, bcs, ft0s, fv0as, fdds); @@ -604,13 +653,18 @@ struct HfTaskD0 { const bool hasZdc = bcForUPC.has_zdc(); float zdcEnergyZNA = -1.f; float zdcEnergyZNC = -1.f; + float zdcTimeZNA = -999.f; + float zdcTimeZNC = -999.f; + if (hasZdc) { const auto& zdc = bcForUPC.zdc(); zdcEnergyZNA = zdc.energyCommonZNA(); zdcEnergyZNC = zdc.energyCommonZNC(); + zdcTimeZNA = zdc.timeZNA(); + zdcTimeZNC = zdc.timeZNC(); registry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); + registry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); } - registry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); registry.fill(HIST("Data/hUpcGapAfterSelection"), gap); @@ -634,6 +688,49 @@ struct HfTaskD0 { const float massD0bar = HfHelper::invMassD0barToKPi(candidate); const auto ptCandidate = candidate.pt(); + auto track0 = candidate.template prong0_as(); + auto track1 = candidate.template prong1_as(); + + registry.fill(HIST("Data/hGapVsEtaTrack0"), gap, track0.eta()); + registry.fill(HIST("Data/hGapVsEtaTrack1"), gap, track1.eta()); + registry.fill(HIST("Data/hGapVsRap"), gap, HfHelper::yD0(candidate)); + + if (gap == 0 && candidate.isSelD0() >= selectionFlagD0) { // A side // D0 --> K-Pi+ + registry.fill(HIST("Data/hTPCnSigProng0Pion_GapA"), track0.p(), track0.tpcNSigmaPi()); + registry.fill(HIST("Data/hTPCnSigProng1Kaon_GapA"), track1.p(), track1.tpcNSigmaKa()); + registry.fill(HIST("Data/hTOFnSigProng0Pion_GapA"), track0.p(), track0.tofNSigmaPi()); + registry.fill(HIST("Data/hTOFnSigProng1Kaon_GapA"), track1.p(), track1.tofNSigmaKa()); + registry.fill(HIST("Data/hTpcTofnSigProng0Pion_GapA"), track0.p(), track0.tpcTofNSigmaPi()); + registry.fill(HIST("Data/hTpcTofnSigProng1Kaon_GapA"), track1.p(), track1.tpcTofNSigmaKa()); + } + + if (gap == 0 && candidate.isSelD0bar() >= selectionFlagD0) { // A side // D0-bar --> K+Pi- + registry.fill(HIST("Data/hTPCnSigProng0Kaon_GapA"), track0.p(), track0.tpcNSigmaKa()); + registry.fill(HIST("Data/hTPCnSigProng1Pion_GapA"), track1.p(), track1.tpcNSigmaPi()); + registry.fill(HIST("Data/hTOFnSigProng0Kaon_GapA"), track0.p(), track0.tofNSigmaKa()); + registry.fill(HIST("Data/hTOFnSigProng1Pion_GapA"), track1.p(), track1.tofNSigmaPi()); + registry.fill(HIST("Data/hTpcTofnSigProng0Kaon_GapA"), track0.p(), track0.tpcTofNSigmaKa()); + registry.fill(HIST("Data/hTpcTofnSigProng1Pion_GapA"), track1.p(), track1.tpcTofNSigmaPi()); + } + + if (gap == 1 && candidate.isSelD0() >= selectionFlagD0) { // C side // D0 --> K-Pi+ + registry.fill(HIST("Data/hTPCnSigProng0Pion_GapC"), track0.p(), track0.tpcNSigmaPi()); + registry.fill(HIST("Data/hTPCnSigProng1Kaon_GapC"), track1.p(), track1.tpcNSigmaKa()); + registry.fill(HIST("Data/hTOFnSigProng0Pion_GapC"), track0.p(), track0.tofNSigmaPi()); + registry.fill(HIST("Data/hTOFnSigProng1Kaon_GapC"), track1.p(), track1.tofNSigmaKa()); + registry.fill(HIST("Data/hTpcTofnSigProng0Pion_GapC"), track0.p(), track0.tpcTofNSigmaPi()); + registry.fill(HIST("Data/hTpcTofnSigProng1Kaon_GapC"), track1.p(), track1.tpcTofNSigmaKa()); + } + + if (gap == 1 && candidate.isSelD0bar() >= selectionFlagD0) { // C side // D0-bar --> K+Pi- + registry.fill(HIST("Data/hTPCnSigProng0Kaon_GapC"), track0.p(), track0.tpcNSigmaKa()); + registry.fill(HIST("Data/hTPCnSigProng1Pion_GapC"), track1.p(), track1.tpcNSigmaPi()); + registry.fill(HIST("Data/hTOFnSigProng0Kaon_GapC"), track0.p(), track0.tofNSigmaKa()); + registry.fill(HIST("Data/hTOFnSigProng1Pion_GapC"), track1.p(), track1.tofNSigmaPi()); + registry.fill(HIST("Data/hTpcTofnSigProng0Kaon_GapC"), track0.p(), track0.tpcTofNSigmaKa()); + registry.fill(HIST("Data/hTpcTofnSigProng1Pion_GapC"), track1.p(), track1.tpcTofNSigmaPi()); + } + if (candidate.isSelD0() >= selectionFlagD0) { registry.fill(HIST("hMass"), massD0, ptCandidate); registry.fill(HIST("hMassFinerBinning"), massD0, ptCandidate); @@ -648,11 +745,13 @@ struct HfTaskD0 { // Fill THnSparse with structure matching histogram axes: [mass, pt, (mlScores if FillMl), rapidity, d0Type, (cent if storeCentrality), (occ, ir if storeOccupancyAndIR), gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC] auto fillTHnData = [&](float mass, int d0Type) { // Pre-calculate vector size to avoid reallocations - constexpr int NAxesBase = 12; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC + constexpr int NAxesBase = 11; // mass, pt, rapidity, d0Type, gapType, FT0A, FT0C, FV0A, FDDA, FDDC, ZNA, ZNC, nPVcontr constexpr int NAxesMl = FillMl ? 3 : 0; // 3 ML scores if FillMl int const nAxesCent = storeCentrality ? 1 : 0; // centrality if storeCentrality int const nAxesOccIR = storeOccupancyAndIR ? 2 : 0; // occupancy and IR if storeOccupancyAndIR - int const nAxesTotal = NAxesBase + NAxesMl + nAxesCent + nAxesOccIR; + int const nAxesZdcEnergy = storeZdcEnergy ? 2 : 0; // ZDC energy if storeZdcEnergy + int const nAxesZdcTime = storeZdcTime ? 2 : 0; // ZDC time if storeZdctime + int const nAxesTotal = NAxesBase + NAxesMl + nAxesCent + nAxesOccIR + nAxesZdcEnergy + nAxesZdcTime; std::vector valuesToFill; valuesToFill.reserve(nAxesTotal); @@ -661,9 +760,12 @@ struct HfTaskD0 { valuesToFill.push_back(static_cast(mass)); valuesToFill.push_back(static_cast(ptCandidate)); if constexpr (FillMl) { - valuesToFill.push_back(candidate.mlProbD0()[0]); - valuesToFill.push_back(candidate.mlProbD0()[1]); - valuesToFill.push_back(candidate.mlProbD0()[2]); + auto const& mlScores = candidate.mlProbD0(); + if (mlScores.size() == 3) { + valuesToFill.push_back(mlScores[0]); + valuesToFill.push_back(mlScores[1]); + valuesToFill.push_back(mlScores[2]); + } } valuesToFill.push_back(static_cast(HfHelper::yD0(candidate))); valuesToFill.push_back(static_cast(d0Type)); @@ -680,9 +782,15 @@ struct HfTaskD0 { valuesToFill.push_back(static_cast(fitInfo.ampFV0A)); valuesToFill.push_back(static_cast(fitInfo.ampFDDA)); valuesToFill.push_back(static_cast(fitInfo.ampFDDC)); - valuesToFill.push_back(static_cast(zdcEnergyZNA)); - valuesToFill.push_back(static_cast(zdcEnergyZNC)); - + valuesToFill.push_back(static_cast(numPvContributors)); + if (storeZdcEnergy) { + valuesToFill.push_back(static_cast(zdcEnergyZNA)); + valuesToFill.push_back(static_cast(zdcEnergyZNC)); + } + if (storeZdcTime) { + valuesToFill.push_back(static_cast(zdcTimeZNA)); + valuesToFill.push_back(static_cast(zdcTimeZNC)); + } if constexpr (FillMl) { registry.get(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsD0Type"))->Fill(valuesToFill.data()); } else { @@ -770,7 +878,7 @@ struct HfTaskD0 { auto bc = collision.template foundBC_as(); ir = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource, true) * 1.e-3; // kHz } - float massD0, massD0bar; + float massD0{0.f}, massD0bar{0.f}; if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { massD0 = candidate.kfGeoMassD0(); massD0bar = candidate.kfGeoMassD0bar(); @@ -1171,9 +1279,11 @@ struct HfTaskD0 { aod::FT0s const& ft0s, aod::FV0As const& fv0as, aod::FDDs const& fdds, - aod::Zdcs const& /*zdcs*/) + TracksWPid const& tracks, + aod::Zdcs const& /*zdcs*/ + ) { - runAnalysisPerCollisionDataWithUpc(collisions, selectedD0Candidates, bcs, ft0s, fv0as, fdds); + runAnalysisPerCollisionDataWithUpc(collisions, selectedD0Candidates, bcs, ft0s, fv0as, fdds, tracks); } PROCESS_SWITCH(HfTaskD0, processDataWithDCAFitterNWithUpc, "Process real data with DCAFitterN w/o ML with UPC", false); @@ -1184,9 +1294,10 @@ struct HfTaskD0 { aod::FT0s const& ft0s, aod::FV0As const& fv0as, aod::FDDs const& fdds, + TracksWPid const& tracks, aod::Zdcs const& /*zdcs*/) { - runAnalysisPerCollisionDataWithUpc(collisions, selectedD0CandidatesMl, bcs, ft0s, fv0as, fdds); + runAnalysisPerCollisionDataWithUpc(collisions, selectedD0CandidatesMl, bcs, ft0s, fv0as, fdds, tracks); } PROCESS_SWITCH(HfTaskD0, processDataWithDCAFitterNMlWithUpc, "Process real data with DCAFitterN and ML with UPC", false); }; diff --git a/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx index 4826a11ded2..aa3c03c7b6d 100644 --- a/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx @@ -74,7 +74,7 @@ struct HfTaskDirectedFlowCharmHadrons { EventPlaneHelper epHelper; SliceCache cache; HfEventSelection hfEvSel; // event selection and monitoring - o2::framework::Service ccdb; + o2::framework::Service ccdb{}; using CandDplusDataWMl = soa::Filtered>; using CandDplusData = soa::Filtered>; diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index 38975f2f190..fb4102b48a1 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -92,7 +92,7 @@ struct HfTaskDplus { HfUpcGapThresholds upcThresholds; // UPC gap determination thresholds ctpRateFetcher mRateFetcher; // interaction rate fetcher - Service ccdb; + Service ccdb{}; using CandDplusData = soa::Filtered>; using CandDplusDataWithMl = soa::Filtered>; @@ -114,12 +114,12 @@ struct HfTaskDplus { Partition selectedDPlusCandidatesWithMl = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; // Matched MC - Partition recoDPlusCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition recoDPlusCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoDPlusCandidates = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoDPlusCandidatesWithMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; // MC Bkg - Partition recoBkgCandidates = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoBkgCandidates = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {600, 1.67, 2.27}, "Cand. mass bins"}; ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {40, -1, 1}, "Cand. rapidity bins"}; diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index 9101672f65e..0f163718eda 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -101,6 +101,7 @@ DECLARE_SOA_COLUMN(Pt, pt, float); //! DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of D-meson candidates (GeV/c) DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Centrality of collision DECLARE_SOA_COLUMN(ImpactParameter, impactParameter, float); //! Impact parameter of D-meson candidate +DECLARE_SOA_COLUMN(ImpactParameterMc, impactParameterMc, float); //! Generated impact parameter of D-meson candidate DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of D-meson candidate DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of D-meson candidate DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of D-meson candidate @@ -108,21 +109,24 @@ DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! DECLARE_SOA_COLUMN(FlagMc, flagMc, int); //! MC flag (according to DataType enum) } // namespace hf_cand_ds_mini -DECLARE_SOA_TABLE(HfCandDsMinis, "AOD", "HFCANDDSMINI", //! Table with few Ds properties +DECLARE_SOA_TABLE(HfCandDsMinis, "AOD", "HFDSMINI", //! Table with few Ds properties hf_cand_ds_mini::M, hf_cand_ds_mini::Pt, hf_cand_ds_mini::Centrality); -DECLARE_SOA_TABLE(HfCandDsDlMinis, "AOD", "HFCANDDSDLMINI", //! Table with decay length Ds properties +DECLARE_SOA_TABLE(HfCandDsDlMinis, "AOD", "HFDSDLMINI", //! Table with decay length Ds properties hf_cand_ds_mini::DecayLength, hf_cand_ds_mini::DecayLengthXY, hf_cand_ds_mini::DecayLengthNormalised, hf_cand_ds_mini::DecayLengthXYNormalised); -DECLARE_SOA_TABLE(HfCandDsD0Minis, "AOD", "HFCANDDSD0MINI", //! Table with impact parameter (d0) +DECLARE_SOA_TABLE(HfCandDsD0Minis, "AOD", "HFDSD0MINI", //! Table with impact parameter (d0) hf_cand_ds_mini::ImpactParameter); -DECLARE_SOA_TABLE(HfCandDsMcMinis, "AOD", "HFCANDDSMCMINI", //! Table with MC decay type check +DECLARE_SOA_TABLE(HfCandDsD0McMinis, "AOD", "HFDSD0MCMINI", //! Table with generated impact parameter (d0) + hf_cand_ds_mini::ImpactParameterMc); + +DECLARE_SOA_TABLE(HfCandDsMcMinis, "AOD", "HFDSMCMINI", //! Table with MC decay type check hf_cand_ds_mini::FlagMc); } // namespace o2::aod @@ -141,6 +145,7 @@ struct HfTaskDs { Produces hfCandDsDlMinis; Produces hfCandDsD0Minis; Produces hfCandDsMcMinis; + Produces hfCandDsD0McMinis; Configurable decayChannel{"decayChannel", 1, "Switch between resonant decay channels: 1 for Ds/Dplus->PhiPi->KKpi, 2 for Ds/Dplus->K0*K->KKPi"}; Configurable fillDplusMc{"fillDplusMc", true, "Switch to fill Dplus MC information"}; @@ -169,7 +174,7 @@ struct HfTaskDs { } ccdbConfig; SliceCache cache; - Service ccdb; + Service ccdb{}; using TH1Ptr = std::shared_ptr; using TH2Ptr = std::shared_ptr; @@ -584,8 +589,8 @@ struct HfTaskDs { } } - template - void fillMiniTrees(const Cand& candidate, DataType dataType, FinalState finalState) + template + void fillMiniTrees(const Cand& candidate, FinalState finalState) { auto mass = finalState == FinalState::KKPi ? HfHelper::invMassDsToKKPi(candidate) : HfHelper::invMassDsToPiKK(candidate); auto pt = candidate.pt(); @@ -597,8 +602,32 @@ struct HfTaskDs { if (miniTrees.extendWithImpactParameter) { hfCandDsD0Minis(candidate.impactParameterXY()); } - if constexpr (IsMc) { - hfCandDsMcMinis(dataType); + } + + template + void fillMiniTreesMc(const Cand& candidate, DataType dataType, FinalState finalState, const CandDsMcGen& mcParticles, int indexMother) + { + auto mass = finalState == FinalState::KKPi ? HfHelper::invMassDsToKKPi(candidate) : HfHelper::invMassDsToPiKK(candidate); + auto pt = candidate.pt(); + + hfCandDsMinis(mass, pt, evaluateCentralityCand(candidate)); + if (miniTrees.extendWithDecayLength) { + hfCandDsDlMinis(candidate.decayLength(), candidate.decayLengthXY(), candidate.decayLengthNormalised(), candidate.decayLengthXYNormalised()); + } + if (miniTrees.extendWithImpactParameter) { + hfCandDsD0Minis(candidate.impactParameterXY()); + } + hfCandDsMcMinis(dataType); + + if (miniTrees.extendWithImpactParameter) { + // indexMother is != -1 here + auto particleMc = mcParticles.rawIteratorAt(indexMother); + auto prong0 = mcParticles.rawIteratorAt(particleMc.daughtersIds()[0]); + + std::array pv{particleMc.mcCollision().posX(), particleMc.mcCollision().posY(), particleMc.mcCollision().posZ()}; + std::array sv{prong0.vx(), prong0.vy(), prong0.vz()}; + auto genD0 = RecoDecay::impParXY(pv, sv, std::array{particleMc.px(), particleMc.py(), particleMc.pz()}); + hfCandDsD0McMinis(genD0); } } @@ -663,7 +692,7 @@ struct HfTaskDs { fillHisto(candidate, dataType); fillHistoKKPi(candidate, dataType); if (miniTrees.produceMiniTrees) { - fillMiniTrees(candidate, dataType, FinalState::KKPi); + fillMiniTreesMc(candidate, dataType, FinalState::KKPi, mcParticles, indexMother); } if (TESTBIT(candidate.isSelDsToKKPi(), aod::SelectionStep::RecoSkims)) { std::get(histosPtr[dataType]["hPtVsYRecoSkim"])->Fill(pt, yCand); @@ -683,7 +712,7 @@ struct HfTaskDs { fillHisto(candidate, dataType); fillHistoPiKK(candidate, dataType); if (miniTrees.produceMiniTrees) { - fillMiniTrees(candidate, dataType, FinalState::PiKK); + fillMiniTreesMc(candidate, dataType, FinalState::PiKK, mcParticles, indexMother); } if (TESTBIT(candidate.isSelDsToPiKK(), aod::SelectionStep::RecoSkims)) { @@ -709,7 +738,7 @@ struct HfTaskDs { fillHisto(candidate, DataType::Data); fillHistoKKPi(candidate, DataType::Data); if (miniTrees.produceMiniTrees) { - fillMiniTrees(candidate, DataType::Data, FinalState::KKPi); + fillMiniTrees(candidate, FinalState::KKPi); } } if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK @@ -719,7 +748,7 @@ struct HfTaskDs { fillHisto(candidate, DataType::Data); fillHistoPiKK(candidate, DataType::Data); if (miniTrees.produceMiniTrees) { - fillMiniTrees(candidate, DataType::Data, FinalState::PiKK); + fillMiniTrees(candidate, FinalState::PiKK); } } } diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index 6c5a2fee257..f0af577b233 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -61,15 +61,14 @@ struct HfTaskDstarToD0Pi { Configurable isCentStudy{"isCentStudy", true, "Flag to select centrality study"}; Configurable qaEnabled{"qaEnabled", true, "Flag to enable QA histograms"}; Configurable studyD0ToPiKPi0{"studyD0ToPiKPi0", false, "Flag to study D*->D0(piKpi0)pi channel"}; + Configurable ptShapeStudy{"ptShapeStudy", false, "Flag to enable pT shape study"}; + Configurable useWeightOnline{"useWeightOnline", false, "Flag to enable use of weights for pT shape study online"}; // CCDB configuration - Configurable useWeight{"useWeight", true, "Flag to use weights from CCDB"}; - Configurable nWeights{"nWeights", 6, "Number of weights to be used from CCDB"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable ccdbPathForWeight{"ccdbPathForWeight", "Users/d/desharma/weights", "CCDB path for PVContrib weights"}; - Configurable timestampCCDB{"timestampCCDB", -1, "CCDB timestamp for the weights"}; - Configurable weightFileName{"weightFileName", "Weights.root", "Name of the weight file to be used for PVContrib"}; - Configurable> centRangesForWeights{"centRangesForWeights", {0.0, 5.0, 10.0, 30.0, 50.0, 70.0, 100.0}, "Centrality ranges for weights. Size of ranges should be equal to nWeights + 1"}; + Configurable ccdbPathForWeight{"ccdbPathForWeight", "", "CCDB path for pt shape weights"}; + Configurable timestampCCDB{"timestampCCDB", -1, "CCDB timestamp for pt shape weights"}; + Configurable weightFileName{"weightFileName", "Weights.root", "Name of the weight file to be used for pt shape study"}; Configurable yCandDstarRecoMax{"yCandDstarRecoMax", 0.8, "max. candidate Dstar rapidity"}; Configurable yCandDstarGenMax{"yCandDstarGenMax", 0.5, "max. rapidity of Generator level Particle"}; @@ -80,9 +79,23 @@ struct HfTaskDstarToD0Pi { o2::ccdb::CcdbApi ccdbApi; SliceCache cache; - std::vector hWeights; + std::vector hWeights; + int const nWeights = 2; // prompt and non-prompt weights + std::vector const weightHistNames = {"promptWeightVsPt", "nonPromptWeightVsPt"}; + enum weightType { + Prompt = 0, + NonPrompt = 1 + }; + + // for offline weights + std::vector axesPtVsCentVsBDTVsPvContribVsPtB; + std::vector axesPtVsCentVsPvContribVsPtB; + std::vector axesPtVsPvContribVsPtB; + std::vector axesPtVsBDTVsPtB; + std::vector axesPtVsCentVsBDTVsPvContrib; std::vector axesPtVsCentVsPvContrib; + std::vector axesPtVsPvContrib; std::vector axesPtVsBDT; using CandDstarWSelFlag = soa::Join; @@ -114,6 +127,7 @@ struct HfTaskDstarToD0Pi { ConfigurableAxis binningBkgBDTScore{"binningBkgBDTScore", {100, 0.0f, 1.0f}, "Bins for background BDT Score"}; ConfigurableAxis binningSigBDTScore{"binningSigBDTScore", {100, 0.0f, 1.0f}, "Bins for Signal (Prompts + Non Prompt) BDT Score"}; ConfigurableAxis binningPvContrib{"binningPvContrib", {100, 0.0f, 300.0f}, "Bins for PVContrib"}; + ConfigurableAxis binningPtFine{"binningPtFine", {100, 0.0f, 100.0f}, "fine bins for pT shape offline study "}; // for offline pt shape study HistogramRegistry registry{"registry", {}}; @@ -136,10 +150,27 @@ struct HfTaskDstarToD0Pi { AxisSpec axisPvContrib = {binningPvContrib, "PV Contribution"}; AxisSpec const axisPt = {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}; + // for offline weights + AxisSpec axisPtFine = {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}; + if (ptShapeStudy && !useWeightOnline) { + axisPtFine = {binningPtFine, "pT (GeV/c)"}; + } + // // std::cout<< "fine pt bins for pt shape study: binningPtFine"<< binningPtFine->data() << std::endl; + // // std::cout<< "fine pt bins for pt shape study: axisPtFine"<< axisPtFine.binEdges[2] << std::endl; + axesPtVsCentVsBDTVsPvContrib = {axisPt, axisCentrality, axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt, axisPvContrib}; axesPtVsCentVsPvContrib = {axisPt, axisCentrality, axisPvContrib}; + axesPtVsPvContrib = {axisPt, axisPvContrib}; axesPtVsBDT = {axisPt, axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt}; + // for offline weights + if (ptShapeStudy && !useWeightOnline) { + axesPtVsCentVsBDTVsPvContribVsPtB = {axisPt, axisCentrality, axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt, axisPvContrib, axisPtFine}; + axesPtVsCentVsPvContribVsPtB = {axisPt, axisCentrality, axisPvContrib, axisPtFine}; + axesPtVsPvContribVsPtB = {axisPt, axisPvContrib, axisPtFine}; + axesPtVsBDTVsPtB = {axisPt, axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt, axisPtFine}; + } + if (qaEnabled) { // only QA registry.add("QA/hPtDstar", "Dstar Candidates; Dstar candidate #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); @@ -223,7 +254,14 @@ struct HfTaskDstarToD0Pi { // Non Prmpt Gen registry.add("Efficiency/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.}}}, true); - // Checking PV contributors from Data as well MC rec for calculation weights offline + if (ptShapeStudy && !useWeightOnline) { + // Prompt Gen + registry.add("Efficiency/PtShape/hPtVsYVsFinePtPromptDstarGen", "MC Matched Prompt D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}; #it{p}_{T} of D*", {HistType::kTH3F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}, {axisPtFine}}}, true); + // Non Prmpt Gen + registry.add("Efficiency/PtShape/hPtVsYVsFinePtBNonPromptDstarGen", "MC Matched Non-Prompt D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}; #it{p}_{T} of B hadron", {HistType::kTH3F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}, {axisPtFine}}}, true); + } + + // Checking PV contributors from Data as well MC rec for calculation of efficiency weights offline if (isCentStudy) { registry.add("Efficiency/hNumPvContributorsAll", "PV Contributors; PV Contributor; FT0M Centrality", {HistType::kTH2F, {{axisPvContrib}, {axisCentrality}}}, true); registry.add("Efficiency/hNumPvContributorsCand", "PV Contributors; PV Contributor; FT0M Centrality", {HistType::kTH2F, {{axisPvContrib}, {axisCentrality}}}, true); @@ -235,10 +273,18 @@ struct HfTaskDstarToD0Pi { registry.add("Efficiency/hPtVsCentVsPvContribRecSig", "Pt Vs Cent Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsPvContrib}, true); registry.add("Efficiency/hPtPromptVsCentVsPvContribRecSig", "Pt Vs Cent Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsPvContrib}, true); registry.add("Efficiency/hPtNonPromptVsCentVsPvContribRecSig", "Pt Vs Cent Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsPvContrib}, true); + if (ptShapeStudy && !useWeightOnline) { + registry.add("Efficiency/PtShape/hPtPromptVsCentVsPvContribVsFinePtRecSig", "Pt Vs Cent Vs PvContrib Vs Fine Pt of D*", {HistType::kTHnSparseF, axesPtVsCentVsPvContribVsPtB}, true); + registry.add("Efficiency/PtShape/hPtNonPromptVsCentVsPvContribVsFinePtBRecSig", "Pt Vs Cent Vs PvContrib Vs Fine Pt of B hadron", {HistType::kTHnSparseF, axesPtVsCentVsPvContribVsPtB}, true); + } } else if (doprocessMcWoMl && !isCentStudy) { - registry.add("Efficiency/hPtVsPvContribRecSig", "Pt Vs PvContrib", {HistType::kTHnSparseF, axesPtVsBDT}, true); - registry.add("Efficiency/hPtPromptVsPvContribRecSig", "Pt Vs PvContrib", {HistType::kTHnSparseF, axesPtVsBDT}, true); - registry.add("Efficiency/hPtNonPromptVsPvContribRecSig", "Pt Vs PvContrib", {HistType::kTHnSparseF, axesPtVsBDT}, true); + registry.add("Efficiency/hPtVsPvContribRecSig", "Pt Vs PvContrib", {HistType::kTHnSparseF, axesPtVsPvContrib}, true); + registry.add("Efficiency/hPtPromptVsPvContribRecSig", "Pt Vs PvContrib", {HistType::kTHnSparseF, axesPtVsPvContrib}, true); + registry.add("Efficiency/hPtNonPromptVsPvContribRecSig", "Pt Vs PvContrib", {HistType::kTHnSparseF, axesPtVsPvContrib}, true); + if (ptShapeStudy && !useWeightOnline) { + registry.add("Efficiency/PtShape/hPtPromptVsPvContribVsFinePtRecSig", "Pt Vs PvContrib Vs Fine Pt of D*", {HistType::kTHnSparseF, axesPtVsPvContribVsPtB}, true); + registry.add("Efficiency/PtShape/hPtNonPromptVsPvContribVsFinePtBRecSig", "Pt Vs PvContrib Vs Fine Pt of B hadron", {HistType::kTHnSparseF, axesPtVsPvContribVsPtB}, true); + } } // Hists at Reco level W/ ML usefull for efficiency calculation @@ -246,11 +292,19 @@ struct HfTaskDstarToD0Pi { registry.add("Efficiency/hPtVsCentVsBDTScoreVsPvContribRecSig", "Pt Vs Cent Vs BDTScore Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsBDTVsPvContrib}, true); registry.add("Efficiency/hPtPromptVsCentVsBDTScorePvContribRecSig", "Pt Vs Cent Vs BDTScore Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsBDTVsPvContrib}, true); registry.add("Efficiency/hPtNonPrompRectVsCentVsBDTScorePvContribRecSig", "Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, axesPtVsCentVsBDTVsPvContrib}, true); + if (ptShapeStudy && !useWeightOnline) { + registry.add("Efficiency/PtShape/hPtPromptVsCentVsBDTScoreVsPvContribVsFinePtRecSig", "Pt Vs Cent Vs BDTScore Vs PvContrib Vs Fine Pt of D*", {HistType::kTHnSparseF, axesPtVsCentVsBDTVsPvContribVsPtB}, true); + registry.add("Efficiency/PtShape/hPtNonPromptVsCentVsBDTScorePvContribVsFinePtBRecSig", "Pt Vs Cent Vs BDTScore Vs PvContrib Vs Fine Pt of B hadron", {HistType::kTHnSparseF, axesPtVsCentVsBDTVsPvContribVsPtB}, true); + } // registry.add("Efficiency/hPtBkgVsCentVsBDTScore", "Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}, {axisBDTScoreBackground}, {axisBDTScorePrompt}, {axisBDTScoreNonPrompt}}}); } else if (doprocessMcWML && !isCentStudy) { registry.add("Efficiency/hPtVsBDTScoreRecSig", "Pt Vs BDTScore", {HistType::kTHnSparseF, axesPtVsBDT}, true); registry.add("Efficiency/hPtPromptVsBDTScoreRecSig", "Pt Vs BDTScore", {HistType::kTHnSparseF, axesPtVsBDT}, true); registry.add("Efficiency/hPtNonPromptVsBDTScoreRecSig", "Pt Vs BDTScore", {HistType::kTHnSparseF, axesPtVsBDT}, true); + if (ptShapeStudy && !useWeightOnline) { + registry.add("Efficiency/PtShape/hPtPromptVsBDTScoreVsFinePtRecSig", "Pt Vs BDTScore Vs Fine Pt of D*", {HistType::kTHnSparseF, axesPtVsBDTVsPtB}, true); + registry.add("Efficiency/PtShape/hPtNonPromptVsBDTScoreVsFinePtBRecSig", "Pt Vs BDTScore Vs Fine Pt of B hadron", {HistType::kTHnSparseF, axesPtVsBDTVsPtB}, true); + } } // Hists at Gen level usefull for efficiency calculation @@ -260,10 +314,18 @@ struct HfTaskDstarToD0Pi { registry.add("Efficiency/hPtVsCentVsPvContribGen", "Pt Vs Cent Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsPvContrib}, true); registry.add("Efficiency/hPtPromptVsCentVsPvContribGen", "Pt Vs Cent Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsPvContrib}, true); registry.add("Efficiency/hPtNonPromptVsCentVsPvContribGen", "Pt Vs Cent Vs PvContrib", {HistType::kTHnSparseF, axesPtVsCentVsPvContrib}, true); + if (ptShapeStudy && !useWeightOnline) { + registry.add("Efficiency/PtShape/hPtPromptVsCentVsPvContribVsFinePtGen", "Pt Vs Cent Vs PvContrib Vs Fine Pt of D*", {HistType::kTHnSparseF, axesPtVsCentVsPvContribVsPtB}, true); + registry.add("Efficiency/PtShape/hPtNonPromptVsCentVsPvContribVsFinePtBGen", "Pt Vs Cent Vs PvContrib Vs Fine Pt of B hadron", {HistType::kTHnSparseF, axesPtVsCentVsPvContribVsPtB}, true); + } } else { registry.add("Efficiency/hPtGen", "MC Matched D* Candidates at Generator Level", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); registry.add("Efficiency/hPtPromptVsGen", "MC Matched Prompt D* Candidates at Generator Level", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); registry.add("Efficiency/hPtNonPromptVsGen", "MC Matched Non-Prompt D* Candidates at Generator Level", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); + if (ptShapeStudy && !useWeightOnline) { + registry.add("Efficiency/PtShape/hPtPromptVsFinePtGen", "MC Matched Prompt D* Candidates at Generator Level; #it{p}_{T} of D*; #it{p}_{T} of D*", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisPtFine}}}, true); + registry.add("Efficiency/PtShape/hPtNonPromptVsFinePtBGen", "MC Matched Non-Prompt D* Candidates at Generator Level; #it{p}_{T} of D*; #it{p}_{T} of B hadron", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisPtFine}}}, true); + } } } @@ -289,8 +351,8 @@ struct HfTaskDstarToD0Pi { } } - // if weights to be applied - if (useWeight) { + // if weights to be applied for pt shape study + if (ptShapeStudy && useWeightOnline) { ccdbApi.init(ccdbUrl); std::map const metadata; // Retrieve the file from CCDB @@ -300,28 +362,39 @@ struct HfTaskDstarToD0Pi { return; } - if (isCentStudy) { - // Open the ROOT file - TFile* weightFile = TFile::Open(weightFileName.value.c_str(), "READ"); - if ((weightFile != nullptr) && !weightFile->IsZombie()) { - // Ensure hWeights is properly sized - hWeights.resize(nWeights); - for (int ithWeight = 0; ithWeight < nWeights; ++ithWeight) { - std::string const histName = "hMult" + std::to_string(ithWeight + 1) + "_Weight"; - hWeights[ithWeight] = reinterpret_cast(weightFile->Get(histName.c_str())); - if (hWeights[ithWeight] == nullptr) { - LOGF(fatal, "Histogram %s not found in weight file!", histName.c_str()); - return; - } - hWeights[ithWeight]->SetDirectory(nullptr); - hWeights[ithWeight]->SetName(("hWeight" + std::to_string(ithWeight + 1)).c_str()); - } - weightFile->Close(); - delete weightFile; - } else { - LOGF(fatal, "Failed to open weight file from CCDB: %s", weightFileName.value.c_str()); + // Open the ROOT file to intialise weight hists + TFile* weightFile = TFile::Open(weightFileName.value.c_str(), "READ"); + if ((weightFile != nullptr) && !weightFile->IsZombie()) { + // Ensure hWeights is properly sized + hWeights.resize(nWeights); // prompt and non-prompt + + hWeights[weightType::Prompt] = dynamic_cast(weightFile->Get(weightHistNames[weightType::Prompt].c_str())); + hWeights[weightType::NonPrompt] = dynamic_cast(weightFile->Get(weightHistNames[weightType::NonPrompt].c_str())); + if (hWeights[weightType::Prompt] == nullptr) { + LOGF(fatal, "Histogram %s not found in weight file!", weightHistNames[weightType::Prompt].c_str()); + return; + } + if (hWeights[weightType::NonPrompt] == nullptr) { + LOGF(fatal, "Histogram %s not found in weight file!", weightHistNames[weightType::NonPrompt].c_str()); return; } + // checking if bin wdith of weight histograms are not finner than pT axis of Dstar + if (hWeights[weightType::Prompt]->GetXaxis()->GetBinWidth(1) >= vecPtBins[1] - vecPtBins[0]) { + LOGF(fatal, "Bin width of weight histogram should be finer than pT axis of Dstar!"); + return; + } + if (hWeights[weightType::NonPrompt]->GetXaxis()->GetBinWidth(1) >= vecPtBins[1] - vecPtBins[0]) { + LOGF(fatal, "Bin width of weight histogram should be finer than pT axis of Dstar!"); + return; + } + hWeights[weightType::Prompt]->SetDirectory(nullptr); + hWeights[weightType::NonPrompt]->SetDirectory(nullptr); + + weightFile->Close(); + delete weightFile; + } else { + LOGF(fatal, "Failed to open weight file from CCDB: %s", weightFileName.value.c_str()); + return; } } } @@ -473,9 +546,10 @@ struct HfTaskDstarToD0Pi { auto prong0 = candDstarMcRec.template prong0_as(); auto indexMother = RecoDecay::getMother(rowsMcPartilces, prong0.template mcParticle_as(), o2::constants::physics::Pdg::kDStar, true, &signDstar, 2); auto particleMother = rowsMcPartilces.rawIteratorAt(indexMother); // What is difference between rawIterator() or iteratorAt() methods? + auto ptMother = particleMother.pt(); if (qaEnabled) { - registry.fill(HIST("QA/hPtSkimDstarGenSig"), particleMother.pt()); // generator level pt - registry.fill(HIST("QA/hPtVsCentSkimDstarGenSig"), particleMother.pt(), centrality); + registry.fill(HIST("QA/hPtSkimDstarGenSig"), ptMother); // generator level pt + registry.fill(HIST("QA/hPtVsCentSkimDstarGenSig"), ptMother, centrality); registry.fill(HIST("QA/hPtVsYSkimDstarRecSig"), ptDstarRecSig, yDstarRecSig); // Skimed at level of trackIndexSkimCreator if (candDstarMcRec.isRecoTopol()) { // if Topological selection are passed registry.fill(HIST("QA/hPtVsYRecoTopolDstarRecSig"), ptDstarRecSig, yDstarRecSig); @@ -487,18 +561,17 @@ struct HfTaskDstarToD0Pi { if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed float weightValue = 1.0; - if (useWeight && (hWeights.empty() || hWeights[0] == nullptr)) { - LOGF(fatal, "Weight histograms are not initialized or empty. Check CCDB path or weight file."); - return; - } - if (useWeight && isCentStudy) { - for (int ithWeight = 0; ithWeight < nWeights; ++ithWeight) { - if (centrality > centRangesForWeights.value[ithWeight] && centrality <= centRangesForWeights.value[ithWeight + 1]) { - weightValue = hWeights[ithWeight]->GetBinContent(hWeights[ithWeight]->FindBin(nPVContributors)); - break; - } + std::vector ptShapeWeightValues(nWeights, 1.0); // Assuming two weights: one for prompt and one for non-prompt + + if (ptShapeStudy && useWeightOnline) { + if (hWeights.empty() || hWeights[0] == nullptr) { + LOGF(fatal, "Weight histograms are not initialized or empty. Check CCDB path or weight file."); + return; } + ptShapeWeightValues[weightType::Prompt] = hWeights[weightType::Prompt]->GetBinContent(hWeights[weightType::Prompt]->FindBin(ptDstarRecSig)); + ptShapeWeightValues[weightType::NonPrompt] = hWeights[weightType::NonPrompt]->GetBinContent(hWeights[weightType::NonPrompt]->FindBin(ptMother)); } + if (qaEnabled) { registry.fill(HIST("QA/hPtFullRecoDstarRecSig"), ptDstarRecSig); } @@ -508,33 +581,61 @@ struct HfTaskDstarToD0Pi { auto bdtScore = candDstarMcRec.mlProbDstarToD0Pi(); registry.fill(HIST("Efficiency/hPtVsCentVsBDTScoreVsPvContribRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, weightValue); if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("Efficiency/hPtPromptVsCentVsBDTScorePvContribRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, weightValue); + registry.fill(HIST("Efficiency/hPtPromptVsCentVsBDTScorePvContribRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, ptShapeWeightValues[weightType::Prompt]); } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("Efficiency/hPtNonPrompRectVsCentVsBDTScorePvContribRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, weightValue); + registry.fill(HIST("Efficiency/hPtNonPrompRectVsCentVsBDTScorePvContribRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, ptShapeWeightValues[weightType::NonPrompt]); + } + if (ptShapeStudy && !useWeightOnline) { + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("Efficiency/PtShape/hPtPromptVsCentVsBDTScoreVsPvContribVsFinePtRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, ptDstarRecSig); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/PtShape/hPtNonPromptVsCentVsBDTScorePvContribVsFinePtBRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, ptMother); + } } } else { auto bdtScore = candDstarMcRec.mlProbDstarToD0Pi(); registry.fill(HIST("Efficiency/hPtVsBDTScoreRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], weightValue); if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("Efficiency/hPtPromptVsBDTScoreRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], weightValue); + registry.fill(HIST("Efficiency/hPtPromptVsBDTScoreRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], ptShapeWeightValues[weightType::Prompt]); } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("Efficiency/hPtNonPromptVsBDTScoreRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], weightValue); + registry.fill(HIST("Efficiency/hPtNonPromptVsBDTScoreRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], ptShapeWeightValues[weightType::NonPrompt]); + } + if (ptShapeStudy && !useWeightOnline) { + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("Efficiency/PtShape/hPtPromptVsBDTScoreVsFinePtRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], ptDstarRecSig); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/PtShape/hPtNonPromptVsBDTScoreVsFinePtBRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], ptMother); + } } } } else { // All efficiency histograms at reconstruction level w/o ml if (isCentStudy) { registry.fill(HIST("Efficiency/hPtVsCentVsPvContribRecSig"), ptDstarRecSig, centrality, nPVContributors, weightValue); if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("Efficiency/hPtPromptVsCentVsPvContribRecSig"), ptDstarRecSig, centrality, nPVContributors, weightValue); + registry.fill(HIST("Efficiency/hPtPromptVsCentVsPvContribRecSig"), ptDstarRecSig, centrality, nPVContributors, ptShapeWeightValues[weightType::Prompt]); } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsPvContribRecSig"), ptDstarRecSig, centrality, nPVContributors, weightValue); + registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsPvContribRecSig"), ptDstarRecSig, centrality, nPVContributors, ptShapeWeightValues[weightType::NonPrompt]); + } + if (ptShapeStudy && !useWeightOnline) { + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("Efficiency/PtShape/hPtPromptVsCentVsPvContribVsFinePtRecSig"), ptDstarRecSig, centrality, nPVContributors, ptDstarRecSig); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/PtShape/hPtNonPromptVsCentVsPvContribVsFinePtBRecSig"), ptDstarRecSig, centrality, nPVContributors, ptMother); + } } } else { registry.fill(HIST("Efficiency/hPtVsPvContribRecSig"), ptDstarRecSig, nPVContributors, weightValue); if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("Efficiency/hPtPromptVsPvContribRecSig"), ptDstarRecSig, nPVContributors, weightValue); + registry.fill(HIST("Efficiency/hPtPromptVsPvContribRecSig"), ptDstarRecSig, nPVContributors, ptShapeWeightValues[weightType::Prompt]); } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("Efficiency/hPtNonPromptVsPvContribRecSig"), ptDstarRecSig, nPVContributors, weightValue); + registry.fill(HIST("Efficiency/hPtNonPromptVsPvContribRecSig"), ptDstarRecSig, nPVContributors, ptShapeWeightValues[weightType::NonPrompt]); + } + if (ptShapeStudy && !useWeightOnline) { + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("Efficiency/PtShape/hPtPromptVsPvContribVsFinePtRecSig"), ptDstarRecSig, nPVContributors, ptDstarRecSig); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/PtShape/hPtNonPromptVsPvContribVsFinePtBRecSig"), ptDstarRecSig, nPVContributors, ptMother); + } } } } @@ -631,6 +732,12 @@ struct HfTaskDstarToD0Pi { for (auto const& mcParticle : rowsMcPartilces) { if (std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { // MC Matching is successful at Generator Level auto ptGen = mcParticle.pt(); + + // mother information + auto idxBhadMotherPart = mcParticle.idxBhadMotherPart(); + auto bMother = rowsMcPartilces.rawIteratorAt(idxBhadMotherPart); + auto ptBMother = bMother.pt(); + auto yGen = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDStar); if (yCandDstarGenMax >= 0. && std::abs(yGen) > yCandDstarGenMax) { continue; @@ -651,8 +758,8 @@ struct HfTaskDstarToD0Pi { } } - float centFT0MGen; - float pvContributors; + float centFT0MGen{0.f}; + float pvContributors{0.f}; // assigning centrality to MC Collision using max FT0M amplitute from Reconstructed collisions if (recCollisions.size() != 0) { std::vector::iterator, int>> tempRecCols; @@ -668,17 +775,15 @@ struct HfTaskDstarToD0Pi { } float weightValue = 1.0; - if (useWeight && (hWeights.empty() || hWeights[0] == nullptr)) { - LOGF(fatal, "Weight histograms are not initialized or empty. Check CCDB path or weight file."); - return; - } - if (useWeight && isCentStudy) { - for (int ithWeight = 0; ithWeight < nWeights; ++ithWeight) { - if (centFT0MGen > centRangesForWeights.value[ithWeight] && centFT0MGen <= centRangesForWeights.value[ithWeight + 1]) { - weightValue = hWeights[ithWeight]->GetBinContent(hWeights[ithWeight]->FindBin(centFT0MGen, pvContributors)); - break; - } + std::vector ptShapeWeightValues(nWeights, 1.0); // Assuming two weights: one for prompt and one for non-prompt + + if (ptShapeStudy && useWeightOnline) { + if (hWeights.empty() || hWeights[0] == nullptr) { + LOGF(fatal, "Weight histograms are not initialized or empty. Check CCDB path or weight file."); + return; } + ptShapeWeightValues[weightType::Prompt] = hWeights[weightType::Prompt]->GetBinContent(hWeights[weightType::Prompt]->FindBin(ptGen)); + ptShapeWeightValues[weightType::NonPrompt] = hWeights[weightType::NonPrompt]->GetBinContent(hWeights[weightType::NonPrompt]->FindBin(ptBMother)); } registry.fill(HIST("Efficiency/hPtVsYDstarGen"), ptGen, yGen, weightValue); @@ -693,20 +798,39 @@ struct HfTaskDstarToD0Pi { // Prompt if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("Efficiency/hPtVsYPromptDstarGen"), ptGen, yGen, weightValue); + registry.fill(HIST("Efficiency/hPtVsYPromptDstarGen"), ptGen, yGen, ptShapeWeightValues[weightType::Prompt]); if (isCentStudy) { - registry.fill(HIST("Efficiency/hPtPromptVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, weightValue); + registry.fill(HIST("Efficiency/hPtPromptVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, ptShapeWeightValues[weightType::Prompt]); } else { - registry.fill(HIST("Efficiency/hPtPromptVsGen"), ptGen, weightValue); + registry.fill(HIST("Efficiency/hPtPromptVsGen"), ptGen, ptShapeWeightValues[weightType::Prompt]); } // Non-Prompt } else if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("Efficiency/hPtVsYNonPromptDstarGen"), ptGen, yGen, weightValue); + registry.fill(HIST("Efficiency/hPtVsYNonPromptDstarGen"), ptGen, yGen, ptShapeWeightValues[weightType::NonPrompt]); if (isCentStudy) { - registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, weightValue); + registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, ptShapeWeightValues[weightType::NonPrompt]); } else { - registry.fill(HIST("Efficiency/hPtNonPromptVsGen"), ptGen, weightValue); + registry.fill(HIST("Efficiency/hPtNonPromptVsGen"), ptGen, ptShapeWeightValues[weightType::NonPrompt]); + } + } + if (ptShapeStudy && !useWeightOnline) { + // prompt + if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("Efficiency/PtShape/hPtVsYVsFinePtPromptDstarGen"), ptGen, yGen, ptGen); + if (isCentStudy) { + registry.fill(HIST("Efficiency/PtShape/hPtPromptVsCentVsPvContribVsFinePtGen"), ptGen, centFT0MGen, pvContributors, ptGen); + } else { + registry.fill(HIST("Efficiency/PtShape/hPtPromptVsFinePtGen"), ptGen, ptGen); + } + // Non-Prompt + } else if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/PtShape/hPtVsYVsFinePtBNonPromptDstarGen"), ptGen, yGen, ptBMother); + if (isCentStudy) { + registry.fill(HIST("Efficiency/PtShape/hPtNonPromptVsCentVsPvContribVsFinePtBGen"), ptGen, centFT0MGen, pvContributors, ptBMother); + } else { + registry.fill(HIST("Efficiency/PtShape/hPtNonPromptVsFinePtBGen"), ptGen, ptBMother); + } } } } diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 40c253d051d..78462e10a73 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; using namespace o2::hf_evsel; @@ -107,7 +109,7 @@ struct HfTaskFlowCharmHadrons { 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, TPC Tot: 6)"}; - Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4)"}; + Configurable centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; Configurable selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"}; Configurable centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; @@ -122,6 +124,8 @@ struct HfTaskFlowCharmHadrons { Configurable storeEpCosSin{"storeEpCosSin", false, "Flag to store cos and sin of EP angle in ThnSparse"}; Configurable storeCandEta{"storeCandEta", false, "Flag to store candidates eta"}; Configurable storeCandSign{"storeCandSign", false, "Flag to store candidates sign"}; + Configurable storeCentSparse{"storeCentSparse", false, "Flag to store up to 4 centrality estimators comparison sparse (only applied in resolution process)"}; + Configurable> centEstimatorsForSparse{"centEstimatorsForSparse", {1, 2, 3, 4}, "Centrality estimators to be stored in the centrality sparse (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4). Up to 4 estimators can be configured."}; Configurable occEstimator{"occEstimator", 0, "Occupancy estimation (0: None, 1: ITS, 2: FT0C)"}; Configurable saveEpResoHisto{"saveEpResoHisto", false, "Flag to save event plane resolution histogram"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -129,7 +133,7 @@ struct HfTaskFlowCharmHadrons { EventPlaneHelper epHelper; HfEventSelection hfEvSel; // event selection and monitoring - o2::framework::Service ccdb; + o2::framework::Service ccdb{}; SliceCache cache; using CandDsDataWMl = soa::Filtered>; @@ -144,7 +148,7 @@ struct HfTaskFlowCharmHadrons { using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; - using CollsWithQvecs = soa::Join; + using CollsWithQvecs = soa::Join; using TracksWithExtra = soa::Join; Filter filterSelectDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -249,6 +253,13 @@ struct HfTaskFlowCharmHadrons { } } registry.add("hSparseFlowCharm", "THn for SP", HistType::kTHnSparseF, axes); + registry.add("hCentEventWithCand", "Centrality distributions with charm candidates;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); + registry.add("hCentEventWithCandInSigRegion", "Centrality distributions with charm candidates in signal range;Cent;entries", HistType::kTH1F, {{100, 0.f, 100.f}}); + + if (storeCentSparse) { + std::vector axesCent = {thnAxisCent, thnAxisCent, thnAxisCent, thnAxisCent}; + registry.add("hSparseCentEstimators", "THn with different centrality estimators; Centrality 0; Centrality 1; Centrality 2; Centrality 3", {HistType::kTHnSparseF, axesCent}); + } if (occEstimator != 0) { registry.add("trackOccVsFT0COcc", "trackOccVsFT0COcc; trackOcc; FT0COcc", {HistType::kTH2F, {thnAxisOccupancyITS, thnAxisOccupancyFT0C}}); @@ -512,6 +523,9 @@ struct HfTaskFlowCharmHadrons { if (cent < centralityMin || cent > centralityMax) { return; } + if (candidates.size() > 0) { + registry.fill(HIST("hCentEventWithCand"), cent); + } float occupancy = 0.; o2::hf_evsel::HfCollisionRejectionMask hfevflag{}; if (occEstimator != 0) { @@ -519,6 +533,10 @@ struct HfTaskFlowCharmHadrons { registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); hfevflag = hfEvSel.getHfCollisionRejectionMask(collision, cent, ccdb, registry); } + bool hasCandInMassWin = false; + float const sigmaMD0 = 0.02; // used 20 MeV as the D0 average peak width in run3 + float const sigmaMDplus = 0.015; // used 15 MeV as the D+ average peak width in run3 + float const nSigmaMass = 2.5; std::array qVecs = getQvec(collision, qVecDetector.value); float xQVec = qVecs[0]; @@ -554,6 +572,9 @@ struct HfTaskFlowCharmHadrons { } } else if constexpr (std::is_same_v || std::is_same_v) { massCand = HfHelper::invMassDplusToPiKPi(candidate); + if (std::abs(massCand - MassDPlus) < nSigmaMass * sigmaMDplus) { + hasCandInMassWin = true; + } auto trackprong0 = candidate.template prong0_as(); signCand = trackprong0.sign(); if constexpr (std::is_same_v) { @@ -566,6 +587,9 @@ struct HfTaskFlowCharmHadrons { case DecayChannel::D0ToPiK: signCand = candidate.isSelD0bar() ? 3 : 1; // 3: reflected D0bar, 1: pure D0 excluding reflected D0bar massCand = HfHelper::invMassD0ToPiK(candidate); + if (std::abs(massCand - MassD0) < nSigmaMass * sigmaMD0) { + hasCandInMassWin = true; + } if constexpr (std::is_same_v) { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMl[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; @@ -574,6 +598,9 @@ struct HfTaskFlowCharmHadrons { break; case DecayChannel::D0ToKPi: massCand = HfHelper::invMassD0barToKPi(candidate); + if (std::abs(massCand - MassD0) < nSigmaMass * sigmaMD0) { + hasCandInMassWin = true; + } signCand = candidate.isSelD0() ? 3 : 2; // 3: reflected D0, 2: pure D0bar excluding reflected D0 if constexpr (std::is_same_v) { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { @@ -699,6 +726,9 @@ struct HfTaskFlowCharmHadrons { fillThn(massCand, ptCand, etaCand, signCand, cent, cosNPhi, sinNPhi, cosDeltaPhi, scalprodCand, outputMl, occupancy, hfevflag); } } + if (hasCandInMassWin) { + registry.fill(HIST("hCentEventWithCandInSigRegion"), cent); + } } // Ds with ML @@ -855,7 +885,7 @@ struct HfTaskFlowCharmHadrons { float const xQVecBTot = collision.qvecBTotRe(); float const yQVecBTot = collision.qvecBTotIm(); - centrality = o2::hf_centrality::getCentralityColl(collision, o2::hf_centrality::CentralityEstimator::FT0C); + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); if (storeResoOccu) { const auto occupancy = o2::hf_occupancy::getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -867,6 +897,11 @@ struct HfTaskFlowCharmHadrons { occupancy, evtSelFlags[0], evtSelFlags[1], evtSelFlags[2], evtSelFlags[3], evtSelFlags[4]); } + if (storeCentSparse) { + registry.fill(HIST("hSparseCentEstimators"), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(0)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(1)), + o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(2)), o2::hf_centrality::getCentralityColl(collision, centEstimatorsForSparse->at(3))); + } + if (!isCollSelected(collision, bcs, centrality)) { // no selection on the centrality is applied, but on event selection flags return; diff --git a/PWGHF/D2H/Tasks/taskHiddenCharm.cxx b/PWGHF/D2H/Tasks/taskHiddenCharm.cxx new file mode 100644 index 00000000000..0830048c0a7 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskHiddenCharm.cxx @@ -0,0 +1,145 @@ +// 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 taskHiddenCharm.cxx +/// \brief Analysis task for hidden charm hadrons at midrapidity +/// +/// \author A. Palasciano, , INFN Bari +/// \author S. Politanò , CERN + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; + +enum TrackType : uint8_t { + Pion = 0, + Kaon, + Proton +}; + +struct HfTaskHiddenCharm { + Configurable centEstimator{"centEstimator", 0, "Centrality estimation (None: 0, FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4, NTracksPV: 5, FT0CVariant2: 6)"}; + Configurable centralityMin{"centralityMin", 0.f, "Minimum accepted centrality"}; + Configurable centralityMax{"centralityMax", 100.f, "Maximum accepted centrality"}; + Configurable fillOnlyUnlikeSign{"fillOnlyUnlikeSign", true, "Fill only unlike-sign proton pairs"}; + Configurable fillOnlyLikeSign{"fillOnlyLikeSign", true, "Fill only like-sign proton pairs"}; + + SliceCache cache; + + using SelectedCollisionsPP = aod::HfRedCollisions; + using SelectedCollisionsPbPb = soa::Join; + Partition selectedProtons = aod::hf_track_vars_reduced::trackType == static_cast(TrackType::Proton); + Partition selectedPions = aod::hf_track_vars_reduced::trackType == static_cast(TrackType::Pion); + Partition selectedKaons = aod::hf_track_vars_reduced::trackType == static_cast(TrackType::Kaon); + + ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {1400, 2.8, 4.2}, ""}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {100, 0., 10.}, ""}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {100, 0., 100.}, ""}; + ConfigurableAxis thnConfigAxisSign{"thnConfigAxisSign", {2, -1., 1.}, ""}; + + HistogramRegistry registry{"registry", {}}; + + void init(InitContext&) + { + const AxisSpec axisInvMass{thnConfigAxisInvMass, "M_{p#bar{p}} (GeV/#it{c}^{2})"}; + const AxisSpec axisPt{thnConfigAxisPt, "#it{p}_{T}^{p#bar{p}} (GeV/#it{c})"}; + const AxisSpec axisCent{thnConfigAxisCent, "Centrality"}; + const AxisSpec axisSign{thnConfigAxisSign, "q_{1} #times q_{2}"}; + + registry.add("hSparseHiddenCharm", "Hidden-charm proton-pair candidates", HistType::kTHnSparseF, {axisInvMass, axisPt, axisSign, axisCent}); + registry.add("hPtVsInvMassLikeSign", "Hidden-charm LS M_{inv}", HistType::kTH2D, {axisInvMass, axisPt}); + registry.add("hPtVsInvMassUnlikeSign", "Hidden-charm proton-pair ULS", HistType::kTH2D, {axisInvMass, axisPt}); + registry.add("hPtVsInvMassAllSign", "Hidden-charm proton-pair LS+ULS M_{inv}", HistType::kTH2D, {axisInvMass, axisPt}); + } + + template + void fillEtac(TCollisions const& collision, + TProtonIds const& protonIds) + { + float cent{-1.f}; + if constexpr (CentEstimator != o2::hf_centrality::CentralityEstimator::None) { + cent = o2::hf_centrality::getCentralityColl(collision, centEstimator); + if (cent < centralityMin || cent >= centralityMax) { + return; // skip events outside the centrality range + } + } + + for (const auto& proton1 : protonIds) { + for (const auto& proton2 : protonIds) { + if (proton1.trackId() >= proton2.trackId()) { + continue; // avoid double counting and self-pairs + } + const int sign = (proton1.sign() * proton2.sign() > 0) ? 1 : -1; + if ((sign == 1 && !fillOnlyLikeSign) || (sign == -1 && !fillOnlyUnlikeSign)) { + continue; + } + std::array pVec1{proton1.px(), proton1.py(), proton1.pz()}; + std::array pVec2{proton2.px(), proton2.py(), proton2.pz()}; + float invMass = RecoDecay::m(std::array{pVec1, pVec2}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassProton}); + float ptEtac = RecoDecay::pt(RecoDecay::sumOfVec(pVec1, pVec2)); + registry.fill(HIST("hSparseHiddenCharm"), invMass, ptEtac, sign, cent); + if (sign == 1) { + registry.fill(HIST("hPtVsInvMassLikeSign"), invMass, ptEtac); + } else if (sign == -1) { + registry.fill(HIST("hPtVsInvMassUnlikeSign"), invMass, ptEtac); + registry.fill(HIST("hPtVsInvMassAllSign"), invMass, ptEtac); + } + } + } + } + + void processEtacPP(SelectedCollisionsPP::iterator const& collision, + aod::HcSelTracks const& /*tracks*/) + { + auto candProtons = selectedProtons->sliceByCached(aod::hf_track_index_reduced::hfRedCollisionId, collision.globalIndex(), cache); + fillEtac(collision, candProtons); + } + PROCESS_SWITCH(HfTaskHiddenCharm, processEtacPP, "Process Etac candidates for pp", true); + + // void processEtacPbPb(SelectedCollisionsPbPb::iterator const& collisions, + // aod::HcSelTracks const& protonIds) + //{ + // fillEtac(collisions, protonIds, true); + // } + // PROCESS_SWITCH(HfTaskHiddenCharm, processEtacPbPb, "Process Etac candidates for PbPb", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskLb.cxx b/PWGHF/D2H/Tasks/taskLb.cxx index ecf0e8f6022..9a605393658 100644 --- a/PWGHF/D2H/Tasks/taskLb.cxx +++ b/PWGHF/D2H/Tasks/taskLb.cxx @@ -72,7 +72,7 @@ struct HfTaskLb { Configurable largeLifetimeBG{"largeLifetimeBG", 0.01, "fraction of strange contribution within 2mm"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lb_to_lc_pi::vecBinsPt}, "pT bin limits"}; - Service pdg; + Service pdg{}; using TracksWExt = soa::Join; using TracksWExtMc = soa::Join; diff --git a/PWGHF/D2H/Tasks/taskLbReduced.cxx b/PWGHF/D2H/Tasks/taskLbReduced.cxx index b8ba64cb42a..fe43e8d2c6e 100644 --- a/PWGHF/D2H/Tasks/taskLbReduced.cxx +++ b/PWGHF/D2H/Tasks/taskLbReduced.cxx @@ -150,13 +150,13 @@ DECLARE_SOA_TABLE(HfRedCandLbLites, "AOD", "HFREDCANDLBLITE", //! Table with som hf_cand_lb_lite::NSigTofPiBachelor, hf_cand_lb_lite::NSigTpcTofPiBachelor, // MC truth - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_lb_lite::FlagWrongCollision, hf_cand_lb_lite::PtGen); DECLARE_SOA_TABLE(HfRedLbMcCheck, "AOD", "HFREDLBMCCHECK", //! Table with MC decay type check - hf_cand_3prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, hf_cand_lb_lite::FlagWrongCollision, hf_cand_lb_lite::MLc, hf_cand_lb_lite::PtLc, diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index 794e49aa322..bd29b00c868 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -30,6 +30,7 @@ #include "PWGHF/DataModel/TrackIndexSkimmingTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsUpcHf.h" +#include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCHelpers.h" #include "Common/Core/RecoDecay.h" @@ -77,6 +78,7 @@ struct HfTaskLc { Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; // ThnSparse for ML outputScores and Vars Configurable fillTHn{"fillTHn", false, "fill THn"}; + Configurable fillUPCTHnLite{"fillUPCTHnLite", false, "fill THn"}; Configurable storeOccupancy{"storeOccupancy", true, "Flag to store occupancy information"}; Configurable occEstimator{"occEstimator", 2, "Occupancy estimation (None: 0, ITS: 1, FT0C: 2)"}; Configurable storeProperLifetime{"storeProperLifetime", false, "Flag to store proper lifetime"}; @@ -88,7 +90,7 @@ struct HfTaskLc { HfEventSelection hfEvSel; // event selection and monitoring HfUpcGapThresholds upcThresholds; // UPC gap determination thresholds SliceCache cache; - Service ccdb; + Service ccdb{}; using Collisions = soa::Join; using CollisionsMc = soa::Join; @@ -125,10 +127,10 @@ struct HfTaskLc { ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for centrality"}; ConfigurableAxis thnConfigAxisProperLifetime{"thnConfigAxisProperLifetime", {200, 0, 2}, "Proper lifetime, ps"}; ConfigurableAxis thnConfigAxisGapType{"thnConfigAxisGapType", {7, -1.5, 5.5}, "axis for UPC gap type (see TrueGap enum in o2::aod::sgselector)"}; + ConfigurableAxis thnConfigAxisFV0A{"thnConfigAxisFV0A", {1001, -1.5, 999.5}, "axis for FV0-A amplitude (a.u.)"}; ConfigurableAxis thnConfigAxisFT0{"thnConfigAxisFT0", {1001, -1.5, 999.5}, "axis for FT0 amplitude (a.u.)"}; - ConfigurableAxis thnConfigAxisFV0A{"thnConfigAxisFV0A", {2001, -1.5, 1999.5}, "axis for FV0-A amplitude (a.u.)"}; - ConfigurableAxis thnConfigAxisFDD{"thnConfigAxisFDD", {200, 0., 4000.}, "axis for FDD amplitude (a.u.)"}; ConfigurableAxis thnConfigAxisZN{"thnConfigAxisZN", {510, -1.5, 49.5}, "axis for ZN energy (a.u.)"}; + ConfigurableAxis thnConfigAxisZNTime{"thnConfigAxisZNTime", {200, -10, 10}, "axis for ZN energy (a.u.)"}; HistogramRegistry registry{"registry", {}}; HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -264,9 +266,12 @@ struct HfTaskLc { addHistogramsRec("hDecLenErrVsPt", "decay length error (cm)", "#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 1.}, {vbins}}}); if (isUpc) { - qaRegistry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{1500, 0., 1500}, {1500, 0., 1500}}}); - qaRegistry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{200, 0., 20}, {200, 0., 20}}}); + qaRegistry.add("Data/fitInfo/ampFT0A_vs_ampFT0C", "FT0-A vs FT0-C amplitude;FT0-A amplitude (a.u.);FT0-C amplitude (a.u.)", {HistType::kTH2F, {{500, 0., 500}, {500, 0., 500}}}); + qaRegistry.add("Data/zdc/energyZNA_vs_energyZNC", "ZNA vs ZNC common energy;E_{ZNA}^{common} (a.u.);E_{ZNC}^{common} (a.u.)", {HistType::kTH2F, {{100, 0., 10}, {100, 0., 10}}}); + qaRegistry.add("Data/zdc/timeZNA_vs_timeZNC", "ZNA vs ZNC time;ZNA Time;ZNC time", {HistType::kTH2F, {{200, -10., 10}, {200, -10., 10}}}); qaRegistry.add("Data/hUpcGapAfterSelection", "UPC gap type after selection;Gap side;Counts", {HistType::kTH1F, {{7, -1.5, 5.5}}}); + qaRegistry.add("Data/hUpcMulti", "Multiplicity of UPC events;Multiplicity;Counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + qaRegistry.add("Data/hUpcVtz", "Vertex Z position of UPC events;Vz (cm);Counts", {HistType::kTH1F, {{200, -10., 10.}}}); } if (fillTHn) { const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; @@ -287,14 +292,13 @@ struct HfTaskLc { const AxisSpec thnAxisTracklets{thnConfigAxisNumPvContr, "Number of PV contributors"}; const AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, "Occupancy"}; const AxisSpec thnAxisProperLifetime{thnConfigAxisProperLifetime, "T_{proper} (ps)"}; - const AxisSpec thnAxisGapType{thnConfigAxisGapType, "Gap type"}; + const AxisSpec thnAxisFV0A{thnConfigAxisFV0A, "FV0-A amplitude"}; const AxisSpec thnAxisFT0A{thnConfigAxisFT0, "FT0-A amplitude"}; const AxisSpec thnAxisFT0C{thnConfigAxisFT0, "FT0-C amplitude"}; - const AxisSpec thnAxisFV0A{thnConfigAxisFV0A, "FV0-A amplitude"}; - const AxisSpec thnAxisFDDA{thnConfigAxisFDD, "FDD-A amplitude"}; - const AxisSpec thnAxisFDDC{thnConfigAxisFDD, "FDD-C amplitude"}; const AxisSpec thnAxisZNA{thnConfigAxisZN, "ZNA energy"}; const AxisSpec thnAxisZNC{thnConfigAxisZN, "ZNC energy"}; + const AxisSpec thnAxisZNATime{thnConfigAxisZNTime, "ZNA time"}; + const AxisSpec thnAxisZNCTime{thnConfigAxisZNTime, "ZNC time"}; bool const isDataWithMl = doprocessDataWithMl || doprocessDataWithMlWithFT0C || doprocessDataWithMlWithFT0M || doprocessDataWithMlWithUpc; bool const isMcWithMl = doprocessMcWithMl || doprocessMcWithMlWithFT0C || doprocessMcWithMlWithFT0M; @@ -307,7 +311,7 @@ struct HfTaskLc { axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets}; } if (isDataStd && isUpc) { - axesUpc = {thnAxisMass, thnAxisPt, thnAxisRapidity, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisGapType, thnAxisFT0A, thnAxisFT0C, thnAxisFV0A, thnAxisFDDA, thnAxisFDDC, thnAxisZNA, thnAxisZNC}; + axesUpc = {thnAxisMass, thnAxisPt, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisFV0A, thnAxisFT0A, thnAxisFT0C, thnAxisZNA, thnAxisZNC, thnAxisZNATime, thnAxisZNCTime}; } if (isMcStd) { axesStd = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisPtProng0, thnAxisPtProng1, thnAxisPtProng2, thnAxisChi2PCA, thnAxisDecLength, thnAxisCPA, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; @@ -319,7 +323,7 @@ struct HfTaskLc { axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets}; } if (isDataWithMl && isUpc) { - axesUpcWithBdt = {thnAxisMass, thnAxisPt, thnAxisRapidity, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisGapType, thnAxisFT0A, thnAxisFT0C, thnAxisFV0A, thnAxisFDDA, thnAxisFDDC, thnAxisZNA, thnAxisZNC}; + axesUpcWithBdt = {thnAxisMass, thnAxisPt, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisFV0A, thnAxisFT0A, thnAxisFT0C, thnAxisZNA, thnAxisZNC, thnAxisZNATime, thnAxisZNCTime}; } if (isMcWithMl) { axesWithBdt = {thnAxisMass, thnAxisPt, thnAxisCentrality, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcPrompt, thnAxisBdtScoreLcNonPrompt, thnAxisTracklets, thnAxisPtB, thnAxisCanType}; @@ -767,13 +771,18 @@ struct HfTaskLc { const bool hasZdc = bcForUPC.has_zdc(); float zdcEnergyZNA = -1.f; float zdcEnergyZNC = -1.f; + float zdcTimeZNA = -1.f; + float zdcTimeZNC = -1.f; if (hasZdc) { const auto zdc = bcForUPC.zdc(); zdcEnergyZNA = zdc.energyCommonZNA(); zdcEnergyZNC = zdc.energyCommonZNC(); + zdcTimeZNA = zdc.timeZNA(); + zdcTimeZNC = zdc.timeZNC(); qaRegistry.fill(HIST("Data/fitInfo/ampFT0A_vs_ampFT0C"), fitInfo.ampFT0A, fitInfo.ampFT0C); qaRegistry.fill(HIST("Data/zdc/energyZNA_vs_energyZNC"), zdcEnergyZNA, zdcEnergyZNC); + qaRegistry.fill(HIST("Data/zdc/timeZNA_vs_timeZNC"), zdcTimeZNA, zdcTimeZNC); qaRegistry.fill(HIST("Data/hUpcGapAfterSelection"), static_cast(gap)); } for (const auto& candidate : groupedLcCandidates) { @@ -790,7 +799,10 @@ struct HfTaskLc { const auto decayLength = candidate.decayLength(); const auto chi2PCA = candidate.chi2PCA(); const auto cpa = candidate.cpa(); - const auto rapidity = HfHelper::yLc(candidate); + if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { + qaRegistry.fill(HIST("Data/hUpcMulti"), collision.multNTracksPV()); + qaRegistry.fill(HIST("Data/hUpcVtz"), collision.posZ()); + } if (fillTHn) { double outputBkg(-1), outputPrompt(-1), outputFD(-1); @@ -806,11 +818,26 @@ struct HfTaskLc { outputFD = mlProb[MlClassNonPrompt]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate - std::vector valuesToFill{massLc, pt, rapidity, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), static_cast(gap), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFDDA), static_cast(fitInfo.ampFDDC), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC)}; - registry.get(HIST("hnLcUpcVarsWithBdt"))->Fill(valuesToFill.data()); + if (fillUPCTHnLite) { + if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { + std::vector valuesToFill{massLc, pt, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; + registry.get(HIST("hnLcUpcVarsWithBdt"))->Fill(valuesToFill.data()); + } + } else { + std::vector valuesToFill{massLc, pt, outputBkg, outputPrompt, outputFD, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; + registry.get(HIST("hnLcUpcVarsWithBdt"))->Fill(valuesToFill.data()); + } + } else { - std::vector valuesToFill{massLc, pt, rapidity, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), static_cast(gap), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFDDA), static_cast(fitInfo.ampFDDC), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC)}; - registry.get(HIST("hnLcUpcVars"))->Fill(valuesToFill.data()); + if (fillUPCTHnLite) { + if (gap == o2::aod::sgselector::TrueGap::SingleGapA || gap == o2::aod::sgselector::TrueGap::SingleGapC) { + std::vector valuesToFill{massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; + registry.get(HIST("hnLcUpcVars"))->Fill(valuesToFill.data()); + } + } else { + std::vector valuesToFill{massLc, pt, ptProng0, ptProng1, ptProng2, chi2PCA, decayLength, cpa, static_cast(numPvContributors), static_cast(fitInfo.ampFV0A), static_cast(fitInfo.ampFT0A), static_cast(fitInfo.ampFT0C), static_cast(zdcEnergyZNA), static_cast(zdcEnergyZNC), static_cast(zdcTimeZNA), static_cast(zdcTimeZNC)}; + registry.get(HIST("hnLcUpcVars"))->Fill(valuesToFill.data()); + } } }; @@ -888,7 +915,7 @@ struct HfTaskLc { } PROCESS_SWITCH(HfTaskLc, processDataWithMlWithFT0M, "Process real data with the ML method and with FT0M centrality", false); - void processDataWithMlWithUpc(soa::Join const& collisions, + void processDataWithMlWithUpc(soa::Join const& collisions, aod::BcFullInfos const& bcs, LcCandidatesMl const& selectedLcCandidatesMl, aod::Tracks const&, @@ -901,7 +928,7 @@ struct HfTaskLc { } PROCESS_SWITCH(HfTaskLc, processDataWithMlWithUpc, "Process real data with the ML method with UPC", false); - void processDataStdWithUpc(soa::Join const& collisions, + void processDataStdWithUpc(soa::Join const& collisions, aod::BcFullInfos const& bcs, LcCandidatesMl const& selectedLcCandidatesMl, aod::Tracks const&, diff --git a/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx b/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx index 23cd80e4d00..c2d0ed06dcd 100644 --- a/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx +++ b/PWGHF/D2H/Tasks/taskOmegac0ToOmegaPi.cxx @@ -91,8 +91,8 @@ struct HfTaskOmegac0ToOmegaPi { using McCollisionsWithFT0M = soa::Join; Filter filterOmegaCToOmegaPiFlag = (aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi))) != static_cast(0); - Filter filterOmegaCMatchedRec = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); - Filter filterOmegaCMatchedGen = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); + Filter filterOmegaCMatchedRec = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); + Filter filterOmegaCMatchedGen = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi)); Preslice candOmegacKFPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candOmegacKFMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; diff --git a/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx new file mode 100644 index 00000000000..d0695616c84 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskPtFlucCharmHadrons.cxx @@ -0,0 +1,405 @@ +// 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 taskPtFlucCharmHadrons.cxx +/// \brief Analysis task for charm hadron pt fluctuation +/// +/// \author Prottay Das, prottay.das@cern.ch + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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, + D0ToPiK, + D0ToKPi }; + +struct HfTaskPtFlucCharmHadrons { + 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 centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP computation"}; + Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP computation"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> classMl{"classMl", {0, 2}, "Indices of BDT scores to be stored. Two indexes max."}; + + Configurable cfgITScluster{"cfgITScluster", 5, "Number of ITS cluster"}; + Configurable cfgITSbarrel{"cfgITSbarrel", 1, "Number of ITS inner barrel"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 0.1f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 0.1f, "DCAz range for tracks"}; + + // Event selection + // Mean-pT (charged hadrons) definition: subevents with eta gap + Configurable etaAMin{"etaAMin", -0.8f, "A: negative eta min"}; + Configurable etaAMax{"etaAMax", 0.0f, "A: negative eta max (0)"}; + Configurable etaBMin{"etaBMin", 0.4f, "B: positive eta min (eta_min)"}; // or set from etaMinGap in code + Configurable etaBMax{"etaBMax", 0.8f, "B: positive eta max"}; + + Configurable ptTrkMin{"ptTrkMin", 0.2f, "Track pT min for (charged hadrons)"}; + Configurable ptTrkMax{"ptTrkMax", 2.0f, "Track pT max for (charged hadrons)"}; + Configurable ptTrkMinD{"ptTrkMinD", 0.2f, "Track pT min for D"}; + Configurable ptTrkMaxD{"ptTrkMaxD", 2.0f, "Track pT max for D"}; + Configurable minNTrk{"minNTrk", 5, "Min charged tracks in each subevent to compute "}; + + // Use ML in denominator AND numerator consistently + Configurable applyMlCut{"applyMlCut", true, "Apply ML window for candidate selection (also in ND denominator)"}; + + // ML window (assumes you store 2 ML outputs: classMl[0], classMl[1]) + Configurable mlOneMin{"mlOneMin", 0.f, "ML1 min"}; + Configurable mlOneMax{"mlOneMax", 1.f, "ML1 max"}; + Configurable mlTwoMin{"mlTwoMin", 0.f, "ML2 min"}; + Configurable mlTwoMax{"mlTwoMax", 1.f, "ML2 max"}; + + // Optional: require D candidate to be in subevent A acceptance (recommended for long-range) + Configurable requireCandInA{"requireCandInA", true, "Require D candidate eta inside subevent A window"}; + + SliceCache cache; + HfEventSelection hfEvSel; // event selection and monitoring + o2::framework::Service ccdb; + + using CandDplusDataWMl = soa::Filtered>; + using CandD0DataWMl = soa::Filtered>; + using Colls = soa::Join; + using TracksWithExtra = soa::Join; + + Filter filterSelectDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlag; + Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; + + Partition selectedD0ToPiKWMl = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag; + Partition selectedD0ToKPiWMl = aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; + + // ------------------------- + // Axes / histograms + // ------------------------- + ConfigurableAxis axisInvMass{"axisInvMass", {100, 1.78, 2.05}, "Inv mass axis"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.5, 8.0, 10.0}, "Candidate pT axis"}; + ConfigurableAxis axisCent{"axisCent", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Centrality axis"}; + ConfigurableAxis axisSign{"axisSign", {VARIABLE_WIDTH, -1.0, 1.0}, "Sign axis"}; + ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""}; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + + /// check process functions + std::array processes = {doprocessDplusMl, doprocessD0Ml}; + 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"); + } else if (nProcesses == 0) { + LOGP(fatal, "No process function enabled"); + } + + const AxisSpec aInvMass{axisInvMass, "Inv. mass (GeV/#it{c}^{2})"}; + const AxisSpec aPt{axisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec aCent{axisCent, "Centrality"}; + const AxisSpec aSign{axisSign, "Sign"}; + const AxisSpec thnAxisMlOne{thnConfigAxisMlOne, "Bkg score"}; + const AxisSpec thnAxisMlTwo{thnConfigAxisMlTwo, "FD score"}; + + // Event-level accumulators (charged hadrons only!) + registry.add("hEvents", "events vs cent", HistType::kTH1F, {aCent}, true); + registry.add("hEventsD", "eventsD vs cent", HistType::kTH1F, {aCent}, true); + // These are sufficient to compute sigma_ offline in each centrality bin. + registry.add("pMeanPtA", "<[pT]_A> vs cent (charged hadrons)", HistType::kTProfile, {aCent}, true); + registry.add("pMeanPtB", "<[pT]_B> vs cent (charged hadrons)", HistType::kTProfile, {aCent}, true); + registry.add("pMeanPtAmeanPtB", "<[pT]_A*[pT]_B> vs cent (charged hadrons)", HistType::kTProfile, {aCent}, true); + + // QA: multiplicities in A/B + registry.add("pNA", " vs cent (charged hadrons)", HistType::kTProfile, {aCent}, true); + registry.add("pNB", " vs cent (charged hadrons)", HistType::kTProfile, {aCent}, true); + + // Candidate mass distributions + registry.add("hD_mass", "D candidate mass (weight=1)", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, thnAxisMlOne, thnAxisMlTwo}, true); + registry.add("hD_f", "hD_f", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, thnAxisMlOne, thnAxisMlTwo}, true); + registry.add("hD_f_wPtB", "hD_f_wPtB", HistType::kTHnSparseF, {aInvMass, aCent, aPt, aSign, thnAxisMlOne, thnAxisMlTwo}, true); + + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + }; // end init + + /// Get the centrality + /// \param collision is the collision with the centrality information + double getCentrality(Colls::iterator const& collision) + { + double cent = -999.; + switch (centEstimator) { + case CentralityEstimator::FV0A: + cent = collision.centFV0A(); + break; + case CentralityEstimator::FT0M: + cent = collision.centFT0M(); + break; + case CentralityEstimator::FT0A: + cent = collision.centFT0A(); + break; + case CentralityEstimator::FT0C: + cent = collision.centFT0C(); + break; + default: + LOG(warning) << "Centrality estimator not valid. Possible values are V0A, T0M, T0A, T0C. Fallback to V0A"; + cent = collision.centFV0A(); + break; + } + return cent; + } + + template + bool selectionTrack(const T& candidate) const + { + if (!(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster.value && candidate.tpcNClsFound() > cfgTPCcluster.value && candidate.itsNClsInnerBarrel() >= cfgITSbarrel.value && std::abs(candidate.dcaXY()) < cfgCutDCAxy.value && std::abs(candidate.dcaZ()) < cfgCutDCAz.value)) { + return false; + } + return true; + } + + // ------------------------- + // Event-wise mean pT from charged hadron tracks + // ------------------------- + template + std::pair computeMeanPtCharged(Trk const& tracks, float etaMin, float etaMax) const + { + double sumPt = 0.0; + int n = 0; + + for (const auto& trk : tracks) { + if (!selectionTrack(trk)) { + continue; + } + float eta = trk.eta(); + if (eta <= etaMin || eta >= etaMax) { + continue; + } + float pt = trk.pt(); + if (pt < ptTrkMin.value || pt >= ptTrkMax.value) { + continue; + } + sumPt += pt; + ++n; + } + + if (n < minNTrk.value) { + return {std::numeric_limits::quiet_NaN(), n}; + } + return {static_cast(sumPt / n), n}; + } + + // Helper: candidate eta-in-A cut + template + bool passCandInA(const Cand& cand) const + { + if (!requireCandInA.value) { + return true; + } + const float eta = cand.eta(); + return (eta > etaAMin.value && eta < etaAMax.value); + } + + template + std::array getMlScores(const Cand& cand) const + { + float ml1 = -999.f; + float ml2 = -999.f; + + if constexpr (std::is_same_v) { + // D+ + const auto& probs = cand.mlProbDplusToPiKPi(); + ml1 = probs[classMl->at(0)]; + ml2 = probs[classMl->at(1)]; + } else { + // D0 / D0bar depends on Channel + if constexpr (Channel == DecayChannel::D0ToPiK) { + const auto& probs = cand.mlProbD0(); + ml1 = probs[classMl->at(0)]; + ml2 = probs[classMl->at(1)]; + } else if constexpr (Channel == DecayChannel::D0ToKPi) { + const auto& probs = cand.mlProbD0bar(); + ml1 = probs[classMl->at(0)]; + ml2 = probs[classMl->at(1)]; + } + } + + return {ml1, ml2}; + } + + inline bool passMlCut(float ml1, float ml2) const + { + if (!applyMlCut.value) { + return true; + } + return (ml1 >= mlOneMin.value && ml1 < mlOneMax.value && + ml2 >= mlTwoMin.value && ml2 < mlTwoMax.value); + } + + /// Compute the scalar product + /// \param collision is the collision with the Q vector information and event plane + /// \param candidates are the selected candidates + template + void runPtFlucAnalysis(Colls::iterator const& collision, + T1 const& candidates, + Trk const& tracks) + { + float cent = getCentrality(collision); + if (cent < centralityMin || cent > centralityMax) { + return; + } + + // Compute in two eta-separated subevents using CHARGED tracks only + auto [meanPtA, nA] = computeMeanPtCharged(tracks, etaAMin.value, etaAMax.value); + auto [meanPtB, nB] = computeMeanPtCharged(tracks, etaBMin.value, etaBMax.value); + + // QA + registry.fill(HIST("pNA"), cent, static_cast(nA)); + registry.fill(HIST("pNB"), cent, static_cast(nB)); + + if (!std::isfinite(meanPtA) || !std::isfinite(meanPtB)) { + return; + } + + registry.fill(HIST("hEvents"), cent, 1.f); + + registry.fill(HIST("pMeanPtA"), cent, meanPtA); + registry.fill(HIST("pMeanPtB"), cent, meanPtB); + registry.fill(HIST("pMeanPtAmeanPtB"), cent, meanPtA * meanPtB); + + int nDcandTotA = 0; + + for (const auto& cand : candidates) { + if (!passCandInA(cand)) { + continue; + } + + // compute ML exactly like numerator + const auto [ml1, ml2] = getMlScores(cand); + + // apply same ML cut + if (!passMlCut(ml1, ml2)) { + continue; + } + float pt = cand.pt(); + if (pt < ptTrkMinD.value || pt >= ptTrkMaxD.value) { + continue; + } + + ++nDcandTotA; + } + + if (nDcandTotA <= 0) { + return; // cannot build fraction + } + + registry.fill(HIST("hEventsD"), cent, 1.f); + const float invND = 1.f / static_cast(nDcandTotA); + + for (const auto& candidate : candidates) { + if (!passCandInA(candidate)) { + continue; + } + + // ML first (same definition) + const auto [ml1, ml2] = getMlScores(candidate); + if (!passMlCut(ml1, ml2)) { + continue; + } + + // compute mass + float massCand = 0.; + float signCand = 0.; + if constexpr (std::is_same_v) { + massCand = HfHelper::invMassDplusToPiKPi(candidate); + auto trackprong0 = candidate.template prong0_as(); + signCand = trackprong0.sign(); + } else { + if constexpr (Channel == DecayChannel::D0ToPiK) { + massCand = HfHelper::invMassD0ToPiK(candidate); + signCand = candidate.isSelD0bar() ? 3 : 1; // 3: reflected D0bar, 1: pure D0 excluding reflected D0bar + } else if constexpr (Channel == DecayChannel::D0ToKPi) { + massCand = HfHelper::invMassD0barToKPi(candidate); + signCand = candidate.isSelD0() ? 3 : 2; // 3: reflected D0, 2: pure D0bar excluding reflected D0 + } + } + + const double ptCand = candidate.pt(); + if (ptCand < ptTrkMinD.value || ptCand >= ptTrkMaxD.value) { + continue; + } + + registry.fill(HIST("hD_mass"), massCand, cent, ptCand, signCand, ml1, ml2, 1.f); + registry.fill(HIST("hD_f"), massCand, cent, ptCand, signCand, ml1, ml2, invND); + registry.fill(HIST("hD_f_wPtB"), massCand, cent, ptCand, signCand, ml1, ml2, meanPtB * invND); + } + } + + // D0 with ML + void processD0Ml(Colls::iterator const& collision, + CandD0DataWMl const& /*candidatesD0*/, + TracksWithExtra const& tracks) + { + auto candsD0ToPiKWMl = selectedD0ToPiKWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto candsD0ToKPiWMl = selectedD0ToKPiWMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runPtFlucAnalysis(collision, candsD0ToPiKWMl, tracks); + runPtFlucAnalysis(collision, candsD0ToKPiWMl, tracks); + } + PROCESS_SWITCH(HfTaskPtFlucCharmHadrons, processD0Ml, "Process D0 candidates with ML", false); + + // Dplus with ML + void processDplusMl(Colls::iterator const& collision, + CandDplusDataWMl const& candidatesDplus, + TracksWithExtra const& tracks) + { + runPtFlucAnalysis(collision, candidatesDplus, tracks); + } + PROCESS_SWITCH(HfTaskPtFlucCharmHadrons, processDplusMl, "Process Dplus candidates with ML", true); + +}; // End struct HfTaskPtFlucCharmHadrons + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index 5c4db44eb42..8bfbff280cb 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -62,8 +62,10 @@ struct HfTaskSigmac { /// consider the new parametrization of the fiducial acceptance (to be seen for reco signal in MC) Configurable yCandGenMax{"yCandGenMax", -1, "Maximum generated Sc rapidity"}; Configurable yCandRecoMax{"yCandRecoMax", -1, "Maximum Sc candidate rapidity"}; - Configurable enableTHn{"enableTHn", false, "enable the usage of THn for Λc+ and Σc0,++"}; - Configurable addSoftPiDcaToSigmacSparse{"addSoftPiDcaToSigmacSparse", false, "enable the filling of sof-pion dcaXY, dcaZ in the Σc0,++ THnSparse"}; + Configurable enableTHnSc{"enableTHnSc", false, "enable the usage of THn for Σc0,++"}; + Configurable enableTHnLc{"enableTHnLc", false, "enable the usage of THn for Λc+"}; + Configurable addSoftPiDcaToSigmacSparse{"addSoftPiDcaToSigmacSparse", false, "enable the filling of soft-pion dcaXY, dcaZ in the Σc0,++ THnSparse"}; + Configurable addMassDiffAbsLambdaCToSigmacSparse{"addMassDiffAbsLambdaCToSigmacSparse", false, "enable the filling of |M(pkpi, piKp) - M(LambdaC)| in the Σc0,++ THnSparse"}; Configurable deltaMassSigmacRecoMax{"deltaMassSigmacRecoMax", 1000, "Maximum allowed value for Sigmac deltaMass. Conceived to reduce the output size (i.e. reject background above a certain threshold)"}; bool isMc{}; @@ -84,6 +86,7 @@ struct HfTaskSigmac { ConfigurableAxis thnConfigAxisBdtScoreLcBkg{"thnConfigAxisBdtScoreLcBkg", {100, 0., 1.}, ""}; ConfigurableAxis thnConfigAxisBdtScoreLcNonPrompt{"thnConfigAxisBdtScoreLcNonPrompt", {100, 0., 1.}, ""}; ConfigurableAxis thnConfigAxisSoftPiAbsDca{"thnConfigAxisSoftPiAbsDca", {14, 0., 0.07}, ""}; + ConfigurableAxis thnConfigAxisMassDiffAbsLambdaC{"thnConfigAxisMassDiffAbsLambdaC", {12, 0, 0.06}, ""}; /// analysis histograms HistogramRegistry registry{ @@ -176,6 +179,7 @@ struct HfTaskSigmac { const AxisSpec thnAxisGenSigmaCSpecies = {o2::aod::hf_cand_sigmac::Species::NSpecies, -0.5f, +o2::aod::hf_cand_sigmac::Species::NSpecies - 0.5f, "bin 1: #Sigma_{c}(2455), bin 2: #Sigma_{c}(2520)"}; const AxisSpec thnAxisSigmaCParticleAntiparticle = {o2::aod::hf_cand_sigmac::Conjugated::NConjugated, -0.5f, +o2::aod::hf_cand_sigmac::Conjugated::NConjugated - 0.5f, "bin 1: particle, bin 2: antiparticle"}; const AxisSpec axisDeltaMassSigmaC{configAxisDeltaMassSigmaC, "#it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisMassDiffAbsLambdaC{thnConfigAxisMassDiffAbsLambdaC, "|#it{M}(pK#pi or piK#pi) - #it{M}(#Lambda_{c})| (GeV/#it{c}^{2})"}; registry.add("Data/hDeltaMassSc0", "#Sigma_{c}^{0} candidates; #it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{0}) (GeV/#it{c});", {HistType::kTH2D, {axisDeltaMassSigmaC, {36, 0., 36.}}}); registry.add("Data/hDeltaMassScPlusPlus", "#Sigma_{c}^{++} candidates; #it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{++}) (GeV/#it{c});", {HistType::kTH2D, {axisDeltaMassSigmaC, {36, 0., 36.}}}); registry.add("Data/hDeltaMassSc0PlusPlus", "#Sigma_{c}^{0,++} candidates; #it{M}(pK#pi#pi) - #it{M}(pK#pi) (GeV/#it{c}^{2}); #it{p}_{T}(#Sigma_{c}^{0,++}) (GeV/#it{c});", {HistType::kTH2D, {axisDeltaMassSigmaC, {36, 0., 36.}}}); @@ -286,7 +290,7 @@ struct HfTaskSigmac { } /// THn for candidate Λc+ and Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc || enableTHnLc) { std::vector axesLambdaCWithMl = {thnAxisPtLambdaC, thnAxisMassLambdaC, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcNonPrompt, thnAxisOriginMc, thnAxisChannel}; std::vector axesSigmaCWithMl = {thnAxisPtLambdaC, axisDeltaMassSigmaC, thnAxisBdtScoreLcBkg, thnAxisBdtScoreLcNonPrompt, thnAxisOriginMc, thnAxisChannel, thnAxisPtSigmaC, thnAxisChargeSigmaC}; std::vector axesLambdaCWoMl = {thnAxisPtLambdaC, thnAxisMassLambdaC, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisCPAXY, thnAxisOriginMc, thnAxisChannel}; @@ -303,8 +307,17 @@ struct HfTaskSigmac { axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaXY); axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaZ); } - registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); - registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); + if (addMassDiffAbsLambdaCToSigmacSparse) { + axesSigmaCWithMl.push_back(thnAxisMassDiffAbsLambdaC); + } + // enable THnSparse for Λc+ + if (enableTHnLc) { + registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); + } + // enable THnSparse for Σc0,++ + if (enableTHnSc) { + registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); + } } else { axesLambdaCWoMl.push_back(thnAxisGenPtLambdaCBMother); axesSigmaCWoMl.push_back(thnAxisGenPtSigmaCBMother); @@ -314,8 +327,17 @@ struct HfTaskSigmac { axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaXY); axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaZ); } - registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWoMl); - registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWoMl); + if (addMassDiffAbsLambdaCToSigmacSparse) { + axesSigmaCWoMl.push_back(thnAxisMassDiffAbsLambdaC); + } + // enable THnSparse for Λc+ + if (enableTHnLc) { + registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); + } + // enable THnSparse for Σc0,++ + if (enableTHnSc) { + registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); + } } } else { if (doprocessDataWithMl) { @@ -323,15 +345,33 @@ struct HfTaskSigmac { axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaXY); axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaZ); } - registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); - registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); + if (addMassDiffAbsLambdaCToSigmacSparse) { + axesSigmaCWithMl.push_back(thnAxisMassDiffAbsLambdaC); + } + // enable THnSparse for Λc+ + if (enableTHnLc) { + registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); + } + // enable THnSparse for Σc0,++ + if (enableTHnSc) { + registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); + } } else { if (addSoftPiDcaToSigmacSparse) { axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaXY); axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaZ); } - registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWoMl); - registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWoMl); + if (addMassDiffAbsLambdaCToSigmacSparse) { + axesSigmaCWoMl.push_back(thnAxisMassDiffAbsLambdaC); + } + // enable THnSparse for Λc+ + if (enableTHnLc) { + registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); + } + // enable THnSparse for Σc0,++ + if (enableTHnSc) { + registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); + } } } } @@ -364,7 +404,7 @@ struct HfTaskSigmac { // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ const int8_t isCandPKPiPiKP = hf_sigmac_utils::isDecayToPKPiToPiKP(candidateLc, candSc); - double massSc(-1.), massLc(-1.), deltaMass(-1.); + double massSc(-1.), massLc(-1.), deltaMass(-1.), massDiffAbsFromPdgLc(-1.); double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); @@ -375,6 +415,7 @@ struct HfTaskSigmac { if (TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) { massSc = HfHelper::invMassScRecoLcToPKPi(candSc, candidateLc); massLc = HfHelper::invMassLcToPKPi(candidateLc); + massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPKPi(candidateLc)); deltaMass = massSc - massLc; if (deltaMass > deltaMassSigmacRecoMax) { @@ -431,7 +472,7 @@ struct HfTaskSigmac { registry.fill(HIST("Data/hDeltaMassLcFromSc0PlusPlus"), deltaMass, ptLc); // Λc+ ← Σc0,++ } /// THn for candidate Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc) { if (!isMc) { /// fill it only if no MC operations are enabled, otherwise fill it in the processMC with the right origin and channel! const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); @@ -445,25 +486,62 @@ struct HfTaskSigmac { outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + } } } else { /// fill w/o BDT information if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + } } } - } - } + } /// end if (!isMc) + } /// end enableTHn } /// end candidate Λc+ → pK-π+ (and charge conjugate) /// candidate Λc+ → π+K-p (and charge conjugate) within the range of M(π+K-p) chosen in the Σc0,++ builder if (TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) { massSc = HfHelper::invMassScRecoLcToPiKP(candSc, candidateLc); massLc = HfHelper::invMassLcToPiKP(candidateLc); + massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPiKP(candidateLc)); deltaMass = massSc - massLc; if (deltaMass > deltaMassSigmacRecoMax) { @@ -520,7 +598,7 @@ struct HfTaskSigmac { registry.fill(HIST("Data/hDeltaMassLcFromSc0PlusPlus"), deltaMass, ptLc); // Λc+ ← Σc0,++ } /// THn for candidate Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc) { if (!isMc) { /// fill it only if no MC operations are enabled, otherwise fill it in the processMC with the right origin and channel! const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); @@ -534,25 +612,61 @@ struct HfTaskSigmac { outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + } } } else { /// fill w/o BDT information if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + } } } - } - } + } /// end if (!isMc) + } /// end enableTHn } /// end candidate Λc+ → π+K-p (and charge conjugate) } /// end loop over the candidate Σc0,++ /// THn for candidate Λc+ cut variation w/o Σc0,++ mass-window cut - if (enableTHn) { + if (enableTHnLc) { /// fill it only if no MC operations are enabled, otherwise fill it in the processMC with the right origin and channel! if (!isMc) { /// loop over Λc+ candidates w/o Σc0,++ mass-window cut @@ -874,7 +988,7 @@ struct HfTaskSigmac { // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ - double massSc(-1.), massLc(-1.), deltaMass(-1.); + double massSc(-1.), massLc(-1.), deltaMass(-1.), massDiffAbsFromPdgLc(-1.); double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); @@ -890,6 +1004,7 @@ struct HfTaskSigmac { if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { massSc = HfHelper::invMassScRecoLcToPKPi(candSc, candidateLc); massLc = HfHelper::invMassLcToPKPi(candidateLc); + massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPKPi(candidateLc)); deltaMass = massSc - massLc; if (deltaMass > deltaMassSigmacRecoMax) { @@ -948,7 +1063,7 @@ struct HfTaskSigmac { } /// THn for candidate Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc) { int8_t const particleAntiparticle = candSc.particleAntiparticle(); const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); @@ -961,16 +1076,52 @@ struct HfTaskSigmac { outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } else { /// fill w/o BDT information if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } @@ -980,6 +1131,7 @@ struct HfTaskSigmac { if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kPiPlus) { massSc = HfHelper::invMassScRecoLcToPiKP(candSc, candidateLc); massLc = HfHelper::invMassLcToPiKP(candidateLc); + massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPiKP(candidateLc)); deltaMass = massSc - massLc; if (deltaMass > deltaMassSigmacRecoMax) { @@ -1038,7 +1190,7 @@ struct HfTaskSigmac { } /// THn for candidate Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc) { int8_t const particleAntiparticle = candSc.particleAntiparticle(); const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); @@ -1051,16 +1203,52 @@ struct HfTaskSigmac { outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } else { /// fill w/o BDT information if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } @@ -1091,7 +1279,7 @@ struct HfTaskSigmac { // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ - double massSc(-1.), massLc(-1.), deltaMass(-1.); + double massSc(-1.), massLc(-1.), deltaMass(-1.), massDiffAbsFromPdgLc(-1.); double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); @@ -1107,6 +1295,7 @@ struct HfTaskSigmac { if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { massSc = HfHelper::invMassScRecoLcToPKPi(candSc, candidateLc); massLc = HfHelper::invMassLcToPKPi(candidateLc); + massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPKPi(candidateLc)); deltaMass = massSc - massLc; if (deltaMass > deltaMassSigmacRecoMax) { @@ -1165,7 +1354,7 @@ struct HfTaskSigmac { } /// THn for candidate Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc) { int8_t const particleAntiparticle = candSc.particleAntiparticle(); const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); @@ -1178,16 +1367,52 @@ struct HfTaskSigmac { outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } else { /// fill w/o BDT information if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } @@ -1197,6 +1422,7 @@ struct HfTaskSigmac { if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kPiPlus) { massSc = HfHelper::invMassScRecoLcToPiKP(candSc, candidateLc); massLc = HfHelper::invMassLcToPiKP(candidateLc); + massDiffAbsFromPdgLc = std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPiKP(candidateLc)); deltaMass = massSc - massLc; if (deltaMass > deltaMassSigmacRecoMax) { @@ -1253,7 +1479,7 @@ struct HfTaskSigmac { } /// THn for candidate Σc0,++ cut variation - if (enableTHn) { + if (enableTHnSc) { int8_t const particleAntiparticle = candSc.particleAntiparticle(); const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); @@ -1266,16 +1492,52 @@ struct HfTaskSigmac { outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } else { /// fill w/o BDT information if (addSoftPiDcaToSigmacSparse) { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + /// dcaXY,Z of soft pion track stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi, massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: dcaXY_softPi, dcaZ_softPi + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } } else { - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + /// dcaXY,Z of soft pion track not stored + if (addMassDiffAbsLambdaCToSigmacSparse) { + /// difference |candidate mass - Lc mass| stored + /// optional axes enabled: massDiffLc + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, massDiffAbsFromPdgLc); + } else { + /// difference |candidate mass - Lc mass| not stored + /// optional axes enabled: none + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } } @@ -1286,7 +1548,7 @@ struct HfTaskSigmac { } /// end loop on reconstructed Σc0,++ /// THn for candidate Λc+ cut variation w/o Σc0,++ mass-window cut - if (enableTHn) { + if (enableTHnLc) { /// loop over Λc+ candidates w/o Σc0,++ mass-window cut for (const auto& candidateLc : candidatesLc) { if (std::abs(candidateLc.flagMcMatchRec()) != hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index b45ba158bf0..46dfdd64521 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -67,7 +67,7 @@ struct HfTaskXic { Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_p_k_pi::vecBinsPt}, "pT bin limits"}; Configurable enableTHn{"enableTHn", false, "enable THn for Xic"}; - Service pdg; + Service pdg{}; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic); diff --git a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx index c9c09f94859..31091e68555 100644 --- a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx @@ -83,8 +83,8 @@ struct HfTaskXic0ToXiPi { using McCollisionsCentFT0Ms = soa::Join; Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections == true; - Filter filterXicMatchedRec = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); - Filter filterXicMatchedGen = nabs(aod::hf_cand_xic0_omegac0::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); + Filter filterXicMatchedRec = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); + Filter filterXicMatchedGen = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi)); Preslice candXicPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candXicKFPerCollision = aod::hf_cand_xic0_omegac0::collisionId; Preslice candXicMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; @@ -165,6 +165,19 @@ struct HfTaskXic0ToXiPi { registry.add("hMassVsPtVsYVsCentVsPtPion", "Thn for Xic0 candidates with Cent&pTpi", HistType::kTHnSparseD, axesWithCent); registry.get(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"))->Sumw2(); registry.get(HIST("hMassVsPtVsYVsCentVsPtPion"))->Sumw2(); + } else { + const AxisSpec thnAxisPromptScore{thnConfigAxisPromptScore, "BDT score prompt."}; + const AxisSpec thnAxisPtPion{thnConfigAxisPtPion, "Pt of Pion from Xic0."}; + std::vector const axesWithBdtWithoutCent = {thnAxisPromptScore, thnAxisMass, thnAxisPt, thnAxisY, thnAxisPtPion, thnConfigAxisNumPvContr}; + std::vector const axesWithoutCent = {thnAxisMass, thnAxisPt, thnAxisY, thnAxisPtPion, thnConfigAxisNumPvContr}; + registry.add("hBdtScoreVsMassVsPtVsYVsPtPion", "Thn for Xic0 candidates with BDT&Cent&pTpi", HistType::kTHnSparseD, axesWithBdtWithoutCent); + registry.add("hMassVsPtVsYVsPtPion", "Thn for Xic0 candidates with Cent&pTpi", HistType::kTHnSparseD, axesWithoutCent); + registry.get(HIST("hBdtScoreVsMassVsPtVsYVsPtPion"))->Sumw2(); + registry.get(HIST("hMassVsPtVsYVsPtPion"))->Sumw2(); + } + + if (yCandRecMax >= 0) { + registry.add("hNumRejCandidate_RapidityCut", "# of rejected candidate using rap cut;Rej;entries", {HistType::kTH1F, {thnAxisY}}); } } @@ -174,13 +187,14 @@ struct HfTaskXic0ToXiPi { if (candidate.resultSelections() != true) { return; } - double yCharmBaryon; + double yCharmBaryon{0.}; if constexpr (UseKfParticle) { yCharmBaryon = candidate.kfRapXic(); } else { yCharmBaryon = candidate.y(o2::constants::physics::MassXiC0); } if (yCandRecMax >= 0. && std::abs(yCharmBaryon) > yCandRecMax) { + registry.fill(HIST("hNumRejCandidate_RapidityCut"), yCharmBaryon); return; } @@ -192,22 +206,41 @@ struct HfTaskXic0ToXiPi { double const ptXic = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); double const ptPiFromXic = RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); if constexpr (ApplyMl) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), - candidate.mlProbToXiPi()[0], - candidate.invMassCharmBaryon(), - ptXic, - yCharmBaryon, - centrality, - ptPiFromXic, - numPvContributors); + if constexpr (UseCentrality) { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + centrality, + ptPiFromXic, + numPvContributors); + } else { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsPtPion"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + ptPiFromXic, + numPvContributors); + } } else { - registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), - candidate.invMassCharmBaryon(), - ptXic, - yCharmBaryon, - centrality, - ptPiFromXic, - numPvContributors); + if constexpr (UseCentrality) { + registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + centrality, + ptPiFromXic, + numPvContributors); + } else { + registry.fill(HIST("hMassVsPtVsYVsPtPion"), + candidate.invMassCharmBaryon(), + ptXic, + yCharmBaryon, + ptPiFromXic, + numPvContributors); + } } } @@ -223,7 +256,7 @@ struct HfTaskXic0ToXiPi { if (candidate.resultSelections() != true) { continue; } - double yCharmBaryon; + double yCharmBaryon{0.}; if constexpr (UseKfParticle) { yCharmBaryon = candidate.kfRapXic(); } else { @@ -348,7 +381,7 @@ struct HfTaskXic0ToXiPi { } } } - PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", true); + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", false); void processDataWithDCAFitterMl(Xic0CandsMl const& candidates, CollisionsWithEvSels const& collisions) diff --git a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx index 256fd600a69..b6b709c7c55 100644 --- a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx @@ -71,7 +71,7 @@ struct HfTaskXicToXiPiPi { static constexpr int NVarsMultiClass{3}; - Service pdg; + Service pdg{}; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic); diff --git a/PWGHF/D2H/Utils/utilsSigmac.h b/PWGHF/D2H/Utils/utilsSigmac.h index 4777235ee6a..3a7c8ca257c 100644 --- a/PWGHF/D2H/Utils/utilsSigmac.h +++ b/PWGHF/D2H/Utils/utilsSigmac.h @@ -16,8 +16,11 @@ #ifndef PWGHF_D2H_UTILS_UTILSSIGMAC_H_ #define PWGHF_D2H_UTILS_UTILSSIGMAC_H_ +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include + #include #include @@ -44,6 +47,25 @@ int8_t isDecayToPKPiToPiKP(L& candidateLc, S& candSc) } return channel; /// 0: none; 1: pK-π+ only; 2: π+K-p only; 3: both possible } + +/// @brief Function to calculate the difference between the measured PKPi invariant mass and the Λc one from PDG +/// @tparam L template for the Λc candidate +/// @param candLc the Λc candidate +template +double massDiffFromPdgLcToPKPi(L& candLc) +{ + return HfHelper::invMassLcToPKPi(candLc) - o2::constants::physics::MassLambdaCPlus; +} + +/// @brief Function to calculate the difference between the measured PiKP invariant mass and the Λc one from PDG +/// @tparam L template for the Λc candidate +/// @param candLc the Λc candidate +template +double massDiffFromPdgLcToPiKP(L& candLc) +{ + return HfHelper::invMassLcToPiKP(candLc) - o2::constants::physics::MassLambdaCPlus; +} + } // namespace o2::hf_sigmac_utils #endif // PWGHF_D2H_UTILS_UTILSSIGMAC_H_ diff --git a/PWGHF/DataModel/AliasTables.h b/PWGHF/DataModel/AliasTables.h index 37e396770db..bb7cce309a3 100644 --- a/PWGHF/DataModel/AliasTables.h +++ b/PWGHF/DataModel/AliasTables.h @@ -45,6 +45,9 @@ using TracksPidPi = soa::Join; using TracksPidKa = soa::Join; using TracksPidPr = soa::Join; using TracksPidDe = soa::Join; +using TracksPidTr = soa::Join; +using TracksPidHe = soa::Join; +using TracksPidAl = soa::Join; using TracksPidTinyEl = soa::Join; using TracksPidTinyMu = soa::Join; @@ -52,6 +55,9 @@ using TracksPidTinyPi = soa::Join; using TracksPidTinyKa = soa::Join; using TracksPidTinyPr = soa::Join; using TracksPidTinyDe = soa::Join; +using TracksPidTinyTr = soa::Join; +using TracksPidTinyHe = soa::Join; +using TracksPidTinyAl = soa::Join; } // namespace o2::aod #endif // PWGHF_DATAMODEL_ALIASTABLES_H_ diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 5bc4cc45c1c..bd34cc4817a 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -44,6 +44,9 @@ DECLARE_SOA_COLUMN(TpcTofNSigmaPi, tpcTofNSigmaPi, float); //! Combined NSigma s DECLARE_SOA_COLUMN(TpcTofNSigmaKa, tpcTofNSigmaKa, float); //! Combined NSigma separation with the TPC & TOF detectors for kaon DECLARE_SOA_COLUMN(TpcTofNSigmaPr, tpcTofNSigmaPr, float); //! Combined NSigma separation with the TPC & TOF detectors for proton DECLARE_SOA_COLUMN(TpcTofNSigmaDe, tpcTofNSigmaDe, float); //! Combined NSigma separation with the TPC & TOF detectors for deuteron +DECLARE_SOA_COLUMN(TpcTofNSigmaTr, tpcTofNSigmaTr, float); //! Combined NSigma separation with the TPC & TOF detectors for triton +DECLARE_SOA_COLUMN(TpcTofNSigmaHe, tpcTofNSigmaHe, float); //! Combined NSigma separation with the TPC & TOF detectors for helium +DECLARE_SOA_COLUMN(TpcTofNSigmaAl, tpcTofNSigmaAl, float); //! Combined NSigma separation with the TPC & TOF detectors for alpha } // namespace pid_tpc_tof_static_full namespace pid_tpc_tof_static_tiny @@ -55,6 +58,9 @@ DECLARE_SOA_COLUMN(TpcTofNSigmaPi, tpcTofNSigmaPi, float); //! Combined NSigma s DECLARE_SOA_COLUMN(TpcTofNSigmaKa, tpcTofNSigmaKa, float); //! Combined NSigma separation with the TPC & TOF detectors for kaon DECLARE_SOA_COLUMN(TpcTofNSigmaPr, tpcTofNSigmaPr, float); //! Combined NSigma separation with the TPC & TOF detectors for proton DECLARE_SOA_COLUMN(TpcTofNSigmaDe, tpcTofNSigmaDe, float); //! Combined NSigma separation with the TPC & TOF detectors for deuteron +DECLARE_SOA_COLUMN(TpcTofNSigmaTr, tpcTofNSigmaTr, float); //! Combined NSigma separation with the TPC & TOF detectors for triton +DECLARE_SOA_COLUMN(TpcTofNSigmaHe, tpcTofNSigmaHe, float); //! Combined NSigma separation with the TPC & TOF detectors for helium +DECLARE_SOA_COLUMN(TpcTofNSigmaAl, tpcTofNSigmaAl, float); //! Combined NSigma separation with the TPC & TOF detectors for alpha } // namespace pid_tpc_tof_static_tiny // Extension of per particle tables @@ -68,9 +74,14 @@ DECLARE_SOA_TABLE(PidTpcTofFullKa, "AOD", "PIDTPCTOFFULLKA", //! Table of the TP pid_tpc_tof_static_full::TpcTofNSigmaKa); DECLARE_SOA_TABLE(PidTpcTofFullPr, "AOD", "PIDTPCTOFFULLPR", //! Table of the TPC & TOF Combined NSigma for proton pid_tpc_tof_static_full::TpcTofNSigmaPr); -DECLARE_SOA_TABLE(PidTpcTofFullDe, "AOD", "PIDTPCTOFFULLDe", //! Table of the TPC & TOF Combined NSigma for deuteron +DECLARE_SOA_TABLE(PidTpcTofFullDe, "AOD", "PIDTPCTOFFULLDE", //! Table of the TPC & TOF Combined NSigma for deuteron pid_tpc_tof_static_full::TpcTofNSigmaDe); - +DECLARE_SOA_TABLE(PidTpcTofFullTr, "AOD", "PIDTPCTOFFULLTR", //! Table of the TPC & TOF Combined NSigma for triton + pid_tpc_tof_static_full::TpcTofNSigmaTr); +DECLARE_SOA_TABLE(PidTpcTofFullHe, "AOD", "PIDTPCTOFFULLHE", //! Table of the TPC & TOF Combined NSigma for helium + pid_tpc_tof_static_full::TpcTofNSigmaHe); +DECLARE_SOA_TABLE(PidTpcTofFullAl, "AOD", "PIDTPCTOFFULLAL", //! Table of the TPC & TOF Combined NSigma for alpha + pid_tpc_tof_static_full::TpcTofNSigmaAl); // Extension of per particle tables DECLARE_SOA_TABLE(PidTpcTofTinyEl, "AOD", "PIDTPCTOFTINYEL", //! Table of the TPC & TOF Combined NSigma for electron pid_tpc_tof_static_tiny::TpcTofNSigmaEl); @@ -84,7 +95,12 @@ DECLARE_SOA_TABLE(PidTpcTofTinyPr, "AOD", "PIDTPCTOFTINYPR", //! Table of the TP pid_tpc_tof_static_tiny::TpcTofNSigmaPr); DECLARE_SOA_TABLE(PidTpcTofTinyDe, "AOD", "PIDTPCTOFTINYDE", //! Table of the TPC & TOF Combined NSigma for deuteron pid_tpc_tof_static_tiny::TpcTofNSigmaDe); - +DECLARE_SOA_TABLE(PidTpcTofTinyTr, "AOD", "PIDTPCTOFTINYTR", //! Table of the TPC & TOF Combined NSigma for triton + pid_tpc_tof_static_tiny::TpcTofNSigmaTr); +DECLARE_SOA_TABLE(PidTpcTofTinyHe, "AOD", "PIDTPCTOFTINYHE", //! Table of the TPC & TOF Combined NSigma for helium + pid_tpc_tof_static_tiny::TpcTofNSigmaHe); +DECLARE_SOA_TABLE(PidTpcTofTinyAl, "AOD", "PIDTPCTOFTINYAL", //! Table of the TPC & TOF Combined NSigma for alpha + pid_tpc_tof_static_tiny::TpcTofNSigmaAl); // general decay properties namespace hf_cand { @@ -181,6 +197,15 @@ DECLARE_SOA_COLUMN(NSigTpcPr2, nSigTpcPr2, float); //! TPC nSigma for DECLARE_SOA_COLUMN(NSigTpcDe0, nSigTpcDe0, float); //! TPC nSigma for deuteron hypothesis - prong 0 DECLARE_SOA_COLUMN(NSigTpcDe1, nSigTpcDe1, float); //! TPC nSigma for deuteron hypothesis - prong 1 DECLARE_SOA_COLUMN(NSigTpcDe2, nSigTpcDe2, float); //! TPC nSigma for deuteron hypothesis - prong 2 +DECLARE_SOA_COLUMN(NSigTpcTr0, nSigTpcTr0, float); //! TPC nSigma for triton hypothesis - prong 0 +DECLARE_SOA_COLUMN(NSigTpcTr1, nSigTpcTr1, float); //! TPC nSigma for triton hypothesis - prong 1 +DECLARE_SOA_COLUMN(NSigTpcTr2, nSigTpcTr2, float); //! TPC nSigma for triton hypothesis - prong 2 +DECLARE_SOA_COLUMN(NSigTpcHe0, nSigTpcHe0, float); //! TPC nSigma for helium hypothesis - prong 0 +DECLARE_SOA_COLUMN(NSigTpcHe1, nSigTpcHe1, float); //! TPC nSigma for helium hypothesis - prong 1 +DECLARE_SOA_COLUMN(NSigTpcHe2, nSigTpcHe2, float); //! TPC nSigma for helium hypothesis - prong 2 +DECLARE_SOA_COLUMN(NSigTpcAl0, nSigTpcAl0, float); //! TPC nSigma for alpha hypothesis - prong 0 +DECLARE_SOA_COLUMN(NSigTpcAl1, nSigTpcAl1, float); //! TPC nSigma for alpha hypothesis - prong 1 +DECLARE_SOA_COLUMN(NSigTpcAl2, nSigTpcAl2, float); //! TPC nSigma for alpha hypothesis - prong 2 DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); //! TOF nSigma for pion hypothesis - prong 0 DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF nSigma for pion hypothesis - prong 1 DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); //! TOF nSigma for pion hypothesis - prong 2 @@ -193,6 +218,15 @@ DECLARE_SOA_COLUMN(NSigTofPr2, nSigTofPr2, float); //! TOF nSigma for DECLARE_SOA_COLUMN(NSigTofDe0, nSigTofDe0, float); //! TOF nSigma for deuteron hypothesis - prong 0 DECLARE_SOA_COLUMN(NSigTofDe1, nSigTofDe1, float); //! TOF nSigma for deuteron hypothesis - prong 1 DECLARE_SOA_COLUMN(NSigTofDe2, nSigTofDe2, float); //! TOF nSigma for deuteron hypothesis - prong 2 +DECLARE_SOA_COLUMN(NSigTofTr0, nSigTofTr0, float); //! TOF nSigma for triton hypothesis - prong 0 +DECLARE_SOA_COLUMN(NSigTofTr1, nSigTofTr1, float); //! TOF nSigma for triton hypothesis - prong 1 +DECLARE_SOA_COLUMN(NSigTofTr2, nSigTofTr2, float); //! TOF nSigma for triton hypothesis - prong 2 +DECLARE_SOA_COLUMN(NSigTofHe0, nSigTofHe0, float); //! TOF nSigma for helium hypothesis - prong 0 +DECLARE_SOA_COLUMN(NSigTofHe1, nSigTofHe1, float); //! TOF nSigma for helium hypothesis - prong 1 +DECLARE_SOA_COLUMN(NSigTofHe2, nSigTofHe2, float); //! TOF nSigma for helium hypothesis - prong 2 +DECLARE_SOA_COLUMN(NSigTofAl0, nSigTofAl0, float); //! TOF nSigma for alpha hypothesis - prong 0 +DECLARE_SOA_COLUMN(NSigTofAl1, nSigTofAl1, float); //! TOF nSigma for alpha hypothesis - prong 1 +DECLARE_SOA_COLUMN(NSigTofAl2, nSigTofAl2, float); //! TOF nSigma for alpha hypothesis - prong 2 DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaPi0, tpcTofNSigmaPi0, //! Combined NSigma separation with the TPC & TOF detectors for pion - prong 0 [](float tpcNSigmaPi0, float tofNSigmaPi0) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaPi0, tofNSigmaPi0); }); DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaPi1, tpcTofNSigmaPi1, //! Combined NSigma separation with the TPC & TOF detectors for pion - prong 1 @@ -217,7 +251,24 @@ DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaDe1, tpcTofNSigmaDe1, //! Combined NSigma [](float tpcNSigmaDe1, float tofNSigmaDe1) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaDe1, tofNSigmaDe1); }); DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaDe2, tpcTofNSigmaDe2, //! Combined NSigma separation with the TPC & TOF detectors for deuteron - prong 2 [](float tpcNSigmaDe2, float tofNSigmaDe2) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaDe2, tofNSigmaDe2); }); - +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaTr0, tpcTofNSigmaTr0, //! Combined NSigma separation with the TPC & TOF detectors for triton - prong 0 + [](float tpcNSigmaTr0, float tofNSigmaTr0) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaTr0, tofNSigmaTr0); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaTr1, tpcTofNSigmaTr1, //! Combined NSigma separation with the TPC & TOF detectors for triton - prong 1 + [](float tpcNSigmaTr1, float tofNSigmaTr1) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaTr1, tofNSigmaTr1); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaTr2, tpcTofNSigmaTr2, //! Combined NSigma separation with the TPC & TOF detectors for triton - prong 2 + [](float tpcNSigmaTr2, float tofNSigmaTr2) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaTr2, tofNSigmaTr2); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaHe0, tpcTofNSigmaHe0, //! Combined NSigma separation with the TPC & TOF detectors for helium - prong 0 + [](float tpcNSigmaHe0, float tofNSigmaHe0) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaHe0, tofNSigmaHe0); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaHe1, tpcTofNSigmaHe1, //! Combined NSigma separation with the TPC & TOF detectors for helium - prong 1 + [](float tpcNSigmaHe1, float tofNSigmaHe1) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaHe1, tofNSigmaHe1); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaHe2, tpcTofNSigmaHe2, //! Combined NSigma separation with the TPC & TOF detectors for helium - prong 2 + [](float tpcNSigmaHe2, float tofNSigmaHe2) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaHe2, tofNSigmaHe2); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaAl0, tpcTofNSigmaAl0, //! Combined NSigma separation with the TPC & TOF detectors for alpha - prong 0 + [](float tpcNSigmaAl0, float tofNSigmaAl0) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaAl0, tofNSigmaAl0); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaAl1, tpcTofNSigmaAl1, //! Combined NSigma separation with the TPC & TOF detectors for alpha - prong 1 + [](float tpcNSigmaAl1, float tofNSigmaAl1) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaAl1, tofNSigmaAl1); }); +DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaAl2, tpcTofNSigmaAl2, //! Combined NSigma separation with the TPC & TOF detectors for alpha - prong 2 + [](float tpcNSigmaAl2, float tofNSigmaAl2) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaAl2, tofNSigmaAl2); }); // tiny (binned) option DECLARE_SOA_DYNAMIC_COLUMN(TpcTofNSigmaTinyPi0, tpcTofNSigmaTinyPi0, //! Combined NSigma separation with the TPC & TOF detectors for pion - prong 0 [](float tpcNSigmaPi0, float tofNSigmaPi0) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaPi0, tofNSigmaPi0); }); @@ -278,13 +329,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(Ct, ct, //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, //! [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); DECLARE_SOA_COLUMN(KfTopolChi2OverNdf, kfTopolChi2OverNdf, float); //! chi2overndf of the KFParticle topological constraint -// B-hadron mother information -DECLARE_SOA_COLUMN(PtBhadMotherPart, ptBhadMotherPart, float); //! pt of the first B-hadron mother particle (only in case of non-prompt) -DECLARE_SOA_COLUMN(PdgBhadMotherPart, pdgBhadMotherPart, int); //! pdg of the first B-hadron mother particle (only in case of non-prompt) -DECLARE_SOA_COLUMN(IdxBhadMotherPart, idxBhadMotherPart, int); //! index of the first B-hadron mother particle (only in case of non-prompt) -// Kink topology and material interaction mc flags -DECLARE_SOA_COLUMN(NTracksDecayed, nTracksDecayed, int8_t); //! number of tracks matched with kinked decay topology -DECLARE_SOA_COLUMN(NInteractionsWithMaterial, nInteractionsWithMaterial, int8_t); //! number of tracks matched after interaction with material // method of secondary-vertex reconstruction enum VertexerType { DCAFitter = 0, @@ -314,13 +358,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1}, std::array{errIp0, errIp1}, std::array{std::array{px0, py0}, std::array{px1, py1}}); }); DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); -// 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 -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel flag, reconstruction level // KF related properties DECLARE_SOA_COLUMN(KfGeoMassD0, kfGeoMassD0, float); //! mass of the D0 candidate from the KFParticle geometric fit @@ -328,6 +365,26 @@ DECLARE_SOA_COLUMN(KfGeoMassD0bar, kfGeoMassD0bar, float); //! mass of the D0bar } // namespace hf_cand_2prong +// MC +namespace hf_cand_mc_flag +{ +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! main decay channel, reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! main decay channel, generator level +DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel, reconstruction level +DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel, 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(IsCandidateSwapped, isCandidateSwapped, int8_t); //! swapping of the prongs order +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); //! debug flag for mis-association reconstruction level +// B-hadron mother information +DECLARE_SOA_COLUMN(PtBhadMotherPart, ptBhadMotherPart, float); //! pt of the first B-hadron mother particle (only in case of non-prompt) +DECLARE_SOA_COLUMN(PdgBhadMotherPart, pdgBhadMotherPart, int); //! pdg of the first B-hadron mother particle (only in case of non-prompt) +DECLARE_SOA_COLUMN(IdxBhadMotherPart, idxBhadMotherPart, int); //! index of the first B-hadron mother particle (only in case of non-prompt) +// Kink topology and material interaction MC flags +DECLARE_SOA_COLUMN(NTracksDecayed, nTracksDecayed, int8_t); //! number of tracks matched with kinked decay topology +DECLARE_SOA_COLUMN(NInteractionsWithMaterial, nInteractionsWithMaterial, int8_t); //! number of tracks matched after interaction with material +} // namespace hf_cand_mc_flag + // general columns #define HFCAND_COLUMNS \ hf_cand::CollisionId, \ @@ -412,20 +469,20 @@ DECLARE_SOA_TABLE(HfCand2ProngKF, "AOD", "HFCAND2PKF", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCand2ProngMcRec, "AOD", "HFCAND2PMCREC", //! - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcRec, - hf_cand_2prong::FlagMcDecayChanRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - hf_cand::NTracksDecayed, - hf_cand::NInteractionsWithMaterial); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, + hf_cand_mc_flag::NTracksDecayed, + hf_cand_mc_flag::NInteractionsWithMaterial); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCand2ProngMcGen, "AOD", "HFCAND2PMCGEN", //! - hf_cand_2prong::FlagMcMatchGen, - hf_cand_2prong::OriginMcGen, - hf_cand_2prong::FlagMcDecayChanGen, - hf_cand::IdxBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::IdxBhadMotherPart); // cascade decay candidate table @@ -444,13 +501,11 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtV0Neg, ptV0Neg, //! pt of the negative V0 daughter [](float px, float py) { return RecoDecay::pt(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(CtV0, ctV0, //! c*t of the V0 [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(std::array{px, py, pz}, RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}), m); }); -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(V0X, v0X, float); //! X position of V0 decay -DECLARE_SOA_COLUMN(V0Y, v0Y, float); //! Y position of V0 decay -DECLARE_SOA_COLUMN(V0Z, v0Z, float); //! Z position of V0 decay +DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthV0, decayLengthV0, //! + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}); }); +DECLARE_SOA_COLUMN(V0X, v0X, float); //! X position of V0 decay +DECLARE_SOA_COLUMN(V0Y, v0Y, float); //! Y position of V0 decay +DECLARE_SOA_COLUMN(V0Z, v0Z, float); //! Z position of V0 decay } // namespace hf_cand_casc DECLARE_SOA_TABLE(HfCandCascBase, "AOD", "HFCANDCASCBASE", //! @@ -501,7 +556,8 @@ DECLARE_SOA_TABLE(HfCandCascBase, "AOD", "HFCANDCASCBASE", //! v0data::legacy::MAntiLambda, v0data::legacy::MK0Short, v0data::MGamma, - hf_cand_casc::CtV0); + hf_cand_casc::CtV0, + hf_cand_casc::DecayLengthV0); // , // v0data::MLambda, // v0data::MAntiLambda, @@ -515,30 +571,21 @@ using HfCandCascade = HfCandCascExt; // table with results of reconstruction level MC matching for Cascade DECLARE_SOA_TABLE(HfCandCascadeMcRec, "AOD", "HFCANDCASCMCREC", //! - hf_cand_casc::FlagMcMatchRec, - hf_cand_casc::OriginMcRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandCascadeMcGen, "AOD", "HFCANDCASCMCGEN", //! - hf_cand_casc::FlagMcMatchGen, - hf_cand_casc::OriginMcGen, - hf_cand::IdxBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::IdxBhadMotherPart); // specific BPlus candidate properties namespace hf_cand_bplus { -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // D0 index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, 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(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // D0 index DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, // Impact parameter product for B+ -> J/Psi K [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float impParK) -> float { return impParK * RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{px0, py0, pz0}, std::array{px1, py1, pz1})); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, // J/Psi impact parameter for B+ -> J/Psi K @@ -601,15 +648,15 @@ using HfCandBplus = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBplusMcRec, "AOD", "HFCANDBPMCREC", - hf_cand_bplus::FlagMcMatchRec, - hf_cand_bplus::FlagMcDecayChanRec, - hf_cand_bplus::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandBplusMcGen, "AOD", "HFCANDBPMCGEN", - hf_cand_bplus::FlagMcMatchGen, - hf_cand_bplus::FlagMcDecayChanGen, - hf_cand_bplus::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); // specific 3-prong decay properties namespace hf_cand_3prong @@ -632,14 +679,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}}, m); }); -// 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 -DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); //! swapping of the prongs order -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel flag, generator level // Ds± → K± K∓ π± or D± → K± K∓ π± @@ -767,11 +806,41 @@ DECLARE_SOA_TABLE(HfCand3Prong1PidDe, "AOD", "HFCAND3P1PIDDE", //! DECLARE_SOA_TABLE(HfCand3Prong2PidDe, "AOD", "HFCAND3P2PIDDE", //! hf_cand::NSigTpcDe2, hf_cand::NSigTofDe2, hf_cand::TpcTofNSigmaDe2); +DECLARE_SOA_TABLE(HfCand3Prong0PidTr, "AOD", "HFCAND3P0PIDTR", //! + hf_cand::NSigTpcTr0, hf_cand::NSigTofTr0, + hf_cand::TpcTofNSigmaTr0); +DECLARE_SOA_TABLE(HfCand3Prong1PidTr, "AOD", "HFCAND3P1PIDTR", //! + hf_cand::NSigTpcTr1, hf_cand::NSigTofTr1, + hf_cand::TpcTofNSigmaTr1); +DECLARE_SOA_TABLE(HfCand3Prong2PidTr, "AOD", "HFCAND3P2PIDTR", //! + hf_cand::NSigTpcTr2, hf_cand::NSigTofTr2, + hf_cand::TpcTofNSigmaTr2); +DECLARE_SOA_TABLE(HfCand3Prong0PidHe, "AOD", "HFCAND3P0PIDHE", //! + hf_cand::NSigTpcHe0, hf_cand::NSigTofHe0, + hf_cand::TpcTofNSigmaHe0); +DECLARE_SOA_TABLE(HfCand3Prong1PidHe, "AOD", "HFCAND3P1PIDHE", //! + hf_cand::NSigTpcHe1, hf_cand::NSigTofHe1, + hf_cand::TpcTofNSigmaHe1); +DECLARE_SOA_TABLE(HfCand3Prong2PidHe, "AOD", "HFCAND3P2PIDHE", //! + hf_cand::NSigTpcHe2, hf_cand::NSigTofHe2, + hf_cand::TpcTofNSigmaHe2); +DECLARE_SOA_TABLE(HfCand3Prong0PidAl, "AOD", "HFCAND3P0PIDAL", //! + hf_cand::NSigTpcAl0, hf_cand::NSigTofAl0, + hf_cand::TpcTofNSigmaAl0); +DECLARE_SOA_TABLE(HfCand3Prong1PidAl, "AOD", "HFCAND3P1PIDAL", //! + hf_cand::NSigTpcAl1, hf_cand::NSigTofAl1, + hf_cand::TpcTofNSigmaAl1); +DECLARE_SOA_TABLE(HfCand3Prong2PidAl, "AOD", "HFCAND3P2PIDAL", //! + hf_cand::NSigTpcAl2, hf_cand::NSigTofAl2, + hf_cand::TpcTofNSigmaAl2); using HfCand3Prong = HfCand3ProngExt; using HfCand3ProngWPidPiKaPr = soa::Join; using HfCand3ProngWPidPiKa = soa::Join; using HfCand3ProngWPidPiKaDe = soa::Join; +using HfCand3ProngWPidPiKaTr = soa::Join; +using HfCand3ProngWPidPiKaHe = soa::Join; +using HfCand3ProngWPidPiKaAl = soa::Join; DECLARE_SOA_TABLE(HfCand3ProngKF, "AOD", "HFCAND3PKF", hf_cand_3prong::KfXError, hf_cand_3prong::KfYError, hf_cand_3prong::KfZError, @@ -786,21 +855,21 @@ DECLARE_SOA_TABLE(HfCand3ProngKF, "AOD", "HFCAND3PKF", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCand3ProngMcRec, "AOD", "HFCAND3PMCREC", //! - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::IsCandidateSwapped, - hf_cand_3prong::FlagMcDecayChanRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - hf_cand::NTracksDecayed, - hf_cand::NInteractionsWithMaterial); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::IsCandidateSwapped, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, + hf_cand_mc_flag::NTracksDecayed, + hf_cand_mc_flag::NInteractionsWithMaterial); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCand3ProngMcGen, "AOD", "HFCAND3PMCGEN", //! - hf_cand_3prong::FlagMcMatchGen, - hf_cand_3prong::OriginMcGen, - hf_cand_3prong::FlagMcDecayChanGen, - hf_cand::IdxBhadMotherPart); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::IdxBhadMotherPart); // declare dedicated BPlus -> J/Psi K decay candidate table // convention: prongs 0 and 1 should be J/Psi decay products @@ -861,14 +930,6 @@ enum ConstructMethod { DcaFitter = 0, namespace hf_cand_x { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // Jpsi 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 -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel flag, generator level - } // namespace hf_cand_x // declare dedicated X candidate table @@ -915,26 +976,20 @@ using HfCandX = HfCandXExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandXMcRec, "AOD", "HFCANDXMCREC", //! - hf_cand_x::FlagMcMatchRec, - hf_cand_x::OriginMcRec, - hf_cand_x::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandXMcGen, "AOD", "HFCANDXMCGEN", //! - hf_cand_x::FlagMcMatchGen, - hf_cand_x::OriginMcGen, - hf_cand_x::FlagMcDecayChanGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen); // specific Xicc candidate properties namespace hf_cand_xicc { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Xic 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 -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level } // namespace hf_cand_xicc // declare dedicated Xicc candidate table @@ -977,14 +1032,14 @@ using HfCandXicc = HfCandXiccExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandXiccMcRec, "AOD", "HFCANDXICCMCREC", //! - hf_cand_xicc::FlagMcMatchRec, - hf_cand_xicc::OriginMcRec, - hf_cand_xicc::DebugMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::DebugMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandXiccMcGen, "AOD", "HFCANDXICCMCGEN", //! - hf_cand_xicc::FlagMcMatchGen, - hf_cand_xicc::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen); // specific Omegac and Xic to Xi Pi candidate properties namespace hf_cand_xic0_omegac0 @@ -1228,16 +1283,10 @@ DECLARE_SOA_COLUMN(Xic0XError, xic0XError, float); DECLARE_SOA_COLUMN(Xic0YError, xic0YError, float); DECLARE_SOA_COLUMN(Xic0ZError, xic0ZError, 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 -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); DECLARE_SOA_COLUMN(DebugGenCharmBar, debugGenCharmBar, int8_t); DECLARE_SOA_COLUMN(DebugGenCasc, debugGenCasc, int8_t); DECLARE_SOA_COLUMN(DebugGenLambda, debugGenLambda, int8_t); -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); DECLARE_SOA_COLUMN(PtCharmBaryonGen, ptCharmBaryonGen, float); DECLARE_SOA_COLUMN(RapidityCharmBaryonGen, rapidityCharmBaryonGen, float); @@ -1319,8 +1368,7 @@ DECLARE_SOA_TABLE(HfCandToOmegaPi, "AOD", "HFCANDTOOMEGAPI", hf_cand_xic0_omegac0::DcaXYToPvV0Dau0, hf_cand_xic0_omegac0::DcaXYToPvV0Dau1, hf_cand_xic0_omegac0::DcaXYToPvCascDau, hf_cand_xic0_omegac0::DcaZToPvV0Dau0, hf_cand_xic0_omegac0::DcaZToPvV0Dau1, hf_cand_xic0_omegac0::DcaZToPvCascDau, hf_cand_xic0_omegac0::DcaCascDau, hf_cand_xic0_omegac0::DcaV0Dau, hf_cand_xic0_omegac0::DcaCharmBaryonDau, - 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, hf_track_index::HFflag, - o2::soa::Marker<1>); + 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, hf_track_index::HFflag); DECLARE_SOA_TABLE(HfCandToOmegaK, "AOD", "HFCANDTOOMEGAK", o2::soa::Index<>, @@ -1348,8 +1396,7 @@ DECLARE_SOA_TABLE(HfCandToOmegaK, "AOD", "HFCANDTOOMEGAK", hf_cand_xic0_omegac0::DcaXYToPvV0Dau0, hf_cand_xic0_omegac0::DcaXYToPvV0Dau1, hf_cand_xic0_omegac0::DcaXYToPvCascDau, hf_cand_xic0_omegac0::DcaZToPvV0Dau0, hf_cand_xic0_omegac0::DcaZToPvV0Dau1, hf_cand_xic0_omegac0::DcaZToPvCascDau, hf_cand_xic0_omegac0::DcaCascDau, hf_cand_xic0_omegac0::DcaV0Dau, hf_cand_xic0_omegac0::DcaCharmBaryonDau, - 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>); + 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); // table with results of KFParticle DECLARE_SOA_TABLE(HfOmegacKf, "AOD", "HFOMEGACKF", //! @@ -1453,51 +1500,47 @@ DECLARE_SOA_TABLE(HfCandToXiPiKfQa, "AOD", "HFCANDTOXIPIKFQA", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfXicToXiPiMCRec, "AOD", "HFXICXIPIMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<1>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); DECLARE_SOA_TABLE(HfOmegacToXiPiMCRec, "AOD", "HFOMCXIPIMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<2>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaPiMCRec, "AOD", "HFTOOMEPIMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<3>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaKMCRec, "AOD", "HFTOOMEKMCREC", //! - hf_cand_xic0_omegac0::FlagMcMatchRec, - hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::DebugMcRec, + hf_cand_mc_flag::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - o2::soa::Marker<4>); + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfXicToXiPiMCGen, "AOD", "HFXICXIPIMCGEN", //! - 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::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<1>); + hf_cand_mc_flag::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_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); DECLARE_SOA_TABLE(HfOmegacToXiPiMCGen, "AOD", "HFOMECXIPIMCGEN", //! - 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::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<2>); + hf_cand_mc_flag::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_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); DECLARE_SOA_TABLE(HfToOmegaPiMCGen, "AOD", "HFTOOMEPIMCGEN", //! - 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::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<3>); + hf_cand_mc_flag::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_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); 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::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<4>); + hf_cand_mc_flag::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_mc_flag::OriginMcGen, hf_cand_mc_flag::IdxBhadMotherPart); // specific Xic to Xi Pi Pi candidate properties namespace hf_cand_xic_to_xi_pi_pi @@ -1562,11 +1605,7 @@ DECLARE_SOA_COLUMN(NSigTofPiFromXicPlus1, nSigTofPiFromXicPlus1, float); DECLARE_SOA_COLUMN(NSigTofBachelorPi, nSigTofBachelorPi, float); DECLARE_SOA_COLUMN(NSigTofPiFromLambda, nSigTofPiFromLambda, float); DECLARE_SOA_COLUMN(NSigTofPrFromLambda, nSigTofPrFromLambda, 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(OriginMcRec, originMcRec, int8_t); -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); +// MC DECLARE_SOA_COLUMN(DecayLengthMcGen, decayLengthMcGen, float); // Residuals and pulls DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); @@ -1664,19 +1703,19 @@ DECLARE_SOA_TABLE(HfCandXicKF, "AOD", "HFCANDXICKF", // 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::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); // 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::OriginMcGen, - hf_cand::PdgBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::PdgBhadMotherPart, hf_cand_xic_to_xi_pi_pi::DecayLengthMcGen); // table with residuals and pulls of PV DECLARE_SOA_TABLE(HfCandXicResid, "AOD", "HFCANDXICRESID", - hf_cand_xic_to_xi_pi_pi::OriginMcGen, + hf_cand_mc_flag::OriginMcGen, hf_cand_xic_to_xi_pi_pi::PResidual, hf_cand_xic_to_xi_pi_pi::PtResidual, hf_cand_xic_to_xi_pi_pi::XPvResidual, @@ -1697,14 +1736,7 @@ namespace hf_cand_chic { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // Jpsi index DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, ECALs, "_1"); -// 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 -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel flag, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel flag, generator level -DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass +DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass } // namespace hf_cand_chic // declare dedicated chi_c candidate table @@ -1750,29 +1782,20 @@ using HfCandChic = HfCandChicExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandChicMcRec, "AOD", "HFCANDCHICMCREC", //! - hf_cand_chic::FlagMcMatchRec, - hf_cand_chic::OriginMcRec, - hf_cand_chic::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandChicMcGen, "AOD", "HFCANDCHICMCGEN", //! - hf_cand_chic::FlagMcMatchGen, - hf_cand_chic::OriginMcGen, - hf_cand_chic::FlagMcDecayChanGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::FlagMcDecayChanGen); // specific Lb candidate properties namespace hf_cand_lb { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Lb index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, 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(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level enum DecayTypeMc : uint8_t { LbToLcPiToPKPiPi = 0, LbToLcKToPKPiK, @@ -1823,30 +1846,21 @@ using HfCandLb = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandLbMcRec, "AOD", "HFCANDLBMCREC", //! - hf_cand_lb::FlagMcMatchRec, - hf_cand_lb::FlagMcDecayChanRec, - hf_cand_lb::OriginMcRec, - hf_cand_lb::DebugMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::DebugMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandLbMcGen, "AOD", "HFCANDLBMCGEN", //! - hf_cand_lb::FlagMcMatchGen, - hf_cand_lb::FlagMcDecayChanGen, - hf_cand_lb::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); // specific B0 candidate properties namespace hf_cand_b0 { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // D index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, 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(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, B0ToDsPiToKKPiPi, @@ -1941,30 +1955,21 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfCandB0DStExt, HfCandB0DStar, "HFCANDB0DSTEXT", // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandB0McRec, "AOD", "HFCANDB0MCREC", - hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::FlagMcDecayChanRec, - hf_cand_b0::OriginMcRec, - hf_cand_b0::DebugMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::DebugMcRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandB0McGen, "AOD", "HFCANDB0MCGEN", - hf_cand_b0::FlagMcMatchGen, - hf_cand_b0::FlagMcDecayChanGen, - hf_cand_b0::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); // specific Bs candidate properties namespace hf_cand_bs { -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index -// MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // main decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // main decay channel, generator level -DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); // resonant decay channel, reconstruction level -DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant decay channel, 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(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, // Impact parameter product for Bs -> J/Psi phi [](float pxJpsiDauPos, float pyJpsiDauPos, float pzJpsiDauPos, float pxJpsiDauNeg, float pyJpsiDauNeg, float pzJpsiDauNeg, float pxLfTrack0, float pyLfTrack0, float pzLfTrack0, float pxLfTrack1, float pyLfTrack1, float pzLfTrack1, float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { float impParJpsi = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{pxJpsiDauPos, pyJpsiDauPos, pzJpsiDauPos}, std::array{pxJpsiDauNeg, pyJpsiDauNeg, pzJpsiDauNeg})); @@ -2024,8 +2029,7 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::Y, hf_cand::E, hf_cand::E2, - hf_cand_2prong::CtXY, - o2::soa::Marker<1>); + hf_cand_2prong::CtXY); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsExt, HfCandBsBase, "HFCANDBSEXT", @@ -2038,13 +2042,13 @@ using HfCandBs = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBsMcRec, "AOD", "HFCANDBSMCREC", - hf_cand_bs::FlagMcMatchRec, - hf_cand_bs::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandBsMcGen, "AOD", "HFCANDBSMCGEN", - hf_cand_bs::FlagMcMatchGen, - hf_cand_bs::FlagMcDecayChanGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen); namespace hf_cand_4prong { @@ -2110,8 +2114,7 @@ DECLARE_SOA_TABLE(HfCandBsJPBase, "AOD", "HFCANDBSJPBASE", hf_cand::Y, hf_cand::E, hf_cand::E2, - hf_cand_4prong::CtXY, - o2::soa::Marker<1>); + hf_cand_4prong::CtXY); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsJPExt, HfCandBsJPBase, "HFCANDBSJPEXT", @@ -2133,10 +2136,6 @@ DECLARE_SOA_COLUMN(SoftPiDcaXY, softPiDcaXY, float); DECLARE_SOA_COLUMN(SoftPiDcaZ, softPiDcaZ, float); //! soft-pion impact parameter in z DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_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 DECLARE_SOA_COLUMN(ParticleAntiparticle, particleAntiparticle, int8_t); //! particle or antiparticle enum Species : int { Sc2455 = 0, @@ -2202,17 +2201,17 @@ using HfCandSc = HfCandScExt; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandScMcRec, "AOD", "HFCANDSCMCREC", //! - hf_cand_sigmac::FlagMcMatchRec, - hf_cand_sigmac::OriginMcRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, hf_cand_sigmac::ParticleAntiparticle); // table with results of generation level MC matching DECLARE_SOA_TABLE(HfCandScMcGen, "AOD", "HFCANDSCMCGEN", //! - hf_cand_sigmac::FlagMcMatchGen, - hf_cand_sigmac::OriginMcGen, - hf_cand::IdxBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::IdxBhadMotherPart, hf_cand_sigmac::ParticleAntiparticle); // specific Σc0,++ candidate properties in cascade channel @@ -2224,11 +2223,6 @@ DECLARE_SOA_COLUMN(ChargeLc, chargeLc, int8_t); 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 @@ -2386,14 +2380,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(PVecSoftPi, pVecSoftPi, [](float px, float py, float DECLARE_SOA_DYNAMIC_COLUMN(TPCTOFNSigmaPiSoftPi, tpcTofNSigmaPiSoftPi, //! Combination of NsigmaTPC and NsigmaTOF, o2-linter: disable=name/o2-column (written to disk) [](float tpcNSigmaPiSoftPi, float TOFNSigmaPiSoftPi) -> float { return pid_tpc_tof_utils::combineNSigma(tpcNSigmaPiSoftPi, TOFNSigmaPiSoftPi); }); // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(FlagMcMatchRecD0, flagMcMatchRecD0, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGenD0, flagMcMatchGenD0, 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_dstar /// D0 (table) from DStar @@ -2524,20 +2512,20 @@ using HfCandDstarsWPid = soa::Join); +// ---------------- +// Lc to K0sP +// ---------------- + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPPars, "HFLCTOK0SPPAR", //! Table with candidate properties used for selection + hf_cand::Chi2PCA, + hf_cand_par::Cpa, + hf_cand_par::CpaXY, + hf_cand_par::DecayLength, + hf_cand_par::DecayLengthXY, + hf_cand_par::PtProng0, + hf_cand_par::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand_par::V0Radius, + hf_cand_par::V0CosPA, + hf_cand_par::MLambda, + hf_cand_par::MAntiLambda, + hf_cand_par::MK0Short, + hf_cand_par::MGamma, + hf_cand_par::DCAV0Daughters, + hf_cand_par::PtV0Pos, + hf_cand_par::PtV0Neg, + hf_cand_par::DecayLengthV0, + hf_cand_par::DCAPosToPV, + hf_cand_par::DCANegToPV, + hf_cand_par::NSigTpcPr0, + hf_cand_par::NSigTofPr0, + hf_cand_par::CtV0, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPParEs, "HFLCTOK0SPPARE", //! Table with additional candidate properties used for selection + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand_par::RSecondaryVertex, + hf_cand_par::PProng0, + hf_cand_par::PProng1, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + v0data::PxPos, + v0data::PyPos, + v0data::PzPos, + v0data::PxNeg, + v0data::PyNeg, + v0data::PzNeg, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + hf_cand_par::Ct, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPMls, "HFLCTOK0SPML", //! Table with candidate selection ML scores + hf_cand_mc::MlScores, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfLcToK0sPMcs, "HFLCTOK0SPMC", //! Table with MC candidate info + hf_cand_mc::FlagMcMatchRec, + hf_cand_mc::OriginMcRec, + o2::soa::Marker); + // ---------------- // D+ // ---------------- @@ -873,8 +979,11 @@ DECLARE_SOA_TABLE_STAGED(HfDplusDaugs, "HFDPDAUG", //! Table to study daughter p hf_cand::PyProng2, hf_cand::PzProng2, hf_cand_par::NSigTpcTofPi0, - hf_cand_par::NSigTpcTofKa1, + hf_cand_par::NSigTpcTofPi1, hf_cand_par::NSigTpcTofPi2, + hf_cand_par::NSigTpcTofKa0, + hf_cand_par::NSigTpcTofKa1, + hf_cand_par::NSigTpcTofKa2, o2::soa::Marker); DECLARE_SOA_TABLE_STAGED(HfDplusMls, "HFDPML", //! Table with candidate selection ML scores @@ -1025,9 +1134,9 @@ DECLARE_SOA_TABLE_STAGED(HfDstarMcs, "HFDSTMC", //! Table with MC candidate info hf_cand_mc::FlagMcMatchRec, hf_cand_mc_charm::FlagMcMatchRecCharm, hf_cand_mc::OriginMcRec, - hf_cand::PtBhadMotherPart, - hf_cand::PdgBhadMotherPart, - hf_cand::NTracksDecayed, + hf_cand_mc_flag::PtBhadMotherPart, + hf_cand_mc_flag::PdgBhadMotherPart, + hf_cand_mc_flag::NTracksDecayed, o2::soa::Marker); // ---------------- diff --git a/PWGHF/DataModel/TrackIndexSkimmingTables.h b/PWGHF/DataModel/TrackIndexSkimmingTables.h index 6408c636f8e..c21c4bf3ed8 100644 --- a/PWGHF/DataModel/TrackIndexSkimmingTables.h +++ b/PWGHF/DataModel/TrackIndexSkimmingTables.h @@ -299,6 +299,9 @@ enum DecayType { DsToKKPi, XicToPKPi, CdToDeKPi, + CtToTrKPi, + ChToHeKPi, + CaToAlKPi, N3ProngDecays }; } // namespace hf_cand_3prong diff --git a/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h b/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h index 555d86f34c8..8f8dbecf390 100644 --- a/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h +++ b/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h @@ -85,6 +85,8 @@ DECLARE_SOA_COLUMN(PhiAssocTrack, phiAssocTrack, float); //! Phi of the track DECLARE_SOA_COLUMN(PtAssocTrack, ptAssocTrack, float); //! Pt of the track DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); //! Impact parameter in XY of the track to the primary vertex DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); //! Impact parameter in Z of the track to the primary vertex +DECLARE_SOA_COLUMN(NSigmaTpc, nSigmaTpc, float); //! Number of sigma TPC +DECLARE_SOA_COLUMN(NSigmaTof, nSigmaTof, float); //! Number of sigma TOF } // namespace hf_assoc_track_reduced DECLARE_SOA_TABLE(AssocTrackReds, "AOD", "ASSOCTRACKRED", //! Table with associated track info soa::Index<>, @@ -103,6 +105,11 @@ DECLARE_SOA_TABLE(AssocTrackSels, "AOD", "ASSOCTRACKSEL", //! Table with associa aod::hf_assoc_track_reduced::DcaXY, aod::hf_assoc_track_reduced::DcaZ); +DECLARE_SOA_TABLE(AssocTrackPids, "AOD", "ASSOCTRACKPID", //! Table with associated track pid info + soa::Index<>, + aod::hf_assoc_track_reduced::NSigmaTpc, + aod::hf_assoc_track_reduced::NSigmaTof); + // definition of columns and tables for Charm-Hadron and Hadron-Hadron correlation pairs namespace hf_correl_charm_had_reduced { diff --git a/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h b/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h new file mode 100644 index 00000000000..9c4484de852 --- /dev/null +++ b/PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h @@ -0,0 +1,247 @@ +// 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 ReducedDMesonPairsTables.h +/// \brief Header file with definition of methods and tables +/// \note used to fold (unfold) track and primary vertex information by writing (reading) AO2Ds +/// +/// \author Valerio DI BELLA , IPHC Strasbourg + +#ifndef PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ +#define PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ + +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include +#include + +namespace o2::aod +{ +DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ); + +DECLARE_SOA_TABLE(HfCandDpMcEvs, "AOD", "HFCANDDPMCEV", + collision::PosX, + collision::PosY, + collision::PosZ); + +namespace full +{ +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! Radius of secondary vertex (cm) +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! Normalised impact parameter of prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1 +DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); //! Transverse momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! Momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, float); //! Normalised impact parameter of prong2 +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! 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(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Collision centrality +DECLARE_SOA_INDEX_COLUMN(HfCandDpMcEv, hfCandDpMcEv); //! The Mc collision index this MC particles belongs to +DECLARE_SOA_INDEX_COLUMN(HfCandDpFullEv, hfCandDpFullEv); //! The collision index this candidate belongs to +DECLARE_SOA_COLUMN(NSigTpcPi0, nSigTpcPi0, float); //! TPC Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); //! TPC Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); //! TOF Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); //! TOF Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); //! TPC Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); //! TOF Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); //! TPC Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); //! TPC Nsigma separation for prong2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); //! TOF Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); //! TOF Nsigma separation for prong2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi0, nSigTpcTofPi0, float); //! TPC and TOF combined Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa0, nSigTpcTofKa0, float); //! TPC and TOF combined Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi1, nSigTpcTofPi1, float); //! TPC and TOF combined Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa1, nSigTpcTofKa1, float); //! TPC and TOF combined Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofPi2, nSigTpcTofPi2, float); //! TPC and TOF combined Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKa2, nSigTpcTofKa2, float); //! TPC and TOF combined Nsigma separation for prong2 with kaon mass hypothesis +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(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime times c of candidate (cm) +// Events +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +// ML scores +DECLARE_SOA_COLUMN(MlScore0, mlScore0, float); //! ML score of the first configured index +DECLARE_SOA_COLUMN(MlScore1, mlScore1, float); //! ML score of the second configured index +} // namespace full +DECLARE_SOA_TABLE(HfCandDpMls, "AOD", "HFCANDDPML", + full::MlScore0, + full::MlScore1) + +DECLARE_SOA_TABLE(HfCandDpTinys, "AOD", "HFCANDDPTINY", + full::CandidateSelFlag, + full::M, + full::Pt, + full::Eta, + full::Phi, + full::HfCandDpFullEvId, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec) + +DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::PtProng0, + full::PtProng1, + full::PtProng2, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ImpactParameter2, + hf_cand::ImpactParameterZ0, + hf_cand::ImpactParameterZ1, + hf_cand::ImpactParameterZ2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcTofPi0, + full::NSigTpcTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTpcTofPi1, + full::NSigTpcTofKa1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTofPi2, + full::NSigTofKa2, + full::NSigTpcTofPi2, + full::NSigTpcTofKa2, + full::CandidateSelFlag, + full::M, + full::Pt, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Eta, + full::Phi, + full::Y, + full::Centrality, + full::HfCandDpFullEvId, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec) + +DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, + full::RSecondaryVertex, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::ImpactParameterNormalised0, + full::PtProng0, + full::PProng0, + full::ImpactParameterNormalised1, + full::PtProng1, + full::PProng1, + full::ImpactParameterNormalised2, + full::PtProng2, + full::PProng2, + 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, + hf_cand::ImpactParameterZ0, + hf_cand::ImpactParameterZ1, + hf_cand::ImpactParameterZ2, + hf_cand::ErrorImpactParameterZ0, + hf_cand::ErrorImpactParameterZ1, + hf_cand::ErrorImpactParameterZ2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcTofPi0, + full::NSigTpcTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTpcTofPi1, + full::NSigTpcTofKa1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTofPi2, + full::NSigTofKa2, + full::NSigTpcTofPi2, + full::NSigTpcTofKa2, + full::CandidateSelFlag, + full::M, + full::Pt, + full::P, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + full::Centrality, + full::HfCandDpFullEvId, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); + +DECLARE_SOA_TABLE(HfCandDpMcPs, "AOD", "HFCANDDPMCP", + full::Pt, + full::Eta, + full::Phi, + full::Y, + full::HfCandDpMcEvId, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); +} // namespace o2::aod + +#endif // PWGHF_HFC_DATAMODEL_REDUCEDDMESONPAIRSTABLES_H_ diff --git a/PWGHF/HFC/TableProducer/CMakeLists.txt b/PWGHF/HFC/TableProducer/CMakeLists.txt index be466d7e86e..cee79035d78 100644 --- a/PWGHF/HFC/TableProducer/CMakeLists.txt +++ b/PWGHF/HFC/TableProducer/CMakeLists.txt @@ -34,6 +34,11 @@ o2physics_add_dpl_workflow(correlator-dplus-dminus PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(correlator-dplus-dplus-reduced + SOURCES correlatorDplusDplusReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(correlator-dplus-hadrons SOURCES correlatorDplusHadrons.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index 474a1d662ad..85ec82b5ed9 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -239,9 +239,6 @@ struct HfCorrelatorD0Hadrons { Configurable useCentrality{"useCentrality", false, "Flag for centrality dependent analyses"}; int leadingIndex = 0; - double massD0{0.}; - double massPi{0.}; - double massK{0.}; double softPiMass = 0.14543; // pion mass + Q-value of the D*->D0pi decay SliceCache cache; @@ -257,7 +254,7 @@ struct HfCorrelatorD0Hadrons { Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "z vertex position pools"}; - ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0.0f, 2000.0f, 6000.0f, 10000.0f}, "event multiplicity pools (FT0M)"}; + ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0.0f, 1100.0f, 1900.0f, 10000.0f}, "event multiplicity pools (FT0M)"}; ConfigurableAxis multPoolBinsMcGen{"multPoolBinsMcGen", {VARIABLE_WIDTH, 0.0f, 20.0f, 50.0f, 500.0f}, "Mixing bins - MC multiplicity"}; // In MCGen multiplicity is defined by counting tracks ConfigurableAxis binsMassD{"binsMassD", {200, 1.3848, 2.3848}, "inv. mass (#pi K) (GeV/#it{c}^{2});entries"}; ConfigurableAxis binsEta{"binsEta", {100, -5., 5.}, "#it{#eta}"}; @@ -268,16 +265,10 @@ struct HfCorrelatorD0Hadrons { ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; ConfigurableAxis binsCentFt0m{"binsCentFt0m", {100, 0., 100.}, "Centrality percentile (FT0M)"}; - BinningType corrBinning{{zPoolBins, multPoolBins}, true}; - HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { - massD0 = MassD0; - massPi = MassPiPlus; - massK = MassKPlus; - AxisSpec axisMassD = {binsMassD, "inv. mass (#pi K) (GeV/#it{c}^{2})"}; AxisSpec const axisEta = {binsEta, "#it{#eta}"}; AxisSpec const axisPhi = {binsPhi, "#it{#varphi}"}; @@ -370,6 +361,7 @@ struct HfCorrelatorD0Hadrons { SelectedTracks const& tracks, SelectedCandidatesDataMl const& candidates) { + BinningType const corrBinning{{zPoolBins, multPoolBins}, true}; // find leading particle if (correlateD0WithLeadingParticle) { leadingIndex = findLeadingParticle(tracks, etaTrackMax.value); @@ -415,8 +407,8 @@ struct HfCorrelatorD0Hadrons { } // ========================== Define parameters for soft pion removal ================================ - auto ePiK = RecoDecay::e(candidate.pVectorProng0(), massPi) + RecoDecay::e(candidate.pVectorProng1(), massK); - auto eKPi = RecoDecay::e(candidate.pVectorProng0(), massK) + RecoDecay::e(candidate.pVectorProng1(), massPi); + auto ePiK = RecoDecay::e(candidate.pVectorProng0(), MassPiPlus) + RecoDecay::e(candidate.pVectorProng1(), MassKPlus); + auto eKPi = RecoDecay::e(candidate.pVectorProng0(), MassKPlus) + RecoDecay::e(candidate.pVectorProng1(), MassPiPlus); // ========================== trigger efficiency ================================ double efficiencyWeight = 1.; @@ -437,7 +429,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), (candidate.isSelD0bar() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only, cent, efficiencyWeight); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMass"), invMassD0bar, candidate.pt(), efficiencyWeight); @@ -447,7 +439,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), (candidate.isSelD0() != 0) ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly, cent, efficiencyWeight); } entryD0CandRecoInfo(invMassD0, invMassD0bar, candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); @@ -479,7 +471,7 @@ struct HfCorrelatorD0Hadrons { // ========== soft pion removal =================================================== double invMassDstar1 = 0., invMassDstar2 = 0.; auto pSum2 = RecoDecay::p2(candidate.pVector(), track.pVector()); - auto ePion = track.energy(massPi); + auto ePion = track.energy(MassPiPlus); invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); @@ -536,6 +528,7 @@ struct HfCorrelatorD0Hadrons { SelectedCandidatesMcRecMl const& candidates, aod::McParticles const& mcParticles) { + BinningType const corrBinning{{zPoolBins, multPoolBins}, true}; // find leading particle if (correlateD0WithLeadingParticle) { leadingIndex = findLeadingParticle(tracks, etaTrackMax.value); @@ -627,7 +620,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), isD0Prompt, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0[0], outputMlD0[1], outputMlD0[2], invMassD0, candidate.pt(), candidate.eta(), isD0Prompt, cent, efficiencyWeight); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar @@ -649,14 +642,14 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), isD0Prompt, cent); + registry.fill(HIST("hMLScoresVsMassVsPtVsEtaVsOriginVsCent"), outputMlD0bar[0], outputMlD0bar[1], outputMlD0bar[2], invMassD0bar, candidate.pt(), candidate.eta(), isD0Prompt, cent, efficiencyWeight); } entryD0CandRecoInfo(invMassD0, invMassD0bar, candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); entryD0CandGenInfo(isD0Prompt); // ===================== Define parameters for soft pion removal ======================== - auto ePiK = RecoDecay::e(candidate.pVectorProng0(), massPi) + RecoDecay::e(candidate.pVectorProng1(), massK); - auto eKPi = RecoDecay::e(candidate.pVectorProng0(), massK) + RecoDecay::e(candidate.pVectorProng1(), massPi); + auto ePiK = RecoDecay::e(candidate.pVectorProng0(), MassPiPlus) + RecoDecay::e(candidate.pVectorProng1(), MassKPlus); + auto eKPi = RecoDecay::e(candidate.pVectorProng0(), MassKPlus) + RecoDecay::e(candidate.pVectorProng1(), MassPiPlus); // ============== D-h correlation dedicated section ==================================== @@ -684,7 +677,7 @@ struct HfCorrelatorD0Hadrons { double invMassDstar1 = 0, invMassDstar2 = 0; bool isSoftPiD0 = false, isSoftPiD0bar = false; auto pSum2 = RecoDecay::p2(candidate.pVector(), track.pVector()); - auto ePion = track.energy(massPi); + auto ePion = track.energy(MassPiPlus); invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); @@ -856,7 +849,7 @@ struct HfCorrelatorD0Hadrons { poolBin, correlationStatus, cent); - entryD0HadronRecoInfo(massD0, massD0, 0); // dummy info + entryD0HadronRecoInfo(MassD0, MassD0, 0); // dummy info entryD0HadronGenInfo(isD0Prompt, particleAssoc.isPhysicalPrimary(), trackOrigin); } // end inner loop (Tracks) } @@ -871,6 +864,7 @@ struct HfCorrelatorD0Hadrons { SelectedCandidatesDataMl const& candidates, SelectedTracks const& tracks) { + BinningType const corrBinning{{zPoolBins, multPoolBins}, true}; for (const auto& collision : collisions) { registry.fill(HIST("hMultFT0M"), collision.multFT0M()); registry.fill(HIST("hZvtx"), collision.posZ()); @@ -897,12 +891,12 @@ struct HfCorrelatorD0Hadrons { // soft pion removal, signal status 1,3 for D0 and 2,3 for D0bar (SoftPi removed), signal status 11,13 for D0 and 12,13 for D0bar (only SoftPi) const auto invMassD0 = HfHelper::invMassD0ToPiK(candidate); const auto invMassD0bar = HfHelper::invMassD0barToKPi(candidate); - auto ePiK = RecoDecay::e(candidate.pVectorProng0(), massPi) + RecoDecay::e(candidate.pVectorProng1(), massK); - auto eKPi = RecoDecay::e(candidate.pVectorProng0(), massK) + RecoDecay::e(candidate.pVectorProng1(), massPi); + auto ePiK = RecoDecay::e(candidate.pVectorProng0(), MassPiPlus) + RecoDecay::e(candidate.pVectorProng1(), MassKPlus); + auto eKPi = RecoDecay::e(candidate.pVectorProng0(), MassKPlus) + RecoDecay::e(candidate.pVectorProng1(), MassPiPlus); double invMassDstar1 = 0., invMassDstar2 = 0.; bool isSoftPiD0 = false, isSoftPiD0bar = false; auto pSum2 = RecoDecay::p2(candidate.pVector(), particleAssoc.pVector()); - auto ePion = particleAssoc.energy(massPi); + auto ePion = particleAssoc.energy(MassPiPlus); invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); std::vector outputMlD0 = {-1., -1., -1.}; @@ -959,6 +953,7 @@ struct HfCorrelatorD0Hadrons { SelectedTracksMcRec const& tracks, aod::McParticles const& mcParticles) { + BinningType const corrBinning{{zPoolBins, multPoolBins}, true}; auto tracksTuple = std::make_tuple(candidates, tracks); Pair const pairMcRec{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; bool isD0Prompt = false; @@ -1004,12 +999,12 @@ struct HfCorrelatorD0Hadrons { // soft pion removal const auto invMassD0 = HfHelper::invMassD0ToPiK(candidate); const auto invMassD0bar = HfHelper::invMassD0barToKPi(candidate); - auto ePiK = RecoDecay::e(candidate.pVectorProng0(), massPi) + RecoDecay::e(candidate.pVectorProng1(), massK); - auto eKPi = RecoDecay::e(candidate.pVectorProng0(), massK) + RecoDecay::e(candidate.pVectorProng1(), massPi); + auto ePiK = RecoDecay::e(candidate.pVectorProng0(), MassPiPlus) + RecoDecay::e(candidate.pVectorProng1(), MassKPlus); + auto eKPi = RecoDecay::e(candidate.pVectorProng0(), MassKPlus) + RecoDecay::e(candidate.pVectorProng1(), MassPiPlus); double invMassDstar1 = 0., invMassDstar2 = 0.; bool isSoftPiD0 = false, isSoftPiD0bar = false; auto pSum2 = RecoDecay::p2(candidate.pVector(), particleAssoc.pVector()); - auto ePion = particleAssoc.energy(massPi); + auto ePion = particleAssoc.energy(MassPiPlus); invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); @@ -1128,7 +1123,7 @@ struct HfCorrelatorD0Hadrons { int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); bool isD0Prompt = particleTrigg.originMcGen() == RecoDecay::OriginType::Prompt; entryD0HadronPair(getDeltaPhi(particleAssoc.phi(), particleTrigg.phi()), particleAssoc.eta() - particleTrigg.eta(), particleTrigg.pt(), particleAssoc.pt(), poolBin, correlationStatus, cent); - entryD0HadronRecoInfo(massD0, massD0, 0); // dummy info + entryD0HadronRecoInfo(MassD0, MassD0, 0); // dummy info entryD0HadronGenInfo(isD0Prompt, particleAssoc.isPhysicalPrimary(), trackOrigin); } } diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 7c14da3fe30..77e43224d52 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -984,9 +984,6 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hInputCheckD0OrD0barMcGen"), nDorDbarevent); } - auto massD = MassD0; - auto massDbar = MassD0Bar; - for (const auto& particle1 : mcParticles) { // check if the particle is D0 or D0bar if (std::abs(particle1.pdgCode()) != Pdg::kD0) { @@ -1112,7 +1109,7 @@ struct HfCorrelatorDMesonPairs { } // Fill pair Selection Status - entryD0PairMcGen(particle1.pt(), particle2.pt(), particle1.y(), particle2.y(), particle1.phi(), particle2.phi(), massD, massDbar, massD, massDbar, pairType, particleType1, particleType2); + entryD0PairMcGen(particle1.pt(), particle2.pt(), particle1.y(), particle2.y(), particle1.phi(), particle2.phi(), MassD0, MassD0Bar, MassD0, MassD0Bar, pairType, particleType1, particleType2); entryD0PairMcGenInfo(originGen1, originGen2, matchedGen1, matchedGen2); } // end inner loop diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx new file mode 100644 index 00000000000..d58da7fccd6 --- /dev/null +++ b/PWGHF/HFC/TableProducer/correlatorDplusDplusReduced.cxx @@ -0,0 +1,393 @@ +// 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 correlatorDplusDplusReduced.cxx +/// \brief Writer of D+ → π+ K- π+ candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples or ML training. +/// In this file are defined and filled the output tables +/// +/// \author Valerio DI BELLA , IPHC Strasbourg +/// Based on the code of Alexandre Bigot , IPHC Strasbourg + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/Zorro.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_centrality; + +/// Writes the full information in an output TTree +struct HfCorrelatorDplusDplusReduced { + Produces rowCandidateFull; + Produces rowCandidateLite; + Produces rowCandidateTiny; + Produces rowCandidateFullEvents; + Produces rowCandidateMl; + + Produces rowCandidateMcParticles; + Produces rowCandidateMcCollisions; + + Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + Configurable fillCandidateTinyTable{"fillCandidateTinyTable", false, "Switch to fill tiny table with candidate properties"}; + // parameters for production of training samples + Configurable fillCorrBkgs{"fillCorrBkgs", false, "Flag to fill derived tables with correlated background candidates"}; + Configurable> classMlIndexes{"classMlIndexes", {0, 2}, "Indexes of ML bkg and non-prompt scores."}; + Configurable centEstimator{"centEstimator", 0, "Centrality estimation (None: 0, FT0C: 2, FT0M: 3)"}; + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Enables processing of skimmed datasets"}; + Configurable skipSingleD{"skipSingleD", true, "Skip collisions with one or less D candidates"}; + + HfHelper hfHelper; + + Service ccdb; + + using SelectedCandidates = soa::Filtered>; + using SelectedCandidatesMc = soa::Filtered>; + using MatchedGenCandidatesMc = soa::Filtered>; + using SelectedCandidatesMcWithMl = soa::Filtered>; + using CollisionsCent = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) != 0)); + + Preslice tracksPerCollision = o2::aod::track::collisionId; + Preslice mcParticlesPerMcCollision = o2::aod::mcparticle::mcCollisionId; + + Partition reconstructedCandSig = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition reconstructedCandSigMl = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); + + HistogramRegistry registry{"registry"}; + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + void init(InitContext const&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + if (cfgSkimmedProcessing) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + } + + template + void fillEvent(const T& collision) + { + rowCandidateFullEvents( + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ()); + } + + template + void fillCandidateTable(const T& candidate, int localEvIdx = -1, int sign = 1) + { + int8_t flagMc = 0; + int8_t originMc = 0; + int8_t channelMc = 0; + + if constexpr (DoMc) { + flagMc = candidate.flagMcMatchRec(); + originMc = candidate.originMcRec(); + channelMc = candidate.flagMcDecayChanRec(); + } + + std::vector outputMl = {-999., -999.}; + if constexpr (DoMl) { + for (unsigned int iclass = 0; iclass < classMlIndexes->size(); iclass++) { + outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMlIndexes->at(iclass)]; + } + rowCandidateMl( + outputMl[0], + outputMl[1]); + } + + float cent{-1.}; + auto coll = candidate.template collision_as(); + if (std::is_same_v && centEstimator != CentralityEstimator::None) { + cent = getCentralityColl(coll, centEstimator); + } + + if (fillCandidateTinyTable) { + rowCandidateTiny( + candidate.isSelDplusToPiKPi(), + hfHelper.invMassDplusToPiKPi(candidate), + sign * candidate.pt(), + candidate.eta(), + candidate.phi(), + localEvIdx, + flagMc, + originMc, + channelMc); + } else if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.impactParameterZ0(), + candidate.impactParameterZ1(), + candidate.impactParameterZ2(), + candidate.nSigTpcPi0(), + candidate.nSigTpcKa0(), + candidate.nSigTofPi0(), + candidate.nSigTofKa0(), + candidate.tpcTofNSigmaPi0(), + candidate.tpcTofNSigmaKa0(), + candidate.nSigTpcPi1(), + candidate.nSigTpcKa1(), + candidate.nSigTofPi1(), + candidate.nSigTofKa1(), + candidate.tpcTofNSigmaPi1(), + candidate.tpcTofNSigmaKa1(), + candidate.nSigTpcPi2(), + candidate.nSigTpcKa2(), + candidate.nSigTofPi2(), + candidate.nSigTofKa2(), + candidate.tpcTofNSigmaPi2(), + candidate.tpcTofNSigmaKa2(), + candidate.isSelDplusToPiKPi(), + hfHelper.invMassDplusToPiKPi(candidate), + sign * candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yDplus(candidate), + cent, + localEvIdx, + flagMc, + originMc, + channelMc); + } else { + rowCandidateFull( + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.impactParameterNormalised2(), + candidate.ptProng2(), + RecoDecay::p(candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxProng2(), + candidate.pyProng2(), + candidate.pzProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + candidate.errorImpactParameter2(), + candidate.impactParameterZ0(), + candidate.impactParameterZ1(), + candidate.impactParameterZ2(), + candidate.errorImpactParameterZ0(), + candidate.errorImpactParameterZ1(), + candidate.errorImpactParameterZ2(), + candidate.nSigTpcPi0(), + candidate.nSigTpcKa0(), + candidate.nSigTofPi0(), + candidate.nSigTofKa0(), + candidate.tpcTofNSigmaPi0(), + candidate.tpcTofNSigmaKa0(), + candidate.nSigTpcPi1(), + candidate.nSigTpcKa1(), + candidate.nSigTofPi1(), + candidate.nSigTofKa1(), + candidate.tpcTofNSigmaPi1(), + candidate.tpcTofNSigmaKa1(), + candidate.nSigTpcPi2(), + candidate.nSigTpcKa2(), + candidate.nSigTofPi2(), + candidate.nSigTofKa2(), + candidate.tpcTofNSigmaPi2(), + candidate.tpcTofNSigmaKa2(), + candidate.isSelDplusToPiKPi(), + hfHelper.invMassDplusToPiKPi(candidate), + sign * candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + hfHelper.ctDplus(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yDplus(candidate), + hfHelper.eDplus(candidate), + cent, + localEvIdx, + flagMc, + originMc, + channelMc); + } + } + + void processData(aod::Collisions const& collisions, + SelectedCandidates const& candidates, + aod::Tracks const&, + aod::BCsWithTimestamps const&) + { + static int lastRunNumber = -1; + // reserve memory + rowCandidateFullEvents.reserve(collisions.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + + for (const auto& collision : collisions) { + if (cfgSkimmedProcessing) { + auto bc = collision.bc_as(); + int runNumber = bc.runNumber(); + if (lastRunNumber != runNumber) { + lastRunNumber = runNumber; + LOGF(info, "Initializing Zorro for run %d", runNumber); + uint64_t currentTimestamp = bc.timestamp(); + zorro.initCCDB(ccdb.service, runNumber, currentTimestamp, "fHfDoubleCharm3P"); + zorro.populateHistRegistry(registry, runNumber); + } + zorro.isSelected(bc.globalBC()); + } + + const auto colId = collision.globalIndex(); + auto candidatesInThisCollision = candidates.sliceBy(tracksPerCollision, colId); + if (skipSingleD) + if (candidatesInThisCollision.size() < 2) // o2-linter: disable=magic-number (number of candidate must be larger than 1) + continue; + fillEvent(collision); + for (const auto& candidate : candidatesInThisCollision) { + auto prongCandidate = candidate.prong1_as(); + auto candidateSign = -prongCandidate.sign(); + fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex(), candidateSign); + } + } + } + PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processData, "Process data per collision", false); + + void processMcRec(aod::Collisions const& collisions, + SelectedCandidatesMc const& candidates, + aod::Tracks const&) + { + // reserve memory + rowCandidateFullEvents.reserve(collisions.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + + for (const auto& collision : collisions) { // No skimming for MC data. No Zorro ! + const auto colId = collision.globalIndex(); + auto candidatesInThisCollision = candidates.sliceBy(tracksPerCollision, colId); + if (skipSingleD) + if (candidatesInThisCollision.size() < 2) // o2-linter: disable=magic-number (number of candidate must be larger than 1) + continue; + fillEvent(collision); + for (const auto& candidate : candidatesInThisCollision) { + auto prongCandidate = candidate.prong1_as(); + auto candidateSign = -prongCandidate.sign(); + fillCandidateTable(candidate, rowCandidateFullEvents.lastIndex(), candidateSign); + } + } + } + PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processMcRec, "Process data per collision", false); + + void processMcGen(aod::McCollisions const& mccollisions, + MatchedGenCandidatesMc const& mcparticles) + { + // reserve memory + rowCandidateMcCollisions.reserve(mccollisions.size()); + rowCandidateMcParticles.reserve(mcparticles.size()); + + for (const auto& mccollision : mccollisions) { // No skimming for MC data. No Zorro ! + const auto colId = mccollision.globalIndex(); + const auto particlesInThisCollision = mcparticles.sliceBy(mcParticlesPerMcCollision, colId); + if (skipSingleD) + if (particlesInThisCollision.size() < 2) // o2-linter: disable=magic-number (number of candidate must be larger than 1) + continue; + rowCandidateMcCollisions( + mccollision.posX(), + mccollision.posY(), + mccollision.posZ()); + for (const auto& particle : particlesInThisCollision) { + rowCandidateMcParticles( + particle.pt(), + particle.eta(), + particle.phi(), + particle.y(), + rowCandidateMcCollisions.lastIndex(), + particle.flagMcMatchGen(), + particle.flagMcDecayChanGen(), + particle.originMcGen()); + } + } + } + PROCESS_SWITCH(HfCorrelatorDplusDplusReduced, processMcGen, "Process MC data at the generator level", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index 37fdb8acea8..3f7f48f84d3 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -186,6 +186,11 @@ struct HfCorrelatorDplusHadrons { Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for Dplus"}; // 7 corresponds to topo+PID cuts Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; + Configurable removeUnreconstructedGenCollisions{"removeUnreconstructedGenCollisions", true, "Remove generator-level collisions that were not reconstructed"}; + Configurable removeCollWSplitVtx{"removeCollWSplitVtx", true, "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 zVtxMax{"zVtxMax", 10., "max. position-z of the reconstructed collision"}; 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"}; @@ -210,6 +215,7 @@ struct HfCorrelatorDplusHadrons { // Event Mixing for the Data Mode using SelCollisionsWithDplus = soa::Filtered>; using SelCollisionsWithDplusMc = soa::Filtered>; // collisionFilter applied + using CollisionsMc = soa::Join; using CandidatesDplusData = soa::Filtered>; // Event Mixing for the MCRec Mode using CandidatesDplusMcRec = soa::Filtered>; @@ -225,6 +231,9 @@ struct HfCorrelatorDplusHadrons { // 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); + Preslice presliceMc{aod::mcparticle::mcCollisionId}; + Preslice candMcGenPerMcCollision = o2::aod::mcparticle::mcCollisionId; + PresliceUnsorted> recoCollisionsPerMcCollision = o2::aod::mccollisionlabel::mcCollisionId; // Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); 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"}; @@ -307,9 +316,129 @@ struct HfCorrelatorDplusHadrons { 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}}); + registry.add("hFakeCollision", "Fake collision counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake coll"}}}); corrBinning = {{binsZVtx, binsMultiplicity}, true}; } + template + void runMcGenDplusHadronAnalysis(const ParticleContainer& particlesToLoop, const AssocContainer& groupedMcParticles, int poolBin, int& counterDplusHadron) + { + for (const auto& particle : particlesToLoop) { + + if (std::abs(particle.pdgCode()) != Pdg::kDPlus) { + continue; + } + + if (std::abs(particle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { + continue; + } + + double yD = RecoDecay::y(particle.pVector(), MassDPlus); + + if (std::abs(yD) > yCandGenMax || + particle.pt() < ptCandMin || + particle.pt() > ptCandMax) { + continue; + } + + std::vector listDaughters{}; + std::array const arrDaughDplusPDG = {+kPiPlus, -kKPlus, kPiPlus}; + std::array prongsId{}; + + RecoDecay::getDaughters(particle, &listDaughters, arrDaughDplusPDG, 2); + + if (listDaughters.size() != NDaughters) { + continue; + } + + bool isDaughtersOk = true; + int counterDaughters = 0; + + for (const auto& dauIdx : listDaughters) { + auto daughI = particlesToLoop.rawIteratorAt(dauIdx - particlesToLoop.offset()); + + if (std::abs(daughI.eta()) >= EtaDaughtersMax) { + isDaughtersOk = false; + break; + } + + prongsId[counterDaughters++] = daughI.globalIndex(); + } + + if (!isDaughtersOk) { // Skip this D+ candidate if any daughter fails eta cut + continue; + } + counterDplusHadron++; + + registry.fill(HIST("hDplusBin"), poolBin); + registry.fill(HIST("hPtCandMCGen"), particle.pt()); + registry.fill(HIST("hEtaMcGen"), particle.eta()); + registry.fill(HIST("hPhiMcGen"), RecoDecay::constrainAngle(particle.phi(), -PIHalf)); + registry.fill(HIST("hYMCGen"), yD); + + // Prompt / Non-prompt separation + bool isDplusPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; + bool isDplusNonPrompt = particle.originMcGen() == RecoDecay::OriginType::NonPrompt; + + if (isDplusPrompt) { + registry.fill(HIST("hPtCandMcGenPrompt"), particle.pt()); + } else if (isDplusNonPrompt) { + registry.fill(HIST("hPtCandMcGenNonPrompt"), particle.pt()); + } + + // Count triggers + registry.fill(HIST("hcountDplustriggersMCGen"), 0, particle.pt()); + + for (const auto& particleAssoc : groupedMcParticles) { + + if (std::abs(particleAssoc.eta()) > etaTrackMax || + particleAssoc.pt() < ptTrackMin || + particleAssoc.pt() > ptTrackMax) { + continue; + } + + // Remove daughters if requested + if (removeDaughters) { + if (particleAssoc.globalIndex() == prongsId[0] || + particleAssoc.globalIndex() == prongsId[1] || + particleAssoc.globalIndex() == prongsId[2]) { + continue; + } + } + + // Particle species selection + 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 trackOrigin = RecoDecay::getCharmHadronOrigin(groupedMcParticles, + particleAssoc, + true); + + registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); + entryDplusHadronPair( + getDeltaPhi(particleAssoc.phi(), particle.phi()), + particleAssoc.eta() - particle.eta(), + particle.pt(), + particleAssoc.pt(), + poolBin); + + entryDplusHadronRecoInfo(MassDPlus, true); + entryDplusHadronGenInfo(isDplusPrompt, + particleAssoc.isPhysicalPrimary(), + trackOrigin); + } + } + } + /// 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, TracksData const& tracks, @@ -535,99 +664,65 @@ 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(SelCollisionsWithDplusMc::iterator const& mcCollision, + void processMcGen(CollisionsMc const& mcCollisions, + soa::Join const& collisions, CandDplusMcGen const& mcParticles) { - int counterDplusHadron = 0; - registry.fill(HIST("hMCEvtCount"), 0); - BinningTypeMcGen const corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; - int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); - registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); - // 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 (std::abs(particle1.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { - continue; - } - double const yD = RecoDecay::y(particle1.pVector(), MassDPlus); - if (std::abs(yD) >= yCandMax || particle1.pt() <= ptCandMin) { - continue; - } - std::vector listDaughters{}; - std::array const arrDaughDplusPDG = {+kPiPlus, -kKPlus, kPiPlus}; - std::array prongsId{}; - listDaughters.clear(); - RecoDecay::getDaughters(particle1, &listDaughters, arrDaughDplusPDG, 2); - int counterDaughters = 0; - if (listDaughters.size() != NDaughters) - continue; - bool isDaughtersOk = true; - for (const auto& dauIdx : listDaughters) { - auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); - if (std::abs(daughI.eta()) >= EtaDaughtersMax) { - isDaughtersOk = false; - break; - } - counterDaughters += 1; - prongsId[counterDaughters - 1] = daughI.globalIndex(); - } - if (!isDaughtersOk) - continue; // Skip this D+ candidate if any daughter fails eta cut - counterDplusHadron++; + for (const auto& mcCollision : mcCollisions) { - 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(), -PIHalf)); - registry.fill(HIST("hYMCGen"), yD); + int counterDplusHadron = 0; + registry.fill(HIST("hMCEvtCount"), 0); - // prompt and non-prompt division - bool isDplusPrompt = particle1.originMcGen() == RecoDecay::OriginType::Prompt; - bool isDplusNonPrompt = particle1.originMcGen() == RecoDecay::OriginType::NonPrompt; - if (isDplusPrompt) { - registry.fill(HIST("hPtCandMcGenPrompt"), particle1.pt()); - } else if (isDplusNonPrompt) { - registry.fill(HIST("hPtCandMcGenNonPrompt"), particle1.pt()); - } + int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); + registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); - // Dplus Hadron correlation dedicated section - // if it's a Dplus particle, search for Hadron and evaluate correlations - registry.fill(HIST("hcountDplustriggersMCGen"), 0, particle1.pt()); // to count trigger Dplus for normalisation) - for (const auto& particleAssoc : mcParticles) { - if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { + const auto groupedMcParticles = mcParticles.sliceBy(candMcGenPerMcCollision, mcCollision.globalIndex()); + const auto groupedCollisions = collisions.sliceBy(recoCollisionsPerMcCollision, mcCollision.globalIndex()); + + if (removeUnreconstructedGenCollisions) { + + if (groupedCollisions.size() < 1) { continue; } - if (removeDaughters) { - 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)) { + + if (groupedCollisions.size() > 1 && removeCollWSplitVtx) { continue; } - if (!particleAssoc.isPhysicalPrimary()) { - continue; + + for (const auto& collision : groupedCollisions) { + + if (useSel8 && !collision.sel8()) { + continue; + } + + if (std::abs(collision.posZ()) > zVtxMax) { + continue; + } + + if (selNoSameBunchPileUpColl && + !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + continue; + } + + if (!collision.has_mcCollision()) { + registry.fill(HIST("hFakeCollision"), 0.); + continue; + } + + // MC particles with reconstructed-collision selection + runMcGenDplusHadronAnalysis(groupedMcParticles, groupedMcParticles, poolBin, counterDplusHadron); } - 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)); + } else { + // MC particles without reconstructed-collision selection (preliminary approval approach) + runMcGenDplusHadronAnalysis(groupedMcParticles, groupedMcParticles, poolBin, counterDplusHadron); + } + + registry.fill(HIST("hcountDplusHadronPerEvent"), counterDplusHadron); + registry.fill(HIST("hZvtx"), mcCollision.posZ()); + } } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcGen, "Process MC Gen mode", false); diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 562df81322d..e2b85b70fc0 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -176,6 +177,7 @@ struct HfCorrelatorDsHadrons { Produces candSelInfo; Produces assocTrackReduced; Produces assocTrackSelInfo; + Produces assocTrackPidInfo; Configurable fillHistoData{"fillHistoData", true, "Flag for filling histograms in data processes"}; Configurable fillHistoMcRec{"fillHistoMcRec", true, "Flag for filling histograms in MC Rec processes"}; @@ -759,25 +761,23 @@ struct HfCorrelatorDsHadrons { listDaughters.clear(); RecoDecay::getDaughters(particle, &listDaughters, arrDaughDsPDG, 2); int counterDaughters = 0; + // Assign Ds charge sign int chargeDs = 0; + if (particle.pdgCode() == kDS) { + chargeDs = 1; + } else { + chargeDs = -1; + } + // Find Ds daughters if (listDaughters.size() == NDaughtersDs) { for (const auto& dauIdx : listDaughters) { // auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); auto daughI = groupedMcParticles.rawIteratorAt(dauIdx - groupedMcParticles.offset()); counterDaughters += 1; - if (counterDaughters == 1) { - if (daughI.pdgCode() == kKPlus) { - chargeDs = 1; - } else { - chargeDs = -1; - } - } prongsId[counterDaughters - 1] = daughI.globalIndex(); } } - int numberOfCorrKaons = 0; - // Ds Hadron correlation dedicated section for (const auto& particleAssoc : groupedMcParticles) { if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { @@ -792,46 +792,37 @@ struct HfCorrelatorDsHadrons { if (!particleAssoc.isPhysicalPrimary()) { continue; } - - if (isDsPrompt) { - registry.fill(HIST("hCorrAllPrimaryParticles"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - if (std::abs(particleAssoc.pdgCode()) == kPiPlus) { - registry.fill(HIST("hCorrAllPrimaryHadrons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - registry.fill(HIST("hCorrAllPrimaryPions"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - } else if (std::abs(particleAssoc.pdgCode()) == kKPlus) { - registry.fill(HIST("hCorrAllPrimaryHadrons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - registry.fill(HIST("hCorrAllPrimaryKaons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - } else if (std::abs(particleAssoc.pdgCode()) == kProton) { - registry.fill(HIST("hCorrAllPrimaryHadrons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - registry.fill(HIST("hCorrAllPrimaryProtons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + if (pidTrkApplied) { + // MC truth match + if (trkPIDspecies->at(0) == o2::track::PID::Kaon && std::abs(particleAssoc.pdgCode()) != kKPlus) { + continue; + } + if (trkPIDspecies->at(0) == o2::track::PID::Pion && std::abs(particleAssoc.pdgCode()) != kPiPlus) { + continue; } - if (pidTrkApplied) { - if (((chargeDs == 1) && (particleAssoc.pdgCode() == kKPlus)) || ((chargeDs == -1) && (particleAssoc.pdgCode() == kKMinus))) { // LS pairs - registry.fill(HIST("hCorrKaonsLSPairs"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - numberOfCorrKaons++; - } - if (((chargeDs == 1) && (particleAssoc.pdgCode() == kKMinus)) || ((chargeDs == -1) && (particleAssoc.pdgCode() == kKPlus))) { // ULS pairs - registry.fill(HIST("hCorrKaonsULSPairs"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); - numberOfCorrKaons++; - } + if (trkPIDspecies->at(0) == o2::track::PID::Proton && std::abs(particleAssoc.pdgCode()) != kProton) { + continue; } } + int chargeParticle = 0; + if ((particleAssoc.pdgCode() == kElectron) || (particleAssoc.pdgCode() == kMuonMinus) || (particleAssoc.pdgCode() == kPiMinus) || (particleAssoc.pdgCode()) == kKMinus || (particleAssoc.pdgCode() == kProtonBar)) { + chargeParticle = -1; + } else { + chargeParticle = 1; + } // 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(), + particle.pt() * chargeDs, + particleAssoc.pt() * chargeParticle, poolBin, 0); entryDsHadronRecoInfo(MassDS, true, isDecayChan); entryDsHadronGenInfo(isDsPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); } // end loop generated particles - if (numberOfCorrKaons == 0) { - registry.fill(HIST("hDsWoKaons"), numberOfCorrKaons); - } } // if statement for Ds selection } // end loop generated Ds } // end loop reconstructed collision @@ -900,6 +891,15 @@ struct HfCorrelatorDsHadrons { assocTrackReduced(indexHfcReducedCollision, track.globalIndex(), track.phi(), track.eta(), track.pt() * track.sign()); assocTrackSelInfo(indexHfcReducedCollision, track.tpcNClsCrossedRows(), track.itsClusterMap(), track.itsNCls(), track.dcaXY(), track.dcaZ()); + if (trkPIDspecies->at(0) == o2::track::PID::Kaon) { + assocTrackPidInfo(track.tpcNSigmaKa(), track.tofNSigmaKa()); + } + if (trkPIDspecies->at(0) == o2::track::PID::Pion) { + assocTrackPidInfo(track.tpcNSigmaPi(), track.tofNSigmaPi()); + } + if (trkPIDspecies->at(0) == o2::track::PID::Proton) { + assocTrackPidInfo(track.tpcNSigmaPr(), track.tofNSigmaPr()); + } } collReduced(collision.multFT0M(), collision.numContrib(), collision.posZ()); @@ -1029,7 +1029,7 @@ struct HfCorrelatorDsHadrons { isDsPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; // Ds Signal isDsSignal = std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; - isDecayChan = candidate.flagMcDecayChanRec() == decayChannel; + isDecayChan = candidate.flagMcDecayChanRec() == channelsResonant[decayChannel]; if (pAssoc.has_mcParticle()) { auto mcParticle = pAssoc.template mcParticle_as(); isPhysicalPrimary = mcParticle.isPhysicalPrimary(); @@ -1095,12 +1095,38 @@ struct HfCorrelatorDsHadrons { if (!particleAssoc.isPhysicalPrimary()) { continue; } + if (pidTrkApplied) { + // MC truth match + if (trkPIDspecies->at(0) == o2::track::PID::Kaon && std::abs(particleAssoc.pdgCode()) != kKPlus) { + continue; + } + if (trkPIDspecies->at(0) == o2::track::PID::Pion && std::abs(particleAssoc.pdgCode()) != kPiPlus) { + continue; + } + if (trkPIDspecies->at(0) == o2::track::PID::Proton && std::abs(particleAssoc.pdgCode()) != kProton) { + continue; + } + } + + int chargeDs = 0; + if (candidate.pdgCode() == kDS) { + chargeDs = 1; + } else { + chargeDs = -1; + } + + int chargeParticle = 0; + if ((particleAssoc.pdgCode() == kElectron) || (particleAssoc.pdgCode() == kMuonMinus) || (particleAssoc.pdgCode() == kPiMinus) || (particleAssoc.pdgCode()) == kKMinus || (particleAssoc.pdgCode() == kProtonBar)) { + chargeParticle = -1; + } else { + chargeParticle = 1; + } int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); bool isDsPrompt = candidate.originMcGen() == RecoDecay::OriginType::Prompt; entryDsHadronPair(getDeltaPhi(particleAssoc.phi(), candidate.phi()), particleAssoc.eta() - candidate.eta(), - candidate.pt(), - particleAssoc.pt(), + candidate.pt() * chargeDs, + particleAssoc.pt() * chargeParticle, poolBin, 0); entryDsHadronRecoInfo(MassDS, true, true); diff --git a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx index f40cf7d279a..093ba4c8666 100644 --- a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx @@ -36,8 +36,10 @@ #include #include +#include #include +#include #include #include @@ -138,8 +140,21 @@ struct HfCorrelatorHfeHadrons { registry.add("hMCgenInclusiveEHCorrl", "Sparse for Delta phi and Delta eta for McGen Electron pair with Hadron;p_{T}^{e} (GeV#it{/c});p_{T}^{h} (GeV#it{/c});#Delta#varphi;#Delta#eta;", {HistType::kTHnSparseF, {{axisPt}, {axisPt}, {axisDeltaPhi}, {axisDeltaEta}}}); registry.add("hptElectron", "hptElectron", {HistType::kTH1D, {axisPt}}); registry.add("hptHadron", "hptHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hptHadronMcRec", "hptHadronMcRec", {HistType::kTH1D, {axisPt}}); + registry.add("hptHadronMcRecPrimary", "hptHadronMcRecPrimary", {HistType::kTH1D, {axisPt}}); + registry.add("hMCRecptEleHadron", "hMCRecptEleHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCRecptMuonHadron", "hMCRecptMuonHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCRecptPionHadron", "hMCRecptPionHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCRecptKaonHadron", "hMCRecptKaonHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCRecptProtonHadron", "hMCRecptProtonHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCgenptHadron", "hMCgenptHadron", {HistType::kTH1D, {axisPt}}); registry.add("hMCgenptHadronprimary", "hMCgenptHadronprimary", {HistType::kTH1D, {axisPt}}); + registry.add("hMCgenptEleHadron", "hMCgenptEleHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCgenptMuonHadron", "hMCgenptMuonHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCgenptPionHadron", "hMCgenptPionHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCgenptKaonHadron", "hMCgenptKaonHadron", {HistType::kTH1D, {axisPt}}); + registry.add("hMCgenptProtonHadron", "hMCgenptProtonHadron", {HistType::kTH1D, {axisPt}}); registry.add("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;", {HistType::kTHnSparseF, {{axisPt}, {axisPt}, {axisDeltaPhi}, {axisDeltaEta}}}); registry.add("hMixEventLSEHCorrel", "Sparse for mix event Delta phi and Delta eta Like sign Electron pair with Hadron;p_{T}^{e} (GeV#it{/c});p_{T}^{h} (GeV#it{/c});#Delta#varphi;#Delta#eta;", {HistType::kTHnSparseF, {{axisPt}, {axisPt}, {axisDeltaPhi}, {axisDeltaEta}}}); @@ -173,8 +188,8 @@ struct HfCorrelatorHfeHadrons { } // Electron-hadron Correlation - template - void fillCorrelation(CollisionType const& collision, ElectronType const& electrons, TracksType const& tracks, BcType const&) + template + void fillCorrelation(CollisionType const& collision, ElectronType const& electrons, TracksType const& tracks, BcType const&, McParticlesType const&) { if (!(isRun3 ? collision.sel8() : (collision.sel7() && collision.alias_bit(kINT7)))) { return; @@ -192,6 +207,7 @@ struct HfCorrelatorHfeHadrons { } registry.fill(HIST("hNevents"), 1); + // Add hadron Table For Mix Event Electron Hadron correlation if (!skipEventTableFilling) { registry.fill(HIST("hZvertex"), collision.posZ()); @@ -199,8 +215,38 @@ struct HfCorrelatorHfeHadrons { if (!selAssoHadron(hTrack)) { continue; } + + // Mc rec hadron efficiency + if constexpr (IsMc) { + if (hTrack.has_mcParticle()) { + auto mcParticle = hTrack.template mcParticle_as(); + 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)) { + continue; + } + + registry.fill(HIST("hptHadronMcRec"), hTrack.pt()); + if (mcParticle.isPhysicalPrimary()) { + + registry.fill(HIST("hptHadronMcRecPrimary"), hTrack.pt()); + + if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hMCRecptEleHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hMCRecptMuonHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hMCRecptPionHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hMCRecptKaonHadron"), hTrack.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hMCRecptProtonHadron"), hTrack.pt()); + } + } + } + } registry.fill(HIST("hTracksBin"), poolBin); + registry.fill(HIST("hptHadron"), hTrack.pt()); + entryHadron(hTrack.phi(), hTrack.eta(), hTrack.pt(), poolBin, gCollisionId, timeStamp); } } @@ -381,22 +427,22 @@ struct HfCorrelatorHfeHadrons { TableTracks const& tracks, aod::BCsWithTimestamps const& bcs) { - fillCorrelation(collision, electrons, tracks, bcs); + fillCorrelation(collision, electrons, tracks, bcs, 0); } - PROCESS_SWITCH(HfCorrelatorHfeHadrons, processData, "Process for Data", true); + PROCESS_SWITCH(HfCorrelatorHfeHadrons, processData, "Process for Data", false); // ======= Process starts for McRec, Same event ============ void processMcRec(McTableCollision const& mcCollision, aod::HfCorrSelEl const& mcElectrons, McTableTracks const& mcTracks, - aod::BCsWithTimestamps const& bcs) + aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticle) { - fillCorrelation(mcCollision, mcElectrons, mcTracks, bcs); + fillCorrelation(mcCollision, mcElectrons, mcTracks, bcs, mcParticle); } - PROCESS_SWITCH(HfCorrelatorHfeHadrons, processMcRec, "Process MC Reco mode", false); + PROCESS_SWITCH(HfCorrelatorHfeHadrons, processMcRec, "Process MC Reco mode", true); void processMcGen(McGenTableCollision const& mcCollision, aod::McParticles const& mcParticles, aod::HfMcGenSelEl const& electrons) { @@ -411,11 +457,25 @@ struct HfCorrelatorHfeHadrons { if (particleMc.pt() < ptTrackMin) { continue; } - + if ((std::abs(particleMc.pdgCode()) != kElectron) && (std::abs(particleMc.pdgCode()) != kMuonMinus) && (std::abs(particleMc.pdgCode()) != kPiPlus) && (std::abs(particleMc.pdgCode()) != kKPlus) && (std::abs(particleMc.pdgCode()) != kProton)) { + continue; + } registry.fill(HIST("hMCgenptHadron"), particleMc.pt()); if (particleMc.isPhysicalPrimary()) { registry.fill(HIST("hMCgenptHadronprimary"), particleMc.pt()); + + if (std::abs(particleMc.pdgCode()) == kElectron) { + registry.fill(HIST("hMCgenptEleHadron"), particleMc.pt()); + } else if (std::abs(particleMc.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hMCgenptMuonHadron"), particleMc.pt()); + } else if (std::abs(particleMc.pdgCode()) == kPiPlus) { + registry.fill(HIST("hMCgenptPionHadron"), particleMc.pt()); + } else if (std::abs(particleMc.pdgCode()) == kKPlus) { + registry.fill(HIST("hMCgenptKaonHadron"), particleMc.pt()); + } else if (std::abs(particleMc.pdgCode()) == kProton) { + registry.fill(HIST("hMCgenptProtonHadron"), particleMc.pt()); + } } } diff --git a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx index 62a8ee5bc8d..960c00485b3 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx @@ -242,7 +242,7 @@ struct HfCorrelatorLcHadrons { Configurable useCentrality{"useCentrality", false, "Flag for centrality dependent analyses"}; SliceCache cache; - Service pdg; + Service pdg{}; int leadingIndex = 0; bool correlationStatus = false; static constexpr std::size_t NDaughters{3u}; diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index a0dcfbd9f90..0952c89de39 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -369,11 +369,12 @@ struct HfCorrelatorLcScHadrons { Configurable cfgDaughPIDCutsTPCPr{"cfgDaughPIDCutsTPCPr", 3., "max. TPCnSigma Proton"}; Configurable cfgDaughPIDCutsTPCPi{"cfgDaughPIDCutsTPCPi", 2., "max. TPCnSigma Pion"}; Configurable cfgDaughPIDCutsTOFPi{"cfgDaughPIDCutsTOFPi", 2., "max. TOFnSigma Pion"}; - Configurable cfgHypMassWindow{"cfgHypMassWindow", 0.5, "single lambda mass selection"}; + Configurable cfgHypMassWindow{"cfgHypMassWindow", 0.1, "single lambda mass selection"}; + Configurable cfgIsCorrCollMatchV0{"cfgIsCorrCollMatchV0", true, "check if daughter and mother collision are same"}; } cfgV0; SliceCache cache; - Service pdg; + Service pdg{}; int8_t chargeCand = 3; int8_t signSoftPion = 0; int leadingIndex = 0; @@ -595,9 +596,15 @@ struct HfCorrelatorLcScHadrons { for (const auto& v0 : v0s) { auto posTrackV0 = v0.template posTrack_as(); auto negTrackV0 = v0.template negTrack_as(); + if (cfgV0.cfgIsCorrCollMatchV0 && ((v0.collisionId() != posTrackV0.collisionId()) || (v0.collisionId() != negTrackV0.collisionId()))) { + continue; + } - if (isSelectedV0Daughter(posTrackV0, kProton) && isSelectedV0Daughter(negTrackV0, kPiPlus)) { - if (std::abs(o2::constants::physics::MassLambda - v0.mLambda()) < cfgV0.cfgHypMassWindow) { + if (std::abs(o2::constants::physics::MassLambda - v0.mLambda()) < cfgV0.cfgHypMassWindow) { + entryHadron(v0.mLambda(), posTrackV0.eta(), posTrackV0.pt() * posTrackV0.sign(), 0, 0, v0.pt()); + entryTrkPID(posTrackV0.tpcNSigmaPr(), posTrackV0.tpcNSigmaKa(), posTrackV0.tpcNSigmaPi(), posTrackV0.tofNSigmaPr(), posTrackV0.tofNSigmaKa(), posTrackV0.tofNSigmaPi()); + + if (isSelectedV0Daughter(posTrackV0, kProton) && isSelectedV0Daughter(negTrackV0, kPiPlus)) { registry.fill(HIST("hV0Lambda"), v0.mLambda(), v0.pt(), posTrackV0.pt()); registry.fill(HIST("hV0LambdaRefl"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); @@ -617,8 +624,11 @@ struct HfCorrelatorLcScHadrons { } } } - if (isSelectedV0Daughter(negTrackV0, kProton) && isSelectedV0Daughter(posTrackV0, kPiPlus)) { - if (std::abs(o2::constants::physics::MassLambda - v0.mAntiLambda()) < cfgV0.cfgHypMassWindow) { + if (std::abs(o2::constants::physics::MassLambda - v0.mAntiLambda()) < cfgV0.cfgHypMassWindow) { + entryHadron(v0.mAntiLambda(), negTrackV0.eta(), negTrackV0.pt() * negTrackV0.sign(), 0, 0, v0.pt()); + entryTrkPID(negTrackV0.tpcNSigmaPr(), negTrackV0.tpcNSigmaKa(), negTrackV0.tpcNSigmaPi(), negTrackV0.tofNSigmaPr(), negTrackV0.tofNSigmaKa(), negTrackV0.tofNSigmaPi()); + + if (isSelectedV0Daughter(negTrackV0, kProton) && isSelectedV0Daughter(posTrackV0, kPiPlus)) { registry.fill(HIST("hV0Lambda"), v0.mAntiLambda(), v0.pt(), negTrackV0.pt()); registry.fill(HIST("hV0LambdaRefl"), v0.mLambda(), v0.pt(), posTrackV0.pt()); diff --git a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx index f418af0e1fb..5636a0b8fa6 100644 --- a/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx +++ b/PWGHF/HFC/TableProducer/derivedDataCreatorCorrelationsReduced.cxx @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -63,6 +64,7 @@ enum CandidateType { DsToPiKK, D0ToPiK, D0ToKPi, + LcToPKPi, Hadron }; @@ -103,7 +105,7 @@ struct HfDerivedDataCreatorCorrelationsReduced { Configurable> binsPtAssoc{"binsPtAssoc", std::vector{0.2, 1., 2., 50.}, "pT bin limits for associated particles"}; HfEventSelection hfEvSel; // event selection and monitoring - o2::framework::Service ccdb; + o2::framework::Service ccdb{}; SliceCache cache; double massCharm{0.}; @@ -113,22 +115,26 @@ struct HfDerivedDataCreatorCorrelationsReduced { using CandDsData = soa::Filtered>; using CandDplusData = soa::Filtered>; using CandD0Data = soa::Filtered>; + using CandLcData = soa::Filtered>; using TracksData = soa::Filtered>; 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; Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; + Filter filterSelectLcCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag; Filter filterSelectTrkData = (nabs(aod::track::eta) < etaTrkMax) && (aod::track::pt > ptTrkMin) && (aod::track::pt < ptTrkMax) && (nabs(aod::track::dcaXY) < dcaXYTrkMax) && (nabs(aod::track::dcaZ) < dcaZTrkMax); Preslice candsDsPerColl = aod::hf_cand::collisionId; Preslice candsDplusPerColl = aod::hf_cand::collisionId; Preslice candsD0PerColl = aod::hf_cand::collisionId; + Preslice candsLcPerColl = aod::hf_cand::collisionId; Preslice trackIndicesPerColl = aod::track::collisionId; Partition selectedDsToKKPi = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag; Partition selectedDsToPiKK = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; Partition selectedD0ToPiK = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag; Partition selectedD0ToKPi = aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; + Partition selectedLcToPKPi = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag; ConfigurableAxis binsInvMass{"binsInvMass", {300, 1.6, 2.2}, ""}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {100, 0., 10000.}, "Multiplicity as FT0M signal amplitude"}; @@ -152,6 +158,8 @@ struct HfDerivedDataCreatorCorrelationsReduced { massCharm = o2::constants::physics::MassDS; } else if (doprocessD0SameEvent || doprocessD0MixedEvent) { massCharm = o2::constants::physics::MassD0; + } else if (doprocessLcSameEvent || doprocessLcMixedEvent) { + massCharm = o2::constants::physics::MassLambdaCPlus; } else if (doprocessHadronHadronSameEvent || doprocessHadronHadronMixedEvent) { LOG(info) << "Charm mass not set, processing Hadron-Hadron case"; } else { @@ -211,6 +219,9 @@ struct HfDerivedDataCreatorCorrelationsReduced { if constexpr (CandType == CandidateType::D0ToKPi) { return HfHelper::invMassD0barToKPi(candidate); } + if constexpr (CandType == CandidateType::LcToPKPi) { + return HfHelper::invMassLcToPKPi(candidate); + } return -1.; } @@ -245,9 +256,34 @@ struct HfDerivedDataCreatorCorrelationsReduced { outputMl[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } } + if constexpr (CandType == CandidateType::LcToPKPi) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { + outputMl[iclass] = candidate.mlProbLcToPKPi()[classMl->at(iclass)]; + } + } return outputMl; } + /// Cut on rapidity of the candidate + /// \param candidate is the charm hadron candidate + template + bool cutCandRapidity(const TCand& candidate) + { + double y = 0.0; + if constexpr (CandType == CandidateType::DsToKKPi || CandType == CandidateType::DsToPiKK) { + y = HfHelper::yDs(candidate); + } else if constexpr (CandType == CandidateType::DplusToPiKPi) { + y = HfHelper::yDplus(candidate); + } else if constexpr (CandType == CandidateType::D0ToPiK || CandType == CandidateType::D0ToKPi) { + y = HfHelper::yD0(candidate); + } else if constexpr (CandType == CandidateType::LcToPKPi) { + y = HfHelper::yLc(candidate); + } else { + return true; + } + return std::fabs(y) < yCandMax; + } + /// Check event selections for collision and fill the collision table /// \param collision is the collision template @@ -320,6 +356,9 @@ struct HfDerivedDataCreatorCorrelationsReduced { const float collCentrality) { for (const auto& trigCand : trigCands) { + if (!cutCandRapidity(trigCand)) { + continue; + } double trigCandPt = trigCand.pt(); registry.fill(HIST("hPhiVsPtTrig"), RecoDecay::constrainAngle(trigCand.phi(), -o2::constants::math::PIHalf), trigCandPt); registry.fill(HIST("hEtaVsPtTrig"), trigCand.eta(), trigCandPt); @@ -373,6 +412,9 @@ struct HfDerivedDataCreatorCorrelationsReduced { void fillCharmMixedEvent(TTrigCands const& trigCands) { for (const auto& trigCand : trigCands) { + if (!cutCandRapidity(trigCand)) { + continue; + } registry.fill(HIST("hPhiVsPtTrig"), RecoDecay::constrainAngle(trigCand.phi(), -o2::constants::math::PIHalf), trigCand.pt()); registry.fill(HIST("hEtaVsPtTrig"), trigCand.eta(), trigCand.pt()); @@ -534,6 +576,43 @@ struct HfDerivedDataCreatorCorrelationsReduced { } PROCESS_SWITCH(HfDerivedDataCreatorCorrelationsReduced, processD0MixedEvent, "Process Mixed Event for D0 candidates", false); + // Lc with ML selections + void processLcSameEvent(CollsWithCentMult::iterator const& coll, + TracksData const& tracks, + CandLcData const&) + { + auto candsLcToPKPi = selectedLcToPKPi->sliceByCached(aod::hf_cand::collisionId, coll.globalIndex(), cache); + if (forceCharmInCollision && candsLcToPKPi.size() < 1) { + return; + } + float cent{-1.}, mult{-1.}; + if (!checkCollision(coll, cent, mult)) { + return; + } + rowCollisions(mult, coll.numContrib(), cent, coll.posZ()); + fillSameEvent(candsLcToPKPi, tracks, cent); + } + PROCESS_SWITCH(HfDerivedDataCreatorCorrelationsReduced, processLcSameEvent, "Process Same Event for Lc candidates", false); + + // Lc with ML selections + void processLcMixedEvent(CollsWithCentMult::iterator const& coll, + TracksData const& tracks, + CandLcData const&) + { + auto candsLcToPKPi = selectedLcToPKPi->sliceByCached(aod::hf_cand::collisionId, coll.globalIndex(), cache); + if (forceCharmInCollision && candsLcToPKPi.size() < 1) { + return; + } + float cent{-1.}, mult{-1.}; + if (!checkCollision(coll, cent, mult)) { + return; + } + rowCollisions(mult, coll.numContrib(), cent, coll.posZ()); + fillCharmMixedEvent(candsLcToPKPi); + fillTrkMixedEvent(tracks, cent); + } + PROCESS_SWITCH(HfDerivedDataCreatorCorrelationsReduced, processLcMixedEvent, "Process Mixed Event for Lc candidates", false); + // Hadron Hadron Same Event void processHadronHadronSameEvent(CollsWithCentMult::iterator const& coll, TracksData const& tracks) diff --git a/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx b/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx index 22956fa8d89..eb197529980 100644 --- a/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx +++ b/PWGHF/HFC/TableProducer/producerCharmHadronsTrackFemtoDream.cxx @@ -32,6 +32,7 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/ZorroSummary.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -41,6 +42,7 @@ #include #include +#include #include #include #include @@ -58,6 +60,7 @@ #include #include +#include #include #include @@ -136,6 +139,24 @@ struct HfProducerCharmHadronsTrackFemtoDream { // 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)"}; + // ------------------------- + // Kaon PID cut parameters + // ------------------------- + struct : ConfigurableGroup { + Configurable pTrackMethod1Max{"pTrackMethod1Max", 0.85f, "Kaon PID Method1 (TPC-only): maximum p (GeV/c)"}; + Configurable pTrackExcludeMin{"pTrackExcludeMin", 0.50f, "Kaon PID Method1: excluded p window minimum (GeV/c)"}; + Configurable pTrackExcludeMax{"pTrackExcludeMax", 0.65f, "Kaon PID Method1: excluded p window maximum (GeV/c)"}; + Configurable pTrackPiRejMin{"pTrackPiRejMin", 0.50f, "Kaon PID Method1: pion rejection active for p > this (GeV/c)"}; + Configurable pTrackElRejMin{"pTrackElRejMin", 0.30f, "Kaon PID Method1: electron rejection active for p > this (GeV/c)"}; + Configurable pTrackTightMin{"pTrackTightMin", 1.20f, "Kaon PID Method2 (TPC+TOF): tighten cuts for p > this (GeV/c)"}; + Configurable nSigmaTpcKaMax{"nSigmaTpcKaMax", 3.f, "Kaon PID Method1: require |nSigmaTpcKa| < this"}; + Configurable nSigmaTpcPiMin{"nSigmaTpcPiMin", 3.f, "Kaon PID Method1: require |nSigmaTpcPi| > this (pion)"}; + Configurable nSigmaTpcElMin{"nSigmaTpcElMin", 3.f, "Kaon PID Method1: require |nSigmaTpcEl| > this (electron)"}; + Configurable nSigmaCombKaMax{"nSigmaCombKaMax", 3.f, "Kaon PID Method2: require |nSigmaCombKa| < this"}; + Configurable nSigmaCombKaTightMax{"nSigmaCombKaTightMax", 2.f, "Kaon PID Method2: for p > pTrackTightMin require |nSigmaCombKa| < this"}; + Configurable nSigmaCombPiMax{"nSigmaCombPiMax", 6.f, "Kaon PID Method2: for p > pTrackTightMin require |nSigmaCombPi| < this"}; + } kaonPidSel; + Configurable isDebug{"isDebug", true, "Enable Debug tables"}; Configurable isRun3{"isRun3", true, "Running on Run3 or pilot"}; @@ -183,7 +204,7 @@ struct HfProducerCharmHadronsTrackFemtoDream { std::vector outputMlPiKP; o2::ccdb::CcdbApi ccdbApi; o2::hf_evsel::HfEventSelection hfEvSel; - Service ccdb; /// Accessing the CCDB + 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 @@ -202,14 +223,14 @@ struct HfProducerCharmHadronsTrackFemtoDream { using FemtoFullCollisionMc = soa::Join::iterator; using FemtoFullMcgenCollisions = soa::Join; using FemtoFullMcgenCollision = FemtoFullMcgenCollisions::iterator; - using FemtoHFTracks = soa::Join; + using FemtoHFTracks = soa::Join; using FemtoHFTrack = FemtoHFTracks::iterator; using FemtoHFMcTracks = soa::Join; using FemtoHFMcTrack = FemtoHFMcTracks::iterator; - using Generated3ProngMc = soa::Filtered>; - using Generated2ProngMc = soa::Filtered>; - using GeneratedDstarMc = soa::Filtered>; + using Generated3ProngMc = soa::Join; + using Generated2ProngMc = soa::Join; + using GeneratedDstarMc = soa::Join; Filter filterSelectCandidateD0 = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagHadron || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagHadron); Filter filterSelectCandidateDstar = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; @@ -218,6 +239,7 @@ struct HfProducerCharmHadronsTrackFemtoDream { HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry trackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; + OutputObj zorroSummary{"zorroSummary"}; void init(InitContext&) { @@ -270,7 +292,7 @@ struct HfProducerCharmHadronsTrackFemtoDream { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - hfEvSel.addHistograms(qaRegistry); // collision monitoring + hfEvSel.init(qaRegistry, &zorroSummary); // collision monitoring int64_t const now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); @@ -281,57 +303,101 @@ struct HfProducerCharmHadronsTrackFemtoDream { bool useDstarMl = doprocessDataDstarToD0PiWithML || doprocessMcDstarToD0PiWithML; if (applyMlMode == FillMlFromNewBDT) { - if (useLcMl) { - hfMlResponseLc.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); - hfMlResponseLc.cacheInputFeaturesIndices(namesInputFeatures); - hfMlResponseLc.init(); - } - if (useDplusMl) { - hfMlResponseDplus.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); - hfMlResponseDplus.cacheInputFeaturesIndices(namesInputFeatures); - hfMlResponseDplus.init(); - } - if (useD0Ml) { - hfMlResponseD0.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); - hfMlResponseD0.cacheInputFeaturesIndices(namesInputFeatures); - hfMlResponseD0.init(); - } - if (useDstarMl) { - hfMlResponseDstar.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); - hfMlResponseDstar.cacheInputFeaturesIndices(namesInputFeatures); - hfMlResponseDstar.init(); - } - if (loadModelsFromCCDB) { - ccdbApi.init(ccdbUrl); - if (useLcMl) { - hfMlResponseLc.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); - } - if (useDplusMl) { - hfMlResponseDplus.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); - } - if (useD0Ml) { - hfMlResponseD0.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); - } - if (useDstarMl) { - hfMlResponseDstar.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + auto setupFeatures = [&](auto& hfResponse, bool useMlFlag) { + if (!useMlFlag) { + return; } + hfResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + hfResponse.cacheInputFeaturesIndices(namesInputFeatures); + }; - } else { - if (useLcMl) { - hfMlResponseLc.setModelPathsLocal(onnxFileNames); - } - if (useDplusMl) { - hfMlResponseDplus.setModelPathsLocal(onnxFileNames); - } - if (useD0Ml) { - hfMlResponseD0.setModelPathsLocal(onnxFileNames); + setupFeatures(hfMlResponseLc, useLcMl); + setupFeatures(hfMlResponseDplus, useDplusMl); + setupFeatures(hfMlResponseD0, useD0Ml); + setupFeatures(hfMlResponseDstar, useDstarMl); + + const bool useAnyMl = useLcMl || useDplusMl || useD0Ml || useDstarMl; + if (loadModelsFromCCDB && useAnyMl) { + ccdbApi.init(ccdbUrl); + } + + auto initModel = [&](auto& hfResponse, bool useMlFlag) { + if (!useMlFlag) { + return; } - if (useDstarMl) { - hfMlResponseDstar.setModelPathsLocal(onnxFileNames); + + if (loadModelsFromCCDB) { + hfResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfResponse.setModelPathsLocal(onnxFileNames); } + hfResponse.init(); + }; + + initModel(hfMlResponseLc, useLcMl); + initModel(hfMlResponseDplus, useDplusMl); + initModel(hfMlResponseD0, useD0Ml); + initModel(hfMlResponseDstar, useDstarMl); + } + } + + // ------------------------- + // Kaon PID selection + // ------------------------- + template + bool isTrackKaonPidSelected(const TrackType& track) + { + const float pTrack = track.p(); + + // ========================= + // Method 1: Tpc-only + // ========================= + bool isTrackKaonPidMethod1 = true; + + if (pTrack >= kaonPidSel.pTrackMethod1Max) { + isTrackKaonPidMethod1 = false; + } + if (std::abs(track.tpcNSigmaKa()) >= kaonPidSel.nSigmaTpcKaMax) { + isTrackKaonPidMethod1 = false; + } + if (pTrack >= kaonPidSel.pTrackExcludeMin && pTrack <= kaonPidSel.pTrackExcludeMax) { + isTrackKaonPidMethod1 = false; + } + if (pTrack > kaonPidSel.pTrackPiRejMin && std::abs(track.tpcNSigmaPi()) <= kaonPidSel.nSigmaTpcPiMin) { + isTrackKaonPidMethod1 = false; + } + if (pTrack > kaonPidSel.pTrackElRejMin && std::abs(track.tpcNSigmaEl()) <= kaonPidSel.nSigmaTpcElMin) { + isTrackKaonPidMethod1 = false; + } + + // ========================= + // Method 2: Tpc+Tof combined + // ========================= + bool isTrackKaonPidMethod2 = true; + + if (pTrack > kaonPidSel.pTrackMethod1Max && !track.hasTOF()) { + isTrackKaonPidMethod2 = false; + } + + const float nSigmaCombKa = std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()); + const float nSigmaCombPi = std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()); + + if (std::abs(nSigmaCombKa) >= kaonPidSel.nSigmaCombKaMax) { + isTrackKaonPidMethod2 = false; + } + + if (pTrack > kaonPidSel.pTrackTightMin) { + if (std::abs(nSigmaCombKa) >= kaonPidSel.nSigmaCombKaTightMax) { + isTrackKaonPidMethod2 = false; + } + if (std::abs(nSigmaCombPi) >= kaonPidSel.nSigmaCombPiMax) { + isTrackKaonPidMethod2 = false; } } + + // OR between the two PID methods + return isTrackKaonPidMethod1 || isTrackKaonPidMethod2; } /// Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T @@ -470,14 +536,28 @@ struct HfProducerCharmHadronsTrackFemtoDream { outputPartsTime(timeStamp); // now the table is filled - outputParts(outputCollision.lastIndex(), - track.pt(), - track.eta(), - track.phi(), - aod::femtodreamparticle::ParticleType::kTrack, - cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), - cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), - track.dcaXY(), childIDs, 0, 0); + if (trkPDGCode == kKPlus) { + const auto pidTrackPassBit = static_cast(isTrackKaonPidSelected(track)); + + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + aod::femtodreamparticle::ParticleType::kTrack, + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + pidTrackPassBit, + track.dcaXY(), childIDs, 0, 0); + } else { + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + aod::femtodreamparticle::ParticleType::kTrack, + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), + cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, 0); + } + fIsTrackFilled = true; // tmpIDtrack.push_back(track.globalIndex()); if (isDebug.value) { diff --git a/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx b/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx index e95ea304bae..ebc38e73682 100644 --- a/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx +++ b/PWGHF/HFC/TableProducer/producerCharmHadronsV0FemtoDream.cxx @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #include #include +#include #include #include #include @@ -151,6 +153,8 @@ struct HfProducerCharmHadronsV0FemtoDream { Configurable v0PDGCode{"v0PDGCode", 310, "PDG code of the selected V0 (310: K0S, 3122: Lambda) for Monte Carlo truth "}; Configurable trkPIDnSigmaOffsetTPC{"trkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; // set to zero for run3 or so Configurable trkPIDnSigmaOffsetTOF{"trkPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; + Configurable trkPIDnSigmaForLambdaSign{"trkPIDnSigmaForLambdaSign", 0., "daught track PID for Lambda sign determination"}; + Configurable trkRejectNotPropagated{"trkRejectNotPropagated", false, "True: reject not propagated tracks"}; struct : o2::framework::ConfigurableGroup { @@ -225,7 +229,7 @@ struct HfProducerCharmHadronsV0FemtoDream { std::vector outputMlPiKP; o2::ccdb::CcdbApi ccdbApi; o2::hf_evsel::HfEventSelection hfEvSel; - Service ccdb; /// Accessing the CCDB + 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 @@ -246,7 +250,9 @@ struct HfProducerCharmHadronsV0FemtoDream { using FemtoFullMcgenCollisions = soa::Join; using FemtoFullMcgenCollision = FemtoFullMcgenCollisions::iterator; - using GeneratedMc = soa::Filtered>; + using Generated3ProngMc = soa::Join; + using Generated2ProngMc = soa::Join; + using GeneratedDstarMc = soa::Join; Filter filterSelectCandidateD0 = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagCharmHadron || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagCharmHadron); Filter filterSelectCandidateDstar = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; @@ -255,8 +261,8 @@ struct HfProducerCharmHadronsV0FemtoDream { HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry qaRegistryV0{"V0", {}, OutputObjHandlingPolicy::AnalysisObject}; - FemtoDreamV0Selection K0SCuts; - FemtoDreamV0Selection LambdaCuts; + FemtoDreamV0Selection k0sCuts; + FemtoDreamV0Selection lambdaCuts; void init(InitContext&) { std::array processes = {doprocessDataDplusToPiKPi, doprocessMcDplusToPiKPi, doprocessDataDplusToPiKPiWithML, doprocessMcDplusToPiKPiWithML, doprocessMcDplusToPiKPiGen, @@ -269,8 +275,8 @@ struct HfProducerCharmHadronsV0FemtoDream { qaRegistryV0.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{cutBits + 1, -0.5, cutBits + 0.5}}); // event QA histograms - constexpr int kEventTypes = PairSelected + 1; - std::string labels[kEventTypes]; + constexpr int EventTypes = PairSelected + 1; + std::string labels[EventTypes]; labels[Event::All] = "All events"; labels[Event::RejEveSel] = "rejected by event selection"; labels[Event::RejNoV0sAndCharm] = "rejected by no V0s and charm"; @@ -278,86 +284,86 @@ struct HfProducerCharmHadronsV0FemtoDream { labels[Event::CharmSelected] = "with charm hadrons "; labels[Event::PairSelected] = "with pairs"; - static const AxisSpec axisEvents = {kEventTypes, 0.5, kEventTypes + 0.5, ""}; + static const AxisSpec axisEvents = {EventTypes, 0.5, EventTypes + 0.5, ""}; qaRegistry.add("hEventQA", "Events;;entries", HistType::kTH1F, {axisEvents}); - for (int iBin = 0; iBin < kEventTypes; iBin++) { + for (int iBin = 0; iBin < EventTypes; iBin++) { qaRegistry.get(HIST("hEventQA"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } if (selectionFlagV0 == V0Channel::K0S) { - K0SCuts.setSelection(V0Sel.confK0shortSign, femto_dream_v0_selection::kV0Sign, femtoDreamSelection::kEqual); - K0SCuts.setSelection(V0Sel.confK0shortPtMin, femto_dream_v0_selection::kV0pTMin, femtoDreamSelection::kLowerLimit); - K0SCuts.setSelection(V0Sel.confK0shortPtMax, femto_dream_v0_selection::kV0pTMax, femtoDreamSelection::kUpperLimit); - K0SCuts.setSelection(V0Sel.confK0shortEtaMax, femto_dream_v0_selection::kV0etaMax, femtoDreamSelection::kAbsUpperLimit); - K0SCuts.setSelection(V0Sel.confK0shortDCADaughMax, femto_dream_v0_selection::kV0DCADaughMax, femtoDreamSelection::kUpperLimit); - K0SCuts.setSelection(V0Sel.confK0shortCPAMin, femto_dream_v0_selection::kV0CPAMin, femtoDreamSelection::kLowerLimit); - K0SCuts.setSelection(V0Sel.confK0shortTranRadMin, femto_dream_v0_selection::kV0TranRadMin, femtoDreamSelection::kLowerLimit); - K0SCuts.setSelection(V0Sel.confK0shortTranRadMax, femto_dream_v0_selection::kV0TranRadMax, femtoDreamSelection::kUpperLimit); - K0SCuts.setSelection(V0Sel.confK0shortDecVtxMax, femto_dream_v0_selection::kV0DecVtxMax, femtoDreamSelection::kUpperLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); - K0SCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); - - K0SCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); - K0SCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); - K0SCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); - K0SCuts.setChildPIDSpecies(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildPIDspecies); - K0SCuts.setChildPIDSpecies(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildPIDspecies); - K0SCuts.init(&qaRegistryV0, &qaRegistryV0); - K0SCuts.setInvMassLimits(V0Sel.confK0shortInvMassLowLimit, V0Sel.confK0shortInvMassUpLimit); - K0SCuts.setIsMother(false); - - K0SCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kPosTrack, trkRejectNotPropagated); - K0SCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kNegTrack, trkRejectNotPropagated); - - K0SCuts.setnSigmaPIDOffsetTPC(trkPIDnSigmaOffsetTPC); - K0SCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kPosTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); - K0SCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kNegTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); - - K0SCuts.setRejectLambda(V0Sel.confK0shortRejectLambdas); - K0SCuts.setKaonInvMassLimits(V0Sel.confK0shortInvKaonMassLowLimit, V0Sel.confK0shortInvKaonMassUpLimit); + k0sCuts.setSelection(V0Sel.confK0shortSign, femto_dream_v0_selection::kV0Sign, femtoDreamSelection::kEqual); + k0sCuts.setSelection(V0Sel.confK0shortPtMin, femto_dream_v0_selection::kV0pTMin, femtoDreamSelection::kLowerLimit); + k0sCuts.setSelection(V0Sel.confK0shortPtMax, femto_dream_v0_selection::kV0pTMax, femtoDreamSelection::kUpperLimit); + k0sCuts.setSelection(V0Sel.confK0shortEtaMax, femto_dream_v0_selection::kV0etaMax, femtoDreamSelection::kAbsUpperLimit); + k0sCuts.setSelection(V0Sel.confK0shortDCADaughMax, femto_dream_v0_selection::kV0DCADaughMax, femtoDreamSelection::kUpperLimit); + k0sCuts.setSelection(V0Sel.confK0shortCPAMin, femto_dream_v0_selection::kV0CPAMin, femtoDreamSelection::kLowerLimit); + k0sCuts.setSelection(V0Sel.confK0shortTranRadMin, femto_dream_v0_selection::kV0TranRadMin, femtoDreamSelection::kLowerLimit); + k0sCuts.setSelection(V0Sel.confK0shortTranRadMax, femto_dream_v0_selection::kV0TranRadMax, femtoDreamSelection::kUpperLimit); + k0sCuts.setSelection(V0Sel.confK0shortDecVtxMax, femto_dream_v0_selection::kV0DecVtxMax, femtoDreamSelection::kUpperLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + k0sCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + k0sCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + k0sCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + k0sCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + k0sCuts.setChildPIDSpecies(femto_dream_v0_selection::kPosTrack, V0Sel.confK0shortChildPIDspecies); + k0sCuts.setChildPIDSpecies(femto_dream_v0_selection::kNegTrack, V0Sel.confK0shortChildPIDspecies); + k0sCuts.init(&qaRegistryV0, &qaRegistryV0); + k0sCuts.setInvMassLimits(V0Sel.confK0shortInvMassLowLimit, V0Sel.confK0shortInvMassUpLimit); + k0sCuts.setIsMother(false); + + k0sCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kPosTrack, trkRejectNotPropagated); + k0sCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kNegTrack, trkRejectNotPropagated); + + k0sCuts.setnSigmaPIDOffsetTPC(trkPIDnSigmaOffsetTPC); + k0sCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kPosTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); + k0sCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kNegTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); + + k0sCuts.setRejectLambda(V0Sel.confK0shortRejectLambdas); + k0sCuts.setKaonInvMassLimits(V0Sel.confK0shortInvKaonMassLowLimit, V0Sel.confK0shortInvKaonMassUpLimit); } if (selectionFlagV0 == V0Channel::Lambda) { - LambdaCuts.setSelection(V0Sel.confLambdaSign, femto_dream_v0_selection::kV0Sign, femtoDreamSelection::kEqual); - LambdaCuts.setSelection(V0Sel.confLambdaPtMin, femto_dream_v0_selection::kV0pTMin, femtoDreamSelection::kLowerLimit); - LambdaCuts.setSelection(V0Sel.confLambdaPtMax, femto_dream_v0_selection::kV0pTMax, femtoDreamSelection::kUpperLimit); - LambdaCuts.setSelection(V0Sel.confLambdaEtaMax, femto_dream_v0_selection::kV0etaMax, femtoDreamSelection::kAbsUpperLimit); - LambdaCuts.setSelection(V0Sel.confLambdaDCADaughMax, femto_dream_v0_selection::kV0DCADaughMax, femtoDreamSelection::kUpperLimit); - LambdaCuts.setSelection(V0Sel.confLambdaCPAMin, femto_dream_v0_selection::kV0CPAMin, femtoDreamSelection::kLowerLimit); - LambdaCuts.setSelection(V0Sel.confLambdaTranRadMin, femto_dream_v0_selection::kV0TranRadMin, femtoDreamSelection::kLowerLimit); - LambdaCuts.setSelection(V0Sel.confLambdaTranRadMax, femto_dream_v0_selection::kV0TranRadMax, femtoDreamSelection::kUpperLimit); - LambdaCuts.setSelection(V0Sel.confLambdaDecVtxMax, femto_dream_v0_selection::kV0DecVtxMax, femtoDreamSelection::kUpperLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); - - LambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); - LambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); - LambdaCuts.setChildPIDSpecies(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildPIDspecies); - LambdaCuts.setChildPIDSpecies(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildPIDspecies); - LambdaCuts.init(&qaRegistryV0, &qaRegistryV0); - LambdaCuts.setInvMassLimits(V0Sel.confLambdaInvMassLowLimit, V0Sel.confLambdaInvMassUpLimit); - LambdaCuts.setIsMother(true); - - LambdaCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kPosTrack, trkRejectNotPropagated); - LambdaCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kNegTrack, trkRejectNotPropagated); - - LambdaCuts.setnSigmaPIDOffsetTPC(trkPIDnSigmaOffsetTPC); - LambdaCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kPosTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); - LambdaCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kNegTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); + // lambdaCuts.setSelection(V0Sel.confLambdaSign, femto_dream_v0_selection::kV0Sign, femtoDreamSelection::kEqual); + lambdaCuts.setSelection(V0Sel.confLambdaPtMin, femto_dream_v0_selection::kV0pTMin, femtoDreamSelection::kLowerLimit); + lambdaCuts.setSelection(V0Sel.confLambdaPtMax, femto_dream_v0_selection::kV0pTMax, femtoDreamSelection::kUpperLimit); + lambdaCuts.setSelection(V0Sel.confLambdaEtaMax, femto_dream_v0_selection::kV0etaMax, femtoDreamSelection::kAbsUpperLimit); + lambdaCuts.setSelection(V0Sel.confLambdaDCADaughMax, femto_dream_v0_selection::kV0DCADaughMax, femtoDreamSelection::kUpperLimit); + lambdaCuts.setSelection(V0Sel.confLambdaCPAMin, femto_dream_v0_selection::kV0CPAMin, femtoDreamSelection::kLowerLimit); + lambdaCuts.setSelection(V0Sel.confLambdaTranRadMin, femto_dream_v0_selection::kV0TranRadMin, femtoDreamSelection::kLowerLimit); + lambdaCuts.setSelection(V0Sel.confLambdaTranRadMax, femto_dream_v0_selection::kV0TranRadMax, femtoDreamSelection::kUpperLimit); + lambdaCuts.setSelection(V0Sel.confLambdaDecVtxMax, femto_dream_v0_selection::kV0DecVtxMax, femtoDreamSelection::kUpperLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + + lambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildSign, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildEtaMax, femtoDreamTrackSelection::kEtaMax, femtoDreamSelection::kAbsUpperLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildTPCnClsMin, femtoDreamTrackSelection::kTPCnClsMin, femtoDreamSelection::kLowerLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildDCAMin, femtoDreamTrackSelection::kDCAMin, femtoDreamSelection::kAbsLowerLimit); + lambdaCuts.setChildCuts(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); + lambdaCuts.setChildPIDSpecies(femto_dream_v0_selection::kPosTrack, V0Sel.confLambdaChildPIDspecies); + lambdaCuts.setChildPIDSpecies(femto_dream_v0_selection::kNegTrack, V0Sel.confLambdaChildPIDspecies); + lambdaCuts.init(&qaRegistryV0, &qaRegistryV0); + lambdaCuts.setInvMassLimits(V0Sel.confLambdaInvMassLowLimit, V0Sel.confLambdaInvMassUpLimit); + lambdaCuts.setIsMother(true); + + lambdaCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kPosTrack, trkRejectNotPropagated); + lambdaCuts.setChildRejectNotPropagatedTracks(femto_dream_v0_selection::kNegTrack, trkRejectNotPropagated); + + lambdaCuts.setnSigmaPIDOffsetTPC(trkPIDnSigmaOffsetTPC); + lambdaCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kPosTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); + lambdaCuts.setChildnSigmaPIDOffset(femto_dream_v0_selection::kNegTrack, trkPIDnSigmaOffsetTPC, trkPIDnSigmaOffsetTOF); if (V0Sel.confLambdaRejectKaons) { - LambdaCuts.setKaonInvMassLimits(V0Sel.confLambdaInvKaonMassLowLimit, V0Sel.confLambdaInvKaonMassUpLimit); + lambdaCuts.setKaonInvMassLimits(V0Sel.confLambdaInvKaonMassLowLimit, V0Sel.confLambdaInvKaonMassUpLimit); } } @@ -583,31 +589,36 @@ struct HfProducerCharmHadronsV0FemtoDream { float massV0 = 0.f; float antiMassV0 = 0.f; + int signV0 = determineV0Sign(v0, postrack, negtrack); + std::array cutContainerV0{}; if (isK0S) { - K0SCuts.fillLambdaQA(col, v0, postrack, negtrack); - if (!K0SCuts.isSelectedMinimal(col, v0, postrack, negtrack)) { + k0sCuts.fillLambdaQA(col, v0, postrack, negtrack); + if (!k0sCuts.isSelectedMinimal(col, v0, postrack, negtrack)) { continue; } - K0SCuts.fillQA(col, v0, postrack, negtrack); - cutContainerV0 = K0SCuts.getCutContainer(col, v0, postrack, negtrack); + cutContainerV0 = k0sCuts.getCutContainer(col, v0, postrack, negtrack); massV0 = v0.mK0Short(); antiMassV0 = v0.mK0Short(); } else { // Lambda - LambdaCuts.fillLambdaQA(col, v0, postrack, negtrack); - if (!LambdaCuts.isSelectedMinimal(col, v0, postrack, negtrack)) { + lambdaCuts.fillLambdaQA(col, v0, postrack, negtrack); + if (!lambdaCuts.isSelectedMinimal(col, v0, postrack, negtrack)) { continue; } - LambdaCuts.fillQA(col, v0, postrack, negtrack); - cutContainerV0 = LambdaCuts.getCutContainer(col, v0, postrack, negtrack); + cutContainerV0 = lambdaCuts.getCutContainer(col, v0, postrack, negtrack); massV0 = v0.mLambda(); antiMassV0 = v0.mAntiLambda(); } + bool passPosPID = false, passNegPID = false; + isV0DaughterPidSelected(postrack, negtrack, signV0, passPosPID, passNegPID); + // --- pos child int rowPos = getRowDaughters(v0.posTrackId(), tmpIDtrack); childIDs[0] = rowPos; @@ -621,7 +632,7 @@ struct HfProducerCharmHadronsV0FemtoDream { v0.positivept(), v0.positiveeta(), v0.positivephi(), daughType, cutContainerV0.at(femto_dream_v0_selection::V0ContainerPosition::kPosCuts), - cutContainerV0.at(femto_dream_v0_selection::V0ContainerPosition::kPosPID), + static_cast(passPosPID), postrack.dcaXY(), childIDs, 0, @@ -638,13 +649,12 @@ struct HfProducerCharmHadronsV0FemtoDream { v0.negativept(), v0.negativeeta(), v0.negativephi(), daughType, cutContainerV0.at(femto_dream_v0_selection::V0ContainerPosition::kNegCuts), - cutContainerV0.at(femto_dream_v0_selection::V0ContainerPosition::kNegPID), + static_cast(passNegPID), negtrack.dcaXY(), childIDs, 0, 0); const int rowOfNegTrack = outputParts.lastIndex(); - // --- mother std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; auto motherType = isK0S ? aod::femtodreamparticle::ParticleType::kV0K0Short @@ -660,7 +670,6 @@ struct HfProducerCharmHadronsV0FemtoDream { indexChildID, massV0, antiMassV0); - auto signV0 = determineV0Sign(v0, postrack, negtrack); if (isDebug.value) { fillDebugParticle(postrack); @@ -708,7 +717,7 @@ struct HfProducerCharmHadronsV0FemtoDream { return; } - if (isNoSelectedV0s(col, tracks, fullV0s, K0SCuts) && sizeCand <= 0) { + if (isNoSelectedV0s(col, tracks, fullV0s, k0sCuts) && sizeCand <= 0) { qaRegistry.fill(HIST("hEventQA"), 1 + Event::RejNoV0sAndCharm); return; } @@ -1009,7 +1018,7 @@ struct HfProducerCharmHadronsV0FemtoDream { const float diffAntiLam = std::abs(mLamPDG - mAntiLamHyp); const float offTPC = trkPIDnSigmaOffsetTPC.value; - const float nSigmaPIDMax = V0Sel.confLambdaChildPIDnSigmaMax.value[0]; + const float nSigmaPIDMax = trkPIDnSigmaForLambdaSign.value; // TPC n-sigma (apply offset by subtraction) const float prNeg = negTrack.tpcNSigmaPr() - offTPC; @@ -1038,6 +1047,56 @@ struct HfProducerCharmHadronsV0FemtoDream { return sign; } + template + bool isV0DaughterPidSelected(const TrackT& posTrack, + const TrackT& negTrack, + int signV0, + bool& passPosPID, + bool& passNegPID) + { + passPosPID = false; + passNegPID = false; + + const bool isK0S = (selectionFlagV0 == V0Channel::K0S); + const bool isLambda = (selectionFlagV0 == V0Channel::Lambda); + + const float offTPC = trkPIDnSigmaOffsetTPC.value; + + const float prPos = posTrack.tpcNSigmaPr() - offTPC; + const float piPos = posTrack.tpcNSigmaPi() - offTPC; + const float prNeg = negTrack.tpcNSigmaPr() - offTPC; + const float piNeg = negTrack.tpcNSigmaPi() - offTPC; + + if (isK0S) { + const float nSigmaPiMaxK0S = V0Sel.confK0shortChildPIDnSigmaMax.value[0]; + passPosPID = (std::abs(piPos) < nSigmaPiMaxK0S); + passNegPID = (std::abs(piNeg) < nSigmaPiMaxK0S); + return passPosPID && passNegPID; + } + + if (isLambda) { + const float nSigmaPiMaxLam = V0Sel.confLambdaChildPIDnSigmaMax.value[0]; + const float nSigmaPrMaxLam = V0Sel.confLambdaChildPIDnSigmaMax.value[1]; + + if (signV0 != +1 && signV0 != -1) { + return false; + } + + const bool posIsProton = (signV0 == +1); + const bool negIsProton = (signV0 == -1); + + passPosPID = posIsProton ? (std::abs(prPos) < nSigmaPrMaxLam) + : (std::abs(piPos) < nSigmaPiMaxLam); + + passNegPID = negIsProton ? (std::abs(prNeg) < nSigmaPrMaxLam) + : (std::abs(piNeg) < nSigmaPiMaxLam); + + return passPosPID && passNegPID; + } + + return false; + } + // check if there is no selected v0 /// \param C type of the collision /// \param T type of the V0s @@ -1166,7 +1225,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcD0ToPiKWithML, "Provide Mc for D0ToPiK with ml", false); - void processMcD0ToPiKGen(GeneratedMc const& particles) + void processMcD0ToPiKGen(Generated2ProngMc const& particles) { fillCharmHadMcGen(particles); } @@ -1225,7 +1284,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcDstarToD0PiWithML, "Provide Mc for DstarToD0Pi with ml", false); - void processMcDstarToD0PiGen(GeneratedMc const& particles) + void processMcDstarToD0PiGen(GeneratedDstarMc const& particles) { fillCharmHadMcGen(particles); @@ -1286,7 +1345,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcDplusToPiKPiWithML, "Provide Mc for DplusToPiKPi with ml", false); - void processMcDplusToPiKPiGen(GeneratedMc const& particles) + void processMcDplusToPiKPiGen(Generated3ProngMc const& particles) { fillCharmHadMcGen(particles); @@ -1347,7 +1406,7 @@ struct HfProducerCharmHadronsV0FemtoDream { } PROCESS_SWITCH(HfProducerCharmHadronsV0FemtoDream, processMcLcToPKPiWithML, "Provide Mc for lctopkpi with ml", false); - void processMcLcToPKPiGen(GeneratedMc const& particles) + void processMcLcToPKPiGen(Generated3ProngMc const& particles) { fillCharmHadMcGen(particles); diff --git a/PWGHF/HFC/Tasks/CMakeLists.txt b/PWGHF/HFC/Tasks/CMakeLists.txt index 5132b7174b7..4fa2b6cd959 100644 --- a/PWGHF/HFC/Tasks/CMakeLists.txt +++ b/PWGHF/HFC/Tasks/CMakeLists.txt @@ -34,6 +34,11 @@ o2physics_add_dpl_workflow(task-correlation-d-meson-pairs PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-correlation-dplus-dplus-reduced + SOURCES taskCorrelationDplusDplusReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-correlation-dplus-hadrons SOURCES taskCorrelationDplusHadrons.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFC/Tasks/taskCharmHadronsTrackFemtoDream.cxx b/PWGHF/HFC/Tasks/taskCharmHadronsTrackFemtoDream.cxx index 962e8b07c91..a0b6b1aed76 100644 --- a/PWGHF/HFC/Tasks/taskCharmHadronsTrackFemtoDream.cxx +++ b/PWGHF/HFC/Tasks/taskCharmHadronsTrackFemtoDream.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file taskCharmHadronsFemtoDream.cxx +/// \file taskCharmHadronsTrackFemtoDream.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 /// \author Biao Zhang, Heidelberg University, biao.zhang@cern.ch @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -62,7 +63,10 @@ using namespace o2::constants::physics; inline o2::framework::expressions::Node coshEta(o2::framework::expressions::Node&& eta) { - return (nexp(std::move(eta)) + nexp(0.0f - std::move(eta))) * 0.5f; + auto e1 = std::move(eta); + auto e2 = e1; + + return (nexp(std::move(e1)) + nexp(std::move(e2) * (-1.0f))) * 0.5f; } struct HfTaskCharmHadronsTrackFemtoDream { @@ -88,6 +92,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { constexpr static int OriginRecPrompt = 1; constexpr static int OriginRecFD = 2; constexpr static int CutBitChargePositive = 2; + constexpr static uint32_t PidTrackPass = 1u; Produces rowFemtoResultPairs; Produces rowFemtoResultCharm3Prong; @@ -114,15 +119,17 @@ struct HfTaskCharmHadronsTrackFemtoDream { Configurable charmHadPromptBDTmax{"charmHadPromptBDTmax", 1., "Maximum prompt bdt score Charm Hadron (particle 2)"}; } charmSel; /// 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"}; + struct : ConfigurableGroup { + 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 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"}; + } pairQASetting; 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"}; Configurable fillTableWithCharm{"fillTableWithCharm", true, "Write charm/tracks/collision table only if >=1 charm hadron in this collision"}; // Mixing configurables @@ -200,11 +207,14 @@ struct HfTaskCharmHadronsTrackFemtoDream { /// Partition for particle 1 Partition partitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && (ncheckbit(aod::femtodreamparticle::cut, trackSel.cutBitTrack1)) && ifnode(aod::femtodreamparticle::pt * coshEta(aod::femtodreamparticle::eta) <= trackSel.pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, trackSel.tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, trackSel.tpcTofBitTrack1)); + Partition partitionTrk1Ka = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && (ncheckbit(aod::femtodreamparticle::cut, trackSel.cutBitTrack1)) && (aod::femtodreamparticle::pidcut == PidTrackPass); Partition partitionMcTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && (ncheckbit(aod::femtodreamparticle::cut, trackSel.cutBitTrack1)) && ifnode(aod::femtodreamparticle::pt * coshEta(aod::femtodreamparticle::eta) <= trackSel.pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, trackSel.tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, trackSel.tpcTofBitTrack1)); + Partition partitionMcTrk1Ka = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && (ncheckbit(aod::femtodreamparticle::cut, trackSel.cutBitTrack1)) && (aod::femtodreamparticle::pidcut == PidTrackPass); + /// Partition for particle 2 Partition partitionCharmHadron3Prong = aod::fdhf::bdtBkg < charmSel.charmHadBkgBDTmax && aod::fdhf::bdtFD < charmSel.charmHadFdBDTmax && aod::fdhf::bdtFD > charmSel.charmHadFdBDTmin&& aod::fdhf::bdtPrompt charmSel.charmHadPromptBDTmin; Partition partitionCharmHadron2Prong = aod::fdhf::bdtBkg < charmSel.charmHadBkgBDTmax && aod::fdhf::bdtFD < charmSel.charmHadFdBDTmax && aod::fdhf::bdtFD > charmSel.charmHadFdBDTmin&& aod::fdhf::bdtPrompt charmSel.charmHadPromptBDTmin; @@ -298,7 +308,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { sameEventCont.init(®istry, binkstar, binpTTrack, binkT, binmT, mixingBinMult, mixingBinMultPercentile, bin4Dkstar, bin4DmT, bin4DMult, bin4DmultPercentile, - isMc, use4D, extendedPlots, + isMc, pairQASetting.use4D, pairQASetting.extendedPlots, highkstarCut, smearingByOrigin, binInvMass); @@ -306,7 +316,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { mixedEventCont.init(®istry, binkstar, binpTTrack, binkT, binmT, mixingBinMult, mixingBinMultPercentile, bin4Dkstar, bin4DmT, bin4DMult, bin4DmultPercentile, - isMc, use4D, extendedPlots, + isMc, pairQASetting.use4D, pairQASetting.extendedPlots, highkstarCut, smearingByOrigin, binInvMass); @@ -316,18 +326,18 @@ struct HfTaskCharmHadronsTrackFemtoDream { registryMixQa.add("MixingQA/hMECollisionBins", "; bin; Entries", kTH1F, {{120, -0.5, 119.5}}); registryCharmHadronQa.add("CharmHadronQA/hPtVsMass", "; #it{p}_{T} (GeV/#it{c}); inv. mass (GeV/#it{c}^{2})", kTH2F, {binpTCharm, binInvMass}); - if (useCPR.value && process3Prong) { + if (pairQASetting.useCPR.value && process3Prong) { pairCleaner3Prong.init(®istry); - pairCloseRejectionSE3Prong.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 1); - pairCloseRejectionME3Prong.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 2); - } else if (useCPR.value && process2Prong) { + pairCloseRejectionSE3Prong.init(®istry, ®istry, pairQASetting.cprDeltaPhiMax.value, pairQASetting.cprDeltaEtaMax.value, pairQASetting.cprPlotPerRadii.value, 1); + pairCloseRejectionME3Prong.init(®istry, ®istry, pairQASetting.cprDeltaPhiMax.value, pairQASetting.cprDeltaEtaMax.value, pairQASetting.cprPlotPerRadii.value, 2); + } else if (pairQASetting.useCPR.value && process2Prong) { pairCleaner2Prong.init(®istry); - pairCloseRejectionSE2Prong.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 1); - pairCloseRejectionME2Prong.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 2); - } else if (useCPR.value && processDstar) { + pairCloseRejectionSE2Prong.init(®istry, ®istry, pairQASetting.cprDeltaPhiMax.value, pairQASetting.cprDeltaEtaMax.value, pairQASetting.cprPlotPerRadii.value, 1); + pairCloseRejectionME2Prong.init(®istry, ®istry, pairQASetting.cprDeltaPhiMax.value, pairQASetting.cprDeltaEtaMax.value, pairQASetting.cprPlotPerRadii.value, 2); + } else if (pairQASetting.useCPR.value && processDstar) { pairCleanerDstar.init(®istry); - pairCloseRejectionSEDstar.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 1); - pairCloseRejectionMEDstar.init(®istry, ®istry, cprDeltaPhiMax.value, cprDeltaEtaMax.value, cprPlotPerRadii.value, 2); + pairCloseRejectionSEDstar.init(®istry, ®istry, pairQASetting.cprDeltaPhiMax.value, pairQASetting.cprDeltaEtaMax.value, pairQASetting.cprPlotPerRadii.value, 1); + pairCloseRejectionMEDstar.init(®istry, ®istry, pairQASetting.cprDeltaPhiMax.value, pairQASetting.cprDeltaEtaMax.value, pairQASetting.cprPlotPerRadii.value, 2); } } @@ -462,10 +472,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { if constexpr (Channel == DecayChannel::D0ToPiK) { - if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id()) + if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id()) { continue; + } - if (useCPR.value) { + if (pairQASetting.useCPR.value) { if (pairCloseRejectionSE2Prong.isClosePair(p1, p2, parts, col.magField())) { continue; } @@ -477,9 +488,10 @@ struct HfTaskCharmHadronsTrackFemtoDream { } if constexpr (Channel == DecayChannel::LcToPKPi || Channel == DecayChannel::DplusToPiKPi) { - if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id() || p1.trackId() == p2.prong2Id()) + if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id() || p1.trackId() == p2.prong2Id()) { continue; - if (useCPR.value) { + } + if (pairQASetting.useCPR.value) { if (pairCloseRejectionSE3Prong.isClosePair(p1, p2, parts, col.magField())) { continue; } @@ -491,9 +503,10 @@ struct HfTaskCharmHadronsTrackFemtoDream { } if constexpr (Channel == DecayChannel::DstarToD0Pi) { - if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id() || p1.trackId() == p2.prong2Id()) + if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id() || p1.trackId() == p2.prong2Id()) { continue; - if (useCPR.value) { + } + if (pairQASetting.useCPR.value) { if (pairCloseRejectionSEDstar.isClosePair(p1, p2, parts, col.magField())) { continue; } @@ -565,7 +578,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { charmHadMc, originType); - sameEventCont.setPair(p1, p2, col.multNtr(), col.multV0M(), use4D, extendedPlots, smearingByOrigin); + sameEventCont.setPair(p1, p2, col.multNtr(), col.multV0M(), pairQASetting.use4D, pairQASetting.extendedPlots, smearingByOrigin); } } @@ -595,7 +608,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { if constexpr (Channel == DecayChannel::D0ToPiK) { - if (useCPR.value) { + if (pairQASetting.useCPR.value) { if (pairCloseRejectionME2Prong.isClosePair(p1, p2, parts, collision1.magField())) { continue; } @@ -608,7 +621,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { if constexpr (Channel == DecayChannel::DplusToPiKPi || Channel == DecayChannel::LcToPKPi) { - if (useCPR.value) { + if (pairQASetting.useCPR.value) { if (pairCloseRejectionME3Prong.isClosePair(p1, p2, parts, collision1.magField())) { continue; } @@ -621,7 +634,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { if constexpr (Channel == DecayChannel::DstarToD0Pi) { - if (useCPR.value) { + if (pairQASetting.useCPR.value) { if (pairCloseRejectionME3Prong.isClosePair(p1, p2, parts, collision1.magField())) { continue; } @@ -691,7 +704,7 @@ struct HfTaskCharmHadronsTrackFemtoDream { charmHadMc, originType); - mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); + mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), pairQASetting.use4D, pairQASetting.extendedPlots, smearingByOrigin); } } } @@ -828,7 +841,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceTrk1 = partitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionTrk1Ka; + } + auto sliceTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceCharmHad = partitionCharmHadron3Prong->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if (fillTableWithCharm.value && sliceCharmHad.size() == 0) { continue; @@ -863,7 +880,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceTrk1 = partitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionTrk1Ka; + } + auto sliceTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceCharmHad = partitionCharmHadron3Prong->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if (fillTableWithCharm.value && sliceCharmHad.size() == 0) { @@ -899,7 +920,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceTrk1 = partitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionTrk1Ka; + } + auto sliceTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceCharmHad = partitionCharmHadron2Prong->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if (fillTableWithCharm.value && sliceCharmHad.size() == 0) { continue; @@ -934,7 +959,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceTrk1 = partitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionTrk1Ka; + } + auto sliceTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceCharmHad = partitionCharmHadronDstar->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if (fillTableWithCharm.value && sliceCharmHad.size() == 0) { continue; @@ -971,7 +1000,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceMcTrk1 = partitionMcTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionMcTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionMcTrk1Ka; + } + auto sliceMcTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceMcCharmHad = partitionMcCharmHadron3Prong->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if ((col.bitmaskTrackOne() & bitMask) != bitMask || (col.bitmaskTrackTwo() & bitMask) != bitMask) { continue; @@ -1002,7 +1035,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceMcTrk1 = partitionMcTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionMcTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionMcTrk1Ka; + } + auto sliceMcTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceMcCharmHad = partitionMcCharmHadron3Prong->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if ((col.bitmaskTrackOne() & bitMask) != bitMask || (col.bitmaskTrackTwo() & bitMask) != bitMask) { continue; @@ -1033,7 +1070,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceMcTrk1 = partitionMcTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionMcTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionMcTrk1Ka; + } + auto sliceMcTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceMcCharmHad = partitionMcCharmHadron2Prong->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if ((col.bitmaskTrackOne() & bitMask) != bitMask || (col.bitmaskTrackTwo() & bitMask) != bitMask) { continue; @@ -1064,7 +1105,11 @@ struct HfTaskCharmHadronsTrackFemtoDream { { for (const auto& col : cols) { eventHisto.fillQA(col); - auto sliceMcTrk1 = partitionMcTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto* partitionTrk1Selected = &partitionMcTrk1; + if (trackSel.pdgCodeTrack1.value == kKPlus) { + partitionTrk1Selected = &partitionMcTrk1Ka; + } + auto sliceMcTrk1 = partitionTrk1Selected->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceMcCharmHad = partitionMcCharmHadronDstar->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); if ((col.bitmaskTrackOne() & bitMask) != bitMask || (col.bitmaskTrackTwo() & bitMask) != bitMask) { continue; diff --git a/PWGHF/HFC/Tasks/taskCharmHadronsV0FemtoDream.cxx b/PWGHF/HFC/Tasks/taskCharmHadronsV0FemtoDream.cxx index e75593574b7..57f05fbea1a 100644 --- a/PWGHF/HFC/Tasks/taskCharmHadronsV0FemtoDream.cxx +++ b/PWGHF/HFC/Tasks/taskCharmHadronsV0FemtoDream.cxx @@ -23,8 +23,6 @@ #include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" #include "PWGHF/Core/DecayChannels.h" -#include "Common/Core/RecoDecay.h" - #include #include #include @@ -45,8 +43,8 @@ #include #include +#include #include -#include #include using namespace o2; @@ -416,14 +414,17 @@ struct HfTaskCharmHadronsV0FemtoDream { for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceV01, sliceCharmHad))) { if constexpr (Channel == DecayChannel::D0ToPiK) { - if (p1.childrenIds()[0] == p2.prong0Id() || p1.childrenIds()[0] == p2.prong1Id() || p1.childrenIds()[1] == p2.prong0Id() || p1.childrenIds()[1] == p2.prong1Id()) + if (p1.childrenIds()[0] == p2.prong0Id() || p1.childrenIds()[0] == p2.prong1Id() || p1.childrenIds()[1] == p2.prong0Id() || p1.childrenIds()[1] == p2.prong1Id()) { continue; + } } else if constexpr (Channel == DecayChannel::LcToPKPi || Channel == DecayChannel::DplusToPiKPi) { - if (p1.childrenIds()[0] == p2.prong0Id() || p1.childrenIds()[0] == p2.prong1Id() || p1.childrenIds()[0] == p2.prong2Id() || p1.childrenIds()[1] == p2.prong0Id() || p1.childrenIds()[1] == p2.prong1Id() || p1.childrenIds()[1] == p2.prong2Id()) + if (p1.childrenIds()[0] == p2.prong0Id() || p1.childrenIds()[0] == p2.prong1Id() || p1.childrenIds()[0] == p2.prong2Id() || p1.childrenIds()[1] == p2.prong0Id() || p1.childrenIds()[1] == p2.prong1Id() || p1.childrenIds()[1] == p2.prong2Id()) { continue; + } } else if constexpr (Channel == DecayChannel::DstarToD0Pi) { - if (p1.childrenIds()[0] == p2.prong0Id() || p1.childrenIds()[0] == p2.prong1Id() || p1.childrenIds()[0] == p2.prong2Id() || p1.childrenIds()[1] == p2.prong0Id() || p1.childrenIds()[1] == p2.prong1Id() || p1.childrenIds()[1] == p2.prong2Id()) + if (p1.childrenIds()[0] == p2.prong0Id() || p1.childrenIds()[0] == p2.prong1Id() || p1.childrenIds()[0] == p2.prong2Id() || p1.childrenIds()[1] == p2.prong0Id() || p1.childrenIds()[1] == p2.prong1Id() || p1.childrenIds()[1] == p2.prong2Id()) { continue; + } } // v0 daughters selection const auto& posChild = femtoParts.iteratorAt(p1.index() - 2); @@ -453,10 +454,11 @@ struct HfTaskCharmHadronsV0FemtoDream { } float invMassV0 = 0.f; - if (p1.sign() > 0) + if (p1.sign() > 0) { invMassV0 = p1.mLambda(); - else + } else { invMassV0 = p1.mAntiLambda(); + } float chargeV0 = 0.; if ((p1.cut() & p1.sign()) == CutBitChargePositive) { @@ -543,10 +545,11 @@ struct HfTaskCharmHadronsV0FemtoDream { } float invMassV0 = 0.f; - if (p1.sign() > 0) + if (p1.sign() > 0) { invMassV0 = p1.mLambda(); - else + } else { invMassV0 = p1.mAntiLambda(); + } float chargeV0 = 0.; if ((p1.cut() & p1.sign()) == CutBitChargePositive) { @@ -723,8 +726,9 @@ struct HfTaskCharmHadronsV0FemtoDream { FDV0Particles const& parts, CharmPart& charmPart) { - if (!mixSetting.doMixEvent) + if (!mixSetting.doMixEvent) { return; + } auto run = [&](auto& v0Part) { switch (mixSetting.mixingBinPolicy) { case femtodreamcollision::kMult: @@ -741,12 +745,13 @@ struct HfTaskCharmHadronsV0FemtoDream { } }; - if (v0Sel.pdgCodeV0 == kLambda0) + if (v0Sel.pdgCodeV0 == kLambda0) { run(partitionLambda); - else if (v0Sel.pdgCodeV0 == kK0Short) + } else if (v0Sel.pdgCodeV0 == kK0Short) { run(partitionK0Short); - else + } else { LOG(fatal) << "Unsupported V0 PDG: " << v0Sel.pdgCodeV0 << " (allowed: 3122, 310) for mixed-events"; + } } void processDataLcV0(FilteredCollisions const& cols, diff --git a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx index 74c33e0868e..2d51bc7ece9 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx @@ -164,6 +164,12 @@ struct HfTaskCorrelationD0Hadrons { AxisSpec axisCentFT0M = {binsCentFt0m, "Centrality percentile (FT0M)"}; // Histograms for data + + registry.add("hBdtScorePrompt", "D0 BDT prompt score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hBdtScoreBkg", "D0 BDT bkg score", {HistType::kTH1F, {axisBdtScore}}); + registry.add("hMassD0VsPt", "D0 candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hMassD0VsPtWoEff", "D0 candidates massVsPt without efficiency", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); + registry.add("hDeltaEtaPtIntSignalRegion", "D0-h deltaEta signal region", {HistType::kTH1F, {axisDeltaEta}}); registry.add("hDeltaPhiPtIntSignalRegion", "D0-h deltaPhi signal region", {HistType::kTH1F, {axisDeltaPhi}}); registry.add("hCorrel2DPtIntSignalRegion", "D0-h deltaPhi vs deltaEta signal region", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); @@ -308,6 +314,7 @@ struct HfTaskCorrelationD0Hadrons { aod::D0CandRecoInfo const& candidates) { for (const auto& candidate : candidates) { + float const massD = candidate.mD(); float const ptD = candidate.ptD(); float const bdtScorePromptD0 = candidate.mlScorePromptD0(); float const bdtScoreBkgD0 = candidate.mlScoreBkgD0(); @@ -324,6 +331,16 @@ struct HfTaskCorrelationD0Hadrons { (bdtScorePromptD0bar < mlOutputPromptD0bar->at(effBinD) || bdtScoreBkgD0bar > mlOutputBkgD0bar->at(effBinD))) { continue; } + + double efficiencyWeightD = 1.; + if (applyEfficiency != 0) { + efficiencyWeightD = 1. / efficiencyDmeson->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); + } + + registry.fill(HIST("hMassD0VsPt"), massD, ptD, efficiencyWeightD); + registry.fill(HIST("hMassD0VsPtWoEff"), massD, ptD); + registry.fill(HIST("hBdtScorePrompt"), bdtScorePromptD0); + registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkgD0); } for (const auto& pairEntry : pairEntries) { diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx new file mode 100644 index 00000000000..c37c1f73feb --- /dev/null +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusDplusReduced.cxx @@ -0,0 +1,140 @@ +// 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 taskCorrelationDplusDplusReduced.cxx +/// \brief Writer of pairs of D mesons candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples or ML training. +/// In this file are defined and filled the output tables +/// +/// \author Valerio DI BELLA , IPHC Strasbourg +/// Based on the code of Alexandre Bigot , IPHC Strasbourg + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/HFC/DataModel/ReducedDMesonPairsTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct HfTaskCorrelationDplusDplusReduced { + Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; + + using SelectedCandidates = soa::Filtered; + using SelectedMcParticles = o2::aod::HfCandDpMcPs; + + Filter filterSelectCandidates = aod::full::candidateSelFlag >= selectionFlagDplus; + + HistogramConfigSpec hTH1NCand{HistType::kTH1F, {{7, -0.5, 6.5}}}; + HistogramConfigSpec hTH1NMcRec{HistType::kTH1F, {{7, -0.5, 6.5}}}; + HistogramConfigSpec hTH1NMcGen{HistType::kTH1F, {{7, -0.5, 6.5}}}; + HistogramRegistry registry{ + "registry", + {{"hNCand", "Number of D candidates per event;N", hTH1NCand}, + {"hNMcRec", "Number of reconstructed Mc D mesons per event;N", hTH1NMcRec}, + {"hNMcGen", "Number of generated Mc D mesons per event;N", hTH1NMcGen}}}; + + void init(InitContext const&) + { + registry.add("hMassDplus", "D+ candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDminus", "D- candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDplusMatched", "D+ matched candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDminusMatched", "D- matched candidates;inv. mass (#pi#pi K) (GeV/#it{c}^{2}))", {HistType::kTH1F, {{120, 1.5848, 2.1848}}}); + registry.add("hMassDplusminusPair", "D plus-minus pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); + registry.add("hMassDplusPair", "D plus pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); + registry.add("hMassDminusPair", "D minus pair candidates;inv. mass (#pi K) (GeV/#it{c}^{2});inv. mass (#pi K) (GeV/#it{c}^{2})", {HistType::kTH2F, {{120, 1.5848, 2.1848}, {120, 1.5848, 2.1848}}}); + registry.add("hDltPhiMcGen", "Azimuthal correlation for D mesons; #Delta#phi", {HistType::kTH1F, {{100, -3.141593, 3.141593}}}); + } + + void processLocalData(o2::aod::HfCandDpFullEvs::iterator const&, + SelectedCandidates const& localCandidates) + { + registry.fill(HIST("hNCand"), localCandidates.size()); + + for (const auto& cand1 : localCandidates) { + auto mass1 = cand1.m(); + auto sign1 = 1; + if (cand1.pt() < 0) { + sign1 = -1; + registry.fill(HIST("hMassDminus"), mass1); + } else { + registry.fill(HIST("hMassDplus"), mass1); + } + + for (auto cand2 = cand1 + 1; cand2 != localCandidates.end(); ++cand2) { + auto mass2 = cand2.m(); + auto sign2 = 1; + if (cand2.pt() < 0) { + sign2 = -1; + } + if (sign1 == sign2) { + if (sign1 == 1) { + registry.fill(HIST("hMassDplusPair"), mass2, mass1); + } else { + registry.fill(HIST("hMassDminusPair"), mass2, mass1); + } + } else { + registry.fill(HIST("hMassDplusminusPair"), mass2, mass1); + } + } + } + } + PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalData, "Process local data", true); + + void processLocalDataMcRec(o2::aod::HfCandDpFullEvs::iterator const&, + SelectedCandidates const& localCandidates) + { + registry.fill(HIST("hNMcRec"), localCandidates.size()); + + for (const auto& cand1 : localCandidates) { + auto mass1 = cand1.m(); + if (cand1.pt() < 0) { + registry.fill(HIST("hMassDminus"), mass1); + if (std::abs(cand1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) + registry.fill(HIST("hMassDminusMatched"), mass1); + } else { + registry.fill(HIST("hMassDplus"), mass1); + if (std::abs(cand1.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) + registry.fill(HIST("hMassDplusMatched"), mass1); + } + } + } + PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalDataMcRec, "Process local MC data", false); + + void processLocalDataMcGen(o2::aod::HfCandDpMcEvs::iterator const&, + SelectedMcParticles const& localMcParticles) + { + registry.fill(HIST("hNMcGen"), localMcParticles.size()); + + for (const auto& part1 : localMcParticles) { + for (auto part2 = part1 + 1; part2 != localMcParticles.end(); ++part2) { + registry.fill(HIST("hDltPhiMcGen"), part2.phi() - part1.phi()); + } + } + } + PROCESS_SWITCH(HfTaskCorrelationDplusDplusReduced, processLocalDataMcGen, "Process local MC data at the gen level", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index f374d34a42d..1b412d170e9 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -148,7 +148,7 @@ struct HfTaskCorrelationDplusHadrons { 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"}; - Service ccdb; + Service ccdb{}; std::shared_ptr mEfficiencyPrompt = nullptr; std::shared_ptr mEfficiencyFD = nullptr; std::shared_ptr mEfficiencyAssociated = nullptr; diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index e257beec41e..622c5a7a037 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -31,6 +31,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include @@ -47,6 +49,7 @@ #include #include #include +#include #include #include @@ -155,7 +158,7 @@ struct HfTaskCorrelationDsHadrons { SliceCache cache; - Service ccdb; + Service ccdb{}; using DsHadronPair = soa::Filtered>; using DsHadronPairFull = soa::Filtered>; @@ -254,7 +257,12 @@ struct HfTaskCorrelationDsHadrons { registry.add("hDeltaEtaPtIntSidebandRightMcRec", "Ds-h deltaEta sideband right region MC reco", {HistType::kTH1F, {axisDetlaEta}}); registry.add("hDeltaPhiPtIntSidebandRightMcRec", "Ds-h deltaPhi sideband right region MC reco", {HistType::kTH1F, {axisDetlaPhi}}); registry.add("hCorrel2DVsPtSidebandRightMcRec", "Ds-h correlations sideband right region MC reco", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); - + if (doLSpair) { + registry.add("hCorrel2DVsPtPhysicalPrimaryMcRecLS", "Ds-h correlations signal region (only true primary particles) MC reco", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisDsPrompt}, {axisPoolBin}}}); + } + if (doULSpair) { + registry.add("hCorrel2DVsPtPhysicalPrimaryMcRecULS", "Ds-h correlations signal region (only true primary particles) MC reco", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisDsPrompt}, {axisPoolBin}}}); + } registry.get(HIST("hCorrel2DVsPtSignalRegionMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSidebandLeftMcRec"))->Sumw2(); @@ -270,6 +278,14 @@ struct HfTaskCorrelationDsHadrons { registry.add("hCorrel2DVsPtMcGenNonPromptDsNonPromptHadron", "Ds-h correlations non prompt Ds non prompt h MC Gen", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtMcGenNonPrompt", "Ds-h correlations NonPrompt MC Gen", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + if (doLSpair) { + registry.add("hCorrel2DVsPtMcGenPromptLS", "Ds-h correlations Prompt MC Gen", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtMcGenNonPromptLS", "Ds-h correlations NonPrompt MC Gen", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + } + if (doULSpair) { + registry.add("hCorrel2DVsPtMcGenPromptULS", "Ds-h correlations Prompt MC Gen", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtMcGenNonPromptULS", "Ds-h correlations NonPrompt MC Gen", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}); + } registry.get(HIST("hCorrel2DVsPtMcGen"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtMcGenPrompt"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtMcGenNonPrompt"))->Sumw2(); @@ -509,6 +525,7 @@ struct HfTaskCorrelationDsHadrons { int const trackTpcCrossedRows = pairEntry.trackTPCNClsCrossedRows(); int const poolBin = pairEntry.poolBin(); int const ptBinD = o2::analysis::findBin(binsPtD, std::abs(ptD)); + const bool haveSameSign = ptD * ptHadron > 0.; if (!isSelectedCandidate(ptBinD, bdtScorePrompt, bdtScoreBkg)) { continue; @@ -527,9 +544,9 @@ struct HfTaskCorrelationDsHadrons { // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSignalRegionLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSignalRegionULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -539,9 +556,9 @@ struct HfTaskCorrelationDsHadrons { } // in sideband left region if (massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandLeftLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandLeftULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSidebandLeft"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -551,9 +568,9 @@ struct HfTaskCorrelationDsHadrons { } // in sideband right region if (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandRightLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandRightULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSidebandRight"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -618,6 +635,7 @@ struct HfTaskCorrelationDsHadrons { int const statusPromptHadron = pairEntry.trackOrigin(); int const ptBinD = o2::analysis::findBin(binsPtD, std::abs(ptD)); bool const isPhysicalPrimary = pairEntry.isPhysicalPrimary(); + const bool haveSameSign = ptD * ptHadron > 0.; if (!isSelectedCandidate(ptBinD, bdtScorePrompt, bdtScoreBkg)) { continue; @@ -642,7 +660,13 @@ struct HfTaskCorrelationDsHadrons { registry.fill(HIST("hDeltaPhiPtIntSignalRegionMcRec"), deltaPhi, efficiencyWeight); registry.fill(HIST("hCorrel2DVsPtSignalRegionMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); if (isPhysicalPrimary) { - registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + if (doLSpair && haveSameSign) { // like-sign pairs + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRecLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRecULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + } else { // default case + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + } if (statusDsPrompt == 1 && statusPromptHadron == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hCorrel2DVsPtSignalRegionPromptDsPromptHadronMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (statusDsPrompt == 0 && statusPromptHadron == RecoDecay::OriginType::NonPrompt) { @@ -679,17 +703,30 @@ struct HfTaskCorrelationDsHadrons { int const poolBin = pairEntry.poolBin(); int const statusPromptHadron = pairEntry.trackOrigin(); bool const isDsPrompt = pairEntry.isPrompt(); + const bool haveSameSign = ptD * ptHadron > 0.; registry.fill(HIST("hCorrel2DVsPtMcGen"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); registry.fill(HIST("hDeltaEtaPtIntMcGen"), deltaEta); registry.fill(HIST("hDeltaPhiPtIntMcGen"), deltaPhi); if (isDsPrompt) { registry.fill(HIST("hCorrel2DVsPtMcGenPrompt"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); + if (doULSpair && !haveSameSign) { + registry.fill(HIST("hCorrel2DVsPtMcGenPromptULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); + } + if (doLSpair && haveSameSign) { + registry.fill(HIST("hCorrel2DVsPtMcGenPromptLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); + } if (statusPromptHadron == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hCorrel2DVsPtMcGenPromptDsPromptHadron"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); } } else { registry.fill(HIST("hCorrel2DVsPtMcGenNonPrompt"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); + if (doULSpair && !haveSameSign) { + registry.fill(HIST("hCorrel2DVsPtMcGenNonPromptULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); + } + if (doLSpair && haveSameSign) { + registry.fill(HIST("hCorrel2DVsPtMcGenNonPromptLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); + } if (statusPromptHadron == RecoDecay::OriginType::NonPrompt) { registry.fill(HIST("hCorrel2DVsPtMcGenNonPromptDsNonPromptHadron"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin); } @@ -715,6 +752,7 @@ struct HfTaskCorrelationDsHadrons { int const trackTpcCrossedRows = pairEntry.trackTPCNClsCrossedRows(); int const poolBin = pairEntry.poolBin(); int const ptBinD = o2::analysis::findBin(binsPtD, std::abs(ptD)); + const bool haveSameSign = ptD * ptHadron > 0.; if (!isSelectedCandidate(ptBinD, bdtScorePrompt, bdtScoreBkg)) { continue; @@ -733,9 +771,9 @@ struct HfTaskCorrelationDsHadrons { // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSignalRegionLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSignalRegionULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -745,9 +783,9 @@ struct HfTaskCorrelationDsHadrons { } // in sideband left region if (massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandLeftLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandLeftULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSidebandLeft"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -757,9 +795,9 @@ struct HfTaskCorrelationDsHadrons { } // in sideband right region if (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandRightLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandRightULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSidebandRight"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -783,6 +821,7 @@ struct HfTaskCorrelationDsHadrons { int multPvContrib = pairEntry.numPvContrib(); int const poolBin = pairEntry.poolBin(); int const ptBinD = o2::analysis::findBin(binsPtD, std::abs(ptD)); + const bool haveSameSign = ptD * ptHadron > 0.; double efficiencyWeight = 1.; if (useHighDimHistoForEff) { @@ -793,9 +832,9 @@ struct HfTaskCorrelationDsHadrons { // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSignalRegionLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSignalRegionULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -805,9 +844,9 @@ struct HfTaskCorrelationDsHadrons { } // in sideband left region if (massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandLeftLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandLeftULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSidebandLeft"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -817,9 +856,9 @@ struct HfTaskCorrelationDsHadrons { } // in sideband right region if (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD)) { - if (doLSpair && ((ptD > 0. && ptHadron > 0.) || (ptD < 0. && ptHadron < 0.))) { // like-sign pairs + if (doLSpair && haveSameSign) { // like-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandRightLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); - } else if (doULSpair && ((ptD > 0. && ptHadron < 0.) || (ptD < 0. && ptHadron > 0.))) { // unlike-sign pairs + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs registry.fill(HIST("hCorrel2DVsPtSidebandRightULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (fillHistoData) { // default case registry.fill(HIST("hCorrel2DVsPtSidebandRight"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); @@ -852,6 +891,7 @@ struct HfTaskCorrelationDsHadrons { int const statusPromptHadron = pairEntry.trackOrigin(); int const ptBinD = o2::analysis::findBin(binsPtD, std::abs(ptD)); bool const isPhysicalPrimary = pairEntry.isPhysicalPrimary(); + const bool haveSameSign = ptD * ptHadron > 0.; if (!isSelectedCandidate(ptBinD, bdtScorePrompt, bdtScoreBkg)) { continue; @@ -876,7 +916,13 @@ struct HfTaskCorrelationDsHadrons { registry.fill(HIST("hDeltaPhiPtIntSignalRegionMcRec"), deltaPhi, efficiencyWeight); registry.fill(HIST("hCorrel2DVsPtSignalRegionMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); if (isPhysicalPrimary) { - registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + if (doLSpair && haveSameSign) { // like-sign pairs + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRecLS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + } else if (doULSpair && !haveSameSign) { // unlike-sign pairs + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRecULS"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + } else { // default case + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), statusDsPrompt, poolBin, efficiencyWeight); + } if (statusDsPrompt == 1 && statusPromptHadron == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hCorrel2DVsPtSignalRegionPromptDsPromptHadronMcRec"), deltaPhi, deltaEta, std::abs(ptD), std::abs(ptHadron), poolBin, efficiencyWeight); } else if (statusDsPrompt == 0 && statusPromptHadron == RecoDecay::OriginType::NonPrompt) { diff --git a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx index 0b354abecee..9b15c6f7233 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx @@ -18,6 +18,7 @@ #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include #include #include #include @@ -27,8 +28,13 @@ #include #include +#include +#include #include +#include +#include +#include #include using namespace o2; @@ -71,15 +77,33 @@ const auto vecSidebandRightOuterDefault = std::vector{sidebandRightOuter const int npTBinsEfficiency = o2::analysis::hf_cuts_dstar_to_d0_pi::NBinsPt; const std::vector vecEfficiencyDstarDefault(npTBinsEfficiency); // line # 76 in taskCorrelationDstarHadron.cxx; why (npTBinsEfficiency+1) ? +const int nPtBinsTrackEfficiency = o2::analysis::hf_cuts_single_track::NBinsPtTrack; +const std::vector vecEfficiencyTracksDefault(nPtBinsTrackEfficiency); + // Dstar-Hadron correlation pair struct HfTaskCorrelationDstarHadrons { Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying efficiency weights"}; + Configurable useCcdbEfficiency{"useCcdbEfficiency", false, "Flag for using efficiency values from CCDB (if false, efficiency values must be provided via json files)"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathEfficiencyDstar{"ccdbPathEfficiencyDstar", "Users/d/desharma/HFC/Efficiency/Dstar", "path in ccdb for Dstar efficiency values"}; + Configurable ccdbPathEfficiencyTracks{"ccdbPathEfficiencyTracks", "Users/d/desharma/HFC/Efficiency/Track", "path in ccdb for track efficiency values"}; + Configurable ccdbTimestamp{"ccdbTimestamp", -1, "timestamp for retrieving efficiency values from CCDB"}; + Configurable efficiencyDstarFileName{"efficiencyDstarFileName", "efficiencyHFCDstar.root", "name of the efficiency file for Dstar"}; + Configurable efficiencyTracksFileName{"efficiencyTracksFileName", "efficiencyHFCTrack.root", "name of the efficiency file for tracks"}; + Configurable nEfficiencyHist{"nEfficiencyHist", 1, "if MB nEfficiencyHist = 1, if Centrality classes nEfficiencyHist = number of centrality classes (i.e. 10)"}; + // 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{vecBinsPtCorrelationsDefault}, "pT bin limits for correlation plots"}; + + // efficiency configurables for candidate Dstar Configurable> binsPtEfficiency{"binsPtEfficiency", std::vector{o2::analysis::hf_cuts_dstar_to_d0_pi::vecBinsPt}, "pT bin limits for efficiency"}; Configurable> efficiencyDstar{"efficiencyDstar", std::vector{vecEfficiencyDstarDefault}, "efficiency values for Dstar vs pT bin"}; + // efficiency configurables for associated tracks + Configurable> binsPtEfficiencyTracks{"binsPtEfficiencyTracks", std::vector{o2::analysis::hf_cuts_single_track::vecBinsPtTrack}, "pT bin limits for track efficiency"}; + Configurable> efficiencyTracks{"efficiencyTracks", std::vector{vecEfficiencyTracksDefault}, "efficiency values for tracks vs pT bin"}; + Configurable> signalRegionLefBound{"signalRegionLefBound", std::vector{vecSignalRegionLefBoundDefault}, "left boundary of signal region vs pT"}; Configurable> signalRegionRightBound{"signalRegionRightBound", std::vector{vecSignalRegionRightBoundDefault}, "right boundary of signal region vs pT"}; // Configurable> leftSidebandOuterBoundary{"leftSidebandOuterBoundary", std::vector{vecSidebandLeftOuterDefault}, "left sideband outer boundary vs pT"}; @@ -93,6 +117,10 @@ struct HfTaskCorrelationDstarHadrons { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + o2::ccdb::CcdbApi ccdbApi; + std::vector vecHistEfficiencyDstar; + std::vector vecHistEfficiencyTracks; + void init(InitContext&) { @@ -111,6 +139,51 @@ struct HfTaskCorrelationDstarHadrons { registry.add("hCorrel2DPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2D, {axisSpecDeltaPhi, axisSpecDeltaEta}}, true); registry.add("hDeltaEtaPtIntSidebands", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1D, {axisSpecDeltaEta}}, true); registry.add("hDeltaPhiPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1D, {axisSpecDeltaPhi}}, true); + + if (applyEfficiency && useCcdbEfficiency) { + ccdbApi.init(ccdbUrl); + std::map const metadata; + bool const isEfficiencyDstarfileAvailable = ccdbApi.retrieveBlob(ccdbPathEfficiencyDstar, ".", metadata, ccdbTimestamp, false, efficiencyDstarFileName); + if (!isEfficiencyDstarfileAvailable) { + LOGF(fatal, "Failed to retrieve efficiency file for Dstar from CCDB"); + } + bool const isEfficiencyTracksfileAvailable = ccdbApi.retrieveBlob(ccdbPathEfficiencyTracks, ".", metadata, ccdbTimestamp, false, efficiencyTracksFileName); + if (!isEfficiencyTracksfileAvailable) { + LOGF(fatal, "Failed to retrieve efficiency file for tracks from CCDB"); + } + + TFile* efficiencyDstarRootFile = TFile::Open(efficiencyDstarFileName.value.c_str(), "READ"); + if (!efficiencyDstarRootFile || efficiencyDstarRootFile->IsZombie()) { + LOGF(fatal, "Failed to open efficiency file for Dstar"); + } + + TFile* efficiencyTracksRootFile = TFile::Open(efficiencyTracksFileName.value.c_str(), "READ"); + if (!efficiencyTracksRootFile || efficiencyTracksRootFile->IsZombie()) { + LOGF(fatal, "Failed to open efficiency file for tracks"); + } + + vecHistEfficiencyDstar.resize(nEfficiencyHist); + vecHistEfficiencyTracks.resize(nEfficiencyHist); + + for (int iHist = 0; iHist < nEfficiencyHist; iHist++) { + vecHistEfficiencyDstar[iHist] = dynamic_cast(efficiencyDstarRootFile->Get(Form("hEfficiencyDstar_%d", iHist))); + if (!vecHistEfficiencyDstar[iHist]) { + LOGF(fatal, "Failed to retrieve Dstar efficiency histogram hEfficiencyDstar_%d from file", iHist); + } + + vecHistEfficiencyTracks[iHist] = dynamic_cast(efficiencyTracksRootFile->Get(Form("hEfficiencyTracks_%d", iHist))); + if (!vecHistEfficiencyTracks[iHist]) { + LOGF(fatal, "Failed to retrieve track efficiency histogram hEfficiencyTracks_%d from file", iHist); + } + vecHistEfficiencyDstar[iHist]->SetDirectory(nullptr); + vecHistEfficiencyTracks[iHist]->SetDirectory(nullptr); + } + + efficiencyDstarRootFile->Close(); + efficiencyTracksRootFile->Close(); + delete efficiencyDstarRootFile; + delete efficiencyTracksRootFile; + } } void processData(aod::DstarHadronPair const& dstarHPairs) @@ -128,6 +201,9 @@ struct HfTaskCorrelationDstarHadrons { int const corrBinPtDstar = o2::analysis::findBin(binsPtCorrelations, ptDstar); // LOG(info) << "correlation index " << corrBinPtDstar; + int const effBinPtTrack = o2::analysis::findBin(binsPtEfficiencyTracks, ptTrack); + // LOG(info) << "track efficiency index " << effBinPtTrack; + // reject candidate if outside pT ranges of interst if (corrBinPtDstar < 0 || effBinPtDstar < 0) { continue; @@ -137,12 +213,22 @@ struct HfTaskCorrelationDstarHadrons { // ptTrack = 10.5; // } float netEfficiencyWeight = 1.0; - float const efficiencyWeightTracks = 1.0; - if (applyEfficiency) { + if (applyEfficiency && !useCcdbEfficiency) { float const efficiencyWeightDstar = efficiencyDstar->at(effBinPtDstar); // LOG(info)<<"efficiencyWeightDstar "<at(effBinPtTrack); + // LOG(info)<<"efficiencyWeightTracks "<GetBinContent(vecHistEfficiencyDstar[0]->GetXaxis()->FindBin(ptDstar)); + // LOG(info)<<"efficiencyWeightDstar "<GetBinContent(vecHistEfficiencyTracks[0]->GetXaxis()->FindBin(ptTrack)); + // LOG(info)<<"efficiencyWeightTracks "< 1) { + // to do + LOGF(fatal, "Using CCDB efficiency with more than 1 histogram is not implemented yet"); } // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots diff --git a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx index a2e69b2e144..9ca930af538 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx @@ -163,7 +163,7 @@ struct HfTaskCorrelationLcHadrons { std::shared_ptr mEfficiencyFD = nullptr; std::shared_ptr mEfficiencyAssociated = nullptr; - Service ccdb; + Service ccdb{}; enum CandidateStep { kCandidateStepMcGenAll = 0, kCandidateStepMcGenLcToPKPi, @@ -269,6 +269,7 @@ struct HfTaskCorrelationLcHadrons { registry.add("hCorrel2DPtIntSidebandsMcRec", stringLcHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}); registry.add("hCorrel2DVsPtSidebandsMcRec", stringLcHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtPhysicalPrimaryMcRec", stringLcHadron + "(only true primary particles)" + stringSignal, {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisLcPrompt}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtTrueLcPhysicalPrimaryMcRec", stringLcHadron + "(only true Lc, and true primary particles)" + stringSignal, {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisLcPrompt}, {axisPoolBin}}}); registry.add("hDeltaEtaPtIntSidebandLeftMcRec", stringLcHadron + "Left" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTH1D, {axisDeltaEta}}); registry.add("hDeltaPhiPtIntSidebandLeftMcRec", stringLcHadron + "Left" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTH1D, {axisDeltaPhi}}); registry.add("hDeltaEtaPtIntSidebandRightMcRec", stringLcHadron + "Right" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTH1D, {axisDeltaEta}}); @@ -279,6 +280,8 @@ struct HfTaskCorrelationLcHadrons { registry.add("hCorrel2DVsPtSidebandRightMcRec", stringLcHadron + "Right" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtSignalRegionPromptLcPromptHadronMcRec", stringLcHadron + "signal region PromptLc - Prompt Track MC reco", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtSignalRegionNonPromptLcNonPromptHadronMcRec", stringLcHadron + " signal region PromptLc - NonPrompt Track MC reco", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtSignalRegionTruePromptLcPromptHadronMcRec", stringLcHadron + "signal region and true PromptLc - Prompt Track MC reco", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisPoolBin}}}); + registry.add("hCorrel2DVsPtSignalRegionTrueNonPromptLcNonPromptHadronMcRec", stringLcHadron + " signal region and true PromptLc - NonPrompt Track MC reco", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtLc}, {axisPtHadron}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtSignalMcRec", stringLcHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtSignalRegionMcRec", stringLcHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisLcPrompt}, {axisPoolBin}}}); registry.add("hCorrel2DVsPtBkgMcRec", stringLcHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtLc + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtCorr}, {axisPtHadron}, {axisPoolBin}}}); @@ -288,6 +291,8 @@ struct HfTaskCorrelationLcHadrons { registry.get(HIST("hCorrel2DVsPtSignalMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSignalRegionPromptLcPromptHadronMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSignalRegionNonPromptLcNonPromptHadronMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionTruePromptLcPromptHadronMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionTrueNonPromptLcNonPromptHadronMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSignalRegionMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtBkgMcRec"))->Sumw2(); @@ -321,6 +326,7 @@ struct HfTaskCorrelationLcHadrons { registry.get(HIST("hCorrel2DVsPtSidebandsMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtTrueLcPhysicalPrimaryMcRec"))->Sumw2(); } // Histograms for MC Gen analysis if (fillHistoMcGen) { @@ -713,17 +719,26 @@ struct HfTaskCorrelationLcHadrons { registry.fill(HIST("hDeltaPhiPtIntSignalRegionMcRec"), deltaPhi, efficiencyWeight); if (isPhysicalPrimary) { registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, statusLcPrompt, poolBin, efficiencyWeight); + if (pairEntry.signalStatus() != 0) { + registry.fill(HIST("hCorrel2DVsPtTrueLcPhysicalPrimaryMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, statusLcPrompt, poolBin, efficiencyWeight); + } if (statusLcPrompt == 1 && statusPromptHadron == RecoDecay::OriginType::Prompt) { if (fillSign) { registry.fill(HIST("hCorrel2DVsPtSignSignalRegionPromptLcPromptHadronMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, signPair, poolBin, efficiencyWeight); } else { registry.fill(HIST("hCorrel2DVsPtSignalRegionPromptLcPromptHadronMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, poolBin, efficiencyWeight); + if (pairEntry.signalStatus() != 0) { + registry.fill(HIST("hCorrel2DVsPtSignalRegionTruePromptLcPromptHadronMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, poolBin, efficiencyWeight); + } } } else if (statusLcPrompt == 0 && statusPromptHadron == RecoDecay::OriginType::NonPrompt) { if (fillSign) { registry.fill(HIST("hCorrel2DVsPtSignSignalRegionNonPromptLcNonPromptHadronMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, signPair, poolBin, efficiencyWeight); } else { registry.fill(HIST("hCorrel2DVsPtSignalRegionNonPromptLcNonPromptHadronMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, poolBin, efficiencyWeight); + if (pairEntry.signalStatus() != 0) { + registry.fill(HIST("hCorrel2DVsPtSignalRegionTrueNonPromptLcNonPromptHadronMcRec"), deltaPhi, deltaEta, ptLc, ptHadron, poolBin, efficiencyWeight); + } } } } diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index d54bfda6956..3591f8f3907 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -26,6 +26,7 @@ #include "PWGMM/Mult/DataModel/bestCollisionTable.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -74,6 +75,7 @@ using namespace o2; using namespace o2::analysis; using namespace o2::aod::pid_tpc_tof_utils; +using namespace o2::aod::rctsel; using namespace o2::aod::track; using namespace o2::constants::math; using namespace o2::framework; @@ -142,6 +144,21 @@ enum MultiplicityEstimators { MultFT0M }; +enum SpecificEventSelectionStep { + AllEventsPrecise = 0, + IsSel8, + IsNoSameBunchPileup, + IsGoodItsLayersAll, + IsGoodZvtxFT0vsPV, + IsNoCollInRofStandard, + IsNoCollInRofStrict, + IsNoCollInTimeRangeStandard, + IsNoCollInTimeRangeStrict, + IsNoHighMultCollInPrevRof, + IsRctFlagChecked, + NSpecificEventSelectionSteps +}; + enum TrackSelection { TrackSelectionNoCut = 0, TrackSelectionGlobalTrack @@ -185,6 +202,7 @@ struct HfTaskFlow { Configurable doReferenceFlow{"doReferenceFlow", false, "Flag to know if reference flow should be done"}; Configurable isReadoutCenter{"isReadoutCenter", false, "Enable Readout Center"}; Configurable nMixedEvents{"nMixedEvents", 5, "Number of mixed events per event"}; + Configurable nSamples{"nSamples", 10, "number of different samples for correlations"}; } configTask; // configurables for collisions @@ -192,11 +210,21 @@ struct HfTaskFlow { std::string prefix = "ConfigCollision_group"; Configurable isApplyGoodItsLayersAll{"isApplyGoodItsLayersAll", false, "Enable GoodITSLayersAll"}; Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", false, "Enable GoodZvtxFT0vsPV cut"}; + Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, ""}; + Configurable isApplyNoCollInRofStrict{"isApplyNoCollInRofStrict", false, ""}; + Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", false, ""}; + Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, ""}; + Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, ""}; Configurable isApplySameBunchPileup{"isApplySameBunchPileup", false, "Enable SameBunchPileup cut"}; Configurable maxMultiplicity{"maxMultiplicity", 300, "maximum multiplicity selection for collision"}; Configurable minMultiplicity{"minMultiplicity", 0, "minimum multiplicity selection for collision"}; Configurable multiplicityEstimator{"multiplicityEstimator", 0, "0: multNTracksPV, 1: numContrib, 2: multFT0C, 3: multFT0M, 4: centFT0C, 5: centFT0CVariants1s, 6: centFT0M, 7: centFV0A, 8: centNTracksPV, 9: centNGlobal, 10: centMFT"}; - Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, ""}; + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable requireCorrelationAnalysisRCTFlagChecker{"requireCorrelationAnalysisRCTFlagChecker", false, "Check event quality in run condition table for correlation analysis"}; + Configurable setRCTFlagCheckerLabel{"setRCTFlagCheckerLabel", "CBT_muon_global", "Evt sel: RCT flag checker label"}; + Configurable requireRCTFlagCheckerLimitAcceptanceAsBad{"requireRCTFlagCheckerLimitAcceptanceAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + Configurable requireZDCCheck{"requireZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable rctFlagCheckerLabel{"rctFlagCheckerLabel", "CBT_fw", "Evt sel: RCT flag checker label"}; Configurable zVertexMax{"zVertexMax", 10.0f, "Accepted z-vertex range"}; } configCollision; @@ -251,16 +279,26 @@ struct HfTaskFlow { Configurable useMftPtCut{"useMftPtCut", false, "if true, use the Mft pt function cut"}; } configMft; + // configurables for MFT tracks + struct : ConfigurableGroup { + std::string prefix = "ConfigFit_group"; + Configurable cfgGainEqPath{"cfgGainEqPath", "Analysis/EventPlane/GainEq", "CCDB path for gain equalization constants"}; + Configurable cfgCorrLevel{"cfgCorrLevel", 1, "calibration step: 0 = no corr, 1 = gain corr"}; + } configFit; + TF1* fPtDepDCAxy = nullptr; SliceCache cache; - Service pdg; - Service ccdb; + Service pdg{}; + Service ccdb{}; std::vector* offsetFT0{}; std::vector* offsetFV0{}; o2::ccdb::CcdbApi ccdbApi; o2::ft0::Geometry ft0Det; o2::fv0::Geometry* fv0Det{}; + std::vector cstFT0RelGain{}; + RCTFlagsChecker rctChecker; + RCTFlagsChecker correlationAnalysisRctChecker{kFT0Bad, kITSBad, kTPCBadTracking, kMFTBad}; // ========================= // using declarations : DATA @@ -343,6 +381,10 @@ struct HfTaskFlow { ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {1, -10, 10}, "vertex axis for efficiency histograms"}; + ConfigurableAxis axisAmplitudeFit{"axisAmplitudeFit", {5000, 0, 1000}, "FT0A amplitude axis"}; + ConfigurableAxis axisChannelFt0a{"axisChannelFt0a", {96, 0.0, 96.0}, "FT0A channel axis"}; + ConfigurableAxis axisSamples{"axisSamples", {10, 0, 10}, "sample axis for correlation containers"}; + ConfigurableAxis axisChID{"axisChID", {220, 0, 220}, "FIT channel ID"}; } configAxis; HistogramRegistry registry{"registry"}; @@ -429,13 +471,15 @@ struct HfTaskFlow { LOGF(info, "Offset for FT0C: x = %.3f y = %.3f z = %.3f\n", (*offsetFT0)[1].getX(), (*offsetFT0)[1].getY(), (*offsetFT0)[1].getZ()); LOGF(info, "Offset for FV0-left: x = %.3f y = %.3f z = %.3f\n", (*offsetFV0)[0].getX(), (*offsetFV0)[0].getY(), (*offsetFV0)[0].getZ()); LOGF(info, "Offset for FV0-right: x = %.3f y = %.3f z = %.3f\n", (*offsetFV0)[1].getX(), (*offsetFV0)[1].getY(), (*offsetFV0)[1].getZ()); - fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); // ========================= // Event histograms // ========================= + rctChecker.init(configCollision.setRCTFlagCheckerLabel, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad); + correlationAnalysisRctChecker.init({kFT0Bad, kITSBad, kTPCBadTracking, kMFTBad}, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad); + registry.add("Data/hVtxZ", "v_{z} (cm)", {HistType::kTH1D, {configAxis.axisVertex}}); registry.add("Data/hNTracks", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); registry.add(Form("Data/hMultiplicity_%s", WhatMultiplicityEstimator[configCollision.multiplicityEstimator].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); @@ -450,6 +494,25 @@ struct HfTaskFlow { registry.get(HIST("Data/hEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } + registry.add("Data/hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); + std::string labelsPreciseEventSelection[SpecificEventSelectionStep::NSpecificEventSelectionSteps]; + labelsPreciseEventSelection[SpecificEventSelectionStep::AllEventsPrecise] = "all"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsSel8] = "sel8"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoSameBunchPileup] = "IsNoSameBunchPileup"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsGoodItsLayersAll] = "IsGoodItsLayersAll"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsGoodZvtxFT0vsPV] = "IsGoodZvtxFT0vsPV"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInRofStandard] = "IsNoCollInRofStandard"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInRofStrict] = "IsNoCollInRofStrict"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInTimeRangeStandard] = "IsNoCollInTimeRangeStandard"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoCollInTimeRangeStrict] = "IsNoCollInTimeRangeStrict"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsNoHighMultCollInPrevRof] = "IsNoHighMultCollInPrevRof"; + labelsPreciseEventSelection[SpecificEventSelectionStep::IsRctFlagChecked] = "IsRctFlagChecked"; + registry.get(HIST("Data/hPreciseEventCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < SpecificEventSelectionStep::NSpecificEventSelectionSteps; iBin++) { + registry.get(HIST("Data/hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsPreciseEventSelection[iBin].data()); + } + mPairCuts.SetHistogramRegistry(®istry); if (configCentral.pairCut->get("Photon") > 0 || configCentral.pairCut->get("K0") > 0 || configCentral.pairCut->get("Lambda") > 0 || configCentral.pairCut->get("Phi") > 0 || configCentral.pairCut->get("Rho") > 0) { mPairCuts.SetPairCut(PairCuts::Photon, configCentral.pairCut->get("Photon")); @@ -472,7 +535,10 @@ struct HfTaskFlow { std::vector const effAxis = {{configAxis.axisEtaEfficiency, "#eta"}, {configAxis.axisPtEfficiency, "p_{T} (GeV/c)"}, {configAxis.axisVertexEfficiency, "z-vtx (cm)"}}; - std::vector const userAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}}; + std::vector const hfUserAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}}; + // std::vector const userAxis = {{configAxis.axisSamples, "sampling"}}; + // std::vector const hfUserAxis = {{configAxis.axisMass, "m_{inv} (GeV/c^{2})"}, + // {configAxis.axisSamples, "sampling"}}; // ========================= // Initialization of histograms and CorrelationContainers for TpcTpc cases @@ -480,20 +546,23 @@ struct HfTaskFlow { if (doprocessSameTpcTpcChCh) { addHistograms(); + sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); } if (doprocessSameTpcTpcD0Ch) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcTpcLcCh) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -512,16 +581,16 @@ struct HfTaskFlow { addHistograms(); addMftHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcMftLcCh || doprocessSameTpcMftLcChReassociated) { addHistograms(); addMftHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -538,15 +607,15 @@ struct HfTaskFlow { if (doprocessSameTpcFv0aD0Ch) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcFv0aLcCh) { addHistograms(); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -568,6 +637,8 @@ struct HfTaskFlow { if (doprocessSameTpcFt0aChCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); @@ -575,16 +646,20 @@ struct HfTaskFlow { if (doprocessSameTpcFt0aD0Ch) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcFt0aLcCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -594,6 +669,8 @@ struct HfTaskFlow { if (doprocessSameMftFt0aChCh || doprocessSameMftFt0aChChReassociated || doprocessSameMftFt0aChChReassociated3d || doprocessSameMftFt0aChChNonAmbiguous) { addHistograms(); addMftHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); @@ -605,6 +682,8 @@ struct HfTaskFlow { if (doprocessSameTpcFt0cChCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); @@ -612,16 +691,20 @@ struct HfTaskFlow { if (doprocessSameTpcFt0cD0Ch) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } if (doprocessSameTpcFt0cLcCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); - sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, userAxis)); - mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, userAxis)); + sameEventHf.setObject(new CorrelationContainer("sameEventHf", "sameEventHf", corrAxis, effAxis, hfUserAxis)); + mixedEventHf.setObject(new CorrelationContainer("mixedEventHf", "mixedEventHf", corrAxis, effAxis, hfUserAxis)); } // ========================= @@ -630,6 +713,8 @@ struct HfTaskFlow { if (doprocessSameFt0aFt0cChCh) { addHistograms(); + registry.add("Data/FT0Amp", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); + registry.add("Data/FT0AmpCorr", "", {HistType::kTH2F, {configAxis.axisChID, configAxis.axisAmplitudeFit}}); sameEvent.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, {})); mixedEvent.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, {})); @@ -722,10 +807,12 @@ struct HfTaskFlow { float dPhiStar = phi1 - phi2 - charge1 * fbSign * std::asin(0.075 * radius / pt1) + charge2 * fbSign * std::asin(0.075 * radius / pt2); - if (dPhiStar > constants::math::PI) + if (dPhiStar > constants::math::PI) { dPhiStar = constants::math::TwoPI - dPhiStar; - if (dPhiStar < -constants::math::PI) + } + if (dPhiStar < -constants::math::PI) { dPhiStar = -constants::math::TwoPI - dPhiStar; + } return dPhiStar; } @@ -756,7 +843,7 @@ struct HfTaskFlow { { int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); - float offsetX, offsetY; + float offsetX{}, offsetY{}; if (isChnoInLeft) { offsetX = (*offsetFV0)[0].getX(); offsetY = (*offsetFV0)[0].getY(); @@ -795,7 +882,7 @@ struct HfTaskFlow { { int const cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, 32, 40, 33, 41, 34, 42, 35, 43}; bool const isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); - float offsetX, offsetY, offsetZ; + float offsetX{}, offsetY{}, offsetZ{}; if (isChnoInLeft) { offsetX = (*offsetFV0)[0].getX(); offsetY = (*offsetFV0)[0].getY(); @@ -822,15 +909,49 @@ struct HfTaskFlow { } template - void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, int fitType) + void getChannel(TFT0s const& ft0, std::size_t const& iCh, int& id, int fitType, float& amplitude) { + int rID{0}; if (fitType == isFT0C) { id = ft0.channelC()[iCh] + MinFt0cCell; + rID = id + MinFt0cCell; + amplitude = ft0.amplitudeC()[iCh]; } else if (fitType == isFT0A) { id = ft0.channelA()[iCh]; + rID = id; + amplitude = ft0.amplitudeA()[iCh]; } else { LOGF(fatal, "Cor Index %d out of range", fitType); } + registry.fill(HIST("Data/FT0Amp"), rID, amplitude); + amplitude = amplitude / cstFT0RelGain[iCh]; + registry.fill(HIST("Data/FT0AmpCorr"), rID, amplitude); + } + + void loadGain(aod::BCsWithTimestamps::iterator const& bc) + { + cstFT0RelGain.clear(); + cstFT0RelGain = {}; + std::string fullPath; + + auto timestamp = bc.timestamp(); + constexpr int ChannelsFT0 = 208; + if (configFit.cfgCorrLevel == 0) { + for (auto i{0u}; i < ChannelsFT0; i++) { + cstFT0RelGain.push_back(1.); + } + } else { + fullPath = configFit.cfgGainEqPath; + fullPath += "/FT0"; + const auto objft0Gain = ccdb->getForTimeStamp>(fullPath, timestamp); + if (!objft0Gain) { + for (auto i{0u}; i < ChannelsFT0; i++) { + cstFT0RelGain.push_back(1.); + } + } else { + cstFT0RelGain = *(objft0Gain); + } + } } // ========================= @@ -843,23 +964,72 @@ struct HfTaskFlow { { if (fillHistograms) { registry.fill(HIST("Data/hEventCounter"), EventSelectionStep::AllEvents); + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); } if (!collision.sel8()) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsSel8); + } if (configCollision.isApplySameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoSameBunchPileup); + } + if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodItsLayersAll); + } if (configCollision.isApplyGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodZvtxFT0vsPV); + } + if (configCollision.isApplyNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStandard); + } + if (configCollision.isApplyNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStrict); + } + if (configCollision.isApplyNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStandard); + } if (configCollision.isApplyNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; } - if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStrict); + } + if (configCollision.isApplyNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsNoHighMultCollInPrevRof); + } + if (configCollision.requireRCTFlagChecker && !rctChecker(collision)) { return false; } + if (configCollision.requireCorrelationAnalysisRCTFlagChecker && !correlationAnalysisRctChecker(collision)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("Data/hPreciseEventCounter"), SpecificEventSelectionStep::IsRctFlagChecked); + } if (fillHistograms) { registry.fill(HIST("Data/hEventCounter"), EventSelectionStep::AfterEventSelection); @@ -987,6 +1157,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1107,15 +1278,16 @@ struct HfTaskFlow { bool bIsBelow = false; if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { - for (double rad(configCentral.minMergingRadius); rad < configCentral.maxMergingRadius; rad += 0.01) { + for (double rad(configCentral.minMergingRadius); rad < configCentral.maxMergingRadius; rad += 0.01) { // FIXME: Variable 'rad' with floating point type 'double' should not be used as a loop counter. double dPhiStar = getDPhiStar(track1, track2, rad, magneticField); if (std::abs(dPhiStar) < kLimit) { bIsBelow = true; break; } } - if (bIsBelow) + if (bIsBelow) { continue; + } } } } @@ -1191,6 +1363,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (const auto& track1 : tracks1) { @@ -1347,6 +1520,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1487,7 +1661,8 @@ struct HfTaskFlow { for (std::size_t indexChannel = 0; indexChannel < channelSize; indexChannel++) { int channelId = 0; - getChannel(tracks2, indexChannel, channelId, fitType); + float amplitude = 0.; + getChannel(tracks2, indexChannel, channelId, fitType, amplitude); auto phi2 = getPhiFT0(channelId, fitType); auto eta2 = getEtaFT0(channelId, fitType); float deltaPhi = phi1 - phi2; @@ -1495,10 +1670,10 @@ struct HfTaskFlow { if (!fillingHFcontainer) { target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + amplitude * triggerWeight * associatedWeight); } else { target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, invmass, - triggerWeight * associatedWeight); + amplitude * triggerWeight * associatedWeight); } // FILL QA PLOTS for associated particle @@ -1545,6 +1720,7 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE for (auto const& track1 : tracks1) { @@ -1617,14 +1793,15 @@ struct HfTaskFlow { for (std::size_t indexChannel = 0; indexChannel < channelSize; indexChannel++) { int channelId = 0; - getChannel(tracks2, indexChannel, channelId, fitType); + float amplitude = 0.; + getChannel(tracks2, indexChannel, channelId, fitType, amplitude); auto phi2 = getPhiFT0(channelId, fitType); auto eta2 = getEtaFT0(channelId, fitType); float deltaPhi = phi1 - phi2; deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); // set range of delta phi in (-pi/2 , 3/2*pi) target->getPairHist()->Fill(step, eta1 - eta2, pt1, pt1, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + amplitude * triggerWeight * associatedWeight); // FILL QA PLOTS for associated particle if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { @@ -1645,16 +1822,18 @@ struct HfTaskFlow { auto triggerWeight = 1; auto associatedWeight = 1; auto loopCounter = 0; // To avoid filling associated tracks QA many times, I fill it only for the first trigger track of the collision + // int sampleIndex = gRandom->Uniform(0, configTask.nSamples); // TRIGGER PARTICLE FROM FT0A for (std::size_t indexChannelA = 0; indexChannelA < ft0as.channelA().size(); indexChannelA++) { loopCounter++; int channelIdA = 0; - getChannel(ft0as, indexChannelA, channelIdA, isFT0A); + float amplitude = 0.; + getChannel(ft0as, indexChannelA, channelIdA, isFT0A, amplitude); auto phiA = getPhiFT0(channelIdA, isFT0A); auto etaA = getEtaFT0(channelIdA, isFT0A); - target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, triggerWeight); + target->getTriggerHist()->Fill(step, 0.f, multiplicity, posZ, amplitude * triggerWeight); if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { fillTriggerQa(multiplicity, etaA, phiA, 0.f); @@ -1664,13 +1843,14 @@ struct HfTaskFlow { for (std::size_t indexChannelC = 0; indexChannelC < ft0cs.channelC().size(); indexChannelC++) { int channelIdC = 0; - getChannel(ft0cs, indexChannelC, channelIdC, isFT0C); + float amplitude = 0.; + getChannel(ft0cs, indexChannelC, channelIdC, isFT0C, amplitude); auto phiC = getPhiFT0(channelIdC, isFT0C); auto etaC = getEtaFT0(channelIdC, isFT0C); float deltaPhi = RecoDecay::constrainAngle(phiA - phiC, -PIHalf); target->getPairHist()->Fill(step, etaA - etaC, 0.f, 0.f, multiplicity, deltaPhi, posZ, - triggerWeight * associatedWeight); + amplitude * triggerWeight * associatedWeight); if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { fillAssociatedQa(multiplicity, etaC, phiC); @@ -2300,13 +2480,17 @@ struct HfTaskFlow { void processSameTpcFt0aChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredTracksWDcaSel const& tracks, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); registry.fill(HIST("Data/hNTracks"), tracks.size()); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2327,13 +2511,17 @@ struct HfTaskFlow { void processSameTpcFt0aD0Ch(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelD0 const& candidates, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2353,13 +2541,17 @@ struct HfTaskFlow { void processSameTpcFt0aLcCh(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelLc const& candidates, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2379,13 +2571,17 @@ struct HfTaskFlow { void processSameMftFt0aChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredMftTracks const& mftTracks, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2402,13 +2598,17 @@ struct HfTaskFlow { void processSameMftFt0aChChReassociated(FilteredCollisionsWSelMult::iterator const& collision, soa::SmallGroups const& reassociatedMftTracks, FilteredMftTracks const&, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2425,13 +2625,17 @@ struct HfTaskFlow { void processSameMftFt0aChChReassociated3d(FilteredCollisionsWSelMult::iterator const& collision, soa::SmallGroups const& reassociatedMftTracks, FilteredMftTracks const&, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2448,13 +2652,17 @@ struct HfTaskFlow { void processSameMftFt0aChChNonAmbiguous(FilteredCollisionsWSelMult::iterator const& collision, soa::SmallGroups const& reassociatedMftTracks, FilteredMftTracks const&, - aod::FT0s const& ft0as) + aod::FT0s const& ft0as, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2474,13 +2682,17 @@ struct HfTaskFlow { void processSameTpcFt0cChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredTracksWDcaSel const& tracks, - aod::FT0s const& ft0cs) + aod::FT0s const& ft0cs, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); registry.fill(HIST("Data/hNTracks"), tracks.size()); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2501,13 +2713,17 @@ struct HfTaskFlow { void processSameTpcFt0cD0Ch(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelD0 const& candidates, - aod::FT0s const& ft0cs) + aod::FT0s const& ft0cs, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2527,13 +2743,17 @@ struct HfTaskFlow { void processSameTpcFt0cLcCh(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelLc const& candidates, - aod::FT0s const& ft0cs) + aod::FT0s const& ft0cs, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); @@ -2552,13 +2772,17 @@ struct HfTaskFlow { // ===================================== void processSameFt0aFt0cChCh(FilteredCollisionsWSelMult::iterator const& collision, - aod::FT0s const&) + aod::FT0s const&, + aod::BCsWithTimestamps const&) { if (!(isAcceptedCollision(collision, true))) { return; } + auto bc = collision.bc_as(); + if (collision.has_foundFT0()) { + loadGain(bc); const auto& ft0 = collision.foundFT0(); const auto multiplicity = getMultiplicityEstimator(collision, true); diff --git a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx index 65896cb5a10..e3a571d3bdd 100644 --- a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx +++ b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx @@ -189,11 +189,20 @@ struct HfElectronSelectionWithTpcEmcal { registry.add("hZvertex", "z vertex", {HistType::kTH1D, {axisPosZ}}); registry.add("hNeventsAfterPassEmcal", "No of events pass the Emcal", {HistType::kTH1D, {{3, 1, 4}}}); registry.add("hNevents", "No of events", {HistType::kTH1D, {{3, 1, 4}}}); - registry.add("hLikeMass", "Like mass", {HistType::kTH1D, {{axisMass}}}); - registry.add("hUnLikeMass", "unLike mass", {HistType::kTH1D, {{axisMass}}}); - registry.add("hLikeSignPt", "Like sign Momentum ", {HistType::kTH1D, {{axisPt}}}); - registry.add("hUnLikeSignPt", "UnLike sign Momentum", {HistType::kTH1D, {{axisPt}}}); + registry.add("hLikeMass_EMCAL", "Like mass Emcal", {HistType::kTH1D, {{axisMass}}}); + registry.add("hUnLikeMass_EMCAL", "unLike mass Emcal", {HistType::kTH1D, {{axisMass}}}); + registry.add("hLikeSignPt_EMCAL", "Like sign Momentum Emcal ", {HistType::kTH1D, {{axisPt}}}); + registry.add("hUnLikeSignPt_EMCAL", "UnLike sign Momentum Emcal", {HistType::kTH1D, {{axisPt}}}); + registry.add("hLikeMass_NoEMCAL", "Like mass NoEMCAL", {HistType::kTH1D, {{axisMass}}}); + registry.add("hUnLikeMass_NoEMCAL", "unLike mass NoEMCAL", {HistType::kTH1D, {{axisMass}}}); + registry.add("hLikeSignPt_NoEMCAL", "Like sign Momentum NoEMCAL ", {HistType::kTH1D, {{axisPt}}}); + registry.add("hUnLikeSignPt_NoEMCAL", "UnLike sign Momentum NoEMCAL", {HistType::kTH1D, {{axisPt}}}); + registry.add("hMcgenInElectron", "Mc Gen Inclusive Electron", {HistType::kTH1D, {{axisPt}}}); + registry.add("hMcRecInElectron", "Mc Rec Inclusive Electron", {HistType::kTH1D, {{axisPt}}}); + registry.add("hMcRecwithoutEMCalInElectron", "Mc Rec Inclusive Electron without Emcal", {HistType::kTH1D, {{axisPt}}}); + registry.add("hphiElectron", "hphiElectron", {HistType::kTH1D, {axisPhi}}); + registry.add("hphiElectronPassEmcal", "hphiElectron pass Emcal", {HistType::kTH1D, {axisPhi}}); registry.add("hMcgenAllNonHfeElectron", "Mc Gen All NonHf Electron", {HistType::kTH1D, {{axisPt}}}); registry.add("hMcgenNonHfeElectron", "Mc Gen NonHf Electron with mother", {HistType::kTH1D, {{axisPt}}}); registry.add("hPi0eEmbTrkPt", "Mc Gen Pi0 mother NonHf Electron", {HistType::kTH1D, {{axisPt}}}); @@ -350,7 +359,9 @@ struct HfElectronSelectionWithTpcEmcal { vecLSMass.push_back(massLike); isLSElectron = true; if (isEMcal) { - registry.fill(HIST("hLikeMass"), massLike); + registry.fill(HIST("hLikeMass_EMCAL"), massLike); + } else { + registry.fill(HIST("hLikeMass_NoEMCAL"), massLike); } } // for unlike charge @@ -359,7 +370,9 @@ struct HfElectronSelectionWithTpcEmcal { vecULSMass.push_back(massUnLike); isULSElectron = true; if (isEMcal) { - registry.fill(HIST("hUnLikeMass"), massUnLike); + registry.fill(HIST("hUnLikeMass_EMCAL"), massUnLike); + } else { + registry.fill(HIST("hUnLikeMass_NoEMCAL"), massUnLike); } } @@ -368,7 +381,9 @@ struct HfElectronSelectionWithTpcEmcal { massLike = invMassElectron; ++nElPairsLS; if (isEMcal) { - registry.fill(HIST("hLikeSignPt"), electron.pt()); + registry.fill(HIST("hLikeSignPt_EMCAL"), electron.pt()); + } else { + registry.fill(HIST("hLikeSignPt_NoEMCAL"), electron.pt()); } } // for unlike charge @@ -376,7 +391,9 @@ struct HfElectronSelectionWithTpcEmcal { massUnLike = invMassElectron; ++nElPairsUS; if (isEMcal) { - registry.fill(HIST("hUnLikeSignPt"), electron.pt()); + registry.fill(HIST("hUnLikeSignPt_EMCAL"), electron.pt()); + } else { + registry.fill(HIST("hUnLikeSignPt_NoEMCAL"), electron.pt()); } } } @@ -386,7 +403,7 @@ struct HfElectronSelectionWithTpcEmcal { } // Electron Identification template - void fillElectronTrack(CollisionType const& collision, TracksType const& tracks, EmcClusterType const& emcClusters, MatchType const& matchedTracks, ParticleType const& /*particlemc*/) + void fillElectronTrack(CollisionType const& collision, TracksType const& tracks, EmcClusterType const& emcClusters, MatchType const& matchedTracks, ParticleType const&) { if (!(isRun3 ? collision.sel8() : (collision.sel7() && collision.alias_bit(kINT7)))) { return; @@ -442,7 +459,7 @@ struct HfElectronSelectionWithTpcEmcal { } if (fillTrackInfo) { - registry.fill(HIST("hTrackEtaPhi"), etaTrack, phiTrack, passEMCal); // track etaphi infor after filter bit + // track etaphi infor after filter bit registry.fill(HIST("hTrackEnergyLossVsP"), track.tpcSignal(), pTrack, passEMCal); // track etaphi infor after filter bit registry.fill(HIST("hTrackEnergyLossVsPt"), track.tpcSignal(), ptTrack, passEMCal); // track etaphi infor after filter bit registry.fill(HIST("hTracknSigmaVsP"), tpcNsigmaTrack, pTrack, passEMCal); // track etaphi infor after filter bit @@ -527,9 +544,105 @@ struct HfElectronSelectionWithTpcEmcal { if (eop < eopElectronMin || eop > eopElectronMax) { continue; } - + registry.fill(HIST("hphiElectronPassEmcal"), track.phi()); ///////////////// NonHf electron Selection with Emcal //////////////////////// + if constexpr (IsMc) { + if (matchTrack.has_mcParticle()) { + auto mcParticle = matchTrack.template mcParticle_as(); + if (std::abs(mcParticle.pdgCode()) == kElectron) { + + registry.fill(HIST("hMcRecInElectron"), mcParticle.pt()); + bool isEmbEta = false; + bool isEmbPi0 = false; + + // Check first mother + if (mcParticle.has_mothers()) { + auto const& mother = mcParticle.template mothers_first_as(); + + if (std::abs(mother.pdgCode()) == kEtaLocal || std::abs(mother.pdgCode()) == kPi0 || std::abs(mother.pdgCode()) == kGamma) { + + auto const& gmother = mother.template mothers_first_as(); + // cases to consider: eta->e, eta->pi0->e, eta->gamma->e, eta->pi0->gamma->e, pi0->e, pi0->gamma->e + + //================= eta->e ====================================== + if (std::abs(mother.pdgCode()) == kEtaLocal) { + + if (mother.isPhysicalPrimary()) { + if ((std::abs(gmother.pdgCode()) >= pdgCodeCharmMin && std::abs(gmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(gmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(gmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; + } + } + + //================= eta->pi0->e ====================================== + + if (std::abs(mother.pdgCode()) == kPi0) { + if (mother.isPhysicalPrimary()) { + if ((std::abs(gmother.pdgCode()) >= pdgCodeCharmMin && std::abs(gmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(gmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(gmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbPi0 = true; // pi0 -> e + } + if (std::abs(gmother.pdgCode()) == kEtaLocal) { + if (gmother.isPhysicalPrimary() || gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if ((std::abs(ggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(ggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(ggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(ggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; // eta->pi0-> e + } + } + } + /// ==================================== eta->gamma->e and eta->pi0->gamma->e============ + if (std::abs(mother.pdgCode()) == kGamma) { + + if (std::abs(gmother.pdgCode()) == kEtaLocal) { + if (gmother.isPhysicalPrimary() || gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if ((std::abs(ggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(ggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(ggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(ggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; // eta->gamma-> e + } + } + if (std::abs(gmother.pdgCode()) == kPi0) { + if (gmother.isPhysicalPrimary() || gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if ((std::abs(ggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(ggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(ggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(ggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbPi0 = true; // pi0-> gamma-> e + } + if (gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if (std::abs(ggmother.pdgCode()) == kEtaLocal) { + if (ggmother.isPhysicalPrimary() || ggmother.has_mothers()) { + auto const& gggmother = ggmother.template mothers_first_as(); + if ((std::abs(gggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(gggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(gggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(gggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; // eta->pi0->gamma-> e + } + } + } + } + } + if (!(isEmbPi0 && isEmbEta)) { + continue; + } + } + } + } + } + } nonHfe(matchTrack, tracks, true); ///////////////// NonHf electron Selection without Emcal //////////////////////// @@ -540,14 +653,113 @@ struct HfElectronSelectionWithTpcEmcal { if (isEMcal) { continue; } - if (std::abs(track.tofNSigmaEl()) > tofNSigmaEl) + if (std::abs(track.tofNSigmaEl()) > tofNSigmaEl) { continue; + } registry.fill(HIST("hTofNSigmaVsPt"), track.tofNSigmaEl(), track.pt()); registry.fill(HIST("hTpcNSigmaVsPt"), track.tpcNSigmaEl(), track.pt()); - if ((track.tpcNSigmaEl() < tpcNsigmaElectronMin || track.tpcNSigmaEl() > tpcNsigmaElectronMax)) + if ((track.tpcNSigmaEl() < tpcNsigmaElectronMin || track.tpcNSigmaEl() > tpcNsigmaElectronMax)) { continue; + } + registry.fill(HIST("hphiElectron"), track.phi()); + if constexpr (IsMc) { + if (track.has_mcParticle()) { + auto mcParticle = track.template mcParticle_as(); + if (std::abs(mcParticle.pdgCode()) == kElectron) { + + registry.fill(HIST("hMcRecwithoutEMCalInElectron"), mcParticle.pt()); + bool isEmbEta = false; + bool isEmbPi0 = false; + // Check first mother + if (mcParticle.has_mothers()) { + auto const& mother = mcParticle.template mothers_first_as(); + + if (std::abs(mother.pdgCode()) == kEtaLocal || std::abs(mother.pdgCode()) == kPi0 || std::abs(mother.pdgCode()) == kGamma) { + + auto const& gmother = mother.template mothers_first_as(); + // cases to consider: eta->e, eta->pi0->e, eta->gamma->e, eta->pi0->gamma->e, pi0->e, pi0->gamma->e + + //================= eta->e ====================================== + if (std::abs(mother.pdgCode()) == kEtaLocal) { + + if (mother.isPhysicalPrimary()) { + if ((std::abs(gmother.pdgCode()) >= pdgCodeCharmMin && std::abs(gmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(gmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(gmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; + } + } + + //================= eta->pi0->e ====================================== + + if (std::abs(mother.pdgCode()) == kPi0) { + if (mother.isPhysicalPrimary()) { + if ((std::abs(gmother.pdgCode()) >= pdgCodeCharmMin && std::abs(gmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(gmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(gmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbPi0 = true; // pi0 -> e + } + if (std::abs(gmother.pdgCode()) == kEtaLocal) { + if (gmother.isPhysicalPrimary() || gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if ((std::abs(ggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(ggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(ggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(ggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; // eta->pi0-> e + } + } + } + + /// ==================================== eta->gamma->e and eta->pi0->gamma->e============ + if (std::abs(mother.pdgCode()) == kGamma) { + + if (std::abs(gmother.pdgCode()) == kEtaLocal) { + if (gmother.isPhysicalPrimary() || gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if ((std::abs(ggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(ggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(ggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(ggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; // eta->gamma-> e + } + } + if (std::abs(gmother.pdgCode()) == kPi0) { + if (gmother.isPhysicalPrimary() || gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if ((std::abs(ggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(ggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(ggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(ggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbPi0 = true; // pi0-> gamma-> e + } + if (gmother.has_mothers()) { + auto const& ggmother = gmother.template mothers_first_as(); + if (std::abs(ggmother.pdgCode()) == kEtaLocal) { + if (ggmother.isPhysicalPrimary() || ggmother.has_mothers()) { + auto const& gggmother = ggmother.template mothers_first_as(); + if ((std::abs(gggmother.pdgCode()) >= pdgCodeCharmMin && std::abs(gggmother.pdgCode()) < pdgCodeCharmMax) || + (std::abs(gggmother.pdgCode()) >= pdgCodeBeautyMin && std::abs(gggmother.pdgCode()) < pdgCodeBeautyMax)) { + continue; + } + isEmbEta = true; // eta->pi0->gamma-> e + } + } + } + } + } + if (!(isEmbPi0 && isEmbEta)) { + continue; + } + } + } + } + } + } nonHfe(track, tracks, false); ///////////////// NonHf electron Selection without Emcal //////////////////////// electronSel(track.collisionId(), track.globalIndex(), etaTrack, phiTrack, ptTrack, pTrack, trackRapidity, dcaxyTrack, dcazTrack, track.tpcNSigmaEl(), track.tofNSigmaEl(), diff --git a/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx b/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx index a5195d2eb24..28c2e834a43 100644 --- a/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx +++ b/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx @@ -63,7 +63,7 @@ struct HfTreeCreatorElectronDCA { Configurable etaRange{"etaRange", 0.5, "pseudorapidity range"}; Configurable pTMin{"pTMin", 0.5, "min pT"}; - Service pdg; + Service pdg{}; using TracksWExt = soa::Join; using TracksWExtMc = soa::Join; diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 2eac2ac28b6..925dc4e831d 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -34,6 +34,11 @@ o2physics_add_dpl_workflow(task-single-muon-mult PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-single-muon-mult-mc + SOURCES taskSingleMuonMultMc.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-single-muon-reader SOURCES taskSingleMuonReader.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index c3729516004..a172f752afc 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -25,6 +25,7 @@ #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Tools/KFparticle/KFUtilities.h" @@ -46,10 +47,12 @@ #include #include +#include #include #include +#include #include #include #include @@ -130,6 +133,8 @@ struct HfTaskElectronWeakBoson { // Centrality estimator configuration Configurable centralityEstimator{"centralityEstimator", CentralityEstimator::FT0M, "Centrality estimator. See CentralityEstimator for valid values."}; Configurable enableCentralityAnalysis{"enableCentralityAnalysis", true, "Enable centrality-dependent analysis"}; + Configurable enableMultiplicityPVAnalysis{"enableMultiplicityPVAnalysis", true, "Enable centrality-dependent analysis"}; + Configurable enableMultiplicityFT0MAnalysis{"enableMultiplicityFT0MAnalysis", true, "Enable centrality-dependent analysis"}; Configurable centralityMin{"centralityMin", -1, "minimum cut on centrality selection"}; Configurable centralityMax{"centralityMax", 101, "maximum cut on centrality selection"}; Configurable> centralityBins{"centralityBins", {0, 20, 60, 100}, "centrality bins"}; @@ -138,7 +143,12 @@ struct HfTaskElectronWeakBoson { Configurable enableZeeRecoQA{"enableZeeRecoQA", false, "Enable QA for Z->ee reconstruction"}; Configurable massZMinQA{"massZMinQA", 0.1, "minimum mass cut for Zee Reco QA"}; // CCDB service object - Service ccdb; + Service ccdb{}; + // UE + Configurable nRandomCones{"nRandomCones", 100, "number of random cones"}; + Configurable rcHardE{"rcHardE", 5.0, "hard cluster veto energy"}; + Configurable rcVetoR{"rcVetoR", 0.4, "veto radius"}; + Configurable useUEsub{"useUEsub", true, "apply UE subtraction in isolation"}; struct HfElectronCandidate { float pt, eta, phi, dcaxyTrk, dcazTrk, eop, energyIso, momIso; @@ -157,7 +167,7 @@ struct HfTaskElectronWeakBoson { : pt(ptr), eta(e), phi(ph), mass(m), ptchild0(ptzee0), ptchild1(ptzee1), charge(ch) {} }; std::vector reconstructedZ; - using CollisionsWithCent = soa::Join; + using CollisionsWithCent = soa::Join; using SelectedClusters = o2::aod::EMCALClusters; // PbPb // using TrackEle = o2::soa::Join; @@ -166,7 +176,7 @@ struct HfTaskElectronWeakBoson { // pp // using TrackEle = o2::soa::Filtered>; - Filter eventFilter = (applySel8 ? (o2::aod::evsel::sel8 == true) : (o2::aod::evsel::sel8 == o2::aod::evsel::sel8)); + Filter eventFilter = (applySel8 ? (o2::aod::evsel::sel8 == true) : (o2::aod::evsel::sel8 == o2::aod::evsel::sel8)); // FIXME: both sides of overloaded operator are equivalent Filter posZFilter = (nabs(o2::aod::collision::posZ) < vtxZ); Filter etafilter = (aod::track::eta < etaTrMax) && (aod::track::eta > etaTrMin); @@ -200,6 +210,8 @@ struct HfTaskElectronWeakBoson { ConfigurableAxis confaxisInvMassZgamma{"confaxisInvMassZgamma", {150, 0, 150}, "M_{ee} (GeV/c^{2})"}; ConfigurableAxis confaxisInvMassZ{"confaxisInvMassZ", {130, 20, 150}, "M_{ee} (GeV/c^{2})"}; ConfigurableAxis confaxisZfrag{"confaxisZfrag", {200, 0, 2.0}, "p_{T,h}/p_{T,Z}"}; + ConfigurableAxis confaxisMultPV{"confaxisMultPV", {200, 0, 200.0}, "multiplicity"}; + ConfigurableAxis confaxisMultFT0{"confaxisMultFT0", {1000, 0, 1000.0}, "multiplicity"}; // Histogram registry: an object to hold your registrygrams HistogramRegistry registry{"registry"}; @@ -208,6 +220,9 @@ struct HfTaskElectronWeakBoson { Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; + // defined rnd + TRandom3* rnd = nullptr; + void init(InitContext const&) { // Configure CCDB @@ -229,6 +244,9 @@ struct HfTaskElectronWeakBoson { // add configurable for CCDB path zorro.setBaseCCDBPath(cfgCCDBPath.value); + // init random + rnd = new TRandom3(0); + // define axes you want to use const AxisSpec axisZvtx{40, -20, 20, "Zvtx"}; const AxisSpec axisCounter{1, 0, 1, "events"}; @@ -281,12 +299,18 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisInvMassZgamma{confaxisInvMassZgamma, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisInvMassZ{confaxisInvMassZ, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisZfrag{confaxisZfrag, "p_{T,h}/p_{T,Z}"}; + const AxisSpec axisMultPV{confaxisMultPV, "multiplicity"}; + const AxisSpec axisMultFT0{confaxisMultFT0, "multiplicity"}; // create registrygrams registry.add("hZvtx", "Z vertex", kTH1D, {axisZvtx}); registry.add("hEventCounterInit", "hEventCounterInit", kTH1D, {axisCounter}); registry.add("hEventCounter", "hEventCounter", kTH1D, {axisCounter}); registry.add("hCentrality", "Centrality distribution", kTH1D, {axisCentrality}); + registry.add("hCentMultCorr", "Centrality distribution", kTH2D, {{axisCentrality}, {axisMultFT0}}); + registry.add("hMultPV", "multiplicity distribution for PV", kTH1D, {axisMultPV}); + registry.add("hMultFT0", "multiplicity distribution for FT0", kTH1D, {axisMultFT0}); + registry.add("hMultFT0PV", "multiplicity distribution", kTH2D, {{axisMultFT0}, {axisMultPV}}); registry.add("hITSchi2", "ITS #chi^{2}", kTH1F, {axisChi2}); registry.add("hTPCchi2", "TPC #chi^{2}", kTH1F, {axisChi2}); registry.add("hTPCnCls", "TPC NCls", kTH1F, {axisCluster}); @@ -320,12 +344,19 @@ struct HfTaskElectronWeakBoson { // hisotgram for EMCal trigger registry.add("hEMCalTrigger", "EMCal trigger", kTH1D, {axisTrigger}); + + // histogram for UE + registry.add("hRho", "rho UE density", kTH1F, {axisE}); + registry.add("hSumERC", "RC sumE", kTH1F, {axisE}); + registry.add("hEnergyUE", "UE vs. centrality", kTH2F, {{axisCentrality}, {axisE}}); } double getIsolatedCluster(const o2::aod::EMCALCluster& cluster, - const SelectedClusters& clusters) + const SelectedClusters& clusters, + float energyUE) { double energySum = 0.0; + double energySum_excl = 0.0; double isoEnergy = 10.0; double const etaAssCluster = cluster.eta(); double const phiAssCluster = cluster.phi(); @@ -346,11 +377,12 @@ struct HfTaskElectronWeakBoson { energySum += associateCluster.energy(); } } - + energySum_excl = energySum - cluster.energy(); if (energySum > 0) { - isoEnergy = energySum / cluster.energy() - 1.0; + isoEnergy = (energySum_excl - energyUE) / cluster.energy(); } + // LOG(info) <<"clustE = " << cluster.energy() << " ; energySum = " << energySum << " ; nclust in Cone = " << nclustSum - 1 << " ; UE = " << energyUE << " ; isoEnergy = " << isoEnergy; registry.fill(HIST("hIsolationEnergy"), cluster.energy(), isoEnergy); return (isoEnergy); @@ -387,6 +419,51 @@ struct HfTaskElectronWeakBoson { // LOG(info) << "isop = " << isoMomentum; return std::make_pair(trackCount - 1, isoMomentum); } + float estimateRhoRC(const SelectedClusters& clusters) + { + const float randomConeR = rIsolation; + const float randomConeArea = o2::constants::math::PI * randomConeR * randomConeR; + + std::vector sumErc; + sumErc.reserve(nRandomCones); + + for (int i = 0; i < nRandomCones; i++) { + + float etarc = rnd->Uniform(-etaEmcMax, etaEmcMax); // in EMCal acceptance + float phirc = rnd->Uniform(phiEmcMin, phiEmcMax); // in EMCal acceptance + + float energySumRC = 0; + + for (const auto& c : clusters) { + if (c.energy() > rcHardE) { + continue; + } + double dEtarc = etarc - c.eta(); + double dPhirc = phirc - c.phi(); + dPhirc = RecoDecay::constrainAngle(dPhirc, -o2::constants::math::PI); + double const deltaRrc = std::sqrt(dEtarc * dEtarc + dPhirc * dPhirc); + if (deltaRrc < randomConeR) { + energySumRC += c.energy(); + } + } + + registry.fill(HIST("hSumERC"), energySumRC); + sumErc.push_back(energySumRC); + } + + if (sumErc.empty()) { + return 0; + } + std::nth_element(sumErc.begin(), + sumErc.begin() + sumErc.size() / 2, + sumErc.end()); + + float median = sumErc[sumErc.size() / 2]; + // LOG(info) << "median = " << median; + registry.fill(HIST("hRho"), median / randomConeArea); + + return median / randomConeArea; + } void recoMassZee(const KFParticle& kfpIsoEle, int charge, @@ -442,7 +519,7 @@ struct HfTaskElectronWeakBoson { if (chiSqNdf > chiSqNdfMax) { continue; } - float massZee, massZeeErr; + float massZee{}, massZeeErr{}; zeeKF.GetMass(massZee, massZeeErr); registry.fill(HIST("hKfInvMassZee"), centrality, track.sign() * charge, kfpIsoEle.GetPt(), massZee); // LOG(info) << "Invarimass cal by KF particle mass = " << massZee; @@ -527,13 +604,39 @@ struct HfTaskElectronWeakBoson { float centrality = 1.0; if (enableCentralityAnalysis) { centrality = o2::hf_centrality::getCentralityColl(collision, centralityEstimator); - // LOG(info) << centrality; + // LOG(info) << "centrality = " << o2::hf_centrality::getCentralityColl(collision, centralityEstimator) << " ; FTC = " << collision.multFT0C(); if (centrality < centralityMin || centrality > centralityMax) { return; } - registry.fill(HIST("hCentrality"), centrality); + registry.fill(HIST("hCentMultCorr"), centrality, collision.multFT0M()); + } + + if (enableMultiplicityFT0MAnalysis || enableMultiplicityPVAnalysis) { + if (enableMultiplicityFT0MAnalysis) + centrality = collision.multFT0M(); + if (enableMultiplicityPVAnalysis) + centrality = collision.multNTracksPV(); + // LOG(info) << "raw mult PV = " << collision.multNTracksPV(); + // LOG(info) << "raw mult FT0M = " << collision.multFT0M(); + registry.fill(HIST("hMultPV"), collision.multNTracksPV()); + registry.fill(HIST("hMultFT0"), collision.multFT0M()); + registry.fill(HIST("hMultFT0PV"), collision.multFT0M(), collision.multNTracksPV()); + } + + registry.fill(HIST("hCentrality"), centrality); + + // UE estimate + float rho = 0.f; + float energyUE = 0.f; + + if (useUEsub) { + rho = estimateRhoRC(emcClusters); + energyUE = rho * static_cast(o2::constants::math::PI * rIsolation * rIsolation); + registry.fill(HIST("hEnergyUE"), centrality, energyUE); + // LOG(info) << "UE = " << energyUE; } + // track loop for (const auto& track : tracks) { if (std::abs(track.eta()) > etaTrMax) { @@ -568,7 +671,7 @@ struct HfTaskElectronWeakBoson { registry.fill(HIST("hTPCNsigma"), track.p(), track.tpcNSigmaEl()); float eop = -0.01; - float isoEnergy = 1.0; + float isoEnergy = 99.0; // track isolation auto [trackCount, isoMomentum] = getIsolatedTrack(track.eta(), track.phi(), track.p(), tracks); // LOG(info) << "isoMomentum = " << isoMomentum; @@ -657,7 +760,7 @@ struct HfTaskElectronWeakBoson { eop = energyEmc / match.track_as().p(); // LOG(info) << "eop = " << eop; - isoEnergy = getIsolatedCluster(cluster, emcClusters); + isoEnergy = getIsolatedCluster(cluster, emcClusters, energyUE); if (match.track_as().pt() > ptTHnThresh && isTHnElectron) { registry.fill(HIST("hTHnElectrons"), match.track_as().pt(), match.track_as().tpcNSigmaEl(), m02Emc, eop, isoEnergy, isoMomentum, trackCount, track.eta(), track.tpcSignal()); diff --git a/PWGHF/HFL/Tasks/taskSingleElectron.cxx b/PWGHF/HFL/Tasks/taskSingleElectron.cxx index 6c4d1f76833..c519765e688 100644 --- a/PWGHF/HFL/Tasks/taskSingleElectron.cxx +++ b/PWGHF/HFL/Tasks/taskSingleElectron.cxx @@ -11,7 +11,7 @@ /// /// \file taskSingleElectron.cxx /// \brief task for electrons from heavy-flavour hadron decays -/// \author Jonghan Park (Jeonbuk National University) +/// \author Jonghan Park (Jeonbuk National University), Seul I Jeong (Pusan National University) #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -41,12 +40,6 @@ using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; -enum PdgCode { - kEta = 221, - kOmega = 223, - kEtaPrime = 331 -}; - enum SourceType { NotElec = 0, // not electron DirectCharm = 1, // electrons from prompt charm hadrons @@ -88,20 +81,23 @@ struct HfTaskSingleElectron { Configurable ptTrackMax{"ptTrackMax", 10., "max pt cut"}; Configurable ptTrackMin{"ptTrackMin", 0.5, "min pt cut"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "eta cut"}; - Configurable tpcNCrossedRowMin{"tpcNCrossedRowMin", 70, "max of TPC n cluster crossed rows"}; - Configurable tpcNClsFoundOverFindableMin{"tpcNClsFoundOverFindableMin", 0.8, "min # of TPC found/findable clusters"}; - Configurable tpcChi2perNClMax{"tpcChi2perNClMax", 4., "min # of tpc chi2 per clusters"}; - Configurable itsIBClsMin{"itsIBClsMin", 3, "min # of its clusters in IB"}; - Configurable itsChi2perNClMax{"itsChi2perNClMax", 6., "min # of tpc chi2 per clusters"}; + Configurable nCrossedRowTPCMin{"nCrossedRowTPCMin", 70, "max of TPC n cluster crossed rows"}; + Configurable nClsFoundOverFindableTpcMin{"nClsFoundOverFindableTpcMin", 0.8, "min # of TPC found/findable clusters"}; + Configurable Chi2pernClTpcMax{"Chi2pernClTpcMax", 4., "min # of tpc chi2 per clusters"}; + Configurable ClsIBItsMin{"ClsIBItsMin", 3, "min # of its clusters in IB"}; + Configurable Chi2pernClItsMax{"Chi2pernClItsMax", 6., "min # of tpc chi2 per clusters"}; Configurable dcaxyMax{"dcaxyMax", 1., "max of track dca in xy"}; Configurable dcazMax{"dcazMax", 2., "max of track dca in z"}; - Configurable tofNSigmaMax{"tofNSigmaMax", 3., "max of tof nsigma"}; - Configurable tpcNSigmaMin{"tpcNSigmaMin", -1., "min of tpc nsigma"}; - Configurable tpcNSigmaMax{"tpcNSigmaMax", 3., "max of tpc nsigma"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 3., "max of tof nsigma"}; + Configurable nSigmaTpcMin{"nSigmaTpcMin", -1., "min of tpc nsigma"}; + Configurable nSigmaTPCMax{"nSigmaTPCMax", 3., "max of tpc nsigma"}; Configurable nBinsP{"nBinsP", 1500, "number of bins of particle momentum"}; Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histo"}; + Configurable nSigmaTpcHadronMax{"nSigmaTpcHadronMax", -3, "max of tpc hadron nsigma"}; + Configurable nSigmaTpcHadronMin{"nSigmaTpcHadronMin", -5, "min of tpc hadron nsigma"}; + // SliceCache SliceCache cache; @@ -119,7 +115,7 @@ struct HfTaskSingleElectron { ConfigurableAxis axisPtEl{"axisPtEl", {VARIABLE_WIDTH, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.75f, 2.0f, 2.25f, 2.5f, 2.75f, 3.f, 3.5f, 4.0f, 5.0f, 6.0f, 8.0f, 10.0f}, "electron pt bins"}; // Histogram registry - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histos{"histos"}; void init(InitContext const&) { @@ -134,35 +130,36 @@ struct HfTaskSingleElectron { const AxisSpec axisTrackIp{4000, -0.2, 0.2, "dca"}; // create histograms - histos.add("nEvents", "Number of events", kTH1D, {{1, 0., 1.}}); - histos.add("VtxZ", "VtxZ; cm; entries", kTH1D, {axisPosZ}); - histos.add("etaTrack", "etaTrack; #eta; entries", kTH1D, {axisEta}); - histos.add("ptTrack", "#it{p}_{T} distribution of selected tracks; #it{p}_{T} (GeV/#it{c}); entries", kTH1D, {axisPt}); + histos.add("hNEvents", "Number of events", kTH1D, {{1, 0., 1.}}); + histos.add("hVtxZ", "hVtxZ; cm; entries", kTH1D, {axisPosZ}); + histos.add("hEtaTrack", "hEtaTrack; #eta; entries", kTH1D, {axisEta}); + histos.add("hPtTrack", "#it{p}_{T} distribution of selected tracks; #it{p}_{T} (GeV/#it{c}); entries", kTH1D, {axisPt}); // QA plots for trigger track selection - histos.add("tpcNClsTrack", "tpcNClsTrack", kTH1D, {{200, 0, 200}}); - histos.add("tpcFoundFindableTrack", "", kTH1D, {{10, 0, 1}}); - histos.add("tpcChi2Track", "", kTH1D, {{100, 0, 10}}); - histos.add("itsIBClsTrack", "", kTH1D, {{10, 0, 10}}); - histos.add("itsChi2Track", "", kTH1D, {{50, 0, 50}}); - histos.add("dcaXYTrack", "", kTH1D, {{600, -3, 3}}); - histos.add("dcaZTrack", "", kTH1D, {{600, -3, 3}}); + histos.add("hNClsTpcTrack", "hNClsTpcTrack", kTH1D, {{200, 0, 200}}); + histos.add("hNClsFoundFindableTpcTrack", "", kTH1D, {{10, 0, 1}}); + histos.add("hChi2TpcTrack", "", kTH1D, {{100, 0, 10}}); + histos.add("hibClsItsTrack", "", kTH1D, {{10, 0, 10}}); + histos.add("hChi2ItsTrack", "", kTH1D, {{50, 0, 50}}); + histos.add("hDcaXYTrack", "", kTH1D, {{600, -3, 3}}); + histos.add("hDcaZTrack", "", kTH1D, {{600, -3, 3}}); // pid - histos.add("tofNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("tofNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("tpcNSigP", "", kTH2D, {{axisP}, {axisNsig}}); - histos.add("tpcNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("tpcNSigPAfterTofCut", "", kTH2D, {{axisP}, {axisNsig}}); - histos.add("tpcNSigPtAfterTofCut", "", kTH2D, {{axisPtEl}, {axisNsig}}); - histos.add("tpcNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTofNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTofNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTPCNSigP", "", kTH2D, {{axisP}, {axisNsig}}); + histos.add("hTPCNSigPt", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTPCNSigPAfterTofCut", "", kTH2D, {{axisP}, {axisNsig}}); + histos.add("hTPCNSigPtAfterTofCut", "", kTH2D, {{axisPtEl}, {axisNsig}}); + histos.add("hTPCNSigPtQA", "", kTH2D, {{axisPtEl}, {axisNsig}}); // track impact parameter - histos.add("dcaTrack", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); - histos.add("dcaBeauty", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); - histos.add("dcaCharm", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); - histos.add("dcaDalitz", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); - histos.add("dcaConv", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaTrack", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaBeauty", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaChram", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaDalitz", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaConv", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); + histos.add("hDcaHadron", "", kTH2D, {{axisPtEl}, {axisTrackIp}}); // QA plots for MC histos.add("hPdgC", "", kTH1D, {{10001, -0.5, 10000.5}}); @@ -181,23 +178,23 @@ struct HfTaskSingleElectron { return false; } - if (track.tpcNClsCrossedRows() < tpcNCrossedRowMin) { + if (track.tpcNClsCrossedRows() < nCrossedRowTPCMin) { return false; } - if (track.tpcCrossedRowsOverFindableCls() < tpcNClsFoundOverFindableMin) { + if (track.tpcCrossedRowsOverFindableCls() < nClsFoundOverFindableTpcMin) { return false; } - if (track.tpcChi2NCl() > tpcChi2perNClMax) { + if (track.tpcChi2NCl() > Chi2pernClTpcMax) { return false; } - if (!(track.itsNClsInnerBarrel() == itsIBClsMin)) { + if (!(track.itsNClsInnerBarrel() == ClsIBItsMin)) { return false; } - if (track.itsChi2NCl() > itsChi2perNClMax) { + if (track.itsChi2NCl() > Chi2pernClItsMax) { return false; } @@ -279,16 +276,16 @@ struct HfTaskSingleElectron { if (grmotherPdg == kPi0) { return GammaPi0; } - if (grmotherPdg == PdgCode::kEta) { + if (grmotherPdg == Pdg::kEta) { return GammaEta; } - if (grmotherPdg == PdgCode::kOmega) { + if (grmotherPdg == Pdg::kOmega) { return GammaOmega; } - if (grmotherPdg == kPhi) { + if (grmotherPdg == Pdg::kPhi) { return GammaPhi; } - if (grmotherPdg == PdgCode::kEtaPrime) { + if (grmotherPdg == Pdg::kEtaPrime) { return GammaEtaPrime; } if (grmotherPdg == kRho770_0) { @@ -320,22 +317,22 @@ struct HfTaskSingleElectron { mpt = grmotherPt; return GammaPi0; } - if (grmotherPdg == PdgCode::kEta) { + if (grmotherPdg == Pdg::kEta) { mpdg = grmotherPdg; mpt = grmotherPt; return GammaEta; } - if (grmotherPdg == PdgCode::kOmega) { + if (grmotherPdg == Pdg::kOmega) { mpdg = grmotherPdg; mpt = grmotherPt; return GammaOmega; } - if (grmotherPdg == kPhi) { + if (grmotherPdg == Pdg::kPhi) { mpdg = grmotherPdg; mpt = grmotherPt; return GammaPhi; } - if (grmotherPdg == PdgCode::kEtaPrime) { + if (grmotherPdg == Pdg::kEtaPrime) { mpdg = grmotherPdg; mpt = grmotherPt; return GammaEtaPrime; @@ -355,10 +352,10 @@ struct HfTaskSingleElectron { if (grmothersIdsVec.empty()) { static const std::map pdgToSource = { {kPi0, Pi0}, - {PdgCode::kEta, Eta}, - {PdgCode::kOmega, Omega}, - {kPhi, Phi}, - {PdgCode::kEtaPrime, EtaPrime}, + {Pdg::kEta, Eta}, + {Pdg::kOmega, Omega}, + {Pdg::kPhi, Phi}, + {Pdg::kEtaPrime, EtaPrime}, {kRho770_0, Rho0}, {kKPlus, Ke3}, {kK0Long, K0l}}; @@ -393,16 +390,16 @@ struct HfTaskSingleElectron { mpdg = motherPdg; return Pi0; } - if (motherPdg == PdgCode::kEta) { + if (motherPdg == Pdg::kEta) { return Eta; } - if (motherPdg == PdgCode::kOmega) { + if (motherPdg == Pdg::kOmega) { return Omega; } - if (motherPdg == kPhi) { + if (motherPdg == Pdg::kPhi) { return Phi; } - if (motherPdg == PdgCode::kEtaPrime) { + if (motherPdg == Pdg::kEtaPrime) { return EtaPrime; } if (motherPdg == kRho770_0) { @@ -434,8 +431,8 @@ struct HfTaskSingleElectron { return; } - histos.fill(HIST("VtxZ"), collision.posZ()); - histos.fill(HIST("nEvents"), flagAnalysedEvt); + histos.fill(HIST("hVtxZ"), collision.posZ()); + histos.fill(HIST("hNEvents"), flagAnalysedEvt); for (const auto& track : tracks) { @@ -447,34 +444,40 @@ struct HfTaskSingleElectron { continue; } - histos.fill(HIST("etaTrack"), track.eta()); - histos.fill(HIST("ptTrack"), track.pt()); + histos.fill(HIST("hEtaTrack"), track.eta()); + histos.fill(HIST("hPtTrack"), track.pt()); - histos.fill(HIST("tpcNClsTrack"), track.tpcNClsCrossedRows()); - histos.fill(HIST("tpcFoundFindableTrack"), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("tpcChi2Track"), track.tpcChi2NCl()); - histos.fill(HIST("itsIBClsTrack"), track.itsNClsInnerBarrel()); - histos.fill(HIST("itsChi2Track"), track.itsChi2NCl()); - histos.fill(HIST("dcaXYTrack"), track.dcaXY()); - histos.fill(HIST("dcaZTrack"), track.dcaZ()); + histos.fill(HIST("hNClsTpcTrack"), track.tpcNClsCrossedRows()); + histos.fill(HIST("hNClsFoundFindableTpcTrack"), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hChi2TpcTrack"), track.tpcChi2NCl()); + histos.fill(HIST("hibClsItsTrack"), track.itsNClsInnerBarrel()); + histos.fill(HIST("hChi2ItsTrack"), track.itsChi2NCl()); + histos.fill(HIST("hDcaXYTrack"), track.dcaXY()); + histos.fill(HIST("hDcaZTrack"), track.dcaZ()); - histos.fill(HIST("tofNSigPt"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("tpcNSigP"), track.p(), track.tpcNSigmaEl()); - histos.fill(HIST("tpcNSigPt"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTofNSigPt"), track.pt(), track.tofNSigmaEl()); + histos.fill(HIST("hTPCNSigP"), track.p(), track.tpcNSigmaEl()); + histos.fill(HIST("hTPCNSigPt"), track.pt(), track.tpcNSigmaEl()); - if (std::abs(track.tofNSigmaEl()) > tofNSigmaMax) { + if (std::abs(track.tofNSigmaEl()) > nSigmaTofMax) { continue; } - histos.fill(HIST("tofNSigPtQA"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("tpcNSigPAfterTofCut"), track.p(), track.tpcNSigmaEl()); - histos.fill(HIST("tpcNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTofNSigPtQA"), track.pt(), track.tofNSigmaEl()); + histos.fill(HIST("hTPCNSigPAfterTofCut"), track.p(), track.tpcNSigmaEl()); + histos.fill(HIST("hTPCNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); - if (track.tpcNSigmaEl() < tpcNSigmaMin || track.tpcNSigmaEl() > tpcNSigmaMax) { + if (track.tpcNSigmaEl() < nSigmaTpcMin || track.tpcNSigmaEl() > nSigmaTPCMax) { continue; } - histos.fill(HIST("tpcNSigPtQA"), track.pt(), track.tpcNSigmaEl()); - histos.fill(HIST("dcaTrack"), track.pt(), track.dcaXY()); + if (track.tpcNSigmaEl() < nSigmaTpcHadronMax && track.tpcNSigmaEl() > nSigmaTpcHadronMin) { + + histos.fill(HIST("hDcaHadron"), track.pt(), track.dcaXY()); + } + + histos.fill(HIST("hTPCNSigPtQA"), track.pt(), track.tpcNSigmaEl()); + + histos.fill(HIST("hDcaTrack"), track.pt(), track.dcaXY()); } } PROCESS_SWITCH(HfTaskSingleElectron, processData, "For real data", true); @@ -493,8 +496,8 @@ struct HfTaskSingleElectron { return; } - histos.fill(HIST("VtxZ"), collision.posZ()); - histos.fill(HIST("nEvents"), flagAnalysedEvt); + histos.fill(HIST("hVtxZ"), collision.posZ()); + histos.fill(HIST("hNEvents"), flagAnalysedEvt); for (const auto& track : tracks) { @@ -502,55 +505,58 @@ struct HfTaskSingleElectron { continue; } - histos.fill(HIST("etaTrack"), track.eta()); - histos.fill(HIST("ptTrack"), track.pt()); + histos.fill(HIST("hEtaTrack"), track.eta()); + histos.fill(HIST("hPtTrack"), track.pt()); - histos.fill(HIST("tpcNClsTrack"), track.tpcNClsCrossedRows()); - histos.fill(HIST("tpcFoundFindableTrack"), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("tpcChi2Track"), track.tpcChi2NCl()); - histos.fill(HIST("itsIBClsTrack"), track.itsNClsInnerBarrel()); - histos.fill(HIST("dcaXYTrack"), track.dcaXY()); - histos.fill(HIST("dcaZTrack"), track.dcaZ()); + histos.fill(HIST("hNClsTpcTrack"), track.tpcNClsCrossedRows()); + histos.fill(HIST("hNClsFoundFindableTpcTrack"), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hChi2TpcTrack"), track.tpcChi2NCl()); + histos.fill(HIST("hibClsItsTrack"), track.itsNClsInnerBarrel()); + histos.fill(HIST("hDcaXYTrack"), track.dcaXY()); + histos.fill(HIST("hDcaZTrack"), track.dcaZ()); - histos.fill(HIST("tofNSigPt"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("tpcNSigPt"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTofNSigPt"), track.pt(), track.tofNSigmaEl()); + histos.fill(HIST("hTPCNSigPt"), track.pt(), track.tpcNSigmaEl()); - int mpdg; // electron source pdg code - double mpt; // electron source pt + int mpdg{}; // electron source pdg code + double mpt{}; // electron source pt int const source = getElecSource(track, mpt, mpdg); if (source == DirectBeauty || source == BeautyCharm) { histos.fill(HIST("hPdgB"), mpdg); - histos.fill(HIST("dcaBeauty"), track.pt(), track.dcaXY()); + histos.fill(HIST("hDcaBeauty"), track.pt(), track.dcaXY()); } if (source == DirectCharm) { histos.fill(HIST("hPdgC"), mpdg); - histos.fill(HIST("dcaCharm"), track.pt(), track.dcaXY()); + histos.fill(HIST("hDcaChram"), track.pt(), track.dcaXY()); } if (source >= GammaPi0 && source <= GammaSigma) { histos.fill(HIST("hPdgCo"), mpdg); - histos.fill(HIST("dcaConv"), track.pt(), track.dcaXY()); + histos.fill(HIST("hDcaConv"), track.pt(), track.dcaXY()); } if (source >= Pi0 && source <= Sigma) { histos.fill(HIST("hPdgDa"), mpdg); - histos.fill(HIST("dcaDalitz"), track.pt(), track.dcaXY()); + histos.fill(HIST("hDcaDalitz"), track.pt(), track.dcaXY()); } - if (std::abs(track.tofNSigmaEl()) > tofNSigmaMax) { + if (track.tpcNSigmaEl() < nSigmaTpcHadronMax && track.tpcNSigmaEl() > nSigmaTpcHadronMin) + histos.fill(HIST("hDcaHadron"), track.pt(), track.dcaXY()); + + if (std::abs(track.tofNSigmaEl()) > nSigmaTofMax) { continue; } - histos.fill(HIST("tofNSigPtQA"), track.pt(), track.tofNSigmaEl()); - histos.fill(HIST("tpcNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTofNSigPtQA"), track.pt(), track.tofNSigmaEl()); + histos.fill(HIST("hTPCNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); - if (track.tpcNSigmaEl() < tpcNSigmaMin || track.tpcNSigmaEl() > tpcNSigmaMax) { + if (track.tpcNSigmaEl() < nSigmaTpcMin || track.tpcNSigmaEl() > nSigmaTPCMax) { continue; } - histos.fill(HIST("tpcNSigPtQA"), track.pt(), track.tpcNSigmaEl()); + histos.fill(HIST("hTPCNSigPtQA"), track.pt(), track.tpcNSigmaEl()); - histos.fill(HIST("dcaTrack"), track.pt(), track.dcaXY()); + histos.fill(HIST("hDcaTrack"), track.pt(), track.dcaXY()); } } PROCESS_SWITCH(HfTaskSingleElectron, processMc, "For real data", false); diff --git a/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx b/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx index f755dfac5e2..39f0d7a29dc 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx @@ -71,6 +71,7 @@ struct HfTaskSingleMuonMult { Configurable rAbsorbMin{"rAbsorbMin", 17.6, "R at absorber end minimum value"}; Configurable rAbsorbMax{"rAbsorbMax", 89.5, "R at absorber end maximum value"}; Configurable rAbsorbMid{"rAbsorbMid", 26.5, "R at absorber end split point for different p*DCA selections"}; + Configurable chi2Max{"chi2Max", 1e6f, "MCH-MFT matching chi2 maximum value"}; Configurable reduceOrphMft{"reduceOrphMft", true, "reduce orphan MFT tracks"}; using MyCollisions = soa::Join; @@ -95,7 +96,7 @@ struct HfTaskSingleMuonMult { AxisSpec const axisNCh{500, 0.5, 500.5, "#it{N}_{ch}"}; AxisSpec const axisNMu{20, -0.5, 19.5, "#it{N}_{#mu}"}; AxisSpec const axisPt{1000, 0., 500., "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec const axisEta{250, -5., 5., "#it{#eta}"}; + AxisSpec const axisEta{1000, -5., 5., "#it{#eta}"}; AxisSpec const axisTheta{500, 170., 180., "#it{#theta}"}; AxisSpec const axisRAbsorb{1000, 0., 100., "#it{R}_{Absorb} (cm)"}; AxisSpec const axisDCA{500, 0., 5., "#it{DCA}_{xy} (cm)"}; @@ -118,13 +119,13 @@ struct HfTaskSingleMuonMult { registry.add("hMuBeforeMatchMFT", "Muon information before any Kinemeatic cuts applied", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("hMuBeforeAccCuts", "Muon information before applying Acceptance cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("h3DCABeforeAccCuts", "DCAx,DCAy,DCAz information before Acceptance cuts", {HistType::kTH3F, {axisDCAx, axisDCAx, axisTrackType}}); - registry.add("hMuDeltaPtBeforeAccCuts", "Muon information with DeltaPt before applying Acceptance cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisDeltaPt}, 10}); + registry.add("hMuDeltaPtBeforeAccCuts", "Muon information with DeltaPt before applying Acceptance cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDeltaPt, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("hMuAfterEtaCuts", "Muon information after applying Eta cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("hMuAfterRAbsorbCuts", "Muon information after applying RAbsorb cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("hMuAfterPdcaCuts", "Muon information after applying Pdca cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("hMuAfterAccCuts", "Muon information after applying all Kinematic cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("h3DCAAfterAccCuts", "DCAx,DCAy,DCAz information after Acceptance cuts", {HistType::kTH3F, {axisDCAx, axisDCAx, axisTrackType}}); - registry.add("hMuDeltaPtAfterAccCuts", "Muon information with DeltaPt after applying Acceptance cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDCA, axisPDca, axisChi2MatchMCHMFT, axisDeltaPt}, 10}); + registry.add("hMuDeltaPtAfterAccCuts", "Muon information with DeltaPt after applying Acceptance cuts", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisTheta, axisRAbsorb, axisDeltaPt, axisPDca, axisChi2MatchMCHMFT, axisTrackType}, 10}); registry.add("hTHnTrk", "Muon information with multiplicity", {HistType::kTHnSparseF, {axisCent, axisNCh, axisPt, axisEta, axisSign}, 5}); registry.add("h3MultNchNmu", "Number of muons and multiplicity", {HistType::kTH3F, {axisCent, axisNCh, axisNMu}}); @@ -192,6 +193,7 @@ struct HfTaskSingleMuonMult { const auto pt{muon.pt()}, eta{muon.eta()}, theta{90.0f - ((std::atan(muon.tgl())) * constants::math::Rad2Deg)}, pDca{muon.pDca()}, rAbsorb{muon.rAtAbsorberEnd()}, chi2{muon.chi2MatchMCHMFT()}; const auto dcaXY{RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())}; const auto muTrackType{muon.trackType()}; + float dptBefore{0.}, dptAfter{0.}; registry.fill(HIST("hMuBeforeMatchMFT"), cent, nCh, pt, eta, theta, rAbsorb, dcaXY, pDca, chi2, muTrackType); @@ -202,11 +204,9 @@ struct HfTaskSingleMuonMult { if (muon.has_matchMCHTrack()) { auto muonType3 = muon.template matchMCHTrack_as(); - auto dpt = muonType3.pt() - pt; - if (muTrackType == ForwardTrackTypeEnum::GlobalMuonTrack) { - registry.fill(HIST("hMuDeltaPtBeforeAccCuts"), cent, nCh, pt, eta, theta, rAbsorb, dcaXY, pDca, chi2, dpt); - } + dptBefore = muonType3.pt() - pt; } + registry.fill(HIST("hMuDeltaPtBeforeAccCuts"), cent, nCh, pt, eta, theta, rAbsorb, dptBefore, pDca, chi2, muTrackType); // Apply various standard muon acceptance cuts // eta cuts @@ -233,7 +233,7 @@ struct HfTaskSingleMuonMult { registry.fill(HIST("hMuAfterPdcaCuts"), cent, nCh, pt, eta, theta, rAbsorb, dcaXY, pDca, chi2, muTrackType); // MCH-MFT matching chi2 - if (muon.chi2() >= 1e6) { + if (muon.chi2() >= chi2Max) { continue; } registry.fill(HIST("hMuonSel"), Chi2Cut); @@ -241,17 +241,15 @@ struct HfTaskSingleMuonMult { // histograms after acceptance cuts registry.fill(HIST("hMuAfterAccCuts"), cent, nCh, pt, eta, theta, rAbsorb, dcaXY, pDca, chi2, muTrackType); registry.fill(HIST("h3DCAAfterAccCuts"), muon.fwdDcaX(), muon.fwdDcaY(), muTrackType); - nMu++; - nMuType[muTrackType]++; if (muon.has_matchMCHTrack()) { auto muonType3 = muon.template matchMCHTrack_as(); - auto dpt = muonType3.pt() - pt; - - if (muTrackType == ForwardTrackTypeEnum::GlobalMuonTrack) { - registry.fill(HIST("hMuDeltaPtAfterAccCuts"), cent, nCh, pt, eta, theta, rAbsorb, dcaXY, pDca, chi2, dpt); - } + dptAfter = muonType3.pt() - pt; } + registry.fill(HIST("hMuDeltaPtAfterAccCuts"), cent, nCh, pt, eta, theta, rAbsorb, dptAfter, pDca, chi2, muTrackType); + + nMu++; + nMuType[muTrackType]++; } registry.fill(HIST("h3MultNchNmu"), cent, nCh, nMu); diff --git a/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx b/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx new file mode 100644 index 00000000000..29ffc66229b --- /dev/null +++ b/PWGHF/HFL/Tasks/taskSingleMuonMultMc.cxx @@ -0,0 +1,552 @@ +// 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 taskSingleMuonMultMc.cxx +/// \brief Task used to identify various sources of single muons and to calculated Axe in Monte Carlo simulation. +/// \author Md Samsul Islam , IITB + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::fwdtrack; + +// Minimum PDG charge (in units of 1/3 e) +auto static constexpr ChargeMin = 3.f; + +namespace +{ +enum ParticleType { + IsIdentified = 0, // this particle is identified + IsMuon, // this is a muon + IsSecondary, // this is a secondary particle + HasTauParent, // this particle has a tau parent + HasWParent, // this particle has a W parent + HasZParent, // this particle has a Z parent + HasLightParent, // this particle has a light flavor parent + HasQuarkoniumParent, // this particle has a quarkonium parent + HasCharmParent, // this particle has a charm parent + HasBeautyParent // this particle has a beauty parent +}; +} // namespace + +struct HfTaskSingleMuonMultMc { + SliceCache cache; + Preslice perCol = aod::track::collisionId; + Preslice perMcCol = aod::mcparticle::mcCollisionId; + o2::framework::Service pdg; + + Configurable mcMaskSelection{"mcMaskSelection", 0, "McMask for correct match, valid values are 0 and 128"}; + Configurable pdgQuark{"pdgQuark", 10, "pdg Max for Quarks"}; + Configurable pdgRemMin{"pdgRemMin", 100, " Min. pdg Remnant for calculating Hadron pdg"}; + Configurable pdgRemMax{"pdgRemMax", 10000, "Max. pdg Remnant for calculating Hadron pdg"}; + Configurable flvMin{"flvMin", 4, "Min flavor of constituent quark"}; + Configurable flvMax{"flvMax", 6, "Max flavor of constituent quark"}; + Configurable flvLeading{"flvLeading", 10, "Base to extract leading flavor of constituent quark"}; + + Configurable charge{"charge", -1, "Muon track charge, validated values are 0, 1 and -1, 0 represents both 1 and -1"}; + Configurable zVtxMax{"zVtxMax", 10., "maxium z of primary vertex [cm]"}; + Configurable ptTrackMin{"ptTrackMin", 0.15, "minimum pt of tracks"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "maximum pseudorapidity of tracks"}; + Configurable etaMin{"etaMin", -3.6, "minimum pseudorapidity"}; + Configurable etaMax{"etaMax", -2.5, "maximum pseudorapidity"}; + Configurable pDcaMin{"pDcaMin", 324., "p*DCA value for small RAbsorb"}; + Configurable pDcaMax{"pDcaMax", 594., "p*DCA value for large RAbsorb"}; + Configurable rAbsorbMin{"rAbsorbMin", 17.6, "R at absorber end minimum value"}; + Configurable rAbsorbMax{"rAbsorbMax", 89.5, "R at absorber end maximum value"}; + Configurable rAbsorbMid{"rAbsorbMid", 26.5, "R at absorber end split point for different p*DCA selections"}; + + using MyCollisions = soa::Join; + using McMuons = soa::Join; + using MyTracks = soa::Filtered>; + using McGenCollisions = soa::Join; + using McRecCollisions = soa::SmallGroups>; + + // Filter Global Track for Multiplicty + Filter trackFilter = ((nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin)); + + HistogramRegistry registry{ + "registry", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + void init(InitContext&) + { + const TString muonSources[]{ + "Identified", + "Muon", + "SecondaryMu", + "LightDecayMu", + "TauDecayMu", + "WBosonDecayMu", + "ZBosonDecayMu", + "QuarkoniumDecayMu", + "BeautyMu", + "BeautyDecayMu", + "NonpromptCharmMu", + "PromptCharmMu", + "OtherMu", + "Hadron", + "Unidentified"}; + + AxisSpec axisColNumber{1, 0.5, 1.5, "Selected collisions"}; + AxisSpec axisMcMask{1001, -500.5, 500.5, "Mc Mask Selection"}; + AxisSpec axisMcLabel{1001, -500.5, 500.5, "McLabel"}; + AxisSpec axisNCh{500, 0.5, 500.5, "#it{N}_{ch}"}; + AxisSpec axisNtrk{500, 0.5, 500.5, "#it{N}_{trk}"}; + AxisSpec axisPt{5000, 0., 500., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{1000, -5., 5., "#it{#eta}"}; + AxisSpec axisRAbsorb{1000, 0., 100., "#it{R}_{Absorb} (cm)"}; + AxisSpec axisDCA{500, 0., 5., "#it{DCA}_{xy} (cm)"}; + AxisSpec axisChi2{1000, 0., 1000., "MCH-MFT matching #chi^{2}"}; + AxisSpec axisPDca{100000, 0, 100000, "#it{p} #times DCA (GeV/#it{c} * cm)"}; + AxisSpec axisDeltaPt{10000, -50, 50, "#Delta #it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisTrackType{8, -1.5, 6.5, "TrackType"}; + AxisSpec axisZ{1000, -50, 50, "V_{z} axis"}; + AxisSpec axisCharge{21, -10.5, 10.5, "charge"}; + AxisSpec axisPDG{201, -100.5, 100.5, "PDG"}; + AxisSpec axisMuonMask{15, -0.5, 14.5, "MuonMask"}; + + HistogramConfigSpec hNEventGen{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hNEventRec{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hParticleGen{HistType::kTHnSparseF, {axisPt, axisEta}}; + HistogramConfigSpec hParticleRec{HistType::kTHnSparseF, {axisPt, axisEta}}; + HistogramConfigSpec hTrackResponse{HistType::kTH2F, {axisNCh, axisNtrk}}; + + HistogramConfigSpec hMcMask{HistType::kTH1F, {axisMcMask}}; + HistogramConfigSpec hMuMcLabel{HistType::kTH1F, {axisMcLabel}}; + HistogramConfigSpec hMuTrackType{HistType::kTH1F, {axisTrackType}}; + HistogramConfigSpec hNEventGenMu{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hNEventRecMu{HistType::kTH1F, {axisColNumber}}; + HistogramConfigSpec hGenMuVar{HistType::kTHnSparseF, {axisPDG, axisPt, axisEta}}; + HistogramConfigSpec hRecMuVar{HistType::kTHnSparseF, {axisPDG, axisPt, axisEta}}; + HistogramConfigSpec hMuAfterAccCuts{HistType::kTHnSparseF, {axisPDG, axisPt, axisEta, axisRAbsorb, axisDCA, axisPDca, axisChi2, axisTrackType}}; + + registry.add("hNEventRec", "", hNEventRec); + registry.add("hNEventGen", "", hNEventGen); + registry.add("hParticleGen", "Generated particles ", hParticleGen); + registry.add("hParticleRec", "Reconstructed particles", hParticleRec); + registry.add("hTrackResponse", "Generation-Recontsruction Response", hTrackResponse); + + registry.add("hMcMask", "Muon mcMask", hMcMask); + registry.add("hMuMcLabel", "Muon mcLabel", hMuMcLabel); + registry.add("hMuTrackType", "PDG code", hMuTrackType); + registry.add("hNEventGenMu", "Muon Generated", hNEventGenMu); + registry.add("hNEventRecMu", "Muon Reconstruced", hNEventRecMu); + registry.add("hGenMuVar", "Muon Generated Variables", hGenMuVar); + registry.add("hRecMuVar", "Muon Reconstructed Variables", hRecMuVar); + registry.add("hMuAfterAccCuts", "Muon Reconstructed Variables", hMuAfterAccCuts); + + for (const auto& src : muonSources) { + registry.add(Form("h2%s", src.Data()), "", {HistType::kTH2F, {axisPt, axisEta}}); + } + } + + // get the bitmask for muon sources identification + uint16_t getMask(const McMuons::iterator& muon) + { + uint16_t mask(0); + if (!muon.has_mcParticle()) { + return mask; + } + SETBIT(mask, IsIdentified); + + auto mcPart(muon.mcParticle()); + if (std::abs(mcPart.pdgCode()) != kMuonMinus) { + return mask; + } + SETBIT(mask, IsMuon); + + while (mcPart.has_mothers()) { + mcPart = *(mcPart.mothers_first_as()); + const int pdgAbs = std::abs(mcPart.pdgCode()); + + // Stop at quark + if (pdgAbs < pdgQuark) { + break; + } + + // Produced in transport code + if (!mcPart.producedByGenerator()) { + SETBIT(mask, IsSecondary); + continue; + } + + // Tau parent + if (pdgAbs == kTauMinus) { + SETBIT(mask, HasTauParent); + continue; + } + + // W boson + if (pdgAbs == kWPlus) { + SETBIT(mask, HasWParent); + continue; + } + + // Z boson + if (pdgAbs == kZ0) { + SETBIT(mask, HasZParent); + continue; + } + + const int pdgRem(pdgAbs % 100000); + + if (pdgRem == kProton) { + continue; + } // Beam particle + + if ((pdgRem < pdgRemMin) || (pdgRem >= pdgRemMax)) { + continue; + } + // compute the leding flavor of constituent quark + int flv(pdgRem); + while (flv >= flvLeading) { + flv /= flvLeading; + } + + if (flv > flvMax) { + // no more than 6 flavors + continue; + } + if (flv < flvMin) { + // light flavor + SETBIT(mask, HasLightParent); + continue; + } + + auto pdgData(pdg->GetParticle(mcPart.pdgCode())); + if (pdgData && (pdgData->AntiParticle() == nullptr)) { + SETBIT(mask, HasQuarkoniumParent); + continue; + } else if (flv == flvMin) { + SETBIT(mask, HasCharmParent); + continue; + } else { + SETBIT(mask, HasBeautyParent); + continue; + } + } + + return mask; + } + + // particle has an associated MC particle + bool isIdentified(const uint16_t mask) + { + return (TESTBIT(mask, IsIdentified)); + } + // this particle is muon + bool isMuon(const uint16_t mask) + { + return (TESTBIT(mask, IsIdentified) && TESTBIT(mask, IsMuon)); + } + + // this muon comes from transport + bool isSecondaryMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, IsSecondary)); + } + + // this muon comes from light flavor quark decay + bool isLightDecayMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasLightParent) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from tau decays + bool isTauDecayMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasTauParent) && (!TESTBIT(mask, HasWParent)) && (!TESTBIT(mask, HasZParent)) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasCharmParent))); + } + + // this muon comes from W+- decay + bool isWBosonDecayMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasWParent) && (!TESTBIT(mask, HasZParent)) && (!TESTBIT(mask, HasTauParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from Z decay + bool isZBosonDecayMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasZParent) && (!TESTBIT(mask, HasWParent)) && (!TESTBIT(mask, HasTauParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from quarkonium decay + bool isQuarkoniumDecayMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasQuarkoniumParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasCharmParent)) && (!TESTBIT(mask, HasLightParent))); + } + + // this muon comes from beauty decay and does not have light flavor parent + bool isBeautyMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasBeautyParent) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes directly from beauty decay + bool isBeautyDecayMu(const uint16_t mask) + { + return (isBeautyMu(mask) && (!TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent))) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from non-prompt charm decay and does not have light flavor parent + bool isNonpromptCharmMu(const uint16_t mask) + { + return (isBeautyMu(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from prompt charm decay and does not have light flavor parent + bool isPromptCharmMu(const uint16_t mask) + { + return (isMuon(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasQuarkoniumParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, IsSecondary))); + } + + // this muon comes from other sources which have not classified above. + bool isOtherMu(const uint16_t mask) + { + return (isMuon(mask) && (!isSecondaryMu(mask)) && (!isLightDecayMu(mask)) && (!isTauDecayMu(mask)) && (!isWBosonDecayMu(mask)) && (!isZBosonDecayMu(mask)) && (!isQuarkoniumDecayMu(mask)) && (!isBeautyMu(mask)) && (!isPromptCharmMu(mask))); + } + + // this is a hadron + bool isHadron(const uint16_t mask) + { + return (TESTBIT(mask, IsIdentified) && (!TESTBIT(mask, IsMuon))); + } + + // this particle is unidentified + bool isUnidentified(const uint16_t mask) + { + return (!TESTBIT(mask, IsIdentified)); + } + + // fill the histograms of each particle types + void fillHistograms(const McMuons::iterator& muon) + { + const auto mask(getMask(muon)); + const auto pt(muon.pt()), eta(muon.eta()); + + if (isIdentified(mask)) { + registry.fill(HIST("h2Identified"), pt, eta); + } + if (isMuon(mask)) { + registry.fill(HIST("h2Muon"), pt, eta); + } + if (isSecondaryMu(mask)) { + registry.fill(HIST("h2SecondaryMu"), pt, eta); + } + if (isLightDecayMu(mask)) { + registry.fill(HIST("h2LightDecayMu"), pt, eta); + } + if (isTauDecayMu(mask)) { + registry.fill(HIST("h2TauDecayMu"), pt, eta); + } + if (isWBosonDecayMu(mask)) { + registry.fill(HIST("h2WBosonDecayMu"), pt, eta); + } + if (isZBosonDecayMu(mask)) { + registry.fill(HIST("h2ZBosonDecayMu"), pt, eta); + } + if (isQuarkoniumDecayMu(mask)) { + registry.fill(HIST("h2QuarkoniumDecayMu"), pt, eta); + } + if (isBeautyMu(mask)) { + registry.fill(HIST("h2BeautyMu"), pt, eta); + } + if (isBeautyDecayMu(mask)) { + registry.fill(HIST("h2BeautyDecayMu"), pt, eta); + } + if (isNonpromptCharmMu(mask)) { + registry.fill(HIST("h2NonpromptCharmMu"), pt, eta); + } + if (isPromptCharmMu(mask)) { + registry.fill(HIST("h2PromptCharmMu"), pt, eta); + } + if (isOtherMu(mask)) { + registry.fill(HIST("h2OtherMu"), pt, eta); + } + if (isHadron(mask)) { + registry.fill(HIST("h2Hadron"), pt, eta); + } + if (isUnidentified(mask)) { + registry.fill(HIST("h2Unidentified"), pt, eta); + } + } + + void process(McGenCollisions::iterator const& mccollision, + McMuons const& muons, + aod::McParticles const&, + McRecCollisions const& collisions) + { + + // event selections + if (std::abs(mccollision.posZ()) > zVtxMax) { + return; + } + + registry.fill(HIST("hNEventGenMu"), 1); + + for (const auto& muon : muons) { + if (!muon.has_mcParticle()) { + continue; + } + auto mcPart(muon.mcParticle()); + auto pdgGen(mcPart.pdgCode()); + auto etaGen(mcPart.eta()); + + if (std::abs(pdgGen) != kMuonMinus) { + continue; + } + if ((etaGen >= etaMax) || (etaGen < etaMin)) { + continue; + } + registry.fill(HIST("hGenMuVar"), pdgGen, mcPart.pt(), etaGen); + } + + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > zVtxMax) { + continue; + } + registry.fill(HIST("hNEventRecMu"), 1); + + for (const auto& muon : muons) { + // muon selections + registry.fill(HIST("hMcMask"), muon.mcMask()); + + if (muon.mcMask() != mcMaskSelection) { + continue; + } + + if (!muon.has_mcParticle()) { + continue; + } + const auto pt(muon.pt()), eta(muon.eta()), rAbsorb(muon.rAtAbsorberEnd()), pDca(muon.pDca()), chi2(muon.chi2MatchMCHMFT()); + const auto dcaXY{RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())}; + const auto muTrackType{muon.trackType()}; + const auto mcLabel(muon.mcParticleId()); + + if (mcLabel < 0) { + continue; + } + + registry.fill(HIST("hMuMcLabel"), mcLabel); + registry.fill(HIST("hMuTrackType"), muTrackType); + + auto mcparticle(muon.mcParticle()); + const auto pdg(mcparticle.pdgCode()); + + if ((eta >= etaMax) || (eta < etaMin)) { + continue; + } + if ((rAbsorb >= rAbsorbMax) || (rAbsorb < rAbsorbMin)) { + continue; + } + if (pDca >= pDcaMax) { + continue; + } + registry.fill(HIST("hRecMuVar"), pdg, pt, eta); + registry.fill(HIST("hMuAfterAccCuts"), pdg, pt, eta, rAbsorb, dcaXY, pDca, chi2, muTrackType); + + fillHistograms(muon); + } + } + } + + void processResTrack(McGenCollisions::iterator const& mccollision, + McRecCollisions const& collisions, + aod::McParticles const& particles, + MyTracks const& tracks) + { + // event selections + if (std::abs(mccollision.posZ()) > zVtxMax) { + return; + } + registry.fill(HIST("hNEventGen"), 1.); + auto nP = 0; + for (const auto& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!particle.producedByGenerator()) { + continue; + } + + auto charge = 0.; + auto* p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + + if (std::abs(charge) < ChargeMin) { + continue; + } + if (particle.pt() < ptTrackMin || std::abs(particle.eta()) >= etaTrackMax) { + continue; + } + + registry.fill(HIST("hParticleGen"), particle.pt(), particle.eta()); + nP++; + } + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > zVtxMax) { + continue; + } + registry.fill(HIST("hNEventRec"), 1.); + auto nTrk = 0; + auto tracksample = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracksample) { + if (!track.isGlobalTrack()) { + continue; + } + registry.fill(HIST("hParticleRec"), track.pt(), track.eta()); + ++nTrk; + } + if (nTrk < 1) { + continue; + } + registry.fill(HIST("hTrackResponse"), nP, nTrk); + } + } + PROCESS_SWITCH(HfTaskSingleMuonMultMc, processResTrack, "Process Track Reconstruction/Generation", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx index 20c3db63117..aea4ee26bea 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx @@ -14,7 +14,6 @@ // \author Maolin Zhang , CCNU #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include @@ -28,6 +27,7 @@ #include #include +#include #include #include #include @@ -41,7 +41,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using McMuons = soa::Join; namespace @@ -74,15 +74,19 @@ struct HfTaskSingleMuonSource { Produces singleMuonSource; Configurable mcMaskSelection{"mcMaskSelection", 0, "McMask for correct match, valid values are 0 and 128"}; - Configurable trackType{"trackType", 0, "Muon track type, validated values are 0, 1, 2, 3 and 4"}; - Configurable charge{"charge", -1, "Muon track charge, validated values are 0, 1 and -1, 0 represents both 1 and -1"}; - - double pDcaMax = 594.0; // p*DCA maximum value for large Rabs - double rAbsMin = 26.5; // R at absorber end minimum value - double rAbsMax = 89.5; // R at absorber end maximum value - double etaLow = -3.6; // low edge of eta acceptance - double etaUp = -2.5; // up edge of eta acceptance - double edgeZ = 10.0; // edge of event position Z + Configurable trackType{"trackType", 3, "Muon track type, validated values are 0, 1, 2, 3 and 4"}; + Configurable charge{"charge", 0, "Muon track charge, validated values are 0, 1 and -1, 0 represents both 1 and -1"}; + Configurable pairSource{"pairSource", true, "check also the source of like-sign muon pairs"}; + + double pDcaMax = 594.0; // p*DCA maximum value for small Rab + double pDcaMax2 = 324.0; // p*DCA maximum value for large Rabs + double rAbsMid = 26.5; // R at absorber end minimum value + double rAbsMax = 89.5; // R at absorber end maximum value + double rAbsMin = 17.6; // R at absorber end maximum value + double etaLow = -4.0; // low edge of eta acceptance + double etaUp = -2.5; // up edge of eta acceptance + double edgeZ = 10.0; // edge of event position Z + double ptLow = 1.0; // low edge of pT for muon pairs HistogramRegistry registry{ "registry", @@ -108,14 +112,23 @@ struct HfTaskSingleMuonSource { AxisSpec const axisChi2{500, 0., 100., "#chi^{2} of MCH-MFT matching"}; AxisSpec const axisPt{200, 0., 100., "#it{p}_{T,reco} (GeV/#it{c})"}; AxisSpec const axisDeltaPt{1000, -50., 50., "#Delta #it{p}_{T} (GeV/#it{c})"}; + AxisSpec const axisMass{200, 0., 20., "Inv.Mass (GeV/#it{c}^2)"}; HistogramConfigSpec const h1ColNumber{HistType::kTH1F, {axisColNumber}}; HistogramConfigSpec const h1Pt{HistType::kTH1F, {axisPt}}; + HistogramConfigSpec h1Mass{HistType::kTH1F, {axisMass}}; HistogramConfigSpec const h2PtDCA{HistType::kTH2F, {axisPt, axisDCA}}; HistogramConfigSpec const h2PtChi2{HistType::kTH2F, {axisPt, axisChi2}}; HistogramConfigSpec const h2PtDeltaPt{HistType::kTH2F, {axisPt, axisDeltaPt}}; registry.add("h1ColNumber", "", h1ColNumber); + registry.add("h1MuBeforeCuts", "", h1Pt); + registry.add("h1MuonMass", "", h1Mass); + registry.add("h1BeautyMass", "", h1Mass); + registry.add("h1OtherMass", "", h1Mass); + registry.add("h1MuonMassGen", "", h1Mass); + registry.add("h1BeautyMassGen", "", h1Mass); + registry.add("h1OtherMassGen", "", h1Mass); for (const auto& src : muonSources) { registry.add(Form("h1%sPt", src.Data()), "", h1Pt); registry.add(Form("h2%sPtDCA", src.Data()), "", h2PtDCA); @@ -146,8 +159,8 @@ struct HfTaskSingleMuonSource { mcPart = *(mcPart.mothers_first_as()); const auto pdgAbs(std::abs(mcPart.pdgCode())); - if (pdgAbs < 10) { - break; // Quark + if (pdgAbs < 10 || pdgAbs == 21) { + break; // Quark and gluon } if (!mcPart.producedByGenerator()) { // Produced in transport code @@ -170,6 +183,9 @@ struct HfTaskSingleMuonSource { if ((pdgRem < 100) || (pdgRem >= 10000)) { continue; } + if ((pdgRem % 100 == 1 || pdgRem % 100 == 3) && pdgRem > 1000) { // diquarks + continue; + } // compute the flavor of constituent quark const int flv(pdgRem / std::pow(10, static_cast(std::log10(pdgRem)))); if (flv > 6) { @@ -325,9 +341,113 @@ struct HfTaskSingleMuonSource { } } + int traceAncestor(const McMuons::iterator& muon, aod::McParticles const& mctracks) + { + int mcNum = 0; + if (!muon.has_mcParticle()) { + return 0; + } + auto mcPart(muon.mcParticle()); + if (std::abs(mcPart.pdgCode()) != kMuonMinus) { + return 0; + } + while (mcPart.has_mothers()) { // the first hadron after hadronization + auto mother = mcPart.mothers_first_as(); + if (std::abs(mother.getGenStatusCode()) < 80) { + break; + } + mcPart = mother; + } + int flv = mcPart.pdgCode() / std::pow(10, static_cast(std::log10(std::abs(mcPart.pdgCode())))); + if (abs(flv) == 5 && mcPart.pdgCode() < 1000) + flv = -flv; + for (int i = (mcPart.mothers_first_as()).globalIndex(); i <= (mcPart.mothers_last_as()).globalIndex(); i++) { // loop over the lund string + for (auto mctrack : mctracks) { + if (mctrack.globalIndex() != i) { + continue; + } + if ((mctrack.pdgCode() != flv) && (abs(mctrack.pdgCode()) < abs(flv) * 1000)) { + continue; + } + while (mctrack.has_mothers()) { + int motherflv = (mctrack.mothers_first_as()).pdgCode() / std::pow(10, static_cast(std::log10(abs((mctrack.mothers_first_as()).pdgCode())))); // find the mother with same flavor + auto mother = (abs(motherflv) == abs(flv)) ? (mctrack.mothers_first_as()) : (mctrack.mothers_last_as()); + if ((mother.pdgCode() != mctrack.pdgCode()) && (abs(mctrack.pdgCode()) < 10)) { // both mother is not the the quark with same flavor + mcNum = mctrack.globalIndex(); + return mcNum; + } + mctrack = mother; + } + } + } + return 0; + } + bool Corr(const McMuons::iterator& muon1, const McMuons::iterator& muon2, aod::McParticles const& mcParts) + { + + int moth11(0), moth12(0), moth21(1), moth22(1); + int anc1 = traceAncestor(muon1, mcParts); + int anc2 = traceAncestor(muon2, mcParts); + if (anc1 == 0 || anc2 == 0) { + return false; + } + for (auto mcPart : mcParts) { + if (mcPart.globalIndex() == anc1) { + moth11 = (mcPart.mothers_first_as()).globalIndex(); + moth12 = (mcPart.mothers_last_as()).globalIndex(); + } + if (mcPart.globalIndex() == anc2) { + moth21 = (mcPart.mothers_first_as()).globalIndex(); + moth22 = (mcPart.mothers_last_as()).globalIndex(); + } + } + if ((moth11 == moth21) && (moth12 == moth22)) { + return true; + } + return false; // uncorrelated + } + void fillPairs(const McMuons::iterator& muon, const McMuons::iterator& muon2, aod::McParticles const& mcParts) + { + if (trackType != 3) { + return; + } + float mm = o2::constants::physics::MassMuon; + + const auto mask1(getMask(muon)); + const auto mask2(getMask(muon2)); + + ROOT::Math::PtEtaPhiMVector mu1Vec(muon.pt(), muon.eta(), muon.phi(), mm); + ROOT::Math::PtEtaPhiMVector mu2Vec(muon2.pt(), muon2.eta(), muon2.phi(), mm); + ROOT::Math::PtEtaPhiMVector dimuVec = mu1Vec + mu2Vec; + auto InvM = dimuVec.M(); + + if (!muon.has_mcParticle() || !muon2.has_mcParticle()) { + return; + } + auto mcPart1(muon.mcParticle()); + auto mcPart2(muon2.mcParticle()); + + ROOT::Math::PtEtaPhiMVector mu1VecGen(mcPart1.pt(), mcPart1.eta(), mcPart1.phi(), mm); + ROOT::Math::PtEtaPhiMVector mu2VecGen(mcPart2.pt(), mcPart2.eta(), mcPart2.phi(), mm); + ROOT::Math::PtEtaPhiMVector dimuVecGen = mu1VecGen + mu2VecGen; + auto InvMGen = dimuVecGen.M(); + + if (isMuon(mask1) && isMuon(mask2)) { + registry.fill(HIST("h1MuonMass"), InvM); + registry.fill(HIST("h1MuonMassGen"), InvMGen); + } + if (Corr(muon, muon2, mcParts) && isBeautyMu(mask1) && isBeautyMu(mask2)) { + registry.fill(HIST("h1BeautyMass"), InvM); + registry.fill(HIST("h1BeautyMassGen"), InvMGen); + } else { + registry.fill(HIST("h1OtherMass"), InvM); + registry.fill(HIST("h1OtherMassGen"), InvMGen); + } + } + void process(MyCollisions::iterator const& collision, McMuons const& muons, - aod::McParticles const&) + aod::McParticles const& mcParts) { // event selections if (std::abs(collision.posZ()) > edgeZ) { @@ -347,11 +467,15 @@ struct HfTaskSingleMuonSource { if ((eta >= etaUp) || (eta < etaLow)) { continue; } - if ((rAbs >= rAbsMax) || (rAbs < rAbsMin)) { - continue; + if ((rAbs >= rAbsMid) || (rAbs < rAbsMin)) { + if (pDca >= pDcaMax || pDca < 0) { + continue; + } } - if (pDca >= pDcaMax) { - continue; + if ((rAbs >= rAbsMax) || (rAbs < rAbsMid)) { + if (pDca >= pDcaMax2 || pDca < 0) { + continue; + } } if ((muon.chi2() >= 1e6) || (muon.chi2() < 0)) { continue; @@ -360,6 +484,48 @@ struct HfTaskSingleMuonSource { continue; } fillHistograms(muon); + if (pairSource) { + if (muon.pt() < ptLow) { + continue; + } + for (const auto& muon2 : muons) { + if (muon2.sign() != muon.sign()) { + continue; + } + if (muon2.globalIndex() <= muon.globalIndex()) { + continue; + } + // muon selections + if (muon2.trackType() != trackType) { + continue; + } + if (muon2.pt() < ptLow) { + continue; + } + const auto eta2(muon2.eta()), pDca2(muon2.pDca()), rAbs2(muon2.rAtAbsorberEnd()); + if ((eta2 >= etaUp) || (eta2 < etaLow)) { + continue; + } + if ((rAbs2 >= rAbsMid) || (rAbs2 < rAbsMin)) { + if (pDca2 >= pDcaMax || pDca2 < 0) { + continue; + } + } + if ((rAbs2 >= rAbsMax) || (rAbs2 < rAbsMid)) { + if (pDca2 >= pDcaMax2 || pDca2 < 0) { + continue; + } + } + + if ((muon2.chi2() >= 1e6) || (muon2.chi2() < 0)) { + continue; + } + if ((muon2.chi2MatchMCHMID() >= 1e6) || (muon2.chi2MatchMCHMID() < 0)) { + continue; + } + fillPairs(muon, muon2, mcParts); + } + } } // loop over muons } }; diff --git a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C index 86caa6243e7..605e0a8f446 100644 --- a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C +++ b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C @@ -87,7 +87,7 @@ void computeFonllPlusPythiaPredictions(int nDecays = 10000000, 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"); +std::array readFonll(const std::string& inFile, const std::string& histName = "hFonllBhadron"); // FUNCTION IMPLEMENTATIONS //__________________________________________________________________________________________________ diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 26b3400ca28..174cbfa9621 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -90,16 +90,16 @@ o2physics_add_dpl_workflow(candidate-creator-xic0-omegac0 PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-creator-xic0-omegac0-qa + SOURCES candidateCreatorXic0Omegac0Qa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils + 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 O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(candidate-creator-xicc - SOURCES candidateCreatorXicc.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(candidate-creator-mc-gen SOURCES candidateCreatorMcGen.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -187,6 +187,11 @@ o2physics_add_dpl_workflow(candidate-selector-to-xi-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-selector-to-xi-pi-qa + SOURCES candidateSelectorToXiPiQa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-selector-xic-to-p-k-pi SOURCES candidateSelectorXicToPKPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore @@ -197,12 +202,7 @@ o2physics_add_dpl_workflow(candidate-selector-xic-to-xi-pi-pi 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 - COMPONENT_NAME Analysis) - - o2physics_add_dpl_workflow(candidate-selector-cd +o2physics_add_dpl_workflow(candidate-selector-cd SOURCES candidateSelectorCd.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -239,6 +239,11 @@ o2physics_add_dpl_workflow(tree-creator-ds-to-k-k-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tree-creator-dstar-to-d0-pi + SOURCES treeCreatorDstarToD0Pi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tree-creator-lb-to-lc-pi SOURCES treeCreatorLbToLcPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -279,6 +284,11 @@ o2physics_add_dpl_workflow(tree-creator-to-xi-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tree-creator-to-xi-pi-qa + SOURCES treeCreatorToXiPiQa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tree-creator-xic0-to-xi-pi-kf SOURCES treeCreatorXic0ToXiPiKf.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -294,16 +304,6 @@ o2physics_add_dpl_workflow(tree-creator-xic-to-xi-pi-pi 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 - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(tree-creator-dstar-to-d0-pi - SOURCES treeCreatorDstarToD0Pi.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(tree-creator-tcc-to-d0-d0-pi SOURCES treeCreatorTccToD0D0Pi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -345,6 +345,11 @@ o2physics_add_dpl_workflow(derived-data-creator-lc-to-p-k-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(derived-data-creator-lc-to-k0s-p + SOURCES derivedDataCreatorLcToK0sP.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(derived-data-creator-xic-to-xi-pi-pi SOURCES derivedDataCreatorXicToXiPiPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index f30f533c17b..821936284fb 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -116,12 +116,12 @@ struct HfCandidateCreator2Prong { HfEventSelection hfEvSel; // event selection and monitoring o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter - Service ccdb; + Service ccdb{}; int runNumber{0}; double bz{0.}; - const float toMicrometers = 10000.; // from cm to µm + constexpr static float CentiToMicro{10000.f}; // from cm to µm std::shared_ptr hCandidates; @@ -313,13 +313,13 @@ struct HfCandidateCreator2Prong { o2::dataformats::DCA impactParameter1; trackParVar0.propagateToDCA(primaryVertex, bz, &impactParameter0); trackParVar1.propagateToDCA(primaryVertex, bz, &impactParameter1); - registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0.getY() * toMicrometers); - registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1.getY() * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track0.pt(), impactParameter0.getZ() * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track1.pt(), impactParameter1.getZ() * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0.getY() * CentiToMicro); + registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1.getY() * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track0.pt(), impactParameter0.getZ() * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track1.pt(), impactParameter1.getZ() * CentiToMicro); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, 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.)); @@ -439,15 +439,15 @@ struct HfCandidateCreator2Prong { float impactParameter0XY = 0., errImpactParameter0XY = 0., impactParameter1XY = 0., errImpactParameter1XY = 0.; if (!kfPosPion.GetDistanceFromVertexXY(kfpV, impactParameter0XY, errImpactParameter0XY)) { - registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0XY * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track0.pt(), std::sqrt(kfPosPion.GetDistanceFromVertex(kfpV) * kfPosPion.GetDistanceFromVertex(kfpV) - impactParameter0XY * impactParameter0XY) * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0XY * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track0.pt(), std::sqrt(kfPosPion.GetDistanceFromVertex(kfpV) * kfPosPion.GetDistanceFromVertex(kfpV) - impactParameter0XY * impactParameter0XY) * CentiToMicro); } else { registry.fill(HIST("hDcaXYProngs"), track0.pt(), -999.f); registry.fill(HIST("hDcaZProngs"), track0.pt(), -999.f); } if (!kfNegPion.GetDistanceFromVertexXY(kfpV, impactParameter1XY, errImpactParameter1XY)) { - registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1XY * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track1.pt(), std::sqrt(kfNegPion.GetDistanceFromVertex(kfpV) * kfNegPion.GetDistanceFromVertex(kfpV) - impactParameter1XY * impactParameter1XY) * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1XY * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track1.pt(), std::sqrt(kfNegPion.GetDistanceFromVertex(kfpV) * kfNegPion.GetDistanceFromVertex(kfpV) - impactParameter1XY * impactParameter1XY) * CentiToMicro); } else { registry.fill(HIST("hDcaXYProngs"), track1.pt(), -999.f); registry.fill(HIST("hDcaZProngs"), track1.pt(), -999.f); @@ -472,7 +472,7 @@ struct HfCandidateCreator2Prong { auto* covMatrixSV = kfCandD0.CovarianceMatrix(); - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{kfpV.GetX(), kfpV.GetY(), kfpV.GetZ()}, std::array{kfCandD0.GetX(), kfCandD0.GetY(), kfCandD0.GetZ()}, 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.)); diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index bb03518d889..7ae95c956b7 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -21,6 +21,7 @@ #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/AliasTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/TrackIndexSkimmingTables.h" @@ -47,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +80,7 @@ #include using namespace o2; +using namespace o2::analysis; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::aod::hf_cand_3prong; @@ -98,14 +101,23 @@ struct HfCandidateCreator3Prong { Produces rowProng0PidKa; Produces rowProng0PidPr; Produces rowProng0PidDe; + Produces rowProng0PidTr; + Produces rowProng0PidHe; + Produces rowProng0PidAl; Produces rowProng1PidPi; Produces rowProng1PidKa; Produces rowProng1PidPr; Produces rowProng1PidDe; + Produces rowProng1PidTr; + Produces rowProng1PidHe; + Produces rowProng1PidAl; Produces rowProng2PidPi; Produces rowProng2PidKa; Produces rowProng2PidPr; Produces rowProng2PidDe; + Produces rowProng2PidTr; + Produces rowProng2PidHe; + Produces rowProng2PidAl; // vertexing Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -126,27 +138,29 @@ struct HfCandidateCreator3Prong { Configurable createDs{"createDs", false, "enable Ds+/- candidate creation"}; Configurable createLc{"createLc", false, "enable Lc+/- candidate creation"}; Configurable createXic{"createXic", false, "enable Xic+/- candidate creation"}; - Configurable createCd{"createCd", false, "enable Cd candidate creation"}; + Configurable createCharmNuclei{"createCharmNuclei", false, "enable createCharmNuclei candidate creation"}; // KF Configurable applyTopoConstraint{"applyTopoConstraint", false, "apply origin from PV hypothesis for created candidate, works only in KF mode"}; Configurable applyInvMassConstraint{"applyInvMassConstraint", false, "apply particle type hypothesis to recalculate created candidate's momentum, works only in KF mode"}; + Configurable> tpcPidBBParamsLightNuclei{"tpcPidBBParamsLightNuclei", {hf_presel_lightnuclei::BetheBlochParams[0], hf_presel_lightnuclei::NParticleRows, hf_presel_lightnuclei::NBetheBlochParams, hf_presel_lightnuclei::labelsRowsNucleiType, hf_presel_lightnuclei::labelsBetheBlochParams}, "TPC PID Bethe–Bloch parameter configurations for light nuclei (deuteron, triton, helium-3)"}; + HfEventSelection hfEvSel; // event selection and monitoring o2::vertexing::DCAFitterN<3> df; // 3-prong vertex fitter - Service ccdb; + Service ccdb{}; int runNumber{0}; double bz{0.}; - const float toMicrometers = 10000.; // from cm to µm + constexpr static float CentiToMicro{10000.f}; // from cm to µm constexpr static float UndefValueFloat{-999.f}; using FilteredHf3Prongs = soa::Filtered; using FilteredPvRefitHf3Prongs = soa::Filtered>; - using TracksWCovExtraPidPiKaPrDe = soa::Join; + using TracksWCovExtraPidPiKaPrLightNuclei = soa::Join; // filter candidates - Filter filterSelected3Prongs = (createDplus && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::DplusToPiKPi))) != static_cast(0)) || (createDs && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::DsToKKPi))) != static_cast(0)) || (createLc && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::LcToPKPi))) != static_cast(0)) || (createXic && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::XicToPKPi))) != static_cast(0)) || (createCd && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::CdToDeKPi))) != static_cast(0)); + Filter filterSelected3Prongs = (createDplus && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::DplusToPiKPi))) != static_cast(0)) || (createDs && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::DsToKKPi))) != static_cast(0)) || (createLc && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::LcToPKPi))) != static_cast(0)) || (createXic && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::XicToPKPi))) != static_cast(0)) || (createCharmNuclei && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::CdToDeKPi))) != static_cast(0)) || (createCharmNuclei && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::CtToTrKPi))) != static_cast(0)) || (createCharmNuclei && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::ChToHeKPi))) != static_cast(0)) || (createCharmNuclei && (o2::aod::hf_track_index::hfflag & static_cast(BIT(DecayType::CaToAlKPi))) != static_cast(0)); std::shared_ptr hCandidates; HistogramRegistry registry{"registry"}; @@ -189,7 +203,7 @@ struct HfCandidateCreator3Prong { if (nProcessesUpc > 0 && isRun2) { LOGP(fatal, "Process function for UPC is only available in Run 3!"); } - std::array creationFlags = {createDplus, createDs, createLc, createXic, createCd}; + std::array creationFlags = {createDplus, createDs, createLc, createXic, createCharmNuclei}; if (std::accumulate(creationFlags.begin(), creationFlags.end(), 0) == 0) { LOGP(fatal, "At least one particle specie should be enabled for the creation."); } @@ -226,10 +240,10 @@ struct HfCandidateCreator3Prong { // Configure DCAFitterN // df.setBz(bz); df.setPropagateToPCA(propagateToPCA); - df.setMaxR(maxR); - df.setMaxDZIni(maxDZIni); - df.setMinParamChange(minParamChange); - df.setMinRelChi2Change(minRelChi2Change); + df.setMaxR(static_cast(maxR)); + df.setMaxDZIni(static_cast(maxDZIni)); + df.setMinParamChange(static_cast(minParamChange)); + df.setMinRelChi2Change(static_cast(minRelChi2Change)); df.setUseAbsDCA(useAbsDCA); df.setWeightedFinalPCA(useWeightedFinalPCA); @@ -258,17 +272,26 @@ struct HfCandidateCreator3Prong { fillProngPid(track1, rowProng1PidPr); fillProngPid(track2, rowProng2PidPr); } - if (createCd) { - fillProngPid(track0, rowProng0PidDe); - fillProngPid(track1, rowProng1PidDe); - fillProngPid(track2, rowProng2PidDe); + if (createCharmNuclei) { + fillProngPidLightNuclei(track0, rowProng0PidDe, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track1, rowProng1PidDe, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track2, rowProng2PidDe, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track0, rowProng0PidHe, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track1, rowProng1PidHe, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track2, rowProng2PidHe, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track0, rowProng0PidTr, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track1, rowProng1PidTr, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track2, rowProng2PidTr, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track0, rowProng0PidAl, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track1, rowProng1PidAl, tpcPidBBParamsLightNuclei); + fillProngPidLightNuclei(track2, rowProng2PidAl, tpcPidBBParamsLightNuclei); } } template void runCreator3ProngWithDCAFitterN(Coll const&, Cand const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const&, + TracksWCovExtraPidPiKaPrLightNuclei const&, BCsType const& bcs) { // loop over triplets of track indices @@ -288,9 +311,9 @@ struct HfCandidateCreator3Prong { continue; } - auto track0 = rowTrackIndexProng3.template prong0_as(); - auto track1 = rowTrackIndexProng3.template prong1_as(); - auto track2 = rowTrackIndexProng3.template prong2_as(); + auto track0 = rowTrackIndexProng3.template prong0_as(); + auto track1 = rowTrackIndexProng3.template prong1_as(); + auto track2 = rowTrackIndexProng3.template prong2_as(); auto trackParVar0 = getTrackParCov(track0); auto trackParVar1 = getTrackParCov(track1); auto trackParVar2 = getTrackParCov(track2); @@ -307,7 +330,7 @@ struct HfCandidateCreator3Prong { // df.setBz(bz); /// put it outside the 'if'! Otherwise we have a difference wrt bz Configurable (< 1 permille) in Run2 conv. data // df.print(); } - df.setBz(bz); + df.setBz(static_cast(bz)); // reconstruct the 3-prong secondary vertex hCandidates->Fill(SVFitting::BeforeFit); @@ -371,15 +394,15 @@ struct HfCandidateCreator3Prong { trackParVar0.propagateToDCA(primaryVertex, bz, &impactParameter0); trackParVar1.propagateToDCA(primaryVertex, bz, &impactParameter1); trackParVar2.propagateToDCA(primaryVertex, bz, &impactParameter2); - registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0.getY() * toMicrometers); - registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1.getY() * toMicrometers); - registry.fill(HIST("hDcaXYProngs"), track2.pt(), impactParameter2.getY() * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track0.pt(), impactParameter0.getZ() * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track1.pt(), impactParameter1.getZ() * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track2.pt(), impactParameter2.getZ() * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0.getY() * CentiToMicro); + registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1.getY() * CentiToMicro); + registry.fill(HIST("hDcaXYProngs"), track2.pt(), impactParameter2.getY() * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track0.pt(), impactParameter0.getZ() * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track1.pt(), impactParameter1.getZ() * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track2.pt(), impactParameter2.getZ() * CentiToMicro); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, 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.)); @@ -445,7 +468,7 @@ struct HfCandidateCreator3Prong { template void runCreator3ProngWithKFParticle(Coll const&, Cand const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const&, + TracksWCovExtraPidPiKaPrLightNuclei const&, BCsType const& bcs) { for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { @@ -463,9 +486,9 @@ struct HfCandidateCreator3Prong { continue; } - auto track0 = rowTrackIndexProng3.template prong0_as(); - auto track1 = rowTrackIndexProng3.template prong1_as(); - auto track2 = rowTrackIndexProng3.template prong2_as(); + auto track0 = rowTrackIndexProng3.template prong0_as(); + auto track1 = rowTrackIndexProng3.template prong1_as(); + auto track2 = rowTrackIndexProng3.template prong2_as(); /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, @@ -481,7 +504,7 @@ struct HfCandidateCreator3Prong { } float covMatrixPV[6]; - KFParticle::SetField(bz); + KFParticle::SetField(static_cast(bz)); KFPVertex kfpVertex = createKFPVertexFromCollision(collision); if constexpr (DoPvRefit) { @@ -513,22 +536,22 @@ struct HfCandidateCreator3Prong { float impactParameter0XY = 0., errImpactParameter0XY = 0., impactParameter1XY = 0., errImpactParameter1XY = 0., impactParameter2XY = 0., errImpactParameter2XY = 0.; if (!kfFirstProton.GetDistanceFromVertexXY(kfpV, impactParameter0XY, errImpactParameter0XY)) { - registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0XY * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track0.pt(), std::sqrt(kfFirstProton.GetDistanceFromVertex(kfpV) * kfFirstProton.GetDistanceFromVertex(kfpV) - impactParameter0XY * impactParameter0XY) * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track0.pt(), impactParameter0XY * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track0.pt(), std::sqrt(kfFirstProton.GetDistanceFromVertex(kfpV) * kfFirstProton.GetDistanceFromVertex(kfpV) - impactParameter0XY * impactParameter0XY) * CentiToMicro); } else { registry.fill(HIST("hDcaXYProngs"), track0.pt(), UndefValueFloat); registry.fill(HIST("hDcaZProngs"), track0.pt(), UndefValueFloat); } if (!kfSecondKaon.GetDistanceFromVertexXY(kfpV, impactParameter1XY, errImpactParameter1XY)) { - registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1XY * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track1.pt(), std::sqrt(kfSecondKaon.GetDistanceFromVertex(kfpV) * kfSecondKaon.GetDistanceFromVertex(kfpV) - impactParameter1XY * impactParameter1XY) * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track1.pt(), impactParameter1XY * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track1.pt(), std::sqrt(kfSecondKaon.GetDistanceFromVertex(kfpV) * kfSecondKaon.GetDistanceFromVertex(kfpV) - impactParameter1XY * impactParameter1XY) * CentiToMicro); } else { registry.fill(HIST("hDcaXYProngs"), track1.pt(), UndefValueFloat); registry.fill(HIST("hDcaZProngs"), track1.pt(), UndefValueFloat); } if (!kfThirdProton.GetDistanceFromVertexXY(kfpV, impactParameter2XY, errImpactParameter2XY)) { - registry.fill(HIST("hDcaXYProngs"), track2.pt(), impactParameter2XY * toMicrometers); - registry.fill(HIST("hDcaZProngs"), track2.pt(), std::sqrt(kfThirdProton.GetDistanceFromVertex(kfpV) * kfThirdProton.GetDistanceFromVertex(kfpV) - impactParameter2XY * impactParameter2XY) * toMicrometers); + registry.fill(HIST("hDcaXYProngs"), track2.pt(), impactParameter2XY * CentiToMicro); + registry.fill(HIST("hDcaZProngs"), track2.pt(), std::sqrt(kfThirdProton.GetDistanceFromVertex(kfpV) * kfThirdProton.GetDistanceFromVertex(kfpV) - impactParameter2XY * impactParameter2XY) * CentiToMicro); } else { registry.fill(HIST("hDcaXYProngs"), track2.pt(), UndefValueFloat); registry.fill(HIST("hDcaZProngs"), track2.pt(), UndefValueFloat); @@ -604,14 +627,14 @@ struct HfCandidateCreator3Prong { const float massPiK = kfPairPiK.GetMass(); if (applyInvMassConstraint) { // constraints applied after minv getters - to preserve unbiased values of minv - kfCandPKPi.SetNonlinearMassConstraint(createLc ? MassLambdaCPlus : MassXiCPlus); - kfCandPiKP.SetNonlinearMassConstraint(createLc ? MassLambdaCPlus : MassXiCPlus); - kfCandPiKPi.SetNonlinearMassConstraint(MassDPlus); - kfCandKKPi.SetNonlinearMassConstraint(MassDS); - kfCandPiKK.SetNonlinearMassConstraint(MassDS); + kfCandPKPi.SetNonlinearMassConstraint(createLc ? static_cast(MassLambdaCPlus) : static_cast(MassXiCPlus)); + kfCandPiKP.SetNonlinearMassConstraint(createLc ? static_cast(MassLambdaCPlus) : static_cast(MassXiCPlus)); + kfCandPiKPi.SetNonlinearMassConstraint(static_cast(MassDPlus)); + kfCandKKPi.SetNonlinearMassConstraint(static_cast(MassDS)); + kfCandPiKK.SetNonlinearMassConstraint(static_cast(MassDS)); } - const float chi2geo = kfCandPKPi.Chi2() / kfCandPKPi.NDF(); + const float chi2geo = kfCandPKPi.Chi2() / static_cast(kfCandPKPi.NDF()); const std::pair ldl = kfCalculateLdL(kfCandPKPi, kfpV); std::array pProng0 = kfCalculateProngMomentumInSecondaryVertex(kfFirstProton, kfCandPiKP); @@ -624,7 +647,7 @@ struct HfCandidateCreator3Prong { registry.fill(HIST("hCovSVZZ"), kfCandPKPi.Covariance(2, 2)); auto* covMatrixSV = kfCandPKPi.CovarianceMatrix(); - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{kfpV.GetX(), kfpV.GetY(), kfpV.GetZ()}, std::array{kfCandPKPi.GetX(), kfCandPKPi.GetY(), kfCandPKPi.GetZ()}, 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.)); @@ -647,7 +670,7 @@ struct HfCandidateCreator3Prong { kfpV.GetX(), kfpV.GetY(), kfpV.GetZ(), kfCandPKPi.GetX(), kfCandPKPi.GetY(), kfCandPKPi.GetZ(), errorDecayLength, errorDecayLengthXY, - kfCandPKPi.GetChi2() / kfCandPKPi.GetNDF(), + kfCandPKPi.GetChi2() / static_cast(kfCandPKPi.GetNDF()), pProng0.at(0), pProng0.at(1), pProng0.at(2), pProng1.at(0), pProng1.at(1), pProng1.at(2), pProng2.at(0), pProng2.at(1), pProng2.at(2), @@ -694,7 +717,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/ PV refit and w/o centrality selections void processPvRefitWithDCAFitterN(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -704,7 +727,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/o PV refit and w/o centrality selections void processNoPvRefitWithDCAFitterN(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -714,7 +737,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/ PV refit and w/o centrality selections void processPvRefitWithKFParticle(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -724,7 +747,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/o PV refit and w/o centrality selections void processNoPvRefitWithKFParticle(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -740,7 +763,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on FT0C void processPvRefitWithDCAFitterNCentFT0C(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -750,7 +773,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/o PV refit and w/ centrality selection on FT0C void processNoPvRefitWithDCAFitterNCentFT0C(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -760,7 +783,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on FT0C void processPvRefitWithKFParticleCentFT0C(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -770,7 +793,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/o PV refit and w/ centrality selection on FT0C void processNoPvRefitWithKFParticleCentFT0C(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -786,7 +809,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on FT0M void processPvRefitWithDCAFitterNCentFT0M(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -796,7 +819,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/o PV refit and w/ centrality selection on FT0M void processNoPvRefitWithDCAFitterNCentFT0M(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -806,7 +829,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on FT0M void processPvRefitWithKFParticleCentFT0M(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -816,7 +839,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/o PV refit and w/ centrality selection on FT0M void processNoPvRefitWithKFParticleCentFT0M(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); @@ -832,7 +855,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on UPC void processPvRefitWithDCAFitterNUpc(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BcFullInfos const& bcWithTimeStamps, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, @@ -846,7 +869,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using DCA fitter w/o PV refit and w/ centrality selection on UPC void processNoPvRefitWithDCAFitterNUpc(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BcFullInfos const& bcWithTimeStamps, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, @@ -860,7 +883,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on UPC void processPvRefitWithKFParticleUpc(soa::Join const& collisions, FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BcFullInfos const& bcWithTimeStamps, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, @@ -874,7 +897,7 @@ struct HfCandidateCreator3Prong { /// @brief process function using KFParticle package w/o PV refit and w/ centrality selection on UPC void processNoPvRefitWithKFParticleUpc(soa::Join const& collisions, FilteredHf3Prongs const& rowsTrackIndexProng3, - TracksWCovExtraPidPiKaPrDe const& tracks, + TracksWCovExtraPidPiKaPrLightNuclei const& tracks, aod::BcFullInfos const& bcWithTimeStamps, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, @@ -904,7 +927,7 @@ struct HfCandidateCreator3Prong { const auto bc = collision.template foundBC_as(); const auto ir = hfEvSel.getInteractionRate(bc, ccdb); // Hz /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, ir); + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, static_cast(ir)); } /// end loop over collisions } @@ -923,7 +946,7 @@ struct HfCandidateCreator3Prong { const auto bc = collision.template foundBC_as(); const auto ir = hfEvSel.getInteractionRate(bc, ccdb); // Hz /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, ir); + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, static_cast(ir)); } /// end loop over collisions } @@ -942,7 +965,7 @@ struct HfCandidateCreator3Prong { const auto bc = collision.template foundBC_as(); const auto ir = hfEvSel.getInteractionRate(bc, ccdb); // Hz /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, ir); + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, static_cast(ir)); } /// end loop over collisions } @@ -966,7 +989,7 @@ struct HfCandidateCreator3Prong { const auto bc = collision.template foundBC_as(); const auto ir = hfEvSel.getInteractionRate(bc, ccdb); // Hz /// monitor the satisfied event selections - hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, ir); + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy, static_cast(ir)); } /// end loop over collisions } @@ -1132,7 +1155,7 @@ struct HfCandidateCreator3ProngExpressions { return; } if (indexRec > -1) { - flagChannelMain = sign * channelMain; + flagChannelMain = static_cast(sign * channelMain); /// swapping for D+, Ds->Kpipi; Lc, Xic->pKpi if (std::abs(flagChannelMain) == DecayChannelMain::DplusToPiKK || std::abs(flagChannelMain) == DecayChannelMain::DsToPiKK || std::abs(flagChannelMain) == DecayChannelMain::LcToPKPi || std::abs(flagChannelMain) == DecayChannelMain::XicToPKPi) { @@ -1185,7 +1208,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDplusToPiKPi, true, &sign, 2); } if (indexRec > -1) { - flagChannelMain = sign * DecayChannelMain::DplusToPiKPi; + flagChannelMain = static_cast(sign * DecayChannelMain::DplusToPiKPi); } } @@ -1215,7 +1238,7 @@ struct HfCandidateCreator3ProngExpressions { } } if (indexRec > -1) { - flagChannelMain = sign * (isDplus ? DecayChannelMain::DplusToPiKK : DecayChannelMain::DsToPiKK); + flagChannelMain = sign * (isDplus ? static_cast(DecayChannelMain::DplusToPiKK) : static_cast(DecayChannelMain::DsToPiKK)); if (arrayDaughters[0].has_mcParticle()) { swapping = static_cast(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } @@ -1243,7 +1266,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, arrPdgDaughtersDstarToPiKPi, true, &sign, 2); } if (indexRec > -1) { - flagChannelMain = sign * DecayChannelMain::DstarToPiKPi; + flagChannelMain = static_cast(sign * DecayChannelMain::DstarToPiKPi); flagChannelResonant = 0; } } @@ -1261,7 +1284,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, arrPdgDaughtersLcToPKPi, true, &sign, 2); } if (indexRec > -1) { - flagChannelMain = sign * DecayChannelMain::LcToPKPi; + flagChannelMain = static_cast(sign * DecayChannelMain::LcToPKPi); // Flagging the different Λc± → p± K∓ π± decay channels if (arrayDaughters[0].has_mcParticle()) { @@ -1297,7 +1320,7 @@ struct HfCandidateCreator3ProngExpressions { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, arrPdgDaughtersXicToPKPi, true, &sign, 2); } if (indexRec > -1) { - flagChannelMain = sign * DecayChannelMain::XicToPKPi; + flagChannelMain = static_cast(sign * DecayChannelMain::XicToPKPi); flagChannelResonant = 0; // TODO if (arrayDaughters[0].has_mcParticle()) { swapping = static_cast(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); @@ -1309,7 +1332,7 @@ struct HfCandidateCreator3ProngExpressions { // Check whether the particle is non-prompt (from a b quark). if (flagChannelMain != 0) { auto particle = mcParticles.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + origin = static_cast(RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers)); } if (origin == RecoDecay::OriginType::NonPrompt) { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); diff --git a/PWGHF/TableProducer/candidateCreatorB0.cxx b/PWGHF/TableProducer/candidateCreatorB0.cxx index 0387acf0b15..385a2d551aa 100644 --- a/PWGHF/TableProducer/candidateCreatorB0.cxx +++ b/PWGHF/TableProducer/candidateCreatorB0.cxx @@ -97,14 +97,11 @@ struct HfCandidateCreatorB0 { 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)"}; - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber{}; - double massPi{0.}; - double massD{0.}; - double massB0{0.}; double invMass2DPiMin{0.}; double invMass2DPiMax{0.}; double bz{0.}; @@ -136,11 +133,8 @@ struct HfCandidateCreatorB0 { void init(InitContext const&) { // invariant-mass window cut - massPi = MassPiPlus; - massD = MassDMinus; - massB0 = MassB0; - invMass2DPiMin = (massB0 - invMassWindowB0) * (massB0 - invMassWindowB0); - invMass2DPiMax = (massB0 + invMassWindowB0) * (massB0 + invMassWindowB0); + invMass2DPiMin = (MassB0 - invMassWindowB0) * (MassB0 - invMassWindowB0); + invMass2DPiMax = (MassB0 + invMassWindowB0) * (MassB0 + invMassWindowB0); // Initialise fitter for B vertex (2-prong vertex filter) df2.setPropagateToPCA(propagateToPCA); @@ -345,14 +339,13 @@ struct HfCandidateCreatorB0 { hCovSVXX->Fill(covMatrixPCA[0]); hCovPVXX->Fill(covMatrixPV[0]); - // propagate D and Pi to the B0 vertex - df2.propagateTracksToVertex(); + // get D and Pi tracks (propagated to the B0 vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of D at the B0 vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the B0 vertex // calculate invariant mass square and apply selection - auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{MassDMinus, MassPiPlus}); if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { continue; } @@ -365,7 +358,7 @@ struct HfCandidateCreatorB0 { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/TableProducer/candidateCreatorBplus.cxx b/PWGHF/TableProducer/candidateCreatorBplus.cxx index 20e1536cd7e..22ded3ecc7b 100644 --- a/PWGHF/TableProducer/candidateCreatorBplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorBplus.cxx @@ -106,7 +106,7 @@ struct HfCandidateCreatorBplus { 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)"}; - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber{}; @@ -326,7 +326,7 @@ struct HfCandidateCreatorBplus { } hCandidatesB->Fill(SVFitting::FitOk); - dfB.propagateTracksToVertex(); // propagate the bachelor and D0 to the B+ vertex + // get D and Pi tracks (propagated to the B+ vertex if propagateToPCA==true) trackD0.getPxPyPzGlo(pVecD0); // momentum of D0 at the B+ vertex trackParCovPi.getPxPyPzGlo(pVecBach); // momentum of pi+ at the B+ vertex @@ -345,7 +345,7 @@ struct HfCandidateCreatorBplus { trackParCovPi.propagateToDCA(primaryVertex, bz, &impactParameter1); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secVertexBplus, 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.)); diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index e73eaa4215a..dfd7e220846 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -98,14 +98,11 @@ struct HfCandidateCreatorBs { o2::vertexing::DCAFitterN<2> df2; // 2-prong vertex fitter o2::vertexing::DCAFitterN<3> df3; // 3-prong vertex fitter - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber{0}; - double massPi{0.}; - double massDs{0.}; - double massBs{0.}; double massDsPi{0.}; double bz{0.}; @@ -130,10 +127,6 @@ struct HfCandidateCreatorBs { void init(InitContext const&) { - massPi = MassPiPlus; - massDs = MassDSBar; - massBs = MassBS; - // Initialise fitter for Bs vertex (2-prong vertex fitter) df2.setPropagateToPCA(propagateToPCA); df2.setMaxR(maxR); @@ -324,15 +317,14 @@ struct HfCandidateCreatorBs { auto chi2PCA = df2.getChi2AtPCACandidate(); auto covMatrixPCA = df2.calcPCACovMatrixFlat(); - // propagate Ds and Pi to the Bs vertex - df2.propagateTracksToVertex(); + // get Ds and Pi tracks (propagated to the Bs vertex if propagateToPCA==true) // track.getPxPyPzGlo(pVec) modifies pVec of track df2.getTrack(0).getPxPyPzGlo(pVecDs); // momentum of Ds at the Bs vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the Bs vertex // calculate invariant mass and apply selection - massDsPi = RecoDecay::m(std::array{pVecDs, pVecPion}, std::array{massDs, massPi}); - if (std::abs(massDsPi - massBs) > invMassWindowBs) { + massDsPi = RecoDecay::m(std::array{pVecDs, pVecPion}, std::array{MassDSBar, MassPiPlus}); + if (std::abs(massDsPi - MassBS) > invMassWindowBs) { continue; } @@ -343,7 +335,7 @@ struct HfCandidateCreatorBs { trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; // getPointDirection modifies phi and theta getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBs, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index a0bb58dfd4c..fe9c2c3a57c 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -92,15 +92,11 @@ struct HfCandidateCreatorCascade { HfEventSelection hfEvSel; // event selection and monitoring o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; 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.}; double mass2K0sP{0.}; double bz = 0.; @@ -143,11 +139,6 @@ struct HfCandidateCreatorCascade { // init HF event selection helper hfEvSel.init(registry, &zorroSummary); - massP = MassProton; - massK0s = MassK0Short; - massPi = MassPiPlus; - massLc = MassLambdaCPlus; - // df.setBz(bz); df.setPropagateToPCA(propagateToPCA); df.setMaxR(maxR); @@ -196,10 +187,10 @@ struct HfCandidateCreatorCascade { } int posGlobalIndex = -1, negGlobalIndex = -1; - float v0X, v0Y, v0Z, v0px, v0py, v0pz; - float v0PosPx, v0PosPy, v0PosPz, v0NegPx, v0NegPy, v0NegPz; - float dcaV0dau, dcaPosToPV, dcaNegToPV, v0cosPA; - std::array covV = {0.}; + float v0X{}, v0Y{}, v0Z{}, v0px{}, v0py{}, v0pz{}; + float v0PosPx{}, v0PosPy{}, v0PosPz{}, v0NegPx{}, v0NegPy{}, v0NegPz{}; + float dcaV0dau{}, dcaPosToPV{}, dcaNegToPV{}, v0cosPA{}; + std::array covV{}; auto v0index = casc.template v0_as(); if (v0index.has_v0Data()) { @@ -233,7 +224,9 @@ struct HfCandidateCreatorCascade { covV[i] = v0row.positionCovMat()[i]; } } else { - LOGF(warning, "V0Data not there for V0 %d in HF cascade %d. Skipping candidate.", casc.v0Id(), casc.globalIndex()); + if (!silenceV0DataWarning) { + LOGF(warning, "V0Data not there for V0 %d in HF cascade %d. Skipping candidate.", casc.v0Id(), casc.globalIndex()); + } continue; // this was inadequately linked, should not happen } @@ -275,7 +268,6 @@ struct HfCandidateCreatorCascade { auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrixFlat(); registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); // FIXME: Calculation of errorDecayLength(XY) gives wrong values without this line. - // do I have to call "df.propagateTracksToVertex();"? auto trackParVarV0 = df.getTrack(0); auto trackParVarBach = df.getTrack(1); @@ -296,7 +288,7 @@ struct HfCandidateCreatorCascade { trackParVarBach.propagateToDCA(primaryVertex, bz, &impactParameterBach); // get uncertainty of the decay length - double phi, theta; + 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.)); @@ -324,7 +316,7 @@ struct HfCandidateCreatorCascade { // fill histograms if (fillHistograms) { // calculate invariant masses - mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); + mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{MassProton, MassK0Short}); registry.fill(HIST("hMass2"), mass2K0sP); } } diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index 185e5f26206..6e4701bc63b 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -105,15 +105,14 @@ struct HfCandidateCreatorDstar { 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"}; - HfEventSelection hfEvSel; // event selection and monitoring - Service ccdb; // From utilsBfieldCCDB.h + HfEventSelection hfEvSel; // event selection and monitoring + Service ccdb{}; // From utilsBfieldCCDB.h o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; // D0-prong vertex fitter o2::vertexing::DCAFitterN<2> df; int runNumber{}; double bz{}; static constexpr float CmToMicrometers = 10000.; // from cm to µm - double massPi{}, massK{}, massD0{}; using TracksWCovExtraPidPiKa = soa::Join; @@ -177,9 +176,6 @@ struct HfCandidateCreatorDstar { hfEvSel.init(registry, &zorroSummary); // LOG(info) << "Init Function Invoked"; - massPi = MassPiPlus; - massK = MassKPlus; - massD0 = MassD0; df.setPropagateToPCA(propagateToPCA); df.setMaxR(maxR); @@ -286,8 +282,6 @@ struct HfCandidateCreatorDstar { registry.fill(HIST("Refit/hCovSVXZ"), covMatrixPCA[3]); registry.fill(HIST("Refit/hCovSVZZ"), covMatrixPCA[5]); - // Doubt:................Below, track object are at secondary vertex! - // < track param propagated to V0 candidate (no check for the candidate validity). propagateTracksToVertex must be called in advance auto trackD0ProngParVar0 = df.getTrack(0); auto trackD0ProngParVar1 = df.getTrack(1); @@ -337,7 +331,7 @@ struct HfCandidateCreatorDstar { registry.fill(HIST("QA/hDCAZPi"), trackPi.pt(), impactParameterPi.getZ() * CmToMicrometers); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); // Calculates the XX element of a XYZ covariance matrix after rotation of the coordinate system by phi around the z-axis and by minus theta around the new y-axis. auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); @@ -726,7 +720,7 @@ struct HfCandidateCreatorDstarExpressions { // check wether the particle is non-promt (from a B0 hadron) if (flagDstar != 0) { - auto particleDstar = mcParticles.iteratorAt(indexRecDstar); + auto particleDstar = mcParticles.rawIteratorAt(indexRecDstar); originDstar = RecoDecay::getCharmHadronOrigin(mcParticles, particleDstar, false, &idxBhadMothers); } if (originDstar == RecoDecay::OriginType::NonPrompt) { diff --git a/PWGHF/TableProducer/candidateCreatorLb.cxx b/PWGHF/TableProducer/candidateCreatorLb.cxx index 3cc9716241e..eb741aacd95 100644 --- a/PWGHF/TableProducer/candidateCreatorLb.cxx +++ b/PWGHF/TableProducer/candidateCreatorLb.cxx @@ -80,8 +80,6 @@ struct HfCandidateCreatorLb { o2::vertexing::DCAFitterN<2> df2; // 2-prong vertex fitter o2::vertexing::DCAFitterN<3> df3; // 3-prong vertex fitter (to rebuild Lc vertex) - double massPi{0.}; - double massLc{0.}; double massLcPi{0.}; Filter filterSelectCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); @@ -99,9 +97,6 @@ struct HfCandidateCreatorLb { void init(InitContext const&) { - massPi = MassPiMinus; - massLc = MassLambdaCPlus; - df2.setBz(bz); df2.setPropagateToPCA(propagateToPCA); df2.setMaxR(maxR); @@ -215,7 +210,7 @@ struct HfCandidateCreatorLb { auto chi2PCA = df2.getChi2AtPCACandidate(); auto covMatrixPCA = df2.calcPCACovMatrixFlat(); - df2.propagateTracksToVertex(); + // get Lc and Pi tracks (propagated to the Lb vertex if propagateToPCA==true) df2.getTrack(0).getPxPyPzGlo(pvecLc); df2.getTrack(1).getPxPyPzGlo(pvecPion); @@ -230,7 +225,7 @@ struct HfCandidateCreatorLb { hCovPVXX->Fill(covMatrixPV[0]); // get uncertainty of the decay length - double phi, theta; + double phi{}, theta{}; getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexLb, 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.)); @@ -248,7 +243,7 @@ struct HfCandidateCreatorLb { rowCandidateProngs(lcCand.globalIndex(), trackPion.globalIndex()); // calculate invariant mass auto arrayMomenta = std::array{pvecLc, pvecPion}; - massLcPi = RecoDecay::m(arrayMomenta, std::array{massLc, massPi}); + massLcPi = RecoDecay::m(arrayMomenta, std::array{MassLambdaCPlus, MassPiMinus}); if (lcCand.isSelLcToPKPi() > 0) { hMassLbToLcPi->Fill(massLcPi); } diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index c482eb702f9..072d7dcf530 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -19,6 +19,7 @@ #include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/Utils/utilsSigmac.h" #include "PWGHF/DataModel/AliasTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -83,8 +84,10 @@ struct HfCandidateCreatorSigmac0plusplus { /// 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 softPiPtMin{"softPiPtMin", 0.1f, "Soft pion min value for pt (GeV/c)"}; 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 softPiApplyCustomITSHitMap{"softPiApplyCustomITSHitMap", true, "Flag to enable/disable the application of the custom ITS hitmap requirement for the candidate soft pion"}; 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)"}; @@ -101,7 +104,7 @@ struct HfCandidateCreatorSigmac0plusplus { TrackSelection softPiCuts; // Needed for dcaXY, dcaZ recalculation of soft pions reassigned to a new collision - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber{}; @@ -156,7 +159,7 @@ struct HfCandidateCreatorSigmac0plusplus { } // kinematics - // softPiCuts.SetPtRange(0.001, 1000.); // pt + softPiCuts.SetPtRange(softPiPtMin, 1e10f); // pt softPiCuts.SetEtaRange(-softPiEtaMax, softPiEtaMax); // eta // softPiCuts.SetMaxDcaXY(softPiDcaXYMax); // dcaXY // softPiCuts.SetMaxDcaZ(softPiDcaZMax); // dcaZ @@ -164,22 +167,24 @@ struct HfCandidateCreatorSigmac0plusplus { // ITS chi2 softPiCuts.SetMaxChi2PerClusterITS(softPiChi2Max); // ITS hitmap - std::set setSoftPiItsHitMap; // = {}; - constexpr std::size_t NLayersIts = 7; - for (std::size_t idItsLayer = 0u; idItsLayer < NLayersIts; idItsLayer++) { - if (TESTBIT(softPiItsHitMap, idItsLayer)) { - setSoftPiItsHitMap.insert(static_cast(idItsLayer)); + if (softPiApplyCustomITSHitMap) { + std::set setSoftPiItsHitMap; // = {}; + constexpr std::size_t NLayersIts = 7; + for (std::size_t idItsLayer = 0u; idItsLayer < NLayersIts; idItsLayer++) { + if (TESTBIT(softPiItsHitMap, idItsLayer)) { + setSoftPiItsHitMap.insert(static_cast(idItsLayer)); + } } + LOG(info) << "### ITS hitmap for soft pion"; + LOG(info) << " >>> setSoftPiItsHitMap.size(): " << setSoftPiItsHitMap.size(); + LOG(info) << " >>> Custom ITS hitmap dfchecked: "; + for (const auto& it : setSoftPiItsHitMap) { + LOG(info) << " Layer " << static_cast(it) << " "; + } + LOG(info) << "############"; + softPiCuts.SetRequireITSRefit(); + softPiCuts.SetRequireHitsInITSLayers(softPiItsHitsMin, setSoftPiItsHitMap); } - LOG(info) << "### ITS hitmap for soft pion"; - LOG(info) << " >>> setSoftPiItsHitMap.size(): " << setSoftPiItsHitMap.size(); - LOG(info) << " >>> Custom ITS hitmap dfchecked: "; - for (const auto it : setSoftPiItsHitMap) { - LOG(info) << " Layer " << static_cast(it) << " "; - } - LOG(info) << "############"; - softPiCuts.SetRequireITSRefit(); - softPiCuts.SetRequireHitsInITSLayers(softPiItsHitsMin, setSoftPiItsHitMap); /// CCDB for dcaXY, dcaZ recalculation of soft pions reassigned to another collision ccdb->setURL(ccdbUrl); @@ -224,10 +229,10 @@ struct HfCandidateCreatorSigmac0plusplus { mPiKPCandLcMax = cutsMassLcMax->get(pTBin, "max piKp mass Lc"); } - if (candLc.isSelLcToPKPi() >= 1 && std::abs(HfHelper::invMassLcToPKPi(candLc) - MassLambdaCPlus) <= mPKPiCandLcMax) { + if (candLc.isSelLcToPKPi() >= 1 && std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPKPi(candLc)) <= mPKPiCandLcMax) { statusSpreadMinvPKPiFromPDG = 1; } - if (candLc.isSelLcToPiKP() >= 1 && std::abs(HfHelper::invMassLcToPiKP(candLc) - MassLambdaCPlus) <= mPiKPCandLcMax) { + if (candLc.isSelLcToPiKP() >= 1 && std::abs(o2::hf_sigmac_utils::massDiffFromPdgLcToPiKP(candLc)) <= mPiKPCandLcMax) { statusSpreadMinvPiKPFromPDG = 1; } if (statusSpreadMinvPKPiFromPDG == 0 && statusSpreadMinvPiKPFromPDG == 0) { diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index b4e2e3f0aa4..b2f6980d93f 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -105,7 +106,7 @@ struct HfCandidateCreatorXic0Omegac0 { Produces rowKfXic0Qa; Produces kfCandidateOmegaKaData; - Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; 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"}; Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; @@ -114,7 +115,6 @@ struct HfCandidateCreatorXic0Omegac0 { 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 maxChi2{"maxChi2", 100., "discard vertices with chi2/Nprongs > this (or sum{DCAi^2}/Nprongs for abs. distance minimization)"}; - Configurable refitWithMatCorr{"refitWithMatCorr", true, "when doing propagateTracksToVertex, propagate tracks to vtx with material corrections and rerun minimization"}; Configurable rejDiffCollTrack{"rejDiffCollTrack", true, "Reject tracks coming from different collisions"}; Configurable fillAllHist{"fillAllHist", true, "Fill additional KF histograms to check selector cuts"}; Configurable doCascadePreselection{"doCascadePreselection", true, "Use invariant mass and dcaXY cuts to preselect cascade candidates"}; @@ -143,7 +143,8 @@ struct HfCandidateCreatorXic0Omegac0 { HfEventSelection hfEvSel; // event selection and monitoring o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter to build the omegac/xic vertex - Service ccdb; + Service ccdb{}; + Service pdgdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber{-1}; @@ -377,7 +378,6 @@ struct HfCandidateCreatorXic0Omegac0 { df.setMaxChi2(maxChi2); df.setUseAbsDCA(useAbsDCA); df.setWeightedFinalPCA(useWeightedFinalPCA); - df.setRefitWithMatCorr(refitWithMatCorr); ccdb->setURL(ccdbUrl); ccdb->setCaching(true); @@ -545,10 +545,6 @@ struct HfCandidateCreatorXic0Omegac0 { auto vertexCharmBaryonFromFitter = df.getPCACandidate(); std::array pVecCascAsD{}; std::array pVecCharmBachelorAsD{}; - df.propagateTracksToVertex(); - if (!df.isPropagateTracksToVertexDone()) { - continue; - } df.getTrack(0).getPxPyPzGlo(pVecCascAsD); df.getTrack(1).getPxPyPzGlo(pVecCharmBachelorAsD); std::array pVecCharmBaryon = {pVecCascAsD[0] + pVecCharmBachelorAsD[0], pVecCascAsD[1] + pVecCharmBachelorAsD[1], pVecCascAsD[2] + pVecCharmBachelorAsD[2]}; @@ -619,7 +615,7 @@ struct HfCandidateCreatorXic0Omegac0 { float const decLenCascade = RecoDecay::distance(coordVtxCharmBaryon, vertexCasc); float const decLenV0 = RecoDecay::distance(vertexCasc, vertexV0); - double phiCharmBaryon, thetaCharmBaryon; + double phiCharmBaryon{}, thetaCharmBaryon{}; getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, coordVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon); auto errorDecayLengthCharmBaryon = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiCharmBaryon, thetaCharmBaryon) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon)); auto errorDecayLengthXYCharmBaryon = std::sqrt(getRotatedCovMatrixXX(primaryVertex.getCov(), phiCharmBaryon, 0.) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, 0.)); @@ -846,7 +842,7 @@ struct HfCandidateCreatorXic0Omegac0 { } // mass window cut on lambda before mass constraint - float massLam, sigLam; + float massLam{}, sigLam{}; kfV0.GetMass(massLam, sigLam); if (std::abs(massLam - MassLambda0) > lambdaMassWindow) { continue; @@ -879,8 +875,8 @@ struct HfCandidateCreatorXic0Omegac0 { LOG(debug) << "Failed to construct Omega or Omega_rej from V0 and bachelor track: " << e.what(); continue; } - float massCasc, sigCasc; - float massCascrej, sigCascrej; + float massCasc{}, sigCasc{}; + float massCascrej{}, sigCascrej{}; kfOmega.GetMass(massCasc, sigCasc); kfOmegarej.GetMass(massCascrej, sigCascrej); // rej // err_massOmega > 0 @@ -920,7 +916,7 @@ struct HfCandidateCreatorXic0Omegac0 { LOG(debug) << "Failed to construct OmegaC0 from Cascade and bachelor pion track: " << e.what(); continue; } - float massOmegaC0, sigOmegaC0; + float massOmegaC0{}, sigOmegaC0{}; kfOmegaC0.GetMass(massOmegaC0, sigOmegaC0); if (sigOmegaC0 <= 0) { continue; @@ -1034,7 +1030,7 @@ struct HfCandidateCreatorXic0Omegac0 { float const decLenCascade = RecoDecay::distance(coordVtxCharmBaryon, vertexCasc); float const decLenV0 = RecoDecay::distance(vertexCasc, vertexV0); - double phiCharmBaryon, thetaCharmBaryon; + 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.)); @@ -1124,7 +1120,7 @@ struct HfCandidateCreatorXic0Omegac0 { kfOmegac0Candidate.rapOmegac = kfOmegaC0.GetRapidity(); // KF cosThetaStar - kfOmegac0Candidate.cosThetaStarPiFromOmegac = cosThetaStarFromKF(0, 4332, 211, 3312, kfBachPionToOmegaC, kfOmegaToOmegaC); + kfOmegac0Candidate.cosThetaStarPiFromOmegac = cosThetaStarFromKF(0, 4332, 211, 3312, kfBachPionToOmegaC, kfOmegaToOmegaC, pdgdb); // KF ct kfOmegac0Candidate.ctV0 = kfV0.GetLifeTime(); @@ -1588,7 +1584,7 @@ struct HfCandidateCreatorXic0Omegac0 { kfXic0Candidate.rapXic = kfXiC0.GetRapidity(); // KF cosThetaStar - kfXic0Candidate.cosThetaStarPiFromXic = cosThetaStarFromKF(0, 4132, 211, 3312, kfCharmBachPionToXiC, kfXiToXiC); + kfXic0Candidate.cosThetaStarPiFromXic = cosThetaStarFromKF(0, 4132, 211, 3312, kfCharmBachPionToXiC, kfXiToXiC, pdgdb); // KF ct kfXic0Candidate.ctV0 = kfV0ToCasc.GetLifeTime(); @@ -1950,8 +1946,8 @@ struct HfCandidateCreatorXic0Omegac0 { float const ptOmega = kfOmega.GetPt(); // KF cosThetaStar - float const cosThetaStarKaFromOmegac = cosThetaStarFromKF(0, 4332, 321, 3334, kfKaFromCharmToOmegaKa, kfOmegaToOmegaKa); - float const cosThetaStarKaFromXic = cosThetaStarFromKF(0, 4132, 321, 3334, kfKaFromCharmToOmegaKa, kfOmegaToOmegaKa); + float const cosThetaStarKaFromOmegac = cosThetaStarFromKF(0, 4332, 321, 3334, kfKaFromCharmToOmegaKa, kfOmegaToOmegaKa, pdgdb); + float const cosThetaStarKaFromXic = cosThetaStarFromKF(0, 4132, 321, 3334, kfKaFromCharmToOmegaKa, kfOmegaToOmegaKa, pdgdb); // KF ct float const ctV0 = kfV0ToOmega.GetLifeTime(); diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx new file mode 100644 index 00000000000..0be6fe96bc5 --- /dev/null +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0Qa.cxx @@ -0,0 +1,2172 @@ +// 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 candidateCreatorXic0Omegac0Qa.cxx +/// \brief Reconstruction of Xic0 and Xicp candiates with hadronic decay chain +/// +/// \author Jinhyun Park , Pusan National University +/// \author Krista Smith , Pusan National University + +#ifndef HomogeneousField +#define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) +#endif + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannelsLegacy.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/strangenessBuilderHelper.h" // -> Added to test removal of strangeness builder workflow + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Tools/KFparticle/KFUtilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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_occupancy; +using namespace o2::constants::physics; +using namespace o2::hf_evsel; + +struct HfCandidateCreatorXic0Omegac0Qa { + + // Cursor to fill tables + struct : ProducesGroup { + // Candidates created with DCAFitter + Produces rowCandToXiPi; + Produces rowCandToOmegaPi; + Produces rowCandToOmegaKa; + // Candidate created with KFParticle + Produces rowCandToXiPiKf; + Produces rowCandToOmegaPiKf; + Produces rowCandToOmegaKaKf; + } cursors; + + // Configurables + struct : ConfigurableGroup { + + // Options for internal cascade building - DCAFitter settings + // ...Initial vaules taken from PWGLF/Utils/strangenessBuilderHelper + // ---------------------------------------------------------------- + Configurable propagateToPCALF{"propagateToPCALF", true, "Create tracks version propagated to PCA"}; + Configurable maxRLF{"maxRLF", 200., "Reject PCA's above this radius"}; + Configurable maxDZIniLF{"maxDZIniLF", 1e9, "Reject (if>0) PCA candidate if tracks DZ exceeds this threshold"}; + Configurable maxDXYIniLF{"maxDXYIniLF", 4.0f, "Reject (if>0) PCA candidate if tracks DXY exceeds this threshold"}; + Configurable minParamChangeLF{"minParamChangeLF", 1.e-3, "Stop iteration if largest change of any X is smaller than this"}; + Configurable minRelChi2ChangeLF{"minRelChi2ChangeLF", 0.9, "Stop iteration if Chi2/Chi2old > this"}; + Configurable maxChi2LF{"maxChi2LF", 1e9, "Discard vertices with Chi2/Nprongs > this(or sum {DCAi^2}/Nprongs for abs. distance minimization)"}; + Configurable useAbsDCALF{"useAbsDCALF", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCALF{"useWeightedFinalPCALF", false, "Recalculate vertex position using track covariance, effective only if useAbsDCA is true"}; + Configurable refitWithMaterialCorrectionLF{"refitWithMaterialCorrectionLF", false, "Do refit after material correction applied"}; + + // Options for internal V0 building + // ...Initial values taken from PWGLF/Utiles/strangenessBuilderModule.h + // ...Modified according to the configurable in core wagon + // --------------------------------------------------------------------- + Configurable minCrossedRowsFromLF{"minCrossedRowsFromLF", 50, "minimun TPC crossed rows for daughter tracks. Used for internal V0 Building"}; + Configurable dcanegtopvFromLF{"dcanegtopvFromLF", .1, "DCV Neg to PV"}; + Configurable dcapostopvFromLF{"dcapostopvFromLF", .1, "DCV Pos To PV"}; + Configurable v0cospaFromLF{"v0cospaFromLF", 0.95, "V0 CosPA"}; + Configurable dcav0dauFromLF{"dcav0dauFromLF", 1.0, "DCA V0 Daughters"}; + Configurable v0radiusFromLF{"v0radiusFromLF", 0.9, "v0radius"}; + Configurable maxDaughterEtaFromLF{"maxDaughterEtaFromLF", 5.0, "Maximun daughter eta (in abs value)"}; + + // Options for internal cascade building + // ...Initial values taken from PWGLF/Utiles/strangenessBuilderModule.h + // ...Modified according to the configurable in core wagon + // -------------------------------------------------------------------- + Configurable dcabachtopvFromLF{"dcabachtopvFromLF", .05, "DCV Bach to PV"}; + Configurable cascradiusFromLF{"cascradiusFromLF", .9, "DCV Bach to PV"}; + Configurable casccospaFromLF{"casccospaFromLF", 0.95, "Cascade CosPA"}; + Configurable dcacascdauFromLF{"dcacascdauFromLF", 1.0, "DCA cascade daughters"}; + Configurable lambdaMassWindowFromLF{"lambdaMassWindowFromLF", 0.01, "Distance from Lambda mass(does not apply to KF path)"}; + + // Options for internal cascade building - KF Building specifics + // ...Initial values taken from PWGLF/Utiles/strangenessBuilderModule.h + // -------------------------------------------------------------------- + Configurable kfTuneForOmegaFromLF{"kfTuneForOmegaFromLF", false, "if enabled, take main cascade properties from omega fit instread of Xi fit(=default)"}; + Configurable kfConstructMethodFromLF{"kfConstructMethodFromLF", 2, "2 : Daughter particle masses stay fixed in construction process"}; + Configurable kfUseV0MassConstraintFromLF{"kfUseV0MassConstraintFromLF", true, "KF : Use Lambda mass constraint"}; + Configurable kfUseCascadeMassConstraintFromLF{"kfUseCascadeMassConstraintFromLF", false, "KF : Use Cascade mass constraint - WARNING : Not adequate for inv mass analysis of Xi"}; + Configurable kfDoDCAFitterPreMinimV0FromLF{"kfDoDCAFitterPreMinimV0FromLF", true, "KF : do DCAFitter pre-optimization before KF fit to include material correction for V0"}; + Configurable kfDoDCAFitterPreMinimCascFromLF{"kfDoDCAFitterPreMinimCascFromLF", false, "KF : do DCAFitter pre-optimization before KF fit to include material correction for Xi"}; + } LFConfigs; + + // For cascade building using LF strangeness builder + o2::pwglf::strangenessBuilderHelper straHelper; + + // Configurables + struct : ConfigurableGroup { + // Switch for filling histograms + // ----------------------------- + Configurable fillHistograms{"fillHistograms", true, "fill validation plots"}; + + // Magnetic field setting from CCDB + // -------------------------------- + Configurable isRun2{"isRun2", false, "enable Run2 or Run3 GRP objects for magnetic field"}; + Configurable ccdbUrl{"ccdbUrl", "https://alice-ccdb.cern.ch", "url of the ccdb object"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parameterization"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "path of the group file (Run2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run3)"}; + + // Cascade pre selection + // --------------------- + Configurable doCascadePreselection{"doCascadePreselection", true, "Use invariant mass and dcaXY cuts to preselect cascade candidates"}; + Configurable massToleranceCascade{"massToleranceCascade", 0.01, "Invariant mass tolerance for cascades"}; + Configurable dcaXYToPVCascadeMax{"dcaXYToPVCascadeMax", 3, "Max cascade DCA to PV in XY plane"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 1.0, "Max DCA of V0 daughter"}; + Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 1.0, "Max DCA of cascade daughter"}; + + // Options for 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 this threshold"}; + Configurable maxDXYIni{"maxDXYIni", 4., "Reject (if>0) PCA candidate if tracks DXY exceeds this threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "Stop iteration if largest change of any X is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "Stop iteration if Chi2/Chi2old > this"}; + Configurable maxChi2{"maxChi2", 100, "Discard vertices with Chi2/Nprongs > this(or sum {DCAi^2}/Nprongs for abs. distance minimization)"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", true, "Recalculate vertex position using track covariance, effective only if useAbsDCA is true"}; + + // Options for KFParticle + // ---------------------- + // V0 cuts + Configurable lambdaMassWindow{"lambdaMassWindow", 0.0075, "Distance from LambdaMass"}; + // 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 lambda mass constraint"}; + + // Options for QA histogram binning + // ----------------------------- + // For Cascade + Configurable nBinMassCasc{"nBinMassCasc", 1000, "nBinCascMass"}; + Configurable minMassCasc{"minMassCasc", 1.0, "xiMassMin"}; + Configurable maxMassCasc{"maxMassCasc", 2.0, "xiMassMax"}; + Configurable nBinPtCasc{"nBinPtCasc", 100, "nBinPtXi"}; + Configurable minPtCasc{"minPtCasc", 0.0, "minimun value of cascade"}; + Configurable maxPtCasc{"maxPtCasc", 20.0, "maximum value of cascade"}; + + // For Prong0 + Configurable nBinMassProng0{"nBinMassProng0", 100, "nBinMassPi"}; + Configurable minMassProng0{"minMassProng0", 0.0, "ptPiMin"}; + Configurable maxMassProng0{"maxMassProng0", 20.0, "ptPiMax"}; + Configurable nBinPtProng0{"nBinPtProng0", 100, "nBinPtProng0"}; + Configurable minPtProng0{"minPtProng0", 0.0, "ptPiMin"}; + Configurable maxPtProng0{"maxPtProng0", 20.0, "ptPiMax"}; + + // For Charm Baryon + Configurable nBinMassCharmBaryon{"nBinMassCharmBaryon", 3000, "nBinXic0Mass"}; + Configurable minMassCharmBaryon{"minMassCharmBaryon", 1.0, "xic0MassMin"}; + Configurable maxMassCharmBaryon{"maxMassCharmBaryon", 4.0, "xic0MassMax"}; + Configurable nBinPtCharmBaryon{"nBinPtCharmBaryon", 100, "nBinXic0Pt"}; + Configurable minPtCharmBaryon{"minPtCharmBaryon", 0.0, "xic0PtMin"}; + Configurable maxPtCharmBaryon{"maxPtCharmBaryon", 20.0, "xic0PtMax"}; + + // Etc + Configurable nBinCpa2Prong{"nBinCpa2Prong", 240, "nBinCpa2Prong"}; + Configurable cpa2ProngMin{"cpa2ProngMin", -1.2, "cpa2ProngMin"}; + Configurable cpa2ProngMax{"cpa2ProngMax", 1.2, "cpa2ProngMax"}; + Configurable nBinImpParXYXi{"nBinImpParXYXi", 30, "nBinImpParXYXi"}; + Configurable impParXYXiMin{"impParXYXiMin", -1.5, "impParXYXiMin"}; + Configurable impParXYXiMax{"impParXYXiMax", 1.5, "impParXYXiMax"}; + Configurable nBinImpParXYPi{"nBinImpParXYPi", 30, "nBinImpParXYPi"}; + Configurable impParXYPiMin{"impParXYPiMin", -1.5, "impParXYPiMin"}; + Configurable impParXYPiMax{"impParXYPiMax", 1.5, "impParXYPiMax"}; + } configs; + + Service ccdb{}; + Service pdgdb{}; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + // DCAFitter + o2::vertexing::DCAFitterN<2> df; + + int runNumber{0}; + double magneticField{0.}; + + enum CharmBaryonCandCounter { All = 0, + HfFlagPass, + CascReconstructed, + VertexFit }; + + // Table aliases + using SelectedCollisions = soa::Join; + using TracksWCovIU = soa::Join; + using TracksWCovDcaExtraPidPrPiKa = soa::Join; + using TracksWCovExtraPidIU = soa::Join; + + HistogramRegistry registry{"hists"}; + OutputObj zorroSummary{"zorroSummary"}; + HfEventSelection hfEvSel; + + // PDG Id of daughter tracks & V0s & cascades & charm baryons - Used in KFParticle + int pdgIdOfV0DauPos, pdgIdOfV0DauNeg, pdgIdOfBach, pdgIdOfCharmBach; + int pdgIdOfAntiV0DauPos, pdgIdOfAntiV0DauNeg, pdgIdOfAntiBach, pdgIdOfAntiCharmBach; + int pdgIdOfV0, pdgIdOfCascade, pdgIdOfCharmBaryon; + + // Track PID - Used in DCAFitter + int trackPidOfCascade; + + // Mass of daughter tracks & V0s & cascades & charm baryons; + float massOfV0DauPos, massOfV0DauNeg, massOfBach, massOfCharmBach; + float massOfV0, massOfCascade, massOfCharmBaryon; + + // Pointer of histograms for QA + std::shared_ptr hInvMassCharmBaryonToXiPi, hInvMassCharmBaryonToOmegaPi, hInvMassCharmBaryonToOmegaKa; + std::shared_ptr hCandidateCounterToXiPi, hCandidateCounterToOmegaPi, hCandidateCounterToOmegaKa; + + void init(InitContext const&) + { + std::vector processesToXiPiDca{doprocessToXiPiWithDCAFitterNoCent, /*doprocessToXiPiWithDCAFitterNoCentWithTrackedCasc,*/ doprocessToXiPiWithDCAFitterCentFT0C, doprocessToXiPiWithDCAFitterCentFT0M}; + std::vector processesToOmegaPiDca{doprocessToOmegaPiWithDCAFitterNoCent, doprocessToOmegaPiWithDCAFitterCentFT0C, doprocessToOmegaPiWithDCAFitterCentFT0M}; + std::vector processesToOmegaKaDca{doprocessToOmegaKaWithDCAFitterNoCent, doprocessToOmegaKaWithDCAFitterCentFT0C, doprocessToOmegaKaWithDCAFitterCentFT0M}; + std::vector processesToXiPiKf{doprocessToXiPiWithKFParticleNoCent, doprocessToXiPiWithKFParticleCentFT0C, doprocessToXiPiWithKFParticleCentFT0M}; + std::vector processesToOmegaPiKf{doprocessToOmegaPiWithKFParticleNoCent, doprocessToOmegaPiWithKFParticleCentFT0C, doprocessToOmegaPiWithKFParticleCentFT0M}; + std::vector processesToOmegaKaKf{doprocessToOmegaKaWithKFParticleNoCent, doprocessToOmegaKaWithKFParticleCentFT0C, doprocessToOmegaKaWithKFParticleCentFT0M}; + std::vector processesCollMonitoring{doprocessCollisionsNoCent, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M}; + + int xipiEnabledDca = std::accumulate(processesToXiPiDca.begin(), processesToXiPiDca.end(), 0); + int xipiEnabledKf = std::accumulate(processesToXiPiKf.begin(), processesToXiPiKf.end(), 0); + int omegapiEnabledDca = std::accumulate(processesToOmegaPiDca.begin(), processesToOmegaPiDca.end(), 0); + int omegapiEnabledKf = std::accumulate(processesToOmegaPiKf.begin(), processesToOmegaPiKf.end(), 0); + int omegakaEnabledDca = std::accumulate(processesToOmegaKaDca.begin(), processesToOmegaKaDca.end(), 0); + int omegakaEnabledKf = std::accumulate(processesToOmegaKaKf.begin(), processesToOmegaKaKf.end(), 0); + + // Exit if workflow is not configured correctly - More than one process function enabled for candidate to XiPi + if ((xipiEnabledDca > 0) && (xipiEnabledKf > 0)) { + LOGP(fatal, "More than one process function enabled for candidte decaying to xi pi"); + } + + // Exit if workflow is not configured correctly - More than one process function enabled for candidate to OmegaPi + if ((omegapiEnabledDca > 0) && (omegapiEnabledKf > 0)) { + LOGP(fatal, "More than one process function enabled for candidte decaying to omega pi"); + } + + // Exit if workflow is not configured correctly - More than one process function enabled for candidate to OmegaKa + if ((omegakaEnabledDca > 0) && (omegakaEnabledKf > 0)) { + LOGP(fatal, "More than one process function enabled for candidte decaying to omega ka"); + } + + // Exit if workflow is not configured correctly - More than one process enabled for collision monitoring + if (std::accumulate(processesCollMonitoring.begin(), processesCollMonitoring.end(), 0) > 1) { + LOGP(fatal, "More than one process fucntion for CollMonitoring was enabled. Please choose only one process function"); + } + + // Assign pdg & mass hypothesis for each decay channel + if (xipiEnabledDca > 0 || xipiEnabledKf > 0) { + pdgIdOfV0DauPos = kProton; + pdgIdOfV0DauNeg = kPiMinus; + pdgIdOfBach = kPiMinus; + pdgIdOfCharmBach = kPiPlus; + + pdgIdOfAntiV0DauPos = kPiPlus; + pdgIdOfAntiV0DauNeg = kProton; + pdgIdOfAntiBach = kPiPlus; + pdgIdOfAntiCharmBach = kPiMinus; + + pdgIdOfV0 = kLambda0; + pdgIdOfCascade = kXiMinus; + pdgIdOfCharmBaryon = kXiC0; + + trackPidOfCascade = o2::track::PID::XiMinus; + + massOfCharmBach = o2::constants::physics::MassPiPlus; + massOfV0DauPos = o2::constants::physics::MassProton; + massOfV0DauNeg = o2::constants::physics::MassPionCharged; + massOfV0 = o2::constants::physics::MassLambda; + massOfCascade = o2::constants::physics::MassXiMinus; + } else if (omegapiEnabledDca > 0 || omegapiEnabledKf > 0) { + pdgIdOfV0DauPos = kProton; + pdgIdOfV0DauNeg = kPiMinus; + pdgIdOfBach = kKMinus; + pdgIdOfCharmBach = kPiPlus; + + pdgIdOfAntiV0DauPos = kPiPlus; + pdgIdOfAntiV0DauNeg = kProton; + pdgIdOfAntiBach = kKPlus; + pdgIdOfAntiCharmBach = kPiMinus; + + pdgIdOfV0 = kLambda0; + pdgIdOfCascade = kOmegaMinus; + pdgIdOfCharmBaryon = kOmegaC0; + + trackPidOfCascade = o2::track::PID::OmegaMinus; + + massOfCharmBach = o2::constants::physics::MassPiPlus; + massOfV0DauPos = o2::constants::physics::MassProton; + massOfV0DauNeg = o2::constants::physics::MassPionCharged; + massOfV0 = o2::constants::physics::MassLambda; + massOfCascade = o2::constants::physics::MassOmegaMinus; + } else if (omegakaEnabledDca > 0 || omegakaEnabledKf > 0) { + pdgIdOfV0DauPos = kProton; + pdgIdOfV0DauNeg = kPiMinus; + pdgIdOfBach = kKMinus; + pdgIdOfCharmBach = kKPlus; + + pdgIdOfAntiV0DauPos = kPiPlus; + pdgIdOfAntiV0DauNeg = kProton; + pdgIdOfAntiBach = kKPlus; + pdgIdOfAntiCharmBach = kKMinus; + + pdgIdOfV0 = kLambda0; + pdgIdOfCascade = kOmegaMinus; + pdgIdOfCharmBaryon = kOmegaC0; + + trackPidOfCascade = o2::track::PID::OmegaMinus; + + massOfCharmBach = o2::constants::physics::MassKPlus; + massOfV0DauPos = o2::constants::physics::MassProton; + massOfV0DauNeg = o2::constants::physics::MassPionCharged; + massOfV0 = o2::constants::physics::MassLambda; + massOfCascade = o2::constants::physics::MassOmegaMinus; + } + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + LOGF(info, "PDG ID of V0 positive daughter: %d", pdgIdOfV0DauPos); + LOGF(info, "PDG ID of V0 negative daughter: %d", pdgIdOfV0DauNeg); + LOGF(info, "PDG ID of Bachelor: %d", pdgIdOfBach); + LOGF(info, "PDG ID of Charm Bachelor: %d", pdgIdOfCharmBach); + LOGF(info, "-------------------------------------------"); + LOGF(info, "PDG ID of anti V0 positive daughter: %d", pdgIdOfAntiV0DauPos); + LOGF(info, "PDG ID of anti V0 negative daughter: %d", pdgIdOfAntiV0DauNeg); + LOGF(info, "PDG ID of anti Bachelor: %d", pdgIdOfAntiBach); + LOGF(info, "PDG ID of anti Charm Bachelor: %d", pdgIdOfAntiCharmBach); + LOGF(info, "-------------------------------------------"); + LOGF(info, "PDG ID of V0: %d", pdgIdOfV0); + LOGF(info, "PDG ID of Cascade: %d", pdgIdOfCascade); + LOGF(info, "PDG ID of Charm Baryon: %d", pdgIdOfCharmBaryon); + LOGF(info, "-------------------------------------------"); + LOGF(info, "Mass of V0 set as: %f", massOfV0); + LOGF(info, "Mass of CharmBach set as: %f", massOfCharmBach); + LOGF(info, "Mass of Casc as: %f", massOfCascade); + LOGF(info, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + + // Add histogram to indicate which sv method was used + registry.add("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", {kTH1F, {{2, 0.0, 2.0}}}); + registry.get(HIST("hVertexerType"))->GetXaxis()->SetBinLabel(1 + aod::hf_cand::VertexerType::DCAFitter, "DCAFitter"); + registry.get(HIST("hVertexerType"))->GetXaxis()->SetBinLabel(1 + aod::hf_cand::VertexerType::KfParticle, "KFParticle"); + + // initialize ccdb + // --------------- + ccdb->setURL(configs.ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(configs.ccdbPathLut)); + straHelper.lut = lut; + runNumber = 0; + + // Initilization for strangeness builder helper + // -------------------------------------------- + + // Settings for internal V0 building + straHelper.v0selections.minCrossedRows = LFConfigs.minCrossedRowsFromLF; + straHelper.v0selections.dcanegtopv = LFConfigs.dcanegtopvFromLF; + straHelper.v0selections.dcapostopv = LFConfigs.dcapostopvFromLF; + straHelper.v0selections.v0cospa = LFConfigs.v0cospaFromLF; + straHelper.v0selections.dcav0dau = LFConfigs.dcav0dauFromLF; + straHelper.v0selections.v0radius = LFConfigs.v0radiusFromLF; + straHelper.v0selections.maxDaughterEta = LFConfigs.maxDaughterEtaFromLF; + + // Settings for internal Cascade building + straHelper.cascadeselections.minCrossedRows = LFConfigs.minCrossedRowsFromLF; + straHelper.cascadeselections.dcabachtopv = LFConfigs.dcabachtopvFromLF; + straHelper.cascadeselections.cascradius = LFConfigs.cascradiusFromLF; + straHelper.cascadeselections.casccospa = LFConfigs.casccospaFromLF; + straHelper.cascadeselections.dcacascdau = LFConfigs.dcacascdauFromLF; + straHelper.cascadeselections.lambdaMassWindow = LFConfigs.lambdaMassWindowFromLF; + straHelper.cascadeselections.maxDaughterEta = LFConfigs.maxDaughterEtaFromLF; + + // Fitter setting + straHelper.fitter.setPropagateToPCA(LFConfigs.propagateToPCALF); + straHelper.fitter.setMaxR(LFConfigs.maxRLF); + straHelper.fitter.setMaxDZIni(LFConfigs.maxDZIniLF); + straHelper.fitter.setMaxDXYIni(LFConfigs.maxDXYIniLF); + straHelper.fitter.setMinParamChange(LFConfigs.minParamChangeLF); + straHelper.fitter.setMinRelChi2Change(LFConfigs.minRelChi2ChangeLF); + straHelper.fitter.setMaxChi2(LFConfigs.maxChi2LF); + straHelper.fitter.setUseAbsDCA(LFConfigs.useAbsDCALF); + straHelper.fitter.setWeightedFinalPCA(LFConfigs.useWeightedFinalPCALF); + straHelper.fitter.setRefitWithMatCorr(LFConfigs.refitWithMaterialCorrectionLF); + + // Extra initialization for DCAFitter + // ---------------------------------- + if (xipiEnabledDca == 1 || omegapiEnabledDca == 1 || omegakaEnabledDca == 1) { + registry.get(HIST("hVertexerType"))->Fill(aod::hf_cand::VertexerType::DCAFitter); + df.setPropagateToPCA(configs.propagateToPCA); + df.setMaxR(configs.maxR); + df.setMaxDZIni(configs.maxDZIni); + df.setMaxDXYIni(configs.maxDXYIni); + df.setMinParamChange(configs.minParamChange); + df.setMinRelChi2Change(configs.minRelChi2Change); + df.setMaxChi2(configs.maxChi2); + df.setUseAbsDCA(configs.useAbsDCA); + df.setWeightedFinalPCA(configs.useWeightedFinalPCA); + } + + // Extra initialization for KFParticle + // ----------------------------------- + if (xipiEnabledKf == 1 || omegapiEnabledKf == 1 || omegakaEnabledKf == 1) { + registry.get(HIST("hVertexerType"))->Fill(aod::hf_cand::VertexerType::KfParticle); + } + + // initailize HF event selection helper + // ------------------------------------ + hfEvSel.init(registry, &zorroSummary); + + // Histograms for QA + // ----------------- + registry.add("ReconstructedDecayChannel", "DecyayChannel", {kTH1F, {{3, 0.0, 3.0}}}); + registry.get(HIST("ReconstructedDecayChannel"))->GetXaxis()->SetBinLabel(1 + hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi, "To #Xi #pi"); + registry.get(HIST("ReconstructedDecayChannel"))->GetXaxis()->SetBinLabel(1 + hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi, "To #Omega #pi"); + registry.get(HIST("ReconstructedDecayChannel"))->GetXaxis()->SetBinLabel(1 + hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK, "To #Omega K"); + + if (xipiEnabledDca != 0 || xipiEnabledKf != 0) { + hInvMassCharmBaryonToXiPi = registry.add("hInvMassCharmBaryonToXiPi", "Charm baryon invariant mass - #Xi #pi decay;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{configs.nBinMassCharmBaryon, configs.minMassCharmBaryon, configs.maxMassCharmBaryon}}}); + hCandidateCounterToXiPi = registry.add("hCandidateCounterToXiPi", "Candidate counter wrt derived data - #Xi #pi decay;status;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + All, "Total"); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + HfFlagPass, "HfFlagPass"); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + CascReconstructed, "CascReconstructed"); + registry.get(HIST("hCandidateCounterToXiPi"))->GetXaxis()->SetBinLabel(1 + VertexFit, "VertexFit"); + registry.get(HIST("ReconstructedDecayChannel"))->Fill(hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi); + } + + if (omegapiEnabledDca != 0 || omegapiEnabledKf != 0) { + hInvMassCharmBaryonToOmegaPi = registry.add("hInvMassCharmBaryonToOmegaPi", "Charm baryon invariant mass - #Omega #pi decay;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{configs.nBinMassCharmBaryon, configs.minMassCharmBaryon, configs.maxMassCharmBaryon}}}); + hCandidateCounterToOmegaPi = registry.add("hCandidateCounterToOmegaPi", "Candidate counter wrt derived data - #Omega #pi decay;status;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + All, "Total"); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + HfFlagPass, "HfFlagPass"); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + CascReconstructed, "CascReconstructed"); + registry.get(HIST("hCandidateCounterToOmegaPi"))->GetXaxis()->SetBinLabel(1 + VertexFit, "VertexFit"); + registry.get(HIST("ReconstructedDecayChannel"))->Fill(hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi); + } + + if (omegakaEnabledDca != 0 || omegakaEnabledKf != 0) { + hInvMassCharmBaryonToOmegaKa = registry.add("hInvMassCharmBaryonToOmegaKa", "Charm baryon invariant mass - #Omega K decay;inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{configs.nBinMassCharmBaryon, configs.minMassCharmBaryon, configs.maxMassCharmBaryon}}}); + hCandidateCounterToOmegaKa = registry.add("hCandidateCounterToOmegaKa", "Candidate counter wrt derived data - #Omega K decay;status;entries", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + All, "Total"); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + HfFlagPass, "HfFlagPass"); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + CascReconstructed, "CascReconstructed"); + registry.get(HIST("hCandidateCounterToOmegaKa"))->GetXaxis()->SetBinLabel(1 + VertexFit, "VertexFit"); + registry.get(HIST("ReconstructedDecayChannel"))->Fill(hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK); + } + + registry.add("hCascMass", "Inv mass of reconstructed cascade;Inv mass;Entries", {HistType::kTH1F, {{configs.nBinMassCasc, configs.minMassCasc, configs.maxMassCasc}}}); + registry.add("hCascPt", "Pt of reconstructed cascade;pT;Entries", {HistType::kTH1F, {{configs.nBinPtCasc, configs.minPtCasc, configs.maxPtCasc}}}); + + } // end of initialization + + //////////////////////////////////////////////////////////// + // // + // Candidate reconstruction with DCAFitter // + // // + //////////////////////////////////////////////////////////// + + // template function for running charm baryon reconstruction with DCAFitter + /// \brief centEstimator is for different centrality estimators + /// \brief decayChannel is for different decay channels. 0 for XiczeroOmegaczeroToXiPi, 1 for OmegaczeroToOmegaPi, 2 for OmegaczeroToOmeagaK + /// \brief Colls is for collision tables joined with different centraltiy estimators + /// \brief Hist is for QA histograms + template + void runCreatorWithDCAFitter(Colls const&, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const&, // -> Internal cascade building + aod::V0s const&, // -> Internal v0 building + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const&, + Hist& hInvMassCharmBaryon, + Hist& hCandCounter) + { + // arrays which holds values for different decay channel reconstruction + + // Loop over candidate + for (auto const& cand : candidates) { + + // Fill cascandidates before selection + if (configs.fillHistograms) { + hCandCounter->Fill(All); + } + + // Apply hfflag selection for different candidate reconstruction + if (!TESTBIT(cand.hfflag(), decayChannel)) { + continue; + } else { + if (configs.fillHistograms) { + hCandCounter->Fill(HfFlagPass); + } + } + + // Event selection + auto collision = cand.collision_as(); + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { // None of the event selection satisfied -> Reject this candidate + continue; + } + + //------------------------------Set Magnetic field------------------------------ + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>> Current run Number : " << runNumber; + initCCDB(bc, runNumber, ccdb, configs.isRun2 ? configs.ccdbPathGrp : configs.ccdbPathGrpMag, lut, configs.isRun2); + magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>> Magnetic field: " << magneticField; + runNumber = bc.runNumber(); + } + straHelper.fitter.setBz(magneticField); // -> Magnetic field setting for internal cascade building + df.setBz(magneticField); // -> Magnetic field setting for charm baryon building + + //------------------Intenal Cascade building------------------ + auto cascAodElement = cand.cascade_as(); + auto v0AodElement = cascAodElement.v0_as(); + auto posTrack = lfTracks.rawIteratorAt(v0AodElement.posTrackId()); + auto negTrack = lfTracks.rawIteratorAt(v0AodElement.negTrackId()); + auto bachTrack = lfTracks.rawIteratorAt(cascAodElement.bachelorId()); + + // Make cascade starting from V0 + // If success, fill Cascade and V0 information for reconstruction + if (!straHelper.buildCascadeCandidate(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + posTrack, + negTrack, + bachTrack, + false, // calculateBachelorBaryonVariable + false, // useCascadeMomentumAtPV + true)) { + continue; + } else { + float storeMass = (decayChannel == 0) ? straHelper.cascade.massXi : straHelper.cascade.massOmega; + float storePt = RecoDecay::pt(straHelper.cascade.cascadeMomentum); + registry.fill(HIST("hCascMass"), storeMass); + registry.fill(HIST("hCascPt"), storePt); + if (configs.fillHistograms) { + hCandCounter->Fill(CascReconstructed); + } + } + + //------------------------------Info of V0 and cascade------------------------------ + // V0 quantities from LF strangeness builder + std::array vertexV0 = {straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2]}; + std::array pVecV0DauPos = {straHelper.cascade.positiveMomentum[0], straHelper.cascade.positiveMomentum[1], straHelper.cascade.positiveMomentum[2]}; + std::array pVecV0DauNeg = {straHelper.cascade.negativeMomentum[0], straHelper.cascade.negativeMomentum[1], straHelper.cascade.negativeMomentum[2]}; + std::array pVecV0 = {pVecV0DauPos[0] + pVecV0DauNeg[0], pVecV0DauPos[1] + pVecV0DauNeg[1], pVecV0DauPos[2] + pVecV0DauNeg[2]}; + + // pseudo rapidity - V0 daughters + // float pseudorapV0Dau0 = RecoDecay::eta(pVecV0DauPos); + // float pseudorapV0Dau1 = RecoDecay::eta(pVecV0DauNeg); + + // Cascade quantities from LF strangeness builder + std::array vertexCasc = {straHelper.cascade.cascadePosition[0], straHelper.cascade.cascadePosition[1], straHelper.cascade.cascadePosition[2]}; + std::array const pVecCasc = {straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2]}; + std::array covCasc = {0.}; + constexpr int NumCovElement = 6; + constexpr int MomInd[NumCovElement] = {9, 13, 14, 18, 19, 20}; + for (int i = 0; i < NumCovElement; i++) { + covCasc[MomInd[i]] = straHelper.cascade.covariance[MomInd[i]]; + covCasc[i] = straHelper.cascade.covariance[i]; + } + + // pseudo rapidity - cascade bachelor + // float pseudorapCascBachelor = RecoDecay::eta(straHelper.cascade.bachelorMomentum); + + //------------------------------Create cascade track------------------------------ + + o2::track::TrackParCov trackCasc; + if (bachTrack.sign() < 0) { // Xi- or Omega- + trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, -1, true); + } else if (bachTrack.sign() > 0) { // Xi+ or Omega+ + trackCasc = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, 1, true); + } else { + continue; + } + + trackCasc.setAbsCharge(1); + trackCasc.setPID(trackPidOfCascade); + + //------------------------------Fit SV & Create Charm Baryon track------------------------------ + + // Perform secondary vertex fitting + auto trackCharmBachelor = tracks.rawIteratorAt(cand.prong0Id()); + auto trackParCovCharmBachelor = getTrackParCov(trackCharmBachelor); + try { + if (df.process(trackCasc, trackParCovCharmBachelor) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitter cannot work. Skipping this candidate"; + continue; + } + + if (configs.fillHistograms) { + hCandCounter->Fill(VertexFit); + } + + //------------------------------Calculate physical properties----------------------------- + + // get track momenta + std::array pVecCascAsD, pVecCharmBachAsD; + df.getTrack(0).getPxPyPzGlo(pVecCascAsD); + df.getTrack(1).getPxPyPzGlo(pVecCharmBachAsD); + + std::array pVecCharmBaryon = {pVecCascAsD[0] + pVecCharmBachAsD[0], pVecCascAsD[1] + pVecCharmBachAsD[1], pVecCascAsD[2] + pVecCharmBachAsD[2]}; + std::array pVecBach = {straHelper.cascade.bachelorMomentum[0], straHelper.cascade.bachelorMomentum[1], straHelper.cascade.bachelorMomentum[2]}; + + // get PV Properties + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + + // get SV Properties + auto const& secondaryVertex = df.getPCACandidate(); + auto covMatrixSV = df.calcPCACovMatrixFlat(); + + // DCAxy and DCAz. Computed with propagatToDCABxByBz method + auto trackParCovV0DauPos = getTrackParCov(posTrack); + auto trackParCovV0DauNeg = getTrackParCov(negTrack); + auto trackParCovBach = getTrackParCov(bachTrack); + + o2::dataformats::DCA impactParameterV0DauPos, impactParameterV0DauNeg, impactParameterBach; + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovV0DauPos, 2.f, matCorr, &impactParameterV0DauPos); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovV0DauNeg, 2.f, matCorr, &impactParameterV0DauNeg); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovBach, 2.f, matCorr, &impactParameterBach); + + float dcaxyV0DauPos = impactParameterV0DauPos.getY(); + float dcaxyV0DauNeg = impactParameterV0DauNeg.getY(); + float dcaxyBach = impactParameterBach.getY(); + float dcazV0DauPos = impactParameterV0DauPos.getZ(); + float dcazV0DauNeg = impactParameterV0DauNeg.getZ(); + float dcazBach = impactParameterBach.getZ(); + + // get impact parameter. Compute with propagateToDCABxByBz method + o2::dataformats::DCA impactParameterCasc, impactParameterCharmBach; + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackCasc, 2.f, matCorr, &impactParameterCasc); // trackCasc is TrackParCov object + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovCharmBachelor, 2.f, matCorr, &impactParameterCharmBach); + // float impactParCharmBachFromCharmBayonXY = impactParameterCharmBach.getY(); + // float impactParCharmBachFromCharmBayonZ = impactParameterCharmBach.getZ(); + + // get v0 invariant mass - from LF Table + float mLambda = RecoDecay::m(std::array{pVecV0DauPos, pVecV0DauNeg}, (straHelper.cascade.charge < 0) ? std::array{massOfV0DauPos, massOfV0DauNeg} : std::array{massOfV0DauNeg, massOfV0DauPos}); + + // get Casc mass - from LF Table + float mCasc = (decayChannel != hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) ? straHelper.cascade.massOmega : straHelper.cascade.massXi; + + // get Charm baryon invariant mass + float massCharmBaryonCand = RecoDecay::m(std::array{pVecCascAsD, pVecCharmBachAsD}, std::array{massOfCascade, massOfCharmBach}); + if (configs.fillHistograms) { + hInvMassCharmBaryon->Fill(massCharmBaryonCand); + } + + // calculate cosine of pointing angle + std::array vtxCoordCharmBaryon = df.getPCACandidatePos(); + float cpaV0 = RecoDecay::cpa(pvCoord, vertexV0, pVecV0); + float cpaCasc = RecoDecay::cpa(pvCoord, vertexCasc, pVecCasc); + float cpaCharmBaryon = RecoDecay::cpa(pvCoord, vtxCoordCharmBaryon, pVecCharmBaryon); + float cpaxyV0 = RecoDecay::cpaXY(pvCoord, vertexV0, pVecV0); + float cpaxyCasc = RecoDecay::cpaXY(pvCoord, vertexCasc, pVecCasc); + float cpaxyCharmBaryon = RecoDecay::cpaXY(pvCoord, vtxCoordCharmBaryon, pVecCharmBaryon); + + // calculate decay length + float decLenV0 = RecoDecay::distance(vertexCasc, vertexV0); + float decLenCasc = RecoDecay::distance(vtxCoordCharmBaryon, vertexCasc); + float decLenCharmBaryon = RecoDecay::distance(pvCoord, vtxCoordCharmBaryon); + float 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.)); + + // calcuate ctau + float ctV0 = RecoDecay::ct(pVecV0, decLenV0, MassLambda0); + float ctCasc = RecoDecay::ct(pVecCasc, decLenCasc, massOfCascade); + float ctOmegac0 = RecoDecay::ct(pVecCharmBaryon, decLenCharmBaryon, MassOmegaC0); + float ctXic0 = RecoDecay::ct(pVecCharmBaryon, decLenCharmBaryon, MassXiC0); + + // get eta + float etaV0DauPos = posTrack.eta(); + float etaV0DauNeg = negTrack.eta(); + float etaBach = bachTrack.eta(); + float etaCharmBach = trackCharmBachelor.eta(); + float etaV0 = RecoDecay::eta(pVecV0); + float etaCasc = RecoDecay::eta(pVecCasc); + float etaCharmBaryon = RecoDecay::eta(pVecCharmBaryon); + + // DCA between daughters + float dcaV0Dau = straHelper.cascade.v0DaughterDCA; + float dcaCascDau = straHelper.cascade.cascadeDaughterDCA; + float dcaCharmBaryonDau = std::sqrt(df.getChi2AtPCACandidate()); + + //------------------------------Fill QA histograms----------------------------- + + //------------------------------Fill the table----------------------------- + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + cursors.rowCandToXiPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covMatrixSV[0], covMatrixSV[1], covMatrixSV[2], covMatrixSV[3], covMatrixSV[4], covMatrixSV[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], + pVecCharmBachAsD[0], pVecCharmBachAsD[1], pVecCharmBachAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBach.getY(), + impactParameterCasc.getZ(), impactParameterCharmBach.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBach.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + mLambda, mCasc, massCharmBaryonCand, + cpaV0, cpaCharmBaryon, cpaCasc, + cpaxyV0, cpaxyCharmBaryon, cpaxyCasc, + ctOmegac0, ctCasc, ctV0, ctXic0, + etaV0DauPos, etaV0DauNeg, etaBach, etaCharmBach, etaCharmBaryon, etaCasc, etaV0, + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + dcaCascDau, dcaV0Dau, dcaCharmBaryonDau, + decLenCharmBaryon, decLenCasc, decLenV0, errorDecayLength, errorDecayLengthXY); + } else if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { + cursors.rowCandToOmegaPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covMatrixSV[0], covMatrixSV[1], covMatrixSV[2], covMatrixSV[3], covMatrixSV[4], covMatrixSV[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], + pVecCharmBachAsD[0], pVecCharmBachAsD[1], pVecCharmBachAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBach.getY(), + impactParameterCasc.getZ(), impactParameterCharmBach.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBach.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + mLambda, mCasc, massCharmBaryonCand, + cpaV0, cpaCharmBaryon, cpaCasc, + cpaxyV0, cpaxyCharmBaryon, cpaxyCasc, + ctOmegac0, ctCasc, ctV0, + etaV0DauPos, etaV0DauNeg, etaBach, etaCharmBach, etaCharmBaryon, etaCasc, etaV0, + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + dcaCascDau, dcaV0Dau, dcaCharmBaryonDau, + decLenCharmBaryon, decLenCasc, decLenV0, errorDecayLength, errorDecayLengthXY, cand.hfflag()); + } else { + cursors.rowCandToOmegaKa(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + secondaryVertex[0], secondaryVertex[1], secondaryVertex[2], + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covMatrixSV[0], covMatrixSV[1], covMatrixSV[2], covMatrixSV[3], covMatrixSV[4], covMatrixSV[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], + pVecCascAsD[0], pVecCascAsD[1], pVecCascAsD[2], + pVecCharmBachAsD[0], pVecCharmBachAsD[1], pVecCharmBachAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBach.getY(), + impactParameterCasc.getZ(), impactParameterCharmBach.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBach.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + mLambda, mCasc, massCharmBaryonCand, + cpaV0, cpaCharmBaryon, cpaCasc, + cpaxyV0, cpaxyCharmBaryon, cpaxyCasc, + ctOmegac0, ctCasc, ctV0, + etaV0DauPos, etaV0DauNeg, etaBach, etaCharmBach, etaCharmBaryon, etaCasc, etaV0, + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + dcaCascDau, dcaV0Dau, dcaCharmBaryonDau, + decLenCharmBaryon, decLenCasc, decLenV0, errorDecayLength, errorDecayLengthXY); + } + } // candidate loop + } // end of run function + + // template function for running Charm Baryon reconstruction via KFParticle method + /// \brief centEstimator is for different centrality estimators + /// \brief decayChannel is for different decay channels. 0 for XiczeroOmegaczeroToXiPi, 1 for OmegaczeroToOmegaPi, 2 for OmegaczeroToOmegaK + /// \brief Colls is for collision tables joined with different centrality estimators + /// \brief Hist is for QA histograms + template + void runCreatorWithKfParticle(Colls const&, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const&, // -> Implemented for internal cascade building + aod::V0s const&, // -> Implemented for internal cascade building + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const&, + Hist& hInvMassCharmBaryon, + Hist& hCandCounter) + { + // Loop over candidates + for (auto const& cand : candidates) { + + // Fill cascandidates before selection + if (configs.fillHistograms) { + hCandCounter->Fill(All); + } + + // Apply hfflag selection + if (!TESTBIT(cand.hfflag(), decayChannel)) { + continue; + } else { + if (configs.fillHistograms) { + hCandCounter->Fill(HfFlagPass); + } + } + + // Event selection + auto collision = cand.collision_as(); + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { // None of the event seletion satisfied -> Reject this candidate + continue; + } + + //------------------------------Set Magnetic field------------------------------ + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>> Current run Number : " << runNumber; + initCCDB(bc, runNumber, ccdb, configs.isRun2 ? configs.ccdbPathGrp : configs.ccdbPathGrpMag, lut, configs.isRun2); + magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>> Magnetic field: " << magneticField; + runNumber = bc.runNumber(); + } + // magnetic field setting for KFParticle + straHelper.fitter.setBz(magneticField); // -> Manetic field setting for internal cascade building + KFParticle::SetField(magneticField); // -> Magnetic field setting for CharmBaryon building + + //------------------Intenal Cascade building------------------ + auto cascAodElement = cand.cascade_as(); + auto v0AodElement = cascAodElement.v0_as(); + auto posTrack = lfTracks.rawIteratorAt(v0AodElement.posTrackId()); + auto negTrack = lfTracks.rawIteratorAt(v0AodElement.negTrackId()); + auto bachTrack = lfTracks.rawIteratorAt(cascAodElement.bachelorId()); + + // Make cascade starting from V0 + // If success, fill Cascade and V0 information for reconstruction + if (!straHelper.buildCascadeCandidateWithKF(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + posTrack, + negTrack, + bachTrack, + false, // calculateBachelorBaryonVariables + LFConfigs.kfConstructMethodFromLF, + LFConfigs.kfTuneForOmegaFromLF, + LFConfigs.kfUseV0MassConstraintFromLF, + LFConfigs.kfUseCascadeMassConstraintFromLF, + LFConfigs.kfDoDCAFitterPreMinimV0FromLF, + LFConfigs.kfDoDCAFitterPreMinimCascFromLF)) { + continue; + } else { + float storeMass = (decayChannel == 0) ? straHelper.cascade.massXi : straHelper.cascade.massOmega; + float storePt = RecoDecay::pt(straHelper.cascade.cascadeMomentum); + registry.fill(HIST("hCascMass"), storeMass); + registry.fill(HIST("hCascPt"), storePt); + if (configs.fillHistograms) { + hCandCounter->Fill(CascReconstructed); + } + } + + //------------------------------Cascade pre-selection------------------------------ + // ! only for Xic0, Omegac0 -> Omega K + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { + if (configs.doCascadePreselection) { + if (std::abs(straHelper.cascade.cascadeDCAxy) > configs.dcaXYToPVCascadeMax) { + continue; + } + // pre selection on dcaV0Daughters + if (std::abs(straHelper.cascade.v0DaughterDCA) > configs.dcaV0DaughtersMax) { + continue; + } + // pre selection on dcaCascDaughters + if (std::abs(straHelper.cascade.cascadeDaughterDCA) > configs.dcaCascDaughtersMax) { + continue; + } + // pre selection on invariantmass + if (std::abs(straHelper.cascade.massOmega - massOfCascade) > configs.massToleranceCascade) { + continue; + } + } + } + + //----------Create charm bayron as KF Partible object starting from V0---------- + + // Create KFParticle object of V0 Daughter & Bachelor + const KFPTrack kfTrack0 = createKFPTrackFromTrack(posTrack); + const KFPTrack kfTrack1 = createKFPTrackFromTrack(negTrack); + const KFPTrack kfTrackBach = createKFPTrackFromTrack(bachTrack); + + bool isAnti = (bachTrack.signed1Pt() > 0 ? true : false); + + KFParticle kfPos(kfTrack0, (isAnti ? pdgIdOfAntiV0DauPos : pdgIdOfV0DauPos)); + KFParticle kfNeg(kfTrack1, (isAnti ? pdgIdOfAntiV0DauNeg : pdgIdOfV0DauNeg)); + KFParticle kfBach(kfTrackBach, (isAnti ? pdgIdOfAntiBach : pdgIdOfBach)); + KFParticle kfBachRej(kfTrackBach, (isAnti ? pdgIdOfAntiBach : pdgIdOfBach)); // Rej -> Used for Omegac0->OmegaPi only + + // ~~~~~~~Construct V0 with KF~~~~~~~ + const KFParticle* v0Daughters[2] = {&kfPos, &kfNeg}; + KFParticle kfV0; + kfV0.SetConstructMethod(configs.kfConstructMethod); + try { + kfV0.Construct(v0Daughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct v0" << e.what(); + continue; + } + + // Require lambda pre-selection before mass constraint + float massLam, sigMassLam; + kfV0.GetMass(massLam, sigMassLam); + if (std::abs(massLam - MassLambda0) > configs.lambdaMassWindow) { + continue; + } + if (sigMassLam <= 0) { + continue; + } + if ((kfV0.GetNDF() <= 0) || (kfV0.GetChi2() <= 0)) { + continue; + } + + // Set mass constraint to lambda + KFParticle kfV0MassConstrained = kfV0; + kfV0MassConstrained.SetNonlinearMassConstraint(massOfV0); + if (configs.kfUseV0MassConstraint) { + kfV0 = kfV0MassConstrained; + } + kfV0.TransportToDecayVertex(); + + //~~~~~~~Construct cascade with KF~~~~~~~ + const KFParticle* cascDaughters[2] = {&kfBach, &kfV0}; + const KFParticle* cascDaughtersRej[2] = {&kfBachRej, &kfV0}; + KFParticle kfCasc, kfCascRej; + + kfCasc.SetConstructMethod(configs.kfConstructMethod); + try { + kfCasc.Construct(cascDaughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Cascade: " << e.what(); + continue; + } + + float massCasc, sigMassCasc, massCascRej, sigMassCascRej; + kfCasc.GetMass(massCasc, sigMassCasc); + + if (sigMassCasc <= 0) { + continue; + } + if (std::abs(massCasc - massOfCascade) > configs.massToleranceCascade) { + continue; + } + if (kfCasc.GetNDF() <= 0 || kfCasc.GetChi2() <= 0) { + continue; + } + + // perform cascade building on casc_rej - only for Omega + if constexpr (decayChannel != hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + kfCascRej.SetConstructMethod(configs.kfConstructMethod); + try { + kfCascRej.Construct(cascDaughtersRej, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Cascade_rej: " << e.what(); + continue; + } + + kfCascRej.GetMass(massCascRej, sigMassCascRej); + } + + // Set mass constraint to cascade + KFParticle kfCascMassConstrained = kfCasc; + kfCascMassConstrained.SetNonlinearMassConstraint(massOfCascade); + if (configs.kfUseCascadeMassConstraint) { + kfCasc = kfCascMassConstrained; + } + kfCasc.TransportToDecayVertex(); + + //~~~~~~~Construct Charm Baryon with KF~~~~~~~ + auto trackCharmBachelor = tracks.rawIteratorAt(cand.prong0Id()); + const KFPTrack kfTrackCharmBach = createKFPTrackFromTrack(trackCharmBachelor); + const KFParticle kfCharmBach(kfTrackCharmBach, (isAnti ? pdgIdOfAntiCharmBach : pdgIdOfCharmBach)); + const KFParticle* charmBaryonDaughters[2] = {&kfCharmBach, &kfCasc}; + + KFParticle kfCharmBaryon; + kfCharmBaryon.SetConstructMethod(configs.kfConstructMethod); + try { + kfCharmBaryon.Construct(charmBaryonDaughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Charm baryon: " << e.what(); + continue; + } + + float massCharmBaryon, sigMassCharmBaryon; + kfCharmBaryon.GetMass(massCharmBaryon, sigMassCharmBaryon); + if (sigMassCharmBaryon <= 0) { + continue; + } + if (kfCharmBaryon.GetNDF() <= 0 || kfCharmBaryon.GetChi2() <= 0) { + continue; + } + kfCharmBaryon.TransportToDecayVertex(); + if (configs.fillHistograms) { + hCandCounter->Fill(VertexFit); + hInvMassCharmBaryon->Fill(massCharmBaryon); + } + + // Set production vertex + // PV + const KFPVertex kfVertex = createKFPVertexFromCollision(collision); + const KFParticle kfPv(kfVertex); + const KFParticle kfPosOrigin = kfPos; + const KFParticle kfNegOrigin = kfNeg; + + // To V0 + kfPos.SetProductionVertex(kfV0); + kfNeg.SetProductionVertex(kfV0); + + // To Casc + KFParticle kfBachToCasc = kfBach; + KFParticle kfV0ToCasc = kfV0; + kfBachToCasc.SetProductionVertex(kfCasc); + kfV0ToCasc.SetProductionVertex(kfCasc); + + // To Charm baryon + KFParticle kfCascToCharmBaryon = kfCasc; + KFParticle kfCharmBachToCharmBaryon = kfCharmBach; + kfCascToCharmBaryon.SetProductionVertex(kfCharmBaryon); + kfCharmBachToCharmBaryon.SetProductionVertex(kfCharmBaryon); + + // To Pv + KFParticle kfV0ToPv = kfV0; + KFParticle kfCascToPv = kfCasc; + KFParticle kfCharmBachToPv = kfCharmBach; + KFParticle kfCharmBaryonToPv = kfCharmBaryon; + kfV0ToPv.SetProductionVertex(kfPv); + kfCascToPv.SetProductionVertex(kfPv); + kfCharmBachToPv.SetProductionVertex(kfPv); + kfCharmBaryonToPv.SetProductionVertex(kfPv); + + //----------Reconstruct information after vertex fit---------- + std::array vertexV0 = {kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}; + std::array vertexCasc = {kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}; + + std::array pVecV0DauPos = {kfPos.GetPx(), kfPos.GetPy(), kfPos.GetPz()}; + std::array pVecV0DauNeg = {kfNeg.GetPx(), kfNeg.GetPy(), kfNeg.GetPz()}; + std::array pVecV0 = {kfV0.GetPx(), kfV0.GetPy(), kfV0.GetPz()}; + std::array pVecBach = {kfBachToCasc.GetPx(), kfBachToCasc.GetPy(), kfBachToCasc.GetPz()}; + std::array pVecCharmBachelorAsD = {kfCharmBachToCharmBaryon.GetPx(), kfCharmBachToCharmBaryon.GetPy(), kfCharmBachToCharmBaryon.GetPz()}; + std::array pVecCharmBaryon = {kfCharmBaryon.GetPx(), kfCharmBaryon.GetPy(), kfCharmBaryon.GetPz()}; + + auto* covVtxCharmBaryon = kfCharmBaryon.CovarianceMatrix(); + float covMatrixPv[6]; + kfVertex.GetCovarianceMatrix(covMatrixPv); + + std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; + + auto trackParCovV0DauPos = getTrackParCovFromKFP(kfPos, kfPos.GetPDG(), 1); + auto trackParCovV0DauNeg = getTrackParCovFromKFP(kfNeg, kfNeg.GetPDG(), -1); + auto trackParCovBach = getTrackParCovFromKFP(kfBachToCasc, kfBachToCasc.GetPDG(), (isAnti ? 1 : -1)); + auto trackParCovCharmBach = getTrackParCovFromKFP(kfCharmBachToCharmBaryon, kfCharmBachToCharmBaryon.GetPDG(), (isAnti ? -1 : 1)); + auto trackParCovCasc = getTrackParCovFromKFP(kfCascToCharmBaryon, kfCascToCharmBaryon.GetPDG(), (isAnti ? 1 : -1)); + trackParCovV0DauPos.setAbsCharge(1); + trackParCovV0DauNeg.setAbsCharge(1); + trackParCovBach.setAbsCharge(1); + trackParCovCharmBach.setAbsCharge(1); + trackParCovCasc.setAbsCharge(1); + + //----------Calculate physical quantities and fill candidate table---------- + + // impact parameters + std::array impactParameterV0DauPos; + std::array impactParameterV0DauNeg; + std::array impactParameterBach; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovV0DauPos, 2.f, matCorr, &impactParameterV0DauPos); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovV0DauNeg, 2.f, matCorr, &impactParameterV0DauNeg); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovBach, 2.f, matCorr, &impactParameterBach); + float dcaxyV0DauPos = impactParameterV0DauPos[0]; + float dcaxyV0DauNeg = impactParameterV0DauNeg[0]; + float dcaxyBach = impactParameterBach[0]; + float dcazV0DauPos = impactParameterV0DauPos[1]; + float dcazV0DauNeg = impactParameterV0DauNeg[1]; + float dcazBach = impactParameterBach[1]; + + o2::dataformats::DCA impactParameterCasc, impactParameterCharmBachelor; + auto primaryVertex = getPrimaryVertex(collision); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovCasc, 2.f, matCorr, &impactParameterCasc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParCovCharmBach, 2.f, matCorr, &impactParameterCharmBachelor); + + // get Chi2Topo/NDF + float chi2NdfTopoV0ToPv = kfV0ToPv.GetChi2() / kfV0ToPv.GetNDF(); + float chi2NdfTopoCascToPv = kfCascToPv.GetChi2() / kfCascToPv.GetNDF(); + float chi2NdfTopoCharmBachToPv = kfCharmBachToPv.GetChi2() / kfCharmBachToPv.GetNDF(); + float chi2NdfTopoCharmBaryonToPv = kfCharmBaryonToPv.GetChi2() / kfCharmBaryonToPv.GetNDF(); + float chi2NdfTopoBachToCasc = kfBachToCasc.GetChi2() / kfBachToCasc.GetNDF(); + float chi2NdfTopoV0ToCasc = kfV0ToCasc.GetChi2() / kfV0ToCasc.GetNDF(); + float chi2NdfTopoCharmBachToCharmBaryon = kfCharmBachToCharmBaryon.GetChi2() / kfCharmBachToCharmBaryon.GetNDF(); + float chi2NdfTopoCascToCharmBaryon = kfCascToCharmBaryon.GetChi2() / kfCascToCharmBaryon.GetNDF(); + + // get ldl + float ldlV0 = ldlFromKF(kfV0, kfPv); + float ldlCasc = ldlFromKF(kfCasc, kfPv); + float ldlCharmBaryon = ldlFromKF(kfCharmBaryon, kfPv); + + // get DCAs + float kfDcaV0Daughters = kfNeg.GetDistanceFromParticle(kfPos); + float kfDcaCascDaughters = kfBachToCasc.GetDistanceFromParticle(kfV0ToCasc); + float kfDcaCharmBaryonDaughters = kfCharmBachToCharmBaryon.GetDistanceFromParticle(kfCascToCharmBaryon); + float kfDcaXYCharmBachelorToPv = kfCharmBachToCharmBaryon.GetDistanceFromVertexXY(kfPv); + float kfDcaXYCascToPv = kfCascToCharmBaryon.GetDistanceFromVertexXY(kfPv); + + // get decay length - In XY + float decayLXYV0, errDecayLXYV0; + kfV0ToCasc.GetDecayLengthXY(decayLXYV0, errDecayLXYV0); + + float decayLXYCasc, errDecayLXYCasc; + kfCascToCharmBaryon.GetDecayLengthXY(decayLXYCasc, errDecayLXYCasc); + + float decayLXYCharmBaryon, errDecayLXYCharmBaryon; + kfCharmBaryonToPv.GetDecayLengthXY(decayLXYCharmBaryon, errDecayLXYCharmBaryon); + + // get decay length - In XYZ + float decayLV0 = RecoDecay::distance(std::array{kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}, std::array{kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}); + float decayLCasc = RecoDecay::distance(std::array{kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ()}, std::array{kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ()}); + float decayLCharmBaryon = RecoDecay::distance(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ()}); + + double phiCharmBaryon, thetaCharmBaryon; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, std::array{kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ()}, phiCharmBaryon, thetaCharmBaryon); + float errDecayLCharmBaryon = std::sqrt(getRotatedCovMatrixXX(covMatrixPv, phiCharmBaryon, thetaCharmBaryon) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon)); + + // get cosine of pointing angle + float cosPaV0ToPv = cpaFromKF(kfV0, kfPv); + float cosPaCascToPv = cpaFromKF(kfCasc, kfPv); + float cosPaCharmBaryonToPv = cpaFromKF(kfCharmBaryon, kfPv); + + float cosPaXYV0ToPv = RecoDecay::cpaXY(pvCoord, vertexV0, pVecV0); + float cosPaXYCascToPv = cpaXYFromKF(kfCasc, kfPv); + float cosPaXYCharmBaryonToPv = cpaXYFromKF(kfCharmBaryon, kfPv); + + float cosPaV0ToCasc = cpaFromKF(kfV0, kfCasc); + float cosPaCascToCharmBaryon = cpaFromKF(kfCasc, kfCharmBaryon); + float cosPaXYV0ToCasc = RecoDecay::cpaXY(vertexCasc, vertexV0, pVecV0); + float cosPaXYCascToCharmBaryon = cpaXYFromKF(kfCasc, kfCharmBaryon); + + float deviationCharmBachToPv = kfCalculateChi2ToPrimaryVertex(kfCharmBaryon, kfPv); // -> For Omegac0 + + // KF pT, eta + float ptCasc = kfCascToCharmBaryon.GetPt(); + float ptCharmBachelor = kfCharmBachToCharmBaryon.GetPt(); + float ptCharmBaryon = kfCharmBaryon.GetPt(); + float yCharmBaryon = kfCharmBaryon.GetRapidity(); + + // get KF cosThetaStar + float cosThetaStarCharmBachelor = -99.0; + float cosThetaStarKaFromOmegac0 = -99.0; + float cosThetaStarKaFromXic0 = -99.0; + + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + cosThetaStarCharmBachelor = cosThetaStarFromKF(0, pdgIdOfCharmBaryon, pdgIdOfCharmBach, pdgIdOfCascade, kfCharmBachToCharmBaryon, kfCascToCharmBaryon, pdgdb); + } + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { // -> Only requeted to be calculated and filled for Xic0/Omegac0 -> Omega K + cosThetaStarKaFromOmegac0 = cosThetaStarFromKF(0, 4332, 321, 3334, kfCharmBachToCharmBaryon, kfCascToCharmBaryon, pdgdb); + cosThetaStarKaFromXic0 = cosThetaStarFromKF(0, 4132, 321, 3334, kfCharmBachToCharmBaryon, kfCascToCharmBaryon, pdgdb); + } + + // KF ct + float ctV0 = kfV0ToCasc.GetLifeTime(); + float ctCasc = kfCascToCharmBaryon.GetLifeTime(); + float ctCharmBaryon = kfCharmBaryonToPv.GetLifeTime(); + + //------------------------------Calculate physical quantities and fill candidate table------------------------------ + + //------------------------------Fill the table------------------------------ + if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi) { + cursors.rowCandToXiPiKf(collision.globalIndex(), // Global index of collision + pvCoord[0], pvCoord[1], pvCoord[2], // coordination of PV + vertexCasc[0], vertexCasc[1], vertexCasc[2], // Decay position of kfCasc + vertexV0[0], vertexV0[1], vertexV0[2], + bachTrack.sign(), + covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], + pVecCharmBaryon[0], pVecCharmBaryon[1], pVecCharmBaryon[2], // x, y, z momentum of charm baryon + kfCascToCharmBaryon.GetPx(), kfCascToCharmBaryon.GetPy(), kfCascToCharmBaryon.GetPz(), + pVecCharmBachelorAsD[0], pVecCharmBachelorAsD[1], pVecCharmBachelorAsD[2], + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + massLam, massCasc, massCharmBaryon, + cosPaV0ToPv, cosPaCascToPv, + ctCasc, ctV0, ctCharmBaryon, + kfPos.GetEta(), kfNeg.GetEta(), kfBach.GetEta(), kfCharmBachToCharmBaryon.GetEta(), + kfCharmBaryon.GetEta(), kfCasc.GetEta(), kfV0.GetEta(), + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + kfDcaCascDaughters, kfDcaV0Daughters, kfDcaCharmBaryonDaughters, + kfDcaXYCharmBachelorToPv, kfDcaXYCascToPv, + kfV0.GetChi2(), kfCasc.GetChi2(), kfCharmBaryon.GetChi2(), kfV0MassConstrained.GetChi2(), kfCascMassConstrained.GetChi2(), + ldlV0, ldlCasc, // ldlCharmBaryon, + chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoCharmBachToPv, chi2NdfTopoCharmBaryonToPv, + chi2NdfTopoV0ToCasc, chi2NdfTopoCascToCharmBaryon, + decayLXYV0, decayLXYCasc, decayLXYCharmBaryon, + cosPaV0ToCasc, cosPaCascToCharmBaryon, // cosPaXYV0ToCasc, cosPaXYCascToCharmBaryon, + yCharmBaryon, // ptCharmBachelor, ptCharmBaryon, + cosThetaStarCharmBachelor, + kfV0.GetNDF(), kfCasc.GetNDF(), kfCharmBaryon.GetNDF(), kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetNDF(), + kfV0.GetChi2() / kfV0.GetNDF(), kfCasc.GetChi2() / kfCasc.GetNDF(), kfCharmBaryon.GetChi2() / kfCharmBaryon.GetNDF(), kfV0MassConstrained.GetChi2() / kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetChi2() / kfCascMassConstrained.GetNDF()); + } else if constexpr (decayChannel == hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { + cursors.rowCandToOmegaPi(collision.globalIndex(), + pvCoord[0], pvCoord[1], pvCoord[2], + 0.f, 0.f, 0.f, // -> vertexCharmBaryonFromFitter. For KF, this is 0 + vertexCasc[0], vertexCasc[1], vertexCasc[2], + vertexV0[0], vertexV0[1], vertexV0[2], + trackCharmBachelor.sign(), + covVtxCharmBaryon[0], covVtxCharmBaryon[1], covVtxCharmBaryon[2], covVtxCharmBaryon[3], covVtxCharmBaryon[4], covVtxCharmBaryon[5], + kfCharmBaryon.GetPx(), kfCharmBaryon.GetPy(), kfCharmBaryon.GetPz(), + kfCascToCharmBaryon.GetPx(), kfCascToCharmBaryon.GetPy(), kfCascToCharmBaryon.GetPz(), + kfCharmBachToCharmBaryon.GetPx(), kfCharmBachToCharmBaryon.GetPy(), kfCharmBachToCharmBaryon.GetPz(), + pVecV0[0], pVecV0[1], pVecV0[2], + pVecBach[0], pVecBach[1], pVecBach[2], + pVecV0DauPos[0], pVecV0DauPos[1], pVecV0DauPos[2], + pVecV0DauNeg[0], pVecV0DauNeg[1], pVecV0DauNeg[2], + impactParameterCasc.getY(), impactParameterCharmBachelor.getY(), + impactParameterCasc.getZ(), impactParameterCharmBachelor.getZ(), + std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBachelor.getSigmaY2()), + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), + cand.cascadeId(), trackCharmBachelor.globalIndex(), cand.prong0Id(), + massLam, massCasc, massCharmBaryon, + cosPaV0ToPv, cosPaCharmBaryonToPv, cosPaCascToPv, cosPaXYV0ToPv, cosPaXYCharmBaryonToPv, cosPaXYCascToPv, + ctCharmBaryon, ctCasc, ctV0, + kfPos.GetEta(), kfNeg.GetEta(), kfBach.GetEta(), kfCharmBachToCharmBaryon.GetEta(), + kfCharmBaryon.GetEta(), kfCasc.GetEta(), kfV0.GetEta(), + dcaxyV0DauPos, dcaxyV0DauNeg, dcaxyBach, + dcazV0DauPos, dcazV0DauNeg, dcazBach, + kfDcaCascDaughters, straHelper.cascade.v0DaughterDCA, kfDcaCharmBaryonDaughters, + decayLCharmBaryon, decayLCasc, decayLV0, errDecayLCharmBaryon, errDecayLXYCharmBaryon, cand.hfflag()); + + cursors.rowCandToOmegaPiKf(kfDcaXYCharmBachelorToPv, kfDcaXYCascToPv, + kfV0.GetChi2(), kfCasc.GetChi2(), kfCharmBaryon.GetChi2(), kfV0MassConstrained.GetChi2(), kfCascMassConstrained.GetChi2(), + ldlV0, ldlCasc, ldlCharmBaryon, + chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoCharmBachToPv, chi2NdfTopoCharmBaryonToPv, deviationCharmBachToPv, + chi2NdfTopoV0ToCasc, chi2NdfTopoCascToCharmBaryon, + decayLXYV0, decayLXYCasc, decayLXYCharmBaryon, + cosPaV0ToCasc, cosPaCascToCharmBaryon, cosPaXYV0ToCasc, cosPaXYCascToCharmBaryon, + kfCharmBaryon.GetRapidity(), ptCharmBachelor, ptCharmBaryon, + cosThetaStarKaFromOmegac0, + kfV0.GetNDF(), kfCasc.GetNDF(), kfCharmBaryon.GetNDF(), kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetNDF(), + kfV0.GetChi2() / kfV0.GetNDF(), kfCasc.Chi2() / kfCasc.GetNDF(), kfCharmBaryon.GetChi2() / kfCharmBaryon.GetNDF(), + kfV0MassConstrained.GetChi2() / kfV0.GetNDF(), kfCascMassConstrained.Chi2() / kfCasc.GetNDF(), + massCascRej); + + } else { + cursors.rowCandToOmegaKaKf(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + kfPv.GetX(), kfPv.GetY(), kfPv.GetZ(), + straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2], + straHelper.cascade.v0Momentum[0], straHelper.cascade.v0Momentum[1], straHelper.cascade.v0Momentum[2], + straHelper.cascade.cascadePosition[0], straHelper.cascade.cascadePosition[1], straHelper.cascade.cascadePosition[2], + straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2], + kfV0.GetX(), kfV0.GetY(), kfV0.GetZ(), + kfV0.GetPx(), kfV0.GetPy(), kfV0.GetPz(), + kfCasc.GetX(), kfCasc.GetY(), kfCasc.GetZ(), + kfCasc.GetPx(), kfCasc.GetPy(), kfCasc.GetPz(), + kfCharmBaryon.GetX(), kfCharmBaryon.GetY(), kfCharmBaryon.GetZ(), + kfCharmBaryon.GetPx(), kfCharmBaryon.GetPy(), kfCharmBaryon.GetPz(), + straHelper.cascade.charge, + kfPos.GetEta(), kfNeg.GetEta(), kfBach.GetEta(), kfCharmBach.GetEta(), kfV0.GetEta(), kfCasc.GetEta(), kfCharmBaryon.GetEta(), kfCharmBaryon.GetRapidity(), + impactParameterCharmBachelor.getY(), std::sqrt(impactParameterCharmBachelor.getSigmaY2()), impactParameterCasc.getY(), std::sqrt(impactParameterCasc.getSigmaY2()), + kfDcaV0Daughters, kfDcaCascDaughters, kfDcaCharmBaryonDaughters, + cosPaV0ToPv, cosPaCascToPv, cosPaCharmBaryonToPv, cosPaXYV0ToPv, cosPaXYCascToPv, cosPaXYCharmBaryonToPv, cosPaV0ToCasc, cosPaCascToCharmBaryon, cosPaXYV0ToCasc, cosPaXYCascToCharmBaryon, + kfV0.GetChi2() / kfV0.GetNDF(), kfCasc.GetChi2() / kfCasc.GetNDF(), kfCharmBaryon.GetChi2() / kfCharmBaryon.GetNDF(), + kfV0MassConstrained.GetChi2() / kfV0MassConstrained.GetNDF(), kfCascMassConstrained.GetChi2() / kfCascMassConstrained.GetNDF(), + chi2NdfTopoV0ToCasc, chi2NdfTopoBachToCasc, chi2NdfTopoCharmBachToCharmBaryon, chi2NdfTopoCascToCharmBaryon, // Topological constraints to mother + chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoCharmBachToPv, chi2NdfTopoCharmBaryonToPv, // Topological constraints to PV + ldlV0, ldlCasc, ldlCharmBaryon, + decayLXYV0, decayLXYCasc, decayLXYCharmBaryon, + massLam, sigMassLam, massCasc, sigMassCasc, massCascRej, sigMassCascRej, massCharmBaryon, sigMassCharmBaryon, + ptCharmBaryon, ptCharmBachelor, ptCasc, + cosThetaStarKaFromOmegac0, cosThetaStarKaFromXic0, ctV0, ctCasc, ctCharmBaryon, + cascAodElement.v0Id(), v0AodElement.posTrackId(), v0AodElement.negTrackId(), cand.cascadeId(), cand.prong0Id(), trackCharmBachelor.globalIndex()); + } + } // end candidate loop + } // end of runCreator + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with DCAFitter /// + /// /// + ///////////////////////////////////////////////////// + + /*~~~~~~~~~~~~~~*/ + /*~~~To Xi Pi~~~*/ + /*~~~~~~~~~~~~~~*/ + void processToXiPiWithDCAFitterNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterNoCent, "Charm candidte reconstruction with Xi Pi via DcaFitter method, no centrality", true); + +#if 0 + void processToXiPiWithDCAFitterNoCentWithTrackedCasc(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::TrackedCascades const& cascades, + aod::V0s const& v0s, + TrackedCascLinked const& trackedCascLinked, + TracksWCovDcaExtraPidPrPiKa const& tracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, trackedCascFull, trackedCascLinked, tracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterNoCentWithTrackedCasc, "Charm candidte reconstruction with Xi Pi via DcaFitter method with tracked cascade, no centrality", false); +#endif + + void processToXiPiWithDCAFitterCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterCentFT0C, "Charm candidate reconstruction with Xi Pi via DcaFitter method, centrality selection on FT0C", false); + + void processToXiPiWithDCAFitterCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithDCAFitterCentFT0M, "Charm candidate reconstruction with Xi Pi via DcaFitter method, centrality selection on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Pi~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaPiWithDCAFitterNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithDCAFitterNoCent, "Charm candidte reconstruction with Omega Pi via DcaFitter method, no centrality", false); + + void processToOmegaPiWithDCAFitterCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithDCAFitterCentFT0C, "Charm candidate reconstruction with Omega Pi via DcaFitter method, centrality selection on FT0C", false); + + void processToOmegaPiWithDCAFitterCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hInvMassCharmBaryonToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithDCAFitterCentFT0M, "Charm candidate reconstruction with Omega Pi via DcaFitter method, centrality selection on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Ka~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaKaWithDCAFitterNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithDCAFitterNoCent, "Charm candidte reconstruction with Omega Ka via DcaFitter method, no centrality", false); + + void processToOmegaKaWithDCAFitterCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithDCAFitterCentFT0C, "Charm candidate reconstruction with Omega Ka via DcaFitter method, centrality selection on FT0C", false); + + void processToOmegaKaWithDCAFitterCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + aod::TracksWCovDca const& tracks, + TracksWCovIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithDCAFitter(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithDCAFitterCentFT0M, "Charm candidate reconstruction with Omega Ka via DcaFitter method, centrality selection on FT0M", false); + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with KFParticle /// + /// /// + ///////////////////////////////////////////////////// + + /*~~~~~~~~~~~~~~*/ + /*~~~To Xi Pi~~~*/ + /*~~~~~~~~~~~~~~*/ + void processToXiPiWithKFParticleNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithKFParticleNoCent, "Charm Baryon decaying to Xi Pi reconstruction via KFParticle method, no centrality", false); + + void processToXiPiWithKFParticleCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithKFParticleCentFT0C, "Charm Baryon decaying to Xi Pi reconstruction via KFParticle method, centrality on FT0C", false); + + void processToXiPiWithKFParticleCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToXiPi, hCandidateCounterToXiPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToXiPiWithKFParticleCentFT0M, "Charm Baryon decaying to Xi Pireconstruction via KFParticle method, centrality on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Pi~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaPiWithKFParticleNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithKFParticleNoCent, "Charm Baryon decaying to Omega Pi reconstruction via KFParticle method, no centrality", false); + + void processToOmegaPiWithKFParticleCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithKFParticleCentFT0C, "Charm Baryon decaying to Omega Pi reconstruction via KFParticle method, centrality on FT0C", false); + + void processToOmegaPiWithKFParticleCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaPi, hCandidateCounterToOmegaPi); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaPiWithKFParticleCentFT0M, "Charm Baryong decaying to Omega Pi reconstruction via KFParticle method, centrality on FT0M", false); + + /*~~~~~~~~~~~~~~~~~*/ + /*~~~To Omega Ka~~~*/ + /*~~~~~~~~~~~~~~~~~*/ + void processToOmegaKaWithKFParticleNoCent(SelectedCollisions const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithKFParticleNoCent, "Charm Baryon decaying to Omega Ka reconstruction via KFParticle method, no centrality", false); + + void processToOmegaKaWithKFParticleCentFT0C(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithKFParticleCentFT0C, "Charm Baryon decaying to Omega Ka reconstruction via KFParticle method, centrality on FT0C", false); + + void processToOmegaKaWithKFParticleCentFT0M(soa::Join const& collisions, + aod::HfCascLf2Prongs const& candidates, + aod::Cascades const& cascades, + aod::V0s const& v0s, + TracksWCovDcaExtraPidPrPiKa const& tracks, + TracksWCovExtraPidIU const& lfTracks, + aod::BCsWithTimestamps const& bcsWithTimestamps) + { + runCreatorWithKfParticle(collisions, candidates, cascades, v0s, tracks, lfTracks, bcsWithTimestamps, hInvMassCharmBaryonToOmegaKa, hCandidateCounterToOmegaKa); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processToOmegaKaWithKFParticleCentFT0M, "Charm Baryong decaying to Omega Ka reconstruction via KFParticle method, centrality on FT0M", false); + + /////////////////////////////////////////////////////////////// + /// /// + /// Process functions for Collision monitoring /// + /// /// + /////////////////////////////////////////////////////////////// + + void processCollisionsNoCent(soa::Join const& collisions, + aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + + // bitmask with event selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + // monitor the satisfied event selection + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + } + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processCollisionsNoCent, "Collision monitoring - No Centrality", true); + + void processCollisionsCentFT0C(soa::Join const& collisions, + aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + + // bitmask with event selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + // monitor the satisfied event selection + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + } + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processCollisionsCentFT0C, "Collision monitoring - Centrality selection with FT0C", false); + + void processCollisionsCentFT0M(soa::Join const& collisions, + aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + + // bitmask with event selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + // monitor the satisfied event selection + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + } + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0Qa, processCollisionsCentFT0M, "Collision monitoring - Centrality selection with FT0M", false); +}; + +struct HfCandidateCreatorXic0Omegac0QaMc { + + // Cursor to fill tables + struct : ProducesGroup { + + Produces rowMcMatchRecXicToXiPi; + Produces rowMcMatchGenXicToXiPi; + Produces rowMcMatchRecOmegacToXiPi; + Produces rowMcMatchGenOmegacToXiPi; + Produces rowMcMatchRecToOmegaPi; + Produces rowMcMatchGenToOmegaPi; + Produces rowMcMatchRecToOmegaKa; + Produces rowMcMatchGenToOmegaKa; + + } cursors; + + // Configurables + struct : ConfigurableGroup { + + Configurable rejectBackground{"rejectBackground", false, "Reject particles from background events"}; // -> Used for only Xic0 + Configurable acceptTrackInteractionWithMaterial{"acceptTrackInteractionWithMaterial", false, "Accept candidates with final daughters interacting with materials"}; + Configurable fillMcHistograms{"fillMcHistograms", true, "Fill validation plots"}; + Configurable fillResidualTable{"fillResidualTable", true, "Fill table contaning residuals and pulls of PV and SV"}; + // Configurable matchDecayedPions{"matchedDecayedPions", true, "Match also candidates with daughter pion tracks that decay with kinked toploogy"}; + + } configs; + + enum McMatchFlag : uint8_t { + None = 0, + CharmBaryonUnmatched, + CascUnmatched, + V0Unmatched, + NumberMcMatchFlag + }; + + std::array pdgOfCharmBaryon{+kXiC0, +kOmegaC0, +kOmegaC0, +kOmegaC0}; + std::array pdgOfCascade{+kXiMinus, +kXiMinus, +kOmegaMinus, +kOmegaMinus}; + std::array pdgOfCharmBachelor{+kPiPlus, +kPiPlus, +kPiPlus, +kKPlus}; + std::array pdgOfBachelor{+kPiMinus, +kPiMinus, +kKMinus, +kKMinus}; + + // Table aliases + using TracksWMcIU = soa::Join; + using McCollisionsNoCents = soa::Join; + using McCollisionsFT0Cs = soa::Join; + using McCollisionsFT0Ms = soa::Join; + using McCollisionsCentFT0Ms = soa::Join; // -> Used for subscription for process functions of centrality with FT0Ms + using BCsInfo = soa::Join; + + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; // -> Why use unsorted?? + PresliceUnsorted colPerMcCollisionFT0C = aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted colPerMcCollisionFT0M = aod::mccollisionlabel::mcCollisionId; + + HistogramRegistry registry{"registry"}; + HfEventSelectionMc hfEvSelMc; + + void init(InitContext& initContext) + { + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-candidate-creator-xic0-omegac0-qa") == 0) { + hfEvSelMc.init(device, registry); + break; + } + } + + // Add histograms for QA + if (configs.fillMcHistograms) { + registry.add("hGenCharmBaryonPtRapidityTight", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + registry.add("hGenCharmBaryonPtRapidityLoose", "Generated charm baryon #it{p}_{T};#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1D, {{20, 0.0, 20.0}}}); + } + } + + // Helper function to fill in table for MC Rec + ///@brief decay Channel is the chosen reconstruction channel + ///@brief flag + ///@brief debug + ///@brief origin + ///@brief collisionMatched + ///@brief pt + ///@brief pdgcode + template + void fillRecoMcTableByDecayChannel(int8_t flag, int8_t debug, int8_t origin, bool collisionMatched, float pt, int pdgCode) + { + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + cursors.rowMcMatchRecXicToXiPi(flag, debug, origin, collisionMatched, pt, pdgCode); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + cursors.rowMcMatchRecOmegacToXiPi(flag, debug, origin, collisionMatched, pt, pdgCode); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + cursors.rowMcMatchRecToOmegaPi(flag, debug, origin, collisionMatched, pt, pdgCode); + } else { + cursors.rowMcMatchRecToOmegaKa(flag, debug, origin, collisionMatched, pt, pdgCode); + } + } + + // Helper function to fill in table for MC Gen + ///@brief decay Channel is the chosen reconstruction channel + ///@brief flag + ///@brief debug + ///@brief origin + ///@brief collisionMatched + ///@brief pt + ///@brief pdgcode + template + void fillGenMcTableByDecayChannel(int8_t flag, int8_t debugGenCharmBaryon, int8_t debugGenCascade, int8_t debugGenLambda, float ptCharmBaryon, float yCharmBaryon, int8_t origin, int idxMother) + { + if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + cursors.rowMcMatchGenXicToXiPi(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + cursors.rowMcMatchGenOmegacToXiPi(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } else if constexpr (decayChannel == aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { + cursors.rowMcMatchGenToOmegaPi(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } else { + cursors.rowMcMatchGenToOmegaKa(flag, debugGenCharmBaryon, debugGenCascade, debugGenLambda, ptCharmBaryon, yCharmBaryon, origin, idxMother); + } + } + + template + void runXic0Omegac0Mc(TRecoCand const& candidates, + TracksWMcIU const&, + aod::McParticles const& mcParticles, + Colls const& collsWithMcLabels, + McCollisions const& mcCollisions, + BCsInfo const&) + { + int indexRec{-1}; + int indexRecCharmBaryon{-1}; + int8_t sign{-9}; + int8_t signCasc{-9}; + int8_t signV0{-9}; + int8_t flag{0}; + int8_t origin{0}; + int8_t debug{0}; + int8_t debugGenCharmBaryon{0}; + int8_t debugGenCasc{0}; + int8_t debugGenV0{0}; + bool collisionMatched = false; + float ptCharmBaryonGen = -999.; + float yCharmBaryonGen = -999.; + + //////////////////////////////////// + // Match reconstructed candidates // + //////////////////////////////////// + + for (const auto& candidate : candidates) { + + flag = 0; + origin = RecoDecay::OriginType::None; + debug = McMatchFlag::None; + collisionMatched = false; + std::vector idxBhadMothers{}; + + auto arrayDaughters = std::array{candidate.template bachelorFromCharmBaryon_as(), + candidate.template bachelor_as(), + candidate.template posTrack_as(), + candidate.template negTrack_as()}; + 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()}; + + // Reject particles from background events + if (configs.rejectBackground) { + bool fromBkg{false}; + for (auto const& daughter : arrayDaughters) { + if (daughter.has_mcParticle()) { + auto mcParticle = daughter.mcParticle(); + if (mcParticle.fromBackgroundEvent()) { + fromBkg = true; + break; + } + } + } + if (fromBkg) { + // fill the tables + fillRecoMcTableByDecayChannel(flag, debug, origin, collisionMatched, -1.f, 0); + continue; + } + } + + // CharmBaryon -> Charm bachelor + Cascade + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgOfCharmBaryon[decayChannel], std::array{pdgOfCharmBachelor[decayChannel], pdgOfBachelor[decayChannel], +kProton, +kPiMinus}, true, &sign, 3); + indexRecCharmBaryon = indexRec; + if (indexRec == -1) { // Xic0 not reconstructed + debug = McMatchFlag::CharmBaryonUnmatched; + } + if (indexRec > -1) { + // Cascade -> Bachelor + V0 + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersCasc, pdgOfCascade[decayChannel], std::array{pdgOfBachelor[decayChannel], +kProton, +kPiMinus}, true, &signCasc, 2); + if (indexRec == -1) { // Xi- not reconstructed + debug = McMatchFlag::CascUnmatched; + } + if (indexRec > -1) { + // V0 -> Pos + Neg + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); + if (indexRec == -1) { // V0 not reconstructed + debug = McMatchFlag::V0Unmatched; + } + if (indexRec > -1) { + flag = sign * (1 << decayChannel); + collisionMatched = candidate.template collision_as().mcCollisionId() == mcParticles.iteratorAt(indexRecCharmBaryon).mcCollisionId(); + } + } + } + + // Check if charm baryon is from b-hadron decay(prompt vs non-prompt) + if (flag != 0) { + auto particle = mcParticles.rawIteratorAt(indexRecCharmBaryon); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (origin == RecoDecay::OriginType::NonPrompt) { + auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); + fillRecoMcTableByDecayChannel(flag, debug, origin, collisionMatched, bHadMother.pt(), bHadMother.pdgCode()); + } else { + fillRecoMcTableByDecayChannel(flag, debug, origin, collisionMatched, -1.f, 0); + } + if (debug == McMatchFlag::CascUnmatched || debug == McMatchFlag::V0Unmatched) { + LOGF(info, "WARNING: Charm baryon decays in the expected final state but the condition on the intermediate states are not fullfilled"); + } + } // candidate loop + + /////////////////////////////// + // Match generated particles // + /////////////////////////////// + + for (const auto& mcCollision : mcCollisions) { + + const auto& mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + + float centrality{-1.f}; + o2::hf_evsel::HfCollisionRejectionMask rejectionMask{}; + int nSplitColl{0}; + + if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::None) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0C) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); + } else if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0M) { + const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); + } + + hfEvSelMc.fillHistograms(mcCollision, rejectionMask, nSplitColl); + + if (rejectionMask != 0) { // At least one event selection not satisfied --> Reject all particles from this event + for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { + fillGenMcTableByDecayChannel(0, 0, 0, 0, -999., -999., RecoDecay::OriginType::None, -1); + } + continue; + } + + // Match generated particles + for (auto const& particle : mcParticlesPerMcColl) { + ptCharmBaryonGen = -999.; + yCharmBaryonGen = -999.; + flag = 0; + sign = -9; + debugGenCharmBaryon = 0; + debugGenCasc = 0; + debugGenV0 = 0; + origin = RecoDecay::OriginType::None; + std::vector idxBhadMothers{}; + const float kYCutTight = 0.5; + const float kYCutLoose = 0.8; + + // Reject particles from background events + if (particle.fromBackgroundEvent() && configs.rejectBackground) { + fillGenMcTableByDecayChannel(flag, debugGenCharmBaryon, debugGenCasc, debugGenV0, ptCharmBaryonGen, yCharmBaryonGen, origin, -1); + continue; + } + + // Charm Baryon -> Cascade + Charm bachelor + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgOfCharmBaryon[decayChannel], std::array{pdgOfCascade[decayChannel], pdgOfCharmBachelor[decayChannel]}, true, &sign)) { + debugGenCharmBaryon = 1; + ptCharmBaryonGen = particle.pt(); + yCharmBaryonGen = particle.y(); + + for (auto const& daughterCharm : particle.template daughters_as()) { + if (std::abs(daughterCharm.pdgCode()) != pdgOfCascade[decayChannel]) { + continue; + } + // Xi -> Lambda + pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCharm, pdgOfCascade[decayChannel], std::array{+kLambda0, pdgOfBachelor[decayChannel]}, true)) { + debugGenCasc = 1; // -> Matched Xi- + for (auto const& daughterCascade : daughterCharm.template daughters_as()) { + if (std::abs(daughterCascade.pdgCode()) != +kLambda0) { + continue; + } + + // Lambda -> p + pi + if (RecoDecay::isMatchedMCGen(mcParticles, daughterCascade, +kLambda0, std::array{+kProton, +kPiMinus}, true)) { + debugGenV0 = 1; // -> Matched Lambda0 + flag = sign * (1 << decayChannel); + } + } // V0 daughter loop + } // cascade daughter loop + } + } // charm daughter loop + + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + if (std::abs(yCharmBaryonGen) < kYCutTight) { + registry.fill(HIST("hGenCharmBaryonPtRapidityTight"), ptCharmBaryonGen); + } + if (std::abs(yCharmBaryonGen) < kYCutLoose) { + registry.fill(HIST("hGenCharmBaryonPtRapidityLoose"), ptCharmBaryonGen); + } + } + + // Check if charm is prompt or non-prompt + if (origin == RecoDecay::OriginType::NonPrompt) { + fillGenMcTableByDecayChannel(flag, debugGenCharmBaryon, debugGenCasc, debugGenV0, ptCharmBaryonGen, yCharmBaryonGen, origin, idxBhadMothers[0]); + } else { + fillGenMcTableByDecayChannel(flag, debugGenCharmBaryon, debugGenCasc, debugGenV0, ptCharmBaryonGen, yCharmBaryonGen, origin, -1); + } + + } // particle loop + + } // end of collision loop + + } // template run function + + void processMcEmpty(aod::Collisions const&) + { + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcEmpty, "Empty process function to prevent workflow from getting stuck", true); + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with DCAFitter /// + /// /// + ///////////////////////////////////////////////////// + + //~~~~~~~~~~~~~~~~// + //~~~~To Xi Pi~~~~// + //~~~~~~~~~~~~~~~~// + void processMcXicToXiPiWithDCAFitterNoCent(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Xic0 to Xi Pi. No cents", false); + + void processMcXicToXiPiWithDCAFitterCentFT0C(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Xic0 to Xi Pi. Cents with FT0C", false); + + void processMcXicToXiPiWithDCAFitterCentFT0M(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Xic0 to Xi Pi. Cents with FT0M", false); + + void processMcOmegacToXiPiWithDCAFitterNoCent(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToXiPiWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Omegac0 to Xi Pi. No cents", false); + + void processMcOmegacToXiPiWithDCAFitterCentFT0C(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToXiPiWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Omeagc0 to Xi Pi. Cents with FT0C", false); + + void processMcOmegacToXiPiWithDCAFitterCentFT0M(aod::HfCandToXiPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToXiPiWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Omegac0 to Xi Pi. Cents with FT0M", false); + + //~~~~~~~~~~~~~~~~~~~// + //~~~~To Omega Pi~~~~// + //~~~~~~~~~~~~~~~~~~~// + void processMcOmegacToOmegaPiWithDCAFitterNoCent(aod::HfCandToOmegaPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaPiWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Pi. No cents", false); + + void processMcOmegacToOmegaPiWithDCAFitterCentFT0C(aod::HfCandToOmegaPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaPiWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Pi. Cents with FT0C", false); + + void processMcOmegacToOmegaPiWithDCAFitterCentFT0M(aod::HfCandToOmegaPi const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaPiWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Pi. Cents with FT0M", false); + + //~~~~~~~~~~~~~~~~~~// + //~~~~To Omega Ka~~~~// + //~~~~~~~~~~~~~~~~~~// + void processMcOmegacToOmegaKaWithDCAFitterNoCent(aod::HfCandToOmegaK const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaKaWithDCAFitterNoCent, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Ka. No cents", false); + + void processMcOmegacToOmegaKaWithDCAFitterCentFT0C(aod::HfCandToOmegaK const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsFT0Cs const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaKaWithDCAFitterCentFT0C, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Ka. Cents with FT0C", false); + + void processMcOmegacToOmegaKaWithDCAFitterCentFT0M(aod::HfCandToOmegaK const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + McCollisionsCentFT0Ms const& mcCollisions, + McCollisionsFT0Ms const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcOmegacToOmegaKaWithDCAFitterCentFT0M, "Perform MC matching of DCAFitter reconstructed Omegac0 to Omega Ka. Cents with FT0M", false); + + ///////////////////////////////////////////////////// + /// /// + /// Process functions with KFParticle /// + /// /// + ///////////////////////////////////////////////////// + void processMcXicToXiPiWithKFParticleNoCent(aod::HfCandToXiPiKf const& candidates, + TracksWMcIU const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + McCollisionsNoCents const& collsWithMcLabels, + BCsInfo const& bcs) + { + runXic0Omegac0Mc(candidates, tracks, mcParticles, collsWithMcLabels, mcCollisions, bcs); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0QaMc, processMcXicToXiPiWithKFParticleNoCent, "Perform MC matching of KFParticle reconstructed Xic0 to Xi Pi. No cents", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx index 2412ca83708..a618360598f 100644 --- a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -112,7 +112,7 @@ struct HfCandidateCreatorXicToXiPiPi { 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; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; @@ -345,7 +345,7 @@ struct HfCandidateCreatorXicToXiPiPi { massXiPi1 = RecoDecay::m(arrayMomentaXiPi1, std::array{MassXiMinus, MassPiPlus}); // get uncertainty of the decay length - float phi, theta; + float 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.)); @@ -362,7 +362,7 @@ struct HfCandidateCreatorXicToXiPiPi { // Lambda daughters auto trackPosLambdaDaughter = casc.posTrack_as(); auto trackNegLambdaDaughter = casc.negTrack_as(); - float pPiFromLambda, pPrFromLambda, nSigTpcPiFromLambda, nSigTofPiFromLambda, nSigTpcPrFromLambda, nSigTofPrFromLambda; + float pPiFromLambda{}, pPrFromLambda{}, nSigTpcPiFromLambda{}, nSigTofPiFromLambda{}, nSigTpcPrFromLambda{}, nSigTofPrFromLambda{}; if (signXic == +1) { pPiFromLambda = trackNegLambdaDaughter.p(); nSigTpcPiFromLambda = trackNegLambdaDaughter.tpcNSigmaPi(); @@ -591,7 +591,7 @@ struct HfCandidateCreatorXicToXiPiPi { // mass of Xi-Pi0 pair KFParticle kfXiPi0; - float errMassXiPi0; + float errMassXiPi0{}; const KFParticle* kfXiResonanceDaughtersPi0[2] = {&kfXi, &kfCharmBachelor0}; kfXiPi0.SetConstructMethod(kfConstructMethod); try { @@ -603,7 +603,7 @@ struct HfCandidateCreatorXicToXiPiPi { // mass of Xi-Pi1 pair KFParticle kfXiPi1; - float errMassXiPi1; + float errMassXiPi1{}; const KFParticle* kfXiResonanceDaughtersPi1[2] = {&kfXi, &kfCharmBachelor1}; kfXiPi1.SetConstructMethod(kfConstructMethod); try { @@ -614,7 +614,7 @@ struct HfCandidateCreatorXicToXiPiPi { kfXiPi1.GetMass(massXiPi1, errMassXiPi1); // get invariant mass of Xic candidate - float errMassXiPiPi; + float errMassXiPiPi{}; kfXicPlus.GetMass(massXiPiPi, errMassXiPiPi); // decay length of XicPlus @@ -637,7 +637,7 @@ struct HfCandidateCreatorXicToXiPiPi { // Lambda daughters auto trackPosLambdaDaughter = casc.posTrack_as(); auto trackNegLambdaDaughter = casc.negTrack_as(); - float pPiFromLambda, pPrFromLambda, nSigTpcPiFromLambda, nSigTofPiFromLambda, nSigTpcPrFromLambda, nSigTofPrFromLambda; + float pPiFromLambda{}, pPrFromLambda{}, nSigTpcPiFromLambda{}, nSigTofPiFromLambda{}, nSigTpcPrFromLambda{}, nSigTofPrFromLambda{}; if (signXic == +1) { pPiFromLambda = trackNegLambdaDaughter.p(); nSigTpcPiFromLambda = trackNegLambdaDaughter.tpcNSigmaPi(); diff --git a/PWGHF/TableProducer/candidateSelectorCd.cxx b/PWGHF/TableProducer/candidateSelectorCd.cxx index eb5173c3570..61c662ada3e 100644 --- a/PWGHF/TableProducer/candidateSelectorCd.cxx +++ b/PWGHF/TableProducer/candidateSelectorCd.cxx @@ -82,7 +82,7 @@ struct HfCandidateSelectorCd { TrackSelectorKa selectorKaon; TrackSelectorDe selectorDeuteron; - const float massCharmDeuteron = 3.23; // possible mass + static constexpr float MassCharmDeuteron{3.23f}; // possible mass using TracksSel = soa::Join; @@ -218,7 +218,7 @@ struct HfCandidateSelectorCd { } // cut on Cd->deKpi, piKde mass values - if (std::abs(massCd - massCharmDeuteron) > cuts->get(binPt, "m")) { + if (std::abs(massCd - MassCharmDeuteron) > cuts->get(binPt, "m")) { return false; } diff --git a/PWGHF/TableProducer/candidateSelectorD0.cxx b/PWGHF/TableProducer/candidateSelectorD0.cxx index 8d72e1c2b3a..791d9c3f6e5 100644 --- a/PWGHF/TableProducer/candidateSelectorD0.cxx +++ b/PWGHF/TableProducer/candidateSelectorD0.cxx @@ -244,7 +244,7 @@ struct HfCandidateSelectorD0 { } // invariant-mass cut - float massD0, massD0bar; + float massD0{}, massD0bar{}; if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { massD0 = candidate.kfGeoMassD0(); massD0bar = candidate.kfGeoMassD0bar(); diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index b372780c1f3..34b183aa1ce 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -133,13 +133,13 @@ struct HfCandidateSelectorLc { LOGP(fatal, "One and only one process function must be enabled at a time."); } - selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorPion.setRangePtBayes(ptPidBayesMin, ptPidBayesMax); + selectorPion.setRangePtTpc(static_cast(ptPidTpcMin), static_cast(ptPidTpcMax)); + selectorPion.setRangeNSigmaTpc(-static_cast(nSigmaTpcMax), static_cast(nSigmaTpcMax)); + selectorPion.setRangeNSigmaTpcCondTof(-static_cast(nSigmaTpcCombinedMax), static_cast(nSigmaTpcCombinedMax)); + selectorPion.setRangePtTof(static_cast(ptPidTofMin), static_cast(ptPidTofMax)); + selectorPion.setRangeNSigmaTof(-static_cast(nSigmaTofMax), static_cast(nSigmaTofMax)); + selectorPion.setRangeNSigmaTofCondTpc(-static_cast(nSigmaTofCombinedMax), static_cast(nSigmaTofCombinedMax)); + selectorPion.setRangePtBayes(static_cast(ptPidBayesMin), static_cast(ptPidBayesMax)); selectorKaon = selectorPion; selectorProton = selectorPion; @@ -518,11 +518,11 @@ struct HfCandidateSelectorLc { if (usePid) { // track-level PID selection - TrackSelectorPID::Status pidTrackPos1Proton; - TrackSelectorPID::Status pidTrackPos2Proton; - TrackSelectorPID::Status pidTrackPos1Pion; - TrackSelectorPID::Status pidTrackPos2Pion; - TrackSelectorPID::Status pidTrackNegKaon; + TrackSelectorPID::Status pidTrackPos1Proton{}; + TrackSelectorPID::Status pidTrackPos2Proton{}; + TrackSelectorPID::Status pidTrackPos1Pion{}; + TrackSelectorPID::Status pidTrackPos2Pion{}; + TrackSelectorPID::Status pidTrackNegKaon{}; if (usePidTpcAndTof) { pidTrackPos1Proton = selectorProton.statusTpcAndTof(trackPos1, candidate.nSigTpcPr0(), candidate.nSigTofPr0()); pidTrackPos2Proton = selectorProton.statusTpcAndTof(trackPos2, candidate.nSigTpcPr2(), candidate.nSigTofPr2()); diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx index e1e32120543..b00b7001a31 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx @@ -14,6 +14,12 @@ /// \author Federica Zanone , Heidelberg University /// \author Ruiqi Yin , Fudan University +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" @@ -38,12 +44,6 @@ #include #include #include -// #include "PWGHF/Core/HfMlResponseOmegaKaToOmegaKa.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/AliasTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" using namespace o2; using namespace o2::aod; diff --git a/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx b/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx new file mode 100644 index 00000000000..b6b40705557 --- /dev/null +++ b/PWGHF/TableProducer/candidateSelectorToXiPiQa.cxx @@ -0,0 +1,772 @@ +// 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 candidateSelectorToXiPiQa.cxx +/// \brief Selection of Xic0 and Xicp candidates +/// +/// \author Jinhyun Park , Pusan National University +/// \author Krista Smith , Pusan National University + +#include "PWGHF/Core/HfMlResponseXic0ToXiPi.h" +#include "PWGHF/Core/HfMlResponseXic0ToXiPiKf.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +enum PidInfoStored { + PiFromLam = 0, + PrFromLam, + PiFromCasc, + PiFromCharm +}; + +enum { + doDcaFitter = 0, + doKfParticle +}; + +/// Struct for applying Omegac0/Xic0 selection cuts +struct HfCandidateSelectorToXiPiQa { + + // DCAFitter + Produces hfSelToXiPi; + // KFParticle + Produces hfSelToXiPiKf; + // ML selection - Filled with both DCAFitter and KFParticle + Produces hfMlToXiPi; + + // cuts from SelectorCuts.h - pT dependent cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_xi_pi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_xic_to_xi_pi::Cuts[0], hf_cuts_xic_to_xi_pi::NBinsPt, hf_cuts_xic_to_xi_pi::NCutVars, hf_cuts_xic_to_xi_pi::labelsPt, hf_cuts_xic_to_xi_pi::labelsCutVar}, "Xic0 candidate selection per Pt Bin"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::Cuts[0], hf_cuts_ml::NBinsPt, hf_cuts_ml::NCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", static_cast(hf_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"EventFiltering/PWGHF/BDTXic0ToXipiKf"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_Xic0ToXipiKf.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"}; + // LF analysis selections + Configurable etaTrackCharmBachMax{"etaTrackCharmBachMax", 0.8, "Max absolute value of eta for charm baryon bachelor"}; + Configurable etaTrackLFDauMax{"etaTrackLFDauMax", 1.0, "Max absolute value of eta for V0 and cascade daughters"}; + Configurable ptPiFromCascMin{"ptPiFromCascMin", 0.15, "Min pT pi <--Casc"}; + Configurable radiusCascMin{"radiusCascMin", 0.6, "Min Cascade radius"}; + Configurable radiusV0Min{"radiusV0Min", 1.2, "Min V0 radius"}; + Configurable impactParXYPiFromCharmBaryonMin{"impactParXYPiFromCharmBaryonMin", 0., "Min dcaxy pi from charm baryon track to pV"}; + Configurable impactParXYPiFromCharmBaryonMax{"impactParXYPiFromCharmBaryonMax", 10., "Max dcaxy pi from charm baryon track to pV"}; + Configurable impactParXYCascMin{"impactParXYCascMin", 0., "Min dcaxy casc track to pV"}; + Configurable impactParXYCascMax{"impactParXYCascMax", 10., "Max dcaxy casc track to pV"}; + Configurable impactParZPiFromCharmBaryonMin{"impactParZPiFromCharmBaryonMin", 0., "Min dcaz pi from charm baryon track to pV"}; + Configurable impactParZPiFromCharmBaryonMax{"impactParZPiFromCharmBaryonMax", 10., "Max dcaz pi from charm baryon track to pV"}; + Configurable impactParZCascMin{"impactParZCascMin", 0., "Min dcaz casc track to pV"}; + Configurable impactParZCascMax{"impactParZCascMax", 10., "Max dcaz casc track to pV"}; + Configurable applyTrkSelLf{"applyTrkSelLf", true, "Apply track selection for LF daughters"}; + // Mass window + Configurable v0MassWindow{"v0MassWindow", 0.01, "v0 mass window"}; + Configurable cascMassWindow{"cascMassWindow", 0.01, "cascade mass window"}; + Configurable invMassCharmBaryonMin{"invMassCharmBaryonMin", 2.0, "Lower limit of invariant mass spectrum charm baryon"}; + Configurable invMassCharmBaryonMax{"invMassCharmBaryonMax", 3.1, "Lower limit of invariant mass spectrum charm baryon"}; + // PID options + Configurable usePidTpcOnly{"usePidTpcOnly", false, "Perform PID using only TPC"}; + Configurable usePidTpcTofCombined{"usePidTpcTofCombined", true, "Perform PID using TPC & TOF"}; + // PID - TPC selections + Configurable ptPiPidTpcMin{"ptPiPidTpcMin", -1, "Lower bound of track pT for TPC PID for pion selection"}; + Configurable ptPiPidTpcMax{"ptPiPidTpcMax", 9999.9, "Upper bound of track pT for TPC PID for pion selection"}; + Configurable nSigmaTpcPiMax{"nSigmaTpcPiMax", 3., "Nsigma cut on TPC only for pion selection"}; + Configurable nSigmaTpcCombinedPiMax{"nSigmaTpcCombinedPiMax", 0., "Nsigma cut on TPC combined with TOF for pion selection"}; + Configurable ptPrPidTpcMin{"ptPrPidTpcMin", -1, "Lower bound of track pT for TPC PID for proton selection"}; + Configurable ptPrPidTpcMax{"ptPrPidTpcMax", 9999.9, "Upper bound of track pT for TPC PID for proton selection"}; + Configurable nSigmaTpcPrMax{"nSigmaTpcPrMax", 3., "Nsigma cut on TPC only for proton selection"}; + Configurable nSigmaTpcCombinedPrMax{"nSigmaTpcCombinedPrMax", 0., "Nsigma cut on TPC combined with TOF for proton selection"}; + // PID - TOF selections + Configurable ptPiPidTofMin{"ptPiPidTofMin", -1, "Lower bound of track pT for TOF PID for pion selection"}; + Configurable ptPiPidTofMax{"ptPiPidTofMax", 9999.9, "Upper bound of track pT for TOF PID for pion selection"}; + Configurable nSigmaTofPiMax{"nSigmaTofPiMax", 3., "Nsigma cut on TOF only for pion selection"}; + Configurable nSigmaTofCombinedPiMax{"nSigmaTofCombinedPiMax", 0., "Nsigma cut on TOF combined with TPC for pion selection"}; + Configurable ptPrPidTofMin{"ptPrPidTofMin", -1, "Lower bound of track pT for TOF PID for proton selection"}; + Configurable ptPrPidTofMax{"ptPrPidTofMax", 9999.9, "Upper bound of track pT for TOF PID for proton selection"}; + Configurable nSigmaTofPrMax{"nSigmaTofPrMax", 3., "Nsigma cut on TOF only for proton selection"}; + Configurable nSigmaTofCombinedPrMax{"nSigmaTofCombinedPrMax", 0., "Nsigma cut on TOF combined with TPC for proton selection"}; + // detector track quality selections + Configurable nClustersTpcMin{"nClustersTpcMin", 70, "Minimum number of TPC clusters requirement"}; + Configurable nTpcCrossedRowsMin{"nTpcCrossedRowsMin", 70, "Minimum number of TPC crossed rows requirement"}; + Configurable tpcCrossedRowsOverFindableClustersRatioMin{"tpcCrossedRowsOverFindableClustersRatioMin", 0.8, "Minimum ratio TPC crossed rows over findable clusters requirement"}; + Configurable tpcChi2PerClusterMax{"tpcChi2PerClusterMax", 4, "Maximum value of chi2 fit over TPC clusters"}; + Configurable nClustersItsMin{"nClustersItsMin", 3, "Minimum number of ITS clusters requirement for pi <- charm baryon"}; + Configurable nClustersItsInnBarrMin{"nClustersItsInnBarrMin", 1, "Minimum number of ITS clusters in inner barrel requirement for pi <- charm baryon"}; + Configurable itsChi2PerClusterMax{"itsChi2PerClusterMax", 36, "Maximum value of chi2 fit over ITS clusters for pi <- charm baryon"}; + + o2::analysis::HfMlResponseXic0ToXiPi hfMlResponseDca; + o2::analysis::HfMlResponseXic0ToXiPiKf hfMlResponseKf; + std::vector outputMlXic0ToXiPi = {}; + o2::ccdb::CcdbApi ccdbApi; + + TrackSelectorPi selectorPion; + TrackSelectorPr selectorProton; + + using TracksSel = soa::Join; + using TracksSelLf = soa::Join; + + HistogramRegistry registry{"registry"}; // for QA of selections + + void init(InitContext const&) + { + selectorPion.setRangePtTpc(ptPiPidTpcMin, ptPiPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcPiMax, nSigmaTpcPiMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedPiMax, nSigmaTpcCombinedPiMax); + selectorPion.setRangePtTof(ptPiPidTofMin, ptPiPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofPiMax, nSigmaTofPiMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPiMax, nSigmaTofCombinedPiMax); + + selectorProton.setRangePtTpc(ptPrPidTpcMin, ptPrPidTpcMax); + selectorProton.setRangeNSigmaTpc(-nSigmaTpcPrMax, nSigmaTpcPrMax); + selectorProton.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedPrMax, nSigmaTpcCombinedPrMax); + selectorProton.setRangePtTof(ptPrPidTofMin, ptPrPidTofMax); + selectorProton.setRangeNSigmaTof(-nSigmaTofPrMax, nSigmaTofPrMax); + selectorProton.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPrMax, nSigmaTofCombinedPrMax); + + const AxisSpec axisSel{2, -0.5, 1.5, "status"}; + const AxisSpec axisSelOnLfDca{14, -0.5, 13.5, "status"}; + const AxisSpec axisSelOnLfKf{23, -0.5, 22.5, "status"}; + const AxisSpec axisSelOnHfDca{6, -0.5, 5.5, "status"}; + const AxisSpec axisSelOnHfKf{12, -0.5, 11.5, "status"}; + + registry.add("hSelSignDec", "hSelSignDec;status;entries", {HistType::kTH1F, {axisSel}}); + registry.add("hSelStatusCluster", "hSelStatusCluster:# of events Passed;;", {HistType::kTH1F, {{6, -0.5, 5.5}}}); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(2, "TpcCluster PiFromV0"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(3, "TpcCluster PrFromV0"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(4, "TpcCluster PiFromCasc"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(5, "TpcCluster PiFromCharm"); + registry.get(HIST("hSelStatusCluster"))->GetXaxis()->SetBinLabel(6, "ItsCluster PiFromCharm"); + + registry.add("hSelStatusPID", "hSelStatusPID;# of events Passed;;", {HistType::kTH1F, {{4, -0.5, 3.5}}}); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(2, "Lambda"); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(3, "Cascade"); + registry.get(HIST("hSelStatusPID"))->GetXaxis()->SetBinLabel(4, "CharmBaryon"); + + // For QA of LF & HF selection + if (doprocessSelectionDCAFitter) { + registry.add("hSelStatusLf", "hSelStatusLf;# of candidate passed;", {HistType::kTH1F, {axisSelOnLfDca}}); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(2, "etaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(3, "radiusV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(4, "radiusCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(5, "cosPAV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(6, "cosPACasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(7, "dcaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(8, "dcaCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(9, "dcaXYToPvV0Dau0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(10, "dcaXYToPvV0Dau1"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(11, "dcaXYToPvCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(12, "ptPiFromCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(13, "impactParCascXY"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(14, "impactParCascZ"); + + registry.add("hSelStatusHf", "hSelStatusHf;# of candidate passed;", {HistType::kTH1F, {axisSelOnHfDca}}); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(2, "etaTrackCharmBach"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(3, "dcaCharmBaryonDau"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(4, "ptPiFromCharmBaryon"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(5, "impactParBachFromCharmXY"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(6, "impactParBachFromCharmZ"); + } + + if (doprocessSelectionKFParticle) { + registry.add("hSelStatusLf", "hSelStatusLf;# of candidate passed;", {HistType::kTH1F, {axisSelOnLfKf}}); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(2, "etaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(3, "radiusV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(4, "radiusCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(5, "cosPAV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(6, "cosPACasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(7, "dcaV0Dau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(8, "dcaCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(9, "dcaXYToPvV0Dau0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(10, "dcaXYToPvV0Dau1"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(11, "dcaXYToPvCascDau"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(12, "ptPiFromCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(13, "cosPAV0ToCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(14, "kfDcaXYCascToPv"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(15, "chi2GeoV0"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(16, "chi2GeoCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(17, "chi2TopoV0ToPv"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(18, "chi2TopoCascToPv"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(19, "chi2TopoV0ToCasc"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(20, "v0ldl"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(21, "cascldl"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(22, "decayLenXYLambda"); + registry.get(HIST("hSelStatusLf"))->GetXaxis()->SetBinLabel(23, "decayLenXYCasc"); + + registry.add("hSelStatusHf", "hSelStatusHf;# of candidate passed;", {HistType::kTH1F, {axisSelOnHfKf}}); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(2, "etaTrackCharmBach"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(3, "dcaCharmBaryonDau"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(4, "ptPiFromCharmBaryon"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(5, "cosPaCascToXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(6, "kfDcaXYPiFromXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(7, "chi2GeoXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(8, "chi2TopoXicToPv"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(9, "chi2TopoPiFromXicToPv"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(10, "chi2TopoCascToXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(11, "decayLenXYXic"); + registry.get(HIST("hSelStatusHf"))->GetXaxis()->SetBinLabel(12, "cTauXic"); + } + + // invarinat mass histograms + registry.add("hInvMassCharmBaryonWoPidInvMassCut", "Charm baryon invariant mass; int mass; entries", {HistType::kTH1F, {{1500, 1.5, 4.5}}}); + registry.add("hInvMassCharmBaryon", "Charm baryon invariant mass; int mass; entries", {HistType::kTH1F, {{1500, 1.5, 4.5}}}); + registry.add("hInvMassCharmBaryonBkg", "Charm baryon invariant mass, rejected; int mass; entries", {HistType::kTH1F, {{1500, 1.5, 4.5}}}); + + // HfMlResponse initialization + if (applyMl) { + if (doprocessSelectionDCAFitter) { + hfMlResponseDca.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseDca.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponseDca.setModelPathsLocal(onnxFileNames); + } + hfMlResponseDca.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponseDca.init(); + } else { + hfMlResponseKf.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseKf.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponseKf.setModelPathsLocal(onnxFileNames); + } + hfMlResponseKf.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponseKf.init(); + } + } + } + + // LF cuts - Cuts on LF tracks reco + // Selection on LF related informations + // returns true if all cuts are passed + template + bool SelectOnLF(const T& candidate, const int& inputPtBin) + { + + registry.fill(HIST("hSelStatusLf"), 0.0); + + // Eta selection of V0, Cascade daughters + double etaV0PosDau = candidate.etaV0PosDau(); + double etaV0NegDau = candidate.etaV0NegDau(); + double etaPiFromCasc = candidate.etaBachFromCasc(); + + if (std::abs(etaV0PosDau) > etaTrackLFDauMax || std::abs(etaV0NegDau) > etaTrackLFDauMax || std::abs(etaPiFromCasc) > etaTrackLFDauMax) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 1.0); + + // Minimum radius cut + double radiusV0 = RecoDecay::sqrtSumOfSquares(candidate.xDecayVtxV0(), candidate.yDecayVtxV0()); + double radiusCasc = RecoDecay::sqrtSumOfSquares(candidate.xDecayVtxCascade(), candidate.yDecayVtxCascade()); + + if (radiusV0 < radiusV0Min) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 2.0); + if (radiusCasc < radiusCascMin) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 3.0); + + // Cosine of pointing angle + if (candidate.cosPAV0() < cuts->get(inputPtBin, "cosPAV0")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 4.0); + if (candidate.cosPACasc() < cuts->get(inputPtBin, "cosPACasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 5.0); + + // Distance of Closest Approach(DCA) + if (candidate.dcaV0Dau() > cuts->get(inputPtBin, "dcaV0Dau")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 6.0); + + if (candidate.dcaCascDau() > cuts->get(inputPtBin, "dcaCascDau")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 7.0); + + if (std::abs(candidate.dcaXYToPvV0Dau0()) < cuts->get(inputPtBin, "dcaXYToPvV0Dau0")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 8.0); + + if (std::abs(candidate.dcaXYToPvV0Dau1()) < cuts->get(inputPtBin, "dcaXYToPvV0Dau1")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 9.0); + + if (std::abs(candidate.dcaXYToPvCascDau()) < cuts->get(inputPtBin, "dcaXYToPvCascDau")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 10.0); + + // pT: Bachelor + double ptPiFromCasc = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCasc(), candidate.pyBachFromCasc()); + if (std::abs(ptPiFromCasc) < ptPiFromCascMin) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 11.0); + + // Extra cuts for KFParticle + if constexpr (svReco == doKfParticle) { + // Cosine of Pointing angle + if (candidate.cosPaV0ToCasc() < cuts->get(inputPtBin, "cosPaV0ToCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 12.0); + + // DCA + if (std::abs(candidate.kfDcaXYCascToPv()) > cuts->get(inputPtBin, "kfDcaXYCascToPv")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 13.0); + + // Chi2 + if (candidate.chi2GeoV0() < 0 || candidate.chi2GeoV0() > cuts->get(inputPtBin, "chi2GeoV0")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 14.0); + if (candidate.chi2GeoCasc() < 0 || candidate.chi2GeoCasc() > cuts->get(inputPtBin, "chi2GeoCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 15.0); + if (candidate.chi2TopoV0ToPv() > 0 && candidate.chi2TopoV0ToPv() < cuts->get(inputPtBin, "chi2TopoV0ToPv")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 16.0); + if (candidate.chi2TopoCascToPv() < 0 || candidate.chi2TopoCascToPv() > cuts->get(inputPtBin, "chi2TopoCascToPv")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 17.0); + if (candidate.chi2TopoV0ToCasc() < 0 || candidate.chi2TopoV0ToCasc() > cuts->get(inputPtBin, "chi2TopoV0ToCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 18.0); + + // ldl + if (candidate.v0ldl() < cuts->get(inputPtBin, "v0ldl")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 19.0); + if (candidate.cascldl() < cuts->get(inputPtBin, "cascldl")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 20.0); + + // Decay length + if (std::abs(candidate.decayLenXYLambda()) < cuts->get(inputPtBin, "decayLenXYLambda")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 21.0); + if (std::abs(candidate.decayLenXYCasc()) < cuts->get(inputPtBin, "decayLenXYCasc")) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 22.0); + + } else { + // Impact parameter(DCA?) + if (std::abs(candidate.impactParCascXY()) < impactParXYCascMin || std::abs(candidate.impactParCascXY()) > impactParXYCascMax) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 12.0); + if (std::abs(candidate.impactParCascZ()) < impactParZCascMin || std::abs(candidate.impactParCascZ()) > impactParZCascMax) { + return false; + } + registry.fill(HIST("hSelStatusLf"), 13.0); + } + + // If passes all cuts, return true + return true; + } + + // HF cuts - Cuts on Charm baryon reco + // Apply cuts with charm baryon & charm bachelor related informations + // returns true if all cuts are passed + template + bool SelectOnHF(const T& candidate, const int& inputPtBin) + { + + registry.fill(HIST("hSelStatusHf"), 0.0); + + // eta selection on charm bayron bachelor + if (std::abs(candidate.etaBachFromCharmBaryon()) > etaTrackCharmBachMax) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 1.0); + // Distance of Closest Approach(DCA) + if (candidate.dcaCharmBaryonDau() > cuts->get(inputPtBin, "dcaCharmBaryonDau")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 2.0); + + // pT: Charm Bachelor + double ptPiFromCharmBaryon = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); + if (ptPiFromCharmBaryon < cuts->get(inputPtBin, "ptPiFromCharmBaryon")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 3.0); + + // specific selections with KFParticle output + if constexpr (svReco == doKfParticle) { + // Cosine of pointing angle + if (candidate.cosPaCascToXic() < cuts->get(inputPtBin, "cosPaCascToXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 4.0); + + // DCA + if (std::abs(candidate.kfDcaXYPiFromXic()) > cuts->get(inputPtBin, "kfDcaXYPiFromXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 5.0); + + // Chi2 + if (candidate.chi2GeoXic() < 0 || candidate.chi2GeoXic() > cuts->get(inputPtBin, "chi2GeoXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 6.0); + if (candidate.chi2TopoXicToPv() < 0 || candidate.chi2TopoXicToPv() > cuts->get(inputPtBin, "chi2TopoXicToPv")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 7.0); + if (candidate.chi2TopoPiFromXicToPv() < 0 || candidate.chi2TopoPiFromXicToPv() > cuts->get(inputPtBin, "chi2TopoPiFromXicToPv")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 8.0); + if (candidate.chi2TopoCascToXic() < 0 || candidate.chi2TopoCascToXic() > cuts->get(inputPtBin, "chi2TopoCascToXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 9.0); + + // Decay Length + if (std::abs(candidate.decayLenXYXic()) > cuts->get(inputPtBin, "decayLenXYXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 10.0); + + // ctau + if (std::abs(candidate.cTauXic()) > cuts->get(inputPtBin, "cTauXic")) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 11.0); + } else { + // Impact parameter(DCA?) + if ((std::abs(candidate.impactParBachFromCharmBaryonXY()) < impactParXYPiFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonXY()) > impactParXYPiFromCharmBaryonMax)) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 4.0); + if ((std::abs(candidate.impactParBachFromCharmBaryonZ()) < impactParZPiFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonZ()) > impactParZPiFromCharmBaryonMax)) { + return false; + } + registry.fill(HIST("hSelStatusHf"), 5.0); + } + + // If passes all cuts, return true + return true; + } + + template + void runSelection(TCandTable const& candidates, + 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 + outputMlXic0ToXiPi.clear(); + + auto trackV0PosDau = lfTracks.rawIteratorAt(candidate.posTrackId()); + auto trackV0NegDau = lfTracks.rawIteratorAt(candidate.negTrackId()); + auto trackPiFromCasc = lfTracks.rawIteratorAt(candidate.bachelorId()); + auto trackPiFromCharm = tracks.rawIteratorAt(candidate.bachelorFromCharmBaryonId()); + + auto trackPiFromLam = trackV0NegDau; + auto trackPrFromLam = trackV0PosDau; + + int8_t signDecay = candidate.signDecay(); // sign of pi <- cascade + + if (signDecay > 0) { + trackPiFromLam = trackV0PosDau; + trackPrFromLam = trackV0NegDau; + registry.fill(HIST("hSelSignDec"), 1); // anti-particle decay + } else { + registry.fill(HIST("hSelSignDec"), 0); // particle decay + } + + // pT selection + auto ptCandXic0 = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + int pTBin = findBin(binsPt, ptCandXic0); + if (pTBin == -1) { + resultSelections = false; + } + + // Topological selection + const bool selectionResOnLF = SelectOnLF(candidate, pTBin); + const bool selectionResOnHF = SelectOnHF(candidate, pTBin); + if (!selectionResOnLF || !selectionResOnHF) { + resultSelections = false; + } + + // TPC clusters selections + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 0.0); + } + if (applyTrkSelLf) { + if (!isSelectedTrackTpcQuality(trackPiFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 1.0); + } + } + + if (!isSelectedTrackTpcQuality(trackPrFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 2.0); + } + } + + if (!isSelectedTrackTpcQuality(trackPiFromCasc, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 3.0); + } + } + } + + if (!isSelectedTrackTpcQuality(trackPiFromCharm, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 4.0); + } + } + + // ITS clusters selection + if (!isSelectedTrackItsQuality(trackPiFromCharm, nClustersItsMin, itsChi2PerClusterMax) || trackPiFromCharm.itsNClsInnerBarrel() < nClustersItsInnBarrMin) { + resultSelections = false; + } else { + if (resultSelections) { + registry.fill(HIST("hSelStatusCluster"), 5.0); + } + } + + // Track level PID selection + if (resultSelections) { + registry.fill(HIST("hSelStatusPID"), 0.0); + } + int statusPidPrFromLam = -999; + int statusPidPiFromLam = -999; + int statusPidPiFromCasc = -999; + int statusPidPiFromCharmBaryon = -999; + + int infoTpcStored = 0; + int infoTofStored = 0; + + if (usePidTpcOnly == usePidTpcTofCombined) { + LOGF(fatal, "Check the PID configurables, usePidTpcOnly and usePidTpcTofCombined can't have the same value"); + } + + if (trackPiFromLam.hasTPC()) { + SETBIT(infoTpcStored, PiFromLam); + } + if (trackPrFromLam.hasTPC()) { + SETBIT(infoTpcStored, PrFromLam); + } + if (trackPiFromCasc.hasTPC()) { + SETBIT(infoTpcStored, PiFromCasc); + } + if (trackPiFromCharm.hasTPC()) { + SETBIT(infoTpcStored, PiFromCharm); + } + if (trackPiFromLam.hasTOF()) { + SETBIT(infoTofStored, PiFromLam); + } + if (trackPrFromLam.hasTOF()) { + SETBIT(infoTofStored, PrFromLam); + } + if (trackPiFromCasc.hasTOF()) { + SETBIT(infoTofStored, PiFromCasc); + } + if (trackPiFromCharm.hasTOF()) { + SETBIT(infoTofStored, PiFromCharm); + } + + if (usePidTpcOnly) { + statusPidPrFromLam = selectorProton.statusTpc(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpc(trackPiFromLam); + statusPidPiFromCasc = selectorPion.statusTpc(trackPiFromCasc); + statusPidPiFromCharmBaryon = selectorPion.statusTpc(trackPiFromCharm); + } else if (usePidTpcTofCombined) { + statusPidPrFromLam = selectorProton.statusTpcOrTof(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpcOrTof(trackPiFromLam); + statusPidPiFromCasc = selectorPion.statusTpcOrTof(trackPiFromCasc); + statusPidPiFromCharmBaryon = selectorPion.statusTpcOrTof(trackPiFromCharm); + } + + bool statusPidLambda = (statusPidPrFromLam == TrackSelectorPID::Accepted) && (statusPidPiFromLam == TrackSelectorPID::Accepted); + if (statusPidLambda && resultSelections) { + registry.fill(HIST("hSelStatusPID"), 1.0); + } + bool statusPidCascade = (statusPidLambda && statusPidPiFromCasc == TrackSelectorPID::Accepted); + if (statusPidCascade && resultSelections) { + registry.fill(HIST("hSelStatusPID"), 2.0); + } + bool statusPidCharmBaryon = (statusPidCascade && statusPidPiFromCharmBaryon == TrackSelectorPID::Accepted); + if (statusPidCharmBaryon && resultSelections) { + registry.fill(HIST("hSelStatusPID"), 3.0); + } + + // invariant mass cuts + bool statusInvMassLambda = false; + bool statusInvMassCascade = false; + bool statusInvMassCharmBaryon = false; + + double invMassLambda = candidate.invMassLambda(); + double invMassCascade = candidate.invMassCascade(); + double invMassCharmBaryon = candidate.invMassCharmBaryon(); + + if (std::abs(invMassLambda - o2::constants::physics::MassLambda0) < v0MassWindow) { + statusInvMassLambda = true; + } + if (std::abs(invMassCascade - o2::constants::physics::MassXiMinus) < cascMassWindow) { + statusInvMassCascade = true; + } + if ((invMassCharmBaryon >= invMassCharmBaryonMin) && (invMassCharmBaryon <= invMassCharmBaryonMax)) { + statusInvMassCharmBaryon = true; + } + + // ML BDT selection + if (applyMl) { + bool isSelectedMlXic0 = false; + std::vector inputFeaturesXic0 = {}; + if constexpr (svReco == doDcaFitter) { + inputFeaturesXic0 = hfMlResponseDca.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponseDca.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); + } else { + inputFeaturesXic0 = hfMlResponseKf.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); + isSelectedMlXic0 = hfMlResponseKf.isSelectedMl(inputFeaturesXic0, ptCandXic0, outputMlXic0ToXiPi); + } + if (!isSelectedMlXic0) { + continue; + } + hfMlToXiPi(outputMlXic0ToXiPi); + } + + // Fill in selection result + if constexpr (svReco == doDcaFitter) { + hfSelToXiPi(statusPidLambda, statusPidCascade, statusPidCharmBaryon, statusInvMassLambda, statusInvMassCascade, statusInvMassCharmBaryon, resultSelections, infoTpcStored, infoTofStored, + trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), + trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); + } else { + // Convert resultSelectrions to false if one of pid status and inv status is false + // This is only needed for KF(currently) since output selection table doesn't contain those information + if (!statusPidCharmBaryon || !statusInvMassLambda || !statusInvMassCascade || !statusInvMassCharmBaryon) { + resultSelections = false; + } + hfSelToXiPiKf(resultSelections, + trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), + trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); + } + + // Fill in invariant mass histogram + if (resultSelections) { + registry.fill(HIST("hInvMassCharmBaryonWoPidInvMassCut"), invMassCharmBaryon); + } + if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && statusInvMassCascade && statusInvMassCharmBaryon && resultSelections) { + registry.fill(HIST("hInvMassCharmBaryon"), invMassCharmBaryon); + } else { + registry.fill(HIST("hInvMassCharmBaryonBkg"), invMassCharmBaryon); + } + + } // end of candidate loop + } // end run fuction + + /////////////////////////////////// + /// Process with DCAFitter // + /////////////////////////////////// + void processSelectionDCAFitter(aod::HfCandToXiPi const& candidates, TracksSel const& tracks, TracksSelLf const& lfTracks) + { + runSelection(candidates, tracks, lfTracks); + } + PROCESS_SWITCH(HfCandidateSelectorToXiPiQa, processSelectionDCAFitter, "Xic0 candidate selection with DCAFitter output", true); + + //////////////////////////////////// + /// Process with KFParticle // + //////////////////////////////////// + void processSelectionKFParticle(aod::HfCandToXiPiKf const& candidates, TracksSel const& tracks, TracksSelLf const& lfTracks) + { + runSelection(candidates, tracks, lfTracks); + } + PROCESS_SWITCH(HfCandidateSelectorToXiPiQa, processSelectionKFParticle, "Xic0 candidate selection with KFParticle output", false); + +}; // end struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx index 5378586cff8..bb52685c14e 100644 --- a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx @@ -107,7 +107,7 @@ struct HfDerivedDataCreatorB0ToDPi { using THfCandDaughtersMl = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_b0::isSelB0ToDPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; - Filter filterMcGenMatching = nabs(aod::hf_cand_b0::flagMcMatchGen) == static_cast(DecayChannelMain::B0ToDminusPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(DecayChannelMain::B0ToDminusPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -121,10 +121,10 @@ struct HfDerivedDataCreatorB0ToDPi { Partition candidatesMlAll = aod::hf_sel_candidate_b0::isSelB0ToDPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_b0::isSelB0ToDPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx index 05c34f4c85b..5baaec8dafa 100644 --- a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx @@ -72,6 +72,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { // Candidates Produces rowCandidatePar; Produces rowCandidateParD0; + Produces rowCandidateParD0E; Produces rowCandidateParE; Produces rowCandidateSel; Produces rowCandidateMl; @@ -83,6 +84,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { HfConfigurableDerivedData confDerData; Configurable fillCandidatePar{"fillCandidatePar", true, "Fill candidate parameters"}; Configurable fillCandidateParD0{"fillCandidateParD0", true, "Fill D0 candidate parameters"}; + Configurable fillCandidateParD0E{"fillCandidateParD0E", true, "Fill additional D0 candidate parameters"}; Configurable fillCandidateParE{"fillCandidateParE", true, "Fill candidate extended parameters"}; Configurable fillCandidateSel{"fillCandidateSel", true, "Fill candidate selection flags"}; Configurable fillCandidateMl{"fillCandidateMl", true, "Fill candidate selection ML scores"}; @@ -108,7 +110,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { using THfCandDaughtersMl = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBplusToD0Pi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; - Filter filterMcGenMatching = nabs(aod::hf_cand_bplus::flagMcMatchGen) == static_cast(DecayChannelMain::BplusToD0Pi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(DecayChannelMain::BplusToD0Pi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -122,10 +124,10 @@ struct HfDerivedDataCreatorBplusToD0Pi { Partition candidatesMlAll = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); - Partition candidatesMcBkg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); void init(InitContext const&) { @@ -197,6 +199,32 @@ struct HfDerivedDataCreatorBplusToD0Pi { sigmas[HfProngSpecies::Kaon][HfProngSpecies::Kaon][1], sigmas[HfProngSpecies::Kaon][HfProngSpecies::Kaon][2]); } + if (fillCandidateParD0E) { + float invMassD0 = 0.; + if (candFlag == 0) { + invMassD0 = HfHelper::invMassD0ToPiK(prongCharm); + } else if (candFlag == 1) { + invMassD0 = HfHelper::invMassD0barToKPi(prongCharm); + } + rowCandidateParD0E( + prongCharm.chi2PCA(), + prongCharm.nProngsContributorsPV(), + invMassD0, + prongCharm.maxNormalisedDeltaIP(), + prongCharm.decayLengthXY(), + prongCharm.decayLengthNormalised(), + prongCharm.decayLengthXYNormalised(), + prongCharm.impactParameterNormalised0(), + prongCharm.impactParameterNormalised1(), + prongCharm.pxProng0(), + prongCharm.pyProng0(), + prongCharm.pzProng0(), + prongCharm.pxProng1(), + prongCharm.pyProng1(), + prongCharm.pzProng1(), + prongCharm.ptProng0(), + prongCharm.ptProng1()); + } if (fillCandidateParE) { rowCandidateParE( candidate.xSecondaryVertex(), @@ -209,6 +237,10 @@ struct HfDerivedDataCreatorBplusToD0Pi { candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), candidate.errorImpactParameter1(), HfHelper::cosThetaStarBplus(candidate), ct); @@ -277,6 +309,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { reserveTable(rowCandidatePar, fillCandidatePar, sizeTableCand); reserveTable(rowCandidateParD0, fillCandidateParD0, sizeTableCand); reserveTable(rowCandidateParE, fillCandidateParE, sizeTableCand); + reserveTable(rowCandidateParD0E, fillCandidateParD0E, sizeTableCand); reserveTable(rowCandidateSel, fillCandidateSel, sizeTableCand); reserveTable(rowCandidateMl, fillCandidateMl, sizeTableCand); reserveTable(rowCandidateMlD0, fillCandidateMlD0, sizeTableCand); diff --git a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx index 6e9a18014a5..9041d4d7c2e 100644 --- a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx @@ -105,7 +105,7 @@ struct HfDerivedDataCreatorD0ToKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesKfPerCollision = aod::hf_cand::collisionId; @@ -127,14 +127,14 @@ struct HfDerivedDataCreatorD0ToKPi { Partition candidatesMcMlAll = aod::hf_sel_candidate_d0::isSelD0 >= 0; Partition candidatesMcKfMlAll = aod::hf_sel_candidate_d0::isSelD0 >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcMlSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfMlSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition candidatesMcKfMlBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition candidatesMcKfMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); void init(InitContext const&) { @@ -310,7 +310,7 @@ struct HfDerivedDataCreatorD0ToKPi { double const ct = HfHelper::ctD0(candidate); double const y = HfHelper::yD0(candidate); - float massD0, massD0bar; + float massD0{}, massD0bar{}; float topolChi2PerNdf = -999.; if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { massD0 = candidate.kfGeoMassD0(); diff --git a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx index 957ad139756..ddc56bfaebc 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx @@ -102,7 +102,7 @@ struct HfDerivedDataCreatorDplusToPiKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; // select candidates which passed all cuts at least up to RecoMl - 1 - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -116,10 +116,10 @@ struct HfDerivedDataCreatorDplusToPiKPi { Partition candidatesMlAll = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); void init(InitContext const&) { @@ -208,8 +208,11 @@ struct HfDerivedDataCreatorDplusToPiKPi { candidate.pyProng2(), candidate.pzProng2(), candidate.tpcTofNSigmaPi0(), + candidate.tpcTofNSigmaPi1(), + candidate.tpcTofNSigmaPi2(), + candidate.tpcTofNSigmaKa0(), candidate.tpcTofNSigmaKa1(), - candidate.tpcTofNSigmaPi2()); + candidate.tpcTofNSigmaKa2()); } if (fillCandidateMl) { rowCandidateMl( diff --git a/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx index 0a5f217e19e..587b967af0b 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx @@ -100,7 +100,7 @@ struct HfDerivedDataCreatorDsToKKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi & static_cast(BIT(aod::SelectionStep::RecoMl - 1))) != 0; // select candidates which passed all cuts at least up to RecoMl - 1 - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -114,10 +114,10 @@ struct HfDerivedDataCreatorDsToKKPi { Partition candidatesMlAll = aod::hf_sel_candidate_ds::isSelDsToKKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_ds::isSelDsToKKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx index 1a15c3b1fb3..a04dc0cf033 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx @@ -98,7 +98,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; - Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -112,10 +112,10 @@ struct HfDerivedDataCreatorDstarToD0Pi { Partition candidatesMlAll = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; Partition candidatesMcMlAll = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.cxx new file mode 100644 index 00000000000..371b9ab9c4c --- /dev/null +++ b/PWGHF/TableProducer/derivedDataCreatorLcToK0sP.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. + +/// \file derivedDataCreatorLcToK0sP.cxx +/// \brief Producer of derived tables of Lc candidates, collisions and MC particles +/// \note Based on treeCreatorLcToK0sP.cxx and derivedDataCreatorD0ToKPi.cxx +/// +/// \author Luigi Dello Stritto , Marietta-Blau Institute +/// \author Vít Kučera , Inha University + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/AliasTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsDerivedData.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::hf_derived; + +/// Writes the full information in an output TTree +struct HfDerivedDataCreatorLcToK0sP { + HfProducesDerivedData< + o2::aod::HfLcToK0sPBases, + o2::aod::HfLcToK0sPCollBases, + o2::aod::HfLcToK0sPCollIds, + o2::aod::HfLcToK0sPMcCollBases, + o2::aod::HfLcToK0sPMcCollIds, + o2::aod::HfLcToK0sPMcRCollIds, + o2::aod::HfLcToK0sPPBases, + o2::aod::HfLcToK0sPPIds> + rowsCommon; + // Candidates + Produces rowCandidatePar; + Produces rowCandidateParE; + Produces rowCandidateSel; + Produces rowCandidateMl; + Produces rowCandidateId; + Produces rowCandidateMc; + + // Switches for filling tables + HfConfigurableDerivedData confDerData; + Configurable fillCandidatePar{"fillCandidatePar", true, "Fill candidate parameters"}; + Configurable fillCandidateParE{"fillCandidateParE", true, "Fill candidate extended parameters"}; + Configurable fillCandidateSel{"fillCandidateSel", true, "Fill candidate selection flags"}; + Configurable fillCandidateMl{"fillCandidateMl", true, "Fill candidate selection ML scores"}; + Configurable fillCandidateId{"fillCandidateId", true, "Fill original indices from the candidate table"}; + Configurable fillCandidateMc{"fillCandidateMc", true, "Fill candidate MC info"}; + // Parameters for production of training samples + 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"}; + + SliceCache cache; + static constexpr double Mass{o2::constants::physics::MassLambdaCPlus}; + + using CollisionsWCentMult = soa::Join; + using CollisionsWMcCentMult = soa::Join; + using TracksWPid = soa::Join; + using SelectedCandidates = soa::Filtered>; + using SelectedCandidatesMc = soa::Filtered>; + using SelectedCandidatesMl = soa::Filtered>; + using SelectedCandidatesMcMl = soa::Filtered>; + using MatchedGenCandidatesMc = soa::Filtered>; + using TypeMcCollisions = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 1; + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == 1; + + Preslice candidatesPerCollision = aod::hf_cand::collisionId; + Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; + Preslice candidatesMlPerCollision = aod::hf_cand::collisionId; + Preslice candidatesMcMlPerCollision = aod::hf_cand::collisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + + // trivial partitions for all candidates to allow "->sliceByCached" inside processCandidates + Partition candidatesAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + Partition candidatesMcAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + Partition candidatesMlAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + Partition candidatesMcMlAll = aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= 0; + // partitions for signal and background + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == 1; + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 1; + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == 1; + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 1; + + void init(InitContext const&) + { + std::array doprocess{doprocessData, doprocessMcSig, doprocessMcBkg, doprocessMcAll, doprocessDataMl, doprocessMcMlSig, doprocessMcMlBkg, doprocessMcMlAll, doprocessMcGenOnly}; + if (std::accumulate(doprocess.begin(), doprocess.end(), 0) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } + rowsCommon.init(confDerData); + } + + template + void fillTablesCandidate(const T& candidate, const U& bach, int candFlag, double invMass, + double ct, double ctV0, double y, int8_t flagMc, int8_t origin, const std::vector& mlScores) + { + rowsCommon.fillTablesCandidate(candidate, invMass, y); + if (fillCandidatePar) { + rowCandidatePar( + candidate.chi2PCA(), + candidate.cpa(), + candidate.cpaXY(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.v0radius(), + candidate.v0cosPA(), + candidate.mLambda(), + candidate.mAntiLambda(), + candidate.mK0Short(), + candidate.mGamma(), + candidate.dcaV0daughters(), + candidate.ptV0Pos(), + candidate.ptV0Neg(), + candidate.decayLengthV0(), + candidate.dcanegtopv(), + candidate.dcapostopv(), + bach.tpcNSigmaPr(), + bach.tofNSigmaPr(), + ctV0); + } + if (fillCandidateParE) { + rowCandidateParE( + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.rSecondaryVertex(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxpos(), + candidate.pypos(), + candidate.pzpos(), + candidate.pxneg(), + candidate.pyneg(), + candidate.pzneg(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + ct); + } + if (fillCandidateSel) { + rowCandidateSel( + BIT(candFlag)); + } + if (fillCandidateMl) { + rowCandidateMl( + mlScores); + } + if (fillCandidateId) { + rowCandidateId( + candidate.collisionId(), + candidate.prong0Id(), + candidate.posTrackId(), + candidate.negTrackId()); + } + if (fillCandidateMc) { + rowCandidateMc( + flagMc, + origin); + } + } + + template + void processCandidates(CollType const& collisions, + Partition& candidates, + TracksWPid const&, + aod::BCs const&) + { + // Fill collision properties + if constexpr (IsMc) { + if (confDerData.fillMcRCollId) { + rowsCommon.matchedCollisions.clear(); + } + } + auto sizeTableColl = collisions.size(); + rowsCommon.reserveTablesColl(sizeTableColl); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candidatesThisColl = candidates->sliceByCached(aod::hf_cand::collisionId, thisCollId, cache); // FIXME + auto sizeTableCand = candidatesThisColl.size(); + LOGF(debug, "Rec. collision %d has %d candidates", thisCollId, sizeTableCand); + // Skip collisions without HF candidates (and without HF particles in matched MC collisions if saving indices of reconstructed collisions matched to MC collisions) + bool mcCollisionHasMcParticles{false}; + if constexpr (IsMc) { + mcCollisionHasMcParticles = confDerData.fillMcRCollId && collision.has_mcCollision() && rowsCommon.hasMcParticles[collision.mcCollisionId()]; + LOGF(debug, "Rec. collision %d has MC collision %d with MC particles? %s", thisCollId, collision.mcCollisionId(), mcCollisionHasMcParticles ? "yes" : "no"); + } + if (sizeTableCand == 0 && (!confDerData.fillMcRCollId || !mcCollisionHasMcParticles)) { + LOGF(debug, "Skipping rec. collision %d", thisCollId); + continue; + } + LOGF(debug, "Filling rec. collision %d at derived index %d", thisCollId, rowsCommon.rowCollBase.lastIndex() + 1); + rowsCommon.fillTablesCollision(collision); + + // Fill candidate properties + rowsCommon.reserveTablesCandidates(sizeTableCand); + reserveTable(rowCandidatePar, fillCandidatePar, sizeTableCand); + reserveTable(rowCandidateParE, fillCandidateParE, sizeTableCand); + reserveTable(rowCandidateSel, fillCandidateSel, sizeTableCand); + reserveTable(rowCandidateMl, fillCandidateMl, sizeTableCand); + reserveTable(rowCandidateId, fillCandidateId, sizeTableCand); + if constexpr (IsMc) { + reserveTable(rowCandidateMc, fillCandidateMc, sizeTableCand); + } + int8_t flagMcRec = 0, origin = 0; + for (const auto& candidate : candidatesThisColl) { + if constexpr (IsMc) { + flagMcRec = candidate.flagMcMatchRec(); + origin = candidate.originMcRec(); + if constexpr (OnlyBkg) { + if (std::abs(flagMcRec) == 1) { + continue; + } + if (downSampleBkgFactor < 1.) { + float const pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + } + if constexpr (OnlySig) { + if (std::abs(flagMcRec) != 1) { + continue; + } + } + } else { + if (downSampleBkgFactor < 1.) { + float const pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + } + auto bach = candidate.template prong0_as(); // bachelor + double const ct = HfHelper::ctLc(candidate); + double const ctV0 = HfHelper::ctV0K0s(candidate); + double const y = HfHelper::yLc(candidate); + float const massLcToK0sP = HfHelper::invMassLcToK0sP(candidate); + std::vector mlScoresLcToK0sP; + if constexpr (IsMl) { + std::copy(candidate.mlProbLcToK0sP().begin(), candidate.mlProbLcToK0sP().end(), std::back_inserter(mlScoresLcToK0sP)); + } + if (candidate.isSelLcToK0sP()) { + fillTablesCandidate(candidate, bach, 0, massLcToK0sP, ct, ctV0, y, flagMcRec, origin, mlScoresLcToK0sP); + } + } + } + } + + void processData(CollisionsWCentMult const& collisions, + SelectedCandidates const&, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processCandidates(collisions, candidatesAll, tracks, bcs); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processData, "Process data", true); + + void processMcSig(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMc const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcSig, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcSig, "Process MC only for signals", false); + + void processMcBkg(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMc const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcBkg, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcBkg, "Process MC only for background", false); + + void processMcAll(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMc const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcAll, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcAll, "Process MC", false); + + // ML versions + + void processDataMl(CollisionsWCentMult const& collisions, + SelectedCandidatesMl const&, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processCandidates(collisions, candidatesMlAll, tracks, bcs); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processDataMl, "Process data with ML", false); + + void processMcMlSig(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMcMl const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcMlSig, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcMlSig, "Process MC with ML only for signals", false); + + void processMcMlBkg(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMcMl const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcMlBkg, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcMlBkg, "Process MC with ML only for background", false); + + void processMcMlAll(CollisionsWMcCentMult const& collisions, + SelectedCandidatesMcMl const&, + TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); + processCandidates(collisions, candidatesMcMlAll, tracks, bcs); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcMlAll, "Process MC with ML", false); + + void processMcGenOnly(TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles) + { + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorLcToK0sP, processMcGenOnly, "Process MC gen. only", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx index b96ac350953..efecd6f6713 100644 --- a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx @@ -100,7 +100,7 @@ struct HfDerivedDataCreatorLcToPKPi { using TypeMcCollisions = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 1 || aod::hf_sel_candidate_lc::isSelLcToPiKP >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -114,10 +114,10 @@ struct HfDerivedDataCreatorLcToPKPi { Partition candidatesMlAll = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_lc::isSelLcToPKPi >= 0; // partitions for signal and background - Partition candidatesMcSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); - Partition candidatesMcBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); - Partition candidatesMcMlSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcMlSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); + Partition candidatesMcMlBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx index fa52ec0a79f..9e0529b97d6 100644 --- a/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx @@ -102,7 +102,7 @@ struct HfDerivedDataCreatorXicToXiPiPi { using THfCandDaughtersMl = aod::Cascades; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToXiPiPi & static_cast(BIT(o2::aod::hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoMl - 1))) != 0; - Filter filterMcGenMatching = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchGen != 0; + Filter filterMcGenMatching = aod::hf_cand_mc_flag::flagMcMatchGen != 0; Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -116,10 +116,10 @@ struct HfDerivedDataCreatorXicToXiPiPi { Partition candidatesMlAll = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= 0; Partition candidatesMcMlAll = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= 0; // partitions for signal and background - Partition candidatesMcSig = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec != 0; - Partition candidatesMcBkg = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec == 0; - Partition candidatesMcMlSig = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec != 0; - Partition candidatesMcMlBkg = aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchRec == 0; + Partition candidatesMcSig = aod::hf_cand_mc_flag::flagMcMatchRec != 0; + Partition candidatesMcBkg = aod::hf_cand_mc_flag::flagMcMatchRec == 0; + Partition candidatesMcMlSig = aod::hf_cand_mc_flag::flagMcMatchRec != 0; + Partition candidatesMcMlBkg = aod::hf_cand_mc_flag::flagMcMatchRec == 0; void init(InitContext const&) { diff --git a/PWGHF/TableProducer/mcPidTof.cxx b/PWGHF/TableProducer/mcPidTof.cxx index d89a7c7144e..c0c6217607c 100644 --- a/PWGHF/TableProducer/mcPidTof.cxx +++ b/PWGHF/TableProducer/mcPidTof.cxx @@ -12,7 +12,7 @@ /// /// \file mcPidTof.cxx /// \author Fabrizio Grosa fabrizio.grosa@cern.ch -/// \brief Task to produce PID tables for TOF split for pi, K, p, de, copied from https://github.com/AliceO2Group/O2Physics/blob/master/Common/TableProducer/PID/pidTofMerge.cxx +/// \brief Task to produce PID tables for TOF split for pi, K, p, de, tr, he3, alpha copied from https://github.com/AliceO2Group/O2Physics/blob/master/Common/TableProducer/PID/pidTofMerge.cxx /// It works only for MC and adds the possibility to apply postcalibrations for MC. /// @@ -65,6 +65,7 @@ using namespace o2::framework; using namespace o2::pid; using namespace o2::framework::expressions; using namespace o2::track; +using namespace o2::common::core; o2::common::core::MetadataHelper metadataInfo; @@ -351,7 +352,7 @@ struct TofSignal { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Detector response and input parameters o2::pid::tof::TOFResoParamsV3 mRespParamsV3; - Service ccdb; + 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"}; @@ -471,7 +472,7 @@ struct TofEventTime { bool enableTableEvTimeTOFOnly = false; // Detector response and input parameters o2::pid::tof::TOFResoParamsV3 mRespParamsV3; - Service ccdb; + Service ccdb{}; TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration // Event time configurations @@ -720,6 +721,9 @@ static constexpr int IdxPi = 2; static constexpr int IdxKa = 3; static constexpr int IdxPr = 4; static constexpr int IdxDe = 5; +static constexpr int IdxTr = 6; +static constexpr int IdxHe = 7; +static constexpr int IdxAl = 8; /// Task to produce the response table struct McPidTof { @@ -728,16 +732,22 @@ struct McPidTof { Produces tablePIDKa; Produces tablePIDPr; Produces tablePIDDe; + Produces tablePIDTr; + Produces tablePIDHe; + Produces tablePIDAl; // Tables to produce (full) Produces tablePIDFullPi; Produces tablePIDFullKa; Produces tablePIDFullPr; Produces tablePIDFullDe; + Produces tablePIDFullTr; + Produces tablePIDFullHe; + Produces tablePIDFullAl; // Detector response parameters o2::pid::tof::TOFResoParamsV3 mRespParamsV3; - Service ccdb; + Service ccdb{}; TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration Configurable enableQaHistograms{"enableQaHistograms", false, "Flag to enable the QA histograms"}; @@ -768,7 +778,7 @@ struct McPidTof { { mTOFCalibConfig.inheritFromBaseTask(initContext); // Checking the tables are requested in the workflow and enabling them (only pi, K, p) - std::array supportedSpecies = {IdxPi, IdxKa, IdxPr, IdxDe}; + std::array supportedSpecies = {IdxPi, IdxKa, IdxPr, IdxDe, IdxTr, IdxHe, IdxAl}; for (auto iSpecie{0u}; iSpecie < supportedSpecies.size(); ++iSpecie) { // First checking tiny int flag = -1; @@ -855,6 +865,30 @@ struct McPidTof { } break; } + case IdxTr: { + if (fullTable) { + tablePIDFullTr.reserve(size); + } else { + tablePIDTr.reserve(size); + } + break; + } + case IdxHe: { + if (fullTable) { + tablePIDFullHe.reserve(size); + } else { + tablePIDHe.reserve(size); + } + break; + } + case IdxAl: { + if (fullTable) { + tablePIDFullAl.reserve(size); + } else { + tablePIDAl.reserve(size); + } + break; + } default: LOG(fatal) << "Wrong particle ID in reserveTable() for " << (fullTable ? "full" : "tiny") << " tables"; break; @@ -893,6 +927,27 @@ struct McPidTof { aod::pidtof_tiny::binning::packInTable(-999.f, tablePIDDe); } break; + case IdxTr: + if (fullTable) { + tablePIDFullTr(-999.f, -999.f); + } else { + aod::pidtof_tiny::binning::packInTable(-999.f, tablePIDTr); + } + break; + case IdxHe: + if (fullTable) { + tablePIDFullHe(-999.f, -999.f); + } else { + aod::pidtof_tiny::binning::packInTable(-999.f, tablePIDHe); + } + break; + case IdxAl: + if (fullTable) { + tablePIDFullAl(-999.f, -999.f); + } else { + aod::pidtof_tiny::binning::packInTable(-999.f, tablePIDAl); + } + break; default: LOG(fatal) << "Wrong particle ID in makeTableEmpty() for " << (fullTable ? "full" : "tiny") << " tables"; break; @@ -974,6 +1029,9 @@ struct McPidTof { constexpr auto ResponseKa = ResponseImplementation(); constexpr auto ResponsePr = ResponseImplementation(); constexpr auto ResponseDe = ResponseImplementation(); + constexpr auto ResponseTr = ResponseImplementation(); + constexpr auto ResponseHe = ResponseImplementation(); + constexpr auto ResponseAl = ResponseImplementation(); mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, bcs.iteratorAt(0)); // Update the calibration parameters @@ -1050,6 +1108,36 @@ struct McPidTof { aod::pidtof_tiny::binning::packInTable(nSigma, tablePIDDe); break; } + case IdxTr: { + nSigma = ResponseTr.GetSeparation(mRespParamsV3, trk); + if (enableMcRecalib && trk.has_mcParticle()) { + if (std::abs(trk.mcParticle().pdgCode()) == o2::constants::physics::kTriton) { // we rescale only true signal + nSigma = applyMcRecalib(IdxPr, trk.pt(), nSigma); // FIXME: currently postcalibrations for protons applied to tritons, to be checked + } + } + aod::pidtof_tiny::binning::packInTable(nSigma, tablePIDTr); + break; + } + case IdxHe: { + nSigma = ResponseHe.GetSeparation(mRespParamsV3, trk); + if (enableMcRecalib && trk.has_mcParticle()) { + if (std::abs(trk.mcParticle().pdgCode()) == o2::constants::physics::kHelium3) { // we rescale only true signal + nSigma = applyMcRecalib(IdxPr, trk.pt(), nSigma); // FIXME: currently postcalibrations for protons applied to helium3, to be checked + } + } + aod::pidtof_tiny::binning::packInTable(nSigma, tablePIDHe); + break; + } + case IdxAl: { + nSigma = ResponseAl.GetSeparation(mRespParamsV3, trk); + if (enableMcRecalib && trk.has_mcParticle()) { + if (std::abs(trk.mcParticle().pdgCode()) == o2::constants::physics::kAlpha) { // we rescale only true signal + nSigma = applyMcRecalib(IdxPr, trk.pt(), nSigma); // FIXME: currently postcalibrations for protons applied to alpha, to be checked + } + } + aod::pidtof_tiny::binning::packInTable(nSigma, tablePIDAl); + break; + } default: LOG(fatal) << "Wrong particle ID for standard tables"; break; @@ -1105,6 +1193,39 @@ struct McPidTof { tablePIDFullDe(resolution, nSigma); break; } + case IdxTr: { + resolution = ResponseTr.GetExpectedSigma(mRespParamsV3, trk); + nSigma = ResponseTr.GetSeparation(mRespParamsV3, trk, resolution); + if (enableMcRecalib && trk.has_mcParticle()) { + if (std::abs(trk.mcParticle().pdgCode()) == o2::constants::physics::kTriton) { // we rescale only true signal + nSigma = applyMcRecalib(IdxPr, trk.pt(), nSigma); // FIXME: currently postcalibrations for protons applied to tritons, to be checked + } + } + tablePIDFullTr(resolution, nSigma); + break; + } + case IdxHe: { + resolution = ResponseHe.GetExpectedSigma(mRespParamsV3, trk); + nSigma = ResponseHe.GetSeparation(mRespParamsV3, trk, resolution); + if (enableMcRecalib && trk.has_mcParticle()) { + if (std::abs(trk.mcParticle().pdgCode()) == o2::constants::physics::kHelium3) { // we rescale only true signal + nSigma = applyMcRecalib(IdxPr, trk.pt(), nSigma); // FIXME: currently postcalibrations for protons applied to helium3, to be checked + } + } + tablePIDFullHe(resolution, nSigma); + break; + } + case IdxAl: { + resolution = ResponseAl.GetExpectedSigma(mRespParamsV3, trk); + nSigma = ResponseAl.GetSeparation(mRespParamsV3, trk, resolution); + if (enableMcRecalib && trk.has_mcParticle()) { + if (std::abs(trk.mcParticle().pdgCode()) == o2::constants::physics::kAlpha) { // we rescale only true signal + nSigma = applyMcRecalib(IdxPr, trk.pt(), nSigma); // FIXME: currently postcalibrations for protons applied to alpha, to be checked + } + } + tablePIDFullAl(resolution, nSigma); + break; + } default: LOG(fatal) << "Wrong particle ID for full tables"; break; diff --git a/PWGHF/TableProducer/pidCreator.cxx b/PWGHF/TableProducer/pidCreator.cxx index a563e8f5d43..f483d10d001 100644 --- a/PWGHF/TableProducer/pidCreator.cxx +++ b/PWGHF/TableProducer/pidCreator.cxx @@ -47,6 +47,12 @@ struct HfPidCreator { Produces trackPidTinyPr; Produces trackPidFullDe; Produces trackPidTinyDe; + Produces trackPidFullTr; + Produces trackPidTinyTr; + Produces trackPidFullHe; + Produces trackPidTinyHe; + Produces trackPidFullAl; + Produces trackPidTinyAl; /// Function to check whether the process function flag matches the need for filling the table /// \param initContext workflow context (argument of the init function) @@ -55,7 +61,7 @@ struct HfPidCreator { template void checkTableSwitch(InitContext& initContext, const std::string& table, TFlag& doprocess) { - auto isNeeded = isTableRequiredInWorkflow(initContext, table); + auto isNeeded = o2::common::core::isTableRequiredInWorkflow(initContext, table); if (isNeeded && !doprocess.value) { LOGF(fatal, "Table %s is needed but not requested. Enable the corresponding process function!", table); } @@ -81,6 +87,12 @@ struct HfPidCreator { checkTableSwitch(initContext, "PidTpcTofTinyPr", doprocessTinyPr); checkTableSwitch(initContext, "PidTpcTofFullDe", doprocessFullDe); checkTableSwitch(initContext, "PidTpcTofTinyDe", doprocessTinyDe); + checkTableSwitch(initContext, "PidTpcTofFullTr", doprocessFullTr); + checkTableSwitch(initContext, "PidTpcTofTinyTr", doprocessTinyTr); + checkTableSwitch(initContext, "PidTpcTofFullHe", doprocessFullHe); + checkTableSwitch(initContext, "PidTpcTofTinyHe", doprocessTinyHe); + checkTableSwitch(initContext, "PidTpcTofFullAl", doprocessFullAl); + checkTableSwitch(initContext, "PidTpcTofTinyAl", doprocessTinyAl); } void processDummy(aod::Collisions const&) {} @@ -111,6 +123,9 @@ struct HfPidCreator { PROCESS_PID(Ka) PROCESS_PID(Pr) PROCESS_PID(De) + PROCESS_PID(Tr) + PROCESS_PID(He) + PROCESS_PID(Al) #undef PROCESS_PID }; diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index af82614aa68..33e1c3a1669 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -20,6 +20,7 @@ /// \author Fabrizio Grosa , CERN /// \author Federica Zanone , Heidelberg University /// \author Ruiqi Yin , Fudan University +/// \author Biao Zhang , Heidelberg University #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/SelectorCuts.h" @@ -38,6 +39,7 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -63,6 +65,7 @@ #include #include #include +#include #include #include // for PV refit @@ -120,18 +123,42 @@ enum ChannelsProtonPid { LcToPK0S, NChannelsProtonPid }; + +enum ChannelsKaonPid { + Charm3ProngToKaon = 0, + NChannelsKaonPid +}; + +enum ChannelsLightNucleiPid { + CdToDeKPi = 0, + CtToTrKPi, + ChToHeKPi, + CaToAlKPi, + NChannelsLightNucleiPid +}; + // kaon PID (opposite-sign track in 3-prong decays) constexpr int ChannelKaonPid = ChannelsProtonPid::NChannelsProtonPid; constexpr int ChannelsDeuteronPid = ChannelsProtonPid::NChannelsProtonPid + 1; - +constexpr int ChannelsTritonPid = ChannelsProtonPid::NChannelsProtonPid + 2; +constexpr int ChannelsHeliumPid = ChannelsProtonPid::NChannelsProtonPid + 3; +constexpr int ChannelsAlphaPid = ChannelsProtonPid::NChannelsProtonPid + 4; +constexpr int NChannelsPidFor3Prong = static_cast(ChannelsProtonPid::NChannelsProtonPid) + static_cast(ChannelsKaonPid::NChannelsKaonPid) + static_cast(ChannelsLightNucleiPid::NChannelsLightNucleiPid); + +enum class ChannelsNucleiQA : int { + Deuteron = 0, + Triton = 1, + Helium3 = 2, + Alpha = 3 +}; /// Event selection struct HfTrackIndexSkimCreatorTagSelCollisions { Produces rowSelectedCollision; Configurable fillHistograms{"fillHistograms", true, "fill histograms"}; Configurable triggerClassName{"triggerClassName", "kINT7", "Run 2 trigger class, only for Run 2 converted data"}; - HfEventSelection hfEvSel; // event selection and monitoring - Service ccdb; // needed for evSelection + HfEventSelection hfEvSel; // event selection and monitoring + Service ccdb{}; // needed for evSelection // QA histos HistogramRegistry registry{"registry"}; @@ -309,8 +336,11 @@ struct HfTrackIndexSkimCreatorTagSelTracks { Configurable useIsGlobalTrackForSoftPion{"useIsGlobalTrackForSoftPion", false, "check isGlobalTrack status for soft pion tracks"}; Configurable useIsGlobalTrackWoDCAForSoftPion{"useIsGlobalTrackWoDCAForSoftPion", false, "check isGlobalTrackWoDCA status for soft pion tracks"}; Configurable useIsQualityTrackITSForSoftPion{"useIsQualityTrackITSForSoftPion", true, "check qualityTracksITS status for soft pion tracks"}; + // CharmNuclei track selection + Configurable> selectionsLightNuclei{"selectionsLightNuclei", {hf_presel_lightnuclei::CutsTrackQuality[0], hf_presel_lightnuclei::NParticleRows, hf_presel_lightnuclei::NVarCuts, hf_presel_lightnuclei::labelsRowsNucleiType, hf_presel_lightnuclei::labelsCutsTrack}, "nuclei track selections for deuteron / triton / helium applied if proper process function enabled"}; + Configurable> tpcPidBBParamsLightNuclei{"tpcPidBBParamsLightNuclei", {hf_presel_lightnuclei::BetheBlochParams[0], hf_presel_lightnuclei::NParticleRows, hf_presel_lightnuclei::NBetheBlochParams, hf_presel_lightnuclei::labelsRowsNucleiType, hf_presel_lightnuclei::labelsBetheBlochParams}, "TPC PID Bethe–Bloch parameter configurations for light nuclei (deuteron, triton, helium-3)"}; // proton PID, applied only if corresponding process function enabled - Configurable> selectionsPid{"selectionsPid", {hf_presel_pid::CutsPid[0], 5, 6, hf_presel_pid::labelsRowsPid, hf_presel_pid::labelsCutsPid}, "PID selections for proton / kaon / deuteron applied if proper process function enabled"}; + Configurable> selectionsPid{"selectionsPid", {hf_presel_pid::CutsPid[0], hf_presel_pid::NPidRows, hf_presel_pid::NPidCuts, hf_presel_pid::labelsRowsPid, hf_presel_pid::labelsCutsPid}, "PID selections for proton / kaon / deuteron / triton /helium applied if proper process function enabled"}; // CCDB Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; @@ -321,15 +351,15 @@ struct HfTrackIndexSkimCreatorTagSelTracks { SliceCache cache; // Needed for PV refitting - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber{}; using TracksWithSelAndDca = soa::Join; - using TracksWithSelAndDcaAndPidTpc = soa::Join; - using TracksWithSelAndDcaAndPidTof = soa::Join; - using TracksWithSelAndDcaAndPidTpcTof = soa::Join; + using TracksWithSelAndDcaAndPidTpc = soa::Join; + using TracksWithSelAndDcaAndPidTof = soa::Join; + using TracksWithSelAndDcaAndPidTpcTof = soa::Join; Preslice perCol = aod::track::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; @@ -341,7 +371,6 @@ struct HfTrackIndexSkimCreatorTagSelTracks { // proton PID, if enabled std::array selectorProton{}; TrackSelectorKa selectorKaon; - TrackSelectorDe selectorDeuteron; Partition pvContributors = ((aod::track::flags & static_cast(aod::track::PVContributor)) == static_cast(aod::track::PVContributor)); Partition pvContributorsWithPidTpc = ((aod::track::flags & static_cast(aod::track::PVContributor)) == static_cast(aod::track::PVContributor)); @@ -381,30 +410,37 @@ struct HfTrackIndexSkimCreatorTagSelTracks { } if (config.fillHistograms) { + const AxisSpec axisPtProng{360, 0., 36., "#it{p}_{T}^{track} (GeV/#it{c})"}; + const AxisSpec axisDca{400, -2., 2., "DCAxy to prim. vtx. (cm)"}; + const auto scaleEtaMax = 1.2; + const auto nBinsPerEta = 50; + // general tracks registry.add("hRejTracks", "Tracks;;entries", {HistType::kTH1D, {{25, 0.5, 25.5}}}); - registry.add("hPtNoCuts", "all tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}}); + registry.add("hPtNoCuts", "all tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPtProng}}); // 2-prong histograms - registry.add("hPtCuts2Prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}}); - registry.add("hDCAToPrimXYVsPtCuts2Prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {{360, 0., 36.}, {400, -2., 2.}}}); - registry.add("hEtaCuts2Prong", "tracks selected for 2-prong vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(0.6 * (config.etaMaxTrack2Prong - config.etaMinTrack2Prong) * 100), -1.2 * config.etaMinTrack2Prong, 1.2 * config.etaMaxTrack2Prong}}}); + registry.add("hPtCuts2Prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPtProng}}); + registry.add("hDCAToPrimXYVsPtCuts2Prong", "tracks selected for 2-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {axisPtProng, axisDca}}); + registry.add("hEtaCuts2Prong", "tracks selected for 2-prong vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(scaleEtaMax * (config.etaMaxTrack2Prong - config.etaMinTrack2Prong) * nBinsPerEta), scaleEtaMax * config.etaMinTrack2Prong, scaleEtaMax * config.etaMaxTrack2Prong}}}); // 3-prong histograms - registry.add("hPtCuts3Prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}}); - registry.add("hDCAToPrimXYVsPtCuts3Prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {{360, 0., 36.}, {400, -2., 2.}}}); - registry.add("hEtaCuts3Prong", "tracks selected for 3-prong vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(0.6 * (config.etaMaxTrack3Prong - config.etaMinTrack3Prong) * 100), -1.2 * config.etaMinTrack3Prong, 1.2 * config.etaMaxTrack3Prong}}}); + registry.add("hPtCuts3Prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPtProng}}); + registry.add("hDCAToPrimXYVsPtCuts3Prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {axisPtProng, axisDca}}); + registry.add("hEtaCuts3Prong", "tracks selected for 3-prong vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(scaleEtaMax * (config.etaMaxTrack3Prong - config.etaMinTrack3Prong) * nBinsPerEta), scaleEtaMax * config.etaMinTrack3Prong, scaleEtaMax * config.etaMaxTrack3Prong}}}); // bachelor (for V0 + bachelor decays) histograms - registry.add("hPtCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}}); - registry.add("hDCAToPrimXYVsPtCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {{360, 0., 36.}, {400, -2., 2.}}}); - registry.add("hEtaCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(0.6 * (config.etaMaxTrackBach - config.etaMinTrackBach) * 100), -1.2 * config.etaMinTrackBach, 1.2 * config.etaMaxTrackBach}}}); + registry.add("hPtCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPtProng}}); + registry.add("hDCAToPrimXYVsPtCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {axisPtProng, axisDca}}); + registry.add("hEtaCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(scaleEtaMax * (config.etaMaxTrackBach - config.etaMinTrackBach) * nBinsPerEta), scaleEtaMax * config.etaMinTrackBach, scaleEtaMax * config.etaMaxTrackBach}}}); // soft pion (for D*) histograms - registry.add("hPtCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}}); - registry.add("hDCAToPrimXYVsPtCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {{360, 0., 36.}, {400, -2., 2.}}}); - registry.add("hEtaCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{#eta};entries", {HistType::kTH1D, {{static_cast(0.6 * (config.etaMaxSoftPionForDstar - config.etaMinSoftPionForDstar) * 100), -1.2 * config.etaMinSoftPionForDstar, 1.2 * config.etaMaxSoftPionForDstar}}}); + registry.add("hPtCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPtProng}}); + registry.add("hDCAToPrimXYVsPtCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {axisPtProng, axisDca}}); + registry.add("hEtaCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{#eta};entries", {HistType::kTH1D, {{static_cast(scaleEtaMax * (config.etaMaxSoftPionForDstar - config.etaMinSoftPionForDstar) * nBinsPerEta), scaleEtaMax * config.etaMinSoftPionForDstar, scaleEtaMax * config.etaMaxSoftPionForDstar}}}); // bachelor (for cascade + bachelor decays) histograms - registry.add("hPtCutsCascadeBachelor", "tracks selected for cascade-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {{360, 0., 36.}}}); - registry.add("hDCAToPrimXYVsPtCutsCascadeBachelor", "tracks selected for cascade-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {{360, 0., 36.}, {400, -2., 2.}}}); - registry.add("hEtaCutsCascadeBachelor", "tracks selected for cascade-bachelor vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(0.6 * (config.etaMaxTrackBachLfCasc - config.etaMinTrackBachLfCasc) * 100), -1.2 * config.etaMinTrackBachLfCasc, 1.2 * config.etaMaxTrackBachLfCasc}}}); + + registry.add("hPtCutsCascadeBachelor", "tracks selected for cascade-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1D, {axisPtProng}}); + registry.add("hDCAToPrimXYVsPtCutsCascadeBachelor", "tracks selected for cascade-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2D, {axisPtProng, axisDca}}); + registry.add("hEtaCutsCascadeBachelor", "tracks selected for cascade-bachelor vertexing;#it{#eta};entries", {HistType::kTH1D, {{static_cast(scaleEtaMax * (config.etaMaxTrackBachLfCasc - config.etaMinTrackBachLfCasc) * nBinsPerEta), scaleEtaMax * config.etaMinTrackBachLfCasc, scaleEtaMax * config.etaMaxTrackBachLfCasc}}}); + registry.add("hTPCSignalsLightNuclei", "Light Nuclei;p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", {HistType::kTH2D, {{2000, -10., 10.}, {1000, 0., 2000.}}}); const std::string cutNames[nCuts + 1] = {"selected", "rej pT", "rej eta", "rej track quality", "rej dca"}; const std::string candNames[CandidateType::NCandidateTypes] = {"2-prong", "3-prong", "bachelor", "dstar", "lfCascBachelor"}; @@ -464,27 +500,173 @@ struct HfTrackIndexSkimCreatorTagSelTracks { selectorKaon.setRangePtTof(config.selectionsPid->get(ChannelKaonPid, 3u), config.selectionsPid->get(ChannelKaonPid, 4u)); // 3u == "minPtTof, 4u == "maxPtTof" selectorKaon.setRangeNSigmaTpc(-config.selectionsPid->get(ChannelKaonPid, 2u), config.selectionsPid->get(ChannelKaonPid, 2u)); // 2u == "nSigmaMaxTpc" selectorKaon.setRangeNSigmaTof(-config.selectionsPid->get(ChannelKaonPid, 5u), config.selectionsPid->get(ChannelKaonPid, 5u)); // 5u == "nSigmaMaxTof" + } + + /// Apply track-quality (ITS/TPC) + optional ITS-PID preselection for light-nucleus daughters used in charm-nuclei 3-prong channels (Cd/Ct/Ch). + /// \tparam TrackType Track providing ITS/TPC quality accessors. + /// \param track Daughter track to be tested (either prong0 or prong2). + /// \param lightnuclei Species selector: 0=Deuteron, 1=Triton, 2=Helium3. + /// \return true if the track passes all enabled selections. + template + bool applyPidAndTrackSelectionForCharmNuclei(const TrackType& track, + ChannelsNucleiQA lightnuclei) + { + // Row index in the selection table: 0 (De), 1 (Tr), 2 (He3) + const int row = static_cast(lightnuclei); + if (row < 0 || row >= NChannelsLightNucleiPid) { + return false; + } + + float nSigmaIts = -999.f; + + switch (lightnuclei) { + case ChannelsNucleiQA::Deuteron: + nSigmaIts = track.itsNSigmaDe(); + break; + case ChannelsNucleiQA::Triton: + nSigmaIts = track.itsNSigmaTr(); + break; + case ChannelsNucleiQA::Helium3: + nSigmaIts = track.itsNSigmaHe(); + break; + case ChannelsNucleiQA::Alpha: + nSigmaIts = track.itsNSigmaAl(); + break; + default: + LOG(fatal) << "Unhandled ChannelsNucleiQA " << static_cast(lightnuclei); + } + + // Load cuts for the selected species. + const float itsPidNsigmaMin = config.selectionsLightNuclei->get(row, 0u); + const float itsClusterSizeMin = config.selectionsLightNuclei->get(row, 1u); + const float itsClusterMin = config.selectionsLightNuclei->get(row, 2u); + const float itsIbClusterMin = config.selectionsLightNuclei->get(row, 3u); + const float tpcClusterMin = config.selectionsLightNuclei->get(row, 4u); + const float tpcCrossedRowsMin = config.selectionsLightNuclei->get(row, 5u); + const float tpcCrossedRowsOverFindMin = config.selectionsLightNuclei->get(row, 6u); + const float tpcSharedMax = config.selectionsLightNuclei->get(row, 7u); + const float tpcFracSharedMax = config.selectionsLightNuclei->get(row, 8u); + + // Optional: BB-based TPC nσ selection (only if enabled) + const float tpcBbPidNsigmaMax = config.selectionsLightNuclei->get(row, 9u); + + if (nSigmaIts < itsPidNsigmaMin) { + return false; + } + if (track.itsClusterSizes() < static_cast(itsClusterSizeMin)) { + return false; + } + if (track.itsNCls() < itsClusterMin) { + return false; + } + if (track.itsNClsInnerBarrel() < itsIbClusterMin) { + return false; + } + if (track.tpcNClsFound() < tpcClusterMin) { + return false; + } + if (track.tpcNClsCrossedRows() < tpcCrossedRowsMin) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < tpcCrossedRowsOverFindMin) { + return false; + } + if (track.tpcNClsShared() > tpcSharedMax) { + return false; + } + if (track.tpcFractionSharedCls() > tpcFracSharedMax) { + return false; + } + + const float tpcBbPidNsigma = getTPCNSigmaLightNucleiBetheBloch(track, lightnuclei); + if (std::abs(tpcBbPidNsigma) > tpcBbPidNsigmaMax) { + return false; + } + registry.fill(HIST("hTPCSignalsLightNuclei"), track.tpcInnerParam() * track.sign(), track.tpcSignal()); + return true; + } + + /// Compute TPC nσ for light nuclei (De/Tr/He3) using a Bethe–Bloch parameter configuration (BB-based PID). + /// + /// \tparam TrackType Track/ASoA row type providing TPC accessors. + /// \param track Track to be tested. + /// \param lightnuclei Species selector: 0=Deuteron, 1=Triton, 2=Helium3. + /// \return TPC nσ for the chosen nucleus hypothesis (or -999 if not applicable). + template + float getTPCNSigmaLightNucleiBetheBloch(const TrackType& track, ChannelsNucleiQA lightnuclei) + { + if (!track.hasTPC()) { + return -999.f; + } + + const int row = static_cast(lightnuclei); + if (row < 0 || row >= NChannelsLightNucleiPid) { + return -999.f; + } + + // Columns: [0..4] BB params, [5] relative resolution (sigma/mean) + const double bb0 = config.tpcPidBBParamsLightNuclei->get(row, 0u); + const double bb1 = config.tpcPidBBParamsLightNuclei->get(row, 1u); + const double bb2 = config.tpcPidBBParamsLightNuclei->get(row, 2u); + const double bb3 = config.tpcPidBBParamsLightNuclei->get(row, 3u); + const double bb4 = config.tpcPidBBParamsLightNuclei->get(row, 4u); + const double relRes = config.tpcPidBBParamsLightNuclei->get(row, 5u); + + if (relRes <= 0.f) { + return -999.f; + } + + // Mass/charge hypothesis for the selected nucleus. + double mass = 0.; + switch (lightnuclei) { + case ChannelsNucleiQA::Deuteron: + mass = MassDeuteron; + break; + case ChannelsNucleiQA::Triton: + mass = MassTriton; + break; + case ChannelsNucleiQA::Helium3: + mass = MassHelium3; + break; + case ChannelsNucleiQA::Alpha: + mass = MassAlpha; + break; + default: + LOG(fatal) << "Unhandled ChannelsNucleiQA " << static_cast(lightnuclei); + } + + const int charge = (lightnuclei == ChannelsNucleiQA::Helium3 || lightnuclei == ChannelsNucleiQA::Alpha) ? 2 : 1; + const float rigidity = track.tpcInnerParam(); // p / |q| note: here we didn't apply rigidity correction - selectorDeuteron.setRangePtTpc(config.selectionsPid->get(ChannelsDeuteronPid, 0u), config.selectionsPid->get(ChannelsDeuteronPid, 1u)); // 0u == "minPtTpc", 1u == "maxPtTpc" - selectorDeuteron.setRangePtTof(config.selectionsPid->get(ChannelsDeuteronPid, 3u), config.selectionsPid->get(ChannelsDeuteronPid, 4u)); // 3u == "minPtTof, 4u == "maxPtTof" - selectorDeuteron.setRangeNSigmaTpc(-config.selectionsPid->get(ChannelsDeuteronPid, 2u), config.selectionsPid->get(ChannelsDeuteronPid, 2u)); // 2u == "nSigmaMaxTpc" - selectorDeuteron.setRangeNSigmaTof(-config.selectionsPid->get(ChannelsDeuteronPid, 5u), config.selectionsPid->get(ChannelsDeuteronPid, 5u)); // 5u == "nSigmaMaxTof" + const double x = static_cast(charge) * static_cast(rigidity) / mass; + const double expBethe = common::BetheBlochAleph(x, bb0, bb1, bb2, bb3, bb4); + const double expSigma = expBethe * static_cast(relRes); + + if (expSigma <= 0.) { + return -999.f; + } + + return static_cast((track.tpcSignal() - expBethe) / expSigma); } /// PID track cuts (for proton only) /// \param hfTrack is a track - /// \return true if the track is compatible with a proton hypothesis - template - uint8_t isSelectedPid(const T& hfTrack) + /// \param hfTrackWithIts is a track joined with the ITS PID table + /// \return bit mask encoding PID compatibility per channel + template + uint8_t isSelectedPid(const T& hfTrack, const TrackWithIts& hfTrackWithIts) { - std::array statusPid{TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted}; + std::array statusPid{TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted, TrackSelectorPID::Accepted}; + auto boolToStatus = [](bool passed) { + return passed ? TrackSelectorPID::Accepted : TrackSelectorPID::Rejected; + }; + if constexpr (PidStrategy == ProtonPidStrategy::PidTofOnly) { if (hfTrack.hasTOF()) { for (auto iChannel{0u}; iChannel < ChannelsProtonPid::NChannelsProtonPid; ++iChannel) { statusPid[iChannel] = selectorProton[iChannel].statusTof(hfTrack); } statusPid[ChannelKaonPid] = selectorKaon.statusTof(hfTrack); - statusPid[ChannelsDeuteronPid] = selectorDeuteron.statusTof(hfTrack); } } if constexpr (PidStrategy == ProtonPidStrategy::PidTpcOnly) { @@ -493,7 +675,10 @@ struct HfTrackIndexSkimCreatorTagSelTracks { statusPid[iChannel] = selectorProton[iChannel].statusTpc(hfTrack); } statusPid[ChannelKaonPid] = selectorKaon.statusTpc(hfTrack); - statusPid[ChannelsDeuteronPid] = selectorDeuteron.statusTpc(hfTrack); + statusPid[ChannelsDeuteronPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Deuteron)); + statusPid[ChannelsTritonPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Triton)); + statusPid[ChannelsHeliumPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Helium3)); + statusPid[ChannelsAlphaPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Alpha)); } } if constexpr (PidStrategy == ProtonPidStrategy::PidTpcOrTof) { @@ -501,18 +686,24 @@ struct HfTrackIndexSkimCreatorTagSelTracks { statusPid[iChannel] = selectorProton[iChannel].statusTpcOrTof(hfTrack); } statusPid[ChannelKaonPid] = selectorKaon.statusTpcOrTof(hfTrack); - statusPid[ChannelsDeuteronPid] = selectorDeuteron.statusTpcOrTof(hfTrack); + statusPid[ChannelsDeuteronPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Deuteron)); + statusPid[ChannelsTritonPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Triton)); + statusPid[ChannelsHeliumPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Helium3)); + statusPid[ChannelsAlphaPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Alpha)); } if constexpr (PidStrategy == ProtonPidStrategy::PidTpcAndTof) { for (auto iChannel{0u}; iChannel < ChannelsProtonPid::NChannelsProtonPid; ++iChannel) { statusPid[iChannel] = selectorProton[iChannel].statusTpcAndTof(hfTrack); } statusPid[ChannelKaonPid] = selectorKaon.statusTpcAndTof(hfTrack); - statusPid[ChannelsDeuteronPid] = selectorDeuteron.statusTpcAndTof(hfTrack); + statusPid[ChannelsDeuteronPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Deuteron)); + statusPid[ChannelsTritonPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Triton)); + statusPid[ChannelsHeliumPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Helium3)); + statusPid[ChannelsAlphaPid] = boolToStatus(applyPidAndTrackSelectionForCharmNuclei(hfTrackWithIts, ChannelsNucleiQA::Alpha)); } - int8_t flag = BIT(ChannelsProtonPid::NChannelsProtonPid + 2) - 1; // all bits on (including the kaon one) - for (auto iChannel{0u}; iChannel < ChannelsProtonPid::NChannelsProtonPid + 2; ++iChannel) { + int8_t flag = BIT(NChannelsPidFor3Prong) - 1; // all bits on (including the kaon one) + for (auto iChannel{0u}; iChannel < NChannelsPidFor3Prong; ++iChannel) { if (statusPid[iChannel] == TrackSelectorPID::Rejected) { CLRBIT(flag, iChannel); } @@ -937,7 +1128,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { /// \param pvRefitPvCovMatrixPerTrack is a vector to be filled with PV coordinate covariances after PV refit template void runTagSelTracks(aod::Collision const& collision, - TTracks const&, + TTracks const& tracks, GroupedTrackIndices const& trackIndicesCollision, GroupedPvContributors const& pvContrCollision, aod::BCsWithTimestamps const& bcWithTimeStamps, @@ -946,9 +1137,13 @@ struct HfTrackIndexSkimCreatorTagSelTracks { std::vector>& pvRefitPvCovMatrixPerTrack) { const auto thisCollId = collision.globalIndex(); + auto tracksWithItsPid = soa::Attach(tracks); + for (const auto& trackId : trackIndicesCollision) { int statusProng = BIT(CandidateType::NCandidateTypes) - 1; // all bits on const auto track = trackId.template track_as(); + const auto trackWithItsPid = tracksWithItsPid.rawIteratorAt(trackId.trackId()); + float trackPt = track.pt(); float trackEta = track.eta(); @@ -1002,7 +1197,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { // } isSelectedTrack(track, trackPt, trackEta, pvRefitDcaXYDcaZ, statusProng); - const int8_t isIdentifiedPid = isSelectedPid(track); + const int8_t isIdentifiedPid = isSelectedPid(track, trackWithItsPid); const bool isPositive = track.sign() > 0; rowSelectedTrack(statusProng, isIdentifiedPid, isPositive); } @@ -1248,7 +1443,15 @@ struct HfTrackIndexSkimCreator { // Cd cuts Configurable> binsPtCdToDeKPi{"binsPtCdToDeKPi", std::vector{hf_cuts_presel_3prong::vecBinsPt}, "pT bin limits for Cd->DeKpi pT-dependent cuts"}; Configurable> cutsCdToDeKPi{"cutsCdToDeKPi", {hf_cuts_presel_3prong::Cuts[0], hf_cuts_presel_3prong::NBinsPt, hf_cuts_presel_3prong::NCutVars, hf_cuts_presel_3prong::labelsPt, hf_cuts_presel_3prong::labelsCutVar}, "Cd->deKpi selections per pT bin"}; - + // Ct cuts + Configurable> binsPtCtToTrKPi{"binsPtCtToTrKPi", std::vector{hf_cuts_presel_3prong::vecBinsPt}, "pT bin limits for Ct->tKpi pT-dependent cuts"}; + Configurable> cutsCtToTrKPi{"cutsCtToTrKPi", {hf_cuts_presel_3prong::Cuts[0], hf_cuts_presel_3prong::NBinsPt, hf_cuts_presel_3prong::NCutVars, hf_cuts_presel_3prong::labelsPt, hf_cuts_presel_3prong::labelsCutVar}, "Ct->tKpi selections per pT bin"}; + // Ch cuts + Configurable> binsPtChToHeKPi{"binsPtChToHeKPi", std::vector{hf_cuts_presel_3prong::vecBinsPt}, "pT bin limits for Ch->heKpi pT-dependent cuts"}; + Configurable> cutsChToHeKPi{"cutsChToHeKPi", {hf_cuts_presel_3prong::Cuts[0], hf_cuts_presel_3prong::NBinsPt, hf_cuts_presel_3prong::NCutVars, hf_cuts_presel_3prong::labelsPt, hf_cuts_presel_3prong::labelsCutVar}, "Ch->heKpi selections per pT bin"}; + // Ca cuts + Configurable> binsPtCaToAlKPi{"binsPtCaToAlKPi", std::vector{hf_cuts_presel_3prong::vecBinsPt}, "pT bin limits for Ca->alKpi pT-dependent cuts"}; + Configurable> cutsCaToAlKPi{"cutsCaToAlKPi", {hf_cuts_presel_3prong::Cuts[0], hf_cuts_presel_3prong::NBinsPt, hf_cuts_presel_3prong::NCutVars, hf_cuts_presel_3prong::labelsPt, hf_cuts_presel_3prong::labelsCutVar}, "Ca->alKpi selections per pT bin"}; // D*+ cuts Configurable> binsPtDstarToD0Pi{"binsPtDstarToD0Pi", std::vector{hf_cuts_presel_dstar::vecBinsPt}, "pT bin limits for D*+->D0pi pT-dependent cuts"}; Configurable> cutsDstarToD0Pi{"cutsDstarToD0Pi", {hf_cuts_presel_dstar::Cuts[0], hf_cuts_presel_dstar::NBinsPt, hf_cuts_presel_dstar::NCutVars, hf_cuts_presel_dstar::labelsPt, hf_cuts_presel_dstar::labelsCutVar}, "D*+->D0pi selections per pT bin"}; @@ -1258,6 +1461,10 @@ struct HfTrackIndexSkimCreator { Configurable applyProtonPidForXicToPKPi{"applyProtonPidForXicToPKPi", false, "Apply proton PID for Xic->pKpi"}; Configurable applyKaonPidIn3Prongs{"applyKaonPidIn3Prongs", false, "Apply kaon PID for opposite-sign track in 3-prong and D* decays"}; Configurable applyDeuteronPidForCdToDeKPi{"applyDeuteronPidForCdToDeKPi", false, "Require deuteron PID for Cd->deKpi"}; + Configurable applyTritonPidForCtToTrKPi{"applyTritonPidForCtToTrKPi", false, "Require triton PID for Ct->tKpi"}; + Configurable applyHeliumPidForChToHeKPi{"applyHeliumPidForChToHeKPi", false, "Require helium3 PID for Ch->heKpi"}; + Configurable applyHeliumPidForCaToAlKPi{"applyHeliumPidForCaToAlKPi", false, "Require Alpha PID for Ca->AlKpi"}; + // ML models for triggers Configurable applyMlForHfFilters{"applyMlForHfFilters", false, "Flag to enable ML application for HF Filters"}; Configurable mlModelPathCCDB{"mlModelPathCCDB", "EventFiltering/PWGHF/BDTSmeared", "Path on CCDB of ML models for HF Filters"}; @@ -1277,18 +1484,19 @@ struct HfTrackIndexSkimCreator { o2::vertexing::DCAFitterN<2> df2; // 2-prong vertex fitter o2::vertexing::DCAFitterN<3> df3; // 3-prong vertex fitter // Needed for PV refitting - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber{}; // int nColls{0}; //can be added to run over limited collisions per file - for tesing purposes - static constexpr int kN2ProngDecays = hf_cand_2prong::DecayType::N2ProngDecays; // number of 2-prong hadron types - static constexpr int kN3ProngDecays = hf_cand_3prong::DecayType::N3ProngDecays; // number of 3-prong hadron types - static constexpr int kNCuts2Prong[kN2ProngDecays] = {hf_cuts_presel_2prong::NCutVars, hf_cuts_presel_2prong::NCutVars, hf_cuts_presel_2prong::NCutVars}; // how many different selections are made on 2-prongs - static constexpr int kNCuts3Prong[kN3ProngDecays] = {hf_cuts_presel_3prong::NCutVars, hf_cuts_presel_3prong::NCutVars + 1, hf_cuts_presel_ds::NCutVars, hf_cuts_presel_3prong::NCutVars + 1, hf_cuts_presel_3prong::NCutVars + 1}; // how many different selections are made on 3-prongs (Lc and Xic have also PID potentially) - static constexpr int kNCutsDstar = 3; // how many different selections are made on Dstars + static constexpr int kN2ProngDecays = hf_cand_2prong::DecayType::N2ProngDecays; // number of 2-prong hadron types + static constexpr int kN3ProngDecays = hf_cand_3prong::DecayType::N3ProngDecays; // number of 3-prong hadron types + static constexpr int kNCuts2Prong[kN2ProngDecays] = {hf_cuts_presel_2prong::NCutVars, hf_cuts_presel_2prong::NCutVars, hf_cuts_presel_2prong::NCutVars}; // how many different selections are made on 2-prongs + static constexpr int kNCuts3Prong[kN3ProngDecays] = {hf_cuts_presel_3prong::NCutVars, hf_cuts_presel_3prong::NCutVars + 1, hf_cuts_presel_ds::NCutVars, hf_cuts_presel_3prong::NCutVars + 1, hf_cuts_presel_3prong::NCutVars + 2, hf_cuts_presel_3prong::NCutVars + 2, hf_cuts_presel_3prong::NCutVars + 2, hf_cuts_presel_3prong::NCutVars + 2}; // how many different selections are made on 3-prongs (Lc, Xic and CharmNuclei have also PID potentially, charmnuclei has also daughter track quality cut potentially) + static constexpr int kNCutsDstar = 3; // how many different selections are made on Dstars + static constexpr int kN3ProngDecaysUsedMlForHfFilters = kN3ProngDecays - NChannelsLightNucleiPid; // number of 3-prong HF decays using ML filters std::array, 2>, kN2ProngDecays> arrMass2Prong{}; std::array, 2>, kN3ProngDecays> arrMass3Prong{}; // arrays of 2-prong and 3-prong cuts @@ -1359,12 +1567,21 @@ struct HfTrackIndexSkimCreator { arrMass3Prong[hf_cand_3prong::DecayType::CdToDeKPi] = std::array{std::array{MassDeuteron, MassKPlus, MassPiPlus}, std::array{MassPiPlus, MassKPlus, MassDeuteron}}; + arrMass3Prong[hf_cand_3prong::DecayType::CtToTrKPi] = std::array{std::array{MassTriton, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassTriton}}; + + arrMass3Prong[hf_cand_3prong::DecayType::ChToHeKPi] = std::array{std::array{MassHelium3, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassHelium3}}; + + arrMass3Prong[hf_cand_3prong::DecayType::CaToAlKPi] = std::array{std::array{MassAlpha, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassAlpha}}; + // cuts for 2-prong decays retrieved by json. the order must be then one in hf_cand_2prong::DecayType cut2Prong = {config.cutsD0ToPiK, config.cutsJpsiToEE, config.cutsJpsiToMuMu}; binsPt2Prong = {config.binsPtD0ToPiK, config.binsPtJpsiToEE, config.binsPtJpsiToMuMu}; // cuts for 3-prong decays retrieved by json. the order must be then one in hf_cand_3prong::DecayType - cut3Prong = {config.cutsDplusToPiKPi, config.cutsLcToPKPi, config.cutsDsToKKPi, config.cutsXicToPKPi, config.cutsCdToDeKPi}; - binsPt3Prong = {config.binsPtDplusToPiKPi, config.binsPtLcToPKPi, config.binsPtDsToKKPi, config.binsPtXicToPKPi, config.binsPtCdToDeKPi}; + cut3Prong = {config.cutsDplusToPiKPi, config.cutsLcToPKPi, config.cutsDsToKKPi, config.cutsXicToPKPi, config.cutsCdToDeKPi, config.cutsCtToTrKPi, config.cutsChToHeKPi, config.cutsCaToAlKPi}; + binsPt3Prong = {config.binsPtDplusToPiKPi, config.binsPtLcToPKPi, config.binsPtDsToKKPi, config.binsPtXicToPKPi, config.binsPtCdToDeKPi, config.binsPtCtToTrKPi, config.binsPtChToHeKPi, config.binsPtCaToAlKPi}; df2.setPropagateToPCA(config.propagateToPCA); df2.setMaxR(config.maxR); @@ -1413,6 +1630,9 @@ struct HfTrackIndexSkimCreator { registry.add("hMassXicToPKPi", "#Xi_{c}^{#plus} candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); registry.add("hMassDstarToD0Pi", "D^{*#plus} candidates;inv. mass (K #pi #pi) - mass (K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0.135, 0.185}}}); registry.add("hMassCdToDeKPi", "C Deuteron candidates;inv. mass (De K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); + registry.add("hMassCtToTrKPi", "C Triton candidates;inv. mass (Tr K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); + registry.add("hMassChToHeKPi", "C Helium3 candidates;inv. mass (He3 K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); + registry.add("hMassCaToAlKPi", "C Alpha candidates;inv. mass (Alpha K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 2., 7.}}}); // needed for PV refitting if (doprocess2And3ProngsWithPvRefit || doprocess2And3ProngsWithPvRefitWithPidForHfFiltersBdt) { @@ -1466,13 +1686,13 @@ struct HfTrackIndexSkimCreator { if (config.applyMlForHfFilters) { const std::vector onnxFileNames2Prongs{config.onnxFileNames->get(0u, 0u)}; - // Exclude Cd from the 3-prong list, as it is not included in the pp trigger program - const std::array, kN3ProngDecays - 1> onnxFileNames3Prongs{std::vector{config.onnxFileNames->get(1u, 0u)}, std::vector{config.onnxFileNames->get(2u, 0u)}, std::vector{config.onnxFileNames->get(3u, 0u)}, std::vector{config.onnxFileNames->get(4u, 0u)}}; + // Exclude Cd, Ct, Ch from the 3-prong list, as it is not included in the pp trigger program + const std::array, kN3ProngDecaysUsedMlForHfFilters> onnxFileNames3Prongs{std::vector{config.onnxFileNames->get(1u, 0u)}, std::vector{config.onnxFileNames->get(2u, 0u)}, std::vector{config.onnxFileNames->get(3u, 0u)}, std::vector{config.onnxFileNames->get(4u, 0u)}}; const std::vector mlModelPathCcdb2Prongs{config.mlModelPathCCDB.value + "D0"}; - const std::array, kN3ProngDecays - 1> mlModelPathCcdb3Prongs{std::vector{config.mlModelPathCCDB.value + "Dplus"}, std::vector{config.mlModelPathCCDB.value + "Lc"}, std::vector{config.mlModelPathCCDB.value + "Ds"}, std::vector{config.mlModelPathCCDB.value + "Xic"}}; + const std::array, kN3ProngDecaysUsedMlForHfFilters> mlModelPathCcdb3Prongs{std::vector{config.mlModelPathCCDB.value + "Dplus"}, std::vector{config.mlModelPathCCDB.value + "Lc"}, std::vector{config.mlModelPathCCDB.value + "Ds"}, std::vector{config.mlModelPathCCDB.value + "Xic"}}; const std::vector ptBinsMl{0., 1.e10}; const std::vector cutDirMl{o2::cuts_ml::CutDirection::CutGreater, o2::cuts_ml::CutDirection::CutSmaller, o2::cuts_ml::CutDirection::CutSmaller}; - const std::array, kN3ProngDecays - 1> thresholdMlScore3Prongs{config.thresholdMlScoreDplusToPiKPi, config.thresholdMlScoreLcToPiKP, config.thresholdMlScoreDsToPiKK, config.thresholdMlScoreXicToPiKP}; + const std::array, kN3ProngDecaysUsedMlForHfFilters> thresholdMlScore3Prongs{config.thresholdMlScoreDplusToPiKPi, config.thresholdMlScoreLcToPiKP, config.thresholdMlScoreDsToPiKK, config.thresholdMlScoreXicToPiKP}; // initialise 2-prong ML response hfMlResponse2Prongs.configure(ptBinsMl, config.thresholdMlScoreD0ToKPi, cutDirMl, 3); @@ -1485,7 +1705,7 @@ struct HfTrackIndexSkimCreator { hfMlResponse2Prongs.init(); // initialise 3-prong ML responses - for (int iDecay3P{0}; iDecay3P < kN3ProngDecays - 1; ++iDecay3P) { + for (int iDecay3P{0}; iDecay3P < kN3ProngDecaysUsedMlForHfFilters; ++iDecay3P) { if (onnxFileNames3Prongs[iDecay3P][0].empty()) { // 3-prong species to be skipped continue; } @@ -1630,22 +1850,22 @@ struct HfTrackIndexSkimCreator { /// \param cutStatus is a 2D array with outcome of each selection (filled only in debug mode) /// \param whichHypo information of the mass hypoteses that were selected /// \param isSelected is a bitmap with selection outcome - template - void applyPreselection3Prong(T1 const& pVecTrack0, T1 const& pVecTrack1, T1 const& pVecTrack2, const auto isIdentifiedPidTrack0, const auto isIdentifiedPidTrack2, T2& cutStatus, T3& whichHypo, auto& isSelected) + template + void applyPreselection3Prong(T2 const& pVecTrack0, T2 const& pVecTrack1, T2 const& pVecTrack2, const auto isIdentifiedPidTrack0, const auto isIdentifiedPidTrack2, T3& cutStatus, T4& whichHypo, auto& isSelected) { const auto pt = RecoDecay::pt(pVecTrack0, pVecTrack1, pVecTrack2) + config.ptTolerance; // add tolerance because of no reco decay vertex for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { - // check proton PID for Lc and Xic whichHypo[iDecay3P] = 3; // 2 bits on - if ((iDecay3P == hf_cand_3prong::DecayType::LcToPKPi && config.applyProtonPidForLcToPKPi) || (iDecay3P == hf_cand_3prong::DecayType::XicToPKPi && config.applyProtonPidForXicToPKPi) || (iDecay3P == hf_cand_3prong::DecayType::CdToDeKPi && config.applyDeuteronPidForCdToDeKPi)) { + // check proton PID for 3prongs + if ((iDecay3P == hf_cand_3prong::DecayType::LcToPKPi && config.applyProtonPidForLcToPKPi) || (iDecay3P == hf_cand_3prong::DecayType::XicToPKPi && config.applyProtonPidForXicToPKPi) || (iDecay3P == hf_cand_3prong::DecayType::CdToDeKPi && config.applyDeuteronPidForCdToDeKPi) || (iDecay3P == hf_cand_3prong::DecayType::CtToTrKPi && config.applyTritonPidForCtToTrKPi) || (iDecay3P == hf_cand_3prong::DecayType::ChToHeKPi && config.applyHeliumPidForChToHeKPi) || (iDecay3P == hf_cand_3prong::DecayType::CaToAlKPi && config.applyHeliumPidForCaToAlKPi)) { - if ((iDecay3P == hf_cand_3prong::DecayType::LcToPKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsProtonPid::LcToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::XicToPKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsProtonPid::XicToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::CdToDeKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsDeuteronPid))) { + if ((iDecay3P == hf_cand_3prong::DecayType::LcToPKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsProtonPid::LcToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::XicToPKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsProtonPid::XicToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::CdToDeKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsDeuteronPid)) || (iDecay3P == hf_cand_3prong::DecayType::CtToTrKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsTritonPid)) || (iDecay3P == hf_cand_3prong::DecayType::ChToHeKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsHeliumPid)) || (iDecay3P == hf_cand_3prong::DecayType::CaToAlKPi && !TESTBIT(isIdentifiedPidTrack0, ChannelsAlphaPid))) { CLRBIT(whichHypo[iDecay3P], 0); } - if ((iDecay3P == hf_cand_3prong::DecayType::LcToPKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsProtonPid::LcToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::XicToPKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsProtonPid::XicToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::CdToDeKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsDeuteronPid))) { + if ((iDecay3P == hf_cand_3prong::DecayType::LcToPKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsProtonPid::LcToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::XicToPKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsProtonPid::XicToPKPi)) || (iDecay3P == hf_cand_3prong::DecayType::CdToDeKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsDeuteronPid)) || (iDecay3P == hf_cand_3prong::DecayType::CtToTrKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsTritonPid)) || (iDecay3P == hf_cand_3prong::DecayType::ChToHeKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsHeliumPid)) || (iDecay3P == hf_cand_3prong::DecayType::CaToAlKPi && !TESTBIT(isIdentifiedPidTrack2, ChannelsAlphaPid))) { CLRBIT(whichHypo[iDecay3P], 1); } if (whichHypo[iDecay3P] == 0) { @@ -1829,14 +2049,14 @@ struct HfTrackIndexSkimCreator { /// \param outputScores is the array of vectors with the output scores to be filled /// \param isSelected ia s bitmap with selection outcome template - void applyMlSelectionForHfFilters3Prong(std::vector featuresCand, std::vector featuresCandPid, std::array, kN3ProngDecays - 1>& outputScores, auto& isSelected) + void applyMlSelectionForHfFilters3Prong(std::vector featuresCand, std::vector featuresCandPid, std::array, kN3ProngDecaysUsedMlForHfFilters>& outputScores, auto& isSelected) { if (isSelected == 0) { return; } const float ptDummy = 1.f; // dummy pT value (only one pT bin) - for (int iDecay3P{0}; iDecay3P < kN3ProngDecays - 1; ++iDecay3P) { + for (int iDecay3P{0}; iDecay3P < kN3ProngDecaysUsedMlForHfFilters; ++iDecay3P) { if (TESTBIT(isSelected, iDecay3P) && hasMlModel3Prong[iDecay3P]) { bool isMlSel = false; if constexpr (UsePidForHfFiltersBdt) { @@ -2420,6 +2640,7 @@ struct HfTrackIndexSkimCreator { } const auto trackPos2 = trackIndexPos2.template track_as(); + auto trackParVarPos2 = getTrackParCov(trackPos2); std::array dcaInfoPos2{trackPos2.dcaXY(), trackPos2.dcaZ()}; @@ -2565,7 +2786,7 @@ struct HfTrackIndexSkimCreator { // 3-prong selections after secondary vertex applySelection3Prong(pVecCandProng3Pos, secondaryVertex3, pvRefitCoord3Prong2Pos1Neg, cutStatus3Prong, isSelected3ProngCand); - std::array, kN3ProngDecays - 1> mlScores3Prongs; + std::array, kN3ProngDecaysUsedMlForHfFilters> mlScores3Prongs; if (config.applyMlForHfFilters) { const std::vector inputFeatures{trackParVarPcaPos1.getPt(), dcaInfoPos1[0], dcaInfoPos1[1], trackParVarPcaNeg1.getPt(), dcaInfoNeg1[0], dcaInfoNeg1[1], trackParVarPcaPos2.getPt(), dcaInfoPos2[0], dcaInfoPos2[1]}; std::vector inputFeaturesLcPid{}; @@ -2633,6 +2854,15 @@ struct HfTrackIndexSkimCreator { case hf_cand_3prong::DecayType::CdToDeKPi: registry.fill(HIST("hMassCdToDeKPi"), mass3Prong); break; + case hf_cand_3prong::DecayType::CtToTrKPi: + registry.fill(HIST("hMassCtToTrKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::ChToHeKPi: + registry.fill(HIST("hMassChToHeKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::CaToAlKPi: + registry.fill(HIST("hMassCaToAlKPi"), mass3Prong); + break; } } if (TESTBIT(whichHypo3Prong[iDecay3P], 1)) { @@ -2650,6 +2880,15 @@ struct HfTrackIndexSkimCreator { case hf_cand_3prong::DecayType::CdToDeKPi: registry.fill(HIST("hMassCdToDeKPi"), mass3Prong); break; + case hf_cand_3prong::DecayType::CtToTrKPi: + registry.fill(HIST("hMassCtToTrKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::ChToHeKPi: + registry.fill(HIST("hMassChToHeKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::CaToAlKPi: + registry.fill(HIST("hMassCaToAlKPi"), mass3Prong); + break; } } } @@ -2822,7 +3061,7 @@ struct HfTrackIndexSkimCreator { // 3-prong selections after secondary vertex applySelection3Prong(pVecCandProng3Neg, secondaryVertex3, pvRefitCoord3Prong1Pos2Neg, cutStatus3Prong, isSelected3ProngCand); - std::array, kN3ProngDecays - 1> mlScores3Prongs{}; + std::array, kN3ProngDecaysUsedMlForHfFilters> mlScores3Prongs{}; if (config.applyMlForHfFilters) { const std::vector inputFeatures{trackParVarPcaNeg1.getPt(), dcaInfoNeg1[0], dcaInfoNeg1[1], trackParVarPcaPos1.getPt(), dcaInfoPos1[0], dcaInfoPos1[1], trackParVarPcaNeg2.getPt(), dcaInfoNeg2[0], dcaInfoNeg2[1]}; std::vector inputFeaturesLcPid{}; @@ -2890,6 +3129,15 @@ struct HfTrackIndexSkimCreator { case hf_cand_3prong::DecayType::CdToDeKPi: registry.fill(HIST("hMassCdToDeKPi"), mass3Prong); break; + case hf_cand_3prong::DecayType::CtToTrKPi: + registry.fill(HIST("hMassCtToTrKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::ChToHeKPi: + registry.fill(HIST("hMassChToHeKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::CaToAlKPi: + registry.fill(HIST("hMassCaToAlKPi"), mass3Prong); + break; } } if (TESTBIT(whichHypo3Prong[iDecay3P], 1)) { @@ -2907,6 +3155,15 @@ struct HfTrackIndexSkimCreator { case hf_cand_3prong::DecayType::CdToDeKPi: registry.fill(HIST("hMassCdToDeKPi"), mass3Prong); break; + case hf_cand_3prong::DecayType::CtToTrKPi: + registry.fill(HIST("hMassCtToTrKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::ChToHeKPi: + registry.fill(HIST("hMassChToHeKPi"), mass3Prong); + break; + case hf_cand_3prong::DecayType::CaToAlKPi: + registry.fill(HIST("hMassCaToAlKPi"), mass3Prong); + break; } } } @@ -3104,7 +3361,7 @@ struct HfTrackIndexSkimCreatorCascades { o2::vertexing::DCAFitterN<2> df2; // 2-prong vertex fitter // Needed for PV refitting - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; @@ -3265,7 +3522,6 @@ struct HfTrackIndexSkimCreatorCascades { 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); } @@ -3324,7 +3580,7 @@ struct HfTrackIndexSkimCreatorLfCascades { Configurable massXiPiPiMax{"massXiPiPiMax", 2.8, "Invariant mass upper limit for xi pi pi decay channel"}; // DCAFitter settings - Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; 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"}; Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; @@ -3333,7 +3589,6 @@ struct HfTrackIndexSkimCreatorLfCascades { 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 maxChi2{"maxChi2", 100., "discard vertices with chi2/Nprongs > this (or sum{DCAi^2}/Nprongs for abs. distance minimization)"}; - Configurable refitWithMatCorr{"refitWithMatCorr", true, "when doing propagateTracksToVertex, propagate tracks to vtx with material corrections and rerun minimization"}; // Selection criteria // selections have been set to run2 lambda dedicated cuts @@ -3367,7 +3622,7 @@ struct HfTrackIndexSkimCreatorLfCascades { } config; o2::vertexing::DCAFitterN<2> df2; // 2-prong vertex fitter - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber{}; @@ -3551,6 +3806,7 @@ struct HfTrackIndexSkimCreatorLfCascades { template bool isSelectedCandidateXic(const T1& pVecCand, const T2& secVtx, const T3& primVtx) { + // pT if (config.ptMinXicplusLfCasc > 0.f) { const auto pt = RecoDecay::pt(pVecCand); @@ -3603,7 +3859,6 @@ struct HfTrackIndexSkimCreatorLfCascades { const auto magneticField = o2::base::Propagator::Instance()->getNominalBz(); // z component df2.setBz(magneticField); - df2.setRefitWithMatCorr(config.refitWithMatCorr); // cascade loop const auto thisCollId = collision.globalIndex(); @@ -3706,34 +3961,27 @@ struct HfTrackIndexSkimCreatorLfCascades { } if (nVtxFrom2ProngFitterXiHyp > 0) { - - df2.propagateTracksToVertex(); - - if (df2.isPropagateTracksToVertexDone()) { - std::array pVecXi{}; - std::array pVecPion1XiHyp{}; - df2.getTrack(0).getPxPyPzGlo(pVecXi); - df2.getTrack(1).getPxPyPzGlo(pVecPion1XiHyp); - const float ptXic = RecoDecay::pt(pVecXi, pVecPion1XiHyp); - - const std::array arrMomToXi{pVecXi, pVecPion1XiHyp}; - const auto mass2ProngXiHyp = RecoDecay::m(arrMomToXi, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi]); - - if ((std::abs(casc.mXi() - MassXiMinus) < config.cascadeMassWindow) && (mass2ProngXiHyp >= config.massXiPiMin) && (mass2ProngXiHyp <= config.massXiPiMax)) { - registry.fill(HIST("hRejpTStatusXicZeroOmegacZeroToXiPi"), 0); - if (ptXic >= config.ptMinXicZeroOmegacZeroToXiPiLfCasc) { - SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi); - registry.fill(HIST("hRejpTStatusXicZeroOmegacZeroToXiPi"), 1); - } + std::array pVecXi{}; + std::array pVecPion1XiHyp{}; + df2.getTrack(0).getPxPyPzGlo(pVecXi); + df2.getTrack(1).getPxPyPzGlo(pVecPion1XiHyp); + const float ptXic = RecoDecay::pt(pVecXi, pVecPion1XiHyp); + + const std::array arrMomToXi{pVecXi, pVecPion1XiHyp}; + const auto mass2ProngXiHyp = RecoDecay::m(arrMomToXi, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi]); + + if ((std::abs(casc.mXi() - MassXiMinus) < config.cascadeMassWindow) && (mass2ProngXiHyp >= config.massXiPiMin) && (mass2ProngXiHyp <= config.massXiPiMax)) { + registry.fill(HIST("hRejpTStatusXicZeroOmegacZeroToXiPi"), 0); + if (ptXic >= config.ptMinXicZeroOmegacZeroToXiPiLfCasc) { + SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi); + registry.fill(HIST("hRejpTStatusXicZeroOmegacZeroToXiPi"), 1); } + } - // fill histograms - if (config.fillHistograms && (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi))) { - registry.fill(HIST("hMassXicZeroOmegacZeroToXiPi"), mass2ProngXiHyp); - registry.fill(HIST("hPtCutsXicZeroOmegacZeroToXiPi"), ptXic); - } - } else if (df2.isPropagationFailure()) { - LOGF(info, "Exception caught: failed to propagate tracks (2prong - xi) to charm baryon decay vtx"); + // fill histograms + if (config.fillHistograms && (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi))) { + registry.fill(HIST("hMassXicZeroOmegacZeroToXiPi"), mass2ProngXiHyp); + registry.fill(HIST("hPtCutsXicZeroOmegacZeroToXiPi"), ptXic); } } @@ -3753,50 +4001,43 @@ struct HfTrackIndexSkimCreatorLfCascades { if (nVtxFrom2ProngFitterOmegaHyp > 0) { - df2.propagateTracksToVertex(); - - if (df2.isPropagateTracksToVertexDone()) { - - std::array pVecOmega{}; - std::array pVecCharmBachelor1OmegaHyp{}; - df2.getTrack(0).getPxPyPzGlo(pVecOmega); - df2.getTrack(1).getPxPyPzGlo(pVecCharmBachelor1OmegaHyp); - const float ptOmegac = RecoDecay::pt(pVecOmega, pVecCharmBachelor1OmegaHyp); - - const std::array arrMomToOmega{pVecOmega, pVecCharmBachelor1OmegaHyp}; - const auto mass2ProngOmegaPiHyp = RecoDecay::m(arrMomToOmega, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi]); - const auto mass2ProngOmegaKHyp = RecoDecay::m(arrMomToOmega, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK]); - - if (std::abs(casc.mOmega() - MassOmegaMinus) < config.cascadeMassWindow) { - if ((mass2ProngOmegaPiHyp >= config.massOmegaCharmBachelorMin) && (mass2ProngOmegaPiHyp <= config.massOmegaCharmBachelorMax)) { - registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaPi"), 0); - if (ptOmegac >= config.ptMinOmegacZeroToOmegaPiLfCasc) { - SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi); - registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaPi"), 1); - } + std::array pVecOmega{}; + std::array pVecCharmBachelor1OmegaHyp{}; + df2.getTrack(0).getPxPyPzGlo(pVecOmega); + df2.getTrack(1).getPxPyPzGlo(pVecCharmBachelor1OmegaHyp); + const float ptOmegac = RecoDecay::pt(pVecOmega, pVecCharmBachelor1OmegaHyp); + + const std::array arrMomToOmega{pVecOmega, pVecCharmBachelor1OmegaHyp}; + const auto mass2ProngOmegaPiHyp = RecoDecay::m(arrMomToOmega, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi]); + const auto mass2ProngOmegaKHyp = RecoDecay::m(arrMomToOmega, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK]); + + if (std::abs(casc.mOmega() - MassOmegaMinus) < config.cascadeMassWindow) { + if ((mass2ProngOmegaPiHyp >= config.massOmegaCharmBachelorMin) && (mass2ProngOmegaPiHyp <= config.massOmegaCharmBachelorMax)) { + registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaPi"), 0); + if (ptOmegac >= config.ptMinOmegacZeroToOmegaPiLfCasc) { + SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi); + registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaPi"), 1); } - if ((mass2ProngOmegaKHyp >= config.massOmegaCharmBachelorMin) && (mass2ProngOmegaKHyp <= config.massOmegaCharmBachelorMax)) { - registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaKa"), 0); - if (ptOmegac >= config.ptMinOmegaczeroToOmegaKaLfCasc) { - SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK); - registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaKa"), 1); - } + } + if ((mass2ProngOmegaKHyp >= config.massOmegaCharmBachelorMin) && (mass2ProngOmegaKHyp <= config.massOmegaCharmBachelorMax)) { + registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaKa"), 0); + if (ptOmegac >= config.ptMinOmegaczeroToOmegaKaLfCasc) { + SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK); + registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaKa"), 1); } } + } - // fill histograms - if (config.fillHistograms) { - if (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi)) { - registry.fill(HIST("hMassOmegacZeroToOmegaPi"), mass2ProngOmegaPiHyp); - registry.fill(HIST("hPtCutsOmegacZeroToOmegaPi"), ptOmegac); - } - if (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK)) { - registry.fill(HIST("hMassOmegacZeroToOmegaK"), mass2ProngOmegaKHyp); - registry.fill(HIST("hPtCutsOmegacZeroToOmegaKa"), ptOmegac); - } + // fill histograms + if (config.fillHistograms) { + if (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi)) { + registry.fill(HIST("hMassOmegacZeroToOmegaPi"), mass2ProngOmegaPiHyp); + registry.fill(HIST("hPtCutsOmegacZeroToOmegaPi"), ptOmegac); + } + if (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK)) { + registry.fill(HIST("hMassOmegacZeroToOmegaK"), mass2ProngOmegaKHyp); + registry.fill(HIST("hPtCutsOmegacZeroToOmegaKa"), ptOmegac); } - } else if (df2.isPropagationFailure()) { - LOGF(info, "Exception caught: failed to propagate tracks (2prong - omega) to charm baryon decay vtx"); } } @@ -3859,43 +4100,45 @@ struct HfTrackIndexSkimCreatorLfCascades { } if (nVtxFrom3ProngFitterXiHyp > 0) { - df2.propagateTracksToVertex(); - if (df2.isPropagateTracksToVertexDone()) { - std::array pVecPi1{}; - std::array pVecPi2{}; - // get bachelor momenta at the Xic vertex - df2.getTrack(0).getPxPyPzGlo(pVecPi1); - df2.getTrack(1).getPxPyPzGlo(pVecPi2); - const auto pVecCand = RecoDecay::pVec(pVecCasc, pVecPi1, pVecPi2); - const auto ptCand = RecoDecay::pt(pVecCand); - const std::array primaryVertex{collision.posX(), collision.posY(), collision.posZ()}; // primary vertex - const auto& secondaryVertex = df2.getPCACandidate(); // secondary vertex - - registry.fill(HIST("hRejpTStatusXicPlusToXiPiPi"), 0); - if (ptCand >= config.ptMinXicplusLfCasc) { - registry.fill(HIST("hRejpTStatusXicPlusToXiPiPi"), 1); - } - - if (!isSelectedCandidateXic(pVecCand, secondaryVertex, primaryVertex)) { - continue; - } + std::array pVecPi1{}; + std::array pVecPi2{}; + // get bachelor momenta at the Xic vertex + df2.getTrack(0).getPxPyPzGlo(pVecPi1); + df2.getTrack(1).getPxPyPzGlo(pVecPi2); + // we propagate the cascade to the pipi vertex + trackParCovCascXi.setPID(o2::track::PID::XiMinus); + trackParCovCascXi.setAbsCharge(1); // to be sure + std::array dcaInfoXi; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovCascXi, 2.f, matCorr, &dcaInfoXi); + std::array pVecXiProp{}; + getPxPyPz(trackParCovCascXi, pVecXiProp); + const auto pVecCand = RecoDecay::pVec(pVecCasc, pVecPi1, pVecPi2); + const auto ptCand = RecoDecay::pt(pVecCand); + const std::array primaryVertex{collision.posX(), collision.posY(), collision.posZ()}; // primary vertex + const auto& secondaryVertex = df2.getPCACandidate(); // secondary vertex + + registry.fill(HIST("hRejpTStatusXicPlusToXiPiPi"), 0); + if (ptCand >= config.ptMinXicplusLfCasc) { + registry.fill(HIST("hRejpTStatusXicPlusToXiPiPi"), 1); + } - // fill histograms - if (config.fillHistograms) { - const std::array arr3Mom{pVecCasc, pVecPi1, pVecPi2}; - const auto mass3Prong = RecoDecay::m(arr3Mom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]); - registry.fill(HIST("hMassXicPlusToXiPiPi"), mass3Prong); - registry.fill(HIST("hPtCutsXicPlusToXiPiPi"), ptCand); - } + if (!isSelectedCandidateXic(pVecCand, secondaryVertex, primaryVertex)) { + continue; + } - // fill table row if a vertex was found - rowTrackIndexCasc3Prong(thisCollId, - casc.cascadeId(), - trackCharmBachelor1.globalIndex(), - trackCharmBachelor2.globalIndex()); - } else if (df2.isPropagationFailure()) { - LOGF(info, "Exception caught: failed to propagate tracks (3prong) to charm baryon decay vtx"); + // fill histograms + if (config.fillHistograms) { + const std::array arr3Mom{pVecCasc, pVecPi1, pVecPi2}; + const auto mass3Prong = RecoDecay::m(arr3Mom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]); + registry.fill(HIST("hMassXicPlusToXiPiPi"), mass3Prong); + registry.fill(HIST("hPtCutsXicPlusToXiPiPi"), ptCand); } + + // fill table row if a vertex was found + rowTrackIndexCasc3Prong(thisCollId, + casc.cascadeId(), + trackCharmBachelor1.globalIndex(), + trackCharmBachelor2.globalIndex()); } } // end 3prong loop } // end 3prong condition diff --git a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx index af4663a1b41..dda2819b164 100644 --- a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx @@ -96,8 +96,8 @@ DECLARE_SOA_TABLE(HfCandB0Lites, "AOD", "HFCANDB0LITE", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); DECLARE_SOA_TABLE(HfCandB0Fulls, "AOD", "HFCANDB0FULL", collision::BCId, @@ -146,8 +146,8 @@ DECLARE_SOA_TABLE(HfCandB0Fulls, "AOD", "HFCANDB0FULL", full::Phi, full::Y, full::E, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); DECLARE_SOA_TABLE(HfCandB0FullEvs, "AOD", "HFCANDB0FULLEV", collision::BCId, @@ -164,8 +164,8 @@ DECLARE_SOA_TABLE(HfCandB0FullPs, "AOD", "HFCANDB0FULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -188,8 +188,8 @@ struct HfTreeCreatorB0ToDPi { Filter filterSelectCandidates = aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0; - Partition recSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); - Partition recBg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx index 9aa6b5f7cab..66826ddfe5c 100644 --- a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx @@ -153,7 +153,7 @@ DECLARE_SOA_TABLE(HfCandBpFulls, "AOD", "HFCANDBPFULL", full::Phi, full::Y, full::E, - hf_cand_2prong::FlagMcMatchRec, + hf_cand_mc_flag::FlagMcMatchRec, full::D0M, full::D0PtProng0, full::D0PtProng1, @@ -195,8 +195,8 @@ DECLARE_SOA_TABLE(HfCandBpFullPs, "AOD", "HFCANDBPFULLP", full::Eta, full::Phi, full::Y, - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcGen); DECLARE_SOA_TABLE(HfCandBpLites, "AOD", "HFCANDBPLITE", hf_cand::Chi2PCA, @@ -219,8 +219,8 @@ DECLARE_SOA_TABLE(HfCandBpLites, "AOD", "HFCANDBPLITE", full::Eta, full::Phi, full::Y, - hf_cand_2prong::FlagMcMatchRec, - hf_cand_2prong::OriginMcRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec); } // namespace o2::aod @@ -244,8 +244,8 @@ struct HfTreeCreatorBplusToD0Pi { Filter filterSelectCandidates = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; - Partition recSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); - Partition recBg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx index 6e30341f584..6dd99548b7c 100644 --- a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -95,7 +95,7 @@ DECLARE_SOA_TABLE(HfCandBsLites, "AOD", "HFCANDBSLITE", full::Eta, full::Phi, full::Y, - hf_cand_bs::FlagMcMatchRec); + hf_cand_mc_flag::FlagMcMatchRec); DECLARE_SOA_TABLE(HfCandBsFulls, "AOD", "HFCANDBSFULL", collision::BCId, @@ -143,7 +143,7 @@ DECLARE_SOA_TABLE(HfCandBsFulls, "AOD", "HFCANDBSFULL", full::Phi, full::Y, full::E, - hf_cand_bs::FlagMcMatchRec); + hf_cand_mc_flag::FlagMcMatchRec); DECLARE_SOA_TABLE(HfCandBsFullEvs, "AOD", "HFCANDBSFULLEV", collision::BCId, @@ -160,7 +160,7 @@ DECLARE_SOA_TABLE(HfCandBsFullPs, "AOD", "HFCANDBSFULLP", full::Eta, full::Phi, full::Y, - hf_cand_bs::FlagMcMatchGen); + hf_cand_mc_flag::FlagMcMatchGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -183,8 +183,8 @@ struct HfTreeCreatorBsToDsPi { Filter filterSelectCandidates = aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs; - Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == static_cast(DecayChannelMain::BsToDsPi); - Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != static_cast(DecayChannelMain::BsToDsPi); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(DecayChannelMain::BsToDsPi); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(DecayChannelMain::BsToDsPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx index 17093c0ef64..49656d8c364 100644 --- a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx @@ -249,17 +249,17 @@ struct HfTreeCreatorD0ToKPi { using MatchedGenCandidatesMc = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && (nabs(aod::hf_cand_2prong::flagMcMatchGen) != 0)); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && (nabs(aod::hf_cand_mc_flag::flagMcMatchGen) != 0)); - Partition reconstructedCandSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition reconstructedCandSigKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkgKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSigKF = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkgKF = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition reconstructedCandSigMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkgMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); - Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); - Partition reconstructedCandBkgKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSigMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkgMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != 0); + Partition reconstructedCandBkgKFMl = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); void init(InitContext const&) { @@ -435,7 +435,7 @@ struct HfTreeCreatorD0ToKPi { double const yD = HfHelper::yD0(candidate); double const eD = HfHelper::eD0(candidate); double const ctD = HfHelper::ctD0(candidate); - float massD0, massD0bar; + float massD0{}, massD0bar{}; float topolChi2PerNdf = -999.; if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { massD0 = candidate.kfGeoMassD0(); @@ -536,7 +536,7 @@ struct HfTreeCreatorD0ToKPi { double const yD = HfHelper::yD0(candidate); double const eD = HfHelper::eD0(candidate); double const ctD = HfHelper::ctD0(candidate); - float massD0, massD0bar; + float massD0{}, massD0bar{}; float topolChi2PerNdf = -999.; if constexpr (ReconstructionType == aod::hf_cand::VertexerType::KfParticle) { massD0 = candidate.kfGeoMassD0(); diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index 97978baac1e..d301cee0752 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -147,9 +147,9 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", full::Y, full::Centrality, collision::NumContrib, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec) + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", collision::NumContrib, @@ -228,9 +228,9 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", full::Y, full::E, full::Centrality, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec); DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", collision::NumContrib, @@ -245,9 +245,9 @@ DECLARE_SOA_TABLE(HfCandDpFullPs, "AOD", "HFCANDDPFULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchGen, - hf_cand_3prong::FlagMcDecayChanGen, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::FlagMcDecayChanGen, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod /// Writes the full information in an output TTree @@ -277,11 +277,11 @@ struct HfTreeCreatorDplusToPiKPi { using CollisionsCent = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) != 0)); + Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) != 0)); - Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition reconstructedCandSigMl = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); + Partition reconstructedCandSig = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Partition reconstructedCandSigMl = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_mc_flag::flagMcMatchRec) != 0)); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx index 90dfa44d771..57d484a63b1 100644 --- a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -146,10 +146,10 @@ DECLARE_SOA_TABLE(HfCandDsLites, "AOD", "HFCANDDSLITE", hf_cand::Chi2PCA, full::Centrality, collision::NumContrib, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec, - hf_cand_3prong::IsCandidateSwapped, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::IsCandidateSwapped, full::Sign); DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", @@ -219,10 +219,10 @@ DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", full::AbsCos3PiK, hf_cand::Chi2PCA, full::Centrality, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcRec, - hf_cand_3prong::FlagMcDecayChanRec, - hf_cand_3prong::IsCandidateSwapped, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, + hf_cand_mc_flag::FlagMcDecayChanRec, + hf_cand_mc_flag::IsCandidateSwapped, full::Sign); DECLARE_SOA_TABLE(HfCandDsFullEvs, "AOD", "HFCANDDSFULLEV", @@ -241,8 +241,8 @@ DECLARE_SOA_TABLE(HfCandDsFullPs, "AOD", "HFCANDDSFULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, - hf_cand_3prong::OriginMcGen); + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcGen); } // namespace o2::aod enum Mother : int8_t { @@ -289,18 +289,18 @@ struct HfTreeCreatorDsToKKPi { Filter filterSelectCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; Filter filterMcGenMatching = - nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && - (aod::hf_cand_3prong::flagMcDecayChanGen == channelsResonant[Mother::Ds][decayChannel] || - (fillDplusMc && aod::hf_cand_3prong::flagMcDecayChanGen == channelsResonant[Mother::Dplus][decayChannel])); // Do not store Dplus MC if fillDplusMc is false + nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && + (aod::hf_cand_mc_flag::flagMcDecayChanGen == channelsResonant[Mother::Ds][decayChannel] || + (fillDplusMc && aod::hf_cand_mc_flag::flagMcDecayChanGen == channelsResonant[Mother::Dplus][decayChannel])); // Do not store Dplus MC if fillDplusMc is false Partition selectedDsToKKPiCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; Partition selectedDsToPiKKCand = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Ds][decayChannel]) || (fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); // Do not store Dplus MC if fillDplusMc is false - Partition reconstructedCandBkg = (nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK)) || - (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec != channelsResonant[Mother::Ds][decayChannel]) || - (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec != channelsResonant[Mother::Dplus][decayChannel]) || - (!fillDplusMc && nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_3prong::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); + Partition reconstructedCandSig = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec == channelsResonant[Mother::Ds][decayChannel]) || (fillDplusMc && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); // Do not store Dplus MC if fillDplusMc is false + Partition reconstructedCandBkg = (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK)) || + (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec != channelsResonant[Mother::Ds][decayChannel]) || + (nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec != channelsResonant[Mother::Dplus][decayChannel]) || + (!fillDplusMc && nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) && aod::hf_cand_mc_flag::flagMcDecayChanRec == channelsResonant[Mother::Dplus][decayChannel]); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx index 059c3ed8f11..9cdbc18b889 100644 --- a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx @@ -153,8 +153,8 @@ DECLARE_SOA_TABLE(HfCandDstLites, "AOD", "HFCANDDSTLITE", full::Phi, full::Y, full::CandidateSelFlag, - hf_cand_dstar::FlagMcMatchRec, - hf_cand_dstar::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, full::PtBhadMother) DECLARE_SOA_TABLE(HfCandDstFulls, "AOD", "HFCANDDSTFULL", @@ -226,8 +226,8 @@ DECLARE_SOA_TABLE(HfCandDstFulls, "AOD", "HFCANDDSTFULL", full::Y, full::E, full::CandidateSelFlag, - hf_cand_dstar::FlagMcMatchRec, - hf_cand_dstar::OriginMcRec, + hf_cand_mc_flag::FlagMcMatchRec, + hf_cand_mc_flag::OriginMcRec, full::PtBhadMother); DECLARE_SOA_TABLE(HfCandDstFullEvs, "AOD", "HFCANDDSTFULLEV", @@ -245,8 +245,8 @@ DECLARE_SOA_TABLE(HfCandDstFullPs, "AOD", "HFCANDDSTFULLP", full::Eta, full::Phi, full::Y, - hf_cand_dstar::FlagMcMatchGen, - hf_cand_dstar::OriginMcGen, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, full::PtBhadMother); } // namespace o2::aod @@ -272,10 +272,10 @@ struct HfTreeCreatorDstarToD0Pi { using CandDstarMcGen = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; - Filter filterMcGenMatching = nabs(aod::hf_cand_dstar::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Filter filterMcGenMatching = nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition reconstructedCandSig = nabs(aod::hf_cand_dstar::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); - Partition reconstructedCandBkg = nabs(aod::hf_cand_dstar::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition reconstructedCandSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index c49d09dfc2d..51112ffe161 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -544,7 +544,7 @@ struct HfTreeCreatorLcToPKPi { /// \param candidatesSize size of the candidates table /// \param isMc boolean flag whether MC or data is processed template - void reserveTables(size_t candidatesSize, bool isMc) + void reserveTables(int64_t candidatesSize, bool isMc) { if (fillCandidateLiteTable) { rowCandidateLite.reserve(candidatesSize * 2); @@ -813,22 +813,22 @@ struct HfTreeCreatorLcToPKPi { int functionSelection, int sigbgstatus) { - float chi2primProton; - float chi2primPion; - float dcaProtonKaon; - float dcaPionKaon; - float chi2GeoProtonKaon; - float chi2GeoPionKaon; - float mass; - float valueTpcNSigmaPr; + float chi2primProton{}; + float chi2primPion{}; + float dcaProtonKaon{}; + float dcaPionKaon{}; + float chi2GeoProtonKaon{}; + float chi2GeoPionKaon{}; + float mass{}; + float valueTpcNSigmaPr{}; const float valueTpcNSigmaKa = candidate.nSigTpcKa1(); - float valueTpcNSigmaPi; - float valueTofNSigmaPr; + float valueTpcNSigmaPi{}; + float valueTofNSigmaPr{}; const float valueTofNSigmaKa = candidate.nSigTofKa1(); - float valueTofNSigmaPi; - float valueTpcTofNSigmaPr; + float valueTofNSigmaPi{}; + float valueTpcTofNSigmaPr{}; const float valueTpcTofNSigmaKa = candidate.tpcTofNSigmaKa1(); - float valueTpcTofNSigmaPi; + float valueTpcTofNSigmaPi{}; if (candFlag == 0) { chi2primProton = candidate.kfChi2PrimProng0(); chi2primPion = candidate.kfChi2PrimProng2(); @@ -874,16 +874,16 @@ struct HfTreeCreatorLcToPKPi { const float chi2Topo = candidate.kfChi2Topo(); const float decayLength = candidate.kfDecayLength(); const float dl = candidate.kfDecayLengthError(); - const float pt = std::sqrt(candidate.kfPx() * candidate.kfPx() + candidate.kfPy() * candidate.kfPy()); + const float pt = std::hypot(candidate.kfPx(), candidate.kfPy()); const float deltaPt = std::sqrt(candidate.kfPx() * candidate.kfPx() * candidate.kfErrorPx() * candidate.kfErrorPx() + candidate.kfPy() * candidate.kfPy() * candidate.kfErrorPy() * candidate.kfErrorPy()) / pt; - const float p = std::sqrt(pt * pt + candidate.kfPz() * candidate.kfPz()); + const float p = std::hypot(pt, candidate.kfPz()); const float deltaP = std::sqrt(pt * pt * deltaPt * deltaPt + candidate.kfPz() * candidate.kfPz() * candidate.kfErrorPz() * candidate.kfErrorPz()) / p; - const float lifetime = decayLength * MassLambdaCPlus / LightSpeedCm2PS / p; - const float deltaT = dl * MassLambdaCPlus / LightSpeedCm2PS / p; + const float lifetime = decayLength * static_cast(MassLambdaCPlus) / LightSpeedCm2PS / p; + const float deltaT = dl * static_cast(MassLambdaCPlus) / LightSpeedCm2PS / p; rowCandidateKF( svX, svY, svZ, svErrX, svErrY, svErrZ, pvErrX, pvErrY, pvErrZ, @@ -923,17 +923,17 @@ struct HfTreeCreatorLcToPKPi { fillEventProperties(collisions); - const size_t candidatesSize = candidates.size(); + const int64_t candidatesSize = static_cast(candidates.size()); reserveTables(candidatesSize, IsMc); int iCand{0}; for (const auto& candidate : candidates) { - auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); + const auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); ++iCand; - float ptProng0 = candidate.ptProng0(); - auto collision = candidate.template collision_as(); + const float ptProng0 = candidate.ptProng0(); + const auto collision = candidate.template collision_as(); auto fillTable = [&](int candFlag) { - double const pseudoRndm = ptProng0 * 1000. - static_cast(ptProng0 * 1000); + double const pseudoRndm = ptProng0 * 1000. - static_cast(static_cast(ptProng0 * 1000)); const int functionSelection = candFlag == 0 ? candidate.isSelLcToPKPi() : candidate.isSelLcToPiKP(); const int sigbgstatus = determineSignalBgStatus(candidate, candFlag); const bool isMcCandidateSignal = (sigbgstatus == Prompt) || (sigbgstatus == NonPrompt); @@ -953,7 +953,7 @@ struct HfTreeCreatorLcToPKPi { fillKFTable(candidate, collision, candFlag, functionSelection, sigbgstatus); } if (fillCandidateMcTable) { - float p, pt, svX, svY, svZ, pvX, pvY, pvZ, decayLength, lifetime; + float p{}, pt{}, svX{}, svY{}, svZ{}, pvX{}, pvY{}, pvZ{}, decayLength{}, lifetime{}; if (!isMcCandidateSignal) { p = UndefValueFloat; pt = UndefValueFloat; @@ -966,13 +966,13 @@ struct HfTreeCreatorLcToPKPi { decayLength = UndefValueFloat; lifetime = UndefValueFloat; } else { - auto mcParticleProng0 = candidate.template prong0_as>().template mcParticle_as>(); - auto indexMother = RecoDecay::getMother(particles, mcParticleProng0, o2::constants::physics::Pdg::kLambdaCPlus, true); - auto particleMother = particles.rawIteratorAt(indexMother); - auto mcCollision = particleMother.template mcCollision_as(); + const auto mcParticleProng0 = candidate.template prong0_as>().template mcParticle_as>(); + const auto indexMother = RecoDecay::getMother(particles, mcParticleProng0, o2::constants::physics::Pdg::kLambdaCPlus, true); + const auto particleMother = particles.rawIteratorAt(indexMother); + const auto mcCollision = particleMother.template mcCollision_as(); p = particleMother.p(); pt = particleMother.pt(); - const float p2m = p / MassLambdaCPlus; + const float p2m = p / static_cast(MassLambdaCPlus); const float gamma = std::sqrt(1 + p2m * p2m); // mother's particle Lorentz factor pvX = mcCollision.posX(); pvY = mcCollision.posY(); @@ -980,7 +980,7 @@ struct HfTreeCreatorLcToPKPi { svX = mcParticleProng0.vx(); svY = mcParticleProng0.vy(); svZ = mcParticleProng0.vz(); - decayLength = RecoDecay::distance(std::array{svX, svY, svZ}, std::array{pvX, pvY, pvZ}); + decayLength = static_cast(RecoDecay::distance(std::array{svX, svY, svZ}, std::array{pvX, pvY, pvZ})); lifetime = mcParticleProng0.vt() * NanoToPico / gamma; // from ns to ps * from lab time to proper time } rowCandidateMC( @@ -999,10 +999,10 @@ struct HfTreeCreatorLcToPKPi { rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { if (std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { - auto mcDaughter0 = particle.template daughters_as>().begin(); - auto mcCollision = particle.template mcCollision_as(); - auto p = particle.p(); - const float p2m = p / MassLambdaCPlus; + const auto mcDaughter0 = particle.template daughters_as>().begin(); + const auto mcCollision = particle.template mcCollision_as(); + const auto p = particle.p(); + const float p2m = p / static_cast(MassLambdaCPlus); const float gamma = std::sqrt(1 + p2m * p2m); // mother's particle Lorentz factor const float pvX = mcCollision.posX(); const float pvY = mcCollision.posY(); @@ -1010,7 +1010,7 @@ struct HfTreeCreatorLcToPKPi { const float svX = mcDaughter0.vx(); const float svY = mcDaughter0.vy(); const float svZ = mcDaughter0.vz(); - const float l = RecoDecay::distance(std::array{svX, svY, svZ}, std::array{pvX, pvY, pvZ}); + const float l = static_cast(RecoDecay::distance(std::array{svX, svY, svZ}, std::array{pvX, pvY, pvZ})); const float t = mcDaughter0.vt() * NanoToPico / gamma; // from ns to ps * from lab time to proper time rowCandidateFullParticles( particle.pt(), @@ -1110,19 +1110,19 @@ struct HfTreeCreatorLcToPKPi { fillEventProperties(collisions); - const size_t candidatesSize = candidates.size(); + const size_t candidatesSize = static_cast(candidates.size()); reserveTables(candidatesSize, IsMc); // Filling candidate properties int iCand{0}; for (const auto& candidate : candidates) { - auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); + const auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); ++iCand; - float ptProng0 = candidate.ptProng0(); - auto collision = candidate.template collision_as(); + const float ptProng0 = candidate.ptProng0(); + const auto collision = candidate.template collision_as(); auto fillTable = [&](int candFlag) { - double const pseudoRndm = ptProng0 * 1000. - static_cast(ptProng0 * 1000); + double const pseudoRndm = ptProng0 * 1000. - static_cast(static_cast(ptProng0 * 1000)); const int functionSelection = candFlag == 0 ? candidate.isSelLcToPKPi() : candidate.isSelLcToPiKP(); if (functionSelection >= selectionFlagLc && (candidate.pt() > downSampleBkgPtMax || (pseudoRndm < downSampleBkgFactor && candidate.pt() < downSampleBkgPtMax))) { if (fillCandidateLiteTable) { diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index b443d8abc5a..8a952cbea49 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -10,12 +10,12 @@ // or submit itself to any jurisdiction. /// \file treeCreatorOmegacSt.cxx -/// \brief Task to reconstruct Ωc from strangeness-tracked Ω and pion/kaon +/// \brief Task to reconstruct Ωc/Ξc from strangeness-tracked Ω/Ξ and pion/kaon /// /// \author Jochen Klein /// \author Tiantian Cheng -#include "PWGHF/DataModel/TrackIndexSkimmingTables.h" +#include "PWGHF/Core/DecayChannelsLegacy.h" #include "PWGHF/Utils/utilsTrkCandHf.h" #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -261,7 +261,7 @@ struct HfTreeCreatorOmegacSt { Configurable cfgTriggersOfInterest{"cfgTriggersOfInterest", "fTrackedOmega,fHfCharmBarToXiBach", "Triggers of interest, comma separated for Zorro"}; SliceCache cache; - Service ccdb; + Service ccdb{}; o2::vertexing::DCAFitterN<2> df2; static constexpr int ItsNClsMin{4}; @@ -306,6 +306,8 @@ struct HfTreeCreatorOmegacSt { {"hMassOmegaPiVsPt", "inv. mass #Omega + #pi;inv. mass (GeV/#it{c}^{2});p_{T} (GeV/#it{c})", {HistType::kTH2D, {{400, 1.5, 3.}, {10, 0., 10.}}}}, {"hMassOmegaK", "inv. mass #Omega + K;inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.5, 3.}}}}, {"hMassOmegaKVsPt", "inv. mass #Omega + K;inv. mass (GeV/#it{c}^{2});p_{T} (GeV/#it{c})", {HistType::kTH2D, {{400, 1.5, 3.}, {10, 0., 10.}}}}, + {"hMassXiPi", "inv. mass #Xi + #pi;inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.2, 3.2}}}}, + {"hMassXiPiVsPt", "inv. mass #Xi + #pi;inv. mass (GeV/#it{c}^{2});p_{T} (GeV/#it{c})", {HistType::kTH2D, {{400, 1.2, 3.2}, {10, 0., 10.}}}}, {"hMassOmegacId", "inv. mass #Omega + #pi (MC ID);inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.5, 3.}}}}, {"hMassOmegacGen", "inv. mass #Omega + #pi (from MC);inv. mass (GeV/#it{c}^{2})", {HistType::kTH1D, {{400, 1.5, 3.}}}}, {"hPtVsMassOmega", "#Omega mass;p_{T} (GeV/#it{c});m (GeV/#it{c}^3)", {HistType::kTH2D, {{200, 0., 10.}, {1000, 1., 3.}}}}, @@ -366,70 +368,111 @@ struct HfTreeCreatorOmegacSt { for (const auto& mcParticle : mcParticles) { 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() == NDaughters) { - int idxPionDaughter = -1; - int idxCascDaughter = -1; - int idxKaonDaughter = -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 (idxKaonDaughter < 0 && (std::abs(daughter.pdgCode()) == kKPlus)) { - idxKaonDaughter = daughter.globalIndex(); - } - } - if (idxPionDaughter >= 0 && idxCascDaughter >= 0) { - decayChannel = o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi; // OmegaC -> Omega + Pi - } else if (idxKaonDaughter >= 0 && idxCascDaughter >= 0) { - decayChannel = o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK; // OmegaC -> Omega + K - } else { - decayChannel = -1; // LOG(warning) << "Decay channel not recognized!"; + if (!isOmegaC && !isXiC) { + continue; + } + const auto daughters = mcParticle.daughters_as(); + if (daughters.size() != NDaughters) { + continue; + } + int idxPionDaughter = -1; + int idxCascDaughter = -1; + int idxKaonDaughter = -1; + for (const auto& daughter : daughters) { + const int absDauPdg = std::abs(daughter.pdgCode()); + if (idxCascDaughter < 0) { + if (absDauPdg == kOmegaMinus || absDauPdg == kXiMinus) { + idxCascDaughter = daughter.globalIndex(); } - if (decayChannel != -1) { - int const idxDaughter = (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) ? idxPionDaughter : idxKaonDaughter; - auto particle = mcParticles.rawIteratorAt(idxDaughter); - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + } + if (idxPionDaughter < 0 && absDauPdg == kPiPlus) { + idxPionDaughter = daughter.globalIndex(); + } + if (idxKaonDaughter < 0 && absDauPdg == kKPlus) { + idxKaonDaughter = daughter.globalIndex(); + } + } - const auto& cascDaughter = mcParticles.iteratorAt(idxCascDaughter); - const auto& mcColl = mcParticle.mcCollision(); - std::array const primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; - std::array const 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 const 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, - origin, - decayChannel); - mapMcPartToGenTable[mcParticle.globalIndex()] = outputTableGen.lastIndex(); + if (idxCascDaughter < 0) { + continue; + } + + int decayChannel = -1; + const int pdgCasc = std::abs(mcParticles.iteratorAt(idxCascDaughter).pdgCode()); + + if (isOmegaC) { + // Omegac0 -> Omega- pi+ or Xi- pi+ + if (idxPionDaughter >= 0) { + if (pdgCasc == kOmegaMinus) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi; + } else if (pdgCasc == kXiMinus) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi; } } + } else if (isXiC) { + // Xic0 -> Omega- K+ or Xi- pi+ + if (pdgCasc == kOmegaMinus && idxKaonDaughter >= 0) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToOmegaK; + } else if (pdgCasc == kXiMinus && idxPionDaughter >= 0) { + decayChannel = o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi; + } + } + + if (decayChannel == -1) { + continue; + } + + int idxDaughter = -1; + switch (decayChannel) { + case o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi: + case o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi: + case o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi: + idxDaughter = idxPionDaughter; + break; + case o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToOmegaK: + idxDaughter = idxKaonDaughter; + break; + default: + idxDaughter = -1; + break; + } + + if (idxDaughter >= 0) { + auto particle = mcParticles.rawIteratorAt(idxDaughter); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } + + const auto& cascDaughter = mcParticles.iteratorAt(idxCascDaughter); + const auto& mcColl = mcParticle.mcCollision(); + std::array const primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; + std::array const 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 const 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, + origin, + decayChannel); + mapMcPartToGenTable[mcParticle.globalIndex()] = outputTableGen.lastIndex(); } } PROCESS_SWITCH(HfTreeCreatorOmegacSt, processMc, "Process MC", true); @@ -476,7 +519,6 @@ struct HfTreeCreatorOmegacSt { } } } - const auto primaryVertex = getPrimaryVertex(collision); const std::array primaryVertexPos = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; @@ -570,7 +612,6 @@ struct HfTreeCreatorOmegacSt { const auto massXi = RecoDecay::m(momentaCascDaughters, massesXiDaughters); std::array const massesOmegaDaughters = {o2::constants::physics::MassLambda0, o2::constants::physics::MassKPlus}; const auto massOmega = RecoDecay::m(momentaCascDaughters, massesOmegaDaughters); - registry.fill(HIST("hDca"), std::sqrt(impactParameterCasc.getR2())); registry.fill(HIST("hDcaXY"), impactParameterCasc.getY()); registry.fill(HIST("hDcaXYVsPt"), trackParCovCasc.getPt(), impactParameterCasc.getY()); @@ -588,7 +629,8 @@ struct HfTreeCreatorOmegacSt { std::array const massesOmegacToOmegaPi{o2::constants::physics::MassOmegaMinus, o2::constants::physics::MassPiPlus}; std::array const massesOmegacToOmegaK{o2::constants::physics::MassOmegaMinus, o2::constants::physics::MassKPlus}; - std::array const massesXicDaughters{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}; + // std::array const massesXicDaughters{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}; + std::array massesXicOrOmegacToXiPi{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}; std::array, NDaughters> momenta{}; auto trackParCovPr = getTrackParCov(v0TrackPr); @@ -662,11 +704,15 @@ struct HfTreeCreatorOmegacSt { df2.getTrackParamAtPCA(1).getPxPyPzGlo(momenta[1]); const auto massOmegaPi = RecoDecay::m(momenta, massesOmegacToOmegaPi); const auto massOmegaK = RecoDecay::m(momenta, massesOmegacToOmegaK); - const auto massXiC = RecoDecay::m(momenta, massesXicDaughters); + // const auto massXiC = RecoDecay::m(momenta, massesXicDaughters); + const auto massXiPi = RecoDecay::m(momenta, massesXicOrOmegacToXiPi); + registry.fill(HIST("hMassOmegaPi"), massOmegaPi); registry.fill(HIST("hMassOmegaPiVsPt"), massOmegaPi, RecoDecay::pt(momenta[0], momenta[1])); registry.fill(HIST("hMassOmegaK"), massOmegaK); registry.fill(HIST("hMassOmegaKVsPt"), massOmegaK, RecoDecay::pt(momenta[0], momenta[1])); + registry.fill(HIST("hMassXiPi"), massXiPi); + registry.fill(HIST("hMassXiPiVsPt"), massXiPi, RecoDecay::pt(momenta[0], momenta[1])); //--- do the MC Rec match if (mcParticles) { @@ -684,7 +730,7 @@ struct HfTreeCreatorOmegacSt { v0.posTrack_as(), // p <- lambda v0.negTrack_as()}; // pi <- lambda - if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { + if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToOmegaPi) { // Match Omegac0 → Omega- + Pi+ indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, std::array{+kPiPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); @@ -700,17 +746,65 @@ struct HfTreeCreatorOmegacSt { } } } - } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { - // Match Omegac0 → Omega- + K+ + // } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { + // // Match Omegac0 → Omega- + K+ + // indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, + // std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); + // indexRecCharmBaryon = indexRec; + // if (indexRec > -1) { + // // Omega- → K pi p (Cascade match) + // indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + // if (indexRec > -1) { + // // Lambda → p pi (Lambda match) + // indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); + // if (indexRec > -1) { + // isMatched = true; + // } + // } + // } + } else if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::OmegaczeroToXiPi) { + // Match Omegac0 -> Xi Pion indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, - std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); + std::array{+kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, &sign, 3); + indexRecCharmBaryon = indexRec; + if (indexRec > -1) { + // Xi- → pi pi p (Cascade match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kXiMinus, std::array{+kPiMinus, +kProton, +kPiMinus}, true, &signCasc, 2); + if (indexRec > -1) { + // Lambda → p pi (Lambda match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); + if (indexRec > -1) { + isMatched = true; + } + } + } + } else if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToOmegaK) { + // Match Xic0 → Omega- + K+ + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kXiC0, + std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3); indexRecCharmBaryon = indexRec; if (indexRec > -1) { // Omega- → K pi p (Cascade match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2); if (indexRec > -1) { // Lambda → p pi (Lambda match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); + if (indexRec > -1) { + isMatched = true; + } + } + } + } else if (decayChannel == o2::aod::hf_cand_xic0_omegac0::DecayType::XiczeroToXiPi) { + // Match Xic0 -> Xi Pion + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kXiC0, + std::array{+kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, &sign, 3); + indexRecCharmBaryon = indexRec; + if (indexRec > -1) { + // Xi- → pi pi p (Cascade match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kXiMinus, std::array{+kPiMinus, +kProton, +kPiMinus}, true, &signCasc, 2); + if (indexRec > -1) { + // Lambda → p pi (Lambda match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1); if (indexRec > -1) { isMatched = true; } @@ -723,9 +817,12 @@ struct HfTreeCreatorOmegacSt { } } - if ((std::abs(massOmegaK - o2::constants::physics::MassOmegaC0) < massWindowOmegaC) || + if ((std::abs(massOmegaK - o2::constants::physics::MassXiC0) < massWindowXiC) || (std::abs(massOmegaPi - o2::constants::physics::MassOmegaC0) < massWindowOmegaC) || - (std::abs(massXiC - o2::constants::physics::MassXiC0) < massWindowXiC)) { + (std::abs(massXiPi - o2::constants::physics::MassXiC0) < massWindowXiC) || + (std::abs(massXiPi - o2::constants::physics::MassOmegaC0) < massWindowOmegaC) + + ) { registry.fill(HIST("hDecayLength"), decayLength * 1e4); registry.fill(HIST("hDecayLengthScaled"), decayLength * o2::constants::physics::MassOmegaC0 / RecoDecay::p(momenta[0], momenta[1]) * 1e4); outputTable(massOmega, diff --git a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx index 212d6e597a6..0b92effcdba 100644 --- a/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx +++ b/PWGHF/TableProducer/treeCreatorSigmacCorrBkg.cxx @@ -41,6 +41,7 @@ #include #include +#include using namespace o2; using namespace o2::framework; // for Produces, Configuable @@ -55,8 +56,11 @@ enum Decays { Sigmac2455Pi = 0, LambdacPiPi }; enum DecaysLambdac { PKPi = 0, PiKP }; +enum Reflections { NotReflected = 0, + Reflected }; DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(PtLc, ptLc, float); DECLARE_SOA_COLUMN(Mass, mass, float); DECLARE_SOA_COLUMN(DeltaMass, deltaMass, float); DECLARE_SOA_COLUMN(Charge, charge, int8_t); @@ -65,10 +69,13 @@ DECLARE_SOA_COLUMN(Decay, decay, int8_t); DECLARE_SOA_COLUMN(DecayLambdac, decayLambdac, int8_t); DECLARE_SOA_COLUMN(MlScoreFirstClass, mlScoreFirstClass, float); /// background score Λc DECLARE_SOA_COLUMN(MlScoreThirdClass, mlScoreThirdClass, float); /// non-prompt score Λc +DECLARE_SOA_COLUMN(IsReflected, isReflected, int8_t); +DECLARE_SOA_COLUMN(Origin, origin, int8_t); } // namespace hf_sigmac_bkg DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::Y, hf_sigmac_bkg::Pt, + hf_sigmac_bkg::PtLc, hf_sigmac_bkg::Mass, hf_sigmac_bkg::DeltaMass, hf_sigmac_bkg::Charge, @@ -76,23 +83,37 @@ DECLARE_SOA_TABLE(HfCorrBkgSc, "AOD", "HFCORRBKGSC", hf_sigmac_bkg::Decay, hf_sigmac_bkg::DecayLambdac, hf_sigmac_bkg::MlScoreFirstClass, - hf_sigmac_bkg::MlScoreThirdClass); + hf_sigmac_bkg::MlScoreThirdClass, + hf_sigmac_bkg::IsReflected); +DECLARE_SOA_TABLE(HfGenBkgSc, "AOD", "HFGENBKGSC", + hf_sigmac_bkg::Y, + hf_sigmac_bkg::Pt, + hf_sigmac_bkg::MotherPdg, + hf_sigmac_bkg::Origin); } // namespace o2::aod struct HfTreeCreatorSigmacCorrBkg { Produces rowCorrBkgSc; + Produces rowGenBkgSc; /// Selection of candidates Λc+ Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; Configurable yCandRecoMax{"yCandRecoMax", -1, "Maximum Sc candidate rapidity"}; + Configurable keepReflectedSignals{"keepReflectedSignals", false, "Keep also the reflected signals (i.e. generated pKpi reco as piKp, and viceversa)"}; using RecoLcMc = soa::Join; using RecoScMc = soa::Join; using ParticlesLcSigmac = soa::Join; /// @brief init function - void init(InitContext&) {} + void init(InitContext&) + { + std::array doprocesses{doprocessReco, doprocessGen}; + if (std::accumulate(doprocesses.begin(), doprocesses.end(), 0) == 0) { + LOGP(fatal, "No process function enabled. Aborting..."); + } + } /// void fillTable(RecoScMc::iterator candidateSc, RecoLcMc::iterator candLcDauSc, int motherPdg, int motherDecay = -1) @@ -103,41 +124,66 @@ struct HfTreeCreatorSigmacCorrBkg { float massLc = -1.f; float deltaMass = -1.f; const int8_t isCandPKPiPiKP = hf_sigmac_utils::isDecayToPKPiToPiKP(candLcDauSc, candidateSc); - std::array outputMl{-1., -1.}; + std::array outputMlLcPKPi{-1., -1.}; + std::array outputMlLcPiKP{-1., -1.}; + const float ptSc = candidateSc.pt(); + const float ptLcDauSc = candLcDauSc.pt(); /// rapidity selection on Σc0,++ if (yCandRecoMax >= 0. && std::abs(rapidity) > yCandRecoMax) { return; } /// BDT scores + // reconstructed Λc± → pK-π+ + if (!candLcDauSc.mlProbLcToPKPi().empty()) { + outputMlLcPKPi.at(0) = candLcDauSc.mlProbLcToPKPi()[0]; /// bkg score + outputMlLcPKPi.at(1) = candLcDauSc.mlProbLcToPKPi()[2]; /// non-prompt score + } + // reconstructed Λc± → π+K-p if (!candLcDauSc.mlProbLcToPiKP().empty()) { - outputMl.at(0) = candLcDauSc.mlProbLcToPiKP()[0]; /// bkg score - outputMl.at(1) = candLcDauSc.mlProbLcToPiKP()[2]; /// non-prompt score + outputMlLcPiKP.at(0) = candLcDauSc.mlProbLcToPiKP()[0]; /// bkg score + outputMlLcPiKP.at(1) = candLcDauSc.mlProbLcToPiKP()[2]; /// non-prompt score } - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candLcDauSc.template prong0_as().template mcParticle_as().pdgCode()) == kProton) { + int pdgCodeProng0Abs = std::abs(candLcDauSc.template prong0_as().template mcParticle_as().pdgCode()); + + /// candidates with Λc± reconstructed in the pK-π+ decay + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi))) { + massSc = HfHelper::invMassScRecoLcToPKPi(candidateSc, candLcDauSc); massLc = HfHelper::invMassLcToPKPi(candLcDauSc); deltaMass = massSc - massLc; - /// fill the tree - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMl.at(0), outputMl.at(1)); + if (pdgCodeProng0Abs == kProton) { + /// candidates with reconstructed Λc± → pK-π+ decay that are generated Λc± → pK-π+ (not reflected) + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); + } else if (keepReflectedSignals && pdgCodeProng0Abs == kPiPlus) { + /// candidates with reconstructed Λc± → pK-π+ decay that are actually generated Λc± → π+K-p (reflected) + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PKPi, outputMlLcPKPi.at(0), outputMlLcPKPi.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); + } } - if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP)) && std::abs(candLcDauSc.template prong0_as().template mcParticle_as().pdgCode()) == kPiPlus) { + /// candidates with Λc± reconstructed in the π+K-p decay + if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PiKP))) { + massSc = HfHelper::invMassScRecoLcToPiKP(candidateSc, candLcDauSc); massLc = HfHelper::invMassLcToPiKP(candLcDauSc); deltaMass = massSc - massLc; - /// fill the tree - rowCorrBkgSc(rapidity, candidateSc.pt(), massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMl.at(0), outputMl.at(1)); + if (pdgCodeProng0Abs == kPiPlus) { + /// candidates with reconstructed Λc± → π+K-p decay that are generated Λc± → π+K-p (not reflected) + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::NotReflected); + } else if (keepReflectedSignals && pdgCodeProng0Abs == kProton) { + /// candidates with reconstructed Λc± → π+K-p decay that are actually generated Λc± → pK-π+ (reflected) + rowCorrBkgSc(rapidity, ptSc, ptLcDauSc, massSc, deltaMass, chargeSc, motherPdg, motherDecay, aod::hf_sigmac_bkg::DecaysLambdac::PiKP, outputMlLcPiKP.at(0), outputMlLcPiKP.at(1), aod::hf_sigmac_bkg::Reflections::Reflected); + } } } /// @brief process function to loop over the Σc reconstructed candidates and match them to corr. background sources in MC - void process(RecoScMc const& candidatesSc, - ParticlesLcSigmac const& particles, - RecoLcMc const&, - aod::TracksWMc const&) + void processReco(RecoScMc const& candidatesSc, + ParticlesLcSigmac const& particles, + RecoLcMc const&, + aod::TracksWMc const&) { /// loop over reconstructed Σc candidates for (auto const& candidateSc : candidatesSc) { @@ -303,6 +349,29 @@ struct HfTreeCreatorSigmacCorrBkg { } /// end loop over reconstructed Σc candidates } + PROCESS_SWITCH(HfTreeCreatorSigmacCorrBkg, processReco, "Process Reco MC", false); + + /// @brief process function to look for generated Σc and Λc±(2595, 2625) (needed to properly normalize the bkg templates) + void processGen(aod::McParticles const& particles) + { + /// loop over particles + for (auto const& particle : particles) { + int pdgCodeAbs = std::abs(particle.pdgCode()); + + /// keep only Σc and Λc±(2595, 2625) + if (pdgCodeAbs != o2::constants::physics::Pdg::kSigmaC0 && pdgCodeAbs != o2::constants::physics::Pdg::kSigmaCPlusPlus && pdgCodeAbs != o2::constants::physics::Pdg::kSigmaCStar0 && pdgCodeAbs != o2::constants::physics::Pdg::kSigmaCStarPlusPlus && pdgCodeAbs != aod::hf_sigmac_bkg::pdgCodeLambdac2595 && pdgCodeAbs != aod::hf_sigmac_bkg::pdgCodeLambdac2625) { + continue; + } + + /// if we arrive here, it means that the particle is either a Σc or Λc±(2595, 2625) + /// let's check the origin (prompt, non-prompt) + int8_t origin = static_cast(RecoDecay::getCharmHadronOrigin(particles, particle, false)); + + /// let's fill the table + rowGenBkgSc(particle.y(), particle.pt(), pdgCodeAbs, origin); + } /// end loop over particles + } + PROCESS_SWITCH(HfTreeCreatorSigmacCorrBkg, processGen, "Process generated MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx b/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx index e57a9c5c7c0..67507a4c36f 100644 --- a/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx @@ -258,7 +258,7 @@ struct HfTreeCreatorTccToD0D0Pi { o2::vertexing::DCAFitterN<2> dfD1; // 2-prong vertex fitter (to rebuild D01 vertex) o2::vertexing::DCAFitterN<2> dfD2; // 2-prong vertex fitter (to rebuild D02 vertex) - Service ccdb; + Service ccdb{}; o2::base::MatLayerCylSet* lut{}; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; double bz{0.}; @@ -599,7 +599,6 @@ struct HfTreeCreatorTccToD0D0Pi { } hCandidatesTcc->Fill(SVFitting::FitOk); - dfTcc.propagateTracksToVertex(); // propagate the softpi and D0 pair to the Tcc vertex trackD1.getPxPyPzGlo(pVecD1); // momentum of D1 at the Tcc vertex trackD2.getPxPyPzGlo(pVecD2); // momentum of D2 at the Tcc vertex trackParCovPi.getPxPyPzGlo(pVecSoftPi); // momentum of pi at the Tcc vertex diff --git a/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx b/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx new file mode 100644 index 00000000000..2e219e14355 --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorToXiPiQa.cxx @@ -0,0 +1,982 @@ +// 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 treeCreatorToXiPiQa.cxx +/// \brief Writer of the omegac0 or xic0 to Xi Pi candidates in the form of flat tables to be stored in TTrees. +/// In this file are defined and filled the output tables +/// +/// \author Jinhyun Park , Pusan National University +/// \author Krista Smith , Pusan National University + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; + +// SV Reco method +enum { + DCAFITTER = 0, + KFPARTICLE +}; + +// Table size +enum { + FULL = 0, + LITE +}; + +namespace o2::aod +{ +namespace full +{ +// collision info +DECLARE_SOA_COLUMN(IsEventSel8, isEventSel8, bool); +DECLARE_SOA_COLUMN(IsEventSelZ, isEventSelZ, bool); +DECLARE_SOA_COLUMN(Centrality, centrality, float); +// from creator +DECLARE_SOA_COLUMN(XPv, xPv, float); +DECLARE_SOA_COLUMN(YPv, yPv, float); +DECLARE_SOA_COLUMN(ZPv, zPv, float); +DECLARE_SOA_COLUMN(XDecayVtxCharmBaryon, xDecayVtxCharmBaryon, float); +DECLARE_SOA_COLUMN(YDecayVtxCharmBaryon, yDecayVtxCharmBaryon, float); +DECLARE_SOA_COLUMN(ZDecayVtxCharmBaryon, zDecayVtxCharmBaryon, float); +DECLARE_SOA_COLUMN(XDecayVtxCascade, xDecayVtxCascade, float); +DECLARE_SOA_COLUMN(YDecayVtxCascade, yDecayVtxCascade, float); +DECLARE_SOA_COLUMN(ZDecayVtxCascade, zDecayVtxCascade, float); +DECLARE_SOA_COLUMN(XDecayVtxV0, xDecayVtxV0, float); +DECLARE_SOA_COLUMN(YDecayVtxV0, yDecayVtxV0, float); +DECLARE_SOA_COLUMN(ZDecayVtxV0, zDecayVtxV0, float); +DECLARE_SOA_COLUMN(SignDecay, signDecay, int8_t); // sign of pi <- xi +DECLARE_SOA_COLUMN(CovVtxCharmBaryonXX, covVtxCharmBaryonXX, float); +DECLARE_SOA_COLUMN(CovVtxCharmBaryonYY, covVtxCharmBaryonYY, float); +DECLARE_SOA_COLUMN(CovVtxCharmBaryonZZ, covVtxCharmBaryonZZ, float); +DECLARE_SOA_COLUMN(PxCharmBaryon, pxCharmBaryon, float); +DECLARE_SOA_COLUMN(PyCharmBaryon, pyCharmBaryon, float); +DECLARE_SOA_COLUMN(PzCharmBaryon, pzCharmBaryon, float); +DECLARE_SOA_COLUMN(PxCasc, pxCasc, float); +DECLARE_SOA_COLUMN(PyCasc, pyCasc, float); +DECLARE_SOA_COLUMN(PzCasc, pzCasc, float); +DECLARE_SOA_COLUMN(PxPiFromCharmBaryon, pxPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PyPiFromCharmBaryon, pyPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PzPiFromCharmBaryon, pzPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PxLambda, pxLambda, float); +DECLARE_SOA_COLUMN(PyLambda, pyLambda, float); +DECLARE_SOA_COLUMN(PzLambda, pzLambda, float); +DECLARE_SOA_COLUMN(PtCharmBaryon, ptCharmBaryon, float); +DECLARE_SOA_COLUMN(PtPiFromCharmBaryon, ptPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(PxPiFromCasc, pxPiFromCasc, float); +DECLARE_SOA_COLUMN(PyPiFromCasc, pyPiFromCasc, float); +DECLARE_SOA_COLUMN(PzPiFromCasc, pzPiFromCasc, float); +DECLARE_SOA_COLUMN(PxPosV0Dau, pxPosV0Dau, float); +DECLARE_SOA_COLUMN(PyPosV0Dau, pyPosV0Dau, float); +DECLARE_SOA_COLUMN(PzPosV0Dau, pzPosV0Dau, float); +DECLARE_SOA_COLUMN(PxNegV0Dau, pxNegV0Dau, float); +DECLARE_SOA_COLUMN(PyNegV0Dau, pyNegV0Dau, float); +DECLARE_SOA_COLUMN(PzNegV0Dau, pzNegV0Dau, float); +DECLARE_SOA_COLUMN(ImpactParCascXY, impactParCascXY, float); +DECLARE_SOA_COLUMN(ImpactParPiFromCharmBaryonXY, impactParPiFromCharmBaryonXY, float); +DECLARE_SOA_COLUMN(ImpactParCascZ, impactParCascZ, float); +DECLARE_SOA_COLUMN(ImpactParPiFromCharmBaryonZ, impactParPiFromCharmBaryonZ, float); +DECLARE_SOA_COLUMN(ErrImpactParCascXY, errImpactParCascXY, float); +DECLARE_SOA_COLUMN(ErrImpactParPiFromCharmBaryonXY, errImpactParPiFromCharmBaryonXY, float); +DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); +DECLARE_SOA_COLUMN(InvMassCascade, invMassCascade, float); +DECLARE_SOA_COLUMN(InvMassCharmBaryon, invMassCharmBaryon, float); +DECLARE_SOA_COLUMN(CosPAV0, cosPAV0, float); +DECLARE_SOA_COLUMN(CosPACharmBaryon, cosPACharmBaryon, float); +DECLARE_SOA_COLUMN(CosPACasc, cosPACasc, float); +DECLARE_SOA_COLUMN(CosPAXYV0, cosPAXYV0, float); +DECLARE_SOA_COLUMN(CosPAXYCharmBaryon, cosPAXYCharmBaryon, float); +DECLARE_SOA_COLUMN(CosPAXYCasc, cosPAXYCasc, float); +DECLARE_SOA_COLUMN(CTauOmegac, cTauOmegac, float); +DECLARE_SOA_COLUMN(CTauCascade, cTauCascade, float); +DECLARE_SOA_COLUMN(CTauV0, cTauV0, float); +DECLARE_SOA_COLUMN(CTauXic, cTauXic, float); +DECLARE_SOA_COLUMN(EtaV0PosDau, etaV0PosDau, float); +DECLARE_SOA_COLUMN(EtaV0NegDau, etaV0NegDau, float); +DECLARE_SOA_COLUMN(EtaPiFromCasc, etaPiFromCasc, float); +DECLARE_SOA_COLUMN(EtaPiFromCharmBaryon, etaPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(EtaCharmBaryon, etaCharmBaryon, float); +DECLARE_SOA_COLUMN(EtaCascade, etaCascade, float); +DECLARE_SOA_COLUMN(EtaV0, etaV0, float); +DECLARE_SOA_COLUMN(DcaXYToPvV0Dau0, dcaXYToPvV0Dau0, float); +DECLARE_SOA_COLUMN(DcaXYToPvV0Dau1, dcaXYToPvV0Dau1, float); +DECLARE_SOA_COLUMN(DcaXYToPvCascDau, dcaXYToPvCascDau, float); +DECLARE_SOA_COLUMN(DcaZToPvV0Dau0, dcaZToPvV0Dau0, float); +DECLARE_SOA_COLUMN(DcaZToPvV0Dau1, dcaZToPvV0Dau1, float); +DECLARE_SOA_COLUMN(DcaZToPvCascDau, dcaZToPvCascDau, float); +DECLARE_SOA_COLUMN(DcaCascDau, dcaCascDau, float); +DECLARE_SOA_COLUMN(DcaV0Dau, dcaV0Dau, float); +DECLARE_SOA_COLUMN(DcaCharmBaryonDau, dcaCharmBaryonDau, float); +DECLARE_SOA_COLUMN(DecLenCharmBaryon, decLenCharmBaryon, float); +DECLARE_SOA_COLUMN(DecLenCascade, decLenCascade, float); +DECLARE_SOA_COLUMN(DecLenV0, decLenV0, float); +DECLARE_SOA_COLUMN(ErrorDecayLengthCharmBaryon, errorDecayLengthCharmBaryon, float); +DECLARE_SOA_COLUMN(ErrorDecayLengthXYCharmBaryon, errorDecayLengthXYCharmBaryon, float); +DECLARE_SOA_COLUMN(NormImpParCascade, normImpParCascade, double); +DECLARE_SOA_COLUMN(NormImpParPiFromCharmBar, normImpParPiFromCharmBar, double); +DECLARE_SOA_COLUMN(NormDecayLenCharmBar, normDecayLenCharmBar, double); +DECLARE_SOA_COLUMN(IsPionGlbTrkWoDca, isPionGlbTrkWoDca, bool); +DECLARE_SOA_COLUMN(PionItsNCls, pionItsNCls, uint8_t); +DECLARE_SOA_COLUMN(NTpcRowsPion, nTpcRowsPion, int16_t); +DECLARE_SOA_COLUMN(NTpcRowsPiFromCasc, nTpcRowsPiFromCasc, int16_t); +DECLARE_SOA_COLUMN(NTpcRowsPosV0Dau, nTpcRowsPosV0Dau, int16_t); +DECLARE_SOA_COLUMN(NTpcRowsNegV0Dau, nTpcRowsNegV0Dau, int16_t); +// from creator - MC +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_COLUMN(OriginRec, originRec, int8_t); +DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); +// from selector +DECLARE_SOA_COLUMN(StatusPidLambda, statusPidLambda, bool); +DECLARE_SOA_COLUMN(StatusPidCascade, statusPidCascade, bool); +DECLARE_SOA_COLUMN(StatusPidCharmBaryon, statusPidCharmBaryon, bool); +DECLARE_SOA_COLUMN(StatusInvMassLambda, statusInvMassLambda, bool); +DECLARE_SOA_COLUMN(StatusInvMassCascade, statusInvMassCascade, bool); +DECLARE_SOA_COLUMN(StatusInvMassCharmBaryon, statusInvMassCharmBaryon, bool); +DECLARE_SOA_COLUMN(ResultSelections, resultSelections, bool); +DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); +DECLARE_SOA_COLUMN(PidTofInfoStored, pidTofInfoStored, int); +DECLARE_SOA_COLUMN(TpcNSigmaPiFromCharmBaryon, tpcNSigmaPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(TpcNSigmaPiFromCasc, tpcNSigmaPiFromCasc, float); +DECLARE_SOA_COLUMN(TpcNSigmaPiFromLambda, tpcNSigmaPiFromLambda, float); +DECLARE_SOA_COLUMN(TpcNSigmaPrFromLambda, tpcNSigmaPrFromLambda, float); +DECLARE_SOA_COLUMN(TofNSigmaPiFromCharmBaryon, tofNSigmaPiFromCharmBaryon, float); +DECLARE_SOA_COLUMN(TofNSigmaPiFromCasc, tofNSigmaPiFromCasc, float); +DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); +DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); +// from creator KF +DECLARE_SOA_COLUMN(KfDcaXYPiFromXic, kfDcaXYPiFromXic, float); +DECLARE_SOA_COLUMN(KfDcaXYCascToPv, kfDcaXYCascToPv, float); +DECLARE_SOA_COLUMN(Chi2GeoV0, chi2GeoV0, float); +DECLARE_SOA_COLUMN(Chi2GeoCasc, chi2GeoCasc, float); +DECLARE_SOA_COLUMN(Chi2GeoXic, chi2GeoXic, 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(Xicldl, xicldl, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToPv, chi2TopoV0ToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToPv, chi2TopoCascToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoPiFromXicToPv, chi2TopoPiFromXicToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoXicToPv, chi2TopoXicToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoV0ToCasc, chi2TopoV0ToCasc, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToXic, chi2TopoCascToXic, float); +DECLARE_SOA_COLUMN(DecayLenXYLambda, decayLenXYLambda, float); +DECLARE_SOA_COLUMN(DecayLenXYCasc, decayLenXYCasc, float); +DECLARE_SOA_COLUMN(DecayLenXYXic, decayLenXYXic, float); +DECLARE_SOA_COLUMN(CosPaV0ToCasc, cosPaV0ToCasc, float); +DECLARE_SOA_COLUMN(CosPaV0ToPv, cosPaV0ToPv, float); +DECLARE_SOA_COLUMN(CosPaCascToXic, cosPaCascToXic, float); +DECLARE_SOA_COLUMN(CosPaCascToPv, cosPaCascToPv, float); +DECLARE_SOA_COLUMN(CosPaXicToPv, cosPaXicToPv, float); +DECLARE_SOA_COLUMN(KfRapXic, kfRapXic, float); +DECLARE_SOA_COLUMN(KfptPiFromXic, kfptPiFromXic, float); +DECLARE_SOA_COLUMN(KfptXic, kfptXic, float); +DECLARE_SOA_COLUMN(CosThetaStarPiFromXic, cosThetaStarPiFromXic, float); +DECLARE_SOA_COLUMN(CtXic, ctXic, float); +DECLARE_SOA_COLUMN(EtaXic, etaXic, float); +DECLARE_SOA_COLUMN(V0Ndf, v0Ndf, float); +DECLARE_SOA_COLUMN(CascNdf, cascNdf, float); +DECLARE_SOA_COLUMN(XicNdf, xicNdf, 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(XicChi2OverNdf, xicChi2OverNdf, float); +DECLARE_SOA_COLUMN(MassV0Chi2OverNdf, massV0Chi2OverNdf, float); +DECLARE_SOA_COLUMN(MassCascChi2OverNdf, massCascChi2OverNdf, float); +} // namespace full + +DECLARE_SOA_TABLE(HfToXiPiEvs, "AOD", "HFTOXIPIEV", + full::IsEventSel8, full::IsEventSelZ); + +DECLARE_SOA_TABLE(HfToXiPiFulls, "AOD", "HFTOXIPIFULL", + full::XPv, full::YPv, full::ZPv, full::Centrality, collision::NumContrib, collision::Chi2, + full::XDecayVtxCharmBaryon, full::YDecayVtxCharmBaryon, full::ZDecayVtxCharmBaryon, + full::XDecayVtxCascade, full::YDecayVtxCascade, full::ZDecayVtxCascade, + full::XDecayVtxV0, full::YDecayVtxV0, full::ZDecayVtxV0, + full::SignDecay, + full::CovVtxCharmBaryonXX, full::CovVtxCharmBaryonYY, full::CovVtxCharmBaryonZZ, + full::PtCharmBaryon, full::PtPiFromCharmBaryon, + full::PxCharmBaryon, full::PyCharmBaryon, full::PzCharmBaryon, + full::PxCasc, full::PyCasc, full::PzCasc, + full::PxPiFromCharmBaryon, full::PyPiFromCharmBaryon, full::PzPiFromCharmBaryon, + full::PxLambda, full::PyLambda, full::PzLambda, + full::PxPiFromCasc, full::PyPiFromCasc, full::PzPiFromCasc, + full::PxPosV0Dau, full::PyPosV0Dau, full::PzPosV0Dau, + full::PxNegV0Dau, full::PyNegV0Dau, full::PzNegV0Dau, + full::ImpactParCascXY, full::ImpactParPiFromCharmBaryonXY, + full::ImpactParCascZ, full::ImpactParPiFromCharmBaryonZ, + full::ErrImpactParCascXY, full::ErrImpactParPiFromCharmBaryonXY, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::CosPAV0, full::CosPACharmBaryon, full::CosPACasc, full::CosPAXYV0, full::CosPAXYCharmBaryon, full::CosPAXYCasc, + full::CTauOmegac, full::CTauCascade, full::CTauV0, full::CTauXic, + full::EtaV0PosDau, full::EtaV0NegDau, full::EtaPiFromCasc, full::EtaPiFromCharmBaryon, + full::EtaCharmBaryon, full::EtaCascade, full::EtaV0, + full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, + full::DcaZToPvV0Dau0, full::DcaZToPvV0Dau1, full::DcaZToPvCascDau, + full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, + full::DecLenCharmBaryon, full::DecLenCascade, full::DecLenV0, full::ErrorDecayLengthCharmBaryon, full::ErrorDecayLengthXYCharmBaryon, + full::NormImpParCascade, full::NormImpParPiFromCharmBar, full::NormDecayLenCharmBar, full::IsPionGlbTrkWoDca, full::PionItsNCls, + full::NTpcRowsPion, full::NTpcRowsPiFromCasc, full::NTpcRowsPosV0Dau, full::NTpcRowsNegV0Dau, + full::StatusPidLambda, full::StatusPidCascade, full::StatusPidCharmBaryon, + full::StatusInvMassLambda, full::StatusInvMassCascade, full::StatusInvMassCharmBaryon, full::ResultSelections, + full::PidTpcInfoStored, full::PidTofInfoStored, + full::TpcNSigmaPiFromCharmBaryon, full::TpcNSigmaPiFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, + full::TofNSigmaPiFromCharmBaryon, full::TofNSigmaPiFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, + full::FlagMcMatchRec, full::DebugMcRec, full::OriginRec, full::CollisionMatched); + +DECLARE_SOA_TABLE(HfToXiPiLites, "AOD", "HFTOXIPILITE", + full::XPv, full::YPv, full::ZPv, full::Centrality, collision::NumContrib, collision::Chi2, + full::XDecayVtxCharmBaryon, full::YDecayVtxCharmBaryon, full::ZDecayVtxCharmBaryon, + full::XDecayVtxCascade, full::YDecayVtxCascade, full::ZDecayVtxCascade, + full::XDecayVtxV0, full::YDecayVtxV0, full::ZDecayVtxV0, + full::SignDecay, + full::PtCharmBaryon, full::PtPiFromCharmBaryon, + full::PxCharmBaryon, full::PyCharmBaryon, full::PzCharmBaryon, + full::PxPiFromCharmBaryon, full::PyPiFromCharmBaryon, full::PzPiFromCharmBaryon, + full::PxPiFromCasc, full::PyPiFromCasc, full::PzPiFromCasc, + full::PxPosV0Dau, full::PyPosV0Dau, full::PzPosV0Dau, + full::PxNegV0Dau, full::PyNegV0Dau, full::PzNegV0Dau, + full::ImpactParCascXY, full::ImpactParPiFromCharmBaryonXY, + full::ErrImpactParCascXY, full::ErrImpactParPiFromCharmBaryonXY, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::CosPAV0, full::CosPACharmBaryon, full::CosPACasc, + full::EtaV0PosDau, full::EtaV0NegDau, full::EtaPiFromCasc, full::EtaPiFromCharmBaryon, full::EtaCharmBaryon, + full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, + full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, + full::ErrorDecayLengthCharmBaryon, full::NormImpParCascade, full::NormImpParPiFromCharmBar, + full::IsPionGlbTrkWoDca, full::PionItsNCls, + full::NTpcRowsPion, full::NTpcRowsPiFromCasc, full::NTpcRowsPosV0Dau, full::NTpcRowsNegV0Dau, + full::PidTpcInfoStored, full::PidTofInfoStored, + full::TpcNSigmaPiFromCharmBaryon, full::TpcNSigmaPiFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, + full::TofNSigmaPiFromCharmBaryon, full::TofNSigmaPiFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, + full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched); + +DECLARE_SOA_TABLE(HfKfXicFulls, "AOD", "HFKFXICFULL", + full::Centrality, + full::TpcNSigmaPiFromCharmBaryon, full::TofNSigmaPiFromCharmBaryon, full::TpcNSigmaPiFromCasc, full::TofNSigmaPiFromCasc, + full::TpcNSigmaPiFromLambda, full::TofNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, full::TofNSigmaPrFromLambda, + full::KfDcaXYPiFromXic, full::DcaCascDau, full::DcaV0Dau, full::DcaCharmBaryonDau, full::KfDcaXYCascToPv, + full::DcaXYToPvV0Dau0, full::DcaXYToPvV0Dau1, full::DcaXYToPvCascDau, + full::Chi2GeoV0, full::Chi2GeoCasc, full::Chi2GeoXic, + full::Chi2MassV0, full::Chi2MassCasc, + full::V0ldl, full::Cascldl, + full::Chi2TopoV0ToPv, full::Chi2TopoCascToPv, full::Chi2TopoPiFromXicToPv, full::Chi2TopoXicToPv, + full::Chi2TopoV0ToCasc, full::Chi2TopoCascToXic, + full::DecayLenXYLambda, full::DecayLenXYCasc, full::DecayLenXYXic, + full::CosPaV0ToCasc, full::CosPaV0ToPv, full::CosPaCascToXic, full::CosPaCascToPv, // full::CosPaXicToPv, + full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, + full::KfRapXic, full::KfptPiFromXic, full::KfptXic, + full::CosThetaStarPiFromXic, full::CtXic, full::EtaXic, + full::V0Ndf, full::CascNdf, full::XicNdf, + full::MassV0Ndf, full::MassCascNdf, + full::V0Chi2OverNdf, full::CascChi2OverNdf, full::XicChi2OverNdf, + full::MassV0Chi2OverNdf, full::MassCascChi2OverNdf, + full::ResultSelections, + full::FlagMcMatchRec, full::DebugMcRec, full::OriginRec, full::CollisionMatched); + +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorToXiPiQa { + + Produces rowCandidateFull; + Produces rowCandidateLite; + Produces rowKfCandidate; + Produces rowEv; + + Configurable zPvCut{"zPvCut", 10., "Cut on absolute value of primary vertex z coordinate"}; + + using MyTrackTable = soa::Join; + using MyEventTable = soa::Join; + using MyEventTableWithFT0C = soa::Join; + using MyEventTableWithFT0M = soa::Join; + using MyEventTableWithNTracksPV = soa::Join; + + void init(InitContext const&) + { + if ((doprocessMcLiteXic0 && doprocessMcLiteOmegac0) || (doprocessMcFullXic0 && doprocessMcFullOmegac0)) { + LOGF(fatal, "Both Xic0 and Omegac0 MC processes enabled, please choose ONLY one!"); + } + } + + ////////////////////////////////////////////////////// + // // + // Fill functions to fill in the tables // + // // + ////////////////////////////////////////////////////// + + template + void fillEvent(const T& collision, float cutZPv) + { + rowEv(collision.sel8(), std::abs(collision.posZ()) < cutZPv); + } + + template + void fillCandidate(const T& candidate, int8_t flagMc, int8_t debugMc, int8_t originMc, bool collisionMatched) + { + // save all candidate information + float centrality = -999.f; + if constexpr (useCentrality) { + const auto& collision = candidate.template collision_as(); + centrality = o2::hf_centrality::getCentralityColl(collision); + } + + if constexpr (svReco == DCAFITTER) { + if constexpr (tableSize == LITE) { + rowCandidateLite(candidate.xPv(), + candidate.yPv(), + candidate.zPv(), + centrality, + candidate.template collision_as().numContrib(), + candidate.template collision_as().chi2(), + candidate.xDecayVtxCharmBaryon(), + candidate.yDecayVtxCharmBaryon(), + candidate.zDecayVtxCharmBaryon(), + candidate.xDecayVtxCascade(), + candidate.yDecayVtxCascade(), + candidate.zDecayVtxCascade(), + candidate.xDecayVtxV0(), + candidate.yDecayVtxV0(), + candidate.zDecayVtxV0(), + candidate.signDecay(), + RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + candidate.pxCharmBaryon(), + candidate.pyCharmBaryon(), + candidate.pzCharmBaryon(), + candidate.pxBachFromCharmBaryon(), + candidate.pyBachFromCharmBaryon(), + candidate.pzBachFromCharmBaryon(), + candidate.pxBachFromCasc(), + candidate.pyBachFromCasc(), + candidate.pzBachFromCasc(), + candidate.pxPosV0Dau(), + candidate.pyPosV0Dau(), + candidate.pzPosV0Dau(), + candidate.pxNegV0Dau(), + candidate.pyNegV0Dau(), + candidate.pzNegV0Dau(), + candidate.impactParCascXY(), + candidate.impactParBachFromCharmBaryonXY(), + candidate.errImpactParCascXY(), + candidate.errImpactParBachFromCharmBaryonXY(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.cosPAV0(), + candidate.cosPACharmBaryon(), + candidate.cosPACasc(), + candidate.etaV0PosDau(), + candidate.etaV0NegDau(), + candidate.etaBachFromCasc(), + candidate.etaBachFromCharmBaryon(), + candidate.etaCharmBaryon(), + candidate.dcaXYToPvV0Dau0(), + candidate.dcaXYToPvV0Dau1(), + candidate.dcaXYToPvCascDau(), + candidate.dcaCascDau(), + candidate.dcaV0Dau(), + candidate.dcaCharmBaryonDau(), + candidate.errorDecayLengthCharmBaryon(), + candidate.impactParCascXY() / candidate.errImpactParCascXY(), + candidate.impactParBachFromCharmBaryonXY() / candidate.errImpactParBachFromCharmBaryonXY(), + candidate.template bachelorFromCharmBaryon_as().isGlobalTrackWoDCA(), + candidate.template bachelorFromCharmBaryon_as().itsNCls(), + candidate.template bachelorFromCharmBaryon_as().tpcNClsCrossedRows(), + candidate.template bachelor_as().tpcNClsCrossedRows(), + candidate.template posTrack_as().tpcNClsCrossedRows(), + candidate.template negTrack_as().tpcNClsCrossedRows(), + candidate.pidTpcInfoStored(), + candidate.pidTofInfoStored(), + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaPiFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCasc(), + candidate.tofNSigmaPiFromLambda(), + candidate.tofNSigmaPrFromLambda(), + flagMc, + originMc, + collisionMatched); + } else { + rowCandidateFull(candidate.xPv(), + candidate.yPv(), + candidate.zPv(), + centrality, + candidate.template collision_as().numContrib(), + candidate.template collision_as().chi2(), + candidate.xDecayVtxCharmBaryon(), + candidate.yDecayVtxCharmBaryon(), + candidate.zDecayVtxCharmBaryon(), + candidate.xDecayVtxCascade(), + candidate.yDecayVtxCascade(), + candidate.zDecayVtxCascade(), + candidate.xDecayVtxV0(), + candidate.yDecayVtxV0(), + candidate.zDecayVtxV0(), + candidate.signDecay(), + candidate.covVtxCharmBaryon0(), + candidate.covVtxCharmBaryon3(), + candidate.covVtxCharmBaryon5(), + RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + RecoDecay::pt(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + candidate.pxCharmBaryon(), + candidate.pyCharmBaryon(), + candidate.pzCharmBaryon(), + candidate.pxCasc(), + candidate.pyCasc(), + candidate.pzCasc(), + candidate.pxBachFromCharmBaryon(), + candidate.pyBachFromCharmBaryon(), + candidate.pzBachFromCharmBaryon(), + candidate.pxLambda(), + candidate.pyLambda(), + candidate.pzLambda(), + candidate.pxBachFromCasc(), + candidate.pyBachFromCasc(), + candidate.pzBachFromCasc(), + candidate.pxPosV0Dau(), + candidate.pyPosV0Dau(), + candidate.pzPosV0Dau(), + candidate.pxNegV0Dau(), + candidate.pyNegV0Dau(), + candidate.pzNegV0Dau(), + candidate.impactParCascXY(), + candidate.impactParBachFromCharmBaryonXY(), + candidate.impactParCascZ(), + candidate.impactParBachFromCharmBaryonZ(), + candidate.errImpactParCascXY(), + candidate.errImpactParBachFromCharmBaryonXY(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.cosPAV0(), + candidate.cosPACharmBaryon(), + candidate.cosPACasc(), + candidate.cosPAXYV0(), + candidate.cosPAXYCharmBaryon(), + candidate.cosPAXYCasc(), + candidate.cTauOmegac(), + candidate.cTauCascade(), + candidate.cTauV0(), + candidate.cTauXic(), + candidate.etaV0PosDau(), + candidate.etaV0NegDau(), + candidate.etaBachFromCasc(), + candidate.etaBachFromCharmBaryon(), + candidate.etaCharmBaryon(), + candidate.etaCascade(), + candidate.etaV0(), + candidate.dcaXYToPvV0Dau0(), + candidate.dcaXYToPvV0Dau1(), + candidate.dcaXYToPvCascDau(), + candidate.dcaZToPvV0Dau0(), + candidate.dcaZToPvV0Dau1(), + candidate.dcaZToPvCascDau(), + candidate.dcaCascDau(), + candidate.dcaV0Dau(), + candidate.dcaCharmBaryonDau(), + candidate.decLenCharmBaryon(), + candidate.decLenCascade(), + candidate.decLenV0(), + candidate.errorDecayLengthCharmBaryon(), + candidate.errorDecayLengthXYCharmBaryon(), + candidate.impactParCascXY() / candidate.errImpactParCascXY(), + candidate.impactParBachFromCharmBaryonXY() / candidate.errImpactParBachFromCharmBaryonXY(), + candidate.decLenCharmBaryon() / candidate.errorDecayLengthCharmBaryon(), + candidate.template bachelorFromCharmBaryon_as().isGlobalTrackWoDCA(), + candidate.template bachelorFromCharmBaryon_as().itsNCls(), + candidate.template bachelorFromCharmBaryon_as().tpcNClsCrossedRows(), + candidate.template bachelor_as().tpcNClsCrossedRows(), + candidate.template posTrack_as().tpcNClsCrossedRows(), + candidate.template negTrack_as().tpcNClsCrossedRows(), + candidate.statusPidLambda(), + candidate.statusPidCascade(), + candidate.statusPidCharmBaryon(), + candidate.statusInvMassLambda(), + candidate.statusInvMassCascade(), + candidate.statusInvMassCharmBaryon(), + candidate.resultSelections(), + candidate.pidTpcInfoStored(), + candidate.pidTofInfoStored(), + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaPiFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCasc(), + candidate.tofNSigmaPiFromLambda(), + candidate.tofNSigmaPrFromLambda(), + flagMc, + debugMc, + originMc, + collisionMatched); + } + } else { + if constexpr (tableSize == LITE) { + // currently, no lite sized table for KFParticle + } else { + rowKfCandidate(centrality, + candidate.tpcNSigmaPiFromCharmBaryon(), + candidate.tofNSigmaPiFromCharmBaryon(), + candidate.tpcNSigmaPiFromCasc(), + candidate.tofNSigmaPiFromCasc(), + candidate.tpcNSigmaPiFromLambda(), + candidate.tofNSigmaPiFromLambda(), + candidate.tpcNSigmaPrFromLambda(), + candidate.tofNSigmaPrFromLambda(), + candidate.kfDcaXYPiFromXic(), + candidate.dcaCascDau(), + candidate.dcaV0Dau(), + candidate.dcaCharmBaryonDau(), + candidate.kfDcaXYCascToPv(), + candidate.dcaXYToPvV0Dau0(), + candidate.dcaXYToPvV0Dau1(), + candidate.dcaXYToPvCascDau(), + candidate.chi2GeoV0(), + candidate.chi2GeoCasc(), + candidate.chi2GeoXic(), + candidate.chi2MassV0(), + candidate.chi2MassCasc(), + candidate.v0ldl(), + candidate.cascldl(), + candidate.chi2TopoV0ToPv(), + candidate.chi2TopoCascToPv(), + candidate.chi2TopoPiFromXicToPv(), + candidate.chi2TopoXicToPv(), + candidate.chi2TopoV0ToCasc(), + candidate.chi2TopoCascToXic(), + candidate.decayLenXYLambda(), + candidate.decayLenXYCasc(), + candidate.decayLenXYXic(), + candidate.cosPaV0ToCasc(), + candidate.cosPAV0(), + candidate.cosPaCascToXic(), + candidate.cosPACasc(), + candidate.invMassLambda(), + candidate.invMassCascade(), + candidate.invMassCharmBaryon(), + candidate.kfRapXic(), + RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), + candidate.cosThetaStarPiFromXic(), + candidate.cTauXic(), + candidate.etaCharmBaryon(), + candidate.v0Ndf(), + candidate.cascNdf(), + candidate.xicNdf(), + candidate.massV0Ndf(), + candidate.massCascNdf(), + candidate.v0Chi2OverNdf(), + candidate.cascChi2OverNdf(), + candidate.xicChi2OverNdf(), + candidate.massV0Chi2OverNdf(), + candidate.massCascChi2OverNdf(), + candidate.resultSelections(), + flagMc, + debugMc, + originMc, + collisionMatched); + } + } + } + + //////////////////////////////////// + // // + // Process functions // + // // + //////////////////////////////////// + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~Data with DCAFitter~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + + void processDataFull(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 + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLite(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) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLiteWithFT0M(MyEventTableWithFT0M 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) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLiteWithFT0C(MyEventTableWithFT0C 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) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processDataLiteWithNTracksPV(MyEventTableWithNTracksPV 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) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataFull, "Process data with full information w/o centrality", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLite, "Process data and produce lite table version", true); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLiteWithFT0M, "Process data and produce lite table version with FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLiteWithFT0C, "Process data and produce lite table version with FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processDataLiteWithNTracksPV, "Process data and produce lite table version with NTracksPV", false); + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~Data with KFParticle~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + void processKfData(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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processKfDataWithFT0M(MyEventTableWithFT0M 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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processKfDataWithFT0C(MyEventTableWithFT0C 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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + void processKfDataWithNTracksPV(MyEventTableWithNTracksPV 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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, -7, -7, RecoDecay::OriginType::None, false); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfData, "Process KF data, no cent", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfDataWithFT0M, "Process KF data, with FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfDataWithFT0C, "Process KF data, with FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfDataWithNTracksPV, "Process KF data, with NTracksPV", false); + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~MC with DCAFitter~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + + void processMcFullXic0(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 + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcFullOmegac0(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 + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0(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) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0WithFT0C(MyEventTableWithFT0C 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) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0WithFT0M(MyEventTableWithFT0M 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) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteXic0WithNTracksPV(MyEventTableWithNTracksPV 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) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processMcLiteOmegac0(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) { + fillCandidate(candidate, candidate.flagMcMatchRec(), -7, candidate.originMcRec(), candidate.collisionMatched()); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcFullXic0, "Process MC with full information for xic0 w/o centrality", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcFullOmegac0, "Process MC with full information for omegac0", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0, "Process MC and produce lite table version for xic0", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0WithFT0C, "Process MC and produce lite table version for Xic0 with FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0WithFT0M, "Process MC and produce lite table version for Xic0 with FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteXic0WithNTracksPV, "Process MC and produce lite table version for Xic0 with NTracksPV", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processMcLiteOmegac0, "Process MC and produce lite table version for omegac0", false); + + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + //*~~~~~~~MC with KFParticle~~~~~~~~*// + //*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*// + void processKfMcXic0(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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processKfMcXic0WithFT0C(MyEventTableWithFT0C 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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processKfMcXic0WithFT0M(MyEventTableWithFT0M 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 + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + void processKfMcXic0WithNTracksPV(MyEventTableWithNTracksPV 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 table + rowKfCandidate.reserve(candidates.size()); + for (const auto& candidate : candidates) { + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); + } + } + + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0, "Process MC with information for xic0", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0WithFT0C, "Process MC with information for xic0 at FT0C", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0WithFT0M, "Process MC with information for xic0 at FT0M", false); + PROCESS_SWITCH(HfTreeCreatorToXiPiQa, processKfMcXic0WithNTracksPV, "Process MC with information for xic0 at Ntrack", false); +}; // end of struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx index 81543b0e7bf..8cdba2fe442 100644 --- a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx @@ -239,13 +239,13 @@ struct HfTreeCreatorXicToPKPi { using CandXicMcGen = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic; - Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Filter filterMcGenMatching = nabs(o2::aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); Partition selectedXicToPKPiCand = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic; Partition selectedXicToPiKPCand = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic; - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); - Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Partition reconstructedCandSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); + Partition reconstructedCandBkg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi); void init(InitContext const&) { diff --git a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx index 3d0500c3690..a21218a5eed 100644 --- a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx @@ -44,7 +44,7 @@ namespace o2::aod { namespace full { -DECLARE_SOA_COLUMN(ParticleFlag, particleFlag, int8_t); //! hf_cand_xic_to_xi_pi_pi::Sign for data, hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec for MC +DECLARE_SOA_COLUMN(ParticleFlag, particleFlag, int8_t); //! hf_cand_xic_to_xi_pi_pi::Sign for data, hf_cand_mc_flag::FlagMcMatchRec for MC DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) // vertices DECLARE_SOA_COLUMN(Chi2SV, chi2SV, float); //! Chi2 of candidate vertex @@ -78,11 +78,14 @@ DECLARE_SOA_COLUMN(PtPi1, ptPi1, float); 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(MlScoreBkg, mlScoreBkg, float); //! ML score for background class +DECLARE_SOA_COLUMN(MlScorePrompt, mlScorePrompt, float); //! ML score for prompt signal class +DECLARE_SOA_COLUMN(MlScoreNonPrompt, mlScoreNonPrompt, float); //! ML score for non-prompt signal class (3-class model only, -1 otherwise) } // namespace full DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -119,7 +122,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -186,9 +189,40 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); +DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteMLs, "AOD", "HFXICXI2PIMLITE", + full::ParticleFlag, + hf_cand_mc_flag::OriginMcRec, + full::CandidateSelFlag, + full::Y, + full::Eta, + full::Phi, + full::P, + full::Pt, + full::M, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + full::DecayLength, + full::DecayLengthXY, + full::Cpa, + full::CpaXY, + hf_cand_xic_to_xi_pi_pi::CpaXi, + hf_cand_xic_to_xi_pi_pi::CpaXYXi, + hf_cand_xic_to_xi_pi_pi::CpaLambda, + hf_cand_xic_to_xi_pi_pi::CpaXYLambda, + full::ImpactParameterXi, + full::ImpactParameterNormalisedXi, + full::ImpactParameterPi0, + full::ImpactParameterNormalisedPi0, + full::ImpactParameterPi1, + full::ImpactParameterNormalisedPi1, + full::MaxNormalisedDeltaIP, + full::MlScoreBkg, + full::MlScorePrompt, + full::MlScoreNonPrompt); + DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -250,7 +284,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::ParticleFlag, - hf_cand_xic_to_xi_pi_pi::OriginMcRec, + hf_cand_mc_flag::OriginMcRec, full::CandidateSelFlag, full::Y, full::Eta, @@ -329,9 +363,9 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullPs, "AOD", "HFXICXI2PIFULLP", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, - hf_cand_xic_to_xi_pi_pi::OriginMcGen, - hf_cand::PdgBhadMotherPart, + hf_cand_mc_flag::FlagMcMatchGen, + hf_cand_mc_flag::OriginMcGen, + hf_cand_mc_flag::PdgBhadMotherPart, full::Pt, full::Eta, full::Phi, @@ -343,6 +377,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullPs, "AOD", "HFXICXI2PIFULLP", struct HfTreeCreatorXicToXiPiPi { Produces rowCandidateLite; Produces rowCandidateLiteKf; + Produces rowCandidateLiteMl; Produces rowCandidateFull; Produces rowCandidateFullKf; Produces rowCandidateFullParticles; @@ -356,25 +391,33 @@ struct HfTreeCreatorXicToXiPiPi { 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"}; + static constexpr int kNumBinaryClasses = 2; + using SelectedCandidates = soa::Filtered>; using SelectedCandidatesKf = soa::Filtered>; + using SelectedCandidatesML = soa::Filtered>; using SelectedCandidatesMc = soa::Filtered>; using SelectedCandidatesKfMc = soa::Filtered>; + using SelectedCandidatesMcML = soa::Filtered>; using MatchedGenXicToXiPiPi = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic; - Filter filterGenXicToXiPiPi = (nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi)) || nabs(aod::hf_cand_xic_to_xi_pi_pi::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi))); + Filter filterGenXicToXiPiPi = (nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi)) || nabs(aod::hf_cand_mc_flag::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi))); - 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); + Partition recSig = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != int8_t(0); + Partition recBg = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == int8_t(0); + Partition recSigKf = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) != int8_t(0); + Partition recBgKf = nabs(aod::hf_cand_mc_flag::flagMcMatchRec) == int8_t(0); void init(InitContext const&) { + std::array doprocess{doprocessData, doprocessDataKf, doprocessDataWithML, doprocessMc, doprocessMcKf, doprocessMcWithML}; + if (std::accumulate(doprocess.begin(), doprocess.end(), 0) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } } - template + template void fillCandidateTable(const T& candidate) { int8_t particleFlag = candidate.sign(); @@ -383,7 +426,7 @@ struct HfTreeCreatorXicToXiPiPi { particleFlag = candidate.flagMcMatchRec(); originMc = candidate.originMcRec(); } - if constexpr (!DoKf) { + if constexpr (!DoKf && !DoMl) { if (fillCandidateLiteTable) { rowCandidateLite( particleFlag, @@ -484,7 +527,7 @@ struct HfTreeCreatorXicToXiPiPi { candidate.nSigTofPiFromLambda(), candidate.nSigTofPrFromLambda()); } - } else { + } else if constexpr (DoKf) { if (fillCandidateLiteTable) { rowCandidateLiteKf( particleFlag, @@ -636,6 +679,47 @@ struct HfTreeCreatorXicToXiPiPi { candidate.dcaXYPi1Xi()); } } + if constexpr (DoMl) { + float mlScoreBkg = -1.f, mlScorePrompt = -1.f, mlScoreNonPrompt = -1.f; + const int scoreSize = static_cast(candidate.mlProbXicToXiPiPi().size()); + if (scoreSize > 0) { + mlScoreBkg = candidate.mlProbXicToXiPiPi()[0]; + mlScorePrompt = candidate.mlProbXicToXiPiPi()[1]; + if (scoreSize > kNumBinaryClasses) { + mlScoreNonPrompt = candidate.mlProbXicToXiPiPi()[2]; + } + } + rowCandidateLiteMl( + particleFlag, + originMc, + candidate.isSelXicToXiPiPi(), + candidate.y(o2::constants::physics::MassXiCPlus), + candidate.eta(), + candidate.phi(), + candidate.p(), + candidate.pt(), + candidate.invMassXicPlus(), + candidate.invMassXi(), + candidate.invMassLambda(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.cpa(), + candidate.cpaXY(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), + candidate.impactParameter0(), + candidate.impactParameterNormalised0(), + candidate.impactParameter1(), + candidate.impactParameterNormalised1(), + candidate.impactParameter2(), + candidate.impactParameterNormalised2(), + candidate.maxNormalisedDeltaIP(), + mlScoreBkg, + mlScorePrompt, + mlScoreNonPrompt); + } } void processData(SelectedCandidates const& candidates) @@ -653,10 +737,10 @@ struct HfTreeCreatorXicToXiPiPi { continue; } } - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } - PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processData, "Process data with DCAFitter reconstruction", true); + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processData, "Process data with DCAFitter reconstruction", false); void processDataKf(SelectedCandidatesKf const& candidates) { @@ -673,11 +757,22 @@ struct HfTreeCreatorXicToXiPiPi { continue; } } - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processDataKf, "Process data with KFParticle reconstruction", false); + void processDataWithML(SelectedCandidatesML const& candidates) + { + // Filling candidate properties + rowCandidateLiteMl.reserve(candidates.size()); + + for (const auto& candidate : candidates) { + fillCandidateTable(candidate); + } + } + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processDataWithML, "Process data with DCAFitter reconstruction and ML", false); + void processMc(SelectedCandidatesMc const& candidates, MatchedGenXicToXiPiPi const& particles) { @@ -689,7 +784,7 @@ struct HfTreeCreatorXicToXiPiPi { rowCandidateFull.reserve(recSig.size()); } for (const auto& candidate : recSig) { - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } else if (fillOnlyBackground) { if (fillCandidateLiteTable) { @@ -702,7 +797,7 @@ struct HfTreeCreatorXicToXiPiPi { if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { continue; } - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } else { if (fillCandidateLiteTable) { @@ -711,7 +806,7 @@ struct HfTreeCreatorXicToXiPiPi { rowCandidateFull.reserve(candidates.size()); } for (const auto& candidate : candidates) { - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } @@ -743,7 +838,7 @@ struct HfTreeCreatorXicToXiPiPi { rowCandidateFull.reserve(recSigKf.size()); } for (const auto& candidate : recSigKf) { - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } else if (fillOnlyBackground) { if (fillCandidateLiteTable) { @@ -756,7 +851,7 @@ struct HfTreeCreatorXicToXiPiPi { if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { continue; } - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } else { if (fillCandidateLiteTable) { @@ -765,7 +860,7 @@ struct HfTreeCreatorXicToXiPiPi { rowCandidateFull.reserve(candidates.size()); } for (const auto& candidate : candidates) { - fillCandidateTable(candidate); + fillCandidateTable(candidate); } } @@ -785,6 +880,52 @@ struct HfTreeCreatorXicToXiPiPi { } } PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processMcKf, "Process MC with KF Particle reconstruction", false); + + void processMcWithML(SelectedCandidatesMcML const& candidates, + MatchedGenXicToXiPiPi const& particles) + { + // Filling candidate properties + rowCandidateLiteMl.reserve(candidates.size()); + if (fillOnlySignal) { + for (const auto& candidate : candidates) { + if (candidate.flagMcMatchRec() == int8_t(0)) { + continue; + } + fillCandidateTable(candidate); + } + } else if (fillOnlyBackground) { + for (const auto& candidate : candidates) { + if (candidate.flagMcMatchRec() != int8_t(0)) { + continue; + } + float const pseudoRndm = candidate.ptProng1() * 1000. - static_cast(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + fillCandidateTable(candidate); + } + } else { + for (const auto& candidate : candidates) { + fillCandidateTable(candidate); + } + } + + if (fillGenParticleTable) { + rowCandidateFullParticles.reserve(particles.size()); + for (const auto& particle : particles) { + rowCandidateFullParticles( + particle.flagMcMatchGen(), + particle.originMcGen(), + particle.pdgBhadMotherPart(), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(particle.pVector(), o2::constants::physics::MassXiCPlus), + particle.decayLengthMcGen()); + } + } + } + PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processMcWithML, "Process MC with DCAFitter reconstruction and ML", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/Tasks/taskMcEfficiency.cxx b/PWGHF/Tasks/taskMcEfficiency.cxx index 5f706c7bede..dc9b708dfeb 100644 --- a/PWGHF/Tasks/taskMcEfficiency.cxx +++ b/PWGHF/Tasks/taskMcEfficiency.cxx @@ -69,7 +69,7 @@ struct HfTaskMcEfficiency { Configurable mcAcceptancePt{"mcAcceptancePt", 0.1, "MC Acceptance: lower pt limit"}; Configurable mcAcceptanceEta{"mcAcceptanceEta", 0.8, "MC Acceptance: upper eta limit"}; - Service pdg; + Service pdg{}; enum HFStep { kHFStepMC = 0, kHFStepMcInRapidity, // MC mothers in rapidity |y| < 0.5 diff --git a/PWGHF/Tasks/taskMcInjection.cxx b/PWGHF/Tasks/taskMcInjection.cxx index b0377cecc23..b649cf88851 100644 --- a/PWGHF/Tasks/taskMcInjection.cxx +++ b/PWGHF/Tasks/taskMcInjection.cxx @@ -142,19 +142,23 @@ struct HfTaskMcInjection { bool isCharm(int pdg) { - if (std::abs(pdg) / 1000 == PDG_t::kCharm) // o2-linter: disable=magic-number (get thousands digit) + if (std::abs(pdg) / 1000 == PDG_t::kCharm) { // o2-linter: disable=magic-number (get thousands digit) return true; - if (std::abs(pdg) / 100 == PDG_t::kCharm) // o2-linter: disable=magic-number (get hundreds digit) + } + if (std::abs(pdg) / 100 == PDG_t::kCharm) { // o2-linter: disable=magic-number (get hundreds digit) return true; + } return false; } bool isBeauty(int pdg) // if needed in the future { - if (std::abs(pdg) / 1000 == PDG_t::kBottom) // o2-linter: disable=magic-number (get thousands digit) + if (std::abs(pdg) / 1000 == PDG_t::kBottom) { // o2-linter: disable=magic-number (get thousands digit) return true; - if (std::abs(pdg) / 100 == PDG_t::kBottom) // o2-linter: disable=magic-number (get hundreds digit) + } + if (std::abs(pdg) / 100 == PDG_t::kBottom) { // o2-linter: disable=magic-number (get hundreds digit) return true; + } return false; } diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index 8f3c5164aa6..4cbb1100766 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -663,7 +663,7 @@ struct HfTaskMcValidationRec { Preslice cand2ProngPerCollision = aod::hf_cand::collisionId; Preslice cand3ProngPerCollision = aod::hf_cand::collisionId; - Service ccdb; + Service ccdb{}; HfEventSelection hfEvSel; // event selection and monitoring AxisSpec axisDeltaMom{2000, -1., 1.}; @@ -1105,7 +1105,7 @@ struct HfTaskMcValidationRec { if (std::abs(cand2Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { whichHad = DzeroToKPi; } - int whichOrigin; + int whichOrigin{}; if (cand2Prong.originMcRec() == RecoDecay::OriginType::Prompt) { whichOrigin = 0; } else { @@ -1153,7 +1153,7 @@ struct HfTaskMcValidationRec { } else if (isXicSel && std::abs(cand3Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi) { whichHad = XiCplusToPKPi; } - int whichOrigin; + int whichOrigin{}; if (cand3Prong.originMcRec() == RecoDecay::OriginType::Prompt) { whichOrigin = 0; } else { diff --git a/PWGHF/Tasks/taskPidStudies.cxx b/PWGHF/Tasks/taskPidStudies.cxx index e7115cd91d8..3c9bd0de808 100644 --- a/PWGHF/Tasks/taskPidStudies.cxx +++ b/PWGHF/Tasks/taskPidStudies.cxx @@ -22,6 +22,7 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/ZorroSummary.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" @@ -212,7 +213,7 @@ struct HfTaskPidStudies { HfEventSelectionMc hfEvSelMc; double interactionRate{-1.}; - o2::framework::Service ccdb; + o2::framework::Service ccdb{}; HistogramRegistry registry{"registry", {}}; OutputObj zorroSummary{"zorroSummary"}; diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index fcf4c389fe0..b3be162359d 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -30,8 +30,8 @@ #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" +#include +#include #include #include #include diff --git a/PWGHF/Utils/utilsPid.h b/PWGHF/Utils/utilsPid.h index fc1d0d18940..674315edc81 100644 --- a/PWGHF/Utils/utilsPid.h +++ b/PWGHF/Utils/utilsPid.h @@ -20,7 +20,11 @@ #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" +#include +#include +#include #include +#include #include @@ -32,6 +36,9 @@ enum HfProngSpecies : uint8_t { Kaon, Proton, Deuteron, + Triton, + Helium3, + Alpha, NHfProngSpecies }; @@ -43,6 +50,131 @@ enum PidMethod { NPidMethods }; +/// Compute TPC nσ for light nuclei (De/Tr/He3/Al) using a Bethe–Bloch parameter configuration (BB-based PID). +/// +/// \tparam TrackType Track/ASoA row type providing TPC accessors. +/// \param track Track to be tested. +/// \param species Species selector: 3=Deuteron, 4=Triton, 5=Helium3, 6=Alpha. +/// \param bbParams is Bethe–Bloch parameters +/// \return TPC nσ for the chosen nucleus hypothesis (or -999 if not applicable). +template +float getNSigmaTpcLightNucleiBetheBloch(const TrackType& track, + HfProngSpecies species, + const o2::framework::Configurable>& bbParams) +{ + constexpr float RetValNotApplicable = -999.f; + + if (!track.hasTPC()) { + return RetValNotApplicable; + } + const int row = static_cast(species) - static_cast(HfProngSpecies::Deuteron); + + if (row < 0 || row >= HfProngSpecies::NHfProngSpecies) { + return RetValNotApplicable; + } + + // Columns: [0..4] BB params, [5] relative resolution (sigma/mean) + + const double relRes = bbParams->get(row, 5u); + if (relRes <= 0.) { + return RetValNotApplicable; + } + + const double bb0 = bbParams->get(row, 0u); + const double bb1 = bbParams->get(row, 1u); + const double bb2 = bbParams->get(row, 2u); + const double bb3 = bbParams->get(row, 3u); + const double bb4 = bbParams->get(row, 4u); + + double mass = 0.; + switch (species) { + case HfProngSpecies::Deuteron: + mass = o2::constants::physics::MassDeuteron; + break; + case HfProngSpecies::Triton: + mass = o2::constants::physics::MassTriton; + break; + case HfProngSpecies::Helium3: + mass = o2::constants::physics::MassHelium3; + break; + case HfProngSpecies::Alpha: + mass = o2::constants::physics::MassAlpha; + break; + default: + LOG(fatal) << "Unhandled HfProngSpecies " << static_cast(species); + } + + const int charge = (species == HfProngSpecies::Helium3 || species == HfProngSpecies::Alpha) ? 2 : 1; + const float rigidity = track.tpcInnerParam(); // p/|q| + + const double x = static_cast(charge) * static_cast(rigidity) / mass; + const double expBethe = o2::common::BetheBlochAleph(x, bb0, bb1, bb2, bb3, bb4); + const double expSigma = expBethe * relRes; + + if (expSigma <= 0.) { + return RetValNotApplicable; + } + + return static_cast((track.tpcSignal() - expBethe) / expSigma); +} + +/// \brief Function to fill tables with HF prong PID information +/// \tparam specPid particle species +/// \tparam TTrack datatype of the prong track +/// \tparam TCursor datatype of the cursor of the prong PID table to fill +/// \param track prong track +/// \param bbParams is Bethe–Bloch parameters (only for light nuclei) +/// \param rowPid cursor of the prong PID table to fill +template +void fillProngPidLightNuclei(TTrack const& track, + TCursor& rowPid, + const o2::framework::Configurable>& bbParams) +{ + + // get PID information for the daughter tracks + // TODO: add here the code for a possible PID post-calibrations in MC + float nSigTpc = -999.f; + float nSigTof = -999.f; + if constexpr (SpecPid == HfProngSpecies::Deuteron) { + // deuteron PID + if (track.hasTPC()) { + nSigTpc = getNSigmaTpcLightNucleiBetheBloch(track, SpecPid, bbParams); + } + if (track.hasTOF()) { + nSigTof = track.tofNSigmaDe(); + } + } else if constexpr (SpecPid == HfProngSpecies::Triton) { + // triton PID + if (track.hasTPC()) { + nSigTpc = getNSigmaTpcLightNucleiBetheBloch(track, SpecPid, bbParams); + } + if (track.hasTOF()) { + nSigTof = track.tofNSigmaTr(); + } + } else if constexpr (SpecPid == HfProngSpecies::Helium3) { + // helium3 PID + if (track.hasTPC()) { + nSigTpc = getNSigmaTpcLightNucleiBetheBloch(track, SpecPid, bbParams); + } + if (track.hasTOF()) { + nSigTof = track.tofNSigmaHe(); + } + } else if constexpr (SpecPid == HfProngSpecies::Alpha) { + // helium4 PID + if (track.hasTPC()) { + nSigTpc = getNSigmaTpcLightNucleiBetheBloch(track, SpecPid, bbParams); + } + if (track.hasTOF()) { + nSigTof = track.tofNSigmaAl(); + } + } else { + LOG(fatal) << "Unsupported PID. Supported species in HF framework: HfProngSpecies::Deuteron, HfProngSpecies::Triton, HfProngSpecies::Helium3, HfProngSpecies::Alpha"; + } + + // fill candidate prong PID rows + rowPid(nSigTpc, nSigTof); +} + /// Function to combine TPC and TOF nSigma /// \tparam Tiny switch between full and tiny (binned) PID tables /// \param nSigmaTpc is the (binned) nSigma separation in TPC (if Tiny = true) @@ -109,16 +241,8 @@ void fillProngPid(TTrack const& track, TCursor& rowPid) if (track.hasTOF()) { nSigTof = track.tofNSigmaPr(); } - } else if constexpr (SpecPid == HfProngSpecies::Deuteron) { - // deuteron PID - if (track.hasTPC()) { - nSigTpc = track.tpcNSigmaDe(); - } - if (track.hasTOF()) { - nSigTof = track.tofNSigmaDe(); - } } else { - LOG(fatal) << "Unsupported PID. Supported species in HF framework: HfProngSpecies::Pion, HfProngSpecies::Kaon, HfProngSpecies::Proton, HfProngSpecies::Deuteron"; + LOG(fatal) << "Unsupported PID. Supported species in HF framework: HfProngSpecies::Pion, HfProngSpecies::Kaon, HfProngSpecies::Proton"; } // fill candidate prong PID rows diff --git a/PWGHF/Utils/utilsUpcHf.h b/PWGHF/Utils/utilsUpcHf.h index a292d9d9e6b..f30d99b5598 100644 --- a/PWGHF/Utils/utilsUpcHf.h +++ b/PWGHF/Utils/utilsUpcHf.h @@ -13,6 +13,7 @@ /// \brief Utility functions for Ultra-Peripheral Collision (UPC) analysis in Heavy Flavor physics /// /// \author Minjung Kim , CERN +/// \author Ran Tu , Fudan University, GSI Darmstadt #ifndef PWGHF_UTILS_UTILSUPCHF_H_ #define PWGHF_UTILS_UTILSUPCHF_H_ @@ -32,28 +33,32 @@ namespace o2::analysis::hf_upc /// \brief Use TrueGap enum from SGSelector for gap type classification using o2::aod::sgselector::TrueGap; -/// \brief Configurable group for UPC gap determination thresholds -struct HfUpcGapThresholds : o2::framework::ConfigurableGroup { - std::string prefix = "upc"; // JSON group name - o2::framework::Configurable fv0aThreshold{"fv0aThreshold", 100.0f, "FV0-A amplitude threshold for UPC gap determination (a.u.)"}; - o2::framework::Configurable ft0aThreshold{"ft0aThreshold", 100.0f, "FT0-A amplitude threshold for UPC gap determination (a.u.)"}; - o2::framework::Configurable ft0cThreshold{"ft0cThreshold", 50.0f, "FT0-C amplitude threshold for UPC gap determination (a.u.)"}; - o2::framework::Configurable zdcThreshold{"zdcThreshold", 1.0f, "ZDC energy threshold for UPC gap determination (a.u.)"}; -}; - /// \brief Default thresholds for gap determination namespace defaults { constexpr float AmplitudeThresholdFV0A = 100.0f; ///< Amplitude threshold for FV0-A (a.u.) constexpr float AmplitudeThresholdFT0A = 100.0f; ///< Amplitude threshold for FT0-A (a.u.) constexpr float AmplitudeThresholdFT0C = 50.0f; ///< Amplitude threshold for FT0-C (a.u.) -constexpr float MaxFITTime = 4.0f; ///< Maximum FIT time (ns) -constexpr int NDtColl = 1000; ///< Time window for BC range (ns) -constexpr int MinNBCs = 7; ///< Minimum number of BCs to check -constexpr int MinNTracks = 0; ///< Minimum number of tracks -constexpr int MaxNTracks = 100; ///< Maximum number of tracks +constexpr float MaxFITTime = 34.0f; ///< Maximum FIT time (ns) +constexpr int NDtColl = 1; ///< Time window for BC range (ns) +constexpr int MinNBCs = 2; ///< Minimum number of BCs to check +constexpr int MinNTracks = 2; ///< Minimum number of tracks +constexpr int MaxNTracks = 1000; ///< Maximum number of tracks } // namespace defaults +/// \brief Configurable group for UPC gap determination thresholds +struct HfUpcGapThresholds : o2::framework::ConfigurableGroup { + std::string prefix = "upc"; // JSON group name + o2::framework::Configurable nDtColl{"nDtColl", static_cast(defaults::NDtColl), "Number of standard deviations to consider in BC range"}; + o2::framework::Configurable nBcsMin{"nBcsMin", static_cast(defaults::MinNBCs), "Minimum number of BCs to consider in BC range"}; + o2::framework::Configurable nContributorsPvMin{"nContributorsPvMin", static_cast(defaults::MinNTracks), "Minimum number of PV contributors"}; + o2::framework::Configurable nContributorsPvMax{"nContributorsPvMax", static_cast(defaults::MaxNTracks), "Maximum number of PV contributors"}; + o2::framework::Configurable timeFitMax{"timeFitMax", static_cast(defaults::MaxFITTime), "Maximum time in FIT"}; + o2::framework::Configurable fv0aThreshold{"fv0aThreshold", static_cast(defaults::AmplitudeThresholdFV0A), "FV0-A amplitude threshold for UPC gap determination (a.u.)"}; + o2::framework::Configurable ft0aThreshold{"ft0aThreshold", static_cast(defaults::AmplitudeThresholdFT0A), "FT0-A amplitude threshold for UPC gap determination (a.u.)"}; + o2::framework::Configurable ft0cThreshold{"ft0cThreshold", static_cast(defaults::AmplitudeThresholdFT0C), "FT0-C amplitude threshold for UPC gap determination (a.u.)"}; +}; + /// \brief Determine gap type using SGSelector with BC range checking /// \tparam TCollision Collision type /// \tparam TBCs BC table type @@ -66,19 +71,26 @@ constexpr int MaxNTracks = 100; ///< Maximum number of tracks template inline auto determineGapType(TCollision const& collision, TBCs const& bcs, + int nDtColl = defaults::NDtColl, + int nBcsMin = defaults::MinNBCs, + int nContributorsPvMin = defaults::MinNTracks, + int nContributorsPvMax = defaults::MaxNTracks, + float timeFitMax = defaults::MaxFITTime, float amplitudeThresholdFV0A = defaults::AmplitudeThresholdFV0A, float amplitudeThresholdFT0A = defaults::AmplitudeThresholdFT0A, float amplitudeThresholdFT0C = defaults::AmplitudeThresholdFT0C) { using BCType = std::decay_t())>; + const float amplitudeThresholdsFDDA = -1.0f; // Not used in SGSelector, set to -1 to indicate unused + const float amplitudeThresholdsFDDC = -1.0f; // Not used in SGSelector, set to -1 to indicate unused // Configure SGSelector thresholds SGCutParHolder sgCuts; - sgCuts.SetNDtcoll(defaults::NDtColl); - sgCuts.SetMinNBCs(defaults::MinNBCs); - sgCuts.SetNTracks(defaults::MinNTracks, defaults::MaxNTracks); - sgCuts.SetMaxFITtime(defaults::MaxFITTime); - sgCuts.SetFITAmpLimits({amplitudeThresholdFV0A, amplitudeThresholdFT0A, amplitudeThresholdFT0C}); + sgCuts.SetNDtcoll(nDtColl); + sgCuts.SetMinNBCs(nBcsMin); + sgCuts.SetNTracks(nContributorsPvMin, nContributorsPvMax); + sgCuts.SetMaxFITtime(timeFitMax); + sgCuts.SetFITAmpLimits({amplitudeThresholdFV0A, amplitudeThresholdFT0A, amplitudeThresholdFT0C, amplitudeThresholdsFDDA, amplitudeThresholdsFDDC}); // Get BC and BC range if (!collision.has_foundBC()) { @@ -108,6 +120,11 @@ inline auto determineGapType(TCollision const& collision, HfUpcGapThresholds const& thresholds) { return determineGapType(collision, bcs, + thresholds.nDtColl.value, + thresholds.nBcsMin.value, + thresholds.nContributorsPvMin.value, + thresholds.nContributorsPvMax.value, + thresholds.timeFitMax.value, thresholds.fv0aThreshold.value, thresholds.ft0aThreshold.value, thresholds.ft0cThreshold.value); diff --git a/PWGJE/Core/FastJetUtilities.cxx b/PWGJE/Core/FastJetUtilities.cxx index ca5956a1554..761978218b0 100644 --- a/PWGJE/Core/FastJetUtilities.cxx +++ b/PWGJE/Core/FastJetUtilities.cxx @@ -15,19 +15,19 @@ #include -void fastjetutilities::setFastJetUserInfo(std::vector& constituents, int index, int status) +void fastjetutilities::setFastJetUserInfo(std::vector& constituents, int index, JetConstituentStatus status) { fastjet_user_info* user_info = new fastjet_user_info(status, index); // FIXME: can setting this as a pointer be avoided? constituents.back().set_user_info(user_info); - if (index != -99999999) { // FIXME: in principle needed for constituent subtraction, particularly when clusters are added to the subtraction. However since the HF particle is not subtracted then we dont need to check for it in this manner + if (index != invalidIndex) { // FIXME: in principle needed for constituent subtraction, particularly when clusters are added to the subtraction. However since the HF particle is not subtracted then we dont need to check for it in this manner int i = index; - if (status == static_cast(JetConstituentStatus::track)) { + if (status == JetConstituentStatus::track) { i = i + 1; } - if (status == static_cast(JetConstituentStatus::cluster)) { + if (status == JetConstituentStatus::cluster) { i = -1 * (i + 1); } - if (status == static_cast(JetConstituentStatus::candidate)) { + if (status == 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 4f5f7295fb3..506036c222f 100644 --- a/PWGJE/Core/FastJetUtilities.h +++ b/PWGJE/Core/FastJetUtilities.h @@ -24,7 +24,10 @@ #include #include +constexpr int invalidIndex = -99999999; + enum class JetConstituentStatus { + invalidStatus = -1, track = 0, cluster = 1, candidate = 2 @@ -36,24 +39,24 @@ namespace fastjetutilities // Class defined to store additional info which is passed to the FastJet object class fastjet_user_info : public fastjet::PseudoJet::UserInfoBase { - int status; // the status of each particle (Options are: TrueParticle (final state particles in generator event which arent special), HFParticle (heavy-flavour particle of interest in generator event), ThermalParticle (particles belonging to the thermal backgound), DecaySisterParticle (other particles poduced in the decay resulting in a non-prompt heavy-flavour particle of interest)) - int index; // a number unique to each particle in the event + JetConstituentStatus status; // the status of each particle (Options are: TrueParticle (final state particles in generator event which arent special), HFParticle (heavy-flavour particle of interest in generator event), ThermalParticle (particles belonging to the thermal backgound), DecaySisterParticle (other particles poduced in the decay resulting in a non-prompt heavy-flavour particle of interest)) + int index; // a number unique to each particle in the event public: fastjet_user_info() { - status = -9; + status = JetConstituentStatus::invalidStatus; index = -9; } - fastjet_user_info(int _status, int _index) + fastjet_user_info(JetConstituentStatus _status, int _index) { status = _status; index = _index; } ~fastjet_user_info() = default; - void setStatus(int set) { status = set; } + void setStatus(JetConstituentStatus set) { status = set; } void setIndex(int set) { index = set; } - int getStatus() const { return status; } + JetConstituentStatus getStatus() const { return status; } int getIndex() const { return index; } }; @@ -65,7 +68,7 @@ class fastjet_user_info : public fastjet::PseudoJet::UserInfoBase * @param status status of constituent type */ -void setFastJetUserInfo(std::vector& constituents, int index = -99999999, int status = static_cast(JetConstituentStatus::track)); +void setFastJetUserInfo(std::vector& constituents, int index = invalidIndex, JetConstituentStatus status = JetConstituentStatus::track); /** * Add track as a pseudojet object to the fastjet vector @@ -78,9 +81,9 @@ 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 = o2::constants::physics::MassPiPlus) +void fillTracks(const T& constituent, std::vector& constituents, int index = invalidIndex, JetConstituentStatus status = JetConstituentStatus::track, float mass = o2::constants::physics::MassPiPlus) { - if (status == static_cast(JetConstituentStatus::track) || status == static_cast(JetConstituentStatus::candidate)) { + if (status == JetConstituentStatus::track || status == 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); @@ -98,9 +101,9 @@ void fillTracks(const T& constituent, std::vector& constitue */ template -void fillClusters(const T& constituent, std::vector& constituents, int index = -99999999, int hadronicCorrectionType = 0, int status = static_cast(JetConstituentStatus::cluster)) +void fillClusters(const T& constituent, std::vector& constituents, int index = invalidIndex, int hadronicCorrectionType = 0, JetConstituentStatus status = JetConstituentStatus::cluster) { - if (status == static_cast(JetConstituentStatus::cluster)) { + if (status == JetConstituentStatus::cluster) { float constituentEnergy = 0.0; if (hadronicCorrectionType == 0) { constituentEnergy = constituent.energy(); diff --git a/PWGJE/Core/JetBkgSubUtils.cxx b/PWGJE/Core/JetBkgSubUtils.cxx index baa8e65d727..91254ddf7a8 100644 --- a/PWGJE/Core/JetBkgSubUtils.cxx +++ b/PWGJE/Core/JetBkgSubUtils.cxx @@ -15,8 +15,6 @@ #include "PWGJE/Core/JetBkgSubUtils.h" -#include "Common/Core/RecoDecay.h" - #include #include @@ -28,6 +26,8 @@ #include #include +#include +#include #include #include @@ -51,7 +51,7 @@ void JetBkgSubUtils::initialise() // Note: recommended to use R=0.2 jetDefBkg = fastjet::JetDefinition(algorithmBkg, jetBkgR, recombSchemeBkg, fastjet::Best); areaDefBkg = fastjet::AreaDefinition(fastjet::active_area_explicit_ghosts, ghostAreaSpec); - selRho = fastjet::SelectorRapRange(bkgEtaMin, bkgEtaMax) && fastjet::SelectorPhiRange(bkgPhiMin, bkgPhiMax) && !fastjet::SelectorNHardest(nHardReject); // here we have to put rap range, to be checked! + selRho = fastjet::SelectorEtaRange(bkgEtaMin + jetBkgR, bkgEtaMax - jetBkgR) && fastjet::SelectorPhiRange(bkgPhiMin, bkgPhiMax) && !fastjet::SelectorNHardest(nHardReject); // here we have to put rap range, to be checked! } std::tuple JetBkgSubUtils::estimateRhoAreaMedian(const std::vector& inputParticles, bool doSparseSub) @@ -75,6 +75,9 @@ std::tuple JetBkgSubUtils::estimateRhoAreaMedian(const std::vect // Fill a vector for pT/area to be used for the median for (auto& ijet : alljets) { + if (ijet.area() <= 0.0) { + continue; + } // Physical area/ Physical jets (no ghost) if (!clusterSeq.is_pure_ghost(ijet)) { rhovector.push_back(ijet.perp() / ijet.area()); @@ -122,14 +125,14 @@ std::vector JetBkgSubUtils::doEventConstSub(std::vector JetBkgSubUtils::doJetConstSub(std::vector& jets, double rhoParam, double rhoMParam) @@ -146,7 +149,7 @@ std::vector JetBkgSubUtils::doJetConstSub(std::vector auto matchedParticle(const T& candidate, const U& tracks, const V& particles) { if constexpr (jethfutilities::isHFCandidate()) { - return jethfutilities::matchedHFParticle(candidate, tracks, particles); + bool isMatched = false; + return jethfutilities::matchedHFParticle(candidate, tracks, particles, isMatched); } 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 + bool isMatched = false; + return jethfutilities::matchedHFParticle(candidate, tracks, particles, isMatched); // this is a dummy output which should never be triggered } } diff --git a/PWGJE/Core/JetDerivedDataUtilities.h b/PWGJE/Core/JetDerivedDataUtilities.h index c7299aab2d0..113e240bc2b 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 "PWGJE/DataModel/EMCALClusters.h" #include "PWGUD/Core/SGSelector.h" #include "Common/CCDB/EventSelectionParams.h" @@ -50,9 +51,9 @@ enum JCollisionSel { selIsGoodZvtxFT0vsPV = 7, selNoCollInTimeRangeStandard = 8, selNoCollInRofStandard = 9, - selUpcSingleGapA = 10, - selUpcSingleGapC = 11, - selUpcDoubleGap = 12, + selUPCSingleGapA = 10, + selUPCSingleGapC = 11, + selUPCDoubleGap = 12, }; enum JCollisionSubGeneratorId { @@ -61,8 +62,9 @@ enum JCollisionSubGeneratorId { }; template -bool commonCollisionSelection(T const& collision, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) +bool selectCollision(T const& collision, const std::vector& eventSelectionMaskBits, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) { + if (skipMBGapEvents && collision.getSubGeneratorId() == JCollisionSubGeneratorId::mbGap) { return false; } @@ -71,39 +73,34 @@ bool commonCollisionSelection(T const& collision, bool skipMBGapEvents = true, b if (rctSelection && !rctChecker.checkTable(collision)) { // CBT_hadronPID given as default so that TOF is included in RCT selection to benefit from better timing for tracks. Impact of this for inclusive jets should be studied return false; } - return true; -} - -template -bool selectMcCollision(T const& mcCollision, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) -{ - return commonCollisionSelection(mcCollision, skipMBGapEvents, rctSelection, rctLabel, rejectLimitedAcceptanceRct, requireZDCRct); -} - -template -bool selectCollision(T const& collision, const std::vector& eventSelectionMaskBits, bool skipMBGapEvents = true, bool rctSelection = true, std::string rctLabel = "CBT_hadronPID", bool rejectLimitedAcceptanceRct = false, bool requireZDCRct = false) -{ - - if (!commonCollisionSelection(collision, skipMBGapEvents, rctSelection, rctLabel, rejectLimitedAcceptanceRct, requireZDCRct)) { - return false; - } if (eventSelectionMaskBits.size() == 0) { return true; } + bool isOrCondition = false; for (auto eventSelectionMaskBit : eventSelectionMaskBits) { - if (!(collision.eventSel() & (1 << eventSelectionMaskBit))) { - return false; + if (eventSelectionMaskBit == -1) { + isOrCondition = true; + continue; + } + if (!isOrCondition) { + if (!(collision.eventSel() & (1ULL << eventSelectionMaskBit))) { + return false; + } + } else { + if (collision.eventSel() & (1ULL << eventSelectionMaskBit)) { + return true; + } } } - return true; + return !isOrCondition; } bool eventSelectionMasksContainSelection(const std::string& eventSelectionMasks, std::string selection) { size_t position = 0; while ((position = eventSelectionMasks.find(selection, position)) != std::string::npos) { - bool validStart = (position == 0 || eventSelectionMasks[position - 1] == '+'); - bool validEnd = (position + selection.length() == eventSelectionMasks.length() || eventSelectionMasks[position + selection.length()] == '+'); + bool validStart = (position == 0 || eventSelectionMasks[position - 1] == '+' || eventSelectionMasks[position - 1] == '|'); + bool validEnd = (position + selection.length() == eventSelectionMasks.length() || eventSelectionMasks[position + selection.length()] == '+' || eventSelectionMasks[position + selection.length()] == '|'); if (validStart && validEnd) { return true; } @@ -115,6 +112,9 @@ bool eventSelectionMasksContainSelection(const std::string& eventSelectionMasks, std::vector initialiseEventSelectionBits(const std::string& eventSelectionMasks) { std::vector eventSelectionMaskBits; + if (eventSelectionMasks.find('|') != std::string::npos) { // needs to be first if statement evaluated + eventSelectionMaskBits.push_back(-1); + } if (eventSelectionMasksContainSelection(eventSelectionMasks, "sel8")) { eventSelectionMaskBits.push_back(JCollisionSel::sel8); } @@ -177,13 +177,13 @@ std::vector initialiseEventSelectionBits(const std::string& eventSelectionM eventSelectionMaskBits.push_back(JCollisionSel::selKINT7); } if (eventSelectionMasksContainSelection(eventSelectionMasks, "selUPCSingleGapA")) { - eventSelectionMaskBits.push_back(JCollisionSel::selUpcSingleGapA); + eventSelectionMaskBits.push_back(JCollisionSel::selUPCSingleGapA); } if (eventSelectionMasksContainSelection(eventSelectionMasks, "selUPCSingleGapC")) { - eventSelectionMaskBits.push_back(JCollisionSel::selUpcSingleGapC); + eventSelectionMaskBits.push_back(JCollisionSel::selUPCSingleGapC); } if (eventSelectionMasksContainSelection(eventSelectionMasks, "selUPCDoubleGap")) { - eventSelectionMaskBits.push_back(JCollisionSel::selUpcDoubleGap); + eventSelectionMaskBits.push_back(JCollisionSel::selUPCDoubleGap); } return eventSelectionMaskBits; @@ -224,14 +224,37 @@ uint16_t setEventSelectionBit(T const& collision, int upcSelectionResult = o2::a SETBIT(bit, JCollisionSel::selNoCollInRofStandard); } if (upcSelectionResult == o2::aod::sgselector::SingleGapA) { - SETBIT(bit, JCollisionSel::selUpcSingleGapA); + SETBIT(bit, JCollisionSel::selUPCSingleGapA); } if (upcSelectionResult == o2::aod::sgselector::SingleGapC) { - SETBIT(bit, JCollisionSel::selUpcSingleGapC); + SETBIT(bit, JCollisionSel::selUPCSingleGapC); } if (upcSelectionResult == o2::aod::sgselector::DoubleGap) { - SETBIT(bit, JCollisionSel::selUpcDoubleGap); + SETBIT(bit, JCollisionSel::selUPCDoubleGap); + } + + return bit; +} + +template +uint16_t setMCEventSelectionBit(T const& bc) +{ + uint16_t bit = 0; + if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + SETBIT(bit, JCollisionSel::sel8); + SETBIT(bit, JCollisionSel::sel7); + SETBIT(bit, JCollisionSel::selKINT7); + SETBIT(bit, JCollisionSel::selTVX); } + SETBIT(bit, JCollisionSel::selNoTimeFrameBorder); + SETBIT(bit, JCollisionSel::selNoITSROFrameBorder); + SETBIT(bit, JCollisionSel::selNoSameBunchPileup); + SETBIT(bit, JCollisionSel::selIsGoodZvtxFT0vsPV); + SETBIT(bit, JCollisionSel::selNoCollInTimeRangeStandard); + SETBIT(bit, JCollisionSel::selNoCollInRofStandard); + SETBIT(bit, JCollisionSel::selUPCSingleGapA); + SETBIT(bit, JCollisionSel::selUPCSingleGapC); + SETBIT(bit, JCollisionSel::selUPCDoubleGap); return bit; } @@ -285,7 +308,7 @@ bool selectTrigger(T const& collision, const std::vector& triggerMaskBits) return true; } for (auto triggerMaskBit : triggerMaskBits) { - if (collision.triggerSel() & (1 << triggerMaskBit)) { + if (collision.triggerSel() & (1ULL << triggerMaskBit)) { return true; } } @@ -296,9 +319,9 @@ template bool selectTrigger(T const& collision, int triggerMaskBit) { if (triggerMaskBit == -1) { - return false; + return true; } - return collision.triggerSel() & (1 << triggerMaskBit); + return collision.triggerSel() & (1ULL << triggerMaskBit); } bool triggerMasksContainTrigger(const std::string& triggerMasks, std::string trigger) @@ -409,7 +432,7 @@ bool selectChargedTrigger(T const& collision, int triggerSelection) if (triggerSelection == -1) { return true; } - return (collision.chargedTriggerSel() & (1 << triggerSelection)); + return (collision.chargedTriggerSel() & (1ULL << triggerSelection)); } int initialiseChargedTriggerSelection(const std::string& triggerSelection) @@ -474,7 +497,7 @@ bool selectFullTrigger(T const& collision, int triggerSelection) if (triggerSelection == -1) { return true; } - return (collision.fullTriggerSel() & (1 << triggerSelection)); + return (collision.fullTriggerSel() & (1ULL << triggerSelection)); } int initialiseFullTriggerSelection(const std::string& triggerSelection) @@ -569,7 +592,7 @@ bool selectChargedHFTrigger(T const& collision, int triggerSelection) if (triggerSelection == -1) { return true; } - return (collision.chargedHFTriggerSel() & (1 << triggerSelection)); + return (collision.chargedHFTriggerSel() & (1ULL << triggerSelection)); } int initialiseChargedHFTriggerSelection(const std::string& triggerSelection) @@ -631,16 +654,16 @@ bool applyTrackKinematics(T const& track, float pTMin = 0.15, float pTMax = 100. template bool selectTrack(T const& track, int trackSelection, bool isEmbedded = false) { - if (!(track.trackSel() & (1 << JTrackSel::notBadMcTrack))) { + if (!(track.trackSel() & (1ULL << JTrackSel::notBadMcTrack))) { return false; } - if (isEmbedded && !(track.trackSel() & (1 << JTrackSel::embeddedTrack))) { // will get rid of non embedded tracks + if (isEmbedded && !(track.trackSel() & (1ULL << JTrackSel::embeddedTrack))) { // will get rid of non embedded tracks return false; } if (trackSelection == -1) { return true; } - return (track.trackSel() & (1 << trackSelection)); + return (track.trackSel() & (1ULL << trackSelection)); } int initialiseTrackSelection(const std::string& trackSelection) @@ -708,6 +731,25 @@ bool selectTrackDcaZ(T const& track, double dcaZmax = 99.) return std::abs(track.dcaZ()) < dcaZmax; } +std::vector initialiseClusterDefinitions(const std::string clusterDefinitions) +{ + std::vector clusterDefinitionsVec; + if (clusterDefinitions.empty()) { + return clusterDefinitionsVec; + } + size_t start = 0; + size_t end; + while ((end = clusterDefinitions.find(',', start)) != std::string::npos) { + clusterDefinitionsVec.push_back(static_cast(o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitions.substr(start, end - start)))); + start = end + 1; + } + // Process the last element (after the final comma or if no comma exists) + if (start < clusterDefinitions.length()) { + clusterDefinitionsVec.push_back(static_cast(o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitions.substr(start)))); + } + return clusterDefinitionsVec; +} + } // namespace jetderiveddatautilities #endif // PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ diff --git a/PWGJE/Core/JetFinder.cxx b/PWGJE/Core/JetFinder.cxx index 87a71fb19e3..c3c2d091908 100644 --- a/PWGJE/Core/JetFinder.cxx +++ b/PWGJE/Core/JetFinder.cxx @@ -36,14 +36,12 @@ void JetFinder::setParams() jetEtaMax += jetR; } } - if (isReclustering) { - jetR = 5.0 * jetR; - } + float jetRForClustering = isReclustering ? 5.0 * jetR : jetR; - // selGhosts =fastjet::SelectorRapRange(ghostEtaMin,ghostEtaMax) && fastjet::SelectorPhiRange(phiMin,phiMax); + selGhosts = fastjet::SelectorRapRange(etaMin, etaMax) && fastjet::SelectorPhiRange(phiMin, phiMax); // note that this is rapidity not eta but since ghosts are effectively massless this is ok // 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(fastjet::antikt_algorithm, jetR, recombScheme, strategy); + ghostAreaSpec = fastjet::GhostedAreaSpec(selGhosts, ghostRepeatN, ghostArea, gridScatter, ktScatter, ghostktMean); + jetDef = fastjet::JetDefinition(fastjet::antikt_algorithm, jetRForClustering, recombScheme, strategy); if (fastjetExtraParam > -98.0) { jetDef.set_extra_param(fastjetExtraParam); } @@ -65,8 +63,5 @@ fastjet::ClusterSequenceArea JetFinder::findJets(std::vector jets = clusterSeq.inclusive_jets(); jets = selJets(jets); jets = fastjet::sorted_by_pt(jets); - if (isReclustering) { - jetR = jetR / 5.0; - } return clusterSeq; } diff --git a/PWGJE/Core/JetFinder.h b/PWGJE/Core/JetFinder.h index 94afd0117ec..8f727bbdbbd 100644 --- a/PWGJE/Core/JetFinder.h +++ b/PWGJE/Core/JetFinder.h @@ -48,7 +48,7 @@ class JetFinder /// \return ClusterSequenceArea object needed to access constituents // fastjet::ClusterSequenceArea findJets(std::vector &inputParticles, std::vector &jets); - float phiMin = 0.; + float phiMin = -1. * M_PI; float phiMax = 2. * M_PI; float etaMin = -.9; float etaMax = .9; @@ -56,14 +56,12 @@ class JetFinder float jetR = .4; float jetPtMin = 0.; float jetPtMax = 1000.; - float jetPhiMin = 0.; + float jetPhiMin = -1. * M_PI; float jetPhiMax = 2. * M_PI; float jetEtaMin = -99.; float jetEtaMax = 99.; bool jetEtaDefault = false; - float ghostEtaMin = -.9; - float ghostEtaMax = .9; float ghostArea = .005; int ghostRepeatN = 1; double ghostktMean = 1.e-100; diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index b082b5df4e4..37ca4eddaa5 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -91,28 +90,18 @@ constexpr bool isEMCALClusterTable() */ template -bool isTrackSelected(T const& track, int trackSelection, bool applyTrackingEfficiency, const std::vector& trackingEfficiency, const std::vector& trackingEfficiencyPtBinning, const U* candidate = nullptr) +bool isTrackSelected(T const& track, int trackSelection, const U* candidate = nullptr) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { return false; } - if (candidate != nullptr) { - if (jetcandidateutilities::isDaughterTrack(track, *candidate)) { - return false; - } - } - if (applyTrackingEfficiency) { - auto iter = std::upper_bound(trackingEfficiencyPtBinning.begin(), trackingEfficiencyPtBinning.end(), track.pt()); - if (iter != trackingEfficiencyPtBinning.begin() && iter != trackingEfficiencyPtBinning.end()) { - std::size_t index = std::distance(trackingEfficiencyPtBinning.begin(), iter) - 1; - TRandom3 randomNumber(0); - if (randomNumber.Rndm() > trackingEfficiency[index]) { - return false; - } - } + if (candidate != nullptr) { + if (jetcandidateutilities::isDaughterTrack(track, *candidate)) { + return false; } - return true; + } + return true; } /** @@ -125,10 +114,10 @@ bool isTrackSelected(T const& track, int trackSelection, bool applyTrackingEffic */ template -void analyseTracks(std::vector& inputParticles, T const& tracks, int trackSelection, bool applyTrackingEfficiency, const std::vector& trackingEfficiency, const std::vector& trackingEfficiencyPtBinning, const U* candidate = nullptr) +void analyseTracks(std::vector& inputParticles, T const& tracks, int trackSelection, const U* candidate = nullptr) { for (auto& track : tracks) { - if (isTrackSelected(track, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning, candidate)) { + if (isTrackSelected(track, trackSelection, candidate)) { fastjetutilities::fillTracks(track, inputParticles, track.globalIndex()); } } @@ -144,7 +133,7 @@ void analyseTracks(std::vector& inputParticles, T const& tra */ template -void analyseTracksMultipleCandidates(std::vector& inputParticles, T const& tracks, int trackSelection, bool applyTrackingEfficiency, const std::vector& trackingEfficiency, const std::vector& trackingEfficiencyPtBinning, U const& candidates) +void analyseTracksMultipleCandidates(std::vector& inputParticles, T const& tracks, int trackSelection, U const& candidates) { for (auto& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -155,16 +144,6 @@ void analyseTracksMultipleCandidates(std::vector& inputParti continue; } } - if (applyTrackingEfficiency) { - auto iter = std::upper_bound(trackingEfficiencyPtBinning.begin(), trackingEfficiencyPtBinning.end(), track.pt()); - if (iter != trackingEfficiencyPtBinning.begin() && iter != trackingEfficiencyPtBinning.end()) { - std::size_t index = std::distance(trackingEfficiencyPtBinning.begin(), iter) - 1; - TRandom3 randomNumber(0); - if (randomNumber.Rndm() > trackingEfficiency[index]) { - continue; - } - } - } fastjetutilities::fillTracks(track, inputParticles, track.globalIndex()); } } @@ -176,10 +155,13 @@ void analyseTracksMultipleCandidates(std::vector& inputParti * @param clusters track table to be added */ template -void analyseClusters(std::vector& inputParticles, T const& clusters, int hadronicCorrectionType = 0) +void analyseClusters(std::vector& inputParticles, T const& clusters, int clusterDefinition, int hadronicCorrectionType) { - for (auto& cluster : *clusters) { + for (auto const& cluster : clusters) { // add cluster selections + if (cluster.definition() != clusterDefinition) { + continue; + } fastjetutilities::fillClusters(cluster, inputParticles, cluster.globalIndex(), hadronicCorrectionType); } } @@ -207,7 +189,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::candidate), candMass); + fastjetutilities::fillTracks(candidate, inputParticles, candidate.globalIndex(), JetConstituentStatus::candidate, candMass); return true; } @@ -274,7 +256,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::candidate), v0Mass); + fastjetutilities::fillTracks(v0, inputParticles, v0.globalIndex(), JetConstituentStatus::candidate, v0Mass); nSelectedV0s++; } if (nSelectedV0s > 0) { @@ -315,8 +297,8 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic if (doCandidateJetFinding) { bool isCandidateJet = false; for (const auto& constituent : jet.constituents()) { - auto constituentStatus = constituent.template user_info().getStatus(); - 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 + JetConstituentStatus constituentStatus = constituent.template user_info().getStatus(); + if (constituentStatus == 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; } @@ -331,13 +313,13 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic jetsTable(collision.globalIndex(), jet.pt(), jet.eta(), jet.phi(), jet.E(), jet.rapidity(), jet.m(), jet.has_area() ? jet.area() : 0., std::round(R * 100)); for (const auto& constituent : sorted_by_pt(jet.constituents())) { - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::track)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::track) { tracks.push_back(constituent.template user_info().getIndex()); } - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::cluster)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::cluster) { clusters.push_back(constituent.template user_info().getIndex()); } - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidate)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::candidate) { cands.push_back(constituent.template user_info().getIndex()); } } @@ -406,7 +388,7 @@ void analyseParticles(std::vector& inputParticles, const std } } } - fastjetutilities::fillTracks(particle, inputParticles, particle.globalIndex(), static_cast(JetConstituentStatus::track), pdgParticle->Mass()); + fastjetutilities::fillTracks(particle, inputParticles, particle.globalIndex(), JetConstituentStatus::track, pdgParticle->Mass()); } } diff --git a/PWGJE/Core/JetHFUtilities.h b/PWGJE/Core/JetHFUtilities.h index 1d9bf0841a5..a018c0c177b 100644 --- a/PWGJE/Core/JetHFUtilities.h +++ b/PWGJE/Core/JetHFUtilities.h @@ -609,48 +609,57 @@ bool isHFDaughterTrack(T& track, U& candidate) * @param particles particle table */ template -auto matchedHFParticle(const T& candidate, const U& /*tracks*/, const V& /*particles*/) +auto matchedHFParticle(const T& candidate, const U& /*tracks*/, const V& /*particles*/, bool& isMatched) { typename V::iterator candidateDaughterParticle; + isMatched = false; if constexpr (isD0Candidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { candidateDaughterParticle = candidate.template prong0_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isDplusCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { candidateDaughterParticle = candidate.template prong0_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isDsCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) { candidateDaughterParticle = candidate.template prong0_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isDstarCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { candidateDaughterParticle = candidate.template prong2_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isLcCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { candidateDaughterParticle = candidate.template prong0_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isB0Candidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::B0ToDminusPi) { candidateDaughterParticle = candidate.template prong3_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isBplusCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::BplusToD0Pi) { candidateDaughterParticle = candidate.template prong2_as().template mcParticle_as(); + isMatched = true; } } if constexpr (isXicToXiPiPiCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi) { candidateDaughterParticle = candidate.template prong0_as().template mcParticle_as(); + isMatched = true; } } return candidateDaughterParticle.template mothers_first_as(); @@ -666,7 +675,13 @@ auto matchedHFParticle(const T& candidate, const U& /*tracks*/, const V& /*parti template auto matchedHFParticleId(const T& candidate, const U& tracks, const V& particles) { - return (matchedHFParticle(candidate, tracks, particles)).globalIndex(); + bool isMatched = false; + auto matchedParticle = matchedHFParticle(candidate, tracks, particles, isMatched); + if (isMatched) { + return matchedParticle.globalIndex(); + } else { + return int64_t{-1}; // does this clash with the case where a track doesnt have an associated particle? + } } /** @@ -1351,6 +1366,10 @@ void fillBplusCandidateTable(T const& candidate, U& BplusParTable, V& BplusParET candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1(), + candidate.pProng0(), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), candidate.errorImpactParameter1(), candidate.cosThetaStar(), candidate.ct()); diff --git a/PWGJE/Core/JetMatchingUtilities.h b/PWGJE/Core/JetMatchingUtilities.h index e4fb0af8308..2285d40b53b 100644 --- a/PWGJE/Core/JetMatchingUtilities.h +++ b/PWGJE/Core/JetMatchingUtilities.h @@ -24,6 +24,8 @@ #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "Common/Core/RecoDecay.h" + #include #include @@ -293,7 +295,7 @@ std::tuple, std::vector> MatchJetsGeometrically( } template -void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& tagToBaseMatchingGeo, float maxMatchingDistance) +void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& tagToBaseMatchingGeo, std::vector const& jetRadiiForMatchingDistance, std::vector const& maxMatchingDistancePerJetR) { std::vector jetsR; for (const auto& jetBase : jetsBasePerCollision) { @@ -307,8 +309,19 @@ void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std:: } } for (auto jetR : jetsR) { + float effectiveMatchingDistance = -1.0f; + for (std::size_t i = 0; i < jetRadiiForMatchingDistance.size(); i++) { + if (std::round(jetRadiiForMatchingDistance[i] * 100.0) == std::round(jetR)) { + effectiveMatchingDistance = maxMatchingDistancePerJetR[i]; + break; + } + } + if (effectiveMatchingDistance < 0.0f) { + LOGP(fatal, "No matching distance configured for jet R={:.2f}. Add it to jetRadiiForMatchingDistance and maxMatchingDistancePerJetR.", jetR / 100.0); + } std::vector jetsBasePhi; std::vector jetsBaseEta; + std::vector jetsBaseGlobalIndex; std::vector baseToTagMatchingGeoIndex; std::vector tagToBaseMatchingGeoIndex; @@ -316,19 +329,22 @@ void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std:: if (std::round(jetBase.r()) != std::round(jetR)) { continue; } - jetsBasePhi.emplace_back(jetBase.phi()); + jetsBasePhi.emplace_back(RecoDecay::constrainAngle(jetBase.phi(), 0.0)); jetsBaseEta.emplace_back(jetBase.eta()); + jetsBaseGlobalIndex.emplace_back(jetBase.globalIndex()); } std::vector jetsTagPhi; std::vector jetsTagEta; + std::vector jetsTagGlobalIndex; for (const auto& jetTag : jetsTagPerCollision) { if (std::round(jetTag.r()) != std::round(jetR)) { continue; } - jetsTagPhi.emplace_back(jetTag.phi()); + jetsTagPhi.emplace_back(RecoDecay::constrainAngle(jetTag.phi(), 0.0)); jetsTagEta.emplace_back(jetTag.eta()); + jetsTagGlobalIndex.emplace_back(jetTag.globalIndex()); } - std::tie(baseToTagMatchingGeoIndex, tagToBaseMatchingGeoIndex) = MatchJetsGeometrically(jetsBasePhi, jetsBaseEta, jetsTagPhi, jetsTagEta, maxMatchingDistance); // change max distnace to a function call + std::tie(baseToTagMatchingGeoIndex, tagToBaseMatchingGeoIndex) = MatchJetsGeometrically(jetsBasePhi, jetsBaseEta, jetsTagPhi, jetsTagEta, effectiveMatchingDistance); int jetBaseIndex = 0; int jetTagIndex = 0; for (const auto& jetBase : jetsBasePerCollision) { @@ -336,19 +352,20 @@ void MatchGeo(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std:: continue; } jetTagIndex = baseToTagMatchingGeoIndex[jetBaseIndex]; - if (jetTagIndex > -1 && jetTagIndex < jetsTagPerCollision.size()) { - int jetTagGlobalIndex = jetsTagPerCollision.iteratorAt(jetTagIndex).globalIndex(); + if (jetTagIndex > -1 && jetTagIndex < std::ssize(jetsTagPhi)) { + int jetTagGlobalIndex = jetsTagGlobalIndex[jetTagIndex]; baseToTagMatchingGeo[jetBase.globalIndex()].push_back(jetTagGlobalIndex); } jetBaseIndex++; } + jetTagIndex = 0; for (const auto& jetTag : jetsTagPerCollision) { if (std::round(jetTag.r()) != std::round(jetR)) { continue; } jetBaseIndex = tagToBaseMatchingGeoIndex[jetTagIndex]; - if (jetBaseIndex > -1 && jetBaseIndex < jetsBasePerCollision.size()) { - int jetBaseGlobalIndex = jetsBasePerCollision.iteratorAt(jetBaseIndex).globalIndex(); + if (jetBaseIndex > -1 && jetBaseIndex < std::ssize(jetsBasePhi)) { + int jetBaseGlobalIndex = jetsBaseGlobalIndex[jetBaseIndex]; tagToBaseMatchingGeo[jetTag.globalIndex()].push_back(jetBaseGlobalIndex); } jetTagIndex++; @@ -484,10 +501,8 @@ float getPtSum(T const& tracksBase, U const& candidatesBase, V const& clustersBa if (candidateBaseMcId == candidateTagId) { ptSum += candidateBase.pt(); } - break; // should only be one } } - break; } } else if constexpr (jetsBaseIsMc) { for (auto const& candidateTag : candidatesTag) { @@ -498,10 +513,8 @@ float getPtSum(T const& tracksBase, U const& candidatesBase, V const& clustersBa if (candidateTagMcId == candidateBaseId) { ptSum += candidateTag.pt(); } - break; // should only be one } } - break; } } else { for (auto const& candidateBase : candidatesBase) { @@ -509,9 +522,7 @@ float getPtSum(T const& tracksBase, U const& candidatesBase, V const& clustersBa if (candidateBase.globalIndex() == candidateTag.globalIndex()) { ptSum += candidateBase.pt(); } - break; // should only be one } - break; } } } @@ -565,11 +576,11 @@ void MatchPt(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::v // function that calls all the Match functions template -void doAllMatching(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& baseToTagMatchingPt, std::vector>& baseToTagMatchingHF, std::vector>& tagToBaseMatchingGeo, std::vector>& tagToBaseMatchingPt, std::vector>& tagToBaseMatchingHF, V const& candidatesBase, M const& tracksBase, N const& clustersBase, O const& candidatesTag, P const& tracksTag, R const& clustersTag, bool doMatchingGeo, bool doMatchingHf, bool doMatchingPt, float maxMatchingDistance, float minPtFraction) +void doAllMatching(T const& jetsBasePerCollision, U const& jetsTagPerCollision, std::vector>& baseToTagMatchingGeo, std::vector>& baseToTagMatchingPt, std::vector>& baseToTagMatchingHF, std::vector>& tagToBaseMatchingGeo, std::vector>& tagToBaseMatchingPt, std::vector>& tagToBaseMatchingHF, V const& candidatesBase, M const& tracksBase, N const& clustersBase, O const& candidatesTag, P const& tracksTag, R const& clustersTag, bool doMatchingGeo, bool doMatchingHf, bool doMatchingPt, float minPtFraction, std::vector const& jetRadiiForMatchingDistance, std::vector const& maxMatchingDistancePerJetR) { // geometric matching if (doMatchingGeo) { - MatchGeo(jetsBasePerCollision, jetsTagPerCollision, baseToTagMatchingGeo, tagToBaseMatchingGeo, maxMatchingDistance); + MatchGeo(jetsBasePerCollision, jetsTagPerCollision, baseToTagMatchingGeo, tagToBaseMatchingGeo, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } // pt matching if (doMatchingPt) { diff --git a/PWGJE/Core/JetSubstructureUtilities.h b/PWGJE/Core/JetSubstructureUtilities.h index 089c1012656..22f301513f1 100644 --- a/PWGJE/Core/JetSubstructureUtilities.h +++ b/PWGJE/Core/JetSubstructureUtilities.h @@ -60,7 +60,7 @@ fastjet::ClusterSequenceArea jetToPseudoJet(T const& jet, U const& /*tracks*/, V } 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()); + fastjetutilities::fillTracks(jetHFConstituent, jetConstituents, jetHFConstituent.globalIndex(), JetConstituentStatus::candidate, jetcandidateutilities::getTablePDGMass()); } } std::vector jetReclustered; diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index 4e685b41bf8..0e8b08c3fa2 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -1095,9 +1095,9 @@ void analyzeJetTrackInfo4MLnoSV(AnalysisJet const& analysisJet, AnyTracks const& std::sort(tracksParams.begin(), tracksParams.end(), compare); } -// Looping over the track info and putting them in the input vector (for GNN b-jet tagging) +// Looping over the track info and putting them in the input vector, with extra input features (for GNN b-jet tagging) template -void analyzeJetTrackInfo4GNN(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const& /*origTracks*/, std::vector>& tracksParams, float trackPtMin = 0.5, float trackDcaXYMax = 10.0, float trackDcaZMax = 10.0, int64_t nMaxConstit = 40) +void analyzeJetTrackInfo4GNNwExtra(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const& /*origTracks*/, std::vector>& tracksParams, float trackPtMin = 0.5, float trackDcaXYMax = 10.0, float trackDcaZMax = 10.0, int64_t nMaxConstit = 40) { for (const auto& constituent : analysisJet.template tracks_as()) { @@ -1124,6 +1124,33 @@ void analyzeJetTrackInfo4GNN(AnalysisJet const& analysisJet, AnyTracks const& /* } } +// Looping over the track info and putting them in the input vector (for GNN b-jet tagging) +template +void analyzeJetTrackInfo4GNN(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, std::vector>& tracksParams, float trackPtMin = 0.5, float trackDcaXYMax = 10.0, float trackDcaZMax = 10.0, int64_t nMaxConstit = 40) +{ + for (const auto& constituent : analysisJet.template tracks_as()) { + + if (constituent.pt() < trackPtMin || !trackAcceptanceWithDca(constituent, trackDcaXYMax, trackDcaZMax)) { + continue; + } + + int sign = getGeoSign(analysisJet, constituent); + + if (static_cast(tracksParams.size()) < nMaxConstit) { + tracksParams.emplace_back(std::vector{constituent.pt(), constituent.phi(), constituent.eta(), static_cast(constituent.sign()), std::abs(constituent.dcaXY()) * sign, constituent.sigmadcaXY(), std::abs(constituent.dcaZ()) * sign, constituent.sigmadcaZ()}); + } else { + // If there are more than nMaxConstit constituents in the jet, select only nMaxConstit constituents with the highest DCA_XY significance. + size_t minIdx = 0; + for (size_t i = 0; i < tracksParams.size(); ++i) { + if (tracksParams[i][4] / tracksParams[i][5] < tracksParams[minIdx][4] / tracksParams[minIdx][5]) + minIdx = i; + } + if (std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY() > tracksParams[minIdx][4] / tracksParams[minIdx][5]) + tracksParams[minIdx] = std::vector{constituent.pt(), constituent.phi(), constituent.eta(), static_cast(constituent.sign()), std::abs(constituent.dcaXY()) * sign, constituent.sigmadcaXY(), std::abs(constituent.dcaZ()) * sign, constituent.sigmadcaZ()}; + } + } +} + // Discriminant value for GNN b-jet tagging template T getDb(const std::vector& logits, double fC = 0.018) diff --git a/PWGJE/Core/JetUtilities.h b/PWGJE/Core/JetUtilities.h index 9c0df210987..c2f555689ce 100644 --- a/PWGJE/Core/JetUtilities.h +++ b/PWGJE/Core/JetUtilities.h @@ -20,122 +20,16 @@ #include "Common/Core/RecoDecay.h" -#include +#include -#include #include -#include -#include -#include #include -#include #include namespace jetutilities { -/** - * Match clusters and tracks. - * - * Match cluster with tracks, where maxNumberMatches are considered in dR=maxMatchingDistance. - * If no unique match was found for a jet, an index of -1 is stored. - * The same map is created for clusters matched to tracks e.g. for electron analyses. - * - * @param clusterPhi cluster collection phi. - * @param clusterEta cluster collection eta. - * @param trackPhi track collection phi. - * @param trackEta track collection eta. - * @param maxMatchingDistance Maximum matching distance. - * @param maxNumberMatches Maximum number of matches (e.g. 5 closest). - * - * @returns (cluster to track index map, track to cluster index map) - */ -template -std::tuple>, std::vector>> MatchClustersAndTracks( - std::vector& clusterPhi, - std::vector& clusterEta, - std::vector& trackPhi, - std::vector& trackEta, - double maxMatchingDistance, - int maxNumberMatches) -{ - // test - // Validation - const std::size_t nClusters = clusterEta.size(); - const std::size_t nTracks = trackEta.size(); - if (!(nClusters && nTracks)) { - // There are no jets, so nothing to be done. - return std::make_tuple(std::vector>(nClusters, std::vector(maxNumberMatches, -1)), std::vector>(nTracks, std::vector(maxNumberMatches, -1))); - } - // Input sizes must match - if (clusterPhi.size() != clusterEta.size()) { - throw std::invalid_argument("cluster collection eta and phi sizes don't match. Check the inputs."); - } - if (trackPhi.size() != trackEta.size()) { - throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs."); - } - - // Build the KD-trees using vectors - // We build two trees: - // treeBase, which contains the base collection. - // treeTag, which contains the tag collection. - // The trees are built to match in two dimensions (eta, phi) - TKDTree treeCluster(clusterEta.size(), 2, 1), treeTrack(trackEta.size(), 2, 1); - // By utilizing SetData, we can avoid having to copy the data again. - treeCluster.SetData(0, clusterEta.data()); - treeCluster.SetData(1, clusterPhi.data()); - treeCluster.Build(); - treeTrack.SetData(0, trackEta.data()); - treeTrack.SetData(1, trackPhi.data()); - treeTrack.Build(); - - // Storage for the cluster matching indices. - std::vector> matchIndexTrack(nClusters, std::vector(maxNumberMatches, -1)); - std::vector> matchIndexCluster(nTracks, std::vector(maxNumberMatches, -1)); - - // Find the track closest to each cluster. - for (std::size_t iCluster = 0; iCluster < nClusters; iCluster++) { - T point[2] = {clusterEta[iCluster], clusterPhi[iCluster]}; - int index[50]; // size 50 for safety - T distance[50]; // size 50 for safery - std::fill_n(index, 50, -1); - std::fill_n(distance, 50, std::numeric_limits::max()); - treeTrack.FindNearestNeighbors(point, maxNumberMatches, index, distance); - // test whether indices are matching: - matchIndexTrack[iCluster] = std::vector(maxNumberMatches); - for (int m = 0; m < maxNumberMatches; m++) { - if (index[m] >= 0 && distance[m] < maxMatchingDistance) { - matchIndexTrack[iCluster][m] = index[m]; - } else { - // no match or no more matches found, fill -1 - matchIndexTrack[iCluster][m] = -1; - } - } - } - - // Find the base jet closest to each tag jet - for (std::size_t iTrack = 0; iTrack < nTracks; iTrack++) { - T point[2] = {trackEta[iTrack], trackPhi[iTrack]}; - int index[50]; // size 50 for safety - T distance[50]; // size 50 for safery - std::fill_n(index, 50, -1); - std::fill_n(distance, 50, std::numeric_limits::max()); - treeCluster.FindNearestNeighbors(point, maxNumberMatches, index, distance); - matchIndexCluster[iTrack] = std::vector(maxNumberMatches); - // loop over maxNumberMatches closest matches - for (int m = 0; m < maxNumberMatches; m++) { - if (index[m] >= 0 && distance[m] < maxMatchingDistance) { - matchIndexCluster[iTrack][m] = index[m]; - } else { - // no match jet or no more matches found, fill -1 - matchIndexCluster[iTrack][m] = -1; - } - } - } - return std::make_tuple(matchIndexTrack, matchIndexCluster); -} - template float deltaR(T const& A, U const& B) { diff --git a/PWGJE/Core/MlResponseHfTagging.h b/PWGJE/Core/MlResponseHfTagging.h index be16b0cd450..4740a087a79 100644 --- a/PWGJE/Core/MlResponseHfTagging.h +++ b/PWGJE/Core/MlResponseHfTagging.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/PWGJE/Core/emcalCrossTalkEmulation.cxx b/PWGJE/Core/emcalCrossTalkEmulation.cxx index 32b08cd13dc..ebd6fa0922a 100644 --- a/PWGJE/Core/emcalCrossTalkEmulation.cxx +++ b/PWGJE/Core/emcalCrossTalkEmulation.cxx @@ -20,12 +20,15 @@ #include #include #include -#include #include +#include + +#include #include // std::find_if #include #include // size_t +#include #include // std::abs #include // setw #include // left and right @@ -34,13 +37,6 @@ #include #include #include -// #include "Framework/OutputObjHeader.h" - -// #include "Common/CCDB/EventSelectionParams.h" -#include -#include - -#include using namespace o2; using namespace o2::emccrosstalk; diff --git a/PWGJE/Core/emcalCrossTalkEmulation.h b/PWGJE/Core/emcalCrossTalkEmulation.h index fb84ec7c1ad..e597ebba4b0 100644 --- a/PWGJE/Core/emcalCrossTalkEmulation.h +++ b/PWGJE/Core/emcalCrossTalkEmulation.h @@ -21,9 +21,8 @@ #include #include #include -#include +#include -#include #include #include diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index e28931982b5..9384ef1a9b6 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -49,11 +49,12 @@ const EMCALClusterDefinition kV3SmallestTimeDiff(ClusterAlgorithm_t::kV3, 42, 1, const EMCALClusterDefinition kV3MostSplitSmallTimeDiff(ClusterAlgorithm_t::kV3, 43, 1, "kV3MostSplitSmallTimeDiff", 0.5, 0.1, -10000, 10000, 500, true, 0., false); const EMCALClusterDefinition kV3MostSplitSmallerTimeDiff(ClusterAlgorithm_t::kV3, 44, 1, "kV3MostSplitSmallerTimeDiff", 0.5, 0.1, -10000, 10000, 100, true, 0., false); const EMCALClusterDefinition kV3MostSplitSmallestTimeDiff(ClusterAlgorithm_t::kV3, 45, 1, "kV3MostSplitSmallestTimeDiff", 0.5, 0.1, -10000, 10000, 50, true, 0., false); +const EMCALClusterDefinition kV3MostSplitSmallestTimeDiffLowestSeed(ClusterAlgorithm_t::kV3, 50, 1, "kV3MostSplitSmallestTimeDiffLowestSeed", 0.1, 0.1, -10000, 10000, 50, true, 0., false); /// \brief function returns EMCALClusterDefinition for the given name /// \param name name of the cluster definition /// \return EMCALClusterDefinition for the given name -const EMCALClusterDefinition getClusterDefinitionFromString(const std::string& clusterDefinitionName) +inline const EMCALClusterDefinition getClusterDefinitionFromString(const std::string& clusterDefinitionName) { if (clusterDefinitionName == "kV3NoSplit") { return kV3NoSplit; @@ -89,6 +90,8 @@ const EMCALClusterDefinition getClusterDefinitionFromString(const std::string& c return kV3MostSplitSmallerTimeDiff; } else if (clusterDefinitionName == "kV3MostSplitSmallestTimeDiff") { return kV3MostSplitSmallestTimeDiff; + } else if (clusterDefinitionName == "kV3MostSplitSmallestTimeDiffLowestSeed") { + return kV3MostSplitSmallestTimeDiffLowestSeed; } else { throw std::invalid_argument("Cluster definition name not recognized"); } diff --git a/PWGJE/DataModel/GammaJetAnalysisTree.h b/PWGJE/DataModel/GammaJetAnalysisTree.h index 02a9602ec6e..1f527ff8137 100644 --- a/PWGJE/DataModel/GammaJetAnalysisTree.h +++ b/PWGJE/DataModel/GammaJetAnalysisTree.h @@ -17,11 +17,12 @@ #ifndef PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ #define PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" +#include -#include "Framework/AnalysisDataModel.h" +#include + +#include +#include namespace o2::aod::gjanalysis { @@ -138,6 +139,23 @@ DECLARE_SOA_COLUMN(NConstituents, nConstituents, ushort); } // namespace gjchjet DECLARE_SOA_TABLE(GjChargedJets, "AOD", "GJCHJET", gjgamma::GjEventId, gjchjet::Pt, gjchjet::Eta, gjchjet::Phi, gjchjet::Radius, gjchjet::Energy, gjchjet::Mass, gjchjet::Area, gjchjet::LeadingTrackPt, gjchjet::PerpConeRho, gjchjet::NConstituents) +using GjChargedJet = GjChargedJets::iterator; + +// Jet substructure information (vectors stored per jet) +namespace gjjetsubstructure +{ +DECLARE_SOA_COLUMN(EnergyMother, energyMother, std::vector); //! energy of mother subjet at each splitting +DECLARE_SOA_COLUMN(PtLeading, ptLeading, std::vector); //! pt of leading subjet at each splitting +DECLARE_SOA_COLUMN(PtSubLeading, ptSubLeading, std::vector); //! pt of subleading subjet at each splitting +DECLARE_SOA_COLUMN(Theta, theta, std::vector); //! opening angle theta at each splitting +} // namespace gjjetsubstructure +DECLARE_SOA_TABLE(GjJetSubstructures, "AOD", "GJJETSUBSTR", + gjgamma::GjEventId, + gjjetsubstructure::EnergyMother, + gjjetsubstructure::PtLeading, + gjjetsubstructure::PtSubLeading, + gjjetsubstructure::Theta) + // MC information for reconstructed charged jet namespace gjchjetmcinfo { diff --git a/PWGJE/DataModel/JetReducedData.h b/PWGJE/DataModel/JetReducedData.h index 69d8bc18d5e..1cd94a96d03 100644 --- a/PWGJE/DataModel/JetReducedData.h +++ b/PWGJE/DataModel/JetReducedData.h @@ -22,6 +22,8 @@ #include #include // IWYU pragma: keep +#include +#include #include #include @@ -36,6 +38,7 @@ 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_COLUMN(TriggerMask, triggerMask, uint64_t); DECLARE_SOA_BITMAP_COLUMN(Alias, alias, 32); DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 64); DECLARE_SOA_BITMAP_COLUMN(Rct, rct, 32); @@ -49,6 +52,7 @@ DECLARE_SOA_TABLE_STAGED(JBCs, "JBC", o2::soa::Index<>, jbc::RunNumber, jbc::GlobalBC, + jbc::TriggerMask, jbc::Timestamp, jbc::Alias, jbc::Selection, @@ -73,6 +77,7 @@ DECLARE_SOA_INDEX_COLUMN(JBC, bc); DECLARE_SOA_COLUMN(PosX, posX, float); DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(CollisionTime, collisionTime, float); DECLARE_SOA_COLUMN(MultFV0A, multFV0A, float); DECLARE_SOA_COLUMN(MultFV0C, multFV0C, float); DECLARE_SOA_DYNAMIC_COLUMN(MultFV0M, multFV0M, @@ -124,9 +129,11 @@ DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); DECLARE_SOA_TABLE_STAGED(JCollisions, "JCOLLISION", o2::soa::Index<>, + jcollision::JBCId, jcollision::PosX, jcollision::PosY, jcollision::PosZ, + jcollision::CollisionTime, jcollision::MultFV0A, jcollision::MultFV0C, jcollision::MultFV0M, @@ -139,11 +146,6 @@ DECLARE_SOA_TABLE_STAGED(JCollisions, "JCOLLISION", jcollision::CentFT0C, jcollision::CentFT0M, jcollision::CentFT0CVariant1, - jcollision::AmplitudesFV0, - jcollision::AmplitudesFT0A, - jcollision::AmplitudesFT0C, - jcollision::AmplitudesFDDA, - jcollision::AmplitudesFDDC, jcollision::HadronicRate, jcollision::TrackOccupancyInTimeRange, jcollision::Alias, @@ -154,6 +156,13 @@ DECLARE_SOA_TABLE_STAGED(JCollisions, "JCOLLISION", using JCollision = JCollisions::iterator; using StoredJCollision = StoredJCollisions::iterator; +DECLARE_SOA_TABLE_STAGED(JCollisionUPCs, "JCOLLISIONUPC", + jcollision::AmplitudesFV0, + jcollision::AmplitudesFT0A, + jcollision::AmplitudesFT0C, + jcollision::AmplitudesFDDA, + jcollision::AmplitudesFDDC); + DECLARE_SOA_TABLE_STAGED(JCollisionMcInfos, "JCOLLISIONMCINFO", jcollision::Weight, jcollision::GetSubGeneratorId); @@ -170,9 +179,6 @@ using StoredJEMCCollisionLb = StoredJEMCCollisionLbs::iterator; DECLARE_SOA_TABLE_STAGED(JCollisionPIs, "JCOLLISIONPI", jcollision::CollisionId); -DECLARE_SOA_TABLE_STAGED(JCollisionBCs, "JCOLLISIONBC", - jcollision::JBCId); - DECLARE_SOA_TABLE(JChTrigSels, "AOD", "JCHTRIGSEL", jcollision::ChargedTriggerSel); @@ -200,6 +206,7 @@ DECLARE_SOA_TABLE_STAGED(CollisionCounts, "COLLCOUNT", namespace jmccollision { DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); +DECLARE_SOA_INDEX_COLUMN(JBC, bc); DECLARE_SOA_COLUMN(PosX, posX, float); DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); @@ -214,6 +221,7 @@ DECLARE_SOA_COLUMN(XsectGen, xsectGen, float); DECLARE_SOA_COLUMN(XsectErr, xsectErr, float); DECLARE_SOA_COLUMN(PtHard, ptHard, float); DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); +DECLARE_SOA_COLUMN(EventSel, eventSel, uint16_t); DECLARE_SOA_BITMAP_COLUMN(Rct, rct, 32); DECLARE_SOA_COLUMN(GetGeneratorId, getGeneratorId, int); DECLARE_SOA_COLUMN(GetSubGeneratorId, getSubGeneratorId, int); @@ -224,6 +232,7 @@ DECLARE_SOA_COLUMN(EventPlaneAngle, eventPlaneAngle, float); } // namespace jmccollision DECLARE_SOA_TABLE_STAGED(JMcCollisions, "JMCCOLLISION", o2::soa::Index<>, + jmccollision::JBCId, jmccollision::PosX, jmccollision::PosY, jmccollision::PosZ, @@ -237,6 +246,7 @@ DECLARE_SOA_TABLE_STAGED(JMcCollisions, "JMCCOLLISION", jmccollision::XsectGen, jmccollision::XsectErr, jmccollision::PtHard, + jmccollision::EventSel, jmccollision::Rct, jmccollision::GetGeneratorId, jmccollision::GetSubGeneratorId, diff --git a/PWGJE/DataModel/JetReducedDataDQ.h b/PWGJE/DataModel/JetReducedDataDQ.h index d8e633cf036..1249263a71f 100644 --- a/PWGJE/DataModel/JetReducedDataDQ.h +++ b/PWGJE/DataModel/JetReducedDataDQ.h @@ -22,6 +22,8 @@ #include #include // IWYU pragma: keep +#include +#include #include #include diff --git a/PWGJE/DataModel/JetReducedDataV0.h b/PWGJE/DataModel/JetReducedDataV0.h index ec460d5b186..e9d4e4040c2 100644 --- a/PWGJE/DataModel/JetReducedDataV0.h +++ b/PWGJE/DataModel/JetReducedDataV0.h @@ -21,6 +21,8 @@ #include #include // IWYU pragma: keep +#include +#include #include #include diff --git a/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h b/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h index 8cd65eedcb5..9b3eef803a8 100644 --- a/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h +++ b/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h @@ -19,11 +19,10 @@ #define PWGJE_DATAMODEL_PHOTONCHARGEDTRIGGERCORRELATION_H_ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { diff --git a/PWGJE/JetFinders/jetFinder.h b/PWGJE/JetFinders/jetFinder.h index 818ed0fd41b..d45cfa15506 100644 --- a/PWGJE/JetFinders/jetFinder.h +++ b/PWGJE/JetFinders/jetFinder.h @@ -21,8 +21,6 @@ #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/EMCALClusterDefinition.h" -#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" @@ -32,7 +30,6 @@ #include #include #include -#include #include #include // IWYU pragma: export @@ -46,6 +43,8 @@ #include #include +#include + template struct JetFinderTask { o2::framework::Produces jetsTable; @@ -72,14 +71,11 @@ struct JetFinderTask { o2::framework::Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; o2::framework::Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; o2::framework::Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; - o2::framework::Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; - o2::framework::Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - o2::framework::Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; o2::framework::Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; o2::framework::Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // cluster level configurables - o2::framework::Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + o2::framework::Configurable clusterDefinitions{"clusterDefinitions", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; o2::framework::Configurable clusterEtaMin{"clusterEtaMin", -0.71, "minimum cluster eta"}; // For ECMAL: |eta| < 0.7, phi = 1.40 - 3.26 o2::framework::Configurable clusterEtaMax{"clusterEtaMax", 0.71, "maximum cluster eta"}; // For ECMAL: |eta| < 0.7, phi = 1.40 - 3.26 o2::framework::Configurable clusterPhiMin{"clusterPhiMin", 1.39, "minimum cluster phi"}; @@ -88,7 +84,7 @@ struct JetFinderTask { o2::framework::Configurable clusterTimeMin{"clusterTimeMin", -25., "minimum Cluster time (ns)"}; o2::framework::Configurable clusterTimeMax{"clusterTimeMax", 25., "maximum Cluster time (ns)"}; o2::framework::Configurable clusterRejectExotics{"clusterRejectExotics", true, "Reject exotic clusters"}; - o2::framework::Configurable hadronicCorrectionType{"hadronicCorrectionType", 0, "0 = no correction, 1 = CorrectedOneTrack1, 2 = CorrectedOneTrack2, 3 = CorrectedAllTracks1, 4 = CorrectedAllTracks2"}; + o2::framework::Configurable> hadronicCorrectionTypes{"hadronicCorrectionTypes", {0}, "0 = no correction, 1 = CorrectedOneTrack1, 2 = CorrectedOneTrack2, 3 = CorrectedAllTracks1, 4 = CorrectedAllTracks2 note :analyses should only use one"}; o2::framework::Configurable doEMCALEventSelection{"doEMCALEventSelection", true, "apply the selection to the event alias_bit for full and neutral jets"}; o2::framework::Configurable doEMCALEventSelectionChargedJets{"doEMCALEventSelectionChargedJets", false, "apply the selection to the event alias_bit for charged jets"}; @@ -96,6 +92,8 @@ struct JetFinderTask { o2::framework::Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; o2::framework::Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; o2::framework::Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; + o2::framework::Configurable jetPhiMin{"jetPhiMin", -99.0, "minimum jet phi"}; + o2::framework::Configurable jetPhiMax{"jetPhiMax", 99.0, "maximum jet phi"}; o2::framework::Configurable jetEWSPtMin{"jetEWSPtMin", 0.0, "minimum event-wise subtracted jet pT"}; o2::framework::Configurable jetEWSPtMax{"jetEWSPtMax", 1000.0, "maximum event-wise subtracted jet pT"}; o2::framework::Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; @@ -120,20 +118,39 @@ struct JetFinderTask { std::vector triggerMaskBits; + std::vector clusterDefinitionsVec; + std::vector hadronicCorrectionTypesVec; + void init(o2::framework::InitContext const&) { + hadronicCorrectionTypesVec = (std::vector)hadronicCorrectionTypes; eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); particleSelection = static_cast(particleSelections); + clusterDefinitionsVec = jetderiveddatautilities::initialiseClusterDefinitions(clusterDefinitions.value); + jetFinder.etaMin = trackEtaMin; jetFinder.etaMax = trackEtaMax; + jetFinder.phiMin = trackPhiMin; + jetFinder.phiMax = trackPhiMax; + if (trackPhiMin < -98.0) { + jetFinder.phiMin = -1.0 * M_PI; + jetFinder.phiMax = 2.0 * M_PI; + } + jetFinder.jetPhiMin = jetPhiMin; + jetFinder.jetPhiMax = jetPhiMax; + if (jetPhiMin < -98.0) { + jetFinder.jetPhiMin = -1.0 * M_PI; + jetFinder.jetPhiMax = 2.0 * M_PI; + } jetFinder.jetEtaMin = jetEtaMin; jetFinder.jetEtaMax = jetEtaMax; if (jetEtaMin < -98.0) { jetFinder.jetEtaDefault = true; } + jetFinder.algorithm = static_cast(static_cast(jetAlgorithm)); jetFinder.recombScheme = static_cast(static_cast(jetRecombScheme)); jetFinder.ghostArea = jetGhostArea; @@ -163,23 +180,13 @@ struct JetFinderTask { registry.add("hJetMCP", "sparse for mcp jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); registry.add("hJetEWSMCP", "sparse for mcp event-wise subtracted jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); } - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "jetFinder workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "jetFinder workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } - o2::aod::EMCALClusterDefinition clusterDefinition = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); o2::framework::expressions::Filter collisionFilter = (nabs(o2::aod::jcollision::posZ) < vertexZCut && o2::aod::jcollision::centFT0M >= centralityMin && o2::aod::jcollision::centFT0M < centralityMax && o2::aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax); // should we add a posZ vtx cut here or leave it to analysers? o2::framework::expressions::Filter mcCollisionFilter = (nabs(o2::aod::jmccollision::posZ) < vertexZCut); o2::framework::expressions::Filter trackCuts = (o2::aod::jtrack::pt >= trackPtMin && o2::aod::jtrack::pt < trackPtMax && o2::aod::jtrack::eta >= trackEtaMin && o2::aod::jtrack::eta <= trackEtaMax && o2::aod::jtrack::phi >= trackPhiMin && o2::aod::jtrack::phi <= trackPhiMax); // do we need eta cut both here and in globalselection? o2::framework::expressions::Filter partCuts = (o2::aod::jmcparticle::pt >= trackPtMin && o2::aod::jmcparticle::pt < trackPtMax && o2::aod::jmcparticle::eta >= trackEtaMin && o2::aod::jmcparticle::eta <= trackEtaMax && o2::aod::jmcparticle::phi >= trackPhiMin && o2::aod::jmcparticle::phi <= trackPhiMax); - o2::framework::expressions::Filter clusterFilter = (o2::aod::jcluster::definition == static_cast(clusterDefinition) && o2::aod::jcluster::eta >= clusterEtaMin && o2::aod::jcluster::eta <= clusterEtaMax && o2::aod::jcluster::phi >= clusterPhiMin && o2::aod::jcluster::phi <= clusterPhiMax && o2::aod::jcluster::energy >= clusterEnergyMin && o2::aod::jcluster::time > clusterTimeMin && o2::aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && o2::aod::jcluster::isExotic != true)); + o2::framework::expressions::Filter clusterFilter = (o2::aod::jcluster::eta >= clusterEtaMin && o2::aod::jcluster::eta <= clusterEtaMax && o2::aod::jcluster::phi >= clusterPhiMin && o2::aod::jcluster::phi <= clusterPhiMax && o2::aod::jcluster::energy >= clusterEnergyMin && o2::aod::jcluster::time > clusterTimeMin && o2::aod::jcluster::time < clusterTimeMax && (!clusterRejectExotics || o2::aod::jcluster::isExotic != true)); void processChargedJets(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks) @@ -188,7 +195,7 @@ struct JetFinderTask { return; } inputParticles.clear(); - jetfindingutilities::analyseTracks, o2::soa::Filtered::iterator>(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning); + jetfindingutilities::analyseTracks, o2::soa::Filtered::iterator>(inputParticles, tracks, trackSelection); jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, fillTHnSparse ? registry.get(HIST("hJet")) : std::shared_ptr(nullptr), fillTHnSparse); } @@ -201,7 +208,7 @@ struct JetFinderTask { return; } inputParticles.clear(); - jetfindingutilities::analyseTracks, o2::soa::Filtered::iterator>(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning); + jetfindingutilities::analyseTracks, o2::soa::Filtered::iterator>(inputParticles, tracks, trackSelection); jetfindingutilities::findJets(jetFinder, inputParticles, jetEWSPtMin, jetEWSPtMax, jetRadius, jetAreaFractionMin, collision, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, fillTHnSparse ? registry.get(HIST("hJetEWS")) : std::shared_ptr(nullptr), fillTHnSparse); } @@ -213,9 +220,13 @@ struct JetFinderTask { if ((doEMCALEventSelection && !jetderiveddatautilities::eventEMCAL(collision)) || !jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, "CBT_calo") || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - inputParticles.clear(); - jetfindingutilities::analyseClusters(inputParticles, &clusters); - jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, fillTHnSparse ? registry.get(HIST("hJet")) : std::shared_ptr(nullptr), fillTHnSparse); + for (auto const& clusterDefinition : clusterDefinitionsVec) { + for (auto const& hadronicCorrectionType : hadronicCorrectionTypesVec) { + inputParticles.clear(); + jetfindingutilities::analyseClusters(inputParticles, clusters, clusterDefinition, hadronicCorrectionType); + jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, fillTHnSparse ? registry.get(HIST("hJet")) : std::shared_ptr(nullptr), fillTHnSparse); + } + } } PROCESS_SWITCH(JetFinderTask, processNeutralJets, "Data and reco level jet finding for neutral jets", false); @@ -226,16 +237,20 @@ struct JetFinderTask { if ((doEMCALEventSelection && !jetderiveddatautilities::eventEMCAL(collision)) || !jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, "CBT_calo") || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - inputParticles.clear(); - jetfindingutilities::analyseTracks, o2::soa::Filtered::iterator>(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning); - jetfindingutilities::analyseClusters(inputParticles, &clusters, hadronicCorrectionType); - jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, fillTHnSparse ? registry.get(HIST("hJet")) : std::shared_ptr(nullptr), fillTHnSparse); + for (auto const& clusterDefinition : clusterDefinitionsVec) { + for (auto const& hadronicCorrectionType : hadronicCorrectionTypesVec) { + inputParticles.clear(); + jetfindingutilities::analyseTracks, o2::soa::Filtered::iterator>(inputParticles, tracks, trackSelection); + jetfindingutilities::analyseClusters(inputParticles, clusters, clusterDefinition, hadronicCorrectionType); + jetfindingutilities::findJets(jetFinder, inputParticles, jetPtMin, jetPtMax, jetRadius, jetAreaFractionMin, collision, jetsTable, constituentsTable, fillTHnSparse ? registry.get(HIST("hJet")) : std::shared_ptr(nullptr), fillTHnSparse); + } + } } PROCESS_SWITCH(JetFinderTask, processFullJets, "Data and reco level jet finding for full and neutral jets", false); void processParticleLevelChargedJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } inputParticles.clear(); @@ -246,7 +261,7 @@ struct JetFinderTask { void processParticleLevelChargedEvtWiseSubJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } inputParticles.clear(); @@ -257,7 +272,7 @@ struct JetFinderTask { void processParticleLevelNeutralJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { return; } inputParticles.clear(); @@ -268,7 +283,7 @@ struct JetFinderTask { void processParticleLevelFullJets(o2::soa::Filtered::iterator const& mcCollision, o2::soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections, "CBT_calo")) { return; } inputParticles.clear(); diff --git a/PWGJE/JetFinders/jetFinderHF.h b/PWGJE/JetFinders/jetFinderHF.h index 5f78d902f3b..3016cdb5265 100644 --- a/PWGJE/JetFinders/jetFinderHF.h +++ b/PWGJE/JetFinders/jetFinderHF.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include // IWYU pragma: export @@ -45,6 +44,8 @@ #include #include +#include + template struct JetFinderHFTask { o2::framework::Produces jetsTable; @@ -71,9 +72,6 @@ struct JetFinderHFTask { o2::framework::Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; o2::framework::Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; o2::framework::Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; - o2::framework::Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; - o2::framework::Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - o2::framework::Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; o2::framework::Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; o2::framework::Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; @@ -91,8 +89,8 @@ struct JetFinderHFTask { // HF candidate level configurables o2::framework::Configurable candPtMin{"candPtMin", 0.0, "minimum candidate pT"}; o2::framework::Configurable candPtMax{"candPtMax", 100.0, "maximum candidate pT"}; - o2::framework::Configurable candYMin{"candYMin", -0.8, "minimum candidate eta"}; - o2::framework::Configurable candYMax{"candYMax", 0.8, "maximum candidate eta"}; + o2::framework::Configurable candYMin{"candYMin", -0.8, "minimum candidate rapidity"}; + o2::framework::Configurable candYMax{"candYMax", 0.8, "maximum candidate rapidity"}; // HF candidiate selection configurables o2::framework::Configurable rejectBackgroundMCDCandidates{"rejectBackgroundMCDCandidates", false, "reject background HF candidates at MC detector level"}; o2::framework::Configurable rejectIncorrectDecaysMCP{"rejectIncorrectDecaysMCP", true, "reject HF paticles decaying to the non-analysed decay channels at MC generator level"}; @@ -101,6 +99,8 @@ struct JetFinderHFTask { o2::framework::Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; o2::framework::Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; o2::framework::Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; + o2::framework::Configurable jetPhiMin{"jetPhiMin", -99.0, "minimum jet phi"}; + o2::framework::Configurable jetPhiMax{"jetPhiMax", 99.0, "maximum jet phi"}; o2::framework::Configurable jetEWSPtMin{"jetEWSPtMin", 0.0, "minimum event-wise subtracted jet pT"}; o2::framework::Configurable jetEWSPtMax{"jetEWSPtMax", 1000.0, "maximum event-wise subtracted jet pT"}; o2::framework::Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; @@ -126,17 +126,32 @@ struct JetFinderHFTask { std::vector triggerMaskBits; + o2::aod::EMCALClusterDefinition clusterDefinition; + void init(o2::framework::InitContext const&) { trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); particleSelection = static_cast(particleSelections); + clusterDefinition = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); jetFinder.etaMin = trackEtaMin; jetFinder.etaMax = trackEtaMax; jetFinder.jetPtMin = jetPtMin; jetFinder.jetPtMax = jetPtMax; + jetFinder.phiMin = trackPhiMin; + jetFinder.phiMax = trackPhiMax; + if (trackPhiMin < -98.0) { + jetFinder.phiMin = -1.0 * M_PI; + jetFinder.phiMax = 2.0 * M_PI; + } + jetFinder.jetPhiMin = jetPhiMin; + jetFinder.jetPhiMax = jetPhiMax; + if (jetPhiMin < -98.0) { + jetFinder.jetPhiMin = -1.0 * M_PI; + jetFinder.jetPhiMax = 2.0 * M_PI; + } jetFinder.jetEtaMin = jetEtaMin; jetFinder.jetEtaMax = jetEtaMax; if (jetEtaMin < -98.0) { @@ -167,23 +182,13 @@ struct JetFinderHFTask { registry.add("hJet", "sparse for data or mcd jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); registry.add("hJetMCP", "sparse for mcp jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "jetFinderHF workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "jetFinderHF workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } - o2::aod::EMCALClusterDefinition clusterDefinition = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); o2::framework::expressions::Filter collisionFilter = (nabs(o2::aod::jcollision::posZ) < vertexZCut && o2::aod::jcollision::centFT0M >= centralityMin && o2::aod::jcollision::centFT0M < centralityMax && o2::aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax); o2::framework::expressions::Filter mcCollisionFilter = (nabs(o2::aod::jmccollision::posZ) < vertexZCut); o2::framework::expressions::Filter trackCuts = (o2::aod::jtrack::pt >= trackPtMin && o2::aod::jtrack::pt < trackPtMax && o2::aod::jtrack::eta >= trackEtaMin && o2::aod::jtrack::eta <= trackEtaMax && o2::aod::jtrack::phi >= trackPhiMin && o2::aod::jtrack::phi <= trackPhiMax); o2::framework::expressions::Filter partCuts = (o2::aod::jmcparticle::pt >= trackPtMin && o2::aod::jmcparticle::pt < trackPtMax && o2::aod::jmcparticle::eta >= trackEtaMin && o2::aod::jmcparticle::eta <= trackEtaMax && o2::aod::jmcparticle::phi >= trackPhiMin && o2::aod::jmcparticle::phi <= trackPhiMax); - o2::framework::expressions::Filter clusterFilter = (o2::aod::jcluster::definition == static_cast(clusterDefinition) && o2::aod::jcluster::eta >= clusterEtaMin && o2::aod::jcluster::eta <= clusterEtaMax && o2::aod::jcluster::phi >= clusterPhiMin && o2::aod::jcluster::phi <= clusterPhiMax && o2::aod::jcluster::energy >= clusterEnergyMin && o2::aod::jcluster::time > clusterTimeMin && o2::aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && o2::aod::jcluster::isExotic != true)); + o2::framework::expressions::Filter clusterFilter = (o2::aod::jcluster::definition == static_cast(clusterDefinition) && o2::aod::jcluster::eta >= clusterEtaMin && o2::aod::jcluster::eta <= clusterEtaMax && o2::aod::jcluster::phi >= clusterPhiMin && o2::aod::jcluster::phi <= clusterPhiMax && o2::aod::jcluster::energy >= clusterEnergyMin && o2::aod::jcluster::time > clusterTimeMin && o2::aod::jcluster::time < clusterTimeMax && (!clusterRejectExotics || o2::aod::jcluster::isExotic != true)); // o2::framework::expressions::Filter candidateCuts = (o2::aod::hfcand::pt >= candPtMin && o2::aod::hfcand::pt < candPtMax && o2::aod::hfcand::y >= candYMin && o2::aod::hfcand::y < candYMax); o2::framework::PresliceOptional> perD0Candidate = o2::aod::bkgd0::candidateId; @@ -206,7 +211,7 @@ struct JetFinderHFTask { o2::framework::PresliceOptional> perDielectronMcCandidate = o2::aod::bkgdielectronmc::candidateId; // function that generalically processes Data and reco level events - template + 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, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { @@ -214,21 +219,19 @@ struct JetFinderHFTask { } inputParticles.clear(); - if constexpr (jetcandidateutilities::isCandidate()) { + if constexpr (!isMC) { if (!jetfindingutilities::analyseCandidate(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax)) { return; } - } - - if constexpr (jetcandidateutilities::isMcCandidate()) { + } else { if (!jetfindingutilities::analyseCandidateMC(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates)) { return; } } if constexpr (isEvtWiseSub) { - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection); } else { - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); } jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true); } @@ -237,7 +240,7 @@ struct JetFinderHFTask { template void analyseMCP(T const& mcCollision, U const& particles, V const& candidate, M& jetsTableInput, N& constituentsTableInput, int jetTypeParticleLevel, float minJetPt, float maxJetPt) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } @@ -265,7 +268,7 @@ struct JetFinderHFTask { void processChargedJetsData(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableData const& candidates) { for (typename CandidateTableData::iterator const& candidate : candidates) { // why can the type not be auto? try const auto - analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedJetsData, "charged hf jet finding on data", false); @@ -273,7 +276,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsData(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableData const& candidates) { for (typename CandidateTableData::iterator const& candidate : candidates) { - analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsData, "charged hf jet finding on data with event-wise constituent subtraction", false); @@ -281,7 +284,7 @@ struct JetFinderHFTask { void processChargedJetsMCD(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableMCD const& candidates) { for (typename CandidateTableMCD::iterator const& candidate : candidates) { - analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedJetsMCD, "charged hf jet finding on MC detector level", false); @@ -289,7 +292,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsMCD(o2::soa::Filtered::iterator const& collision, o2::soa::Filtered const& tracks, CandidateTableMCD const& candidates) { for (typename CandidateTableMCD::iterator const& candidate : candidates) { - analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDsCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perXicToXiPiPiCandidate, 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/jetFinderHFHFBar.h b/PWGJE/JetFinders/jetFinderHFHFBar.h index 9b36af83e6c..ec4cfa9d94c 100644 --- a/PWGJE/JetFinders/jetFinderHFHFBar.h +++ b/PWGJE/JetFinders/jetFinderHFHFBar.h @@ -14,8 +14,8 @@ /// \author Nima Zardoshti /// \author Jochen Klein -#ifndef PWGJE_JETFINDERS_JETFINDERHF_H_ -#define PWGJE_JETFINDERS_JETFINDERHF_H_ +#ifndef PWGJE_JETFINDERS_JETFINDERHFHFBAR_H_ +#define PWGJE_JETFINDERS_JETFINDERHFHFBAR_H_ #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" @@ -32,7 +32,6 @@ #include #include #include -#include #include #include // IWYU pragma: export @@ -45,6 +44,8 @@ #include #include +#include + template struct JetFinderHFHFBarTask { o2::framework::Produces jetsTable; @@ -71,9 +72,6 @@ struct JetFinderHFHFBarTask { o2::framework::Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; o2::framework::Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; o2::framework::Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; - o2::framework::Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; - o2::framework::Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - o2::framework::Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; o2::framework::Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; o2::framework::Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; @@ -101,6 +99,8 @@ struct JetFinderHFHFBarTask { o2::framework::Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; o2::framework::Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; o2::framework::Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; + o2::framework::Configurable jetPhiMin{"jetPhiMin", -99.0, "minimum jet phi"}; + o2::framework::Configurable jetPhiMax{"jetPhiMax", 99.0, "maximum jet phi"}; o2::framework::Configurable jetEWSPtMin{"jetEWSPtMin", 0.0, "minimum event-wise subtracted jet pT"}; o2::framework::Configurable jetEWSPtMax{"jetEWSPtMax", 1000.0, "maximum event-wise subtracted jet pT"}; o2::framework::Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; @@ -137,6 +137,18 @@ struct JetFinderHFHFBarTask { jetFinder.etaMax = trackEtaMax; jetFinder.jetPtMin = jetPtMin; jetFinder.jetPtMax = jetPtMax; + jetFinder.phiMin = trackPhiMin; + jetFinder.phiMax = trackPhiMax; + if (trackPhiMin < -98.0) { + jetFinder.phiMin = -1.0 * M_PI; + jetFinder.phiMax = 2.0 * M_PI; + } + jetFinder.jetPhiMin = jetPhiMin; + jetFinder.jetPhiMax = jetPhiMax; + if (jetPhiMin < -98.0) { + jetFinder.jetPhiMin = -1.0 * M_PI; + jetFinder.jetPhiMax = 2.0 * M_PI; + } jetFinder.jetEtaMin = jetEtaMin; jetFinder.jetEtaMax = jetEtaMax; if (jetEtaMin < -98.0) { @@ -167,15 +179,6 @@ struct JetFinderHFHFBarTask { registry.add("hJet", "sparse for data or mcd jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); registry.add("hJetMCP", "sparse for mcp jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "jetFinderHF workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "jetFinderHF workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } o2::aod::EMCALClusterDefinition clusterDefinition = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); @@ -206,7 +209,7 @@ struct JetFinderHFHFBarTask { o2::framework::PresliceOptional> perDielectronMcCandidate = o2::aod::bkgdielectronmc::candidateId; // function that generalically processes Data and reco level events - template + template void analyseCharged(T const& collision, U const& tracks, V const& candidate, V const& candidateBar, M& jetsTableInput, N& constituentsTableInput, O& /*originalTracks*/, float minJetPt, float maxJetPt) { if (candidate.globalIndex() == candidateBar.globalIndex() || candidate.candidateSelFlag() == candidateBar.candidateSelFlag()) { @@ -222,18 +225,16 @@ struct JetFinderHFHFBarTask { } inputParticles.clear(); - if constexpr (jetcandidateutilities::isCandidate()) { + if constexpr (!isMC) { if (!jetfindingutilities::analyseCandidate(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax) || !jetfindingutilities::analyseCandidate(inputParticles, candidateBar, candPtMin, candPtMax, candYMin, candYMax)) { return; } - } - - if constexpr (jetcandidateutilities::isMcCandidate()) { + } else { if (!jetfindingutilities::analyseCandidateMC(inputParticles, candidate, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates) || !jetfindingutilities::analyseCandidateMC(inputParticles, candidateBar, candPtMin, candPtMax, candYMin, candYMax, rejectBackgroundMCDCandidates)) { return; } } - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, true); } @@ -250,7 +251,7 @@ struct JetFinderHFHFBarTask { return; } } - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } @@ -280,7 +281,7 @@ struct JetFinderHFHFBarTask { for (; candidateBarIterator != candidates.end(); ++candidateBarIterator) { typename CandidateTableData::iterator const& candidate = *candidateIterator; typename CandidateTableData::iterator const& candidateBar = *candidateBarIterator; - analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } } @@ -294,7 +295,7 @@ struct JetFinderHFHFBarTask { for (; candidateBarIterator != candidates.end(); ++candidateBarIterator) { typename CandidateTableMCD::iterator const& candidate = *candidateIterator; typename CandidateTableMCD::iterator const& candidateBar = *candidateBarIterator; - analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); + analyseCharged(collision, tracks, candidate, candidateBar, jetsTable, constituentsTable, tracks, jetPtMin, jetPtMax); } } } @@ -317,4 +318,4 @@ struct JetFinderHFHFBarTask { PROCESS_SWITCH(JetFinderHFHFBarTask, processChargedJetsMCP, "hf jet finding on MC particle level", false); }; -#endif // PWGJE_JETFINDERS_JETFINDERHF_H_ +#endif // PWGJE_JETFINDERS_JETFINDERHFHFBAR_H_ diff --git a/PWGJE/JetFinders/jetFinderV0.h b/PWGJE/JetFinders/jetFinderV0.h index e90bbcb97bc..14c2f977ada 100644 --- a/PWGJE/JetFinders/jetFinderV0.h +++ b/PWGJE/JetFinders/jetFinderV0.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include // IWYU pragma: export @@ -41,6 +40,8 @@ #include #include +#include + template struct JetFinderV0Task { @@ -66,23 +67,22 @@ struct JetFinderV0Task { o2::framework::Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; o2::framework::Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; o2::framework::Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; - o2::framework::Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; - o2::framework::Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - o2::framework::Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; o2::framework::Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; o2::framework::Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // V0 candidate level configurables o2::framework::Configurable candPtMin{"candPtMin", 0.0, "minimum candidate pT"}; o2::framework::Configurable candPtMax{"candPtMax", 100.0, "maximum candidate pT"}; - o2::framework::Configurable candYMin{"candYMin", -0.8, "minimum candidate eta"}; - o2::framework::Configurable candYMax{"candYMax", 0.8, "maximum candidate eta"}; + o2::framework::Configurable candYMin{"candYMin", -0.8, "minimum candidate rapidity"}; + o2::framework::Configurable candYMax{"candYMax", 0.8, "maximum candidate rapidity"}; o2::framework::Configurable candPDG{"candPDG", 310, "candidate PDG for mass in clustering"}; // jet level configurables o2::framework::Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; o2::framework::Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; o2::framework::Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; + o2::framework::Configurable jetPhiMin{"jetPhiMin", -99.0, "minimum jet phi"}; + o2::framework::Configurable jetPhiMax{"jetPhiMax", 99.0, "maximum jet phi"}; o2::framework::Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; o2::framework::Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; o2::framework::Configurable jetTypeParticleLevel{"jetTypeParticleLevel", 1, "Type of stored jets. 0 = full, 1 = charged, 2 = neutral"}; @@ -121,6 +121,18 @@ struct JetFinderV0Task { jetFinder.etaMax = trackEtaMax; jetFinder.jetPtMin = jetPtMin; jetFinder.jetPtMax = jetPtMax; + jetFinder.phiMin = trackPhiMin; + jetFinder.phiMax = trackPhiMax; + if (trackPhiMin < -98.0) { + jetFinder.phiMin = -1.0 * M_PI; + jetFinder.phiMax = 2.0 * M_PI; + } + jetFinder.jetPhiMin = jetPhiMin; + jetFinder.jetPhiMax = jetPhiMax; + if (jetPhiMin < -98.0) { + jetFinder.jetPhiMin = -1.0 * M_PI; + jetFinder.jetPhiMax = 2.0 * M_PI; + } jetFinder.jetEtaMin = jetEtaMin; jetFinder.jetEtaMax = jetEtaMax; if (jetEtaMin < -98.0) { @@ -158,15 +170,6 @@ struct JetFinderV0Task { registry.add("hJet", "sparse for data or mcd jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); registry.add("hJetMCP", "sparse for mcp jets", {o2::framework::HistType::kTHnD, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "jetFinderV0 workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "jetFinderV0 workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } o2::framework::expressions::Filter collisionFilter = (nabs(o2::aod::jcollision::posZ) < vertexZCut && o2::aod::jcollision::centFT0M >= centralityMin && o2::aod::jcollision::centFT0M < centralityMax && o2::aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax); @@ -195,7 +198,7 @@ struct JetFinderV0Task { } } */ - jetfindingutilities::analyseTracksMultipleCandidates(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning, candidates); + jetfindingutilities::analyseTracksMultipleCandidates(inputParticles, tracks, trackSelection, candidates); jetfindingutilities::findJets(jetFinder, inputParticles, minJetPt, maxJetPt, jetRadius, jetAreaFractionMin, collision, jetsTableInput, constituentsTableInput, registry.get(HIST("hJet")), fillTHnSparse, saveJetsWithCandidatesOnly); } @@ -204,7 +207,7 @@ struct JetFinderV0Task { void analyseMCP(T const& mcCollision, U const& particles, V const& candidates, int jetTypeParticleLevel, float minJetPt, float maxJetPt) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } diff --git a/PWGJE/TableProducer/CMakeLists.txt b/PWGJE/TableProducer/CMakeLists.txt index c56719d652b..f0d91e9c98b 100644 --- a/PWGJE/TableProducer/CMakeLists.txt +++ b/PWGJE/TableProducer/CMakeLists.txt @@ -93,7 +93,7 @@ endif() o2physics_add_dpl_workflow(emcal-correction-task SOURCES emcalCorrectionTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2::EMCALBase O2::EMCALReconstruction O2::EMCALCalibration O2Physics::PWGJECore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2::EMCALBase O2::EMCALReconstruction O2::EMCALCalibration O2Physics::PWGJECore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(emcal-matchedtracks-writer diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h index 504219671fd..d1adaf02e28 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.h @@ -34,7 +34,8 @@ struct JetMatchingDuplicates { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -49,6 +50,12 @@ struct JetMatchingDuplicates { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetCollisions const& collisions, @@ -72,7 +79,7 @@ struct JetMatchingDuplicates { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, collision.globalIndex()); // initialise template parameters as false since even if they are Mc we are not matching between detector and particle level - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracks, tracks, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracks, tracks, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h index 82d93552c6e..afc68acaa6b 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.h @@ -41,7 +41,8 @@ struct JetSubstructureMatching { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Configurable requireGeoMatchedJets{"requireGeoMatchedJets", false, "require jets are geo matched as well"}; o2::framework::Configurable requirePtMatchedJets{"requirePtMatchedJets", false, "require jets are pT matched as well"}; @@ -52,6 +53,12 @@ struct JetSubstructureMatching { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } o2::framework::PresliceOptional BaseSplittingsPerBaseJetInclusive = o2::aod::chargedmcdetectorlevelsplitting::jetId; @@ -98,14 +105,14 @@ struct JetSubstructureMatching { // workaround till binding nodes can be passed as template arguments template - auto slicedPerJetForMatching(T const& table, U const& jet, V const& perIncluisveJet, M const& perD0Jet, N const& perDplusJet, O const& perDsJet, P const& perDstarJet, Q const& perLcJet, R const& perB0Jet, S const& perBplusJet, A const& perXicToXiPiPiJet, B const& perDielectronJet) + auto slicedPerJetForMatching(T const& table, U const& jet, V const& perInclusiveJet, M const& perD0Jet, N const& perDplusJet, O const& perDsJet, P const& perDstarJet, Q const& perLcJet, R const& perB0Jet, S const& perBplusJet, A const& perXicToXiPiPiJet, B const& perDielectronJet) { if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perDsJet, perDstarJet, perLcJet, perB0Jet, perBplusJet, perXicToXiPiPiJet); } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { return jetdqutilities::slicedPerDielectronJet(table, jet, perDielectronJet); } else { - return table.sliceBy(perIncluisveJet, jet.globalIndex()); + return table.sliceBy(perInclusiveJet, jet.globalIndex()); } } @@ -218,7 +225,7 @@ struct JetSubstructureMatching { jetBaseSplittingsMap[jetBaseSplitting.globalIndex()] = baseSplittingIndex; baseSplittingIndex++; } - jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidatesBase, tracksBase, clustersBase, candidatesTag, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidatesBase, tracksBase, clustersBase, candidatesTag, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); // auto const& jetBasePairs = jetsBasePairs.sliceBy(BasePairsPerBaseJet, jetBase.globalIndex()); auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetDs, BasePairsPerBaseJetDstar, BasePairsPerBaseJetLc, BasePairsPerBaseJetB0, BasePairsPerBaseJetBplus, BasePairsPerBaseJetXicToXiPiPi, BasePairsPerBaseJetDielectron); int basePairIndex = 0; diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h index bcce8a6103f..6075d86cd55 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.h @@ -42,7 +42,8 @@ struct JetSubstructureMatchingSub { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Configurable requireGeoMatchedJets{"requireGeoMatchedJets", false, "require jets are geo matched as well"}; o2::framework::Configurable requirePtMatchedJets{"requirePtMatchedJets", false, "require jets are pT matched as well"}; @@ -53,6 +54,12 @@ struct JetSubstructureMatchingSub { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } o2::framework::PresliceOptional BaseSplittingsPerBaseJetInclusive = o2::aod::chargedsplitting::jetId; @@ -219,7 +226,7 @@ struct JetSubstructureMatchingSub { jetBaseSplittingsMap[jetBaseSplitting.globalIndex()] = baseSplittingIndex; baseSplittingIndex++; } - jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidates, tracksBase, clustersBase, candidates, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidates, tracksBase, clustersBase, candidates, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); // auto const& jetBasePairs = jetsBasePairs.sliceBy(BasePairsPerBaseJet, jetBase.globalIndex()); auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetDs, BasePairsPerBaseJetDstar, BasePairsPerBaseJetLc, BasePairsPerBaseJetB0, BasePairsPerBaseJetBplus, BasePairsPerBaseJetXicToXiPiPi, BasePairsPerBaseJetDielectron); int basePairIndex = 0; diff --git a/PWGJE/TableProducer/Matching/jetMatchingMC.h b/PWGJE/TableProducer/Matching/jetMatchingMC.h index 10257b94ba7..95aceb4f6ed 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMC.h +++ b/PWGJE/TableProducer/Matching/jetMatchingMC.h @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -37,7 +38,8 @@ struct JetMatchingMc { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -54,6 +56,12 @@ struct JetMatchingMc { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetMcCollisions const& mcCollisions, o2::aod::JetCollisionsMCD const& collisions, @@ -84,7 +92,7 @@ struct JetMatchingMc { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, jetsBaseIsMc ? mcCollision.globalIndex() : collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, jetsTagIsMc ? mcCollision.globalIndex() : collision.globalIndex()); - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidatesBase, tracks, clusters, candidatesTag, particles, particles, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidatesBase, tracks, clusters, candidatesTag, particles, particles, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSub.h b/PWGJE/TableProducer/Matching/jetMatchingMCSub.h index 51a0b3d8424..395783865b4 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSub.h +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSub.h @@ -33,7 +33,8 @@ struct JetMatchingMcSub { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -48,6 +49,12 @@ struct JetMatchingMcSub { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetCollisions const& collisions, @@ -73,7 +80,7 @@ struct JetMatchingMcSub { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, collision.globalIndex()); - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/Matching/jetMatchingSub.h b/PWGJE/TableProducer/Matching/jetMatchingSub.h index 0aa035794c3..b5d1db2491c 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSub.h +++ b/PWGJE/TableProducer/Matching/jetMatchingSub.h @@ -34,7 +34,8 @@ struct JetMatchingSub { o2::framework::Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; o2::framework::Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; o2::framework::Configurable doMatchingHf{"doMatchingHf", false, "Enable HF matching"}; - o2::framework::Configurable maxMatchingDistance{"maxMatchingDistance", 0.24f, "Max matching distance"}; + o2::framework::Configurable> jetRadiiForMatchingDistance{"jetRadiiForMatchingDistance", {0.2, 0.3, 0.4, 0.5, 0.6}, "Jet R values for per-R matching distance"}; + o2::framework::Configurable> maxMatchingDistancePerJetR{"maxMatchingDistancePerJetR", {0.12, 0.18, 0.24, 0.30, 0.36}, "Max matching distance (0.6*R, see ALICE-AN-852) for each R in jetRadiiForMatchingDistance"}; o2::framework::Configurable minPtFraction{"minPtFraction", 0.5f, "Minimum pt fraction for pt matching"}; o2::framework::Produces jetsBasetoTagMatchingTable; @@ -49,6 +50,12 @@ struct JetMatchingSub { void init(o2::framework::InitContext const&) { + if (jetRadiiForMatchingDistance->empty() || maxMatchingDistancePerJetR->empty()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must not be empty"); + } + if (jetRadiiForMatchingDistance->size() != maxMatchingDistancePerJetR->size()) { + LOGP(fatal, "jetRadiiForMatchingDistance and maxMatchingDistancePerJetR must have the same number of entries"); + } } void processJets(o2::aod::JetCollisions const& collisions, @@ -72,7 +79,7 @@ struct JetMatchingSub { const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, collision.globalIndex()); const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, collision.globalIndex()); - jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); + jetmatchingutilities::doAllMatching(jetsBasePerColl, jetsTagPerColl, jetsBasetoTagMatchingGeo, jetsBasetoTagMatchingPt, jetsBasetoTagMatchingHF, jetsTagtoBaseMatchingGeo, jetsTagtoBaseMatchingPt, jetsTagtoBaseMatchingHF, candidates, tracks, tracks, candidates, tracksSub, tracksSub, doMatchingGeo, doMatchingHf, doMatchingPt, minPtFraction, jetRadiiForMatchingDistance, maxMatchingDistancePerJetR); } for (auto i = 0; i < jetsBase.size(); ++i) { diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index 4a8b0ca0366..6a482f981df 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -13,9 +13,6 @@ // /// \author Nima Zardoshti -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGJE/Core/JetDQUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetV0Utilities.h" @@ -25,10 +22,15 @@ #include "PWGJE/DataModel/JetReducedDataDQ.h" #include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataV0.h" +// +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" #include "PWGUD/Core/SGCutParHolder.h" #include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UDHelpers.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" @@ -40,23 +42,26 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "ReconstructionDataFormats/Vertex.h" +#include #include #include +#include +#include +#include #include +#include #include #include +#include #include #include +#include + +#include #include #include +#include #include #include #include @@ -76,9 +81,9 @@ struct JetDerivedDataProducerTask { Produces jBCsTable; Produces jBCParentIndexTable; Produces jCollisionsTable; + Produces jCollisionUPCsTable; Produces jCollisionMcInfosTable; Produces jCollisionsParentIndexTable; - Produces jCollisionsBunchCrossingIndexTable; Produces jCollisionsEMCalLabelTable; Produces jMcCollisionsLabelTable; Produces jMcCollisionsTable; @@ -161,6 +166,11 @@ struct JetDerivedDataProducerTask { Configurable includeHadronicRate{"includeHadronicRate", true, "fill the collision information with the hadronic rate"}; Configurable includeUpcs{"includeUpcs", true, "include option to identify UPC events"}; Configurable v0ChargedDecaysOnly{"v0ChargedDecaysOnly", true, "store V0s (at particle-level) only if they decay to charged particles"}; + Configurable isMCGenOnly{"isMCGenOnly", false, "analysis is run over mcGen only"}; + + o2::framework::Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; + o2::framework::Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; + o2::framework::Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; } config; struct : PresliceGroup { @@ -184,14 +194,17 @@ struct JetDerivedDataProducerTask { std::vector amplitudesFDDA; std::vector amplitudesFDDC; - std::vector trackWeightedMCSelection; + std::vector trackMCSelection; + std::vector bcSelMapping; std::vector bcRctMapping; ctpRateFetcher rateFetcher; int runNumber; float hadronicRate; bool withCollisionAssociator; + TRandom3 trackingEfficiencyRandomNumber; + void init(InitContext const&) { hadronicRate = -1.0; @@ -213,16 +226,44 @@ struct JetDerivedDataProducerTask { upcCuts.SetNTracks(config.upcMinNTracks, config.upcMaxNTracks); upcCuts.SetMaxFITtime(config.upcMaxFITTime); upcCuts.SetFITAmpLimits({config.upcMaxFV0AAmplitude, config.upcMaxFT0AAmplitude, config.upcMaxFT0CAmplitude, config.upcMaxFDDAAmplitude, config.upcMaxFDDCAmplitude}); + + if (config.applyTrackingEfficiency) { + trackingEfficiencyRandomNumber.SetSeed(0); + if (config.trackingEfficiencyPtBinning->size() < 2) { + LOGP(fatal, "jetFinder workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); + } + if (config.trackingEfficiency->size() + 1 != config.trackingEfficiencyPtBinning->size()) { + LOGP(fatal, "jetFinder workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); + } + } } void processClearMaps(aod::Collisions const& collisions, aod::Tracks const& tracks) { trackCollisionMapping.clear(); - trackWeightedMCSelection.clear(); - trackWeightedMCSelection.resize(tracks.size(), true); - if (!doprocessMcCollisionLabels) { + trackMCSelection.clear(); + trackMCSelection.resize(tracks.size(), true); + if (config.applyTrackingEfficiency) { + std::vector trackingEfficiencyPtBinningVec = config.trackingEfficiencyPtBinning; + std::vector trackingEfficiencyVec = config.trackingEfficiency; + for (const auto& track : tracks) { + auto iter = std::upper_bound(trackingEfficiencyPtBinningVec.begin(), trackingEfficiencyPtBinningVec.end(), track.pt()); + if (iter != trackingEfficiencyPtBinningVec.begin() && iter != trackingEfficiencyPtBinningVec.end()) { + std::size_t index = std::distance(trackingEfficiencyPtBinningVec.begin(), iter) - 1; + if (trackingEfficiencyRandomNumber.Rndm() > trackingEfficiencyVec[index]) { + trackMCSelection[track.globalIndex()] = false; + } + } + } + } + if (!doprocessMcCollisionLabels || !doprocessEMCalCollisionLabels) { for (int i = 0; i < collisions.size(); i++) { - products.jCollisionMcInfosTable(-1.0, jetderiveddatautilities::JCollisionSubGeneratorId::none); // fill a dummy weights table if not MC + if (!doprocessMcCollisionLabels) { + products.jCollisionMcInfosTable(-1.0, jetderiveddatautilities::JCollisionSubGeneratorId::none); // fill a dummy weights table if not MC + } + if (!doprocessEMCalCollisionLabels) { + products.jCollisionsEMCalLabelTable(false, false); + } } } } @@ -230,11 +271,14 @@ struct JetDerivedDataProducerTask { void processBunchCrossings(soa::Join const& bcs) { + bcSelMapping.clear(); + bcSelMapping.resize(bcs.size(), ~uint16_t{0}); bcRctMapping.clear(); bcRctMapping.resize(bcs.size(), ~uint32_t{0}); for (const auto& bc : bcs) { - products.jBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp(), bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); + products.jBCsTable(bc.runNumber(), bc.globalBC(), bc.triggerMask(), bc.timestamp(), bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); products.jBCParentIndexTable(bc.globalIndex()); + bcSelMapping[bc.globalIndex()] = jetderiveddatautilities::setMCEventSelectionBit(bc); bcRctMapping[bc.globalIndex()] = bc.rct_raw(); } } @@ -242,10 +286,12 @@ struct JetDerivedDataProducerTask { void processBunchCrossingsWithoutSels(soa::Join const& bcs) { + bcSelMapping.clear(); + bcSelMapping.resize(bcs.size(), ~uint16_t{0}); bcRctMapping.clear(); bcRctMapping.resize(bcs.size(), ~uint32_t{0}); for (const auto& bc : bcs) { - products.jBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp(), ~uint32_t{0}, ~uint64_t{0}, ~uint32_t{0}); + products.jBCsTable(bc.runNumber(), bc.globalBC(), bc.triggerMask(), bc.timestamp(), ~uint32_t{0}, ~uint64_t{0}, ~uint32_t{0}); products.jBCParentIndexTable(bc.globalIndex()); } } @@ -286,11 +332,11 @@ struct JetDerivedDataProducerTask { amplitudesFDDC.clear(); } } + products.jCollisionUPCsTable(amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC); } - products.jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.centFV0A(), -1.0, collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.centFT0CVariant1(), amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC, hadronicRate, collision.trackOccupancyInTimeRange(), collision.alias_raw(), jetderiveddatautilities::setEventSelectionBit(collision, upcGapResult), collision.rct_raw(), triggerBit); // note change multFT0C to multFT0M when problems with multFT0A are fixed + products.jCollisionsTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), collision.collisionTime(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.centFV0A(), -1.0, collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.centFT0CVariant1(), hadronicRate, collision.trackOccupancyInTimeRange(), collision.alias_raw(), jetderiveddatautilities::setEventSelectionBit(collision, upcGapResult), collision.rct_raw(), triggerBit); // note change multFT0C to multFT0M when problems with multFT0A are fixed products.jCollisionsParentIndexTable(collision.globalIndex()); - products.jCollisionsBunchCrossingIndexTable(collision.bcId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisions, "produces derived collision tables", true); @@ -302,34 +348,25 @@ struct JetDerivedDataProducerTask { triggerDecider.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), jetderiveddatautilities::JTriggerMasks); triggerBit = jetderiveddatautilities::setTriggerSelectionBit(triggerDecider.getTriggerOfInterestResults(bc.globalBC())); } - products.jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC, -1.0, -1, collision.alias_raw(), jetderiveddatautilities::setEventSelectionBit(collision), collision.rct_raw(), triggerBit); + products.jCollisionsTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), collision.collisionTime(), -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1, collision.alias_raw(), jetderiveddatautilities::setEventSelectionBit(collision), collision.rct_raw(), triggerBit); products.jCollisionsParentIndexTable(collision.globalIndex()); - products.jCollisionsBunchCrossingIndexTable(collision.bcId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisionsWithoutCentralityAndMultiplicity, "produces derived collision tables without centrality or multiplicity", false); void processCollisionsRun2(soa::Join::iterator const& collision) { - products.jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1.0, -1.0, collision.centRun2V0A(), collision.centRun2V0M(), -1.0, -1.0, -1.0, -1.0, amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC, 1.0, -1, collision.alias_raw(), jetderiveddatautilities::setEventSelectionBit(collision), collision.rct_raw(), 0); // note change multFT0C to multFT0M when problems with multFT0A are fixed + products.jCollisionsTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1.0, -1.0, -1.0, collision.centRun2V0A(), collision.centRun2V0M(), -1.0, -1.0, -1.0, -1.0, -1.0, -1, collision.alias_raw(), jetderiveddatautilities::setEventSelectionBit(collision), collision.rct_raw(), 0); // note change multFT0C to multFT0M when problems with multFT0A are fixed products.jCollisionsParentIndexTable(collision.globalIndex()); - products.jCollisionsBunchCrossingIndexTable(collision.bcId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisionsRun2, "produces derived collision tables for Run 2 data", false); void processCollisionsALICE3(aod::Collision const& collision) { - products.jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC, -1.0, -1, -1.0, 0, 0, 0); + products.jCollisionsTable(collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1, -1.0, 0, 0, 0); products.jCollisionsParentIndexTable(collision.globalIndex()); - products.jCollisionsBunchCrossingIndexTable(-1); } PROCESS_SWITCH(JetDerivedDataProducerTask, processCollisionsALICE3, "produces derived collision tables for ALICE 3 simulations", false); - void processWithoutEMCalCollisionLabels(aod::Collision const&) - { - products.jCollisionsEMCalLabelTable(false, false); - } - PROCESS_SWITCH(JetDerivedDataProducerTask, processWithoutEMCalCollisionLabels, "produces dummy derived collision labels for EMCal", true); - void processEMCalCollisionLabels(aod::EMCALMatchedCollision const& collision) { products.jCollisionsEMCalLabelTable(collision.ambiguous(), collision.isemcreadout()); @@ -349,36 +386,87 @@ struct JetDerivedDataProducerTask { void processMcCollisions(soa::Join::iterator const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), bcRctMapping[mcCollision.bcId()], mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + uint32_t selDecision = ~uint16_t{0}; + uint32_t rctDecision = ~uint32_t{0}; + int32_t bcId = -1; + if (!config.isMCGenOnly) { + bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; + rctDecision = bcRctMapping[bcId]; + } else { + products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); + bcId = products.jBCsTable.lastIndex(); + } + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisions, "produces derived MC collision table", false); void processMcCollisionsWithoutCentralityAndMultiplicity(soa::Join::iterator const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), bcRctMapping[mcCollision.bcId()], mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + + uint32_t selDecision = ~uint16_t{0}; + uint32_t rctDecision = ~uint32_t{0}; + int32_t bcId = -1; + if (!config.isMCGenOnly) { + bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; + rctDecision = bcRctMapping[bcId]; + } else { + products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); + bcId = products.jBCsTable.lastIndex(); + } + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutCentralityAndMultiplicity, "produces derived MC collision table without centraility and multiplicity", false); void processMcCollisionsWithoutXsection(soa::Join::iterator const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, bcRctMapping[mcCollision.bcId()], mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + uint32_t selDecision = ~uint16_t{0}; + uint32_t rctDecision = ~uint32_t{0}; + int32_t bcId = -1; + if (!config.isMCGenOnly) { + bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; + rctDecision = bcRctMapping[bcId]; + } else { + products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); + bcId = products.jBCsTable.lastIndex(); + } + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFT0M(), mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutXsection, "produces derived MC collision table without cross section information", false); void processMcCollisionsWithoutCentralityAndMultiplicityAndXsection(aod::McCollision const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, bcRctMapping[mcCollision.bcId()], mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + uint32_t selDecision = ~uint16_t{0}; + uint32_t rctDecision = ~uint32_t{0}; + int32_t bcId = -1; + if (!config.isMCGenOnly) { + bcId = mcCollision.bcId(); + selDecision = bcSelMapping[bcId]; + rctDecision = bcRctMapping[bcId]; + } else { + products.jBCsTable(-1, -1, -1, -1, ~uint32_t{0}, ~uint32_t{0}, ~uint32_t{0}); + bcId = products.jBCsTable.lastIndex(); + } + products.jMcCollisionsTable(bcId, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), 1, 1, 1.0, 1.0, 999.0, selDecision, rctDecision, mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutCentralityAndMultiplicityAndXsection, "produces derived MC collision table without centrality, multiplicity and cross section information", false); void processTrackSelectionForWeightedMC(soa::Join const& tracks, soa::Join const&, aod::McCollisions const& mcCollisions, aod::McParticles const&) { - if (mcCollisions.iteratorAt(0).getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap || mcCollisions.iteratorAt(1).getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - + bool hasMBGap = false; + for (auto const& mcCollision : mcCollisions) { + if (mcCollision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + hasMBGap = true; + break; + } + } + if (hasMBGap) { for (auto const& track : tracks) { if (track.has_collision()) { auto const& trackCollision = track.collision_as>(); @@ -386,7 +474,7 @@ struct JetDerivedDataProducerTask { auto const& trackMcCollision = trackCollision.mcCollision_as(); auto const& particleMcCollision = track.mcParticle().mcCollision_as(); if (trackMcCollision.globalIndex() != particleMcCollision.globalIndex() && trackMcCollision.getSubGeneratorId() != jetderiveddatautilities::JCollisionSubGeneratorId::mbGap && particleMcCollision.getSubGeneratorId() != jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - trackWeightedMCSelection[track.globalIndex()] = false; + trackMCSelection[track.globalIndex()] = false; } } } @@ -397,7 +485,7 @@ struct JetDerivedDataProducerTask { void processTracks(soa::Join::iterator const& track, aod::Collisions const&) { - products.jTracksTable(track.collisionId(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), config.dcaZMax, trackWeightedMCSelection[track.globalIndex()])); + products.jTracksTable(track.collisionId(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), config.dcaZMax, trackMCSelection[track.globalIndex()])); auto trackParCov = getTrackParCov(track); auto xyzTrack = trackParCov.getXYZGlo(); float sigmaDCAXYZ2; @@ -425,7 +513,7 @@ struct JetDerivedDataProducerTask { auto track = collisionTrackIndex.track_as>(); auto trackParCov = getTrackParCov(track); if (track.collisionId() == collision.globalIndex()) { - products.jTracksTable(collision.globalIndex(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), config.dcaZMax, trackWeightedMCSelection[track.globalIndex()])); + products.jTracksTable(collision.globalIndex(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), config.dcaZMax, trackMCSelection[track.globalIndex()])); products.jTracksParentIndexTable(track.globalIndex()); auto xyzTrack = trackParCov.getXYZGlo(); float sigmaDCAXYZ2; @@ -440,7 +528,7 @@ struct JetDerivedDataProducerTask { 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); - products.jTracksTable(collision.globalIndex(), trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), jetderiveddatautilities::setTrackSelectionBit(track, dcaCovInfo.getZ(), config.dcaZMax, trackWeightedMCSelection[track.globalIndex()])); // only qualitytracksWDCA are a reliable selection + products.jTracksTable(collision.globalIndex(), trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), jetderiveddatautilities::setTrackSelectionBit(track, dcaCovInfo.getZ(), config.dcaZMax, trackMCSelection[track.globalIndex()])); // only qualitytracksWDCA are a reliable selection products.jTracksParentIndexTable(track.globalIndex()); auto xyzTrack = trackParCov.getXYZGlo(); float dcaXY = dcaCovInfo.getY(); @@ -466,7 +554,7 @@ struct JetDerivedDataProducerTask { void processTracksRun2(soa::Join::iterator const& track) { // TracksDCACov table is not yet available for Run 2 converted data. Remove this process function and use only processTracks when that becomes available. - products.jTracksTable(track.collisionId(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), config.dcaZMax, trackWeightedMCSelection[track.globalIndex()])); + products.jTracksTable(track.collisionId(), track.pt(), track.eta(), track.phi(), jetderiveddatautilities::setTrackSelectionBit(track, track.dcaZ(), config.dcaZMax, trackMCSelection[track.globalIndex()])); float sigmaDCAXYZ2 = 0.0; float dcaXYZ = getDcaXYZ(track, &sigmaDCAXYZ2); float dcaX = -99.0; diff --git a/PWGJE/TableProducer/derivedDataSelector.cxx b/PWGJE/TableProducer/derivedDataSelector.cxx index 60f07e9b2bf..c9a0ca6ca32 100644 --- a/PWGJE/TableProducer/derivedDataSelector.cxx +++ b/PWGJE/TableProducer/derivedDataSelector.cxx @@ -22,9 +22,9 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataSelector.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include #include #include @@ -50,8 +50,6 @@ struct JetDerivedDataSelector { 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 thresholdD0PtMin{"thresholdD0PtMin", 0.0, "Minimum D0 pt to accept event"}; @@ -100,7 +98,9 @@ struct JetDerivedDataSelector { 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 thresholdTriggerTrackReferencePtMin{"thresholdTriggerTrackReferencePtMin", 0.0, "Minimum trigger track reference pt to accept event"}; Configurable thresholdTriggerParticlePtMin{"thresholdTriggerParticlePtMin", 0.0, "Minimum trigger particle pt to accept event"}; + Configurable thresholdTriggerParticleReferencePtMin{"thresholdTriggerParticleReferencePtMin", 0.0, "Minimum trigger particle reference pt to accept event"}; Configurable thresholdClusterEnergyMin{"thresholdClusterEnergyMin", 0.0, "Minimum cluster energy to accept event"}; Configurable downscaleFactor{"downscaleFactor", 1, "random downscale of selected events"}; @@ -116,12 +116,15 @@ struct JetDerivedDataSelector { 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 triggerTrackSignalFraction{"triggerTrackSignalFraction", 0.95, "fraction of events to scan for signal trigger track class"}; 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; std::vector collisionFlag; - std::vector McCollisionFlag; + std::vector mcCollisionFlag; + std::vector collisionSplitFlag; + std::vector mcCollisionSplitFlag; TRandom3 randomNumber; @@ -146,8 +149,8 @@ struct JetDerivedDataSelector { void processSetupMcCollisions(aod::JMcCollisions const& mcCollisions) { - McCollisionFlag.clear(); - McCollisionFlag.resize(mcCollisions.size(), false); + mcCollisionFlag.clear(); + mcCollisionFlag.resize(mcCollisions.size(), false); } void processSelectMcCollisionsPerCollision(aod::JMcCollisions const& mcCollisions, soa::Join const& collisions) @@ -156,7 +159,7 @@ struct JetDerivedDataSelector { const auto collisionsPerMcCollision = collisions.sliceBy(CollisionsPerMcCollision, mcCollision.globalIndex()); for (auto collision : collisionsPerMcCollision) { if (collisionFlag[collision.globalIndex()]) { - McCollisionFlag[mcCollision.globalIndex()] = true; + mcCollisionFlag[mcCollision.globalIndex()] = true; } } } @@ -164,8 +167,10 @@ struct JetDerivedDataSelector { void processSelectCollisionsPerMcCollision(soa::Join::iterator const& collision) { - if (McCollisionFlag[collision.mcCollisionId()]) { - collisionFlag[collision.globalIndex()] = true; + if (collision.has_mcCollision()) { + if (mcCollisionFlag[collision.mcCollisionId()]) { + collisionFlag[collision.globalIndex()] = true; + } } } @@ -182,11 +187,11 @@ struct JetDerivedDataSelector { void processSetupAllMcCollisionsWithDownscaling(aod::JMcCollisions const& mcCollisions) { - McCollisionFlag.clear(); - McCollisionFlag.resize(mcCollisions.size(), false); + mcCollisionFlag.clear(); + mcCollisionFlag.resize(mcCollisions.size(), false); for (const auto& mcCollision : mcCollisions) { if (randomNumber.Integer(config.downscaleFactor) == 0) { - McCollisionFlag[mcCollision.globalIndex()] = true; + mcCollisionFlag[mcCollision.globalIndex()] = true; } } } @@ -201,8 +206,8 @@ struct JetDerivedDataSelector { } } if constexpr (std::is_same_v, aod::JMcCollisions>) { - if (McCollisionFlag[collision.globalIndex()] && randomNumber.Integer(config.downscaleFactor) != 0) { - McCollisionFlag[collision.globalIndex()] = false; + if (mcCollisionFlag[collision.globalIndex()] && randomNumber.Integer(config.downscaleFactor) != 0) { + mcCollisionFlag[collision.globalIndex()] = false; } } } @@ -225,7 +230,7 @@ struct JetDerivedDataSelector { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBitsCharged, config.skipMBGapEvents, config.applyRCTSelectionsCharged)) { barrelRCTFlagSelection = true; } - if (doprocessSelectingNeutralJets || doprocessSelectingNeutralMCDJets || doprocessSelectingNeutralMCPJets || doprocessSelectingFullJets || doprocessSelectingFullMCDJets || doprocessSelectingFullMCPJets || doprocessSelectingClusters) { + if (doprocessSelectingFullJets || doprocessSelectingFullMCDJets || doprocessSelectingFullMCPJets || doprocessSelectingClusters) { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBitsFull, config.skipMBGapEvents, config.applyRCTSelectionsFull, "CBT_calo")) { emcalRCTFlagSelection = true; } @@ -235,8 +240,35 @@ struct JetDerivedDataSelector { } } + void processCollisionSplitting(aod::JCollisions const& collisions) + { + collisionSplitFlag.clear(); + collisionSplitFlag.resize(collisions.size(), true); + for (auto const& collision : collisions) { + if (randomNumber.Rndm() > config.triggerTrackSignalFraction) { + collisionSplitFlag[collision.globalIndex()] = false; + } + } + } + + void processCollisionSplittingMC(aod::JMcCollisions const& mcCollisions, soa::Join const& collisions) + { + mcCollisionSplitFlag.clear(); + mcCollisionSplitFlag.resize(mcCollisions.size(), true); + collisionSplitFlag.clear(); + collisionSplitFlag.resize(collisions.size(), true); + for (auto const& mcCollision : mcCollisions) { + if (randomNumber.Rndm() > config.triggerTrackSignalFraction) { + mcCollisionSplitFlag[mcCollision.globalIndex()] = false; + for (auto const& collision : collisions.sliceBy(CollisionsPerMcCollision, mcCollision.globalIndex())) { + collisionSplitFlag[collision.globalIndex()] = false; + } + } + } + } + template - void processSelectionObjects(T& selectionObjects) + void processSelectionObjects(T const& selectionObjects) { float selectionObjectPtMin = 0.0; if constexpr (std::is_same_v, aod::ChargedJets> || std::is_same_v, aod::ChargedMCDetectorLevelJets>) { @@ -245,10 +277,6 @@ struct JetDerivedDataSelector { 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>) { @@ -360,21 +388,43 @@ struct JetDerivedDataSelector { } } else { if constexpr (std::is_same_v, aod::JTracks>) { - if (config.performTrackSelection && !(selectionObject.trackSel() & ~(1 << jetderiveddatautilities::JTrackSel::trackSign))) { + if (config.performTrackSelection && !(selectionObject.trackSel() & ~((1ULL << jetderiveddatautilities::JTrackSel::trackSign) | (1ULL << jetderiveddatautilities::JTrackSel::notBadMcTrack)))) { continue; } if (selectionObject.pt() < config.trackPtSelectionMin || std::abs(selectionObject.eta()) > config.trackEtaSelectionMax) { continue; } + if (doprocessCollisionSplitting || doprocessCollisionSplittingMC) { + if (collisionSplitFlag[selectionObject.collisionId()]) { + selectionObjectPtMin = config.thresholdTriggerTrackPtMin; + } else { + selectionObjectPtMin = config.thresholdTriggerTrackReferencePtMin; + } + } + } + if constexpr (std::is_same_v, aod::JMcParticles>) { + if (!selectionObject.isPhysicalPrimary()) { + continue; + } + if (selectionObject.pt() < config.trackPtSelectionMin || std::abs(selectionObject.eta()) > config.trackEtaSelectionMax) { + continue; + } + if (doprocessCollisionSplittingMC) { + if (mcCollisionSplitFlag[selectionObject.mcCollisionId()]) { + selectionObjectPtMin = config.thresholdTriggerParticlePtMin; + } else { + selectionObjectPtMin = config.thresholdTriggerParticleReferencePtMin; + } + } } 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::CandidatesD0MCP> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDplusMCP> || std::is_same_v, aod::DplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDsMCP> || std::is_same_v, aod::DsChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDstarMCP> || std::is_same_v, aod::DstarChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesLcMCP> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesB0MCP> || std::is_same_v, aod::B0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesBplusMCP> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesXicToXiPiPiMCP> || std::is_same_v, aod::XicToXiPiPiChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDielectronMCP> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets> || std::is_same_v, aod::JMcParticles>) { + if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::CandidatesD0MCP> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDplusMCP> || std::is_same_v, aod::DplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDsMCP> || std::is_same_v, aod::DsChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDstarMCP> || std::is_same_v, aod::DstarChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesLcMCP> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesB0MCP> || std::is_same_v, aod::B0ChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesBplusMCP> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesXicToXiPiPiMCP> || std::is_same_v, aod::XicToXiPiPiChargedMCParticleLevelJets> || std::is_same_v, aod::CandidatesDielectronMCP> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets> || std::is_same_v, aod::JMcParticles>) { if (selectionObject.mcCollisionId() >= 0) { - McCollisionFlag[selectionObject.mcCollisionId()] = true; + mcCollisionFlag[selectionObject.mcCollisionId()] = true; } } else { if (selectionObject.collisionId() >= 0) { @@ -390,14 +440,13 @@ struct JetDerivedDataSelector { PROCESS_SWITCH(JetDerivedDataSelector, processSetupAllCollisionsWithDownscaling, "setup the writing of untriggered collisions with downscaling", false); PROCESS_SWITCH(JetDerivedDataSelector, processSetupAllMcCollisionsWithDownscaling, "setup the writing of untriggered mccollisions with downscaling", false); PROCESS_SWITCH(JetDerivedDataSelector, processSetupEventTriggering, "process software triggers", false); + PROCESS_SWITCH(JetDerivedDataSelector, processCollisionSplitting, "process collision splitting for trigger tracks", false); + PROCESS_SWITCH(JetDerivedDataSelector, processCollisionSplittingMC, "process mcCollision and collision splitting for trigger tracks", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedJets, "process charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedEventWiseSubtractedJets, "process charged event-wise subtracted jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedMCDJets, "process charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedMCDetectorLevelEventWiseSubtractedJets, "process charged event-wise subtracted mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingChargedMCPJets, "process charged mcp jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingNeutralJets, "process neutral jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingNeutralMCDJets, "process neutral mcd jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingNeutralMCPJets, "process neutral mcp jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingFullJets, "process full jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingFullMCDJets, "process full mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingFullMCPJets, "process full mcp jets", false); @@ -450,8 +499,8 @@ struct JetDerivedDataSelector { PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCDJets, "process Bplus charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCDetectorLevelEventWiseSubtractedJets, "process Bplus event-wise subtracted charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCPJets, "process Bplus charged mcp jets", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidates, "process XicToXiPiPi candidates", false); - PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidatesMCP, "process XicToXiPiPi particles", false); + // PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidates, "process XicToXiPiPi candidates", false); + // PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiCandidatesMCP, "process XicToXiPiPi particles", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiChargedJets, "process XicToXiPiPi charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiChargedEventWiseSubtractedJets, "process XicToXiPiPi event-wise subtracted charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingXicToXiPiPiChargedMCDJets, "process XicToXiPiPi charged mcd jets", false); @@ -485,7 +534,7 @@ struct JetDerivedDataSelector { void processStoreMcCollisionDecision(aod::JMcCollision const& mcCollision) { - if (McCollisionFlag[mcCollision.globalIndex()]) { + if (mcCollisionFlag[mcCollision.globalIndex()]) { mcCollisionSelectionsTable(true); } else { mcCollisionSelectionsTable(false); diff --git a/PWGJE/TableProducer/derivedDataTriggerProducer.cxx b/PWGJE/TableProducer/derivedDataTriggerProducer.cxx index b90495d0bb6..2c80e811464 100644 --- a/PWGJE/TableProducer/derivedDataTriggerProducer.cxx +++ b/PWGJE/TableProducer/derivedDataTriggerProducer.cxx @@ -18,10 +18,10 @@ #include "EventFiltering/filterTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" +#include +#include #include +#include #include #include #include diff --git a/PWGJE/TableProducer/derivedDataWriter.cxx b/PWGJE/TableProducer/derivedDataWriter.cxx index 044ba77d08f..41f4d80d227 100644 --- a/PWGJE/TableProducer/derivedDataWriter.cxx +++ b/PWGJE/TableProducer/derivedDataWriter.cxx @@ -28,9 +28,9 @@ #include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataSelector.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include #include #include @@ -55,7 +55,6 @@ struct JetDerivedDataWriter { Configurable trackEtaSelectionMax{"trackEtaSelectionMax", 0.9, "only save tracks that have an eta smaller than this eta"}; Configurable savePartonLevelInfo{"savePartonLevelInfo", true, "save parton level info at MCP level"}; - 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; struct : ProducesGroup { @@ -63,9 +62,9 @@ struct JetDerivedDataWriter { Produces storedJBCsTable; Produces storedJBCParentIndexTable; Produces storedJCollisionsTable; + Produces storedJCollisionUPCsTable; Produces storedJCollisionMcInfosTable; Produces storedJCollisionsParentIndexTable; - Produces storedJCollisionsBunchCrossingIndexTable; Produces storedJCollisionsEMCalLabelTable; Produces storedJMcCollisionsLabelTable; Produces storedJMcCollisionsTable; @@ -78,7 +77,6 @@ struct JetDerivedDataWriter { Produces storedJMcParticlesTable; Produces storedJParticlesParentIndexTable; Produces storedJClustersTable; - Produces storedJClustersCorrectedEnergiesTable; Produces storedJClustersParentIndexTable; Produces storedJClustersMatchedTracksTable; Produces storedJMcClustersLabelTable; @@ -286,7 +284,7 @@ struct JetDerivedDataWriter { template bool trackSelection(T const& track) { - if (config.performTrackSelection && !(track.trackSel() & ~((1 << jetderiveddatautilities::JTrackSel::trackSign) | (1 << jetderiveddatautilities::JTrackSel::notBadMcTrack)))) { // 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. + if (config.performTrackSelection && !(track.trackSel() & ~((1ULL << jetderiveddatautilities::JTrackSel::trackSign) | (1ULL << jetderiveddatautilities::JTrackSel::notBadMcTrack)))) { // 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. return false; } if (track.pt() < config.trackPtSelectionMin || std::abs(track.eta()) > config.trackEtaSelectionMax) { @@ -430,13 +428,15 @@ struct JetDerivedDataWriter { std::vector particleMapping; std::vector d0McCollisionMapping; std::vector dplusMcCollisionMapping; + std::vector dsMcCollisionMapping; std::vector dstarMcCollisionMapping; std::vector lcMcCollisionMapping; std::vector b0McCollisionMapping; std::vector bplusMcCollisionMapping; + std::vector xicToXiPiPiMcCollisionMapping; // std::vector dielectronMcCollisionMapping; - void processBCs(soa::Join const& collisions, soa::Join const& bcs) + void processBCs(soa::Join const& collisions, soa::Join const& bcs) { std::vector bcIndicies; bcMapping.clear(); @@ -446,7 +446,7 @@ struct JetDerivedDataWriter { if (collision.isCollisionSelected()) { auto bc = collision.bc_as>(); if (std::find(bcIndicies.begin(), bcIndicies.end(), bc.globalIndex()) == bcIndicies.end()) { - products.storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.timestamp(), bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); + products.storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.triggerMask(), bc.timestamp(), bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); products.storedJBCParentIndexTable(bc.bcId()); bcIndicies.push_back(bc.globalIndex()); bcMapping[bc.globalIndex()] = products.storedJBCsTable.lastIndex(); @@ -456,17 +456,48 @@ struct JetDerivedDataWriter { } PROCESS_SWITCH(JetDerivedDataWriter, processBCs, "write out output tables for Bunch crossings", true); - void processColllisons(soa::Join const& collisions) + void processBCsForMcGenOnly(soa::Join const& mcCollisions, aod::JBCs const& bcs) + { + std::vector bcIndicies; + bcMapping.clear(); + bcMapping.resize(bcs.size(), -1); + + for (auto const& mcCollision : mcCollisions) { + if (mcCollision.isMcCollisionSelected()) { + auto bc = mcCollision.bc_as(); + if (std::find(bcIndicies.begin(), bcIndicies.end(), bc.globalIndex()) == bcIndicies.end()) { + products.storedJBCsTable(bc.runNumber(), bc.globalBC(), bc.triggerMask(), bc.timestamp(), bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); + bcIndicies.push_back(bc.globalIndex()); + bcMapping[bc.globalIndex()] = products.storedJBCsTable.lastIndex(); + } + } + } + } + PROCESS_SWITCH(JetDerivedDataWriter, processBCsForMcGenOnly, "write out output tables for Bunch crossings for mc gen only configurations", false); + + void processColllisons(soa::Join const& collisions) { collisionMapping.clear(); collisionMapping.resize(collisions.size(), -1); + for (auto const& collision : collisions) { + if (collision.isCollisionSelected()) { + products.storedJCollisionsTable(bcMapping[collision.bcId()], collision.posX(), collision.posY(), collision.posZ(), collision.collisionTime(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.centFV0A(), collision.centFV0M(), collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.centFT0CVariant1(), collision.hadronicRate(), collision.trackOccupancyInTimeRange(), collision.alias_raw(), collision.eventSel(), collision.rct_raw(), collision.triggerSel()); + collisionMapping[collision.globalIndex()] = products.storedJCollisionsTable.lastIndex(); + products.storedJCollisionMcInfosTable(collision.weight(), collision.getSubGeneratorId()); + products.storedJCollisionsParentIndexTable(collision.collisionId()); + } + } + } + PROCESS_SWITCH(JetDerivedDataWriter, processColllisons, "write out output tables for collisions", true); + + void processUPCCollisionInfos(soa::Join const& collisions) + { std::vector amplitudesFV0; std::vector amplitudesFT0A; std::vector amplitudesFT0C; std::vector amplitudesFDDA; std::vector amplitudesFDDC; - for (auto const& collision : collisions) { if (collision.isCollisionSelected()) { amplitudesFV0.clear(); @@ -484,17 +515,11 @@ struct JetDerivedDataWriter { std::copy(amplitudesFT0CSpan.begin(), amplitudesFT0CSpan.end(), std::back_inserter(amplitudesFT0C)); std::copy(amplitudesFDDASpan.begin(), amplitudesFDDASpan.end(), std::back_inserter(amplitudesFDDA)); std::copy(amplitudesFDDCSpan.begin(), amplitudesFDDCSpan.end(), std::back_inserter(amplitudesFDDC)); - products.storedJCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.centFV0A(), collision.centFV0M(), collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.centFT0CVariant1(), amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC, collision.hadronicRate(), collision.trackOccupancyInTimeRange(), collision.alias_raw(), collision.eventSel(), collision.rct_raw(), collision.triggerSel()); - collisionMapping[collision.globalIndex()] = products.storedJCollisionsTable.lastIndex(); - products.storedJCollisionMcInfosTable(collision.weight(), collision.getSubGeneratorId()); - products.storedJCollisionsParentIndexTable(collision.collisionId()); - if (doprocessBCs) { - products.storedJCollisionsBunchCrossingIndexTable(bcMapping[collision.bcId()]); - } + products.storedJCollisionUPCsTable(amplitudesFV0, amplitudesFT0A, amplitudesFT0C, amplitudesFDDA, amplitudesFDDC); } } } - PROCESS_SWITCH(JetDerivedDataWriter, processColllisons, "write out output tables for collisions", true); + PROCESS_SWITCH(JetDerivedDataWriter, processUPCCollisionInfos, "write out table for upc collision info", false); void processTracks(soa::Join const& collisions, soa::Join const& tracks) { @@ -518,7 +543,7 @@ struct JetDerivedDataWriter { } PROCESS_SWITCH(JetDerivedDataWriter, processTracks, "write out output tables for tracks", true); - void processClusters(soa::Join::iterator const& collision, aod::JTracks const&, aod::JEMCTracks const& emcTracks, soa::Join const& clusters) + void processClusters(soa::Join::iterator const& collision, aod::JTracks const&, aod::JEMCTracks const& emcTracks, soa::Join const& clusters) { if (collision.isCollisionSelected()) { products.storedJCollisionsEMCalLabelTable(collision.isAmbiguous(), collision.isEmcalReadout()); @@ -526,7 +551,6 @@ struct JetDerivedDataWriter { products.storedJClustersTable(collisionMapping[collision.globalIndex()], 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.storedJClustersCorrectedEnergiesTable(cluster.energyCorrectedOneTrack1(), cluster.energyCorrectedOneTrack2(), cluster.energyCorrectedAllTracks1(), cluster.energyCorrectedAllTracks2()); products.storedJClustersParentIndexTable(cluster.clusterId()); std::vector clusterStoredJTrackIDs; @@ -661,7 +685,7 @@ struct JetDerivedDataWriter { mcCollisionMapping.resize(mcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - products.storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multFV0A(), mcCollision.multFT0A(), mcCollision.multFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), mcCollision.rct_raw(), mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); + products.storedJMcCollisionsTable(bcMapping[mcCollision.bcId()], mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multFV0A(), mcCollision.multFT0A(), mcCollision.multFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard(), mcCollision.eventSel(), mcCollision.rct_raw(), mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); products.storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); mcCollisionMapping[mcCollision.globalIndex()] = products.storedJMcCollisionsTable.lastIndex(); } @@ -763,18 +787,18 @@ struct JetDerivedDataWriter { void processDsMCP(soa::Join const& mcCollisions, aod::McCollisionsDs const& DsMcCollisions, aod::CandidatesDsMCP const& DsParticles) { - dplusMcCollisionMapping.clear(); - dplusMcCollisionMapping.resize(DsMcCollisions.size(), -1); + dsMcCollisionMapping.clear(); + dsMcCollisionMapping.resize(DsMcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto dplusMcCollisionsPerMcCollision = DsMcCollisions.sliceBy(preslices.DsMcCollisionsPerMcCollision, mcCollision.globalIndex()); - for (const auto& dplusMcCollisionPerMcCollision : dplusMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillHFMcCollisionTable(dplusMcCollisionPerMcCollision, products.productsDs.storedDsMcCollisionsTable); + const auto dsMcCollisionsPerMcCollision = DsMcCollisions.sliceBy(preslices.DsMcCollisionsPerMcCollision, mcCollision.globalIndex()); + for (const auto& dsMcCollisionPerMcCollision : dsMcCollisionsPerMcCollision) { // should only ever be one + jethfutilities::fillHFMcCollisionTable(dsMcCollisionPerMcCollision, products.productsDs.storedDsMcCollisionsTable); products.productsDs.storedDsMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - dplusMcCollisionMapping[dplusMcCollisionPerMcCollision.globalIndex()] = products.productsDs.storedDsMcCollisionsTable.lastIndex(); + dsMcCollisionMapping[dsMcCollisionPerMcCollision.globalIndex()] = products.productsDs.storedDsMcCollisionsTable.lastIndex(); } - const auto dplusParticlesPerMcCollision = DsParticles.sliceBy(preslices.DsParticlesPerMcCollision, mcCollision.globalIndex()); - for (const auto& DsParticle : dplusParticlesPerMcCollision) { + const auto dsParticlesPerMcCollision = DsParticles.sliceBy(preslices.DsParticlesPerMcCollision, mcCollision.globalIndex()); + for (const auto& DsParticle : dsParticlesPerMcCollision) { jethfutilities::fillHFCandidateMcTable(DsParticle, products.productsDs.storedDsMcCollisionsTable.lastIndex(), products.productsDs.storedDsParticlesTable); products.productsDs.storedDsParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DsParticle.mcParticleId()]); } @@ -873,18 +897,18 @@ struct JetDerivedDataWriter { void processXicToXiPiPiMCP(soa::Join const& mcCollisions, aod::McCollisionsXicToXiPiPi const& XicToXiPiPiMcCollisions, aod::CandidatesXicToXiPiPiMCP const& XicToXiPiPiParticles) { - dplusMcCollisionMapping.clear(); - dplusMcCollisionMapping.resize(XicToXiPiPiMcCollisions.size(), -1); + xicToXiPiPiMcCollisionMapping.clear(); + xicToXiPiPiMcCollisionMapping.resize(XicToXiPiPiMcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto dplusMcCollisionsPerMcCollision = XicToXiPiPiMcCollisions.sliceBy(preslices.XicToXiPiPiMcCollisionsPerMcCollision, mcCollision.globalIndex()); - for (const auto& dplusMcCollisionPerMcCollision : dplusMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillHFMcCollisionTable(dplusMcCollisionPerMcCollision, products.productsXicToXiPiPi.storedXicToXiPiPiMcCollisionsTable); + const auto xicToXiPiPiMcCollisionsPerMcCollision = XicToXiPiPiMcCollisions.sliceBy(preslices.XicToXiPiPiMcCollisionsPerMcCollision, mcCollision.globalIndex()); + for (const auto& xicToXiPiPiMcCollisionPerMcCollision : xicToXiPiPiMcCollisionsPerMcCollision) { // should only ever be one + jethfutilities::fillHFMcCollisionTable(xicToXiPiPiMcCollisionPerMcCollision, products.productsXicToXiPiPi.storedXicToXiPiPiMcCollisionsTable); products.productsXicToXiPiPi.storedXicToXiPiPiMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - dplusMcCollisionMapping[dplusMcCollisionPerMcCollision.globalIndex()] = products.productsXicToXiPiPi.storedXicToXiPiPiMcCollisionsTable.lastIndex(); + xicToXiPiPiMcCollisionMapping[xicToXiPiPiMcCollisionPerMcCollision.globalIndex()] = products.productsXicToXiPiPi.storedXicToXiPiPiMcCollisionsTable.lastIndex(); } - const auto dplusParticlesPerMcCollision = XicToXiPiPiParticles.sliceBy(preslices.XicToXiPiPiParticlesPerMcCollision, mcCollision.globalIndex()); - for (const auto& XicToXiPiPiParticle : dplusParticlesPerMcCollision) { + const auto xicToXiPiPiParticlesPerMcCollision = XicToXiPiPiParticles.sliceBy(preslices.XicToXiPiPiParticlesPerMcCollision, mcCollision.globalIndex()); + for (const auto& XicToXiPiPiParticle : xicToXiPiPiParticlesPerMcCollision) { jethfutilities::fillHFCandidateMcTable(XicToXiPiPiParticle, products.productsXicToXiPiPi.storedXicToXiPiPiMcCollisionsTable.lastIndex(), products.productsXicToXiPiPi.storedXicToXiPiPiParticlesTable); products.productsXicToXiPiPi.storedXicToXiPiPiParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[XicToXiPiPiParticle.mcParticleId()]); } @@ -906,7 +930,7 @@ struct JetDerivedDataWriter { for (const auto& DielectronParticle : DielectronParticles) { jetdqutilities::fillDielectronCandidateMcTable(DielectronParticle, products.productsDielectron.storedDielectronMcCollisionsTable.lastIndex(), products.productsDielectron.storedDielectronParticlesTable); std::vector DielectronMothersIds; - int DielectronDaughtersId[2]; + int DielectronDaughtersIds[2] = {-1, -1}; if (DielectronParticle.has_mothers()) { for (auto const& DielectronMother : DielectronParticle.template mothers_as()) { DielectronMothersIds.push_back(particleMapping[DielectronMother.globalIndex()]); @@ -918,11 +942,11 @@ struct JetDerivedDataWriter { if (i > 1) { break; } - DielectronDaughtersId[i] = particleMapping[DielectronDaughter.globalIndex()]; + DielectronDaughtersIds[i] = particleMapping[DielectronDaughter.globalIndex()]; i++; } } - products.productsDielectron.storedDielectronParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DielectronParticle.mcParticleId()], DielectronMothersIds, DielectronDaughtersId); + products.productsDielectron.storedDielectronParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DielectronParticle.mcParticleId()], DielectronMothersIds, DielectronDaughtersIds); } } } @@ -931,7 +955,9 @@ struct JetDerivedDataWriter { void processColllisonsMcCollisionLabel(soa::Join::iterator const& collision) { if (collision.isCollisionSelected()) { - products.storedJMcCollisionsLabelTable(mcCollisionMapping[collision.mcCollisionId()]); + if (collision.has_mcCollision()) { + products.storedJMcCollisionsLabelTable(mcCollisionMapping[collision.mcCollisionId()]); + } } } PROCESS_SWITCH(JetDerivedDataWriter, processColllisonsMcCollisionLabel, "write out collision mcCollision label output tables", false); diff --git a/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx b/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx index 588030e132c..7f9e9dfe7dc 100644 --- a/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx @@ -12,21 +12,18 @@ // **Hadronic Correction in the EMCAL framework: to avoid the double counting of the charged particles' contribution in jets** /// \author Archita Rani Dash -#include "PWGJE/DataModel/EMCALClusterDefinition.h" -#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include #include +#include #include +#include #include #include #include -#include "TVector2.h" #include #include @@ -45,12 +42,6 @@ struct EmcalClusterHadronicCorrectionTask { PresliceUnsorted perTrackMatchedTrack = aod::jemctrack::trackId; // define configurables here - Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; - - Configurable minTime{"minTime", -25., "Minimum cluster time for time cut"}; - Configurable maxTime{"maxTime", 20., "Maximum cluster time for time cut"}; - Configurable minM02{"minM02", 0.1, "Minimum M02 for M02 cut"}; - Configurable maxM02{"maxM02", 0.9, "Maximum M02 for M02 cut"}; Configurable minTrackPt{"minTrackPt", 0.15, "Minimum pT for tracks"}; Configurable hadCorr1{"hadCorr1", 1., "hadronic correction fraction for complete cluster energy subtraction for one matched track"}; // 100% - default Configurable hadCorr2{"hadCorr2", 0.7, "hadronic correction fraction for systematic studies for one matched track"}; // 70% @@ -99,13 +90,10 @@ struct EmcalClusterHadronicCorrectionTask { registry.add("h_matchedtracks", "Total matched tracks; track status;entries", {HistType::kTH1F, {{1, 0.5, 1.5}}}); } - aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); - Filter clusterDefinitionSelection = (aod::jcluster::definition == static_cast(clusterDefinition)); - // The matching of clusters and tracks is already centralised in the EMCAL framework. // One only needs to apply a filter on matched clusters // Here looping over all collisions matched to EMCAL clusters - void processMatchedCollisions(aod::JetCollision const&, soa::Filtered> const& clusters, aod::JEMCTracks const& emcTracks, aod::JetTracks const&) + void processMatchedCollisions(aod::JetCollision const&, soa::Join const& clusters, aod::JEMCTracks const& emcTracks, aod::JetTracks const&) { registry.fill(HIST("h_allcollisions"), 1); @@ -116,6 +104,7 @@ struct EmcalClusterHadronicCorrectionTask { // Looping over all clusters matched to the collision for (const auto& cluster : clusters) { + registry.fill(HIST("h_matchedclusters"), 1); double clusterE1; @@ -137,7 +126,7 @@ struct EmcalClusterHadronicCorrectionTask { TF1 funcPtDepEta("func", "[1] + 1 / pow(x + pow(1 / ([0] - [1]), 1 / [2]), [2])"); funcPtDepEta.SetParameters(eta0, eta1, eta2); TF1 funcPtDepPhi("func", "[1] + 1 / pow(x + pow(1 / ([0] - [1]), 1 / [2]), [2])"); - funcPtDepEta.SetParameters(phi0, phi1, phi2); + funcPtDepPhi.SetParameters(phi0, phi1, phi2); // No matched tracks (trackless case) if (cluster.matchedTracks().size() == 0) { @@ -245,7 +234,6 @@ struct EmcalClusterHadronicCorrectionTask { // Fill the table with all four corrected energies clusterEnergyCorrectedTable(clusterE1, clusterE2, clusterEAll1, clusterEAll2); - } // End of cluster loop } // process function ends PROCESS_SWITCH(EmcalClusterHadronicCorrectionTask, processMatchedCollisions, "hadronic correction", true); diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 9a274427955..037f793a0d1 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -23,6 +23,8 @@ #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" // for EM V0 legs #include "Common/Core/RecoDecay.h" +#include "Common/Core/Zorro.h" +#include "Common/Core/ZorroSummary.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -48,13 +50,12 @@ #include #include #include +#include #include #include #include -#include - #include #include @@ -77,7 +78,7 @@ using namespace o2::framework::expressions; using namespace o2::emccrosstalk; using namespace tmemcutilities; using MyGlobTracks = o2::soa::Join; -using BcEvSels = o2::soa::Join; +using BcEvSels = soa::Join; using CollEventSels = o2::soa::Join; using FilteredCells = o2::soa::Filtered; using McCells = o2::soa::Join; @@ -137,7 +138,8 @@ struct EmcalCorrectionTask { Configurable mcCellEnergyShift{"mcCellEnergyShift", 1., "Relative shift of the MC cell energy. 1.1 for 10% shift to higher mass, etc. Only applied to MC."}; Configurable mcCellEnergyResolutionBroadening{"mcCellEnergyResolutionBroadening", 0., "Relative widening of the MC cell energy resolution. 0 for no widening, 0.1 for 10% widening, etc. Only applied to MC."}; Configurable applyGainCalibShift{"applyGainCalibShift", false, "Apply shift for cell gain calibration to use values before cell format change (Sept. 2023)"}; - + Configurable applySoftwareTriggerSelection{"applySoftwareTriggerSelection", false, "Apply software trigger selection"}; + Configurable softwareTriggerSelection{"softwareTriggerSelection", "fGammaHighPtEMCAL,fGammaHighPtDCAL", "Default: fGammaHighPtEMCAL,fGammaHighPtDCAL"}; // cross talk emulation configs EmcCrossTalkConf emcCrossTalkConf; @@ -150,6 +152,11 @@ struct EmcalCorrectionTask { // CDB service (for geometry) Service mCcdbManager; + // Zorro for optional software trigger selection + // this allows to save computation time + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + // Clusterizer and related // Apparently streaming these objects really doesn't work, and causes problems for setting up the workflow. // So we use unique_ptr and define them below. @@ -224,6 +231,10 @@ struct EmcalCorrectionTask { initializeGainCalibShift(); } + if (applySoftwareTriggerSelection) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + // read all the cluster definitions specified in the options if (clusterDefinitions->length()) { std::stringstream parser(clusterDefinitions.value); @@ -370,6 +381,15 @@ struct EmcalCorrectionTask { mExtraTimeShiftRunRanges.emplace_back(559544, 559856); // PbPb 2024 } + template + void initZorroCCDB(const BCType& bc) + { + if (applySoftwareTriggerSelection) { + zorro.initCCDB(mCcdbManager.service, bc.runNumber(), bc.timestamp(), softwareTriggerSelection.value); + zorro.populateHistRegistry(mHistManager, bc.runNumber()); + } + } + // void process(aod::Collision const& collision, soa::Filtered const& fullTracks, aod::Calos const& cells) // void process(aod::Collision const& collision, aod::Tracks const& tracks, aod::Calos const& cells) // void process(aod::BCs const& bcs, aod::Collision const& collision, aod::Calos const& cells) @@ -387,6 +407,8 @@ struct EmcalCorrectionTask { for (const auto& bc : bcs) { LOG(debug) << "Next BC"; + initZorroCCDB(bc); + // get run number runNumber = bc.runNumber(); @@ -412,6 +434,14 @@ struct EmcalCorrectionTask { } // Counters for BCs with matched collisions countBC(collisionsInFoundBC.size(), true); + + // do not do the next part if we do not fulfill the software trigger selection + if (applySoftwareTriggerSelection) { + if (!zorro.isSelected(bc.globalBC())) { + continue; + } + } + std::vector cellsBC; std::vector cellIndicesBC; for (const auto& cell : cellsInBC) { @@ -496,6 +526,7 @@ struct EmcalCorrectionTask { } // end of bc loop // Loop through all collisions and fill emcalcollisionmatch with a boolean stating, whether the collision was ambiguous (not the only collision in its BC) + // NOTE: we can not do zorro selection here since emcalcollisionmatch needs to alway be filled to be joinable with collision table for (const auto& collision : collisions) { auto globalbcid = collision.foundBC_as().globalIndex(); auto foundColls = numberCollsInBC.find(globalbcid); @@ -523,6 +554,8 @@ struct EmcalCorrectionTask { for (const auto& bc : bcs) { LOG(debug) << "Next BC"; + initZorroCCDB(bc); + // get run number runNumber = bc.runNumber(); @@ -548,6 +581,14 @@ struct EmcalCorrectionTask { } // Counters for BCs with matched collisions countBC(collisionsInFoundBC.size(), true); + + // do not do the next part if we do not fulfill the software trigger selection + if (applySoftwareTriggerSelection) { + if (!zorro.isSelected(bc.globalBC())) { + continue; + } + } + std::vector cellsBC; std::vector cellIndicesBC; for (const auto& cell : cellsInBC) { @@ -636,6 +677,7 @@ struct EmcalCorrectionTask { } // end of bc loop // Loop through all collisions and fill emcalcollisionmatch with a boolean stating, whether the collision was ambiguous (not the only collision in its BC) + // NOTE: we can not do zorro selection here since emcalcollisionmatch needs to alway be filled to be joinable with collision table for (const auto& collision : collisions) { auto globalbcid = collision.foundBC_as().globalIndex(); auto foundColls = numberCollsInBC.find(globalbcid); @@ -665,6 +707,8 @@ struct EmcalCorrectionTask { // Convert aod::Calo to o2::emcal::Cell which can be used with the clusterizer. // In particular, we need to filter only EMCAL cells. + initZorroCCDB(bc); + // get run number runNumber = bc.runNumber(); @@ -682,6 +726,14 @@ struct EmcalCorrectionTask { } // Counters for BCs with matched collisions countBC(collisionsInFoundBC.size(), true); + + // do not do the next part if we do not fulfill the software trigger selection + if (applySoftwareTriggerSelection) { + if (!zorro.isSelected(bc.globalBC())) { + continue; + } + } + std::vector cellsBC; std::vector cellIndicesBC; std::vector cellLabels; @@ -833,6 +885,8 @@ struct EmcalCorrectionTask { // Convert aod::Calo to o2::emcal::Cell which can be used with the clusterizer. // In particular, we need to filter only EMCAL cells. + initZorroCCDB(bc); + // get run number runNumber = bc.runNumber(); @@ -850,6 +904,13 @@ struct EmcalCorrectionTask { } // Counters for BCs with matched collisions countBC(collisionsInFoundBC.size(), true); + + if (applySoftwareTriggerSelection) { + if (!zorro.isSelected(bc.globalBC())) { + continue; + } + } + std::vector cellsBC; std::vector cellIndicesBC; std::vector cellLabels; @@ -991,7 +1052,7 @@ struct EmcalCorrectionTask { } PROCESS_SWITCH(EmcalCorrectionTask, processMCWithSecondaries, "run full analysis with MC info", false); - void processStandalone(aod::BCs const& bcs, aod::Collisions const& collisions, FilteredCells const& cells) + void processStandalone(BcEvSels const& bcs, aod::Collisions const& collisions, FilteredCells const& cells) { LOG(debug) << "Starting process standalone."; int previousCollisionId = 0; // Collision ID of the last unique BC. Needed to skip unordered collisions to ensure ordered collisionIds in the cluster table @@ -1006,6 +1067,14 @@ struct EmcalCorrectionTask { // Get the collisions matched to the BC using global bc index of the collision // since we do not have event selection available here! + initZorroCCDB(bc); + + if (applySoftwareTriggerSelection) { + if (!zorro.isSelected(bc.globalBC())) { + continue; + } + } + // get run number runNumber = bc.runNumber(); @@ -1085,7 +1154,7 @@ struct EmcalCorrectionTask { hasCollision = true; mHistManager.fill(HIST("hCollisionType"), 2); } - fillAmbigousClusterTable(bc, iClusterizer, cellIndicesBC, hasCollision); + fillAmbigousClusterTable(bc, iClusterizer, cellIndicesBC, hasCollision); } mClusterPhi.clear(); diff --git a/PWGJE/TableProducer/emcalMatchedTracksTask.cxx b/PWGJE/TableProducer/emcalMatchedTracksTask.cxx index 55781eb6bc4..14f8cc8b92a 100644 --- a/PWGJE/TableProducer/emcalMatchedTracksTask.cxx +++ b/PWGJE/TableProducer/emcalMatchedTracksTask.cxx @@ -18,14 +18,14 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "EMCALBase/Geometry.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include #include +#include #include +#include #include #include #include diff --git a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx index 13dcb7a228c..d60275c6fac 100644 --- a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx +++ b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx @@ -20,18 +20,19 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include #include +#include #include #include #include -#include +#include #include +#include #include +#include #include #include @@ -75,16 +76,12 @@ 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 applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in the collision analysed by this task"}; - Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied if applyTrackingEfficiency is true"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; Configurable alpha{"alpha", 1.0, "exponent of transverse momentum in calculating the distance measure between pairs"}; Configurable rMax{"rMax", 0.24, "maximum distance of subtraction"}; - Configurable eventEtaMax{"eventEtaMax", 0.9, "maximum pseudorapidity of event"}; Configurable doRhoMassSub{"doRhoMassSub", true, "perfom mass subtraction as well"}; Configurable ghostRapMax{"ghostRapMax", 0.9, "Ghost rapidity max"}; Configurable ghostRepeat{"ghostRepeat", 1, "Ghost tiling repeats"}; @@ -112,19 +109,10 @@ struct eventWiseConstituentSubtractorTask { eventWiseConstituentSubtractor.setDoRhoMassSub(doRhoMassSub); eventWiseConstituentSubtractor.setConstSubAlphaRMax(alpha, rMax); - eventWiseConstituentSubtractor.setMaxEtaEvent(eventEtaMax); + eventWiseConstituentSubtractor.setEtaMinMax(trackEtaMin, trackEtaMax); fastjet::GhostedAreaSpec ghostAreaSpec(ghostRapMax, ghostRepeat, ghostArea, ghostGridScatter, ghostKtScatter, ghostMeanPt); eventWiseConstituentSubtractor.setGhostAreaSpec(ghostAreaSpec); - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "eventWiseConstituentSubtractor workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "eventWiseConstituentSubtractor workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } 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); @@ -142,7 +130,7 @@ struct eventWiseConstituentSubtractorTask { } inputParticles.clear(); tracksSubtracted.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); tracksSubtracted = eventWiseConstituentSubtractor.JetBkgSubUtils::doEventConstSub(inputParticles, candidate.rho(), candidate.rhoM()); for (auto const& trackSubtracted : tracksSubtracted) { @@ -154,7 +142,7 @@ struct eventWiseConstituentSubtractorTask { template void analyseHFMc(T const& mcCollision, U const& particles, V const& candidates, M& particleSubTable) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { return; } for (auto& candidate : candidates) { @@ -179,7 +167,7 @@ struct eventWiseConstituentSubtractorTask { } inputParticles.clear(); tracksSubtracted.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); tracksSubtracted = eventWiseConstituentSubtractor.JetBkgSubUtils::doEventConstSub(inputParticles, collision.rho(), collision.rhoM()); @@ -191,7 +179,7 @@ struct eventWiseConstituentSubtractorTask { void processMcCollisions(soa::Join::iterator const& mcCollision, soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || std::abs(mcCollision.posZ()) > vertexZCut) { return; } inputParticles.clear(); diff --git a/PWGJE/TableProducer/heavyFlavourDefinition.cxx b/PWGJE/TableProducer/heavyFlavourDefinition.cxx index a9f52f96a35..57027ad8b13 100644 --- a/PWGJE/TableProducer/heavyFlavourDefinition.cxx +++ b/PWGJE/TableProducer/heavyFlavourDefinition.cxx @@ -18,9 +18,9 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetTagging.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include #include #include diff --git a/PWGJE/TableProducer/jetEventWeightMCD.cxx b/PWGJE/TableProducer/jetEventWeightMCD.cxx index ddb518e1bba..f294adc0511 100644 --- a/PWGJE/TableProducer/jetEventWeightMCD.cxx +++ b/PWGJE/TableProducer/jetEventWeightMCD.cxx @@ -16,9 +16,9 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include #include #include diff --git a/PWGJE/TableProducer/jetEventWeightMCP.cxx b/PWGJE/TableProducer/jetEventWeightMCP.cxx index 7f262e998ea..0bc5728a0e0 100644 --- a/PWGJE/TableProducer/jetEventWeightMCP.cxx +++ b/PWGJE/TableProducer/jetEventWeightMCP.cxx @@ -15,8 +15,8 @@ #include "PWGJE/DataModel/Jet.h" -#include "Framework/AnalysisTask.h" #include +#include #include #include #include diff --git a/PWGJE/TableProducer/jetTaggerHF.cxx b/PWGJE/TableProducer/jetTaggerHF.cxx index 90412b53207..10cbcef6286 100644 --- a/PWGJE/TableProducer/jetTaggerHF.cxx +++ b/PWGJE/TableProducer/jetTaggerHF.cxx @@ -16,8 +16,6 @@ /// \author Hanseo Park /// \author Hadi Hassan , University of Jyväskylä -#include "MlResponse.h" - #include "PWGJE/Core/JetTaggingUtilities.h" #include "PWGJE/Core/MlResponseHfTagging.h" #include "PWGJE/DataModel/Jet.h" @@ -25,12 +23,13 @@ #include "PWGJE/DataModel/JetTagging.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Tools/ML/MlResponse.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" #include +#include +#include #include +#include #include #include #include @@ -42,6 +41,7 @@ #include #include +#include #include @@ -277,7 +277,7 @@ struct JetTaggerHFTask { } } } - if (doprocessAlgorithmGNN) { + if (doprocessAlgorithmGNN || doprocessAlgorithmGNNwExtra) { if (jet.pt() >= jetpTMin) { float dbRange; if (scoreML[jet.globalIndex()] < dbMin) { @@ -513,7 +513,7 @@ struct JetTaggerHFTask { } } - if (doprocessAlgorithmML || doprocessAlgorithmGNN) { + if (doprocessAlgorithmML || doprocessAlgorithmGNN || doprocessAlgorithmGNNwExtra) { bMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); if (loadModelsFromCCDB) { ccdbApi.init(ccdbUrl); @@ -525,7 +525,7 @@ struct JetTaggerHFTask { bMlResponse.init(); } - if (doprocessAlgorithmGNN) { + if (doprocessAlgorithmGNN || doprocessAlgorithmGNNwExtra) { tensorAlloc = o2::analysis::GNNBjetAllocator(nJetFeat.value, nTrkFeat.value, nClassesMl.value, nTrkOrigin.value, transformFeatureJetMean.value, transformFeatureJetStdev.value, transformFeatureTrkMean.value, transformFeatureTrkStdev.value, nJetConst, tfFuncTypeGNN.value); registry.add("h2_count_db", "#it{D}_{b} underflow/overflow;Jet flavour;#it{D}_{b} range", {HistType::kTH2F, {{4, 0., 4.}, {3, 0., 3.}}}); @@ -538,10 +538,10 @@ struct JetTaggerHFTask { h2CountDb->GetYaxis()->SetBinLabel(2, "in range"); h2CountDb->GetYaxis()->SetBinLabel(3, "overflow"); - registry.add("h_db_b", "#it{D}_{b} b-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -10., 35.}}}); - registry.add("h_db_c", "#it{D}_{b} c-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -10., 35.}}}); - registry.add("h_db_lf", "#it{D}_{b} lf-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -10., 35.}}}); - registry.add("h2_pt_db", "#it{p}_{T} vs. #it{D}_{b};#it{p}_{T}^{ch jet} (GeV/#it{c}^{2});#it{D}_{b}", {HistType::kTH2F, {{100, 0., 200.}, {50, -10., 35.}}}); + registry.add("h_db_b", "#it{D}_{b} b-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -20., 30.}}}); + registry.add("h_db_c", "#it{D}_{b} c-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -20., 30.}}}); + registry.add("h_db_lf", "#it{D}_{b} lf-jet;#it{D}_{b}", {HistType::kTH1F, {{50, -20., 30.}}}); + registry.add("h2_pt_db", "#it{p}_{T} vs. #it{D}_{b};#it{p}_{T}^{ch jet} (GeV/#it{c}^{2});#it{D}_{b}", {HistType::kTH2F, {{100, 0., 200.}, {50, -20., 30.}}}); } } @@ -612,11 +612,40 @@ struct JetTaggerHFTask { } template - void analyzeJetAlgorithmGNN(AnyJets const& jets, AnyTracks const& tracks, AnyOriginalTracks const& origTracks) + void analyzeJetAlgorithmGNNwExtra(AnyJets const& jets, AnyTracks const& tracks, AnyOriginalTracks const& origTracks) { for (const auto& jet : jets) { std::vector> trkFeat; - jettaggingutilities::analyzeJetTrackInfo4GNN(jet, tracks, origTracks, trkFeat, trackPtMin, trackDcaXYMax, trackDcaZMax, nJetConst); + jettaggingutilities::analyzeJetTrackInfo4GNNwExtra(jet, tracks, origTracks, trkFeat, trackPtMin, trackDcaXYMax, trackDcaZMax, nJetConst); + + std::vector jetFeat{jet.pt(), jet.phi(), jet.eta(), jet.mass()}; + + if (trkFeat.size() > 0) { + std::vector feat; + std::vector gnnInput; + tensorAlloc.getGNNInput(jetFeat, trkFeat, feat, gnnInput); + + auto modelOutput = bMlResponse.getModelOutput(gnnInput, 0); + float db = jettaggingutilities::getDb(modelOutput, fC); + if (!std::isnan(db)) { + scoreML[jet.globalIndex()] = db; + } else { + scoreML[jet.globalIndex()] = 999.; + LOGF(debug, "doprocessAlgorithmGNNwExtra, Db is NaN (%d)", jet.globalIndex()); + } + } else { + scoreML[jet.globalIndex()] = -999.; + LOGF(debug, "doprocessAlgorithmGNNwExtra, trkFeat.size() <= 0 (%d)", jet.globalIndex()); + } + } + } + + template + void analyzeJetAlgorithmGNN(AnyJets const& jets, AnyTracks const& tracks) + { + for (const auto& jet : jets) { + std::vector> trkFeat; + jettaggingutilities::analyzeJetTrackInfo4GNN(jet, tracks, trkFeat, trackPtMin, trackDcaXYMax, trackDcaZMax, nJetConst); std::vector jetFeat{jet.pt(), jet.phi(), jet.eta(), jet.mass()}; @@ -684,9 +713,15 @@ struct JetTaggerHFTask { } PROCESS_SWITCH(JetTaggerHFTask, processAlgorithmMLnoSV, "Fill ML evaluation score for charged jets but without using SVs", false); - void processAlgorithmGNN(JetTable const& jets, JetTracksExt const& jtracks, OriginalTracks const& origTracks) + void processAlgorithmGNNwExtra(JetTable const& jets, JetTracksExt const& jtracks, OriginalTracks const& origTracks) + { + analyzeJetAlgorithmGNNwExtra(jets, jtracks, origTracks); + } + PROCESS_SWITCH(JetTaggerHFTask, processAlgorithmGNNwExtra, "Fill GNN evaluation score (D_b) for charged jets with extra input features", false); + + void processAlgorithmGNN(JetTable const& jets, JetTracksExt const& jtracks) { - analyzeJetAlgorithmGNN(jets, jtracks, origTracks); + analyzeJetAlgorithmGNN(jets, jtracks); } PROCESS_SWITCH(JetTaggerHFTask, processAlgorithmGNN, "Fill GNN evaluation score (D_b) for charged jets", false); diff --git a/PWGJE/TableProducer/jetTrackDerived.cxx b/PWGJE/TableProducer/jetTrackDerived.cxx index 9111ae36c3c..db9a7f5325b 100644 --- a/PWGJE/TableProducer/jetTrackDerived.cxx +++ b/PWGJE/TableProducer/jetTrackDerived.cxx @@ -16,7 +16,6 @@ /// \brief Header for the trackJetQa task for the analysis of the tracks for jets.. /// -// O2 includes #include "PWGJE/DataModel/TrackJetQa.h" #include "Common/Core/TrackSelection.h" @@ -26,12 +25,12 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include #include +#include #include +#include #include #include #include diff --git a/PWGJE/TableProducer/luminosityCalculator.cxx b/PWGJE/TableProducer/luminosityCalculator.cxx index 93a97aea92d..c4e9faafc94 100644 --- a/PWGJE/TableProducer/luminosityCalculator.cxx +++ b/PWGJE/TableProducer/luminosityCalculator.cxx @@ -16,11 +16,11 @@ #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include #include +#include #include #include #include diff --git a/PWGJE/TableProducer/luminosityProducer.cxx b/PWGJE/TableProducer/luminosityProducer.cxx index cafac8d6d2a..31823c7ebb7 100644 --- a/PWGJE/TableProducer/luminosityProducer.cxx +++ b/PWGJE/TableProducer/luminosityProducer.cxx @@ -21,17 +21,15 @@ #include "Common/CCDB/EventSelectionParams.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include #include #include #include -#include #include -#include #include #include diff --git a/PWGJE/TableProducer/mcOutlierRejector.cxx b/PWGJE/TableProducer/mcOutlierRejector.cxx index 3cdb38aa1c6..32fed7ebbb3 100644 --- a/PWGJE/TableProducer/mcOutlierRejector.cxx +++ b/PWGJE/TableProducer/mcOutlierRejector.cxx @@ -13,17 +13,21 @@ // /// \author Nima Zardoshti +#include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include #include +#include #include -#include #include +#include +#include +#include +#include +#include #include using namespace o2; diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index 65b473d6c93..c7f11e99b0c 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// Task to produce a table joinable to the jcollision table with the mean background pT density +// Task to produce a table joinable to the jcollision or candidate table with the mean background pT density // /// \author Nima Zardoshti @@ -20,15 +20,15 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include #include +#include #include #include -#include +#include #include +#include #include #include @@ -72,9 +72,6 @@ struct RhoEstimatorTask { Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackPhiMin{"trackPhiMin", -99.0, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 99.0, "maximum track phi"}; - Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in the collision analysed by this task"}; - Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied if applyTrackingEfficiency is true"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; @@ -82,10 +79,6 @@ struct RhoEstimatorTask { Configurable jetAlgorithm{"jetAlgorithm", 0, "jet clustering algorithm. 0 = kT, 1 = C/A, 2 = Anti-kT"}; Configurable jetRecombScheme{"jetRecombScheme", 0, "jet recombination scheme. 0 = E-scheme, 1 = pT-scheme, 2 = pT2-scheme"}; Configurable bkgjetR{"bkgjetR", 0.2, "jet resolution parameter for determining background density"}; - Configurable bkgEtaMin{"bkgEtaMin", -0.7, "minimim pseudorapidity for determining background density"}; - Configurable bkgEtaMax{"bkgEtaMax", 0.7, "maximum pseudorapidity for determining background density"}; - Configurable bkgPhiMin{"bkgPhiMin", -6.283, "minimim phi for determining background density"}; - Configurable bkgPhiMax{"bkgPhiMax", 6.283, "maximum phi for determining background density"}; Configurable doSparse{"doSparse", false, "perfom sparse estimation"}; Configurable ghostRapMax{"ghostRapMax", 0.9, "Ghost rapidity max"}; Configurable ghostRepeat{"ghostRepeat", 1, "Ghost tiling repeats"}; @@ -130,14 +123,14 @@ struct RhoEstimatorTask { bkgSub.setJetAlgorithmAndScheme(static_cast(static_cast(config.jetAlgorithm)), static_cast(static_cast(config.jetRecombScheme))); bkgSub.setJetBkgR(config.bkgjetR); - bkgSub.setEtaMinMax(config.bkgEtaMin, config.bkgEtaMax); - bkgPhiMax_ = config.bkgPhiMax; - bkgPhiMin_ = config.bkgPhiMin; - if (config.bkgPhiMax > 98.0) { + bkgSub.setEtaMinMax(config.trackEtaMin, config.trackEtaMax); + bkgPhiMax_ = config.trackPhiMax; + bkgPhiMin_ = config.trackPhiMin; + if (config.trackPhiMax > 98.0) { bkgPhiMax_ = 2.0 * M_PI; } - if (config.bkgPhiMin < -98.0) { - bkgPhiMin_ = -2.0 * M_PI; + if (config.trackPhiMin < -98.0) { + bkgPhiMin_ = -1.0 * M_PI; } bkgSub.setPhiMinMax(bkgPhiMin_, bkgPhiMax_); @@ -147,15 +140,6 @@ struct RhoEstimatorTask { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(config.eventSelections)); triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(config.triggerMasks); - - if (config.applyTrackingEfficiency) { - if (config.trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "rhoEstimator workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (config.trackingEfficiency->size() + 1 != config.trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "rhoEstimator workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } Filter trackCuts = (aod::jtrack::pt >= config.trackPtMin && aod::jtrack::pt < config.trackPtMax && aod::jtrack::eta > config.trackEtaMin && aod::jtrack::eta < config.trackEtaMax && aod::jtrack::phi >= config.trackPhiMin && aod::jtrack::phi <= config.trackPhiMax); @@ -227,7 +211,7 @@ struct RhoEstimatorTask { return; } inputParticles.clear(); - jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning); + jetfindingutilities::analyseTracks, soa::Filtered::iterator>(inputParticles, tracks, trackSelection); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoChargedTable(rho, rhoM); } @@ -235,7 +219,7 @@ struct RhoEstimatorTask { void processChargedMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoChargedMcTable(0.0, 0.0); return; } @@ -254,7 +238,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoD0Table(rho, rhoM); @@ -265,7 +249,7 @@ struct RhoEstimatorTask { void processD0McCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesD0MCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoD0McTable(0.0, 0.0); continue; } @@ -286,7 +270,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoDplusTable(rho, rhoM); @@ -298,7 +282,7 @@ struct RhoEstimatorTask { { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDplusMcTable(0.0, 0.0); continue; } @@ -319,7 +303,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoDsTable(rho, rhoM); @@ -330,7 +314,7 @@ struct RhoEstimatorTask { void processDsMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesDsMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDsMcTable(0.0, 0.0); continue; } @@ -351,7 +335,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoDstarTable(rho, rhoM); @@ -362,7 +346,7 @@ struct RhoEstimatorTask { void processDstarMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesDstarMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDstarMcTable(0.0, 0.0); continue; } @@ -383,7 +367,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoLcTable(rho, rhoM); @@ -394,7 +378,7 @@ struct RhoEstimatorTask { void processLcMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesLcMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoLcMcTable(0.0, 0.0); continue; } @@ -415,7 +399,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoB0Table(rho, rhoM); @@ -426,7 +410,7 @@ struct RhoEstimatorTask { void processB0McCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesB0MCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoB0McTable(0.0, 0.0); continue; } @@ -447,7 +431,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoBplusTable(rho, rhoM); @@ -458,7 +442,7 @@ struct RhoEstimatorTask { void processBplusMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesBplusMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoBplusMcTable(0.0, 0.0); continue; } @@ -479,7 +463,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoXicToXiPiPiTable(rho, rhoM); @@ -490,7 +474,7 @@ struct RhoEstimatorTask { void processXicToXiPiPiMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesXicToXiPiPiMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoXicToXiPiPiMcTable(0.0, 0.0); continue; } @@ -511,7 +495,7 @@ struct RhoEstimatorTask { continue; } inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.applyTrackingEfficiency, config.trackingEfficiency, config.trackingEfficiencyPtBinning, &candidate); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, &candidate); auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); rhoDielectronTable(rho, rhoM); @@ -522,7 +506,7 @@ struct RhoEstimatorTask { void processDielectronMcCollisions(aod::JetMcCollision const& mcCollision, soa::Filtered const& particles, aod::CandidatesDielectronMCP const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectMcCollision(mcCollision, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mcCollision, eventSelectionBits, config.skipMBGapEvents, config.applyRCTSelections) || std::abs(mcCollision.posZ()) > config.vertexZCut) { rhoDielectronMcTable(0.0, 0.0); continue; } diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index 8bab0ea0c05..e2f2246b21b 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -22,22 +22,22 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/DCA.h" #include +#include +#include #include #include +#include +#include #include +#include #include #include #include #include #include #include +#include #include #include diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index aba4f69c2c6..0275a7a66ed 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# Copyright 2019-2026 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. # @@ -8,7 +8,25 @@ # 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. +add_library(JetSubstructureHFPCH OBJECT jetSubstructureHFPCH.cxx) +target_link_libraries(JetSubstructureHFPCH + PUBLIC O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore) +if(NOT DEFINED ENV{USE_RECC}) +target_precompile_headers(JetSubstructureHFPCH PRIVATE + [["PWGJE/DataModel/Jet.h"]] + [["PWGJE/DataModel/JetSubstructure.h"]] + [["PWGJE/DataModel/JetSubtraction.h"]] + [["PWGJE/Tasks/jetSubstructureHF.h"]] + + + + + + + +) +endif() o2physics_add_dpl_workflow(emc-cellmonitor SOURCES emcCellMonitor.cxx @@ -70,6 +88,7 @@ if(FastJet_FOUND) COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure SOURCES jetSubstructure.cxx + REUSE_FROM JetSubstructureHFPCH PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-output @@ -79,38 +98,47 @@ if(FastJet_FOUND) o2physics_add_dpl_workflow(jet-substructure-d0 SOURCES jetSubstructureD0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-dplus SOURCES jetSubstructureDplus.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-ds SOURCES jetSubstructureDs.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-dstar SOURCES jetSubstructureDstar.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-lc SOURCES jetSubstructureLc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-b0 SOURCES jetSubstructureB0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-bplus SOURCES jetSubstructureBplus.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-xictoxipipi SOURCES jetSubstructureXicToXiPiPi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-dielectron SOURCES jetSubstructureDielectron.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + REUSE_FROM JetSubstructureHFPCH COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-d0-output SOURCES jetSubstructureD0Output.cxx @@ -289,6 +317,10 @@ if(FastJet_FOUND) SOURCES jetLundReclustering.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore FastJet::FastJet FastJet::Contrib COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-lund-plane + SOURCES jetLundPlane.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore FastJet::FastJet FastJet::Contrib + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hf-fragmentation-function SOURCES hfFragmentationFunction.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -347,6 +379,10 @@ if(FastJet_FOUND) SOURCES jetFormationTimeReclustering.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-correlation-d0 + SOURCES jetCorrelationD0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hf-debug SOURCES hfDebug.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -359,4 +395,16 @@ if(FastJet_FOUND) SOURCES substructureDebug.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) -endif() \ No newline at end of file + o2physics_add_dpl_workflow(jet-ds-spectrum-subs + SOURCES jetDsSpectrumAndSubstructure.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-d0-ang-substructure + SOURCES jetD0AngSubstructure.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(bjet-cent-mult + SOURCES bjetCentMult.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) +endif() diff --git a/PWGJE/Tasks/bjetCentMult.cxx b/PWGJE/Tasks/bjetCentMult.cxx new file mode 100644 index 00000000000..576afeb4ac0 --- /dev/null +++ b/PWGJE/Tasks/bjetCentMult.cxx @@ -0,0 +1,627 @@ +// 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 bjetCentMult.cxx +/// \brief bjet multiplicity and centrality analysis +/// +/// \author Hanseo Park + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" +#include "PWGJE/DataModel/JetTagging.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +template +struct BjetCentMultTask { + + // task on/off configuration + Configurable fillGeneralSVQA{"fillGeneralSVQA", true, "process of general QA for sv"}; + Configurable fillSVxyz{"fillSVxyz", true, "process of decay lenngth of xyz for sv"}; + Configurable useEventWeight{"useEventWeight", true, "Flag whether to scale histograms with the event weight"}; + + // Cut configuration + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable> trackCuts{"trackCuts", std::vector{0.15, 100.0, -0.9, 0.9}, "Track cuts: ptMin, ptMax, etaMin, etaMax"}; + Configurable trackDcaXYMax{"trackDcaXYMax", 1, "minimum DCA xy acceptance for tracks [cm]"}; + Configurable trackDcaZMax{"trackDcaZMax", 2, "minimum DCA z acceptance for tracks [cm]"}; + Configurable maxDeltaR{"maxDeltaR", 0.25, "maximum distance of jet axis from flavour initiating parton"}; + Configurable> jetEtaCuts{"jetEtaCuts", std::vector{-99.0, 99.0}, "Jet cuts: etaMin, etaMax"}; + Configurable> prongCuts{"prongCuts", std::vector{1, 100, 100, 100, 0.008, 1}, "prong cuts: chi2PCAMin, chi2PCAMax, sigmaLxyMax, sigmaLxyzMax, IPxyMin, IPxyMax"}; + Configurable svDispersionMax{"svDispersionMax", 0.03f, "maximum dispersion of sv"}; + 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 pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value 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 leadingConstituentPtMax{"leadingConstituentPtMax", 9999.0, "maximum 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 meanFT0A{"meanFT0A", -1., "Mean value of FT0A signal"}; + Configurable meanFT0C{"meanFT0C", -1., "Mean value of FT0C signal"}; + + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + + // Binning + ConfigurableAxis binJetFlavour{"binJetFlavour", {6, -0.5, 5.5}, ""}; + ConfigurableAxis binJetPt{"binJetPt", {200, 0., 200.}, ""}; + ConfigurableAxis binEta{"binEta", {100, -1.f, 1.f}, ""}; + ConfigurableAxis binPhi{"binPhi", {18 * 8, 0.f, o2::constants::math::TwoPI}, ""}; + ConfigurableAxis binNtracks{"binNtracks", {100, 0., 100.}, ""}; + ConfigurableAxis binTrackPt{"binTrackPt", {200, 0.f, 100.f}, ""}; + ConfigurableAxis binNprongs{"binNprongs", {100, 0., 100.}, ""}; + ConfigurableAxis binLxy{"binLxy", {200, 0, 20.f}, ""}; + ConfigurableAxis binSxy{"binSxy", {1000, 0, 1000.f}, ""}; + ConfigurableAxis binLxyz{"binLxyz", {200, 0, 20.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}, ""}; + ConfigurableAxis binFT0{"binFT0", {1000, 0, 1000.f}, ""}; + ConfigurableAxis binMultScaledFT0M{"binMultScaledFT0M", {100, 0, 20.f}, "scaled FT0M"}; + ConfigurableAxis binMultScaledFT0MClass{"binMultScaledFT0MClass", {VARIABLE_WIDTH, 0, 0.2, 0.3, 0.4, 0.6, 0.8, 1., 1.4, 1.8, 2.4, 3.6, 5., 20.}, "Percentiles of scaled FT0M: 100-90%, 90-80%, 80-70%, 70-60%, 60-50%, 50-40%, 40-30%, 30-20%, 20-10%, 10-1%, 1-0.1%"}; + ConfigurableAxis rebinnedCent{"rebinnedCent", {VARIABLE_WIDTH, 0, 0.1, 1.0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100., 110.}, "Rebinned percentiles of centality: 100-90%, 90-80%, 80-70%, 70-60%, 60-50%, 50-40%, 40-30%, 30-20%, 20-10%, 10-1%, 1-0.1%"}; + + int numberOfJetFlavourSpecies = 6; + std::vector eventSelectionBits; + int trackSelection = -1; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + numberOfJetFlavourSpecies = static_cast(numFlavourSpecies); + + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + // Axis + AxisSpec axisJetFlavour = {binJetFlavour, "Jet flavour"}; + AxisSpec axisJetPt = {binJetPt, "#it{p}_{T, jet}"}; + AxisSpec axisMCDJetPt = {binJetPt, "#it{p}_{T, jet}^{rec}"}; + AxisSpec axisMCPJetPt = {binJetPt, "#it{p}_{T, jet}^{gen}"}; + AxisSpec axisEta = {binEta, "#eta"}; + AxisSpec axisPhi = {binPhi, "#phi"}; + AxisSpec axisNTracks = {binNtracks, "#it{N}_{tracks}"}; + AxisSpec axisTrackPt = {binTrackPt, "#it{p}_{T}^{track}"}; + AxisSpec axisNprongs = {binNprongs, "#it{N}_{SV}"}; + AxisSpec axisLxy = {binLxy, "L_{XY} [cm]"}; + AxisSpec axisSxy = {binSxy, "S_{XY}"}; + AxisSpec axisLxyz = {binLxyz, "L_{XYZ} [cm]"}; + AxisSpec axisSxyz = {binSxyz, "S_{XYZ}"}; + AxisSpec axisMass = {binMass, "#it{m}_{SV}"}; + AxisSpec axisSigmaLxy = {binSigmaLxy, "#sigma_{L_{XY}} [cm]"}; + AxisSpec axisSigmaLxyz = {binSigmaLxyz, "#sigma_{L_{XYZ}} [cm]"}; + AxisSpec axisFracSecPt = {100, 0, 1, "#frac{#Sigma#it{p}_{T}^{secondary track}}{#it{p}_{T, jet}}"}; + AxisSpec axisFT0 = {binFT0, "amplitude FT0"}; + AxisSpec axisMultScaledFT0M = {binMultScaledFT0M, "scaled FT0M"}; + AxisSpec axisMultScaledFT0MClass = {binMultScaledFT0MClass, "scaled FT0M classes"}; + AxisSpec axisCentrality = {110, -5., 105., "Centrality"}; + AxisSpec axisRebinnedCentrality = {rebinnedCent, "Centrality"}; + AxisSpec axisPercentileMultiplicity = {110, -5., 105., "Percentile multiplicity"}; + + if (doprocessCentMultQa) { + registry.add("h_amplitude_FT0A", "", {HistType::kTH1F, {{axisFT0}}}); + registry.add("h_amplitude_FT0C", "", {HistType::kTH1F, {{axisFT0}}}); + registry.add("h_scaled_FT0M", "", {HistType::kTH1F, {{axisMultScaledFT0M}}}); + registry.add("h_scaled_FT0M_class", "", {HistType::kTH1F, {{axisMultScaledFT0MClass}}}); + registry.add("h2_centrality_percentile_multiplicity", "mcd collision centrality; centrality; counts", {HistType::kTH2F, {{axisRebinnedCentrality}, {axisPercentileMultiplicity}}}); + } + if (doprocessSV3ProngData) { + registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); + registry.add("h2_jet_pt_centrality", "", {HistType::kTH2F, {{axisJetPt}, {axisCentrality}}}); + registry.add("h2_jet_eta_centrality", "", {HistType::kTH2F, {{axisEta}, {axisCentrality}}}); + registry.add("h2_jet_phi_centrality", "", {HistType::kTH2F, {{axisPhi}, {axisCentrality}}}); + if (fillGeneralSVQA) { + registry.add("h2_3prong_nprongs_centrality", "", {HistType::kTH2F, {{axisNprongs}, {axisCentrality}}}); + registry.add("hn_jet_3prong_Sxy_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}}}); + if (fillSVxyz) { + registry.add("hn_jet_3prong_Sxyz_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}}}); + } + } + registry.add("hn_jet_3prong_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + registry.add("hn_taggedjet_3prong_Sxy_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}}}); + if (fillSVxyz) { + registry.add("hn_jet_3prong_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + registry.add("hn_taggedjet_3prong_Sxyz_N1_centrality", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}}}); + } + } + if (doprocessSV3ProngMCD || doprocessSV3ProngMCPMCDMatched) { + registry.add("h_event_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); + registry.add("h3_jet_pt_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_jet_eta_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_jet_phi_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}); + if (fillGeneralSVQA) { + registry.add("h3_3prong_nprongs_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_3prong_Sxy_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); + if (fillSVxyz) { + registry.add("hn_jet_3prong_Sxyz_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); + } + } + registry.add("hn_jet_3prong_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_3prong_Sxy_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + if (fillSVxyz) { + registry.add("hn_jet_3prong_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_3prong_Sxyz_N1_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + } + } + if (doprocessRhoAreaSubSV3ProngMCD || doprocessRhoAreaSubSV3ProngMCPMCDMatched) { + registry.add("h_event_rhoareasubtracted_centrality", "", {HistType::kTH1F, {{axisCentrality}}}); + registry.add("h3_jet_pt_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_jet_eta_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisEta}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("h3_jet_phi_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisCentrality}, {axisJetFlavour}}}); + if (fillGeneralSVQA) { + registry.add("h3_3prong_nprongs_rhoareasubtracted_centrality_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_jet_3prong_Sxy_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisCentrality}, {axisJetFlavour}}}); + if (fillSVxyz) { + registry.add("hn_jet_3prong_Sxyz_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisCentrality}, {axisJetFlavour}}}); + } + } + registry.add("hn_jet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + if (fillSVxyz) { + registry.add("hn_jet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + registry.add("hn_taggedjet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisCentrality}, {axisJetFlavour}}}); + } + } + } + + // Filter trackCuts = (aod::jtrack::pt >= trackCuts->at(0) && aod::jtrack::pt < trackCuts->at(1) && aod::jtrack::eta > trackCuts->at(2) && aod::jtrack::eta < trackCuts->at(3)); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); + PresliceUnsorted> collisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; + PresliceUnsorted> McCollisionsPerMCPCollision = aod::jmccollision::mcCollisionId; + Preslice particlesPerCollision = aod::jmcparticle::mcCollisionId; + + 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) + { + const float noJetAreaFractionFilter = -98.0; + const float noConstituentPtMinFilter = -98.0; + const float noConstituentPtMaxFilter = 9998.0; + if (jetAreaFractionMin > noJetAreaFractionFilter) { + if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + return false; + } + } + bool checkConstituentPt = true; + bool checkConstituentMinPt = (leadingConstituentPtMin > noConstituentPtMinFilter); + bool checkConstituentMaxPt = (leadingConstituentPtMax < noConstituentPtMaxFilter); + 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; + } + } + return isMinLeadingConstituent && isMaxLeadingConstituent; + } + + return true; + } + + template + bool trackAcceptance(T const& track) + { + if (track.pt() < trackCuts->at(0) || track.pt() > trackCuts->at(1)) + return false; + + return true; + } + + float getScaledFT0A(const float multFT0A) + { + return multFT0A / meanFT0A; + } + + float getScaledFT0C(const float multFT0C) + { + return multFT0C / meanFT0C; + } + + float getScaledFT0M(const float multFT0A, const float multFT0C) + { + return 0.5 * (getScaledFT0A(multFT0A) + getScaledFT0C(multFT0C)); + } + + float getPercentile(const float scaledFT0M) + { + static const std::vector x = {0.0, 0.2, 0.3, 0.4, 0.6, 0.8, 1.0, 1.4, 1.8, 2.4, 3.6, 5.0, 20.0}; + static const std::vector y = {100.0, 90.0, 80.0, 70.0, 60.0, 50.0, 40.0, 30.0, 20.0, 10.0, 1.0, 0.1, 0.0}; + + if (scaledFT0M <= x.front()) + return y.front(); + if (scaledFT0M >= x.back()) + return y.back(); + + for (size_t i = 0; i < x.size() - 1; ++i) { + if (scaledFT0M >= x[i] && scaledFT0M < x[i + 1]) { + float slope = (y[i + 1] - y[i]) / (x[i + 1] - x[i]); + return y[i] + slope * (scaledFT0M - x[i]); + } + } + return -1.0f; + } + + template + void fillHistogramMCP(T const& mcpjet, float eventWeight = 1.0, float pTHat = 999.) + { + if (mcpjet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + 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 fillHistogramSV3ProngData(T const& jet, U const& /*prongs*/, float centrality) + { + if (jet.template secondaryVertices_as().size() < 1) + return; + registry.fill(HIST("h2_jet_pt_centrality"), jet.pt(), centrality); + registry.fill(HIST("h2_jet_eta_centrality"), jet.eta(), centrality); + registry.fill(HIST("h2_jet_phi_centrality"), jet.phi(), centrality); + if (fillGeneralSVQA) { + registry.fill(HIST("h2_3prong_nprongs_centrality"), jet.template secondaryVertices_as().size(), centrality); + for (const auto& prong : jet.template secondaryVertices_as()) { + registry.fill(HIST("hn_jet_3prong_Sxy_centrality"), jet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality); + if (fillSVxyz) { + registry.fill(HIST("hn_jet_3prong_Sxyz_centrality"), jet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality); + } + } + } + bool checkSv = false; + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); + if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + registry.fill(HIST("hn_jet_3prong_Sxy_N1_centrality"), jet.pt(), maxSxy, massSV, centrality); + if (jet.isTagged(BJetTaggingMethod::SV)) { + registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_centrality"), jet.pt(), maxSxy, massSV, centrality); + } + } + if (fillSVxyz) { + checkSv = false; + auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); + if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { + auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); + auto massSV = bjetCandXYZ.m(); + registry.fill(HIST("hn_jet_3prong_Sxyz_N1_centrality"), jet.pt(), maxSxyz, massSV, centrality); + if (jet.isTagged(BJetTaggingMethod::SV3D)) { + registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_centrality"), jet.pt(), maxSxyz, massSV, centrality); + } + } + } + } + + template + void fillHistogramSV3ProngMCD(T const& mcdjet, U const& /*prongs*/, float centrality, float eventWeight = 1.0) + { + if (useEventWeight) { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + } + auto origin = mcdjet.origin(); + if (mcdjet.template secondaryVertices_as().size() < 1) + return; + registry.fill(HIST("h3_jet_pt_centrality_flavour"), mcdjet.pt(), centrality, origin, eventWeight); + registry.fill(HIST("h3_jet_eta_centrality_flavour"), mcdjet.eta(), centrality, origin, eventWeight); + registry.fill(HIST("h3_jet_phi_centrality_flavour"), mcdjet.phi(), centrality, origin, eventWeight); + if (fillGeneralSVQA) { + registry.fill(HIST("h3_3prong_nprongs_centrality_flavour"), mcdjet.template secondaryVertices_as().size(), centrality, origin, eventWeight); + for (const auto& prong : mcdjet.template secondaryVertices_as()) { + registry.fill(HIST("hn_jet_3prong_Sxy_centrality_flavour"), mcdjet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality, origin, eventWeight); + if (fillSVxyz) { + registry.fill(HIST("hn_jet_3prong_Sxyz_centrality_flavour"), mcdjet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality, origin, eventWeight); + } + } + } + bool checkSv = false; + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); + if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + registry.fill(HIST("hn_jet_3prong_Sxy_N1_centrality_flavour"), mcdjet.pt(), maxSxy, massSV, centrality, origin, eventWeight); + if (mcdjet.isTagged(BJetTaggingMethod::SV)) { + registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_centrality_flavour"), mcdjet.pt(), maxSxy, massSV, centrality, origin, eventWeight); + } + } + if (fillSVxyz) { + auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); + if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { + auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); + auto massSV = bjetCandXYZ.m(); + registry.fill(HIST("hn_jet_3prong_Sxyz_N1_centrality_flavour"), mcdjet.pt(), maxSxyz, massSV, centrality, origin, eventWeight); + if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { + registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_centrality_flavour"), mcdjet.pt(), maxSxyz, massSV, centrality, origin, eventWeight); + } + } + } + } + + template + void fillRhoAreaSubtractedHistogramSV3ProngMCD(T const& mcdjet, U const& /*prongs*/, float centrality, float rho, float eventWeight = 1.0) + { + if (useEventWeight) { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (mcdjet.pt() > pTHatMaxMCD * pTHat) { + return; + } + } + auto origin = mcdjet.origin(); + if (mcdjet.template secondaryVertices_as().size() < 1) + return; + registry.fill(HIST("h3_jet_pt_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), centrality, origin, eventWeight); + registry.fill(HIST("h3_jet_eta_rhoareasubtracted_centrality_flavour"), mcdjet.eta(), centrality, origin, eventWeight); + registry.fill(HIST("h3_jet_phi_rhoareasubtracted_centrality_flavour"), mcdjet.phi(), centrality, origin, eventWeight); + if (fillGeneralSVQA) { + registry.fill(HIST("h3_3prong_nprongs_rhoareasubtracted_centrality_flavour"), mcdjet.template secondaryVertices_as().size(), centrality, origin, eventWeight); + for (const auto& prong : mcdjet.template secondaryVertices_as()) { + registry.fill(HIST("hn_jet_3prong_Sxy_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), centrality, origin, eventWeight); + if (fillSVxyz) { + registry.fill(HIST("hn_jet_3prong_Sxyz_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), centrality, origin, eventWeight); + } + } + } + bool checkSv = false; + auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); + if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { + auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); + auto massSV = bjetCand.m(); + registry.fill(HIST("hn_jet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxy, massSV, centrality, origin, eventWeight); + if (mcdjet.isTagged(BJetTaggingMethod::SV)) { + registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxy, massSV, centrality, origin, eventWeight); + } + } + if (fillSVxyz) { + auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); + if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { + auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); + auto massSV = bjetCandXYZ.m(); + registry.fill(HIST("hn_jet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxyz, massSV, centrality, origin, eventWeight); + if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { + registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_rhoareasubtracted_centrality_flavour"), mcdjet.pt() - (rho * mcdjet.area()), maxSxyz, massSV, centrality, origin, eventWeight); + } + } + } + } + + void processDummy(aod::Collision const&, aod::Tracks const&) + { + } + PROCESS_SWITCH(BjetCentMultTask, processDummy, "Dummy process", true); + + void processCentMultQa(soa::Filtered::iterator const& collision) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + float multFT0A = collision.multFT0A(); + float multFT0C = collision.multFT0C(); + float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); + float percentileMult = getPercentile(scaledFT0M); + registry.fill(HIST("h_amplitude_FT0A"), multFT0A); + registry.fill(HIST("h_amplitude_FT0C"), multFT0C); + registry.fill(HIST("h_scaled_FT0M"), scaledFT0M); + registry.fill(HIST("h_scaled_FT0M_class"), scaledFT0M); + registry.fill(HIST("h2_centrality_percentile_multiplicity"), collision.centFT0M(), percentileMult); + } + PROCESS_SWITCH(BjetCentMultTask, processCentMultQa, "Fill centality and mulitplicity qa", false); + + void processMCP(JetTableMCP const& mcpjets, aod::JetParticles const&, soa::Join const& mcCollisions, soa::Filtered> const& collisions) + { + for (auto const& mcpjet : mcpjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcpjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { + continue; + } + if (!isAcceptedJet(mcpjet)) { + continue; + } + auto mcCollision = mcCollisions.sliceBy(McCollisionsPerMCPCollision, mcpjet.mcCollisionId()); + if (mcCollision.size() == 1) { + float weight = useEventWeight ? mcCollision.begin().weight() : 1.f; + if (checkMcCollisionIsMatched) { + auto collisionspermcpjet = collisions.sliceBy(collisionsPerMCPCollision, mcpjet.mcCollisionId()); + if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits) && !collisionspermcpjet.begin().isOutlier()) { + fillHistogramMCP(mcpjet, weight, mcCollision.begin().ptHard()); + } + } else { + fillHistogramMCP(mcpjet, weight, mcCollision.begin().ptHard()); + } + } + } + } + PROCESS_SWITCH(BjetCentMultTask, processMCP, "Fill impact parameter imformation for mcp jets", false); + + void processSV3ProngData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + float centrality = collision.centFT0M(); + registry.fill(HIST("h_event_centrality"), centrality); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillHistogramSV3ProngData(jet, prongs, centrality); + } + } + PROCESS_SWITCH(BjetCentMultTask, processSV3ProngData, "Fill 3prong imformation for data jets", false); + + void processSV3ProngMCD(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (collision.isOutlier()) { + return; + } + float centrality = collision.centFT0M(); + float weight = useEventWeight ? collision.weight() : 1.f; + registry.fill(HIST("h_event_centrality"), collision.centFT0M()); + for (auto const& mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillHistogramSV3ProngMCD(mcdjet, prongs, centrality, weight); + } + } + PROCESS_SWITCH(BjetCentMultTask, processSV3ProngMCD, "Fill 3prong imformation for mcd jets", false); + + void processSV3ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (collision.isOutlier()) { + return; + } + float centrality = collision.centFT0M(); + float weight = useEventWeight ? collision.weight() : 1.f; + registry.fill(HIST("h_event_centrality"), collision.centFT0M()); + for (auto const& mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + if (!mcdjet.has_matchedJetGeo()) { + continue; + } + fillHistogramSV3ProngMCD(mcdjet, prongs, centrality, weight); + } + } + PROCESS_SWITCH(BjetCentMultTask, processSV3ProngMCPMCDMatched, "Fill 3prong imformation for mcd jets matched", false); + + void processRhoAreaSubSV3ProngMCD(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (collision.isOutlier()) { + return; + } + float centrality = collision.centFT0M(); + float rho = collision.rho(); + float weight = useEventWeight ? collision.weight() : 1.f; + registry.fill(HIST("h_event_rhoareasubtracted_centrality"), collision.centFT0M()); + for (auto const& mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + fillRhoAreaSubtractedHistogramSV3ProngMCD(mcdjet, prongs, centrality, rho, weight); + } + } + PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSV3ProngMCD, "Fill 3prong imformation for mcd jets with background subraction", false); + + void processRhoAreaSubSV3ProngMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (collision.isOutlier()) { + return; + } + float centrality = collision.centFT0M(); + float rho = collision.rho(); + float weight = useEventWeight ? collision.weight() : 1.f; + registry.fill(HIST("h_event_rhoareasubtracted_centrality"), collision.centFT0M()); + for (auto const& mcdjet : mcdjets) { + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { + continue; + } + if (!isAcceptedJet(mcdjet)) { + continue; + } + if (!mcdjet.has_matchedJetGeo()) { + continue; + } + fillRhoAreaSubtractedHistogramSV3ProngMCD(mcdjet, prongs, centrality, rho, weight); + } + } + PROCESS_SWITCH(BjetCentMultTask, processRhoAreaSubSV3ProngMCPMCDMatched, "Fill 3prong imformation for mcd jets matched with background subtraction", false); +}; + +using BjetCentMultChargedDataJets = soa::Join; +using BjetCentMultChargedMCDJets = soa::Join; +using BjetCentMultChargedMCPJets = soa::Join; + +using BjetCentMultCharged = BjetCentMultTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"bjet-cent-mult-charged"})}; // o2-linter: disable=name/o2-task (templated struct) +} diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index 03ef54ab2e8..8a48eab4af5 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -20,28 +20,35 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetTagging.h" -#include "Common/CCDB/TriggerAliases.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" #include "Common/DataModel/EventSelection.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include #include +#include #include #include +#include #include -#include +#include + #include #include #include -#include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -126,6 +133,7 @@ struct BjetTaggingGnn { Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; // track level configurables + Configurable trackSelections{"trackSelections", "QualityTracks", "set track selections"}; Configurable trackPtMin{"trackPtMin", 0.15, "minimum track pT"}; Configurable trackPtMax{"trackPtMax", 1000.0, "maximum track pT"}; Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track eta"}; @@ -153,6 +161,7 @@ struct BjetTaggingGnn { Configurable dbNbins{"dbNbins", 3000, "number of bins in axisDbFine"}; Configurable doDataDriven{"doDataDriven", false, "Flag whether to use fill THnSpase for data driven methods"}; + Configurable doDataDrivenExtra{"doDataDrivenExtra", false, "Flag whether to add extra axes to THnSparses"}; Configurable callSumw2{"callSumw2", false, "Flag whether to call THnSparse::Sumw2() for error calculation"}; Configurable trainingDatasetRatioParam{"trainingDatasetRatioParam", 0, "Parameter for splitting training/evaluation datasets by collisionId"}; @@ -174,6 +183,8 @@ struct BjetTaggingGnn { std::vector eventSelectionBitsSelMC; std::vector eventSelectionBitsSel8; + int trackSelectionBits; + std::vector jetRadiiValues; void init(InitContext const&) @@ -185,13 +196,19 @@ struct BjetTaggingGnn { eventSelectionBitsSel8 = jetderiveddatautilities::initialiseEventSelectionBits("sel8"); eventSelectionBitsSelMC = jetderiveddatautilities::initialiseEventSelectionBits("selMC"); + trackSelectionBits = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + + if (doprocessDataJetsTrig) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + registry.add("h_event_counter", ";analysis collision counter", {HistType::kTH1F, {{1, 0.0, 1.0}}}, callSumw2); registry.add("h_event_counter_mcp", ";analysis collision matched MC collision counter", {HistType::kTH1F, {{1, 0.0, 1.0}}}, callSumw2); registry.add("h_vertexZ", "Vertex Z;#it{Z} (cm)", {HistType::kTH1F, {{100, -20.0, 20.0}}}, callSumw2); registry.add("hCollCounter", ";collision counter", {HistType::kTH1F, {{12, 1.0, 13.0}}}, callSumw2); auto hCollCounter = registry.get(HIST("hCollCounter")); - hCollCounter->GetXaxis()->SetBinLabel(1, ""); - hCollCounter->GetXaxis()->SetBinLabel(2, ""); + hCollCounter->GetXaxis()->SetBinLabel(1, "_1"); + hCollCounter->GetXaxis()->SetBinLabel(2, "_2"); hCollCounter->GetXaxis()->SetBinLabel(3, "Coll"); hCollCounter->GetXaxis()->SetBinLabel(4, "Coll+Zvtx"); hCollCounter->GetXaxis()->SetBinLabel(5, "Coll+TVX"); @@ -200,7 +217,7 @@ struct BjetTaggingGnn { hCollCounter->GetXaxis()->SetBinLabel(8, "Coll+TVX+NoTFB+Zvtx"); hCollCounter->GetXaxis()->SetBinLabel(9, "Coll+TVX+NoTFB+NoITSROFB"); // sel8 hCollCounter->GetXaxis()->SetBinLabel(10, "Coll+TVX+NoTFB+NoITSROFB+Zvtx"); - hCollCounter->GetXaxis()->SetBinLabel(11, ""); + hCollCounter->GetXaxis()->SetBinLabel(11, "_11"); hCollCounter->GetXaxis()->SetBinLabel(12, "INELgt0+Zvtx(rec)"); // sel8 registry.add("hMcCollCounter", ";MC collision counter", {HistType::kTH1F, {{12, 1.0, 13.0}}}, callSumw2); auto hMcCollCounter = registry.get(HIST("hMcCollCounter")); @@ -231,7 +248,8 @@ struct BjetTaggingGnn { const AxisSpec axisTrackpT{200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisTrackpTFine{1000, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec axisJetpT{200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisJetpT{250, 0., 250., "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisJetEta{200, -0.8, 0.8, "#it{#eta}_{jet}"}; const AxisSpec axisDb{200, dbMin, dbMax, "#it{D}_{b}"}; const AxisSpec axisDbFine{dbNbins, dbMin, dbMax, "#it{D}_{b}"}; const AxisSpec axisJetMass{200, 0., 50., "#it{m}_{jet} (GeV/#it{c}^{2})"}; @@ -239,13 +257,35 @@ struct BjetTaggingGnn { const AxisSpec axisNTracks{42, 0, 42, "#it{n}_{tracks}"}; registry.add("h_jetpT", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); + registry.add("h_jetEta", "", {HistType::kTH1F, {axisJetEta}}, callSumw2); + registry.add("h_jetPhi", "", {HistType::kTH1F, {{200, 0., 2. * M_PI, "#it{phi}_{jet}"}}}); + registry.add("h_jetMass", "", {HistType::kTH1F, {axisJetMass}}); registry.add("h_Db", "", {HistType::kTH1F, {axisDbFine}}); registry.add("h2_jetpT_Db", "", {HistType::kTH2F, {axisJetpT, axisDb}}); + registry.add("h2_nTracks_Db", "", {HistType::kTH2F, {axisNTracks, axisDb}}); + + registry.add("h_gnnfeat_trackpT", "", {HistType::kTH1F, {{200, 0., 100., "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("h_gnnfeat_trackPhi", "", {HistType::kTH1F, {{200, 0., 2. * M_PI, "#it{#phi}"}}}); + registry.add("h_gnnfeat_trackEta", "", {HistType::kTH1F, {{200, -0.9, 0.9, "#it{#eta}"}}}); + registry.add("h_gnnfeat_trackCharge", "", {HistType::kTH1F, {{3, -1., 2., "#it{q}"}}}); + registry.add("h_gnnfeat_trackDCAxy", "", {HistType::kTH1F, {{200, -5., 5., "DCA_{#it{xy}} (cm)"}}}); + registry.add("h_gnnfeat_trackSigmaDCAxy", "", {HistType::kTH1F, {{200, 0., 5., "#it{#sigma}_{{DCA_{#it{xy}}} (cm)"}}}); + registry.add("h_gnnfeat_trackDCAz", "", {HistType::kTH1F, {{200, -5., 5., "DCA_{#it{z}} (cm)"}}}); + registry.add("h_gnnfeat_trackSigmaDCAz", "", {HistType::kTH1F, {{200, 0., 5., "#it{#sigma}_{{DCA_{#it{z}}} (cm)"}}}); + registry.add("h_gnnfeat_trackITSChi2NCl", "", {HistType::kTH1F, {{200, 0., 40., "ITS #it{#chi}^{2}/ndf"}}}); + registry.add("h_gnnfeat_trackTPCChi2NCl", "", {HistType::kTH1F, {{200, 0., 5., "TPC #it{#chi}^{2}/ndf"}}}); + registry.add("h_gnnfeat_trackITSNCls", "", {HistType::kTH1F, {{8, 0., 8., "ITS NCls"}}}); + registry.add("h_gnnfeat_trackTPCNCls", "", {HistType::kTH1F, {{153, 0., 153., "TPC NCls"}}}); + registry.add("h_gnnfeat_trackTPCNCrossedRows", "", {HistType::kTH1F, {{153, 0., 153., "TPC NCrossedRows"}}}); + registry.add("h_gnnfeat_tracksIPxy", "", {HistType::kTH1F, {{200, -5., 5., "{sIP}_{#it{xy}}"}}}); + registry.add("h_gnnfeat_tracksIPz", "", {HistType::kTH1F, {{200, -5., 5., "{sIP}_{#it{z}}"}}}); if (doprocessDataTracks || doprocessMCDTracks) { registry.add("h_trackpT", "", {HistType::kTH1F, {axisTrackpT}}, callSumw2); registry.add("h_tracketa", "", {HistType::kTH1F, {{100, trackEtaMin, trackEtaMax, "#it{#eta}"}}}, callSumw2); registry.add("h_trackphi", "", {HistType::kTH1F, {{100, 0.0, 2.0 * M_PI, "#it{#phi}"}}}, callSumw2); + registry.add("h_dcaXY", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); } if (doprocessMCDTracks) { @@ -253,6 +293,23 @@ struct BjetTaggingGnn { registry.add("h_partpT_matched_fine", "", {HistType::kTH1F, {axisTrackpTFine}}, callSumw2); registry.add("h_partpT", "", {HistType::kTH1F, {axisTrackpT}}, callSumw2); registry.add("h_partpT_fine", "", {HistType::kTH1F, {axisTrackpTFine}}, callSumw2); + // DCA cut study histograms (pT > pTMin) + registry.add("h_dcaXY_coll_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from fake collisions + registry.add("h_dcaXY_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // fake tracks (no matched particle) + registry.add("h_dcaXY_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions + registry.add("h_dcaXY_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, b hadron decay + registry.add("h_dcaXY_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, c hadron decay + registry.add("h_dcaXY_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from matched collisions, others + registry.add("h_dcaXY_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // tracks from mismatched collisions + registry.add("h_dcaXY_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{xy}}| (cm)"}}}, callSumw2); // non-physical primary tracks (GenStatusCode=-1) + registry.add("h_dcaZ_coll_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_fake", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_b", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_c", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_matched_lf", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_coll_mismatched", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); + registry.add("h_dcaZ_npp", "", {HistType::kTH1F, {{200, 0., 4., "|DCA_{#it{z}}| (cm)"}}}, callSumw2); } if (doprocessDataJetsSel || doprocessMCDJetsSel) { @@ -277,6 +334,9 @@ struct BjetTaggingGnn { registry.add("h2_jetpT_Db_b", "b-jet", {HistType::kTH2F, {axisJetpT, axisDb}}); registry.add("h2_jetpT_Db_c", "c-jet", {HistType::kTH2F, {axisJetpT, axisDb}}); registry.add("h2_jetpT_Db_lf", "lf-jet", {HistType::kTH2F, {axisJetpT, axisDb}}); + registry.add("h2_nTracks_Db_b", "b-jet", {HistType::kTH2F, {axisNTracks, axisDb}}); + registry.add("h2_nTracks_Db_c", "c-jet", {HistType::kTH2F, {axisNTracks, axisDb}}); + registry.add("h2_nTracks_Db_lf", "lf-jet", {HistType::kTH2F, {axisNTracks, axisDb}}); registry.add("h2_Response_DetjetpT_PartjetpT", "", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); registry.add("h2_Response_DetjetpT_PartjetpT_b", "b-jet", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); registry.add("h2_Response_DetjetpT_PartjetpT_c", "c-jet", {HistType::kTH2F, {axisJetpT, axisJetpT}}, callSumw2); @@ -295,7 +355,6 @@ struct BjetTaggingGnn { registry.add("h_jetpT_particle_matched", "", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_b_matched", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); registry.add("h_jetpT_particle_b_matched", "b-jet", {HistType::kTH1F, {axisJetpT}}, callSumw2); - registry.add("hSparse_overflow_b", "", {HistType::kTHnSparseF, {axisJetpT, axisJetpT, axisNTracks}}); } if (doprocessMCDJetsSel) { @@ -357,13 +416,24 @@ struct BjetTaggingGnn { } if (doDataDriven) { - registry.add("hSparse_Incljets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); - if (doprocessMCDJets) { - registry.add("hSparse_bjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); - registry.add("hSparse_cjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); - registry.add("hSparse_lfjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); - registry.add("hSparse_lfjets_none", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); - registry.add("hSparse_lfjets_matched", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + if (doDataDrivenExtra) { + registry.add("hSparse_Incljets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks, axisJetMass}}, callSumw2); + if (doprocessMCDJets) { + registry.add("hSparse_bjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks, axisJetMass}}, callSumw2); + registry.add("hSparse_cjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks, axisJetMass}}, callSumw2); + registry.add("hSparse_lfjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks, axisJetMass}}, callSumw2); + registry.add("hSparse_lfjets_none", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks, axisJetMass}}, callSumw2); + registry.add("hSparse_lfjets_matched", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks, axisJetMass}}, callSumw2); + } + } else { + registry.add("hSparse_Incljets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + if (doprocessMCDJets) { + registry.add("hSparse_bjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + registry.add("hSparse_cjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + registry.add("hSparse_lfjets", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + registry.add("hSparse_lfjets_none", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + registry.add("hSparse_lfjets_matched", "", {HistType::kTHnSparseF, {axisJetpT, axisDbFine, axisNTracks}}, callSumw2); + } } } } @@ -374,13 +444,14 @@ struct BjetTaggingGnn { using AnalysisCollisions = soa::Join; using FilteredCollisions = soa::Filtered; - using AnalysisCollisionsTriggered = soa::Join; + using AnalysisCollisionsTriggered = soa::Join; using FilteredCollisionsTriggered = soa::Filtered; using OrigCollisions = soa::Join; using DataJets = soa::Join; using FilteredDataJets = soa::Filtered; using AnalysisTracks = soa::Join; using FilteredTracks = soa::Filtered; + using OriginalTracks = soa::Join; using MCDJets = soa::Join; using FilteredMCDJets = soa::Filtered; @@ -395,8 +466,8 @@ struct BjetTaggingGnn { using MCPJets = soa::Join; using FilteredMCPJets = soa::Filtered; - template - int analyzeJetTrackInfo(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/ /*, int8_t jetFlavor = 0, double weight = 1.0*/) + template + int analyzeJetTrackInfo(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const /*origTracks*/ /*, int8_t jetFlavor = 0, double weight = 1.0*/) { int nTracks = 0; for (const auto& constituent : analysisJet.template tracks_as()) { @@ -405,7 +476,25 @@ struct BjetTaggingGnn { continue; } - // ... + int sign = jettaggingutilities::getGeoSign(analysisJet, constituent); + auto origConstit = constituent.template track_as(); + + registry.fill(HIST("h_gnnfeat_trackpT"), constituent.pt()); + registry.fill(HIST("h_gnnfeat_trackPhi"), origConstit.phi()); + registry.fill(HIST("h_gnnfeat_trackEta"), constituent.eta()); + registry.fill(HIST("h_gnnfeat_trackCharge"), static_cast(constituent.sign())); + registry.fill(HIST("h_gnnfeat_trackDCAxy"), std::abs(constituent.dcaXY()) * sign); + registry.fill(HIST("h_gnnfeat_trackSigmaDCAxy"), constituent.sigmadcaXY()); + registry.fill(HIST("h_gnnfeat_trackDCAz"), std::abs(constituent.dcaZ()) * sign); + registry.fill(HIST("h_gnnfeat_trackSigmaDCAz"), constituent.sigmadcaZ()); + registry.fill(HIST("h_gnnfeat_trackITSNCls"), static_cast(origConstit.itsNCls())); + registry.fill(HIST("h_gnnfeat_trackTPCNCls"), static_cast(origConstit.tpcNClsFound())); + registry.fill(HIST("h_gnnfeat_trackTPCNCrossedRows"), static_cast(origConstit.tpcNClsCrossedRows())); + registry.fill(HIST("h_gnnfeat_trackITSChi2NCl"), origConstit.itsChi2NCl()); + registry.fill(HIST("h_gnnfeat_trackTPCChi2NCl"), origConstit.tpcChi2NCl()); + + registry.fill(HIST("h_gnnfeat_tracksIPxy"), std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY()); + registry.fill(HIST("h_gnnfeat_tracksIPz"), std::abs(constituent.dcaZ()) * sign / constituent.sigmadcaZ()); ++nTracks; } @@ -448,22 +537,30 @@ struct BjetTaggingGnn { return true; } - template - void fillDataJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& allTracks) + template + void fillDataJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& allTracks, AnyOriginalTracks const& origTracks) { - int nTracks = analyzeJetTrackInfo(analysisJet, allTracks); + int nTracks = analyzeJetTrackInfo(analysisJet, allTracks, origTracks); registry.fill(HIST("h_jetpT"), analysisJet.pt()); + registry.fill(HIST("h_jetPhi"), analysisJet.phi()); + registry.fill(HIST("h_jetEta"), analysisJet.eta()); + registry.fill(HIST("h_jetMass"), analysisJet.mass()); registry.fill(HIST("h_Db"), analysisJet.scoreML()); registry.fill(HIST("h2_jetpT_Db"), analysisJet.pt(), analysisJet.scoreML()); + registry.fill(HIST("h2_nTracks_Db"), nTracks, analysisJet.scoreML()); if (doDataDriven) { - registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), nTracks); + if (doDataDrivenExtra) { + registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass()); + } else { + registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), nTracks); + } } } - template - int8_t fillMCDJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, double weightEvt = 1.0) + template + int8_t fillMCDJetHistograms(AnalysisJet const& analysisJet, AnyTracks const& /*allTracks*/, AnyOriginalTracks const& /*origTracks*/, double weightEvt = 1.0) { int8_t jetFlavor = analysisJet.origin(); @@ -476,25 +573,53 @@ struct BjetTaggingGnn { if (!constituent.has_mcParticle() || !constituent.template mcParticle_as().isPhysicalPrimary()) { ++nNppTracks; } + + int sign = jettaggingutilities::getGeoSign(analysisJet, constituent); + auto origConstit = constituent.template track_as(); + + registry.fill(HIST("h_gnnfeat_trackpT"), constituent.pt()); + registry.fill(HIST("h_gnnfeat_trackPhi"), origConstit.phi()); + registry.fill(HIST("h_gnnfeat_trackEta"), constituent.eta()); + registry.fill(HIST("h_gnnfeat_trackCharge"), static_cast(constituent.sign())); + registry.fill(HIST("h_gnnfeat_trackDCAxy"), std::abs(constituent.dcaXY()) * sign); + registry.fill(HIST("h_gnnfeat_trackSigmaDCAxy"), constituent.sigmadcaXY()); + registry.fill(HIST("h_gnnfeat_trackDCAz"), std::abs(constituent.dcaZ()) * sign); + registry.fill(HIST("h_gnnfeat_trackSigmaDCAz"), constituent.sigmadcaZ()); + registry.fill(HIST("h_gnnfeat_trackITSNCls"), static_cast(origConstit.itsNCls())); + registry.fill(HIST("h_gnnfeat_trackTPCNCls"), static_cast(origConstit.tpcNClsFound())); + registry.fill(HIST("h_gnnfeat_trackTPCNCrossedRows"), static_cast(origConstit.tpcNClsCrossedRows())); + registry.fill(HIST("h_gnnfeat_trackITSChi2NCl"), origConstit.itsChi2NCl()); + registry.fill(HIST("h_gnnfeat_trackTPCChi2NCl"), origConstit.tpcChi2NCl()); + + registry.fill(HIST("h_gnnfeat_tracksIPxy"), std::abs(constituent.dcaXY()) * sign / constituent.sigmadcaXY()); + registry.fill(HIST("h_gnnfeat_tracksIPz"), std::abs(constituent.dcaZ()) * sign / constituent.sigmadcaZ()); + ++nTracks; } registry.fill(HIST("h_jetpT"), analysisJet.pt(), weightEvt); + registry.fill(HIST("h_jetPhi"), analysisJet.phi(), weightEvt); + registry.fill(HIST("h_jetEta"), analysisJet.eta(), weightEvt); + registry.fill(HIST("h_jetMass"), analysisJet.mass(), weightEvt); registry.fill(HIST("h_Db"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db"), nTracks, analysisJet.scoreML(), weightEvt); if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h_jetpT_b"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_Db_b"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db_b"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db_b"), nTracks, analysisJet.scoreML(), weightEvt); } else if (jetFlavor == JetTaggingSpecies::charm) { registry.fill(HIST("h_jetpT_c"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_Db_c"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db_c"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db_c"), nTracks, analysisJet.scoreML(), weightEvt); } else { registry.fill(HIST("h_jetpT_lf"), analysisJet.pt(), weightEvt); registry.fill(HIST("h_Db_lf"), analysisJet.scoreML(), weightEvt); registry.fill(HIST("h2_jetpT_Db_lf"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); + registry.fill(HIST("h2_nTracks_Db_lf"), nTracks, analysisJet.scoreML(), weightEvt); if (jetFlavor == JetTaggingSpecies::none) { registry.fill(HIST("h2_jetpT_Db_lf_none"), analysisJet.pt(), analysisJet.scoreML(), weightEvt); } else { @@ -519,17 +644,33 @@ struct BjetTaggingGnn { } if (doDataDriven) { - registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("hSparse_bjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("hSparse_cjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + if (doDataDrivenExtra) { + registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass(), weightEvt); + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("hSparse_bjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass(), weightEvt); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("hSparse_cjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass(), weightEvt); + } else { + registry.fill(HIST("hSparse_lfjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass(), weightEvt); + if (jetFlavor == JetTaggingSpecies::none) { + registry.fill(HIST("hSparse_lfjets_none"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass(), weightEvt); + } else { + registry.fill(HIST("hSparse_lfjets_matched"), analysisJet.pt(), analysisJet.scoreML(), nTracks, analysisJet.mass(), weightEvt); + } + } } else { - registry.fill(HIST("hSparse_lfjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); - if (jetFlavor == JetTaggingSpecies::none) { - registry.fill(HIST("hSparse_lfjets_none"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("hSparse_bjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("hSparse_cjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); } else { - registry.fill(HIST("hSparse_lfjets_matched"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + registry.fill(HIST("hSparse_lfjets"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + if (jetFlavor == JetTaggingSpecies::none) { + registry.fill(HIST("hSparse_lfjets_none"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + } else { + registry.fill(HIST("hSparse_lfjets_matched"), analysisJet.pt(), analysisJet.scoreML(), nTracks, weightEvt); + } } } } @@ -611,7 +752,7 @@ struct BjetTaggingGnn { } PROCESS_SWITCH(BjetTaggingGnn, processDummy, "Dummy process function turned on by default", true); - void processDataJets(FilteredCollisions::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks) + void processDataJets(FilteredCollisions::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, OriginalTracks const& origTracks) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -625,12 +766,12 @@ struct BjetTaggingGnn { continue; } - fillDataJetHistograms(analysisJet, allTracks); + fillDataJetHistograms(analysisJet, allTracks, origTracks); } } PROCESS_SWITCH(BjetTaggingGnn, processDataJets, "jet information in Data", false); - void processDataJetsTrig(FilteredCollisionsTriggered::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, aod::JBCs const& /*bcInfo*/) + void processDataJetsTrig(FilteredCollisionsTriggered::iterator const& collision, FilteredDataJets const& alljets, FilteredTracks const& allTracks, OriginalTracks const& origTracks, aod::JBCs const& /*bcInfo*/) { // Get BC info associated with the collision before applying any event selections auto bc = collision.bc_as(); @@ -653,7 +794,7 @@ struct BjetTaggingGnn { continue; } - fillDataJetHistograms(analysisJet, allTracks); + fillDataJetHistograms(analysisJet, allTracks, origTracks); } } PROCESS_SWITCH(BjetTaggingGnn, processDataJetsTrig, "jet information in software triggered Data", false); @@ -693,11 +834,15 @@ struct BjetTaggingGnn { registry.fill(HIST("h_trackpT"), track.pt()); registry.fill(HIST("h_tracketa"), track.eta()); registry.fill(HIST("h_trackphi"), track.phi()); + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY"), std::fabs(track.dcaXY())); + registry.fill(HIST("h_dcaZ"), std::fabs(track.dcaZ())); + } } } PROCESS_SWITCH(BjetTaggingGnn, processDataTracks, "track information in Data", false); - void processMCDJets(FilteredCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& allTracks, FilteredMCPJets const& /*MCPjets*/, aod::JetParticles const& /*mcParticles*/, FilteredCollisionsMCP const& /*mcCollisions*/) + void processMCDJets(FilteredCollisionsMCD::iterator const& collision, FilteredMCDJets const& MCDjets, FilteredTracksMCD const& allTracks, OriginalTracks const& origTracks, FilteredMCPJets const& /*MCPjets*/, aod::JetParticles const& /*mcParticles*/, FilteredCollisionsMCP const& /*mcCollisions*/) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -724,7 +869,7 @@ struct BjetTaggingGnn { continue; } - int8_t jetFlavor = fillMCDJetHistograms(analysisJet, allTracks, weightEvt); + int8_t jetFlavor = fillMCDJetHistograms(analysisJet, allTracks, origTracks, weightEvt); if (!matchedMcColl) { continue; @@ -960,20 +1105,63 @@ struct BjetTaggingGnn { bool matchedMcColl = collision.has_mcCollision() && std::fabs(collision.template mcCollision_as().posZ()) < vertexZCut; for (const auto& track : tracks) { - if (track.eta() <= trackEtaMin || track.eta() >= trackEtaMax) { + if (!jetderiveddatautilities::selectTrack(track, trackSelectionBits) || track.eta() <= trackEtaMin || track.eta() >= trackEtaMax) { continue; } registry.fill(HIST("h_trackpT"), track.pt(), weightEvt); registry.fill(HIST("h_tracketa"), track.eta(), weightEvt); registry.fill(HIST("h_trackphi"), track.phi(), weightEvt); + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ"), std::fabs(track.dcaZ()), weightEvt); + } - if (!matchedMcColl || !track.has_mcParticle()) { + if (!matchedMcColl) { + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY_coll_fake"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_fake"), std::fabs(track.dcaZ()), weightEvt); + } + continue; + } + if (!track.has_mcParticle()) { + if (track.pt() >= trackPtMin) { + registry.fill(HIST("h_dcaXY_fake"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_fake"), std::fabs(track.dcaZ()), weightEvt); + } continue; } auto particle = track.template mcParticle_as(); - if (particle.isPhysicalPrimary() && particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { - registry.fill(HIST("h2_trackpT_partpT"), track.pt(), particle.pt(), weightEvt); - registry.fill(HIST("h_partpT_matched_fine"), particle.pt(), weightEvt); + if (particle.eta() > trackEtaMin && particle.eta() < trackEtaMax) { + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("h2_trackpT_partpT"), track.pt(), particle.pt(), weightEvt); + registry.fill(HIST("h_partpT_matched_fine"), particle.pt(), weightEvt); + } + if (track.pt() >= trackPtMin) { + // Track association accuracy as a function of DCA + if (particle.isPhysicalPrimary()) { + if (particle.mcCollisionId() == collision.mcCollisionId()) { + registry.fill(HIST("h_dcaXY_coll_matched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from the same MC collision + registry.fill(HIST("h_dcaZ_coll_matched"), std::fabs(track.dcaZ()), weightEvt); + int origin = RecoDecay::getParticleOrigin(allParticles, particle, false); + if (origin == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("h_dcaXY_coll_matched_b"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_matched_b"), std::fabs(track.dcaZ()), weightEvt); + } else if (origin == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("h_dcaXY_coll_matched_c"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_matched_c"), std::fabs(track.dcaZ()), weightEvt); + } else { + registry.fill(HIST("h_dcaXY_coll_matched_lf"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_coll_matched_lf"), std::fabs(track.dcaZ()), weightEvt); + } + } else { + registry.fill(HIST("h_dcaXY_coll_mismatched"), std::fabs(track.dcaXY()), weightEvt); // Matched to particle from a different MC collision + registry.fill(HIST("h_dcaZ_coll_mismatched"), std::fabs(track.dcaZ()), weightEvt); + } + } else { + registry.fill(HIST("h_dcaXY_npp"), std::fabs(track.dcaXY()), weightEvt); + registry.fill(HIST("h_dcaZ_npp"), std::fabs(track.dcaZ()), weightEvt); + } + } } } diff --git a/PWGJE/Tasks/bjetTaggingML.cxx b/PWGJE/Tasks/bjetTaggingML.cxx index 6e1b135b745..002f3b4bf02 100644 --- a/PWGJE/Tasks/bjetTaggingML.cxx +++ b/PWGJE/Tasks/bjetTaggingML.cxx @@ -23,10 +23,10 @@ #include "Common/Core/RecoDecay.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/bjetTreeCreator.cxx b/PWGJE/Tasks/bjetTreeCreator.cxx index 4065a6cf334..a5c85560f26 100644 --- a/PWGJE/Tasks/bjetTreeCreator.cxx +++ b/PWGJE/Tasks/bjetTreeCreator.cxx @@ -25,13 +25,13 @@ #include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include +#include #include +#include #include +#include #include #include #include @@ -49,6 +49,8 @@ #include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/chargedJetHadron.cxx b/PWGJE/Tasks/chargedJetHadron.cxx index 81db287268e..fd4b5831977 100644 --- a/PWGJE/Tasks/chargedJetHadron.cxx +++ b/PWGJE/Tasks/chargedJetHadron.cxx @@ -21,14 +21,14 @@ #include "Common/Core/RecoDecay.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include #include #include #include +#include #include #include #include @@ -46,7 +46,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::math; -const double absPiCut = 1.5; const double assoHadronPtCut = 2.0; static const float kNaN = std::numeric_limits::quiet_NaN(); @@ -59,6 +58,7 @@ struct ChargedJetHadron { Configurable centralityMax{"centralityMax", 100.0, "maximum centrality"}; Configurable leadingjetptMin{"leadingjetptMin", 20.0, "minimum leadingjetpt"}; Configurable subleadingjetptMin{"subleadingjetptMin", 10.0, "minimum subleadingjetpt"}; + Configurable dijetDphiCut{"dijetDphiCut", 0.5, "minimum dijetDphiCut"}; Configurable assoHadronPtMaxCut{"assoHadronPtMaxCut", 10.0, "maximum associate hadron pt cut"}; Configurable etaGapdw{"etaGapdw", 0.5, "dijet eta gap low threshold"}; Configurable etaGapup{"etaGapup", 1.0, "dijet eta gap high threshold"}; @@ -82,7 +82,7 @@ struct ChargedJetHadron { Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events; jet-level rejection can also be applied at the jet finder level for jets only, here rejection is applied for collision and track process functions for the first time, and on jets in case it was set to false at the jet finder level"}; Configurable checkLeadConstituentPtForMcpJets{"checkLeadConstituentPtForMcpJets", false, "flag to choose whether particle level jets should have their lead track pt above leadingConstituentPtMin to be accepted; off by default, as leadingConstituentPtMin cut is only applied on MCD jets for the Pb-Pb analysis using pp MC anchored to Pb-Pb for the response matrix"}; Configurable doDijetRaa{"doDijetRaa", false, "0: all axis fill of thnsparse, 1: partial filling of thnsparse"}; - // + Configurable doEventWeighted{"doEventWeighted", false, "0: weight is 1 for MB Sample, 1: weight from Jet-Jet Sample"}; Configurable cfgCentEstimator{"cfgCentEstimator", 0, "0:FT0C; 1:FT0A; 2:FT0M"}; Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; @@ -106,7 +106,6 @@ struct ChargedJetHadron { using FilterMcpCollision = soa::Filtered>::iterator; using FilterMcpCollisions = soa::Filtered>; using FilterJetTracks = soa::Filtered; - using CorrChargedJets = soa::Join; using CorrChargedMCDJets = soa::Join; using CorrChargedMCPJets = soa::Join; @@ -129,8 +128,7 @@ struct ChargedJetHadron { BinningType corrBinning{{binsZVtx, binsCentrality}, true}; BinningTypeMC corrBinningMC{{binsZVtx, binsCentrality}, true}; - ////////////////////////////////////////// - HistogramRegistry registry; + HistogramRegistry registry; // histogram registry std::vector eventSelectionBits; int trackSelection = -1; @@ -155,34 +153,30 @@ struct ChargedJetHadron { AxisSpec centralityAxis = {110, -5., 105., "Centrality"}; AxisSpec trackPtAxis = {200, 0.0, 200.0, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec etaAxis = {100, -1.0, 1.0, "#eta"}; - AxisSpec phiAxis = {70, -0.5, 6.5, "#varphi"}; + AxisSpec etaAxis = {40, -1.0, 1.0, "#eta"}; + AxisSpec phiAxis = {65, -0.2, 6.3, "#varphi"}; AxisSpec jetPtAxis = {200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; AxisSpec jetPtAxisRhoAreaSub = {280, -80., 200., "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec jetmultetaAxis = {100, -0.5, 0.5, "#Delta#eta"}; - AxisSpec dphiAxis = {140, -1.7, 5.3, "#Delta#varphi"}; - AxisSpec dphijetAxis = {160, -1.7, 6.3, "#Delta#varphi"}; - AxisSpec detaAxis = {160, -1.6, 1.6, "#Delta#eta"}; - AxisSpec drAxis = {200, 0.0, 5.0, "#Delta#it{R}"}; + AxisSpec jetmultetaAxis = {4, -0.5, 0.5, "#Delta#eta"}; + AxisSpec detaAxis = {64, -1.6, 1.6, "#Delta#eta"}; + AxisSpec dphiAxis = {70, -1.7, 5.3, "#Delta#varphi"}; + AxisSpec drAxis = {60, 0.0, 1.5, "#Delta#it{R}"}; AxisSpec axisBdtScore = {100, 0., 1., "Bdt score"}; if (doprocessCollisionsQCData || doprocessCollisionsQCMCD) { - registry.add("h_collisions", "event status;event status; entries", {HistType::kTH1F, {{5, 0.0, 5.0}}}); + registry.add("h_collisions", "event status;event status; entries", {HistType::kTH1F, {{7, 0.0, 7.0}}}); + registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{7, 0.0, 7.0}}}); registry.add("h_fakecollisions", "event status;event status; entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); registry.add("h2_centrality_occupancy", "centrality vs occupancy; centrality; occupancy", {HistType::kTH2F, {centralityAxis, {60, 0, 30000}}}); registry.add("h_collisions_Zvertex", "position of collision; #it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}); - registry.add("h_collisions_multFT0", " multiplicity using multFT0; entries", {HistType::kTH1F, {{3000, 0, 10000}}}); - if (doprocessCollisionsQCMCD) { - registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - } - registry.add("h_track_pt", "track #it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}); + registry.add("h_collisions_multFT0", " multiplicity using multFT0; entries", {HistType::kTH1F, {{300, 0, 60000}}}); registry.add("h2_track_eta_track_phi", "track #eta vs. track #phi; #eta; #phi; counts", {HistType::kTH2F, {etaAxis, phiAxis}}); registry.add("h2_track_eta_pt", "track #eta vs. track #it{p}_{T}; #eta; #it{p}_{T,track} (GeV/#it{c}; counts", {HistType::kTH2F, {etaAxis, trackPtAxis}}); registry.add("h2_track_phi_pt", "track #phi vs. track #it{p}_{T}; #phi; #it{p}_{T,track} (GeV/#it{c}; counts", {HistType::kTH2F, {phiAxis, trackPtAxis}}); } - if (doprocessSpectraAreaSubData || doprocessSpectraAreaSubMCD || doprocessSpectraMCDWeighted) { - if (doprocessSpectraMCDWeighted) { + if (doprocessSpectraAreaSubData || doprocessSpectraAreaSubMCD) { + if (doprocessSpectraAreaSubMCD && doEventWeighted) { registry.add("h_jet_phat", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); registry.add("h_jet_phat_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); } @@ -191,8 +185,6 @@ struct ChargedJetHadron { registry.add("h_jet_phi", "jet phi; #phi_{jet}; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_jet_area", "jet Area_{jet}; Area_{jet}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); registry.add("h_jet_ntracks", "jet N_{jet tracks}; N_{jet, tracks}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_jet_pt_track_pt", "jet #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, {jetPtAxis, trackPtAxis}}); - registry.add("h_jet_pt_rhoareasubtracted", "jet pt; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("h_jet_eta_rhoareasubtracted", "jet eta; #eta_{jet}; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_jet_phi_rhoareasubtracted", "jet phi; #phi_{jet}; counts", {HistType::kTH1F, {phiAxis}}); @@ -203,16 +195,16 @@ struct ChargedJetHadron { //========jet-hadron correlations====================== if (doprocessJetHadron || doprocessMixJetHadron || doprocessJetHadronMCD || doprocessMixJetHadronMCD) { registry.add("h_trigjet_corrpt", "trigger jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("thn_jeth_correlations", "jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, trackPtAxis, detaAxis, dphiAxis, drAxis}); - registry.add("h_jeth_event_stats", "Same event statistics; Event pair type; counts", {HistType::kTH1F, {{10, 0.5, 10.5}}}); - registry.get(HIST("h_jeth_event_stats"))->GetXaxis()->SetBinLabel(2, "Total jets"); + registry.add("thn_jeth_correlations", "jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxis, trackPtAxis, detaAxis, dphiAxis, drAxis}); + registry.add("h_jeth_event_stats", "Same event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); + registry.get(HIST("h_jeth_event_stats"))->GetXaxis()->SetBinLabel(1, "Total jets"); + registry.get(HIST("h_jeth_event_stats"))->GetXaxis()->SetBinLabel(2, "Total jets with pTHat cut"); registry.get(HIST("h_jeth_event_stats"))->GetXaxis()->SetBinLabel(3, "Total jets with cuts"); registry.get(HIST("h_jeth_event_stats"))->GetXaxis()->SetBinLabel(4, "Total j-h pairs"); registry.get(HIST("h_jeth_event_stats"))->GetXaxis()->SetBinLabel(5, "Total j-h pairs with accepted"); - registry.add("h_mixtrigjet_corrpt", "trigger jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("thn_mixjeth_correlations", "ME: jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, trackPtAxis, detaAxis, dphiAxis, drAxis}); - registry.add("h_mixjeth_event_stats", "Mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{10, 0.5, 10.5}}}); + registry.add("thn_mixjeth_correlations", "ME: jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxis, trackPtAxis, detaAxis, dphiAxis, drAxis}); + registry.add("h_mixjeth_event_stats", "Mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); registry.get(HIST("h_mixjeth_event_stats"))->GetXaxis()->SetBinLabel(1, "Total mixed events"); registry.get(HIST("h_mixjeth_event_stats"))->GetXaxis()->SetBinLabel(2, "Total jets"); registry.get(HIST("h_mixjeth_event_stats"))->GetXaxis()->SetBinLabel(3, "Total jets with cuts"); @@ -235,38 +227,32 @@ struct ChargedJetHadron { registry.add("h_d0bar_bdtScoreBkg", "D0bar BDT bkg score", {HistType::kTH1F, {axisBdtScore}}); registry.add("h2_d0jet_detadphi", "D^{0}-jets deta vs dphi; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); } - //========leading jet-hadron correlations====================== if (doprocessLeadingJetHadron || doprocessLeadinJetHadronMCD) { registry.add("h_centrality", "centrality distributions; centrality; counts", {HistType::kTH1F, {centralityAxis}}); registry.add("h_inclusivejet_corrpt", "inclusive jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_dijet_pair_counts", "number of pairs with good leading-subleading jets; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); - registry.add("h_dijet_pair_counts_cut", "number of pairs with leadingjet & subleadingjet cut pair; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); registry.add("h_leadjet_pt", "leading jet pT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); registry.add("h_leadjet_corrpt", "leading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("h_subleadjet_pt", "subleading jet pT;#it{p}_{T,subleadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); registry.add("h_subleadjet_corrpt", "subleading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_dijet_dphi", "dijet #Delta#varphi before converted to 0-2pi; #Delta#varphi; counts", {HistType::kTH1F, {{126, -6.3, 6.3}}}); registry.add("h_leadjet_eta", "leading jet eta;#eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_leadjet_phi", "leading jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_subleadjet_eta", "subleading jet eta;#eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_subleadjet_phi", "subleading jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h2_dijet_detanoflip_dphi", "dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); - registry.add("h2_dijet_deta_dphi", "dijet #Delta#eta flip vs #Delta#varphi; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); registry.add("h2_dijet_Asymmetry", "dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); - registry.add("h3_dijet_deta_pt", "dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {detaAxis, jetPtAxis, jetPtAxis}}); + registry.add("h3_dijet_deta_pt", "dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #it{p}_{T,jet1} (GeV/#it{c}); #it{p}_{T,jet2} (GeV/#it{c})", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); + registry.add("h2_dijet_TimeEtaThan0_pt", "dijet #eta_{jet1}#eta_{jet1} > 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); + registry.add("h2_dijet_TimeEtaLess0_pt", "dijet #eta_{jet1}#eta_{jet1} < 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); registry.add("h_jeth_detatot", "jet-hadron tot #Delta#eta;#Delta#eta; counts", {HistType::kTH1F, {detaAxis}}); registry.add("h_jeth_deta", "jet-hadron #Delta#eta;#Delta#eta; counts", {HistType::kTH1F, {detaAxis}}); registry.add("h_jeth_dphi", "jet-hadron #Delta#varphi;#Delta#varphi; counts", {HistType::kTH1F, {dphiAxis}}); - registry.add("h2_jeth_detatot_dphi", "jeth deta vs dphi with physical cuts; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_deta_dphi", "jeth deta vs dphi; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_physicalcutsup_deta_dphi", "jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| > 1.0; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_physicalcutsmd_deta_dphi", "jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| #in (0.5, 1.0); #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_physicalcutsdw_deta_dphi", "jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_jeth_physicalcutsHup_deta_dphi", "jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| > 1.0,#Delta#eta_{jet1}>#Delta#eta_{jet2}; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_jeth_physicalcutsHdw_deta_dphi", "jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5 #Delta#eta_{jet1}> #Delta#eta_{jet2}; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("thn_ljeth_correlations", "leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub, trackPtAxis, jetmultetaAxis, detaAxis, etaAxis, detaAxis, dphiAxis}); + registry.add("thn_ljeth_correlations", "leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {10, 0., 10.}, jetmultetaAxis, {16, 0, 1.6}, etaAxis, detaAxis, dphiAxis}); } if (doprocessMixLeadingJetHadron || doprocessMixLeadinJetHadronMCD) { @@ -276,22 +262,20 @@ struct ChargedJetHadron { registry.add("h_mixleadjet_eta", "ME: leading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_mixsubleadjet_eta", "ME: subleading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h2_mixdijet_detanoflip_dphi", "ME: dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); - registry.add("h2_mixdijet_deta_dphi", "ME: dijet #Delta#eta flip vs #Delta#varphi; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); registry.add("h2_mixdijet_Asymmetry", "ME: dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); - registry.add("h3_mixdijet_deta_pt", "ME: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {detaAxis, jetPtAxis, jetPtAxis}}); - + registry.add("h3_mixdijet_deta_pt", "ME: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); + registry.add("h2_mixdijet_TimeEtaThan0_pt", "dijet #eta_{jet1}#eta_{jet1} > 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); + registry.add("h2_mixdijet_TimeEtaLess0_pt", "dijet #eta_{jet1}#eta_{jet1} < 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); registry.add("h_mixjeth_detatot", "ME: jet-hadron correlations; no flip #Delta#eta", {HistType::kTH1F, {detaAxis}}); registry.add("h_mixjeth_deta", "ME: jet-hadron correlations; #Delta#eta", {HistType::kTH1F, {detaAxis}}); registry.add("h_mixjeth_dphi", "ME: jet-hadron correlations; #Delta#phi", {HistType::kTH1F, {dphiAxis}}); - registry.add("h2_mixjeth_detatot_dphi", "ME: jet-hadron correlations; no flip #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_deta_dphi", "ME: jet-hadron correlations; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_physicalcutsup_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| > 1.0; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_physicalcutsmd_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| #in (0.5, 1.0); #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_physicalcutsdw_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_mixjeth_physicalcutsHdw_deta_dphi", "ME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5 #Delta#eta_{jet1}> #Delta#eta_{jet2}; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("thn_mixljeth_correlations", "ME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi; poolBin", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub, trackPtAxis, jetmultetaAxis, detaAxis, etaAxis, detaAxis, dphiAxis, {20, 0, 20}}); + registry.add("thn_mixljeth_correlations", "ME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi; poolBin", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {10, 0., 10.}, jetmultetaAxis, {16, 0, 1.6}, etaAxis, detaAxis, dphiAxis, {15, 0, 15}}); - registry.add("h_mix_event_stats", "Mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{10, 0.5, 10.5}}}); + registry.add("h_mix_event_stats", "Mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(1, "Total mixed events"); registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(2, "Total dijets"); registry.get(HIST("h_mix_event_stats"))->GetXaxis()->SetBinLabel(3, "Total dijets with cuts"); @@ -300,55 +284,57 @@ struct ChargedJetHadron { } if (doprocessCollisionsQCMCP) { - registry.add("h_mcColl_counts", " number of mc events; event status; entries", {HistType::kTH1F, {{10, 0, 10}}}); + registry.add("h_mcColl_counts", " number of mc events; event status; entries", {HistType::kTH1F, {{7, 0., 7.}}}); registry.get(HIST("h_mcColl_counts"))->GetXaxis()->SetBinLabel(1, "allMcColl"); registry.get(HIST("h_mcColl_counts"))->GetXaxis()->SetBinLabel(2, "vertexZ"); registry.get(HIST("h_mcColl_counts"))->GetXaxis()->SetBinLabel(3, "noRecoColl"); registry.get(HIST("h_mcColl_counts"))->GetXaxis()->SetBinLabel(4, "recoEvtSel"); registry.get(HIST("h_mcColl_counts"))->GetXaxis()->SetBinLabel(5, "centralitycut"); registry.get(HIST("h_mcColl_counts"))->GetXaxis()->SetBinLabel(6, "occupancycut"); - registry.add("h_mc_mult", " multiplicity global tracks; entries", {HistType::kTH1F, {{3000, 0, 60000}}}); + registry.add("h_mcdColl_mult", " mcd multiplicity global tracks; entries", {HistType::kTH1F, {{300, 0, 60000}}}); - registry.add("h_mcColl_zvertex", "position of collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}); + registry.add("h_mcpColl_Zvertex", "position of collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}); registry.add("h_mcpColl_centrality", "mcp collision centrality; centrality; counts", {HistType::kTH1F, {centralityAxis}}); - registry.add("h_mcpColl_mult", " mcp multiplicity global tracks; entries", {HistType::kTH1F, {{3000, 0, 60000}}}); - registry.add("h_particle_pt", "particle #it{p}_{T}; #it{p}_{T,particle} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}); + registry.add("h_mcpColl_mult", " mcp multiplicity global tracks; entries", {HistType::kTH1F, {{300, 0, 60000}}}); registry.add("h2_particle_eta_phi", "particle #eta vs. particle #phi; #eta; #phi; counts", {HistType::kTH2F, {etaAxis, phiAxis}}); registry.add("h2_particle_eta_pt", "particle #eta vs. particle #it{p}_{T}; #eta; #it{p}_{T,particle} (GeV/#it{c}; counts", {HistType::kTH2F, {etaAxis, trackPtAxis}}); registry.add("h2_particle_phi_pt", "particle #phi vs. particle #it{p}_{T}; #phi; #it{p}_{T,particle} (GeV/#it{c}; counts", {HistType::kTH2F, {phiAxis, trackPtAxis}}); } - if (doprocessSpectraMCP || doprocessSpectraMCPWeighted) { + if (doprocessSpectraAreaSubMCP) { + if (doEventWeighted) { + registry.add("h_mcColl_counts_weight", " number of weighted mc events; event status; entries", {HistType::kTH1F, {{7, 0., 7.}}}); + registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(1, "McColl"); + registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(2, "xsectGen"); + registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(3, "event weight"); + } + registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); registry.add("h_jet_pt_part", "partvjet pT;#it{p}_{T,jet}^{part} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); registry.add("h_jet_eta_part", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_jet_phi_part", "part jet #varphi;#phi^{part}; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h_jet_area_part", "part jet Area_{jet}; Area_{jet}^{part}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); registry.add("h_jet_ntracks_part", "part jet N_{jet tracks}; N_{jet, tracks}^{part}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - registry.add("h2_jet_pt_part_track_pt_part", "part jet #it{p}_{T,jet} vs. #it{p}_{T,track}; #it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,track}^{part} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, trackPtAxis}}); - if (doprocessSpectraMCPWeighted) { - registry.add("h_mcColl_counts_weight", " number of weighted mc events; event status; entries", {HistType::kTH1F, {{10, 0, 10}}}); - registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(1, "McColl"); - registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(2, "xsectGen"); - registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(3, "event weight"); - registry.get(HIST("h_mcColl_counts_weight"))->GetXaxis()->SetBinLabel(4, "jet weight"); - registry.add("h2_jet_ptcut_part", "p_{T} cut;p_{T,jet}^{part} (GeV/#it{c});N;entries", {HistType::kTH2F, {{300, 0, 300}, {20, 0, 5}}}); - registry.add("h_jet_phat_part_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); - } + registry.add("h_jet_pt_part_rhoareasubtracted", "part jet corr pT;#it{p}_{T,jet}^{part} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_eta_part_rhoareasubtracted", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {etaAxis}}); + registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); + registry.add("h_jet_area_part_rhoareasubtracted", "part jet Area_{jet}; Area_{jet}^{part}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); + registry.add("h_jet_ntracks_part_rhoareasubtracted", "part jet N_{jet tracks}; N_{jet, tracks}^{part}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); } if (doprocessJetHadronMCP || doprocessMixJetHadronMCP) { //.........MCP: jet-hadron correlations................. registry.add("h_trigjet_corrpt_part", "trigger jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("thn_jeth_correlations_part", "MCP: jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, trackPtAxis, detaAxis, dphiAxis, drAxis}); + registry.add("thn_jeth_correlations_part", "MCP: jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxis, trackPtAxis, detaAxis, dphiAxis, drAxis}); - registry.add("h_jeth_event_stats_part", "MCP: same event statistics; Event pair type; counts", {HistType::kTH1F, {{10, 0.5, 10.5}}}); - registry.get(HIST("h_jeth_event_stats_part"))->GetXaxis()->SetBinLabel(2, "Total jets"); + registry.add("h_jeth_event_stats_part", "MCP: same event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); + registry.get(HIST("h_jeth_event_stats_part"))->GetXaxis()->SetBinLabel(1, "Total jets"); + registry.get(HIST("h_jeth_event_stats_part"))->GetXaxis()->SetBinLabel(2, "Total jets with pTHat cut"); registry.get(HIST("h_jeth_event_stats_part"))->GetXaxis()->SetBinLabel(3, "Total jets with cuts"); registry.get(HIST("h_jeth_event_stats_part"))->GetXaxis()->SetBinLabel(4, "Total j-h pairs"); registry.get(HIST("h_jeth_event_stats_part"))->GetXaxis()->SetBinLabel(5, "Total j-h pairs with accepted"); registry.add("h_mixtrigjet_corrpt_part", "trigger jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("thn_mixjeth_correlations_part", "mcpME: jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, trackPtAxis, detaAxis, dphiAxis, drAxis}); - registry.add("h_mixjeth_event_stats_part", "MCP: mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{10, 0.5, 10.5}}}); + registry.add("thn_mixjeth_correlations_part", "mcpME: jet-h correlations; jetpT; trackpT; jeth#Delta#eta; jeth#Delta#varphi; jeth#Delta#it{R}", HistType::kTHnSparseF, {jetPtAxis, trackPtAxis, detaAxis, dphiAxis, drAxis}); + registry.add("h_mixjeth_event_stats_part", "MCP: mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); registry.get(HIST("h_mixjeth_event_stats_part"))->GetXaxis()->SetBinLabel(1, "Total mixed events"); registry.get(HIST("h_mixjeth_event_stats_part"))->GetXaxis()->SetBinLabel(2, "Total jets"); registry.get(HIST("h_mixjeth_event_stats_part"))->GetXaxis()->SetBinLabel(3, "Total jets with cuts"); @@ -356,20 +342,8 @@ struct ChargedJetHadron { registry.get(HIST("h_mixjeth_event_stats_part"))->GetXaxis()->SetBinLabel(5, "Total j-h pairs with accepted"); } - if (doprocessLeadingJetHadronMCP || doprocessMixLeadingJetHadronMCP) { - registry.add("h_mcColl_centrality", "mcd collision centrality; centrality; counts", {HistType::kTH1F, {centralityAxis}}); - registry.add("h_mcColl_mult", " mcd multiplicity global tracks; entries", {HistType::kTH1F, {{3000, 0, 60000}}}); - registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); - - registry.add("h_jet_pt_part_rhoareasubtracted", "part jet corr pT;#it{p}_{T,jet}^{part} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_eta_part_rhoareasubtracted", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {etaAxis}}); - registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); - registry.add("h_jet_area_part_rhoareasubtracted", "part jet Area_{jet}; Area_{jet}^{part}; counts", {HistType::kTH1F, {{150, 0., 1.5}}}); - registry.add("h_jet_ntracks_part_rhoareasubtracted", "part jet N_{jet tracks}; N_{jet, tracks}^{part}; counts", {HistType::kTH1F, {{200, -0.5, 199.5}}}); - + if (doprocessLeadingJetHadronMCP) { //.........SE leading jet correlations............... - registry.add("h_dijet_pair_counts_part", "MCP: number of pairs with good leading-subleading jets; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); - registry.add("h_dijet_pair_counts_cut_part", "MCP: number of pairs with leadingjet & subleadingjet cut pair; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); registry.add("h_leadjet_pt_part", "MCP: leading jet pT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); registry.add("h_leadjet_corrpt_part", "MCP: leading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("h_leadjet_eta_part", "MCP: leading jet eta;#eta; counts", {HistType::kTH1F, {etaAxis}}); @@ -379,21 +353,22 @@ struct ChargedJetHadron { registry.add("h_subleadjet_eta_part", "MCP: subleading jet eta;#eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_subleadjet_phi_part", "MCP: subleading jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}); registry.add("h2_dijet_detanoflip_dphi_part", "MCP: dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); - registry.add("h2_dijet_deta_dphi_part", "MCP: dijet #Delta#eta flip vs #Delta#varphi; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); registry.add("h2_dijet_Asymmetry_part", "MCP: dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); - registry.add("h3_dijet_deta_pt_part", "MCP: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {detaAxis, jetPtAxis, jetPtAxis}}); + registry.add("h3_dijet_deta_pt_part", "MCP: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); + registry.add("h2_dijet_TimeEtaThan0_pt_part", "dijet #eta_{jet1}#eta_{jet1} > 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); + registry.add("h2_dijet_TimeEtaLess0_pt_part", "dijet #eta_{jet1}#eta_{jet1} < 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); registry.add("h_jeth_detatot_part", "MCP: jet-hadron tot #Delta#eta;#Delta#eta; counts", {HistType::kTH1F, {detaAxis}}); registry.add("h_jeth_deta_part", "MCP: jet-hadron #Delta#eta;#Delta#eta; counts", {HistType::kTH1F, {detaAxis}}); registry.add("h_jeth_dphi_part", "MCP: jet-hadron #Delta#varphi;#Delta#varphi; counts", {HistType::kTH1F, {dphiAxis}}); - registry.add("h2_jeth_detatot_dphi_part", "MCP: jeth deta vs dphi with physical cuts; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_deta_dphi_part", "MCP: jeth deta vs dphi; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_physicalcutsup_deta_dphi_part", "MCP: jeth deta vs dphi with physical cuts |#Delta#eta_{jet}| > 1.0; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_physicalcutsmd_deta_dphi_part", "MCP: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| #in (0.5, 1.0); #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_jeth_physicalcutsdw_deta_dphi_part", "MCP: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_jeth_physicalcutsHdw_deta_dphi_part", "MCP: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5 #Delta#eta_{jet1}>#Delta#eta_{jet2}; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("thn_ljeth_correlations_part", "MCP: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub, trackPtAxis, jetmultetaAxis, detaAxis, etaAxis, detaAxis, dphiAxis}); + registry.add("thn_ljeth_correlations_part", "MCP: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {10, 0., 10.}, jetmultetaAxis, {16, 0, 1.6}, etaAxis, detaAxis, dphiAxis}); + } + if (doprocessMixLeadingJetHadronMCP) { //...........mcp mixed events: leading jet correlations................. registry.add("h_mixdijet_pair_counts_cut_part", "mcpME: number of pairs with leadingjet & subleadingjet cut pair; jet pairs; counts", {HistType::kTH1F, {{10, 0, 10}}}); registry.add("h_mixleadjet_corrpt_part", "mcpME: leading jet corrpT;#it{p}_{T,leadingjet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); @@ -401,28 +376,30 @@ struct ChargedJetHadron { registry.add("h_mixleadjet_eta_part", "mcpME: leading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h_mixsubleadjet_eta_part", "mcpME: subleading jet eta; #eta; counts", {HistType::kTH1F, {etaAxis}}); registry.add("h2_mixdijet_detanoflip_dphi_part", "mcpME: dijet #Delta#eta no flip vs #Delta#varphi; #Delta#eta_{noflip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); - registry.add("h2_mixdijet_deta_dphi_part", "mcpME: dijet #Delta#eta flip vs #Delta#varphi; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH2F, {detaAxis, {63, 0, 6.3}}}); registry.add("h2_mixdijet_Asymmetry_part", "mcpME: dijet Asymmetry; #it{p}_{T,subleadingjet} (GeV/#it{c}); #it{X}_{J}; counts", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {40, 0, 1.0}}}); - registry.add("h3_mixdijet_deta_pt_part", "mcpME: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {detaAxis, jetPtAxis, jetPtAxis}}); + registry.add("h3_mixdijet_deta_pt_part", "mcpME: dijet #Delta#eta flip vs #it{p}_{T,jet1-jet2}; #Delta#eta_{flip}; #Delta#varphi; counts", {HistType::kTH3F, {{16, 0, 1.6}, jetPtAxis, jetPtAxis}}); + registry.add("h2_mixdijet_TimeEtaThan0_pt_part", "dijet #eta_{jet1}#eta_{jet1} > 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); + registry.add("h2_mixdijet_TimeEtaLess0_pt_part", "dijet #eta_{jet1}#eta_{jet1} < 0", {HistType::kTH2F, {jetPtAxis, jetPtAxis}}); registry.add("h_mixjeth_detatot_part", "mcpME: jet-hadron correlations; no flip #Delta#eta", {HistType::kTH1F, {detaAxis}}); registry.add("h_mixjeth_deta_part", "mcpME: jet-hadron correlations; #Delta#eta", {HistType::kTH1F, {detaAxis}}); registry.add("h_mixjeth_dphi_part", "mcpME: jet-hadron correlations; #Delta#phi", {HistType::kTH1F, {dphiAxis}}); - registry.add("h2_mixjeth_detatot_dphi_part", "mcpME: jet-hadron correlations; no flip #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_deta_dphi_part", "mcpME: jet-hadron correlations; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_physicalcutsup_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet}| > 1.0; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_physicalcutsmd_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| #in (0.5, 1.0); #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); registry.add("h2_mixjeth_physicalcutsdw_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("h2_mixjeth_physicalcutsHdw_deta_dphi_part", "mcpME: jeth deta vs dphi with physical cuts |#Delta#eta_{jet1,2}| < 0.5 #Delta#eta_{jet1}>#Delta#eta_{jet2}; #Delta#eta; #Delta#phi", {HistType::kTH2F, {detaAxis, dphiAxis}}); - registry.add("thn_mixljeth_correlations_part", "mcpME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub, trackPtAxis, jetmultetaAxis, detaAxis, etaAxis, detaAxis, dphiAxis}); + registry.add("thn_mixljeth_correlations_part", "mcpME: leading jet-h correlations; leadingjetpT; subleadingjetpT; trackpT; timedijeteta; #Delta#eta_{jet1,2}; track #eta; jeth#Delta#eta; jeth#Delta#varphi", HistType::kTHnSparseF, {jetPtAxis, jetPtAxis, {10, 0., 10.}, jetmultetaAxis, {16, 0, 1.6}, etaAxis, detaAxis, dphiAxis}); - registry.add("h_mixevent_stats_part", "MCP: mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{10, 0.5, 10.5}}}); + registry.add("h_mixevent_stats_part", "MCP: mixed event statistics; Event pair type; counts", {HistType::kTH1F, {{7, 0., 7.}}}); registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(1, "Total mixed events"); registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(2, "Total dijets"); registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(3, "Total dijets with cuts"); registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(4, "Total Lj-h pairs"); registry.get(HIST("h_mixevent_stats_part"))->GetXaxis()->SetBinLabel(5, "Total Lj-h pairs with cut"); } + if (!(acceptSplitCollisions == NonSplitOnly || acceptSplitCollisions == SplitOkCheckAnyAssocColl || acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly)) { + LOGF(fatal, "Configurable acceptSplitCollisions has wrong input value; stopping workflow"); + } } // ========================================================== // getcentrality getmultiplicity @@ -469,16 +446,19 @@ struct ChargedJetHadron { template bool applyMCCollisionCuts(const TMcCollision& mccollision, const TCollisions& collisions) const { - // MC z-vertex cut, must have associated collisions, plit-collision rule + // MC z-vertex cut, must have associated collisions, split-collision rule if (std::abs(mccollision.posZ()) > vertexZCut.value) return false; if (collisions.size() < 1) return false; - if (acceptSplitCollisions.value == NonSplitOnly && collisions.size() > 1) { + if (acceptSplitCollisions.value == NonSplitOnly && collisions.size() > 1) return false; - } + // At least one associated collision must pass all cuts + if (acceptSplitCollisions.value == SplitOkCheckFirstAssocCollOnly) + return isGoodCollision(*collisions.begin()); + for (auto const& collision : collisions) { if (isGoodCollision(collision)) { return true; @@ -511,7 +491,13 @@ struct ChargedJetHadron { template void fillTrackHistograms(TTracks const& track, float weight = 1.0) { - registry.fill(HIST("h_track_pt"), track.pt(), weight); + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + if (track.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) + return; + if (doEventWeighted) { + registry.fill(HIST("h_jet_phat"), pTHat); + registry.fill(HIST("h_jet_phat_weighted"), pTHat, weight); + } registry.fill(HIST("h2_track_eta_track_phi"), track.eta(), track.phi(), weight); registry.fill(HIST("h2_track_eta_pt"), track.eta(), track.pt(), weight); registry.fill(HIST("h2_track_phi_pt"), track.phi(), track.pt(), weight); @@ -520,7 +506,9 @@ struct ChargedJetHadron { template void fillParticleHistograms(const TParticles& particle, float weight = 1.0) { - registry.fill(HIST("h_particle_pt"), particle.pt(), weight); + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + if (particle.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) + return; registry.fill(HIST("h2_particle_eta_phi"), particle.eta(), particle.phi(), weight); registry.fill(HIST("h2_particle_eta_pt"), particle.eta(), particle.pt(), weight); registry.fill(HIST("h2_particle_phi_pt"), particle.phi(), particle.pt(), weight); @@ -530,9 +518,8 @@ struct ChargedJetHadron { void fillJetHistograms(TJets const& jet, float weight = 1.0) { float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) return; - } if (jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h_jet_pt"), jet.pt(), weight); registry.fill(HIST("h_jet_eta"), jet.eta(), weight); @@ -540,19 +527,14 @@ struct ChargedJetHadron { registry.fill(HIST("h_jet_area"), jet.area(), weight); registry.fill(HIST("h_jet_ntracks"), jet.tracksIds().size(), weight); } - - for (const auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); - } } template void fillJetAreaSubHistograms(TJets const& jet, float rho, float weight = 1.0) { float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) return; - } double jetcorrpt = jet.pt() - (rho * jet.area()); if (jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jetcorrpt, weight); @@ -569,9 +551,8 @@ struct ChargedJetHadron { void fillMCPHistograms(TJets const& jet, float weight = 1.0) { float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) return; - } if (jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); @@ -579,18 +560,14 @@ struct ChargedJetHadron { registry.fill(HIST("h_jet_area_part"), jet.area(), weight); registry.fill(HIST("h_jet_ntracks_part"), jet.tracksIds().size(), weight); } - for (const auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), constituent.pt(), weight); - } } template void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0) { float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) return; - } if (jet.r() == round(selectedJetsRadius * 100.0f)) { double jetcorrpt = jet.pt() - (rho * jet.area()); registry.fill(HIST("h_jet_pt_part_rhoareasubtracted"), jetcorrpt, weight); @@ -607,16 +584,19 @@ struct ChargedJetHadron { //..........jet - hadron correlations........................ // ========================================================== template - void fillJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float eventWeight = 1.0) + void fillJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0) { + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + using TracksTable = std::decay_t; for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - using TracksTable = std::decay_t; - if (!isAcceptedJet(jet)) { + if (!isAcceptedJet(jet)) + continue; + registry.fill(HIST("h_jeth_event_stats"), 1); + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) continue; - } registry.fill(HIST("h_jeth_event_stats"), 2); double ptCorr = jet.pt() - jet.area() * collision.rho(); if (ptCorr < subleadingjetptMin) @@ -632,19 +612,22 @@ struct ChargedJetHadron { double dphi = track.phi() - jet.phi(); dphi = RecoDecay::constrainAngle(dphi, -PIHalf); double dr = std::sqrt(deta * deta + dphi * dphi); - registry.fill(HIST("thn_jeth_correlations"), ptCorr, track.pt(), deta, dphi, dr, eventWeight); + registry.fill(HIST("thn_jeth_correlations"), ptCorr, track.pt(), deta, dphi, dr, weight); } } } //.......mixed events................................. template - void fillMixJetHadronHistograms(const TCollisions& collisions, const TJets& jets, const TTracks& tracks, float eventWeight = 1.0) + void fillMixJetHadronHistograms(const TCollisions& collisions, const TJets& jets, const TTracks& tracks, float weight = 1.0) { + using TracksTable = std::decay_t; auto tracksTuple = std::make_tuple(jets, tracks); Pair pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; //// -1 is the number of the bin to skip for (const auto& [c1, jets1, c2, tracks2] : pairData) { + weight = doEventWeighted ? c1.weight() : 1.f; + const float pTHat = 10.f / std::pow(weight, 1.f / pTHatExponent); registry.fill(HIST("h_mixjeth_event_stats"), 1); if (!isGoodCollision(c1) || !isGoodCollision(c2)) continue; @@ -652,10 +635,10 @@ struct ChargedJetHadron { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - using TracksTable = std::decay_t; - if (!isAcceptedJet(jet)) { + if (!isAcceptedJet(jet)) + continue; // for pp Reason: Trying to dereference index with a wrong type in tracks_as for base target "JTracks" + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) continue; - } // for pp Reason: Trying to dereference index with a wrong type in tracks_as for base target "JTracks" registry.fill(HIST("h_mixjeth_event_stats"), 2); double ptCorr = jet.pt() - jet.area() * c1.rho(); if (ptCorr < subleadingjetptMin) @@ -671,7 +654,7 @@ struct ChargedJetHadron { double dphi = track.phi() - jet.phi(); dphi = RecoDecay::constrainAngle(dphi, -PIHalf); double dr = std::sqrt(deta * deta + dphi * dphi); - registry.fill(HIST("thn_mixjeth_correlations"), ptCorr, track.pt(), deta, dphi, dr, eventWeight); + registry.fill(HIST("thn_mixjeth_correlations"), ptCorr, track.pt(), deta, dphi, dr, weight); } } } @@ -679,16 +662,19 @@ struct ChargedJetHadron { //........MCP..jet - hadron correlations.......................................... template - void fillMCPJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float eventWeight = 1.0) + void fillMCPJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float weight = 1.0) { + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + using ParticlesTable = std::decay_t; for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - using ParticlesTable = std::decay_t; if (!isAcceptedJet(jet, true)) { continue; } + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) + return; registry.fill(HIST("h_jeth_event_stats_part"), 2); double ptCorr = jet.pt() - jet.area() * mccollision.rho(); if (ptCorr < subleadingjetptMin) @@ -701,18 +687,21 @@ struct ChargedJetHadron { double dphi = particle.phi() - jet.phi(); dphi = RecoDecay::constrainAngle(dphi, -PIHalf); double dr = std::sqrt(deta * deta + dphi * dphi); - registry.fill(HIST("thn_jeth_correlations_part"), ptCorr, particle.pt(), deta, dphi, dr, eventWeight); + registry.fill(HIST("thn_jeth_correlations_part"), ptCorr, particle.pt(), deta, dphi, dr, weight); } } } //......mixed events...................... template - void fillMCPMixJetHadronHistograms(const TmcCollisions& mccollisions, const TCollisions& collisions, const TJets& jets, const TParticles& particles, float eventWeight = 1.0) + void fillMCPMixJetHadronHistograms(const TmcCollisions& mccollisions, const TCollisions& collisions, const TJets& jets, const TParticles& particles, float weight = 1.0) { + using ParticlesTable = std::decay_t; auto particlesTuple = std::make_tuple(jets, particles); Pair pairMCData{corrBinningMC, numberEventsMixed, -1, mccollisions, particlesTuple, &cache}; for (const auto& [c1, jets1, c2, particles2] : pairMCData) { + weight = doEventWeighted ? c1.weight() : 1.f; + const float pTHat = 10.f / std::pow(weight, 1.f / pTHatExponent); registry.fill(HIST("h_mixjeth_event_stats_part"), 1); if (!applyMCCollisionCuts(c1, collisions) || !applyMCCollisionCuts(c2, collisions)) continue; @@ -720,9 +709,10 @@ struct ChargedJetHadron { for (auto const& jet : jets1) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - using ParticlesTable = std::decay_t; if (!isAcceptedJet(jet, true)) continue; + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) + return; registry.fill(HIST("h_mixjeth_event_stats_part"), 2); double ptCorr = jet.pt() - jet.area() * c1.rho(); @@ -737,7 +727,7 @@ struct ChargedJetHadron { double dphi = particle.phi() - jet.phi(); dphi = RecoDecay::constrainAngle(dphi, -PIHalf); double dr = std::sqrt(deta * deta + dphi * dphi); - registry.fill(HIST("thn_mixjeth_correlations_part"), ptCorr, particle.pt(), deta, dphi, dr, eventWeight); + registry.fill(HIST("thn_mixjeth_correlations_part"), ptCorr, particle.pt(), deta, dphi, dr, weight); } } } @@ -747,8 +737,10 @@ struct ChargedJetHadron { //..........leading jet - hadron correlations................ // ========================================================== template - void fillLeadingJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float eventWeight = 1.0) + void fillLeadingJetHadronHistograms(const TCollision& collision, const TJets& jets, const TTracks& tracks, float weight = 1.0) { + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + using TracksTable = std::decay_t; registry.fill(HIST("h_centrality"), getCentrality(collision)); typename TJets::iterator leadingJet; typename TJets::iterator subleadingJet; @@ -756,7 +748,6 @@ struct ChargedJetHadron { bool hasSubleading = false; double ptLeadingCorr = -1.0; double ptSubleadingCorr = -1.0; - using TracksTable = std::decay_t; for (auto it = jets.begin(); it != jets.end(); ++it) { const auto& jet = *it; @@ -764,9 +755,10 @@ struct ChargedJetHadron { continue; if (!isAcceptedJet(jet)) continue; - - const double ptCorr = jet.pt() - jet.area() * collision.rho(); - registry.fill(HIST("h_inclusivejet_corrpt"), ptCorr, eventWeight); + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) + continue; + double ptCorr = jet.pt() - jet.area() * collision.rho(); + registry.fill(HIST("h_inclusivejet_corrpt"), ptCorr, weight); if (ptCorr > ptLeadingCorr) { if (hasLeading) { subleadingJet = leadingJet; @@ -785,87 +777,81 @@ struct ChargedJetHadron { if (!hasLeading || !hasSubleading) return; // fewer than 2 jets - const double phiLead = leadingJet.phi(); - const double phiSub = subleadingJet.phi(); + double phiLead = leadingJet.phi(); + double phiSub = subleadingJet.phi(); double deltaPhiJets = phiLead - phiSub; - registry.fill(HIST("h_dijet_dphi"), deltaPhiJets, eventWeight); - deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, 0.); - if (std::abs(deltaPhiJets) < PIHalf || std::abs(deltaPhiJets) > absPiCut * PI) + deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, -PIHalf); + if (std::abs(deltaPhiJets) < dijetDphiCut * PI) return; - // === Step2: eta ordering etajet1 > etajet2) === - const double etaJet1Raw = leadingJet.eta(); - const double etaJet2Raw = subleadingJet.eta(); - const double multEta1Eta2 = etaJet1Raw * etaJet2Raw; - const double deltaEtaJetsNoflip = etaJet1Raw - etaJet2Raw; - const double inverse = (etaJet1Raw > 0) ? 1.0 : -1.0; // Dr.Yang suggestion - const double flip = (etaJet1Raw > etaJet2Raw) ? 1.0 : -1.0; - const double etajet1 = flip * etaJet1Raw; // leading jet eta after flip - const double etajet2 = flip * etaJet2Raw; // subleading jet eta after flip - const double deltaEtaJets = etajet1 - etajet2; // >= 0 - registry.fill(HIST("h_dijet_pair_counts"), 1); - registry.fill(HIST("h_leadjet_pt"), leadingJet.pt(), eventWeight); - registry.fill(HIST("h_subleadjet_pt"), subleadingJet.pt(), eventWeight); - registry.fill(HIST("h_leadjet_corrpt"), ptLeadingCorr, eventWeight); - registry.fill(HIST("h_subleadjet_corrpt"), ptSubleadingCorr, eventWeight); + double etaJet1Raw = leadingJet.eta(); + double etaJet2Raw = subleadingJet.eta(); + double multEta1Eta2 = etaJet1Raw * etaJet2Raw; + double deltaEtaJetsNoflip = etaJet1Raw - etaJet2Raw; + double inverse = (etaJet1Raw > 0) ? 1.0 : -1.0; // Dr.Yang suggestion + double flip = (etaJet1Raw > etaJet2Raw) ? 1.0 : -1.0; + double etajet1 = flip * etaJet1Raw; // leading jet eta after flip + double etajet2 = flip * etaJet2Raw; // subleading jet eta after flip + double deltaEtaJets = etajet1 - etajet2; // >= 0 + registry.fill(HIST("h_leadjet_pt"), leadingJet.pt(), weight); + registry.fill(HIST("h_subleadjet_pt"), subleadingJet.pt(), weight); + registry.fill(HIST("h_leadjet_corrpt"), ptLeadingCorr, weight); + registry.fill(HIST("h_subleadjet_corrpt"), ptSubleadingCorr, weight); if (ptLeadingCorr < leadingjetptMin || ptSubleadingCorr < subleadingjetptMin) return; - registry.fill(HIST("h_dijet_pair_counts_cut"), 2); - registry.fill(HIST("h_leadjet_eta"), etaJet1Raw, eventWeight); - registry.fill(HIST("h_subleadjet_eta"), etaJet2Raw, eventWeight); - registry.fill(HIST("h_leadjet_phi"), phiLead, eventWeight); - registry.fill(HIST("h_subleadjet_phi"), phiSub, eventWeight); - registry.fill(HIST("h2_dijet_detanoflip_dphi"), deltaEtaJetsNoflip, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_dijet_deta_dphi"), deltaEtaJets, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_dijet_Asymmetry"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, eventWeight); - registry.fill(HIST("h3_dijet_deta_pt"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_leadjet_eta"), etaJet1Raw, weight); + registry.fill(HIST("h_subleadjet_eta"), etaJet2Raw, weight); + registry.fill(HIST("h_leadjet_phi"), phiLead, weight); + registry.fill(HIST("h_subleadjet_phi"), phiSub, weight); + registry.fill(HIST("h2_dijet_detanoflip_dphi"), deltaEtaJetsNoflip, deltaPhiJets, weight); + registry.fill(HIST("h2_dijet_Asymmetry"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, weight); + registry.fill(HIST("h3_dijet_deta_pt"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, weight); + if (multEta1Eta2 > 0) + registry.fill(HIST("h2_dijet_TimeEtaThan0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); + else if (multEta1Eta2 < 0) + registry.fill(HIST("h2_dijet_TimeEtaLess0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; - const double hpt = track.pt(); - const double heta = inverse * (track.eta()); // Dr.Yang - const double detatot = track.eta() - etaJet1Raw; - const double deta = flip * (track.eta() - etaJet1Raw); // always relative to leadingJet (after flip) + double hpt = track.pt(); + double heta = inverse * (track.eta()); // Dr.Yang + double detatot = track.eta() - etaJet1Raw; + double deta = flip * (track.eta() - etaJet1Raw); // always relative to leadingJet (after flip) double dphi = track.phi() - leadingJet.phi(); dphi = RecoDecay::constrainAngle(dphi, -PIHalf); - if (hpt > assoHadronPtMaxCut) continue; - registry.fill(HIST("h_jeth_detatot"), detatot, eventWeight); - registry.fill(HIST("h_jeth_deta"), deta, eventWeight); - registry.fill(HIST("h_jeth_dphi"), dphi, eventWeight); - registry.fill(HIST("h2_jeth_detatot_dphi"), detatot, dphi, eventWeight); + registry.fill(HIST("h_jeth_detatot"), detatot, weight); + registry.fill(HIST("h_jeth_deta"), deta, weight); + registry.fill(HIST("h_jeth_dphi"), dphi, weight); if (doDijetRaa) - registry.fill(HIST("thn_ljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, eventWeight); + registry.fill(HIST("thn_ljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, weight); else - registry.fill(HIST("thn_ljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, eventWeight); + registry.fill(HIST("thn_ljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, weight); if (hpt < assoHadronPtCut) { - registry.fill(HIST("h2_jeth_deta_dphi"), deta, dphi, eventWeight); + registry.fill(HIST("h2_jeth_deta_dphi"), deta, dphi, weight); if (std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_jeth_physicalcutsup_deta_dphi"), deta, dphi, eventWeight); + registry.fill(HIST("h2_jeth_physicalcutsup_deta_dphi"), deta, dphi, weight); if (std::abs(deltaEtaJets) >= etaGapdw && std::abs(deltaEtaJets) < etaGapup) - registry.fill(HIST("h2_jeth_physicalcutsmd_deta_dphi"), deta, dphi, eventWeight); + registry.fill(HIST("h2_jeth_physicalcutsmd_deta_dphi"), deta, dphi, weight); if (std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_jeth_physicalcutsdw_deta_dphi"), deta, dphi, eventWeight); - if (etaJet1Raw > etaJet2Raw && std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_jeth_physicalcutsHup_deta_dphi"), detatot, dphi, eventWeight); // Dr.Yang - if (etaJet1Raw > etaJet2Raw && std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_jeth_physicalcutsHdw_deta_dphi"), detatot, dphi, eventWeight); // Dr.Yang + registry.fill(HIST("h2_jeth_physicalcutsdw_deta_dphi"), deta, dphi, weight); } } } //.......mixed events leadingjet-hadrons......................... template - void fillMixLeadingJetHadronHistograms(const TCollisions& collisions, const TJets& jets, const TTracks& tracks, float eventWeight = 1.0) + void fillMixLeadingJetHadronHistograms(const TCollisions& collisions, const TJets& jets, const TTracks& tracks, float weight = 1.0) { - int totalmix = 0, totaldijets = 0, totaldijetscut = 0, totalPairs = 0, passedPairs = 0; + using TracksTable = std::decay_t; auto tracksTuple = std::make_tuple(jets, tracks); Pair pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, jets1, c2, tracks2] : pairData) { - totalmix++; + weight = doEventWeighted ? c1.weight() : 1.f; + const float pTHat = 10.f / std::pow(weight, 1.f / pTHatExponent); registry.fill(HIST("h_mix_event_stats"), 1); int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), getCentrality(c2))); if (!isGoodCollision(c1) || !isGoodCollision(c2)) @@ -882,9 +868,10 @@ struct ChargedJetHadron { const auto& jet = *it; if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - using TracksTable = std::decay_t; if (!isAcceptedJet(jet)) continue; + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) + continue; double ptCorr = jet.pt() - jet.area() * c1.rho(); if (ptCorr > ptLeadingCorr) { @@ -908,13 +895,11 @@ struct ChargedJetHadron { double phiLead = leadingJet.phi(); double phiSub = subleadingJet.phi(); double deltaPhiJets = phiLead - phiSub; - deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, 0.); - if (std::abs(deltaPhiJets) < PIHalf || std::abs(deltaPhiJets) > absPiCut * PI) + deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, -PIHalf); + if (std::abs(deltaPhiJets) < dijetDphiCut * PI) continue; - totaldijets++; registry.fill(HIST("h_mix_event_stats"), 2); - double etaJet1Raw = leadingJet.eta(); double etaJet2Raw = subleadingJet.eta(); double multEta1Eta2 = etaJet1Raw * etaJet2Raw; @@ -924,27 +909,27 @@ struct ChargedJetHadron { double etajet2 = flip * etaJet2Raw; double deltaEtaJetsNoflip = etaJet1Raw - etaJet2Raw; double deltaEtaJets = etajet1 - etajet2; - registry.fill(HIST("h_mixleadjet_corrpt"), ptLeadingCorr, eventWeight); - registry.fill(HIST("h_mixsubleadjet_corrpt"), ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_mixleadjet_corrpt"), ptLeadingCorr, weight); + registry.fill(HIST("h_mixsubleadjet_corrpt"), ptSubleadingCorr, weight); if (ptLeadingCorr < leadingjetptMin || ptSubleadingCorr < subleadingjetptMin) continue; - totaldijetscut++; registry.fill(HIST("h_mix_event_stats"), 3); registry.fill(HIST("h_mixdijet_pair_counts_cut"), 2); - registry.fill(HIST("h_mixleadjet_eta"), etaJet1Raw, eventWeight); - registry.fill(HIST("h_mixsubleadjet_eta"), etaJet2Raw, eventWeight); - registry.fill(HIST("h2_mixdijet_detanoflip_dphi"), deltaEtaJetsNoflip, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_mixdijet_deta_dphi"), deltaEtaJets, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_mixdijet_Asymmetry"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, eventWeight); - registry.fill(HIST("h3_mixdijet_deta_pt"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_mixleadjet_eta"), etaJet1Raw, weight); + registry.fill(HIST("h_mixsubleadjet_eta"), etaJet2Raw, weight); + registry.fill(HIST("h2_mixdijet_detanoflip_dphi"), deltaEtaJetsNoflip, deltaPhiJets, weight); + registry.fill(HIST("h2_mixdijet_Asymmetry"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, weight); + registry.fill(HIST("h3_mixdijet_deta_pt"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, weight); + if (multEta1Eta2 > 0) + registry.fill(HIST("h2_mixdijet_TimeEtaThan0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); + else if (multEta1Eta2 < 0) + registry.fill(HIST("h2_mixdijet_TimeEtaLess0_pt"), ptLeadingCorr, ptSubleadingCorr, weight); for (auto const& track : tracks2) { - totalPairs++; registry.fill(HIST("h_mix_event_stats"), 4); if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; - passedPairs++; registry.fill(HIST("h_mix_event_stats"), 5); double hpt = track.pt(); double heta = inverse * (track.eta()); // Dr.Yang @@ -955,38 +940,32 @@ struct ChargedJetHadron { if (hpt > assoHadronPtMaxCut) continue; - registry.fill(HIST("h_mixjeth_detatot"), detatot, eventWeight); - registry.fill(HIST("h_mixjeth_deta"), deta, eventWeight); - registry.fill(HIST("h_mixjeth_dphi"), dphi, eventWeight); - registry.fill(HIST("h2_mixjeth_detatot_dphi"), detatot, dphi, eventWeight); + registry.fill(HIST("h_mixjeth_detatot"), detatot, weight); + registry.fill(HIST("h_mixjeth_deta"), deta, weight); + registry.fill(HIST("h_mixjeth_dphi"), dphi, weight); if (doDijetRaa) - registry.fill(HIST("thn_mixljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, eventWeight); + registry.fill(HIST("thn_mixljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, weight); else - registry.fill(HIST("thn_mixljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, poolBin, eventWeight); + registry.fill(HIST("thn_mixljeth_correlations"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, poolBin, weight); if (hpt < assoHadronPtCut) { - registry.fill(HIST("h2_mixjeth_deta_dphi"), deta, dphi, eventWeight); + registry.fill(HIST("h2_mixjeth_deta_dphi"), deta, dphi, weight); if (std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsup_deta_dphi"), deta, dphi, eventWeight); + registry.fill(HIST("h2_mixjeth_physicalcutsup_deta_dphi"), deta, dphi, weight); if (std::abs(deltaEtaJets) >= etaGapdw && std::abs(deltaEtaJets) < etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsmd_deta_dphi"), deta, dphi, eventWeight); + registry.fill(HIST("h2_mixjeth_physicalcutsmd_deta_dphi"), deta, dphi, weight); if (std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_mixjeth_physicalcutsdw_deta_dphi"), deta, dphi, eventWeight); - if (etaJet1Raw > etaJet2Raw && std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_mixjeth_physicalcutsHdw_deta_dphi"), detatot, dphi, eventWeight); // Dr.Yang + registry.fill(HIST("h2_mixjeth_physicalcutsdw_deta_dphi"), deta, dphi, weight); } } } - registry.fill(HIST("h_mix_event_stats"), 6, totalmix); - registry.fill(HIST("h_mix_event_stats"), 7, totaldijets); - registry.fill(HIST("h_mix_event_stats"), 8, totaldijetscut); - registry.fill(HIST("h_mix_event_stats"), 9, totalPairs); - registry.fill(HIST("h_mix_event_stats"), 10, passedPairs); } //........MCP..leading jet - hadron correlations..................... template - void fillMCPLeadingJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float eventWeight = 1.0) + void fillMCPLeadingJetHadronHistograms(const TmcCollision& mccollision, const TJets& jets, const TParticles& particles, float weight = 1.0) { + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + using ParticlesTable = std::decay_t; typename TJets::iterator leadingJet; typename TJets::iterator subleadingJet; bool hasLeading = false; @@ -998,9 +977,10 @@ struct ChargedJetHadron { const auto& jet = *it; if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - using ParticlesTable = std::decay_t; if (!isAcceptedJet(jet, true)) continue; + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) + return; double ptCorr = jet.pt() - jet.area() * mccollision.rho(); if (ptCorr > ptLeadingCorr) { @@ -1020,8 +1000,8 @@ struct ChargedJetHadron { } if (!hasLeading || !hasSubleading) return; - double deltaPhiJets = RecoDecay::constrainAngle(leadingJet.phi() - subleadingJet.phi(), 0.); - if (std::abs(deltaPhiJets) < PIHalf || std::abs(deltaPhiJets) > absPiCut * PI) + double deltaPhiJets = RecoDecay::constrainAngle(leadingJet.phi() - subleadingJet.phi(), -PIHalf); + if (std::abs(deltaPhiJets) < dijetDphiCut * PI) return; double etaJet1Raw = leadingJet.eta(); @@ -1033,23 +1013,24 @@ struct ChargedJetHadron { double etajet1 = flip * etaJet1Raw; // leading jet eta after flip double etajet2 = flip * etaJet2Raw; // subleading jet eta after flip double deltaEtaJets = etajet1 - etajet2; // >= 0 - registry.fill(HIST("h_dijet_pair_counts_part"), 1); - registry.fill(HIST("h_leadjet_pt_part"), leadingJet.pt(), eventWeight); - registry.fill(HIST("h_subleadjet_pt_part"), subleadingJet.pt(), eventWeight); - registry.fill(HIST("h_leadjet_corrpt_part"), ptLeadingCorr, eventWeight); - registry.fill(HIST("h_subleadjet_corrpt_part"), ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_leadjet_pt_part"), leadingJet.pt(), weight); + registry.fill(HIST("h_subleadjet_pt_part"), subleadingJet.pt(), weight); + registry.fill(HIST("h_leadjet_corrpt_part"), ptLeadingCorr, weight); + registry.fill(HIST("h_subleadjet_corrpt_part"), ptSubleadingCorr, weight); if (ptLeadingCorr < leadingjetptMin || ptSubleadingCorr < subleadingjetptMin) return; - registry.fill(HIST("h_dijet_pair_counts_cut_part"), 2); - registry.fill(HIST("h_leadjet_eta_part"), etaJet1Raw, eventWeight); - registry.fill(HIST("h_subleadjet_eta_part"), etaJet2Raw, eventWeight); - registry.fill(HIST("h_leadjet_phi_part"), leadingJet.phi(), eventWeight); - registry.fill(HIST("h_subleadjet_phi_part"), subleadingJet.phi(), eventWeight); - registry.fill(HIST("h2_dijet_detanoflip_dphi_part"), deltaEtaJetsNoflip, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_dijet_deta_dphi_part"), deltaEtaJets, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_dijet_Asymmetry_part"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, eventWeight); - registry.fill(HIST("h3_dijet_deta_pt_part"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_leadjet_eta_part"), etaJet1Raw, weight); + registry.fill(HIST("h_subleadjet_eta_part"), etaJet2Raw, weight); + registry.fill(HIST("h_leadjet_phi_part"), leadingJet.phi(), weight); + registry.fill(HIST("h_subleadjet_phi_part"), subleadingJet.phi(), weight); + registry.fill(HIST("h2_dijet_detanoflip_dphi_part"), deltaEtaJetsNoflip, deltaPhiJets, weight); + registry.fill(HIST("h2_dijet_Asymmetry_part"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, weight); + registry.fill(HIST("h3_dijet_deta_pt_part"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, weight); + if (multEta1Eta2 > 0) + registry.fill(HIST("h2_dijet_TimeEtaThan0_pt_part"), ptLeadingCorr, ptSubleadingCorr, weight); + else if (multEta1Eta2 < 0) + registry.fill(HIST("h2_dijet_TimeEtaLess0_pt_part"), ptLeadingCorr, ptSubleadingCorr, weight); for (auto const& particle : particles) { double hpt = particle.pt(); @@ -1060,36 +1041,36 @@ struct ChargedJetHadron { dphi = RecoDecay::constrainAngle(dphi, -PIHalf); if (hpt > assoHadronPtMaxCut) continue; - registry.fill(HIST("h_jeth_detatot_part"), detatot, eventWeight); - registry.fill(HIST("h_jeth_deta_part"), deta, eventWeight); - registry.fill(HIST("h_jeth_dphi_part"), dphi, eventWeight); - registry.fill(HIST("h2_jeth_detatot_dphi_part"), detatot, dphi, eventWeight); + registry.fill(HIST("h_jeth_detatot_part"), detatot, weight); + registry.fill(HIST("h_jeth_deta_part"), deta, weight); + registry.fill(HIST("h_jeth_dphi_part"), dphi, weight); if (doDijetRaa) - registry.fill(HIST("thn_ljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, eventWeight); + registry.fill(HIST("thn_ljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, weight); else - registry.fill(HIST("thn_ljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, eventWeight); + registry.fill(HIST("thn_ljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, weight); if (hpt < assoHadronPtCut) { registry.fill(HIST("h2_jeth_deta_dphi_part"), deta, dphi); if (std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_jeth_physicalcutsup_deta_dphi_part"), deta, dphi, eventWeight); + registry.fill(HIST("h2_jeth_physicalcutsup_deta_dphi_part"), deta, dphi, weight); if (std::abs(deltaEtaJets) >= etaGapdw && std::abs(deltaEtaJets) < etaGapup) - registry.fill(HIST("h2_jeth_physicalcutsmd_deta_dphi_part"), deta, dphi, eventWeight); + registry.fill(HIST("h2_jeth_physicalcutsmd_deta_dphi_part"), deta, dphi, weight); if (std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_jeth_physicalcutsdw_deta_dphi_part"), deta, dphi, eventWeight); - if (std::abs(deltaEtaJets) < etaGapdw && etaJet1Raw > etaJet2Raw) - registry.fill(HIST("h2_jeth_physicalcutsHdw_deta_dphi_part"), detatot, dphi, eventWeight); + registry.fill(HIST("h2_jeth_physicalcutsdw_deta_dphi_part"), deta, dphi, weight); } } } //..........MCP..mixed events......................................... template - void fillMCPMixLeadingJetHadronHistograms(const TmcCollisions& mccollisions, const TCollisions& collisions, const TJets& jets, const TParticles& particles, float eventWeight = 1.0) + void fillMCPMixLeadingJetHadronHistograms(const TmcCollisions& mccollisions, const TCollisions& collisions, const TJets& jets, const TParticles& particles, float weight = 1.0) { + using ParticlesTable = std::decay_t; auto particlesTuple = std::make_tuple(jets, particles); Pair pairMCData{corrBinningMC, numberEventsMixed, -1, mccollisions, particlesTuple, &cache}; for (const auto& [c1, jets1, c2, particles2] : pairMCData) { + weight = doEventWeighted ? c1.weight() : 1.f; + const float pTHat = 10.f / std::pow(weight, 1.f / pTHatExponent); registry.fill(HIST("h_mixevent_stats_part"), 1); // int poolBin = corrBinningMC.getBin(std::make_tuple(c2.posZ(), getMultiplicity(c2))); if (!applyMCCollisionCuts(c1, collisions) || !applyMCCollisionCuts(c2, collisions)) @@ -1106,9 +1087,10 @@ struct ChargedJetHadron { const auto& jet = *it; if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - using ParticlesTable = std::decay_t; if (!isAcceptedJet(jet, true)) continue; + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) + return; double ptCorr = jet.pt() - jet.area() * c1.rho(); if (ptCorr > ptLeadingCorr) { @@ -1130,8 +1112,8 @@ struct ChargedJetHadron { continue; double deltaPhiJets = leadingJet.phi() - subleadingJet.phi(); - deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, 0.); - if (std::abs(deltaPhiJets) < PIHalf || std::abs(deltaPhiJets) > absPiCut * PI) + deltaPhiJets = RecoDecay::constrainAngle(deltaPhiJets, -PIHalf); + if (std::abs(deltaPhiJets) < dijetDphiCut * PI) continue; registry.fill(HIST("h_mixevent_stats_part"), 2); @@ -1144,19 +1126,22 @@ struct ChargedJetHadron { double etajet1 = flip * etaJet1Raw; double etajet2 = flip * etaJet2Raw; double deltaEtaJets = etajet1 - etajet2; - registry.fill(HIST("h_mixleadjet_corrpt_part"), ptLeadingCorr, eventWeight); - registry.fill(HIST("h_mixsubleadjet_corrpt_part"), ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_mixleadjet_corrpt_part"), ptLeadingCorr, weight); + registry.fill(HIST("h_mixsubleadjet_corrpt_part"), ptSubleadingCorr, weight); if (ptLeadingCorr < leadingjetptMin || ptSubleadingCorr < subleadingjetptMin) return; registry.fill(HIST("h_mixevent_stats_part"), 3); registry.fill(HIST("h_mixdijet_pair_counts_cut_part"), 1); - registry.fill(HIST("h_mixleadjet_eta_part"), etaJet1Raw, eventWeight); - registry.fill(HIST("h_mixsubleadjet_eta_part"), etaJet2Raw, eventWeight); - registry.fill(HIST("h2_mixdijet_detanoflip_dphi_part"), deltaEtaJetsNoflip, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_mixdijet_deta_dphi_part"), deltaEtaJets, deltaPhiJets, eventWeight); - registry.fill(HIST("h2_mixdijet_Asymmetry_part"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, eventWeight); - registry.fill(HIST("h3_mixdijet_deta_pt_part"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, eventWeight); + registry.fill(HIST("h_mixleadjet_eta_part"), etaJet1Raw, weight); + registry.fill(HIST("h_mixsubleadjet_eta_part"), etaJet2Raw, weight); + registry.fill(HIST("h2_mixdijet_detanoflip_dphi_part"), deltaEtaJetsNoflip, deltaPhiJets, weight); + registry.fill(HIST("h2_mixdijet_Asymmetry_part"), ptSubleadingCorr, ptSubleadingCorr / ptLeadingCorr, weight); + registry.fill(HIST("h3_mixdijet_deta_pt_part"), deltaEtaJets, ptLeadingCorr, ptSubleadingCorr, weight); + if (multEta1Eta2 > 0) + registry.fill(HIST("h2_mixdijet_TimeEtaThan0_pt_part"), ptLeadingCorr, ptSubleadingCorr, weight); + else if (multEta1Eta2 < 0) + registry.fill(HIST("h2_mixdijet_TimeEtaLess0_pt_part"), ptLeadingCorr, ptSubleadingCorr, weight); for (auto const& particle : particles2) { registry.fill(HIST("h_mixevent_stats_part"), 4); @@ -1170,24 +1155,21 @@ struct ChargedJetHadron { if (hpt > assoHadronPtMaxCut) continue; registry.fill(HIST("h_mixevent_stats_part"), 5); - registry.fill(HIST("h_mixjeth_detatot_part"), detatot, eventWeight); - registry.fill(HIST("h_mixjeth_deta_part"), deta, eventWeight); - registry.fill(HIST("h_mixjeth_dphi_part"), dphi, eventWeight); - registry.fill(HIST("h2_mixjeth_detatot_dphi_part"), detatot, dphi, eventWeight); + registry.fill(HIST("h_mixjeth_detatot_part"), detatot, weight); + registry.fill(HIST("h_mixjeth_deta_part"), deta, weight); + registry.fill(HIST("h_mixjeth_dphi_part"), dphi, weight); if (doDijetRaa) - registry.fill(HIST("thn_mixljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, eventWeight); + registry.fill(HIST("thn_mixljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, kNaN, multEta1Eta2, deltaEtaJetsNoflip, kNaN, kNaN, kNaN, weight); else - registry.fill(HIST("thn_mixljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, eventWeight); + registry.fill(HIST("thn_mixljeth_correlations_part"), ptLeadingCorr, ptSubleadingCorr, hpt, multEta1Eta2, deltaEtaJets, heta, deta, dphi, weight); if (hpt < assoHadronPtCut) { registry.fill(HIST("h2_mixjeth_deta_dphi_part"), deta, dphi); if (std::abs(deltaEtaJets) >= etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsup_deta_dphi_part"), deta, dphi, eventWeight); + registry.fill(HIST("h2_mixjeth_physicalcutsup_deta_dphi_part"), deta, dphi, weight); if (std::abs(deltaEtaJets) >= etaGapdw && std::abs(deltaEtaJets) < etaGapup) - registry.fill(HIST("h2_mixjeth_physicalcutsmd_deta_dphi_part"), deta, dphi, eventWeight); + registry.fill(HIST("h2_mixjeth_physicalcutsmd_deta_dphi_part"), deta, dphi, weight); if (std::abs(deltaEtaJets) < etaGapdw) - registry.fill(HIST("h2_mixjeth_physicalcutsdw_deta_dphi_part"), deta, dphi, eventWeight); - if (std::abs(deltaEtaJets) < etaGapdw && etaJet1Raw > etaJet2Raw) - registry.fill(HIST("h2_mixjeth_physicalcutsHdw_deta_dphi_part"), detatot, dphi, eventWeight); + registry.fill(HIST("h2_mixjeth_physicalcutsdw_deta_dphi_part"), deta, dphi, weight); } } } @@ -1220,7 +1202,7 @@ struct ChargedJetHadron { fillTrackHistograms(track); } } - PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCData, "collisions and tracks QC for Data and MCD", true); + PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCData, "QC of collisions and tracks for Data", true); void processSpectraAreaSubData(FilterCollision const& collision, CorrChargedJets const& jets, @@ -1239,7 +1221,7 @@ struct ChargedJetHadron { fillJetAreaSubHistograms(jet, collision.rho()); } } - PROCESS_SWITCH(ChargedJetHadron, processSpectraAreaSubData, "jet spectra with rho-area subtraction for Data", false); + PROCESS_SWITCH(ChargedJetHadron, processSpectraAreaSubData, "jet spectra without and with rho-area subtraction for Data", false); void processLeadingJetHadron(FilterCollision const& collision, CorrChargedJets const& jets, @@ -1249,7 +1231,7 @@ struct ChargedJetHadron { return; fillLeadingJetHadronHistograms(collision, jets, tracks); } - PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadron, "leadingjet-h for Data", false); + PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadron, "ame event subleading jet-h for Data", false); void processMixLeadingJetHadron(FilterCollisions const& collisions, CorrChargedJets const& jets, @@ -1259,7 +1241,7 @@ struct ChargedJetHadron { return; fillMixLeadingJetHadronHistograms(collisions, jets, tracks); } - PROCESS_SWITCH(ChargedJetHadron, processMixLeadingJetHadron, "leadingjet-h mixed event correlation for Data", false); + PROCESS_SWITCH(ChargedJetHadron, processMixLeadingJetHadron, "mixed event leading jet-h for Data", false); void processJetHadron(FilterCollision const& collision, CorrChargedJets const& jets, @@ -1279,7 +1261,7 @@ struct ChargedJetHadron { return; fillMixJetHadronHistograms(collisions, jets, tracks); } - PROCESS_SWITCH(ChargedJetHadron, processMixJetHadron, "jet-h mixed event correlation for Data", false); + PROCESS_SWITCH(ChargedJetHadron, processMixJetHadron, "mixed event jet-h for Data", false); //...HF jet correlations.................... void processHFJetCorrelation(FilterCollision const& collision, @@ -1298,7 +1280,6 @@ struct ChargedJetHadron { registry.fill(HIST("h_d0jet_phi"), jet.phi()); } for (const auto& candidate : candidates) { - // float ptD = candidate.ptD(); //from HFC D0-h registry.fill(HIST("h_d0_mass"), candidate.m()); registry.fill(HIST("h_d0_pt"), candidate.pt()); registry.fill(HIST("h_d0_eta"), candidate.eta()); @@ -1317,7 +1298,7 @@ struct ChargedJetHadron { void processCollisionsQCMCD(soa::Join::iterator const& collision, FilterJetTracks const& tracks) { - float eventWeight = collision.weight(); + const float eventWeight = doEventWeighted ? collision.weight() : 1.f; if (!collision.has_mcCollision()) { registry.fill(HIST("h_fakecollisions"), 0.5); } @@ -1345,12 +1326,13 @@ struct ChargedJetHadron { fillTrackHistograms(track, eventWeight); } } - PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCMCD, "weighted collisions and tracks for MCD", false); + PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCMCD, "QC of collisions and tracks for MCD", false); void processSpectraAreaSubMCD(FilterCollision const& collision, CorrChargedMCDJets const& jets, aod::JetTracks const&) { + const float eventWeight = doEventWeighted ? collision.weight() : 1.f; if (!isGoodCollision(collision)) return; for (auto const& jet : jets) { @@ -1360,8 +1342,8 @@ struct ChargedJetHadron { if (!isAcceptedJet(jet)) { continue; } - fillJetHistograms(jet); - fillJetAreaSubHistograms(jet, collision.rho()); + fillJetHistograms(jet, eventWeight); + fillJetAreaSubHistograms(jet, collision.rho(), eventWeight); } } PROCESS_SWITCH(ChargedJetHadron, processSpectraAreaSubMCD, "jet spectra with rho-area subtraction for MCD", false); @@ -1370,10 +1352,11 @@ struct ChargedJetHadron { CorrChargedMCDJets const& jets, FilterJetTracks const& tracks) { + const float eventWeight = doEventWeighted ? collision.weight() : 1.f; if (!isGoodCollision(collision)) { return; } - fillLeadingJetHadronHistograms(collision, jets, tracks); + fillLeadingJetHadronHistograms(collision, jets, tracks, eventWeight); } PROCESS_SWITCH(ChargedJetHadron, processLeadinJetHadronMCD, "same event leading jet-hadron correlations for MCD", false); @@ -1391,9 +1374,10 @@ struct ChargedJetHadron { CorrChargedMCDJets const& jets, FilterJetTracks const& tracks) { + const float eventWeight = doEventWeighted ? collision.weight() : 1.f; if (!isGoodCollision(collision)) return; - fillJetHadronHistograms(collision, jets, tracks); + fillJetHadronHistograms(collision, jets, tracks, eventWeight); } PROCESS_SWITCH(ChargedJetHadron, processJetHadronMCD, "same event jet-hadron correlations for MCD", false); @@ -1407,38 +1391,12 @@ struct ChargedJetHadron { } PROCESS_SWITCH(ChargedJetHadron, processMixJetHadronMCD, "mixed event jet-hadron correlations for MCD", false); - //............weighted................ - void processSpectraMCDWeighted(soa::Filtered::iterator const& collision, - soa::Join const& jets, - aod::JetTracks const&) - { - if (!isGoodCollision(collision)) - return; - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; - } - if (!isAcceptedJet(jet)) { - continue; - } - float eventWeight = jet.eventWeight(); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - if (jet.pt() > pTHatMaxMCD * pTHat) { - continue; - } - registry.fill(HIST("h_jet_phat"), pTHat); - registry.fill(HIST("h_jet_phat_weighted"), pTHat, eventWeight); - fillJetHistograms(jet, eventWeight); - } - } - PROCESS_SWITCH(ChargedJetHadron, processSpectraMCDWeighted, "jet finder QC mcd with weighted events", false); - //........MCP.................................................. void processCollisionsQCMCP(aod::JetMcCollision const& mccollision, soa::SmallGroups const& collisions, soa::Filtered const& particles) { - float eventWeight = mccollision.weight(); + const float eventWeight = doEventWeighted ? mccollision.weight() : 1.f; registry.fill(HIST("h_mcColl_counts"), 0.5); if (std::abs(mccollision.posZ()) > vertexZCut) @@ -1456,30 +1414,37 @@ struct ChargedJetHadron { int nGood = 0; for (auto const& collision : collisions) { if (isGoodCollision(collision)) { - registry.fill(HIST("h_mc_mult"), getMultiplicity(collision)); + registry.fill(HIST("h_mcdColl_mult"), getMultiplicity(collision), eventWeight); nGood++; } } if (nGood == 0) return; registry.fill(HIST("h_mcColl_counts"), 4.5); - registry.fill(HIST("h_mcColl_zvertex"), mccollision.posZ(), eventWeight); + registry.fill(HIST("h_mcpColl_Zvertex"), mccollision.posZ(), eventWeight); registry.fill(HIST("h_mcpColl_centrality"), mccollision.centFT0M(), eventWeight); registry.fill(HIST("h_mcpColl_mult"), getMultiplicity(mccollision), eventWeight); for (auto const& particle : particles) { fillParticleHistograms(particle, eventWeight); } } - PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCMCP, "collisions and tracks for MCP", false); + PROCESS_SWITCH(ChargedJetHadron, processCollisionsQCMCP, "QC of collisions and particles for MCP", false); - void processSpectraMCP(soa::Filtered::iterator const& mccollision, - soa::SmallGroups const& collisions, - CorrChargedMCPJets const& jets, - aod::JetParticles const&) + void processSpectraAreaSubMCP(FilterMcpCollision const& mccollision, + soa::SmallGroups const& collisions, + CorrChargedMCPJets const& jets, + soa::Filtered const&) { bool mcLevelIsParticleLevel = true; + const float eventWeight = doEventWeighted ? mccollision.weight() : 1.f; if (!applyMCCollisionCuts(mccollision, collisions)) return; + registry.fill(HIST("h_mcColl_rho"), mccollision.rho(), eventWeight); + if (doEventWeighted) { + registry.fill(HIST("h_mcColl_counts_weight"), 1.5); + registry.fill(HIST("h_mcColl_counts_weight"), 2.5, mccollision.xsectGen()); + registry.fill(HIST("h_mcColl_counts_weight"), 3.5, eventWeight); + } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1487,40 +1452,24 @@ struct ChargedJetHadron { if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { continue; } - fillMCPHistograms(jet); + fillMCPHistograms(jet, eventWeight); + fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight); } } - PROCESS_SWITCH(ChargedJetHadron, processSpectraMCP, "jet spectra for MCP", false); + PROCESS_SWITCH(ChargedJetHadron, processSpectraAreaSubMCP, "jet spectra without and with UE subtraction of area-based for MCP", false); void processLeadingJetHadronMCP(FilterMcpCollision const& mccollision, soa::SmallGroups const& collisions, CorrChargedMCPJets const& jets, soa::Filtered const& particles) { - bool mcLevelIsParticleLevel = true; + const float eventWeight = doEventWeighted ? mccollision.weight() : 1.f; if (!applyMCCollisionCuts(mccollision, collisions)) return; - for (auto const& collision : collisions) { - if (isGoodCollision(collision)) { - registry.fill(HIST("h_mcColl_centrality"), getCentrality(collision)); - registry.fill(HIST("h_mcColl_mult"), getMultiplicity(collision)); - break; - } - } - registry.fill(HIST("h_mcColl_rho"), mccollision.rho()); - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; - } - if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { - continue; - } - fillMCPAreaSubHistograms(jet, mccollision.rho()); - } - fillMCPLeadingJetHadronHistograms(mccollision, jets, particles); + fillMCPLeadingJetHadronHistograms(mccollision, jets, particles, eventWeight); } - PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadronMCP, "jet spectra with area-based & SM leading jet-hadron for MCP", false); + PROCESS_SWITCH(ChargedJetHadron, processLeadingJetHadronMCP, "same event leading jet-hadron for MCP", false); void processMixLeadingJetHadronMCP(FilterMcpCollisions const& mccollisions, soa::SmallGroups const& collisions, @@ -1538,10 +1487,11 @@ struct ChargedJetHadron { CorrChargedMCPJets const& jets, soa::Filtered const& particles) { + const float eventWeight = doEventWeighted ? mccollision.weight() : 1.f; if (!applyMCCollisionCuts(mccollision, collisions)) return; - fillMCPJetHadronHistograms(mccollision, jets, particles); + fillMCPJetHadronHistograms(mccollision, jets, particles, eventWeight); } PROCESS_SWITCH(ChargedJetHadron, processJetHadronMCP, "same event jet-hadron for MCP", false); @@ -1555,34 +1505,6 @@ struct ChargedJetHadron { fillMCPMixJetHadronHistograms(mccollisions, collisions, jets, particles); } PROCESS_SWITCH(ChargedJetHadron, processMixJetHadronMCP, "mixed event jet-hadron for MCP", false); - - //............weighted................ - void processSpectraMCPWeighted(soa::Filtered::iterator const& mccollision, - soa::SmallGroups const& collisions, - soa::Join const& jets, - aod::JetParticles const&) - { - bool mcLevelIsParticleLevel = true; - float eventWeight = mccollision.weight(); // float jetweight = jet.eventWeight(); - - if (!applyMCCollisionCuts(mccollision, collisions)) - return; - registry.fill(HIST("h_mcColl_counts_weight"), 1.5); - registry.fill(HIST("h_mcColl_counts_weight"), 2.5, mccollision.xsectGen()); - registry.fill(HIST("h_mcColl_counts_weight"), 3.5, eventWeight); - - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; - } - if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { - continue; - } - registry.fill(HIST("h_mcColl_counts_weight"), 4.5, jet.eventWeight()); - fillMCPHistograms(jet, eventWeight); - } - } - PROCESS_SWITCH(ChargedJetHadron, processSpectraMCPWeighted, "jet spectra for MCP weighted", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/dijetFinderQA.cxx b/PWGJE/Tasks/dijetFinderQA.cxx index 5c9f39f1a84..defb8a6c926 100644 --- a/PWGJE/Tasks/dijetFinderQA.cxx +++ b/PWGJE/Tasks/dijetFinderQA.cxx @@ -18,10 +18,10 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/emcCellMonitor.cxx b/PWGJE/Tasks/emcCellMonitor.cxx index 880ce14e490..0df39215cb2 100644 --- a/PWGJE/Tasks/emcCellMonitor.cxx +++ b/PWGJE/Tasks/emcCellMonitor.cxx @@ -9,15 +9,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsEMCAL/Constants.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/emcClusterMonitor.cxx b/PWGJE/Tasks/emcClusterMonitor.cxx index fbb8885c5be..b014ffae8fb 100644 --- a/PWGJE/Tasks/emcClusterMonitor.cxx +++ b/PWGJE/Tasks/emcClusterMonitor.cxx @@ -14,14 +14,14 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "EMCALBase/Geometry.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/emcEventSelectionQA.cxx b/PWGJE/Tasks/emcEventSelectionQA.cxx index 8ba3f5168c8..ff39021dce6 100644 --- a/PWGJE/Tasks/emcEventSelectionQA.cxx +++ b/PWGJE/Tasks/emcEventSelectionQA.cxx @@ -19,10 +19,10 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include #include #include #include diff --git a/PWGJE/Tasks/emcVertexSelectionQA.cxx b/PWGJE/Tasks/emcVertexSelectionQA.cxx index eb579326966..da45a313015 100644 --- a/PWGJE/Tasks/emcVertexSelectionQA.cxx +++ b/PWGJE/Tasks/emcVertexSelectionQA.cxx @@ -18,11 +18,11 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/emcalGammaGammaBcWise.cxx b/PWGJE/Tasks/emcalGammaGammaBcWise.cxx index d9674888aed..aa5e99fb70b 100644 --- a/PWGJE/Tasks/emcalGammaGammaBcWise.cxx +++ b/PWGJE/Tasks/emcalGammaGammaBcWise.cxx @@ -22,20 +22,20 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "EMCALBase/Geometry.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include #include #include #include +#include #include +#include #include #include #include -#include "TLorentzVector.h" -#include "TVector3.h" +#include +#include #include #include diff --git a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx index 273907b8056..61bff6d13e1 100644 --- a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx +++ b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx @@ -15,22 +15,22 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "EMCALBase/Geometry.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include #include +#include #include #include #include #include -#include "TLorentzVector.h" -#include "TVector3.h" #include #include +#include #include +#include #include #include diff --git a/PWGJE/Tasks/fullJetSpectra.cxx b/PWGJE/Tasks/fullJetSpectra.cxx index 8f8795cc074..0af05f60cac 100644 --- a/PWGJE/Tasks/fullJetSpectra.cxx +++ b/PWGJE/Tasks/fullJetSpectra.cxx @@ -23,20 +23,22 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" +#include "Common/DataModel/EventSelection.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include +#include +#include +#include #include +#include #include +#include #include #include +#include #include #include @@ -66,6 +68,7 @@ struct FullJetSpectra { Configurable doMcClosure{"doMcClosure", false, "Enable random splitting for MC closure test"}; */ // Event configurables + Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; @@ -93,11 +96,11 @@ struct FullJetSpectra { Configurable jetPhiMax{"jetPhiMax", 2.86, "maximum emcal Fid phi"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; - // Leading track and cluster pT configurables - Configurable minTrackPt{"minTrackPt", -99.0, "minimum pT selection on jet tracks"}; - Configurable maxTrackPt{"maxTrackPt", 999.0, "maximum pT selection on jet tracks"}; - Configurable minClusterPt{"minClusterPt", -99.0, "minimum pT selection on jet clusters"}; - Configurable maxClusterPt{"maxClusterPt", 999.0, "maximum pT selection on jet clusters"}; + // Maximum track and cluster pT configurables + Configurable minTrackPt{"minTrackPt", 0.15, "minimum pT selection on jet tracks"}; + Configurable maxTrackPt{"maxTrackPt", 150.0, "maximum pT selection on jet tracks"}; + Configurable minClusterPt{"minClusterPt", 0.3, "minimum pT selection on jet clusters"}; + Configurable maxClusterPt{"maxClusterPt", 250.0, "maximum pT selection on jet clusters"}; // Track configurables Configurable trackpTMin{"trackpTMin", 0.15, "minimum track pT"}; @@ -279,6 +282,19 @@ struct FullJetSpectra { hMatchedNoFidcollisionCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedDetColl"); } + if (doprocessJetsNewNoFidMCPMCDMatchedWeighted) { + auto hMatchedNewNoFidcollisionCounter = registry.get(HIST("hMatchedNewNoFidcollisionCounter")); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(1, "allDetColl"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(3, "RejectedDetCollWithOutliers"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(4, "RejectedPartCollWithOutliers"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(5, "EMCMBRejectedDetColl"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(6, "EventsNotSatisfyingEventSelection"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(7, "EMCreadoutDetJJEventsWithkTVXinEMC"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(8, "AllRejectedDetEventsAfterEMCEventSelection"); + hMatchedNewNoFidcollisionCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedDetColl"); + } + if (doprocessMBCollisionsDATAWithMultiplicity || doprocessMBMCDCollisionsWithMultiplicity) { auto hEventmultiplicityCounter = registry.get(HIST("hEventmultiplicityCounter")); hEventmultiplicityCounter->GetXaxis()->SetBinLabel(1, "allDetColl"); @@ -586,6 +602,38 @@ struct FullJetSpectra { registry.add("h_full_jet_NoFidResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F, {{500, 0., 500.}, {500, 0., 500.}}}, doSumw2); } + if (doprocessJetsNewNoFidMCPMCDMatchedWeighted) { + registry.add("hMatchedNewNoFidcollisionCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}, doSumw2); + registry.add("h_allMatchedNewNoFidPartJetsCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}, doSumw2); + + registry.add("h_full_NoFidmatchedmcdjet_tablesize", "", {HistType::kTH1F, {{350, 0., 350.}}}, doSumw2); + registry.add("h_full_NoFidmatchedmcpjet_tablesize", "", {HistType::kTH1F, {{350, 0., 350.}}}, doSumw2); + registry.add("h_full_NoFidmatchedmcdjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}, doSumw2); + registry.add("h_full_NoFidmatchedmcpjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}, doSumw2); + registry.add("h_full_NewNoFidmatchedmcpjet_eta", "Matched No Fid MCP jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1., 1.}}}, doSumw2); + registry.add("h_full_NewNoFidmatchedmcpjet_phi", "Matched No Fid MCP jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{160, 0., 7.}}}, doSumw2); + registry.add("h_allMatchedNewNoFidPartJetsPt", "Matched No Fid MCP jet Pt;p_{T,part} (GeV/c);entries", {HistType::kTH1F, {{350, 0.0, 350.0}}}, doSumw2); + registry.add("h_full_jet_NoFiddeltaR", "Distance between matched Det Jet and Part Jet; #Delta R; entries", {HistType::kTH1F, {{100, 0., 1.}}}, doSumw2); + + registry.add("h2_full_jet_NoFidenergyscaleDet", "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.}}}, doSumw2); + + registry.add("h2_NoFidmatchedjet_etaphiDet", "Det jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}, doSumw2); + registry.add("h2_NoFidmatchedjet_etaphiPart", "Part jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}, doSumw2); + registry.add("h2_NoFidmatchedjet_deltaEtaCorr", "Correlation between Det Eta and Part Eta; #eta_{jet,det}; #eta_{jet,part}", {HistType::kTH2F, {{100, -1., 1.}, {100, -1., 1.}}}, doSumw2); + registry.add("h2_NoFidmatchedjet_deltaPhiCorr", "Correlation between Det Phi and Part Phi; #varphi_{jet,det}; #varphi_{jet,part}", {HistType::kTH2F, {{160, 0., 7.}, {160, 0., 7.}}}, doSumw2); + + registry.add("h2_full_jet_NoFidenergyscalePart", "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.}}}, doSumw2); + registry.add("h3_full_jet_NoFidenergyscalePart", "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.}}}, doSumw2); + registry.add("h2_full_jet_NoFidetaresolutionPart", ";p_{T,part} (GeV/c); (#eta_{jet,det} - #eta_{jet,part})/#eta_{jet,part}", {HistType::kTH2F, {{400, 0., 400.}, {100, -1., 1.}}}, doSumw2); + registry.add("h2_full_jet_NoFidphiresolutionPart", ";p_{T,part} (GeV/c); (#varphi_{jet,det} - #varphi_{jet,part})/#varphi_{jet,part}", {HistType::kTH2F, {{400, 0., 400.}, {160, -1., 7.}}}, doSumw2); + registry.add("h2_full_NewNoFidfakemcdjets", "Fake MCD Jets; p_{T,det} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}, doSumw2); + registry.add("h2_full_NewNoFidfakemcpjets", "Fake MCP Jets; p_{T,part} (GeV/c); NCounts", {HistType::kTH2F, {{350, 0., 350.}, {100, 0., 100.}}}, doSumw2); + registry.add("h2_full_NewNoFidmatchedmcpjet_pt", "Matched No Fid MCP jet #it{p}_{T,part};#it{p}_{T,part} (GeV/c); Ncounts", {HistType::kTH2F, {{350, 0., 350.}, {10000, 0., 10000.}}}, doSumw2); + + // Response Matrix + registry.add("h_full_jet_NoFidResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F, {{500, 0., 500.}, {500, 0., 500.}}}, doSumw2); + } + if (doprocessMBCollisionsDATAWithMultiplicity || doprocessMBMCDCollisionsWithMultiplicity || doprocessMCDCollisionsWeightedWithMultiplicity) { registry.add("hEventmultiplicityCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}, doSumw2); registry.add("h_FT0Mults_occupancy", "", {HistType::kTH1F, {{3500, 0., 3500.}}}, doSumw2); @@ -705,7 +753,7 @@ struct FullJetSpectra { } */ using EMCCollisionsData = o2::soa::Join; // JetCollisions with EMCAL Collision Labels - using EMCCollisionsTriggeredData = o2::soa::Join; + using EMCCollisionsTriggeredData = o2::soa::Join; using EMCCollisionsMCD = o2::soa::Join; // where, JetCollisionsMCD = JetCollisions+JMcCollisionLbs @@ -742,48 +790,39 @@ struct FullJetSpectra { PresliceUnsorted> perFoundBC = aod::evsel::foundBCId; template - bool isAcceptedRecoJet(U const& jet, double& filteredTrackPt, double& filteredClusterPt) + bool isAcceptedRecoJet(U const& jet /*, double& filteredTrackPt, double& filteredClusterPt*/) { // Reset filtered pT accumulators (for QA if needed) - filteredTrackPt = 0.0; - filteredClusterPt = 0.0; - - // --- Track cuts: ALL tracks must satisfy 0.15 <= pT <= 200 or 150 GeV/c--- - // if (leadingTrackPtMin > kLeadingTrackPtMinThreshold || leadingTrackPtMax < kLeadingTrackPtMaxThreshold) { - bool hasValidTrack = false; - for (const auto& constituent : jet.template tracks_as()) { - const float pt = constituent.pt(); - if ((minTrackPt > kLeadingTrackPtMinThreshold && pt < minTrackPt) || - (maxTrackPt < kLeadingTrackPtMaxThreshold && pt > maxTrackPt)) { - continue; // SKIP this invalid track + // filteredTrackPt = 0.0; + // filteredClusterPt = 0.0; + + // --- Track cuts: ALL tracks must satisfy 0.15 <= pT <= 140 GeV/c--- + if (minTrackPt > kLeadingTrackPtMinThreshold || maxTrackPt < kLeadingTrackPtMaxThreshold) { + for (const auto& constituent : jet.template tracks_as()) { + const float pt = constituent.pt(); + + // Reject entire jet if ANY track fails the cuts + if ((minTrackPt > kLeadingTrackPtMinThreshold && pt < minTrackPt) || + (maxTrackPt < kLeadingTrackPtMaxThreshold && pt > maxTrackPt)) { + return false; // Reject the jet + } } - filteredTrackPt += pt; // Accumulate valid track pT - hasValidTrack = true; // At least one track exists (if needed) - } - // Reject jets without valid tracks (edge case) - if (!hasValidTrack) { - return false; } - // } // --- Cluster cuts: ALL clusters must satisfy min <= pT <= max == 0.3 <= pT <= 250 - // if (leadingClusterPtMin > kLeadingClusterPtMinThreshold || leadingClusterPtMax < kLeadingClusterPtMaxThreshold) { - bool hasValidCluster = false; - for (const auto& cluster : jet.template clusters_as()) { - const double pt = cluster.energy() / std::cosh(cluster.eta()); - if ((minClusterPt > kLeadingClusterPtMinThreshold && pt < minClusterPt) || - (maxClusterPt < kLeadingClusterPtMaxThreshold && pt > maxClusterPt)) { - continue; // SKIP this invalid cluster + // Reject jet if ANY cluster is outside range + if (minClusterPt > kLeadingClusterPtMinThreshold || maxClusterPt < kLeadingClusterPtMaxThreshold) { + for (const auto& cluster : jet.template clusters_as()) { + const double pt = cluster.energy() / std::cosh(cluster.eta()); + + // Reject entire jet if ANY cluster fails the cuts + if ((minClusterPt > kLeadingClusterPtMinThreshold && pt < minClusterPt) || + (maxClusterPt < kLeadingClusterPtMaxThreshold && pt > maxClusterPt)) { + return false; + } } - filteredClusterPt += pt; - hasValidCluster = true; // At least one cluster exists - } - // Reject jets without valid clusters (edge case) - if (!hasValidCluster) { - return false; } - // } - return true; // Valid Jet + return true; // Valid Jet that passes all cuts } // isAcceptedRecoJet ends /* template @@ -1191,7 +1230,7 @@ struct FullJetSpectra { } registry.fill(HIST("hDetcollisionCounter"), 1.5); // DetCollWithVertexZ - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hDetcollisionCounter"), 4.5); // EventsNotSatisfyingEventSelection return; } @@ -1227,6 +1266,9 @@ struct FullJetSpectra { // if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { // continue; // } + if (!isAcceptedRecoJet(jet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } if (!isInPhiAcceptance(jet)) { // Using the new phi acceptance function continue; } @@ -1257,8 +1299,8 @@ struct FullJetSpectra { } registry.fill(HIST("hDetTrigcollisionCounter"), 2.5); // DetTrigCollWithVertexZ - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - registry.fill(HIST("hDetTrigcollisionCounter"), 3.5); // EventsNotSatisfyingEvent+TriggerSelection + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { // applyRCTSelections doesn't work here + registry.fill(HIST("hDetTrigcollisionCounter"), 3.5); // EventsNotSatisfyingEvent+TriggerSelection return; } //- should this kTVX HW trigger be still in place? - Removing it for now; probably not needed if we are only interested in SW triggers @@ -1350,10 +1392,14 @@ struct FullJetSpectra { registry.fill(HIST("hDetTrigcollisionCounter"), 15.5); // EMCAcceptedDetTrigCollWithLow+HighFullJetTriggers eventAccepted = true; } + for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } + if (!isAcceptedRecoJet(jet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } if (!isInPhiAcceptance(jet)) { // Using the new phi acceptance function continue; } @@ -1415,7 +1461,7 @@ struct FullJetSpectra { registry.fill(HIST("hDetcollisionCounter"), 3.5); // MBRejectedDetEvents return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hDetcollisionCounter"), 4.5); // EventsNotSatisfyingEventSelection return; } @@ -1448,6 +1494,9 @@ struct FullJetSpectra { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } + if (!isAcceptedRecoJet(jet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } if (!isInPhiAcceptance(jet)) { // Using the new phi acceptance function continue; } @@ -1507,7 +1556,7 @@ struct FullJetSpectra { registry.fill(HIST("hDetcollisionCounter"), 3.5, collision.mcCollision().weight()); // MBRejectedDetEvents return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hDetcollisionCounter"), 4.5, collision.mcCollision().weight()); // EventsNotSatisfyingEventSelection return; } @@ -1537,10 +1586,12 @@ struct FullJetSpectra { registry.fill(HIST("hDetcollisionCounter"), 7.5, collision.mcCollision().weight()); // EMCAcceptedDetColl for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } + if (!isAcceptedRecoJet(jet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } if (!isInPhiAcceptance(jet)) { // Using the new phi acceptance function continue; } @@ -1612,7 +1663,7 @@ struct FullJetSpectra { registry.fill(HIST("hPartcollisionCounter"), 5.5); // AcceptedPartCollWithSize>=1 for (auto const& collision : collisionspermcpjet) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { continue; } if (doEMCALEventWorkaround) { @@ -1706,7 +1757,7 @@ struct FullJetSpectra { registry.fill(HIST("hPartcollisionCounter"), 5.5, mccollision.weight()); // AcceptedPartCollWithSize>=1 for (auto const& collision : collisionspermcpjet) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { continue; } if (doEMCALEventWorkaround) { @@ -1804,7 +1855,7 @@ struct FullJetSpectra { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hMatchedcollisionCounter"), 5.5); // EventsNotSatisfyingEventSelection return; } @@ -1828,13 +1879,15 @@ struct FullJetSpectra { registry.fill(HIST("hMatchedcollisionCounter"), 8.5); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isInPhiAcceptance(mcdjet)) { fakeMcdJet++; registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakeMcdJet, 1.0); continue; } + if (!isAcceptedRecoJet(mcdjet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } // Check if MCD jet is within the EMCAL fiducial region; if not then flag it as a fake jet // if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax || mcdjet.eta() < jetEtaMin || mcdjet.eta() > jetEtaMax) { // fakeMcdJet++; @@ -1887,7 +1940,7 @@ struct FullJetSpectra { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hMatchedNoFidcollisionCounter"), 5.5, eventWeight); // EventsNotSatisfyingEventSelection return; } @@ -1917,13 +1970,15 @@ struct FullJetSpectra { registry.fill(HIST("hMatchedNoFidcollisionCounter"), 8.5, eventWeight); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isInPhiAcceptance(mcdjet)) { fakeMcdJet++; registry.fill(HIST("h2_full_NoFidfakemcdjets"), mcdjet.pt(), fakeMcdJet, eventWeight); continue; } + if (!isAcceptedRecoJet(mcdjet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { allMatchedPartJets++; @@ -1950,6 +2005,110 @@ struct FullJetSpectra { } PROCESS_SWITCH(FullJetSpectra, processJetsNoFidMCPMCDMatchedWeighted, "Full Jet finder No Fid MCP matched to MCD on weighted events", false); + // Matching with Fiducial cuts at MCD only. + // New: First matching is done and then all the cuts are applied - if the matched jet pair pass the cuts then Accept the pair otherwise reject the jet pair. + void processJetsNewNoFidMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, JetTableMCDMatchedJoined const& mcdjets, JetTableMCPMatchedJoined const& mcpjets, aod::JMcCollisions const&, + aod::JetTracks const&, ClusterWithCorrections const&, aod::JetParticles const&) + { + bool eventAccepted = false; + int fakeMcdJet = 0; + int fakeMcpJet = 0; + int NPartJetFid = 0; // counter for the matched and accepted particle-level jets at the event level. + // int allMatchedPartJets = 0; + float eventWeight = collision.mcCollision().weight(); + float pTHat = 10.f / (std::pow(eventWeight, 1.0f / pTHatExponent)); + const auto mcpJetsPerMcCollision = mcpjets.sliceBy(JetMCPPerMcCollision, collision.mcCollisionId()); + + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 0.5, eventWeight); // allDetColl + if (std::fabs(collision.posZ()) > vertexZCut) { // making double sure this condition is satisfied + return; + } + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 1.5, eventWeight); // DetCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event + for (auto const& mcdjet : mcdjets) { + if (mcdjet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 2.5, eventWeight); // RejectedDetCollWithOutliers + return; + } + } + + if (doMBGapTrigger && collision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 4.5, eventWeight); // EMCMBRejectedDetColl + return; + } + + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 5.5, eventWeight); // EventsNotSatisfyingEventSelection + return; + } + + for (auto const& mcpjet : mcpJetsPerMcCollision) { + if (mcpjet.pt() > pTHatMaxMCP * pTHat) { // outlier rejection for MCP: Should I remove this cut as I'm already doing MC outlier rejection @L1071? + return; + } + } + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 6.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 6.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC + } + } + if (!eventAccepted) { + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 7.5, eventWeight); // AllRejectedDetEventsAfterEMCEventSelection + return; + } + registry.fill(HIST("hMatchedNewNoFidcollisionCounter"), 8.5, eventWeight); // EMCAcceptedDetColl + + // NEW: event-level counter of all MCP–MCD matches (pair count) + int allMatchedPartJetsEvent = 0; + + for (const auto& mcdjet : mcdjets) { + + for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + // allMatchedPartJets++; + // count every matched pair (MCD ↔ MCP), regardless of later cuts + ++allMatchedPartJetsEvent; + + registry.fill(HIST("h_allMatchedNewNoFidPartJetsPt"), mcpjet.pt(), eventWeight); + + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || + !isInPhiAcceptance(mcdjet)) { + fakeMcdJet++; + registry.fill(HIST("h2_full_NewNoFidfakemcdjets"), mcdjet.pt(), fakeMcdJet, eventWeight); + continue; + } + if (!isAcceptedRecoJet(mcdjet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } + + // Not applying any emcal fiducial cuts in eta and phi on MCP jets when matching. + // Keeping jet eta here open = |0.9| and no cut in phi at all. + if (!jetfindingutilities::isInEtaAcceptance(mcpjet, jetNoFidPartEtaMin, jetNoFidPartEtaMax, trackEtaMin, trackEtaMax)) { + fakeMcpJet++; + registry.fill(HIST("h2_full_NewNoFidfakemcpjets"), mcpjet.pt(), fakeMcpJet, eventWeight); + continue; + } + ++NPartJetFid; + // Fill matched histograms (including Response Matrix) for valid MCD-MCP pairs + fillMatchedNoFidHistograms(mcdjet, eventWeight); + registry.fill(HIST("h2_full_NewNoFidmatchedmcpjet_pt"), mcpjet.pt(), NPartJetFid, eventWeight); + registry.fill(HIST("h_full_NewNoFidmatchedmcpjet_eta"), mcpjet.eta(), eventWeight); + registry.fill(HIST("h_full_NewNoFidmatchedmcpjet_phi"), mcpjet.phi(), eventWeight); + } // mcpjet + } // mcdjet + // Fill the total matched particle jets histogram after processing all MCP jets for the MCD jet in a given accepted event + registry.fill(HIST("h_allMatchedNewNoFidPartJetsCounter"), allMatchedPartJetsEvent, eventWeight); + } + PROCESS_SWITCH(FullJetSpectra, processJetsNewNoFidMCPMCDMatchedWeighted, "Full Jet finder No Fid MCP matched to MCD on weighted events with new algorithm of rejecting jet pair", false); + void processJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, JetTableMCDMatchedJoined const& mcdjets, JetTableMCPMatchedJoined const& mcpjets, aod::JMcCollisions const&, aod::JetTracks const&, ClusterWithCorrections const&, aod::JetParticles const&) { @@ -2013,7 +2172,7 @@ struct FullJetSpectra { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hMatchedcollisionCounter"), 5.5, eventWeight); // EventsNotSatisfyingEventSelection return; } @@ -2043,13 +2202,15 @@ struct FullJetSpectra { registry.fill(HIST("hMatchedcollisionCounter"), 8.5, eventWeight); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isInPhiAcceptance(mcdjet)) { fakeMcdJet++; registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakeMcdJet, eventWeight); continue; } + if (!isAcceptedRecoJet(mcdjet)) { + continue; // maximum cuts on tracks and clusters due to poor detector reso; discard jets + } for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { allMatchedPartJets++; @@ -2115,7 +2276,7 @@ struct FullJetSpectra { registry.fill(HIST("hCollisionsUnweighted"), 2.5); // MBRejectedDetEvents return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hCollisionsUnweighted"), 3.5); // EventsNotSatisfyingEventSelection return; } @@ -2179,7 +2340,7 @@ struct FullJetSpectra { registry.fill(HIST("hCollisionsUnweighted"), 2.5); // MBRejectedDetEvents return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hCollisionsUnweighted"), 3.5); // EventsNotSatisfyingEventSelection return; } @@ -2237,7 +2398,7 @@ struct FullJetSpectra { registry.fill(HIST("hCollisionsWeighted"), 2.5, eventWeight); // MBRejectedDetEvents return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hCollisionsWeighted"), 3.5, eventWeight); // EventsNotSatisfyingEventSelection return; } @@ -2288,7 +2449,7 @@ struct FullJetSpectra { } registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // EventsNotSatisfyingEventSelection return; } @@ -2324,9 +2485,6 @@ struct FullJetSpectra { // Verify jet-collision association for (auto const& jet : jets) { - // Declare variables to store filtered track/cluster pT - double filteredTrackPt = 0.0; - double filteredClusterPt = 0.0; if (jet.collisionId() != collision.globalIndex()) { LOGF(warn, "Jet with pT %.2f belongs to collision %d but processing collision %d", jet.pt(), jet.collisionId(), collision.globalIndex()); continue; @@ -2336,7 +2494,7 @@ struct FullJetSpectra { continue; if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) continue; - if (!isAcceptedRecoJet(jet, filteredTrackPt, filteredClusterPt)) + if (!isAcceptedRecoJet(jet)) continue; selectedJets.push_back(jet); @@ -2473,7 +2631,7 @@ struct FullJetSpectra { } registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // EventsNotSatisfyingEventSelection return; } @@ -2509,9 +2667,6 @@ struct FullJetSpectra { // Verify jet-collision association for (auto const& mcdjet : mcdjets) { - // Declare variables to store filtered track/cluster pT - double filteredTrackPt = 0.0; - double filteredClusterPt = 0.0; if (mcdjet.collisionId() != collision.globalIndex()) { LOGF(warn, "Jet with pT %.2f belongs to collision %d but processing collision %d", mcdjet.pt(), mcdjet.collisionId(), collision.globalIndex()); continue; @@ -2521,7 +2676,7 @@ struct FullJetSpectra { continue; if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax) continue; - if (!isAcceptedRecoJet(mcdjet, filteredTrackPt, filteredClusterPt)) + if (!isAcceptedRecoJet(mcdjet)) continue; selectedJets.push_back(mcdjet); @@ -2622,7 +2777,7 @@ struct FullJetSpectra { registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { registry.fill(HIST("hEventmultiplicityCounter"), 3.5, eventWeight); // WeightedEventsNotSatisfyingEventSelection return; } @@ -2665,10 +2820,6 @@ struct FullJetSpectra { for (auto const& mcdjet : mcdjets) { float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - // Declare variables to store filtered track/cluster pT - double filteredTrackPt = 0.0; - double filteredClusterPt = 0.0; - if (mcdjet.collisionId() != collision.globalIndex()) { LOGF(warn, "Jet with pT %.2f belongs to collision %d but processing collision %d", mcdjet.pt(), mcdjet.collisionId(), collision.globalIndex()); continue; @@ -2683,7 +2834,7 @@ struct FullJetSpectra { if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax) { continue; } - if (!isAcceptedRecoJet(mcdjet, filteredTrackPt, filteredClusterPt)) { + if (!isAcceptedRecoJet(mcdjet)) { continue; } selectedJets.push_back(mcdjet); @@ -2809,7 +2960,7 @@ struct FullJetSpectra { registry.fill(HIST("hPartEventmultiplicityCounter"), 5.5); // AcceptedPartCollWithSize>1 for (auto const& collision : collisionspermcpjet) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { continue; } if (doEMCALEventWorkaround) { @@ -2971,7 +3122,7 @@ struct FullJetSpectra { registry.fill(HIST("hPartEventmultiplicityCounter"), 5.5, mccollision.weight()); // AcceptedWeightedPartCollWithSize>1 for (auto const& collision : collisionspermcpjet) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger, applyRCTSelections, "CBT_calo")) { continue; } if (doEMCALEventWorkaround) { diff --git a/PWGJE/Tasks/fullJetTriggerQATask.cxx b/PWGJE/Tasks/fullJetTriggerQATask.cxx index 88255a2dda7..4aff2f9ec2e 100644 --- a/PWGJE/Tasks/fullJetTriggerQATask.cxx +++ b/PWGJE/Tasks/fullJetTriggerQATask.cxx @@ -22,23 +22,22 @@ #include "Common/CCDB/TriggerAliases.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" #include +#include +#include #include #include #include #include #include -#include "TTree.h" #include #include #include #include +#include #include -#include #include #include diff --git a/PWGJE/Tasks/gammaJetTreeProducer.cxx b/PWGJE/Tasks/gammaJetTreeProducer.cxx index c5d38a4d395..de043149abe 100644 --- a/PWGJE/Tasks/gammaJetTreeProducer.cxx +++ b/PWGJE/Tasks/gammaJetTreeProducer.cxx @@ -14,41 +14,49 @@ /// \author Florian Jonas , UC Berkeley/LBNL /// \since 02.08.2024 -// C++ system headers first -#include - -#include -#include -#include - -// Framework and other headers after #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/GammaJetAnalysisTree.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.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 "EventFiltering/filterTables.h" - -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "TVector2.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include // \struct GammaJetTreeProducer /// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets @@ -62,20 +70,19 @@ using namespace o2::framework::expressions; using emcClusters = o2::soa::Join; using emcMCClusters = o2::soa::Join; -#include "Framework/runDataProcessing.h" - struct GammaJetTreeProducer { // analysis tree // charged jets // photon candidates - Produces chargedJetsTable; // detector level jets - Produces eventsTable; // rec events - Produces gammasTable; // detector level clusters - Produces mcEventsTable; // mc collisions information - Produces mcParticlesTable; // gen level particles (photons and pi0) - Produces gammaMCInfosTable; // detector level clusters MC information - Produces chJetMCInfosTable; // detector level charged jets MC information - Produces mcJetsTable; // gen level jets + Produces chargedJetsTable; // detector level jets + Produces eventsTable; // rec events + Produces gammasTable; // detector level clusters + Produces mcEventsTable; // mc collisions information + Produces mcParticlesTable; // gen level particles (photons and pi0) + Produces gammaMCInfosTable; // detector level clusters MC information + Produces chJetMCInfosTable; // detector level charged jets MC information + Produces mcJetsTable; // gen level jets + Produces jetSubstructuresTable; // jet substructure observables HistogramRegistry mHistograms{"GammaJetTreeProducerHisto"}; @@ -89,8 +96,8 @@ struct GammaJetTreeProducer { 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 trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable rctLabel{"rctLabel", "CBT_calo", "RCT label"}; Configurable trackMinPt{"trackMinPt", 0.15, "minimum track pT cut"}; Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable isoR{"isoR", 0.4, "isolation cone radius"}; @@ -98,7 +105,7 @@ struct GammaJetTreeProducer { Configurable trackMatchingEoverP{"trackMatchingEoverP", 2.0, "closest track is required to have E/p < value"}; Configurable minClusterETrigger{"minClusterETrigger", 0.0, "minimum cluster energy to trigger"}; Configurable minMCGenPt{"minMCGenPt", 0.0, "minimum pt of mc gen particles to store"}; - + Configurable calculateJetSubstructure{"calculateJetSubstructure", false, "calculate jet substructure"}; int mRunNumber = 0; std::vector eventSelectionBits; int trackSelection = -1; @@ -119,6 +126,21 @@ struct GammaJetTreeProducer { TKDTree* trackTree = nullptr; TKDTree* mcParticleTree = nullptr; + // for substructure calculation + std::vector jetConstituents; + std::vector jetReclustered; + JetFinder jetReclusterer; + std::vector energyMotherVec; + std::vector ptLeadingVec; + std::vector ptSubLeadingVec; + std::vector thetaVec; + + // keeping track of the current collision index + // to determine if we need to rebuild the kdTree + // this makes loadorder more robust + int32_t curTrackTreeColIndex = -1; + int32_t curMcParticleTreeColIndex = -1; + void init(InitContext const&) { using o2HistType = HistType; @@ -128,6 +150,11 @@ struct GammaJetTreeProducer { triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + // for substructure calculation + jetReclusterer.isReclustering = true; + jetReclusterer.algorithm = fastjet::JetAlgorithm::cambridge_algorithm; + jetReclusterer.ghostRepeatN = 0; + // create histograms LOG(info) << "Creating histograms"; @@ -223,8 +250,21 @@ struct GammaJetTreeProducer { /// \brief Builds the kd tree for the tracks or mc particles (used for fast isolation calculation) /// \param objects The objects to build the kd tree for (tracks or mc particles) template - void buildKdTree(const T& objects) + void buildKdTree(const auto& collision, const T& objects) { + // check if we need to rebuild the kdTree + if constexpr (std::is_same_v, aod::JetTracks>) { + if (curTrackTreeColIndex == collision.globalIndex()) { + return; + } + curTrackTreeColIndex = collision.globalIndex(); + } else if constexpr (std::is_same_v, aod::JetParticles>) { + if (curMcParticleTreeColIndex == collision.globalIndex()) { + return; + } + curMcParticleTreeColIndex = collision.globalIndex(); + } + trackEta.clear(); trackPhi.clear(); trackPt.clear(); @@ -895,7 +935,7 @@ struct GammaJetTreeProducer { if (collision.posZ() > mVertexCut) { continue; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, true, true, rctLabel)) { continue; } if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { @@ -933,7 +973,7 @@ struct GammaJetTreeProducer { /// \brief Processes data events in data fill event table /// \param collision The collision to process /// \param clusters The EMCAL clusters in the event - void processEventData(soa::Join::iterator const& collision, emcClusters const& clusters) + void processEventData(soa::Join::iterator const& collision, emcClusters const& clusters) { if (!isEventAccepted(collision, clusters)) { return; @@ -950,7 +990,7 @@ struct GammaJetTreeProducer { /// \param collision The collision to process /// \param clusters The EMCAL clusters in the event /// \param mcCollisions The MC collisions collection - void processEventMC(soa::Join::iterator const& collision, emcClusters const& clusters, MCCol const&) + void processEventMC(soa::Join::iterator const& collision, emcClusters const& clusters, MCCol const&) { if (!isEventAccepted(collision, clusters)) { return; @@ -999,7 +1039,7 @@ struct GammaJetTreeProducer { /// \param clusters The EMCAL clusters to process /// \param tracks The tracks collection /// \param emctracks The EMCAL tracks collection from track matching - void processClusters(soa::Join::iterator const& collision, emcClusters const& clusters, aod::JetTracks const& tracks, aod::JEMCTracks const& emctracks) + void processClusters(soa::Join::iterator const& collision, emcClusters const& clusters, aod::JetTracks const& tracks, aod::JEMCTracks const& emctracks) { // event selection int32_t storedColIndex = getStoredColIndex(collision); @@ -1010,7 +1050,7 @@ struct GammaJetTreeProducer { runTrackQA(collision, tracks); // build kd tree for tracks and mc particles - buildKdTree(tracks); + buildKdTree(collision, tracks); // loop over clusters for (const auto& cluster : clusters) { @@ -1059,7 +1099,7 @@ struct GammaJetTreeProducer { /// \param collision The collision to process /// \param mcClusters The MC clusters to process /// \param mcParticles The MC particles collection - void processClustersMCInfo(soa::Join::iterator const& collision, emcMCClusters const& mcClusters, aod::JMcParticles const& mcParticles) + void processClustersMCInfo(soa::Join::iterator const& collision, emcMCClusters const& mcClusters, aod::JMcParticles const& mcParticles) { // event selection int32_t storedColIndex = getStoredColIndex(collision); @@ -1143,20 +1183,85 @@ struct GammaJetTreeProducer { mHistograms.fill(HIST("chjetPt"), jet.pt()); } + /// \brief Fills the substructure table with z and theta values for each splitting in the jet + /// \param jetGlobalIndex The global index of the stored jet in the GjChargedJets table + /// \param jet The jet to process + /// \param tracks The tracks collection + template + void fillSubstructureTable(int32_t storedColIndex, T const& jet, U const& /*tracks*/) + { + // adjust settings according to the jet radius + jetReclusterer.jetR = jet.r() / 100.0; + // clear vectors + energyMotherVec.clear(); + ptLeadingVec.clear(); + ptSubLeadingVec.clear(); + thetaVec.clear(); + jetReclustered.clear(); + jetConstituents.clear(); + + if (jet.pt() < jetPtMin) { + return; + } + for (auto& jetConstituent : jet.template tracks_as()) { + fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); + } + + fastjet::ClusterSequenceArea clusterSeq(jetReclusterer.findJets(jetConstituents, jetReclustered)); + jetReclustered = sorted_by_pt(jetReclustered); + + if (jetReclustered.size() == 0) { + return; + } + + fastjet::PseudoJet daughterSubJet = jetReclustered[0]; + fastjet::PseudoJet parentSubJet1; + fastjet::PseudoJet parentSubJet2; + + // Iterate through the Cambridge/Aachen tree and store all z, theta pairs + while (daughterSubJet.has_parents(parentSubJet1, parentSubJet2)) { + if (parentSubJet1.perp() < parentSubJet2.perp()) { + std::swap(parentSubJet1, parentSubJet2); + } + + energyMotherVec.push_back(daughterSubJet.e()); + ptLeadingVec.push_back(parentSubJet1.pt()); + ptSubLeadingVec.push_back(parentSubJet2.pt()); + thetaVec.push_back(parentSubJet1.delta_R(parentSubJet2)); + + // Continue with harder parent + daughterSubJet = parentSubJet1; + } + + // Fill one row per jet with all splittings stored as vectors + // Pass the jet's global index to associate this substructure entry with the jet + jetSubstructuresTable(storedColIndex, energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec); + } + Filter jetCuts = aod::jet::pt > jetPtMin; /// \brief Processes charged jets and fills jet table /// \param collision The collision to process /// \param chargedJets The charged jets to process /// \param tracks The tracks collection - void processChargedJetsData(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks) + void processChargedJetsData(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks) { // event selection int32_t storedColIndex = getStoredColIndex(collision); if (storedColIndex == -1) return; + + // build kd tree for tracks (needed for perpendicular cone rho calculation) + buildKdTree(collision, tracks); + // loop over charged jets for (const auto& jet : chargedJets) { + // Fill jet table and get the stored jet's global index fillChargedJetTable(storedColIndex, jet, tracks); + + // Fill substructure table if enabled and jet was stored + if (calculateJetSubstructure) { + fillSubstructureTable(storedColIndex, jet, tracks); + } } } PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsData, "Process charged jets", true); @@ -1165,7 +1270,7 @@ struct GammaJetTreeProducer { /// \brief Processes MC particles and fills MC particle table /// \param collision The collision to process /// \param mcgenparticles The MC particles to process - void processMCParticles(soa::Join::iterator const& collision, aod::JetParticles const& mcgenparticles, MCCol const&) + void processMCParticles(soa::Join::iterator const& collision, aod::JetParticles const& mcgenparticles, MCCol const&) { // event selection int32_t storedColIndex = getStoredColIndex(collision); @@ -1180,7 +1285,7 @@ struct GammaJetTreeProducer { auto particlesPerMcCollision = mcgenparticles.sliceBy(ParticlesPerMCCollisions, collision.mcCollisionId()); // build kd tree for mc particles - buildKdTree(particlesPerMcCollision); + buildKdTree(collision, particlesPerMcCollision); // Now we want to store every pi0 and every prompt photon that we find on generator level for (const auto& particle : particlesPerMcCollision) { @@ -1238,13 +1343,14 @@ struct GammaJetTreeProducer { } PROCESS_SWITCH(GammaJetTreeProducer, processMCParticles, "Process MC particles", false); - // NOTE: It is important that this function runs after the processMCParticles function (where the isolation tree is built ) + // NOTE: The KD tree is now built lazily in each function that needs it, so execution order is no longer critical Preslice PJetsPerMCCollisions = aod::jmcparticle::mcCollisionId; /// \brief Processes MC particle level charged jets and fills MC jet table /// \param collision The collision to process /// \param chargedJets The MC particle level charged jets to process + /// \param mcgenparticles The MC particles collection /// \param mcCollisions The MC collisions collection - void processChargedJetsMCP(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, MCCol const&) + void processChargedJetsMCP(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetParticles const& mcgenparticles, MCCol const&) { // event selection int32_t storedColIndex = getStoredColIndex(collision); @@ -1254,6 +1360,11 @@ struct GammaJetTreeProducer { if (!collision.has_mcCollision()) { return; } + + // build kd tree for mc particles (needed for perpendicular cone rho calculation) + auto particlesPerMcCollision = mcgenparticles.sliceBy(ParticlesPerMCCollisions, collision.mcCollisionId()); + buildKdTree(collision, particlesPerMcCollision); + int localIndex = 0; auto pjetsPerMcCollision = chargedJets.sliceBy(PJetsPerMCCollisions, collision.mcCollisionId()); for (const auto& pjet : pjetsPerMcCollision) { @@ -1275,16 +1386,26 @@ struct GammaJetTreeProducer { /// \param chargedJets The MC detector level charged jets to process /// \param tracks The tracks collection /// \param pjets The MC particle level jets collection (just loaded to have subscription to the table) - void processChargedJetsMCD(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks, JetMCPTable const& /*pjets*/) + void processChargedJetsMCD(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks, JetMCPTable const& /*pjets*/) { // event selection int32_t storedColIndex = getStoredColIndex(collision); if (storedColIndex == -1) return; + + // build kd tree for tracks (needed for perpendicular cone rho calculation) + buildKdTree(collision, tracks); + // loop over charged jets for (const auto& jet : chargedJets) { + // Fill jet table and get the stored jet's global index fillChargedJetTable(storedColIndex, jet, tracks); + // Fill substructure table if enabled and jet was stored + if (calculateJetSubstructure) { + fillSubstructureTable(storedColIndex, jet, tracks); + } + // Fill Matching information int iLocalIndexGeo = -1; int iLocalIndexPt = -1; diff --git a/PWGJE/Tasks/hadronPhotonCorrelation.cxx b/PWGJE/Tasks/hadronPhotonCorrelation.cxx index f84d69d621e..7040898d6d1 100644 --- a/PWGJE/Tasks/hadronPhotonCorrelation.cxx +++ b/PWGJE/Tasks/hadronPhotonCorrelation.cxx @@ -26,24 +26,22 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/InitContext.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include -// #include // o2-linter: disable= root/lorentz-vector (TLorentzVector is needed for TPythia8Decayer) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include -// #include -// #include #include #include diff --git a/PWGJE/Tasks/hfDebug.cxx b/PWGJE/Tasks/hfDebug.cxx index 4efaf6ce7c9..f5c96c13337 100644 --- a/PWGJE/Tasks/hfDebug.cxx +++ b/PWGJE/Tasks/hfDebug.cxx @@ -14,28 +14,32 @@ /// \author Nima Zardoshti // -#include "PWGHF/Utils/utilsMcGen.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" +// +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/DerivedTables.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 "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct HFDebugTask { HistogramRegistry registry{"registry", {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}}, diff --git a/PWGJE/Tasks/hfFragmentationFunction.cxx b/PWGJE/Tasks/hfFragmentationFunction.cxx index b3790cda8cd..abcdcdb28b9 100644 --- a/PWGJE/Tasks/hfFragmentationFunction.cxx +++ b/PWGJE/Tasks/hfFragmentationFunction.cxx @@ -17,29 +17,29 @@ /// The task store data relevant to the calculation of hadronization observables radial /// profile and/or jet momentum fraction for charmed hadrons +#include "PWGHF/Core/DecayChannels.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -// -#include "PWGHF/Core/DecayChannels.h" #include "Common/Core/RecoDecay.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include +#include #include +#include #include +#include #include #include #include #include -#include "TVector3.h" #include +#include #include @@ -179,13 +179,17 @@ struct HfFragmentationFunction { Produces matchJetTable; // Tables for MC jet matching - using JetMCDTable = soa::Join; - using JetMCPTable = soa::Join; + using JetD0MCDTable = soa::Join; + using JetD0MCPTable = soa::Join; + using JetLcMCDTable = soa::Join; + using JetLcMCPTable = soa::Join; // slices for accessing proper HF mcdjets collision associated to mccollisions PresliceUnsorted collisionsPerMCCollisionPreslice = aod::jmccollisionlb::mcCollisionId; - Preslice d0MCDJetsPerCollisionPreslice = aod::jet::collisionId; - Preslice d0MCPJetsPerMCCollisionPreslice = aod::jet::mcCollisionId; + Preslice d0MCDJetsPerCollisionPreslice = aod::jet::collisionId; + Preslice d0MCPJetsPerMCCollisionPreslice = aod::jet::mcCollisionId; + Preslice lcMCDJetsPerCollisionPreslice = aod::jet::collisionId; + Preslice lcMCPJetsPerMCCollisionPreslice = aod::jet::mcCollisionId; // Histogram registry: an object to hold your histograms HistogramRegistry registry{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -217,24 +221,25 @@ struct HfFragmentationFunction { jetCounter->GetXaxis()->SetBinLabel(5, "mcd matched to mcp loop"); jetCounter->GetXaxis()->SetBinLabel(6, "mcp matched to mcd loop"); // D0 candidate histograms from data - registry.add("h_d0_jet_projection", ";z^{D^{0},jet}_{||};dN/dz^{D^{0},jet}_{||}", {HistType::kTH1F, {{1000, 0., 10.}}}); - registry.add("h_d0_jet_distance_vs_projection", ";#DeltaR_{D^{0},jet};z^{D^{0},jet}_{||}", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}); - registry.add("h_d0_jet_distance", ";#DeltaR_{D^{0},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 10.}}}); - registry.add("h_d0_jet_pt", ";p_{T,D^{0} jet};dN/dp_{T,D^{0} jet}", {HistType::kTH1F, {{200, 0., 10.}}}); - registry.add("h_d0_jet_eta", ";#eta_{T,D^{0} jet};dN/d#eta_{D^{0} jet}", {HistType::kTH1F, {{250, -5., 5.}}}); - registry.add("h_d0_jet_phi", ";#phi_{T,D^{0} jet};dN/d#phi_{D^{0} jet}", {HistType::kTH1F, {{250, -10., 10.}}}); - registry.add("h_d0_mass", ";m_{D^{0}} (GeV/c^{2});dN/dm_{D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}); - registry.add("h_d0_eta", ";#eta_{D^{0}} (GeV/c^{2});dN/d#eta_{D^{0}}", {HistType::kTH1F, {{250, -5., 5.}}}); - registry.add("h_d0_phi", ";#phi_{D^{0}} (GeV/c^{2});dN/d#phi_{D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}); + registry.add("h_hf_jet_projection", ";z^{HF,jet}_{||};dN/dz^{HF,jet}_{||}", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add("h_hf_jet_distance_vs_projection", ";#DeltaR_{HF,jet};z^{HF,jet}_{||}", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}); + registry.add("h_hf_jet_distance", ";#DeltaR_{HF,jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add("h_hf_jet_pt", ";p_{T,HF jet};dN/dp_{T,HF jet}", {HistType::kTH1F, {{200, 0., 10.}}}); + registry.add("h_hf_jet_eta", ";#eta_{T,HF jet};dN/d#eta_{HF jet}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add("h_hf_jet_phi", ";#phi_{T,HF jet};dN/d#phi_{HF jet}", {HistType::kTH1F, {{250, -10., 10.}}}); + registry.add("h_hf_mass", ";m_{HF} (GeV/c^{2});dN/dm_{HF}", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add("h_hf_eta", ";#eta_{HF} (GeV/c^{2});dN/d#eta_{HF}", {HistType::kTH1F, {{250, -5., 5.}}}); + registry.add("h_hf_phi", ";#phi_{HF} (GeV/c^{2});dN/d#phi_{HF}", {HistType::kTH1F, {{250, -10., 10.}}}); } void processDummy(aod::TracksIU const&) {} PROCESS_SWITCH(HfFragmentationFunction, processDummy, "Dummy process function turned on by default", true); - void processDataChargedSubstructure(aod::JetCollision const& collision, - soa::Join const& jets, - aod::CandidatesD0Data const&, - aod::JetTracks const&) + template + void analyzeData(aod::JetCollision const& collision, + TJets const& jets, + TCandidates const&, + aod::JetTracks const&) { // apply event selection and fill histograms for sanity check registry.fill(HIST("h_collision_counter"), 2.0); @@ -249,45 +254,62 @@ struct HfFragmentationFunction { // obtaining jet 3-vector TVector3 jetVector(jet.px(), jet.py(), jet.pz()); - for (const auto& d0Candidate : jet.candidates_as()) { + for (const auto& candidate : jet.template candidates_as()) { // obtaining jet 3-vector - TVector3 d0Vector(d0Candidate.px(), d0Candidate.py(), d0Candidate.pz()); + TVector3 hadronMomentum(candidate.px(), candidate.py(), candidate.pz()); - // calculating fraction of the jet momentum carried by the D0 along the direction of the jet axis - double zParallel = (jetVector * d0Vector) / (jetVector * jetVector); + // calculating fraction of the jet momentum carried by the HF hadron along the direction of the jet axis + double zParallel = (jetVector * hadronMomentum) / (jetVector * jetVector); // calculating angular distance in eta-phi plane - double axisDistance = jetutilities::deltaR(jet, d0Candidate); + double axisDistance = jetutilities::deltaR(jet, candidate); // filling histograms - registry.fill(HIST("h_d0_jet_projection"), zParallel); - registry.fill(HIST("h_d0_jet_distance_vs_projection"), axisDistance, zParallel); - registry.fill(HIST("h_d0_jet_distance"), axisDistance); - registry.fill(HIST("h_d0_jet_pt"), jet.pt()); - registry.fill(HIST("h_d0_jet_eta"), jet.eta()); - registry.fill(HIST("h_d0_jet_phi"), jet.phi()); - registry.fill(HIST("h_d0_mass"), d0Candidate.m()); - registry.fill(HIST("h_d0_eta"), d0Candidate.eta()); - registry.fill(HIST("h_d0_phi"), d0Candidate.phi()); + registry.fill(HIST("h_hf_jet_projection"), zParallel); + registry.fill(HIST("h_hf_jet_distance_vs_projection"), axisDistance, zParallel); + registry.fill(HIST("h_hf_jet_distance"), axisDistance); + registry.fill(HIST("h_hf_jet_pt"), jet.pt()); + registry.fill(HIST("h_hf_jet_eta"), jet.eta()); + registry.fill(HIST("h_hf_jet_phi"), jet.phi()); + registry.fill(HIST("h_hf_mass"), candidate.m()); + registry.fill(HIST("h_hf_eta"), candidate.eta()); + registry.fill(HIST("h_hf_phi"), candidate.phi()); // filling table distJetTable(axisDistance, - jet.pt(), jet.eta(), jet.phi(), jet.tracks_as().size(), - d0Candidate.pt(), d0Candidate.eta(), d0Candidate.phi(), d0Candidate.m(), d0Candidate.y(), d0Candidate.mlScores()[0], d0Candidate.mlScores()[1], d0Candidate.mlScores()[2]); + jet.pt(), jet.eta(), jet.phi(), jet.template tracks_as().size() + jet.template candidates_as().size(), + candidate.pt(), candidate.eta(), candidate.phi(), candidate.m(), candidate.y(), candidate.mlScores()[0], candidate.mlScores()[1], candidate.mlScores()[2]); break; // get out of candidates' loop after first HF particle is found in jet - } // end of D0 candidates loop + } // end of HF hadron candidates loop } // end of jets loop - } // end of process function - PROCESS_SWITCH(HfFragmentationFunction, processDataChargedSubstructure, "charged HF jet substructure", false); + } // end of analyzeData function + + void processD0DataCharged(aod::JetCollision const& collision, + soa::Join const& jets, + aod::CandidatesD0Data const& candidates, + aod::JetTracks const& jettracks) + { + analyzeData, aod::CandidatesD0Data>(collision, jets, candidates, jettracks); + } + PROCESS_SWITCH(HfFragmentationFunction, processD0DataCharged, "Store kinematic charged D0 jet information from measured DATA", false); + + void processLcDataCharged(aod::JetCollision const& collision, + soa::Join const& jets, + aod::CandidatesLcData const& candidates, + aod::JetTracks const& jettracks) + { + analyzeData, aod::CandidatesLcData>(collision, jets, candidates, jettracks); + } + PROCESS_SWITCH(HfFragmentationFunction, processLcDataCharged, "Store kinematic charged Lc jet information from measured DATA", false); void processMcEfficiency(aod::JetMcCollisions const& mccollisions, aod::JetCollisionsMCD const& collisions, - JetMCDTable const& mcdjets, - JetMCPTable const& mcpjets, + JetD0MCDTable const& mcdjets, + JetD0MCPTable const& mcpjets, aod::CandidatesD0MCD const&, aod::CandidatesD0MCP const&, aod::JetTracks const&, @@ -297,7 +319,7 @@ struct HfFragmentationFunction { registry.fill(HIST("h_collision_counter"), 0.0); // skip collisions outside of |z| < vertexZCut - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mccollision, eventSelectionBits) || !(std::abs(mccollision.posZ()) < vertexZCut)) { continue; } registry.fill(HIST("h_collision_counter"), 1.0); @@ -344,7 +366,7 @@ struct HfFragmentationFunction { // store data in MC detector level table mcddistJetTable(jetutilities::deltaR(mcdjet, mcdd0cand), - mcdjet.pt(), mcdjet.eta(), mcdjet.phi(), mcdjet.tracks_as().size(), // detector level jet + mcdjet.pt(), mcdjet.eta(), mcdjet.phi(), mcdjet.tracks_as().size() + mcdjet.candidates_as().size(), // detector level jet mcdd0cand.pt(), mcdd0cand.eta(), mcdd0cand.phi(), mcdd0cand.m(), mcdd0cand.y(), (mcdd0cand.originMcRec() == RecoDecay::OriginType::Prompt), // detector level D0 candidate mcdjet.has_matchedJetCand(), mcdd0cand.mlScores()[0], mcdd0cand.mlScores()[1], mcdd0cand.mlScores()[2], // // Machine Learning PID scores: background, prompt, non-prompt matchedFrom, selectedAs); // D0 = +1, D0bar = -1, neither = 0 @@ -366,94 +388,128 @@ struct HfFragmentationFunction { // store data in MC detector level table (calculate angular distance in eta-phi plane on the fly) mcpdistJetTable(jetutilities::deltaR(mcpjet, mcpd0cand), - mcpjet.pt(), mcpjet.eta(), mcpjet.phi(), mcpjet.tracks_as().size(), // particle level jet - mcpd0cand.pt(), mcpd0cand.eta(), mcpd0cand.phi(), mcpd0cand.y(), (mcpd0cand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level D0 + mcpjet.pt(), mcpjet.eta(), mcpjet.phi(), mcpjet.tracks_as().size() + mcpjet.candidates_as().size(), // particle level jet + mcpd0cand.pt(), mcpd0cand.eta(), mcpd0cand.phi(), mcpd0cand.y(), (mcpd0cand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level D0 mcpjet.has_matchedJetCand()); } } } PROCESS_SWITCH(HfFragmentationFunction, processMcEfficiency, "non-matched and matched MC HF and jets", false); - void processMcChargedMatched(aod::JetMcCollisions const& mccollisions, - aod::JetCollisionsMCD const& collisions, - JetMCDTable const& mcdjets, - JetMCPTable const&, - aod::CandidatesD0MCD const&, - aod::CandidatesD0MCP const&, - aod::JetTracks const&, - aod::JetParticles const&) + template + void analyzeMC(TMCPJetsPerMCCollisionPreslice const& MCPJetsPerMCCollisionPreslice, + aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + TJetsMCD const&, + TJetsMCP const& mcpjets, + TCandidatesMCD const&, + TCandidatesMCP const&, + aod::JetTracks const&, + aod::JetParticles const&) { for (const auto& mccollision : mccollisions) { - registry.fill(HIST("h_collision_counter"), 0.0); - // skip collisions outside of |z| < vertexZCut - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(mccollision, eventSelectionBits) || !(std::abs(mccollision.posZ()) < vertexZCut)) { continue; } registry.fill(HIST("h_collision_counter"), 1.0); - // reconstructed collisions associated to same mccollision - const auto collisionsPerMCCollision = collisions.sliceBy(collisionsPerMCCollisionPreslice, mccollision.globalIndex()); - for (const auto& collision : collisionsPerMCCollision) { - - registry.fill(HIST("h_collision_counter"), 2.0); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { - continue; - } - registry.fill(HIST("h_collision_counter"), 3.0); - // d0 detector level jets associated to the current same collision - const auto d0mcdJetsPerCollision = mcdjets.sliceBy(d0MCDJetsPerCollisionPreslice, collision.globalIndex()); - for (const auto& mcdjet : d0mcdJetsPerCollision) { - - registry.fill(HIST("h_jet_counter"), 0.5); - - // comparison with fill on bin on 2.5 for sanity check - if (mcdjet.has_matchedJetCand()) { - registry.fill(HIST("h_jet_counter"), 1.5); - } + // hf particle level jets associated to same mccollision + const auto mcpJetsPerMCCollision = mcpjets.sliceBy(MCPJetsPerMCCollisionPreslice, mccollision.globalIndex()); + for (const auto& mcpjet : mcpJetsPerMCCollision) { - // obtain leading HF candidate in jet - auto mcdd0cand = mcdjet.candidates_first_as(); + registry.fill(HIST("h_jet_counter"), 0.0); - // reflection information for storage: D0 = +1, D0bar = -1, neither = 0 - int matchedFrom = 0; - int decayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; - int selectedAs = 0; + // obtain leading HF particle in jet + auto mcpcand = mcpjet.template candidates_first_as(); - if (mcdd0cand.flagMcMatchRec() == decayChannel) { // matched to D0 on truth level - matchedFrom = 1; - } else if (mcdd0cand.flagMcMatchRec() == -decayChannel) { // matched to D0bar on truth level - matchedFrom = -1; - } - // bitwise AND operation: Checks whether BIT(i) is set, regardless of other bits - if (mcdd0cand.candidateSelFlag() & BIT(0)) { // CandidateSelFlag == BIT(0) -> selected as D0 - selectedAs = 1; - } else if (mcdd0cand.candidateSelFlag() & BIT(1)) { // CandidateSelFlag == BIT(1) -> selected as D0bar - selectedAs = -1; - } + if (mcpjet.has_matchedJetCand()) { + registry.fill(HIST("h_jet_counter"), 1.0); - // loop through detector level matched to current particle level - for (const auto& mcpjet : mcdjet.matchedJetCand_as()) { + // loop over detector level matched to current particle level + for (const auto& mcdjet : mcpjet.template matchedJetCand_as()) { + registry.fill(HIST("h_jet_counter"), 2.0); - registry.fill(HIST("h_jet_counter"), 2.5); + // apply collision sel8 selection on detector level jet's collision + const auto& collision = collisions.iteratorAt(mcdjet.collisionId()); + registry.fill(HIST("h_collision_counter"), 2.0); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { + continue; + } + registry.fill(HIST("h_collision_counter"), 3.0); // obtain leading HF candidate in jet - auto mcpd0cand = mcpjet.candidates_first_as(); + auto mcdcand = mcdjet.template candidates_first_as(); + + // reflection information for storage: HF = +1, HFbar = -1, neither = 0 + int matchedFrom = 0; + int decayChannel = 0; + if (jethfutilities::isD0Table()) { + decayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; + } else if (jethfutilities::isLcTable()) { + decayChannel = o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; + } + int selectedAs = 0; + + if (mcdcand.flagMcMatchRec() == decayChannel) { // matched to HF on truth level + matchedFrom = 1; + } else if (mcdcand.flagMcMatchRec() == -decayChannel) { // matched to HFbar on truth level + matchedFrom = -1; + } + // bitwise AND operation: Checks whether BIT(i) is set, regardless of other bits + if (mcdcand.candidateSelFlag() & BIT(0)) { // CandidateSelFlag == BIT(0) -> selected as HF + selectedAs = 1; + } else if (mcdcand.candidateSelFlag() & BIT(1)) { // CandidateSelFlag == BIT(1) -> selected as HFbar + selectedAs = -1; + } // store matched particle and detector level data in one single table (calculate angular distance in eta-phi plane on the fly) - matchJetTable(jetutilities::deltaR(mcpjet, mcpd0cand), mcpjet.pt(), mcpjet.eta(), mcpjet.phi(), mcpjet.tracks_as().size(), // particle level jet - mcpd0cand.pt(), mcpd0cand.eta(), mcpd0cand.phi(), mcpd0cand.y(), (mcpd0cand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level D0 - jetutilities::deltaR(mcdjet, mcdd0cand), mcdjet.pt(), mcdjet.eta(), mcdjet.phi(), mcdjet.tracks_as().size(), // detector level jet - mcdd0cand.pt(), mcdd0cand.eta(), mcdd0cand.phi(), mcdd0cand.m(), mcdd0cand.y(), (mcdd0cand.originMcRec() == RecoDecay::OriginType::Prompt), // detector level D0 - mcdd0cand.mlScores()[0], mcdd0cand.mlScores()[1], mcdd0cand.mlScores()[2], // Machine Learning PID scores: background, prompt, non-prompt - matchedFrom, selectedAs); // D0 = +1, D0bar = -1, neither = 0 + matchJetTable(jetutilities::deltaR(mcpjet, mcpcand), mcpjet.pt(), mcpjet.eta(), mcpjet.phi(), mcpjet.template tracks_as().size() + mcpjet.template candidates_as().size(), // particle level jet + mcpcand.pt(), mcpcand.eta(), mcpcand.phi(), mcpcand.y(), (mcpcand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level HF + jetutilities::deltaR(mcdjet, mcdcand), mcdjet.pt(), mcdjet.eta(), mcdjet.phi(), mcdjet.template tracks_as().size() + +mcdjet.template candidates_as().size(), // detector level jet + mcdcand.pt(), mcdcand.eta(), mcdcand.phi(), mcdcand.m(), mcdcand.y(), (mcdcand.originMcRec() == RecoDecay::OriginType::Prompt), // detector level HF + mcdcand.mlScores()[0], mcdcand.mlScores()[1], mcdcand.mlScores()[2], // Machine Learning PID scores: background, prompt, non-prompt + matchedFrom, selectedAs); // HF = +1, HFbar = -1, neither = 0 } + } else { + // store matched particle and detector level data in one single table (calculate angular distance in eta-phi plane on the fly) + matchJetTable(jetutilities::deltaR(mcpjet, mcpcand), mcpjet.pt(), mcpjet.eta(), mcpjet.phi(), mcpjet.template tracks_as().size() + +mcpjet.template candidates_as().size(), // particle level jet + mcpcand.pt(), mcpcand.eta(), mcpcand.phi(), mcpcand.y(), (mcpcand.originMcGen() == RecoDecay::OriginType::Prompt), // particle level HF + -2, -2, -2, -2, -2, // detector level jet + -2, -2, -2, -2, -2, -2, // detector level HF + -2, -2, -2, // Machine Learning PID scores: background, prompt, non-prompt + -2, -2); // HF = +1, HFbar = -1, neither = 0 } - } - } + } // end of mcpjets loop + } // end of mccollisions loop + } // end of analyzeMC function + + void processD0MC(aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + JetD0MCDTable const& mcdjets, + JetD0MCPTable const& mcpjets, + aod::CandidatesD0MCD const& mcdcands, + aod::CandidatesD0MCP const& mcpcands, + aod::JetTracks const& jettracks, + aod::JetParticles const& jetparticles) + { + analyzeMC, JetD0MCDTable, JetD0MCPTable, aod::CandidatesD0MCD, aod::CandidatesD0MCP>(d0MCPJetsPerMCCollisionPreslice, mccollisions, collisions, mcdjets, mcpjets, mcdcands, mcpcands, jettracks, jetparticles); + } + PROCESS_SWITCH(HfFragmentationFunction, processD0MC, "Store all simulated D0 jets information with matched candidate (if any found)", false); + + void processLcMC(aod::JetMcCollisions const& mccollisions, + aod::JetCollisionsMCD const& collisions, + JetLcMCDTable const& mcdjets, + JetLcMCPTable const& mcpjets, + aod::CandidatesLcMCD const& mcdcands, + aod::CandidatesLcMCP const& mcpcands, + aod::JetTracks const& jettracks, + aod::JetParticles const& jetparticles) + { + analyzeMC, JetLcMCDTable, JetLcMCPTable, aod::CandidatesLcMCD, aod::CandidatesLcMCP>(lcMCPJetsPerMCCollisionPreslice, mccollisions, collisions, mcdjets, mcpjets, mcdcands, mcpcands, jettracks, jetparticles); } - PROCESS_SWITCH(HfFragmentationFunction, processMcChargedMatched, "matched MC HF and jets", false); + PROCESS_SWITCH(HfFragmentationFunction, processLcMC, "Store all simulated Lc jets information with matched candidate (if any found)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetBackgroundAnalysis.cxx b/PWGJE/Tasks/jetBackgroundAnalysis.cxx index 2272456e8b4..f7a0c56c7ac 100644 --- a/PWGJE/Tasks/jetBackgroundAnalysis.cxx +++ b/PWGJE/Tasks/jetBackgroundAnalysis.cxx @@ -22,6 +22,7 @@ #include "Common/Core/RecoDecay.h" +#include #include #include #include @@ -30,7 +31,6 @@ #include #include -#include #include #include @@ -71,12 +71,14 @@ struct JetBackgroundAnalysisTask { std::vector eventSelectionBits; int trackSelection = -1; + TRandom3 randomNumber{}; void init(o2::framework::InitContext&) { // selection settings initialisation eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + randomNumber.SetSeed(0); // Axes definitions AxisSpec bkgFluctuationsAxis = {nBinsFluct, -100.0, 100.0, "#delta #it{p}_{T} (GeV/#it{c})"}; @@ -117,7 +119,6 @@ struct JetBackgroundAnalysisTask { template void bkgFluctuationsRandomCone(TCollisions const& collision, TJets const& jets, TTracks const& tracks, float centrality) { - TRandom3 randomNumber(0); float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); float randomConePt = 0; @@ -133,20 +134,23 @@ struct JetBackgroundAnalysisTask { registry.fill(HIST("h2_centrality_rhorandomcone"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles - randomConePt = 0; + float randomConePtRandomTrackDirection = 0; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, o2::constants::math::TwoPI) - randomConePhi, static_cast(-o2::constants::math::PI)); // ignores actual phi of track float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); + randomConePtRandomTrackDirection += track.pt(); } } } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), centrality, randomConePtRandomTrackDirection - o2::constants::math::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 + const bool hasLead = jets.size() >= 1; + const bool hasSub = jets.size() >= 2; + float randomConePtWithoutLeadingJet = randomConePt; + if (hasLead) { float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; @@ -159,32 +163,36 @@ struct JetBackgroundAnalysisTask { dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; } if (jetWasInCone) { - randomConePt = 0.0; + randomConePtWithoutLeadingJet = 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(-o2::constants::math::PI)); float dEta = track.eta() - randomConeEta; if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - randomConePt += track.pt(); + randomConePtWithoutLeadingJet += track.pt(); } } } } } - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), centrality, randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), centrality, randomConePtWithoutLeadingJet - o2::constants::math::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; - if (jets.size() > 1) { // if there are no jets, or just one, in the acceptance (from the jetfinder cuts) then one cannot find 2 leading jets + double randomConePtWithoutOneLeadJet = randomConePtRandomTrackDirection; + double randomConePtWithoutTwoLeadJet = randomConePtRandomTrackDirection; + if (hasLead) { + randomConePtWithoutOneLeadJet = 0.0; + randomConePtWithoutTwoLeadJet = 0.0; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { float dPhi = RecoDecay::constrainAngle(randomNumber.Uniform(0.0, o2::constants::math::TwoPI) - randomConePhi, static_cast(-o2::constants::math::PI)); // ignores actual phi of track float dEta = randomNumber.Uniform(trackEtaMin, trackEtaMax) - randomConeEta; // ignores actual eta of track if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { - if (!trackIsInJet(track, jets.iteratorAt(0))) { + const bool inLead = hasLead && trackIsInJet(track, jets.iteratorAt(0)); + const bool inSub = hasSub && trackIsInJet(track, jets.iteratorAt(1)); + if (!inLead) { randomConePtWithoutOneLeadJet += track.pt(); - if (!trackIsInJet(track, jets.iteratorAt(1))) { + if (!hasSub || !inSub) { randomConePtWithoutTwoLeadJet += track.pt(); } } diff --git a/PWGJE/Tasks/jetChCorr.cxx b/PWGJE/Tasks/jetChCorr.cxx index e9a4a937334..be4fcf59b0b 100644 --- a/PWGJE/Tasks/jetChCorr.cxx +++ b/PWGJE/Tasks/jetChCorr.cxx @@ -19,36 +19,32 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/PseudoJet.hh" +#include #include +#include #include #include #include -// #include "PWGLF/DataModel/LFResonanceTables.h" - -#include -#include -#include -#include -#include - using namespace std; using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; int trackSelection = -1; int trackL = -1; @@ -419,7 +415,7 @@ struct JetChCorr { { jetConstituents.clear(); for (auto& jetConstituent : jet.template tracks_as()) { - fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), pdg->Mass(jetConstituent.pdgCode())); + fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), JetConstituentStatus::track, pdg->Mass(jetConstituent.pdgCode())); } jetReclustering(jet); } diff --git a/PWGJE/Tasks/jetChargedV2.cxx b/PWGJE/Tasks/jetChargedV2.cxx index f33874ca55d..2dbdb7e5206 100644 --- a/PWGJE/Tasks/jetChargedV2.cxx +++ b/PWGJE/Tasks/jetChargedV2.cxx @@ -13,44 +13,39 @@ /// \file jetChargedV2.cxx /// \brief This file contains the implementation for the Charged Jet v2 analysis in the ALICE experiment -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/EventPlaneHelper.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Qvectors.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "EventFiltering/filterTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" - -#include -#include -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -#include #include #include -#include +#include + +#include #include -#include #include #include +#include #include using namespace o2; diff --git a/PWGJE/Tasks/jetCorrelationD0.cxx b/PWGJE/Tasks/jetCorrelationD0.cxx new file mode 100644 index 00000000000..bba4f0273aa --- /dev/null +++ b/PWGJE/Tasks/jetCorrelationD0.cxx @@ -0,0 +1,438 @@ +// 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 jetCorrelationD0.cxx +/// \brief Task for analysing D0 triggered jet events. +/// \author Matthew Ockleton matthew.ockleton@cern.ch, University of Liverpool + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/Logger.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ + +namespace d0collisionInfo +{ +DECLARE_SOA_COLUMN(PosZ, posZ, float); +} // namespace d0collisionInfo + +DECLARE_SOA_TABLE(CollisionTables, "AOD", "COLLINFOTABLE", + o2::soa::Index<>, + d0collisionInfo::PosZ); + +DECLARE_SOA_TABLE(McCollisionTables, "AOD", "MCCOLLINFOTABLE", + o2::soa::Index<>, + d0collisionInfo::PosZ); + +DECLARE_SOA_TABLE(MatchCollTables, "AOD", "MATCHCOLLTABLE", + o2::soa::Index<>, + d0collisionInfo::PosZ); + +namespace collisionInfo +{ +DECLARE_SOA_INDEX_COLUMN_CUSTOM(CollisionTable, collisionTable, "COLLINFOTABLES"); +DECLARE_SOA_INDEX_COLUMN_CUSTOM(McCollisionTable, mcCollisionTable, "MCCOLLINFOTABLES"); +DECLARE_SOA_INDEX_COLUMN_CUSTOM(MatchCollTable, matchCollTable, "MATCHCOLLTABLES"); +} // namespace collisionInfo +namespace d0Info +{ +// D0 +DECLARE_SOA_COLUMN(D0PromptBDT, d0PromptBDT, float); +DECLARE_SOA_COLUMN(D0NonPromptBDT, d0NonPromptBDT, float); +DECLARE_SOA_COLUMN(D0BkgBDT, d0BkgBDT, float); +DECLARE_SOA_COLUMN(D0M, d0M, float); +DECLARE_SOA_COLUMN(D0Pt, d0Pt, float); +DECLARE_SOA_COLUMN(D0Eta, d0Eta, float); +DECLARE_SOA_COLUMN(D0Phi, d0Phi, float); +DECLARE_SOA_COLUMN(D0Y, d0Y, float); +DECLARE_SOA_COLUMN(D0McOrigin, d0McOrigin, float); +DECLARE_SOA_COLUMN(D0MD, d0MD, float); +DECLARE_SOA_COLUMN(D0PtD, d0PtD, float); +DECLARE_SOA_COLUMN(D0EtaD, d0EtaD, float); +DECLARE_SOA_COLUMN(D0PhiD, d0PhiD, float); +DECLARE_SOA_COLUMN(D0Reflection, d0Reflection, int); +} // namespace d0Info + +DECLARE_SOA_TABLE(D0DataTables, "AOD", "D0TABLE", + o2::soa::Index<>, + collisionInfo::CollisionTableId, + d0Info::D0PromptBDT, + d0Info::D0NonPromptBDT, + d0Info::D0BkgBDT, + d0Info::D0M, + d0Info::D0Pt, + d0Info::D0Eta, + d0Info::D0Phi, + d0Info::D0Y); + +DECLARE_SOA_TABLE(D0McPTables, "AOD", "D0MCPTABLE", + o2::soa::Index<>, + collisionInfo::McCollisionTableId, + d0Info::D0McOrigin, + d0Info::D0Pt, + d0Info::D0Eta, + d0Info::D0Phi, + d0Info::D0Y); + +namespace jetInfo +{ +// D0 tables +DECLARE_SOA_INDEX_COLUMN(D0DataTable, d0DataTable); +DECLARE_SOA_INDEX_COLUMN(D0McPTable, d0McPTable); +// Jet +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +DECLARE_SOA_COLUMN(PJetPt, pJetPt, float); +DECLARE_SOA_COLUMN(PJetEta, pJetEta, float); +DECLARE_SOA_COLUMN(PJetPhi, pJetPhi, float); +// D0-jet +DECLARE_SOA_COLUMN(D0JetDeltaPhi, d0JetDeltaPhi, float); +DECLARE_SOA_COLUMN(D0JetDeltaPhiP, d0JetDeltaPhiP, float); +} // namespace jetInfo + +DECLARE_SOA_TABLE_STAGED(JetDataTables, "JETTABLE", + o2::soa::Index<>, + collisionInfo::CollisionTableId, + jetInfo::D0DataTableId, + jetInfo::JetPt, + jetInfo::JetEta, + jetInfo::JetPhi, + jetInfo::D0JetDeltaPhi); + +DECLARE_SOA_TABLE_STAGED(JetMcPTables, "JETMCPTABLE", + o2::soa::Index<>, + collisionInfo::McCollisionTableId, + jetInfo::D0McPTableId, + jetInfo::JetPt, + jetInfo::JetEta, + jetInfo::JetPhi, + jetInfo::D0JetDeltaPhiP); + +DECLARE_SOA_TABLE_STAGED(JetMatchedTables, "JETMATCHEDTABLE", + o2::soa::Index<>, + collisionInfo::MatchCollTableId, + jetInfo::JetPt, + jetInfo::JetEta, + jetInfo::JetPhi, + jetInfo::PJetPt, + jetInfo::PJetEta, + jetInfo::PJetPhi, + jetInfo::D0JetDeltaPhi, + jetInfo::D0JetDeltaPhiP); + +} // namespace o2::aod + +struct JetCorrelationD0 { + // Define new table + Produces tableCollision; + Produces tableMatchedCollision; + Produces tableMcCollision; + Produces tableD0; + Produces tableD0McParticle; + Produces tableJet; + Produces tableJetMcParticle; + Produces tableJetMatched; + + // Configurables + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable skipMBGapEvents{"skipMBGapEvents", false, "decide to run over MB gap events or not"}; + Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; + Configurable jetPtCutMin{"jetPtCutMin", 5.0, "minimum value of jet pt"}; + Configurable d0PtCutMin{"d0PtCutMin", 1.0, "minimum value of d0 pt"}; + Configurable jetMcPtCutMin{"jetMcPtCutMin", 3.0, "minimum value of jet pt particle level"}; + Configurable d0McPtCutMin{"d0McPtCutMin", 0.5, "minimum value of d0 pt particle level"}; + Configurable vertexZCut{"vertexZCut", 10.0, "Accepted z-vertex range"}; + 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"}; + Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value of pTHat"}; + + // Filters + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut); + std::vector eventSelectionBits; + + // Histograms + HistogramRegistry registry{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + template + void fillD0Histograms(T const& d0, U const& scores) + { + registry.fill(HIST("hD0MlBkg"), scores[0]); + registry.fill(HIST("hD0MlNonPrompt"), scores[1]); + registry.fill(HIST("hD0MlPrompt"), scores[2]); + + registry.fill(HIST("hD0Pt"), d0.pt()); + registry.fill(HIST("hD0M"), d0.m()); + registry.fill(HIST("hD0Eta"), d0.eta()); + registry.fill(HIST("hD0Phi"), d0.phi()); + } + template + void fillJetHistograms(T const& jet, U const& dPhi) + { + registry.fill(HIST("hJetPt"), jet.pt()); + registry.fill(HIST("hJetEta"), jet.eta()); + registry.fill(HIST("hJetPhi"), jet.phi()); + registry.fill(HIST("hJet3D"), jet.pt(), jet.eta(), jet.phi()); + registry.fill(HIST("h_Jet_D0_Jet_dPhi"), dPhi); + registry.fill(HIST("h_Jet_pT_D0_Jet_dPhi"), jet.pt(), dPhi); + } + + template + bool applyCollisionSelections(T const& collision) + { + registry.fill(HIST("hCollisions"), 0.5); // All collisions + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + return false; + } + registry.fill(HIST("hCollisions"), 1.5); // Selected collisions + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + return true; + } + void init(InitContext const&) + { + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + // General Axes + AxisSpec axisEta = {100, -1.0, 1.0, "#eta"}; + AxisSpec axisPhi = {100, 0.0, o2::constants::math::TwoPI, "#phi"}; + AxisSpec axisInvMass = {500, 0, 10, "M (GeV/c)"}; + + // General Histograms + registry.add("hCollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("hZvtxSelected", "Z vertex position;Z_{vtx};entries", {HistType::kTH1F, {{80, -20, 20}}}); + + // D0 Histograms + registry.add("hD0MlPrompt", "D0 ML Prompt Scores", {HistType::kTH1F, {{100, -1.0, 2.0}}}); + registry.add("hD0MlNonPrompt", "D0 ML NonPrompt Scores", {HistType::kTH1F, {{100, -1.0, 2.0}}}); + registry.add("hD0MlBkg", "D0 ML Background Scores", {HistType::kTH1F, {{100, -1.0, 2.0}}}); + + registry.add("hD0Pt", "D^{0} p_{T};p_{T}^{D^{0}} (GeV/c);entries", {HistType::kTH1F, {{500, -100, 400, "p_{T}^{D^{0}} (GeV/c)"}}}); + registry.add("hD0M", "D^{0} Mass;M_{#pi K} (GeV/c);entries", HistType::kTH1F, {axisInvMass}); + registry.add("hD0Eta", "D^{0} #eta ;#eta_{D^{0}};entries", HistType::kTH1F, {axisEta}); + registry.add("hD0Phi", "D^{0} #phi ;#phi_{D^{0}};entries", HistType::kTH1F, {axisPhi}); + + // Jet Histograms + registry.add("hJetPt", "jet p_{T};p_{T,jet};entries", {HistType::kTH1F, {{500, -100, 400}}}); + registry.add("hJetEta", "jet #eta;#eta_{jet};entries", HistType::kTH1F, {axisEta}); + registry.add("hJetPhi", "jet #phi;#phi_{jet};entries", HistType::kTH1F, {axisPhi}); + registry.add("hJet3D", "3D jet distribution;p_{T};#eta;#phi", {HistType::kTH3F, {{500, -100, 400}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}); + registry.add("h_Jet_D0_Jet_dPhi", "#Delta #phi _{D^{0}, jet}", kTH1F, {{100, 0, o2::constants::math::TwoPI}}); + registry.add("h_Jet_pT_D0_Jet_dPhi", "p_{T, jet} vs #Delta #phi _{D^{0}, jet}", kTH2F, {{100, 0, 100}, {100, 0, o2::constants::math::TwoPI}}); + + // Matching histograms + registry.add("hPtMatched", "p_{T} matching;p_{T,det};p_{T,part}", {HistType::kTH2F, {{500, -100, 400}, {400, 0, 400}}}); + registry.add("hPtMatched1d", "p_{T} matching 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}); + registry.add("hPhiMatched", "#phi matching;#phi_{det};#phi_{part}", {HistType::kTH2F, {{100, 0.0, o2::constants::math::TwoPI}, {100, 0.0, o2::constants::math::TwoPI}}}); + registry.add("hEtaMatched", "#eta matching;#eta_{det};#eta_{part}", {HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}}); + registry.add("hPtResolution", "p_{T} resolution;p_{T,part};Relative Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -5.0, 5.0}}}); + registry.add("hPhiResolution", "#phi resolution;#p_{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -7.0, 7.0}}}); + registry.add("hEtaResolution", "#eta resolution;#p_{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -1.0, 1.0}}}); + } + void processData(soa::Filtered::iterator const& collision, + aod::CandidatesD0Data const& d0Candidates, + soa::Join const& jets) + { + if (!applyCollisionSelections(collision)) { + return; + } + tableCollision(collision.posZ()); + for (const auto& d0Candidate : d0Candidates) { + if (d0Candidate.pt() < d0PtCutMin) { // once settled on a mlcut, then add the lower bound of the systematics as a cut here + continue; + } + const auto scores = d0Candidate.mlScores(); + fillD0Histograms(d0Candidate, scores); + tableD0(tableCollision.lastIndex(), + scores[2], + scores[1], + scores[0], + d0Candidate.m(), + d0Candidate.pt(), + d0Candidate.eta(), + d0Candidate.phi(), + d0Candidate.y()); + for (const auto& jet : jets) { + if (jet.pt() < jetPtCutMin) { + continue; + } + float dPhi = RecoDecay::constrainAngle(jet.phi() - d0Candidate.phi(), -o2::constants::math::PI); + if (std::abs(dPhi - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { + continue; + } + fillJetHistograms(jet, dPhi); + tableJet(tableCollision.lastIndex(), + tableD0.lastIndex(), + jet.pt(), + jet.eta(), + jet.phi(), + dPhi); + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processData, "charged particle level jet analysis", true); + + void processMcDetector(soa::Filtered::iterator const& collision, + aod::CandidatesD0MCD const& d0Candidates, + soa::Join const& jets) + { + if (!applyCollisionSelections(collision)) { + return; + } + tableCollision(collision.posZ()); + for (const auto& d0Candidate : d0Candidates) { + if (d0Candidate.pt() < d0PtCutMin) { // once settled on a mlcut, then add the lower biund of the systematics as a cut here + continue; + } + const auto scores = d0Candidate.mlScores(); + fillD0Histograms(d0Candidate, scores); + tableD0(tableCollision.lastIndex(), // might want to add some more detector level D0 quantities like prompt or non prompt info + scores[2], + scores[1], + scores[0], + d0Candidate.m(), + d0Candidate.pt(), + d0Candidate.eta(), + d0Candidate.phi(), + d0Candidate.y()); + for (const auto& jet : jets) { + if (jet.pt() < jetPtCutMin) { + continue; + } + float dPhi = RecoDecay::constrainAngle(jet.phi() - d0Candidate.phi(), -o2::constants::math::PI); + if (std::abs(dPhi - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { + continue; + } + fillJetHistograms(jet, dPhi); + tableJet(tableCollision.lastIndex(), + tableD0.lastIndex(), + jet.pt(), + jet.eta(), + jet.phi(), + dPhi); + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processMcDetector, "charged detector level jet analysis", false); + + void processMcParticle(aod::JetMcCollision const& collision, + aod::CandidatesD0MCP const& d0McPCandidates, + soa::Join const& jets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + return; + } + tableMcCollision(collision.posZ()); + for (const auto& d0McPCandidate : d0McPCandidates) { + if (d0McPCandidate.pt() < d0McPtCutMin) { + continue; + } + tableD0McParticle(tableMcCollision.lastIndex(), + d0McPCandidate.originMcGen(), + d0McPCandidate.pt(), + d0McPCandidate.eta(), + d0McPCandidate.phi(), + d0McPCandidate.y()); + + for (const auto& jet : jets) { + if (jet.pt() < jetMcPtCutMin) { + continue; + } + float dPhi = RecoDecay::constrainAngle(jet.phi() - d0McPCandidate.phi(), -o2::constants::math::PI); + if (std::abs(dPhi - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { + continue; + } + fillJetHistograms(jet, dPhi); + tableJetMcParticle(tableMcCollision.lastIndex(), + tableD0McParticle.lastIndex(), + jet.pt(), + jet.eta(), + jet.phi(), + dPhi); + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processMcParticle, "charged MC Particle jets", false); + + void processMcMatched(soa::Filtered::iterator const& collision, + aod::CandidatesD0MCD const& d0Candidates, + aod::JetTracksMCD const& tracks, + aod::JetParticles const& particles, + soa::Join const& McDJets, + aod::ChargedMCParticleLevelJets const&) + { + if (!applyCollisionSelections(collision)) { + return; + } + tableMatchedCollision(collision.posZ()); + for (const auto& d0Candidate : d0Candidates) { + if (d0Candidate.pt() < d0PtCutMin) { // once settled on a mlcut, then add the lower bound of the systematics as a cut here + continue; + } + bool isMatched = false; + const auto& d0Particle = jethfutilities::matchedHFParticle(d0Candidate, tracks, particles, isMatched); + if (!isMatched) { + continue; + } + for (const auto& McDJet : McDJets) { + if (McDJet.pt() < jetPtCutMin) { + continue; + } + float dPhiD = RecoDecay::constrainAngle(McDJet.phi() - d0Candidate.phi(), -o2::constants::math::PI); + if (std::abs(dPhiD - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { + continue; + } + if (McDJet.has_matchedJetGeo()) { // geometric matching + for (auto const& McPJet : McDJet.template matchedJetGeo_as()) { + float dPhiP = RecoDecay::constrainAngle(McPJet.phi() - d0Particle.phi(), -o2::constants::math::PI); + // if (std::abs(dPhiP - o2::constants::math::PI) > (o2::constants::math::PI / 2)) { + // continue; + // } + tableJetMatched(tableMatchedCollision.lastIndex(), + McDJet.pt(), + McDJet.eta(), + McDJet.phi(), + McPJet.pt(), + McPJet.eta(), + McPJet.phi(), + dPhiD, + dPhiP); + } + } + } + } + } + PROCESS_SWITCH(JetCorrelationD0, processMcMatched, "process matching of particle level jets to detector level jets", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGJE/Tasks/jetCrossSectionEfficiency.cxx b/PWGJE/Tasks/jetCrossSectionEfficiency.cxx index 8f1c9858a5b..240fb3e7a20 100644 --- a/PWGJE/Tasks/jetCrossSectionEfficiency.cxx +++ b/PWGJE/Tasks/jetCrossSectionEfficiency.cxx @@ -17,17 +17,24 @@ #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include +#include #include #include #include +#include +#include + #include #include +#include #include +#include +#include #include using namespace o2; diff --git a/PWGJE/Tasks/jetD0AngSubstructure.cxx b/PWGJE/Tasks/jetD0AngSubstructure.cxx new file mode 100644 index 00000000000..9650d7ea4bb --- /dev/null +++ b/PWGJE/Tasks/jetD0AngSubstructure.cxx @@ -0,0 +1,201 @@ +// 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 JetD0AngSubstructure.cxx +// +// \brief Analysis task for the reconstruction and study of charged jets +// containing D_0 mesons in pp collisions. +// \inherited from D0 fragmentation and Ds +// \P. Dhankher + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// Definition of a custom AOD table to store jet–D0 quantities +namespace o2::aod +{ +namespace jet_obj +{ +// Jet-related quantities +DECLARE_SOA_COLUMN(JetHfDist, jetHfDist, float); +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +DECLARE_SOA_COLUMN(JetNConst, jetNConst, int); +DECLARE_SOA_COLUMN(JetAng, jetAng, float); +// D0 candidate quantities +DECLARE_SOA_COLUMN(HfPt, hfPt, float); +DECLARE_SOA_COLUMN(HfEta, hfEta, float); +DECLARE_SOA_COLUMN(HfPhi, hfPhi, float); +DECLARE_SOA_COLUMN(HfMass, hfMass, float); +DECLARE_SOA_COLUMN(HfY, hfY, float); +// ML scores +DECLARE_SOA_COLUMN(HfMlScore0, hfMlScore0, float); +DECLARE_SOA_COLUMN(HfMlScore1, hfMlScore1, float); +DECLARE_SOA_COLUMN(HfMlScore2, hfMlScore2, float); +} // namespace jet_obj +// AOD table definition +DECLARE_SOA_TABLE(JetObjTable, "AOD", "JETOBJTABLE", + jet_obj::JetHfDist, + jet_obj::JetPt, + jet_obj::JetEta, + jet_obj::JetPhi, + jet_obj::JetNConst, + jet_obj::JetAng, + jet_obj::HfPt, + jet_obj::HfEta, + jet_obj::HfPhi, + jet_obj::HfMass, + jet_obj::HfY, + jet_obj::HfMlScore0, + jet_obj::HfMlScore1, + jet_obj::HfMlScore2); +} // namespace o2::aod +struct JetD0AngSubstructure { + /** + * Histogram registry + * + * Contains: + * - Event and track histograms + * - Jet kinematic distributions + * - D0–jet substructure observables + */ + HistogramRegistry registry{"registry", + {{"h_collision_counter", "# of collisions;", {HistType::kTH1F, {{2, 0., 2.}}}}, + {"h_jet_counter", ";# of D^{0} jets;", {HistType::kTH1F, {{6, 0., 3.0}}}}, + {"h_d0_jet_projection", ";z^{D^{0},jet}_{||};dN/dz^{D^{0},jet}_{||}", {HistType::kTH1F, {{1000, 0., 10.}}}}, + {"h_d0_jet_distance_vs_projection", ";#DeltaR_{D^{0},jet};z^{D^{0},jet}_{||}", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}}, + {"h_d0_jet_distance", ";#DeltaR_{D^{0},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 10.}}}}, + {"h_d0_jet_pt", ";p_{T,D^{0} jet};dN/dp_{T,D^{0} jet}", {HistType::kTH1F, {{200, 0., 10.}}}}, + {"h_d0_jet_eta", ";#eta_{T,D^{0} jet};dN/d#eta_{D^{0} jet}", {HistType::kTH1F, {{250, -5., 5.}}}}, + {"h_d0_jet_phi", ";#phi_{T,D^{0} jet};dN/d#phi_{D^{0} jet}", {HistType::kTH1F, {{250, -10., 10.}}}}, + {"h_d0_mass", ";m_{D^{0}});dN/dm_{D^{0}}", {HistType::kTH1F, {{1000, 0., 10.}}}}, + {"h_d0_eta", ";#eta_{D^{0}});dN/d#eta_{D_{}}", {HistType::kTH1F, {{250, -5., 5.}}}}, + {"h_d0_phi", ";#phi_{D^{0}});dN/d#phi_{D^{0}}", {HistType::kTH1F, {{250, -10., 10.}}}}, + {"h_d0_ang", ";#lambda_{#kappa}^{#alpha};counts", {HistType::kTH1F, {{100, 0., 1.}}}}}}; + + // Configurables + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; + Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; + + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable kappa{"kappa", 1.0, "angularity kappa"}; // to do: configurable from json + Configurable alpha{"alpha", 1.0, "angularity alpha"}; + + std::vector eventSelectionBits; + int trackSelection = -1; + + // Output table producer + Produces ObjJetTable; + + float angularity; + + void init(o2::framework::InitContext&) + { + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + } + + template + void jetCalculateAngularity(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) / (jet.r() / 100.f), alpha); + } + angularity /= std::pow(jet.pt(), kappa); + } + + void processDataChargedSubstructure(aod::JetCollision const& collision, + soa::Join const& jets, + aod::CandidatesD0Data const&, aod::JetTracks const& tracks) + { + // apply event selection and fill histograms for sanity check + registry.fill(HIST("h_collision_counter"), 0.5); + + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !(std::abs(collision.posZ()) < vertexZCut)) { + return; + } + registry.fill(HIST("h_collision_counter"), 1.5); + + // Loop over jets containing D0 candidates + for (const auto& jet : jets) { + // number of charged jets with D0 + registry.fill(HIST("h_jet_counter"), 0.5); + // obtaining jet 3-vector + TVector3 jetVector(jet.px(), jet.py(), jet.pz()); + + // Loop over D0 candidates associated to the jet + for (const auto& d0Candidate : jet.candidates_as()) { + // obtaining jet 3-vector + TVector3 d0Vector(d0Candidate.px(), d0Candidate.py(), d0Candidate.pz()); + + // calculating fraction of the jet momentum carried by the D0 along the direction of the jet axis + double zParallel = (jetVector * d0Vector) / (jetVector * jetVector); + + // calculating angular distance in eta-phi plane + double axisDistance = jetutilities::deltaR(jet, d0Candidate); + + jetCalculateAngularity(jet, tracks); + + // filling histograms + registry.fill(HIST("h_d0_jet_projection"), zParallel); + registry.fill(HIST("h_d0_jet_distance_vs_projection"), axisDistance, zParallel); + registry.fill(HIST("h_d0_jet_distance"), axisDistance); + registry.fill(HIST("h_d0_jet_pt"), jet.pt()); + registry.fill(HIST("h_d0_jet_eta"), jet.eta()); + registry.fill(HIST("h_d0_jet_phi"), jet.phi()); + registry.fill(HIST("h_d0_mass"), d0Candidate.m()); + registry.fill(HIST("h_d0_eta"), d0Candidate.eta()); + registry.fill(HIST("h_d0_phi"), d0Candidate.phi()); + registry.fill(HIST("h_d0_ang"), angularity); // add more axis + + // filling table + ObjJetTable(axisDistance, + jet.pt(), jet.eta(), jet.phi(), jet.tracks_as().size(), angularity, + d0Candidate.pt(), d0Candidate.eta(), d0Candidate.phi(), d0Candidate.m(), d0Candidate.y(), d0Candidate.mlScores()[0], d0Candidate.mlScores()[1], d0Candidate.mlScores()[2]); + + break; // get out of candidates' loop after first HF particle is found in jet + } // end of D0 candidates loop + + } // end of jets loop + + } // end of process function + PROCESS_SWITCH(JetD0AngSubstructure, processDataChargedSubstructure, "charged HF jet substructure", false); +}; +// Workflow definition +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-d0-ang-substructure"})}; } diff --git a/PWGJE/Tasks/jetDebug.cxx b/PWGJE/Tasks/jetDebug.cxx index be4a84f1a38..53b440e8ea8 100644 --- a/PWGJE/Tasks/jetDebug.cxx +++ b/PWGJE/Tasks/jetDebug.cxx @@ -14,27 +14,35 @@ /// \author Nima Zardoshti // -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.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 "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetDebugTask { HistogramRegistry registry{"registry", {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}}, diff --git a/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx b/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx new file mode 100644 index 00000000000..629ba2f75f3 --- /dev/null +++ b/PWGJE/Tasks/jetDsSpectrumAndSubstructure.cxx @@ -0,0 +1,319 @@ +// 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 substructure and spectrum task for D_s mesons +// +// This task is used to reconstruct and analyse jets containing charged D_s +// mesons +// +/// \author Monalisa Melo +// + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace jet_distance +{ +DECLARE_SOA_COLUMN(JetHfDist, jetHfDist, float); +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +DECLARE_SOA_COLUMN(JetNConst, jetNConst, int); +DECLARE_SOA_COLUMN(HfPt, hfPt, float); +DECLARE_SOA_COLUMN(HfEta, hfEta, float); +DECLARE_SOA_COLUMN(HfPhi, hfPhi, float); +DECLARE_SOA_COLUMN(HfMass, hfMass, float); +DECLARE_SOA_COLUMN(HfY, hfY, float); +DECLARE_SOA_COLUMN(HfMlScore0, hfMlScore0, float); +DECLARE_SOA_COLUMN(HfMlScore1, hfMlScore1, float); +DECLARE_SOA_COLUMN(HfMlScore2, hfMlScore2, float); + +// extra +DECLARE_SOA_COLUMN(JetMass, jetMass, float); +DECLARE_SOA_COLUMN(JetGirth, jetGirth, float); +DECLARE_SOA_COLUMN(JetThrust, jetThrust, float); // lambda_2^1 +DECLARE_SOA_COLUMN(JetLambda11, jetLambda11, float); // lambda_1^1 +} // namespace jet_distance + +DECLARE_SOA_TABLE(JetDistanceTable, "AOD", "JETDISTTABLE", + jet_distance::JetHfDist, + jet_distance::JetPt, + jet_distance::JetEta, + jet_distance::JetPhi, + jet_distance::JetNConst, + jet_distance::HfPt, + jet_distance::HfEta, + jet_distance::HfPhi, + jet_distance::HfMass, + jet_distance::HfY, + jet_distance::HfMlScore0, + jet_distance::HfMlScore1, + jet_distance::HfMlScore2, + jet_distance::JetMass, + jet_distance::JetGirth, + jet_distance::JetThrust, + jet_distance::JetLambda11); +} // namespace o2::aod + +struct JetDsSpecSubs { + HistogramRegistry registry{ + "registry", + { + {"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, + {"h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, + {"h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, + {"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 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_collision_counter", "# of collisions;", {HistType::kTH1F, {{200, 0., 200.}}}}, + {"h_jet_counter", ";# of D_{S} jets;", {HistType::kTH1F, {{6, 0., 3.0}}}}, + {"h_ds_jet_projection", ";z^{D_{S},jet}_{||};dN/dz^{D_{S},jet}_{||}", {HistType::kTH1F, {{1000, 0., 2.}}}}, + {"h_ds_jet_distance_vs_projection", ";#DeltaR_{D_{S},jet};z^{D_{S},jet}_{||}", {HistType::kTH2F, {{1000, 0., 1.}, {1000, 0., 2.}}}}, + {"h_ds_jet_distance", ";#DeltaR_{D_{S},jet};dN/d(#DeltaR)", {HistType::kTH1F, {{1000, 0., 1.}}}}, + {"h_ds_jet_pt", ";p_{T,D_{S} jet};dN/dp_{T,D_{S} jet}", {HistType::kTH1F, {{1000, 0., 100.}}}}, + {"h_ds_jet_eta", ";#eta_{D_{S} jet};entries", {HistType::kTH1F, {{250, -1., 1.}}}}, + {"h_ds_jet_phi", ";#phi_{D_{S} jet};entries", {HistType::kTH1F, {{250, -1., 7.}}}}, + {"h_ds_mass", ";m_{D_{S}} (GeV/c^{2});entries", {HistType::kTH1F, {{1000, 0., 6.}}}}, + {"h_ds_eta", ";#eta_{D_{S}};entries", {HistType::kTH1F, {{250, -1., 1.}}}}, + {"h_ds_phi", ";#phi_{D_{S}};entries", {HistType::kTH1F, {{250, -1., 7.}}}}, + {"h_ds_jet_mass", ";m_{jet}^{ch} (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{200, 0., 50.}}}}, + {"h_ds_jet_lambda11", ";#lambda_{1}^{1};entries", {HistType::kTH1F, {{200, 0., 1.0}}}}, + {"h_ds_jet_lambda12", ";#lambda_{2}^{1} (thrust);entries", {HistType::kTH1F, {{200, 0., 1.0}}}}, + {"h_ds_jet_girth", ";g (#equiv #lambda_{1}^{1}R);entries", {HistType::kTH1F, {{200, 0., 0.5}}}}, + {"h2_dsjet_pt_lambda11", ";#it{p}_{T,jet} (GeV/#it{c});#lambda_{1}^{1}", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 1.0}}}}, + {"h2_dsjet_pt_lambda12", ";#it{p}_{T,jet} (GeV/#it{c});#lambda_{2}^{1}", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 1.0}}}}, + {"h2_dsjet_pt_mass", ";#it{p}_{T,jet} (GeV/#it{c});m_{jet}^{ch} (GeV/#it{c}^{2})", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 50.0}}}}, + {"h2_dsjet_pt_girth", ";#it{p}_{T,jet} (GeV/#it{c});g", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 0.5}}}}, + {"h_ds_jet_lambda_extra", ";#lambda_{#alpha}^{#kappa};entries", {HistType::kTH1F, {{200, 0., 1.0}}}}, + {"h2_dsjet_pt_lambda_extra", ";#it{p}_{T,jet} (GeV/#it{c});#lambda_{#alpha}^{#kappa}", {HistType::kTH2F, {{100, 0., 100.}, {200, 0., 1.0}}}}, + }}; + + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; + Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; + + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + + // extra angularity knob + Configurable kappa{"kappa", 1.0f, "angularity kappa"}; + Configurable alpha{"alpha", 1.0f, "angularity alpha"}; + + bool doExtraAngularity = false; + + std::vector eventSelectionBits; + int trackSelection = -1; + + Produces distJetTable; + + template + float computeLambda(JET const& jet, TRACKS const& tracks, float a, float k) + { + if (jet.pt() <= 0.f) { + return -1.f; + } + float sum = 0.f; + for (auto const& trk : tracks) { + const float dr = jetutilities::deltaR(jet, trk); + sum += std::pow(trk.pt(), k) * std::pow(dr, a); + } + const float R = jet.r() / 100.f; + const float denom = std::pow(jet.pt(), k) * std::pow(R, a); + if (denom <= 0.f) { + return -1.f; + } + return sum / denom; + } + + template + float computeJetMassFromTracksMass(TRACKS const& tracks) + { + double sumPx = 0.0, sumPy = 0.0, sumPz = 0.0, sumE = 0.0; + + for (auto const& trk : tracks) { + const double pt = trk.pt(); + const double phi = trk.phi(); + const double eta = trk.eta(); + + const double px = pt * std::cos(phi); + const double py = pt * std::sin(phi); + const double pz = pt * std::sinh(eta); + const double p = std::sqrt(px * px + py * py + pz * pz); + + sumPx += px; + sumPy += py; + sumPz += pz; + sumE += p; // massless + } + + const double m2 = sumE * sumE - (sumPx * sumPx + sumPy * sumPy + sumPz * sumPz); + return (m2 > 0.0) ? static_cast(std::sqrt(m2)) : 0.f; + } + + void init(o2::framework::InitContext&) + { + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + + const bool is11 = (std::abs(kappa.value - 1.f) < 1e-6f) && (std::abs(alpha.value - 1.f) < 1e-6f); + const bool is12 = (std::abs(kappa.value - 1.f) < 1e-6f) && (std::abs(alpha.value - 2.f) < 1e-6f); + doExtraAngularity = !(is11 || is12); + } + + Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * 100.0f); + Filter collisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; + + void processCollisions(aod::JetCollision const& collision, aod::JetTracks const& tracks) + { + registry.fill(HIST("h_collisions"), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + registry.fill(HIST("h_track_pt"), track.pt()); + registry.fill(HIST("h_track_eta"), track.eta()); + registry.fill(HIST("h_track_phi"), track.phi()); + } + } + PROCESS_SWITCH(JetDsSpecSubs, processCollisions, "process JE collisions", false); + + void processDataCharged(soa::Filtered::iterator const& collision, + soa::Filtered const& jets) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + for (auto& jet : jets) { + registry.fill(HIST("h_jet_pt"), jet.pt()); + registry.fill(HIST("h_jet_eta"), jet.eta()); + registry.fill(HIST("h_jet_phi"), jet.phi()); + } + } + PROCESS_SWITCH(JetDsSpecSubs, processDataCharged, "charged jets in data", false); + + void processDataChargedSubstructure(aod::JetCollision const& collision, + soa::Join const& jets, + aod::CandidatesDsData const&, + aod::JetTracks const&) + { + registry.fill(HIST("h_collision_counter"), 2.0); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || + !(std::abs(collision.posZ()) < vertexZCut)) { + return; + } + registry.fill(HIST("h_collision_counter"), 3.0); + + for (const auto& jet : jets) { + registry.fill(HIST("h_jet_counter"), 0.5); + + TVector3 jetVector(jet.px(), jet.py(), jet.pz()); + + for (const auto& dsCandidate : jet.candidates_as()) { + TVector3 dsVector(dsCandidate.px(), dsCandidate.py(), dsCandidate.pz()); + + const double zParallel = (jetVector * dsVector) / (jetVector * jetVector); + const double axisDistance = jetutilities::deltaR(jet, dsCandidate); + + registry.fill(HIST("h_ds_jet_projection"), zParallel); + registry.fill(HIST("h_ds_jet_distance_vs_projection"), axisDistance, zParallel); + registry.fill(HIST("h_ds_jet_distance"), axisDistance); + registry.fill(HIST("h_ds_jet_pt"), jet.pt()); + registry.fill(HIST("h_ds_jet_eta"), jet.eta()); + registry.fill(HIST("h_ds_jet_phi"), jet.phi()); + registry.fill(HIST("h_ds_mass"), dsCandidate.m()); + registry.fill(HIST("h_ds_eta"), dsCandidate.eta()); + registry.fill(HIST("h_ds_phi"), dsCandidate.phi()); + + auto jetTracks = jet.tracks_as(); + + const float lambda11 = computeLambda(jet, jetTracks, 1.f, 1.f); + const float lambda12 = computeLambda(jet, jetTracks, 2.f, 1.f); // thrust = λ_2^1 + const float mjet = computeJetMassFromTracksMass(jetTracks); + + const float R = jet.r() / 100.f; + const float girth = (lambda11 >= 0.f) ? (lambda11 * R) : -1.f; + + if (lambda11 >= 0.f) { + registry.fill(HIST("h_ds_jet_lambda11"), lambda11); + registry.fill(HIST("h2_dsjet_pt_lambda11"), jet.pt(), lambda11); + } + if (lambda12 >= 0.f) { + registry.fill(HIST("h_ds_jet_lambda12"), lambda12); + registry.fill(HIST("h2_dsjet_pt_lambda12"), jet.pt(), lambda12); + } + registry.fill(HIST("h_ds_jet_mass"), mjet); + registry.fill(HIST("h2_dsjet_pt_mass"), jet.pt(), mjet); + + if (girth >= 0.f) { + registry.fill(HIST("h_ds_jet_girth"), girth); + registry.fill(HIST("h2_dsjet_pt_girth"), jet.pt(), girth); + } + + if (doExtraAngularity) { + const float lambdaExtra = computeLambda(jet, jetTracks, alpha.value, kappa.value); + if (lambdaExtra >= 0.f) { + registry.fill(HIST("h_ds_jet_lambda_extra"), lambdaExtra); + registry.fill(HIST("h2_dsjet_pt_lambda_extra"), jet.pt(), lambdaExtra); + } + } + + auto scores = dsCandidate.mlScores(); + const float s0 = (scores.size() > 0) ? scores[0] : -999.f; + const float s1 = (scores.size() > 1) ? scores[1] : -999.f; + const float s2 = (scores.size() > 2) ? scores[2] : -999.f; + + distJetTable(static_cast(axisDistance), + jet.pt(), jet.eta(), jet.phi(), + static_cast(jetTracks.size()), + dsCandidate.pt(), dsCandidate.eta(), dsCandidate.phi(), + dsCandidate.m(), dsCandidate.y(), + s0, s1, s2, + mjet, girth, lambda12, lambda11); + + break; // only first Ds per jet + } + } + } + PROCESS_SWITCH(JetDsSpecSubs, processDataChargedSubstructure, "charged HF jet substructure", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-ds-spectrum-subs"})}; } diff --git a/PWGJE/Tasks/jetFinderFullQA.cxx b/PWGJE/Tasks/jetFinderFullQA.cxx index 6dc665fe07d..69b18b6e4af 100644 --- a/PWGJE/Tasks/jetFinderFullQA.cxx +++ b/PWGJE/Tasks/jetFinderFullQA.cxx @@ -20,12 +20,12 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include #include +#include #include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetFinderQA.cxx b/PWGJE/Tasks/jetFinderQA.cxx index 878083b557f..c7c9e359a51 100644 --- a/PWGJE/Tasks/jetFinderQA.cxx +++ b/PWGJE/Tasks/jetFinderQA.cxx @@ -83,6 +83,15 @@ struct JetFinderQATask { Configurable intRateMax{"intRateMax", 50000.0, "maximum value of interaction rate axis"}; Configurable kappa{"kappa", 1.0, "angularity kappa"}; Configurable alpha{"alpha", 1.0, "angularity alpha"}; + Configurable checkCentFT0M{"checkCentFT0M", false, "0: centFT0C as default, 1: use centFT0M estimator"}; + + // Configurable qcCutOnJetMultVsPt{"qcCutOnJetMultVsPt", false, "debug configurable for LHC26a7 10% test production with strange high mult jet pupulation"}; + Configurable multCutCheck_proportionalFactor{"multCut_proportionalFactor", 0.5, "debug cut value for LHC26a7 10% test production with strange high mult jet pupulation"}; + Configurable multCutCheck_abscissaAtOrigin{"multCut_abscissaAtOrigin", 5, "debug cut value LHC26a7 10% test production with strange high mult jet pupulation"}; + Configurable multCutCheck_analyseMBGapEvents{"multCutCheck_analyseMBGapEvents", 0, "flag to choose to reject min. bias gap events; -1: MBGap only, 0: skip MBGap events, 1: analyse all events"}; + Configurable doMultCutCheck{"doMultCutCheck", false, "decide to apply multCutCheck or not"}; + Configurable multCutCheck_applyRCTSelections{"multCutCheck_applyRCTSelections", true, "decide to apply RCT selections"}; + Configurable multCutCheck_applyWeightCorrection{"multCutCheck_applyWeightCorrection", true, "decide to apply weight correction"}; std::vector filledJetR_Both; std::vector filledJetR_Low; @@ -92,6 +101,8 @@ struct JetFinderQATask { std::vector eventSelectionBits; int trackSelection = -1; + float simPtRef = 10.; + std::vector jetPtBins; std::vector jetPtBinsRhoAreaSub; @@ -373,7 +384,7 @@ struct JetFinderQATask { registry.add("h_xsecErrSumWeighted", "Summed Cross section error per collision in pb with weights; Summed Cross section error per collision in pb with weights; entries", {HistType::kTH1F, {{1, 0., 1.}}}); } - AxisSpec occupancyAxis = {142, -1.5, 14000.5, "occupancy"}; + AxisSpec occupancyAxis = {140, -0.5, 13999.5, "occupancy"}; AxisSpec nTracksAxis = {16001, -1., 16000, "n tracks"}; if (doprocessOccupancyQA) { @@ -384,10 +395,78 @@ struct JetFinderQATask { registry.add("h2_occupancy_ntracksselptetacuts_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); registry.add("h2_occupancy_ntracksselptetacuts_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); } + + if (doprocessQcMultCutCheck) { + std::vector centralityBinning{0., 10., 50., 70., 100}; + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; + bool doSumw2 = true; + + AxisSpec centralityAxis = {1200, -10., 110., "Centrality"}; + AxisSpec trackPtAxis = {200, -0.5, 199.5, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec trackEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; + AxisSpec phiAxis = {160, -1.0, 7.0, "#varphi"}; + AxisSpec jetPtAxis = {200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPtAxisRhoAreaSub = {400, -200., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; + + registry.add("h_fakecollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + + 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}}}); + registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + + registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, doSumw2); + registry.add("h2_centrality_collisions_weighted", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}, doSumw2); + registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}}, doSumw2); + + registry.add("h_collisions_zvertex", "position of collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}, doSumw2); + registry.add("h_collisions_ntracks", "N_{tracks};", {HistType::kTH1F, {{10000, 0.0, 10000.0}}}, doSumw2); + registry.add("h_collisions_njets", "N_{jets};", {HistType::kTH1F, {{10000, 0.0, 10000.0}}}, doSumw2); + + registry.add("h2_centrality_ntracks", "; centrality; N_{tracks};", {HistType::kTH2F, {{1100, 0., 110.0}, {10000, 0.0, 10000.0}}}); + registry.add("h2_centrality_njets", "; centrality; N_{jets};", {HistType::kTH2F, {{1100, 0., 110.0}, {10000, 0.0, 10000.0}}}); + registry.add("h2_ntracks_rho", "; N_{tracks}; #it{rho} (GeV/area);", {HistType::kTH2F, {{10000, 0.0, 10000.0}, {400, 0.0, 400.0}}}); + registry.add("h2_centrality_rho", "; centrality; #it{rho} (GeV/area);", {HistType::kTH2F, {{1100, 0., 110.}, {400, 0., 400.0}}}); + + 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_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, 10.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, 10.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.}, {10000, 0.0, 1.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.}, {10000, 0.0, 1.0}}}); + + registry.add("h_mccollision_processid", "mccollision process id;mccollision process id;entries", {HistType::kTH1D, {{200, 0.0, 200.0}}}); + + registry.add("h_particle_pdgcode", "particle pdgcode;particle pdgcode;entries", {HistType::kTH1D, {{3000, 0.0, 3000.0}}}); + registry.add("h_particle_genstatuscode", "particle gen status code;particle gen status code;entries", {HistType::kTH1D, {{420, -210.0, 210.0}}}); + registry.add("h_particle_hepmcstatuscode", "particle hep mc status code;particle hep mc status code;entries", {HistType::kTH1D, {{210, 0.0, 210.0}}}); + registry.add("h_particle_process", "particle process;particle process;entries", {HistType::kTH1D, {{50, 0.0, 50.0}}}); + registry.add("h_particle_producedbygenerator", "particle producedByGenerator status;particle producedByGenerator status;entries", {HistType::kTH1D, {{2, 0.0, 2}}}); + + registry.add("h_particle_primary_pdgcode", "primary particle pdgcode;primary particle pdgcode;entries", {HistType::kTH1D, {{3000, 0.0, 3000.0}}}); + registry.add("h_particle_primary_genstatuscode", "primary particle gen status code;primary particle gen status code;entries", {HistType::kTH1D, {{420, -210.0, 210.0}}}); + registry.add("h_particle_primary_hepmcstatuscode", "primary particle hep mc status code;primary particle hep mc status code;entries", {HistType::kTH1D, {{210, 0.0, 210.0}}}); + registry.add("h_particle_primary_process", "primary particle process;primary particle process;entries", {HistType::kTH1D, {{50, 0.0, 50.0}}}); + registry.add("h_particle_primary_producedbygenerator", "primary particle producedByGenerator status;primary particle producedByGenerator status;entries", {HistType::kTH1D, {{2, 0.0, 2}}}); + + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}, doSumw2); + registry.add("h_jet_eta", "jet eta;#eta; counts", {HistType::kTH1F, {jetEtaAxis}}, doSumw2); + registry.add("h_jet_phi", "jet phi;#phi; counts", {HistType::kTH1F, {phiAxis}}, doSumw2); + registry.add("h2_centrality_jet_pt", "centrality vs. jet pT;centrality; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH2F, {centralityAxis, jetPtAxis}}, doSumw2); + registry.add("h2_centrality_jet_eta", "centrality vs. jet eta;centrality; #eta; counts", {HistType::kTH2F, {centralityAxis, jetEtaAxis}}, doSumw2); + registry.add("h2_centrality_jet_phi", "centrality vs. jet phi;centrality; #varphi; counts", {HistType::kTH2F, {centralityAxis, phiAxis}}, doSumw2); + registry.add("h2_jet_pt_jet_area", "jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet} (GeV/#it{c}); Area_{jet}", {HistType::kTH2F, {jetPtAxis, {150, 0., 1.5}}}, doSumw2); + registry.add("h2_jet_pt_jet_ntracks", "jet #it{p}_{T,jet} vs. N_{jet tracks}; #it{p}_{T,jet} (GeV/#it{c}); N_{jet, tracks}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}, doSumw2); + registry.add("h2_jet_pt_track_pt", "jet #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, {jetPtAxis, trackPtAxis}}, doSumw2); + registry.add("h3_jet_pt_jet_eta_jet_phi", "jet pt vs. eta vs. phi", {HistType::kTH3F, {jetPtAxis, jetEtaAxis, phiAxis}}, doSumw2); + } } 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 && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); + Filter particleCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta > trackEtaMin && aod::jmcparticle::eta < trackEtaMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && + ((checkCentFT0M ? aod::jcollision::centFT0M : aod::jcollision::centFT0C) >= centralityMin) && + ((checkCentFT0M ? aod::jcollision::centFT0M : aod::jcollision::centFT0C) < centralityMax)); PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; PresliceUnsorted> McCollisionsPerMCPCollision = aod::jmccollision::mcCollisionId; @@ -810,6 +889,64 @@ struct JetFinderQATask { registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centFT0M(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); } + enum mbGapSelectionRequirement { + mbGapOnly = -1, + mbGapSkip = 0, + mbGapAndSignal = 1 + }; + + template + bool applyCollisionCuts_multCutCheck(TColl const& collision, bool fillHistograms = false, bool isWeighted = false, float eventWeight = 1.0) + { + float centrality = -1.0; + checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); + + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 0.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight); + } + + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, multCutCheck_applyRCTSelections)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 1.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 1.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 1.5, eventWeight); + } + + if (centrality < centralityMin || centralityMax < centrality) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 2.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 2.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); + } + + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("h_collisions"), 3.5); + registry.fill(HIST("h2_centrality_collisions"), centrality, 3.5, eventWeight); + if (isWeighted) + registry.fill(HIST("h_collisions_weighted"), 3.5, eventWeight); + } + + if (multCutCheck_analyseMBGapEvents == mbGapSelectionRequirement::mbGapOnly && collision.getSubGeneratorId() != jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return false; + } else if (multCutCheck_analyseMBGapEvents == mbGapSelectionRequirement::mbGapSkip && collision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return false; + } + + return true; + } + void processJetsData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::JetTracks const&) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { @@ -945,14 +1082,11 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCD, "jet finder QA mcd", false); - void processJetsMCDWeighted(soa::Filtered>::iterator const& collision, aod::JetMcCollisions const&, soa::Join const& jets, aod::JetTracks const&) + void processJetsMCDWeighted(soa::Filtered>::iterator const& collision, aod::JetMcCollisions const&, soa::Join const& jets, aod::JetTracks const&) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - if (collision.isOutlier()) { - return; - } for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -990,7 +1124,7 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCP, "jet finder QA mcp", false); - void processJetsMCPWeighted(soa::Join::iterator const& jet, aod::JetParticles const&, soa::Join const& mcCollisions, soa::Filtered> const& collisions) + void processJetsMCPWeighted(soa::Join::iterator const& jet, aod::JetParticles const&, soa::Join const& mcCollisions, soa::Filtered const& collisions) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { return; @@ -1007,7 +1141,7 @@ struct JetFinderQATask { } if (checkMcCollisionIsMatched) { auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, jet.mcCollisionId()); - if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits) && !collisionspermcpjet.begin().isOutlier()) { + if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits)) { fillMCPHistograms(jet, mcCollision.begin().weight(), mcCollision.begin().ptHard()); } } else { @@ -1047,7 +1181,7 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processJetsMCPMCDMatched, "jet finder QA matched mcp and mcd", false); - void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, + void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, aod::JetMcCollisions const&, soa::Join const& mcdjets, soa::Join const&, @@ -1056,9 +1190,6 @@ struct JetFinderQATask { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - if (collision.isOutlier()) { - return; - } for (const auto& mcdjet : mcdjets) { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1246,7 +1377,7 @@ struct JetFinderQATask { } PROCESS_SWITCH(JetFinderQATask, processTracks, "QA for charged tracks", false); - void processTracksWeighted(soa::Join::iterator const& collision, + void processTracksWeighted(soa::Join::iterator const& collision, aod::JetMcCollisions const&, soa::Filtered> const& tracks) { @@ -1266,11 +1397,6 @@ struct JetFinderQATask { } registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); - if (collision.isOutlier()) { - return; - } - registry.fill(HIST("h_collisions"), 3.5); - registry.fill(HIST("h_collisions_weighted"), 3.5, eventWeight); fillTrackHistograms(collision, tracks, eventWeight, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetFinderQATask, processTracksWeighted, "QA for charged tracks weighted", false); @@ -1357,12 +1483,102 @@ struct JetFinderQATask { registry.fill(HIST("h2_occupancy_ntrackssel_presel"), occupancy, nTracksAllAcceptanceAndSelected); registry.fill(HIST("h2_occupancy_ntracksselptetacuts_presel"), occupancy, nTracksInAcceptanceAndSelected); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); - registry.fill(HIST("h2_occupancy_ntrackssel_postsel"), occupancy, nTracksAllAcceptanceAndSelected); - registry.fill(HIST("h2_occupancy_ntracksselptetacuts_postsel"), occupancy, nTracksInAcceptanceAndSelected); + return; } + registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); + registry.fill(HIST("h2_occupancy_ntrackssel_postsel"), occupancy, nTracksAllAcceptanceAndSelected); + registry.fill(HIST("h2_occupancy_ntracksselptetacuts_postsel"), occupancy, nTracksInAcceptanceAndSelected); } PROCESS_SWITCH(JetFinderQATask, processOccupancyQA, "occupancy QA on jet derived data", false); + + void processQcMultCutCheck(soa::Filtered>::iterator const& collision, + soa::Join const&, + // soa::Join const& aodMcCollisions, + soa::Join const& mcdjets, + soa::Filtered> const& tracks, + soa::Filtered const& mcparticles) + { + float eventWeight = multCutCheck_applyWeightCorrection ? collision.weight() : 1; + + bool hasJetAboveMultCut = false; + for (auto const& mcdjet : mcdjets) { + if (mcdjet.tracksIds().size() > multCutCheck_proportionalFactor * mcdjet.pt() + multCutCheck_abscissaAtOrigin) { + hasJetAboveMultCut = true; + } + } + if (doMultCutCheck && hasJetAboveMultCut == false) { + return; + } + + bool fillHistograms = true; + bool isWeighted = multCutCheck_applyWeightCorrection; + if (!applyCollisionCuts_multCutCheck(collision, fillHistograms, isWeighted, eventWeight)) { + return; + } + registry.fill(HIST("h_collisions_zvertex"), collision.posZ(), eventWeight); + + if (collision.has_mcCollision()) { // the collision is not fake and has one associated mc coll; .mccollision() can be called + auto jetMcCollision = collision.mcCollision_as>(); + auto aodMcCollision = jetMcCollision.mcCollision_as>(); + + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), simPtRef / (std::pow(collision.weight(), 1.0 / pTHatExponent)), jetMcCollision.ptHard()); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted"), simPtRef / (std::pow(collision.weight(), 1.0 / pTHatExponent)), jetMcCollision.ptHard(), eventWeight); + registry.fill(HIST("h_mccollision_processid"), aodMcCollision.processId(), eventWeight); + } else { + registry.fill(HIST("h_fakecollisions"), 0.5); + } + + registry.fill(HIST("h_collisions_ntracks"), tracks.size(), eventWeight); + registry.fill(HIST("h2_centrality_ntracks"), collision.centFT0M(), tracks.size(), eventWeight); + registry.fill(HIST("h_collisions_njets"), mcdjets.size(), eventWeight); + registry.fill(HIST("h2_centrality_njets"), collision.centFT0M(), mcdjets.size(), eventWeight); + registry.fill(HIST("h2_ntracks_rho"), tracks.size(), collision.rho(), eventWeight); + registry.fill(HIST("h2_centrality_rho"), collision.centFT0M(), collision.rho(), eventWeight); + + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + registry.fill(HIST("h2_centrality_track_pt"), collision.centFT0M(), track.pt(), eventWeight); + registry.fill(HIST("h2_centrality_track_eta"), collision.centFT0M(), track.eta(), eventWeight); + registry.fill(HIST("h2_track_pt_track_sigma1overpt"), track.pt(), track.sigma1Pt(), eventWeight); + registry.fill(HIST("h2_track_pt_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), eventWeight); + registry.fill(HIST("h2_track_pt_high_track_sigma1overpt"), track.pt(), track.sigma1Pt(), eventWeight); + registry.fill(HIST("h2_track_pt_high_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), eventWeight); + } + + for (auto const& mcparticle : mcparticles) { + registry.fill(HIST("h_particle_pdgcode"), mcparticle.pdgCode(), eventWeight); + registry.fill(HIST("h_particle_genstatuscode"), mcparticle.getGenStatusCode(), eventWeight); + registry.fill(HIST("h_particle_hepmcstatuscode"), mcparticle.getHepMCStatusCode(), eventWeight); + registry.fill(HIST("h_particle_process"), mcparticle.getProcess(), eventWeight); + registry.fill(HIST("h_particle_producedbygenerator"), mcparticle.producedByGenerator(), eventWeight); + if (mcparticle.isPhysicalPrimary()) { + registry.fill(HIST("h_particle_primary_pdgcode"), mcparticle.pdgCode(), eventWeight); + registry.fill(HIST("h_particle_primary_genstatuscode"), mcparticle.getGenStatusCode(), eventWeight); + registry.fill(HIST("h_particle_primary_hepmcstatuscode"), mcparticle.getHepMCStatusCode(), eventWeight); + registry.fill(HIST("h_particle_primary_process"), mcparticle.getProcess(), eventWeight); + registry.fill(HIST("h_particle_primary_producedbygenerator"), mcparticle.producedByGenerator(), eventWeight); + } + } + + for (auto const& mcdjet : mcdjets) { + registry.fill(HIST("h_jet_pt"), mcdjet.pt(), eventWeight); + registry.fill(HIST("h_jet_eta"), mcdjet.eta(), eventWeight); + registry.fill(HIST("h_jet_phi"), mcdjet.phi(), eventWeight); + registry.fill(HIST("h2_centrality_jet_pt"), collision.centFT0M(), mcdjet.pt(), eventWeight); + registry.fill(HIST("h2_centrality_jet_eta"), collision.centFT0M(), mcdjet.eta(), eventWeight); + registry.fill(HIST("h2_centrality_jet_phi"), collision.centFT0M(), mcdjet.phi(), eventWeight); + registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi"), mcdjet.pt(), mcdjet.eta(), mcdjet.phi(), eventWeight); + + registry.fill(HIST("h2_jet_pt_jet_area"), mcdjet.pt(), mcdjet.area(), eventWeight); + registry.fill(HIST("h2_jet_pt_jet_ntracks"), mcdjet.pt(), mcdjet.tracksIds().size(), eventWeight); + for (const auto& constituent : mcdjet.template tracks_as>>()) { + registry.fill(HIST("h2_jet_pt_track_pt"), mcdjet.pt(), constituent.pt(), eventWeight); + } + } + } + PROCESS_SWITCH(JetFinderQATask, processQcMultCutCheck, "processing QC on collision, track and jet quantities after cut on collision based on jet quantities;", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderV0QA.cxx b/PWGJE/Tasks/jetFinderV0QA.cxx index a80ee0eea25..55036241730 100644 --- a/PWGJE/Tasks/jetFinderV0QA.cxx +++ b/PWGJE/Tasks/jetFinderV0QA.cxx @@ -18,11 +18,11 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetFormationTimeReclustering.cxx b/PWGJE/Tasks/jetFormationTimeReclustering.cxx index f3f2348f7d5..b411fdddbe9 100644 --- a/PWGJE/Tasks/jetFormationTimeReclustering.cxx +++ b/PWGJE/Tasks/jetFormationTimeReclustering.cxx @@ -23,11 +23,10 @@ #ifndef PWGJE_TASKS_JETFORMATIONTIMERECLUSTERING_H_ #define PWGJE_TASKS_JETFORMATIONTIMERECLUSTERING_H_ -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/DataModel/Jet.h" // IWYU pragma: keep #include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetSubstructure.h" // new +#include "PWGJE/DataModel/JetSubtraction.h" #include @@ -37,27 +36,12 @@ namespace o2::aod { - -namespace jetcollision -{ //! -DECLARE_SOA_COLUMN(PosZ, posZ, float); //! -DECLARE_SOA_COLUMN(Centrality, centrality, float); //! -DECLARE_SOA_COLUMN(EventSel, eventSel, uint8_t); //! -DECLARE_SOA_COLUMN(EventWeight, eventWeight, float); //! -} // namespace jetcollision - -namespace jetmccollision -{ -DECLARE_SOA_COLUMN(PosZ, posZ, float); //! -DECLARE_SOA_COLUMN(Accepted, accepted, uint64_t); //! -DECLARE_SOA_COLUMN(Attempted, attempted, uint64_t); //! -DECLARE_SOA_COLUMN(XsectGen, xsectGen, float); //! -DECLARE_SOA_COLUMN(XsectErr, xsectErr, float); //! -DECLARE_SOA_COLUMN(EventWeight, eventWeight, float); //! -} // namespace jetmccollision - -namespace jetsubstructure +// new part +namespace jetTFsubstructure { //! +DECLARE_SOA_COLUMN(JetPt, jetPt, float); //! +DECLARE_SOA_COLUMN(JetEta, jetEta, float); //! +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); //! DECLARE_SOA_COLUMN(EnergyMother, energyMother, std::vector); //! DECLARE_SOA_COLUMN(PtLeading, ptLeading, std::vector); //! DECLARE_SOA_COLUMN(PtSubLeading, ptSubLeading, std::vector); //! @@ -71,111 +55,13 @@ DECLARE_SOA_COLUMN(Thetag, thetag, std::vector); //! DECLARE_SOA_COLUMN(Zg, zg, std::vector); //! DECLARE_SOA_COLUMN(TauFormg, tauFormg, std::vector); //! //! -} // namespace jetsubstructure - -namespace splitting -{ //! -DECLARE_SOA_COLUMN(Pt, pt, float); //! -DECLARE_SOA_COLUMN(Eta, eta, float); //! -DECLARE_SOA_COLUMN(Phi, phi, float); //! -DECLARE_SOA_COLUMN(R, r, int); //! -DECLARE_SOA_COLUMN(SplittingMatchingGeo, splittingMatchingGeo, std::vector); //! -DECLARE_SOA_COLUMN(SplittingMatchingPt, splittingMatchingPt, std::vector); //! -DECLARE_SOA_COLUMN(SplittingMatchingHF, splittingMatchingHF, std::vector); //! -} // namespace splitting - -// Defines the jet table definition -#define JETSPLITTING_TABLE_DEF(_jet_type_, _jet_description_, _name_, _track_type_, _cand_type_) \ - \ - namespace _name_##splitting \ - { \ - DECLARE_SOA_INDEX_COLUMN(_jet_type_##Jet, jet); \ - } \ - namespace _name_##splittingconstituents \ - { \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(Tracks, tracks, int32_t, _track_type_, "_tracks"); \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(Clusters, clusters, int32_t, JClusters, "_clusters"); \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(Candidates, candidates, int32_t, _cand_type_, "_cand"); \ - } \ - DECLARE_SOA_TABLE(_jet_type_##SPs, "AOD", _jet_description_ "SP", \ - o2::soa::Index<>, \ - _name_##splitting::_jet_type_##JetId, \ - _name_##splittingconstituents::TracksIds, \ - _name_##splittingconstituents::ClustersIds, \ - _name_##splittingconstituents::CandidatesIds, \ - splitting::Pt, \ - splitting::Eta, \ - splitting::Phi, \ - splitting::R); - -namespace jetoutput -{ -DECLARE_SOA_COLUMN(JetPt, jetPt, float); //! -DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); //! -DECLARE_SOA_COLUMN(JetEta, jetEta, float); //! -DECLARE_SOA_COLUMN(JetY, jetY, float); //! -DECLARE_SOA_COLUMN(JetR, jetR, float); //! -DECLARE_SOA_COLUMN(JetArea, jetArea, float); //! -DECLARE_SOA_COLUMN(JetRho, jetRho, float); //! -DECLARE_SOA_COLUMN(JetPerpConeRho, jetPerpConeRho, float); //! -DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, int); //! -} // namespace jetoutput - -#define MCCOLL_TABLE_DEF(_jet_type_, _jet_description_, _name_) \ - namespace _name_##mccollisionoutput \ - { \ - DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ - } \ - DECLARE_SOA_TABLE(_jet_type_##MCCOs, "AOD", _jet_description_ "MCCO", \ - jetmccollision::PosZ, \ - jetmccollision::Accepted, \ - jetmccollision::Attempted, \ - jetmccollision::XsectGen, \ - jetmccollision::XsectErr, \ - jetmccollision::EventWeight, \ - _name_##mccollisionoutput::Dummy##_jet_type_<>); - -// Defines the jet substrcuture table definition -#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, jetcollision::EventWeight, _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::JetArea, jetoutput::JetRho, jetoutput::JetPerpConeRho, 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", jetoutput::JetPt, jetoutput::JetPhi, jetoutput::JetEta, jetsubstructure::EnergyMother, jetsubstructure::PtLeading, jetsubstructure::PtSubLeading, jetsubstructure::Theta, jetsubstructure::PtLeadingConstituent, jetsubstructure::TauForm, jetsubstructure::Z, jetsubstructure::Ptg, jetsubstructure::Thetag, jetsubstructure::Zg, jetsubstructure::TauFormg, _name_##substructure::Dummy##_jet_type_<>); \ - DECLARE_SOA_TABLE(_jet_type_##SSOs, "AOD", _jet_description_ "SSO", _name_##substructure::_jet_type_##OId, jetoutput::JetPt, jetoutput::JetPhi, jetoutput::JetEta, jetsubstructure::EnergyMother, jetsubstructure::PtLeading, jetsubstructure::PtSubLeading, jetsubstructure::Theta, jetsubstructure::PtLeadingConstituent, jetsubstructure::TauForm, jetsubstructure::Z, jetsubstructure::Ptg, jetsubstructure::Thetag, jetsubstructure::Zg, jetsubstructure::TauFormg); \ - \ - using _jet_type_##O = _jet_type_##Os::iterator; \ - using _jet_type_##SSO = _jet_type_##SSOs::iterator; - -#define JETSUBSTRUCTURE_TABLES_DEF(_jet_type_, _jet_description_, _jet_type_full_, _jet_full_description_, _track_type_data_, _cand_type_data_, _cand_description_data_, _track_type_ewsdata_, _cand_type_ewsdata_, _cand_description_ewsdata_, _track_type_mcd_, _cand_type_mcd_, _cand_description_mcd_, _particle_type_, _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_) \ - JETSPLITTING_TABLE_DEF(_jet_type_full_, _jet_description_, _jet_full_description_, _track_type_data_, _cand_type_data_) \ - JETSPLITTING_TABLE_DEF(_jet_type_full_##EventWiseSubtracted, _jet_description_ "EWS", _jet_full_description_##eventwisesubtracted, _cand_type_ewsdata_, _cand_type_ewsdata_) \ - 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_) \ - MCCOLL_TABLE_DEF(_jet_type_##MCPJet, _jet_description_ "MCPJET", _jet_type_##mcpjet) \ - JETSPLITTING_TABLE_DEF(_jet_type_full_##MCDetectorLevel, _jet_description_ "D", _jet_full_description_##mcdetectorlevel, _track_type_mcd_, _cand_type_mcd_) \ - JETSPLITTING_TABLE_DEF(_jet_type_full_##MCParticleLevel, _jet_description_ "P", _jet_full_description_##mcparticlelevel, _particle_type_, _hfparticle_type_) - -JETSUBSTRUCTURE_TABLES_DEF(C, "C", Charged, charged, JTracks, CJetCOs, "CJETCO", JTrackSubs, CEWSJetCOs, "CEWSJETCO", JTracks, CMCDJetCOs, "CMCDJETCO", JMcParticles, CMCPJetCOs, "CMCPJETCO"); +} // namespace jetTFsubstructure + +// all tables have the same content (for now) +DECLARE_SOA_TABLE(CJetTFSSs, "AOD", "CJETTFSS", jetTFsubstructure::JetPt, jetTFsubstructure::JetPhi, jetTFsubstructure::JetEta, jetTFsubstructure::EnergyMother, jetTFsubstructure::PtLeading, jetTFsubstructure::PtSubLeading, jetTFsubstructure::Theta, jetTFsubstructure::PtLeadingConstituent, jetTFsubstructure::TauForm, jetTFsubstructure::Z, jetTFsubstructure::Ptg, jetTFsubstructure::Thetag, jetTFsubstructure::Zg, jetTFsubstructure::TauFormg); +DECLARE_SOA_TABLE(CMCDJetTFSSs, "AOD", "CMCDJETTFSS", jetTFsubstructure::JetPt, jetTFsubstructure::JetPhi, jetTFsubstructure::JetEta, jetTFsubstructure::EnergyMother, jetTFsubstructure::PtLeading, jetTFsubstructure::PtSubLeading, jetTFsubstructure::Theta, jetTFsubstructure::PtLeadingConstituent, jetTFsubstructure::TauForm, jetTFsubstructure::Z, jetTFsubstructure::Ptg, jetTFsubstructure::Thetag, jetTFsubstructure::Zg, jetTFsubstructure::TauFormg); +DECLARE_SOA_TABLE(CMCPJetTFSSs, "AOD", "CMCPJETTFSS", jetTFsubstructure::JetPt, jetTFsubstructure::JetPhi, jetTFsubstructure::JetEta, jetTFsubstructure::EnergyMother, jetTFsubstructure::PtLeading, jetTFsubstructure::PtSubLeading, jetTFsubstructure::Theta, jetTFsubstructure::PtLeadingConstituent, jetTFsubstructure::TauForm, jetTFsubstructure::Z, jetTFsubstructure::Ptg, jetTFsubstructure::Thetag, jetTFsubstructure::Zg, jetTFsubstructure::TauFormg); +DECLARE_SOA_TABLE(CEWSJetTFSSs, "AOD", "CEWSJETTFSS", jetTFsubstructure::JetPt, jetTFsubstructure::JetPhi, jetTFsubstructure::JetEta, jetTFsubstructure::EnergyMother, jetTFsubstructure::PtLeading, jetTFsubstructure::PtSubLeading, jetTFsubstructure::Theta, jetTFsubstructure::PtLeadingConstituent, jetTFsubstructure::TauForm, jetTFsubstructure::Z, jetTFsubstructure::Ptg, jetTFsubstructure::Thetag, jetTFsubstructure::Zg, jetTFsubstructure::TauFormg); } // namespace o2::aod @@ -189,24 +75,22 @@ JETSUBSTRUCTURE_TABLES_DEF(C, "C", Charged, charged, JTracks, CJetCOs, "CJETCO", #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include #include +#include #include +#include #include #include +#include #include #include -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/PseudoJet.hh" +#include #include +#include #include #include @@ -216,12 +100,12 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct FormationTimeReclustering { +struct JetFormationTimeReclustering { - Produces jetSubstructureDataTable; - Produces jetSubstructureMCDTable; - Produces jetSubstructureMCPTable; - Produces jetSubstructureDataSubTable; + Produces jetSubstructureDataTable; + Produces jetSubstructureMCDTable; + Produces jetSubstructureMCPTable; + Produces jetSubstructureDataSubTable; Produces jetSplittingsDataTable; Produces jetSplittingsMCDTable; @@ -314,13 +198,13 @@ struct FormationTimeReclustering { std::vector candidates; std::vector clusters; for (const auto& constituent : sorted_by_pt(parentSubJet2.constituents())) { - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::track)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::track) { tracks.push_back(constituent.template user_info().getIndex()); } } splittingTable(jet.globalIndex(), tracks, clusters, candidates, parentSubJet2.perp(), parentSubJet2.eta(), parentSubJet2.phi(), 0); auto z = parentSubJet2.perp() / (parentSubJet1.perp() + parentSubJet2.perp()); - auto theta = parentSubJet1.delta_R(parentSubJet2); + auto theta = parentSubJet1.delta_R(parentSubJet2); // this is deltaR - divide by R in postprocessing auto tau = (parentSubJet1.perp() + parentSubJet2.perp()) / (parentSubJet1.perp() * parentSubJet2.perp() * theta * theta); // as in run2 aliphysics energyMotherVec.push_back(daughterSubJet.e()); ptLeadingVec.push_back(parentSubJet1.pt()); @@ -387,28 +271,28 @@ struct FormationTimeReclustering { void processDummy(aod::JetTracks const&) { } - PROCESS_SWITCH(FormationTimeReclustering, processDummy, "Dummy process function turned on by default", true); + PROCESS_SWITCH(JetFormationTimeReclustering, processDummy, "Dummy process function turned on by default", true); void processChargedJetsData(soa::Join::iterator const& jet, aod::JetTracks const& tracks) { analyseCharged(jet, tracks, TracksPerCollision, jetSubstructureDataTable, jetSplittingsDataTable); } - PROCESS_SWITCH(FormationTimeReclustering, processChargedJetsData, "charged jet substructure", false); + PROCESS_SWITCH(JetFormationTimeReclustering, processChargedJetsData, "charged jet substructure", false); void processChargedJetsEventWiseSubData(soa::Join::iterator const& jet, aod::JetTracksSub const& tracks) { analyseCharged(jet, tracks, TracksPerCollisionDataSub, jetSubstructureDataSubTable, jetSplittingsDataSubTable); } - PROCESS_SWITCH(FormationTimeReclustering, processChargedJetsEventWiseSubData, "eventwise-constituent subtracted charged jet substructure", false); + PROCESS_SWITCH(JetFormationTimeReclustering, processChargedJetsEventWiseSubData, "eventwise-constituent subtracted charged jet substructure", false); void processChargedJetsMCD(typename soa::Join::iterator const& jet, aod::JetTracks const& tracks) { analyseCharged(jet, tracks, TracksPerCollision, jetSubstructureMCDTable, jetSplittingsMCDTable); } - PROCESS_SWITCH(FormationTimeReclustering, processChargedJetsMCD, "charged jet substructure", false); + PROCESS_SWITCH(JetFormationTimeReclustering, processChargedJetsMCD, "charged jet substructure", false); void processChargedJetsMCP(typename soa::Join::iterator const& jet) { @@ -417,17 +301,17 @@ struct FormationTimeReclustering { phiJet = jet.phi(); etaJet = jet.eta(); for (auto& jetConstituent : jet.template tracks_as()) { - fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), pdg->Mass(jetConstituent.pdgCode())); + fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), JetConstituentStatus::track, pdg->Mass(jetConstituent.pdgCode())); } jetReclustering(jet, jetSplittingsMCPTable); jetSubstructureMCPTable(ptJet, phiJet, etaJet, energyMotherVec, ptLeadingVec, ptSubLeadingVec, thetaVec, leadingConstituentPt, tauFormVec, zVec, ptgVec, thetagVec, zgVec, taugVec); } - PROCESS_SWITCH(FormationTimeReclustering, processChargedJetsMCP, "charged jet substructure on MC particle level", false); + PROCESS_SWITCH(JetFormationTimeReclustering, processChargedJetsMCP, "charged jet substructure on MC particle level", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask( - cfgc, TaskName{"jet-formationtimereclustering"})}; + return WorkflowSpec{adaptAnalysisTask( + cfgc, TaskName{"jet-formation-time-reclustering"})}; } diff --git a/PWGJE/Tasks/jetFragmentation.cxx b/PWGJE/Tasks/jetFragmentation.cxx index 0d3fe2965ed..f919d1f3ec3 100644 --- a/PWGJE/Tasks/jetFragmentation.cxx +++ b/PWGJE/Tasks/jetFragmentation.cxx @@ -23,7 +23,6 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/TrackSelectionTables.h" #include #include diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 0ade9be55fd..0cfbcd2ea8d 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -16,25 +16,25 @@ #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/RecoDecay.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include #include +#include #include +#include #include #include -#include +#include #include -#include "TRandom3.h" +#include #include #include @@ -52,6 +52,10 @@ using namespace o2::framework::expressions; struct JetHadronRecoil { + using JetParticlesWithOriginal = soa::Join; + + Preslice> perColJetMC = aod::jet::mcCollisionId; + std::vector jetConstituents; std::vector jetReclustered; JetFinder jetReclusterer; @@ -66,6 +70,7 @@ struct JetHadronRecoil { Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable trackOccupancyInTimeRangeMax{"trackOccupancyInTimeRangeMax", 999999, "maximum track occupancy in time range"}; Configurable ptTTrefMin{"ptTTrefMin", 5, "reference minimum trigger track pt"}; Configurable ptTTrefMax{"ptTTrefMax", 7, "reference maximum trigger track pt"}; Configurable ptTTsigMin{"ptTTsigMin", 20, "signal minimum trigger track pt"}; @@ -89,7 +94,7 @@ struct JetHadronRecoil { 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 particleCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta > trackEtaMin && aod::jmcparticle::eta < trackEtaMax); - Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax && aod::jcollision::trackOccupancyInTimeRange < trackOccupancyInTimeRangeMax); std::vector ptBinningPart = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, @@ -143,8 +148,11 @@ struct JetHadronRecoil { jetReclusterer.recombScheme = fastjet::WTA_pt_scheme; registry.add("hZvtxSelected", "Z vertex position;Z_{vtx};entries", {HistType::kTH1F, {{80, -20, 20}}}, doSumw); + registry.add("hCentOccupancy", "centrality vs track occupancy;centrality (%);track occupancy", {HistType::kTH2F, {{100, 0, 100}, {200, 0, 10000}}}, doSumw); + registry.add("hCentRho", "centrality vs rho;centrality (%);#rho", {HistType::kTH2F, {{100, 0, 100}, {125, 0, 250}}}, doSumw); - if (doprocessData || doprocessDataWithRhoSubtraction || doprocessMCD || doprocessMCDWithRhoSubtraction || doprocessMCDWeighted || doprocessMCDWeightedWithRhoSubtraction || doprocessMCP || doprocessMCPWeighted) { + if (doprocessData || doprocessDataWithRhoSubtraction || doprocessMCD || doprocessMCDWithRhoSubtraction || doprocessMCDWeighted || doprocessMCDWeightedWithRhoSubtraction || doprocessMCP || doprocessMCPWeighted || doprocessMCPOnTheFly || doprocessMCPOnTheFlyWeighted) { + registry.add("hNtracksRho", "track multiplicity vs #rho;N_{tracks};#rho", {HistType::kTH2F, {{125, 0, 5000}, {125, 0, 250}}}, doSumw); registry.add("hNtrig", "number of triggers;trigger type;entries", {HistType::kTH1F, {{2, 0, 2}}}, doSumw); registry.add("hSignalTriggersPtHard", "Signal triggers vs PtHard", {HistType::kTH1F, {pThatAxis}}, doSumw); registry.add("hReferenceTriggersPtHard", "Reference triggers vs PtHard", {HistType::kTH1F, {pThatAxis}}, doSumw); @@ -164,6 +172,7 @@ struct JetHadronRecoil { registry.add("hJetEta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, doSumw); registry.add("hJetPhi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{100, 0.0, o2::constants::math::TwoPI}}}, doSumw); registry.add("hJet3D", "3D jet distribution;p_{T};#eta;#phi", {HistType::kTH3F, {{500, -100, 400}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}, doSumw); + registry.add("hJetPtArea", "jet p_{T}vs area;jet p_{T};A_{jet}", {HistType::kTH2F, {{500, -100, 400}, {100, 0, 2}}}, doSumw); } if (doprocessData || doprocessDataWithRhoSubtraction || doprocessMCD || doprocessMCDWithRhoSubtraction || doprocessMCDWeighted || doprocessMCDWeightedWithRhoSubtraction) { @@ -183,11 +192,9 @@ struct JetHadronRecoil { registry.add("hDeltaRpTReference", "jet p_{T} vs #DeltaR;p_{T,jet};#DeltaR", {HistType::kTH2F, {{500, -100, 400}, dRAxis}}, doSumw); registry.add("hDeltaRpTDPhiReference", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{500, -100, 400}, {100, 0, o2::constants::math::TwoPI}, dRAxis}}, doSumw); registry.add("hDeltaRpTDPhiReferenceShifts", "testing shifts;p_{T,jet};#Delta#phi;#DeltaR;shifts", {HistType::kTHnSparseD, {{500, -100, 400}, {100, 0, o2::constants::math::TwoPI}, dRAxis, {20, 0.0, 2.0}}}, doSumw); - registry.add("hPtTrackMatched", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); - registry.add("hPtTrackMatchedToCollisions", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); } - if (doprocessMCP || doprocessMCPWeighted) { + if (doprocessMCP || doprocessMCPWeighted || doprocessMCPOnTheFly || doprocessMCPOnTheFlyWeighted) { registry.add("hPartvsJets", "comparing leading particles and jets;p_{T,part};p_{T,jet};#hat{p}", {HistType::kTH3F, {{200, 0, 200}, {500, -100, 400}, {195, 5, 200}}}, doSumw); registry.add("hPtPart", "Particle p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); registry.add("hEtaPart", "Particle #eta;#eta;entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, doSumw); @@ -202,20 +209,44 @@ struct JetHadronRecoil { registry.add("hDeltaRpTDPhiReferencePart", "jet p_{T} vs #DeltaR vs #Delta#phi;p_{T,jet};#Delta#phi;#DeltaR", {HistType::kTH3F, {{400, 0, 400}, {100, 0, o2::constants::math::TwoPI}, dRAxis}}, doSumw); } - if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWithRhoSubtraction || doprocessJetsMCPMCDMatchedWeighted || doprocessJetsMCPMCDMatchedWeightedWithRhoSubtraction || doprocessRecoilJetsMCPMCDMatched || doprocessRecoilJetsMCPMCDMatchedWeighted || doprocessRecoilJetsMCPMCDMatchedWeightedWithRhoSubtraction) { + if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWithRhoSubtraction || doprocessJetsMCPMCDMatchedWeighted || doprocessJetsMCPMCDMatchedWeightedWithRhoSubtraction) { registry.add("hPtMatched", "p_{T} matching;p_{T,det};p_{T,part}", {HistType::kTH2F, {ptAxisDet, ptAxisPart}}, doSumw); - registry.add("hPhiMatched", "#phi matching;#phi_{det};#phi_{part}", {HistType::kTH2F, {phiAxisDet, phiAxisPart}}, doSumw); - registry.add("hPhiMatchedPt", "#phi matching 2d;#phi;p_{T}", {HistType::kTH2F, {{400, 0, 400}, phiAxisPart}}, doSumw); - registry.add("hDeltaRMatched", "#DeltaR matching;#DeltaR_{det};#DeltaR_{part}", {HistType::kTH2F, {dRAxisDet, dRAxisPart}}, doSumw); - registry.add("hPtMatched1d", "p_{T} matching 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); - registry.add("hPtTruth2D", "p_{T} truth 2d;p_{T,part};dphip", {HistType::kTH2F, {{400, 0, 400}, phiAxisPart}}, doSumw); - registry.add("hPtTruth1D", "p_{T} truth 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); - registry.add("hDeltaRMatched1d", "#DeltaR matching 1d;#DeltaR_{part}", {HistType::kTH1F, {dRAxisPart}}, doSumw); + registry.add("hMatchedPt", "p_{T} matching 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hMatchedPtPhi", "p_{T} matching 2d;p_{T,part};#Delta#varphi", {HistType::kTH2F, {{400, 0, 400}, phiAxisPart}}, doSumw); + registry.add("hMatchedPtDeltaR", "p_{T} matching 2d;p_{T,part};#Delta R_{axis}", {HistType::kTH2F, {{400, 0, 400}, dRAxisPart}}, doSumw); + registry.add("hPtPhiTruth", "p_{T} truth 2d;p_{T,part};dphip", {HistType::kTH2F, {{400, 0, 400}, phiAxisPart}}, doSumw); + registry.add("hPtTruth", "p_{T} truth 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); registry.add("hPtResolution", "p_{T} resolution;p_{T,part};Relative Resolution", {HistType::kTH2F, {ptAxisPart, {100, -5.0, 5.0}}}, doSumw); registry.add("hPhiResolution", "#phi resolution;#p_{T,part};Resolution", {HistType::kTH2F, {ptAxisPart, {100, -7.0, 7.0}}}, doSumw); registry.add("hDeltaRResolution", "#DeltaR Resolution;p_{T,part};Resolution", {HistType::kTH2F, {ptAxisPart, {100, -0.15, 0.15}}}, doSumw); registry.add("hFullMatching", "Full 6D matching;p_{T,det};p_{T,part};#phi_{det};#phi_{part};#DeltaR_{det};#DeltaR_{part}", {HistType::kTHnSparseD, {ptAxisDet, ptAxisPart, phiAxisDet, phiAxisPart, dRAxisDet, dRAxisPart}}, doSumw); } + + if (doprocessRecoilJetsMCPMCDMatchedWeighted || doprocessRecoilJetsMCPMCDMatchedWeighted || doprocessRecoilJetsMCPMCDMatchedWeightedWithRhoSubtraction) { + registry.add("hPtTrackMatched", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); + registry.add("hPtTrackMatchedToCollisions", "Track p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}, doSumw); + registry.add("hNjetsMCP", "N jets MCP", {HistType::kTH1F, {{100, 0, 100}}}, doSumw); + registry.add("hNjetsMCPMatchedMCD", "N jets MCP matched to MCD", {HistType::kTH1F, {{100, 0, 100}}}, doSumw); + registry.add("hNjetsMCD", "N jets MCD", {HistType::kTH1F, {{100, 0, 100}}}, doSumw); + registry.add("hNjetsMCDMatchedMCP", "N jets MCD matched to MCP", {HistType::kTH1F, {{100, 0, 100}}}, doSumw); + registry.add("hPtDPhiTruth", "p_{T} truth 2d;p_{T,part};dphip", {HistType::kTH2F, {{400, 0, 400}, phiAxisPart}}, doSumw); + registry.add("hPtDeltaRTruth", "p_{T} truth 2d;p_{T,part};dr", {HistType::kTH2F, {{400, 0, 400}, dRAxisPart}}, doSumw); + registry.add("hPtTruth", "p_{T} truth 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hPtInclusiveMCP", "p_{T} matching ;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hMatchedPt", "p_{T} matching 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hMatchedPtPhi", "p_{T} matching 2d;p_{T,part};#Delta#varphi", {HistType::kTH2F, {{400, 0, 400}, phiAxisPart}}, doSumw); + registry.add("hMatchedPtDeltaR", "p_{T} matching 2d;p_{T,part};#Delta R_{axis}", {HistType::kTH2F, {{400, 0, 400}, dRAxisPart}}, doSumw); + registry.add("hPtMatchedInclusiveMCP", "p_{T} matching ;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hPtMatchedRecoilMCP", "p_{T} matching ;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hPtInclusiveMCD", "p_{T} matching ;p_{T,det}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hPtMatchedInclusiveMCD", "p_{T} matching ;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hPtMatchedRecoilMCD", "p_{T} matching ;p_{T,det}", {HistType::kTH1F, {{400, 0, 400}}}, doSumw); + registry.add("hPhiResolution", "#phi resolution;#p_{T,part};Resolution", {HistType::kTH2F, {ptAxisPart, {100, -7.0, 7.0}}}, doSumw); + registry.add("hPtMatched", "p_{T} matching;p_{T,det};p_{T,part}", {HistType::kTH2F, {ptAxisDet, ptAxisPart}}, doSumw); + registry.add("hPtResolution", "p_{T} resolution;p_{T,part};Relative Resolution", {HistType::kTH2F, {ptAxisPart, {100, -5.0, 5.0}}}, doSumw); + registry.add("hDeltaRResolution", "#DeltaR Resolution;p_{T,part};Resolution", {HistType::kTH2F, {ptAxisPart, {100, -0.15, 0.15}}}, doSumw); + registry.add("hFullMatching", "Full 6D matching;p_{T,det};p_{T,part};#phi_{det};#phi_{part};#DeltaR_{det};#DeltaR_{part}", {HistType::kTHnSparseD, {ptAxisDet, ptAxisPart, phiAxisDet, phiAxisPart, dRAxisDet, dRAxisPart}}, doSumw); + } } template @@ -227,6 +258,7 @@ struct JetHadronRecoil { double phiTT = 0; double ptTT = 0; int nTT = 0; + int nTracks = 0; double leadingPT = 0; double leadingTrackPt = 0; double leadingJetPt = 0; @@ -269,7 +301,9 @@ struct JetHadronRecoil { registry.fill(HIST("hPhiTrack"), track.phi(), weight); registry.fill(HIST("hTrack3D"), track.pt(), track.eta(), track.phi(), weight); registry.fill(HIST("hPtTrackPtHard"), track.pt() / pTHat, track.pt(), weight); + nTracks++; } + registry.fill(HIST("hNtracksRho"), nTracks, rho); if (nTT > 0) { int trigNumber = rand->Integer(nTT); phiTT = phiTTAr[trigNumber]; @@ -314,6 +348,7 @@ struct JetHadronRecoil { registry.fill(HIST("hJetEta"), jet.eta(), weight); registry.fill(HIST("hJetPhi"), jet.phi(), weight); registry.fill(HIST("hJet3D"), jet.pt() - (rho * jet.area()), jet.eta(), jet.phi(), weight); + registry.fill(HIST("hJetPtArea"), jet.pt(), jet.area(), weight); if (nTT > 0) { float dphi = RecoDecay::constrainAngle(jet.phi() - phiTT); @@ -354,7 +389,7 @@ struct JetHadronRecoil { } template - void fillHistogramsMCD(T const& jets, U const& tracks, float weight = 1.0, float rho = 0.0, float pTHat = 999.0, auto collisionID = 0) + void fillHistogramsMCD(T const& jets, U const& tracks, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) { bool isSigCol; std::vector phiTTAr; @@ -362,6 +397,7 @@ struct JetHadronRecoil { double phiTT = 0; double ptTT = 0; int nTT = 0; + int nTracks = 0; double leadingPT = 0; double leadingTrackPt = 0; double leadingJetPt = 0; @@ -404,14 +440,9 @@ struct JetHadronRecoil { registry.fill(HIST("hPhiTrack"), track.phi(), weight); registry.fill(HIST("hTrack3D"), track.pt(), track.eta(), track.phi(), weight); registry.fill(HIST("hPtTrackPtHard"), track.pt() / pTHat, track.pt(), weight); - if (track.has_mcParticle()) { - registry.fill(HIST("hPtTrackMatched"), track.pt(), weight); - auto mcParticle = track.mcParticle(); - if (mcParticle.mcCollisionId() == collisionID) { - registry.fill(HIST("hPtTrackMatchedToCollisions"), track.pt(), weight); - } - } + nTracks++; } + registry.fill(HIST("hNtracksRho"), nTracks, rho); if (nTT > 0) { int trigNumber = rand->Integer(nTT); phiTT = phiTTAr[trigNumber]; @@ -617,10 +648,11 @@ struct JetHadronRecoil { } template - void fillMatchedHistograms(T const&, U const& jetsTag, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) + void fillMatchedHistograms(T const& jetsBase, U const& jetsTag, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0, float pTHat = 999.0, auto collisionID = 0) { - for (const auto& jetTag : jetsTag) { + const auto jetsTagColl = jetsTag.sliceBy(perColJetMC, collisionID); + for (const auto& jetTag : jetsTagColl) { if (jetTag.pt() > pTHatMaxMCP * pTHat) { if (outlierRejectEvent) { return; @@ -629,12 +661,24 @@ struct JetHadronRecoil { } } - registry.fill(HIST("hPtTruth1D"), jetTag.pt(), weight); + registry.fill(HIST("hPtTruth"), jetTag.pt(), weight); + registry.fill(HIST("hPtPhiTruth"), jetTag.pt(), jetTag.phi(), weight); + } - double dR = getWTAaxisDifference(jetTag, particles); - if (jetTag.has_matchedJetGeo()) { - for (const auto& jetBase : jetTag.template matchedJetGeo_as>()) { - if (jetBase.pt() > pTHatMaxMCD * pTHat) { + for (const auto& jetBase : jetsBase) { + + if (jetBase.pt() > pTHatMaxMCD * pTHat) { + if (outlierRejectEvent) { + return; + } else { + continue; + } + } + + double dR = getWTAaxisDifference(jetBase, tracks); + if (jetBase.has_matchedJetGeo()) { + for (const auto& jetTag : jetBase.template matchedJetGeo_as>()) { + if (jetTag.pt() > pTHatMaxMCP * pTHat) { if (outlierRejectEvent) { return; } else { @@ -642,58 +686,119 @@ struct JetHadronRecoil { } } - double dRp = getWTAaxisDifference(jetBase, tracks); + double dRp = getWTAaxisDifference(jetTag, particles); registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); - registry.fill(HIST("hPhiMatched"), jetBase.phi(), jetTag.phi(), weight); registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / 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() - (rho * jetBase.area()), jetTag.pt(), jetBase.phi(), jetTag.phi(), dR, dRp, weight); - registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); - registry.fill(HIST("hDeltaRMatched1d"), dRp, weight); + registry.fill(HIST("hMatchedPt"), jetTag.pt(), weight); + registry.fill(HIST("hMatchedPtPhi"), jetTag.pt(), jetTag.phi(), weight); + registry.fill(HIST("hMatchedPtDeltaR"), jetTag.pt(), dRp, weight); } } } } template - void fillRecoilJetMatchedHistograms(T const&, U const& jetsTag, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) + void fillRecoilJetMatchedHistograms(T const& jetsBase, U const& jetsTag, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0, float pTHat = 999.0, auto collisionID = 0) { - std::vector phiTTAr; - double phiTT = 0; + std::vector phiTTArPart; + std::vector phiTTArMatched; + double phiTTPart = 0; int nTT = 0; - for (const auto& particle : particles) { - if (particle.pt() > pTHatTrackMaxMCP * pTHat) { + for (const auto& track : tracks) { + + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { + if (track.has_mcParticle()) { + registry.fill(HIST("hPtTrackMatched"), track.pt(), weight); + auto mcParticle = track.template mcParticle_as(); + if (mcParticle.mcCollisionId() == collisionID) { + nTT++; + registry.fill(HIST("hPtTrackMatchedToCollisions"), track.pt(), weight); + phiTTArMatched.push_back(track.phi()); + phiTTArPart.push_back(mcParticle.phi()); + } + } + } + } + + if (nTT > 0) { + int trigNumber = rand->Integer(nTT); + phiTTPart = phiTTArPart[trigNumber]; + } + + // + // ---- MC Detector -> MC Particle matched ---- + int nJetsMCD = 0; + int nJetsMCDMatchedMCP = 0; + + for (const auto& jetBase : jetsBase) { + + if (!jetfindingutilities::isInEtaAcceptance(jetBase, -0.9, 0.9, trackEtaMin, trackEtaMax)) { + continue; + } + + if (jetBase.pt() > pTHatMaxMCD * pTHat) { if (outlierRejectEvent) { return; } else { continue; } } - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (!pdgParticle) { - continue; - } - if ((pdgParticle->Charge() == 0.0) || (!particle.isPhysicalPrimary())) { - continue; - } - if (particle.pt() < ptTTsigMax && particle.pt() > ptTTsigMin) { - nTT++; - phiTTAr.push_back(particle.phi()); + registry.fill(HIST("hPtInclusiveMCD"), jetBase.pt(), weight); + if (jetBase.has_matchedJetGeo()) { + for (auto& jetTag : jetBase.template matchedJetGeo_as>()) { + + if (jetTag.pt() > pTHatMaxMCP * pTHat) { + if (outlierRejectEvent) { + return; + } else { + continue; + } + } + + registry.fill(HIST("hPtMatchedInclusiveMCD"), jetBase.pt(), weight); + registry.fill(HIST("hPtMatchedInclusiveMCP"), jetTag.pt(), weight); + if (nTT > 0) { + float dphip = RecoDecay::constrainAngle(jetTag.phi() - phiTTPart); + float dphi = RecoDecay::constrainAngle(jetBase.phi() - phiTTPart); + double dRp = getWTAaxisDifference(jetTag, particles); + double dR = getWTAaxisDifference(jetBase, tracks); + registry.fill(HIST("hMatchedPtPhi"), dphip, jetTag.pt(), weight); + registry.fill(HIST("hPhiResolution"), jetTag.pt(), dphip - dphi, weight); + registry.fill(HIST("hFullMatching"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), dphi, dphip, dR, dRp, weight); + if ((std::abs(dphip - o2::constants::math::PI) < 0.6)) { + registry.fill(HIST("hMatchedPt"), jetTag.pt(), weight); + registry.fill(HIST("hMatchedPtDeltaR"), dRp, jetTag.pt(), weight); + registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); + registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); + registry.fill(HIST("hDeltaRResolution"), jetTag.pt(), dRp - dR, weight); + registry.fill(HIST("hPtMatchedRecoilMCD"), jetBase.pt(), weight); + } + } + } + nJetsMCDMatchedMCP++; } + nJetsMCD++; } + registry.fill(HIST("hNjetsMCD"), nJetsMCD); + registry.fill(HIST("hNjetsMCDMatchedMCP"), nJetsMCDMatchedMCP); - if (nTT > 0) { - int trigNumber = rand->Integer(nTT); - phiTT = phiTTAr[trigNumber]; - } else { - return; - } + // + // ---- MC Particle -> MC Detector matched ---- + // - for (const auto& jetTag : jetsTag) { + const auto jetsTagColl = jetsTag.sliceBy(perColJetMC, collisionID); + int nJetsMCP = 0; + int nJetsMCPMatchedMCD = 0; + + for (const auto& jetTag : jetsTagColl) { if (jetTag.pt() > pTHatMaxMCP * pTHat) { if (outlierRejectEvent) { @@ -703,10 +808,18 @@ struct JetHadronRecoil { } } - float dphip = RecoDecay::constrainAngle(jetTag.phi() - phiTT); - double dRp = getWTAaxisDifference(jetTag, particles); - registry.fill(HIST("hPtTruth1D"), jetTag.pt(), weight); - registry.fill(HIST("hPtTruth2D"), jetTag.pt(), dphip, weight); + registry.fill(HIST("hPtInclusiveMCP"), jetTag.pt(), weight); + float dphip = 0; + if (nTT > 0) { + dphip = RecoDecay::constrainAngle(jetTag.phi() - phiTTPart); + double dRp = getWTAaxisDifference(jetTag, particles); + if ((std::abs(dphip - o2::constants::math::PI) < 0.6)) { + registry.fill(HIST("hPtTruth"), jetTag.pt(), weight); + registry.fill(HIST("hPtDPhiTruth"), jetTag.pt(), dphip, weight); + registry.fill(HIST("hPtDeltaRTruth"), jetTag.pt(), dRp, weight); + } + } + if (jetTag.has_matchedJetGeo()) { for (const auto& jetBase : jetTag.template matchedJetGeo_as>()) { if (jetBase.pt() > pTHatMaxMCD * pTHat) { @@ -716,24 +829,19 @@ struct JetHadronRecoil { continue; } } - - float dphi = RecoDecay::constrainAngle(jetBase.phi() - phiTT); - double dR = getWTAaxisDifference(jetBase, tracks); - registry.fill(HIST("hPhiMatched"), dphi, dphip, weight); - registry.fill(HIST("hPhiMatchedPt"), jetTag.pt(), dphip, weight); - registry.fill(HIST("hPhiResolution"), jetTag.pt(), dphip - dphi, weight); - registry.fill(HIST("hFullMatching"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), dphi, dphip, dR, dRp, weight); - registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); - if ((std::abs(dphip - o2::constants::math::PI) < 0.6)) { - registry.fill(HIST("hDeltaRMatched1d"), dRp, weight); - registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); - registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); - registry.fill(HIST("hDeltaRMatched"), dR, dRp, weight); - registry.fill(HIST("hDeltaRResolution"), jetTag.pt(), dRp - dR, weight); + registry.fill(HIST("hPtMatchedInclusiveMCP"), jetTag.pt(), weight); + if (nTT > 0) { + if ((std::abs(dphip - o2::constants::math::PI) < 0.6)) { + registry.fill(HIST("hPtMatchedRecoilMCP"), jetTag.pt(), weight); + } } } + nJetsMCPMatchedMCD++; } + nJetsMCP++; } + registry.fill(HIST("hNjetsMCP"), nJetsMCP); + registry.fill(HIST("hNjetsMCPMatchedMCD"), nJetsMCPMatchedMCD); } void processData(soa::Filtered::iterator const& collision, @@ -762,6 +870,8 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ()); + registry.fill(HIST("hCentOccupancy"), collision.centFT0M(), collision.trackOccupancyInTimeRange()); + registry.fill(HIST("hCentRho"), collision.centFT0M(), collision.rho()); fillHistograms(jets, tracks, 1.0, collision.rho()); } PROCESS_SWITCH(JetHadronRecoil, processDataWithRhoSubtraction, "process data with rho subtraction", false); @@ -784,7 +894,7 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillHistogramsMCD(jets, tracks, 1.0, 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); + fillHistogramsMCD(jets, tracks, 1.0, 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCD, "process MC detector level", false); @@ -806,7 +916,9 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillHistogramsMCD(jets, tracks, 1.0, collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); + registry.fill(HIST("hCentOccupancy"), collision.centFT0M(), collision.trackOccupancyInTimeRange()); + registry.fill(HIST("hCentRho"), collision.centFT0M(), collision.rho()); + fillHistogramsMCD(jets, tracks, 1.0, collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWithRhoSubtraction, "process MC detector level with rho subtraction", false); @@ -828,7 +940,7 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); - fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); + fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWeighted, "process MC detector level with event weights", false); @@ -850,7 +962,9 @@ struct JetHadronRecoil { return; } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); - fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); + registry.fill(HIST("hCentOccupancy"), collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.mcCollision().weight()); + registry.fill(HIST("hCentRho"), collision.centFT0M(), collision.rho()); + fillHistogramsMCD(jets, tracks, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWeightedWithRhoSubtraction, "process MC detector level with event weights and rho subtraction", false); @@ -862,7 +976,7 @@ struct JetHadronRecoil { if (std::abs(mccollision.posZ()) > vertexZCut) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mccollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } if (mccollision.ptHard() < pTHatMinEvent) { @@ -892,7 +1006,7 @@ struct JetHadronRecoil { if (std::abs(mccollision.posZ()) > vertexZCut) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!jetderiveddatautilities::selectCollision(mccollision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } if (mccollision.ptHard() < pTHatMinEvent) { @@ -914,229 +1028,212 @@ struct JetHadronRecoil { } PROCESS_SWITCH(JetHadronRecoil, processMCPWeighted, "process MC particle level with event weights", false); - void processJetsMCPMCDMatched(aod::JetMcCollisions::iterator const& mccollision, - soa::SmallGroups const& collisions, - soa::Filtered> const& mcdjets, - soa::Filtered const& particles, - soa::Filtered const& tracks, - soa::Filtered> const& mcpjets) + void processMCPOnTheFly(aod::JetMcCollision const& mccollision, + soa::Filtered> const& jets, + soa::Filtered const& particles) { if (std::abs(mccollision.posZ()) > vertexZCut) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (mccollision.ptHard() < pTHatMinEvent) { + return; + } + registry.fill(HIST("hZvtxSelected"), mccollision.posZ()); + fillMCPHistograms(jets, particles, 1.0, mccollision.ptHard()); + } + PROCESS_SWITCH(JetHadronRecoil, processMCPOnTheFly, "process MC particle level for on-the-fly simulations", false); + + void processMCPOnTheFlyWeighted(aod::JetMcCollision const& mccollision, + soa::Filtered> const& jets, + soa::Filtered const& particles) + { + if (std::abs(mccollision.posZ()) > vertexZCut) { return; } if (mccollision.ptHard() < pTHatMinEvent) { return; } - if (collisions.size() < 1) { + registry.fill(HIST("hZvtxSelected"), mccollision.posZ(), mccollision.weight()); + fillMCPHistograms(jets, particles, mccollision.weight(), mccollision.ptHard()); + } + PROCESS_SWITCH(JetHadronRecoil, processMCPOnTheFlyWeighted, "process MC particle level for on-the-fly simulations with event weights", false); + + void processJetsMCPMCDMatched(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, + soa::Filtered> const& mcdjets, + soa::Filtered const& tracks, + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } + if (!collision.has_mcCollision()) { + return; } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ()); - fillMatchedHistograms(mcdjets, mcpjets, tracks, particles); + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, 1.0, 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatched, "process MC matched (inc jets)", false); - void processJetsMCPMCDMatchedWithRhoSubtraction(soa::Join::iterator const& mccollision, - soa::SmallGroups const& collisions, + void processJetsMCPMCDMatchedWithRhoSubtraction(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& mcdjets, soa::Filtered const& tracks, - soa::Filtered const& particles, - soa::Filtered> const& mcpjets) + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) { - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!collision.has_mcCollision()) { return; } - if (mccollision.ptHard() < pTHatMinEvent) { + if (collision.mcCollision().ptHard() < pTHatMinEvent) { return; } - if (collisions.size() < 1) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } - } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ()); - fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, 1.0, 0.0, mccollision.ptHard()); + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, 1.0, collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatchedWithRhoSubtraction, "process MC matched (inc jets) with rho subtraction", false); - void processJetsMCPMCDMatchedWeighted(aod::JetMcCollisions::iterator const& mccollision, - soa::SmallGroups const& collisions, + void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& mcdjets, soa::Filtered const& tracks, - soa::Filtered const& particles, - soa::Filtered> const& mcpjets) + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) { - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!collision.has_mcCollision()) { return; } - if (mccollision.ptHard() < pTHatMinEvent) { + if (collision.mcCollision().ptHard() < pTHatMinEvent) { return; } - if (collisions.size() < 1) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } - } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ(), mccollision.weight()); - fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, mccollision.weight(), 0.0, mccollision.ptHard()); + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatchedWeighted, "process MC matched with event weights (inc jets)", false); - void processJetsMCPMCDMatchedWeightedWithRhoSubtraction(soa::Join::iterator const& mccollision, - soa::SmallGroups const& collisions, + void processJetsMCPMCDMatchedWeightedWithRhoSubtraction(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& mcdjets, soa::Filtered const& tracks, - soa::Filtered const& particles, - soa::Filtered> const& mcpjets) + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) { - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (!collision.has_mcCollision()) { return; } - if (mccollision.ptHard() < pTHatMinEvent) { + if (collision.mcCollision().ptHard() < pTHatMinEvent) { return; } - if (collisions.size() < 1) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } - } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ(), mccollision.weight()); - fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, mccollision.weight(), mccollision.rho(), mccollision.ptHard()); + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillMatchedHistograms(mcdjets, mcpjets, tracks, particles, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatchedWeightedWithRhoSubtraction, "process MC matched with event weights (inc jets) and rho subtraction", false); - void processRecoilJetsMCPMCDMatched(aod::JetMcCollisions::iterator const& mccollision, - soa::SmallGroups const& collisions, + void processRecoilJetsMCPMCDMatched(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& mcdjets, - soa::Filtered const& particles, soa::Filtered const& tracks, - soa::Filtered> const& mcpjets) + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) { - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (skipMBGapEvents && collision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } - if (mccollision.ptHard() < pTHatMinEvent) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - if (collisions.size() < 1) { + if (!collision.has_mcCollision()) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ(), mccollision.weight()); - fillRecoilJetMatchedHistograms(mcdjets, mcpjets, tracks, particles, 1.0, 0.0, mccollision.ptHard()); + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillRecoilJetMatchedHistograms(mcdjets, mcpjets, tracks, particles, 1.0, 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); } PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatched, "process MC matched (recoil jets)", false); - void processRecoilJetsMCPMCDMatchedWeighted(aod::JetMcCollisions::iterator const& mccollision, - soa::SmallGroups const& collisions, + void processRecoilJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& mcdjets, soa::Filtered const& tracks, - soa::Filtered const& particles, - soa::Filtered> const& mcpjets) + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) { - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (skipMBGapEvents && collision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } - if (mccollision.ptHard() < pTHatMinEvent) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - if (collisions.size() < 1) { + if (!collision.has_mcCollision()) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ(), mccollision.weight()); - fillRecoilJetMatchedHistograms(mcdjets, mcpjets, tracks, particles, mccollision.weight(), 0.0, mccollision.ptHard()); + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillRecoilJetMatchedHistograms(mcdjets, mcpjets, tracks, particles, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard(), collision.mcCollisionId()); } PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatchedWeighted, "process MC matched with event weights (recoil jets)", false); - void processRecoilJetsMCPMCDMatchedWeightedWithRhoSubtraction(soa::Join::iterator const& mccollision, - soa::SmallGroups const& collisions, + void processRecoilJetsMCPMCDMatchedWeightedWithRhoSubtraction(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& mcdjets, soa::Filtered const& tracks, - soa::Filtered const& particles, - soa::Filtered> const& mcpjets) + soa::Filtered> const& mcpjets, + JetParticlesWithOriginal const& particles) { - if (std::abs(mccollision.posZ()) > vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - if (!jetderiveddatautilities::selectMcCollision(mccollision, skipMBGapEvents, applyRCTSelections)) { + if (skipMBGapEvents && collision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } - if (mccollision.ptHard() < pTHatMinEvent) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - if (collisions.size() < 1) { + if (!collision.has_mcCollision()) { return; } - for (auto const& collision : collisions) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; } - registry.fill(HIST("hZvtxSelected"), mccollision.posZ(), mccollision.weight()); - fillRecoilJetMatchedHistograms(mcdjets, mcpjets, tracks, particles, mccollision.weight(), mccollision.rho(), mccollision.ptHard()); + registry.fill(HIST("hZvtxSelected"), collision.posZ()); + fillRecoilJetMatchedHistograms(mcdjets, mcpjets, tracks, particles, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard(), collision.mcCollisionId()); } - PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatchedWeightedWithRhoSubtraction, "process MC matched with event weights (recoil jets) and rho subtraction", false); + PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatchedWeightedWithRhoSubtraction, "process MC matched with event weights (recoil jets) with rho subtraction", false); template double getWTAaxisDifference(T const& jet, X const& /*tracks or particles*/) diff --git a/PWGJE/Tasks/jetLundPlane.cxx b/PWGJE/Tasks/jetLundPlane.cxx new file mode 100644 index 00000000000..eaa2af5b3a6 --- /dev/null +++ b/PWGJE/Tasks/jetLundPlane.cxx @@ -0,0 +1,804 @@ +// 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 jetLundPlane.cxx +/// \brief Task for jet Lund plane. Creates histograms for offline unfolding (including QA histos), and optionally tables. +/// \author Zoltan Varga + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/Core/RecoDecay.h" + +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// Mini-AOD (tables) +namespace o2::aod +{ +// Parent table: one row per collision stored in the MiniAOD +DECLARE_SOA_COLUMN(MiniCollTag, miniCollTag, uint8_t); +DECLARE_SOA_TABLE(MiniCollisions, "AOD", "MINICOLL", + MiniCollTag); + +// MiniJets -> MiniCollisions +DECLARE_SOA_INDEX_COLUMN_CUSTOM(MiniCollision, miniCollision, "MINICOLLS"); + +// Jet payload +DECLARE_SOA_COLUMN(Level, level, uint8_t); // JetLevel::Det=reco(det), JetLevel::Part=truth(part) +DECLARE_SOA_COLUMN(JetRint, jetRint, int32_t); // jet.r() as stored (int R*100) +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); + +DECLARE_SOA_TABLE(MiniJets, "AOD", "MINIJET", + MiniCollisionId, Level, JetRint, JetPt, JetEta, JetPhi); + +// MiniSplittings -> MiniJets +DECLARE_SOA_INDEX_COLUMN(MiniJet, miniJet); + +// Per-splitting observables (primary branch) +DECLARE_SOA_COLUMN(SplitId, splitId, uint16_t); +DECLARE_SOA_COLUMN(DeltaR, deltaR, float); +DECLARE_SOA_COLUMN(PtSoft, ptSoft, float); +DECLARE_SOA_COLUMN(PtHard, ptHard, float); +DECLARE_SOA_COLUMN(SoftEta, softEta, float); +DECLARE_SOA_COLUMN(SoftPhi, softPhi, float); + +DECLARE_SOA_TABLE(MiniSplittings, "AOD", "MINISPL", + MiniJetId, SplitId, DeltaR, PtSoft, PtHard, SoftEta, SoftPhi, JetPt); + +// Jet-jet matching (MC) +DECLARE_SOA_COLUMN(MatchDR, matchDR, float); +DECLARE_SOA_COLUMN(MatchRelPt, matchRelPt, float); + +DECLARE_SOA_INDEX_COLUMN_FULL(DetMiniJet, detMiniJet, int, MiniJets, "_Det"); +DECLARE_SOA_INDEX_COLUMN_FULL(PartMiniJet, partMiniJet, int, MiniJets, "_Part"); + +DECLARE_SOA_TABLE(MiniJetMatches, "AOD", "MINIMCH", + DetMiniJetId, + PartMiniJetId, + MatchDR, + MatchRelPt); +} // namespace o2::aod + +namespace +{ +constexpr float kTiny = 1e-12f; +constexpr uint64_t collisionKeyShift = 1ULL; +constexpr uint64_t partCollisionKeyTag = 1ULL; +constexpr size_t MinConstituentsForJet = 2; + +struct JetLevel { + enum Type : uint8_t { + Det = 0, + Part = 1 + }; +}; + +template +float jetRfromTable(const JetT& jet) +{ + return static_cast(jet.r()) * 0.01f; +} + +struct SplittingObs { + float deltaR{}; + float ptSoft{}; + float ptHard{}; + float kT{}; + float lnRoverDR{}; + float lnkt{}; + float z{}; + float softEta{}; + float softPhi{}; +}; + +struct SplitMatchPair { + size_t recoIdx{}; + size_t truthIdx{}; + float dR{}; +}; + +struct JetMatchInfo { + uint64_t otherKey{}; + float dR{1e9f}; + float relPt{-1.f}; + float otherPt{}; +}; + +inline float deltaPhi(float phi1, float phi2) +{ + return RecoDecay::constrainAngle(phi1 - phi2, -o2::constants::math::PI); +} + +inline float splittingMatchDistance(const SplittingObs& a, const SplittingObs& b) +{ + return std::hypot(a.softEta - b.softEta, deltaPhi(a.softPhi, b.softPhi)); +} + +std::vector buildUniqueSplittingMatches(const std::vector& recoSpl, + const std::vector& truthSpl, + float maxDR) +{ + std::vector matches; + matches.reserve(std::min(recoSpl.size(), truthSpl.size())); + + if (recoSpl.empty() || truthSpl.empty()) { + return matches; + } + + // Mutual-nearest-neighbor matching in the soft-prong (eta,phi) coordinates: + // 1) for each truth splitting, find the closest reco splitting within maxDR + // 2) for that reco splitting, find the closest truth splitting within maxDR + // 3) keep the pair only if the reco splitting points back to the original truth splitting + for (size_t truthIdx = 0; truthIdx < truthSpl.size(); ++truthIdx) { + float bestRecoDR = maxDR; + size_t bestRecoIdx = recoSpl.size(); + + for (size_t recoIdx = 0; recoIdx < recoSpl.size(); ++recoIdx) { + const float dR = splittingMatchDistance(recoSpl[recoIdx], truthSpl[truthIdx]); + if (dR < bestRecoDR) { + bestRecoDR = dR; + bestRecoIdx = recoIdx; + } + } + + if (bestRecoIdx == recoSpl.size()) { + continue; + } + + float bestTruthDR = maxDR; + size_t reverseTruthIdx = truthSpl.size(); + for (size_t candTruthIdx = 0; candTruthIdx < truthSpl.size(); ++candTruthIdx) { + const float dR = splittingMatchDistance(recoSpl[bestRecoIdx], truthSpl[candTruthIdx]); + if (dR < bestTruthDR) { + bestTruthDR = dR; + reverseTruthIdx = candTruthIdx; + } + } + + if (reverseTruthIdx == truthIdx) { + matches.push_back({bestRecoIdx, truthIdx, bestRecoDR}); + } + } + + return matches; +} + +template +std::vector buildFastJetInputs(ConstituentRangeT&& constituents, float trackPtMin) +{ + std::vector fjInputs; + fjInputs.reserve(64); + for (auto const& c : constituents) { + if (c.pt() < trackPtMin) { + continue; + } + const float mPi = o2::constants::physics::MassPiPlus; + const float e = std::sqrt(c.p() * c.p() + mPi * mPi); + fjInputs.emplace_back(c.px(), c.py(), c.pz(), e); + } + return fjInputs; +} + +std::vector primaryDeclusteringSplittings(fastjet::PseudoJet jetCA, float jetR) +{ + std::vector out; + out.reserve(32); + + fastjet::PseudoJet p1, p2; + while (jetCA.has_parents(p1, p2)) { + if (p2.perp() > p1.perp()) { + std::swap(p1, p2); + } + const float pt1 = p1.perp(); + const float pt2 = p2.perp(); + const float pt = pt1 + pt2; + if (pt <= kTiny) { + break; + } + const float z = pt2 / pt; + const float dR = p1.delta_R(p2); + const float kT = pt2 * std::sin(dR); + + if (dR > kTiny && kT > kTiny && z > kTiny) { + SplittingObs s; + s.deltaR = dR; + s.ptSoft = pt2; + s.ptHard = pt1; + s.kT = kT; + s.lnRoverDR = std::log(jetR / dR); + s.lnkt = std::log(kT); + s.z = z; + s.softEta = p2.eta(); + s.softPhi = p2.phi_std(); + out.push_back(s); + } + jetCA = p1; // follow hard branch (primary Lund) + } + return out; +} + +} // namespace + +struct JetLundPlaneUnfolding { + // Config + Configurable vertexZCut{"vertexZCut", 10.f, "|z_vtx| cut"}; + Configurable jetPtMin{"jetPtMin", 20.f, "min reco jet pT"}; + Configurable jetEtaMin{"jetEtaMin", -0.5f, "min jet eta"}; + Configurable jetEtaMax{"jetEtaMax", 0.5f, "max jet eta"}; + Configurable jetR{"jetR", 0.4f, "jet radius (must match derived tables)"}; + Configurable trackPtMin{"trackPtMin", 0.15f, "min constituent pT"}; + + Configurable nBinsJetPt{"nBinsJetPt", 200, "jet pT bins"}; + Configurable jetPtMax{"jetPtMax", 200.f, "jet pT max"}; + + Configurable nBinsLund{"nBinsLund", 120, "lund bins (lnR/DR and lnkt)"}; + Configurable lnRoverDRMin{"lnRoverDRMin", -1.f, "min ln(R/DR)"}; + Configurable lnRoverDRMax{"lnRoverDRMax", 6.f, "max ln(R/DR)"}; + Configurable lnKtMin{"lnKtMin", -6.f, "min ln(kT)"}; + Configurable lnKtMax{"lnKtMax", 6.f, "max ln(kT)"}; + + // switches (runtime) + Configurable writeMiniAOD{"writeMiniAOD", true, "write mini-AOD tables (jets, splittings, matching)"}; + + // matching knobs (applied on top of matching relations) + Configurable matchMaxDR{"matchMaxDR", 0.2f, "max ΔR between det and part jet"}; + Configurable splitMatchMaxDR{"splitMatchMaxDR", 0.1f, "max ΔR between reco and truth splittings (soft prong)"}; + Configurable matchUseRelPt{"matchUseRelPt", true, "apply relative pT compatibility cut"}; + Configurable matchMaxRelPtDiff{"matchMaxRelPtDiff", 0.5f, "max |pTdet-pTpart|/pTpart"}; + + // Registry + HistogramRegistry registry{"registry"}; + + // Mini-AOD outputs (optional) + Produces outMiniCollisions; + Produces outMiniJets; + Produces outMiniSplittings; + Produces outMiniJetMatches; + + // FastJet reclustering setup (C/A) + JetFinder reclusterer; + std::vector jetReclustered; + + void init(InitContext const&) + { + const int nbPt = nBinsJetPt.value; + const float ptMax = jetPtMax.value; + const int nbL = nBinsLund.value; + + registry.add("hEventCount", "Event counter;step;counts", HistType::kTH1F, {{10, 0.f, 10.f}}); + registry.add("hJetCountSummary", "Jet count summary;category;counts", HistType::kTH1F, {{6, 0.5f, 6.5f}}); + + // Jet spectra / matching QA + registry.add("hJetPtRecoAll", "Reco jets;p_{T}^{jet} (GeV/c);counts", HistType::kTH1F, {{nbPt, 0.f, ptMax}}); + registry.add("hJetPtRecoMatched", "Reco matched jets;p_{T}^{jet} (GeV/c);counts", HistType::kTH1F, {{nbPt, 0.f, ptMax}}); + registry.add("hJetPtRecoFake", "Reco unmatched (fake) jets;p_{T}^{jet} (GeV/c);counts", HistType::kTH1F, {{nbPt, 0.f, ptMax}}); + + registry.add("hJetPtTruthAll", "Truth jets;p_{T}^{jet} (GeV/c);counts", HistType::kTH1F, {{nbPt, 0.f, ptMax}}); + registry.add("hJetPtTruthMatched", "Truth matched jets;p_{T}^{jet} (GeV/c);counts", HistType::kTH1F, {{nbPt, 0.f, ptMax}}); + registry.add("hJetPtTruthMiss", "Truth unmatched (miss) jets;p_{T}^{jet} (GeV/c);counts", HistType::kTH1F, {{nbPt, 0.f, ptMax}}); + + // Jet pT response (1D unfolding) + registry.add("hJetPtResponse", "Jet pT response;p_{T}^{det};p_{T}^{part}", HistType::kTH2F, + {{nbPt, 0.f, ptMax}, {nbPt, 0.f, ptMax}}); + + // Lund reco / truth (3D) + registry.add("hLundReco3D", "Primary Lund (reco);ln(R/#DeltaR);ln(k_{T});p_{T}^{jet}", + HistType::kTH3F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, + {nbL, lnKtMin.value, lnKtMax.value}, + {nbPt, 0.f, ptMax}}); + + registry.add("hLundTruth3D", "Primary Lund (truth);ln(R/#DeltaR);ln(k_{T});p_{T}^{jet}", + HistType::kTH3F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, + {nbL, lnKtMin.value, lnKtMax.value}, + {nbPt, 0.f, ptMax}}); + + // 6D response for 3D unfolding: + // (det lnR/DR, det lnkt, det jetpt, part lnR/DR, part lnkt, part jetpt) + registry.add("hLundResponse6D", + "Lund response 6D;" + "ln(R/#DeltaR)_{det};ln(k_{T})_{det};p_{T}^{det};" + "ln(R/#DeltaR)_{part};ln(k_{T})_{part};p_{T}^{part}", + HistType::kTHnSparseF, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, + {nbL, lnKtMin.value, lnKtMax.value}, + {nbPt, 0.f, ptMax}, + {nbL, lnRoverDRMin.value, lnRoverDRMax.value}, + {nbL, lnKtMin.value, lnKtMax.value}, + {nbPt, 0.f, ptMax}}); + + // Early QA histograms for declustering and matching + registry.add("hNSplittingsReco", "Number of primary splittings (reco);N_{split};counts", HistType::kTH1F, {{40, -0.5f, 39.5f}}); + registry.add("hNSplittingsTruth", "Number of primary splittings (truth);N_{split};counts", HistType::kTH1F, {{40, -0.5f, 39.5f}}); + registry.add("hNSplittingsVsJetPtReco", "Reco primary splittings;#it{p}_{T}^{jet} (GeV/#it{c});N_{split}", HistType::kTH2F, {{nbPt, 0.f, ptMax}, {40, -0.5f, 39.5f}}); + registry.add("hNSplittingsVsJetPtTruth", "Truth primary splittings;#it{p}_{T}^{jet} (GeV/#it{c});N_{split}", HistType::kTH2F, {{nbPt, 0.f, ptMax}, {40, -0.5f, 39.5f}}); + + registry.add("hDeltaRReco", "Reco splitting #DeltaR;#DeltaR;counts", HistType::kTH1F, {{120, 0.f, 1.2f}}); + registry.add("hDeltaRTruth", "Truth splitting #DeltaR;#DeltaR;counts", HistType::kTH1F, {{120, 0.f, 1.2f}}); + registry.add("hLnRoverDRReco", "Reco splitting ln(R/#DeltaR);ln(R/#DeltaR);counts", HistType::kTH1F, {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}}); + registry.add("hLnRoverDRTruth", "Truth splitting ln(R/#DeltaR);ln(R/#DeltaR);counts", HistType::kTH1F, {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}}); + registry.add("hLnKtReco", "Reco splitting ln(k_{T});ln(k_{T});counts", HistType::kTH1F, {{nbL, lnKtMin.value, lnKtMax.value}}); + registry.add("hLnKtTruth", "Truth splitting ln(k_{T});ln(k_{T});counts", HistType::kTH1F, {{nbL, lnKtMin.value, lnKtMax.value}}); + registry.add("hKtReco", "Reco splitting k_{T};k_{T};counts", HistType::kTH1F, {{200, 0.f, 20.f}}); + registry.add("hKtTruth", "Truth splitting k_{T};k_{T};counts", HistType::kTH1F, {{200, 0.f, 20.f}}); + + registry.add("hJetMatchDR", "Matched jet #DeltaR;#DeltaR(det,part);counts", HistType::kTH1F, {{100, 0.f, 1.f}}); + registry.add("hJetMatchRelPt", "Matched jet relative #it{p}_{T} difference;|#it{p}_{T}^{det}-#it{p}_{T}^{part}|/#it{p}_{T}^{part};counts", HistType::kTH1F, {{100, 0.f, 2.f}}); + registry.add("hJetPtResidual", "Jet #it{p}_{T} residual;(#it{p}_{T}^{det}-#it{p}_{T}^{part})/#it{p}_{T}^{part};counts", HistType::kTH1F, {{160, -2.f, 2.f}}); + registry.add("hLnRoverDRResidual", "Splitting ln(R/#DeltaR) residual;ln(R/#DeltaR)_{det}-ln(R/#DeltaR)_{part};counts", HistType::kTH1F, {{160, -4.f, 4.f}}); + registry.add("hLnKtResidual", "Splitting ln(k_{T}) residual;ln(k_{T})_{det}-ln(k_{T})_{part};counts", HistType::kTH1F, {{160, -6.f, 6.f}}); + registry.add("hSplitMatchDR", "Matched splitting #DeltaR (soft prong);#DeltaR_{match};counts", HistType::kTH1F, {{120, 0.f, 1.2f}}); + + registry.add("hSplitTruthDen", "Truth splitting denominator;ln(R/#DeltaR);ln(k_{T})", HistType::kTH2F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, {nbL, lnKtMin.value, lnKtMax.value}}); + registry.add("hSplitTruthMatched", "Truth matched splitting numerator;ln(R/#DeltaR);ln(k_{T})", HistType::kTH2F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, {nbL, lnKtMin.value, lnKtMax.value}}); + registry.add("hSplitTruthMiss", "Truth missed splittings;ln(R/#DeltaR);ln(k_{T})", HistType::kTH2F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, {nbL, lnKtMin.value, lnKtMax.value}}); + + registry.add("hSplitRecoDen", "Reco splitting denominator;ln(R/#DeltaR);ln(k_{T})", HistType::kTH2F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, {nbL, lnKtMin.value, lnKtMax.value}}); + registry.add("hSplitRecoMatched", "Reco matched splitting numerator;ln(R/#DeltaR);ln(k_{T})", HistType::kTH2F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, {nbL, lnKtMin.value, lnKtMax.value}}); + registry.add("hSplitRecoFake", "Reco fake splittings;ln(R/#DeltaR);ln(k_{T})", HistType::kTH2F, + {{nbL, lnRoverDRMin.value, lnRoverDRMax.value}, {nbL, lnKtMin.value, lnKtMax.value}}); + + // reclusterer config + reclusterer.isReclustering = true; + reclusterer.algorithm = fastjet::cambridge_algorithm; + reclusterer.jetR = 1.0; // recluster radius for declustering tree + reclusterer.recombScheme = fastjet::E_scheme; + reclusterer.strategy = fastjet::Best; + reclusterer.areaType = fastjet::active_area; + } + + // Filters for reco jets (data or MC reco) + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut.node()); + Filter jetFilter = (aod::jet::pt > jetPtMin.node()) && + (aod::jet::eta > jetEtaMin.node()) && + (aod::jet::eta < jetEtaMax.node()) && + (aod::jet::r == nround(jetR.node() * 100.f)); + + // Type aliases + using RecoJets = soa::Join; + using DetJetsMatched = soa::Join; + using PartJetsMatched = soa::Join; + + template + bool passJetFiducial(JetT const& jet, int rWanted) const + { + return (jet.r() == rWanted) && (jet.pt() > jetPtMin.value) && (jet.eta() > jetEtaMin.value) && (jet.eta() < jetEtaMax.value); + } + + void fillJetCountSummary(int bin) + { + registry.fill(HIST("hJetCountSummary"), static_cast(bin)); + } + + // Helpers to fill Lund from a jet row + template + std::vector getPrimarySplittings(JetRowT const& jet, ConstituentTableT const&) + { + auto fjInputs = buildFastJetInputs(jet.template tracks_as(), trackPtMin.value); + if (fjInputs.size() < MinConstituentsForJet) { + return {}; + } + + jetReclustered.clear(); + fastjet::ClusterSequenceArea cs(reclusterer.findJets(fjInputs, jetReclustered)); + jetReclustered = sorted_by_pt(jetReclustered); + if (jetReclustered.empty()) { + return {}; + } + + const float rjet = jetRfromTable(jet); + return primaryDeclusteringSplittings(jetReclustered[0], rjet); + } + + void fillPrimaryLund3DFromSplittings(std::vector const& spl, float jetPt, bool isTruth, float weight = 1.f) + { + for (auto const& s : spl) { + if (isTruth) { + registry.fill(HIST("hLundTruth3D"), s.lnRoverDR, s.lnkt, jetPt, weight); + } else { + registry.fill(HIST("hLundReco3D"), s.lnRoverDR, s.lnkt, jetPt, weight); + } + } + } + + template + void fillPrimaryLund3D(JetRowT const& jet, ConstituentTableT const& constituents, bool isTruth, float weight = 1.f) + { + fillPrimaryLund3DFromSplittings(getPrimarySplittings(jet, constituents), jet.pt(), isTruth, weight); + } + + void fillSplittingQAHists(std::vector const& splittings, bool isTruth, float jetPt) + { + if (isTruth) { + registry.fill(HIST("hNSplittingsTruth"), static_cast(splittings.size())); + registry.fill(HIST("hNSplittingsVsJetPtTruth"), jetPt, static_cast(splittings.size())); + } else { + registry.fill(HIST("hNSplittingsReco"), static_cast(splittings.size())); + registry.fill(HIST("hNSplittingsVsJetPtReco"), jetPt, static_cast(splittings.size())); + } + + for (auto const& s : splittings) { + if (isTruth) { + registry.fill(HIST("hDeltaRTruth"), s.deltaR); + registry.fill(HIST("hLnRoverDRTruth"), s.lnRoverDR); + registry.fill(HIST("hLnKtTruth"), s.lnkt); + registry.fill(HIST("hKtTruth"), s.kT); + } else { + registry.fill(HIST("hDeltaRReco"), s.deltaR); + registry.fill(HIST("hLnRoverDRReco"), s.lnRoverDR); + registry.fill(HIST("hLnKtReco"), s.lnkt); + registry.fill(HIST("hKtReco"), s.kT); + } + } + } + + std::vector fillSplittingCorrectionHists(std::vector const& recoSpl, std::vector const& truthSpl) + { + for (auto const& s : truthSpl) { + registry.fill(HIST("hSplitTruthDen"), s.lnRoverDR, s.lnkt); + } + for (auto const& s : recoSpl) { + registry.fill(HIST("hSplitRecoDen"), s.lnRoverDR, s.lnkt); + } + + const auto matches = buildUniqueSplittingMatches(recoSpl, truthSpl, splitMatchMaxDR.value); + std::vector recoUsed(recoSpl.size(), false); + std::vector truthUsed(truthSpl.size(), false); + + for (const auto& m : matches) { + recoUsed[m.recoIdx] = true; + truthUsed[m.truthIdx] = true; + registry.fill(HIST("hSplitRecoMatched"), recoSpl[m.recoIdx].lnRoverDR, recoSpl[m.recoIdx].lnkt); + registry.fill(HIST("hSplitTruthMatched"), truthSpl[m.truthIdx].lnRoverDR, truthSpl[m.truthIdx].lnkt); + registry.fill(HIST("hSplitMatchDR"), m.dR); + } + + for (size_t i = 0; i < truthSpl.size(); ++i) { + if (!truthUsed[i]) { + registry.fill(HIST("hSplitTruthMiss"), truthSpl[i].lnRoverDR, truthSpl[i].lnkt); + } + } + for (size_t i = 0; i < recoSpl.size(); ++i) { + if (!recoUsed[i]) { + registry.fill(HIST("hSplitRecoFake"), recoSpl[i].lnRoverDR, recoSpl[i].lnkt); + } + } + return matches; + } + + // DATA / RECO PROCESSING + void processData(soa::Filtered::iterator const&, + soa::Filtered const& jets, + aod::JetTracks const& tracks) + { + registry.fill(HIST("hEventCount"), 0.5); + + int miniCollIdx = -1; + if (writeMiniAOD.value) { + outMiniCollisions(static_cast(0)); + miniCollIdx = outMiniCollisions.lastIndex(); + } + for (auto const& jet : jets) { + registry.fill(HIST("hJetPtRecoAll"), jet.pt()); + auto spl = getPrimarySplittings(jet, tracks); + fillPrimaryLund3DFromSplittings(spl, jet.pt(), /*isTruth*/ false); + fillSplittingQAHists(spl, /*isTruth*/ false, jet.pt()); + + if (writeMiniAOD.value) { + outMiniJets(miniCollIdx, /*level*/ JetLevel::Det, jet.r(), jet.pt(), jet.eta(), jet.phi()); + const int miniJetIdx = outMiniJets.lastIndex(); + + uint16_t sid = 0; + for (auto const& s : spl) { + outMiniSplittings(miniJetIdx, sid++, s.deltaR, s.ptSoft, s.ptHard, s.softEta, s.softPhi, jet.pt()); + } + } + } + } + PROCESS_SWITCH(JetLundPlaneUnfolding, processData, "Reco/data Lund + jet spectra", true); + + // MC PROCESSING (det + part + response) + + void processMC(DetJetsMatched const& detJets, + PartJetsMatched const& partJets, + aod::JetCollisions const&, + aod::JetTracks const& tracks, + aod::JetParticles const& particles) + { + registry.fill(HIST("hEventCount"), 1.5); + + const int rWanted = static_cast(std::lround(jetR.value * 100.f)); + std::unordered_map truthMatchedById; + std::unordered_map> truthSplittingsById; + std::unordered_map truthBestDet; + std::unordered_set detSplittingsWritten; + std::unordered_set truthSplittingsWritten; + auto h6 = registry.get(HIST("hLundResponse6D")); + + // Transient maps used only during this task execution to avoid duplicating + // MiniCollision / MiniJet rows and to translate framework-local indices into + // merge-safe MiniAOD row indices. + std::unordered_map detMiniCollByKey; + std::unordered_map partMiniCollByKey; + std::unordered_map detJetToMiniJetIdx; + std::unordered_map partJetToMiniJetIdx; + + // --- Truth pass --- + // Fill inclusive truth histograms, cache truth splittings, write all accepted + // truth jets to MiniJets, and determine the best detector candidate for each truth jet. + for (auto const& partJet : partJets) { + if (!passJetFiducial(partJet, rWanted)) { + continue; + } + + registry.fill(HIST("hJetPtTruthAll"), partJet.pt()); + fillJetCountSummary(4); + + const uint64_t truthJetKey = partJet.globalIndex(); + auto spl = getPrimarySplittings(partJet, particles); + truthSplittingsById[truthJetKey] = spl; + + fillPrimaryLund3DFromSplittings(spl, partJet.pt(), /*isTruth*/ true); + fillSplittingQAHists(spl, /*isTruth*/ true, partJet.pt()); + + if (writeMiniAOD.value) { + const uint64_t partCollKey = + (static_cast(partJet.mcCollisionId()) << collisionKeyShift) | partCollisionKeyTag; + int partMiniCollIdx = -1; + auto collIt = partMiniCollByKey.find(partCollKey); + if (collIt == partMiniCollByKey.end()) { + outMiniCollisions(static_cast(0)); + partMiniCollIdx = outMiniCollisions.lastIndex(); + partMiniCollByKey.emplace(partCollKey, partMiniCollIdx); + } else { + partMiniCollIdx = collIt->second; + } + + outMiniJets(partMiniCollIdx, /*level*/ JetLevel::Part, partJet.r(), partJet.pt(), partJet.eta(), partJet.phi()); + partJetToMiniJetIdx[truthJetKey] = outMiniJets.lastIndex(); + } + + if (!partJet.has_matchedJetGeo()) { + continue; + } + + JetMatchInfo bestDet{}; + bool foundDet = false; + for (auto const& candDetJet : partJet.template matchedJetGeo_as()) { + if (!passJetFiducial(candDetJet, rWanted)) { + continue; + } + + const float dR = std::hypot(candDetJet.eta() - partJet.eta(), + deltaPhi(candDetJet.phi(), partJet.phi())); + if (dR > matchMaxDR.value) { + continue; + } + + const float rel = std::abs(candDetJet.pt() - partJet.pt()) / std::max(partJet.pt(), kTiny); + if (matchUseRelPt.value && rel > matchMaxRelPtDiff.value) { + continue; + } + + if (!foundDet || dR < bestDet.dR) { + bestDet.otherKey = candDetJet.globalIndex(); + bestDet.dR = dR; + bestDet.relPt = rel; + bestDet.otherPt = candDetJet.pt(); + foundDet = true; + } + } + if (foundDet) { + truthBestDet[truthJetKey] = bestDet; + } + } + + // --- Detector loop --- + // Write all accepted detector jets to MiniJets. A final matched pair is accepted only + // if the detector jet and truth jet are mutual best matches under the same cuts. + for (auto const& detJet : detJets) { + if (!passJetFiducial(detJet, rWanted)) { + continue; + } + + registry.fill(HIST("hJetPtRecoAll"), detJet.pt()); + fillJetCountSummary(1); + + const uint64_t detJetKey = detJet.globalIndex(); + auto detSpl = getPrimarySplittings(detJet, tracks); + fillPrimaryLund3DFromSplittings(detSpl, detJet.pt(), /*isTruth*/ false); + fillSplittingQAHists(detSpl, /*isTruth*/ false, detJet.pt()); + + if (writeMiniAOD.value) { + const uint64_t detCollKey = + (static_cast(detJet.collisionId()) << collisionKeyShift); + int detMiniCollIdx = -1; + auto collIt = detMiniCollByKey.find(detCollKey); + if (collIt == detMiniCollByKey.end()) { + outMiniCollisions(static_cast(0)); + detMiniCollIdx = outMiniCollisions.lastIndex(); + detMiniCollByKey.emplace(detCollKey, detMiniCollIdx); + } else { + detMiniCollIdx = collIt->second; + } + + outMiniJets(detMiniCollIdx, /*level*/ JetLevel::Det, detJet.r(), detJet.pt(), detJet.eta(), detJet.phi()); + detJetToMiniJetIdx[detJetKey] = outMiniJets.lastIndex(); + } + + if (!detJet.has_matchedJetGeo()) { + registry.fill(HIST("hJetPtRecoFake"), detJet.pt()); + fillJetCountSummary(3); + continue; + } + + JetMatchInfo bestTruth{}; + bool foundMatch = false; + std::vector bestPartSpl; + + for (auto const& candPartJet : detJet.template matchedJetGeo_as()) { + if (!passJetFiducial(candPartJet, rWanted)) { + continue; + } + + const float dR = std::hypot(detJet.eta() - candPartJet.eta(), + deltaPhi(detJet.phi(), candPartJet.phi())); + if (dR > matchMaxDR.value) { + continue; + } + + const float rel = std::abs(detJet.pt() - candPartJet.pt()) / std::max(candPartJet.pt(), kTiny); + if (matchUseRelPt.value && rel > matchMaxRelPtDiff.value) { + continue; + } + + if (!foundMatch || dR < bestTruth.dR) { + const uint64_t candTruthKey = candPartJet.globalIndex(); + bestTruth.otherKey = candTruthKey; + bestTruth.dR = dR; + bestTruth.relPt = rel; + bestTruth.otherPt = candPartJet.pt(); + + auto splIt = truthSplittingsById.find(candTruthKey); + if (splIt != truthSplittingsById.end()) { + bestPartSpl = splIt->second; + } else { + bestPartSpl = getPrimarySplittings(candPartJet, particles); + truthSplittingsById[candTruthKey] = bestPartSpl; + } + foundMatch = true; + } + } + + if (!foundMatch) { + registry.fill(HIST("hJetPtRecoFake"), detJet.pt()); + fillJetCountSummary(3); + continue; + } + + const auto reverseIt = truthBestDet.find(bestTruth.otherKey); + if (reverseIt == truthBestDet.end() || reverseIt->second.otherKey != detJetKey) { + registry.fill(HIST("hJetPtRecoFake"), detJet.pt()); + fillJetCountSummary(3); + continue; + } + + const float bestDR = bestTruth.dR; + const float bestRelPt = bestTruth.relPt; + const uint64_t bestPartId = bestTruth.otherKey; + const float bestPartPt = bestTruth.otherPt; + + registry.fill(HIST("hJetPtRecoMatched"), detJet.pt()); + fillJetCountSummary(2); + registry.fill(HIST("hJetPtTruthMatched"), bestPartPt); + fillJetCountSummary(5); + registry.fill(HIST("hJetPtResponse"), detJet.pt(), bestPartPt); + registry.fill(HIST("hJetMatchDR"), bestDR); + registry.fill(HIST("hJetMatchRelPt"), bestRelPt); + registry.fill(HIST("hJetPtResidual"), (detJet.pt() - bestPartPt) / std::max(bestPartPt, kTiny)); + truthMatchedById[bestPartId] = true; + + if (writeMiniAOD.value) { + auto detIdxIt = detJetToMiniJetIdx.find(detJetKey); + auto partIdxIt = partJetToMiniJetIdx.find(bestPartId); + if (detIdxIt != detJetToMiniJetIdx.end() && partIdxIt != partJetToMiniJetIdx.end()) { + const int detMiniJetIdx = detIdxIt->second; + const int partMiniJetIdx = partIdxIt->second; + + outMiniJetMatches(detMiniJetIdx, partMiniJetIdx, bestDR, bestRelPt); + + if (detSplittingsWritten.insert(detJetKey).second) { + uint16_t sidTmp = 0; + for (auto const& s : detSpl) { + outMiniSplittings(detMiniJetIdx, sidTmp++, s.deltaR, s.ptSoft, s.ptHard, s.softEta, s.softPhi, detJet.pt()); + } + } + + if (truthSplittingsWritten.insert(bestPartId).second) { + uint16_t sid = 0; + for (auto const& s : bestPartSpl) { + outMiniSplittings(partMiniJetIdx, sid++, s.deltaR, s.ptSoft, s.ptHard, s.softEta, s.softPhi, bestPartPt); + } + } + } + } + + const auto splitMatches = fillSplittingCorrectionHists(detSpl, bestPartSpl); + + // Fill the 6D response and residual QA using the unique geometric splitting matches + for (const auto& m : splitMatches) { + const auto& detS = detSpl[m.recoIdx]; + const auto& partS = bestPartSpl[m.truthIdx]; + double x[6] = {detS.lnRoverDR, detS.lnkt, detJet.pt(), + partS.lnRoverDR, partS.lnkt, bestPartPt}; + h6->Fill(x); + registry.fill(HIST("hLnRoverDRResidual"), detS.lnRoverDR - partS.lnRoverDR); + registry.fill(HIST("hLnKtResidual"), detS.lnkt - partS.lnkt); + } + } + + // --- Final truth pass for misses --- + for (auto const& partJet : partJets) { + if (!passJetFiducial(partJet, rWanted)) { + continue; + } + + const uint64_t truthJetKey = partJet.globalIndex(); + if (!truthMatchedById[truthJetKey]) { + registry.fill(HIST("hJetPtTruthMiss"), partJet.pt()); + fillJetCountSummary(6); + } + } + } + PROCESS_SWITCH(JetLundPlaneUnfolding, processMC, "MC det+part + responses", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGJE/Tasks/jetLundReclustering.cxx b/PWGJE/Tasks/jetLundReclustering.cxx index b78c6f2b6ef..95b5b027931 100644 --- a/PWGJE/Tasks/jetLundReclustering.cxx +++ b/PWGJE/Tasks/jetLundReclustering.cxx @@ -23,17 +23,17 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include #include #include #include -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/PseudoJet.hh" +#include #include +#include #include #include diff --git a/PWGJE/Tasks/jetMatchingQA.cxx b/PWGJE/Tasks/jetMatchingQA.cxx index 6770d42e47e..eac3b3cf4bf 100644 --- a/PWGJE/Tasks/jetMatchingQA.cxx +++ b/PWGJE/Tasks/jetMatchingQA.cxx @@ -17,8 +17,8 @@ #include "PWGJE/DataModel/Jet.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include +#include #include #include #include diff --git a/PWGJE/Tasks/jetOutlierQA.cxx b/PWGJE/Tasks/jetOutlierQA.cxx index a41610c952e..d0d802a95a8 100644 --- a/PWGJE/Tasks/jetOutlierQA.cxx +++ b/PWGJE/Tasks/jetOutlierQA.cxx @@ -17,11 +17,9 @@ #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/JetSubtraction.h" - -#include "Common/Core/RecoDecay.h" #include +#include #include #include #include @@ -29,17 +27,14 @@ #include #include -#include #include -#include -#include #include -#include +#include +#include #include #include #include -#include #include #include @@ -418,7 +413,7 @@ struct JetOutlierQATask { } PROCESS_SWITCH(JetOutlierQATask, processJetsAmbiguous, "jet finder QA mcd with weighted events", false); - void processCollisionsBC(soa::Join const& collisions, + void processCollisionsBC(soa::Join const& collisions, aod::JetMcCollisions const&) { // @@ -510,7 +505,7 @@ struct JetOutlierQATask { } PROCESS_SWITCH(JetOutlierQATask, processCollisionsBC, "jet finder QA outliers", false); - void processTracksBC(soa::Filtered> const& collisions, + void processTracksBC(soa::Filtered> const& collisions, soa::Join const&, aod::JetMcCollisions const& collisionsMC, aod::JetTracksMCD const& tracks, diff --git a/PWGJE/Tasks/jetPlanarFlow.cxx b/PWGJE/Tasks/jetPlanarFlow.cxx index 1edf34d8396..480dcc69a53 100644 --- a/PWGJE/Tasks/jetPlanarFlow.cxx +++ b/PWGJE/Tasks/jetPlanarFlow.cxx @@ -12,6 +12,7 @@ // task for planar flow analysis // /// \author Nima Zardoshti +/// \author Wenhui Feng // #include "JetDerivedDataUtilities.h" @@ -23,18 +24,21 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include +#include +#include #include #include #include #include -#include "fastjet/contrib/AxesDefinition.hh" +#include +#include #include #include #include @@ -88,6 +92,8 @@ struct JetPlanarFlowTask { Produces jetTable; Produces jetTableMC; + HistogramRegistry registry; + // event level configurables Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; @@ -99,11 +105,15 @@ struct JetPlanarFlowTask { Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum track eta"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum track eta"}; Configurable trackDRMax{"trackDRMax", 0.8, "maximum track distance from jet axis"}; + Configurable planarTrackPtMin{"planarTrackPtMin", 5.0, "minimum constituent pT in planar flow calculation"}; + Configurable relatedTrackptlow{"relatedTrackptlow", 0.15, "after rotation related track pT low edge"}; + Configurable relatedTrackpthigh{"relatedTrackpthigh", 5.0, "after rotation related track pT high edge"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // jet level configurables + Configurable jetsRadius{"selectedJetsRadius", 0.4, "resolution parameter for histograms without radius"}; Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; @@ -128,13 +138,58 @@ struct JetPlanarFlowTask { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); particleSelection = static_cast(particleSelections); precisionMask = 0xFFFFFC00; + + AxisSpec centralityAxis = {1200, -10., 110., "Centrality"}; + AxisSpec trackPtAxis = {200, -0.5, 199.5, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec trackEtaAxis = {200, -1.0, 1.0, "#eta"}; + AxisSpec trackphiAxis = {160, -1.0, 7.0, "#varphi"}; + AxisSpec jetPtAxis = {200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPtAxisRhoAreaSub = {400, -200., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetEtaAxis = {200, -1.0, 1.0, "#eta"}; + + if (doprocessJetsQCData || doprocessJetsQCMCD) { + registry.add("h_collisions", "number of events;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h_collisions_zvertex", "position of collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}); + registry.add("h2_centrality_collisions", "event status vs. centrality;entries;centrality", {HistType::kTH2F, {centralityAxis, {4, 0.0, 4.0}}}); + registry.add("h_track_pt", "track #it{p}_{T} ; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}); + registry.add("h2_track_eta_track_phi", "track eta vs. track phi; #eta; #phi; counts", {HistType::kTH2F, {trackEtaAxis, trackphiAxis}}); + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h_jet_eta", "jet eta;#eta; counts", {HistType::kTH1F, {jetEtaAxis}}); + registry.add("h_jet_phi", "jet phi;#phi; counts", {HistType::kTH1F, {trackphiAxis}}); + registry.add("h_leadingjet_pt", "leading jet pT;#it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH1F, {jetPtAxis}}); + registry.add("h2_jet_pt_jet_ntracks", "jet #it{p}_{T,jet} vs. N_{jet tracks}; #it{p}_{T,jet} (GeV/#it{c}); N_{jet, tracks}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h2_leadingjet_pt_ntracks", "leading jet pT vs. N_{jet tracks}; #it{p}_{T,jet} (GeV/#it{c}); N_{jet, tracks}", {HistType::kTH2F, {jetPtAxis, {200, -0.5, 199.5}}}); + registry.add("h2_jet_pt_track_pt", "jet #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, {jetPtAxis, trackPtAxis}}); + registry.add("h2_leadingjet_pt_track_pt", "leading jet #it{p}_{T,jet} vs. #it{p}_{T,track}; leading #it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxis, trackPtAxis}}); + } + + if (doprocessChargedJetsData || doprocessChargedJetsMCD) { + registry.add("h2_leadingjet_pt_planarflow", "leading jet #it{p}_{T,jet} vs. planar flow; #it{p}_{T,jet} (GeV/#it{c}); planar flow", {HistType::kTH2F, {jetPtAxis, {50, 0, 1}}}); + registry.add("h2_jetpt_Nsub2to1CASD", "leading jet #it{p}_{T,jet} vs. Nsubjettiness tau2/tua1; #it{p}_{T,jet} (GeV/#it{c}); tau2 / tau1", {HistType::kTH2F, {jetPtAxis, {50, 0, 1}}}); + registry.add("h2_trackDR_Nsub2to1CASD", "track Delta R vs. Nsubjettiness tau2/tua1; track to jet axis Delta R ; tau2 / tau1", {HistType::kTH2F, {{100, 0, 1}, {50, 0, 1}}}); + registry.add("h2_jetDR_Nsub2to1CASD", "jet axis Delta R vs. Nsubjettiness tau2/tua1; jet reclustering axis Delta R ; tau2 / tau1", {HistType::kTH2F, {{100, 0, 1}, {50, 0, 1}}}); + registry.add("h3_jet_pt_jetDR_Nsub2to1CASD", "leading jet #it{p}_{T,jet} vs. jet axis Delta R vs. Nsubjettiness tau2/tua1; #it{p}_{T,jet} (GeV/#it{c}); jet reclustering axis Delta R ; tau2 / tau1", {HistType::kTH3F, {jetPtAxis, {100, 0, 1}, {50, 0, 1}}}); + registry.add("h3_track_pt_track_theta_track_phi_incone_beforeRot", "track #it{p}_{T} vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {trackPtAxis, {80, -0.5, 3.5}, {140, -1.0, 7.0}}}); + registry.add("h3_track_pt_track_theta_track_phi_outcone_beforeRot", "track #it{p}_{T} vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {trackPtAxis, {80, -0.5, 3.5}, {140, -1.0, 7.0}}}); + registry.add("h3_track_pt_track_theta_track_phi_incone_afterRot", "track #it{p}_{T} vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {trackPtAxis, {80, -0.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h3_track_pt_track_theta_track_phi_outcone_afterRot", "track #it{p}_{T} vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {trackPtAxis, {80, -0.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h3_track_pt_thetaSinphi_track_thetaCosphi_afterRot", "track #it{p}_{T} vs. track theta * Sin phi vs. track theta * Cos phi; #it{p}_{T,track} (GeV/#it{c}); #theta * Sin #phi; #theta * Cos #phi", {HistType::kTH3F, {trackPtAxis, {140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h2_track_thetaSinphi_track_thetaCosphi_incone_lowpt_afterRot", "track theta * Sin phi vs. track theta * Cos phi; #theta * Sin #phi; #theta * Cos #phi", {HistType::kTH2F, {{140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h2_track_thetaSinphi_track_thetaCosphi_incone_highpt_afterRot", "track theta * Sin phi vs. track theta * Cos phi; #theta * Sin #phi; #theta * Cos #phi", {HistType::kTH2F, {{140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h2_track_thetaSinphi_track_thetaCosphi_outcone_lowpt_afterRot", "track theta * Sin phi vs. track theta * Cos phi; #theta * Sin #phi; #theta * Cos #phi", {HistType::kTH2F, {{140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h2_track_thetaSinphi_track_thetaCosphi_outcone_highpt_afterRot", "track theta * Sin phi vs. track theta * Cos phi; #theta * Sin #phi; #theta * Cos #phi", {HistType::kTH2F, {{140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_2prolong_lowpt", "jet axis Delta R vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {{50, 0, 1}, {140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_2prolong_highpt", "jet axis Delta R vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {{50, 0, 1}, {140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_1prolong_lowpt", "jet axis Delta R vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {{50, 0, 1}, {140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + registry.add("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_1prolong_highpt", "jet axis Delta R vs. track theta vs. track phi; #it{p}_{T,track} (GeV/#it{c}); #theta ; #phi", {HistType::kTH3F, {{50, 0, 1}, {140, -3.5, 3.5}, {140, -3.5, 3.5}}}); + } } // jet pT, tau2/tau1, jetdR, track pt, phi', eta', dR, isInJet Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); - template - void fillHistograms(T const& collision, U const& jet, V const& tracks) + template + void fillHistograms(Tcoll const& collision, Tjet const& jet, Ttrk const& tracks) { std::vector nSubCASDResults = jetsubstructureutilities::getNSubjettiness(jet, tracks, tracks, tracks, 2, fastjet::contrib::CA_Axes(), true, zCutSD, betaSD); @@ -166,8 +221,11 @@ struct JetPlanarFlowTask { } } - for (auto& jetConstituent : jet.template tracks_as()) { + for (auto& jetConstituent : jet.template tracks_as()) { + if (jetConstituent.pt() < planarTrackPtMin) { + continue; // calculate flow eigenvector using high pT constituents + } double normalisation_factor = (1.0 / (jetConstituent.energy() * jet.mass())); float pxRotated = (rotationMatrix[0][0] * jetConstituent.px()) + (rotationMatrix[0][1] * jetConstituent.py()) + (rotationMatrix[0][2] * jetConstituent.pz()); float pyRotated = (rotationMatrix[1][0] * jetConstituent.px()) + (rotationMatrix[1][1] * jetConstituent.py()) + (rotationMatrix[1][2] * jetConstituent.pz()); @@ -185,6 +243,18 @@ struct JetPlanarFlowTask { float eigenValue2 = 0.5 * (principleMatrixTrace - TMath::Sqrt(principleMatrixTrace * principleMatrixTrace - 4 * PrinciplMatrixDeterminant)); auto planarFlow = (4.0 * PrinciplMatrixDeterminant) / (principleMatrixTrace * principleMatrixTrace); + auto NsubTau2to1 = nSubCASDResults[2] / nSubCASDResults[1]; + + float jetPt = 0.0; + if constexpr (isAreaSubtracted) { + jetPt = jet.pt() - (jet.area() * collision.rho()); + } else { + jetPt = jet.pt(); + } + registry.fill(HIST("h2_leadingjet_pt_planarflow"), jetPt, planarFlow); + registry.fill(HIST("h2_jetpt_Nsub2to1CASD"), jetPt, NsubTau2to1); + registry.fill(HIST("h2_jetDR_Nsub2to1CASD"), nSubCASDResults[0], NsubTau2to1); + registry.fill(HIST("h3_jet_pt_jetDR_Nsub2to1CASD"), jetPt, nSubCASDResults[0], NsubTau2to1); float eigenVector1[2]; float eigenVector2[2]; @@ -205,8 +275,9 @@ struct JetPlanarFlowTask { } float theta = TMath::ATan(eigenVector1[1] / eigenVector1[0]); - if (theta < 0) + if (theta < 0) { theta += TMath::Pi(); + } rotationMatrix2D[0][0] = TMath::Cos(theta); rotationMatrix2D[0][1] = TMath::Sin(theta); rotationMatrix2D[1][0] = -TMath::Sin(theta); @@ -249,7 +320,7 @@ struct JetPlanarFlowTask { break; } } - + float thetaOrigin = TMath::ACos(track.pz() / TMath::Sqrt((track.pt() * track.pt()) + (track.pz() * track.pz()))); float pxRotatedPrincipleAxis = 0.0; float pyRotatedPrincipleAxis = 0.0; float pxRotated = (rotationMatrix[0][0] * track.px()) + (rotationMatrix[0][1] * track.py()) + (rotationMatrix[0][2] * track.pz()); @@ -263,26 +334,145 @@ struct JetPlanarFlowTask { trackPhiRotVector.push_back(o2::math_utils::detail::truncateFloatFraction(TMath::ATan2(pyRotatedPrincipleAxis, pxRotatedPrincipleAxis), precisionMask)); trackDRVector.push_back(o2::math_utils::detail::truncateFloatFraction(jetutilities::deltaR(jet, track), precisionMask)); trackIsInJetVector.push_back(isInJet); + + float thetaRot = TMath::ACos(pzRotated / TMath::Sqrt((pxRotated * pxRotated) + (pyRotated * pyRotated) + (pzRotated * pzRotated))); + float phiRot = TMath::ATan2(pyRotatedPrincipleAxis, pxRotatedPrincipleAxis); + + registry.fill(HIST("h2_trackDR_Nsub2to1CASD"), trackDR, NsubTau2to1); + registry.fill(HIST("h3_track_pt_thetaSinphi_track_thetaCosphi_afterRot"), track.pt(), thetaRot * TMath::Sin(phiRot), thetaRot * TMath::Cos(phiRot)); + if (isInJet) { + registry.fill(HIST("h3_track_pt_track_theta_track_phi_incone_beforeRot"), track.pt(), thetaOrigin, track.phi()); + registry.fill(HIST("h3_track_pt_track_theta_track_phi_incone_afterRot"), track.pt(), thetaRot, phiRot); + if (track.pt() > relatedTrackptlow && track.pt() < relatedTrackpthigh) { // low pt tracks, no contribute to rotation axis + registry.fill(HIST("h2_track_thetaSinphi_track_thetaCosphi_incone_lowpt_afterRot"), thetaRot * TMath::Sin(phiRot), thetaRot * TMath::Cos(phiRot)); + } else if (track.pt() > relatedTrackpthigh) { + registry.fill(HIST("h2_track_thetaSinphi_track_thetaCosphi_incone_highpt_afterRot"), thetaRot * TMath::Sin(phiRot), thetaRot * TMath::Cos(phiRot)); + } + } else { + registry.fill(HIST("h3_track_pt_track_theta_track_phi_outcone_beforeRot"), track.pt(), thetaOrigin, track.phi()); + registry.fill(HIST("h3_track_pt_track_theta_track_phi_outcone_afterRot"), track.pt(), thetaRot, phiRot); + if (track.pt() > relatedTrackptlow && track.pt() < relatedTrackpthigh) { // low pt tracks, no contribute to rotation axis + registry.fill(HIST("h2_track_thetaSinphi_track_thetaCosphi_outcone_lowpt_afterRot"), thetaRot * TMath::Sin(phiRot), thetaRot * TMath::Cos(phiRot)); + } else if (track.pt() > relatedTrackpthigh) { + registry.fill(HIST("h2_track_thetaSinphi_track_thetaCosphi_outcone_highpt_afterRot"), thetaRot * TMath::Sin(phiRot), thetaRot * TMath::Cos(phiRot)); + } + } + + if (NsubTau2to1 < 0.3) { + if (track.pt() > relatedTrackptlow && track.pt() < relatedTrackpthigh) { + registry.fill(HIST("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_2prolong_lowpt"), nSubCASDResults[0], thetaRot * TMath::Sin(track.phi()), thetaRot * TMath::Cos(track.phi())); + } else if (track.pt() > relatedTrackpthigh) { + registry.fill(HIST("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_2prolong_highpt"), nSubCASDResults[0], thetaRot * TMath::Sin(track.phi()), thetaRot * TMath::Cos(track.phi())); + } + } else if (NsubTau2to1 > 0.6) { + if (track.pt() > relatedTrackptlow && track.pt() < relatedTrackpthigh) { + registry.fill(HIST("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_1prolong_lowpt"), nSubCASDResults[0], thetaRot * TMath::Sin(track.phi()), thetaRot * TMath::Cos(track.phi())); + } else if (track.pt() > relatedTrackpthigh) { + registry.fill(HIST("h3_track_thetaSinPhi_track_thetaCosphi_jetDR_1prolong_highpt"), nSubCASDResults[0], thetaRot * TMath::Sin(track.phi()), thetaRot * TMath::Cos(track.phi())); + } + } } if (isMc) { - jetTableMC(o2::math_utils::detail::truncateFloatFraction(jet.pt(), precisionMask), o2::math_utils::detail::truncateFloatFraction(planarFlow, precisionMask), o2::math_utils::detail::truncateFloatFraction(nSubCASDResults[2] / nSubCASDResults[1], precisionMask), o2::math_utils::detail::truncateFloatFraction(nSubCASDResults[0], precisionMask), trackPtVector, trackPhiRotVector, trackThetaRotVector, trackDRVector, trackIsInJetVector); + jetTableMC(o2::math_utils::detail::truncateFloatFraction(jetPt, precisionMask), o2::math_utils::detail::truncateFloatFraction(planarFlow, precisionMask), o2::math_utils::detail::truncateFloatFraction(nSubCASDResults[2] / nSubCASDResults[1], precisionMask), o2::math_utils::detail::truncateFloatFraction(nSubCASDResults[0], precisionMask), trackPtVector, trackPhiRotVector, trackThetaRotVector, trackDRVector, trackIsInJetVector); } else { - float jetPt = 0.0; - if constexpr (isAreaSubtracted) { - jetPt = jet.pt() - (jet.area() * collision.rho()); - } else { - jetPt = jet.pt(); - } jetTable(o2::math_utils::detail::truncateFloatFraction(jetPt, precisionMask), o2::math_utils::detail::truncateFloatFraction(planarFlow, precisionMask), o2::math_utils::detail::truncateFloatFraction(nSubCASDResults[2] / nSubCASDResults[1], precisionMask), o2::math_utils::detail::truncateFloatFraction(nSubCASDResults[0], precisionMask), trackPtVector, trackPhiRotVector, trackThetaRotVector, trackDRVector, trackIsInJetVector); } } + template + void fillJetQCHistograms(Tjet const& jet, bool isjetlead = false, float weight = 1.0) + { + if (jet.r() == round(jetsRadius * 100.0f)) { + 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("h2_jet_pt_jet_ntracks"), jet.pt(), jet.tracksIds().size(), weight); + if (isjetlead) { + registry.fill(HIST("h_leadingjet_pt"), jet.pt(), weight); + registry.fill(HIST("h2_leadingjet_pt_ntracks"), jet.pt(), jet.tracksIds().size(), weight); + } + } + + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); + if (isjetlead) { + registry.fill(HIST("h2_leadingjet_pt_track_pt"), jet.pt(), constituent.pt(), weight); + } + } + } + void processDummy(aod::JetTracks const&) { } PROCESS_SWITCH(JetPlanarFlowTask, processDummy, "Dummy process function turned on by default", true); + void processJetsQCData(soa::Filtered::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const& tracks) + { + registry.fill(HIST("h_collisions"), 0.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); + registry.fill(HIST("h_collisions_zvertex"), collision.posZ()); + + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + registry.fill(HIST("h_track_pt"), track.pt()); + registry.fill(HIST("h2_track_eta_track_phi"), track.eta(), track.phi()); + } + + bool isjetlead = true; + for (auto const& jet : jets) { + + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax) || jet.pt() < jetPtMin) { + continue; + } + fillJetQCHistograms(jet, isjetlead); + isjetlead = false; + } + } + PROCESS_SWITCH(JetPlanarFlowTask, processJetsQCData, "charged jet QC data ", true); + + void processJetsQCMCD(soa::Filtered::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const& tracks) + { + registry.fill(HIST("h_collisions"), 0.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); + registry.fill(HIST("h_collisions_zvertex"), collision.posZ()); + + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + registry.fill(HIST("h_track_pt"), track.pt()); + registry.fill(HIST("h2_track_eta_track_phi"), track.eta(), track.phi()); + } + + bool isjetlead = true; + for (auto const& jet : jets) { + + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax) || jet.pt() < jetPtMin) { + continue; + } + fillJetQCHistograms(jet, isjetlead); + isjetlead = false; + } + } + PROCESS_SWITCH(JetPlanarFlowTask, processJetsQCMCD, "charged jet QC MCD ", false); + void processChargedJetsData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::JetTracks const& tracks) diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index 4c14536f776..c48fad2f35c 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -13,27 +13,30 @@ /// \author Yuto Nishida /// \brief Task for measuring the dependence of the jet shape function rho(r) on the distance r from the jet axis. -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include @@ -43,13 +46,15 @@ using namespace o2::framework::expressions; struct JetShapeTask { - Configurable nBinsNSigma{"nBinsNSigma", 101, "Number of nsigma bins"}; - Configurable nSigmaMin{"nSigmaMin", -10.1f, "Min value of nsigma"}; - Configurable nSigmaMax{"nSigmaMax", 10.1f, "Max value of nsigma"}; + Configurable nBinsNSigma{"nBinsNSigma", 100, "Number of nsigma bins"}; + Configurable nSigmaMin{"nSigmaMin", -10.0f, "Min value of nsigma"}; + Configurable nSigmaMax{"nSigmaMax", 10.0f, "Max value of nsigma"}; Configurable nBinsPForDedx{"nBinsPForDedx", 700, "Number of p bins"}; Configurable nBinsPForBeta{"nBinsPForBeta", 500, "Number of pT bins"}; Configurable nBinsTpcDedx{"nBinsTpcDedx", 500, "Number of DEdx bins"}; Configurable nBinsTofBeta{"nBinsTofBeta", 350, "Number of Beta bins"}; + Configurable dcaxyMin{"dcaxyMin", -1.0f, "Min value of dcaXY"}; + Configurable dcaxyMax{"dcaxyMax", 1.0f, "Max value of dcaXY"}; Configurable pMax{"pMax", 8.0f, "Max value of p"}; Configurable ptMax{"ptMax", 6.0f, "Max value of pT"}; Configurable jetPtMinForCut{"jetPtMinForCut", 0.0f, "Minimum value of jet pT cut"}; @@ -58,11 +63,14 @@ struct JetShapeTask { Configurable centralityMaxForCut{"centralityMaxForCut", 100.0f, "Maximum value of the jet pT cut"}; Configurable jetShapeFuncMax{"jetShapeFuncMax", 300, "Maximum value of JetShapeFunction"}; Configurable nBinsJetShapeFunc{"nBinsJetShapeFunc", 900, "Number of JetShapeFunction bins"}; - Configurable nBinsP{"nBinsP", 80, "Number of p bins"}; - Configurable nBinsPt{"nBinsPt", 60, "Number of pT bins"}; + Configurable nBinsDcaxyForData{"nBinsDcaxyForData", 400, "Number of DcaXY bins for data"}; + Configurable nBinsDcaxyForMc{"nBinsDcaxyForMc", 400, "Number of DcaXY bins for mc data"}; + Configurable nBinsP{"nBinsP", 40, "Number of p bins"}; + Configurable nBinsPt{"nBinsPt", 30, "Number of pT bins"}; + Configurable nBinsPtForDca{"nBinsPtForDca", 15, "Number of pT bins for dcaXY"}; Configurable nBinsJetPt{"nBinsJetPt", 10, "Number of jet pT bins"}; Configurable nBinsPForCut{"nBinsPForCut", 30, "Number of p track bins"}; - Configurable nBinsCentrality{"nBinsCentrality", 20, "Number of centrality bins"}; + Configurable nBinsCentrality{"nBinsCentrality", 10, "Number of centrality bins"}; Configurable nBinsDistance{"nBinsDistance", 7, "Number of distance bins"}; Configurable distanceMax{"distanceMax", 0.7f, "Max value of distance"}; Configurable nSigmaTofCut{"nSigmaTofCut", 2.0f, "Number of sigma cut for TOF PID"}; @@ -79,11 +87,10 @@ struct JetShapeTask { {"tofPi", "tofPi", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, {"tpcPr", "tpcPr", {HistType::kTH2F, {{nBinsP, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, {"tofPr", "tofPr", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, - {"tpcDedx", "tpcDedx", {HistType::kTHnSparseD, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}}}}, - {"tofBeta", "tofBeta", {HistType::kTH2F, {{nBinsPForBeta, 0, pMax}, {nBinsTofBeta, 0.4, 1.1}}}}, + {"tpcDedx", "tpcDedx", {HistType::kTHnSparseD, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"tofBeta", "tofBeta", {HistType::kTHnSparseD, {{nBinsPForBeta, 0, pMax}, {nBinsTofBeta, 0.4, 1.1}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"pVsPtForPr", "pVsPtForPr", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"pVsPtForPi", "pVsPtPi", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"tofMass", "tofMass", {HistType::kTH1F, {{90, 0, 3}}}}, {"trackPhi", "trackPhi", {HistType::kTH1F, {{80, -1, 7}}}}, {"trackEta", "trackEta", {HistType::kTH1F, {{100, -1, 1}}}}, {"trackTpcNClsCrossedRows", "trackTpcNClsCrossedRows", {HistType::kTH1F, {{50, 0, 200}}}}, @@ -107,6 +114,10 @@ struct JetShapeTask { {"jetpVsPtForPi", "jetpVsPtPi", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"pVsPtForPrOutOfJet", "pVsPtForPrOutOfJet", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"pVsPtForPiOutOfJet", "pVsPtPionOutOfJet", {HistType::kTHnSparseD, {{nBinsP, 0, pMax}, {nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"jetDcaPr", "jetDcaPr", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"jetDcaPi", "jetDcaPi", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsDistance, 0, distanceMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"dcaPrOutOfJet", "dcaPrOutOfJet", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"dcaPiOutOfJet", "dcaPiOutOfJet", {HistType::kTHnSparseD, {{nBinsPtForDca, 0, ptMax}, {nBinsDcaxyForData, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"jetPt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}}, {"jetEta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"jetPhi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, @@ -114,23 +125,29 @@ struct JetShapeTask { {"rho", "rho", {HistType::kTH1F, {{120, 0, 300}}}}, {"ptCorr", "Corrected jet pT; p_{T}^{corr} (GeV/c); Counts", {HistType::kTH1F, {{200, 0, 200}}}}, {"ptCorrVsDistance", "ptcorr_vs_distance", {HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}}}, - {"distanceVsTrackpt", "trackpt_vs_distance", {HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}}}, {"jetDistanceVsTrackpt", "trackpt_vs_distance_injet", {HistType::kTH2F, {{70, 0, 0.7}, {100, 0, 100}}}}, {"ptSum", "ptSum", {HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc, 0, jetShapeFuncMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptSumBg1", "ptSumBg1", {HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc, 0, jetShapeFuncMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptSumBg2", "ptSumBg2", {HistType::kTHnSparseD, {{14, 0, 0.7}, {nBinsJetShapeFunc, 0, jetShapeFuncMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"event/vertexz", ";Vtx_{z} (cm);Entries", {HistType::kTH1F, {{100, -20, 20}}}}, - {"eventCounter", "eventCounter", {HistType::kTH1F, {{1, 0, +1, ""}}}}, + {"eventCounterJetShape", "eventCounterJetShape", {HistType::kTH1F, {{1, 0, +1, ""}}}}, + {"eventCounterJet", "eventCounterJet", {HistType::kTH1F, {{1, 0, +1, ""}}}}, + {"eventCounterInc", "eventCounterInc", {HistType::kTH1F, {{1, 0, +1, ""}}}}, + {"eventCounterMc", "eventCounterMc", {HistType::kTH1F, {{1, 0, +1, ""}}}}, {"ptVsCentrality", "ptvscentrality", {HistType::kTH2F, {{100, 0, 100}, {300, 0, 300}}}}, {"ptResolution", "ptResolution", {HistType::kTH2F, {{nBinsPt, 0, ptMax}, {100, -1.0, +1.0}}}}, {"mcCentralityReco", "mcCentralityReco", {HistType::kTH1F, {{100, 0, 100}}}}, {"mcCentralitySim", "mcCentralitySim", {HistType::kTH1F, {{100, 0, 100}}}}, - {"ptHistogramPion", "ptHistogramPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramKaon", "ptHistogramKaon", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, - {"ptHistogramProton", "ptHistogramProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"ptHistogramPion", "ptHistogramPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"ptHistogramKaon", "ptHistogramKaon", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"ptHistogramProton", "ptHistogramProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptHistogramPionTof", "ptHistogramPionTof", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptHistogramKaonTof", "ptHistogramKaonTof", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptHistogramProtonTof", "ptHistogramProtonTof", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"dcaDecayPion", "dcaDecayPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"dcaDecayProton", "dcaDecayProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"dcaMaterialPion", "dcaMaterialPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, + {"dcaMaterialProton", "dcaMaterialProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsDcaxyForMc, dcaxyMin, dcaxyMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptGeneratedPion", "ptGeneratedPion", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptGeneratedKaon", "ptGeneratedKaon", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}, {"ptGeneratedProton", "ptGeneratedProton", {HistType::kTHnSparseD, {{nBinsPt, 0, ptMax}, {nBinsJetPt, jetPtMinForCut, jetPtMaxForCut}, {nBinsCentrality, centralityMinForCut, centralityMaxForCut}}}}}}; @@ -153,7 +170,7 @@ struct JetShapeTask { // for ppi production Configurable etaTrUp{"etaTrUp", 0.7f, "maximum track eta"}; - Configurable dcaxyMax{"dcaxyMax", 2.0f, "maximum DCA xy"}; + Configurable dcaxyCutMax{"dcaxyCutMax", 2.0f, "maximum DCA xy"}; Configurable chi2ItsMax{"chi2ItsMax", 15.0f, "its chi2 cut"}; Configurable chi2TpcMax{"chi2TpcMax", 4.0f, "tpc chi2 cut"}; Configurable nclItsMin{"nclItsMin", 2.0f, "its # of cluster cut"}; @@ -161,7 +178,8 @@ struct JetShapeTask { Configurable nclcrossTpcMin{"nclcrossTpcMin", 70.0f, "tpc # of crossedRows cut"}; Configurable mcRapidityMax{"mcRapidityMax", 0.5f, "maximum mctrack y"}; Configurable epsilon{"epsilon", 1e-6, "standard for aboid division of zero"}; - Configurable maxDeltaEtaSafe{"maxDeltaEtaSafe", 2.0f, "maximum track eta for cut"}; + Configurable maxDeltaEtaSafe{"maxDeltaEtaSafe", 0.9f, "maximum track eta for cut"}; + Configurable nSigmaMaxForDcaxy{"nSigmaMaxForDcaxy", 4.0f, "maximum nSigma for DCAxy"}; 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"}; @@ -227,8 +245,16 @@ struct JetShapeTask { Filter collisionFilter = nabs(aod::collision::posZ) < vertexZCut; Filter mcCollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; + using FullTrackInfo = soa::Join; + void processJetShape(soa::Filtered>::iterator const& collision, aod::JetTracks const& tracks, soa::Join const& jets) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + + registry.fill(HIST("eventCounterJetShape"), 0.5); + size_t nBins = distanceCategory->size() - 1; float maxDistance = distanceCategory->at(nBins); @@ -273,7 +299,9 @@ struct JetShapeTask { } for (const auto& track : tracks) { - + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } float trkPt = track.pt(); float trkPhi = track.phi(); float trkEta = track.eta(); @@ -367,12 +395,12 @@ struct JetShapeTask { PROCESS_SWITCH(JetShapeTask, processJetShape, "JetShape", false); - void processJetProductionRatio(soa::Filtered>::iterator const& collision, soa::Join const& tracks, soa::Join const& jets) + void processJetProductionRatio(soa::Filtered>::iterator const& collision, soa::Join const& tracks, FullTrackInfo const&, soa::Join const& jets) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - + registry.fill(HIST("eventCounterJet"), 0.5); registry.fill(HIST("event/vertexz"), collision.posZ()); float rho = collision.rho(); @@ -402,13 +430,18 @@ struct JetShapeTask { {jet.pt(), jet.eta(), jet.phi(), ptCorr, phiBg1, phiBg2}); } - for (const auto& track : tracks) { + for (const auto& jetTrack : tracks) { + if (!jetderiveddatautilities::selectTrack(jetTrack, trackSelection)) { + continue; + } + + auto track = jetTrack.track_as(); if (std::abs(track.eta()) > etaTrUp) continue; if (track.tpcNClsCrossedRows() < nclcrossTpcMin) continue; - if (std::abs(track.dcaXY()) > dcaxyMax) + if (std::abs(track.dcaXY()) > dcaxyCutMax) continue; if (track.itsChi2NCl() > chi2ItsMax) continue; @@ -442,6 +475,9 @@ struct JetShapeTask { bool isTpcPiRange = (tpcPi > tpcNSigmaPiMin && tpcPi < tpcNSigmaPiMax); bool isTpcPrRange = (tpcPr > tpcNSigmaPrMin && tpcPr < tpcNSigmaPrMax); + float nSigmaSqPr = tpcPr * tpcPr + tofPr * tofPr; + float nSigmaSqPi = tpcPi * tpcPi + tofPi * tofPi; + for (const auto& jet : cachedJets) { float dEta = trkEta - jet.eta; @@ -458,9 +494,20 @@ struct JetShapeTask { float distBg2 = std::sqrt(dEta * dEta + deltaPhiBg2 * deltaPhiBg2); // --- Background Fill --- - if (distBg1 < jetR || distBg2 < jetR) { + if (distBg1 < distanceMax || distBg2 < distanceMax) { registry.fill(HIST("tpcDedxOutOfJet"), trkP, tpcSig); + // dcaXY + if (track.hasTOF()) { + if (nSigmaSqPr < nSigmaMaxForDcaxy) { + registry.fill(HIST("dcaPrOutOfJet"), trkPt, track.dcaXY(), jet.ptCorr, centrality); + } + + if (nSigmaSqPi < nSigmaMaxForDcaxy) { + registry.fill(HIST("dcaPiOutOfJet"), trkPt, track.dcaXY(), jet.ptCorr, centrality); + } + } + if (hasTofPi) { registry.fill(HIST("tpcTofPiOutOfJet"), trkP, tpcPi, jet.ptCorr, centrality); if (isTpcPiRange) { @@ -480,6 +527,17 @@ struct JetShapeTask { registry.fill(HIST("jetTpcDedx"), trkP, tpcSig, distance); registry.fill(HIST("jetTofBeta"), trkP, beta); + // dcaXY + if (track.hasTOF()) { + if (nSigmaSqPr < nSigmaMaxForDcaxy) { + registry.fill(HIST("jetDcaPr"), trkPt, track.dcaXY(), distance, jet.ptCorr, centrality); + } + + if (nSigmaSqPi < nSigmaMaxForDcaxy) { + registry.fill(HIST("jetDcaPi"), trkPt, track.dcaXY(), distance, jet.ptCorr, centrality); + } + } + if (hasTofPr) { registry.fill(HIST("jetTpcTofPr"), trkP, tpcPr, distance, jet.ptCorr, centrality); if (isTpcPrRange) { @@ -496,14 +554,23 @@ struct JetShapeTask { } } } - PROCESS_SWITCH(JetShapeTask, processJetProductionRatio, - "production ratio around jets", false); + PROCESS_SWITCH(JetShapeTask, processJetProductionRatio, "production ratio around jets", false); - void processInclusiveProductionRatio(soa::Filtered>::iterator const& collision, soa::Join const& tracks) + void processInclusiveProductionRatio(soa::Filtered::iterator const& collision, soa::Join const& tracks, FullTrackInfo const&) { - + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + registry.fill(HIST("eventCounterJet"), 0.5); // tracks conditions - for (const auto& track : tracks) { + for (const auto& jetTrack : tracks) { + + if (!jetderiveddatautilities::selectTrack(jetTrack, trackSelection)) { + continue; + } + + auto track = jetTrack.track_as(); + registry.fill(HIST("trackTpcNClsCrossedRows"), track.tpcNClsCrossedRows()); registry.fill(HIST("trackDcaXY"), track.dcaXY()); registry.fill(HIST("trackItsChi2NCl"), track.itsChi2NCl()); @@ -517,7 +584,7 @@ struct JetShapeTask { continue; if (track.tpcNClsCrossedRows() < nclcrossTpcMin) continue; - if (std::abs(track.dcaXY()) > dcaxyMax) + if (std::abs(track.dcaXY()) > dcaxyCutMax) continue; if (track.itsChi2NCl() > chi2ItsMax) continue; @@ -529,11 +596,12 @@ struct JetShapeTask { continue; // PID check - registry.fill(HIST("tofMass"), track.mass()); registry.fill(HIST("tpcPi"), track.p(), track.tpcNSigmaPi()); registry.fill(HIST("tofPi"), track.pt(), track.tofNSigmaPi()); registry.fill(HIST("tpcPr"), track.p(), track.tpcNSigmaPr()); registry.fill(HIST("tofPr"), track.pt(), track.tofNSigmaPr()); + registry.fill(HIST("tpcDedx"), track.p(), track.tpcSignal(), collision.centFT0M()); + registry.fill(HIST("tofBeta"), track.p(), track.beta(), collision.centFT0M()); if (std::abs(track.tofNSigmaPr()) < nSigmaTofCut) { registry.fill(HIST("tpcTofPr"), track.p(), track.tpcNSigmaPr(), collision.centFT0M()); @@ -551,19 +619,20 @@ struct JetShapeTask { } } } - PROCESS_SWITCH(JetShapeTask, processInclusiveProductionRatio, - "inclusive Production ratio", false); + PROCESS_SWITCH(JetShapeTask, processInclusiveProductionRatio, "inclusive Production ratio", false); - void processReco( - soa::Filtered>::iterator const& collision, - soa::Join const& tracks, aod::ChargedMCDetectorLevelJets const& jets, aod::McParticles const& mcParticles) + void processReco(soa::Filtered>::iterator const& collision, soa::Join const& tracks, aod::ChargedMCDetectorLevelJets const& jets, aod::McParticles const& mcParticles) { - (void)mcParticles; + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } - registry.fill(HIST("eventCounter"), 0.5); + (void)mcParticles; float centrality = collision.centFT0M(); float rho = collision.rho(); + + registry.fill(HIST("eventCounterMc"), 0.5); registry.fill(HIST("mcCentralityReco"), centrality); struct CachedJet { @@ -576,13 +645,18 @@ struct JetShapeTask { cachedJets.reserve(jets.size()); for (const auto& jet : jets) { - registry.fill(HIST("jetPt"), jet.pt()); - float mcdPtCorr = jet.pt() - rho * jet.area(); cachedJets.push_back({jet.pt(), jet.eta(), jet.phi(), mcdPtCorr}); + registry.fill(HIST("jetPt"), jet.pt()); } + // reco track loop for (const auto& track : tracks) { + + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + if (!track.has_mcParticle()) continue; @@ -590,7 +664,7 @@ struct JetShapeTask { continue; if (track.tpcNClsCrossedRows() < nclcrossTpcMin) continue; - if (std::abs(track.dcaXY()) > dcaxyMax) + if (std::abs(track.dcaXY()) > dcaxyCutMax) continue; if (track.itsChi2NCl() > chi2ItsMax) continue; @@ -604,9 +678,15 @@ struct JetShapeTask { auto mcParticle = track.mcParticle(); registry.fill(HIST("ptResolution"), track.pt(), track.pt() - mcParticle.pt()); - if (!mcParticle.isPhysicalPrimary() || std::fabs(mcParticle.y()) >= mcRapidityMax) + if (std::fabs(mcParticle.y()) >= mcRapidityMax) continue; + const int producedByDecay = 4; + + bool isPrimary = mcParticle.isPhysicalPrimary(); + bool isSecondDecay = !isPrimary && (mcParticle.getProcess() == producedByDecay); + bool isSecondMaterial = !isPrimary && !isSecondDecay; + int pdg = std::abs(mcParticle.pdgCode()); bool isPion = (pdg == PDG_t::kPiPlus); bool isKaon = (pdg == PDG_t::kKPlus); @@ -635,57 +715,112 @@ struct JetShapeTask { if (deltaR > distanceMax) continue; - // TPC (All matched) - if (isPion) - registry.fill(HIST("ptHistogramPion"), mcParticle.pt(), jet.ptCorr, centrality); - else if (isKaon) - registry.fill(HIST("ptHistogramKaon"), mcParticle.pt(), jet.ptCorr, centrality); - else if (isProton) - registry.fill(HIST("ptHistogramProton"), mcParticle.pt(), jet.ptCorr, centrality); - - // TOF (Required) - if (hasTof) { + if (isPrimary) { + // Tracking if (isPion) - registry.fill(HIST("ptHistogramPionTof"), mcParticle.pt(), jet.ptCorr, centrality); + registry.fill(HIST("ptHistogramPion"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); else if (isKaon) - registry.fill(HIST("ptHistogramKaonTof"), mcParticle.pt(), jet.ptCorr, centrality); + registry.fill(HIST("ptHistogramKaon"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); else if (isProton) - registry.fill(HIST("ptHistogramProtonTof"), mcParticle.pt(), jet.ptCorr, centrality); + registry.fill(HIST("ptHistogramProton"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); + + // TOF matched + if (hasTof) { + if (isPion) + registry.fill(HIST("ptHistogramPionTof"), mcParticle.pt(), jet.ptCorr, centrality); + else if (isKaon) + registry.fill(HIST("ptHistogramKaonTof"), mcParticle.pt(), jet.ptCorr, centrality); + else if (isProton) + registry.fill(HIST("ptHistogramProtonTof"), mcParticle.pt(), jet.ptCorr, centrality); + } + } else { // Secondary + if (isSecondDecay) { + // from Decay + if (isPion) + registry.fill(HIST("dcaDecayPion"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); + else if (isProton) + registry.fill(HIST("dcaDecayProton"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); + } else if (isSecondMaterial) { + // from Material + if (isPion) + registry.fill(HIST("dcaMaterialPion"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); + else if (isProton) + registry.fill(HIST("dcaMaterialProton"), mcParticle.pt(), track.dcaXY(), jet.ptCorr, centrality); + } } } } } PROCESS_SWITCH(JetShapeTask, processReco, "process reconstructed simulation information", true); - void processSim(soa::Join::iterator const& mcCollision, aod::ChargedMCParticleLevelJets const& mcpjets, aod::McParticles const& mcParticles) + void processSim(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::ChargedMCParticleLevelJets const& mcpjets, aod::JetParticles const& mcParticles) { + if (std::abs(mcCollision.posZ()) > vertexZCut) { + return; + } - float centrality = mcCollision.centFT0M(); + if (collisions.size() == 0) { + return; + } + + // --- centrality --- + float centrality = collisions.begin().centFT0M(); registry.fill(HIST("mcCentralitySim"), centrality); + const float maxR2 = distanceMax * distanceMax; + + // --- loop over MC particles only once --- + for (const auto& mcParticle : mcParticles) { + + // --- early cuts on particle --- + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + + if (std::abs(mcParticle.y()) > mcRapidityMax) { + continue; + } - for (const auto& mcpjet : mcpjets) { + int absPdg = std::abs(mcParticle.pdgCode()); + if (absPdg != PDG_t::kPiPlus && + absPdg != PDG_t::kKPlus && + absPdg != PDG_t::kProton) { + continue; + } - for (const auto& mcParticle : mcParticles) { + const float partPt = mcParticle.pt(); + const float partEta = mcParticle.eta(); + const float partPhi = mcParticle.phi(); - float dEta = mcParticle.eta() - mcpjet.eta(); - float dPhi = std::abs(mcParticle.phi() - mcpjet.phi()); + // --- loop over jets --- + for (const auto& mcpjet : mcpjets) { + // --- delta eta cut first --- + float dEta = partEta - mcpjet.eta(); + if (std::abs(dEta) > distanceMax) { + continue; + } + + // --- delta phi --- + float dPhi = std::abs(partPhi - mcpjet.phi()); if (dPhi > o2::constants::math::PI) { dPhi = o2::constants::math::TwoPI - dPhi; } - float deltaR = std::sqrt(dEta * dEta + dPhi * dPhi); - if (deltaR > distanceMax) { + // --- delta R^2 --- + float dR2 = dEta * dEta + dPhi * dPhi; + if (dR2 > maxR2) { continue; } - if (mcParticle.isPhysicalPrimary() && std::fabs(mcParticle.y()) < mcRapidityMax) { - if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) - registry.fill(HIST("ptGeneratedPion"), mcParticle.pt(), mcpjet.pt(), centrality); - if (std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus) - registry.fill(HIST("ptGeneratedKaon"), mcParticle.pt(), mcpjet.pt(), centrality); - if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton) - registry.fill(HIST("ptGeneratedProton"), mcParticle.pt(), mcpjet.pt(), centrality); + const float jetPt = mcpjet.pt(); + + // --- histogram fill --- + if (absPdg == PDG_t::kPiPlus) { + registry.fill(HIST("ptGeneratedPion"), partPt, jetPt, centrality); + } else if (absPdg == PDG_t::kKPlus) { + registry.fill(HIST("ptGeneratedKaon"), partPt, jetPt, centrality); + } else if (absPdg == PDG_t::kProton) { + registry.fill(HIST("ptGeneratedProton"), partPt, jetPt, centrality); } } } diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index 6a2fbe52ed6..bd055c36f2a 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -19,15 +19,16 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include +#include #include +#include #include #include #include +#include #include #include @@ -48,6 +49,7 @@ struct JetSpectraCharged { HistogramRegistry registry; Configurable selectedJetsRadius{"selectedJetsRadius", 0.2, "resolution parameter for histograms without radius"}; + Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable centralityMin{"centralityMin", -999.0, "minimum centrality"}; @@ -61,6 +63,7 @@ struct JetSpectraCharged { 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 simPtRef{"simPtRef", 10.0, "reference pT for the back-calculation of pTHat from the event weight"}; Configurable pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value of pTHat"}; Configurable jetPtMax{"jetPtMax", 200., "set jet pT bin max"}; Configurable jetEtaMin{"jetEtaMin", -0.7, "minimum jet pseudorapidity"}; @@ -77,6 +80,7 @@ struct JetSpectraCharged { 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 skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events; jet-level rejection can also be applied at the jet finder level for jets only, here rejection is applied for collision and track process functions for the first time, and on jets in case it was set to false at the jet finder level"}; Configurable checkLeadConstituentPtForMcpJets{"checkLeadConstituentPtForMcpJets", false, "flag to choose whether particle level jets should have their lead track pt above leadingConstituentPtMin to be accepted; off by default, as leadingConstituentPtMin cut is only applied on MCD jets for the Pb-Pb analysis using pp MC anchored to Pb-Pb for the response matrix"}; + Configurable isMCGenOnly{"isMCGenOnly", false, "analysis is run over mcGen only"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -105,11 +109,6 @@ struct JetSpectraCharged { AxisSpec jetPtAxisRhoAreaSub = {400, -200., 200., "#it{p}_{T} (GeV/#it{c})"}; AxisSpec jetEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; - if (doprocessTracksQC || doprocessTracksQCWeighted) { - registry.add("h_track_pt", "track #it{p}_{T} ; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}, doSumw2); - registry.add("h2_track_eta_track_phi", "track eta vs. track phi; #eta; #phi; counts", {HistType::kTH2F, {trackEtaAxis, phiAxis}}, doSumw2); - } - if (doprocessCollisions || doprocessCollisionsWeighted) { registry.add("h_collisions", "number of events;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, doSumw2); registry.get(HIST("h_collisions"))->GetXaxis()->SetBinLabel(1, "allColl"); @@ -153,7 +152,7 @@ struct JetSpectraCharged { } registry.add("h2_centrality_mccollisions", "mc event status vs. centrality;entries;centrality", {HistType::kTH2F, {centralityAxis, {4, 0.0, 4.0}}}, doSumw2); } - if (doprocessSpectraMCP || doprocessSpectraMCPWeighted || doprocessMCCollisions || doprocessMCCollisionsWeighted) { + if (doprocessMCCollisions || doprocessMCCollisionsWeighted) { registry.add("h_mccollisions_zvertex", "position of mc collision ;#it{Z} (cm)", {HistType::kTH1F, {{300, -15.0, 15.0}}}, doSumw2); } @@ -263,6 +262,7 @@ struct JetSpectraCharged { if (doprocessJetsMatchedAreaSub || doprocessJetsMatchedAreaSubWeighted) { registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcdetaconstraint", "corr pT mcd vs. corr cpT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcpetaconstraint", "corr pT mcd vs. corr cpT mcp;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}, doSumw2); + registry.add("h2_jet_pt_mcd_rhoareasubtracted_jet_pt_mcp_matchedgeo_mcdetaconstraint", "UEsub pT mcd vs. raw pT mcp;#it{p}_{T,jet}^{mcd} - #rho#it{A} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxis}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_rhoareasubtracted", "jet mcp corr pT vs. corr delta pT / jet mcp corr pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); (#it{p}_{T,jet}^{mcp} (GeV/#it{c}) - #it{p}_{T,jet}^{mcd} (GeV/#it{c})) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_rhoareasubtracted", "jet mcd corr pT vs. corr delta pT / jet mcd corr pt;#it{p}_{T,jet}^{mcd} (GeV/#it{c}); (#it{p}_{T,jet}^{mcd} (GeV/#it{c}) - #it{p}_{T,jet}^{mcp} (GeV/#it{c})) / #it{p}_{T,jet}^{mcd} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_rhoareasubtracted", "jet mcp corr pT vs. jet mcd corr pT / jet mcp corr pt;#it{p}_{T,jet}^{mcp} (GeV/#it{c}); #it{p}_{T,jet}^{mcd} (GeV/#it{c}) / #it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {1000, -5.0, 5.0}}}, doSumw2); @@ -317,6 +317,13 @@ struct JetSpectraCharged { template bool applyMCCollisionCuts(TMCColl const& mccollision, TCollisions const& collisions, bool fillHistograms = false, bool isWeighted = false, float eventWeight = 1.0) { + if (isMCGenOnly) { + if (fillHistograms) { + registry.fill(HIST("h_mccollisions"), 0.5); + } + return true; + } // if isMCGenOnly is true, skip MC selection and accept all of them + float centrality = -1.0; // checkCentFT0M ? centrality = mccollision.centFT0M() : centrality = mccollision.centFT0C(); centrality = mccollision.centFT0M(); @@ -352,7 +359,7 @@ struct JetSpectraCharged { bool centralityIsGood = false; bool occupancyIsGood = false; if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { hasSel8Coll = true; } if ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -364,7 +371,7 @@ struct JetSpectraCharged { } } else { for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { hasSel8Coll = true; } if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -425,7 +432,7 @@ struct JetSpectraCharged { registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight); } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return false; } if (fillHistograms) { @@ -459,9 +466,8 @@ struct JetSpectraCharged { } template - void fillJetHistograms(TJets const& jet, float centrality, float weight = 1.0) + void fillJetHistograms(TJets const& jet, float centrality, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -483,9 +489,8 @@ struct JetSpectraCharged { } template - void fillJetAreaSubHistograms(TJets const& jet, float centrality, float rho, float weight = 1.0) + void fillJetAreaSubHistograms(TJets const& jet, float centrality, float rho, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -512,9 +517,8 @@ struct JetSpectraCharged { } template - void fillMCPHistograms(TJets const& jet, float weight = 1.0) + void fillMCPHistograms(TJets const& jet, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -534,9 +538,8 @@ struct JetSpectraCharged { } template - void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0) + void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -555,9 +558,8 @@ struct JetSpectraCharged { } template - void fillEventWiseConstituentSubtractedHistograms(TJets const& jet, float centrality, float weight = 1.0) + void fillEventWiseConstituentSubtractedHistograms(TJets const& jet, float centrality, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -567,17 +569,9 @@ struct JetSpectraCharged { } } - template - void fillTrackHistograms(TTracks const& track, float weight = 1.0) - { - registry.fill(HIST("h_track_pt"), track.pt(), weight); - registry.fill(HIST("h2_track_eta_track_phi"), track.eta(), track.phi(), weight); - } - template - void fillMatchedHistograms(TBase const& jetMCD, float weight = 1.0) + void fillMatchedHistograms(TBase const& jetMCD, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jetMCD.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { return; } @@ -668,15 +662,14 @@ struct JetSpectraCharged { } template - void fillGeoMatchedAreaSubHistograms(TBase const& jetMCD, float rho, float mcrho = 0.0, float weight = 1.0) + void fillGeoMatchedAreaSubHistograms(TBase const& jetMCD, float rho, float mcrho = 0.0, float weight = 1.0, float pTHat = 999.0) { - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jetMCD.pt() > pTHatMaxMCD * pTHat) { return; } if (jetMCD.has_matchedJetGeo()) { for (const auto& jetMCP : jetMCD.template matchedJetGeo_as>()) { - if (jetMCP.pt() > pTHatMaxMCD * pTHat) { + if (jetMCP.pt() > pTHatMaxMCP * pTHat) { continue; } if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { @@ -685,6 +678,7 @@ struct JetSpectraCharged { double dcorrpt = corrBasejetpt - corrTagjetpt; if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcd_rhoareasubtracted_jet_pt_mcp_matchedgeo_mcdetaconstraint"), corrBasejetpt, jetMCP.pt(), weight); registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_rhoareasubtracted"), corrBasejetpt, dcorrpt / corrBasejetpt, weight); } if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -697,42 +691,6 @@ struct JetSpectraCharged { } } - void processTracksQC(soa::Filtered::iterator const& collision, - soa::Filtered> const& tracks) - { - if (!applyCollisionCuts(collision)) { - return; - } - - for (auto const& track : tracks) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { - continue; - } - fillTrackHistograms(track); - } - } - PROCESS_SWITCH(JetSpectraCharged, processTracksQC, "collisions and track QC for Data and MCD", false); - - void processTracksQCWeighted(soa::Filtered>::iterator const& collision, - aod::JetMcCollisions const&, - soa::Filtered> const& tracks) - { - bool fillHistograms = false; - bool isWeighted = true; - float eventWeight = collision.weight(); - if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { - return; - } - - for (auto const& track : tracks) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { - continue; - } - fillTrackHistograms(track, eventWeight); - } - } - PROCESS_SWITCH(JetSpectraCharged, processTracksQCWeighted, "weighted collsions and tracks QC for MC", false); - void processCollisions(soa::Filtered::iterator const& collision) { bool fillHistograms = true; @@ -760,7 +718,7 @@ struct JetSpectraCharged { registry.fill(HIST("h_collisions_zvertex"), collision.posZ(), eventWeight); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); registry.fill(HIST("h_coll_phat"), pTHat); registry.fill(HIST("h_coll_phat_weighted"), pTHat, eventWeight); } @@ -789,7 +747,7 @@ struct JetSpectraCharged { registry.fill(HIST("h_mccollisions_zvertex"), mccollision.posZ(), eventWeight); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); registry.fill(HIST("h_mccoll_phat"), pTHat); registry.fill(HIST("h_mccoll_phat_weighted"), pTHat, eventWeight); } @@ -887,9 +845,10 @@ struct JetSpectraCharged { } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCD, "jet spectra with rho-area subtraction for MCD", false); - void processSpectraMCDWeighted(soa::Filtered::iterator const& collision, + void processSpectraMCDWeighted(soa::Filtered::iterator const& collision, soa::Join const& jets, - aod::JetTracks const&) + aod::JetTracks const&, + aod::JetMcCollisions const&) { bool fillHistograms = false; bool isWeighted = true; @@ -897,7 +856,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); @@ -908,14 +867,15 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetHistograms(jet, centrality, eventWeight); + fillJetHistograms(jet, centrality, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraMCDWeighted, "jet finder QA mcd with weighted events", false); - void processSpectraAreaSubMCDWeighted(soa::Filtered>::iterator const& collision, + void processSpectraAreaSubMCDWeighted(soa::Filtered>::iterator const& collision, soa::Join const& jets, - aod::JetTracks const&) + aod::JetTracks const&, + aod::JetMcCollisions const&) { bool fillHistograms = false; bool isWeighted = true; @@ -923,7 +883,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); float centrality = -1.0; checkCentFT0M ? centrality = collision.centFT0M() : centrality = collision.centFT0C(); @@ -934,7 +894,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetAreaSubHistograms(jet, centrality, collision.rho(), eventWeight); + fillJetAreaSubHistograms(jet, centrality, collision.rho(), eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCDWeighted, "jet spectra with rho-area subtraction for MCD", false); @@ -949,7 +909,6 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions)) { return; } - registry.fill(HIST("h_mccollisions_zvertex"), mccollision.posZ()); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -979,7 +938,7 @@ struct JetSpectraCharged { bool occupancyIsGood = false; float centrality = mccollision.centFT0M(); if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - if (hasRecoColl && jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { + if (hasRecoColl && jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { hasSel8Coll = true; } if (hasRecoColl && (trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -990,7 +949,7 @@ struct JetSpectraCharged { } } else { for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { hasSel8Coll = true; } if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -1062,7 +1021,7 @@ struct JetSpectraCharged { bool occupancyIsGood = false; float centrality = mccollision.centFT0M(); if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly) { - if (hasRecoColl && jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { + if (hasRecoColl && jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { hasSel8Coll = true; } if (hasRecoColl && (trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -1073,7 +1032,7 @@ struct JetSpectraCharged { } } else { for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { hasSel8Coll = true; } if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -1167,7 +1126,7 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = mccollision.ptHard() < 999.0f ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; @@ -1175,14 +1134,13 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { continue; } - double pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); int Nmax = 21; for (int N = 1; N < Nmax; N++) { if (jet.pt() < N * 0.25 * pTHat && jet.r() == round(selectedJetsRadius * 100.0f)) { registry.fill(HIST("h2_jet_ptcut_part"), jet.pt(), N * 0.25, eventWeight); } } - fillMCPHistograms(jet, eventWeight); + fillMCPHistograms(jet, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraMCPWeighted, "jet spectra for MC particle level weighted", false); @@ -1200,6 +1158,7 @@ struct JetSpectraCharged { if (!applyMCCollisionCuts(mccollision, collisions, fillHistograms, isWeighted, eventWeight)) { return; } + float pTHat = mccollision.ptHard() < 999.0f ? mccollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); registry.fill(HIST("h_mccollisions_rho"), mccollision.rho(), eventWeight); for (auto const& jet : jets) { @@ -1209,7 +1168,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { continue; } - fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight); + fillMCPAreaSubHistograms(jet, mccollision.rho(), eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCPWeighted, "jet spectra with area-based subtraction for MC particle level", false); @@ -1278,10 +1237,11 @@ struct JetSpectraCharged { } PROCESS_SWITCH(JetSpectraCharged, processJetsMatched, "matched mcp and mcd jets", false); - void processJetsMatchedWeighted(soa::Filtered::iterator const& collision, + void processJetsMatchedWeighted(soa::Filtered::iterator const& collision, ChargedMCDMatchedJets const& mcdjets, ChargedMCPMatchedJets const&, - aod::JetTracks const&, aod::JetParticles const&) + aod::JetTracks const&, aod::JetParticles const&, + aod::JetMcCollisions const&) { bool fillHistograms = false; bool isWeighted = true; @@ -1289,12 +1249,12 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } - + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); for (const auto& mcdjet : mcdjets) { if (!isAcceptedJet(mcdjet)) { continue; } - fillMatchedHistograms(mcdjet, eventWeight); + fillMatchedHistograms(mcdjet, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processJetsMatchedWeighted, "matched mcp and mcd jets with weighted events", false); @@ -1332,6 +1292,7 @@ struct JetSpectraCharged { if (!applyCollisionCuts(collision, fillHistograms, isWeighted, eventWeight)) { return; } + float pTHat = collision.has_mcCollision() && collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); double mcrho = collision.has_mcCollision() ? collision.mcCollision_as().rho() : -1; @@ -1339,7 +1300,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(mcdjet)) { continue; } - fillGeoMatchedAreaSubHistograms(mcdjet, collision.rho(), mcrho, eventWeight); + fillGeoMatchedAreaSubHistograms(mcdjet, collision.rho(), mcrho, eventWeight, pTHat); } } PROCESS_SWITCH(JetSpectraCharged, processJetsMatchedAreaSubWeighted, "matched mcp and mcd jets after area-based pt subtraction with weighted events", false); diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index b4ac9ffdc25..e9e445861e0 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -24,22 +24,28 @@ #include "Common/DataModel/EseTable.h" #include "Common/DataModel/Qvectors.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include +#include +#include #include +#include +#include #include #include #include +#include #include #include #include #include +#include #include #include +#include + #include #include #include @@ -48,34 +54,18 @@ #include #include #include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct JetSpectraEseTask { - ConfigurableAxis binJetPt{"binJetPt", {250, -50., 200.}, ""}; - ConfigurableAxis bindPhi{"bindPhi", {180, -o2::constants::math::PI, o2::constants::math::PI}, ""}; - ConfigurableAxis binESE{"binESE", {100, 0, 100}, ""}; - ConfigurableAxis binCos{"binCos", {100, -1.05, 1.05}, ""}; - ConfigurableAxis binOccupancy{"binOccupancy", {5000, 0, 25000}, ""}; - ConfigurableAxis binQVec{"binQVec", {500, -3, 3}, ""}; - ConfigurableAxis binCentrality{"binCentrality", {101, -1, 100}, ""}; - ConfigurableAxis binPhi{"binPhi", {60, -1.0, 7.0}, ""}; - ConfigurableAxis binEta{"binEta", {80, -0.9, 0.9}, ""}; - ConfigurableAxis binFit0{"binFit0", {100, 0, 50}, ""}; - ConfigurableAxis binFit13{"binFit13", {100, 0, 1.4}, ""}; - ConfigurableAxis binFit24{"binFit24", {100, 0, 10}, ""}; - ConfigurableAxis binTrackPt{"binTrackPt", {100, 0, 10}, ""}; - ConfigurableAxis dbinEta{"dbinEta", {100, -1.6, 1.6}, ""}; - ConfigurableAxis dbinPhi{"dbinPhi", {120, -o2::constants::math::PIHalf, o2::constants::math::TwoPI - o2::constants::math::PIHalf}, ""}; - + Configurable cfgEfficiency{"cfgEfficiency", "", "CCDB path to efficiency"}; Configurable jetPtMin{"jetPtMin", 5.0, "minimum jet pT cut"}; Configurable jetR{"jetR", 0.2, "jet resolution parameter"}; 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 vertexZCut{"vertexZCut", 10.0, "vertex z cut"}; - Configurable> centRange{"centRange", {0, 90}, "centrality region of interest"}; - Configurable cfgSelCentrality{"cfgSelCentrality", true, "Flag for centrality selection"}; // Configurable leadingTrackPtCut{"leadingTrackPtCut", 5.0, "leading jet pT cut"}; Configurable jetAreaFractionMin{"jetAreaFractionMin", -99, "used to make a cut on the jet areas"}; Configurable cfgCentVariant{"cfgCentVariant", false, "Flag for centrality variant 1"}; @@ -89,8 +79,8 @@ struct JetSpectraEseTask { 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 fLeadJetPtCut{"fLeadJetPtCut", false, "Flag for leading jet pT cut"}; Configurable leadJetPtMin{"leadJetPtMin", 20.0, "minimum leading jet pT cut"}; - Configurable subleadJetPtMin{"subleadJetPtMin", 10.0, "minimum sub-leading jet pT cut"}; Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum eta acceptance for tracks"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum eta acceptance for tracks"}; @@ -101,14 +91,11 @@ struct JetSpectraEseTask { Configurable jetEtaMin{"jetEtaMin", -0.7, "minimum jet pseudorapidity"}; Configurable jetEtaMax{"jetEtaMax", 0.7, "maximum jet pseudorapidity"}; - Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; - Configurable fRequireDijetEvent{"fRequireDijetEvent", false, "flag to require dijet event"}; Configurable eventSelections{"eventSelections", "sel8FullPbPb", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; Configurable cfgEvSelOccupancy{"cfgEvSelOccupancy", true, "Flag for occupancy cut"}; - Configurable> cfgCutOccupancy{"cfgCutOccupancy", {0, 1000}, "Occupancy cut"}; Configurable> cfgOccupancyPtCut{"cfgOccupancyPtCut", {0, 100}, "pT cut"}; @@ -121,22 +108,29 @@ struct JetSpectraEseTask { Configurable cfgEPRefB{"cfgEPRefB", "TPCpos", "EP reference B"}; Configurable cfgEPRefC{"cfgEPRefC", "TPCneg", "EP reference C"}; - AxisSpec jetPtAxis = {binJetPt, "#it{p}_{T,jet}"}; - AxisSpec dPhiAxis = {bindPhi, "#Delta#phi"}; - AxisSpec eseAxis = {binESE, "#it{q}_{2}"}; - AxisSpec cosAxis = {binCos, ""}; - AxisSpec occAxis = {binOccupancy, "Occupancy"}; - AxisSpec qvecAxis = {binQVec, "Q-vector"}; - AxisSpec centAxis = {binCentrality, "Centrality"}; - AxisSpec phiAxis = {binPhi, "#phi"}; - AxisSpec etaAxis = {binEta, "#eta"}; - AxisSpec detaAxis = {dbinEta, "#Delta#eta"}; - AxisSpec dphiAxis = {dbinPhi, "#Delta#phi"}; - AxisSpec fitAxis0 = {binFit0, "Fit0"}; - AxisSpec fitAxis13 = {binFit13, "Fit13"}; - AxisSpec fitAxis24 = {binFit24, "Fit24"}; - - AxisSpec trackPtAxis = {binTrackPt, "#it{p}_{T}"}; + ConfigurableAxis assocTrackPt{"assocTrackPt", {VARIABLE_WIDTH, 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, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "pT of associated track"}; + ConfigurableAxis jetPtAxis{"jetPtAxis", {VARIABLE_WIDTH, 0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 70.0, 100.0, 150.0, 200.0}, "#it{p}_{T,jet} (GeV/#it{c})"}; + ConfigurableAxis dPhiAxis{"dPhiAxis", {60, -o2::constants::math::PI, o2::constants::math::PI}, "#Delta#phi"}; + ConfigurableAxis eseAxis{"eseAxis", {100, 0, 100}, "#it{q}_{2}"}; + Configurable cfgSelCentrality{"cfgSelCentrality", true, "Flag for centrality selection"}; + Configurable> centRange{"centRange", {0, 90}, "centrality region of interest"}; + ConfigurableAxis centAxis{"centAxis", {91, -1, 90}, "centrality"}; + ConfigurableAxis cosAxis{"cosAxis", {50, -1.0, 1.0}, "cos(2(#Psi_{2}^{A}-#Psi_{2}^{B}))"}; + ConfigurableAxis occAxis{"occAxis", {5000, 0, 25000}, "Occupancy"}; + ConfigurableAxis qvecAxis{"qvecAxis", {60, -3, 3}, "Q-vector"}; + ConfigurableAxis phiAxis{"phiAxis", {30, -1.0, 7.0}, "#phi"}; + ConfigurableAxis etaAxis{"etaAxis", {30, -1.0, 1.0}, "#eta"}; + ConfigurableAxis detaAxis{"detaAxis", {60, -1.6, 1.6}, "#Delta#eta"}; + ConfigurableAxis dphiAxis{"dphiAxis", {120, -o2::constants::math::PIHalf, 3 * o2::constants::math::PI / 2}, "#Delta#phi"}; + ConfigurableAxis trackPtAxis{"trackPtAxis", {100, 0, 100}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis fitAxis0{"fitAxis0", {100, 0, 50}, ""}; + ConfigurableAxis fitAxis13{"fitAxis13", {100, 0, 1.4}, ""}; + ConfigurableAxis fitAxis24{"fitAxis24", {100, 0, 10}, ""}; + ConfigurableAxis rhoAxis{"rhoAxis", {50, 0, 200}, "#rho"}; + ConfigurableAxis vertexZAxis{"vertexZAxis", {20, -10.0, 10.0}, "z vertex"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; + ConfigurableAxis binsCentrality{"binsCentrality", {VARIABLE_WIDTH, 0.0, 10., 30., 50, 70., 100.}, "Mixing bins - centrality"}; + ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -147,6 +141,12 @@ struct JetSpectraEseTask { static constexpr float Acceptance = 0.9f; static constexpr float LowFT0Cut = 1e-8; + Service ccdb; + struct Efficiency { + TH1D* hEff = nullptr; + bool isLoaded = false; + } cfg; + Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); Filter jetCuts = aod::jet::pt > jetPtMin&& aod::jet::r == nround(jetR.node() * Scaler) && nabs(aod::jet::eta) < Acceptance - jetR; Filter colFilter = nabs(aod::jcollision::posZ) < vertexZCut; @@ -154,12 +154,12 @@ struct JetSpectraEseTask { using ChargedMCDJets = soa::Filtered>; Preslice mcdjetsPerJCollision = o2::aod::jet::collisionId; Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; + Preslice mcdTracksPerJCollision = o2::aod::jtrack::collisionId; - ConfigurableAxis binsCentrality{"binsCentrality", {VARIABLE_WIDTH, 0.0, 10., 30., 50, 70., 100.}, "Mixing bins - centrality"}; - ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; SliceCache cache; using BinningType = ColumnBinningPolicy; BinningType corrBinning{{binsZVtx, binsCentrality}, true}; + Service pdg; enum class DetID { FT0C, FT0A, @@ -186,14 +186,15 @@ struct JetSpectraEseTask { kCentCut, kEse, kRhoLocal, - kDijetEv, - kLeadJetPtCut, - kSubLeadJetPtCut + kLeadJetCut }; static constexpr EventPlaneFiller PsiFillerEP = {true, true}; static constexpr EventPlaneFiller PsiFillerEse = {true, false}; static constexpr EventPlaneFiller PsiFillerFalse = {false, false}; + TRandom3* fRndm = new TRandom3(0); + static constexpr int NumSubSmpl = 10; + std::array, NumSubSmpl> hSameSub; void init(o2::framework::InitContext&) { @@ -206,20 +207,21 @@ struct JetSpectraEseTask { LOGF(info, "JetSpectraEseTask::init() - ESE Data Process"); registry.add("eventQA/hEventCounter", "event status;event status;entries", {HistType::kTH1F, {{20, 0.0, 20.0}}}); registry.add("eventQA/hCentralityAnalyzed", ";Centrality;entries", {HistType::kTH1F, {{centAxis}}}); + registry.add("eventQA/hJetR", ";jet R;entries", {HistType::kTH1F, {{10, 0.0, 1.0}}}); registry.add("trackQA/hRhoTrackCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); registry.add("hJetPt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{jetPtAxis}}}); registry.add("hJetPt_bkgsub", "jet pT background sub;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{jetPtAxis}}}); registry.add("hJetEta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{etaAxis}}}); registry.add("hJetPhi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{phiAxis}}}); - registry.add("eventQA/hRho", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {100, 0, 200.}}}); - registry.add("eventQA/hRhoPhi", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {100, 0, 200.}}}); - registry.add("hJetArea", ";area_{jet};entries", {HistType::kTH1F, {{80, 0, 10.}}}); - registry.add("hJetAreaRho", "", {HistType::kTH1F, {{100, 0, 500.}}}); + registry.add("eventQA/hRho", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {rhoAxis}}}); + registry.add("eventQA/hRhoPhi", ";#rho;entries", {HistType::kTH2F, {{centAxis}, {rhoAxis}}}); + registry.add("hJetArea", ";area_{jet};entries", {HistType::kTH1F, {{50, 0, 5.}}}); + registry.add("hJetAreaRho", "", {HistType::kTH1F, {{50, 0, 10.}}}); registry.add("hCentJetPtdPhiq2", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); registry.add("hCentJetPtdPhiq2RhoPhi", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); - registry.add("eventQA/before/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - registry.add("eventQA/after/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); + registry.add("eventQA/before/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/after/hVtxZ", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kFilteredInputEv, "Input filtered event"); registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kEventSel, "Event selection"); @@ -227,9 +229,7 @@ struct JetSpectraEseTask { registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kCentCut, "Centrality cut"); registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kEse, "ESE available"); registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kRhoLocal, "rho(#phi) available"); - registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kDijetEv, "dijet event found"); - registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kLeadJetPtCut, "leading jet pT cut"); - registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kSubLeadJetPtCut, "sub leading jet pT cut"); + registry.get(HIST("eventQA/hEventCounter"))->GetXaxis()->SetBinLabel(kLeadJetCut, "leading jet pT cut"); registry.get(HIST("trackQA/hRhoTrackCounter"))->GetXaxis()->SetBinLabel(1, "Input tracks"); registry.get(HIST("trackQA/hRhoTrackCounter"))->GetXaxis()->SetBinLabel(2, "Track selection"); registry.get(HIST("trackQA/hRhoTrackCounter"))->GetXaxis()->SetBinLabel(3, "Tracks for rho(phi)"); @@ -241,11 +241,31 @@ struct JetSpectraEseTask { registry.add("eventQA/hfitPar3", "", {HistType::kTH2F, {{centAxis}, {fitAxis13}}}); registry.add("eventQA/hfitPar4", "", {HistType::kTH2F, {{centAxis}, {fitAxis24}}}); registry.add("eventQA/hPValueCentCDF", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{centAxis}, {40, 0, 1}}}); - registry.add("eventQA/hCentChi2Ndf", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{centAxis}, {100, 0, 5}}}); - registry.add("eventQA/hCentPhi", "centrality vs #rho(#varphi); centrality; #rho(#varphi) ", {HistType::kTH2F, {{centAxis}, {210, -10.0, 200.0}}}); - registry.add("eventQA/hdPhiRhoPhi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, -o2::constants::math::PI, o2::constants::math::PI}, {210, -10.0, 200.0}}}); - - registry.add("thn_jethad_corr_same", "jet-had; centrality; #it{p}_{T,lead jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,sublead jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c}); #Delta#eta; #Delta#phi; #Delta#phi to EP; #it{q}_{2}", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {jetPtAxis}, {trackPtAxis}, {detaAxis}, {dphiAxis}, {dPhiAxis}, {eseAxis}}}); + registry.add("eventQA/hCentChi2Ndf", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{centAxis}, {50, 0, 5}}}); + registry.add("eventQA/hCentPhi", "centrality vs #rho(#varphi); centrality; #rho(#varphi) ", {HistType::kTH2F, {{centAxis}, {rhoAxis}}}); + registry.add("eventQA/hdPhiRhoPhi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, -o2::constants::math::PI, o2::constants::math::PI}, {rhoAxis}}}); + + registry.add("jetQA/before/hLeadJetPt", ";Centrality;#it{p}_{T,lead jet} (GeV/#it{c});entries", {HistType::kTH2F, {{centAxis}, {jetPtAxis}}}); + registry.add("jetQA/before/hLeadJetPhi", ";Centrality;#phi_{lead jet};entries", {HistType::kTH2F, {{centAxis}, {phiAxis}}}); + registry.add("jetQA/before/hLeadJetEta", ";Centrality;#eta_{lead jet};entries", {HistType::kTH2F, {{centAxis}, {etaAxis}}}); + registry.add("jetQA/after/hLeadJetPt", ";Centrality;#it{p}_{T,lead jet} (GeV/#it{c});entries", {HistType::kTH2F, {{centAxis}, {jetPtAxis}}}); + registry.add("jetQA/after/hLeadJetPhi", ";Centrality;#phi_{lead jet};entries", {HistType::kTH2F, {{centAxis}, {phiAxis}}}); + registry.add("jetQA/after/hLeadJetEta", ";Centrality;#eta_{lead jet};entries", {HistType::kTH2F, {{centAxis}, {etaAxis}}}); + registry.add("h3CenttrPhiPsi2", ";Centrality;#phi_{track} - #Psi_{2};#it{q}_{2}", {HistType::kTH3F, {{centAxis}, {dPhiAxis}, {eseAxis}}}); + + std::vector axes = { + {centAxis}, + {jetPtAxis}, + {assocTrackPt}, + {detaAxis}, + {dphiAxis}, + {dPhiAxis}, + {eseAxis}}; + registry.add("thn_jethad_corr_same", "jet-had; centrality; #it{p}_{T,jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c}); #Delta#eta; #Delta#phi; #Delta#phi to EP; #it{q}_{2}", {HistType::kTHnSparseF, axes}); + for (int i = 0; i < NumSubSmpl; ++i) { + std::string n = fmt::format("subsamples/thn_jethad_corr_same_subsample{}", i); + hSameSub[i] = registry.add(n, "same;...", o2::framework::HistType::kTHnSparseF, axes); + } registry.add("hNtrig", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); registry.add("trackQA/before/hTrackPt", "", {HistType::kTH2F, {{centAxis}, {trackPtAxis}}}); @@ -263,13 +283,31 @@ struct JetSpectraEseTask { registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kCentCut, "Centrality cut"); registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kEse, "ESE available"); registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kRhoLocal, "rho(#phi) available"); - registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kDijetEv, "dijet event found"); - registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kLeadJetPtCut, "leading jet pT cut"); - registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kSubLeadJetPtCut, "sub leading jet pT cut"); - registry.add("eventQA/before/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - registry.add("eventQA/after/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{100, -10.0, 10.0}}}); - - registry.add("thn_jethad_corr_mixed", "jet-had; centrality; #it{p}_{T,lead jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,sublead jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c}); #Delta#eta; #Delta#phi; #Delta#phi to EP; #it{q}_{2}", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {jetPtAxis}, {trackPtAxis}, {detaAxis}, {dphiAxis}, {dPhiAxis}, {eseAxis}}}); + registry.get(HIST("eventQA/hEventCounterMixed"))->GetXaxis()->SetBinLabel(kLeadJetCut, "leading jet pT cut"); + registry.add("eventQA/before/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/after/hVtxZMixed", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/before/hVtxZMixed2", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/after/hVtxZMixed2", ";z_{vtx} (cm);entries", {HistType::kTH1F, {{vertexZAxis}}}); + registry.add("eventQA/hCentralityAnalyzedMixed", ";Centrality;entries", {HistType::kTH1F, {{centAxis}}}); + registry.add("eventQA/hCentralityAnalyzedMixed2", ";Centrality;entries", {HistType::kTH1F, {{centAxis}}}); + registry.add("eventQA/hDeltaCentMixed", ";Centrality difference;entries", {HistType::kTH1F, {{50, -100, 100}}}); + registry.add("eventQA/hDeltaVtxZMixed", ";z_{vtx} difference (cm);entries", {HistType::kTH1F, {{50, -20.0, 20.0}}}); + + registry.add("trackQA/before/hTrackPtMixed", "", {HistType::kTH2F, {{centAxis}, {trackPtAxis}}}); + registry.add("trackQA/before/hTrackEtaMixed", "", {HistType::kTH2F, {{centAxis}, {etaAxis}}}); + registry.add("trackQA/before/hTrackPhiMixed", "", {HistType::kTH2F, {{centAxis}, {phiAxis}}}); + registry.add("trackQA/after/hTrackPtMixed", "", {HistType::kTH2F, {{centAxis}, {trackPtAxis}}}); + registry.add("trackQA/after/hTrackEtaMixed", "", {HistType::kTH2F, {{centAxis}, {etaAxis}}}); + registry.add("trackQA/after/hTrackPhiMixed", "", {HistType::kTH2F, {{centAxis}, {phiAxis}}}); + std::vector axes = { + {centAxis}, + {jetPtAxis}, + {assocTrackPt}, + {detaAxis}, + {dphiAxis}, + {dPhiAxis}, + {eseAxis}}; + registry.add("thn_jethad_corr_mixed", "jet-had; centrality; #it{p}_{T,jet} - #rho_{local} * area_{jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c}); #Delta#eta; #Delta#phi; #Delta#phi to EP; #it{q}_{2}", {HistType::kTHnSparseF, axes}); registry.add("hNtrigMixed", "", {HistType::kTHnSparseF, {{centAxis}, {jetPtAxis}, {dPhiAxis}, {eseAxis}}}); } if (doprocessESEEPData) { @@ -312,6 +350,8 @@ struct JetSpectraEseTask { registry.get(HIST("mcp/hEventCounter"))->GetXaxis()->SetBinLabel(2, "Collision size < 1"); registry.get(HIST("mcp/hEventCounter"))->GetXaxis()->SetBinLabel(3, "MCD size != 1"); registry.get(HIST("mcp/hEventCounter"))->GetXaxis()->SetBinLabel(4, "Occupancy cut"); + registry.get(HIST("mcp/hEventCounter"))->GetXaxis()->SetBinLabel(5, "Vtx z cut"); + registry.get(HIST("mcp/hEventCounter"))->GetXaxis()->SetBinLabel(6, "Event selection"); } if (doprocessMCDetectorLevel) { LOGF(info, "JetSpectraEseTask::init() - MC Detector level"); @@ -324,8 +364,9 @@ struct JetSpectraEseTask { // registry.add("mcd/hJetPhi", "particle level jet #phi;#phi_{jet part};entries", {HistType::kTH1F, {{phiAxis}}}); registry.get(HIST("mcd/hEventCounter"))->GetXaxis()->SetBinLabel(1, "Input event"); - registry.get(HIST("mcd/hEventCounter"))->GetXaxis()->SetBinLabel(2, "Collision size < 1"); - registry.get(HIST("mcd/hEventCounter"))->GetXaxis()->SetBinLabel(3, "Occupancy cut"); + registry.get(HIST("mcd/hEventCounter"))->GetXaxis()->SetBinLabel(1, "Event selection"); + registry.get(HIST("mcd/hEventCounter"))->GetXaxis()->SetBinLabel(2, "Occupancy cut"); + registry.get(HIST("mcd/hEventCounter"))->GetXaxis()->SetBinLabel(3, "Vtx z cut"); } if (doprocessMCChargedMatched) { LOGF(info, "JetSpectraEseTask::init() - MC Charged Matched"); @@ -367,14 +408,49 @@ struct JetSpectraEseTask { registry.add("hOccupancy", "Occupancy;Occupancy;entries", {HistType::kTH1F, {{occAxis}}}); registry.add("hPsiOccupancy", "Occupancy;#Psi_{2};entries", {HistType::kTH3F, {{centAxis}, {150, -2.5, 2.5}, {occAxis}}}); } + if (doprocessMCGenTrack) { + LOGF(info, "JetSpectraEseTask::init() - MCGen track"); + registry.add("mcgen/hTrackPtGen", "", {HistType::kTH1F, {{assocTrackPt}}}); + registry.add("mcgen/hTrackEtaGen", "", {HistType::kTH1F, {{etaAxis}}}); + registry.add("mcgen/hTrackPhiGen", "", {HistType::kTH1F, {{phiAxis}}}); + } + if (doprocessMCRecoTrack) { + LOGF(info, "JetSpectraEseTask::init() - MCRec track"); + registry.add("mcrec/hTrackPtReco", "", {HistType::kTH1F, {{assocTrackPt}}}); + registry.add("mcrec/hTrackEtaReco", "", {HistType::kTH1F, {{etaAxis}}}); + registry.add("mcrec/hTrackPhiReco", "", {HistType::kTH1F, {{phiAxis}}}); + } } - struct DijetEvent { - float lead = -999; - float sub = -999; - bool fLead = false; - bool fSub = false; - }; + template + void loadEfficiency(TBC const& bc) + { + uint64_t timestamp = bc.timestamp(); + if (cfg.isLoaded) { + return; + } + if (!cfgEfficiency.value.empty()) { + cfg.hEff = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfg.hEff == nullptr) { + LOGF(fatal, "Could not load track efficiency from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded tracking efficiency from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.hEff); + } + cfg.isLoaded = true; + return; + } + + template + double getEfficiency(TTrack track) + { + double eff{1.0}; + if (cfg.hEff) + eff = cfg.hEff->GetBinContent(cfg.hEff->FindBin(track.pt())); + if (eff == 0) + return -1.; + else + return 1. / eff; + } template float corr(const TCollision& collision, const TJets& jet) @@ -404,19 +480,20 @@ struct JetSpectraEseTask { if (!rhoFit) return; } - DijetEvent dijetEv{}; + registry.fill(HIST("eventQA/hEventCounter"), kRhoLocal); + if (fLeadJetPtCut) { + if (!isAcceptedLeadingJet(collision, jets, centrality)) + return; + } + registry.fill(HIST("eventQA/hEventCounter"), kLeadJetCut); registry.fill(HIST("eventQA/after/hVtxZ"), collision.posZ()); - registry.fill(HIST("eventQA/hEventCounter"), kRhoLocal); registry.fill(HIST("eventQA/hRho"), centrality, collision.rho()); registry.fill(HIST("eventQA/hCentralityAnalyzed"), centrality); + int lRndInd = fRndm->Integer(NumSubSmpl); - using JetIter = typename TJets::iterator; - JetIter leadingJet; - JetIter subleadingJet; auto corrL = [&](const auto& j) { return j.pt() - evalRho(rhoFit.get(), jetR, j.phi(), collision.rho()) * j.area(); }; - for (auto it = jets.begin(); it != jets.end(); ++it) { - const auto& jet = *it; + for (const auto& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; if (!isAcceptedJet(jet)) { @@ -430,6 +507,7 @@ struct JetSpectraEseTask { registry.fill(HIST("hJetPhi"), jet.phi()); registry.fill(HIST("hJetArea"), jet.area()); registry.fill(HIST("hJetAreaRho"), jet.area() * collision.rho()); + registry.fill(HIST("eventQA/hJetR"), jet.r() / 100.0f); float dPhi{RecoDecay::constrainAngle(jet.phi() - psi.psi2, -o2::constants::math::PI)}; registry.fill(HIST("hCentJetPtdPhiq2"), centrality, vCorr, dPhi, qPerc[0]); @@ -442,47 +520,32 @@ struct JetSpectraEseTask { registry.fill(HIST("eventQA/hdPhiRhoPhi"), dPhi, rhoLocal); } - if (!dijetEv.fLead) { - leadingJet = it; - dijetEv.fLead = true; - dijetEv.lead = vCorrL; - } else if (vCorrL > dijetEv.lead) { - subleadingJet = leadingJet; - dijetEv.fSub = true; - dijetEv.sub = dijetEv.lead; - leadingJet = it; - dijetEv.fLead = true; - dijetEv.lead = vCorrL; - } else if (!dijetEv.fSub || vCorrL > dijetEv.sub) { - subleadingJet = it; - dijetEv.fSub = true; - dijetEv.sub = vCorrL; + registry.fill(HIST("hNtrig"), centrality, vCorrL, dPhi, qPerc[0]); + for (const auto& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) + continue; + double weff = getEfficiency(track); + if (weff < 0) + continue; + auto deta = track.eta() - jet.eta(); + auto dphi = RecoDecay::constrainAngle(track.phi() - jet.phi(), -o2::constants::math::PIHalf); + registry.fill(HIST("thn_jethad_corr_same"), centrality, vCorrL, track.pt(), deta, dphi, dPhi, qPerc[0], weff); + hSameSub[lRndInd]->Fill(centrality, vCorrL, track.pt(), deta, dphi, dPhi, qPerc[0], weff); } } - if ((fRequireDijetEvent) && (!dijetEv.fLead || !dijetEv.fSub)) - return; - registry.fill(HIST("eventQA/hEventCounter"), kDijetEv); - if (dijetEv.lead < leadJetPtMin) - return; - registry.fill(HIST("eventQA/hEventCounter"), kLeadJetPtCut); - if ((fRequireDijetEvent) && (dijetEv.sub < subleadJetPtMin)) - return; - registry.fill(HIST("eventQA/hEventCounter"), kSubLeadJetPtCut); - const auto leaddPhi = RecoDecay::constrainAngle(leadingJet.phi() - psi.psi2, -o2::constants::math::PI); - - registry.fill(HIST("hNtrig"), centrality, dijetEv.lead, leaddPhi, qPerc[0]); - for (auto const& track : tracks) { - registry.fill(HIST("trackQA/before/hTrackPt"), centrality, track.pt()); + for (const auto& track : tracks) { + double weff = getEfficiency(track); + if (weff < 0) + continue; + registry.fill(HIST("trackQA/before/hTrackPt"), centrality, track.pt(), weff); registry.fill(HIST("trackQA/before/hTrackEta"), centrality, track.eta()); registry.fill(HIST("trackQA/before/hTrackPhi"), centrality, track.phi()); if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; - registry.fill(HIST("trackQA/after/hTrackPt"), centrality, track.pt()); + registry.fill(HIST("trackQA/after/hTrackPt"), centrality, track.pt(), weff); registry.fill(HIST("trackQA/after/hTrackEta"), centrality, track.eta()); registry.fill(HIST("trackQA/after/hTrackPhi"), centrality, track.phi()); - auto deta = track.eta() - leadingJet.eta(); - auto dphi = RecoDecay::constrainAngle(track.phi() - leadingJet.phi(), -o2::constants::math::PIHalf); - registry.fill(HIST("thn_jethad_corr_same"), centrality, dijetEv.lead, dijetEv.sub, track.pt(), deta, dphi, leaddPhi, qPerc[0]); + registry.fill(HIST("h3CenttrPhiPsi2"), centrality, RecoDecay::constrainAngle(track.phi() - psi.psi2, -o2::constants::math::PI), qPerc[0]); } } @@ -493,10 +556,13 @@ struct JetSpectraEseTask { { auto tracksTuple = std::make_tuple(jets, tracks); Pair pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + for (const auto& [c1, jets1, c2, tracks2] : pairData) { + auto bc = c2.template bc_as(); + loadEfficiency(bc); auto c1Tracks = tracks.sliceBy(tracksPerJCollision, c1.globalIndex()); - registry.fill(HIST("eventQA/before/hVtxZMixed"), c1.posZ()); + registry.fill(HIST("eventQA/before/hVtxZMixed2"), c2.posZ()); registry.fill(HIST("eventQA/hEventCounterMixed"), kFilteredInputEv); if (!jetderiveddatautilities::selectCollision(c1, eventSelectionBits)) continue; @@ -529,17 +595,20 @@ struct JetSpectraEseTask { continue; } registry.fill(HIST("eventQA/hEventCounterMixed"), kRhoLocal); + if (fLeadJetPtCut) { + if (!isAcceptedLeadingJet(c1, jets, centrality)) + return; + } + registry.fill(HIST("eventQA/hEventCounterMixed"), kLeadJetCut); registry.fill(HIST("eventQA/after/hVtxZMixed"), c1.posZ()); + registry.fill(HIST("eventQA/after/hVtxZMixed2"), c2.posZ()); + registry.fill(HIST("eventQA/hCentralityAnalyzedMixed"), centrality); + registry.fill(HIST("eventQA/hCentralityAnalyzedMixed2"), centrality2); + registry.fill(HIST("eventQA/hDeltaCentMixed"), centrality - centrality2); + registry.fill(HIST("eventQA/hDeltaVtxZMixed"), c1.posZ() - c2.posZ()); auto corrL = [&](const auto& j) { return j.pt() - evalRho(rhoFit.get(), jetR, j.phi(), c1.rho()) * j.area(); }; - - DijetEvent dijetEv{}; - - using JetIter = typename TJets::iterator; - JetIter leadingJet; - JetIter subleadingJet; - for (auto it = jets1.begin(); it != jets1.end(); ++it) { - const auto& jet = *it; + for (const auto& jet : jets1) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; if (!isAcceptedJet(jet)) { @@ -547,49 +616,40 @@ struct JetSpectraEseTask { } auto vCorr = corr(c1, jet); auto vCorrL = cfgrhoPhi ? corrL(jet) : vCorr; + float dPhi{RecoDecay::constrainAngle(jet.phi() - psi.psi2, -o2::constants::math::PI)}; - if (!dijetEv.fLead) { - leadingJet = it; - dijetEv.fLead = true; - dijetEv.lead = vCorrL; - } else if (vCorrL > dijetEv.lead) { - subleadingJet = leadingJet; - dijetEv.fSub = true; - dijetEv.sub = dijetEv.lead; - leadingJet = it; - dijetEv.fLead = true; - dijetEv.lead = vCorrL; - } else if (!dijetEv.fSub || vCorrL > dijetEv.sub) { - subleadingJet = it; - dijetEv.fSub = true; - dijetEv.sub = vCorrL; + registry.fill(HIST("hNtrigMixed"), centrality, vCorrL, dPhi, qPerc[0]); + for (const auto& track : tracks2) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) + continue; + double weff = getEfficiency(track); + if (weff < 0) + continue; + auto deta = track.eta() - jet.eta(); + auto dphi = RecoDecay::constrainAngle(track.phi() - jet.phi(), -o2::constants::math::PIHalf); + registry.fill(HIST("thn_jethad_corr_mixed"), centrality, vCorrL, track.pt(), deta, dphi, dPhi, qPerc[0], weff); } } - if ((fRequireDijetEvent) && (!dijetEv.fLead || !dijetEv.fSub)) - continue; - registry.fill(HIST("eventQA/hEventCounterMixed"), kDijetEv); - if (dijetEv.lead < leadJetPtMin) - continue; - registry.fill(HIST("eventQA/hEventCounterMixed"), kLeadJetPtCut); - if ((fRequireDijetEvent) && (dijetEv.sub < subleadJetPtMin)) - continue; - registry.fill(HIST("eventQA/hEventCounterMixed"), kSubLeadJetPtCut); - const auto leaddPhi = RecoDecay::constrainAngle(leadingJet.phi() - psi.psi2, -o2::constants::math::PI); - registry.fill(HIST("hNtrigMixed"), centrality, dijetEv.lead, leaddPhi, qPerc[0]); - for (auto const& track : tracks2) { + for (const auto& track : tracks2) { + double weff = getEfficiency(track); + if (weff < 0) + continue; + registry.fill(HIST("trackQA/before/hTrackPtMixed"), centrality, track.pt(), weff); + registry.fill(HIST("trackQA/before/hTrackEtaMixed"), centrality, track.eta()); + registry.fill(HIST("trackQA/before/hTrackPhiMixed"), centrality, track.phi()); if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; - auto deta = track.eta() - leadingJet.eta(); - auto dphi = RecoDecay::constrainAngle(track.phi() - leadingJet.phi(), -o2::constants::math::PIHalf); - registry.fill(HIST("thn_jethad_corr_mixed"), centrality, dijetEv.lead, dijetEv.sub, track.pt(), deta, dphi, leaddPhi, qPerc[0]); + registry.fill(HIST("trackQA/after/hTrackPtMixed"), centrality, track.pt(), weff); + registry.fill(HIST("trackQA/after/hTrackEtaMixed"), centrality, track.eta()); + registry.fill(HIST("trackQA/after/hTrackPhiMixed"), centrality, track.phi()); } } } void processESEDataCharged(soa::Join::iterator const& collision, soa::Filtered> const& jets, - aod::JetTracks const& tracks) + aod::JetTracks const& tracks, aod::JBCs const&) { registry.fill(HIST("eventQA/hEventCounter"), kFilteredInputEv); registry.fill(HIST("eventQA/before/hVtxZ"), collision.posZ()); @@ -601,13 +661,15 @@ struct JetSpectraEseTask { return; registry.fill(HIST("eventQA/hEventCounter"), kOccupancyCut); + auto bc = collision.bc_as(); + loadEfficiency(bc); jetSpectra(collision, jets, tracks); } PROCESS_SWITCH(JetSpectraEseTask, processESEDataCharged, "process ese collisions", true); void processESEDataChargedMixed(soa::Join const& collisions, soa::Filtered> const& jets, - aod::JetTracks const& tracks) + aod::JetTracks const& tracks, aod::JBCs const&) { jetMixed(collisions, jets, tracks); } @@ -694,12 +756,13 @@ struct JetSpectraEseTask { } if (cfgEvSelOccupancy && !fOccupancy) return; + registry.fill(HIST("mcp/hEventCounter"), counter++); if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { return; } + registry.fill(HIST("mcp/hEventCounter"), counter++); if (!eventSel) return; - registry.fill(HIST("mcp/hEventCounter"), counter++); registry.fill(HIST("mcp/hCentralitySel"), centrality); @@ -724,6 +787,7 @@ struct JetSpectraEseTask { if (!(std::abs(collision.posZ()) < vertexZCut)) { return; } + registry.fill(HIST("mcd/hEventCounter"), counter++); auto centrality = cfgisPbPb ? collision.centFT0M() : -1; @@ -784,6 +848,134 @@ struct JetSpectraEseTask { } PROCESS_SWITCH(JetSpectraEseTask, processMCChargedMatched, "jet MC process: geometrically matched MCP and MCD for response matrix and efficiency", false); + // process for gen/reco tracks for pT efficiency + bool isChargedParticle(int pdgCode) + { + auto pdgParticle = pdg->GetParticle(pdgCode); + return pdgParticle && pdgParticle->Charge() != 0.0; + } + + void processMCGenTrack(soa::Filtered>::iterator const& mcCollision, + soa::SmallGroups const& collisions, + aod::JetTracksMCD const&, + aod::JetParticles const& particles) + { + if (mcCollision.size() < 1) { + return; + } + if (collisions.size() != 1) { + return; + } + if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + + auto collision = collisions.begin(); + if (!(std::abs(collision.posZ()) < vertexZCut)) { + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + if (cfgEvSelOccupancy && !isOccupancyAccepted(collision)) { + return; + } + + auto centrality = cfgisPbPb ? collision.centFT0M() : -1.0f; + if (cfgSelCentrality && cfgisPbPb && !isCentralitySelected(centrality)) { + return; + } + + for (const auto& particle : particles) { + if (particle.mcCollisionId() != mcCollision.globalIndex()) { + continue; + } + if (!isChargedParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + if (particle.pt() < trackPtMin || particle.pt() >= trackPtMax) { + continue; + } + if (particle.eta() <= trackEtaMin || particle.eta() >= trackEtaMax) { + continue; + } + + registry.fill(HIST("mcgen/hTrackPtGen"), particle.pt()); + registry.fill(HIST("mcgen/hTrackEtaGen"), particle.eta()); + registry.fill(HIST("mcgen/hTrackPhiGen"), particle.phi()); + } + } + PROCESS_SWITCH(JetSpectraEseTask, processMCGenTrack, "jet MC process: Generated track", false); + void processMCRecoTrack(soa::Filtered>::iterator const& mcCollision, + soa::SmallGroups const& collisions, + aod::JetTracksMCD const& tracks, + aod::JetParticles const&) + { + if (mcCollision.size() < 1) { + return; + } + if (collisions.size() < 1) { + return; + } + if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + + std::vector seenMcParticles; + for (const auto& collision : collisions) { + if (!(std::abs(collision.posZ()) < vertexZCut)) { + continue; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + continue; + } + if (cfgEvSelOccupancy && !isOccupancyAccepted(collision)) { + continue; + } + + auto centrality = cfgisPbPb ? collision.centFT0M() : -1.0f; + if (cfgSelCentrality && cfgisPbPb && !isCentralitySelected(centrality)) { + continue; + } + + auto tracksInCollision = tracks.sliceBy(mcdTracksPerJCollision, collision.globalIndex()); + for (const auto& track : tracksInCollision) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + if (!track.has_mcParticle()) { + continue; + } + + auto particle = track.mcParticle_as(); + if (!isChargedParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + if (particle.pt() < trackPtMin || particle.pt() >= trackPtMax) { + continue; + } + if (particle.eta() <= trackEtaMin || particle.eta() >= trackEtaMax) { + continue; + } + if (std::find(seenMcParticles.begin(), seenMcParticles.end(), particle.globalIndex()) != seenMcParticles.end()) { + continue; + } + seenMcParticles.push_back(particle.globalIndex()); + + registry.fill(HIST("mcrec/hTrackPtReco"), track.pt()); + registry.fill(HIST("mcrec/hTrackEtaReco"), track.eta()); + registry.fill(HIST("mcrec/hTrackPhiReco"), track.phi()); + } + } + } + PROCESS_SWITCH(JetSpectraEseTask, processMCRecoTrack, "jet MC process: Reconstructed track", false); + static constexpr float InvalidValue = 999.; // template @@ -1207,6 +1399,52 @@ struct JetSpectraEseTask { } } } + // leadJet(collision, jets) + template + bool isAcceptedLeadingJet(TCollisions const& collision, TJets const& jets, const float& centrality) + { + float leadJetPt = 0.0; + float leadJetPhi = -999; + float leadJetEta = -999; + bool hasLeadingJet = false; + for (const auto& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) + continue; + if (!isAcceptedJet(jet)) { + continue; + } + auto jetPtBkg = jet.pt() - (collision.rho() * jet.area()); + + if (!hasLeadingJet) { + leadJetPt = jetPtBkg; + leadJetPhi = jet.phi(); + leadJetEta = jet.eta(); + hasLeadingJet = true; + } + if (jetPtBkg > leadJetPt) { + leadJetPt = jetPtBkg; + leadJetPhi = jet.phi(); + leadJetEta = jet.eta(); + } + } + if (!hasLeadingJet) { + return false; + } + if constexpr (fill) { + registry.fill(HIST("jetQA/before/hLeadJetPt"), centrality, leadJetPt); + registry.fill(HIST("jetQA/before/hLeadJetPhi"), centrality, leadJetPhi); + registry.fill(HIST("jetQA/before/hLeadJetEta"), centrality, leadJetEta); + } + if (leadJetPt < leadJetPtMin) { + return false; + } + if constexpr (fill) { + registry.fill(HIST("jetQA/after/hLeadJetPt"), centrality, leadJetPt); + registry.fill(HIST("jetQA/after/hLeadJetPhi"), centrality, leadJetPhi); + registry.fill(HIST("jetQA/after/hLeadJetEta"), centrality, leadJetEta); + } + return true; + } template bool isAcceptedJet(TJets const& jet, bool mcLevelIsParticleLevel = false) diff --git a/PWGJE/Tasks/jetSubstructure.cxx b/PWGJE/Tasks/jetSubstructure.cxx index f175e289628..fe568b6c2a6 100644 --- a/PWGJE/Tasks/jetSubstructure.cxx +++ b/PWGJE/Tasks/jetSubstructure.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -79,9 +80,6 @@ struct JetSubstructureTask { Configurable doPairBkg{"doPairBkg", true, "save bkg pairs"}; Configurable pairConstituentPtMin{"pairConstituentPtMin", 1.0, "pt cut off for constituents going into pairs"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; - Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; Service pdg; std::vector jetConstituents; @@ -132,15 +130,6 @@ struct JetSubstructureTask { jetReclusterer.ghostRepeatN = 0; trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "jetFinder workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "jetFinder workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } Preslice TracksPerCollision = aod::jtrack::collisionId; @@ -171,7 +160,7 @@ struct JetSubstructureTask { std::vector candidates; std::vector clusters; for (const auto& constituent : sorted_by_pt(parentSubJet2.constituents())) { - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::track)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::track) { tracks.push_back(constituent.template user_info().getIndex()); } } @@ -271,7 +260,7 @@ struct JetSubstructureTask { } if constexpr (!std::is_same_v, aod::JetParticles>) { - if (!jetfindingutilities::isTrackSelected(track, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning)) { + if (!jetfindingutilities::isTrackSelected(track, trackSelection)) { continue; } } @@ -344,7 +333,7 @@ struct JetSubstructureTask { } angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); } - angularity /= (jet.pt() * (jet.r() / 100.f)); + angularity /= (std::pow(jet.pt(), kappa) * std::pow((jet.r() / 100.f), alpha)); } template @@ -392,7 +381,7 @@ struct JetSubstructureTask { { jetConstituents.clear(); for (auto& jetConstituent : jet.template tracks_as()) { - fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), pdg->Mass(jetConstituent.pdgCode())); + fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), JetConstituentStatus::track, pdg->Mass(jetConstituent.pdgCode())); } nSub = jetsubstructureutilities::getNSubjettiness(jet, particles, particles, particles, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); jetReclustering(jet, jetSplittingsMCPTable); diff --git a/PWGJE/Tasks/jetSubstructureHF.h b/PWGJE/Tasks/jetSubstructureHF.h index 7aa47a466df..0dbe9aa6e3f 100644 --- a/PWGJE/Tasks/jetSubstructureHF.h +++ b/PWGJE/Tasks/jetSubstructureHF.h @@ -52,8 +52,6 @@ #include -// NB: runDataProcessing.h must be included after customize! - template struct JetSubstructureHFTask { o2::framework::Produces jetSubstructureDataTable; @@ -83,9 +81,6 @@ struct JetSubstructureHFTask { o2::framework::Configurable doPairBkg{"doPairBkg", true, "save bkg pairs"}; o2::framework::Configurable pairConstituentPtMin{"pairConstituentPtMin", 1.0, "pt cut off for constituents going into pairs"}; o2::framework::Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - o2::framework::Configurable applyTrackingEfficiency{"applyTrackingEfficiency", {false}, "configurable to decide whether to apply artificial tracking efficiency (discarding tracks) in jet finding"}; - o2::framework::Configurable> trackingEfficiencyPtBinning{"trackingEfficiencyPtBinning", {0., 10, 999.}, "pt binning of tracking efficiency array if applyTrackingEfficiency is true"}; - o2::framework::Configurable> trackingEfficiency{"trackingEfficiency", {1.0, 1.0}, "tracking efficiency array applied to jet finding if applyTrackingEfficiency is true"}; o2::framework::Configurable recoilRegion{"recoilRegion", 0.6, "recoil acceptance in phi"}; o2::framework::Service pdg; @@ -141,15 +136,6 @@ struct JetSubstructureHFTask { candMass = jetcandidateutilities::getTablePDGMass(); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); - - if (applyTrackingEfficiency) { - if (trackingEfficiencyPtBinning->size() < 2) { - LOGP(fatal, "jetFinder workflow: trackingEfficiencyPtBinning configurable should have at least two bin edges"); - } - if (trackingEfficiency->size() + 1 != trackingEfficiencyPtBinning->size()) { - LOGP(fatal, "jetFinder workflow: trackingEfficiency configurable should have exactly one less entry than the number of bin edges set in trackingEfficiencyPtBinning configurable"); - } - } } o2::framework::Preslice TracksPerCollision = o2::aod::jtrack::collisionId; @@ -209,7 +195,7 @@ struct JetSubstructureHFTask { int nHFInSubjet1 = 0; for (auto& subjet1Constituent : parentSubJet1.constituents()) { - if (subjet1Constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidate)) { + if (subjet1Constituent.template user_info().getStatus() == JetConstituentStatus::candidate) { nHFInSubjet1++; } } @@ -231,10 +217,10 @@ struct JetSubstructureHFTask { std::vector candidates; std::vector clusters; for (const auto& constituent : sorted_by_pt(parentSubJet2.constituents())) { - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::track)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::track) { tracks.push_back(constituent.template user_info().getIndex()); } - if (constituent.template user_info().getStatus() == static_cast(JetConstituentStatus::candidate)) { + if (constituent.template user_info().getStatus() == JetConstituentStatus::candidate) { candidates.push_back(constituent.template user_info().getIndex()); } } @@ -369,7 +355,7 @@ struct JetSubstructureHFTask { } if constexpr (!std::is_same_v, o2::aod::JetParticles>) { - if (!jetfindingutilities::isTrackSelected(track, trackSelection, applyTrackingEfficiency, trackingEfficiency, trackingEfficiencyPtBinning)) { + if (!jetfindingutilities::isTrackSelected(track, trackSelection)) { continue; } } @@ -470,7 +456,7 @@ struct JetSubstructureHFTask { } angularity += std::pow(constituent.pt(), kappa) * std::pow(jetutilities::deltaR(jet, constituent), alpha); } - angularity /= (jet.pt() * (jet.r() / 100.f)); + angularity /= (std::pow(jet.pt(), kappa) * std::pow((jet.r() / 100.f), alpha)); } template @@ -482,7 +468,7 @@ struct JetSubstructureHFTask { } int nHFCandidates = 0; for (auto& jetHFCandidate : jet.template candidates_as()) { - fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidate), candMass); + fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), JetConstituentStatus::candidate, candMass); nHFCandidates++; } nSub = jetsubstructureutilities::getNSubjettiness(jet, tracks, tracks, candidates, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); @@ -535,11 +521,11 @@ struct JetSubstructureHFTask { { jetConstituents.clear(); for (auto& jetConstituent : jet.template tracks_as()) { - fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), pdg->Mass(jetConstituent.pdgCode())); + fastjetutilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), JetConstituentStatus::track, pdg->Mass(jetConstituent.pdgCode())); } int nHFCandidates = 0; for (auto& jetHFCandidate : jet.template candidates_as()) { - fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidate), candMass); + fastjetutilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), JetConstituentStatus::candidate, candMass); nHFCandidates++; } nSub = jetsubstructureutilities::getNSubjettiness(jet, particles, particles, candidates, 2, fastjet::contrib::CA_Axes(), true, zCut, beta); diff --git a/PWGJE/Tasks/jetSubstructureHFOutput.h b/PWGJE/Tasks/jetSubstructureHFOutput.h index ac35f02ab9d..2eb799a6708 100644 --- a/PWGJE/Tasks/jetSubstructureHFOutput.h +++ b/PWGJE/Tasks/jetSubstructureHFOutput.h @@ -36,8 +36,6 @@ #include #include -// NB: runDataProcessing.h must be included after customize! - template struct JetSubstructureHFOutputTask { @@ -329,10 +327,10 @@ struct JetSubstructureHFOutputTask { std::copy(pairPerpCone1PerpCone2EnergySpan.begin(), pairPerpCone1PerpCone2EnergySpan.end(), std::back_inserter(pairPerpCone1PerpCone2EnergyVec)); std::copy(pairPerpCone1PerpCone2ThetaSpan.begin(), pairPerpCone1PerpCone2ThetaSpan.end(), std::back_inserter(pairPerpCone1PerpCone2ThetaVec)); - std::vector splittingMatchesGeoVec; - std::vector splittingMatchesPtVec; - std::vector splittingMatchesHFVec; - std::vector pairMatchesVec; + std::vector splittingMatchesGeoVec; + std::vector splittingMatchesPtVec; + std::vector splittingMatchesHFVec; + std::vector pairMatchesVec; if (doprocessOutputSubstructureMatchingData || doprocessOutputSubstructureMatchingMC) { splittingMatchesGeoVec = splittingMatchesGeoVecVec[jet.globalIndex()]; splittingMatchesPtVec = splittingMatchesPtVecVec[jet.globalIndex()]; @@ -367,7 +365,7 @@ struct JetSubstructureHFOutputTask { if (candidateTableIndex != candidateMap.end()) { candidatesIndices.push_back(candidateTableIndex->second); } - rho = candidate.rho(); + rho = candidate.rho(); // doesn't work if multiple jet candidates } if (nJetInCollision == 0) { float centrality = -1.0; @@ -413,6 +411,9 @@ struct JetSubstructureHFOutputTask { { for (const auto& jet : jets) { auto const& candidates = jet.template candidates_as(); + for (auto const& candidate : candidates) { + candidateSelectionFlags[candidate.globalIndex()] = true; + } if (jet.pt() < jetPtMin) { for (const auto& candidate : candidates) { candidateSelectionFlags[candidate.globalIndex()] = false; @@ -445,6 +446,7 @@ struct JetSubstructureHFOutputTask { { for (const auto& jet : jets) { auto candidateId = jet.candidateId(); + candidateSelectionFlags[candidateId] = true; if (jet.pt() < jetPtMin) { candidateSelectionFlags[candidateId] = false; continue; @@ -578,7 +580,7 @@ struct JetSubstructureHFOutputTask { } else { continue; } - for (const auto& jetRadiiValue : jetRadiiValues) { + for (const auto& jetRadiiValue : recoilJetRadiiValues) { if (recoilJet.r() == round(jetRadiiValue * 100.0f)) { auto const& jet = recoilJet.template jet_as(); std::vector geoMatching; diff --git a/PWGJE/Tasks/jetSubstructureHFPCH.cxx b/PWGJE/Tasks/jetSubstructureHFPCH.cxx new file mode 100644 index 00000000000..384b1987f80 --- /dev/null +++ b/PWGJE/Tasks/jetSubstructureHFPCH.cxx @@ -0,0 +1,10 @@ +// Copyright 2019-2026 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. diff --git a/PWGJE/Tasks/jetSubstructureOutput.cxx b/PWGJE/Tasks/jetSubstructureOutput.cxx index 32a53ca6516..954214c7226 100644 --- a/PWGJE/Tasks/jetSubstructureOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureOutput.cxx @@ -19,9 +19,9 @@ #include "PWGJE/DataModel/JetSubstructure.h" #include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include #include +#include #include #include #include @@ -38,8 +38,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// NB: runDataProcessing.h must be included after customize! - struct JetSubstructureOutputTask { Produces collisionOutputTableData; @@ -187,11 +185,11 @@ struct JetSubstructureOutputTask { std::copy(pairPerpCone1PerpCone2EnergySpan.begin(), pairPerpCone1PerpCone2EnergySpan.end(), std::back_inserter(pairPerpCone1PerpCone2EnergyVec)); std::copy(pairPerpCone1PerpCone2ThetaSpan.begin(), pairPerpCone1PerpCone2ThetaSpan.end(), std::back_inserter(pairPerpCone1PerpCone2ThetaVec)); - std::vector splittingMatchesGeoVec; - std::vector splittingMatchesPtVec; - std::vector splittingMatchesHFVec; - std::vector pairMatchesVec; - std::vector dummyVec; + std::vector splittingMatchesGeoVec; + std::vector splittingMatchesPtVec; + std::vector splittingMatchesHFVec; + std::vector pairMatchesVec; + std::vector dummyVec; if (doprocessOutputSubstructureMatchingData || doprocessOutputSubstructureMatchingMC) { splittingMatchesGeoVec = splittingMatchesGeoVecVec[jet.globalIndex()]; splittingMatchesPtVec = splittingMatchesPtVecVec[jet.globalIndex()]; diff --git a/PWGJE/Tasks/jetTaggerHFQA.cxx b/PWGJE/Tasks/jetTaggerHFQA.cxx index f2ee579935e..1dd147c0ff7 100644 --- a/PWGJE/Tasks/jetTaggerHFQA.cxx +++ b/PWGJE/Tasks/jetTaggerHFQA.cxx @@ -21,12 +21,10 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetTagging.h" -#include "Common/DataModel/Multiplicity.h" - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" #include +#include +#include +#include #include #include #include @@ -36,8 +34,8 @@ #include #include -#include #include +#include #include #include #include @@ -109,7 +107,6 @@ struct JetTaggerHFQA { ConfigurableAxis binMass{"binMass", {50, 0, 10.f}, ""}; ConfigurableAxis binSigmaLxy{"binSigmaLxy", {100, 0., 0.1}, ""}; ConfigurableAxis binSigmaLxyz{"binSigmaLxyz", {100, 0., 0.1}, ""}; - ConfigurableAxis binMultScaledFT0M{"binMultScaledFT0M", {VARIABLE_WIDTH, 0, 0.2, 0.3, 0.4, 0.6, 0.8, 1., 1.4, 1.8, 2.4, 3.6, 5., 20.}, "Percentiles of scaled FT0M: 100-90%, 90-80%, 80-70%, 70-60%, 60-50%, 50-40%, 40-30%, 30-20%, 20-10%, 10-1%, 1-0.1%"}; int numberOfJetFlavourSpecies = 6; std::vector eventSelectionBits; @@ -151,7 +148,6 @@ struct JetTaggerHFQA { AxisSpec axisSigmaLxy = {binSigmaLxy, "#sigma_{L_{XY}} [cm]"}; AxisSpec axisSigmaLxyz = {binSigmaLxyz, "#sigma_{L_{XYZ}} [cm]"}; AxisSpec axisFracSecPt = {100, 0, 1, "#frac{#Sigma#it{p}_{T}^{secondary track}}{#it{p}_{T, jet}}"}; - AxisSpec axisMultScaledFT0M = {binMultScaledFT0M, "Multiplicity classes"}; registry.add("h_collision_events", "data;mcd;mcp evnets", {HistType::kTH1F, {{4, 0.0, 4.0}}}); if (doprocessTracksDca) { @@ -397,25 +393,6 @@ struct JetTaggerHFQA { registry.add("h2_taggedjet_pt_3prong_mass_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); registry.add("h2_taggedjet_pt_3prong_mass_xyz_N1", "", {HistType::kTH2F, {{axisJetPt}, {axisMass}}}); } - if (doprocessSV3ProngDataMult) { - registry.add("h_event_mult", "", {HistType::kTH1F, {{axisMultScaledFT0M}}}); - registry.add("h2_jet_pt_mult", "", {HistType::kTH2F, {{axisJetPt}, {axisMultScaledFT0M}}}); - registry.add("h2_jet_eta_mult", "", {HistType::kTH2F, {{axisEta}, {axisMultScaledFT0M}}}); - registry.add("h2_jet_phi_mult", "", {HistType::kTH2F, {{axisPhi}, {axisMultScaledFT0M}}}); - if (fillGeneralSVQA) { - registry.add("h2_3prong_nprongs_mult", "", {HistType::kTH2F, {{axisNprongs}, {axisMultScaledFT0M}}}); - registry.add("hn_jet_3prong_Sxy_mult", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisMultScaledFT0M}}}); - if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_mult", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisMultScaledFT0M}}}); - } - } - registry.add("hn_jet_3prong_Sxy_N1_mult", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisMultScaledFT0M}}}); - registry.add("hn_taggedjet_3prong_Sxy_N1_mult", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisMultScaledFT0M}}}); - if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_N1_mult", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisMultScaledFT0M}}}); - registry.add("hn_taggedjet_3prong_Sxyz_N1_mult", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisMultScaledFT0M}}}); - } - } if (doprocessSV2ProngMCD || doprocessSV2ProngMCDWeighted || doprocessSV2ProngMCPMCDMatched || doprocessSV2ProngMCPMCDMatchedWeighted) { if (!(doprocessIPsMCD || doprocessIPsMCDWeighted || doprocessIPsMCPMCDMatched || doprocessIPsMCPMCDMatchedWeighted) && !(doprocessJPMCD || doprocessJPMCDWeighted || doprocessJPMCPMCDMatched || doprocessJPMCPMCDMatchedWeighted) && !(doprocessSV3ProngMCD || doprocessSV3ProngMCDWeighted || doprocessSV3ProngMCPMCDMatched || doprocessSV3ProngMCPMCDMatchedWeighted)) { registry.add("h2_jet_pt_flavour", "", {HistType::kTH2F, {{axisJetPt}, {axisJetFlavour}}}); @@ -464,25 +441,6 @@ struct JetTaggerHFQA { registry.add("h3_taggedjet_pt_3prong_mass_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); registry.add("h3_taggedjet_pt_3prong_mass_xyz_N1_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMass}, {axisJetFlavour}}}); } - if (doprocessSV3ProngMCDMult || doprocessSV3ProngMCDMultWeighted || doprocessSV3ProngMCPMCDMatchedMult || doprocessSV3ProngMCPMCDMatchedMultWeighted) { - registry.add("h_event_mult", "", {HistType::kTH1F, {{axisMultScaledFT0M}}}); - registry.add("h3_jet_pt_mult_flavour", "", {HistType::kTH3F, {{axisJetPt}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - registry.add("h3_jet_eta_mult_flavour", "", {HistType::kTH3F, {{axisEta}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - registry.add("h3_jet_phi_mult_flavour", "", {HistType::kTH3F, {{axisPhi}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - if (fillGeneralSVQA) { - registry.add("h3_3prong_nprongs_mult_flavour", "", {HistType::kTH3F, {{axisNprongs}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - registry.add("hn_jet_3prong_Sxy_mult_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxy}, {axisSigmaLxy}, {axisSxy}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_mult_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisLxyz}, {axisSigmaLxyz}, {axisSxyz}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - } - } - registry.add("hn_jet_3prong_Sxy_N1_mult_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisMass}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_3prong_Sxy_N1_mult_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisSxyz}, {axisMass}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - if (fillSVxyz) { - registry.add("hn_jet_3prong_Sxyz_N1_mult_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxyz}, {axisMass}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - registry.add("hn_taggedjet_3prong_Sxyz_N1_mult_flavour", "", {HistType::kTHnSparseF, {{axisJetPt}, {axisSxy}, {axisSxyz}, {axisMass}, {axisMultScaledFT0M}, {axisJetFlavour}}}); - } - } } // Filter trackCuts = (aod::jtrack::pt >= trackCuts->at(0) && aod::jtrack::pt < trackCuts->at(1) && aod::jtrack::eta > trackCuts->at(2) && aod::jtrack::eta < trackCuts->at(3)); @@ -546,21 +504,6 @@ struct JetTaggerHFQA { return true; } - float getScaledFT0A(const float multFT0A) - { - return multFT0A / meanFT0A; - } - - float getScaledFT0C(const float multFT0C) - { - return multFT0C / meanFT0C; - } - - float getScaledFT0M(const float multFT0A, const float multFT0C) - { - return 0.5 * (getScaledFT0A(multFT0A) + getScaledFT0C(multFT0C)); - } - template void fillValidationFlavourDefMCD(T const& mcdjet, V const& tracks, W const& particles, X const& particlesPerColl, float eventWeight = 1.0) { @@ -1052,50 +995,6 @@ struct JetTaggerHFQA { } } - template - void fillHistogramSV3ProngDataMult(T const& collision, U const& jet, V const& /*prongs*/) - { - if (jet.template secondaryVertices_as().size() < 1) - return; - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - registry.fill(HIST("h2_jet_pt_mult"), jet.pt(), scaledFT0M); - registry.fill(HIST("h2_jet_eta_mult"), jet.eta(), scaledFT0M); - registry.fill(HIST("h2_jet_phi_mult"), jet.phi(), scaledFT0M); - if (fillGeneralSVQA) { - registry.fill(HIST("h2_3prong_nprongs_mult"), jet.template secondaryVertices_as().size(), scaledFT0M); - for (const auto& prong : jet.template secondaryVertices_as()) { - registry.fill(HIST("hn_jet_3prong_Sxy_mult"), jet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), scaledFT0M); - if (fillSVxyz) { - registry.fill(HIST("hn_jet_3prong_Sxyz_mult"), jet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), scaledFT0M); - } - } - } - bool checkSv = false; - auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { - auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); - auto massSV = bjetCand.m(); - registry.fill(HIST("hn_jet_3prong_Sxy_N1_mult"), jet.pt(), maxSxy, massSV, scaledFT0M); - if (jet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_mult"), jet.pt(), maxSxy, massSV, scaledFT0M); - } - } - if (fillSVxyz) { - checkSv = false; - auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(jet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { - auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); - auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("hn_jet_3prong_Sxyz_N1_mult"), jet.pt(), maxSxyz, massSV, scaledFT0M); - if (jet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_mult"), jet.pt(), maxSxyz, massSV, scaledFT0M); - } - } - } - } - template void fillHistogramSV2ProngMCD(T const& mcdjet, U const& /*prongs*/, float eventWeight = 1.0) { @@ -1208,54 +1107,6 @@ struct JetTaggerHFQA { } } - template - void fillHistogramSV3ProngMCDMult(T const& collision, U const& mcdjet, V 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(); - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - if (mcdjet.template secondaryVertices_as().size() < 1) - return; - registry.fill(HIST("h3_jet_pt_mult_flavour"), mcdjet.pt(), scaledFT0M, origin, eventWeight); - registry.fill(HIST("h3_jet_eta_mult_flavour"), mcdjet.eta(), scaledFT0M, origin, eventWeight); - registry.fill(HIST("h3_jet_phi_mult_flavour"), mcdjet.phi(), scaledFT0M, origin, eventWeight); - if (fillGeneralSVQA) { - registry.fill(HIST("h3_3prong_nprongs_mult_flavour"), mcdjet.template secondaryVertices_as().size(), scaledFT0M, origin, eventWeight); - for (const auto& prong : mcdjet.template secondaryVertices_as()) { - registry.fill(HIST("hn_jet_3prong_Sxy_mult_flavour"), mcdjet.pt(), prong.decayLengthXY(), prong.errorDecayLengthXY(), prong.decayLengthXY() / prong.errorDecayLengthXY(), scaledFT0M, origin, eventWeight); - if (fillSVxyz) { - registry.fill(HIST("hn_jet_3prong_Sxyz_mult_flavour"), mcdjet.pt(), prong.decayLength(), prong.errorDecayLength(), prong.decayLength() / prong.errorDecayLength(), scaledFT0M, origin, eventWeight); - } - } - } - bool checkSv = false; - auto bjetCand = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(2), prongCuts->at(4), prongCuts->at(5), false, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCand, svDispersionMax)) { - auto maxSxy = bjetCand.decayLengthXY() / bjetCand.errorDecayLengthXY(); - auto massSV = bjetCand.m(); - registry.fill(HIST("hn_jet_3prong_Sxy_N1_mult_flavour"), mcdjet.pt(), maxSxy, massSV, scaledFT0M, origin, eventWeight); - if (mcdjet.isTagged(BJetTaggingMethod::SV)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxy_N1_mult_flavour"), mcdjet.pt(), maxSxy, massSV, scaledFT0M, origin, eventWeight); - } - } - if (fillSVxyz) { - auto bjetCandXYZ = jettaggingutilities::jetFromProngMaxDecayLength(mcdjet, prongCuts->at(0), prongCuts->at(1), prongCuts->at(3), prongCuts->at(4), prongCuts->at(5), true, &checkSv); - if (checkSv && jettaggingutilities::svAcceptance(bjetCandXYZ, svDispersionMax)) { - auto maxSxyz = bjetCandXYZ.decayLength() / bjetCandXYZ.errorDecayLength(); - auto massSV = bjetCandXYZ.m(); - registry.fill(HIST("hn_jet_3prong_Sxyz_N1_mult_flavour"), mcdjet.pt(), maxSxyz, massSV, scaledFT0M, origin, eventWeight); - if (mcdjet.isTagged(BJetTaggingMethod::SV3D)) { - registry.fill(HIST("hn_taggedjet_3prong_Sxyz_N1_mult_flavour"), mcdjet.pt(), maxSxyz, massSV, scaledFT0M, origin, eventWeight); - } - } - } - } - void processDummy(aod::Collision const&, aod::Tracks const&) { } @@ -1749,27 +1600,6 @@ struct JetTaggerHFQA { } PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngData, "Fill 3prong imformation for data jets", false); - void processSV3ProngDataMult(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::DataSecondaryVertex3Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - registry.fill(HIST("h_event_mult"), scaledFT0M); - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(jet)) { - continue; - } - fillHistogramSV3ProngDataMult(collision, jet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngDataMult, "Fill 3prong imformation for data jets", false); - void processSV2ProngMCD(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex2Prongs const& prongs) { if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { @@ -1941,104 +1771,6 @@ struct JetTaggerHFQA { } } PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatchedWeighted, "Fill 3prong imformation for mcd jets", false); - - void processSV3ProngMCDMult(soa::Filtered::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - registry.fill(HIST("h_event_mult"), scaledFT0M); - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - fillHistogramSV3ProngMCDMult(collision, mcdjet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCDMult, "Fill 3prong imformation for mcd jets with multiplicity", false); - - void processSV3ProngMCDMultWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, aod::MCDSecondaryVertex3Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - if (collision.isOutlier()) { - return; - } - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - registry.fill(HIST("h_event_mult"), scaledFT0M); - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - fillHistogramSV3ProngMCDMult(collision, mcdjet, prongs, collision.weight()); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCDMultWeighted, "Fill 3prong imformation for mcd jets with multiplicity weighted", false); - - void processSV3ProngMCPMCDMatchedMult(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - registry.fill(HIST("h_event_mult"), scaledFT0M); - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - if (!mcdjet.has_matchedJetGeo()) { - continue; - } - if (!doprocessSV3ProngMCDMult) - fillHistogramSV3ProngMCDMult(collision, mcdjet, prongs); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatchedMult, "Fill 3prong imformation for mcd jets matched with multiplicity", false); - - void processSV3ProngMCPMCDMatchedMultWeighted(soa::Filtered>::iterator const& collision, soa::Join const& mcdjets, soa::Join const& /*mcpjets*/, aod::MCDSecondaryVertex3Prongs const& prongs) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - if (collision.isOutlier()) { - return; - } - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float scaledFT0M = getScaledFT0M(multFT0A, multFT0C); - registry.fill(HIST("h_event_mult"), scaledFT0M); - for (auto const& mcdjet : mcdjets) { - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaCuts->at(0), jetEtaCuts->at(1), trackCuts->at(2), trackCuts->at(3))) { - continue; - } - if (!isAcceptedJet(mcdjet)) { - continue; - } - if (!mcdjet.has_matchedJetGeo()) { - continue; - } - if (!doprocessSV3ProngMCDMultWeighted) - fillHistogramSV3ProngMCDMult(collision, mcdjet, prongs, collision.weight()); - } - } - PROCESS_SWITCH(JetTaggerHFQA, processSV3ProngMCPMCDMatchedMultWeighted, "Fill 3prong imformation for mcd jets matched with multiplicity weightd", false); }; using JetTaggerQAChargedDataJets = soa::Join; diff --git a/PWGJE/Tasks/jetTriggerChargedQa.cxx b/PWGJE/Tasks/jetTriggerChargedQa.cxx index d8b795aa1d6..22ee5b8306d 100644 --- a/PWGJE/Tasks/jetTriggerChargedQa.cxx +++ b/PWGJE/Tasks/jetTriggerChargedQa.cxx @@ -18,15 +18,12 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/EventSelection.h" - -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetTutorial.cxx b/PWGJE/Tasks/jetTutorial.cxx index 48742399bf7..828a23a86ce 100644 --- a/PWGJE/Tasks/jetTutorial.cxx +++ b/PWGJE/Tasks/jetTutorial.cxx @@ -23,12 +23,12 @@ #include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetTutorialSkeleton.cxx b/PWGJE/Tasks/jetTutorialSkeleton.cxx index eeccd409d26..763f2dc4c0e 100644 --- a/PWGJE/Tasks/jetTutorialSkeleton.cxx +++ b/PWGJE/Tasks/jetTutorialSkeleton.cxx @@ -18,10 +18,10 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/jetValidationQA.cxx b/PWGJE/Tasks/jetValidationQA.cxx index 4ccd260f47e..999a1feeaef 100644 --- a/PWGJE/Tasks/jetValidationQA.cxx +++ b/PWGJE/Tasks/jetValidationQA.cxx @@ -18,11 +18,11 @@ #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/mcGeneratorStudies.cxx b/PWGJE/Tasks/mcGeneratorStudies.cxx index 8310b03c25a..1fd61f64bfc 100644 --- a/PWGJE/Tasks/mcGeneratorStudies.cxx +++ b/PWGJE/Tasks/mcGeneratorStudies.cxx @@ -19,18 +19,18 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "EMCALBase/Geometry.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include #include +#include +#include +#include #include +#include #include #include #include -#include "TDatabasePDG.h" +#include #include #include diff --git a/PWGJE/Tasks/nsubjettiness.cxx b/PWGJE/Tasks/nsubjettiness.cxx index 133e1e6323b..e09bff37b17 100644 --- a/PWGJE/Tasks/nsubjettiness.cxx +++ b/PWGJE/Tasks/nsubjettiness.cxx @@ -20,11 +20,11 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include #include +#include #include +#include #include #include #include @@ -32,8 +32,8 @@ #include #include -#include "fastjet/contrib/AxesDefinition.hh" #include +#include #include diff --git a/PWGJE/Tasks/nucleiInJets.cxx b/PWGJE/Tasks/nucleiInJets.cxx index 5f83bffc8c6..f6a419992b8 100644 --- a/PWGJE/Tasks/nucleiInJets.cxx +++ b/PWGJE/Tasks/nucleiInJets.cxx @@ -14,36 +14,39 @@ #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" +// #include "PWGLF/DataModel/LFParticleIdentification.h" #include "PWGLF/Utils/inelGt.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include #include +#include #include +#include #include #include #include +#include #include #include -#include "TDatabasePDG.h" #include #include #include -#include +#include +#include #include #include @@ -1601,7 +1604,7 @@ struct nucleiInJets { //////////////////////////////////////// } - void processJetTracksData(soa::Join::iterator const& collision, + void processJetTracksData(soa::Join::iterator const& collision, chargedJetstrack const& chargedjets, soa::Join const& tracks, TrackCandidates const&, aod::JBCs const&) { auto bc = collision.bc_as(); @@ -1665,7 +1668,7 @@ struct nucleiInJets { } } - void processJetTracksDataLfPid(soa::Join::iterator const& collision, + void processJetTracksDataLfPid(soa::Join::iterator const& collision, chargedJetstrack const& chargedjets, soa::Join const& tracks, TrackCandidatesLfPid const&, aod::JBCs const&) { auto bc = collision.bc_as(); diff --git a/PWGJE/Tasks/phiInJets.cxx b/PWGJE/Tasks/phiInJets.cxx index 8571b76b880..085da029904 100644 --- a/PWGJE/Tasks/phiInJets.cxx +++ b/PWGJE/Tasks/phiInJets.cxx @@ -25,22 +25,22 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include +#include #include +#include #include #include #include #include -#include "TRandom.h" #include #include #include +#include #include #include diff --git a/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx b/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx index 0f4dbf82e41..81cd439194e 100644 --- a/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx +++ b/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx @@ -20,31 +20,43 @@ #include "PWGJE/DataModel/PhotonChargedTriggerCorrelation.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +// +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TableHelper.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Math/Vector4D.h" -#include "TMath.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include #include #include #include +#include +#include #include -#include +#include +#include #include #include #include @@ -716,7 +728,7 @@ struct PhotonChargedTriggerCorrelation { // init analysis variables // get variables from other tasks - getTaskOptionValue(initContext, "photon-charged-trigger-producer", "etaMax", etaMax, false); + o2::common::core::getTaskOptionValue(initContext, "photon-charged-trigger-producer", "etaMax", etaMax, false); // histograms from ccdb initCcdbHistograms(); diff --git a/PWGJE/Tasks/photonChargedTriggerProducer.cxx b/PWGJE/Tasks/photonChargedTriggerProducer.cxx index d600ca43c03..4ffc372ad67 100644 --- a/PWGJE/Tasks/photonChargedTriggerProducer.cxx +++ b/PWGJE/Tasks/photonChargedTriggerProducer.cxx @@ -15,35 +15,30 @@ /// /// Table producer for photon-jet angular correlation analysis (see photonChargedTriggerCorrelation.cxx) -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/PhotonChargedTriggerCorrelation.h" +// +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "Common/Core/TableHelper.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "Math/Vector4D.h" -#include "TMath.h" +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include -#include -#include #include -#include -#include -#include #include #include diff --git a/PWGJE/Tasks/photonIsolationQA.cxx b/PWGJE/Tasks/photonIsolationQA.cxx index 1738fef952f..4f31995b218 100644 --- a/PWGJE/Tasks/photonIsolationQA.cxx +++ b/PWGJE/Tasks/photonIsolationQA.cxx @@ -15,13 +15,13 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/recoilJets.cxx b/PWGJE/Tasks/recoilJets.cxx index 2428d4c2dd4..bb141c84a86 100644 --- a/PWGJE/Tasks/recoilJets.cxx +++ b/PWGJE/Tasks/recoilJets.cxx @@ -18,31 +18,38 @@ #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetSubtraction.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include #include +#include #include +#include #include #include #include +#include #include -#include "TRandom3.h" #include +#include +#include +#include #include +#include #include +#include #include #include #include #include -#include +#include #include using namespace o2; @@ -50,96 +57,164 @@ using namespace o2::framework; using namespace o2::framework::expressions; // Shorthand notations -using FilteredColl = soa::Filtered>::iterator; -using FilteredCollPartLevel = soa::Filtered>::iterator; -using FilteredCollDetLevelGetWeight = soa::Filtered>::iterator; -using FilteredEventMultiplicity = soa::Filtered>::iterator; -using FilteredEventMultiplicityDetLevelGetWeight = soa::Filtered>::iterator; -using FilteredEventMultiplicityPartLevel = soa::Filtered>::iterator; -using FilteredJets = soa::Filtered>; -using FilteredJetsDetLevel = soa::Filtered>; -using FilteredJetsPartLevel = soa::Filtered>; - -using FilteredMatchedJetsDetLevel = soa::Filtered>; -using FilteredMatchedJetsPartLevel = soa::Filtered>; - -using FilteredTracks = soa::Filtered; -using FilteredParticles = soa::Filtered; - -using ColEvSelEA = soa::Filtered>::iterator; -using BCsRun3 = soa::Join; // aod::Run3MatchedToBCExclusive +// --- Collisions (+ rho) +using CollDataIt = soa::Filtered::iterator; +using CollRhoDataIt = soa::Filtered>::iterator; +using CollRhoOutlierDetIt = soa::Filtered>::iterator; +using CollOutlierDetIt = soa::Filtered>::iterator; +using CollDetIt = soa::Filtered::iterator; +using CollRhoDetIt = soa::Filtered>::iterator; + +using CollPartIt = soa::Filtered::iterator; +using CollRhoPartTbl = soa::Join; +using CollRhoPartIt = soa::Filtered>::iterator; +using CollRhoOutlierPartIt = soa::Filtered>::iterator; +using CollRhoOutlierPartTbl = soa::Join; + +// --- Event multiplicity (+ ZDC etc.) +using EvMultZDCDataIt = soa::Filtered>::iterator; +using EvMultOutlierZDCDetIt = soa::Filtered>::iterator; +using EvMultOutlierPartIt = soa::Filtered>::iterator; + +// --- Tracks / Particles +using TrackTbl = soa::Filtered; +using TrackMCLbsTbl = soa::Filtered; +using PartTbl = soa::Filtered; + +// --- Jets (with constituents) +using JetsDataTbl = soa::Filtered>; +using JetsDetTbl = soa::Filtered>; +using JetsPartTbl = soa::Filtered>; + +// --- Matched jets (det <-> part) +using MatchedJetsDetToPartTbl = soa::Filtered>; +using MatchedJetsPartToDetTbl = soa::Filtered>; + +// --- O2 collisions event selection (not JCollisions) +using CollEvSelExtendedIt = soa::Filtered>::iterator; +using BCsRun3Tbl = soa::Join; // aod::Run3MatchedToBCExclusive struct RecoilJets { // List of configurable parameters - Configurable evSel{"evSel", "sel8", "Choose event selection"}; - Configurable trkSel{"trkSel", "globalTracks", "Set track selection"}; - Configurable vertexZCut{"vertexZCut", 10., "Accepted z-vertex range"}; - Configurable fracSig{"fracSig", 0.9, "Fraction of events to use for signal TT"}; - - Configurable trkPtMin{"trkPtMin", 0.15, "Minimum pT of acceptanced tracks"}; - Configurable trkPtMax{"trkPtMax", 100., "Maximum pT of acceptanced tracks"}; - - Configurable trkEtaCut{"trkEtaCut", 0.9, "Eta acceptance of TPC"}; - Configurable jetR{"jetR", 0.4, "Jet cone radius"}; - Configurable maxJetConstituentPt{"maxJetConstituentPt", 100., "Remove jets with constituent above this pT cut"}; - - Configurable randomConeR{"randomConeR", 0.4, "Size of random cone for estimating background fluctuations"}; - Configurable randomConeJetDeltaR{"randomConeJetDeltaR", 0.0, "Min distance between high pT jet axis and random cone axis; if default, min distance is set to R_Jet + R_RC "}; - - Configurable triggerMasks{"triggerMasks", "", "Relevant trigger masks: fTrackLowPt,fTrackHighPt"}; - Configurable skipMBGapEvents{"skipMBGapEvents", false, - "flag to choose to reject min. bias gap events; jet-level rejection " - "applied at the jet finder level, here rejection is applied for " - "collision and track process functions"}; - - Configurable meanFT0A{"meanFT0A", -1., "Mean value of FT0A signal"}; - Configurable meanFT0C{"meanFT0C", -1., "Mean value of FT0C signal"}; - - Configurable meanZeqFT0A{"meanZeqFT0A", -1., "Mean value of equalized FT0A signal"}; - Configurable meanZeqFT0C{"meanZeqFT0C", -1., "Mean value of equalized FT0C signal"}; - - Configurable meanFT0APartLevel{"meanFT0APartLevel", -1., "Mean number of charged part. within FT0A acceptance"}; - Configurable meanFT0CPartLevel{"meanFT0CPartLevel", -1., "Mean number of charged part. within FT0C acceptance"}; - - // Parameters for recoil jet selection - Configurable> ptTTref{"ptTTref", {5., 7}, "Transverse momentum (min, max) range for reference TT"}; - Configurable> ptTTsig{"ptTTsig", {20., 50}, "Transverse momentum (min, max) range for signal TT"}; - Configurable recoilRegion{"recoilRegion", 0.6, "Width of recoil acceptance"}; - Configurable> phiRestrTTSelection{"phiRestrTTSelection", {0., 6.3}, "Restriction on phi angle (min, max) to search for TT"}; - // Leading track and associated track - Configurable> pTLeadTrack{"pTLeadTrack", {4., 6.}, "Transverse momenturm range (min, max) for leading tracks"}; - Configurable pTAssociatTrackMin{"pTAssociatTrackMin", 2., "Min transverse momenturm for associated tracks"}; - - // List of configurable parameters for histograms - Configurable histJetPt{"histJetPt", 100, "Maximum value of jet pT stored in histograms"}; - Configurable histMultBins{"histMultBins", 600, "Number of bins for scaled FT0M multiplicity"}; - Configurable histZDCTimeBins{"histZDCTimeBins", 240, "Number of bins for ZDC timing histograms"}; - - // Axes specification - ConfigurableAxis multFT0CThresh{"multFT0CThresh", {VARIABLE_WIDTH, 0.0, 0.133, 0.233, 0.367, 0.567, 0.767, 1.067, 1.4, 1.867, 2.5, 3.9, 5.4, 6.9, 20.}, "Percentiles of scaled FT0C: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; // default values for raw data - ConfigurableAxis multFT0MThresh{"multFT0MThresh", {VARIABLE_WIDTH, 0.0, 0.167, 0.267, 0.4, 0.567, 0.8, 1.067, 1.4, 1.833, 2.433, 3.667, 5.1, 6.433, 20.}, "Percentiles of scaled FT0M: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; // default values for raw data - - ConfigurableAxis multFT0CThreshPartLevel{"multFT0CThreshPartLevel", {VARIABLE_WIDTH, 0.0, 0.133, 0.233, 0.367, 0.567, 0.767, 1.067, 1.4, 1.867, 2.5, 3.9, 5.4, 6.9, 20.}, "Percentiles of scaled FT0C: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; - ConfigurableAxis multFT0MThreshPartLevel{"multFT0MThreshPartLevel", {VARIABLE_WIDTH, 0.0, 0.167, 0.267, 0.4, 0.567, 0.8, 1.067, 1.4, 1.833, 2.433, 3.667, 5.1, 6.433, 20.}, "Percentiles of scaled FT0M: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; + // ---------- Event selection ---------- + struct EvCfg : ConfigurableGroup { + std::string prefix = "event"; + Configurable sel{"sel", "sel8", "Choose event selection"}, + triggerMasks{"triggerMasks", "", "Relevant trigger masks: fTrackLowPt,fTrackHighPt"}; + + Configurable vertexZCut{"vertexZCut", 10., "Accepted z-vertex range"}; + Configurable isMCJJProd{"isMCJJProd", false, "Flag to select MC production: MB (false) or JJ(true)"}, + skipMBGapEvents{"skipMBGapEvents", false, + "Flag to choose to reject min. bias gap events; jet-level rejection " + "applied at the jet finder level, here rejection is applied for " + "collision and track process functions"}; + } ev; + + // ---------- RCT / flag-based selections ---------- + struct Rct : ConfigurableGroup { + std::string prefix = "rct"; + Configurable label{"label", "CBT_hadronPID", "Apply rct flag"}; // CBT + + Configurable enable{"enable", true, "Apply RCT selections"}, + requireZDC{"requireZDC", false, "Require ZDC flag"}, + rejectLimitedAcceptance{"rejectLimitedAcceptance", false, "Reject LimitedAcceptance flag"}; + } rct; + + // ---------- Track selection ---------- + struct Trk : ConfigurableGroup { + std::string prefix = "track"; + Configurable sel{"sel", "globalTracks", "Set track selection"}; + + Configurable ptMin{"ptMin", 0.15, "Minimum pT of acceptanced tracks"}, + ptMax{"ptMax", 100., "Maximum pT of acceptanced tracks"}, + etaCut{"etaCut", 0.9, "Eta acceptance of TPC"}; + } trk; + + // ---------- Jet reconstruction ---------- + struct Jet : ConfigurableGroup { + std::string prefix = "jet"; + Configurable constituentPtMax{"constituentPtMax", 100., "Remove jets with constituent above this pT cut"}, + radius{"radius", 0.4, "Jet cone radius"}; + } jet; + + // ---------- Background tools ---------- + struct Bkgd : ConfigurableGroup { + std::string prefix = "bkgd"; + + // Random cone method + Configurable randomConeR{"randomConeR", 0.4, "Size of random cone for estimating background fluctuations"}, + minDeltaRToJet{"minDeltaRToJet", 0.0, + "Min dR between random cone axis and lead./sublead. jet axis; if 0 -> use R_jet + R_rc"}; + } bkgd; + + // ---------- Normalization FT0 by means ---------- + struct FT0A : ConfigurableGroup { + std::string prefix = "ft0a"; + Configurable mean{"mean", -1., "Mean FT0A signal"}, + meanPartLevel{"meanPartLevel", -1., "Mean Nch (part level) within FT0A acceptance"}, + meanZeq{"meanZeq", -1., "Mean equalized FT0A signal"}; + } ft0a; + + struct FT0C : ConfigurableGroup { + std::string prefix = "ft0c"; + Configurable mean{"mean", -1., "Mean FT0C signal"}, + meanPartLevel{"meanPartLevel", -1., "Mean Nch (part level) within FT0C acceptance"}, + meanZeq{"meanZeq", -1., "Mean equalized FT0C signal"}; + } ft0c; + + // ---------- TT / recoil ---------- + struct TT : ConfigurableGroup { + std::string prefix = "triggerTrack"; + Configurable fracSig{"fracSig", 0.9, "Fraction of events used for signal TT"}; + Configurable recoilRegion{"recoilRegion", 0.6, "Width of recoil acceptance"}; + + Configurable> refPtRange{"refPtRange", {5., 7}, "Reference TT pT range [min,max] (GeV/c)"}, + sigPtRange{"sigPtRange", {20., 50}, "Signal TT pT range [min,max] (GeV/c)"}; + + Configurable> phiRestr{"phiRestr", {0., 6.3}, "Phi restriction [min,max] (rad) for TT search"}; + } tt; + + // ---------- Two particle correlations ---------- + struct TwoPartCorrel : ConfigurableGroup { + std::string prefix = "twoPartCorrel"; + Configurable> leadPtRange{"leadPtRange", {4., 6.}, "Leading track pT range [min,max] (GeV/c)"}; + Configurable associatTrackPtMin{"associatTrackPtMin", 2., "Associated track minimum pT (GeV/c)"}; + } twoPartCorrel; + + // ---------- Histogram settings ---------- + struct Hist : ConfigurableGroup { + std::string prefix = "hist"; + Configurable sumw2{"sumw2", false, "Enable Sumw2() for histograms"}; + + Configurable jetPtMax{"jetPtMax", 100, "Maximum jet pT stored"}, + multNBins{"multNBins", 600, "Number of bins for scaled FT0M multiplicity"}, + zdcTimeNBins{"zdcTimeNBins", 240, "Number of bins for ZDC timing histograms"}; + + ConfigurableAxis multFT0CThresh{"multFT0CThresh", {VARIABLE_WIDTH, 0.0, 0.133, 0.233, 0.367, 0.567, 0.767, 1.067, 1.4, 1.867, 2.5, 3.9, 5.4, 6.9, 20.}, "Percentiles of scaled FT0C: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; // default values for raw data + ConfigurableAxis multFT0CThreshPartLevel{"multFT0CThreshPartLevel", {VARIABLE_WIDTH, 0.0, 0.133, 0.233, 0.367, 0.567, 0.767, 1.067, 1.4, 1.867, 2.5, 3.9, 5.4, 6.9, 20.}, "Percentiles of scaled FT0C: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; + + ConfigurableAxis multFT0MThresh{"multFT0MThresh", {VARIABLE_WIDTH, 0.0, 0.167, 0.267, 0.4, 0.567, 0.8, 1.067, 1.4, 1.833, 2.433, 3.667, 5.1, 6.433, 20.}, "Percentiles of scaled FT0M: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; // default values for raw data + ConfigurableAxis multFT0MThreshPartLevel{"multFT0MThreshPartLevel", {VARIABLE_WIDTH, 0.0, 0.167, 0.267, 0.4, 0.567, 0.8, 1.067, 1.4, 1.833, 2.433, 3.667, 5.1, 6.433, 20.}, "Percentiles of scaled FT0M: 100%, 90%, 80%, 70%, 60%, 50%, 40%, 30%, 20%, 10%, 1%, 0.1%, 0.01%"}; + } hist; // Auxiliary variables std::unique_ptr randGen = std::make_unique(0); // Declare filter on collision Z vertex - Filter jCollisionFilter = nabs(aod::jcollision::posZ) < vertexZCut.node(); - Filter jCollisionFilterMC = nabs(aod::jmccollision::posZ) < vertexZCut.node(); - Filter collisionFilter = nabs(aod::collision::posZ) < vertexZCut.node(); + Filter jCollisionFilter = nabs(aod::jcollision::posZ) < ev.vertexZCut.node(); + Filter jCollisionFilterMC = nabs(aod::jmccollision::posZ) < ev.vertexZCut.node(); + Filter collisionFilter = nabs(aod::collision::posZ) < ev.vertexZCut.node(); // Declare filters on accepted tracks and MC particles (settings for jet reco are provided in the jet finder wagon) - Filter trackFilter = aod::jtrack::pt > trkPtMin.node() && aod::jtrack::pt < trkPtMax.node() && nabs(aod::jtrack::eta) < trkEtaCut.node(); - Filter partFilter = nabs(aod::jmcparticle::eta) < trkEtaCut.node(); + Filter trackFilter = aod::jtrack::pt > trk.ptMin.node() && aod::jtrack::pt < trk.ptMax.node() && nabs(aod::jtrack::eta) < trk.etaCut.node(); + Filter partFilter = nabs(aod::jmcparticle::eta) < trk.etaCut.node(); // Declare filter on jets - Filter jetRadiusFilter = aod::jet::r == nround(jetR.node() * 100.); - Filter jetEtaFilter = nabs(aod::jet::eta) < trkEtaCut.node() - jetR.node(); // 0.5 in our analysis + Filter jetRadiusFilter = aod::jet::r == nround(jet.radius.node() * 100.); + Filter jetEtaFilter = nabs(aod::jet::eta) < trk.etaCut.node() - jet.radius.node(); // 0.5 in our analysis HistogramRegistry spectra; @@ -148,17 +223,49 @@ struct RecoilJets { std::vector triggerMaskBits; Service pdg; - Preslice partJetsPerCollision = aod::jet::mcCollisionId; + Preslice partJetsPerMcCollision = aod::jet::mcCollisionId; + + template + struct AxisDesc { + AxisDesc(const char* label_, const AxisObject& axis_, const std::string& axisName_ = "") + : label(label_), axis(axis_), axisName(axisName_) {} + + const char* label; // "FT0C" / "FT0M" + const AxisObject& axis; // AxisSpec or ConfigurableAxis + std::string axisName; // Empty for AxisSpec + }; + + struct FT0Metrics { + float multFT0A = 0.f; + float multFT0C = 0.f; + float multFT0M = 0.f; + float scaledFT0A = 0.f; + float scaledFT0C = 0.f; + float scaledFT0M = 0.f; + }; void init(InitContext const&) { - // Initialize histogram axes - AxisSpec pT{histJetPt, 0.0, histJetPt * 1., "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec jetPTcorr{histJetPt + 20, -20., histJetPt * 1.0, "#it{p}_{T, jet}^{ch, corr} (GeV/#it{c})"}; - AxisSpec scaledFT0A{histMultBins, 0.0, 20., "FT0A / #LT FT0A #GT"}; - AxisSpec scaledFT0C{histMultBins, 0.0, 20., "FT0C / #LT FT0C #GT"}; - AxisSpec scaledFT0M{histMultBins, 0.0, 20., "FT0M^{*}"}; - AxisSpec zdcTiming{histZDCTimeBins, -30., 30., ""}; + // Initialize histogram axes: configurable + AxisSpec pT{hist.jetPtMax, 0.0, hist.jetPtMax * 1., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPTcorr{hist.jetPtMax + 20, -20., hist.jetPtMax * 1.0, "#it{p}_{T, jet}^{ch, corr} (GeV/#it{c})"}; + AxisSpec scaledFT0A{hist.multNBins, 0.0, 20., "FT0A / #LT FT0A #GT"}; + AxisSpec scaledFT0C{hist.multNBins, 0.0, 20., "FT0C / #LT FT0C #GT"}; + AxisSpec scaledFT0M{hist.multNBins, 0.0, 20., "FT0M^{*}"}; + AxisSpec zdcTiming{hist.zdcTimeNBins, -30., 30., ""}; + + // Fixed size histo + AxisSpec unscaledFT0A{2000, 0.0, 40000., "FT0A"}; + AxisSpec unscaledFT0C{2000, 0.0, 40000., "FT0C"}; + AxisSpec unscaledFT0M{3000, 0.0, 60000., "FT0M (FT0A + FT0C)"}; + + AxisSpec zdcNeutronA{1000, 0.0, 5000., "ZNA"}; + AxisSpec zdcNeutronC{1000, 0.0, 5000., "ZNC"}; + AxisSpec zdcNeutronM{4000, 0.0, 8000., "ZNM (ZNA + ZNC)"}; + + AxisSpec zdcProtonA{1000, 0.0, 5000., "ZPA"}; + AxisSpec zdcProtonC{1000, 0.0, 5000., "ZPC"}; + AxisSpec zdcProtonM{4000, 0.0, 8000., "ZPM (ZPA + ZPC)"}; AxisSpec phiAngle{40, 0.0, constants::math::TwoPI, "#it{#varphi} (rad)"}; AxisSpec deltaPhiAngle{52, 0.0, constants::math::PI, "#Delta#it{#varphi} (rad)"}; @@ -170,300 +277,539 @@ struct RecoilJets { std::string nameFT0Caxis = "FT0C / #LT FT0C #GT"; std::string nameFT0Maxis = "FT0M^{*}"; + std::array, 2> arrAxisSpecScaledEA = {{{"FT0C", scaledFT0C}, + {"FT0M", scaledFT0M}}}; + + std::array, 3> arrAxisSpecUnscaledEA = {{{"FT0A", unscaledFT0A}, + {"FT0C", unscaledFT0C}, + {"FT0M", unscaledFT0M}}}; + + std::array, 2> arrConfigurableAxis = {{{"FT0C", hist.multFT0CThresh, nameFT0Caxis}, + {"FT0M", hist.multFT0MThresh, nameFT0Maxis}}}; + + std::array, 2> arrConfigurableAxisPartLevel = {{{"FT0C", hist.multFT0CThreshPartLevel, nameFT0Caxis}, + {"FT0M", hist.multFT0MThreshPartLevel, nameFT0Maxis}}}; + + // Zero-degree calorimeter + std::array, 3> arrAxisSpecZDCNeutron = {{{"ZNA", zdcNeutronA}, + {"ZNC", zdcNeutronC}, + {"ZNM", zdcNeutronM}}}; + + std::array, 3> arrAxisSpecZDCProton = {{{"ZPA", zdcProtonA}, + {"ZPC", zdcProtonC}, + {"ZPM", zdcProtonM}}}; + // Convert configurable strings to std::string - std::string evSelToString = static_cast(evSel); - std::string trkSelToString = static_cast(trkSel); + std::string evSelToString = static_cast(ev.sel); + std::string trkSelToString = static_cast(trk.sel); eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(evSelToString); trackSelection = jetderiveddatautilities::initialiseTrackSelection(trkSelToString); - triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(ev.triggerMasks); + + const auto phiMin = tt.phiRestr->at(0); + const auto phiMax = tt.phiRestr->at(1); // List of raw and MC det. distributions if (doprocessData || doprocessMCDetLevel || doprocessMCDetLevelWeighted) { - spectra.add("hEventSelectionCount", "Count # of events in the analysis", kTH1F, {{6, 0.0, 6.}}); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(1, "Total # of events"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(3, "# of events skipMBGap"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(4, "# of events w. outlier"); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(5, "# of events w/o assoc MC."); - spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(6, "# of selected events"); - - spectra.add("hScaledFT0C_vertexZ", "Z vertex of collisions", kTH2F, {{multFT0CThresh, nameFT0Caxis}, {60, -12., 12., "#it{z}_{vertex}"}}); - spectra.add("hScaledFT0M_vertexZ", "Z vertex of collisions", kTH2F, {{multFT0MThresh, nameFT0Maxis}, {60, -12., 12., "#it{z}_{vertex}"}}); + spectra.add("hEventSelectionCountReco", "Count # of events in the analysis", kTH1F, {{5, 0.0, 5.}}); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(1, "Total # of events"); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(3, "# of events w. outlier"); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(4, "# of events w/o assoc MC."); + spectra.get(HIST("hEventSelectionCountReco"))->GetXaxis()->SetBinLabel(5, "# of selected events"); spectra.add("hTrackSelectionCount", "Count # of tracks in the analysis", kTH1F, {{2, 0.0, 2.}}); spectra.get(HIST("hTrackSelectionCount"))->GetXaxis()->SetBinLabel(1, "Total # of tracks"); spectra.get(HIST("hTrackSelectionCount"))->GetXaxis()->SetBinLabel(2, Form("# of tracks after sel. %s", trkSelToString.data())); - spectra.add("hScaledFT0CTrackPtEtaPhi", "Charact. of tracks", kTHnSparseF, {{multFT0CThresh, nameFT0Caxis}, pT, pseudorap, phiAngle}); - spectra.add("hScaledFT0MTrackPtEtaPhi", "Charact. of tracks", kTHnSparseF, {{multFT0MThresh, nameFT0Maxis}, pT, pseudorap, phiAngle}); spectra.add("hTTSig_pT", "pT spectrum of all found TT_{Sig} cand.", kTH1F, {{40, 10., 50.}}); // needed to distinguish merged data from diff. wagons - spectra.add("hScaledFT0C_Ntrig", "Total number of selected triggers per class vs scaled FT0C", kTH2F, {{multFT0CThresh, nameFT0Caxis}, {2, 0.0, 2.}}); - spectra.get(HIST("hScaledFT0C_Ntrig"))->GetYaxis()->SetBinLabel(1, "TT_{ref}"); - spectra.get(HIST("hScaledFT0C_Ntrig"))->GetYaxis()->SetBinLabel(2, "TT_{sig}"); + spectra.add("hJetPtEtaPhiRhoArea", "Charact. of inclusive jets", kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}, hist.sumw2); + spectra.add("hJetArea_JetPt_Rho_TTRef", "Events w. TT_{Ref}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}, hist.sumw2); + spectra.add("hJetArea_JetPt_Rho_TTSig", "Events w. TT_{Sig}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}, hist.sumw2); - spectra.add("hScaledFT0M_Ntrig", "Total number of selected triggers per class vs scaled FT0M", kTH2F, {{multFT0MThresh, nameFT0Maxis}, {2, 0.0, 2.}}); - spectra.get(HIST("hScaledFT0M_Ntrig"))->GetYaxis()->SetBinLabel(1, "TT_{ref}"); - spectra.get(HIST("hScaledFT0M_Ntrig"))->GetYaxis()->SetBinLabel(2, "TT_{sig}"); + for (const auto& eaAxis : arrConfigurableAxis) { + spectra.add(Form("hScaled%s_vertexZ", eaAxis.label), + "Z vertex of collisions", + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {60, -12., 12., "#it{z}_{vertex}"}}, hist.sumw2); - spectra.add("hScaledFT0C_TTRef_per_event", "Number of TT_{Ref} per event vs scaled FT0C", kTH2F, {{multFT0CThresh, nameFT0Caxis}, {15, 0.5, 15.5, "# of TT_{Ref}"}}); - spectra.add("hScaledFT0M_TTRef_per_event", "Number of TT_{Ref} per event vs scaled FT0M", kTH2F, {{multFT0MThresh, nameFT0Maxis}, {15, 0.5, 15.5, "# of TT_{Ref}"}}); + spectra.add(Form("hScaled%sTrackPtEtaPhi", eaAxis.label), + "Charact. of tracks", + kTHnSparseF, {{eaAxis.axis, eaAxis.axisName}, pT, pseudorap, phiAngle}, hist.sumw2); - spectra.add("hScaledFT0C_TTSig_per_event", "Number of TT_{Sig} per event vs scaled FT0C", kTH2F, {{multFT0CThresh, nameFT0Caxis}, {10, 0.5, 10.5, "# of TT_{Sig}"}}); - spectra.add("hScaledFT0M_TTSig_per_event", "Number of TT_{Sig} per event vs scaled FT0M", kTH2F, {{multFT0MThresh, nameFT0Maxis}, {10, 0.5, 10.5, "# of TT_{Sig}"}}); + auto tmpHistPointer = spectra.add(Form("hScaled%s_Ntrig", eaAxis.label), + Form("Total number of selected triggers per class vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {2, 0.0, 2.}}); + tmpHistPointer->GetYaxis()->SetBinLabel(1, "TT_{Ref}"); + tmpHistPointer->GetYaxis()->SetBinLabel(2, "TT_{Sig}"); - spectra.add("hJetPtEtaPhiRhoArea", "Charact. of inclusive jets", kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}); + spectra.add(Form("hScaled%s_TTRef_per_event", eaAxis.label), + Form("Number of TT_{Ref} per event vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {15, 0.5, 15.5, "# of TT_{Ref}"}}); - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTRef", "Events w. TT_{Ref}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThresh, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTRef", "Events w. TT_{Ref}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThresh, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + spectra.add(Form("hScaled%s_TTSig_per_event", eaAxis.label), + Form("Number of TT_{Sig} per event vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {10, 0.5, 10.5, "# of TT_{Sig}"}}); - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTSig", "Events w. TT_{Sig}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThresh, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTSig", "Events w. TT_{Sig}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThresh, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_DPhi_JetPt_TTRef", "Events w. TT_{Ref}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThresh, nameFT0Caxis}, deltaPhiAngle, pT}); - spectra.add("hScaledFT0M_DPhi_JetPt_TTRef", "Events w. TT_{Ref}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThresh, nameFT0Maxis}, deltaPhiAngle, pT}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_DPhi_JetPt_TTSig", "Events w. TT_{Sig}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThresh, nameFT0Caxis}, deltaPhiAngle, pT}); - spectra.add("hScaledFT0M_DPhi_JetPt_TTSig", "Events w. TT_{Sig}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThresh, nameFT0Maxis}, deltaPhiAngle, pT}); + spectra.add(Form("hScaled%s_DPhi_JetPt_TTRef", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, pT}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_Corr_TTRef", "Events w. TT_{Ref}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThresh, nameFT0Caxis}, jetPTcorr}); - spectra.add("hScaledFT0M_Recoil_JetPt_Corr_TTRef", "Events w. TT_{Ref}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThresh, nameFT0Maxis}, jetPTcorr}); + spectra.add(Form("hScaled%s_DPhi_JetPt_TTSig", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, pT}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_Corr_TTSig", "Events w. TT_{Sig}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThresh, nameFT0Caxis}, jetPTcorr}); - spectra.add("hScaledFT0M_Recoil_JetPt_Corr_TTSig", "Events w. TT_{Sig}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThresh, nameFT0Maxis}, jetPTcorr}); + spectra.add(Form("hScaled%s_Recoil_JetPt_Corr_TTRef", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_TTRef", "Events w. TT_{Ref}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThresh, nameFT0Caxis}, pT}); - spectra.add("hScaledFT0M_Recoil_JetPt_TTRef", "Events w. TT_{Ref}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThresh, nameFT0Maxis}, pT}); + spectra.add(Form("hScaled%s_Recoil_JetPt_Corr_TTSig", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_TTSig", "Events w. TT_{Sig}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThresh, nameFT0Caxis}, pT}); - spectra.add("hScaledFT0M_Recoil_JetPt_TTSig", "Events w. TT_{Sig}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThresh, nameFT0Maxis}, pT}); + spectra.add(Form("hScaled%s_Recoil_JetPt_TTRef", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, pT}, hist.sumw2); - spectra.add("hJetArea_JetPt_Rho_TTRef", "Events w. TT_{Ref}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}); - spectra.add("hJetArea_JetPt_Rho_TTSig", "Events w. TT_{Sig}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}); + spectra.add(Form("hScaled%s_Recoil_JetPt_TTSig", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, pT}, hist.sumw2); - spectra.add("hScaledFT0C_Rho", "Scaled FT0C & #rho", kTH2F, {{multFT0CThresh, nameFT0Caxis}, rho}); - spectra.add("hScaledFT0M_Rho", "Scaled FT0M & #rho", kTH2F, {{multFT0MThresh, nameFT0Maxis}, rho}); + spectra.add(Form("hScaled%s_Rho", eaAxis.label), + Form("Scaled %s & #rho", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add("hScaledFT0C_Rho_TTRef", "Events w. TT_{Ref}: scaled FT0C & #rho", kTH2F, {{multFT0CThresh, nameFT0Caxis}, rho}); - spectra.add("hScaledFT0M_Rho_TTRef", "Events w. TT_{Ref}: scaled FT0M & #rho", kTH2F, {{multFT0MThresh, nameFT0Maxis}, rho}); + spectra.add(Form("hScaled%s_Rho_TTRef", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #rho", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add("hScaledFT0C_Rho_TTSig", "Events w. TT_{Sig}: scaled FT0C & #rho", kTH2F, {{multFT0CThresh, nameFT0Caxis}, rho}); - spectra.add("hScaledFT0M_Rho_TTSig", "Events w. TT_{Sig}: scaled FT0M & #rho", kTH2F, {{multFT0MThresh, nameFT0Maxis}, rho}); + spectra.add(Form("hScaled%s_Rho_TTSig", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #rho", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add("hScaledFT0C_TTRef", "Events w. TT_{Ref}: scaled FT0C", kTH1F, {scaledFT0C}); - spectra.add("hScaledFT0M_TTRef", "Events w. TT_{Ref}: scaled FT0M", kTH1F, {scaledFT0M}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_RestrictedPhi", eaAxis.label), + Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_TTSig", "Events w. TT_{Sig}: scaled FT0C", kTH1F, {scaledFT0C}); - spectra.add("hScaledFT0M_TTSig", "Events w. TT_{Sig}: scaled FT0M", kTH1F, {scaledFT0M}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_RestrictedPhi", eaAxis.label), + Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); + } - // Rectricted phi range for TT selection - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RectrictedPhi", Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0CThresh, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RectrictedPhi", Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0MThresh, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaled%s_TTRef", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s", eaAxis.label), + kTH1F, {eaAxis.axis}); - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RectrictedPhi", Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0CThresh, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RectrictedPhi", Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0MThresh, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + spectra.add(Form("hScaled%s_TTSig", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s", eaAxis.label), + kTH1F, {eaAxis.axis}); + } } // List of MC particle level distributions if (doprocessMCPartLevel || doprocessMCPartLevelWeighted) { - spectra.add("hScaledFT0C_vertexZMC", "Z vertex of MCcollision", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, {60, -12., 12., "#it{z}_{vertex}"}}); - spectra.add("hScaledFT0M_vertexZMC", "Z vertex of MCcollision", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, {60, -12., 12., "#it{z}_{vertex}"}}); - spectra.add("ptHat", "Distribution of pT hat", kTH1F, {{5000, 0.0, 1000.}}); - spectra.add("hEventSelectionCountPartLevel", "Count # of events in the part. level analysis", kTH1F, {{4, 0.0, 4.}}); spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(1, "Total # of events"); - spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(2, "# of events skipMB gap"); + spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(3, "# of events w. outlier"); spectra.get(HIST("hEventSelectionCountPartLevel"))->GetXaxis()->SetBinLabel(4, "# of selected events"); - spectra.add("hScaledFT0CPartPtEtaPhi", "Charact. of particles", kTHnSparseF, {{multFT0CThreshPartLevel, nameFT0Caxis}, pT, pseudorap, phiAngle}); - spectra.add("hScaledFT0MPartPtEtaPhi", "Charact. of particles", kTHnSparseF, {{multFT0MThreshPartLevel, nameFT0Maxis}, pT, pseudorap, phiAngle}); + spectra.add("ptHat", "Distribution of pT hat", kTH1F, {{2000, 0.0, 1000.}}); - spectra.add("hScaledFT0C_Ntrig_Part", "Total number of selected triggers per class vs scaled FT0C", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, {2, 0.0, 2.}}); - spectra.get(HIST("hScaledFT0C_Ntrig_Part"))->GetXaxis()->SetBinLabel(1, "TT_{ref}"); - spectra.get(HIST("hScaledFT0C_Ntrig_Part"))->GetXaxis()->SetBinLabel(2, "TT_{sig}"); + spectra.add("hJetPtEtaPhiRhoArea_Part", "Charact. of inclusive part. level jets", kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}, hist.sumw2); + spectra.add("hJetArea_JetPt_Rho_TTRef_Part", "Events w. TT_{Ref}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}, hist.sumw2); + spectra.add("hJetArea_JetPt_Rho_TTSig_Part", "Events w. TT_{Sig}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}, hist.sumw2); - spectra.add("hScaledFT0M_Ntrig_Part", "Total number of selected triggers per class vs scaled FT0M", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, {2, 0.0, 2.}}); - spectra.get(HIST("hScaledFT0M_Ntrig_Part"))->GetXaxis()->SetBinLabel(1, "TT_{ref}"); - spectra.get(HIST("hScaledFT0M_Ntrig_Part"))->GetXaxis()->SetBinLabel(2, "TT_{sig}"); + for (const auto& eaAxis : arrConfigurableAxisPartLevel) { + spectra.add(Form("hScaled%s_vertexZMC", eaAxis.label), + "Z vertex of MC collision", + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {60, -12., 12., "#it{z}_{vertex}"}}, hist.sumw2); - spectra.add("hScaledFT0C_TTRef_per_event_Part", "Number of TT_{Ref} per event vs scaled FT0C", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, {15, 0.5, 15.5, "# of TT_{Ref}"}}); - spectra.add("hScaledFT0M_TTRef_per_event_Part", "Number of TT_{Ref} per event vs scaled FT0M", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, {15, 0.5, 15.5, "# of TT_{Ref}"}}); + auto tmpHistPointer = spectra.add(Form("hScaled%s_Ntrig_Part", eaAxis.label), + Form("Total number of selected triggers per class vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {2, 0.0, 2.}}); + tmpHistPointer->GetYaxis()->SetBinLabel(1, "TT_{Ref}"); + tmpHistPointer->GetYaxis()->SetBinLabel(2, "TT_{Sig}"); - spectra.add("hScaledFT0C_TTSig_per_event_Part", "Number of TT_{Sig} per event vs scaled FT0C", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, {10, 0.5, 10.5, "# of TT_{Sig}"}}); - spectra.add("hScaledFT0M_TTSig_per_event_Part", "Number of TT_{Sig} per event vs scaled FT0M", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, {10, 0.5, 10.5, "# of TT_{Sig}"}}); + spectra.add(Form("hScaled%sPartPtEtaPhi", eaAxis.label), + "Charact. of particles", + kTHnSparseF, {{eaAxis.axis, eaAxis.axisName}, pT, pseudorap, phiAngle}, hist.sumw2); - spectra.add("hJetPtEtaPhiRhoArea_Part", "Charact. of inclusive part. level jets", kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}); + spectra.add(Form("hScaled%s_TTRef_per_event_Part", eaAxis.label), + Form("Number of TT_{Ref} per event vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {15, 0.5, 15.5, "# of TT_{Ref}"}}); - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTRef_Part", "Events w. TT_{Ref}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThreshPartLevel, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTRef_Part", "Events w. TT_{Ref}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThreshPartLevel, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + spectra.add(Form("hScaled%s_TTSig_per_event_Part", eaAxis.label), + Form("Number of TT_{Sig} per event vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, {10, 0.5, 10.5, "# of TT_{Sig}"}}); - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTSig_Part", "Events w. TT_{Sig}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThreshPartLevel, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTSig_Part", "Events w. TT_{Sig}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThreshPartLevel, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_Part", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_DPhi_JetPt_TTRef_Part", "Events w. TT_{Ref}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThreshPartLevel, nameFT0Caxis}, deltaPhiAngle, pT}); - spectra.add("hScaledFT0M_DPhi_JetPt_TTRef_Part", "Events w. TT_{Ref}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThreshPartLevel, nameFT0Maxis}, deltaPhiAngle, pT}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_Part", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_DPhi_JetPt_TTSig_Part", "Events w. TT_{Sig}: scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0CThreshPartLevel, nameFT0Caxis}, deltaPhiAngle, pT}); - spectra.add("hScaledFT0M_DPhi_JetPt_TTSig_Part", "Events w. TT_{Sig}: scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH3F, {{multFT0MThreshPartLevel, nameFT0Maxis}, deltaPhiAngle, pT}); + spectra.add(Form("hScaled%s_DPhi_JetPt_TTRef_Part", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, pT}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_Corr_TTRef_Part", "Events w. TT_{Ref}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, jetPTcorr}); - spectra.add("hScaledFT0M_Recoil_JetPt_Corr_TTRef_Part", "Events w. TT_{Ref}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, jetPTcorr}); + spectra.add(Form("hScaled%s_DPhi_JetPt_TTSig_Part", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, pT}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_Corr_TTSig_Part", "Events w. TT_{Sig}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, jetPTcorr}); - spectra.add("hScaledFT0M_Recoil_JetPt_Corr_TTSig_Part", "Events w. TT_{Sig}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, jetPTcorr}); + spectra.add(Form("hScaled%s_Recoil_JetPt_Corr_TTRef_Part", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_TTRef_Part", "Events w. TT_{Ref}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, pT}); - spectra.add("hScaledFT0M_Recoil_JetPt_TTRef_Part", "Events w. TT_{Ref}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, pT}); + spectra.add(Form("hScaled%s_Recoil_JetPt_Corr_TTSig_Part", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_Recoil_JetPt_TTSig_Part", "Events w. TT_{Sig}: scaled FT0C & #it{p}_{T} of recoil jets", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, pT}); - spectra.add("hScaledFT0M_Recoil_JetPt_TTSig_Part", "Events w. TT_{Sig}: scaled FT0M & #it{p}_{T} of recoil jets", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, pT}); + spectra.add(Form("hScaled%s_Recoil_JetPt_TTRef_Part", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, pT}, hist.sumw2); - spectra.add("hJetArea_JetPt_Rho_TTRef_Part", "Events w. TT_{Ref}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}); - spectra.add("hJetArea_JetPt_Rho_TTSig_Part", "Events w. TT_{Sig}: A_{jet} & jet pT & #rho", kTH3F, {jetArea, pT, rho}); + spectra.add(Form("hScaled%s_Recoil_JetPt_TTSig_Part", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #it{p}_{T} of recoil jets", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, pT}, hist.sumw2); - spectra.add("hScaledFT0C_Rho_Part", "Scaled FT0C & #rho", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, rho}); - spectra.add("hScaledFT0M_Rho_Part", "Scaled FT0M & #rho", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, rho}); + spectra.add(Form("hScaled%s_Rho_Part", eaAxis.label), + Form("Scaled %s & #rho", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add("hScaledFT0C_Rho_TTRef_Part", "Events w. TT_{Ref}: scaled FT0C & #rho", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, rho}); - spectra.add("hScaledFT0M_Rho_TTRef_Part", "Events w. TT_{Ref}: scaled FT0M & #rho", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, rho}); + spectra.add(Form("hScaled%s_Rho_TTRef_Part", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s & #rho", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add("hScaledFT0C_Rho_TTSig_Part", "Events w. TT_{Sig}: scaled FT0C & #rho", kTH2F, {{multFT0CThreshPartLevel, nameFT0Caxis}, rho}); - spectra.add("hScaledFT0M_Rho_TTSig_Part", "Events w. TT_{Sig}: scaled FT0M & #rho", kTH2F, {{multFT0MThreshPartLevel, nameFT0Maxis}, rho}); + spectra.add(Form("hScaled%s_Rho_TTSig_Part", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s & #rho", eaAxis.label), + kTH2F, {{eaAxis.axis, eaAxis.axisName}, rho}, hist.sumw2); - spectra.add("hScaledFT0C_TTRef_Part", "Events w. TT_{Ref}: scaled FT0C", kTH1F, {scaledFT0C}); - spectra.add("hScaledFT0M_TTRef_Part", "Events w. TT_{Ref}: scaled FT0M", kTH1F, {scaledFT0M}); + // Rectricted phi range for TT selection + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTRef_RestrictedPhi_Part", eaAxis.label), + Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); - spectra.add("hScaledFT0C_TTSig_Part", "Events w. TT_{Sig}: scaled FT0C", kTH1F, {scaledFT0C}); - spectra.add("hScaledFT0M_TTSig_Part", "Events w. TT_{Sig}: scaled FT0M", kTH1F, {scaledFT0M}); + spectra.add(Form("hScaled%s_DPhi_JetPt_Corr_TTSig_RestrictedPhi_Part", eaAxis.label), + Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled %s & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiMin, phiMax, eaAxis.label), + kTH3F, {{eaAxis.axis, eaAxis.axisName}, deltaPhiAngle, jetPTcorr}, hist.sumw2); + } - // Rectricted phi range for TT selection - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part", Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0CThreshPartLevel, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part", Form("Events w. TT_{Ref} #in #varphi (%.2f, %.2f): scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0MThreshPartLevel, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaled%s_TTRef_Part", eaAxis.label), + Form("Events w. TT_{Ref}: scaled %s", eaAxis.label), + kTH1F, {eaAxis.axis}); - spectra.add("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part", Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled FT0C & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0CThreshPartLevel, nameFT0Caxis}, deltaPhiAngle, jetPTcorr}); - spectra.add("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part", Form("Events w. TT_{Sig} #in #varphi (%.2f, %.2f): scaled FT0M & #Delta#varphi & #it{p}_{T, jet}^{ch}", phiRestrTTSelection->at(0), phiRestrTTSelection->at(1)), kTH3F, {{multFT0MThreshPartLevel, nameFT0Maxis}, deltaPhiAngle, jetPTcorr}); + spectra.add(Form("hScaled%s_TTSig_Part", eaAxis.label), + Form("Events w. TT_{Sig}: scaled %s", eaAxis.label), + kTH1F, {eaAxis.axis}); + } } - // Jet matching: part. vs. det. - if (doprocessJetsMatched || doprocessJetsMatchedWeighted) { - spectra.add("hJetPt_DetLevel_vs_PartLevel", "Correlation jet pT at det. vs. part. levels", kTH2F, {{200, 0.0, 200.}, {200, 0.0, 200.}}); - // spectra.add("hJetPt_Corr_PartLevel_vs_DetLevel", "Correlation jet pT at - // part. vs. det. levels", kTH2F, {jetPTcorr, jetPTcorr}); - spectra.add("hJetPt_DetLevel_vs_PartLevel_RecoilJets", "Correlation recoil jet pT at part. vs. det. levels", kTH2F, {{200, 0.0, 200.}, {200, 0.0, 200.}}); - // spectra.add("hJetPt_Corr_PartLevel_vs_DetLevel_RecoilJets", "Correlation recoil jet pT at part. vs. det. levels", kTH2F, {jetPTcorr, jetPTcorr}); - - spectra.add("hMissedJets_pT", "Part. level jets w/o matched pair", kTH1F, {{200, 0.0, 200.}}); - // spectra.add("hMissedJets_Corr_pT", "Part. level jets w/o matched pair", kTH1F, {jetPTcorr}); - spectra.add("hMissedJets_pT_RecoilJets", "Part. level jets w/o matched pair", kTH1F, {{200, 0.0, 200.}}); - // spectra.add("hMissedJets_Corr_pT_RecoilJets", "Part. level jets w/o matched pair", kTH1F, {jetPTcorr}); - - spectra.add("hFakeJets_pT", "Det. level jets w/o matched pair", kTH1F, {{200, 0.0, 200.}}); - // spectra.add("hFakeJets_Corr_pT", "Det. level jets w/o matched pair", kTH1F, {jetPTcorr}); - spectra.add("hFakeJets_pT_RecoilJets", "Det. level jets w/o matched pair", kTH1F, {{200, 0.0, 200.}}); - // spectra.add("hFakeJets_Corr_pT_RecoilJets", "Det. level jets w/o matched pair", kTH1F, {jetPTcorr}); - - spectra.add("hJetPt_resolution", "Jet p_{T} relative resolution as a func. of jet #it{p}_{T, part}", kTH2F, {{100, -5., 5.}, pT}); - spectra.add("hJetPt_resolution_RecoilJets", "Jet p_{T} relative resolution as a func. of jet #it{p}_{T, part}", kTH2F, {{100, -5., 5.}, pT}); - - spectra.add("hJetPhi_resolution", "#varphi resolution as a func. of jet #it{p}_{T, part}", kTH2F, {{40, -1., 1.}, pT}); - spectra.add("hJetPhi_resolution_RecoilJets", "#varphi resolution as a func. of jet #it{p}_{T, part}", kTH2F, {{40, -1., 1.}, pT}); - - spectra.add("hNumberMatchedJetsPerOneBaseJet", "# of tagged jets per 1 base jet vs. jet pT", kTH2F, {{10, 0.5, 10.5}, {100, 0.0, 100.}}); + // Jet matching + if (doprocessJetsGeoMatching || doprocessJetsGeoMatchingWeighted || doprocessJetsGeoPtMatchingWeighted || doprocessJetsGeoPtMatching) { + AxisSpec detJetPt{200, 0.0, 200., "#it{p}_{T, det} (GeV/#it{c})"}; + AxisSpec detJetPtCorr{220, -20.0, 200., "#it{p}_{T, det}^{corr.} (GeV/#it{c})"}; + + AxisSpec partJetPt{200, 0.0, 200., "#it{p}_{T, part} (GeV/#it{c})"}; + AxisSpec partJetPtCorr{220, -20.0, 200., "#it{p}_{T, part}^{corr.} (GeV/#it{c})"}; + + AxisSpec relJetSmearPt{100, -5., 1., "(#it{p}_{T, part} - #it{p}_{T, det}) / #it{p}_{T, part}"}; + + //==================================================================================== + // Part. level jets + spectra.add("hPartLevelInclusiveJetsPt", + "All part. level inclusive jets", + kTH1F, {partJetPt}, hist.sumw2); + + spectra.add("hPartLevelInclusiveJetsPtCorr", + "All part. level inclusive jets", + kTH1F, {partJetPtCorr}, hist.sumw2); + + spectra.add("hPartLevelRecoilJetsPt", + "All part. level recoil jets", + kTH1F, {partJetPt}, hist.sumw2); + + spectra.add("hPartLevelRecoilJetsPtCorr", + "All part. level recoil jets", + kTH1F, {partJetPtCorr}, hist.sumw2); + + spectra.add("hMissedInclusiveJetsPt", + "Part. level inclusive jets w/o matched pair", + kTH1F, {partJetPt}, hist.sumw2); + + spectra.add("hMissedInclusiveJetsPtCorr", + "Part. level inclusive jets w/o matched pair", + kTH1F, {partJetPtCorr}, hist.sumw2); + + spectra.add("hMissedRecoilJetsPt", + "Part. level recoil jets w/o matched pair", + kTH1F, {partJetPt}, hist.sumw2); + + spectra.add("hMissedRecoilJetsPtCorr", + "Part. level recoil jets w/o matched pair", + kTH1F, {partJetPtCorr}, hist.sumw2); + + //==================================================================================== + // Det. level jets + spectra.add("hDetLevelInclusiveJetsPt", + "All reconstructed inclusive jets", + kTH1F, {detJetPt}, hist.sumw2); + + spectra.add("hDetLevelInclusiveJetsPtCorr", + "All reconstructed inclusive jets", + kTH1F, {detJetPtCorr}, hist.sumw2); + + spectra.add("hDetLevelRecoilJetsPt", + "All reconstructed recoil jets", + kTH1F, {detJetPt}, hist.sumw2); + + spectra.add("hDetLevelRecoilJetsPtCorr", + "All reconstructed recoil jets", + kTH1F, {detJetPtCorr}, hist.sumw2); + + spectra.add("hFakeInclusiveJetsPt", + "Det. level inclusive jets w/o matched pair", + kTH1F, {detJetPt}, hist.sumw2); + + spectra.add("hFakeInclusiveJetsPtCorr", + "Det. level inclusive jets w/o matched pair", + kTH1F, {detJetPtCorr}, hist.sumw2); + + spectra.add("hFakeRecoilJetsPt", + "Det. level recoil jets w/o matched pair", + kTH1F, {detJetPt}, hist.sumw2); + + spectra.add("hFakeRecoilJetsPtCorr", + "Det. level recoil jets w/o matched pair", + kTH1F, {detJetPtCorr}, hist.sumw2); + + //==================================================================================== + // Response matices with inclusive jets + spectra.add("hResponseMatrixInclusiveJetsPt", + "Correlation inclusive #it{p}_{T, det.} vs. #it{p}_{T, part}", + kTH2F, {detJetPt, partJetPt}, hist.sumw2); + + spectra.add("hResponseMatrixInclusiveJetsPtCorr", + "Correlation inclusive #it{p}_{T, det.} vs. #it{p}_{T, part}", + kTH2F, {detJetPtCorr, partJetPtCorr}, hist.sumw2); + + //==================================================================================== + // Response matices with recoil jets + spectra.add("hResponseMatrixRecoilJetsPt", + "Correlation recoil #it{p}_{T, det.} vs. #it{p}_{T, part}", + kTH2F, {detJetPt, partJetPt}, hist.sumw2); + + spectra.add("hResponseMatrixRecoilJetsPtCorr", + "Correlation recoil #it{p}_{T, det.} vs. #it{p}_{T, part}", + kTH2F, {detJetPtCorr, partJetPtCorr}, hist.sumw2); + + //==================================================================================== + // Jet energy scale and resolution: pT and phi + spectra.add("hInclusiveJESPt", + "ES of inclusive jets vs. #it{p}_{T, part}", + kTH2F, {relJetSmearPt, partJetPt}, hist.sumw2); + + spectra.add("hInclusiveJESPtCorr", + "ES of inclusive jets vs. #it{p}_{T, part}", + kTH2F, {relJetSmearPt, partJetPtCorr}, hist.sumw2); + + spectra.add("hRecoilJESPt", + "ES of recoil jets vs. #it{p}_{T, part}", + kTH2F, {relJetSmearPt, partJetPt}, hist.sumw2); + + spectra.add("hRecoilJESPtCorr", + "ES of recoil jets vs. #it{p}_{T, part}", + kTH2F, {relJetSmearPt, partJetPtCorr}, hist.sumw2); + + AxisSpec jetSmearPhi{100, -0.5, 0.5, "#it{#varphi}_{part} - #it{#varphi}_{det}"}; + spectra.add("hInclusiveJESPhi", + "#varphi resolution as a func. of jet #it{p}_{T, part}", + kTH2F, {jetSmearPhi, partJetPt}, hist.sumw2); + + spectra.add("hRecoilJESPhi", + "#varphi resolution as a func. of jet #it{p}_{T, part}", + kTH2F, {jetSmearPhi, partJetPt}, hist.sumw2); + + //==================================================================================== + // Utility histograms + spectra.add("hNumberMatchedInclusiveDetJetsPerOnePartJet", + "# of det. level inclusive jets per 1 part. level jet vs. #it{p}_{T, det.} vs. #it{p}_{T, part.}", + kTH3F, {{6, 0.5, 6.5, "# of matched det. level jets"}, {200, 0.0, 200., "#it{p}_{T, det.}"}, {200, 0.0, 200., "#it{p}_{T, part.}"}}, hist.sumw2); + + spectra.add("hNumberMatchedRecoilDetJetsPerOnePartJet", + "# of det. level recoil jets per 1 part. level jet vs. #it{p}_{T, det.} vs. #it{p}_{T, part.}", + kTH3F, {{6, 0.5, 6.5, "# of matched det. level jets"}, {200, 0.0, 200., "#it{p}_{T, det.}"}, {200, 0.0, 200., "#it{p}_{T, part.}"}}, hist.sumw2); } // Multiplicity for raw data and detector level MC - if (doprocessMultiplicityOO || doprocessMultiplicityMCDetLevelWeightedOO) { - spectra.add("hMultFT0A", "Mult. signal from FTOA", kTH1F, {{2000, 0.0, 40000., "FT0A"}}); - spectra.add("hMultFT0C", "Mult. signal from FTOC", kTH1F, {{2000, 0.0, 40000., "FT0C"}}); - spectra.add("hMultFT0M", "Total mult. signal from FT0A & FTOC", kTH1F, {{3000, 0.0, 60000., "FT0M"}}); - - spectra.add("hScaleMultFT0A", "Scaled mult. signal from FTOA", kTH1F, {scaledFT0A}); - spectra.add("hScaleMultFT0C", "Scaled mult. signal from FTOC", kTH1F, {scaledFT0C}); - spectra.add("hScaleMultFT0M", "Scaled total mult. signal from FT0A & FTOC", kTH1F, {scaledFT0M}); - - spectra.add("hMultZNA", "Mult. signal from ZDC A-side", kTH1F, {{1000, 0.0, 5000., "ZNA"}}); - spectra.add("hMultZNC", "Mult. signal from ZDC C-side", kTH1F, {{1000, 0.0, 5000., "ZNC"}}); - spectra.add("hMultZNM", "Total mult. signal from ZDCs for neutrons", kTH1F, {{4000, 0.0, 8000., "ZNM"}}); - - spectra.add("hMultZPA", "Mult. signal from ZDC A-side", kTH1F, {{1000, 0.0, 5000., "ZPA"}}); - spectra.add("hMultZPC", "Mult. signal from ZDC C-side", kTH1F, {{1000, 0.0, 5000., "ZPC"}}); - spectra.add("hMultZPM", "Total mult. signal from ZDCs for protons", kTH1F, {{4000, 0.0, 8000., "ZPM"}}); + if (doprocessEventActivity || doprocessEventActivityMCDetLevelWeighted) { + + //==================================================================================== + // FIT data + for (const auto& eaAxis : arrAxisSpecUnscaledEA) { + spectra.add(Form("hMult%s", eaAxis.label), + Form("Mult. signal %s", eaAxis.label), + kTH1F, {eaAxis.axis}, hist.sumw2); + } - // Correlations - spectra.add("hZPA_vs_ZNA", "Correlation of signals ZPA vs ZNA", kTH2F, {{1000, 0.0, 5000., "ZPA"}, {1000, 0.0, 5000., "ZNA"}}); - spectra.add("hZPC_vs_ZNC", "Correlation of signals ZPC vs ZNC", kTH2F, {{1000, 0.0, 5000., "ZPC"}, {1000, 0.0, 5000., "ZNC"}}); + spectra.add("hScaleMultFT0A", "Scaled FTOA signal", kTH1F, {scaledFT0A}, hist.sumw2); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaleMult%s", eaAxis.label), + Form("Scaled %s signal", eaAxis.label), + kTH1F, {eaAxis.axis}, hist.sumw2); + } - spectra.add("hMultFT0A_vs_ZNA", "Correlation of signals FTOA vs ZNA", kTH2F, {{2000, 0.0, 40000., "FT0A"}, {1000, 0.0, 5000., "ZNA"}}); - spectra.add("hMultFT0C_vs_ZNC", "Correlation of signals FTOC vs ZNC", kTH2F, {{2000, 0.0, 40000., "FT0C"}, {1000, 0.0, 5000., "ZNC"}}); - spectra.add("hMultFT0M_vs_ZNM", "Correlation of signals FTOM vs ZNM", kTH2F, {{3000, 0.0, 60000., "FT0M"}, {4000, 0.0, 8000., "ZNM"}}); + //==================================================================================== + // Zero-degree calorimeter data + for (size_t i = 0; i < arrAxisSpecZDCNeutron.size(); ++i) { + spectra.add(Form("hMult%s", arrAxisSpecZDCNeutron[i].label), + Form("Mult. signal from %s", arrAxisSpecZDCNeutron[i].label), + kTH1F, {arrAxisSpecZDCNeutron[i].axis}, hist.sumw2); + + spectra.add(Form("hMult%s", arrAxisSpecZDCProton[i].label), + Form("Mult. signal from %s", arrAxisSpecZDCProton[i].label), + kTH1F, {arrAxisSpecZDCProton[i].axis}, hist.sumw2); + + // Correlation + spectra.add(Form("h%s_vs_%s", arrAxisSpecZDCProton[i].label, arrAxisSpecZDCNeutron[i].label), + Form("Correlation of signals %s vs %s", arrAxisSpecZDCProton[i].label, arrAxisSpecZDCNeutron[i].label), + kTH2F, {{arrAxisSpecZDCProton[i].axis}, {arrAxisSpecZDCNeutron[i].axis}}, hist.sumw2); + } - spectra.add("hScaleMultFT0A_vs_ZNA", "Correlation of signals FT0A/meanFT0A vs ZNA", kTH2F, {{scaledFT0A}, {1000, 0.0, 5000., "ZNA"}}); - spectra.add("hScaleMultFT0C_vs_ZNC", "Correlation of signals FT0C/meanFT0C vs ZNC", kTH2F, {{scaledFT0C}, {1000, 0.0, 5000., "ZNC"}}); - spectra.add("hScaleMultFT0M_vs_ZNM", "Correlation of signals FT0M^{*} vs ZNM", kTH2F, {{scaledFT0M}, {4000, 0.0, 8000., "ZNM"}}); + //==================================================================================== + // FT0 vs. ZDC correlation + for (size_t i = 0; i < arrAxisSpecUnscaledEA.size(); ++i) { + spectra.add(Form("hMult%s_vs_%s", arrAxisSpecUnscaledEA[i].label, arrAxisSpecZDCNeutron[i].label), + Form("Correlation of signals %s vs %s", arrAxisSpecUnscaledEA[i].label, arrAxisSpecZDCNeutron[i].label), + kTH2F, {{arrAxisSpecUnscaledEA[i].axis}, {arrAxisSpecZDCNeutron[i].axis}}, hist.sumw2); + + if (i != 0) { + spectra.add(Form("hScaleMult%s_vs_%s", arrAxisSpecScaledEA[i - 1].label, arrAxisSpecZDCNeutron[i].label), + Form("Correlation of signals scaled %s vs %s", arrAxisSpecScaledEA[i - 1].label, arrAxisSpecZDCNeutron[i].label), + kTH2F, {{arrAxisSpecScaledEA[i - 1].axis}, {arrAxisSpecZDCNeutron[i].axis}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_vs_%s", arrAxisSpecScaledEA[i - 1].label, arrAxisSpecZDCProton[i].label), + Form("Correlation of signals scaled %s vs %s", arrAxisSpecScaledEA[i - 1].label, arrAxisSpecZDCProton[i].label), + kTH2F, {{arrAxisSpecScaledEA[i - 1].axis}, {arrAxisSpecZDCProton[i].axis}}, hist.sumw2); + } else { + spectra.add("hScaleMultFT0A_vs_ZNA", "Correlation of signals scaled FT0A vs ZNA", kTH2F, {{scaledFT0A}, {arrAxisSpecZDCNeutron[i].axis}}, hist.sumw2); + spectra.add("hScaleMultFT0A_vs_ZPA", "Correlation of signals scaled FT0A vs ZPA", kTH2F, {{scaledFT0A}, {arrAxisSpecZDCProton[i].axis}}, hist.sumw2); + } + } - spectra.add("hScaleMultFT0A_vs_ZPA", "Correlation of signals FT0A/meanFT0A vs ZPA", kTH2F, {{scaledFT0A}, {1000, 0.0, 5000., "ZPA"}}); - spectra.add("hScaleMultFT0C_vs_ZPC", "Correlation of signals FT0C/meanFT0C vs ZPC", kTH2F, {{scaledFT0C}, {1000, 0.0, 5000., "ZPC"}}); - spectra.add("hScaleMultFT0M_vs_ZPM", "Correlation of signals FT0M^{*} vs ZPM", kTH2F, {{scaledFT0M}, {4000, 0.0, 8000., "ZPM"}}); + spectra.add("hScaleMultFT0M_vs_ZNA_vs_ZNC", + "Correlation of signals FT0M^{*} vs ZNA vs ZNC", + kTH3F, {{scaledFT0M}, {600, 0.0, 3000., "ZNA"}, {600, 0.0, 3000., "ZNC"}}, hist.sumw2); - spectra.add("hScaleMultFT0M_vs_ZNA_vs_ZNC", "Correlation of signals FT0M^{*} vs ZNA vs ZNC", kTH3F, {{scaledFT0M}, {600, 0.0, 3000., "ZNA"}, {600, 0.0, 3000., "ZNC"}}); - spectra.add("hScaleMultFT0M_vs_ZPA_vs_ZPC", "Correlation of signals FT0M^{*} vs ZPA vs ZPC", kTH3F, {{scaledFT0M}, {600, 0.0, 3000., "ZPA"}, {600, 0.0, 3000., "ZPC"}}); + spectra.add("hScaleMultFT0M_vs_ZPA_vs_ZPC", + "Correlation of signals FT0M^{*} vs ZPA vs ZPC", + kTH3F, {{scaledFT0M}, {600, 0.0, 3000., "ZPA"}, {600, 0.0, 3000., "ZPC"}}, hist.sumw2); } // Multiplicity for particle level MC - if (doprocessMultiplicityPartLevelMC || doprocessMultiplicityPartLevelMCWeighted) { - spectra.add("hMultFT0APartLevel", "# of primary particles within FTOA acceptance", kTH1F, {{2000, 0.0, 500., "FT0A"}}); - spectra.add("hMultFT0CPartLevel", "# of primary particles within FTOC acceptance", kTH1F, {{2000, 0.0, 500., "FT0C"}}); - spectra.add("hMultFT0MPartLevel", "Total # of primary particles from FT0A & FTOC", kTH1F, {{4000, 0.0, 1000., "FT0M"}}); - - spectra.add("hScaleMultFT0APartLevel", "Scaled # of primary particles within FTOA acceptance", kTH1F, {scaledFT0A}); - spectra.add("hScaleMultFT0CPartLevel", "Scaled # of primary particles within FTOC acceptance", kTH1F, {scaledFT0C}); - spectra.add("hScaleMultFT0MPartLevel", "Scaled total # of primary particles from FT0A & FTOC", kTH1F, {scaledFT0M}); + if (doprocessEventActivityMCPartLevel || doprocessEventActivityMCPartLevelWeighted) { + spectra.add("hMultFT0APartLevel", "# of primary particles within FTOA acceptance", kTH1F, {{2000, 0.0, 1000., "FT0A"}}, hist.sumw2); + spectra.add("hMultFT0CPartLevel", "# of primary particles within FTOC acceptance", kTH1F, {{2000, 0.0, 1000., "FT0C"}}, hist.sumw2); + spectra.add("hMultFT0MPartLevel", "Total # of primary particles from FT0A & FTOC", kTH1F, {{4000, 0.0, 2000., "FT0M"}}, hist.sumw2); + + spectra.add("hScaleMultFT0APartLevel", "Scaled # of primary particles within FTOA acceptance", kTH1F, {{scaledFT0A}}, hist.sumw2); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaleMult%sPartLevel", eaAxis.label), + Form("Scaled # of primary particles within %s acceptance", eaAxis.label), + kTH1F, {{eaAxis.axis}}, hist.sumw2); + } } - if (doprocessMultiplicityQA) { - - // ZNC timing QA - spectra.add("hTimeCorrZnaZnc", "Correlat. #it{t}_{ZNA} - #it{t}_{ZNC} vs. #it{t}_{ZNA} + #it{t}_{ZNC}", kTH2F, {{1000, -10., 10., "#it{t}_{ZNA} - #it{t}_{ZNC} (ns)"}, {1000, -10., 10., "#it{t}_{ZNA} + #it{t}_{ZNC} (ns)"}}); - spectra.add("hTimeZnaVsZncVsFT0C", "Correlat. #it{t}_{ZNA} (ns) vs. #it{t}_{ZNC} (ns) vs. FT0C/meanFT0C", kTH3F, {{zdcTiming}, {zdcTiming}, {scaledFT0C}}); - spectra.add("hTimeZnaVsZncVsFT0M", "Correlat. #it{t}_{ZNA} (ns) vs. #it{t}_{ZNC} (ns) vs. FT0M^{*}", kTH3F, {{zdcTiming}, {zdcTiming}, {scaledFT0M}}); - - // Number of tracks from PV within acceptance |eta| < 0.8 - spectra.add("hScaledFT0C_TracksPV", "Correlat. FT0C/meanFT0C vs. PV tracks", kTH2F, {{scaledFT0C}, {5000, 0., 5000.}}); - spectra.add("hScaledFT0M_TracksPV", "Correlat. FT0M^{*} vs. PV tracks", kTH2F, {{scaledFT0M}, {5000, 0., 5000.}}); - - // ITS-only tracks - spectra.add("hScaledFT0C_ITStracks", "Correlat. FT0C/meanFT0C vs. number of ITS tracks", kTH2F, {{scaledFT0C}, {5000, 0., 5000.}}); - spectra.add("hScaledFT0M_ITStracks", "Correlat. FT0M^{*} vs. number of ITS tracks", kTH2F, {{scaledFT0M}, {5000, 0., 5000.}}); + if (doprocessEventActivitySelectionQA) { + spectra.add("hEventSelectionCountQA", "Count # of events in the analysis", kTH1F, {{5, 0.0, 5.}}); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(1, "sel8"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(2, "IsGoodZvtxFT0vsPV"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(3, "NoSameBunchPileup"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(4, "NoCollInTimeRangeStandard"); + spectra.get(HIST("hEventSelectionCountQA"))->GetXaxis()->SetBinLabel(5, "All flags"); + + //==================================================================================== + // ZNA vs. ZNC correlation + spectra.add("hTimeCorrZnaZnc", + "Correlat. #it{t}_{ZNA} - #it{t}_{ZNC} vs. #it{t}_{ZNA} + #it{t}_{ZNC}", + kTH2F, {{500, -10., 10., "#it{t}_{ZNA} - #it{t}_{ZNC} (ns)"}, {500, -10., 10., "#it{t}_{ZNA} + #it{t}_{ZNC} (ns)"}}, hist.sumw2); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + + // ZNA vs. ZNC vs. scaled FIT signal + spectra.add(Form("hTimeZnaVsZncVs%s", eaAxis.label), + Form("Correlat. #it{t}_{ZNA} (ns) vs. #it{t}_{ZNC} (ns) vs. scaled %s", eaAxis.label), + kTH3F, {{zdcTiming}, {zdcTiming}, {eaAxis.axis}}, hist.sumw2); + + // Number of tracks from PV within acceptance |eta| < 0.8 + spectra.add(Form("hScaled%s_TracksPV", eaAxis.label), + Form("Correlat. scaled %s vs. PV tracks", eaAxis.label), + kTH2F, {{eaAxis.axis}, {700, 0., 700.}}, hist.sumw2); + + // ITS-only tracks + spectra.add(Form("hScaled%s_ITStracks", eaAxis.label), + Form("Correlat. scaled %s vs. number of ITS tracks", eaAxis.label), + kTH2F, {{eaAxis.axis}, {700, 0., 700.}}, hist.sumw2); + } - // Multiplicity equalized for the vertex position with FT0 detector - spectra.add("hMultZeqFT0A", "Equalized mult. FT0A", kTH1F, {{{2000, 0.0, 40000., "FT0A"}}}); - spectra.add("hMultZeqFT0C", "Equalized mult. FT0C", kTH1F, {{{2000, 0.0, 40000., "FT0C"}}}); - spectra.add("hMultZeqFT0M", "Equalized mult. FT0M", kTH1F, {{{3000, 0.0, 60000., "FT0M"}}}); + //==================================================================================== + // EA equalized for the vertex position with FT0 detector + for (const auto& eaAxis : arrAxisSpecUnscaledEA) { + spectra.add(Form("hMultZeq%s", eaAxis.label), + Form("Equalized mult. %s", eaAxis.label), + kTH1F, {{eaAxis.axis}}, hist.sumw2); + } - spectra.add("hScaledZeqFT0A", "Equalized FT0A/meanFT0A", kTH1F, {{scaledFT0A}}); - spectra.add("hScaledZeqFT0C", "Equalized FT0C/meanFT0C", kTH1F, {{scaledFT0C}}); - spectra.add("hScaledZeqFT0M", "Equalized FT0M^{*}", kTH1F, {{scaledFT0M}}); + // Scaled EA + spectra.add("hScaledZeqFT0A", "Equalized scaled FT0A", kTH1F, {{scaledFT0A}}, hist.sumw2); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaledZeq%s", eaAxis.label), + Form("Equalized scaled %s", eaAxis.label), + kTH1F, {{eaAxis.axis}}, hist.sumw2); + } + //==================================================================================== // Run-by-run study of EA std::vector runNumbersOO = { "564356", "564359", "564373", "564374", "564387", "564400", "564414", "564430", "564445"}; const int nRunsOO = runNumbersOO.size(); std::vector evSelFlags = { - "sel8", "sel8 + IsGoodZvtxFT0vsPV", "sel8 + NoSameBunchPileup", "sel8 + IsGoodZvtxFT0vsPV + NoSameBunchPileup"}; + "sel8", "sel8 + IsGoodZvtxFT0vsPV", "sel8 + NoSameBunchPileup", "NoCollInTimeRangeStandard", "sel8 && IsGoodZvtxFT0vsPV && NoSameBunchPileup && NoCollInTimeRangeStandard"}; const int nEvSelFlags = evSelFlags.size(); - // Scaled FT0 signal - spectra.add("hScaledFT0APerRunPerSetOfFlags", "FT0A/meanFT0A signal per run per set of ev. sel. flags", kTH3F, {{scaledFT0A}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}); - spectra.add("hScaledFT0CPerRunPerSetOfFlags", "FT0C/meanFT0C signal per run per set of ev. sel. flags", kTH3F, {{scaledFT0C}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}); - spectra.add("hScaledFT0MPerRunPerSetOfFlags", "FT0M^{*} signal per run per set of ev. sel. flags", kTH3F, {{scaledFT0M}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}); + // Scaled FT0 signal; Run-by-run QA + spectra.add("hScaledFT0APerRunPerSetOfFlags", + "Scaled FT0A signal per run per set of ev. sel. flags", + kTH3F, {{scaledFT0A}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}, hist.sumw2); + setBinLabelsYZAxes(spectra.get(HIST("hScaledFT0APerRunPerSetOfFlags")), runNumbersOO, evSelFlags); + + for (const auto& eaAxis : arrAxisSpecScaledEA) { + auto tmpHistPointer = spectra.add(Form("hScaled%sPerRunPerSetOfFlags", eaAxis.label), + Form("Scaled %s signal per run per set of ev. sel. flags", eaAxis.label), + kTH3F, {{eaAxis.axis}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}, hist.sumw2); + setBinLabelsYZAxes(tmpHistPointer, runNumbersOO, evSelFlags); + } // Unscaled FT0 signal; check whether mean value is the same for all runs - spectra.add("hFT0APerRunPerSetOfFlags", "FT0A signal per run per set of ev. sel. flags", kTH3F, {{2000, 0.0, 40000., "FT0A"}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}); - spectra.add("hFT0CPerRunPerSetOfFlags", "FT0C signal per run per set of ev. sel. flags", kTH3F, {{2000, 0.0, 40000., "FT0C"}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}); - spectra.add("hFT0MPerRunPerSetOfFlags", "FT0M signal per run per set of ev. sel. flags", kTH3F, {{3000, 0.0, 60000., "FT0M"}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}); + for (const auto& eaAxis : arrAxisSpecUnscaledEA) { + auto tmpHistPointer = spectra.add(Form("h%sPerRunPerSetOfFlags", eaAxis.label), + Form("%s signal per run per set of ev. sel. flags", eaAxis.label), + kTH3F, {{eaAxis.axis}, {nRunsOO, 0., nRunsOO * 1.}, {nEvSelFlags, 0., nEvSelFlags * 1.}}, hist.sumw2); + setBinLabelsYZAxes(tmpHistPointer, runNumbersOO, evSelFlags); + } // Check whether each BC has FT0 signal spectra.add("hIsFT0SignalComeFromCollPerRun", "", kTH2F, {{4, 0., 4.}, {nRunsOO, 0., nRunsOO * 1.}}); @@ -471,83 +817,162 @@ struct RecoilJets { spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetXaxis()->SetBinLabel(2, "BC has not FT0"); spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetXaxis()->SetBinLabel(3, "Coll. w. BC"); spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetXaxis()->SetBinLabel(4, "Coll. w/o BC"); + setBinLabelsYZAxes(spectra.get(HIST("hIsFT0SignalComeFromCollPerRun")), runNumbersOO, {}); // FT0 signal for the case when there is no associated BC - spectra.add("hFT0AsignalWithoutBC", "", kTH2F, {{2000, 0.0, 40000., "FT0A"}, {nRunsOO, 0., nRunsOO * 1.}}); - spectra.add("hFT0CsignalWithoutBC", "", kTH2F, {{2000, 0.0, 40000., "FT0C"}, {nRunsOO, 0., nRunsOO * 1.}}); - spectra.add("hFT0MsignalWithoutBC", "", kTH2F, {{2000, 0.0, 40000., "FT0M"}, {nRunsOO, 0., nRunsOO * 1.}}); - - // Rename Y axis with Run numbers - for (int iRun = 0; iRun < nRunsOO; ++iRun) { - spectra.get(HIST("hScaledFT0APerRunPerSetOfFlags"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); - spectra.get(HIST("hScaledFT0CPerRunPerSetOfFlags"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); - spectra.get(HIST("hScaledFT0MPerRunPerSetOfFlags"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); + spectra.add("hScaledFT0AsignalWithoutBC", "", kTH2F, {{scaledFT0A}, {nRunsOO, 0., nRunsOO * 1.}}); + setBinLabelsYZAxes(spectra.get(HIST("hScaledFT0AsignalWithoutBC")), runNumbersOO, {}); + + for (const auto& eaAxis : arrAxisSpecScaledEA) { + auto tmpHistPointer = spectra.add(Form("hScaled%ssignalWithoutBC", eaAxis.label), + "", + kTH2F, {{eaAxis.axis}, {nRunsOO, 0., nRunsOO * 1.}}); + setBinLabelsYZAxes(tmpHistPointer, runNumbersOO, {}); + } + } - spectra.get(HIST("hFT0APerRunPerSetOfFlags"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); - spectra.get(HIST("hFT0CPerRunPerSetOfFlags"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); - spectra.get(HIST("hFT0MPerRunPerSetOfFlags"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); + // Di-hadron correlation + if (doprocessLeadingAndAssociatedTracksTask) { + const auto pTLeadTrackMin = twoPartCorrel.leadPtRange->at(0); + const auto pTLeadTrackMax = twoPartCorrel.leadPtRange->at(1); - spectra.get(HIST("hIsFT0SignalComeFromCollPerRun"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaled%s_NleadTracks", eaAxis.label), + Form("Total number of selected leading tracks vs scaled %s", eaAxis.label), + kTH2F, {{eaAxis.axis}, {1, 0.0, 1.}}, hist.sumw2); - spectra.get(HIST("hFT0AsignalWithoutBC"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); - spectra.get(HIST("hFT0CsignalWithoutBC"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); - spectra.get(HIST("hFT0MsignalWithoutBC"))->GetYaxis()->SetBinLabel(iRun + 1, runNumbersOO[iRun]); + spectra.add(Form("hScaled%s_Correlation_LeadTrack_AssociatTracks", eaAxis.label), + Form("Leading track #it{p}_{T} #in (%.2f, %.2f); Associated track #it{p}_{T} #in (%.2f, #it{p}_{T, lead. trk})", pTLeadTrackMin, pTLeadTrackMax, twoPartCorrel.associatTrackPtMin.value), + kTH2F, {{eaAxis.axis}, {160, -1.28, 5.0, "#it{#varphi} (rad)"}}, hist.sumw2); } + } + + // Bkgd fluctuations in raw and MC det. level data + const auto ptTTsigMin = tt.sigPtRange->at(0); + const auto ptTTsigMax = tt.sigPtRange->at(1); - // Rename Z axis with event selection flags - for (int iFlag = 0; iFlag < nEvSelFlags; ++iFlag) { - spectra.get(HIST("hScaledFT0APerRunPerSetOfFlags"))->GetZaxis()->SetBinLabel(iFlag + 1, evSelFlags[iFlag]); - spectra.get(HIST("hScaledFT0CPerRunPerSetOfFlags"))->GetZaxis()->SetBinLabel(iFlag + 1, evSelFlags[iFlag]); - spectra.get(HIST("hScaledFT0MPerRunPerSetOfFlags"))->GetZaxis()->SetBinLabel(iFlag + 1, evSelFlags[iFlag]); + if (doprocessBkgdFluctuations || doprocessBkgdFluctuationsMCDetLevel || doprocessBkgdFluctuationsMCDetLevelWeighted) { + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaled%s_deltaPtRandomCone", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f vs. EA", bkgd.randomConeR.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); - spectra.get(HIST("hFT0APerRunPerSetOfFlags"))->GetZaxis()->SetBinLabel(iFlag + 1, evSelFlags[iFlag]); - spectra.get(HIST("hFT0CPerRunPerSetOfFlags"))->GetZaxis()->SetBinLabel(iFlag + 1, evSelFlags[iFlag]); - spectra.get(HIST("hFT0MPerRunPerSetOfFlags"))->GetZaxis()->SetBinLabel(iFlag + 1, evSelFlags[iFlag]); + spectra.add(Form("hScaled%s_deltaPtRandomConeAvoidLeadJet", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", bkgd.randomConeR.value, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); + + spectra.add(Form("hScaled%s_deltaPtPerpConeAvoidLeadJet", eaAxis.label), + Form("Bkgd fluctuations PC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", bkgd.randomConeR.value, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); + + spectra.add(Form("hScaled%s_deltaPtRandomConeAvoidLeadAndSubleadJet", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead, sublead jet in vic. %.1f vs. EA", bkgd.randomConeR.value, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); + + spectra.add(Form("hScaled%s_deltaPtRandomConeInEventTTSig", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f in events with TT{%.0f, %.0f} in vic. %.1f vs. EA", bkgd.randomConeR.value, ptTTsigMin, ptTTsigMax, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); } } - if (doprocessLeadingAndAssociatedTracksTask) { + // Bkgd fluctuations in MC part. level data + if (doprocessBkgdFluctuationsMCPartLevel || doprocessBkgdFluctuationsMCPartLevelWeighted) { + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaled%s_deltaPtRandomCone_PartLevel", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f vs. EA", bkgd.randomConeR.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); - spectra.add("hScaledFT0C_NleadTracks", "Total number of selected leading tracks vs scaled FT0C", kTH2F, {{scaledFT0C}, {1, 0.0, 1.}}); - spectra.add("hScaledFT0M_NleadTracks", "Total number of selected leading tracks vs scaled FT0M", kTH2F, {{scaledFT0M}, {1, 0.0, 1.}}); + spectra.add(Form("hScaled%s_deltaPtRandomConeAvoidLeadJet_PartLevel", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", bkgd.randomConeR.value, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); - spectra.add("hScaledFT0C_Correlation_LeadTrack_AssociatTracks", Form("Leading track #it{p}_{T} #in (%.2f, %.2f); Associated track #it{p}_{T} #in (%.2f, #it{p}_{T, lead. trk})", pTLeadTrack->at(0), pTLeadTrack->at(1), pTAssociatTrackMin.value), kTH2F, {{scaledFT0C}, {160, -1.28, 5.0, "#it{#varphi} (rad)"}}); - spectra.add("hScaledFT0M_Correlation_LeadTrack_AssociatTracks", Form("Leading track #it{p}_{T} #in (%.2f, %.2f); Associated track #it{p}_{T} #in (%.2f, #it{p}_{T, lead. trk})", pTLeadTrack->at(0), pTLeadTrack->at(1), pTAssociatTrackMin.value), kTH2F, {{scaledFT0M}, {160, -1.28, 5.0, "#it{#varphi} (rad)"}}); - } + spectra.add(Form("hScaled%s_deltaPtPerpConeAvoidLeadJet_PartLevel", eaAxis.label), + Form("Bkgd fluctuations PC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", bkgd.randomConeR.value, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); - if (doprocessBkgdFluctuationsRC) { - spectra.add("hScaledFT0C_deltaPtRandomCone", Form("Bkgd fluctuations RC with #it{R} = %.1f vs. EA", randomConeR.value), kTH2F, {{scaledFT0C}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); - spectra.add("hScaledFT0M_deltaPtRandomCone", Form("Bkgd fluctuations RC with #it{R} = %.1f vs. EA", randomConeR.value), kTH2F, {{scaledFT0M}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); + spectra.add(Form("hScaled%s_deltaPtRandomConeAvoidLeadAndSubleadJet_PartLevel", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead, sublead jet in vic. %.1f vs. EA", bkgd.randomConeR.value, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); - spectra.add("hScaledFT0C_deltaPtRandomConeAvoidLeadJet", Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", randomConeR.value, randomConeJetDeltaR.value), kTH2F, {{scaledFT0C}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); - spectra.add("hScaledFT0M_deltaPtRandomConeAvoidLeadJet", Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", randomConeR.value, randomConeJetDeltaR.value), kTH2F, {{scaledFT0M}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); + spectra.add(Form("hScaled%s_deltaPtRandomConeInEventTTSig_PartLevel", eaAxis.label), + Form("Bkgd fluctuations RC with #it{R} = %.1f in events with TT{%.0f, %.0f} in vic. %.1f vs. EA", bkgd.randomConeR.value, ptTTsigMin, ptTTsigMax, bkgd.minDeltaRToJet.value), + kTH2F, {{eaAxis.axis}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}, hist.sumw2); + } + } - spectra.add("hScaledFT0C_deltaPtPerpConeAvoidLeadJet", Form("Bkgd fluctuations PC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", randomConeR.value, randomConeJetDeltaR.value), kTH2F, {{scaledFT0C}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); - spectra.add("hScaledFT0M_deltaPtPerpConeAvoidLeadJet", Form("Bkgd fluctuations PC with #it{R} = %.1f avoid lead jet in vic. %.1f vs. EA", randomConeR.value, randomConeJetDeltaR.value), kTH2F, {{scaledFT0M}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); + if (doprocessTTSmearingPtPhi || doprocessTTSmearingPtPhiWeighted) { + AxisSpec relPtSmearTT{120, -5., 1., "(#it{p}_{T, part} - #it{p}_{T, det}) / #it{p}_{T, part}"}; + AxisSpec smearPhi{80, -0.2, 0.2, "#it{#varphi}_{part} - #it{#varphi}_{det}"}; + AxisSpec smearEta{80, -0.2, 0.2, "#it{#eta}_{part} - #it{#eta}_{det}"}; + + int nBinsPtTTSig = static_cast(tt.sigPtRange->at(1) - tt.sigPtRange->at(0)) * 5; + int nBinsPtTTRef = static_cast(tt.refPtRange->at(1) - tt.refPtRange->at(0)) * 5; + AxisSpec partPtTTSig{nBinsPtTTSig, tt.sigPtRange->at(0), tt.sigPtRange->at(1), "#it{p}_{T, part}^{TT_{Sig}}"}; + AxisSpec partPtTTRef{nBinsPtTTRef, tt.refPtRange->at(0), tt.refPtRange->at(1), "#it{p}_{T, part}^{TT_{Ref}}"}; + + //==================================================================================== + // Signal TT + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaleMult%s_PtSmearingTTSig", eaAxis.label), + Form("#it{p}_{T} smearing of TT_{Sig} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {relPtSmearTT}, {partPtTTSig}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_PhiSmearingTTSig", eaAxis.label), + Form("#it{#varphi} smearing of TT_{Sig} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearPhi}, {partPtTTSig}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_EtaSmearingTTSig", eaAxis.label), + Form("#it{#eta} smearing of TT_{Sig} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearEta}, {partPtTTSig}}, hist.sumw2); + + auto tmpHistPointer = spectra.add(Form("hScaled%s_FractionOfPartTTSigSatisfCond", eaAxis.label), + "Check associat. part. level also satisf. TT_{Sig} conditions", + kTH3F, {{eaAxis.axis}, {2, 0.0, 2.0}, {2, 0.0, 2.0}}); + tmpHistPointer->GetYaxis()->SetBinLabel(1, "#in |#it{#eta}| < 0.9"); + tmpHistPointer->GetYaxis()->SetBinLabel(2, "#notin |#it{#eta}| < 0.9"); + tmpHistPointer->GetZaxis()->SetBinLabel(1, "#it{p}_{T} #in TT_{Sig}"); + tmpHistPointer->GetZaxis()->SetBinLabel(2, "#it{p}_{T} #notin TT_{Sig}"); + } - spectra.add("hScaledFT0C_deltaPtRandomConeAvoidLeadAndSubleadJet", Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead, sublead jet in vic. %.1f vs. EA", randomConeR.value, randomConeJetDeltaR.value), kTH2F, {{scaledFT0C}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); - spectra.add("hScaledFT0M_deltaPtRandomConeAvoidLeadAndSubleadJet", Form("Bkgd fluctuations RC with #it{R} = %.1f avoid lead, sublead jet in vic. %.1f vs. EA", randomConeR.value, randomConeJetDeltaR.value), kTH2F, {{scaledFT0M}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); + // Reference TT + for (const auto& eaAxis : arrAxisSpecScaledEA) { + spectra.add(Form("hScaleMult%s_PtSmearingTTRef", eaAxis.label), + Form("#it{p}_{T} smearing of TT_{Ref} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {relPtSmearTT}, {partPtTTRef}}, hist.sumw2); - spectra.add("hScaledFT0C_deltaPtRandomConeInEventTTSig", Form("Bkgd fluctuations RC with #it{R} = %.1f in events with TT{%.0f, %.0f} in vic. %.1f vs. EA", randomConeR.value, ptTTsig->at(0), ptTTsig->at(1), randomConeJetDeltaR.value), kTH2F, {{scaledFT0C}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); - spectra.add("hScaledFT0M_deltaPtRandomConeInEventTTSig", Form("Bkgd fluctuations RC with #it{R} = %.1f in events with TT{%.0f, %.0f} in vic. %.1f vs. EA", randomConeR.value, ptTTsig->at(0), ptTTsig->at(1), randomConeJetDeltaR.value), kTH2F, {{scaledFT0M}, {400, -40., 60., "#delta#it{p}_{T} (GeV/#it{c})"}}); + spectra.add(Form("hScaleMult%s_PhiSmearingTTRef", eaAxis.label), + Form("#it{#varphi} smearing of TT_{Ref} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearPhi}, {partPtTTRef}}, hist.sumw2); + + spectra.add(Form("hScaleMult%s_EtaSmearingTTRef", eaAxis.label), + Form("#it{#eta} smearing of TT_{Ref} vs %s", eaAxis.label), + kTH3F, {{eaAxis.axis}, {smearEta}, {partPtTTRef}}, hist.sumw2); + } } } + //============================================================================= + // Recoil jet analysis + //============================================================================= + // Fill histograms with raw or MC det. level data template - void fillHistograms(JCollision const& collision, Jets const& jets, - JTracks const& tracks, float weight = 1.) + void fillHistograms(JCollision const& collision, + Jets const& jets, + JTracks const& tracks, + float weight = 1.) { bool bSigEv = false; std::vector vPhiOfTT; double phiTT = 0.; int nTT = 0; float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), meanFT0C); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), meanFT0A), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; auto dice = randGen->Rndm(); - if (dice < fracSig) + if (dice < tt.fracSig) bSigEv = true; spectra.fill(HIST("hScaledFT0C_vertexZ"), scaledFT0C, collision.posZ(), weight); @@ -570,13 +995,17 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0MTrackPtEtaPhi"), scaledFT0M, trackPt, track.eta(), trackPhi, weight); // Search for TT candidate - if (bSigEv && (trackPt > ptTTsig->at(0) && trackPt < ptTTsig->at(1))) { + const auto ptTTsigMin = tt.sigPtRange->at(0); + const auto ptTTsigMax = tt.sigPtRange->at(1); + if (bSigEv && (trackPt > ptTTsigMin && trackPt < ptTTsigMax)) { vPhiOfTT.push_back(trackPhi); spectra.fill(HIST("hTTSig_pT"), trackPt, weight); ++nTT; } - if (!bSigEv && (trackPt > ptTTref->at(0) && trackPt < ptTTref->at(1))) { + const auto ptTTrefMin = tt.refPtRange->at(0); + const auto ptTTrefMax = tt.refPtRange->at(1); + if (!bSigEv && (trackPt > ptTTrefMin && trackPt < ptTTrefMax)) { vPhiOfTT.push_back(trackPhi); ++nTT; } @@ -613,7 +1042,7 @@ struct RecoilJets { for (const auto& jet : jets) { // skip jets which have a constituent with pT above specified cut - if (isJetWithHighPtConstituent(jet, tracks)) + if (isJetWithHighPtConstituent(jet)) continue; float jetPt = jet.pt(); @@ -623,6 +1052,9 @@ struct RecoilJets { spectra.fill(HIST("hJetPtEtaPhiRhoArea"), jetPt, jet.eta(), jet.phi(), rho, jetArea, weight); if (nTT > 0) { + const auto phiMin = tt.phiRestr->at(0); + const auto phiMax = tt.phiRestr->at(1); + auto [dphi, bRecoilJet] = isRecoilJet(jet, phiTT); if (bSigEv) { @@ -633,9 +1065,9 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_TTSig"), scaledFT0M, dphi, jetPt, weight); spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig"), jetArea, jetPt, rho, weight); - if (phiTT > phiRestrTTSelection->at(0) && phiTT < phiRestrTTSelection->at(1)) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RectrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RectrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); + if (phiTT > phiMin && phiTT < phiMax) { + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RestrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RestrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -653,9 +1085,9 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_TTRef"), scaledFT0M, dphi, jetPt, weight); spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef"), jetArea, jetPt, rho, weight); - if (phiTT > phiRestrTTSelection->at(0) && phiTT < phiRestrTTSelection->at(1)) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RectrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RectrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); + if (phiTT > phiMin && phiTT < phiMax) { + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RestrictedPhi"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RestrictedPhi"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -671,19 +1103,22 @@ struct RecoilJets { } template - void fillMCPHistograms(JCollision const& collision, Jets const& jets, - JParticles const& particles, float weight = 1.) + void fillHistogramsMCPartLevel(JCollision const& collision, + Jets const& jets, + JParticles const& particles, + float weight = 1.) { bool bSigEv = false; std::vector vPhiOfTT; double phiTT = 0.; int nTT = 0; float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), meanFT0CPartLevel); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), meanFT0APartLevel), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.meanPartLevel, ft0c.meanPartLevel); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; auto dice = randGen->Rndm(); - if (dice < fracSig) + if (dice < tt.fracSig) bSigEv = true; spectra.fill(HIST("hScaledFT0C_vertexZMC"), scaledFT0C, collision.posZ(), weight); @@ -693,13 +1128,7 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0M_Rho_Part"), scaledFT0M, rho, weight); for (const auto& particle : particles) { - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (!pdgParticle) - continue; - - // Need charge and physical primary particles - bool bParticleNeutral = (static_cast(pdgParticle->Charge()) == 0); - if (bParticleNeutral || !particle.isPhysicalPrimary()) + if (skipParticle(particle)) continue; float particlePt = particle.pt(); @@ -708,12 +1137,17 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0CPartPtEtaPhi"), scaledFT0C, particlePt, particle.eta(), particlePhi, weight); spectra.fill(HIST("hScaledFT0MPartPtEtaPhi"), scaledFT0M, particlePt, particle.eta(), particlePhi, weight); - if (bSigEv && (particlePt > ptTTsig->at(0) && particlePt < ptTTsig->at(1))) { + // Search for TT candidate + const auto ptTTsigMin = tt.sigPtRange->at(0); + const auto ptTTsigMax = tt.sigPtRange->at(1); + if (bSigEv && (particlePt > ptTTsigMin && particlePt < ptTTsigMax)) { vPhiOfTT.push_back(particlePhi); ++nTT; } - if (!bSigEv && (particlePt > ptTTref->at(0) && particlePt < ptTTref->at(1))) { + const auto ptTTrefMin = tt.refPtRange->at(0); + const auto ptTTrefMax = tt.refPtRange->at(1); + if (!bSigEv && (particlePt > ptTTrefMin && particlePt < ptTTrefMax)) { vPhiOfTT.push_back(particlePhi); ++nTT; } @@ -756,6 +1190,8 @@ struct RecoilJets { spectra.fill(HIST("hJetPtEtaPhiRhoArea_Part"), jetPt, jet.eta(), jet.phi(), rho, jetArea, weight); if (nTT > 0) { + const auto phiMin = tt.phiRestr->at(0); + const auto phiMax = tt.phiRestr->at(1); auto [dphi, bRecoilJet] = isRecoilJet(jet, phiTT); @@ -768,9 +1204,9 @@ struct RecoilJets { spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig_Part"), jetArea, jetPt, rho, weight); - if (phiTT > phiRestrTTSelection->at(0) && phiTT < phiRestrTTSelection->at(1)) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RectrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); + if (phiTT > phiMin && phiTT < phiMax) { + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTSig_RestrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTSig_RestrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -791,9 +1227,9 @@ struct RecoilJets { spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef_Part"), jetArea, jetPt, rho, weight); - if (phiTT > phiRestrTTSelection->at(0) && phiTT < phiRestrTTSelection->at(1)) { - spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); - spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RectrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); + if (phiTT > phiMin && phiTT < phiMax) { + spectra.fill(HIST("hScaledFT0C_DPhi_JetPt_Corr_TTRef_RestrictedPhi_Part"), scaledFT0C, dphi, jetPtCorr, weight); + spectra.fill(HIST("hScaledFT0M_DPhi_JetPt_Corr_TTRef_RestrictedPhi_Part"), scaledFT0M, dphi, jetPtCorr, weight); } if (bRecoilJet) { @@ -808,45 +1244,270 @@ struct RecoilJets { } } - template - void fillMatchedHistograms(JTracksTable const& tracks, - JetsBase const& jetsBase, JetsTag const& jetsTag, - float weight = 1.) + //============================================================================= + // Construction of response matrix + //============================================================================= + template + void fillMatchedGeoHistograms(JetsPart const& jetsPart, + JetsDet const& jetsDet, + JTracks const& tracks, + float partLevelCollRho, + float detLevelCollRho, + float weight = 1.) { - std::vector vPhiOfTT; - double phiTTSig = 0.; + /// TODO: consider TT cand. on both MC levels simultaneously - for (const auto& track : tracks) { - if (skipTrack(track)) + // Utilities for recoil jets; TTsis at det. level MC + std::vector vPhiOfTT = getPhiOfAllTTsigCandidates(tracks); + double phiTTSig = 0.0; + bool bIsThereTTSig = vPhiOfTT.size() > 0; + + if (bIsThereTTSig) + phiTTSig = getPhiTT(vPhiOfTT); + + for (const auto& jetPart : jetsPart) { + auto partJetPt = jetPart.pt(); + auto partJetPtCorr = partJetPt - partLevelCollRho * jetPart.area(); + + bool bIsPartJetRecoil = + get<1>(isRecoilJet(jetPart, phiTTSig)) && bIsThereTTSig; + + // Distribution of all part. level jets + spectra.fill(HIST("hPartLevelInclusiveJetsPt"), partJetPt, weight); + spectra.fill(HIST("hPartLevelInclusiveJetsPtCorr"), partJetPtCorr, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hPartLevelRecoilJetsPt"), partJetPt, weight); + spectra.fill(HIST("hPartLevelRecoilJetsPtCorr"), partJetPtCorr, weight); + } + + if (jetPart.has_matchedJetGeo()) { + const auto& jetsDetMatched = jetPart.template matchedJetGeo_as(); + + for (const auto& jetDetMatched : jetsDetMatched) { + // Skip matches where detector level jets have a constituent with pT above specified cut + const bool skipMatchedDetJet = isJetWithHighPtConstituent(jetDetMatched); + + if (skipMatchedDetJet) { + // Miss jets + spectra.fill(HIST("hMissedInclusiveJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedInclusiveJetsPtCorr"), partJetPtCorr, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hMissedRecoilJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedRecoilJetsPtCorr"), partJetPtCorr, weight); + } + + } else { + auto detJetPt = jetDetMatched.pt(); + auto detJetPtCorr = detJetPt - detLevelCollRho * jetDetMatched.area(); + + spectra.fill(HIST("hNumberMatchedInclusiveDetJetsPerOnePartJet"), jetsDetMatched.size(), detJetPt, partJetPt, weight); + + spectra.fill(HIST("hResponseMatrixInclusiveJetsPt"), detJetPt, partJetPt, weight); + spectra.fill(HIST("hResponseMatrixInclusiveJetsPtCorr"), detJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hInclusiveJESPt"), (partJetPt - detJetPt) / partJetPt, partJetPt, weight); + spectra.fill(HIST("hInclusiveJESPtCorr"), (partJetPtCorr - detJetPtCorr) / partJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hInclusiveJESPhi"), jetPart.phi() - jetDetMatched.phi(), partJetPt, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hNumberMatchedRecoilDetJetsPerOnePartJet"), jetsDetMatched.size(), detJetPt, partJetPt, weight); + + spectra.fill(HIST("hResponseMatrixRecoilJetsPt"), detJetPt, partJetPt, weight); + spectra.fill(HIST("hResponseMatrixRecoilJetsPtCorr"), detJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hRecoilJESPt"), (partJetPt - detJetPt) / partJetPt, partJetPt, weight); + spectra.fill(HIST("hRecoilJESPtCorr"), (partJetPtCorr - detJetPtCorr) / partJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hRecoilJESPhi"), jetPart.phi() - jetDetMatched.phi(), partJetPt, weight); + } + } + } + } else { + // Miss jets + spectra.fill(HIST("hMissedInclusiveJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedInclusiveJetsPtCorr"), partJetPtCorr, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hMissedRecoilJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedRecoilJetsPtCorr"), partJetPtCorr, weight); + } + } + } + + // Reconstructed jets + for (const auto& jetDet : jetsDet) { + if (isJetWithHighPtConstituent(jetDet)) continue; - if (track.pt() > ptTTsig->at(0) && track.pt() < ptTTsig->at(1)) { - vPhiOfTT.push_back(track.phi()); + auto detJetPt = jetDet.pt(); + auto detJetPtCorr = detJetPt - detLevelCollRho * jetDet.area(); + + bool bIsJetRecoil = + get<1>(isRecoilJet(jetDet, phiTTSig)) && bIsThereTTSig; + + // Distribution of all det. level jets + spectra.fill(HIST("hDetLevelInclusiveJetsPt"), detJetPt, weight); + spectra.fill(HIST("hDetLevelInclusiveJetsPtCorr"), detJetPtCorr, weight); + + if (bIsJetRecoil) { + spectra.fill(HIST("hDetLevelRecoilJetsPt"), detJetPt, weight); + spectra.fill(HIST("hDetLevelRecoilJetsPtCorr"), detJetPtCorr, weight); + } + + if (!jetDet.has_matchedJetGeo()) { + spectra.fill(HIST("hFakeInclusiveJetsPt"), detJetPt, weight); + spectra.fill(HIST("hFakeInclusiveJetsPtCorr"), detJetPtCorr, weight); + + if (bIsJetRecoil) { + spectra.fill(HIST("hFakeRecoilJetsPt"), detJetPt, weight); + spectra.fill(HIST("hFakeRecoilJetsPtCorr"), detJetPtCorr, weight); + } } } + } + /// TODO: think how to implement matching matching geo/geo+pT in one function + template + void fillMatchedGeoPtHistograms(JetsPart const& jetsPart, + JetsDet const& jetsDet, + JTracks const& tracks, + float partLevelCollRho, + float detLevelCollRho, + float weight = 1.) + { + // Utilities for recoil jets; TTsis at det. level MC + std::vector vPhiOfTT = getPhiOfAllTTsigCandidates(tracks); + double phiTTSig = 0.0; bool bIsThereTTSig = vPhiOfTT.size() > 0; if (bIsThereTTSig) phiTTSig = getPhiTT(vPhiOfTT); - for (const auto& jetBase : jetsBase) { - bool bIsBaseJetRecoil = - get<1>(isRecoilJet(jetBase, phiTTSig)) && bIsThereTTSig; - dataForUnfolding(jetBase, jetsTag, bIsBaseJetRecoil, tracks, weight); + for (const auto& jetPart : jetsPart) { + auto partJetPt = jetPart.pt(); + auto partJetPtCorr = partJetPt - partLevelCollRho * jetPart.area(); + + bool bIsPartJetRecoil = + get<1>(isRecoilJet(jetPart, phiTTSig)) && bIsThereTTSig; + + // Distribution of all part. level jets + spectra.fill(HIST("hPartLevelInclusiveJetsPt"), partJetPt, weight); + spectra.fill(HIST("hPartLevelInclusiveJetsPtCorr"), partJetPtCorr, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hPartLevelRecoilJetsPt"), partJetPt, weight); + spectra.fill(HIST("hPartLevelRecoilJetsPtCorr"), partJetPtCorr, weight); + } + + // Geo + pT matching + if (jetPart.has_matchedJetGeo() && jetPart.has_matchedJetPt()) { + const auto& jetsDetMatched = jetPart.template matchedJetGeo_as(); + auto both = intersectMatchIds(jetPart.matchedJetGeoIds(), jetPart.matchedJetPtIds()); + + for (const auto& jetDetMatched : jetsDetMatched) { + // Skip matches where detector level jets have a constituent with pT above specified cut + const bool skipMatchedDetJet = isJetWithHighPtConstituent(jetDetMatched); + + // If indecies for geo and pT matching do not coinside, reject detector level jet + const bool skipNotBothId = !both.contains(jetDetMatched.globalIndex()); + + if (skipMatchedDetJet || skipNotBothId) { + // Miss jets + spectra.fill(HIST("hMissedInclusiveJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedInclusiveJetsPtCorr"), partJetPtCorr, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hMissedRecoilJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedRecoilJetsPtCorr"), partJetPtCorr, weight); + } + } else { + auto detJetPt = jetDetMatched.pt(); + auto detJetPtCorr = detJetPt - detLevelCollRho * jetDetMatched.area(); + + spectra.fill(HIST("hNumberMatchedInclusiveDetJetsPerOnePartJet"), jetsDetMatched.size(), detJetPt, partJetPt, weight); + + spectra.fill(HIST("hResponseMatrixInclusiveJetsPt"), detJetPt, partJetPt, weight); + spectra.fill(HIST("hResponseMatrixInclusiveJetsPtCorr"), detJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hInclusiveJESPt"), (partJetPt - detJetPt) / partJetPt, partJetPt, weight); + spectra.fill(HIST("hInclusiveJESPtCorr"), (partJetPtCorr - detJetPtCorr) / partJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hInclusiveJESPhi"), jetPart.phi() - jetDetMatched.phi(), partJetPt, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hNumberMatchedRecoilDetJetsPerOnePartJet"), jetsDetMatched.size(), detJetPt, partJetPt, weight); + + spectra.fill(HIST("hResponseMatrixRecoilJetsPt"), detJetPt, partJetPt, weight); + spectra.fill(HIST("hResponseMatrixRecoilJetsPtCorr"), detJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hRecoilJESPt"), (partJetPt - detJetPt) / partJetPt, partJetPt, weight); + spectra.fill(HIST("hRecoilJESPtCorr"), (partJetPtCorr - detJetPtCorr) / partJetPtCorr, partJetPtCorr, weight); + + spectra.fill(HIST("hRecoilJESPhi"), jetPart.phi() - jetDetMatched.phi(), partJetPt, weight); + } + } + } + } else { + // Miss jets + spectra.fill(HIST("hMissedInclusiveJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedInclusiveJetsPtCorr"), partJetPtCorr, weight); + + if (bIsPartJetRecoil) { + spectra.fill(HIST("hMissedRecoilJetsPt"), partJetPt, weight); + spectra.fill(HIST("hMissedRecoilJetsPtCorr"), partJetPtCorr, weight); + } + } + } + + // Reconstructed jets + for (const auto& jetDet : jetsDet) { + if (isJetWithHighPtConstituent(jetDet)) + continue; + + auto detJetPt = jetDet.pt(); + auto detJetPtCorr = detJetPt - detLevelCollRho * jetDet.area(); + + bool bIsJetRecoil = + get<1>(isRecoilJet(jetDet, phiTTSig)) && bIsThereTTSig; + + // Distribution of all det. level jets + spectra.fill(HIST("hDetLevelInclusiveJetsPt"), detJetPt, weight); + spectra.fill(HIST("hDetLevelInclusiveJetsPtCorr"), detJetPtCorr, weight); + + if (bIsJetRecoil) { + spectra.fill(HIST("hDetLevelRecoilJetsPt"), detJetPt, weight); + spectra.fill(HIST("hDetLevelRecoilJetsPtCorr"), detJetPtCorr, weight); + } + + if (!jetDet.has_matchedJetGeo()) { + spectra.fill(HIST("hFakeInclusiveJetsPt"), detJetPt, weight); + spectra.fill(HIST("hFakeInclusiveJetsPtCorr"), detJetPtCorr, weight); + + if (bIsJetRecoil) { + spectra.fill(HIST("hFakeRecoilJetsPt"), detJetPt, weight); + spectra.fill(HIST("hFakeRecoilJetsPtCorr"), detJetPtCorr, weight); + } + } } } + //============================================================================= + // Event Activity analysis + //============================================================================= template - void fillMultiplicityHistogramsOO(JCollision const& collision, - float weight = 1.) + void fillMultiplicityHistograms(JCollision const& collision, + float weight = 1.) { - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float multFT0M = collision.multFT0M(); - float scaledFT0A = getScaledFT0(multFT0A, meanFT0A); - float scaledFT0C = getScaledFT0(multFT0C, meanFT0C); - float scaledFT0M = getScaledFT0M(scaledFT0A, scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto multFT0A = ft0Metrics.multFT0A; + const auto multFT0C = ft0Metrics.multFT0C; + const auto multFT0M = ft0Metrics.multFT0M; + const auto scaledFT0A = ft0Metrics.scaledFT0A; + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; float multZNA = collision.multZNA(); float multZNC = collision.multZNC(); @@ -894,34 +1555,39 @@ struct RecoilJets { } template - void fillMultiplicityHistogramsPartLevelMC(JCollisionMC const& collision, + void fillMultiplicityHistogramsMCPartLevel(JCollisionMC const& collision, float weight = 1.) { - spectra.fill(HIST("hMultFT0APartLevel"), collision.multFT0A(), weight); - spectra.fill(HIST("hMultFT0CPartLevel"), collision.multFT0C(), weight); - spectra.fill(HIST("hMultFT0MPartLevel"), collision.multFT0A() + collision.multFT0C(), weight); - - auto scaledFT0A = getScaledFT0(collision.multFT0A(), meanFT0APartLevel); - auto scaledFT0C = getScaledFT0(collision.multFT0C(), meanFT0CPartLevel); - spectra.fill(HIST("hScaleMultFT0APartLevel"), scaledFT0A, weight); - spectra.fill(HIST("hScaleMultFT0CPartLevel"), scaledFT0C, weight); - spectra.fill(HIST("hScaleMultFT0MPartLevel"), getScaledFT0M(scaledFT0A, scaledFT0C), weight); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.meanPartLevel, ft0c.meanPartLevel); + spectra.fill(HIST("hMultFT0APartLevel"), ft0Metrics.multFT0A, weight); + spectra.fill(HIST("hMultFT0CPartLevel"), ft0Metrics.multFT0C, weight); + spectra.fill(HIST("hMultFT0MPartLevel"), ft0Metrics.multFT0M, weight); + + spectra.fill(HIST("hScaleMultFT0APartLevel"), ft0Metrics.scaledFT0A, weight); + spectra.fill(HIST("hScaleMultFT0CPartLevel"), ft0Metrics.scaledFT0C, weight); + spectra.fill(HIST("hScaleMultFT0MPartLevel"), ft0Metrics.scaledFT0M, weight); } + //============================================================================= + // Event Activity QA analysis in raw OO data + //============================================================================= template - void fillMultiplicityQA(Collision const& collision, BC const&, - ZDC const&, float weight = 1.) + void fillEventActivitySelectionQAHistograms(Collision const& collision, + BC const&, + ZDC const&, + float weight = 1.) { int runNumber = collision.multRunNumber(); int fillNumber = getBinNumberOnYaxisForGivenRun(spectra.get(HIST("hScaledFT0CPerRunPerSetOfFlags")), runNumber) - 0.5; // Same for FT0M distrib. // FT0 Signal - float multFT0A = collision.multFT0A(); - float multFT0C = collision.multFT0C(); - float multFT0M = collision.multFT0M(); - float scaledFT0A = getScaledFT0(multFT0A, meanFT0A); - float scaledFT0C = getScaledFT0(multFT0C, meanFT0C); - float scaledFT0M = getScaledFT0M(scaledFT0A, scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto multFT0A = ft0Metrics.multFT0A; + const auto multFT0C = ft0Metrics.multFT0C; + const auto multFT0M = ft0Metrics.multFT0M; + const auto scaledFT0A = ft0Metrics.scaledFT0A; + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; // Event with flag Sel8 spectra.fill(HIST("hFT0APerRunPerSetOfFlags"), multFT0A, fillNumber, 0.5, weight); @@ -932,6 +1598,8 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 0.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 0.5, weight); + spectra.fill(HIST("hEventSelectionCountQA"), 0.5); + bool isGoodZvtxFT0vsPV = collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV); if (isGoodZvtxFT0vsPV) { spectra.fill(HIST("hFT0APerRunPerSetOfFlags"), multFT0A, fillNumber, 1.5, weight); @@ -941,6 +1609,8 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0APerRunPerSetOfFlags"), scaledFT0A, fillNumber, 1.5, weight); spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 1.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 1.5, weight); + + spectra.fill(HIST("hEventSelectionCountQA"), 1.5); } bool isNoSameBunchPileup = collision.selection_bit(aod::evsel::kNoSameBunchPileup); @@ -952,9 +1622,13 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0APerRunPerSetOfFlags"), scaledFT0A, fillNumber, 2.5, weight); spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 2.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 2.5, weight); + + spectra.fill(HIST("hEventSelectionCountQA"), 2.5); } - if (isGoodZvtxFT0vsPV && isNoSameBunchPileup) { + bool isNoCollInTimeRangeStandard = collision.selection_bit(aod::evsel::kNoCollInTimeRangeStandard); + if (isNoCollInTimeRangeStandard) { + spectra.fill(HIST("hFT0APerRunPerSetOfFlags"), multFT0A, fillNumber, 3.5, weight); spectra.fill(HIST("hFT0CPerRunPerSetOfFlags"), multFT0C, fillNumber, 3.5, weight); spectra.fill(HIST("hFT0MPerRunPerSetOfFlags"), multFT0M, fillNumber, 3.5, weight); @@ -962,20 +1636,34 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0APerRunPerSetOfFlags"), scaledFT0A, fillNumber, 3.5, weight); spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 3.5, weight); spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 3.5, weight); - } else { - return; + + spectra.fill(HIST("hEventSelectionCountQA"), 3.5); } - // Investigate other EA variables + if (!(isGoodZvtxFT0vsPV && isNoSameBunchPileup && isNoCollInTimeRangeStandard)) + return; + + spectra.fill(HIST("hEventSelectionCountQA"), 4.5); // All accepted events after 4 flags cut + + spectra.fill(HIST("hFT0APerRunPerSetOfFlags"), multFT0A, fillNumber, 4.5, weight); + spectra.fill(HIST("hFT0CPerRunPerSetOfFlags"), multFT0C, fillNumber, 4.5, weight); + spectra.fill(HIST("hFT0MPerRunPerSetOfFlags"), multFT0M, fillNumber, 4.5, weight); + + spectra.fill(HIST("hScaledFT0APerRunPerSetOfFlags"), scaledFT0A, fillNumber, 4.5, weight); + spectra.fill(HIST("hScaledFT0CPerRunPerSetOfFlags"), scaledFT0C, fillNumber, 4.5, weight); + spectra.fill(HIST("hScaledFT0MPerRunPerSetOfFlags"), scaledFT0M, fillNumber, 4.5, weight); + //____________________________________________________________________________________ + // Investigate other EA variables // Multiplicity equalized for the vertex position with FT0 detector - float multZeqFT0A = collision.multZeqFT0A(); - float multZeqFT0C = collision.multZeqFT0C(); - float multZeqFT0M = multZeqFT0A + multZeqFT0C; - float scaledZeqFT0A = getScaledFT0(multZeqFT0A, meanZeqFT0A); - float scaledZeqFT0C = getScaledFT0(multZeqFT0C, meanZeqFT0C); - float scaledZeqFT0M = getScaledFT0M(scaledZeqFT0A, scaledZeqFT0C); + const auto zeqFT0Metrics = makeFT0Metrics(collision.multZeqFT0A(), collision.multZeqFT0C(), ft0a.meanZeq, ft0c.meanZeq); + const auto multZeqFT0A = zeqFT0Metrics.multFT0A; + const auto multZeqFT0C = zeqFT0Metrics.multFT0C; + const auto multZeqFT0M = zeqFT0Metrics.multFT0M; + const auto scaledZeqFT0A = zeqFT0Metrics.scaledFT0A; + const auto scaledZeqFT0C = zeqFT0Metrics.scaledFT0C; + const auto scaledZeqFT0M = zeqFT0Metrics.scaledFT0M; spectra.fill(HIST("hMultZeqFT0A"), multZeqFT0A, weight); spectra.fill(HIST("hMultZeqFT0C"), multZeqFT0C, weight); @@ -1007,22 +1695,25 @@ struct RecoilJets { spectra.fill(HIST("hScaledFT0C_TracksPV"), scaledFT0C, multNContribs, weight); spectra.fill(HIST("hScaledFT0M_TracksPV"), scaledFT0M, multNContribs, weight); - if (foundBC.foundFT0Id() > 0) // -1 if does not + if (foundBC.foundFT0Id() != -1) // -1 if does not { spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 0.5, fillNumber, weight); } else { spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 1.5, fillNumber, weight); - spectra.fill(HIST("hFT0AsignalWithoutBC"), multFT0A, fillNumber, weight); - spectra.fill(HIST("hFT0CsignalWithoutBC"), multFT0C, fillNumber, weight); - spectra.fill(HIST("hFT0MsignalWithoutBC"), multFT0M, fillNumber, weight); + spectra.fill(HIST("hScaledFT0AsignalWithoutBC"), scaledFT0A, fillNumber, weight); + spectra.fill(HIST("hScaledFT0CsignalWithoutBC"), scaledFT0C, fillNumber, weight); + spectra.fill(HIST("hScaledFT0MsignalWithoutBC"), scaledFT0M, fillNumber, weight); } - if (collision.foundBCId() > 0) + if (collision.foundBCId() != -1) // -1 if does not spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 2.5, fillNumber, weight); else spectra.fill(HIST("hIsFT0SignalComeFromCollPerRun"), 3.5, fillNumber, weight); } + //============================================================================= + // Di-hadron azimuthal correlation in raw and MC det. level (no weight; MB events) data + //============================================================================= template void fillLeadingAndAssociatedTracksTask(JCollision const& collision, JTracks const& tracks, float weight = 1.) { @@ -1030,8 +1721,9 @@ struct RecoilJets { std::vector vPtOfLeadingTracks; std::vector vPhiOfAssociatedTracks; - float scaledFT0C = getScaledFT0(collision.multFT0C(), meanFT0C); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), meanFT0A), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; // Search for leading tracks for (const auto& track : tracks) { @@ -1040,7 +1732,7 @@ struct RecoilJets { float trackPt = track.pt(); - if (trackPt > pTLeadTrack->at(0) && trackPt < pTLeadTrack->at(1)) { + if (trackPt > twoPartCorrel.leadPtRange->at(0) && trackPt < twoPartCorrel.leadPtRange->at(1)) { vPhiOfLeadingTracks.push_back(track.phi()); vPtOfLeadingTracks.push_back(trackPt); } @@ -1065,7 +1757,7 @@ struct RecoilJets { float trackPhi = track.phi(); // Search for associated tracks - if (trackPt > pTAssociatTrackMin && trackPt < pTLeadingTrack) { + if (trackPt > twoPartCorrel.associatTrackPtMin && trackPt < pTLeadingTrack) { double dphi = RecoDecay::constrainAngle(phiLeadingTrack - trackPhi, -1.3); spectra.fill(HIST("hScaledFT0C_Correlation_LeadTrack_AssociatTracks"), scaledFT0C, dphi, weight); spectra.fill(HIST("hScaledFT0M_Correlation_LeadTrack_AssociatTracks"), scaledFT0M, dphi, weight); @@ -1074,17 +1766,22 @@ struct RecoilJets { } } - // Background fluctuations in MC part. level + //============================================================================= + // Estimation of bkgd fluctuations + //============================================================================= + + // Background fluctuations in raw data and MC det. level template - void fillBkgdFluctuationsRC(JCollision const& collision, - Jets const& jets, - JTracks const& tracks, - float weight = 1.) + void fillBkgdFluctuations(JCollision const& collision, + Jets const& jets, + JTracks const& tracks, + float weight = 1.) { //---------------------------------------------------------- float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), meanFT0C); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), meanFT0A), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; //---------------------------------------------------------- // Study bkgd fluctuations in events with TTsig @@ -1092,9 +1789,9 @@ struct RecoilJets { //---------------------------------------------------------- // Place absolutely random cone (anywhere in an event) - float randomConeEta = randGen->Uniform(-trkEtaCut + randomConeR, trkEtaCut - randomConeR); + float randomConeEta = randGen->Uniform(-trk.etaCut + bkgd.randomConeR, trk.etaCut - bkgd.randomConeR); float randomConePhi = randGen->Uniform(0.0, constants::math::TwoPI); - float radiusRC2 = std::pow(randomConeR, 2); + float radiusRC2 = std::pow(bkgd.randomConeR, 2); float areaRC = constants::math::PI * radiusRC2; float randomConePt = 0.0; @@ -1111,8 +1808,10 @@ struct RecoilJets { randomConePt += track.pt(); } - // Search for TT candidate - if (track.pt() > ptTTsig->at(0) && track.pt() < ptTTsig->at(1)) { + // Search for TT_Sig candidate + const auto ptTTsigMin = tt.sigPtRange->at(0); + const auto ptTTsigMax = tt.sigPtRange->at(1); + if (track.pt() > ptTTsigMin && track.pt() < ptTTsigMax) { vCandForTT.emplace_back(index); } ++index; @@ -1124,7 +1823,7 @@ struct RecoilJets { // Avoid leading jet (JE jet reconstruction sorts jets by pT) // square of distance to accept RC placement in events with leading jet - float dMinR2 = std::pow(jetR + randomConeR + randomConeJetDeltaR, 2); + float dMinR2 = std::pow(jet.radius + bkgd.randomConeR + bkgd.minDeltaRToJet, 2); // max # of attempts to find a place for RC; to avoid possibility with infinite loop in While cycle const int maxAttempts = 15000; @@ -1144,7 +1843,7 @@ struct RecoilJets { break; } - randomConeEta = randGen->Uniform(-trkEtaCut + randomConeR, trkEtaCut - randomConeR); + randomConeEta = randGen->Uniform(-trk.etaCut + bkgd.randomConeR, trk.etaCut - bkgd.randomConeR); randomConePhi = randGen->Uniform(0.0, constants::math::TwoPI); dEtaLeadJet = std::pow(leadJetEta - randomConeEta, 2); @@ -1172,7 +1871,7 @@ struct RecoilJets { //---------------------------------------------------------- // Place cone perpendicular to the leading jet (perpendicular cone) float perpConeEta = leadJetEta; - float perpConePhi = leadJetPhi + constants::math::PI / 2.; + float perpConePhi = leadJetPhi + constants::math::PIHalf; float perpConePt = 0.0; for (const auto& track : tracks) { @@ -1216,7 +1915,7 @@ struct RecoilJets { auto objTT = tracks.iteratorAt(vCandForTT[randIndexTrack]); // Skip events where TT is not a part of leading or subleading jets (mutlijet event, difficult to place RC and avoid hard jets) - if (IsTrackInJet(jets.iteratorAt(0), objTT) || IsTrackInJet(jets.iteratorAt(1), objTT)) { + if (isTrackInJet(jets.iteratorAt(0), objTT) || isTrackInJet(jets.iteratorAt(1), objTT)) { keepEventWithTT = true; } } @@ -1229,7 +1928,7 @@ struct RecoilJets { break; } - randomConeEta = randGen->Uniform(-trkEtaCut + randomConeR, trkEtaCut - randomConeR); + randomConeEta = randGen->Uniform(-trk.etaCut + bkgd.randomConeR, trk.etaCut - bkgd.randomConeR); randomConePhi = randGen->Uniform(0.0, constants::math::TwoPI); dEtaLeadJet = std::pow(leadJetEta - randomConeEta, 2); @@ -1265,15 +1964,16 @@ struct RecoilJets { } template - void fillBkgdFluctuationsRCMCP(JCollision const& collision, - Jets const& jets, - JParticles const& particles, - float weight = 1.) + void fillBkgdFluctuationsMCPartLevel(JCollision const& collision, + Jets const& jets, + JParticles const& particles, + float weight = 1.) { //---------------------------------------------------------- float rho = collision.rho(); - float scaledFT0C = getScaledFT0(collision.multFT0C(), meanFT0C); - float scaledFT0M = getScaledFT0M(getScaledFT0(collision.multFT0A(), meanFT0A), scaledFT0C); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.meanPartLevel, ft0c.meanPartLevel); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; //---------------------------------------------------------- // Study bkgd fluctuations in events with TTsig @@ -1281,21 +1981,15 @@ struct RecoilJets { //---------------------------------------------------------- // Place absolutely random cone (anywhere in an event) - float randomConeEta = randGen->Uniform(-trkEtaCut + randomConeR, trkEtaCut - randomConeR); + float randomConeEta = randGen->Uniform(-trk.etaCut + bkgd.randomConeR, trk.etaCut - bkgd.randomConeR); float randomConePhi = randGen->Uniform(0.0, constants::math::TwoPI); - float radiusRC2 = std::pow(randomConeR, 2); + float radiusRC2 = std::pow(bkgd.randomConeR, 2); float areaRC = constants::math::PI * radiusRC2; float randomConePt = 0.0; uint64_t index = 0; for (const auto& particle : particles) { - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (!pdgParticle) - continue; - - // Need charge and physical primary particles - bool bParticleNeutral = (static_cast(pdgParticle->Charge()) == 0); - if (bParticleNeutral || !particle.isPhysicalPrimary()) + if (skipParticle(particle)) continue; float dEta = std::pow(randomConeEta - particle.eta(), 2); @@ -1306,20 +2000,22 @@ struct RecoilJets { randomConePt += particle.pt(); } - // Search for TT candidate - if (particle.pt() > ptTTsig->at(0) && particle.pt() < ptTTsig->at(1)) { + // Search for TT_Sig candidate + const auto ptTTsigMin = tt.sigPtRange->at(0); + const auto ptTTsigMax = tt.sigPtRange->at(1); + if (particle.pt() > ptTTsigMin && particle.pt() < ptTTsigMax) { vCandForTT.emplace_back(index); } ++index; } - spectra.fill(HIST("hScaledFT0C_deltaPtRandomCone"), scaledFT0C, randomConePt - areaRC * rho, weight); - spectra.fill(HIST("hScaledFT0M_deltaPtRandomCone"), scaledFT0M, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0C_deltaPtRandomCone_PartLevel"), scaledFT0C, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0M_deltaPtRandomCone_PartLevel"), scaledFT0M, randomConePt - areaRC * rho, weight); //---------------------------------------------------------- // Avoid leading jet (JE jet reconstruction sorts jets by pT) // square of distance to accept RC placement in events with leading jet - float dMinR2 = std::pow(jetR + randomConeR + randomConeJetDeltaR, 2); + float dMinR2 = std::pow(jet.radius + bkgd.randomConeR + bkgd.minDeltaRToJet, 2); // max # of attempts to find a place for RC; to avoid possibility with infinite loop in While cycle const int maxAttempts = 15000; @@ -1339,7 +2035,7 @@ struct RecoilJets { break; } - randomConeEta = randGen->Uniform(-trkEtaCut + randomConeR, trkEtaCut - randomConeR); + randomConeEta = randGen->Uniform(-trk.etaCut + bkgd.randomConeR, trk.etaCut - bkgd.randomConeR); randomConePhi = randGen->Uniform(0.0, constants::math::TwoPI); dEtaLeadJet = std::pow(leadJetEta - randomConeEta, 2); @@ -1349,13 +2045,7 @@ struct RecoilJets { if (isTherePlaceForRC) { randomConePt = 0.0; for (const auto& particle : particles) { - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (!pdgParticle) - continue; - - // Need charge and physical primary particles - bool bParticleNeutral = (static_cast(pdgParticle->Charge()) == 0); - if (bParticleNeutral || !particle.isPhysicalPrimary()) + if (skipParticle(particle)) continue; float dEta = std::pow(randomConeEta - particle.eta(), 2); @@ -1366,24 +2056,18 @@ struct RecoilJets { randomConePt += particle.pt(); } } - spectra.fill(HIST("hScaledFT0C_deltaPtRandomConeAvoidLeadJet"), scaledFT0C, randomConePt - areaRC * rho, weight); - spectra.fill(HIST("hScaledFT0M_deltaPtRandomConeAvoidLeadJet"), scaledFT0M, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0C_deltaPtRandomConeAvoidLeadJet_PartLevel"), scaledFT0C, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0M_deltaPtRandomConeAvoidLeadJet_PartLevel"), scaledFT0M, randomConePt - areaRC * rho, weight); } //---------------------------------------------------------- // Place cone perpendicular to the leading jet (perpendicular cone) float perpConeEta = leadJetEta; - float perpConePhi = leadJetPhi + constants::math::PI / 2.; + float perpConePhi = leadJetPhi + constants::math::PIHalf; float perpConePt = 0.0; for (const auto& particle : particles) { - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (!pdgParticle) - continue; - - // Need charge and physical primary particles - bool bParticleNeutral = (static_cast(pdgParticle->Charge()) == 0); - if (bParticleNeutral || !particle.isPhysicalPrimary()) + if (skipParticle(particle)) continue; float dEta = std::pow(perpConeEta - particle.eta(), 2); @@ -1394,8 +2078,8 @@ struct RecoilJets { perpConePt += particle.pt(); } } - spectra.fill(HIST("hScaledFT0C_deltaPtPerpConeAvoidLeadJet"), scaledFT0C, perpConePt - areaRC * rho, weight); - spectra.fill(HIST("hScaledFT0M_deltaPtPerpConeAvoidLeadJet"), scaledFT0M, perpConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0C_deltaPtPerpConeAvoidLeadJet_PartLevel"), scaledFT0C, perpConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0M_deltaPtPerpConeAvoidLeadJet_PartLevel"), scaledFT0M, perpConePt - areaRC * rho, weight); } //---------------------------------------------------------- @@ -1423,7 +2107,7 @@ struct RecoilJets { auto objTT = particles.iteratorAt(vCandForTT[randIndexParticle]); // Skip events where TT is not a part of leading or subleading jets (mutlijet event, difficult to place RC and avoid hard jets) - if (IsTrackInJet(jets.iteratorAt(0), objTT) || IsTrackInJet(jets.iteratorAt(1), objTT)) { + if (isTrackInJet(jets.iteratorAt(0), objTT) || isTrackInJet(jets.iteratorAt(1), objTT)) { keepEventWithTT = true; } } @@ -1436,7 +2120,7 @@ struct RecoilJets { break; } - randomConeEta = randGen->Uniform(-trkEtaCut + randomConeR, trkEtaCut - randomConeR); + randomConeEta = randGen->Uniform(-trk.etaCut + bkgd.randomConeR, trk.etaCut - bkgd.randomConeR); randomConePhi = randGen->Uniform(0.0, constants::math::TwoPI); dEtaLeadJet = std::pow(leadJetEta - randomConeEta, 2); @@ -1449,13 +2133,7 @@ struct RecoilJets { if (isTherePlaceForRC) { randomConePt = 0.0; for (const auto& particle : particles) { - auto pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (!pdgParticle) - continue; - - // Need charge and physical primary particles - bool bParticleNeutral = (static_cast(pdgParticle->Charge()) == 0); - if (bParticleNeutral || !particle.isPhysicalPrimary()) + if (skipParticle(particle)) continue; float dEta = std::pow(randomConeEta - particle.eta(), 2); @@ -1466,108 +2144,229 @@ struct RecoilJets { randomConePt += particle.pt(); } } - spectra.fill(HIST("hScaledFT0C_deltaPtRandomConeAvoidLeadAndSubleadJet"), scaledFT0C, randomConePt - areaRC * rho, weight); - spectra.fill(HIST("hScaledFT0M_deltaPtRandomConeAvoidLeadAndSubleadJet"), scaledFT0M, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0C_deltaPtRandomConeAvoidLeadAndSubleadJet_PartLevel"), scaledFT0C, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0M_deltaPtRandomConeAvoidLeadAndSubleadJet_PartLevel"), scaledFT0M, randomConePt - areaRC * rho, weight); if (keepEventWithTT) { - spectra.fill(HIST("hScaledFT0C_deltaPtRandomConeInEventTTSig"), scaledFT0C, randomConePt - areaRC * rho, weight); - spectra.fill(HIST("hScaledFT0M_deltaPtRandomConeInEventTTSig"), scaledFT0M, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0C_deltaPtRandomConeInEventTTSig_PartLevel"), scaledFT0C, randomConePt - areaRC * rho, weight); + spectra.fill(HIST("hScaledFT0M_deltaPtRandomConeInEventTTSig_PartLevel"), scaledFT0M, randomConePt - areaRC * rho, weight); } } } } - //------------------------------------------------------------------------------ - // Process functions - void processData(FilteredColl const& collision, FilteredTracks const& tracks, - FilteredJets const& jets) + //============================================================================= + // Pt and Phi smearing of TT + //============================================================================= + template + void fillTTSmearingPtPhi(JColl const& collision, + JTracks const& tracks, + JParticles const&, + float weight = 1.) { - spectra.fill(HIST("hEventSelectionCount"), 0.5); + const auto ft0Metrics = getFT0Metrics(collision, ft0a.mean, ft0c.mean); + const auto scaledFT0C = ft0Metrics.scaledFT0C; + const auto scaledFT0M = ft0Metrics.scaledFT0M; - if (skipEvent(collision)) + bool bSigEv = false; + auto dice = randGen->Rndm(); + if (dice < tt.fracSig) + bSigEv = true; + + float ptTTMin = 0.0, ptTTMax = 0.0; + if (bSigEv) { + ptTTMin = tt.sigPtRange->at(0); + ptTTMax = tt.sigPtRange->at(1); + } else { + ptTTMin = tt.refPtRange->at(0); + ptTTMax = tt.refPtRange->at(1); + } + + //============================================================================= + // Search for TT + int nCand = 0; + int32_t index = 0; + int32_t chosenTTPos = -1; + + for (const auto& track : tracks) { + if (skipTrack(track)) { + ++index; + continue; + } + + // Search for TT candidate + float trackPt = track.pt(); + if (trackPt > ptTTMin && trackPt < ptTTMax) { + + ++nCand; + // Random selection of TT + if (randGen->Integer(nCand) == 0) { + chosenTTPos = index; + } + } + ++index; + } + + // Skip if no TT + if (chosenTTPos < 0) + return; + + bool bHasAssocMcPart = tracks.iteratorAt(chosenTTPos).has_mcParticle(); + if (!bHasAssocMcPart) + return; + + // No filter on Particles, it can be outside of |eta| acceptance + auto particle = tracks.iteratorAt(chosenTTPos).mcParticle(); + float particleEta = particle.eta(); + bool bPartWithinEta = std::fabs(particleEta) < trk.etaCut; + + if (bSigEv) { + float particlePt = particle.pt(); + bool bPartWithinPtOfTT = (particlePt > ptTTMin) && (particlePt < ptTTMax); + + if (bPartWithinEta && bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 0.5, 0.5); + spectra.fill(HIST("hScaledFT0M_FractionOfPartTTSigSatisfCond"), scaledFT0M, 0.5, 0.5); + } + + if (!bPartWithinEta && bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 1.5, 0.5); + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0M, 1.5, 0.5); + } + + if (bPartWithinEta && !bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 0.5, 1.5); + spectra.fill(HIST("hScaledFT0M_FractionOfPartTTSigSatisfCond"), scaledFT0M, 0.5, 1.5); + } + + if (!bPartWithinEta && !bPartWithinPtOfTT) { + spectra.fill(HIST("hScaledFT0C_FractionOfPartTTSigSatisfCond"), scaledFT0C, 1.5, 1.5); + spectra.fill(HIST("hScaledFT0M_FractionOfPartTTSigSatisfCond"), scaledFT0M, 1.5, 1.5); + } + } + if (!bPartWithinEta) return; - spectra.fill(HIST("hEventSelectionCount"), 1.5); // number of events selected for analysis + //============================================================================= + // Fill histograms + float particlePt = particle.pt(); + float particlePhi = particle.phi(); + + float relPtSmearing = (particlePt - tracks.iteratorAt(chosenTTPos).pt()) / particlePt; + float phiSmearing = particlePhi - tracks.iteratorAt(chosenTTPos).phi(); + float etaSmearing = particleEta - tracks.iteratorAt(chosenTTPos).eta(); + + if (bSigEv) { + spectra.fill(HIST("hScaleMultFT0C_PtSmearingTTSig"), scaledFT0C, relPtSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PtSmearingTTSig"), scaledFT0M, relPtSmearing, particlePt, weight); - fillHistograms(collision, jets, tracks); + spectra.fill(HIST("hScaleMultFT0C_PhiSmearingTTSig"), scaledFT0C, phiSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PhiSmearingTTSig"), scaledFT0M, phiSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_EtaSmearingTTSig"), scaledFT0C, etaSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_EtaSmearingTTSig"), scaledFT0M, etaSmearing, particlePt, weight); + } else { + spectra.fill(HIST("hScaleMultFT0C_PtSmearingTTRef"), scaledFT0C, relPtSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PtSmearingTTRef"), scaledFT0M, relPtSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_PhiSmearingTTRef"), scaledFT0C, phiSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_PhiSmearingTTRef"), scaledFT0M, phiSmearing, particlePt, weight); + + spectra.fill(HIST("hScaleMultFT0C_EtaSmearingTTRef"), scaledFT0C, etaSmearing, particlePt, weight); + spectra.fill(HIST("hScaleMultFT0M_EtaSmearingTTRef"), scaledFT0M, etaSmearing, particlePt, weight); + } } - PROCESS_SWITCH(RecoilJets, processData, "process raw data", true); - void processMCDetLevel(FilteredColl const& collision, - FilteredTracks const& tracks, - FilteredJetsDetLevel const& jets) + //----------------------------------------------------------------------------- + // Block of Process Functions + + //============================================================================= + // Recoil jet analysis + //============================================================================= + void processData(CollRhoDataIt const& collision, + TrackTbl const& tracksPerColl, + JetsDataTbl const& jetsPerColl) { - spectra.fill(HIST("hEventSelectionCount"), 0.5); + spectra.fill(HIST("hEventSelectionCountReco"), 0.5); + if (skipEvent(collision)) return; - spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("hEventSelectionCountReco"), 1.5); // number of events selected for analysis + + fillHistograms(collision, jetsPerColl, tracksPerColl); + } + PROCESS_SWITCH(RecoilJets, processData, "process raw data", true); - if (skipMBGapEvent(collision)) { - spectra.fill(HIST("hEventSelectionCount"), 2.5); + //____________________ + void processMCDetLevel(CollRhoDataIt const& collision, + TrackTbl const& tracksPerColl, + JetsDetTbl const& jetsPerColl) + { + spectra.fill(HIST("hEventSelectionCountReco"), 0.5); + if (skipEvent(collision)) return; - } - spectra.fill(HIST("hEventSelectionCount"), 5.5); // number of events selected for analysis - fillHistograms(collision, jets, tracks); + spectra.fill(HIST("hEventSelectionCountReco"), 1.5); + + spectra.fill(HIST("hEventSelectionCountReco"), 4.5); // number of events selected for analysis + fillHistograms(collision, jetsPerColl, tracksPerColl); } - PROCESS_SWITCH(RecoilJets, processMCDetLevel, "process MC detector level data (no weight)", false); + PROCESS_SWITCH(RecoilJets, processMCDetLevel, "process MC det. level data (no weight; MB events)", false); - void processMCDetLevelWeighted(FilteredCollDetLevelGetWeight const& collision, + //____________________________ + void processMCDetLevelWeighted(CollRhoOutlierDetIt const& collision, aod::JetMcCollisions const&, - FilteredTracks const& tracks, - FilteredJetsDetLevel const& jets) + TrackTbl const& tracksPerColl, + JetsDetTbl const& jetsPerColl) { - spectra.fill(HIST("hEventSelectionCount"), 0.5); + spectra.fill(HIST("hEventSelectionCountReco"), 0.5); if (skipEvent(collision)) return; - spectra.fill(HIST("hEventSelectionCount"), 1.5); - - if (skipMBGapEvent(collision)) { - spectra.fill(HIST("hEventSelectionCount"), 2.5); - return; - } + spectra.fill(HIST("hEventSelectionCountReco"), 1.5); if (collision.isOutlier()) { - spectra.fill(HIST("hEventSelectionCount"), 3.5); + spectra.fill(HIST("hEventSelectionCountReco"), 2.5); return; } if (!collision.has_mcCollision()) { - spectra.fill(HIST("hEventSelectionCount"), 4.5); + spectra.fill(HIST("hEventSelectionCountReco"), 3.5); return; } - spectra.fill(HIST("hEventSelectionCount"), 5.5); // number of events selected for analysis + spectra.fill(HIST("hEventSelectionCountReco"), 4.5); // number of events selected for analysis auto weight = collision.mcCollision().weight(); - fillHistograms(collision, jets, tracks, weight); + fillHistograms(collision, jetsPerColl, tracksPerColl, weight); } - PROCESS_SWITCH(RecoilJets, processMCDetLevelWeighted, "process MC detector level data (weighted)", false); + PROCESS_SWITCH(RecoilJets, processMCDetLevelWeighted, "process MC det. level data (weighted JJ)", false); - void processMCPartLevel(FilteredCollPartLevel const& collision, - FilteredParticles const& particles, - FilteredJetsPartLevel const& jets) + //_____________________ + void processMCPartLevel(CollRhoPartIt const& collision, + PartTbl const& particlesPerColl, + JetsPartTbl const& jetsPerColl) { spectra.fill(HIST("hEventSelectionCountPartLevel"), 0.5); - if (skipMBGapEvent(collision)) { + if (skipMCEvent(collision)) { spectra.fill(HIST("hEventSelectionCountPartLevel"), 1.5); return; } spectra.fill(HIST("hEventSelectionCountPartLevel"), 3.5); // number of events selected for analysis - fillMCPHistograms(collision, jets, particles); + fillHistogramsMCPartLevel(collision, jetsPerColl, particlesPerColl); } - PROCESS_SWITCH(RecoilJets, processMCPartLevel, "process MC particle level data (no weight)", false); + PROCESS_SWITCH(RecoilJets, processMCPartLevel, "process MC part. level data (no weight; MB events)", false); - void processMCPartLevelWeighted(FilteredCollPartLevel const& collision, - FilteredParticles const& particles, - FilteredJetsPartLevel const& jets) + //_____________________________ + void processMCPartLevelWeighted(CollRhoOutlierPartIt const& collision, + PartTbl const& particlesPerColl, + JetsPartTbl const& jetsPerColl) { spectra.fill(HIST("hEventSelectionCountPartLevel"), 0.5); - if (skipMBGapEvent(collision)) { + if (skipMCEvent(collision)) { spectra.fill(HIST("hEventSelectionCountPartLevel"), 1.5); return; } @@ -1581,133 +2380,281 @@ struct RecoilJets { auto weight = collision.weight(); spectra.fill(HIST("ptHat"), collision.ptHard(), weight); - fillMCPHistograms(collision, jets, particles, weight); + fillHistogramsMCPartLevel(collision, jetsPerColl, particlesPerColl, weight); } - PROCESS_SWITCH(RecoilJets, processMCPartLevelWeighted, "process MC particle level data (weighted)", false); + PROCESS_SWITCH(RecoilJets, processMCPartLevelWeighted, "process MC part. level data (weighted JJ)", false); + + //============================================================================= + // Construction of response matrix + //============================================================================= + void processJetsGeoMatching(CollRhoDetIt const& collision, + CollRhoPartTbl const&, + TrackTbl const& tracksPerColl, + MatchedJetsDetToPartTbl const& mcDetJetsPerColl, + MatchedJetsPartToDetTbl const& mcPartJets) + { + // Skip detector level collisions + if (skipEvent(collision) || !collision.has_mcCollision()) + return; - void processJetsMatched(FilteredCollDetLevelGetWeight const& collision, - aod::JetMcCollisions const&, - FilteredTracks const& tracks, - FilteredMatchedJetsDetLevel const& mcdjets, - FilteredMatchedJetsPartLevel const& mcpjets) + auto mcCollisionId = collision.mcCollisionId(); + auto detLevelCollRho = collision.rho(); + + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); + + // Slice for mc part level jets associated to a given mcCollisionId + auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) + + fillMatchedGeoHistograms(mcPartJetsPerMcCollision, mcDetJetsPerColl, tracksPerColl, partLevelCollRho, detLevelCollRho); + } + PROCESS_SWITCH(RecoilJets, processJetsGeoMatching, "process matching of MC jets using Geo criterion (no weight; MB events)", false); + + //___________________________ + void processJetsGeoPtMatching(CollRhoDetIt const& collision, + CollRhoPartTbl const&, + TrackTbl const& tracksPerColl, + MatchedJetsDetToPartTbl const& mcDetJetsPerColl, + MatchedJetsPartToDetTbl const& mcPartJets) { - if (skipEvent(collision) || skipMBGapEvent(collision) || collision.isOutlier()) + // Skip detector level collisions + if (skipEvent(collision) || !collision.has_mcCollision()) return; - auto mcpjetsPerMCCollision = mcpjets.sliceBy(partJetsPerCollision, collision.mcCollisionId()); + auto mcCollisionId = collision.mcCollisionId(); + auto detLevelCollRho = collision.rho(); + + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); - fillMatchedHistograms(tracks, mcpjetsPerMCCollision, mcdjets); + // Slice for mc part level jets associated to a given mcCollisionId + auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) + + fillMatchedGeoPtHistograms(mcPartJetsPerMcCollision, mcDetJetsPerColl, tracksPerColl, partLevelCollRho, detLevelCollRho); } - PROCESS_SWITCH(RecoilJets, processJetsMatched, "process matching of MC jets (no weight)", false); + PROCESS_SWITCH(RecoilJets, processJetsGeoPtMatching, "process matching of MC jets using Geo+Pt criteria (no weight; MB events)", false); + + //_________________________________ + void processJetsGeoMatchingWeighted(CollRhoOutlierDetIt const& collision, + CollRhoOutlierPartTbl const&, + TrackTbl const& tracksPerColl, + MatchedJetsDetToPartTbl const& mcDetJetsPerColl, + MatchedJetsPartToDetTbl const& mcPartJets) + { + // Skip detector level collisions + if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) + return; + + auto mcCollisionId = collision.mcCollisionId(); + auto detLevelCollRho = collision.rho(); - void processJetsMatchedWeighted(FilteredCollDetLevelGetWeight const& collision, - aod::JetMcCollisions const&, - FilteredTracks const& tracks, - FilteredMatchedJetsDetLevel const& mcdjets, - FilteredMatchedJetsPartLevel const& mcpjets) + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); + auto weight = mcColl.weight(); + + // Slice for mc part level jets associated to a given mcCollisionId + auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) + + fillMatchedGeoHistograms(mcPartJetsPerMcCollision, mcDetJetsPerColl, tracksPerColl, partLevelCollRho, detLevelCollRho, weight); + } + PROCESS_SWITCH(RecoilJets, processJetsGeoMatchingWeighted, "process matching of MC jets using Geo criterion (weighted JJ)", false); + + //___________________________________ + void processJetsGeoPtMatchingWeighted(CollRhoOutlierDetIt const& collision, + CollRhoOutlierPartTbl const&, + TrackTbl const& tracksPerColl, + MatchedJetsDetToPartTbl const& mcDetJetsPerColl, + MatchedJetsPartToDetTbl const& mcPartJets) { - if (skipEvent(collision) || skipMBGapEvent(collision) || collision.isOutlier()) + // Skip detector level collisions + if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) return; - auto mcpjetsPerMCCollision = mcpjets.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - auto weight = collision.mcCollision().weight(); + auto mcCollisionId = collision.mcCollisionId(); + auto detLevelCollRho = collision.rho(); - fillMatchedHistograms(tracks, mcpjetsPerMCCollision, mcdjets, weight); + auto mcColl = collision.mcCollision_as(); + auto partLevelCollRho = mcColl.rho(); + auto weight = mcColl.weight(); + + // Slice for mc part level jets associated to a given mcCollisionId + auto mcPartJetsPerMcCollision = mcPartJets.sliceBy(partJetsPerMcCollision, mcCollisionId); // signature: (__column to slice___, __index__) + + fillMatchedGeoPtHistograms(mcPartJetsPerMcCollision, mcDetJetsPerColl, tracksPerColl, partLevelCollRho, detLevelCollRho, weight); } - PROCESS_SWITCH(RecoilJets, processJetsMatchedWeighted, "process matching of MC jets (weighted)", false); + PROCESS_SWITCH(RecoilJets, processJetsGeoPtMatchingWeighted, "process matching of MC jets using Geo+Pt criteria (weighted JJ)", false); - void processMultiplicityOO(FilteredEventMultiplicity const& collision) + //============================================================================= + // Event Activity analysis in OO and pp collisions (raw and MC detector level (no weight; MB events)) + //============================================================================= + void processEventActivity(EvMultZDCDataIt const& collision) { if (skipEvent(collision)) return; - fillMultiplicityHistogramsOO(collision); + fillMultiplicityHistograms(collision); } - PROCESS_SWITCH(RecoilJets, processMultiplicityOO, "process multiplicity for OO collisions and MC detector level (no weight)", false); + PROCESS_SWITCH(RecoilJets, processEventActivity, "process event activity in raw data and MC det. level (no weight; MB events)", false); - void processMultiplicityMCDetLevelWeightedOO(FilteredEventMultiplicityDetLevelGetWeight const& collision) + //_________________________________________ + void processEventActivityMCDetLevelWeighted(EvMultOutlierZDCDetIt const& collision, + aod::JetMcCollisions const&) { if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) return; auto weight = collision.mcCollision().weight(); - fillMultiplicityHistogramsOO(collision, weight); + fillMultiplicityHistograms(collision, weight); } - PROCESS_SWITCH(RecoilJets, processMultiplicityMCDetLevelWeightedOO, "process multiplicity for MC detector level OO collisions (weighted)", false); + PROCESS_SWITCH(RecoilJets, processEventActivityMCDetLevelWeighted, "process event activity in MC det. level events (weighted JJ)", false); - void processMultiplicityPartLevelMC(FilteredEventMultiplicityPartLevel const& collision) + //============================================================================= + // Event Activity analysis in OO and pp collisions at Particle level + //============================================================================= + void processEventActivityMCPartLevel(CollPartIt const& collision) { - if (skipMBGapEvent(collision)) + if (skipMCEvent(collision)) return; - fillMultiplicityHistogramsPartLevelMC(collision); + fillMultiplicityHistogramsMCPartLevel(collision); } - PROCESS_SWITCH(RecoilJets, processMultiplicityPartLevelMC, "process multiplicity for MC particle level events (no weight)", false); + PROCESS_SWITCH(RecoilJets, processEventActivityMCPartLevel, "process event activity in MC part. level events (no weight; MB events)", false); - void processMultiplicityPartLevelMCWeighted(FilteredEventMultiplicityPartLevel const& collision) + //__________________________________________ + void processEventActivityMCPartLevelWeighted(EvMultOutlierPartIt const& collision) { - if (skipMBGapEvent(collision) || collision.isOutlier()) + if (skipMCEvent(collision) || collision.isOutlier()) return; auto weight = collision.weight(); - fillMultiplicityHistogramsPartLevelMC(collision, weight); + fillMultiplicityHistogramsMCPartLevel(collision, weight); } - PROCESS_SWITCH(RecoilJets, processMultiplicityPartLevelMCWeighted, "process multiplicity for MC particle level events (weighted)", false); - - void processMultiplicityQA(ColEvSelEA const& collision, - BCsRun3 const& BCs, - aod::Zdcs const& ZDCs) + PROCESS_SWITCH(RecoilJets, processEventActivityMCPartLevelWeighted, "process event activity in MC part. level events (weighted JJ)", false); + + //============================================================================= + // Event Activity QA analysis in raw OO + //============================================================================= + void processEventActivitySelectionQA(CollEvSelExtendedIt const& collision, + BCsRun3Tbl const& BCs, + aod::Zdcs const& ZDCs) { // Base flag for event selection if (!collision.sel8()) return; - fillMultiplicityQA(collision, BCs, ZDCs); + fillEventActivitySelectionQAHistograms(collision, BCs, ZDCs); } - PROCESS_SWITCH(RecoilJets, processMultiplicityQA, "process function for EA QA purposes", false); + PROCESS_SWITCH(RecoilJets, processEventActivitySelectionQA, "process function for EA QA purposes in raw OO collisions", false); - void processLeadingAndAssociatedTracksTask(soa::Filtered::iterator const& collision, - soa::Filtered const& tracks) + //============================================================================= + // Di-hadron azimuthal correlation in raw and MC det. level (no weight; MB events) data + //============================================================================= + void processLeadingAndAssociatedTracksTask(CollDataIt const& collision, + TrackTbl const& tracksPerColl) + { + if (skipEvent(collision)) + return; + fillLeadingAndAssociatedTracksTask(collision, tracksPerColl); + } + PROCESS_SWITCH(RecoilJets, processLeadingAndAssociatedTracksTask, "process di-hadron azimuthal correlation in raw and MC det. level (no weight; MB events) data", false); + + //============================================================================= + // Estimation of bkgd fluctuations + //============================================================================= + void processBkgdFluctuations(CollRhoDataIt const& collision, + TrackTbl const& tracksPerColl, + JetsDataTbl const& jetsPerColl) { if (skipEvent(collision)) return; - fillLeadingAndAssociatedTracksTask(collision, tracks); + + fillBkgdFluctuations(collision, jetsPerColl, tracksPerColl); } - PROCESS_SWITCH(RecoilJets, processLeadingAndAssociatedTracksTask, "process function for correlation between leading and associated tracks", false); + PROCESS_SWITCH(RecoilJets, processBkgdFluctuations, "process raw data to estimate bkgd fluctuations", false); - void processBkgdFluctuationsRC(FilteredColl const& collision, - FilteredTracks const& tracks, - FilteredJets const& jets) + //____________________________________ + void processBkgdFluctuationsMCDetLevel(CollRhoDataIt const& collision, + TrackTbl const& tracksPerColl, + JetsDetTbl const& jetsPerColl) { if (skipEvent(collision)) return; - fillBkgdFluctuationsRC(collision, jets, tracks); + fillBkgdFluctuations(collision, jetsPerColl, tracksPerColl); + } + PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsMCDetLevel, "process MC det. level (no weight; MB events) data to estimate bkgd fluctuations", false); + + //____________________________________________ + void processBkgdFluctuationsMCDetLevelWeighted(CollRhoOutlierDetIt const& collision, + aod::JetMcCollisions const&, + TrackTbl const& tracksPerColl, + JetsDetTbl const& jetsPerColl) + { + if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) + return; + + auto weight = collision.mcCollision().weight(); + fillBkgdFluctuations(collision, jetsPerColl, tracksPerColl, weight); } - PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsRC, "process data to estimate bkgd fluctuations using random cone (RC)", false); + PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsMCDetLevelWeighted, "process MC det. level (weighted JJ) data to estimate bkgd fluctuations", false); - void processBkgdFluctuationsRCMCP(FilteredCollPartLevel const& collision, - FilteredParticles const& particles, - FilteredJetsPartLevel const& jets) + //_____________________________________ + void processBkgdFluctuationsMCPartLevel(CollRhoPartIt const& collision, + PartTbl const& particlesPerColl, + JetsPartTbl const& jetsPerColl) { - if (skipMBGapEvent(collision)) + if (skipMCEvent(collision)) return; - fillBkgdFluctuationsRCMCP(collision, jets, particles); + fillBkgdFluctuationsMCPartLevel(collision, jetsPerColl, particlesPerColl); } - PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsRCMCP, "process data to estimate bkgd fluctuations using random cone (RC) in MC Particle Level", false); + PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsMCPartLevel, "process MC part. level (no weight; MB events) data to estimate bkgd fluctuations", false); - void processBkgdFluctuationsRCMCPWeighted(FilteredCollPartLevel const& collision, - FilteredParticles const& particles, - FilteredJetsPartLevel const& jets) + //_____________________________________________ + void processBkgdFluctuationsMCPartLevelWeighted(CollRhoOutlierPartIt const& collision, + PartTbl const& particlesPerColl, + JetsPartTbl const& jetsPerColl) { - if (skipMBGapEvent(collision) || collision.isOutlier()) + if (skipMCEvent(collision) || collision.isOutlier()) return; auto weight = collision.weight(); - fillBkgdFluctuationsRCMCP(collision, jets, particles, weight); + fillBkgdFluctuationsMCPartLevel(collision, jetsPerColl, particlesPerColl, weight); + } + PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsMCPartLevelWeighted, "process MC part. level (weighted JJ) data to estimate bkgd fluctuations", false); + + //============================================================================= + // Pt and Phi smearing of TT + //============================================================================= + void processTTSmearingPtPhi(CollDetIt const& collision, + aod::JetMcCollisions const&, + TrackMCLbsTbl const& tracksPerColl, + aod::JetParticles const& particles) + { + + // Skip detector level collisions + if (skipEvent(collision) || !collision.has_mcCollision()) + return; + + fillTTSmearingPtPhi(collision, tracksPerColl, particles); } - PROCESS_SWITCH(RecoilJets, processBkgdFluctuationsRCMCPWeighted, "process data to estimate bkgd fluctuations using random cone (RC) in MC Particle Level weighted", false); + PROCESS_SWITCH(RecoilJets, processTTSmearingPtPhi, "process MC data (no weight; MB events) to estimate pT and phi smearing of TT", false); + + //_________________________________ + void processTTSmearingPtPhiWeighted(CollOutlierDetIt const& collision, + aod::JetMcCollisions const&, + TrackMCLbsTbl const& tracksPerColl, + aod::JetParticles const& particles) + { + + // Skip detector level collisions + if (skipEvent(collision) || collision.isOutlier() || !collision.has_mcCollision()) + return; + + auto weight = collision.mcCollision().weight(); + fillTTSmearingPtPhi(collision, tracksPerColl, particles, weight); + } + PROCESS_SWITCH(RecoilJets, processTTSmearingPtPhiWeighted, "process MC data (weighted JJ) to estimate pT and phi smearing of TT", false); //------------------------------------------------------------------------------ // Auxiliary functions @@ -1715,13 +2662,13 @@ struct RecoilJets { bool skipEvent(const Collision& coll) { /// \brief: trigger cut is needed for pp data - return !jetderiveddatautilities::selectCollision(coll, eventSelectionBits) || !jetderiveddatautilities::selectTrigger(coll, triggerMaskBits); + return !jetderiveddatautilities::selectCollision(coll, eventSelectionBits, ev.skipMBGapEvents, rct.enable, rct.label, rct.rejectLimitedAcceptance, rct.requireZDC) || !jetderiveddatautilities::selectTrigger(coll, triggerMaskBits); } template - bool skipMBGapEvent(const Collision& coll) + bool skipMCEvent(const Collision& coll) { - return skipMBGapEvents && coll.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap; + return !jetderiveddatautilities::selectCollision(coll, eventSelectionBits, ev.skipMBGapEvents, rct.enable, rct.label, rct.rejectLimitedAcceptance, rct.requireZDC); } template @@ -1730,11 +2677,22 @@ struct RecoilJets { return !jetderiveddatautilities::selectTrack(track, trackSelection); } + template + bool skipParticle(const Particle& particle) + { + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (!pdgParticle) { + return true; + } + const bool bParticleNeutral = (static_cast(pdgParticle->Charge()) == 0); + return bParticleNeutral || !particle.isPhysicalPrimary(); + } + template std::tuple isRecoilJet(const Jet& jet, double phiTT) { double dphi = std::fabs(RecoDecay::constrainAngle(jet.phi() - phiTT, -constants::math::PI)); - return {dphi, (constants::math::PI - recoilRegion) < dphi}; + return {dphi, (constants::math::PI - tt.recoilRegion) < dphi}; } double getPhiTT(const std::vector& vPhiOfTT) @@ -1743,8 +2701,34 @@ struct RecoilJets { return vPhiOfTT[iTrig]; } + FT0Metrics makeFT0Metrics(float multFT0A, + float multFT0C, + float meanFT0A, + float meanFT0C) + { + FT0Metrics values; + values.multFT0A = multFT0A; + values.multFT0C = multFT0C; + values.multFT0M = multFT0A + multFT0C; + values.scaledFT0A = getScaledFT0(values.multFT0A, meanFT0A); + values.scaledFT0C = getScaledFT0(values.multFT0C, meanFT0C); + values.scaledFT0M = getScaledFT0M(values.scaledFT0A, values.scaledFT0C); + return values; + } + + template + FT0Metrics getFT0Metrics(const Collision& collision, + float meanFT0A, + float meanFT0C) + { + return makeFT0Metrics(collision.multFT0A(), collision.multFT0C(), meanFT0A, meanFT0C); + } + float getScaledFT0(const float& multFT0, const float& meanFT0) { + if (meanFT0 == 0.f) { + LOGF(fatal, "FT0 mean is 0. This would cause division by zero. Use a non-zero mean (or keep -1 when scaling is not required)."); + } return multFT0 / meanFT0; } @@ -1753,12 +2737,12 @@ struct RecoilJets { return 0.5 * (scaledMultFT0A + scaledMultFT0C); } - template - bool isJetWithHighPtConstituent(Jet const& jet, Tracks const&) + template + bool isJetWithHighPtConstituent(Jet const& chJet) { bool bIsJetWithHighPtConstituent = false; - for (const auto& jetConstituent : jet.template tracks_as()) { - if (jetConstituent.pt() > maxJetConstituentPt) { + for (const auto& chJetConstituent : chJet.template tracks_as()) { + if (chJetConstituent.pt() > jet.constituentPtMax) { bIsJetWithHighPtConstituent = true; break; } @@ -1767,7 +2751,7 @@ struct RecoilJets { } template - bool IsTrackInJet(Jet const& jet, Track const& track) + bool isTrackInJet(Jet const& jet, Track const& track) { for (auto const& constituentId : jet.tracksIds()) { if (constituentId == track.globalIndex()) { @@ -1778,7 +2762,7 @@ struct RecoilJets { } template - int getBinNumberOnYaxisForGivenRun(std::shared_ptr histogram, int runNumber) + int getBinNumberOnYaxisForGivenRun(const std::shared_ptr& histogram, int runNumber) { int nBins = histogram->GetYaxis()->GetNbins(); int binNumber = -1; @@ -1797,61 +2781,65 @@ struct RecoilJets { return binNumber; } - template - void dataForUnfolding(PartJet const& partJet, DetJet const& detJets, - bool bIsBaseJetRecoil, TracksTable const& tracks, float weight = 1.) + template + std::vector getPhiOfAllTTsigCandidates(JTracksTable const& tracks) { + std::vector vPhiOfTT; - float partJetPt = partJet.pt(); - bool bIsThereMatchedJet = partJet.has_matchedJetGeo(); - - if (bIsThereMatchedJet) { - const auto& jetsMatched = partJet.template matchedJetGeo_as>(); + for (const auto& track : tracks) { + if (skipTrack(track)) + continue; - for (const auto& jetMatched : jetsMatched) { + // Search for TT_Sig candidate + const auto ptTTsigMin = tt.sigPtRange->at(0); + const auto ptTTsigMax = tt.sigPtRange->at(1); + if (track.pt() > ptTTsigMin && track.pt() < ptTTsigMax) { + vPhiOfTT.emplace_back(track.phi()); + } + } + return vPhiOfTT; + } - // skip matches where detector level jets have a constituent with pT above specified cut - bool skipMatchedDetJet = isJetWithHighPtConstituent(jetMatched, tracks); + template + void setBinLabelsYZAxes(const std::shared_ptr& histPointer, + const std::vector& yAxis, + const std::vector& zAxis) + { + const int nRunsOO = yAxis.size(); + const int nEvSelFlags = zAxis.size(); + for (int iRun = 0; iRun < nRunsOO; ++iRun) { + histPointer->GetYaxis()->SetBinLabel(iRun + 1, yAxis[iRun]); + } - if (skipMatchedDetJet) { - // Miss jets - spectra.fill(HIST("hMissedJets_pT"), partJetPt, weight); - if (bIsBaseJetRecoil) - spectra.fill(HIST("hMissedJets_pT_RecoilJets"), partJetPt, weight); - } else { - float detJetPt = jetMatched.pt(); + const int dimOf2DHist = 2; + bool isHist2D = histPointer->GetDimension() == dimOf2DHist; + if (isHist2D) + return; - spectra.fill(HIST("hNumberMatchedJetsPerOneBaseJet"), jetsMatched.size(), detJetPt, weight); - spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel"), detJetPt, partJetPt, weight); - spectra.fill(HIST("hJetPt_resolution"), (partJetPt - detJetPt) / partJetPt, partJetPt, weight); - spectra.fill(HIST("hJetPhi_resolution"), partJet.phi() - jetMatched.phi(), partJetPt, weight); + for (int iFlag = 0; iFlag < nEvSelFlags; ++iFlag) { + histPointer->GetZaxis()->SetBinLabel(iFlag + 1, zAxis[iFlag]); + } + } - if (bIsBaseJetRecoil) { - spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel_RecoilJets"), detJetPt, partJetPt, weight); - spectra.fill(HIST("hJetPt_resolution_RecoilJets"), (partJetPt - detJetPt) / partJetPt, partJetPt, weight); - spectra.fill(HIST("hJetPhi_resolution_RecoilJets"), partJet.phi() - jetMatched.phi(), partJetPt, weight); - } - } + template + std::unordered_set intersectMatchIds(MassiveA const& geoIds, MassiveB const& ptIds) + { + std::unordered_set geoSet; + geoSet.reserve(geoIds.size()); + for (const auto& id : geoIds) { + if (id >= 0) { + geoSet.insert(id); } - } else { - // Miss jets - spectra.fill(HIST("hMissedJets_pT"), partJetPt, weight); - if (bIsBaseJetRecoil) - spectra.fill(HIST("hMissedJets_pT_RecoilJets"), partJetPt, weight); } - // Fake jets - for (const auto& detJet : detJets) { - if (isJetWithHighPtConstituent(detJet, tracks)) - continue; - - bIsThereMatchedJet = detJet.has_matchedJetGeo(); - if (!bIsThereMatchedJet) { - spectra.fill(HIST("hFakeJets_pT"), detJet.pt(), weight); - if (bIsBaseJetRecoil) - spectra.fill(HIST("hFakeJets_pT_RecoilJets"), detJet.pt(), weight); + std::unordered_set bothSet; + bothSet.reserve(std::min(geoIds.size(), ptIds.size())); + for (const auto& id : ptIds) { + if (id >= 0 && geoSet.contains(id)) { + bothSet.insert(id); } } + return bothSet; } }; diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index ebf50c2ad9d..b7d6fce2dff 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -15,45 +15,35 @@ /// /// \author Adrian Fereydon Nassirpour -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.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/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include +#include #include #include +#include #include #include - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -96,6 +86,7 @@ struct statPromptPhoton { Configurable cfgTrackFilter{"cfgTrackFilter", "globalTracks", "set track selections"}; Configurable cfgJETracks{"cfgJETracks", false, "Enables running on derived JE data"}; Configurable cfgGenHistograms{"cfgGenHistograms", false, "Enables Generated histograms"}; + Configurable cfgGenReqRec{"cfgGenReqRec", false, "Only consider generated events which are successfully reconstructed"}; Configurable cfgRecHistograms{"cfgRecHistograms", false, "Enables Reconstructed histograms"}; Configurable cfgDataHistograms{"cfgDataHistograms", false, "Enables Data histograms"}; Configurable cfgTriggerMasks{"cfgTriggerMasks", "", "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"}; @@ -191,9 +182,52 @@ struct statPromptPhoton { 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("REC_prompt_phiQA", "REC_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_prompt_etaQA", "REC_prompt_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_prompt_ptQA", "REC_prompt_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_decay_phiQA", "REC_decay_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_decay_etaQA", "REC_decay_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_decay_ptQA", "REC_decay_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_frag_phiQA", "REC_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_frag_etaQA", "REC_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_frag_ptQA", "REC_frag_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_direct_phiQA", "REC_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_direct_etaQA", "REC_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_direct_ptQA", "REC_direct_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_phiQA", "REC_cluster_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_etaQA", "REC_cluster_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_energyQA", "REC_cluster_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_clusteriso_phiQA", "REC_clusteriso_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_clusteriso_etaQA", "REC_clusteriso_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_clusteriso_energyQA", "REC_clusteriso_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_track_phiQA", "REC_track_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_track_etaQA", "REC_track_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_track_ptQA", "REC_track_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_direct_phiQA", "REC_cluster_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_direct_etaQA", "REC_cluster_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_direct_energyQA", "REC_cluster_direct_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_frag_phiQA", "REC_cluster_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_frag_etaQA", "REC_cluster_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_frag_energyQA", "REC_cluster_frag_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_both_phiQA", "REC_cluster_both_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_both_etaQA", "REC_cluster_both_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_both_energyQA", "REC_cluster_both_energyQA", kTH1F, {{82, -1.0, 40.0}}); } if (cfgGenHistograms) { + histos.add("GEN_prompt_phiQA", "GEN_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_prompt_etaQA", "GEN_prompt_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_prompt_ptQA", "GEN_prompt_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_decay_phiQA", "GEN_decay_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_decay_etaQA", "GEN_decay_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_decay_ptQA", "GEN_decay_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_frag_phiQA", "GEN_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_frag_etaQA", "GEN_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_frag_ptQA", "GEN_frag_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_direct_phiQA", "GEN_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_direct_etaQA", "GEN_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_direct_ptQA", "GEN_direct_ptQA", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_nEvents", "GEN_nEvents", kTH1F, {{4, 0.0, 4.0}}); + histos.add("GEN_nEvents_simple", "GEN_nEvents", kTH1F, {{4, 0.0, 4.0}}); histos.add("GEN_True_Trigger_Energy", "GEN_True_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_Particle_Pt", "GEN_Particle_Pt", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_True_Photon_Energy", "GEN_True_Photon_Energy", kTH1F, {{8200, -1.0, 40.0}}); @@ -252,9 +286,9 @@ struct statPromptPhoton { using jMCClusters = o2::soa::Join; using jClusters = o2::soa::Join; - using jselectedCollisions = soa::Join; - using jselectedDataCollisions = soa::Join; - // using jselectedDataCollisions = soa::Join; + using jselectedCollisions = soa::Join; + using jselectedDataCollisions = soa::Join; + // using jselectedDataCollisions = soa::Join; using jfilteredCollisions = soa::Filtered; using jfilteredDataCollisions = soa::Filtered; using jfilteredMCClusters = soa::Filtered; @@ -420,6 +454,71 @@ struct statPromptPhoton { }; // end of track selection ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// + // Below is shamelessly stolen from Florian's gammetreeproducer code. + template + T iTopCopy(const T& particle) const + { + int iUp = particle.globalIndex(); + T currentParticle = particle; + int pdgCode = particle.pdgCode(); + auto mothers = particle.template mothers_as(); + while (iUp > 0 && mothers.size() == 1 && mothers[0].globalIndex() > 0 && mothers[0].pdgCode() == pdgCode) { + iUp = mothers[0].globalIndex(); + currentParticle = mothers[0]; + mothers = currentParticle.template mothers_as(); + } + return currentParticle; + } + + /// \brief Checks if a particle is a prompt photon + /// \param particle The MC particle to check + /// \return true if particle is a prompt photon, false otherwise + bool isPromptPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + return true; + } + return false; + } + /// \brief Checks if a particle is a direct prompt photon + /// \param particle The particle to check + /// \return true if particle is a direct prompt photon, false otherwise + bool isDirectPromptPhoton(const auto& particle) + { + // check if particle isa prompt photon + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) < 40) { // < 40 is particle directly produced in hard scattering + return true; + } + } + return false; + } + /// \brief Checks if a particle is a fragmentation photon + /// \param particle The particle to check + /// \return true if particle is a fragmentation photon, false otherwise + bool isFragmentationPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) >= 40) { // frag photon + return true; + } + } + return false; + } + /// \brief Checks if a particle is a decay photon + /// \param particle The particle to check + /// \return true if particle is a decay photon, false otherwise + bool isDecayPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + return true; + } + return false; + } ///////////////////////////////////////////////////////////////////////////// // PROCESS @@ -1364,6 +1463,362 @@ struct statPromptPhoton { PROCESS_SWITCH(statPromptPhoton, processData, "processJE data", false); + int nEventsGenMC_Simple = 0; + void processMCGen_simple(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::JMcParticles const& mcParticles, jfilteredMCClusters const&) + { + nEventsGenMC_Simple++; + if (cfgDebug) { + if ((nEventsGenMC_Simple + 1) % 10000 == 0) { + std::cout << "Processed Gen MC Events: " << nEventsGenMC_Simple << std::endl; + } + } + histos.fill(HIST("GEN_nEvents_simple"), 0.5); + if (fabs(collision.posZ()) > cfgVtxCut) + return; + + if (cfgGenReqRec) { + if (recocolls.size() <= 0) // not reconstructed + return; + for (auto& recocoll : recocolls) { // poorly reconstructed + if (!recocoll.sel8()) + return; + if (fabs(recocoll.posZ()) > cfgVtxCut) + + return; + histos.fill(HIST("GEN_nEvents_simple"), 1.5); + + if (cfgEmcTrigger) { + if (!recocoll.isEmcalReadout()) + return; + } + histos.fill(HIST("GEN_nEvents_simple"), 2.5); + } + } + + // First pass: find all status -23 particles + for (auto& hardParticle : mcParticles) { + if (hardParticle.getGenStatusCode() != -23) + continue; + + bool isPhoton23 = (hardParticle.pdgCode() == 22); + + // For prompt: find the final-state photon descending from this -23 photon// + // For frag: find any final-state photon descending from this -23 non-photon// + // We search all final-state photons and check if they trace back here// + + for (auto& mcParticle : mcParticles) { + if (mcParticle.pdgCode() != 22) + continue; + if (mcParticle.getGenStatusCode() < 0) + continue; + if (std::fabs(mcParticle.getGenStatusCode()) >= 81 || !mcParticle.isPhysicalPrimary()) + continue; + + // Chase this final-state photon upward + int chaseindex = -1; + for (auto& mom : mcParticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) + continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool reachedThisHard = false; + bool cleanPhotonChain = true; // all intermediates are photons + + while (chase) { + if (visited.count(chaseindex)) { + chase = false; + break; + } + visited.insert(chaseindex); + + for (auto& particle : mcParticles) { + if (particle.globalIndex() != chaseindex) + continue; + + if (particle.globalIndex() == hardParticle.globalIndex()) { + reachedThisHard = true; + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) + hadronInChain = true; + if (abspdg != 22) + cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { + chase = false; + } else { + chaseindex = nextindex; + } + break; + } + } + + if (!reachedThisHard) + continue; + + if (isPhoton23 && cleanPhotonChain) { + // Case 1: -23 photon, clean photon chain — direct prompt + histos.fill(HIST("GEN_direct_phiQA"), mcParticle.phi()); + histos.fill(HIST("GEN_direct_etaQA"), mcParticle.eta()); + histos.fill(HIST("GEN_direct_ptQA"), mcParticle.pt()); + } else if (!isPhoton23 && !hadronInChain) { + // Case 2: -23 non-photon, no hadrons — fragmentation + histos.fill(HIST("GEN_frag_phiQA"), mcParticle.phi()); + histos.fill(HIST("GEN_frag_etaQA"), mcParticle.eta()); + histos.fill(HIST("GEN_frag_ptQA"), mcParticle.pt()); + } + } // final-state photon loop + } // hard particle loop + } + PROCESS_SWITCH(statPromptPhoton, processMCGen_simple, "processMC_QA_Gen", false); + int nEventsRecMC_simple = 0; + void processMCRec_simple(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const&, soa::Join const&, TrackCandidates const&, aod::JMcParticles const& mcparticles, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) + { + nEventsRecMC_simple++; + if (cfgDebug) { + if ((nEventsRecMC_simple + 1) % 10000 == 0) { + std::cout << "Processed JE Rec MC Events: " << nEventsRecMC_simple << std::endl; + } + } + histos.fill(HIST("REC_nEvents"), 0.5); + if (fabs(collision.posZ()) > cfgVtxCut) + return; + if (!collision.sel8()) + return; + histos.fill(HIST("REC_nEvents"), 1.5); + if (cfgEmcTrigger) { + if (!collision.isEmcalReadout()) + return; + } + histos.fill(HIST("REC_nEvents"), 2.5); + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) + return; + + for (auto& mccluster : mcclusters) { + histos.fill(HIST("REC_M02_BC"), mccluster.m02()); + if (mccluster.m02() < cfgLowM02) + continue; + if (mccluster.m02() > cfgHighM02) + continue; + if (mccluster.energy() < cfgLowClusterE) + continue; + if (mccluster.energy() > cfgHighClusterE) + continue; + if (fabs(mccluster.eta()) > cfgtrkMaxEta) + continue; + int ClusterHasDirectPhoton = 0; + int ClusterHasFragPhoton = 0; + auto ClusterParticles = mccluster.mcParticles_as(); + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() != 22 && std::fabs(clusterparticle.pdgCode()) != 13) + continue; + if (clusterparticle.getGenStatusCode() < 0) + continue; + if (std::fabs(clusterparticle.getGenStatusCode()) >= 81) + continue; + + int chaseindex = -1; + for (auto& mom : clusterparticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) + continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool cleanPhotonChain = true; + bool adrianprompt = false; + bool adrianfrag = false; + + while (chase) { + if (visited.count(chaseindex)) { + chase = false; + break; + } + visited.insert(chaseindex); + + for (auto& particle : mcparticles) { + if (particle.globalIndex() != chaseindex) + continue; + + if (particle.getGenStatusCode() == -23) { + if (particle.pdgCode() == 22 && cleanPhotonChain) { + adrianprompt = true; + } else if (particle.pdgCode() != 22 && !hadronInChain) { + adrianfrag = true; + } + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) + hadronInChain = true; + if (abspdg != 22) + cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { + chase = false; + } else { + chaseindex = nextindex; + } + break; + } + } // chase + + if (adrianprompt) { + ClusterHasDirectPhoton++; + histos.fill(HIST("REC_direct_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_direct_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_direct_ptQA"), clusterparticle.pt()); + } + if (adrianfrag) { + ClusterHasFragPhoton++; + histos.fill(HIST("REC_frag_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_frag_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_frag_ptQA"), clusterparticle.pt()); + } + } // clusterparticle loop + + if (ClusterHasFragPhoton > 0) { + histos.fill(HIST("REC_cluster_frag_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_frag_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_frag_energyQA"), mccluster.energy()); + } + if (ClusterHasDirectPhoton > 0) { + histos.fill(HIST("REC_cluster_direct_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_direct_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_direct_energyQA"), mccluster.energy()); + } + if (ClusterHasDirectPhoton > 0 && ClusterHasFragPhoton > 0) { + histos.fill(HIST("REC_cluster_both_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_both_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_both_energyQA"), mccluster.energy()); + } + + // now we do cluster tracks + bool photontrigger = false; // is a neutral cluster + bool chargetrigger = false; // is definitely not a neutral cluster + auto tracksofcluster = mccluster.matchedTracks_as>(); + // first, we check if veto is required + double sumptT = 0; + bool clusterqa = false; + for (auto& ctrack : tracksofcluster) { + double etaT, phiT; + if (cfgJETracks) { + if (!jetderiveddatautilities::selectTrack(ctrack, trackFilter)) { + continue; + } + auto emctracksPerTrack = emctracks.sliceBy(EMCTrackPerTrack, ctrack.globalIndex()); + auto emctrack = emctracksPerTrack.iteratorAt(0); + etaT = emctrack.etaEmcal(); + phiT = emctrack.phiEmcal(); + } else { + auto ogtrack = ctrack.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (!ogtrack.isGlobalTrack()) { + continue; + } + etaT = ogtrack.trackEtaEmcal(); + phiT = ogtrack.trackPhiEmcal(); + } + + double etaC = mccluster.eta(); + double phiC = mccluster.phi(); + double ptT = ctrack.pt(); + bool etatrigger = false; + bool phitrigger = false; + double phidiff = TVector2::Phi_mpi_pi(mccluster.phi() - ctrack.phi()); + double etadiff = mccluster.eta() - ctrack.eta(); + + if (cfgPtClusterCut) { + if (fabs(etaT - etaC) < (0.010 + pow(ptT + 4.07, -2.5))) { + etatrigger = true; + } + + if (fabs(TVector2::Phi_mpi_pi(phiT - phiC)) < (0.015 + pow(ptT + 3.65, -2.0))) { + phitrigger = true; + } + } else { + if (fabs(etadiff) < 0.05) { + etatrigger = true; + } + + if (fabs(phidiff) < 0.05) { + phitrigger = true; + } + } + + if (etatrigger && phitrigger) { + chargetrigger = true; + sumptT += ptT; + } + if (chargetrigger) { + if (!clusterqa) { + histos.fill(HIST("REC_Cluster_QA"), 1.5); + clusterqa = true; + } + } + histos.fill(HIST("REC_Track_v_Cluster_Phi"), phidiff); + histos.fill(HIST("REC_Track_v_Cluster_Eta"), etadiff); + histos.fill(HIST("REC_Track_v_Cluster_Phi_Eta"), phidiff, etadiff); + histos.fill(HIST("REC_track_phiQA"), ctrack.phi()); + histos.fill(HIST("REC_track_etaQA"), ctrack.eta()); + histos.fill(HIST("REC_track_ptQA"), ctrack.pt()); + } // track of cluster loop + + if (chargetrigger && sumptT > 0) { + double mccluster_over_sumptT = mccluster.energy() / sumptT; + histos.fill(HIST("REC_SumPt_BC"), mccluster_over_sumptT); + if (mccluster_over_sumptT < 1.7) { + histos.fill(HIST("REC_Cluster_QA"), 2.5); // veto fails, cluster is charged + } else { + histos.fill(HIST("REC_Cluster_QA"), 3.5); // veto is good, cluster is converted to neutral cluster + // chargetrigger = false; + histos.fill(HIST("REC_SumPt_AC"), mccluster_over_sumptT); + } + } // sumptT check + + if (!chargetrigger) { + photontrigger = true; + } + + if (photontrigger) { + histos.fill(HIST("REC_clusteriso_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_clusteriso_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_clusteriso_energyQA"), mccluster.energy()); + } + if (chargetrigger) { + histos.fill(HIST("REC_cluster_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_energyQA"), mccluster.energy()); + } + } // clusters + } // main function + PROCESS_SWITCH(statPromptPhoton, processMCRec_simple, "processMC_QA_Rce", false); + }; // end of main struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/substructureDebug.cxx b/PWGJE/Tasks/substructureDebug.cxx index c6830c3a038..0243cce3c1a 100644 --- a/PWGJE/Tasks/substructureDebug.cxx +++ b/PWGJE/Tasks/substructureDebug.cxx @@ -14,28 +14,26 @@ /// \author Nima Zardoshti // -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetSubstructure.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 +#include +#include +#include +#include +#include +#include +#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct SubstructureDebugTask { HistogramRegistry registry{"registry", {{"h_collisions_posZ", "event posZ;posZ;entries", {HistType::kTH1F, {{20, -10.0, 10.0}}}}, diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index 7be0b41f6fb..c1da7482405 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -19,16 +19,18 @@ #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include #include +#include #include +#include #include #include #include +#include #include #include @@ -52,6 +54,7 @@ struct TrackEfficiency { Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections; other option: uniformTracks"}; Configurable skipMBGapEvents{"skipMBGapEvents", false, "flag to choose to reject min. bias gap events"}; + Configurable applyRCTSelections{"applyRCTSelections", true, "decide to apply RCT selections"}; // Tracking efficiency process function configurables: Configurable checkPrimaryPart{"checkPrimaryPart", true, "0: doesn't check mcparticle.isPhysicalPrimary() - 1: checks particle.isPhysicalPrimary()"}; @@ -80,18 +83,20 @@ struct TrackEfficiency { Configurable phiEffNBins{"phiEffNBins", 200, "number of bins for phi axis in efficiency plots"}; Configurable etaEffNBins{"etaEffNBins", 200, "number of bins for eta axis in efficiency plots"}; - Configurable ptHatMin{"ptHatMin", 5, "min pT hat of collisions"}; - Configurable ptHatMax{"ptHatMax", 300, "max pT hat of collisions"}; - Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable ptHatMin{"ptHatMin", -999, "min pT hat of collisions"}; + Configurable ptHatMax{"ptHatMax", 999, "max pT hat of collisions"}; + Configurable pTHatExponent{"pTHatExponent", 4.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable simPtRef{"simPtRef", 10.0, "reference pT for the back-calculation of pTHat from the event weight"}; Configurable pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track acceptance in MC"}; + Configurable pTHatMaxFractionMCP{"pTHatMaxFractionMCP", 999.0, "maximum fraction of hard scattering for particle acceptance in MC"}; - Configurable getPtHatFromHepMCXSection{"getPtHatFromHepMCXSection", true, "test configurable, configurable should be removed once well tested"}; Configurable useTrueTrackWeight{"useTrueTrackWeight", true, "test configurable, should be set to 1 then config removed once well tested"}; // systematics variation - Run 2 guidelines: https://twiki.cern.ch/twiki/bin/view/ALICE/AliDPGtoolsTrackSystematicUncertainty TrackSelection customTrackSelection; Configurable useCustomTrackSelection{"useCustomTrackSelection", false, "whether to use the custom cuts (used for cut variation for tracking efficiency systematics)"}; Configurable effSystMinNCrossedRowsTPC{"effSystMinNCrossedRowsTPC", 70, "min number of crossed rows TPC"}; + Configurable effSystMinNCrossedRowsTPCUseAlternateCut{"effSystMinNCrossedRowsTPCUseAlternateCut", false, "min number of crossed rows TPC - alternate cut of 120 - 5./pt"}; Configurable effSystMinNCrossedRowsOverFindableClustersTPC{"effSystMinNCrossedRowsOverFindableClustersTPC", 0.8, "min ratio of crossed rows over findable clusters TPC"}; Configurable effSystMaxChi2PerClusterTPC{"effSystMaxChi2PerClusterTPC", 4.0, "max chi2 per cluster TPC"}; Configurable effSystMaxChi2PerClusterITS{"effSystMaxChi2PerClusterITS", 36.0, "max chi2 per cluster ITS"}; @@ -101,7 +106,6 @@ struct TrackEfficiency { std::vector eventSelectionBits; int trackSelection = -1; - float simPtRef = 10.; enum AcceptSplitCollisionsOptions { NonSplitOnly = 0, @@ -118,6 +122,9 @@ struct TrackEfficiency { } } else { const auto& aodTrack = jetTrack.template track_as>(); + if (effSystMinNCrossedRowsTPCUseAlternateCut) { + customTrackSelection.SetMinNCrossedRowsTPC(120 - 5. / jetTrack.pt()); + } if (customTrackSelection.IsSelected(aodTrack)) { return true; } @@ -170,6 +177,10 @@ struct TrackEfficiency { float centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); for (auto const& mcparticle : mcparticles) { + float pTHat = simPtRef / (std::pow(weight, 1.0 / pTHatExponent)); + if (mcparticle.pt() > pTHatMaxFractionMCP * pTHat) { + continue; + } registry.fill(HIST("h2_centrality_particle_pt"), centrality, mcparticle.pt(), weight); registry.fill(HIST("h2_centrality_particle_eta"), centrality, mcparticle.eta(), weight); registry.fill(HIST("h2_centrality_particle_phi"), centrality, mcparticle.phi(), weight); @@ -310,10 +321,10 @@ struct TrackEfficiency { 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("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}}}); + 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, 10.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, 10.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.}, {10000, 0.0, 1.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.}, {10000, 0.0, 1.0}}}); registry.add("h3_intrate_centrality_track_pt", "interaction rate vs centrality vs track pT; int. rate; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH3F, {intRateAxis, centAxis, {200, 0., 200.}}}); } @@ -372,6 +383,18 @@ struct TrackEfficiency { registry.add("h2_trackselplot_pt_dcaxy", "track selection variable: pt vs dca XY", {HistType::kTH2F, {{200, 0., 200.}, {1000, -1.0, 1.0}}}); registry.add("h2_trackselplot_pt_dcaz", "track selection variable: pt vs dca Z", {HistType::kTH2F, {{200, 0., 200.}, {4000, -4.0, 4.0}}}); } + + AxisSpec occupancyAxis = {140, -0.5, 13999.5, "occupancy"}; + AxisSpec nTracksAxis = {16001, -1., 16000, "n tracks"}; + + if (doprocessOccupancyQA) { + registry.add("h2_occupancy_ntracksall_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntracksall_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntrackssel_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntrackssel_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntracksselptetacuts_presel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + registry.add("h2_occupancy_ntracksselptetacuts_postsel", "occupancy vs N_{tracks}; occupancy; N_{tracks}", {HistType::kTH2I, {occupancyAxis, nTracksAxis}}); + } } Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; @@ -382,8 +405,7 @@ struct TrackEfficiency { 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); - void processEFficiencyPurity(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processEFficiencyPurity(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, soa::Join const&, @@ -415,8 +437,8 @@ struct TrackEfficiency { bool hasSel8Coll = false; bool centralityCheck = false; bool occupancyCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -428,7 +450,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC @@ -454,7 +476,7 @@ struct TrackEfficiency { } registry.fill(HIST("hMcCollCutsCounts"), 5.5); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : simPtRef / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -500,7 +522,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } @@ -570,8 +592,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurity, "Histograms for efficiency and purity quantities", true); - void processEFficiencyPurityWeighted(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processEFficiencyPurityWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, soa::Join const&, @@ -602,8 +623,8 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -612,7 +633,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -643,6 +664,9 @@ struct TrackEfficiency { registry.fill(HIST("hMcCollCutsCounts"), 6.5, mcCollision.weight()); // ptHat condition for (auto const& jMcParticle : jMcParticles) { + if (jMcParticle.pt() > pTHatMaxFractionMCP * pTHat) { + continue; + } registry.fill(HIST("hMcPartCutsCounts"), 0.5, mcCollision.weight()); // allPartsInSelMcColl if (!isChargedParticle(jMcParticle.pdgCode())) { @@ -661,7 +685,7 @@ struct TrackEfficiency { registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); - if ((std::abs(jMcParticle.eta()) < trackEtaAcceptanceCountQA)) { // removed from actual cuts for now because all the histograms have an eta axis + if ((std::abs(jMcParticle.eta()) < trackEtaAcceptanceCountQA)) { // removed from actual cuts for now because all the histograms have an eta axis registry.fill(HIST("hMcPartCutsCounts"), 3.5, mcCollision.weight()); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing } } @@ -675,7 +699,7 @@ struct TrackEfficiency { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents) || !(std::abs(collision.posZ()) < vertexZCut)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections) || !(std::abs(collision.posZ()) < vertexZCut)) { continue; } @@ -702,10 +726,13 @@ struct TrackEfficiency { registry.fill(HIST("hTrackCutsCounts"), 3.5, mcCollision.weight()); auto mcParticle = track.mcParticle_as(); - auto trueTrackMcCollision = mcParticle.mcCollision_as>(); + auto trueTrackMcCollision = mcParticle.mcCollision_as(); float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight; auto jMcParticleFromTrack = track.mcParticle_as(); + if (jMcParticleFromTrack.pt() > pTHatMaxFractionMCP * pTHat) { + continue; + } if (!jMcParticleFromTrack.isPhysicalPrimary()) { registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); @@ -758,7 +785,7 @@ struct TrackEfficiency { soa::Filtered> const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -774,15 +801,14 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processTracksFromData, "QA for charged tracks in data", false); void processTracksFromMc(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&, + aod::JetMcCollisions const&, soa::Filtered> const& jetTracks, soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -793,7 +819,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -803,16 +829,15 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processTracksFromMc, "QA for charged tracks in MC without weights", false); void processTracksFromMcWeighted(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&, + aod::JetMcCollisions const&, soa::Filtered> const& jetTracks, soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called return; } - float eventWeight = collision.mcCollision_as>().weight(); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + float eventWeight = collision.mcCollision().weight(); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -823,7 +848,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -832,8 +857,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processTracksFromMcWeighted, "QA for charged tracks in weighted MC", false); - void processParticles(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processParticles(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, soa::Filtered const& mcparticles, soa::Filtered const& tracks) @@ -849,7 +873,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : simPtRef / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -857,8 +881,8 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -867,7 +891,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -891,8 +915,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processParticles, "QA for charged particles", false); - void processParticlesWeighted(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processParticlesWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, soa::Filtered const& mcparticles, soa::Filtered const& tracks) @@ -913,7 +936,7 @@ struct TrackEfficiency { return; } - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -921,8 +944,8 @@ struct TrackEfficiency { float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -931,7 +954,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -962,7 +985,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -981,8 +1004,7 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processCollisionsFromData, "QA for reconstructed collisions in data", false); void processCollisionsFromMc(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&) + aod::JetMcCollisions const&) { float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -992,7 +1014,7 @@ struct TrackEfficiency { } registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1008,7 +1030,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 3.5); registry.fill(HIST("h2_centrality_collisions"), centrality, 3.5); - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -1018,8 +1040,7 @@ struct TrackEfficiency { PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMc, "QA for reconstructed collisions in MC without weights", false); void processCollisionsFromMcWeighted(soa::Filtered>::iterator const& collision, - soa::Join const&, - soa::Join const&) + aod::JetMcCollisions const&) { float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1027,10 +1048,10 @@ struct TrackEfficiency { registry.fill(HIST("h_fakecollisions"), 0.5); return; } - float eventWeight = collision.mcCollision_as>().weight(); + float eventWeight = collision.mcCollision().weight(); registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h_collisions_weighted"), 0.5, eventWeight); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } registry.fill(HIST("h_collisions"), 1.5); @@ -1046,7 +1067,7 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 3.5); registry.fill(HIST("h_collisions_weighted"), 3.5, eventWeight); - float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = collision.mcCollision().ptHard() < 999.0f ? collision.mcCollision().ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -1055,22 +1076,21 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMcWeighted, "QA for reconstructed collisions in weighted MC", false); - void processMcCollisions(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processMcCollisions(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions) { // float centrality = checkCentFT0M ? mcCollision.centFT0M() : mcCollision.centFT0C(); mcCollision.centFT0C() isn't filled at the moment; can be added back when it is float eventWeight = mcCollision.weight(); - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard()); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.ptHard()); float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1079,7 +1099,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1124,8 +1144,7 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processMcCollisions, "QA for McCollisions in MC without weights", false); - void processMcCollisionsWeighted(soa::Join::iterator const& mcCollision, - soa::Join const&, + void processMcCollisionsWeighted(aod::JetMcCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions) { if (skipMBGapEvents && mcCollision.getSubGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { @@ -1135,16 +1154,16 @@ struct TrackEfficiency { // float centrality = checkCentFT0M ? mcCollision.centFT0M() : mcCollision.centFT0C(); mcCollision.centFT0C() isn't filled at the moment; can be added back when it is float eventWeight = mcCollision.weight(); - float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard()); - registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard(), eventWeight); + float pTHat = mcCollision.ptHard() < 999.0f ? mcCollision.ptHard() : simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.ptHard()); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted"), simPtRef / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.ptHard(), eventWeight); float centrality = -1; bool hasSel8Coll = false; bool centralityCheck = false; - if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed - if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) - if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have their first associated collision not reconstructed + if (collisions.size() > 1) { // remove and move the if block below under if (collisions.size() < 1) { when mccoll.centFt0C has been fixed + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have their first associated collision not reconstructed hasSel8Coll = true; } centrality = checkCentFT0M ? collisions.begin().centFT0M() : collisions.begin().centFT0C(); @@ -1153,7 +1172,7 @@ struct TrackEfficiency { } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks for (auto const& collision : collisions) { - if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1205,7 +1224,7 @@ struct TrackEfficiency { void processTrackSelectionHistograms(soa::Filtered::iterator const& collision, soa::Join const& jetTracks, soa::Join const&) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { return; } float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); @@ -1235,6 +1254,38 @@ struct TrackEfficiency { } } PROCESS_SWITCH(TrackEfficiency, processTrackSelectionHistograms, "plots distributions of variables that are cut on during track selection", false); + + void processOccupancyQA(soa::Filtered::iterator const& collision, aod::JetTracks const& tracks) + { + float centrality = checkCentFT0M ? collision.centFT0M() : collision.centFT0C(); + if (cutCentrality && (centrality < centralityMin || centralityMax < centrality)) { + return; + } + + int occupancy = collision.trackOccupancyInTimeRange(); + int nTracksAll = tracks.size(); + int nTracksAllAcceptanceAndSelected = 0; + int nTracksInAcceptanceAndSelected = 0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + nTracksAllAcceptanceAndSelected += 1; + if (track.pt() >= trackQAPtMin && track.pt() < trackQAPtMax && track.eta() > trackQAEtaMin && track.eta() < trackQAEtaMax) { + nTracksInAcceptanceAndSelected += 1; + } + } + } + + registry.fill(HIST("h2_occupancy_ntracksall_presel"), occupancy, nTracksAll); + registry.fill(HIST("h2_occupancy_ntrackssel_presel"), occupancy, nTracksAllAcceptanceAndSelected); + registry.fill(HIST("h2_occupancy_ntracksselptetacuts_presel"), occupancy, nTracksInAcceptanceAndSelected); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents, applyRCTSelections)) { + return; + } + registry.fill(HIST("h2_occupancy_ntracksall_postsel"), occupancy, nTracksAll); + registry.fill(HIST("h2_occupancy_ntrackssel_postsel"), occupancy, nTracksAllAcceptanceAndSelected); + registry.fill(HIST("h2_occupancy_ntracksselptetacuts_postsel"), occupancy, nTracksInAcceptanceAndSelected); + } + PROCESS_SWITCH(TrackEfficiency, processOccupancyQA, "occupancy QA on jet derived data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/trackJetQA.cxx b/PWGJE/Tasks/trackJetQA.cxx index 60c099bf7a3..3b7eafded61 100644 --- a/PWGJE/Tasks/trackJetQA.cxx +++ b/PWGJE/Tasks/trackJetQA.cxx @@ -24,11 +24,11 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/triggerCorrelations.cxx b/PWGJE/Tasks/triggerCorrelations.cxx index c0c272d39c7..2a32add9252 100644 --- a/PWGJE/Tasks/triggerCorrelations.cxx +++ b/PWGJE/Tasks/triggerCorrelations.cxx @@ -16,10 +16,10 @@ #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include +#include #include #include #include diff --git a/PWGJE/Tasks/v0JetSpectra.cxx b/PWGJE/Tasks/v0JetSpectra.cxx index 95081bad725..d17078958f9 100644 --- a/PWGJE/Tasks/v0JetSpectra.cxx +++ b/PWGJE/Tasks/v0JetSpectra.cxx @@ -19,8 +19,8 @@ #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisTask.h" +#include +#include #include #include #include diff --git a/PWGJE/Tasks/v0QA.cxx b/PWGJE/Tasks/v0QA.cxx index 353869e4644..e32d56bc590 100644 --- a/PWGJE/Tasks/v0QA.cxx +++ b/PWGJE/Tasks/v0QA.cxx @@ -24,10 +24,10 @@ #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" #include +#include +#include +#include #include #include #include @@ -35,6 +35,7 @@ #include #include +#include #include #include diff --git a/PWGLF/DataModel/EPCalibrationTables.h b/PWGLF/DataModel/EPCalibrationTables.h index 8954ccd1c9e..4f32d4f91f0 100644 --- a/PWGLF/DataModel/EPCalibrationTables.h +++ b/PWGLF/DataModel/EPCalibrationTables.h @@ -16,13 +16,13 @@ #ifndef PWGLF_DATAMODEL_EPCALIBRATIONTABLES_H_ #define PWGLF_DATAMODEL_EPCALIBRATIONTABLES_H_ -#include - -#include "Common/DataModel/PIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/AnalysisDataModel.h" +#include + namespace o2::aod { namespace epcalibrationtable diff --git a/PWGLF/DataModel/FilterF1ProtonTables.h b/PWGLF/DataModel/FilterF1ProtonTables.h index 0475e7cebb5..ff90b328d9e 100644 --- a/PWGLF/DataModel/FilterF1ProtonTables.h +++ b/PWGLF/DataModel/FilterF1ProtonTables.h @@ -16,13 +16,13 @@ #ifndef PWGLF_DATAMODEL_FILTERF1PROTONTABLES_H_ #define PWGLF_DATAMODEL_FILTERF1PROTONTABLES_H_ -#include - -#include "Common/DataModel/PIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/AnalysisDataModel.h" +#include + namespace o2::aod { namespace filtering diff --git a/PWGLF/DataModel/LFAntinCexTables.h b/PWGLF/DataModel/LFAntinCexTables.h index 9e8f4ce1ca8..0e762f03e17 100644 --- a/PWGLF/DataModel/LFAntinCexTables.h +++ b/PWGLF/DataModel/LFAntinCexTables.h @@ -26,11 +26,12 @@ namespace o2::aod namespace antin_cex { // Metadata -DECLARE_SOA_COLUMN(IsCex, isCex, bool); // 1=CEX (from antin), 0=BG -DECLARE_SOA_COLUMN(MotherPdg, motherPdg, int32_t); // mother PDG -DECLARE_SOA_COLUMN(ColId, colId, int32_t); // mcCollisionId -DECLARE_SOA_COLUMN(PId, pId, int32_t); // proton MC id -DECLARE_SOA_COLUMN(AntipId, antipId, int32_t); // antiproton MC id +DECLARE_SOA_COLUMN(IsCex, isCex, bool); // 1=CEX (from antin), 0=BG +DECLARE_SOA_COLUMN(MotherPdg, motherPdg, int32_t); // mother PDG +DECLARE_SOA_COLUMN(MotherNHitIB, motherNHitIB, int); // mother IB Hits +DECLARE_SOA_COLUMN(ColId, colId, int32_t); // mcCollisionId +DECLARE_SOA_COLUMN(PId, pId, int32_t); // proton MC id +DECLARE_SOA_COLUMN(AntipId, antipId, int32_t); // antiproton MC id // MC (pair) DECLARE_SOA_COLUMN(McPairP, mcPairP, float); @@ -41,6 +42,12 @@ DECLARE_SOA_COLUMN(McAngleDeg, mcAngleDeg, float); DECLARE_SOA_COLUMN(McVtxX, mcVtxX, float); DECLARE_SOA_COLUMN(McVtxY, mcVtxY, float); DECLARE_SOA_COLUMN(McVtxZ, mcVtxZ, float); +DECLARE_SOA_COLUMN(VtxNAll, vtxNAll, int16_t); +DECLARE_SOA_COLUMN(VtxNCh, vtxNCh, int16_t); +DECLARE_SOA_COLUMN(VtxNNeut, vtxNNeut, int16_t); +DECLARE_SOA_COLUMN(VtxNPi0, vtxNPi0, int16_t); +DECLARE_SOA_COLUMN(VtxNGamma, vtxNGamma, int16_t); +DECLARE_SOA_COLUMN(VtxNN, vtxNN, int16_t); // Tracks (pair, fitter) DECLARE_SOA_COLUMN(TrkPairP, trkPairP, float); @@ -85,6 +92,8 @@ DECLARE_SOA_COLUMN(AntipTrkNClsIts, antipTrkNClsIts, int16_t); DECLARE_SOA_COLUMN(SelMask, selMask, uint32_t); DECLARE_SOA_COLUMN(PairPointingAngleDeg, pairPointingAngleDeg, float); +DECLARE_SOA_COLUMN(PvsvThetaDeg, pvsvThetaDeg, float); +DECLARE_SOA_COLUMN(PvsvPhiDeg, pvsvPhiDeg, float); DECLARE_SOA_COLUMN(PairPBalance, pairPBalance, float); DECLARE_SOA_COLUMN(PairPtBalance, pairPtBalance, float); DECLARE_SOA_COLUMN(PairQ, pairQ, float); @@ -118,9 +127,10 @@ DECLARE_SOA_COLUMN(AntipTrkTgl, antipTrkTgl, float); // Table DECLARE_SOA_TABLE(AntinCexPairs, "AOD", "ANTINCEX", antin_cex::IsCex, - antin_cex::MotherPdg, antin_cex::ColId, antin_cex::PId, antin_cex::AntipId, + antin_cex::MotherPdg, antin_cex::MotherNHitIB, antin_cex::ColId, antin_cex::PId, antin_cex::AntipId, antin_cex::McPairP, antin_cex::McPairPt, antin_cex::McPairPz, antin_cex::McDplane, antin_cex::McAngleDeg, antin_cex::McVtxX, antin_cex::McVtxY, antin_cex::McVtxZ, + antin_cex::VtxNAll, antin_cex::VtxNCh, antin_cex::VtxNNeut, antin_cex::VtxNPi0, antin_cex::VtxNGamma, antin_cex::VtxNN, antin_cex::TrkPairP, antin_cex::TrkPairPt, antin_cex::TrkPairPz, antin_cex::TrkAngleDeg, antin_cex::TrkVtxfitDcaPair, antin_cex::TrkVtxfitR, antin_cex::TrkVtxfitDistToPv, antin_cex::TrkVtxfitSecVtxX, antin_cex::TrkVtxfitSecVtxY, antin_cex::TrkVtxfitSecVtxZ, @@ -129,7 +139,7 @@ DECLARE_SOA_TABLE(AntinCexPairs, "AOD", "ANTINCEX", antin_cex::PTrkP, antin_cex::PTrkPx, antin_cex::PTrkPy, antin_cex::PTrkPz, antin_cex::PTrkEta, antin_cex::PTrkTpcSignal, antin_cex::PTrkNClsIts, antin_cex::AntipTrkP, antin_cex::AntipTrkPx, antin_cex::AntipTrkPy, antin_cex::AntipTrkPz, antin_cex::AntipTrkEta, antin_cex::AntipTrkTpcSignal, antin_cex::AntipTrkNClsIts, antin_cex::SelMask, - antin_cex::PairPointingAngleDeg, antin_cex::PairPBalance, antin_cex::PairPtBalance, antin_cex::PairQ, + antin_cex::PairPointingAngleDeg, antin_cex::PvsvThetaDeg, antin_cex::PvsvPhiDeg, antin_cex::PairPBalance, antin_cex::PairPtBalance, antin_cex::PairQ, antin_cex::DPairP, antin_cex::DPairPt, antin_cex::DPairPz, antin_cex::DOpenAngle, antin_cex::SVNearestLayerId, antin_cex::SVDeltaRToLayer, antin_cex::PTrkItsHitMap, antin_cex::APTrkItsHitMap, antin_cex::PLayersOk, antin_cex::APLayersOk, diff --git a/PWGLF/DataModel/LFCKSSpinalignmentTables.h b/PWGLF/DataModel/LFCKSSpinalignmentTables.h index 6593d22fe6b..02296578a49 100644 --- a/PWGLF/DataModel/LFCKSSpinalignmentTables.h +++ b/PWGLF/DataModel/LFCKSSpinalignmentTables.h @@ -20,13 +20,13 @@ #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include +#include namespace o2::aod { @@ -34,7 +34,7 @@ namespace kshortpionevent { DECLARE_SOA_COLUMN(Cent, cent, float); DECLARE_SOA_COLUMN(Posz, posz, float); -DECLARE_SOA_COLUMN(CollIndex, collIndex, float); +// DECLARE_SOA_COLUMN(CollIndex, collIndex, float); DECLARE_SOA_COLUMN(PsiFT0C, psiFT0C, float); DECLARE_SOA_COLUMN(PsiFT0A, psiFT0A, float); DECLARE_SOA_COLUMN(PsiTPC, psiTPC, float); @@ -43,7 +43,7 @@ DECLARE_SOA_TABLE(KShortpionEvents, "AOD", "KSHORTPIONEVENT", o2::soa::Index<>, kshortpionevent::Cent, kshortpionevent::Posz, - kshortpionevent::CollIndex, + // kshortpionevent::CollIndex, kshortpionevent::PsiFT0C, kshortpionevent::PsiFT0A, kshortpionevent::PsiTPC) @@ -65,12 +65,13 @@ DECLARE_SOA_COLUMN(KShortMass, kShortMass, float); //! KShort Ma DECLARE_SOA_COLUMN(PionBachPx, pionBachPx, float); //! Bachelor Pion Px DECLARE_SOA_COLUMN(PionBachPy, pionBachPy, float); //! Bachelor Pion Py DECLARE_SOA_COLUMN(PionBachPz, pionBachPz, float); //! Bachelor Pion Pz -DECLARE_SOA_COLUMN(PionBachTPC, pionBachTPC, float); //! Bachelor Pion nsigmatpc +/*DECLARE_SOA_COLUMN(PionBachTPC, pionBachTPC, float); //! Bachelor Pion nsigmatpc DECLARE_SOA_COLUMN(PionBachTOFHit, pionBachTOFHit, int); //! Bachelor Pion tof hit availability -DECLARE_SOA_COLUMN(PionBachTOF, pionBachTOF, float); //! Bachelor Pion nsigmatof -DECLARE_SOA_COLUMN(PionBachIndex, pionBachIndex, int); //! Bachelor Pion index -DECLARE_SOA_COLUMN(PionIndex1, pionIndex1, int); //! Daughter Pion index1 -DECLARE_SOA_COLUMN(PionIndex2, pionIndex2, int); //! Daughter Pion index2 +DECLARE_SOA_COLUMN(PionBachTOF, pionBachTOF, float); //! Bachelor Pion nsigmatof*/ +DECLARE_SOA_COLUMN(PionBachIndex, pionBachIndex, int); //! Bachelor Pion index +DECLARE_SOA_COLUMN(PionIndex1, pionIndex1, int); //! Daughter Pion index1 +DECLARE_SOA_COLUMN(PionIndex2, pionIndex2, int); //! Daughter Pion index2 +DECLARE_SOA_COLUMN(PionPidMask, pionPidMask, uint8_t); //! bitmask for PID selections } // namespace kshortpionpair DECLARE_SOA_TABLE(KShortTracks, "AOD", "KSHORTTRACK", o2::soa::Index<>, @@ -98,10 +99,11 @@ DECLARE_SOA_TABLE(PionTracks, "AOD", "PIONTRACK", kshortpionpair::PionBachPy, kshortpionpair::PionBachPz, // kshortpionpair::PionBachSign, - kshortpionpair::PionBachTPC, - kshortpionpair::PionBachTOFHit, - kshortpionpair::PionBachTOF, - kshortpionpair::PionBachIndex); + // kshortpionpair::PionBachTPC, + // kshortpionpair::PionBachTOFHit, + // kshortpionpair::PionBachTOF, + kshortpionpair::PionBachIndex, + kshortpionpair::PionPidMask); using PionTrack = PionTracks::iterator; } // namespace o2::aod diff --git a/PWGLF/DataModel/LFF1Tables.h b/PWGLF/DataModel/LFF1Tables.h index 947e9f0c3a8..2532f182306 100644 --- a/PWGLF/DataModel/LFF1Tables.h +++ b/PWGLF/DataModel/LFF1Tables.h @@ -16,13 +16,13 @@ #ifndef PWGLF_DATAMODEL_LFF1TABLES_H_ #define PWGLF_DATAMODEL_LFF1TABLES_H_ -#include - -#include "Common/DataModel/PIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/AnalysisDataModel.h" +#include + namespace o2::aod { /// F1 Collisions diff --git a/PWGLF/DataModel/LFHStrangeCorrelationTables.h b/PWGLF/DataModel/LFHStrangeCorrelationTables.h index 3d54170252a..cebe1bf4115 100644 --- a/PWGLF/DataModel/LFHStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFHStrangeCorrelationTables.h @@ -29,8 +29,7 @@ #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisDataModel.h" - -#include +#include // Simple checker #define bitcheck(var, nbit) ((var) & (1 << (nbit))) @@ -45,8 +44,9 @@ 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"); //! DECLARE_SOA_COLUMN(MCOriginalPt, mcOriginalPt, float); // true generated pt +DECLARE_SOA_COLUMN(IsLeading, isLeading, bool); // is leading track in the event } // namespace triggerTracks -DECLARE_SOA_TABLE(TriggerTracks, "AOD", "TRIGGERTRACKS", o2::soa::Index<>, triggerTracks::CollisionId, triggerTracks::MCPhysicalPrimary, triggerTracks::TrackId, triggerTracks::MCOriginalPt); +DECLARE_SOA_TABLE(TriggerTracks, "AOD", "TRIGGERTRACKS", o2::soa::Index<>, triggerTracks::CollisionId, triggerTracks::MCPhysicalPrimary, triggerTracks::TrackId, triggerTracks::MCOriginalPt, triggerTracks::IsLeading); namespace triggerTrackExtras { DECLARE_SOA_COLUMN(Extra, extra, int); // true physical primary flag diff --git a/PWGLF/DataModel/LFHypernucleiTables.h b/PWGLF/DataModel/LFHypernucleiTables.h index ca389cf928b..9ff524dd347 100644 --- a/PWGLF/DataModel/LFHypernucleiTables.h +++ b/PWGLF/DataModel/LFHypernucleiTables.h @@ -59,6 +59,8 @@ DECLARE_SOA_COLUMN(NTPCclusHe, nTPCclusHe, uint8_t); // Number DECLARE_SOA_COLUMN(NTPCclusPi, nTPCclusPi, uint8_t); // Number of TPC clusters of the Pi daughter DECLARE_SOA_COLUMN(NTPCpidClusHe, nTPCpidClusHe, uint8_t); // Number of TPC clusters with PID information of the He daughter DECLARE_SOA_COLUMN(NTPCpidClusPi, nTPCpidClusPi, uint8_t); // Number of TPC clusters with PID information of the Pi daughter +DECLARE_SOA_COLUMN(NTPCCrossedRowsHe, nTPCCrossedRowsHe, uint8_t); // Number of TPC crossed rows of the He daughter +DECLARE_SOA_COLUMN(NTPCCrossedRowsPi, nTPCCrossedRowsPi, uint8_t); // Number of TPC crossed rows 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(TPCChi2He, tpcChi2He, float); // TPC chi2 of the He daughter @@ -99,7 +101,7 @@ DECLARE_SOA_TABLE(DataHypCands, "AOD", "HYPCANDS", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, @@ -118,7 +120,7 @@ DECLARE_SOA_TABLE(DataHypCandsFlow, "AOD", "HYPCANDSFLOW", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, @@ -134,7 +136,7 @@ DECLARE_SOA_TABLE(MCHypCands, "AOD", "MCHYPCANDS", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, @@ -163,7 +165,7 @@ DECLARE_SOA_TABLE(DataHypCandsWColl, "AOD", "HYPCANDSWCOLL", hyperrec::PtPi, hyperrec::PhiPi, hyperrec::EtaPi, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, hyperrec::DcaV0Daug, hyperrec::DcaHe, hyperrec::DcaPi, - hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, hyperrec::NTPCCrossedRowsHe, hyperrec::NTPCCrossedRowsPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, diff --git a/PWGLF/DataModel/LFLnnTables.h b/PWGLF/DataModel/LFLnnTables.h index f9ab7fe3989..16f8a9fbba5 100644 --- a/PWGLF/DataModel/LFLnnTables.h +++ b/PWGLF/DataModel/LFLnnTables.h @@ -53,6 +53,8 @@ DECLARE_SOA_COLUMN(CosPA, cosPA, double); // Cos DECLARE_SOA_COLUMN(NSigma3H, nSigma3H, float); // Number of sigmas of the 3H daughter DECLARE_SOA_COLUMN(NTPCclus3H, nTPCclus3H, uint8_t); // Number of TPC clusters of the 3H daughter DECLARE_SOA_COLUMN(NTPCclusPi, nTPCclusPi, uint8_t); // Number of TPC clusters of the Pi daughter +DECLARE_SOA_COLUMN(NTPCNClsCrossedRows3H, nTPCclsCrossedRows3H, uint8_t); // Number of TPC clusters crossed rows of the 3H daughter +DECLARE_SOA_COLUMN(NTPCNClsCrossedRowsPi, nTPCclsCrossedRowsPi, uint8_t); // Number of TPC clusters crossed rows of the Pi daughter DECLARE_SOA_COLUMN(TPCsignal3H, tpcSignal3H, uint16_t); // TPC signal of the 3H daughter DECLARE_SOA_COLUMN(TPCsignalPi, tpcSignalPi, uint16_t); // TPC signal of the Pi daughter DECLARE_SOA_COLUMN(Flags, flags, uint8_t); // Flags for PID in tracking (bits [0, 3] for negative daughter, [4,7] for positive daughter) @@ -73,6 +75,7 @@ DECLARE_SOA_COLUMN(GenYDecVtx, genYDecVtx, float); // Dec DECLARE_SOA_COLUMN(GenZDecVtx, genZDecVtx, float); // Decay vertex of the candidate (z direction) DECLARE_SOA_COLUMN(IsReco, isReco, bool); // bool: true for reco DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for signal +DECLARE_SOA_COLUMN(IsRecoMcCollision, isRecoMcCollision, bool); // bool: true for survived event selection DECLARE_SOA_COLUMN(SurvivedEventSelection, survivedEventSelection, bool); // bool: true for survived event selection } // namespace lnnrec @@ -87,7 +90,7 @@ DECLARE_SOA_TABLE(DataLnnCands, "AOD", "LNNCANDS", lnnrec::PtPi, lnnrec::PhiPi, lnnrec::EtaPi, lnnrec::XDecVtx, lnnrec::YDecVtx, lnnrec::ZDecVtx, lnnrec::DcaV0Daug, lnnrec::Dca3H, lnnrec::DcaPi, - lnnrec::NSigma3H, lnnrec::NTPCclus3H, lnnrec::NTPCclusPi, + lnnrec::NSigma3H, lnnrec::NTPCclus3H, lnnrec::NTPCclusPi, lnnrec::NTPCNClsCrossedRows3H, lnnrec::NTPCNClsCrossedRowsPi, lnnrec::TPCmom3H, lnnrec::TPCmomPi, lnnrec::TPCsignal3H, lnnrec::TPCsignalPi, lnnrec::MassTrTOF, lnnrec::TPCchi3H, lnnrec::ITSclusterSizes3H, lnnrec::ITSclusterSizesPi, @@ -104,7 +107,7 @@ DECLARE_SOA_TABLE(MCLnnCands, "AOD", "MCLNNCANDS", lnnrec::XDecVtx, lnnrec::YDecVtx, lnnrec::ZDecVtx, lnnrec::DcaV0Daug, lnnrec::Dca3H, lnnrec::DcaPi, lnnrec::NSigma3H, lnnrec::NTPCclus3H, lnnrec::NTPCclusPi, - lnnrec::TPCmom3H, lnnrec::TPCmomPi, lnnrec::TPCsignal3H, lnnrec::TPCsignalPi, + lnnrec::TPCmom3H, lnnrec::TPCmomPi, lnnrec::TPCsignal3H, lnnrec::TPCsignalPi, lnnrec::NTPCNClsCrossedRows3H, lnnrec::NTPCNClsCrossedRowsPi, lnnrec::MassTrTOF, lnnrec::TPCchi3H, lnnrec::ITSclusterSizes3H, lnnrec::ITSclusterSizesPi, lnnrec::Flags, @@ -116,7 +119,7 @@ DECLARE_SOA_TABLE(MCLnnCands, "AOD", "MCLNNCANDS", lnnrec::GenYDecVtx, lnnrec::GenZDecVtx, lnnrec::IsReco, - lnnrec::IsSignal, + lnnrec::IsSignal, lnnrec::IsRecoMcCollision, lnnrec::SurvivedEventSelection); using DataLnnCand = DataLnnCands::iterator; diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index d9ed41fe6bf..da4a1495602 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -123,6 +123,10 @@ DECLARE_SOA_COLUMN(MultNTracksGlobal, multNTracksGlobal, int); DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(NoSameBunchPileup, noSameBunchPileup, bool); +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); +DECLARE_SOA_COLUMN(PtGen, ptGen, float); +DECLARE_SOA_COLUMN(PtRec, ptRec, float); +DECLARE_SOA_COLUMN(MultGen, multGen, int); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", @@ -434,7 +438,6 @@ DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::MultNTracksGlobal, NPCascadeTable::ToiMask, NPCascadeTable::NoSameBunchPileup) - DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", NPCascadeTable::gPt, NPCascadeTable::gEta, @@ -447,7 +450,22 @@ DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", NPCascadeTable::IsFromBeauty, NPCascadeTable::IsFromCharm, NPCascadeTable::MotherDecayDaughters) - +DECLARE_SOA_TABLE(NPCollisionTable, "AOD", "NPCollisionTABLE", + NPCascadeTable::RunNumber, + NPCascadeTable::GlobalBC, + aod::collision::NumContrib, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::CentFT0M, + NPCascadeTable::MultFT0M); +DECLARE_SOA_TABLE(NPMCChargedTable, "AOD", "NPMCChargedTABLE", + NPCascadeTable::PtGen, + NPCascadeTable::PtRec, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::MultGen); +DECLARE_SOA_INDEX_COLUMN_FULL(NPCollision, npCollision, int32_t, NPCollisionTable, ""); +DECLARE_SOA_TABLE(NPRecoChargedCandidate, "AOD", "NPRecoChargedCandidate", + NPCollisionId, + NPCascadeTable::PtRec); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFNONPROMPTCASCADETABLES_H_ diff --git a/PWGLF/DataModel/LFNucleiTables.h b/PWGLF/DataModel/LFNucleiTables.h index 1cd9ba76c93..059410617bf 100644 --- a/PWGLF/DataModel/LFNucleiTables.h +++ b/PWGLF/DataModel/LFNucleiTables.h @@ -16,8 +16,9 @@ /// #include "Common/CCDB/EventSelectionParams.h" -#include "Framework/AnalysisDataModel.h" + #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #ifndef PWGLF_DATAMODEL_LFNUCLEITABLES_H_ #define PWGLF_DATAMODEL_LFNUCLEITABLES_H_ @@ -97,6 +98,7 @@ DECLARE_SOA_COLUMN(TOFExpMom, tofExpMom, float); DECLARE_SOA_COLUMN(TPCSignal, tpcSignal, float); DECLARE_SOA_COLUMN(Beta, beta, float); // TPC and ITS QA +DECLARE_SOA_COLUMN(PIDForTracking, pidForTracking, uint8_t); DECLARE_SOA_COLUMN(ITSNCls, itsNCls, int16_t); DECLARE_SOA_COLUMN(TPCChi2Ncl, tpcChi2NCl, float); DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, float); @@ -168,6 +170,7 @@ DECLARE_SOA_TABLE(LfCandNucleus, "AOD", "LFNUCL", full::HasTRD, full::TPCInnerParam, full::Beta, + full::PIDForTracking, full::TPCSignal, full::Pt, full::Eta, @@ -200,6 +203,7 @@ DECLARE_SOA_TABLE_VERSIONED(LfCandNucleusDummy, "AOD", "LFNUCL", 1, full::HasTRD, full::TPCInnerParam, full::Beta, + full::PIDForTracking, full::TPCSignal, full::Pt, full::Eta, diff --git a/PWGLF/DataModel/LFParticleIdentification.h b/PWGLF/DataModel/LFParticleIdentification.h index 5a688e4c97c..43a455b333c 100644 --- a/PWGLF/DataModel/LFParticleIdentification.h +++ b/PWGLF/DataModel/LFParticleIdentification.h @@ -19,12 +19,7 @@ #ifndef PWGLF_DATAMODEL_LFPARTICLEIDENTIFICATION_H_ #define PWGLF_DATAMODEL_LFPARTICLEIDENTIFICATION_H_ -// O2 includes -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" -#include "ReconstructionDataFormats/PID.h" -#include "Framework/Logger.h" +#include "Common/DataModel/PIDResponseTPC.h" namespace o2::aod { diff --git a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h index b19b67f9388..aca738fe6f2 100644 --- a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h @@ -22,14 +22,48 @@ namespace o2::aod { +namespace lf_selection_event +{ +DECLARE_SOA_COLUMN(DefaultSel, defaultSel, bool); +DECLARE_SOA_COLUMN(PhimesonSel, phimesonSel, bool); +} // namespace lf_selection_event + +/*DECLARE_SOA_TABLE(PhiStrangeDefEvtSelDataLike, "AOD", "DEFEVTSELDATA", + lf_selection_event::DefaultSel); + +DECLARE_SOA_TABLE(PhiStrangeDefEvtSelMcGen, "AOD", "DEFEVTSELMCGEN", + lf_selection_event::DefaultSel);*/ + +DECLARE_SOA_TABLE(PhiStrangeEvtSelDataLike, "AOD", "EVTSELDATA", + lf_selection_event::DefaultSel, + lf_selection_event::PhimesonSel); + +DECLARE_SOA_TABLE(PhiStrangeEvtSelMcGen, "AOD", "EVTSELMCGEN", + lf_selection_event::DefaultSel, + lf_selection_event::PhimesonSel); + +/*namespace lf_selection_default_collision +{ +DECLARE_SOA_COLUMN(DefaultSel, defaultSel, bool); +} // namespace lf_selection_default_collision + +DECLARE_SOA_TABLE(DefaultSelectionData, "AOD", "DEFSELDATA", + lf_selection_default_collision::DefaultSel); + +DECLARE_SOA_TABLE(DefaultSelectionMcGen, "AOD", "DEFSELMCGEN", + lf_selection_default_collision::DefaultSel); + namespace lf_selection_phi_collision { DECLARE_SOA_COLUMN(PhimesonSel, phimesonSel, bool); } // namespace lf_selection_phi_collision -DECLARE_SOA_TABLE(PhimesonSelection, "AOD", "PHIINCOLL", +DECLARE_SOA_TABLE(PhimesonSelectionData, "AOD", "PHIINCOLLDATA", lf_selection_phi_collision::PhimesonSel); +DECLARE_SOA_TABLE(PhimesonSelectionMcGen, "AOD", "PHIINCOLLMCGEN", + lf_selection_phi_collision::PhimesonSel);*/ + namespace lf_selection_phi_candidate { DECLARE_SOA_INDEX_COLUMN(Collision, collision); @@ -45,13 +79,112 @@ DECLARE_SOA_DYNAMIC_COLUMN(InMassRegion, inMassRegion, }); } // namespace lf_selection_phi_candidate -DECLARE_SOA_TABLE(PhimesonCandidates, "AOD", "PHICANDIDATES", +DECLARE_SOA_TABLE(PhimesonCandidatesData, "AOD", "PHICANDDATA", + soa::Index<>, + lf_selection_phi_candidate::CollisionId, + lf_selection_phi_candidate::M, + lf_selection_phi_candidate::Pt, + lf_selection_phi_candidate::Y, + lf_selection_phi_candidate::Phi, + lf_selection_phi_candidate::InMassRegion); + +DECLARE_SOA_TABLE(PhimesonCandidatesMcReco, "AOD", "PHICANDMCRECO", + soa::Index<>, + lf_selection_phi_candidate::CollisionId, + lf_selection_phi_candidate::M, + lf_selection_phi_candidate::Pt, + lf_selection_phi_candidate::Y, + lf_selection_phi_candidate::Phi, + lf_selection_phi_candidate::InMassRegion); + +DECLARE_SOA_TABLE(PhimesonCandidatesMcGen, "AOD", "PHICANDMCGEN", + soa::Index<>, lf_selection_phi_candidate::CollisionId, lf_selection_phi_candidate::M, lf_selection_phi_candidate::Pt, lf_selection_phi_candidate::Y, lf_selection_phi_candidate::Phi, lf_selection_phi_candidate::InMassRegion); + +namespace lf_selection_k0s_reduced +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); + +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Phi, phi, float); + +DECLARE_SOA_DYNAMIC_COLUMN(InMassRegion, inMassRegion, + [](float m, float minM, float maxM) -> bool { + return (m >= minM && m <= maxM); + }); +} // namespace lf_selection_k0s_reduced + +DECLARE_SOA_TABLE(K0sReducedCandidatesData, "AOD", "K0SCANDDATA", + soa::Index<>, + lf_selection_k0s_reduced::CollisionId, + lf_selection_k0s_reduced::M, + lf_selection_k0s_reduced::Pt, + lf_selection_k0s_reduced::Y, + lf_selection_k0s_reduced::Phi, + lf_selection_k0s_reduced::InMassRegion); + +DECLARE_SOA_TABLE(K0sReducedCandidatesMcReco, "AOD", "K0SCANDMCRECO", + soa::Index<>, + lf_selection_k0s_reduced::CollisionId, + lf_selection_k0s_reduced::M, + lf_selection_k0s_reduced::Pt, + lf_selection_k0s_reduced::Y, + lf_selection_k0s_reduced::Phi, + lf_selection_k0s_reduced::InMassRegion); + +namespace lf_selection_pion_track +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); + +DECLARE_SOA_COLUMN(NSigmaTPC, nSigmaTPC, float); +DECLARE_SOA_COLUMN(NSigmaTOF, nSigmaTOF, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); + +DECLARE_SOA_DYNAMIC_COLUMN(InNSigmaRegion, inNSigmaRegion, + [](float nSigmaTPC, float pt, bool hasTOF, float nSigmaTOF, float pidTPCMax, float tofPIDThreshold, float pidTOFMax) -> bool { + if (std::abs(nSigmaTPC) >= pidTPCMax) { + return false; // TPC check failed + } + if (pt >= tofPIDThreshold && hasTOF && std::abs(nSigmaTOF) >= pidTOFMax) { + return false; // TOF check failed + } + return true; + }); +} // namespace lf_selection_pion_track + +DECLARE_SOA_TABLE(PionTracksData, "AOD", "PITRACKSDATA", + soa::Index<>, + lf_selection_pion_track::CollisionId, + lf_selection_pion_track::NSigmaTPC, + lf_selection_pion_track::NSigmaTOF, + lf_selection_pion_track::Pt, + lf_selection_pion_track::Y, + lf_selection_pion_track::Phi, + lf_selection_pion_track::HasTOF, + lf_selection_pion_track::InNSigmaRegion); + +DECLARE_SOA_TABLE(PionTracksMcReco, "AOD", "PITRACKSMCRECO", + soa::Index<>, + lf_selection_pion_track::CollisionId, + lf_selection_pion_track::NSigmaTPC, + lf_selection_pion_track::NSigmaTOF, + lf_selection_pion_track::Pt, + lf_selection_pion_track::Y, + lf_selection_pion_track::Phi, + lf_selection_pion_track::HasTOF, + lf_selection_pion_track::InNSigmaRegion); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFPHISTRANGECORRELATIONTABLES_H_ diff --git a/PWGLF/DataModel/LFResonanceTables.h b/PWGLF/DataModel/LFResonanceTables.h index b8f60a6fc7a..675b7265d4b 100644 --- a/PWGLF/DataModel/LFResonanceTables.h +++ b/PWGLF/DataModel/LFResonanceTables.h @@ -22,15 +22,18 @@ #ifndef PWGLF_DATAMODEL_LFRESONANCETABLES_H_ #define PWGLF_DATAMODEL_LFRESONANCETABLES_H_ -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/Core/RecoDecay.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/Multiplicity.h" + +#include +#include namespace o2::aod { @@ -65,6 +68,7 @@ DECLARE_SOA_COLUMN(EvtPlResAB, evtPlResAB, float); // DECLARE_SOA_COLUMN(EvtPlResAC, evtPlResAC, float); //! Second harmonic event plane resolution of A-C sub events DECLARE_SOA_COLUMN(EvtPlResBC, evtPlResBC, float); //! Second harmonic event plane resolution of B-C sub events DECLARE_SOA_COLUMN(BMagField, bMagField, float); //! Magnetic field +DECLARE_SOA_COLUMN(IsRecINELgt0, isRecINELgt0, bool); //! Is reconstructed INEL>0 event // MC DECLARE_SOA_COLUMN(IsVtxIn10, isVtxIn10, bool); //! Vtx10 DECLARE_SOA_COLUMN(IsINELgt0, isINELgt0, bool); //! INEL>0 @@ -72,16 +76,20 @@ 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 +DECLARE_SOA_COLUMN(MCMultiplicity, mcMultiplicity, float); //! MC Multiplicity } // namespace resocollision DECLARE_SOA_TABLE(ResoCollisions, "AOD", "RESOCOLLISION", o2::soa::Index<>, o2::aod::mult::MultNTracksPV, + o2::aod::mult::MultNTracksPVeta1, + o2::aod::mult::MultNTracksPVetaHalf, collision::PosX, collision::PosY, collision::PosZ, resocollision::Cent, - resocollision::BMagField); + resocollision::BMagField, + resocollision::IsRecINELgt0); using ResoCollision = ResoCollisions::iterator; DECLARE_SOA_TABLE(ResoCollisionColls, "AOD", "RESOCOLLISIONCOL", @@ -95,7 +103,8 @@ DECLARE_SOA_TABLE(ResoMCCollisions, "AOD", "RESOMCCOLLISION", resocollision::IsTriggerTVX, resocollision::IsInSel8, resocollision::IsInAfterAllCuts, - resocollision::ImpactParameter); + resocollision::ImpactParameter, + resocollision::MCMultiplicity); using ResoMCCollision = ResoMCCollisions::iterator; DECLARE_SOA_TABLE(ResoSpheroCollisions, "AOD", "RESOSPHEROCOLLISION", @@ -201,6 +210,8 @@ DECLARE_SOA_COLUMN(CascTransRadius, cascTransRadius, float); DECLARE_SOA_COLUMN(DecayVtxX, decayVtxX, float); //! X position of the decay vertex DECLARE_SOA_COLUMN(DecayVtxY, decayVtxY, float); //! Y position of the decay vertex DECLARE_SOA_COLUMN(DecayVtxZ, decayVtxZ, float); //! Z position of the decay vertex +DECLARE_SOA_COLUMN(Alpha, alpha, float); //! Alpha of the decay vertex +DECLARE_SOA_COLUMN(QtArm, qtarm, float); //! Armenteros Qt of the decay vertex DECLARE_SOA_COLUMN(TpcSignal10, tpcSignal10, int8_t); //! TPC signal of the track x10 DECLARE_SOA_COLUMN(DaughterTPCNSigmaPosPi10, daughterTPCNSigmaPosPi10, int8_t); //! TPC PID x10 of the positive daughter as Pion DECLARE_SOA_COLUMN(DaughterTPCNSigmaPosKa10, daughterTPCNSigmaPosKa10, int8_t); //! TPC PID x10 of the positive daughter as Kaon @@ -226,6 +237,8 @@ DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); DECLARE_SOA_COLUMN(ProducedByGenerator, producedByGenerator, bool); DECLARE_SOA_COLUMN(MotherId, motherId, int); //! Id of the mother particle DECLARE_SOA_COLUMN(MotherPDG, motherPDG, int); //! PDG code of the mother particle +DECLARE_SOA_COLUMN(MotherPt, motherPt, float); //! Pt of the mother particle +DECLARE_SOA_COLUMN(MotherRap, motherRap, float); //! Rapidity of the mother particle DECLARE_SOA_COLUMN(DaughterPDG1, daughterPDG1, int); //! PDG code of the first Daughter particle DECLARE_SOA_COLUMN(DaughterPDG2, daughterPDG2, int); //! PDG code of the second Daughter particle DECLARE_SOA_COLUMN(DaughterID1, daughterID1, int); //! Id of the first Daughter particle @@ -637,6 +650,8 @@ DECLARE_SOA_TABLE(ResoV0s, "AOD", "RESOV0", resodaughter::DecayVtxX, resodaughter::DecayVtxY, resodaughter::DecayVtxZ, + resodaughter::Alpha, + resodaughter::QtArm, // resodaughter::Pt, resodaughter::Eta, resodaughter::Phi, @@ -809,6 +824,8 @@ DECLARE_SOA_TABLE(ResoMCV0s, "AOD", "RESOMCV0", mcparticle::PdgCode, resodaughter::MotherId, resodaughter::MotherPDG, + resodaughter::MotherPt, + resodaughter::MotherRap, resodaughter::DaughterID1, resodaughter::DaughterID2, resodaughter::DaughterPDG1, @@ -821,6 +838,8 @@ DECLARE_SOA_TABLE(ResoMCCascades, "AOD", "RESOMCCASCADE", mcparticle::PdgCode, resodaughter::MotherId, resodaughter::MotherPDG, + resodaughter::MotherPt, + resodaughter::MotherRap, resodaughter::BachTrkID, resodaughter::V0ID, resodaughter::DaughterPDG1, @@ -855,7 +874,7 @@ using Reso2TracksMC = soa::Join; using Reso2TracksPID = soa::Join; using Reso2TracksPIDExt = soa::Join; // Without Extra -using ResoCollisionCandidates = soa::Join; +using ResoCollisionCandidates = soa::Join; using ResoRun2CollisionCandidates = soa::Join; using ResoCollisionCandidatesMC = soa::Join; using ResoRun2CollisionCandidatesMC = soa::Join; diff --git a/PWGLF/DataModel/LFSigmaHadTables.h b/PWGLF/DataModel/LFSigmaHadTables.h new file mode 100644 index 00000000000..a70af6317fd --- /dev/null +++ b/PWGLF/DataModel/LFSigmaHadTables.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 LFSigmaHadTables.h +/// \brief Slim tables for Sigma-hadron pairs +/// \author Francesco Mazzaschi +/// + +#include "PWGLF/DataModel/LFKinkDecayTables.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + +#ifndef PWGLF_DATAMODEL_LFSIGMAHADTABLES_H_ +#define PWGLF_DATAMODEL_LFSIGMAHADTABLES_H_ + +namespace o2::aod +{ + +namespace sigmaproton +{ +DECLARE_SOA_COLUMN(ChargeSigma, chargeSigma, int); //! Charge of the sigma candidate +DECLARE_SOA_COLUMN(SigmaDecRad, sigmaDecRad, float); //! Decay radius of the Sigma candidate +DECLARE_SOA_COLUMN(SigmaCosPA, sigmaCosPA, float); //! Cosine of pointing angle of the Sigma candidate +DECLARE_SOA_COLUMN(ChargeHad, chargeHad, int); //! Charge of the hadron candidate +DECLARE_SOA_COLUMN(PxHad, pxHad, float); //! Px of the hadron candidate +DECLARE_SOA_COLUMN(PyHad, pyHad, float); //! Py of the hadron candidate +DECLARE_SOA_COLUMN(PzHad, pzHad, float); //! Pz of the hadron candidate +DECLARE_SOA_COLUMN(NSigmaTPCHad, nSigmaTPCHad, float); //! Number of sigmas for the hadron candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTOFHad, nSigmaTOFHad, float); //! Number of sigmas for the hadron candidate from Sigma kink in TOF + +// MC Columns +DECLARE_SOA_COLUMN(SigmaPDG, sigmaPDG, int); //! PDG code of the Sigma daughter +DECLARE_SOA_COLUMN(DaughterPDG, daughterPDG, int); //! PDG code of the kink daughter +DECLARE_SOA_COLUMN(HadPDG, hadPDG, int); //! PDG code of the hadron candidate +DECLARE_SOA_COLUMN(SigmaGenPt, sigmaGenPt, float); //! Generated pT of the Sigma candidate +DECLARE_SOA_COLUMN(HadGenPt, hadGenPt, float); //! Generated pT of the hadron candidate +DECLARE_SOA_COLUMN(GenKStar, genKStar, float); //! Generated k* of the Sigma-hadron pair + +} // namespace sigmaproton + +DECLARE_SOA_TABLE(SigmaProtonCands, "AOD", "SIGMAPROTONCANDS", + o2::soa::Index<>, + sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, + kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, + sigmaproton::ChargeHad, sigmaproton::PxHad, sigmaproton::PyHad, sigmaproton::PzHad, + sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad); + +DECLARE_SOA_TABLE(SigmaProtonMCCands, "AOD", "SIGMAPROTONMCCANDS", + o2::soa::Index<>, + sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, + kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, + sigmaproton::ChargeHad, sigmaproton::PxHad, sigmaproton::PyHad, sigmaproton::PzHad, + sigmaproton::NSigmaTPCHad, sigmaproton::NSigmaTOFHad, + sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::HadPDG, + sigmaproton::SigmaGenPt, sigmaproton::HadGenPt, sigmaproton::GenKStar); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFSIGMAHADTABLES_H_ diff --git a/PWGLF/DataModel/LFSigmaProtonTables.h b/PWGLF/DataModel/LFSigmaProtonTables.h deleted file mode 100644 index cf512422c79..00000000000 --- a/PWGLF/DataModel/LFSigmaProtonTables.h +++ /dev/null @@ -1,67 +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 LFKinkDecayTables.h -/// \brief Slim tables for kinks -/// \author Francesco Mazzaschi -/// - -#include "PWGLF/DataModel/LFKinkDecayTables.h" - -#include "Common/Core/RecoDecay.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" - -#ifndef PWGLF_DATAMODEL_LFSIGMAPROTONTABLES_H_ -#define PWGLF_DATAMODEL_LFSIGMAPROTONTABLES_H_ - -namespace o2::aod -{ - -namespace sigmaproton -{ -DECLARE_SOA_COLUMN(ChargeSigma, chargeSigma, int); //! Charge of the sigma candidate -DECLARE_SOA_COLUMN(SigmaDecRad, sigmaDecRad, float); //! Decay radius of the Sigma candidate -DECLARE_SOA_COLUMN(SigmaCosPA, sigmaCosPA, float); //! Cosine of pointing angle of the Sigma candidate -DECLARE_SOA_COLUMN(ChargePr, chargePr, int); //! Charge of the proton candidate -DECLARE_SOA_COLUMN(PxPr, pxPr, float); //! Px of the proton candidate -DECLARE_SOA_COLUMN(PyPr, pyPr, float); //! Py of the proton candidate -DECLARE_SOA_COLUMN(PzPr, pzPr, float); //! Pz of the proton candidate -DECLARE_SOA_COLUMN(NSigmaTPCPr, nSigmaTPCPr, float); //! Number of sigmas for the proton candidate from Sigma kink in TPC -DECLARE_SOA_COLUMN(NSigmaTOFPr, nSigmaTOFPr, float); //! Number of sigmas for the proton candidate from Sigma kink in TOF - -// MC Columns -DECLARE_SOA_COLUMN(SigmaPDG, sigmaPDG, int); //! PDG code of the Sigma daughter -DECLARE_SOA_COLUMN(DaughterPDG, daughterPDG, int); //! PDG code of the kink daughter -DECLARE_SOA_COLUMN(PrPDG, prPDG, int); //! PDG code of the proton candidate - -} // namespace sigmaproton - -DECLARE_SOA_TABLE(SigmaProtonCands, "AOD", "SIGMAPROTONCANDS", - o2::soa::Index<>, - sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, - kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, - sigmaproton::ChargePr, sigmaproton::PxPr, sigmaproton::PyPr, sigmaproton::PzPr, - sigmaproton::NSigmaTPCPr, sigmaproton::NSigmaTOFPr); - -DECLARE_SOA_TABLE(SigmaProtonMCCands, "AOD", "SIGMAPROTONMCCANDS", - o2::soa::Index<>, - sigmaproton::ChargeSigma, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, - kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, sigmaproton::SigmaDecRad, sigmaproton::SigmaCosPA, - sigmaproton::ChargePr, sigmaproton::PxPr, sigmaproton::PyPr, sigmaproton::PzPr, - sigmaproton::NSigmaTPCPr, sigmaproton::NSigmaTOFPr, - sigmaproton::SigmaPDG, sigmaproton::DaughterPDG, sigmaproton::PrPDG); - -} // namespace o2::aod - -#endif // PWGLF_DATAMODEL_LFSIGMAPROTONTABLES_H_ diff --git a/PWGLF/DataModel/LFSigmaTables.h b/PWGLF/DataModel/LFSigmaTables.h index 9d728bab596..6c8c9c3a232 100644 --- a/PWGLF/DataModel/LFSigmaTables.h +++ b/PWGLF/DataModel/LFSigmaTables.h @@ -35,16 +35,11 @@ using std::array; namespace o2::aod { -// Indexing -namespace sigma0Core -{ -DECLARE_SOA_INDEX_COLUMN_FULL(PhotonV0, photonV0, int, V0Cores, "_PhotonV0"); //! -DECLARE_SOA_INDEX_COLUMN_FULL(LambdaV0, lambdaV0, int, V0Cores, "_LambdaV0"); //! -} // namespace sigma0Core - // for real data namespace sigma0Core { +DECLARE_SOA_COLUMN(PhotonV0ID, photonV0ID, int); +DECLARE_SOA_COLUMN(LambdaV0ID, lambdaV0ID, int); DECLARE_SOA_COLUMN(X, x, float); DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(Z, z, float); @@ -163,6 +158,9 @@ DECLARE_SOA_DYNAMIC_COLUMN(LambdaPhi, lambdaPhi, //! Phi in the range [0, 2pi) } // namespace sigma0Core DECLARE_SOA_TABLE(Sigma0Cores, "AOD", "SIGMA0CORES", + // Indices for debug + sigma0Core::PhotonV0ID, sigma0Core::LambdaV0ID, + // Basic properties sigma0Core::X, sigma0Core::Y, sigma0Core::Z, sigma0Core::DCADaughters, sigma0Core::PhotonPx, sigma0Core::PhotonPy, sigma0Core::PhotonPz, sigma0Core::PhotonMass, @@ -502,6 +500,42 @@ DECLARE_SOA_TABLE(Sigma0PhotonExtras, "AOD", "SIGMA0PHOTON", sigma0PhotonExtra::PhotonNegTrackCode, sigma0PhotonExtra::PhotonV0Type); +// For EMCal Photon extra info +namespace sigma0EMPhoton +{ +//______________________________________________________ +// REGULAR COLUMNS FOR SIGMA0EMPHOTON +DECLARE_SOA_COLUMN(PhotonID, photonID, int); +DECLARE_SOA_COLUMN(PhotonEnergy, photonEnergy, float); +DECLARE_SOA_COLUMN(PhotonEMCEta, photonEMCEta, float); +DECLARE_SOA_COLUMN(PhotonEMCPhi, photonEMCPhi, float); +DECLARE_SOA_COLUMN(PhotonM02, photonM02, float); +DECLARE_SOA_COLUMN(PhotonM20, photonM20, float); +DECLARE_SOA_COLUMN(PhotonNCells, photonNCells, int); +DECLARE_SOA_COLUMN(PhotonTime, photonTime, float); +DECLARE_SOA_COLUMN(PhotonIsExotic, photonIsExotic, bool); +DECLARE_SOA_COLUMN(PhotonDistToBad, photonDistToBad, float); +DECLARE_SOA_COLUMN(PhotonNLM, photonNLM, int); +DECLARE_SOA_COLUMN(PhotonDefinition, photonDefinition, int); +DECLARE_SOA_COLUMN(PhotonHasAssocTrk, photonHasAssocTrk, bool); + +} // namespace sigma0EMPhoton + +DECLARE_SOA_TABLE(Sigma0EMPhotons, "AOD", "SIGMA0EMPHOTON", + sigma0EMPhoton::PhotonID, + sigma0EMPhoton::PhotonEnergy, + sigma0EMPhoton::PhotonEMCEta, + sigma0EMPhoton::PhotonEMCPhi, + sigma0EMPhoton::PhotonM02, + sigma0EMPhoton::PhotonM20, + sigma0EMPhoton::PhotonNCells, + sigma0EMPhoton::PhotonTime, + sigma0EMPhoton::PhotonIsExotic, + sigma0EMPhoton::PhotonDistToBad, + sigma0EMPhoton::PhotonNLM, + sigma0EMPhoton::PhotonDefinition, + sigma0EMPhoton::PhotonHasAssocTrk); + // For Lambda extra info namespace sigma0LambdaExtra { @@ -567,6 +601,7 @@ DECLARE_SOA_TABLE(Sigma0LambdaExtras, "AOD", "SIGMA0LAMBDA", // for MC namespace sigma0MCCore { +DECLARE_SOA_COLUMN(ParticleIdMC, particleIdMC, int); //! V0 Particle ID DECLARE_SOA_COLUMN(MCradius, mcradius, float); DECLARE_SOA_COLUMN(PDGCode, pdgCode, int); DECLARE_SOA_COLUMN(PDGCodeMother, pdgCodeMother, int); @@ -576,6 +611,9 @@ DECLARE_SOA_COLUMN(IsProducedByGenerator, isProducedByGenerator, bool); DECLARE_SOA_COLUMN(PhotonMCPx, photonmcpx, float); DECLARE_SOA_COLUMN(PhotonMCPy, photonmcpy, float); DECLARE_SOA_COLUMN(PhotonMCPz, photonmcpz, float); +DECLARE_SOA_COLUMN(PhotonAmplitudeA, photonAmplitudeA, float); // Energy fraction deposited by a particle inside this calo cell. +DECLARE_SOA_COLUMN(PhotonPDGCodePos, photonPDGCodePos, int); +DECLARE_SOA_COLUMN(PhotonPDGCodeNeg, photonPDGCodeNeg, int); DECLARE_SOA_COLUMN(IsPhotonPrimary, isPhotonPrimary, bool); DECLARE_SOA_COLUMN(PhotonPDGCode, photonPDGCode, int); DECLARE_SOA_COLUMN(PhotonPDGCodeMother, photonPDGCodeMother, int); @@ -585,6 +623,8 @@ DECLARE_SOA_COLUMN(LambdaMCPx, lambdamcpx, float); DECLARE_SOA_COLUMN(LambdaMCPy, lambdamcpy, float); DECLARE_SOA_COLUMN(LambdaMCPz, lambdamcpz, float); DECLARE_SOA_COLUMN(IsLambdaPrimary, isLambdaPrimary, bool); +DECLARE_SOA_COLUMN(LambdaPDGCodePos, lambdaPDGCodePos, int); +DECLARE_SOA_COLUMN(LambdaPDGCodeNeg, lambdaPDGCodeNeg, int); DECLARE_SOA_COLUMN(LambdaPDGCode, lambdaPDGCode, int); DECLARE_SOA_COLUMN(LambdaPDGCodeMother, lambdaPDGCodeMother, int); DECLARE_SOA_COLUMN(LambdaIsCorrectlyAssoc, lambdaIsCorrectlyAssoc, bool); @@ -691,15 +731,17 @@ DECLARE_SOA_DYNAMIC_COLUMN(LambdaMCPhi, lambdaMCPhi, //! Phi in the range [0, 2p } // namespace sigma0MCCore DECLARE_SOA_TABLE(Sigma0MCCores, "AOD", "SIGMA0MCCORES", + // MC particle index for debug + sigma0MCCore::ParticleIdMC, // Basic properties sigma0MCCore::MCradius, sigma0MCCore::PDGCode, sigma0MCCore::PDGCodeMother, sigma0MCCore::MCprocess, sigma0MCCore::IsProducedByGenerator, - sigma0MCCore::PhotonMCPx, sigma0MCCore::PhotonMCPy, sigma0MCCore::PhotonMCPz, - sigma0MCCore::IsPhotonPrimary, sigma0MCCore::PhotonPDGCode, sigma0MCCore::PhotonPDGCodeMother, sigma0MCCore::PhotonIsCorrectlyAssoc, + sigma0MCCore::PhotonMCPx, sigma0MCCore::PhotonMCPy, sigma0MCCore::PhotonMCPz, sigma0MCCore::PhotonAmplitudeA, + sigma0MCCore::PhotonPDGCodePos, sigma0MCCore::PhotonPDGCodeNeg, sigma0MCCore::IsPhotonPrimary, sigma0MCCore::PhotonPDGCode, sigma0MCCore::PhotonPDGCodeMother, sigma0MCCore::PhotonIsCorrectlyAssoc, sigma0MCCore::LambdaMCPx, sigma0MCCore::LambdaMCPy, sigma0MCCore::LambdaMCPz, - sigma0MCCore::IsLambdaPrimary, sigma0MCCore::LambdaPDGCode, sigma0MCCore::LambdaPDGCodeMother, sigma0MCCore::LambdaIsCorrectlyAssoc, + sigma0MCCore::LambdaPDGCodePos, sigma0MCCore::LambdaPDGCodeNeg, sigma0MCCore::IsLambdaPrimary, sigma0MCCore::LambdaPDGCode, sigma0MCCore::LambdaPDGCodeMother, sigma0MCCore::LambdaIsCorrectlyAssoc, // Dynamic columns sigma0MCCore::IsSigma0, @@ -728,11 +770,6 @@ DECLARE_SOA_TABLE(Sigma0MCCores, "AOD", "SIGMA0MCCORES", sigma0MCCore::LambdaMCY, sigma0MCCore::LambdaMCPhi); -namespace sigma0MCCore -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Sigma0 -} - // for MC namespace kstarMCCore { @@ -923,12 +960,6 @@ DECLARE_SOA_TABLE(KStarGens, "AOD", "KSTARGENS", DECLARE_SOA_TABLE(SigmaCollRef, "AOD", "SIGMACOLLREF", //! optional table to refer back to a collision o2::soa::Index<>, v0data::StraCollisionId); -DECLARE_SOA_TABLE(SigmaIndices, "AOD", "SIGMAINDEX", //! index table when using AO2Ds - o2::soa::Index<>, sigma0Core::PhotonV0Id, sigma0Core::LambdaV0Id, o2::soa::Marker<1>); - -DECLARE_SOA_TABLE(SigmaMCLabels, "AOD", "SIGMAMCLABEL", //! optional table to refer to mcparticles - o2::soa::Index<>, sigma0MCCore::McParticleId); - DECLARE_SOA_TABLE(SigmaGenCollRef, "AOD", "SIGMAGENCOLLREF", //! optional table to refer back to a collision o2::soa::Index<>, v0data::StraMCCollisionId); diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index e266bed5001..84a2da9966f 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -55,6 +55,10 @@ DECLARE_SOA_COLUMN(MotherPDGcode, MotherpdgCode, int); DECLARE_SOA_COLUMN(MotherDecRad, motherDecRad, float); DECLARE_SOA_COLUMN(AbsoDecL, absoDecL, float); DECLARE_SOA_COLUMN(McProcess, mcProcess, uint64_t); +DECLARE_SOA_COLUMN(gEventMask, genEventMask, uint8_t); + +DECLARE_SOA_COLUMN(NsigmaTpc, nsigmaTpc, uint8_t); +DECLARE_SOA_COLUMN(NsigmaTof, nsigmaTof, uint8_t); } // namespace NucleiTableNS @@ -203,6 +207,45 @@ DECLARE_SOA_TABLE(NucleiTableRed, "AOD", "NUCLEITABLERED", NucleiTableNS::PDGcode, NucleiTableNS::MotherPDGcode); +// Table for keeping track of selection of generated events +DECLARE_SOA_TABLE(GenEventMCSel, "AOD", "GENEVENTMCSEL", + NucleiTableNS::gEventMask); + +DECLARE_SOA_TABLE(NucleiTableMCExtension, "AOD", "NUCTABLEMCSEL", + NucleiTableNS::Pt, + NucleiTableNS::Eta, + NucleiTableNS::Phi, + NucleiTableNS::TPCInnerParam, + NucleiTableNS::Beta, + NucleiTableNS::Zvertex, + NucleiTableNS::NContrib, + NucleiTableNS::DCAxy, + NucleiTableNS::DCAz, + NucleiTableNS::TPCsignal, + NucleiTableNS::ITSchi2, + NucleiTableNS::TPCchi2, + NucleiTableNS::TOFchi2, + NucleiTableNS::Flags, + NucleiTableNS::TPCfindableCls, + NucleiTableNS::TPCcrossedRows, + NucleiTableNS::ITSclsMap, + NucleiTableNS::TPCnCls, + NucleiTableNS::TPCnClsShared, + NucleiTableNS::ITSclusterSizes, + NucleiTableNS::SurvivedEventSelection, + NucleiTableNS::gPt, + NucleiTableNS::gEta, + NucleiTableNS::gPhi, + NucleiTableNS::PDGcode, + NucleiTableNS::MotherPDGcode, + NucleiTableNS::MotherDecRad, + NucleiTableNS::AbsoDecL, + NucleiTableNS::gEventMask); +// Extended table with central PID information +DECLARE_SOA_TABLE(NucleiTableExt, "AOD", "NUCLEITABLEEXT", + NucleiTableNS::NsigmaTpc, + NucleiTableNS::NsigmaTof); + } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ diff --git a/PWGLF/DataModel/LFSpincorrelationTables.h b/PWGLF/DataModel/LFSpincorrelationTables.h index f875736d794..b7161eb3654 100644 --- a/PWGLF/DataModel/LFSpincorrelationTables.h +++ b/PWGLF/DataModel/LFSpincorrelationTables.h @@ -18,7 +18,6 @@ #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index bc7fd7d3aaa..33d06f159d9 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -82,6 +82,11 @@ DECLARE_SOA_TABLE_VERSIONED(StraCents_001, "AOD", "STRACENTS", 1, //! centrality cent::CentFT0C, cent::CentFV0A, cent::CentFT0CVariant1, cent::CentMFT, cent::CentNGlobal); +DECLARE_SOA_TABLE_VERSIONED(StraCents_002, "AOD", "STRACENTS", 2, //! centrality percentiles in Run 3 + cent::CentFT0M, cent::CentFT0A, + cent::CentFT0C, cent::CentFV0A, + cent::CentFT0CVariant1, cent::CentFT0CVariant2, + cent::CentMFT, cent::CentNGlobal, cent::CentNTPV); DECLARE_SOA_TABLE(StraCentsRun2, "AOD", "STRACENTSRUN2", //! centrality percentiles in Run 2 cent::CentRun2V0M, cent::CentRun2V0A, @@ -274,6 +279,16 @@ DECLARE_SOA_TABLE_VERSIONED(StraEvSels_005, "AOD", "STRAEVSELS", 5, //! // stracollision::EnergyCommonZNC, stracollision::IsUPC); +DECLARE_SOA_TABLE(StraEvSelExtras, "AOD", "STRAEVSELEXTRAS", //! debug information + udzdc::TimeZNA, // UPC info: re-assigned ZN-A time, in case of SG event, from the most active bc + udzdc::TimeZNC, // UPC info: re-assigned ZN-C time, in case of SG event, from the most active bc + udcollision::TimeFDDA, // Average A-side time (ns) + udcollision::TimeFDDC, // Average C-side time (ns) + udcollision::TimeFV0A, // Average A-side time (ns) + udcollision::TimeFT0A, // Average A-side time (ns) + udcollision::TimeFT0C, // Average C-side time (ns) + udcollision::TriggerMaskFT0); // 8 trigger bits: OrA, OrC, Semi-central, Central, Vertex, IsActiveA, IsActiveC, IsFlangeEvent + DECLARE_SOA_TABLE(StraEvSelsRun2, "AOD", "STRAEVSELSRUN2", //! debug information evsel::Sel8, evsel::Sel7, evsel::Selection, //! event selection: sel8 mult::MultFT0A, mult::MultFT0C, // FIT detectors @@ -315,11 +330,11 @@ DECLARE_SOA_TABLE(StraEvTimes, "AOD", "STRAEVTIMES", //! event time (FT0, TOF) stracollision::EventTime); using StraRawCents = StraRawCents_004; -using StraCents = StraCents_001; +using StraCents = StraCents_002; using StraEvSels = StraEvSels_005; using StraStamps = StraStamps_001; using StraCollision = StraCollisions::iterator; -using StraCent = StraCents_001::iterator; +using StraCent = StraCents::iterator; namespace stramccollision { diff --git a/PWGLF/DataModel/ReducedDoublePhiTables.h b/PWGLF/DataModel/ReducedDoublePhiTables.h index 76cc65312a7..080dc6004bb 100644 --- a/PWGLF/DataModel/ReducedDoublePhiTables.h +++ b/PWGLF/DataModel/ReducedDoublePhiTables.h @@ -15,15 +15,15 @@ #ifndef PWGLF_DATAMODEL_REDUCEDDOUBLEPHITABLES_H_ #define PWGLF_DATAMODEL_REDUCEDDOUBLEPHITABLES_H_ -#include - +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" + #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include namespace o2::aod { diff --git a/PWGLF/DataModel/ReducedF1ProtonTables.h b/PWGLF/DataModel/ReducedF1ProtonTables.h index 2f806c4bd1b..108df966bb1 100644 --- a/PWGLF/DataModel/ReducedF1ProtonTables.h +++ b/PWGLF/DataModel/ReducedF1ProtonTables.h @@ -16,15 +16,15 @@ #ifndef PWGLF_DATAMODEL_REDUCEDF1PROTONTABLES_H_ #define PWGLF_DATAMODEL_REDUCEDF1PROTONTABLES_H_ -#include - +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" + #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include namespace o2::aod { @@ -77,6 +77,31 @@ DECLARE_SOA_COLUMN(ProtonNsigmaTPC, protonNsigmaTPC, float); //! P DECLARE_SOA_COLUMN(ProtonTOFHit, protonTOFHit, int); //! Proton TOF Hit DECLARE_SOA_COLUMN(ProtonNsigmaTOF, protonNsigmaTOF, float); //! Proton TOF nsigma DECLARE_SOA_COLUMN(F1ProtonIndex, f1ProtonIndex, int64_t); //! F1 proton index +DECLARE_SOA_COLUMN(PionTOF, pionTOF, float); //! Pion TOF +DECLARE_SOA_COLUMN(PionDcaxy, pionDcaxy, float); //! Pion DCAxy +DECLARE_SOA_COLUMN(PionDcaz, pionDcaz, float); //! Pion DCAz +DECLARE_SOA_COLUMN(PionTPCNcls, pionTPCNcls, float); //! Pion TPC Ncls +DECLARE_SOA_COLUMN(PionTPCNcrs, pionTPCNcrs, float); //! Pion TPC Ncrs +DECLARE_SOA_COLUMN(KaonTOF, kaonTOF, float); //! Kaon TOF +DECLARE_SOA_COLUMN(KaonDcaxy, kaonDcaxy, float); //! Kaon DCAxy +DECLARE_SOA_COLUMN(KaonDcaz, kaonDcaz, float); //! Kaon DCAz +DECLARE_SOA_COLUMN(KaonTPCNcls, kaonTPCNcls, float); //! Kaon TPC Ncls +DECLARE_SOA_COLUMN(KaonTPCNcrs, kaonTPCNcrs, float); //! Kaon TPC Ncrs +DECLARE_SOA_COLUMN(K0D1Dcaxy, k0D1Dcaxy, float); //! K0 daughter 1 DCAxy +DECLARE_SOA_COLUMN(K0D1TPCNcls, k0D1TPCNcls, float); //! K0 daughter 1 TPC Ncls +DECLARE_SOA_COLUMN(K0D1TPCNcrs, k0D1TPCNcrs, float); //! K0 daughter 1 TPC Ncrs +DECLARE_SOA_COLUMN(K0D2Dcaxy, k0D2Dcaxy, float); //! K0 daughter 2 DCAxy +DECLARE_SOA_COLUMN(K0D2TPCNcls, k0D2TPCNcls, float); //! K0 daughter 2 TPC Ncls +DECLARE_SOA_COLUMN(K0D2TPCNcrs, k0D2TPCNcrs, float); //! K0 daughter 2 TPC Ncrs +DECLARE_SOA_COLUMN(K0Cpa, k0Cpa, float); //! K0 CPA +DECLARE_SOA_COLUMN(K0Radius, k0Radius, float); //! K0 decay radius +DECLARE_SOA_COLUMN(K0DcaDaughters, k0DcaDaughters, float); //! K0 DCA between daughters +DECLARE_SOA_COLUMN(K0Dca, k0Dca, float); //! K0 DCA to PV +DECLARE_SOA_COLUMN(K0LifeTime, k0LifeTime, float); //! K0 proper lifetime +DECLARE_SOA_COLUMN(ProtonDcaxy, protonDcaxy, float); //! Proton DCAxy +DECLARE_SOA_COLUMN(ProtonDcaz, protonDcaz, float); //! Proton DCAz +DECLARE_SOA_COLUMN(ProtonTPCNcls, protonTPCNcls, float); //! Proton TPC Ncls +DECLARE_SOA_COLUMN(ProtonTPCNcrs, protonTPCNcrs, float); //! Proton TPC Ncrs } // namespace f1protondaughter DECLARE_SOA_TABLE(F1Tracks, "AOD", "F1TRACK", o2::soa::Index<>, @@ -104,7 +129,28 @@ DECLARE_SOA_TABLE(F1Tracks, "AOD", "F1TRACK", f1protondaughter::F1PionIndex, f1protondaughter::F1KaonIndex, f1protondaughter::F1KshortPositiveIndex, - f1protondaughter::F1KshortNegativeIndex); + f1protondaughter::F1KshortNegativeIndex, + f1protondaughter::PionTOF, + f1protondaughter::PionDcaxy, + f1protondaughter::PionDcaz, + f1protondaughter::PionTPCNcls, + f1protondaughter::PionTPCNcrs, + f1protondaughter::KaonTOF, + f1protondaughter::KaonDcaxy, + f1protondaughter::KaonDcaz, + f1protondaughter::KaonTPCNcls, + f1protondaughter::KaonTPCNcrs, + f1protondaughter::K0D1Dcaxy, + f1protondaughter::K0D1TPCNcls, + f1protondaughter::K0D1TPCNcrs, + f1protondaughter::K0D2Dcaxy, + f1protondaughter::K0D2TPCNcls, + f1protondaughter::K0D2TPCNcrs, + f1protondaughter::K0Cpa, + f1protondaughter::K0Radius, + f1protondaughter::K0DcaDaughters, + f1protondaughter::K0Dca, + f1protondaughter::K0LifeTime); using F1Track = F1Tracks::iterator; DECLARE_SOA_TABLE(ProtonTracks, "AOD", "PROTONTRACK", @@ -117,7 +163,11 @@ DECLARE_SOA_TABLE(ProtonTracks, "AOD", "PROTONTRACK", f1protondaughter::ProtonNsigmaTPC, f1protondaughter::ProtonTOFHit, f1protondaughter::ProtonNsigmaTOF, - f1protondaughter::F1ProtonIndex); + f1protondaughter::F1ProtonIndex, + f1protondaughter::ProtonDcaxy, + f1protondaughter::ProtonDcaz, + f1protondaughter::ProtonTPCNcls, + f1protondaughter::ProtonTPCNcrs); using ProtonTrack = ProtonTracks::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_REDUCEDF1PROTONTABLES_H_ diff --git a/PWGLF/DataModel/ReducedHeptaQuarkTables.h b/PWGLF/DataModel/ReducedHeptaQuarkTables.h index b547933cb59..d54870ae0e7 100644 --- a/PWGLF/DataModel/ReducedHeptaQuarkTables.h +++ b/PWGLF/DataModel/ReducedHeptaQuarkTables.h @@ -15,22 +15,22 @@ #ifndef PWGLF_DATAMODEL_REDUCEDHEPTAQUARKTABLES_H_ #define PWGLF_DATAMODEL_REDUCEDHEPTAQUARKTABLES_H_ -#include - +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" + #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include namespace o2::aod { namespace redhqevent { -DECLARE_SOA_COLUMN(NumPhi, numPhi, int); //! Number of negative K -DECLARE_SOA_COLUMN(NumLambda, numLambda, int); //! Number of lambda +DECLARE_SOA_COLUMN(NumPhi, numPhi, int); //! Number of negative K +DECLARE_SOA_COLUMN(NumLambda, numLambda, int); //! Number of lambda DECLARE_SOA_COLUMN(Centrality, centrality, float); //! } // namespace redhqevent DECLARE_SOA_TABLE(RedHQEvents, "AOD", "REDHQEVENT", @@ -38,6 +38,8 @@ DECLARE_SOA_TABLE(RedHQEvents, "AOD", "REDHQEVENT", bc::GlobalBC, bc::RunNumber, timestamp::Timestamp, + collision::PosX, + collision::PosY, collision::PosZ, collision::NumContrib, redhqevent::Centrality, diff --git a/PWGLF/DataModel/ReducedLambdaLambdaTables.h b/PWGLF/DataModel/ReducedLambdaLambdaTables.h index 88ea8fb0530..d0e91e43085 100644 --- a/PWGLF/DataModel/ReducedLambdaLambdaTables.h +++ b/PWGLF/DataModel/ReducedLambdaLambdaTables.h @@ -15,15 +15,15 @@ #ifndef PWGLF_DATAMODEL_REDUCEDLAMBDALAMBDATABLES_H_ #define PWGLF_DATAMODEL_REDUCEDLAMBDALAMBDATABLES_H_ -#include - +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" + #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include namespace o2::aod { diff --git a/PWGLF/DataModel/SPCalibrationTables.h b/PWGLF/DataModel/SPCalibrationTables.h index 2b417ce8758..6000055c1f1 100644 --- a/PWGLF/DataModel/SPCalibrationTables.h +++ b/PWGLF/DataModel/SPCalibrationTables.h @@ -17,13 +17,13 @@ #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" +#include + namespace o2::aod { namespace spcalibrationtable diff --git a/PWGLF/DataModel/ZDCCalTables.h b/PWGLF/DataModel/ZDCCalTables.h index 0f2c4e0afb6..fee4e89e309 100644 --- a/PWGLF/DataModel/ZDCCalTables.h +++ b/PWGLF/DataModel/ZDCCalTables.h @@ -18,7 +18,6 @@ #define PWGLF_DATAMODEL_ZDCCALTABLES_H_ #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisDataModel.h" @@ -35,16 +34,10 @@ DECLARE_SOA_COLUMN(Cent, cent, float); DECLARE_SOA_COLUMN(Vx, vx, float); DECLARE_SOA_COLUMN(Vy, vy, float); DECLARE_SOA_COLUMN(Vz, vz, float); -DECLARE_SOA_COLUMN(ZnaC, znaC, float); -DECLARE_SOA_COLUMN(ZncC, zncC, float); -DECLARE_SOA_COLUMN(ZnaE0, znaE0, float); -DECLARE_SOA_COLUMN(ZnaE1, znaE1, float); -DECLARE_SOA_COLUMN(ZnaE2, znaE2, float); -DECLARE_SOA_COLUMN(ZnaE3, znaE3, float); -DECLARE_SOA_COLUMN(ZncE0, zncE0, float); -DECLARE_SOA_COLUMN(ZncE1, zncE1, float); -DECLARE_SOA_COLUMN(ZncE2, zncE2, float); -DECLARE_SOA_COLUMN(ZncE3, zncE3, float); +DECLARE_SOA_COLUMN(QxA, qxA, float); +DECLARE_SOA_COLUMN(QxC, qxC, float); +DECLARE_SOA_COLUMN(QyA, qyA, float); +DECLARE_SOA_COLUMN(QyC, qyC, float); } // namespace zdccaltable DECLARE_SOA_TABLE(ZDCCalTables, "AOD", "ZDCCALTABLE", zdccaltable::TriggerEventZDC, @@ -53,16 +46,10 @@ DECLARE_SOA_TABLE(ZDCCalTables, "AOD", "ZDCCALTABLE", zdccaltable::Vx, zdccaltable::Vy, zdccaltable::Vz, - zdccaltable::ZnaC, - zdccaltable::ZncC, - zdccaltable::ZnaE0, - zdccaltable::ZnaE1, - zdccaltable::ZnaE2, - zdccaltable::ZnaE3, - zdccaltable::ZncE0, - zdccaltable::ZncE1, - zdccaltable::ZncE2, - zdccaltable::ZncE3); + zdccaltable::QxA, + zdccaltable::QxC, + zdccaltable::QyA, + zdccaltable::QyC); using ZDCCalTable = ZDCCalTables::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_ZDCCALTABLES_H_ diff --git a/PWGLF/DataModel/cascqaanalysis.h b/PWGLF/DataModel/cascqaanalysis.h index 4cb9176f99e..4b1fe3000e3 100644 --- a/PWGLF/DataModel/cascqaanalysis.h +++ b/PWGLF/DataModel/cascqaanalysis.h @@ -16,17 +16,19 @@ #ifndef PWGLF_DATAMODEL_CASCQAANALYSIS_H_ #define PWGLF_DATAMODEL_CASCQAANALYSIS_H_ -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "TRandom.h" -#include "Math/Vector4D.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + #include "Math/Boost.h" +#include "Math/Vector4D.h" +#include "TRandom.h" namespace o2::aod { diff --git a/PWGLF/DataModel/lambdaJetPolarizationIons.h b/PWGLF/DataModel/lambdaJetPolarizationIons.h new file mode 100644 index 00000000000..faa06e78b22 --- /dev/null +++ b/PWGLF/DataModel/lambdaJetPolarizationIons.h @@ -0,0 +1,151 @@ +// 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 lambdaJetPolarizationIons.h +/// \brief Derived Data table for Jet-induced polarization analysis (HI) +/// \author Cicero Domenico Muncinelli (cicero.domenico.muncinelli@cern.ch) +// Comments, questions, complaints, suggestions? +// Please write to: +// cicero.domenico.muncinelli@cern.ch +// + +#ifndef PWGLF_DATAMODEL_LAMBDAJETPOLARIZATIONIONS_H_ +#define PWGLF_DATAMODEL_LAMBDAJETPOLARIZATIONIONS_H_ + +#include + +#include + +namespace o2::aod +{ + +namespace lambdajetpol +{ +// Collision information: +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); +DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); + +// Jet (and jet proxies) information: +DECLARE_SOA_COLUMN(JetPt, jetPt, float); +DECLARE_SOA_COLUMN(JetEta, jetEta, float); +DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); +DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, int); + +DECLARE_SOA_COLUMN(LeadParticlePt, leadParticlePt, float); +DECLARE_SOA_COLUMN(LeadParticleEta, leadParticleEta, float); +DECLARE_SOA_COLUMN(LeadParticlePhi, leadParticlePhi, float); + +// V0 information: +DECLARE_SOA_COLUMN(V0Pt, v0Pt, float); +DECLARE_SOA_COLUMN(V0Eta, v0Eta, float); +DECLARE_SOA_COLUMN(V0Phi, v0Phi, float); + +DECLARE_SOA_COLUMN(IsLambda, isLambda, bool); +DECLARE_SOA_COLUMN(IsAntiLambda, isAntiLambda, bool); +DECLARE_SOA_COLUMN(MassLambda, massLambda, float); +DECLARE_SOA_COLUMN(MassAntiLambda, massAntiLambda, float); + +DECLARE_SOA_COLUMN(PosPt, posPt, float); +DECLARE_SOA_COLUMN(PosEta, posEta, float); +DECLARE_SOA_COLUMN(PosPhi, posPhi, float); +DECLARE_SOA_COLUMN(NegPt, negPt, float); +DECLARE_SOA_COLUMN(NegEta, negEta, float); +DECLARE_SOA_COLUMN(NegPhi, negPhi, float); + +DECLARE_SOA_COLUMN(PosTPCNSigmaPr, posTPCNSigmaPr, float); +DECLARE_SOA_COLUMN(PosTPCNSigmaPi, posTPCNSigmaPi, float); +DECLARE_SOA_COLUMN(NegTPCNSigmaPr, negTPCNSigmaPr, float); +DECLARE_SOA_COLUMN(NegTPCNSigmaPi, negTPCNSigmaPi, float); + +DECLARE_SOA_COLUMN(V0CosPA, v0CosPA, float); +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); +DECLARE_SOA_COLUMN(DcaV0Daughters, dcaV0Daughters, float); +DECLARE_SOA_COLUMN(DcaPosToPV, dcaPosToPV, float); +DECLARE_SOA_COLUMN(DcaNegToPV, dcaNegToPV, float); + +// Dynamic columns for jets (Px,Py,Pz): +DECLARE_SOA_DYNAMIC_COLUMN(JetPx, jetPx, //! Jet px + [](float jetPt, float jetPhi) -> float { return jetPt * std::cos(jetPhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(JetPy, jetPy, //! Jet py + [](float jetPt, float jetPhi) -> float { return jetPt * std::sin(jetPhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(JetPz, jetPz, //! Jet pz + [](float jetPt, float jetEta) -> float { return jetPt * std::sinh(jetEta); }); +// Same for leading particles: +DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePx, leadParticlePx, //! Leading particle px + [](float leadParticlePt, float leadParticlePhi) -> float { return leadParticlePt * std::cos(leadParticlePhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePy, leadParticlePy, //! Leading particle py + [](float leadParticlePt, float leadParticlePhi) -> float { return leadParticlePt * std::sin(leadParticlePhi); }); +DECLARE_SOA_DYNAMIC_COLUMN(LeadParticlePz, leadParticlePz, //! Leading particle pz + [](float leadParticlePt, float leadParticleEta) -> float { return leadParticlePt * std::sinh(leadParticleEta); }); +} // namespace lambdajetpol + +DECLARE_SOA_TABLE(RingCollisions, "AOD", "RINGCOLLISION", + o2::soa::Index<>, // self-index: auto-assigned row number + lambdajetpol::CentFT0M, + lambdajetpol::CentFT0C, + lambdajetpol::CentFV0A); + +namespace lambdajetpol +{ +DECLARE_SOA_INDEX_COLUMN(RingCollision, ringCollision); // Declare index after table is available +} // namespace lambdajetpol + +DECLARE_SOA_TABLE(RingJets, "AOD", "RINGJET", + lambdajetpol::RingCollisionId, // relational index -> RingCollisions + lambdajetpol::JetPt, + lambdajetpol::JetEta, + lambdajetpol::JetPhi, + lambdajetpol::JetNConstituents, + // Dynamic columns (explicitly bound to their static inputs): + lambdajetpol::JetPx, + lambdajetpol::JetPy, + lambdajetpol::JetPz); + +DECLARE_SOA_TABLE(RingLeadPs, "AOD", "RINGLEADP", + lambdajetpol::RingCollisionId, + lambdajetpol::LeadParticlePt, + lambdajetpol::LeadParticleEta, + lambdajetpol::LeadParticlePhi, + // Dynamic columns: + lambdajetpol::LeadParticlePx, + lambdajetpol::LeadParticlePy, + lambdajetpol::LeadParticlePz); + +DECLARE_SOA_TABLE(RingLaV0s, "AOD", "RINGLAV0", + lambdajetpol::RingCollisionId, + lambdajetpol::V0Pt, + lambdajetpol::V0Eta, + lambdajetpol::V0Phi, + lambdajetpol::IsLambda, + lambdajetpol::IsAntiLambda, + lambdajetpol::MassLambda, + lambdajetpol::MassAntiLambda, + lambdajetpol::PosPt, + lambdajetpol::PosEta, + lambdajetpol::PosPhi, + lambdajetpol::NegPt, + lambdajetpol::NegEta, + lambdajetpol::NegPhi, + lambdajetpol::PosTPCNSigmaPr, + lambdajetpol::PosTPCNSigmaPi, + lambdajetpol::NegTPCNSigmaPr, + lambdajetpol::NegTPCNSigmaPi, + lambdajetpol::V0CosPA, + lambdajetpol::V0Radius, + lambdajetpol::DcaV0Daughters, + lambdajetpol::DcaPosToPV, + lambdajetpol::DcaNegToPV); + +using RingCollision = RingCollisions::iterator; // Useful shorthand +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LAMBDAJETPOLARIZATIONIONS_H_ diff --git a/PWGLF/DataModel/lambdaJetpolarization.h b/PWGLF/DataModel/lambdaJetpolarization.h index 41bd7e26b15..55a06538986 100644 --- a/PWGLF/DataModel/lambdaJetpolarization.h +++ b/PWGLF/DataModel/lambdaJetpolarization.h @@ -16,17 +16,19 @@ #ifndef PWGLF_DATAMODEL_LAMBDAJETPOLARIZATION_H_ #define PWGLF_DATAMODEL_LAMBDAJETPOLARIZATION_H_ -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "TRandom.h" -#include "Math/Vector4D.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + #include "Math/Boost.h" +#include "Math/Vector4D.h" +#include "TRandom.h" namespace o2::aod { diff --git a/PWGLF/DataModel/spectraTOF.h b/PWGLF/DataModel/spectraTOF.h index 9cf4b789295..35811d322cd 100644 --- a/PWGLF/DataModel/spectraTOF.h +++ b/PWGLF/DataModel/spectraTOF.h @@ -19,27 +19,29 @@ #ifndef PWGLF_DATAMODEL_SPECTRATOF_H_ #define PWGLF_DATAMODEL_SPECTRATOF_H_ -#include +#include "PWGLF/DataModel/LFParticleIdentification.h" -// O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/StaticFor.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/FT0Corrected.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" #include "TPDGCode.h" +#include + static constexpr o2::track::PID::ID Np = 9; static constexpr int NCharges = 2; static constexpr o2::track::PID::ID NpCharge = Np * NCharges; diff --git a/PWGLF/TableProducer/Common/mcCentrality.cxx b/PWGLF/TableProducer/Common/mcCentrality.cxx index 1dec9b7fb28..8eaaf6fd768 100644 --- a/PWGLF/TableProducer/Common/mcCentrality.cxx +++ b/PWGLF/TableProducer/Common/mcCentrality.cxx @@ -66,12 +66,13 @@ struct McCentrality { ConfigurableAxis binsMultiplicity{"binsMultiplicity", {1000, 0, 5000}, "Binning of the multiplicity axis"}; Configurable fillFt0A{"fillFt0A", false, "Fills the FT0A histogram"}; Configurable fillFt0C{"fillFt0C", false, "Fills the FT0C histogram"}; + Configurable doNotCrashOnNull{"doNotCrashOnNull", false, "If ccdb object does not exist, fill with dummy values"}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - TH1F* h1dFT0M; - TH1F* h1dFT0A; - TH1F* h1dFT0C; + TH1F* h1dFT0M = nullptr; + TH1F* h1dFT0A = nullptr; + TH1F* h1dFT0C = nullptr; // TH1F* h1dFDD; // TH1F* h1dNTP; @@ -99,13 +100,17 @@ struct McCentrality { histos.add("FT0C/percentilevsMult", "FT0C percentile.", HistType::kTH2D, {{binsPercentile, "FT0C percentile"}, {binsMultiplicity, "FT0C mult."}}); } - TList* lOfInput; + TList* lOfInput = nullptr; if (path.value.rfind("ccdb://", 0) == 0) { // Getting post calib. from CCDB path.value.replace(0, 7, ""); lOfInput = ccdb->get(path); if (!lOfInput) { - LOG(fatal) << "Could not find the calibration TList from CCDB in path " << path; - return; + if (doNotCrashOnNull) { + LOG(info) << "Could not find the calibration TList from CCDB in path " << path << ", will fill tables with dummy values"; + } else { + LOG(fatal) << "Could not find the calibration TList from CCDB in path " << path; + return; + } } } else { // Getting post calib. from file TFile* f = TFile::Open(path.value.c_str(), "READ"); @@ -121,11 +126,18 @@ struct McCentrality { LOG(fatal) << "The input file " << path.value << " does not contain the TList ccdb_object"; } } - auto getHist = [lOfInput](const char* name) -> TH1F* { + auto getHist = [this, lOfInput](const char* name) -> TH1F* { + if (!lOfInput) { + return nullptr; + } auto hist = static_cast(lOfInput->FindObject(name)); if (!hist) { lOfInput->ls(); - LOG(fatal) << "Could not open histogram " << name << " from TList"; + if (this->doNotCrashOnNull) { + LOG(info) << "Could not open histogram " << name << " from TList, will fill tables with dummy values"; + } else { + LOG(fatal) << "Could not open histogram " << name << " from TList"; + } } return hist; }; @@ -147,13 +159,19 @@ struct McCentrality { const float nFT0M = nFT0A + nFT0C; // const float nFV0A = mCounter.countFV0A(mcParticles); - const float valueCentFT0M = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFT0M)); + float valueCentFT0M = 105.0f; + if (h1dFT0M) + valueCentFT0M = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFT0M)); if (fillFt0A) { - const float valueCentFT0A = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFT0A)); + float valueCentFT0A = 105.0f; + if (h1dFT0A) + valueCentFT0A = h1dFT0A->GetBinContent(h1dFT0A->FindBin(nFT0A)); centFT0A(valueCentFT0A); } if (fillFt0C) { - const float valueCentFT0C = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFT0C)); + float valueCentFT0C = 105.0f; + if (h1dFT0C) + valueCentFT0C = h1dFT0C->GetBinContent(h1dFT0C->FindBin(nFT0C)); centFT0C(valueCentFT0C); } // const float valueCentFV0A = h1dFT0M->GetBinContent(h1dFT0M->FindBin(nFV0A)); diff --git a/PWGLF/TableProducer/Common/spvector.cxx b/PWGLF/TableProducer/Common/spvector.cxx index 5689a5e13ef..17af2282ef4 100644 --- a/PWGLF/TableProducer/Common/spvector.cxx +++ b/PWGLF/TableProducer/Common/spvector.cxx @@ -22,6 +22,7 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" diff --git a/PWGLF/TableProducer/Common/zdcvector.cxx b/PWGLF/TableProducer/Common/zdcvector.cxx index f7a811a7b9e..6ce044dac61 100644 --- a/PWGLF/TableProducer/Common/zdcvector.cxx +++ b/PWGLF/TableProducer/Common/zdcvector.cxx @@ -22,6 +22,7 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -84,6 +85,7 @@ struct zdcvector { Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 0.0f, "Centrality cut Min"}; Configurable additionalEvSel{"additionalEvSel", false, "additionalEvSel"}; Configurable usemem{"usemem", true, "usemem"}; + Configurable usecfactor{"usecfactor", false, "use c factor"}; struct : ConfigurableGroup { Configurable vzFineNbins{"vzFineNbins", 20, "Number of bins in Vz fine histograms"}; @@ -118,6 +120,7 @@ struct zdcvector { AxisSpec vzfineAxis = {configbins.vzFineNbins, configbins.lfinebinVz, configbins.hfinebinVz, "vzfine"}; AxisSpec centfineAxis = {configbins.centFineNbins, configbins.lfinebinCent, configbins.hfinebinCent, "V0M (%) fine"}; AxisSpec VxyAxis = {2, 0, 2, "Vxy"}; + // AxisSpec EAxis = {500, 0, 1000, "Eaxis"}; histos.add("htpcnsigmapi", "htpcnsigmapi", kTH1F, {{50, -10, 10.0}}); histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); @@ -127,6 +130,14 @@ struct zdcvector { histos.add("ZDCAmp", "ZDCAmp", kTProfile2D, {channelZDCAxis, vzfineAxis}); histos.add("ZDCAmpCommon", "ZDCAmpCommon", kTProfile2D, {{2, 0.0, 2.0}, vzfineAxis}); histos.add("AvgVxy", "AvgVxy", kTProfile, {VxyAxis}); + /*histos.add("hZNA0", "hZNA0", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNA1", "hZNA1", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNA2", "hZNA2", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNA3", "hZNA3", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNC0", "hZNC0", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNC1", "hZNC1", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNC2", "hZNC2", kTH2D, {{centfineAxis}, {EAxis}}, true); + histos.add("hZNC3", "hZNC3", kTH2D, {{centfineAxis}, {EAxis}}, true);*/ ccdb->setURL(cfgCcdbParam.cfgURL); ccdbApi.init("http://alice-ccdb.cern.ch"); @@ -140,6 +151,11 @@ struct zdcvector { TH2D* gainprofile; TProfile* gainprofilevxy; + // int lastRunNumberTimeRec = -999; + // for time since start of run + // int runForStartTime = -999; + // uint64_t runStartTime = 0; + using MyCollisions = soa::Join; using AllTrackCandidates = soa::Join; @@ -175,10 +191,18 @@ struct zdcvector { if (!bc.has_zdc()) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } + // -------- define time since run start -------- + /*uint64_t ts = bc.timestamp(); + if (currentRunNumber != runForStartTime) { + runStartTime = ts; + runForStartTime = currentRunNumber; + } + double tsec = 1.e-3 * static_cast(ts - runStartTime); + */ histos.fill(HIST("hEvtSelInfo"), 1.5); auto zdc = bc.zdc(); @@ -186,10 +210,12 @@ struct zdcvector { auto znaEnergy = zdc.energySectorZNA(); auto zncEnergycommon = zdc.energyCommonZNC(); auto znaEnergycommon = zdc.energyCommonZNA(); + auto beamEne = 5.36 * 0.5; if (znaEnergycommon <= 0.0 || zncEnergycommon <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -197,14 +223,16 @@ struct zdcvector { if (znaEnergy[0] <= 0.0 || znaEnergy[1] <= 0.0 || znaEnergy[2] <= 0.0 || znaEnergy[3] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } histos.fill(HIST("hEvtSelInfo"), 3.5); if (zncEnergy[0] <= 0.0 || zncEnergy[1] <= 0.0 || zncEnergy[2] <= 0.0 || zncEnergy[3] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -212,15 +240,25 @@ struct zdcvector { if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } histos.fill(HIST("hEvtSelInfo"), 5.5); + /*histos.fill(HIST("hZNA0"), centrality, znaEnergy[0]); + histos.fill(HIST("hZNA1"), centrality, znaEnergy[1]); + histos.fill(HIST("hZNA2"), centrality, znaEnergy[2]); + histos.fill(HIST("hZNA3"), centrality, znaEnergy[3]); + histos.fill(HIST("hZNC0"), centrality, zncEnergy[0]); + histos.fill(HIST("hZNC1"), centrality, zncEnergy[1]); + histos.fill(HIST("hZNC2"), centrality, zncEnergy[2]); + histos.fill(HIST("hZNC3"), centrality, zncEnergy[3]);*/ if (additionalEvSel && (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -238,6 +276,8 @@ struct zdcvector { auto alphaZDC = 0.395; constexpr double x[4] = {-1.75, 1.75, -1.75, 1.75}; constexpr double y[4] = {-1.75, -1.75, 1.75, 1.75}; + double zncEnergycommonsum = 0.0; + double znaEnergycommonsum = 0.0; histos.fill(HIST("ZDCAmpCommon"), 0.5, vz, znaEnergycommon); histos.fill(HIST("ZDCAmpCommon"), 1.5, vz, zncEnergycommon); @@ -246,6 +286,7 @@ struct zdcvector { constexpr std::size_t ntow = 8; for (std::size_t iChA = 0; iChA < ntow; iChA++) { auto chanelid = iChA; + gainequal = 1.0; if (useGainCallib && gainprofile) { gainequal = gainprofile->GetBinContent(gainprofile->FindBin(vz + 0.00001, chanelid + 0.5)); } @@ -254,10 +295,11 @@ struct zdcvector { if (znaEnergy[iChA] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); return; } else { double ampl = gainequal * znaEnergy[iChA]; + znaEnergycommonsum += ampl; if (followpub) { ampl = std::pow(ampl, alphaZDC); } @@ -269,10 +311,12 @@ struct zdcvector { } else { if (zncEnergy[iChA - 4] <= 0.0) { triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } else { double ampl = gainequal * zncEnergy[iChA - 4]; + zncEnergycommonsum += ampl; if (followpub) { ampl = std::pow(ampl, alphaZDC); } @@ -284,13 +328,26 @@ struct zdcvector { } } + auto cZNC = 1.0; + auto cZNA = 1.0; + if (sumA > 0) { - qxZDCA = qxZDCA / sumA; - qyZDCA = qyZDCA / sumA; + float nSpecnA = znaEnergycommonsum / beamEne; + if (usecfactor) + cZNA = 1.89358 - 0.71262 / (nSpecnA + 0.71789); + else + cZNA = 1.0; + qxZDCA = cZNA * (qxZDCA / sumA); + qyZDCA = cZNA * (qyZDCA / sumA); } if (sumC > 0) { - qxZDCC = qxZDCC / sumC; - qyZDCC = qyZDCC / sumC; + float nSpecnC = zncEnergycommonsum / beamEne; + if (usecfactor) + cZNC = 1.89358 - 0.71262 / (nSpecnC + 0.71789); + else + cZNC = 1.0; + qxZDCC = cZNC * (qxZDCC / sumC); + qyZDCC = cZNC * (qyZDCC / sumC); } if (sumA <= 1e-4 || sumC <= 1e-4) { @@ -299,7 +356,8 @@ struct zdcvector { qyZDCA = 0.0; qyZDCC = 0.0; triggerevent = false; - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, 0.0, 0.0, 0.0, 0.0); + // zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); return; } @@ -314,6 +372,8 @@ struct zdcvector { gainprofilevxy = ccdb->getForTimeStamp(confGainPathVxy.value, bc.timestamp()); } + // LOG(info)<<"*****time stamp is:"<GetBinContent(1); vy = vy - gainprofilevxy->GetBinContent(2); @@ -321,7 +381,7 @@ struct zdcvector { lastRunNumber = currentRunNumber; } - zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3]); + zdccaltable(triggerevent, currentRunNumber, centrality, vx, vy, vz, qxZDCA, qxZDCC, qyZDCA, qyZDCC); } }; diff --git a/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx b/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx index c32d68a539a..a54cd34bca9 100644 --- a/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx +++ b/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx @@ -247,6 +247,7 @@ struct LfTreeCreatorNuclei { track.hasTRD(), track.tpcInnerParam(), track.beta(), + track.pidForTracking(), track.tpcSignal(), track.pt(), track.eta(), track.phi(), track.sign(), diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index 024ad6fb6f7..8e1e0431010 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -123,6 +123,9 @@ struct decay3bodyBuilder { Configurable doVertexQA{"doVertexQA", false, "Flag to fill QA histograms for PV of (selected) events."}; Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROF border cut"}; + // MC processing options + Configurable doStoreMcBkg{"doStoreMcBkg", false, "Flag to store candidates which were not matched to true H3L/Anti-H3L decaying via three-body decay in MC (i.e. MC background) in the output table"}; + // data processing options Configurable doSkimmedProcessing{"doSkimmedProcessing", false, "Apply Zoroo counting in case of skimmed data input"}; Configurable triggerList{"triggerList", "fTriggerEventF1Proton, fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega, fGammaVeryLowPtEMCAL, fGammaVeryLowPtDCAL, fGammaHighPtEMCAL, fGammaLowPtEMCAL, fGammaVeryHighPtDCAL, fGammaVeryHighPtEMCAL, fGammaLowPtDCAL, fJetNeutralLowPt, fJetNeutralHighPt, fGammaHighPtDCAL, fJetFullLowPt, fJetFullHighPt, fEMCALReadout, fPCMandEE, fPHOSnbar, fPCMHighPtPhoton, fPHOSPhoton, fLD, fPPPHI, fPD, fLLL, fPLL, fPPL, fPPP, fLeadingPtTrack, fHighFt0cFv0Flat, fHighFt0cFv0Mult, fHighFt0Flat, fHighFt0Mult, fHighMultFv0, fHighTrackMult, fHfSingleNonPromptCharm3P, fHfSingleNonPromptCharm2P, fHfSingleCharm3P, fHfPhotonCharm3P, fHfHighPt2P, fHfSigmaC0K0, fHfDoubleCharm2P, fHfBeauty3P, fHfFemto3P, fHfFemto2P, fHfHighPt3P, fHfSigmaCPPK, fHfDoubleCharm3P, fHfDoubleCharmMix, fHfPhotonCharm2P, fHfV0Charm2P, fHfBeauty4P, fHfV0Charm3P, fHfSingleCharm2P, fHfCharmBarToXiBach, fSingleMuHigh, fSingleMuLow, fLMeeHMR, fDiMuon, fDiElectron, fLMeeIMR, fSingleE, fTrackHighPt, fTrackLowPt, fJetChHighPt, fJetChLowPt, fUDdiffLarge, fUDdiffSmall, fITSextremeIonisation, fITSmildIonisation, fH3L3Body, fHe, fH2", "List of triggers used to select events"}; @@ -794,47 +797,56 @@ struct decay3bodyBuilder { // check if daughters have MC particle if (!trackProton.has_mcParticle() || !trackPion.has_mcParticle() || !trackDeuteron.has_mcParticle()) { - continue; - } + if (!doStoreMcBkg) { + continue; // if not storing MC background, skip candidates where at least one daughter is not matched to MC particle + } else { + this3BodyMCInfo.label = -5; // at least one non-matched daughter + // fill analysis table (only McVtx3BodyDatas is filled here) + fillAnalysisTables(); + } + } else { // all daughters are matched to MC particles, get their MC info + // get MC daughter particles + auto mcTrackProton = trackProton.template mcParticle_as(); + auto mcTrackPion = trackPion.template mcParticle_as(); + auto mcTrackDeuteron = trackDeuteron.template mcParticle_as(); + + // set daughter MC info (also for non-matched mothers) + this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode(); + this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode(); + this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode(); + this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary(); + this3BodyMCInfo.genMomProton = mcTrackProton.p(); + this3BodyMCInfo.genMomPion = mcTrackPion.p(); + this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p(); + this3BodyMCInfo.genPtProton = mcTrackProton.pt(); + this3BodyMCInfo.genPtPion = mcTrackPion.pt(); + this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt(); + + // daughters are matched to MC, now we check if reco mother is true H3L/Anti-H3l and decayed via three-body decay + this3BodyMCInfo.label = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron); // returns global index of mother if true H3L/Anti-H3L mother decaying via three-body decay, otherwise negative value + + // if not storing MC background, skip candidates where mother is not true H3L/Anti-H3L decaying via three-body decay + if (!doStoreMcBkg && this3BodyMCInfo.label <= 0) { + continue; + } - // get MC daughter particles - auto mcTrackProton = trackProton.template mcParticle_as(); - auto mcTrackPion = trackPion.template mcParticle_as(); - auto mcTrackDeuteron = trackDeuteron.template mcParticle_as(); - - // set daughter MC info (also for non-matched candidates) - this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode(); - this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode(); - this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode(); - this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary(); - this3BodyMCInfo.genMomProton = mcTrackProton.p(); - this3BodyMCInfo.genMomPion = mcTrackPion.p(); - this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p(); - this3BodyMCInfo.genPtProton = mcTrackProton.pt(); - this3BodyMCInfo.genPtPion = mcTrackPion.pt(); - this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt(); - - // check if reco mother is true H3L/Anti-H3l - bool isMuonReco; - int motherID = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron, isMuonReco); - - // get generated mother MC info - if (motherID > 0) { - auto mcTrackH3L = mcParticles.rawIteratorAt(motherID); - this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode(); - this3BodyMCInfo.label = motherID; - this3BodyMCInfo.genMomentum = {mcTrackH3L.px(), mcTrackH3L.py(), mcTrackH3L.pz()}; - this3BodyMCInfo.genDecVtx = {mcTrackProton.vx(), mcTrackProton.vy(), mcTrackProton.vz()}; - this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(mcTrackProton.vx() - mcTrackH3L.vx(), mcTrackProton.vy() - mcTrackH3L.vy(), mcTrackProton.vz() - mcTrackH3L.vz()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p(); - this3BodyMCInfo.genPhi = mcTrackH3L.phi(); - this3BodyMCInfo.genEta = mcTrackH3L.eta(); - this3BodyMCInfo.genRapidity = mcTrackH3L.y(); - this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false; - this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false; - } + // get generated mother MC info for matched candidates + if (this3BodyMCInfo.label > -1) { + auto mcTrackH3L = mcParticles.rawIteratorAt(this3BodyMCInfo.label); + this3BodyMCInfo.motherPdgCode = mcTrackH3L.pdgCode(); + this3BodyMCInfo.genMomentum = {mcTrackH3L.px(), mcTrackH3L.py(), mcTrackH3L.pz()}; + this3BodyMCInfo.genDecVtx = {mcTrackProton.vx(), mcTrackProton.vy(), mcTrackProton.vz()}; + this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(mcTrackProton.vx() - mcTrackH3L.vx(), mcTrackProton.vy() - mcTrackH3L.vy(), mcTrackProton.vz() - mcTrackH3L.vz()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p(); + this3BodyMCInfo.genPhi = mcTrackH3L.phi(); + this3BodyMCInfo.genEta = mcTrackH3L.eta(); + this3BodyMCInfo.genRapidity = mcTrackH3L.y(); + this3BodyMCInfo.isTrueH3L = this3BodyMCInfo.motherPdgCode > 0 ? true : false; + this3BodyMCInfo.isTrueAntiH3L = this3BodyMCInfo.motherPdgCode < 0 ? true : false; + } - // fill analysis tables (only McVtx3BodyDatas is filled here) - fillAnalysisTables(); + // fill analysis tables (only McVtx3BodyDatas is filled here) + fillAnalysisTables(); + } // end of check if daughters have MC particle // mark mcParticle as reconstructed if (this3BodyMCInfo.label > -1) { @@ -1094,7 +1106,7 @@ struct decay3bodyBuilder { helper.decay3body.daughterDCAtoSV[0], helper.decay3body.daughterDCAtoSV[1], helper.decay3body.daughterDCAtoSV[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.daughterDCAtoSVaverage, helper.decay3body.cosPA, helper.decay3body.ctau, - helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[2], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[3], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp helper.decay3body.tofNsigmaDeuteron, helper.decay3body.averageITSClSize[0], helper.decay3body.averageITSClSize[1], helper.decay3body.averageITSClSize[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.tpcNCl[0], helper.decay3body.tpcNCl[1], helper.decay3body.tpcNCl[2], // 0 - proton, 1 - pion, 2 - deuteron @@ -1125,7 +1137,7 @@ struct decay3bodyBuilder { helper.decay3body.daughterDCAtoSV[0], helper.decay3body.daughterDCAtoSV[1], helper.decay3body.daughterDCAtoSV[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.daughterDCAtoSVaverage, helper.decay3body.cosPA, helper.decay3body.ctau, - helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[2], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[3], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp helper.decay3body.tofNsigmaDeuteron, helper.decay3body.averageITSClSize[0], helper.decay3body.averageITSClSize[1], helper.decay3body.averageITSClSize[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.tpcNCl[0], helper.decay3body.tpcNCl[1], helper.decay3body.tpcNCl[2], // 0 - proton, 1 - pion, 2 - deuteron @@ -1179,30 +1191,23 @@ struct decay3bodyBuilder { // ______________________________________________________________ // function to check if a reconstructed mother is a true H3L/Anti-H3L (returns -1 if not) template - int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe, bool& isMuonReco) + int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe) { - if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron) { - return -1; - } - // check proton and deuteron mother - int prDeMomID = -1; - for (const auto& motherPr : mcParticlePr.template mothers_as()) { - for (const auto& motherDe : mcParticleDe.template mothers_as()) { - if (motherPr.globalIndex() == motherDe.globalIndex() && std::abs(motherPr.pdgCode()) == o2::constants::physics::Pdg::kHyperTriton) { - prDeMomID = motherPr.globalIndex(); - break; - } - } - } - if (prDeMomID == -1) { - return -1; - } - if (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus) { - return -1; + // return legend + // -4: proton, pion, or deuteron have wrong identity + // -3: proton and pion have a common mother which is a Lambda (i.e., not a direct daughter of hypertriton) + // -2: proton, pion, and deuteron don't have a common mother + // -1: proton, pion, and deuteron have common mother but it's NOT a hypertriton + // global mother ID: proton, pion, and deuteron have common mother and it's a hypertriton + + // first, check identity of MC daughters + if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron || (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus)) { + return -4; } // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi auto mcParticlePiTmp = mcParticlePi; if (std::abs(mcParticlePiTmp.pdgCode()) == PDG_t::kMuonMinus) { + bool isMuonReco = false; for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { if (std::abs(motherPi.pdgCode()) == PDG_t::kPiPlus) { mcParticlePiTmp = motherPi; @@ -1210,14 +1215,45 @@ struct decay3bodyBuilder { break; } } + // If the track is a muon but none of its mothers is a pi+, treat as wrong identity + if (!isMuonReco) { + return -4; + } + } + + // now first check if the proton and pion have the same mother and it is a Lambda + for (const auto& motherPr : mcParticlePr.template mothers_as()) { + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (motherPr.globalIndex() == motherPi.globalIndex() && std::abs(motherPr.pdgCode()) == PDG_t::kLambda0) { + return -3; + } + } } - // now loop over the pion mother - for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (motherPi.globalIndex() == prDeMomID) { - return motherPi.globalIndex(); + + // now check if all three daughters have the same mother + int momID = -1; + int momPdgCode = 0; + for (const auto& motherPr : mcParticlePr.template mothers_as()) { + for (const auto& motherDe : mcParticleDe.template mothers_as()) { + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (motherPr.globalIndex() == motherDe.globalIndex() && motherPr.globalIndex() == motherPi.globalIndex()) { + momID = motherPr.globalIndex(); + momPdgCode = motherPr.pdgCode(); + break; + } + } } } - return -1; + if (momID == -1) { + return -2; + } + + // check if the common mother is a hypertriton + if (std::abs(momPdgCode) == o2::constants::physics::Pdg::kHyperTriton) { + return momID; + } else { + return -1; // common mother found but not a hypertriton + } } // ______________________________________________________________ diff --git a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx index ddb6db7af84..16379b55d2d 100644 --- a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx +++ b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx @@ -93,6 +93,24 @@ float calculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, fl { 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)); } +void encode16bit(int const& n, uint8_t& low, uint8_t& up) +{ + if (n >= (1 << 16)) { + low = up = -1; + return; + } else { + low = up = 0; + } + int bByte = 8; + for (int b{0}; b < bByte; ++b) { + int bL = (n & (1 << b)) >> b; + int bU = (n & (1 << (b + bByte))) >> (b + bByte); + if (bL > 0) + low += (1 << b); + if (bU > 0) + up += (1 << b); + } +} } // namespace struct CandidateV0 { @@ -184,6 +202,7 @@ struct EbyeMaker { uint8_t nTrackletsColl; uint8_t nTracksColl; uint8_t nChPartGen; + int nTracksCollFull; Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {kBetheBlochDefault[0], 2, 6, particleNamesPar, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; @@ -194,6 +213,8 @@ struct EbyeMaker { const AxisSpec zVtxAxis{100, -20.f, 20.f, "vertex z in cm"}; const AxisSpec nTpcAxis{160, 0, 160, "N TPC"}; const AxisSpec dcaAxis{2000, -1., 1., "DCA in cm"}; + const AxisSpec phiAxis{650, 0, 6.5, "#phi (rad)"}; + const AxisSpec signMomAxis{1000, -5.f, 5.f, "#it{p}_{T}/#it{Z} (GeV/#it{c})"}; // 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"}; @@ -231,6 +252,7 @@ struct EbyeMaker { Configurable trackNclusItsCut{"trackNclusITScut", 2, "Minimum number of ITS clusters"}; Configurable trackNclusTpcCut{"trackNclusTPCcut", 60, "Minimum number of TPC clusters"}; Configurable trackChi2Cut{"trackChi2Cut", 4.f, "Maximum chi2/ncls in TPC"}; + Configurable trackMinChi2Cut{"trackMinChi2Cut", 0.f, "Minimum chi2/ncls in TPC"}; 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"}; @@ -329,7 +351,6 @@ struct EbyeMaker { { const float defItsChi2NClCut = 36.f; const float defNClCROverFind = 0.8f; - const float defMinChi2Cut = 0.f; if (std::abs(track.eta()) > etaMax) { return false; } @@ -337,9 +358,9 @@ struct EbyeMaker { return false; } if (track.itsNCls() < trackNclusItsCut || - track.tpcNClsCrossedRows() < defNClCROverFind * track.tpcNClsFindable() || + (track.tpcNClsCrossedRows() < defNClCROverFind * track.tpcNClsFindable() && !(doprocessRun3 || doprocessMcRun3)) || track.tpcChi2NCl() > trackChi2Cut || - track.tpcChi2NCl() < defMinChi2Cut || + track.tpcChi2NCl() < trackMinChi2Cut || track.itsChi2NCl() > defItsChi2NClCut) { return false; } @@ -517,7 +538,7 @@ struct EbyeMaker { // event QA histos.add("QA/zVtx", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); if (doprocessRun3) { - histos.add("QA/PvMultVsCent", ";Centrality T0C (%);#it{N}_{PV contributors};", HistType::kTH2F, {centAxis, multAxis}); + histos.add("QA/PvMultVsCent", ";Centrality FT0C (%);#it{N}_{tracks};", HistType::kTH2F, {centAxis, multAxis}); } 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}); @@ -533,8 +554,9 @@ struct EbyeMaker { // tracking variables QA histos.add("QA/tpcCRvsCls", ";#it{N}_{TPCCR};#it{N}_{TPCcls}", HistType::kTH2F, {nTpcAxis, nTpcAxis}); - histos.add("QA/dcaxyVsPt", ";#it{p}_{T} (GeV/#it{c});DCA_{#it{xy}} (cm)", HistType::kTH2F, {momAxis, dcaAxis}); - histos.add("QA/dcazVsPt", ";#it{p}_{T} (GeV/#it{c});DCA_{#it{z}} (cm)", HistType::kTH2F, {momAxis, dcaAxis}); + histos.add("QA/dcaxyVsPt", ";#it{p}_{T} (GeV/#it{c});DCA_{#it{xy}} (cm)", HistType::kTH2F, {signMomAxis, dcaAxis}); + histos.add("QA/dcazVsPt", ";#it{p}_{T} (GeV/#it{c});DCA_{#it{z}} (cm)", HistType::kTH2F, {signMomAxis, dcaAxis}); + histos.add("QA/phiVsPtVsCls", ";#it{N}^{TPC}_{CR};#it{p}_{T} (GeV/#it{c});#phi (rad)", HistType::kTH3F, {nTpcAxis, signMomAxis, phiAxis}); ptMin = std::array{antipPtMin, antidPtMin}; ptMax = std::array{antipPtMax, antidPtMax}; @@ -562,6 +584,7 @@ struct EbyeMaker { candidateV0s.clear(); nTrackletsColl = 0u; nTracksColl = 0u; + nTracksCollFull = 0; std::array dcaInfo; for (const auto& track : tracks) { @@ -573,25 +596,26 @@ struct EbyeMaker { if (!selectTrack(track)) { continue; } - histos.fill(HIST("QA/tpcCRvsCls"), track.tpcNClsCrossedRows(), track.tpcNClsFound()); - if (track.tpcNClsFound() < trackNclusTpcCut || track.tpcNClsCrossedRows() < trackNcrossedRows) - continue; auto trackParCov = getTrackParCov(track); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto dca = std::hypot(dcaInfo[0], dcaInfo[1]); auto trackPt = trackParCov.getPt(); + auto trackPhi = trackParCov.getPhi(); auto trackEta = trackParCov.getEta(); - histos.fill(HIST("QA/dcaxyVsPt"), track.pt(), dcaInfo[0]); - histos.fill(HIST("QA/dcazVsPt"), track.pt(), dcaInfo[1]); - if (std::abs(dcaInfo[0]) > dcaSigma(track.pt(), "dcaxy") || std::abs(dcaInfo[1]) > dcaSigma(track.pt(), "dcaz") || dca > dcaSigma(track.pt(), "dca")) { // dcaxy + if (track.tpcNClsFound() < trackNclusTpcCut || track.tpcNClsCrossedRows() < trackNcrossedRows) continue; - } + histos.fill(HIST("QA/dcaxyVsPt"), track.sign() > 0. ? track.pt() : -track.pt(), dcaInfo[0]); // TODO: this should rather be trackPt (likely small effect for 7 ITS clusters?) + histos.fill(HIST("QA/dcazVsPt"), track.sign() > 0. ? track.pt() : -track.pt(), dcaInfo[1]); + if (std::abs(dcaInfo[0]) > dcaSigma(track.pt(), "dcaxy") || std::abs(dcaInfo[1]) > dcaSigma(track.pt(), "dcaz") || dca > dcaSigma(track.pt(), "dca")) + continue; + histos.fill(HIST("QA/phiVsPtVsCls"), track.tpcNClsFound(), track.sign() > 0. ? trackPt : -trackPt, trackPhi); histos.fill(HIST("QA/tpcSignal"), track.tpcInnerParam(), track.tpcSignal()); - if (trackPt > ptMin[0] && trackPt < ptMax[0] && ((track.sign() < 0 && countOnlyLSTrk == TracksCharge::kNegative) || (track.sign() > 0 && countOnlyLSTrk == TracksCharge::kPositive) || (countOnlyLSTrk == TracksCharge::kAll))) + if (trackPt > ptMin[0] && trackPt < ptMax[0] && ((track.sign() < 0 && countOnlyLSTrk == TracksCharge::kNegative) || (track.sign() > 0 && countOnlyLSTrk == TracksCharge::kPositive) || (countOnlyLSTrk == TracksCharge::kAll))) { nTracksColl++; - + nTracksCollFull++; + } for (int iP{0}; iP < kNpart; ++iP) { if (trackPt < ptMin[iP] || trackPt > ptMax[iP]) { continue; @@ -622,7 +646,7 @@ struct EbyeMaker { candTrack.dcaxypv = dcaInfo[0]; candTrack.dcazpv = dcaInfo[1]; candTrack.tpcchi2 = track.tpcChi2NCl(); - candTrack.tpcncls = track.tpcNClsFound(); + candTrack.tpcncls = (doprocessRun3 || doprocessMcRun3) ? track.tpcNClsCrossedRows() : track.tpcNClsFound(); candTrack.tpcnsigma = nSigmaTPC; candTrack.tofmass = hasTof ? mass : -999.f; candTrack.globalIndex = track.globalIndex(); @@ -932,8 +956,8 @@ struct EbyeMaker { auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); v0TableThisCollision.bindExternalIndices(&tracks); - histos.fill(HIST("QA/PvMultVsCent"), centrality, collision.numContrib()); fillRecoEvent(collision, tracks, v0TableThisCollision, centrality); + histos.fill(HIST("QA/PvMultVsCent"), centrality, nTracksColl); miniCollTable(static_cast(collision.posZ() * 10), 0x0, nTrackletsColl, centrality, nTracksColl); for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) @@ -986,6 +1010,7 @@ struct EbyeMaker { histos.fill(HIST("QA/V0MvsCL0"), centralityCl0, centrality); histos.fill(HIST("QA/trackletsVsV0M"), centrality, multTracklets); + encode16bit(nTracksCollFull, nTrackletsColl, nTracksColl); miniCollTable(static_cast(collision.posZ() * 10), 0x0, nTrackletsColl, centrality, nTracksColl); for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) auto tk = tracks.rawIteratorAt(candidateTrack.globalIndex); diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index e18eff3bdf3..41e5a177282 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -15,8 +15,10 @@ /// \author Your Name (your.email@cern.ch) /// \since April 2025 +#include "PWGCF/FemtoWorld/Core/FemtoWorldMath.h" #include "PWGLF/DataModel/EPCalibrationTables.h" #include "PWGLF/DataModel/LFhe3HadronTables.h" +#include "PWGLF/Utils/nucleiUtils.h" #include "PWGLF/Utils/svPoolCreator.h" #include "Common/Core/PID/PIDTOF.h" @@ -38,7 +40,6 @@ #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" @@ -47,6 +48,7 @@ #include "Framework/HistogramRegistry.h" #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Track.h" #include @@ -92,6 +94,29 @@ constexpr int ProtonPDG = PDG_t::kProton; constexpr int He3PDG = o2::constants::physics::Pdg::kHelium3; constexpr float CommonInite = 0.0f; +float getkstar(const float pt1, const float eta1, const float phi1, const float mass1, const float z1, + const float pt2, const float eta2, const float phi2, const float mass2, const float z2) +{ + const ROOT::Math::PtEtaPhiMVector vecpart1(pt1 * z1, eta1, phi1, mass1); + const ROOT::Math::PtEtaPhiMVector vecpart2(pt2 * z2, eta2, phi2, mass2); + const ROOT::Math::PtEtaPhiMVector trackSum = vecpart1 + vecpart2; + + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + + ROOT::Math::PxPyPzMVector PartOneCMS(vecpart1); + ROOT::Math::PxPyPzMVector PartTwoCMS(vecpart2); + + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + + const ROOT::Math::PxPyPzMVector trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); +} + enum Selections { kNoCuts = 0, kTrackCuts, @@ -237,6 +262,7 @@ struct he3HadronFemto { Configurable settingCutPtMinTOFHad{"settingCutPtMinTOFHad", 0.4f, "Minimum pT to apply the TOF cut on hadrons"}; Configurable settingCutNsigmaTOF{"settingCutNsigmaTOF", 3.0f, "Value of the TOF Nsigma cut"}; + Configurable> settingEventSelections{"settingEventSelections", {nuclei::EvSelDefault[0], 8, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; Configurable settingNoMixedEvents{"settingNoMixedEvents", 5, "Number of mixed events per event"}; Configurable settingEnableBkgUS{"settingEnableBkgUS", false, "Enable US background"}; Configurable settingEnableDCAfitter{"settingEnableDCAfitter", false, "Enable DCA fitter"}; @@ -295,15 +321,17 @@ struct he3HadronFemto { HistogramRegistry mQaRegistry{ "QA", { + {"hEventSelections", "Event selections; Selection step; Counts", {HistType::kTH1D, {{nuclei::evSel::kNevSels + 1, -0.5f, static_cast(nuclei::evSel::kNevSels) + 0.5f}}}}, + {"hEvents", "Number of events processed;Counts", {HistType::kTH1F, {{1, -0.5f, 2.5f}}}}, {"hVtxZBefore", "Vertex distribution in Z before selections;Z (cm)", {HistType::kTH1F, {{400, -20.0, 20.0}}}}, {"hVtxZ", "Vertex distribution in Z;Z (cm)", {HistType::kTH1F, {{400, -20.0, 20.0}}}}, {"hCentralityFT0A", ";Centrality FT0A (%)", {HistType::kTH1F, {{100, 0, 100.0}}}}, {"hCentralityFT0C", ";Centrality FT0C (%)", {HistType::kTH1F, {{100, 0, 100.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}}}}, {"hhe3HadtInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", {HistType::kTH1F, {{300, 3.74f, 4.34f}}}}, + {"hKstarRecVsKstarGen", "; #it{k}*_{gen} (GeV/#it{c}); #it{k}*_{rec} (GeV/#it{c})", {HistType::kTH2F, {{400, 0.f, 0.8f}, {400, 0.f, 0.8f}}}}, {"He3/hDCAxyHe3", "^{3}He;DCA_{xy} (cm)", {HistType::kTH1F, {{200, -0.5f, 0.5f}}}}, {"He3/hDCAzHe3", "^{3}He;DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, @@ -319,16 +347,16 @@ struct he3HadronFemto { {"Had/hNClsHadITS", "had;N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, {"Had/hChi2NClHadITS", "had;Chi2_{ITS} Ncluster", {HistType::kTH1F, {{100, 0, 100.0f}}}}, {"Had/hHadronPt", "had; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{120, -3.0f, 3.0f}}}}, - {"Had/h2NsigmaHadronITS", "NsigmaHadron ITS distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{ITS}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"Had/h2NsigmaHadronITS_preselection", "NsigmaHadron ITS distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"Had/h2NsigmaHadronTPC", "NsigmaHadron TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"Had/h2NsigmaHadronTPC_preselection", "NsigmaHadron TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"Had/h2NsigmaHadronTPC_mcBackground", "NsigmaHadron TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"Had/h2NsigmaHadronTPC_mcSignal", "NsigmaHadron TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"Had/h2NsigmaHadronTOF", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"Had/h2NsigmaHadronTOF_preselection", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"Had/h2NsigmaHadronTOF_mcBackground", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"Had/h2NsigmaHadronTOF_mcSignal", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronITS", "NsigmaHadron ITS distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{ITS}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"Had/h2NsigmaHadronITS_preselection", "NsigmaHadron ITS distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronTPC", "NsigmaHadron TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"Had/h2NsigmaHadronTPC_preselection", "NsigmaHadron TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronTPC_mcBackground", "NsigmaHadron TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronTPC_mcSignal", "NsigmaHadron TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronTOF", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"Had/h2NsigmaHadronTOF_preselection", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronTOF_mcBackground", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"Had/h2NsigmaHadronTOF_mcSignal", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, }, OutputObjHandlingPolicy::AnalysisObject, false, @@ -358,8 +386,14 @@ struct he3HadronFemto { if (settingSkipAmbiTracks) { mSvPoolCreator.setSkipAmbiTracks(); } - const int numberParticle = 5; - for (int i = 0; i < numberParticle; i++) { + + mQaRegistry.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(1, "All"); + for (int iSel = 1; iSel < nuclei::evSel::kNevSels + 1; iSel++) { + mQaRegistry.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(iSel + 1, nuclei::eventSelectionLabels[iSel].c_str()); + } + + const int nBetheBlochParameters = 5; + for (int i = 0; i < nBetheBlochParameters; i++) { mBBparamsHe[i] = settingBetheBlochParams->get("He3", Form("p%i", i)); } mBBparamsHe[5] = settingBetheBlochParams->get("He3", "resolution"); @@ -423,31 +457,22 @@ struct he3HadronFemto { bool selectCollision(const Tcollision& collision, const aod::BCsWithTimestamps&) { mQaRegistry.fill(HIST("hEvents"), 0); - mQaRegistry.fill(HIST("hVtxZBefore"), collision.posZ()); auto bc = collision.template bc_as(); initCCDB(bc); - if constexpr (isMC) { - if (/*!collision.sel8() ||*/ std::abs(collision.posZ()) > settingCutVertex) { - return false; - } - } else { - - if (!collision.sel8() || std::abs(collision.posZ()) > settingCutVertex) { - return false; - } - if (settingSkimmedProcessing) { - bool zorroSelected = mZorro.isSelected(collision.template bc_as().globalBC()); - if (zorroSelected) { - mQaRegistry.fill(HIST("hEvents"), 2); - } + if (!nuclei::eventSelection(collision, mQaRegistry, settingEventSelections, settingCutVertex)) { + return false; + } + if (settingSkimmedProcessing) { + bool zorroSelected = mZorro.isSelected(collision.template bc_as().globalBC()); + if (zorroSelected) { + mQaRegistry.fill(HIST("hEvents"), 2); } } mQaRegistry.fill(HIST("hEvents"), 1); mQaRegistry.fill(HIST("hNcontributor"), collision.numContrib()); - mQaRegistry.fill(HIST("hVtxZ"), collision.posZ()); mQaRegistry.fill(HIST("hCentralityFT0A"), collision.centFT0A()); mQaRegistry.fill(HIST("hCentralityFT0C"), collision.centFT0C()); return true; @@ -480,12 +505,20 @@ struct he3HadronFemto { template float correctPtHe3TrackedAsTriton(const Ttrack& candidate) { - if (candidate.pt() < 2.5 && candidate.pidForTracking() == o2::track::PID::Triton) + if (candidate.pt() * 2. < 2.5 && candidate.pidForTracking() == o2::track::PID::Triton) return candidate.pt() * 2. * (1. - kHePidTrkParams[0] - kHePidTrkParams[1] * candidate.pt() * 2.); return candidate.pt() * 2.; } + float correctPtHe3TrackedAsTriton(const float pt, const uint32_t pidForTracking) + { + if (pt < 2.5 && pidForTracking == o2::track::PID::Triton) + return pt * (1. - kHePidTrkParams[0] - kHePidTrkParams[1] * pt); + + return pt; + } + float computeNsigmaDCA(const float pt, const float dca, const int iSpecies, const char* dcaType = "xy") { @@ -920,7 +953,7 @@ struct he3HadronFemto { } } - void fillHistograms(const He3HadCandidate& he3Hadcand) + void fillHistograms(const He3HadCandidate& he3Hadcand, bool isMc = false) { mQaRegistry.fill(HIST("He3/hHe3Pt"), he3Hadcand.recoPtHe3()); mQaRegistry.fill(HIST("Had/hHadronPt"), he3Hadcand.recoPtHad()); @@ -931,6 +964,15 @@ struct he3HadronFemto { mQaRegistry.fill(HIST("Had/hNClsHadITS"), he3Hadcand.nclsITSHad); mQaRegistry.fill(HIST("He3/hChi2NClHe3ITS"), he3Hadcand.chi2nclITSHe3); mQaRegistry.fill(HIST("Had/hChi2NClHadITS"), he3Hadcand.chi2nclITSHad); + + if (isMc) { + const float correctedPtHe3 = correctPtHe3TrackedAsTriton(std::abs(he3Hadcand.recoPtHe3()), he3Hadcand.pidtrkHe3); + const float kstarGen = getkstar(std::abs(he3Hadcand.momHe3MC), he3Hadcand.etaHe3MC, he3Hadcand.phiHe3MC, o2::constants::physics::MassHelium3, 1., + std::abs(he3Hadcand.momHadMC), he3Hadcand.etaHadMC, he3Hadcand.phiHadMC, settingHadPDGCode == PDG_t::kPiPlus ? o2::constants::physics::MassPiPlus : o2::constants::physics::MassProton, 1.); + const float kstarRec = getkstar(std::abs(correctedPtHe3), he3Hadcand.recoEtaHe3(), he3Hadcand.recoPhiHe3(), o2::constants::physics::MassHelium3, 1., + std::abs(he3Hadcand.recoPtHad()), he3Hadcand.recoEtaHad(), he3Hadcand.recoPhiHad(), settingHadPDGCode == PDG_t::kPiPlus ? o2::constants::physics::MassPiPlus : o2::constants::physics::MassProton, 1.); + mQaRegistry.fill(HIST("hKstarRecVsKstarGen"), kstarGen, kstarRec); + } } // ================================================================================================================== @@ -1186,7 +1228,7 @@ struct he3HadronFemto { filledMothers.push_back(motherParticle.globalIndex()); } - fillHistograms(he3Hadcand); + fillHistograms(he3Hadcand, /*isMc*/ true); auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); fillTable(he3Hadcand, collision, /*isMC*/ true); } diff --git a/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx index 12e6344e84e..fc5f9882729 100644 --- a/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx @@ -16,13 +16,17 @@ #include "MetadataHelper.h" #include "PWGLF/DataModel/LFHypernucleiKfTables.h" +#include "PWGLF/DataModel/LFNucleiTables.h" +#include "PWGLF/DataModel/LFPIDTOFGenericTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/Utils/pidTOFGeneric.h" -#include "Common/Core/PID/TPCPIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -33,20 +37,19 @@ #include "DCAFitter/DCAFitterN.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" -#include "TRandom3.h" - #include #include +#include #include #include @@ -64,9 +67,9 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using CollisionsFull = soa::Join; +using CollisionsFull = soa::Join; using CollisionsFullMC = soa::Join; -using TracksFull = soa::Join; +using TracksFull = soa::Join; o2::common::core::MetadataHelper metadataInfo; // Metadata helper //---------------------------------------------------------------------------------------------------------------- @@ -80,69 +83,96 @@ enum DAUGHTERS { kPion, kTriton, kHe3, kAlpha }; +enum Decays { kTwoBody = 2, + kThreeBody = 3 }; +constexpr float NoVal = -999.f; static const std::vector particleNames{"pion", "proton", "deuteron", "triton", "helion", "alpha"}; static const std::vector particlePdgCodes{211, 2212, o2::constants::physics::kDeuteron, o2::constants::physics::kTriton, o2::constants::physics::kHelium3, o2::constants::physics::kAlpha}; static const std::vector particleMasses{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron, o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3, o2::constants::physics::MassAlpha}; static const std::vector particleCharge{1, 1, 1, 1, 2, 2}; -const int nBetheParams = 6; -static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; -constexpr double betheBlochDefault[nDaughterParticles][nBetheParams]{ - {13.611469, 3.598765, -0.021138, 2.039562, 0.651040, 0.09}, // pion - {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09}, // proton - {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09}, // deuteron - {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09}, // triton - {-126.557359, -0.858569, 1.111643, 1.210323, 2.656374, 0.09}, // helion - {-126.557359, -0.858569, 1.111643, 1.210323, 2.656374, 0.09}}; // alpha - -const int nTrkSettings = 15; -static const std::vector trackPIDsettingsNames{"useBBparams", "minITSnCls", "minTPCnCls", "maxTPCchi2", "maxITSchi2", "minRigidity", "maxRigidity", "maxTPCnSigma", "TOFrequiredabove", "minTOFmass", "maxTOFmass", "minDcaToPvXY", "minDcaToPvZ", "minITSclsSize", "maxITSclsSize"}; -constexpr double trackPIDsettings[nDaughterParticles][nTrkSettings]{ - {0, 0, 60, 3.0, 5000, 0.15, 1.2, 2.5, -1, 0, 100, 0., 0., 0., 1000}, - {1, 0, 70, 2.5, 5000, 0.20, 4.0, 3.0, -1, 0, 100, 0., 0., 0., 1000}, - {1, 0, 70, 5.0, 5000, 0.50, 5.0, 3.0, -1, 0, 100, 0., 0., 0., 1000}, - {1, 0, 70, 5.0, 5000, 0.50, 5.0, 3.0, -1, 0, 100, 0., 0., 0., 1000}, - {1, 0, 75, 1.5, 5000, 0.50, 5.0, 3.0, -1, 0, 100, 0., 0., 0., 1000}, - {1, 0, 70, 1.5, 5000, 0.50, 5.0, 3.0, -1, 0, 100, 0., 0., 0., 1000}}; +const int nBetheParams = 8; +enum BBPAR { kP0, + kP1, + kP2, + kP3, + kP4, + kResolution, + kMip, + kExp }; +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution", "mip", "exp"}; +constexpr double BetheBlochDefault[nDaughterParticles][nBetheParams]{ + {13.611469, 3.598765, -0.021138, 2.039562, 0.651040, 0.09, 1., 0.}, // pion + {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09, 1., 0.}, // proton + {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09, 1., 0.}, // deuteron + {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09, 1., 0.}, // triton + {-126.557359, -0.858569, 1.111643, 1.210323, 2.656374, 0.09, 1., 0.}, // helion + {-126.557359, -0.858569, 1.111643, 1.210323, 2.656374, 0.09, 1., 0.}}; // alpha + +const int nTrkSettings = 18; +enum TRACKPIDSETTINGS { kPIDmethodTPC, + kMinITSnCls, + kMinTPCnCls, + kMaxTPCchi2, + kMaxITSchi2, + kMinRigidity, + kMaxRigidity, + kMaxTPCnSigma, + kMaxITSnSigma, + kTOFrequiredabove, + kMinTOFmass, + kMaxTOFmass, + kMinDcaToPvXY, + kMinDcaToPvZ, + kMinITSmeanClsSize, + kMaxITSmeanClsSize, + kTrackCharge, + kUsePVcontributors }; +static const std::vector trackPIDsettingNames{"PIDmethodTPC", "minITSnCls", "minTPCnCls", "maxTPCchi2", "maxITSchi2", "minRigidity", "maxRigidity", "maxTPCnSigma", "maxITSnSigma", "TOFrequiredabove", "minTOFmass", "maxTOFmass", "minDcaToPvXY", "minDcaToPvZ", "minITSclsSize", "maxITSclsSize", "trackCharge", "usePVcontributors"}; +constexpr double TrackPIDsettings[nDaughterParticles][nTrkSettings]{ + {0, 0, 60, 3.0, 5000, 0.15, 1.2, 2.5, 3.0, -1, 0, 100, 0., 0., 0., 1000, 0, 0}, + {1, 0, 70, 2.5, 5000, 0.20, 4.0, 3.0, 3.0, -1, 0, 100, 0., 0., 0., 1000, 0, 0}, + {1, 0, 70, 5.0, 5000, 0.50, 5.0, 3.0, 3.0, -1, 0, 100, 0., 0., 0., 1000, 0, 0}, + {1, 0, 70, 5.0, 5000, 0.50, 5.0, 3.0, 3.0, -1, 0, 100, 0., 0., 0., 1000, 0, 0}, + {1, 0, 75, 1.5, 5000, 0.50, 5.0, 3.0, 3.0, -1, 0, 100, 0., 0., 0., 1000, 0, 0}, + {1, 0, 70, 1.5, 5000, 0.50, 5.0, 3.0, 3.0, -1, 0, 100, 0., 0., 0., 1000, 0, 0}}; static const int nHyperNuclei = 10; static const std::vector hyperNucNames{"L->p+pi", "3LH->3He+pi", "3LH->d+p+pi", "4LH->4He+pi", "4LH->t+p+pi", "4LHe->3He+p+pi", "5LHe->4He+p+pi", "5LHe->3He+d+pi", "custom1", "custom2"}; -static const std::vector hyperNucEnabledLb{"enabled"}; -static const std::vector reduceLb{"reduce factor"}; -constexpr int hyperNucEnabled[nHyperNuclei][1]{{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}}; -constexpr float reduceFactor[nHyperNuclei][1]{{1.}, {1.}, {1.}, {1.}, {1.}, {1.}, {1.}, {1.}, {1.}, {1.}}; -static const std::vector hyperNucPdgLb{"PDG code"}; -static constexpr int hyperNucPdgCodes[nHyperNuclei][1]{ - {3122}, - {o2::constants::physics::kHyperTriton}, - {o2::constants::physics::kHyperTriton}, - {o2::constants::physics::kHyperHydrogen4}, - {o2::constants::physics::kHyperHydrogen4}, - {o2::constants::physics::kHyperHelium4}, - {o2::constants::physics::kHyperHelium5}, - {o2::constants::physics::kHyperHelium5}, - {0}, - {0}}; -static const std::vector hyperNucDaughtersLb{"daughter1", "daughter2", "daughter3", "daughter4"}; -static const std::string hyperNucDaughters[nHyperNuclei][4]{{"proton", "pion", "none", "none"}, {"helion", "pion", "none", "none"}, {"deuteron", "proton", "pion", "none"}, {"alpha", "pion", "none", "none"}, {"triton", "proton", "pion", "none"}, {"helion", "proton", "pion", "none"}, {"alpha", "proton", "pion", "none"}, {"helion", "deuteron", "pion", "none"}, {"none", "none", "none", "none"}, {"none", "none", "none", "none"}}; // NOLINT: runtime/string -static const std::string hyperNucSigns[nHyperNuclei][4]{{"+", "-", "", ""}, {"+", "-", "", ""}, {"+", "+", "-", ""}, {"+", "-", "", ""}, {"+", "+", "-", ""}, {"+", "+", "-", ""}, {"+", "+", "-", ""}, {"+", "+", "-", ""}, {"", "", "", ""}, {"", "", "", ""}}; // NOLINT: runtime/string +static const int nHypNucDefs = 8; +enum HYPNUCDEFS { kEnabled, + kPdgCode, + kD1, + kD2, + kD3, + kD4, + kDsigns, + kUseV0for }; +static const std::vector hypNucDefsLb{"Enabled", "PDGCode", "d1", "d2", "d3", "d4", "daughterSigns", "useV0for"}; +const std::string hypNucDefs[nHyperNuclei][nHypNucDefs]{// NOLINT: runtime/string + {"0", "3122", "proton", "pion", "none", "none", "+-", ""}, + {"0", "1010010030", "helion", "pion", "none", "none", "+-", ""}, + {"0", "1010010030", "deuteron", "proton", "pion", "none", "++-", ""}, + {"0", "1010010040", "alpha", "pion", "none", "none", "+-", ""}, + {"0", "1010010040", "triton", "proton", "pion", "none", "++-", ""}, + {"0", "1010020040", "helion", "proton", "pion", "none", "++-", ""}, + {"0", "1010020050", "alpha", "proton", "pion", "none", "++-", ""}, + {"0", "1010020050", "helion", "deuteron", "pion", "none", "++-", ""}, + {"0", "0", "none", "none", "none", "none", "", ""}, + {"0", "0", "none", "none", "none", "none", "", ""}}; + const int nSelPrim = 8; +enum PRESELECTIONSPRIMARIES { kMinMass, + kMaxMass, + kMinCt, + kMaxCt, + kMinCosPa, + kMaxDcaTracks, + kMaxDcaMotherToPvXY, + kMaxDcaMotherToPvZ }; static const std::vector preSelectionPrimNames{"minMass", "maxMass", "minCt", "maxCt", "minCosPa", "maxDcaTracks", "maxDcaMotherToPvXY", "maxDcaMotherToPvZ"}; -constexpr double preSelectionsPrimaries[nHyperNuclei][nSelPrim]{ - {1.00, 1.30, 0, 50, 0.90, 100., 2.0, 5.0}, - {2.96, 3.04, 0, 30, 0.99, 100., 1.5, 4.0}, - {2.96, 3.04, 0, 30, 0.99, 100., 1.5, 4.0}, - {3.87, 3.97, 0, 30, 0.95, 100., 2.0, 5.0}, - {3.87, 3.97, 0, 30, 0.95, 100., 2.0, 5.0}, - {3.85, 3.99, 0, 30, 0.98, 100., 1.5, 4.0}, - {4.60, 5.20, 0, 100, -1., 100., 10., 10.}, - {4.60, 5.20, 0, 100, -1., 100., 10., 10.}, - {0.00, 9.90, 0, 100, -1., 100., 10., 10.}, - {0.00, 9.90, 0, 100, -1., 100., 10., 10.}}; -const int nSelSec = 8; -static const std::vector preSelectionSecNames{"minMass", "maxMass", "minCt", "maxCt", "minCosPaSv", "maxDcaTracks", "maxDcaMotherToSvXY", "maxDcaMotherToSvZ"}; -constexpr double preSelectionsSecondaries[nHyperNuclei][nSelSec]{ +constexpr double PreSelectionsPrimaries[nHyperNuclei][nSelPrim]{ {1.00, 1.30, 0, 50, 0.90, 100., 2.0, 5.0}, {2.96, 3.04, 0, 30, 0.99, 100., 1.5, 4.0}, {2.96, 3.04, 0, 30, 0.99, 100., 1.5, 4.0}, @@ -153,83 +183,83 @@ constexpr double preSelectionsSecondaries[nHyperNuclei][nSelSec]{ {4.60, 5.20, 0, 100, -1., 100., 10., 10.}, {0.00, 9.90, 0, 100, -1., 100., 10., 10.}, {0.00, 9.90, 0, 100, -1., 100., 10., 10.}}; - -static const int nCascades = 6; -static const std::vector cascadeNames{"4LLH->4LHe+pi", "4XHe->4LHe+pi", "custom1", "custom2", "custom3", "custom4"}; -constexpr int cascadeEnabled[nCascades][1]{{0}, {0}, {0}, {0}, {0}, {0}}; -constexpr int cascadePdgCodes[nCascades][1]{ - {1020010040}, - {1120020040}, - {0}, - {0}, - {0}, - {0}}; -static const std::vector cascadeHypDaughterLb{"hypernucleus"}; -static const std::string cascadeHypDaughter[nCascades][1]{{"4LHe->3He+p+pi"}, {"4LHe->3He+p+pi"}, {"none"}, {"none"}, {"none"}, {"none"}}; // NOLINT: runtime/string -static const std::vector cascadeDaughtersLb{"daughter2", "daughter3", "daughter4"}; -static const std::string cascadeDaughters[nCascades][3]{{"pion", "none", "none"}, {"pion", "none", "none"}, {"none", "none", "none"}, {"none", "none", "none"}, {"none", "none", "none"}, {"none", "none", "none"}}; // NOLINT: runtime/string -static const std::string cascadeSigns[nCascades][4]{{"+", "-", "", ""}, {"+", "-", "", ""}, {"", "", "", ""}, {"", "", "", ""}, {"", "", "", ""}, {"", "", "", ""}}; // NOLINT: runtime/string -const int nSelCas = 8; -static const std::vector preSelectionCascadeNames{"minMass", "maxMass", "minCt", "maxCt", "minCosPa", "maxDcaTracks", "maxDcaMotherToPvXY", "maxDcaMotherToPvZ"}; -constexpr double preSelectionsCascades[nCascades][nSelCas]{ - {4.00, 4.20, 0, 30, 0.95, 100., 2.0, 5.}, - {4.00, 4.20, 0, 30, 0.95, 100., 2.0, 5.}, - {0.00, 9.90, 0, 100, -1., 100., 10., 10.}, - {0.00, 9.90, 0, 100, -1., 100., 10., 10.}, - {0.00, 9.90, 0, 100, -1., 100., 10., 10.}, - {0.00, 9.90, 0, 100, -1., 100., 10., 10.}}; //---------------------------------------------------------------------------------------------------------------- + struct DaughterParticle { TString name; int pdgCode, charge; - double mass, resolution; - std::array betheParams; + double mass; + std::array betheParams; + std::array trkSettings; bool active; - DaughterParticle(std::string name_, int pdgCode_, double mass_, int charge_, LabeledArray bethe) : name(name_), pdgCode(pdgCode_), charge(charge_), mass(mass_), active(false) + DaughterParticle(std::string name_, int pdgCode_, double mass_, int charge_, LabeledArray bethe, LabeledArray settings) : name(name_), pdgCode(pdgCode_), charge(charge_), mass(mass_), active(false) { - resolution = bethe.get(name, "resolution"); - for (unsigned int i = 0; i < betheParams.size(); i++) + for (unsigned int i = 0; i < betheParams.size(); i++) { betheParams[i] = bethe.get(name, i); + } + for (unsigned int i = 0; i < trkSettings.size(); i++) { + trkSettings[i] = settings.get(name, i); + } + } + float getTPCnSigmaBB(float rigidity, float tpcSignal) + { + float expBethe = betheParams[kMip] * std::pow(charge, betheParams[kExp]) * o2::common::BetheBlochAleph(static_cast(charge * rigidity / mass), betheParams[kP0], betheParams[kP1], betheParams[kP2], betheParams[kP3], betheParams[kP4]); + return (tpcSignal - expBethe) / (expBethe * betheParams[kResolution]); } - int getCentralPIDIndex() { return getPIDIndex(pdgCode); } }; // struct DaughterParticle struct HyperNucleus { TString name; int pdgCode; bool active, savePrimary; - std::vector daughters, daughterTrackSigns; - HyperNucleus(std::string name_, int pdgCode_, bool active_, std::vector daughters_, std::vector daughterTrackSigns_) : pdgCode(pdgCode_), active(active_), savePrimary(active_) + std::vector daughters, daughterTrackSigns, v0DaughterVec; + std::vector primSettings; + HyperNucleus(std::string name_, int pdgCode_, bool active_, std::vector daughters_, std::vector daughterTrackSigns_, std::vector v0DaughterVec_, LabeledArray primSettings_) : pdgCode(pdgCode_), active(active_), savePrimary(active_) { - init(name_, daughters_, daughterTrackSigns_); + init(name_, daughters_, daughterTrackSigns_, v0DaughterVec_); + for (unsigned int i = 0; i < nSelPrim; i++) { + primSettings.push_back(primSettings_.get(name, i)); + } } HyperNucleus(std::string name_, int pdgCode_, bool active_, int hypDaughter, std::vector daughters_, std::vector daughterTrackSigns_) : pdgCode(pdgCode_), active(active_), savePrimary(active_) { daughters.push_back(hypDaughter); init(name_, daughters_, daughterTrackSigns_); } - void init(std::string name_, std::vector daughters_, std::vector daughterTrackSigns_) + void init(std::string name_, std::vector daughters_, std::vector daughterTrackSigns_, std::vector v0DaughterVec_ = {}) { name = TString(name_); for (const int& d : daughters_) daughters.push_back(d); for (const int& dc : daughterTrackSigns_) daughterTrackSigns.push_back(dc); + for (const int& dv0 : v0DaughterVec_) + v0DaughterVec.push_back(dv0 - 1); } int getNdaughters() { return static_cast(daughters.size()); } + std::vector getV0daughters() { return v0DaughterVec; } + std::vector getNonV0daughters() + { + std::vector vec; + for (int daughter = 0; daughter < getNdaughters(); daughter++) { + if (std::find(v0DaughterVec.begin(), v0DaughterVec.end(), daughter) == v0DaughterVec.end()) + vec.push_back(daughter); + } + return vec; + }; const char* motherName() { return name.Contains("->") ? ((TString)name(0, name.First("-"))).Data() : name.Data(); } const char* daughterNames() { return name.Contains("->") ? ((TString)name(name.First("-") + 2, name.Length())).Data() : ""; } }; // struct HyperNucleus struct DaughterKf { + static int uniqueId; int64_t daughterTrackId; - int species, hypNucId; + int id, species, sign, hypNucId; KFParticle daughterKfp; float dcaToPv, dcaToPvXY, dcaToPvZ, tpcNsigma, tpcNsigmaNLP, tpcNsigmaNHP; bool active; std::vector vtx; - DaughterKf(int species_, int64_t daughterTrackId_, std::vector vtx_, float tpcNsigma_, float tpcNsigmaNLP_, float tpcNsigmaNHP_) : daughterTrackId(daughterTrackId_), species(species_), hypNucId(-1), tpcNsigma(tpcNsigma_), tpcNsigmaNLP(tpcNsigmaNLP_), tpcNsigmaNHP(tpcNsigmaNHP_), vtx(vtx_) {} - DaughterKf(int species_, KFParticle daughterKfp_, int hypNucId_) : daughterTrackId(-999), species(species_), hypNucId(hypNucId_), daughterKfp(daughterKfp_), dcaToPv(-999), dcaToPvXY(-999), dcaToPvZ(-999) {} + DaughterKf(int species_, int64_t daughterTrackId_, int sign_, std::vector vtx_, float tpcNsigma_, float tpcNsigmaNLP_, float tpcNsigmaNHP_) : daughterTrackId(daughterTrackId_), id(uniqueId++), species(species_), sign(sign_), hypNucId(-1), tpcNsigma(tpcNsigma_), tpcNsigmaNLP(tpcNsigmaNLP_), tpcNsigmaNHP(tpcNsigmaNHP_), vtx(vtx_) {} void addKfp(KFParticle daughterKfp_) { daughterKfp = daughterKfp_; @@ -237,9 +267,10 @@ struct DaughterKf { dcaToPv = daughterKfp.GetDistanceFromVertex(&vtx[0]); dcaToPvZ = std::sqrt(dcaToPv * dcaToPv - dcaToPvXY * dcaToPvXY); } - bool isTrack() { return daughterTrackId >= 0; } -}; // struct DaughterKf +}; +int DaughterKf::uniqueId = 0; +// struct DaughterKf struct HyperNucCandidate { int species; @@ -249,11 +280,11 @@ struct HyperNucCandidate { std::vector recoSV; std::vector> daughterPosMoms; float mass, px, py, pz; - float devToPvXY, dcaToPvXY, dcaToPvZ, dcaToVtxXY, dcaToVtxZ, chi2; + float devToPvXY, dcaToPvXY, dcaToPvZ, dcaToVtxXY, dcaToVtxZ, chi2, itsMeanClsSize; bool mcTrue, isPhysPrimary, isPrimaryCandidate, isSecondaryCandidate, isUsedSecondary; int64_t mcParticleId; int tableId; - HyperNucCandidate(int species_, HyperNucCandidate* hypNucDaughter_, std::vector daughters_) : species(species_), hypNucDaughter(hypNucDaughter_), devToPvXY(999), dcaToPvXY(999), dcaToPvZ(999), dcaToVtxXY(999), dcaToVtxZ(999), chi2(999), mcTrue(false), isPhysPrimary(false), isPrimaryCandidate(false), isSecondaryCandidate(false), isUsedSecondary(false), mcParticleId(-1), tableId(-1) + HyperNucCandidate(int species_, HyperNucCandidate* hypNucDaughter_, std::vector daughters_) : species(species_), hypNucDaughter(hypNucDaughter_), devToPvXY(-999), dcaToPvXY(-999), dcaToPvZ(-999), dcaToVtxXY(-999), dcaToVtxZ(-999), chi2(-999), itsMeanClsSize(-1), mcTrue(false), isPhysPrimary(false), isPrimaryCandidate(false), isSecondaryCandidate(false), isUsedSecondary(false), mcParticleId(-1), tableId(-1) { for (const auto& d : daughters_) daughters.push_back(d); @@ -284,7 +315,7 @@ struct HyperNucCandidate { bool checkKfp() { return mass != 0 && !std::isnan(mass); } int getDaughterTableId() { return hypNucDaughter ? hypNucDaughter->tableId : -1; } bool isCascade() { return hypNucDaughter != 0; } - int getSign() + int getSign() // K0s !!!!! { if (kfp.GetQ() == 0) return daughters.front()->daughterKfp.GetQ() / std::abs(daughters.front()->daughterKfp.GetQ()); @@ -341,7 +372,7 @@ struct HyperNucCandidate { } void calcDcaToVtx(KFPVertex& vtx) { - if (devToPvXY != 999) // o2-linter: disable=magic-number (To be checked) + if (devToPvXY != NoVal) return; devToPvXY = kfp.GetDeviationFromVertexXY(vtx); dcaToPvXY = kfp.GetDistanceFromVertexXY(vtx); @@ -361,7 +392,7 @@ struct HyperNucCandidate { { if (!isCascade()) { LOGF(warning, "Primary hypernucleus has no hypernucleus daughter!"); - return -999; + return NoVal; } return calcSubDaughterMass(daughters.at(d1)->daughterKfp, hypNucDaughter->daughters.at(d2)->daughterKfp); } @@ -401,6 +432,30 @@ struct IndexPairs { } }; // struct IndexPairs +struct IndexPairsVec { + std::vector>> pairs; + IndexPairsVec() + { + pairs.resize(nDaughterParticles); + } + void add(int i, int64_t a, int b) { pairs.at(i).push_back({a, b}); } + void clear() + { + for (size_t i = 0; i < nDaughterParticles; i++) + pairs.at(i).clear(); + } + bool getIndex(int i, int64_t a, int& b) + { + for (const auto& pair : pairs.at(i)) { + if (pair.first == a) { + b = pair.second; + return true; + } + } + return false; + } +}; // struct IndexPairsVec + struct McCollInfo { bool hasRecoColl; bool passedEvSel; @@ -409,6 +464,40 @@ struct McCollInfo { McCollInfo() : hasRecoColl(false), passedEvSel(false), hasRecoParticle(false), tableIndex(-1) {} }; // struct McCollInfo +struct DaughterCombinations { + std::vector::iterator> it, itBegin, itEnd; + int nVecs, nCombinations; + bool end; + std::vector nonV0daughters; + DaughterCombinations(std::vector*>& vecs, std::vector nonV0daughters_) : nVecs(0), nCombinations(1), end(false), nonV0daughters(nonV0daughters_) + { + for (const auto& vec : vecs) { + nVecs++; + nCombinations *= vec->size(); + it.push_back(vec->begin()); + itEnd.push_back(vec->end()); + } + itBegin = it; + } + void getNextCombination(std::vector& vec) + { + int counter = 0; + for (const auto& i : it) { + vec.at(nonV0daughters.at(counter++)) = &(*i); + } + it[nVecs - 1]++; + for (int i = nVecs - 1; i && it[i] == itEnd[i]; i--) { + it[i] = itBegin[i]; + it[i - 1]++; + } + if (it[0] == itEnd[0]) + end = true; + } + void init() { it = itBegin; } + bool isEmpty() { return nCombinations == 0; } + int getNcombinations() { return nCombinations; } +}; // struct DaughterCombinations + //---------------------------------------------------------------------------------------------------------------- std::vector> hDeDx; std::vector> hInvMass; @@ -427,40 +516,26 @@ struct HypKfRecoTask { Produces outputHypNucTable; Preslice perCollision = aod::track_association::collisionId; + Preslice perCollisionV0 = o2::aod::v0::collisionId; + Preslice perCollision3b = o2::aod::decay3body::collisionId; + PresliceUnsorted perV0 = aod::strangenesstracking::v0Id; + PresliceUnsorted perDec3 = aod::strangenesstracking::decay3BodyId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable cfgSaveOnlyMcTrue{"cfgSaveOnlyMcTrue", true, "save only MCtrue candidates"}; Configurable cfgDebug{"cfgDebug", 1, "debug level"}; - Configurable cfgRigidityCorrection{"cfgRigidityCorrection", false, "apply rigidity correction"}; Configurable cfgCutEta{"cfgCutEta", 0.9f, "Eta range for tracks"}; - Configurable cfgUsePVcontributors{"cfgUsePVcontributors", true, "use tracks that are PV contibutors"}; - - Configurable> cfgHyperNucsActive{"cfgHyperNucsActive", {hyperNucEnabled[0], nHyperNuclei, 1, hyperNucNames, hyperNucEnabledLb}, "enable or disable reconstruction"}; - Configurable> cfgReduce{"cfgReduce", {reduceFactor[0], nHyperNuclei, 1, hyperNucNames, reduceLb}, "reconstruct only a percentage of all possible hypernuclei"}; - Configurable> cfgHyperNucPdg{"cfgHyperNucPdg", {hyperNucPdgCodes[0], nHyperNuclei, 1, hyperNucNames, hyperNucPdgLb}, "PDG codes"}; - Configurable> cfgHyperNucDaughters{"cfgHyperNucDaughters", {hyperNucDaughters[0], nHyperNuclei, 4, hyperNucNames, hyperNucDaughtersLb}, "Daughter particles"}; - Configurable> cfgHyperNucSigns{"cfgHyperNucSigns", {hyperNucSigns[0], nHyperNuclei, 4, hyperNucNames, hyperNucDaughtersLb}, "Daughter signs"}; - - Configurable> cfgCascadesActive{"cfgCascadesActive", {cascadeEnabled[0], nCascades, 1, cascadeNames, hyperNucEnabledLb}, "enable or disable reconstruction"}; - Configurable> cfgCascadesPdg{"cfgCascadesPdg", {cascadePdgCodes[0], nCascades, 1, cascadeNames, hyperNucPdgLb}, "PDG codes"}; - Configurable> cfgCascadeHypDaughter{"cfgCascadeHypDaughter", {cascadeHypDaughter[0], nCascades, 1, cascadeNames, cascadeHypDaughterLb}, "Hyernuclei daugther"}; - Configurable> cfgCascadeDaughters{"cfgCascadeDaughters", {cascadeDaughters[0], nCascades, 3, cascadeNames, cascadeDaughtersLb}, "Daughter particles"}; - Configurable> cfgCascadeSigns{"cfgCascadeSigns", {cascadeSigns[0], nCascades, 4, cascadeNames, hyperNucDaughtersLb}, "Daughter signs"}; - - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], nDaughterParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; - Configurable> cfgTrackPIDsettings{"cfgTrackPIDsettings", {trackPIDsettings[0], nDaughterParticles, nTrkSettings, particleNames, trackPIDsettingsNames}, "track selection and PID criteria"}; - Configurable> cfgPreSelectionsPrimaries{"cfgPreSelectionsPrimaries", {preSelectionsPrimaries[0], nHyperNuclei, nSelPrim, hyperNucNames, preSelectionPrimNames}, "selection criteria for primary hypernuclei"}; - Configurable> cfgPreSelectionsSecondaries{"cfgPreSelectionsSecondaries", {preSelectionsSecondaries[0], nHyperNuclei, nSelSec, hyperNucNames, preSelectionSecNames}, "selection criteria for secondary hypernuclei"}; - Configurable> cfgPreSelectionsCascades{"cfgPreSelectionsCascades", {preSelectionsCascades[0], nCascades, nSelCas, cascadeNames, preSelectionCascadeNames}, "selection criteria for cascade hypernuclei"}; - - // TPC PID Response - bool usePidResponse; - o2::pid::tpc::Response* response; + Configurable> cfgHypNucDefs{"cfgHypNucDefs", {hypNucDefs[0], nHyperNuclei, nHypNucDefs, hyperNucNames, hypNucDefsLb}, "Hypernuclei definition"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {BetheBlochDefault[0], nDaughterParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgTrackPIDsettings{"cfgTrackPIDsettings", {TrackPIDsettings[0], nDaughterParticles, nTrkSettings, particleNames, trackPIDsettingNames}, "track selection and PID criteria"}; + Configurable> cfgPreSelectionsPrimaries{"cfgPreSelectionsPrimaries", {PreSelectionsPrimaries[0], nHyperNuclei, nSelPrim, hyperNucNames, preSelectionPrimNames}, "selection criteria for primary hypernuclei"}; + Configurable cfgVtxCutZ{"cfgVtxCutZ", 10.0f, "Accepted z-vertex range"}; + std::map metadata; - std::array betheParams; + o2::aod::ITSResponse itsResponse; // CCDB Service ccdb; Configurable bField{"bField", -999, "bz field, -999 is automatic"}; @@ -473,63 +548,43 @@ struct HypKfRecoTask { std::vector activePdgs; std::vector daughterParticles; - std::vector> foundDaughterKfs, hypNucDaughterKfs; - std::vector> singleHyperNucCandidates, cascadeHyperNucCandidates; + std::vector> foundDaughterKfs; + std::vector> singleHyperNucCandidates; std::vector singleHyperNuclei, cascadeHyperNuclei; std::vector primVtx, cents; std::vector mcCollInfos; - IndexPairs trackIndices, mcPartIndices; + IndexPairsVec trackIndices; + IndexPairs mcPartIndices; KFPVertex kfPrimVtx; bool collHasCandidate, collHasMcTrueCandidate, collPassedEvSel, activeCascade, isMC; int64_t mcCollTableIndex; int mRunNumber, occupancy; float dBz; - TRandom3 rand; //---------------------------------------------------------------------------------------------------------------- - void init(InitContext const&) + void init(o2::framework::InitContext& context) { - isMC = false; + isMC = doprocessMC ? true : false; mRunNumber = 0; dBz = 0; - rand.SetSeed(0); - + o2::aod::ITSResponse::setParameters(context, isMC); ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - usePidResponse = false; for (unsigned int i = 0; i < nDaughterParticles; i++) { // create daughterparticles - daughterParticles.push_back(DaughterParticle(particleNames.at(i), particlePdgCodes.at(i), particleMasses.at(i), particleCharge.at(i), cfgBetheBlochParams)); - if (cfgTrackPIDsettings->get(i, "useBBparams") == 2 || cfgTrackPIDsettings->get(i, "useBBparams") == 0) // o2-linter: disable=magic-number (To be checked) - usePidResponse = true; + daughterParticles.push_back(DaughterParticle(particleNames.at(i), particlePdgCodes.at(i), particleMasses.at(i), particleCharge.at(i), cfgBetheBlochParams, cfgTrackPIDsettings)); } for (unsigned int i = 0; i < nHyperNuclei; i++) { // create hypernuclei - auto active = cfgHyperNucsActive->get(i, 0u); - auto pdg = cfgHyperNucPdg->get(i, 0u); - singleHyperNuclei.push_back(HyperNucleus(hyperNucNames.at(i), pdg, active, getDaughterVec(i, cfgHyperNucDaughters), getDaughterSignVec(i, cfgHyperNucSigns))); + auto active = cfgHypNucDefs->get(i, "Enabled") != "0"; + auto pdg = std::stoi(cfgHypNucDefs->get(i, "PDGCode")); + singleHyperNuclei.push_back(HyperNucleus(hyperNucNames.at(i), pdg, active, getDaughterVec(i, cfgHypNucDefs), getDaughterSignVec(i, cfgHypNucDefs), getV0DaughterVec(i, cfgHypNucDefs), cfgPreSelectionsPrimaries)); if (active) activePdgs.push_back(pdg); } - activeCascade = false; - for (unsigned int i = 0; i < nCascades; i++) { // create cascades - auto active = cfgCascadesActive->get(i, 0u); - auto pdg = cfgCascadesPdg->get(i, 0u); - auto hypDaughter = getHypDaughterVec(i, cfgCascadeHypDaughter); - cascadeHyperNuclei.push_back(HyperNucleus(cascadeNames.at(i), pdg, active, hypDaughter, getDaughterVec(i, cfgCascadeDaughters), getDaughterSignVec(i, cfgCascadeSigns))); - if (active) { - activePdgs.push_back(pdg); - if (!singleHyperNuclei.at(hypDaughter).active) { - singleHyperNuclei.at(hypDaughter).active = true; - activePdgs.push_back(singleHyperNuclei.at(hypDaughter).pdgCode); - } - activeCascade = true; - } - } - // define histogram axes const AxisSpec axisMagField{10, -10., 10., "magnetic field"}; const AxisSpec axisNev{3, 0., 3., "Number of events"}; @@ -554,9 +609,9 @@ struct HypKfRecoTask { hDeDx[2 * i + 1] = histos.add(Form("histdEdx_%s_Cuts", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); } // create invariant mass histograms - hInvMass.resize(nHyperNuclei + nCascades); + hInvMass.resize(nHyperNuclei); int histCount = 0; - std::vector> hypNucVectors = {singleHyperNuclei, cascadeHyperNuclei}; + std::vector> hypNucVectors = {singleHyperNuclei}; for (size_t i = 0; i < hypNucVectors.size(); i++) { for (size_t j = 0; j < hypNucVectors.at(i).size(); j++) { if (hypNucVectors.at(i).at(j).active) { @@ -568,46 +623,33 @@ struct HypKfRecoTask { } //---------------------------------------------------------------------------------------------------------------- - void findDaughterParticles(aod::TrackAssoc const& tracksByColl, TracksFull const& tracks, CollisionsFull::iterator const& coll) + void findDaughterParticles(aod::TrackAssoc const& tracksByColl, TracksFull const& tracks, CollisionsFull::iterator const&) { // track loop, store daughter candidates in std::vector for (const auto& trackId : tracksByColl) { const auto& track = tracks.rawIteratorAt(trackId.trackId()); filldedx(track, nDaughterParticles); - if (std::abs(track.eta()) > cfgCutEta) - continue; - if (!cfgUsePVcontributors && track.isPVContributor()) - continue; for (size_t i = 0; i < daughterParticles.size(); i++) { - if (track.tpcNClsFound() < cfgTrackPIDsettings->get(i, "minTPCnCls")) - continue; - if (track.tpcChi2NCl() > cfgTrackPIDsettings->get(i, "maxTPCchi2")) - continue; - if (track.itsNCls() < cfgTrackPIDsettings->get(i, "minITSnCls")) - continue; - if (track.itsChi2NCl() > cfgTrackPIDsettings->get(i, "maxITSchi2")) + if (!checkTrack(track, daughterParticles.at(i))) continue; - if (getRigidity(track) < cfgTrackPIDsettings->get(i, "minRigidity") || getRigidity(track) > cfgTrackPIDsettings->get(i, "maxRigidity")) + const float tpcNsigma = getTPCnSigma(track, daughterParticles.at(i)); + if (daughterParticles.at(i).trkSettings[kMaxTPCnSigma] >= 0 && std::abs(tpcNsigma) > daughterParticles.at(i).trkSettings[kMaxTPCnSigma]) continue; - float tpcNsigma = getTPCnSigma(track, coll, daughterParticles.at(i)); - if (std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) + const float itsNsigma = getITSnSigma(track, daughterParticles.at(i)); + if (daughterParticles.at(i).trkSettings[kMaxITSnSigma] >= 0 && std::abs(itsNsigma) > daughterParticles.at(i).trkSettings[kMaxITSnSigma]) continue; + float tpcNsigmaNlp = NoVal; + if (daughterParticles.at(i).name == "alpha") { + tpcNsigmaNlp = getTPCnSigma(track, daughterParticles.at(i - 1)); + } filldedx(track, i); - if (getMeanItsClsSize(track) < cfgTrackPIDsettings->get(i, "minITSclsSize")) - continue; - if (getMeanItsClsSize(track) > cfgTrackPIDsettings->get(i, "maxITSclsSize")) - continue; - if (cfgTrackPIDsettings->get(i, "TOFrequiredabove") >= 0 && getRigidity(track) > cfgTrackPIDsettings->get(i, "TOFrequiredabove") && (track.mass() < cfgTrackPIDsettings->get(i, "minTOFmass") || track.mass() > cfgTrackPIDsettings->get(i, "maxTOFmass"))) - continue; - float tpcNsigmaNHP = (i == kAlpha ? -999 : getTPCnSigma(track, coll, daughterParticles.at(i + 1))); - float tpcNsigmaNLP = (i == kPion ? 999 : getTPCnSigma(track, coll, daughterParticles.at(i - 1))); - foundDaughterKfs.at(i).push_back(DaughterKf(i, track.globalIndex(), primVtx, tpcNsigma, tpcNsigmaNLP, tpcNsigmaNHP)); + foundDaughterKfs.at(i).push_back(DaughterKf(i, track.globalIndex(), track.sign(), primVtx, tpcNsigma, tpcNsigmaNlp, itsNsigma)); } } // track loop } //---------------------------------------------------------------------------------------------------------------- - void checkMCTrueTracks(aod::McTrackLabels const& trackLabels, aod::McParticles const&, TracksFull const& tracks, CollisionsFull::iterator const& coll) + void checkMCTrueTracks(aod::McTrackLabels const& trackLabels, aod::McParticles const&) { for (int i = 0; i < nDaughterParticles; i++) { auto& daughterVec = foundDaughterKfs.at(i); @@ -640,17 +682,6 @@ struct HypKfRecoTask { continue; } } - if (cfgTrackPIDsettings->get(i, "useBBparams") == 0) { - const auto& trk = tracks.rawIteratorAt(it->daughterTrackId); - const auto tpcNsigmaMC = getTPCnSigmaMC(trk, coll, daughterParticles.at(i), daughterParticles.at(i)); - if (std::abs(tpcNsigmaMC) <= cfgTrackPIDsettings->get(i, "maxTPCnSigma")) { - it->tpcNsigma = tpcNsigmaMC; - it->tpcNsigmaNHP = (i == kAlpha ? -999 : getTPCnSigmaMC(trk, coll, daughterParticles.at(i), daughterParticles.at(i + 1))); - it->tpcNsigmaNLP = (i == kPion ? 999 : getTPCnSigmaMC(trk, coll, daughterParticles.at(i), daughterParticles.at(i - 1))); - } else { - daughterVec.erase(it); - } - } } } } @@ -660,7 +691,7 @@ struct HypKfRecoTask { for (size_t daughterCount = 0; daughterCount < daughterParticles.size(); daughterCount++) { daughterParticles.at(daughterCount).active = false; } - std::vector*> hypNucVectors = {&singleHyperNuclei, &cascadeHyperNuclei}; + std::vector*> hypNucVectors = {&singleHyperNuclei}; bool singleHypNucActive = false; for (size_t vec = 0; vec < hypNucVectors.size(); vec++) { for (const auto& hyperNuc : *(hypNucVectors.at(vec))) { @@ -698,7 +729,7 @@ struct HypKfRecoTask { } //---------------------------------------------------------------------------------------------------------------- - void createKFHypernuclei(TracksFull const& tracks) + void createKFHypernuclei(aod::V0s const& V0s, aod::Decay3Bodys const& decay3Bodys, aod::TrackedV0s const& trackedV0s, aod::Tracked3Bodys const& tracked3Bodys) { // loop over all hypernuclei that are to be reconstructed for (size_t hyperNucIter = 0; hyperNucIter < singleHyperNuclei.size(); hyperNucIter++) { @@ -706,165 +737,86 @@ struct HypKfRecoTask { if (!hyperNuc->active) continue; int nDaughters = hyperNuc->getNdaughters(); - std::vector::iterator> it; - int nCombinations = 1; - for (int i = 0; i < nDaughters; i++) { - nCombinations *= foundDaughterKfs.at(hyperNuc->daughters.at(i)).size(); - it.push_back(foundDaughterKfs.at(hyperNuc->daughters.at(i)).begin()); + auto nonV0daughters = hyperNuc->getNonV0daughters(); + std::vector*> nonV0daughterKfs; + for (const auto& d : nonV0daughters) { + nonV0daughterKfs.push_back(&foundDaughterKfs.at(hyperNuc->daughters.at(d))); } - if (!nCombinations) + bool hasNonV0daughters = nonV0daughters.size() > 0; + DaughterCombinations nonV0daughterComb(nonV0daughterKfs, nonV0daughters); + if (hasNonV0daughters && nonV0daughterComb.isEmpty()) continue; - const float reduceFactor = cfgReduce->get(hyperNucIter, 0u); - const float minMassPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "minMass"); - const float maxMassPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "maxMass"); - const float minCtPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "minCt"); - const float maxCtPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "maxCt"); - const float minCosPaPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "minCosPa"); - const float maxDcaTracksPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "maxDcaTracks"); - const float maxDcaMotherToPvXYPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "maxDcaMotherToPvXY"); - const float maxDcaMotherToPvZPrim = cfgPreSelectionsPrimaries->get(hyperNucIter, "maxDcaMotherToPvZ"); - const float minMassSec = cfgPreSelectionsSecondaries->get(hyperNucIter, "minMass"); - const float maxMassSec = cfgPreSelectionsSecondaries->get(hyperNucIter, "maxMass"); - const float minCtSec = cfgPreSelectionsSecondaries->get(hyperNucIter, "minCt"); - const float maxCtSec = cfgPreSelectionsSecondaries->get(hyperNucIter, "maxCt"); - const float maxDcaTracksSec = cfgPreSelectionsSecondaries->get(hyperNucIter, "maxDcaTracks"); - while (it[0] != foundDaughterKfs.at(hyperNuc->daughters.at(0)).end()) { - // check for correct signs, avoid double usage of tracks - bool passedChecks = true; - int checkSign = 0; - std::vector vec; - for (int i = 0; i < nDaughters; i++) { - const auto& daughterTrack = tracks.rawIteratorAt(it[i]->daughterTrackId); - if (!i) - checkSign = daughterTrack.sign(); - if (daughterTrack.sign() != checkSign * hyperNuc->daughterTrackSigns.at(i) || std::find(vec.begin(), vec.end(), it[i]->daughterTrackId) != vec.end()) { - passedChecks = false; - break; - } - vec.push_back(it[i]->daughterTrackId); + + auto v0daughters = hyperNuc->getV0daughters(); + bool useDecay3Body = (v0daughters.size() == Decays::kThreeBody), useV0 = (v0daughters.size() == Decays::kTwoBody); + bool hasV0daughters = useDecay3Body || useV0; + if ((useDecay3Body && !decay3Bodys.size()) || (useV0 && !V0s.size())) + continue; + auto v0Size = !hasV0daughters ? 0 : (useV0 ? V0s.size() : decay3Bodys.size()); + int v0Count = 0; + + do { + std::vector daughters; + daughters.resize(nDaughters); + std::vector trackIds; + if (useDecay3Body) { + const auto& v0 = decay3Bodys.rawIteratorAt(v0Count); + trackIds = std::vector{v0.track0Id(), v0.track1Id(), v0.track2Id()}; } - if (passedChecks && rand.Rndm() <= reduceFactor) { - std::vector daughters; + if (useV0) { + const auto& v0 = V0s.rawIteratorAt(v0Count); + trackIds = std::vector{v0.posTrackId(), v0.negTrackId()}; + } + if (hasV0daughters && !findDaughterKfComb(daughters, hyperNuc, v0daughters, trackIds)) + continue; + nonV0daughterComb.init(); + do { + if (hasNonV0daughters) + nonV0daughterComb.getNextCombination(daughters); + + // check for correct signs, avoid double usage of tracks + bool passedChecks = true; + int checkSign = daughters[0]->sign; + ; + std::vector vec; ///!!! index + sign für daughterKFs??? for (int i = 0; i < nDaughters; i++) { - daughters.push_back(&(*it[i])); + if (daughters[i]->sign != checkSign * hyperNuc->daughterTrackSigns.at(i) || std::find(vec.begin(), vec.end(), daughters[i]->id) != vec.end()) { + passedChecks = false; + break; + } + vec.push_back(daughters[i]->id); } + if (!passedChecks) + continue; HyperNucCandidate candidate(hyperNucIter, static_cast(0), daughters); // check preselections - if (candidate.checkKfp()) { - if (candidate.mass <= maxMassPrim && candidate.mass >= minMassPrim && candidate.getDcaTracks() <= maxDcaTracksPrim && candidate.getCt(primVtx) <= maxCtPrim && candidate.getCt(primVtx) >= minCtPrim && candidate.getCpa(primVtx) >= minCosPaPrim) { - candidate.calcDcaToVtx(kfPrimVtx); - if (std::abs(candidate.dcaToPvXY) <= maxDcaMotherToPvXYPrim && std::abs(candidate.dcaToPvZ) <= maxDcaMotherToPvZPrim) { - candidate.isPrimaryCandidate = true; - collHasCandidate = true; - } + if (checkPrimaryHypNuc(candidate, hyperNuc->primSettings) && hyperNuc->savePrimary) { + collHasCandidate = true; + candidate.isPrimaryCandidate = true; + if (useV0) { + auto trackedByDecay = trackedV0s.sliceBy(perV0, v0Count); + if (trackedByDecay.size()) + candidate.itsMeanClsSize = trackedByDecay.rawIteratorAt(0).itsClsSize(); } - if (activeCascade && candidate.mass <= maxMassSec && candidate.mass >= minMassSec && candidate.getDcaTracks() <= maxDcaTracksSec && candidate.getCt(primVtx) <= maxCtSec && candidate.getCt(primVtx) >= minCtSec) { - candidate.calcDcaToVtx(kfPrimVtx); - candidate.isSecondaryCandidate = true; + if (useDecay3Body) { + auto trackedByDecay = tracked3Bodys.sliceBy(perDec3, v0Count); + if (trackedByDecay.size()) + candidate.itsMeanClsSize = trackedByDecay.rawIteratorAt(0).itsClsSize(); } - if ((candidate.isPrimaryCandidate && hyperNuc->savePrimary) || (candidate.isSecondaryCandidate && activeCascade)) - singleHyperNucCandidates.at(hyperNucIter).push_back(candidate); + singleHyperNucCandidates.at(hyperNucIter).push_back(candidate); } - } - it[nDaughters - 1]++; - for (int i = nDaughters - 1; i && it[i] == foundDaughterKfs.at(hyperNuc->daughters.at(i)).end(); i--) { - it[i] = foundDaughterKfs.at(hyperNuc->daughters.at(i)).begin(); - it[i - 1]++; - } - } + } while (hasNonV0daughters && !nonV0daughterComb.end); + } while (hasV0daughters && ++v0Count < v0Size); } } //---------------------------------------------------------------------------------------------------------------- - void createKFCascades(TracksFull const& tracks) - { - // loop over all cascade hypernuclei that are to be reconstructed - for (size_t hyperNucIter = 0; hyperNucIter < cascadeHyperNuclei.size(); hyperNucIter++) { - HyperNucleus* hyperNuc = &(cascadeHyperNuclei.at(hyperNucIter)); - if (!hyperNuc->active) - continue; - int nDaughters = hyperNuc->getNdaughters(); - int nHypNucDaughters = singleHyperNucCandidates.at(hyperNuc->daughters.at(0)).size(); - for (int64_t i = 0; i < static_cast(nHypNucDaughters); i++) { - if (singleHyperNucCandidates.at(hyperNuc->daughters.at(0)).at(i).isSecondaryCandidate) { - auto hypNucDaughter = &(singleHyperNucCandidates.at(hyperNuc->daughters.at(0)).at(i)); - hypNucDaughterKfs.at(hyperNucIter).push_back(DaughterKf(hyperNuc->daughters.at(0), hypNucDaughter->kfp, i)); - } - } - int nCombinations = hypNucDaughterKfs.at(hyperNucIter).size(); - std::vector::iterator> it; - it.push_back(hypNucDaughterKfs.at(hyperNucIter).begin()); - for (int i = 1; i < nDaughters; i++) { - nCombinations *= foundDaughterKfs.at(hyperNuc->daughters.at(i)).size(); - it.push_back(foundDaughterKfs.at(hyperNuc->daughters.at(i)).begin()); - } - if (!nCombinations) - continue; - const float minMassCas = cfgPreSelectionsCascades->get(hyperNucIter, "minMass"); - const float maxMassCas = cfgPreSelectionsCascades->get(hyperNucIter, "maxMass"); - const float minCtCas = cfgPreSelectionsCascades->get(hyperNucIter, "minCt"); - const float maxCtCas = cfgPreSelectionsCascades->get(hyperNucIter, "maxCt"); - const float minCosPaCas = cfgPreSelectionsCascades->get(hyperNucIter, "minCosPa"); - const float maxDcaTracksCas = cfgPreSelectionsCascades->get(hyperNucIter, "maxDcaTracks"); - const float maxDcaMotherToPvXYCas = cfgPreSelectionsCascades->get(hyperNucIter, "maxDcaMotherToPvXY"); - const float maxDcaMotherToPvZCas = cfgPreSelectionsCascades->get(hyperNucIter, "maxDcaMotherToPvZ"); - const float minCtSec = cfgPreSelectionsSecondaries->get(hyperNuc->daughters.at(0), "minCt"); - const float maxCtSec = cfgPreSelectionsSecondaries->get(hyperNuc->daughters.at(0), "maxCt"); - const float minCosPaSvSec = cfgPreSelectionsSecondaries->get(hyperNuc->daughters.at(0), "minCosPaSv"); - const float maxDcaMotherToSvXYSec = cfgPreSelectionsSecondaries->get(hyperNuc->daughters.at(0), "maxDcaMotherToSvXY"); - const float maxDcaMotherToSvZSec = cfgPreSelectionsSecondaries->get(hyperNuc->daughters.at(0), "maxDcaMotherToSvZ"); - - while (it[0] != hypNucDaughterKfs.at(hyperNucIter).end()) { - // select hypernuclei daughter KFParticle - auto hypNucDaughter = &(singleHyperNucCandidates.at(hyperNuc->daughters.at(0)).at(it[0]->hypNucId)); - // check for correct signs - int checkSign = hypNucDaughter->getSign(); - bool passedChecks = true; - std::vector vec = hypNucDaughter->daughterTrackIds(); - for (int i = 1; i < nDaughters; i++) { - const auto& daughterTrack = tracks.rawIteratorAt(it[i]->daughterTrackId); - if (daughterTrack.sign() != checkSign * hyperNuc->daughterTrackSigns.at(i) || std::find(vec.begin(), vec.end(), it[i]->daughterTrackId) != vec.end()) { - passedChecks = false; - break; - } - vec.push_back(it[i]->daughterTrackId); - } - if (passedChecks) { - std::vector daughters; - daughters.push_back(&(*it[0])); - for (int i = 1; i < nDaughters; i++) { - daughters.push_back(&(*it[i])); - } - HyperNucCandidate candidate(hyperNucIter, hypNucDaughter, daughters); - if (candidate.checkKfp()) { - // preselections for cascade and hypernucleus daughter - if (candidate.mass <= maxMassCas && candidate.mass >= minMassCas && candidate.getDcaTracks() <= maxDcaTracksCas && candidate.getCt(primVtx) >= minCtCas && candidate.getCt(primVtx) <= maxCtCas && hypNucDaughter->getCt(candidate.recoSV) >= minCtSec && hypNucDaughter->getCt(candidate.recoSV) <= maxCtSec && candidate.getCpa(primVtx) >= minCosPaCas && hypNucDaughter->getCpa(candidate.recoSV) >= minCosPaSvSec) { - candidate.calcDcaToVtx(kfPrimVtx); - if (std::abs(candidate.dcaToPvXY) <= maxDcaMotherToPvXYCas && std::abs(candidate.dcaToPvZ) <= maxDcaMotherToPvZCas) { - hypNucDaughter->calcDcaToVtx(candidate); - if (hypNucDaughter->dcaToVtxXY <= maxDcaMotherToSvXYSec && hypNucDaughter->dcaToVtxZ <= maxDcaMotherToSvZSec) { - collHasCandidate = true; - hypNucDaughter->isUsedSecondary = true; - cascadeHyperNucCandidates.at(hyperNucIter).push_back(candidate); - } - } - } - } - } - it[nDaughters - 1]++; - for (int i = nDaughters - 1; i && it[i] == foundDaughterKfs.at(hyperNuc->daughters.at(i)).end(); i--) { - it[i] = foundDaughterKfs.at(hyperNuc->daughters.at(i)).begin(); - it[i - 1]++; - } - } - } - } //---------------------------------------------------------------------------------------------------------------- - void createMCinfo(aod::McTrackLabels const& trackLabels, aod::McCollisionLabels const&, aod::McParticles const& particlesMC, aod::McCollisions const&, bool cascadesOnly = false) + void createMCinfo(aod::McTrackLabels const& trackLabels, aod::McCollisionLabels const&, aod::McParticles const&, aod::McCollisions const&, bool cascadesOnly = false) { - // check for mcTrue: single (primary & cascade daughter) and cascade hypernuclei - std::vector*> hypNucVectors = {&singleHyperNuclei, &cascadeHyperNuclei}; - std::vector>*> candidateVectors = {&singleHyperNucCandidates, &cascadeHyperNucCandidates}; + // check for mcTrue + std::vector*> hypNucVectors = {&singleHyperNuclei}; + std::vector>*> candidateVectors = {&singleHyperNucCandidates}; const int nVecs = candidateVectors.size(); const int startVec = cascadesOnly ? 1 : 0; for (int vec = startVec; vec < nVecs; vec++) { @@ -875,19 +827,6 @@ struct HypKfRecoTask { continue; for (auto& hypCand : candidateVector->at(hyperNucIter)) { // o2-linter: disable=[const-ref-in-for-loop] (Object is non const and modified in loop) std::vector motherIds; - if (hypCand.isCascade()) { - if (!hypCand.hypNucDaughter->mcTrue) - continue; - const auto& mcPart = particlesMC.rawIteratorAt(hypCand.hypNucDaughter->mcParticleId); - if (!mcPart.has_mothers()) - continue; - for (const auto& mother : mcPart.mothers_as()) { - if (mother.pdgCode() == hyperNuc->pdgCode * hypCand.getSign()) { - motherIds.push_back(mother.globalIndex()); - break; - } - } - } for (const auto& daughter : hypCand.daughters) { if (!daughter->isTrack()) continue; @@ -937,8 +876,8 @@ struct HypKfRecoTask { primVtx.at(0), primVtx.at(1), primVtx.at(2), cents.at(0), cents.at(1), cents.at(2), occupancy, mRunNumber); - std::vector*> hypNucVectors = {&singleHyperNuclei, &cascadeHyperNuclei}; - std::vector>*> candidateVectors = {&singleHyperNucCandidates, &cascadeHyperNucCandidates}; + std::vector*> hypNucVectors = {&singleHyperNuclei}; + std::vector>*> candidateVectors = {&singleHyperNucCandidates}; for (unsigned int vec = 0; vec < candidateVectors.size(); vec++) { auto candidateVector = candidateVectors.at(vec); @@ -947,7 +886,7 @@ struct HypKfRecoTask { if (!hyperNuc->active) continue; for (auto& hypCand : candidateVector->at(hyperNucIter)) { // o2-linter: disable=const-ref-in-for-loop (Object is non const and modified in loop) - if (!hypCand.isPrimaryCandidate && !hypCand.isUsedSecondary && !hypCand.isCascade()) + if (!hypCand.isPrimaryCandidate) continue; if (saveOnlyMcTrue && !hypCand.mcTrue && !hypCand.isCascade()) continue; @@ -958,14 +897,14 @@ struct HypKfRecoTask { continue; const auto& daughterTrackId = daughter->daughterTrackId; int trackTableId; - if (!trackIndices.getIndex(daughterTrackId, trackTableId)) { + if (!trackIndices.getIndex(daughter->species, daughterTrackId, trackTableId)) { const auto& track = tracks.rawIteratorAt(daughterTrackId); outputTrackTable( daughter->species * track.sign(), track.pt(), track.eta(), track.phi(), daughter->dcaToPvXY, daughter->dcaToPvZ, track.tpcNClsFound(), track.tpcChi2NCl(), track.itsClusterSizes(), track.itsChi2NCl(), getRigidity(track), track.tpcSignal(), daughter->tpcNsigma, daughter->tpcNsigmaNHP, daughter->tpcNsigmaNLP, - track.mass(), track.isPVContributor()); + getMass2(track), track.isPVContributor()); trackTableId = outputTrackTable.lastIndex(); - trackIndices.add(daughterTrackId, trackTableId); + trackIndices.add(daughter->species, daughterTrackId, trackTableId); } vecDaugtherTracks.push_back(trackTableId); } @@ -975,7 +914,7 @@ struct HypKfRecoTask { posMom.at(0), posMom.at(1), posMom.at(2), posMom.at(3), posMom.at(4), posMom.at(5)); vecAddons.push_back(outputDaughterAddonTable.lastIndex()); } - if (hypCand.getNdaughters() > 2) { // o2-linter: disable=magic-number (To be checked) + if (hypCand.getNdaughters() > Decays::kTwoBody) { for (int i = 0; i < hypCand.getNdaughters(); i++) { for (int j = i + 1; j < hypCand.getNdaughters(); j++) { outputSubDaughterTable(hypCand.getSubDaughterMass(i, j)); @@ -983,15 +922,6 @@ struct HypKfRecoTask { } } } - if (hypCand.isCascade()) { - for (int i = 1; i < hypCand.getNdaughters(); i++) { - for (int j = 0; j < hypCand.hypNucDaughter->getNdaughters(); j++) { - outputSubDaughterTable(hypCand.getSubDaughterMassCascade(i, j)); - vecSubDaughters.push_back(outputSubDaughterTable.lastIndex()); - } - } - } - hypCand.kfp.TransportToDecayVertex(); int mcPartTableId; outputHypNucTable( @@ -999,7 +929,7 @@ struct HypKfRecoTask { outputCollisionTable.lastIndex(), vecDaugtherTracks, vecAddons, hypCand.getDaughterTableId(), vecSubDaughters, (vec * nHyperNuclei + hyperNucIter + 1) * hypCand.getSign(), hypCand.isPrimaryCandidate, hypCand.mass, hypCand.px, hypCand.py, hypCand.pz, hypCand.dcaToPvXY, hypCand.dcaToPvZ, hypCand.devToPvXY, - hypCand.dcaToVtxXY, hypCand.dcaToVtxZ, hypCand.chi2, hypCand.recoSV.at(0), hypCand.recoSV.at(1), hypCand.recoSV.at(2)); + hypCand.dcaToVtxXY, hypCand.dcaToVtxZ, hypCand.chi2, /* hypCand.itsMeanClsSize,*/ hypCand.recoSV.at(0), hypCand.recoSV.at(1), hypCand.recoSV.at(2)); hypCand.tableId = outputHypNucTable.lastIndex(); } } @@ -1007,19 +937,18 @@ struct HypKfRecoTask { } //---------------------------------------------------------------------------------------------------------------- - void processMC(CollisionsFullMC const& collisions, aod::McCollisions const& mcColls, TracksFull const& tracks, aod::BCsWithTimestamps const&, aod::McParticles const& particlesMC, aod::McTrackLabels const& trackLabelsMC, aod::McCollisionLabels const& collLabels, aod::TrackAssoc const& tracksColl, CollisionsFull const& colls) + void processMC(CollisionsFullMC const& collisions, aod::McCollisions const& mcColls, TracksFull const& tracks, aod::BCsWithTimestamps const&, aod::McParticles const& particlesMC, aod::McTrackLabels const& trackLabelsMC, aod::McCollisionLabels const& collLabels, aod::TrackAssoc const& tracksColl, CollisionsFull const& colls, aod::V0s const& V0s, aod::Decay3Bodys const& decay3bodys, aod::TrackedV0s const& trackedV0s, aod::Tracked3Bodys const& tracked3Bodys) { - isMC = true; mcCollInfos.clear(); mcCollInfos.resize(mcColls.size()); mcPartIndices.clear(); for (const auto& collision : collisions) { if (!collision.has_mcCollision()) continue; - if (collision.sel8() && std::abs(collision.posZ()) < 10) // o2-linter: disable=magic-number (To be checked) + if (collision.sel8() && std::abs(collision.posZ()) < cfgVtxCutZ) mcCollInfos.at(collision.mcCollisionId()).passedEvSel = true; } - std::vector*> hypNucVectors = {&singleHyperNuclei, &cascadeHyperNuclei}; + std::vector*> hypNucVectors = {&singleHyperNuclei}; for (const auto& mcPart : particlesMC) { if (!mcCollInfos.at(mcPart.mcCollisionId()).passedEvSel) continue; @@ -1074,14 +1003,15 @@ struct HypKfRecoTask { const uint64_t collIdx = collision.globalIndex(); auto tracksByColl = tracksColl.sliceBy(perCollision, collIdx); + auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); + auto decay3bodyThisCollision = decay3bodys.sliceBy(perCollision3b, collIdx); + findDaughterParticles(tracksByColl, tracks, colls.rawIteratorAt(collision.globalIndex())); - if (cfgSaveOnlyMcTrue || usePidResponse) - checkMCTrueTracks(trackLabelsMC, particlesMC, tracks, colls.rawIteratorAt(collision.globalIndex())); + if (cfgSaveOnlyMcTrue) + checkMCTrueTracks(trackLabelsMC, particlesMC); createKFDaughters(tracks); - createKFHypernuclei(tracks); + createKFHypernuclei(v0TableThisCollision, decay3bodyThisCollision, trackedV0s, tracked3Bodys); createMCinfo(trackLabelsMC, collLabels, particlesMC, mcColls); - createKFCascades(tracks); - createMCinfo(trackLabelsMC, collLabels, particlesMC, mcColls, true); if (!collHasCandidate) continue; @@ -1101,7 +1031,7 @@ struct HypKfRecoTask { } PROCESS_SWITCH(HypKfRecoTask, processMC, "MC analysis", false); //---------------------------------------------------------------------------------------------------------------- - void processData(CollisionsFull const& collisions, TracksFull const& tracks, aod::BCsWithTimestamps const&, aod::TrackAssoc const& tracksColl) + void processData(CollisionsFull const& collisions, TracksFull const& tracks, aod::BCsWithTimestamps const&, aod::TrackAssoc const& tracksColl, aod::V0s const& V0s, aod::Decay3Bodys const& decay3bodys, aod::TrackedV0s const& trackedV0s, aod::Tracked3Bodys const& tracked3Bodys) { for (const auto& collision : collisions) { @@ -1112,10 +1042,11 @@ struct HypKfRecoTask { continue; const uint64_t collIdx = collision.globalIndex(); auto tracksByColl = tracksColl.sliceBy(perCollision, collIdx); + auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); + auto decay3bodyThisCollision = decay3bodys.sliceBy(perCollision3b, collIdx); findDaughterParticles(tracksByColl, tracks, collision); createKFDaughters(tracks); - createKFHypernuclei(tracks); - createKFCascades(tracks); + createKFHypernuclei(v0TableThisCollision, decay3bodyThisCollision, trackedV0s, tracked3Bodys); if (!collHasCandidate) continue; mcCollTableIndex = -1; @@ -1135,7 +1066,7 @@ struct HypKfRecoTask { o2::parameters::GRPMagField* grpmag = 0x0; if (grpo) { o2::base::Propagator::initFieldFromGRP(grpo); - if (bField < -990) { // o2-linter: disable=magic-number (To be checked) + if (bField <= NoVal) { // Fetch magnetic field from ccdb for current collision dBz = grpo->getNominalL3Field(); LOG(info) << "Retrieved GRP for timestamp " << run3grpTimestamp << " with magnetic field of " << dBz << " kZG"; @@ -1148,7 +1079,7 @@ struct HypKfRecoTask { LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grpTimestamp; } o2::base::Propagator::initFieldFromGRP(grpmag); - if (bField < -990) { // o2-linter: disable=magic-number (To be checked) + if (bField <= NoVal) { // Fetch magnetic field from ccdb for current collision dBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); LOG(info) << "Retrieved GRP for timestamp " << run3grpTimestamp << " with magnetic field of " << dBz << " kZG"; @@ -1158,30 +1089,6 @@ struct HypKfRecoTask { } mRunNumber = bc.runNumber(); KFParticle::SetField(dBz); - - // PID response - if (!usePidResponse) - return; - if (metadataInfo.isFullyDefined()) { - metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); - LOGP(info, "Automatically setting reco pass for TPC Response to {} from AO2D", metadata["RecoPassName"]); - } else { - LOG(info) << "Setting reco pass for TPC response to default name"; - metadata["RecoPassName"] = "apass5"; - } - const std::string path = pidPath.value; - ccdb->setTimestamp(run3grpTimestamp); - response = ccdb->getSpecific(path, run3grpTimestamp, metadata); - if (!response) { - LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); - response = ccdb->getForTimeStamp(path, run3grpTimestamp); - if (!response) { - LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", run3grpTimestamp); - } - } - LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << run3grpTimestamp << ", recoPass " << metadata["RecoPassName"]; - response->PrintAll(); - betheParams = response->GetBetheBlochParams(); } //---------------------------------------------------------------------------------------------------------------- template @@ -1189,18 +1096,14 @@ struct HypKfRecoTask { { foundDaughterKfs.clear(); foundDaughterKfs.resize(nDaughterParticles); - hypNucDaughterKfs.clear(); - hypNucDaughterKfs.resize(nCascades); singleHyperNucCandidates.clear(); singleHyperNucCandidates.resize(nHyperNuclei); - cascadeHyperNucCandidates.clear(); - cascadeHyperNucCandidates.resize(nCascades); trackIndices.clear(); collHasCandidate = false; collHasMcTrueCandidate = false; histos.fill(HIST("histMagField"), dBz); histos.fill(HIST("histNev"), 0.5); - collPassedEvSel = collision.sel8() && std::abs(collision.posZ()) < 10; // o2-linter: disable=magic-number (To be checked) + collPassedEvSel = collision.sel8() && std::abs(collision.posZ()) < cfgVtxCutZ; occupancy = collision.trackOccupancyInTimeRange(); if (collPassedEvSel) { histos.fill(HIST("histNev"), 1.5); @@ -1214,73 +1117,146 @@ struct HypKfRecoTask { primVtx.assign({collision.posX(), collision.posY(), collision.posZ()}); cents.assign({collision.centFT0A(), collision.centFT0C(), collision.centFT0M()}); } + //---------------------------------------------------------------------------------------------------------------- + bool checkPrimaryHypNuc(HyperNucCandidate& candidate, std::vector& settings) + { + if (!candidate.checkKfp()) + return false; + if (candidate.mass >= settings[kMaxMass] || candidate.mass <= settings[kMinMass]) + return false; + if (candidate.getDcaTracks() >= settings[kMaxDcaTracks]) + return false; + if (candidate.getCt(primVtx) >= settings[kMaxCt] || candidate.getCt(primVtx) <= settings[kMinCt]) + return false; + if (candidate.getCpa(primVtx) <= settings[kMinCosPa]) + return false; + candidate.calcDcaToVtx(kfPrimVtx); + if (std::abs(candidate.dcaToPvXY) >= settings[kMaxDcaMotherToPvXY] || std::abs(candidate.dcaToPvZ) >= settings[kMaxDcaMotherToPvZ]) + return false; + return true; + } + //---------------------------------------------------------------------------------------------------------------- + bool findDaughterKfComb(std::vector& kfDaughters, HyperNucleus* hyperNuc, std::vector& daughterPos, std::vector trackIds) + { + if (daughterPos.size() != trackIds.size()) + return false; + auto vecSize = daughterPos.size(); + std::set foundMatches; + for (size_t dpos = 0; dpos < vecSize; dpos++) { + auto daughterParticle = hyperNuc->daughters.at(daughterPos.at(dpos)); + for (size_t trackId = 0; trackId < vecSize; trackId++) { + auto daughterKf = findDaughterKfByTrackId(daughterParticle, trackIds.at(trackId)); + if (daughterKf >= 0) { + kfDaughters.at(daughterPos.at(dpos)) = &foundDaughterKfs.at(daughterParticle).at(daughterKf); + foundMatches.insert(dpos); + break; + } + } + if (foundMatches.size() != dpos + 1) + return false; + } + return true; + } //---------------------------------------------------------------------------------------------------------------- template void filldedx(T const& track, int species) { + constexpr int NTpcClsMin = 100; + constexpr int NItsClsMin = 2; const float rigidity = getRigidity(track); hDeDx[2 * species]->Fill(track.sign() * rigidity, track.tpcSignal()); - if (track.tpcNClsFound() < 100 || track.itsNCls() < 2) // o2-linter: disable=magic-number (To be checked) + if (track.tpcNClsFound() < NTpcClsMin || track.itsNCls() < NItsClsMin) return; hDeDx[2 * species + 1]->Fill(track.sign() * rigidity, track.tpcSignal()); } - //---------------------------------------------------------------------------------------------------------------- - template - float getTPCnSigma(T const& track, C const& coll, DaughterParticle& particle) + template + bool checkTrack(T const& track, DaughterParticle& particle) + { + if (std::abs(track.eta()) > cfgCutEta) + return false; + if (track.sign() * particle.trkSettings[kTrackCharge] < 0) + return false; + if (particle.trkSettings[kUsePVcontributors] >= 0 && particle.trkSettings[kUsePVcontributors] == track.isPVContributor()) + return false; + if (track.tpcNClsFound() < particle.trkSettings[kMinTPCnCls]) + return false; + if (track.tpcChi2NCl() > particle.trkSettings[kMaxTPCchi2]) + return false; + if (track.itsNCls() < particle.trkSettings[kMinITSnCls]) + return false; + if (track.itsChi2NCl() > particle.trkSettings[kMaxITSchi2]) + return false; + if (getRigidity(track) < particle.trkSettings[kMinRigidity] || getRigidity(track) > particle.trkSettings[kMaxRigidity]) + return false; + if (getMeanItsClsSize(track) < particle.trkSettings[kMinITSmeanClsSize]) + return false; + if (getMeanItsClsSize(track) > particle.trkSettings[kMaxITSmeanClsSize]) + return false; + if (particle.trkSettings[kTOFrequiredabove] >= 0 && getRigidity(track) > particle.trkSettings[kTOFrequiredabove] && (getMass2(track) < particle.trkSettings[kMinTOFmass] || getMass2(track) > particle.trkSettings[kMaxTOFmass])) + return false; + return true; + } + //---------------------------------------------------------------------------------------------------------------- + template + float getITSnSigma(T const& track, DaughterParticle& particle) + { + switch (std::abs(particle.pdgCode)) { + case 211: + return itsResponse.nSigmaITS(track); + case 2212: + return itsResponse.nSigmaITS(track); + case o2::constants::physics::kDeuteron: + return itsResponse.nSigmaITS(track); + case o2::constants::physics::kTriton: + return itsResponse.nSigmaITS(track); + case o2::constants::physics::kHelium3: + return itsResponse.nSigmaITS(track); + case o2::constants::physics::kAlpha: + return itsResponse.nSigmaITS(track); + default: + return NoVal; + } + } + //---------------------------------------------------------------------------------------------------------------- + template + float getTPCnSigma(T const& track, DaughterParticle& particle) { const float rigidity = getRigidity(track); - if (!track.hasTPC()) - return -999; - float mMip = 1, chargeFactor = 1; - float* parBB; - - switch (static_cast(cfgTrackPIDsettings->get(particle.name, "useBBparams"))) { + switch (static_cast(cfgTrackPIDsettings->get(particle.name, "PIDmethodTPC"))) { case -1: return 0; case 0: - return isMC ? 0 : response->GetNumberOfSigma(coll, track, particle.getCentralPIDIndex()); + if (particle.name == "proton") + return track.tpcNSigmaPr(); + else if (particle.name == "pion") + return track.tpcNSigmaPi(); + else + return NoVal; case 1: - parBB = &particle.betheParams[0]; - break; - case 2: - mMip = response->GetMIP(); - chargeFactor = std::pow(particle.charge, response->GetChargeFactor()); - parBB = &betheParams[0]; - break; + return particle.getTPCnSigmaBB(rigidity, track.tpcSignal()); default: - return -999; + return NoVal; } - double expBethe{mMip * chargeFactor * o2::common::BetheBlochAleph(static_cast(particle.charge * rigidity / particle.mass), parBB[0], parBB[1], parBB[2], parBB[3], parBB[4])}; - double expSigma{expBethe * particle.resolution}; - float sigmaTPC = static_cast((track.tpcSignal() - expBethe) / expSigma); - return sigmaTPC; } //---------------------------------------------------------------------------------------------------------------- - - template - float getTPCnSigmaMC(T const& trk, C const& coll, DaughterParticle& particle1, DaughterParticle& particle2) - { - const float pidval1 = particle1.getCentralPIDIndex(); - const float pidval2 = particle2.getCentralPIDIndex(); - const auto expSignal = response->GetExpectedSignal(trk, pidval2); - const auto expSigma = response->GetExpectedSigma(coll, trk, pidval2); - const auto mcTunedTPCSignal = gRandom->Gaus(expSignal, expSigma); - return response->GetNumberOfSigmaMCTuned(coll, trk, pidval1, mcTunedTPCSignal); - } - //---------------------------------------------------------------------------------------------------------------- - template float getMeanItsClsSize(T const& track) { + constexpr int NLayers = 8; + constexpr int NBitsPerLayer = 4; + constexpr int BitMask = (1 << NBitsPerLayer) - 1; int sum = 0, n = 0; - for (int i = 0; i < 0x08; i++) { - sum += (track.itsClusterSizes() >> (0x04 * i) & 0x0f); - if (track.itsClusterSizes() >> (0x04 * i) & 0x0f) + for (int i = 0; i < NLayers; i++) { + int clsSize = (track.itsClusterSizes() >> (NBitsPerLayer * i)) & BitMask; + sum += clsSize; + if (clsSize) { n++; + } } - return n > 0 ? static_cast(sum) / n : 0.f; + const float lambda = 1. / std::cosh(track.eta()); + return n > 0 ? (static_cast(sum) / n) * lambda : 0.f; } //---------------------------------------------------------------------------------------------------------------- template @@ -1296,17 +1272,19 @@ struct HypKfRecoTask { template KFParticle createKFParticle(const T& track, float mass, int charge) { + constexpr int Ndim = 3; auto trackparCov = getTrackParCov(track); - std::array fP; - std::array fM; + std::array fP; + std::array fM; trackparCov.getXYZGlo(fP); trackparCov.getPxPyPzGlo(fM); - float fPM[6]; - for (int i = 0; i < 0x03; i++) { + float fPM[2 * Ndim]; + for (int i = 0; i < Ndim; i++) { fPM[i] = fP[i]; - fPM[i + 3] = fM[i] * std::abs(charge); + fPM[i + Ndim] = fM[i] * std::abs(charge); } - std::array fC; + constexpr int NcovPars = 21; + std::array fC; trackparCov.getCovXYZPxPyPzGlo(fC); KFParticle part; part.Create(fPM, fC.data(), std::abs(charge) * track.sign(), mass); @@ -1338,7 +1316,7 @@ struct HypKfRecoTask { std::vector getDaughterVec(unsigned int hypNuc, LabeledArray cfg) { std::vector vec; - for (unsigned int i = 0; i < 0x04; i++) { + for (unsigned int i = kD1; i <= kD4; i++) { std::string daughter = cfg.get(hypNuc, i); if (std::find(particleNames.begin(), particleNames.end(), daughter) == particleNames.end()) break; @@ -1351,8 +1329,9 @@ struct HypKfRecoTask { std::vector getDaughterSignVec(unsigned int hypNuc, LabeledArray cfg) { std::vector vec; - for (unsigned int i = 0; i < 0x04; i++) { - std::string sign = cfg.get(hypNuc, i); + std::string signs = cfg.get(hypNuc, "daughterSigns"); + for (size_t i = 0; i < signs.size(); i++) { + std::string sign(1, signs.at(i)); if (sign != "+" && sign != "-") break; vec.push_back(sign == "+" ? +1 : -1); @@ -1360,6 +1339,47 @@ struct HypKfRecoTask { return vec; } //---------------------------------------------------------------------------------------------------------------- + std::vector getV0DaughterVec(unsigned int hypNuc, LabeledArray cfg) + { + std::vector vec; + std::string v0ds = cfg.get(hypNuc, "useV0for"); + for (size_t i = 0; i < v0ds.size(); i++) { + std::string v0d(1, v0ds.at(i)); + vec.push_back(std::stoi(v0d)); + } + return vec; + } + + //---------------------------------------------------------------------------------------------------------------- + int findDaughterKfByTrackId(int daughter, int trackId) + { + const auto& daughterKfVector = foundDaughterKfs.at(daughter); + int count = 0; + for (const auto& d : daughterKfVector) { + if (d.daughterTrackId == trackId) + return count; + count++; + } + return -1; + } + //---------------------------------------------------------------------------------------------------------------- + template + float getMass2(const T& track) + { + const float p = track.p(); + const float& tofStartTime = track.evTimeForTrack(); + const float& tofTime = track.tofSignal(); + constexpr float CInCmPs = 2.99792458e-2f; + const float& length = track.length(); + const float time = tofTime - tofStartTime; + if (time > 0.f && length > 0.f) { + const float beta = length / (CInCmPs * time); + const float gamma = 1.f / std::sqrt(1.f - beta * beta); + const float mass = p / std::sqrt(gamma * gamma - 1.f); + return mass * mass; + } + return -1.f; + } //---------------------------------------------------------------------------------------------------------------- }; //---------------------------------------------------------------------------------------------------------------- diff --git a/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx b/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx index 47c40e6c550..d1335959545 100644 --- a/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx +++ b/PWGLF/TableProducer/Nuspex/hypKfTreeCreator.cxx @@ -15,26 +15,10 @@ #include "PWGLF/DataModel/LFHypernucleiKfTables.h" -#include "Common/Core/PID/TPCPIDResponse.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" + #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" #include @@ -44,13 +28,14 @@ typedef std::array arr3; namespace { -std::vector> hPt; +enum Decays { kTwoBody = 2, + kThreeBody = 3 }; struct TrackProperties { - TrackProperties() : x(0), y(0), z(0), px(0), py(0), pz(0), tpcNcls(0), itsNcls(0), tpcChi2(0), itsChi2(0), itsMeanClsSize(0), itsMeanClsSizeL(0), rigidity(0), tpcSignal(0), tpcNsigma(0), tpcNsigmaNhp(0), tpcNsigmaNlp(0), tofMass(0), dcaXY(0), dcaZ(0), isPvContributor(0), subMass(0) {} + TrackProperties() : x(0), y(0), z(0), px(0), py(0), pz(0), tpcNcls(0), itsNcls(0), tpcChi2(0), itsChi2(0), itsMeanClsSizeL(0), rigidity(0), tpcSignal(0), tpcNsigma(0), tpcNsigmaNhp(0), tpcNsigmaNlp(0), tofMass(0), dcaXY(0), dcaZ(0), isPvContributor(0), subMass(0) {} float x, y, z, px, py, pz; uint8_t tpcNcls, itsNcls; - float tpcChi2, itsChi2, itsMeanClsSize, itsMeanClsSizeL; + float tpcChi2, itsChi2, itsMeanClsSizeL; float rigidity, tpcSignal, tpcNsigma, tpcNsigmaNhp, tpcNsigmaNlp; float tofMass, dcaXY, dcaZ; bool isPvContributor; @@ -58,24 +43,18 @@ struct TrackProperties { }; struct HyperNucleus { - HyperNucleus() : pdgCode(0), isReconstructed(0), globalIndex(0), species(0), speciesMC(0), isPrimaryCandidate(0), isMatter(0), isCascade(0), isCascadeMC(0), passedEvSel(0), isMatterMC(0), passedEvSelMC(0), isPhysicalPrimary(0), collisionMcTrue(0), mass(0), y(0), pt(0), ct(0), yGen(0), ptGen(0), ctGen(0), cpaPvGen(0), cpaPv(0), cpaSv(0), maxDcaTracks(0), maxDcaTracksSv(0), dcaToPvXY(0), dcaToPvZ(0), dcaToVtxXY(0), dcaToVtxZ(0), devToPvXY(0), chi2(0), pvx(0), pvy(0), pvz(0), svx(0), svy(0), svz(0), px(0), py(0), pz(0), pvxGen(0), pvyGen(0), pvzGen(0), svxGen(0), svyGen(0), svzGen(0), pxGen(0), pyGen(0), pzGen(0), nSingleDaughters(0), nCascadeDaughters(0), mcTrue(0), mcTrueVtx(0), mcPhysicalPrimary(0), hypNucDaughter(0) {} + HyperNucleus() : pdgCode(0), isReconstructed(0), globalIndex(0), species(0), speciesMC(0), isMatter(0), passedEvSel(0), isMatterMC(0), passedEvSelMC(0), isPhysicalPrimary(0), collisionMcTrue(0), mass(0), y(0), pt(0), ct(0), yGen(0), ptGen(0), ctGen(0), cpaPvGen(0), cpaPv(0), cpaSv(0), maxDcaTracks(0), maxDcaTracksSv(0), dcaToPvXY(0), dcaToPvZ(0), dcaToVtxXY(0), dcaToVtxZ(0), devToPvXY(0), chi2(0), pvx(0), pvy(0), pvz(0), svx(0), svy(0), svz(0), px(0), py(0), pz(0), pvxGen(0), pvyGen(0), pvzGen(0), svxGen(0), svyGen(0), svzGen(0), pxGen(0), pyGen(0), pzGen(0), nSingleDaughters(0), mcTrue(0), mcTrueVtx(0), mcPhysicalPrimary(0) {} int pdgCode, isReconstructed, globalIndex; uint8_t species, speciesMC; - bool isPrimaryCandidate, isMatter, isCascade, isCascadeMC, passedEvSel, isMatterMC, passedEvSelMC, isPhysicalPrimary, collisionMcTrue; + bool isMatter, passedEvSel, isMatterMC, passedEvSelMC, isPhysicalPrimary, collisionMcTrue; float mass, y, pt, ct, yGen, ptGen, ctGen, cpaPvGen, cpaPv, cpaSv, maxDcaTracks, maxDcaTracksSv; float dcaToPvXY, dcaToPvZ, dcaToVtxXY, dcaToVtxZ, devToPvXY, chi2; float pvx, pvy, pvz, svx, svy, svz, px, py, pz; float pvxGen, pvyGen, pvzGen, svxGen, svyGen, svzGen, pxGen, pyGen, pzGen; - int nSingleDaughters, nCascadeDaughters, cent, occu, runNumber; + int nSingleDaughters, cent, occu, runNumber; bool mcTrue, mcTrueVtx, mcPhysicalPrimary; std::vector daughterTracks; std::vector subDaughterMassVec; - HyperNucleus* hypNucDaughter; - ~HyperNucleus() - { - if (hypNucDaughter) - delete hypNucDaughter; - } }; } // namespace namespace o2::aod @@ -129,7 +108,6 @@ DECLARE_SOA_COLUMN(D1TPCnCls, d1TPCnCls, uint8_t); DECLARE_SOA_COLUMN(D1TPCchi2, d1TPCchi2, float); DECLARE_SOA_COLUMN(D1ITSnCls, d1ITSnCls, uint8_t); DECLARE_SOA_COLUMN(D1ITSchi2, d1ITSchi2, float); -DECLARE_SOA_COLUMN(D1ITSmeanClsSize, d1ITSmeanClsSize, float); DECLARE_SOA_COLUMN(D1ITSmeanClsSizeL, d1ITSmeanClsSizeL, float); DECLARE_SOA_COLUMN(D1Rigidity, d1Rigidity, float); DECLARE_SOA_COLUMN(D1TPCsignal, d1TPCsignal, float); @@ -150,7 +128,6 @@ DECLARE_SOA_COLUMN(D2TPCnCls, d2TPCnCls, uint8_t); DECLARE_SOA_COLUMN(D2TPCchi2, d2TPCchi2, float); DECLARE_SOA_COLUMN(D2ITSnCls, d2ITSnCls, uint8_t); DECLARE_SOA_COLUMN(D2ITSchi2, d2ITSchi2, float); -DECLARE_SOA_COLUMN(D2ITSmeanClsSize, d2ITSmeanClsSize, float); DECLARE_SOA_COLUMN(D2ITSmeanClsSizeL, d2ITSmeanClsSizeL, float); DECLARE_SOA_COLUMN(D2Rigidity, d2Rigidity, float); DECLARE_SOA_COLUMN(D2TPCsignal, d2TPCsignal, float); @@ -171,7 +148,6 @@ DECLARE_SOA_COLUMN(D3TPCnCls, d3TPCnCls, uint8_t); DECLARE_SOA_COLUMN(D3TPCchi2, d3TPCchi2, float); DECLARE_SOA_COLUMN(D3ITSnCls, d3ITSnCls, uint8_t); DECLARE_SOA_COLUMN(D3ITSchi2, d3ITSchi2, float); -DECLARE_SOA_COLUMN(D3ITSmeanClsSize, d3ITSmeanClsSize, float); DECLARE_SOA_COLUMN(D3ITSmeanClsSizeL, d3ITSmeanClsSizeL, float); DECLARE_SOA_COLUMN(D3Rigidity, d3Rigidity, float); DECLARE_SOA_COLUMN(D3TPCsignal, d3TPCsignal, float); @@ -185,120 +161,23 @@ DECLARE_SOA_COLUMN(D1d2Mass, d1d2Mass, float); DECLARE_SOA_COLUMN(D1d3Mass, d1d3Mass, float); DECLARE_SOA_COLUMN(D2d3Mass, d2d3Mass, float); DECLARE_SOA_COLUMN(D3IsPvContributor, d3IsPvContributor, bool); -DECLARE_SOA_COLUMN(D0X, d0X, float); -DECLARE_SOA_COLUMN(D0Y, d0Y, float); -DECLARE_SOA_COLUMN(D0Z, d0Z, float); -DECLARE_SOA_COLUMN(D0Px, d0Px, float); -DECLARE_SOA_COLUMN(D0Py, d0Py, float); -DECLARE_SOA_COLUMN(D0Pz, d0Pz, float); -DECLARE_SOA_COLUMN(D0Mass, d0Mass, float); -DECLARE_SOA_COLUMN(D0ct, d0ct, float); -DECLARE_SOA_COLUMN(D0cosPa, d0cosPa, float); -DECLARE_SOA_COLUMN(D0dcaTracks, d0dcaTracks, float); -DECLARE_SOA_COLUMN(D0dcaTracksTv, d0dcaTracksTv, float); -DECLARE_SOA_COLUMN(D0dcaToPvXY, d0dcaToPvXY, float); -DECLARE_SOA_COLUMN(D0dcaToPvZ, d0dcaToPvZ, float); -DECLARE_SOA_COLUMN(D0dcaToSvXY, d0dcaToSvXY, float); -DECLARE_SOA_COLUMN(D0dcaToSvZ, d0dcaToSvZ, float); -DECLARE_SOA_COLUMN(D0chi2, d0chi2, float); -DECLARE_SOA_COLUMN(Sd1X, sd1X, float); -DECLARE_SOA_COLUMN(Sd1Y, sd1Y, float); -DECLARE_SOA_COLUMN(Sd1Z, sd1Z, float); -DECLARE_SOA_COLUMN(Sd1Px, sd1Px, float); -DECLARE_SOA_COLUMN(Sd1Py, sd1Py, float); -DECLARE_SOA_COLUMN(Sd1Pz, sd1Pz, float); -DECLARE_SOA_COLUMN(Sd1TPCnCls, sd1TPCnCls, uint8_t); -DECLARE_SOA_COLUMN(Sd1TPCchi2, sd1TPCchi2, float); -DECLARE_SOA_COLUMN(Sd1ITSnCls, sd1ITSnCls, uint8_t); -DECLARE_SOA_COLUMN(Sd1ITSchi2, sd1ITSchi2, float); -DECLARE_SOA_COLUMN(Sd1ITSmeanClsSize, sd1ITSmeanClsSize, float); -DECLARE_SOA_COLUMN(Sd1ITSmeanClsSizeL, sd1ITSmeanClsSizeL, float); -DECLARE_SOA_COLUMN(Sd1Rigidity, sd1Rigidity, float); -DECLARE_SOA_COLUMN(Sd1TPCsignal, sd1TPCsignal, float); -DECLARE_SOA_COLUMN(Sd1TPCnSigma, sd1TPCnSigma, float); -DECLARE_SOA_COLUMN(Sd1TPCnSigmaNhp, sd1TPCnSigmaNhp, float); -DECLARE_SOA_COLUMN(Sd1TPCnSigmaNlp, sd1TPCnSigmaNlp, float); -DECLARE_SOA_COLUMN(Sd1TOFmass, sd1TOFmass, float); -DECLARE_SOA_COLUMN(Sd1DcaXY, sd1DcaXY, float); -DECLARE_SOA_COLUMN(Sd1DcaZ, sd1DcaZ, float); -DECLARE_SOA_COLUMN(Sd1IsPvContributor, sd1IsPvContributor, bool); -DECLARE_SOA_COLUMN(Sd2X, sd2X, float); -DECLARE_SOA_COLUMN(Sd2Y, sd2Y, float); -DECLARE_SOA_COLUMN(Sd2Z, sd2Z, float); -DECLARE_SOA_COLUMN(Sd2Px, sd2Px, float); -DECLARE_SOA_COLUMN(Sd2Py, sd2Py, float); -DECLARE_SOA_COLUMN(Sd2Pz, sd2Pz, float); -DECLARE_SOA_COLUMN(Sd2TPCnCls, sd2TPCnCls, uint8_t); -DECLARE_SOA_COLUMN(Sd2TPCchi2, sd2TPCchi2, float); -DECLARE_SOA_COLUMN(Sd2ITSnCls, sd2ITSnCls, uint8_t); -DECLARE_SOA_COLUMN(Sd2ITSchi2, sd2ITSchi2, float); -DECLARE_SOA_COLUMN(Sd2ITSmeanClsSize, sd2ITSmeanClsSize, float); -DECLARE_SOA_COLUMN(Sd2ITSmeanClsSizeL, sd2ITSmeanClsSizeL, float); -DECLARE_SOA_COLUMN(Sd2Rigidity, sd2Rigidity, float); -DECLARE_SOA_COLUMN(Sd2TPCsignal, sd2TPCsignal, float); -DECLARE_SOA_COLUMN(Sd2TPCnSigma, sd2TPCnSigma, float); -DECLARE_SOA_COLUMN(Sd2TPCnSigmaNhp, sd2TPCnSigmaNhp, float); -DECLARE_SOA_COLUMN(Sd2TPCnSigmaNlp, sd2TPCnSigmaNlp, float); -DECLARE_SOA_COLUMN(Sd2TOFmass, sd2TOFmass, float); -DECLARE_SOA_COLUMN(Sd2DcaXY, sd2DcaXY, float); -DECLARE_SOA_COLUMN(Sd2DcaZ, sd2DcaZ, float); -DECLARE_SOA_COLUMN(Sd2IsPvContributor, sd2IsPvContributor, bool); -DECLARE_SOA_COLUMN(Sd3X, sd3X, float); -DECLARE_SOA_COLUMN(Sd3Y, sd3Y, float); -DECLARE_SOA_COLUMN(Sd3Z, sd3Z, float); -DECLARE_SOA_COLUMN(Sd3Px, sd3Px, float); -DECLARE_SOA_COLUMN(Sd3Py, sd3Py, float); -DECLARE_SOA_COLUMN(Sd3Pz, sd3Pz, float); -DECLARE_SOA_COLUMN(Sd3TPCnCls, sd3TPCnCls, uint8_t); -DECLARE_SOA_COLUMN(Sd3TPCchi2, sd3TPCchi2, float); -DECLARE_SOA_COLUMN(Sd3ITSnCls, sd3ITSnCls, uint8_t); -DECLARE_SOA_COLUMN(Sd3ITSchi2, sd3ITSchi2, float); -DECLARE_SOA_COLUMN(Sd3ITSmeanClsSize, sd3ITSmeanClsSize, float); -DECLARE_SOA_COLUMN(Sd3ITSmeanClsSizeL, sd3ITSmeanClsSizeL, float); -DECLARE_SOA_COLUMN(Sd3Rigidity, sd3Rigidity, float); -DECLARE_SOA_COLUMN(Sd3TPCsignal, sd3TPCsignal, float); -DECLARE_SOA_COLUMN(Sd3TPCnSigma, sd3TPCnSigma, float); -DECLARE_SOA_COLUMN(Sd3TPCnSigmaNhp, sd3TPCnSigmaNhp, float); -DECLARE_SOA_COLUMN(Sd3TPCnSigmaNlp, sd3TPCnSigmaNlp, float); -DECLARE_SOA_COLUMN(Sd3TOFmass, sd3TOFmass, float); -DECLARE_SOA_COLUMN(Sd3DcaXY, sd3DcaXY, float); -DECLARE_SOA_COLUMN(Sd3DcaZ, sd3DcaZ, float); -DECLARE_SOA_COLUMN(Sd3IsPvContributor, sd3IsPvContributor, bool); -DECLARE_SOA_COLUMN(Sd1sd2Mass, sd1sd2Mass, float); -DECLARE_SOA_COLUMN(Sd1sd3Mass, sd1sd3Mass, float); -DECLARE_SOA_COLUMN(Sd2sd3Mass, sd2sd3Mass, float); -DECLARE_SOA_COLUMN(D1sd1Mass, d1sd1Mass, float); -DECLARE_SOA_COLUMN(D1sd2Mass, d1sd2Mass, float); -DECLARE_SOA_COLUMN(D1sd3Mass, d1sd3Mass, float); } // namespace hypkftree #define HYPKFGENBASE hypkftree::SpeciesMC, mcparticle::PdgCode, hypkftree::IsMatterGen, hypkftree::IsReconstructed, hykfmc::IsPhysicalPrimary, hypkftree::PassedEvSelMC, hypkftree::YGen, hypkftree::PtGen, hypkftree::CtGen #define HYPKFGENEXT hypkftree::CpaPvGen, hypkftree::PxGen, hypkftree::PyGen, hypkftree::PzGen, hypkftree::PvxGen, hypkftree::PvyGen, hypkftree::PvzGen, hypkftree::SvxGen, hypkftree::SvyGen, hypkftree::SvzGen -#define HYPKFGENCAS hypkftree::TvxGen, hypkftree::TvyGen, hypkftree::TvzGen - #define HYPKFHYPNUC hykfmc::Species, hypkftree::IsMatter, hypkftree::Centrality, hypkftree::Occupancy, hypkftree::RunNumber, hykfmccoll::PassedEvSel, hykfhyp::Mass, hypkftree::Y, track::Pt, hypkftree::Ct, hypkftree::CosPa, hypkftree::DcaTracks, hypkftree::DcaTrackSv, hykfhyp::DcaToPvXY, hykfhyp::DcaToPvZ, hykfhyp::DevToPvXY, hykfhyp::Chi2, hypkftree::Pvx, hypkftree::Pvy, hypkftree::Pvz, hykfmc::Svx, hykfmc::Svy, hykfmc::Svz, hykfhyp::Px, hykfhyp::Py, hykfhyp::Pz, hypkftree::CollMcTrue #define HYPKFHYPNUCMC hypkftree::McTrue, hykfmc::IsPhysicalPrimary -#define HYPKFD0 hypkftree::Tvx, hypkftree::Tvy, hypkftree::Tvz, hypkftree::D0X, hypkftree::D0Y, hypkftree::D0Z, hypkftree::D0Px, hypkftree::D0Py, hypkftree::D0Pz, hypkftree::D0Mass, hypkftree::D0ct, hypkftree::D0cosPa, hypkftree::D0dcaTracks, hypkftree::D0dcaToPvXY, hypkftree::D0dcaToPvZ, hypkftree::D0dcaToSvXY, hypkftree::D0dcaToSvZ, hypkftree::D0chi2 - #define HYPKFD1 hypkftree::D1X, hypkftree::D1Y, hypkftree::D1Z, hypkftree::D1Px, hypkftree::D1Py, hypkftree::D1Pz, hypkftree::D1TPCnCls, hypkftree::D1TPCchi2, hypkftree::D1ITSnCls, hypkftree::D1ITSchi2, hypkftree::D1ITSmeanClsSizeL, hypkftree::D1Rigidity, hypkftree::D1TPCsignal, hypkftree::D1TPCnSigma, hypkftree::D1TPCnSigmaNhp, hypkftree::D1TPCnSigmaNlp, hypkftree::D1TOFmass, hypkftree::D1DcaXY, hypkftree::D1DcaZ, hypkftree::D1IsPvContributor #define HYPKFD2 hypkftree::D2X, hypkftree::D2Y, hypkftree::D2Z, hypkftree::D2Px, hypkftree::D2Py, hypkftree::D2Pz, hypkftree::D2TPCnCls, hypkftree::D2TPCchi2, hypkftree::D2ITSnCls, hypkftree::D2ITSchi2, hypkftree::D2ITSmeanClsSizeL, hypkftree::D2Rigidity, hypkftree::D2TPCsignal, hypkftree::D2TPCnSigma, hypkftree::D2TPCnSigmaNhp, hypkftree::D2TPCnSigmaNlp, hypkftree::D2TOFmass, hypkftree::D2DcaXY, hypkftree::D2DcaZ, hypkftree::D2IsPvContributor #define HYPKFD3 hypkftree::D3X, hypkftree::D3Y, hypkftree::D3Z, hypkftree::D3Px, hypkftree::D3Py, hypkftree::D3Pz, hypkftree::D3TPCnCls, hypkftree::D3TPCchi2, hypkftree::D3ITSnCls, hypkftree::D3ITSchi2, hypkftree::D3ITSmeanClsSizeL, hypkftree::D3Rigidity, hypkftree::D3TPCsignal, hypkftree::D3TPCnSigma, hypkftree::D3TPCnSigmaNhp, hypkftree::D3TPCnSigmaNlp, hypkftree::D3TOFmass, hypkftree::D3DcaXY, hypkftree::D3DcaZ, hypkftree::D3IsPvContributor -#define HYPKFSD1 hypkftree::Sd1X, hypkftree::Sd1Y, hypkftree::Sd1Z, hypkftree::Sd1Px, hypkftree::Sd1Py, hypkftree::Sd1Pz, hypkftree::Sd1TPCnCls, hypkftree::Sd1TPCchi2, hypkftree::Sd1ITSnCls, hypkftree::Sd1ITSchi2, hypkftree::Sd1ITSmeanClsSizeL, hypkftree::Sd1Rigidity, hypkftree::Sd1TPCsignal, hypkftree::Sd1TPCnSigma, hypkftree::Sd1TPCnSigmaNhp, hypkftree::Sd1TPCnSigmaNlp, hypkftree::Sd1TOFmass, hypkftree::Sd1DcaXY, hypkftree::Sd1DcaZ, hypkftree::Sd1IsPvContributor - -#define HYPKFSD2 hypkftree::Sd2X, hypkftree::Sd2Y, hypkftree::Sd2Z, hypkftree::Sd2Px, hypkftree::Sd2Py, hypkftree::Sd2Pz, hypkftree::Sd2TPCnCls, hypkftree::Sd2TPCchi2, hypkftree::Sd2ITSnCls, hypkftree::Sd2ITSchi2, hypkftree::Sd2ITSmeanClsSizeL, hypkftree::Sd2Rigidity, hypkftree::Sd2TPCsignal, hypkftree::Sd2TPCnSigma, hypkftree::Sd2TPCnSigmaNhp, hypkftree::Sd2TPCnSigmaNlp, hypkftree::Sd2TOFmass, hypkftree::Sd2DcaXY, hypkftree::Sd2DcaZ, hypkftree::Sd2IsPvContributor - -#define HYPKFSD3 hypkftree::Sd3X, hypkftree::Sd3Y, hypkftree::Sd3Z, hypkftree::Sd3Px, hypkftree::Sd3Py, hypkftree::Sd3Pz, hypkftree::Sd3TPCnCls, hypkftree::Sd3TPCchi2, hypkftree::Sd3ITSnCls, hypkftree::Sd3ITSchi2, hypkftree::Sd3ITSmeanClsSizeL, hypkftree::Sd3Rigidity, hypkftree::Sd3TPCsignal, hypkftree::Sd3TPCnSigma, hypkftree::Sd3TPCnSigmaNhp, hypkftree::Sd3TPCnSigmaNlp, hypkftree::Sd3TOFmass, hypkftree::Sd3DcaXY, hypkftree::Sd3DcaZ, hypkftree::Sd3IsPvContributor - #define HYPKFSDMASS hypkftree::D1d2Mass, hypkftree::D1d3Mass, hypkftree::D2d3Mass -#define HYPKFSSDMASS hypkftree::Sd1sd2Mass, hypkftree::Sd1sd3Mass, hypkftree::Sd2sd3Mass -#define HYPKFCSDMASS hypkftree::D1sd1Mass, hypkftree::D1sd2Mass, hypkftree::D1sd3Mass DECLARE_SOA_TABLE(HypKfGens, "AOD", "HYPKFGEN", HYPKFGENBASE); using HypKfGen = HypKfGens::iterator; @@ -315,17 +194,6 @@ using HypKfSingleThreeBodyCandidate = HypKfSingleThreeBodyCandidates::iterator; DECLARE_SOA_TABLE(HypKfMcSingleThreeBodyCandidates, "AOD", "HYPKFMCCAND3", HYPKFGENBASE, HYPKFGENEXT, HYPKFHYPNUC, HYPKFD1, HYPKFD2, HYPKFD3, HYPKFSDMASS); using HypKfMcSingleThreeBodyCandidate = HypKfMcSingleThreeBodyCandidates::iterator; -DECLARE_SOA_TABLE(HypKfCascadeTwoThreeCandidates, "AOD", "HYPKFCAND23", HYPKFHYPNUC, HYPKFHYPNUCMC, HYPKFD0, HYPKFD1, HYPKFSD1, HYPKFSD2, HYPKFSD3, HYPKFSSDMASS, HYPKFCSDMASS); -using HypKfCascadeTwoThreeCandidate = HypKfCascadeTwoThreeCandidates::iterator; - -DECLARE_SOA_TABLE(HypKfMcCascadeTwoThreeCandidates, "AOD", "HYPKFMCCAND23", HYPKFGENBASE, HYPKFGENEXT, HYPKFHYPNUC, HYPKFD0, HYPKFD1, HYPKFSD1, HYPKFSD2, HYPKFSD3, HYPKFSSDMASS, HYPKFCSDMASS); -using HypKfMcCascadeTwoThreeCandidate = HypKfMcCascadeTwoThreeCandidates::iterator; - -DECLARE_SOA_TABLE(HypKfCascadeThreeTwoCandidates, "AOD", "HYPKFCAND32", HYPKFHYPNUC, HYPKFHYPNUCMC, HYPKFD0, HYPKFD1, HYPKFD2, HYPKFSDMASS, HYPKFSD1, HYPKFSD2); -using HypKfCascadeThreeTwoCandidate = HypKfCascadeThreeTwoCandidates::iterator; - -DECLARE_SOA_TABLE(HypKfMcCascadeThreeTwoCandidates, "AOD", "HYPKFMCCAND32", HYPKFGENBASE, HYPKFGENEXT, HYPKFHYPNUC, HYPKFD0, HYPKFD1, HYPKFD2, HYPKFSDMASS, HYPKFSD1, HYPKFSD2); -using HypKfMcCascadeThreeTwoCandidate = HypKfMcCascadeThreeTwoCandidates::iterator; } // namespace o2::aod struct HypKfTreeCreator { @@ -336,15 +204,10 @@ struct HypKfTreeCreator { Produces outputTableMcTwo; Produces outputTableThree; Produces outputTableMcThree; - Produces outputTableTwoThree; - Produces outputTableMcTwoThree; - Produces outputTableThreeTwo; - Produces outputTableMcThreeTwo; PresliceUnsorted perMcParticle = aod::hykfhyp::hypKfMcPartId; Configurable cfgSpecies{"cfgSpecies", 0, "Select species"}; Configurable cfgNprimDaughters{"cfgNprimDaughters", 0, "Number of primary daughters"}; - Configurable cfgNsecDaughters{"cfgNsecDaughters", 0, "Number of secondary daughters (cascades only)"}; Configurable cfgMCGenerated{"cfgMCGenerated", false, "create MC generated tree"}; Configurable cfgMCReconstructed{"cfgMCReconstructed", false, "create MC reconstructed tree"}; Configurable cfgMCCombined{"cfgMCCombined", false, "create MC tree containig generated and reconstructed"}; @@ -354,33 +217,11 @@ struct HypKfTreeCreator { void init(InitContext const&) { - const AxisSpec axisPt{10, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; - hPt.resize(3); - hPt[0] = histos.add("hGen", "", HistType::kTH1F, {axisPt}); - hPt[0]->Sumw2(); - hPt[1] = histos.add("hRec", "", HistType::kTH1F, {axisPt}); - hPt[1]->Sumw2(); - hPt[2] = histos.add("hEff", "", HistType::kTH1F, {axisPt}); isMC = false; } - //___________________________________________________________________________________________________________________________________________________________ - void processData(aod::HypKfHypNucs const& hypNucs, aod::HypKfColls const& hypKfColls, aod::HypKfTracks const& hypKfTrks, aod::HypKfDaughtAdds const& hypKfDAdd, aod::HypKfSubDs const& hypKfDSub) - { - for (const auto& hypNuc : hypNucs) { - if (cfgSpecies && std::abs(hypNuc.species()) != cfgSpecies) - continue; - HyperNucleus candidate, hypNucDaughter; - fillCandidatePrim(candidate, hypNuc, hypNucs, hypKfColls, hypKfTrks, hypKfDAdd, hypKfDSub); - if (hypNuc.hypDaughterId() >= 0) { - fillCandidateSec(hypNucDaughter, hypNucs.rawIteratorAt(hypNuc.hypDaughterId()), hypNuc, hypNucs, hypKfColls, hypKfTrks, hypKfDAdd, hypKfDSub); - } - fillTable(candidate, hypNucDaughter); - } - } - PROCESS_SWITCH(HypKfTreeCreator, processData, "single tree", false); //___________________________________________________________________________________________________________________________________________________________ - void fillTable(HyperNucleus& cand, HyperNucleus& hypDaughter) + void fillTable(HyperNucleus& cand) { if (isMC && cfgMCGenerated) outputMcGenTable( @@ -389,19 +230,16 @@ struct HypKfTreeCreator { if (!cand.isReconstructed) { cand.daughterTracks.resize(4); cand.subDaughterMassVec.resize(4); - hypDaughter.daughterTracks.resize(4); - hypDaughter.subDaughterMassVec.resize(8); } - if (cfgNprimDaughters == 2 && cfgNsecDaughters == 0) { // o2-linter: disable=magic-number (To be checked) + if (cfgNprimDaughters == Decays::kTwoBody) { const auto& d1 = cand.daughterTracks.at(0); const auto& d2 = cand.daughterTracks.at(1); if (!isMC || (isMC && cfgMCReconstructed && cand.isReconstructed)) outputTableTwo( cand.species, cand.isMatter, cand.cent, cand.occu, cand.runNumber, cand.passedEvSel, cand.mass, cand.y, cand.pt, cand.ct, cand.cpaPv, cand.maxDcaTracks, cand.maxDcaTracksSv, cand.dcaToPvXY, cand.dcaToPvZ, cand.devToPvXY, cand.chi2, cand.pvx, cand.pvy, cand.pvz, cand.svx, cand.svy, cand.svz, cand.px, cand.py, cand.pz, cand.collisionMcTrue, - cand.mcTrue, cand.mcPhysicalPrimary, - d1.x, d1.y, d1.z, d1.px, d1.py, d1.pz, d1.tpcNcls, d1.tpcChi2, d1.itsNcls, d1.itsChi2, d1.itsMeanClsSizeL, + cand.mcTrue, cand.mcPhysicalPrimary, d1.x, d1.y, d1.z, d1.px, d1.py, d1.pz, d1.tpcNcls, d1.tpcChi2, d1.itsNcls, d1.itsChi2, d1.itsMeanClsSizeL, d1.rigidity, d1.tpcSignal, d1.tpcNsigma, d1.tpcNsigmaNhp, d1.tpcNsigmaNlp, d1.tofMass, d1.dcaXY, d1.dcaZ, d1.isPvContributor, d2.x, d2.y, d2.z, d2.px, d2.py, d2.pz, d2.tpcNcls, d2.tpcChi2, d2.itsNcls, d2.itsChi2, d2.itsMeanClsSizeL, d2.rigidity, d2.tpcSignal, d2.tpcNsigma, d2.tpcNsigmaNhp, d2.tpcNsigmaNlp, d2.tofMass, d2.dcaXY, d2.dcaZ, d2.isPvContributor); @@ -417,7 +255,7 @@ struct HypKfTreeCreator { d2.x, d2.y, d2.z, d2.px, d2.py, d2.pz, d2.tpcNcls, d2.tpcChi2, d2.itsNcls, d2.itsChi2, d2.itsMeanClsSizeL, d2.rigidity, d2.tpcSignal, d2.tpcNsigma, d2.tpcNsigmaNhp, d2.tpcNsigmaNlp, d2.tofMass, d2.dcaXY, d2.dcaZ, d2.isPvContributor); } - if (((!isMC && cand.isPrimaryCandidate) || (isMC && cand.isPhysicalPrimary)) && ((cfgNprimDaughters == 3 && cfgNsecDaughters == 0) || (cfgNsecDaughters == 3 && cfgSpecies == 0))) { // o2-linter: disable=magic-number (To be checked) + if (cfgNprimDaughters == Decays::kThreeBody) { const auto& d1 = cand.daughterTracks.at(0); const auto& d2 = cand.daughterTracks.at(1); const auto& d3 = cand.daughterTracks.at(2); @@ -448,103 +286,6 @@ struct HypKfTreeCreator { d3.rigidity, d3.tpcSignal, d3.tpcNsigma, d3.tpcNsigmaNhp, d3.tpcNsigmaNlp, d3.tofMass, d3.dcaXY, d3.dcaZ, d3.isPvContributor, d1.subMass, d2.subMass, d3.subMass); } - if ((!isMC && !cand.isCascade) || (isMC && !cand.isCascadeMC)) - return; - if (cfgNprimDaughters == 2 && cfgNsecDaughters == 3) { // o2-linter: disable=magic-number (To be checked) - const auto& d0 = cand.daughterTracks.at(0); - const auto& d1 = cand.daughterTracks.at(1); - const auto& sd1 = hypDaughter.daughterTracks.at(0); - const auto& sd2 = hypDaughter.daughterTracks.at(1); - const auto& sd3 = hypDaughter.daughterTracks.at(2); - if (!isMC || (isMC && cfgMCReconstructed && cand.isReconstructed)) - outputTableTwoThree( - cand.species, cand.isMatter, cand.cent, cand.occu, cand.runNumber, cand.passedEvSel, cand.mass, cand.y, cand.pt, cand.ct, cand.cpaPv, cand.maxDcaTracks, cand.maxDcaTracksSv, - cand.dcaToPvXY, cand.dcaToPvZ, cand.devToPvXY, cand.chi2, cand.pvx, cand.pvy, cand.pvz, cand.svx, cand.svy, cand.svz, cand.px, cand.py, cand.pz, cand.collisionMcTrue, - cand.mcTrue, cand.mcPhysicalPrimary, - hypDaughter.svx, hypDaughter.svy, hypDaughter.svz, d0.x, d0.y, d0.z, d0.px, d0.py, d0.pz, hypDaughter.mass, hypDaughter.ct, hypDaughter.cpaPv, - hypDaughter.maxDcaTracks, hypDaughter.dcaToPvXY, hypDaughter.dcaToPvZ, hypDaughter.dcaToVtxXY, hypDaughter.dcaToVtxZ, hypDaughter.chi2, - d1.x, d1.y, d1.z, d1.px, d1.py, d1.pz, d1.tpcNcls, d1.tpcChi2, d1.itsNcls, d1.itsChi2, d1.itsMeanClsSizeL, - d1.rigidity, d1.tpcSignal, d1.tpcNsigma, d1.tpcNsigmaNhp, d1.tpcNsigmaNlp, d1.tofMass, d1.dcaXY, d1.dcaZ, d1.isPvContributor, - sd1.x, sd1.y, sd1.z, sd1.px, sd1.py, sd1.pz, sd1.tpcNcls, sd1.tpcChi2, sd1.itsNcls, sd1.itsChi2, sd1.itsMeanClsSizeL, - sd1.rigidity, sd1.tpcSignal, sd1.tpcNsigma, sd1.tpcNsigmaNhp, sd1.tpcNsigmaNlp, sd1.tofMass, sd1.dcaXY, sd1.dcaZ, sd1.isPvContributor, - sd2.x, sd2.y, sd2.z, sd2.px, sd2.py, sd2.pz, sd2.tpcNcls, sd2.tpcChi2, sd2.itsNcls, sd2.itsChi2, sd2.itsMeanClsSizeL, - sd2.rigidity, sd2.tpcSignal, sd2.tpcNsigma, sd2.tpcNsigmaNhp, sd2.tpcNsigmaNlp, sd2.tofMass, sd2.dcaXY, sd2.dcaZ, sd2.isPvContributor, - sd3.x, sd3.y, sd3.z, sd3.px, sd3.py, sd3.pz, sd3.tpcNcls, sd3.tpcChi2, sd3.itsNcls, sd3.itsChi2, sd3.itsMeanClsSizeL, - sd3.rigidity, sd3.tpcSignal, sd3.tpcNsigma, sd3.tpcNsigmaNhp, sd3.tpcNsigmaNlp, sd3.tofMass, sd3.dcaXY, sd3.dcaZ, sd3.isPvContributor, - sd1.subMass, sd2.subMass, sd3.subMass, cand.subDaughterMassVec.at(0), cand.subDaughterMassVec.at(1), cand.subDaughterMassVec.at(2)); - if (isMC && cfgMCCombined) - outputTableMcTwoThree( - cand.speciesMC, cand.pdgCode, cand.isMatterMC, cand.isReconstructed, cand.isPhysicalPrimary, cand.passedEvSelMC, cand.yGen, cand.ptGen, cand.ctGen, - cand.cpaPvGen, cand.pxGen, cand.pyGen, cand.pzGen, cand.pvxGen, cand.pvyGen, cand.pvzGen, cand.svxGen, cand.svyGen, cand.svzGen, - cand.species, cand.isMatter, cand.cent, cand.occu, cand.runNumber, cand.passedEvSel, cand.mass, cand.y, cand.pt, cand.ct, cand.cpaPv, cand.maxDcaTracks, cand.maxDcaTracksSv, - cand.dcaToPvXY, cand.dcaToPvZ, cand.devToPvXY, - cand.chi2, cand.pvx, cand.pvy, cand.pvz, cand.svx, cand.svy, cand.svz, cand.px, cand.py, cand.pz, cand.collisionMcTrue, - hypDaughter.svx, hypDaughter.svy, hypDaughter.svz, d0.x, d0.y, d0.z, d0.px, d0.py, d0.pz, hypDaughter.mass, hypDaughter.ct, hypDaughter.cpaPv, - hypDaughter.maxDcaTracks, hypDaughter.dcaToPvXY, hypDaughter.dcaToPvZ, hypDaughter.dcaToVtxXY, hypDaughter.dcaToVtxZ, hypDaughter.chi2, - d1.x, d1.y, d1.z, d1.px, d1.py, d1.pz, d1.tpcNcls, d1.tpcChi2, d1.itsNcls, d1.itsChi2, d1.itsMeanClsSizeL, - d1.rigidity, d1.tpcSignal, d1.tpcNsigma, d1.tpcNsigmaNhp, d1.tpcNsigmaNlp, d1.tofMass, d1.dcaXY, d1.dcaZ, d1.isPvContributor, - sd1.x, sd1.y, sd1.z, sd1.px, sd1.py, sd1.pz, sd1.tpcNcls, sd1.tpcChi2, sd1.itsNcls, sd1.itsChi2, sd1.itsMeanClsSizeL, - sd1.rigidity, sd1.tpcSignal, sd1.tpcNsigma, sd1.tpcNsigmaNhp, sd1.tpcNsigmaNlp, sd1.tofMass, sd1.dcaXY, sd1.dcaZ, sd1.isPvContributor, - sd2.x, sd2.y, sd2.z, sd2.px, sd2.py, sd2.pz, sd2.tpcNcls, sd2.tpcChi2, sd2.itsNcls, sd2.itsChi2, sd2.itsMeanClsSizeL, - sd2.rigidity, sd2.tpcSignal, sd2.tpcNsigma, sd2.tpcNsigmaNhp, sd2.tpcNsigmaNlp, sd2.tofMass, sd2.dcaXY, sd2.dcaZ, sd2.isPvContributor, - sd3.x, sd3.y, sd3.z, sd3.px, sd3.py, sd3.pz, sd3.tpcNcls, sd3.tpcChi2, sd3.itsNcls, sd3.itsChi2, sd3.itsMeanClsSizeL, - sd3.rigidity, sd3.tpcSignal, sd3.tpcNsigma, sd3.tpcNsigmaNhp, sd3.tpcNsigmaNlp, sd3.tofMass, sd3.dcaXY, sd3.dcaZ, sd3.isPvContributor, - sd1.subMass, sd2.subMass, sd3.subMass, cand.subDaughterMassVec.at(0), cand.subDaughterMassVec.at(1), cand.subDaughterMassVec.at(2)); - } - if (cfgNprimDaughters == 3 && cfgNsecDaughters == 1) { // o2-linter: disable=magic-number (To be checked) - const auto& d0 = cand.daughterTracks.at(0); - const auto& d1 = cand.daughterTracks.at(1); - const auto& d2 = cand.daughterTracks.at(2); - const auto& sd1 = hypDaughter.daughterTracks.at(0); - const auto& sd2 = hypDaughter.daughterTracks.at(1); - if (!isMC || (isMC && cfgMCReconstructed && cand.isReconstructed)) - outputTableThreeTwo( - cand.species, cand.isMatter, cand.cent, cand.occu, cand.runNumber, cand.passedEvSel, cand.mass, cand.y, cand.pt, cand.ct, cand.cpaPv, cand.maxDcaTracks, cand.maxDcaTracksSv, - cand.dcaToPvXY, cand.dcaToPvZ, cand.devToPvXY, cand.chi2, cand.pvx, cand.pvy, cand.pvz, cand.svx, cand.svy, cand.svz, cand.px, cand.py, cand.pz, cand.collisionMcTrue, - cand.mcTrue, cand.mcPhysicalPrimary, hypDaughter.svx, hypDaughter.svy, hypDaughter.svz, d0.x, d0.y, d0.z, d0.px, d0.py, d0.pz, hypDaughter.mass, hypDaughter.ct, - hypDaughter.cpaPv, hypDaughter.maxDcaTracks, hypDaughter.dcaToPvXY, hypDaughter.dcaToPvZ, hypDaughter.dcaToVtxXY, hypDaughter.dcaToVtxZ, hypDaughter.chi2, - d1.x, d1.y, d1.z, d1.px, d1.py, d1.pz, d1.tpcNcls, d1.tpcChi2, d1.itsNcls, d1.itsChi2, d1.itsMeanClsSizeL, - d1.rigidity, d1.tpcSignal, d1.tpcNsigma, d1.tpcNsigmaNhp, d1.tpcNsigmaNlp, d1.tofMass, d1.dcaXY, d1.dcaZ, d1.isPvContributor, - d2.x, d2.y, d2.z, d2.px, d2.py, d2.pz, d2.tpcNcls, d2.tpcChi2, d2.itsNcls, d2.itsChi2, d2.itsMeanClsSizeL, - d2.rigidity, d2.tpcSignal, d2.tpcNsigma, d2.tpcNsigmaNhp, d2.tpcNsigmaNlp, d2.tofMass, d2.dcaXY, d2.dcaZ, d2.isPvContributor, - d0.subMass, d1.subMass, d2.subMass, - sd1.x, sd1.y, sd1.z, sd1.px, sd1.py, sd1.pz, sd1.tpcNcls, sd1.tpcChi2, sd1.itsNcls, sd1.itsChi2, sd1.itsMeanClsSizeL, - sd1.rigidity, sd1.tpcSignal, sd1.tpcNsigma, sd1.tpcNsigmaNhp, sd1.tpcNsigmaNlp, sd1.tofMass, sd1.dcaXY, sd1.dcaZ, sd1.isPvContributor, - sd2.x, sd2.y, sd2.z, sd2.px, sd2.py, sd2.pz, sd2.tpcNcls, sd2.tpcChi2, sd2.itsNcls, sd2.itsChi2, sd2.itsMeanClsSizeL, - sd2.rigidity, sd2.tpcSignal, sd2.tpcNsigma, sd2.tpcNsigmaNhp, sd2.tpcNsigmaNlp, sd2.tofMass, sd2.dcaXY, sd2.dcaZ, sd2.isPvContributor); - if (isMC && cfgMCCombined) - outputTableMcThreeTwo( - cand.speciesMC, cand.pdgCode, cand.isMatterMC, cand.isReconstructed, cand.isPhysicalPrimary, cand.passedEvSelMC, cand.yGen, cand.ptGen, cand.ctGen, - cand.cpaPvGen, cand.pxGen, cand.pyGen, cand.pzGen, cand.pvxGen, cand.pvyGen, cand.pvzGen, cand.svxGen, cand.svyGen, cand.svzGen, - cand.species, cand.isMatter, cand.cent, cand.occu, cand.runNumber, cand.passedEvSel, cand.mass, cand.y, cand.pt, cand.ct, cand.cpaPv, cand.maxDcaTracks, cand.maxDcaTracksSv, - cand.dcaToPvXY, cand.dcaToPvZ, cand.devToPvXY, cand.chi2, cand.pvx, cand.pvy, cand.pvz, cand.svx, cand.svy, cand.svz, cand.px, cand.py, cand.pz, cand.collisionMcTrue, - hypDaughter.svx, hypDaughter.svy, hypDaughter.svz, d0.x, d0.y, d0.z, d0.px, d0.py, d0.pz, hypDaughter.mass, hypDaughter.ct, hypDaughter.cpaPv, - hypDaughter.maxDcaTracks, hypDaughter.dcaToPvXY, hypDaughter.dcaToPvZ, hypDaughter.dcaToVtxXY, hypDaughter.dcaToVtxZ, hypDaughter.chi2, - d1.x, d1.y, d1.z, d1.px, d1.py, d1.pz, d1.tpcNcls, d1.tpcChi2, d1.itsNcls, d1.itsChi2, d1.itsMeanClsSizeL, - d1.rigidity, d1.tpcSignal, d1.tpcNsigma, d1.tpcNsigmaNhp, d1.tpcNsigmaNlp, d1.tofMass, d1.dcaXY, d1.dcaZ, d1.isPvContributor, - d2.x, d2.y, d2.z, d2.px, d2.py, d2.pz, d2.tpcNcls, d2.tpcChi2, d2.itsNcls, d2.itsChi2, d2.itsMeanClsSizeL, - d2.rigidity, d2.tpcSignal, d2.tpcNsigma, d2.tpcNsigmaNhp, d2.tpcNsigmaNlp, d2.tofMass, d2.dcaXY, d2.dcaZ, d2.isPvContributor, - d0.subMass, d1.subMass, d2.subMass, - sd1.x, sd1.y, sd1.z, sd1.px, sd1.py, sd1.pz, sd1.tpcNcls, sd1.tpcChi2, sd1.itsNcls, sd1.itsChi2, sd1.itsMeanClsSizeL, - sd1.rigidity, sd1.tpcSignal, sd1.tpcNsigma, sd1.tpcNsigmaNhp, sd1.tpcNsigmaNlp, sd1.tofMass, sd1.dcaXY, sd1.dcaZ, sd1.isPvContributor, - sd2.x, sd2.y, sd2.z, sd2.px, sd2.py, sd2.pz, sd2.tpcNcls, sd2.tpcChi2, sd2.itsNcls, sd2.itsChi2, sd2.itsMeanClsSizeL, - sd2.rigidity, sd2.tpcSignal, sd2.tpcNsigma, sd2.tpcNsigmaNhp, sd2.tpcNsigmaNlp, sd2.tofMass, sd2.dcaXY, sd2.dcaZ, sd2.isPvContributor); - } - } - //___________________________________________________________________________________________________________________________________________________________ - void fillCandidatePrim(HyperNucleus& cand, aod::HypKfHypNuc const& hypNuc, aod::HypKfHypNucs const& hypNucs, aod::HypKfColls const& colls, aod::HypKfTracks const& tracks, aod::HypKfDaughtAdds const& daughterAdds, aod::HypKfSubDs const& subDs) - { - auto coll = hypNuc.hypKfColl(); - cand.ct = ct(coll, hypNuc); - cand.cpaPv = cpa(coll, hypNuc); - fillCandidate(cand, hypNuc, hypNucs, colls, tracks, daughterAdds, subDs); - } - //___________________________________________________________________________________________________________________________________________________________ - void fillCandidateSec(HyperNucleus& cand, aod::HypKfHypNuc const& hypNuc, aod::HypKfHypNuc const& mother, aod::HypKfHypNucs const& hypNucs, aod::HypKfColls const& colls, aod::HypKfTracks const& tracks, aod::HypKfDaughtAdds const& daughterAdds, aod::HypKfSubDs const& subDs) - { - cand.ct = ct(mother, hypNuc); - cand.cpaPv = cpa(mother, hypNuc); - fillCandidate(cand, hypNuc, hypNucs, colls, tracks, daughterAdds, subDs); } //___________________________________________________________________________________________________________________________________________________________ void fillCandidate(HyperNucleus& cand, aod::HypKfHypNuc const& hypNuc, aod::HypKfHypNucs const&, aod::HypKfColls const&, aod::HypKfTracks const&, aod::HypKfDaughtAdds const&, aod::HypKfSubDs const&) @@ -555,14 +296,14 @@ struct HypKfTreeCreator { auto addOns = hypNuc.hypKfDaughtAdd_as(); auto posVec = posVector(addOns); cand.species = std::abs(hypNuc.species()); - cand.isPrimaryCandidate = hypNuc.primary(); cand.isMatter = hypNuc.isMatter(); cand.mcTrue = hypNuc.mcTrue(); - cand.isCascade = cand.species > 10; // o2-linter: disable=magic-number (To be checked) cand.cent = coll.centFT0C(); cand.occu = coll.occupancy(); cand.runNumber = coll.runNumber(); cand.passedEvSel = coll.passedEvSel(); + cand.ct = ct(coll, hypNuc); + cand.cpaPv = cpa(coll, hypNuc); cand.mass = hypNuc.mass(); cand.y = hypNuc.y(); cand.pt = hypNuc.pt(); @@ -583,10 +324,7 @@ struct HypKfTreeCreator { cand.px = hypNuc.px(); cand.py = hypNuc.py(); cand.pz = hypNuc.pz(); - if (hypNuc.hypDaughterId() >= 0) { - TrackProperties hypDaughter; - cand.daughterTracks.push_back(hypDaughter); - } + auto daughterTracks = hypNuc.hypKfTrack_as(); for (const auto& track : daughterTracks) { TrackProperties daughter; @@ -594,7 +332,6 @@ struct HypKfTreeCreator { daughter.itsNcls = track.itsNcluster(); daughter.tpcChi2 = track.tpcChi2NCl(); daughter.itsChi2 = track.itsChi2NCl(); - daughter.itsMeanClsSize = track.itsMeanClsSize(); daughter.itsMeanClsSizeL = track.itsMeanClsSize() * track.lambda(); daughter.rigidity = track.rigidity(); daughter.tpcSignal = track.tpcSignal(); @@ -618,15 +355,8 @@ struct HypKfTreeCreator { trackCount++; } - if (cand.isCascade) { - auto subDaughters = hypNuc.hypKfSubD_as(); - for (const auto& subDaughter : subDaughters) { - cand.subDaughterMassVec.push_back(subDaughter.subMass()); - } - } - cand.nSingleDaughters = trackCount; - if (cand.nSingleDaughters < 3) // o2-linter: disable=magic-number (To be checked) + if (cand.nSingleDaughters < Decays::kThreeBody) return; trackCount = 0; @@ -637,6 +367,20 @@ struct HypKfTreeCreator { } //___________________________________________________________________________________________________________________________________________________________ + void processData(aod::HypKfHypNucs const& hypNucs, aod::HypKfColls const& hypKfColls, aod::HypKfTracks const& hypKfTrks, aod::HypKfDaughtAdds const& hypKfDAdd, aod::HypKfSubDs const& hypKfDSub) + { + for (const auto& hypNuc : hypNucs) { + if (cfgSpecies && std::abs(hypNuc.species()) != cfgSpecies) + continue; + HyperNucleus candidate; + fillCandidate(candidate, hypNuc, hypNucs, hypKfColls, hypKfTrks, hypKfDAdd, hypKfDSub); + fillTable(candidate); + } + } + PROCESS_SWITCH(HypKfTreeCreator, processData, "data tree", false); + + //___________________________________________________________________________________________________________________________________________________________ + void processMC(aod::HypKfMcParts const& mcHypNucs, aod::HypKfHypNucs const& hypNucs, aod::HypKfMcColls const&, aod::HypKfColls const& hypKfColls, aod::HypKfTracks const& hypKfTrks, aod::HypKfDaughtAdds const& hypKfDAdd, aod::HypKfSubDs const& hypKfDSub) { isMC = true; @@ -648,7 +392,6 @@ struct HypKfTreeCreator { auto hypNucsByMc = hypNucs.sliceBy(perMcParticle, mcParticleIdx); HyperNucleus candidate, hypNucDaughter; candidate.speciesMC = mcHypNuc.species(); - candidate.isCascadeMC = candidate.speciesMC > 10; // o2-linter: disable=magic-number (To be checked) candidate.pdgCode = mcHypNuc.pdgCode(); candidate.isMatterMC = mcHypNuc.isMatter(); candidate.isPhysicalPrimary = mcHypNuc.isPhysicalPrimary(); @@ -674,19 +417,12 @@ struct HypKfTreeCreator { candidate.collisionMcTrue = true; } candidate.isReconstructed++; - fillCandidatePrim(candidate, hypNucs.rawIteratorAt(hypNuc.globalIndex()), hypNucs, hypKfColls, hypKfTrks, hypKfDAdd, hypKfDSub); - if (hypNuc.hypDaughterId() >= 0) { - fillCandidateSec(hypNucDaughter, hypNucs.rawIteratorAt(hypNuc.hypDaughterId()), hypNucs.rawIteratorAt(hypNuc.globalIndex()), hypNucs, hypKfColls, hypKfTrks, hypKfDAdd, hypKfDSub); - } + fillCandidate(candidate, hypNucs.rawIteratorAt(hypNuc.globalIndex()), hypNucs, hypKfColls, hypKfTrks, hypKfDAdd, hypKfDSub); } - fillTable(candidate, hypNucDaughter); - hPt[0]->Fill(mcHypNuc.pt()); - if (candidate.isReconstructed) - hPt[1]->Fill(candidate.pt); + fillTable(candidate); } - hPt[2]->Divide(hPt[1].get(), hPt[0].get()); } - PROCESS_SWITCH(HypKfTreeCreator, processMC, "MC Gen tree", false); + PROCESS_SWITCH(HypKfTreeCreator, processMC, "MC tree", false); //___________________________________________________________________________________________________________________________________________________________ std::vector dcaTracksAll(std::vector& posVec, TString opt = "") @@ -787,22 +523,6 @@ struct HypKfTreeCreator { { return RecoDecay::cpa(primVtx(coll), decayVtx(hypNuc), momenta(hypNuc)); } - // only for Cascades - template - float decayLength(TPart const& mother, TPart const& daughter) - { - return RecoDecay::distance(decayVtx(mother), decayVtx(daughter)); - } - template - float ct(TPart const& mother, TPart const& daughter) - { - return RecoDecay::ct(momenta(daughter), decayLength(mother, daughter), daughter.mass()); - } - template - double cpa(TPart const& mother, TPart const& daughter) - { - return RecoDecay::cpa(decayVtx(mother), decayVtx(daughter), momenta(daughter)); - } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index 338f8bc971f..1928dbdbc45 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -24,21 +24,24 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" #include "Common/TableProducer/PID/pidTOFBase.h" #include "CCDB/BasicCCDBManager.h" #include "DCAFitter/DCAFitterN.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Track.h" +#include "Math/Vector4D.h" + #include #include #include @@ -48,6 +51,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using std::array; + using CollBracket = o2::math_utils::Bracket; using TracksFull = soa::Join; using CollisionsFull = soa::Join; @@ -55,6 +60,9 @@ using CollisionsFullMC = soa::Join; +using McCollisionMults = soa::Join; +using EventCandidatesMC = soa::Join; + namespace { constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; @@ -76,6 +84,30 @@ std::shared_ptr hH4LMassTracked; std::shared_ptr hDecayChannel; std::shared_ptr hIsMatterGen; std::shared_ptr hIsMatterGenTwoBody; +std::shared_ptr hEvtMC; +std::shared_ptr hImpactParamGen; +std::shared_ptr hImpactParamReco; +std::shared_ptr hGen3HLBeforeEvtSel; +std::shared_ptr hGen3HLAfterSel; +std::shared_ptr hGenEventsNchEta05; +std::shared_ptr hGenEventsNchEta08; +std::shared_ptr hGenCentralityColvsMultiplicityGenEta05; +std::shared_ptr hGenCentralityColvsMultiplicityGenEta08; +std::shared_ptr hGenCentralityColvsImpactParamGen; +std::shared_ptr hGenCentralityColvsFT0Cmultiplicity; +std::shared_ptr hRecoCentralityColvsMultiplicityRecoEta05; +std::shared_ptr hRecoCentralityColvsMultiplicityRecoEta08; +std::shared_ptr hRecoCentralityColvsImpactParamReco; +std::shared_ptr hRecoCentralityColvsFT0Cmultiplicity; +std::shared_ptr hGen3HLvsImpactParameterBeforeEvtSel; +std::shared_ptr hGen3HLvsImpactParameterAfterSel; +std::shared_ptr hGen3HLvsMultiplicityGenEta05BeforeEvtSel; +std::shared_ptr hGen3HLvsMultiplicityGenEta05AfterSel; +std::shared_ptr hGen3HLvsMultiplicityGenEta08BeforeEvtSel; +std::shared_ptr hGen3HLvsMultiplicityGenEta08AfterSel; +std::shared_ptr hGen3HLvsMultiplicityFT0CBeforeEvtSel; +std::shared_ptr hGen3HLvsMultiplicityFT0CAfterSel; + } // namespace struct hyperCandidate { @@ -116,6 +148,8 @@ struct hyperCandidate { uint8_t nTPCClustersPi = 0u; uint8_t nTPCpidClusHe3 = 0u; uint8_t nTPCpidClusPi = 0u; + uint8_t nTPCCrossedRowsHe3 = 0u; + uint8_t nTPCCrossedRowsPi = 0u; uint32_t clusterSizeITSHe3 = 0u; uint32_t clusterSizeITSPi = 0u; @@ -146,6 +180,7 @@ struct hyperRecoTask { // PDG codes Configurable hyperPdg{"hyperPDG", 1010010030, "PDG code of the hyper-mother (could be 3LamH or 4LamH)"}; Configurable heDauPdg{"heDauPDG", 1000020030, "PDG code of the helium (could be 3He or 4He)"}; + Configurable piDauPdg{"piDauPdg", 211, "PDG code of pion"}; // Selection criteria Configurable v0cospacut{"hypcospa", 0.95, "V0 CosPA"}; @@ -159,6 +194,8 @@ struct hyperRecoTask { Configurable nSigmaMaxHe{"nSigmaMaxHe", 5, "helium dEdx cut (n sigma)"}; Configurable nTPCClusMinHe{"nTPCClusMinHe", 70, "helium NTPC clusters cut"}; Configurable nTPCClusMinPi{"nTPCClusMinPi", -1., "pion NTPC clusters cut"}; + Configurable nTPCCrossedRowsMinHe{"nTPCCrossedRowsMinHe", 70, "helium minimum crossed rows"}; + Configurable nTPCCrossedRowsMinPi{"nTPCCrossedRowsMinPi", -1., "pion minimum crossed rows"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; Configurable isEventUsedForEPCalibration{"isEventUsedForEPCalibration", 1, "Event is used for EP calibration"}; @@ -179,6 +216,8 @@ struct hyperRecoTask { Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, particleName, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", true, "If true, divide tpcInnerParam by the electric charge"}; Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; + Configurable cfgEvSelkNoSameBunchPileup{"cfgEvSelkNoSameBunchPileup", false, "Rejects collisions which are associated with the same found-by-T0 bunch crossing"}; + Configurable cfgEvSelkIsGoodZvtxFT0vsPV{"cfgEvSelkIsGoodZvtxFT0vsPV", false, "Verifies the consistency between the primary vertex z position from tracking and the z position of the PV from FT0 timing"}; // CCDB options Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; @@ -196,6 +235,13 @@ struct hyperRecoTask { ConfigurableAxis zVtxBins{"zVtxBins", {100, -20.f, 20.f}, "Binning for n sigma"}; ConfigurableAxis centBins{"centBins", {100, 0.f, 100.f}, "Binning for centrality"}; + // histogram axes for EvtLossMC + ConfigurableAxis binsImpactPar{"binsImpactPar", {80, 0, 16}, "Binning of the impact parameter axis"}; + ConfigurableAxis binsCent{"binsCent", {10, 0.0, 100.0}, "Binning of the centrality axis"}; + ConfigurableAxis binsPt{"binsPt", {20, 0, 10}, "Binning of the pt"}; + ConfigurableAxis binsFT0CMult{"binsFT0CMult", {500, 0.0f, +500.0f}, "Binning of the FT0C multiplicity"}; + ConfigurableAxis binsMult{"binsMult", {500, 0.0f, +500.0f}, ""}; + // std vector of candidates std::vector hyperCandidates; // vector to keep track of MC mothers already filled @@ -216,7 +262,6 @@ struct hyperRecoTask { void init(InitContext const&) { - zorroSummary.setObject(zorro.getZorroSummary()); mRunNumber = 0; @@ -237,6 +282,7 @@ struct hyperRecoTask { int mat{static_cast(cfgMaterialCorrection)}; fitter.setMatCorrType(static_cast(mat)); + svCreator.setPDGs(heDauPdg, piDauPdg); svCreator.setTimeMargin(customVertexerTimeMargin); if (skipAmbiTracks) { svCreator.setSkipAmbiTracks(); @@ -247,6 +293,11 @@ struct hyperRecoTask { const AxisSpec nSigma3HeAxis{nSigmaBins, "n_{#sigma}({}^{3}He)"}; const AxisSpec zVtxAxis{zVtxBins, "z_{vtx} (cm)"}; const AxisSpec centAxis{centBins, "Centrality"}; + const AxisSpec impactParamAxis{binsImpactPar, "Impact Parameter (b)"}; + const AxisSpec centFT0CAxis{binsCent, "Centrality (FT0C %)"}; + const AxisSpec binsFT0CMultAxis{binsFT0CMult, "FT0C multiplicity"}; + const AxisSpec ptAxis{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec multAxis = {binsMult, "Multiplicity #eta <0.5"}; hNsigma3HeSel = qaRegistry.add("hNsigma3HeSel", "; p_{TPC}/z (GeV/#it{c}); n_{#sigma} ({}^{3}He)", HistType::kTH2F, {rigidityAxis, nSigma3HeAxis}); hDeDx3HeSel = qaRegistry.add("hDeDx3HeSel", ";p_{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dedxAxis}); @@ -256,9 +307,12 @@ 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, {{5, -0.5, 4.5}}); hEvents->GetXaxis()->SetBinLabel(1, "All"); - hEvents->GetXaxis()->SetBinLabel(2, "Selected"); + hEvents->GetXaxis()->SetBinLabel(2, "sel8"); + hEvents->GetXaxis()->SetBinLabel(3, "z_{vtx}"); + hEvents->GetXaxis()->SetBinLabel(4, "kNoSameBunchPileup"); + hEvents->GetXaxis()->SetBinLabel(5, "kIsGoodZvtxFT0vsPV"); hEventsZorro = qaRegistry.add("hEventsZorro", ";Events; ", HistType::kTH1D, {{2, -0.5, 1.5}}); hEventsZorro->GetXaxis()->SetBinLabel(1, "Zorro before evsel"); @@ -279,6 +333,43 @@ struct hyperRecoTask { hCentFT0A = qaRegistry.add("hCentFT0A", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); hCentFT0C = qaRegistry.add("hCentFT0C", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); hCentFT0M = qaRegistry.add("hCentFT0M", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); + + if (doprocessEventLossMC) { + hEvtMC = qaRegistry.add("QAEvent/hEvtMC", ";; ", HistType::kTH1D, {{3, -0.5, 2.5}}); + hEvtMC->GetXaxis()->SetBinLabel(1, "All gen evts"); + hEvtMC->GetXaxis()->SetBinLabel(2, "Gen evts with al least one reconstructed"); + hEvtMC->GetXaxis()->SetBinLabel(3, "Gen evts with no reconstructed collisions"); + hGenEventsNchEta05 = qaRegistry.add("QAEvent/hGenEventsNchEta05", ";;", HistType::kTH2D, {{multAxis}, {2, -0.5f, +1.5f}}); + hGenEventsNchEta05->GetYaxis()->SetBinLabel(1, "All gen. events"); + hGenEventsNchEta05->GetYaxis()->SetBinLabel(2, "Gen evts with at least 1 rec. collisions"); + hGenEventsNchEta08 = qaRegistry.add("QAEvent/hGenEventsNchEta08", ";;", HistType::kTH2D, {{multAxis}, {2, -0.5f, +1.5f}}); + hGenEventsNchEta08->GetYaxis()->SetBinLabel(1, "All gen. events"); + hGenEventsNchEta08->GetYaxis()->SetBinLabel(2, "Gen evts with at least 1 rec. collisions"); + // Infomation for all generated collisions collisions + hImpactParamGen = qaRegistry.add("QAEvent/McColAll/hImpactParamGen", "Impact parameter of generated MC events; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); + hGenCentralityColvsMultiplicityGenEta05 = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsMultiplicityGenEta05", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hGenCentralityColvsMultiplicityGenEta08 = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsMultiplicityGenEta08", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hGenCentralityColvsImpactParamGen = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsImpactParamGen", "Correlation between FT0C centrality and impact parameter in generated MC events; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); + hGenCentralityColvsFT0Cmultiplicity = qaRegistry.add("QAEvent/McColAll/hGenCentralityColvsFT0Cmultiplicity", "Correlation between FT0C centrality and FT0C multiplicity in generated MC events; FT0c multiplicity", HistType::kTH2D, {centFT0CAxis, binsFT0CMultAxis}); + // Infomation for generated collisions collisions with at least one rec. event + hImpactParamReco = qaRegistry.add("QAEvent/McColAll/hImpactParamReco", "Impact parameter of generated MC events with at least one rec. evt; Impact Parameter (b); Counts", HistType::kTH1D, {impactParamAxis}); + hRecoCentralityColvsMultiplicityRecoEta05 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta05", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt; Multiplicity #eta <0.5; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hRecoCentralityColvsMultiplicityRecoEta08 = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsMultiplicityRecoEta08", "Correlation between FT0C centrality and charged particle multiplicity in generated MC events with at least one rec. evt; Multiplicity #eta <0.8; Counts", HistType::kTH2D, {centFT0CAxis, multAxis}); + hRecoCentralityColvsImpactParamReco = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsImpactParamReco", "Correlation between FT0C centrality and impact parameter in generated MC events with at least one rec. evt; Impact Parameter (b); Counts", HistType::kTH2D, {centFT0CAxis, impactParamAxis}); + hRecoCentralityColvsFT0Cmultiplicity = qaRegistry.add("QAEvent/McColAll/hRecoCentralityColvsFT0Cmultiplicity", "Correlation between FT0C centrality and FT0C multiplicity in generated MC events with at least one rec. evt; FT0C (%); FT0c multiplicity", HistType::kTH2D, {centFT0CAxis, binsFT0CMultAxis}); + // Information of generated 3HL in generated events + hGen3HLBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLBeforeEvtSel", "3HL generated #it{p}_{T} distribution in all gen evt;#it{p}_{T} (GeV/#it{c}); Counts", HistType::kTH1D, {ptAxis}); + hGen3HLvsImpactParameterBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsImpactParameterBeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and impact parameter in all gen evt;#it{p}_{T} (GeV/#it{c}); Impact parameter (b)", HistType::kTH2D, {ptAxis, impactParamAxis}); + hGen3HLvsMultiplicityGenEta05BeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta05BeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.5", HistType::kTH2D, {ptAxis, multAxis}); + hGen3HLvsMultiplicityGenEta08BeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta08BeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.8", HistType::kTH2D, {ptAxis, multAxis}); + hGen3HLvsMultiplicityFT0CBeforeEvtSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityFT0CBeforeEvtSel", "Correlation 3HL generated #it{p}_{T} and FT0C multiplicity in all gen evt;#it{p}_{T} (GeV/#it{c}); FT0C Multiplicity", HistType::kTH2D, {ptAxis, binsFT0CMultAxis}); + // Information of generated 3HL in generated events with at least one rec. event + hGen3HLAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLAfterSel", "3HL generated #it{p}_{T} distribution in gen. evts with at least one rec. evt; #it{p}_{T} (GeV/#it{c}); Counts", HistType::kTH1D, {ptAxis}); + hGen3HLvsImpactParameterAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsImpactParameterAfterSel", "Correlation 3HL generated #it{p}_{T} and impact parameter in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Impact parameter (b)", HistType::kTH2D, {ptAxis, impactParamAxis}); + hGen3HLvsMultiplicityGenEta05AfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta05AfterSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.5", HistType::kTH2D, {ptAxis, multAxis}); + hGen3HLvsMultiplicityGenEta08AfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityGenEta08AfterSel", "Correlation 3HL generated #it{p}_{T} and charged particle multiplicity in gen. evts with at least one rec. evt;#it{p}_{T} (GeV/#it{c}); Multiplicity #eta <0.8", HistType::kTH2D, {ptAxis, multAxis}); + hGen3HLvsMultiplicityFT0CAfterSel = qaRegistry.add("QAEvent/McCol3HL/hGen3HLvsMultiplicityFT0CAfterSel", "Correlation 3HL generated #it{p}_{T} and FT0C multiplicity in gen. evts with at least one rec;#it{p}_{T} (GeV/#it{c}); FT0C Multiplicity", HistType::kTH2D, {ptAxis, binsFT0CMultAxis}); + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -361,16 +452,35 @@ struct hyperRecoTask { } } - if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > 10) { + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { continue; } + hEvents->Fill(1.); + + if (std::abs(collision.posZ()) > 10) { + continue; + } + hEvents->Fill(2.); + if (zorroSelected) { hEventsZorro->Fill(1.); } + if (cfgEvSelkNoSameBunchPileup) { + if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + hEvents->Fill(3.); + } + if (cfgEvSelkIsGoodZvtxFT0vsPV) { + if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + continue; + } + hEvents->Fill(4.); + } + goodCollision[collision.globalIndex()] = true; - hEvents->Fill(1.); hZvtx->Fill(collision.posZ()); hCentFT0A->Fill(collision.centFT0A()); hCentFT0C->Fill(collision.centFT0C()); @@ -388,21 +498,39 @@ struct hyperRecoTask { if (collision.has_mcCollision()) { recoCollisionIds[collision.mcCollisionId()] = collision.globalIndex(); } - if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > 10) + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) continue; + hEvents->Fill(1.); + + if (std::abs(collision.posZ()) > 10) { + continue; + } + hEvents->Fill(2.); + + if (cfgEvSelkNoSameBunchPileup) { + if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + hEvents->Fill(3.); + } + if (cfgEvSelkIsGoodZvtxFT0vsPV) { + if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + continue; + } + hEvents->Fill(4.); + } + if (collision.has_mcCollision()) { isSurvEvSelCollision[collision.mcCollisionId()] = true; } goodCollision[collision.globalIndex()] = true; - hEvents->Fill(1.); hZvtx->Fill(collision.posZ()); hCentFT0A->Fill(collision.centFT0A()); hCentFT0C->Fill(collision.centFT0C()); hCentFT0M->Fill(collision.centFT0M()); } } - template void fillHyperCand(Ttrack& heTrack, Ttrack& piTrack, CollBracket collBracket, const Tcolls& collisions, hyperCandidate& hypCand) { @@ -410,10 +538,12 @@ struct hyperRecoTask { hypCand.isMatter = heTrack.sign() > 0; hypCand.nSigmaHe3 = computeNSigmaHe3(heTrack); hypCand.nTPCClustersHe3 = heTrack.tpcNClsFound(); + hypCand.nTPCCrossedRowsHe3 = heTrack.tpcNClsCrossedRows(); hypCand.tpcSignalHe3 = heTrack.tpcSignal(); hypCand.nTPCpidClusHe3 = static_cast(heTrack.tpcNClsFindable()) - heTrack.tpcNClsFindableMinusPID(); hypCand.clusterSizeITSHe3 = heTrack.itsClusterSizes(); hypCand.nTPCClustersPi = piTrack.tpcNClsFound(); + hypCand.nTPCCrossedRowsPi = piTrack.tpcNClsCrossedRows(); hypCand.nTPCpidClusPi = static_cast(piTrack.tpcNClsFindable()) - piTrack.tpcNClsFindableMinusPID(); hypCand.tpcSignalPi = piTrack.tpcSignal(); hypCand.tpcChi2He3 = heTrack.tpcChi2NCl(); @@ -560,7 +690,7 @@ struct hyperRecoTask { if (std::abs(posTrack.eta()) > etaMax || std::abs(negTrack.eta()) > etaMax) continue; - // temporary fix: tpcInnerParam() returns the momentum in all the software tags before: https://github.com/AliceO2Group/AliceO2/pull/12521 + // temporary fix: tpcInnhRecoCentralityColvsFT0CmultiplicityerParam() returns the momentum in all the software tags before: https://github.com/AliceO2Group/AliceO2/pull/12521 auto nSigmaTPCpos = computeNSigmaHe3(posTrack); auto nSigmaTPCneg = computeNSigmaHe3(negTrack); // ITS only tracks do not have TPC information. TPCnSigma: only lower cut to allow for both hypertriton and hyperhydrogen4 reconstruction @@ -574,6 +704,9 @@ struct hyperRecoTask { if (heTrack.tpcNClsFound() < nTPCClusMinHe || piTrack.tpcNClsFound() < nTPCClusMinPi) { continue; } + if (heTrack.tpcNClsCrossedRows() < nTPCCrossedRowsMinHe || piTrack.tpcNClsCrossedRows() < nTPCCrossedRowsMinPi) { + continue; + } hyperCandidate hypCand; hypCand.v0ID = v0.globalIndex(); @@ -608,6 +741,10 @@ struct hyperRecoTask { continue; if (!isHe && track.tpcNClsFound() < nTPCClusMinPi) continue; + if (isHe && track.tpcNClsCrossedRows() < nTPCCrossedRowsMinHe) + continue; + if (!isHe && track.tpcNClsCrossedRows() < nTPCCrossedRowsMinPi) + continue; svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); } @@ -694,6 +831,7 @@ struct hyperRecoTask { hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); @@ -729,6 +867,7 @@ struct hyperRecoTask { hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); @@ -757,6 +896,7 @@ struct hyperRecoTask { hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); @@ -791,7 +931,7 @@ struct hyperRecoTask { hypCand.recoPtPi(), hypCand.recoPhiPi(), hypCand.recoEtaPi(), hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, - hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, hypCand.nTPCCrossedRowsHe3, hypCand.nTPCCrossedRowsPi, hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize, @@ -861,14 +1001,14 @@ struct hyperRecoTask { } outputMCTable(centFT0A, centFT0C, centFT0M, - mRunNumber, -1, -1, -1, - 0, -1, -1, -1, + mRunNumber, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, + -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, false, chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), hypCand.gDecVtx[0], hypCand.gDecVtx[1], hypCand.gDecVtx[2], @@ -887,6 +1027,124 @@ struct hyperRecoTask { processMC(collisions, mcCollisions, V0s, tracks, ambiTracks, bcs, trackLabelsMC, particlesMC); } PROCESS_SWITCH(hyperRecoTask, processMCTracked, "MC analysis with tracked V0s", false); + + template + bool passEvtSel(const CollType& collision) + { + if (!collision.sel8()) + return false; + + if ((std::abs(collision.posZ())) > 10) + return false; + + if (cfgEvSelkNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + + if (cfgEvSelkIsGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + + return true; + } + + void processEventLossMC(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& GenParticles) + { + if (std::abs(mcCollision.posZ()) > 10) { + return; + } + + //////////// Event loss estimation via impact parameter and multiplicity by MCFT0C + + // Fill all generated events + hEvtMC->Fill(0); + hImpactParamGen->Fill(mcCollision.impactParameter()); + hGenEventsNchEta05->Fill(mcCollision.multMCNParticlesEta05(), 0); + hGenEventsNchEta08->Fill(mcCollision.multMCNParticlesEta08(), 0); + + // Fill generated events with no reconstructed collisions + if (collisions.size() == 0) { + hEvtMC->Fill(1); + } + + // Define the generated events with at least one reconstructed event + bool atLeastOneRecoEvt = false; + auto centralityFT0C = -999.; + + for (auto const& col : collisions) { + if (!passEvtSel(col)) { + continue; + } + centralityFT0C = col.centFT0C(); + atLeastOneRecoEvt = true; + } + + hGenCentralityColvsMultiplicityGenEta05->Fill(centralityFT0C, mcCollision.multMCNParticlesEta05()); + hGenCentralityColvsMultiplicityGenEta08->Fill(centralityFT0C, mcCollision.multMCNParticlesEta08()); + hGenCentralityColvsImpactParamGen->Fill(centralityFT0C, mcCollision.impactParameter()); + hGenCentralityColvsFT0Cmultiplicity->Fill(centralityFT0C, mcCollision.multMCFT0C()); + + if (atLeastOneRecoEvt) { + hEvtMC->Fill(2); + hGenEventsNchEta05->Fill(mcCollision.multMCNParticlesEta05(), 1); + hGenEventsNchEta08->Fill(mcCollision.multMCNParticlesEta08(), 1); + hImpactParamReco->Fill(mcCollision.impactParameter()); + hRecoCentralityColvsMultiplicityRecoEta05->Fill(centralityFT0C, mcCollision.multMCNParticlesEta05()); + hRecoCentralityColvsMultiplicityRecoEta08->Fill(centralityFT0C, mcCollision.multMCNParticlesEta08()); + hRecoCentralityColvsImpactParamReco->Fill(centralityFT0C, mcCollision.impactParameter()); + hRecoCentralityColvsFT0Cmultiplicity->Fill(centralityFT0C, mcCollision.multMCFT0C()); + } + // Construct the H3L 4-vector based on the generated daugthers identification by PDG + ROOT::Math::PxPyPzMVector daugh1, daugh2, mother; + + for (const auto& genParticle : GenParticles) { + if (std::abs(genParticle.y()) > 1) + continue; + if (std::abs(genParticle.pdgCode()) != hyperPdg) + continue; + + auto daughters = genParticle.daughters_as(); + + bool dauHe3 = false, dauPiMinus = false, dauAntiHe3 = false, dauPiPos = true; + + for (const auto& daughter : daughters) { + if (daughter.pdgCode() == heDauPdg) { + dauHe3 = true; + daugh1 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), he3Mass); + } else if (daughter.pdgCode() == -piDauPdg) { + dauPiMinus = true; + daugh2 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), piMass); + } + if (daughter.pdgCode() == -heDauPdg) { + dauAntiHe3 = true; + daugh1 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), he3Mass); + } else if (daughter.pdgCode() == piDauPdg) { + dauPiPos = true; + daugh2 = ROOT::Math::PxPyPzMVector(daughter.px(), daughter.py(), daughter.pz(), piMass); + } + } + // Check pairs to avoid wrong charge associations + if (!((dauHe3 && dauPiMinus) || !(dauAntiHe3 && dauPiPos))) + continue; + + mother = daugh1 + daugh2; + + // Fill informations for generated 3HL in all generated events + hGen3HLBeforeEvtSel->Fill(mother.pt()); + hGen3HLvsImpactParameterBeforeEvtSel->Fill(mother.pt(), mcCollision.impactParameter()); + hGen3HLvsMultiplicityGenEta05BeforeEvtSel->Fill(mother.pt(), mcCollision.multMCNParticlesEta05()); + hGen3HLvsMultiplicityGenEta08BeforeEvtSel->Fill(mother.pt(), mcCollision.multMCNParticlesEta08()); + hGen3HLvsMultiplicityFT0CBeforeEvtSel->Fill(mother.pt(), mcCollision.multMCFT0C()); + + // Fill informations for generated 3HL in generated events with at least one reconstructed event + if (atLeastOneRecoEvt) { + hGen3HLAfterSel->Fill(mother.pt()); + hGen3HLvsImpactParameterAfterSel->Fill(mother.pt(), mcCollision.impactParameter()); + hGen3HLvsMultiplicityGenEta05AfterSel->Fill(mother.pt(), mcCollision.multMCNParticlesEta05()); + hGen3HLvsMultiplicityGenEta08AfterSel->Fill(mother.pt(), mcCollision.multMCNParticlesEta08()); + hGen3HLvsMultiplicityFT0CAfterSel->Fill(mother.pt(), mcCollision.multMCFT0C()); + } + } + } + PROCESS_SWITCH(hyperRecoTask, processEventLossMC, "Event loss analysis", false); }; WorkflowSpec diff --git a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx index d2f5bcd6102..b932d8ba624 100644 --- a/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/lnnRecoTask.cxx @@ -8,14 +8,13 @@ // 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. -// -// Build \Lambda-n-n candidates from V0s and tracks + +/// \file lnnRecoTask.cxx +/// \brief Reconstruction task for the \Lambda nn candidate +/// \author Maria Paula Palhares // ============================================================================== -#include "PWGLF/DataModel/EPCalibrationTables.h" #include "PWGLF/DataModel/LFLnnTables.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/Core/PID/TPCPIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" @@ -29,17 +28,17 @@ #include "DCAFitter/DCAFitterN.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" +#include "PID/PIDTOF.h" +#include "PID/TPCPIDResponse.h" #include "ReconstructionDataFormats/Track.h" -#include - #include #include #include @@ -50,16 +49,22 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using TracksFull = soa::Join; -using TracksFullMC = soa::Join; +using TracksFull = soa::Join; +using TracksFullMC = soa::Join; using CollisionsFull = soa::Join; using CollisionsFullMC = soa::Join; +using CollisionCandidates = o2::soa::Join; +using CollisionCandidatesMC = o2::soa::Join; +using TrackCandidates = o2::soa::Join; +using TrackCandidatesMC = o2::soa::Join; + namespace { -constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +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 NucleiName{"3H"}; +static const std::vector nucleiName{"3H"}; +// Histograms for QA lnn-task std::shared_ptr hEvents; std::shared_ptr hZvtx; std::shared_ptr hCentFT0A; @@ -70,15 +75,41 @@ std::shared_ptr hNsigma3HSel; std::shared_ptr hNsigma3HSelTOF; std::shared_ptr hdEdx3HSel; std::shared_ptr hdEdx3HPosTrack; +std::shared_ptr hdEdx3HNegTrack; std::shared_ptr hdEdxTot; std::shared_ptr h3HMassPtTOF; std::shared_ptr h3HSignalPtTOF; -std::shared_ptr hDecayChannel; std::shared_ptr hIsMatterGen; -std::shared_ptr hIsMatterGenTwoBody; -std::shared_ptr hDCAxy3H; std::shared_ptr hLnnCandLoss; -std::shared_ptr hNSigma3HTPC_preselection; +std::shared_ptr hDecayChannel; +// QA histograms before track selections +std::shared_ptr h2FT0CnClusTPCtoTrBfSel; +std::shared_ptr h2FT0CnClusTPCtoPiBfSel; +std::shared_ptr h2FT0Cchi2NClTPCtoTrBfSel; +std::shared_ptr h2FT0Cchi2NClITStoTrBfSel; +std::shared_ptr h2FT0CnTPCNClsCrossedRows3HBfSel; +std::shared_ptr h2FT0CnTPCNClsCrossedRowsPiBfSel; +// QA ITS-TPC and ITS-TPC-TOF track signals +std::shared_ptr h2FT0CptTrBfSelItsTpc; +std::shared_ptr h2FT0CptTrBfSelItsTpcTof; +std::shared_ptr h2FT0CptPiBfSelItsTpc; +// QA MC tracks from the lnn decay +std::shared_ptr hPtGeneratedTrStr; +std::shared_ptr hPtGeneratedPiStr; +std::shared_ptr hPtItsTpcTrStr; +std::shared_ptr hPtTrkItsTpcTrStr; +std::shared_ptr hPtItsTpcTofTrStr; +std::shared_ptr hPtTrkItsTpcTofTrStr; +std::shared_ptr hPtItsTpcPiStr; +std::shared_ptr hPtTrkItsTpcPiStr; +// QA reco generated candidate and daugher particles from secondary vertex +std::shared_ptr h2FT0CPtGenColRecCandMC; +std::shared_ptr h2FT0CPtGenColRecTrStrMC; +std::shared_ptr h2FT0CPtGenColRecPiStrMC; +// QA signal generated candidate and daugher particles from secondary vertex +std::shared_ptr h2FT0CPtGenColGenCandMC; +std::shared_ptr h2FT0CPtGenColGenTrStrMC; +std::shared_ptr h2FT0CPtGenColGenPiStrMC; float alphaAP(std::array const& momB, std::array const& momC) { @@ -91,18 +122,27 @@ float alphaAP(std::array const& momB, std::array const& momC } // namespace -struct lnnCandidate { +struct LnnCandidate { float recoPt3H() const { return std::hypot(mom3H[0], mom3H[1]); } float recoPhi3H() const { return std::atan2(mom3H[1], mom3H[0]); } float recoEta3H() const { return std::asinh(mom3H[2] / recoPt3H()); } + float recoPtPi() const { return std::hypot(momPi[0], momPi[1]); } float recoPhiPi() const { return std::atan2(momPi[1], momPi[0]); } float recoEtaPi() const { return std::asinh(momPi[2] / recoPtPi()); } + float genPt() const { return std::hypot(gMom[0], gMom[1]); } - float genPt3H() const { return std::hypot(gMom3H[0], gMom3H[1]); } float genPhi() const { return std::atan2(gMom[1], gMom[0]); } float genEta() const { return std::asinh(gMom[2] / genPt()); } + float genPt3H() const { return std::hypot(gMom3H[0], gMom3H[1]); } + float genPhi3H() const { return std::atan2(gMom3H[1], gMom3H[0]); } + float genEta3H() const { return std::asinh(gMom3H[2] / genPt3H()); } + + float genPtPi() const { return std::hypot(gMomPi[0], gMomPi[1]); } + float genPhiPi() const { return std::atan2(gMomPi[1], gMomPi[0]); } + float genEtaPi() const { return std::asinh(gMomPi[2] / genPtPi()); } + int posTrackID; int negTrackID; float dcaV0dau = -10; @@ -113,8 +153,8 @@ struct lnnCandidate { float mom3HTPC = -10.f; float momPiTPC = -10.f; float mass2TrTOF = -10.f; - float DCAPvto3H = -10.f; - float DCAPvtoPi = -10.f; + float dcaPvto3H = -10.f; + float dcaPvtoPi = -10.f; float beta = -10.f; float tpcChi3H = -10.f; std::array mom3H; @@ -122,17 +162,21 @@ struct lnnCandidate { std::array decVtx; std::array gMom; std::array gMom3H; + std::array gMomPi; std::array gDecVtx; uint16_t tpcSignal3H = 0u; uint16_t tpcSignalPi = 0u; uint8_t nTPCClusters3H = 0u; uint8_t nTPCClustersPi = 0u; + uint8_t nTPCClustersCrossedRows3H = 0u; + uint8_t nTPCClustersCrossedRowsPi = 0u; uint32_t clusterSizeITS3H = 0u; uint32_t clusterSizeITSPi = 0u; bool isMatter = false; bool isSignal = false; // true MC signal bool isReco = false; // true if the candidate is actually reconstructed bool survEvSelection = false; // true if the corresponding event passed the event selection + bool recoMcColl = false; // true if the mc collision is reconstructed int pdgCode = 0; // PDG code of the hypernucleus uint8_t flags = 0u; // flags for dughter particles }; @@ -144,23 +188,27 @@ struct lnnRecoTask { Service ccdb; // Selection criteria - Configurable v0cospa{"lnncospa", 0.95, "V0 CosPA"}; - Configurable masswidth{"lnnmasswidth", 0.1, "Mass width (GeV/c^2)"}; - Configurable dcav0dau{"lnndcaDau", 0.6, "DCA V0 Daughters"}; - Configurable Chi2nClusTPCMax{"Chi2NClusTPCMax", 4, "Chi2 / nClusTPC for triton track max"}; - Configurable Chi2nClusTPCMin{"Chi2NClusTPC", 0.5, "Chi2 / nClusTPC for triton track min"}; - Configurable Chi2nClusITS{"Chi2NClusITS", 36., "Chi2 / nClusITS for triton track"}; + Configurable v0cospa{"v0cospa", 0.95, "V0 CosPA"}; + Configurable masswidth{"masswidth", 0.1, "Mass width (GeV/c^2)"}; + Configurable dcav0dau{"dcav0dau", 0.6, "DCA V0 Daughters"}; + Configurable chi2nClusTPCMax{"chi2nClusTPCMax", 4, "Chi2 / nClusTPC for triton track max"}; + Configurable chi2nClusTPCMin{"chi2nClusTPCMin", 0.5, "Chi2 / nClusTPC for triton track min"}; + 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.2, "Minimum rigidity of the triton candidate"}; + Configurable etaMax{"etaMax", 0.8, "eta daughter"}; + Configurable tpcRigidityMin3H{"tpcRigidityMin3H", 0.2, "Minimum rigidity of the triton candidate"}; Configurable nSigmaCutMinTPC{"nSigmaCutMinTPC", -5, "triton dEdx cut (n sigma)"}; Configurable nSigmaCutMaxTPC{"nSigmaCutMaxTPC", 5, "triton dEdx cut (n sigma)"}; + Configurable nTPCNClsCrossedRows3H{"nTPCNClsCrossedRows3H", 80, "Number of crossed TPC Rows for triton"}; + Configurable nTPCNClsCrossedRowsPi{"nTPCNClsCrossedRowsPi", 80, "Number of crossed TPC Rows for pions"}; Configurable nTPCClusMin3H{"nTPCClusMin3H", 80, "triton NTPC clusters cut"}; Configurable nTPCClusMinPi{"nTPCClusMinPi", 60, "pion NTPC clusters cut"}; Configurable ptMinTOF{"ptMinTOF", 0.8, "minimum pt for TOF cut"}; - Configurable TrTOFMass2Cut{"TrTOFMass2Cut", 5.5, "minimum Triton mass square to TOF"}; - Configurable BetaTrTOF{"BetaTrTOF", 0.4, "minimum beta TOF cut"}; + Configurable trTOFMass2Cut{"trTOFMass2Cut", 5.5, "minimum Triton mass square to TOF"}; + Configurable betaTrTOF{"betaTrTOF", 0.4, "minimum beta TOF cut"}; Configurable mcSignalOnly{"mcSignalOnly", true, "If true, save only signal in MC"}; + Configurable doTrackQA{"doTrackQA", true, "if true, compute the QA studies beased on detectors (ITS-TPC-TOF) signals"}; + Configurable useNoSameBunchPileup{"useNoSameBunchPileup", false, "reject collisions in case of pileup with another collision in the same foundBC"}; // Define o2 fitter, 2-prong, active memory (no need to redefine per event) o2::vertexing::DCAFitterN<2> fitter; @@ -170,12 +218,12 @@ struct lnnRecoTask { float piMass = o2::constants::physics::MassPionCharged; // bethe bloch parameters - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, NucleiName, 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 - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable d_bz_input{"d_bz_input", -999., "bz field, -999 is automatic"}; + Configurable ccdburl{"ccdburl", "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"}; @@ -184,32 +232,40 @@ struct lnnRecoTask { // PDG codes Configurable h3DauPdg{"h3DauPdg", 1000010030, "PDG Triton"}; // PDG Triton + Configurable piDauPdg{"piDauPdg", 211, "PDG Pi"}; // PDG Pi Configurable lnnPdg{"lnnPdg", 1010000030, "PDG Lnn"}; // PDG Lnn - // histogram axes - ConfigurableAxis rigidityBins{"rigidityBins", {200, -10.f, 10.f}, "Binning for rigidity #it{p}^{TPC}/#it{z}"}; + // Histogram configuration QA lnn-task + ConfigurableAxis rigidityBins{"rigidityBins", {200, -10.f, 10.f}, "Binning for rigidity"}; 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 nSigmaBins{"nSigmaBins", {200, -5.f, 5.f}, "Binning for n#sigma_{TPC}"}; + ConfigurableAxis zVtxBins{"zVtxBins", {100, -20.f, 20.f}, "Binning for vtx z"}; ConfigurableAxis centBins{"centBins", {100, 0.f, 100.f}, "Binning for centrality"}; - ConfigurableAxis TritMomBins{"TritMomBins", {100, -5.f, 5.f}, "Binning for Triton momentum"}; - ConfigurableAxis MassTOFBins{"MassTOFBins", {400, 2.0f, 12.f}, "Binning for Triton Mass TOF"}; - ConfigurableAxis PtTritonBins{"PtTritonBins", {200, -5.f, 5.f}, "Binning for Triton p values"}; - ConfigurableAxis PtPosTritonBins{"PtPosTritonBins", {200, 0.f, 5.f}, "Binning for Triton pt positive values"}; - ConfigurableAxis BetaBins{"BetaBins", {550, 0.f, 1.1f}, "Binning for Beta"}; - ConfigurableAxis DCAxyBins{"DCAxyBins", {550, -5.f, 5.f}, "Binning for DCAxy"}; + ConfigurableAxis mTOFBins{"mTOFBins", {400, 2.0f, 12.f}, "Binning for triton mass TOF"}; + ConfigurableAxis tPtBins{"tPtBins", {160, -10.f, 10.f}, "Binning for (anti-)triton pt"}; + ConfigurableAxis tPtPosBins{"tPtPosBins", {160, 0, 8.f}, "Binning for (anti-)triton pt > 0"}; + ConfigurableAxis tPPosBins{"tPPosBins", {200, 0.f, 5.f}, "Binning for triton rigidity (p)"}; + ConfigurableAxis tPNegBins{"tPNegBins", {200, -5.f, 0.f}, "Binning for anti-triton rigidity (p)"}; + ConfigurableAxis betaBins{"betaBins", {550, 0.f, 1.1f}, "Binning for Beta"}; + ConfigurableAxis dcaXYBins{"dcaXYBins", {550, -5.f, 5.f}, "Binning for dcaXY triton"}; + ConfigurableAxis tpcNClusBins{"tpcNClusBins", {260, 30, 165}, "Binning for nClusTPC"}; + ConfigurableAxis tpcNClsCrossedRowsBins{"TPCNClsCrossedRowsBins", {260, 30, 165}, "Binning for TPCNClsCrossedRows"}; + ConfigurableAxis tpcChi2NClusBins{"tpcChi2NClusBins", {20, 0.5, 10}, "Binning for chi2NClusTPC"}; + ConfigurableAxis itsChi2NClusBins{"itsChi2NClusBins", {72, 0, 36}, "Binning for chi2NClusTPC"}; + ConfigurableAxis candPtBins{"candPtBins", {160, 0, 8}, "Binning for lnn cand pt"}; + ConfigurableAxis candEtaBins{"candEtaBins", {160, -0.8, 0.8}, "Binning for eta"}; // std vector of candidates - std::vector lnnCandidates; + std::vector lnnCandidates; // vector to keep track of MC mothers already filled std::vector filledMothers; // vector to keep track of the collisions passing the event selection in the MC std::vector isGoodCollision; std::vector collisionFT0Ccent; + std::vector recoCollisionIds; // vector to armazenade h3Track Preslice perCollision = o2::aod::v0::collisionId; - HistogramRegistry qaRegistry{"QA", {}, OutputObjHandlingPolicy::AnalysisObject}; int mRunNumber; @@ -241,31 +297,57 @@ struct lnnRecoTask { const AxisSpec dEdxAxis{dEdxBins, "d#it{E}/d#it{x}"}; const AxisSpec nSigma3HAxis{nSigmaBins, "n_{#sigma}({}^{3}H)"}; const AxisSpec zVtxAxis{zVtxBins, "z_{vtx} (cm)"}; - const AxisSpec centAxis{centBins, "Centrality"}; - const AxisSpec TritMomAxis{TritMomBins, "#it{p}({}^{3}H)"}; - const AxisSpec PtTrAxis{PtTritonBins, "#it{p_T}({}^{3}H)"}; - const AxisSpec PtPosTrAxis{PtPosTritonBins, "#it{p_T}({}^{3}H)"}; - const AxisSpec MassTOFAxis{MassTOFBins, "{m}^{2}/{z}^{2}"}; - const AxisSpec BetaAxis{BetaBins, "#beta (TOF)"}; - const AxisSpec DCAxyAxis(DCAxyBins, "DCAxy ({}^{3}H) (cm)"); - - 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_{T} ({}^{3}H) (GeV/#it{c^2}); n#sigma_{TOF} ({}^{3}H)", HistType::kTH2F, {PtTrAxis, 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}); + const AxisSpec centAxis{centBins, "FT0C (%)"}; + const AxisSpec mTOFAxis{mTOFBins, "#frac{m^{2}}{z^{2}}"}; + const AxisSpec tPtAxis{tPtBins, "#it{p}_{T} (Gev/#it{c})"}; + const AxisSpec tPosRigidityAxis{tPPosBins, "#it{p}^{TPC}/#it{z}"}; + const AxisSpec tPNegRigidityAxis{tPNegBins, "#it{p}^{TPC}/#it{z}"}; + const AxisSpec betaAxis{betaBins, "#beta_{TOF}"}; + const AxisSpec dcaXYAxis(dcaXYBins, "DCA_{xy} ({}^{3}H (cm)"); + const AxisSpec tpcNClusAxis(tpcNClusBins, "N_{clus}^{TPC}"); + const AxisSpec tpcNClsCrossedRowsAxis(tpcNClsCrossedRowsBins, "N_{TPC} crossed rows"); + const AxisSpec tpcChi2NClusAxis(tpcChi2NClusBins, "{#Chi}^{2}/N_{clus}^{TPC}"); + const AxisSpec itsChi2NClusAxis(itsChi2NClusBins, "{#Chi}^{2}/N_{clus}^{ITS}"); + const AxisSpec candPtAxis(candPtBins, "#it{p}_{T} (Gev/#it{c})"); + const AxisSpec candEtaAxis(candEtaBins, "#eta"); + + hNsigma3HSel = qaRegistry.add("PID/hNsigma3HSel", ";#it{p}^{TPC}/z (GeV/#it{c}); n_{#sigma} ({}^{3}H)", HistType::kTH2F, {rigidityAxis, nSigma3HAxis}); + hNsigma3HSelTOF = qaRegistry.add("PID/hNsigma3HSelTOF", ";#it{p}_{T} (GeV/#it{c}); n_{#sigma} ({}^{3}H)", HistType::kTH2F, {tPtAxis, nSigma3HAxis}); + hdEdx3HSel = qaRegistry.add("hdEdx3HSel", ";#it{p}^{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {rigidityAxis, dEdxAxis}); + hdEdx3HPosTrack = qaRegistry.add("PID/hdEdx3HPosTrack", "; #it{p}^{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {tPosRigidityAxis, dEdxAxis}); + hdEdx3HNegTrack = qaRegistry.add("PID/hdEdx3HNegTrack", "; #it{p}^{TPC}/z (GeV/#it{c}); dE/dx", HistType::kTH2F, {tPNegRigidityAxis, 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, {PtTrAxis, MassTOFAxis}); - h3HSignalPtTOF = qaRegistry.add("h3HSignalPtTOF", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta (TOF)", HistType::kTH2F, {PtTrAxis, BetaAxis}); - hDCAxy3H = qaRegistry.add("hDCAxy3H", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #it{DCA}_{xy} 3H", HistType::kTH2F, {PtPosTrAxis, DCAxyAxis}); - hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{2, -0.5, 1.5}}); - hLnnCandLoss = qaRegistry.add("hLnnCandLoss", ";CandLoss; ", HistType::kTH1D, {{7, -0.5, 6.5}}); - hNSigma3HTPC_preselection = qaRegistry.add("hNSigma3HTPC_preselection", "#it{p}/z (GeV/#it{c}); n#sigma_{TPC}(^{3}H)", HistType::kTH2F, {rigidityAxis, nSigma3HAxis}); + h3HMassPtTOF = qaRegistry.add("PID/hTrMassPtTOF", "; #it{p}_{T} ({}^{3}H) (GeV/#it{c}); #frac{m^{2}}{z^{2}} (GeV^{2}/#it{c}^{4})", HistType::kTH2F, {tPtAxis, mTOFAxis}); + h3HSignalPtTOF = qaRegistry.add("PID/h3HSignalPtTOF", "; #it{p}_{T}({}^{3}H) (GeV/#it{c}); #beta_{TOF}", HistType::kTH2F, {tPtAxis, betaAxis}); + hEvents = qaRegistry.add("hEvents", ";Events; ", HistType::kTH1D, {{4, -0.5, 3.5}}); + hLnnCandLoss = qaRegistry.add("CandCounts/hLnnCandLoss", ";CandLoss; ", HistType::kTH1D, {{7, -0.5, 6.5}}); + // QA its-tpc and its-tpc-tof tracks before selection + h2FT0CnClusTPCtoTrBfSel = qaRegistry.add("QATracks/h2FT0CnClusTPCtoTrBfSel", ";FT0C (%);N_{clus}^{TPC}", HistType::kTH2F, {centAxis, tpcNClusAxis}); + h2FT0CnClusTPCtoPiBfSel = qaRegistry.add("QATracks/h2FT0CnClusTPCtoPiBfSel", ";FT0C (%);N_{clus}^{TPC}", HistType::kTH2F, {centAxis, tpcNClusAxis}); + h2FT0Cchi2NClTPCtoTrBfSel = qaRegistry.add("QATracks/h2FT0Cchi2NClTPCtoTrBfSel", ";FT0C (%);{#Chi}^{2}/N_{clus}^{TPC} ", HistType::kTH2F, {centAxis, tpcChi2NClusAxis}); + h2FT0Cchi2NClITStoTrBfSel = qaRegistry.add("QATracks/h2FT0Cchi2NClITStoTrBfSel", ";FT0C (%);{#Chi}^{2}/N_{clus}^{ITS}", HistType::kTH2F, {centAxis, itsChi2NClusAxis}); + h2FT0CnTPCNClsCrossedRows3HBfSel = qaRegistry.add("QATracks/h2FT0CnTPCNClsCrossedRows3H", ";FT0C (%);N_{TPC} crossed rows", HistType::kTH2F, {centAxis, tpcNClsCrossedRowsAxis}); + h2FT0CnTPCNClsCrossedRowsPiBfSel = qaRegistry.add("QATracks/h2FT0CnTPCNClsCrossedRowsPi", ";FT0C (%);N_{TPC} crossed rows", HistType::kTH2F, {centAxis, tpcNClsCrossedRowsAxis}); + h2FT0CptTrBfSelItsTpc = qaRegistry.add("QATracks/h2FT0CptTrBfSelItsTpc", ";FT0C (%);#it{p}_{T}", HistType::kTH2F, {centAxis, candPtBins}); + h2FT0CptTrBfSelItsTpcTof = qaRegistry.add("QATracks/h2FT0CptTrBfSelItsTpcTof", ";FT0C (%);#it{p}_{T}", HistType::kTH2F, {centAxis, candPtBins}); + h2FT0CptPiBfSelItsTpc = qaRegistry.add("QATracks/h2FT0CptPiBfSelItsTpc", ";FT0C (%);#it{p}_{T}", HistType::kTH2F, {centAxis, candPtBins}); + // QA its-tpc, its-tpc-tof, and generated MC + hPtItsTpcTrStr = qaRegistry.add("MC/McTracks/hPtItsTpcTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtTrkItsTpcTrStr = qaRegistry.add("MC/McTracks/hPtTrkItsTpcTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtItsTpcTofTrStr = qaRegistry.add("MC/McTracks/hPtItsTpcTofTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtTrkItsTpcTofTrStr = qaRegistry.add("MC/McTracks/hPtTrkItsTpcTofTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtItsTpcPiStr = qaRegistry.add("MC/McTracks/hPtItsTpcPiStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtTrkItsTpcPiStr = qaRegistry.add("MC/McTracks/hPtTrkItsTpcPiStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtGeneratedTrStr = qaRegistry.add("MC/McGen/hPtGeneratedTrStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); + hPtGeneratedPiStr = qaRegistry.add("MC/McGen/hPtGeneratedPiStr", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{10, 0, 100}, {160, 0, 8}}); hEvents->GetXaxis()->SetBinLabel(1, "All"); hEvents->GetXaxis()->SetBinLabel(2, "sel8"); - hLnnCandLoss->GetYaxis()->SetTitle("#it{N}_{candidates}"); + hEvents->GetXaxis()->SetBinLabel(3, "z_{vtx}"); + hEvents->GetXaxis()->SetBinLabel(4, "NoSameBunchPileUp"); + hLnnCandLoss->GetYaxis()->SetTitle("#it{N}_{cand}"); hLnnCandLoss->GetXaxis()->SetTitle("Cuts"); - hLnnCandLoss->GetXaxis()->SetBinLabel(1, "Initial LnnCandidates"); + hLnnCandLoss->GetXaxis()->SetBinLabel(1, "Initial"); hLnnCandLoss->GetXaxis()->SetBinLabel(2, "not 3H"); hLnnCandLoss->GetXaxis()->SetBinLabel(3, "not anti3H"); hLnnCandLoss->GetXaxis()->SetBinLabel(4, "#it{p}_{Tmin}"); @@ -273,14 +355,20 @@ struct lnnRecoTask { hLnnCandLoss->GetXaxis()->SetBinLabel(6, "DCA #it{V}_{0} daughter"); hLnnCandLoss->GetXaxis()->SetBinLabel(7, "cosPA"); if (doprocessMC) { - hDecayChannel = qaRegistry.add("hDecayChannel", ";Decay channel; ", HistType::kTH1D, {{2, -0.5, 1.5}}); - hDecayChannel->GetXaxis()->SetBinLabel(1, "2-body"); - hIsMatterGen = qaRegistry.add("hIsMatterGen", ";; ", HistType::kTH1D, {{2, -0.5, 1.5}}); + hDecayChannel = qaRegistry.add("MC/hDecayChannel", ";Decay channel; ", HistType::kTH1D, {{2, -0.5, 1.5}}); + hDecayChannel->GetXaxis()->SetBinLabel(1, "All"); + hDecayChannel->GetXaxis()->SetBinLabel(2, "2-body"); + hIsMatterGen = qaRegistry.add("MC/hIsMatterGen", ";; ", HistType::kTH1D, {{2, -0.5, 1.5}}); hIsMatterGen->GetXaxis()->SetBinLabel(1, "Matter"); hIsMatterGen->GetXaxis()->SetBinLabel(2, "Antimatter"); - hIsMatterGenTwoBody = qaRegistry.add("hIsMatterGenTwoBody", ";; ", HistType::kTH1D, {{2, -0.5, 1.5}}); - hIsMatterGenTwoBody->GetXaxis()->SetBinLabel(1, "Matter"); - hIsMatterGenTwoBody->GetXaxis()->SetBinLabel(2, "Antimatter"); + // QA for generated mother candidate and daughter particles + h2FT0CPtGenColRecCandMC = qaRegistry.add("MC/RecMcCol/h2FT0CPtGenColRecCandMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColRecTrStrMC = qaRegistry.add("MC/RecMcCol/h2FT0CPtGenColRecTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColRecPiStrMC = qaRegistry.add("MC/RecMcCol/h2FT0CPtGenColRecPiStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + // QA signal generated candidate and daugher particles from secondary vertex + h2FT0CPtGenColGenCandMC = qaRegistry.add("MC/QASignalGenSV/h2FT0CPtGenColGenCandMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColGenTrStrMC = qaRegistry.add("MC/QASignalGenSV/h2FT0CPtGenColGenTrStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); + h2FT0CPtGenColGenPiStrMC = qaRegistry.add("MC/QASignalGenSV/h2FT0CPtGenColGenPiStrMC", ";FT0C (%);#it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {centAxis, candPtAxis}); } hZvtx = qaRegistry.add("hZvtx", ";z_{vtx} (cm); ", HistType::kTH1D, {{100, -20, 20}}); hCentFT0A = qaRegistry.add("hCentFT0A", ";Centrality; ", HistType::kTH1D, {{100, 0, 100}}); @@ -297,11 +385,13 @@ struct lnnRecoTask { } auto run3grp_timestamp = bc.timestamp(); + static const double kBzAutoThreshold = -990.; + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); o2::parameters::GRPMagField* grpmag = 0x0; if (grpo) { o2::base::Propagator::initFieldFromGRP(grpo); - if (d_bz_input < -990) { + if (d_bz_input < kBzAutoThreshold) { // 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"; @@ -314,7 +404,7 @@ struct lnnRecoTask { 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); - if (d_bz_input < -990) { + if (d_bz_input < kBzAutoThreshold) { // 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"; @@ -343,7 +433,7 @@ struct lnnRecoTask { LOG(fatal) << "Bethe-Bloch parameters for 3H not set, please check your CCDB and configuration"; } - for (auto& v0 : V0s) { + for (const auto& v0 : V0s) { auto posTrack = v0.posTrack_as(); auto negTrack = v0.negTrack_as(); @@ -378,7 +468,7 @@ struct lnnRecoTask { std::array momPos = std::array{posTrack.px(), posTrack.py(), posTrack.pz()}; std::array momNeg = std::array{negTrack.px(), negTrack.py(), negTrack.pz()}; float alpha = alphaAP(momPos, momNeg); - lnnCandidate lnnCand; + LnnCandidate lnnCand; lnnCand.isMatter = alpha > 0; hLnnCandLoss->Fill(0.); if ((lnnCand.isMatter && !is3H) || (!lnnCand.isMatter && !isAnti3H)) { @@ -393,26 +483,54 @@ struct lnnRecoTask { auto& h3track = lnnCand.isMatter ? posTrack : negTrack; auto& pitrack = lnnCand.isMatter ? negTrack : posTrack; auto& h3Rigidity = lnnCand.isMatter ? posRigidity : negRigidity; + auto& piRigidity = lnnCand.isMatter ? negRigidity : posRigidity; + + // fill QA track histogram studies to check track signal before selections + h2FT0CnClusTPCtoTrBfSel->Fill(collision.centFT0C(), h3track.tpcNClsFound()); + h2FT0CnClusTPCtoPiBfSel->Fill(collision.centFT0C(), pitrack.tpcNClsFound()); + h2FT0CnTPCNClsCrossedRows3HBfSel->Fill(collision.centFT0C(), h3track.tpcNClsCrossedRows()); + h2FT0CnTPCNClsCrossedRowsPiBfSel->Fill(collision.centFT0C(), pitrack.tpcNClsCrossedRows()); + h2FT0Cchi2NClTPCtoTrBfSel->Fill(collision.centFT0C(), h3track.tpcChi2NCl()); + h2FT0Cchi2NClITStoTrBfSel->Fill(collision.centFT0C(), h3track.itsChi2NCl()); + + if (doTrackQA) { + bool passedTrTrackITS = h3track.hasITS(); + bool passedTrTrackTOF = h3track.hasTOF(); + bool passedPiTrackITS = pitrack.hasITS(); + if (passedTrTrackITS) { + h2FT0CptTrBfSelItsTpc->Fill(collision.centFT0C(), h3track.pt()); + if (passedTrTrackTOF) { + h2FT0CptTrBfSelItsTpcTof->Fill(collision.centFT0C(), h3track.pt()); + } + } + if (passedPiTrackITS) { + h2FT0CptPiBfSelItsTpc->Fill(collision.centFT0C(), pitrack.pt()); + } + } - if (h3Rigidity < TPCRigidityMin3H || - h3track.tpcNClsFound() < nTPCClusMin3H || - h3track.tpcChi2NCl() < Chi2nClusTPCMin || - h3track.tpcChi2NCl() > Chi2nClusTPCMax || - h3track.itsChi2NCl() > Chi2nClusITS || - pitrack.tpcNClsFound() < nTPCClusMinPi) { + if (h3Rigidity < tpcRigidityMin3H || + h3track.tpcNClsCrossedRows() < nTPCNClsCrossedRows3H || + h3track.tpcChi2NCl() < chi2nClusTPCMin || + h3track.tpcChi2NCl() > chi2nClusTPCMax || + h3track.itsChi2NCl() > chi2nClusITS || + pitrack.tpcNClsCrossedRows() < nTPCNClsCrossedRowsPi) { continue; } - lnnCand.tpcChi3H = lnnCand.isMatter ? h3track.tpcChi2NCl() : negTrack.tpcChi2NCl(); + lnnCand.tpcChi3H = h3track.tpcChi2NCl(); lnnCand.nSigma3H = lnnCand.isMatter ? nSigmaTPCpos : nSigmaTPCneg; - 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; + lnnCand.nTPCClusters3H = h3track.tpcNClsFound(); + lnnCand.nTPCClustersCrossedRows3H = h3track.tpcNClsCrossedRows(); + lnnCand.tpcSignal3H = h3track.tpcSignal(); + lnnCand.clusterSizeITS3H = h3track.itsClusterSizes(); + + lnnCand.nTPCClustersPi = pitrack.tpcNClsFound(); + lnnCand.nTPCClustersCrossedRowsPi = pitrack.tpcNClsCrossedRows(); + lnnCand.tpcSignalPi = pitrack.tpcSignal(); + lnnCand.clusterSizeITSPi = pitrack.itsClusterSizes(); + + lnnCand.mom3HTPC = h3Rigidity; + lnnCand.momPiTPC = piRigidity; lnnCand.flags |= lnnCand.isMatter ? static_cast((posTrack.pidForTracking() & 0xF) << 4) : static_cast((negTrack.pidForTracking() & 0xF) << 4); lnnCand.flags |= lnnCand.isMatter ? static_cast(negTrack.pidForTracking() & 0xF) : static_cast(posTrack.pidForTracking() & 0xF); @@ -423,14 +541,13 @@ struct lnnRecoTask { float beta = -1.f; if (h3track.pt() >= ptMinTOF) { - hNSigma3HTPC_preselection->Fill(h3track.tpcInnerParam(), lnnCand.nSigma3H); if (!h3track.hasTOF()) { continue; } beta = h3track.beta(); lnnCand.mass2TrTOF = h3track.mass() * h3track.mass(); - if (lnnCand.mass2TrTOF < TrTOFMass2Cut || beta < BetaTrTOF) { + if (lnnCand.mass2TrTOF < trTOFMass2Cut || beta < betaTrTOF) { continue; } } @@ -459,7 +576,8 @@ struct lnnRecoTask { float h3lE = h3E + piE; // Building the mother particle: lnn - std::array lnnMom; + constexpr std::size_t kMomDim = 3; + std::array lnnMom; const auto& vtx = fitter.getPCACandidate(); for (int i = 0; i < 3; i++) { @@ -472,7 +590,6 @@ struct lnnRecoTask { hLnnCandLoss->Fill(3.); continue; } - // Definition of lnn mass float mLNN_HypHI = 3.00; // , but 2993.7 MeV/c**2 float massLNNL = std::sqrt(h3lE * h3lE - lnnMom[0] * lnnMom[0] - lnnMom[1] * lnnMom[1] - lnnMom[2] * lnnMom[2]); @@ -492,7 +609,8 @@ struct lnnRecoTask { continue; } - std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; + constexpr std::size_t kprimVtxDim = 3; + std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; double cosPA = RecoDecay::cpa(primVtx, lnnCand.decVtx, lnnMom); if (cosPA < v0cospa) { @@ -519,10 +637,13 @@ struct lnnRecoTask { lnnCandidates.push_back(lnnCand); - // Fill QA histograms + // Fill 2D map after all selections hdEdx3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, h3track.tpcSignal()); + hdEdx3HPosTrack->Fill(lnnCand.mom3HTPC, h3track.tpcSignal()); + if (!lnnCand.isMatter) { + hdEdx3HNegTrack->Fill(-lnnCand.mom3HTPC, h3track.tpcSignal()); + } hNsigma3HSel->Fill(chargeFactor * lnnCand.mom3HTPC, lnnCand.nSigma3H); - hDCAxy3H->Fill(h3track.pt(), h3track.dcaXY()); if (h3track.hasTOF()) { h3HSignalPtTOF->Fill(chargeFactor * h3track.pt(), beta); hNsigma3HSelTOF->Fill(chargeFactor * h3track.p(), h3track.tofNSigmaTr()); @@ -548,26 +669,33 @@ struct lnnRecoTask { for (auto& posMother : mcTrackPos.mothers_as()) { if (posMother.globalIndex() != negMother.globalIndex()) continue; - if (!((mcTrackPos.pdgCode() == h3DauPdg && mcTrackNeg.pdgCode() == -211) || (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -1 * h3DauPdg))) + if (!((mcTrackPos.pdgCode() == h3DauPdg && mcTrackNeg.pdgCode() == -1 * piDauPdg) || (mcTrackPos.pdgCode() == piDauPdg && mcTrackNeg.pdgCode() == -1 * h3DauPdg))) continue; if (std::abs(posMother.pdgCode()) != lnnPdg) continue; // Checking primary and second vertex with MC simulations - std::array posPrimVtx = {posMother.vx(), posMother.vy(), posMother.vz()}; - - std::array secVtx = {mcTrackPos.vx(), mcTrackPos.vy(), mcTrackPos.vz()}; + constexpr std::size_t kposVtxDim = 3; + std::array posPrimVtx = {posMother.vx(), posMother.vy(), posMother.vz()}; + constexpr std::size_t ksecVtxDim = 3; + std::array secVtx = {mcTrackPos.vx(), mcTrackPos.vy(), mcTrackPos.vz()}; lnnCand.gMom = posMother.pVector(); - lnnCand.gMom3H = mcTrackPos.pdgCode() == h3DauPdg ? mcTrackPos.pVector() : mcTrackNeg.pVector(); + bool isTrTrack = (mcTrackPos.pdgCode() == h3DauPdg); + + lnnCand.gMom3H = isTrTrack ? mcTrackPos.pVector() : mcTrackNeg.pVector(); + + lnnCand.gMomPi = isTrTrack ? mcTrackNeg.pVector() : mcTrackPos.pVector(); for (int i = 0; i < 3; i++) { lnnCand.gDecVtx[i] = secVtx[i] - posPrimVtx[i]; } + lnnCand.isSignal = true; lnnCand.pdgCode = posMother.pdgCode(); lnnCand.survEvSelection = isGoodCollision[posMother.mcCollisionId()]; + lnnCand.recoMcColl = recoCollisionIds[posMother.mcCollisionId()] > 0; filledMothers.push_back(posMother.globalIndex()); } } @@ -576,6 +704,57 @@ struct lnnRecoTask { } } + bool isLnnDecay(aod::McParticles::iterator const& mcPart) + { + if (!mcPart.has_mothers()) + return false; + + if (mcPart.getProcess() != 4) + return false; + + bool motherIsAccepted = false; + auto mothers = mcPart.mothers_as(); + for (const auto& mother : mothers) { + if (std::abs(mother.pdgCode()) == lnnPdg) { + motherIsAccepted = true; + break; + } + } + return motherIsAccepted; + } + + template + void fillMcHistograms(TracksFullMC::iterator const& mcTrack, aod::McParticles::iterator const& mc, Tcoll const& collision) + { + + bool passedTrackITS = mcTrack.hasITS(); + bool passedTrackTPC = mcTrack.hasTPC(); + bool passedTrackTOF = mcTrack.hasTOF(); + + int pdg = std::abs(mc.pdgCode()); + + if (pdg == h3DauPdg) { + hPtGeneratedTrStr->Fill(collision.centFT0C(), mc.pt()); + + if (passedTrackITS && passedTrackTPC) { + hPtItsTpcTrStr->Fill(collision.centFT0C(), mc.pt()); + hPtTrkItsTpcTrStr->Fill(collision.centFT0C(), mcTrack.pt()); + if (passedTrackTOF) { + hPtItsTpcTofTrStr->Fill(collision.centFT0C(), mc.pt()); + hPtTrkItsTpcTofTrStr->Fill(collision.centFT0C(), mcTrack.pt()); + } + } + } + + if (pdg == piDauPdg) { + hPtGeneratedPiStr->Fill(collision.centFT0C(), mc.pt()); + if (passedTrackITS && passedTrackTPC) { + hPtItsTpcPiStr->Fill(collision.centFT0C(), mc.pt()); + hPtTrkItsTpcPiStr->Fill(collision.centFT0C(), mcTrack.pt()); + } + } + } + void processData(CollisionsFull const& collisions, aod::V0s const& V0s, TracksFull const& tracks, aod::BCsWithTimestamps const&) { for (const auto& collision : collisions) { @@ -585,10 +764,19 @@ struct lnnRecoTask { initCCDB(bc); hEvents->Fill(0.); - if ((!collision.sel8()) || std::abs(collision.posZ()) > 10) { + if ((!collision.sel8())) { continue; } hEvents->Fill(1.); + if (std::abs(collision.posZ()) > 10) { + continue; + } + hEvents->Fill(2.); + if (useNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + hEvents->Fill(3.); + hZvtx->Fill(collision.posZ()); hCentFT0A->Fill(collision.centFT0A()); hCentFT0C->Fill(collision.centFT0C()); @@ -601,7 +789,7 @@ struct lnnRecoTask { fillCandidateData(collision, V0Table_thisCollision); - for (auto& lnnCand : lnnCandidates) { + for (const auto& lnnCand : lnnCandidates) { outputDataTable(collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ(), lnnCand.isMatter, @@ -609,7 +797,7 @@ struct lnnRecoTask { lnnCand.recoPtPi(), lnnCand.recoPhiPi(), lnnCand.recoEtaPi(), lnnCand.decVtx[0], lnnCand.decVtx[1], lnnCand.decVtx[2], lnnCand.dcaV0dau, lnnCand.h3DCAXY, lnnCand.piDCAXY, - lnnCand.nSigma3H, lnnCand.nTPCClusters3H, lnnCand.nTPCClustersPi, + lnnCand.nSigma3H, lnnCand.nTPCClusters3H, lnnCand.nTPCClustersPi, lnnCand.nTPCClustersCrossedRows3H, lnnCand.nTPCClustersCrossedRowsPi, lnnCand.mom3HTPC, lnnCand.momPiTPC, lnnCand.tpcSignal3H, lnnCand.tpcSignalPi, lnnCand.mass2TrTOF, lnnCand.tpcChi3H, lnnCand.clusterSizeITS3H, lnnCand.clusterSizeITSPi, lnnCand.flags); @@ -619,26 +807,52 @@ struct lnnRecoTask { PROCESS_SWITCH(lnnRecoTask, processData, "Data analysis", true); // MC process - 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) + void processMC(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, aod::V0s const& V0s, aod::BCsWithTimestamps const&, TracksFull const& tracks, TracksFullMC const& tracksMC, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC) { filledMothers.clear(); - isGoodCollision.clear(); isGoodCollision.resize(mcCollisions.size(), false); collisionFT0Ccent.clear(); collisionFT0Ccent.resize(mcCollisions.size(), -1.f); + recoCollisionIds.clear(); + recoCollisionIds.resize(mcCollisions.size(), -1); for (const auto& collision : collisions) { + for (auto const& trackMC : tracksMC) { + + if (!trackMC.has_mcParticle()) + continue; + + auto mc = trackMC.mcParticle(); + + if (!isLnnDecay(mc)) + continue; + + fillMcHistograms(trackMC, mc, collision); + } + lnnCandidates.clear(); auto bc = collision.bc_as(); initCCDB(bc); hEvents->Fill(0.); + if (collision.has_mcCollision()) { + recoCollisionIds[collision.mcCollisionId()] = collision.globalIndex(); + } - if (std::abs(collision.posZ()) > 10) { + if ((!collision.sel8())) { continue; } hEvents->Fill(1.); + if (std::abs(collision.posZ()) > 10) { + continue; + } + hEvents->Fill(2.); + if (useNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + hEvents->Fill(3.); + hZvtx->Fill(collision.posZ()); hCentFT0A->Fill(collision.centFT0A()); hCentFT0C->Fill(collision.centFT0C()); @@ -657,11 +871,16 @@ struct lnnRecoTask { fillCandidateData(collision, V0Table_thisCollision); fillMCinfo(trackLabelsMC, particlesMC); - for (auto& lnnCand : lnnCandidates) { + for (const auto& lnnCand : lnnCandidates) { if (!lnnCand.isSignal && mcSignalOnly) { continue; } int chargeFactor = -1 + 2 * (lnnCand.pdgCode > 0); + if (lnnCand.recoMcColl && lnnCand.survEvSelection) { + h2FT0CPtGenColRecCandMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt()); + h2FT0CPtGenColRecTrStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPt3H()); + h2FT0CPtGenColRecPiStrMC->Fill(collision.centFT0C(), chargeFactor * lnnCand.genPtPi()); + } outputMCTable(collision.centFT0A(), collision.centFT0C(), collision.centFT0M(), collision.posX(), collision.posY(), collision.posZ(), lnnCand.isMatter, @@ -669,58 +888,65 @@ struct lnnRecoTask { lnnCand.recoPtPi(), lnnCand.recoPhiPi(), lnnCand.recoEtaPi(), lnnCand.decVtx[0], lnnCand.decVtx[1], lnnCand.decVtx[2], lnnCand.dcaV0dau, lnnCand.h3DCAXY, lnnCand.piDCAXY, - lnnCand.nSigma3H, lnnCand.nTPCClusters3H, lnnCand.nTPCClustersPi, + lnnCand.nSigma3H, lnnCand.nTPCClusters3H, lnnCand.nTPCClustersPi, lnnCand.nTPCClustersCrossedRows3H, lnnCand.nTPCClustersCrossedRowsPi, lnnCand.mom3HTPC, lnnCand.momPiTPC, lnnCand.tpcSignal3H, lnnCand.tpcSignalPi, lnnCand.mass2TrTOF, lnnCand.tpcChi3H, 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); + chargeFactor * lnnCand.genPt(), lnnCand.genPhi(), lnnCand.genEta(), chargeFactor * lnnCand.genPt3H(), + lnnCand.gDecVtx[0], lnnCand.gDecVtx[1], lnnCand.gDecVtx[2], lnnCand.isReco, lnnCand.isSignal, lnnCand.recoMcColl, lnnCand.survEvSelection); } - } // now we fill only the signal candidates that were not reconstructed - for (auto& mcPart : particlesMC) { + for (const auto& mcPart : particlesMC) { if (std::abs(mcPart.pdgCode()) != lnnPdg) { continue; } - std::array secVtx; - std::array primVtx = {mcPart.vx(), mcPart.vy(), mcPart.vz()}; + float cent = collisionFT0Ccent[mcPart.mcCollisionId()]; + + h2FT0CPtGenColGenCandMC->Fill(cent, mcPart.pt()); + + constexpr std::size_t kVtxDim = 3; + std::array secVtx; + std::array primVtx = {mcPart.vx(), mcPart.vy(), mcPart.vz()}; - std::array momMother = mcPart.pVector(); + constexpr std::size_t kArrayDim = 3; + std::array momMother = mcPart.pVector(); - std::array mom3H; + std::array mom3H; + std::array momPi; bool is3HFound = false; - for (auto& mcDaught : mcPart.daughters_as()) { - if (std::abs(mcDaught.pdgCode()) == h3DauPdg) { - secVtx = {mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; - mom3H = mcDaught.pVector(); + for (const auto& mcDaught : mcPart.daughters_as()) { + int pdg = std::abs(mcDaught.pdgCode()); + if (pdg == h3DauPdg) { + secVtx = {mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; + mom3H = mcDaught.pVector(); + h2FT0CPtGenColGenTrStrMC->Fill(cent, mcDaught.pt()); is3HFound = true; - break; + } + if (pdg == piDauPdg) { + momPi = mcDaught.pVector(); + h2FT0CPtGenColGenPiStrMC->Fill(cent, mcDaught.pt()); } } + if (mcPart.pdgCode() > 0) { hIsMatterGen->Fill(0.); } else { hIsMatterGen->Fill(1.); } + if (!is3HFound) { hDecayChannel->Fill(1.); - continue; } hDecayChannel->Fill(0.); - if (mcPart.pdgCode() > 0) { - hIsMatterGenTwoBody->Fill(0.); - } else { - hIsMatterGenTwoBody->Fill(1.); - } if (std::find(filledMothers.begin(), filledMothers.end(), mcPart.globalIndex()) != std::end(filledMothers)) { continue; } - lnnCandidate lnnCand; + LnnCandidate lnnCand; lnnCand.pdgCode = mcPart.pdgCode(); lnnCand.survEvSelection = isGoodCollision[mcPart.mcCollisionId()]; int chargeFactor = -1 + 2 * (lnnCand.pdgCode > 0); @@ -728,23 +954,34 @@ struct lnnRecoTask { lnnCand.gDecVtx[i] = secVtx[i] - primVtx[i]; lnnCand.gMom[i] = momMother[i]; lnnCand.gMom3H[i] = mom3H[i]; + lnnCand.gMomPi[i] = momPi[i]; } + lnnCand.posTrackID = -1; lnnCand.negTrackID = -1; lnnCand.isSignal = true; - outputMCTable(-1, collisionFT0Ccent[mcPart.mcCollisionId()], -1, + + float centFT0A = -1, centFT0C = -1, centFT0M = -1; + if (lnnCand.recoMcColl) { + auto recoCollision = collisions.rawIteratorAt(recoCollisionIds[mcPart.mcCollisionId()]); + centFT0A = recoCollision.centFT0A(); + centFT0C = recoCollision.centFT0C(); + centFT0M = recoCollision.centFT0M(); + } + outputMCTable(centFT0A, centFT0C, centFT0M, -1, -1, -1, 0, -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, chargeFactor * lnnCand.genPt(), lnnCand.genPhi(), lnnCand.genEta(), lnnCand.genPt3H(), - lnnCand.gDecVtx[0], lnnCand.gDecVtx[1], lnnCand.gDecVtx[2], lnnCand.isReco, lnnCand.isSignal, lnnCand.survEvSelection); + lnnCand.gDecVtx[0], lnnCand.gDecVtx[1], lnnCand.gDecVtx[2], lnnCand.isReco, lnnCand.isSignal, lnnCand.recoMcColl, lnnCand.survEvSelection); + } } } PROCESS_SWITCH(lnnRecoTask, processMC, "MC analysis", false); diff --git a/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx b/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx index b97456ecdcb..71cbd488d71 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiAntineutronCex.cxx @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -50,10 +51,10 @@ struct NucleiAntineutronCex { // === Cut values === static constexpr double kIts2MinR = 4.5; // ITS2 min radius (exluding IB) [cm] - static constexpr double kIts2MaxR = 45.0; // ITS2 max radius [cm] + static constexpr double kIts2MaxR = 48.0; // ITS2 max radius [cm] static constexpr double kIts2MaxVz = 39.0; // ITS2 max |vz| [cm] static constexpr double kAccMaxEta = 1.2; // acceptance |eta| - static constexpr double kAccMaxVz = 5.3; // acceptance |vz| [cm] + static constexpr double kAccMaxVz = 10.0; // acceptance |vz| [cm] static constexpr double kStrictEta = 0.9; // tighter eta cut static constexpr double kInitDplane = 10.0; // init dplane static constexpr double kHuge = 1e9; // fallback for bad denom @@ -102,8 +103,24 @@ struct NucleiAntineutronCex { histos.add("pEta", "Pseudorapidity;#eta;Entries", kTH1F, {{100, -10., 10.}}); histos.add("pP_ITScuts", "Momentum with ITS cuts;|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); - // test (MC) - histos.add("antip_test", "Secondary antiprotons;|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); + // Process enum breakdown (secondary antiproton that anchors the SV) + histos.add("hProcEnumAP_CEX", "procEnum of secondary #bar{p} (CEX);procEnum;Entries", kTH1I, {{100, -0.5, 99.5}}); + histos.add("hProcEnumAP_BG", "procEnum of secondary #bar{p} (BG);procEnum;Entries", kTH1I, {{100, -0.5, 99.5}}); + + // Multiplicity/composition at the SV (MC truth, for FINAL selected candidates) + histos.add("hVtxNAll_CEX", "N(all) secondaries at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNAll_BG", "N(all) secondaries at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNCh_CEX", "N(charged) secondaries at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNCh_BG", "N(charged) secondaries at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNNeut_CEX", "N(neutral) secondaries at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNNeut_BG", "N(neutral) secondaries at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + + histos.add("hVtxNPi0_CEX", "N(#pi^{0}) at SV (CEX);N;Entries", kTH1I, {{40, -0.5, 39.5}}); + histos.add("hVtxNPi0_BG", "N(#pi^{0}) at SV (BG);N;Entries", kTH1I, {{40, -0.5, 39.5}}); + histos.add("hVtxNGamma_CEX", "N(#gamma) at SV (CEX);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNGamma_BG", "N(#gamma) at SV (BG);N;Entries", kTH1I, {{60, -0.5, 59.5}}); + histos.add("hVtxNN_CEX", "N(n) at SV (CEX);N;Entries", kTH1I, {{40, -0.5, 39.5}}); + histos.add("hVtxNN_BG", "N(n) at SV (BG);N;Entries", kTH1I, {{40, -0.5, 39.5}}); // CEX pair from antineutron (MC) histos.add("cexPairMcP", "CEX pair total momentum;|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); @@ -130,6 +147,13 @@ struct NucleiAntineutronCex { histos.add("cexbg_pairmc_vtxz", "Background secondary vertex Z;Z (cm);Entries", kTH1F, {{200, -60., 60.}}); histos.add("cexbg_pairmc_pITScuts", "Background momentum (ITS cuts);|p| (GeV/c);Entries", kTH1F, {{100, 0., 10.}}); + histos.add("hDeltaP_CEX", "|p_{mother}-Σp_{SV}| (CEX);Δp (GeV/c);Entries", kTH1F, {{200, 0., 10.}}); + histos.add("hDeltaP_BG", "|p_{mother}-Σp_{SV}| (BG);Δp (GeV/c);Entries", kTH1F, {{200, 0., 10.}}); + + // Mother IB hits + histos.add("hMotherNHitIB_CEX", "Mother IB hit layers (L0-L2) (CEX);N_{IB layers};Entries", kTH1I, {{5, -1.5, 4.5}}); + histos.add("hMotherNHitIB_BG", "Mother IB hit layers (L0-L2) (BG);N_{IB layers};Entries", kTH1I, {{5, -1.5, 4.5}}); + // CEX pair from antineutron (TRK) histos.add("cex_pairtrk_angle", "Pair opening angle (tracks);Angle (°);Entries", kTH1F, {{180, 0., 180.}}); histos.add("cexPairTrkP", "Pair momentum (tracks);|p| (GeV/c);Entries", kTH1F, {{120, 0., 12.}}); @@ -260,26 +284,31 @@ struct NucleiAntineutronCex { const bool isSecondaryFromMaterial = (!particle.producedByGenerator()) && (procEnum == kPHadronic || procEnum == kPHInhelastic); if (particle.pdgCode() != -kProton || !isSecondaryFromMaterial || particle.mothersIds().empty()) continue; - histos.fill(HIST("antip_test"), particle.p()); // Primary mother bool hasPrimaryMotherAntip = false; double motherPt = 0.0; + double motherPx = 0.0; + double motherPy = 0.0; double motherPz = 0.0; double motherVz = 0.0; double motherP = 0.0; double motherEta = 0.0; int motherPdg = 0; + int motherId = -1; for (const auto& mother : particle.mothers_as()) { if (mother.isPhysicalPrimary()) { hasPrimaryMotherAntip = true; motherPt = mother.pt(); + motherPx = mother.px(); + motherPy = mother.py(); motherPz = mother.pz(); motherVz = mother.vz(); motherP = mother.p(); motherEta = mother.eta(); motherPdg = mother.pdgCode(); + motherId = mother.globalIndex(); break; } } @@ -530,6 +559,9 @@ struct NucleiAntineutronCex { int8_t antipTrkItsPidValid = 0; float antipTrkTgl = 0.f; + bool motherHasTrack = false; + int motherNHitIB = -1; // number of hits in IB (L0-L2) + o2::aod::ITSResponse itsResponse; for (const auto& track : tracks) { @@ -557,6 +589,11 @@ struct NucleiAntineutronCex { int nITS = track.itsNCls(); bool layerCondition = (!hitIB) && hitOuter && (nITS >= kMinItsHits); + if (mc.globalIndex() == motherId) { + motherHasTrack = true; + motherNHitIB = static_cast(hitL0) + static_cast(hitL1) + static_cast(hitL2); + } + if (mc.globalIndex() == antipId) { antipTrkP = track.p(); antipTrkPx = track.px(); @@ -695,6 +732,13 @@ struct NucleiAntineutronCex { const TVector3 pv2sv(secX - pvtxX, secY - pvtxY, secZ - pvtxZ); const double pairPointingAngleDeg = pv2sv.Angle(total_trk_pVec) * Rad2Deg; + const double pvsvThetaDeg = pv2sv.Theta() * Rad2Deg; + + double pvsvPhiDeg = pv2sv.Phi() * Rad2Deg; + if (pvsvPhiDeg < 0.) { + pvsvPhiDeg += 360.; + } + const double pP = pVecProton_trk.Mag(); const double pAP = AntipVecProton_trk.Mag(); const double ptP = pVecProton_trk.Pt(); @@ -715,7 +759,7 @@ struct NucleiAntineutronCex { const float dOpenAngle = trkangleDeg - mcangleDeg; // Closest ITS layer: Radius need to be checked - static const std::array rLayers = {2.2, 2.8, 3.6, 19.6, 24.0, 29.0, 35.0}; + static const std::array rLayers = {2.3, 3.1, 3.9, 24.0, 30.0, 42.0, 48.0}; int16_t svNearestLayerId = -1; float svDeltaRToLayer = 1e9f; for (int i = 0; i < static_cast(rLayers.size()); ++i) { @@ -757,16 +801,112 @@ struct NucleiAntineutronCex { const bool isCex = (motherPdg == -kNeutron); + // Nature of the process + if (isCex) { + histos.fill(HIST("hProcEnumAP_CEX"), static_cast(procEnum)); + } else { + histos.fill(HIST("hProcEnumAP_BG"), static_cast(procEnum)); + } + + // Count material secondaries produced at the same SV as the selected secondary antiproton. + int vtxNAll = 0; + int vtxNCh = 0; + int vtxNNeut = 0; + int vtxNPi0 = 0; + int vtxNGamma = 0; + int vtxNN = 0; + double sumPx_vtx = 0.0; + double sumPy_vtx = 0.0; + double sumPz_vtx = 0.0; + auto* pdgDB = TDatabasePDG::Instance(); + + for (const auto& particle5 : mcPartsThis) { + if (particle5.mcCollisionId() != colId) { + continue; + } + // Same SV (use the SV of the selected secondary antiproton) + if (std::abs(particle5.vx() - antipVx) >= kVtxTol || std::abs(particle5.vy() - antipVy) >= kVtxTol || std::abs(particle5.vz() - antipVz) >= kVtxTol) { + continue; + } + const auto proc5Enum = particle5.getProcess(); + const bool isSecondaryFromMaterial5 = + (!particle5.producedByGenerator()) && (proc5Enum == kPHadronic || proc5Enum == kPHInhelastic); + if (!isSecondaryFromMaterial5) { + continue; + } + ++vtxNAll; + sumPx_vtx += particle5.px(); + sumPy_vtx += particle5.py(); + sumPz_vtx += particle5.pz(); + const int pdg = particle5.pdgCode(); + if (pdg == kPi0) { + ++vtxNPi0; + } + if (pdg == kGamma) { + ++vtxNGamma; + } + if (pdg == kNeutron) { + ++vtxNN; + } + // Charged vs neutral via PDG database (Charge() is in units of e/3) + double q = 0.0; + if (auto* part = pdgDB->GetParticle(pdg)) { + q = part->Charge() / 3.0; + } + if (std::abs(q) > 0.0) { + ++vtxNCh; + } else { + ++vtxNNeut; + } + } + + // Fill histos (final selected candidates only) + if (isCex) { + histos.fill(HIST("hVtxNAll_CEX"), vtxNAll); + histos.fill(HIST("hVtxNCh_CEX"), vtxNCh); + histos.fill(HIST("hVtxNNeut_CEX"), vtxNNeut); + histos.fill(HIST("hVtxNPi0_CEX"), vtxNPi0); + histos.fill(HIST("hVtxNGamma_CEX"), vtxNGamma); + histos.fill(HIST("hVtxNN_CEX"), vtxNN); + } else { + histos.fill(HIST("hVtxNAll_BG"), vtxNAll); + histos.fill(HIST("hVtxNCh_BG"), vtxNCh); + histos.fill(HIST("hVtxNNeut_BG"), vtxNNeut); + histos.fill(HIST("hVtxNPi0_BG"), vtxNPi0); + histos.fill(HIST("hVtxNGamma_BG"), vtxNGamma); + histos.fill(HIST("hVtxNN_BG"), vtxNN); + } + const float vtxfitDX = secX - antipVx; const float vtxfitDY = secY - antipVy; const float vtxfitDZ = secZ - antipVz; const float vtxfitD3D = std::sqrt(vtxfitDX * vtxfitDX + vtxfitDY * vtxfitDY + vtxfitDZ * vtxfitDZ); + const double dPx = motherPx - sumPx_vtx; + const double dPy = motherPy - sumPy_vtx; + const double dPz = motherPz - sumPz_vtx; + const double deltaP = std::sqrt(dPx * dPx + dPy * dPy + dPz * dPz); + + if (isCex) { + histos.fill(HIST("hDeltaP_CEX"), deltaP); + } else { + histos.fill(HIST("hDeltaP_BG"), deltaP); + } + + if (motherHasTrack) { + if (isCex) { + histos.fill(HIST("hMotherNHitIB_CEX"), motherNHitIB); + } else { + histos.fill(HIST("hMotherNHitIB_BG"), motherNHitIB); + } + } + const uint32_t selMask = 0u; outPairs( isCex, motherPdg, + motherNHitIB, colId, pId, antipId, @@ -780,6 +920,13 @@ struct NucleiAntineutronCex { antipVy, antipVz, + static_cast(vtxNAll), + static_cast(vtxNCh), + static_cast(vtxNNeut), + static_cast(vtxNPi0), + static_cast(vtxNGamma), + static_cast(vtxNN), + cexPairTrkP, cexPairTrkPt, cexPairTrkPz, @@ -818,6 +965,8 @@ struct NucleiAntineutronCex { selMask, pairPointingAngleDeg, + pvsvThetaDeg, + pvsvPhiDeg, pairPBalance, pairPtBalance, pairQ, diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index 011a3585a7c..a412b6a93c4 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -21,6 +21,7 @@ #include "PWGLF/DataModel/EPCalibrationTables.h" #include "PWGLF/DataModel/LFSlimNucleiTables.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/Core/EventPlaneHelper.h" #include "Common/Core/PID/PIDTOF.h" @@ -41,7 +42,6 @@ #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" @@ -49,11 +49,14 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Track.h" #include +#include #include #include // for PDG codes +#include #include #include @@ -231,13 +234,15 @@ enum evSel { kIsGoodZvtxFT0vsPV, kIsGoodITSLayersAll, kIsEPtriggered, + kINELgt0, kNevSels }; static const std::vector eventSelectionTitle{"Event selections"}; -static const std::vector eventSelectionLabels{"TVX", "Z vtx", "TF border", "ITS ROF border", "No same-bunch pile-up", "kIsGoodZvtxFT0vsPV", "isGoodITSLayersAll", "isEPtriggered"}; +static const std::vector eventSelectionLabels{"TVX", "Z vtx", "TF border", "ITS ROF border", "No same-bunch pile-up", "kIsGoodZvtxFT0vsPV", "isGoodITSLayersAll", "isEPtriggered", "INEL > 0"}; -constexpr int EvSelDefault[8][1]{ +constexpr int EvSelDefault[9][1]{ + {1}, {1}, {1}, {0}, @@ -246,6 +251,14 @@ constexpr int EvSelDefault[8][1]{ {0}, {0}, {0}}; + +enum EvGenSel : uint8_t { + kGenTVX = 1 << 0, + kGenZvtx = 1 << 1, + kGenINELgt0 = 1 << 2, + kHasRecoEv = 1 << 3 +}; + } // namespace nuclei struct nucleiSpectra { @@ -267,7 +280,9 @@ struct nucleiSpectra { Produces nucleiTable; Produces nucleiPairTable; Produces nucleiTableMC; + Produces nucleiTableMCExtension; Produces nucleiTableFlow; + Produces GenEventMCSel; Service ccdb; Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; @@ -297,7 +312,7 @@ struct nucleiSpectra { Configurable cfgCutPtMinTree{"cfgCutPtMinTree", 0.2f, "Minimum track transverse momentum for tree saving"}; Configurable cfgCutPtMaxTree{"cfgCutPtMaxTree", 15.0f, "Maximum track transverse momentum for tree saving"}; - Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 8, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; + Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 9, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {nuclei::bbMomScalingDefault[0], 5, 2, nuclei::names, nuclei::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {nuclei::betheBlochDefault[0], 5, 6, nuclei::names, nuclei::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; @@ -332,6 +347,8 @@ struct nucleiSpectra { ConfigurableAxis cfgNTPCClusBins{"cfgNTPCClusBins", {3, 89.5, 159.5}, "N TPC clusters binning"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable cfgTriggerList{"cfgTriggerList", "fHe", "Trigger List"}; + Configurable cfgSelectTrgEv{"cfgSelectTrgEv", false, "If true, select events with active trigger list"}; // running variables for track tuner o2::dataformats::DCA mDcaInfoCov; @@ -347,7 +364,7 @@ struct nucleiSpectra { using TrackCandidates = soa::Join; - // Collisions with chentrality + // Collisions with centrality using CollWithCent = soa::Join::iterator; // Flow analysis @@ -437,6 +454,11 @@ struct nucleiSpectra { spectra.fill(HIST("hEventSelections"), nuclei::evSel::kIsEPtriggered + 1); } + if (cfgEventSelections->get(nuclei::evSel::kINELgt0) && !collision.selection_bit(aod::kINELgtZERO)) { + return false; + } + spectra.fill(HIST("hEventSelections"), nuclei::evSel::kINELgt0 + 1); + return true; } @@ -446,7 +468,7 @@ struct nucleiSpectra { return; } if (cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fHe"); + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), cfgTriggerList); zorro.populateHistRegistry(spectra, bc.runNumber()); } auto timestamp = bc.timestamp(); @@ -510,6 +532,7 @@ struct nucleiSpectra { spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsGoodZvtxFT0vsPV + 2, "isGoodZvtxFT0vsPV"); spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsGoodITSLayersAll + 2, "IsGoodITSLayersAll"); spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kIsEPtriggered + 2, "IsEPtriggered"); + spectra.get(HIST("hEventSelections"))->GetXaxis()->SetBinLabel(nuclei::evSel::kINELgt0 + 2, "IsINELgt0"); spectra.add("hRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); if (doprocessMC) { @@ -592,8 +615,15 @@ struct nucleiSpectra { { auto bc = collision.template bc_as(); initCCDB(bc); + + bool isTriggered = true; + + // Using zorro for selecting only events with active trigger if (cfgSkimmedProcessing) { - zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + isTriggered = zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + if (cfgSelectTrgEv && !isTriggered) { + return; + } } gRandom->SetSeed(bc.timestamp()); @@ -814,7 +844,7 @@ struct nucleiSpectra { void processData(soa::Join::iterator const& collision, TrackCandidates const& tracks, aod::BCsWithTimestamps const&) { nuclei::candidates.clear(); - if (!eventSelection(collision)) { + if (!eventSelectionWithHisto(collision)) { return; } @@ -903,21 +933,74 @@ struct nucleiSpectra { PROCESS_SWITCH(nucleiSpectra, processDataFlowAlternative, "Data analysis with flow - alternative framework", false); Preslice tracksPerCollisions = aod::track::collisionId; + Preslice particlesPerMcCollision = aod::mcparticle::mcCollisionId; void processMC(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& tracks, aod::McParticles const& particlesMC, aod::BCsWithTimestamps const&) { nuclei::candidates.clear(); + + std::vector goodCollisions(mcCollisions.size(), false); + std::vector eventMask(mcCollisions.size(), 0); + + auto* pdgDB = TDatabasePDG::Instance(); // Useful for evaluating the particle charge + for (const auto& c : mcCollisions) { + + uint8_t mask = 0; + + const auto& slicedParticles = particlesMC.sliceBy(particlesPerMcCollision, c.globalIndex()); + + bool hasHitFT0A(false); + bool hasHitFT0C(false); + + // TVX trigger + for (const auto& p : slicedParticles) { + if (!p.isPhysicalPrimary()) + continue; + + auto* pdg = pdgDB->GetParticle(p.pdgCode()); + if (!pdg || pdg->Charge() == 0) + continue; + + // Apply the TVX trigger condition + if (p.eta() > 3.5f && p.eta() < 4.9f) + hasHitFT0A = true; + else if (p.eta() > -3.3f && p.eta() < -2.1f) + hasHitFT0C = true; + + if (hasHitFT0A && hasHitFT0C) + break; + } + + if (hasHitFT0A && hasHitFT0C) + mask |= nuclei::kGenTVX; + + // |z| condition + if (std::abs(c.posZ()) < cfgCutVertex) + mask |= nuclei::kGenZvtx; + + // INEL > 0 selection + if (o2::pwglf::isINELgt0mc(slicedParticles, pdgDB)) { + mask |= nuclei::kGenINELgt0; + } + + eventMask[c.globalIndex()] = mask; + GenEventMCSel(mask); spectra.fill(HIST("hGenVtxZ"), c.posZ()); } - std::vector goodCollisions(mcCollisions.size(), false); + for (const auto& collision : collisions) { - if (!eventSelection(collision)) { + if (!eventSelectionWithHisto(collision)) { continue; } goodCollisions[collision.mcCollisionId()] = true; + auto& mask = eventMask[collision.mcCollisionId()]; + mask |= nuclei::kHasRecoEv; + + GenEventMCSel(mask); const auto& slicedTracks = tracks.sliceBy(tracksPerCollisions, collision.globalIndex()); fillDataInfo(collision, slicedTracks); } + std::vector isReconstructed(particlesMC.size(), false); for (auto& c : nuclei::candidates) { auto label = tracks.iteratorAt(c.globalIndex); @@ -979,7 +1062,7 @@ struct nucleiSpectra { isReconstructed[particle.globalIndex()] = true; float absoDecL = computeAbsoDecL(particle); - nucleiTableMC(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.nContrib, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absoDecL); + nucleiTableMCExtension(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.nContrib, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absoDecL, eventMask[particle.mcCollisionId()]); } int index{0}; @@ -1031,7 +1114,7 @@ struct nucleiSpectra { continue; // skip secondaries from material if not requested } float absDecL = computeAbsoDecL(particle); - nucleiTableMC(999., 999., 999., 0., 0., 999., -1, 999., 999., -1, -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absDecL); + nucleiTableMCExtension(999., 999., 999., 0., 0., 999., -1, 999., 999., -1, -1, -1, -1, flags, 0, 0, 0, 0, 0, 0, goodCollisions[particle.mcCollisionId()], particle.pt(), particle.eta(), particle.phi(), particle.pdgCode(), motherPdgCode, motherDecRadius, absDecL, eventMask[particle.mcCollisionId()]); } break; } diff --git a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx index c1363bf8d20..5cfed67e4b4 100644 --- a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx +++ b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx @@ -8,285 +8,321 @@ // 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 trHeAnalysis.cxx -/// -/// \brief Triton and Helion Analysis on pp Data -/// -/// \author Matthias Herzer , Goethe University Frankfurt -/// +/// \brief triton and helion analysis on Run 3 pp data +/// \author Esther Bartsch , Goethe University Frankfurt + +#include "MetadataHelper.h" + #include "PWGLF/DataModel/LFNucleiTables.h" #include "PWGLF/DataModel/LFPIDTOFGenericTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "PWGLF/Utils/pidTOFGeneric.h" -#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" -#include +#include "TRandom3.h" +#include +#include #include #include +using namespace o2; +using namespace o2::framework; + +using CollisionsFull = + soa::Join; +using CollisionsFullMC = soa::Join; +using TracksFull = + soa::Join; +using TracksFullMC = soa::Join; +using TracksFullPid = + soa::Join; +using TracksFullPidMC = soa::Join; +using TracksFullLfPid = + soa::Join; +using TracksFullLfPidMC = soa::Join; + namespace o2::aod { -namespace h3_data +namespace trhe_data { -DECLARE_SOA_COLUMN(TPt, tPt, float); -DECLARE_SOA_COLUMN(TEta, tEta, float); -DECLARE_SOA_COLUMN(TPhi, tPhi, float); -DECLARE_SOA_COLUMN(TCharge, tCharge, int8_t); -DECLARE_SOA_COLUMN(TP, tP, float); -DECLARE_SOA_COLUMN(TH3DeDx, tH3DeDx, float); -DECLARE_SOA_COLUMN(TnSigmaTpc, tnSigmaTpc, float); -DECLARE_SOA_COLUMN(TTofSignalH3, tTofSignalH3, float); -DECLARE_SOA_COLUMN(TDcaXY, tDcaXY, float); -DECLARE_SOA_COLUMN(TDcaZ, tDcaZ, float); -DECLARE_SOA_COLUMN(TSigmaYX, tSigmaYX, float); -DECLARE_SOA_COLUMN(TSigmaXYZ, tSigmaXYZ, float); -DECLARE_SOA_COLUMN(TSigmaZ, tSigmaZ, float); -DECLARE_SOA_COLUMN(TnTpcCluster, tnTpcCluster, int); -DECLARE_SOA_COLUMN(TnItsCluster, tnItsCluster, int); -DECLARE_SOA_COLUMN(TTpcChi2NCl, tTpcChi2NCl, float); -DECLARE_SOA_COLUMN(TItsChi2NCl, tItsChi2NCl, float); -DECLARE_SOA_COLUMN(TRigidity, tRigidity, float); -DECLARE_SOA_COLUMN(TItsClusterSize, tItsClusterSize, float); -DECLARE_SOA_COLUMN(THasTof, tHasTof, bool); -DECLARE_SOA_COLUMN(TDetectorMap, tDetectorMap, int8_t); -} // namespace h3_data -DECLARE_SOA_TABLE(H3Data, "AOD", "h3_data", h3_data::TPt, h3_data::TEta, - h3_data::TPhi, h3_data::TCharge, h3_data::TH3DeDx, - h3_data::TnSigmaTpc, h3_data::TTofSignalH3, h3_data::TDcaXY, - h3_data::TDcaZ, h3_data::TSigmaYX, h3_data::TSigmaXYZ, - h3_data::TSigmaZ, h3_data::TnTpcCluster, - h3_data::TnItsCluster, h3_data::TTpcChi2NCl, - h3_data::TItsChi2NCl, h3_data::TRigidity, - h3_data::TItsClusterSize, h3_data::THasTof, h3_data::TDetectorMap); -namespace he_data -{ -DECLARE_SOA_COLUMN(TPt, tPt, float); -DECLARE_SOA_COLUMN(TEta, tEta, float); -DECLARE_SOA_COLUMN(TPhi, tPhi, float); -DECLARE_SOA_COLUMN(TCharge, tCharge, int8_t); -DECLARE_SOA_COLUMN(TP, tP, float); -DECLARE_SOA_COLUMN(THeDeDx, tHeDeDx, float); -DECLARE_SOA_COLUMN(TnSigmaTpc, tnSigmaTpc, float); -DECLARE_SOA_COLUMN(TTofSignalHe, tTofSignalHe, float); -DECLARE_SOA_COLUMN(TDcaXY, tDcaXY, float); -DECLARE_SOA_COLUMN(TDcaZ, tDcaZ, float); -DECLARE_SOA_COLUMN(TSigmaYX, tSigmaYX, float); -DECLARE_SOA_COLUMN(TSigmaXYZ, tSigmaXYZ, float); -DECLARE_SOA_COLUMN(TSigmaZ, tSigmaZ, float); -DECLARE_SOA_COLUMN(TnTpcCluster, tnTpcCluster, int); -DECLARE_SOA_COLUMN(TnItsCluster, tnItsCluster, int); -DECLARE_SOA_COLUMN(TTpcChi2NCl, tTpcChi2NCl, float); -DECLARE_SOA_COLUMN(TItsChi2NCl, tItsChi2NCl, float); -DECLARE_SOA_COLUMN(TRigidity, tRigidity, float); -DECLARE_SOA_COLUMN(TItsClusterSize, tItsClusterSize, float); -DECLARE_SOA_COLUMN(THasTof, tHasTof, bool); -DECLARE_SOA_COLUMN(TDetectorMap, tDetectorMap, int8_t); -} // namespace he_data -DECLARE_SOA_TABLE(HeData, "AOD", "he_data", he_data::TPt, he_data::TEta, - he_data::TPhi, he_data::TCharge, he_data::THeDeDx, - he_data::TnSigmaTpc, he_data::TTofSignalHe, he_data::TDcaXY, - he_data::TDcaZ, he_data::TSigmaYX, he_data::TSigmaXYZ, - he_data::TSigmaZ, he_data::TnTpcCluster, - he_data::TnItsCluster, he_data::TTpcChi2NCl, - he_data::TItsChi2NCl, he_data::TRigidity, - he_data::TItsClusterSize, he_data::THasTof, he_data::TDetectorMap); +DECLARE_SOA_COLUMN(Species, species, uint8_t); +DECLARE_SOA_COLUMN(Charge, charge, int8_t); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Rigidity, rigidity, float); +DECLARE_SOA_COLUMN(DeDx, deDx, float); +DECLARE_SOA_COLUMN(NSigmaTpc, nSigmaTpc, float); +DECLARE_SOA_COLUMN(NSigmaIts, nSigmaIts, float); +DECLARE_SOA_COLUMN(TofMass2, tofMass2, float); +DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); +DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); +DECLARE_SOA_COLUMN(SigmaYX, sigmaYX, float); +DECLARE_SOA_COLUMN(SigmaXYZ, sigmaXYZ, float); +DECLARE_SOA_COLUMN(SigmaZ, sigmaZ, float); +DECLARE_SOA_COLUMN(NTpcCluster, nTpcCluster, uint8_t); +DECLARE_SOA_COLUMN(NItsCluster, nItsCluster, uint8_t); +DECLARE_SOA_COLUMN(TpcChi2NCl, tpcChi2NCl, float); +DECLARE_SOA_COLUMN(ItsChi2NCl, itsChi2NCl, float); +DECLARE_SOA_COLUMN(ItsClusterSize, itsClusterSize, float); +DECLARE_SOA_COLUMN(DetectorMap, detectorMap, uint8_t); +DECLARE_SOA_COLUMN(Centrality, centrality, int); +DECLARE_SOA_COLUMN(Occupancy, occupancy, int); +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(McTrue, mcTrue, bool); +DECLARE_SOA_COLUMN(McCollTrue, mcCollTrue, bool); +DECLARE_SOA_COLUMN(IsPhysPrimary, isPhysPrimary, bool); +DECLARE_SOA_COLUMN(IsReconstructed, isReconstructed, bool); +DECLARE_SOA_COLUMN(YGen, yGen, float); +DECLARE_SOA_COLUMN(ChargeGen, chargeGen, float); +DECLARE_SOA_COLUMN(PtGen, ptGen, float); +DECLARE_SOA_COLUMN(EtaGen, etaGen, float); +DECLARE_SOA_COLUMN(PhiGen, phiGen, float); +DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); +} // namespace trhe_data +DECLARE_SOA_TABLE(TrHeData, "AOD", "trhe_data", trhe_data::Species, + trhe_data::Charge, trhe_data::Y, trhe_data::Pt, + trhe_data::Eta, trhe_data::Phi, trhe_data::Rigidity, + trhe_data::DeDx, trhe_data::NSigmaTpc, trhe_data::NSigmaIts, + trhe_data::TofMass2, trhe_data::DcaXY, trhe_data::DcaZ, + trhe_data::SigmaYX, trhe_data::SigmaXYZ, trhe_data::SigmaZ, + trhe_data::NTpcCluster, trhe_data::NItsCluster, + trhe_data::TpcChi2NCl, trhe_data::ItsChi2NCl, + trhe_data::ItsClusterSize, trhe_data::DetectorMap, + trhe_data::Centrality, trhe_data::Occupancy, + trhe_data::RunNumber); +DECLARE_SOA_TABLE(TrHeMcRec, "AOD", "trhe_mc_rec", trhe_data::Species, + trhe_data::Charge, trhe_data::Y, trhe_data::Pt, + trhe_data::Eta, trhe_data::Phi, trhe_data::Rigidity, + trhe_data::DeDx, trhe_data::NSigmaTpc, trhe_data::NSigmaIts, + trhe_data::TofMass2, trhe_data::DcaXY, trhe_data::DcaZ, + trhe_data::SigmaYX, trhe_data::SigmaXYZ, trhe_data::SigmaZ, + trhe_data::NTpcCluster, trhe_data::NItsCluster, + trhe_data::TpcChi2NCl, trhe_data::ItsChi2NCl, + trhe_data::ItsClusterSize, trhe_data::DetectorMap, + trhe_data::Centrality, trhe_data::Occupancy, + trhe_data::RunNumber, trhe_data::McTrue, + trhe_data::IsPhysPrimary, trhe_data::PdgCode, trhe_data::McCollTrue); +DECLARE_SOA_TABLE(TrHeMcGen, "AOD", "trhe_mc_gen", trhe_data::Species, + trhe_data::ChargeGen, trhe_data::YGen, trhe_data::PtGen, + trhe_data::EtaGen, trhe_data::PhiGen, + trhe_data::IsPhysPrimary, trhe_data::PdgCode); +DECLARE_SOA_TABLE(TrHeMc, "AOD", "trhe_mc", trhe_data::Species, trhe_data::YGen, + trhe_data::PtGen, trhe_data::EtaGen, trhe_data::PhiGen, + trhe_data::Charge, trhe_data::Y, trhe_data::Pt, + trhe_data::Eta, trhe_data::Phi, trhe_data::Rigidity, + trhe_data::DeDx, trhe_data::NSigmaTpc, trhe_data::NSigmaIts, + trhe_data::TofMass2, trhe_data::DcaXY, trhe_data::DcaZ, + trhe_data::SigmaYX, trhe_data::SigmaXYZ, trhe_data::SigmaZ, + trhe_data::NTpcCluster, trhe_data::NItsCluster, + trhe_data::TpcChi2NCl, trhe_data::ItsChi2NCl, + trhe_data::ItsClusterSize, trhe_data::DetectorMap, + trhe_data::Centrality, trhe_data::Occupancy, + trhe_data::RunNumber, trhe_data::IsPhysPrimary, + trhe_data::IsReconstructed, trhe_data::PdgCode, trhe_data::McCollTrue); } // namespace o2::aod + namespace { -const int nBetheParams = 6; -const int nParticles = 2; -static const std::vector particleNames{"triton", "helion"}; +static const int nParticles = 5; +enum Species { kProton, + kDeuteron, + kTriton, + kHe3, + kAlpha }; +static const std::vector particleNames{ + "proton", "deuteron", "triton", "helion", "alpha"}; static const std::vector particlePdgCodes{ - o2::constants::physics::kTriton, o2::constants::physics::kHelium3}; -static const std::vector particleMasses{ - o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3}; -static const std::vector particleCharge{1, 2}; -static const std::vector particleChargeFactor{2.3, 2.55}; + 2212, o2::constants::physics::kDeuteron, o2::constants::physics::kTriton, + o2::constants::physics::kHelium3, o2::constants::physics::kAlpha}; +static const std::vector particleMasses{ + o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron, + o2::constants::physics::MassTriton, o2::constants::physics::MassHelium3, + o2::constants::physics::MassAlpha}; +static const std::vector particleCharge{1, 1, 1, 2, 2}; +enum MassMethod { kMassFromTrack, + kMassFromBeta, + kMassFromTime }; +const int nBetheParams = 8; +enum BBPAR { kP0, + kP1, + kP2, + kP3, + kP4, + kResolution, + kMip, + kExp }; static const std::vector betheBlochParNames{ - "p0", "p1", "p2", "p3", "p4", "resolution"}; + "p0", "p1", "p2", "p3", "p4", "resolution", "mip", "exp"}; constexpr float BetheBlochDefault[nParticles][nBetheParams]{ - {0.248753, 3.58634, 0.0167065, 2.29194, 0.774344, - 0.07}, // triton - {0.0274556, 18.3054, 3.99987e-05, 3.17219, 11.1775, - 0.07}}; // Helion -} // namespace -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using TracksFull = - soa::Join; + {0.248753, 3.58634, 0.0167065, 2.29194, 0.774344, 0.07, 50., 1.}, // proton + {0.248753, 3.58634, 0.0167065, 2.29194, 0.774344, 0.07, 50., + 1.}, // deuteron + {0.248753, 3.58634, 0.0167065, 2.29194, 0.774344, 0.07, 50., 1.}, // triton + {0.0274556, 18.3054, 3.99987e-05, 3.17219, 11.1775, 0.07, 50., + 2.55}, // helion + {0.0274556, 18.3054, 3.99987e-05, 3.17219, 11.1775, 0.07, 50., + 2.55}}; // alpha -class Particle -{ - public: - TString name; - int pdgCode; - float mass; - int charge; - float resolution; - float chargeFactor; - std::vector betheParams; - static constexpr int NNumBetheParams = 5; - - Particle(const std::string name_, int pdgCode_, float mass_, int charge_, - LabeledArray bethe, float chargeFactor_) - { - name = TString(name_); - pdgCode = pdgCode_; - mass = mass_; - charge = charge_; - chargeFactor = chargeFactor_; - - resolution = - bethe.get(name, "resolution"); // Access the "resolution" parameter - - betheParams.clear(); - for (int i = 0; i < NNumBetheParams; ++i) { - betheParams.push_back(bethe.get(name, i)); - } - } +const int nTrkSettings = 12; +enum TPCPIDMETHOD { + kSkipParticle = -1, + kNone = 0, + kParamBB = 1, + kCentral = 2, + kMC = 3 +}; +enum TRACKPIDSETTINGS { + kPIDmethodTPC, + kMinRigidity, + kMaxRigidity, + kMaxTPCnSigma, + kMaxITSnSigma, + kTOFrequiredabove, + kMinTOFmass, + kMaxTOFmass, + kMinITSmeanClsSize, + kMaxITSmeanClsSize, + kMaxTPCchi2, + kMaxITSchi2 }; +static const std::vector trackPIDsettingsNames{ + "PIDmethodTPC", "minRigidity", "maxRigidity", "maxTPCnSigma", + "maxITSnSigma", "TOFrequiredabove", "minTOFmass2", "maxTOFmass2", + "minITSclsSize", "maxITSclsSize", "maxTPCchi2", "maxITSchi2"}; +constexpr float TrackPIDsettings[nParticles][nTrkSettings]{ + {-1, 0, 10, 3.0, -1., 100, 0, 10, 0., 100, 100, 10000}, // proton + {-1, 0, 10, 3.0, -1., 100, 0, 10, 0., 100, 100, 10000}, // deuteron + {2, 0, 10, 3.0, -1., 100, 0, 10, 0., 100, 100, 10000}, // triton + {2, 0, 10, 3.0, -1., 100, 0, 10, 0., 100, 100, 10000}, // helion + {-1, 0, 10, 3.0, -1., 100, 0, 10, 0., 100, 100, 10000}}; // alpha +} // end namespace struct TrHeAnalysis { - Produces h3Data; - Produces heData; + Produces outData; + Produces outMcRec; + Produces outMcGen; + Produces outMc; + + Preslice perCollision = aod::track::collisionId; + HistogramRegistry histos{ - "Histos", + "histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::vector particles; - Configurable enableTr{"enableTr", true, "Flag to enable triton analysis."}; - Configurable enableHe{"enableHe", true, "Flag to enable helium-3 analysis."}; - Configurable cfgRigidityCorrection{"cfgRigidityCorrection", true, "Enable Rigidity correction"}; - 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}, ""}; - ConfigurableAxis binsSigmaTof{"binsSigmaTof", {1000, -100, 100}, ""}; - ConfigurableAxis binsMassTr{"binsMassTr", {250, -2.5, 2.5f}, ""}; - ConfigurableAxis binsMassHe{"binsMassHe", {300, -3., 3.f}, ""}; - // Set the event selection cuts - struct : ConfigurableGroup { - Configurable useSel8{"useSel8", true, "Use Sel8 for run3 Event Selection"}; - Configurable tvxTrigger{"tvxTrigger", false, "Use TVX for Event Selection (default w/ Sel8)"}; - Configurable removeTfBorder{"removeTfBorder", false, "Remove TimeFrame border (default w/ Sel8)"}; - Configurable removeItsRofBorder{"removeItsRofBorder", false, "Remove ITS Read-Out Frame border (default w/ Sel8)"}; - } evselOptions; - - Configurable cfgTPCPidMethod{"cfgTPCPidMethod", false, "Using own or built in bethe parametrization"}; // false for built in - Configurable cfgMassMethod{"cfgMassMethod", 0, "0: Using built in 1: mass calculated with beta 2: mass calculated with the event time"}; - Configurable cfgEnableItsClusterSizeCut{"cfgEnableItsClusterSizeCut", false, "Enable ITS cluster size cut"}; - Configurable cfgEnableTofMassCut{"cfgEnableTofMassCut", false, "Enable TOF mass cut"}; - Configurable cfgTofMassCutPt{"cfgTofMassCutPt", 1.6f, "Pt value for which the TOF-cut starts to be used"}; - // Set the multiplity event limits - Configurable cfgLowMultCut{"cfgLowMultCut", 0.0f, "Accepted multiplicity percentage lower limit"}; - Configurable cfgHighMultCut{"cfgHighMultCut", 100.0f, "Accepted multiplicity percentage higher limit"}; - - // Set the z-vertex event cut limits - Configurable cfgHighCutVertex{"cfgHighCutVertex", 10.0f, "Accepted z-vertex upper limit"}; - Configurable cfgLowCutVertex{"cfgLowCutVertex", -10.0f, "Accepted z-vertex lower limit"}; - - // Set the quality cuts for tracks - Configurable rejectFakeTracks{"rejectFakeTracks", false, "Flag to reject ITS-TPC fake tracks (for MC)"}; - Configurable cfgCutItsClusters{"cfgCutItsClusters", -1.f, "Minimum number of ITS clusters"}; - Configurable cfgCutTpcXRows{"cfgCutTpcXRows", -1.f, "Minimum number of crossed TPC rows"}; - Configurable cfgCutTpcClusters{"cfgCutTpcClusters", 40.f, "Minimum number of found TPC clusters"}; - Configurable nItsLayer{"nItsLayer", 0, "ITS Layer (0-6)"}; - Configurable cfgCutTpcCrRowToFindableCl{"cfgCutTpcCrRowToFindableCl", 0.8f, "Minimum ratio of crossed rows to findable cluster in TPC"}; - Configurable cfgCutMaxChi2TpcH3{"cfgCutMaxChi2TpcH3", 4.f, "Maximum chi2 per cluster for TPC"}; - Configurable cfgCutMaxChi2ItsH3{"cfgCutMaxChi2ItsH3", 36.f, "Maximum chi2 per cluster for ITS"}; - Configurable cfgCutMaxChi2TpcHe{"cfgCutMaxChi2TpcHe", 4.f, "Maximum chi2 per cluster for TPC"}; - Configurable cfgCutMaxChi2ItsHe{"cfgCutMaxChi2ItsHe", 36.f, "Maximum chi2 per cluster for ITS"}; - Configurable cfgCutTpcRefit{"cfgCutTpcRefit", 1, "TPC refit "}; - Configurable cfgCutItsRefit{"cfgCutItsRefit", 1, "ITS refit"}; - Configurable cfgCutMaxItsClusterSizeHe{"cfgCutMaxItsClusterSizeHe", 4.f, "Maximum ITS Cluster Size for He "}; - Configurable cfgCutMinItsClusterSizeHe{"cfgCutMinItsClusterSizeHe", 1.f, "Minimum ITS Cluster Size for He"}; - Configurable cfgCutMaxItsClusterSizeH3{"cfgCutMaxItsClusterSizeH3", 4.f, "Maximum ITS Cluster Size for Tr"}; - Configurable cfgCutMinItsClusterSizeH3{"cfgCutMinItsClusterSizeH3", 1.f, "Minimum ITS Cluster Size for Tr"}; - Configurable cfgCutMinTofMassH3{"cfgCutMinTofMassH3", 5.f, "Minimum Tof mass H3"}; - Configurable cfgCutMaxTofMassH3{"cfgCutMaxTofMassH3", 11.f, "Maximum TOF mass H3"}; - Configurable cfgMaxRigidity{"cfgMaxRigidity", 10.f, "Maximum rigidity value"}; - Configurable cfgMaxPt{"cfgMaxPt", 10.f, "Maximum pT value"}; - - // Set the kinematic and PID cuts for tracks - struct : ConfigurableGroup { - Configurable pCut{"pCut", 0.6f, "Value of the p selection for spectra (default 0.3)"}; - Configurable etaCut{"etaCut", 0.8f, "Value of the eta selection for spectra (default 0.8)"}; - Configurable yLowCut{"yLowCut", -1.0f, "Value of the low rapidity selection for spectra (default -1.0)"}; - Configurable yHighCut{"yHighCut", 1.0f, "Value of the high rapidity selection for spectra (default 1.0)"}; - } kinemOptions; + o2::aod::ITSResponse itsResponse; + // configurables + Configurable cfgLowMultCut{"cfgLowMultCut", 0.0f, + "Accepted multiplicity percentage lower limit"}; + Configurable cfgHighMultCut{"cfgHighMultCut", 100.0f, + "Accepted multiplicity percentage higher limit"}; + Configurable cfgRigidityCorrection{"cfgRigidityCorrection", false, + "Enable Rigidity correction"}; + Configurable cfgVtxCutZ{"cfgVtxCutZ", 10.0f, + "Accepted z-vertex range"}; + Configurable cfgMassMethod{"cfgMassMethod", 0, + "0: Using built in 1: mass calculated with beta 2: mass calculated with " + "the event time"}; + ConfigurableAxis binsVtxZ{"binsVtxZ", {100, -20.f, 20.f}, ""}; + ConfigurableAxis binsRigidity{"binsRigidity", {3000, -10.f, 10.f}, ""}; + ConfigurableAxis binsTpcSignal{"binsTpcSignal", {3000, 0.f, 3000.f}, ""}; + ConfigurableAxis binsPt{"binsPt", {20, 0.f, 10.f}, ""}; struct : ConfigurableGroup { - Configurable nsigmaTPCTr{"nsigmaTPCTr", 5.f, "Value of the Nsigma TPC cut for tritons"}; - Configurable nsigmaTPCHe{"nsigmaTPCHe", 5.f, "Value of the Nsigma TPC cut for helium-3"}; - } nsigmaTPCvar; - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {BetheBlochDefault[0], nParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable cfgMinPt{"cfgMinPt", 0.f, + "Min value of the pt selection"}; + Configurable cfgMaxPt{"cfgMaxPt", 15.f, + "Max value of the pt selection"}; + Configurable cfgMaxEta{"cfgMaxEta", 0.8f, + "Value of the eta selection"}; + Configurable cfgMaxRapidity{"cfgMaxRapidity", 1.0f, + "Value of rapidity selection"}; + Configurable cfgMinTpcCls{"cfgMinTpcCls", 0, + "Minimum numbers of TPC clusters"}; + Configurable cfgMinItsCls{"cfgMinItsCls", 0, + "Minimum numbers of ITS clusters"}; + Configurable cfgCutTpcXRows{"cfgCutTpcXRows", -1.f, + "Minimum number of crossed TPC rows"}; + Configurable cfgCutTpcCrRowToFindableCl{"cfgCutTpcCrRowToFindableCl", + 0.8f, "Minimum ratio of crossed rows to findable cluster in TPC"}; + Configurable cfgCutTpcRefit{"cfgCutTpcRefit", 1, "TPC refit required"}; + Configurable cfgCutItsRefit{"cfgCutItsRefit", 1, "ITS refit required"}; + Configurable cfgMinDCAXY{"cfgMinDCAXY", 0.f, "Minimum DCA to PV in XY"}; + Configurable cfgMaxDCAXY{"cfgMaxDCAXY", 10000.f, "Maximum DCA to PV in Z"}; + Configurable cfgMinDCAZ{"cfgMinDCAZ", 0.f, "Minimum DCA to PV in XY"}; + Configurable cfgMaxDCAZ{"cfgMaxDCAZ", 10000.f, "Maximum DCA to PV in Z"}; + Configurable cfgTrackSign{"cfgTrackSign", 0, "1: positive only, -1: negative only, 0: all tracks"}; + } trackCuts; + + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", + {BetheBlochDefault[0], nParticles, nBetheParams, particleNames, + betheBlochParNames}, + "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgTrackPIDsettings{"cfgTrackPIDsettings", + {TrackPIDsettings[0], nParticles, nTrkSettings, particleNames, + trackPIDsettingsNames}, + "track PID criteria"}; - void init(o2::framework::InitContext&) + std::vector> histCuts; + std::vector recoMcs; + std::vector goodEvents; + //---------------------------------------------------------------------------- + void init(o2::framework::InitContext& context) { - const AxisSpec dedxAxis{binsDeDx, "d#it{E}/d#it{x} A.U."}; - const AxisSpec betaAxis{binsBeta, "TOF #beta"}; - const AxisSpec dcaxyAxis{binsDca, "DCAxy (cm)"}; - const AxisSpec dcazAxis{binsDca, "DCAz (cm)"}; - const AxisSpec massTrAxis{binsMassTr, ""}; - const AxisSpec massHeAxis{binsMassHe, ""}; - const AxisSpec sigmaTPCAxis{binsSigmaTpc, ""}; - const AxisSpec sigmaTOFAxis{binsSigmaTof, ""}; - - histos.add("histogram/pT", - "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", - HistType::kTH1F, {{500, 0., 10.}}); - histos.add("histogram/p", "Track momentum; p (GeV/#it{c}); counts", - HistType::kTH1F, {{500, 0., 10.}}); - histos.add("histogram/TPCsignVsTPCmomentum", - "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}}); - histos.add( - "histogram/TOFbetaVsP", - "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", - HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); - histos.add("histogram/H3/H3-TPCsignVsTPCmomentum", - "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}}); - histos.add( - "histogram/H3/H3-TOFbetaVsP", - "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", - HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); - histos.add("histogram/He/He-TPCsignVsTPCmomentum", - "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}}); - histos.add( - "histogram/He/He-TOFbetaVsP", - "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", - HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); + bool isMC = doprocessMC || doprocessMCCentralPid || doprocessMCLfPid; + o2::aod::ITSResponse::setParameters(context, isMC); + + // define histogram axes + const AxisSpec axisNev{3, 0., 3., "Number of events"}; + const AxisSpec axisCent{100, 0, 100, "centrality"}; + const AxisSpec axisOccupancy{5000, 0, 50000, "occupancy"}; + const AxisSpec axisVtxZ{binsVtxZ, "#it{z} (cm)"}; + const AxisSpec axisRigidity{binsRigidity, "#it{p/z} (GeV/#it{c})"}; + const AxisSpec axisdEdx{binsTpcSignal, "d#it{E}/d#it{x} (arb. u.)"}; + const AxisSpec axisPt{binsPt, "#it{p}_{T} GeV/#it{c}"}; + // create histograms + histos.add("event/histVtxZ", "histVtxZ", kTH1F, {axisVtxZ}); + histos.add("event/histCentFT0A", "histCentFT0A", kTH1F, {axisCent}); + histos.add("event/histCentFT0C", "histCentFT0C", kTH1F, {axisCent}); + histos.add("event/histCentFT0M", "histCentFT0M", kTH1F, {axisCent}); + histos.add("event/histEvents", "histEvents", kTH2F, + {axisCent, axisOccupancy}); histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, - {{7, -0.5, 6.5}}); + {{8, -0.5, 7.5}}); auto h = histos.get(HIST("event/eventSelection")); h->GetXaxis()->SetBinLabel(1, "Total"); h->GetXaxis()->SetBinLabel(2, "TVX trigger cut"); @@ -295,472 +331,475 @@ struct TrHeAnalysis { h->GetXaxis()->SetBinLabel(5, "TVX + TF + ITS ROF"); h->GetXaxis()->SetBinLabel(6, "Sel8 cut"); h->GetXaxis()->SetBinLabel(7, "Z-vert Cut"); - histos.add("histogram/cuts", "cuts", HistType::kTH1D, - {{13, -0.5, 12.5}}); - auto hCuts = histos.get(HIST("histogram/cuts")); - hCuts->GetXaxis()->SetBinLabel(1, "total"); - hCuts->GetXaxis()->SetBinLabel(2, "p cut"); - hCuts->GetXaxis()->SetBinLabel(3, "eta cut"); - hCuts->GetXaxis()->SetBinLabel(4, "TPC cluster"); - hCuts->GetXaxis()->SetBinLabel(5, "ITS clsuter"); - hCuts->GetXaxis()->SetBinLabel(6, "TPC crossed rows"); - hCuts->GetXaxis()->SetBinLabel(7, "max chi2 ITS"); - hCuts->GetXaxis()->SetBinLabel(8, "max chi2 TPC"); - hCuts->GetXaxis()->SetBinLabel(9, "crossed rows over findable cluster"); - hCuts->GetXaxis()->SetBinLabel(10, "TPC refit"); - hCuts->GetXaxis()->SetBinLabel(11, "ITS refit"); - hCuts->GetXaxis()->SetBinLabel(12, "ITS cluster size"); - hCuts->GetXaxis()->SetBinLabel(13, "TOF mass cut"); - for (int i = 0; i < nParticles; i++) { - particles.push_back(Particle(particleNames.at(i), particlePdgCodes.at(i), - particleMasses.at(i), particleCharge.at(i), - cfgBetheBlochParams, particleChargeFactor.at(i))); + h->GetXaxis()->SetBinLabel(7, "Centrality Cut"); + histos.add("PID/histdEdx", + ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x} (arb. u.)", + HistType::kTH2F, {axisRigidity, axisdEdx}); + histCuts.resize(nParticles); + for (unsigned int species = 0; species < nParticles; species++) { + int tpcMethod = + static_cast(cfgTrackPIDsettings->get(species, "PIDmethodTPC")); + if (tpcMethod == kSkipParticle) + continue; + auto histName = Form("histCuts_%s", particleNames.at(species).data()); + histCuts.at(species) = + histos.add(Form("cuts/%s", histName), histName, HistType::kTH2F, + {{15, -0.5, 14.5}, axisPt}); + histCuts.at(species)->GetXaxis()->SetBinLabel(1, "TPC PID"); + histCuts.at(species)->GetXaxis()->SetBinLabel(2, "ITS PID"); + histCuts.at(species)->GetXaxis()->SetBinLabel(3, "TOF PID"); + histCuts.at(species)->GetXaxis()->SetBinLabel(4, "MeanItsClsSize"); + histCuts.at(species)->GetXaxis()->SetBinLabel(5, "eta"); + histCuts.at(species)->GetXaxis()->SetBinLabel(6, "nTPCcls"); + histCuts.at(species)->GetXaxis()->SetBinLabel(7, "nITScls"); + histCuts.at(species)->GetXaxis()->SetBinLabel(8, "ClsCrossedRows"); + histCuts.at(species)->GetXaxis()->SetBinLabel(9, "CrRowToFind"); + histCuts.at(species)->GetXaxis()->SetBinLabel(10, "TPC refit"); + histCuts.at(species)->GetXaxis()->SetBinLabel(11, "ITS refit"); + histCuts.at(species)->GetXaxis()->SetBinLabel(12, "TPC chi2"); + histCuts.at(species)->GetXaxis()->SetBinLabel(13, "ITS chi2"); + histCuts.at(species)->GetXaxis()->SetBinLabel(14, "DCA XY"); + histCuts.at(species)->GetXaxis()->SetBinLabel(15, "DCA Z"); } } - void process(soa::Join::iterator const& event, - TracksFull const& tracks) + //---------------------------------------------------------------------------- + void processData(CollisionsFull const& collisions, TracksFull const& tracks, + aod::BCsWithTimestamps const& bcs) { - bool trRapCut = kFALSE; - bool heRapCut = kFALSE; - histos.fill(HIST("event/eventSelection"), 0); - if ((event.selection_bit(aod::evsel::kNoITSROFrameBorder)) && - (event.selection_bit(aod::evsel::kNoTimeFrameBorder)) && - (event.selection_bit(aod::evsel::kIsTriggerTVX))) { - histos.fill(HIST("event/eventSelection"), 4); - } - if (evselOptions.useSel8 && !event.sel8()) - return; - histos.fill(HIST("event/eventSelection"), 5); - if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) - return; - histos.fill(HIST("event/eventSelection"), 6); - if (cfgTPCPidMethod) { - for (const auto& track : tracks) { - trRapCut = - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) > - kinemOptions.yLowCut && - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) < - kinemOptions.yHighCut; - heRapCut = - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) > - kinemOptions.yLowCut && - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) < - kinemOptions.yHighCut; - histos.fill(HIST("histogram/cuts"), 0); - if (std::abs(track.p()) < kinemOptions.pCut) { - histos.fill(HIST("histogram/cuts"), 1); - continue; - } - if (std::abs(track.eta()) > kinemOptions.etaCut) { - histos.fill(HIST("histogram/cuts"), 2); - continue; - } - if (track.pt() > cfgMaxPt || getRigidity(track) > cfgMaxRigidity) { - continue; - } - if (track.tpcNClsFound() < cfgCutTpcClusters) { - histos.fill(HIST("histogram/cuts"), 3); - continue; - } - if (track.itsNCls() < cfgCutItsClusters) { - histos.fill(HIST("histogram/cuts"), 4); - continue; - } - if (track.tpcNClsCrossedRows() < cfgCutTpcXRows) { - histos.fill(HIST("histogram/cuts"), 5); - continue; + fillTree(collisions, tracks, true, bcs); + } + PROCESS_SWITCH(TrHeAnalysis, processData, "data analysis", false); + //---------------------------------------------------------------------------- + void processDataCentralPid(CollisionsFull const& collisions, + TracksFullPid const& tracks, + aod::BCsWithTimestamps const& bcs) + { + fillTree(collisions, tracks, true, bcs); + } + PROCESS_SWITCH(TrHeAnalysis, processDataCentralPid, + "data analysis using central PID", false); + //---------------------------------------------------------------------------- + void processDataLfPid(CollisionsFull const& collisions, + TracksFullLfPid const& tracks, + aod::BCsWithTimestamps const& bcs) + { + fillTree(collisions, tracks, true, bcs); + } + PROCESS_SWITCH(TrHeAnalysis, processDataLfPid, "data analysis using LF PID", + false); + //---------------------------------------------------------------------------- + void processMC(CollisionsFullMC const& collisions, TracksFullMC const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::McParticles const& particlesMC) + { + fillTree(collisions, tracks, particlesMC, bcs); + } + PROCESS_SWITCH(TrHeAnalysis, processMC, "Monte Carlo analysis", true); + //---------------------------------------------------------------------------- + void processMCCentralPid(CollisionsFullMC const& collisions, + TracksFullPidMC const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::McParticles const& particlesMC) + { + fillTree(collisions, tracks, particlesMC, bcs); + } + PROCESS_SWITCH(TrHeAnalysis, processMCCentralPid, + "Monte Carlo analysis using central PID", false); + //---------------------------------------------------------------------------- + void processMCLfPid(CollisionsFullMC const& collisions, + TracksFullLfPidMC const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::McParticles const& particlesMC) + { + fillTree(collisions, tracks, particlesMC, bcs); + } + PROCESS_SWITCH(TrHeAnalysis, processMCLfPid, + "Monte Carlo analysis using LF PID", false); + //---------------------------------------------------------------------------- + template + void fillTree(const C& collision, const T& tracks, const P& particles, + aod::BCsWithTimestamps const& bcs) + { + recoMcs.clear(); + goodEvents.clear(); + // event loop + for (const auto& collision : collision) { + const auto& bc = bcs.rawIteratorAt(collision.bcId()); + // event selection + histos.fill(HIST("event/eventSelection"), 0); + if ((collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) && + (collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) && + (collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + histos.fill(HIST("event/eventSelection"), 4); + } + if (!collision.sel8()) + continue; + histos.fill(HIST("event/eventSelection"), 5); + if (std::abs(collision.posZ()) > cfgVtxCutZ) + continue; + histos.fill(HIST("event/eventSelection"), 6); + float centrality = collision.centFT0C(); + if (centrality < cfgLowMultCut || centrality > cfgHighMultCut) + continue; + histos.fill(HIST("event/eventSelection"), 7); + float occupancy = collision.trackOccupancyInTimeRange(); + histos.fill(HIST("event/histVtxZ"), collision.posZ()); + histos.fill(HIST("event/histCentFT0A"), collision.centFT0A()); + histos.fill(HIST("event/histCentFT0C"), collision.centFT0C()); + histos.fill(HIST("event/histCentFT0M"), collision.centFT0M()); + histos.fill(HIST("event/histEvents"), collision.centFT0C(), occupancy); + if constexpr (IsMC) { + goodEvents.push_back(collision.mcCollisionId()); + } + auto tracksByEvent = + tracks.sliceBy(perCollision, collision.globalIndex()); + + // track loop + for (const auto& track : tracksByEvent) { + if constexpr (IsMC) { + if (!track.has_mcParticle()) + continue; } - if (track.tpcCrossedRowsOverFindableCls() <= cfgCutTpcCrRowToFindableCl) { - histos.fill(HIST("histogram/cuts"), 8); + if (track.sign() * trackCuts.cfgTrackSign < 0) continue; - } - if (cfgCutTpcRefit) { - if (!track.passedTPCRefit()) { - histos.fill(HIST("histogram/cuts"), 9); + float rigidity = getRigidity(track); + histos.fill(HIST("PID/histdEdx"), track.sign() * rigidity, + track.tpcSignal()); + for (int species = 0; species < nParticles; species++) { + int tpcMethod = static_cast( + cfgTrackPIDsettings->get(species, "PIDmethodTPC")); + if (tpcMethod == kSkipParticle) continue; - } - } - if (cfgCutItsRefit) { - if (!track.passedITSRefit()) { - histos.fill(HIST("histogram/cuts"), 10); + if (rigidity < cfgTrackPIDsettings->get(species, "minRigidity") || + rigidity > cfgTrackPIDsettings->get(species, "maxRigidity")) continue; - } - } - histos.fill(HIST("histogram/pT"), track.pt()); - histos.fill(HIST("histogram/p"), track.p()); - histos.fill(HIST("histogram/TPCsignVsTPCmomentum"), - getRigidity(track) * track.sign(), - track.tpcSignal()); - histos.fill(HIST("histogram/TOFbetaVsP"), - getRigidity(track) * track.sign(), - track.beta()); - if (enableTr && trRapCut) { - if (std::abs(getTPCnSigma(track, particles.at(0))) < - nsigmaTPCvar.nsigmaTPCTr) { - if (track.itsChi2NCl() > cfgCutMaxChi2ItsH3) { - histos.fill(HIST("histogram/cuts"), 6); - continue; - } - if (track.tpcChi2NCl() > cfgCutMaxChi2TpcH3) { - histos.fill(HIST("histogram/cuts"), 7); - continue; - } - if (cfgEnableItsClusterSizeCut) { - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - continue; + float pt = particleCharge.at(species) * track.pt(); + if (pt < trackCuts.cfgMinPt || pt > trackCuts.cfgMaxPt) + continue; + + float rapidity = + RecoDecayPtEtaPhi::y(pt, track.eta(), particleMasses.at(species)); + if (std::abs(rapidity) > trackCuts.cfgMaxRapidity) + continue; + + // TPC PID + float tpcNsigma; + switch (tpcMethod) { + case kNone: + tpcNsigma = 0; + break; + + case kParamBB: + tpcNsigma = getTpcNsigmaBB(track, species); + break; + + case kCentral: + if constexpr (UseExtPid) { + tpcNsigma = getTpcNsigmaExt(track, species); + } else { + tpcNsigma = -999; } - } - if (cfgEnableTofMassCut && track.pt() > cfgTofMassCutPt) { - if (getMass(track) < cfgCutMinTofMassH3 || getMass(track) > cfgCutMaxTofMassH3) { - histos.fill(HIST("histogram/cuts"), 13); - continue; + break; + + case kMC: + if constexpr (IsMC) { + tpcNsigma = (std::abs(track.mcParticle().pdgCode()) == + particlePdgCodes[species]) + ? 0 + : -999; + } else { + tpcNsigma = -999; } - } - histos.fill(HIST("histogram/H3/H3-TPCsignVsTPCmomentum"), - getRigidity(track) * track.sign(), - track.tpcSignal()); - histos.fill(HIST("histogram/H3/H3-TOFbetaVsP"), - getRigidity(track) * track.sign(), - track.beta()); - float tPt = track.pt(); - float tEta = track.eta(); - float tPhi = track.phi(); - int8_t tCharge = track.sign(); - float tH3DeDx = track.tpcSignal(); - float tnSigmaTpc = getTPCnSigma(track, particles.at(0)); - float tTofSignalH3 = getMass(track); - float tDcaXY = track.dcaXY(); - float tDcaZ = track.dcaZ(); - float tSigmaYX = track.sigmaY(); - float tSigmaXYZ = track.sigmaSnp(); - float tSigmaZ = track.sigmaZ(); - int tnTpcCluster = track.tpcNClsFound(); - int tnItsCluster = track.itsNCls(); - float tTpcChi2NCl = track.tpcChi2NCl(); - float tItsChi2NCl = track.itsChi2NCl(); - float tRigidity = getRigidity(track); - float tItsClusterSize = - getMeanItsClsSize(track) / std::cosh(track.eta()); - bool tHasTof = track.hasTOF(); - int8_t tDetectorMap = track.detectorMap(); - h3Data(tPt, tEta, tPhi, tCharge, tH3DeDx, tnSigmaTpc, tTofSignalH3, - tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, - tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize, tHasTof, tDetectorMap); + break; + + default: + tpcNsigma = -999; } - } - if (enableHe && heRapCut) { - if (std::abs(getTPCnSigma(track, particles.at(1))) < - nsigmaTPCvar.nsigmaTPCHe) { - if (track.itsChi2NCl() > cfgCutMaxChi2ItsHe) { - histos.fill(HIST("histogram/cuts"), 6); - continue; - } - if (track.tpcChi2NCl() > cfgCutMaxChi2TpcHe) { - histos.fill(HIST("histogram/cuts"), 7); + + if (std::abs(tpcNsigma) > + cfgTrackPIDsettings->get(species, "maxTPCnSigma")) + continue; + histCuts.at(species)->Fill(0., pt); + + // ITS PID + float itsNsigma = getItsNsigma(track, species); + if (cfgTrackPIDsettings->get(species, "maxITSnSigma") > 0 && + std::abs(itsNsigma) > + cfgTrackPIDsettings->get(species, "maxITSnSigma")) + continue; + histCuts.at(species)->Fill(1., pt); + + // TOF PID + float tofMass2 = -1.f; + if (track.hasTOF()) + tofMass2 = getMass2(track); + if (pt > cfgTrackPIDsettings->get(species, "TOFrequiredabove") && + (tofMass2 < cfgTrackPIDsettings->get(species, "minTOFmass2") || + tofMass2 > cfgTrackPIDsettings->get(species, "maxTOFmass2"))) + continue; + histCuts.at(species)->Fill(2., pt); + + // apply selection criteria + const float itsMeanClsSize = getMeanItsClsSize(track); + if (itsMeanClsSize < + cfgTrackPIDsettings->get(species, "minITSclsSize") || + itsMeanClsSize > + cfgTrackPIDsettings->get(species, "maxITSclsSize")) + continue; + histCuts.at(species)->Fill(3., pt); + + if (std::abs(track.eta()) > trackCuts.cfgMaxEta) + continue; + histCuts.at(species)->Fill(4., pt); + + if (track.tpcNClsFound() < trackCuts.cfgMinTpcCls) + continue; + histCuts.at(species)->Fill(5., pt); + + if (track.itsNCls() < trackCuts.cfgMinItsCls) + continue; + histCuts.at(species)->Fill(6., pt); + + if (track.tpcNClsCrossedRows() < trackCuts.cfgCutTpcXRows) + continue; + histCuts.at(species)->Fill(7., pt); + + if (track.tpcCrossedRowsOverFindableCls() <= + trackCuts.cfgCutTpcCrRowToFindableCl) + continue; + histCuts.at(species)->Fill(8., pt); + + if (trackCuts.cfgCutTpcRefit && !track.passedTPCRefit()) + continue; + histCuts.at(species)->Fill(9., pt); + + if (trackCuts.cfgCutItsRefit && !track.passedITSRefit()) + continue; + histCuts.at(species)->Fill(10., pt); + + if (track.tpcChi2NCl() > + cfgTrackPIDsettings->get(species, "maxTPCchi2")) + continue; + histCuts.at(species)->Fill(11., pt); + + if (track.itsChi2NCl() > + cfgTrackPIDsettings->get(species, "maxITSchi2")) + continue; + histCuts.at(species)->Fill(12., pt); + + if (std::abs(track.dcaXY()) < trackCuts.cfgMinDCAXY || + std::abs(track.dcaXY()) > trackCuts.cfgMaxDCAXY) + continue; + histCuts.at(species)->Fill(13., pt); + + if (std::abs(track.dcaZ()) < trackCuts.cfgMinDCAZ || + std::abs(track.dcaZ()) > trackCuts.cfgMaxDCAZ) + continue; + histCuts.at(species)->Fill(14., pt); + + // write output tables + if constexpr (IsMC) { + const auto& mcPart = particles.rawIteratorAt(track.mcParticleId()); + const bool isMcTrue = + mcPart.pdgCode() == particlePdgCodes.at(species) * track.sign(); + const bool mcTrueColl = mcPart.mcCollisionId() == collision.mcCollisionId(); + // mc reconstructed tree + outMcRec(species, particleCharge.at(species) * track.sign(), + rapidity, pt, track.eta(), track.phi(), rigidity, + track.tpcSignal(), tpcNsigma, itsNsigma, tofMass2, + track.dcaXY(), track.dcaZ(), track.sigmaY(), + track.sigmaSnp(), track.sigmaZ(), track.tpcNClsFound(), + track.itsNCls(), track.tpcChi2NCl(), track.itsChi2NCl(), + itsMeanClsSize, track.detectorMap(), centrality, + collision.trackOccupancyInTimeRange(), bc.runNumber(), + isMcTrue, mcPart.isPhysicalPrimary(), mcPart.pdgCode(), mcTrueColl); + // mc generated & reconstructed tree (mcTrue particles only) + if (!isMcTrue) continue; - } - if (cfgEnableItsClusterSizeCut) { - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - continue; - } - } - histos.fill(HIST("histogram/He/He-TPCsignVsTPCmomentum"), - getRigidity(track) * track.sign(), - track.tpcSignal()); - histos.fill(HIST("histogram/He/He-TOFbetaVsP"), - getRigidity(track) * track.sign(), - track.beta()); - float tPt = track.pt(); - float tEta = track.eta(); - float tPhi = track.phi(); - int8_t tCharge = 2.f * track.sign(); - float tHeDeDx = track.tpcSignal(); - float tnSigmaTpc = getTPCnSigma(track, particles.at(1)); - float tTofSignalHe = getMass(track); - float tDcaXY = track.dcaXY(); - float tDcaZ = track.dcaZ(); - float tSigmaYX = track.sigmaY(); - float tSigmaXYZ = track.sigmaSnp(); - float tSigmaZ = track.sigmaZ(); - int tnTpcCluster = track.tpcNClsFound(); - int tnItsCluster = track.itsNCls(); - float tTpcChi2NCl = track.tpcChi2NCl(); - float tItsChi2NCl = track.itsChi2NCl(); - float tRigidity = getRigidity(track); - float tItsClusterSize = - getMeanItsClsSize(track) / std::cosh(track.eta()); - bool tHasTof = track.hasTOF(); - int8_t tDetectorMap = track.detectorMap(); - heData(tPt, tEta, tPhi, tCharge, tHeDeDx, tnSigmaTpc, tTofSignalHe, - tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, - tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize, tHasTof, tDetectorMap); + outMc(species, mcPart.y(), mcPart.pt(), mcPart.eta(), mcPart.phi(), + particleCharge.at(species) * track.sign(), rapidity, pt, + track.eta(), track.phi(), rigidity, track.tpcSignal(), + tpcNsigma, itsNsigma, tofMass2, track.dcaXY(), track.dcaZ(), + track.sigmaY(), track.sigmaSnp(), track.sigmaZ(), + track.tpcNClsFound(), track.itsNCls(), track.tpcChi2NCl(), + track.itsChi2NCl(), itsMeanClsSize, track.detectorMap(), + centrality, collision.trackOccupancyInTimeRange(), + bc.runNumber(), mcPart.isPhysicalPrimary(), true, mcPart.pdgCode(), mcTrueColl); + recoMcs.push_back(mcPart.globalIndex()); + } else { // data tree + outData(species, particleCharge.at(species) * track.sign(), + rapidity, pt, track.eta(), track.phi(), rigidity, + track.tpcSignal(), tpcNsigma, itsNsigma, tofMass2, + track.dcaXY(), track.dcaZ(), track.sigmaY(), + track.sigmaSnp(), track.sigmaZ(), track.tpcNClsFound(), + track.itsNCls(), track.tpcChi2NCl(), track.itsChi2NCl(), + itsMeanClsSize, track.detectorMap(), centrality, + collision.trackOccupancyInTimeRange(), bc.runNumber()); } - } - } - } - if (!cfgTPCPidMethod) { - for (const auto& track : tracks) { - trRapCut = - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) > - kinemOptions.yLowCut && - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) < - kinemOptions.yHighCut; - heRapCut = - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) > - kinemOptions.yLowCut && - track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) < - kinemOptions.yHighCut; - histos.fill(HIST("histogram/cuts"), 0); - if (std::abs(track.p()) < kinemOptions.pCut) { - histos.fill(HIST("histogram/cuts"), 1); - continue; - } - if (std::abs(track.eta()) > kinemOptions.etaCut) { - histos.fill(HIST("histogram/cuts"), 2); - continue; - } - if (track.pt() > cfgMaxPt || getRigidity(track) > cfgMaxRigidity) { - continue; - } - if (track.tpcNClsFound() < cfgCutTpcClusters) { - histos.fill(HIST("histogram/cuts"), 3); - continue; - } - if (track.itsNCls() < cfgCutItsClusters) { - histos.fill(HIST("histogram/cuts"), 4); - continue; - } - if (track.tpcNClsCrossedRows() < cfgCutTpcXRows) { - histos.fill(HIST("histogram/cuts"), 5); - continue; - } - if (track.tpcCrossedRowsOverFindableCls() <= cfgCutTpcCrRowToFindableCl) { - histos.fill(HIST("histogram/cuts"), 8); + } // end species loop + } // end track loop + } // end event loop + + // MC generated + if constexpr (IsMC) { + for (const auto& mcPart : particles) { + if (!isInVector(goodEvents, mcPart.mcCollisionId())) continue; - } - if (cfgCutTpcRefit) { - if (!track.passedTPCRefit()) { - histos.fill(HIST("histogram/cuts"), 9); + for (int species = 0; species < nParticles; species++) { + int tpcMethod = static_cast( + cfgTrackPIDsettings->get(species, "PIDmethodTPC")); + if (tpcMethod == kSkipParticle) continue; - } - } - if (cfgCutItsRefit) { - if (!track.passedITSRefit()) { - histos.fill(HIST("histogram/cuts"), 10); + if (std::abs(mcPart.pdgCode()) != particlePdgCodes.at(species)) continue; - } - } - histos.fill(HIST("histogram/pT"), track.pt()); - histos.fill(HIST("histogram/p"), track.p()); - histos.fill(HIST("histogram/TPCsignVsTPCmomentum"), - getRigidity(track) * (1.f * track.sign()), - track.tpcSignal()); - histos.fill(HIST("histogram/TOFbetaVsP"), - track.p() * (1.f * track.sign()), track.beta()); - if (enableTr && trRapCut) { - if (std::abs(track.tpcNSigmaTr()) < nsigmaTPCvar.nsigmaTPCTr) { - if (track.itsChi2NCl() > cfgCutMaxChi2ItsH3) { - histos.fill(HIST("histogram/cuts"), 6); - continue; - } - if (track.tpcChi2NCl() > cfgCutMaxChi2TpcH3) { - histos.fill(HIST("histogram/cuts"), 7); - continue; - } - if (cfgEnableItsClusterSizeCut) { - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeH3 || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeH3) { - histos.fill(HIST("histogram/cuts"), 12); - continue; - } - } - if (cfgEnableTofMassCut && track.pt() > cfgTofMassCutPt) { - if (getMass(track) < cfgCutMinTofMassH3 || getMass(track) > cfgCutMaxTofMassH3) { - histos.fill(HIST("histogram/cuts"), 13); - continue; - } - } - histos.fill(HIST("histogram/H3/H3-TPCsignVsTPCmomentum"), - getRigidity(track) * (1.f * track.sign()), - track.tpcSignal()); - histos.fill(HIST("histogram/H3/H3-TOFbetaVsP"), - track.p() * (1.f * track.sign()), - track.beta()); - float tPt = track.pt(); - float tEta = track.eta(); - float tPhi = track.phi(); - int8_t tCharge = track.sign(); - float tH3DeDx = track.tpcSignal(); - float tnSigmaTpc = track.tpcNSigmaTr(); - float tTofSignalH3 = getMass(track); - float tDcaXY = track.dcaXY(); - float tDcaZ = track.dcaZ(); - float tSigmaYX = track.sigmaY(); - float tSigmaXYZ = track.sigmaSnp(); - float tSigmaZ = track.sigmaZ(); - int tnTpcCluster = track.tpcNClsFound(); - int tnItsCluster = track.itsNCls(); - float tTpcChi2NCl = track.tpcChi2NCl(); - float tItsChi2NCl = track.itsChi2NCl(); - float tRigidity = getRigidity(track); - float tItsClusterSize = - getMeanItsClsSize(track) / std::cosh(track.eta()); - bool tHasTof = track.hasTOF(); - int8_t tDetectorMap = track.detectorMap(); - h3Data(tPt, tEta, tPhi, tCharge, tH3DeDx, tnSigmaTpc, tTofSignalH3, - tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, - tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize, tHasTof, tDetectorMap); - } - } - if (enableHe && heRapCut) { - if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - if (track.itsChi2NCl() > cfgCutMaxChi2ItsHe) { - histos.fill(HIST("histogram/cuts"), 6); - continue; - } - if (track.tpcChi2NCl() > cfgCutMaxChi2TpcHe) { - histos.fill(HIST("histogram/cuts"), 7); - continue; - } - if (cfgEnableItsClusterSizeCut) { - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - continue; - } - } - histos.fill(HIST("histogram/He/He-TPCsignVsTPCmomentum"), - getRigidity(track) * track.sign(), - track.tpcSignal()); - histos.fill(HIST("histogram/He/He-TOFbetaVsP"), - getRigidity(track) * track.sign(), - track.beta()); - float tPt = track.pt(); - float tEta = track.eta(); - float tPhi = track.phi(); - int8_t tCharge = 2.f * track.sign(); - float tHeDeDx = track.tpcSignal(); - float tnSigmaTpc = track.tpcNSigmaHe(); - float tTofSignalHe = getMass(track); - float tDcaXY = track.dcaXY(); - float tDcaZ = track.dcaZ(); - float tSigmaYX = track.sigmaY(); - float tSigmaXYZ = track.sigmaSnp(); - float tSigmaZ = track.sigmaZ(); - int tnTpcCluster = track.tpcNClsFound(); - int tnItsCluster = track.itsNCls(); - float tTpcChi2NCl = track.tpcChi2NCl(); - float tItsChi2NCl = track.itsChi2NCl(); - float tRigidity = getRigidity(track); - float tItsClusterSize = - getMeanItsClsSize(track) / std::cosh(track.eta()); - bool tHasTof = track.hasTOF(); - int8_t tDetectorMap = track.detectorMap(); - heData(tPt, tEta, tPhi, tCharge, tHeDeDx, tnSigmaTpc, tTofSignalHe, - tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, - tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize, tHasTof, tDetectorMap); - } - } - } + if (std::abs(mcPart.y()) > trackCuts.cfgMaxRapidity) + continue; + float charge = + particleCharge[species] * (mcPart.pdgCode() < 0 ? -1 : +1); + // MC generated tree + outMcGen(species, charge, mcPart.y(), mcPart.pt(), mcPart.eta(), + mcPart.phi(), mcPart.isPhysicalPrimary(), mcPart.pdgCode()); + // mc generated & reconstructed tree (non-reconstructed particles + // only) + if (isInVector(recoMcs, mcPart.globalIndex())) + continue; + outMc(species, mcPart.y(), mcPart.pt(), mcPart.eta(), mcPart.phi(), + charge, -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -999.f, -999.f, + -1.f, -1.f, -1.f, -1.f, -1.f, -1.f, -1, -1, -1.f, -1.f, -1.f, 0, + 0, 0, 0, mcPart.isPhysicalPrimary(), false, mcPart.pdgCode(), false); + } // end species loop + } // end mc particle loop } } - + //---------------------------------------------------------------------------- template - float getTPCnSigma(T const& track, Particle const& particle) + float getRigidity(T const& track) { - const float rigidity = getRigidity(track); - if (!track.hasTPC()) - return -999; - - float expBethe{betheBlochAleph(particle, rigidity)}; - float expSigma{expBethe * particle.resolution}; - float sigmaTPC = - static_cast((track.tpcSignal() - expBethe) / expSigma); - return sigmaTPC; + if (!cfgRigidityCorrection) + return track.tpcInnerParam(); + bool hePID = track.pidForTracking() == o2::track::PID::Helium3 || + track.pidForTracking() == o2::track::PID::Alpha; + return hePID ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); } - + //---------------------------------------------------------------------------- template - float betheBlochAleph(Particle const& particle, T const& rigidity) + float getTpcNsigmaExt(T const& track, int species) { - double bg = particle.charge * rigidity / particle.mass; - double beta = bg / std::sqrt(1. + bg * bg); - double aa = std::pow(beta, particle.betheParams[3]); - double bb = std::pow(1. / bg, particle.betheParams[4]); - if ((particle.betheParams[2] + bb) <= 0) - return 0; - bb = std::log(particle.betheParams[2] + bb); - return std::pow(particle.charge, particle.chargeFactor) * 50 * (particle.betheParams[1] - aa - bb) * particle.betheParams[0] / aa; + switch (species) { + case Species::kProton: + return track.tpcNSigmaPr(); + case Species::kDeuteron: + return track.tpcNSigmaDe(); + case Species::kTriton: + return track.tpcNSigmaTr(); + case Species::kHe3: + return track.tpcNSigmaHe(); + case Species::kAlpha: + return track.tpcNSigmaAl(); + default: + return -999; + } } - + //---------------------------------------------------------------------------- template - float getMeanItsClsSize(T const& track) + float getTpcNsigmaBB(T const& track, int species) { - constexpr int NNumLayers = 8; - constexpr int NBitsPerLayer = 4; - constexpr int NBitMask = (1 << NBitsPerLayer) - 1; - - int sum = 0, n = 0; - for (int i = 0; i < NNumLayers; i++) { - int clsSize = (track.itsClusterSizes() >> (NBitsPerLayer * i)) & NBitMask; - sum += clsSize; - if (clsSize) { - n++; - } - } - return n > 0 ? static_cast(sum) / n : 0.f; + const float mass = particleMasses.at(species); + const float charge = particleCharge.at(species); + const float mip = cfgBetheBlochParams->get(species, "mip"); + const float exp = + std::pow(charge, cfgBetheBlochParams->get(species, "exp")); + const float bg = charge * getRigidity(track) / mass; + const float expBethe = + mip * exp * + o2::common::BetheBlochAleph(bg, cfgBetheBlochParams->get(species, "p0"), + cfgBetheBlochParams->get(species, "p1"), + cfgBetheBlochParams->get(species, "p2"), + cfgBetheBlochParams->get(species, "p3"), + cfgBetheBlochParams->get(species, "p4")); + const float expSigma = + expBethe * cfgBetheBlochParams->get(species, "resolution"); + return (track.tpcSignal() - expBethe) / expSigma; } + //---------------------------------------------------------------------------- template - float getRigidity(T const& track) + float getItsNsigma(T const& track, int species) { - if (!cfgRigidityCorrection) - return track.tpcInnerParam(); - bool hePID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; - return hePID ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + switch (species) { + case Species::kProton: + return itsResponse.nSigmaITS(track); + case Species::kDeuteron: + return itsResponse.nSigmaITS(track); + case Species::kTriton: + return itsResponse.nSigmaITS(track); + case Species::kHe3: + return itsResponse.nSigmaITS(track); + case Species::kAlpha: + return itsResponse.nSigmaITS(track); + default: + return -999; + } } + //---------------------------------------------------------------------------- template - float getMass(const T& track) + float getMass2(const T& track) { - if (cfgMassMethod == 0) { - float m = track.mass(); + if (cfgMassMethod == kMassFromTrack) { + const float& m = track.mass(); return m * m; } - if (cfgMassMethod == 1) { - const float beta = track.beta(); - const float rigidity = getRigidity(track); + if (cfgMassMethod == kMassFromBeta) { + const float& beta = track.beta(); + const float& p = track.p(); float gamma = 1.f / std::sqrt(1.f - beta * beta); - float mass = rigidity / std::sqrt(gamma * gamma - 1.f); + float mass = p / std::sqrt(gamma * gamma - 1.f); return mass * mass; } - if (cfgMassMethod == 2) { - const float rigidity = getRigidity(track); - float tofStartTime = track.evTimeForTrack(); - float tofTime = track.tofSignal(); + if (cfgMassMethod == kMassFromTime) { + const float p = track.p(); + const float& tofStartTime = track.evTimeForTrack(); + const float& tofTime = track.tofSignal(); constexpr float CInCmPs = 2.99792458e-2f; - float length = track.length(); - float time = tofTime - tofStartTime; + const float& length = track.length(); + const float time = tofTime - tofStartTime; if (time > 0.f && length > 0.f) { - float beta = length / (CInCmPs * time); - float gamma = 1.f / std::sqrt(1.f - beta * beta); - float mass = rigidity / std::sqrt(gamma * gamma - 1.f); + const float beta = length / (CInCmPs * time); + const float gamma = 1.f / std::sqrt(1.f - beta * beta); + const float mass = p / std::sqrt(gamma * gamma - 1.f); return mass * mass; } return -1.f; } return -1.f; } -}; + //---------------------------------------------------------------------------- + template + float getMeanItsClsSize(T const& track) + { + constexpr int NLayers = 8; + constexpr int NBitsPerLayer = 4; + constexpr int BitMask = (1 << NBitsPerLayer) - 1; + int sum = 0, n = 0; + for (int i = 0; i < NLayers; i++) { + int clsSize = (track.itsClusterSizes() >> (NBitsPerLayer * i)) & BitMask; + sum += clsSize; + if (clsSize) { + n++; + } + } + return n > 0 ? static_cast(sum) / n : 0.f; + } + //---------------------------------------------------------------------------- + template + bool isInVector(std::vector const& vec, T const& val) + { + return std::find(vec.begin(), vec.end(), val) != vec.end(); + } + //---------------------------------------------------------------------------- +}; +//------------------------------------------------------------------------------ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/QC/nucleiQC.cxx b/PWGLF/TableProducer/QC/nucleiQC.cxx index 149c11df141..a6597d45137 100644 --- a/PWGLF/TableProducer/QC/nucleiQC.cxx +++ b/PWGLF/TableProducer/QC/nucleiQC.cxx @@ -39,7 +39,6 @@ #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" @@ -48,6 +47,7 @@ #include "Framework/HistogramRegistry.h" #include "Framework/StaticFor.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Track.h" #include "Math/Vector4D.h" @@ -64,11 +64,32 @@ using namespace o2; using namespace o2::framework; +namespace +{ + +enum trackQuality { + kNoCuts = 0, + kEtaCut = 1, + kPtpcCut = 2, + kNclsItsCut = 3, + kNclsTpcCut = 4, + kNCrossedRowsCut = 5, + kTpcChi2Cut = 6, + kItsChi2Cut = 7, + kNtrackQuality = 8 +}; + +std::array trackQualityLabels{"All", "#eta cut", "#it{p}_{TPC}^{min} cut", "#it{N}_{cls}^{ITS} cut", "#it{N}_{cls}^{TPC} cut", "Crossed rows cut", "#chi^{2}_{TPC} cut", "#chi^{2}_{ITS} cut"}; + +} // namespace + struct nucleiQC { using TrackCandidates = soa::Join; using TrackCandidatesMC = soa::Join; using Collision = soa::Join::iterator; + using Collisions = soa::Join; + Preslice mTracksPerCollision = aod::track::collisionId; Preslice mMcParticlesPerCollision = o2::aod::mcparticle::mcCollisionId; Configurable cfgFillTable{"cfgFillTable", true, "Fill output tree"}; @@ -77,8 +98,12 @@ struct nucleiQC { Configurable> cfgSpeciesToProcess{"cfgSpeciesToProcess", {nuclei::speciesToProcessDefault[0], nuclei::Species::kNspecies, 1, nuclei::names, {"processNucleus"}}, "Nuclei to process"}; Configurable> cfgEventSelections{"cfgEventSelections", {nuclei::EvSelDefault[0], 8, 1, nuclei::eventSelectionLabels, nuclei::eventSelectionTitle}, "Event selections"}; Configurable cfgCentralityEstimator{"cfgCentralityEstimator", 0, "Centrality estimator (FV0A: 0, FT0M: 1, FT0A: 2, FT0C: 3)"}; + Configurable cfgPerformPidSelectionInIts{"cfgPerformPidSelectionInIts", false, "Perform PID selections in ITS"}; + Configurable cfgPerformPidSelectionInTpc{"cfgPerformPidSelectionInTpc", false, "Perform PID selections in TPC"}; + Configurable cfgPerformPidSelectionInTof{"cfgPerformPidSelectionInTof", false, "Perform PID selections in TOF"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {nuclei::betheBlochDefault[0], nuclei::Species::kNspecies, 6, nuclei::names, nuclei::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; Configurable> cfgUseCentralTpcCalibration{"cfgUseCentralTpcCalibration", {nuclei::useCentralTpcCalibrationDefault[0], nuclei::Species::kNspecies, 1, nuclei::names, {"UseCentralTpcCalibration"}}, "Use central TPC calibration"}; + Configurable> cfgDownscalingFactor{"cfgDownscalingFactor", {nuclei::DownscalingDefault[0], nuclei::Species::kNspecies, 1, nuclei::names, {"DownscalingFactor"}}, "Save to the AO2D with a downscaling factor"}; Configurable> cfgUseTrackTuner{"cfgUseTrackTuner", {nuclei::useTrackTuner[0], nuclei::Species::kNspecies, 1, nuclei::names, {"UseTrckTuner"}}, "Use Track Tuner"}; Configurable cfgTrackTunerParams{"cfgTrackTunerParams", "debugInfo=0|updateTrackDCAs=1|updateTrackCovMat=1|updateCurvature=0|updateCurvatureIU=0|updatePulls=0|isInputFileFromCCDB=1|pathInputFile=Users/m/mfaggin/test/inputsTrackTuner/pp2023/pass4/correct_names|nameInputFile=trackTuner_DataLHC23hPass4_McLHC23k4g.root|pathFileQoverPt=Users/h/hsharma/qOverPtGraphs|nameFileQoverPt=D0sigma_Data_removal_itstps_MC_LHC22b1b.root|usePvRefitCorrections=0|qOverPtMC=-1.|qOverPtData=-1.|nPhiBins=1|autoDetectDcaCalib=false", "TrackTuner parameter initialization (format: =|=)"}; @@ -94,6 +119,9 @@ struct nucleiQC { Configurable cfgCutTpcMom{"cfgCutTpcMom", 0.2f, "Minimum TPC momentum for tracks"}; Configurable cfgCutNclusITS{"cfgCutNclusITS", 5, "Minimum number of ITS clusters"}; Configurable cfgCutNclusTPC{"cfgCutNclusTPC", 70, "Minimum number of TPC clusters"}; + Configurable cfgCutNclusCrossedRowsTPC{"cfgCutNclusCrossedRowsTPC", 70, "Minimum number of TPC clusters crossed rows"}; + Configurable cfgCutChi2PerClusterTPC{"cfgCutChi2PerClusterTPC", 4.f, "Maximum chi2 per TPC cluster"}; + Configurable cfgCutChi2PerClusterITS{"cfgCutChi2PerClusterITS", 36.f, "Maximum chi2 per ITS cluster"}; Configurable> cfgNsigmaTPC{"cfgNsigmaTPC", {nuclei::nSigmaTPCdefault[0], nuclei::Species::kNspecies, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; Configurable> cfgNsigmaTOF{"cfgNsigmaTOF", {nuclei::nSigmaTOFdefault[0], nuclei::Species::kNspecies, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; @@ -122,6 +150,7 @@ struct nucleiQC { std::vector mSpeciesToProcess; Produces mNucleiTableRed; + Produces mNucleiTableExt; std::vector mNucleiCandidates; std::vector mFilledMcParticleIds; @@ -165,6 +194,10 @@ struct nucleiQC { } nuclei::createHistogramRegistryNucleus(mHistograms); + mHistograms.add(fmt::format("{}/hTrackQuality", nuclei::cNames[kSpeciesRt]).c_str(), (fmt::format("{} track quality;", nuclei::cNames[kSpeciesRt]) + std::string("#it{p}_{T} / #it{Z} (GeV/#it{c}); Selection step; Counts")).c_str(), o2::framework::HistType::kTH2D, {{400, -10.0f, 10.0f}, {trackQuality::kNtrackQuality, -0.5f, static_cast(trackQuality::kNtrackQuality) - 0.5f}}); + for (size_t iSel = 0; iSel < trackQuality::kNtrackQuality; iSel++) { + mHistograms.get(HIST(nuclei::cNames[kSpeciesRt]) + HIST("/hTrackQuality"))->GetYaxis()->SetBinLabel(iSel + 1, trackQualityLabels[iSel].c_str()); + } if (cfgUseCentralTpcCalibration->get(static_cast(kSpeciesRt), static_cast(0)) == 0) { mPidManagers[kSpeciesRt] = nuclei::PidManager(kSpeciesRt, tpcBetheBlochParams); @@ -216,19 +249,39 @@ struct nucleiQC { LOGF(info, "Retrieved GRP for timestamp %ull (%i) with magnetic field of %1.2f kZG", timestamp, mRunNumber, mBz); } - template + template bool trackSelection(const Ttrack& track) { - if (std::abs(track.eta()) > cfgCutEta || - track.tpcInnerParam() < cfgCutTpcMom || - track.itsNCls() < cfgCutNclusITS || - track.tpcNClsFound() < cfgCutNclusTPC || - track.tpcNClsCrossedRows() < 70 || - track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || - track.tpcChi2NCl() > 4.f || - track.itsChi2NCl() > 36.f) { + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNoCuts); + + if (std::abs(track.eta()) > cfgCutEta) return false; - } + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kEtaCut); + + if (track.tpcInnerParam() < cfgCutTpcMom) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kPtpcCut); + + if (track.itsNCls() < cfgCutNclusITS) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNclsItsCut); + + if (track.tpcNClsFound() < cfgCutNclusTPC) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNclsTpcCut); + + if (track.tpcNClsCrossedRows() < cfgCutNclusCrossedRowsTPC) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kNCrossedRowsCut); + + if (track.tpcChi2NCl() > cfgCutChi2PerClusterTPC) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kTpcChi2Cut); + + if (track.itsChi2NCl() > cfgCutChi2PerClusterITS) + return false; + mHistograms.fill(HIST(nuclei::cNames[iSpecies]) + HIST("/hTrackQuality"), track.sign() * track.pt(), trackQuality::kItsChi2Cut); + return true; } @@ -242,7 +295,7 @@ struct nucleiQC { float centrality = nuclei::getCentrality(collision, cfgCentralityEstimator); float nsigmaTPC = mPidManagers[kIndex].getNSigmaTPC(track); mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTPC_preselectionVsCentrality"), track.pt() * track.sign(), nsigmaTPC, centrality); - if (std::abs(nsigmaTPC) > cfgNsigmaTPC->get(kIndex, 1)) + if (std::abs(nsigmaTPC) > cfgNsigmaTPC->get(kIndex, 1) && cfgPerformPidSelectionInTpc) return false; mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTPCVsCentrality"), track.pt() * track.sign(), nsigmaTPC, centrality); @@ -253,7 +306,7 @@ struct nucleiQC { float nsigmaTOF = mPidManagers[kIndex].getNSigmaTOF(track); mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTOF_preselectionVsCentrality"), track.sign() * track.pt(), nsigmaTOF, centrality); - if (std::abs(nsigmaTOF) > cfgNsigmaTOF->get(kIndex, 1) && track.hasTOF()) + if (std::abs(nsigmaTOF) > cfgNsigmaTOF->get(kIndex, 1) && track.hasTOF() && cfgPerformPidSelectionInTof) return false; mHistograms.fill(HIST(nuclei::cNames[kIndex]) + HIST("/h3NsigmaTOFVsCentrality"), track.sign() * track.pt(), nsigmaTOF, centrality); @@ -389,7 +442,9 @@ struct nucleiQC { .yGenerated = 0.f, .phiGenerated = 0.f, .centrality = nuclei::getCentrality(collision, cfgCentralityEstimator, mHistFailCentrality), - .mcProcess = TMCProcess::kPNoProcess}; + .mcProcess = TMCProcess::kPNoProcess, + .nsigmaTpc = mPidManagers[iSpecies].getNSigmaTPC(track), + .nsigmaTof = mPidManagers[iSpecies].getNSigmaTOF(track)}; fillNucleusFlagsPdgs(iSpecies, collision, track, candidate); @@ -455,6 +510,8 @@ struct nucleiQC { void processMc(const Collision& collision, const TrackCandidatesMC& tracks, const aod::BCsWithTimestamps&, const aod::McParticles& mcParticles) { + + gRandom->SetSeed(67); mNucleiCandidates.clear(); mFilledMcParticleIds.clear(); @@ -478,6 +535,9 @@ struct nucleiQC { mTrackTuner.getDcaGraphs(); } + auto tracksThisCollision = tracks.sliceBy(mTracksPerCollision, collision.globalIndex()); + tracksThisCollision.bindExternalIndices(&tracks); + for (const auto& track : tracks) { static_for<0, nuclei::kNspecies - 1>([&](auto iSpecies) { @@ -496,6 +556,11 @@ struct nucleiQC { return; } + if (cfgDownscalingFactor->get(kSpeciesRt) < 1.) { + if ((gRandom->Uniform()) > cfgDownscalingFactor->get(kSpeciesRt)) + return; + } + if ((particle.y() - cfgRapidityCenterMass) < cfgRapidityMin || (particle.y() - cfgRapidityCenterMass) > cfgRapidityMax) return; @@ -503,7 +568,7 @@ struct nucleiQC { return; mHistograms.fill(HIST(nuclei::cNames[kSpeciesCt]) + HIST("/hTrackSelections"), nuclei::trackSelection::kNoCuts); - if (!trackSelection(track)) + if (!trackSelection(track)) return; mHistograms.fill(HIST(nuclei::cNames[kSpeciesCt]) + HIST("/hTrackSelections"), nuclei::trackSelection::kTrackCuts); @@ -540,6 +605,11 @@ struct nucleiQC { if (std::find(mSpeciesToProcess.begin(), mSpeciesToProcess.end(), iSpecies) == mSpeciesToProcess.end()) continue; + if (cfgDownscalingFactor->get(iSpecies) < 1.) { + if ((gRandom->Uniform()) > cfgDownscalingFactor->get(iSpecies)) + return; + } + nuclei::SlimCandidate candidate; candidate.centrality = nuclei::getCentrality(collision, cfgCentralityEstimator, mHistFailCentrality); fillNucleusFlagsPdgsMc(particle, candidate); @@ -569,6 +639,9 @@ struct nucleiQC { candidate.mcProcess, candidate.pdgCode, candidate.motherPdgCode); + mNucleiTableExt( + candidate.nsigmaTpc, + candidate.nsigmaTof); } } PROCESS_SWITCH(nucleiQC, processMc, "Mc analysis", false); diff --git a/PWGLF/TableProducer/Resonances/HeptaQuarktable.cxx b/PWGLF/TableProducer/Resonances/HeptaQuarktable.cxx index 818c43da234..1d6b20dd6e4 100644 --- a/PWGLF/TableProducer/Resonances/HeptaQuarktable.cxx +++ b/PWGLF/TableProducer/Resonances/HeptaQuarktable.cxx @@ -438,7 +438,7 @@ struct heptaquarktable { if (keepEventDoubleHQ && numberPhi > 1 && numberLambda > 0 && (hqresonance.size() == hqresonanced1.size()) && (hqresonance.size() == hqresonanced2.size())) { histos.fill(HIST("hEventstat"), 2.5); /////////// Fill collision table/////////////// - redHQEvents(bc.globalBC(), currentRunNumber, bc.timestamp(), collision.posZ(), collision.numContrib(), centrality, numberPhi, numberLambda); + redHQEvents(bc.globalBC(), currentRunNumber, bc.timestamp(), collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), centrality, numberPhi, numberLambda); auto indexEvent = redHQEvents.lastIndex(); //// Fill track table for HQ////////////////// for (auto if1 = hqresonance.begin(); if1 != hqresonance.end(); ++if1) { diff --git a/PWGLF/TableProducer/Resonances/cksspinalignment.cxx b/PWGLF/TableProducer/Resonances/cksspinalignment.cxx index b76c9382798..f897dcb1dc8 100644 --- a/PWGLF/TableProducer/Resonances/cksspinalignment.cxx +++ b/PWGLF/TableProducer/Resonances/cksspinalignment.cxx @@ -73,6 +73,8 @@ struct cksspinalignment { Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; } rctCut; + Configurable useNoCollInTimeRangeStandard{"useNoCollInTimeRangeStandard", false, "Apply kNoCollInTimeRangeStandard selection bit"}; + Configurable useGoodITSLayersAll{"useGoodITSLayersAll", true, "Apply kIsGoodITSLayersAll selection bit"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; // events @@ -101,6 +103,13 @@ struct cksspinalignment { Configurable cutTOFBetaPiMeson{"cutTOFBetaPiMeson", 3.0, "Maximum beta cut for pi meson track"}; } grpPion; + enum PionPidBits : uint8_t { + kPID1 = 1u << 0, // selectionPID + kPID2 = 1u << 1, // selectionPID2 + kPID3 = 1u << 2, // selectionPID3 + kPID4 = 1u << 3 // selectionPID4 + }; + // Configs for V0 Configurable confV0PtMin{"confV0PtMin", 0.f, "Minimum transverse momentum of V0"}; Configurable confV0PtMax{"confV0PtMax", 1000.f, "Maximum transverse momentum of V0"}; @@ -120,6 +129,10 @@ struct cksspinalignment { Configurable confDaughTPCncrwsMin{"confDaughTPCncrwsMin", 70.f, "V0 Daugh sel: Min. nCrws TPC"}; Configurable confDaughPIDCuts{"confDaughPIDCuts", 3, "PID selections for Kshortpion daughters"}; + // configurable for chargedkstar + Configurable cfgKstarMassMin{"cfgKstarMassMin", 0.75f, "K* mass min"}; + Configurable cfgKstarMassMax{"cfgKstarMassMax", 1.05f, "K* mass max"}; + Configurable iMNbins{"iMNbins", 50, "Number of bins in invariant mass"}; Configurable lbinIM{"lbinIM", 1.09, "lower bin value in IM histograms"}; Configurable hbinIM{"hbinIM", 1.14, "higher bin value in IM histograms"}; @@ -130,6 +143,8 @@ struct cksspinalignment { { rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); AxisSpec thnAxisInvMass{iMNbins, lbinIM, hbinIM, "#it{M} (GeV/#it{c}^{2})"}; + + histos.add("hCent", "hCent", kTH1F, {{8, 0, 80.0}}); histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{5, 0, 5.0}}); histos.add("hTrkSelInfo", "hTrkSelInfo", kTH1F, {{5, 0, 5.0}}); histos.add("hKShortMass", "hKShortMass", kTH1F, {thnAxisInvMass}); @@ -157,6 +172,81 @@ struct cksspinalignment { return false; } + template + bool selectionPID2(const T& candidate) + { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < grpPion.nsigmaCutTPCPiMeson) { + return true; + } + if (candidate.hasTOF() && candidate.beta() > grpPion.cutTOFBetaPiMeson && std::sqrt(candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi()) < grpPion.nsigmaCutTOFPiMeson) { + return true; + } + return false; + } + + template + bool selectionPID3(const T& candidate) + { + auto px = candidate.px(); + auto py = candidate.py(); + // auto pz = candidate.pz(); + auto pt = std::sqrt(px * px + py * py); + float lowmom = 0.5; + if (pt < lowmom) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < grpPion.nsigmaCutTPCPiMeson) { + return true; + } else if (candidate.hasTOF() && std::sqrt(candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi()) < grpPion.nsigmaCutTOFPiMeson) { + return true; + } + } else if (candidate.hasTOF() && std::sqrt(candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi()) < grpPion.nsigmaCutTOFPiMeson) { + return true; + } + return false; + } + + template + bool selectionPID4(const T& candidate) + { + // Use total momentum p (as you said). If you really want pT, replace with sqrt(px^2+py^2). + const float px = candidate.px(); + const float py = candidate.py(); + // const float pz = candidate.pz(); + const float pt = std::sqrt(px * px + py * py); + + constexpr float pSwitch = 0.5f; // GeV/c + + const float nTPC = candidate.tpcNSigmaPi(); + + // Low momentum: TPC-only, TOF not required and not used + if (pt < pSwitch) { + return std::abs(nTPC) < grpPion.nsigmaCutTPCPiMeson; // e.g. 3 + } + + // High momentum: TOF hit mandatory + separate 3σ cuts + if (!candidate.hasTOF()) { + return false; + } + + const float nTOF = candidate.tofNSigmaPi(); + return (std::abs(nTPC) < grpPion.nsigmaCutTPCPiMeson) && + (std::abs(nTOF) < grpPion.nsigmaCutTOFPiMeson); + } + + template + uint8_t pionPidMask(const T& trk) + { + uint8_t m = 0; + if (selectionPID(trk)) + m |= kPID1; + if (selectionPID2(trk)) + m |= kPID2; + if (selectionPID3(trk)) + m |= kPID3; + if (selectionPID4(trk)) + m |= kPID4; + return m; + } + template bool selectionV0(Collision const& collision, V0 const& candidate) { @@ -280,11 +370,12 @@ struct cksspinalignment { std::vector dcaBetweenDaughter = {}; std::vector v0Lifetime = {}; // std::vector armenteros = {}; - std::vector pionBachelorIndex = {}; + std::vector pionBachelorIndex = {}; // std::vector pionBachelorSign = {}; - std::vector pionBachelorTPC = {}; - std::vector pionBachelorTOF = {}; - std::vector pionBachelorTOFHit = {}; + // std::vector pionBachelorTPC = {}; + // std::vector pionBachelorTOF = {}; + // std::vector pionBachelorTOFHit = {}; + std::vector pionBachelorPidMask = {}; int numbV0 = 0; auto centrality = collision.centFT0C(); @@ -296,10 +387,12 @@ struct cksspinalignment { // auto psiTPCR = collision.psiTPCR(); // auto psiTPCL = collision.psiTPCL(); histos.fill(HIST("hEvtSelInfo"), 0.5); - if ((rctCut.requireRCTFlagChecker && rctChecker(collision)) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) && collision.sel8() && collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll) && occupancy < cfgCutOccupancy) { + // if ((!rctCut.requireRCTFlagChecker || rctChecker(collision)) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && collision.sel8() && collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll) && occupancy < cfgCutOccupancy) { + if ((!rctCut.requireRCTFlagChecker || rctChecker(collision)) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && (!useNoCollInTimeRangeStandard || collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) && collision.sel8() && (!useGoodITSLayersAll || collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) && occupancy < cfgCutOccupancy) { histos.fill(HIST("hEvtSelInfo"), 1.5); if (collision.triggereventep()) { histos.fill(HIST("hEvtSelInfo"), 2.5); + histos.fill(HIST("hCent"), centrality); for (const auto& track1 : tracks) { histos.fill(HIST("hTrkSelInfo"), 0.5); @@ -312,8 +405,12 @@ struct cksspinalignment { continue; } histos.fill(HIST("hTrkSelInfo"), 2.5); - - if (grpPion.usePID && !selectionPID(track1)) { + /* + if (grpPion.usePID && !selectionPID2(track1)) { + continue; + }*/ + const uint8_t mask = pionPidMask(track1); + if (grpPion.usePID && mask == 0) { continue; } histos.fill(HIST("hTrkSelInfo"), 3.5); @@ -322,21 +419,22 @@ struct cksspinalignment { auto track1sign = track1.sign(); if (track1sign == 0) continue; - auto track1nsigTPC = track1.tpcNSigmaPi(); + /*auto track1nsigTPC = track1.tpcNSigmaPi(); auto track1nsigTOF = -999.9; auto track1TOFHit = -1; if (track1.hasTOF()) { track1TOFHit = 1; track1nsigTOF = track1.tofNSigmaPi(); histos.fill(HIST("hTrkSelInfo"), 4.5); - } + }*/ pionbach = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassPionCharged); pionBachelor.push_back(pionbach); pionBachelorIndex.push_back(track1ID); // pionBachelorSign.push_back(track1sign); - pionBachelorTPC.push_back(track1nsigTPC); - pionBachelorTOF.push_back(track1nsigTOF); - pionBachelorTOFHit.push_back(track1TOFHit); + // pionBachelorTPC.push_back(track1nsigTPC); + // pionBachelorTOF.push_back(track1nsigTOF); + // pionBachelorTOFHit.push_back(track1TOFHit); + pionBachelorPidMask.push_back(mask); } for (const auto& v0 : V0s) { histos.fill(HIST("hV0Info"), 0.5); @@ -365,23 +463,66 @@ struct cksspinalignment { } numbV0 = numbV0 + 1; } - if (numbV0 > 1 && v0Cospa.size() > 1) { - histos.fill(HIST("hEvtSelInfo"), 3.5); - kshortpionEvent(centrality, vz, collision.index(), psiFT0C, psiFT0A, psiTPC); - auto indexEvent = kshortpionEvent.lastIndex(); - //// Fill track table for Charged KStar////////////////// - for (auto icks = kshortMother.begin(); icks != kshortMother.end(); ++icks) { - auto iter = std::distance(kshortMother.begin(), icks); - kshortDummy = kshortMother.at(iter); - // chargedkstarDummy = chargedkstarMother.at(iter); - - kshortTrack(indexEvent, v0Cospa.at(iter), v0Radius.at(iter), dcaPositive.at(iter), dcaNegative.at(iter), dcaBetweenDaughter.at(iter), v0Lifetime.at(iter), kshortDummy.Px(), kshortDummy.Py(), kshortDummy.Pz(), kshortDummy.M(), positiveIndex.at(iter), negativeIndex.at(iter)); + if (numbV0 > 1 && v0Cospa.size() > 1 && !kshortMother.empty() && !pionBachelor.empty()) { + + std::vector useK0(kshortMother.size(), 0); + std::vector usePi(pionBachelor.size(), 0); + bool anyPair = false; + for (size_t ik0 = 0; ik0 < kshortMother.size(); ++ik0) { + const auto& k0 = kshortMother[ik0]; + const int posId = positiveIndex[ik0]; + const int negId = negativeIndex[ik0]; + + for (size_t ipi = 0; ipi < pionBachelor.size(); ++ipi) { + const int piId = pionBachelorIndex[ipi]; + + // avoid self-combination: bachelor pion can't be a V0 daughter + if (piId == posId || piId == negId) { + continue; + } + + const auto kstar = k0 + pionBachelor[ipi]; + const float m = kstar.M(); + + if (m < cfgKstarMassMin || m > cfgKstarMassMax) { + continue; + } + + useK0[ik0] = 1; + usePi[ipi] = 1; + anyPair = true; + } } - for (auto ipi = pionBachelor.begin(); ipi != pionBachelor.end(); ++ipi) { - auto iterpi = std::distance(pionBachelor.begin(), ipi); - pionDummy = pionBachelor.at(iterpi); - pionTrack(indexEvent, pionDummy.Px(), pionDummy.Py(), pionDummy.Pz(), pionBachelorTPC.at(iterpi), pionBachelorTOFHit.at(iterpi), pionBachelorTOF.at(iterpi), pionBachelorIndex.at(iterpi)); + // only write event + tables if at least one K* candidate exists in window + if (anyPair) { + histos.fill(HIST("hEvtSelInfo"), 3.5); + // kshortpionEvent(centrality, vz, collision.index(), psiFT0C, psiFT0A, psiTPC); + kshortpionEvent(centrality, vz, psiFT0C, psiFT0A, psiTPC); + auto indexEvent = kshortpionEvent.lastIndex(); + // write only used K0s + for (size_t ik0 = 0; ik0 < kshortMother.size(); ++ik0) { + if (!useK0[ik0]) { + continue; + } + kshortDummy = kshortMother[ik0]; + kshortTrack(indexEvent, v0Cospa[ik0], v0Radius[ik0], dcaPositive[ik0], dcaNegative[ik0], dcaBetweenDaughter[ik0], v0Lifetime[ik0], kshortDummy.Px(), kshortDummy.Py(), kshortDummy.Pz(), kshortDummy.M(), positiveIndex[ik0], negativeIndex[ik0]); + } + // write only used pions + for (size_t ipi = 0; ipi < pionBachelor.size(); ++ipi) { + if (!usePi[ipi]) { + continue; + } + pionDummy = pionBachelor[ipi]; + /* + pionTrack(indexEvent, + pionDummy.Px(), pionDummy.Py(), pionDummy.Pz(), + pionBachelorTPC[ipi], + pionBachelorTOFHit[ipi], + pionBachelorTOF[ipi], + pionBachelorIndex[ipi]);*/ + pionTrack(indexEvent, pionDummy.Px(), pionDummy.Py(), pionDummy.Pz(), pionBachelorIndex[ipi], pionBachelorPidMask[ipi]); + } } } } diff --git a/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx b/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx index a1e5a5bd18c..90cfd3f4d5f 100644 --- a/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx +++ b/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx @@ -30,12 +30,12 @@ #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" #include "CommonConstants/MathConstants.h" -#include "MathUtils/BetheBlochAleph.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include #include @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -69,14 +70,21 @@ struct f1protonreducedtable { OutputObj zorroSummary{"zorroSummary"}; // Configs for events - Configurable ConfEvtSelectZvtx{"ConfEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; - Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + + /// Event selection + struct : ConfigurableGroup { + std::string prefix = std::string("EventSel"); + Configurable ConfEvtSelectZvtx{"ConfEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; + Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable ConfEvtSel8{"ConfEvtSel8", true, "Event selection sel8"}; + } EventSel; // event spherocity calculation Configurable trackSphDef{"trackSphDef", 0, "Spherocity Definition: |pT| = 1 -> 0, otherwise -> 1"}; Configurable trackSphMin{"trackSphMin", 10, "Number of tracks for Spherocity Calculation"}; // Configs for track PID + Configurable Confglobaltrackcheck{"Confglobaltrackcheck", true, "Global track check"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Analysed skimmed events"}; Configurable ConfUseManualPIDproton{"ConfUseManualPIDproton", true, "True: use home-made PID solution for proton "}; Configurable ConfUseManualPIDkaon{"ConfUseManualPIDkaon", true, "True: use home-made PID solution for kaon "}; @@ -154,8 +162,8 @@ struct f1protonreducedtable { {"hInvMassf1Like", "hInvMassf1Like", {HistType::kTH2F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}}}}, {"hInvMassf1kstar", "hInvMassf1kstar", {HistType::kTH3F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}, {8, 0.0f, 0.8f}}}}, {"hkstarDist", "hkstarDist", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, - {"hDCAxy", "hDCAxy", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, - {"hDCAz", "hDCAz", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, + {"hDCAxy", "hDCAxy", {HistType::kTH3F, {{100, -0.05f, 0.05f}, {5, -2.5, 2.5}, {40, 0.0, 4.0}}}}, + {"hDCAz", "hDCAz", {HistType::kTH3F, {{100, -0.05f, 0.05f}, {2, 0, 2}, {40, 0.0, 4.0}}}}, {"hPhi", "hPhi", {HistType::kTH1F, {{1400, -7.0f, 7.0f}}}}, {"hPhiSphero", "hPhiSphero", {HistType::kTH1F, {{1400, -7.0f, 7.0f}}}}, {"hEta", "hEta", {HistType::kTH1F, {{20, -1.0f, 1.0f}}}}, @@ -163,7 +171,7 @@ struct f1protonreducedtable { {"hNsigmaPtpionTOF", "hNsigmaPtpionTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, {"hNsigmaPtkaonTPC", "hNsigmaPtkaonTPC", {HistType::kTH3F, {{200, -10.0f, 10.0f}, {200, -20.0f, 20.0f}, {100, 0.0f, 10.0f}}}}, {"hNsigmaPtkaonTOF", "hNsigmaPtkaonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, - {"hNsigmaPtprotonTPC", "hNsigmaPtprotonTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtprotonTPC", "hNsigmaPtprotonTPC", {HistType::kTH3F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}, {100, 0.0f, 10.0f}}}}, {"hNsigmaPtprotonTOF", "hNsigmaPtprotonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, {"hInvMassk0", "hInvMassk0", {HistType::kTH2F, {{200, 0.4f, 0.6f}, {100, 0.0f, 10.0f}}}}, }, @@ -184,7 +192,10 @@ struct f1protonreducedtable { template bool isSelectedEvent(T const& col) { - if (ConfEvtSelectZvtx && std::abs(col.posZ()) > ConfEvtZvtx) { + if (EventSel.ConfEvtSelectZvtx && std::abs(col.posZ()) > EventSel.ConfEvtZvtx) { + return false; + } + if (EventSel.ConfEvtSel8 && !col.sel8()) { return false; } return true; @@ -255,7 +266,7 @@ struct f1protonreducedtable { template bool selectionGlobalTrack(const T& candidate) { - if (!(candidate.isGlobalTrack() && candidate.isPVContributor())) { + if (Confglobaltrackcheck && !(candidate.isGlobalTrack() && candidate.isPVContributor())) { return false; } return true; @@ -338,6 +349,32 @@ struct f1protonreducedtable { return false; } + inline bool passProtonPID(float nsigmaTPC, float nsigmaTOF, float TOFHit, ROOT::Math::PtEtaPhiMVector proton) + { + // pidMode: + // 0 = default: p < thr -> |TPC| < 2.5 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.0 + // 1 = syst-1: p < thr -> |TPC| < 2.0 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.0 + // 2 = syst-2: p < thr -> |TPC| < 2.5 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.5 + + if (proton.Pt() > 4.0 || proton.Pt() < 0.15) { + return false; + } + + if (proton.P() < 0.7) { + return (std::abs(nsigmaTPC) < 2.5); + } + + // above threshold: TOF must exist + if (TOFHit != 1) { + return false; + } + + const float nsTPC = nsigmaTPC; + const float nsTOF = nsigmaTOF; + const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + return (comb < 2.5); + } + template bool SelectionV0(Collision const& collision, V0 const& candidate) { @@ -497,7 +534,7 @@ struct f1protonreducedtable { Filter dcaFilter = nabs(aod::track::dcaXY) < ConfTrkDCAxyMaxF1Proton && nabs(aod::track::dcaZ) < ConfTrkDCAzMaxF1Proton; // using EventCandidates = soa::Join; - using EventCandidates = aod::Collisions; + using EventCandidates = soa::Join; using ResoV0s = aod::V0Datas; using PrimaryTrackCandidates = soa::Filtered PionTOFHitFinal = {}; std::vector PionTPC = {}; std::vector PionTPCFinal = {}; + std::vector PionTOFNsigma = {}; + std::vector PionTOFNsigmaFinal = {}; // keep TOF Hit of kaon std::vector KaonTOFHit = {}; std::vector KaonTOFHitFinal = {}; std::vector KaonTPC = {}; std::vector KaonTPCFinal = {}; + std::vector KaonTOFNsigma = {}; + std::vector KaonTOFNsigmaFinal = {}; std::vector KaonTPCPionHypo = {}; std::vector KaonTPCPionHypoFinal = {}; @@ -561,6 +602,68 @@ struct f1protonreducedtable { // keep status of F1 signal unlike or wrong sign std::vector f1signal = {}; + // keep track dcaxy + std::vector PionDcaxy = {}; + std::vector KaonDcaxy = {}; + std::vector ProtonDcaxy = {}; + std::vector K0D1Dcaxy = {}; + std::vector K0D2Dcaxy = {}; + + // keep track ncls + std::vector PionTPCNcls = {}; + std::vector KaonTPCNcls = {}; + std::vector ProtonTPCNcls = {}; + std::vector K0D1TPCNcls = {}; + std::vector K0D2TPCNcls = {}; + + // keep track ncrs + std::vector PionTPCNcrs = {}; + std::vector KaonTPCNcrs = {}; + std::vector ProtonTPCNcrs = {}; + std::vector K0D1TPCNcrs = {}; + std::vector K0D2TPCNcrs = {}; + + // keep track dcaz + std::vector PionDcaz = {}; + std::vector KaonDcaz = {}; + std::vector ProtonDcaz = {}; + + // keep v0 topology + std::vector K0Cpa = {}; + std::vector K0radius = {}; + std::vector K0DcaBetweenDaughters = {}; + std::vector K0Dca = {}; + std::vector K0LifeTime = {}; + + // keep track dcaxy + std::vector PionDcaxyFinal = {}; + std::vector KaonDcaxyFinal = {}; + std::vector K0D1DcaxyFinal = {}; + std::vector K0D2DcaxyFinal = {}; + + // keep track ncls + std::vector PionTPCNclsFinal = {}; + std::vector KaonTPCNclsFinal = {}; + std::vector K0D1TPCNclsFinal = {}; + std::vector K0D2TPCNclsFinal = {}; + + // keep track ncrs + std::vector PionTPCNcrsFinal = {}; + std::vector KaonTPCNcrsFinal = {}; + std::vector K0D1TPCNcrsFinal = {}; + std::vector K0D2TPCNcrsFinal = {}; + + // keep track dcaz + std::vector PionDcazFinal = {}; + std::vector KaonDcazFinal = {}; + + // keep v0 topology + std::vector K0CpaFinal = {}; + std::vector K0radiusFinal = {}; + std::vector K0DcaBetweenDaughtersFinal = {}; + std::vector K0DcaFinal = {}; + std::vector K0LifeTimeFinal = {}; + // Prepare vectors for different species std::vector protons, kaons, pions, kshorts, f1resonance, f1resonanced1, f1resonanced2, f1resonanced3; // , protonsfinal; @@ -606,8 +709,6 @@ struct f1protonreducedtable { if (!selectionGlobalTrack(track)) { continue; } - qaRegistry.fill(HIST("hDCAxy"), track.dcaXY()); - qaRegistry.fill(HIST("hDCAz"), track.dcaZ()); qaRegistry.fill(HIST("hEta"), track.eta()); qaRegistry.fill(HIST("hPhi"), track.phi()); double nTPCSigmaP[3]{track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; @@ -639,7 +740,14 @@ struct f1protonreducedtable { pions.push_back(temp); PionIndex.push_back(track.globalIndex()); PionCharge.push_back(track.sign()); + + PionDcaxy.push_back(std::abs(track.dcaXY())); + PionDcaz.push_back(std::abs(track.dcaZ())); + PionTPCNcls.push_back(std::abs(track.tpcNClsFound())); + PionTPCNcrs.push_back(std::abs(track.tpcNClsCrossedRows())); + auto PionTOF = 0; + auto nSigmaPionTOF = -999; if (track.sign() > 0) { qaRegistry.fill(HIST("hNsigmaPtpionTPC"), nTPCSigmaP[0], track.pt()); PionTPC.push_back(nTPCSigmaP[0]); @@ -650,9 +758,11 @@ struct f1protonreducedtable { } if (track.hasTOF()) { qaRegistry.fill(HIST("hNsigmaPtpionTOF"), track.tofNSigmaPi(), track.pt()); + nSigmaPionTOF = track.tofNSigmaPi(); PionTOF = 1; } PionTOFHit.push_back(PionTOF); + PionTOFNsigma.push_back(nSigmaPionTOF); } if ((track.pt() > cMinKaonPt && track.sign() > 0 && SelectionPID(track, strategyPIDKaon, 1, nTPCSigmaP[1]) && (itsResponse.nSigmaITS(track) > -3.0 && itsResponse.nSigmaITS(track) < 3.0)) || (track.pt() > cMinKaonPt && track.sign() < 0 && SelectionPID(track, strategyPIDKaon, 1, nTPCSigmaN[1]) && (itsResponse.nSigmaITS(track) > -3.0 && itsResponse.nSigmaITS(track) < 3.0))) { @@ -660,7 +770,14 @@ struct f1protonreducedtable { kaons.push_back(temp); KaonIndex.push_back(track.globalIndex()); KaonCharge.push_back(track.sign()); + + KaonDcaxy.push_back(std::abs(track.dcaXY())); + KaonDcaz.push_back(std::abs(track.dcaZ())); + KaonTPCNcls.push_back(std::abs(track.tpcNClsFound())); + KaonTPCNcrs.push_back(std::abs(track.tpcNClsCrossedRows())); + auto KaonTOF = 0; + auto nSigmaKaonTOF = -999.0; if (track.sign() > 0) { qaRegistry.fill(HIST("hNsigmaPtkaonTPC"), nTPCSigmaP[1], nTPCSigmaP[0], track.pt()); KaonTPC.push_back(nTPCSigmaP[1]); @@ -674,8 +791,10 @@ struct f1protonreducedtable { if (track.hasTOF()) { qaRegistry.fill(HIST("hNsigmaPtkaonTOF"), track.tofNSigmaKa(), track.pt()); KaonTOF = 1; + nSigmaKaonTOF = track.tofNSigmaKa(); } KaonTOFHit.push_back(KaonTOF); + KaonTOFNsigma.push_back(nSigmaKaonTOF); } if ((track.pt() < cMaxProtonPt && track.sign() > 0 && SelectionPID(track, strategyPIDProton, 2, nTPCSigmaP[2]) && (itsResponse.nSigmaITS(track) > -3.0 && itsResponse.nSigmaITS(track) < 3.0)) || (track.pt() < cMaxProtonPt && track.sign() < 0 && SelectionPID(track, strategyPIDProton, 2, nTPCSigmaN[2]) && (itsResponse.nSigmaITS(track) > -3.0 && itsResponse.nSigmaITS(track) < 3.0))) { @@ -683,12 +802,16 @@ struct f1protonreducedtable { protons.push_back(temp); ProtonIndex.push_back(track.globalIndex()); ProtonCharge.push_back(track.sign()); + + ProtonDcaxy.push_back(track.dcaXY()); + ProtonDcaz.push_back(track.dcaZ()); + ProtonTPCNcls.push_back(std::abs(track.tpcNClsFound())); + ProtonTPCNcrs.push_back(std::abs(track.tpcNClsCrossedRows())); + if (track.sign() > 0) { - qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaP[2], track.pt()); ProtonTPCNsigma.push_back(nTPCSigmaP[2]); } if (track.sign() < 0) { - qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaN[2], track.pt()); ProtonTPCNsigma.push_back(nTPCSigmaN[2]); } if (track.hasTOF()) { @@ -697,7 +820,7 @@ struct f1protonreducedtable { ProtonTOFHit.push_back(1); } if (!track.hasTOF()) { - ProtonTOFNsigma.push_back(999.0); + ProtonTOFNsigma.push_back(-999.0); ProtonTOFHit.push_back(0); } } @@ -729,6 +852,20 @@ struct f1protonreducedtable { kshorts.push_back(temp); KshortPosDaughIndex.push_back(postrack.globalIndex()); KshortNegDaughIndex.push_back(negtrack.globalIndex()); + + K0D1Dcaxy.push_back(std::abs(postrack.dcaXY())); + K0D1TPCNcls.push_back(std::abs(postrack.tpcNClsFound())); + K0D1TPCNcrs.push_back(std::abs(postrack.tpcNClsCrossedRows())); + + K0D2Dcaxy.push_back(std::abs(negtrack.dcaXY())); + K0D2TPCNcls.push_back(std::abs(negtrack.tpcNClsFound())); + K0D2TPCNcrs.push_back(std::abs(negtrack.tpcNClsCrossedRows())); + + K0Cpa.push_back(std::abs(v0.v0cosPA())); + K0radius.push_back(std::abs(v0.v0radius())); + K0DcaBetweenDaughters.push_back(std::abs(v0.dcaV0daughters())); + K0LifeTime.push_back(std::abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass())); + K0Dca.push_back(std::abs(v0.dcav0topv())); } if (pions.size() != 0 && kaons.size() != 0 && kshorts.size() != 0) { @@ -782,6 +919,31 @@ struct f1protonreducedtable { PionTPCFinal.push_back(PionTPC.at(i1)); // Pion TPC KaonTPCFinal.push_back(KaonTPC.at(i2)); // Kaon TPC KaonTPCPionHypoFinal.push_back(KaonTPCPionHypo.at(i2)); // Kaon TPC + + // Fill variable for systematic + + PionTOFNsigmaFinal.push_back(PionTOFNsigma.at(i1)); + PionDcaxyFinal.push_back(PionDcaxy.at(i1)); + PionDcazFinal.push_back(PionDcaz.at(i1)); + PionTPCNcrsFinal.push_back(PionTPCNcrs.at(i1)); + PionTPCNclsFinal.push_back(PionTPCNcls.at(i1)); + KaonTOFNsigmaFinal.push_back(KaonTOFNsigma.at(i2)); + KaonDcaxyFinal.push_back(KaonDcaxy.at(i2)); + KaonDcazFinal.push_back(KaonDcaz.at(i2)); + KaonTPCNcrsFinal.push_back(KaonTPCNcrs.at(i2)); + KaonTPCNclsFinal.push_back(KaonTPCNcls.at(i2)); + K0D1DcaxyFinal.push_back(K0D1Dcaxy.at(i3)); + K0D1TPCNcrsFinal.push_back(K0D1TPCNcrs.at(i3)); + K0D1TPCNclsFinal.push_back(K0D1TPCNcls.at(i3)); + K0D2DcaxyFinal.push_back(K0D2Dcaxy.at(i3)); + K0D2TPCNcrsFinal.push_back(K0D2TPCNcrs.at(i3)); + K0D2TPCNclsFinal.push_back(K0D2TPCNcls.at(i3)); + K0CpaFinal.push_back(K0Cpa.at(i3)); + K0radiusFinal.push_back(K0radius.at(i3)); + K0DcaBetweenDaughtersFinal.push_back(K0DcaBetweenDaughters.at(i3)); + K0DcaFinal.push_back(K0Dca.at(i3)); + K0LifeTimeFinal.push_back(K0LifeTime.at(i3)); + if (pairsign > 0) { qaRegistry.fill(HIST("hInvMassf1"), F1Vector.M(), F1Vector.Pt()); numberF1 = numberF1 + 1; @@ -822,6 +984,25 @@ struct f1protonreducedtable { } } qaRegistry.fill(HIST("hEventstat"), 0.5); + if (keepEventF1Proton) { + for (auto iproton = protons.begin(); iproton != protons.end(); ++iproton) { + auto i6 = std::distance(protons.begin(), iproton); + ProtonVectorDummy2 = protons.at(i6); + if (std::abs(ProtonDcaxy.at(i6)) < 0.05 && std::abs(ProtonDcaz.at(i6)) < 0.05) { + if (ProtonTOFHit.at(i6) && ProtonVectorDummy2.P() > 0.7) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), ProtonTPCNsigma.at(i6), ProtonTOFNsigma.at(i6), ProtonVectorDummy2.Pt()); + } + if (ProtonVectorDummy2.P() < 0.7) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), ProtonTPCNsigma.at(i6), 4.999, ProtonVectorDummy2.Pt()); + } + } + if (passProtonPID(ProtonTPCNsigma.at(i6), ProtonTOFNsigma.at(i6), ProtonTOFHit.at(i6), ProtonVectorDummy2)) { + qaRegistry.fill(HIST("hDCAxy"), ProtonDcaxy.at(i6), ProtonCharge.at(i6), ProtonVectorDummy2.Pt()); + qaRegistry.fill(HIST("hDCAz"), ProtonDcaz.at(i6), ProtonCharge.at(i6), ProtonVectorDummy2.Pt()); + } + } + } + if (numberF1 > 0 && (f1resonance.size() == f1signal.size()) && (f1resonance.size() == f1kaonkshortmass.size()) && (f1resonance.size() == f1resonanced1.size()) && (f1resonance.size() == f1resonanced2.size()) && (f1resonance.size() == f1resonanced3.size())) { qaRegistry.fill(HIST("hEventstat"), 1.5); if (keepEventF1Proton) { @@ -838,13 +1019,13 @@ struct f1protonreducedtable { F1d1dummy = f1resonanced1.at(i5); F1d2dummy = f1resonanced2.at(i5); F1d3dummy = f1resonanced3.at(i5); - f1track(indexEvent, f1signal.at(i5), F1VectorDummy.Px(), F1VectorDummy.Py(), F1VectorDummy.Pz(), F1d1dummy.Px(), F1d1dummy.Py(), F1d1dummy.Pz(), F1d2dummy.Px(), F1d2dummy.Py(), F1d2dummy.Pz(), F1d3dummy.Px(), F1d3dummy.Py(), F1d3dummy.Pz(), PionTOFHitFinal.at(i5), KaonTOFHitFinal.at(i5), PionTPCFinal.at(i5), KaonTPCFinal.at(i5), KaonTPCPionHypoFinal.at(i5), F1VectorDummy.M(), f1kaonkshortmass.at(i5), F1PionIndex.at(i5), F1KaonIndex.at(i5), F1KshortDaughterPositiveIndex.at(i5), F1KshortDaughterNegativeIndex.at(i5)); + f1track(indexEvent, f1signal.at(i5), F1VectorDummy.Px(), F1VectorDummy.Py(), F1VectorDummy.Pz(), F1d1dummy.Px(), F1d1dummy.Py(), F1d1dummy.Pz(), F1d2dummy.Px(), F1d2dummy.Py(), F1d2dummy.Pz(), F1d3dummy.Px(), F1d3dummy.Py(), F1d3dummy.Pz(), PionTOFHitFinal.at(i5), KaonTOFHitFinal.at(i5), PionTPCFinal.at(i5), KaonTPCFinal.at(i5), KaonTPCPionHypoFinal.at(i5), F1VectorDummy.M(), f1kaonkshortmass.at(i5), F1PionIndex.at(i5), F1KaonIndex.at(i5), F1KshortDaughterPositiveIndex.at(i5), F1KshortDaughterNegativeIndex.at(i5), PionTOFNsigmaFinal.at(i5), PionDcaxyFinal.at(i5), PionDcazFinal.at(i5), PionTPCNclsFinal.at(i5), PionTPCNcrsFinal.at(i5), KaonTOFNsigmaFinal.at(i5), KaonDcaxyFinal.at(i5), KaonDcazFinal.at(i5), KaonTPCNclsFinal.at(i5), KaonTPCNcrsFinal.at(i5), K0D1DcaxyFinal.at(i5), K0D1TPCNclsFinal.at(i5), K0D1TPCNcrsFinal.at(i5), K0D2DcaxyFinal.at(i5), K0D2TPCNclsFinal.at(i5), K0D2TPCNcrsFinal.at(i5), K0CpaFinal.at(i5), K0radiusFinal.at(i5), K0DcaBetweenDaughtersFinal.at(i5), K0DcaFinal.at(i5), K0LifeTimeFinal.at(i5)); } //// Fill track table for proton////////////////// for (auto iproton = protons.begin(); iproton != protons.end(); ++iproton) { auto i6 = std::distance(protons.begin(), iproton); ProtonVectorDummy2 = protons.at(i6); - protontrack(indexEvent, ProtonCharge.at(i6), ProtonVectorDummy2.Px(), ProtonVectorDummy2.Py(), ProtonVectorDummy2.Pz(), ProtonTPCNsigma.at(i6), ProtonTOFHit.at(i6), ProtonTOFNsigma.at(i6), ProtonIndex.at(i6)); + protontrack(indexEvent, ProtonCharge.at(i6), ProtonVectorDummy2.Px(), ProtonVectorDummy2.Py(), ProtonVectorDummy2.Pz(), ProtonTPCNsigma.at(i6), ProtonTOFHit.at(i6), ProtonTOFNsigma.at(i6), ProtonIndex.at(i6), ProtonDcaxy.at(i6), ProtonDcaz.at(i6), ProtonTPCNcls.at(i6), ProtonTPCNcrs.at(i6)); } } } diff --git a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx index 79514728d10..03c28a9b701 100644 --- a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx @@ -11,11 +11,12 @@ /// /// \file resonanceInitializer.cxx /// \brief Initializes variables for the resonance candidate producers -/// \author Bong-Hwi Lim +/// \author Bong-Hwi Lim , Minjae Kim /// #include "PWGLF/DataModel/LFResonanceTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/collisionCuts.h" #include "Common/Core/EventPlaneHelper.h" @@ -24,6 +25,7 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -137,7 +139,7 @@ struct ResonanceInitializer { // Pre-selection cuts Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; - Configurable pidnSigmaPreSelectionCut{"pidnSigmaPreSelectionCut", 5.0f, "TPC and TOF PID cut (loose, improve performance)"}; + Configurable pidnSigmaPreSelectionCut{"pidnSigmaPreSelectionCut", 5.0f, "TPC PID cut (loose, improve performance)"}; Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; /// DCA Selections for V0 @@ -179,6 +181,8 @@ struct ResonanceInitializer { Configurable cfgFillLambda0{"cfgFillLambda0", false, "Fill Lambda0"}; Configurable cfgFillXi0{"cfgFillXi0", false, "Fill Xi0"}; Configurable cfgFillOmega0{"cfgFillOmega0", false, "Fill Omega0"}; + Configurable cfgBypassNoPairCascades{"cfgBypassNoPairCascades", true, "Bypass track fill if no pair cascade with track"}; + Configurable cfgBypassNoPairV0s{"cfgBypassNoPairV0s", false, "Bypass if no pair V0 with track"}; } FilterForDerivedTables; // Secondary cuts @@ -205,6 +209,28 @@ struct ResonanceInitializer { Configurable cfgSecondaryCrossMassCutWindow{"cfgSecondaryCrossMassCutWindow", 0.05, "Secondary inv mass selection window with (anti)lambda hypothesis"}; } SecondaryCuts; + struct : ConfigurableGroup { + Configurable cfgGenMult05{"cfgGenMult05", true, "GenEvent: multiplicity in |eta| < 0.5"}; + Configurable cfgGenMult10{"cfgGenMult10", false, "GenEvent: multiplicity in |eta| < 1.0"}; + Configurable cfgGenMultPercentile{"cfgGenMultPercentile", false, "Inherit Centrality(Multiplicity) percentile from MC collision only using LF-mc-centrality task"}; + + Configurable isZvtxcutGen{"isZvtxcutGen", true, "z-vertex cut for the GenCollision"}; + Configurable cutzvertexGen{"cutzvertexGen", 10.0f, "z-vertex cut for the GenCollision"}; + Configurable checkIsTrueINELgt0{"checkIsTrueINELgt0", true, "Check true INEL>0 for the Gen. Collision"}; + + ConfigurableAxis ptAxisGen{"ptAxisGen", {400, 0.0f, 20.0f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis multNTracksAxis{"multNTracksAxis", {500, 0.0f, +5000.0f}, "Number of charged particles"}; + ConfigurableAxis impactParameterAxis{"impactParameterAxis", {500, 0, 50}, "IP (fm)"}; + + Configurable isDaughterCheck{"isDaughterCheck", 1, "Check if the mother has the correct daughters when it is considered"}; + Configurable cfgRapidityCutMinGen{"cfgRapidityCutMinGen", -0.5, "Rapidity cut for the truth particle"}; + Configurable cfgRapidityCutMaxGen{"cfgRapidityCutMaxGen", 0.5, "Rapidity cut for the truth particle"}; + Configurable pdgTruthMother{"pdgTruthMother", 3324, "pdgcode for the truth mother e.g. Xi(1530) (3324)"}; + Configurable pdgTruthDaughter1{"pdgTruthDaughter1", 3312, "pdgcode for the daughter 1, e.g. Xi- 3312"}; + Configurable pdgTruthDaughter2{"pdgTruthDaughter2", 211, "pdgcode for the daughter 2, e.g. pi+ 211"}; + } GenCuts; + Configurable checkIsRecINELgt0{"checkIsRecINELgt0", true, "Check rec INEL>0 for the Rec. Collision"}; + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Pre-filters for efficient process @@ -244,7 +270,8 @@ struct ResonanceInitializer { || (nabs(aod::mcparticle::pdgCode) == 123314) // Xi(1820)0 || (nabs(aod::mcparticle::pdgCode) == 123324); // Xi(1820)-0 - using ResoEvents = soa::Join; + using ResoEvents = soa::Join; + using ResoEvents001 = soa::Join; using ResoRun2Events = soa::Join; using ResoEventsMC = soa::Join; using ResoRun2EventsMC = soa::Join; @@ -357,7 +384,7 @@ struct ResonanceInitializer { return false; if (v0.qtarm() < SecondaryCuts.cfgSecondaryparamArmenterosCut * std::abs(v0.alpha())) return false; - if (std::fabs(v0.mLambda() - MassLambda0) < SecondaryCuts.cfgSecondaryMassWindow) + if (std::fabs(v0.mLambda() - MassLambda0) > SecondaryCuts.cfgSecondaryMassWindow) return false; if (SecondaryCuts.cfgSecondaryCrossMassHypothesisCut && (std::fabs(v0.mK0Short() - MassK0Short) < SecondaryCuts.cfgSecondaryCrossMassCutWindow)) return false; @@ -568,6 +595,9 @@ struct ResonanceInitializer { case 2: returnValue = ResoEvents.centFT0A(); break; + case 3: + returnValue = ResoEvents.centFV0A(); + break; default: returnValue = ResoEvents.centFT0M(); break; @@ -769,7 +799,8 @@ struct ResonanceInitializer { v0.mLambda(), v0.mAntiLambda(), v0.mK0Short(), - v0.v0radius(), v0.x(), v0.y(), v0.z()); + v0.v0radius(), v0.x(), v0.y(), v0.z(), + v0.alpha(), v0.qtarm()); if (!cfgBypassTrackIndexFill) { resoV0V0s(v0.globalIndex()); } @@ -931,6 +962,22 @@ struct ResonanceInitializer { } return lMothersPDGs; }; + auto getMothersPt = [&](auto const& theMcParticle) { + std::vector lMothersPts{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother pdgcode lMother: %f", lMother.pt()); + lMothersPts.push_back(lMother.pt()); + } + return lMothersPts; + }; + auto getMothersRap = [&](auto const& theMcParticle) { + std::vector lMothersRaps{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother rap lMother: %f", lMother.y()); + lMothersRaps.push_back(lMother.y()); + } + return lMothersRaps; + }; auto getDaughtersIndeces = [&](auto const& theMcParticle) { std::vector lDaughtersIndeces{}; for (auto const& lDaughter : theMcParticle.template daughters_as()) { @@ -954,6 +1001,8 @@ struct ResonanceInitializer { // ------ std::vector mothers = {-1, -1}; std::vector motherPDGs = {-1, -1}; + std::vector mothersPts = {-1.0f, -1.0f}; + std::vector mothersRaps = {-1.0f, -1.0f}; std::vector daughters = {-1, -1}; std::vector daughterPDGs = {-1, -1}; if (v0.has_mcParticle()) { @@ -961,23 +1010,28 @@ struct ResonanceInitializer { if (v0mc.has_mothers()) { mothers = getMothersIndeces(v0mc); motherPDGs = getMothersPDGCodes(v0mc); + mothersPts = getMothersPt(v0mc); + mothersRaps = getMothersRap(v0mc); } while (mothers.size() > 2) { mothers.pop_back(); motherPDGs.pop_back(); + mothersPts.pop_back(); } if (v0mc.has_daughters()) { daughters = getDaughtersIndeces(v0mc); daughterPDGs = getDaughtersPDGCodes(v0mc); } while (daughters.size() > 2) { - LOGF(info, "daughters.size() is larger than 2"); + // LOGF(info, "daughters.size() is larger than 2"); daughters.pop_back(); daughterPDGs.pop_back(); } reso2mcv0s(v0mc.pdgCode(), mothers[0], motherPDGs[0], + mothersPts[0], + mothersRaps[0], daughters[0], daughters[1], daughterPDGs[0], @@ -988,6 +1042,8 @@ struct ResonanceInitializer { reso2mcv0s(0, mothers[0], motherPDGs[0], + mothersPts[0], + mothersRaps[0], daughters[0], daughters[1], daughterPDGs[0], @@ -1017,6 +1073,22 @@ struct ResonanceInitializer { } return lMothersPDGs; }; + auto getMothersPt = [&](auto const& theMcParticle) { + std::vector lMothersPts{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother pdgcode lMother: %f", lMother.pt()); + lMothersPts.push_back(lMother.pt()); + } + return lMothersPts; + }; + auto getMothersRap = [&](auto const& theMcParticle) { + std::vector lMothersRaps{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother rap lMother: %f", lMother.y()); + lMothersRaps.push_back(lMother.y()); + } + return lMothersRaps; + }; auto getDaughtersIndeces = [&](auto const& theMcParticle) { std::vector lDaughtersIndeces{}; for (auto const& lDaughter : theMcParticle.template daughters_as()) { @@ -1042,28 +1114,35 @@ struct ResonanceInitializer { std::vector motherPDGs = {-1, -1}; std::vector daughters = {-1, -1}; std::vector daughterPDGs = {-1, -1}; + std::vector mothersPts = {-1.0f, -1.0f}; + std::vector mothersRaps = {-1.0f, -1.0f}; if (casc.has_mcParticle()) { auto cascmc = casc.mcParticle(); if (cascmc.has_mothers()) { mothers = getMothersIndeces(cascmc); + mothersPts = getMothersPt(cascmc); + mothersRaps = getMothersRap(cascmc); motherPDGs = getMothersPDGCodes(cascmc); } while (mothers.size() > 2) { mothers.pop_back(); motherPDGs.pop_back(); + mothersPts.pop_back(); } if (cascmc.has_daughters()) { daughters = getDaughtersIndeces(cascmc); daughterPDGs = getDaughtersPDGCodes(cascmc); } while (daughters.size() > 2) { - LOGF(info, "daughters.size() is larger than 2"); + // LOGF(info, "daughters.size() is larger than 2"); daughters.pop_back(); daughterPDGs.pop_back(); } reso2mccascades(cascmc.pdgCode(), mothers[0], motherPDGs[0], + mothersPts[0], + mothersRaps[0], daughters[0], daughters[1], daughterPDGs[0], @@ -1074,6 +1153,8 @@ struct ResonanceInitializer { reso2mccascades(0, mothers[0], motherPDGs[0], + mothersPts[0], + mothersRaps[0], daughters[0], daughters[1], daughterPDGs[0], @@ -1112,20 +1193,55 @@ struct ResonanceInitializer { } } + template + void fillMCGenParticles(TotalMCParts const& mcParticles, MCCentGen const& Cent, MCMultGen const& MCMult, MCIPGen const& IP, evtType const& eventType) + { + for (auto const& mcPart : mcParticles) { + + if (std::abs(mcPart.pdgCode()) != GenCuts.pdgTruthMother) + continue; + if ((mcPart.y() >= GenCuts.cfgRapidityCutMaxGen) || (mcPart.y() <= GenCuts.cfgRapidityCutMinGen)) + continue; + std::vector daughterPDGs; + if (mcPart.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(mcPart.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(mcPart.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; + } + + if (GenCuts.isDaughterCheck) { + bool pass1 = std::abs(daughterPDGs[0]) == GenCuts.pdgTruthDaughter1 || std::abs(daughterPDGs[1]) == GenCuts.pdgTruthDaughter1; + bool pass2 = std::abs(daughterPDGs[0]) == GenCuts.pdgTruthDaughter2 || std::abs(daughterPDGs[1]) == GenCuts.pdgTruthDaughter2; + if (!pass1 || !pass2) + continue; + } + if (mcPart.pdgCode() > 0) // Consider INELt0 or INEL + qaRegistry.fill(HIST("EventGen/h5ResonanceTruth"), eventType, mcPart.pt(), Cent, MCMult, IP); + else + qaRegistry.fill(HIST("EventGen/h5ResonanceTruthAnti"), eventType, mcPart.pt(), Cent, MCMult, IP); + + daughterPDGs.clear(); + } + } + template - void fillMCCollision(MCCol const& mccol, MCPart const& mcparts, float impactpar = -999.0) + void fillMCCollision(MCCol const& mccol, MCPart const& mcparts, float impactpar = -999.0, float mult = -1.0) { auto centrality = 0.0; if constexpr (!isRun2) centrality = centEst(mccol); else centrality = mccol.centRun2V0M(); - bool inVtx10 = (std::abs(mccol.mcCollision().posZ()) > 10.) ? false : true; + + // bool inVtx10 = (std::abs(mccol.mcCollision().posZ()) > 10.) ? false : true; -> Gen. level informations will be processed in processMCGen + bool inVtx10 = (std::abs(mccol.posZ()) > 10.) ? false : true; bool isTrueINELgt0 = isTrueINEL0(mccol, mcparts); bool isTriggerTVX = mccol.selection_bit(aod::evsel::kIsTriggerTVX); bool isSel8 = mccol.sel8(); bool isSelected = colCuts.isSelected(mccol); - resoMCCollisions(inVtx10, isTrueINELgt0, isTriggerTVX, isSel8, isSelected, impactpar); + resoMCCollisions(inVtx10, isTrueINELgt0, isTriggerTVX, isSel8, isSelected, impactpar, mult); // QA for Trigger efficiency qaRegistry.fill(HIST("Event/hMCEventIndices"), centrality, aod::resocollision::kINEL); @@ -1171,7 +1287,7 @@ struct ResonanceInitializer { { mRunNumber = 0; dBz = 0; - // Multiplicity estimator selection (0: FT0M, 1: FT0C, 2: FT0A, 99: FV0A) + // Multiplicity estimator selection (0: FT0M, 1: FT0C, 2: FT0A, 3: FV0A) if (cfgMultName.value == "FT0M") { multEstimator = 0; } else if (cfgMultName.value == "FT0C") { @@ -1179,7 +1295,7 @@ struct ResonanceInitializer { } else if (cfgMultName.value == "FT0A") { multEstimator = 2; } else if (cfgMultName.value == "FV0A") { - multEstimator = 99; + multEstimator = 3; } else { multEstimator = 0; } @@ -1229,6 +1345,7 @@ struct ResonanceInitializer { AxisSpec idxMCAxis = {26, -0.5, 25.5, "Index"}; qaRegistry.add("Event/hMCEventIndices", "hMCEventIndices", kTH2D, {centAxis, idxMCAxis}); } + qaRegistry.add("Event/CentFV0A", "; FV0A Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); AxisSpec idxAxis = {8, 0, 8, "Index"}; if (cfgFillQA) { qaRegistry.add("hGoodTrackIndices", "hGoodTrackIndices", kTH1F, {idxAxis}); @@ -1239,6 +1356,22 @@ struct ResonanceInitializer { qaRegistry.add("hGoodMCCascIndices", "hGoodMCCascIndices", kTH1F, {idxAxis}); qaRegistry.add("Phi", "#phi distribution", kTH1F, {{65, -0.1, 6.4}}); } + + TString hNEventsMCLabels[4] = {"All", "z vrtx", "INEL", "INEL>0"}; + if (doprocessMCgen) { + AxisSpec centAxisGen = {binsCent, "Centrality (%)"}; + qaRegistry.add("EventGen/hNEventsMC", "EventGen/hNEventsMC", kTH1D, {{4, 0.0f, 4.0f}}); + for (int n = 1; n <= qaRegistry.get(HIST("EventGen/hNEventsMC"))->GetNbinsX(); n++) { + qaRegistry.get(HIST("EventGen/hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsMCLabels[n - 1]); + } + qaRegistry.add("EventGen/h5ResonanceTruth", "EventGen/h5ResonanceTruth", kTHnSparseD, {{2, 0.0f, 2.0f}, GenCuts.ptAxisGen, centAxisGen, GenCuts.multNTracksAxis, GenCuts.impactParameterAxis}); + qaRegistry.add("EventGen/h5ResonanceTruthAnti", "EventGen/h5ResonanceTruthAnti", kTHnSparseD, {{2, 0.0f, 2.0f}, GenCuts.ptAxisGen, centAxisGen, GenCuts.multNTracksAxis, GenCuts.impactParameterAxis}); + qaRegistry.add("EventGen/hZCollisionGen", "EventGen/hZCollisionGen", kTH1D, {{100, -20.0f, 20.0f}}); + + qaRegistry.add("EventGen/h4MultCent_genMC", "EventGen/h4MultCent_genMC", kTHnSparseD, {{2, 0.0f, 2.0f}, centAxisGen, GenCuts.multNTracksAxis, GenCuts.impactParameterAxis}); + qaRegistry.add("EventGen/h4MultCent_recMC", "EventGen/h4MultCent_recMC", kTHnSparseD, {{2, 0.0f, 2.0f}, centAxisGen, GenCuts.multNTracksAxis, GenCuts.impactParameterAxis}); + qaRegistry.add("EventGen/h2CentralityVsMultMC", "EventGen/h2CentralityVsMultMC", kTH2D, {centAxisGen, GenCuts.multNTracksAxis}); + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) // Simple copy from LambdaKzeroFinder.cxx @@ -1303,7 +1436,7 @@ struct ResonanceInitializer { return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1329,7 +1462,7 @@ struct ResonanceInitializer { return; colCuts.fillQARun2(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1356,7 +1489,7 @@ struct ResonanceInitializer { return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1383,12 +1516,15 @@ struct ResonanceInitializer { return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } resoSpheroCollisions(computeSpherocity(tracks, trackSphMin, trackSphDef)); resoEvtPlCollisions(0, 0, 0, 0); + if (FilterForDerivedTables.cfgBypassNoPairV0s && (V0s.size() < 1)) { + return; + } fillTracks(collision, tracks); if (cfgFillMicroTracks) { @@ -1409,7 +1545,7 @@ struct ResonanceInitializer { return; colCuts.fillQARun2(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1424,7 +1560,7 @@ struct ResonanceInitializer { } PROCESS_SWITCH(ResonanceInitializer, processTrackV0DataRun2, "Process for data", false); - void processTrackV0CascData(ResoEvents::iterator const& collision, + void processTrackV0CascData(ResoEvents001::iterator const& collision, soa::Filtered const& tracks, ResoV0s const& V0s, ResoCascades const& Cascades, @@ -1438,13 +1574,24 @@ struct ResonanceInitializer { if (EventCuts.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) return; colCuts.fillQA(collision); + bool isRecINELgt0 = 0; + if (checkIsRecINELgt0) + isRecINELgt0 = collision.isInelGt0(); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf(), collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, isRecINELgt0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } resoSpheroCollisions(computeSpherocity(tracks, trackSphMin, trackSphDef)); resoEvtPlCollisions(0, 0, 0, 0); + if (cfgMultName.value == "FV0A") + qaRegistry.fill(HIST("Event/CentFV0A"), centEst(collision)); + if (FilterForDerivedTables.cfgBypassNoPairV0s && (V0s.size() < 1)) { + return; + } + if (FilterForDerivedTables.cfgBypassNoPairCascades && (Cascades.size() < 1)) { + return; + } fillTracks(collision, tracks); if (cfgFillMicroTracks) { fillMicroTracks(collision, tracks); @@ -1466,7 +1613,7 @@ struct ResonanceInitializer { return; colCuts.fillQARun2(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1493,7 +1640,7 @@ struct ResonanceInitializer { return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1525,7 +1672,7 @@ struct ResonanceInitializer { return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1552,7 +1699,7 @@ struct ResonanceInitializer { // auto bc = collision.bc_as(); colCuts.fillQARun2(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1582,7 +1729,7 @@ struct ResonanceInitializer { return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1591,6 +1738,9 @@ struct ResonanceInitializer { fillMCCollision(collision, mcParticles); // Loop over tracks + if (FilterForDerivedTables.cfgBypassNoPairV0s && (V0s.size() < 1)) { + return; + } fillTracks(collision, tracks); if (cfgFillMicroTracks) { fillMicroTracks(collision, tracks); @@ -1611,7 +1761,7 @@ struct ResonanceInitializer { // auto bc = collision.bc_as(); colCuts.fillQARun2(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1632,27 +1782,57 @@ struct ResonanceInitializer { } PROCESS_SWITCH(ResonanceInitializer, processTrackV0MCRun2, "Process for MC", false); - void processTrackV0CascMC(soa::Join::iterator const& collision, - aod::McCollisions const&, soa::Filtered const& tracks, + void processTrackV0CascMC(soa::Join::iterator const& collision, + soa::Join const& mcCollisions, soa::Filtered const& tracks, ResoV0sMC const& V0s, ResoCascadesMC const& Cascades, aod::McParticles const& mcParticles, aod::BCsWithTimestamps const&) { + auto bc = collision.bc_as(); /// adding timestamp to access magnetic field later initCCDB(bc); if (EventCuts.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) return; colCuts.fillQA(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centEst(collision), dBz); + float Cent = 100.5f; + + const auto mcId = collision.mcCollisionId(); + auto mcCollision = mcCollisions.iteratorAt(mcId); + float impactpar = mcCollision.impactParameter(); + float mult = -1.0f; + if (GenCuts.cfgGenMultPercentile) + Cent = mcCollision.centFT0M(); + else + Cent = centEst(collision); + if (cfgMultName.value == "FV0A") + qaRegistry.fill(HIST("Event/CentFV0A"), centEst(collision)); + + bool isRecINELgt0 = 0; + if (checkIsRecINELgt0) + isRecINELgt0 = collision.isInelGt0(); + + resoCollisions(collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf(), collision.posX(), collision.posY(), collision.posZ(), Cent, dBz, isRecINELgt0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } resoSpheroCollisions(computeSpherocity(tracks, trackSphMin, trackSphDef)); resoEvtPlCollisions(0, 0, 0, 0); - fillMCCollision(collision, mcParticles); + + if (GenCuts.cfgGenMult05) + mult = mcCollision.multMCNParticlesEta05(); + else if (GenCuts.cfgGenMult10) + mult = mcCollision.multMCNParticlesEta10(); + + fillMCCollision(collision, mcParticles, impactpar, mult); // Loop over tracks + if (FilterForDerivedTables.cfgBypassNoPairV0s && (V0s.size() < 1)) { + return; + } + if (FilterForDerivedTables.cfgBypassNoPairCascades && (Cascades.size() < 1)) { + return; + } fillTracks(collision, tracks); if (cfgFillMicroTracks) { fillMicroTracks(collision, tracks); @@ -1661,13 +1841,100 @@ struct ResonanceInitializer { fillCascades(collision, Cascades, tracks); // Loop over all MC particles - auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + auto mcParts = selectedMCParticles->sliceBy(perMcCollision, mcId); fillMCParticles(mcParts, mcParticles); } PROCESS_SWITCH(ResonanceInitializer, processTrackV0CascMC, "Process for MC", false); + // Following the discussions at the PAG meeting (https://indico.cern.ch/event/1583408/) + // we have introduced an auxiliary task that, when the resonanceInitializer.cxx is used, + // Only consider N_rec / N_gen i.e. not consider level of N_gen at least once + void processMCgen(soa::Join::iterator const& mcCollision, + aod::McParticles const& mcParticles, + const soa::SmallGroups>& collisions, + aod::BCsWithTimestamps const&) + { + auto bc = mcCollision.bc_as(); /// adding timestamp to access magnetic field later + initCCDB(bc); + + auto getCentGen = [&]() { + if (cfgMultName.value == "FT0M") { // FT0A,C results wiill be updated later when CCDB is available + return mcCollision.centFT0M(); + } + return 100.5f; + }; + auto getCentReco = [&](auto const& col) { + if (cfgMultName.value == "FT0M") { + return col.centFT0M(); + } else if (cfgMultName.value == "FT0C") { + return col.centFT0C(); + } else if (cfgMultName.value == "FT0A") { + return col.centFT0A(); + } else if (cfgMultName.value == "FV0A") { + return col.centFV0A(); + } + return 100.5f; + }; + + float cent = getCentGen(); + float IP = mcCollision.impactParameter(); + float mult = -1; + if (GenCuts.cfgGenMult05) { + mult = mcCollision.multMCNParticlesEta05(); + } else if (GenCuts.cfgGenMult10) { + mult = mcCollision.multMCNParticlesEta10(); + } + + qaRegistry.fill(HIST("EventGen/hNEventsMC"), 0.5); + + if (GenCuts.isZvtxcutGen && std::fabs(mcCollision.posZ()) > GenCuts.cutzvertexGen) { + return; + } + qaRegistry.fill(HIST("EventGen/hZCollisionGen"), mcCollision.posZ()); + qaRegistry.fill(HIST("EventGen/hNEventsMC"), 1.5); + + int evType = 0; + + qaRegistry.fill(HIST("EventGen/hNEventsMC"), 2.5); + if (GenCuts.checkIsTrueINELgt0 && mcCollision.isInelGt0()) { + evType++; + qaRegistry.fill(HIST("EventGen/hNEventsMC"), 3.5); + } + + bool atLeastOne = false; + int biggestNContribs = -1; + + float centReco = 100.5f; + for (const auto& collision : collisions) { + if (EventCuts.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) + continue; + if (!colCuts.isSelected(collision, false)) // Bug is appeared in colCuts-> double counting in event QA histo, will be fixed later + continue; + if (biggestNContribs < collision.multPVTotalContributors()) { + biggestNContribs = collision.multPVTotalContributors(); + centReco = getCentReco(collision); + } + + atLeastOne = true; + } + + if (GenCuts.cfgGenMultPercentile) { + fillMCGenParticles(mcParticles, cent, mult, IP, evType); + qaRegistry.fill(HIST("EventGen/h4MultCent_genMC"), evType, cent, mult, IP); + } else { + fillMCGenParticles(mcParticles, centReco, mult, IP, evType); + qaRegistry.fill(HIST("EventGen/h4MultCent_genMC"), evType, centReco, mult, IP); + qaRegistry.fill(HIST("EventGen/h2CentralityVsMultMC"), centReco, mult); + } + + if (atLeastOne) { + qaRegistry.fill(HIST("EventGen/h4MultCent_recMC"), evType, centReco, mult, IP); + } + } + PROCESS_SWITCH(ResonanceInitializer, processMCgen, "Process for MCGen", true); + void processTrackV0CascMCRun2(soa::Join::iterator const& collision, - aod::McCollisions const&, soa::Filtered const& tracks, + aod::McCollisions const&, ResoTracksMC const& tracks, ResoV0sMC const& V0s, ResoCascadesMC const& Cascades, aod::McParticles const& mcParticles, BCsWithRun2Info const&) @@ -1675,7 +1942,7 @@ struct ResonanceInitializer { // auto bc = collision.bc_as(); colCuts.fillQARun2(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), collision.centRun2V0M(), dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } diff --git a/PWGLF/TableProducer/Resonances/resonanceMergeDF.cxx b/PWGLF/TableProducer/Resonances/resonanceMergeDF.cxx index 50315d864cd..d5a178ed844 100644 --- a/PWGLF/TableProducer/Resonances/resonanceMergeDF.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceMergeDF.cxx @@ -63,6 +63,7 @@ using namespace o2::soa; struct ResonanceMergeDF { // SliceCache cache; Configurable nDF{"nDF", 1, "no of combination of collision"}; + Configurable isLoggingEnabled{"isLoggingEnabled", 0, "print log"}; Configurable cpidCut{"cpidCut", 0, "pid cut"}; Configurable crejtpc{"crejtpc", 0, "reject electron pion"}; Configurable crejtof{"crejtof", 0, "reject electron pion tof"}; @@ -175,7 +176,8 @@ struct ResonanceMergeDF { vecOfVecOfTuples.push_back(innerVector); innerVector.clear(); df++; - LOGF(info, "collisions: df = %i", df); + if (isLoggingEnabled) + LOGF(info, "collisions: df = %i", df); if (df < nCollisions) return; df = 0; diff --git a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx index a1ade00c627..358703eaf13 100644 --- a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx @@ -475,7 +475,7 @@ struct ResonanceModuleInitializer { bool isTriggerTVX = mccol.selection_bit(aod::evsel::kIsTriggerTVX); bool isSel8 = mccol.sel8(); bool isSelected = colCuts.isSelected(mccol); - resoMCCollisions(inVtx10, isTrueINELgt0, isTriggerTVX, isSel8, isSelected, mcCent); + resoMCCollisions(inVtx10, isTrueINELgt0, isTriggerTVX, isSel8, isSelected, mcCent, -1.0f); // QA for Trigger efficiency qaRegistry.fill(HIST("Event/hMCEventIndices"), mcCent, aod::resocollision::kINEL); @@ -546,7 +546,7 @@ struct ResonanceModuleInitializer { colCuts.fillQA(collision); centrality = centEst(collision); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centrality, dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centrality, dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -569,7 +569,7 @@ struct ResonanceModuleInitializer { colCuts.fillQARun2(collision); centrality = collision.centRun2V0M(); - resoCollisions(0, collision.posX(), collision.posY(), collision.posZ(), centrality, dBz); + resoCollisions(0, 0, 0, collision.posX(), collision.posY(), collision.posZ(), centrality, dBz, 0); if (!cfgBypassCollIndexFill) { resoCollisionColls(collision.globalIndex()); } @@ -1037,7 +1037,8 @@ struct ResonanceDaughterInitializer { v0.mLambda(), v0.mAntiLambda(), v0.mK0Short(), - v0.v0radius(), v0.x(), v0.y(), v0.z()); + v0.v0radius(), v0.x(), v0.y(), v0.z(), + v0.alpha(), v0.qtarm()); if (!cfgBypassTrackIndexFill) { resoV0V0s(v0.globalIndex()); } @@ -1123,6 +1124,8 @@ struct ResonanceDaughterInitializer { reso2mcv0s(v0mc.pdgCode(), mothers[0], motherPDGs[0], + 0, + 0, daughters[0], daughters[1], daughterPDGs[0], @@ -1133,6 +1136,8 @@ struct ResonanceDaughterInitializer { reso2mcv0s(0, mothers[0], motherPDGs[0], + 0, + 0, daughters[0], daughters[1], daughterPDGs[0], @@ -1289,6 +1294,8 @@ struct ResonanceDaughterInitializer { reso2mccascades(cascmc.pdgCode(), mothers[0], motherPDGs[0], + 0, + 0, daughters[0], daughters[1], daughterPDGs[0], @@ -1299,6 +1306,8 @@ struct ResonanceDaughterInitializer { reso2mccascades(0, mothers[0], motherPDGs[0], + 0, + 0, daughters[0], daughters[1], daughterPDGs[0], diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index 43c6331ae07..08ec72c6913 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -139,7 +139,7 @@ o2physics_add_dpl_workflow(cascademlselection o2physics_add_dpl_workflow(sigma0builder SOURCES sigma0builder.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lambdajetpolarizationbuilder @@ -147,6 +147,11 @@ o2physics_add_dpl_workflow(lambdajetpolarizationbuilder PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambdajetpolarizationions + SOURCES lambdaJetPolarizationIons.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(stracents SOURCES stracents.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -157,8 +162,8 @@ o2physics_add_dpl_workflow(lambdaspincorrelation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(sigmaprotoncorr - SOURCES sigmaProtonCorr.cxx +o2physics_add_dpl_workflow(sigmahadcorr + SOURCES sigmaHadCorr.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt index 83dfdaa3a36..8239715863d 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt @@ -124,6 +124,11 @@ o2physics_add_dpl_workflow(stracentconverter PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(stracentconverter2 + SOURCES stracentconverter2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(stramccollmultconverter SOURCES stramccollmultconverter.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.cxx new file mode 100644 index 00000000000..febbb451be9 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/Converters/stracentconverter2.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. +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; + +// Converts Stra Cents from 001 to 002 +struct stracentconverter2 { + Produces straCents_002; + + void process(aod::StraCents_001 const& straCents_001) + { + for (auto& values : straCents_001) { + straCents_002(values.centFT0M(), + values.centFT0A(), + values.centFT0C(), + values.centFV0A(), + values.centFT0CVariant1(), + -999.0 /*dummy FT0C Variant 2*/, + values.centMFT(), + values.centNGlobal(), + -999.0 /*dummy NTPV value*/); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index ac3de656a2b..d342a3effcd 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -52,6 +52,7 @@ using CollEventAndSpecPlane = soa::Join::iterator; using MCCollisionsStra = soa::Join; using V0Candidates = soa::Join; +using V0MCCandidates = soa::Join; using CascCandidates = soa::Join; using CascMCCandidates = soa::Join; @@ -92,6 +93,7 @@ const double AlphaLambda[2] = {0.747, -0.757}; // decay parameter of Lambda and std::shared_ptr hMassBeforeSelVsPt[nCharges]; std::shared_ptr hMassAfterSelVsPt[nCharges]; +std::shared_ptr hMassAfterSelVsPtTrue[nCharges]; } // namespace lambdav2 namespace cascade_flow_cuts_ml @@ -263,6 +265,8 @@ struct cascadeFlow { Configurable rapidityLambda{"rapidityLambda", 0.5, "rapidityLambda"}; Configurable etaLambda{"etaLambda", 0.8, "etaLambda"}; Configurable dauTrackV0Eta{"dauTrackV0Eta", 0.8, "dauTrackV0Eta"}; + Configurable isPositiveEta{"isPositiveEta", 0, "isPositiveEta"}; + Configurable isNegativeEta{"isNegativeEta", 0, "isNegativeEta"}; } V0Configs; Configurable sideBandStart{"sideBandStart", 5, "Start of the sideband region in number of sigmas"}; @@ -441,10 +445,6 @@ struct cascadeFlow { return false; counter++; - - // eta daughters) - // if (abs(posExtra.eta()) > V0Configs.dauTrackV0Eta || abs(negExtra.y()) > V0Configs.dauTrackV0Eta) return false; - return true; } template @@ -485,6 +485,28 @@ struct cascadeFlow { return false; if (std::abs(v0.eta()) > V0Configs.etaLambda) return false; + Float_t posDauEta = RecoDecay::eta(std::array{v0.pxpos(), v0.pypos(), v0.pzpos()}); + Float_t negDauEta = RecoDecay::eta(std::array{v0.pxneg(), v0.pyneg(), v0.pzneg()}); + if (std::abs(posDauEta) > V0Configs.dauTrackV0Eta) + return false; + if (std::abs(negDauEta) > V0Configs.dauTrackV0Eta) + return false; + if (V0Configs.isPositiveEta) { // v0 and daughter tracks required to have positive eta + if (v0.pzpos() <= 0) + return false; + if (v0.pzneg() <= 0) + return false; + if (v0.eta() <= 0) + return false; + } + if (V0Configs.isNegativeEta) { + if (v0.pzpos() >= 0) + return false; + if (v0.pzneg() >= 0) + return false; + if (v0.eta() >= 0) + return false; + } return true; } @@ -587,6 +609,7 @@ struct cascadeFlow { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry histosMCGen{"histosMCGen", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry histosMCReco{"histosMCReco", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry resolution{"resolution", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; // Tables to produce @@ -810,6 +833,7 @@ struct cascadeFlow { TString hNEventsLabels[10] = {"All", "sel8", "z vrtx", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "trackOccupancyInTimeRange", "kNoCollInTimeRange", "kNoCollInROF", "kTVXinTRD", "kIsGoodEventEP"}; TString hNEventsLabelsMC[6] = {"All", "z vtx", ">=1RecoColl", "1Reco", "2Reco", "EvSelected"}; TString hNCascLabelsMC[8] = {"All Xi", "all Omega", "Xi: has MC coll", "Om: has MC coll", "Xi: isPrimary", "Om: is Primary", "Xi: |eta|<0.8", "Om: |eta| < 0.8"}; + TString hNLambdaLabelsMC[5] = {"All Lambdas", "has MC coll", "isPrimary", "|eta|<0.8", "|y| < 0.5"}; resolution.add("QVectorsT0CTPCA", "QVectorsT0CTPCA", HistType::kTH2F, {axisQVs, CentAxisPerCent}); resolution.add("QVectorsT0CTPCC", "QVectorsT0CTPCC", HistType::kTH2F, {axisQVs, CentAxisPerCent}); @@ -906,6 +930,10 @@ struct cascadeFlow { histos.add("hv2CEPvsv2CSP", "hv2CEPvsV2CSP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); histos.add("hv1EPvsv1SP", "hV1EPvsV1SP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); histos.add("hv1SP_ZDCA_vs_ZDCC", "hv1SP_ZDCA_vs_ZDCC", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); + histos.add("hV0RapidityvsPt", "hV0RapidityvsPt", HistType::kTH2F, {{100, 0, 10}, {100, -2, 2}}); + histos.add("hEtaV0", "hEtaV0", HistType::kTH1F, {{100, -1, 1}}); + histos.add("hEtaV0posDau", "hEtaV0posDau", HistType::kTH1F, {{100, -1, 1}}); + histos.add("hEtaV0negDau", "hEtaV0negDau", HistType::kTH1F, {{100, -1, 1}}); const AxisSpec thnAxisFT0C{thnAxisConfigs.thnConfigAxisFT0C, "FT0C (%)"}; const AxisSpec thnAxisEta{thnAxisConfigs.thnConfigAxisEta, "#eta"}; @@ -927,6 +955,8 @@ struct cascadeFlow { const AxisSpec thnAxisCosThetaOmegaAlpha{thnAxisConfigs.thnConfigAxisCosThetaOmegaAlpha, "CosThetaOmegaWithAlpha"}; const AxisSpec thnAxisCosThetaProtonAlpha{thnAxisConfigs.thnConfigAxisCosThetaProtonAlpha, "CosThetaProtonWithAlpha"}; + histos.add("hCentvsPtvsPrimaryFracLambda", "hCentvsPtvsPrimaryFracLambda", HistType::kTH3F, {{100, 0, 100}, thnAxisPtLambda, {4, -0.5, 3.5}}); + histos.add("hCentvsPrimaryFracLambda", "hCentvsPrimaryFracLambda", HistType::kTH2F, {{100, 0, 100}, {4, -0.5, 3.5}}); histos.add("massXi_ProtonAcc", "massXi", HistType::kTH1F, {thnAxisMassXi}); histos.add("massOmega_ProtonAcc", "massOmega", HistType::kTH1F, {thnAxisMassOmega}); @@ -1001,8 +1031,14 @@ struct cascadeFlow { histosMCGen.add("h2DGenOmegaEta08", "h2DGenOmegaEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histosMCGen.add("h2DGenXiY05", "h2DGenXiY05", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histosMCGen.add("h2DGenOmegaY05", "h2DGenOmegaY05", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); + histosMCGen.add("h2DGenLambdaEta08", "h2DGenLambdaEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); + histosMCGen.add("h2DGenLambdaY05", "h2DGenLambdaY05", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); + histosMCGen.add("h2DGenAntiLambdaEta08", "h2DGenAntiLambdaEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); + histosMCGen.add("h2DGenAntiLambdaY05", "h2DGenAntiLambdaY05", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histosMCGen.add("hGenXiY", "hGenXiY", HistType::kTH1F, {{100, -1, 1}}); histosMCGen.add("hGenOmegaY", "hGenOmegaY", HistType::kTH1F, {{100, -1, 1}}); + histosMCGen.add("hGenLambdaY", "hGenLambdaY", HistType::kTH1F, {{100, -2, 2}}); + histosMCGen.add("hGenLambdaEta", "hGenLambdaEta", HistType::kTH1F, {{100, -2, 2}}); histosMCGen.add("hZvertexGen", "hZvertexGen", HistType::kTH1F, {{100, -20, 20}}); histosMCGen.add("hNEventsMC", "hNEventsMC", {HistType::kTH1F, {{6, 0.f, 6.f}}}); for (Int_t n = 1; n <= histosMCGen.get(HIST("hNEventsMC"))->GetNbinsX(); n++) { @@ -1012,6 +1048,13 @@ struct cascadeFlow { for (Int_t n = 1; n <= histosMCGen.get(HIST("hNCascGen"))->GetNbinsX(); n++) { histosMCGen.get(HIST("hNCascGen"))->GetXaxis()->SetBinLabel(n, hNCascLabelsMC[n - 1]); } + histosMCGen.add("hNLambdaGen", "hNLambdaGen", {HistType::kTH1F, {{5, 0.f, 5.f}}}); + for (Int_t n = 1; n <= histosMCGen.get(HIST("hNLambdaGen"))->GetNbinsX(); n++) { + histosMCGen.get(HIST("hNLambdaGen"))->GetXaxis()->SetBinLabel(n, hNLambdaLabelsMC[n - 1]); + } + + histosMCReco.add("h2DRecoTrueLambda", "h2DRecoTrueLambda", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); + histosMCReco.add("h2DRecoTrueAntiLambda", "h2DRecoTrueAntiLambda", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); for (int iS{0}; iS < nParticles; ++iS) { cascadev2::hMassBeforeSelVsPt[iS] = histos.add(Form("hMassBeforeSelVsPt%s", cascadev2::speciesNames[iS].data()), "hMassBeforeSelVsPt", HistType::kTH2F, {massCascAxis[iS], ptAxisCasc}); @@ -1025,6 +1068,7 @@ struct cascadeFlow { for (int iS{0}; iS < nCharges; ++iS) { lambdav2::hMassBeforeSelVsPt[iS] = histos.add(Form("hMassBeforeSelVsPt%s", lambdav2::speciesNames[iS].data()), "hMassBeforeSelVsPt", HistType::kTH2F, {massLambdaAxis[iS], ptAxisLambda}); lambdav2::hMassAfterSelVsPt[iS] = histos.add(Form("hMassAfterSelVsPt%s", lambdav2::speciesNames[iS].data()), "hMassAfterSelVsPt", HistType::kTH2F, {massLambdaAxis[iS], ptAxisLambda}); + lambdav2::hMassAfterSelVsPtTrue[iS] = histos.add(Form("hMassAfterSelVsPtTrue%s", lambdav2::speciesNames[iS].data()), "hMassAfterSelVsPtTrue", HistType::kTH2F, {massLambdaAxis[iS], ptAxisLambda}); } if (isApplyML) { @@ -1996,6 +2040,12 @@ struct cascadeFlow { if (!isSelectedV0[0] && !isSelectedV0[1]) continue; + histos.fill(HIST("hV0RapidityvsPt"), v0.pt(), v0.yLambda()); + histos.fill(HIST("hEtaV0"), v0.eta()); + Float_t posDauEta = RecoDecay::eta(std::array{v0.pxpos(), v0.pypos(), v0.pzpos()}); + histos.fill(HIST("hEtaV0posDau"), posDauEta); + Float_t negDauEta = RecoDecay::eta(std::array{v0.pxneg(), v0.pyneg(), v0.pzneg()}); + histos.fill(HIST("hEtaV0negDau"), negDauEta); ROOT::Math::XYZVector lambdaQvec{std::cos(2 * v0.phi()), std::sin(2 * v0.phi()), 0}; auto v2CSP = lambdaQvec.Dot(eventplaneVecT0C); // not normalised by amplitude auto lambdaminuspsiT0C = GetPhiInRange(v0.phi() - psiT0CCorr); @@ -2405,7 +2455,7 @@ struct cascadeFlow { } } - void processMCGen(MCCollisionsStra::iterator const& mcCollision, const soa::SmallGroups>& collisions, const soa::SmallGroups>& cascMC) + void processMCGen(MCCollisionsStra::iterator const& mcCollision, const soa::SmallGroups>& collisions, const soa::SmallGroups>& v0MC, const soa::SmallGroups>& cascMC) { histosMCGen.fill(HIST("hZvertexGen"), mcCollision.posZ()); @@ -2443,6 +2493,42 @@ struct cascadeFlow { histosMCGen.fill(HIST("hNEventsMC"), 5.5); + for (auto const& v0mc : v0MC) { + if (std::abs(v0mc.pdgCode()) == PDG_t::kLambda0) + histosMCGen.fill(HIST("hNLambdaGen"), 0.5); + if (!v0mc.has_straMCCollision()) + continue; + if (std::abs(v0mc.pdgCode()) == PDG_t::kLambda0) + histosMCGen.fill(HIST("hNLambdaGen"), 1.5); + if (!v0mc.isPhysicalPrimary()) + continue; + if (std::abs(v0mc.pdgCode()) == PDG_t::kLambda0) + histosMCGen.fill(HIST("hNLambdaGen"), 2.5); + + float ptmc = RecoDecay::sqrtSumOfSquares(v0mc.pxMC(), v0mc.pyMC()); + float lambdaMCeta = RecoDecay::eta(std::array{v0mc.pxMC(), v0mc.pyMC(), v0mc.pzMC()}); + float lambdaMCy = 0; + if (std::abs(v0mc.pdgCode()) == PDG_t::kLambda0) { + lambdaMCy = RecoDecay::y(std::array{v0mc.pxMC(), v0mc.pyMC(), v0mc.pzMC()}, constants::physics::MassLambda); + if (std::abs(lambdaMCeta) < etaCascMCGen) { + if (v0mc.pdgCode() == PDG_t::kLambda0) + histosMCGen.fill(HIST("h2DGenLambdaEta08"), centrality, ptmc); + else if (v0mc.pdgCode() == PDG_t::kLambda0Bar) + histosMCGen.fill(HIST("h2DGenAntiLambdaEta08"), centrality, ptmc); + histosMCGen.fill(HIST("hNLambdaGen"), 3.5); + } + if (std::abs(lambdaMCy) < yCascMCGen) { + if (v0mc.pdgCode() == PDG_t::kLambda0) + histosMCGen.fill(HIST("h2DGenLambdaY05"), centrality, ptmc); + else if (v0mc.pdgCode() == PDG_t::kLambda0Bar) + histosMCGen.fill(HIST("h2DGenAntiLambdaY05"), centrality, ptmc); + histosMCGen.fill(HIST("hNLambdaGen"), 4.5); + } + histosMCGen.fill(HIST("hGenLambdaY"), lambdaMCy); + histosMCGen.fill(HIST("hGenLambdaEta"), lambdaMCeta); + } + } + for (auto const& cascmc : cascMC) { if (std::abs(cascmc.pdgCode()) == PDG_t::kXiMinus) histosMCGen.fill(HIST("hNCascGen"), 0.5); @@ -2498,6 +2584,128 @@ struct cascadeFlow { } } + void processMCPrimaryLambdaFraction(soa::Join::iterator const& coll, V0MCCandidates const& V0s, DauTracks const&, soa::Join const&) + { + + Float_t collisionCentrality = 0; + if (isCollisionCentrality == 0) { // T0C + collisionCentrality = coll.centFT0C(); + } else if (isCollisionCentrality == 1) { // T0M + collisionCentrality = coll.centFT0M(); + } + + histos.fill(HIST("hEventCentralityBefEvSel"), collisionCentrality); + + if (!AcceptEvent(coll, 1)) { + return; + } + + // no EP requirements as in MC we do not have EP info + histos.fill(HIST("hNEvents"), 9.5); + histos.fill(HIST("hEventCentrality"), collisionCentrality); + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + + for (auto const& v0 : V0s) { + + /// Add some minimal cuts for single track variables (min number of TPC clusters) + auto negExtra = v0.negTrackExtra_as(); + auto posExtra = v0.posTrackExtra_as(); + + int counterLambda = 0; + int counterALambda = 0; + bool isLambdaCandidate = 0; + bool isALambdaCandidate = 0; + + // check if v0 has MC info + if (!v0.has_v0MCCore()) + continue; + + //-- selections ------------------------------------------------------------ + if (isLambdaAccepted(negExtra, posExtra, counterLambda)) + isLambdaCandidate = 1; + if (isAntiLambdaAccepted(negExtra, posExtra, counterALambda)) + isALambdaCandidate = 1; + histos.fill(HIST("hLambdaDauSel"), counterLambda); + histos.fill(HIST("hALambdaDauSel"), counterALambda); + + if (v0.pt() < V0Configs.MinPtV0 || v0.pt() > V0Configs.MaxPtV0) { + continue; + } + + float massV0[nCharges]{v0.mLambda(), v0.mAntiLambda()}; + lambdav2::hMassBeforeSelVsPt[0]->Fill(massV0[0], v0.pt()); + lambdav2::hMassBeforeSelVsPt[1]->Fill(massV0[1], v0.pt()); + + bool isSelectedV0[2]{false, false}; + if (isV0TopoAccepted(v0) && isLambdaCandidate) + isSelectedV0[0] = true; + if (isV0TopoAccepted(v0) && isALambdaCandidate) + isSelectedV0[1] = true; + + if (isSelectedV0[0] && !isSelectedV0[1]) { // Lambdas + histos.fill(HIST("hLambdaCandidate"), 0); + } + if (isSelectedV0[1] && !isSelectedV0[0]) { // AntiLambdas + histos.fill(HIST("hLambdaCandidate"), 1); + } + if (isSelectedV0[0] && isSelectedV0[1]) { + histos.fill(HIST("hLambdaCandidate"), 2); + if (v0.mLambda() > V0Configs.MinMassLambda && v0.mLambda() < V0Configs.MaxMassLambda && v0.mAntiLambda() > V0Configs.MinMassLambda && v0.mAntiLambda() < V0Configs.MaxMassLambda) { + histos.fill(HIST("hLambdaCandidate"), 3); + continue; // in case of ambiguity between Lambda and AntiLambda, I skip the particle; checked to be zero in range 1.105 - 1.125 + } + if (!(v0.mLambda() > V0Configs.MinMassLambda && v0.mLambda() < V0Configs.MaxMassLambda) && !(v0.mAntiLambda() > V0Configs.MinMassLambda && v0.mAntiLambda() < V0Configs.MaxMassLambda)) + histos.fill(HIST("hLambdaCandidate"), 4); // bkg candidates + } + if (!isSelectedV0[0] && !isSelectedV0[1]) + continue; + + lambdav2::hMassAfterSelVsPt[0]->Fill(massV0[0], v0.pt()); + lambdav2::hMassAfterSelVsPt[1]->Fill(massV0[1], v0.pt()); + //-------------------------------------------------------------- + + auto v0MC = v0.v0MCCore_as>(); + float ptmc = RecoDecay::sqrtSumOfSquares(v0MC.pxMC(), v0MC.pyMC()); + int pdgCode{v0MC.pdgCode()}; + // select true lambdas + bool isTrueLambda = 0; + bool isTrueALambda = 0; + if (pdgCode == PDG_t::kLambda0 && v0MC.pdgCodePositive() == PDG_t::kProton && v0MC.pdgCodeNegative() == PDG_t::kPiMinus) + isTrueLambda = 1; + else if (pdgCode == PDG_t::kLambda0Bar && v0MC.pdgCodePositive() == PDG_t::kPiPlus && v0MC.pdgCodeNegative() == PDG_t::kProtonBar) + isTrueALambda = 1; + if (!isTrueLambda && !isTrueALambda) + continue; + if (isTrueLambda) + lambdav2::hMassAfterSelVsPtTrue[0]->Fill(massV0[0], v0.pt()); + if (isTrueALambda) + lambdav2::hMassAfterSelVsPtTrue[1]->Fill(massV0[1], v0.pt()); + + bool isPrimary = v0MC.isPhysicalPrimary(); + + // histo for primary fraction + if (isTrueLambda) { + if (isPrimary) { + histos.fill(HIST("hCentvsPtvsPrimaryFracLambda"), collisionCentrality, v0.pt(), 0); + histos.fill(HIST("hCentvsPrimaryFracLambda"), collisionCentrality, 0); + histosMCReco.fill(HIST("h2DRecoTrueLambda"), collisionCentrality, ptmc); + } else { + histos.fill(HIST("hCentvsPtvsPrimaryFracLambda"), collisionCentrality, v0.pt(), 1); + histos.fill(HIST("hCentvsPrimaryFracLambda"), collisionCentrality, 1); + } + } else if (isTrueALambda) { + if (isPrimary) { + histos.fill(HIST("hCentvsPtvsPrimaryFracLambda"), collisionCentrality, v0.pt(), 2); + histos.fill(HIST("hCentvsPrimaryFracLambda"), collisionCentrality, 2); + histosMCReco.fill(HIST("h2DRecoTrueAntiLambda"), collisionCentrality, ptmc); + } else { + histos.fill(HIST("hCentvsPtvsPrimaryFracLambda"), collisionCentrality, v0.pt(), 3); + histos.fill(HIST("hCentvsPrimaryFracLambda"), collisionCentrality, 3); + } + } + } + } + PROCESS_SWITCH(cascadeFlow, processTrainingBackground, "Process to create the training dataset for the background", true); PROCESS_SWITCH(cascadeFlow, processTrainingSignal, "Process to create the training dataset for the signal", false); PROCESS_SWITCH(cascadeFlow, processAnalyseData, "Process to apply ML model to the data", false); @@ -2506,6 +2714,7 @@ struct cascadeFlow { PROCESS_SWITCH(cascadeFlow, processAnalyseLambdaEP2CentralFW, "Process to measure flow and polarization of Lambda - event plane calibration from central framework", false); PROCESS_SWITCH(cascadeFlow, processAnalyseMC, "Process to apply ML model to the MC", false); PROCESS_SWITCH(cascadeFlow, processMCGen, "Process to store MC generated particles", false); + PROCESS_SWITCH(cascadeFlow, processMCPrimaryLambdaFraction, "Process to compute primary lambda fraction", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx index e32ebd8a9db..81293bcebf2 100644 --- a/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/Strangeness/cascqaanalysis.cxx @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include using namespace o2; @@ -122,7 +124,7 @@ struct Cascqaanalysis { SliceCache cache; // Random number generator for event scaling - TRandom2* fRand = new TRandom2(); + TRandom2 fRand; // Struct to select on event type typedef struct CollisionIndexAndType { @@ -130,6 +132,41 @@ struct Cascqaanalysis { uint8_t typeFlag; } CollisionIndexAndType; + template + static int countITSHits(TTrack const& track) + { + int nHits = 0; + for (unsigned int i = 0; i < 7; ++i) { + if (track.itsClusterMap() & (1 << i)) { + ++nHits; + } + } + return nHits; + } + + template + static uint8_t buildRecoEventFlags(TCollision const& collision) + { + uint8_t evFlag = o2::aod::mycascades::EvFlags::EvINEL; + if (collision.isInelGt0()) { + evFlag |= o2::aod::mycascades::EvFlags::EvINELgt0; + } + if (collision.isInelGt1()) { + evFlag |= o2::aod::mycascades::EvFlags::EvINELgt1; + } + return evFlag; + } + + template + static std::pair computeCascadeCtau(TCascade const& casc, TCollision const& collision) + { + const float decayLength = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); + const float totalMomentum = std::hypot(casc.px(), casc.py(), casc.pz()); + const float invMomentum = 1.f / (totalMomentum + 1.e-13f); + return {o2::constants::physics::MassXiMinus * decayLength * invMomentum, + o2::constants::physics::MassOmegaMinus * decayLength * invMomentum}; + } + void init(InitContext const&) { TString hCandidateCounterLabels[4] = {"All candidates", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; @@ -210,17 +247,13 @@ struct Cascqaanalysis { auto bachelor = cascCand.template bachelor_as(); // Basic set of selections - if (cascCand.cascradius() > cascradius && - cascCand.v0radius() > v0radius && - cascCand.casccosPA(pvx, pvy, pvz) > casccospa && - cascCand.v0cosPA(pvx, pvy, pvz) > v0cospa && - std::fabs(posdau.eta()) < etadau && - std::fabs(negdau.eta()) < etadau && - std::fabs(bachelor.eta()) < etadau) { - return true; - } else { - return false; - } + return cascCand.cascradius() > cascradius && + cascCand.v0radius() > v0radius && + cascCand.casccosPA(pvx, pvy, pvz) > casccospa && + cascCand.v0cosPA(pvx, pvy, pvz) > v0cospa && + std::fabs(posdau.eta()) < etadau && + std::fabs(negdau.eta()) < etadau && + std::fabs(bachelor.eta()) < etadau; } template @@ -419,39 +452,16 @@ struct Cascqaanalysis { registry.fill(HIST("hCandidateCounter"), 1.5); // passed topo cuts nCandSel++; // Fill table - if (fRand->Rndm() < lEventScale) { + if (fRand.Rndm() < lEventScale) { auto posdau = casc.posTrack_as(); auto negdau = casc.negTrack_as(); auto bachelor = casc.bachelor_as(); - // ITS N hits - int posITSNhits = 0, negITSNhits = 0, bachITSNhits = 0; - for (unsigned int i = 0; i < 7; i++) { - if (posdau.itsClusterMap() & (1 << i)) { - posITSNhits++; - } - if (negdau.itsClusterMap() & (1 << i)) { - negITSNhits++; - } - if (bachelor.itsClusterMap() & (1 << i)) { - bachITSNhits++; - } - } - - uint8_t evFlag = 0; - evFlag |= o2::aod::mycascades::EvFlags::EvINEL; - if (collision.multNTracksPVeta1() > 0) { - evFlag |= o2::aod::mycascades::EvFlags::EvINELgt0; - } - if (collision.multNTracksPVeta1() > 1) { - evFlag |= o2::aod::mycascades::EvFlags::EvINELgt1; - } - - // c x tau - float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); - float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - float ctauXi = o2::constants::physics::MassXiMinus * cascpos / (cascptotmom + 1e-13); - float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / (cascptotmom + 1e-13); + const int posITSNhits = countITSHits(posdau); + const int negITSNhits = countITSHits(negdau); + const int bachITSNhits = countITSHits(bachelor); + const uint8_t evFlag = buildRecoEventFlags(collision); + const auto [ctauXi, ctauOmega] = computeCascadeCtau(casc, collision); mycascades(collision.posZ(), collision.centFT0M(), collision.centFV0A(), @@ -563,41 +573,17 @@ struct Cascqaanalysis { genY = cascmc.y(); } } - if (fRand->Rndm() < lEventScale) { + if (fRand.Rndm() < lEventScale) { // Fill table auto posdau = casc.posTrack_as(); auto negdau = casc.negTrack_as(); auto bachelor = casc.bachelor_as(); - // ITS N hits - int posITSNhits = 0, negITSNhits = 0, bachITSNhits = 0; - for (unsigned int i = 0; i < 7; i++) { - if (posdau.itsClusterMap() & (1 << i)) { - posITSNhits++; - } - if (negdau.itsClusterMap() & (1 << i)) { - negITSNhits++; - } - if (bachelor.itsClusterMap() & (1 << i)) { - bachITSNhits++; - } - } - - // Event type flag - uint8_t evFlag = 0; - evFlag |= o2::aod::mycascades::EvFlags::EvINEL; - if (collision.multNTracksPVeta1() > 0) { - evFlag |= o2::aod::mycascades::EvFlags::EvINELgt0; - } - if (collision.multNTracksPVeta1() > 1) { - evFlag |= o2::aod::mycascades::EvFlags::EvINELgt1; - } - - // c x tau - float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); - float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - float ctauXi = o2::constants::physics::MassXiMinus * cascpos / (cascptotmom + 1e-13); - float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / (cascptotmom + 1e-13); + const int posITSNhits = countITSHits(posdau); + const int negITSNhits = countITSHits(negdau); + const int bachITSNhits = countITSHits(bachelor); + const uint8_t evFlag = buildRecoEventFlags(collision); + const auto [ctauXi, ctauOmega] = computeCascadeCtau(casc, collision); mycascades(collision.posZ(), mcCollision.centFT0M(), 0, // mcCollision.centFV0A() to be added diff --git a/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx index 164d95d1ac6..669a69016f0 100644 --- a/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/doubleCascTreeCreator.cxx @@ -248,7 +248,22 @@ struct doubleCascTreeCreator { histos.fill(HIST("QA/massXi2"), casc2.pt(), casc2.mXi()); histos.fill(HIST("QA/massOmega2"), casc2.pt(), casc2.mOmega()); - if (casc1.posTrackId() == casc2.posTrackId() || casc1.posTrackId() == casc2.negTrackId() || casc1.bachelorId() == casc2.bachelorId()) { + // check that the cascades do not share any track + std::vector trackIdsCasc1 = {casc1.posTrackId(), casc1.negTrackId(), casc1.bachelorId()}; + std::vector trackIdsCasc2 = {casc2.posTrackId(), casc2.negTrackId(), casc2.bachelorId()}; + bool shareTrack = false; + for (auto id1 : trackIdsCasc1) { + for (auto id2 : trackIdsCasc2) { + if (id1 == id2) { + shareTrack = true; + break; + } + } + if (shareTrack) { + break; + } + } + if (shareTrack) { continue; } diff --git a/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx b/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx index b9a789e47b0..f944b37749a 100644 --- a/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx +++ b/PWGLF/TableProducer/Strangeness/hStrangeCorrelationFilter.cxx @@ -31,9 +31,9 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include #include "TF1.h" #include @@ -49,8 +49,8 @@ using namespace o2::framework::expressions; #define BIT_CHECK(var, nbit) ((var) & (1 << (nbit))) struct HStrangeCorrelationFilter { - const float ctauxiPDG = 4.91; // from PDG - const float ctauomegaPDG = 2.461; // from PDG + const float ctauxi = 4.91; // from PDG + const float ctauomega = 2.461; // from PDG Service ccdb; @@ -59,6 +59,8 @@ struct HStrangeCorrelationFilter { // master analysis switches Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; Configurable useParameterization{"useParameterization", true, "ture for parameterization method, false for hist method"}; + Configurable minPtForParam{"minPtForParam", 0.2f, "min pt for parameterization method"}; + Configurable maxPtForParam{"maxPtForParam", 14.5f, "max pt for parameterization method"}; // Operational Configurable fillTableOnlyWithCompatible{"fillTableOnlyWithCompatible", true, "pre-apply dE/dx, broad mass window in table filling"}; Configurable strangedEdxNSigmaLoose{"strangedEdxNSigmaLoose", 5, "Nsigmas for strange decay daughters"}; @@ -72,19 +74,33 @@ struct HStrangeCorrelationFilter { Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low cut on TPC occupancy"}; struct : ConfigurableGroup { + std::string prefix = "eventSelections"; // event filtering Configurable zVertexCut{"zVertexCut", 10, "Cut on PV position"}; Configurable selectINELgtZERO{"selectINELgtZERO", true, "select INEL>0 events"}; Configurable requireAllGoodITSLayers{"requireAllGoodITSLayers", false, " require that in the event all ITS are good"}; + Configurable minCentPercent{"minCentPercent", 0, "minimum centrality percentage"}; + Configurable maxCentPercent{"maxCentPercent", 100, "maximum centrality percentage"}; } eventSelections; struct : ConfigurableGroup { + std::string prefix = "generalSelections"; + + // Associated particle selections in phase space + Configurable assocEtaMin{"assocEtaMin", -0.8, "triggeretamin"}; + Configurable assocEtaMax{"assocEtaMax", 0.8, "triggeretamax"}; + Configurable assocPtCutMin{"assocPtCutMin", 0.2, "assocptmin"}; + Configurable assocPtCutMax{"assocPtCutMax", 10, "assocptmax"}; + // Trigger particle selections in phase space Configurable triggerEtaMin{"triggerEtaMin", -0.8, "triggeretamin"}; Configurable triggerEtaMax{"triggerEtaMax", 0.8, "triggeretamax"}; Configurable triggerPtCutMin{"triggerPtCutMin", 3, "triggerptmin"}; Configurable triggerPtCutMax{"triggerPtCutMax", 20, "triggerptmax"}; + } generalSelections; + struct : ConfigurableGroup { + std::string prefix = "trackSelections"; // Track quality Configurable minTPCNCrossedRows{"minTPCNCrossedRows", 70, "Minimum TPC crossed rows"}; Configurable triggerRequireITS{"triggerRequireITS", true, "require ITS signal in trigger tracks"}; @@ -92,73 +108,62 @@ struct HStrangeCorrelationFilter { Configurable triggerMaxTPCSharedClusters{"triggerMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive)"}; Configurable triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"}; - // Associated particle selections in phase space - Configurable assocEtaMin{"assocEtaMin", -0.8, "triggeretamin"}; - Configurable assocEtaMax{"assocEtaMax", 0.8, "triggeretamax"}; - Configurable assocPtCutMin{"assocPtCutMin", 0.2, "assocptmin"}; - Configurable assocPtCutMax{"assocPtCutMax", 10, "assocptmax"}; - // Associated pion identification Configurable pionMinBayesProb{"pionMinBayesProb", 0.95, "minimal Bayesian probability for pion ID"}; Configurable assocPionNSigmaTPCFOF{"assocPionNSigmaTPCFOF", 3, "minimal n sigma in TOF and TPC for Pion ID"}; Configurable rejectSigma{"rejectSigma", 1, "n sigma for rejecting pion candidates"}; + // primary particle DCAxy selections + // 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"}; + } trackSelections; + struct : ConfigurableGroup { // V0 selections + std::string prefix = "v0Selection"; 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 dcaBaryonToPV{"dcaBaryonToPV", 0.2, "DCA of baryon daughter track To PV"}; + Configurable dcaMesonToPV{"dcaMesonToPV", 0.05, "DCA of meson daughter track To PV"}; Configurable v0RadiusMin{"v0RadiusMin", 0.5, "v0radius"}; Configurable v0RadiusMax{"v0RadiusMax", 200, "v0radius"}; - // more V0 selections in PbPb + Configurable lifetimecutK0S{"lifetimecutK0S", 20, "lifetimecutK0S"}; Configurable lifetimecutLambda{"lifetimecutLambda", 30, "lifetimecutLambda"}; - Configurable dcanegtopvK0S{"dcanegtopvK0S", 0.1, "DCA Neg To PV"}; - Configurable dcapostopvK0S{"dcapostopvK0S", 0.1, "DCA Pos To PV"}; - Configurable dcanegtopvLambda{"dcanegtopvLambda", 0.05, "DCA Neg To PV"}; - Configurable dcapostopvLambda{"dcapostopvLambda", 0.2, "DCA Pos To PV"}; - Configurable dcanegtopvAntiLambda{"dcanegtopvAntiLambda", 0.2, "DCA Neg To PV"}; - Configurable dcapostopvAntiLambda{"dcapostopvAntiLambda", 0.05, "DCA Pos To PV"}; - // original equation: lArmPt*2>TMath::Abs(lArmAlpha) only for K0S Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; - // specific selections - Configurable lambdaCospa{"lambdaCospa", 0.995, "CosPA for lambda"}; // allows for tighter selection for Lambda - - // primary particle DCAxy selections - // 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"}; - - // cascade selections - Configurable cascCospa{"cascCospa", 0.95, "cascCospa"}; - Configurable cascRadius{"cascRadius", 0.5, "cascRadius"}; - Configurable dcaCascdau{"dcaCascdau", 1.0, "dcaCascdau"}; - Configurable dcaBachtopv{"dcaBachtopv", 0.1, "dcaBachtopv"}; - Configurable cascV0masswindow{"cascV0masswindow", 0.01, "cascV0masswindow"}; - Configurable cascMindcav0topv{"cascMindcav0topv", 0.01, "cascMindcav0topv"}; - } systCuts; + Configurable lambdaCospa{"lambdaCospa", 0.995, "Lambda CosPA, if needed to be stricter"}; // allows for tighter selection for Lambda + } v0Selection; struct : ConfigurableGroup { - // cascade selections in PbPb - Configurable cascDcacascdau{"cascDcacascdau", 1.0, "cascDcacascdau"}; - Configurable cascDcabachtopv{"cascDcabachtopv", 0.1, "cascDcabachtopv"}; + // cascade selections + std::string prefix = "cascSelection"; Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; - Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.05, "DCA of baryon doughter track To PV"}; - Configurable dcaMesonToPV{"dcaMesonToPV", 0.1, "DCA of meson doughter track To PV"}; Configurable dcaBachToPV{"dcaBachToPV", 0.07, "DCA Bach To PV"}; + Configurable cascDcaBaryonToPV{"cascDcaBaryonToPV", 0.2, "DCA of baryon daughter track To PV"}; + Configurable cascDcaMesonToPV{"cascDcaMesonToPV", 0.05, "DCA of meson daughter track To PV"}; Configurable cascdcaV0dau{"cascdcaV0dau", 0.5, "DCA V0 Daughters"}; Configurable dcaCacsDauPar0{"dcaCacsDauPar0", 0.8, " par for pt dep DCA cascade daughter cut, p_T < 1 GeV/c"}; Configurable dcaCacsDauPar1{"dcaCacsDauPar1", 0.5, " par for pt dep DCA cascade daughter cut, 1< p_T < 4 GeV/c"}; Configurable dcaCacsDauPar2{"dcaCacsDauPar2", 0.2, " par for pt dep DCA cascade daughter cut, p_T > 4 GeV/c"}; - Configurable cascdcaV0ToPV{"cascdcaV0ToPV", 0.06, "DCA V0 To PV"}; Configurable cascv0cospa{"cascv0cospa", 0.98, "V0 CosPA"}; Configurable cascv0RadiusMin{"cascv0RadiusMin", 2.5, "v0radius"}; Configurable proplifetime{"proplifetime", 3, "ctau/"}; Configurable lambdaMassWin{"lambdaMassWin", 0.005, "V0 Mass window limit"}; Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; Configurable rapCut{"rapCut", 0.8, "Rapidity acceptance"}; - } MorePbPbsystCuts; + Configurable cascCospa{"cascCospa", 0.95, "cascCospa"}; + Configurable cascRadius{"cascRadius", 0.5, "cascRadius"}; + Configurable dcaCascdau{"dcaCascdau", 1.0, "DCA between V0 and bachelor track"}; + Configurable dcaBachtopv{"dcaBachtopv", 0.1, "DCA bachelor track to PV"}; + Configurable cascV0masswindow{"cascV0masswindow", 0.01, "V0 Mass window"}; + Configurable cascMindcav0topv{"cascMindcav0topv", 0.01, "Minimum DCA V0 to PV"}; + // pt Range for pt dep cuts + Configurable highPtForCascDaugPtDep{"highPtForCascDaugPtDep", 4.0, "high pt range for pt dep cuts"}; + Configurable lowPtForCascDaugPtDep{"lowPtForCascDaugPtDep", 1.0, "low pt range for pt dep cuts"}; + } cascSelection; Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; Configurable parameterCCDBPath{"parameterCCDBPath", "Users/k/kcui/LHC25b4a/parameter", "Path of the mean and sigma"}; @@ -178,11 +183,11 @@ struct HStrangeCorrelationFilter { // 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) < systCuts.dcaXYconstant + systCuts.dcaXYpTdep * nabs(aod::track::signed1Pt); - Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > systCuts.dcaPostopv&& - nabs(aod::v0data::dcanegtopv) > systCuts.dcaNegtopv&& aod::v0data::dcaV0daughters < systCuts.dcaV0dau; + Filter preFilterTracks = nabs(aod::track::dcaXY) < trackSelections.dcaXYconstant + trackSelections.dcaXYpTdep * nabs(aod::track::signed1Pt); + Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > v0Selection.dcaPostopv&& + nabs(aod::v0data::dcanegtopv) > v0Selection.dcaNegtopv&& aod::v0data::dcaV0daughters < v0Selection.dcaV0dau; Filter preFilterCascade = - nabs(aod::cascdata::dcapostopv) > systCuts.dcaPostopv&& nabs(aod::cascdata::dcanegtopv) > systCuts.dcaNegtopv&& nabs(aod::cascdata::dcabachtopv) > systCuts.dcaBachtopv&& aod::cascdata::dcaV0daughters < systCuts.dcaV0dau&& aod::cascdata::dcacascdaughters < systCuts.dcaCascdau; + nabs(aod::cascdata::dcapostopv) > v0Selection.dcaPostopv&& nabs(aod::cascdata::dcanegtopv) > v0Selection.dcaNegtopv&& nabs(aod::cascdata::dcabachtopv) > cascSelection.dcaBachtopv&& aod::cascdata::dcaV0daughters < cascSelection.cascdcaV0dau&& aod::cascdata::dcacascdaughters < cascSelection.dcaCascdau; // using V0LinkedTagged = soa::Join; // using CascadesLinkedTagged = soa::Join; @@ -237,6 +242,17 @@ struct HStrangeCorrelationFilter { OutputObj zorroSummary{"zorroSummary"}; int mRunNumber; + struct TriggCandidate { + float pt; + int collisionId; + int trackId; + bool isPhysicalPrimary; + float origPt; + }; + TriggCandidate thisTrigg; + + std::vector triggerCandidates; + void init(InitContext const&) { zorroSummary.setObject(zorro.getZorroSummary()); @@ -326,7 +342,7 @@ struct HStrangeCorrelationFilter { if (std::abs(collision.posZ()) > eventSelections.zVertexCut) { return false; } - if (collision.centFT0M() > 100 || collision.centFT0M() < 0) { + if (collision.centFT0M() > eventSelections.maxCentPercent || collision.centFT0M() < eventSelections.minCentPercent) { return false; } if (!collision.isInelGt0() && eventSelections.selectINELgtZERO) { @@ -372,23 +388,23 @@ struct HStrangeCorrelationFilter { template bool isValidTrigger(TTrack track) { - if (track.eta() > systCuts.triggerEtaMax || track.eta() < systCuts.triggerEtaMin) { + if (track.eta() > generalSelections.triggerEtaMax || track.eta() < generalSelections.triggerEtaMin) { return false; } // if (track.sign()= 1 ) {continue;} - if (track.pt() > systCuts.triggerPtCutMax || track.pt() < systCuts.triggerPtCutMin) { + if (track.pt() > generalSelections.triggerPtCutMax || track.pt() < generalSelections.triggerPtCutMin) { return false; } - if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) { + if (track.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) { return false; // crossed rows } - if (!track.hasITS() && systCuts.triggerRequireITS) { + if (!track.hasITS() && trackSelections.triggerRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } - if (track.tpcNClsShared() > systCuts.triggerMaxTPCSharedClusters) { + if (track.tpcNClsShared() > trackSelections.triggerMaxTPCSharedClusters) { return false; // skip, has shared clusters } - if (!(BIT_CHECK(track.itsClusterMap(), 0)) && systCuts.triggerRequireL0) { + if (!(BIT_CHECK(track.itsClusterMap(), 0)) && trackSelections.triggerRequireL0) { return false; // skip, doesn't have cluster in ITS L0 } return true; @@ -396,16 +412,16 @@ struct HStrangeCorrelationFilter { template bool isValidAssocTrack(TTrack assoc) { - if (assoc.eta() > systCuts.assocEtaMax || assoc.eta() < systCuts.assocEtaMin) { + if (assoc.eta() > generalSelections.assocEtaMax || assoc.eta() < generalSelections.assocEtaMin) { return false; } - if (assoc.pt() > systCuts.assocPtCutMax || assoc.pt() < systCuts.assocPtCutMin) { + if (assoc.pt() > generalSelections.assocPtCutMax || assoc.pt() < generalSelections.assocPtCutMin) { return false; } - if (assoc.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) { + if (assoc.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) { return false; // crossed rows } - if (!assoc.hasITS() && systCuts.assocRequireITS) { + if (!assoc.hasITS() && trackSelections.assocRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } @@ -413,26 +429,26 @@ struct HStrangeCorrelationFilter { float nSigmaTPCTOF[8] = {-10, -10, -10, -10, -10, -10, -10, -10}; if constexpr (requires { assoc.tofSignal(); } && !requires { assoc.mcParticle(); }) { if (assoc.tofSignal() > 0) { - if (std::sqrt(assoc.tofNSigmaPi() * assoc.tofNSigmaPi() + assoc.tpcNSigmaPi() * assoc.tpcNSigmaPi()) > systCuts.assocPionNSigmaTPCFOF) + if (std::sqrt(assoc.tofNSigmaPi() * assoc.tofNSigmaPi() + assoc.tpcNSigmaPi() * assoc.tpcNSigmaPi()) > trackSelections.assocPionNSigmaTPCFOF) return false; - if (assoc.tofNSigmaPr() < systCuts.rejectSigma) + if (assoc.tofNSigmaPr() < trackSelections.rejectSigma) return false; - if (assoc.tpcNSigmaPr() < systCuts.rejectSigma) + if (assoc.tpcNSigmaPr() < trackSelections.rejectSigma) return false; - if (assoc.tofNSigmaKa() < systCuts.rejectSigma) + if (assoc.tofNSigmaKa() < trackSelections.rejectSigma) return false; - if (assoc.tpcNSigmaKa() < systCuts.rejectSigma) + if (assoc.tpcNSigmaKa() < trackSelections.rejectSigma) return false; nSigmaTPCTOF[4] = assoc.tofNSigmaPi(); nSigmaTPCTOF[5] = assoc.tofNSigmaKa(); nSigmaTPCTOF[6] = assoc.tofNSigmaPr(); nSigmaTPCTOF[7] = assoc.tofNSigmaEl(); } else { - if (assoc.tpcNSigmaPi() > systCuts.assocPionNSigmaTPCFOF) + if (assoc.tpcNSigmaPi() > trackSelections.assocPionNSigmaTPCFOF) return false; - if (assoc.tpcNSigmaPr() < systCuts.rejectSigma) + if (assoc.tpcNSigmaPr() < trackSelections.rejectSigma) return false; - if (assoc.tpcNSigmaKa() < systCuts.rejectSigma) + if (assoc.tpcNSigmaKa() < trackSelections.rejectSigma) return false; } nSigmaTPCTOF[0] = assoc.tpcNSigmaPi(); @@ -443,13 +459,13 @@ struct HStrangeCorrelationFilter { bool physicalPrimary = false; float origPt = -1; - float pdgCode = -9999; + float code = -9999; if constexpr (requires { assoc.mcParticle(); }) { if (assoc.has_mcParticle()) { auto mcParticle = assoc.mcParticle(); physicalPrimary = mcParticle.isPhysicalPrimary(); origPt = mcParticle.pt(); - pdgCode = mcParticle.pdgCode(); + code = mcParticle.pdgCode(); } } @@ -458,7 +474,7 @@ struct HStrangeCorrelationFilter { physicalPrimary, assoc.globalIndex(), origPt, - pdgCode); + code); assocPID( nSigmaTPCTOF[0], nSigmaTPCTOF[1], @@ -473,42 +489,42 @@ struct HStrangeCorrelationFilter { // cascadeselection in PbPb template - bool CascadeSelectedPbPb(TCascade casc, float pvx, float pvy, float pvz) + bool cascadeSelectedPbPb(TCascade casc, float pvx, float pvy, float pvz) { // bachBaryonCosPA - if (casc.bachBaryonCosPA() < MorePbPbsystCuts.bachBaryonCosPA) + if (casc.bachBaryonCosPA() < cascSelection.bachBaryonCosPA) return false; // bachBaryonDCAxyToPV - if (std::abs(casc.bachBaryonDCAxyToPV()) > MorePbPbsystCuts.bachBaryonDCAxyToPV) + if (std::abs(casc.bachBaryonDCAxyToPV()) > cascSelection.bachBaryonDCAxyToPV) return false; // casccosPA - if (casc.casccosPA(pvx, pvy, pvz) < systCuts.cascCospa) + if (casc.casccosPA(pvx, pvy, pvz) < cascSelection.cascCospa) return false; // dcacascdaughters - float ptDepCut = MorePbPbsystCuts.dcaCacsDauPar0; - if (casc.pt() > 1 && casc.pt() < 4) - ptDepCut = MorePbPbsystCuts.dcaCacsDauPar1; - else if (casc.pt() > 4) - ptDepCut = MorePbPbsystCuts.dcaCacsDauPar2; + float ptDepCut = cascSelection.dcaCacsDauPar0; + if (casc.pt() > cascSelection.lowPtForCascDaugPtDep && casc.pt() < cascSelection.highPtForCascDaugPtDep) + ptDepCut = cascSelection.dcaCacsDauPar1; + else if (casc.pt() > cascSelection.highPtForCascDaugPtDep) + ptDepCut = cascSelection.dcaCacsDauPar2; if (casc.dcacascdaughters() > ptDepCut) return false; // dcaV0daughters - if (casc.dcaV0daughters() > systCuts.dcaV0dau) + if (casc.dcaV0daughters() > cascSelection.cascdcaV0dau) return false; // dcav0topv - if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < MorePbPbsystCuts.cascdcaV0ToPV) + if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < cascSelection.cascMindcav0topv) return false; // cascradius - if (casc.cascradius() < systCuts.cascRadius) + if (casc.cascradius() < cascSelection.cascRadius) return false; // v0radius - if (casc.v0radius() < MorePbPbsystCuts.cascv0RadiusMin) + if (casc.v0radius() < cascSelection.cascv0RadiusMin) return false; // v0cosPA - if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < MorePbPbsystCuts.cascv0cospa) + if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < cascSelection.cascv0cospa) return false; // lambdaMassWin - if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > MorePbPbsystCuts.lambdaMassWin) + if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelection.lambdaMassWin) return false; return true; } @@ -516,20 +532,37 @@ struct HStrangeCorrelationFilter { // for real data processing void processTriggers(soa::Join::iterator const& collision, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) { + triggerCandidates.clear(); if (((doPPAnalysis && !isCollisionSelected(collision))) || (!doPPAnalysis && !isCollisionSelectedPbPb(collision))) { return; } /// _________________________________________________ /// Step 1: Populate table with trigger tracks + double leadingPt = -1.; + int leadingId = -1; for (auto const& track : tracks) { if (!isValidTrigger(track)) continue; + thisTrigg.pt = track.pt(); + thisTrigg.trackId = track.globalIndex(); + thisTrigg.collisionId = track.collisionId(); + thisTrigg.isPhysicalPrimary = false; // if you decide to check real data for primaries, you'll have a hard time + thisTrigg.origPt = 0; + triggerCandidates.push_back(thisTrigg); + if (track.pt() > leadingPt) { + leadingPt = track.pt(); + leadingId = track.globalIndex(); + } + } + for (auto const& TriggCandidate : triggerCandidates) { + bool isLeading = (leadingId == TriggCandidate.trackId); triggerTrack( - track.collisionId(), - false, // if you decide to check real data for primaries, you'll have a hard time - track.globalIndex(), - 0); + TriggCandidate.collisionId, + TriggCandidate.isPhysicalPrimary, + TriggCandidate.trackId, + TriggCandidate.origPt, + isLeading); triggerTrackExtra(1); } } @@ -537,27 +570,41 @@ struct HStrangeCorrelationFilter { // for MC processing void processTriggersMC(soa::Join::iterator const& collision, soa::Filtered const& tracks, aod::McParticles const&, aod::BCsWithTimestamps const&) { + triggerCandidates.clear(); if (((doPPAnalysis && !isCollisionSelected(collision))) || (!doPPAnalysis && !isCollisionSelectedPbPb(collision))) { return; } /// _________________________________________________ /// Step 1: Populate table with trigger tracks + double leadingPt = -1.; + int leadingId = -1; for (auto const& track : tracks) { if (!isValidTrigger(track)) continue; - bool physicalPrimary = false; - float origPt = -1; + thisTrigg.pt = track.pt(); + thisTrigg.trackId = track.globalIndex(); + thisTrigg.collisionId = track.collisionId(); if (track.has_mcParticle()) { auto mcParticle = track.mcParticle(); - physicalPrimary = mcParticle.isPhysicalPrimary(); - origPt = mcParticle.pt(); + thisTrigg.isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + thisTrigg.origPt = mcParticle.pt(); + } + triggerCandidates.push_back(thisTrigg); + if (track.pt() > leadingPt) { + leadingPt = track.pt(); + leadingId = track.globalIndex(); } + } + + for (auto const& TriggCandidate : triggerCandidates) { + bool isLeading = (leadingId == TriggCandidate.trackId); triggerTrack( - track.collisionId(), - physicalPrimary, - track.globalIndex(), - origPt); + TriggCandidate.collisionId, + TriggCandidate.isPhysicalPrimary, + TriggCandidate.trackId, + TriggCandidate.origPt, + isLeading); triggerTrackExtra(1); } } @@ -571,7 +618,7 @@ struct HStrangeCorrelationFilter { return; } // No need to correlate stuff that's in far collisions - if (std::abs(collision.posZ()) > 10.0) { + if (std::abs(collision.posZ()) > eventSelections.zVertexCut) { return; } if (zorroMask.value != "") { @@ -599,7 +646,7 @@ struct HStrangeCorrelationFilter { return; } // No need to correlate stuff that's in far collisions - if (std::abs(collision.posZ()) > 10.0) { + if (std::abs(collision.posZ()) > eventSelections.zVertexCut) { return; } if (zorroMask.value != "") { @@ -627,7 +674,7 @@ struct HStrangeCorrelationFilter { return; } // No need to correlate stuff that's in far collisions - if (std::abs(collision.posZ()) > 10.0) { + if (std::abs(collision.posZ()) > eventSelections.zVertexCut) { return; } if (zorroMask.value != "") { @@ -654,7 +701,7 @@ struct HStrangeCorrelationFilter { return; } // No need to correlate stuff that's in far collisions - if (std::abs(collision.posZ()) > 10.0) { + if (std::abs(collision.posZ()) > eventSelections.zVertexCut) { return; } if (zorroMask.value != "") { @@ -683,10 +730,10 @@ struct HStrangeCorrelationFilter { /// _________________________________________________ /// Populate table with associated V0s for (auto const& v0 : V0s) { - if (v0.v0radius() < systCuts.v0RadiusMin || v0.v0radius() > systCuts.v0RadiusMax || v0.eta() > systCuts.assocEtaMax || v0.eta() < systCuts.assocEtaMin || v0.v0cosPA() < systCuts.v0Cospa) { + if (v0.v0radius() < v0Selection.v0RadiusMin || v0.v0radius() > v0Selection.v0RadiusMax || v0.eta() > generalSelections.assocEtaMax || v0.eta() < generalSelections.assocEtaMin || v0.v0cosPA() < v0Selection.v0Cospa) { continue; } - if (v0.pt() > systCuts.assocPtCutMax || v0.pt() < systCuts.assocPtCutMin) { + if (v0.pt() > generalSelections.assocPtCutMax || v0.pt() < generalSelections.assocPtCutMin) { continue; } // check dE/dx compatibility @@ -697,76 +744,61 @@ struct HStrangeCorrelationFilter { auto posdau = v0.posTrack_as(); auto negdau = v0.negTrack_as(); - if (negdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; + bool isGoodK0Short = (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < v0Selection.lifetimecutK0S && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV && + v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha())); + bool isGoodLambda = (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaBaryonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV); + bool isGoodAntiLambda = (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaBaryonToPV); if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 0); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 1); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 2); } } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (v0.v0cosPA() > v0Selection.lambdaCospa) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 2); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 2); } } @@ -782,7 +814,7 @@ struct HStrangeCorrelationFilter { // Load parameters for sideband subtraction initParametersFromCCDB(bc); // simplified handling: calculate NSigma in mass here - if (v0.pt() < 0.2f || v0.pt() > 14.5f) { + if (v0.pt() < minPtForParam || v0.pt() > maxPtForParam) { massNSigmaK0Short = (v0.mK0Short() - hK0ShortMean->GetBinContent(hK0ShortMean->FindBin(v0.pt()))) / (hK0ShortWidth->GetBinContent(hK0ShortWidth->FindBin(v0.pt())) + 1e-6); massNSigmaLambda = (v0.mLambda() - hLambdaMean->GetBinContent(hLambdaMean->FindBin(v0.pt()))) / (hLambdaWidth->GetBinContent(hLambdaMean->FindBin(v0.pt())) + 1e-6); massNSigmaAntiLambda = (v0.mAntiLambda() - hLambdaMean->GetBinContent(hLambdaMean->FindBin(v0.pt()))) / (hLambdaWidth->GetBinContent(hLambdaMean->FindBin(v0.pt())) + 1e-6); @@ -824,10 +856,10 @@ struct HStrangeCorrelationFilter { /// Populate table with associated V0s for (auto const& v0 : V0s) { - if (v0.v0radius() < systCuts.v0RadiusMin || v0.v0radius() > systCuts.v0RadiusMax || v0.eta() > systCuts.assocEtaMax || v0.eta() < systCuts.assocEtaMin || v0.v0cosPA() < systCuts.v0Cospa) { + if (v0.v0radius() < v0Selection.v0RadiusMin || v0.v0radius() > v0Selection.v0RadiusMax || v0.eta() > generalSelections.assocEtaMax || v0.eta() < generalSelections.assocEtaMin || v0.v0cosPA() < v0Selection.v0Cospa) { continue; } - if (v0.pt() > systCuts.assocPtCutMax || v0.pt() < systCuts.assocPtCutMin) { + if (v0.pt() > generalSelections.assocPtCutMax || v0.pt() < generalSelections.assocPtCutMin) { continue; } // check dE/dx compatibility @@ -838,76 +870,62 @@ struct HStrangeCorrelationFilter { auto posdau = v0.posTrack_as(); auto negdau = v0.negTrack_as(); - if (negdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posdau.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posdau.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; + bool isGoodK0Short = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < v0Selection.lifetimecutK0S && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV && + v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha()); + bool isGoodLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaBaryonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV; + bool isGoodAntiLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar < v0Selection.lifetimecutLambda && + std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaBaryonToPV; if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 0); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 1); } } if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && - v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha()))) { + if (doPPAnalysis || isGoodK0Short) { BIT_SET(compatibleK0Short, 2); } } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (v0.v0cosPA() > v0Selection.lambdaCospa) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda)) { + + if (std::abs(posdau.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPi()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodLambda) { BIT_SET(compatibleLambda, 2); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaLoose) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 0); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 1); } } - } - if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { - if (v0.v0cosPA() > systCuts.lambdaCospa) { - if (doPPAnalysis || (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < systCuts.lifetimecutLambda && - std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda)) { + if (std::abs(posdau.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negdau.tpcNSigmaPr()) < strangedEdxNSigmaTight) { + if (doPPAnalysis || isGoodAntiLambda) { BIT_SET(compatibleAntiLambda, 2); } } @@ -924,7 +942,7 @@ struct HStrangeCorrelationFilter { // Load parameters for sideband subtraction initParametersFromCCDB(bc); // simplified handling: calculate NSigma in mass here - if (v0.pt() < 0.2f || v0.pt() > 14.5f) { + if (v0.pt() < minPtForParam || v0.pt() > maxPtForParam) { massNSigmaK0Short = (v0.mK0Short() - hK0ShortMean->GetBinContent(hK0ShortMean->FindBin(v0.pt()))) / (hK0ShortWidth->GetBinContent(hK0ShortWidth->FindBin(v0.pt())) + 1e-6); massNSigmaLambda = (v0.mLambda() - hLambdaMean->GetBinContent(hLambdaMean->FindBin(v0.pt()))) / (hLambdaWidth->GetBinContent(hLambdaMean->FindBin(v0.pt())) + 1e-6); massNSigmaAntiLambda = (v0.mAntiLambda() - hLambdaMean->GetBinContent(hLambdaMean->FindBin(v0.pt()))) / (hLambdaWidth->GetBinContent(hLambdaMean->FindBin(v0.pt())) + 1e-6); @@ -939,11 +957,11 @@ struct HStrangeCorrelationFilter { bool trueLambda = false; bool trueAntiLambda = false; v0PhysicalPrimary = v0.isPhysicalPrimary(); - if (v0.pdgCode() == 310) + if (v0.pdgCode() == PDG_t::kK0Short) trueK0Short = true; - if (v0.pdgCode() == 3122) + if (v0.pdgCode() == PDG_t::kLambda0) trueLambda = true; - if (v0.pdgCode() == -3122) + if (v0.pdgCode() == PDG_t::kLambda0Bar) trueAntiLambda = true; if (compatibleK0Short && (!doTrueSelectionInMass || (trueK0Short && v0PhysicalPrimary))) histos.fill(HIST("h3dMassK0Short"), v0.pt(), v0.mK0Short(), cent); @@ -976,31 +994,36 @@ struct HStrangeCorrelationFilter { /// _________________________________________________ /// Step 3: Populate table with associated Cascades for (auto const& casc : Cascades) { - if (casc.eta() > systCuts.assocEtaMax || casc.eta() < systCuts.assocEtaMin) { + if (casc.eta() > generalSelections.assocEtaMax || casc.eta() < generalSelections.assocEtaMin) { continue; } - if (casc.pt() > systCuts.assocPtCutMax || casc.pt() < systCuts.assocPtCutMin) { + if (casc.pt() > generalSelections.assocPtCutMax || casc.pt() < generalSelections.assocPtCutMin) { continue; } - if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0Cospa || - casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.cascCospa || - casc.cascradius() < systCuts.cascRadius || - std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.cascMindcav0topv || - std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascv0cospa || + casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascCospa || + casc.cascradius() < cascSelection.cascRadius || + std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascSelection.cascMindcav0topv || + std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelection.cascV0masswindow)) continue; auto bachTrackCast = casc.bachelor_as(); auto posTrackCast = casc.posTrack_as(); auto negTrackCast = casc.negTrack_as(); // minimum TPC crossed rows - if (bachTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (bachTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (negTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (!doPPAnalysis && !CascadeSelectedPbPb(casc, collision.posX(), collision.posY(), collision.posZ())) + if (!doPPAnalysis && !cascadeSelectedPbPb(casc, collision.posX(), collision.posY(), collision.posZ())) continue; + + bool isGoodNegCascadePbPb = std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaBaryonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaMesonToPV; + bool isGoodPosCascadePbPb = std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaMesonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaBaryonToPV; // check dE/dx compatibility int compatibleXiMinus = 0; int compatibleXiPlus = 0; @@ -1008,93 +1031,73 @@ struct HStrangeCorrelationFilter { int compatibleOmegaPlus = 0; float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxiPDG); - float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomegaPDG); + float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxi); + float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomega); + bool isGoodXiPbPb = std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascSelection.rejcomp && + ctauXi < cascSelection.proplifetime && std::abs(casc.yXi()) < cascSelection.rapCut; + bool isGoodOmegaPbPb = std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascSelection.rejcomp && + ctauOmega < cascSelection.proplifetime && std::abs(casc.yOmega()) < cascSelection.rapCut; if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 2); } } @@ -1106,7 +1109,7 @@ struct HStrangeCorrelationFilter { } else { // Load parameters for sideband subtraction initParametersFromCCDB(bc); - if (casc.pt() < 0.2f || casc.pt() > 14.5f) { + if (casc.pt() < minPtForParam || casc.pt() > maxPtForParam) { massNSigmaXi = (casc.mXi() - hXiMean->GetBinContent(hXiMean->FindBin(casc.pt()))) / (hXiWidth->GetBinContent(hXiWidth->FindBin(casc.pt())) + 1e-6); massNSigmaOmega = (casc.mOmega() - hOmegaMean->GetBinContent(hOmegaMean->FindBin(casc.pt()))) / (hOmegaWidth->GetBinContent(hOmegaWidth->FindBin(casc.pt())) + 1e-6); } else { @@ -1147,17 +1150,17 @@ struct HStrangeCorrelationFilter { /// _________________________________________________ /// Step 3: Populate table with associated Cascades for (auto const& casc : Cascades) { - if (casc.eta() > systCuts.assocEtaMax || casc.eta() < systCuts.assocEtaMin) { + if (casc.eta() > generalSelections.assocEtaMax || casc.eta() < generalSelections.assocEtaMin) { continue; } - if (casc.pt() > systCuts.assocPtCutMax || casc.pt() < systCuts.assocPtCutMin) { + if (casc.pt() > generalSelections.assocPtCutMax || casc.pt() < generalSelections.assocPtCutMin) { continue; } - if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0Cospa || - casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.cascCospa || - casc.cascradius() < systCuts.cascRadius || - std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.cascMindcav0topv || - std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (doPPAnalysis && (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascv0cospa || + casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelection.cascCospa || + casc.cascradius() < cascSelection.cascRadius || + std::abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascSelection.cascMindcav0topv || + std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelection.cascV0masswindow)) continue; auto bachTrackCast = casc.bachelor_as(); @@ -1165,15 +1168,18 @@ struct HStrangeCorrelationFilter { auto negTrackCast = casc.negTrack_as(); // minimum TPC crossed rows - if (bachTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (bachTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (posTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (posTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (negTrackCast.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRows) + if (negTrackCast.tpcNClsCrossedRows() < trackSelections.minTPCNCrossedRows) continue; - if (!doPPAnalysis && !CascadeSelectedPbPb(casc, collision.posX(), collision.posY(), collision.posZ())) + if (!doPPAnalysis && !cascadeSelectedPbPb(casc, collision.posX(), collision.posY(), collision.posZ())) continue; - + bool isGoodNegCascadePbPb = (std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaBaryonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaMesonToPV); + bool isGoodPosCascadePbPb = (std::abs(casc.dcabachtopv()) > cascSelection.dcaBachToPV && std::abs(casc.dcapostopv()) > cascSelection.cascDcaMesonToPV && + std::abs(casc.dcanegtopv()) > cascSelection.cascDcaBaryonToPV); // check dE/dx compatibility int compatibleXiMinus = 0; int compatibleXiPlus = 0; @@ -1181,93 +1187,73 @@ struct HStrangeCorrelationFilter { int compatibleOmegaPlus = 0; float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxiPDG); - float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomegaPDG); + float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxi); + float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomega); + bool iGoodXiPbPb = std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascSelection.rejcomp && + ctauXi < cascSelection.proplifetime && std::abs(casc.yXi()) < cascSelection.rapCut; + bool isGoodOmegaPbPb = std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascSelection.rejcomp && + ctauOmega < cascSelection.proplifetime && std::abs(casc.yOmega()) < cascSelection.rapCut; if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > MorePbPbsystCuts.rejcomp && - ctauXi < MorePbPbsystCuts.proplifetime && std::abs(casc.yXi()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && iGoodXiPbPb)) { BIT_SET(compatibleXiPlus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() < 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaMesonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodNegCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaMinus, 2); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaLoose && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaLoose && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaLoose && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 0); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigma && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigma && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigma && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 1); } } if (std::abs(posTrackCast.tpcNSigmaPi()) < strangedEdxNSigmaTight && std::abs(negTrackCast.tpcNSigmaPr()) < strangedEdxNSigmaTight && std::abs(bachTrackCast.tpcNSigmaKa()) < strangedEdxNSigmaTight && casc.sign() > 0) { - if (doPPAnalysis || (std::abs(casc.dcabachtopv()) > MorePbPbsystCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > MorePbPbsystCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > MorePbPbsystCuts.dcaBaryonToPV && std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > MorePbPbsystCuts.rejcomp && - ctauOmega < MorePbPbsystCuts.proplifetime && std::abs(casc.yOmega()) < MorePbPbsystCuts.rapCut)) { + if (doPPAnalysis || (isGoodPosCascadePbPb && isGoodOmegaPbPb)) { BIT_SET(compatibleOmegaPlus, 2); } } @@ -1279,7 +1265,7 @@ struct HStrangeCorrelationFilter { } else { // Load parameters for sideband subtraction initParametersFromCCDB(bc); - if (casc.pt() < 0.2f || casc.pt() > 14.5f) { + if (casc.pt() < minPtForParam || casc.pt() > maxPtForParam) { massNSigmaXi = (casc.mXi() - hXiMean->GetBinContent(hXiMean->FindBin(casc.pt()))) / (hXiWidth->GetBinContent(hXiWidth->FindBin(casc.pt())) + 1e-6); massNSigmaOmega = (casc.mOmega() - hOmegaMean->GetBinContent(hOmegaMean->FindBin(casc.pt()))) / (hOmegaWidth->GetBinContent(hOmegaWidth->FindBin(casc.pt())) + 1e-6); } else { @@ -1294,13 +1280,13 @@ struct HStrangeCorrelationFilter { bool trueOmegaMinus = false; bool trueOmegaPlus = false; cascPhysicalPrimary = casc.isPhysicalPrimary(); - if (casc.pdgCode() == 3312) + if (casc.pdgCode() == PDG_t::kXiMinus) trueXiMinus = true; - if (casc.pdgCode() == -3312) + if (casc.pdgCode() == PDG_t::kXiPlusBar) trueXiPlus = true; - if (casc.pdgCode() == 3334) + if (casc.pdgCode() == PDG_t::kOmegaMinus) trueOmegaMinus = true; - if (casc.pdgCode() == -3334) + if (casc.pdgCode() == PDG_t::kOmegaPlusBar) trueOmegaPlus = true; if (compatibleXiMinus && (!doTrueSelectionInMass || (trueXiMinus && cascPhysicalPrimary))) histos.fill(HIST("h3dMassXiMinus"), casc.pt(), casc.mXi(), cent); diff --git a/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx new file mode 100644 index 00000000000..0ed6559e140 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/lambdaJetPolarizationIons.cxx @@ -0,0 +1,2031 @@ +// 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 lambdaJetPolarizationIons.cxx +/// \brief Lambda and antiLambda polarization analysis task using raw data +/// +/// \author Cicero Domenico Muncinelli , Campinas State University +// +// Jet Polarization Ions task +// ================ +// +// This code loops over a V0Datas table and produces standard derived +// data as output. In the post-processing stage, this analysis aims +// to measure the formation of vorticity rings in HI collisions. +// +// Comments, questions, complaints, suggestions? +// Please write to: +// cicero.domenico.muncinelli@cern.ch +// + +// Standard Library +#include +#include +#include +#include +#include +#include + +// PWGLF +#include "EventSelectionParams.h" +#include "RCTSelectionFlags.h" + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/lambdaJetPolarizationIons.h" +// #include "Common/DataModel/PIDResponseTOF.h" // Maybe switch this around with LFStrangenessPIDTables? +#include "PWGLF/DataModel/LFStrangenessTables.h" // For V0TOFPIDs and NSigmas getters. Better for considering the daughters as coming from V0s instead of from PV: + +// // MC +// #include "Common/DataModel/CollisionAssociationTables.h" +// #include "Common/DataModel/McCollisionExtra.h" +// #include "PWGLF/DataModel/mcCentrality.h" + +// PWGJE +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetUtilities.h" + +// Common DataModel +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +// Common Core +#include "Common/Core/RecoDecay.h" + +// Framework +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// O2 subsystems +#include "Common/CCDB/ctpRateFetcher.h" + +#include +#include +#include + +// External libraries +#include +#include +#include +#include +#include +#include +#include + +// ROOT math +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; + +///// Aliases for joined tables +/// Collisions: +using SelCollisions = soa::Join; // Added PVMults to get MultNTracksPVeta1 as centrality estimator +/// V0s and Daughter tracks: +using V0CandidatesWithTOF = soa::Join; // Tables created by o2-analysis-lf-strangenesstofpid +using DauTracks = soa::Join; +/// Jets: +// using JetTracks = soa::Join; // Simpler tracks access, yet can't pass this and DauTracks as subscriptions simultaneously. +/// MC: +// using SimCollisions = soa::Join; +// using DauTracksMC = soa::Join; + +enum CentEstimator { + kCentFT0C = 0, + kCentFT0M, + kCentFV0A +}; + +enum JetAlgorithm { + kKt = 0, + kCambridgeAachen, + kAntiKt +}; + +enum JetRecombScheme { + kEScheme = 0, + kPtScheme = 1, + kPt2Scheme = 2, + kWTAScheme = 7 +}; + +enum JetType { + kChargedJet = 0, + kFullJet, + kPhotonJet, + kZJet +}; + +enum BkgSubtraction { + kNoSubtraction = 0, + kAreaBased, + kConstituentBased +}; + +////////////////////////////////////////////// +struct lambdajetpolarizationions { + + // struct : ProducesGroup { + // } products; + Produces tableV0s; + Produces tableJets; + Produces tableLeadParticles; + Produces tableCollisions; + + // Define histogram registries: + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // master analysis switches + Configurable analyseLambda{"analyseLambda", true, "process Lambda-like candidates"}; + Configurable analyseAntiLambda{"analyseAntiLambda", false, "process AntiLambda-like candidates"}; // Will work only with Lambdas, in a first analysis + + Configurable doPPAnalysis{"doPPAnalysis", false, "if in pp, set to true. Default is HI"}; + Configurable irSource{"irSource", "ZNChadronic", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNChadronic)"}; // Renamed David's "ZNC hadronic" to the proper code "ZNChadronic" + Configurable centralityEstimatorForQA{"centralityEstimatorForQA", kCentFT0M, "Run 3 centrality estimator (0:CentFT0C, 1:CentFT0M, 2:CentFV0A)"}; // Default is FT0M + // (Now saving all centralities at the derived data level -- Makes them all available for consumer) + // (But still using this variable for QA histograms) + + ///////////////////////////////////////////// + Configurable doEventQA{"doEventQA", false, "do event QA histograms"}; + // Configurable qaCentrality{"qaCentrality", false, "qa centrality flag: check base raw values"}; + Configurable doCompleteTopoQA{"doCompleteTopoQA", false, "do topological variables QA histograms"}; // Includes doPlainTopoQA from derivedlambdakzeroanalysis + Configurable doV0KinematicQA{"doV0KinematicQA", false, "do kinematic variables QA histograms"}; + Configurable doArmenterosQA{"doArmenterosQA", false, "do Armenteros QA histograms"}; + Configurable doTPCQA{"doTPCQA", false, "do TPC QA histograms"}; + Configurable doTOFQA{"doTOFQA", false, "do TOF QA histograms"}; + Configurable doEtaPhiQA{"doEtaPhiQA", false, "do Eta/Phi QA histograms for V0s and daughters"}; + Configurable doJetKinematicsQA{"doJetKinematicsQA", false, "do pT,Eta,Phi QA histograms for jets"}; + ///////////////////////////////////////////// + + // ///////////////////////////////////////////// + // MC block -- not implemented! (TODO) + // Configurable doMCAssociation{"doMCAssociation", true, "if MC, do MC association"}; + // Configurable doTreatPiToMuon{"doTreatPiToMuon", false, "Take pi decay into muon into account in MC"}; + // Configurable doCollisionAssociationQA{"doCollisionAssociationQA", true, "check collision association"}; + // ///////////////////////////////////////////// + + // TODO: COMPLEMENTARY ANALYSES TO STUDY SPURIOUS POLARIZATION SOURCES! + // TODO: add an event plane selection procedure to get an angle between the global polarization axis and the jet axis to uncouple polarizations? + // TODO: (related to previous comment) if we already have event plane, also estimate v_2-caused polarization. Hydro papers indicate observable is unsensitive to this spurious polarization, but this is a perfect consistency check. + // TODO: add a longitudinal polarization block of code to estimate other sources of polarization (and possibly study their differential dependence on the angle wrlt the jets and their rings)? + // TODO: add a block of code that calculates polarization from Lambda fragmentation to estimate the contamination of this third source of polarization + + // Configurable groups: + struct : ConfigurableGroup { + std::string prefix = "eventSelections"; // JSON group name + Configurable requireSel8{"requireSel8", true, "require sel8 event selection"}; + Configurable requireTriggerTVX{"requireTriggerTVX", true, "require FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level"}; // part of sel8, actually + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border (Run 3 only)"}; // part of sel8, actually + Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border (Run 3 only)"}; // part of sel8, actually + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track (Run 3 only)"}; + 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 (Run 3 only)"}; // o2::aod::evsel::kIsGoodZvtxFT0vsPV. Recommended for OO + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF (Run 3 only)"}; + Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD (Run 3 only)"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC (Run 3 only)"}; // o2::aod::evsel::kNoSameBunchPileup. Recommended for OO + Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds or mult above a certain threshold in -4 - -2 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeNarrow{"requireNoCollInTimeRangeNarrow", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds (Run 3 only)"}; + Configurable requireNoCollInROFStd{"requireNoCollInROFStd", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF with mult. above a certain threshold (Run 3 only)"}; + Configurable requireNoCollInROFStrict{"requireNoCollInROFStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF (Run 3 only)"}; + Configurable requireINEL0{"requireINEL0", true, "require INEL>0 event selection"}; // Only truly useful in pp + Configurable requireINEL1{"requireINEL1", false, "require INEL>1 event selection"}; + + Configurable maxZVtxPosition{"maxZVtxPosition", 10., "max Z vtx position"}; + + Configurable useEvtSelInDenomEff{"useEvtSelInDenomEff", false, "Consider event selections in the recoed <-> gen collision association for the denominator (or numerator) of the acc. x eff. (or signal loss)?"}; + Configurable applyZVtxSelOnMCPV{"applyZVtxSelOnMCPV", true, "Apply Z-vtx cut on the PV of the generated collision?"}; // I see no reason as to not do this by default + Configurable useFT0CbasedOccupancy{"useFT0CbasedOccupancy", false, "Use sum of FT0-C amplitudes for estimating occupancy? (if not, use track-based definition)"}; + // fast check on occupancy + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + // fast check on interaction rate + Configurable minIR{"minIR", -1, "minimum IR collisions"}; + Configurable maxIR{"maxIR", -1, "maximum IR collisions"}; + } eventSelections; + + struct : ConfigurableGroup { + std::string prefix = "v0Selections"; // JSON group name + Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + + // Selection criteria: acceptance + Configurable rapidityCut{"rapidityCut", 1.0f, "rapidity"}; + Configurable v0EtaCut{"v0EtaCut", 0.9f, "eta cut for v0"}; + Configurable daughterEtaCut{"daughterEtaCut", 0.9f, "max eta for daughters"}; // Default is 0.8. Changed to 0.9 to agree with jet selection. TODO: test the impact/biasing of this! + + // Standard 5 topological criteria -- Closed a bit more for the Lambda analysis + Configurable v0cospa{"v0cospa", 0.995, "min V0 CosPA"}; // Default is 0.97 + Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; // Default is 1.0 + // Configurable dcanegtopv{"dcanegtopv", .2, "min DCA Neg To PV (cm)"}; // Default is .05 + // Configurable dcapostopv{"dcapostopv", .05, "min DCA Pos To PV (cm)"}; // Default is .05 + // Renamed for better consistency of candidate selection (the cut is not determined by charge, but by mass and how deflected the daughter is): + Configurable dcaPionToPV{"dcaPionToPV", .2, "min DCA pion-like daughter To PV (cm)"}; // Default is .05. Suppresses pion background. + Configurable dcaProtonToPV{"dcaProtonToPV", .05, "min DCA proton-like daughter To PV (cm)"}; // Default is .05 + Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; // Default is 1.2 + Configurable v0radiusMax{"v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + Configurable lambdaLifetimeCut{"lambdaLifetimeCut", 30., "lifetime cut (c*tau) for Lambda (cm)"}; + + // invariant mass selection + Configurable compMassRejection{"compMassRejection", -1, "Competing mass rejection (GeV/#it{c}^{2})"}; // This was creating bumps in the pp analysis code's invariant mass. Turned off for now. + + // Track quality + Configurable minTPCrows{"minTPCrows", 70, "minimum TPC crossed rows"}; + Configurable minITSclusters{"minITSclusters", 3, "minimum ITS clusters"}; // Default is off + Configurable minTPCrowsOverFindableClusters{"minTPCrowsOverFindableClusters", -1, "minimum nbr of TPC crossed rows over findable clusters"}; + Configurable minTPCfoundOverFindableClusters{"minTPCfoundOverFindableClusters", -1, "minimum nbr of found over findable TPC clusters"}; + Configurable maxFractionTPCSharedClusters{"maxFractionTPCSharedClusters", 1e+09, "maximum fraction of TPC shared clusters"}; + Configurable maxITSchi2PerNcls{"maxITSchi2PerNcls", 36.0f, "maximum ITS chi2 per clusters"}; // Default is 1e+09. New values from StraInJets recommendations + Configurable maxTPCchi2PerNcls{"maxTPCchi2PerNcls", 4.0f, "maximum TPC chi2 per clusters"}; // Default is 1e+09 + 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)"}; + Configurable rejectPosITSafterburner{"rejectPosITSafterburner", false, "reject positive track formed out of afterburner ITS tracks"}; + Configurable rejectNegITSafterburner{"rejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; + Configurable requirePosITSafterburnerOnly{"requirePosITSafterburnerOnly", false, "require positive track formed out of afterburner ITS tracks"}; + Configurable requireNegITSafterburnerOnly{"requireNegITSafterburnerOnly", false, "require negative track formed out of afterburner ITS tracks"}; + Configurable rejectTPCsectorBoundary{"rejectTPCsectorBoundary", false, "reject tracks close to the TPC sector boundaries"}; + Configurable phiLowCut{"phiLowCut", "0.06/x+pi/18.0-0.06", "Low azimuth cut parametrisation"}; + Configurable phiHighCut{"phiHighCut", "0.1/x+pi/18.0+0.06", "High azimuth cut parametrisation"}; + + // PID (TPC/TOF) + Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 4, "tpcPidNsigmaCut"}; // Default is 5 + Configurable tofPidNsigmaCutLaPr{"tofPidNsigmaCutLaPr", 1e+6, "tofPidNsigmaCutLaPr"}; + Configurable tofPidNsigmaCutLaPi{"tofPidNsigmaCutLaPi", 1e+6, "tofPidNsigmaCutLaPi"}; + + // PID (TOF) + Configurable maxDeltaTimeProton{"maxDeltaTimeProton", 1e+9, "check maximum allowed time"}; + Configurable maxDeltaTimePion{"maxDeltaTimePion", 1e+9, "check maximum allowed time"}; + } v0Selections; + + // Helpers for the "isTrackFarFromTPCBoundary" function: + TF1* fPhiCutLow = new TF1("fPhiCutLow", v0Selections.phiLowCut.value.data(), 0, 100); + TF1* fPhiCutHigh = new TF1("fPhiCutHigh", v0Selections.phiHighCut.value.data(), 0, 100); + + // Run Condition Table (RCT) configurables + struct : ConfigurableGroup { + std::string prefix = "rctConfigurations"; // JSON group name + Configurable cfgRCTLabel{"cfgRCTLabel", "", "Which detector condition requirements? (CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo)"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "Include ZDC flags in the bit selection (for Pb-Pb only)"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + } rctConfigurations; + RCTFlagsChecker rctFlagsChecker{rctConfigurations.cfgRCTLabel.value}; + + // ML SELECTIONS BLOCK -- NOT IMPLEMENTED! (TODO) + + // CCDB options + struct : ConfigurableGroup { + std::string prefix = "ccdbConfigurations"; // JSON group name + Configurable ccdbUrl{"ccdbUrl", "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 mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + + // manual magnetic field: + Configurable useCustomMagField{"useCustomMagField", false, "Use custom magnetic field value"}; + Configurable customMagField{"customMagField", 5.0f, "Manually set magnetic field"}; + } ccdbConfigurations; + + // Instantiating CCDB: + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + + // Other useful variables: + ctpRateFetcher rateFetcher; + int mRunNumber; + float magField; + std::map metadata; + o2::parameters::GRPMagField* grpmag = nullptr; + + // Histogram axes configuration: + struct : ConfigurableGroup { + std::string prefix = "axisConfigurations"; // JSON group name + 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 analysis"}; + ConfigurableAxis axisPtXi{"axisPtXi", {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 feeddown from Xi"}; + ConfigurableAxis axisPtCoarse{"axisPtCoarse", {VARIABLE_WIDTH, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 7.0f, 10.0f, 15.0f}, "pt axis for QA"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {450, 1.08f, 1.15f}, ""}; // Default is {200, 1.101f, 1.131f} + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "Centrality"}; + ConfigurableAxis axisNch{"axisNch", {500, 0.0f, +5000.0f}, "Number of charged particles"}; + ConfigurableAxis axisIRBinning{"axisIRBinning", {500, 0, 50}, "Binning for the interaction rate (kHz)"}; + ConfigurableAxis axisMultFT0M{"axisMultFT0M", {500, 0.0f, +100000.0f}, "Multiplicity FT0M"}; + ConfigurableAxis axisMultFT0C{"axisMultFT0C", {500, 0.0f, +10000.0f}, "Multiplicity FT0C"}; + ConfigurableAxis axisMultFV0A{"axisMultFV0A", {500, 0.0f, +100000.0f}, "Multiplicity FV0A"}; + + ConfigurableAxis axisRawCentrality{"axisRawCentrality", {VARIABLE_WIDTH, 0.000f, 52.320f, 75.400f, 95.719f, 115.364f, 135.211f, 155.791f, 177.504f, 200.686f, 225.641f, 252.645f, 281.906f, 313.850f, 348.302f, 385.732f, 426.307f, 470.146f, 517.555f, 568.899f, 624.177f, 684.021f, 748.734f, 818.078f, 892.577f, 973.087f, 1058.789f, 1150.915f, 1249.319f, 1354.279f, 1465.979f, 1584.790f, 1710.778f, 1844.863f, 1985.746f, 2134.643f, 2291.610f, 2456.943f, 2630.653f, 2813.959f, 3006.631f, 3207.229f, 3417.641f, 3637.318f, 3865.785f, 4104.997f, 4354.938f, 4615.786f, 4885.335f, 5166.555f, 5458.021f, 5762.584f, 6077.881f, 6406.834f, 6746.435f, 7097.958f, 7462.579f, 7839.165f, 8231.629f, 8635.640f, 9052.000f, 9484.268f, 9929.111f, 10389.350f, 10862.059f, 11352.185f, 11856.823f, 12380.371f, 12920.401f, 13476.971f, 14053.087f, 14646.190f, 15258.426f, 15890.617f, 16544.433f, 17218.024f, 17913.465f, 18631.374f, 19374.983f, 20136.700f, 20927.783f, 21746.796f, 22590.880f, 23465.734f, 24372.274f, 25314.351f, 26290.488f, 27300.899f, 28347.512f, 29436.133f, 30567.840f, 31746.818f, 32982.664f, 34276.329f, 35624.859f, 37042.588f, 38546.609f, 40139.742f, 41837.980f, 43679.429f, 45892.130f, 400000.000f}, "raw centrality signal"}; // for QA + + ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "Occupancy"}; + + // topological variable QA axes + ConfigurableAxis axisDCAtoPV{"axisDCAtoPV", {20, 0.0f, 1.0f}, "DCA (cm)"}; + ConfigurableAxis axisDCAdau{"axisDCAdau", {20, 0.0f, 2.0f}, "DCA (cm)"}; + ConfigurableAxis axisPointingAngle{"axisPointingAngle", {20, 0.0f, 2.0f}, "pointing angle (rad)"}; + ConfigurableAxis axisV0Radius{"axisV0Radius", {20, 0.0f, 60.0f}, "V0 2D radius (cm)"}; + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {200, -10.0f, 10.0f}, "N sigma TPC"}; + ConfigurableAxis axisTPCsignal{"axisTPCsignal", {200, 0.0f, 200.0f}, "TPC signal"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {200, -10.0f, 10.0f}, "N sigma TOF"}; + ConfigurableAxis axisTOFdeltaT{"axisTOFdeltaT", {200, -5000.0f, 5000.0f}, "TOF Delta T (ps)"}; + ConfigurableAxis axisPhi{"axisPhi", {50, 0.0f, constants::math::TwoPI}, "Azimuth angle (rad)"}; + ConfigurableAxis axisPhiMod{"axisPhiMod", {100, 0.0f, constants::math::TwoPI / 18}, "Azimuth angle wrt TPC sector (rad.)"}; + ConfigurableAxis axisEta{"axisEta", {50, -1.0f, 1.0f}, "#eta"}; + ConfigurableAxis axisRapidity{"axisRapidity", {50, -1.0f, 1.0f}, "y"}; + ConfigurableAxis axisITSchi2{"axisITSchi2", {100, 0.0f, 100.0f}, "#chi^{2} per ITS clusters"}; + ConfigurableAxis axisTPCchi2{"axisTPCchi2", {100, 0.0f, 100.0f}, "#chi^{2} per TPC clusters"}; + ConfigurableAxis axisTPCrowsOverFindable{"axisTPCrowsOverFindable", {120, 0.0f, 1.2f}, "Fraction of TPC crossed rows over findable clusters"}; + ConfigurableAxis axisTPCfoundOverFindable{"axisTPCfoundOverFindable", {120, 0.0f, 1.2f}, "Fraction of TPC found over findable clusters"}; + ConfigurableAxis axisTPCsharedClusters{"axisTPCsharedClusters", {101, -0.005f, 1.005f}, "Fraction of TPC shared clusters"}; + + // 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"}; + + // Track quality axes + ConfigurableAxis axisTPCrows{"axisTPCrows", {160, 0.0f, 160.0f}, "N TPC rows"}; + ConfigurableAxis axisITSclus{"axisITSclus", {7, 0.0f, 7.0f}, "N ITS Clusters"}; + ConfigurableAxis axisITScluMap{"axisITScluMap", {128, -0.5f, 127.5f}, "ITS Cluster map"}; + ConfigurableAxis axisDetMap{"axisDetMap", {16, -0.5f, 15.5f}, "Detector use 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"}; + + // Jet QA axes: + ConfigurableAxis JetsPerEvent{"JetsPerEvent", {20, 0, 20}, "Jets per event"}; + + ConfigurableAxis axisLeadingParticlePt{"axisLeadingParticlePt", {200, 0.f, 200.f}, "Leading particle p_{T} (GeV/c)"}; // Simpler version! + ConfigurableAxis axisJetPt{"axisJetPt", {200, 0.f, 200.f}, "Jet p_{t} (GeV)"}; + ConfigurableAxis axisCosTheta{"axisCosTheta", {50, -1.f, 1.f}, "cos(#Delta #theta_{jet})"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {50, -constants::math::PI, constants::math::PI}, "#Delta #phi"}; + ConfigurableAxis axisDeltaEta{"axisDeltaEta", {50, -1.5f, 1.5f}, "#Delta #phi"}; // Calculated as twice the subtraction "eta_max=0.9 - R_min=0.2", with a margin + ConfigurableAxis axisDeltaR{"axisDeltaR", {50, 0, 3.5f}, "#Delta R"}; // From 0 to about the maximum Delta R possible with R = 0.2 + ConfigurableAxis axisEnergy{"axisEnergy", {200, 0.f, 200.f}, "E_{jet} (GeV) (#pi mass hypothesis)"}; // Jet energy is not that well defined here, due to track mass hypothesis being of pions! This is just to include px,py,pz in full! + } axisConfigurations; + + // Jet selection configuration: + // (TODO: create a reasonable track selection for full, photon, and Z-tagged jet tracks, including detector angular acceptance parameters for EMCal) + struct : ConfigurableGroup { + std::string prefix = "jetConfigurations"; // JSON group name + Configurable minJetPt{"minJetPt", 30.0f, "Minimum reconstructed pt of the jet (GeV/c)"}; // Something in between pp and PbPb minima. Change for bkgSubtraction true or false! + Configurable radiusJet{"radiusJet", 0.4f, "Jet resolution parameter (R)"}; // (TODO: check if the JE people don't define this as a rescaled int to not lose precision for stricter selections) + // Notice that the maximum Eta of the jet will then be 0.9 - R to keep the jet contained within the ITS+TPC barrel. + + Configurable jetAlgorithm{"jetAlgorithm", kAntiKt, "jet clustering algorithm. 0 = kT, 1 = C/A, 2 = Anti-kT"}; + Configurable jetRecombScheme{"jetRecombScheme", kEScheme, "Jet recombination scheme: 0: E_scheme, 1: pT-scheme, 2: pt2-scheme, 7: WTA_pt_scheme"}; // See PWGJE/JetFinders/jetFinder.h for more info. + Configurable bkgSubtraction{"bkgSubtraction", kNoSubtraction, "Jet background subtraction: No subtraction (false), Area (true), Constituent (TODO)"}; // Selection bool for background subtraction strategy + Configurable GhostedAreaSpecRapidity{"GhostedAreaSpecRapidity", 1.1, "Max ghost particle rapidity for jet area estimates"}; // At least 1.0 for tracks and jets within the |eta| < 0.9 window of ITS+TPC + // Using an enum for readability: + Configurable jetType{"jetType", kChargedJet, "Jet type: 0: Charged Jet, 1: Full Jet, 2: Photon-tagged, 3: Z-tagged"}; // TODO: implement full, photon and Z jets + // (TODO: check the maximum pT of jets used in my analyses! If it is way too hard, it might not be the best jet to use!) + + // (TODO: Check which of these configurables might be useful for the photon-tagged and regular analyses) + // // Configurables from JE PWG: + // Configurable jetEWSPtMin{"jetEWSPtMin", 0.0, "minimum event-wise subtracted jet pT"}; + // Configurable jetEWSPtMax{"jetEWSPtMax", 1000.0, "maximum event-wise subtracted jet pT"}; + // Configurable jetGhostArea{"jetGhostArea", 0.005, "jet ghost area"}; + // Configurable ghostRepeat{"ghostRepeat", 0, "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"}; + // // cluster level configurables + // Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + // Configurable clusterEtaMin{"clusterEtaMin", -0.71, "minimum cluster eta"}; // For ECMAL: |eta| < 0.7, phi = 1.40 - 3.26 + // Configurable clusterEtaMax{"clusterEtaMax", 0.71, "maximum cluster eta"}; // For ECMAL: |eta| < 0.7, phi = 1.40 - 3.26 + // Configurable clusterPhiMin{"clusterPhiMin", 1.39, "minimum cluster phi"}; + // Configurable clusterPhiMax{"clusterPhiMax", 3.27, "maximum cluster phi"}; + // Configurable clusterEnergyMin{"clusterEnergyMin", 0.5, "minimum cluster energy in EMCAL (GeV)"}; + // Configurable clusterTimeMin{"clusterTimeMin", -25., "minimum Cluster time (ns)"}; + // Configurable clusterTimeMax{"clusterTimeMax", 25., "maximum Cluster time (ns)"}; + // Configurable clusterRejectExotics{"clusterRejectExotics", true, "Reject exotic clusters"}; + // Configurable hadronicCorrectionType{"hadronicCorrectionType", 0, "0 = no correction, 1 = CorrectedOneTrack1, 2 = CorrectedOneTrack2, 3 = CorrectedAllTracks1, 4 = CorrectedAllTracks2"}; + // Configurable doEMCALEventSelection{"doEMCALEventSelection", true, "apply the selection to the event alias_bit for full and neutral jets"}; + // Configurable doEMCALEventSelectionChargedJets{"doEMCALEventSelectionChargedJets", false, "apply the selection to the event alias_bit for charged jets"}; + + Configurable minLeadParticlePt{"minLeadParticlePt", 2.0f, "Minimum Pt for a lead track to be considered a valid proxy for a jet"}; // For OO, about 2 or 3 should be enough (z~0.3 of jet), and for PbPb maybe 8 GeV + } jetConfigurations; + + // Creating a short map to make sure the proper FastJet enums are used (safeguard against possible updates in FastJet indices): + fastjet::JetAlgorithm mapFJAlgorithm(int algoIdx) + { + switch (algoIdx) { + case 0: + return fastjet::kt_algorithm; + case 1: + return fastjet::cambridge_algorithm; + case 2: + return fastjet::antikt_algorithm; + default: + throw std::invalid_argument("Unknown jet algorithm"); + } + } + fastjet::RecombinationScheme mapFJRecombScheme(int schemeIdx) + { + switch (schemeIdx) { + case 0: + return fastjet::E_scheme; + case 1: + return fastjet::pt_scheme; + case 2: + return fastjet::pt2_scheme; + case 7: + return fastjet::WTA_pt_scheme; + default: + throw std::invalid_argument("Unknown recombination scheme"); + } + } + + // Track analysis parameters -- A specific group that is different from the v0Selections. In jet analyses we need to control our PseudoJet candidates! + // (TODO: include minimal selection criteria for electrons, muons and photons) + // Notice you do NOT need any PID for the PseudoJet candidates! Only need is to know the 4-momentum appropriately. Thus removed nsigma checks on PID + struct : ConfigurableGroup { + std::string prefix = "pseudoJetCandidateTrackSelections"; // JSON group name + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "Minimum number of TPC crossed rows"}; + Configurable minITSnCls{"minITSnCls", -1, "Minimum number of ITS clusters"}; + Configurable maxChi2TPC{"maxChi2TPC", 5.0f, "Maximum chi2 per cluster TPC"}; // Loose cuts for pseudojet candidate selection + Configurable maxChi2ITS{"maxChi2ITS", 40.0f, "Maximum chi2 per cluster ITS"}; + Configurable etaCut{"etaCut", 0.9f, "Maximum eta absolute value"}; // (TODO: same test as the previous 0.8 eta cut) + + Configurable minCandidatePt{"minCandidatePt", 0.15f, "Minimum track pt for pseudojet candidate (GeV/c)"}; // Reduces number of pseudojet candidates from IR radiation + // (TODO: test these minimal ratios to suppress split tracks in high occupancy PbPb or OO) + // Configurable minTPCrowsOverFindableClusters{"minTPCrowsOverFindableClusters", -1, "minimum nbr of TPC crossed rows over findable clusters"}; + // Configurable minTPCfoundOverFindableClusters{"minTPCfoundOverFindableClusters", 0.8f, "minimum nbr of found over findable TPC clusters"}; + + // Jets typical cuts (suppress non-primary candidates): + Configurable doDCAcuts{"doDCAcuts", false, "Apply DCA cuts to jet candidates (biases towards primary-vertex/prompt hadron jets)"}; + Configurable maxDCAz{"maxDCAz", 3.2f, "Max DCAz to primary vertex [cm] (remove pileup influence)"}; + + // Configurable maxDCAxy{"maxDCAxy", 2.4f,"Max DCAxy to primary vertex [cm]"}; + // Using same cuts as the StrangenessInJets analysis, with a pt dependence (which may bias high pt, so use with care): + Configurable dcaxyMaxTrackPar0{"dcaxyMaxTrackPar0", 0.0105f, "Asymptotic DCA resolution at high pt [cm]"}; + Configurable dcaxyMaxTrackPar1{"dcaxyMaxTrackPar1", 0.035f, "Low pt multiple-scattering term for DCA resolution [cm*(GeV/c)^Par2]"}; + Configurable dcaxyMaxTrackPar2{"dcaxyMaxTrackPar2", 1.1f, "Exponent of pt dependence of DCA resolution"}; + } pseudoJetCandidateTrackSelections; + + JetBkgSubUtils backgroundSub; + + void init(InitContext const&) + { + // setting CCDB service + ccdb->setURL(ccdbConfigurations.ccdbUrl); + ccdb->setCaching(true); + ccdb->setFatalWhenNull(false); + + // Initialise the RCTFlagsChecker + rctFlagsChecker.init(rctConfigurations.cfgRCTLabel.value, rctConfigurations.cfgCheckZDC, rctConfigurations.cfgTreatLimitedAcceptanceAsBad); + + // Event Counters + histos.add("hEventSelection", "hEventSelection", kTH1D, {{23, -0.5f, +20.5f}}); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(6, "posZ cut"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(7, "kIsVertexITSTPC"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(8, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(9, "kIsVertexTOFmatched"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(10, "kIsVertexTRDmatched"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(11, "kNoSameBunchPileup"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(12, "kNoCollInTimeRangeStd"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(13, "kNoCollInTimeRangeStrict"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(14, "kNoCollInTimeRangeNarrow"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(15, "kNoCollInRofStd"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(16, "kNoCollInRofStrict"); + if (doPPAnalysis) { + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(17, "INEL>0"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(18, "INEL>1"); + } else { + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(17, "Below min occup."); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(18, "Above max occup."); + } + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(19, "Below min IR"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(20, "Above max IR"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(21, "RCT flags"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(22, "hasRingJet"); + histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(23, "hasRingV0"); + // (notice we lack a hasRingJet AND hasRingV0 bin because the tasks run separately on all events!) + // (this QA number can be obtained at derived data level with ease) + + histos.add("Centrality/hEventCentrality", "hEventCentrality", kTH1D, {{101, 0.0f, 101.0f}}); + histos.add("Centrality/hCentralityVsNch", "hCentralityVsNch", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisNch}); + if (doEventQA) { + histos.add("hEventSelectionVsCentrality", "hEventSelectionVsCentrality", kTH2D, {{23, -0.5f, +20.5f}, {101, 0.0f, 101.0f}}); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(1, "All collisions"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(6, "posZ cut"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(7, "kIsVertexITSTPC"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(8, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(9, "kIsVertexTOFmatched"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(10, "kIsVertexTRDmatched"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(11, "kNoSameBunchPileup"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(12, "kNoCollInTimeRangeStd"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(13, "kNoCollInTimeRangeStrict"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(14, "kNoCollInTimeRangeNarrow"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(15, "kNoCollInRofStd"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(16, "kNoCollInRofStrict"); + if (doPPAnalysis) { + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(17, "INEL>0"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(18, "INEL>1"); + } else { + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(17, "Below min occup."); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(18, "Above max occup."); + } + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(19, "Below min IR"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(20, "Above max IR"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(21, "RCT flags"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(22, "hasRingJet"); + histos.get(HIST("hEventSelectionVsCentrality"))->GetXaxis()->SetBinLabel(23, "hasRingV0"); + + // Centrality: + histos.add("Centrality/hEventCentVsMultFT0M", "hEventCentVsMultFT0M", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisMultFT0M}); + histos.add("Centrality/hEventCentVsMultFT0C", "hEventCentVsMultFT0C", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisMultFT0C}); + histos.add("Centrality/hEventCentVsMultFV0A", "hEventCentVsMultFV0A", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisMultFV0A}); + histos.add("Centrality/hEventMultFT0CvsMultFV0A", "hEventMultFT0CvsMultFV0A", kTH2D, {axisConfigurations.axisMultFT0C, axisConfigurations.axisMultFV0A}); + } + + histos.add("hEventPVz", "hEventPVz", kTH1D, {{100, -20.0f, +20.0f}}); + histos.add("hCentralityVsPVz", "hCentralityVsPVz", kTH2D, {{101, 0.0f, 101.0f}, {100, -20.0f, +20.0f}}); + + // (TODO: add MC centrality vs PVz histos) + + histos.add("hEventOccupancy", "hEventOccupancy", kTH1D, {axisConfigurations.axisOccupancy}); + histos.add("hCentralityVsOccupancy", "hCentralityVsOccupancy", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisOccupancy}); + histos.add("hInteractionRate", "hInteractionRate", kTH1D, {axisConfigurations.axisIRBinning}); + histos.add("hCentralityVsInteractionRate", "hCentralityVsInteractionRate", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisIRBinning}); + histos.add("hInteractionRateVsOccupancy", "hInteractionRateVsOccupancy", kTH2D, {axisConfigurations.axisIRBinning, axisConfigurations.axisOccupancy}); + + // for QA and test purposes + // auto hRawCentrality = histos.add("Centrality/hRawCentrality", "hRawCentrality", kTH1D, {axisConfigurations.axisRawCentrality}); + + // for (int ii = 1; ii < 101; ii++) { + // float value = 100.5f - static_cast(ii); + // hRawCentrality->SetBinContent(ii, value); + // } + + ////////////////////////////////////////////////////////////// + /// Lambda / AntiLambda V0 selection QA + ////////////////////////////////////////////////////////////// + struct CutLabel { + std::string label; + bool enabled; + }; // A method of hiding labels of selections which were not used! + std::vector v0LambdaSelectionLabels = { + {"All V0 candidates", true}, + {"V0 radius (min)", true}, + {"V0 radius (max)", true}, + {"V0 cosPA", true}, + {"DCA_{V0 daughters}", true}, + {"|y_{#Lambda}|", v0Selections.rapidityCut > 0.f}, + {"K^{0}_{S} mass rejection", v0Selections.compMassRejection >= 0.f}, + {"ITS clusters (pos)", v0Selections.minITSclusters > 0}, + {"ITS #chi^{2}/N_{cls} (pos)", v0Selections.maxITSchi2PerNcls < 1e8}, + {"Reject ITS afterburner (pos)", v0Selections.rejectPosITSafterburner}, + {"Require ITS afterburner (pos)", v0Selections.requirePosITSafterburnerOnly}, + {"ITS clusters (neg)", v0Selections.minITSclusters > 0}, + {"ITS #chi^{2}/N_{cls} (neg)", v0Selections.maxITSchi2PerNcls < 1e8}, + {"Reject ITS afterburner (neg)", v0Selections.rejectNegITSafterburner}, + {"Require ITS afterburner (neg)", v0Selections.requireNegITSafterburnerOnly}, + {"TPC crossed rows (pos)", v0Selections.minTPCrows > 0}, + {"TPC #chi^{2}/N_{cls} (pos)", v0Selections.maxTPCchi2PerNcls < 1e8}, + {"TPC rows / findable (pos)", v0Selections.minTPCrowsOverFindableClusters >= 0}, + {"TPC found / findable (pos)", v0Selections.minTPCfoundOverFindableClusters >= 0}, + {"TPC shared clusters (pos)", v0Selections.maxFractionTPCSharedClusters < 1e8}, + {"TPC sector boundary (pos)", v0Selections.rejectTPCsectorBoundary}, + {"TPC crossed rows (neg)", v0Selections.minTPCrows > 0}, + {"TPC #chi^{2}/N_{cls} (neg)", v0Selections.maxTPCchi2PerNcls < 1e8}, + {"TPC rows / findable (neg)", v0Selections.minTPCrowsOverFindableClusters >= 0}, + {"TPC found / findable (neg)", v0Selections.minTPCfoundOverFindableClusters >= 0}, + {"TPC shared clusters (neg)", v0Selections.maxFractionTPCSharedClusters < 1e8}, + {"TPC sector boundary (neg)", v0Selections.rejectTPCsectorBoundary}, + {"Require ITS-only (pos)", v0Selections.requirePosITSonly}, + {"Require ITS-only (neg)", v0Selections.requireNegITSonly}, + {"Reject TPC-only (pos)", v0Selections.skipTPConly}, + {"Reject TPC-only (neg)", v0Selections.skipTPConly}, + }; // First, the labels that are hypothesis-agnostic + // Adding the Lambda or AntiLambda hypothesis labels as needed: + auto addHypothesis = [&](bool isLambda, bool analysisEnabled) { + if (!analysisEnabled) + return; // i.e., don't add these labels if not analyzing said particle type + std::string p = isLambda ? "#Lambda: " : "#bar{#Lambda}: "; + v0LambdaSelectionLabels.insert(v0LambdaSelectionLabels.end(), {{p + "DCA_{p} to PV", true}, + {p + "DCA_{#pi} to PV", true}, + {p + "TPC PID p", v0Selections.tpcPidNsigmaCut > 0}, + {p + "TPC PID #pi", v0Selections.tpcPidNsigmaCut > 0}, + {p + "TOF #Delta t p", v0Selections.maxDeltaTimeProton < 1e+9}, + {p + "TOF #Delta t #pi", v0Selections.maxDeltaTimePion < 1e+9}, + {p + "TOF PID p", v0Selections.tofPidNsigmaCutLaPr < 1e+6}, + {p + "TOF PID #pi", v0Selections.tofPidNsigmaCutLaPi < 1e+6}, + {p + "c#tau", v0Selections.lambdaLifetimeCut > 0}}); + }; + constexpr bool Lambda = true; // Some constexpr to make it more readable (works at compile level) + constexpr bool AntiLambda = false; // "false" is just a flag for this addHypothesis function! It just means fill "AntiLambda" labels + addHypothesis(Lambda, analyseLambda); + addHypothesis(AntiLambda, analyseAntiLambda); + + auto hSelectionV0s = histos.add("GeneralQA/hSelectionV0s", "V0 #rightarrow #Lambda / #bar{#Lambda} selection flow", kTH1D, + {{static_cast(v0LambdaSelectionLabels.size()), -0.5, static_cast(v0LambdaSelectionLabels.size()) - 0.5}}); + for (size_t i = 0; i < v0LambdaSelectionLabels.size(); ++i) { + auto lbl = v0LambdaSelectionLabels[i].label; + if (!v0LambdaSelectionLabels[i].enabled) + lbl = "#color[16]{(off) " + lbl + "}"; + hSelectionV0s->GetXaxis()->SetBinLabel(i + 1, lbl.c_str()); // First non-underflow bin is bin 1 + } + //////////////////////////////////////////////// + // Jet track candidate selection flow (analogous to hSelectionV0s): + // Each label's "enabled" flag reflects whether the corresponding configurable + // makes that cut active, so disabled stages are shown in grey in the output. + std::vector jetTrackSelectionLabels = { + {"All track candidates", true}, + {"ITS clusters (min)", pseudoJetCandidateTrackSelections.minITSnCls >= 0}, + {"TPC crossed rows (min)", pseudoJetCandidateTrackSelections.minNCrossedRowsTPC > 0}, + {"TPC #chi^{2}/N_{cls} (max)", pseudoJetCandidateTrackSelections.maxChi2TPC < 1.e8f}, + {"ITS #chi^{2}/N_{cls} (max)", pseudoJetCandidateTrackSelections.maxChi2ITS < 1.e8f}, + {"p_{T} min", pseudoJetCandidateTrackSelections.minCandidatePt > 0.f}, + {"|#eta| cut", pseudoJetCandidateTrackSelections.etaCut < 1.5f}, + {"DCA_{z} to PV", pseudoJetCandidateTrackSelections.doDCAcuts.value}, + {"DCA_{xy} to PV (parametric)", pseudoJetCandidateTrackSelections.doDCAcuts.value}, + }; + auto hSelectionJetTracks = histos.add("GeneralQA/hSelectionJetTracks", "Charged pseudojet candidate selection flow", kTH1D, + {{static_cast(jetTrackSelectionLabels.size()), -0.5, static_cast(jetTrackSelectionLabels.size()) - 0.5}}); + for (size_t i = 0; i < jetTrackSelectionLabels.size(); ++i) { + auto lbl = jetTrackSelectionLabels[i].label; + if (!jetTrackSelectionLabels[i].enabled) + lbl = "#color[16]{(off) " + lbl + "}"; + hSelectionJetTracks->GetXaxis()->SetBinLabel(i + 1, lbl.c_str()); + } + //////////////////////////////////////////////// + + // Histograms versus mass: + if (analyseLambda) { + histos.add("Lambda/h2dNbrOfLambdaVsCentrality", "h2dNbrOfLambdaVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("Lambda/h3dMassLambda", "h3dMassLambda", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + // Non-UPC info + histos.add("Lambda/h3dMassLambdaHadronic", "h3dMassLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + if (doTPCQA) { + histos.add("Lambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dPosTPCsignal", "h3dPosTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dNegTPCsignal", "h3dNegTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dPosNsigmaTPCvsTrackPtot", "h3dPosNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dNegNsigmaTPCvsTrackPtot", "h3dNegNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dPosTPCsignalVsTrackPtot", "h3dPosTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dNegTPCsignalVsTrackPtot", "h3dNegTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dPosNsigmaTPCvsTrackPt", "h3dPosNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dNegNsigmaTPCvsTrackPt", "h3dNegNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("Lambda/h3dPosTPCsignalVsTrackPt", "h3dPosTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("Lambda/h3dNegTPCsignalVsTrackPt", "h3dNegTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + } + if (doTOFQA) { + histos.add("Lambda/h3dPosNsigmaTOF", "h3dPosNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dNegNsigmaTOF", "h3dNegNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dPosTOFdeltaT", "h3dPosTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dNegTOFdeltaT", "h3dNegTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dPosNsigmaTOFvsTrackPtot", "h3dPosNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dNegNsigmaTOFvsTrackPtot", "h3dNegNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dPosTOFdeltaTvsTrackPtot", "h3dPosTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dNegTOFdeltaTvsTrackPtot", "h3dNegTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dPosNsigmaTOFvsTrackPt", "h3dPosNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dNegNsigmaTOFvsTrackPt", "h3dNegNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("Lambda/h3dPosTOFdeltaTvsTrackPt", "h3dPosTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("Lambda/h3dNegTOFdeltaTvsTrackPt", "h3dNegTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + } + // (TODO: add collision association capabilities in MC) + if (doEtaPhiQA) { + histos.add("Lambda/h5dV0PhiVsEta", "h5dV0PhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("Lambda/h5dPosPhiVsEta", "h5dPosPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("Lambda/h5dNegPhiVsEta", "h5dNegPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + } + } + if (analyseAntiLambda) { + histos.add("AntiLambda/h2dNbrOfAntiLambdaVsCentrality", "h2dNbrOfAntiLambdaVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); + histos.add("AntiLambda/h3dMassAntiLambda", "h3dMassAntiLambda", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + // Non-UPC info + histos.add("AntiLambda/h3dMassAntiLambdaHadronic", "h3dMassAntiLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + if (doTPCQA) { + histos.add("AntiLambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dPosTPCsignal", "h3dPosTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dNegTPCsignal", "h3dNegTPCsignal", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dPosNsigmaTPCvsTrackPtot", "h3dPosNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dNegNsigmaTPCvsTrackPtot", "h3dNegNsigmaTPCvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dPosTPCsignalVsTrackPtot", "h3dPosTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dNegTPCsignalVsTrackPtot", "h3dNegTPCsignalVsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dPosNsigmaTPCvsTrackPt", "h3dPosNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dNegNsigmaTPCvsTrackPt", "h3dNegNsigmaTPCvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); + histos.add("AntiLambda/h3dPosTPCsignalVsTrackPt", "h3dPosTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + histos.add("AntiLambda/h3dNegTPCsignalVsTrackPt", "h3dNegTPCsignalVsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTPCsignal}); + } + if (doTOFQA) { + histos.add("AntiLambda/h3dPosNsigmaTOF", "h3dPosNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dNegNsigmaTOF", "h3dNegNsigmaTOF", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dPosTOFdeltaT", "h3dPosTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dNegTOFdeltaT", "h3dNegTOFdeltaT", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dPosNsigmaTOFvsTrackPtot", "h3dPosNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dNegNsigmaTOFvsTrackPtot", "h3dNegNsigmaTOFvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dPosTOFdeltaTvsTrackPtot", "h3dPosTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dNegTOFdeltaTvsTrackPtot", "h3dNegTOFdeltaTvsTrackPtot", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dPosNsigmaTOFvsTrackPt", "h3dPosNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dNegNsigmaTOFvsTrackPt", "h3dNegNsigmaTOFvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTOF}); + histos.add("AntiLambda/h3dPosTOFdeltaTvsTrackPt", "h3dPosTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + histos.add("AntiLambda/h3dNegTOFdeltaTvsTrackPt", "h3dNegTOFdeltaTvsTrackPt", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisTOFdeltaT}); + } + if (doEtaPhiQA) { + histos.add("AntiLambda/h5dV0PhiVsEta", "h5dV0PhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("AntiLambda/h5dPosPhiVsEta", "h5dPosPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + histos.add("AntiLambda/h5dNegPhiVsEta", "h5dNegPhiVsEta", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPhi, axisConfigurations.axisEta}); + } + } + + if (analyseLambda) { + histos.add("hMassLambda", "hMassLambda", kTH1D, {axisConfigurations.axisLambdaMass}); + histos.add("Lambda/hLambdasPerEvent", "hLambdasPerEvent", kTH1D, {{15, 0, 15}}); + } + if (analyseAntiLambda) { + histos.add("hMassAntiLambda", "hMassAntiLambda", kTH1D, {axisConfigurations.axisLambdaMass}); + histos.add("AntiLambda/hAntiLambdasPerEvent", "hAntiLambdasPerEvent", kTH1D, {{15, 0, 15}}); + } + if (analyseLambda && analyseAntiLambda) { + histos.add("hAmbiguousLambdaCandidates", "hAmbiguousLambdaCandidates", kTH1D, {{1, 0, 1}}); + histos.add("hAmbiguousPerEvent", "hAmbiguousPerEvent", kTH1D, {{15, 0, 15}}); + } + + // QA histograms if requested + if (doV0KinematicQA) { + if (analyseLambda) { + // --- Basic kinematics --- + histos.add("V0KinematicQA/Lambda/hPt", "Lambda p_{T}", kTH1D, {axisConfigurations.axisPt}); + histos.add("V0KinematicQA/Lambda/hY", "Lambda rapidity", kTH1D, {axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/Lambda/hPhi", "Lambda #varphi", kTH1D, {axisConfigurations.axisPhi}); + // --- Mass correlations --- + histos.add("V0KinematicQA/Lambda/hMassVsPt", "Lambda mass vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/Lambda/hMassVsY", "Lambda mass vs y", kTH2D, {axisConfigurations.axisRapidity, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/Lambda/hMassVsPhi", "Lambda mass vs #varphi", kTH2D, {axisConfigurations.axisPhi, axisConfigurations.axisLambdaMass}); + // --- Kinematic correlations --- + histos.add("V0KinematicQA/Lambda/hYVsPt", "Lambda y vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/Lambda/hPhiVsPt", "Lambda #varphi vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisPhi}); + } + if (analyseAntiLambda) { + // --- Basic kinematics --- + histos.add("V0KinematicQA/AntiLambda/hPt", "AntiLambda p_{T}", kTH1D, {axisConfigurations.axisPt}); + histos.add("V0KinematicQA/AntiLambda/hY", "AntiLambda rapidity", kTH1D, {axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/AntiLambda/hPhi", "AntiLambda #varphi", kTH1D, {axisConfigurations.axisPhi}); + // --- Mass correlations --- + histos.add("V0KinematicQA/AntiLambda/hMassVsPt", "AntiLambda mass vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/AntiLambda/hMassVsY", "AntiLambda mass vs y", kTH2D, {axisConfigurations.axisRapidity, axisConfigurations.axisLambdaMass}); + histos.add("V0KinematicQA/AntiLambda/hMassVsPhi", "AntiLambda mass vs #varphi", kTH2D, {axisConfigurations.axisPhi, axisConfigurations.axisLambdaMass}); + // --- Kinematic correlations --- + histos.add("V0KinematicQA/AntiLambda/hYVsPt", "AntiLambda y vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisRapidity}); + histos.add("V0KinematicQA/AntiLambda/hPhiVsPt", "AntiLambda #varphi vs p_{T}", kTH2D, {axisConfigurations.axisPt, axisConfigurations.axisPhi}); + } + } + + if (doCompleteTopoQA) { + if (analyseLambda) { + histos.add("Lambda/h4dPosDCAToPV", "h4dPosDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/h4dNegDCAToPV", "h4dNegDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/h4dDCADaughters", "h4dDCADaughters", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAdau}); + histos.add("Lambda/h4dPointingAngle", "h4dPointingAngle", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPointingAngle}); + histos.add("Lambda/h4dV0Radius", "h4dV0Radius", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisV0Radius}); + } + if (analyseAntiLambda) { + histos.add("AntiLambda/h4dPosDCAToPV", "h4dPosDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/h4dNegDCAToPV", "h4dNegDCAToPV", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/h4dDCADaughters", "h4dDCADaughters", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisDCAdau}); + histos.add("AntiLambda/h4dPointingAngle", "h4dPointingAngle", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisPointingAngle}); + histos.add("AntiLambda/h4dV0Radius", "h4dV0Radius", kTHnD, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisLambdaMass, axisConfigurations.axisV0Radius}); + } + + // For all received candidates: + histos.add("V0KinematicQA/hPosDCAToPV", "hPosDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("V0KinematicQA/hNegDCAToPV", "hNegDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("V0KinematicQA/hDCADaughters", "hDCADaughters", kTH1D, {axisConfigurations.axisDCAdau}); + histos.add("V0KinematicQA/hPointingAngle", "hPointingAngle", kTH1D, {axisConfigurations.axisPointingAngle}); + histos.add("V0KinematicQA/hV0Radius", "hV0Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos.add("V0KinematicQA/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("V0KinematicQA/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("V0KinematicQA/h2dPositivePtVsPhi", "h2dPositivePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + histos.add("V0KinematicQA/h2dNegativePtVsPhi", "h2dNegativePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + if (analyseLambda) { + histos.add("Lambda/hPosDCAToPV", "hPosDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/hNegDCAToPV", "hNegDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("Lambda/hDCADaughters", "hDCADaughters", kTH1D, {axisConfigurations.axisDCAdau}); + histos.add("Lambda/hPointingAngle", "hPointingAngle", kTH1D, {axisConfigurations.axisPointingAngle}); + histos.add("Lambda/hV0Radius", "hV0Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos.add("Lambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("Lambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("Lambda/h2dPositivePtVsPhi", "h2dPositivePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + histos.add("Lambda/h2dNegativePtVsPhi", "h2dNegativePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + } + if (analyseAntiLambda) { + histos.add("AntiLambda/hPosDCAToPV", "hPosDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/hNegDCAToPV", "hNegDCAToPV", kTH1D, {axisConfigurations.axisDCAtoPV}); + histos.add("AntiLambda/hDCADaughters", "hDCADaughters", kTH1D, {axisConfigurations.axisDCAdau}); + histos.add("AntiLambda/hPointingAngle", "hPointingAngle", kTH1D, {axisConfigurations.axisPointingAngle}); + histos.add("AntiLambda/hV0Radius", "hV0Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos.add("AntiLambda/h2dPositiveITSvsTPCpts", "h2dPositiveITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("AntiLambda/h2dNegativeITSvsTPCpts", "h2dNegativeITSvsTPCpts", kTH2D, {axisConfigurations.axisTPCrows, axisConfigurations.axisITSclus}); + histos.add("AntiLambda/h2dPositivePtVsPhi", "h2dPositivePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + histos.add("AntiLambda/h2dNegativePtVsPhi", "h2dNegativePtVsPhi", kTH2D, {axisConfigurations.axisPtCoarse, axisConfigurations.axisPhiMod}); + } + } + + // Check ambiguous candidates in AP space: + histos.add("GeneralQA/h2dArmenterosAll", "h2dArmenterosAll", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosKinematicSelected", "h2dArmenterosKinematicSelected", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelected", "h2dArmenterosFullSelected", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedLambda", "h2dArmenterosFullSelectedLambda", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedAntiLambda", "h2dArmenterosFullSelectedAntiLambda", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedNonAmbiguous", "h2dArmenterosFullSelectedNonAmbiguous", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + histos.add("GeneralQA/h2dArmenterosFullSelectedAmbiguous", "h2dArmenterosFullSelectedAmbiguous", kTH2D, {axisConfigurations.axisAPAlpha, axisConfigurations.axisAPQt}); + + // Jets histograms: + // Histogram that needs to be present even out of QA: + histos.add("hEventsWithJet", "hEventsWithJet", kTH1D, {{1, 0, 1}}); + histos.add("hJetsPerEvent", "hJetsPerEvent", kTH1D, {axisConfigurations.JetsPerEvent}); + // counter of events with jet (could be interesting to compare with the minimum pT cut or between the background subtraction vs no background subtraction cases) + // number of jets per event + if (doJetKinematicsQA) { + histos.add("JetKinematicsQA/hJetPt", "hJetPt", kTH1D, {axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/hJetEta", "hJetEta", kTH1D, {axisConfigurations.axisEta}); + histos.add("JetKinematicsQA/hJetPhi", "hJetPhi", kTH1D, {axisConfigurations.axisPhi}); + + histos.add("JetKinematicsQA/hCosThetaToLeadingJet", "hCosThetaToLeadingJet", kTH1D, {axisConfigurations.axisCosTheta}); + histos.add("JetKinematicsQA/hDeltaPhiToLeadingJet", "hDeltaPhiToLeadingJet", kTH1D, {axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/hDeltaEtaToLeadingJet", "hDeltaEtaToLeadingJet", kTH1D, {axisConfigurations.axisDeltaEta}); + histos.add("JetKinematicsQA/hDeltaRToLeadingJet", "hDeltaRToLeadingJet", kTH1D, {axisConfigurations.axisDeltaR}); + + histos.add("JetKinematicsQA/hLeadingJetPt", "hLeadingJetPt", kTH1D, {axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/hLeadingJetEta", "hLeadingJetEta", kTH1D, {axisConfigurations.axisEta}); + histos.add("JetKinematicsQA/hLeadingJetPhi", "hLeadingJetPhi", kTH1D, {axisConfigurations.axisPhi}); + + // 2D correlations: + histos.add("JetKinematicsQA/h2dJetsPerEventvsLeadJetPt", "h2dJetsPerEventvsLeadJetPt", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/h2dJetsPerEventvsJetPt", "h2dJetsPerEventvsJetPt", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisJetPt}); + histos.add("JetKinematicsQA/h2dCosThetaToLeadvsDeltaPhiToLead", "h2dCosThetaToLeadvsDeltaPhiToLead", kTH2D, {axisConfigurations.axisCosTheta, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dCosThetaToLeadvsDeltaEtaToLead", "h2dCosThetaToLeadvsDeltaEtaToLead", kTH2D, {axisConfigurations.axisCosTheta, axisConfigurations.axisDeltaEta}); + histos.add("JetKinematicsQA/h2dCosThetaToLeadvsDeltaRToLead", "h2dCosThetaToLeadvsDeltaRToLead", kTH2D, {axisConfigurations.axisCosTheta, axisConfigurations.axisDeltaR}); + histos.add("JetKinematicsQA/h2dDeltaPhiToLeadvsDeltaEtaToLead", "h2dDeltaPhiToLeadvsDeltaEtaToLead", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisDeltaEta}); // to see existence of back-to-back jets, and in which window + + // Comparisons to jet energy: + histos.add("JetKinematicsQA/h2dJetPtvsDeltaPhiToLead", "h2dJetPtvsDeltaPhiToLead", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dJetEnergyvsDeltaPhiToLead", "h2dJetEnergyvsDeltaPhiToLead", kTH2D, {axisConfigurations.axisEnergy, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dJetEnergyvsCosThetaToLead", "h2dJetEnergyvsCosThetaToLead", kTH2D, {axisConfigurations.axisEnergy, axisConfigurations.axisCosTheta}); + + // Jets per event vs correlation to lead jet + histos.add("JetKinematicsQA/h2dJetsPerEventvsDeltaPhiToLead", "h2dJetsPerEventvsDeltaPhiToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaPhi}); + histos.add("JetKinematicsQA/h2dJetsPerEventvsDeltaEtaToLead", "h2dJetsPerEventvsDeltaEtaToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaEta}); + histos.add("JetKinematicsQA/h2dJetsPerEventvsCosThetaToLead", "h2dJetsPerEventvsCosThetaToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisCosTheta}); + + //////////////////////////// + // Leading particle 1D QA: + histos.add("JetVsLeadingParticleQA/hLeadingParticlePt", "hLeadingParticlePt", kTH1D, {axisConfigurations.axisLeadingParticlePt}); + histos.add("JetVsLeadingParticleQA/hLeadingParticleEta", "hLeadingParticleEta", kTH1D, {axisConfigurations.axisEta}); + histos.add("JetVsLeadingParticleQA/hLeadingParticlePhi", "hLeadingParticlePhi", kTH1D, {axisConfigurations.axisPhi}); + + // 1D correlations to lead jet: + histos.add("JetVsLeadingParticleQA/hCosThetaLeadParticleToJet", "hCosThetaLeadParticleToJet", kTH1D, {axisConfigurations.axisCosTheta}); + histos.add("JetVsLeadingParticleQA/hDeltaPhiLeadParticleToJet", "hDeltaPhiLeadParticleToJet", kTH1D, {axisConfigurations.axisDeltaPhi}); + histos.add("JetVsLeadingParticleQA/hDeltaEtaToLeadParticleToJet", "hDeltaEtaToLeadParticleToJet", kTH1D, {axisConfigurations.axisDeltaEta}); + + // Leading particle correlations: + histos.add("JetVsLeadingParticleQA/h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead", "h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisDeltaEta}); + + // Jets-per-event vs particle-to-lead correlations: + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaPhiParticleToLead", "h2dJetsPerEventvsDeltaPhiParticleToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaPhi}); + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaEtaParticleToLead", "h2dJetsPerEventvsDeltaEtaParticleToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisDeltaEta}); + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsCosThetaParticleToLead", "h2dJetsPerEventvsCosThetaParticleToLead", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisCosTheta}); + + // Main "Leading jet vs leading particle" correlations: + histos.add("JetVsLeadingParticleQA/h2dJetsPerEventvsLeadParticlePt", "h2dJetsPerEventvsLeadParticlePt", kTH2D, {axisConfigurations.JetsPerEvent, axisConfigurations.axisLeadingParticlePt}); + histos.add("JetVsLeadingParticleQA/h2dLeadJetPtvsLeadParticlePt", "h2dLeadJetPtvsLeadParticlePt", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisLeadingParticlePt}); + histos.add("JetVsLeadingParticleQA/h2dLeadJetPtvsCosThetaParticleToLead", "h2dLeadJetPtvsCosThetaParticleToLead", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisCosTheta}); + histos.add("JetVsLeadingParticleQA/h2dLeadParticlePtvsCosThetaParticleToLead", "h2dLeadParticlePtvsCosThetaParticleToLead", kTH2D, {axisConfigurations.axisLeadingParticlePt, axisConfigurations.axisCosTheta}); + histos.add("JetVsLeadingParticleQA/h2dLeadJetPtvsDeltaPhiParticleToLead", "h2dLeadJetPtvsDeltaPhiParticleToLead", kTH2D, {axisConfigurations.axisJetPt, axisConfigurations.axisDeltaPhi}); + histos.add("JetVsLeadingParticleQA/h2dLeadParticlePtvsDeltaPhiParticleToLead", "h2dLeadParticlePtvsDeltaPhiParticleToLead", kTH2D, {axisConfigurations.axisLeadingParticlePt, axisConfigurations.axisDeltaPhi}); + } + + // inspect histogram sizes, please + histos.print(); + } + + template + auto getCentrality(TCollision const& collision) + { + if (centralityEstimatorForQA == kCentFT0M) + return collision.centFT0M(); + else if (centralityEstimatorForQA == kCentFT0C) + return collision.centFT0C(); + else if (centralityEstimatorForQA == kCentFV0A) + return collision.centFV0A(); + return -1.f; + } + + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + mRunNumber = bc.runNumber(); + + // Fetching magnetic field as requested + // In case override, don't proceed, please - no CCDB access required + if (ccdbConfigurations.useCustomMagField) { + magField = ccdbConfigurations.customMagField; + } else { + grpmag = ccdb->getForRun(ccdbConfigurations.grpmagPath, mRunNumber); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField and " << ccdbConfigurations.grpPath << " of object GRPObject for run " << mRunNumber; + } + // Fetch magnetic field from ccdb for current bc + magField = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for run " << mRunNumber << " with magnetic field of " << magField << " kZG"; + } + } + + // Minimal helper to fill the hSelectionV0s histogram without having to deal with bins by myself + // (CAUTION! If you change selection order, change this too!) + struct V0SelectionFlowCounter { // Using struct to keep internal bin counter over different functions + int binValue = -1; // Starts at x=-1, which will go to bin 0 (underflow) in the definition of hSelectionV0s + // Made it like this because we use ++binValue when filling, so the first filled + // bin will always be x=0 due to operator precedence. + HistogramRegistry* histos = nullptr; // Had to pass the histos group to this struct, as it was not visible to the members of this struct + + void resetForNewV0() { binValue = -1; } + // Advance to targetBinX, filling all intermediate bins. + // Use this for DISABLED cuts within a single hypothesis + // (shows pass-through count as a flat line, making it visually + // clear that the stage was not active). + // (Replaces N dummy fill() calls) + void fillUpTo(int targetBinX) + { + while (binValue < targetBinX) + histos->fill(HIST("GeneralQA/hSelectionV0s"), ++binValue); + } + + void advanceTo(int targetBinX) { binValue = targetBinX - 1; } // next fill() lands at targetBin. Needed to deal with early exits at isLambda vs isAntiLambda checks + void fill() { histos->fill(HIST("GeneralQA/hSelectionV0s"), ++binValue); } // Hardcoded hSelectionV0s histogram, as it will not change. Increments before filling, by default + }; + V0SelectionFlowCounter V0SelCounter{-1, &histos}; // Could initialize with any index (resetForNewV0 is always called for a new V0 anyways) + // Calculating some bins, for convenience: + int nGenericCuts = 31; // x=0 to x=30 + int nHypoCuts = 9; // per hypothesis (x=31..39 for Lambda) + int lambdaHypoEnd = nGenericCuts + nHypoCuts - 1; // x=39 + + // Minimal helper to fill hSelectionJetTracks, mirroring V0SelectionFlowCounter. + // Reset once per track candidate, fill once per passed cut stage. + struct JetTrackSelectionFlowCounter { + int binValue = -1; // Same convention as V0: starts at -1, first fill goes to bin x=0 + HistogramRegistry* histos = nullptr; + void resetForNewTrack() { binValue = -1; } + void fill() { histos->fill(HIST("GeneralQA/hSelectionJetTracks"), ++binValue); } + }; + JetTrackSelectionFlowCounter JetTrackSelCounter{-1, &histos}; + + // Short inlined helper to simplify QA + inline void fillEventSelectionQA(int bin, float centrality) + { + histos.fill(HIST("hEventSelection"), bin); + histos.fill(HIST("hEventSelectionVsCentrality"), bin, centrality); + } + + // Fill reconstructed event centrality information + // Based off fillReconstructedEventProperties, but optimized to avoid re-accessing information already present on isEventAccepted! + template + void fillCentralityProperties(TCollision const& collision, float centrality) + { + // if (qaCentrality) { + // auto hRawCentrality = histos.get(HIST("Centrality/hRawCentrality")); + // centrality = hRawCentrality->GetBinContent(hRawCentrality->FindBin(doPPAnalysis ? collision.multFT0A() + collision.multFT0C() : collision.multFT0C())); + // } + histos.fill(HIST("Centrality/hEventCentrality"), centrality); + histos.fill(HIST("Centrality/hCentralityVsNch"), centrality, collision.multNTracksPVeta1()); + if (doEventQA) { + histos.fill(HIST("Centrality/hEventCentVsMultFT0M"), collision.centFT0M(), collision.multFT0A() + collision.multFT0C()); + histos.fill(HIST("Centrality/hEventCentVsMultFT0C"), collision.centFT0C(), collision.multFT0C()); + histos.fill(HIST("Centrality/hEventCentVsMultFV0A"), collision.centFV0A(), collision.multFV0A()); + histos.fill(HIST("Centrality/hEventMultFT0CvsMultFV0A"), collision.multFT0C(), collision.multFV0A()); + } + return; + } + + ///////////////////////////////////////////// + // Computation helper functions: + double computePhiMod(double phi, int sign) + // Compute phi wrt to a TPC sector + // Calculation taken from CF: https://github.com/AliceO2Group/O2Physics/blob/376392cb87349886a300c75fa2492b50b7f46725/PWGCF/Flow/Tasks/flowAnalysisGF.cxx#L470 + { + if (magField < 0) // for negative polarity field + phi = o2::constants::math::TwoPI - phi; + if (sign < 0) // for negative charge + phi = o2::constants::math::TwoPI - phi; + if (phi < 0) + LOGF(warning, "phi < 0: %g", phi); + + phi += o2::constants::math::PI / 18.0; // to center gap in the middle + return fmod(phi, o2::constants::math::PI / 9.0); + } + + bool isTrackFarFromTPCBoundary(double trackPt, double trackPhi, int sign) + // check whether the track passes close to a TPC sector boundary + { + double phiModn = computePhiMod(trackPhi, sign); + if (phiModn > fPhiCutHigh->Eval(trackPt)) + return true; // keep track + if (phiModn < fPhiCutLow->Eval(trackPt)) + return true; // keep track + + return false; // reject track + } + + inline float cosThetaJets(const fastjet::PseudoJet& a, const fastjet::PseudoJet& b) + { + const double dot = a.px() * b.px() + a.py() * b.py() + a.pz() * b.pz(); + const double magA = std::sqrt(a.px() * a.px() + a.py() * a.py() + a.pz() * a.pz()); + const double magB = std::sqrt(b.px() * b.px() + b.py() * b.py() + b.pz() * b.pz()); + return dot / (magA * magB); + } + + ///////////////////////////////////////////// + // Helper functions for event and candidate selection: + template + bool isEventAccepted(TCollision const& collision, TBC const& bc, float centrality, bool fillHists) + { // check whether the collision passes our collision selections + int selectionIdx = 0; // To loop over QA histograms. First bin is already filled: first call will already increment this index (not actually the bin index, but a value in the X axis). + if (eventSelections.requireSel8 && !collision.sel8()) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + const float collisionPVz = collision.posZ(); + if (std::abs(collisionPVz) > eventSelections.maxZVtxPosition) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + if (eventSelections.requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInROFStd && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireNoCollInROFStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + if (doPPAnalysis) { // we are in pp + if constexpr (requires { collision.multNTracksPVeta1(); }) { + // Only considers compiling this block when the collision type actually + // has multNTracksPVeta1(). This is done to reduce collision-table + // subscriptions in the jet processing function. + // This is a compile-time check: since the function is templated, it + // is instantiated separately for Jets and V0s, and this block will be + // properly compiled for each use case and table subscription automatically! + if (eventSelections.requireINEL0 && collision.multNTracksPVeta1() < 1) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.requireINEL1 && collision.multNTracksPVeta1() < 2) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + } + } else { // Performing selections as if in Pb-Pb: + const float collisionOccupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); + if (eventSelections.minOccupancy >= 0 && collisionOccupancy < eventSelections.minOccupancy) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.maxOccupancy >= 0 && collisionOccupancy > eventSelections.maxOccupancy) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + // Fetch interaction rate only if required (in order to limit ccdb calls) + const double interactionRate = (eventSelections.minIR >= 0 || eventSelections.maxIR >= 0) ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3 : -1; + if (eventSelections.minIR >= 0 && interactionRate < eventSelections.minIR) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (eventSelections.maxIR >= 0 && interactionRate > eventSelections.maxIR) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + if (!rctConfigurations.cfgRCTLabel.value.empty() && !rctFlagsChecker(collision)) + return false; + if (fillHists) + fillEventSelectionQA(++selectionIdx, centrality); + + // Filling histograms previously filled in fillReconstructedEventProperties here, to avoid re-accessing data: + if (fillHists) { + histos.fill(HIST("hEventOccupancy"), collisionOccupancy); + histos.fill(HIST("hCentralityVsOccupancy"), centrality, collisionOccupancy); + histos.fill(HIST("hInteractionRate"), interactionRate); + histos.fill(HIST("hCentralityVsInteractionRate"), centrality, interactionRate); + histos.fill(HIST("hInteractionRateVsOccupancy"), interactionRate, collisionOccupancy); + } + } + + if (fillHists) { + histos.fill(HIST("hCentralityVsPVz"), centrality, collisionPVz); + histos.fill(HIST("hEventPVz"), collisionPVz); + } + return true; + } + + template + bool isCandidateForChargedPseudojetAccepted(JetCandidate const& track) + { // (TODO: add an equivalent for photon jets and Z jets, which don't consider charged particles) + // if (track.sign() == 0) return false; // Tracks are always either positive or negative, at least in TPC and ITS, which are the ones used (not looking at photon-jets right now) + // ITS/TPC cuts: + if (pseudoJetCandidateTrackSelections.minITSnCls >= 0) { + if (track.itsNCls() < pseudoJetCandidateTrackSelections.minITSnCls) + return false; + } + JetTrackSelCounter.fill(); // bin: ITS clusters (min) + + if (track.tpcNClsCrossedRows() < pseudoJetCandidateTrackSelections.minNCrossedRowsTPC) + return false; + JetTrackSelCounter.fill(); + + if (track.tpcChi2NCl() > pseudoJetCandidateTrackSelections.maxChi2TPC) + return false; + JetTrackSelCounter.fill(); + if (track.itsChi2NCl() > pseudoJetCandidateTrackSelections.maxChi2ITS) + return false; + JetTrackSelCounter.fill(); + + // Kinematics: + const float pt = track.pt(); + if (pt < pseudoJetCandidateTrackSelections.minCandidatePt) + return false; + JetTrackSelCounter.fill(); + if (std::fabs(track.eta()) > pseudoJetCandidateTrackSelections.etaCut) + return false; + JetTrackSelCounter.fill(); + + // DCA pseudojet candidate selections -- These select primary vertex particles for the jet: + if (pseudoJetCandidateTrackSelections.doDCAcuts) { + // if (std::fabs(track.dcaXY()) > pseudoJetCandidateTrackSelections.maxDCAxy) return false; + if (std::fabs(track.dcaZ()) > pseudoJetCandidateTrackSelections.maxDCAz) + return false; + JetTrackSelCounter.fill(); + // Slightly more physics-motivated cut (parametrizes the DCA resolution as function of pt) + if (std::fabs(track.dcaXY()) > (pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar0 + + pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar1 / std::pow(pt, pseudoJetCandidateTrackSelections.dcaxyMaxTrackPar2))) + return false; + JetTrackSelCounter.fill(); + } else { // Should fill counters an equal number of times to advance indices (future-proofing, but could do it by just advancing indices by hand in JetTrackSelectionFlowCounter) + JetTrackSelCounter.fill(); + JetTrackSelCounter.fill(); + } + return true; + } + + // Lambda selections: + template + bool passesGenericV0Cuts(TV0 const& v0) + { + // Base topological variables (high rejection, low cost checks) + if (v0.v0radius() < v0Selections.v0radius) + return false; + V0SelCounter.fill(); + if (v0.v0radius() > v0Selections.v0radiusMax) + return false; + V0SelCounter.fill(); + if (v0.v0cosPA() < v0Selections.v0cospa) + return false; + V0SelCounter.fill(); + if (v0.dcaV0daughters() > v0Selections.dcav0dau) + return false; + V0SelCounter.fill(); + + // pseudorapidity cuts: + if (std::fabs(v0.yLambda()) > v0Selections.rapidityCut) + return false; + // if (std::fabs(v0.eta()) > v0Selections.v0EtaCut) return false; + V0SelCounter.fill(); + // if (std::fabs(v0.eta()) > v0Selections.daughterEtaCut) return false; // (TODO: properly consider this in daughter selection!) + + // competing mass rejection (if compMassRejection < 0, this cut does nothing) + if (std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0Selections.compMassRejection) + return false; + V0SelCounter.fill(); + + const auto posTrackExtra = v0.template posTrack_as(); // (TODO: is it worth it to cache these transformations outside of the function? They are reused in the Lambda hypothesis checks) + const auto negTrackExtra = v0.template negTrack_as(); + + // ITS quality cuts + bool posIsFromAfterburner = posTrackExtra.isITSAfterburner(); + bool negIsFromAfterburner = negTrackExtra.isITSAfterburner(); + + // check minimum number of ITS clusters + maximum ITS chi2 per clusters + reject or select ITS afterburner tracks if requested + if (posTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; // check minimum ITS clusters + V0SelCounter.fill(); + if (posTrackExtra.itsChi2NCl() >= v0Selections.maxITSchi2PerNcls) + return false; // check maximum ITS chi2 per clusters + V0SelCounter.fill(); + if (v0Selections.rejectPosITSafterburner && posIsFromAfterburner) + return false; // reject afterburner track or not + V0SelCounter.fill(); + if (v0Selections.requirePosITSafterburnerOnly && !posIsFromAfterburner) + return false; // keep afterburner track or not + V0SelCounter.fill(); + + if (negTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; // check minimum ITS clusters + V0SelCounter.fill(); + if (negTrackExtra.itsChi2NCl() >= v0Selections.maxITSchi2PerNcls) + return false; // check maximum ITS chi2 per clusters + V0SelCounter.fill(); + if (v0Selections.rejectNegITSafterburner && negIsFromAfterburner) + return false; // reject afterburner track or not + V0SelCounter.fill(); + if (v0Selections.requireNegITSafterburnerOnly && !negIsFromAfterburner) + return false; // keep afterburner track or not + V0SelCounter.fill(); + + // TPC quality cuts + if (posTrackExtra.tpcNClsCrossedRows() < v0Selections.minTPCrows) + return false; // check minimum TPC crossed rows + V0SelCounter.fill(); + if (posTrackExtra.tpcChi2NCl() >= v0Selections.maxTPCchi2PerNcls) + return false; // check maximum TPC chi2 per clusters + V0SelCounter.fill(); + if (posTrackExtra.tpcCrossedRowsOverFindableCls() < v0Selections.minTPCrowsOverFindableClusters) + return false; // check minimum fraction of TPC rows over findable + V0SelCounter.fill(); + if (posTrackExtra.tpcFoundOverFindableCls() < v0Selections.minTPCfoundOverFindableClusters) + return false; // check minimum fraction of found over findable TPC clusters + V0SelCounter.fill(); + if (posTrackExtra.tpcFractionSharedCls() >= v0Selections.maxFractionTPCSharedClusters) + return false; // check the maximum fraction of allowed shared TPC clusters + V0SelCounter.fill(); + if (v0Selections.rejectTPCsectorBoundary && !isTrackFarFromTPCBoundary(v0.positivept(), v0.positivephi(), +1)) + return false; // reject track far from TPC sector boundary or not + V0SelCounter.fill(); + + if (negTrackExtra.tpcNClsCrossedRows() < v0Selections.minTPCrows) + return false; // check minimum TPC crossed rows + V0SelCounter.fill(); + if (negTrackExtra.tpcChi2NCl() >= v0Selections.maxTPCchi2PerNcls) + return false; // check maximum TPC chi2 per clusters + V0SelCounter.fill(); + if (negTrackExtra.tpcCrossedRowsOverFindableCls() < v0Selections.minTPCrowsOverFindableClusters) + return false; // check minimum fraction of TPC rows over findable + V0SelCounter.fill(); + if (negTrackExtra.tpcFoundOverFindableCls() < v0Selections.minTPCfoundOverFindableClusters) + return false; // check minimum fraction of found over findable TPC clusters + V0SelCounter.fill(); + if (negTrackExtra.tpcFractionSharedCls() >= v0Selections.maxFractionTPCSharedClusters) + return false; // check the maximum fraction of allowed shared TPC clusters + V0SelCounter.fill(); + if (v0Selections.rejectTPCsectorBoundary && !isTrackFarFromTPCBoundary(v0.negativept(), v0.negativephi(), -1)) + return false; // reject track far from TPC sector boundary or not + V0SelCounter.fill(); + + // ITS only tag + if (v0Selections.requirePosITSonly && posTrackExtra.tpcNClsCrossedRows() > 1) + return false; + V0SelCounter.fill(); + if (v0Selections.requireNegITSonly && negTrackExtra.tpcNClsCrossedRows() > 1) + return false; + V0SelCounter.fill(); + + // TPC only tag + if (v0Selections.skipTPConly && posTrackExtra.detectorMap() == o2::aod::track::TPC) + return false; + V0SelCounter.fill(); + if (v0Selections.skipTPConly && negTrackExtra.detectorMap() == o2::aod::track::TPC) + return false; + V0SelCounter.fill(); + + return true; + } + + // Tests the hypothesis of the V0 being a Lambda or of it being an antiLambda. + template + bool passesLambdaLambdaBarHypothesis(TV0 const& v0, TCollision const& collision, bool Lambda_hypothesis) + { + // Remaining topological cuts that were charge-dependent: + // (there is no real gain in doing a looser version of these in the passesGenericV0Cuts function. + // The DCA check will be done anyways and is very unexpensive) + // (even though they are high rejection, they demand a Lambda vs AntiLambda hypothesis, so they + // only appear here...) + const float dcaProtonToPV = Lambda_hypothesis ? std::abs(v0.dcapostopv()) : std::abs(v0.dcanegtopv()); + if (dcaProtonToPV < v0Selections.dcaProtonToPV) + return false; + V0SelCounter.fill(); + const float dcaPionToPV = Lambda_hypothesis ? std::abs(v0.dcanegtopv()) : std::abs(v0.dcapostopv()); // Checks Lambda_hypothesis twice, but compiler can handle it cleanly. + if (dcaPionToPV < v0Selections.dcaPionToPV) + return false; + V0SelCounter.fill(); + + const auto posTrackExtra = v0.template posTrack_as(); + const auto negTrackExtra = v0.template negTrack_as(); + + // For the PID cuts to be properly applied while also keeping this function + // general enough for Lambdas and AntiLambdas, we identify the roles of + // proton-like and pion-like for the pos and neg tracks accordingly: + auto const& protonTrack = Lambda_hypothesis ? posTrackExtra : negTrackExtra; + auto const& pionTrack = Lambda_hypothesis ? negTrackExtra : posTrackExtra; + + ///// Expensive PID checks come last: + // TPC PID + if (std::fabs(protonTrack.tpcNSigmaPr()) > v0Selections.tpcPidNsigmaCut) + return false; + V0SelCounter.fill(); + if (std::fabs(pionTrack.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCut) + return false; + V0SelCounter.fill(); + + // Only do TOF checks when actually using TOF subscriptions: + // if (doprocessDataWithTOF) { + if constexpr (requires { v0.tofNSigmaLaPr(); }) { // Compile-time check is better in hot-loop + // TOF PID in DeltaT (if TOF is not available, then uses the track. If is available, uses it. In this sense, TOF is optional) + // const bool posHasTOF = posTrackExtra.hasTOF(); // For the older version, which worked only for Lambdas + const bool protonHasTOF = protonTrack.hasTOF(); // Should work even without PIDResponseTOF.h, as it is a TracksExtra property + const bool pionHasTOF = pionTrack.hasTOF(); + + // Proton-like track + if (protonHasTOF && std::abs(Lambda_hypothesis ? v0.posTOFDeltaTLaPr() : v0.negTOFDeltaTLaPr()) > v0Selections.maxDeltaTimeProton) + return false; + V0SelCounter.fill(); + // Pion-like track + if (pionHasTOF && std::abs(Lambda_hypothesis ? v0.negTOFDeltaTLaPi() : v0.posTOFDeltaTLaPi()) > v0Selections.maxDeltaTimePion) + return false; + V0SelCounter.fill(); + + // TOF PID in NSigma (TODO: add asymmetric NSigma windows for purity tuning?) + // Proton-like track (notice usage of tofNSigmaLaPr vs tofNSigmaALaPr) + if (protonHasTOF && std::fabs(Lambda_hypothesis ? v0.tofNSigmaLaPr() : v0.tofNSigmaALaPr()) > v0Selections.tofPidNsigmaCutLaPr) + return false; // (No need to select which candidate is which with the Lambda_hypothesis. Automatically done already!) + V0SelCounter.fill(); + // Pion-like track + if (pionHasTOF && std::fabs(Lambda_hypothesis ? v0.tofNSigmaLaPi() : v0.tofNSigmaALaPi()) > v0Selections.tofPidNsigmaCutLaPi) + return false; + V0SelCounter.fill(); + + // (CAUTION!) You cannot use the getter for raw data's PIDResponseTOF.h instead of LFStrangenessPIDTables.h (as below) + // If you do use, TOF will just try to identify that track as a proton from the PV, instead of using the correct path + // length from the V0s PV-DCA and the such! In other words, it is a naive estimator of TOF PID, because it does not + // correct for the V0 mother's travel time and considers all tracks as if they came from the PV! + // if (protonHasTOF && std::fabs(protonTrack.tofNSigmaPr()) > v0Selections.tofPidNsigmaCutLaPr) return false; + // To properly use the LFStrangenessPIDTables version, you need to call o2-analysis-lf-strangenesstofpid too. + } else { // Should fill counters an equal number of times to advance indices + V0SelCounter.fillUpTo(V0SelCounter.binValue + 4); // Fills the 4 times "V0SelCounter.fill()" would be called + } + + // proper lifetime + if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 > v0Selections.lambdaLifetimeCut) + return false; + V0SelCounter.fill(); + + return true; + } + + // Function to help distinguish ambiguous candidates (via Armenteros) that pass both + // the Lambda_hypothesis true (i.e., a Lambda) or false (i.e., an AntiLambda) checks + // (This function is only called in about 1-3% of the Lambda-Like V0s which remain ambiguous after all other cuts) + // int isCandidateArmenterosLambda(const float alpha, const float qt){ + // // Remove K0s band + // if (std::abs(alpha) < v0Selections.armK0AlphaThreshold && qt < v0Selections.armK0QtThreshold) return kIsArmenterosK0; + // // std::abs(alpha) < 0.2 && qt < 0.1 + // if (std::abs(alpha) < v0Selections.armMinAlpha) return kArmenterosAmbiguous; + // // std::abs(alpha) < 0.01f + // // Lambda selection + // if (alpha > 0) return kIsArmenterosLambda; + // else return kIsArmenterosAntiLambda; + // } + + // TODO: another possible check that could be done (if not implemented already inside mLambda() getters) + // template + // int isCandidateMassLambda(TV0 const& v0) { + // float m1 = v0.mLambda(); // proton=positive + // float m2 = v0.mAntiLambda(); // proton=negative + // float d = std::abs(m1 - mLambdaTrue) - std::abs(m2 - mLambdaTrue); + // if (d < 0.f) return +1; // Lambda + // else return -1; // AntiLambda + // } + + template + void jetsProcess(TJetTracks const& tracks, const int ringCollIdx, const float centrality) + { + // Loop over reconstructed tracks: + std::vector fjParticles; + int leadingParticleIdx = -1; // Initialized as -1, but could leave it unitialized as well. We reject any invalid events where this could pose a problem (e.g., pT<=0) + float leadingParticlePt = 0; + for (auto const& track : tracks) { + JetTrackSelCounter.resetForNewTrack(); // reset bin counter for this candidate + JetTrackSelCounter.fill(); // bin: "All track candidates" + + // Require that tracks pass selection criteria + if (!isCandidateForChargedPseudojetAccepted(track)) + continue; + + // Constructing pseudojet candidates vector: + // Using pion mass as hypothesis for track energy estimate (before PID, all particles treated as if with the same invariant mass) + // (TODO: study the possibility of using identified PseudoJet candidates for this estimate) + fastjet::PseudoJet candidate(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); + fjParticles.emplace_back(candidate); + + // Calculating leading particle + float pt = candidate.pt(); + if (pt > leadingParticlePt) { + leadingParticlePt = pt; + leadingParticleIdx = fjParticles.size() - 1; + } + } + // Reject empty events + if (fjParticles.size() < 1) + return; + + int lastBinEvSel = histos.get(HIST("hEventSelection"))->GetXaxis()->GetNbins(); + + auto const& leadingParticle = fjParticles[leadingParticleIdx]; + if (leadingParticle.pt() > jetConfigurations.minLeadParticlePt) { // If not, leading particle is probably a bad proxy + tableLeadParticles(ringCollIdx, leadingParticle.pt(), leadingParticle.eta(), leadingParticle.phi()); + } + + // Start jet clusterization: + // Cluster particles using the anti-kt algorithm + fastjet::JetDefinition jetDef(mapFJAlgorithm(jetConfigurations.jetAlgorithm), jetConfigurations.radiusJet, mapFJRecombScheme(jetConfigurations.jetRecombScheme)); + if (jetConfigurations.bkgSubtraction == kAreaBased) { + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(jetConfigurations.GhostedAreaSpecRapidity)); + fastjet::ClusterSequenceArea clustSeq(fjParticles, jetDef, areaDef); // Attributes an area for each pseudojet in the list + std::vector jets = fastjet::sorted_by_pt(clustSeq.inclusive_jets()); // No minimum pt before background subtraction + if (jets.empty()) + return; + // Perpendicular cone area subtraction, not the traditional subtraction (TODO: include an option for traditional area subtraction) + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], jetConfigurations.radiusJet); // This uses a geometric, pi*R^2 area, not exactly a ghost-based area! + + // Loop over clustered jets: + int selectedJets = 0; + + fastjet::PseudoJet leadingJetSub; + float leadingJetPt = -1.f; + for (const auto& jet : jets) { + // Jet must be fully contained in the acceptance (0.9 for ITS+TPC barrel) + const float jet_eta = jet.eta(); + if (std::fabs(jet_eta) > (0.9f - jetConfigurations.radiusJet)) + continue; + + auto jetForSub = jet; + // Subtracts same background estimated for highest pt jet, but every jet might have a slightly different area + // (TODO: check possible problems with OO and physics impacts of this particular cone method and choice of single background estimator based on leading jet) + // (TODO: improve for Pb-Pb, specially central!) + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + // Jet pt must be larger than threshold: + if (jetMinusBkg.pt() < jetConfigurations.minJetPt) + continue; + selectedJets++; + + // Store jet: + tableJets(ringCollIdx, + jetMinusBkg.pt(), + jetMinusBkg.eta(), // Using eta instead of rapidity + jetMinusBkg.phi(), + jetMinusBkg.constituents().size()); + + // Finding the leading jet after subtraction (leading jet is NOT known a priori!): + if (jetMinusBkg.pt() > leadingJetPt) { + leadingJetPt = jetMinusBkg.pt(); + leadingJetSub = jetMinusBkg; + } + } + histos.fill(HIST("hJetsPerEvent"), selectedJets); + if (selectedJets == 0) + return; + histos.fill(HIST("hEventsWithJet"), 0.5); + // Another version of this counter, which is already integrated in the Event Selection flow: + if (doEventQA) + fillEventSelectionQA(lastBinEvSel - 1, centrality); // hasRingJet passes + + if (doJetKinematicsQA) { + histos.fill(HIST("JetKinematicsQA/hLeadingJetPt"), leadingJetSub.pt()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetEta"), leadingJetSub.eta()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetPhi"), leadingJetSub.phi()); + + // Now looping through jets again to calculate the correlations: + for (const auto& jet : jets) { + // Will recalculated background subtraction during QA to avoid storing jets in memory when running in non-QA cases: + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + + if (jetMinusBkg.pt() < jetConfigurations.minJetPt) + continue; + + float cosTheta = cosThetaJets(leadingJetSub, jetMinusBkg); + float deltaPhi = RecoDecay::constrainAngle(leadingJetSub.phi() - jetMinusBkg.phi(), -o2::constants::math::PI); + float deltaEta = leadingJetSub.eta() - jetMinusBkg.eta(); + float deltaR = std::sqrt(deltaPhi * deltaPhi + deltaEta * deltaEta); + + histos.fill(HIST("JetKinematicsQA/hCosThetaToLeadingJet"), cosTheta); + histos.fill(HIST("JetKinematicsQA/hDeltaPhiToLeadingJet"), deltaPhi); + histos.fill(HIST("JetKinematicsQA/hDeltaEtaToLeadingJet"), deltaEta); + histos.fill(HIST("JetKinematicsQA/hDeltaRToLeadingJet"), deltaR); + + // 2D correlations: + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsLeadJetPt"), selectedJets, leadingJetSub.pt()); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsJetPt"), selectedJets, jetMinusBkg.pt()); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaPhiToLead"), cosTheta, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaEtaToLead"), cosTheta, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaRToLead"), cosTheta, deltaR); + histos.fill(HIST("JetKinematicsQA/h2dDeltaPhiToLeadvsDeltaEtaToLead"), deltaPhi, deltaEta); + + histos.fill(HIST("JetKinematicsQA/h2dJetPtvsDeltaPhiToLead"), jetMinusBkg.pt(), deltaPhi); // Can't really get the energy of the jet, just the pt to make this comparison + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsDeltaPhiToLead"), jetMinusBkg.E(), deltaPhi); // Just a different scale + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsCosThetaToLead"), jetMinusBkg.E(), cosTheta); + + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaPhiToLead"), selectedJets, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaEtaToLead"), selectedJets, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsCosThetaToLead"), selectedJets, cosTheta); + } + // Leading particle comparisons: + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePt"), leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticleEta"), leadingParticle.eta()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePhi"), leadingParticle.phi()); + + float deltaPhiParticleToJet = RecoDecay::constrainAngle(leadingJetSub.phi() - leadingParticle.phi(), -o2::constants::math::PI); + float deltaEtaParticleToJet = leadingJetSub.eta() - leadingParticle.eta(); + float cosThetaParticleToJet = cosThetaJets(leadingJetSub, leadingParticle); // Takes advantage of the fact that this leading particle is a PseudoJet object + + histos.fill(HIST("JetVsLeadingParticleQA/hCosThetaLeadParticleToJet"), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaPhiLeadParticleToJet"), deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaEtaToLeadParticleToJet"), deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead"), deltaPhiParticleToJet, deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaPhiParticleToLead"), selectedJets, deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaEtaParticleToLead"), selectedJets, deltaEtaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsCosThetaParticleToLead"), selectedJets, cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsLeadParticlePt"), selectedJets, leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsLeadParticlePt"), leadingJetSub.pt(), leadingParticle.pt()); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsCosThetaParticleToLead"), leadingJetSub.pt(), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsCosThetaParticleToLead"), leadingParticle.pt(), cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsDeltaPhiParticleToLead"), leadingJetSub.pt(), deltaPhiParticleToJet); // To see if there is any backgound in phi due to soft jets (or soft particles below) + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsDeltaPhiParticleToLead"), leadingParticle.pt(), deltaPhiParticleToJet); + } + } else { // Otherwise, simple jet clustering (TODO: this is the fall back for kConstituentBased while not implemented) + fastjet::ClusterSequence clustSeq(fjParticles, jetDef); + // Jet pt must be larger than threshold: + std::vector jets = fastjet::sorted_by_pt(clustSeq.inclusive_jets(jetConfigurations.minJetPt)); + + const int jetsInEvent = jets.size(); + histos.fill(HIST("hJetsPerEvent"), jetsInEvent); // Fills even in empty events, as this is a useful number to know! + + if (jetsInEvent == 0) + return; + histos.fill(HIST("hEventsWithJet"), 0.5); + // Another version of this counter, which is already integrated in the Event Selection flow: + if (doEventQA) + fillEventSelectionQA(lastBinEvSel - 1, centrality); // hasRingJet passes + + const auto& leadingJet = jets[0]; + for (const auto& jet : jets) { + // Jet must be fully contained in the acceptance (0.9 for ITS+TPC barrel) + const float jet_eta = jet.eta(); + if (std::fabs(jet_eta) > (0.9f - jetConfigurations.radiusJet)) + continue; + + tableJets(ringCollIdx, + jet.pt(), + jet_eta, // Using eta instead of rapidity + jet.phi(), + jet.constituents().size()); + + if (doJetKinematicsQA) { + histos.fill(HIST("JetKinematicsQA/hJetPt"), jet.pt()); + histos.fill(HIST("JetKinematicsQA/hJetEta"), jet_eta); + histos.fill(HIST("JetKinematicsQA/hJetPhi"), jet.phi()); + + // Calculate angle to leading jet: + float cosTheta = cosThetaJets(leadingJet, jet); + + // Calculate angular separation in projected angles: + float deltaPhi = RecoDecay::constrainAngle(leadingJet.phi() - jet.phi(), -o2::constants::math::PI); + float deltaEta = leadingJet.eta() - jet_eta; + float deltaR = std::sqrt(deltaPhi * deltaPhi + deltaEta * deltaEta); // 2D angular distance in the eta-phi plane + + histos.fill(HIST("JetKinematicsQA/hCosThetaToLeadingJet"), cosTheta); // Measuring the cosine, not angle, because it is faster! + histos.fill(HIST("JetKinematicsQA/hDeltaPhiToLeadingJet"), deltaPhi); + histos.fill(HIST("JetKinematicsQA/hDeltaEtaToLeadingJet"), deltaEta); + histos.fill(HIST("JetKinematicsQA/hDeltaRToLeadingJet"), deltaR); + + // 2D correlations: + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsLeadJetPt"), jetsInEvent, leadingJet.pt()); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsJetPt"), jetsInEvent, jet.pt()); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaPhiToLead"), cosTheta, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaEtaToLead"), cosTheta, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dCosThetaToLeadvsDeltaRToLead"), cosTheta, deltaR); + histos.fill(HIST("JetKinematicsQA/h2dDeltaPhiToLeadvsDeltaEtaToLead"), deltaPhi, deltaEta); + + histos.fill(HIST("JetKinematicsQA/h2dJetPtvsDeltaPhiToLead"), jet.pt(), deltaPhi); // Can't really get the energy of the jet, just the pt to make this comparison + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsDeltaPhiToLead"), jet.E(), deltaPhi); // Just a different scale + histos.fill(HIST("JetKinematicsQA/h2dJetEnergyvsCosThetaToLead"), jet.E(), cosTheta); + + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaPhiToLead"), jetsInEvent, deltaPhi); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsDeltaEtaToLead"), jetsInEvent, deltaEta); + histos.fill(HIST("JetKinematicsQA/h2dJetsPerEventvsCosThetaToLead"), jetsInEvent, cosTheta); + } + } + if (doJetKinematicsQA) { + histos.fill(HIST("JetKinematicsQA/hLeadingJetPt"), leadingJet.pt()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetEta"), leadingJet.eta()); + histos.fill(HIST("JetKinematicsQA/hLeadingJetPhi"), leadingJet.phi()); + + // Leading particle comparisons: + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePt"), leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticleEta"), leadingParticle.eta()); + histos.fill(HIST("JetVsLeadingParticleQA/hLeadingParticlePhi"), leadingParticle.phi()); + + double deltaPhiParticleToJet = RecoDecay::constrainAngle(leadingJet.phi() - leadingParticle.phi(), -o2::constants::math::PI); + double deltaEtaParticleToJet = leadingJet.eta() - leadingParticle.eta(); + double cosThetaParticleToJet = cosThetaJets(leadingJet, leadingParticle); // Takes advantage of the fact that this leading particle is a PseudoJet object + + histos.fill(HIST("JetVsLeadingParticleQA/hCosThetaLeadParticleToJet"), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaPhiLeadParticleToJet"), deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/hDeltaEtaToLeadParticleToJet"), deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dDeltaPhiParticleToLeadvsDeltaEtaParticleToLead"), deltaPhiParticleToJet, deltaEtaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaPhiParticleToLead"), jetsInEvent, deltaPhiParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsDeltaEtaParticleToLead"), jetsInEvent, deltaEtaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsCosThetaParticleToLead"), jetsInEvent, cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dJetsPerEventvsLeadParticlePt"), jetsInEvent, leadingParticle.pt()); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsLeadParticlePt"), leadingJet.pt(), leadingParticle.pt()); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsCosThetaParticleToLead"), leadingJet.pt(), cosThetaParticleToJet); + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsCosThetaParticleToLead"), leadingParticle.pt(), cosThetaParticleToJet); + + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadJetPtvsDeltaPhiParticleToLead"), leadingJet.pt(), deltaPhiParticleToJet); // To see if there is any backgound in phi due to soft jets (or soft particles below) + histos.fill(HIST("JetVsLeadingParticleQA/h2dLeadParticlePtvsDeltaPhiParticleToLead"), leadingParticle.pt(), deltaPhiParticleToJet); + } + } + } + + // No longer use a separate JetTracks joined table -- it was mostly a subset of DauTracks + TracksIU (which was not used) + template + void dataProcess(TCollision const& collision, TV0Candidates const& V0s, TDaughterTracks const& V0DauTracks, aod::BCsWithTimestamps const& bcs) + { + float centrality = getCentrality(collision); // Strictly for QA. We save other types of centrality estimators in the derived data! + + // For event QA the last two indices never change for NEv_withJets and NEv_withV0s + // (Not the best way to initialize this: runs once per collision! TODO: think of a better way to do it) + int lastBinEvSel = histos.get(HIST("hEventSelection"))->GetXaxis()->GetNbins(); + bool validV0AlreadyFound = false; + + histos.fill(HIST("hEventSelection"), 0. /* all collisions */); + histos.fill(HIST("hEventSelectionVsCentrality"), 0. /* all collisions */, centrality); + + auto bc = bcs.iteratorAt(collision.bcId()); + if (!isEventAccepted(collision, bc, centrality, doEventQA)) + return; // Uses return instead of continue, as there is no explicit loop here + + if (doEventQA) + fillCentralityProperties(collision, centrality); + if (v0Selections.rejectTPCsectorBoundary) + initCCDB(bc); // Substituted call from collision to bc for raw data + + // Fill event table: + tableCollisions(collision.centFT0M(), + collision.centFT0C(), + collision.centFV0A()); // (TODO: add InteractionRate info and other useful cuts for later on in the analysis?) + + // Get the derived collision row index for this event: + const int ringCollIdx = tableCollisions.lastIndex(); + + // Call to jets process: + jetsProcess(V0DauTracks, ringCollIdx, centrality); // V0DauTracks takes the place of jetTracks now + + uint NLambdas = 0; // Counting particles per event + uint NAntiLambdas = 0; + uint NAmbiguous = 0; + for (auto const& v0 : V0s) { + V0SelCounter.resetForNewV0(); + V0SelCounter.fill(); // Fill for all v0 candidates + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosAll"), v0.alpha(), v0.qtarm()); // fill AP plot for all V0s + if (!passesGenericV0Cuts(v0)) + continue; + + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosKinematicSelected"), v0.alpha(), v0.qtarm()); + + // Else, just continue the loop: + bool isLambda = false; + bool isAntiLambda = false; + if (analyseLambda) + isLambda = passesLambdaLambdaBarHypothesis(v0, collision, true); + if (analyseAntiLambda) { + if (analyseLambda) // We only need to advance when the Lambda hypothesis had an early exit on the counters + V0SelCounter.advanceTo(lambdaHypoEnd + 1); // sync to bin 41 (x=40 means bin 41, the first #bar{#Lambda} bin) + isAntiLambda = passesLambdaLambdaBarHypothesis(v0, collision, false); + } + + if (!isLambda && !isAntiLambda) + continue; // Candidate is not considered to be a Lambda-like + + if (isLambda) + NLambdas++; + if (isAntiLambda) + NAntiLambdas++; + + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelected"), v0.alpha(), v0.qtarm()); // cross-check + if (isLambda && !isAntiLambda) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedLambda"), v0.alpha(), v0.qtarm()); + if (!isLambda && isAntiLambda) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedAntiLambda"), v0.alpha(), v0.qtarm()); + + // XOR check: + if (isLambda ^ isAntiLambda) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedNonAmbiguous"), v0.alpha(), v0.qtarm()); + + // int lambdaIdx = -1; // No need to pass armenteros + if (isLambda && isAntiLambda) { + NAmbiguous++; + histos.fill(HIST("hAmbiguousLambdaCandidates"), 0); + if (doArmenterosQA) + histos.fill(HIST("GeneralQA/h2dArmenterosFullSelectedAmbiguous"), v0.alpha(), v0.qtarm()); // To know the discerning power of Armenteros in an Ambiguous Lambda vs AntiLambda case + + // Armenteros cut is not worth it! From QA histograms, only about 0.05% of ambiguous candidates are in the regions probable to be Lamda/AntiLambdas! + // The statistics gain is not worth it. + // // Third and final check to distinguish between Lambda and AntiLambda ambiguous v0s: + // // (This check is only performed to recycle AMBIGUOUS candidates! Not a hard cut on all candidates!) + // lambdaIdx = isCandidateArmenterosLambda(v0.alpha(), v0.qtarm()); + } + // if (lambdaIdx == kIsArmenterosK0) continue; // Should just skip this step then! + + if (doEventQA) + fillEventSelectionQA(lastBinEvSel, centrality); // hasRingV0 passes + + // // Extra competing mass rejection of Lambdas // (TODO: test competing mass cuts) + // v0.mLambda() + + // Saving the Lambdas into a derived data column: + auto const v0pt = v0.pt(); + const auto posTrackExtra = v0.template posTrack_as(); + const auto negTrackExtra = v0.template negTrack_as(); + tableV0s(ringCollIdx, + v0pt, v0.eta(), v0.phi(), // Using eta instead of rapidity + isLambda, isAntiLambda, + v0.mLambda(), v0.mAntiLambda(), + v0.positivept(), v0.positiveeta(), v0.positivephi(), + v0.negativept(), v0.negativeeta(), v0.negativephi(), + posTrackExtra.tpcNSigmaPr(), posTrackExtra.tpcNSigmaPi(), + negTrackExtra.tpcNSigmaPr(), negTrackExtra.tpcNSigmaPi(), + v0.v0cosPA(), v0.v0radius(), v0.dcaV0daughters(), v0.dcapostopv(), v0.dcanegtopv()); + if (doEventQA && !validV0AlreadyFound) + fillEventSelectionQA(lastBinEvSel, centrality); // hasRingV0 passes + validV0AlreadyFound = true; + + if (doV0KinematicQA) { + // Cache kinematics once + const float v0y = v0.yLambda(); + const float v0phi = v0.phi(); + const float mLambda = v0.mLambda(); + const float mAntiLambda = v0.mAntiLambda(); + if (analyseLambda && isLambda) { + // --- Basic kinematics --- + histos.fill(HIST("V0KinematicQA/Lambda/hPt"), v0pt); + histos.fill(HIST("V0KinematicQA/Lambda/hY"), v0y); + histos.fill(HIST("V0KinematicQA/Lambda/hPhi"), v0phi); + // --- Mass correlations --- + histos.fill(HIST("V0KinematicQA/Lambda/hMassVsPt"), v0pt, mLambda); + histos.fill(HIST("V0KinematicQA/Lambda/hMassVsY"), v0y, mLambda); + histos.fill(HIST("V0KinematicQA/Lambda/hMassVsPhi"), v0phi, mLambda); + // --- Kinematic correlations --- + histos.fill(HIST("V0KinematicQA/Lambda/hYVsPt"), v0pt, v0y); + histos.fill(HIST("V0KinematicQA/Lambda/hPhiVsPt"), v0pt, v0phi); + } + if (analyseAntiLambda && isAntiLambda) { + // --- Basic kinematics --- + histos.fill(HIST("V0KinematicQA/AntiLambda/hPt"), v0pt); + histos.fill(HIST("V0KinematicQA/AntiLambda/hY"), v0y); + histos.fill(HIST("V0KinematicQA/AntiLambda/hPhi"), v0phi); + // --- Mass correlations --- + histos.fill(HIST("V0KinematicQA/AntiLambda/hMassVsPt"), v0pt, mAntiLambda); + histos.fill(HIST("V0KinematicQA/AntiLambda/hMassVsY"), v0y, mAntiLambda); + histos.fill(HIST("V0KinematicQA/AntiLambda/hMassVsPhi"), v0phi, mAntiLambda); + // --- Kinematic correlations --- + histos.fill(HIST("V0KinematicQA/AntiLambda/hYVsPt"), v0pt, v0y); + histos.fill(HIST("V0KinematicQA/AntiLambda/hPhiVsPt"), v0pt, v0phi); + } + } + + if (doCompleteTopoQA) { + // Remaking these variables outside of the passesLambdaLambdaBarHypothesis. Loses performance, but that should be OK for QA + histos.fill(HIST("V0KinematicQA/hPosDCAToPV"), v0.dcapostopv()); + histos.fill(HIST("V0KinematicQA/hNegDCAToPV"), v0.dcanegtopv()); + histos.fill(HIST("V0KinematicQA/hDCADaughters"), v0.dcaV0daughters()); + histos.fill(HIST("V0KinematicQA/hPointingAngle"), std::acos(v0.v0cosPA())); + histos.fill(HIST("V0KinematicQA/hV0Radius"), v0.v0radius()); + histos.fill(HIST("V0KinematicQA/h2dPositiveITSvsTPCpts"), posTrackExtra.tpcNClsCrossedRows(), posTrackExtra.itsNCls()); + histos.fill(HIST("V0KinematicQA/h2dNegativeITSvsTPCpts"), negTrackExtra.tpcNClsCrossedRows(), negTrackExtra.itsNCls()); + histos.fill(HIST("V0KinematicQA/h2dPositivePtVsPhi"), v0.positivept(), computePhiMod(v0.positivephi(), 1)); + histos.fill(HIST("V0KinematicQA/h2dNegativePtVsPhi"), v0.negativept(), computePhiMod(v0.negativephi(), -1)); + if (isLambda && analyseLambda) { + histos.fill(HIST("hMassLambda"), v0.mLambda()); + histos.fill(HIST("Lambda/h3dMassLambda"), centrality, v0pt, v0.mLambda()); + histos.fill(HIST("Lambda/hPosDCAToPV"), v0.dcapostopv()); + histos.fill(HIST("Lambda/hNegDCAToPV"), v0.dcanegtopv()); + histos.fill(HIST("Lambda/hDCADaughters"), v0.dcaV0daughters()); + histos.fill(HIST("Lambda/hPointingAngle"), std::acos(v0.v0cosPA())); + histos.fill(HIST("Lambda/hV0Radius"), v0.v0radius()); + histos.fill(HIST("Lambda/h2dPositiveITSvsTPCpts"), posTrackExtra.tpcNClsCrossedRows(), posTrackExtra.itsNCls()); + histos.fill(HIST("Lambda/h2dNegativeITSvsTPCpts"), negTrackExtra.tpcNClsCrossedRows(), negTrackExtra.itsNCls()); + histos.fill(HIST("Lambda/h2dPositivePtVsPhi"), v0.positivept(), computePhiMod(v0.positivephi(), 1)); + histos.fill(HIST("Lambda/h2dNegativePtVsPhi"), v0.negativept(), computePhiMod(v0.negativephi(), -1)); + if (doTPCQA) { + histos.fill(HIST("Lambda/h3dPosNsigmaTPC"), centrality, v0pt, posTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTPC"), centrality, v0pt, negTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("Lambda/h3dPosTPCsignal"), centrality, v0pt, posTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dNegTPCsignal"), centrality, v0pt, negTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dPosNsigmaTPCvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTPCvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("Lambda/h3dPosTPCsignalVsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dNegTPCsignalVsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dPosNsigmaTPCvsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTPCvsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("Lambda/h3dPosTPCsignalVsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcSignal()); + histos.fill(HIST("Lambda/h3dNegTPCsignalVsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcSignal()); + } + if constexpr (requires { v0.tofNSigmaLaPr(); }) { + if (doTOFQA) { + histos.fill(HIST("Lambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPi()); + histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPi()); + histos.fill(HIST("Lambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaLaPr()); + histos.fill(HIST("Lambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaLaPi()); + histos.fill(HIST("Lambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPr()); + histos.fill(HIST("Lambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPi()); + } + } + if (doEtaPhiQA) { + histos.fill(HIST("Lambda/h5dV0PhiVsEta"), centrality, v0pt, v0.mLambda(), v0.phi(), v0.eta()); + histos.fill(HIST("Lambda/h5dPosPhiVsEta"), centrality, v0.positivept(), v0.mLambda(), v0.positivephi(), v0.positiveeta()); + histos.fill(HIST("Lambda/h5dNegPhiVsEta"), centrality, v0.negativept(), v0.mLambda(), v0.negativephi(), v0.negativeeta()); + } + } + if (isAntiLambda && analyseAntiLambda) { + histos.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); + histos.fill(HIST("AntiLambda/h3dMassAntiLambda"), centrality, v0pt, v0.mAntiLambda()); + histos.fill(HIST("AntiLambda/hPosDCAToPV"), v0.dcapostopv()); + histos.fill(HIST("AntiLambda/hNegDCAToPV"), v0.dcanegtopv()); + histos.fill(HIST("AntiLambda/hDCADaughters"), v0.dcaV0daughters()); + histos.fill(HIST("AntiLambda/hPointingAngle"), std::acos(v0.v0cosPA())); + histos.fill(HIST("AntiLambda/hV0Radius"), v0.v0radius()); + histos.fill(HIST("AntiLambda/h2dPositiveITSvsTPCpts"), posTrackExtra.tpcNClsCrossedRows(), posTrackExtra.itsNCls()); + histos.fill(HIST("AntiLambda/h2dNegativeITSvsTPCpts"), negTrackExtra.tpcNClsCrossedRows(), negTrackExtra.itsNCls()); + histos.fill(HIST("AntiLambda/h2dPositivePtVsPhi"), v0.positivept(), computePhiMod(v0.positivephi(), 1)); + histos.fill(HIST("AntiLambda/h2dNegativePtVsPhi"), v0.negativept(), computePhiMod(v0.negativephi(), -1)); + if (doTPCQA) { + histos.fill(HIST("AntiLambda/h3dPosNsigmaTPC"), centrality, v0pt, posTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTPC"), centrality, v0pt, negTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("AntiLambda/h3dPosTPCsignal"), centrality, v0pt, posTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dNegTPCsignal"), centrality, v0pt, negTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTPCvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTPCvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("AntiLambda/h3dPosTPCsignalVsTrackPtot"), centrality, v0.pfracpos() * v0.p(), posTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dNegTPCsignalVsTrackPtot"), centrality, v0.pfracneg() * v0.p(), negTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTPCvsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcNSigmaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTPCvsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcNSigmaPr()); + histos.fill(HIST("AntiLambda/h3dPosTPCsignalVsTrackPt"), centrality, v0.positivept(), posTrackExtra.tpcSignal()); + histos.fill(HIST("AntiLambda/h3dNegTPCsignalVsTrackPt"), centrality, v0.negativept(), negTrackExtra.tpcSignal()); + } + if constexpr (requires { v0.tofNSigmaLaPr(); }) { + if (doTOFQA) { + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOF"), centrality, v0pt, v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaT"), centrality, v0pt, v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaT"), centrality, v0pt, v0.negTOFDeltaTLaPr()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPtot"), centrality, v0.pfracpos() * v0.p(), v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPtot"), centrality, v0.pfracneg() * v0.p(), v0.negTOFDeltaTLaPr()); + histos.fill(HIST("AntiLambda/h3dPosNsigmaTOFvsTrackPt"), centrality, v0.positivept(), v0.tofNSigmaALaPi()); + histos.fill(HIST("AntiLambda/h3dNegNsigmaTOFvsTrackPt"), centrality, v0.negativept(), v0.tofNSigmaALaPr()); + histos.fill(HIST("AntiLambda/h3dPosTOFdeltaTvsTrackPt"), centrality, v0.positivept(), v0.posTOFDeltaTLaPi()); + histos.fill(HIST("AntiLambda/h3dNegTOFdeltaTvsTrackPt"), centrality, v0.negativept(), v0.negTOFDeltaTLaPr()); + } + } + if (doEtaPhiQA) { + histos.fill(HIST("AntiLambda/h5dV0PhiVsEta"), centrality, v0pt, v0.mAntiLambda(), v0.phi(), v0.eta()); + histos.fill(HIST("AntiLambda/h5dPosPhiVsEta"), centrality, v0.positivept(), v0.mAntiLambda(), v0.positivephi(), v0.positiveeta()); + histos.fill(HIST("AntiLambda/h5dNegPhiVsEta"), centrality, v0.negativept(), v0.mAntiLambda(), v0.negativephi(), v0.negativeeta()); + } + } + } // end CompleteTopoQA + } // end V0s loop + + // Fill histograms on a per-event level: + histos.fill(HIST("Lambda/hLambdasPerEvent"), NLambdas); + histos.fill(HIST("AntiLambda/hAntiLambdasPerEvent"), NAntiLambdas); + histos.fill(HIST("hAmbiguousPerEvent"), NAmbiguous); + histos.fill(HIST("Lambda/h2dNbrOfLambdaVsCentrality"), centrality, NLambdas); + histos.fill(HIST("AntiLambda/h2dNbrOfAntiLambdaVsCentrality"), centrality, NAntiLambdas); + } + + void processData(SelCollisions::iterator const& collision, aod::V0Datas const& V0s, DauTracks const& V0DauTracks, aod::BCsWithTimestamps const& bcs) + { + dataProcess(collision, V0s, V0DauTracks, bcs); // No longer need "JetTracks const& jetTracks" -- using DauTracks subscription instead + } + + void processDataWithTOF(SelCollisions::iterator const& collision, V0CandidatesWithTOF const& V0s, DauTracks const& V0DauTracks, aod::BCsWithTimestamps const& bcs) + { + dataProcess(collision, V0s, V0DauTracks, bcs); + } + + PROCESS_SWITCH(lambdajetpolarizationions, processData, "Process jets and V0s, produces derived data in Run 3 Data", true); + PROCESS_SWITCH(lambdajetpolarizationions, processDataWithTOF, "Process jets and V0s (with TOF), produces derived data in Run 3 Data", false); + // PROCESS_SWITCH(lambdajetpolarizationions, processMC, "Process jets and V0s, produces derived data in Run 3 MC", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/lfinjets.cxx b/PWGLF/TableProducer/Strangeness/lfinjets.cxx index 7b518ab2884..6843531ce79 100644 --- a/PWGLF/TableProducer/Strangeness/lfinjets.cxx +++ b/PWGLF/TableProducer/Strangeness/lfinjets.cxx @@ -199,7 +199,7 @@ struct LFInJets { } // Define binning and axis specifications for multiplicity, eta, pT, PID, and invariant mass histograms - std::vector multBinning = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; + std::vector multBinning = {0, 1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; AxisSpec multAxis = {multBinning, "FT0C percentile"}; const AxisSpec ptAxis{100, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec invMassK0sAxis{200, 0.44, 0.56, "m_{#pi#pi} (GeV/#it{c}^{2})"}; diff --git a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx index 273b20fe7cf..b4f266b96b1 100644 --- a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx +++ b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx @@ -14,6 +14,7 @@ /// \author Stefano Cannito (stefano.cannito@cern.ch) #include "PWGLF/DataModel/LFPhiStrangeCorrelationTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/inelGt.h" @@ -43,6 +44,7 @@ #include #include #include +#include #include #include @@ -50,6 +52,8 @@ #include #include #include +#include +#include #include #include #include @@ -60,10 +64,15 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct PhiMesonCandProducer { - // Produce the table with the event selection information - Produces phimesonCandidates; + // Produce the table with the phi candidates information + Produces phimesonCandidatesData; + Produces phimesonCandidatesMcReco; + Produces phimesonCandidatesMcGen; - HistogramRegistry histos{"phiCandidates", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry histos{"phimesonCandidates", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable on multiplicity bins + Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; // Configurables for phi's daughter tracks selection struct : ConfigurableGroup { @@ -86,15 +95,28 @@ struct PhiMesonCandProducer { // Configurables on phi selection struct : ConfigurableGroup { - Configurable maxMPhi{"maxMPhi", 1.5f, "Maximum mass for Phi candidates"}; + Configurable maxMPhi{"maxMPhi", 1.2f, "Maximum mass for Phi candidates"}; Configurable minPhiPt{"minPhiPt", 0.4f, "Minimum pT for Phi candidates"}; Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; } phiConfigs; + // Configurables on phi pT bins + Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; + + // Filter on default selected collisions + // Filter collisionFilter = aod::lf_selection_default_collision::defaultSel == true; + // Filter collisionFilter = aod::lf_selection_event::defaultSel == true; + // Defining the type of the collisions for data and MC - using SelCollisions = soa::Join; + using SelCollisions = soa::Join; using SimCollisions = soa::Join; + /*using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + using FilteredSelCollisions = soa::Filtered; + using FilteredSimCollisions = soa::Filtered;*/ + // Defining the type of the phi's daughter tracks for data and MC using FullTracks = soa::Join; using FullMCTracks = soa::Join; @@ -114,9 +136,18 @@ struct PhiMesonCandProducer { void init(InitContext&) { + AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + AxisSpec binnedpTPhiAxis{(std::vector)binspTPhi, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec massPhiAxis = {200, 0.9f, 1.2f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - histos.add("h1PhiCandidateMass", "Phi candidate invariant mass", kTH1F, {massPhiAxis}); + histos.add("h3PhiCandidatesMass", "Phi candidate invariant mass", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + + // Phi's daughter tracks information + /*histos.add("hEta", "Eta of Kaon candidates", kTH1F, {{100, -1.0f, 1.0f}}); + histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); + histos.add("h2DauTracksPhiDCAxy", "DCAxy distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + histos.add("h2DauTracksPhiDCAz", "DCAz distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}});*/ } // Topological track selection @@ -165,19 +196,53 @@ struct PhiMesonCandProducer { return mother; } - void processData(SelCollisions::iterator const& collision, FullTracks const&) + template + void processPhiCandidates(const T& collision, std::optional> mcParticlesOpt = std::nullopt) { - auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - + // Compile-time selection of the track partition to use based on the type of the analysis (Data or MCReco) + auto posThisColl = [&]() { + if constexpr (isMC) + return posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + else + return posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + }(); + + auto negThisColl = [&]() { + if constexpr (isMC) + return negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + else + return negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + }(); + + // Loop over positive tracks for (const auto& track1 : posThisColl) { if (!selectionTrackResonance(track1) || !selectionPIDKaonpTdependent(track1)) continue; + if constexpr (isMC) { + if (!track1.has_mcParticle()) + continue; + const auto& mcParticles = mcParticlesOpt.value().get(); + const auto track1McParticle = mcParticles.rawIteratorAt(track1.mcParticleId()); + if (track1McParticle.pdgCode() != PDG_t::kKPlus || !track1McParticle.isPhysicalPrimary()) + continue; + } + + // Loop over negative tracks for (const auto& track2 : negThisColl) { if (!selectionTrackResonance(track2) || !selectionPIDKaonpTdependent(track2)) continue; + if constexpr (isMC) { + if (!track2.has_mcParticle()) + continue; + const auto& mcParticles = mcParticlesOpt.value().get(); + const auto track2McParticle = mcParticles.rawIteratorAt(track2.mcParticleId()); + if (track2McParticle.pdgCode() != PDG_t::kKMinus || !track2McParticle.isPhysicalPrimary()) + continue; + } + + // Kinematic reconstruction (common for data and MC) ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); if (recPhi.Pt() < phiConfigs.minPhiPt) @@ -187,43 +252,70 @@ struct PhiMesonCandProducer { if (std::abs(recPhi.Rapidity()) > phiConfigs.cfgYAcceptance) continue; - histos.fill(HIST("h1PhiCandidateMass"), recPhi.M()); - - phimesonCandidates(collision.globalIndex(), recPhi.M(), recPhi.Pt(), recPhi.Rapidity(), recPhi.Phi()); + // PDG check and MC truth association for MCReco analysis + if constexpr (isMC) { + const auto& mcParticles = mcParticlesOpt.value().get(); + + const auto track1McParticle = mcParticles.rawIteratorAt(track1.mcParticleId()); + const auto track2McParticle = mcParticles.rawIteratorAt(track2.mcParticleId()); + + const auto track1mcPartMotherIndexes = track1McParticle.mothersIds(); + const auto track2mcPartMotherIndexes = track2McParticle.mothersIds(); + + auto genPhiMaybe = [&]() -> std::optional { + for (const auto& mother1Index : track1mcPartMotherIndexes) { + for (const auto& mother2Index : track2mcPartMotherIndexes) { + if (mother1Index != mother2Index) + continue; + const auto motherMcParticle = mcParticles.rawIteratorAt(mother1Index); + if (std::abs(motherMcParticle.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + return motherMcParticle; + } + } + } + return std::nullopt; + }(); + + if (!genPhiMaybe) + continue; + const auto genPhi = *genPhiMaybe; + + phimesonCandidatesMcReco(collision.globalIndex(), recPhi.M(), genPhi.pt(), genPhi.y(), genPhi.phi()); + } else { + histos.fill(HIST("h3PhiCandidatesMass"), collision.centFT0M(), recPhi.Pt(), recPhi.M()); + phimesonCandidatesData(collision.globalIndex(), recPhi.M(), recPhi.Pt(), recPhi.Rapidity(), recPhi.Phi()); + } } } } - PROCESS_SWITCH(PhiMesonCandProducer, processData, "Process function to select Phi meson candidates in Data", true); - - void processMCReco(SimCollisions::iterator const& collision, FullMCTracks const&) + void processData(SelCollisions::iterator const& collision, FullTracks const&) { - auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + processPhiCandidates(collision); + } - for (const auto& track1 : posThisColl) { - if (!selectionTrackResonance(track1) || !selectionPIDKaonpTdependent(track1)) - continue; + PROCESS_SWITCH(PhiMesonCandProducer, processData, "Process function to select Phi meson candidates in Data or in McReco (w/o McTruth) analysis", true); - for (const auto& track2 : negThisColl) { - if (!selectionTrackResonance(track2) || !selectionPIDKaonpTdependent(track2)) - continue; + void processMCReco(SimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const& mcParticles) + { + processPhiCandidates(collision, mcParticles); + } - ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); + PROCESS_SWITCH(PhiMesonCandProducer, processMCReco, "Process function to select Phi meson candidates in MCReco w MC truth", false); - if (recPhi.Pt() < phiConfigs.minPhiPt) - continue; - if (recPhi.M() > phiConfigs.maxMPhi) - continue; - if (std::abs(recPhi.Rapidity()) > phiConfigs.cfgYAcceptance) - continue; + /*void processFilteredData(FilteredSelCollisions::iterator const& collision, FullTracks const&) + { + processPhiCandidates(collision); + } - phimesonCandidates(collision.globalIndex(), recPhi.M(), recPhi.Pt(), recPhi.Rapidity(), recPhi.Phi()); - } - } + PROCESS_SWITCH(PhiMesonCandProducer, processFilteredData, "Process function to select Phi meson candidates in filtered Data", true); + + void processFilteredMCReco(FilteredSimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const& mcParticles) + { + processPhiCandidates(collision, mcParticles); } - PROCESS_SWITCH(PhiMesonCandProducer, processMCReco, "Process function to select Phi meson candidates in MCReco", false); + PROCESS_SWITCH(PhiMesonCandProducer, processFilteredMCReco, "Process function to select Phi meson candidates in filtered MCReco w MC truth", false);*/ void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles) { @@ -248,7 +340,7 @@ struct PhiMesonCandProducer { if (std::abs(genKPair.Rapidity()) > phiConfigs.cfgYAcceptance) continue; - phimesonCandidates(mcCollision.globalIndex(), genKPair.M(), genKPair.Pt(), genKPair.Rapidity(), genKPair.Phi()); + phimesonCandidatesMcGen(mcCollision.globalIndex(), genKPair.M(), genKPair.Pt(), genKPair.Rapidity(), genKPair.Phi()); } } } @@ -256,14 +348,421 @@ struct PhiMesonCandProducer { PROCESS_SWITCH(PhiMesonCandProducer, processMCGen, "Process function to select Phi meson candidates in MCGen", false); }; -struct PhiMesonSelCollision { +struct K0sReducedCandProducer { + // Produce the table with the K0s candidates information + Produces k0sReducedCandidatesData; + Produces k0sReducedCandidatesMcReco; + + HistogramRegistry histos{"k0sReducedCandidates", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable on multiplicity bins + Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; + + // Configurables for tracks selection + struct : ConfigurableGroup { + Configurable etaMax{"etaMax", 0.8f, "eta max"}; + Configurable nSigmaCutTPCSecPion{"nSigmaCutTPCSecPion", 4.0f, "Value of the TPC Nsigma cut for secondary Pions"}; + + Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "min number of TPC crossed rows"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; + } trackConfigs; + + // Configurables for V0 selection + struct : ConfigurableGroup { + Configurable v0SettingCosPA{"v0SettingCosPA", 0.98f, "V0 CosPA"}; + Configurable v0SettingRadius{"v0SettingRadius", 0.5f, "v0radius"}; + Configurable v0SettingDCAV0Dau{"v0SettingDCAV0Dau", 1.0f, "DCA V0 Daughters"}; + Configurable v0SettingDCAPosToPV{"v0SettingDCAPosToPV", 0.1f, "DCA Pos To PV"}; + Configurable v0SettingDCANegToPV{"v0SettingDCANegToPV", 0.1f, "DCA Neg To PV"}; + Configurable v0SettingMinPt{"v0SettingMinPt", 0.1f, "V0 min pt"}; + + Configurable cfgFurtherV0Selection{"cfgFurtherV0Selection", false, "Further V0 selection"}; + Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0s(cm)"}; + Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "parameter Armenteros Cut"}; + Configurable v0rejK0s{"v0rejK0s", 0.005f, "V0 rej K0s"}; + + Configurable> rangeMK0sSignal{"rangeMK0sSignal", {0.47f, 0.53f}, "K0S mass range for signal extraction"}; + + Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; + } v0Configs; + + // Configurable on K0S pT bins + Configurable> binspTK0S{"binspTK0S", {0.1, 0.5, 0.8, 1.2, 1.6, 2.0, 2.5, 3.0, 4.0, 6.0}, "pT bin limits for K0S"}; + + // Constants + static constexpr double massK0S = o2::constants::physics::MassK0Short; + static constexpr double massLambda = o2::constants::physics::MassLambda0; + + // Filter on default selected collisions + // Filter collisionFilter = aod::lf_selection_default_collision::defaultSel == true; + Filter collisionFilter = aod::lf_selection_event::defaultSel == true; + + // Defining filters on V0s (cannot filter on dynamic columns) + Filter v0PreFilter = (nabs(aod::v0data::dcapostopv) > v0Configs.v0SettingDCAPosToPV && nabs(aod::v0data::dcanegtopv) > v0Configs.v0SettingDCANegToPV && aod::v0data::dcaV0daughters < v0Configs.v0SettingDCAV0Dau); + + // Defining the type of the collisions for data and MC + using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + using FilteredSelCollisions = soa::Filtered; + using FilteredSimCollisions = soa::Filtered; + + // Defining the type of the V0s and corresponding daughter tracks for data and MC + using FullV0s = soa::Filtered; + using FullMCV0s = soa::Filtered>; + + using V0DauTracks = soa::Join; + using V0DauMCTracks = soa::Join; + + void init(InitContext&) + { + AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + AxisSpec binnedpTK0SAxis{(std::vector)binspTK0S, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec massK0SAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + + histos.add("h3K0sCandidatesMass", "K^{0}_{S} candidate invariant mass", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + } + + // Single track selection for strangeness sector + template + bool selectionTrackStrangeness(const T& track) + { + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < trackConfigs.minNCrossedRowsTPC) + return false; + if (track.tpcChi2NCl() > trackConfigs.maxChi2TPC) + return false; + + if (std::abs(track.eta()) > trackConfigs.etaMax) + return false; + return true; + } + + // V0 selection + template + bool selectionV0(const T1& v0, const T2& collision) + { + using V0DauTrackType = std::conditional_t; + + const auto& posDaughterTrack = v0.template posTrack_as(); + const auto& negDaughterTrack = v0.template negTrack_as(); + + if (!selectionTrackStrangeness(posDaughterTrack) || !selectionTrackStrangeness(negDaughterTrack)) + return false; + + if constexpr (!isMC) { + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) + return false; + if (std::abs(negDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) + return false; + } + + if (v0.v0cosPA() < v0Configs.v0SettingCosPA) + return false; + if (v0.v0radius() < v0Configs.v0SettingRadius) + return false; + if (v0.pt() < v0Configs.v0SettingMinPt) + return false; + + if (v0Configs.cfgFurtherV0Selection) { + if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0S > v0Configs.ctauK0s) + return false; + if (v0.qtarm() < (v0Configs.paramArmenterosCut * std::abs(v0.alpha()))) + return false; + if (std::abs(v0.mLambda() - massLambda) < v0Configs.v0rejK0s) + return false; + } + + if (std::abs(v0.yK0Short()) > v0Configs.cfgYAcceptance) + return false; + + return true; + } + + // void processData(SelCollisions::iterator const& collision, FullV0s const& V0s, V0DauTracks const&) + void processData(FilteredSelCollisions::iterator const& collision, FullV0s const& V0s, V0DauTracks const&) + { + for (const auto& v0 : V0s) { + // Cut on V0 dynamic columns + if (!selectionV0(v0, collision)) + continue; + + histos.fill(HIST("h3K0sCandidatesMass"), collision.centFT0M(), v0.pt(), v0.mK0Short()); + + k0sReducedCandidatesData(collision.globalIndex(), v0.mK0Short(), v0.pt(), v0.yK0Short(), v0.phi()); + } + } + + PROCESS_SWITCH(K0sReducedCandProducer, processData, "Process function to select reduced K0s candidates in Data or in McReco (w/o McTruth) analysis", true); + + // void processMCReco(SimCollisions::iterator const& collision, FullMCV0s const& V0s, V0DauMCTracks const&, aod::McParticles const& mcParticles) + void processMCReco(FilteredSimCollisions::iterator const& collision, FullMCV0s const& V0s, V0DauMCTracks const&, aod::McParticles const& mcParticles) + { + for (const auto& v0 : V0s) { + if (!selectionV0(v0, collision)) + continue; + if (!v0.has_mcParticle()) + continue; + + const auto& v0McParticle = mcParticles.rawIteratorAt(v0.mcParticleId()); + if (std::abs(v0McParticle.pdgCode()) != PDG_t::kK0Short || !v0McParticle.isPhysicalPrimary()) + continue; + + k0sReducedCandidatesMcReco(collision.globalIndex(), v0.mK0Short(), v0McParticle.pt(), v0McParticle.y(), v0McParticle.phi()); + } + } + + PROCESS_SWITCH(K0sReducedCandProducer, processMCReco, "Process function to select reduced K0s candidates in MCReco w MC truth", false); +}; + +struct PionTrackProducer { + // Produce the table with the pion tracks information + Produces pionTracksData; + Produces pionTracksMcReco; + + HistogramRegistry histos{"pionTracks", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for analysis mode + // Configurable analysisMode{"analysisMode", 1, "Analysis mode: 0 - old method with online normalization, 1 - new method with correlations"}; + + // Configurable on multiplicity bins + Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; + + // Configurables for pion track selection + struct : ConfigurableGroup { + Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; + Configurable nSigmaCutTPCPrimPion{"nSigmaCutTPCPrimPion", 2.0f, "Value of the TPC Nsigma cut for primary Pions"}; + Configurable nSigmaCutCombinedPi{"nSigmaCutCombinedPi", 2.0f, "Value of the TPC and TOF Nsigma cut for Pions"}; + + Configurable cfgIsTOFChecked{"cfgIsTOFChecked", true, "Is TOF checked in PID for pions"}; + Configurable> cMaxDCArToPVPion{"cMaxDCArToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAr cut to PV for Pions"}; + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0f, "Track DCAz cut to PV Maximum"}; + Configurable cfgIsDCAzParameterized{"cfgIsDCAzParameterized", false, "IsDCAzParameterized"}; + Configurable> cMaxDCAzToPVPion{"cMaxDCAzToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAz cut to PV for Pions"}; + + Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; + Configurable minITSnCls{"minITSnCls", 4, "min number of ITS clusters"}; + + // Configurable forceTOF{"forceTOF", false, "force the TOF signal for the PID"}; + Configurable tofPIDThreshold{"tofPIDThreshold", 0.5, "minimum pT after which TOF PID is applicable"}; + Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID rejection, kaon, proton"}; + Configurable> pidTPCMax{"pidTPCMax", std::vector{2.0f, 2.0f}, "maximum nSigma TPC"}; + Configurable> pidTOFMax{"pidTOFMax", std::vector{2.0f, 2.0f}, "maximum nSigma TOF"}; + + Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; + } trackConfigs; + + // Configurable on pion pT bins + Configurable> binspTPi{"binspTPi", {0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.5, 2.0, 3.0}, "pT bin limits for pions"}; + + static constexpr double massPi = o2::constants::physics::MassPiPlus; + + // Filter on default selected collisions + // Filter collisionFilter = aod::lf_selection_default_collision::defaultSel == true; + Filter collisionFilter = aod::lf_selection_event::defaultSel == true; + + // Defining the type of the collisions for data and MC + using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + using FilteredSelCollisions = soa::Filtered; + using FilteredSimCollisions = soa::Filtered; + + // Defining the type of the tracks for data and MC + using FullTracks = soa::Join; + using FullMCTracks = soa::Join; + + void init(InitContext&) + { + AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + AxisSpec binnedpTPiAxis{(std::vector)binspTPi, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaPiAxis = {100, -10.0f, 10.0f, "N#sigma #pi"}; + + histos.add("h3PionTPCnSigma", "Pion TPC nSigma distribution", kTH3F, {binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis}); + histos.add("h3PionTOFnSigma", "Pion TOF nSigma distribution", kTH3F, {binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis}); + + histos.add("h2RecMCDCAxyPrimPi", "Dcaxy distribution vs pt for Primary Pions", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + histos.add("h2RecMCDCAxySecWeakDecayPi", "Dcaz distribution vs pt for Secondary Pions from Weak Decay", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + histos.add("h2RecMCDCAxySecMaterialPi", "Dcaxy distribution vs pt for Secondary Pions from Material", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + } + + /*// PID selection for Pions + template + bool pidSelectionPion(const T& track) + { + for (size_t speciesIndex = 0; speciesIndex < trackConfigs.trkPIDspecies->size(); ++speciesIndex) { + auto const& pid = trackConfigs.trkPIDspecies->at(speciesIndex); + auto nSigmaTPC = aod::pidutils::tpcNSigma(pid, track); + + if (trackConfigs.forceTOF && !track.hasTOF()) { + return false; + } + + if (speciesIndex == 0) { // First species logic + if (std::abs(nSigmaTPC) >= trackConfigs.pidTPCMax->at(speciesIndex)) { + return false; // TPC check failed + } + if (trackConfigs.forceTOF || (track.pt() >= trackConfigs.tofPIDThreshold && track.hasTOF())) { + auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) >= trackConfigs.pidTOFMax->at(speciesIndex)) { + return false; // TOF check failed + } + } + } else { // Other species logic + if (std::abs(nSigmaTPC) < trackConfigs.pidTPCMax->at(speciesIndex)) { // Check TPC nSigma first + if (track.hasTOF()) { + auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) < trackConfigs.pidTOFMax->at(speciesIndex)) { + return false; // Reject if both TPC and TOF are within thresholds + } + } else { + return false; // Reject if only TPC is within threshold and TOF is unavailable + } + } + } + } + + return true; + }*/ + + // PID Hypotheses rejection for Pions + template + bool pidHypothesesRejection(const T& track) + { + for (size_t speciesIndex = 0; speciesIndex < trackConfigs.trkPIDspecies->size(); ++speciesIndex) { + auto const& pid = trackConfigs.trkPIDspecies->at(speciesIndex); + auto nSigmaTPC = aod::pidutils::tpcNSigma(pid, track); + + if (std::abs(nSigmaTPC) < trackConfigs.pidTPCMax->at(speciesIndex)) { // Check TPC nSigma first + if (track.hasTOF()) { + auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) < trackConfigs.pidTOFMax->at(speciesIndex)) { + return false; // Reject if both TPC and TOF are within thresholds + } + } else { + return false; // Reject if only TPC is within threshold and TOF is unavailable + } + } + } + + return true; + } + + // Track selection for Pions + template + bool selectionPion(const T& track) + { + if (!track.isGlobalTrackWoDCA()) + return false; + + if (track.itsNCls() < trackConfigs.minITSnCls) + return false; + if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) + return false; + + if (track.pt() < trackConfigs.cMinPionPtcut) + return false; + + if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPVPion->at(0) + (trackConfigs.cMaxDCArToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCArToPVPion->at(2)))) + return false; + if (trackConfigs.cfgIsDCAzParameterized) { + if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVPion->at(0) + (trackConfigs.cMaxDCAzToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCAzToPVPion->at(2)))) + return false; + } else { + if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVcut) + return false; + } + + if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && !track.hasTOF()) + return false; + + /*if (analysisMode == 1 && !pidSelectionPion(track)) + return false;*/ + + if (!pidHypothesesRejection(track)) + return false; + + /* + if (analysisMode == 1) { + if (track.pt() < trackConfigs.tofPIDThreshold && std::abs(track.tpcNSigmaPi()) >= trackConfigs.nSigmaCutTPCPrimPion) + return false; + if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && (std::pow(track.tofNSigmaPi(), 2) + std::pow(track.tpcNSigmaPi(), 2)) >= std::pow(trackConfigs.nSigmaCutCombinedPi, 2)) + return false; + } + */ + + if (std::abs(track.rapidity(massPi)) > trackConfigs.cfgYAcceptance) + return false; + + return true; + } + + // void processData(SelCollisions::iterator const& collision, FullTracks const& fullTracks) + void processData(FilteredSelCollisions::iterator const& collision, FullTracks const& fullTracks) + { + for (const auto& track : fullTracks) { + if (!selectionPion(track)) + continue; + + histos.fill(HIST("h3PionTPCnSigma"), collision.centFT0M(), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("h3PionTOFnSigma"), collision.centFT0M(), track.pt(), track.tofNSigmaPi()); + + pionTracksData(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi(), track.hasTOF()); + } + } + + PROCESS_SWITCH(PionTrackProducer, processData, "Process function to select pion tracks in Data or in McReco (w/o MC truth) analysis", true); + + // void processMCReco(SimCollisions::iterator const& collision, FullMCTracks const& fullTracks, aod::McParticles const& mcParticles) + void processMCReco(FilteredSimCollisions::iterator const& collision, FullMCTracks const& fullTracks, aod::McParticles const& mcParticles) + { + for (const auto& track : fullTracks) { + if (!selectionPion(track)) + continue; + if (!track.has_mcParticle()) + continue; + + const auto trackMcParticle = mcParticles.rawIteratorAt(track.mcParticleId()); + if (std::abs(trackMcParticle.pdgCode()) != PDG_t::kPiPlus) + continue; + + if (trackMcParticle.isPhysicalPrimary()) { + histos.fill(HIST("h2RecMCDCAxyPrimPi"), track.pt(), track.dcaXY()); + } else { + if (trackMcParticle.getProcess() == TMCProcess::kPDecay) { // Selection of secondary pions from weak decay + histos.fill(HIST("h2RecMCDCAxySecWeakDecayPi"), track.pt(), track.dcaXY()); + } else { // Selection of secondary pions from material interactions + histos.fill(HIST("h2RecMCDCAxySecMaterialPi"), track.pt(), track.dcaXY()); + } + continue; + } + + pionTracksMcReco(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi(), track.hasTOF()); + } + } + + PROCESS_SWITCH(PionTrackProducer, processMCReco, "Process function to select pion tracks in MCReco w MC truth", false); +}; + +struct EventSelectionProducer { // Produce the table with the event selection information - Produces phimesonSelection; + Produces phiStrangeEvtSelDataLike; + Produces phiStrangeEvtSelMcGen; - HistogramRegistry histos{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // Produces phiStrangeDefEvtSelDataLike; + // Produces phiStrangeDefEvtSelMcGen; - // Configurable for selection type - Configurable selectionType{"selectionType", 1, "Selection type: 0 - default selection only, 1 - default + phi meson selection"}; + /*Produces defaultSelectionData; + Produces defaultSelectionMcGen; + + Produces phimesonSelectionData; + Produces phimesonSelectionMcGen;*/ + + HistogramRegistry histos{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for event selection Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; @@ -326,13 +825,6 @@ struct PhiMesonSelCollision { histos.add("hMultiplicityPercentWPhi", "Multiplicity Percentile in Events with a Phi Candidate", kTH1F, {multAxis}); histos.add("h2VertexZvsMult", "Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); histos.add("h2VertexZvsMultWPhi", "Vertex Z vs Multiplicity Percentile with a Phi Candidate", kTH2F, {vertexZAxis, binnedmultAxis}); - - // Phi's daughter tracks information - /*histos.add("hEta", "Eta of Kaon candidates", kTH1F, {{100, -1.0f, 1.0f}}); - histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); - histos.add("h2DauTracksPhiDCAxy", "DCAxy distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - histos.add("h2DauTracksPhiDCAz", "DCAz distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}});*/ } // Default event selection @@ -433,30 +925,65 @@ struct PhiMesonSelCollision { return true; } - void processData(SelCollisions::iterator const& collision, aod::PhimesonCandidates const& phiCandidates) + // Default event selection + void processData(SelCollisions::iterator const& collision) + { + // phiStrangeDefEvtSelDataLike(defaultEventSelection(collision)); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), false); + // defaultSelectionData(defaultEventSelection(collision), false); + } + + PROCESS_SWITCH(EventSelectionProducer, processData, "Process function to select default events in Data", true); + + void processMCReco(SimCollisions::iterator const& collision, MCCollisions const&) + { + // phiStrangeDefEvtSelDataLike(defaultEventSelection(collision)); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), false); + // defaultSelectionData(defaultEventSelection(collision)); + } + + PROCESS_SWITCH(EventSelectionProducer, processMCReco, "Process function to select default events in MCReco", false); + + void processMCGen(MCCollisions::iterator const&, aod::McParticles const& mcParticles) + { + + // phiStrangeDefEvtSelMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB)); + phiStrangeEvtSelMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB), false); + // defaultSelectionMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB)); + } + + PROCESS_SWITCH(EventSelectionProducer, processMCGen, "Process function to select default events in MCGen", false); + + // Default event selection + phi meson requirement + void processDataWPhi(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidatesData) { - phimesonSelection(defaultEventSelection(collision) && selectionType == 1 ? eventHasPhi(collision, phiCandidates) : true); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), eventHasPhi(collision, phiCandidatesData)); + // phimesonSelectionData(defaultEventSelection(collision) && eventHasPhi(collision, phiCandidatesData)); } - PROCESS_SWITCH(PhiMesonSelCollision, processData, "Process function to select events with Phi mesons in Data", true); + PROCESS_SWITCH(EventSelectionProducer, processDataWPhi, "Process function to select events with Phi mesons in Data", false); - void processMCReco(SimCollisions::iterator const& collision, MCCollisions const&, aod::PhimesonCandidates const& phiCandidates) + void processMCRecoWPhi(SimCollisions::iterator const& collision, MCCollisions const&, aod::PhimesonCandidatesData const& phiCandidatesData) { - phimesonSelection(defaultEventSelection(collision) && selectionType == 1 ? eventHasPhi(collision, phiCandidates) : true); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), eventHasPhi(collision, phiCandidatesData)); + // phimesonSelectionData(defaultEventSelection(collision) && eventHasPhi(collision, phiCandidatesData)); } - PROCESS_SWITCH(PhiMesonSelCollision, processMCReco, "Process function to select events with Phi mesons in MCReco", false); + PROCESS_SWITCH(EventSelectionProducer, processMCRecoWPhi, "Process function to select events with Phi mesons in MCReco", false); - void processMCGen(MCCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, aod::PhimesonCandidates const& phiCandidates) + void processMCGenWPhi(MCCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, aod::PhimesonCandidatesMcGen const& phiCandidatesMcGen) { - phimesonSelection(pwglf::isINELgt0mc(mcParticles, pdgDB) && selectionType == 1 ? eventHasPhi(mcCollision, phiCandidates) : true); + phiStrangeEvtSelMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB), eventHasPhi(mcCollision, phiCandidatesMcGen)); + // phimesonSelectionMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB) && eventHasPhi(mcCollision, phiCandidatesMcGen)); } - PROCESS_SWITCH(PhiMesonSelCollision, processMCGen, "Process function to select events with Phi mesons in MCGen", false); + PROCESS_SWITCH(EventSelectionProducer, processMCGenWPhi, "Process function to select events with Phi mesons in MCGen", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx index 973fef69a8b..339088a311c 100644 --- a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx +++ b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx @@ -20,6 +20,8 @@ // gianni.shigeru.setoue.liveraro@cern.ch // +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGLF/DataModel/LFSigmaTables.h" #include "PWGLF/DataModel/LFStrangenessMLTables.h" #include "PWGLF/DataModel/LFStrangenessPIDTables.h" @@ -31,7 +33,6 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" @@ -44,10 +45,8 @@ #include "Math/Vector3D.h" #include -#include #include #include -#include #include #include @@ -55,6 +54,7 @@ #include #include #include +#include #include using namespace o2; @@ -67,8 +67,10 @@ using V0DerivedMCDatas = soa::Join; using V0TOFDerivedMCDatas = soa::Join; -static const std::vector DirList = {"V0BeforeSel", "PhotonSel", "LambdaSel"}; -; +using EMCalMCClusters = soa::Join; + +static const std::vector DirList = {"V0BeforeSel", "PhotonSel", "LambdaSel", "KShortSel"}; +static const std::vector DirList2 = {"EMCalPhotonBeforeSel", "EMCalPhotonSel"}; struct sigma0builder { Service ccdb; @@ -76,7 +78,6 @@ struct sigma0builder { //___________________________________________________ // KStar Specific - Produces kstarcores; // kstar candidates info for analysis Produces kshortExtras; // lambdas from sigma0 candidates info Produces kstarPhotonExtras; // photons from kstar candidates info @@ -87,15 +88,14 @@ struct sigma0builder { //__________________________________________________ // Sigma0 specific - Produces sigmaIndices; // references V0Cores from sigma0Gens - Produces sigma0cores; // sigma0 candidates info for analysis - Produces sigmaPhotonExtras; // photons from sigma0 candidates info - Produces sigmaLambdaExtras; // lambdas from sigma0 candidates info - Produces sigma0CollRefs; // references collisions from Sigma0Cores - Produces sigma0mccores; // Reco sigma0 MC properties - Produces sigma0mclabel; // Link of reco sigma0 to mcparticles - Produces sigma0Gens; // Generated sigma0s - Produces sigma0GenCollRefs; // references collisions from sigma0Gens[ + Produces sigma0cores; // sigma0 candidates info for analysis + Produces sigmaPhotonExtras; // photons from sigma0 candidates info + Produces sigmaEmCalPhotonExtras; // EMCAL photons from sigma0 candidates info + Produces sigmaLambdaExtras; // lambdas from sigma0 candidates info + Produces sigma0CollRefs; // references collisions from Sigma0Cores + Produces sigma0mccores; // Reco sigma0 MC properties + Produces sigma0Gens; // Generated sigma0s + Produces sigma0GenCollRefs; // references collisions from sigma0Gens //__________________________________________________ // Pi0 specific @@ -121,6 +121,7 @@ struct sigma0builder { Configurable fFillNoSelV0Histos{"fFillNoSelV0Histos", false, "Fill QA histos for input V0s."}; Configurable fFillSelPhotonHistos{"fFillSelPhotonHistos", true, "Fill QA histos for sel photons."}; Configurable fFillSelLambdaHistos{"fFillSelLambdaHistos", true, "Fill QA histos for sel lambdas."}; + Configurable fFillSelKShortHistos{"fFillSelKShortHistos", true, "Fill QA histos for sel kshorts."}; Configurable doAssocStudy{"doAssocStudy", false, "Do v0 to collision association study."}; Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; @@ -161,8 +162,13 @@ struct sigma0builder { Configurable minIR{"minIR", -1, "minimum IR collisions"}; Configurable maxIR{"maxIR", -1, "maximum IR collisions"}; + Configurable fSkipEmptyEMCal{"fSkipEmptyEMCal", true, "Flag to skip events without EMCal clusters"}; + } eventSelections; + // Photon Source + // Configurable fUsePCMPhotons{"fUsePCMPhotons", true, "Use PCM Photons for sigma0/kstar reconstruction. If False, EMCal photons are used instead."}; + // Tables to fill Configurable fillPi0Tables{"fillPi0Tables", false, "fill pi0 tables for QA"}; Configurable fillSigma0Tables{"fillSigma0Tables", true, "fill sigma0 tables for analysis"}; @@ -178,7 +184,7 @@ struct sigma0builder { std::string prefix = "lambdaSelections"; // JSON group name Configurable Lambda_MLThreshold{"Lambda_MLThreshold", 0.1, "Decision Threshold value to select lambdas"}; Configurable AntiLambda_MLThreshold{"AntiLambda_MLThreshold", 0.1, "Decision Threshold value to select antilambdas"}; - Configurable doMCAssociation{"doMCAssociation", false, "if MC, select true lambda/alambdas only"}; + Configurable doMCAssociation{"doMCAssociation", false, "if MC, select true lambda/alambdas only"}; Configurable LambdaMinDCANegToPv{"LambdaMinDCANegToPv", .05, "min DCA Neg To PV (cm)"}; Configurable LambdaMinDCAPosToPv{"LambdaMinDCAPosToPv", .05, "min DCA Pos To PV (cm)"}; Configurable LambdaMaxDCAV0Dau{"LambdaMaxDCAV0Dau", 2.5, "Max DCA V0 Daughters (cm)"}; @@ -207,7 +213,7 @@ struct sigma0builder { struct : ConfigurableGroup { std::string prefix = "photonSelections"; // JSON group name Configurable Gamma_MLThreshold{"Gamma_MLThreshold", 0.1, "Decision Threshold value to select gammas"}; - Configurable doMCAssociation{"doMCAssociation", false, "if MC, select true photons only"}; + Configurable doMCAssociation{"doMCAssociation", false, "if MC, select true photons only"}; Configurable Photonv0TypeSel{"Photonv0TypeSel", 7, "select on a certain V0 type (leave negative if no selection desired)"}; Configurable PhotonMinDCADauToPv{"PhotonMinDCADauToPv", 0.0, "Min DCA daughter To PV (cm)"}; Configurable PhotonMaxDCAV0Dau{"PhotonMaxDCAV0Dau", 3.5, "Max DCA V0 Daughters (cm)"}; @@ -232,15 +238,47 @@ struct sigma0builder { Configurable PhotonPhiMax2{"PhotonPhiMax2", -1, "Phi min value to reject photons, region 2 (leave negative if no selection desired)"}; } photonSelections; - /// KShort criteria: - Configurable V0Rapidity{"V0Rapidity", 0.5, "v0 rapidity"}; - Configurable K0ShortDauPseudoRap{"K0SDauPseudoRap", 1.5, "Max pseudorapidity of daughter tracks"}; - Configurable K0ShortMinDCANegToPv{"K0SMinDCANegToPv", 0.0, "min DCA Neg To PV (cm)"}; - Configurable K0ShortMinDCAPosToPv{"K0SMinDCAPosToPv", 0.0, "min DCA Pos To PV (cm)"}; - Configurable K0ShortMaxDCAV0Dau{"K0SMaxDCAV0Dau", 3.5, "Max DCA V0 Daughters (cm)"}; - Configurable K0ShortMinv0radius{"K0SMinv0radius", 0.0, "Min V0 radius (cm)"}; - Configurable K0ShortMaxv0radius{"K0SMaxv0radius", 60, "Max V0 radius (cm)"}; - Configurable K0ShortWindow{"K0SWindow", 0.1, "Mass window around expected (in GeV/c2)"}; + //// Photon criteria: + struct : ConfigurableGroup { + std::string prefix = "EMCalPhotonSelections"; // JSON group name + Configurable definition{"definition", 13, "Cluster definitions to be accepted (e.g. 13 for kV3MostSplitLowSeed)"}; + Configurable MinCells{"MinCells", 1, "Min number of cells in cluster"}; + Configurable MinEnergy{"MinEnergy", 0.0, "Minimum energy of selected clusters (GeV)"}; + Configurable MaxEnergy{"MaxEnergy", 5, "Max energy of selected clusters (GeV)"}; + Configurable MaxEta{"MaxEta", 1.0, "Max absolute cluster Eta"}; + Configurable MinTime{"MinTime", -50, "Minimum time of selected clusters (ns)"}; + Configurable MaxTime{"MaxTime", 50, "Max time of selected clusters (ns)"}; + Configurable RemoveExotic{"RemoveExotic", false, "Flag to enable the removal of exotic clusters"}; + Configurable MinM02{"MinM02", -1., "Minimum shower shape long axis"}; + Configurable MaxM02{"MaxM02", 5., "Max shower shape long axis"}; + + } EMCalPhotonSelections; + + // KShort criteria: + struct : ConfigurableGroup { + std::string prefix = "kshortSelections"; // JSON group name + Configurable KShort_MLThreshold{"KShort_MLThreshold", 0.1, "Decision Threshold value to select kshorts"}; + Configurable doMCAssociation{"doMCAssociation", false, "if MC, select true kshorts only"}; + Configurable KShortMinDCANegToPv{"KShortMinDCANegToPv", .05, "min DCA Neg To PV (cm)"}; + Configurable KShortMinDCAPosToPv{"KShortMinDCAPosToPv", .05, "min DCA Pos To PV (cm)"}; + Configurable KShortMaxDCAV0Dau{"KShortMaxDCAV0Dau", 2.5, "Max DCA V0 Daughters (cm)"}; + Configurable KShortMinv0radius{"KShortMinv0radius", 0.0, "Min V0 radius (cm)"}; + Configurable KShortMaxv0radius{"KShortMaxv0radius", 40, "Max V0 radius (cm)"}; + Configurable KShortMinv0cospa{"KShortMinv0cospa", 0.95, "Min V0 CosPA"}; + Configurable KShortMaxLifeTime{"KShortMaxLifeTime", 20, "Max lifetime"}; + Configurable KShortWindow{"KShortWindow", 0.015, "Mass window around expected (in GeV/c2). Leave negative to disable"}; + Configurable KShortMinRapidity{"KShortMinRapidity", -0.5, "v0 min rapidity"}; + Configurable KShortMaxRapidity{"KShortMaxRapidity", 0.5, "v0 max rapidity"}; + Configurable KShortDauEtaMin{"KShortDauEtaMin", -0.8, "Min pseudorapidity of daughter tracks"}; + Configurable KShortDauEtaMax{"KShortDauEtaMax", 0.8, "Max pseudorapidity of daughter tracks"}; + Configurable KShortMinZ{"KShortMinZ", -240, "Min kshort decay point z value (cm)"}; + Configurable KShortMaxZ{"KShortMaxZ", 240, "Max kshort decay point z value (cm)"}; + Configurable KShortMinTPCCrossedRows{"KShortMinTPCCrossedRows", 50, "Min daughter TPC Crossed Rows"}; + Configurable KShortMinITSclusters{"KShortMinITSclusters", 1, "minimum ITS clusters"}; + Configurable KShortRejectPosITSafterburner{"KShortRejectPosITSafterburner", false, "reject positive track formed out of afterburner ITS tracks"}; + Configurable KShortRejectNegITSafterburner{"KShortRejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; + Configurable KShortArmenterosCoefficient{"KShortArmenterosCoefficient", 0.2, "Armenteros-Podolanski coefficient to reject lambdas"}; + } kshortSelections; // KStar criteria: Configurable KStarWindow{"KStarWindow", 0.1, "Mass window around expected (in GeV/c2)"}; @@ -277,6 +315,7 @@ struct sigma0builder { ConfigurableAxis axisPhotonMass{"axisPhotonMass", {200, 0.0f, 0.3f}, "M_{#Gamma}"}; ConfigurableAxis axisK0SMass{"axisK0SMass", {200, 0.4f, 0.6f}, "M_{K^{0}}"}; ConfigurableAxis axisKStarMass{"axisKStarMass", {500, 0.6f, 1.6f}, "M_{K^{*}} (GeV/c^{2})"}; + // 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"}; @@ -296,19 +335,26 @@ struct sigma0builder { ConfigurableAxis axisRapidity{"axisRapidity", {100, -2.0f, 2.0f}, "Rapidity"}; ConfigurableAxis axisCandSel{"axisCandSel", {15, 0.5f, +15.5f}, "Candidate Selection"}; ConfigurableAxis axisIRBinning{"axisIRBinning", {151, -10, 1500}, "Binning for the interaction rate (kHz)"}; + ConfigurableAxis axisLifetime{"axisLifetime", {200, 0, 50}, "Lifetime"}; - // For manual sliceBy (necessary to calculate the correction factors) - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + // EMCal-specifc + ConfigurableAxis axisClrDefinition{"axisClrDefinition", {51, -0.5, 50.5}, "Cluster Definition"}; + ConfigurableAxis axisClrNCells{"axisClrNCells", {25, 0.0, 25}, "N cells per cluster"}; + ConfigurableAxis axisClrEnergy{"axisClrEnergy", {400, 0.0, 10}, "Energy per cluster"}; + ConfigurableAxis axisClrTime{"axisClrTime", {300, -30.0, 30.0}, "cluster time (ns)"}; + ConfigurableAxis axisClrShape{"axisClrShape", {100, 0.0, 1.0}, "cluster shape"}; void init(InitContext const&) { LOGF(info, "Initializing now: cross-checking correctness..."); if (doprocessRealData + doprocessRealDataWithTOF + + doprocessRealDataWithEMCal + doprocessMonteCarlo + doprocessMonteCarloWithTOF + - doprocessPhotonLambdaQA + - doprocessPhotonLambdaMCQA > + doprocessMonteCarloWithEMCal + + doprocessV0QA + + doprocessV0MCQA > 1) { LOGF(fatal, "You have enabled more than one process function. Please check your configuration! Aborting now."); } @@ -355,35 +401,13 @@ struct sigma0builder { } } - histos.add("K0ShortSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); - histos.get(HIST("K0ShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); - histos.get(HIST("K0ShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "K0Short Mass Cut"); - histos.get(HIST("K0ShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "K0Short Eta/Y Cut"); - histos.get(HIST("K0ShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(4, "K0Short DCAToPV Cut"); - histos.get(HIST("K0ShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(5, "K0Short Radius Cut"); - histos.get(HIST("K0ShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(6, "K0Short DCADau Cut"); - - histos.add("K0ShortSel/hK0ShortMass", "hK0ShortMass", kTH1F, {axisK0SMass}); - histos.add("K0ShortSel/hK0ShortNegEta", "hK0ShortNegEta", kTH1F, {axisRapidity}); - histos.add("K0ShortSel/hK0ShortPosEta", "hK0ShortPosEta", kTH1F, {axisRapidity}); - histos.add("K0ShortSel/hK0ShortY", "hK0ShortY", kTH1F, {axisRapidity}); - histos.add("K0ShortSel/hK0ShortDCANegToPV", "hK0ShortDCANegToPV", kTH1F, {axisDCAtoPV}); - histos.add("K0ShortSel/hK0ShortDCAPosToPV", "hK0ShortDCAPosToPV", kTH1F, {axisDCAtoPV}); - histos.add("K0ShortSel/hK0ShortDCADau", "hK0ShortDCADau", kTH1F, {axisDCAdau}); - histos.add("K0ShortSel/hK0ShortRadius", "hK0ShortRadius", kTH1F, {axisRadius}); - histos.add("K0ShortSel/h3dK0ShortMass", "h3dK0ShortMass", kTH3D, {axisCentrality, axisPt, axisK0SMass}); - - histos.add("KStarSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); - histos.get(HIST("KStarSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); - histos.get(HIST("KStarSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "KStar Mass Window"); - histos.get(HIST("KStarSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "KStar Y Window"); - - histos.add("KStarSel/hKStarMassSelected", "hKStarMassSelected", kTH1F, {axisKStarMass}); + bool fUsePCMPhoton = !doprocessRealDataWithEMCal && !doprocessMonteCarloWithEMCal && !doprocessPCMVsEMCalQA; for (const auto& histodir : DirList) { if ((histodir == "V0BeforeSel" && !fFillNoSelV0Histos) || - (histodir == "PhotonSel" && !fFillSelPhotonHistos) || - (histodir == "LambdaSel" && !fFillSelLambdaHistos)) { + (histodir == "PhotonSel" && !fFillSelPhotonHistos && !fUsePCMPhoton) || + (histodir == "LambdaSel" && !fFillSelLambdaHistos) || + (histodir == "KShortSel" && !fFillSelKShortHistos)) { continue; } @@ -414,31 +438,71 @@ struct sigma0builder { histos.add(histodir + "/hPhotonMass", "hPhotonMass", kTH1D, {axisPhotonMass}); histos.add(histodir + "/h2dMassPhotonVsK0S", "h2dMassPhotonVsK0S", kTH2D, {axisPhotonMass, axisK0SMass}); histos.add(histodir + "/h2dMassPhotonVsLambda", "h2dMassPhotonVsLambda", kTH2D, {axisPhotonMass, axisLambdaMass}); - histos.add(histodir + "/hLifeTime", "hLifeTime", kTH1D, {axisRapidity}); + histos.add(histodir + "/hLambdaLifeTime", "hLambdaLifeTime", kTH1D, {axisLifetime}); histos.add(histodir + "/hLambdaY", "hLambdaY", kTH1D, {axisRapidity}); histos.add(histodir + "/hLambdaMass", "hLambdaMass", kTH1D, {axisLambdaMass}); histos.add(histodir + "/hALambdaMass", "hALambdaMass", kTH1D, {axisLambdaMass}); histos.add(histodir + "/h2dMassLambdaVsK0S", "h2dMassLambdaVsK0S", kTH2D, {axisLambdaMass, axisK0SMass}); histos.add(histodir + "/h2dMassLambdaVsGamma", "h2dMassLambdaVsGamma", kTH2D, {axisLambdaMass, axisPhotonMass}); + histos.add(histodir + "/hKShortLifeTime", "hKShortLifeTime", kTH1D, {axisLifetime}); + histos.add(histodir + "/hKShortY", "hKShortY", kTH1D, {axisRapidity}); + histos.add(histodir + "/hKShortMass", "hKShortMass", kTH1D, {axisK0SMass}); + histos.add(histodir + "/h2dMassK0SvsLambda", "h2dMassK0SvsLambda", kTH2D, {axisK0SMass, axisLambdaMass}); + histos.add(histodir + "/h2dMassK0SVsGamma", "h2dMassK0SVsGamma", kTH2D, {axisK0SMass, axisPhotonMass}); if (histodir != "V0BeforeSel" && fFillV03DPositionHistos) // We dont want this for all reco v0s! histos.add(histodir + "/h3dV0XYZ", "h3dV0XYZ", kTH3D, {axisXY, axisXY, axisZ}); } - histos.add("PhotonSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "Mass"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "Y"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(4, "Neg Eta"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(5, "Pos Eta"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(6, "DCAToPV"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(7, "DCADau"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(8, "Radius"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(9, "Z"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(10, "CosPA"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(11, "Phi"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(12, "TPCCR"); - histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(13, "TPC NSigma"); + if (fUsePCMPhoton || doprocessPCMVsEMCalQA) { + histos.add("PhotonSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "Mass"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "Y"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(4, "Neg Eta"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(5, "Pos Eta"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(6, "DCAToPV"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(7, "DCADau"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(8, "Radius"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(9, "Z"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(10, "CosPA"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(11, "Phi"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(12, "TPCCR"); + histos.get(HIST("PhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(13, "TPC NSigma"); + + if (doprocessPCMVsEMCalQA) { + histos.add("EMCalPhotonSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "Definition"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "MinCell"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(4, "Energy"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(5, "Eta"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(6, "Time"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(7, "Exotic"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(8, "Shape"); + } + + } else { + for (const auto& histodir : DirList2) { + histos.add(histodir + "/hDefinition", "hDefinition", kTH1D, {axisClrDefinition}); + histos.add(histodir + "/h2dNCells", "h2dNCells", kTH2D, {axisPt, axisClrNCells}); + histos.add(histodir + "/h2dEnergy", "h2dEnergy", kTH2D, {axisPt, axisClrEnergy}); + histos.add(histodir + "/h2dEtaVsPhi", "h2dEtaVsPhi", kTH2D, {axisRapidity, axisPhi}); + histos.add(histodir + "/h2dTime", "h2dTime", kTH2D, {axisPt, axisClrTime}); + histos.add(histodir + "/hExotic", "hExotic", kTH1D, {{2, -0.5f, 1.5f}}); + histos.add(histodir + "/h2dShape", "h2dShape", kTH2D, {axisPt, axisClrShape}); + } + + histos.add("EMCalPhotonSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "Definition"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "MinCell"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(4, "Energy"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(5, "Eta"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(6, "Time"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(7, "Exotic"); + histos.get(HIST("EMCalPhotonSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(8, "Shape"); + } histos.add("LambdaSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); histos.get(HIST("LambdaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); @@ -456,14 +520,38 @@ struct sigma0builder { histos.get(HIST("LambdaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(13, "ITSNCls"); histos.get(HIST("LambdaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(14, "Lifetime"); - if (doprocessRealData || doprocessRealDataWithTOF || doprocessMonteCarlo || doprocessMonteCarloWithTOF) { + histos.add("KShortSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "Mass"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "Y"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(4, "Neg Eta"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(5, "Pos Eta"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(6, "DCAToPV"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(7, "Radius"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(8, "Z"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(9, "DCADau"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(10, "Armenteros"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(11, "CosPA"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(12, "TPCCR"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(13, "ITSNCls"); + histos.get(HIST("KShortSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(14, "Lifetime"); + + if (doprocessRealData || doprocessRealDataWithTOF || doprocessRealDataWithEMCal || doprocessMonteCarlo || doprocessMonteCarloWithTOF || doprocessMonteCarloWithEMCal) { histos.add("SigmaSel/hSigma0DauDeltaIndex", "hSigma0DauDeltaIndex", kTH1F, {{100, -49.5f, 50.5f}}); histos.add("SigmaSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); histos.get(HIST("SigmaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); histos.get(HIST("SigmaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "Sigma Mass Window"); histos.get(HIST("SigmaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "Sigma Y Window"); + histos.add("SigmaSel/hSigmaMassBeforeSel", "hSigmaMassBeforeSel", kTH1F, {axisSigmaMass}); histos.add("SigmaSel/hSigmaMassSelected", "hSigmaMassSelected", kTH1F, {axisSigmaMass}); + + histos.add("KStarSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); + histos.get(HIST("KStarSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); + histos.get(HIST("KStarSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(2, "KStar Mass Window"); + histos.get(HIST("KStarSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(3, "KStar Y Window"); + + histos.add("KStarSel/hKStarMassSelected", "hKStarMassSelected", kTH1F, {axisKStarMass}); } if (doAssocStudy && (doprocessMonteCarlo || doprocessMonteCarloWithTOF)) { @@ -479,19 +567,58 @@ struct sigma0builder { } // MC - if (doprocessMonteCarlo || doprocessMonteCarloWithTOF) { + if (doprocessMonteCarlo || doprocessMonteCarloWithTOF || doprocessMonteCarloWithEMCal) { histos.add("MCQA/h2dPhotonNMothersVsPDG", "h2dPhotonNMothersVsPDG", kTHnSparseD, {{10, -0.5f, +9.5f}, {10001, -5000.5f, +5000.5f}}); histos.add("MCQA/h2dPhotonNMothersVsMCProcess", "h2dPhotonNMothersVsMCProcess", kTH2D, {{10, -0.5f, +9.5f}, {50, -0.5f, 49.5f}}); histos.add("MCQA/hPhotonMotherSize", "hPhotonMotherSize", kTH1D, {{10, -0.5f, +9.5f}}); histos.add("MCQA/hPhotonMCProcess", "hPhotonMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); histos.add("MCQA/hPhotonMotherMCProcess", "hPhotonMotherMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); + + // photons for kstar analysis + histos.add("MCQA/h2dPhoton_KShortNMothersVsPDG", "h2dPhoton_KShortNMothersVsPDG", kTHnSparseD, {{10, -0.5f, +9.5f}, {10001, -5000.5f, +5000.5f}}); + histos.add("MCQA/h2dPhoton_KShortNMothersVsMCProcess", "h2dPhoton_KShortNMothersVsMCProcess", kTH2D, {{10, -0.5f, +9.5f}, {50, -0.5f, 49.5f}}); + histos.add("MCQA/hPhoton_KShortMotherSize", "hPhoton_KShortMotherSize", kTH1D, {{10, -0.5f, +9.5f}}); + histos.add("MCQA/hPhoton_KShortMCProcess", "hPhoton_KShortMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); + histos.add("MCQA/hPhoton_KShortMotherMCProcess", "hPhoton_KShortMotherMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); + histos.add("MCQA/hLambdaMotherSize", "hLambdaMotherSize", kTH1D, {{10, -0.5f, +9.5f}}); histos.add("MCQA/hLambdaMCProcess", "hLambdaMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); histos.add("MCQA/hLambdaMotherMCProcess", "hLambdaMotherMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); + + histos.add("MCQA/hKShortMotherSize", "hKShortMotherSize", kTH1D, {{10, -0.5f, +9.5f}}); + histos.add("MCQA/hKShortMCProcess", "hKShortMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); + histos.add("MCQA/hKShortMotherMCProcess", "hKShortMotherMCProcess", kTH1D, {{50, -0.5f, 49.5f}}); + histos.add("MCQA/hSigma0MCCheck", "hSigma0MCCheck", kTH1D, {{4, -0.5f, +3.5f}}); + histos.add("MCQA/hKStarMCCheck", "hKStarMCCheck", kTH1D, {{4, -0.5f, +3.5f}}); + histos.add("MCQA/hNoV0MCCores", "hNoV0MCCores", kTH1D, {{4, -0.5f, +3.5f}}); } + if (doprocessPCMVsEMCalQA) { + histos.add("PhotonMCQA/hPCMPhotonMCpT", "hPCMPhotonMCpT", kTH1D, {axisPt}); + histos.add("PhotonMCQA/h2dPCMPhotonMCpTResolution", "h2dPCMPhotonMCpTResolution", kTH2D, {axisPt, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/hPCMSigma0PhotonMCpT", "hPCMSigma0PhotonMCpT", kTH1D, {axisPt}); + histos.add("PhotonMCQA/h2dPCMSigma0PhotonMCpTResolution", "h2dPCMSigma0PhotonMCpTResolution", kTH2D, {axisPt, {100, -2.0f, 2.0f}}); + + histos.add("PhotonMCQA/hEMCalPhotonMCpT", "hEMCalPhotonMCpT", kTH1D, {axisPt}); + histos.add("PhotonMCQA/h2dEMCalPhotonMCpTResolution", "h2dEMCalPhotonMCpTResolution", kTH2D, {axisPt, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalPhotonMCEnergyResolution", "h2dEMCalPhotonMCEnergyResolution", kTH2D, {axisClrEnergy, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalPhotonMCEtaResolution", "h2dEMCalPhotonMCEtaResolution", kTH2D, {axisRapidity, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalPhotonMCPhiResolution", "h2dEMCalPhotonMCPhiResolution", kTH2D, {axisPhi, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalPhotonMCFractionEnergy", "h2dEMCalPhotonMCFractionEnergy", kTH2D, {axisPt, {100, -1.0f, 1.0f}}); + + histos.add("PhotonMCQA/hEMCalSigma0PhotonMCpT", "hEMCalSigma0PhotonMCpT", kTH1D, {axisPt}); + histos.add("PhotonMCQA/h2dEMCalSigma0PhotonMCpTResolution", "h2dEMCalSigma0PhotonMCpTResolution", kTH2D, {axisPt, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalSigma0PhotonMCEnergyResolution", "h2dEMCalSigma0PhotonMCEnergyResolution", kTH2D, {axisClrEnergy, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalSigma0PhotonMCEtaResolution", "h2dEMCalSigma0PhotonMCEtaResolution", kTH2D, {axisRapidity, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalSigma0PhotonMCPhiResolution", "h2dEMCalSigma0PhotonMCPhiResolution", kTH2D, {axisPhi, {100, -2.0f, 2.0f}}); + histos.add("PhotonMCQA/h2dEMCalSigma0PhotonMCFractionEnergy", "h2dEMCalSigma0PhotonMCFractionEnergy", kTH2D, {axisPt, {100, -1.0f, 1.0f}}); + + histos.add("PhotonMCQA/hGenPhoton", "hGenPhoton", kTH1D, {axisPt}); + histos.add("PhotonMCQA/hGenSigma0Photon", "hGenSigma0Photon", kTH1D, {axisPt}); + } + if (doprocessGeneratedRun3 && genSelections.doQA) { // Pi0s @@ -575,61 +702,75 @@ struct sigma0builder { h2DGenKStarTypeVsProducedByGen->GetYaxis()->SetBinLabel(2, "Transport"); } - if (doprocessPhotonLambdaQA || doprocessPhotonLambdaMCQA) { + if (doprocessV0QA || doprocessV0MCQA) { // Event selection: - histos.add("PhotonLambdaQA/hEventCentrality", "hEventCentrality", kTH1D, {axisCentrality}); + histos.add("V0QA/hEventCentrality", "hEventCentrality", kTH1D, {axisCentrality}); // Photon part: - histos.add("PhotonLambdaQA/h3dPhotonMass", "h3dPhotonMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); - histos.add("PhotonLambdaQA/h3dYPhotonMass", "h3dYPhotonMass", kTH3D, {axisRapidity, axisPt, axisPhotonMass}); - histos.add("PhotonLambdaQA/h3dYPhotonRadius", "h3dYPhotonRadius", kTH3D, {axisRapidity, axisPt, axisRadius}); + histos.add("V0QA/h3dPhotonMass", "h3dPhotonMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); + histos.add("V0QA/h3dYPhotonMass", "h3dYPhotonMass", kTH3D, {axisRapidity, axisPt, axisPhotonMass}); + histos.add("V0QA/h3dYPhotonRadius", "h3dYPhotonRadius", kTH3D, {axisRapidity, axisPt, axisRadius}); - histos.add("PhotonLambdaQA/h3dTruePhotonMass", "h3dTruePhotonMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); - histos.add("PhotonLambdaQA/h2dTrueSigma0PhotonMass", "h2dTrueSigma0PhotonMass", kTH2D, {axisPt, axisPhotonMass}); + histos.add("V0QA/h3dTruePhotonMass", "h3dTruePhotonMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); + histos.add("V0QA/h2dTrueSigma0PhotonMass", "h2dTrueSigma0PhotonMass", kTH2D, {axisPt, axisPhotonMass}); + histos.add("V0QA/h2dTrueKStarPhotonMass", "h2dTrueKStarPhotonMass", kTH2D, {axisPt, axisPhotonMass}); // Lambda part: - histos.add("PhotonLambdaQA/h3dLambdaMass", "h3dLambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); - histos.add("PhotonLambdaQA/h3dTrueLambdaMass", "h3dTrueLambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); - histos.add("PhotonLambdaQA/h3dYLambdaMass", "h3dYLambdaMass", kTH3D, {axisRapidity, axisPt, axisLambdaMass}); - histos.add("PhotonLambdaQA/h3dYRLambdaMass", "h3dYRLambdaMass", kTH3D, {axisRapidity, axisRadius, axisLambdaMass}); + histos.add("V0QA/h3dLambdaMass", "h3dLambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("V0QA/h3dTrueLambdaMass", "h3dTrueLambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("V0QA/h3dYLambdaMass", "h3dYLambdaMass", kTH3D, {axisRapidity, axisPt, axisLambdaMass}); + histos.add("V0QA/h3dYRLambdaMass", "h3dYRLambdaMass", kTH3D, {axisRapidity, axisRadius, axisLambdaMass}); - histos.add("PhotonLambdaQA/h2dTrueSigma0LambdaMass", "h2dTrueSigma0LambdaMass", kTH2D, {axisPt, axisLambdaMass}); + histos.add("V0QA/h2dTrueSigma0LambdaMass", "h2dTrueSigma0LambdaMass", kTH2D, {axisPt, axisLambdaMass}); // AntiLambda part: - histos.add("PhotonLambdaQA/h3dALambdaMass", "h3dALambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); - histos.add("PhotonLambdaQA/h3dTrueALambdaMass", "h3dTrueALambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); - histos.add("PhotonLambdaQA/h3dYALambdaMass", "h3dYALambdaMass", kTH3D, {axisRapidity, axisPt, axisLambdaMass}); - histos.add("PhotonLambdaQA/h3dYRALambdaMass", "h3dYRALambdaMass", kTH3D, {axisRapidity, axisRadius, axisLambdaMass}); - - histos.add("PhotonLambdaQA/h2dTrueASigma0ALambdaMass", "h2dTrueASigma0ALambdaMass", kTH2D, {axisPt, axisLambdaMass}); + histos.add("V0QA/h3dALambdaMass", "h3dALambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("V0QA/h3dTrueALambdaMass", "h3dTrueALambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("V0QA/h3dYALambdaMass", "h3dYALambdaMass", kTH3D, {axisRapidity, axisPt, axisLambdaMass}); + histos.add("V0QA/h3dYRALambdaMass", "h3dYRALambdaMass", kTH3D, {axisRapidity, axisRadius, axisLambdaMass}); + + histos.add("V0QA/h2dTrueASigma0ALambdaMass", "h2dTrueASigma0ALambdaMass", kTH2D, {axisPt, axisLambdaMass}); + + // KShort part: + histos.add("V0QA/h3dKShortMass", "h3dKShortMass", kTH3D, {axisCentrality, axisPt, axisK0SMass}); + histos.add("V0QA/h3dTrueKShortMass", "h3dTrueKShortMass", kTH3D, {axisCentrality, axisPt, axisK0SMass}); + histos.add("V0QA/h3dYKShortMass", "h3dYKShortMass", kTH3D, {axisRapidity, axisPt, axisK0SMass}); + histos.add("V0QA/h3dYRKShortMass", "h3dYRKShortMass", kTH3D, {axisRapidity, axisRadius, axisK0SMass}); + histos.add("V0QA/h2dTrueKStarKShortMass", "h2dTrueKStarKShortMass", kTH2D, {axisPt, axisK0SMass}); } - if (doprocessPhotonLambdaGenerated) { + if (doprocessV0Generated) { + + histos.add("V0QA/hGenEvents", "hGenEvents", kTH2D, {{axisNch}, {2, -0.5f, +1.5f}}); + histos.get(HIST("V0QA/hGenEvents"))->GetYaxis()->SetBinLabel(1, "All gen. events"); + histos.get(HIST("V0QA/hGenEvents"))->GetYaxis()->SetBinLabel(2, "Gen. with at least 1 rec. events"); + histos.add("V0QA/hGenEventCentrality", "hGenEventCentrality", kTH1D, {{101, 0.0f, 101.0f}}); + + histos.add("V0QA/hCentralityVsNcoll_beforeEvSel", "hCentralityVsNcoll_beforeEvSel", kTH2D, {axisCentrality, {50, -0.5f, 49.5f}}); + histos.add("V0QA/hCentralityVsNcoll_afterEvSel", "hCentralityVsNcoll_afterEvSel", kTH2D, {axisCentrality, {50, -0.5f, 49.5f}}); + + histos.add("V0QA/hCentralityVsMultMC", "hCentralityVsMultMC", kTH2D, {{101, 0.0f, 101.0f}, axisNch}); + histos.add("V0QA/hEventPVzMC", "hEventPVzMC", kTH1D, {{100, -20.0f, +20.0f}}); + histos.add("V0QA/hCentralityVsPVzMC", "hCentralityVsPVzMC", kTH2D, {{101, 0.0f, 101.0f}, {100, -20.0f, +20.0f}}); - histos.add("PhotonLambdaQA/hGenEvents", "hGenEvents", kTH2D, {{axisNch}, {2, -0.5f, +1.5f}}); - histos.get(HIST("PhotonLambdaQA/hGenEvents"))->GetYaxis()->SetBinLabel(1, "All gen. events"); - histos.get(HIST("PhotonLambdaQA/hGenEvents"))->GetYaxis()->SetBinLabel(2, "Gen. with at least 1 rec. events"); - histos.add("PhotonLambdaQA/hGenEventCentrality", "hGenEventCentrality", kTH1D, {{101, 0.0f, 101.0f}}); + histos.add("V0QA/h2dGenPhoton", "h2dGenPhoton", kTH2D, {axisCentrality, axisPt}); + histos.add("V0QA/h2dGenLambda", "h2dGenLambda", kTH2D, {axisCentrality, axisPt}); + histos.add("V0QA/h2dGenAntiLambda", "h2dGenAntiLambda", kTH2D, {axisCentrality, axisPt}); - histos.add("PhotonLambdaQA/hCentralityVsNcoll_beforeEvSel", "hCentralityVsNcoll_beforeEvSel", kTH2D, {axisCentrality, {50, -0.5f, 49.5f}}); - histos.add("PhotonLambdaQA/hCentralityVsNcoll_afterEvSel", "hCentralityVsNcoll_afterEvSel", kTH2D, {axisCentrality, {50, -0.5f, 49.5f}}); + histos.add("V0QA/h2dGenPhotonVsMultMC_RecoedEvt", "h2dGenPhotonVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); + histos.add("V0QA/h2dGenLambdaVsMultMC_RecoedEvt", "h2dGenLambdaVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); + histos.add("V0QA/h2dGenAntiLambdaVsMultMC_RecoedEvt", "h2dGenAntiLambdaVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/hCentralityVsMultMC", "hCentralityVsMultMC", kTH2D, {{101, 0.0f, 101.0f}, axisNch}); - histos.add("PhotonLambdaQA/hEventPVzMC", "hEventPVzMC", kTH1D, {{100, -20.0f, +20.0f}}); - histos.add("PhotonLambdaQA/hCentralityVsPVzMC", "hCentralityVsPVzMC", kTH2D, {{101, 0.0f, 101.0f}, {100, -20.0f, +20.0f}}); + histos.add("V0QA/h2dGenPhotonVsMultMC", "h2dGenPhotonVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("V0QA/h2dGenLambdaVsMultMC", "h2dGenLambdaVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("V0QA/h2dGenAntiLambdaVsMultMC", "h2dGenAntiLambdaVsMultMC", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/h2dGenPhoton", "h2dGenPhoton", kTH2D, {axisCentrality, axisPt}); - histos.add("PhotonLambdaQA/h2dGenLambda", "h2dGenLambda", kTH2D, {axisCentrality, axisPt}); - histos.add("PhotonLambdaQA/h2dGenAntiLambda", "h2dGenAntiLambda", kTH2D, {axisCentrality, axisPt}); + histos.add("V0QA/h2dGenKShort", "h2dGenKShort", kTH2D, {axisCentrality, axisPt}); - histos.add("PhotonLambdaQA/h2dGenPhotonVsMultMC_RecoedEvt", "h2dGenPhotonVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/h2dGenLambdaVsMultMC_RecoedEvt", "h2dGenLambdaVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/h2dGenAntiLambdaVsMultMC_RecoedEvt", "h2dGenAntiLambdaVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); + histos.add("V0QA/h2dGenKShortVsMultMC_RecoedEvt", "h2dGenKShortVsMultMC_RecoedEvt", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/h2dGenPhotonVsMultMC", "h2dGenPhotonVsMultMC", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/h2dGenLambdaVsMultMC", "h2dGenLambdaVsMultMC", kTH2D, {axisNch, axisPt}); - histos.add("PhotonLambdaQA/h2dGenAntiLambdaVsMultMC", "h2dGenAntiLambdaVsMultMC", kTH2D, {axisNch, axisPt}); + histos.add("V0QA/h2dGenKShortVsMultMC", "h2dGenKShortVsMultMC", kTH2D, {axisNch, axisPt}); } // inspect histogram sizes, please @@ -654,6 +795,10 @@ struct sigma0builder { bool fIsV01Primary = false; bool fIsV02Primary = false; bool fV0PairProducedByGenerator = false; + int V01PDGCodePos = 0; + int V02PDGCodePos = 0; + int V01PDGCodeNeg = 0; + int V02PDGCodeNeg = 0; int V01PDGCode = 0; int V02PDGCode = 0; int V01PDGCodeMother = 0; @@ -669,6 +814,7 @@ struct sigma0builder { float V02MCpy = -999.f; float V02MCpz = -999.f; float V0PairMCRadius = -999.f; + float EMCalClusterAmplitude = -999.f; }; // ______________________________________________________ @@ -728,7 +874,8 @@ struct sigma0builder { info.DCADau = (cross.Mag2() > 0) ? std::abs(posdiff.Dot(cross)) / cross.R() : 999.f; info.CosPA = v01momentumNorm.Dot(v02momentumNorm); - if (d < 1e-5f) { // Parallel or nearly parallel lines + float Min_threshold = 1e-5f; // Threshold to consider lines as parallel, can be tuned + if (d < Min_threshold) { // Parallel or nearly parallel lines info.X = info.Y = info.Z = 0.f; // should we use another dummy value? Perhaps 999.f? return info; } @@ -758,6 +905,10 @@ struct sigma0builder { if ((v01MC.pdgCode() == PDG_t::kGamma) && (v01MC.pdgCodeMother() == PDG_t::kSigma0) && (v02MC.pdgCode() == PDG_t::kLambda0) && (v02MC.pdgCodeMother() == PDG_t::kSigma0) && (v01.motherMCPartId() == v02.motherMCPartId())) fIsSigma0 = true; + bool fIsKStar = false; + if ((v01MC.pdgCode() == PDG_t::kGamma) && (v01MC.pdgCodeMother() == o2::constants::physics::Pdg::kK0Star892) && (v02MC.pdgCode() == PDG_t::kK0Short) && (v02MC.pdgCodeMother() == o2::constants::physics::Pdg::kK0Star892) && (v01.motherMCPartId() == v02.motherMCPartId())) + fIsKStar = true; + // Check collision assignment if (collision.has_straMCCollision()) { auto MCCollision = collision.template straMCCollision_as>(); @@ -776,6 +927,10 @@ struct sigma0builder { // MC association info MCinfo.fIsV01Primary = v01MC.isPhysicalPrimary(); MCinfo.fIsV02Primary = v02MC.isPhysicalPrimary(); + MCinfo.V01PDGCodePos = v01MC.pdgCodePositive(); + MCinfo.V01PDGCodeNeg = v01MC.pdgCodeNegative(); + MCinfo.V02PDGCodePos = v02MC.pdgCodePositive(); + MCinfo.V02PDGCodeNeg = v02MC.pdgCodeNegative(); MCinfo.V01PDGCode = v01MC.pdgCode(); MCinfo.V02PDGCode = v02MC.pdgCode(); MCinfo.V01PDGCodeMother = v01MC.pdgCodeMother(); @@ -790,8 +945,8 @@ struct sigma0builder { auto const& MCMothersList_v02 = MCParticle_v02.template mothers_as(); if (!MCMothersList_v01.empty() && !MCMothersList_v02.empty()) { // Are there mothers? - auto const& MCMother_v01 = MCMothersList_v01.front(); // First mother - auto const& MCMother_v02 = MCMothersList_v02.front(); // First mother + auto const& MCMother_v01 = MCMothersList_v01.front(); // First mother + auto const& MCMother_v02 = MCMothersList_v02.front(); // First mother if (MCMother_v01.globalIndex() == MCMother_v02.globalIndex()) { // Is it the same mother? @@ -833,6 +988,30 @@ struct sigma0builder { } } + // Parenthood check for kstar-like candidate + if (MCParticle_v01.pdgCode() == PDG_t::kGamma && TMath::Abs(MCParticle_v02.pdgCode()) == PDG_t::kK0Short) { + for (const auto& mother1 : MCMothersList_v01) { // Photon mothers + histos.fill(HIST("MCQA/h2dPhoton_KShortNMothersVsPDG"), MCMothersList_v01.size(), mother1.pdgCode()); + histos.fill(HIST("MCQA/h2dPhoton_KShortNMothersVsMCProcess"), MCMothersList_v01.size(), mother1.getProcess()); + + for (const auto& mother2 : MCMothersList_v02) { // Lambda mothers + if (mother1.globalIndex() == mother2.globalIndex()) { // Match found: same physical mother + + if (mother1.globalIndex() == MCMother_v01.globalIndex()) { + histos.fill(HIST("MCQA/hPhoton_KShortMotherSize"), MCMothersList_v01.size()); + histos.fill(HIST("MCQA/hPhoton_KShortMCProcess"), MCParticle_v01.getProcess()); + histos.fill(HIST("MCQA/hPhoton_KShortMotherMCProcess"), mother1.getProcess()); + } + + if (mother2.globalIndex() == MCMother_v02.globalIndex()) { + histos.fill(HIST("MCQA/hKShortMotherSize"), MCMothersList_v02.size()); + histos.fill(HIST("MCQA/hKShortMCProcess"), MCParticle_v02.getProcess()); + histos.fill(HIST("MCQA/hKShortMotherMCProcess"), mother2.getProcess()); + } + } + } + } + } // Check association correctness if (fIsSigma0 && (MCinfo.V0PairPDGCode == PDG_t::kSigma0)) histos.fill(HIST("MCQA/hSigma0MCCheck"), 1); // match @@ -840,9 +1019,180 @@ struct sigma0builder { histos.fill(HIST("MCQA/hSigma0MCCheck"), 2); // mismatch if (!fIsSigma0 && (MCinfo.V0PairPDGCode == PDG_t::kSigma0)) histos.fill(HIST("MCQA/hSigma0MCCheck"), 3); // mismatch + + // Check association correctness + if (fIsKStar && (MCinfo.V0PairPDGCode == o2::constants::physics::Pdg::kK0Star892)) + histos.fill(HIST("MCQA/hKStarMCCheck"), 1); // match + if (fIsKStar && !(MCinfo.V0PairPDGCode == o2::constants::physics::Pdg::kK0Star892)) + histos.fill(HIST("MCQA/hKStarMCCheck"), 2); // mismatch + if (!fIsKStar && (MCinfo.V0PairPDGCode == o2::constants::physics::Pdg::kK0Star892)) + histos.fill(HIST("MCQA/hKStarMCCheck"), 3); // mismatch + } + } + + return MCinfo; + } + + template + V0PairMCInfo getClusterV0PairMCInfo(TEMCalCls const& cluster, + TV0 const& v0, + TCollision const& collision, + TMCParticles const& mcparticles) + { + // Output container + V0PairMCInfo MCinfo; + + // ============================================================ + // 1) --- V0 (Lambda/AntiLambda) MC information --- + // ============================================================ + + // Check if V0 has MC information + if (!v0.has_v0MCCore()) { + return MCinfo; + } + + auto v0MC = v0.template v0MCCore_as>(); + auto mcLambda = mcparticles.rawIteratorAt(v0MC.particleIdMC()); + + // Save basic Lambda MC info (always saved, independent of matching) + MCinfo.V02MCpx = v0MC.pxMC(); + MCinfo.V02MCpy = v0MC.pyMC(); + MCinfo.V02MCpz = v0MC.pzMC(); + MCinfo.fIsV02Primary = v0MC.isPhysicalPrimary(); + MCinfo.V02PDGCode = v0MC.pdgCode(); + MCinfo.V02PDGCodeMother = v0MC.pdgCodeMother(); + MCinfo.V02PDGCodePos = v0MC.pdgCodePositive(); + MCinfo.V02PDGCodeNeg = v0MC.pdgCodeNegative(); + + // Check correct MC collision assignment (if available) + if (collision.has_straMCCollision()) { + auto MCCollision = collision.template straMCCollision_as< + soa::Join>(); + MCinfo.fIsV02CorrectlyAssign = (v0MC.straMCCollisionId() == MCCollision.globalIndex()); + } + + // Retrieve Lambda mothers + auto const& lambdaMothers = mcLambda.template mothers_as(); + if (lambdaMothers.empty()) { + // No ancestry -> cannot match to any parent + return MCinfo; + } + + // Assumption: first mother is the physical one + auto const& lambdaMother = lambdaMothers.front(); + int lambdaMotherIndex = lambdaMother.globalIndex(); + + // ============================================================ + // 2) --- EMCal cluster: loop over MC contributors --- + // ============================================================ + + int matchedPhotonId = -1; // MC photon candidate + int matchedMotherIndex = -1; // Common Sigma0 candidate + + // Fallback: sum of all contributor momenta (useful for resolution studies, perhaps?) + float sumPx = 0.f, sumPy = 0.f, sumPz = 0.f; + + // Loop over all MC contributors to the cluster + for (size_t i = 0; i < cluster.mcParticleIds().size(); i++) { + + int mcId = cluster.mcParticleIds()[i]; + auto mcPart = mcparticles.iteratorAt(mcId); + + // Accumulate total momentum (fallback strategy) + sumPx += mcPart.px(); + sumPy += mcPart.py(); + sumPz += mcPart.pz(); + + // ------------------------------------------------------------ + // Check 1: + // Does this contributor come from a Sigma0/AntiSigma0 somewhere in its ancestry? + // ------------------------------------------------------------ + int daughterId = aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(mcPart, mcparticles, std::vector{PDG_t::kSigma0, PDG_t::kSigma0Bar}); + + if (daughterId < 0) + continue; // Not from Sigma0 -> try next contributor + + auto mcPhoton = mcparticles.iteratorAt(daughterId); + + // Sanity check: are we getting the correct particles? + auto dummy = mcparticles.rawIteratorAt(daughterId); + if (mcPhoton.globalIndex() != dummy.globalIndex()) + LOGF(fatal, "The behave of rawIteratorAt != iteratorAt. Index %i != %i. Please check. Aborting.", mcPhoton.globalIndex(), dummy.globalIndex()); + + // Require true photon, please + if (mcPhoton.pdgCode() != PDG_t::kGamma) + continue; + + // Get Sigma0 index from photon mother + auto mothers = mcPhoton.mothersIds(); + if (mothers.empty()) // No mothers? Weird + continue; + + int sigmaIndex = mothers[0]; + + // ------------------------------------------------------------ + // Check 2: + // Does this photon share the same mother as the Lambda? + // ------------------------------------------------------------ + if (sigmaIndex == lambdaMotherIndex) { + matchedPhotonId = daughterId; + matchedMotherIndex = sigmaIndex; + MCinfo.EMCalClusterAmplitude = cluster.amplitudeA()[i]; + break; // SUCCESS -> stop loop } } + // ============================================================ + // 3) --- SUCCESS: true Lambda–photon pair from same Sigma0 --- + // ============================================================ + + if (matchedPhotonId >= 0 && matchedMotherIndex >= 0) { + + auto mcPhoton = mcparticles.iteratorAt(matchedPhotonId); + auto mcSigma = mcparticles.iteratorAt(matchedMotherIndex); + + // --- Pair (Sigma0) information + MCinfo.fV0PairProducedByGenerator = mcSigma.producedByGenerator(); + MCinfo.V0PairPDGCode = mcSigma.pdgCode(); + MCinfo.V0PairMCProcess = mcSigma.getProcess(); + MCinfo.V0PairMCParticleID = mcSigma.globalIndex(); + MCinfo.V0PairMCRadius = std::hypot(mcSigma.vx(), mcSigma.vy()); + + // Sigma0 mother (optional) + auto const& sigmaMothers = mcSigma.template mothers_as(); + if (!sigmaMothers.empty()) { + MCinfo.V0PairPDGCodeMother = sigmaMothers.front().pdgCode(); + } + + // --- Photon MC info + MCinfo.V01MCpx = mcPhoton.px(); + MCinfo.V01MCpy = mcPhoton.py(); + MCinfo.V01MCpz = mcPhoton.pz(); + MCinfo.fIsV01Primary = mcPhoton.isPhysicalPrimary(); + MCinfo.V01PDGCode = mcPhoton.pdgCode(); + + if (!mcPhoton.mothersIds().empty()) { + auto mcMother = mcparticles.iteratorAt(mcPhoton.mothersIds()[0]); + MCinfo.V01PDGCodeMother = mcMother.pdgCode(); + } + + return MCinfo; + } + + // ============================================================ + // 4) --- FAILURE: no true matching photon found --- + // ============================================================ + + // Strategy: + // - Keep Lambda MC info (already filled) + // - For cluster: + // use summed momentum of contributors (proxy for cluster truth) + // - Leave PDG / primary flags as default (dummy) + + MCinfo.V01MCpx = sumPx; + MCinfo.V01MCpy = sumPy; + MCinfo.V01MCpz = sumPz; + return MCinfo; } @@ -992,12 +1342,21 @@ struct sigma0builder { std::vector getListOfRecoCollIndices(TMCollisions const& mcCollisions, TCollisions const& collisions) { std::vector listBestCollisionIdx(mcCollisions.size()); + + // Custom grouping + std::vector> groupedCollisions(mcCollisions.size()); + + for (const auto& coll : collisions) { + groupedCollisions[coll.straMCCollisionId()].push_back(coll.globalIndex()); + } + for (auto const& mcCollision : mcCollisions) { - auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex()); int biggestNContribs = -1; int bestCollisionIndex = -1; - for (auto const& collision : groupedCollisions) { + for (size_t i = 0; i < groupedCollisions[mcCollision.globalIndex()].size(); i++) { // consider event selections in the recoed <-> gen collision association, for the denominator (or numerator) of the efficiency (or signal loss)? + auto collision = collisions.rawIteratorAt(groupedCollisions[mcCollision.globalIndex()][i]); + if (eventSelections.useEvtSelInDenomEff && eventSelections.fUseEventSelection) { if (!IsEventAccepted(collision, false)) continue; @@ -1021,6 +1380,14 @@ struct sigma0builder { void fillGeneratedEventProperties(TMCCollisions const& mcCollisions, TCollisions const& collisions) { std::vector listBestCollisionIdx(mcCollisions.size()); + + // Custom grouping + std::vector> groupedCollisions(mcCollisions.size()); + + for (const auto& coll : collisions) { + groupedCollisions[coll.straMCCollisionId()].push_back(coll.globalIndex()); + } + for (auto const& mcCollision : mcCollisions) { // Apply selections on MC collisions if (eventSelections.applyZVtxSelOnMCPV && std::abs(mcCollision.posZ()) > eventSelections.maxZVtxPosition) { @@ -1036,16 +1403,17 @@ struct sigma0builder { } } - histos.fill(HIST("PhotonLambdaQA/hGenEvents"), mcCollision.multMCNParticlesEta05(), 0 /* all gen. events*/); + histos.fill(HIST("V0QA/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; float centrality = 100.5f; int nCollisions = 0; - for (auto const& collision : groupedCollisions) { + for (size_t i = 0; i < groupedCollisions[mcCollision.globalIndex()].size(); i++) { + auto collision = collisions.rawIteratorAt(groupedCollisions[mcCollision.globalIndex()][i]); + if (eventSelections.fUseEventSelection) { if (!IsEventAccepted(collision, false)) continue; @@ -1059,15 +1427,15 @@ struct sigma0builder { atLeastOne = true; } - histos.fill(HIST("PhotonLambdaQA/hCentralityVsNcoll_beforeEvSel"), centrality, groupedCollisions.size()); - histos.fill(HIST("PhotonLambdaQA/hCentralityVsNcoll_afterEvSel"), centrality, nCollisions); - histos.fill(HIST("PhotonLambdaQA/hCentralityVsMultMC"), centrality, mcCollision.multMCNParticlesEta05()); - histos.fill(HIST("PhotonLambdaQA/hCentralityVsPVzMC"), centrality, mcCollision.posZ()); - histos.fill(HIST("PhotonLambdaQA/hEventPVzMC"), mcCollision.posZ()); + histos.fill(HIST("V0QA/hCentralityVsNcoll_beforeEvSel"), centrality, groupedCollisions.size()); + histos.fill(HIST("V0QA/hCentralityVsNcoll_afterEvSel"), centrality, nCollisions); + histos.fill(HIST("V0QA/hCentralityVsMultMC"), centrality, mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("V0QA/hCentralityVsPVzMC"), centrality, mcCollision.posZ()); + histos.fill(HIST("V0QA/hEventPVzMC"), mcCollision.posZ()); if (atLeastOne) { - histos.fill(HIST("PhotonLambdaQA/hGenEvents"), mcCollision.multMCNParticlesEta05(), 1 /* at least 1 rec. event*/); - histos.fill(HIST("PhotonLambdaQA/hGenEventCentrality"), centrality); + histos.fill(HIST("V0QA/hGenEvents"), mcCollision.multMCNParticlesEta05(), 1 /* at least 1 rec. event*/); + histos.fill(HIST("V0QA/hGenEventCentrality"), centrality); } } return; @@ -1076,7 +1444,7 @@ struct sigma0builder { // ______________________________________________________ // Auxiliary function to get generated photon and lambda info template - void runGenPhotonLambdaQA(TMCCollisions const& mcCollisions, TV0MCs const& V0MCCores, TCollisions const& collisions) + void runGenV0QA(TMCCollisions const& mcCollisions, TV0MCs const& V0MCCores, TCollisions const& collisions) { fillGeneratedEventProperties(mcCollisions, collisions); std::vector listBestCollisionIdx = getListOfRecoCollIndices(mcCollisions, collisions); @@ -1093,7 +1461,8 @@ struct sigma0builder { ymc = RecoDecay::y(std::array{v0MC.pxMC(), v0MC.pyMC(), v0MC.pzMC()}, o2::constants::physics::MassGamma); else if (std::abs(v0MC.pdgCode()) == PDG_t::kLambda0) ymc = v0MC.rapidityMC(1); - + else if (v0MC.pdgCode() == PDG_t::kK0Short) + ymc = v0MC.rapidityMC(2); // what is the 2 here? if ((ymc < genSelections.mc_rapidityMin) || (ymc > genSelections.mc_rapidityMax)) continue; @@ -1118,27 +1487,34 @@ struct sigma0builder { centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); if (v0MC.pdgCode() == PDG_t::kGamma) { - histos.fill(HIST("PhotonLambdaQA/h2dGenPhotonVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + histos.fill(HIST("V0QA/h2dGenPhotonVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); } if (v0MC.pdgCode() == PDG_t::kLambda0) { - histos.fill(HIST("PhotonLambdaQA/h2dGenLambdaVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + histos.fill(HIST("V0QA/h2dGenLambdaVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); } if (v0MC.pdgCode() == PDG_t::kLambda0Bar) { - histos.fill(HIST("PhotonLambdaQA/h2dGenAntiLambdaVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + histos.fill(HIST("V0QA/h2dGenAntiLambdaVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (v0MC.pdgCode() == PDG_t::kK0Short) { + histos.fill(HIST("V0QA/h2dGenKShortVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); } } if (v0MC.pdgCode() == PDG_t::kGamma) { - histos.fill(HIST("PhotonLambdaQA/h2dGenPhoton"), centrality, ptmc); - histos.fill(HIST("PhotonLambdaQA/h2dGenPhotonVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + histos.fill(HIST("V0QA/h2dGenPhoton"), centrality, ptmc); + histos.fill(HIST("V0QA/h2dGenPhotonVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); } if (v0MC.pdgCode() == PDG_t::kLambda0) { - histos.fill(HIST("PhotonLambdaQA/h2dGenLambda"), centrality, ptmc); - histos.fill(HIST("PhotonLambdaQA/h2dGenLambdaVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + histos.fill(HIST("V0QA/h2dGenLambda"), centrality, ptmc); + histos.fill(HIST("V0QA/h2dGenLambdaVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); } if (v0MC.pdgCode() == PDG_t::kLambda0Bar) { - histos.fill(HIST("PhotonLambdaQA/h2dGenAntiLambda"), centrality, ptmc); - histos.fill(HIST("PhotonLambdaQA/h2dGenAntiLambdaVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + histos.fill(HIST("V0QA/h2dGenAntiLambda"), centrality, ptmc); + histos.fill(HIST("V0QA/h2dGenAntiLambdaVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (v0MC.pdgCode() == PDG_t::kK0Short) { + histos.fill(HIST("V0QA/h2dGenKShort"), centrality, ptmc); + histos.fill(HIST("V0QA/h2dGenKShortVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); } } } @@ -1149,14 +1525,21 @@ struct sigma0builder { template void analyzeV0CollAssoc(TCollision const& collision, TV0Object const& fullv0s, std::vector selV0Indices, bool isPhotonAnalysis) { + if (!collision.has_straMCCollision()) + return; + auto v0MCCollision = collision.template straMCCollision_as>(); float IR = (fGetIR) ? rateFetcher.fetch(ccdb.service, collision.timestamp(), collision.runNumber(), irSource, fIRCrashOnNull) * 1.e-3 : -1; for (size_t i = 0; i < selV0Indices.size(); ++i) { auto v0 = fullv0s.rawIteratorAt(selV0Indices[i]); + + if (!v0.has_v0MCCore()) + continue; + auto v0MC = v0.template v0MCCore_as>(); - float V0MCpT = RecoDecay::pt(array{v0MC.pxMC(), v0MC.pyMC()}); + float V0MCpT = RecoDecay::pt(std::array{v0MC.pxMC(), v0MC.pyMC()}); float V0PA = TMath::ACos(v0.v0cosPA()); bool fIsV0CorrectlyAssigned = (v0MC.straMCCollisionId() == v0MCCollision.globalIndex()); bool isPrimary = v0MC.isPhysicalPrimary(); @@ -1220,7 +1603,7 @@ struct sigma0builder { histos.fill(HIST("GenQA/h2dSigma0MCSourceVsPDGMother"), GenInfo.IsProducedByGenerator, GenInfo.PDGCodeMother); // Checking decay modes and getting daughter pTs - for (auto& daughter : daughters) { + for (auto const& daughter : daughters) { histos.fill(HIST("GenQA/h2dSigma0NDaughtersVsPDG"), daughters.size(), daughter.pdgCode()); if (GenInfo.NDaughters == 2) { @@ -1235,13 +1618,13 @@ struct sigma0builder { if ((GenInfo.IsKStar) && genSelections.doQA) { histos.fill(HIST("GenQA/h2dKStarMCSourceVsPDGMother"), GenInfo.IsProducedByGenerator, GenInfo.PDGCodeMother); - for (auto& daughter : daughters) // checking decay modes + for (auto const& daughter : daughters) // checking decay modes histos.fill(HIST("GenQA/h2dKStarNDaughtersVsPDG"), daughters.size(), daughter.pdgCode()); } if (GenInfo.IsPi0 && genSelections.doQA) { histos.fill(HIST("GenQA/h2dPi0MCSourceVsPDGMother"), GenInfo.IsProducedByGenerator, GenInfo.PDGCodeMother); - for (auto& daughter : daughters) // checking decay modes + for (auto const& daughter : daughters) // checking decay modes histos.fill(HIST("GenQA/h2dPi0NDaughtersVsPDG"), daughters.size(), daughter.pdgCode()); } } @@ -1351,7 +1734,7 @@ struct sigma0builder { template void genProcess(TMCParticles const& mcParticles) { - for (auto& mcParticle : mcParticles) { + for (auto const& mcParticle : mcParticles) { // Rapidity selection if ((mcParticle.y() < genSelections.mc_rapidityMin) || (mcParticle.y() > genSelections.mc_rapidityMax)) continue; @@ -1382,7 +1765,7 @@ struct sigma0builder { // Pi0 if (fillPi0Tables && MCGenInfo.IsPi0) { pi0Gens(MCGenInfo.IsProducedByGenerator, MCGenInfo.MCPt, mcParticle.y()); // optional table to store generated pi0 candidates. Be careful, this is a large table! - pi0GenCollRefs(MCGenInfo.MCCollId); // link to stramccollision table + pi0GenCollRefs(MCGenInfo.MCCollId); // link to stramccollision table } // Sigma0/ASigma0 @@ -1399,12 +1782,31 @@ struct sigma0builder { } } + // Function to fill QA histograms. mode = 0 (before selections, all clusters), 1 after all selections + template + void fillEMCalHistos(TEMCalClusterObject const& cluster) + { + // Check whether it is before or after selections + static constexpr std::string_view MainDir2[] = {"EMCalPhotonBeforeSel", "EMCalPhotonSel"}; + + // calculate pT for cluster assuming they are photons (so no mass) + float gammapT = std::sqrt(cluster.energy() * cluster.energy()) / std::cosh(cluster.eta()); + + histos.fill(HIST(MainDir2[mode]) + HIST("/hDefinition"), cluster.definition()); + histos.fill(HIST(MainDir2[mode]) + HIST("/h2dNCells"), gammapT, cluster.nCells()); + histos.fill(HIST(MainDir2[mode]) + HIST("/h2dEnergy"), gammapT, cluster.energy()); + histos.fill(HIST(MainDir2[mode]) + HIST("/h2dShape"), gammapT, cluster.m02()); + histos.fill(HIST(MainDir2[mode]) + HIST("/h2dEtaVsPhi"), cluster.eta(), cluster.phi()); + histos.fill(HIST(MainDir2[mode]) + HIST("/h2dTime"), gammapT, cluster.time()); + histos.fill(HIST(MainDir2[mode]) + HIST("/hExotic"), cluster.isExotic()); + } + // Function to fill QA histograms. mode = 0 (before selections, all v0s), 1 (photon candidates), 2 (lambda/alambda candidates) template - void fillHistos(TV0Object const& v0, TCollision const& collision) + void fillV0Histos(TV0Object const& v0, TCollision const& collision) { // Check whether it is before or after selections - static constexpr std::string_view MainDir[] = {"V0BeforeSel", "PhotonSel", "LambdaSel"}; + static constexpr std::string_view MainDir[] = {"V0BeforeSel", "PhotonSel", "LambdaSel", "KShortSel"}; auto posTrack = v0.template posTrackExtra_as(); auto negTrack = v0.template negTrackExtra_as(); @@ -1412,6 +1814,7 @@ struct sigma0builder { float Phi = RecoDecay::phi(v0.px(), v0.py()); float PhotonY = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, o2::constants::physics::MassGamma); float fLambdaLifeTime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + float fKShortLifeTime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; // Fill histos histos.fill(HIST(MainDir[mode]) + HIST("/hpT"), v0.pt()); @@ -1448,27 +1851,83 @@ struct sigma0builder { histos.fill(HIST(MainDir[mode]) + HIST("/h2dMassPhotonVsLambda"), v0.mGamma(), v0.mLambda()); // Lambda/ALambda-specific - histos.fill(HIST(MainDir[mode]) + HIST("/hLifeTime"), fLambdaLifeTime); + histos.fill(HIST(MainDir[mode]) + HIST("/hLambdaLifeTime"), fLambdaLifeTime); histos.fill(HIST(MainDir[mode]) + HIST("/hLambdaY"), v0.yLambda()); histos.fill(HIST(MainDir[mode]) + HIST("/hLambdaMass"), v0.mLambda()); histos.fill(HIST(MainDir[mode]) + HIST("/hALambdaMass"), v0.mAntiLambda()); histos.fill(HIST(MainDir[mode]) + HIST("/h2dMassLambdaVsK0S"), v0.mLambda(), v0.mK0Short()); histos.fill(HIST(MainDir[mode]) + HIST("/h2dMassLambdaVsGamma"), v0.mLambda(), v0.mGamma()); + + // KShort-specific + histos.fill(HIST(MainDir[mode]) + HIST("/hKShortLifeTime"), fKShortLifeTime); + histos.fill(HIST(MainDir[mode]) + HIST("/hKShortY"), v0.yK0Short()); + histos.fill(HIST(MainDir[mode]) + HIST("/hKShortMass"), v0.mK0Short()); + histos.fill(HIST(MainDir[mode]) + HIST("/h2dMassK0SvsLambda"), v0.mK0Short(), v0.mLambda()); + histos.fill(HIST(MainDir[mode]) + HIST("/h2dMassK0SVsGamma"), v0.mK0Short(), v0.mGamma()); } //_______________________________________________ - // Process photon candidate + // Process v0 photon candidate + template + bool processEMCalPhotonCandidate(TEMCalClusterObject const& cluster) + { + // Clusterizer + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 1.); + if (cluster.definition() != EMCalPhotonSelections.definition && EMCalPhotonSelections.definition > -1) + return false; + + // Number of Cells + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 2.); + if (cluster.nCells() < EMCalPhotonSelections.MinCells) + return false; + + // Energy + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 3.); + if (cluster.energy() < EMCalPhotonSelections.MinEnergy || cluster.energy() > EMCalPhotonSelections.MaxEnergy) + return false; + + // Eta + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 4.); + if (TMath::Abs(cluster.eta()) > EMCalPhotonSelections.MaxEta) + return false; + + // Timing + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 5.); + if (cluster.time() < EMCalPhotonSelections.MinTime || cluster.time() > EMCalPhotonSelections.MaxTime) + return false; + + // Exotic Clusters + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 6.); + if (cluster.isExotic() && EMCalPhotonSelections.RemoveExotic) { + return false; + } + + // Shower shape long axis + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 7.); + if (cluster.nCells() > 1) { // Only if we have more than one + if (cluster.m02() < EMCalPhotonSelections.MinM02 || cluster.m02() > EMCalPhotonSelections.MaxM02) { + return false; + } + } + + histos.fill(HIST("EMCalPhotonSel/hSelectionStatistics"), 8.); + + return true; + } + + //_______________________________________________ + // Process v0 photon candidate template bool processPhotonCandidate(TV0Object const& gamma) { // Optional MC selection if (photonSelections.doMCAssociation) { if constexpr (requires { gamma.motherMCPartId(); }) { - if (gamma.has_v0MCCore()) { - auto gammaMC = gamma.template v0MCCore_as>(); - if (gammaMC.pdgCode() != PDG_t::kGamma) - return false; - } + if (!gamma.has_v0MCCore()) + return false; + auto gammaMC = gamma.template v0MCCore_as>(); + if (gammaMC.pdgCode() != PDG_t::kGamma) + return false; } } @@ -1561,11 +2020,12 @@ struct sigma0builder { // Optional MC selection if (lambdaSelections.doMCAssociation) { if constexpr (requires { lambda.motherMCPartId(); }) { - if (lambda.has_v0MCCore()) { - auto lambdaMC = lambda.template v0MCCore_as>(); - if (TMath::Abs(lambdaMC.pdgCode()) != PDG_t::kLambda0) - return false; - } + if (!lambda.has_v0MCCore()) + return false; + + auto lambdaMC = lambda.template v0MCCore_as>(); + if (TMath::Abs(lambdaMC.pdgCode()) != PDG_t::kLambda0) + return false; } } @@ -1652,52 +2112,93 @@ struct sigma0builder { template bool processKShortCandidate(TV0Object const& kshort, TCollision const& collision) { + // Optional MC selection + if (kshortSelections.doMCAssociation) { + if constexpr (requires { kshort.motherMCPartId(); }) { + if (!kshort.has_v0MCCore()) + return false; + + auto kshortMC = kshort.template v0MCCore_as>(); + if (TMath::Abs(kshortMC.pdgCode()) != PDG_t::kK0Short) + return false; + } + } + // V0 type selection if (kshort.v0Type() != 1) return false; - float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + if (useMLScores) { + // if (kshort.k0ShortBDTScore() <= kshortSelections.KShort_MLThreshold) + return false; - histos.fill(HIST("K0ShortSel/h3dK0ShortMass"), centrality, kshort.pt(), kshort.mK0Short()); + } else { + // KShort basic selection criteria: + histos.fill(HIST("KShortSel/hSelectionStatistics"), 1.); + if ((TMath::Abs(kshort.mK0Short() - o2::constants::physics::MassK0Short) > kshortSelections.KShortWindow) && kshortSelections.KShortWindow > 0) + return false; - histos.fill(HIST("K0ShortSel/hSelectionStatistics"), 1.); - histos.fill(HIST("K0ShortSel/hK0ShortMass"), kshort.mK0Short()); + histos.fill(HIST("KShortSel/hSelectionStatistics"), 2.); + if ((kshort.yK0Short() < kshortSelections.KShortMinRapidity) || (kshort.yK0Short() > kshortSelections.KShortMaxRapidity)) + return false; - if ((TMath::Abs(kshort.mK0Short() - o2::constants::physics::MassK0Short) > K0ShortWindow)) - return false; - histos.fill(HIST("K0ShortSel/hK0ShortNegEta"), kshort.negativeeta()); - histos.fill(HIST("K0ShortSel/hK0ShortPosEta"), kshort.positiveeta()); - histos.fill(HIST("K0ShortSel/hK0ShortY"), kshort.yK0Short()); - histos.fill(HIST("K0ShortSel/hSelectionStatistics"), 2.); + histos.fill(HIST("KShortSel/hSelectionStatistics"), 3.); + if ((kshort.negativeeta() < kshortSelections.KShortDauEtaMin) || (kshort.negativeeta() > kshortSelections.KShortDauEtaMax)) + return false; - if ((TMath::Abs(kshort.yK0Short()) > V0Rapidity) || (TMath::Abs(kshort.negativeeta()) > K0ShortDauPseudoRap) || (TMath::Abs(kshort.positiveeta()) > K0ShortDauPseudoRap)) - return false; - histos.fill(HIST("K0ShortSel/hK0ShortDCANegToPV"), kshort.dcanegtopv()); - histos.fill(HIST("K0ShortSel/hK0ShortDCAPosToPV"), kshort.dcapostopv()); - histos.fill(HIST("K0ShortSel/hSelectionStatistics"), 3.); + histos.fill(HIST("KShortSel/hSelectionStatistics"), 4.); + if ((kshort.positiveeta() < kshortSelections.KShortDauEtaMin) || (kshort.positiveeta() > kshortSelections.KShortDauEtaMax)) + return false; - if ((TMath::Abs(kshort.dcapostopv()) < K0ShortMinDCAPosToPv) || (TMath::Abs(kshort.dcanegtopv()) < K0ShortMinDCANegToPv)) - return false; - histos.fill(HIST("K0ShortSel/hK0ShortRadius"), kshort.v0radius()); - histos.fill(HIST("K0ShortSel/hSelectionStatistics"), 4.); + histos.fill(HIST("KShortSel/hSelectionStatistics"), 5.); + if ((TMath::Abs(kshort.dcapostopv()) < kshortSelections.KShortMinDCAPosToPv) || (TMath::Abs(kshort.dcanegtopv()) < kshortSelections.KShortMinDCANegToPv)) + return false; - if ((kshort.v0radius() < K0ShortMinv0radius) || (kshort.v0radius() > K0ShortMaxv0radius)) - return false; - histos.fill(HIST("K0ShortSel/hK0ShortDCADau"), kshort.dcaV0daughters()); - histos.fill(HIST("K0ShortSel/hSelectionStatistics"), 5.); + histos.fill(HIST("KShortSel/hSelectionStatistics"), 6.); + if ((kshort.v0radius() < kshortSelections.KShortMinv0radius) || (kshort.v0radius() > kshortSelections.KShortMaxv0radius)) + return false; - if (TMath::Abs(kshort.dcaV0daughters()) > K0ShortMaxDCAV0Dau) - return false; - histos.fill(HIST("K0ShortSel/hSelectionStatistics"), 6.); - // MC Processing (if available) - // if constexpr (requires { kshort.motherMCPartId(); }) { - // if (kshort.has_v0MCCore()) { - // auto kshortMC = kshort.template v0MCCore_as>(); - // // if (kshortMC.pdgCode() == 310) // Is K0Short - // // histos.fill(HIST("MC/h2dPtVsCentrality_MCAssocKShort"), centrality, kshort.pt()); - // } - // } + histos.fill(HIST("KShortSel/hSelectionStatistics"), 7.); + if ((kshort.z() < kshortSelections.KShortMinZ) || (kshort.z() > kshortSelections.KShortMaxZ)) + return false; + + histos.fill(HIST("KShortSel/hSelectionStatistics"), 8.); + if (TMath::Abs(kshort.dcaV0daughters()) > kshortSelections.KShortMaxDCAV0Dau) + return false; + + histos.fill(HIST("KShortSel/hSelectionStatistics"), 9.); + + if (kshort.qtarm() < kshortSelections.KShortArmenterosCoefficient * TMath::Abs(kshort.alpha())) + return false; + + histos.fill(HIST("KShortSel/hSelectionStatistics"), 10.); + if (kshort.v0cosPA() < kshortSelections.KShortMinv0cospa) + return false; + + auto posTrackKShort = kshort.template posTrackExtra_as(); + auto negTrackKShort = kshort.template negTrackExtra_as(); + histos.fill(HIST("KShortSel/hSelectionStatistics"), 11.); + if ((posTrackKShort.tpcCrossedRows() < kshortSelections.KShortMinTPCCrossedRows) || (negTrackKShort.tpcCrossedRows() < kshortSelections.KShortMinTPCCrossedRows)) + return false; + + // MinITSCls + bool posIsFromAfterburner = posTrackKShort.itsChi2PerNcl() < 0; + bool negIsFromAfterburner = negTrackKShort.itsChi2PerNcl() < 0; + + histos.fill(HIST("KShortSel/hSelectionStatistics"), 12.); + if (posTrackKShort.itsNCls() < kshortSelections.KShortMinITSclusters && (!kshortSelections.KShortRejectPosITSafterburner || posIsFromAfterburner)) + return false; + if (negTrackKShort.itsNCls() < kshortSelections.KShortMinITSclusters && (!kshortSelections.KShortRejectNegITSafterburner || negIsFromAfterburner)) + return false; + + histos.fill(HIST("KShortSel/hSelectionStatistics"), 13.); + float fKShortLifeTime = kshort.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; + if (fKShortLifeTime > kshortSelections.KShortMaxLifeTime) + return false; + + histos.fill(HIST("KShortSel/hSelectionStatistics"), 14.); + } return true; } @@ -1766,14 +2267,20 @@ struct sigma0builder { } //_______________________________________________ - // Build sigma0 candidate + // Build sigma0 candidate with PCM photons template - bool buildSigma0(TV0Object const& lambda, TV0Object const& gamma, TCollision const& collision, TMCParticles const& mcparticles) + bool buildPCMSigma0(TV0Object const& lambda, TV0Object const& gamma, TCollision const& collision, TMCParticles const& mcparticles) { //_______________________________________________ + // Same index rejection + if (gamma.globalIndex() == lambda.globalIndex()) + return false; + // Checking if both V0s are made of the very same tracks if (gamma.posTrackExtraId() == lambda.posTrackExtraId() || - gamma.negTrackExtraId() == lambda.negTrackExtraId()) { + gamma.negTrackExtraId() == lambda.negTrackExtraId() || + gamma.posTrackExtraId() == lambda.negTrackExtraId() || + gamma.negTrackExtraId() == lambda.posTrackExtraId()) { return false; } @@ -1807,26 +2314,23 @@ struct sigma0builder { // Sigma0 topological info auto sigma0TopoInfo = propagateV0PairToDCA(gamma, lambda); - sigma0cores(sigma0TopoInfo.X, sigma0TopoInfo.Y, sigma0TopoInfo.Z, sigma0TopoInfo.DCADau, + sigma0cores(gamma.globalIndex(), lambda.globalIndex(), sigma0TopoInfo.X, sigma0TopoInfo.Y, sigma0TopoInfo.Z, sigma0TopoInfo.DCADau, gamma.px(), gamma.py(), gamma.pz(), gamma.mGamma(), lambda.px(), lambda.py(), lambda.pz(), lambda.mLambda(), lambda.mAntiLambda()); // MC properties if constexpr (requires { gamma.motherMCPartId(); lambda.motherMCPartId(); }) { auto sigma0MCInfo = getV0PairMCInfo(gamma, lambda, collision, mcparticles); - sigma0mccores(sigma0MCInfo.V0PairMCRadius, sigma0MCInfo.V0PairPDGCode, sigma0MCInfo.V0PairPDGCodeMother, sigma0MCInfo.V0PairMCProcess, sigma0MCInfo.fV0PairProducedByGenerator, - sigma0MCInfo.V01MCpx, sigma0MCInfo.V01MCpy, sigma0MCInfo.V01MCpz, - sigma0MCInfo.fIsV01Primary, sigma0MCInfo.V01PDGCode, sigma0MCInfo.V01PDGCodeMother, sigma0MCInfo.fIsV01CorrectlyAssign, + sigma0mccores(sigma0MCInfo.V0PairMCParticleID, sigma0MCInfo.V0PairMCRadius, sigma0MCInfo.V0PairPDGCode, sigma0MCInfo.V0PairPDGCodeMother, sigma0MCInfo.V0PairMCProcess, sigma0MCInfo.fV0PairProducedByGenerator, + sigma0MCInfo.V01MCpx, sigma0MCInfo.V01MCpy, sigma0MCInfo.V01MCpz, sigma0MCInfo.EMCalClusterAmplitude, + sigma0MCInfo.V01PDGCodePos, sigma0MCInfo.V01PDGCodeNeg, sigma0MCInfo.fIsV01Primary, sigma0MCInfo.V01PDGCode, sigma0MCInfo.V01PDGCodeMother, sigma0MCInfo.fIsV01CorrectlyAssign, sigma0MCInfo.V02MCpx, sigma0MCInfo.V02MCpy, sigma0MCInfo.V02MCpz, - sigma0MCInfo.fIsV02Primary, sigma0MCInfo.V02PDGCode, sigma0MCInfo.V02PDGCodeMother, sigma0MCInfo.fIsV02CorrectlyAssign); - - sigma0mclabel(sigma0MCInfo.V0PairMCParticleID); + sigma0MCInfo.V02PDGCodePos, sigma0MCInfo.V02PDGCodeNeg, sigma0MCInfo.fIsV02Primary, sigma0MCInfo.V02PDGCode, sigma0MCInfo.V02PDGCodeMother, sigma0MCInfo.fIsV02CorrectlyAssign); } // Sigma0s -> stracollisions link histos.fill(HIST("SigmaSel/hSigma0DauDeltaIndex"), gamma.globalIndex() - lambda.globalIndex()); sigma0CollRefs(collision.globalIndex()); - sigmaIndices(gamma.globalIndex(), lambda.globalIndex()); //_______________________________________________ // Photon extra properties @@ -1891,6 +2395,111 @@ struct sigma0builder { return true; } + // Build sigma0 candidate + template + bool buildEMCalSigma0(TV0Object const& lambda, TEMCalClsObject const& gamma, TCollision const& collision, TMCParticles const& mcparticles, std::vector const& emcaltracksmatched) + { + // calculate pT for cluster assuming they are photons (so no mass) + float gammapT = std::sqrt(gamma.energy() * gamma.energy()) / std::cosh(gamma.eta()); + + // Momentum components + float gammapx = gammapT * std::cos(gamma.phi()); + float gammapy = gammapT * std::sin(gamma.phi()); + float gammapz = gammapT * std::sinh(gamma.phi()); + + //_______________________________________________ + // Sigma0 pre-selections + std::array pVecPhotons{gammapx, gammapy, gammapz}; + std::array pVecLambda{lambda.px(), lambda.py(), lambda.pz()}; + + auto arrMom = std::array{pVecPhotons, pVecLambda}; + float sigmaMass = RecoDecay::m(arrMom, std::array{o2::constants::physics::MassPhoton, o2::constants::physics::MassLambda0}); + + // N.B. At this stage, we are only using the reconstructed rapidity (ideally with a very loose cut) + // A proper selection should be done in the sigmaanalysis + float sigmaY = RecoDecay::y(std::array{gammapx + lambda.px(), gammapy + lambda.py(), gammapz + lambda.pz()}, o2::constants::physics::MassSigma0); + + histos.fill(HIST("SigmaSel/hSelectionStatistics"), 1.); + histos.fill(HIST("SigmaSel/hSigmaMassBeforeSel"), sigmaMass); + if (TMath::Abs(sigmaMass - o2::constants::physics::MassSigma0) > Sigma0Window) + return false; + + histos.fill(HIST("SigmaSel/hSelectionStatistics"), 2.); + if (TMath::Abs(sigmaY) > SigmaMaxRap) + return false; + + histos.fill(HIST("SigmaSel/hSigmaMassSelected"), sigmaMass); + histos.fill(HIST("SigmaSel/hSelectionStatistics"), 3.); + + //_______________________________________________ + // Calculate properties & Fill tables + sigma0cores(gamma.globalIndex(), lambda.globalIndex(), + 0.0f, 0.0f, 0.0f, 0.0f, // N.B: Filling with dummy values for now + gammapx, gammapy, gammapz, 0.0f, + lambda.px(), lambda.py(), lambda.pz(), lambda.mLambda(), lambda.mAntiLambda()); + + // MC properties + if constexpr (requires { gamma.mcParticleIds(); lambda.motherMCPartId(); }) { + + auto sigma0MCInfo = getClusterV0PairMCInfo(gamma, lambda, collision, mcparticles); + + sigma0mccores(sigma0MCInfo.V0PairMCParticleID, sigma0MCInfo.V0PairMCRadius, sigma0MCInfo.V0PairPDGCode, sigma0MCInfo.V0PairPDGCodeMother, sigma0MCInfo.V0PairMCProcess, sigma0MCInfo.fV0PairProducedByGenerator, + sigma0MCInfo.V01MCpx, sigma0MCInfo.V01MCpy, sigma0MCInfo.V01MCpz, sigma0MCInfo.EMCalClusterAmplitude, + sigma0MCInfo.V01PDGCodePos, sigma0MCInfo.V01PDGCodeNeg, sigma0MCInfo.fIsV01Primary, sigma0MCInfo.V01PDGCode, sigma0MCInfo.V01PDGCodeMother, sigma0MCInfo.fIsV01CorrectlyAssign, + sigma0MCInfo.V02MCpx, sigma0MCInfo.V02MCpy, sigma0MCInfo.V02MCpz, + sigma0MCInfo.V02PDGCodePos, sigma0MCInfo.V02PDGCodeNeg, sigma0MCInfo.fIsV02Primary, sigma0MCInfo.V02PDGCode, sigma0MCInfo.V02PDGCodeMother, sigma0MCInfo.fIsV02CorrectlyAssign); + } + + sigma0CollRefs(collision.globalIndex()); + + //_______________________________________________ + // Photon extra properties + bool hasAssociatedTrack = emcaltracksmatched[gamma.globalIndex()]; + sigmaEmCalPhotonExtras(gamma.id(), gamma.energy(), gamma.eta(), gamma.phi(), + gamma.m02(), gamma.m20(), gamma.nCells(), gamma.time(), + gamma.isExotic(), gamma.distanceToBadChannel(), gamma.nlm(), gamma.definition(), hasAssociatedTrack); + + //_______________________________________________ + // Lambda extra properties + auto posTrackLambda = lambda.template posTrackExtra_as(); + auto negTrackLambda = lambda.template negTrackExtra_as(); + + uint8_t fLambdaPosTrackCode = ((uint8_t(posTrackLambda.hasTPC()) << hasTPC) | + (uint8_t(posTrackLambda.hasITSTracker()) << hasITSTracker) | + (uint8_t(posTrackLambda.hasITSAfterburner()) << hasITSAfterburner) | + (uint8_t(posTrackLambda.hasTRD()) << hasTRD) | + (uint8_t(posTrackLambda.hasTOF()) << hasTOF)); + + uint8_t fLambdaNegTrackCode = ((uint8_t(negTrackLambda.hasTPC()) << hasTPC) | + (uint8_t(negTrackLambda.hasITSTracker()) << hasITSTracker) | + (uint8_t(negTrackLambda.hasITSAfterburner()) << hasITSAfterburner) | + (uint8_t(negTrackLambda.hasTRD()) << hasTRD) | + (uint8_t(negTrackLambda.hasTOF()) << hasTOF)); + + float fLambdaLifeTime = lambda.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + float fLambdaPrTOFNSigma = -999.f; + float fLambdaPiTOFNSigma = -999.f; + float fALambdaPrTOFNSigma = -999.f; + float fALambdaPiTOFNSigma = -999.f; + + if constexpr (requires { lambda.tofNSigmaLaPr(); }) { // If TOF info avaiable + fLambdaPrTOFNSigma = lambda.tofNSigmaLaPr(); + fLambdaPiTOFNSigma = lambda.tofNSigmaLaPi(); + fALambdaPrTOFNSigma = lambda.tofNSigmaALaPr(); + fALambdaPiTOFNSigma = lambda.tofNSigmaALaPi(); + } + + sigmaLambdaExtras(lambda.qtarm(), lambda.alpha(), fLambdaLifeTime, lambda.v0radius(), lambda.v0cosPA(), lambda.dcaV0daughters(), lambda.dcanegtopv(), lambda.dcapostopv(), + posTrackLambda.tpcNSigmaPr(), posTrackLambda.tpcNSigmaPi(), negTrackLambda.tpcNSigmaPr(), negTrackLambda.tpcNSigmaPi(), + fLambdaPrTOFNSigma, fLambdaPiTOFNSigma, fALambdaPrTOFNSigma, fALambdaPiTOFNSigma, + posTrackLambda.tpcCrossedRows(), negTrackLambda.tpcCrossedRows(), + lambda.positiveeta(), lambda.negativeeta(), + posTrackLambda.itsNCls(), negTrackLambda.itsNCls(), posTrackLambda.itsChi2PerNcl(), negTrackLambda.itsChi2PerNcl(), + fLambdaPosTrackCode, fLambdaNegTrackCode, lambda.v0Type()); + + return true; + } + //_______________________________________________ // Build kstar candidate template @@ -2013,25 +2622,40 @@ struct sigma0builder { } // Process photon and lambda candidates to build sigma0 candidates - template - void dataProcess(TCollision const& collisions, TV0s const& fullV0s, TMCParticles const& mcparticles) + template + void dataProcess(TCollision const& collisions, TV0s const& fullV0s, TEMCal const& fullEMCalClusters, TEMCalTracks const& emcaltracks, TMCParticles const& mcparticles) { //_______________________________________________ // Initial setup + bool fUsePCMPhoton = !doprocessRealDataWithEMCal && !doprocessMonteCarloWithEMCal; + // Auxiliary vectors to store best candidates std::vector bestGammasArray; std::vector bestLambdasArray; - - std::vector bestKStarGammasArray; std::vector bestKShortsArray; // Custom grouping std::vector> v0grouped(collisions.size()); + std::vector> emclustersgrouped(collisions.size()); + std::vector emcaltracksgrouped; + // Grouping step: for (const auto& v0 : fullV0s) { v0grouped[v0.straCollisionId()].push_back(v0.globalIndex()); } + if constexpr (soa::is_table) { + emcaltracksgrouped.resize(fullEMCalClusters.size(), false); + for (const auto& cluster : fullEMCalClusters) { + emclustersgrouped[cluster.collisionId()].push_back(cluster.globalIndex()); + } + + // Mapping emccluster to matched tracks + for (const auto& calotrack : emcaltracks) { + emcaltracksgrouped[calotrack.emcalclusterId()] = true; + } + } + //_______________________________________________ // Collisions loop for (const auto& coll : collisions) { @@ -2041,11 +2665,14 @@ struct sigma0builder { continue; } + if constexpr (soa::is_table) { + if (emclustersgrouped[coll.globalIndex()].size() == 0 && eventSelections.fSkipEmptyEMCal) + continue; + } + // Clear vectors bestGammasArray.clear(); bestLambdasArray.clear(); - - bestKStarGammasArray.clear(); bestKShortsArray.clear(); float centrality = doPPAnalysis ? coll.centFT0M() : coll.centFT0C(); @@ -2057,37 +2684,55 @@ struct sigma0builder { auto v0 = fullV0s.rawIteratorAt(v0grouped[coll.globalIndex()][i]); if (fFillNoSelV0Histos) - fillHistos<0>(v0, coll); // Filling "all V0s" histograms + fillV0Histos<0>(v0, coll); // Filling "all V0s" histograms - if (processPhotonCandidate(v0)) { // selecting photons - if (fFillSelPhotonHistos) - fillHistos<1>(v0, coll); // QA histos - bestGammasArray.push_back(v0.globalIndex()); // Save indices of best gamma candidates + if (fUsePCMPhoton) { + if (processPhotonCandidate(v0)) { // selecting photons + if (fFillSelPhotonHistos) + fillV0Histos<1>(v0, coll); // QA histos + bestGammasArray.push_back(v0.globalIndex()); // Save indices of best gamma candidates + } } if (processLambdaCandidate(v0, coll)) { // selecting lambdas if (fFillSelLambdaHistos) - fillHistos<2>(v0, coll); // QA histos + fillV0Histos<2>(v0, coll); // QA histos bestLambdasArray.push_back(v0.globalIndex()); // Save indices of best lambda candidates } - if (processKShortCandidate(v0, coll)) // selecting kshorts + if (processKShortCandidate(v0, coll)) { // selecting kshorts + if (fFillSelKShortHistos) + fillV0Histos<3>(v0, coll); // QA histos bestKShortsArray.push_back(v0.globalIndex()); // Save indices of best kshort candidates + } + } + + // If EMCalClusters is available, we don't use PCM + if constexpr (soa::is_table) { + for (size_t i = 0; i < emclustersgrouped[coll.globalIndex()].size(); i++) { + auto cluster = fullEMCalClusters.rawIteratorAt(emclustersgrouped[coll.globalIndex()][i]); + fillEMCalHistos<0>(cluster); + + if (processEMCalPhotonCandidate(cluster)) { // selecting photons + fillEMCalHistos<1>(cluster); // QA histos + bestGammasArray.push_back(cluster.globalIndex()); // Save indices of best gamma candidates + } + } } //_______________________________________________ // Wrongly collision association study (MC-specific) - if constexpr (requires { coll.StraMCCollisionId(); }) { + if constexpr (requires { coll.straMCCollisionId(); }) { if (doAssocStudy) { - analyzeV0CollAssoc(coll, fullV0s, bestGammasArray, true); // Photon-analysis + if constexpr (!soa::is_table) + analyzeV0CollAssoc(coll, fullV0s, bestGammasArray, true); // Photon-analysis analyzeV0CollAssoc(coll, fullV0s, bestLambdasArray, false); // Lambda-analysis } } //_______________________________________________ - // V0 nested loop + // Photon-V0 nested loop for (size_t i = 0; i < bestGammasArray.size(); ++i) { - auto gamma1 = fullV0s.rawIteratorAt(bestGammasArray[i]); //_______________________________________________ // Sigma0 loop @@ -2096,32 +2741,45 @@ struct sigma0builder { auto lambda = fullV0s.rawIteratorAt(bestLambdasArray[j]); // Building sigma0 candidate & filling tables - if (!buildSigma0(lambda, gamma1, coll, mcparticles)) - continue; + if constexpr (soa::is_table) { // using EMCal photons + auto gamma1 = fullEMCalClusters.rawIteratorAt(bestGammasArray[i]); + if (!buildEMCalSigma0(lambda, gamma1, coll, mcparticles, emcaltracksgrouped)) + continue; + } else { // using PCM photons + auto gamma1 = fullV0s.rawIteratorAt(bestGammasArray[i]); + if (!buildPCMSigma0(lambda, gamma1, coll, mcparticles)) + continue; + } } } //_______________________________________________ // KStar loop - if (fillKStarTables) { - for (size_t j = 0; j < bestKShortsArray.size(); ++j) { - auto kshort = fullV0s.rawIteratorAt(bestKShortsArray[j]); - - // Building kstar candidate & filling tables - if (!buildKStar(kshort, gamma1, coll, mcparticles)) - continue; + if constexpr (!soa::is_table) { // Don't use EMCal clusters here + if (fillKStarTables) { + auto gamma1 = fullV0s.rawIteratorAt(bestGammasArray[i]); + for (size_t j = 0; j < bestKShortsArray.size(); ++j) { + auto kshort = fullV0s.rawIteratorAt(bestKShortsArray[j]); + + // Building kstar candidate & filling tables + if (!buildKStar(kshort, gamma1, coll, mcparticles)) + continue; + } } } //_______________________________________________ // pi0 loop - if (fillPi0Tables) { - for (size_t j = i + 1; j < bestGammasArray.size(); ++j) { - auto gamma2 = fullV0s.rawIteratorAt(bestGammasArray[j]); - - // Building pi0 candidate & filling tables - if (!buildPi0(gamma1, gamma2, coll, mcparticles)) - continue; + if constexpr (!soa::is_table) { // Don't use EMCal clusters here + if (fillPi0Tables) { + auto gamma1 = fullV0s.rawIteratorAt(bestGammasArray[i]); + for (size_t j = i + 1; j < bestGammasArray.size(); ++j) { + auto gamma2 = fullV0s.rawIteratorAt(bestGammasArray[j]); + + // Building pi0 candidate & filling tables + if (!buildPi0(gamma1, gamma2, coll, mcparticles)) + continue; + } } } } @@ -2130,7 +2788,7 @@ struct sigma0builder { // Process photon and lambda candidates template - void runPhotonLambdaQA(TCollision const& collisions, TV0s const& fullV0s) + void runV0QA(TCollision const& collisions, TV0s const& fullV0s) { // Custom grouping std::vector> v0grouped(collisions.size()); @@ -2149,48 +2807,60 @@ struct sigma0builder { } float centrality = doPPAnalysis ? coll.centFT0M() : coll.centFT0C(); - histos.fill(HIST("PhotonLambdaQA/hEventCentrality"), centrality); + histos.fill(HIST("V0QA/hEventCentrality"), centrality); //_______________________________________________ // V0s loop for (size_t i = 0; i < v0grouped[coll.globalIndex()].size(); i++) { bool fPassPhotonSel = false; bool fPassLambdaSel = false; + bool fPassKShortSel = false; // Get V0 object auto v0 = fullV0s.rawIteratorAt(v0grouped[coll.globalIndex()][i]); if (fFillNoSelV0Histos) - fillHistos<0>(v0, coll); // Filling "all V0s" histograms + fillV0Histos<0>(v0, coll); // Filling "all V0s" histograms // Selection process fPassPhotonSel = processPhotonCandidate(v0); fPassLambdaSel = processLambdaCandidate(v0, coll); + fPassKShortSel = processKShortCandidate(v0, coll); // Reco part: if (fPassPhotonSel) { if (fFillSelPhotonHistos) - fillHistos<1>(v0, coll); + fillV0Histos<1>(v0, coll); // Fill analysis Histos: float PhotonY = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, o2::constants::physics::MassGamma); - histos.fill(HIST("PhotonLambdaQA/h3dPhotonMass"), centrality, v0.pt(), v0.mGamma()); - histos.fill(HIST("PhotonLambdaQA/h3dYPhotonMass"), PhotonY, v0.pt(), v0.mGamma()); - histos.fill(HIST("PhotonLambdaQA/h3dYPhotonRadius"), PhotonY, v0.pt(), v0.v0radius()); + histos.fill(HIST("V0QA/h3dPhotonMass"), centrality, v0.pt(), v0.mGamma()); + histos.fill(HIST("V0QA/h3dYPhotonMass"), PhotonY, v0.pt(), v0.mGamma()); + histos.fill(HIST("V0QA/h3dYPhotonRadius"), PhotonY, v0.pt(), v0.v0radius()); } if (fPassLambdaSel) { if (fFillSelLambdaHistos) - fillHistos<2>(v0, coll); + fillV0Histos<2>(v0, coll); // Fill analysis Histos: - histos.fill(HIST("PhotonLambdaQA/h3dLambdaMass"), centrality, v0.pt(), v0.mLambda()); - histos.fill(HIST("PhotonLambdaQA/h3dALambdaMass"), centrality, v0.pt(), v0.mAntiLambda()); + histos.fill(HIST("V0QA/h3dLambdaMass"), centrality, v0.pt(), v0.mLambda()); + histos.fill(HIST("V0QA/h3dALambdaMass"), centrality, v0.pt(), v0.mAntiLambda()); + + histos.fill(HIST("V0QA/h3dYLambdaMass"), v0.yLambda(), v0.pt(), v0.mLambda()); + histos.fill(HIST("V0QA/h3dYALambdaMass"), v0.yLambda(), v0.pt(), v0.mAntiLambda()); - histos.fill(HIST("PhotonLambdaQA/h3dYLambdaMass"), v0.yLambda(), v0.pt(), v0.mLambda()); - histos.fill(HIST("PhotonLambdaQA/h3dYALambdaMass"), v0.yLambda(), v0.pt(), v0.mAntiLambda()); + histos.fill(HIST("V0QA/h3dYRLambdaMass"), v0.yLambda(), v0.v0radius(), v0.mLambda()); + histos.fill(HIST("V0QA/h3dYRALambdaMass"), v0.yLambda(), v0.v0radius(), v0.mAntiLambda()); + } + + if (fPassKShortSel) { + if (fFillSelKShortHistos) + fillV0Histos<3>(v0, coll); - histos.fill(HIST("PhotonLambdaQA/h3dYRLambdaMass"), v0.yLambda(), v0.v0radius(), v0.mLambda()); - histos.fill(HIST("PhotonLambdaQA/h3dYRALambdaMass"), v0.yLambda(), v0.v0radius(), v0.mAntiLambda()); + // Fill analysis Histos: + histos.fill(HIST("V0QA/h3dKShortMass"), centrality, v0.pt(), v0.mK0Short()); + histos.fill(HIST("V0QA/h3dYKShortMass"), v0.yK0Short(), v0.pt(), v0.mK0Short()); + histos.fill(HIST("V0QA/h3dYRKShortMass"), v0.yK0Short(), v0.v0radius(), v0.mK0Short()); } // MC part: @@ -2200,25 +2870,35 @@ struct sigma0builder { // True Photon if (v0MC.pdgCode() == PDG_t::kGamma && fPassPhotonSel) { - histos.fill(HIST("PhotonLambdaQA/h3dTruePhotonMass"), centrality, v0MC.ptMC(), v0.mGamma()); + histos.fill(HIST("V0QA/h3dTruePhotonMass"), centrality, v0MC.ptMC(), v0.mGamma()); if (TMath::Abs(v0MC.pdgCodeMother()) == PDG_t::kSigma0) { // If from sigma0 or ASigma0 - histos.fill(HIST("PhotonLambdaQA/h2dTrueSigma0PhotonMass"), v0MC.ptMC(), v0.mGamma()); + histos.fill(HIST("V0QA/h2dTrueSigma0PhotonMass"), v0MC.ptMC(), v0.mGamma()); + } + if (v0MC.pdgCodeMother() == o2::constants::physics::kK0Star892) { // If from kstar + histos.fill(HIST("V0QA/h2dTrueKStarPhotonMass"), v0MC.ptMC(), v0.mGamma()); } } // True Lambda if (v0MC.pdgCode() == PDG_t::kLambda0 && fPassLambdaSel) { - histos.fill(HIST("PhotonLambdaQA/h3dTrueLambdaMass"), centrality, v0MC.ptMC(), v0.mLambda()); + histos.fill(HIST("V0QA/h3dTrueLambdaMass"), centrality, v0MC.ptMC(), v0.mLambda()); if (v0MC.pdgCodeMother() == PDG_t::kSigma0) { // If from sigma0 - histos.fill(HIST("PhotonLambdaQA/h2dTrueSigma0LambdaMass"), v0MC.ptMC(), v0.mLambda()); + histos.fill(HIST("V0QA/h2dTrueSigma0LambdaMass"), v0MC.ptMC(), v0.mLambda()); } } // True ALambda if (v0MC.pdgCode() == PDG_t::kLambda0Bar && fPassLambdaSel) { - histos.fill(HIST("PhotonLambdaQA/h3dTrueALambdaMass"), centrality, v0MC.ptMC(), v0.mAntiLambda()); + histos.fill(HIST("V0QA/h3dTrueALambdaMass"), centrality, v0MC.ptMC(), v0.mAntiLambda()); if (v0MC.pdgCodeMother() == PDG_t::kSigma0Bar) { // If from asigma0 - histos.fill(HIST("PhotonLambdaQA/h2dTrueASigma0ALambdaMass"), v0MC.ptMC(), v0.mAntiLambda()); + histos.fill(HIST("V0QA/h2dTrueASigma0ALambdaMass"), v0MC.ptMC(), v0.mAntiLambda()); + } + } + // True KShort + if (v0MC.pdgCode() == PDG_t::kK0Short && fPassKShortSel) { + histos.fill(HIST("V0QA/h3dTrueKShortMass"), centrality, v0MC.ptMC(), v0.mK0Short()); + if (v0MC.pdgCodeMother() == o2::constants::physics::Pdg::kK0Star892) { // If from kstar + histos.fill(HIST("V0QA/h2dTrueKStarKShortMass"), v0MC.ptMC(), v0.mK0Short()); } } } @@ -2227,25 +2907,249 @@ struct sigma0builder { } } + template + void runPCMVsEMCalQA(TCollision const& collisions, TV0s const& fullV0s, TEMCal const& fullEMCalClusters, TEMCalTracks const& emcaltracks, TMCParticles const& mcparticles) + { + + // Custom grouping + std::vector> v0grouped(collisions.size()); + std::vector> emclustersgrouped(collisions.size()); + std::vector emcaltracksgrouped(collisions.size(), false); + + // Grouping step: + for (const auto& v0 : fullV0s) { + v0grouped[v0.straCollisionId()].push_back(v0.globalIndex()); + } + + for (const auto& cluster : fullEMCalClusters) { + emclustersgrouped[cluster.collisionId()].push_back(cluster.globalIndex()); + } + + // Mapping emccluster to matched tracks + for (const auto& calotrack : emcaltracks) { + emcaltracksgrouped[calotrack.emcalclusterId()] = true; + } + + //_______________________________________________ + // Collisions loop + for (const auto& coll : collisions) { + // Event selection + if (eventSelections.fUseEventSelection) { + if (!IsEventAccepted(coll, true)) + continue; + } + + float centrality = doPPAnalysis ? coll.centFT0M() : coll.centFT0C(); + histos.fill(HIST("hEventCentrality"), centrality); + + //_______________________________________________ + // V0s loop + for (size_t i = 0; i < v0grouped[coll.globalIndex()].size(); i++) { + auto v0 = fullV0s.rawIteratorAt(v0grouped[coll.globalIndex()][i]); + + if (processPhotonCandidate(v0)) { // selecting PCM photons + + // Check if V0 has MC information + if (!v0.has_v0MCCore()) { + continue; + } + + auto v0MC = v0.template v0MCCore_as>(); + auto mcv0Photon = mcparticles.rawIteratorAt(v0MC.particleIdMC()); + + if (mcv0Photon.pdgCode() != PDG_t::kGamma || !mcv0Photon.isPhysicalPrimary() || TMath::Abs(mcv0Photon.y()) > 0.5) + continue; + + // MC pT histo + histos.fill(HIST("PhotonMCQA/hPCMPhotonMCpT"), mcv0Photon.pt()); + + // pT resolution + histos.fill(HIST("PhotonMCQA/h2dPCMPhotonMCpTResolution"), mcv0Photon.pt(), 1 - v0.pt() / mcv0Photon.pt()); + + // photon from sigma0/asigma0 + auto const& v0photonMothers = mcv0Photon.template mothers_as(); + if (!v0photonMothers.empty()) { + // Assumption: first mother is the physical one + auto const& v0photonMother = v0photonMothers.front(); + if (TMath::Abs(v0photonMother.pdgCode()) == PDG_t::kSigma0) { // Sigma0 or ASigma0 + // For efficiency + histos.fill(HIST("PhotonMCQA/hPCMSigma0PhotonMCpT"), mcv0Photon.pt()); + + // pT resolution + histos.fill(HIST("PhotonMCQA/h2dPCMSigma0PhotonMCpTResolution"), mcv0Photon.pt(), 1 - v0.pt() / mcv0Photon.pt()); + } + } + } + } + + // EMCal clusters loop + for (size_t icl = 0; icl < emclustersgrouped[coll.globalIndex()].size(); icl++) { + auto cluster = fullEMCalClusters.rawIteratorAt(emclustersgrouped[coll.globalIndex()][icl]); + + if (!processEMCalPhotonCandidate(cluster)) + continue; + + // ============================================================ + // --- Reco kinematics (assume photon mass = 0) + // ============================================================ + + float E = cluster.energy(); + float eta = cluster.eta(); + + float pt = E / std::cosh(eta); + + // ============================================================ + // --- MC matching + // ============================================================ + // Map to avoid double counting of photons in case of conversions (one cluster can be matched to both e+ and e-) + std::unordered_set uniquePhotonIds; + + // Loop over cluster contributors + for (size_t i = 0; i < cluster.mcParticleIds().size(); i++) { + + int mcId = cluster.mcParticleIds()[i]; + auto mcPart = mcparticles.iteratorAt(mcId); + + // ============================================================ + // Find photon ancestor (including conversions) + // ============================================================ + + int photonId = -1; + + // Case 1: particle itself is photon + if (mcPart.pdgCode() == PDG_t::kGamma) { + photonId = mcPart.globalIndex(); + } else { + // Case 2: climb ancestry to find photon + int candidateId = + aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain( + mcPart, mcparticles, std::vector{22}); + + if (candidateId >= 0) + photonId = candidateId; + } + + if (photonId < 0) + continue; + + // ============================================================ + // Avoid double counting (conversion case!) + // ============================================================ + + if (uniquePhotonIds.find(photonId) != uniquePhotonIds.end()) + continue; + + uniquePhotonIds.insert(photonId); + + auto mcPhoton = mcparticles.iteratorAt(photonId); + + // ============================================================ + // Select TRUE + PRIMARY photons + // ============================================================ + + if (mcPhoton.pdgCode() != PDG_t::kGamma || !mcPhoton.isPhysicalPrimary() || TMath::Abs(mcPhoton.y()) > 0.5) + continue; + + // ============================================================ + // Fill QA histos + // ============================================================ + + // MC pT histo + histos.fill(HIST("PhotonMCQA/hEMCalPhotonMCpT"), mcPhoton.pt()); + + // pT resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalPhotonMCpTResolution"), mcPhoton.pt(), 1 - pt / mcPhoton.pt()); + + // Energy resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalPhotonMCEnergyResolution"), mcPhoton.e(), 1 - cluster.energy() / mcPhoton.e()); + + // Eta resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalPhotonMCEtaResolution"), mcPhoton.eta(), cluster.eta() - mcPhoton.eta()); + + // Phi resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalPhotonMCPhiResolution"), mcPhoton.phi(), cluster.phi() - mcPhoton.phi()); + + // Fraction of energy Vs MC pT + histos.fill(HIST("PhotonMCQA/h2dEMCalPhotonMCFractionEnergy"), mcPhoton.pt(), cluster.amplitudeA()[i]); + + // photon from sigma0/asigma0 + auto const& photonMothers = mcPhoton.template mothers_as(); + if (!photonMothers.empty()) { + // Assumption: first mother is the physical one + auto const& photonMother = photonMothers.front(); + if (TMath::Abs(photonMother.pdgCode()) == PDG_t::kSigma0) { // Sigma0 or ASigma0 + // For efficiency + histos.fill(HIST("PhotonMCQA/hEMCalSigma0PhotonMCpT"), mcPhoton.pt()); + + // pT resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalSigma0PhotonMCpTResolution"), mcPhoton.pt(), 1 - pt / mcPhoton.pt()); + + // Energy resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalSigma0PhotonMCEnergyResolution"), mcPhoton.e(), 1 - cluster.energy() / mcPhoton.e()); + + // Eta resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalSigma0PhotonMCEtaResolution"), mcPhoton.eta(), cluster.eta() - mcPhoton.eta()); + + // Phi resolution + histos.fill(HIST("PhotonMCQA/h2dEMCalSigma0PhotonMCPhiResolution"), mcPhoton.phi(), cluster.phi() - mcPhoton.phi()); + + // Fraction of energy Vs MC pT + histos.fill(HIST("PhotonMCQA/h2dEMCalSigma0PhotonMCFractionEnergy"), mcPhoton.pt(), cluster.amplitudeA()[i]); + } + } + } + } + + } // end of collisions loop + + // Process MC generated photons + for (const auto& mcpart : mcparticles) { + if (mcpart.pdgCode() != PDG_t::kGamma || !mcpart.isPhysicalPrimary() || TMath::Abs(mcpart.y()) > 0.5) + continue; + + histos.fill(HIST("PhotonMCQA/hGenPhoton"), mcpart.pt()); + + // photon from sigma0/asigma0 + auto const& photonMothers = mcpart.template mothers_as(); + if (!photonMothers.empty()) { + // Assumption: first mother is the physical one + auto const& photonMother = photonMothers.front(); + if (TMath::Abs(photonMother.pdgCode()) == PDG_t::kSigma0) { // Sigma0 or ASigma0 + histos.fill(HIST("PhotonMCQA/hGenSigma0Photon"), mcpart.pt()); + } + } + } + } + // Sigma0 processing part void processRealData(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) { - dataProcess(collisions, fullV0s, nullptr); + dataProcess(collisions, fullV0s, nullptr, nullptr, nullptr); } void processRealDataWithTOF(soa::Join const& collisions, V0TOFStandardDerivedDatas const& fullV0s, dauTracks const&) { - dataProcess(collisions, fullV0s, nullptr); + dataProcess(collisions, fullV0s, nullptr, nullptr, nullptr); + } + + void processRealDataWithEMCal(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&, aod::EMCALClusters const& fullEMCalClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) + { + dataProcess(collisions, fullV0s, fullEMCalClusters, emcmatchedtracks, nullptr); } void processMonteCarlo(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { - dataProcess(collisions, fullV0s, mcParticles); + dataProcess(collisions, fullV0s, nullptr, nullptr, mcParticles); } void processMonteCarloWithTOF(soa::Join const& collisions, V0TOFDerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { - dataProcess(collisions, fullV0s, mcParticles); + dataProcess(collisions, fullV0s, nullptr, nullptr, mcParticles); + } + + void processMonteCarloWithEMCal(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&, EMCalMCClusters const& fullEMCalMCClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) + { + dataProcess(collisions, fullV0s, fullEMCalMCClusters, emcmatchedtracks, mcParticles); } void processGeneratedRun3(aod::McParticles const& mcParticles) @@ -2254,29 +3158,37 @@ struct sigma0builder { } // Photon and lambda-specific part (QA) - void processPhotonLambdaQA(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) + void processV0QA(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) + { + runV0QA(collisions, fullV0s); + } + + void processV0MCQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { - runPhotonLambdaQA(collisions, fullV0s); + runV0QA(collisions, fullV0s); } - void processPhotonLambdaMCQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) + void processV0Generated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& collisions) { - runPhotonLambdaQA(collisions, fullV0s); + runGenV0QA(mcCollisions, V0MCCores, collisions); } - void processPhotonLambdaGenerated(soa::Join const& mcCollisions, soa::Join const& V0MCCores, soa::Join const& collisions) + void processPCMVsEMCalQA(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, aod::McParticles const& mcParticles, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&, EMCalMCClusters const& fullEMCalMCClusters, aod::EMCALMatchedTracks const& emcmatchedtracks) { - runGenPhotonLambdaQA(mcCollisions, V0MCCores, collisions); + runPCMVsEMCalQA(collisions, fullV0s, fullEMCalMCClusters, emcmatchedtracks, mcParticles); } PROCESS_SWITCH(sigma0builder, processRealData, "process as if real data", true); - PROCESS_SWITCH(sigma0builder, processRealDataWithTOF, "process as if real data", false); + PROCESS_SWITCH(sigma0builder, processRealDataWithTOF, "process as if real data, uses TOF PID info", false); + PROCESS_SWITCH(sigma0builder, processRealDataWithEMCal, "process as if real data, uses EMCal clusters", false); PROCESS_SWITCH(sigma0builder, processMonteCarlo, "process as if MC data", false); PROCESS_SWITCH(sigma0builder, processMonteCarloWithTOF, "process as if MC data, uses TOF PID info", false); + PROCESS_SWITCH(sigma0builder, processMonteCarloWithEMCal, "process as if MC data, uses EMCal clusters", false); PROCESS_SWITCH(sigma0builder, processGeneratedRun3, "process generated MC info", false); - PROCESS_SWITCH(sigma0builder, processPhotonLambdaQA, "process QA of lambdas and photons", false); - PROCESS_SWITCH(sigma0builder, processPhotonLambdaMCQA, "process QA of lambdas and photons", false); - PROCESS_SWITCH(sigma0builder, processPhotonLambdaGenerated, "process QA of gen lambdas and photons", false); + PROCESS_SWITCH(sigma0builder, processV0QA, "process QA of lambdas and photons", false); + PROCESS_SWITCH(sigma0builder, processV0MCQA, "process QA of lambdas and photons", false); + PROCESS_SWITCH(sigma0builder, processV0Generated, "process QA of gen lambdas and photons", false); + PROCESS_SWITCH(sigma0builder, processPCMVsEMCalQA, "process QA of PCM and EMCal photons", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx new file mode 100644 index 00000000000..bb3f29449b8 --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/sigmaHadCorr.cxx @@ -0,0 +1,717 @@ +// 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 sigmaHadCorr.cxx +/// \brief Analysis task for sigma-hadron correlations +/// \author Francesco Mazzaschi + +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFSigmaHadTables.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" + +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using TracksFull = soa::Join; +using TracksFullMC = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; + +struct sigmaHadCand { + + float ptHad() const + { + return std::hypot(pxHad, pyHad); + } + float sigmaPt() const + { + return std::hypot(sigmaPx, sigmaPy); + } + + int sigmaCharge = 0; // Charge of the sigma candidate + float sigmaMass = -1.f; // Mass of the Sigma candidate + float sigmaPx = -1; // Px of the Sigma candidate + float sigmaPy = -1; // Py of the Sigma candidate + float sigmaPz = -1; // Pz of the Sigma candidate + float sigmaDauPx = -1; // Px of the daughter track from Sigma decay + float sigmaDauPy = -1; // Py of the daughter track from Sigma decay + float sigmaDauPz = -1; // Pz of the daughter track from Sigma decay + float sigmaDecRadius = -1; // Decay radius of the Sigma candidate + float sigmaCosPA = -1; // Cosine of pointing angle of the Sigma candidate + + int chargeHad = 0; // Charge of the hadron candidate + float pxHad = -1; // Px of the hadron candidate + float pyHad = -1; // Py of the hadron candidate + float pzHad = -1; // Pz of the hadron candidate + + float nSigmaTPCHad = -1; // Number of sigmas for the hadron candidate + float nSigmaTOFHad = -1; // Number of sigmas for the hadron candidate using TOF + + int kinkDauID = -1; // ID of the pion from Sigma decay in MC + int sigmaID = -1; // ID of the Sigma candidate in MC + int hadID = -1; // ID of the hadron candidate in MC +}; + +struct sigmaHadCorrTask { + + std::vector sigmaHadCandidates; // Vector to store Sigma-hadron candidates + Produces outputDataTable; // Output table for Sigma-hadron candidates + Produces outputDataTableMC; // Output table for Sigma-hadron candidates in MC + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rSigmaHad{"sigmaHad", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // Configurable for event selection + Configurable cutzvertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + + Configurable doSigmaPion{"doSigmaPion", false, "If true, pair Sigma with pions instead of protons"}; + Configurable doSigmaMinus{"doSigmaMinus", true, "If true, pair Sigma- candidates, else Sigma+"}; + Configurable cutMaxKStar{"cutMaxKStar", 1.5, "Maximum k* for Sigma-hadron pairs (GeV/c)"}; + + Configurable minPtSigma{"minPtSigma", 1.f, "Minimum pT for Sigma candidates (GeV/c)"}; + Configurable useRecalculatedSigmaMomentum{"useRecalculatedSigmaMomentum", true, "If true, compute k* using Sigma momentum recalculated from daughter kinematics"}; + Configurable cutDCAtoPVSigma{"cutDCAtoPVSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; + Configurable cutSigmaRadius{"cutSigmaRadius", 20.f, "Minimum radius for Sigma candidates (cm)"}; + Configurable cutSigmaMass{"cutSigmaMass", 0.3, "Sigma mass window (GeV/c^2)"}; + Configurable alphaAPCut{"alphaAPCut", 0., "Alpha AP cut for Sigma candidates"}; + Configurable qtAPCutLow{"qtAPCutLow", 0.15, "Lower qT AP cut for Sigma candidates (GeV/c)"}; + Configurable qtAPCutHigh{"qtAPCutHigh", 0.2, "Upper qT AP cut for Sigma candidates (GeV/c)"}; + Configurable cutEtaDaught{"cutEtaDaughter", 0.8f, "Eta cut for daughter tracks"}; + Configurable ptMinTOFKinkDau{"ptMinTOFKinkDau", 0.75f, "Minimum pT to require TOF for kink daughter PID (GeV/c)"}; + Configurable applyTOFPIDKinkDaughter{"applyTOFPIDKinkDaughter", false, "If true, apply TOF PID cut to the kink daughter track"}; + + Configurable cutNITSClusHad{"cutNITSClusHad", 5, "Minimum number of ITS clusters for hadron track"}; + Configurable cutNTPCClusHad{"cutNTPCClusHad", 90, "Minimum number of TPC clusters for hadron track"}; + Configurable ptMinHad{"ptMinHad", 0.2f, "Minimum pT for hadron track (GeV/c)"}; + Configurable ptMinTOFHad{"ptMinTOFHad", 0.75f, "Minimum pT to require TOF for hadron PID (GeV/c)"}; + Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "TPC nSigma cut for hadron track"}; + Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "TOF nSigma cut for hadron track"}; + + Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Sigma-hadron candidates"}; + Configurable fillSparseInvMassKstar{"fillSparseInvMassKstar", false, "If true, fill THn with invmass, k*, sigma charge, proton charge, sigma decay radius, cosPA, sigma pt"}; + + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; + Configurable nEvtMixingBkg{"nEvtMixingBkg", 5, "Number of events to mix for background reconstruction"}; + + Preslice kinkCandsPerCollisionPreslice = aod::kinkcand::collisionId; + Preslice tracksPerCollisionPreslice = aod::track::collisionId; + Preslice tracksMCPerCollisionPreslice = aod::track::collisionId; + + void init(InitContext const&) + { + // Axes + const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; + const AxisSpec nSigmaHadAxis{100, -5, 5, "n#sigma_{had}"}; + const AxisSpec sigmaMassAxis{50, 1.1, 1.3, "m (GeV/#it{c}^{2})"}; + const AxisSpec kStarAxis{200, 0.0, 2., "k* (GeV/#it{c})"}; + const AxisSpec ptHadAxis{100, 0.0, 6.0, "#it{p}_{T,had} (GeV/#it{c})"}; + const AxisSpec sigmaPtAxis{100, 0.0, 6.0, "#it{p}_{T,#Sigma} (GeV/#it{c})"}; + const AxisSpec sigmaPtAxisCoarse{30, 0.0, 6.0, "#it{p}_{T,#Sigma} (GeV/#it{c})"}; + const AxisSpec sigmaChargeAxis{2, -1.5, 1.5, "#Sigma charge"}; + const AxisSpec hadronChargeAxis{2, -1.5, 1.5, "Hadron charge"}; + const AxisSpec sigmaDecRadiusAxis{25, 14.5, 40.5, "#Sigma decay radius (cm)"}; + const AxisSpec sigmaDecRadiusAxisCoarse{5, 14.5, 40.5, "#Sigma decay radius (cm)"}; + const AxisSpec cosPAAxis{50, 0.9, 1.0, "cos(PA)"}; + const AxisSpec cosPAAxisCoarse{5, 0.9, 1.0, "cos(PA)"}; + const AxisSpec alphaAPAxis{100, -1.0, 1.0, "#alpha_{AP}"}; + const AxisSpec qtAPAxis{100, 0.0, 0.5, "q_{T,AP} (GeV/#it{c})"}; + const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; + + // qa histograms + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + // Dedicated QA folder + rSigmaHad.add("QA/h2TPCNSigmaHadVsPtHad", "TPC n#sigma_{had} vs #it{p}_{T,had}", {HistType::kTH2F, {ptHadAxis, nSigmaHadAxis}}); + rSigmaHad.add("QA/h2TOFNSigmaHadVsPtHad", "TOF n#sigma_{had} vs #it{p}_{T,had}", {HistType::kTH2F, {ptHadAxis, nSigmaHadAxis}}); + rSigmaHad.add("QA/hSigmaPt", "#Sigma #it{p}_{T}", {HistType::kTH1F, {sigmaPtAxis}}); + rSigmaHad.add("QA/hSigmaPtRecal", "#Sigma #it{p}_{T} recalculated", {HistType::kTH1F, {sigmaPtAxis}}); + rSigmaHad.add("QA/h2InvMassVsPtSigma", "m_{#Sigma} vs #it{p}_{T,#Sigma}", {HistType::kTH2F, {sigmaPtAxis, sigmaMassAxis}}); + rSigmaHad.add("QA/h2QtAPvsAlphaAP", "q_{T,AP} vs #alpha_{AP}", {HistType::kTH2F, {alphaAPAxis, qtAPAxis}}); + + if (fillSparseInvMassKstar) { + rSigmaHad.add("hSparseSigmaHad", + "7D THnSparse: invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt", + {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse}}); + rSigmaHad.add("hSparseSigmaHadMC", + "8D THnSparse (MC): invmass, k*, sigma charge, hadron charge, sigma decay radius, cosPA, sigma pt, k* gen", + {HistType::kTHnSparseF, {sigmaMassAxis, kStarAxis, sigmaChargeAxis, hadronChargeAxis, sigmaDecRadiusAxisCoarse, cosPAAxisCoarse, sigmaPtAxisCoarse, kStarAxis}}); + } + + LOG(info) << "Sigma-hadron correlation task initialized"; + LOG(info) << "Process SE enabled: " << doprocessSameEvent; + LOG(info) << "Process ME enabled: " << doprocessMixedEvent; + LOG(info) << "Process SE MC enabled: " << doprocessSameEventMC; + LOG(info) << "Process ME MC enabled: " << doprocessMixedEventMC; + LOG(info) << "Pairing mode: " << (doSigmaPion ? "Sigma-pion" : "Sigma-proton"); + } + + float getAlphaAP(const std::array& momMother, const std::array& momKink) + { + std::array momMissing = {momMother[0] - momKink[0], momMother[1] - momKink[1], momMother[2] - momKink[2]}; + float lQlP = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); + float lQlN = std::inner_product(momMother.begin(), momMother.end(), momMissing.begin(), 0.f); + return (lQlP - lQlN) / (lQlP + lQlN); + } + + float getQtAP(const std::array& momMother, const std::array& momKink) + { + float dp = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); + float p2V0 = std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f); + float p2A = std::inner_product(momKink.begin(), momKink.end(), momKink.begin(), 0.f); + return std::sqrt(p2A - dp * dp / p2V0); + } + + float getCosPA(const std::array& momMother, const std::array& decayVertex, const std::array& primaryVertex) + { + std::array decayVec = {decayVertex[0] - primaryVertex[0], decayVertex[1] - primaryVertex[1], decayVertex[2] - primaryVertex[2]}; + float dotProduct = std::inner_product(momMother.begin(), momMother.end(), decayVec.begin(), 0.f); + float momMotherMag = std::sqrt(std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f)); + float decayVecMag = std::sqrt(std::inner_product(decayVec.begin(), decayVec.end(), decayVec.begin(), 0.f)); + return dotProduct / (momMotherMag * decayVecMag); + } + + float getRecalculatedSigmaMomentum(float sigmaPx, float sigmaPy, float sigmaPz, float sigmaDauPx, float sigmaDauPy, float sigmaDauPz) + { + // Sigma- -> n + pi- (charged daughter = pion, neutral daughter = neutron) + // Sigma+ -> p + pi0 (charged daughter = proton, neutral daughter = pi0) + float massChargedDau = doSigmaMinus ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; + float massNeutralDau = doSigmaMinus ? o2::constants::physics::MassNeutron : o2::constants::physics::MassPionNeutral; + float massSigma = doSigmaMinus ? o2::constants::physics::MassSigmaMinus : o2::constants::physics::MassSigmaPlus; + + float pMother = std::sqrt(sigmaPx * sigmaPx + sigmaPy * sigmaPy + sigmaPz * sigmaPz); + if (pMother < 1e-6f) { + return -999.f; + } + float versorX = sigmaPx / pMother; + float versorY = sigmaPy / pMother; + float versorZ = sigmaPz / pMother; + float eChDau = std::sqrt(massChargedDau * massChargedDau + sigmaDauPx * sigmaDauPx + sigmaDauPy * sigmaDauPy + sigmaDauPz * sigmaDauPz); + float a = versorX * sigmaDauPx + versorY * sigmaDauPy + versorZ * sigmaDauPz; + float K = massSigma * massSigma + massChargedDau * massChargedDau - massNeutralDau * massNeutralDau; + float A = 4.f * (eChDau * eChDau - a * a); + float B = -4.f * a * K; + float C = 4.f * eChDau * eChDau * massSigma * massSigma - K * K; + if (std::abs(A) < 1e-6f) { + return -999.f; + } + float D = B * B - 4.f * A * C; + if (D < 0.f) { + return -999.f; + } + float sqrtD = std::sqrt(D); + float P1 = (-B + sqrtD) / (2.f * A); + float P2 = (-B - sqrtD) / (2.f * A); + if (P2 < 0.f && P1 < 0.f) { + return -999.f; + } + if (P2 < 0.f) { + return P1; + } + float p1Diff = std::abs(P1 - pMother); + float p2Diff = std::abs(P2 - pMother); + return (p1Diff < p2Diff) ? P1 : P2; + } + + std::array getSigmaMomentumForKstar(float sigmaPx, float sigmaPy, float sigmaPz, float sigmaDauPx, float sigmaDauPy, float sigmaDauPz) + { + std::array sigmaMomentum = {sigmaPx, sigmaPy, sigmaPz}; + if (!useRecalculatedSigmaMomentum) { + return sigmaMomentum; + } + + float pNew = getRecalculatedSigmaMomentum(sigmaPx, sigmaPy, sigmaPz, sigmaDauPx, sigmaDauPy, sigmaDauPz); + if (pNew <= 0.f) { + return sigmaMomentum; + } + + float pOld = std::sqrt(sigmaPx * sigmaPx + sigmaPy * sigmaPy + sigmaPz * sigmaPz); + if (pOld <= 0.f) { + return sigmaMomentum; + } + + float scale = pNew / pOld; + sigmaMomentum[0] *= scale; + sigmaMomentum[1] *= scale; + sigmaMomentum[2] *= scale; + return sigmaMomentum; + } + + float getHadTrackMass() + { + return doSigmaPion ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; + } + + float getSigmaMassForKstar() + { + return doSigmaMinus ? o2::constants::physics::MassSigmaMinus : o2::constants::physics::MassSigmaPlus; + } + + template + float getTPCNSigmaHad(const Ttrack& track) + { + return doSigmaPion ? track.tpcNSigmaPi() : track.tpcNSigmaPr(); + } + + template + float getTOFNSigmaHad(const Ttrack& track) + { + return doSigmaPion ? track.tofNSigmaPi() : track.tofNSigmaPr(); + } + + TLorentzVector trackSum, PartOneCMS, PartTwoCMS, trackRelK; + float getKStar(float sigmaPx, float sigmaPy, float sigmaPz, float pxHad, float pyHad, float pzHad) + { + TLorentzVector part1; // Sigma + TLorentzVector part2; // Hadron track (proton/pion) + part1.SetXYZM(sigmaPx, sigmaPy, sigmaPz, getSigmaMassForKstar()); + part2.SetXYZM(pxHad, pyHad, pzHad, getHadTrackMass()); + trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); + PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + + template + bool selectHadTrack(const Ttrack& candidate) + { + if (candidate.pt() < ptMinHad) { + return false; + } + if (std::abs(getTPCNSigmaHad(candidate)) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusHad || std::abs(candidate.eta()) > cutEtaDaught) { + return false; + } + + if (candidate.itsNCls() < cutNITSClusHad) { + return false; + } + + if (!candidate.hasTOF()) { + return false; + } + if (std::abs(getTOFNSigmaHad(candidate)) > cutNSigmaTOF) { + return false; + } + return true; // Track is selected + } + + template + bool selectSigma(aod::KinkCands::iterator const& sigmaCand, Ttrack const& kinkDauTrack) + { + float mass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + std::array momDaug = {sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; + float alphaAP = getAlphaAP(momMoth, momDaug); + float qtAP = getQtAP(momMoth, momDaug); + + if (alphaAP > alphaAPCut || (qtAP < qtAPCutLow || qtAP > qtAPCutHigh)) { + return false; + } + float decRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); + if (decRad < cutSigmaRadius) { + return false; + } + + if (doSigmaMinus) { + if (mass < o2::constants::physics::MassSigmaMinus - cutSigmaMass || mass > o2::constants::physics::MassSigmaMinus + cutSigmaMass) { + return false; + } + if (std::abs(kinkDauTrack.tpcNSigmaPi()) > cutNSigmaTPC) { + return false; + } + } else { + if (mass < o2::constants::physics::MassSigmaPlus - cutSigmaMass || mass > o2::constants::physics::MassSigmaPlus + cutSigmaMass) { + return false; + } + if (std::abs(kinkDauTrack.tpcNSigmaPr()) > cutNSigmaTPC) { + return false; + } + } + + if (applyTOFPIDKinkDaughter) { + if (kinkDauTrack.pt() >= ptMinTOFKinkDau) { + if (!kinkDauTrack.hasTOF()) { + return false; + } + float kinkDauTOFNSigma = doSigmaMinus ? kinkDauTrack.tofNSigmaPi() : kinkDauTrack.tofNSigmaPr(); + if (std::abs(kinkDauTOFNSigma) > cutNSigmaTOF) { + return false; + } + } + } + + if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma) { + return false; + } + return true; + } + + template + void fillTreeAndHistograms(aod::KinkCands const& kinkCands, Ttrack const& tracksDauSigma, Ttrack const& tracks, Tcollision const& collision, bool isMC) + { + for (const auto& sigmaCand : kinkCands) { + auto kinkDauTrack = tracksDauSigma.rawIteratorAt(sigmaCand.trackDaugId()); + if (!selectSigma(sigmaCand, kinkDauTrack)) { + continue; + } + + std::array momMothAll = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + std::array momDaugAll = {sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; + float alphaAP = getAlphaAP(momMothAll, momDaugAll); + float qtAP = getQtAP(momMothAll, momDaugAll); + rSigmaHad.fill(HIST("QA/h2QtAPvsAlphaAP"), alphaAP, qtAP); + + auto sigmaPRecal = getSigmaMomentumForKstar(sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth(), + sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()); + float sigmaPtRecal = std::hypot(sigmaPRecal[0], sigmaPRecal[1]); + float sigmaMassForQa = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + + if (sigmaPtRecal < minPtSigma) { + continue; + } + + rSigmaHad.fill(HIST("QA/hSigmaPt"), sigmaCand.ptMoth()); + rSigmaHad.fill(HIST("QA/hSigmaPtRecal"), sigmaPtRecal); + rSigmaHad.fill(HIST("QA/h2InvMassVsPtSigma"), sigmaPtRecal, sigmaMassForQa); + + for (const auto& hadTrack : tracks) { + if (hadTrack.globalIndex() == sigmaCand.trackDaugId()) { + continue; + } + + if (!selectHadTrack(hadTrack)) { + continue; + } + + sigmaHadCand candidate; + candidate.sigmaCharge = sigmaCand.mothSign(); + candidate.sigmaPx = sigmaCand.pxMoth(); + candidate.sigmaPy = sigmaCand.pyMoth(); + candidate.sigmaPz = sigmaCand.pzMoth(); + candidate.sigmaDauPx = sigmaCand.pxDaug(); + candidate.sigmaDauPy = sigmaCand.pyDaug(); + candidate.sigmaDauPz = sigmaCand.pzDaug(); + candidate.sigmaDecRadius = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); + + std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + std::array decayVtx = {sigmaCand.xDecVtx(), sigmaCand.yDecVtx(), sigmaCand.zDecVtx()}; + std::array primaryVtx = {collision.posX(), collision.posY(), collision.posZ()}; + candidate.sigmaCosPA = getCosPA(momMoth, decayVtx, primaryVtx); + + candidate.chargeHad = hadTrack.sign(); + candidate.pxHad = hadTrack.px(); + candidate.pyHad = hadTrack.py(); + candidate.pzHad = hadTrack.pz(); + candidate.nSigmaTPCHad = getTPCNSigmaHad(hadTrack); + candidate.nSigmaTOFHad = getTOFNSigmaHad(hadTrack); + candidate.sigmaMass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); + + candidate.sigmaID = sigmaCand.trackMothId(); + candidate.kinkDauID = sigmaCand.trackDaugId(); + candidate.hadID = hadTrack.globalIndex(); + + float kStar = getKStar(sigmaPRecal[0], sigmaPRecal[1], sigmaPRecal[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + if (kStar > cutMaxKStar) { + continue; + } + + rSigmaHad.fill(HIST("QA/h2TPCNSigmaHadVsPtHad"), candidate.ptHad(), candidate.nSigmaTPCHad); + if (hadTrack.hasTOF()) { + rSigmaHad.fill(HIST("QA/h2TOFNSigmaHadVsPtHad"), candidate.ptHad(), candidate.nSigmaTOFHad); + } + if (fillSparseInvMassKstar && !isMC) { + rSigmaHad.fill(HIST("hSparseSigmaHad"), + candidate.sigmaMass, + kStar, + candidate.sigmaCharge, + candidate.chargeHad, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + sigmaPtRecal); + } + sigmaHadCandidates.push_back(candidate); + } + } + } + + void processSameEvent(CollisionsFull const& collisions, aod::KinkCands const& kinkCands, TracksFull const& tracks) + { + for (auto const& collision : collisions) { + + sigmaHadCandidates.clear(); + auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); + auto tracks_c = tracks.sliceBy(tracksPerCollisionPreslice, collision.globalIndex()); + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + fillTreeAndHistograms(kinkCands_c, tracks, tracks_c, collision, false); + if (fillOutputTree) { + // Fill output table + for (const auto& candidate : sigmaHadCandidates) { + outputDataTable(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad); + } + } + } + } + PROCESS_SWITCH(sigmaHadCorrTask, processSameEvent, "Process Same event", true); + + // Processing Event Mixing + SliceCache cache; + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; + + void processMixedEvent(const CollisionsFull& collisions, const aod::KinkCands& kinkCands, const TracksFull& tracks) + { + for (auto const& [collision1, collision2] : + selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { + continue; + } + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { + continue; + } + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, false); + + if (fillOutputTree) { + // Fill output table + for (const auto& candidate : sigmaHadCandidates) { + outputDataTable(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad); + } + } + } + LOG(debug) << "Processing mixed event"; + } + PROCESS_SWITCH(sigmaHadCorrTask, processMixedEvent, "Process Mixed event", false); + + void processSameEventMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, TracksFullMC const& tracks, aod::McParticles const&) + { + for (auto const& collision : collisions) { + + sigmaHadCandidates.clear(); + auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); + auto tracks_c = tracks.sliceBy(tracksMCPerCollisionPreslice, collision.globalIndex()); + + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + fillTreeAndHistograms(kinkCands_c, tracks, tracks_c, collision, true); + for (const auto& candidate : sigmaHadCandidates) { + auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); + auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); + auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); + + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) { + continue; // Skip candidates where MC truth is not available + } + + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartHad = mcLabelHad.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); + + if (fillSparseInvMassKstar) { + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz); + float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + rSigmaHad.fill(HIST("hSparseSigmaHadMC"), + candidate.sigmaMass, + kStarRec, + candidate.sigmaCharge, + candidate.chargeHad, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + sigmaPtUsed, + kStarGen); + } + + if (fillOutputTree) { + outputDataTableMC(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad, + pdgSigma, + pdgSigmaDau, + pdgHad, + sigmaPtGen, + hadPtGen, + kStarGen); + } + } + } + } + PROCESS_SWITCH(sigmaHadCorrTask, processSameEventMC, "Process Same event MC", false); + + void processMixedEventMC(const CollisionsFullMC& collisions, const aod::KinkCands& kinkCands, const TracksFullMC& tracks, const aod::McParticles&) + { + for (auto const& [collision1, collision2] : + selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + + sigmaHadCandidates.clear(); + if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { + continue; + } + if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { + continue; + } + auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); + auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); + fillTreeAndHistograms(kinkCands_c1, tracks, tracks_c2, collision1, true); + + for (const auto& candidate : sigmaHadCandidates) { + auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); + auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); + auto mcLabelHad = tracks.rawIteratorAt(candidate.hadID); + + if (!mcLabelSigma.has_mcParticle() || !mcLabelSigmaDau.has_mcParticle() || !mcLabelHad.has_mcParticle()) { + continue; // Skip candidates where MC truth is not available + } + + auto mcPartSigma = mcLabelSigma.mcParticle_as(); + auto mcPartSigmaDau = mcLabelSigmaDau.mcParticle_as(); + auto mcPartHad = mcLabelHad.mcParticle_as(); + auto pdgSigma = mcPartSigma.pdgCode(); + auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcPartSigmaDau.pdgCode() : -999; + auto pdgHad = mcLabelHad.has_mcParticle() ? mcPartHad.pdgCode() : -999; + float sigmaPtGen = std::hypot(mcPartSigma.px(), mcPartSigma.py()); + float hadPtGen = std::hypot(mcPartHad.px(), mcPartHad.py()); + float kStarGen = getKStar(mcPartSigma.px(), mcPartSigma.py(), mcPartSigma.pz(), mcPartHad.px(), mcPartHad.py(), mcPartHad.pz()); + + if (fillSparseInvMassKstar) { + auto sigmaMomForKstar = getSigmaMomentumForKstar(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, + candidate.sigmaDauPx, candidate.sigmaDauPy, candidate.sigmaDauPz); + float kStarRec = getKStar(sigmaMomForKstar[0], sigmaMomForKstar[1], sigmaMomForKstar[2], candidate.pxHad, candidate.pyHad, candidate.pzHad); + float sigmaPtUsed = std::hypot(sigmaMomForKstar[0], sigmaMomForKstar[1]); + rSigmaHad.fill(HIST("hSparseSigmaHadMC"), + candidate.sigmaMass, + kStarRec, + candidate.sigmaCharge, + candidate.chargeHad, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + sigmaPtUsed, + kStarGen); + } + + if (fillOutputTree) { + outputDataTableMC(candidate.sigmaCharge, + candidate.sigmaPx, + candidate.sigmaPy, + candidate.sigmaPz, + candidate.sigmaDauPx, + candidate.sigmaDauPy, + candidate.sigmaDauPz, + candidate.sigmaDecRadius, + candidate.sigmaCosPA, + candidate.chargeHad, + candidate.pxHad, + candidate.pyHad, + candidate.pzHad, + candidate.nSigmaTPCHad, + candidate.nSigmaTOFHad, + pdgSigma, + pdgSigmaDau, + pdgHad, + sigmaPtGen, + hadPtGen, + kStarGen); + } + } + } + LOG(debug) << "Processing mixed event MC"; + } + PROCESS_SWITCH(sigmaHadCorrTask, processMixedEventMC, "Process Mixed event MC", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx b/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx deleted file mode 100644 index 17741f3a8c1..00000000000 --- a/PWGLF/TableProducer/Strangeness/sigmaProtonCorr.cxx +++ /dev/null @@ -1,497 +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 sigmaProtonCorr.cxx -/// \brief Analysis task for sigma-proton correlations -/// \author Francesco Mazzaschi - -#include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "PWGLF/DataModel/LFSigmaProtonTables.h" - -#include "Common/Core/PID/PIDTOF.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" - -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using TracksFull = soa::Join; -using TracksFullMC = soa::Join; -using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; - -struct sigmaProtonCand { - - float ptPr() const - { - return std::hypot(pxPr, pyPr); - } - float sigmaPt() const - { - return std::hypot(sigmaPx, sigmaPy); - } - - int sigmaCharge = 0; // Charge of the sigma candidate - int sigmaMass = -1; // Mass of the Sigma candidate - float sigmaPx = -1; // Px of the Sigma candidate - float sigmaPy = -1; // Py of the Sigma candidate - float sigmaPz = -1; // Pz of the Sigma candidate - float sigmaDauPx = -1; // Px of the daughter track from Sigma decay - float sigmaDauPy = -1; // Py of the daughter track from Sigma decay - float sigmaDauPz = -1; // Pz of the daughter track from Sigma decay - float sigmaDecRadius = -1; // Decay radius of the Sigma candidate - float sigmaCosPA = -1; // Cosine of pointing angle of the Sigma candidate - - int chargePr = 0; // Charge of the proton candidate - float pxPr = -1; // Px of the proton candidate - float pyPr = -1; // Py of the proton candidate - float pzPr = -1; // Pz of the proton candidate - - float nSigmaTPCPr = -1; // Number of sigmas for the proton candidate - float nSigmaTOFPr = -1; // Number of sigmas for the proton candidate using TOF - - int kinkDauID = -1; // ID of the pion from Sigma decay in MC - int sigmaID = -1; // ID of the Sigma candidate in MC - int prID = -1; // ID of the proton candidate in MC -}; - -struct sigmaProtonCorrTask { - - std::vector sigmaProtonCandidates; // Vector to store Sigma-Proton candidates - Produces outputDataTable; // Output table for Sigma-Proton candidates - Produces outputDataTableMC; // Output table for Sigma-Proton candidates in MC - // Histograms are defined with HistogramRegistry - HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rSigmaProton{"sigmaProton", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // Configurable for event selection - Configurable cutzvertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; - - Configurable minPtSigma{"minPtSigma", 1.f, "Minimum pT for Sigma candidates (GeV/c)"}; - Configurable cutEtaDaught{"cutEtaDaughter", 0.8f, "Eta cut for daughter tracks"}; - Configurable cutDCAtoPVSigma{"cutDCAtoPVSigma", 0.1f, "Max DCA to primary vertex for Sigma candidates (cm)"}; - Configurable doSigmaMinus{"doSigmaMinus", true, "If true, pair Sigma- candidates, else Sigma+"}; - Configurable cutSigmaRadius{"cutSigmaRadius", 20.f, "Minimum radius for Sigma candidates (cm)"}; - Configurable cutSigmaMass{"cutSigmaMass", 0.3, "Sigma mass window (GeV/c^2)"}; - Configurable alphaAPCut{"alphaAPCut", 0., "Alpha AP cut for Sigma candidates"}; - Configurable qtAPCutLow{"qtAPCutLow", 0.15, "Lower qT AP cut for Sigma candidates (GeV/c)"}; - Configurable qtAPCutHigh{"qtAPCutHigh", 0.2, "Upper qT AP cut for Sigma candidates (GeV/c)"}; - - Configurable cutNITSClusPr{"cutNITSClusPr", 5, "Minimum number of ITS clusters for proton candidate"}; - Configurable cutNTPCClusPr{"cutNTPCClusPr", 90, "Minimum number of TPC clusters for proton candidate"}; - Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "NSigmaTPCPr"}; - Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "NSigmaTOFPr"}; - - Configurable cutMaxKStar{"cutMaxKStar", 1.5, "Maximum k* for Sigma-Proton pairs (GeV/c)"}; - - Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Sigma-Proton candidates"}; - - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; - Configurable nEvtMixingBkg{"nEvtMixingBkg", 5, "Number of events to mix for background reconstruction"}; - - Preslice kinkCandsPerCollisionPreslice = aod::kinkcand::collisionId; - Preslice tracksPerCollisionPreslice = aod::track::collisionId; - Preslice tracksMCPerCollisionPreslice = aod::track::collisionId; - - void init(InitContext const&) - { - // Axes - const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; - const AxisSpec nSigmaPrAxis{100, -5, 5, "n#sigma_{#pr}"}; - const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; - const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; - - // qa histograms - rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - rSigmaProton.add("h2PtMassSigma", "h2PtMassSigma", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rSigmaProton.add("h2PtPrNSigma", "h2PtPrNSigma", {HistType::kTH2F, {ptAxis, nSigmaPrAxis}}); - rSigmaProton.add("h2PtPrNSigmaTOF", "h2PtPrNSigmaTOF", {HistType::kTH2F, {ptAxis, nSigmaPrAxis}}); - - LOG(info) << "Sigma-Proton correlation task initialized"; - LOG(info) << "Process SE enabled: " << doprocessSameEvent; - LOG(info) << "Process ME enabled: " << doprocessMixedEvent; - LOG(info) << "Process SE MC enabled: " << doprocessSameEventMC; - LOG(info) << "Process ME MC enabled: " << doprocessMixedEventMC; - } - - float getAlphaAP(const std::array& momMother, const std::array& momKink) - { - std::array momMissing = {momMother[0] - momKink[0], momMother[1] - momKink[1], momMother[2] - momKink[2]}; - float lQlP = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); - float lQlN = std::inner_product(momMother.begin(), momMother.end(), momMissing.begin(), 0.f); - return (lQlP - lQlN) / (lQlP + lQlN); - } - - float getQtAP(const std::array& momMother, const std::array& momKink) - { - float dp = std::inner_product(momMother.begin(), momMother.end(), momKink.begin(), 0.f); - float p2V0 = std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f); - float p2A = std::inner_product(momKink.begin(), momKink.end(), momKink.begin(), 0.f); - return std::sqrt(p2A - dp * dp / p2V0); - } - - float getCosPA(const std::array& momMother, const std::array& decayVertex, const std::array& primaryVertex) - { - std::array decayVec = {decayVertex[0] - primaryVertex[0], decayVertex[1] - primaryVertex[1], decayVertex[2] - primaryVertex[2]}; - float dotProduct = std::inner_product(momMother.begin(), momMother.end(), decayVec.begin(), 0.f); - float momMotherMag = std::sqrt(std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f)); - float decayVecMag = std::sqrt(std::inner_product(decayVec.begin(), decayVec.end(), decayVec.begin(), 0.f)); - return dotProduct / (momMotherMag * decayVecMag); - } - - TLorentzVector trackSum, PartOneCMS, PartTwoCMS, trackRelK; - float getKStar(const sigmaProtonCand& candidate) - { - TLorentzVector part1; // Sigma - TLorentzVector part2; // Proton - part1.SetXYZM(candidate.sigmaPx, candidate.sigmaPy, candidate.sigmaPz, o2::constants::physics::MassSigmaMinus); - part2.SetXYZM(candidate.pxPr, candidate.pyPr, candidate.pzPr, o2::constants::physics::MassProton); - trackSum = part1 + part2; - const float beta = trackSum.Beta(); - const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); - const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); - const float betaz = beta * std::cos(trackSum.Theta()); - PartOneCMS.SetXYZM(part1.Px(), part1.Py(), part1.Pz(), part1.M()); - PartTwoCMS.SetXYZM(part2.Px(), part2.Py(), part2.Pz(), part2.M()); - const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); - PartOneCMS = boostPRF(PartOneCMS); - PartTwoCMS = boostPRF(PartTwoCMS); - trackRelK = PartOneCMS - PartTwoCMS; - return 0.5 * trackRelK.P(); - } - - template - bool selectPrTrack(const Ttrack& candidate) - { - if (std::abs(candidate.tpcNSigmaPr()) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPr || std::abs(candidate.eta()) > cutEtaDaught) { - return false; - } - - if (candidate.itsNCls() < cutNITSClusPr) { - return false; - } - - float ptMinTOF = 0.75f; // Minimum pT to use TOF for proton PID - if (candidate.pt() < ptMinTOF) { - return true; // No TOF cut for low pT - } - - if (!candidate.hasTOF()) { - return false; - } - if (std::abs(candidate.tofNSigmaPr()) > cutNSigmaTOF) { - return false; - } - return true; // Track is selected - } - - template - bool selectSigma(aod::KinkCands::iterator const& sigmaCand, Ttrack const&) - { - - auto kinkDauTrack = sigmaCand.trackDaug_as(); - float mass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); - std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; - std::array momDaug = {sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; - float alphaAP = getAlphaAP(momMoth, momDaug); - float qtAP = getQtAP(momMoth, momDaug); - - if (sigmaCand.ptMoth() < minPtSigma) { - return false; - } - - if (alphaAP > alphaAPCut || (qtAP < qtAPCutLow || qtAP > qtAPCutHigh)) { - return false; - } - float decRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); - if (decRad < cutSigmaRadius) { - return false; - } - - if (doSigmaMinus) { - if (mass < o2::constants::physics::MassSigmaMinus - cutSigmaMass || mass > o2::constants::physics::MassSigmaMinus + cutSigmaMass) { - return false; - } - if (std::abs(kinkDauTrack.tpcNSigmaPi()) > cutNSigmaTPC) { - return false; - } - } else { - if (mass < o2::constants::physics::MassSigmaPlus - cutSigmaMass || mass > o2::constants::physics::MassSigmaPlus + cutSigmaMass) { - return false; - } - if (std::abs(kinkDauTrack.tpcNSigmaPr()) > cutNSigmaTPC) { - return false; - } - } - if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma) { - return false; - } - return true; - } - - template - void fillTreeAndHistograms(aod::KinkCands const& kinkCands, Ttrack const& tracksDauSigma, Ttrack const& tracks, Tcollision const& collision) - { - for (const auto& sigmaCand : kinkCands) { - if (selectSigma(sigmaCand, tracksDauSigma)) { - if (doSigmaMinus) { - rSigmaProton.fill(HIST("h2PtMassSigma"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); - } else { - rSigmaProton.fill(HIST("h2PtMassSigma"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); - } - - for (const auto& prTrack : tracks) { - if (!selectPrTrack(prTrack)) { - continue; - } - - sigmaProtonCand candidate; - candidate.sigmaCharge = sigmaCand.mothSign(); - candidate.sigmaPx = sigmaCand.pxMoth(); - candidate.sigmaPy = sigmaCand.pyMoth(); - candidate.sigmaPz = sigmaCand.pzMoth(); - candidate.sigmaDauPx = sigmaCand.pxDaug(); - candidate.sigmaDauPy = sigmaCand.pyDaug(); - candidate.sigmaDauPz = sigmaCand.pzDaug(); - candidate.sigmaDecRadius = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); - - std::array momMoth = {sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; - std::array decayVtx = {sigmaCand.xDecVtx(), sigmaCand.yDecVtx(), sigmaCand.zDecVtx()}; - std::array primaryVtx = {collision.posX(), collision.posY(), collision.posZ()}; - candidate.sigmaCosPA = getCosPA(momMoth, decayVtx, primaryVtx); - - candidate.chargePr = prTrack.sign(); - candidate.pxPr = prTrack.px(); - candidate.pyPr = prTrack.py(); - candidate.pzPr = prTrack.pz(); - candidate.nSigmaTPCPr = prTrack.tpcNSigmaPr(); - candidate.nSigmaTOFPr = prTrack.tofNSigmaPr(); - candidate.sigmaMass = doSigmaMinus ? sigmaCand.mSigmaMinus() : sigmaCand.mSigmaPlus(); - - candidate.sigmaID = sigmaCand.trackMothId(); - candidate.kinkDauID = sigmaCand.trackDaugId(); - candidate.prID = prTrack.globalIndex(); - - if (getKStar(candidate) > cutMaxKStar) { - continue; - } - - rSigmaProton.fill(HIST("h2PtPrNSigma"), candidate.ptPr(), candidate.nSigmaTPCPr); - if (prTrack.hasTOF()) { - rSigmaProton.fill(HIST("h2PtPrNSigmaTOF"), candidate.ptPr(), candidate.nSigmaTOFPr); - } - sigmaProtonCandidates.push_back(candidate); - } - } - } - } - - void processSameEvent(CollisionsFull const& collisions, aod::KinkCands const& kinkCands, TracksFull const& tracks) - { - for (auto const& collision : collisions) { - - sigmaProtonCandidates.clear(); - auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); - auto tracks_c = tracks.sliceBy(tracksPerCollisionPreslice, collision.globalIndex()); - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { - continue; - } - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision); - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - outputDataTable(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr); - } - } - } - } - PROCESS_SWITCH(sigmaProtonCorrTask, processSameEvent, "Process Same event", true); - - // Processing Event Mixing - SliceCache cache; - using BinningType = ColumnBinningPolicy; - BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; - - void processMixedEvent(const CollisionsFull& collisions, const aod::KinkCands& kinkCands, const TracksFull& tracks) - { - for (auto const& [collision1, collision2] : - selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { - if (collision1.index() == collision2.index()) - continue; - - sigmaProtonCandidates.clear(); - if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { - continue; - } - if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { - continue; - } - auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1); - - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - outputDataTable(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr); - } - } - } - LOG(debug) << "Processing mixed event"; - } - PROCESS_SWITCH(sigmaProtonCorrTask, processMixedEvent, "Process Mixed event", false); - - void processSameEventMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, TracksFullMC const& tracks, aod::McParticles const&) - { - for (auto const& collision : collisions) { - - sigmaProtonCandidates.clear(); - auto kinkCands_c = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision.globalIndex()); - auto tracks_c = tracks.sliceBy(tracksMCPerCollisionPreslice, collision.globalIndex()); - - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { - continue; - } - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - fillTreeAndHistograms(kinkCands_c, tracks_c, tracks_c, collision); - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); - auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); - auto mcLabelPr = tracks.rawIteratorAt(candidate.prID); - auto pdgSigma = mcLabelSigma.has_mcParticle() ? mcLabelSigma.mcParticle_as().pdgCode() : -999; - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcLabelSigmaDau.mcParticle_as().pdgCode() : -999; - auto pdgPr = mcLabelPr.has_mcParticle() ? mcLabelPr.mcParticle_as().pdgCode() : -999; - outputDataTableMC(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr, - pdgSigma, - pdgSigmaDau, - pdgPr); - } - } - } - } - PROCESS_SWITCH(sigmaProtonCorrTask, processSameEventMC, "Process Same event MC", false); - - void processMixedEventMC(const CollisionsFullMC& collisions, const aod::KinkCands& kinkCands, const TracksFullMC& tracks, const aod::McParticles&) - { - for (auto const& [collision1, collision2] : - selfCombinations(colBinning, nEvtMixingBkg, -1, collisions, collisions)) { - if (collision1.index() == collision2.index()) - continue; - - sigmaProtonCandidates.clear(); - if (std::abs(collision1.posZ()) > cutzvertex || !collision1.sel8()) { - continue; - } - if (std::abs(collision2.posZ()) > cutzvertex || !collision2.sel8()) { - continue; - } - auto kinkCands_c1 = kinkCands.sliceBy(kinkCandsPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c1 = tracks.sliceBy(tracksPerCollisionPreslice, collision1.globalIndex()); - auto tracks_c2 = tracks.sliceBy(tracksPerCollisionPreslice, collision2.globalIndex()); - fillTreeAndHistograms(kinkCands_c1, tracks_c1, tracks_c2, collision1); - - if (fillOutputTree) { - // Fill output table - for (const auto& candidate : sigmaProtonCandidates) { - auto mcLabelSigma = tracks.rawIteratorAt(candidate.sigmaID); - auto mcLabelSigmaDau = tracks.rawIteratorAt(candidate.kinkDauID); - auto mcLabelPr = tracks.rawIteratorAt(candidate.prID); - auto pdgSigma = mcLabelSigma.has_mcParticle() ? mcLabelSigma.mcParticle_as().pdgCode() : -999; - auto pdgSigmaDau = mcLabelSigmaDau.has_mcParticle() ? mcLabelSigmaDau.mcParticle_as().pdgCode() : -999; - auto pdgPr = mcLabelPr.has_mcParticle() ? mcLabelPr.mcParticle_as().pdgCode() : -999; - outputDataTableMC(candidate.sigmaCharge, - candidate.sigmaPx, - candidate.sigmaPy, - candidate.sigmaPz, - candidate.sigmaDauPx, - candidate.sigmaDauPy, - candidate.sigmaDauPz, - candidate.sigmaDecRadius, - candidate.sigmaCosPA, - candidate.chargePr, - candidate.pxPr, - candidate.pyPr, - candidate.pzPr, - candidate.nSigmaTPCPr, - candidate.nSigmaTOFPr, - pdgSigma, - pdgSigmaDau, - pdgPr); - } - } - } - LOG(debug) << "Processing mixed event MC"; - } - PROCESS_SWITCH(sigmaProtonCorrTask, processMixedEventMC, "Process Mixed event MC", false); -}; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; -} diff --git a/PWGLF/TableProducer/Strangeness/stracents.cxx b/PWGLF/TableProducer/Strangeness/stracents.cxx index ce5597563da..96ca0a745c8 100644 --- a/PWGLF/TableProducer/Strangeness/stracents.cxx +++ b/PWGLF/TableProducer/Strangeness/stracents.cxx @@ -131,6 +131,7 @@ struct straCents { CalibrationInfo ft0aInfo = CalibrationInfo("FT0A"); CalibrationInfo ft0cInfo = CalibrationInfo("FT0C"); CalibrationInfo ft0cVariant1Info = CalibrationInfo("FT0Cvar1"); + CalibrationInfo ft0cVariant2Info = CalibrationInfo("FT0Cvar2"); CalibrationInfo fddmInfo = CalibrationInfo("FDD"); CalibrationInfo ntpvInfo = CalibrationInfo("NTracksPV"); CalibrationInfo nGlobalInfo = CalibrationInfo("NGlobal"); @@ -243,6 +244,7 @@ struct straCents { ft0aInfo.mCalibrationStored = false; ft0cInfo.mCalibrationStored = false; ft0cVariant1Info.mCalibrationStored = false; + ft0cVariant2Info.mCalibrationStored = false; fddmInfo.mCalibrationStored = false; ntpvInfo.mCalibrationStored = false; nGlobalInfo.mCalibrationStored = false; @@ -371,6 +373,7 @@ struct straCents { getccdb(ft0aInfo, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); getccdb(ft0cInfo, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); getccdb(ft0cVariant1Info, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); + getccdb(ft0cVariant2Info, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); getccdb(fddmInfo, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); getccdb(ntpvInfo, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); getccdb(nGlobalInfo, ccdbConfig.genName, ccdbConfig.doNotCrashOnNull); @@ -533,12 +536,14 @@ struct straCents { float centFT0C = getCentrality(ft0cInfo, multZeqFT0C); float centFV0A = getCentrality(fv0aInfo, multZeqFV0A); float centFT0CVariant1 = getCentrality(ft0cVariant1Info, multZeqFT0C); + float centFT0CVariant2 = getCentrality(ft0cVariant2Info, multZeqFT0C); float centMFT = 100.5f; // missing mftNtracks in strangeness data model float centNGlobal = getCentrality(nGlobalInfo, collision.multNTracksGlobal()); + float centNTPV = 100.5f; // missing multNContribs in strangeness data model strangeCents(centFT0M, centFT0A, - centFT0C, centFV0A, centFT0CVariant1, - centMFT, centNGlobal); + centFT0C, centFV0A, centFT0CVariant1, centFT0CVariant2, + centMFT, centNGlobal, centNTPV); if (produceHistograms.value) { histos.fill(HIST("FT0M/Mult"), multZeqFT0A + multZeqFT0C); diff --git a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx index a68b06b4b79..7be69eeca47 100644 --- a/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangederivedbuilder.cxx @@ -78,20 +78,21 @@ struct strangederivedbuilder { struct : ProducesGroup { //__________________________________________________ // fundamental building blocks of derived data - Produces strangeColl; // characterises collisions - Produces strangeCollLabels; // characterises collisions - Produces strangeMCColl; // characterises collisions / MC - Produces strangeMCMults; // characterises collisions / MC mults - Produces strangeCents; // characterises collisions / centrality in Run 3 - Produces strangeCentsRun2; // characterises collisions / centrality in Run 2 - Produces strangeEvSels; // characterises collisions / centrality / sel8 selection in Run 3 - Produces strangeEvSelsRun2; // characterises collisions / centrality / sel8 selection in Run 2 - Produces strangeStamps; // provides timestamps, run numbers - Produces straEvTimes; // provides event times (FT0, TOF) - Produces v0collref; // references collisions from V0s - Produces casccollref; // references collisions from cascades - Produces kfcasccollref; // references collisions from KF cascades - Produces tracasccollref; // references collisions from tracked cascades + Produces strangeColl; // characterises collisions + Produces strangeCollLabels; // characterises collisions + Produces strangeMCColl; // characterises collisions / MC + Produces strangeMCMults; // characterises collisions / MC mults + Produces strangeCents; // characterises collisions / centrality in Run 3 + Produces strangeCentsRun2; // characterises collisions / centrality in Run 2 + Produces strangeEvSels; // characterises collisions / centrality / sel8 selection in Run 3 + Produces strangeEvSelExtras; // extra event selection variables in Run 3 + Produces strangeEvSelsRun2; // characterises collisions / centrality / sel8 selection in Run 2 + Produces strangeStamps; // provides timestamps, run numbers + Produces straEvTimes; // provides event times (FT0, TOF) + Produces v0collref; // references collisions from V0s + Produces casccollref; // references collisions from cascades + Produces kfcasccollref; // references collisions from KF cascades + Produces tracasccollref; // references collisions from tracked cascades //__________________________________________________ // track extra references @@ -207,6 +208,8 @@ struct strangederivedbuilder { 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"}; + ConfigurableAxis axisZNAtime{"ZNAtime", {100, -999.f, 999.0f}, "ZNAtime"}; + ConfigurableAxis axisZNCtime{"ZNCtime", {100, -999.f, 999.0f}, "ZNCtime"}; } axisDetectors; // For manual sliceBy @@ -404,6 +407,8 @@ struct strangederivedbuilder { 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}); + auto hZNATimeVsZNAUD = histos.add("hZNATimeVsZNAUD", "hZNAMultVsZNAUD; ZNA time; ZNA UD", kTH2F, {axisDetectors.axisZNAtime, axisDetectors.axisZNAtime}); + auto hZNCTimeVsZNCUD = histos.add("hZNCTimeVsZNCUD", "hZNCMultVsZNCUD; ZNC time; ZNC UD", kTH2F, {axisDetectors.axisZNCtime, axisDetectors.axisZNCtime}); for (int ii = 1; ii < 101; ii++) { float value = 100.5f - static_cast(ii); @@ -458,6 +463,14 @@ struct strangederivedbuilder { float totalFDDAmplitudeC = -999; float energyCommonZNA = -999; float energyCommonZNC = -999; + float timeZNA = -999; + float timeZNC = -999; + float timeFV0A = -999; + float timeFT0A = -999; + float timeFT0C = -999; + float timeFDDA = -999; + float timeFDDC = -999; + uint8_t ft0TriggerMask = 0; // +-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+-<*>-+ // set UD information in case present at this stage @@ -474,6 +487,14 @@ struct strangederivedbuilder { totalFDDAmplitudeC = udColl.totalFDDAmplitudeC(); energyCommonZNA = udColl.energyCommonZNA(); energyCommonZNC = udColl.energyCommonZNC(); + timeZNA = udColl.timeZNA(); + timeZNC = udColl.timeZNC(); + timeFDDA = udColl.timeFDDA(); + timeFDDC = udColl.timeFDDC(); + timeFV0A = udColl.timeFV0A(); + timeFT0A = udColl.timeFT0A(); + timeFT0C = udColl.timeFT0C(); + ft0TriggerMask = udColl.triggerMaskFT0(); histos.fill(HIST("hFT0AMultVsFT0AUD"), collision.multFT0A(), udColl.totalFT0AmplitudeA()); histos.fill(HIST("hFT0CMultVsFT0CUD"), collision.multFT0C(), udColl.totalFT0AmplitudeC()); @@ -482,6 +503,14 @@ struct strangederivedbuilder { histos.fill(HIST("hFDDCMultVsFDDCUD"), collision.multFDDC(), udColl.totalFDDAmplitudeC()); histos.fill(HIST("hZNAMultVsZNAUD"), collision.multZNA(), udColl.energyCommonZNA()); histos.fill(HIST("hZNCMultVsZNCUD"), collision.multZNC(), udColl.energyCommonZNC()); + if (bc.has_zdc()) { + auto zdc = bc.zdc(); + histos.fill(HIST("hZNATimeVsZNAUD"), zdc.timeZNA(), udColl.timeZNA()); + histos.fill(HIST("hZNCTimeVsZNCUD"), zdc.timeZNC(), udColl.timeZNC()); + } else { + histos.fill(HIST("hZNATimeVsZNAUD"), -999., udColl.timeZNA()); + histos.fill(HIST("hZNCTimeVsZNCUD"), -999., udColl.timeZNC()); + } } } } @@ -502,9 +531,32 @@ struct strangederivedbuilder { centrality = hRawCentrality->GetBinContent(hRawCentrality->FindBin(collision.multFT0C())); } + if (gapSide < 0) { // if UD collision is not found, store the timing information from collision instead + if (bc.has_zdc()) { + auto zdc = bc.zdc(); + timeZNA = zdc.timeZNA(); + timeZNC = zdc.timeZNC(); + } + if (collision.has_foundFDD()) { // Analysis is fully based on FT0 presence + const auto& fdd = collision.foundFDD(); + timeFDDA = fdd.timeA(); + timeFDDC = fdd.timeC(); + } + if (collision.has_foundFV0()) { // Analysis is fully based on FV0 presence + const auto& fv0a = collision.foundFV0(); + timeFV0A = fv0a.time(); + } + if (collision.has_foundFT0()) { // Analysis is fully based on FT0 presence + const auto& ft0 = collision.foundFT0(); + timeFT0A = ft0.timeA(); + timeFT0C = ft0.timeC(); + ft0TriggerMask = ft0.triggerMask(); + } + } + products.strangeCents(collision.centFT0M(), collision.centFT0A(), - centrality, collision.centFV0A(), collision.centFT0CVariant1(), - collision.centMFT(), collision.centNGlobal()); + centrality, collision.centFV0A(), collision.centFT0CVariant1(), collision.centFT0CVariant2(), + collision.centMFT(), collision.centNGlobal(), collision.centNTPV()); products.strangeEvSels(collision.sel8(), collision.selection_raw(), collision.multFT0A() * static_cast(fillTruncationOptions.fillRawFT0A), collision.multFT0C() * static_cast(fillTruncationOptions.fillRawFT0C), @@ -534,6 +586,10 @@ struct strangederivedbuilder { collision.flags(), collision.alias_raw(), collision.rct_raw()); + products.strangeEvSelExtras(timeZNA, timeZNC, // ZDC info + timeFDDA, timeFDDC, // FDD info + timeFV0A, // FV0A info + timeFT0A, timeFT0C, ft0TriggerMask); // FT0 info } else { // We are in Run 2 products.strangeCentsRun2(collision.centRun2V0M(), collision.centRun2V0A(), collision.centRun2SPDTracklets(), collision.centRun2SPDClusters()); @@ -651,23 +707,23 @@ struct strangederivedbuilder { } } - void processCollisionsRun3(soa::Join const& collisions, aod::V0Datas const& V0s, aod::CascDatas const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, aod::BCsWithTimestamps const& bcs) + void processCollisionsRun3(soa::Join const& collisions, aod::V0Datas const& V0s, aod::CascDatas const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, soa::Join const& bcs, aod::FT0s const&, aod::FV0As const&, aod::FDDs const&, aod::Zdcs const&) { populateCollisionTables(collisions, collisions, V0s, Cascades, KFCascades, TraCascades, bcs); } - void processCollisionsRun3WithUD(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) + void processCollisionsRun3WithUD(soa::Join const& collisions, aod::V0Datas const& V0s, aod::CascDatas const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, soa::Join const& bcs, aod::FT0s const&, aod::FV0As const&, aod::FDDs const&, aod::Zdcs const&, UDCollisionsFull const& udCollisions) { populateCollisionTables(collisions, udCollisions, V0s, Cascades, KFCascades, TraCascades, bcs); } - void processCollisionsRun3WithMC(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, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) + void processCollisionsRun3WithMC(soa::Join const& collisions, soa::Join const& V0s, soa::Join const& /*V0MCCores*/, soa::Join const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, soa::Join const& bcs, aod::FT0s const&, aod::FV0As const&, aod::FDDs const&, aod::Zdcs const&, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) { populateMCCollisionTable(mcCollisions, mcParticles); populateCollisionTables(collisions, collisions, V0s, Cascades, KFCascades, TraCascades, bcs); } - void processCollisionsRun3WithUDWithMC(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& mcParticles) + void processCollisionsRun3WithUDWithMC(soa::Join const& collisions, soa::Join const& V0s, soa::Join const& /*V0MCCores*/, soa::Join const& Cascades, aod::KFCascDatas const& KFCascades, aod::TraCascDatas const& TraCascades, soa::Join const& bcs, aod::FT0s const&, aod::FV0As const&, aod::FDDs const&, aod::Zdcs const&, UDCollisionsFull const& udCollisions, soa::Join const& mcCollisions, aod::McParticles const& mcParticles) { populateMCCollisionTable(mcCollisions, mcParticles); populateCollisionTables(collisions, udCollisions, V0s, Cascades, KFCascades, TraCascades, bcs); diff --git a/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt b/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt index b80c7711571..c622a91ee37 100644 --- a/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt +++ b/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt @@ -19,8 +19,8 @@ o2physics_add_dpl_workflow(ucc-zdc PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(dndeta-mft-pp - SOURCES dndeta-mft-pp.cxx +o2physics_add_dpl_workflow(pseudorapidity-density-mft + SOURCES PseudorapidityDensityMFT.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx new file mode 100644 index 00000000000..370f7da75a9 --- /dev/null +++ b/PWGLF/Tasks/GlobalEventProperties/PseudorapidityDensityMFT.cxx @@ -0,0 +1,2870 @@ +// Copyright 2020-2025 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 PseudorapidityDensityMFT.cxx +/// \author Sarah Herrmann +/// \author Tulika Tripathy +/// \brief This code loops over MFT tracks and collisions and fills histograms +/// useful to compute dNdeta + +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonConstants/MathConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Configurable.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RuntimeError.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/Utils.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" +#include "ReconstructionDataFormats/TrackFwd.h" +#include "ReconstructionDataFormats/TrackParametrization.h" + +#include "Math/MatrixFunctions.h" +#include "Math/SMatrix.h" +#include "Math/SVector.h" +#include "TFile.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::track; +using namespace o2::aod::rctsel; + +AxisSpec ptAxis = {2001, -0.005, 20.005}; +AxisSpec deltazAxis = {6100, -6.1, 6.1}; +AxisSpec zAxis = {3001, -30.1, 30.1}; +AxisSpec phiAxis = {629, 0, o2::constants::math::TwoPI, "Rad", "phi axis"}; +AxisSpec etaAxis = {18, -4.6, -1.}; +// AxisSpec dcaXyAxis = {2000, -10, 10}; +// AxisSpec dcaZAxis = {2000, -10, 10}; +// AxisSpec dcaXAxis = {2000, -10, 10}; +// AxisSpec dcaYAxis = {2000, -10, 10};// previous AxisSpec dcaYAxis = {2000, -10, 10}; + +AxisSpec dcaXyAxis = {6000, -30, 30}; +AxisSpec dcaZAxis = {6000, -30, 30}; +AxisSpec dcaXAxis = {6000, -30, 30}; +AxisSpec dcaYAxis = {6000, -30, 30}; // previous AxisSpec dcaYAxis = {2000, -10, 10}; + +// AxisSpec dcaXyAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaZAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaXAxis = {600, -0.15f, 0.15f}; +// AxisSpec dcaYAxis = {600, -0.15f, 0.15f}; + +AxisSpec centAxis = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 100}}; + +// Vertex position axes (cm) +AxisSpec vxAxis = {200, -0.5, 0.5, "V_{x} (cm)"}; +AxisSpec vyAxis = {200, -0.5, 0.5, "V_{y} (cm)"}; +// Status axis for reco/truth (1=reco, 2=true) +AxisSpec recoTruthStatusAxis = {2, 0.5, 2.5, "status"}; + +// Delta-vertex axes (reco - true) in cm +AxisSpec deltaVxAxis = {400, -0.5, 0.5, "#DeltaV_{x} = V_{x}^{rec}-V_{x}^{true} (cm)"}; +AxisSpec deltaVyAxis = {400, -0.5, 0.5, "#DeltaV_{y} = V_{y}^{rec}-V_{y}^{true} (cm)"}; + +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; + +// using MFTTracksLabeled = soa::Join; +// replace your alias with the extension included: +using FullBCs = soa::Join; + +// using MFTTracksLabeled = +// soa::Join; +using MFTTracksLabeled = + soa::Join; +using MFTTracksLabeled2d = + soa::Join; + +using MFTTracksLabeledOrg = + soa::Join; +// using McCollisionsWithExtra = soa::Join; +using McCollisionsWithExtra = o2::soa::Join; + +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix5 = ROOT::Math::SVector; +struct PseudorapidityDensityMFT { + SliceCache cache; + Preslice perCol = o2::aod::fwdtrack::collisionId; + Preslice perMcCol = aod::mcparticle::mcCollisionId; + Preslice perColCentral = aod::track::collisionId; + + Service pdg; + + // --- CCDB magnetic field (needed for propagateToDCAhelix in this device) --- + Service ccdbMgr; + Configurable ccdburlMag{"ccdburlMag", "http://alice-ccdb.cern.ch", + "CCDB url for GRPMagField"}; + Configurable grpmagPathMag{"grpmagPathMag", "GLO/Config/GRPMagField", + "CCDB path for GRPMagField"}; + + int magRunNumber = -1; + float bzMFT = 0.f; + o2::parameters::GRPMagField* grpmag = nullptr; + static constexpr double CenterMft[3] = {0., 0., -61.4}; + + enum class GenRecoCutBin : int { + AllRecoCollisions = 1, + UseContBestCollisionIndex, + HasMcCollision, + IsTriggerTVX, + NoTimeFrameBorder, + NoITSROFrameBorder, + NoSameBunchPileup, + GoodZvtxFT0vsPV, + NoCollInRofStandard, + NoCollInRofStrict, + NoCollInTimeRangeStandard, + NoCollInTimeRangeStrict, + NoHighMultCollInPrevRof, + RctMFT, + VzWindow, + InelGt0 + }; + + enum class TrackLabelSummaryBin : int { + AllTracks = 1, + NoMcLabel, + FakeTracks, + TrueTracks, + PrimaryTracks, + SecondaryTracks + }; + + enum class GenRecoTimeComTrackMode : int { + AllNonOrphan = 0, + NonOrphanNonAmbiguous, + NonOrphanAmbiguous + }; + + enum class RightWrongBin : int { + Right = 1, + Wrong, + Neither, + Both + }; + enum class EventSelectionBin : int { + All = 1, + Vz, + VzItsRof, + VzSelected, + Sel8VzInelGt0, + SelInelInelFwdGt0, + Rejected, + GoodBCs, + BCsWithCollisions, + BCsWithPileupSplitting, + PerCollisionSampleGt0, + MidtracksAndPerCollisionSampleGt0 + }; + enum class HashTableRowCountsBin : int { + RowsSaved = 1, + UniqueRecoColsSaved, + UniqueBestRecoCols + }; + enum class WrongVertexRecoExistsBin : int { + RecoOfTrueExists = 1, + RecoOfTrueMissing + }; + enum class BoolBin : int { + No = 0, + Yes = 1 + }; + enum class SingleCountBin : int { + Count = 1 + }; + enum class EventEfficiencyBin : int { + Generated = 1, + GeneratedInelGt0, + Reconstructed, + Selected, + SelectedInelGt0 + }; + enum class CentralitySelectionBin : int { + All = 1, + Selected, + Rejected + }; + static constexpr float ForwardEtaMax = -2.0f; + static constexpr float ForwardEtaMin = -3.9f; + + static constexpr float PhiVetoLow = 0.02f; + static constexpr float PhiVetoPiMin = 3.10f; + static constexpr float PhiVetoPiMax = 3.23f; + static constexpr float PhiVetoHigh = 6.21f; + + static constexpr float NdfScale = 2.0f; + static constexpr float NdfOffset = 5.0f; + static constexpr float MinNdf = 1.0f; + + template + static float getTrackNdf(TrackT const& track) + { + return std::max(NdfScale * track.nClusters() - NdfOffset, MinNdf); + } + static constexpr int NoCompatibleCollisions = 0; + static constexpr int SingleCompatibleCollision = 1; + + static constexpr int OrphanAmbDegree = 0; + static constexpr int NonAmbiguousAmbDegree = 1; + + static constexpr int ChargeUnitTimesThree = 3; + + void initMagField(FullBCs::iterator const& bc) + { + if (magRunNumber == bc.runNumber()) { + return; + } + + grpmag = ccdbMgr->getForTimeStamp(grpmagPathMag.value, bc.timestamp()); + if (!grpmag) { + LOGF(warning, "GRPMagField not found in CCDB for ts=%lld", static_cast(bc.timestamp())); + bzMFT = 0.f; + magRunNumber = bc.runNumber(); + return; + } + + // This sets TGeoGlobalMagField internally + o2::base::Propagator::initFieldFromGRP(grpmag); + magRunNumber = bc.runNumber(); + + auto* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + if (field) { + bzMFT = field->getBz(CenterMft); + LOGP(info, "Initialized magnetic field for run {}: bzMFT={} kG", magRunNumber, bzMFT); + } else { + LOGF(warning, "TGeoGlobalMagField has no field even after initFieldFromGRP; bzMFT=0"); + bzMFT = 0.f; + } + } + + RCTFlagsChecker rctChecker{"CBT"}; + RCTFlagsChecker myChecker{kFT0Bad, kITSBad, kTPCBadTracking, kTPCBadPID, kMFTBad}; + Configurable maxGenRecoEvents{"maxGenRecoEvents", -1, + "Maximum number of MC collisions to process in processGenReco (-1 = all)"}; + + int nProcessedGenReco = 0; + + Configurable estimatorEta{"estimatorEta", 1.0, + "eta range for INEL>0 sample definition"}; + + Configurable useEvSel{"useEvSel", true, "use event selection"}; + Configurable useNoSameBunchPileup{"useNoSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable useNoCollInRofStandard{"useNoCollInRofStandard", true, "Require evsel::kNoCollInRofStrict in processGenReco"}; + Configurable useNoCollInRofStrict{"useNoCollInRofStrict", true, "Require evsel::kNoCollInRofStrict in processGenReco"}; + Configurable useNoCollInTimeRangeStrict{"useNoCollInTimeRangeStrict", true, "Require evsel::kNoCollInTimeRangeStrict in processGenReco"}; + Configurable useNoCollInTimeRangeStandard{"useNoCollInTimeRangeStandard", true, "Require evsel::kNoCollInTimeRangeStandard in processGenReco"}; + Configurable useNoHighMultCollInPrevRof{"useNoHighMultCollInPrevRof", true, "Require evsel::kNoHighMultCollInPrevRof in processGenReco"}; + Configurable useGoodZvtxFT0vsPV{"useGoodZvtxFT0vsPV", true, "Require evsel::kIsGoodZvtxFT0vsPV in processGenReco"}; + Configurable useRctMFT{"useRctMFT", true, "Apply RCT runlist flags for MFT"}; + + Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROF cut for event selection"}; + + ConfigurableAxis multBinning{"multBinning", {701, -0.5, 700.5}, ""}; + ConfigurableAxis etaBinning{"etaBinning", {36, -4.6, -1.}, ""}; + Configurable useZDiffCut{"useZDiffCut", true, "use Z difference cut"}; + Configurable maxZDiff{"maxZDiff", 1.0f, "max allowed Z difference for reconstructed collisions (cm)"}; + + Configurable usePhiCut{"usePhiCut", true, "use azimuthal angle cut"}; + Configurable useDCAxyCut{"useDCAxyCut", false, "use DCAxy cut"}; + Configurable useCont{"useCont", false, "No of contributors cut"}; + + Configurable usePtCut{"usePtCut", false, "use Pt cut"}; + + Configurable useDCAzCut{"useDCAzCut", false, "use DCAz cut"}; + + Configurable cfgPhiCut{"cfgPhiCut", 0.1f, + "Cut on azimuthal angle of MFT tracks"}; + Configurable cfgPhiCut1{"cfgPhiCut1", 0.0f, + "low Cut on azimuthal angle of MFT tracks"}; + Configurable cfgPhiCut2{"cfgPhiCut2", 6.3f, + "high Cut on azimuthal angle of MFT tracks"}; + Configurable cfgVzCut1{"cfgVzCut1", -30.0f, + "Cut1 on vertex position of MFT tracks"}; + Configurable cfgVzCut2{"cfgVzCut2", 30.0f, + "Cut2 on vertex position of MFT tracks"}; + Configurable cfgnCluster{"cfgnCluster", 5.0f, + "Cut on no of clusters per MFT track"}; + Configurable cfgnEta1{"cfgnEta1", -4.5f, + "Cut on eta1"}; + Configurable cfgnEta2{"cfgnEta2", -1.0f, + "Cut on eta1"}; + Configurable cfgnPt{"cfgnPt", 10.0f, + "Cut on Pt"}; + Configurable cfgChi2NDFMax{"cfgChi2NDFMax", 2000.0f, "Max allowed chi2/NDF for MFT tracks"}; + Configurable maxDCAxy{"maxDCAxy", 2.0f, "Cut on dcaXY"}; + Configurable maxDCAz{"maxDCAz", 2.0f, "Cut on dcaZ"}; + Configurable useLostByCutVeto{"useLostByCutVeto", true, "Reject tracks with lostNoRecoOfTrue or lostRecoExistsButNotCompatible"}; + + Configurable cfgGenRecoTimeComTrackMode{"cfgGenRecoTimeComTrackMode", + static_cast(GenRecoTimeComTrackMode::AllNonOrphan), + "processGenRecoTimeCom track mode: AllNonOrphan=0, NonOrphanNonAmbiguous=1, NonOrphanAmbiguous=2"}; + + HistogramRegistry registry{ + "registry", + { + {"TracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}, // + {"Tracks/EtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}, // + {"TracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}, // + {"TracksPhiZvtx", + "; #varphi; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {phiAxis, zAxis}}}, // + {"TracksPtEta", + " ; p_{T} (GeV/c); #eta", + {HistType::kTH2F, {ptAxis, etaBinning}}}, // + {"EventSelection", + ";status;events", + {HistType::kTH1F, {{15, 0.5, 15.5}}}}, + {"EventCounts", + ";status;events", + {HistType::kTH1F, {{2, 0.5, 2.5}}}}, + }}; + + void init(InitContext&) + { + ccdbMgr->setURL(ccdburlMag.value); // or ccdburlMag.value (depending on your Configurable) + ccdbMgr->setCaching(true); + ccdbMgr->setLocalObjectValidityChecking(); + + if (static_cast(doprocessMult) + + static_cast(doprocessMultReassoc) + + static_cast(doprocessMultReassoc3d) + + static_cast(doprocessCountingCentrality) > + 1) { + LOGP(fatal, + "Exactly one process function between processMult, " + "processMultReassoc, processMultReassoc3d and processCountingCentrality should be " + "enabled!"); + } + AxisSpec multAxis = {multBinning, "N_{trk}"}; + auto hstat = registry.get(HIST("EventSelection")); + auto* x = hstat->GetXaxis(); + x->SetBinLabel(static_cast(EventSelectionBin::All), "All"); + x->SetBinLabel(static_cast(EventSelectionBin::Vz), "Vz"); + x->SetBinLabel(static_cast(EventSelectionBin::VzItsRof), "Vz+ITSRof"); + x->SetBinLabel(static_cast(EventSelectionBin::VzSelected), "Vz+Selected"); + x->SetBinLabel(static_cast(EventSelectionBin::Sel8VzInelGt0), "Sel8+Vz+INEL>0"); + x->SetBinLabel(static_cast(EventSelectionBin::SelInelInelFwdGt0), "Sel INEL,INEL_fwd>0"); + x->SetBinLabel(static_cast(EventSelectionBin::Rejected), "Rejected"); + x->SetBinLabel(static_cast(EventSelectionBin::GoodBCs), "Good BCs"); + x->SetBinLabel(static_cast(EventSelectionBin::BCsWithCollisions), "BCs with collisions"); + x->SetBinLabel(static_cast(EventSelectionBin::BCsWithPileupSplitting), "BCs with pile-up/splitting"); + x->SetBinLabel(static_cast(EventSelectionBin::PerCollisionSampleGt0), "percollisionSample>0"); + x->SetBinLabel(static_cast(EventSelectionBin::MidtracksAndPerCollisionSampleGt0), "midtracks+percollisionSample>0"); + registry.add({"EventsNtrkZvtx", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"EventsNtrkZvtx_gt0", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_all", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_sel8", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelfwdgt0", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"Tracks/Control/DCAXY", + " ; DCA_{XY} (cm)", + {HistType::kTH1F, {dcaXyAxis}}}); + + if (doprocessGenReco || doprocessGenRecoTimeCom) { + registry.add({"EventsRecoCuts_GenReco", + ";cut;events", + {HistType::kTH1F, {{16, 0.5, 16.5}}}}); + { + auto h = registry.get(HIST("EventsRecoCuts_GenReco")); + auto* x = h->GetXaxis(); + x->SetBinLabel(static_cast(GenRecoCutBin::AllRecoCollisions), "All reco collisions (loop entry)"); + x->SetBinLabel(static_cast(GenRecoCutBin::UseContBestCollisionIndex), "useContBestcollisionIndex"); + x->SetBinLabel(static_cast(GenRecoCutBin::HasMcCollision), "has_mcCollision()"); + x->SetBinLabel(static_cast(GenRecoCutBin::IsTriggerTVX), "kIsTriggerTVX (if useEvSel)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoTimeFrameBorder), "kNoTimeFrameBorder (if useEvSel)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoITSROFrameBorder), "kNoITSROFrameBorder (if useEvSel)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoSameBunchPileup), "kNoSameBunchPileup"); + x->SetBinLabel(static_cast(GenRecoCutBin::GoodZvtxFT0vsPV), "kIsGoodZvtxFT0vsPV"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoCollInRofStandard), "kNoCollInRofStandard (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoCollInRofStrict), "kNoCollInRofStrict (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoCollInTimeRangeStandard), "kNoCollInTimeRangeStandard (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoCollInTimeRangeStrict), "kNoCollInTimeRangeStrict (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::NoHighMultCollInPrevRof), "kNoHighMultCollInPrevRof (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::RctMFT), "myChecker (cfg)"); + x->SetBinLabel(static_cast(GenRecoCutBin::VzWindow), "Vz window"); + x->SetBinLabel(static_cast(GenRecoCutBin::InelGt0), "INEL>0 (midtracks>0)"); + // x->SetBinLabel(11, "rctChecker (cfg)"); + + // x->SetBinLabel(15, "Passed all event cuts"); + } + + AxisSpec trackLabelAxis = {6, 0.5, 6.5, "Track label category"}; + registry.add({"Purity/TrackLabelSummary", + ";Track label category;Counts", + {HistType::kTH1D, {trackLabelAxis}}}); + { + auto h = registry.get(HIST("Purity/TrackLabelSummary")); + auto* x = h->GetXaxis(); + x->SetBinLabel(static_cast(TrackLabelSummaryBin::AllTracks), "All tracks"); + x->SetBinLabel(static_cast(TrackLabelSummaryBin::NoMcLabel), "No MC label"); + x->SetBinLabel(static_cast(TrackLabelSummaryBin::FakeTracks), "Fake tracks"); + x->SetBinLabel(static_cast(TrackLabelSummaryBin::TrueTracks), "True tracks"); + x->SetBinLabel(static_cast(TrackLabelSummaryBin::PrimaryTracks), "Primary tracks"); + x->SetBinLabel(static_cast(TrackLabelSummaryBin::SecondaryTracks), "Secondary tracks"); + } + registry.add({"Purity/TrackEtaCategorySparse", + ";#eta_{all};#eta_{noMC};#eta_{fake};#eta_{true};#eta_{primary};#eta_{secondary}", + {HistType::kTHnSparseF, {etaBinning, etaBinning, etaBinning, etaBinning, etaBinning, etaBinning}}}); + + registry.add({"Purity/WrongVertexRecoExists", + ";status;Counts", + {HistType::kTH1F, {{2, 0.5, 2.5}}}}); + { + auto h = registry.get(HIST("Purity/WrongVertexRecoExists")); + if (h) { + h->GetXaxis()->SetBinLabel(static_cast(WrongVertexRecoExistsBin::RecoOfTrueExists), "Reco of true exists"); + h->GetXaxis()->SetBinLabel(static_cast(WrongVertexRecoExistsBin::RecoOfTrueMissing), "Reco of true missing"); + } + } + + registry.add({"Purity/HashTableRowCounts", + ";status;counts", + {HistType::kTH1F, {{3, 0.5, 3.5}}}}); + auto hHashTableRowCounts = registry.get(HIST("Purity/HashTableRowCounts")); + auto* xHash = hHashTableRowCounts->GetXaxis(); + xHash->SetBinLabel(static_cast(HashTableRowCountsBin::RowsSaved), "rows saved"); + xHash->SetBinLabel(static_cast(HashTableRowCountsBin::UniqueRecoColsSaved), "unique recoCol saved"); + xHash->SetBinLabel(static_cast(HashTableRowCountsBin::UniqueBestRecoCols), "unique bestRecoCol"); + registry.add({"Purity/THnDCAChosenVsRight_Wrong", + ";#eta;DCA_{xy}^{chosen} (cm);DCA_{xy}^{calculated} (cm);DCA_{xy}^{right} (cm);DCA_{z}^{chosen} (cm);DCA_{z}^{calculated} (cm);DCA_{z}^{right} (cm)", + {HistType::kTHnSparseF, {etaBinning, dcaXyAxis, dcaXyAxis, dcaXyAxis, dcaZAxis, dcaZAxis, dcaZAxis}}}); + registry.add({"Purity/THnDCAChosenVsRight_Right", + ";#eta;DCA_{xy}^{chosen} (cm);DCA_{xy}^{calculated} (cm);DCA_{xy}^{right} (cm);DCA_{z}^{chosen} (cm);DCA_{z}^{calculated} (cm);DCA_{z}^{right} (cm)", + {HistType::kTHnSparseF, {etaBinning, dcaXyAxis, dcaXyAxis, dcaXyAxis, dcaZAxis, dcaZAxis, dcaZAxis}}}); + registry.add("Purity/RecoOfTrueExists", + "Any reco collision exists for track true MC collision id;exists (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + registry.add("Purity/RecoOfTrueInCompatible", + "Reco collision(s) of true MC event present in track compatible collisions;inCompatible (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + registry.add("Purity/RecoOfTrueExistsR", + "Any reco collision exists for track true MC collision id;exists (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + registry.add("Purity/RecoOfTrueInCompatibleR", + "Reco collision(s) of true MC event present in track compatible collisions;inCompatible (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + + registry.add("Purity/RecoOfTrueExistsW", + "Any reco collision exists for track true MC collision id;exists (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + registry.add("Purity/RecoOfTrueInCompatibleW", + "Reco collision(s) of true MC event present in track compatible collisions;inCompatible (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + + registry.add("Purity/hCorrectRecoIDinTheListR", + "Any reco collision exists for track true MC collision id;exists (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + registry.add("Purity/hCorrectRecoIDinTheListW", + "Any reco collision exists for track true MC collision id;exists (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + + // P(Nch): number of selected MFT tracks per accepted reco collision (after all event+track cuts) + // Tracks lost because of the OR cut ( !exists || !inCompatible ) + registry.add("Purity/LostByBoth", + "Tracks rejected by (!recoOfTrueExists || !recoOfTrueInCompatible);status (0=kept,1=lost);tracks", + kTH1F, {{2, -0.5, 1.5}}); + // Number of ITS-TPC contributors to the reconstructed collision (PV contributors) + registry.add({"Purity/reco/CollisionNumContrib", + ";N_{contrib} ( PV contributors);collisions", + {HistType::kTH1F, {{3001, -0.5, 3000.5}}}}); + + // Tracks that were WRONG (by your definition) BEFORE applying the cut + registry.add("Purity/WrongBeforeRecoOfTrueCut", + "Tracks classified wrong BEFORE applying recoOfTrue cut;wrong (0=no,1=yes);tracks", + kTH1F, {{2, -0.5, 1.5}}); + + // Optional but very useful: intersection (lost AND wrong) + + registry.add({"Purity/reco/PNchMFT_afterCuts", + ";N_{trk}^{MFT} (selected);events", + {HistType::kTH1F, {multAxis}}}); + registry.add({"Purity/DCAyVsDCAx_Right", + ";DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTH2F, {dcaXAxis, dcaYAxis}}}); + registry.add({"Purity/reco/woOrp/All", + ";bin;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/reco/woOrp/AllEta", + ";#eta;counts", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"Purity/SelectedAfterDCAxy/PrimaryAll", + ";bin;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/SelectedAfterDCAxy/PrimaryAllEta", + ";#eta;counts", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"TracksToPartPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"EventsReco", + "; status; events", + {HistType::kTH1F, {{7, 0.5, 7.5}}}}); + + // Additional histograms for processGenReco (w/o orphan), grouped under Purity/reco/ + registry.add({"Purity/reco/weakStrange/SelectedTracksEta", + "; #eta; selected reco tracks from weak strange decays", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"Purity/reco/weakStrange/SelectedTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); selected reco tracks from weak strange decays", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/SelectedTracksEta", + "; #eta; selected reco tracks", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"Purity/reco/woOrp/nTrk", + " ; N_{Trk}^{all}", + {HistType::kTH1F, {{701, -0.5, 700.5}}}}); + + registry.add({"Purity/reco/woOrp/woOrpTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp/woOrpTracksPtZvtx", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp/woOrpPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + + registry.add({"Purity/reco/woOrp/woOrpEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + + registry.add({"Purity/reco/woOrp/woOrpTracksDCAxyZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {dcaXyAxis, zAxis}}}); + + registry.add({"Purity/reco/woOrp/woOrpTracksDCAzZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {dcaZAxis, zAxis}}}); + + registry.add({"Purity/reco/woOrp/woOrpTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + + // --- Category-wise woOrp histograms (after track cuts & woOrp) --- + // Fake tracks (no MC particle) + registry.add({"Purity/reco/woOrp_fake/woOrpEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_fake/woOrpTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_fake/woOrpTracksPtZvtx", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_fake/woOrpPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_fake/woOrpTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + + // Tracks that have an MC particle (matched) + registry.add({"Purity/reco/woOrp_hasMC/woOrpEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_hasMC/woOrpTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_hasMC/woOrpTracksPtZvtx", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_hasMC/woOrpPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_hasMC/woOrpTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + + // Secondary tracks (has MC but not primary) + registry.add({"Purity/reco/woOrp_secondary/woOrpEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_secondary/woOrpTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_secondary/woOrpTracksPtZvtx", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_secondary/woOrpPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_secondary/woOrpTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + + // Primary tracks (has MC and is physical primary) + registry.add({"Purity/reco/woOrp_primary/woOrpEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_primary/woOrpTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/reco/woOrp_primary/woOrpTracksPtZvtx", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_primary/woOrpPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/reco/woOrp_primary/woOrpTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + + // MC-side (generator truth) histograms for purity in processGenReco + registry.add({"Purity/mc/PrimaryAll", + ";bin;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/mc/PrimaryAllEta", + ";#eta;counts", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"Purity/mc/PrimaryTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/mc/PrimaryTracksEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/mc/PrimaryTracksDCAxyZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {dcaXyAxis, zAxis}}}); + registry.add({"Purity/mc/PrimaryTracksDCAzZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {dcaZAxis, zAxis}}}); + + registry.add({"Purity/mc/PrimaryTracksPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); primary tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/mc/PrimaryTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + // --- MC-side (NO-DCA) truth histograms for pre-DCA accounting --- + registry.add({"Purity/mc_noDCA/PrimaryAll", + ";bin;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/mc_noDCA/PrimaryAllEta", + ";#eta;counts", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"Purity/mc_noDCA/PrimaryTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/mc_noDCA/PrimaryTracksEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/mc_noDCA/PrimaryTracksPtZvtx_gt0", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); primary tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"Purity/mc_noDCA/PrimaryTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + + // Book keeping for pre-DCA selection counters (for symmetry with AfterDCAxy) + registry.add({"Purity/SelectedBeforeDCAxy/PrimaryAll", + ";bin;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/SelectedBeforeDCAxy/PrimaryAllEta", + ";#eta;counts", + {HistType::kTH1F, {etaBinning}}}); + // --- Fake-track counters (reco side after DCA selections) --- + registry.add({"Purity/Fakes/All", + ";bin;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/Fakes/AllEta", + ";#eta_{reco};counts", + {HistType::kTH1F, {etaBinning}}}); + registry.add({"Purity/Fakes/TracksEtaZvtx", + "; #eta_{reco}; #it{z}_{vtx}^{rec} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Purity/Fakes/TracksPhiEta", + "; #varphi_{reco}; #eta_{reco}; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + // Fake reason breakdown: 1-INEL>0 true (vz), 2-Reco sel (woOrp), 3-has_mcParticle, 4-isPrimary, 5-rightVertex + + // --- Purity calculation histograms (as profiles: purity = ) --- + registry.add({"Purity/PurityOverall", + ";bin;purity", + {HistType::kTProfile, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/PurityVsEta", + ";#eta;purity", + {HistType::kTProfile, {etaBinning}}}); + registry.add({"RightWrong", + ";category;counts", + {HistType::kTH1F, {{4, 0.5, 4.5}}}}); + auto hrw = registry.get(HIST("RightWrong")); + hrw->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Right), "right"); + hrw->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Wrong), "wrong"); + hrw->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Neither), "neither"); + hrw->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Both), "both"); + + registry.add({"Purity/RightWrongLater", + ";category;counts", + {HistType::kTH1F, {{4, 0.5, 4.5}}}}); + auto hrw1 = registry.get(HIST("Purity/RightWrongLater")); + hrw1->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Right), "right"); + hrw1->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Wrong), "wrong"); + hrw1->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Neither), "neither"); + hrw1->GetXaxis()->SetBinLabel(static_cast(RightWrongBin::Both), "both"); + + // Vertex-position difference for wrong-vertex associations (reco - true MC) + registry.add({"deltaVZ_fromReco", + ";#Delta z_{vtx}^{reco-true} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"deltaVZ_fromTrue", + ";#Delta z_{vtx}^{reco-true} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"Purity/DeltaXWrong", + ";#Delta x_{vtx}^{reco-true} (cm);tracks", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Purity/DeltaYWrong", + ";#Delta y_{vtx}^{reco-true} (cm);tracks", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Purity/DeltaZWrong", + ";#Delta z_{vtx}^{reco-true} (cm);tracks", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Purity/xReco", + ";#Delta z_{vtx}^{reco} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"Purity/xTrue", + ";#Delta z_{vtx}^{true} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"Purity/yReco", + ";#Delta z_{vtx}^{reco} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"Purity/yTrue", + ";#Delta z_{vtx}^{true} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"Purity/zReco", + ";#Delta z_{vtx}^{reco} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + registry.add({"Purity/zTrue", + ";#Delta z_{vtx}^{true} (cm);tracks", + {HistType::kTH1F, {zAxis}}}); + + // Vertex positions: store both reco and truth in one THnSparse with a status axis + registry.add({"Purity/VtxXYZTruth", + "; V_{x} (cm); V_{y} (cm); V_{z} (cm)", + {HistType::kTHnSparseF, {vxAxis, vyAxis, zAxis}}}); + registry.add({"Purity/VtxXYZReco", + "; V_{x} (cm); V_{y} (cm); V_{z} (cm)", + {HistType::kTHnSparseF, {vxAxis, vyAxis, zAxis}}}); + + // Delta vertex positions (reco - true) + registry.add({"Purity/DeltaVtxXYZ", + "; #DeltaV_{x} (cm); #DeltaV_{y} (cm); #DeltaV_{z} (cm)", + {HistType::kTHnSparseF, {deltaVxAxis, deltaVyAxis, deltazAxis}}}); + + registry.add({"Purity/DeltaXRight", + ";#Delta x_{vtx}^{reco-true} (cm) (right);tracks", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Purity/DeltaYRight", + ";#Delta y_{vtx}^{reco-true} (cm) (right);tracks", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Purity/DeltaZRight", + ";#Delta z_{vtx}^{reco-true} (cm) (right);tracks", + {HistType::kTH1F, {dcaZAxis}}}); + + // 5D THnSparse histograms: (eta, DCAxy, DCAz, DCAx, DCAy) + + // 1) All / Primary / Secondary after track selection (no vertex classification) + registry.add({"Purity/RecoSparseAll", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"RecoSparseAllBest", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"RecoSparseAllBestWrong", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparsePrimary", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparseSecondary", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + // 2) Right-vertex: all / primary / secondary + registry.add({"Purity/RecoSparseRightAll", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparseRightPrimary", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparseRightSecondary", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + // 3) Wrong-vertex: all / primary / secondary + registry.add({"Purity/RecoSparseWrongAll", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparseWrongPrimary", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparseWrongSecondary", + ";#eta;DCA_{xy} (cm);DCA_{z} (cm);DCA_{x} (cm);DCA_{y} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + // 4) Generator-truth DCA 5D THnSparse: (eta_truth, DCAxy_truth, DCAz_truth, DCAx_truth, DCAy_truth) + // booked under Tracks/dca/Truth/ + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthAll", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthPrim", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (primary)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthSec", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (secondary)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + // Right-vertex truth DCA + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthRightAll", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (right vertex)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthRightPrim", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (primary, right vertex)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthRightSec", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (secondary, right vertex)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + // Wrong-vertex truth DCA + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthWrongAll", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (wrong vertex)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthWrongPrim", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (primary, wrong vertex)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDCAxyBestGenTruthWrongSec", + ";#eta_{truth};DCA_{xy}^{truth} (cm);DCA_{z}^{truth} (cm);DCA_{x}^{truth} (cm);DCA_{y}^{truth} (cm) (secondary, wrong vertex)", + {HistType::kTHnSparseF, + {etaBinning, dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + // 5) Delta-DCA THnSparse: (ΔDCAxy, ΔDCAz, ΔDCAx, ΔDCAy) for right/wrong vertex, all/primary/secondary + registry.add({"Tracks/dca/Truth/THnDeltaDCARightAll", + ";#Delta DCA_{xy} (cm);#Delta DCA_{z} (cm);#Delta DCA_{x} (cm);#Delta DCA_{y} (cm)", + {HistType::kTHnSparseF, + {dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDeltaDCARightPrim", + ";#Delta DCA_{xy} (cm);#Delta DCA_{z} (cm);#Delta DCA_{x} (cm);#Delta DCA_{y} (cm) (primary, right vertex)", + {HistType::kTHnSparseF, + {dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDeltaDCARightSec", + ";#Delta DCA_{xy} (cm);#Delta DCA_{z} (cm);#Delta DCA_{x} (cm);#Delta DCA_{y} (cm) (secondary, right vertex)", + {HistType::kTHnSparseF, + {dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Tracks/dca/Truth/THnDeltaDCAWrongAll", + ";#Delta DCA_{xy} (cm);#Delta DCA_{z} (cm);#Delta DCA_{x} (cm);#Delta DCA_{y} (cm) (wrong vertex)", + {HistType::kTHnSparseF, + {dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDeltaDCAWrongPrim", + ";#Delta DCA_{xy} (cm);#Delta DCA_{z} (cm);#Delta DCA_{x} (cm);#Delta DCA_{y} (cm) (primary, wrong vertex)", + {HistType::kTHnSparseF, + {dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + registry.add({"Tracks/dca/Truth/THnDeltaDCAWrongSec", + ";#Delta DCA_{xy} (cm);#Delta DCA_{z} (cm);#Delta DCA_{x} (cm);#Delta DCA_{y} (cm) (secondary, wrong vertex)", + {HistType::kTHnSparseF, + {dcaXyAxis, dcaZAxis, dcaXAxis, dcaYAxis}}}); + + registry.add({"Purity/RecoSparseAll_EventCount", + ";events;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/RecoSparseAll_EventCountBest", + ";events;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/RecoSparseRightAll_EventCount", + ";events;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/RecoSparseWrongAll_EventCount", + ";events;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + registry.add({"Purity/BestRecoColNotFound", + ";events;counts", + {HistType::kTH1F, {{1, 0.5, 1.5}}}}); + } + + if (doprocessGen) { + registry.add({"EventsNtrkZvtxGen", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"EventsNtrkZvtxGen_t", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"EventsNtrkZvtxGen_gt0", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"EventsNtrkZvtxGen_gt0t", + "; N_{trk}; #it{z}_{vtx} (cm); events", + {HistType::kTH2F, {multAxis, zAxis}}}); + registry.add({"TracksEtaZvtxGen", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"TracksEtaZvtxGen_t", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"TracksEtaZvtxGen_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"TracksEtaZvtxGen_gt0t", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"TracksPhiEtaGen", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"TracksPhiEtaGen_gt0", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"TracksPhiEtaGen_gt0t", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"TracksPhiZvtxGen", + "; #varphi; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {phiAxis, zAxis}}}); // + registry.add({"TracksToPartPtEta", + " ; p_{T} (GeV/c); #eta", + {HistType::kTH2F, {ptAxis, etaBinning}}}); // + registry.add({"TracksPtEtaGen", + " ; p_{T} (GeV/c); #eta", + {HistType::kTH2F, {ptAxis, etaBinning}}}); + registry.add({"TracksPtEtaGen_t", + " ; p_{T} (GeV/c); #eta", + {HistType::kTH2F, {ptAxis, etaBinning}}}); + registry.add({"NotFoundEventZvtx", + " ; #it{z}_{vtx} (cm)", + {HistType::kTH1F, {zAxis}}}); + registry.add({"EventsZposDiff", + " ; Z_{rec} - Z_{gen} (cm)", + {HistType::kTH1F, {deltazAxis}}}); + + registry.add({"TracksEtaZvtxGen_gt0_primary", + "; #eta; #it{z}_{vtx} (cm); primary tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"TracksPhiEtaGen_gt0_primary", + "; #varphi; #eta; primary tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"TracksPtZvtxGen_gt0_primary", + "; p_{T} (GeV/c); #it{z}_{vtx} (cm); primary tracks", + {HistType::kTH2F, {ptAxis, zAxis}}}); + registry.add({"EventsSplitMult", " ; N_{gen}", {HistType::kTH1F, {multAxis}}}); + auto heff = registry.get(HIST("EventEfficiency")); + x = heff->GetXaxis(); + x->SetBinLabel(static_cast(EventEfficiencyBin::Generated), "Generated"); + x->SetBinLabel(static_cast(EventEfficiencyBin::GeneratedInelGt0), "Generated INEL>0"); + x->SetBinLabel(static_cast(EventEfficiencyBin::Reconstructed), "Reconstructed"); + x->SetBinLabel(static_cast(EventEfficiencyBin::Selected), "Selected"); + x->SetBinLabel(static_cast(EventEfficiencyBin::SelectedInelGt0), "Selected INEL>0"); + } + + if (doprocessMultReassoc || doprocessMultReassoc3d) { + // Purity denominator histograms (reco side after DCAxy selection) + + registry.add({"Tracks/Control/DeltaZ", + " ; #it{z_{orig}}-#it{z_{reass}}", + {HistType::kTH1F, {zAxis}}}); + + registry.add({"Tracks/Control/TrackAmbDegree", + " ; N_{coll}^{comp}", + {HistType::kTH1F, {{51, -0.5, 50.5}}}}); + registry.add({"Tracks/Control/TrackIsAmb", + " ; isAmbiguous", + {HistType::kTH1I, {{2, -0.5, 1.5}}}}); + + registry.add({"Tracks/Control/ReassignedTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Tracks/Control/ReassignedTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"Tracks/Control/ReassignedVertexCorr", + "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", + {HistType::kTH2F, {zAxis, zAxis}}}); + + registry.add({"Tracks/Control/notReassignedTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); + registry.add({"Tracks/Control/notReassignedTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); + registry.add({"Tracks/Control/notReassignedVertexCorr", + "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", + {HistType::kTH2F, {zAxis, zAxis}}}); + registry.add({"Tracks/Control/Chi2NDF", + " ; #chi^{2}/ndf", + {HistType::kTH1F, {{5000, 0.0, 5000.0}}}}); + registry.add({"Tracks/Control/amb/AmbTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + + registry.add({"Tracks/Control/woOrp/nTrk", + " ; N_{Trk}^{all}", + {HistType::kTH1F, {{701, -0.5, 700.5}}}}); // + registry.add({"Tracks/Control/amb/nTrkAmb", + " ; N_{Trk}^{amb}", + {HistType::kTH1F, {{701, -0.5, 700.5}}}}); // + registry.add({"Tracks/Control/nonamb/nTrkNonAmb", + " ; N_{Trk}^{nonamb}", + {HistType::kTH1F, {{701, -0.5, 700.5}}}}); // + + registry.add({"Tracks/Control/amb/AmbTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); // + registry.add({"Tracks/Control/amb/AmbVertexCorr", + "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", + {HistType::kTH2F, {zAxis, zAxis}}}); // + registry.add({"Tracks/Control/amb/EtaZvtxAmb_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/Control/amb/DCAxy_amb", " ; DCA_{xy} (cm) ambiguous", + // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // + {HistType::kTH1F, {dcaXyAxis}}}); // + + registry.add({"Tracks/Control/nonamb/nonAmbTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + + registry.add({"Tracks/Control/nonamb/nonAmbTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); // + registry.add({"Tracks/Control/nonamb/nonAmbVertexCorr", + "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", + {HistType::kTH2F, {zAxis, zAxis}}}); // + registry.add({"Tracks/Control/nonamb/EtaZvtxNonAmb_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/Control/nonamb/DCAxy_nonamb", " ; DCA_{xy}(cm) non-ambiguous", + // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // + {HistType::kTH1F, {{dcaXyAxis}}}}); // + + registry.add({"Tracks/Control/woOrp/woOrpTracksEtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/Control/woOrp/woOrpEtaZvtx_gt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/2Danalysis/EtaZvtx", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/2Danalysis/EtaZvtx_sel8", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/2Danalysis/EtaZvtx_sel8_inelgt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/2Danalysis/EtaZvtx_sel8_inelfwdgt0", + "; #eta; #it{z}_{vtx} (cm); tracks", + {HistType::kTH2F, {etaBinning, zAxis}}}); // + registry.add({"Tracks/Control/woOrp/woOrpTracksPhiEta", + "; #varphi; #eta; tracks", + {HistType::kTH2F, {phiAxis, etaBinning}}}); // + registry.add({"Tracks/Control/woOrp/woOrpVertexCorr", + "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", + {HistType::kTH2F, {zAxis, zAxis}}}); // + registry.add({"Tracks/Control/woOrp/DCAxy_woOrp", " ; DCA_{xy}(cm) w/o orphan", + // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // + {HistType::kTH1F, {{dcaXyAxis}}}}); // + + if (doprocessMultReassoc3d) { + // DCAz histograms analogous to DCAxy, only for 3D reassociation + registry.add({"Tracks/Control/DCAZ", + " ; DCA_{Z} (cm)", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Tracks/Control/amb/DCAz_amb", + " ; DCA_{z} (cm) ambiguous", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Tracks/Control/nonamb/DCAz_nonamb", + " ; DCA_{z}(cm) non-ambiguous", + {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"Tracks/Control/woOrp/DCAz_woOrp", + " ; DCA_{z}(cm) w/o orphan", + {HistType::kTH1F, {dcaZAxis}}}); + } + + registry.add({"collisionID", " ; Collision ID", + // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // + {HistType::kTH1F, {{100000, -50000.0, 50000.0}}}}); // + registry.add({"collisionIDamb", " ; Collision ID amb", + // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // + {HistType::kTH1F, {{100000, -50000.0, 50000.0}}}}); // + registry.add({"NonambEventCounts", " ; EventCounts Nonamb", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // + registry.add({"hNumCollisionsNonAmb_InelMFT", " ; Number of Collisions with Non-Ambiguous Tracks;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // + registry.add({"hNumCollisionsAmb_InelMFT", " ; Number of Collisions with Non-Ambiguous Tracks;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // + registry.add({"hNumCollisions_InelMFT", " ; Number of selected events with Inel>0 and MFT>0;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // + registry.add({"hNumCollisions_Inel", " ; Number of selected events with Inel>0;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // + registry.add({"ambEventCounts", " ; EventCounts Nonamb", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // + } + + if (doprocessCountingCentrality) { + registry.add({"Events/Centrality/Selection", + ";status;centrality;events", + {HistType::kTH2F, {{3, 0.5, 3.5}, centAxis}}}); + auto hstat = registry.get(HIST("Events/Centrality/Selection")); + auto* x = hstat->GetXaxis(); + x->SetBinLabel(static_cast(CentralitySelectionBin::All), "All"); + x->SetBinLabel(static_cast(CentralitySelectionBin::Selected), "Selected"); + x->SetBinLabel(static_cast(CentralitySelectionBin::Rejected), "Rejected"); + + registry.add({"Events/Centrality/NtrkZvtx", + "; N_{trk}; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {multAxis, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/EtaZvtx", + "; #eta; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {etaBinning, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/PhiEta", + "; #varphi; #eta; centrality", + {HistType::kTH3F, {phiAxis, etaBinning, centAxis}}}); + registry.add({"Tracks/Centrality/Control/PtEta", + " ; p_{T} (GeV/c); #eta; centrality", + {HistType::kTH3F, {ptAxis, etaBinning, centAxis}}}); + registry.add({"Tracks/Centrality/Control/DCAXYPt", + " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", + {HistType::kTH3F, {ptAxis, dcaXyAxis, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedDCAXYPt", + " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", + {HistType::kTH3F, {ptAxis, dcaXyAxis, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraDCAXYPt", + " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", + {HistType::kTH3F, {ptAxis, dcaXyAxis, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraTracksEtaZvtx", + "; #eta; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {etaBinning, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraTracksPhiEta", + "; #varphi; #eta; centrality", + {HistType::kTH3F, {phiAxis, etaBinning, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedTracksEtaZvtx", + "; #eta; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {etaBinning, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedTracksPhiEta", + "; #varphi; #eta; centrality", + {HistType::kTH3F, {phiAxis, etaBinning, centAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedVertexCorr", + "; Z_{vtx}^{orig} (cm); Z_{vtx}^{re} (cm); centrality", + {HistType::kTH3F, {zAxis, zAxis, centAxis}}}); + } + + if (doprocessGenCent) { + registry.add({"Events/Centrality/EventEfficiency", + ";status;centrality;events", + {HistType::kTH2F, {{2, 0.5, 2.5}, centAxis}}}); + auto heff = registry.get(HIST("Events/Centrality/EventEfficiency")); + auto* x = heff->GetXaxis(); + x->SetBinLabel(1, "Generated"); + x->SetBinLabel(2, "Selected"); + + registry.add("Events/Centrality/CentPercentileMCGen", + "CentPercentileMCGen", kTH1D, {centAxis}, false); + registry.add({"Events/Centrality/NtrkZvtxGen", + "; N_{trk}; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {multAxis, zAxis, centAxis}}}); + registry.add({"Events/Centrality/NtrkZvtxGen_t", + "; N_{trk}; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {multAxis, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/EtaZvtxGen_t", + "; #eta; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {etaBinning, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/EtaZvtxGen", + "; #eta; Z_{vtx} (cm); centrality", + {HistType::kTH3F, {etaBinning, zAxis, centAxis}}}); + registry.add({"Tracks/Centrality/PhiEtaGen", + "; #varphi; #eta; centrality", + {HistType::kTH3F, {phiAxis, etaBinning, centAxis}}}); + } + } + + using FullBCs = soa::Join; + void processTagging(FullBCs const& bcs, + soa::Join const& collisions) + { + + std::vector::iterator> cols; + for (const auto& bc : bcs) { + if (!useEvSel || + (useEvSel && ((bc.selection_bit(aod::evsel::kIsBBT0A) && + bc.selection_bit(aod::evsel::kIsBBT0C)) != 0))) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::GoodBCs)); + cols.clear(); + for (const auto& collision : collisions) { + if (collision.has_foundBC()) { + if (collision.foundBCId() == bc.globalIndex()) { + cols.emplace_back(collision); + } + } else if (collision.bcId() == bc.globalIndex()) { + cols.emplace_back(collision); + } + } + LOGP(debug, "BC {} has {} collisions", bc.globalBC(), cols.size()); + if (!cols.empty()) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::BCsWithCollisions)); + if (cols.size() > 1) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::BCsWithPileupSplitting)); + } + } + } + } + } + + bool passGenRecoTrackMode(auto const& track) const + { + const auto compatibleColls = track.compatibleCollIds(); + const auto nCompatibleColls = compatibleColls.size(); + + if (nCompatibleColls == NoCompatibleCollisions) { + return false; + } + + const auto mode = + static_cast(cfgGenRecoTimeComTrackMode.value); + + switch (mode) { + case GenRecoTimeComTrackMode::AllNonOrphan: + return nCompatibleColls > NoCompatibleCollisions; + case GenRecoTimeComTrackMode::NonOrphanNonAmbiguous: + return nCompatibleColls == SingleCompatibleCollision; + case GenRecoTimeComTrackMode::NonOrphanAmbiguous: + return nCompatibleColls > SingleCompatibleCollision; + default: + return false; + } + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processTagging, + "Collect event sample stats", true); + + static constexpr float SampleEtaMax = -2.8f; + static constexpr float SampleEtaMin = -3.2f; + + Partition sample = + (aod::fwdtrack::eta < SampleEtaMax) && (aod::fwdtrack::eta > SampleEtaMin); + + static constexpr float CentralEtaMax = 1.f; + Partition sampleCentral = (nabs(aod::track::eta) < CentralEtaMax); + + static constexpr int ValidBestCollisionIdMin = 0; + static constexpr int InvalidCollisionId = -1; + static constexpr float MaxBestDcaXy = 2.f; + expressions::Filter atrackFilter = + (aod::fwdtrack::bestCollisionId >= ValidBestCollisionIdMin) && + (aod::fwdtrack::eta < ForwardEtaMax) && + (aod::fwdtrack::eta > ForwardEtaMin) && + (nabs(aod::fwdtrack::bestDCAXY) <= MaxBestDcaXy); + + using CollwEv = soa::Join; + + expressions::Filter trackSelectionCentral = + ((aod::track::trackCutFlag & TrackSelectionIts) == TrackSelectionIts) && + ifnode((aod::track::v001::detectorMap & (uint8_t)o2::aod::track::TPC) == + (uint8_t)o2::aod::track::TPC, + (aod::track::trackCutFlag & TrackSelectionTpc) == + TrackSelectionTpc, + true) && + ((aod::track::trackCutFlag & TrackSelectionDca) == TrackSelectionDca) && + (nabs(aod::track::eta) < estimatorEta); + + using FiCentralTracks = soa::Filtered< + soa::Join>; // central tracks for INEL>0 + + void processMult(CollwEv::iterator const& collision, + aod::MFTTracks const& tracks, + FiCentralTracks const& midtracks, aod::Tracks const&) + { + + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::All)); + if (!useEvSel || (useEvSel && collision.sel8())) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::VzSelected)); + auto z = collision.posZ(); + auto perCollisionSample = sampleCentral->sliceByCached( + o2::aod::track::collisionId, collision.globalIndex(), cache); + auto nTrk = perCollisionSample.size(); + + registry.fill(HIST("EventsNtrkZvtx"), nTrk, z); + + if (midtracks.size() > 0) // INEL>0 + { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Sel8VzInelGt0)); + registry.fill(HIST("EventsNtrkZvtx_gt0"), nTrk, z); + } + + if (tracks.size() > 0) { + for (const auto& track : tracks) { + + float phi = track.phi(); + o2::math_utils::bringTo02Pi(phi); + + if (usePhiCut) { + if ((phi < cfgPhiCut) || + ((phi > o2::constants::math::PI - cfgPhiCut) && (phi < o2::constants::math::PI + cfgPhiCut)) || + (phi > o2::constants::math::TwoPI - cfgPhiCut) || + ((phi > ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) - cfgPhiCut) && + (phi < ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) + cfgPhiCut))) + continue; + } + + registry.fill(HIST("TracksEtaZvtx"), track.eta(), z); + if (midtracks.size() > 0) // INEL>0 + { + registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.eta(), z); + } + registry.fill(HIST("TracksPhiEta"), phi, track.eta()); + registry.fill(HIST("TracksPtEta"), track.pt(), track.eta()); + if ((track.eta() < ForwardEtaMax) && (track.eta() > ForwardEtaMin)) { + registry.fill(HIST("TracksPhiZvtx"), phi, z); + } + } + } + + } else { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Rejected)); + } + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processMult, + "Process reco or data info", true); + // Common implementation for both BestCollisionsFwd and BestCollisionsFwd3d + template + void processMultReassocCommon(CollwEv::iterator const& collision, + o2::aod::MFTTracks const&, + RetracksT const& retracks, + FiCentralTracks const& midtracks, aod::Tracks const&) + { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::All)); + auto perCollisionSample = sampleCentral->sliceByCached( + o2::aod::track::collisionId, collision.globalIndex(), cache); + auto nTrk = perCollisionSample.size(); + auto z = collision.posZ(); + registry.fill(HIST("EventsNtrkZvtx"), nTrk, z); + if ((z >= cfgVzCut1) && (z <= cfgVzCut2)) { + registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_all"), nTrk, z); + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Vz)); + for (const auto& retrack : retracks) { + auto track = retrack.mfttrack(); + float ndf = getTrackNdf(track); + float chi2ndf = track.chi2() / ndf; + float phi = track.phi(); + o2::math_utils::bringTo02Pi(phi); + if (usePhiCut) { + if ((phi <= PhiVetoLow) || + ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || + (phi >= PhiVetoHigh)) { + continue; + } + } + float dcaXyCut = retrack.bestDCAXY(); + if (useDCAxyCut) { + if (dcaXyCut > maxDCAxy) + continue; + } + if constexpr (std::is_same_v>) { + float dcaZCut = retrack.bestDCAZ(); + if (useDCAzCut) { + if (dcaZCut > maxDCAz) + continue; + } + } + if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0 && chi2ndf < cfgChi2NDFMax && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { + registry.fill(HIST("Tracks/2Danalysis/EtaZvtx"), track.eta(), z); + } + } + if (!disableITSROFCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::VzItsRof)); + if (!useEvSel || (useEvSel && collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoSameBunchPileup))) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::VzSelected)); + registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8"), nTrk, z); + std::unordered_set uniqueEvents; + std::unordered_set uniqueEventsAmb; + std::unordered_set uniqueCollisions; + std::unordered_set uniqueCollisionsAmb; + std::unordered_set eventsInelMFT; + std::unordered_set eventsInel; + if (midtracks.size() > 0) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Sel8VzInelGt0)); + registry.fill(HIST("EventsNtrkZvtx_gt0"), nTrk, z); + registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0"), nTrk, z); + eventsInel.insert(collision.globalIndex()); + } + if (perCollisionSample.size() > 0) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::PerCollisionSampleGt0)); + } + if (midtracks.size() > 0 && perCollisionSample.size() > 0) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::MidtracksAndPerCollisionSampleGt0)); + } + int64_t i = 0.0, j = 0.0, k = 0.0; + for (const auto& retrack : retracks) { + auto track = retrack.mfttrack(); + float ndf = getTrackNdf(track); + float chi2ndf = track.chi2() / ndf; + float phi = track.phi(); + o2::math_utils::bringTo02Pi(phi); + if (usePhiCut) { + if ((phi <= PhiVetoLow) || + ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || + (phi >= PhiVetoHigh)) { + continue; + } + } + float dcaXyCut = retrack.bestDCAXY(); + if (useDCAxyCut) { + if (dcaXyCut > maxDCAxy) + continue; + } + if constexpr (std::is_same_v>) { + float dcaZCut = retrack.bestDCAZ(); + if (useDCAzCut) { + if (dcaZCut > maxDCAz) + continue; + } + } + if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0 && chi2ndf < cfgChi2NDFMax && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { + registry.fill(HIST("Tracks/Control/Chi2NDF"), chi2ndf); + registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8"), track.eta(), z); + if (midtracks.size() > 0 && retrack.ambDegree() > 0) { + registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8_inelgt0"), track.eta(), z); + } + } + } + if (retracks.size() > 0) { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::SelInelInelFwdGt0)); + if (midtracks.size() > 0) { + registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelfwdgt0"), nTrk, z); + } + for (const auto& retrack : retracks) { + auto track = retrack.mfttrack(); + float ndf = getTrackNdf(track); + float chi2ndf = track.chi2() / ndf; + float phi = track.phi(); + float dcaXyCut = retrack.bestDCAXY(); + o2::math_utils::bringTo02Pi(phi); + // Declare dcaZCut only if needed below. + if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && chi2ndf < cfgChi2NDFMax && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { + if (usePhiCut) { + if ((phi <= PhiVetoLow) || + ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || + (phi >= PhiVetoHigh)) { + continue; + } + } + if (useDCAxyCut) { + if (dcaXyCut > maxDCAxy) + continue; + } + if constexpr (std::is_same_v>) { + float dcaZCut = retrack.bestDCAZ(); + if (useDCAzCut) { + if (dcaZCut > maxDCAz) + continue; + } + } + + registry.fill(HIST("TracksEtaZvtx"), track.eta(), z); + if (midtracks.size() > 0 && retrack.ambDegree() > 0) { + registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.eta(), z); + registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8_inelfwdgt0"), track.eta(), z); + eventsInelMFT.insert(retrack.bestCollisionId()); + } + if (retrack.ambDegree() != 0) { + registry.fill(HIST("Tracks/Control/woOrp/woOrpEtaZvtx_gt0"), track.eta(), z); + ++k; + } + float phi = track.phi(); + o2::math_utils::bringTo02Pi(phi); + registry.fill(HIST("TracksPhiEta"), phi, track.eta()); + registry.fill(HIST("TracksPtEta"), track.pt(), track.eta()); + if ((track.eta() < ForwardEtaMax) && (track.eta() > ForwardEtaMin)) { + registry.fill(HIST("TracksPhiZvtx"), phi, z); + } + if (track.collisionId() > InvalidCollisionId && + retrack.ambDegree() == SingleCompatibleCollision) { + registry.fill(HIST("collisionID"), track.collisionId()); + } + if (track.collisionId() > InvalidCollisionId && + retrack.ambDegree() > SingleCompatibleCollision) { + registry.fill(HIST("collisionIDamb"), track.collisionId()); + } + if (track.collisionId() != retrack.bestCollisionId()) { + registry.fill(HIST("Tracks/Control/ReassignedTracksEtaZvtx"), + track.eta(), z); + registry.fill(HIST("Tracks/Control/ReassignedTracksPhiEta"), phi, + track.eta()); + registry.fill(HIST("Tracks/Control/ReassignedVertexCorr"), + track.template collision_as().posZ(), z); + + registry.fill(HIST("Tracks/Control/DeltaZ"), + track.template collision_as().posZ() - + collision.posZ()); + } + if (track.collisionId() == retrack.bestCollisionId()) { + registry.fill(HIST("Tracks/Control/notReassignedTracksEtaZvtx"), + track.eta(), z); + registry.fill(HIST("Tracks/Control/notReassignedTracksPhiEta"), phi, + track.eta()); + registry.fill(HIST("Tracks/Control/notReassignedVertexCorr"), + track.template collision_as().posZ(), z); + } + + registry.fill(HIST("Tracks/Control/TrackAmbDegree"), + retrack.ambDegree()); + registry.fill(HIST("Tracks/Control/DCAXY"), retrack.bestDCAXY()); + if constexpr (std::is_same_v>) { + registry.fill(HIST("Tracks/Control/DCAZ"), retrack.bestDCAZ()); + } + int isAmbiguous = 0; + + if (retrack.ambDegree() > 1 && retrack.ambDegree() != 0) { + isAmbiguous = 1; + ++i; + + registry.fill(HIST("Tracks/Control/amb/EtaZvtxAmb_gt0"), track.eta(), z); + + registry.fill(HIST("Tracks/Control/amb/AmbTracksEtaZvtx"), + track.eta(), z); + registry.fill(HIST("Tracks/Control/amb/AmbTracksPhiEta"), phi, + track.eta()); + registry.fill(HIST("Tracks/Control/amb/AmbVertexCorr"), + track.template collision_as().posZ(), z); + registry.fill(HIST("Tracks/Control/amb/DCAxy_amb"), retrack.bestDCAXY()); + if constexpr (std::is_same_v>) { + registry.fill(HIST("Tracks/Control/amb/DCAz_amb"), retrack.bestDCAZ()); + } + uniqueEventsAmb.insert(retrack.bestCollisionId()); + } + if (midtracks.size() > 0 && retrack.ambDegree() > 1 && retrack.ambDegree() != 0) { + uniqueCollisionsAmb.insert(collision.globalIndex()); + } + + registry.fill(HIST("Tracks/Control/TrackIsAmb"), isAmbiguous); + if (retrack.ambDegree() == 1 && retrack.ambDegree() != 0) { + ++j; + registry.fill(HIST("Tracks/Control/nonamb/EtaZvtxNonAmb_gt0"), track.eta(), z); + registry.fill(HIST("Tracks/Control/nonamb/nonAmbTracksEtaZvtx"), + track.eta(), z); + registry.fill(HIST("Tracks/Control/nonamb/nonAmbTracksPhiEta"), phi, + track.eta()); + registry.fill(HIST("Tracks/Control/nonamb/nonAmbVertexCorr"), + track.template collision_as().posZ(), z); + registry.fill(HIST("Tracks/Control/nonamb/DCAxy_nonamb"), retrack.bestDCAXY()); + if constexpr (std::is_same_v>) { + registry.fill(HIST("Tracks/Control/nonamb/DCAz_nonamb"), retrack.bestDCAZ()); + } + uniqueEvents.insert(retrack.bestCollisionId()); + } + if (midtracks.size() > 0 && retrack.ambDegree() == 1 && retrack.ambDegree() != 0) { + uniqueCollisions.insert(collision.globalIndex()); + } + + if (retrack.ambDegree() != 0) { + registry.fill(HIST("Tracks/Control/woOrp/woOrpTracksEtaZvtx"), + track.eta(), z); + registry.fill(HIST("Tracks/Control/woOrp/woOrpTracksPhiEta"), phi, + track.eta()); + registry.fill(HIST("Tracks/Control/woOrp/woOrpVertexCorr"), + track.template collision_as().posZ(), z); + registry.fill(HIST("Tracks/Control/woOrp/DCAxy_woOrp"), retrack.bestDCAXY()); + if constexpr (std::is_same_v>) { + registry.fill(HIST("Tracks/Control/woOrp/DCAz_woOrp"), retrack.bestDCAZ()); + } + } + } + } + registry.fill(HIST("ambEventCounts"), 1, uniqueEventsAmb.size()); + registry.fill(HIST("NonambEventCounts"), 1, uniqueEvents.size()); + registry.fill(HIST("hNumCollisionsNonAmb_InelMFT"), 1, uniqueCollisions.size()); + registry.fill(HIST("hNumCollisionsAmb_InelMFT"), 1, uniqueCollisionsAmb.size()); + registry.fill(HIST("hNumCollisions_InelMFT"), 1, eventsInelMFT.size()); + } + registry.fill(HIST("Tracks/Control/amb/nTrkAmb"), i); + registry.fill(HIST("Tracks/Control/nonamb/nTrkNonAmb"), j); + registry.fill(HIST("Tracks/Control/woOrp/nTrk"), k); + registry.fill(HIST("hNumCollisions_Inel"), 1, eventsInel.size()); + } + } else { + registry.fill(HIST("EventSelection"), static_cast(EventSelectionBin::Rejected)); + } + } + + void processMultReassoc(CollwEv::iterator const& collision, + o2::aod::MFTTracks const& mft, + soa::SmallGroups const& retracks, + FiCentralTracks const& midtracks, aod::Tracks const& trk) + { + processMultReassocCommon(collision, mft, retracks, midtracks, trk); + } + + void processMultReassoc3d(CollwEv::iterator const& collision, + o2::aod::MFTTracks const& mft, + soa::SmallGroups const& retracks, + FiCentralTracks const& midtracks, aod::Tracks const& trk) + { + processMultReassocCommon(collision, mft, retracks, midtracks, trk); + } + PROCESS_SWITCH(PseudorapidityDensityMFT, processMultReassoc, + "Process reco or data info", false); + + PROCESS_SWITCH(PseudorapidityDensityMFT, processMultReassoc3d, + "Process reco or data info (3d)", false); + + using ExColsCent = soa::Join; + + void processCountingCentrality(ExColsCent::iterator const& collision, + aod::MFTTracks const& tracks) + { + auto c = collision.centFT0C(); + registry.fill(HIST("Events/Centrality/Selection"), 1., c); + + if (!useEvSel || collision.sel8()) { + auto z = collision.posZ(); + registry.fill(HIST("Events/Centrality/Selection"), 2., c); + auto perCollisionSample = sample->sliceByCached( + o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + auto nTrk = perCollisionSample.size(); + + registry.fill(HIST("Events/Centrality/NtrkZvtx"), nTrk, z, c); + + for (const auto& track : tracks) { + + float phi = track.phi(); + o2::math_utils::bringTo02Pi(phi); + + if (usePhiCut) { + if ((phi < cfgPhiCut) || + ((phi > o2::constants::math::PI - cfgPhiCut) && (phi < o2::constants::math::PI + cfgPhiCut)) || + (phi > o2::constants::math::TwoPI - cfgPhiCut) || + ((phi > ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) - cfgPhiCut) && + (phi < ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) + cfgPhiCut))) + continue; + } + + registry.fill(HIST("Tracks/Centrality/EtaZvtx"), track.eta(), z, c); + registry.fill(HIST("Tracks/Centrality/PhiEta"), phi, track.eta(), c); + } + + } else { + registry.fill(HIST("Events/Centrality/Selection"), 3., + c); // rejected events + } + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processCountingCentrality, + "Count tracks in centrality bins", false); + + using Particles = soa::Filtered; + expressions::Filter primaries = + (aod::mcparticle::flags & + (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == + (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary; + static constexpr float McSampleEtaMax = 1.1f; + Partition mcSample = nabs(aod::mcparticle::eta) < McSampleEtaMax; + Partition mcSampleCentral = + nabs(aod::mcparticle::eta) < estimatorEta; + + void processGen( + aod::McCollisions::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, aod::MFTTracks const& /*tracks*/, + FiCentralTracks const& midtracks) + { + registry.fill(HIST("EventEfficiency"), static_cast(EventEfficiencyBin::Generated)); + + auto perCollisionMCSample = mcSample->sliceByCached( + aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + auto nCharged = 0; + for (const auto& particle : perCollisionMCSample) { + auto charge = 0.; + auto p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < ChargeUnitTimesThree) { + continue; + } + nCharged++; + } + registry.fill(HIST("EventsNtrkZvtxGen_t"), nCharged, mcCollision.posZ()); + + //--------for INEL>0 + auto perCollisionMCSampleCentral = mcSampleCentral->sliceByCached( + aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + auto nChargedCentral = 0; + for (const auto& particle : perCollisionMCSample) { + auto charge = 0.; + auto p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < ChargeUnitTimesThree) { + continue; + } + nChargedCentral++; + } + if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { + if (nChargedCentral > 0) { + registry.fill(HIST("EventEfficiency"), static_cast(EventEfficiencyBin::GeneratedInelGt0)); + registry.fill(HIST("EventsNtrkZvtxGen_gt0t"), nCharged, + mcCollision.posZ()); + } + } + //----------- + bool atLeastOne = false; + bool atLeastOneGt0 = false; + int moreThanOne = 0; + + LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), + collisions.size()); + for (const auto& collision : collisions) { + registry.fill(HIST("EventEfficiency"), static_cast(EventEfficiencyBin::Reconstructed)); + if (!disableITSROFCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + if (!useEvSel || (useEvSel && collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoSameBunchPileup))) { + atLeastOne = true; + auto perCollisionSample = sample->sliceByCached( + o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + + registry.fill(HIST("EventEfficiency"), static_cast(EventEfficiencyBin::Selected)); + auto perCollisionSampleCentral = + midtracks.sliceBy(perColCentral, collision.globalIndex()); + if ((collision.posZ() >= cfgVzCut1) && (collision.posZ() <= cfgVzCut2) && (mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { + if (perCollisionSampleCentral.size() > 0) { + registry.fill(HIST("EventEfficiency"), static_cast(EventEfficiencyBin::SelectedInelGt0)); + atLeastOneGt0 = true; + registry.fill(HIST("EventsNtrkZvtxGen_gt0"), + perCollisionSample.size(), collision.posZ()); + } + + registry.fill(HIST("EventsZposDiff"), + collision.posZ() - mcCollision.posZ()); + if (useZDiffCut) { + if (std::abs(collision.posZ() - mcCollision.posZ()) > maxZDiff) { + continue; + } + } + registry.fill(HIST("EventsNtrkZvtxGen"), perCollisionSample.size(), + collision.posZ()); + ++moreThanOne; + } + } + } + if (collisions.size() == 0) { + registry.fill(HIST("NotFoundEventZvtx"), mcCollision.posZ()); + } + if (moreThanOne > 1) { + registry.fill(HIST("EventsSplitMult"), nCharged); + } + if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { + + for (const auto& particle : particles) { + auto p = pdg->GetParticle(particle.pdgCode()); + auto charge = 0; + if (p != nullptr) { + charge = static_cast(p->Charge()); + } + if (std::abs(charge) < ChargeUnitTimesThree) { + continue; + } + float phi = particle.phi(); + o2::math_utils::bringTo02Pi(phi); + float ptCut = particle.pt(); + + if (usePhiCut) { + if ((phi <= PhiVetoLow) || + ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || + (phi >= PhiVetoHigh)) + continue; + } + if (usePtCut) { + if (ptCut > cfgnPt) + continue; + } + if (cfgnEta1 < particle.eta() && particle.eta() < cfgnEta2 && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { + registry.fill(HIST("TracksEtaZvtxGen_t"), particle.eta(), + mcCollision.posZ()); + if (perCollisionMCSampleCentral.size() > 0) { + registry.fill(HIST("TracksEtaZvtxGen_gt0t"), particle.eta(), + mcCollision.posZ()); + registry.fill(HIST("TracksPhiEtaGen_gt0t"), particle.phi(), particle.eta()); + } + if (atLeastOne) { + registry.fill(HIST("TracksEtaZvtxGen"), particle.eta(), + mcCollision.posZ()); + registry.fill(HIST("TracksPtEtaGen"), particle.pt(), particle.eta()); + if (atLeastOneGt0) { + registry.fill(HIST("TracksEtaZvtxGen_gt0"), particle.eta(), + mcCollision.posZ()); + registry.fill(HIST("TracksPhiEtaGen_gt0"), particle.phi(), particle.eta()); + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("TracksEtaZvtxGen_gt0_primary"), particle.eta(), mcCollision.posZ()); + registry.fill(HIST("TracksPhiEtaGen_gt0_primary"), particle.phi(), particle.eta()); + registry.fill(HIST("TracksPtZvtxGen_gt0_primary"), particle.pt(), mcCollision.posZ()); + } + } + } + + registry.fill(HIST("TracksPhiEtaGen"), particle.phi(), particle.eta()); + registry.fill(HIST("TracksPhiZvtxGen"), particle.phi(), + mcCollision.posZ()); + registry.fill(HIST("TracksPtEtaGen_t"), particle.pt(), particle.eta()); + } + } + } + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processGen, + "Process generator-level info", false); + + using ExColsGenCent = + soa::SmallGroups>; + + void processGenCent(aod::McCollisions::iterator const& mcCollision, + ExColsGenCent const& collisions, + Particles const& particles, + MFTTracksLabeled const& /*tracks*/) + { + + LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), + collisions.size()); + + float cGen = -1; + bool atLeastOne = false; + for (const auto& collision : collisions) { + float cRec = -1; + if constexpr (ExColsGenCent::template contains()) { + cRec = collision.centFT0C(); + } + if (!useEvSel || (useEvSel && collision.sel8())) { + if constexpr (ExColsGenCent::template contains()) { + if (!atLeastOne) { + cGen = cRec; + } + } + atLeastOne = true; + + registry.fill(HIST("Events/Centrality/EventEfficiency"), 2., cGen); + registry.fill(HIST("Events/Centrality/CentPercentileMCGen"), cGen); + + auto perCollisionSample = sample->sliceByCached( + o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); + registry.fill(HIST("Events/Centrality/NtrkZvtxGen"), + perCollisionSample.size(), collision.posZ(), cGen); + } + } + + registry.fill(HIST("Events/Centrality/EventEfficiency"), 1., cGen); + + auto perCollisionMCSample = mcSample->sliceByCached( + aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + auto nCharged = 0; + + for (const auto& particle : perCollisionMCSample) { + auto p = pdg->GetParticle(particle.pdgCode()); + auto charge = 0; + if (p != nullptr) { + charge = static_cast(p->Charge()); + } + if (std::abs(charge) < ChargeUnitTimesThree) { + continue; + } + nCharged++; + } + + if constexpr (ExColsGenCent::template contains()) { + registry.fill(HIST("Events/Centrality/NtrkZvtxGen_t"), nCharged, + mcCollision.posZ(), cGen); + } + + for (const auto& particle : particles) { + auto p = pdg->GetParticle(particle.pdgCode()); + auto charge = 0; + if (p != nullptr) { + charge = static_cast(p->Charge()); + } + if (std::abs(charge) < ChargeUnitTimesThree) { + continue; + } + + if constexpr (ExColsGenCent::template contains()) { + registry.fill(HIST("Tracks/Centrality/EtaZvtxGen_t"), particle.eta(), + mcCollision.posZ(), cGen); + } + + if (atLeastOne) { + if constexpr (ExColsGenCent::template contains()) { + registry.fill(HIST("Tracks/Centrality/EtaZvtxGen"), particle.eta(), + mcCollision.posZ(), cGen); + float phi = particle.phi(); + o2::math_utils::bringTo02Pi(phi); + registry.fill(HIST("Tracks/Centrality/PhiEtaGen"), phi, + particle.eta(), cGen); + } + } + } + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processGenCent, + "Process generator-level info in centrality bins", false); + + void processGenPt( + soa::Join::iterator const& collision, + MFTTracksLabeled const& tracks, aod::McParticles const&) + { + if (!useEvSel || (useEvSel && collision.sel8())) { + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + auto particle = track.mcParticle(); + if (!particle.isPhysicalPrimary()) { + continue; + } + registry.fill(HIST("TracksToPartPtEta"), particle.pt(), particle.eta()); + } + } + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processGenPt, + "Process particle-level info of pt", false); + + void processGenRecoTimeCom(McCollisionsWithExtra::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + MFTTracksLabeledOrg const& tracks, + FiCentralTracks const& midtracks, + aod::McParticles const&) + { + const auto fillGenRecoCut = [&](GenRecoCutBin bin) { + registry.fill(HIST("EventsRecoCuts_GenReco"), static_cast(bin)); + }; + fillGenRecoCut(GenRecoCutBin::AllRecoCollisions); + std::unordered_map recoToMc; + std::unordered_map> mcToReco; // MC collision id -> list of reco collision globalIndex + + for (const auto& collision : collisions) { + int nSavedRows = 0; + std::unordered_set uniqueRecoColsSaved; + int recoCol = collision.globalIndex(); // reconstructed vertex index + int mcCol = collision.mcCollisionId(); // true MC collision index + + if (mcCol >= 0) { + recoToMc[recoCol] = mcCol; + mcToReco[mcCol].push_back(recoCol); + + ++nSavedRows; + uniqueRecoColsSaved.insert(recoCol); + } + registry.fill(HIST("Purity/HashTableRowCounts"), + static_cast(HashTableRowCountsBin::RowsSaved), nSavedRows); + registry.fill(HIST("Purity/HashTableRowCounts"), + static_cast(HashTableRowCountsBin::UniqueRecoColsSaved), uniqueRecoColsSaved.size()); + + registry.fill(HIST("Purity/reco/CollisionNumContrib"), collision.numContrib()); + + if (useCont && collision.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + fillGenRecoCut(GenRecoCutBin::UseContBestCollisionIndex); + + if (!collision.has_mcCollision()) { + LOGF(warning, "No MC collision found..."); + return; + } + fillGenRecoCut(GenRecoCutBin::HasMcCollision); + + auto countAndPassEvSelGenReco = [&](auto const& collision) { + struct EvSelStep { + bool enabled; + decltype(aod::evsel::kIsTriggerTVX) bit; + GenRecoCutBin bin; + }; + + const std::array steps = {{ + {true, aod::evsel::kIsTriggerTVX, GenRecoCutBin::IsTriggerTVX}, + {true, aod::evsel::kNoTimeFrameBorder, GenRecoCutBin::NoTimeFrameBorder}, + {true, aod::evsel::kNoITSROFrameBorder, GenRecoCutBin::NoITSROFrameBorder}, + {useNoSameBunchPileup, aod::evsel::kNoSameBunchPileup, GenRecoCutBin::NoSameBunchPileup}, + {useGoodZvtxFT0vsPV, aod::evsel::kIsGoodZvtxFT0vsPV, GenRecoCutBin::GoodZvtxFT0vsPV}, + {useNoCollInRofStandard, aod::evsel::kNoCollInRofStandard, GenRecoCutBin::NoCollInRofStandard}, + {useNoCollInRofStrict, aod::evsel::kNoCollInRofStrict, GenRecoCutBin::NoCollInRofStrict}, + {useNoCollInTimeRangeStandard, aod::evsel::kNoCollInTimeRangeStandard, GenRecoCutBin::NoCollInTimeRangeStandard}, + {useNoCollInTimeRangeStrict, aod::evsel::kNoCollInTimeRangeStrict, GenRecoCutBin::NoCollInTimeRangeStrict}, + {useNoHighMultCollInPrevRof, aod::evsel::kNoHighMultCollInPrevRof, GenRecoCutBin::NoHighMultCollInPrevRof}, + }}; + + if (!useEvSel) { + for (const auto& step : steps) { + fillGenRecoCut(step.bin); + } + fillGenRecoCut(GenRecoCutBin::RctMFT); + return true; + } + + for (const auto& step : steps) { + if (!step.enabled) { + fillGenRecoCut(step.bin); + continue; + } + + if (!collision.selection_bit(step.bit)) { + return false; + } + fillGenRecoCut(step.bin); + } + + if (useRctMFT && !myChecker(collision)) { + return false; + } + fillGenRecoCut(GenRecoCutBin::RctMFT); + + return true; + }; + + if (!countAndPassEvSelGenReco(collision)) { + continue; + } + + const auto z = collision.posZ(); + if ((z < cfgVzCut1) || (z > cfgVzCut2)) { + continue; + } + fillGenRecoCut(GenRecoCutBin::VzWindow); + + auto perCollisionSampleCentral = midtracks.sliceBy(perColCentral, collision.globalIndex()); + if (perCollisionSampleCentral.size() <= 0) { + continue; + } + fillGenRecoCut(GenRecoCutBin::InelGt0); + + // constexpr uint8_t kFakeMcMask = 1u << 7; + for (const auto& track : tracks) { + float ndf = getTrackNdf(track); + const float chi2ndf = track.chi2() / ndf; + float phi = track.phi(); + // const float dcaXyCut = track.bestDCAXY(); + // const float dcaZCut = track.bestDCAZ(); + const float ptCut = track.pt(); + o2::math_utils::bringTo02Pi(phi); + + const bool failTrackCuts = + track.nClusters() < cfgnCluster || + track.eta() <= cfgnEta1 || + track.eta() >= cfgnEta2 || + chi2ndf >= cfgChi2NDFMax || + phi <= cfgPhiCut1 || + phi >= cfgPhiCut2 || + (usePhiCut && + ((phi <= PhiVetoLow) || + ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || + (phi >= PhiVetoHigh))) || + // (useDCAxyCut && dcaxyCut > maxDCAxy) || + // (useDCAzCut && std::abs(dcazCut) > maxDCAz) || + (usePtCut && ptCut > cfgnPt); + + if (failTrackCuts) { + continue; + } + const bool hasMcLabel = track.has_mcParticle(); + const bool isFakeByLabel = hasMcLabel ? (track.mcMask() != 0) : false; + const bool isTrueByLabel = hasMcLabel && !isFakeByLabel; + const bool hasNoMcLabel = !hasMcLabel; + const bool isPrimaryCharged = hasMcLabel && !isFakeByLabel && track.mcParticle().isPhysicalPrimary(); + const bool isSecondaryCharged = hasMcLabel && !isFakeByLabel && !track.mcParticle().isPhysicalPrimary(); + const float eta = track.eta(); + if (!passGenRecoTrackMode(track)) { // 0-> All nonorphans, 1->Non-Amb, 2->Amb + continue; + } + int bin = static_cast(RightWrongBin::Neither); + bool recoOfTrueExists = false; + + if (isTrueByLabel) { + int recoCol = track.collisionId(); + auto itRecoToMc = recoToMc.find(recoCol); + const int mcOfTrack = track.mcParticle().mcCollisionId(); + + // Check whether any reco vertex exists for the true MC collision of this track + for (const auto& [recoId, mcId] : recoToMc) { + if (mcId == mcOfTrack) { + recoOfTrueExists = true; + break; + } + } + + if (recoCol >= 0 && itRecoToMc != recoToMc.end()) { + int mcFromReco = itRecoToMc->second; + bin = (mcFromReco == mcOfTrack) + ? static_cast(RightWrongBin::Right) + : static_cast(RightWrongBin::Wrong); + } + } + + registry.fill(HIST("RightWrong"), bin); + + if (bin == static_cast(RightWrongBin::Wrong)) { + registry.fill(HIST("Purity/WrongVertexRecoExists"), recoOfTrueExists ? static_cast(BoolBin::Yes) : static_cast(BoolBin::No)); + } + + const auto fillTrackLabelSummary = [&](TrackLabelSummaryBin bin) { + registry.fill(HIST("Purity/TrackLabelSummary"), static_cast(bin)); + }; + const auto fillTrackEtaCategory = [&](TrackLabelSummaryBin bin) { + constexpr float EtaSentinel = -999.f; + + float etaAll = EtaSentinel; + float etaNoMc = EtaSentinel; + float etaFake = EtaSentinel; + float etaTrue = EtaSentinel; + float etaPrimary = EtaSentinel; + float etaSecondary = EtaSentinel; + + switch (bin) { + case TrackLabelSummaryBin::AllTracks: + etaAll = eta; + break; + case TrackLabelSummaryBin::NoMcLabel: + etaNoMc = eta; + break; + case TrackLabelSummaryBin::FakeTracks: + etaFake = eta; + break; + case TrackLabelSummaryBin::TrueTracks: + etaTrue = eta; + break; + case TrackLabelSummaryBin::PrimaryTracks: + etaPrimary = eta; + break; + case TrackLabelSummaryBin::SecondaryTracks: + etaSecondary = eta; + break; + } + + registry.fill(HIST("Purity/TrackEtaCategorySparse"), + etaAll, etaNoMc, etaFake, etaTrue, etaPrimary, etaSecondary); + }; + + // registry.fill(HIST("Purity/TrackLabelStatus"), hasMcLabel ? 1.0 : 0.0); + // registry.fill(HIST("Purity/TrackFakeStatus"), isFakeByLabel ? 1.0 : 0.0); + + fillTrackLabelSummary(TrackLabelSummaryBin::AllTracks); + fillTrackEtaCategory(TrackLabelSummaryBin::AllTracks); + + if (hasNoMcLabel) { + fillTrackLabelSummary(TrackLabelSummaryBin::NoMcLabel); + fillTrackEtaCategory(TrackLabelSummaryBin::NoMcLabel); + continue; + } + + if (isFakeByLabel) { + fillTrackLabelSummary(TrackLabelSummaryBin::FakeTracks); + fillTrackEtaCategory(TrackLabelSummaryBin::FakeTracks); + continue; + } + + fillTrackLabelSummary(TrackLabelSummaryBin::TrueTracks); + fillTrackEtaCategory(TrackLabelSummaryBin::TrueTracks); + + if (isPrimaryCharged) { + fillTrackLabelSummary(TrackLabelSummaryBin::PrimaryTracks); + fillTrackEtaCategory(TrackLabelSummaryBin::PrimaryTracks); + } + + if (isSecondaryCharged) { + fillTrackLabelSummary(TrackLabelSummaryBin::SecondaryTracks); + fillTrackEtaCategory(TrackLabelSummaryBin::SecondaryTracks); + } + // registry.fill(HIST("RightWrong"), bin); + + } // Track loop 1 + } // Collision + } + PROCESS_SWITCH(PseudorapidityDensityMFT, processGenRecoTimeCom, + "Process for MC time compatible", false); + + // using MFTTracksLabeled = soa::Join; + // using MFTTracksLabeled =soa::Join; + + // aod::MFTTracks const& tracks + // soa::Join::iterator const& mcCollision + // aod::McCollisions::iterator const& mcCollision + // McCollisionsWithExtra::iterator const& mcCollision + + // void processMCeff(soa::Join::iterator const& mcCollision, CollisionMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) + // soa::Join::iterator const& mcCollision //This worked + void processGenReco(McCollisionsWithExtra::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + FullBCs const& bcs, + MFTTracksLabeled const& tracks, + FiCentralTracks const& midtracks, + aod::McParticles const&) + + { + + const auto fillGenRecoCut = [&](GenRecoCutBin bin) { + registry.fill(HIST("EventsRecoCuts_GenReco"), static_cast(bin)); + }; + fillGenRecoCut(GenRecoCutBin::AllRecoCollisions); + + // if (maxGenRecoEvents >= 0 && nProcessedGenReco >= maxGenRecoEvents) { + // return; + // } + // ++nProcessedGenReco; // for HIR + std::unordered_map recoToMc; + std::unordered_map> mcToReco; // MC collision id -> list of reco collision globalIndex + std::unordered_map recoToMcVZ; + std::unordered_map recoVtxX; + std::unordered_map recoVtxY; + std::unordered_map recoVtxZ; + std::unordered_map> recoVtxByRecoId; + std::unordered_map> recoVtxByMcId; + + recoVtxByRecoId.reserve(collisions.size()); + recoVtxByMcId.reserve(collisions.size()); + mcToReco.reserve(collisions.size()); + + // --- Make sure magnetic field exists in THIS device before any propagation --- + // IMPORTANT: calling collision.bc_as() requires the BC table to be subscribed. + // We subscribe by taking `FullBCs const& bcs` in the process signature and init once here. + bool magInited = false; + for (auto const& bc : bcs) { + initMagField(bc); + magInited = true; + break; // once is enough (initMagField is internally guarded) + } + if (!magInited) { + LOGF(fatal, "BC table is empty: cannot initialize magnetic field"); + } + + //_______________________________________________________________________________ + + for (const auto& collision : collisions) { + int nSavedRows = 0; + std::unordered_set uniqueRecoColsSaved; + int recoCol = collision.globalIndex(); // reconstructed vertex index + int mcCol = collision.mcCollisionId(); // true MC collision index + + if (mcCol >= 0) { + recoToMc[recoCol] = mcCol; + mcToReco[mcCol].push_back(recoCol); + + ++nSavedRows; + uniqueRecoColsSaved.insert(recoCol); + } + registry.fill(HIST("Purity/HashTableRowCounts"), + static_cast(HashTableRowCountsBin::RowsSaved), nSavedRows); + registry.fill(HIST("Purity/HashTableRowCounts"), + static_cast(HashTableRowCountsBin::UniqueRecoColsSaved), uniqueRecoColsSaved.size()); + + recoVtxX[recoCol] = collision.posX(); + recoVtxY[recoCol] = collision.posY(); + recoVtxZ[recoCol] = collision.posZ(); + + registry.fill(HIST("Purity/reco/CollisionNumContrib"), collision.numContrib()); + + if (useCont && collision.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + fillGenRecoCut(GenRecoCutBin::UseContBestCollisionIndex); + + if (!collision.has_mcCollision()) { + LOGF(warning, "No MC collision found..."); + return; + } + fillGenRecoCut(GenRecoCutBin::HasMcCollision); + + auto countAndPassEvSelGenReco = [&](auto const& collision) { + struct EvSelStep { + bool enabled; + decltype(aod::evsel::kIsTriggerTVX) bit; + GenRecoCutBin bin; + }; + + const std::array steps = {{ + {true, aod::evsel::kIsTriggerTVX, GenRecoCutBin::IsTriggerTVX}, + {true, aod::evsel::kNoTimeFrameBorder, GenRecoCutBin::NoTimeFrameBorder}, + {true, aod::evsel::kNoITSROFrameBorder, GenRecoCutBin::NoITSROFrameBorder}, + {useNoSameBunchPileup, aod::evsel::kNoSameBunchPileup, GenRecoCutBin::NoSameBunchPileup}, + {useGoodZvtxFT0vsPV, aod::evsel::kIsGoodZvtxFT0vsPV, GenRecoCutBin::GoodZvtxFT0vsPV}, + {useNoCollInRofStandard, aod::evsel::kNoCollInRofStandard, GenRecoCutBin::NoCollInRofStandard}, + {useNoCollInRofStrict, aod::evsel::kNoCollInRofStrict, GenRecoCutBin::NoCollInRofStrict}, + {useNoCollInTimeRangeStandard, aod::evsel::kNoCollInTimeRangeStandard, GenRecoCutBin::NoCollInTimeRangeStandard}, + {useNoCollInTimeRangeStrict, aod::evsel::kNoCollInTimeRangeStrict, GenRecoCutBin::NoCollInTimeRangeStrict}, + {useNoHighMultCollInPrevRof, aod::evsel::kNoHighMultCollInPrevRof, GenRecoCutBin::NoHighMultCollInPrevRof}, + }}; + + if (!useEvSel) { + for (const auto& step : steps) { + fillGenRecoCut(step.bin); + } + fillGenRecoCut(GenRecoCutBin::RctMFT); + return true; + } + + for (const auto& step : steps) { + if (!step.enabled) { + fillGenRecoCut(step.bin); + continue; + } + + if (!collision.selection_bit(step.bit)) { + return false; + } + fillGenRecoCut(step.bin); + } + + if (useRctMFT && !myChecker(collision)) { + return false; + } + fillGenRecoCut(GenRecoCutBin::RctMFT); + + return true; + }; + + if (!countAndPassEvSelGenReco(collision)) { + continue; + } + + const auto z = collision.posZ(); + if ((z < cfgVzCut1) || (z > cfgVzCut2)) { + continue; + } + fillGenRecoCut(GenRecoCutBin::VzWindow); + + auto perCollisionSampleCentral = midtracks.sliceBy(perColCentral, collision.globalIndex()); + if (perCollisionSampleCentral.size() <= 0) { + continue; + } + fillGenRecoCut(GenRecoCutBin::InelGt0); + + //________________________________________________________________________________ + + registry.fill(HIST("Purity/xReco"), collision.posX()); + registry.fill(HIST("Purity/xTrue"), mcCollision.posX()); + registry.fill(HIST("Purity/yReco"), collision.posY()); + + registry.fill(HIST("Purity/yTrue"), mcCollision.posY()); + registry.fill(HIST("Purity/zReco"), collision.posZ()); + registry.fill(HIST("Purity/zTrue"), mcCollision.posZ()); + + // --- Vertex position THnSparse: status axis (1=reco, 2=true) --- + registry.fill(HIST("Purity/VtxXYZTruth"), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + registry.fill(HIST("Purity/VtxXYZReco"), collision.posX(), collision.posY(), collision.posZ()); + + // --- Delta vertex THnSparse (reco - true) --- + registry.fill(HIST("Purity/DeltaVtxXYZ"), + collision.posX() - mcCollision.posX(), // Reco - Truth + collision.posY() - mcCollision.posY(), + collision.posZ() - mcCollision.posZ()); + + recoVtxByRecoId[collision.globalIndex()] = {collision.posX(), collision.posY(), collision.posZ()}; + recoVtxByMcId[collision.mcCollisionId()] = {mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()}; + + int64_t woOrpCount = 0; + bool filledRight = false; + bool filledWrong = false; + int nMftSelectedAfterCuts = 0; + std::unordered_set uniqueBestRecoCols; + // auto particle = templatedTrack.template mcParticle_as(); + + if (tracks.size() > 0) { + bool countedPrimary = false; + for (const auto& track : tracks) { // track loop starts + // All compatible collisions assigned by track-to-collision-associator + if (!(midtracks.size() > 0)) + continue; + // std::cout <<" midtracks.size() " <= cfgnEta2 || + chi2ndf >= cfgChi2NDFMax || + phi <= cfgPhiCut1 || + phi >= cfgPhiCut2 || + (usePhiCut && + ((phi <= PhiVetoLow) || + ((phi >= PhiVetoPiMin) && (phi <= PhiVetoPiMax)) || + (phi >= PhiVetoHigh))) || + (useDCAxyCut && dcaXyCut > maxDCAxy) || + (useDCAzCut && std::abs(dcaZCut) > maxDCAz) || + (usePtCut && ptCut > cfgnPt); + + if (failTrackCuts) { + continue; + } + + const bool hasMcLabel = track.has_mcParticle(); + const bool isFakeByLabel = hasMcLabel ? (track.mcMask() != 0) : false; + const bool isTrueByLabel = hasMcLabel && !isFakeByLabel; + const bool isPrimaryCharged = hasMcLabel && !isFakeByLabel && track.mcParticle().isPhysicalPrimary(); + const bool isSecondaryCharged = hasMcLabel && !isFakeByLabel && !track.mcParticle().isPhysicalPrimary(); + const auto mcColObj = track.mcParticle().mcCollision_as(); + const auto mcPart = track.mcParticle(); + + if (!passGenRecoTrackMode(track)) { // + continue; + } + int bin = static_cast(RightWrongBin::Neither); + bool recoOfTrueExists = false; + bool recoOfTrueInCompatible = false; + + const int bestColID = track.bestCollisionId(); // same as track.collisionId(); + if (isTrueByLabel) { + auto itRecoToMc = recoToMc.find(bestColID); + const int mcOfTrack = track.mcParticle().mcCollisionId(); + const auto compatibleIds = track.compatibleCollIds(); + auto itRecoList = mcToReco.find(mcOfTrack); + + // 1) First check whether the correct reco collision of the true MC collision + // is present in the compatible-collision list. + if (!compatibleIds.empty() && itRecoList != mcToReco.end() && !itRecoList->second.empty()) { + for (const auto& trueRecoId : itRecoList->second) { + for (const auto& compatibleId : compatibleIds) { + if (compatibleId == trueRecoId) { + recoOfTrueInCompatible = true; + break; + } + } + if (recoOfTrueInCompatible) { + break; + } + } + } + + // 2) Then check whether any reco collision for the true MC collision exists at all. + if (itRecoList != mcToReco.end() && !itRecoList->second.empty()) { + recoOfTrueExists = true; + } + + // 3) Finally classify the actually chosen reco collision as right/wrong. + if (bestColID >= 0 && itRecoToMc != recoToMc.end()) { + const int mcFromReco = itRecoToMc->second; + bin = (mcFromReco == mcOfTrack) + ? static_cast(RightWrongBin::Right) + : static_cast(RightWrongBin::Wrong); + } + } + + registry.fill(HIST("RightWrong"), bin); + registry.fill(HIST("Purity/RecoOfTrueExists"), + recoOfTrueExists ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + registry.fill(HIST("Purity/RecoOfTrueInCompatible"), + recoOfTrueInCompatible ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + + if (bin == static_cast(RightWrongBin::Wrong)) { + registry.fill(HIST("Purity/WrongVertexRecoExists"), + recoOfTrueExists ? static_cast(WrongVertexRecoExistsBin::RecoOfTrueExists) + : static_cast(WrongVertexRecoExistsBin::RecoOfTrueMissing)); + registry.fill(HIST("Purity/RecoOfTrueExistsW"), + recoOfTrueExists ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + registry.fill(HIST("Purity/RecoOfTrueInCompatibleW"), + recoOfTrueInCompatible ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + } + + if (bin == static_cast(RightWrongBin::Right)) { + registry.fill(HIST("Purity/RecoOfTrueExistsR"), + recoOfTrueExists ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + registry.fill(HIST("Purity/RecoOfTrueInCompatibleR"), + recoOfTrueInCompatible ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + } + + registry.fill(HIST("Purity/RecoSparseAll"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + + if (isPrimaryCharged) { + registry.fill(HIST("Purity/RecoSparsePrimary"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } else { + registry.fill(HIST("Purity/RecoSparseSecondary"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } + + registry.fill(HIST("RecoSparseAllBest"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + if (bin == static_cast(RightWrongBin::Wrong)) { + float vzBest = 999.; + float vzTrue = 999.; + auto itVzBest = recoVtxZ.find(bestColID); + if (itVzBest != recoVtxZ.end()) { + vzBest = itVzBest->second; + } + auto itVzTrue = recoToMcVZ.find(vzBest); + if (itVzTrue != recoToMcVZ.end()) { + vzTrue = itVzBest->second; + } + double_t vztrueParticle = mcColObj.posZ(); + double_t diff1 = vzBest - vztrueParticle; + double_t diff2 = vzBest - vzTrue; + registry.fill(HIST("deltaVZ_fromReco"), diff1); + registry.fill(HIST("deltaVZ_fromTrue"), diff2); + registry.fill(HIST("RecoSparseAllBestWrong"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } + + // Truth DCA components w.r.t. MC collision vertex + const auto dcaXtruth = mcPart.vx() - mcColObj.posX(); // here mcColObj -> mcPart.mcCollision() + const auto dcaYtruth = mcPart.vy() - mcColObj.posY(); + const auto dcaZtruth = mcPart.vz() - mcColObj.posZ(); + const auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + + dcaYtruth * dcaYtruth); + + const float etaTruth = mcPart.eta(); + const bool isPrimaryTruth = mcPart.isPhysicalPrimary(); + + // Base truth histograms (independent of right/wrong vertex) + registry.fill(HIST("Tracks/dca/Truth/THnDCAxyBestGenTruthAll"), + etaTruth, dcaXYtruth, dcaZtruth, dcaXtruth, dcaYtruth); + if (isPrimaryTruth) { + registry.fill(HIST("Tracks/dca/Truth/THnDCAxyBestGenTruthPrim"), + etaTruth, dcaXYtruth, dcaZtruth, dcaXtruth, dcaYtruth); + } else { + registry.fill(HIST("Tracks/dca/Truth/THnDCAxyBestGenTruthSec"), + etaTruth, dcaXYtruth, dcaZtruth, dcaXtruth, dcaYtruth); + } + + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksEtaZvtx"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksPtZvtx"), track.pt(), z); + if (perCollisionSampleCentral.size() > 0) { + registry.fill(HIST("Purity/reco/woOrp/woOrpEtaZvtx_gt0"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpPtZvtx_gt0"), track.pt(), z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksDCAxyZvtx_gt0"), dcaXyCut, z); + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksDCAzZvtx_gt0"), dcaZCut, z); + } + registry.fill(HIST("Purity/reco/woOrp/woOrpTracksPhiEta"), phi, track.eta()); + + if (isFakeByLabel) { + // std::cout << " track.eta() " < 0) { + registry.fill(HIST("Purity/reco/woOrp_fake/woOrpEtaZvtx_gt0"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp_fake/woOrpPtZvtx_gt0"), track.pt(), z); + } + } + if (isTrueByLabel) { + // Has MC particle + // std::cout << " track.eta() has mc particle " < 0) { + registry.fill(HIST("Purity/reco/woOrp_hasMC/woOrpEtaZvtx_gt0"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp_hasMC/woOrpPtZvtx_gt0"), track.pt(), z); + } + } + if (isSecondaryCharged) { + registry.fill(HIST("Purity/reco/woOrp_secondary/woOrpTracksEtaZvtx"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp_secondary/woOrpTracksPtZvtx"), track.pt(), z); + registry.fill(HIST("Purity/reco/woOrp_secondary/woOrpTracksPhiEta"), phi, track.eta()); + if (perCollisionSampleCentral.size() > 0) { + registry.fill(HIST("Purity/reco/woOrp_secondary/woOrpEtaZvtx_gt0"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp_secondary/woOrpPtZvtx_gt0"), track.pt(), z); + } + } + if (isPrimaryCharged) { + registry.fill(HIST("Purity/reco/woOrp_primary/woOrpTracksEtaZvtx"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp_primary/woOrpTracksPtZvtx"), track.pt(), z); + registry.fill(HIST("Purity/reco/woOrp_primary/woOrpTracksPhiEta"), phi, track.eta()); + if (perCollisionSampleCentral.size() > 0) { + registry.fill(HIST("Purity/reco/woOrp_primary/woOrpEtaZvtx_gt0"), track.eta(), z); + registry.fill(HIST("Purity/reco/woOrp_primary/woOrpPtZvtx_gt0"), track.pt(), z); + } + } + + ++woOrpCount; + // Category 2: all reco tracks after selections (woOrp) + + // --- Primary vs Fake accounting --- + const float xTrue = mcColObj.posX(); + const float yTrue = mcColObj.posY(); + const float zTrue = mcColObj.posZ(); + + std::array dcaInfOrig{999., 999., 999.}; + std::array dcaChosen{999., 999.}; // (DCAxy, DCAz) to chosen reco vertex + std::array dcaRight{999., 999.}; // (DCAxy, DCAz) to truth MC vertex (reference) + std::array dcaChosenXYZ{999., 999., 999.}; // (DCAx, DCAy, DCAz) to chosen reco vertex + + const double bZ = o2::base::Propagator::Instance()->getNominalBz(); + + // Build forward track parameters once per track, then use a fresh copy for each vertex propagation + std::vector v1; // empty -> null cov + SMatrix55 tcovs(v1.begin(), v1.end()); + SMatrix5 tpars(track.x(), track.y(), track.phi(), track.tgl(), track.signed1Pt()); + o2::track::TrackParCovFwd trackPar0{track.z(), tpars, tcovs, track.chi2()}; + + auto trackPar = trackPar0; // copy + dcaInfOrig = {999., 999., 999.}; + const std::array vtxChosen{collision.posX(), collision.posY(), collision.posZ()}; + trackPar.propagateToDCAhelix(bZ, vtxChosen, dcaInfOrig); + dcaChosenXYZ = dcaInfOrig; // store (DCAx, DCAy, DCAz) + dcaChosen[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + dcaChosen[1] = dcaInfOrig[2]; + + dcaInfOrig = {999., 999., 999.}; + const std::array vtxTruth{xTrue, yTrue, zTrue}; + trackPar.propagateToDCAhelix(bZ, vtxTruth, dcaInfOrig); + dcaRight[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + dcaRight[1] = dcaInfOrig[2]; + + registry.fill(HIST("Purity/DCAyVsDCAx_Right"), dcaChosenXYZ[2], dcaChosenXYZ[1]); + // Fill only for WRONG-vertex tracks (the diagnostic you want) + if (bin == static_cast(RightWrongBin::Wrong)) { + // std::cout <<"dcaxy choosen " << dcaXyCut<<" dcaxy calculated "<(RightWrongBin::Right)) { + // std::cout <<"dcaxy choosen " << dcaXyCut<<" dcaxy calculated "<(RightWrongBin::Right)) { + // Right-vertex: all / primary / secondary + registry.fill(HIST("Purity/RecoSparseRightAll"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + if (!filledRight) { + registry.fill(HIST("Purity/RecoSparseRightAll_EventCount"), static_cast(SingleCountBin::Count)); + + filledRight = true; + } + if (isPrimaryCharged) { + registry.fill(HIST("Purity/RecoSparseRightPrimary"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } else { + registry.fill(HIST("Purity/RecoSparseRightSecondary"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } + } else if (bin == static_cast(RightWrongBin::Wrong)) { + // Wrong-vertex: all / primary / secondary + registry.fill(HIST("Purity/RecoSparseWrongAll"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + if (!filledWrong) { + registry.fill(HIST("Purity/RecoSparseWrongAll_EventCount"), static_cast(SingleCountBin::Count)); + filledWrong = true; + } + if (isPrimaryCharged) { + registry.fill(HIST("Purity/RecoSparseWrongPrimary"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } else { + registry.fill(HIST("Purity/RecoSparseWrongSecondary"), + etaReco, dcaXYReco, dcaZReco, dcaXReco, dcaYReco); + } + } + // Reconstructed vertex position for bestbestColID, if available + auto itVtxX = recoVtxX.find(bestColID); + + if (itVtxX != recoVtxX.end()) { + + const float xReco = itVtxX->second; + const float yReco = recoVtxY[bestColID]; + const float zReco = recoVtxZ[bestColID]; + const bool recoVzIn = (zReco >= cfgVzCut1) && (zReco <= cfgVzCut2); + const bool trueVzIn = (zTrue >= cfgVzCut1) && (zTrue <= cfgVzCut2); + + if (!(recoVzIn && trueVzIn)) { + continue; // skip filling Delta* histos for this track + } + + const float deltaXvtx = xReco - xTrue; + const float deltaYvtx = yReco - yTrue; + const float deltaZvtx = zReco - zTrue; + + // We are interested in how far the WRONG collisions are from the true one + if (bin == static_cast(RightWrongBin::Wrong)) { + registry.fill(HIST("Purity/DeltaXWrong"), deltaXvtx); + registry.fill(HIST("Purity/DeltaYWrong"), deltaYvtx); + registry.fill(HIST("Purity/DeltaZWrong"), deltaZvtx); + } + if (bin == static_cast(RightWrongBin::Right)) { + registry.fill(HIST("Purity/DeltaXRight"), deltaXvtx); + registry.fill(HIST("Purity/DeltaYRight"), deltaYvtx); + registry.fill(HIST("Purity/DeltaZRight"), deltaZvtx); + } + } + + // --- Delta-DCA components: truth minus reco --- + const float deltaDCAxy = dcaXYtruth - dcaXYReco; + const float deltaDCAz = dcaZtruth - dcaZReco; + const float deltaDCAx = dcaXtruth - dcaXReco; + const float deltaDCAy = dcaYtruth - dcaYReco; + if (bin == static_cast(RightWrongBin::Right)) { + // Right-vertex: all / primary / secondary + registry.fill(HIST("Tracks/dca/Truth/THnDeltaDCARightAll"), + deltaDCAxy, deltaDCAz, deltaDCAx, deltaDCAy); + if (isPrimaryCharged) { + registry.fill(HIST("Tracks/dca/Truth/THnDeltaDCARightPrim"), + deltaDCAxy, deltaDCAz, deltaDCAx, deltaDCAy); + } else { + registry.fill(HIST("Tracks/dca/Truth/THnDeltaDCARightSec"), + deltaDCAxy, deltaDCAz, deltaDCAx, deltaDCAy); + } + } else { + // Wrong-vertex: all / primary / secondary + registry.fill(HIST("Tracks/dca/Truth/THnDeltaDCAWrongAll"), + deltaDCAxy, deltaDCAz, deltaDCAx, deltaDCAy); + if (isPrimaryCharged) { + registry.fill(HIST("Tracks/dca/Truth/THnDeltaDCAWrongPrim"), + deltaDCAxy, deltaDCAz, deltaDCAx, deltaDCAy); + } else { + registry.fill(HIST("Tracks/dca/Truth/THnDeltaDCAWrongSec"), + deltaDCAxy, deltaDCAz, deltaDCAx, deltaDCAy); + } + } + + // auto mcColObj = track.mcParticle().mcCollision_as(); + // True primary match (purity numerator) + registry.fill(HIST("Purity/mc/PrimaryAll"), static_cast(SingleCountBin::Count)); + registry.fill(HIST("Purity/mc/PrimaryAllEta"), mcPart.eta()); + registry.fill(HIST("Purity/mc/PrimaryTracksEtaZvtx"), mcPart.eta(), mcCollision.posZ()); + if (perCollisionSampleCentral.size() > 0) { + registry.fill(HIST("Purity/mc/PrimaryTracksEtaZvtx_gt0"), mcPart.eta(), mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryTracksPtZvtx_gt0"), mcPart.pt(), mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryTracksDCAxyZvtx_gt0"), dcaXyCut, mcCollision.posZ()); + registry.fill(HIST("Purity/mc/PrimaryTracksDCAzZvtx_gt0"), dcaZCut, mcCollision.posZ()); + } + registry.fill(HIST("Purity/mc/PrimaryTracksPhiEta"), mcPart.phi(), mcPart.eta()); + registry.fill(HIST("Purity/SelectedAfterDCAxy/PrimaryAll"), static_cast(SingleCountBin::Count)); + registry.fill(HIST("Purity/SelectedAfterDCAxy/PrimaryAllEta"), mcPart.eta()); + countedPrimary = true; + + // --- Purity profiles (mean of indicator gives purity) --- + registry.fill(HIST("Purity/PurityOverall"), + static_cast(SingleCountBin::Count), + countedPrimary ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + + registry.fill(HIST("Purity/PurityVsEta"), track.eta(), + countedPrimary ? static_cast(BoolBin::Yes) + : static_cast(BoolBin::No)); + } // track loop + registry.fill(HIST("Purity/HashTableRowCounts"), + static_cast(HashTableRowCountsBin::UniqueBestRecoCols), uniqueBestRecoCols.size()); + } + registry.fill(HIST("Purity/reco/woOrp/nTrk"), woOrpCount); + registry.fill(HIST("Purity/reco/PNchMFT_afterCuts"), nMftSelectedAfterCuts); + } // collision + } + + PROCESS_SWITCH(PseudorapidityDensityMFT, processGenReco, + "Process particle-level info of pt", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx b/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx deleted file mode 100644 index 93b8625ba65..00000000000 --- a/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx +++ /dev/null @@ -1,1223 +0,0 @@ -// Copyright 2020-2025 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 dndeta-mft.cxx -// \author Sarah Herrmann -// -// \brief This code loops over MFT tracks and collisions and fills histograms -// useful to compute dNdeta - -#include "PWGMM/Mult/DataModel/bestCollisionTable.h" - -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RuntimeError.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" - -#include "TFile.h" - -#include -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::aod::track; - -AxisSpec PtAxis = {1001, -0.005, 10.005}; -AxisSpec DeltaZAxis = {61, -6.1, 6.1}; -AxisSpec ZAxis = {301, -30.1, 30.1}; -AxisSpec PhiAxis = {629, 0, o2::constants::math::TwoPI, "Rad", "phi axis"}; -// AxisSpec EtaAxis = {18, -4.6, -1.}; -AxisSpec DCAxyAxis = {5000, -1, 500}; -AxisSpec DCAzAxis = {5000, -251, 250}; -AxisSpec CentAxis = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 100}}; - -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; - -using MFTTracksLabeled = soa::Join; - -struct PseudorapidityDensityMFT { - SliceCache cache; - Preslice perCol = o2::aod::fwdtrack::collisionId; - Preslice perMcCol = aod::mcparticle::mcCollisionId; - Preslice perColCentral = aod::track::collisionId; - - Service pdg; - - Configurable estimatorEta{"estimatorEta", 1.0, - "eta range for INEL>0 sample definition"}; - - Configurable useEvSel{"useEvSel", true, "use event selection"}; - Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROF cut for event selection"}; - ConfigurableAxis multBinning{"multBinning", {701, -0.5, 700.5}, ""}; - ConfigurableAxis EtaAxis = {"etaBinning", {36, -4.6, -1.}, ""}; - - Configurable useZDiffCut{"useZDiffCut", true, "use Z difference cut"}; - Configurable maxZDiff{ - "maxZDiff", 1.0f, - "max allowed Z difference for reconstructed collisions (cm)"}; - - Configurable usePhiCut{"usePhiCut", true, "use azimuthal angle cut"}; - Configurable useDCAxyCut{"useDCAxyCut", false, "use DCAxy cut"}; - Configurable useDCAzCut{"useDCAzCut", false, "use DCAz cut"}; - - Configurable cfgPhiCut{"cfgPhiCut", 0.1f, - "Cut on azimuthal angle of MFT tracks"}; - Configurable cfgPhiCut1{"cfgPhiCut1", 0.0f, - "low Cut on azimuthal angle of MFT tracks"}; - Configurable cfgPhiCut2{"cfgPhiCut2", 6.3f, - "high Cut on azimuthal angle of MFT tracks"}; - Configurable cfgVzCut1{"cfgVzCut1", -30.0f, - "Cut1 on vertex position of MFT tracks"}; - Configurable cfgVzCut2{"cfgVzCut2", 30.0f, - "Cut2 on vertex position of MFT tracks"}; - Configurable cfgnCluster{"cfgnCluster", 5.0f, - "Cut on no of clusters per MFT track"}; - Configurable cfgnEta1{"cfgnEta1", -4.5f, - "Cut on eta1"}; - Configurable cfgnEta2{"cfgnEta2", -1.0f, - "Cut on eta1"}; - Configurable cfgChi2NDFMax{"cfgChi2NDFMax", 2000.0f, "Max allowed chi2/NDF for MFT tracks"}; - Configurable maxDCAxy{"maxDCAxy", 2.0f, "Cut on dcaXY"}; - Configurable maxDCAz{"maxDCAz", 2.0f, "Cut on dcaZ"}; - - HistogramRegistry registry{ - "registry", - {{"TracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}, // - {"Tracks/EtaZvtx_gt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}, // - {"TracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}, // - {"TracksPhiZvtx", - "; #varphi; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {PhiAxis, ZAxis}}}, // - {"TracksPtEta", - " ; p_{T} (GeV/c); #eta", - {HistType::kTH2F, {PtAxis, EtaAxis}}}, // - {"EventSelection", - ";status;events", - {HistType::kTH1F, {{15, 0.5, 15.5}}}}, - {"EventCounts", - ";status;events", - {HistType::kTH1F, {{2, 0.5, 2.5}}}}, - {"Tracks/Control/TrackCount", ";status;Track counts", {HistType::kTH1F, {{15, 0.5, 15.5}}}}, // added - // Purity-related histograms - {"Purity/SelectedAfterDCAxy/All", - ";bin;counts", - {HistType::kTH1F, {{1, 0.5, 1.5}}}}, - {"Purity/SelectedAfterDCAxy/AllEta", - ";#eta;counts", - {HistType::kTH1F, {EtaAxis}}}, - {"Purity/Gen/PrimaryEta", - ";#eta;primaries", - {HistType::kTH1F, {EtaAxis}}}, - {"Purity/Gen/All", - ";bin;counts", - {HistType::kTH1F, {{1, 0.5, 1.5}}}}, - {"Purity/Gen/AllEta", - ";#eta;counts", - {HistType::kTH1F, {EtaAxis}}}}}; - - void init(InitContext&) - { - if (static_cast(doprocessMult) + - static_cast(doprocessMultReassoc) + - static_cast(doprocessMultReassoc3d) + - static_cast(doprocessCountingCentrality) > - 1) { - LOGP(fatal, - "Exactly one process function between processMult, " - "processMultReassoc, processMultReassoc3d and processCountingCentrality should be " - "enabled!"); - } - AxisSpec MultAxis = {multBinning, "N_{trk}"}; - auto hstat = registry.get(HIST("EventSelection")); - auto* x = hstat->GetXaxis(); - x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "Vz"); - x->SetBinLabel(3, "Vz+ITSRof"); - x->SetBinLabel(4, "Vz+Selected"); - x->SetBinLabel(5, "Sel8+Vz+INEL>0"); - x->SetBinLabel(6, "Sel INEL,INEL_fwd>0"); - x->SetBinLabel(7, "Rejected"); - x->SetBinLabel(8, "Good BCs"); - x->SetBinLabel(9, "BCs with collisions"); - x->SetBinLabel(10, "BCs with pile-up/splitting"); - x->SetBinLabel(11, "percollisionSample>0"); - x->SetBinLabel(12, "midtracks+percollisionSample>0"); - registry.add({"EventsNtrkZvtx", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"EventsNtrkZvtx_gt0", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_all", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_sel8", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelfwdgt0", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"Tracks/Control/DCAXY", - " ; DCA_{XY} (cm)", - {HistType::kTH1F, {DCAxyAxis}}}); - if (doprocessGen) { - registry.add({"EventsNtrkZvtxGen", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"EventsNtrkZvtxGen_t", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"EventsNtrkZvtxGen_gt0", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"EventsNtrkZvtxGen_gt0t", - "; N_{trk}; #it{z}_{vtx} (cm); events", - {HistType::kTH2F, {MultAxis, ZAxis}}}); - registry.add({"TracksEtaZvtxGen", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"TracksEtaZvtxGen_t", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"TracksEtaZvtxGen_gt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"TracksEtaZvtxGen_gt0t", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"TracksPhiEtaGen", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"TracksPhiEtaGen_gt0", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"TracksPhiEtaGen_gt0t", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"TracksPhiZvtxGen", - "; #varphi; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {PhiAxis, ZAxis}}}); // - registry.add({"TracksToPartPtEta", - " ; p_{T} (GeV/c); #eta", - {HistType::kTH2F, {PtAxis, EtaAxis}}}); // - registry.add({"TracksPtEtaGen", - " ; p_{T} (GeV/c); #eta", - {HistType::kTH2F, {PtAxis, EtaAxis}}}); - registry.add({"TracksPtEtaGen_t", - " ; p_{T} (GeV/c); #eta", - {HistType::kTH2F, {PtAxis, EtaAxis}}}); - registry.add({"EventEfficiency", - "; status; events", - {HistType::kTH1F, {{5, 0.5, 5.5}}}}); - registry.add({"NotFoundEventZvtx", - " ; #it{z}_{vtx} (cm)", - {HistType::kTH1F, {ZAxis}}}); - registry.add({"EventsZposDiff", - " ; Z_{rec} - Z_{gen} (cm)", - {HistType::kTH1F, {DeltaZAxis}}}); - registry.add({"EventsSplitMult", " ; N_{gen}", {HistType::kTH1F, {MultAxis}}}); - auto heff = registry.get(HIST("EventEfficiency")); - x = heff->GetXaxis(); - x->SetBinLabel(1, "Generated"); - x->SetBinLabel(2, "Generated INEL>0"); - x->SetBinLabel(3, "Reconstructed"); - x->SetBinLabel(4, "Selected"); - x->SetBinLabel(5, "Selected INEL>0"); - } - - if (doprocessMultReassoc || doprocessMultReassoc3d) { - registry.add({"Tracks/Control/DeltaZ", - " ; #it{z_{orig}}-#it{z_{reass}}", - {HistType::kTH1F, {ZAxis}}}); - - registry.add({"Tracks/Control/TrackAmbDegree", - " ; N_{coll}^{comp}", - {HistType::kTH1F, {{51, -0.5, 50.5}}}}); - registry.add({"Tracks/Control/TrackIsAmb", - " ; isAmbiguous", - {HistType::kTH1I, {{2, -0.5, 1.5}}}}); - - auto htrk = registry.get(HIST("Tracks/Control/TrackCount")); - auto* x = htrk->GetXaxis(); - x->SetBinLabel(0, "All"); - x->SetBinLabel(1, "Reass"); - x->SetBinLabel(2, "Not Reass"); - x->SetBinLabel(3, "Amb"); - x->SetBinLabel(4, "Amb+Not-reass"); - x->SetBinLabel(5, "Non-Amb"); - x->SetBinLabel(6, "Not-Reass+Non-Amb"); - x->SetBinLabel(7, "Amb+Non-Amb"); - x->SetBinLabel(8, "colid<0"); - x->SetBinLabel(9, "wo orphan"); - - registry.add({"Tracks/Control/ReassignedTracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"Tracks/Control/ReassignedTracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"Tracks/Control/ReassignedVertexCorr", - "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", - {HistType::kTH2F, {ZAxis, ZAxis}}}); - - registry.add({"Tracks/Control/notReassignedTracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"Tracks/Control/notReassignedTracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"Tracks/Control/notReassignedVertexCorr", - "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", - {HistType::kTH2F, {ZAxis, ZAxis}}}); - registry.add({"Tracks/Control/Chi2NDF", - " ; #chi^{2}/ndf", - {HistType::kTH1F, {{5000, 0.0, 5000.0}}}}); - registry.add({"Tracks/Control/amb/AmbTracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - - registry.add({"Tracks/Control/woOrp/nTrk", - " ; N_{Trk}^{all}", - {HistType::kTH1F, {{701, -0.5, 700.5}}}}); // - registry.add({"Tracks/Control/amb/nTrkAmb", - " ; N_{Trk}^{amb}", - {HistType::kTH1F, {{701, -0.5, 700.5}}}}); // - registry.add({"Tracks/Control/nonamb/nTrkNonAmb", - " ; N_{Trk}^{nonamb}", - {HistType::kTH1F, {{701, -0.5, 700.5}}}}); // - - registry.add({"Tracks/Control/amb/AmbTracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); // - registry.add({"Tracks/Control/amb/AmbVertexCorr", - "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", - {HistType::kTH2F, {ZAxis, ZAxis}}}); // - registry.add({"Tracks/Control/amb/EtaZvtxAmb_gt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/Control/amb/DCAxy_amb", " ; DCA_{xy} (cm) ambiguous", - // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // - {HistType::kTH1F, {DCAxyAxis}}}); // - - registry.add({"Tracks/Control/nonamb/nonAmbTracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - - registry.add({"Tracks/Control/nonamb/nonAmbTracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); // - registry.add({"Tracks/Control/nonamb/nonAmbVertexCorr", - "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", - {HistType::kTH2F, {ZAxis, ZAxis}}}); // - registry.add({"Tracks/Control/nonamb/EtaZvtxNonAmb_gt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/Control/nonamb/DCAxy_nonamb", " ; DCA_{xy}(cm) non-ambiguous", - // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // - {HistType::kTH1F, {{DCAxyAxis}}}}); // - - registry.add({"Tracks/Control/woOrp/woOrpTracksEtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/Control/woOrp/woOrpEtaZvtx_gt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/2Danalysis/EtaZvtx", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/2Danalysis/EtaZvtx_sel8", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/2Danalysis/EtaZvtx_sel8_inelgt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/2Danalysis/EtaZvtx_sel8_inelfwdgt0", - "; #eta; #it{z}_{vtx} (cm); tracks", - {HistType::kTH2F, {EtaAxis, ZAxis}}}); // - registry.add({"Tracks/Control/woOrp/woOrpTracksPhiEta", - "; #varphi; #eta; tracks", - {HistType::kTH2F, {PhiAxis, EtaAxis}}}); // - registry.add({"Tracks/Control/woOrp/woOrpVertexCorr", - "; #it{z}_{vtx}^{orig} (cm); #it{z}_{vtx}^{re} (cm)", - {HistType::kTH2F, {ZAxis, ZAxis}}}); // - registry.add({"Tracks/Control/woOrp/DCAxy_woOrp", " ; DCA_{xy}(cm) w/o orphan", - // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // - {HistType::kTH1F, {{DCAxyAxis}}}}); // - - if (doprocessMultReassoc3d) { - // DCAz histograms analogous to DCAxy, only for 3D reassociation - registry.add({"Tracks/Control/DCAZ", - " ; DCA_{Z} (cm)", - {HistType::kTH1F, {DCAzAxis}}}); - registry.add({"Tracks/Control/amb/DCAz_amb", - " ; DCA_{z} (cm) ambiguous", - {HistType::kTH1F, {DCAzAxis}}}); - registry.add({"Tracks/Control/nonamb/DCAz_nonamb", - " ; DCA_{z}(cm) non-ambiguous", - {HistType::kTH1F, {DCAzAxis}}}); - registry.add({"Tracks/Control/woOrp/DCAz_woOrp", - " ; DCA_{z}(cm) w/o orphan", - {HistType::kTH1F, {DCAzAxis}}}); - } - - registry.add({"collisionID", " ; Collision ID", - // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // - {HistType::kTH1F, {{100000, -50000.0, 50000.0}}}}); // - registry.add({"collisionIDamb", " ; Collision ID amb", - // {HistType::kTH1F,{{100000, 0.5, 100000.0}}}}); // - {HistType::kTH1F, {{100000, -50000.0, 50000.0}}}}); // - registry.add({"NonambEventCounts", " ; EventCounts Nonamb", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // - registry.add({"hNumCollisionsNonAmb_InelMFT", " ; Number of Collisions with Non-Ambiguous Tracks;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // - registry.add({"hNumCollisionsAmb_InelMFT", " ; Number of Collisions with Non-Ambiguous Tracks;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // - registry.add({"hNumCollisions_InelMFT", " ; Number of selected events with Inel>0 and MFT>0;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // - registry.add({"hNumCollisions_Inel", " ; Number of selected events with Inel>0;Count;Frequency", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // - registry.add({"ambEventCounts", " ; EventCounts Nonamb", {HistType::kTH1F, {{1, 0.5, 1.5}}}}); // - } - - if (doprocessCountingCentrality) { - registry.add({"Events/Centrality/Selection", - ";status;centrality;events", - {HistType::kTH2F, {{3, 0.5, 3.5}, CentAxis}}}); - auto hstat = registry.get(HIST("Events/Centrality/Selection")); - auto* x = hstat->GetXaxis(); - x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "Selected"); - x->SetBinLabel(3, "Rejected"); - - registry.add({"Events/Centrality/NtrkZvtx", - "; N_{trk}; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {MultAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/EtaZvtx", - "; #eta; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/PhiEta", - "; #varphi; #eta; centrality", - {HistType::kTH3F, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/PtEta", - " ; p_{T} (GeV/c); #eta; centrality", - {HistType::kTH3F, {PtAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/DCAXYPt", - " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", - {HistType::kTH3F, {PtAxis, DCAxyAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedDCAXYPt", - " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", - {HistType::kTH3F, {PtAxis, DCAxyAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraDCAXYPt", - " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", - {HistType::kTH3F, {PtAxis, DCAxyAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraTracksEtaZvtx", - "; #eta; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraTracksPhiEta", - "; #varphi; #eta; centrality", - {HistType::kTH3F, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedTracksEtaZvtx", - "; #eta; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedTracksPhiEta", - "; #varphi; #eta; centrality", - {HistType::kTH3F, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedVertexCorr", - "; Z_{vtx}^{orig} (cm); Z_{vtx}^{re} (cm); centrality", - {HistType::kTH3F, {ZAxis, ZAxis, CentAxis}}}); - } - - if (doprocessGenCent) { - registry.add({"Events/Centrality/EventEfficiency", - ";status;centrality;events", - {HistType::kTH2F, {{2, 0.5, 2.5}, CentAxis}}}); - auto heff = registry.get(HIST("Events/Centrality/EventEfficiency")); - auto* x = heff->GetXaxis(); - x->SetBinLabel(1, "Generated"); - x->SetBinLabel(2, "Selected"); - - registry.add("Events/Centrality/CentPercentileMCGen", - "CentPercentileMCGen", kTH1D, {CentAxis}, false); - registry.add({"Events/Centrality/NtrkZvtxGen", - "; N_{trk}; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {MultAxis, ZAxis, CentAxis}}}); - registry.add({"Events/Centrality/NtrkZvtxGen_t", - "; N_{trk}; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {MultAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/EtaZvtxGen_t", - "; #eta; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/EtaZvtxGen", - "; #eta; Z_{vtx} (cm); centrality", - {HistType::kTH3F, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/PhiEtaGen", - "; #varphi; #eta; centrality", - {HistType::kTH3F, {PhiAxis, EtaAxis, CentAxis}}}); - } - } - - using FullBCs = soa::Join; - void processTagging(FullBCs const& bcs, - soa::Join const& collisions) - { - - std::vector::iterator> cols; - for (const auto& bc : bcs) { - if (!useEvSel || - (useEvSel && ((bc.selection_bit(aod::evsel::kIsBBT0A) && - bc.selection_bit(aod::evsel::kIsBBT0C)) != 0))) { - registry.fill(HIST("EventSelection"), 8); // added 5->12 - cols.clear(); - for (const auto& collision : collisions) { - if (collision.has_foundBC()) { - if (collision.foundBCId() == bc.globalIndex()) { - cols.emplace_back(collision); - } - } else if (collision.bcId() == bc.globalIndex()) { - cols.emplace_back(collision); - } - } - LOGP(debug, "BC {} has {} collisions", bc.globalBC(), cols.size()); - if (!cols.empty()) { - registry.fill(HIST("EventSelection"), 9); // added 6->13 - if (cols.size() > 1) { - registry.fill(HIST("EventSelection"), 10); // added 7->14 - } - } - } - } - } - - PROCESS_SWITCH(PseudorapidityDensityMFT, processTagging, - "Collect event sample stats", true); - - Partition sample = - (aod::fwdtrack::eta < -2.8f) && (aod::fwdtrack::eta > -3.2f); - - Partition sampleCentral = (nabs(aod::track::eta) < 1.f); - - expressions::Filter atrackFilter = - (aod::fwdtrack::bestCollisionId >= 0) && (aod::fwdtrack::eta < -2.0f) && - (aod::fwdtrack::eta > -3.9f) && (nabs(aod::fwdtrack::bestDCAXY) <= 2.f); - - using CollwEv = soa::Join; - - expressions::Filter trackSelectionCentral = - ((aod::track::trackCutFlag & trackSelectionITS) == trackSelectionITS) && - ifnode((aod::track::v001::detectorMap & (uint8_t)o2::aod::track::TPC) == - (uint8_t)o2::aod::track::TPC, - (aod::track::trackCutFlag & trackSelectionTPC) == - trackSelectionTPC, - true) && - ((aod::track::trackCutFlag & trackSelectionDCA) == trackSelectionDCA) && - (nabs(aod::track::eta) < estimatorEta); - - using FiCentralTracks = soa::Filtered< - soa::Join>; // central tracks for INEL>0 - - void processMult(CollwEv::iterator const& collision, - aod::MFTTracks const& tracks, - FiCentralTracks const& midtracks, aod::Tracks const&) - { - - registry.fill(HIST("EventSelection"), 1.); - if (!useEvSel || (useEvSel && collision.sel8())) { - registry.fill(HIST("EventSelection"), 2.); - auto z = collision.posZ(); - auto perCollisionSample = sampleCentral->sliceByCached( - o2::aod::track::collisionId, collision.globalIndex(), cache); - auto Ntrk = perCollisionSample.size(); - - registry.fill(HIST("EventsNtrkZvtx"), Ntrk, z); - - if (midtracks.size() > 0) // INEL>0 - { - registry.fill(HIST("EventSelection"), 3.); - registry.fill(HIST("EventsNtrkZvtx_gt0"), Ntrk, z); - } - - if (tracks.size() > 0) { - for (const auto& track : tracks) { - - float phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - - if (usePhiCut) { - if ((phi < cfgPhiCut) || - ((phi > o2::constants::math::PI - cfgPhiCut) && (phi < o2::constants::math::PI + cfgPhiCut)) || - (phi > o2::constants::math::TwoPI - cfgPhiCut) || - ((phi > ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) - cfgPhiCut) && - (phi < ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) + cfgPhiCut))) - continue; - } - - registry.fill(HIST("TracksEtaZvtx"), track.eta(), z); - if (midtracks.size() > 0) // INEL>0 - { - registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.eta(), z); - } - registry.fill(HIST("TracksPhiEta"), phi, track.eta()); - registry.fill(HIST("TracksPtEta"), track.pt(), track.eta()); - if ((track.eta() < -2.0f) && (track.eta() > -3.9f)) { - registry.fill(HIST("TracksPhiZvtx"), phi, z); - } - } - } - - } else { - registry.fill(HIST("EventSelection"), 4.); - } - } - - PROCESS_SWITCH(PseudorapidityDensityMFT, processMult, - "Process reco or data info", true); - // Common implementation for both BestCollisionsFwd and BestCollisionsFwd3d - template - void processMultReassocCommon(CollwEv::iterator const& collision, - o2::aod::MFTTracks const&, - RetracksT const& retracks, - FiCentralTracks const& midtracks, aod::Tracks const&) - { - registry.fill(HIST("EventSelection"), 1.); - auto perCollisionSample = sampleCentral->sliceByCached( - o2::aod::track::collisionId, collision.globalIndex(), cache); - auto Ntrk = perCollisionSample.size(); - auto z = collision.posZ(); - registry.fill(HIST("EventsNtrkZvtx"), Ntrk, z); - if ((z >= cfgVzCut1) && (z <= cfgVzCut2)) { - registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_all"), Ntrk, z); - registry.fill(HIST("EventSelection"), 2.); - for (const auto& retrack : retracks) { - auto track = retrack.mfttrack(); - float ndf = std::max(2.0f * track.nClusters() - 5.0f, 1.0f); - float chi2ndf = track.chi2() / ndf; - float phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - if (usePhiCut) { - if ((phi <= 0.02) || ((phi >= 3.10) && (phi <= 3.23)) || (phi >= 6.21)) - continue; - } - float dcaxy_cut = retrack.bestDCAXY(); - if (useDCAxyCut) { - if (dcaxy_cut > maxDCAxy) - continue; - } - if constexpr (std::is_same_v>) { - float dcaz_cut = retrack.bestDCAZ(); - if (useDCAzCut) { - if (dcaz_cut > maxDCAz) - continue; - } - } - if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0 && chi2ndf < cfgChi2NDFMax && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { - registry.fill(HIST("Tracks/2Danalysis/EtaZvtx"), track.eta(), z); - } - } - if (!disableITSROFCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return; - } - registry.fill(HIST("EventSelection"), 3.); - if (!useEvSel || (useEvSel && collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoSameBunchPileup))) { - registry.fill(HIST("EventSelection"), 4.); - registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8"), Ntrk, z); - std::unordered_set uniqueEvents; - std::unordered_set uniqueEventsAmb; - std::unordered_set uniqueCollisions; - std::unordered_set uniqueCollisionsAmb; - std::unordered_set eventsInelMFT; - std::unordered_set eventsInel; - if (midtracks.size() > 0) { - registry.fill(HIST("EventSelection"), 5.); - registry.fill(HIST("EventsNtrkZvtx_gt0"), Ntrk, z); - registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0"), Ntrk, z); - eventsInel.insert(collision.globalIndex()); - } - if (perCollisionSample.size() > 0) { - registry.fill(HIST("EventSelection"), 11.); - } - if (midtracks.size() > 0 && perCollisionSample.size() > 0) { - registry.fill(HIST("EventSelection"), 12.); - } - int64_t i = 0.0, j = 0.0, k = 0.0; - for (const auto& retrack : retracks) { - auto track = retrack.mfttrack(); - float ndf = std::max(2.0f * track.nClusters() - 5.0f, 1.0f); - float chi2ndf = track.chi2() / ndf; - float phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - if (usePhiCut) { - if ((phi <= 0.02) || ((phi >= 3.10) && (phi <= 3.23)) || (phi >= 6.21)) - continue; - } - float dcaxy_cut = retrack.bestDCAXY(); - if (useDCAxyCut) { - if (dcaxy_cut > maxDCAxy) - continue; - } - if constexpr (std::is_same_v>) { - float dcaz_cut = retrack.bestDCAZ(); - if (useDCAzCut) { - if (dcaz_cut > maxDCAz) - continue; - } - } - if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0 && chi2ndf < cfgChi2NDFMax && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { - registry.fill(HIST("Tracks/Control/Chi2NDF"), chi2ndf); - registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8"), track.eta(), z); - if (midtracks.size() > 0 && retrack.ambDegree() > 0) { - registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8_inelgt0"), track.eta(), z); - } - } - } - if (retracks.size() > 0) { - registry.fill(HIST("EventSelection"), 6.); - if (midtracks.size() > 0) { - registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelfwdgt0"), Ntrk, z); - } - for (const auto& retrack : retracks) { - auto track = retrack.mfttrack(); - float ndf = std::max(2.0f * track.nClusters() - 5.0f, 1.0f); - float chi2ndf = track.chi2() / ndf; - float phi = track.phi(); - float dcaxy_cut = retrack.bestDCAXY(); - o2::math_utils::bringTo02Pi(phi); - // Declare dcaz_cut only if needed below. - if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && chi2ndf < cfgChi2NDFMax && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { - if (usePhiCut) { - if ((phi <= 0.02) || ((phi >= 3.10) && (phi <= 3.23)) || (phi >= 6.21)) - continue; - } - if (useDCAxyCut) { - if (dcaxy_cut > maxDCAxy) - continue; - } - if constexpr (std::is_same_v>) { - float dcaz_cut = retrack.bestDCAZ(); - if (useDCAzCut) { - if (dcaz_cut > maxDCAz) - continue; - } - } - // Purity denominator: all tracks that pass the DCA selection and other quality cuts - registry.fill(HIST("Purity/SelectedAfterDCAxy/All"), 1.); - registry.fill(HIST("Purity/SelectedAfterDCAxy/AllEta"), track.eta()); - registry.fill(HIST("TracksEtaZvtx"), track.eta(), z); - if (midtracks.size() > 0 && retrack.ambDegree() > 0) { - registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.eta(), z); - registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8_inelfwdgt0"), track.eta(), z); - eventsInelMFT.insert(retrack.bestCollisionId()); - } - if (retrack.ambDegree() != 0) { - registry.fill(HIST("Tracks/Control/woOrp/woOrpEtaZvtx_gt0"), track.eta(), z); - ++k; - } - float phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - registry.fill(HIST("Tracks/Control/TrackCount"), 0); - registry.fill(HIST("TracksPhiEta"), phi, track.eta()); - registry.fill(HIST("TracksPtEta"), track.pt(), track.eta()); - if ((track.eta() < -2.0f) && (track.eta() > -3.9f)) { - registry.fill(HIST("TracksPhiZvtx"), phi, z); - } - if (track.collisionId() > -1 && retrack.ambDegree() == 1) { - registry.fill(HIST("Tracks/Control/TrackCount"), 8); - registry.fill(HIST("collisionID"), track.collisionId()); - } - if (track.collisionId() > -1 && retrack.ambDegree() > 1) { - registry.fill(HIST("collisionIDamb"), track.collisionId()); - } - if (track.collisionId() != retrack.bestCollisionId()) { - registry.fill(HIST("Tracks/Control/ReassignedTracksEtaZvtx"), - track.eta(), z); - registry.fill(HIST("Tracks/Control/ReassignedTracksPhiEta"), phi, - track.eta()); - registry.fill(HIST("Tracks/Control/ReassignedVertexCorr"), - track.template collision_as().posZ(), z); - - registry.fill(HIST("Tracks/Control/DeltaZ"), - track.template collision_as().posZ() - - collision.posZ()); - registry.fill(HIST("Tracks/Control/TrackCount"), 1); - } - if (track.collisionId() == retrack.bestCollisionId()) { - registry.fill(HIST("Tracks/Control/notReassignedTracksEtaZvtx"), - track.eta(), z); - registry.fill(HIST("Tracks/Control/notReassignedTracksPhiEta"), phi, - track.eta()); - registry.fill(HIST("Tracks/Control/notReassignedVertexCorr"), - track.template collision_as().posZ(), z); - registry.fill(HIST("Tracks/Control/TrackCount"), 2); - } - - registry.fill(HIST("Tracks/Control/TrackAmbDegree"), - retrack.ambDegree()); - registry.fill(HIST("Tracks/Control/DCAXY"), retrack.bestDCAXY()); - if constexpr (std::is_same_v>) { - registry.fill(HIST("Tracks/Control/DCAZ"), retrack.bestDCAZ()); - } - int isAmbiguous = 0; - - if (retrack.ambDegree() > 1 && retrack.ambDegree() != 0) { - isAmbiguous = 1; - ++i; - - registry.fill(HIST("Tracks/Control/amb/EtaZvtxAmb_gt0"), track.eta(), z); - - registry.fill(HIST("Tracks/Control/amb/AmbTracksEtaZvtx"), - track.eta(), z); - registry.fill(HIST("Tracks/Control/amb/AmbTracksPhiEta"), phi, - track.eta()); - registry.fill(HIST("Tracks/Control/amb/AmbVertexCorr"), - track.template collision_as().posZ(), z); - registry.fill(HIST("Tracks/Control/amb/DCAxy_amb"), retrack.bestDCAXY()); - if constexpr (std::is_same_v>) { - registry.fill(HIST("Tracks/Control/amb/DCAz_amb"), retrack.bestDCAZ()); - } - registry.fill(HIST("Tracks/Control/TrackCount"), 3); - if (track.collisionId() == retrack.bestCollisionId()) { - registry.fill(HIST("Tracks/Control/TrackCount"), 5); - } - uniqueEventsAmb.insert(retrack.bestCollisionId()); - } - if (midtracks.size() > 0 && retrack.ambDegree() > 1 && retrack.ambDegree() != 0) { - uniqueCollisionsAmb.insert(collision.globalIndex()); - } - - registry.fill(HIST("Tracks/Control/TrackIsAmb"), isAmbiguous); - if (retrack.ambDegree() == 1 && retrack.ambDegree() != 0) { - ++j; - registry.fill(HIST("Tracks/Control/nonamb/EtaZvtxNonAmb_gt0"), track.eta(), z); - registry.fill(HIST("Tracks/Control/nonamb/nonAmbTracksEtaZvtx"), - track.eta(), z); - registry.fill(HIST("Tracks/Control/nonamb/nonAmbTracksPhiEta"), phi, - track.eta()); - registry.fill(HIST("Tracks/Control/nonamb/nonAmbVertexCorr"), - track.template collision_as().posZ(), z); - registry.fill(HIST("Tracks/Control/nonamb/DCAxy_nonamb"), retrack.bestDCAXY()); - if constexpr (std::is_same_v>) { - registry.fill(HIST("Tracks/Control/nonamb/DCAz_nonamb"), retrack.bestDCAZ()); - } - registry.fill(HIST("Tracks/Control/TrackCount"), 4); - if (track.collisionId() == retrack.bestCollisionId()) { - registry.fill(HIST("Tracks/Control/TrackCount"), 6); - } - uniqueEvents.insert(retrack.bestCollisionId()); - } - if (midtracks.size() > 0 && retrack.ambDegree() == 1 && retrack.ambDegree() != 0) { - uniqueCollisions.insert(collision.globalIndex()); - } - if ((retrack.ambDegree() > 1) || (retrack.ambDegree() <= 1)) - registry.fill(HIST("Tracks/Control/TrackCount"), 7); - if (retrack.ambDegree() != 0) { - registry.fill(HIST("Tracks/Control/woOrp/woOrpTracksEtaZvtx"), - track.eta(), z); - registry.fill(HIST("Tracks/Control/woOrp/woOrpTracksPhiEta"), phi, - track.eta()); - registry.fill(HIST("Tracks/Control/woOrp/woOrpVertexCorr"), - track.template collision_as().posZ(), z); - registry.fill(HIST("Tracks/Control/TrackCount"), 9); // without orphan - registry.fill(HIST("Tracks/Control/woOrp/DCAxy_woOrp"), retrack.bestDCAXY()); - if constexpr (std::is_same_v>) { - registry.fill(HIST("Tracks/Control/woOrp/DCAz_woOrp"), retrack.bestDCAZ()); - } - } - } - } - registry.fill(HIST("ambEventCounts"), 1, uniqueEventsAmb.size()); - registry.fill(HIST("NonambEventCounts"), 1, uniqueEvents.size()); - registry.fill(HIST("hNumCollisionsNonAmb_InelMFT"), 1, uniqueCollisions.size()); - registry.fill(HIST("hNumCollisionsAmb_InelMFT"), 1, uniqueCollisionsAmb.size()); - registry.fill(HIST("hNumCollisions_InelMFT"), 1, eventsInelMFT.size()); - } - registry.fill(HIST("Tracks/Control/amb/nTrkAmb"), i); - registry.fill(HIST("Tracks/Control/nonamb/nTrkNonAmb"), j); - registry.fill(HIST("Tracks/Control/woOrp/nTrk"), k); - registry.fill(HIST("hNumCollisions_Inel"), 1, eventsInel.size()); - } - } else { - registry.fill(HIST("EventSelection"), 7); - } - } - - void processMultReassoc(CollwEv::iterator const& collision, - o2::aod::MFTTracks const& mft, - soa::SmallGroups const& retracks, - FiCentralTracks const& midtracks, aod::Tracks const& trk) - { - processMultReassocCommon(collision, mft, retracks, midtracks, trk); - } - - void processMultReassoc3d(CollwEv::iterator const& collision, - o2::aod::MFTTracks const& mft, - soa::SmallGroups const& retracks, - FiCentralTracks const& midtracks, aod::Tracks const& trk) - { - processMultReassocCommon(collision, mft, retracks, midtracks, trk); - } - PROCESS_SWITCH(PseudorapidityDensityMFT, processMultReassoc, - "Process reco or data info", false); - - PROCESS_SWITCH(PseudorapidityDensityMFT, processMultReassoc3d, - "Process reco or data info (3d)", false); - - using ExColsCent = soa::Join; - - void processCountingCentrality(ExColsCent::iterator const& collision, - aod::MFTTracks const& tracks) - { - auto c = collision.centFT0C(); - registry.fill(HIST("Events/Centrality/Selection"), 1., c); - - if (!useEvSel || collision.sel8()) { - auto z = collision.posZ(); - registry.fill(HIST("Events/Centrality/Selection"), 2., c); - auto perCollisionSample = sample->sliceByCached( - o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); - auto Ntrk = perCollisionSample.size(); - - registry.fill(HIST("Events/Centrality/NtrkZvtx"), Ntrk, z, c); - - for (const auto& track : tracks) { - - float phi = track.phi(); - o2::math_utils::bringTo02Pi(phi); - - if (usePhiCut) { - if ((phi < cfgPhiCut) || - ((phi > o2::constants::math::PI - cfgPhiCut) && (phi < o2::constants::math::PI + cfgPhiCut)) || - (phi > o2::constants::math::TwoPI - cfgPhiCut) || - ((phi > ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) - cfgPhiCut) && - (phi < ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) + cfgPhiCut))) - continue; - } - - registry.fill(HIST("Tracks/Centrality/EtaZvtx"), track.eta(), z, c); - registry.fill(HIST("Tracks/Centrality/PhiEta"), phi, track.eta(), c); - } - - } else { - registry.fill(HIST("Events/Centrality/Selection"), 3., - c); // rejected events - } - } - - PROCESS_SWITCH(PseudorapidityDensityMFT, processCountingCentrality, - "Count tracks in centrality bins", false); - - using Particles = soa::Filtered; - expressions::Filter primaries = - (aod::mcparticle::flags & - (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == - (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary; - Partition mcSample = nabs(aod::mcparticle::eta) < 1.1f; - Partition mcSampleCentral = - nabs(aod::mcparticle::eta) < estimatorEta; - - void processGen( - aod::McCollisions::iterator const& mcCollision, - o2::soa::SmallGroups> const& collisions, - Particles const& particles, aod::MFTTracks const& /*tracks*/, - FiCentralTracks const& midtracks) - { - registry.fill(HIST("EventEfficiency"), 1.); - - auto perCollisionMCSample = mcSample->sliceByCached( - aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); - auto nCharged = 0; - for (const auto& particle : perCollisionMCSample) { - auto charge = 0.; - auto p = pdg->GetParticle(particle.pdgCode()); - if (p != nullptr) { - charge = p->Charge(); - } - if (std::abs(charge) < 3.) { - continue; - } - nCharged++; - } - registry.fill(HIST("EventsNtrkZvtxGen_t"), nCharged, mcCollision.posZ()); - - //--------for INEL>0 - auto perCollisionMCSampleCentral = mcSampleCentral->sliceByCached( - aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); - auto nChargedCentral = 0; - for (const auto& particle : perCollisionMCSample) { - auto charge = 0.; - auto p = pdg->GetParticle(particle.pdgCode()); - if (p != nullptr) { - charge = p->Charge(); - } - if (std::abs(charge) < 3.) { - continue; - } - nChargedCentral++; - } - if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { - if (nChargedCentral > 0) { - registry.fill(HIST("EventEfficiency"), 2.); - registry.fill(HIST("EventsNtrkZvtxGen_gt0t"), nCharged, - mcCollision.posZ()); - } - } - //----------- - bool atLeastOne = false; - bool atLeastOne_gt0 = false; - int moreThanOne = 0; - - LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), - collisions.size()); - for (const auto& collision : collisions) { - registry.fill(HIST("EventEfficiency"), 3.); - if (!disableITSROFCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return; - } - if (!useEvSel || (useEvSel && collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoSameBunchPileup))) { - atLeastOne = true; - auto perCollisionSample = sample->sliceByCached( - o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); - - registry.fill(HIST("EventEfficiency"), 4.); - - auto perCollisionSampleCentral = - midtracks.sliceBy(perColCentral, collision.globalIndex()); - if ((collision.posZ() >= cfgVzCut1) && (collision.posZ() <= cfgVzCut2) && (mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { - if (perCollisionSampleCentral.size() > 0) { - registry.fill(HIST("EventEfficiency"), 5.); - atLeastOne_gt0 = true; - registry.fill(HIST("EventsNtrkZvtxGen_gt0"), - perCollisionSample.size(), collision.posZ()); - } - - registry.fill(HIST("EventsZposDiff"), - collision.posZ() - mcCollision.posZ()); - if (useZDiffCut) { - if (std::abs(collision.posZ() - mcCollision.posZ()) > maxZDiff) { - continue; - } - } - registry.fill(HIST("EventsNtrkZvtxGen"), perCollisionSample.size(), - collision.posZ()); - ++moreThanOne; - } - } - } - if (collisions.size() == 0) { - registry.fill(HIST("NotFoundEventZvtx"), mcCollision.posZ()); - } - if (moreThanOne > 1) { - registry.fill(HIST("EventsSplitMult"), nCharged); - } - if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { - for (const auto& particle : particles) { - auto p = pdg->GetParticle(particle.pdgCode()); - auto charge = 0; - if (p != nullptr) { - charge = static_cast(p->Charge()); - } - if (std::abs(charge) < 3.) { - continue; - } - float phi = particle.phi(); - o2::math_utils::bringTo02Pi(phi); - if (usePhiCut) { - if ((phi <= 0.02) || ((phi >= 3.10) && (phi <= 3.23)) || (phi >= 6.21)) - continue; - } - if (cfgnEta1 < particle.eta() && particle.eta() < cfgnEta2 && (phi > cfgPhiCut1 && phi < cfgPhiCut2)) { - // Purity numerator reference at generator level: physical primaries in the same eta window - if (particle.isPhysicalPrimary()) { - registry.fill(HIST("Purity/Gen/PrimaryEta"), particle.eta()); - // Truth-side total counters for primaries in acceptance (for purity calculations) - registry.fill(HIST("Purity/Gen/All"), 1.); - registry.fill(HIST("Purity/Gen/AllEta"), particle.eta()); - } - registry.fill(HIST("TracksEtaZvtxGen_t"), particle.eta(), - mcCollision.posZ()); - if (perCollisionMCSampleCentral.size() > 0) { - registry.fill(HIST("TracksEtaZvtxGen_gt0t"), particle.eta(), - mcCollision.posZ()); - registry.fill(HIST("TracksPhiEtaGen_gt0t"), particle.phi(), particle.eta()); - } - if (atLeastOne) { - registry.fill(HIST("TracksEtaZvtxGen"), particle.eta(), - mcCollision.posZ()); - registry.fill(HIST("TracksPtEtaGen"), particle.pt(), particle.eta()); - if (atLeastOne_gt0) { - registry.fill(HIST("TracksEtaZvtxGen_gt0"), particle.eta(), - mcCollision.posZ()); - registry.fill(HIST("TracksPhiEtaGen_gt0"), particle.phi(), particle.eta()); - } - } - - registry.fill(HIST("TracksPhiEtaGen"), particle.phi(), particle.eta()); - registry.fill(HIST("TracksPhiZvtxGen"), particle.phi(), - mcCollision.posZ()); - registry.fill(HIST("TracksPtEtaGen_t"), particle.pt(), particle.eta()); - } - } - } - } - - PROCESS_SWITCH(PseudorapidityDensityMFT, processGen, - "Process generator-level info", false); - - using ExColsGenCent = - soa::SmallGroups>; - - void processGenCent(aod::McCollisions::iterator const& mcCollision, - ExColsGenCent const& collisions, - Particles const& particles, - MFTTracksLabeled const& /*tracks*/) - { - - LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), - collisions.size()); - - float c_gen = -1; - bool atLeastOne = false; - for (const auto& collision : collisions) { - float c_rec = -1; - if constexpr (ExColsGenCent::template contains()) { - c_rec = collision.centFT0C(); - } - if (!useEvSel || (useEvSel && collision.sel8())) { - if constexpr (ExColsGenCent::template contains()) { - if (!atLeastOne) { - c_gen = c_rec; - } - } - atLeastOne = true; - - registry.fill(HIST("Events/Centrality/EventEfficiency"), 2., c_gen); - registry.fill(HIST("Events/Centrality/CentPercentileMCGen"), c_gen); - - auto perCollisionSample = sample->sliceByCached( - o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); - registry.fill(HIST("Events/Centrality/NtrkZvtxGen"), - perCollisionSample.size(), collision.posZ(), c_gen); - } - } - - registry.fill(HIST("Events/Centrality/EventEfficiency"), 1., c_gen); - - auto perCollisionMCSample = mcSample->sliceByCached( - aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); - auto nCharged = 0; - - for (const auto& particle : perCollisionMCSample) { - auto p = pdg->GetParticle(particle.pdgCode()); - auto charge = 0; - if (p != nullptr) { - charge = static_cast(p->Charge()); - } - if (std::abs(charge) < 3.) { - continue; - } - nCharged++; - } - - if constexpr (ExColsGenCent::template contains()) { - registry.fill(HIST("Events/Centrality/NtrkZvtxGen_t"), nCharged, - mcCollision.posZ(), c_gen); - } - - for (const auto& particle : particles) { - auto p = pdg->GetParticle(particle.pdgCode()); - auto charge = 0; - if (p != nullptr) { - charge = static_cast(p->Charge()); - } - if (std::abs(charge) < 3.) { - continue; - } - - if constexpr (ExColsGenCent::template contains()) { - registry.fill(HIST("Tracks/Centrality/EtaZvtxGen_t"), particle.eta(), - mcCollision.posZ(), c_gen); - } - - if (atLeastOne) { - if constexpr (ExColsGenCent::template contains()) { - registry.fill(HIST("Tracks/Centrality/EtaZvtxGen"), particle.eta(), - mcCollision.posZ(), c_gen); - float phi = particle.phi(); - o2::math_utils::bringTo02Pi(phi); - registry.fill(HIST("Tracks/Centrality/PhiEtaGen"), phi, - particle.eta(), c_gen); - } - } - } - } - - PROCESS_SWITCH(PseudorapidityDensityMFT, processGenCent, - "Process generator-level info in centrality bins", false); - - void processGenPt( - soa::Join::iterator const& collision, - MFTTracksLabeled const& tracks, aod::McParticles const&) - { - if (!useEvSel || (useEvSel && collision.sel8())) { - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - continue; - } - auto particle = track.mcParticle(); - if (!particle.isPhysicalPrimary()) { - continue; - } - registry.fill(HIST("TracksToPartPtEta"), particle.pt(), particle.eta()); - } - } - } - - PROCESS_SWITCH(PseudorapidityDensityMFT, processGenPt, - "Process particle-level info of pt", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx index d5bec464235..f86828f6cea 100644 --- a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx @@ -50,10 +50,12 @@ #include "TEfficiency.h" #include "THashList.h" -#include "TPDGCode.h" #include #include #include +#include +#include +#include #include #include @@ -69,9 +71,12 @@ using std::string; using namespace o2; using namespace o2::framework; using namespace o2::constants::math; +using namespace o2::aod::rctsel; auto static constexpr CminCharge = 3.f; +static constexpr float CnullInt = 0; static constexpr float Cnull = 0.0f; +static constexpr float ConeInt = 1; static constexpr float Cone = 1.0f; // FV0 specific constants @@ -82,6 +87,10 @@ static constexpr float Cfv0IndexPhi[5] = {0., 8., 16., 24., 32.}; static constexpr float CmaxEtaFV0 = 5.1; static constexpr float CminEtaFV0 = 2.2; static constexpr float CdEtaFV0 = (CmaxEtaFV0 - CminEtaFV0) / CmaxRingsFV0; +auto static constexpr CminAccFT0A = 3.5f; +auto static constexpr CmaxAccFT0A = 4.9f; +auto static constexpr CminAccFT0C = -3.3f; +auto static constexpr CmaxAccFT0C = -2.1f; // PID names static constexpr int CprocessIdWeak = 4; static constexpr int Ncharges = 2; @@ -91,29 +100,47 @@ static constexpr int PDGs[] = {11, 13, 211, 321, 2212}; static constexpr int PidSgn[NpartChrg] = {11, 13, 211, 321, 2212, -11, -13, -211, -321, -2212}; static constexpr const char* Pid[Npart] = {"el", "mu", "pi", "ka", "pr"}; static constexpr const char* PidChrg[NpartChrg] = {"e^{-}", "#mu^{-}", "#pi^{+}", "K^{+}", "p", "e^{+}", "#mu^{+}", "#pi^{-}", "K^{-}", "#bar{p}"}; -static constexpr std::string_view Cspecies[NpartChrg] = {"Elminus", "Muplus", "PiPlus", "KaPlus", "Pr", "ElPlus", "MuMinus", "PiMinus", "KaMinus", "PrBar"}; static constexpr std::string_view CspeciesAll[Npart] = {"El", "Mu", "Pi", "Ka", "Pr"}; // histogram naming +static constexpr std::string_view PidDir[] = {"el/", "pi/", "pr/"}; +static constexpr std::string_view V0Dir[] = {"Ga/", "K0s/", "La/", "ALa/"}; static constexpr std::string_view Ccharge[] = {"all/", "pos/", "neg/"}; static constexpr std::string_view Cprefix = "Tracks/"; static constexpr std::string_view CprefixCleanTof = "Tracks/CleanTof/"; static constexpr std::string_view CprefixCleanV0 = "Tracks/CleanV0/"; +static constexpr std::string_view CprefixV0qa = "Tracks/V0qa/"; static constexpr std::string_view Cstatus[] = {"preSel/", "postSel/"}; static constexpr std::string_view CstatCalib[] = {"preCalib/", "postCalib/"}; +static constexpr std::string_view CdEdxMcRecPrim = "/hdEdxMcRecPrim"; +static constexpr std::string_view CdEdxMcRecPrimF = "Tracks/{}/hdEdxMcRecPrim"; +static constexpr std::string_view CpTvsDCAxy = "/hPtVsDCAxy"; +static constexpr std::string_view CpTvsDCAxyF = "Tracks/{}/hPtVsDCAxy"; +static constexpr std::string_view CpTvsDCAxyAll = "/hPtVsDCAxyAll"; +static constexpr std::string_view CpTvsDCAxyAllF = "Tracks/{}/hPtVsDCAxyAll"; +static constexpr std::string_view CpTvsDCAxyPrimAll = "/hPtVsDCAxyRecPrimAll"; +static constexpr std::string_view CpTvsDCAxyPrimAllF = "Tracks/{}/hPtVsDCAxyRecPrimAll"; +static constexpr std::string_view CpTvsDCAxyWeakAll = "/hPtVsDCAxyRecWeakAll"; +static constexpr std::string_view CpTvsDCAxyWeakAllF = "Tracks/{}/hPtVsDCAxyRecWeakAll"; +static constexpr std::string_view CpTvsDCAxyMatAll = "/hPtVsDCAxyRecMatAll"; +static constexpr std::string_view CpTvsDCAxyMatAllF = "Tracks/{}/hPtVsDCAxyRecMatAll"; static constexpr std::string_view CpTgenPrimSgn = "/hPtGenPrimSgn"; static constexpr std::string_view CpTgenPrimSgnF = "Tracks/{}/hPtGenPrimSgn"; -static constexpr std::string_view CpTgenPrimSgnINEL = "/hPtGenPrimSgnINEL"; -static constexpr std::string_view CpTgenPrimSgnINELF = "Tracks/{}/hPtGenPrimSgnINEL"; static constexpr std::string_view CpTrecCollPrimSgn = "/hPtRecCollPrimSgn"; static constexpr std::string_view CpTrecCollPrimSgnF = "Tracks/{}/hPtRecCollPrimSgn"; -static constexpr std::string_view CpTrecCollPrimSgnINEL = "/hPtRecCollPrimSgnINEL"; -static constexpr std::string_view CpTrecCollPrimSgnINELF = "Tracks/{}/hPtRecCollPrimSgnINEL"; -static constexpr std::string_view CpTGenRecCollPrimSgn = "/hPtGenRecCollPrimSgn"; -static constexpr std::string_view CpTGenRecCollPrimSgnF = "Tracks/{}/hPtGenRecCollPrimSgn"; -static constexpr std::string_view CpTGenRecCollPrimSgnINEL = "/hPtGenRecCollPrimSgnINEL"; -static constexpr std::string_view CpTGenRecCollPrimSgnINELF = "Tracks/{}/hPtGenRecCollPrimSgnINEL"; -static constexpr std::string_view CpTmcClosurePrim = "/hPtMCclosurePrim"; -static constexpr std::string_view CpTmcClosurePrimF = "Tracks/{}/hPtMCclosurePrim"; +static constexpr std::string_view CpTmcClosureGenPrim = "/hPtMCclosureGenPrim"; +static constexpr std::string_view CpTmcClosureGenPrimF = "Tracks/{}/hPtMCclosureGenPrim"; +static constexpr std::string_view CpTmcClosureRec = "/hPtMCclosureRec"; +static constexpr std::string_view CpTmcClosureRecF = "Tracks/{}/hPtMCclosureRec"; +static constexpr std::string_view CpTeffPrimRecEvt = "/hPtEffPrimRecEvt"; +static constexpr std::string_view CpTeffPrimRecEvtF = "Tracks/{}/hPtEffPrimRecEvt"; +static constexpr std::string_view CpTeffGenPrimRecEvt = "/hPtEffGenPrimRecEvt"; +static constexpr std::string_view CpTeffGenPrimRecEvtF = "Tracks/{}/hPtEffGenPrimRecEvt"; + +enum PidType { + kEl = 0, + kPi, + kPr +}; enum V0sSel { kNaN = -1, @@ -148,16 +175,13 @@ enum TrkSel { enum V0Sel { v0SelAll, - v0SelEta, - v0SelDaughters, - v0SelTPCnClsFound, - v0SelTPCnClsPID, - v0SelRejectV0sAtTPCSector, v0SelRejectSameSign, - v0SelDCAv0daughter, + v0SelRejectV0sAtTPCSector, v0SelCosPA, v0SelV0radius, v0SelDCAposToPV, + v0SelDaughters, + v0SelDCAv0daughter, nV0Sel }; @@ -172,6 +196,7 @@ enum EvtSel { evtSelkIsVertexTOFmatched, evtSelVtxZ, evtSelINELgt0, + evtSelRCTFlagChecker, nEvtSel }; @@ -183,31 +208,29 @@ struct MultE { std::array rhoLatticeFV0{0}; std::array fv0AmplitudeWoCalib{0}; - -std::array, NpartChrg> hPtEffRecPrim{}; -std::array, NpartChrg> hPtEffRecWeak{}; -std::array, NpartChrg> hPtEffRecMat{}; +std::array, NpartChrg> hPtGenRecEvt{}; +std::array, NpartChrg> hPtGenPrimRecEvt{}; std::array, NpartChrg> hPtEffRec{}; std::array, NpartChrg> hPtEffGen{}; -std::array, NpartChrg> hPtGenRecEvt{}; -std::array, NpartChrg> hPtGenPrimRecEvt{}; -std::array, NpartChrg> hPtEffGenPrim{}; -std::array, NpartChrg> hPtEffGenWeak{}; -std::array, NpartChrg> hPtEffGenMat{}; -std::array, NpartChrg> hPtVsDCAxyPrim{}; -std::array, NpartChrg> hPtVsDCAxyWeak{}; -std::array, NpartChrg> hPtVsDCAxyMat{}; -std::array, NpartChrg> hDCAxyBadCollPrim{}; -std::array, NpartChrg> hDCAxyBadCollWeak{}; -std::array, NpartChrg> hDCAxyBadCollMat{}; -std::array, NpartChrg> hPtNsigmaTPC{}; -std::array, NpartChrg> hThPtNsigmaTPC{}; -std::array, NpartChrg> hPtNsigmaTOF{}; -std::array, NpartChrg> hPtNsigmaTPCTOF{}; +std::array, NpartChrg> hPtEffRecGoodCollPrim{}; +std::array, NpartChrg> hPtEffRecGoodCollWeak{}; +std::array, NpartChrg> hPtEffRecGoodCollMat{}; +std::array, NpartChrg> hPtEffGenPrim{}; +std::array, NpartChrg> hPtEffGenWeak{}; +std::array, NpartChrg> hPtEffGenMat{}; +std::array, NpartChrg> hDCAxyRecBadCollPrim{}; +std::array, NpartChrg> hDCAxyRecBadCollWeak{}; +std::array, NpartChrg> hDCAxyRecBadCollMat{}; +std::array, NpartChrg> hPtVsDCAxyRecGoodCollPrim{}; +std::array, NpartChrg> hPtVsDCAxyRecGoodCollWeak{}; +std::array, NpartChrg> hPtVsDCAxyRecGoodCollMat{}; struct FlattenictyPikp { - HistogramRegistry flatchrg{"flatchrg", {}, OutputObjHandlingPolicy::AnalysisObject, true, false}; + HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + OutputObj listEfficiency{"Efficiency"}; Service pdg; @@ -223,18 +246,26 @@ struct FlattenictyPikp { Configurable applyCalibDeDx{"applyCalibDeDx", false, "calibration of dedx signal"}; Configurable applyCalibDeDxFromCCDB{"applyCalibDeDxFromCCDB", false, "use CCDB-based calibration of dedx signal"}; Configurable cfgFillTrackQaHist{"cfgFillTrackQaHist", false, "fill track QA histograms"}; + Configurable cfgFillNclVsPhiCutQaHist{"cfgFillNclVsPhiCutQaHist", false, "fill TPC cluster vs geometrical cut QA histograms"}; Configurable cfgFilldEdxCalibHist{"cfgFilldEdxCalibHist", false, "fill dEdx calibration histograms"}; Configurable cfgFilldEdxQaHist{"cfgFilldEdxQaHist", false, "fill dEdx QA histograms"}; - Configurable cfgFillNsigmaQAHist{"cfgFillNsigmaQAHist", false, "fill nsigma QA histograms"}; + Configurable cfgFillDCAxyHist{"cfgFillDCAxyHist", false, "fill nsigma QA histograms"}; Configurable cfgFillV0Hist{"cfgFillV0Hist", false, "fill V0 histograms"}; Configurable cfgFillChrgType{"cfgFillChrgType", false, "fill histograms per charge types"}; Configurable cfgFillChrgTypeV0s{"cfgFillChrgTypeV0s", false, "fill V0s histograms per charge types"}; - Configurable> paramsFuncMIPpos{"paramsFuncMIPpos", std::vector{-1.f}, "parameters of pol2"}; - Configurable> paramsFuncMIPneg{"paramsFuncMIPneg", std::vector{-1.f}, "parameters of pol2"}; - Configurable> paramsFuncMIPall{"paramsFuncMIPall", std::vector{-1.f}, "parameters of pol2"}; - Configurable> paramsFuncPlateaUpos{"paramsFuncPlateaUpos", std::vector{-1.f}, "parameters of pol2"}; - Configurable> paramsFuncPlateaUneg{"paramsFuncPlateaUneg", std::vector{-1.f}, "parameters of pol2"}; - Configurable> paramsFuncPlateaUall{"paramsFuncPlateaUall", std::vector{-1.f}, "parameters of pol2"}; + Configurable cfgCalibDeDxFunction{"cfgCalibDeDxFunction", "pol8", "Functional form for dEdx calibration"}; + Configurable> paramsFuncMIPposEtaP{"paramsFuncMIPposEtaP", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncMIPnegEtaP{"paramsFuncMIPnegEtaP", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncMIPallEtaP{"paramsFuncMIPallEtaP", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncMIPposEtaN{"paramsFuncMIPposEtaN", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncMIPnegEtaN{"paramsFuncMIPnegEtaN", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncMIPallEtaN{"paramsFuncMIPallEtaN", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncPlateaUposEtaP{"paramsFuncPlateaUposEtaP", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncPlateaUnegEtaP{"paramsFuncPlateaUnegEtaP", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncPlateaUallEtaP{"paramsFuncPlateaUallEtaP", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncPlateaUposEtaN{"paramsFuncPlateaUposEtaN", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncPlateaUnegEtaN{"paramsFuncPlateaUnegEtaN", std::vector{-1.f}, "function parameters"}; + Configurable> paramsFuncPlateaUallEtaN{"paramsFuncPlateaUallEtaN", std::vector{-1.f}, "function parameters"}; Configurable cfgGainEqCcdbPath{"cfgGainEqCcdbPath", "Users/g/gbencedi/flattenicity/GainEq", "CCDB path for gain equalization constants"}; Configurable cfgVtxEqCcdbPath{"cfgVtxEqCcdbPath", "Users/g/gbencedi/flattenicity/ZvtxEq", "CCDB path for z-vertex equalization constants"}; Configurable cfgDeDxCalibCcdbPath{"cfgDeDxCalibCcdbPath", "Users/g/gbencedi/flattenicity/dEdxCalib", "CCDB path for dEdx calibration"}; @@ -243,29 +274,26 @@ struct FlattenictyPikp { struct : ConfigurableGroup { Configurable cfgCustomTVX{"cfgCustomTVX", false, "Ask for custom TVX instead of sel8"}; - Configurable cfgRemoveNoTimeFrameBorder{"cfgRemoveNoTimeFrameBorder", true, "Bunch crossing is far from Time Frame borders"}; - Configurable cfgRemoveITSROFrameBorder{"cfgRemoveITSROFrameBorder", true, "Bunch crossing is far from ITS RO Frame border"}; + Configurable cfgRemoveNoTimeFrameBorder{"cfgRemoveNoTimeFrameBorder", false, "Bunch crossing is far from Time Frame borders"}; + Configurable cfgRemoveITSROFrameBorder{"cfgRemoveITSROFrameBorder", false, "Bunch crossing is far from ITS RO Frame border"}; Configurable cfgCutVtxZ{"cfgCutVtxZ", 10.0f, "Accepted z-vertex range"}; - Configurable cfgINELCut{"cfgINELCut", true, "INEL event selection"}; - Configurable cfgRemoveNoSameBunchPileup{"cfgRemoveNoSameBunchPileup", false, "Reject collisions in case of pileup with another collision in the same foundBC"}; - Configurable cfgRequireIsGoodZvtxFT0vsPV{"cfgRequireIsGoodZvtxFT0vsPV", false, "Small difference between z-vertex from PV and from FT0"}; + Configurable cfgRemoveNoSameBunchPileup{"cfgRemoveNoSameBunchPileup", true, "Reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable cfgRequireIsGoodZvtxFT0vsPV{"cfgRequireIsGoodZvtxFT0vsPV", true, "Small difference between z-vertex from PV and from FT0"}; Configurable cfgRequireIsVertexITSTPC{"cfgRequireIsVertexITSTPC", false, "At least one ITS-TPC track (reject vertices built from ITS-only tracks)"}; Configurable cfgRequirekIsVertexTOFmatched{"cfgRequirekIsVertexTOFmatched", false, "Require kIsVertexTOFmatched: at least one of vertex contributors is matched to TOF"}; + Configurable useMultMCmidrap{"useMultMCmidrap", true, "use generated Nch in ∣eta∣ < 0.8"}; + Configurable cfgUseInelgt0wTVX{"cfgUseInelgt0wTVX", true, "Use INEL > 0 condition with TVX trigger, i.e. FT0A and FT0C acceptance"}; } evtSelOpt; struct : ConfigurableGroup { - Configurable useFlatData{"useFlatData", true, "use flattenicity from rec collisions"}; - } flatSelOpt; - - struct : ConfigurableGroup { - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 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, 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.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, "pT binning"}; - ConfigurableAxis axisPtV0s{"axisPtV0s", {VARIABLE_WIDTH, 0, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.5, 3.0, 3.5, 4, 5, 7, 9, 12, 15, 20}, "pT V0s binning"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 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, 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.2, 3.4, 3.6, 3.8, 4, 4.4, 4.8, 5.2, 5.6, 6, 6.5, 7, 7.5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, "pT binning"}; + ConfigurableAxis axisPtV0s{"axisPtV0s", {VARIABLE_WIDTH, 0, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.2, 3.4, 3.6, 3.8, 4, 4.4, 4.8, 5.2, 5.6, 6, 6.4, 6.8, 7.2, 7.6, 8, 8.4, 8.8, 9.2, 9.6, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 20}, "pT V0s binning"}; ConfigurableAxis axisFlatPerc{"axisFlatPerc", {102, -0.01, 1.01}, "Flattenicity percentiles binning"}; - ConfigurableAxis axisMultPerc{"axisMultPerc", {20, 0, 100}, "Multiplicity percentiles binning"}; + ConfigurableAxis axisMultPerc{"axisMultPerc", {VARIABLE_WIDTH, 0., 5., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.}, "T0 percentiles binning"}; ConfigurableAxis axisVertexZ{"axisVertexZ", {80, -20., 20.}, "Vertex z binning"}; ConfigurableAxis axisMult{"axisMult", {301, -0.5, 300.5}, "Multiplicity binning"}; - ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -5, 5}, "DCAxy binning"}; - ConfigurableAxis axisDCAz{"axisDCAz", {200, -5, 5}, "DCAz binning"}; + ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -5., 5.}, "DCAxy binning"}; + ConfigurableAxis axisDCAz{"axisDCAz", {200, -5., 5.}, "DCAz binning"}; ConfigurableAxis axisPhi = {"axisPhi", {60, 0, constants::math::TwoPI}, "#varphi binning"}; ConfigurableAxis axisPhiMod = {"axisPhiMod", {100, 0, constants::math::PI / 9}, "fmod(#varphi,#pi/9)"}; ConfigurableAxis axisEta = {"axisEta", {50, -1.0, 1.0}, "#eta binning"}; @@ -281,10 +309,11 @@ struct FlattenictyPikp { struct : ConfigurableGroup { Configurable cfgTrkEtaMax{"cfgTrkEtaMax", 0.8f, "Eta range for tracks"}; Configurable cfgRapMax{"cfgRapMax", 0.5f, "Maximum range of rapidity for tracks"}; - Configurable cfgTrkPtMin{"cfgTrkPtMin", 0.15f, "Minimum pT of tracks"}; - Configurable cfgNclTPCMin{"cfgNclTPCMin", 80.0f, "Minimum of number of TPC found clusters"}; + Configurable cfgTrkPtMin{"cfgTrkPtMin", 0.1f, "Minimum pT of tracks"}; + Configurable cfgApplyNcl{"cfgApplyNcl", false, "Apply cut on TPC clusters"}; + Configurable cfgNclTPCMin{"cfgNclTPCMin", 135.0f, "Minimum of number of TPC found clusters"}; Configurable cfgApplyNclPID{"cfgApplyNclPID", true, "Apply cut on TPC PID clusters"}; - Configurable cfgNclPidTPCMin{"cfgNclPidTPCMin", 130.0f, "Minimum of number of TPC PID clusters"}; + Configurable cfgNclPidTPCMin{"cfgNclPidTPCMin", 135.0f, "Minimum of number of TPC PID clusters"}; Configurable cfgPhiCutPtMin{"cfgPhiCutPtMin", 2.0f, "Minimum pT for phi cut"}; Configurable cfgTOFBetaPion{"cfgTOFBetaPion", 1.0f, "Minimum beta for TOF pions"}; Configurable cfgTofBetaPiMax{"cfgTofBetaPiMax", 5E-5, "Maximum beta for TOF pion selection"}; @@ -296,6 +325,7 @@ struct FlattenictyPikp { Configurable cfgDeDxMIPMax{"cfgDeDxMIPMax", 60.0f, "Maximum range of MIP dedx"}; Configurable cfgDeDxMIPMin{"cfgDeDxMIPMin", 40.0f, "Maximum range of MIP dedx"}; Configurable cfgNsigmaMax{"cfgNsigmaMax", 100.0f, "Maximum range of nsgima for tracks"}; + Configurable cfgDcaNsigmaCombinedMax{"cfgDcaNsigmaCombinedMax", 3.0f, "Maximum range of combined nsgima of tracks for DCA"}; Configurable cfgMomSelPiTOF{"cfgMomSelPiTOF", 0.4f, "Minimum momentum cut for TOF pions"}; Configurable cfgNsigSelKaTOF{"cfgNsigSelKaTOF", 3.0f, "Nsigma cut for TOF kaons"}; Configurable cfgBetaPlateuMax{"cfgBetaPlateuMax", 0.1f, "Beta max for Plateau electrons"}; @@ -306,6 +336,7 @@ struct FlattenictyPikp { Configurable cfgV0TypeSel{"cfgV0TypeSel", 1, "select on a certain V0 type (leave negative if no selection desired)"}; Configurable cfgV0Ymax{"cfgV0Ymax", 0.5f, "Maximum rapidity of V0s"}; Configurable cfgRejectV0sAtTPCSector{"cfgRejectV0sAtTPCSector", true, "Reject V0s close to the TPC sector boundaries"}; + Configurable cfgRequireITS{"cfgRequireITS", true, "Additional cut on the ITS requirement"}; Configurable cfgNsigmaElTPC{"cfgNsigmaElTPC", 5.0, "max nsigma of TPC for electorn"}; Configurable cfgNsigmaPiTPC{"cfgNsigmaPiTPC", 5.0, "max nsigma of TPC for pion"}; Configurable cfgNsigmaPrTPC{"cfgNsigmaPrTPC", 5.0, "max nsigma of TPC for proton"}; @@ -315,10 +346,17 @@ struct FlattenictyPikp { ConfigurableAxis axisArmPodAlpha{"axisArmPodAlpha", {200, -1.0, 1.0}, "Armenteros-Podolanski alpha"}; ConfigurableAxis axisArmPodqT{"axisArmPodqT", {600, 0.0f, 0.3f}, "Armenteros-Podolanski qT"}; // standad parameters for V0 selection - Configurable cfgV0etamax{"cfgV0etamax", 0.8f, "max eta of V0s"}; - Configurable cfgTPCnClsmin{"cfgTPCnClsmin", 80.0f, "Minimum of number of TPC found clusters"}; + Configurable cfgV0etamin{"cfgV0etamin", -0.8f, "min eta of V0s"}; + Configurable cfgV0etamax{"cfgV0etamax", +0.8f, "max eta of V0s"}; + Configurable cfgminNCrossedRowsTPC{"cfgminNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable cfgApplyV0sNclFound{"cfgApplyV0sNclFound", false, "Apply cut on TPC Found clusters"}; + Configurable cfgV0NclTPCMin{"cfgV0NclTPCMin", 135.0f, "Minimum of number of TPC found clusters"}; Configurable cfgApplyV0sNclPID{"cfgApplyV0sNclPID", true, "Apply cut on TPC PID clusters"}; - Configurable cfgTPCnClsPidmin{"cfgTPCnClsPidmin", 130.0f, "Minimum of number of TPC PID clusters"}; + Configurable cfgV0NclPidTPCMin{"cfgV0NclPidTPCMin", 135.0f, "Minimum of number of TPC PID clusters"}; + Configurable cfgmaxChi2PerClusterTPC{"cfgmaxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable cfgmaxChi2PerClusterITS{"cfgmaxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + Configurable cfgminITSnClusters{"cfgminITSnClusters", 4, "minimum number of found ITS clusters"}; + Configurable cfgminNCrossedRowsOverFindableClustersTPC{"cfgminNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; Configurable cfgDCAv0daughter{"cfgDCAv0daughter", 1.0, "max DCA of V0 daughter tracks (cm)"}; Configurable cfgv0cospa{"cfgv0cospa", 0.995, "min V0 CosPA"}; Configurable cfgDCAposToPV{"cfgDCAposToPV", 0.05f, "min DCA Pos To PV (cm)"}; @@ -329,7 +367,7 @@ struct FlattenictyPikp { Configurable cfgcTauK0s{"cfgcTauK0s", 20, "v0ctau for K0s"}; Configurable cfgCosPAK0s{"cfgCosPAK0s", 0.995, "V0 CosPA for K0s"}; Configurable cfgV0radiusK0s{"cfgV0radiusK0s", 0.5, "v0radius for K0s"}; - Configurable cfgdmassK{"cfgdmassK", 0.005, "Competing Mass Rejection cut for K0s"}; + Configurable cfgdmassK{"cfgdmassK", 0.01f, "Competing Mass Rejection cut for K0s"}; Configurable cfgArmPodK0s{"cfgArmPodK0s", 5.0f, "pT * (cut) > |alpha|, Armenteros-Podolanski cut for K0s"}; ConfigurableAxis axisK0sMass{"axisK0sMass", {200, 0.4f, 0.6f}, "K0Short mass binning"}; // parameters for selection Lambda / antiLambda @@ -343,7 +381,7 @@ struct FlattenictyPikp { Configurable cfgArmPodGammasalpha{"cfgArmPodGammasalpha", 0.45f, "Armenteros-Podolanski alpha cut for Gammas"}; Configurable cfgArmPodGammasqT{"cfgArmPodGammasqT", 0.01f, "Armenteros-Podolanski qT cut for Gammas"}; ConfigurableAxis axisGammaMass{"axisGammaMass", {200, 0.0f, 0.5f}, "Gamma mass binning"}; - Configurable cfgdEdxPlateauSel{"cfgdEdxPlateauSel", 5, "dEdx selection sensitivity for electrons"}; + Configurable cfgdEdxPlateauSel{"cfgdEdxPlateauSel", 50, "dEdx selection sensitivity for electrons"}; } v0SelOpt; Service ccdb; @@ -365,11 +403,23 @@ struct FlattenictyPikp { bool lCalibLoaded = false; } dedxcalib; + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + } rctCuts; + + RCTFlagsChecker rctChecker; + TrackSelection selTrkGlobal; Configurable isCustomTracks{"isCustomTracks", true, "Use custom track cuts"}; - Configurable requirePt{"requirePt", 0.15f, "Set minimum pT of tracks"}; + Configurable minPt{"minPt", 0.1f, "Set minimum pT of tracks"}; + Configurable maxPt{"maxPt", 1e10f, "Set maximum pT of tracks"}; Configurable requireEta{"requireEta", 0.8f, "Set eta range of tracks"}; - Configurable setITSreq{"setITSreq", 2, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable setITSreq{"setITSreq", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable requireITSminCl{"requireITSminCl", false, "Require additional cut on ITS clusters"}; + Configurable setITSminCl{"setITSminCl", 7, "Additional cut on ITS clusters"}; Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; @@ -380,18 +430,6 @@ struct FlattenictyPikp { Configurable minITSnClusters{"minITSnClusters", 5, "minimum number of found ITS clusters"}; Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Multiplicative factor on the maximum value of the DCA xy"}; Configurable maxDcaZ{"maxDcaZ", 2.f, "Additional cut on the maximum value of the DCA z"}; - Configurable minTPCNClsFound{"minTPCNClsFound", 70.0f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; - - TrackSelection selTrkV0sDaughters; - TrackSelection selV0sDaugthers() - { - TrackSelection selTracks; - selTracks.SetEtaRange(-0.8f, 0.8f); - selTracks.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); - selTracks.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); - selTracks.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); - return selTracks; - } TF1* fPhiCutLow = nullptr; TF1* fPhiCutHigh = nullptr; @@ -401,27 +439,50 @@ struct FlattenictyPikp { std::vector> fEDeDxVsEta; std::vector> vecParamsPLA; + using MyCollisions = soa::Join; + using Colls = soa::Join; + using CollsGen = soa::Join; + using MCColls = soa::Join; + using CollsGenSgn = soa::SmallGroups>; + using MyPIDTracks = soa::Join; + using MyLabeledTracks = soa::Join; + using MyFiltLabeledTracks = soa::Filtered; + using MyLabeledPIDTracks = soa::Join; + void init(InitContext&) { - auto vecParamsMIPpos = (std::vector)paramsFuncMIPpos; - auto vecParamsMIPneg = (std::vector)paramsFuncMIPneg; - auto vecParamsMIPall = (std::vector)paramsFuncMIPall; - auto vecParamsPLApos = (std::vector)paramsFuncPlateaUpos; - auto vecParamsPLAneg = (std::vector)paramsFuncPlateaUneg; - auto vecParamsPLAall = (std::vector)paramsFuncPlateaUall; + auto vecParamsMIPposEtaP = (std::vector)paramsFuncMIPposEtaP; + auto vecParamsMIPposEtaN = (std::vector)paramsFuncMIPposEtaN; + auto vecParamsMIPnegEtaP = (std::vector)paramsFuncMIPnegEtaP; + auto vecParamsMIPnegEtaN = (std::vector)paramsFuncMIPnegEtaN; + auto vecParamsMIPallEtaP = (std::vector)paramsFuncMIPallEtaP; + auto vecParamsMIPallEtaN = (std::vector)paramsFuncMIPallEtaN; + + auto vecParamsPLAposEtaP = (std::vector)paramsFuncPlateaUposEtaP; + auto vecParamsPLAposEtaN = (std::vector)paramsFuncPlateaUposEtaN; + auto vecParamsPLAnegEtaP = (std::vector)paramsFuncPlateaUnegEtaP; + auto vecParamsPLAnegEtaN = (std::vector)paramsFuncPlateaUnegEtaN; + auto vecParamsPLAallEtaP = (std::vector)paramsFuncPlateaUallEtaP; + auto vecParamsPLAallEtaN = (std::vector)paramsFuncPlateaUallEtaN; auto addVec = [&](std::vector>& targetVec, const std::string& name, bool isMIP) { if (isMIP) { - targetVec.emplace_back(vecParamsMIPpos); - targetVec.emplace_back(vecParamsMIPneg); - targetVec.emplace_back(vecParamsMIPall); + targetVec.emplace_back(vecParamsMIPposEtaP); + targetVec.emplace_back(vecParamsMIPnegEtaP); + targetVec.emplace_back(vecParamsMIPallEtaP); + targetVec.emplace_back(vecParamsMIPposEtaN); + targetVec.emplace_back(vecParamsMIPnegEtaN); + targetVec.emplace_back(vecParamsMIPallEtaN); if (!vecParamsMIP.size()) { LOG(info) << "size of " << name << "is zero."; } } else { - targetVec.emplace_back(vecParamsPLApos); - targetVec.emplace_back(vecParamsPLAneg); - targetVec.emplace_back(vecParamsPLAall); + targetVec.emplace_back(vecParamsPLAposEtaP); + targetVec.emplace_back(vecParamsPLAnegEtaP); + targetVec.emplace_back(vecParamsPLAallEtaP); + targetVec.emplace_back(vecParamsPLAposEtaN); + targetVec.emplace_back(vecParamsPLAnegEtaN); + targetVec.emplace_back(vecParamsPLAallEtaN); if (!vecParamsPLA.size()) { LOG(info) << "size of " << name << "is zero."; } @@ -442,11 +503,11 @@ struct FlattenictyPikp { ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); ccdb->setFatalWhenNull(false); - selTrkV0sDaughters = selV0sDaugthers(); + rctChecker.init(rctCuts.cfgEvtRCTFlagCheckerLabel, rctCuts.cfgEvtRCTFlagCheckerZDCCheck, rctCuts.cfgEvtRCTFlagCheckerLimitAcceptAsBad); if (isCustomTracks.value) { selTrkGlobal = getGlobalTrackSelectionRun3ITSMatch(setITSreq.value); - selTrkGlobal.SetPtRange(requirePt.value, 1e10f); + selTrkGlobal.SetPtRange(minPt.value, maxPt.value); selTrkGlobal.SetEtaRange(-requireEta.value, requireEta.value); selTrkGlobal.SetRequireITSRefit(requireITS.value); selTrkGlobal.SetRequireTPCRefit(requireTPC.value); @@ -454,8 +515,10 @@ struct FlattenictyPikp { selTrkGlobal.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); selTrkGlobal.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); selTrkGlobal.SetMinNClustersITS(minITSnClusters.value); + if (requireITSminCl.value) { + selTrkGlobal.SetRequireHitsInITSLayers(setITSminCl.value, {0, 1, 2, 3, 4, 5, 6}); + } selTrkGlobal.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); - selTrkGlobal.SetMinNClustersTPC(minTPCNClsFound.value); selTrkGlobal.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); // // selTrkGlobal.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); selTrkGlobal.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); @@ -467,6 +530,7 @@ struct FlattenictyPikp { const AxisSpec dEdxAxis{binOpt.axisDedx, "TPC dEdx (a.u.)"}; const AxisSpec vtxzAxis{binOpt.axisVertexZ, "Z_{vtx} (cm)"}; const AxisSpec flatAxis{binOpt.axisFlatPerc, "Flat FV0"}; + const AxisSpec nChAxis{binOpt.axisMult, "Nch, |eta|<0.8"}; const AxisSpec etaAxis{binOpt.axisEta, "#eta"}; const AxisSpec rapidityAxis{binOpt.axisRapidity, "#it{y}"}; const AxisSpec phiAxis{binOpt.axisPhi, "#varphi"}; @@ -499,227 +563,254 @@ struct FlattenictyPikp { LOG(fatal) << "No valid option for mult estimator " << multEst; } - // Event counter - flatchrg.add("Events/hEvtSel", "Number of events; Cut; #Events Passed Cut", {kTH1F, {{nEvtSel + 1, 0, nEvtSel + 1}}}); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelAll + 1, "Events read"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelSel8 + 1, "Evt. sel8"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelNoITSROFrameBorder + 1, "NoITSROFrameBorder"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkNoTimeFrameBorder + 1, "NoTimeFrameBorder"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkNoSameBunchPileup + 1, "NoSameBunchPileup"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsGoodZvtxFT0vsPV + 1, "IsGoodZvtxFT0vsPV"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsVertexITSTPC + 1, "IsVertexITSTPC"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsVertexTOFmatched + 1, "IsVertexTOFmatched"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelVtxZ + 1, "Vtx-z pos"); - flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelINELgt0 + 1, "INEL>0"); - // Track counter - flatchrg.add("Tracks/hTrkSel", "Number of tracks; Cut; #Tracks Passed Cut", {kTH1F, {{nTrkSel + 1, 0, nTrkSel + 1}}}); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelAll + 1, "All"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelEta + 1, "Eta"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelPt + 1, "Pt"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelDCA + 1, "DCA"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkNRowsTPC + 1, "trkNRowsTPC"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelNClsFound + 1, "NClsTPCFound"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelNClsPID + 1, "NClsTPCPid"); - flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelTPCBndr + 1, "TPC Boundary"); - // V0 counter - flatchrg.add("Tracks/V0qa/hV0Sel", "Number of V0s; Cut; #Tracks Passed Cut", {kTH1F, {{nV0Sel + 1, 0, nV0Sel + 1}}}); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelAll + 1, "All"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelEta + 1, "Eta"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelDaughters + 1, "V0 daughters' sel."); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelTPCnClsFound + 1, "TPC nCls found"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelTPCnClsPID + 1, "TPC nCls PID"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelRejectV0sAtTPCSector + 1, "Reject V0s at TPC sector"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelRejectSameSign + 1, "Reject same sign"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelDCAv0daughter + 1, "DCA v0 daughter"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelCosPA + 1, "Cos PA"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelV0radius + 1, "V0 radius"); - flatchrg.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelDCAposToPV + 1, "DCA pos to PV"); - if (trkSelOpt.cfgRejectTrkAtTPCSector || v0SelOpt.cfgRejectV0sAtTPCSector) { fPhiCutLow = new TF1("fPhiCutLow", trkSelOpt.cfgGeoTrkCutMin.value.c_str(), 0, 100); fPhiCutHigh = new TF1("fPhiCutHigh", trkSelOpt.cfgGeoTrkCutMax.value.c_str(), 0, 100); } + registryQC.add("Events/hVtxZ", "Measured vertex z position", kTH1F, {vtxzAxis}); + + // Event counter + registryQC.add("Events/hEvtSel", "Number of events; Cut; #Events Passed Cut", {kTH1F, {{nEvtSel, 0, nEvtSel}}}); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelAll + 1, "Events read"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelSel8 + 1, "Evt. sel8"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelNoITSROFrameBorder + 1, "NoITSROFrameBorder"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkNoTimeFrameBorder + 1, "NoTimeFrameBorder"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkNoSameBunchPileup + 1, "NoSameBunchPileup"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsGoodZvtxFT0vsPV + 1, "IsGoodZvtxFT0vsPV"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsVertexITSTPC + 1, "IsVertexITSTPC"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsVertexTOFmatched + 1, "IsVertexTOFmatched"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelVtxZ + 1, "Vtx-z pos"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelINELgt0 + 1, "INEL>0"); + registryQC.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelRCTFlagChecker + 1, "RCT Flag Checker"); + // FV0 QA + registryQC.add("FV0/hFV0AmplWCalib", "", {kTH2F, {channelFV0Axis, amplitudeFV0}}); + registryQC.add("FV0/hFV0AmplvsVtxzWoCalib", "", {kTH2F, {vtxzAxis, amplitudeFV0Sum}}); + registryQC.add("FV0/hFV0AmplvsVtxzCalib", "", {kTH2F, {vtxzAxis, amplitudeFV0Sum}}); + registryQC.add("FV0/hFV0amp", "", {kTH2F, {channelFV0Axis, amplitudeFV0}}); + registryQC.add("FV0/pFV0amp", "", kTProfile, {channelFV0Axis}); + registryQC.add("FV0/hFV0ampCorr", "", {kTH2F, {channelFV0Axis, amplitudeFV0}}); + + LOG(info) << "Size of the QC histograms:"; + registryQC.print(); + if (doprocessFlat) { - flatchrg.add("Events/hVtxZ", "Measured vertex z position", kTH1F, {vtxzAxis}); - flatchrg.add("Events/hFlatVsMultEst", "hFlatVsMultEst", kTH2F, {flatAxis, multAxis}); - flatchrg.add("Tracks/postSel/hPVsPtEta", "; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c}); #eta;", {kTH3F, {pAxis, ptAxis, etaAxis}}); - if (cfgFillTrackQaHist || cfgFilldEdxQaHist || cfgFillNsigmaQAHist) { + // Track counter + registryData.add("Tracks/hTrkSel", "Number of tracks; Cut; #Tracks Passed Cut", {kTH1F, {{nTrkSel, 0, nTrkSel}}}); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelAll + 1, "All"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelEta + 1, "Eta"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelPt + 1, "Pt"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelDCA + 1, "DCA"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkNRowsTPC + 1, "trkNRowsTPC"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelNClsFound + 1, "NClsTPCFound"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelNClsPID + 1, "NClsTPCPid"); + registryData.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelTPCBndr + 1, "TPC Boundary"); + // V0 counter + registryData.add("Tracks/V0qa/hV0Sel", "Number of V0s; Cut; #Tracks Passed Cut", {kTH1F, {{nV0Sel, 0, nV0Sel}}}); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelAll + 1, "All"); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelRejectSameSign + 1, "Reject same sign"); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelRejectV0sAtTPCSector + 1, "Reject V0s at TPC sector"); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelCosPA + 1, "Cos PA"); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelV0radius + 1, "V0 radius"); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelDCAposToPV + 1, "DCA pos to PV"); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelDaughters + 1, "V0 daughters' sel."); + registryData.get(HIST("Tracks/V0qa/hV0Sel"))->GetXaxis()->SetBinLabel(v0SelDCAv0daughter + 1, "DCA v0 daughter"); + + registryData.add("Events/hFlatVsMultEst", "hFlatVsMultEst", kTH2F, {flatAxis, multAxis}); + registryData.add("Tracks/postSel/hPVsPtEta", "; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c}); #eta;", {kTH3F, {pAxis, ptAxis, etaAxis}}); + if (cfgFillNclVsPhiCutQaHist || cfgFillTrackQaHist || cfgFilldEdxQaHist || cfgFillDCAxyHist) { + if (cfgFillNclVsPhiCutQaHist) { + registryData.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {kTH2F, {ptAxis, phiAxisMod}}); + registryData.add("Tracks/postSel/hPtPhiNclTPC", "; #{eta}; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{cluster}", {kTHnSparseF, {etaAxis, ptAxis, phiAxisMod, clTpcAxis}}); + registryData.add("Tracks/postSel/hPtPhiNclPIDTPC", "; #{eta}; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{PID cluster}", {kTHnSparseF, {etaAxis, ptAxis, phiAxisMod, clTpcAxis}}); + registryData.add("Tracks/postSel/hPtNclTPC", "; #it{p}_{T} (GeV/#it{c}); N_{cluster}", {kTH2F, {ptAxis, clTpcAxis}}); + registryData.add("Tracks/postSel/pPtNclTPC", "; #it{p}_{T} (GeV/#it{c}); N_{cluster}", {kTProfile, {ptAxis}}); + registryData.add("Tracks/postSel/hPtNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); N_{PID cluster}", {kTH2F, {ptAxis, clTpcAxis}}); + registryData.add("Tracks/postSel/pPtNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); N_{PID cluster}", {kTProfile, {ptAxis}}); + } if (cfgFillTrackQaHist) { - flatchrg.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {kTH2F, {ptAxis, phiAxisMod}}); - flatchrg.add("Tracks/postSel/hPtVsWOcutDCA", "hPtVsWOcutDCA", kTH2F, {ptAxis, dcaXYAxis}); - flatchrg.add("Tracks/postSel/hPt", "", kTH1F, {ptAxis}); - flatchrg.add("Tracks/postSel/hPhi", "", kTH1F, {phiAxis}); - flatchrg.add("Tracks/postSel/hEta", "", kTH1F, {etaAxis}); - flatchrg.add("Tracks/postSel/hDCAXYvsPt", "", kTH2F, {ptAxis, dcaXYAxis}); - flatchrg.add("Tracks/postSel/hDCAZvsPt", "", kTH2F, {ptAxis, dcaZAxis}); + registryData.add("Tracks/postSel/hShTpcClvsPt", "", {kTH2F, {ptAxis, shCluserAxis}}); + registryData.add("Tracks/postSel/hNclTPCFoundvsPt", "", {kTH2F, {ptAxis, clTpcAxis}}); + registryData.add("Tracks/postSel/hNClTPCPidvsPt", "", {kTH2F, {ptAxis, clTpcAxis}}); + registryData.add("Tracks/postSel/hNclTPCFoundvsEta", "", {kTH2F, {etaAxis, clTpcAxis}}); + registryData.add("Tracks/postSel/hNClTPCPidvsEta", "", {kTH2F, {etaAxis, clTpcAxis}}); + registryData.add("Tracks/postSel/hTPCCluster", "N_{cluster}", kTH1F, {clTpcAxis}); + registryData.add("Tracks/postSel/hPtVsWOcutDCA", "hPtVsWOcutDCA", kTH2F, {ptAxis, dcaXYAxis}); + registryData.add("Tracks/postSel/hPt", "", kTH1F, {ptAxis}); + registryData.add("Tracks/postSel/hPhi", "", kTH1F, {phiAxis}); + registryData.add("Tracks/postSel/hEta", "", kTH1F, {etaAxis}); + registryData.add("Tracks/postSel/hDCAXYvsPt", "", kTH2F, {ptAxis, dcaXYAxis}); + registryData.add("Tracks/postSel/hDCAZvsPt", "", kTH2F, {ptAxis, dcaZAxis}); // tpc - if (cfgStoreThnSparse) { - flatchrg.add("Tracks/postSel/hPtPhiNclTPC", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{cluster}", {kTHnSparseF, {ptAxis, phiAxisMod, clTpcAxis}}); - flatchrg.add("Tracks/postSel/hPtPhiNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{PID cluster}", {kTHnSparseF, {ptAxis, phiAxisMod, clTpcAxis}}); - } else { - flatchrg.add("Tracks/postSel/hPtPhiNclTPC", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{cluster}", {kTH3F, {ptAxis, phiAxisMod, clTpcAxis}}); - flatchrg.add("Tracks/postSel/hPtPhiNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{PID cluster}", {kTH3F, {ptAxis, phiAxisMod, clTpcAxis}}); - } - flatchrg.add("Tracks/postSel/hPtNclTPC", "; #it{p}_{T} (GeV/#it{c}); N_{cluster}", {kTH2F, {ptAxis, clTpcAxis}}); - flatchrg.add("Tracks/postSel/pPtNclTPC", "; #it{p}_{T} (GeV/#it{c}); N_{cluster}", {kTProfile, {ptAxis}}); - flatchrg.add("Tracks/postSel/hPtNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); N_{PID cluster}", {kTH2F, {ptAxis, clTpcAxis}}); - flatchrg.add("Tracks/postSel/pPtNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); N_{PID cluster}", {kTProfile, {ptAxis}}); - flatchrg.add("Tracks/postSel/hShTpcClvsPt", "", {kTH2F, {ptAxis, shCluserAxis}}); - flatchrg.add("Tracks/postSel/hNclTPCFoundvsPt", "", {kTH2F, {ptAxis, clTpcAxis}}); - flatchrg.add("Tracks/postSel/hNClTPCPidvsPt", "", {kTH2F, {ptAxis, clTpcAxis}}); - flatchrg.add("Tracks/postSel/hTPCCluster", "N_{cluster}", kTH1F, {clTpcAxis}); - flatchrg.add("Tracks/postSel/hTPCnClsShared", " ; # shared TPC clusters TPC", kTH1F, {{165, -0.5, 164.5}}); - flatchrg.add("Tracks/postSel/hTPCcrossedRows", " ; # crossed TPC rows", kTH1F, {{165, -0.5, 164.5}}); - flatchrg.add("Tracks/postSel/hTPCcrossedRowsOverFindableCls", " ; crossed rows / findable TPC clusters", kTH1F, {{60, 0.7, 1.3}}); + registryData.add("Tracks/postSel/hTPCnClsShared", " ; # shared TPC clusters TPC", kTH1F, {{165, -0.5, 164.5}}); + registryData.add("Tracks/postSel/hTPCcrossedRows", " ; # crossed TPC rows", kTH1F, {{165, -0.5, 164.5}}); + registryData.add("Tracks/postSel/hTPCcrossedRowsOverFindableCls", " ; crossed rows / findable TPC clusters", kTH1F, {{60, 0.7, 1.3}}); // its - flatchrg.add("Tracks/postSel/hITSnCls", " ; # ITS clusters", kTH1F, {{8, -0.5, 7.5}}); - flatchrg.add("Tracks/postSel/hChi2ITSTrkSegment", "chi2ITS", kTH1F, {{100, -0.5, 99.5}}); + registryData.add("Tracks/postSel/hITSnCls", " ; # ITS clusters", kTH1F, {{8, -0.5, 7.5}}); + registryData.add("Tracks/postSel/hChi2ITSTrkSegment", "chi2ITS", kTH1F, {{100, -0.5, 99.5}}); // tof - flatchrg.add("Tracks/postSel/hTOFPvsBeta", "Beta from TOF; #it{p} (GeV/#it{c}); #beta", {kTH2F, {pAxis, {120, 0.0, 1.2}}}); - if (cfgStoreThnSparse) { - flatchrg.add("Tracks/postSel/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, pAxis, dEdxAxis}}); - } else { - flatchrg.add("Tracks/postSel/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}); - } + registryData.add("Tracks/postSel/hTOFPvsBeta", "Beta from TOF; #it{p} (GeV/#it{c}); #beta", {kTH2F, {pAxis, {120, 0.0, 1.2}}}); + registryData.add("Tracks/postSel/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, pAxis, dEdxAxis}}); } if (cfgFilldEdxQaHist) { if (cfgStoreThnSparse) { - flatchrg.add("Tracks/postCalib/all/hMIP", "; mult; flat; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {kTHnSparseF, {multAxis, flatAxis, etaAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateau", "; mult; flat; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {kTHnSparseF, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + registryData.add("Tracks/postCalib/all/hMIP", "; mult; flat; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {kTHnSparseF, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + registryData.add("Tracks/postCalib/all/hPlateau", "; mult; flat; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {kTHnSparseF, {multAxis, flatAxis, etaAxis, dEdxAxis}}); } else { - flatchrg.add("Tracks/postCalib/all/hMIP", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {kTH2F, {etaAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateau", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {kTH2F, {etaAxis, dEdxAxis}}); + registryData.add("Tracks/postCalib/all/hMIP", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {kTH2F, {etaAxis, dEdxAxis}}); + registryData.add("Tracks/postCalib/all/hPlateau", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {kTH2F, {etaAxis, dEdxAxis}}); } - flatchrg.add("Tracks/postCalib/all/hMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {kTH2F, {phiAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/pMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {kTProfile, {phiAxis}}); - flatchrg.add("Tracks/postCalib/all/hMIPVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks}; #eta;", {kTH3F, {phiAxis, dEdxAxis, etaAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {kTH2F, {phiAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/pPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {kTProfile, {phiAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateauVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks}; #eta;", {kTH3F, {phiAxis, dEdxAxis, etaAxis}}); - flatchrg.addClone("Tracks/postCalib/all/", "Tracks/preCalib/all/"); + registryData.add("Tracks/postCalib/all/hMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {kTH2F, {phiAxis, dEdxAxis}}); + registryData.add("Tracks/postCalib/all/pMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {kTProfile, {phiAxis}}); + registryData.add("Tracks/postCalib/all/hMIPVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks}; #eta;", {kTH3F, {phiAxis, dEdxAxis, etaAxis}}); + registryData.add("Tracks/postCalib/all/hPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {kTH2F, {phiAxis, dEdxAxis}}); + registryData.add("Tracks/postCalib/all/pPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {kTProfile, {phiAxis}}); + registryData.add("Tracks/postCalib/all/hPlateauVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks}; #eta;", {kTH3F, {phiAxis, dEdxAxis, etaAxis}}); + registryData.addClone("Tracks/postCalib/all/", "Tracks/preCalib/all/"); if (cfgFillChrgType) { - flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/pos/"); - flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/neg/"); - flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/pos/"); - flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/neg/"); + registryData.addClone("Tracks/postCalib/all/", "Tracks/postCalib/pos/"); + registryData.addClone("Tracks/postCalib/all/", "Tracks/postCalib/neg/"); + registryData.addClone("Tracks/preCalib/all/", "Tracks/preCalib/pos/"); + registryData.addClone("Tracks/preCalib/all/", "Tracks/preCalib/neg/"); } } - if (cfgFillNsigmaQAHist) { - for (int i = 0; i < NpartChrg; i++) { - const std::string strID = Form("/%s/%s", (i < Npart) ? "pos" : "neg", Pid[i % Npart]); - if (cfgStoreThnSparse) { - hThPtNsigmaTPC[i] = flatchrg.add("Tracks/hThPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", kTHnSparseF, {ptAxis, nSigmaTPCAxis, multAxis, flatAxis}); - } else { - hPtNsigmaTPC[i] = flatchrg.add("Tracks/hPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, nSigmaTPCAxis}); - } - hPtNsigmaTOF[i] = flatchrg.add("Tracks/hPtNsigmaTOF" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, nSigmaTOFAxis}); - hPtNsigmaTPCTOF[i] = flatchrg.add("Tracks/hPtNsigmaTPCTOF" + strID, PidChrg[i], kTH2F, {nSigmaTPCAxis, nSigmaTOFAxis}); + if (cfgFillDCAxyHist) { + for (int i = 0; i < Npart; i++) { + registryData.add({fmt::format(CpTvsDCAxyF.data(), CspeciesAll[i]).c_str(), "; mult; flat; #it{p} (GeV/#it{c}); DCA_{xy} (cm)", {kTHnSparseF, {multAxis, flatAxis, ptAxis, dcaXYAxis}}}); } } } - flatchrg.addClone("Tracks/postSel/", "Tracks/preSel/"); - // FV0 QA - flatchrg.add("FV0/hFV0AmplWCalib", "", {kTH2F, {channelFV0Axis, amplitudeFV0}}); - flatchrg.add("FV0/hFV0AmplvsVtxzWoCalib", "", {kTH2F, {vtxzAxis, amplitudeFV0Sum}}); - flatchrg.add("FV0/hFV0AmplvsVtxzCalib", "", {kTH2F, {vtxzAxis, amplitudeFV0Sum}}); - flatchrg.add("FV0/hFV0amp", "", {kTH2F, {channelFV0Axis, amplitudeFV0}}); - flatchrg.add("FV0/pFV0amp", "", kTProfile, {channelFV0Axis}); - flatchrg.add("FV0/hFV0ampCorr", "", {kTH2F, {channelFV0Axis, amplitudeFV0}}); + registryData.addClone("Tracks/postSel/", "Tracks/preSel/"); // V0's QA - flatchrg.add("Tracks/V0qa/hV0Pt", "pT", kTH1F, {ptAxisV0s}); - flatchrg.add("Tracks/V0qa/hEtaVsRapK0s", ";#eta;#it{y};", kTH2F, {etaAxis, rapidityAxis}); - flatchrg.add("Tracks/V0qa/hEtaVsRapLam", ";#eta;#it{y};", kTH2F, {etaAxis, rapidityAxis}); - flatchrg.add("Tracks/V0qa/hEtaVsRapALam", ";#eta;#it{y};", kTH2F, {etaAxis, rapidityAxis}); - flatchrg.add("Tracks/V0qa/hEtaVsRapGamma", ";#eta;#it{y};", kTH2F, {etaAxis, rapidityAxis}); - flatchrg.add("Tracks/V0qa/hV0ArmPod", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); - flatchrg.add("Tracks/V0qa/hArmPodK0s", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); - flatchrg.add("Tracks/V0qa/hArmPodLam", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); - flatchrg.add("Tracks/V0qa/hArmPodALam", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); - flatchrg.add("Tracks/V0qa/hArmPodGamma", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); - flatchrg.add("Tracks/V0qa/hMassK0sVsPt", ";;Inv. Mass (GeV/#it{c}^{2});", kTH2F, {ptAxisV0s, v0SelOpt.axisK0sMass}); - flatchrg.add("Tracks/V0qa/hMassLamVsPt", ";;Inv. Mass (GeV/#it{c}^{2});", kTH2F, {ptAxisV0s, v0SelOpt.axisLambdaMass}); - flatchrg.add("Tracks/V0qa/hMassALamVsPt", ";;Inv. Mass (GeV/#it{c}^{2});", kTH2F, {ptAxisV0s, v0SelOpt.axisLambdaMass}); - flatchrg.add("Tracks/V0qa/hMassGammaVsPt", ";;Inv. Mass (GeV/#it{c}^{2});", kTH2F, {ptAxisV0s, v0SelOpt.axisGammaMass}); - flatchrg.add("Tracks/V0qa/hNsigmaPiFromK0s", ";#it{n#sigma};;", kTH2F, {ptAxisV0s, nSigmaTPCAxis}); - flatchrg.add("Tracks/V0qa/hNsigmaPiFromLam", ";#it{n#sigma};;", kTH2F, {ptAxisV0s, nSigmaTPCAxis}); - flatchrg.add("Tracks/V0qa/hNsigmaPrFromLam", ";#it{n#sigma};;", kTH2F, {ptAxisV0s, nSigmaTPCAxis}); - flatchrg.add("Tracks/V0qa/hNsigmaPiFromALam", ";#it{n#sigma};;", kTH2F, {ptAxisV0s, nSigmaTPCAxis}); - flatchrg.add("Tracks/V0qa/hNsigmaPrFromALam", ";#it{n#sigma};;", kTH2F, {ptAxisV0s, nSigmaTPCAxis}); - flatchrg.add("Tracks/V0qa/hNsigmaElFromGamma", ";#it{n#sigma};;", kTH2F, {ptAxisV0s, nSigmaTPCAxis}); + registryData.add("Tracks/V0qa/hV0Pt", "pT", kTH1F, {ptAxisV0s}); + registryData.add("Tracks/V0qa/hV0ArmPod", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); + // daughters' QA + registryData.add("Tracks/V0qa/el/Ga/hArmPod", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); + registryData.add("Tracks/V0qa/pi/K0s/hArmPod", ";#alpha; #it{q}_T (GeV/c)", kTH2F, {v0SelOpt.axisArmPodAlpha, v0SelOpt.axisArmPodqT}); + registryData.add("Tracks/V0qa/el/Ga/hNclVsEta", ";#eta; #it{N}^{TPC}_cl", kTH2F, {etaAxis, clTpcAxis}); + registryData.add("Tracks/V0qa/pi/K0s/hNclVsEta", ";#eta; #it{N}^{TPC}_cl", kTH2F, {etaAxis, clTpcAxis}); + registryData.add("Tracks/V0qa/el/Ga/hdEdxMIPVsEta", ";#eta; dE/dx", kTH2F, {etaAxis, dEdxAxis}); + registryData.add("Tracks/V0qa/pi/K0s/hdEdxMIPVsEta", ";#eta; dE/dx", kTH2F, {etaAxis, dEdxAxis}); + registryData.addClone("Tracks/V0qa/pi/K0s/", "Tracks/V0qa/pi/La/"); + registryData.addClone("Tracks/V0qa/pi/K0s/", "Tracks/V0qa/pi/ALa/"); + registryData.addClone("Tracks/V0qa/pi/La/", "Tracks/V0qa/pr/La/"); + registryData.addClone("Tracks/V0qa/pi/ALa/", "Tracks/V0qa/pr/ALa/"); // dEdx PID - flatchrg.add({"Tracks/all/hdEdx", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/all/hdEdx", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); // Clean samples if (cfgFillV0Hist) { if (cfgStoreThnSparse) { - flatchrg.add({"Tracks/CleanTof/all/hPiTof", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); - flatchrg.add({"Tracks/CleanV0/pos/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); - flatchrg.add({"Tracks/CleanV0/pos/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); - flatchrg.add({"Tracks/CleanV0/pos/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanTof/all/hPiTof", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanV0/all/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanV0/all/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanV0/all/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); } else { - flatchrg.add({"Tracks/CleanTof/all/hPiTof", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); - flatchrg.add({"Tracks/CleanV0/pos/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); - flatchrg.add({"Tracks/CleanV0/pos/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); - flatchrg.add({"Tracks/CleanV0/pos/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanTof/all/hPiTof", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanV0/all/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanV0/all/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + registryData.add({"Tracks/CleanV0/all/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTH3F, {etaAxis, pAxis, dEdxAxis}}}); } - flatchrg.add("Tracks/CleanTof/all/hBetaVsP", ";Momentum (GeV/#it{c}); #beta", kTH2F, {{{ptAxisV0s}, {120, 0., 1.2}}}); - flatchrg.add("Tracks/CleanTof/all/hTofExpPi", ";Momentum (GeV/#it{c});#it{t}^{#pi}_{Exp}/#it{t}_{TOF}", kTH2F, {{{ptAxisV0s}, {100, 0.2, 1.2}}}); - flatchrg.addClone("Tracks/CleanV0/pos/", "Tracks/CleanV0/neg/"); + registryData.add("Tracks/CleanTof/all/hBetaVsP", ";Momentum (GeV/#it{c}); #beta", kTH2F, {{{ptAxisV0s}, {120, 0., 1.2}}}); + registryData.add("Tracks/CleanTof/all/hTofExpPi", ";Momentum (GeV/#it{c});#it{t}^{#pi}_{Exp}/#it{t}_{TOF}", kTH2F, {{{ptAxisV0s}, {100, 0.2, 1.2}}}); if (cfgFillChrgType) { - flatchrg.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/pos/"); - flatchrg.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/neg/"); + registryData.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/pos/"); + registryData.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/neg/"); + registryData.addClone("Tracks/CleanV0/all/", "Tracks/CleanV0/pos/"); + registryData.addClone("Tracks/CleanV0/all/", "Tracks/CleanV0/neg/"); } } if (cfgFillChrgType) { - flatchrg.addClone("Tracks/all/", "Tracks/pos/"); - flatchrg.addClone("Tracks/all/", "Tracks/neg/"); + registryData.addClone("Tracks/all/", "Tracks/pos/"); + registryData.addClone("Tracks/all/", "Tracks/neg/"); } + LOG(info) << "Size of the Data histograms:"; + registryData.print(); } if (doprocessMC) { - auto h = flatchrg.add("hEvtGenRec", "Generated and Reconstructed MC Collisions", kTH1F, {{3, 0.5, 3.5}}); + registryMC.add({"Events/ResponseGen", ";N_{ch,FV0};1-#rho_{FV0};", {kTHnSparseF, {multAxis, flatAxis}}}); + registryMC.add("Events/h1flatencityFV0MCGen", "", {kTH1F, {flatAxis}}); + registryMC.add("Events/hFlatMCGen", "Events/hFlatMCGen", {kTH1F, {flatAxis}}); + registryMC.add("Events/hFlatMCRec", "Events/hFlatMCRec", {kTH1F, {flatAxis}}); + // Event counter + auto h = registryMC.add("Events/hEvtGenRec", "Generated and Reconstructed MC Collisions", kTH1F, {{3, 0.5, 3.5}}); h->GetXaxis()->SetBinLabel(1, "Gen coll"); h->GetXaxis()->SetBinLabel(2, "Rec coll"); h->GetXaxis()->SetBinLabel(3, "INEL>0"); - - flatchrg.add("hEvtMcGenColls", "Number of events; Cut; #Events Passed Cut", {kTH1F, {{5, 0.5, 5.5}}}); - flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(1, "Gen. coll"); - flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(2, "At least 1 reco"); - flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(3, "Reco. coll."); - flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(4, "Reco. good coll."); - - flatchrg.add("Events/hVtxZRec", "MC Rec vertex z position", kTH1F, {vtxzAxis}); - flatchrg.add("Events/hVtxZGen", "Generated vertex z position", kTH1F, {vtxzAxis}); + registryMC.add("Events/hEvtMcGen", "Events/hEvtMcGen", {kTH1F, {{4, 0.f, 4.f}}}); + registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(1, "all"); + registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(2, "z-vtx"); + registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(3, "INELgt0"); + registryMC.get(HIST("Events/hEvtMcGen"))->GetXaxis()->SetBinLabel(4, "INELgt0TVX"); + registryMC.add("Events/hEvtMCRec", "Events/hEvtMCRec", {kTH1F, {{3, 0.f, 3.f}}}); + registryMC.get(HIST("Events/hEvtMCRec"))->GetXaxis()->SetBinLabel(1, "all"); + registryMC.get(HIST("Events/hEvtMCRec"))->GetXaxis()->SetBinLabel(2, "evt sel"); + registryMC.get(HIST("Events/hEvtMCRec"))->GetXaxis()->SetBinLabel(3, "INELgt0"); + registryMC.add("Events/hEvtMcGenColls", "Number of events; Cut; #Events Passed Cut", {kTH1F, {{4, 0.5, 4.5}}}); + registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(1, "Gen. coll"); + registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(2, "At least 1 reco"); + registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(3, "Reco. coll."); + registryMC.get(HIST("Events/hEvtMcGenColls"))->GetXaxis()->SetBinLabel(4, "Reco. good coll."); + // + registryMC.add("Events/hNchVsCent", "Gen Nch vs Cent; mult; Gen Nch (|#eta|<0.8)", {kTH2F, {multAxis, nChAxis}}); + registryMC.add("Events/hVtxZRec", "MC Rec vertex z position", kTH1F, {vtxzAxis}); + registryMC.add("Events/hVtxZGen", "Generated vertex z position", kTH1F, {vtxzAxis}); + registryMC.add("Events/hNchTVX", "Nch in FT0A+FT0C; Nch; status", {kTH2F, {nChAxis, {2, 0, 2}}}); + registryMC.add({"Tracks/hPtFakes", "Fake tracks; Gen Nch (|#eta|<0.8); flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {nChAxis, flatAxis, ptAxis}}}); + // Event loss + registryMC.add("Events/hNchVsFlatGenINELgt0", "Gen Nch w/o Evt sel; Gen Nch (|#eta|<0.8); flat", {kTH2F, {nChAxis, flatAxis}}); + registryMC.add("Events/hNchVsFlatGenINELgt0wRecEvtSel", "Gen Nch w/ Nrec > 0 + Evt sel; Gen Nch (|#eta|<0.8); flat", {kTH2F, {nChAxis, flatAxis}}); + // Event split + registryMC.add("Events/hCentVsFlatRecINELgt0", "Gen evt w/o Evt sel; mult; flat", {kTH2F, {multAxis, flatAxis}}); + registryMC.add("Events/hCentVsFlatRecINELgt0wRecEvt", "Gen evt w/ Nrec > 0; mult; flat", {kTH2F, {multAxis, flatAxis}}); + registryMC.add("Events/hCentVsFlatRecINELgt0wRecEvtSel", "Gen evt w/ Nrec > 0 + Evt sel; mult; flat", {kTH2F, {multAxis, flatAxis}}); + for (int i = 0; i < Npart; ++i) { + // Signal loss + registryMC.add({fmt::format(CpTgenPrimSgnF.data(), CspeciesAll[i]).c_str(), "Gen evt w/o Evt sel; Gen Nch (|#eta|<0.8); flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {nChAxis, flatAxis, ptAxis}}}); + registryMC.add({fmt::format(CpTrecCollPrimSgnF.data(), CspeciesAll[i]).c_str(), "Gen Nch w/ Nrec > 0; Gen Nch (|#eta|<0.8); flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {nChAxis, flatAxis, ptAxis}}}); + // Closure test + registryMC.add({fmt::format(CpTmcClosureGenPrimF.data(), CspeciesAll[i]).c_str(), "Gen evt w/o Evt sel; Gen Nch (|#eta|<0.8); flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {nChAxis, flatAxis, ptAxis}}}); + registryMC.add({fmt::format(CpTmcClosureRecF.data(), CspeciesAll[i]).c_str(), "Gen Nch w/ Nrec > 0 + Evt. sel; Gen Nch (|#eta|<0.8); flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {nChAxis, flatAxis, ptAxis}}}); + } + if (cfgFillNclVsPhiCutQaHist) { + registryMC.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {kTH2F, {ptAxis, phiAxisMod}}); + registryMC.add("Tracks/postSel/hPtPhiNclTPC", "; #eta; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{cluster}", {kTHnSparseF, {etaAxis, ptAxis, phiAxisMod, clTpcAxis}}); + registryMC.add("Tracks/postSel/hPtPhiNclPIDTPC", "; #eta; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{PID cluster}", {kTHnSparseF, {etaAxis, ptAxis, phiAxisMod, clTpcAxis}}); + registryMC.add("Tracks/postSel/hPtNclTPC", "; #it{p}_{T} (GeV/#it{c}); N_{cluster}", {kTH2F, {ptAxis, clTpcAxis}}); + registryMC.add("Tracks/postSel/pPtNclTPC", "; #it{p}_{T} (GeV/#it{c}); N_{cluster}", {kTProfile, {ptAxis}}); + registryMC.add("Tracks/postSel/hPtNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); N_{PID cluster}", {kTH2F, {ptAxis, clTpcAxis}}); + registryMC.add("Tracks/postSel/pPtNclPIDTPC", "; #it{p}_{T} (GeV/#it{c}); N_{PID cluster}", {kTProfile, {ptAxis}}); + } + registryMC.addClone("Tracks/postSel/", "Tracks/preSel/"); for (int i = 0; i < NpartChrg; i++) { const std::string strID = Form("/%s/%s", (i < Npart) ? "pos" : "neg", Pid[i % Npart]); - hPtGenRecEvt[i] = flatchrg.add("Tracks/hPtGenRecEvt" + strID, " ; p_{T} (GeV/c)", kTH1F, {ptAxis}); - hPtGenPrimRecEvt[i] = flatchrg.add("Tracks/hPtGenPrimRecEvt" + strID, " ; p_{T} (GeV/c)", kTH1F, {ptAxis}); - hPtEffGenPrim[i] = flatchrg.add("Tracks/hPtEffGenPrim" + strID, " ; p_{T} (GeV/c)", kTH3F, {multAxis, flatAxis, ptAxis}); - hPtEffGenWeak[i] = flatchrg.add("Tracks/hPtEffGenWeak" + strID, " ; p_{T} (GeV/c)", kTH3F, {multAxis, flatAxis, ptAxis}); - hPtEffGenMat[i] = flatchrg.add("Tracks/hPtEffGenMat" + strID, " ; p_{T} (GeV/c)", kTH3F, {multAxis, flatAxis, ptAxis}); - hPtEffRecPrim[i] = flatchrg.add("Tracks/hPtEffRecPrim" + strID, " ; p_{T} (GeV/c)", kTH3F, {multAxis, flatAxis, ptAxis}); - hPtEffRecWeak[i] = flatchrg.add("Tracks/hPtEffRecWeak" + strID, " ; p_{T} (GeV/c)", kTH3F, {multAxis, flatAxis, ptAxis}); - hPtEffRecMat[i] = flatchrg.add("Tracks/hPtEffRecMat" + strID, " ; p_{T} (GeV/c)", kTH3F, {multAxis, flatAxis, ptAxis}); - hDCAxyBadCollPrim[i] = flatchrg.add("Tracks/hDCAxyBadCollPrim" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, dcaXYAxis}); - hDCAxyBadCollWeak[i] = flatchrg.add("Tracks/hDCAxyBadCollWeak" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, dcaXYAxis}); - hDCAxyBadCollMat[i] = flatchrg.add("Tracks/hDCAxyBadCollMat" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, dcaXYAxis}); - hPtVsDCAxyPrim[i] = flatchrg.add("Tracks/hPtVsDCAxyPrim" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, dcaXYAxis}); - hPtVsDCAxyWeak[i] = flatchrg.add("Tracks/hPtVsDCAxyWeak" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, dcaXYAxis}); - hPtVsDCAxyMat[i] = flatchrg.add("Tracks/hPtVsDCAxyMat" + strID, " ; p_{T} (GeV/c)", kTH2F, {ptAxis, dcaXYAxis}); - } - - flatchrg.add({"hPtOut", " ; p_{T} (GeV/c)", {kTH1F, {ptAxis}}}); - flatchrg.add({"hPtOutPrim", " ; p_{T} (GeV/c)", {kTH1F, {ptAxis}}}); - flatchrg.add({"hPtOutNoEtaCut", " ; p_{T} (GeV/c)", {kTH1F, {ptAxis}}}); - flatchrg.add({"PtOutFakes", " ; p_{T} (GeV/c)", {kTH1F, {ptAxis}}}); - flatchrg.add("hPtVsDCAxyPrimAll", "hPtVsDCAxyPrimAll", kTH2F, {ptAxis, dcaXYAxis}); - flatchrg.add("hPtVsDCAxyWeakAll", "hPtVsDCAxyWeakAll", kTH2F, {ptAxis, dcaXYAxis}); - flatchrg.add("hPtVsDCAxyMatAll", "hPtVsDCAxyMatAll", kTH2F, {ptAxis, dcaXYAxis}); - flatchrg.add("hPtVsDCAxyAll", "hPtVsDCAxyAll", kTH2F, {ptAxis, dcaXYAxis}); - flatchrg.add({"ResponseGen", " ; N_{part}; F_{FV0};", {kTHnSparseF, {multAxis, flatAxis}}}); - flatchrg.add("h1flatencityFV0MCGen", "", kTH1F, {{102, -0.01, 1.01, "1-flatencityFV0"}}); + hPtGenRecEvt[i] = registryMC.add("Tracks/hPtGenRecEvt" + strID, "Gen evt w/ Nrec > 0; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtGenPrimRecEvt[i] = registryMC.add("Tracks/hPtGenPrimRecEvt" + strID, "Gen evt w/ Nrec > 0 (primary); mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtEffGenPrim[i] = registryMC.add("Tracks/hPtEffGenPrim" + strID, "Gen evt w/o rec Evt; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtEffGenWeak[i] = registryMC.add("Tracks/hPtEffGenWeak" + strID, "Gen evt w/o rec Evt; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtEffGenMat[i] = registryMC.add("Tracks/hPtEffGenMat" + strID, "Gen evt w/o rec Evt; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtEffRecGoodCollPrim[i] = registryMC.add("Tracks/hPtEffRecGoodCollPrim" + strID, "; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtEffRecGoodCollWeak[i] = registryMC.add("Tracks/hPtEffRecGoodCollWeak" + strID, "; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hPtEffRecGoodCollMat[i] = registryMC.add("Tracks/hPtEffRecGoodCollMat" + strID, "; mult; flat; #it{p}_{T} (GeV/#it{c})", kTHnSparseF, {multAxis, flatAxis, ptAxis}); + hDCAxyRecBadCollPrim[i] = registryMC.add("Tracks/hDCAxyRecBadCollPrim" + strID, "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {ptAxis, dcaXYAxis}); + hDCAxyRecBadCollWeak[i] = registryMC.add("Tracks/hDCAxyRecBadCollWeak" + strID, "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {ptAxis, dcaXYAxis}); + hDCAxyRecBadCollMat[i] = registryMC.add("Tracks/hDCAxyRecBadCollMat" + strID, "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {ptAxis, dcaXYAxis}); + hPtVsDCAxyRecGoodCollPrim[i] = registryMC.add("Tracks/hPtVsDCAxyRecGoodCollPrim" + strID, "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {ptAxis, dcaXYAxis}); + hPtVsDCAxyRecGoodCollWeak[i] = registryMC.add("Tracks/hPtVsDCAxyRecGoodCollWeak" + strID, "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {ptAxis, dcaXYAxis}); + hPtVsDCAxyRecGoodCollMat[i] = registryMC.add("Tracks/hPtVsDCAxyRecGoodCollMat" + strID, "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {ptAxis, dcaXYAxis}); + } + + for (int i = 0; i < Npart; i++) { + registryMC.add({fmt::format(CpTeffGenPrimRecEvtF.data(), CspeciesAll[i]).c_str(), "Gen evt w/ Nrec > 0; mult; flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {multAxis, flatAxis, ptAxis}}}); + registryMC.add({fmt::format(CpTeffPrimRecEvtF.data(), CspeciesAll[i]).c_str(), "Gen evt w/ Nrec > 0 + Evt sel; mult; flat; #it{p}_{T} (GeV/#it{c})", {kTHnSparseF, {multAxis, flatAxis, ptAxis}}}); + registryMC.add({fmt::format(CpTvsDCAxyAllF.data(), CspeciesAll[i]).c_str(), "; mult; flat; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", {kTHnSparseF, {multAxis, flatAxis, ptAxis, dcaXYAxis}}}); + registryMC.add({fmt::format(CpTvsDCAxyPrimAllF.data(), CspeciesAll[i]).c_str(), "; mult; flat; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", {kTHnSparseF, {multAxis, flatAxis, ptAxis, dcaXYAxis}}}); + registryMC.add({fmt::format(CpTvsDCAxyWeakAllF.data(), CspeciesAll[i]).c_str(), "; mult; flat; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", {kTHnSparseF, {multAxis, flatAxis, ptAxis, dcaXYAxis}}}); + registryMC.add({fmt::format(CpTvsDCAxyMatAllF.data(), CspeciesAll[i]).c_str(), "; mult; flat; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", {kTHnSparseF, {multAxis, flatAxis, ptAxis, dcaXYAxis}}}); + registryMC.add({fmt::format(CdEdxMcRecPrimF.data(), CspeciesAll[i]).c_str(), "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + } // Hash list for efficiency listEfficiency.setObject(new THashList); @@ -731,44 +822,10 @@ struct FlattenictyPikp { initEfficiency(); initEfficiency(); }); - } - if (doprocessMCclosure) { - for (int i = 0; i < Npart; i++) { - flatchrg.add({fmt::format(CpTmcClosurePrimF.data(), CspeciesAll[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - } + LOG(info) << "Size of the MC histograms:"; + registryMC.print(); } - - if (doprocessSgnLoss) { - flatchrg.add("hFlatMCGenRecColl", "hFlatMCGenRecColl", {kTH1F, {flatAxis}}); - flatchrg.add("hFlatMCGen", "hFlatMCGen", {kTH1F, {flatAxis}}); - // Event counter - flatchrg.add("hEvtMcGen", "hEvtMcGen", {kTH1F, {{4, 0.f, 4.f}}}); - flatchrg.get(HIST("hEvtMcGen"))->GetXaxis()->SetBinLabel(1, "all"); - flatchrg.get(HIST("hEvtMcGen"))->GetXaxis()->SetBinLabel(2, "z-vtx"); - flatchrg.get(HIST("hEvtMcGen"))->GetXaxis()->SetBinLabel(3, "INELgt0"); - flatchrg.add("hEvtMCRec", "hEvtMCRec", {kTH1F, {{4, 0.f, 4.f}}}); - flatchrg.get(HIST("hEvtMCRec"))->GetXaxis()->SetBinLabel(1, "all"); - flatchrg.get(HIST("hEvtMCRec"))->GetXaxis()->SetBinLabel(2, "evt sel"); - flatchrg.get(HIST("hEvtMCRec"))->GetXaxis()->SetBinLabel(3, "INELgt0"); - flatchrg.add("hEvtMcGenRecColl", "hEvtMcGenRecColl", {kTH1F, {{2, 0.f, 2.f}}}); - flatchrg.get(HIST("hEvtMcGenRecColl"))->GetXaxis()->SetBinLabel(1, "INEL"); - flatchrg.get(HIST("hEvtMcGenRecColl"))->GetXaxis()->SetBinLabel(2, "INELgt0"); - - flatchrg.add("hFlatGenINELgt0", "hFlatGenINELgt0", {kTH1F, {flatAxis}}); - - for (int i = 0; i < NpartChrg; ++i) { - flatchrg.add({fmt::format(CpTgenPrimSgnF.data(), Cspecies[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - flatchrg.add({fmt::format(CpTgenPrimSgnINELF.data(), Cspecies[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - flatchrg.add({fmt::format(CpTrecCollPrimSgnF.data(), Cspecies[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - flatchrg.add({fmt::format(CpTrecCollPrimSgnINELF.data(), Cspecies[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - flatchrg.add({fmt::format(CpTGenRecCollPrimSgnF.data(), Cspecies[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - flatchrg.add({fmt::format(CpTGenRecCollPrimSgnINELF.data(), Cspecies[i]).c_str(), " ; p_{T} (GeV/c)", {kTH3F, {multAxis, flatAxis, ptAxis}}}); - } - } - - LOG(info) << "Size of the histograms:"; - flatchrg.print(); } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -850,48 +907,27 @@ struct FlattenictyPikp { } } - using MyCollisions = soa::Join; - using Colls = soa::Join; - using CollsGen = soa::Join; - using MCColls = soa::Join; - using CollsGenSgn = soa::SmallGroups>; - using MyPIDTracks = soa::Join; - using MyLabeledTracks = soa::Join; - using MyFiltLabeledTracks = soa::Filtered; - using MyLabeledPIDTracks = soa::Join; - template std::unique_ptr setFuncPars(T const& vecPars) { - std::unique_ptr fCalibFunc(new TF1("fCalibFunc", "pol2", -1., 1.)); + std::unique_ptr fCalibDeDxFunc(new TF1("fCalibDeDxFunc", cfgCalibDeDxFunction.value.c_str(), -1., 1.)); if (vecPars.size() >= 1) { for (typename T::size_type i = 0; i < vecPars.size(); i++) { - fCalibFunc->SetParameter(i, vecPars[i]); + fCalibDeDxFunc->SetParameter(i, vecPars[i]); } } - return fCalibFunc; + return fCalibDeDxFunc; } template bool isPID(const P& mcParticle) { - static_assert(pidSgn == Cnull || pidSgn == 1); - static_assert(id > Cnull || id < Npart); + static_assert(pidSgn == CnullInt || pidSgn == ConeInt); + static_assert(id > CnullInt || id < Npart); constexpr int Cidx = id + pidSgn * Npart; return mcParticle.pdgCode() == PidSgn[Cidx]; } - template - bool selTPCtrack(T const& track) - { - return (track.hasTPC() && - track.passedTPCCrossedRowsOverNCls() && - track.passedTPCChi2NDF() && - track.passedTPCNCls() && - track.passedTPCCrossedRows() && - track.passedTPCRefit()); - } - template bool selTOFPi(T const& track) { @@ -900,9 +936,9 @@ struct FlattenictyPikp { const float trkLength = track.length(); const float tExpPiTOF = track.tofExpSignalPi(tTOF); if (track.p() >= trkSelOpt.cfgMomSelPiTOF && trkLength > Cnull && tTOF > Cnull) { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[chrg]) + HIST("hTofExpPi"), track.p(), tExpPiTOF / tTOF); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[chrg]) + HIST("hTofExpPi"), track.p(), tExpPiTOF / tTOF); if (std::abs((tExpPiTOF / tTOF) - Cone) < trkSelOpt.cfgTofBetaPiMax) { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[chrg]) + HIST("hBetaVsP"), track.p(), track.beta()); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[chrg]) + HIST("hBetaVsP"), track.p(), track.beta()); // if (std::abs(track.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC && std::abs(track.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { return true; // } @@ -912,13 +948,43 @@ struct FlattenictyPikp { return false; } - template - void fillNsigma(T const& tracks, C const& collision) + template + void fillDCA(T const& tracks, C const& collision, aod::BCsWithTimestamps const& /*bcs*/) { + if (trkSelOpt.cfgRejectTrkAtTPCSector) { + auto bc = collision.template bc_as(); + int currentRun = bc.runNumber(); + if (runNumber != currentRun) { + initCCDB(bc); + runNumber = currentRun; + } + } const float mult = getMult(collision); const float flat = fillFlat(collision); for (const auto& track : tracks) { - checkNsigma(track, mult, flat); + if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { + continue; + } + if (track.pt() < trkSelOpt.cfgTrkPtMin) { + continue; + } + if (trkSelOpt.cfgApplyNcl && track.tpcNClsFound() < trkSelOpt.cfgNclTPCMin) { + continue; + } + if (trkSelOpt.cfgApplyNclPID && track.tpcNClsPID() < trkSelOpt.cfgNclPidTPCMin) { + continue; + } + float phiModn = track.phi(); + phiMod(phiModn, magField, track.sign()); + if (trkSelOpt.cfgRejectTrkAtTPCSector && (track.pt() >= trkSelOpt.cfgPhiCutPtMin && phiModn < fPhiCutHigh->Eval(track.pt()) && phiModn > fPhiCutLow->Eval(track.pt()))) { + continue; + } + if (!isDCAxyWoCut(track)) { + continue; + } + if (track.hasTOF() && (std::sqrt(std::pow(std::fabs(o2::aod::pidutils::tpcNSigma(track)), 2) + std::pow(std::fabs(o2::aod::pidutils::tofNSigma(track)), 2) < trkSelOpt.cfgDcaNsigmaCombinedMax))) { + registryData.fill(HIST(Cprefix) + HIST(CspeciesAll[id]) + HIST(CpTvsDCAxy), mult, flat, track.pt(), track.dcaXY()); + } } } @@ -936,7 +1002,7 @@ struct FlattenictyPikp { const float mult = getMult(collision); const float flat = fillFlat(collision); - flatchrg.fill(HIST("Events/hFlatVsMultEst"), flat, mult); + registryData.fill(HIST("Events/hFlatVsMultEst"), flat, mult); for (const auto& track : tracks) { float dEdx = track.tpcSignal(); @@ -951,7 +1017,7 @@ struct FlattenictyPikp { } if (cfgFilldEdxCalibHist && cfgFilldEdxQaHist) { if (cfgFillChrgType) { - if (track.sign() * track.tpcInnerParam() > Cnull) { + if (track.sign() * track.p() > Cnull) { filldEdxQA(track, collision, dEdx); } else { filldEdxQA(track, collision, dEdx); @@ -962,7 +1028,7 @@ struct FlattenictyPikp { } if (applyCalibDeDx) { if (cfgFillChrgType) { - if (track.sign() * track.tpcInnerParam() > Cnull) { + if (track.sign() * track.p() > Cnull) { if (applyCalibDeDxFromCCDB) { dEdx *= (50.0 / dedxcalib.hMIPcalibPos->GetBinContent(dedxcalib.hMIPcalibPos->FindBin(track.eta()))); } else { @@ -995,37 +1061,37 @@ struct FlattenictyPikp { // PID TPC dEdx if (cfgFillChrgType) { - if (track.sign() * track.tpcInnerParam() > Cnull) { - flatchrg.fill(HIST(Cprefix) + HIST(Ccharge[kPos]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + if (track.sign() * track.p() > Cnull) { + registryData.fill(HIST(Cprefix) + HIST(Ccharge[kPos]) + HIST("hdEdx"), track.eta(), mult, flat, track.p(), dEdx); } else { - flatchrg.fill(HIST(Cprefix) + HIST(Ccharge[kNeg]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(Ccharge[kNeg]) + HIST("hdEdx"), track.eta(), mult, flat, track.p(), dEdx); } } else { - flatchrg.fill(HIST(Cprefix) + HIST(Ccharge[kAll]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(Ccharge[kAll]) + HIST("hdEdx"), track.eta(), mult, flat, track.p(), dEdx); } // TOF pions if (cfgFillV0Hist) { if (selTOFPi(track)) { if (cfgFillChrgType) { - if (track.sign() * track.tpcInnerParam() > Cnull) { + if (track.sign() * track.p() > Cnull) { if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kPos]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kPos]) + HIST("hPiTof"), track.eta(), mult, flat, track.p(), dEdx); } else { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kPos]) + HIST("hPiTof"), track.eta(), track.tpcInnerParam(), dEdx); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kPos]) + HIST("hPiTof"), track.eta(), track.p(), dEdx); } } else { if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kNeg]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kNeg]) + HIST("hPiTof"), track.eta(), mult, flat, track.p(), dEdx); } else { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kNeg]) + HIST("hPiTof"), track.eta(), track.tpcInnerParam(), dEdx); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kNeg]) + HIST("hPiTof"), track.eta(), track.p(), dEdx); } } } else { if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kAll]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kAll]) + HIST("hPiTof"), track.eta(), mult, flat, track.p(), dEdx); } else { - flatchrg.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kAll]) + HIST("hPiTof"), track.eta(), track.tpcInnerParam(), dEdx); + registryData.fill(HIST(CprefixCleanTof) + HIST(Ccharge[kAll]) + HIST("hPiTof"), track.eta(), track.p(), dEdx); } } } @@ -1068,6 +1134,8 @@ struct FlattenictyPikp { } if (selectTypeV0s(collision, v0, posTrack, negTrack) == kGa) { // Gamma selection + fillV0QA(v0, posTrack); + fillV0QA(v0, negTrack); if (applyCalibDeDx) { if (cfgFillChrgTypeV0s) { if (applyCalibDeDxFromCCDB) { @@ -1100,38 +1168,84 @@ struct FlattenictyPikp { } } if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hEV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hEV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hEV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hEV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hEV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hEV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } } else { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hEV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hEV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hEV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hEV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hEV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hEV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } } } if (selectTypeV0s(collision, v0, posTrack, negTrack) == kKz) { // K0S -> pi + pi + fillV0QA(v0, posTrack); + fillV0QA(v0, negTrack); if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } } else { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } } } if (selectTypeV0s(collision, v0, posTrack, negTrack) == kLam) { // L -> p + pi- + fillV0QA(v0, negTrack); + fillV0QA(v0, posTrack); if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } } else { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } } } - if (selectTypeV0s(collision, v0, posTrack, negTrack) == kaLam) { // L -> p + pi- + if (selectTypeV0s(collision, v0, posTrack, negTrack) == kaLam) { // antiLambda -> pbar + pi+ + fillV0QA(v0, posTrack); + fillV0QA(v0, negTrack); if (cfgStoreThnSparse) { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.p(), dEdxNeg); + } } else { - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); - flatchrg.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + if (cfgFillChrgType) { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kPos]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kNeg]) + HIST("hPV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } else { + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.p(), dEdxPos); + registryData.fill(HIST(CprefixCleanV0) + HIST(Ccharge[kAll]) + HIST("hPV0"), negTrack.eta(), negTrack.sign() * negTrack.p(), dEdxNeg); + } } } } @@ -1143,13 +1257,25 @@ struct FlattenictyPikp { { float valCalib = -1.; if constexpr (isChrg) { - if (track.sign() * track.tpcInnerParam() > Cnull) { - valCalib = fCalib.at(0)->Eval(track.eta()); + if (track.sign() * track.p() > Cnull) { + if (track.eta() >= 0) { + valCalib = fCalib.at(0)->Eval(track.eta()); + } else { + valCalib = fCalib.at(3)->Eval(track.eta()); + } } else { - valCalib = fCalib.at(1)->Eval(track.eta()); + if (track.eta() >= 0) { + valCalib = fCalib.at(1)->Eval(track.eta()); + } else { + valCalib = fCalib.at(4)->Eval(track.eta()); + } } } else { - valCalib = fCalib.at(2)->Eval(track.eta()); + if (track.eta() >= 0) { + valCalib = fCalib.at(2)->Eval(track.eta()); + } else { + valCalib = fCalib.at(5)->Eval(track.eta()); + } } return valCalib; } @@ -1164,103 +1290,167 @@ struct FlattenictyPikp { return std::abs(charge) >= CminCharge; } - template - bool phiCut(T const& track, float mag, TF1* fphiCutLow, TF1* fphiCutHigh) + template + int countPart(P const& particles) + { + auto nCharged = 0; + for (auto const& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.eta()) > trkSelOpt.cfgTrkEtaMax) { + continue; + } + nCharged++; + } + return nCharged; + } + + template + bool isInelGt0wTVX(P const& particles) + { + int nChrgMc = 0; + int nChrgFT0A = 0; + int nChrgFT0C = 0; + for (auto const& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + // trigger TVX + if (particle.eta() > CminAccFT0A && particle.eta() < CmaxAccFT0A) { + nChrgFT0A++; + } + if (particle.eta() > CminAccFT0C && particle.eta() < CmaxAccFT0C) { + nChrgFT0C++; + } + nChrgMc++; + } + if (nChrgFT0A == CnullInt || nChrgFT0C == CnullInt) { + registryMC.fill(HIST("Events/hNchTVX"), nChrgMc, 0.5); + return false; + } + registryMC.fill(HIST("Events/hNchTVX"), nChrgMc, 1.5); + if (nChrgMc == CnullInt) { + return false; + } + return true; + } + + void phiMod(float& phimodn, const int& mag, const int& charge) { - if (track.pt() < trkSelOpt.cfgPhiCutPtMin) - return true; - // cut to remove tracks at TPC boundaries - double phimodn = track.phi(); if (mag < Cnull) // for negative polarity field phimodn = o2::constants::math::TwoPI - phimodn; - if (track.sign() < Cnull) // for negative charge + if (charge < Cnull) // for negative charge phimodn = o2::constants::math::TwoPI - phimodn; if (phimodn < Cnull) LOGF(warning, "phi < Cnull: %g", phimodn); phimodn += o2::constants::math::PI / 18.0f; // to center gap in the middle phimodn = std::fmod(phimodn, o2::constants::math::PI / 9.0f); + } - if (cfgFillTrackQaHist) { - flatchrg.fill(HIST("Tracks/preSel/hPtPhi"), track.pt(), phimodn); - if (track.hasTPC() && track.hasITS()) { - if (cfgStoreThnSparse) { - flatchrg.fill(HIST("Tracks/preSel/hPtPhiNclTPC"), track.pt(), phimodn, track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/preSel/hPtPhiNclPIDTPC"), track.pt(), phimodn, track.tpcNClsPID()); - } else { - flatchrg.fill(HIST("Tracks/preSel/hPtPhiNclTPC"), track.pt(), phimodn, track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/preSel/hPtPhiNclPIDTPC"), track.pt(), phimodn, track.tpcNClsPID()); - flatchrg.fill(HIST("Tracks/preSel/hPtNclTPC"), track.pt(), track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/preSel/pPtNclTPC"), track.pt(), track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/preSel/hPtNclPIDTPC"), track.pt(), track.tpcNClsPID()); - flatchrg.fill(HIST("Tracks/preSel/pPtNclPIDTPC"), track.pt(), track.tpcNClsPID()); - } - } - } - if (phimodn < fphiCutHigh->Eval(track.pt()) && phimodn > fphiCutLow->Eval(track.pt())) { - return false; - } - if (cfgFillTrackQaHist) { - flatchrg.fill(HIST("Tracks/postSel/hPtPhi"), track.pt(), phimodn); - if (track.hasTPC() && track.hasITS()) { - if (cfgStoreThnSparse) { - flatchrg.fill(HIST("Tracks/postSel/hPtPhiNclTPC"), track.pt(), phimodn, track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/postSel/hPtPhiNclPIDTPC"), track.pt(), phimodn, track.tpcNClsPID()); - } else { - flatchrg.fill(HIST("Tracks/postSel/hPtPhiNclTPC"), track.pt(), phimodn, track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/postSel/hPtPhiNclPIDTPC"), track.pt(), phimodn, track.tpcNClsPID()); - flatchrg.fill(HIST("Tracks/postSel/hPtNclTPC"), track.pt(), track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/postSel/pPtNclTPC"), track.pt(), track.tpcNClsFound()); - flatchrg.fill(HIST("Tracks/postSel/hPtNclPIDTPC"), track.pt(), track.tpcNClsPID()); - flatchrg.fill(HIST("Tracks/postSel/pPtNclPIDTPC"), track.pt(), track.tpcNClsPID()); - } - } + template + inline void fillNclVsPhiCutQaHist(T const& track, const float phimodn) + { + if (cfgFillNclVsPhiCutQaHist) { + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtPhi"), track.pt(), phimodn); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtPhiNclTPC"), track.eta(), track.pt(), phimodn, track.tpcNClsFound()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtPhiNclPIDTPC"), track.eta(), track.pt(), phimodn, track.tpcNClsPID()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtNclTPC"), track.pt(), track.tpcNClsFound()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("pPtNclTPC"), track.pt(), track.tpcNClsFound()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtNclPIDTPC"), track.pt(), track.tpcNClsPID()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("pPtNclPIDTPC"), track.pt(), track.tpcNClsPID()); } - return true; } template - bool isGoodTrack(T const& track, int const magfield) + bool isGoodTrack(T const& track, const int magfield) { - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelAll); + registryData.fill(HIST("Tracks/hTrkSel"), trkSelAll); if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelEta); + registryData.fill(HIST("Tracks/hTrkSel"), trkSelEta); if (track.pt() < trkSelOpt.cfgTrkPtMin) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelPt); + registryData.fill(HIST("Tracks/hTrkSel"), trkSelPt); if (!isDCAxyCut(track)) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelDCA); + registryData.fill(HIST("Tracks/hTrkSel"), trkSelDCA); if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkNRowsTPC); - if (track.tpcNClsFound() < trkSelOpt.cfgNclTPCMin) { + registryData.fill(HIST("Tracks/hTrkSel"), trkNRowsTPC); + if (trkSelOpt.cfgApplyNcl && track.tpcNClsFound() < trkSelOpt.cfgNclTPCMin) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelNClsFound); + registryData.fill(HIST("Tracks/hTrkSel"), trkSelNClsFound); if (trkSelOpt.cfgApplyNclPID && track.tpcNClsPID() < trkSelOpt.cfgNclPidTPCMin) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelNClsPID); - if (trkSelOpt.cfgRejectTrkAtTPCSector && !phiCut(track, magfield, fPhiCutLow, fPhiCutHigh)) { + registryData.fill(HIST("Tracks/hTrkSel"), trkSelNClsPID); + + float phimodn = track.phi(); + phiMod(phimodn, magfield, track.sign()); + if (cfgFillNclVsPhiCutQaHist) { + fillNclVsPhiCutQaHist(track, phimodn); + } + if (trkSelOpt.cfgRejectTrkAtTPCSector && (track.pt() >= trkSelOpt.cfgPhiCutPtMin && phimodn < fPhiCutHigh->Eval(track.pt()) && phimodn > fPhiCutLow->Eval(track.pt()))) { return false; } - flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelTPCBndr); + if (cfgFillNclVsPhiCutQaHist) { + fillNclVsPhiCutQaHist(track, phimodn); + } + registryData.fill(HIST("Tracks/hTrkSel"), trkSelTPCBndr); return true; } + template + void fillV0QA(V const& v0, U const& track) + { + registryData.fill(HIST(CprefixV0qa) + HIST(PidDir[id]) + HIST(V0Dir[typeMother]) + HIST("hArmPod"), v0.alpha(), v0.qtarm()); + registryData.fill(HIST(CprefixV0qa) + HIST(PidDir[id]) + HIST(V0Dir[typeMother]) + HIST("hNclVsEta"), track.eta(), track.tpcNClsPID()); + registryData.fill(HIST(CprefixV0qa) + HIST(PidDir[id]) + HIST(V0Dir[typeMother]) + HIST("hdEdxMIPVsEta"), track.eta(), track.tpcSignal()); + } + template int selectTypeV0s(C const& collision, T1 const& v0, T2 const& postrk, T2 const& negtrk) { + const float dMassK0s = std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short); + const float dMassL = std::abs(v0.mLambda() - o2::constants::physics::MassLambda0); + const float dMassAL = std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0); + const float dMassG = std::abs(v0.mGamma() - o2::constants::physics::MassGamma); + + bool isMassG = false; + bool isMassK0s = false; + bool isMassL = false; + bool isMassAL = false; + + if (dMassK0s > v0SelOpt.cfgdmassK && dMassL > v0SelOpt.cfgdmassL && dMassAL > v0SelOpt.cfgdmassL && dMassG < v0SelOpt.cfgdmassG) { + isMassG = true; + } + if (dMassK0s < v0SelOpt.cfgdmassK && dMassL > v0SelOpt.cfgdmassL && dMassAL > v0SelOpt.cfgdmassL && dMassG > v0SelOpt.cfgdmassG) { + isMassK0s = true; + } + if (dMassK0s > v0SelOpt.cfgdmassK && dMassL < v0SelOpt.cfgdmassL && dMassG > v0SelOpt.cfgdmassG) { + isMassL = true; + } + if (dMassK0s > v0SelOpt.cfgdmassK && dMassAL < v0SelOpt.cfgdmassL && dMassG > v0SelOpt.cfgdmassG) { + isMassAL = true; + } + // Gamma selection const float yGamma = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, o2::constants::physics::MassGamma); - if (v0.mGamma() < v0SelOpt.cfgdmassG) { // inv mass cut + if (isMassG) { if (std::abs(yGamma) < v0SelOpt.cfgV0Ymax) { // rapidity cut if (std::abs(v0.alpha()) < v0SelOpt.cfgArmPodGammasalpha && v0.qtarm() < v0SelOpt.cfgArmPodGammasqT) { // if (postrk.hasTPC() && std::abs(postrk.tpcNSigmaEl()) < v0SelOpt.cfgNsigmaElTPC) { @@ -1273,17 +1463,11 @@ struct FlattenictyPikp { return kGa; } } - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapGamma"), negtrk.eta(), yGamma); - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapGamma"), postrk.eta(), yGamma); - flatchrg.fill(HIST("Tracks/V0qa/hArmPodGamma"), v0.alpha(), v0.qtarm()); - flatchrg.fill(HIST("Tracks/V0qa/hMassGammaVsPt"), v0.pt(), v0.mGamma()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaElFromGamma"), postrk.pt(), postrk.tpcNSigmaEl()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaElFromGamma"), negtrk.pt(), negtrk.tpcNSigmaEl()); } } } // K0S selection, K0S -> pi + pi - if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0SelOpt.cfgdmassK) { // inv mass cut + if (isMassK0s) { if (std::abs(v0.yK0Short()) < v0SelOpt.cfgV0Ymax) { // rapidity cut if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < v0SelOpt.cfgcTauK0s) { // ctau cut if (v0.v0cosPA() >= v0SelOpt.cfgCosPAK0s && v0.v0radius() >= v0SelOpt.cfgV0radiusK0s && v0.qtarm() * v0SelOpt.cfgArmPodK0s > std::abs(v0.alpha())) { // @@ -1297,18 +1481,12 @@ struct FlattenictyPikp { return kKz; } } - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapK0s"), negtrk.eta(), v0.yK0Short()); - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapK0s"), postrk.eta(), v0.yK0Short()); - flatchrg.fill(HIST("Tracks/V0qa/hArmPodK0s"), v0.alpha(), v0.qtarm()); - flatchrg.fill(HIST("Tracks/V0qa/hMassK0sVsPt"), v0.pt(), v0.mK0Short()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaPiFromK0s"), postrk.pt(), postrk.tpcNSigmaPi()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaPiFromK0s"), negtrk.pt(), negtrk.tpcNSigmaPi()); } } } } // Lambda selection, L -> p + pi- - if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0SelOpt.cfgdmassL) { // inv mass cut + if (isMassL) { if (std::abs(v0.yLambda()) < v0SelOpt.cfgV0Ymax) { // rapidity cut if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < v0SelOpt.cfgcTauLambda) { // ctau cut if (v0.v0cosPA() >= v0SelOpt.cfgCosPALambda && v0.v0radius() >= v0SelOpt.cfgV0radiusLambda) { // @@ -1317,18 +1495,12 @@ struct FlattenictyPikp { return kLam; } } - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapLam"), negtrk.eta(), v0.yLambda()); - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapLam"), postrk.eta(), v0.yLambda()); - flatchrg.fill(HIST("Tracks/V0qa/hArmPodLam"), v0.alpha(), v0.qtarm()); - flatchrg.fill(HIST("Tracks/V0qa/hMassLamVsPt"), v0.pt(), v0.mLambda()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaPrFromLam"), postrk.pt(), postrk.tpcNSigmaPr()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaPiFromLam"), negtrk.pt(), negtrk.tpcNSigmaPi()); } } } } // antiLambda -> pbar + pi+ - if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < v0SelOpt.cfgdmassL) { // inv mass cut + if (isMassAL) { if (std::abs(v0.yLambda()) < v0SelOpt.cfgV0Ymax) { // rapidity cut if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < v0SelOpt.cfgcTauLambda) { // ctau cut if (v0.v0cosPA() >= v0SelOpt.cfgCosPALambda && v0.v0radius() >= v0SelOpt.cfgV0radiusLambda) { // @@ -1337,12 +1509,6 @@ struct FlattenictyPikp { return kaLam; } } - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapALam"), negtrk.eta(), v0.yLambda()); - flatchrg.fill(HIST("Tracks/V0qa/hEtaVsRapALam"), postrk.eta(), v0.yLambda()); - flatchrg.fill(HIST("Tracks/V0qa/hArmPodALam"), v0.alpha(), v0.qtarm()); - flatchrg.fill(HIST("Tracks/V0qa/hMassALamVsPt"), v0.pt(), v0.mLambda()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaPiFromALam"), postrk.pt(), postrk.tpcNSigmaPi()); - flatchrg.fill(HIST("Tracks/V0qa/hNsigmaPrFromALam"), negtrk.pt(), negtrk.tpcNSigmaPr()); } } } @@ -1351,157 +1517,132 @@ struct FlattenictyPikp { } template - bool isGoodV0Track(T1 const& v0, T2 const& /*track*/, int const magfield) + bool isGoodV0Track(T1 const& v0, T2 const& /*track*/, const int magfield) { const auto& posTrack = v0.template posTrack_as(); const auto& negTrack = v0.template negTrack_as(); - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelAll); - if (std::abs(posTrack.eta()) > v0SelOpt.cfgV0etamax || std::abs(negTrack.eta()) > v0SelOpt.cfgV0etamax) { - return false; - } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelEta); - if (!(selTrkV0sDaughters.IsSelected(posTrack) && selTrkV0sDaughters.IsSelected(negTrack))) { - return false; - } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelDaughters); - if (posTrack.tpcNClsFound() < v0SelOpt.cfgTPCnClsmin || negTrack.tpcNClsFound() < v0SelOpt.cfgTPCnClsmin) { + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelAll); + if (posTrack.sign() * negTrack.sign() > Cnull) { return false; } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelTPCnClsFound); + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelRejectSameSign); - if (v0SelOpt.cfgApplyV0sNclPID) { - if (posTrack.tpcNClsPID() < v0SelOpt.cfgTPCnClsPidmin || negTrack.tpcNClsPID() < v0SelOpt.cfgTPCnClsPidmin) { - return false; - } - } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelTPCnClsPID); + float posTrackPhiModn = posTrack.phi(); + float negTrackPhiModn = negTrack.phi(); + phiMod(posTrackPhiModn, magfield, posTrack.sign()); + phiMod(negTrackPhiModn, magfield, negTrack.sign()); if (v0SelOpt.cfgRejectV0sAtTPCSector) { - if (!(phiCut(posTrack, magfield, fPhiCutLow, fPhiCutHigh) && phiCut(negTrack, magfield, fPhiCutLow, fPhiCutHigh))) { + if ((posTrack.pt() >= trkSelOpt.cfgPhiCutPtMin && posTrackPhiModn < fPhiCutHigh->Eval(posTrack.pt()) && posTrackPhiModn > fPhiCutLow->Eval(posTrack.pt())) && (negTrack.pt() >= trkSelOpt.cfgPhiCutPtMin && negTrackPhiModn < fPhiCutHigh->Eval(negTrack.pt()) && negTrackPhiModn > fPhiCutLow->Eval(negTrack.pt()))) { return false; } } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelRejectV0sAtTPCSector); - if (posTrack.sign() * negTrack.sign() > Cnull) { // reject same sign pair + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelRejectV0sAtTPCSector); + // V0 topological selections + if (v0.v0cosPA() < v0SelOpt.cfgv0cospa) { return false; } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelRejectSameSign); - if (v0.dcaV0daughters() > v0SelOpt.cfgDCAv0daughter) { + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelCosPA); + if (v0.v0radius() < v0SelOpt.cfgv0Rmin || v0.v0radius() > v0SelOpt.cfgv0Rmax) { return false; } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelDCAv0daughter); - if (v0.v0cosPA() < v0SelOpt.cfgv0cospa) { + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelV0radius); + if (std::abs(v0.dcapostopv()) < v0SelOpt.cfgDCAposToPV || std::abs(v0.dcanegtopv()) < v0SelOpt.cfgDCAnegToPV) { return false; } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelCosPA); - if (v0.v0radius() < v0SelOpt.cfgv0Rmin || v0.v0radius() > v0SelOpt.cfgv0Rmax) { + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelDCAposToPV); + // selection of V0 daughters + if (!(isGoodV0DaughterTrack(posTrack) && isGoodV0DaughterTrack(negTrack))) { return false; } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelV0radius); - if (std::abs(v0.dcapostopv()) < v0SelOpt.cfgDCAposToPV || std::abs(v0.dcanegtopv()) < v0SelOpt.cfgDCAnegToPV) { + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelDaughters); + if (v0.dcaV0daughters() > v0SelOpt.cfgDCAv0daughter) { return false; } - flatchrg.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelDCAposToPV); + registryData.fill(HIST("Tracks/V0qa/hV0Sel"), v0SelDCAv0daughter); if constexpr (fillHist) { - flatchrg.fill(HIST("Tracks/V0qa/hV0Pt"), v0.pt()); - flatchrg.fill(HIST("Tracks/V0qa/hV0ArmPod"), v0.alpha(), v0.qtarm()); + registryData.fill(HIST("Tracks/V0qa/hV0Pt"), v0.pt()); + registryData.fill(HIST("Tracks/V0qa/hV0ArmPod"), v0.alpha(), v0.qtarm()); } return true; } - template - void checkNsigma(const T& track, const float mult, const float flat) + template + bool isGoodV0DaughterTrack(const T& track) { - if (std::abs(track.rapidity(o2::track::PID::getMass(pid))) > trkSelOpt.cfgRapMax) { - return; + if (track.eta() < v0SelOpt.cfgV0etamin || track.eta() > v0SelOpt.cfgV0etamax) { + return false; } - - float valTPCnsigma = -999, valTOFnsigma = -999; - switch (pid) { - case o2::track::PID::Pion: - valTPCnsigma = track.tpcNSigmaPi(); - valTOFnsigma = track.tofNSigmaPi(); - break; - case o2::track::PID::Kaon: - valTPCnsigma = track.tpcNSigmaKa(); - valTOFnsigma = track.tofNSigmaKa(); - break; - case o2::track::PID::Proton: - valTPCnsigma = track.tpcNSigmaPr(); - valTOFnsigma = track.tofNSigmaPr(); - break; - case o2::track::PID::Electron: - valTPCnsigma = track.tpcNSigmaEl(); - valTOFnsigma = track.tofNSigmaEl(); - break; - case o2::track::PID::Muon: - valTPCnsigma = track.tpcNSigmaMu(); - valTOFnsigma = track.tofNSigmaMu(); - break; - default: - valTPCnsigma = -999, valTOFnsigma = -999; - break; + if (!track.hasTPC()) { + return false; } - - if (track.sign() > Cnull) { - if (cfgStoreThnSparse) { - hThPtNsigmaTPC[pid]->Fill(track.pt(), valTPCnsigma, mult, flat); - } else { - hPtNsigmaTPC[pid]->Fill(track.pt(), valTPCnsigma); + if (track.tpcNClsCrossedRows() < v0SelOpt.cfgminNCrossedRowsTPC) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < v0SelOpt.cfgminNCrossedRowsOverFindableClustersTPC) { + return false; + } + if (v0SelOpt.cfgApplyV0sNclFound) { + if (track.tpcNClsFound() < v0SelOpt.cfgV0NclTPCMin) { + return false; } - } else { - if (cfgStoreThnSparse) { - hThPtNsigmaTPC[pid + Npart]->Fill(track.pt(), valTPCnsigma, mult, flat); - } else { - hPtNsigmaTPC[pid + Npart]->Fill(track.pt(), valTPCnsigma); + } + if (v0SelOpt.cfgApplyV0sNclPID) { + if (track.tpcNClsPID() < v0SelOpt.cfgV0NclPidTPCMin) { + return false; } } - if (!track.hasTOF()) { - return; + if (track.tpcChi2NCl() > v0SelOpt.cfgmaxChi2PerClusterTPC) { + return false; } - if (track.sign() > Cnull) { - hPtNsigmaTOF[pid]->Fill(track.pt(), valTOFnsigma); - hPtNsigmaTPCTOF[pid]->Fill(valTPCnsigma, valTOFnsigma); - } else { - hPtNsigmaTOF[pid + Npart]->Fill(track.pt(), valTOFnsigma); - hPtNsigmaTPCTOF[pid + Npart]->Fill(valTPCnsigma, valTOFnsigma); + if (v0SelOpt.cfgRequireITS && (!track.hasITS())) { + return false; + } + if (v0SelOpt.cfgRequireITS && track.itsNCls() < v0SelOpt.cfgminITSnClusters) { + return false; + } + if (track.itsChi2NCl() > v0SelOpt.cfgmaxChi2PerClusterITS) { + return false; } + return true; } template inline void fillTrackQA(T const& track) { if constexpr (fillHist) { - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPt"), track.pt()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPhi"), track.phi()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hEta"), track.eta()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hDCAXYvsPt"), track.pt(), track.dcaXY()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hDCAZvsPt"), track.pt(), track.dcaZ()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPt"), track.pt()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPhi"), track.phi()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hEta"), track.eta()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hDCAXYvsPt"), track.pt(), track.dcaXY()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hDCAZvsPt"), track.pt(), track.dcaZ()); if (track.hasTPC() && track.hasITS()) { - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCCluster"), track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hShTpcClvsPt"), track.pt(), track.tpcFractionSharedCls()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hNclTPCFoundvsPt"), track.pt(), track.tpcNClsFound()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hNClTPCPidvsPt"), track.pt(), track.tpcNClsPID()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCnClsShared"), track.tpcNClsShared()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCcrossedRows"), track.tpcNClsCrossedRows()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCcrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hChi2ITSTrkSegment"), track.itsChi2NCl()); - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hITSnCls"), track.itsNCls()); - } - - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTOFPvsBeta"), track.tpcInnerParam(), track.beta()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCCluster"), track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hShTpcClvsPt"), track.pt(), track.tpcFractionSharedCls()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hNclTPCFoundvsPt"), track.pt(), track.tpcNClsFound()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hNClTPCPidvsPt"), track.pt(), track.tpcNClsPID()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hNclTPCFoundvsEta"), track.eta(), track.tpcNClsFound()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hNClTPCPidvsEta"), track.eta(), track.tpcNClsPID()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCnClsShared"), track.tpcNClsShared()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCcrossedRows"), track.tpcNClsCrossedRows()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTPCcrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hChi2ITSTrkSegment"), track.itsChi2NCl()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hITSnCls"), track.itsNCls()); + } + + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTOFPvsBeta"), track.p(), track.beta()); if (track.beta() > trkSelOpt.cfgTOFBetaPion && track.beta() < trkSelOpt.cfgTOFBetaPion + 0.05) { // TOF pions - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTOFpi"), track.eta(), track.tpcInnerParam(), track.tpcSignal()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hTOFpi"), track.eta(), track.p(), track.tpcSignal()); } if (std::abs(track.eta()) < trkSelOpt.cfgTrkEtaMax) { if (isDCAxyWoCut(track)) { - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtVsWOcutDCA"), track.pt(), track.dcaXY()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPtVsWOcutDCA"), track.pt(), track.dcaXY()); } } } - flatchrg.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPVsPtEta"), track.tpcInnerParam(), track.pt(), track.eta()); + registryData.fill(HIST(Cprefix) + HIST(Cstatus[ft]) + HIST("hPVsPtEta"), track.p(), track.pt(), track.eta()); } template @@ -1510,27 +1651,27 @@ struct FlattenictyPikp { const float mult = getMult(collision); const float flat = fillFlat(collision); if constexpr (fillHist) { - if (track.tpcInnerParam() >= trkSelOpt.cfgMomMIPMin && track.tpcInnerParam() <= trkSelOpt.cfgMomMIPMax) { + if (track.p() >= trkSelOpt.cfgMomMIPMin && track.p() <= trkSelOpt.cfgMomMIPMax) { if (dEdx > trkSelOpt.cfgDeDxMIPMin && dEdx < trkSelOpt.cfgDeDxMIPMax) { // MIP pions if (cfgStoreThnSparse) { - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIP"), mult, flat, track.eta(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIP"), mult, flat, track.eta(), dEdx); } else { - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIP"), track.eta(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIP"), track.eta(), dEdx); } - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIPVsPhi"), track.phi(), dEdx); - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIPVsPhiVsEta"), track.phi(), dEdx, track.eta()); - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("pMIPVsPhi"), track.phi(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIPVsPhi"), track.phi(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hMIPVsPhiVsEta"), track.phi(), dEdx, track.eta()); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("pMIPVsPhi"), track.phi(), dEdx); } if (dEdx > trkSelOpt.cfgDeDxMIPMax + 10. && dEdx < trkSelOpt.cfgDeDxMIPMax + 30.) { // Plateau electrons if (std::abs(track.beta() - 1) < trkSelOpt.cfgBetaPlateuMax) { if (cfgStoreThnSparse) { - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateau"), mult, flat, track.eta(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateau"), mult, flat, track.eta(), dEdx); } else { - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateau"), track.eta(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateau"), track.eta(), dEdx); } - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateauVsPhi"), track.phi(), dEdx); - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateauVsPhiVsEta"), track.phi(), dEdx, track.eta()); - flatchrg.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("pPlateauVsPhi"), track.phi(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateauVsPhi"), track.phi(), dEdx); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("hPlateauVsPhiVsEta"), track.phi(), dEdx, track.eta()); + registryData.fill(HIST(Cprefix) + HIST(CstatCalib[ft]) + HIST(Ccharge[chrg]) + HIST("pPlateauVsPhi"), track.phi(), dEdx); } } } @@ -1541,7 +1682,7 @@ struct FlattenictyPikp { bool isGoodEvent(C const& collision) { if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelAll); + registryQC.fill(HIST("Events/hEvtSel"), evtSelAll); } if (evtSelOpt.cfgCustomTVX) { if (!collision.selection_bit(aod::evsel::kIsTriggerTVX)) { @@ -1553,56 +1694,62 @@ struct FlattenictyPikp { } } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelSel8); + registryQC.fill(HIST("Events/hEvtSel"), evtSelSel8); } if (evtSelOpt.cfgRemoveITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelNoITSROFrameBorder); + registryQC.fill(HIST("Events/hEvtSel"), evtSelNoITSROFrameBorder); } if (evtSelOpt.cfgRemoveNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelkNoTimeFrameBorder); + registryQC.fill(HIST("Events/hEvtSel"), evtSelkNoTimeFrameBorder); } if (evtSelOpt.cfgRemoveNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelkNoSameBunchPileup); + registryQC.fill(HIST("Events/hEvtSel"), evtSelkNoSameBunchPileup); } if (evtSelOpt.cfgRequireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelkIsGoodZvtxFT0vsPV); + registryQC.fill(HIST("Events/hEvtSel"), evtSelkIsGoodZvtxFT0vsPV); } if (evtSelOpt.cfgRequireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelkIsVertexITSTPC); + registryQC.fill(HIST("Events/hEvtSel"), evtSelkIsVertexITSTPC); } if (evtSelOpt.cfgRequirekIsVertexTOFmatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelkIsVertexTOFmatched); + registryQC.fill(HIST("Events/hEvtSel"), evtSelkIsVertexTOFmatched); } if (std::abs(collision.posZ()) > evtSelOpt.cfgCutVtxZ) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelVtxZ); - flatchrg.fill(HIST("Events/hVtxZ"), collision.posZ()); + registryQC.fill(HIST("Events/hEvtSel"), evtSelVtxZ); + registryQC.fill(HIST("Events/hVtxZ"), collision.posZ()); + } + if (!collision.isInelGt0()) { + return false; + } + if constexpr (fillHist) { + registryQC.fill(HIST("Events/hEvtSel"), evtSelINELgt0); } - if (evtSelOpt.cfgINELCut && !collision.isInelGt0()) { + if (rctCuts.requireRCTFlagChecker && !rctChecker(collision)) { return false; } if constexpr (fillHist) { - flatchrg.fill(HIST("Events/hEvtSel"), evtSelINELgt0); + registryQC.fill(HIST("Events/hEvtSel"), evtSelRCTFlagChecker); } return true; } @@ -1712,7 +1859,11 @@ struct FlattenictyPikp { return val; break; case MultE::CmultFT0M: - return collision.centFT0M(); + if constexpr (!isMC) { + return collision.centFT0M(); + } else { + return collision.multMCFT0C() + collision.multMCFT0A(); + } break; case MultE::CmultTPC: if constexpr (!isMC) { @@ -1784,10 +1935,10 @@ struct FlattenictyPikp { int chv0 = fv0.channel()[ich]; int chv0phi = getFV0IndexPhi(chv0); if constexpr (fillHist) { - flatchrg.fill(HIST("FV0/hFV0amp"), chv0, amplCh); - flatchrg.fill(HIST("FV0/pFV0amp"), chv0, amplCh); + registryQC.fill(HIST("FV0/hFV0amp"), chv0, amplCh); + registryQC.fill(HIST("FV0/pFV0amp"), chv0, amplCh); if (applyCalibGain) { - flatchrg.fill(HIST("FV0/hFV0ampCorr"), chv0, amplCh / fv0AmplCorr[chv0]); + registryQC.fill(HIST("FV0/hFV0ampCorr"), chv0, amplCh / fv0AmplCorr[chv0]); } } if (amplCh > Cnull) { @@ -1797,7 +1948,7 @@ struct FlattenictyPikp { if (chv0phi > Cnull) { fv0AmplitudeWoCalib[chv0phi] = amplCh; if constexpr (fillHist) { - flatchrg.fill(HIST("FV0/hFV0AmplWCalib"), ich, fv0AmplitudeWoCalib[ich]); + registryQC.fill(HIST("FV0/hFV0AmplWCalib"), ich, fv0AmplitudeWoCalib[ich]); } if (chv0 < CinnerFV0) { rhoLatticeFV0[chv0phi] += amplCh; @@ -1805,12 +1956,12 @@ struct FlattenictyPikp { rhoLatticeFV0[chv0phi] += amplCh / 2.; } if constexpr (fillHist) { - flatchrg.fill(HIST("FV0/hFV0AmplvsVtxzWoCalib"), collision.posZ(), rhoLatticeFV0[chv0phi]); + registryQC.fill(HIST("FV0/hFV0AmplvsVtxzWoCalib"), collision.posZ(), rhoLatticeFV0[chv0phi]); } if (applyCalibVtx) { rhoLatticeFV0[chv0phi] *= zVtxMap->GetBinContent(zVtxMap->GetXaxis()->FindBin(chv0phi), zVtxMap->GetYaxis()->FindBin(collision.posZ())); if constexpr (fillHist) { - flatchrg.fill(HIST("FV0/hFV0AmplvsVtxzCalib"), collision.posZ(), rhoLatticeFV0[chv0phi]); + registryQC.fill(HIST("FV0/hFV0AmplvsVtxzCalib"), collision.posZ(), rhoLatticeFV0[chv0phi]); } } } @@ -1880,10 +2031,10 @@ struct FlattenictyPikp { auto v0sPerCollision = v0s.sliceBy(perColV0s, collision.globalIndex()); v0sPerCollision.bindExternalIndices(&tracks); filldEdx(tracksPerCollision, v0sPerCollision, collision, bcs); - if (cfgFillNsigmaQAHist) { - fillNsigma(tracksPerCollision, collision); - fillNsigma(tracksPerCollision, collision); - fillNsigma(tracksPerCollision, collision); + if (cfgFillDCAxyHist) { + static_for<0, 4>([&](auto i) { + fillDCA(tracksPerCollision, collision, bcs); + }); } } } @@ -1907,8 +2058,8 @@ struct FlattenictyPikp { float maxPhi = 0; float dPhi = 0; - double etaMinFV0bins[CmaxRingsFV0] = {0.0}; - double etaMaxFV0bins[CmaxRingsFV0] = {0.0}; + float etaMinFV0bins[CmaxRingsFV0] = {0.0}; + float etaMaxFV0bins[CmaxRingsFV0] = {0.0}; for (int i = 0; i < CmaxRingsFV0; ++i) { etaMaxFV0bins[i] = CmaxEtaFV0 - i * CdEtaFV0; if (i < CmaxRingsFV0 - 1) { @@ -1920,11 +2071,18 @@ struct FlattenictyPikp { rhoLatticeFV0.fill(0); std::vector vNch; - float nCharged{0}; + float nChFV0{0}; for (const auto& mcPart : mcparts) { if (!isChrgParticle(mcPart.pdgCode())) { continue; } + if (!mcPart.isPhysicalPrimary()) { + continue; + } + if (mcPart.pt() <= 0.) { + continue; + } + auto etaMc = mcPart.eta(); auto phiMc = mcPart.phi(); @@ -1944,22 +2102,22 @@ struct FlattenictyPikp { if (etaMc >= etaMinFV0bins[ieta] && etaMc < etaMaxFV0bins[ieta] && phiMc >= minPhi && phiMc < maxPhi) { rhoLatticeFV0[isegment] += 1. / std::abs(CdEtaFV0 * dPhi); + nChFV0++; } isegment++; } } - nCharged++; } - vNch.push_back(nCharged); - auto flatFV0 = calcFlatenicity(rhoLatticeFV0); + vNch.push_back(nChFV0); + auto flatFV0 = 1. - calcFlatenicity(rhoLatticeFV0); if constexpr (fillHist) { - flatchrg.fill(HIST("ResponseGen"), vNch[0], 1. - flatFV0); - flatchrg.fill(HIST("h1flatencityFV0MCGen"), 1. - flatFV0); + registryMC.fill(HIST("Events/ResponseGen"), vNch[0], flatFV0); + registryMC.fill(HIST("Events/h1flatencityFV0MCGen"), flatFV0); } vNch.clear(); - return 1. - flatFV0; + return flatFV0; } template @@ -1968,16 +2126,16 @@ struct FlattenictyPikp { AxisSpec ptAxis{binOpt.axisPt, "#it{p}_{T} (GeV/#it{c})"}; constexpr int ChistIdx = id + pidSgn * Npart; auto idx = static_cast(id); - const std::string strID = Form("/%s/%s", (pidSgn == Cnull && id < Npart) ? "pos" : "neg", Pid[idx]); - hPtEffRec[ChistIdx] = flatchrg.add("Tracks/hPtEffRec" + strID, " ; p_{T} (GeV/c)", kTH1F, {ptAxis}); - hPtEffGen[ChistIdx] = flatchrg.add("Tracks/hPtEffGen" + strID, " ; p_{T} (GeV/c)", kTH1F, {ptAxis}); + const std::string strID = Form("/%s/%s", (pidSgn == CnullInt && id < Npart) ? "pos" : "neg", Pid[idx]); + hPtEffRec[ChistIdx] = registryMC.add("Tracks/hPtEffRec" + strID, " ; #it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); + hPtEffGen[ChistIdx] = registryMC.add("Tracks/hPtEffGen" + strID, " ; #it{p}_{T} (GeV/#it{c})", kTH1F, {ptAxis}); } template void initEfficiency() { - static_assert(pidSgn == Cnull || pidSgn == 1); - static_assert(id > Cnull || id < Npart); + static_assert(pidSgn == CnullInt || pidSgn == ConeInt); + static_assert(id > CnullInt || id < Npart); constexpr int Cidx = id + pidSgn * Npart; const TString partName = PidChrg[Cidx]; THashList* lhash = new THashList(); @@ -1999,7 +2157,7 @@ struct FlattenictyPikp { template void fillEfficiency() { - static_assert(pidSgn == Cnull || pidSgn == 1); + static_assert(pidSgn == CnullInt || pidSgn == ConeInt); constexpr int ChistIdx = id + pidSgn * Npart; const char* partName = PidChrg[ChistIdx]; THashList* lhash = static_cast(listEfficiency->FindObject(partName)); @@ -2023,64 +2181,57 @@ struct FlattenictyPikp { template void fillMCRecTrack(MyLabeledPIDTracks::iterator const& track, const float mult, const float flat) { - static_assert(pidSgn == Cnull || pidSgn == 1); + static_assert(pidSgn == CnullInt || pidSgn == ConeInt); constexpr int ChistIdx = id + pidSgn * Npart; + // LOG(debug) << "fillMCRecTrack for pidSgn '" << pidSgn << "' and id '" << static_cast(id) << " with index " << ChistIdx; const aod::McParticles::iterator& mcParticle = track.mcParticle(); const CollsGen::iterator& collision = track.collision_as(); - if (!isPID(mcParticle)) { + if (!isChrgParticle(mcParticle.pdgCode())) { return; } - flatchrg.fill(HIST("hPtOutNoEtaCut"), track.pt()); - if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { return; } - if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + if (!isPID(mcParticle)) { return; } if ((collision.has_mcCollision() && (mcParticle.mcCollisionId() != collision.mcCollisionId())) || !collision.has_mcCollision()) { if (!mcParticle.isPhysicalPrimary()) { if (mcParticle.getProcess() == CprocessIdWeak) { - hDCAxyBadCollWeak[ChistIdx]->Fill(track.pt(), track.dcaXY()); + hDCAxyRecBadCollWeak[ChistIdx]->Fill(track.pt(), track.dcaXY()); } else { - hDCAxyBadCollMat[ChistIdx]->Fill(track.pt(), track.dcaXY()); + hDCAxyRecBadCollMat[ChistIdx]->Fill(track.pt(), track.dcaXY()); } } else { - hDCAxyBadCollPrim[ChistIdx]->Fill(track.pt(), track.dcaXY()); + hDCAxyRecBadCollPrim[ChistIdx]->Fill(track.pt(), track.dcaXY()); } } - if (!isDCAxyCut(track)) { - return; - } - flatchrg.fill(HIST("hPtVsDCAxyAll"), track.pt(), track.dcaXY()); - - if (selTPCtrack(track)) { - hPtEffRec[ChistIdx]->Fill(mcParticle.pt()); - } - - if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == CprocessIdWeak) { - hPtEffRecWeak[ChistIdx]->Fill(mult, flat, track.pt()); - hPtVsDCAxyWeak[ChistIdx]->Fill(track.pt(), track.dcaXY()); - flatchrg.fill(HIST("hPtVsDCAxyWeakAll"), track.pt(), track.dcaXY()); + if (collision.has_mcCollision() && (mcParticle.mcCollisionId() == collision.mcCollisionId())) { + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == CprocessIdWeak) { + hPtEffRecGoodCollWeak[ChistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyRecGoodCollWeak[ChistIdx]->Fill(track.pt(), track.dcaXY()); + } else { + hPtEffRecGoodCollMat[ChistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyRecGoodCollMat[ChistIdx]->Fill(track.pt(), track.dcaXY()); + } } else { - hPtEffRecMat[ChistIdx]->Fill(mult, flat, track.pt()); - hPtVsDCAxyMat[ChistIdx]->Fill(track.pt(), track.dcaXY()); - flatchrg.fill(HIST("hPtVsDCAxyMatAll"), track.pt(), track.dcaXY()); + hPtEffRecGoodCollPrim[ChistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyRecGoodCollPrim[ChistIdx]->Fill(track.pt(), track.dcaXY()); } - } else { - hPtEffRecPrim[ChistIdx]->Fill(mult, flat, track.pt()); - hPtVsDCAxyPrim[ChistIdx]->Fill(track.pt(), track.dcaXY()); - flatchrg.fill(HIST("hPtVsDCAxyPrimAll"), track.pt(), track.dcaXY()); + } + if (isDCAxyCut(track)) { + hPtEffRec[ChistIdx]->Fill(mcParticle.pt()); } } template void fillMCGen(aod::McParticles::iterator const& mcParticle, const float mult, const float flat) { - static_assert(pidSgn == Cnull || pidSgn == 1); + static_assert(pidSgn == CnullInt || pidSgn == ConeInt); constexpr int ChistIdx = id + pidSgn * Npart; if (!isPID(mcParticle)) { @@ -2088,9 +2239,9 @@ struct FlattenictyPikp { } if constexpr (recoEvt) { - hPtGenRecEvt[ChistIdx]->Fill(mcParticle.pt()); + hPtGenRecEvt[ChistIdx]->Fill(mult, flat, mcParticle.pt()); if (mcParticle.isPhysicalPrimary()) { - hPtGenPrimRecEvt[ChistIdx]->Fill(mcParticle.pt()); + hPtGenPrimRecEvt[ChistIdx]->Fill(mult, flat, mcParticle.pt()); } return; } @@ -2107,249 +2258,178 @@ struct FlattenictyPikp { } } - void processSgnLoss(MCColls::iterator const& mcCollision, - CollsGenSgn const& collisions, - aod::FV0As const& /*fv0s*/, - aod::McParticles const& particles) - { - float flat; - float mult; - if (flatSelOpt.useFlatData) { - float flatRec = 999.0; - float multRec = 999.0; - for (const auto& collision : collisions) { - multRec = getMult(collision); - flatRec = fillFlat(collision); - } - flat = flatRec; - mult = multRec; - flatchrg.fill(HIST("hFlatMCGenRecColl"), flatRec); - } else { - float flatGen = fillFlatMC(particles); - flat = flatGen; - flatchrg.fill(HIST("hFlatMCGen"), flatGen); - float multGen = getMultMC(mcCollision); - mult = multGen; - } - - // Evt loss den - flatchrg.fill(HIST("hEvtMcGen"), 0.5); - if (std::abs(mcCollision.posZ()) > evtSelOpt.cfgCutVtxZ) { - return; - } - flatchrg.fill(HIST("hEvtMcGen"), 1.5); - - bool isINELgt0mc = false; - if (pwglf::isINELgtNmc(particles, 0, pdg)) { - isINELgt0mc = true; - flatchrg.fill(HIST("hEvtMcGen"), 2.5); - flatchrg.fill(HIST("hFlatGenINELgt0"), flat); - } - - // Sgn loss den - for (const auto& particle : particles) { - if (!particle.isPhysicalPrimary()) { - continue; - } - if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { - continue; - } - static_for<0, 5>([&](auto i) { - constexpr int Cidx = i.value; - if (particle.pdgCode() == PidSgn[Cidx]) { - flatchrg.fill(HIST(Cprefix) + HIST(Cspecies[Cidx]) + HIST(CpTgenPrimSgn), mult, flat, particle.pt()); - if (isINELgt0mc) { - flatchrg.fill(HIST(Cprefix) + HIST(Cspecies[Cidx]) + HIST(CpTgenPrimSgnINEL), mult, flat, particle.pt()); - } - } - }); - } - - int nRecCollINEL = 0; - int nRecCollINELgt0 = 0; - for (const auto& collision : collisions) { - // Evt split num - flatchrg.fill(HIST("hEvtMCRec"), 0.5); - if (!isGoodEvent(collision)) { - continue; - } - flatchrg.fill(HIST("hEvtMCRec"), 1.5); - - nRecCollINEL++; - - if (collision.isInelGt0() && isINELgt0mc) { - flatchrg.fill(HIST("hEvtMCRec"), 2.5); - nRecCollINELgt0++; - } - // Sgn split num - for (const auto& particle : particles) { - if (!particle.isPhysicalPrimary()) { - continue; - } - if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { - continue; - } - static_for<0, 5>([&](auto i) { - constexpr int Cidx = i.value; - if (particle.pdgCode() == PidSgn[Cidx]) { - flatchrg.fill(HIST(Cprefix) + HIST(Cspecies[Cidx]) + HIST(CpTrecCollPrimSgn), mult, flat, particle.pt()); - if (nRecCollINELgt0) { - flatchrg.fill(HIST(Cprefix) + HIST(Cspecies[Cidx]) + HIST(CpTrecCollPrimSgnINEL), mult, flat, particle.pt()); - } - } - }); - } - } - - if (nRecCollINEL < 1) { - return; - } - // Evt loss num - flatchrg.fill(HIST("hEvtMcGenRecColl"), 0.5); - if (nRecCollINELgt0 > Cnull) { - flatchrg.fill(HIST("hEvtMcGenRecColl"), 1.5); - } - - // Sgn loss num - for (const auto& particle : particles) { - if (!particle.isPhysicalPrimary()) { - continue; - } - if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { - continue; - } - static_for<0, 5>([&](auto i) { - constexpr int Cidx = i.value; - if (particle.pdgCode() == PidSgn[Cidx]) { - flatchrg.fill(HIST(Cprefix) + HIST(Cspecies[Cidx]) + HIST(CpTGenRecCollPrimSgn), mult, flat, particle.pt()); - if (nRecCollINELgt0) { - flatchrg.fill(HIST(Cprefix) + HIST(Cspecies[Cidx]) + HIST(CpTGenRecCollPrimSgnINEL), mult, flat, particle.pt()); - } - } - }); - } - } - PROCESS_SWITCH(FlattenictyPikp, processSgnLoss, "process to calcuate signal/event lossses", false); - - // using Particles = soa::Filtered; - // expressions::Filter primaries = (aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary; - - void processMCclosure(Colls::iterator const& collision, - MyPIDTracks const& tracks, - MyLabeledTracks const& mcTrackLabels, - aod::McParticles const& particles, - // Particles const& particles, - aod::FV0As const& /*fv0s*/, - aod::BCsWithTimestamps const& /*bcs*/) - { - const float multRec = getMult(collision); - const float flatRec = fillFlat(collision); - for (const auto& track : tracks) { - if (!track.has_collision()) { - continue; - } - const auto& coll = track.collision_as(); - if (trkSelOpt.cfgRejectTrkAtTPCSector) { - auto bc = coll.template bc_as(); - int currentRun = bc.runNumber(); - if (runNumber != currentRun) { - initCCDB(bc); - runNumber = currentRun; - } - } - if (!isGoodEvent(coll)) { - continue; - } - if (!isGoodTrack(track, magField)) { - continue; - } - if (!isDCAxyCut(track)) { - continue; - } - const auto& mcLabel = mcTrackLabels.iteratorAt(track.globalIndex()); - const auto& mcParticle = particles.iteratorAt(mcLabel.mcParticleId()); - - static_for<0, 4>([&](auto i) { - constexpr int Cidx = i.value; - if ((std::abs(o2::aod::pidutils::tpcNSigma(track)) < trkSelOpt.cfgNsigmaMax) && std::abs(track.rapidity(o2::track::PID::getMass(Cidx))) <= trkSelOpt.cfgRapMax) { - if (std::fabs(mcParticle.pdgCode()) == PDGs[Cidx]) { - flatchrg.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTmcClosurePrim), multRec, flatRec, track.pt()); - } - } - }); - } - } - PROCESS_SWITCH(FlattenictyPikp, processMCclosure, "process MC closure test", false); - Preslice perCollTrk = aod::track::collisionId; PresliceUnsorted perCollMcLabel = aod::mccollisionlabel::mcCollisionId; Preslice perCollMcPart = aod::mcparticle::mcCollisionId; void processMC(MCColls const& mcCollisions, CollsGen const& collisions, + aod::BCsWithTimestamps const& /*bcs*/, MyLabeledPIDTracks const& tracks, + aod::FV0As const& /*fv0s*/, aod::McParticles const& mcparticles) { - flatchrg.fill(HIST("hEvtGenRec"), 1.f, mcCollisions.size()); - flatchrg.fill(HIST("hEvtGenRec"), 2.f, collisions.size()); + registryMC.fill(HIST("Events/hEvtGenRec"), 1.f, mcCollisions.size()); + registryMC.fill(HIST("Events/hEvtGenRec"), 2.f, collisions.size()); + // Generated collisions for (const auto& mcCollision : mcCollisions) { if (mcCollision.isInelGt0()) { - flatchrg.fill(HIST("hEvtGenRec"), 3.f); + registryMC.fill(HIST("Events/hEvtGenRec"), 3.f); } - flatchrg.fill(HIST("hEvtMcGenColls"), 1); + registryMC.fill(HIST("Events/hEvtMcGenColls"), 1); + const auto groupedColls = collisions.sliceBy(perCollMcLabel, mcCollision.globalIndex()); const auto groupedParts = mcparticles.sliceBy(perCollMcPart, mcCollision.globalIndex()); const float flatMC = fillFlatMC(groupedParts); - const float multMC = getMultMC(mcCollision); - if (groupedColls.size() < 1) { // if MC events have no rec collisions + registryMC.fill(HIST("Events/hFlatMCGen"), flatMC); + + auto multMC = -1.; + if (evtSelOpt.useMultMCmidrap || multEst == 2) { // use generated Nch in ∣eta∣ < 0.8 + multMC = countPart(groupedParts); + } else { + multMC = getMultMC(mcCollision); // using McCentFT0Ms + } + + if (groupedColls.size() < ConeInt) { // if MC events have no rec collisions continue; } - flatchrg.fill(HIST("hEvtMcGenColls"), 2); + + auto maxNcontributors = -1; + auto bestCollIndex = -1; + for (const auto& collision : groupedColls) { + registryMC.fill(HIST("Events/hEvtMCRec"), 0.5); + if (!isGoodEvent(collision)) { + continue; + } + registryMC.fill(HIST("Events/hEvtMCRec"), 1.5); + if (collision.isInelGt0()) { + registryMC.fill(HIST("Events/hEvtMCRec"), 2.5); + } + const float multRecGt1 = getMult(collision); + const float flatRec = fillFlat(collision); + registryMC.fill(HIST("Events/hFlatMCRec"), flatRec); + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + } + registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0"), multRecGt1, flatRec); // Evt split den + } + registryMC.fill(HIST("Events/hEvtMcGenColls"), 2); + // + // Rec collisions w/ largest number of PV contributors for (const auto& collision : groupedColls) { - flatchrg.fill(HIST("hEvtMcGenColls"), 3); + if (trkSelOpt.cfgRejectTrkAtTPCSector || applyCalibGain || applyCalibVtx) { + auto bc = collision.bc_as(); + int currentRun = bc.runNumber(); + if (runNumber != currentRun) { + initCCDB(bc); + runNumber = currentRun; + } + } + const float multRecGt1 = getMult(collision); + const float flatRec = fillFlat(collision); + registryMC.fill(HIST("Events/hEvtMcGenColls"), 3); + if (bestCollIndex != collision.globalIndex()) { + continue; + } + registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0wRecEvt"), multRecGt1, flatRec); // Evt split num, w/ Nrec > 0 if (!isGoodEvent(collision)) { continue; } - flatchrg.fill(HIST("hEvtMcGenColls"), 4); + registryMC.fill(HIST("Events/hEvtMcGenColls"), 4); + registryMC.fill(HIST("Events/hCentVsFlatRecINELgt0wRecEvtSel"), multRecGt1, flatRec); // Evt split num, w/ Nrec > 0 + Evt. sel + registryMC.fill(HIST("Events/hNchVsCent"), multRecGt1, multMC); + registryMC.fill(HIST("Events/hNchVsFlatGenINELgt0wRecEvtSel"), multMC, flatMC); // Evt loss num, w/ Nrec > 0 + Evt. sel + // + // Rec tracks; track selection w/ DCA open (for secondaries), w/ DCA close (for efficiency) + // Obtain here: DCAxy for sec contamination, closure const auto groupedTrks = tracks.sliceBy(perCollTrk, collision.globalIndex()); for (const auto& track : groupedTrks) { - if (!isDCAxyWoCut(track)) { + if (!track.has_collision()) { continue; } - if (!track.has_mcParticle()) { - flatchrg.fill(HIST("PtOutFakes"), track.pt()); + if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { continue; } - const auto& mcParticle = track.mcParticle(); - if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + if (track.pt() < trkSelOpt.cfgTrkPtMin) { continue; } - if (!track.has_collision()) { + if (trkSelOpt.cfgApplyNcl && track.tpcNClsFound() < trkSelOpt.cfgNclTPCMin) { + continue; + } + if (trkSelOpt.cfgApplyNclPID && track.tpcNClsPID() < trkSelOpt.cfgNclPidTPCMin) { + continue; + } + float phiModn = track.phi(); + phiMod(phiModn, magField, track.sign()); + if (trkSelOpt.cfgRejectTrkAtTPCSector && (track.pt() >= trkSelOpt.cfgPhiCutPtMin && phiModn < fPhiCutHigh->Eval(track.pt()) && phiModn > fPhiCutLow->Eval(track.pt()))) { continue; } + if (!isDCAxyWoCut(track)) { + continue; + } + if (!track.has_mcParticle()) { + registryMC.fill(HIST("Tracks/hPtFakes"), multMC, flatMC, track.pt()); + continue; + } + auto particle = track.mcParticle_as(); static_for<0, 1>([&](auto pidSgn) { fillMCRecTrack(track, multMC, flatMC); fillMCRecTrack(track, multMC, flatMC); fillMCRecTrack(track, multMC, flatMC); }); + static_for<0, 4>([&](auto i) { + constexpr int Cidx = i.value; + if (std::sqrt(std::pow(std::fabs(o2::aod::pidutils::tpcNSigma(track)), 2) + std::pow(std::fabs(o2::aod::pidutils::tofNSigma(track)), 2) < trkSelOpt.cfgDcaNsigmaCombinedMax)) { + if (std::fabs(particle.pdgCode()) == PDGs[Cidx]) { + if (!particle.isPhysicalPrimary()) { + if (particle.getProcess() == CprocessIdWeak) { + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTvsDCAxyWeakAll), multMC, flatMC, track.pt(), track.dcaXY()); + } else { + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTvsDCAxyMatAll), multMC, flatMC, track.pt(), track.dcaXY()); + } + } else { + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTvsDCAxyPrimAll), multMC, flatMC, track.pt(), track.dcaXY()); + } + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTvsDCAxyAll), multMC, flatMC, track.pt(), track.dcaXY()); + } + } + }); + if (isDCAxyCut(track)) { + static_for<0, 4>([&](auto i) { + constexpr int Cidx = i.value; + if (std::fabs(particle.pdgCode()) == PDGs[Cidx]) { + if (particle.isPhysicalPrimary()) { + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CdEdxMcRecPrim), track.eta(), multMC, flatMC, track.p(), track.tpcSignal()); + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTeffPrimRecEvt), multRecGt1, flatRec, track.pt()); // Tracking eff. num + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTmcClosureRec), multMC, flatMC, track.pt()); + } + } + }); + } } if (std::abs(mcCollision.posZ()) > evtSelOpt.cfgCutVtxZ) { continue; } - - flatchrg.fill(HIST("Events/hVtxZRec"), collision.posZ()); - flatchrg.fill(HIST("Events/hVtxZGen"), mcCollision.posZ()); - - if (evtSelOpt.cfgINELCut.value) { - if (!o2::pwglf::isINELgt0mc(groupedParts, pdg)) { - continue; - } + registryMC.fill(HIST("Events/hVtxZRec"), collision.posZ()); + registryMC.fill(HIST("Events/hVtxZGen"), mcCollision.posZ()); + if (!pwglf::isINELgt0mc(groupedParts, pdg)) { + continue; } for (const auto& particle : groupedParts) { - if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.eta()) > trkSelOpt.cfgTrkEtaMax) { + continue; + } + if (particle.pt() < trkSelOpt.cfgTrkPtMin) { continue; } static_for<0, 1>([&](auto pidSgn) { @@ -2357,17 +2437,41 @@ struct FlattenictyPikp { fillMCGen(particle, multMC, flatMC); fillMCGen(particle, multMC, flatMC); }); + static_for<0, 4>([&](auto i) { + constexpr int Cidx = i.value; + if (std::fabs(particle.pdgCode()) == PDGs[Cidx]) { + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTrecCollPrimSgn), multMC, flatMC, particle.pt()); // Sgn loss num + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTeffGenPrimRecEvt), multRecGt1, flatRec, particle.pt()); // Tracking eff. den + } + }); } - } // reco collisions - - if (evtSelOpt.cfgINELCut.value) { - if (!o2::pwglf::isINELgt0mc(groupedParts, pdg)) { - continue; - } } + // Generated collisions without rec collision requirement + // Obtain here: signal loss den, event loss den, closure + // + registryMC.fill(HIST("Events/hEvtMcGen"), 0.5); + if (std::abs(mcCollision.posZ()) > evtSelOpt.cfgCutVtxZ) { + continue; + } + registryMC.fill(HIST("Events/hEvtMcGen"), 1.5); + if (!pwglf::isINELgt0mc(groupedParts, pdg)) { + continue; + } + registryMC.fill(HIST("Events/hEvtMcGen"), 2.5); + if (evtSelOpt.cfgUseInelgt0wTVX && !isInelGt0wTVX(groupedParts)) { // TVX trigger: FT0A + FT0C acceptance + continue; + } + registryMC.fill(HIST("Events/hEvtMcGen"), 3.5); + registryMC.fill(HIST("Events/hNchVsFlatGenINELgt0"), multMC, flatMC); // Evt loss den for (const auto& mcParticle : groupedParts) { - if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + if (!isChrgParticle(mcParticle.pdgCode())) { + continue; + } + if (std::abs(mcParticle.eta()) > trkSelOpt.cfgTrkEtaMax) { + continue; + } + if (mcParticle.pt() < trkSelOpt.cfgTrkPtMin) { continue; } static_for<0, 1>([&](auto pidSgn) { @@ -2375,15 +2479,23 @@ struct FlattenictyPikp { fillMCGen(mcParticle, multMC, flatMC); fillMCGen(mcParticle, multMC, flatMC); }); + static_for<0, 4>([&](auto i) { + constexpr int Cidx = i.value; + // LOG(debug) << "fillMCGen for pidSgn '" << pidSgn << "' and id '" << static_cast(id) << " with index " << ChistIdx; + if (mcParticle.isPhysicalPrimary()) { + if (std::fabs(mcParticle.pdgCode()) == PDGs[Cidx]) { + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTgenPrimSgn), multMC, flatMC, mcParticle.pt()); // Sgn loss den + registryMC.fill(HIST(Cprefix) + HIST(CspeciesAll[Cidx]) + HIST(CpTmcClosureGenPrim), multMC, flatMC, mcParticle.pt()); + } + } + }); } - static_for<0, 1>([&](auto pidSgn) { fillEfficiency(); fillEfficiency(); fillEfficiency(); }); - - } // gen collisions + } } PROCESS_SWITCH(FlattenictyPikp, processMC, "process MC", false); diff --git a/PWGLF/Tasks/GlobalEventProperties/heavyionMultiplicity.cxx b/PWGLF/Tasks/GlobalEventProperties/heavyionMultiplicity.cxx index e27973ca4c2..5dd2ed61719 100644 --- a/PWGLF/Tasks/GlobalEventProperties/heavyionMultiplicity.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/heavyionMultiplicity.cxx @@ -52,13 +52,11 @@ using namespace o2::aod::track; using namespace o2::aod::evsel; using CollisionDataTable = soa::Join; -using ColDataTablepp = soa::Join; using TrackDataTable = soa::Join; using FilTrackDataTable = soa::Filtered; using CollisionMCTrueTable = aod::McCollisions; using TrackMCTrueTable = aod::McParticles; using CollisionMCRecTable = soa::SmallGroups>; -using ColMCRecTablepp = soa::SmallGroups>; using TrackMCRecTable = soa::Join; using FilTrackMCRecTable = soa::Filtered; using V0TrackCandidates = soa::Join; @@ -87,6 +85,7 @@ enum { kSpOther, kSpStrangeDecay, kBkg, + kFake, kSpNotPrimary, kSpAll, kSpeciesend @@ -128,7 +127,7 @@ static constexpr TrackSelectionFlags::flagtype TrackSelectionDca = static constexpr TrackSelectionFlags::flagtype TrackSelectionDcaxyOnly = TrackSelectionFlags::kDCAxy; -AxisSpec axisEvent{10, 0.5, 10.5, "#Event", "EventAxis"}; +AxisSpec axisEvent{15, 0.5, 15.5, "#Event", "EventAxis"}; AxisSpec axisVtxZ{40, -20, 20, "Vertex Z", "VzAxis"}; AxisSpec axisEta{40, -2, 2, "#eta", "EtaAxis"}; AxisSpec axisEtaExtended{100, -5, 5, "#eta", "EtaAxisExtended"}; @@ -157,14 +156,22 @@ struct HeavyionMultiplicity { Configurable etaRange{"etaRange", 1.0f, "Eta range to consider"}; Configurable vtxRange{"vtxRange", 10.0f, "Vertex Z range to consider"}; Configurable dcaZ{"dcaZ", 0.2f, "Custom DCA Z cut (ignored if negative)"}; - Configurable v0radiusCut{"v0radiusCut", 1.2f, "RadiusCut"}; - Configurable dcapostopvCut{"dcapostopvCut", 0.05f, "dcapostopvCut"}; - Configurable dcanegtopvCut{"dcanegtopvCut", 0.05f, "dcanegtopvCut"}; - Configurable v0cospaCut{"v0cospaCut", 0.995f, "v0cospaCut"}; - Configurable dcav0daughtercut{"dcav0daughtercut", 1.0f, "dcav0daughtercut"}; - Configurable minTPCnClsCut{"minTPCnClsCut", 50.0f, "minTPCnClsCut"}; - Configurable nSigmaTpcCut{"nSigmaTpcCut", 5.0f, "nSigmaTpcCut"}; - Configurable v0etaCut{"v0etaCut", 0.9f, "v0etaCut"}; + Configurable v0radiusK0SCut{"v0radiusK0SCut", 1.2f, "K0S RadiusCut"}; + Configurable dcapostopvK0SCut{"dcapostopvK0SCut", 0.05f, "K0S dcapostopvCut"}; + Configurable dcanegtopvK0SCut{"dcanegtopvK0SCut", 0.05f, "K0S dcanegtopvCut"}; + Configurable v0cospaK0SCut{"v0cospaK0SCut", 0.995f, "K0S v0cospaCut"}; + Configurable dcav0daughterK0Scut{"dcav0daughterK0Scut", 1.0f, "K0S dcav0daughtercut"}; + Configurable minTPCnClsK0SCut{"minTPCnClsK0SCut", 50.0f, "K0S minTPCnClsCut"}; + Configurable nSigmaTpcK0SCut{"nSigmaTpcK0SCut", 5.0f, "K0S nSigmaTpcCut"}; + Configurable v0etaK0SCut{"v0etaK0SCut", 0.9f, "K0S v0etaCut"}; + Configurable v0radiusLambdaCut{"v0radiusLambdaCut", 1.2f, "Lambda RadiusCut"}; + Configurable dcapostopvLambdaCut{"dcapostopvLambdaCut", 0.05f, "Lambda dcapostopvCut"}; + Configurable dcanegtopvLambdaCut{"dcanegtopvLambdaCut", 0.05f, "Lambda dcanegtopvCut"}; + Configurable v0cospaLambdaCut{"v0cospaLambdaCut", 0.995f, "Lambda v0cospaCut"}; + Configurable dcav0daughterLambdacut{"dcav0daughterLambdacut", 1.0f, "Lambda dcav0daughtercut"}; + Configurable minTPCnClsLambdaCut{"minTPCnClsLambdaCut", 50.0f, "Lambda minTPCnClsCut"}; + Configurable nSigmaTpcLambdaCut{"nSigmaTpcLambdaCut", 5.0f, "Lambda nSigmaTpcCut"}; + Configurable v0etaLambdaCut{"v0etaLambdaCut", 0.9f, "Lambda v0etaCut"}; Configurable extraphicut1{"extraphicut1", 3.07666f, "Extra Phi cut 1"}; Configurable extraphicut2{"extraphicut2", 3.12661f, "Extra Phi cut 2"}; Configurable extraphicut3{"extraphicut3", 0.03f, "Extra Phi cut 3"}; @@ -182,15 +189,14 @@ struct HeavyionMultiplicity { ConfigurableAxis binsMult{"binsMult", {500, 0.0f, +500.0f}, ""}; ConfigurableAxis binsDCA{"binsDCA", {500, -10.0f, 10.0f}, ""}; + Configurable isApplyTFcut{"isApplyTFcut", true, "Enable TimeFrameBorder cut"}; + Configurable isApplyITSROcut{"isApplyITSROcut", true, "Enable ITS ReadOutFrameBorder cut"}; Configurable isApplySameBunchPileup{"isApplySameBunchPileup", true, "Enable SameBunchPileup cut"}; Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", true, "Enable GoodZvtxFT0vsPV cut"}; - Configurable isApplyExtraCorrCut{"isApplyExtraCorrCut", false, "Enable extra NPVtracks vs FTOC correlation cut"}; - Configurable isApplyExtraPhiCut{"isApplyExtraPhiCut", false, "Enable extra phi cut"}; - Configurable npvTracksCut{"npvTracksCut", 1.0f, "Apply extra NPVtracks cut"}; - Configurable ft0cCut{"ft0cCut", 1.0f, "Apply extra FT0C cut"}; Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", true, "Enable NoCollInTimeRangeStandard cut"}; Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, "Enable NoCollInRofStandard cut"}; Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, "Enable NoHighMultCollInPrevRof cut"}; + Configurable isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"}; Configurable isApplyFT0CbasedOccupancy{"isApplyFT0CbasedOccupancy", false, "Enable FT0CbasedOccupancy cut"}; Configurable isApplyCentFT0C{"isApplyCentFT0C", true, "Centrality based on FT0C"}; Configurable isApplyCentFV0A{"isApplyCentFV0A", false, "Centrality based on FV0A"}; @@ -199,8 +205,8 @@ struct HeavyionMultiplicity { Configurable isApplyCentFT0M{"isApplyCentFT0M", false, "Centrality based on FT0A + FT0C"}; Configurable isApplyCentNGlobal{"isApplyCentNGlobal", false, "Centrality based on global tracks"}; Configurable isApplyCentMFT{"isApplyCentMFT", false, "Centrality based on MFT tracks"}; - Configurable isApplySplitRecCol{"isApplySplitRecCol", false, "Split MC reco collisions"}; - Configurable isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"}; + Configurable isApplyTVX{"isApplyTVX", false, "Enable TVX trigger sel"}; + Configurable isApplyExtraPhiCut{"isApplyExtraPhiCut", false, "Enable extra phi cut"}; void init(InitContext const&) { @@ -223,14 +229,15 @@ struct HeavyionMultiplicity { auto hstat = histos.get(HIST("EventHist")); auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All events"); - x->SetBinLabel(2, "sel8"); - x->SetBinLabel(3, "kNoSameBunchPileup"); // reject collisions in case of pileup with another collision in the same foundBC - x->SetBinLabel(4, "kIsGoodZvtxFT0vsPV"); // small difference between z-vertex from PV and from FT0 - x->SetBinLabel(5, "ApplyExtraCorrCut"); - x->SetBinLabel(6, "ApplyNoCollInTimeRangeStandard"); - x->SetBinLabel(7, "ApplyNoCollInRofStandard"); - x->SetBinLabel(8, "ApplyNoHighMultCollInPrevRof"); - x->SetBinLabel(9, "INEL > 0"); + x->SetBinLabel(2, "kIsTriggerTVX"); + x->SetBinLabel(3, "kNoTimeFrameBorder"); + x->SetBinLabel(4, "kNoITSROFrameBorder"); + x->SetBinLabel(5, "kNoSameBunchPileup"); // reject collisions in case of pileup with another collision in the same foundBC + x->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); // small difference between z-vertex from PV and from FT0 + x->SetBinLabel(7, "ApplyNoCollInTimeRangeStandard"); + x->SetBinLabel(8, "ApplyNoCollInRofStandard"); + x->SetBinLabel(9, "ApplyNoHighMultCollInPrevRof"); + x->SetBinLabel(10, "INEL > 0"); if (doprocessData) { histos.add("hdcaxy", "dca to pv in the xy plane", kTH1D, {dcaAxis}, false); @@ -242,7 +249,7 @@ struct HeavyionMultiplicity { histos.add("hdatadndetaMB", "hdatadndetaMB", kTHnSparseD, {axisVtxZ, axisEta, axisPhi}, false); } - if (doprocessMonteCarlo || doprocessMCpTefficiency || doprocessMCcheckFakeTracks) { + if (doprocessMonteCarlo || doprocessMCcheckFakeTracks) { histos.add("CentPercentileMCRecHist", "CentPercentileMCRecHist", kTH1D, {axisCent}, false); histos.add("hmczvtxcent", "hmczvtxcent", kTH3D, {axisVtxZ, centAxis, axisOccupancy}, false); } @@ -257,11 +264,6 @@ struct HeavyionMultiplicity { histos.add("hmcgendndetaMB", "hmcgendndetaMB", kTHnSparseD, {axisVtxZ, axisEta, axisPhi, axisSpecies}, false); } - if (doprocessMCpTefficiency) { - histos.add("hmcrecdndpt", "hmcrecdndpt", kTHnSparseD, {centAxis, axisOccupancy, axisTrackType, axisPt}, false); - histos.add("hmcgendndpt", "hmcgendndpt", kTHnSparseD, {centAxis, axisPt, axisGenPtVary}, false); - } - if (doprocessMCcheckFakeTracks) { histos.add("hTracksCount", "hTracksCount", kTHnSparseD, {centAxis, axisTracks}, false); auto htrack = histos.get(HIST("hTracksCount")); @@ -291,21 +293,6 @@ struct HeavyionMultiplicity { histos.add("AntiLambdaCentEtaMass", "AntiLambdaCentEtaMass", kTH3D, {centAxis, axisEta, axisMassLambda}, false); } - if (doprocessppData) { - histos.add("MultPercentileHist", "MultPercentileHist", kTH1D, {axisCent}, false); - histos.add("hdatazvtxmultpp", "hdatazvtxmultpp", kTH2D, {axisVtxZ, centAxis}, false); - histos.add("PhiVsEtaHistpp", "PhiVsEtaHistpp", kTH2D, {axisPhi2, axisEta}, false); - histos.add("hdatadndetapp", "hdatadndetapp", kTHnSparseD, {axisVtxZ, centAxis, axisEta, axisPhi, axisTrackType}, false); - } - - if (doprocessppMonteCarlo) { - histos.add("MultPercentileMCRecHist", "MultPercentileMCRecHist", kTH1D, {axisCent}, false); - histos.add("hmczvtxmultpp", "hmczvtxmultpp", kTH2D, {axisVtxZ, centAxis}, false); - histos.add("MCrecPhiVsEtaHistpp", "MCrecPhiVsEtaHistpp", kTH2D, {axisPhi2, axisEta}, false); - histos.add("hmcrecdndetapp", "hmcrecdndetapp", kTHnSparseD, {axisVtxZ, centAxis, axisEta, axisPhi, axisSpecies, axisTrackType}, false); - histos.add("hmcgendndetapp", "hmcgendndetapp", kTHnSparseD, {axisVtxZ, centAxis, axisEta, axisPhi, axisSpecies, axisGenPtVary}, false); - } - if (doprocessGen) { histos.add("MultBarrelEta10_vs_FT0A", "MultBarrelEta10_vs_FT0A", kTH2F, {axisMult, axisFt0aMult}, true); histos.add("MultBarrelEta10_vs_FT0C", "MultBarrelEta10_vs_FT0C", kTH2F, {axisMult, axisFt0cMult}, true); @@ -334,6 +321,10 @@ struct HeavyionMultiplicity { histos.add("hMultEta05vsCentrRec", "multiplicity in eta<0.5 of selected MC events vs centrality", kTH2F, {axisCent, multAxis}); histos.add("hgendndetaVsMultEta05BeforeEvtSel", "hgendndetaBeforeEvtSel vs multiplicity in eta<0.5", kTH2F, {axisEta, multAxis}); histos.add("hgendndetaVsMultEta05AfterEvtSel", "hgendndetaAfterEvtSel vs multiplicity in eta<0.5", kTH2F, {axisEta, multAxis}); + histos.add("hImpactParameterSplit", "Impact parameter of selected and split MC events", kTH1F, {impactParAxis}); + histos.add("hMultEta05Split", "multiplicity in eta<0.5 of selected and split MC events", kTH1F, {multAxis}); + histos.add("hMultSplit", "multiplicity of selected and split MC events", kTH1F, {axisFt0cMult}); + histos.add("hMultvsCentrSplit", "multiplicity of selected and split MC events vs centrality ", kTH2F, {axisCent, axisFt0cMult}); histos.add("hMultGen", "multiplicity of generated MC events", kTH1F, {axisFt0cMult}); histos.add("hMultRec", "multiplicity of selected MC events", kTH1F, {axisFt0cMult}); @@ -372,46 +363,42 @@ struct HeavyionMultiplicity { bool isEventSelected(CheckCol const& col) { histos.fill(HIST("EventHist"), 1); - - if (!col.sel8()) { + if (!col.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { return false; } histos.fill(HIST("EventHist"), 2); - - if (isApplySameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (isApplyTFcut && !col.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { return false; } histos.fill(HIST("EventHist"), 3); - - if (isApplyGoodZvtxFT0vsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (isApplyITSROcut && !col.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { return false; } histos.fill(HIST("EventHist"), 4); - - if (isApplyExtraCorrCut && col.multNTracksPV() > npvTracksCut && col.multFT0C() < (10 * col.multNTracksPV() - ft0cCut)) { + if (isApplySameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } histos.fill(HIST("EventHist"), 5); - - if (isApplyNoCollInTimeRangeStandard && !col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (isApplyGoodZvtxFT0vsPV && !col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } histos.fill(HIST("EventHist"), 6); - - if (isApplyNoCollInRofStandard && !col.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (isApplyNoCollInTimeRangeStandard && !col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } histos.fill(HIST("EventHist"), 7); - - if (isApplyNoHighMultCollInPrevRof && !col.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (isApplyNoCollInRofStandard && !col.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return false; } histos.fill(HIST("EventHist"), 8); - - if (isApplyInelgt0 && !col.isInelGt0()) { + if (isApplyNoHighMultCollInPrevRof && !col.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return false; } histos.fill(HIST("EventHist"), 9); + if (isApplyInelgt0 && !col.isInelGt0()) { + return false; + } + histos.fill(HIST("EventHist"), 10); return true; } @@ -449,8 +436,9 @@ struct HeavyionMultiplicity { auto cent = -1; if (isApplyCentFT0C) { cent = col.multMCFT0C(); - } - if (isApplyCentFV0A) { + } else if (isApplyCentFT0M) { + cent = col.multMCFT0C() + col.multMCFT0A(); + } else if (isApplyCentFV0A) { cent = col.multMCFV0A(); } return cent; @@ -562,17 +550,15 @@ struct HeavyionMultiplicity { histos.fill(HIST("NPVtracks_vs_GlobalMult"), cols.multNTracksPV(), nchTracks); } - void processMonteCarlo(CollisionMCTrueTable::iterator const&, CollisionMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) + void processMonteCarlo(soa::Join::iterator const& mcCollision, CollisionMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { - - if (isApplySplitRecCol && (RecCols.size() == 0 || RecCols.size() > 1)) { - return; - } - for (const auto& RecCol : RecCols) { if (!isEventSelected(RecCol)) { continue; } + if (RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } histos.fill(HIST("VtxZHist"), RecCol.posZ()); histos.fill(HIST("CentPercentileMCRecHist"), selColCent(RecCol)); histos.fill(HIST("hmczvtxcent"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol)); @@ -582,6 +568,15 @@ struct HeavyionMultiplicity { if (!isTrackSelected(Rectrack)) { continue; } + if (!Rectrack.has_mcParticle()) { + histos.fill(HIST("hmcrecdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(kBkg), kGlobalplusITS); + histos.fill(HIST("hmcrecdndetaMB"), RecCol.posZ(), Rectrack.eta(), Rectrack.phi(), static_cast(kBkg)); + continue; + } + auto mcpart = Rectrack.mcParticle(); + if (RecCol.mcCollisionId() != mcpart.mcCollisionId()) { + continue; + } histos.fill(HIST("hmcdcaxy"), Rectrack.dcaXY()); histos.fill(HIST("hmcdcaz"), Rectrack.dcaZ()); histos.fill(HIST("MCrecPhiVsEtaHist"), Rectrack.phi(), Rectrack.eta()); @@ -593,43 +588,37 @@ struct HeavyionMultiplicity { histos.fill(HIST("hmcrecdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(kSpAll), kITSonly); } - if (Rectrack.has_mcParticle()) { - int pid = kBkg; - auto mcpart = Rectrack.template mcParticle_as(); - if (mcpart.isPhysicalPrimary()) { - switch (std::abs(mcpart.pdgCode())) { - case PDG_t::kPiPlus: - pid = kSpPion; - break; - case PDG_t::kKPlus: - pid = kSpKaon; - break; - case PDG_t::kProton: - pid = kSpProton; - break; - default: - pid = kSpOther; - break; - } - } else { - pid = kSpNotPrimary; - } - if (mcpart.has_mothers()) { - auto mcpartMother = mcpart.template mothers_as().front(); - if (mcpartMother.pdgCode() == PDG_t::kK0Short || std::abs(mcpartMother.pdgCode()) == PDG_t::kLambda0) { - pid = kSpStrangeDecay; - } + int pid = kFake; + if (mcpart.isPhysicalPrimary()) { + switch (std::abs(mcpart.pdgCode())) { + case PDG_t::kPiPlus: + pid = kSpPion; + break; + case PDG_t::kKPlus: + pid = kSpKaon; + break; + case PDG_t::kProton: + pid = kSpProton; + break; + default: + pid = kSpOther; + break; } - if (find(mclabels.begin(), mclabels.end(), Rectrack.mcParticleId()) != mclabels.end()) { - pid = kBkg; - } - mclabels.push_back(Rectrack.mcParticleId()); - histos.fill(HIST("hmcrecdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(pid), kGlobalplusITS); - histos.fill(HIST("hmcrecdndetaMB"), RecCol.posZ(), Rectrack.eta(), Rectrack.phi(), static_cast(pid)); } else { - histos.fill(HIST("hmcrecdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(kBkg), kGlobalplusITS); - histos.fill(HIST("hmcrecdndetaMB"), RecCol.posZ(), Rectrack.eta(), Rectrack.phi(), static_cast(kBkg)); + pid = kSpNotPrimary; + } + if (mcpart.has_mothers()) { + auto mcpartMother = mcpart.template mothers_as().front(); + if (mcpartMother.pdgCode() == PDG_t::kK0Short || std::abs(mcpartMother.pdgCode()) == PDG_t::kLambda0) { + pid = kSpStrangeDecay; + } + } + if (find(mclabels.begin(), mclabels.end(), Rectrack.mcParticleId()) != mclabels.end()) { + pid = kFake; } + mclabels.push_back(Rectrack.mcParticleId()); + histos.fill(HIST("hmcrecdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(pid), kGlobalplusITS); + histos.fill(HIST("hmcrecdndetaMB"), RecCol.posZ(), Rectrack.eta(), Rectrack.phi(), static_cast(pid)); } // track (mcrec) loop for (const auto& particle : GenParticles) { @@ -645,7 +634,6 @@ struct HeavyionMultiplicity { histos.fill(HIST("hmcgendndeta"), RecCol.posZ(), selColCent(RecCol), particle.eta(), particle.phi(), static_cast(kSpAll), kGenpTup); histos.fill(HIST("hmcgendndeta"), RecCol.posZ(), selColCent(RecCol), particle.eta(), particle.phi(), static_cast(kSpAll), kGenpTdown); } - int pid = 0; switch (std::abs(particle.pdgCode())) { case PDG_t::kPiPlus: @@ -667,53 +655,6 @@ struct HeavyionMultiplicity { } // collision loop } - void processMCpTefficiency(CollisionMCTrueTable::iterator const&, CollisionMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) - { - for (const auto& RecCol : RecCols) { - if (!isEventSelected(RecCol)) { - continue; - } - if (std::abs(RecCol.posZ()) >= vtxRange) { - continue; - } - histos.fill(HIST("VtxZHist"), RecCol.posZ()); - histos.fill(HIST("CentPercentileMCRecHist"), selColCent(RecCol)); - histos.fill(HIST("hmczvtxcent"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol)); - - auto recTracksPart = RecTracks.sliceBy(perCollision, RecCol.globalIndex()); - for (const auto& Rectrack : recTracksPart) { - if (std::abs(Rectrack.eta()) >= etaRange) { - continue; - } - if (Rectrack.has_mcParticle()) { - auto mcpart = Rectrack.mcParticle(); - if (mcpart.isPhysicalPrimary()) { - histos.fill(HIST("hmcrecdndpt"), selColCent(RecCol), selColOccu(RecCol), kGlobalplusITS, mcpart.pt()); - if (Rectrack.hasTPC()) { - histos.fill(HIST("hmcrecdndpt"), selColCent(RecCol), selColOccu(RecCol), kGlobalonly, mcpart.pt()); - } else { - histos.fill(HIST("hmcrecdndpt"), selColCent(RecCol), selColOccu(RecCol), kITSonly, mcpart.pt()); - } - } - } - } - - for (const auto& particle : GenParticles) { - if (!isGenTrackSelected(particle)) { - continue; - } - histos.fill(HIST("hmcgendndpt"), selColCent(RecCol), particle.pt(), kNoGenpTVar); - if (particle.pt() < KminPtCut) { - histos.fill(HIST("hmcgendndpt"), selColCent(RecCol), particle.pt(), kGenpTup, -10.0 * particle.pt() + 2); - histos.fill(HIST("hmcgendndpt"), selColCent(RecCol), particle.pt(), kGenpTdown, 5.0 * particle.pt() + 0.5); - } else { - histos.fill(HIST("hmcgendndpt"), selColCent(RecCol), particle.pt(), kGenpTup); - histos.fill(HIST("hmcgendndpt"), selColCent(RecCol), particle.pt(), kGenpTdown); - } - } - } - } - void processMCcheckFakeTracks(CollisionMCTrueTable::iterator const&, CollisionMCRecTable const& RecCols, FilTrackMCRecTable const& RecTracks) { for (const auto& RecCol : RecCols) { @@ -764,157 +705,20 @@ struct HeavyionMultiplicity { for (const auto& v0track : v0data) { auto v0pTrack = v0track.template posTrack_as(); auto v0nTrack = v0track.template negTrack_as(); - if (std::abs(v0pTrack.eta()) > v0etaCut || std::abs(v0nTrack.eta()) > v0etaCut) { - continue; - } - if (v0pTrack.tpcNClsFound() < minTPCnClsCut) { - continue; - } - if (v0nTrack.tpcNClsFound() < minTPCnClsCut) { - continue; - } - if (std::abs(v0pTrack.tpcNSigmaPi()) > nSigmaTpcCut) { - continue; - } - if (std::abs(v0nTrack.tpcNSigmaPi()) > nSigmaTpcCut) { - continue; - } - if (std::abs(v0pTrack.tpcNSigmaPr()) > nSigmaTpcCut) { - continue; - } - if (std::abs(v0nTrack.tpcNSigmaPr()) > nSigmaTpcCut) { - continue; - } - if (std::abs(v0track.dcapostopv()) < dcapostopvCut || std::abs(v0track.dcanegtopv()) < dcanegtopvCut || v0track.v0radius() < v0radiusCut || v0track.v0cosPA() < v0cospaCut || std::abs(v0track.dcaV0daughters()) > dcav0daughtercut) { - continue; - } - histos.fill(HIST("K0sCentEtaMass"), selColCent(cols), v0track.eta(), v0track.mK0Short()); - histos.fill(HIST("LambdaCentEtaMass"), selColCent(cols), v0track.eta(), v0track.mLambda()); - histos.fill(HIST("AntiLambdaCentEtaMass"), selColCent(cols), v0track.eta(), v0track.mAntiLambda()); - } - } - - void processppData(ColDataTablepp::iterator const& cols, FilTrackDataTable const& tracks) - { - if (!isEventSelected(cols)) { - return; - } - - histos.fill(HIST("VtxZHist"), cols.posZ()); - histos.fill(HIST("MultPercentileHist"), cols.centFT0M()); - histos.fill(HIST("hdatazvtxmultpp"), cols.posZ(), cols.centFT0M()); - - for (const auto& track : tracks) { - if (!isTrackSelected(track)) { - continue; - } - histos.fill(HIST("PhiVsEtaHistpp"), track.phi(), track.eta()); - histos.fill(HIST("hdatadndetapp"), cols.posZ(), cols.centFT0M(), track.eta(), track.phi(), kGlobalplusITS); - if (track.hasTPC()) { - histos.fill(HIST("hdatadndetapp"), cols.posZ(), cols.centFT0M(), track.eta(), track.phi(), kGlobalonly); - } else { - histos.fill(HIST("hdatadndetapp"), cols.posZ(), cols.centFT0M(), track.eta(), track.phi(), kITSonly); - } - } // track loop - } - - void processppMonteCarlo(CollisionMCTrueTable::iterator const&, ColMCRecTablepp const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) - { - if (isApplySplitRecCol && (RecCols.size() == 0 || RecCols.size() > 1)) { - return; - } + if (std::abs(v0pTrack.eta()) <= v0etaK0SCut && std::abs(v0nTrack.eta()) <= v0etaK0SCut && v0pTrack.tpcNClsFound() >= minTPCnClsK0SCut && v0nTrack.tpcNClsFound() >= minTPCnClsK0SCut && std::abs(v0track.dcapostopv()) >= dcapostopvK0SCut && std::abs(v0track.dcanegtopv()) >= dcanegtopvK0SCut && v0track.v0radius() >= v0radiusK0SCut && v0track.v0cosPA() >= v0cospaK0SCut && std::abs(v0track.dcaV0daughters()) <= dcav0daughterK0Scut && std::abs(v0pTrack.tpcNSigmaPi()) <= nSigmaTpcK0SCut && std::abs(v0nTrack.tpcNSigmaPi()) <= nSigmaTpcK0SCut) { - for (const auto& RecCol : RecCols) { - if (!isEventSelected(RecCol)) { - continue; + histos.fill(HIST("K0sCentEtaMass"), selColCent(cols), v0track.eta(), v0track.mK0Short()); } - auto recTracksPart = RecTracks.sliceBy(perCollision, RecCol.globalIndex()); - std::vector mclabels; - - histos.fill(HIST("VtxZHist"), RecCol.posZ()); - histos.fill(HIST("MultPercentileMCRecHist"), RecCol.centFT0M()); - histos.fill(HIST("hmczvtxmultpp"), RecCol.posZ(), RecCol.centFT0M()); + if (std::abs(v0pTrack.eta()) <= v0etaLambdaCut && std::abs(v0nTrack.eta()) <= v0etaLambdaCut && v0pTrack.tpcNClsFound() >= minTPCnClsLambdaCut && v0nTrack.tpcNClsFound() >= minTPCnClsLambdaCut && std::abs(v0track.dcapostopv()) >= dcapostopvLambdaCut && std::abs(v0track.dcanegtopv()) >= dcanegtopvLambdaCut && v0track.v0radius() >= v0radiusLambdaCut && v0track.v0cosPA() >= v0cospaLambdaCut && std::abs(v0track.dcaV0daughters()) <= dcav0daughterLambdacut) { - for (const auto& Rectrack : recTracksPart) { - if (!isTrackSelected(Rectrack)) { - continue; - } - histos.fill(HIST("MCrecPhiVsEtaHistpp"), Rectrack.phi(), Rectrack.eta()); - histos.fill(HIST("hmcrecdndetapp"), RecCol.posZ(), RecCol.centFT0M(), Rectrack.eta(), Rectrack.phi(), static_cast(kSpAll), kGlobalplusITS); - if (Rectrack.hasTPC()) { - histos.fill(HIST("hmcrecdndetapp"), RecCol.posZ(), RecCol.centFT0M(), Rectrack.eta(), Rectrack.phi(), static_cast(kSpAll), kGlobalonly); - } else { - histos.fill(HIST("hmcrecdndetapp"), RecCol.posZ(), RecCol.centFT0M(), Rectrack.eta(), Rectrack.phi(), static_cast(kSpAll), kITSonly); + if (std::abs(v0pTrack.tpcNSigmaPr()) <= nSigmaTpcLambdaCut && std::abs(v0nTrack.tpcNSigmaPi()) <= nSigmaTpcLambdaCut) { + histos.fill(HIST("LambdaCentEtaMass"), selColCent(cols), v0track.eta(), v0track.mLambda()); } - - if (Rectrack.has_mcParticle()) { - int pid = kBkg; - auto mcpart = Rectrack.template mcParticle_as(); - if (mcpart.isPhysicalPrimary()) { - switch (std::abs(mcpart.pdgCode())) { - case PDG_t::kPiPlus: - pid = kSpPion; - break; - case PDG_t::kKPlus: - pid = kSpKaon; - break; - case PDG_t::kProton: - pid = kSpProton; - break; - default: - pid = kSpOther; - break; - } - } else { - pid = kSpNotPrimary; - } - if (mcpart.has_mothers()) { - auto mcpartMother = mcpart.template mothers_as().front(); - if (mcpartMother.pdgCode() == PDG_t::kK0Short || std::abs(mcpartMother.pdgCode()) == PDG_t::kLambda0) { - pid = kSpStrangeDecay; - } - } - if (find(mclabels.begin(), mclabels.end(), Rectrack.mcParticleId()) != mclabels.end()) { - pid = kBkg; - } - mclabels.push_back(Rectrack.mcParticleId()); - histos.fill(HIST("hmcrecdndetapp"), RecCol.posZ(), RecCol.centFT0M(), Rectrack.eta(), Rectrack.phi(), static_cast(pid), kGlobalplusITS); - } else { - histos.fill(HIST("hmcrecdndetapp"), RecCol.posZ(), RecCol.centFT0M(), Rectrack.eta(), Rectrack.phi(), static_cast(kBkg), kGlobalplusITS); + if (std::abs(v0pTrack.tpcNSigmaPi()) <= nSigmaTpcLambdaCut && std::abs(v0nTrack.tpcNSigmaPr()) <= nSigmaTpcLambdaCut) { + histos.fill(HIST("AntiLambdaCentEtaMass"), selColCent(cols), v0track.eta(), v0track.mAntiLambda()); } - } // track (mcrec) loop - - for (const auto& particle : GenParticles) { - if (!isGenTrackSelected(particle)) { - continue; - } - histos.fill(HIST("hmcgendndetapp"), RecCol.posZ(), RecCol.centFT0M(), particle.eta(), particle.phi(), static_cast(kSpAll), kNoGenpTVar); - if (particle.pt() < KminPtCut) { - histos.fill(HIST("hmcgendndetapp"), RecCol.posZ(), RecCol.centFT0M(), particle.eta(), particle.phi(), static_cast(kSpAll), kGenpTup, -10.0 * particle.pt() + 2); - histos.fill(HIST("hmcgendndetapp"), RecCol.posZ(), RecCol.centFT0M(), particle.eta(), particle.phi(), static_cast(kSpAll), kGenpTdown, 5.0 * particle.pt() + 0.5); - } else { - histos.fill(HIST("hmcgendndetapp"), RecCol.posZ(), RecCol.centFT0M(), particle.eta(), particle.phi(), static_cast(kSpAll), kGenpTup); - histos.fill(HIST("hmcgendndetapp"), RecCol.posZ(), RecCol.centFT0M(), particle.eta(), particle.phi(), static_cast(kSpAll), kGenpTdown); - } - - int pid = 0; - switch (std::abs(particle.pdgCode())) { - case PDG_t::kPiPlus: - pid = kSpPion; - break; - case PDG_t::kKPlus: - pid = kSpKaon; - break; - case PDG_t::kProton: - pid = kSpProton; - break; - default: - pid = kSpOther; - break; - } - histos.fill(HIST("hmcgendndetapp"), RecCol.posZ(), RecCol.centFT0M(), particle.eta(), particle.phi(), static_cast(pid), kNoGenpTVar); - } // track (mcgen) loop - } // collision loop + } + } } void processGen(aod::McCollisions::iterator const&, aod::McParticles const& GenParticles) @@ -961,6 +765,11 @@ struct HeavyionMultiplicity { if (isApplyInelgt0 && !mcCollision.isInelGt0()) { return; } + + if (isApplyTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + if (std::abs(mcCollision.posZ()) >= vtxRange) { return; } @@ -986,6 +795,12 @@ struct HeavyionMultiplicity { if (std::abs(RecCol.posZ()) >= vtxRange) { continue; } + + histos.fill(HIST("hImpactParameterSplit"), mcCollision.impactParameter()); + histos.fill(HIST("hMultEta05Split"), mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("hMultSplit"), selColMultMC(mcCollision)); + histos.fill(HIST("hMultvsCentrSplit"), selColCent(RecCol), selColMultMC(mcCollision)); + if (RecCol.numContrib() <= numcontributors) { continue; } else { @@ -1110,44 +925,48 @@ struct HeavyionMultiplicity { if (!isTrackSelected(Rectrack)) { continue; } + if (!Rectrack.has_mcParticle()) { + histos.fill(HIST("hRecMCdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(kRecoBkg)); + continue; + } + auto mcpart = Rectrack.mcParticle(); + if (RecCol.mcCollisionId() != mcpart.mcCollisionId()) { + continue; + } histos.fill(HIST("hRecMCphivseta"), Rectrack.phi(), Rectrack.eta()); histos.fill(HIST("hRecMCdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(kRecoAll)); - if (Rectrack.has_mcParticle()) { - int pid = 0; - auto mcpart = Rectrack.mcParticle(); - histos.fill(HIST("etaResolution"), Rectrack.eta(), Rectrack.eta() - mcpart.eta()); - if (mcpart.isPhysicalPrimary()) { - switch (std::abs(mcpart.pdgCode())) { - case PDG_t::kPiPlus: - pid = kRecoPion; - break; - case PDG_t::kKPlus: - pid = kRecoKaon; - break; - case PDG_t::kProton: - pid = kRecoProton; - break; - default: - pid = kRecoOther; - break; - } - } else { - pid = kRecoSecondary; - } - if (mcpart.has_mothers()) { - auto mcpartMother = mcpart.template mothers_as().front(); - if (mcpartMother.pdgCode() == PDG_t::kK0Short || std::abs(mcpartMother.pdgCode()) == PDG_t::kLambda0) { - pid = kRecoWeakDecay; - } - } - if (find(mclabels.begin(), mclabels.end(), Rectrack.mcParticleId()) != mclabels.end()) { - pid = kRecoFake; + + int pid = 0; + histos.fill(HIST("etaResolution"), Rectrack.eta(), Rectrack.eta() - mcpart.eta()); + if (mcpart.isPhysicalPrimary()) { + switch (std::abs(mcpart.pdgCode())) { + case PDG_t::kPiPlus: + pid = kRecoPion; + break; + case PDG_t::kKPlus: + pid = kRecoKaon; + break; + case PDG_t::kProton: + pid = kRecoProton; + break; + default: + pid = kRecoOther; + break; } - mclabels.push_back(Rectrack.mcParticleId()); - histos.fill(HIST("hRecMCdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), mcpart.eta(), mcpart.phi(), static_cast(pid)); } else { - histos.fill(HIST("hRecMCdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), Rectrack.eta(), Rectrack.phi(), static_cast(kRecoBkg)); + pid = kRecoSecondary; + } + if (mcpart.has_mothers()) { + auto mcpartMother = mcpart.template mothers_as().front(); + if (mcpartMother.pdgCode() == PDG_t::kK0Short || std::abs(mcpartMother.pdgCode()) == PDG_t::kLambda0) { + pid = kRecoWeakDecay; + } + } + if (find(mclabels.begin(), mclabels.end(), Rectrack.mcParticleId()) != mclabels.end()) { + pid = kRecoFake; } + mclabels.push_back(Rectrack.mcParticleId()); + histos.fill(HIST("hRecMCdndeta"), RecCol.posZ(), selColCent(RecCol), selColOccu(RecCol), mcpart.eta(), mcpart.phi(), static_cast(pid)); } // track (mcrec) loop } // collision loop } @@ -1155,11 +974,8 @@ struct HeavyionMultiplicity { PROCESS_SWITCH(HeavyionMultiplicity, processData, "process data CentFT0C", false); PROCESS_SWITCH(HeavyionMultiplicity, processCorrelation, "do correlation study in data", false); PROCESS_SWITCH(HeavyionMultiplicity, processMonteCarlo, "process MC CentFT0C", false); - PROCESS_SWITCH(HeavyionMultiplicity, processMCpTefficiency, "process MC pTefficiency", false); PROCESS_SWITCH(HeavyionMultiplicity, processMCcheckFakeTracks, "Check Fake tracks", false); PROCESS_SWITCH(HeavyionMultiplicity, processStrangeYield, "Strange particle yield", false); - PROCESS_SWITCH(HeavyionMultiplicity, processppData, "process pp data", false); - PROCESS_SWITCH(HeavyionMultiplicity, processppMonteCarlo, "process pp MC", false); PROCESS_SWITCH(HeavyionMultiplicity, processGen, "process pure MC gen", false); PROCESS_SWITCH(HeavyionMultiplicity, processEvtLossSigLossMC, "process Signal Loss, Event Loss", false); PROCESS_SWITCH(HeavyionMultiplicity, processMCeff, "process extra efficiency function", false); diff --git a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx index 0392059fa1e..62f5e93d830 100644 --- a/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/studyPnch.cxx @@ -12,7 +12,7 @@ /// \file studyPnch.cxx /// /// \brief task for analysis of charged-particle multiplicity distributions -/// \author Abhi Modak (abhi.modak@cern.ch) +/// \author Abhi Modak (abhi.modak@cern.ch), Lucas José (lucas.jose.franco.da.silva@cern.ch) /// \since September 10, 2025 #include "PWGLF/DataModel/LFStrangenessTables.h" @@ -42,6 +42,7 @@ #include #include +#include #include using namespace o2; @@ -96,12 +97,14 @@ struct StudyPnch { ConfigurableAxis ft0aMultHistBin{"ft0aMultHistBin", {501, -0.5, 500.5}, ""}; ConfigurableAxis ft0cMultHistBin{"ft0cMultHistBin", {501, -0.5, 500.5}, ""}; ConfigurableAxis ptHistBin{"ptHistBin", {200, 0., 20.}, ""}; + ConfigurableAxis countNumberTracks{"countNumberTracks", {10, -0.5, 9.5}, ""}; Configurable isApplyTFcut{"isApplyTFcut", true, "Enable TimeFrameBorder cut"}; Configurable isApplyITSROcut{"isApplyITSROcut", true, "Enable ITS ReadOutFrameBorder cut"}; Configurable isApplySameBunchPileup{"isApplySameBunchPileup", true, "Enable SameBunchPileup cut"}; Configurable isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"}; Configurable isApplyExtraPhiCut{"isApplyExtraPhiCut", false, "Enable extra phi cut"}; + Configurable isApplyTVX{"isApplyTVX", false, "Enable TVX trigger sel"}; void init(InitContext const&) { @@ -111,6 +114,7 @@ struct StudyPnch { AxisSpec axisFt0aMult = {ft0aMultHistBin, "ft0a", "FT0AMultAxis"}; AxisSpec axisFt0cMult = {ft0cMultHistBin, "ft0c", "FT0CMultAxis"}; AxisSpec axisPt = {ptHistBin, "pT", "pTAxis"}; + AxisSpec axisCountNumberTracks = {countNumberTracks, "Count", "CountAxis"}; histos.add("EventHist", "EventHist", kTH1D, {axisEvent}, false); histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}, false); @@ -125,7 +129,7 @@ struct StudyPnch { x->SetBinLabel(6, "INEL > 0"); x->SetBinLabel(7, "|vz| < 10"); - if (doprocessData || doprocessCorrelation || doprocessMonteCarlo) { + if (doprocessData || doprocessCorrelation || doprocessMonteCarlo || doprocessModifiedMonteCarlo) { histos.add("PhiVsEtaHist", "PhiVsEtaHist", kTH2F, {axisPhi, axisEta}, false); } if (doprocessData) { @@ -142,6 +146,13 @@ struct StudyPnch { histos.add("hMultiplicityMCrec", "hMultiplicityMCrec", kTH1F, {axisMult}, true); histos.add("hMultiplicityMCgen", "hMultiplicityMCgen", kTH1F, {axisMult}, true); histos.add("hResponseMatrix", "hResponseMatrix", kTH2F, {axisMult, axisMult}, true); + histos.add("hCountNTracks", "hCountNTracks", kTH1F, {axisCountNumberTracks}, true); + } + if (doprocessModifiedMonteCarlo) { + histos.add("hMultiplicityMCrecMod", "hMultiplicityMCrecMod", kTH1F, {axisMult}, true); + histos.add("hMultiplicityMCgenMod", "hMultiplicityMCgenMod", kTH1F, {axisMult}, true); + histos.add("hResponseMatrixMod", "hResponseMatrixMod", kTH2F, {axisMult, axisMult}, true); + histos.add("hCountNTracksMod", "hCountNTracksMod", kTH1F, {axisCountNumberTracks}, true); } if (doprocessEvtLossSigLossMC) { histos.add("MCEventHist", "MCEventHist", kTH1F, {axisEvent}, false); @@ -237,20 +248,55 @@ struct StudyPnch { return nTrk; } - template - int countGenTracks(countTrk const& tracks) + template + int countGenTracks(countTrk const& tracks, McColType const& McCol) { auto nTrk = 0; for (const auto& track : tracks) { if (!isGenTrackSelected(track)) { continue; } + if (track.mcCollisionId() != McCol.globalIndex()) { + continue; + } + histos.fill(HIST("PhiVsEtaHist"), track.phi(), track.eta()); nTrk++; } return nTrk; } + template + int countNTracksMcCol(countTrk const& tracks, McColType const& McCol) + { + auto nTrk = 0; + std::unordered_map recoFrequencies; // Map that stores globalIndex and the times it appears + for (const auto& track : tracks) { + if (!isTrackSelected(track)) { + continue; + } + if (track.has_mcParticle()) { + auto particle = track.mcParticle(); + if (particle.mcCollisionId() != McCol.mcCollisionId()) { + continue; + } + auto globalIndex = particle.globalIndex(); + recoFrequencies[globalIndex]++; // Increment the count for this globalIndex + } + histos.fill(HIST("PhiVsEtaHist"), track.phi(), track.eta()); + } + // Loop to fill the histogram without cloned tracks + for (const auto& [globalIndex, frequency] : recoFrequencies) { + histos.fill(HIST("hCountNTracks"), frequency); + // Fill histogram with not cloned tracks + if (frequency == 1) { + nTrk++; + } + } + // return recoFrequencies; + return nTrk; + } + 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), @@ -264,7 +310,9 @@ struct StudyPnch { return; } auto mult = countNTracks(tracks); - histos.fill(HIST("hMultiplicityData"), mult); + if (mult > 0) { + histos.fill(HIST("hMultiplicityData"), mult); + } } void processCorrelation(ColDataTable::iterator const& cols, FilTrackDataTable const& tracks) @@ -280,18 +328,48 @@ struct StudyPnch { histos.fill(HIST("NPVtracks_vs_GlobalMult"), cols.multNTracksPV(), mult); } - void processMonteCarlo(ColMCTrueTable::iterator const&, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) + void processMonteCarlo(ColMCTrueTable::iterator const& mcCollision, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { for (const auto& RecCol : RecCols) { if (!isEventSelected(RecCol)) { continue; } auto recTracksPart = RecTracks.sliceBy(perCollision, RecCol.globalIndex()); - auto multrec = countNTracks(recTracksPart); - histos.fill(HIST("hMultiplicityMCrec"), multrec); - auto multgen = countGenTracks(GenParticles); - histos.fill(HIST("hMultiplicityMCgen"), multgen); - histos.fill(HIST("hResponseMatrix"), multrec, multgen); + auto multrec = countNTracksMcCol(recTracksPart, RecCol); + if (multrec > 0) { + histos.fill(HIST("hMultiplicityMCrec"), multrec); + } + auto multgen = countGenTracks(GenParticles, mcCollision); + if (multgen > 0 && multrec > 0) { + histos.fill(HIST("hMultiplicityMCgen"), multgen); + histos.fill(HIST("hResponseMatrix"), multrec, multgen); + } + } + } + + void processModifiedMonteCarlo(soa::Join::iterator const& mcCollision, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) + { + for (const auto& RecCol : RecCols) { + if (!isEventSelected(RecCol)) { + continue; + } + // Evaluation of reconstructed collisions with more than 1 contributor + if (RecCol.globalIndex() != mcCollision.bestCollisionIndex()) { + continue; + } + if (!RecCol.has_mcCollision()) { + continue; + } + auto recTracksPart = RecTracks.sliceBy(perCollision, RecCol.globalIndex()); + auto multrec = countNTracksMcCol(recTracksPart, RecCol); + if (multrec > 0) { + histos.fill(HIST("hMultiplicityMCrecMod"), multrec); + } + auto multgen = countGenTracks(GenParticles, mcCollision); + if (multgen > 0 && multrec > 0) { + histos.fill(HIST("hMultiplicityMCgenMod"), multgen); + histos.fill(HIST("hResponseMatrixMod"), multrec, multgen); + } } } @@ -300,13 +378,18 @@ struct StudyPnch { if (isApplyInelgt0 && !mcCollision.isInelGt0()) { return; } + if (isApplyTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } if (std::abs(mcCollision.posZ()) >= vtxRange) { return; } // All generated events histos.fill(HIST("MCEventHist"), 1); - auto multAll = countGenTracks(GenParticles); - histos.fill(HIST("hMultiplicityMCgenAll"), multAll); + auto multAll = countGenTracks(GenParticles, mcCollision); + if (multAll > 0) { + histos.fill(HIST("hMultiplicityMCgenAll"), multAll); + } bool atLeastOne = false; auto numcontributors = -999; @@ -324,14 +407,17 @@ struct StudyPnch { if (atLeastOne) { histos.fill(HIST("MCEventHist"), 2); - auto multSel = countGenTracks(GenParticles); - histos.fill(HIST("hMultiplicityMCgenSel"), multSel); + auto multSel = countGenTracks(GenParticles, mcCollision); + if (multSel > 0) { + histos.fill(HIST("hMultiplicityMCgenSel"), multSel); + } } } PROCESS_SWITCH(StudyPnch, processData, "process data CentFT0C", false); PROCESS_SWITCH(StudyPnch, processCorrelation, "do correlation study in data", false); PROCESS_SWITCH(StudyPnch, processMonteCarlo, "process MC CentFT0C", false); + PROCESS_SWITCH(StudyPnch, processModifiedMonteCarlo, "process MC CentFT0C", false); PROCESS_SWITCH(StudyPnch, processEvtLossSigLossMC, "process Signal Loss, Event Loss", false); }; diff --git a/PWGLF/Tasks/Nuspex/CMakeLists.txt b/PWGLF/Tasks/Nuspex/CMakeLists.txt index 0247878bf85..0609b38835e 100644 --- a/PWGLF/Tasks/Nuspex/CMakeLists.txt +++ b/PWGLF/Tasks/Nuspex/CMakeLists.txt @@ -166,9 +166,9 @@ o2physics_add_dpl_workflow(he3-lambda-derived-analysis COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dedx-pid-analysis - SOURCES dedxPidAnalysis.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES dedxPidAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(pikp-raa-analysis SOURCES piKpRAA.cxx @@ -180,4 +180,14 @@ o2physics_add_dpl_workflow(chargedparticle-raa PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(multiplicity-pt + SOURCES multiplicityPt.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(deuteron-in-jets-trg-pt + SOURCES DeuteronInJetsTrgPt.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + endif() diff --git a/PWGLF/Tasks/Nuspex/DeuteronInJetsTrgPt.cxx b/PWGLF/Tasks/Nuspex/DeuteronInJetsTrgPt.cxx new file mode 100644 index 00000000000..d03d028c3ef --- /dev/null +++ b/PWGLF/Tasks/Nuspex/DeuteronInJetsTrgPt.cxx @@ -0,0 +1,564 @@ +// 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. +// +// Task for analysing (anti)deuteron production in jets using pT-triggered data - update: 05-02-2026 +// +// Executable : o2-analysis-lf-deuteron-in-jets-trg-pt + +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetUtilities.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/Zorro.h" +#include "Common/Core/ZorroSummary.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::constants::math; +using namespace o2::constants::physics; + +// Define conventional aliases for commoly used table joins +using SelectedCollisions = soa::Join; +using SelectedTracks = soa::Join; + +struct DeuteronInJetsTrgPt { + // Histogram registry for data + HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Random generator for subsample assignment + TRandom3 mRand; + + // Setting default selection criteria to select tracks. May be changed when configuring the analysis. + struct : o2::framework::ConfigurableGroup { + std::string prefix{"cfgTrackCut"}; + // General specific + Configurable requirePvContributor{"requirePvContributor", false, "Require that the track is a PV contributor"}; + Configurable EtaMax{"EtaMax", 0.9f, "Max Eta for track acceptance"}; + Configurable minPt{"minPt", 0.3, "Minimum pt of the tracks"}; + Configurable maxDcaxy{"maxDcaxy", 0.05, "Maximum DCAxy"}; + Configurable maxDcaz{"maxDcaz", 0.05, "Maximum DCAz"}; + // Part relative to ITS + Configurable ITSnClusMin{"ITSnClsMin", 6, "Minimum number of ITS clusters"}; + Configurable ITSchi2ClusMax{"ITSchi2ClusMax", 36.f, "Max ITS Chi2 per cluster"}; + Configurable applyItsPid{"applyItsPid", false, "apply ITS PID"}; + Configurable setMCDefaultItsParams{"setMCDefaultItsParams", true, "Set MC default parameters for ITS PID"}; + Configurable nSigmaItsMin{"nSigmaItsMin", -3.0, "nSigmaITS min"}; + Configurable nSigmaItsMax{"nSigmaItsMax", +3.0, "nSigmaITS max"}; + Configurable ptMaxItsPidProt{"ptMaxItsPidProt", 1.0, "maximum pt for ITS PID for protons"}; + Configurable ptMaxItsPidDeut{"ptMaxItsPidDeut", 1.0, "maximum pt for ITS PID for deuterons"}; + // Part relative to TPC + Configurable TPCnClsMin{"TPCnClsMin", 100, "Minimum number of TPC clusters"}; + Configurable TPCchi2ClusMin{"TPCchi2ClusMin", 0.f, "Min TPC Chi2 per cluster"}; + Configurable TPCchi2ClusMax{"TPCchi2ClusMax", 4.f, "Max TPC Chi2 per cluster"}; + Configurable TPCnCrossedRowsMin{"TPCnCrossedRowsMin", 100, "Minimum number of TPC crossed rows"}; + Configurable Rtpc{"minRtpc", 0.8, "Minimum value of TPC crossed rows/TPC n cluster findable"}; + Configurable TPCrigidityMin{"TPCrigidityMin", 0.3f, "Minimum TPC rigidity (p/Z) for track"}; + Configurable minNsigmaTpc{"minNsigmaTpc", -3.0, "Minimum nsigma TPC"}; + Configurable maxNsigmaTpc{"maxNsigmaTpc", +3.0, "Maximum nsigma TPC"}; + // Part relatuive to TOF + Configurable minNsigmaTof{"minNsigmaTof", -3.0, "Minimum nsigma TOF"}; + Configurable maxNsigmaTof{"maxNsigmaTof", +3.5, "Maximum nsigma TOF"}; + } cfgTrackCut; + + // Setting default selection criteria for events. May be changes when configuring the analysis. + struct : o2::framework::ConfigurableGroup { + std::string prefix{"cgfEventCut"}; + Configurable zVtx{"zVtx", 10.0, "Maximum z vertex"}; + } cfgEvCut; + + // Skimmed data flag and list of active triggers for processing + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable triggerList{"triggerList", "fJetFullLowPt", "Trigger list"}; + + // Setting default selection criteria fr jet identification. May be changes when configuring the analysis. + struct : o2::framework::ConfigurableGroup { + std::string prefix{"cgfJetCut"}; + Configurable minJetPt{"minJetPt", 10.0, "Minimum pt of the jet after bkg subtraction"}; + Configurable rJet{"rJet", 0.3, "Jet parameter R"}; + Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from the edge"}; + } cfgJetCut; + + // Setting the number of bins and min and max value for the nsigma distribution + Configurable cfgNbins{"Nbins", 120, "Number of pT-bins"}; + Configurable cfgpt_min{"pt_min", 0.0, "Min pT value of pT-axis"}; + Configurable cfgpt_max{"pt_max", 6.0, "Max pT value of pT-axis"}; + + // CCDB manager service for accessing condition data + Service ccdb; + + // Instantiate the main Zorro processing object and define an output to store summary information + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + // Utility object for jet background subtraction methods + JetBkgSubUtils backgroundSub; + + // Initiliaze ITS PID Rensponse object + o2::aod::ITSResponse itsResponse; + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (cfgSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); + zorro.populateHistRegistry(registryData, bc.runNumber()); + } + } + + // Set all configuration to allow task working + void init(InitContext const&) + { + // Set summary object if processing skimmed data + if (cfgSkimmedProcessing) + zorroSummary.setObject(zorro.getZorroSummary()); + + // Set default MC parametrization for ITS response + if (cfgTrackCut.setMCDefaultItsParams) + itsResponse.setMCDefaultParameters(); + + // Initialize random seed using high-resolution clock to ensure unique sequences across parallel Grid jobs + auto time_seed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + mRand.SetSeed(time_seed); + + // Histrograms for real data + if (doprocessData) { + registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{4, 0, 4, "counter"}}); // Event counters + registryData.add("settingData", "settingData", HistType::kTH2F, {{100, 0.0, 50.0, "min #it{p}^{jet}_{T} [GeV/#it{c}]"}, {20, 0.0, 1.0, "#it{R}_{jet}"}}); // Configuration + registryData.add("jetEffectiveAreaOverPiR2", "jet effective area / piR^2", HistType::kTH1F, {{2000, 0, 2, "Area/#piR^{2}"}}); // Jet effective area over piR^2 + + // Antiprotons + registryData.add("antiproton_jet_tpc", "antiproton_jet_tpc", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_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, {{cfgNbins, cfgpt_min, cfgpt_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, {{cfgNbins, cfgpt_min, cfgpt_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, {{cfgNbins, cfgpt_min, cfgpt_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, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {200, -1.0, 1.0, "DCA_{xy} [cm]"}}); + registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {200, -1.0, 1.0, "DCA_{xy} [cm]"}}); + + // protons + registryData.add("proton_jet_tpc", "proton_jet_tpc", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("proton_jet_tof", "proton_jet_tof", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("proton_ue_tpc", "proton_ue_tpc", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("proton_ue_tof", "proton_ue_tof", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("proton_dca_jet", "proton_dca_jet", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {200, -1.0, 1.0, "DCA_{xy} [cm]"}}); + registryData.add("proton_dca_ue", "proton_dca_ue", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {200, -1.0, 1.0, "DCA_{xy} [cm]"}}); + + // Antideuterons + registryData.add("antideuteron_jet_tpc", "antideuteron_jet_tpc", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antideuteron_jet_tof", "antideuteron_jet_tof", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antideuteron_ue_tpc", "antideuteron_ue_tpc", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antideuteron_ue_tof", "antideuteron_ue_tof", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + + // Deuterons + registryData.add("deuteron_jet_tpc", "deuteron_jet_tpc", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("deuteron_jet_tof", "deuteron_jet_tof", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("deuteron_ue_tpc", "deuteron_ue_tpc", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("deuteron_ue_tof", "deuteron_ue_tof", HistType::kTH2F, {{cfgNbins, 2 * cfgpt_min, 2 * cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + + // nsigmaITS for antiproton candidates + registryData.add("antiproton_nsigma_its_data", "antiproton_nsigma_its_data", HistType::kTH2F, {{cfgNbins, cfgpt_min, cfgpt_max, "#it{p}_{T} [GeV/#it{c}]"}, {400, -20.0, 20.0, "n#sigma_{ITS}"}}); + } + } + + // Compute two transverse directions orthogonal to vector p (useful for UE evaluation) + void getPerpendicularDirections(const TVector3& p, TVector3& u1, TVector3& u2) + { + // Get momentum components + double px = p.X(); + double py = p.Y(); + double pz = p.Z(); + + // Precompute squared terms + double px2 = px * px; + double py2 = py * py; + double pz2 = pz * pz; + double pz4 = pz2 * pz2; + + // Case 1: vector along z-axis -> undefined perpendiculars + if (px == 0 && py == 0) { + u1.SetXYZ(0, 0, 0); + u2.SetXYZ(0, 0, 0); + return; + } + + // Case 2: px = 0 -> avoid division by zero + if (px == 0 && py != 0) { + double ux = std::sqrt(py2 - pz4 / py2); + double uy = -pz2 / py; + u1.SetXYZ(ux, uy, pz); + u2.SetXYZ(-ux, uy, pz); + return; + } + + // Case 3: py = 0 -> avoid division by zero + if (py == 0 && px != 0) { + double ux = -pz2 / px; + double uy = std::sqrt(px2 - pz4 / px2); + u1.SetXYZ(ux, uy, pz); + u2.SetXYZ(ux, -uy, pz); + return; + } + + // General case: solve quadratic for perpendicular vectors + double a = px2 + py2; + double b = 2.0 * px * pz2; + double c = pz4 - py2 * py2 - px2 * py2; + double delta = b * b - 4.0 * a * c; + + // Invalid or degenerate solutions + if (delta < 0 || a == 0) { + u1.SetXYZ(0, 0, 0); + u2.SetXYZ(0, 0, 0); + return; + } + + // Solution 1 + double u1x = (-b + std::sqrt(delta)) / (2.0 * a); + double u1y = (-pz2 - px * u1x) / py; + u1.SetXYZ(u1x, u1y, pz); + + // Solution 2 + double u2x = (-b - std::sqrt(delta)) / (2.0 * a); + double u2y = (-pz2 - px * u2x) / py; + u2.SetXYZ(u2x, u2y, pz); + } + + // Find hit on ITS layer + template + bool hasHitITS(const TrackIts& track, int layer) + { + int ibit = layer - 1; + return (track.itsClusterMap() & (1 << ibit)); + } + + // Track selection criteria for creating jets + template + bool passedTrackSelectionForJetReconstruction(const JetTrack& track) + { + static constexpr int MinTpcCr = 70; + static constexpr double MaxChi2Tpc = 4.0; + static constexpr double MaxChi2Its = 36.0; + static constexpr double MinPtTrack = 0.1; + static constexpr double DcaxyMaxTrackPar0 = 0.0105; + static constexpr double DcaxyMaxTrackPar1 = 0.035; + static constexpr double DcaxyMaxTrackPar2 = 1.1; + static constexpr double DcazMaxTrack = 2.0; + + // General part + if (std::fabs(track.eta()) > cfgTrackCut.EtaMax) + return false; + if (track.pt() < MinPtTrack) + return false; + if (std::fabs(track.dcaXY()) > (DcaxyMaxTrackPar0 + DcaxyMaxTrackPar1 / std::pow(track.pt(), DcaxyMaxTrackPar2))) + return false; // DCAxy cut + if (std::fabs(track.dcaZ()) > DcazMaxTrack) + return false; // DCAz cut + // Part relative to ITS + if (!track.hasITS()) + return false; + if ((!hasHitITS(track, 1)) && (!hasHitITS(track, 2)) && (!hasHitITS(track, 3))) + return false; // Has Inner Barrel hit + if (track.itsChi2NCl() >= MaxChi2Its) + return false; + // Part relative to TPC + if (!track.hasTPC()) + return false; + if (track.tpcNClsCrossedRows() < MinTpcCr) + return false; + if (track.tpcChi2NCl() >= MaxChi2Tpc) + return false; + + return true; + } + + // Track selection for antinuclei + template + bool passedTrackSelection(const AntinucleusTrack& track) + { + // General part + if (cfgTrackCut.requirePvContributor && !(track.isPVContributor())) + return false; // Flag to check if the track contributed to the collision vertex fit + if (std::fabs(track.eta()) > cfgTrackCut.EtaMax) + return false; // Eta + if (track.pt() < cfgTrackCut.minPt) + return false; + // Part relative to ITS + if (!track.hasITS()) + return false; // Flag to check if track has a ITS match + if ((!hasHitITS(track, 1)) && (!hasHitITS(track, 2)) && (!hasHitITS(track, 3))) + return false; // Require IB hit + if (track.itsNCls() < cfgTrackCut.ITSnClusMin) + return false; // Minimum number of ITS cluster + if (track.itsChi2NCl() > cfgTrackCut.ITSchi2ClusMax) + return false; // Minimum chi2 per cluster in ITS + // Part relative to TPC + if (!track.hasTPC()) + return false; // Flag to check if track has a ITS match + if (track.tpcNClsFound() < cfgTrackCut.TPCnClsMin) + return false; // Minimum number of TPC cluster + if (track.tpcNClsCrossedRows() < cfgTrackCut.TPCnCrossedRowsMin) + return false; // Minimum number of crossed rows in TPC + if (track.tpcChi2NCl() < cfgTrackCut.TPCchi2ClusMin) + return false; // Minimum chi2 per cluster in TPC + if (track.tpcChi2NCl() > cfgTrackCut.TPCchi2ClusMax) + return false; // Maximum chi2 per cluster in TPC + if (track.tpcCrossedRowsOverFindableCls() < cfgTrackCut.Rtpc) + return false; // R_{TPC} > 0.8 + + return true; + } + + void processData(SelectedCollisions::iterator const& collision, SelectedTracks const& tracks, aod::BCsWithTimestamps const&) + { + // Event counter before event selection + registryData.fill(HIST("number_of_events_data"), 0.5); + registryData.fill(HIST("settingData"), cfgJetCut.minJetPt.value, cfgJetCut.rJet.value); + + // Retrieve the bunch crossing information with timestamps from the collision + auto bc = collision.template bc_as(); + initCCDB(bc); + + // If skimmed processing is enabled, aplly Zorro trigger selection + if (cfgSkimmedProcessing && !zorro.isSelected(collision.template bc_as().globalBC())) + return; + registryData.fill(HIST("number_of_events_data"), 1.5); + + // Apply standard event selection + if (!collision.sel8() || std::fabs(collision.posZ()) >= cfgEvCut.zVtx) + return; + registryData.fill(HIST("number_of_events_data"), 2.5); // Save number of collisions that passed standard selections + + // loop over reco tracks + int id(-1); + std::vector fjParticles; + for (auto const& track : tracks) { + id++; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; // Skip tracks that not satisfy tracking selection criteria + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); + fourMomentum.set_user_index(id); + fjParticles.emplace_back(fourMomentum); + } + + if (fjParticles.empty()) + return; // Reject empty events + + // Cluster particles using the the anti-kT algorithm + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, cfgJetCut.rJet); // Defining the algorithm to cluster, and the jet radius + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // Activate area evaluation, and set area evaluation method + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); // Declare the will of applying clustering algorithm with area evaluation to the selected candidates + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], cfgJetCut.rJet); + + // Loop over reco jets + bool isAtLeastOneJetSelected = false; + for (auto const& jet : jets) { + + if ((std::fabs(jet.eta()) + cfgJetCut.rJet) > (cfgTrackCut.EtaMax - cfgJetCut.deltaEtaEdge)) + continue; // Jet must be fully contained in the acceptance + + // Jet pt must be larger than threshold + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < cfgJetCut.minJetPt) + continue; // Skip jets with pT < pT threshold + + double normalizedJetArea = jet.area() / (PI * cfgJetCut.rJet * cfgJetCut.rJet); + isAtLeastOneJetSelected = true; + + // Perpendicular cones + double coneRadius = std::sqrt(jet.area() / PI); + TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); + getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); + if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) + continue; // Skip not valid orthogonal cones + + registryData.fill(HIST("jetEffectiveAreaOverPiR2"), normalizedJetArea); // Fill histogram with jet effective area / piR^2 + std::vector jetConstituents = jet.constituents(); // Get jet constituents + + // Loop over constituents + for (const auto& particle : jetConstituents) { + auto const& track = tracks.iteratorAt(particle.user_index()); // Get the corresponding track + if (!passedTrackSelection(track)) + continue; // Apply track selection criteria + + // Define variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double nsigmaTPCDe = track.tpcNSigmaDe(); + double nsigmaTOFDe = track.tofNSigmaDe(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); + + // Fill DCA distribution for (anti)protons + if (track.sign() < 0 && std::fabs(dcaz) < cfgTrackCut.maxDcaz) + registryData.fill(HIST("antiproton_dca_jet"), pt, dcaxy); + if (track.sign() > 0 && std::fabs(dcaz) < cfgTrackCut.maxDcaz) + registryData.fill(HIST("proton_dca_jet"), pt, dcaxy); + + // Apply DCA selections + if (std::fabs(dcaxy) > cfgTrackCut.maxDcaxy || std::fabs(dcaz) > cfgTrackCut.maxDcaz) + continue; + + // Particle identification using the ITS cluster size + bool passedItsPidProt(true), passedItsPidDeut(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + + if (cfgTrackCut.applyItsPid && pt < cfgTrackCut.ptMaxItsPidProt && (nSigmaITSprot < cfgTrackCut.nSigmaItsMin || nSigmaITSprot > cfgTrackCut.nSigmaItsMax)) + passedItsPidProt = false; + if (cfgTrackCut.applyItsPid && pt < cfgTrackCut.ptMaxItsPidDeut && (nSigmaITSdeut < cfgTrackCut.nSigmaItsMin || nSigmaITSdeut > cfgTrackCut.nSigmaItsMax)) + passedItsPidDeut = false; + + // Fill histograms for antimatter + if (track.sign() < 0) { + if (passedItsPidProt) { + registryData.fill(HIST("antiproton_jet_tpc"), pt, nsigmaTPCPr); + if (nsigmaTPCPr > cfgTrackCut.minNsigmaTpc && nsigmaTPCPr < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("antiproton_jet_tof"), pt, nsigmaTOFPr); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + if (passedItsPidDeut) { + registryData.fill(HIST("antideuteron_jet_tpc"), pt, nsigmaTPCDe); + if (nsigmaTPCDe > cfgTrackCut.minNsigmaTpc && nsigmaTPCDe < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("antideuteron_jet_tof"), pt, nsigmaTOFDe); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + } + // Fill histograms for matter + if (track.sign() > 0) { + if (passedItsPidProt) { + registryData.fill(HIST("proton_jet_tpc"), pt, nsigmaTPCPr); + if (nsigmaTPCPr > cfgTrackCut.minNsigmaTpc && nsigmaTPCPr < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("proton_jet_tof"), pt, nsigmaTOFPr); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + if (passedItsPidDeut) { + registryData.fill(HIST("deuteron_jet_tpc"), pt, nsigmaTPCDe); + if (nsigmaTPCDe > cfgTrackCut.minNsigmaTpc && nsigmaTPCDe < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("deuteron_jet_tof"), pt, nsigmaTOFDe); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + } + } // End of loop over jet constituents + + // Loop over tracks in the UE + for (auto const& track : tracks) { + if (!passedTrackSelection(track)) + continue; // Apply track selection criteria + + // Calculate the angular distance between the track and the UE axes in eta-phi space + double deltaEtaUe1 = track.eta() - ueAxis1.Eta(); + double deltaPhiUe1 = std::fabs(RecoDecay::constrainAngle(track.phi() - ueAxis1.Phi(), -PI)); + double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + double deltaEtaUe2 = track.eta() - ueAxis2.Eta(); + double deltaPhiUe2 = std::fabs(RecoDecay::constrainAngle(track.phi() - ueAxis2.Phi(), -PI)); + double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + double maxConeRadius = coneRadius; + if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) + continue; // Reject tracks that lie outside the maxConeRadius from both UE axes + + // Define variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double nsigmaTPCDe = track.tpcNSigmaDe(); + double nsigmaTOFDe = track.tofNSigmaDe(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); + + // Fill DCA distribution for (anti)protons + if (track.sign() < 0 && std::fabs(dcaz) < cfgTrackCut.maxDcaz) + registryData.fill(HIST("antiproton_dca_ue"), pt, dcaxy); + if (track.sign() > 0 && std::fabs(dcaz) < cfgTrackCut.maxDcaz) + registryData.fill(HIST("proton_dca_ue"), pt, dcaxy); + + // Apply DCA selections + if (std::fabs(dcaxy) > cfgTrackCut.maxDcaxy || std::fabs(dcaz) > cfgTrackCut.maxDcaz) + continue; + + // Particle identification using the ITS cluster size + bool passedItsPidProt(true), passedItsPidDeut(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + + if (cfgTrackCut.applyItsPid && pt < cfgTrackCut.ptMaxItsPidProt && (nSigmaITSprot < cfgTrackCut.nSigmaItsMin || nSigmaITSprot > cfgTrackCut.nSigmaItsMax)) + passedItsPidProt = false; + if (cfgTrackCut.applyItsPid && pt < cfgTrackCut.ptMaxItsPidDeut && (nSigmaITSdeut < cfgTrackCut.nSigmaItsMin || nSigmaITSdeut > cfgTrackCut.nSigmaItsMax)) + passedItsPidDeut = false; + + // Fill histograms for antimatter + if (track.sign() < 0) { + if (passedItsPidProt) { + registryData.fill(HIST("antiproton_ue_tpc"), pt, nsigmaTPCPr); + if (nsigmaTPCPr > cfgTrackCut.minNsigmaTpc && nsigmaTPCPr < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("antiproton_ue_tof"), pt, nsigmaTOFPr); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + if (passedItsPidDeut) { + registryData.fill(HIST("antideuteron_ue_tpc"), pt, nsigmaTPCDe); + if (nsigmaTPCDe > cfgTrackCut.minNsigmaTpc && nsigmaTPCDe < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("antideuteron_ue_tof"), pt, nsigmaTOFDe); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + } + // Fill histograms for matter + if (track.sign() > 0) { + if (passedItsPidProt) { + registryData.fill(HIST("proton_ue_tpc"), pt, nsigmaTPCPr); + if (nsigmaTPCPr > cfgTrackCut.minNsigmaTpc && nsigmaTPCPr < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("proton_ue_tof"), pt, nsigmaTOFPr); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + if (passedItsPidDeut) { + registryData.fill(HIST("deuteron_ue_tpc"), pt, nsigmaTPCDe); + if (nsigmaTPCDe > cfgTrackCut.minNsigmaTpc && nsigmaTPCDe < cfgTrackCut.maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("deuteron_ue_tof"), pt, nsigmaTOFDe); // requiring that track candidate in TOF have nisgma in TPC < threshold + } + } + } + } + + // Event counter: events with at least one jet selected + if (isAtLeastOneJetSelected) + registryData.fill(HIST("number_of_events_data"), 3.5); + } + PROCESS_SWITCH(DeuteronInJetsTrgPt, processData, "Process Data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx index d8327d466dd..80b50320ea6 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx @@ -215,6 +215,7 @@ struct LFNucleiBATask { TF1* fShiftPtantiHe = 0; TF1* fShiftAntiD = 0; TF1* fShiftD = 0; + TF1* fShiftPtPID = 0; Configurable enablePtShiftD{"enablePtShiftD", true, "Flag to enable Pt shift (for Deuteron only)"}; Configurable enablePtShiftAntiD{"enablePtShiftAntiD", true, "Flag to enable Pt shift (for antiDeuteron only)"}; @@ -225,6 +226,9 @@ struct LFNucleiBATask { Configurable> parShiftPtHe{"parShiftPtHe", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for helium3-Pt shift (if enabled)."}; Configurable> parShiftPtAntiHe{"parShiftPtAntiHe", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for anti-helium3-Pt shift (if enabled)."}; + Configurable enablePtShiftPID{"enablePtShiftPID", true, "Flag to enable wrong PID in tracking pT correction shift"}; + Configurable> parShiftPtPID{"parShiftPtPID", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for helium3-Pt wrong pid shift (if enabled)."}; + Configurable enableCentrality{"enableCentrality", true, "Flag to enable centrality 3D histos)"}; // ITS to TPC - Fake hit loop @@ -581,7 +585,7 @@ struct LFNucleiBATask { } if (enableDebug) { - debugHistos.add("debug/event/h1CentV0M", "V0M; Multiplicity; counts", HistType::kTH1F, {{27000, 0, 27000}}); + // debugHistos.add("debug/event/h1CentV0M", "V0M; Multiplicity; counts", HistType::kTH1F, {{27000, 0, 27000}}); // trackQA debugHistos.add("debug/tracks/h1Eta", "pseudoRapidity; #eta; counts", HistType::kTH1F, {{200, -2.0, 2.0}}); debugHistos.add("debug/tracks/h1VarPhi", "#phi; #phi; counts", HistType::kTH1F, {{63, 0.0, 6.3}}); @@ -776,6 +780,11 @@ struct LFNucleiBATask { histos.add("tracks/helium/h1HeliumSpectra_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1antiHeliumSpectra_Z2", "#it{p}_{T} (#bar{He})", HistType::kTH1F, {ptHeAxis}); + if (enableDebug) { + debugHistos.add("tracks/helium/h2HeliumPidTrackingVsPt", "#it{p}_{T} (He) vs PIDforTracking", HistType::kTH2F, {{80, 0, 8}, {12, -0.5, 11.5}}); + debugHistos.add("tracks/helium/h2antiHeliumPidTrackingVsPt", "#it{p}_{T} (#bar{He}) vs PIDforTracking", HistType::kTH2F, {{80, 0, 8}, {12, -0.5, 11.5}}); + } + if (outFlagOptions.doTOFplots && enableCentrality) { histos.add("tracks/helium/TOF/h2HeliumSpectraVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/TOF/h2antiHeliumSpectraVsMult_Z2", "#it{p}_{T} (#bar{He})", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); @@ -998,6 +1007,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2HeliumSpectraTrueVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/h2HeliumSpectraTrueWPIDVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/h2HeliumSpectraTruePrimVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); + histos.add("tracks/helium/h2HeliumSpectraTruePrimGenVsMult_Z2", "#it{p}_{T}(gen) (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/h2HeliumSpectraTrueSecVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); } @@ -1011,6 +1021,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2antiHeliumSpectraTrueVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/h2antiHeliumSpectraTrueWPIDVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/h2antiHeliumSpectraTruePrimVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); + histos.add("tracks/helium/h2antiHeliumSpectraTruePrimGenVsMult_Z2", "#it{p}_{T}(gen) (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/h2antiHeliumSpectraTrueSecVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); } @@ -1020,8 +1031,11 @@ struct LFNucleiBATask { if (enableCentrality) { histos.add("tracks/helium/TOF/h2HeliumSpectraTrueWPIDVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/TOF/h2HeliumSpectraTruePrimVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); + histos.add("tracks/helium/TOF/h2HeliumSpectraTruePrimGenVsMult_Z2", "#it{p}_{T}(gen) (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); + histos.add("tracks/helium/TOF/h2antiHeliumSpectraTrueWPIDVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); histos.add("tracks/helium/TOF/h2antiHeliumSpectraTruePrimVsMult_Z2", "#it{p}_{T} (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); + histos.add("tracks/helium/TOF/h2antiHeliumSpectraTruePrimGenVsMult_Z2", "#it{p}_{T}(gen) (He)", HistType::kTH2F, {{ptHeAxis}, {binsPercentile}}); } } if (outFlagOptions.enableEffPlots) { @@ -1728,7 +1742,7 @@ struct LFNucleiBATask { } if (outFlagOptions.doTOFplots && outFlagOptions.enablePIDplot) { - 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/h2TPCsignVsBetaGamma", "TPC <-dE/dX> vs #beta#gamma/Z; Signed #beta#gamma; TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, -4.f, 4.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 (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}}); @@ -2149,23 +2163,39 @@ struct LFNucleiBATask { spectraGen.add("helium/histPtGenHe", "PtGenHe", HistType::kTH1F, {{800, 0.f, 8.f}}); spectraGen.add("helium/histPtRecHe", "PtRecHe", HistType::kTH1F, {{800, 0.f, 8.f}}); - spectraGen.add("helium/histPtShiftHe", "PtReco-PtGen vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); - spectraGen.add("helium/histPtShiftVsEtaHe", "PtReco-PtGen vs #eta", HistType::kTH2F, {{200, -2.f, 2.f}, {400, -4.f, 4.f}}); + spectraGen.add("helium/histPtShiftHe", "PtReco-PtGen vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftHeVsGen", "PtReco-PtGen vs PtGen;#it{p}_{T}(gen); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftHe_WrongPidAll", "PtReco-PtGen (He, wrong PIDforTracking) vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftHe_WrongPidDe", "PtReco-PtGen (He, wrong PIDforTracking) vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftHe_WrongPidTr", "PtReco-PtGen (He, wrong PIDforTracking) vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + + spectraGen.add("helium/histPtShiftVsEtaHe", "PtReco-PtGen vs #eta", HistType::kTH2F, {{140, -1.4f, 1.4f}, {140, -1.f, 1.4f}}); spectraGen.add("helium/histPGenHe", "PGenHe", HistType::kTH1F, {{800, 0.f, 8.f}}); spectraGen.add("helium/histPRecHe", "PRecHe", HistType::kTH1F, {{800, 0.f, 8.f}}); - spectraGen.add("helium/histPShiftHe", "PReco-PGen vs PReco", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); - spectraGen.add("helium/histPShiftVsEtaHe", "PReco-PGen vs #eta", HistType::kTH2F, {{200, -2.f, 2.f}, {400, -4.f, 4.f}}); + spectraGen.add("helium/histPShiftHe", "PReco-PGen vs PReco", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPShiftVsEtaHe", "PReco-PGen vs #eta", HistType::kTH2F, {{140, -1.4f, 1.4f}, {140, -1.f, 1.4f}}); spectraGen.add("helium/histPtGenantiHe", "PtGenantiHe", HistType::kTH1F, {{800, 0.f, 8.f}}); spectraGen.add("helium/histPtRecantiHe", "PtRecantiHe", HistType::kTH1F, {{800, 0.f, 8.f}}); - spectraGen.add("helium/histPtShiftantiHe", "PtReco-PtGen vs PtReco; #it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); - spectraGen.add("helium/histPtShiftVsEtaantiHe", "PtReco-PtGen vs #eta", HistType::kTH2F, {{200, -2.f, 2.f}, {400, -4.f, 4.f}}); + spectraGen.add("helium/histPtShiftantiHe", "PtReco-PtGen vs PtReco; #it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftantiHeVsGen", "PtReco-PtGen vs PtGen; #it{p}_{T}(gen); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftantiHe_WrongPidAll", "PtReco-PtGen (#bar{H}e, wrong PIDforTracking) vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftantiHe_WrongPidDe", "PtReco-PtGen (#bar{H}e, wrong PIDforTracking) vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftantiHe_WrongPidTr", "PtReco-PtGen (#bar{H}e, wrong PIDforTracking) vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPtShiftVsEtaantiHe", "PtReco-PtGen vs #eta", HistType::kTH2F, {{140, -1.4f, 1.4f}, {140, -1.f, 1.4f}}); + + if (outFlagOptions.doTOFplots) { + spectraGen.add("helium/TOF/histPtShiftHe", "PtReco-PtGen vs PtReco;#it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/TOF/histPtShiftHeVsGen", "PtReco-PtGen vs PtGen;#it{p}_{T}(gen); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/TOF/histPtShiftantiHe", "PtReco-PtGen vs PtReco; #it{p}_{T}(reco); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/TOF/histPtShiftantiHeVsGen", "PtReco-PtGen vs PtGen; #it{p}_{T}(gen); #it{p}_{T}(reco) - #it{p}_{T}(gen)", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + } spectraGen.add("helium/histPGenantiHe", "PGenantiHe", HistType::kTH1F, {{800, 0.f, 8.f}}); spectraGen.add("helium/histPRecantiHe", "PRecantiHe", HistType::kTH1F, {{800, 0.f, 8.f}}); - spectraGen.add("helium/histPShiftantiHe", "PReco-PGen vs PReco", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); - spectraGen.add("helium/histPShiftVsEtaantiHe", "PReco-PGen vs #eta", HistType::kTH2F, {{200, -2.f, 2.f}, {400, -4.f, 4.f}}); + spectraGen.add("helium/histPShiftantiHe", "PReco-PGen vs PReco", HistType::kTH2F, {{800, 0.f, 8.f}, {140, -1.f, 1.4f}}); + spectraGen.add("helium/histPShiftVsEtaantiHe", "PReco-PGen vs #eta", HistType::kTH2F, {{140, -1.4f, 1.4f}, {140, -1.f, 1.4f}}); spectraGen.add("pion/histGenPtPion", "generated particles", HistType::kTH1F, {ptAxis}); spectraGen.add("pion/histGenPtPionPrim", "generated particles", HistType::kTH1F, {ptAxis}); @@ -2361,6 +2391,7 @@ struct LFNucleiBATask { if (evselOptions.removeTFBorder && !event.selection_bit(aod::evsel::kNoTimeFrameBorder)) return; } + if (centFT0M <= cfgMultCutLow || centFT0M > cfgMultCutHigh) { return; } @@ -2369,10 +2400,6 @@ struct LFNucleiBATask { else histos.fill(HIST("event/eventSelection"), 7); - if (enableCentrality && enableDebug) { - debugHistos.fill(HIST("event/h1VtxZ_Centrality"), event.posZ()); - } - float gamma = 0., massTOF = 0., massTOFhe = 0., massTOFantihe = 0., heTPCmomentum = 0.f, antiheTPCmomentum = 0.f, heP = 0.f, antiheP = 0.f, hePt = 0.f, antihePt = 0.f, antiDPt = 0.f, DPt = 0.f; bool isTritonTPCpid = false; bool prRapCut = false; @@ -2442,9 +2469,13 @@ struct LFNucleiBATask { } isTritonTPCpid = std::abs(track.tpcNSigmaTr()) < nsigmaTPCvar.nsigmaTPCTr; + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + bool tritonPID = track.pidForTracking() == o2::track::PID::Triton; + bool deuteronPID = track.pidForTracking() == o2::track::PID::Deuteron; float shiftPtPos = 0.f; float shiftPtNeg = 0.f; + float shiftPtPID = 0.f; if (enablePtShiftHe && !fShiftPtHe) { fShiftPtHe = new TF1("fShiftPtHe", "[0] * exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); @@ -2464,6 +2495,12 @@ struct LFNucleiBATask { fShiftAntiD->SetParameters(parAntiD[0], parAntiD[1], parAntiD[2], parAntiD[3], parAntiD[4]); } + if (enablePtShiftPID && !fShiftPtPID) { + fShiftPtPID = new TF1("fShiftPtPID", "[0] * exp([1] + [2] * x) + [3] + [4] * x + [5] * x * x + [6] * x * x * x", 0.f, 8.f); + auto parPID = (std::vector)parShiftPtPID; // NOLINT + fShiftPtPID->SetParameters(parPID[0], parPID[1], parPID[2], parPID[3], parPID[4], parPID[5], parPID[6]); + } + switch (unableAntiDPtShift) { case 0: if (enablePtShiftAntiD && fShiftAntiD) { @@ -2506,6 +2543,13 @@ struct LFNucleiBATask { shiftPtNeg = fShiftPtantiHe->Eval(2 * track.pt()); antihePt = track.pt() - shiftPtNeg / 2.f; } + if (enablePtShiftPID && fShiftPtPID) { + shiftPtPID = fShiftPtPID->Eval(2 * track.pt()); + if (tritonPID && (track.pt() <= 1.25f)) { + hePt = track.pt() - shiftPtPID / 2.f; + antihePt = track.pt() - shiftPtPID / 2.f; + } + } break; case 1: hePt = 2.f * track.pt(); @@ -3707,8 +3751,19 @@ struct LFNucleiBATask { spectraGen.fill(HIST("helium/histPtGenHe"), std::abs(track.mcParticle().pt())); spectraGen.fill(HIST("helium/histPtRecHe"), 2.f * hePt); spectraGen.fill(HIST("helium/histPtShiftHe"), 2.f * hePt, 2.f * hePt - track.mcParticle().pt()); - spectraGen.fill(HIST("helium/histPtShiftVsEtaHe"), track.eta(), 2.f * hePt - track.mcParticle().pt()); + spectraGen.fill(HIST("helium/histPtShiftHeVsGen"), track.mcParticle().pt(), 2.f * hePt - track.mcParticle().pt()); + if (!heliumPID) + spectraGen.fill(HIST("helium/histPtShiftHe_WrongPidAll"), 2.f * hePt, 2.f * hePt - track.mcParticle().pt()); + if (tritonPID) + spectraGen.fill(HIST("helium/histPtShiftHe_WrongPidTr"), 2.f * hePt, 2.f * hePt - track.mcParticle().pt()); + if (deuteronPID) + spectraGen.fill(HIST("helium/histPtShiftHe_WrongPidDe"), 2.f * hePt, 2.f * hePt - track.mcParticle().pt()); + spectraGen.fill(HIST("helium/histPtShiftVsEtaHe"), track.eta(), 2.f * hePt - track.mcParticle().pt()); + if (track.hasTOF() && outFlagOptions.doTOFplots) { + spectraGen.fill(HIST("helium/TOF/histPtShiftHe"), 2.f * hePt, 2.f * hePt - track.mcParticle().pt()); + spectraGen.fill(HIST("helium/TOF/histPtShiftHeVsGen"), track.mcParticle().pt(), 2.f * hePt - track.mcParticle().pt()); + } spectraGen.fill(HIST("helium/histPGenHe"), std::abs(track.mcParticle().p())); spectraGen.fill(HIST("helium/histPRecHe"), 2.f * heP); spectraGen.fill(HIST("helium/histPShiftHe"), 2.f * heP, 2.f * heP - track.mcParticle().p()); @@ -3774,21 +3829,30 @@ struct LFNucleiBATask { } } } - if (isHeWoTPCpid) { + if (isAntiHeWoTPCpid) { if (isPhysPrim) { if constexpr (!IsFilteredData) { spectraGen.fill(HIST("helium/histPtGenantiHe"), std::abs(track.mcParticle().pt())); spectraGen.fill(HIST("helium/histPtRecantiHe"), 2.f * antihePt); spectraGen.fill(HIST("helium/histPtShiftantiHe"), 2.f * antihePt, 2.f * antihePt - track.mcParticle().pt()); - spectraGen.fill(HIST("helium/histPtShiftVsEtaantiHe"), track.eta(), 2.f * antihePt - track.mcParticle().pt()); + spectraGen.fill(HIST("helium/histPtShiftantiHeVsGen"), track.mcParticle().pt(), 2.f * antihePt - track.mcParticle().pt()); + if (!heliumPID) + spectraGen.fill(HIST("helium/histPtShiftantiHe_WrongPidAll"), 2.f * antihePt, 2.f * antihePt - track.mcParticle().pt()); + if (tritonPID) + spectraGen.fill(HIST("helium/histPtShiftantiHe_WrongPidTr"), 2.f * antihePt, 2.f * antihePt - track.mcParticle().pt()); + if (deuteronPID) + spectraGen.fill(HIST("helium/histPtShiftantiHe_WrongPidDe"), 2.f * antihePt, 2.f * antihePt - track.mcParticle().pt()); + spectraGen.fill(HIST("helium/histPtShiftVsEtaantiHe"), track.eta(), 2.f * antihePt - track.mcParticle().pt()); + if (track.hasTOF() && outFlagOptions.doTOFplots) { + spectraGen.fill(HIST("helium/TOF/histPtShiftantiHe"), 2.f * antihePt, 2.f * antihePt - track.mcParticle().pt()); + spectraGen.fill(HIST("helium/TOF/histPtShiftantiHeVsGen"), track.mcParticle().pt(), 2.f * antihePt - track.mcParticle().pt()); + } spectraGen.fill(HIST("helium/histPGenantiHe"), std::abs(track.mcParticle().p())); spectraGen.fill(HIST("helium/histPRecantiHe"), 2.f * antiheP); 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 (outFlagOptions.makeDCABeforeCutPlots) { - } } } } @@ -4574,7 +4638,7 @@ struct LFNucleiBATask { // TOF if (outFlagOptions.doTOFplots) { - if (isDeWoTPCpid) { + if (isDeWTPCpid) { switch (useHasTRDConfig) { case 0: histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTOF"), DPt, track.tofNSigmaDe()); @@ -4594,7 +4658,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/h2DeuteronTOFExpSignalDiffVsPt"), DPt, track.tofExpSignalDiffDe()); } - if (isAntiDeWoTPCpid) { + if (isAntiDeWTPCpid) { switch (useHasTRDConfig) { case 0: histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspTNSigmaTOF"), antiDPt, track.tofNSigmaDe()); @@ -4614,13 +4678,13 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/h2antiDeuteronTOFExpSignalDiffVsPt"), antiDPt, track.tofExpSignalDiffDe()); } - if (isHeWoTPCpid) { + if (isHeWTPCpid) { histos.fill(HIST("tracks/helium/h2HeliumVspTNSigmaTOF"), hePt, track.tofNSigmaHe()); if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/helium/h2HeliumTOFExpSignalDiffVsPt"), hePt, track.tofExpSignalDiffHe()); } - if (isAntiHeWoTPCpid) { + if (isAntiHeWTPCpid) { histos.fill(HIST("tracks/helium/h2antiHeliumVspTNSigmaTOF"), antihePt, track.tofNSigmaHe()); if (outFlagOptions.enableExpSignalTOF) histos.fill(HIST("tracks/helium/h2antiHeliumTOFExpSignalDiffVsPt"), antihePt, track.tofExpSignalDiffHe()); @@ -4815,6 +4879,8 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2HeliumEtavsPt_Z2"), track.eta(), 2 * hePt); if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumHelium"), heTPCmomentum, track.tpcSignal()); + if (enableDebug) + debugHistos.fill(HIST("tracks/helium/h2HeliumPidTrackingVsPt"), 2 * hePt, track.pidForTracking()); } if (isAntiHeWTPCpid) { if (outFlagOptions.enableEffPlots) { @@ -4826,6 +4892,8 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2antiHeliumEtavsPt_Z2"), track.eta(), 2 * antihePt); if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumantiHelium"), antiheTPCmomentum, track.tpcSignal()); + if (enableDebug) + debugHistos.fill(HIST("tracks/helium/h2antiHeliumPidTrackingVsPt"), 2 * antihePt, track.pidForTracking()); } if (outFlagOptions.doTOFplots && track.hasTOF()) { @@ -5811,13 +5879,19 @@ struct LFNucleiBATask { } if (isPhysPrim) { histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim_Z2"), 2 * hePt); - if (enableCentrality) + if (enableCentrality) { histos.fill(HIST("tracks/helium/h2HeliumSpectraTruePrimVsMult_Z2"), 2 * hePt, centFT0M); + if constexpr (!IsFilteredData) + histos.fill(HIST("tracks/helium/h2HeliumSpectraTruePrimGenVsMult_Z2"), track.mcParticle().pt(), centFT0M); + } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/TOF/h1HeliumSpectraTruePrim_Z2"), 2 * hePt); - if (enableCentrality) + if (enableCentrality) { histos.fill(HIST("tracks/helium/TOF/h2HeliumSpectraTruePrimVsMult_Z2"), 2 * hePt, centFT0M); + if constexpr (!IsFilteredData) + histos.fill(HIST("tracks/helium/TOF/h2HeliumSpectraTruePrimGenVsMult_Z2"), track.mcParticle().pt(), centFT0M); + } } } @@ -5886,14 +5960,20 @@ struct LFNucleiBATask { } if (isPhysPrim) { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim_Z2"), 2 * antihePt); - if (enableCentrality) + if (enableCentrality) { histos.fill(HIST("tracks/helium/h2antiHeliumSpectraTruePrimVsMult_Z2"), 2 * antihePt, centFT0M); + if constexpr (!IsFilteredData) + histos.fill(HIST("tracks/helium/h2antiHeliumSpectraTruePrimGenVsMult_Z2"), track.mcParticle().pt(), centFT0M); + } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/TOF/h1antiHeliumSpectraTruePrim_Z2"), 2 * antihePt); - if (enableCentrality) + if (enableCentrality) { histos.fill(HIST("tracks/helium/TOF/h2antiHeliumSpectraTruePrimVsMult_Z2"), 2 * antihePt, centFT0M); + if constexpr (!IsFilteredData) + histos.fill(HIST("tracks/helium/TOF/h2antiHeliumSpectraTruePrimGenVsMult_Z2"), track.mcParticle().pt(), centFT0M); + } } } diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index e91b29ce65f..b2576226bce 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -20,6 +20,7 @@ #include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/Zorro.h" @@ -34,7 +35,6 @@ #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" -#include "MathUtils/BetheBlochAleph.h" #include "Framework/ASoA.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" @@ -44,6 +44,7 @@ #include "Framework/Logger.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" @@ -89,10 +90,9 @@ using std::array; // Define convenient aliases for commonly used table joins using SelectedCollisions = soa::Join; using RecCollisionsMc = soa::Join; -using GenCollisionsMc = aod::McCollisions; +using GenCollisionsMc = soa::Join; using AntiNucleiTracks = soa::Join; using AntiNucleiTracksMc = soa::Join; - using LorentzVector = ROOT::Math::PxPyPzEVector; // Lightweight particle container for fast kinematic access @@ -128,8 +128,19 @@ struct ReducedParticle { } }; +// Jet Matching +struct JetMatching { + double distance; + double ptTrue; + double ptDiff; +}; + struct AntinucleiInJets { + // Random engine + std::mt19937 rng; + std::uniform_int_distribution generateRandomNr{0, 1}; + // Histogram registries for data, MC, quality control, multiplicity and correlations HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -140,6 +151,13 @@ struct AntinucleiInJets { // Random generator for subsample assignment TRandom3 mRand; + // Parameters for ppRef analysis + Configurable isppRefAnalysis{"isppRefAnalysis", false, "Is ppRef analysis"}; + Configurable cfgAreaFrac{"cfgAreaFrac", 0.6, "fraction of jet area"}; + Configurable cfgEtaJetMax{"cfgEtaJetMax", 0.5, "max jet eta"}; + Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.1, "minimum pt of tracks for jet reconstruction"}; + Configurable alpha{"alpha", 0.3, "parameter to control jet matching"}; + // Event selection criteria Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "Reject events near the ITS ROF border"}; Configurable rejectTFBorder{"rejectTFBorder", true, "Reject events near the TF border"}; @@ -154,8 +172,9 @@ struct AntinucleiInJets { // Jet selection and event filtering parameters Configurable minJetPt{"minJetPt", 10.0, "Minimum pt of the jet after bkg subtraction"}; + Configurable maxJetPt{"maxJetPt", 1e+06, "Maximum pt of the jet after bkg subtraction"}; Configurable ptLeadingMin{"ptLeadingMin", 5.0, "pt Leading Min"}; - Configurable rJet{"rJet", 0.3, "Jet resolution parameter R"}; + Configurable rJet{"rJet", 0.4, "Jet resolution parameter R"}; Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; Configurable applyAreaCut{"applyAreaCut", true, "apply area cut"}; Configurable maxNormalizedJetArea{"maxNormalizedJetArea", 1.0, "area cut"}; @@ -191,15 +210,15 @@ struct AntinucleiInJets { // Configuration parameters for CCDB access and reweighting input files Configurable applyReweighting{"applyReweighting", true, "enable reweighting for efficiency"}; - Configurable urlToCcdb{"urlToCcdb", "http://alice-ccdb.cern.ch", "url of the personal ccdb"}; - Configurable pathToFile{"pathToFile", "Users/a/alcaliva/reweightingHistogramsAntipInJet", "path to file"}; - Configurable weightsProton{"weightsProton", "", "weightsProton"}; - Configurable weightsLambda{"weightsLambda", "", "weightsLambda"}; - Configurable weightsSigma{"weightsSigma", "", "weightsSigma"}; - Configurable weightsXi{"weightsXi", "", "weightsXi"}; - Configurable weightsOmega{"weightsOmega", "", "weightsOmega"}; - Configurable weightsJet{"weightsJet", "", "weightsJet"}; - Configurable weightsUe{"weightsUe", "", "weightsUe"}; + Configurable urlToCcdb{"urlToCcdb", "http://alice-ccdb.cern.ch/", "url of the personal ccdb"}; + Configurable pathToFile{"pathToFile", "Users/a/alcaliva/reweightingHistogramsAnalysis/", "path to file"}; + Configurable weightsProton{"weightsProton", "weightsProton", "weightsProton"}; + Configurable weightsLambda{"weightsLambda", "weightsLambda", "weightsLambda"}; + Configurable weightsSigma{"weightsSigma", "weightsSigma", "weightsSigma"}; + Configurable weightsXi{"weightsXi", "weightsXi", "weightsXi"}; + Configurable weightsOmega{"weightsOmega", "weightsOmega", "weightsOmega"}; + Configurable weightsJet{"weightsJet", "weightsJet", "weightsJet"}; + Configurable weightsUe{"weightsUe", "weightsUe", "weightsUe"}; // Number of events Configurable shrinkInterval{"shrinkInterval", 1000, "variable that controls how often shrinking happens"}; @@ -261,6 +280,9 @@ struct AntinucleiInJets { auto timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count(); mRand.SetSeed(timeSeed); + // Set seed of random engine + rng.seed(12345); + // Load reweighting histograms from CCDB if antinuclei efficiency processing is enabled if (doprocessAntinucleiEfficiency || doprocessJetsMCgen || doprocessJetsMCrec) { ccdb->setURL(urlToCcdb.value); @@ -313,6 +335,7 @@ struct AntinucleiInJets { // Jet effective area over piR^2 registryData.add("jetEffectiveAreaOverPiR2", "jet effective area / piR^2", HistType::kTH1F, {{2000, 0, 2, "Area/#piR^{2}"}}); + registryData.add("jetArea", "jetArea", HistType::kTH1F, {{5000, 0, 5, "area"}}); // angle between track and jet axis registryData.add("theta_track_jet", "theta_track_jet", HistType::kTH2F, {{100, 0, 100, "#it{p}^{jet}_{T} (GeV/#it{c})"}, {400, 0, 20.0, "#theta_{track-jet} (deg)"}}); @@ -324,12 +347,16 @@ struct AntinucleiInJets { 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, -1.0, 1.0, "DCA_{xy} (cm)"}}); registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1.0, 1.0, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_fullEvent_tpc", "antiproton_fullEvent_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antiproton_fullEvent_tof", "antiproton_fullEvent_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); // Antideuterons registryData.add("antideuteron_jet_tpc", "antideuteron_jet_tpc", HistType::kTH2F, {{nbins, 2 * min, 2 * max, "#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, 2 * min, 2 * max, "#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, 2 * min, 2 * max, "#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, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antideuteron_fullEvent_tpc", "antideuteron_fullEvent_tpc", HistType::kTH2F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antideuteron_fullEvent_tof", "antideuteron_fullEvent_tof", HistType::kTH2F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); // Deuterons registryData.add("deuteron_jet_tpc", "deuteron_jet_tpc", HistType::kTH2F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); @@ -369,6 +396,12 @@ struct AntinucleiInJets { registryMC.add("antiproton_gen_ue", "antiproton_gen_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_gen_full", "antiproton_gen_full", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Generated spectra of antiprotons for closure test + registryMC.add("antiproton_gen_jet_data", "antiproton_gen_jet_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_data", "antiproton_gen_ue_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_jet_mc", "antiproton_gen_jet_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_mc", "antiproton_gen_ue_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Normalization histogram registryMC.add("antiproton_deltay_deltaphi_jet", "antiproton_deltay_deltaphi_jet", HistType::kTH2F, {{2000, -1.0, 1.0, "#Delta#it{y}"}, {2000, 0.0, 2.0, "#Delta#phi"}}); registryMC.add("antiproton_deltay_deltaphi_ue", "antiproton_deltay_deltaphi_ue", HistType::kTH2F, {{2000, -1.0, 1.0, "#Delta#it{y}"}, {2000, 0.0, 2.0, "#Delta#phi"}}); @@ -396,6 +429,16 @@ struct AntinucleiInJets { registryMC.add("antiproton_rec_tpc_full", "antiproton_rec_tpc_full", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_rec_tof_full", "antiproton_rec_tof_full", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Reconstructed spectra of antiprotons for closure test + registryMC.add("antiproton_rec_tpc_jet_data", "antiproton_rec_tpc_jet_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_jet_data", "antiproton_rec_tof_jet_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_ue_data", "antiproton_rec_tpc_ue_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_ue_data", "antiproton_rec_tof_ue_data", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_jet_mc", "antiproton_rec_tpc_jet_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_jet_mc", "antiproton_rec_tof_jet_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_ue_mc", "antiproton_rec_tpc_ue_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_ue_mc", "antiproton_rec_tof_ue_mc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // Fraction of primary antiprotons registryMC.add("antiproton_prim_jet", "antiproton_prim_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_incl_jet", "antiproton_incl_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); @@ -489,6 +532,43 @@ struct AntinucleiInJets { registryMC.add("antiproton_coal_ue", "antiproton_coal_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); } + // jet pt resolution + if (doprocessJetPtResolution) { + registryMC.add("jetPtResolution", "jet Pt Resolution", HistType::kTH2F, {{1000, 0, 100, "#it{p}^{jet}_{T,true} (GeV/#it{c})"}, {1000, -20, 20, "#Delta #it{p}^{jet}_{T} (GeV/#it{c})"}}); + } + + // Coalescence and Correlation analysis + if (doprocessCoalescenceCorr) { + + // Axes definitions for multidimensional histogram binning + const AxisSpec multiplicityAxis{100, 0.0, 100.0, "multiplicity percentile"}; + const AxisSpec ptPerNucleonAxis{5, 0.4, 0.9, "{p}_{T}/A (GeV/#it{c})"}; + const AxisSpec nAntideuteronsAxis{10, 0.0, 10.0, "N_{#bar{d}}"}; + const AxisSpec nAntiprotonsAxis{10, 0.0, 10.0, "N_{#bar{p}}"}; + const AxisSpec nBarD2Axis{100, 0.0, 100.0, "N_{#bar{d}}^{i} #times N_{#bar{d}}^{j}"}; + const AxisSpec nBarP2Axis{100, 0.0, 100.0, "N_{#bar{p}}^{i} #times N_{#bar{p}}^{j}"}; + const AxisSpec nBarDnBarPAxis{100, 0.0, 100.0, "N_{#bar{d}}^{i} #times N_{#bar{p}}^{j}"}; + + registryMC.add("genEventsCoalescenceCorr", "genEventsCoalescenceCorr", HistType::kTH1F, {{20, 0, 20, "counter"}}); + registryMC.add("antideuteron_fullEvent_CoalescenceCorr", "antideuteron_fullEvent_CoalescenceCorr", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_fullEvent_CoalescenceCorr", "antiproton_fullEvent_CoalescenceCorr", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Counter histograms + registryCorr.add("eventCounter_CoalescenceCorr", "number of events in Coalescence simulation", HistType::kTH1F, {{20, 0, 20, "counter"}}); + registryCorr.add("eventCounter_centrality_fullEvent_CoalescenceCorr", "Number of events per centrality (Full Event) in Coalescence simulation", HistType::kTH1F, {multiplicityAxis}); + + // Correlation histograms + registryCorr.add("rho_fullEvent_CoalescenceCorr", "rho_fullEvent_CoalescenceCorr", HistType::kTH3F, {nAntideuteronsAxis, nAntiprotonsAxis, multiplicityAxis}); + registryCorr.add("rho_netP_netD_fullEvent_CoalescenceCorr", "rho_netP_netD_fullEvent_CoalescenceCorr", HistType::kTH2F, {nAntideuteronsAxis, nAntiprotonsAxis}); + + // Efficiency histograms full event + registryCorr.add("q1d_fullEvent_CoalescenceCorr", "q1d_fullEvent_CoalescenceCorr", HistType::kTH3F, {nAntideuteronsAxis, ptPerNucleonAxis, multiplicityAxis}); + registryCorr.add("q1p_fullEvent_CoalescenceCorr", "q1p_fullEvent_CoalescenceCorr", HistType::kTH3F, {nAntiprotonsAxis, ptPerNucleonAxis, multiplicityAxis}); + registryCorr.add("q1d_square_fullEvent_CoalescenceCorr", "q1d_square_fullEvent_CoalescenceCorr", HistType::kTHnSparseD, {ptPerNucleonAxis, ptPerNucleonAxis, nBarD2Axis, multiplicityAxis}); + registryCorr.add("q1p_square_fullEvent_CoalescenceCorr", "q1p_square_fullEvent_CoalescenceCorr", HistType::kTHnSparseD, {ptPerNucleonAxis, ptPerNucleonAxis, nBarP2Axis, multiplicityAxis}); + registryCorr.add("q1d_q1p_fullEvent_CoalescenceCorr", "q1d_q1p_fullEvent_CoalescenceCorr", HistType::kTHnSparseD, {ptPerNucleonAxis, ptPerNucleonAxis, nBarDnBarPAxis, multiplicityAxis}); + } + // Systematic uncertainties (Data) if (doprocessSystData) { registryData.add("number_of_events_data_syst", "event counter", HistType::kTH1F, {{20, 0, 20, "counter"}}); @@ -835,7 +915,6 @@ struct AntinucleiInJets { static constexpr int MinTpcCr = 70; static constexpr double MaxChi2Tpc = 4.0; static constexpr double MaxChi2Its = 36.0; - static constexpr double MinPtTrack = 0.1; static constexpr double DcaxyMaxTrackPar0 = 0.0105; static constexpr double DcaxyMaxTrackPar1 = 0.035; static constexpr double DcaxyMaxTrackPar2 = 1.1; @@ -855,7 +934,7 @@ struct AntinucleiInJets { return false; if (std::fabs(track.eta()) > maxEta) return false; - if (track.pt() < MinPtTrack) + if (track.pt() < cfgMinPtTrack) return false; if (std::fabs(track.dcaXY()) > (DcaxyMaxTrackPar0 + DcaxyMaxTrackPar1 / std::pow(track.pt(), DcaxyMaxTrackPar2))) return false; @@ -1120,6 +1199,56 @@ struct AntinucleiInJets { return; registryData.fill(HIST("number_of_events_data"), 8.5); + // Loop over all tracks for Full Event histograms + for (auto const& track : tracks) { + // Apply standard track selection + if (!passedTrackSelection(track)) + continue; + + // Define variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double nsigmaTPCDe = track.tpcNSigmaDe(); + double nsigmaTOFDe = track.tofNSigmaDe(); + double pt = track.pt(); + + // ITS PID logic + bool passedItsPidProt(true), passedItsPidDeut(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; + } + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; + } + + // Fill histograms for antimatter + if (track.sign() < 0) { + + // Antiprotons Full Event + if (passedItsPidProt) { + registryData.fill(HIST("antiproton_fullEvent_tpc"), pt, nsigmaTPCPr); + + // Require TOF matching and preliminary TPC cut + if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc && track.hasTOF()) { + registryData.fill(HIST("antiproton_fullEvent_tof"), pt, nsigmaTOFPr); + } + } + + // Antideuterons Full Event + if (passedItsPidDeut) { + registryData.fill(HIST("antideuteron_fullEvent_tpc"), pt, nsigmaTPCDe); + + // Require TOF matching and preliminary TPC cut + if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc && track.hasTOF()) { + registryData.fill(HIST("antideuteron_fullEvent_tof"), pt, nsigmaTOFDe); + } + } + } + } + // Loop over reconstructed tracks int id(-1); std::vector fjParticles; @@ -1156,18 +1285,24 @@ struct AntinucleiInJets { for (const auto& jet : jets) { // Jet must be fully contained in the acceptance - if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) + if (!isppRefAnalysis && ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge))) + continue; + if (isppRefAnalysis && std::fabs(jet.eta()) > cfgEtaJetMax) continue; // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (jetMinusBkg.pt() < minJetPt) + if (isppRefAnalysis && (jet.pt() < minJetPt || jet.pt() > maxJetPt)) + continue; + if (!isppRefAnalysis && (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt)) continue; // Apply area cut if required double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + if (applyAreaCut && (!isppRefAnalysis) && normalizedJetArea > maxNormalizedJetArea) + continue; + if (isppRefAnalysis && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; @@ -1182,6 +1317,7 @@ struct AntinucleiInJets { // Fill histogram with jet effective area / piR^2 registryData.fill(HIST("jetEffectiveAreaOverPiR2"), jet.area() / (PI * rJet * rJet)); + registryData.fill(HIST("jetArea"), jet.area()); // Get jet constituents std::vector jetConstituents = jet.constituents(); @@ -1443,7 +1579,7 @@ struct AntinucleiInJets { // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (jetMinusBkg.pt() < minJetPt) + if (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt) continue; // Apply area cut if required @@ -1521,7 +1657,7 @@ struct AntinucleiInJets { registryQC.fill(HIST("ptDistributionJetCone"), ptJetBeforeSub); registryQC.fill(HIST("ptDistributionJet"), ptJetAfterSub); - if (jetMinusBkg.pt() < minJetPt) + if (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt) continue; njetsHighPt++; registryQC.fill(HIST("sumPtJet"), jet.pt()); @@ -1931,6 +2067,10 @@ struct AntinucleiInJets { // Get particles in this MC collision const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + // Generate random number to decide if simulated event has to be considered as data or MC in the closure test + int sample = generateRandomNr(rng); + bool isPseudoData = (sample == 0); + // Loop over MC particles for (const auto& particle : mcParticlesThisMcColl) { @@ -1975,18 +2115,24 @@ struct AntinucleiInJets { for (const auto& jet : jets) { // Jet must be fully contained in the acceptance - if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) + if (!isppRefAnalysis && ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge))) + continue; + if (isppRefAnalysis && std::fabs(jet.eta()) > cfgEtaJetMax) continue; // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (jetMinusBkg.pt() < minJetPt) + if (isppRefAnalysis && (jet.pt() < minJetPt || jet.pt() > maxJetPt)) + continue; + if (!isppRefAnalysis && (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt)) continue; // Apply area cut if required double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + if (applyAreaCut && (!isppRefAnalysis) && normalizedJetArea > maxNormalizedJetArea) + continue; + if (isppRefAnalysis && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; @@ -2015,6 +2161,13 @@ struct AntinucleiInJets { // Fill histogram for generated antiprotons registryMC.fill(HIST("antiproton_gen_jet"), particle.pt(), weightJet); + // Fill histograms for generated antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_gen_jet_data"), particle.pt()); + } else { + registryMC.fill(HIST("antiproton_gen_jet_mc"), particle.pt()); + } + // Fill 2d (pt,eta) distribution of antiprotons registryMC.fill(HIST("antiproton_eta_pt_jet"), particle.pt(), particle.eta(), weightJet); } @@ -2063,12 +2216,24 @@ struct AntinucleiInJets { // Fill histogram for antiprotons in the UE registryMC.fill(HIST("antiproton_gen_ue"), protonVec.Pt(), weightUe); + // Fill histograms for generated antiprotons for closure test + if (sample == 0) { + registryMC.fill(HIST("antiproton_gen_ue_data"), protonVec.Pt()); + } else { + registryMC.fill(HIST("antiproton_gen_ue_mc"), protonVec.Pt()); + } + // Fill 2d (pt,eta) distribution of antiprotons registryMC.fill(HIST("antiproton_eta_pt_ue"), protonVec.Pt(), protonVec.Eta(), weightUe); } } if (isAtLeastOneJetSelected) { registryMC.fill(HIST("genEvents"), 3.5); + if (isPseudoData) { + registryMC.fill(HIST("genEvents"), 4.5); + } else { + registryMC.fill(HIST("genEvents"), 5.5); + } } // Shrink large vectors @@ -2150,6 +2315,10 @@ struct AntinucleiInJets { // Get tracks in this MC collision const auto mcTracksThisMcColl = mcTracks.sliceBy(mcTracksPerMcCollision, collision.globalIndex()); + // Generate random number to decide if simulated event has to be considered as data or MC in the closure test + int sample = generateRandomNr(rng); + bool isPseudoData = (sample == 0); + // Loop over reconstructed tracks int id(-1); for (auto const& track : mcTracksThisMcColl) { @@ -2203,18 +2372,24 @@ struct AntinucleiInJets { for (const auto& jet : jets) { // Jet must be fully contained in the acceptance - if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) + if (!isppRefAnalysis && ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge))) + continue; + if (isppRefAnalysis && std::fabs(jet.eta()) > cfgEtaJetMax) continue; // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (jetMinusBkg.pt() < minJetPt) + if (isppRefAnalysis && (jet.pt() < minJetPt || jet.pt() > maxJetPt)) + continue; + if (!isppRefAnalysis && (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt)) continue; // Apply area cut if required double normalizedJetArea = jet.area() / (PI * rJet * rJet); - if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + if (applyAreaCut && (!isppRefAnalysis) && normalizedJetArea > maxNormalizedJetArea) + continue; + if (isppRefAnalysis && (jet.area() < cfgAreaFrac * PI * rJet * rJet)) continue; isAtLeastOneJetSelected = true; @@ -2308,8 +2483,23 @@ struct AntinucleiInJets { // Fill histograms (TPC and TOF) only for selected candidates if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { registryMC.fill(HIST("antiproton_rec_tpc_jet"), pt, weightJet); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tpc_jet_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tpc_jet_mc"), pt); + } + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { registryMC.fill(HIST("antiproton_rec_tof_jet"), pt, weightJet); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tof_jet_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tof_jet_mc"), pt); + } } } } @@ -2390,14 +2580,34 @@ struct AntinucleiInJets { // Fill histograms (TPC and TOF) only for selected candidates if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { registryMC.fill(HIST("antiproton_rec_tpc_ue"), pt, weightUe); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tpc_ue_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tpc_ue_mc"), pt); + } + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { registryMC.fill(HIST("antiproton_rec_tof_ue"), pt, weightUe); + + // Fill histograms for reconstructed antiprotons for closure test + if (isPseudoData) { + registryMC.fill(HIST("antiproton_rec_tof_ue_data"), pt); + } else { + registryMC.fill(HIST("antiproton_rec_tof_ue_mc"), pt); + } } } } } if (isAtLeastOneJetSelected) { registryMC.fill(HIST("recEvents"), 9.5); + if (isPseudoData) { + registryMC.fill(HIST("recEvents"), 10.5); + } else { + registryMC.fill(HIST("recEvents"), 11.5); + } } // Shrink large vectors @@ -2954,7 +3164,7 @@ struct AntinucleiInJets { // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (jetMinusBkg.pt() < minJetPt) + if (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt) continue; // Apply area cut if required @@ -3532,7 +3742,7 @@ struct AntinucleiInJets { // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (jetMinusBkg.pt() < minJetPt) + if (jetMinusBkg.pt() < minJetPt || jetMinusBkg.pt() > maxJetPt) continue; // Apply area cut if required @@ -3597,6 +3807,356 @@ struct AntinucleiInJets { } } PROCESS_SWITCH(AntinucleiInJets, processCoalescence, "process coalescence", false); + + // process Coalescence and Correlation Analysis + void processCoalescenceCorr(GenCollisionsMc const& collisions, aod::McParticles const& mcParticles) + { + // Deuteron Mass and minimum pt + double massDeut = o2::constants::physics::MassDeuteron; + static constexpr double MinPtPerNucleon = 0.1; // Cut on pt/A + + // Containers for candidates (before coalescence) + std::vector protonCandidates; + std::vector neutronCandidates; + + // Final containers for analysis (after coalescence) + std::vector finalProtons; + std::vector finalDeuterons; + + // pt/A bins + std::vector ptOverAbins = {0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; + const int nBins = ptOverAbins.size() - 1; + + // Loop over all simulated collisions + for (const auto& collision : collisions) { + + // Clear containers + protonCandidates.clear(); + neutronCandidates.clear(); + finalProtons.clear(); + finalDeuterons.clear(); + + // Event counter: before event selection + registryCorr.fill(HIST("eventCounter_CoalescenceCorr"), 0.5); + registryMC.fill(HIST("genEventsCoalescenceCorr"), 0.5); + + // Apply event selection: require vertex position to be within the allowed z range + if (std::fabs(collision.posZ()) > zVtx) + continue; + + // Event counter: after event selection + registryCorr.fill(HIST("eventCounter_CoalescenceCorr"), 1.5); + registryMC.fill(HIST("genEventsCoalescenceCorr"), 1.5); + + // Multiplicity percentile + const float multiplicity = collision.centFT0M(); + + // Fill event counter vs centrality + registryCorr.fill(HIST("eventCounter_centrality_fullEvent_CoalescenceCorr"), multiplicity); + + // Get particles in this MC collision + const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + + // Loop over MC particles + for (const auto& particle : mcParticlesThisMcColl) { + + // Monte Carlo index + int mcId = particle.globalIndex(); + int pdg = particle.pdgCode(); + int absPdg = std::abs(pdg); + + // Store Protons + if (particle.isPhysicalPrimary()) { + if (absPdg == PDG_t::kProton) { + protonCandidates.push_back({particle.px(), particle.py(), particle.pz(), pdg, mcId, false}); + } else if (absPdg == PDG_t::kNeutron) { // Store Neutrons + neutronCandidates.push_back({particle.px(), particle.py(), particle.pz(), pdg, mcId, false}); + } + } + } + + // Reject empty events + if (protonCandidates.empty() && neutronCandidates.empty()) + continue; + + registryMC.fill(HIST("genEventsCoalescenceCorr"), 2.5); + + // Build deuterons + for (size_t iP = 0; iP < protonCandidates.size(); ++iP) { + if (protonCandidates[iP].used) + continue; + + for (size_t iN = 0; iN < neutronCandidates.size(); ++iN) { + if (neutronCandidates[iN].used) + continue; + + // Physics consistency check + if (protonCandidates[iP].pdgCode * neutronCandidates[iN].pdgCode < 0) + continue; + + if (passDeuteronCoalescence(protonCandidates[iP], neutronCandidates[iN], coalescenceMomentum, mRand)) { + neutronCandidates[iN].used = true; + protonCandidates[iP].used = true; + + int sign = (protonCandidates[iP].pdgCode > 0) ? +1 : -1; + int deuteronPdg = sign * o2::constants::physics::Pdg::kDeuteron; + + double pxDeut = protonCandidates[iP].px + neutronCandidates[iN].px; + double pyDeut = protonCandidates[iP].py + neutronCandidates[iN].py; + double pzDeut = protonCandidates[iP].pz + neutronCandidates[iN].pz; + double energyDeut = std::sqrt(pxDeut * pxDeut + pyDeut * pyDeut + pzDeut * pzDeut + massDeut * massDeut); + LorentzVector pd(pxDeut, pyDeut, pzDeut, energyDeut); + if (pd.Eta() >= minEta && pd.Eta() <= maxEta && (0.5 * pd.Pt()) >= MinPtPerNucleon) { + // Store Deuteron + finalDeuterons.push_back({pxDeut, pyDeut, pzDeut, deuteronPdg, protonCandidates[iP].mcIndex, false}); + } + + break; + } + } + } + + // Add unused protons to final vectors + for (const auto& proton : protonCandidates) { + if (!proton.used) { + finalProtons.push_back(proton); + } + } + + // Correlation Analysis + std::vector nAntiprotonFullEvent(nBins, 0); + std::vector nAntideuteronFullEvent(nBins, 0); + int nTotProtonFullEvent(0); + int nTotDeuteronFullEvent(0); + int nTotAntiprotonFullEvent(0); + int nTotAntideuteronFullEvent(0); + + // Loop over final protons + for (const auto& part : finalProtons) { + double pt = std::hypot(part.px, part.py); + + if (part.eta() < minEta || part.eta() > maxEta) + continue; + + // Standard histograms for antiprotons + if (part.pdgCode == PDG_t::kProtonBar) { + registryMC.fill(HIST("antiproton_fullEvent_CoalescenceCorr"), pt); + } + + // Kinematic selection and Multiplicity counting + if (pt < ptOverAbins[0] || pt >= ptOverAbins[nBins]) + continue; + + if (part.pdgCode > 0) { + nTotProtonFullEvent++; + } else { + nTotAntiprotonFullEvent++; + int ibin = findBin(ptOverAbins, pt); + if (ibin >= 0 && ibin < nBins) + nAntiprotonFullEvent[ibin]++; + } + } + + // Loop over final deuterons + for (const auto& part : finalDeuterons) { + double pt = std::hypot(part.px, part.py); + double ptPerNucleon = 0.5 * pt; + + // Apply detector acceptance cuts (to match real data) + if (part.eta() < minEta || part.eta() > maxEta) + continue; + + // Standard histograms for antideuterons + if (part.pdgCode == -o2::constants::physics::Pdg::kDeuteron) { + registryMC.fill(HIST("antideuteron_fullEvent_CoalescenceCorr"), pt); + } + + // Kinematic selection and Multiplicity counting + if (ptPerNucleon < ptOverAbins[0] || ptPerNucleon >= ptOverAbins[nBins]) + continue; + + if (part.pdgCode > 0) { + nTotDeuteronFullEvent++; + } else { + nTotAntideuteronFullEvent++; + int ibin = findBin(ptOverAbins, ptPerNucleon); + if (ibin >= 0 && ibin < nBins) + nAntideuteronFullEvent[ibin]++; + } + } + + // Fill correlation histograms + int netProtonFullEvent = nTotProtonFullEvent - nTotAntiprotonFullEvent; + int netDeuteronFullEvent = nTotDeuteronFullEvent - nTotAntideuteronFullEvent; + + registryCorr.fill(HIST("rho_fullEvent_CoalescenceCorr"), nTotAntideuteronFullEvent, nTotAntiprotonFullEvent, multiplicity); + registryCorr.fill(HIST("rho_netP_netD_fullEvent_CoalescenceCorr"), netDeuteronFullEvent, netProtonFullEvent); + + // Fill efficiency histograms + for (int i = 0; i < nBins; i++) { + double ptAcenteri = 0.5 * (ptOverAbins[i] + ptOverAbins[i + 1]); + + registryCorr.fill(HIST("q1d_fullEvent_CoalescenceCorr"), nAntideuteronFullEvent[i], ptAcenteri, multiplicity); + registryCorr.fill(HIST("q1p_fullEvent_CoalescenceCorr"), nAntiprotonFullEvent[i], ptAcenteri, multiplicity); + + for (int j = 0; j < nBins; j++) { + double ptAcenterj = 0.5 * (ptOverAbins[j] + ptOverAbins[j + 1]); + + registryCorr.fill(HIST("q1d_square_fullEvent_CoalescenceCorr"), ptAcenteri, ptAcenterj, static_cast(nAntideuteronFullEvent[i] * nAntideuteronFullEvent[j]), multiplicity); + registryCorr.fill(HIST("q1p_square_fullEvent_CoalescenceCorr"), ptAcenteri, ptAcenterj, static_cast(nAntiprotonFullEvent[i] * nAntiprotonFullEvent[j]), multiplicity); + registryCorr.fill(HIST("q1d_q1p_fullEvent_CoalescenceCorr"), ptAcenteri, ptAcenterj, static_cast(nAntideuteronFullEvent[i] * nAntiprotonFullEvent[j]), multiplicity); + } + } + } + } + PROCESS_SWITCH(AntinucleiInJets, processCoalescenceCorr, "process coalescence correlation", false); + + // Jet Pt resolution + void processJetPtResolution(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles) + { + // Define per-event particle containers + std::vector fjParticles; + std::vector fjTracks; + + // Jet and area definitions + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over all reconstructed collisions + for (const auto& collision : collisions) { + + // Clear containers at the start of the event loop + fjParticles.clear(); + fjTracks.clear(); + + // Reject reconstructed collisions with no simulated collision + if (!collision.has_mcCollision()) + continue; + + // Apply event selection: require sel8 and vertex position to be within the allowed z range + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + continue; + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + continue; + + // Get tracks and particles in this MC collision + const auto mcTracksThisMcColl = mcTracks.sliceBy(mcTracksPerMcCollision, collision.globalIndex()); + const auto mcParticlesThisMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, collision.globalIndex()); + + // Loop over reconstructed tracks + for (auto const& track : mcTracksThisMcColl) { + + // Apply track selection for jet reconstruction + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); + fjTracks.emplace_back(fourMomentum); + } + + // Loop over MC particles + for (const auto& particle : mcParticlesThisMcColl) { + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + continue; + + // Select particles within acceptance + if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < cfgMinPtTrack) + continue; + + // 4-momentum representation of a particle + double energy = std::sqrt(particle.p() * particle.p() + MassPionCharged * MassPionCharged); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fjParticles.emplace_back(fourMomentum); + } + + // Reject empty events + if (fjTracks.empty() || fjParticles.empty()) + continue; + + // Cluster particles using the anti-kt algorithm + fastjet::ClusterSequenceArea csRec(fjTracks, jetDef, areaDef); + std::vector jetsRec = fastjet::sorted_by_pt(csRec.inclusive_jets()); + + fastjet::ClusterSequenceArea csGen(fjParticles, jetDef, areaDef); + std::vector jetsGen = fastjet::sorted_by_pt(csGen.inclusive_jets()); + + // Loop over reconstructed jets + std::vector jetGenRec; + for (const auto& jetRec : jetsRec) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jetRec.eta()) + rJet) > (maxEta - deltaEtaEdge)) + continue; + + // Apply area cut if required + if (applyAreaCut && (jetRec.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + continue; + + // Clear jet-pair container + jetGenRec.clear(); + + for (const auto& jetGen : jetsGen) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jetGen.eta()) + rJet) > (maxEta - deltaEtaEdge)) + continue; + + // Apply area cut if required + if (applyAreaCut && (jetGen.area() / (PI * rJet * rJet)) > maxNormalizedJetArea) + continue; + + double deltaEta = jetGen.eta() - jetRec.eta(); + double deltaPhi = getDeltaPhi(jetGen.phi(), jetRec.phi()); + double deltaR = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + if (deltaR < rJet) + jetGenRec.push_back({deltaR, jetGen.pt(), jetGen.pt() - jetRec.pt()}); + } + if (jetGenRec.empty()) + continue; + + double distanceMin(1e+06); + double diffPt(0); + double ptJetTrue(0); + for (const auto& jetPair : jetGenRec) { + if (jetPair.distance < distanceMin) { + distanceMin = jetPair.distance; + diffPt = jetPair.ptDiff; + ptJetTrue = jetPair.ptTrue; + } + } + + if (distanceMin < alpha * rJet) { + registryMC.fill(HIST("jetPtResolution"), ptJetTrue, diffPt); + } + } + } + } + PROCESS_SWITCH(AntinucleiInJets, processJetPtResolution, "process jet pt resolution", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx index 441056dc30e..0966ad1a97d 100644 --- a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -49,12 +49,13 @@ using PIDTracks = soa::Join< aod::Tracks, aod::TracksExtra, aod::TrackSelectionExtension, aod::TracksDCA, aod::TrackSelection, aod::pidTOFFullPi, aod::pidTOFFullPr, aod::pidTOFFullEl, aod::pidTOFbeta, aod::pidTPCPi, aod::pidTPCPr, aod::pidTPCEl>; -using SelectedCollisions = soa::Join; +using SelectedCollisions = soa::Join; using BCsRun3 = soa::Join; -static constexpr int kNCentHists{10}; -std::array, kNCentHists> hDedxVsMomentumVsCentPos{}; -std::array, kNCentHists> hDedxVsMomentumVsCentNeg{}; +static constexpr int NCentHists{10}; +std::array, NCentHists> hDedxVsMomentumVsCentPos{}; +std::array, NCentHists> hDedxVsMomentumVsCentNeg{}; struct DedxPidAnalysis { @@ -66,9 +67,9 @@ struct DedxPidAnalysis { true, true}; // Constant values - static constexpr int kEtaIntervals = 8; - static constexpr int kParticlesType = 4; - static constexpr int kCentralityClasses = 10; + static constexpr int EtaIntervals = 8; + static constexpr int ParticlesType = 4; + static constexpr int CentralityClasses = 10; float tpcCut = 0.6; float pionMin = 0.35; float pionMax = 0.45; @@ -78,14 +79,35 @@ struct DedxPidAnalysis { bool fillHist = false; - enum V0SelectionMode { + enum MultSelectionMode : int { + NoMultiplicity = 0, + MultFV0A = 1, + MultFT0M = 2, + MultFDDM = 3, + MultTracklets = 4, + MultTPC = 5, + MultNTracksPV = 6, + MultNTracksPVeta1 = 7, + CentralityFT0C = 8, + CentralityFT0M = 9, + CentralityFV0A = 10 + }; + + enum V0SelectionMode : int { V0TPC = 1, V0TOF = 2, V0TPCTOF = 3 }; - enum MomentumMode { + enum NINELSelectionMode : int { + NoSelINEL = 1, + SelINELgt0 = 2, + SelINELgt1 = 3 + + }; + + enum MomentumMode : int { TpcInnerParam = 1, TotalMomentum = 2 }; @@ -96,8 +118,8 @@ struct DedxPidAnalysis { SelEigth, ZVtxCut, NoSameBunchPileup, - GoodZvtxFT0vsPV - + GoodZvtxFT0vsPV, + INELgt }; // Track primary label @@ -105,34 +127,44 @@ struct DedxPidAnalysis { AllPri = 1, SelectionPrim, PhiVarCutPri, - NClTPCFoundCutPri, - NClTPCPIDCutPri + NClTPCPIDCutPri, + NClTPCFoundCutPri }; // Track secondary lebel enum TrkSecCutLabel { AllSec = 1, - V0Type, V0CosPA, V0DecayRadius, V0Daughters, - TPCRefit, PhiVarCutSec, NClTPCFoundCutSec, NClTPCPIDCutSec, AllK0s, + SingleTrackSelectionK0s, + V0TypeK0s, + DCAtoVtxK0s, + Armenteros, V0RapidityK0s, V0ProperLifetimeK0s, MassCutK0s, AllLambda, + SingleTrackSelectionLambda, + V0TypeLambda, + DCAtoVtxLambda, V0RapidityLambda, V0ProperLifetimeLambda, MassCutLambda, AllAntiLambda, + SingleTrackSelectionAntiLambda, + V0TypeAntiLambda, + DCAtoVtxAntiLambda, V0RapidityAntiLambda, V0ProperLifetimeAntiLambda, MassCutAntiLambda, AllGamma, + SingleTrackSelectionGamma, + V0TypeGamma, V0RapidityGamma, MassCutGamma }; @@ -154,51 +186,64 @@ struct DedxPidAnalysis { Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; Configurable maxDCAz{"maxDCAz", 0.1f, "maxDCAz"}; // v0 cuts - Configurable v0cospaMin{"v0cospaMin", 0.998f, "Minimum V0 CosPA"}; - Configurable minimumV0Radius{"minimumV0Radius", 0.5f, + Configurable v0cospaMin{"v0cospaMin", 0.999f, "Minimum V0 CosPA"}; + Configurable minimumV0Radius{"minimumV0Radius", 1.2f, "Minimum V0 Radius"}; Configurable maximumV0Radius{"maximumV0Radius", 100.0f, "Maximum V0 Radius"}; Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, "Maximum DCA Daughters"}; + Configurable dcaProtonsFromLambda{"dcaProtonsFromLambda", 0.05f, + "Minimum DCA of protons to vtx for Lambda"}; + Configurable dcaPionsFromLambda{"dcaPionsFromLambda", 0.2f, + "Minimum DCA of pions to vtx for Lambda"}; + Configurable dcaPionsFromK0s{"dcaPionsFromK0s", 0.1f, + "Minimum DCA of pions to vtx for K0s"}; Configurable v0rapidityCut{"v0rapidityCut", 0.5f, "V0 rapidity cut"}; Configurable v0ProperLifetimeCutK0s{"v0ProperLifetimeCutK0s", 20.f, "V0 proper lifetime cut for K0s"}; Configurable v0ProperLifetimeCutLambda{"v0ProperLifetimeCutLambda", 30.f, "V0 proper lifetime cut for Lambda"}; Configurable nsigmaTOFmax{"nsigmaTOFmax", 3.0f, "Maximum nsigma TOF"}; - Configurable invMassCutK0s{"invMassCutK0s", 0.2f, "invariant Mass Cut for K0s"}; - Configurable invMassCutLambda{"invMassCutLambda", 0.1f, "invariant Mass Cut for Lambda"}; - Configurable invMassCutGamma{"invMassCutGamma", 0.1f, "invariant Mass Cut for Gamma"}; + Configurable invMassCutK0s{"invMassCutK0s", 0.015f, "invariant Mass Cut for K0s"}; + Configurable invMassCutLambda{"invMassCutLambda", 0.015f, "invariant Mass Cut for Lambda"}; + Configurable invMassCutGamma{"invMassCutGamma", 0.015f, "invariant Mass Cut for Gamma"}; Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; Configurable phiVarCut{"phiVarCut", true, "phi var cut"}; Configurable nClTPCFoundCut{"nClTPCFoundCut", false, "number of found clusters in TPC cut"}; Configurable nClTPCPIDCut{"nClTPCPIDCut", true, "number of PID clusters in TPC cut"}; + Configurable nGoodZvtx{"nGoodZvtx", true, "Rejects events with no vertex match between FT0 and PV"}; // + Configurable nPileUp{"nPileUp", true, "Rejects events with pileup in the same bunch crossing"}; + Configurable nINELSelectionMode{"nINELSelectionMode", 2, "INEL event selection: 1 no sel, 2 INEL>0, 3 INEL>1"}; Configurable v0SelectionMode{"v0SelectionMode", 3, "V0 Selection base on TPC: 1, TOF:2 ,Both:3"}; - Configurable momentumMode{"momentumMode", 1, "1: TPC inner param, 2: Total momentum p"}; + Configurable momentumMode{"momentumMode", 2, "1: TPC inner param, 2: Total momentum p"}; Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + Configurable v0TypeSelectionGamma{"v0TypeSelectionGamma", 7, "select on a certain V0 type (leave negative if no selection desired)"}; + Configurable multiplicityEstimator{"multiplicityEstimator", 9, "Flag to use a multiplicity estimator; No multiplicity: 0, MultFV0A: 1, MultFT0M: 2, MultFDDM: 3 ,MultTracklets: 4,MultTPC: 5,MultNTracksPV: 6 ,MultNTracksPVeta1: 7,CentralityFT0C: 8 ,CentralityFT0M: 9, CentralityFV0A: 10"}; Configurable lowParam1{"lowParam1", 0.119297, "First parameter for low phi cut"}; Configurable lowParam2{"lowParam2", 0.000379693, "Second parameter for low phi cut"}; Configurable highParam1{"highParam1", 0.16685, "First parameter for high phi cut"}; Configurable highParam2{"highParam2", 0.00981942, "Second parameter for high phi cut"}; + Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|"}; // Histograms names - static constexpr std::string_view kDedxvsMomentumPos[kParticlesType] = {"dEdx_vs_Momentum_all_Pos", "dEdx_vs_Momentum_Pi_v0_Pos", "dEdx_vs_Momentum_Pr_v0_Pos", "dEdx_vs_Momentum_El_v0_Pos"}; - static constexpr std::string_view kDedxvsMomentumNeg[kParticlesType] = {"dEdx_vs_Momentum_all_Neg", "dEdx_vs_Momentum_Pi_v0_Neg", "dEdx_vs_Momentum_Pr_v0_Neg", "dEdx_vs_Momentum_El_v0_Neg"}; - static constexpr std::string_view kDedxvsMomentumvsCentPos[kCentralityClasses] = {"dEdx_vs_Momentum_Cent0_1_Pos", "dEdx_vs_Momentum_Cent1_5_Pos", "dEdx_vs_Momentum_Cent5_10_Pos", "dEdx_vs_Momentum_Cent10_15_Pos", "dEdx_vs_Momentum_Cent15_20_Pos", "dEdx_vs_Momentum_Cent20_30_Pos", "dEdx_vs_Momentum_Cent30_40_Pos", "dEdx_vs_Momentum_Cent40_50_Pos", "dEdx_vs_Momentum_Cent50_70_Pos", "dEdx_vs_Momentum_Cent70_100_Pos"}; - static constexpr std::string_view kDedxvsMomentumvsCentNeg[kCentralityClasses] = {"dEdx_vs_Momentum_Cent0_1_Neg", "dEdx_vs_Momentum_Cent1_5_Neg", "dEdx_vs_Momentum_Cent5_10_Neg", "dEdx_vs_Momentum_Cent10_15_Neg", "dEdx_vs_Momentum_Cent15_20_Neg", "dEdx_vs_Momentum_Cent20_30_Neg", "dEdx_vs_Momentum_Cent30_40_Neg", "dEdx_vs_Momentum_Cent40_50_Neg", "dEdx_vs_Momentum_Cent50_70_Neg", "dEdx_vs_Momentum_Cent70_100_Neg"}; + static constexpr std::string_view DedxvsMomentumPos[ParticlesType] = {"dEdx_vs_Momentum_all_Pos", "dEdx_vs_Momentum_Pi_v0_Pos", "dEdx_vs_Momentum_Pr_v0_Pos", "dEdx_vs_Momentum_El_v0_Pos"}; + static constexpr std::string_view DedxvsMomentumNeg[ParticlesType] = {"dEdx_vs_Momentum_all_Neg", "dEdx_vs_Momentum_Pi_v0_Neg", "dEdx_vs_Momentum_Pr_v0_Neg", "dEdx_vs_Momentum_El_v0_Neg"}; + static constexpr std::string_view DedxvsMomentumvsCentPos[CentralityClasses] = {"dEdx_vs_Momentum_Cent0_1_Pos", "dEdx_vs_Momentum_Cent1_5_Pos", "dEdx_vs_Momentum_Cent5_10_Pos", "dEdx_vs_Momentum_Cent10_15_Pos", "dEdx_vs_Momentum_Cent15_20_Pos", "dEdx_vs_Momentum_Cent20_30_Pos", "dEdx_vs_Momentum_Cent30_40_Pos", "dEdx_vs_Momentum_Cent40_50_Pos", "dEdx_vs_Momentum_Cent50_70_Pos", "dEdx_vs_Momentum_Cent70_100_Pos"}; + static constexpr std::string_view DedxvsMomentumvsCentNeg[CentralityClasses] = {"dEdx_vs_Momentum_Cent0_1_Neg", "dEdx_vs_Momentum_Cent1_5_Neg", "dEdx_vs_Momentum_Cent5_10_Neg", "dEdx_vs_Momentum_Cent10_15_Neg", "dEdx_vs_Momentum_Cent15_20_Neg", "dEdx_vs_Momentum_Cent20_30_Neg", "dEdx_vs_Momentum_Cent30_40_Neg", "dEdx_vs_Momentum_Cent40_50_Neg", "dEdx_vs_Momentum_Cent50_70_Neg", "dEdx_vs_Momentum_Cent70_100_Neg"}; // Ncl TPC - static constexpr std::string_view kNclTPCDedxMomentumNegBefore[kEtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_8_Before"}; - static constexpr std::string_view kNclTPCDedxMomentumPosBefore[kEtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_8_Before"}; - static constexpr std::string_view kNclTPCDedxMomentumNegAfter[kEtaIntervals] = {"Ncl_TFoundPC_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_8_After"}; - static constexpr std::string_view kNclTPCDedxMomentumPosAfter[kEtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_8_After"}; + static constexpr std::string_view NclTPCDedxMomentumNegBefore[EtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_8_Before"}; + static constexpr std::string_view NclTPCDedxMomentumPosBefore[EtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_8_Before"}; + static constexpr std::string_view NclTPCDedxMomentumNegAfter[EtaIntervals] = {"Ncl_TFoundPC_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Neg_8_After"}; + static constexpr std::string_view NclTPCDedxMomentumPosAfter[EtaIntervals] = {"Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_FoundTPC_vs_dEdx_vs_Momentum_Pos_8_After"}; // Ncl PID TPC - static constexpr std::string_view kNclPIDTPCDedxMomentumNegBefore[kEtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_8_Before"}; - static constexpr std::string_view kNclPIDTPCDedxMomentumPosBefore[kEtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_8_Before"}; - static constexpr std::string_view kNclPIDTPCDedxMomentumNegAfter[kEtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_8_After"}; - static constexpr std::string_view kNclPIDTPCDedxMomentumPosAfter[kEtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_8_After"}; - static constexpr double EtaCut[kEtaIntervals + 1] = {-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}; - static constexpr double CentClasses[kCentralityClasses + 1] = {0.0, 0.1, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}; + static constexpr std::string_view NclPIDTPCDedxMomentumNegBefore[EtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_8_Before"}; + static constexpr std::string_view NclPIDTPCDedxMomentumPosBefore[EtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_8_Before"}; + static constexpr std::string_view NclPIDTPCDedxMomentumNegAfter[EtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Neg_8_After"}; + static constexpr std::string_view NclPIDTPCDedxMomentumPosAfter[EtaIntervals] = {"Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_PIDTPC_vs_dEdx_vs_Momentum_Pos_8_After"}; + static constexpr double EtaCut[EtaIntervals + 1] = {-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}; + static constexpr double CentClasses[CentralityClasses + 1] = {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}; Configurable> calibrationFactorNeg{"calibrationFactorNeg", {50.4011, 50.4764, 50.186, 49.2955, 48.8222, 49.4273, 49.9292, 50.0556}, "negative calibration factors"}; Configurable> calibrationFactorPos{"calibrationFactorPos", {50.5157, 50.6359, 50.3198, 49.3345, 48.9197, 49.4931, 50.0188, 50.1406}, "positive calibration factors"}; ConfigurableAxis binP{"binP", {VARIABLE_WIDTH, 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, 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.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, ""}; + ConfigurableAxis centBins{"centBins", {100, 0, 100}, "Binning for centralidad"}; // phi cut fits TF1* fphiCutHigh = nullptr; @@ -228,6 +273,26 @@ struct DedxPidAnalysis { void init(InitContext const&) { + const char* label = "No INEL selection"; + if (nPileUp) { + LOGF(info, "Applying NoSameBunchPileup cut"); + } else { + LOGF(info, "NoSameBunchPileup cut disabled"); + } + if (nGoodZvtx) { + LOGF(info, "Applying GoodZvtxFT0vsPV cut"); + } else { + LOGF(info, "GoodZvtxFT0vsPV cut disabled"); + } + if (nINELSelectionMode == NoSelINEL) { + LOGF(info, "INEL cut disabled"); + } else if (nINELSelectionMode == SelINELgt0) { + LOGF(info, "Applying INEL > 0 cut"); + label = "INEL > 0"; + } else if (nINELSelectionMode == SelINELgt1) { + LOGF(info, "Applying INEL > 1 cut"); + label = "INEL > 1"; + } if (v0SelectionMode == V0TPC) { LOGF(info, "V0 seleccion using TPC only"); } else if (v0SelectionMode == V0TOF) { @@ -270,6 +335,55 @@ struct DedxPidAnalysis { AxisSpec etaAxis{8, -0.8, 0.8, "#eta"}; AxisSpec pAxis = {binP, "#it{p}/Z (GeV/c)"}; AxisSpec pAxisTrack = {binP, "#it{p} (GeV/c)"}; + AxisSpec centAxis{centBins, "Undefined multiplicity estimator"}; + switch (multiplicityEstimator) { + case MultSelectionMode::NoMultiplicity: // No multiplicity + LOGF(info, "No multiplicity estimator applied"); + break; + case MultSelectionMode::MultFV0A: // MultFV0A + centAxis.title = "MultFV0A"; + LOGF(info, "MultFV0A estimator applied"); + break; + case MultSelectionMode::MultFT0M: // MultFT0M + centAxis.title = "MultFT0M"; + LOGF(info, "MultFT0M estimator applied"); + break; + case MultSelectionMode::MultFDDM: // MultFDDM + centAxis.title = "MultFDDM"; + LOGF(info, " MultFDDM estimator applied"); + break; + case MultSelectionMode::MultTracklets: // MultTracklets + centAxis.title = "MultTracklets"; + LOGF(info, "MultTracklets estimator applied"); + break; + case MultSelectionMode::MultTPC: // MultTPC + centAxis.title = "MultTPC"; + LOGF(info, "MultTPC estimator applied"); + break; + case MultSelectionMode::MultNTracksPV: // MultNTracksPV + centAxis.title = "MultNTracksPV"; + LOGF(info, "MultNTracksPV estimator applied"); + break; + case MultSelectionMode::MultNTracksPVeta1: // MultNTracksPVeta1 + centAxis.title = "MultNTracksPVeta1"; + LOGF(info, "MultNTracksPVeta1 estimator applied"); + break; + case MultSelectionMode::CentralityFT0C: // Centrality FT0C + centAxis.title = "Centrality FT0C"; + LOGF(info, "Centrality FT0C estimator applied"); + break; + case MultSelectionMode::CentralityFT0M: // Centrality FT0M + centAxis.title = "Centrality FT0M"; + LOGF(info, "Centrality FT0M estimator applied"); + break; + case MultSelectionMode::CentralityFV0A: // Centrality FV0A + centAxis.title = "Centrality FV0A"; + LOGF(info, "Centrality FV0A estimator applied"); + break; + default: + LOG(fatal) << "Unrecognized option for multiplicity " << multiplicityEstimator; + } + fphiCutLow = new TF1("StandardPhiCutLow", Form("%f/x/x+pi/18.0-%f", lowParam1.value, lowParam2.value), 0, 50); @@ -340,16 +454,16 @@ struct DedxPidAnalysis { {{etaAxis}, {ptAxis}, {pAxisTrack}}); // De/Dx for ch and v0 particles - for (int i = 0; i < kParticlesType; ++i) { - registryDeDx.add(kDedxvsMomentumPos[i].data(), "dE/dx", HistType::kTH3F, + for (int i = 0; i < ParticlesType; ++i) { + registryDeDx.add(DedxvsMomentumPos[i].data(), "dE/dx", HistType::kTH3F, {{pAxisTrack}, {dedxAxis}, {etaAxis}}); - registryDeDx.add(kDedxvsMomentumNeg[i].data(), "dE/dx", HistType::kTH3F, + registryDeDx.add(DedxvsMomentumNeg[i].data(), "dE/dx", HistType::kTH3F, {{pAxisTrack}, {dedxAxis}, {etaAxis}}); } - for (int i = 0; i < kCentralityClasses; ++i) { - hDedxVsMomentumVsCentPos[i] = registryDeDx.add(kDedxvsMomentumvsCentPos[i].data(), "dE/dx", HistType::kTH3F, {{pAxisTrack}, {dedxAxis}, {etaAxis}}); - hDedxVsMomentumVsCentNeg[i] = registryDeDx.add(kDedxvsMomentumvsCentNeg[i].data(), "dE/dx", HistType::kTH3F, {{pAxisTrack}, {dedxAxis}, {etaAxis}}); + for (int i = 0; i < CentralityClasses; ++i) { + hDedxVsMomentumVsCentPos[i] = registryDeDx.add(DedxvsMomentumvsCentPos[i].data(), "dE/dx", HistType::kTH3F, {{pAxisTrack}, {dedxAxis}, {etaAxis}}); + hDedxVsMomentumVsCentNeg[i] = registryDeDx.add(DedxvsMomentumvsCentNeg[i].data(), "dE/dx", HistType::kTH3F, {{pAxisTrack}, {dedxAxis}, {etaAxis}}); } } @@ -394,30 +508,30 @@ struct DedxPidAnalysis { } // Ncl vs de/dx TPC if (nClTPCFoundCut) { - for (int i = 0; i < kEtaIntervals; ++i) { - registryDeDx.add(kNclTPCDedxMomentumPosBefore[i].data(), "Ncl found TPC vs dE/dx vs Momentum Positive before", HistType::kTH3F, + for (int i = 0; i < EtaIntervals; ++i) { + registryDeDx.add(NclTPCDedxMomentumPosBefore[i].data(), "Ncl found TPC vs dE/dx vs Momentum Positive before", HistType::kTH3F, {{100, 0, 160, "N_{cl, found}^{TPC}"}, {dedxAxis}, {pAxis}}); - registryDeDx.add(kNclTPCDedxMomentumNegBefore[i].data(), "Ncl found TPC vs dE/dx vs Momentum Negative before", HistType::kTH3F, + registryDeDx.add(NclTPCDedxMomentumNegBefore[i].data(), "Ncl found TPC vs dE/dx vs Momentum Negative before", HistType::kTH3F, {{100, 0, 160, "N_{cl, found}^{TPC}"}, {dedxAxis}, {pAxis}}); - registryDeDx.add(kNclTPCDedxMomentumPosAfter[i].data(), "Ncl found TPC vs dE/dx vs Momentum Positive after", HistType::kTH3F, + registryDeDx.add(NclTPCDedxMomentumPosAfter[i].data(), "Ncl found TPC vs dE/dx vs Momentum Positive after", HistType::kTH3F, {{100, 0, 160, "N_{cl, found}^{TPC}"}, {dedxAxis}, {pAxis}}); - registryDeDx.add(kNclTPCDedxMomentumNegAfter[i].data(), "Ncl found TPC vs dE/dx vs Momentum Negative after", HistType::kTH3F, + registryDeDx.add(NclTPCDedxMomentumNegAfter[i].data(), "Ncl found TPC vs dE/dx vs Momentum Negative after", HistType::kTH3F, {{100, 0, 160, "N_{cl, found}^{TPC}"}, {dedxAxis}, {pAxis}}); } } // Ncl vs de/dx ITS if (nClTPCPIDCut) { - for (int i = 0; i < kEtaIntervals; ++i) { - registryDeDx.add(kNclPIDTPCDedxMomentumPosBefore[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Positive before", HistType::kTH3F, + for (int i = 0; i < EtaIntervals; ++i) { + registryDeDx.add(NclPIDTPCDedxMomentumPosBefore[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Positive before", HistType::kTH3F, {{100, 0, 160, "N_{cl, PID}^{TPC}"}, {dedxAxis}, {pAxis}}); - registryDeDx.add(kNclPIDTPCDedxMomentumNegBefore[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Negative before", HistType::kTH3F, + registryDeDx.add(NclPIDTPCDedxMomentumNegBefore[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Negative before", HistType::kTH3F, {{100, 0, 160, "N_{cl, PID}^{TPC}"}, {dedxAxis}, {pAxis}}); - registryDeDx.add(kNclPIDTPCDedxMomentumPosAfter[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Positive after", HistType::kTH3F, + registryDeDx.add(NclPIDTPCDedxMomentumPosAfter[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Positive after", HistType::kTH3F, {{100, 0, 160, "N_{cl, PID}^{TPC}"}, {dedxAxis}, {pAxis}}); - registryDeDx.add(kNclPIDTPCDedxMomentumNegAfter[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Negative after", HistType::kTH3F, + registryDeDx.add(NclPIDTPCDedxMomentumNegAfter[i].data(), "Ncl PID TPC vs dE/dx vs Momentum Negative after", HistType::kTH3F, {{100, 0, 160, "N_{cl, PID}^{TPC}"}, {dedxAxis}, {pAxis}}); } } @@ -524,8 +638,15 @@ struct DedxPidAnalysis { // Event Counter registryDeDx.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{100, -20.0, +20.0, "z_{vtx} (cm)"}}); + // Event Counter by centrality + registryDeDx.add("histCentrality", "Centrality", HistType::kTH1F, {centAxis}); + + // Tracks vs p + registryDeDx.add("Tracks_vs_pT_all", "pT All", HistType::kTH1F, {{ptAxis}}); + registryDeDx.add("Tracks_vs_pT_all_cuts", "pT All + cuts", HistType::kTH1F, {{ptAxis}}); + // Event Counter - registryDeDx.add("evsel", "events selected", HistType::kTH1F, {{5, 0.5, 5.5, ""}}); + registryDeDx.add("evsel", "events selected", HistType::kTH1F, {{6, 0.5, 6.5, ""}}); auto hstat = registryDeDx.get(HIST("evsel")); auto* x = hstat->GetXaxis(); x->SetBinLabel(AllEv, "AllEv"); @@ -533,45 +654,55 @@ struct DedxPidAnalysis { x->SetBinLabel(ZVtxCut, "ZVtxCut"); x->SetBinLabel(NoSameBunchPileup, "NoSameBunchPileup"); x->SetBinLabel(GoodZvtxFT0vsPV, "GoodZvtxFT0vsPV"); + x->SetBinLabel(INELgt, label); - // Track Counter - registryDeDx.add("trackselAll", "track selected all particles", HistType::kTH1F, {{5, 0.5, 6.5, ""}}); + // Track Prim Counter + registryDeDx.add("trackselAll", "track selected all particles", HistType::kTH1F, {{5, 0.5, 5.5, ""}}); auto htrackAll = registryDeDx.get(HIST("trackselAll")); auto* xAll = htrackAll->GetXaxis(); xAll->SetBinLabel(AllPri, "AllPri"); xAll->SetBinLabel(SelectionPrim, "SelectionPrim"); xAll->SetBinLabel(PhiVarCutPri, "PhiVarCutPri"); - xAll->SetBinLabel(NClTPCFoundCutPri, "NClTPCFoundCutPri"); xAll->SetBinLabel(NClTPCPIDCutPri, "NClTPCPIDCutPri"); + xAll->SetBinLabel(NClTPCFoundCutPri, "NClTPCFoundCutPri"); - registryDeDx.add("trackselSec", "track selected sec particles", HistType::kTH1F, {{24, 0.5, 24.5, ""}}); + registryDeDx.add("trackselSec", "track selected sec particles", HistType::kTH1F, {{34, 0.5, 34.5, ""}}); auto htrackSec = registryDeDx.get(HIST("trackselSec")); auto* xSec = htrackSec->GetXaxis(); xSec->SetBinLabel(AllSec, "AllSec"); - xSec->SetBinLabel(V0Type, "V0Type"); xSec->SetBinLabel(V0CosPA, "V0CosPA"); xSec->SetBinLabel(V0DecayRadius, "V0DecayRadius"); xSec->SetBinLabel(V0Daughters, "V0Daughters"); - xSec->SetBinLabel(TPCRefit, "TPCRefit"); xSec->SetBinLabel(PhiVarCutSec, "PhiVarCutSec"); xSec->SetBinLabel(NClTPCFoundCutSec, "NClTPCFoundCutSec"); xSec->SetBinLabel(NClTPCPIDCutSec, "NClTPCPIDCutSec"); xSec->SetBinLabel(AllK0s, "AllK0s"); + xSec->SetBinLabel(SingleTrackSelectionK0s, "SingleTrackSelectionK0s"); + xSec->SetBinLabel(V0TypeK0s, "V0TypeK0s"); + xSec->SetBinLabel(DCAtoVtxK0s, "DCAtoVtxK0s"); + xSec->SetBinLabel(Armenteros, "Armenteros"); xSec->SetBinLabel(V0RapidityK0s, "V0RapidityK0s"); xSec->SetBinLabel(V0ProperLifetimeK0s, "V0ProperLifetimeK0s"); xSec->SetBinLabel(MassCutK0s, "MassCutK0s"); xSec->SetBinLabel(AllLambda, "AllLambda"); + xSec->SetBinLabel(SingleTrackSelectionLambda, "SingleTrackSelectionLambda"); + xSec->SetBinLabel(V0TypeLambda, "V0TypeLambda"); + xSec->SetBinLabel(DCAtoVtxLambda, "DCAtoVtxLambda"); xSec->SetBinLabel(V0RapidityLambda, "V0RapidityLambda"); xSec->SetBinLabel(V0ProperLifetimeLambda, "V0ProperLifetimeLambda"); xSec->SetBinLabel(MassCutLambda, "MassCutLambda"); xSec->SetBinLabel(AllAntiLambda, "AllAntiLambda"); + xSec->SetBinLabel(SingleTrackSelectionAntiLambda, "SingleTrackSelectionAntiLambda"); + xSec->SetBinLabel(V0TypeAntiLambda, "V0TypeAntiLambda"); + xSec->SetBinLabel(DCAtoVtxAntiLambda, "DCAtoVtxAntiLambda"); xSec->SetBinLabel(V0RapidityAntiLambda, "V0RapidityAntiLambda"); xSec->SetBinLabel(V0ProperLifetimeAntiLambda, "V0ProperLifetimeAntiLambda"); xSec->SetBinLabel(MassCutAntiLambda, "MassCutAntiLambda"); xSec->SetBinLabel(AllGamma, "AllGamma"); + xSec->SetBinLabel(SingleTrackSelectionGamma, "SingleTrackSelectionGamma"); + xSec->SetBinLabel(V0TypeGamma, "V0TypeGamma"); xSec->SetBinLabel(V0RapidityGamma, "V0RapidityGamma"); xSec->SetBinLabel(MassCutGamma, "MassCutGamma"); - mySelectionPrim = myTrackSelection(); } @@ -580,12 +711,12 @@ struct DedxPidAnalysis { bool passedSingleTrackSelection(const T1& track, const C& /*collision*/) { // Single-Track Selections - if (!track.hasTPC()) - return false; + // if (!track.hasTPC()) + // return false; if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) return false; - if (track.tpcChi2NCl() > maxChi2TPC) - return false; + // if (track.tpcChi2NCl() > maxChi2TPC) + // return false; if (track.eta() < etaMin || track.eta() > etaMax) return false; @@ -623,12 +754,15 @@ struct DedxPidAnalysis { bool passedK0Selection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllK0s); // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -654,23 +788,39 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllK0s); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionK0s); - if (std::abs(v0.yK0Short()) > v0rapidityCut) + if (v0.v0Type() != v0TypeSelection) // V0 type selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeK0s); + + if (std::fabs(v0.dcapostopv()) < dcaPionsFromK0s) // DCA selection + return false; + if (std::fabs(v0.dcanegtopv()) < dcaPionsFromK0s) // DCA selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxK0s); + + if (armPodCut * v0.qtarm() < std::abs(v0.alpha())) // Armenteros-Podolanski cut + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::Armenteros); + + if (std::abs(v0.yK0Short()) > v0rapidityCut) // Rapidity selection return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityK0s); float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; - - if (properLifetime > v0ProperLifetimeCutK0s) + if (properLifetime > v0ProperLifetimeCutK0s) // Proper lifetime return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0ProperLifetimeK0s); - if (std::abs(v0.mK0Short() - MassK0Short) > invMassCutK0s) + if (std::abs(v0.mK0Short() - MassK0Short) > invMassCutK0s) // Invarian mass return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutK0s); @@ -683,13 +833,16 @@ struct DedxPidAnalysis { bool passedLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllLambda); // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -715,26 +868,36 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ + if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllLambda); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionLambda); - if (std::abs(v0.yLambda()) > v0rapidityCut) + if (v0.v0Type() != v0TypeSelection) // V0 type selection return false; if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityLambda); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeLambda); - float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda; + if (std::fabs(v0.dcapostopv()) < dcaProtonsFromLambda) // DCA selection + return false; + if (std::fabs(v0.dcanegtopv()) < dcaPionsFromLambda) // DCA selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxLambda); - if (properLifetime > v0ProperLifetimeCutLambda) + if (std::abs(v0.yLambda()) > v0rapidityCut) // Rapidity selection return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityLambda); + float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda; + if (properLifetime > v0ProperLifetimeCutLambda) // Proper lifetime + return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0ProperLifetimeLambda); - if (std::abs(v0.mLambda() - MassLambda) > invMassCutLambda) { + if (std::abs(v0.mLambda() - MassLambda) > invMassCutLambda) // Invarian mass return false; - } if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutLambda); @@ -746,13 +909,15 @@ struct DedxPidAnalysis { bool passedAntiLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllAntiLambda); // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -777,27 +942,37 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ + if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllAntiLambda); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionAntiLambda); - if (std::abs(v0.yLambda()) > v0rapidityCut) + // Select V0 type + if (v0.v0Type() != v0TypeSelection) // V0 type selection return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeAntiLambda); + if (std::fabs(v0.dcapostopv()) < dcaPionsFromLambda) // DCA selection + return false; + if (std::fabs(v0.dcanegtopv()) < dcaProtonsFromLambda) // DCA selection + return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::DCAtoVtxAntiLambda); + + if (std::abs(v0.yLambda()) > v0rapidityCut) // Rapidity selection + return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityAntiLambda); float properLifetime = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassLambda; - - if (properLifetime > v0ProperLifetimeCutLambda) + if (properLifetime > v0ProperLifetimeCutLambda) // Proper lifetime return false; - if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0ProperLifetimeAntiLambda); - if (std::abs(v0.mAntiLambda() - MassLambda) > invMassCutLambda) + if (std::abs(v0.mAntiLambda() - MassLambda) > invMassCutLambda) // Invarian mass return false; - if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutAntiLambda); @@ -809,13 +984,16 @@ struct DedxPidAnalysis { bool passedGammaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, const C& collision) { + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllGamma); + // Single-Track Selections if (!passedSingleTrackSelection(ptrack, collision)) return false; if (!passedSingleTrackSelection(ntrack, collision)) return false; - double sigmap = 0.0; + /*double sigmap = 0.0; double sigman = 0.0; if (v0SelectionMode == V0TPC) { @@ -841,23 +1019,25 @@ struct DedxPidAnalysis { return false; if (std::abs(sigman) > nsigmaTOFmax) return false; - } + }*/ const float gammaMass = 2 * MassElectron; // GeV/c^2 if (fillHist) - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllGamma); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::SingleTrackSelectionGamma); - const float yGamma = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, MassGamma); - - if (std::abs(yGamma) > v0rapidityCut) + if (v0.v0Type() != v0TypeSelectionGamma) // V0 type selection return false; + if (fillHist) + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0TypeGamma); + const float yGamma = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, MassGamma); + if (std::abs(yGamma) > v0rapidityCut) // Rapidity selection + return false; if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0RapidityGamma); - if (std::abs(v0.mGamma() - gammaMass) > invMassCutGamma) + if (std::abs(v0.mGamma() - gammaMass) > invMassCutGamma) // Invarian mass return false; - if (fillHist) registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::MassCutGamma); @@ -927,51 +1107,51 @@ struct DedxPidAnalysis { if (eta >= EtaCut[0] && eta < EtaCut[1]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[1] && eta < EtaCut[2]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[2] && eta < EtaCut[3]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[3] && eta < EtaCut[4]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[4] && eta < EtaCut[5]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[5] && eta < EtaCut[6]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[6] && eta < EtaCut[7]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[7] && eta < EtaCut[8]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); } } @@ -980,51 +1160,51 @@ struct DedxPidAnalysis { if (eta >= EtaCut[0] && eta < EtaCut[1]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[1] && eta < EtaCut[2]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[2] && eta < EtaCut[3]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[3] && eta < EtaCut[4]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[4] && eta < EtaCut[5]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[5] && eta < EtaCut[6]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[6] && eta < EtaCut[7]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[7] && eta < EtaCut[8]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclTPCDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclTPCDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclTPCDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclTPCDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); } } @@ -1041,51 +1221,51 @@ struct DedxPidAnalysis { if (eta >= EtaCut[0] && eta < EtaCut[1]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[1] && eta < EtaCut[2]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[2] && eta < EtaCut[3]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[3] && eta < EtaCut[4]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[4] && eta < EtaCut[5]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[5] && eta < EtaCut[6]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[6] && eta < EtaCut[7]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[7] && eta < EtaCut[8]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); } } @@ -1094,51 +1274,51 @@ struct DedxPidAnalysis { if (eta >= EtaCut[0] && eta < EtaCut[1]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[1] && eta < EtaCut[2]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[2] && eta < EtaCut[3]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[3] && eta < EtaCut[4]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[4] && eta < EtaCut[5]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[5] && eta < EtaCut[6]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[6] && eta < EtaCut[7]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); } } else if (eta >= EtaCut[7] && eta < EtaCut[8]) { if (sigP < 0) { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); } else { - registryDeDx.fill(HIST(kNclPIDTPCDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); + registryDeDx.fill(HIST(NclPIDTPCDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); } } @@ -1195,7 +1375,46 @@ struct DedxPidAnalysis { return true; } - + // Get Multiplicity + template + float getMultiplicity(const T& collision) + { + switch (multiplicityEstimator) { + case MultSelectionMode::NoMultiplicity: // No multiplicity + return 50.f; // to check if its filled + break; + case MultSelectionMode::MultFV0A: // MultFV0M + return collision.multZeqFV0A(); + break; + case MultSelectionMode::MultFT0M: + return collision.multZeqFT0A() + collision.multZeqFT0C(); + break; + case MultSelectionMode::MultFDDM: // MultFDDM + return collision.multZeqFDDA() + collision.multZeqFDDC(); + break; + case MultSelectionMode::MultTracklets: // MultTracklets + return 0.f; // Undefined in Run3 + break; + case MultSelectionMode::MultTPC: // MultTPC + return collision.multTPC(); + break; + case MultSelectionMode::MultNTracksPV: // MultNTracksPV + return collision.multZeqNTracksPV(); + break; + case MultSelectionMode::MultNTracksPVeta1: // MultNTracksPVeta1 + return collision.multNTracksPVeta1(); + break; + case MultSelectionMode::CentralityFT0C: // Centrality FT0C + return collision.centFT0C(); + break; + case MultSelectionMode::CentralityFT0M: // Centrality FT0M + return collision.centFT0M(); + break; + default: + LOG(fatal) << "Unknown multiplicity estimator: " << multiplicityEstimator; + return 0.f; + } + } // Process Data void process(SelectedCollisions::iterator const& collision, BCsRun3 const& /**/, aod::V0Datas const& fullV0s, PIDTracks const& tracks) @@ -1212,15 +1431,28 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("evsel"), EvCutLabel::ZVtxCut); - if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) - return; - - registryDeDx.fill(HIST("evsel"), EvCutLabel::NoSameBunchPileup); + if (nPileUp) { + if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + registryDeDx.fill(HIST("evsel"), EvCutLabel::NoSameBunchPileup); + } - if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) - return; + if (nGoodZvtx) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + registryDeDx.fill(HIST("evsel"), EvCutLabel::GoodZvtxFT0vsPV); + } - registryDeDx.fill(HIST("evsel"), EvCutLabel::GoodZvtxFT0vsPV); + if (nINELSelectionMode == NoSelINEL) { + } else if (nINELSelectionMode == SelINELgt0) { + if (!collision.isInelGt0()) + return; + registryDeDx.fill(HIST("evsel"), EvCutLabel::INELgt); + } else if (nINELSelectionMode == SelINELgt1) { + if (!collision.isInelGt1()) + return; + registryDeDx.fill(HIST("evsel"), EvCutLabel::INELgt); + } // Event Counter registryDeDx.fill(HIST("histRecVtxZData"), collision.posZ()); @@ -1230,43 +1462,53 @@ struct DedxPidAnalysis { const uint64_t timeStamp{foundBC.timestamp()}; const int magField{getMagneticField(timeStamp)}; - float centrality = collision.centFT0C(); + float centrality = getMultiplicity(collision); if (centrality < CentClasses[0] || centrality > CentClasses[10]) return; + // Event Counter by cent + registryDeDx.fill(HIST("histCentrality"), centrality); + for (const auto& trk : tracks) { registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::AllPri); + // track Selection if (!mySelectionPrim.IsSelected(trk)) continue; registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::SelectionPrim); + // For pt + registryDeDx.fill(HIST("Tracks_vs_pT_all"), trk.pt()); // phi and Ncl cut if (phiVarCut) { if (!passedPhiCutPri(trk, magField, *fphiCutLow, *fphiCutHigh)) continue; + registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::PhiVarCutPri); } - registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::PhiVarCutPri); - - // NCl cut TPC - registryDeDx.fill(HIST("heta_vs_NclFound_TPC_Before_Primary"), trk.eta(), trk.tpcNClsFound()); - if (nClTPCFoundCut) { - if (!passedNClTPCFoundCutPri(trk)) - continue; - } - registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::NClTPCFoundCutPri); - registryDeDx.fill(HIST("heta_vs_NclFound_TPC_After_Primary"), trk.eta(), trk.tpcNClsFound()); // NCl cut PID TPC registryDeDx.fill(HIST("heta_vs_NclPID_TPC_Before_Primary"), trk.eta(), trk.tpcNClsPID()); if (nClTPCPIDCut) { if (!passedNClTPCPIDCutPri(trk)) continue; + registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::NClTPCPIDCutPri); } - registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::NClTPCPIDCutPri); + registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_Primary"), trk.eta(), trk.tpcNClsPID()); + // NCl cut TPC + registryDeDx.fill(HIST("heta_vs_NclFound_TPC_Before_Primary"), trk.eta(), trk.tpcNClsFound()); + if (nClTPCFoundCut) { + if (!passedNClTPCFoundCutPri(trk)) + continue; + registryDeDx.fill(HIST("trackselAll"), TrkPriCutLabel::NClTPCFoundCutPri); + } + + registryDeDx.fill(HIST("heta_vs_NclFound_TPC_After_Primary"), trk.eta(), trk.tpcNClsFound()); + // For pt + cuts + registryDeDx.fill(HIST("Tracks_vs_pT_all_cuts"), trk.pt()); + float signedP = trk.sign() * getMomentum(trk); // MIP calibration for pions @@ -1279,7 +1521,7 @@ struct DedxPidAnalysis { } } else { - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (trk.eta() >= EtaCut[i] && trk.eta() < EtaCut[i + 1]) { if (signedP < 0) { registryDeDx.fill(HIST("hdEdx_vs_eta_Neg_calibrated_Pi"), trk.eta(), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i)); @@ -1305,7 +1547,7 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Pos_El"), trk.eta(), trk.tpcSignal(), signedP); } } else { - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (trk.eta() >= EtaCut[i] && trk.eta() < EtaCut[i + 1]) { if (signedP < 0) { registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Neg_calibrated_El"), trk.eta(), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), std::abs(signedP)); @@ -1325,7 +1567,7 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Pos_TOF"), trk.eta(), trk.tpcSignal(), signedP); } } else { - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (trk.eta() >= EtaCut[i] && trk.eta() < EtaCut[i + 1]) { if (signedP < 0) { registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Neg_calibrated_TOF"), trk.eta(), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), std::abs(signedP)); @@ -1341,7 +1583,7 @@ struct DedxPidAnalysis { if (!calibrationMode) { int centIndex = -1; - for (int j = 0; j < kCentralityClasses; ++j) { + for (int j = 0; j < CentralityClasses; ++j) { if (centrality >= CentClasses[j] && centrality < CentClasses[j + 1]) { centIndex = j; break; @@ -1350,14 +1592,14 @@ struct DedxPidAnalysis { if (centIndex == -1) continue; - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (trk.eta() >= EtaCut[i] && trk.eta() < EtaCut[i + 1]) { if (signedP > 0) { - registryDeDx.fill(HIST(kDedxvsMomentumPos[0]), signedP, trk.tpcSignal() * 50 / calibrationFactorPos->at(i), trk.eta()); + registryDeDx.fill(HIST(DedxvsMomentumPos[0]), signedP, trk.tpcSignal() * 50 / calibrationFactorPos->at(i), trk.eta()); registryDeDx.fill(HIST("heta_vs_pt_vs_p_all_Pos"), trk.eta(), trk.pt(), trk.p()); hDedxVsMomentumVsCentPos[centIndex]->Fill(signedP, trk.tpcSignal() * 50 / calibrationFactorPos->at(i), trk.eta()); } else { - registryDeDx.fill(HIST(kDedxvsMomentumNeg[0]), std::abs(signedP), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); + registryDeDx.fill(HIST(DedxvsMomentumNeg[0]), std::abs(signedP), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); registryDeDx.fill(HIST("heta_vs_pt_vs_p_all_Neg"), trk.eta(), trk.pt(), trk.p()); hDedxVsMomentumVsCentNeg[centIndex]->Fill(std::abs(signedP), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); } @@ -1373,12 +1615,6 @@ struct DedxPidAnalysis { // Standard V0 Selections registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::AllSec); - // Select V0 type - if (v0.v0Type() != v0TypeSelection) - continue; - - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::V0Type); - if (!passedV0Selection(v0, collision)) { continue; } @@ -1387,21 +1623,22 @@ struct DedxPidAnalysis { const auto& posTrack = v0.posTrack_as(); const auto& negTrack = v0.negTrack_as(); - if (!posTrack.passedTPCRefit()) + /*if (!posTrack.passedTPCRefit()) continue; if (!negTrack.passedTPCRefit()) - continue; + continue;*/ - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::TPCRefit); - // phi and Ncl cut + // registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel::TPCRefit); + // phi and Ncl cut if (phiVarCut) { if (!passedPhiCutSecondaries(posTrack, magField, *fphiCutLow, *fphiCutHigh)) continue; if (!passedPhiCutSecondaries(negTrack, magField, *fphiCutLow, *fphiCutHigh)) continue; + + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel ::PhiVarCutSec); } - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel ::PhiVarCutSec); fillHist = false; // K0s Selection @@ -1439,9 +1676,9 @@ struct DedxPidAnalysis { if (!passedNClTPCFoundCutSecondaries(negTrack)) continue; - } - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel ::NClTPCFoundCutSec); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel ::NClTPCFoundCutSec); + } if (nClTPCPIDCut) { if (!passedNClTPCPIDCutSecondaries(posTrack)) @@ -1449,9 +1686,9 @@ struct DedxPidAnalysis { if (!passedNClTPCPIDCutSecondaries(negTrack)) continue; - } - registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel ::NClTPCPIDCutSec); + registryDeDx.fill(HIST("trackselSec"), TrkSecCutLabel ::NClTPCPIDCutSec); + } float signedPpos = posTrack.sign() * getMomentum(posTrack); float signedPneg = negTrack.sign() * getMomentum(negTrack); @@ -1464,12 +1701,12 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_PionsK0s"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsK0s"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsK0s"), negTrack.p(), negTrack.tpcNClsPID()); - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumNeg[1]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumNeg[1]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); } if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumPos[1]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumPos[1]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); } } } @@ -1480,12 +1717,12 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_PionsLambda"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ProtonsLambda"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsLambda"), negTrack.p(), negTrack.tpcNClsPID()); - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumNeg[1]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumNeg[1]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); } if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumPos[2]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumPos[2]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); } } } @@ -1496,12 +1733,12 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_ProtonsLambda"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_PionsLambda"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ProtonsLambda"), negTrack.p(), negTrack.tpcNClsPID()); - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumNeg[2]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumNeg[2]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); } if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumPos[1]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumPos[1]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); } } } @@ -1512,12 +1749,12 @@ struct DedxPidAnalysis { registryDeDx.fill(HIST("heta_vs_NclPID_TPC_After_ElectronsGamma"), negTrack.eta(), negTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ElectronsGamma"), posTrack.p(), posTrack.tpcNClsPID()); registryDeDx.fill(HIST("hp_vs_NclPID_TPC_After_ElectronsGamma"), negTrack.p(), negTrack.tpcNClsPID()); - for (int i = 0; i < kEtaIntervals; ++i) { + for (int i = 0; i < EtaIntervals; ++i) { if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumNeg[3]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumNeg[3]), std::abs(signedPneg), negTrack.tpcSignal() * 50 / calibrationFactorNeg->at(i), negTrack.eta()); } if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST(kDedxvsMomentumPos[3]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + registryDeDx.fill(HIST(DedxvsMomentumPos[3]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); } } } diff --git a/PWGLF/Tasks/Nuspex/multiplicityPt.cxx b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx new file mode 100644 index 00000000000..1a71c04db8b --- /dev/null +++ b/PWGLF/Tasks/Nuspex/multiplicityPt.cxx @@ -0,0 +1,1215 @@ +// 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 Dushmanta Sahu (dushmanta.sahu@cern.ch) +/// \file multiplicityPt.cxx +/// \brief Analysis to do PID with MC + +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/mcCentrality.h" // For McCentFT0Ms +#include "PWGLF/DataModel/spectraTOF.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/Logger.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "TPDGCode.h" +#include +#include +#include +#include + +#include +#include +#include +#include // For std::accumulate +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::math; +using namespace constants::physics; + +using BCsRun3 = soa::Join; + +struct MultiplicityPt { + + // Service + Service pdg; + Service ccdb; + static constexpr int CentBinMax = 100; + static constexpr int MultBinMax = 200; + static constexpr int RecMultBinMax = 100; + static constexpr int DebugCountMax = 20; + static constexpr int CentMultClasses = 10; + + enum INELCutSelection : int { + INEL = 0, + INELgt0 = 1, + INELgt1 = 2 + + }; + + Configurable isRun3{"isRun3", true, "is Run3 dataset"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgINELCut{"cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; + Configurable askForCustomTVX{"askForCustomTVX", false, "Ask for custom TVX rather than sel8"}; + Configurable removeITSROFrameBorder{"removeITSROFrameBorder", false, "Remove ITS Read-Out Frame border"}; + Configurable removeNoSameBunchPileup{"removeNoSameBunchPileup", false, "Remove no same bunch pileup"}; + Configurable requireIsGoodZvtxFT0vsPV{"requireIsGoodZvtxFT0vsPV", false, "Require good Z vertex FT0 vs PV"}; + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "Require vertex ITSTPC"}; + Configurable removeNoTimeFrameBorder{"removeNoTimeFrameBorder", false, "Remove no time frame border"}; + Configurable cfgCutEtaMax{"cfgCutEtaMax", 0.8f, "Max eta range for tracks"}; + Configurable cfgCutEtaMin{"cfgCutEtaMin", -0.8f, "Min eta range for tracks"}; + Configurable cfgCutY{"cfgCutY", 0.5f, "Y range for tracks"}; + Configurable cfgCutNsigma{"cfgCutNsigma", 3.0f, "nsigma cut range for tracks"}; + Configurable lastRequiredTrdCluster{"lastRequiredTrdCluster", -1, "Last cluster to require in TRD"}; + Configurable requireTrdOnly{"requireTrdOnly", false, "Require only tracks from TRD"}; + Configurable requireNoTrd{"requireNoTrd", false, "Require tracks without TRD"}; + + // Analysis switches + Configurable enableDCAHistograms{"enableDCAHistograms", false, "Enable DCA histograms"}; + Configurable enablePIDHistograms{"enablePIDHistograms", true, "Enable PID histograms"}; + Configurable useCustomTrackCuts{"useCustomTrackCuts", true, "Flag to use custom track cuts"}; + Configurable itsPattern{"itsPattern", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; + Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable minChi2PerClusterTPC{"minChi2PerClusterTPC", 0.5f, "Additional cut on the minimum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Additional cut on the maximum value of the DCA xy (multiplicative factor)"}; + Configurable maxDcaZ{"maxDcaZ", 0.1f, "Additional cut on the maximum value of the DCA z"}; + Configurable minTPCNClsFound{"minTPCNClsFound", 70.0f, "min number of found TPC clusters"}; + Configurable minTPCNClsPID{"minTPCNClsPID", 130.0f, "min number of PID TPC clusters"}; + Configurable nClTPCFoundCut{"nClTPCFoundCut", false, "Apply TPC found clusters cut"}; + Configurable nClTPCPIDCut{"nClTPCPIDCut", true, "Apply TPC clusters for PID cut"}; + + // Phi cut parameters + Configurable applyPhiCut{"applyPhiCut", false, "Apply phi sector cut to remove problematic TPC regions"}; + Configurable pTthresholdPhiCut{"pTthresholdPhiCut", 2.0f, "pT threshold above which to apply phi cut"}; + Configurable phiCutLowParam1{"phiCutLowParam1", 0.119297, "First parameter for low phi cut"}; + Configurable phiCutLowParam2{"phiCutLowParam2", 0.000379693, "Second parameter for low phi cut"}; + Configurable phiCutHighParam1{"phiCutHighParam1", 0.16685, "First parameter for high phi cut"}; + Configurable phiCutHighParam2{"phiCutHighParam2", 0.00981942, "Second parameter for high phi cut"}; + + // Basic track cuts + Configurable cfgTrkEtaCut{"cfgTrkEtaCut", 0.8f, "Eta range for tracks"}; + Configurable cfgTrkLowPtCut{"cfgTrkLowPtCut", 0.15f, "Minimum constituent pT"}; + + // PID selection - make them configurable per particle + Configurable cfgCutNsigmaPi{"cfgCutNsigmaPi", 3.0f, "nsigma cut for pions"}; + Configurable cfgCutNsigmaKa{"cfgCutNsigmaKa", 2.5f, "nsigma cut for kaons"}; + Configurable cfgCutNsigmaPr{"cfgCutNsigmaPr", 2.5f, "nsigma cut for protons"}; + + // Custom track cuts matching spectraTOF + TrackSelection customTrackCuts; + + // TF1 pointers for phi cuts + TF1* fphiCutLow = nullptr; + TF1* fphiCutHigh = nullptr; + + // Histogram Registry + HistogramRegistry ue; + + // Data collisions (not used but kept for completeness) + using CollisionTableData = soa::Join; + + // Track tables + using TrackTableData = soa::Join; + using TrackTableMC = soa::Join; + + // MC particles table + using ParticlesMC = aod::McParticles; + + // MC collisions table + using McCollisions = aod::McCollisions; + + // Reconstructed collisions (without joins that cause size mismatch) + using RecoCollisions = aod::Collisions; + + // Preslice for MC particles + Preslice perMCCol = aod::mcparticle::mcCollisionId; + + enum ParticleSpecies : int { + kPion = 0, + kKaon = 1, + kProton = 2, + kNSpecies = 3 + }; + + static constexpr int PDGPion = kPiPlus; + static constexpr int PDGKaon = kKPlus; + static constexpr int PDGProton = kProton; + + // Get magnetic field from CCDB + int getMagneticField(uint64_t timestamp) + { + static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + // Get transformed phi for phi cut (with magnetic field) + float getTransformedPhi(const float phi, const int charge, const float magField) const + { + float transformedPhi = phi; + if (magField < 0) { + transformedPhi = o2::constants::math::TwoPI - transformedPhi; + } + if (charge < 0) { + transformedPhi = o2::constants::math::TwoPI - transformedPhi; + } + transformedPhi += o2::constants::math::PI / 18.0f; + transformedPhi = std::fmod(transformedPhi, o2::constants::math::PI / 9.0f); + return transformedPhi; + } + + // Phi cut function (with magnetic field) + template + bool passedPhiCut(const TrackType& track, float magField) const + { + if (!applyPhiCut.value) { + return true; + } + + if (track.pt() < pTthresholdPhiCut.value) { + return true; + } + + float pt = track.pt(); + float phi = track.phi(); + int charge = track.sign(); + + if (magField < 0) { + phi = o2::constants::math::TwoPI - phi; + } + if (charge < 0) { + phi = o2::constants::math::TwoPI - phi; + } + + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + if (phi < fphiCutHigh->Eval(pt) && phi > fphiCutLow->Eval(pt)) { + return false; + } + + return true; + } + + template + int countGeneratedChargedPrimaries(const ParticleContainer& particles, float etaMax, float ptMin) const + { + int count = 0; + for (const auto& particle : particles) { + auto pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (!pdgParticle || pdgParticle->Charge() == 0.) + continue; + + if (!particle.isPhysicalPrimary()) + continue; + + if (std::abs(particle.eta()) > etaMax) + continue; + + if (particle.pt() < ptMin) + continue; + + count++; + } + return count; + } + + template + bool passedNClTPCFoundCut(const T& trk) const + { + if (!nClTPCFoundCut.value) + return true; + return trk.tpcNClsFound() >= minTPCNClsFound.value; + } + + template + bool passedNClTPCPIDCut(const T& trk) const + { + if (!nClTPCPIDCut.value) + return true; + return trk.tpcNClsPID() >= minTPCNClsPID.value; + } + + template + bool passesCutWoDCA(TrackType const& track) const + { + if (useCustomTrackCuts.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy) || + i == static_cast(TrackSelection::TrackCuts::kDCAz)) { + continue; + } + if (!customTrackCuts.IsSelected(track, static_cast(i))) { + return false; + } + } + return true; + } + return track.isGlobalTrackWoDCA(); + } + + template + bool passesDCAxyCut(TrackType const& track) const + { + if (useCustomTrackCuts.value) { + if (!passesCutWoDCA(track)) { + return false; + } + constexpr float DcaXYConst = 0.0105f; + constexpr float DcaXYPtScale = 0.0350f; + constexpr float DcaXYPtPower = 1.1f; + const float maxDcaXY = maxDcaXYFactor.value * (DcaXYConst + DcaXYPtScale / std::pow(track.pt(), DcaXYPtPower)); + return std::abs(track.dcaXY()) <= maxDcaXY; + } + return track.isGlobalTrack(); + } + + template + bool passesTrackSelection(TrackType const& track, float magField = 0) const + { + if (track.eta() < cfgCutEtaMin.value || track.eta() > cfgCutEtaMax.value) + return false; + + if (track.tpcChi2NCl() < minChi2PerClusterTPC.value || track.tpcChi2NCl() > maxChi2PerClusterTPC.value) + return false; + + if (!passesCutWoDCA(track)) + return false; + + if (!passesDCAxyCut(track)) + return false; + + if (!passedNClTPCFoundCut(track)) + return false; + + if (!passedNClTPCPIDCut(track)) + return false; + + // Add phi cut with magnetic field + if (!passedPhiCut(track, magField)) + return false; + + return true; + } + + template + bool passesPIDSelection(TrackType const& track) const + { + float nsigmaTPC = 0.f; + + if constexpr (species == kPion) { + nsigmaTPC = track.tpcNSigmaPi(); + } else if constexpr (species == kKaon) { + nsigmaTPC = track.tpcNSigmaKa(); + } else if constexpr (species == kProton) { + nsigmaTPC = track.tpcNSigmaPr(); + } + + float cutValue = cfgCutNsigma.value; + if constexpr (species == kPion) + cutValue = cfgCutNsigmaPi.value; + if constexpr (species == kKaon) + cutValue = cfgCutNsigmaKa.value; + if constexpr (species == kProton) + cutValue = cfgCutNsigmaPr.value; + + return (std::abs(nsigmaTPC) < cutValue); + } + + template + int getBestPIDHypothesis(TrackType const& track) const + { + float nsigmaPi = std::abs(track.tpcNSigmaPi()); + float nsigmaKa = std::abs(track.tpcNSigmaKa()); + float nsigmaPr = std::abs(track.tpcNSigmaPr()); + + float minNSigma = 999.0f; + int bestSpecies = -1; + + if (nsigmaPi < cfgCutNsigmaPi.value && nsigmaPi < minNSigma) { + minNSigma = nsigmaPi; + bestSpecies = kPion; + } + if (nsigmaKa < cfgCutNsigmaKa.value && nsigmaKa < minNSigma) { + minNSigma = nsigmaKa; + bestSpecies = kKaon; + } + if (nsigmaPr < cfgCutNsigmaPr.value && nsigmaPr < minNSigma) { + minNSigma = nsigmaPr; + bestSpecies = kProton; + } + + return bestSpecies; + } + + template + bool isGoodPrimary(ParticleType const& particle) const + { + auto pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (!pdgParticle || pdgParticle->Charge() == 0.) + return false; + + if (!particle.isPhysicalPrimary()) + return false; + + if (std::abs(particle.eta()) >= cfgCutEtaMax.value) + return false; + if (particle.pt() < cfgTrkLowPtCut.value) + return false; + + return true; + } + + void processData(CollisionTableData::iterator const& collision, + TrackTableData const& tracks, + BCsRun3 const& bcs); + PROCESS_SWITCH(MultiplicityPt, processData, "process data", false); + + void processMC(TrackTableMC const& tracks, + aod::McParticles const& particles, + aod::McCollisions const& mcCollisions, + RecoCollisions const& collisions, + aod::McCollisionLabels const& labels, + aod::McCentFT0Ms const& centTable, + BCsRun3 const& bcs); + PROCESS_SWITCH(MultiplicityPt, processMC, "process MC", true); + + void init(InitContext const&); + + void endOfStream(EndOfStreamContext& /*eos*/) + { + LOG(info) << "\n=== END OF STREAM: Writing histograms to output ==="; + auto hGenMult = ue.get(HIST("MC/EventLoss/GenMultVsCent")); + if (hGenMult) { + LOG(info) << "GenMultVsCent: Entries=" << hGenMult->GetEntries() + << ", Integral=" << hGenMult->Integral(); + } + LOG(info) << "=== END OF STREAM COMPLETE ==="; + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} + +void MultiplicityPt::init(InitContext const&) +{ + LOG(info) << "=================================================="; + LOG(info) << "Initializing MultiplicityPt task with full centrality diagnostics"; + LOG(info) << "=================================================="; + + // Initialize phi cut functions + if (applyPhiCut.value) { + fphiCutLow = new TF1("StandardPhiCutLow", + Form("%f/x/x+pi/18.0-%f", + phiCutLowParam1.value, phiCutLowParam2.value), + 0, 50); + fphiCutHigh = new TF1("StandardPhiCutHigh", + Form("%f/x+pi/18.0+%f", + phiCutHighParam1.value, phiCutHighParam2.value), + 0, 50); + + LOGF(info, "=== Phi Cut Parameters ==="); + LOGF(info, "Low cut: %.6f/x² + pi/18 - %.6f", + phiCutLowParam1.value, phiCutLowParam2.value); + LOGF(info, "High cut: %.6f/x + pi/18 + %.6f", + phiCutHighParam1.value, phiCutHighParam2.value); + LOGF(info, "Applied for pT > %.1f GeV/c", pTthresholdPhiCut.value); + } + + if (useCustomTrackCuts.value) { + LOG(info) << "Using custom track cuts matching spectraTOF approach"; + customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); + + customTrackCuts.SetRequireITSRefit(requireITS.value); + customTrackCuts.SetRequireTPCRefit(requireTPC.value); + customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); + customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + customTrackCuts.SetMinNClustersTPC(minTPCNClsFound.value); + customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + customTrackCuts.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); + customTrackCuts.SetMaxDcaZ(maxDcaZ.value); + + customTrackCuts.print(); + } + + // Axis definitions + ConfigurableAxis ptBinning{"ptBinning", {VARIABLE_WIDTH, 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, 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.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, "pT bin limits"}; + + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + + std::vector centBinningStd = {0., 1., 5., 10., 15., 20., 30., 40., 50., 60., 70., 80., 90., 100.}; + + // Fine centrality binning for diagnostics (100 bins, guaranteed increasing) + std::vector centBinningFine; + for (int i = 0; i <= CentBinMax; i++) { + centBinningFine.push_back(static_cast(i)); + } + + AxisSpec centAxis = {centBinningStd, "FT0M Centrality (%)"}; + AxisSpec centFineAxis = {centBinningFine, "FT0M Centrality (%)"}; + + // Multiplicity axes - properly defined + std::vector multBins; + for (int i = 0; i <= MultBinMax; i++) { + multBins.push_back(static_cast(i)); + } + AxisSpec multAxis = {multBins, "N_{ch}^{gen} (|#eta|<0.8)"}; + + // Reconstructed multiplicity axis - properly defined with explicit bin edges + std::vector recoMultBins; + for (int i = 0; i <= RecMultBinMax; i++) { + recoMultBins.push_back(static_cast(i)); + } + AxisSpec recoMultAxis = {recoMultBins, "N_{ch}^{reco}"}; + + // Centrality diagnostic histograms - USE FINE BINNING + ue.add("Centrality/hCentRaw", "Raw FT0M Centrality (no cuts);Centrality (%);Counts", + HistType::kTH1D, {centFineAxis}); + ue.add("Centrality/hCentAfterVtx", "Centrality after vertex cut;Centrality (%);Counts", + HistType::kTH1D, {centFineAxis}); + ue.add("Centrality/hCentAfterINEL", "Centrality after INEL cut;Centrality (%);Counts", + HistType::kTH1D, {centFineAxis}); + ue.add("Centrality/hCentAfterAll", "Centrality after all cuts;Centrality (%);Counts", + HistType::kTH1D, {centFineAxis}); + + // 2D correlations - USE FINE BINNING FOR DIAGNOSTICS + ue.add("Centrality/hCentVsMult", "Centrality vs Generated Multiplicity;Centrality (%);N_{ch}^{gen}", + HistType::kTH2D, {centFineAxis, multAxis}); + ue.add("Centrality/hMultVsCent", "Generated Multiplicity vs Centrality;N_{ch}^{gen};Centrality (%)", + HistType::kTH2D, {multAxis, centFineAxis}); + ue.add("Centrality/hCentVsVz", "Centrality vs Vertex Z;Centrality (%);V_{z} (cm)", + HistType::kTH2D, {centFineAxis, {40, -20, 20}}); + ue.add("Centrality/hRecoMultVsCent", "Reconstructed Track Multiplicity vs Centrality;Centrality (%);N_{tracks}^{reco}", + HistType::kTH2D, {centFineAxis, recoMultAxis}); + ue.add("Centrality/hGenMultPerCent", "Generated Multiplicity Distribution per Centrality Bin;Centrality (%);", + HistType::kTH2D, {centFineAxis, multAxis}); + + // Vertex resolution vs centrality + ue.add("Centrality/hVertexResVsCent", "Vertex Resolution vs Centrality;Centrality (%);V_{z} resolution (cm)", + HistType::kTH2D, {centFineAxis, {100, -1, 1}}); + + // INEL class distributions + ue.add("INEL/hINELClass", "INEL Class for MC Collisions;INEL Class;Counts", + HistType::kTH1D, {{3, 0.5, 3.5}}); + auto hINEL = ue.get(HIST("INEL/hINELClass")); + hINEL->GetXaxis()->SetBinLabel(1, "INEL0"); + hINEL->GetXaxis()->SetBinLabel(2, "INEL>0"); + hINEL->GetXaxis()->SetBinLabel(3, "INEL>1"); + + ue.add("INEL/hINELVsCent", "INEL Class vs Centrality;Centrality (%);INEL Class", + HistType::kTH2D, {centFineAxis, {3, 0.5, 3.5}}); + + // Cut flow + ue.add("CutFlow/hCutStats", "Cut Statistics;Cut Stage;Counts", + HistType::kTH1D, {{6, 0.5, 6.5}}); + auto hCut = ue.get(HIST("CutFlow/hCutStats")); + hCut->GetXaxis()->SetBinLabel(1, "All reco events"); + hCut->GetXaxis()->SetBinLabel(2, "Has MC match"); + hCut->GetXaxis()->SetBinLabel(3, "Has centrality"); + hCut->GetXaxis()->SetBinLabel(4, "Pass vertex"); + hCut->GetXaxis()->SetBinLabel(5, "Pass INEL"); + hCut->GetXaxis()->SetBinLabel(6, "Selected"); + + ue.add("CutFlow/hCentPerCut", "Centrality Distribution at Each Cut;Cut Stage;Centrality (%)", + HistType::kTH2D, {{6, 0.5, 6.5}, centFineAxis}); + + ue.add("MC/GenRecoCollisions", "Generated and Reconstructed MC Collisions", + HistType::kTH1D, {{10, 0.5, 10.5}}); + auto hColl = ue.get(HIST("MC/GenRecoCollisions")); + hColl->GetXaxis()->SetBinLabel(1, "Collisions generated"); + hColl->GetXaxis()->SetBinLabel(2, "Collisions reconstructed"); + hColl->GetXaxis()->SetBinLabel(3, "INEL>0"); + hColl->GetXaxis()->SetBinLabel(4, "INEL>1"); + + ue.add("hEventLossBreakdown", "Event loss breakdown", + HistType::kTH1D, {{4, 0.5, 4.5}}); + auto hLoss = ue.get(HIST("hEventLossBreakdown")); + hLoss->GetXaxis()->SetBinLabel(1, "Physics selected"); + hLoss->GetXaxis()->SetBinLabel(2, "Reconstructed"); + hLoss->GetXaxis()->SetBinLabel(3, "Selected"); + hLoss->GetXaxis()->SetBinLabel(4, "Final efficiency"); + + // Multiplicity histograms + ue.add("MC/EventLoss/NchGenerated", "Generated charged multiplicity;N_{ch}^{gen} (|#eta|<0.8);Counts", + HistType::kTH1D, {{200, 0, 200}}); + ue.add("MC/EventLoss/NchGenerated_PhysicsSelected", "Generated charged multiplicity (physics selected);N_{ch}^{gen} (|#eta|<0.8);Counts", + HistType::kTH1D, {{200, 0, 200}}); + ue.add("MC/EventLoss/NchGenerated_Reconstructed", "Generated charged multiplicity (reconstructed);N_{ch}^{gen} (|#eta|<0.8);Counts", + HistType::kTH1D, {{200, 0, 200}}); + + // pT vs Multiplicity + ue.add("MC/GenPtVsNch", "Generated pT vs Multiplicity;#it{p}_{T} (GeV/#it{c});N_{ch}^{gen}", + HistType::kTH2D, {ptAxis, {200, 0, 200}}); + ue.add("MC/GenPtVsNch_PhysicsSelected", "Generated pT vs Multiplicity (physics selected);#it{p}_{T} (GeV/#it{c});N_{ch}^{gen}", + HistType::kTH2D, {ptAxis, {200, 0, 200}}); + + // Centrality vs Multiplicity correlations - USE STANDARD BINNING FOR THESE + ue.add("MC/EventLoss/GenMultVsCent", "Generated charged particles vs FT0M centrality;FT0M Centrality (%);N_{ch}^{gen} (|#eta|<0.8)", + HistType::kTH2D, {centAxis, multAxis}); + ue.add("MC/EventLoss/GenMultVsCent_Selected", "Generated vs FT0M centrality (selected events);FT0M Centrality (%);N_{ch}^{gen}", + HistType::kTH2D, {centAxis, multAxis}); + ue.add("MC/EventLoss/GenMultVsCent_Rejected", "Generated vs FT0M centrality (rejected events);FT0M Centrality (%);N_{ch}^{gen}", + HistType::kTH2D, {centAxis, multAxis}); + + // TPC cluster histograms + ue.add("hNclFoundTPC", "Number of TPC found clusters", + HistType::kTH1D, {{200, 0, 200, "N_{cl, found}"}}); + ue.add("hNclPIDTPC", "Number of TPC PID clusters", + HistType::kTH1D, {{200, 0, 200, "N_{cl, PID}"}}); + ue.add("hNclFoundTPCvsPt", "TPC found clusters vs pT;#it{p}_{T} (GeV/#it{c});N_{cl,found}", + HistType::kTH2D, {ptAxis, {200, 0., 200.}}); + ue.add("hNclPIDTPCvsPt", "TPC PID clusters vs pT;#it{p}_{T} (GeV/#it{c});N_{cl,PID}", + HistType::kTH2D, {ptAxis, {200, 0., 200.}}); + + // Inclusive histograms + ue.add("Inclusive/hPtPrimGenAll", "All generated primaries (no cuts);#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtPrimBadVertex", "Generated primaries (bad vertex);#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtPrimGen", "Generated primaries (after physics selection);#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtPrimRecoEv", "Generated primaries (reco events);#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtPrimGoodEv", "Generated primaries (good events);#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + + ue.add("Inclusive/hPtNumEff", "Tracking efficiency numerator;#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtDenEff", "Tracking efficiency denominator;#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + + ue.add("Inclusive/hPtAllReco", "All reconstructed tracks;#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtPrimReco", "Reconstructed primaries;#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + ue.add("Inclusive/hPtSecReco", "Reconstructed secondaries;#it{p}_{T} (GeV/#it{c});Counts", + HistType::kTH1D, {ptAxis}); + + ue.add("Inclusive/hPtMeasuredVsCent", "All measured tracks (PID) vs centrality;#it{p}_{T} (GeV/#it{c});FT0M Centrality (%)", + HistType::kTH2D, {ptAxis, centAxis}); + + // Phi cut monitoring histograms + if (applyPhiCut.value) { + ue.add("PhiCut/hPtVsPhiPrimeBefore", "pT vs φ' before cut;p_{T} (GeV/c);φ'", + HistType::kTH2F, {{100, 0, 10}, {100, 0, 0.4}}); + ue.add("PhiCut/hPtVsPhiPrimeAfter", "pT vs φ' after cut;p_{T} (GeV/c);φ'", + HistType::kTH2F, {{100, 0, 10}, {100, 0, 0.4}}); + ue.add("PhiCut/hRejectionRate", "Track rejection rate by phi cut;p_{T} (GeV/c);Rejection Rate", + HistType::kTProfile, {{100, 0, 10}}); + } + + // Particle-specific histograms + const std::array particleNames = {"Pion", "Kaon", "Proton"}; + const std::array particleSymbols = {"#pi^{#pm}", "K^{#pm}", "p+#bar{p}"}; + + for (int iSpecies = 0; iSpecies < kNSpecies; ++iSpecies) { + const auto& name = particleNames[iSpecies]; + const auto& symbol = particleSymbols[iSpecies]; + + ue.add(Form("%s/hPtPrimGenAll", name.c_str()), + Form("All generated %s (no cuts);#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtPrimBadVertex", name.c_str()), + Form("Generated %s (bad vertex);#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtPrimGen", name.c_str()), + Form("Generated %s (after physics selection);#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtPrimRecoEv", name.c_str()), + Form("Generated %s (reco events);#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtPrimGoodEv", name.c_str()), + Form("Generated %s (good events);#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + + ue.add(Form("%s/hPtNumEff", name.c_str()), + Form("%s tracking efficiency numerator;#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtDenEff", name.c_str()), + Form("%s tracking efficiency denominator;#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + + ue.add(Form("%s/hPtAllReco", name.c_str()), + Form("All reconstructed %s;#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtPrimReco", name.c_str()), + Form("Reconstructed primary %s;#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + ue.add(Form("%s/hPtSecReco", name.c_str()), + Form("Reconstructed secondary %s;#it{p}_{T} (GeV/#it{c});Counts", symbol.c_str()), + HistType::kTH1D, {ptAxis}); + + ue.add(Form("%s/hPtMeasuredVsCent", name.c_str()), + Form("Measured %s (PID) vs centrality;#it{p}_{T} (GeV/#it{c});FT0M Centrality (%%)", symbol.c_str()), + HistType::kTH2D, {ptAxis, centAxis}); + + if (enablePIDHistograms) { + ue.add(Form("%s/hNsigmaTPC", name.c_str()), + Form("TPC n#sigma %s;#it{p}_{T} (GeV/#it{c});n#sigma_{TPC}", symbol.c_str()), + HistType::kTH2D, {ptAxis, {200, -10, 10}}); + } + } + + // Event selection histogram + constexpr int NEvSelBins = 20; + constexpr float EvSelMin = 0.5f; + constexpr float EvSelMax = 20.5f; + ue.add("evsel", "Event selection", HistType::kTH1D, {{NEvSelBins, EvSelMin, EvSelMax}}); + auto h = ue.get(HIST("evsel")); + h->GetXaxis()->SetBinLabel(1, "Events read"); + h->GetXaxis()->SetBinLabel(4, "Trigger 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(13, "posZ passed"); + + // Basic tracking histograms + ue.add("hEta", "Track eta;#eta;Counts", HistType::kTH1D, {{20, -0.8, 0.8}}); + ue.add("hPhi", "Track phi;#varphi (rad);Counts", HistType::kTH1D, {{64, 0, TwoPI}}); + ue.add("hvtxZ", "Vertex Z (data);Vertex Z (cm);Events", HistType::kTH1F, {{40, -20.0, 20.0}}); + ue.add("hvtxZmc", "MC vertex Z;Vertex Z (cm);Events", HistType::kTH1F, {{40, -20.0, 20.0}}); + + LOG(info) << "=== Initialized MultiplicityPt task with full centrality diagnostics ==="; + LOG(info) << "Standard centrality binning: " << centBinningStd.size() - 1 << " bins (0-100%)"; + LOG(info) << "Fine centrality binning: " << centBinningFine.size() - 1 << " bins (0-100%)"; + if (applyPhiCut.value) { + LOG(info) << "Phi cut ENABLED for pT > " << pTthresholdPhiCut.value << " GeV/c"; + } +} + +void MultiplicityPt::processData(CollisionTableData::iterator const& /*collision*/, + TrackTableData const& /*tracks*/, + BCsRun3 const& /*bcs*/) +{ + // Intentionally empty - data processing disabled +} + +void MultiplicityPt::processMC(TrackTableMC const& tracks, + aod::McParticles const& particles, + aod::McCollisions const& mcCollisions, + RecoCollisions const& collisions, + aod::McCollisionLabels const& labels, + aod::McCentFT0Ms const& centTable, + BCsRun3 const& /*bcs*/) +{ + LOG(info) << "\n=== processMC START ==="; + LOG(info) << "Total MC collisions (generated): " << mcCollisions.size(); + LOG(info) << "Total reconstructed collisions: " << collisions.size(); + LOG(info) << "Total collision labels: " << labels.size(); + LOG(info) << "Total centrality entries: " << centTable.size(); + + LOG(info) << "\n=== CENTRALITY DEBUG - RAW DATA ==="; + LOG(info) << "First 20 centrality values from centTable:"; + int debugCount = 0; + float minCent = 999.0f, maxCent = -999.0f; + std::map centDistribution; + + for (const auto& cent : centTable) { + float c = cent.centFT0M(); + if (debugCount < DebugCountMax) { + LOG(info) << " Cent entry " << debugCount << ": " << c; + } + minCent = std::min(minCent, c); + maxCent = std::max(maxCent, c); + + int bin10 = static_cast(c / 10) * 10; + centDistribution[bin10]++; + debugCount++; + } + + LOG(info) << "Centrality range: [" << minCent << ", " << maxCent << "]"; + LOG(info) << "Distribution by 10% bins:"; + for (int i = 0; i < CentBinMax; i += 10) { + LOG(info) << " " << i << "-" << i + 10 << "%: " << centDistribution[i]; + } + + // Check if centrality is inverted (0 = peripheral, 100 = central) + // If minCent is near 0 and maxCent near 100, check correlation with multiplicity + LOG(info) << "Checking if centrality might be inverted..."; + LOG(info) << "Will check correlation with multiplicity in the next step."; + + std::map mcCollisionToNch; + std::map mcCollisionVz; + std::set physicsSelectedMCCollisions; + std::map mcCollisionToINELClass; // 0=INEL0, 1=INEL>0, 2=INEL>1 + + ue.fill(HIST("MC/GenRecoCollisions"), 1.f, mcCollisions.size()); + ue.fill(HIST("MC/GenRecoCollisions"), 2.f, collisions.size()); + + LOG(info) << "\n--- FIRST PASS: Building MC collision maps ---"; + + int mcWithParticles = 0; + int mcINELgt0 = 0, mcINELgt1 = 0; + + for (const auto& mcCollision : mcCollisions) { + int64_t mcCollId = mcCollision.globalIndex(); + auto particlesInCollision = particles.sliceBy(perMCCol, mcCollId); + + int nGenCharged = countGeneratedChargedPrimaries(particlesInCollision, cfgCutEtaMax.value, cfgTrkLowPtCut.value); + + mcCollisionToNch[mcCollId] = nGenCharged; + mcCollisionVz[mcCollId] = mcCollision.posZ(); + + // Determine INEL class + bool inel0 = o2::pwglf::isINELgt0mc(particlesInCollision, pdg); + bool inel1 = o2::pwglf::isINELgt1mc(particlesInCollision, pdg); + + int inelClass = 0; + if (inel1) + inelClass = 2; + else if (inel0) + inelClass = 1; + mcCollisionToINELClass[mcCollId] = inelClass; + + ue.fill(HIST("INEL/hINELClass"), inelClass); + + if (inel0) + mcINELgt0++; + if (inel1) + mcINELgt1++; + if (nGenCharged > 0) + mcWithParticles++; + + ue.fill(HIST("MC/EventLoss/NchGenerated"), nGenCharged); + + // Physics selection based on vertex and INEL cuts + bool physicsSelected = true; + + if (std::abs(mcCollision.posZ()) > cfgCutVertex.value) { + physicsSelected = false; + } + + // Apply INEL cut based on configuration + if (cfgINELCut.value == INELgt0 && !inel0) { + physicsSelected = false; + } + if (cfgINELCut.value == INELgt1 && !inel1) { + physicsSelected = false; + } + + if (physicsSelected) { + physicsSelectedMCCollisions.insert(mcCollId); + ue.fill(HIST("MC/EventLoss/NchGenerated_PhysicsSelected"), nGenCharged); + + if (inel0) { + ue.fill(HIST("MC/GenRecoCollisions"), 3.f); + } + if (inel1) { + ue.fill(HIST("MC/GenRecoCollisions"), 4.f); + } + } + } + + LOG(info) << "\n--- FIRST PASS SUMMARY ---"; + LOG(info) << "Total MC collisions processed: " << mcCollisions.size(); + LOG(info) << "MC collisions with particles: " << mcWithParticles; + LOG(info) << "INEL0: " << (mcCollisions.size() - mcINELgt0); + LOG(info) << "INEL>0: " << mcINELgt0; + LOG(info) << "INEL>1: " << mcINELgt1; + LOG(info) << "Physics-selected MC collisions: " << physicsSelectedMCCollisions.size(); + + std::map recoToMcMap; + std::map recoToCentMap; + + size_t nCollisions = collisions.size(); + + // Associate labels with collisions by index + size_t iLabel = 0; + for (const auto& label : labels) { + if (iLabel < nCollisions) { + const auto& collision = collisions.iteratorAt(iLabel); + int64_t recoCollId = collision.globalIndex(); + int64_t mcCollId = label.mcCollisionId(); + recoToMcMap[recoCollId] = mcCollId; + } + iLabel++; + } + + // Associate centrality with collisions by index + size_t iCent = 0; + for (const auto& cent : centTable) { + if (iCent < nCollisions) { + const auto& collision = collisions.iteratorAt(iCent); + int64_t recoCollId = collision.globalIndex(); + float centValue = cent.centFT0M(); + + // Fill raw centrality histogram + ue.fill(HIST("Centrality/hCentRaw"), centValue); + + recoToCentMap[recoCollId] = centValue; + } + iCent++; + } + + LOG(info) << "\n--- MAP SIZES ---"; + LOG(info) << "recoToMcMap size: " << recoToMcMap.size(); + LOG(info) << "recoToCentMap size: " << recoToCentMap.size(); + + LOG(info) << "\n=== CENTRALITY VS MULTIPLICITY DEBUG ==="; + + // Create temporary vectors to check correlation + std::vector> centMultPairs; + for (const auto& collision : collisions) { + int64_t collId = collision.globalIndex(); + + auto mcIt = recoToMcMap.find(collId); + if (mcIt == recoToMcMap.end()) + continue; + + auto centIt = recoToCentMap.find(collId); + if (centIt == recoToCentMap.end()) + continue; + + auto nchIt = mcCollisionToNch.find(mcIt->second); + if (nchIt == mcCollisionToNch.end()) + continue; + + centMultPairs.push_back({centIt->second, nchIt->second}); + } + + // Sort by centrality + std::sort(centMultPairs.begin(), centMultPairs.end()); + + LOG(info) << "Correlation between centrality and multiplicity:"; + LOG(info) << " If centrality is normal (0=central, 100=peripheral), multiplicity should decrease with centrality"; + LOG(info) << " If inverted (0=peripheral, 100=central), multiplicity should increase with centrality"; + + // Print a few samples across the range + if (centMultPairs.size() > CentMultClasses) { + for (size_t i = 0; i < centMultPairs.size(); i += centMultPairs.size() / 10) { + LOG(info) << " Cent: " << centMultPairs[i].first + << "%, Mult: " << centMultPairs[i].second; + } + } + + //=========================================================================== + // SECOND PASS: Process reconstructed collisions with detailed cut accounting + //=========================================================================== + + LOG(info) << "\n--- SECOND PASS: Processing reconstructed collisions ---"; + + std::set reconstructedMCCollisions; + std::set selectedMCCollisions; + + int nRecoCollisions = 0; + int nSelectedEvents = 0; + int nRejectedEvents = 0; + int nNoMCMatch = 0; + int nNoCent = 0; + int nInvalidCent = 0; + + // Cut counters + int nPassVertex = 0; + int nPassINEL = 0; + int nPassAll = 0; + + // For mean calculations + std::vector centAll, centVertex, centINEL, centSelected; + + for (const auto& collision : collisions) { + nRecoCollisions++; + + int64_t collId = collision.globalIndex(); + + // Fill cut flow + ue.fill(HIST("CutFlow/hCutStats"), 1); + + // Get MC collision ID from labels map + auto mcIt = recoToMcMap.find(collId); + if (mcIt == recoToMcMap.end()) { + nNoMCMatch++; + continue; + } + ue.fill(HIST("CutFlow/hCutStats"), 2); + + int64_t mcCollId = mcIt->second; + + // Get generated multiplicity for this MC collision + auto nchIt = mcCollisionToNch.find(mcCollId); + if (nchIt == mcCollisionToNch.end()) { + continue; + } + + int nGenCharged = nchIt->second; + + // Get INEL class + auto inelIt = mcCollisionToINELClass.find(mcCollId); + int inelClass = (inelIt != mcCollisionToINELClass.end()) ? inelIt->second : 0; + + // Get centrality from cent map + auto centIt = recoToCentMap.find(collId); + if (centIt == recoToCentMap.end()) { + nNoCent++; + continue; + } + ue.fill(HIST("CutFlow/hCutStats"), 3); + + float cent = centIt->second; + if (cent < 0 || cent > CentBinMax) { + nInvalidCent++; + continue; + } + + // Store all events with valid info + centAll.push_back(cent); + ue.fill(HIST("Centrality/hCentVsMult"), cent, nGenCharged); + ue.fill(HIST("Centrality/hMultVsCent"), nGenCharged, cent); + ue.fill(HIST("Centrality/hCentVsVz"), cent, collision.posZ()); + ue.fill(HIST("INEL/hINELVsCent"), cent, inelClass); + + // Track cuts progressively + bool passVertex = std::abs(collision.posZ()) <= cfgCutVertex.value; + if (passVertex) { + centVertex.push_back(cent); + ue.fill(HIST("Centrality/hCentAfterVtx"), cent); + ue.fill(HIST("CutFlow/hCutStats"), 4); + ue.fill(HIST("CutFlow/hCentPerCut"), 4, cent); + nPassVertex++; + } + + // Check INEL selection at generator level + bool passINEL = true; + if (cfgINELCut.value == INELgt0 && inelClass < INELgt0) + passINEL = false; + if (cfgINELCut.value == INELgt1 && inelClass < INELgt1) + passINEL = false; + + if (passINEL) { + centINEL.push_back(cent); + ue.fill(HIST("Centrality/hCentAfterINEL"), cent); + ue.fill(HIST("CutFlow/hCutStats"), 5); + ue.fill(HIST("CutFlow/hCentPerCut"), 5, cent); + nPassINEL++; + } + + // Fill GenMultVsCent for all reconstructed events + ue.fill(HIST("MC/EventLoss/GenMultVsCent"), cent, nGenCharged); + ue.fill(HIST("MC/EventLoss/NchGenerated_Reconstructed"), nGenCharged); + + reconstructedMCCollisions.insert(mcCollId); + + // Apply all cuts + bool passedAll = passVertex && passINEL; + + if (!passedAll) { + ue.fill(HIST("MC/EventLoss/GenMultVsCent_Rejected"), cent, nGenCharged); + nRejectedEvents++; + continue; + } + + // Event passed all selections + centSelected.push_back(cent); + ue.fill(HIST("Centrality/hCentAfterAll"), cent); + ue.fill(HIST("CutFlow/hCutStats"), 6); + ue.fill(HIST("CutFlow/hCentPerCut"), 6, cent); + ue.fill(HIST("MC/EventLoss/GenMultVsCent_Selected"), cent, nGenCharged); + ue.fill(HIST("hvtxZ"), collision.posZ()); + selectedMCCollisions.insert(mcCollId); + nSelectedEvents++; + nPassAll++; + + // Get magnetic field for phi cut + float magField = 0; + if (applyPhiCut.value) { + const auto& bc = collision.bc_as(); + magField = getMagneticField(bc.timestamp()); + } + + // Process tracks in selected events + int nTracksInEvent = 0; + for (const auto& track : tracks) { + if (!track.has_collision()) + continue; + if (track.collisionId() != collId) + continue; + + // Fill phi cut monitoring before cut + if (applyPhiCut.value && track.pt() >= pTthresholdPhiCut.value) { + float phiPrime = getTransformedPhi(track.phi(), track.sign(), magField); + ue.fill(HIST("PhiCut/hPtVsPhiPrimeBefore"), track.pt(), phiPrime); + } + + if (!passesTrackSelection(track, magField)) { + continue; + } + + // Fill phi cut monitoring after cut + if (applyPhiCut.value && track.pt() >= pTthresholdPhiCut.value) { + float phiPrime = getTransformedPhi(track.phi(), track.sign(), magField); + ue.fill(HIST("PhiCut/hPtVsPhiPrimeAfter"), track.pt(), phiPrime); + } + + nTracksInEvent++; + + // Fill TPC cluster histograms + ue.fill(HIST("hNclFoundTPC"), track.tpcNClsFound()); + ue.fill(HIST("hNclPIDTPC"), track.tpcNClsPID()); + ue.fill(HIST("hNclFoundTPCvsPt"), track.pt(), track.tpcNClsFound()); + ue.fill(HIST("hNclPIDTPCvsPt"), track.pt(), track.tpcNClsPID()); + + ue.fill(HIST("Inclusive/hPtAllReco"), track.pt()); + ue.fill(HIST("Inclusive/hPtMeasuredVsCent"), track.pt(), cent); + ue.fill(HIST("hEta"), track.eta()); + ue.fill(HIST("hPhi"), track.phi()); + + if (track.has_mcParticle()) { + const auto& particle = track.mcParticle(); + int pdgCode = std::abs(particle.pdgCode()); + + if (particle.isPhysicalPrimary()) { + ue.fill(HIST("Inclusive/hPtNumEff"), particle.pt()); + ue.fill(HIST("Inclusive/hPtPrimReco"), track.pt()); + + if (pdgCode == PDGPion) { + ue.fill(HIST("Pion/hPtNumEff"), particle.pt()); + ue.fill(HIST("Pion/hPtPrimReco"), track.pt()); + } else if (pdgCode == PDGKaon) { + ue.fill(HIST("Kaon/hPtNumEff"), particle.pt()); + ue.fill(HIST("Kaon/hPtPrimReco"), track.pt()); + } else if (pdgCode == PDGProton) { + ue.fill(HIST("Proton/hPtNumEff"), particle.pt()); + ue.fill(HIST("Proton/hPtPrimReco"), track.pt()); + } + } else { + ue.fill(HIST("Inclusive/hPtSecReco"), track.pt()); + + if (pdgCode == PDGPion) { + ue.fill(HIST("Pion/hPtSecReco"), track.pt()); + } else if (pdgCode == PDGKaon) { + ue.fill(HIST("Kaon/hPtSecReco"), track.pt()); + } else if (pdgCode == PDGProton) { + ue.fill(HIST("Proton/hPtSecReco"), track.pt()); + } + } + } + + int bestSpecies = getBestPIDHypothesis(track); + + if (bestSpecies == kPion) { + ue.fill(HIST("Pion/hPtMeasuredVsCent"), track.pt(), cent); + ue.fill(HIST("Pion/hPtAllReco"), track.pt()); + + if (enablePIDHistograms) { + ue.fill(HIST("Pion/hNsigmaTPC"), track.pt(), track.tpcNSigmaPi()); + } + } else if (bestSpecies == kKaon) { + ue.fill(HIST("Kaon/hPtMeasuredVsCent"), track.pt(), cent); + ue.fill(HIST("Kaon/hPtAllReco"), track.pt()); + + if (enablePIDHistograms) { + ue.fill(HIST("Kaon/hNsigmaTPC"), track.pt(), track.tpcNSigmaKa()); + } + } else if (bestSpecies == kProton) { + ue.fill(HIST("Proton/hPtMeasuredVsCent"), track.pt(), cent); + ue.fill(HIST("Proton/hPtAllReco"), track.pt()); + + if (enablePIDHistograms) { + ue.fill(HIST("Proton/hNsigmaTPC"), track.pt(), track.tpcNSigmaPr()); + } + } + } + + // Fill event-level track multiplicity + ue.fill(HIST("Centrality/hRecoMultVsCent"), cent, nTracksInEvent); + } + + // Calculate and display cut statistics + LOG(info) << "\n=== CUT STATISTICS ==="; + LOG(info) << "Total collisions with valid info: " << centAll.size(); + LOG(info) << "Pass vertex cut: " << nPassVertex << " (" + << (centAll.size() > 0 ? 100.0 * nPassVertex / centAll.size() : 0.0) << "%)"; + LOG(info) << "Pass INEL cut: " << nPassINEL << " (" + << (centAll.size() > 0 ? 100.0 * nPassINEL / centAll.size() : 0.0) << "%)"; + LOG(info) << "Pass all cuts: " << nPassAll << " (" + << (centAll.size() > 0 ? 100.0 * nPassAll / centAll.size() : 0.0) << "%)"; + LOG(info) << "Reco collisions: " << nRecoCollisions; + LOG(info) << "Selected Events: " << nSelectedEvents; + LOG(info) << "Rejected Events: " << nRejectedEvents; + LOG(info) << "No Match: " << nNoMCMatch; + LOG(info) << "No Cent: " << nNoCent; + LOG(info) << "Invalid Cent: " << nInvalidCent; + + // Calculate mean centrality at each stage + if (!centAll.empty()) { + float meanAll = std::accumulate(centAll.begin(), centAll.end(), 0.0) / centAll.size(); + float meanVertex = centVertex.empty() ? 0 : std::accumulate(centVertex.begin(), centVertex.end(), 0.0) / centVertex.size(); + float meanINEL = centINEL.empty() ? 0 : std::accumulate(centINEL.begin(), centINEL.end(), 0.0) / centINEL.size(); + float meanSelected = centSelected.empty() ? 0 : std::accumulate(centSelected.begin(), centSelected.end(), 0.0) / centSelected.size(); + + LOG(info) << "\n=== CENTRALITY MEANS ==="; + LOG(info) << "Mean centrality (all): " << meanAll; + LOG(info) << "Mean centrality (after vertex): " << meanVertex; + LOG(info) << "Mean centrality (after INEL): " << meanINEL; + LOG(info) << "Mean centrality (selected): " << meanSelected; + } + + ue.fill(HIST("hEventLossBreakdown"), 1.f, physicsSelectedMCCollisions.size()); + ue.fill(HIST("hEventLossBreakdown"), 2.f, reconstructedMCCollisions.size()); + ue.fill(HIST("hEventLossBreakdown"), 3.f, selectedMCCollisions.size()); + + float efficiency = physicsSelectedMCCollisions.size() > 0 ? 100.f * selectedMCCollisions.size() / physicsSelectedMCCollisions.size() : 0; + ue.fill(HIST("hEventLossBreakdown"), 4.f, efficiency); + + LOG(info) << "\n=== FINAL EFFICIENCY ==="; + LOG(info) << "Physics selected: " << physicsSelectedMCCollisions.size(); + LOG(info) << "Reconstructed: " << reconstructedMCCollisions.size(); + LOG(info) << "Selected: " << selectedMCCollisions.size(); + LOG(info) << "Efficiency: " << efficiency << "%"; + LOG(info) << "=== processMC END ==="; +} diff --git a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx index 2f7aa796ec3..f1ee505a4e5 100644 --- a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx +++ b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx @@ -22,20 +22,21 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" #include "ReconstructionDataFormats/Track.h" #include @@ -127,7 +128,6 @@ struct NucleitpcPbPb { HistogramRegistry histomc{"histomc", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Event Selection Configurables - Configurable removeITSROFrameBorder{"removeITSROFrameBorder", false, "Remove ITS RO frame border"}; Configurable removeNoSameBunchPileup{"removeNoSameBunchPileup", false, "Remove no same bunch pileup"}; Configurable requireIsGoodZvtxFT0vsPV{"requireIsGoodZvtxFT0vsPV", false, "Require is good Zvtx FT0 vs PV"}; Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "Require is vertex ITS TPC"}; @@ -182,7 +182,6 @@ struct NucleitpcPbPb { Configurable cfgRigidityCorrection{"cfgRigidityCorrection", false, "apply rigidity correction"}; Configurable cfgRequirebetaplot{"cfgRequirebetaplot", true, "Require beta plot"}; Configurable cfgmass2{"cfgmass2", true, "Fill mass square difference"}; - Configurable cfgFillhspectra{"cfgFillhspectra", true, "fill data sparsh"}; Configurable cfgFillmass{"cfgFillmass", false, "Fill mass histograms"}; Configurable cfgFillmassnsigma{"cfgFillmassnsigma", true, "Fill mass vs nsigma histograms"}; @@ -206,12 +205,9 @@ struct NucleitpcPbPb { ConfigurableAxis axismass{"axismass", {1200, 0, 12}, "mass"}; ConfigurableAxis axismassnsigma{"axismassnsigma", {1200, 0, 12}, "nsigma mass"}; ConfigurableAxis nsigmaAxis{"nsigmaAxis", {160, -10, 10}, "n#sigma_{#pi^{+}}"}; - ConfigurableAxis speciesBitAxis{"speciesBitAxis", {8, -0.5, 7.5}, "particle type 0: pion, 1: proton, 2: deuteron, 3: triton, 4:He3, 5:He4"}; - ConfigurableAxis speciesTrackingAxis{"speciesTrackingAxis", {11, -0.5, 10.5}, "particle type 0: pion, 1: proton, 2: deuteron, 3: triton, 4:He3, 5:He4"}; ConfigurableAxis axisDCA{"axisDCA", {400, -10., 10.}, "DCA axis"}; ConfigurableAxis particleAntiAxis{"particleAntiAxis", {2, -0.5, 1.5}, "Particle/Anti-particle"}; // 0 = particle, 1 = anti-particle ConfigurableAxis decayTypeAxis{"decayTypeAxis", {3, -0.5, 2.5}, "Decay type"}; // 0 = primary, 1 = from decay, 2 = material - ConfigurableAxis axisTPCsig{"axisTPCsig", {1000, 0, 2000}, "TPC signal (a.u.)"}; // CCDB Service ccdb; @@ -229,6 +225,8 @@ struct NucleitpcPbPb { int mRunNumber, occupancy; float dBz; TRandom3 rand; + + float de = 2; float triton = 3; float he3 = 4; float he4 = 5; @@ -253,99 +251,80 @@ struct NucleitpcPbPb { histos.add("histCentFT0C", "histCentFT0C", kTH1F, {axisCent}); histos.add("histCentFT0M", "histCentFT0M", kTH1F, {axisCent}); histos.add("histCentFTOC_cut", "histCentFTOC_cut", kTH1F, {axisCent}); - histos.add("hSpectra", " ", HistType::kTHnSparseF, {speciesBitAxis, ptAxis, nsigmaAxis, {5, -2.5, 2.5}, axisCent, axisDCA, axisDCA, axisOccupancy}); - histos.add("DCAxy_vs_pT_He3_data", "DCA_{xy} vs p_{T} for He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histos.add("DCAxy_vs_pT_antiHe3_data", "DCA_{xy} vs p_{T} for anti-He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - - histos.add("TPCsig_triton", "TPC signal for triton;p/z (GeV/c);TPC signal", - {HistType::kTH2F, {axisRigidity, axisTPCsig}}); - histos.add("TPCsig_he3", "TPC signal for he3;p/z (GeV/c);TPC signal", - {HistType::kTH2F, {axisRigidity, axisTPCsig}}); - histos.add("TPCsig_he4", "TPC signal for he4;p/z (GeV/c);TPC signal", - {HistType::kTH2F, {axisRigidity, axisTPCsig}}); + histos.add("hSpectra", " ", HistType::kTHnSparseF, {ptAxis, nsigmaAxis, {5, -2.5, 2.5}, axisCent}); + histos.add("DCAxy_vs_pT_data", "DCA_{xy} vs p_{T} for He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histos.add("DCAxy_vs_pT_anti_data", "DCA_{xy} vs p_{T} for anti-He3 (Data);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + + hmass.resize(2 * nParticles + 2); + hmassnsigma.resize(2 * nParticles + 2); + + for (int i = 0; i < nParticles; i++) { + TString histName = primaryParticles[i].name; + if (cfgFillmass) { + hmass[2 * i] = histos.add(Form("histmass_pt/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); + hmass[2 * i + 1] = histos.add(Form("histmass_ptanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); + } + } + for (int i = 0; i < nParticles; i++) { + TString histName = primaryParticles[i].name; + if (cfgFillmassnsigma) { + hmassnsigma[2 * i] = histos.add(Form("histmass_nsigma/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; Centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); + hmassnsigma[2 * i + 1] = histos.add(Form("histmass_nsigmaanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); + } + } + + histos.add("histeta", "histeta", kTH1F, {axiseta}); + + histos.add("histEvents", "histEvents", kTH2F, {axisCent, axisOccupancy}); } - histos.add("histeta", "histeta", kTH1F, {axiseta}); - histos.add("histEvents", "histEvents", kTH2F, {axisCent, axisOccupancy}); + histos.add("dcaZ", "dcaZ", kTH2F, {ptAxis, axisDCA}); histos.add("dcaXY", "dcaXY", kTH2F, {ptAxis, axisDCA}); histos.add("Tofsignal", "Tofsignal", kTH2F, {axisRigidity, {4000, 0.2, 1.2, "#beta"}}); histos.add("Tpcsignal", "Tpcsignal", kTH2F, {axisRigidity, axisdEdx}); - hmass.resize(2 * nParticles + 2); - hmassnsigma.resize(2 * nParticles + 2); - - for (int i = 0; i < nParticles; i++) { - TString histName = primaryParticles[i].name; - if (cfgFillmass) { - hmass[2 * i] = histos.add(Form("histmass_pt/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); - hmass[2 * i + 1] = histos.add(Form("histmass_ptanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismass, axisCent}); - } - } - for (int i = 0; i < nParticles; i++) { - TString histName = primaryParticles[i].name; - if (cfgFillmassnsigma) { - hmassnsigma[2 * i] = histos.add(Form("histmass_nsigma/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; Centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); - hmassnsigma[2 * i + 1] = histos.add(Form("histmass_nsigmaanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}/z^{2}; centrality(%)", HistType::kTH3F, {ptAxis, axismassnsigma, axisCent}); - } - } - if (doprocessMC) { - histomc.add("hSpectramc", " ", HistType::kTHnSparseF, {speciesBitAxis, {5, -2.5, 2.5}, axisCent, ptAxis, ptAxis}); + histomc.add("hSpectramc", " ", HistType::kTHnSparseF, {{5, -2.5, 2.5}, axisCent, ptAxis, ptAxis}); // Efficiency x Acceptance histomc.add("hDenomEffAcc", "Denominator for Efficiency x Acceptance", - {HistType::kTHnSparseF, {speciesBitAxis, ptAxis, axisrapidity, axisCent, particleAntiAxis, decayTypeAxis}}); + {HistType::kTHnSparseF, {ptAxis, axisCent, particleAntiAxis, decayTypeAxis}}); histomc.add("hNumerEffAcc", "Numerator for Efficiency x Acceptance", - {HistType::kTHnSparseF, {speciesBitAxis, ptAxis, axisrapidity, axisCent, particleAntiAxis, decayTypeAxis}}); + {HistType::kTHnSparseF, {ptAxis, axisCent, particleAntiAxis, decayTypeAxis}}); // The Signal loss correction - histomc.add("hHe3SignalLossDenom", "He3 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("hHe3SignalLossNumer", "He3 Signal Loss Numerator", kTH1F, {axisCent}); - histomc.add("hHe4SignalLossDenom", "He4 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("hHe4SignalLossNumer", "He4 Signal Loss Numerator", kTH1F, {axisCent}); + histomc.add("hSignalLossDenom", "Signal Loss Denominator", kTH2F, {axisCent, ptAxis}); + histomc.add("hSignalLossNumer", "Signal Loss Numerator", kTH2F, {axisCent, ptAxis}); - histomc.add("haHe3SignalLossDenom", "He3 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("haHe3SignalLossNumer", "He3 Signal Loss Numerator", kTH1F, {axisCent}); - histomc.add("haHe4SignalLossDenom", "He4 Signal Loss Denominator", kTH1F, {axisCent}); - histomc.add("haHe4SignalLossNumer", "He4 Signal Loss Numerator", kTH1F, {axisCent}); + histomc.add("haSignalLossDenom", "anti particle Signal Loss Denominator", kTH2F, {axisCent, ptAxis}); + histomc.add("haSignalLossNumer", "antiparticle Signal Loss Numerator", kTH2F, {axisCent, ptAxis}); // The event loss correction histomc.add("hEventLossDenom", "Event loss denominator", kTH1F, {axisCent}); histomc.add("hEventLossNumer", "Event loss numerator", kTH1F, {axisCent}); histomc.add("histVtxZgen", "histVtxZgen", kTH1F, {axisVtxZ}); - histomc.add("histNevReco", "histNevReco", kTH1F, {axisNev}); histomc.add("histVtxZReco", "histVtxZReco", kTH1F, {axisVtxZ}); - histomc.add("histCentFT0CReco", "histCentFT0CReco", kTH1F, {axisCent}); - histomc.add("histCentFT0MReco", "histCentFT0MReco", kTH1F, {axisCent}); - - histomc.add("histdetapttriton", " delta pt vs pt rec for trition detected", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histdetapttritonanti", " delta pt vs pt rec for trition detected", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histDeltaPtVsPtGen", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); histomc.add("histDeltaPtVsPtGenanti", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histDeltaPtVsPtGenHe4", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); - histomc.add("histDeltaPtVsPtGenHe4anti", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); + histomc.add("histDeltaPtVsPtGen", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10}, {1000, -0.5, 0.5, "p_{T}(reco) - p_{T}(gen);p_{T}(reco)"}}); histomc.add("histPIDtrack", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); histomc.add("histPIDtrackanti", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); - histomc.add("histPIDtrackhe4", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); - histomc.add("histPIDtrackantihe4", " delta pt vs pt rec", HistType::kTH2F, {{1000, 0, 10, "p_{T}(reco)"}, {9, -0.5, 8.5, "p_{T}(reco) - p_{T}(gen)"}}); } if (doprocessDCA) { - histomc.add("hSpectraDCA", " ", HistType::kTHnSparseF, {speciesBitAxis, {5, -2.5, 2.5}, axisCent, ptAxis, ptAxis, decayTypeAxis, axisDCA}); // NEW: Add DCAxy vs pT histograms for MC - histomc.add("DCAxy_vs_pT_He3_transport", "DCA_{xy} vs p_{T} for He3 (Transport);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histomc.add("DCAxy_vs_pT_He3_weakdecay", "DCA_{xy} vs p_{T} for He3 (Weak Decay);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histomc.add("DCAxy_vs_pT_He3_total", "DCA_{xy} vs p_{T} for He3 (Total);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); - histomc.add("DCAxy_vs_pT_antiHe3_total", "DCA_{xy} vs p_{T} for anti-He3 (Total);p_{T} (GeV/c);DCA_{xy} (cm)", - {HistType::kTH2F, {ptAxis, axisDCA}}); + histomc.add("DCAxy_vs_pT_transport", "DCA_{xy} vs p_{T} (Transport);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histomc.add("DCAxy_vs_pT_weakdecay", "DCA_{xy} vs p_{T} (Weak Decay);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histomc.add("DCAxy_vs_pT_total", "DCA_{xy} vs p_{T} (Total);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); + histomc.add("DCAxy_vs_pT_anti_total", "DCA_{xy} vs p_{T} for anti (Total);p_{T} (GeV/c);DCA_{xy} (cm)", + {HistType::kTH3F, {ptAxis, axisDCA, axisCent}}); } } //---------------------------------------------------------------------------------------------------------------- @@ -361,39 +340,34 @@ struct NucleitpcPbPb { if (!collPassedEvSel) continue; - if (removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - continue; - histos.fill(HIST("histNev"), 2.5); if (removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) continue; - histos.fill(HIST("histNev"), 3.5); + histos.fill(HIST("histNev"), 2.5); if (requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) continue; - histos.fill(HIST("histNev"), 4.5); + histos.fill(HIST("histNev"), 3.5); if (requireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) continue; - histos.fill(HIST("histNev"), 5.5); + histos.fill(HIST("histNev"), 4.5); if (removeNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) continue; - histos.fill(HIST("histNev"), 6.5); + histos.fill(HIST("histNev"), 5.5); histos.fill(HIST("histEvents"), collision.centFT0C(), occupancy); histos.fill(HIST("histVtxZ"), collision.posZ()); histos.fill(HIST("histCentFT0C"), collision.centFT0C()); histos.fill(HIST("histCentFT0M"), collision.centFT0M()); if (collision.centFT0C() > centcut) continue; - histos.fill(HIST("histNev"), 7.5); + histos.fill(HIST("histNev"), 6.5); histos.fill(HIST("histCentFTOC_cut"), collision.centFT0C()); // new slicing auto tracksInColl = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); - // loop over sliced tracks for (const auto& track : tracksInColl) { if (!track.isPVContributor() && cfgUsePVcontributors) continue; - if (!track.hasTPC()) continue; if (!track.passedITSRefit() && cfgPassedITSRefit) @@ -402,13 +376,13 @@ struct NucleitpcPbPb { continue; if (std::abs(track.eta()) > cfgCutEta && cfgetaRequire) continue; - for (size_t i = 0; i < primaryParticles.size(); i++) { + if (cfgTrackPIDsettings2->get(i, "fillsparsh") != 1) + continue; float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); ptMomn = (i == he3 || i == he4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); - float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) continue; @@ -421,23 +395,19 @@ struct NucleitpcPbPb { } else if (i == he4) { param = (track.sign() > 0) ? 2 : 3; } - if (param >= 0) { a = cfgktrackcorrection->get(param, "a"); b = cfgktrackcorrection->get(param, "b"); c = cfgktrackcorrection->get(param, "c"); } - if (i == he4 && ptMomn < pTcorrectHe4) { ptMomn = ptMomn + a + b * std::exp(c * ptMomn); } - if (i == he3 && ptMomn < pTcorrectHe3) { ptMomn = ptMomn - a + b * ptMomn - c * ptMomn * ptMomn; } } int sign = (track.sign() > 0) ? 1 : ((track.sign() < 0) ? -1 : 0); - if (std::abs(getRapidity(track, i)) > cfgCutRapidity && cfgRapidityRequire) continue; if (track.tpcNClsFound() < cfgTrackPIDsettings->get(i, "minTPCnCls")) @@ -452,7 +422,6 @@ struct NucleitpcPbPb { continue; if (track.itsNCls() < cfgTrackPIDsettings->get(i, "minITSnCls") && cfgminITSnClsRequire) continue; - double cosheta = std::cosh(track.eta()); if ((track.itsNCls() / cosheta) < cfgTrackPIDsettings->get(i, "minITSnClscos") && cfgminITSnClscosRequire) continue; @@ -462,9 +431,7 @@ struct NucleitpcPbPb { continue; if (getMeanItsClsSize(track) < cfgTrackPIDsettings->get(i, "minITSclsSize") && cfgminGetMeanItsClsSizeRequire) continue; - bool insideDCAxy = false; - if (cfgUseNewDCAxyCut) { double sigmaFactor = cfgTrackPIDsettings->get(i, "maxDcaXY"); double sigma_base = (0.0118 * std::exp(-0.6889 * ptMomn) + 0.0017); @@ -513,51 +480,37 @@ struct NucleitpcPbPb { if (i == he4) { tpcNsigmaDe = track.tpcNSigmaDe(); } - if (i == triton || i == he3 || i == he4) { - float rigidity = getRigidity(track); - if (i == triton) { - histos.fill(HIST("TPCsig_triton"), rigidity * track.sign(), track.tpcSignal()); - } else if (i == he3) { - histos.fill(HIST("TPCsig_he3"), rigidity * track.sign(), track.tpcSignal()); - } else if (i == he4) { - histos.fill(HIST("TPCsig_he4"), rigidity * track.sign(), track.tpcSignal()); - } - } - if (i == he3) { - if (track.sign() > 0) { - histos.fill(HIST("DCAxy_vs_pT_He3_data"), ptMomn, track.dcaXY()); - } else if (track.sign() < 0) { - histos.fill(HIST("DCAxy_vs_pT_antiHe3_data"), ptMomn, track.dcaXY()); - } + if (track.sign() > 0) { + histos.fill(HIST("DCAxy_vs_pT_data"), ptMomn, track.dcaXY(), collision.centFT0C()); + } else if (track.sign() < 0) { + histos.fill(HIST("DCAxy_vs_pT_anti_data"), ptMomn, track.dcaXY(), collision.centFT0C()); } - if (cfgFillhspectra && cfgTrackPIDsettings2->get(i, "fillsparsh") == 1) { - if (i != he4) { - histos.fill(HIST("hSpectra"), i, ptMomn, tpcNsigma, sign, collision.centFT0C(), track.dcaZ(), track.dcaXY(), collision.trackOccupancyInTimeRange()); + if (i != he4) { + histos.fill(HIST("hSpectra"), ptMomn, tpcNsigma, sign, collision.centFT0C()); + } else { + if (!track.hasTOF()) { + if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { + histos.fill(HIST("hSpectra"), ptMomn, tpcNsigma, sign, collision.centFT0C()); + } } else { - if (!track.hasTOF()) { - if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { - histos.fill(HIST("hSpectra"), i, ptMomn, tpcNsigma, sign, collision.centFT0C(), track.dcaZ(), track.dcaXY(), collision.trackOccupancyInTimeRange()); - } - } else { - // Has TOF - apply mass cut - float beta = o2::pid::tof::Beta::GetBeta(track); - const float eps = 1e-6f; - if (beta < eps || beta > 1.0f - eps) - continue; - - float charge = 2.f; // he4 has charge 2 - float p = getRigidity(track); - float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); - - // Apply mass cut for he4 (mass^2 around 3.73^2 = 13.9) - if (cfghe3massrejreq && (massTOF * massTOF > cfgminmassrejection && massTOF * massTOF < cfgmaxmassrejection)) { - continue; // Skip if mass cut fails - } - if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { - histos.fill(HIST("hSpectra"), i, ptMomn, tpcNsigma, sign, collision.centFT0C(), track.dcaZ(), track.dcaXY(), collision.trackOccupancyInTimeRange()); - } + // Has TOF - apply mass cut + float beta = o2::pid::tof::Beta::GetBeta(track); + const float eps = 1e-6f; + if (beta < eps || beta > 1.0f - eps) + continue; + + float charge = 2.f; // he4 has charge 2 + float p = getRigidity(track); + float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); + + // Apply mass cut for he4 (mass^2 around 3.73^2 = 13.9) + if (cfghe3massrejreq && (massTOF * massTOF > cfgminmassrejection && massTOF * massTOF < cfgmaxmassrejection)) { + continue; // Skip if mass cut fails + } + if (std::abs(tpcNsigmaDe) > deuteronsigmarejection) { + histos.fill(HIST("hSpectra"), ptMomn, tpcNsigma, sign, collision.centFT0C()); } } } @@ -630,9 +583,6 @@ struct NucleitpcPbPb { if (collision.centFT0C() > centcut) continue; - // Additional cuts - if (removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - continue; if (removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) continue; if (requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) @@ -655,7 +605,7 @@ struct NucleitpcPbPb { // FILL EVENT LOSS AND SIGNAL LOSS: Combined loop per MC collision for (size_t i = 0; i < mcCollInfos.size(); i++) { if (mcCollInfos[i].centrality >= 0) { // Only if we found a matching collision - // Event loss denominator + // Event loss denominator (always filled regardless of fillsparsh) histomc.fill(HIST("hEventLossDenom"), mcCollInfos[i].centrality); // Event loss numerator (if passed selection) @@ -672,29 +622,31 @@ struct NucleitpcPbPb { continue; } - // Signal loss denominator - if (mcParticle.pdgCode() == particlePdgCodes.at(4)) { // He3 - histomc.fill(HIST("hHe3SignalLossDenom"), mcCollInfos[i].centrality); + // Check if this particle type has fillsparsh enabled + int particleType = -1; + for (size_t j = 0; j < primaryParticles.size(); j++) { + if (std::abs(mcParticle.pdgCode()) == std::abs(particlePdgCodes.at(j))) { + particleType = j; + break; + } + } - } else if (mcParticle.pdgCode() == particlePdgCodes.at(5)) { // He4 - histomc.fill(HIST("hHe4SignalLossDenom"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(4)) { // anti-He3 - histomc.fill(HIST("haHe3SignalLossDenom"), mcCollInfos[i].centrality); + // Skip if fillsparsh is not enabled for this particle + if (particleType < 0 || cfgTrackPIDsettings2->get(particleType, "fillsparsh") != 1) + continue; - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(5)) { // He4 - histomc.fill(HIST("haHe4SignalLossDenom"), mcCollInfos[i].centrality); + // Signal loss denominator + if (mcParticle.pdgCode() == particlePdgCodes.at(particleType)) { // particle + histomc.fill(HIST("hSignalLossDenom"), mcCollInfos[i].centrality, mcParticle.pt()); + } else if (mcParticle.pdgCode() == -particlePdgCodes.at(particleType)) { // anti-particle + histomc.fill(HIST("haSignalLossDenom"), mcCollInfos[i].centrality, mcParticle.pt()); } - // Signal loss numerator (if event passed selection) if (mcCollInfos[i].passedEvSel) { - if (mcParticle.pdgCode() == particlePdgCodes.at(4)) { // He3 - histomc.fill(HIST("hHe3SignalLossNumer"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == particlePdgCodes.at(5)) { // He4 - histomc.fill(HIST("hHe4SignalLossNumer"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(4)) { // anti-He3 - histomc.fill(HIST("haHe3SignalLossNumer"), mcCollInfos[i].centrality); - } else if (mcParticle.pdgCode() == -particlePdgCodes.at(5)) { // anti-He4 - histomc.fill(HIST("haHe4SignalLossNumer"), mcCollInfos[i].centrality); + if (mcParticle.pdgCode() == particlePdgCodes.at(particleType)) { // particle + histomc.fill(HIST("hSignalLossNumer"), mcCollInfos[i].centrality, mcParticle.pt()); + } else if (mcParticle.pdgCode() == -particlePdgCodes.at(particleType)) { // anti-particle + histomc.fill(HIST("haSignalLossNumer"), mcCollInfos[i].centrality, mcParticle.pt()); } } } @@ -708,7 +660,6 @@ struct NucleitpcPbPb { continue; float centrality = mcCollInfos[idx].centrality; - // bool passedEvSel = mcCollInfos[idx].passedEvSel; bool passedEvSelVtZ = mcCollInfos[idx].passedEvSelVtZ; // Process generated particles for efficiency denominators @@ -719,10 +670,18 @@ struct NucleitpcPbPb { continue; int pdgCode = mcParticle.pdgCode(); - bool isHe3 = (std::abs(pdgCode) == particlePdgCodes.at(4)); - bool isHe4 = (std::abs(pdgCode) == particlePdgCodes.at(5)); - if (!isHe3 && !isHe4) + // Check which particle type this is + int particleType = -1; + for (size_t j = 0; j < primaryParticles.size(); j++) { + if (std::abs(pdgCode) == std::abs(particlePdgCodes.at(j))) { + particleType = j; + break; + } + } + + // Only process if this particle type has fillsparsh enabled + if (particleType < 0 || cfgTrackPIDsettings2->get(particleType, "fillsparsh") != 1) continue; if (std::abs(mcParticle.eta()) > cfgCutEta && cfgetaRequireMC) @@ -750,24 +709,10 @@ struct NucleitpcPbPb { decayType = 2; continue; } - bool isFromWeakDecay = (decayType == 1); - - if (!mcParticle.isPhysicalPrimary() && !isFromWeakDecay) - // if (!mcParticle.isPhysicalPrimary()) - continue; - - int particleType = -1; - if (std::abs(pdgCode) == particlePdgCodes.at(4)) - particleType = he3; - else if (std::abs(pdgCode) == particlePdgCodes.at(5)) - particleType = he4; - if (particleType >= 0) { - - // Efficiency x Acceptance histograms - if (passedEvSelVtZ) { - histomc.fill(HIST("hDenomEffAcc"), particleType, mcParticle.pt(), mcParticle.y(), centrality, particleAnti, decayType); - } + // Efficiency x Acceptance histograms - Denominator + if (passedEvSelVtZ) { + histomc.fill(HIST("hDenomEffAcc"), mcParticle.pt(), centrality, particleAnti, decayType); } } @@ -781,10 +726,7 @@ struct NucleitpcPbPb { auto bc = collision.bc_as(); initCCDB(bc); - histomc.fill(HIST("histNevReco"), 0.5); histomc.fill(HIST("histVtxZReco"), collision.posZ()); - histomc.fill(HIST("histCentFT0CReco"), collision.centFT0C()); - histomc.fill(HIST("histCentFT0MReco"), collision.centFT0M()); auto tracksInColl = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); @@ -799,11 +741,6 @@ struct NucleitpcPbPb { continue; int pdg = matchedMCParticle.pdgCode(); - bool isHe3 = (std::abs(pdg) == particlePdgCodes.at(4)); - bool isHe4 = (std::abs(pdg) == particlePdgCodes.at(5)); - - if (!isHe3 && !isHe4) - continue; int decayType = 0; @@ -835,13 +772,15 @@ struct NucleitpcPbPb { continue; if (std::abs(track.eta()) > cfgCutEta && cfgetaRequire) continue; - if (!matchedMCParticle.isPhysicalPrimary()) - continue; for (size_t i = 0; i < primaryParticles.size(); i++) { if (std::abs(pdg) != std::abs(particlePdgCodes.at(i))) continue; + // CRITICAL: Only process if fillsparsh is enabled for this particle + if (cfgTrackPIDsettings2->get(i, "fillsparsh") != 1) + continue; + float ptReco; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); @@ -854,9 +793,9 @@ struct NucleitpcPbPb { int param = -1; if (i == he3) { - param = (-particlePdgCodes.at(4) > 0) ? 0 : 1; + param = (pdg > 0) ? 0 : 1; } else if (i == he4) { - param = (-particlePdgCodes.at(4) > 0) ? 2 : 3; + param = (pdg > 0) ? 2 : 3; } if (param >= 0) { @@ -906,31 +845,22 @@ struct NucleitpcPbPb { double sigmaFactor = cfgTrackPIDsettings->get(i, "maxDcaXY"); double sigma_base = (0.0118 * std::exp(-0.6889 * ptReco) + 0.0017); double sigma_new = sigmaFactor * sigma_base; - insideDCAxy = (std::abs(track.dcaXY()) <= sigma_new); } else { - insideDCAxy = - cfgdcaxynopt - ? (std::abs(track.dcaXY()) <= cfgTrackPIDsettings->get(i, "maxDcaXY")) - : (std::abs(track.dcaXY()) <= - (cfgTrackPIDsettings->get(i, "maxDcaXY") * - (0.0105f + 0.0350f / std::pow(ptReco, 1.1f)))); + insideDCAxy = cfgdcaxynopt + ? (std::abs(track.dcaXY()) <= cfgTrackPIDsettings->get(i, "maxDcaXY")) + : (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(ptReco, 1.1f)))); } bool insideDCAz = false; if (cfgUseNewDCAzCut) { - double sigmaFactorZ = cfgTrackPIDsettings->get(i, "maxDcaZ"); - double p0 = 0.1014; double p1 = 1.7512; double p2 = 0.0024; - double sigma_base_z = p0 * std::exp(-p1 * ptReco) + p2; - double sigma_new_z = sigmaFactorZ * sigma_base_z; - insideDCAz = (std::abs(track.dcaZ()) <= sigma_new_z); } else { insideDCAz = (std::abs(track.dcaZ()) <= cfgTrackPIDsettings->get(i, "maxDcaZ")); @@ -944,56 +874,32 @@ struct NucleitpcPbPb { if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) continue; - if (i == he3 || i == he4) { - histomc.fill(HIST("hNumerEffAcc"), i, ptReco, getRapidity(track, i), collision.centFT0C(), particleAnti, decayType); - } + // Efficiency x Acceptance - Numerator + histomc.fill(HIST("hNumerEffAcc"), ptReco, collision.centFT0C(), particleAnti, decayType); - float ptTOF = -1.0; // Default: no TOF + // Sparse histogram + float ptTOF = -1.0; if (track.hasTOF()) { ptTOF = ptReco; } + histomc.fill(HIST("hSpectramc"), particleAnti, collision.centFT0C(), ptReco, ptTOF); - if (cfgTrackPIDsettings2->get(i, "fillsparsh") == 1) { - histomc.fill(HIST("hSpectramc"), i, particleAnti, collision.centFT0C(), - ptReco, ptTOF); - } - + // Basic track histograms histos.fill(HIST("dcaXY"), ptReco, track.dcaXY()); histos.fill(HIST("dcaZ"), ptReco, track.dcaZ()); - histos.fill(HIST("Tpcsignal"), getRigidity(track) * track.sign(), track.tpcSignal()); - // Fill the requested histograms + // Delta Pt histograms float ptGen = matchedMCParticle.pt(); float deltaPt = ptReco - ptGen; - if (pdg == -particlePdgCodes.at(4)) { + if (pdg == -particlePdgCodes.at(i)) { // Anti-particle histomc.fill(HIST("histDeltaPtVsPtGenanti"), ptReco, deltaPt); histomc.fill(HIST("histPIDtrackanti"), ptReco, track.pidForTracking()); - - int pidGuess = track.pidForTracking(); - int antitriton = 6; - if (pidGuess == antitriton) { - histomc.fill(HIST("histdetapttritonanti"), ptReco, deltaPt); - } } - if (pdg == particlePdgCodes.at(4)) { + if (pdg == particlePdgCodes.at(i)) { // Particle histomc.fill(HIST("histDeltaPtVsPtGen"), ptReco, deltaPt); histomc.fill(HIST("histPIDtrack"), ptReco, track.pidForTracking()); - - int pidGuess = track.pidForTracking(); - int antitriton = 6; - if (pidGuess == antitriton) { - histomc.fill(HIST("histdetapttriton"), ptReco, deltaPt); - } - } - if (pdg == -particlePdgCodes.at(5)) { - histomc.fill(HIST("histDeltaPtVsPtGenHe4anti"), ptReco, deltaPt); - histomc.fill(HIST("histPIDtrackantihe4"), ptReco, track.pidForTracking()); - } - if (pdg == particlePdgCodes.at(5)) { - histomc.fill(HIST("histDeltaPtVsPtGenHe4"), ptReco, deltaPt); - histomc.fill(HIST("histPIDtrackhe4"), ptReco, track.pidForTracking()); } } } @@ -1004,9 +910,6 @@ struct NucleitpcPbPb { } PROCESS_SWITCH(NucleitpcPbPb, processMC, "MC reco+gen analysis with efficiency corrections", false); //=-=-=-==-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - //---------------------------------------------------------------------------------------------------------------- - // MC particles - DCA secondary fraction - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= void processDCA(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, @@ -1033,9 +936,6 @@ struct NucleitpcPbPb { if (collision.centFT0C() > centcut) continue; - // Additional cuts - if (removeITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - continue; if (removeNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) continue; if (requireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) @@ -1085,11 +985,6 @@ struct NucleitpcPbPb { continue; int pdg = matchedMCParticle.pdgCode(); - bool isHe3 = (std::abs(pdg) == particlePdgCodes.at(4)); - bool isHe4 = (std::abs(pdg) == particlePdgCodes.at(5)); - - if (!isHe3 && !isHe4) - continue; if (!track.isPVContributor() && cfgUsePVcontributors) continue; @@ -1107,14 +1002,15 @@ struct NucleitpcPbPb { if (std::abs(pdg) != std::abs(particlePdgCodes.at(i))) continue; + if (cfgTrackPIDsettings2->get(i, "fillsparsh") != 1) + continue; + float ptReco; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); ptReco = (std::abs(pdg) == particlePdgCodes.at(4) || std::abs(pdg) == particlePdgCodes.at(5)) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); - int particleAnti = (pdg > 0) ? 0 : 1; - double a = 0, b = 0, c = 0; int param = -1; @@ -1198,67 +1094,23 @@ struct NucleitpcPbPb { decayType = 2; } - if (i == he3) { - if (pdg == particlePdgCodes.at(4)) { // He3 - histomc.fill(HIST("DCAxy_vs_pT_He3_total"), ptReco, track.dcaXY()); - if (decayType == 2) { // Transport/Material - histomc.fill(HIST("DCAxy_vs_pT_He3_transport"), ptReco, track.dcaXY()); - } else if (decayType == 1) { // Weak decay (including HF) - histomc.fill(HIST("DCAxy_vs_pT_He3_weakdecay"), ptReco, track.dcaXY()); - } - } else if (pdg == -particlePdgCodes.at(4)) { // anti-He3 - histomc.fill(HIST("DCAxy_vs_pT_antiHe3_total"), ptReco, track.dcaXY()); - } - } - - bool insideDCAxy = false; - - if (cfgUseNewDCAxyCut) { - double sigmaFactor = cfgTrackPIDsettings->get(i, "maxDcaXY"); - double sigma_base = (0.0118 * std::exp(-0.6889 * ptReco) + 0.0017); - double sigma_new = sigmaFactor * sigma_base; - - insideDCAxy = (std::abs(track.dcaXY()) <= sigma_new); - } else { - insideDCAxy = - cfgdcaxynopt - ? (std::abs(track.dcaXY()) <= cfgTrackPIDsettings->get(i, "maxDcaXY")) - : (std::abs(track.dcaXY()) <= - (cfgTrackPIDsettings->get(i, "maxDcaXY") * - (0.0105f + 0.0350f / std::pow(ptReco, 1.1f)))); - } - - bool insideDCAz = false; - - if (cfgUseNewDCAzCut) { - - double sigmaFactorZ = cfgTrackPIDsettings->get(i, "maxDcaZ"); - - double p0 = 0.1014; - double p1 = 1.7512; - double p2 = 0.0024; - - double sigma_base_z = p0 * std::exp(-p1 * ptReco) + p2; + float ptDCA; - double sigma_new_z = sigmaFactorZ * sigma_base_z; - - insideDCAz = (std::abs(track.dcaZ()) <= sigma_new_z); + if (i == he3 || i == he4) { + ptDCA = ptReco; } else { - insideDCAz = (std::abs(track.dcaZ()) <= cfgTrackPIDsettings->get(i, "maxDcaZ")); + ptDCA = 2 * ptReco; } - if ((!insideDCAxy || !insideDCAz)) { - continue; - } - - float ptTOF = -1.0; // Default: no TOF - if (track.hasTOF()) { - ptTOF = ptReco; - } - - if (cfgTrackPIDsettings2->get(i, "fillsparsh") == 1) { - histomc.fill(HIST("hSpectraDCA"), i, particleAnti, collision.centFT0C(), - ptReco, ptTOF, decayType, track.dcaXY()); + if (pdg == particlePdgCodes.at(i)) { // He3 + histomc.fill(HIST("DCAxy_vs_pT_total"), ptDCA, track.dcaXY(), collision.centFT0C()); + if (decayType == 2) { // Transport/Material + histomc.fill(HIST("DCAxy_vs_pT_transport"), ptDCA, track.dcaXY(), collision.centFT0C()); + } else if (decayType == 1) { // Weak decay (including HF) + histomc.fill(HIST("DCAxy_vs_pT_weakdecay"), ptDCA, track.dcaXY(), collision.centFT0C()); + } + } else if (pdg == -particlePdgCodes.at(i)) { // anti-He3 + histomc.fill(HIST("DCAxy_vs_pT_anti_total"), ptDCA, track.dcaXY(), collision.centFT0C()); } } } @@ -1391,7 +1243,6 @@ struct NucleitpcPbPb { return; } - // Get pT similar to fillhmass float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); diff --git a/PWGLF/Tasks/Nuspex/piKpRAA.cxx b/PWGLF/Tasks/Nuspex/piKpRAA.cxx index b6328ecc744..fdddc29f9e1 100644 --- a/PWGLF/Tasks/Nuspex/piKpRAA.cxx +++ b/PWGLF/Tasks/Nuspex/piKpRAA.cxx @@ -26,7 +26,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/MathConstants.h" @@ -66,6 +67,7 @@ using namespace o2::framework; using namespace o2::aod::evsel; using namespace o2::constants::math; using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; using ColEvSels = soa::Join; using BCsRun3 = soa::Join; @@ -75,30 +77,27 @@ using ColEvSelsMC = soa::Join; using TracksMC = soa::Join; -// using SimTracks = soa::Join; static constexpr int kNEtaHists{8}; -std::array, kNEtaHists> dEdxPiV0{}; -std::array, kNEtaHists> dEdxPrV0{}; -std::array, kNEtaHists> dEdxElV0{}; -std::array, kNEtaHists> dEdxPiTOF{}; +std::array, kNEtaHists> dEdxPiV0{}; +std::array, kNEtaHists> dEdxPrV0{}; +std::array, kNEtaHists> dEdxElV0{}; +std::array, kNEtaHists> dEdxPiMC{}; +std::array, kNEtaHists> dEdxMuMC{}; +std::array, kNEtaHists> dEdxPiMCLoSel{}; +std::array, kNEtaHists> dEdxMuMCLoSel{}; std::array, kNEtaHists> dEdx{}; -std::array, kNEtaHists> nClVsdEdxPiV0{}; -std::array, kNEtaHists> nClVsdEdxElV0{}; -std::array, kNEtaHists> nClVsdEdxPrV0{}; std::array, kNEtaHists> pTVsP{}; std::array, kNEtaHists> nClVsP{}; std::array, kNEtaHists> nClVsPElV0{}; std::array, kNEtaHists> nClVsPPiV0{}; std::array, kNEtaHists> nClVsPPrV0{}; +std::array, kNEtaHists> nClVsPPiMC{}; std::array, kNEtaHists> nClVsPp{}; std::array, kNEtaHists> nClVsPpElV0{}; std::array, kNEtaHists> nClVsPpPiV0{}; std::array, kNEtaHists> nClVsPpPrV0{}; -std::array, kNEtaHists> nClVsdEdxpPiV0{}; -std::array, kNEtaHists> nClVsdEdxpElV0{}; -std::array, kNEtaHists> nClVsdEdxpPrV0{}; struct PiKpRAA { @@ -128,25 +127,16 @@ struct PiKpRAA { static constexpr float kLowEta[kNEtaHists] = {-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6}; static constexpr float kHighEta[kNEtaHists] = {-0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}; - // static constexpr float kLowEta[kNEtaHists] = {0.0, 0.2, 0.4, 0.6}; - // static constexpr float kHighEta[kNEtaHists] = {0.2, 0.4, 0.6, 0.8}; static constexpr float DefaultLifetimeCuts[1][2] = {{30., 20.}}; Configurable> lifetimecut{"lifetimecut", {DefaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0S"}}, "lifetimecut"}; struct : ConfigurableGroup { - Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + Configurable minEta{"minEta", -0.8, "Daughter minimum-eta selection"}; + Configurable maxEta{"maxEta", +0.8, "Daughter maximum-eta selection"}; + Configurable minPt{"minPt", 0.1, "minimum pt of the tracks"}; + Configurable maxPt{"maxPt", 10000000000.0, "maximum pt of the tracks"}; - // Selection criteria: acceptance - Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; - Configurable minEtaDaughter{"minEtaDaughter", -0.8, "Daughter minimum-eta selection"}; - Configurable maxEtaDaughter{"maxEtaDaughter", +0.8, "Daughter maximum-eta selection"}; - Configurable minPt{"minPt", 0.15, "minimum pt of the tracks"}; - Configurable maxPt{"maxPt", 20.0, "maximum pt of the tracks"}; - Configurable minPtDaughter{"minPtDaughter", 0.15, "minimum pt of the tracks"}; - Configurable maxPtDaughter{"maxPtDaughter", 20.0, "maximum pt of the tracks"}; - Configurable useNclsPID{"useNclsPID", true, "Use Ncl for PID?"}; - Configurable minNcl{"minNcl", 135, "minimum found Ncl in TPC"}; Configurable minNCrossedRows{"minNCrossedRows", 70, "minimum number of crossed rows"}; Configurable minNCrossedRowsOverFindableCls{"minNCrossedRowsOverFindableCls", 0.8, "min N crossed rows over findable Cls"}; Configurable maxChi2ClsTPC{"maxChi2ClsTPC", 4.0, "Max chi2 per Cls TPC"}; @@ -156,15 +146,38 @@ struct PiKpRAA { Configurable tpcRefit{"tpcRefit", true, "Require TPC refit"}; Configurable chi2Golden{"chi2Golden", true, "Require Chi2 golde selection"}; Configurable its1HitIB{"its1HitIB", true, "Require one hit in the ITS IB"}; - Configurable requireITShit{"requireITShit", true, "Apply requirement of one hit in the ITS IB?"}; + + // Phi cut + Configurable applyPhiCut{"applyPhiCut", false, "Apply geometrical cut?"}; + Configurable applyEtaCal{"applyEtaCal", false, "Apply eta calibration?"}; + Configurable applyPlateauSel{"applyPlateauSel", false, "Apply eta calibration?"}; + Configurable usePinPhiSelection{"usePinPhiSelection", true, "Uses Phi selection as a function of P or Pt?"}; + Configurable applyNclSel{"applyNclSel", false, "Apply Min. found Ncl in TPC?"}; + } trackSelections; + + struct : ConfigurableGroup { + Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + Configurable useOfficialV0sSelOfDaughters{"useOfficialV0sSelOfDaughters", true, "Use the same track selection for daughters as the V0s analysis in OO"}; + Configurable useTPCNsigma{"useTPCNsigma", false, "Include TPC Nsigma selection on decay products"}; + + // Selection criteria: acceptance + Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; + Configurable useNclsPID{"useNclsPID", true, "Use Ncl for PID?"}; + Configurable minNcl{"minNcl", 135, "minimum found Ncl in TPC"}; // Standard 5 topological criteria Configurable v0cospa{"v0cospa", 0.995, "min V0 CosPA"}; Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; Configurable dcanegtopv{"dcanegtopv", .1, "min DCA Neg To PV (cm)"}; Configurable dcapostopv{"dcapostopv", .1, "min DCA Pos To PV (cm)"}; + Configurable dcaProtonFromLambda{"dcaProtonFromLambda", .05, "min DCA Proton (from Lambda) To PV (cm)"}; + Configurable dcaPionFromLambda{"dcaPionFromLambda", .2, "min DCA Pion (from Lambda) To PV (cm)"}; + Configurable dcaElectronFromGamma{"dcaElectronFromGamma", .1, "min DCA Electron (from Gamma conversion) To PV (cm)"}; + Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; Configurable v0radiusMax{"v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + Configurable lifeTimeCutK0s{"lifeTimeCutK0s", 20.0, "lifetime cut K0s (cm)"}; + Configurable lifeTimeCutLambda{"lifeTimeCutLambda", 30.0, "lifetime cut Lambda and AntiLambda (cm)"}; // Additional selection on the AP plot (exclusive for K0Short) // original equation: lArmPt*5>TMath::Abs(lArmAlpha) @@ -173,23 +186,14 @@ struct PiKpRAA { Configurable qTSel{"qTSel", 0.01f, "Armenteros qT select (Gammas)"}; // Selection + Configurable applyInvMassSel{"applyInvMassSel", true, "Select V0s close to the Inv. mass value"}; Configurable selElecFromGammas{"selElecFromGammas", true, "track selection for electrons"}; - Configurable applyInvMassSel{"applyInvMassSel", false, "Select V0s close to the Inv. mass value"}; Configurable dMassSel{"dMassSel", 0.01f, "Invariant mass selection"}; Configurable dMassSelG{"dMassSelG", 0.1f, "Inv mass selection gammas"}; // PID (TPC/TOF) Configurable dEdxPlateauSel{"dEdxPlateauSel", 50, "dEdx selection for electrons"}; - Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; - Configurable maxExpTOFPi{"maxExpTOFPi", 0.00005, "Maximum beta TOF selection"}; - Configurable applyTPCTOFCombinedCut{"applyTPCTOFCombinedCut", false, " Apply geometrical cut ? "}; - - // Phi cut - Configurable applyPhiCut{"applyPhiCut", false, "Apply geometrical cut?"}; - Configurable applyEtaCal{"applyEtaCal", false, "Apply eta calibration?"}; - Configurable applyPlateauSel{"applyPlateauSel", false, "Apply eta calibration?"}; - Configurable usePinPhiSelection{"usePinPhiSelection", true, "Uses Phi selection as a function of P or Pt?"}; - Configurable applyNclSel{"applyNclSel", false, "Apply Min. found Ncl in TPC?"}; + Configurable pidNsigmaCut{"pidNsigmaCut", 3.0, "pidNsigmaCut"}; } v0Selections; // Configurables Event Selection @@ -203,15 +207,20 @@ struct PiKpRAA { Configurable isNoCollInTimeRangeNarrow{"isNoCollInTimeRangeNarrow", false, "use isNoCollInTimeRangeNarrow?"}; Configurable isOccupancyCut{"isOccupancyCut", true, "Occupancy cut?"}; Configurable isCentSel{"isCentSel", true, "Centrality selection?"}; + Configurable selHasBC{"selHasBC", true, "Has BC?"}; Configurable selHasFT0{"selHasFT0", true, "Has FT0?"}; Configurable isT0Ccent{"isT0Ccent", true, "Use T0C-based centrality?"}; + + Configurable useSel8{"useSel8", false, "Use sel8?"}; + Configurable selTriggerTVX{"selTriggerTVX", true, "selTriggerTVX?"}; + Configurable selNoITSROFrameBorder{"selNoITSROFrameBorder", true, "selNoITSROFrameBorder?"}; + Configurable selNoTimeFrameBorder{"selNoTimeFrameBorder", true, "selNoTimeFrameBorder?"}; Configurable isZvtxPosSel{"isZvtxPosSel", true, "Zvtx position selection?"}; Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; Configurable selINELgt0{"selINELgt0", true, "Select INEL > 0?"}; Configurable isApplyFT0CbasedOccupancy{"isApplyFT0CbasedOccupancy", false, "T0C Occu cut"}; Configurable applyNchSel{"applyNchSel", false, "Use mid-rapidity-based Nch selection"}; - Configurable skipRecoColGTOne{"skipRecoColGTOne", true, "Remove collisions if reconstructed more than once"}; // Event selection Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; @@ -220,6 +229,7 @@ struct PiKpRAA { Configurable minOccCut{"minOccCut", 0., "min Occu cut"}; Configurable maxOccCut{"maxOccCut", 500., "max Occu cut"}; Configurable nSigmaNchCut{"nSigmaNchCut", 3., "nSigma Nch selection"}; + Configurable tpcNchAcceptance{"tpcNchAcceptance", 0.5, "Eta window to measure Nch MC for Nch vs Cent distribution"}; ConfigurableAxis binsPtPhiCut{"binsPtPhiCut", {VARIABLE_WIDTH, 0.0, 0.6, 0.8, 1.0, 1.4, 1.8, 2.2, 2.6, 3.0, 3.5, 4.0, 5.0, 7.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 45.0, 50.0}, "pT"}; ConfigurableAxis binsPtV0s{"binsPtV0s", {VARIABLE_WIDTH, 0, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.5, 3.0, 3.5, 4, 5, 7, 9, 12, 15, 20}, "pT"}; @@ -252,12 +262,26 @@ struct PiKpRAA { Configurable pathPhiCutHigh{"pathPhiCutHigh", "Users/o/omvazque/PhiCut/OO/Global/High", "base path to the ccdb object"}; Configurable pathPhiCutLow{"pathPhiCutLow", "Users/o/omvazque/PhiCut/OO/Global/Low", "base path to the ccdb object"}; 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 rctLabel{"rctLabel", "CBT_hadronPID", "RCT selection flag (CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo)"}; + Configurable rctCheckZDC{"rctCheckZDC", false, "RCT flag to check whether the ZDC is present or not"}; + Configurable rctTreatLimitedAcceptanceAsBad{"rctTreatLimitedAcceptanceAsBad", false, "RCT flag to reject events with limited acceptance for selected detectors"}; + Configurable requireGoodRct{"requireGoodRct", true, "RCT flag to reject events with limited acceptance for selected detectors"}; + Configurable requireBCRct{"requireBCRct", true, "RCT flag to reject events with limited acceptance for selected detectors"}; + + // RCT Checker instance + RCTFlagsChecker rctChecker; enum EvCutLabel { All = 1, + HasBC, + HasFT0, SelEigth, - NoSameBunchPileup, + SelTriggerTVX, + SelNoITSROFrameBorder, + SelNoTimeFrameBorder, + VtxZ, IsGoodZvtxFT0vsPV, + NoSameBunchPileup, NoCollInTimeRangeStrict, NoCollInTimeRangeStandard, NoCollInRofStrict, @@ -265,9 +289,7 @@ struct PiKpRAA { NoHighMultCollInPrevRof, NoCollInTimeRangeNarrow, OccuCut, - HasFT0, Centrality, - VtxZ, NchSel, INELgt0 }; @@ -317,31 +339,48 @@ struct PiKpRAA { } etaCal; TrackSelection trkSelGlobalOpenDCAxy; - // TrackSelection trkSelDaugthers; TrackSelection trkSelGlobal; - // TrackSelection trkSelDaugthersV0s() { - // TrackSelection selectedTracks; - // selectedTracks.SetEtaRange(-0.8f, 0.8f); - // selectedTracks.SetMinNCrossedRowsTPC(70); - // return selectedTracks; - // } TrackSelection trkSelOpenDCAxy() { TrackSelection selectedTracks; - selectedTracks.SetTrackType(o2::aod::track::TrackTypeEnum::Track); // Run 2 track asked by default - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer - selectedTracks.SetMaxChi2PerClusterITS(36.f); - // selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(2.f); + selectedTracks.SetTrackType(o2::aod::track::TrackTypeEnum::Track); // Run 3 track asked by default + selectedTracks.SetPtRange(trackSelections.minPt, trackSelections.maxPt); + selectedTracks.SetEtaRange(trackSelections.minEta, trackSelections.maxEta); + selectedTracks.SetRequireITSRefit(trackSelections.itsRefit); + selectedTracks.SetRequireTPCRefit(trackSelections.tpcRefit); + selectedTracks.SetRequireGoldenChi2(trackSelections.chi2Golden); + selectedTracks.SetMinNCrossedRowsTPC(trackSelections.minNCrossedRows); + selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(trackSelections.minNCrossedRowsOverFindableCls); + selectedTracks.SetMaxChi2PerClusterTPC(trackSelections.maxChi2ClsTPC); + if (trackSelections.its1HitIB) + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); // one hit in any layer of the inner barrel + if (!trackSelections.its1HitIB) + selectedTracks.SetRequireHitsInITSLayers(7, {0, 1, 2, 3, 4, 5, 6}); // one hit in every of the seven layers + selectedTracks.SetMaxChi2PerClusterITS(trackSelections.maxChi2ClsITS); + selectedTracks.SetMaxDcaZ(trackSelections.maxDCAZ); + return selectedTracks; + } + + TrackSelection trkSelGlb() + { + TrackSelection selectedTracks; + selectedTracks.SetTrackType(o2::aod::track::TrackTypeEnum::Track); // Run 3 track asked by default + selectedTracks.SetPtRange(trackSelections.minPt, trackSelections.maxPt); + selectedTracks.SetEtaRange(trackSelections.minEta, trackSelections.maxEta); + selectedTracks.SetRequireITSRefit(trackSelections.itsRefit); + selectedTracks.SetRequireTPCRefit(trackSelections.tpcRefit); + selectedTracks.SetRequireGoldenChi2(trackSelections.chi2Golden); + selectedTracks.SetMinNCrossedRowsTPC(trackSelections.minNCrossedRows); + selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(trackSelections.minNCrossedRowsOverFindableCls); + selectedTracks.SetMaxChi2PerClusterTPC(trackSelections.maxChi2ClsTPC); + if (trackSelections.its1HitIB) + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); // one hit in any layer of the inner barrel + if (!trackSelections.its1HitIB) + selectedTracks.SetRequireHitsInITSLayers(7, {0, 1, 2, 3, 4, 5, 6}); // one hit in every of the seven layers + selectedTracks.SetMaxChi2PerClusterITS(trackSelections.maxChi2ClsITS); + selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + selectedTracks.SetMaxDcaZ(trackSelections.maxDCAZ); return selectedTracks; } @@ -349,16 +388,21 @@ struct PiKpRAA { int currentRunNumberPhiSel; void init(InitContext const&) { + + // Initialize the rct checker + if (requireGoodRct) { + rctChecker.init(rctLabel.value, rctCheckZDC.value, rctTreatLimitedAcceptanceAsBad.value); + } + currentRunNumberNchSel = -1; currentRunNumberPhiSel = -1; trkSelGlobalOpenDCAxy = trkSelOpenDCAxy(); - // trkSelDaugthers = trkSelDaugthersV0s(); - trkSelGlobal = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + trkSelGlobal = trkSelGlb(); // define axes you want to use - const std::string titlePorPt{v0Selections.usePinPhiSelection ? "#it{p} (GeV/#it{c})" : "#it{p}_{T} (GeV/#it{c})"}; + const std::string titlePorPt{trackSelections.usePinPhiSelection ? "#it{p} (GeV/#it{c})" : "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisZpos{binsZpos, "Vtx_{z} (cm)"}; - const AxisSpec axisEvent{17, 0.5, 17.5, ""}; + const AxisSpec axisEvent{22, 0.5, 22.5, ""}; const AxisSpec axisNcl{161, -0.5, 160.5, "#it{N}_{cl} TPC"}; const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisPtV0s{binsPtV0s, "#it{p}_{T} (GeV/#it{c})"}; @@ -369,39 +413,63 @@ struct PiKpRAA { const char* latexEta[kNEtaHists] = {"-0.8<#eta<-0.6", "-0.6<#eta<-0.4", "-0.4<#eta<-0.2", "-0.2<#eta<0", "0<#eta<0.2", "0.2<#eta<0.4", "0.4<#eta<0.6", "0.6<#eta<0.8"}; registry.add("EventCounter", ";;Events", kTH1F, {axisEvent}); + registry.add("HasBCVsFT0VsTVXVsEvSel", "Alls=1 | BC=2 | FT0=3 | TVX=4 | EvSel=5;;", kTH1F, {{5, 0.5, 5.5}}); registry.add("zPos", "With Event Selection;;Entries;", kTH1F, {axisZpos}); registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); - registry.add("T0CcentVsFoundFT0", ";Found(=1.5) NOT Found(=0.5);", kTH2F, {{{axisCent}, {2, 0, 2}}}); + registry.add("RCTSel", "Event accepted if flag=false: All=1 | RTC sel=2;;;", kTH1F, {{2, 0.5, 2.5}}); + registry.add("T0CcentVsRCTSel", "Event accepted if flag=false;;RCT Status;", kTH2F, {{{axisCent}, {9, 0.5, 9.5}}}); + registry.add("T0CcentVsFoundFT0", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{axisCent}, {2, 0, 2}}}); + registry.add("T0CcentVsBCVsFT0VsTVXVsEvSel", "All=1 | BC=2 | FT0=3 | TVX=4 | EvSel=5;;Status;", kTH2F, {{axisCent}, {5, 0.5, 5.5}}); registry.add("NchVsCent", "Measured Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Nch", kTH2F, {{axisCent, {nBinsNch, minNch, maxNch}}}); registry.add("NclVsEtaPID", ";#eta;Ncl used for PID", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); registry.add("NclVsEtaPIDp", ";#eta;#LTNcl#GT used for PID", kTProfile, {axisEta}); + registry.add("NclVsEta", ";#eta;Found Ncl TPC", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); + registry.add("NclVsEtap", ";#eta;Found #LTNcl#GT TPC", kTProfile, {axisEta}); + registry.add("NclVsPt", ";#eta;Found Ncl TPC", kTH2F, {{{axisPtNcl}, {161, -0.5, 160.5}}}); + registry.add("NclVsPtPID", ";#eta;PID Ncl", kTH2F, {{{axisPtNcl}, {161, -0.5, 160.5}}}); registry.add("dcaVsPtPi", "Primary pions;#it{p}_{T} (GeV/#it{c});DCA_{xy} (cm);Centrality Perc.;", kTH3F, {axisPt, axisDCAxy, axisCent}); registry.add("dcaVsPtPr", "Primary protons;#it{p}_{T} (GeV/#it{c});DCA_{xy} (cm);Centrality Perc.;", kTH3F, {axisPt, axisDCAxy, axisCent}); + registry.add("TrackDaughterCounter", "itsrefit, and itshit NOT appplied for electrons sel.;Trk Sel.; Entries;", kTH1F, {{14, 0.5, 14.5}}); auto hstat = registry.get(HIST("EventCounter")); auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "SelEigth"); - x->SetBinLabel(3, "NoSameBunchPileup"); - x->SetBinLabel(4, "GoodZvtxFT0vsPV"); - x->SetBinLabel(5, "NoCollInTimeRangeStrict"); - x->SetBinLabel(6, "NoCollInTimeRangeStandard"); - x->SetBinLabel(7, "NoCollInRofStrict"); - x->SetBinLabel(8, "NoCollInRofStandard"); - x->SetBinLabel(9, "NoHighMultCollInPrevRof"); - x->SetBinLabel(10, "NoCollInTimeRangeNarrow"); - x->SetBinLabel(11, "Occupancy Cut"); - x->SetBinLabel(12, "Has FT0?"); - x->SetBinLabel(13, "Cent. Sel."); - x->SetBinLabel(14, "VtxZ Sel."); - x->SetBinLabel(15, "Nch Sel."); - x->SetBinLabel(16, "INEL > 0"); + x->SetBinLabel(2, "Has BC?"); + x->SetBinLabel(3, "Has FT0?"); + x->SetBinLabel(4, "SelEigth"); + x->SetBinLabel(5, "SelTriggerTVX"); + x->SetBinLabel(6, "SelNoITSROFrameBorder"); + x->SetBinLabel(7, "SelNoTimeFrameBorder"); + x->SetBinLabel(8, "VtxZ Sel."); + x->SetBinLabel(9, "GoodZvtxFT0vsPV"); + x->SetBinLabel(10, "NoSameBunchPileup"); + x->SetBinLabel(11, "NoCollInTimeRangeStrict"); + x->SetBinLabel(12, "NoCollInTimeRangeStandard"); + x->SetBinLabel(13, "NoCollInRofStrict"); + x->SetBinLabel(14, "NoCollInRofStandard"); + x->SetBinLabel(15, "NoHighMultCollInPrevRof"); + x->SetBinLabel(16, "NoCollInTimeRangeNarrow"); + x->SetBinLabel(17, "Occupancy Cut"); + x->SetBinLabel(18, "Cent. Sel."); + x->SetBinLabel(19, "Nch Sel."); + x->SetBinLabel(20, "INEL > 0"); + + auto hrct = registry.get(HIST("T0CcentVsRCTSel")); + auto* y = hrct->GetYaxis(); + y->SetBinLabel(1, "All"); + y->SetBinLabel(2, "kFT0Bad"); + y->SetBinLabel(3, "kITSBad"); + y->SetBinLabel(4, "kITSLimAccMCRepr"); + y->SetBinLabel(5, "kTOFBad"); + y->SetBinLabel(6, "kTOFLimAccMCRepr"); + y->SetBinLabel(7, "kTPCBadTracking"); + y->SetBinLabel(8, "kTPCBadPID"); + y->SetBinLabel(9, "kTPCLimAccMCRepr"); if (doprocessCalibrationAndV0s) { registry.add("NchVsNPV", ";Nch; NPV;", kTH2F, {{{nBinsNPV, minNpv, maxNpv}, {nBinsNch, minNch, maxNch}}}); registry.add("ExcludedEvtVsNch", ";Nch;Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); registry.add("ExcludedEvtVsNPV", ";NPV;Entries;", kTH1F, {{nBinsNPV, minNpv, maxNpv}}); - registry.add("TrackDaughterCounter", "itsrefit, and itshit NOT appplied for electrons sel.;Trk Sel.; Entries;", kTH1F, {{14, 0.5, 14.5}}); registry.add("V0sCounter", ";V0 type; Entries;", kTH1F, {{4, 0.5, 4.5}}); registry.add("dcaDauVsPt", ";V0 #it{p}_{T} (GeV/#it{c});DCA_{xy} (cm) daughters;", kTH2F, {axisPt, axisDCAxy}); registry.add("nSigPiFromK0s", ";#it{n#sigma};;", kTH2F, {axisPtV0s, axisNsigmaTPC}); @@ -422,14 +490,10 @@ struct PiKpRAA { registry.add("MassALVsPt", ";;Inv. Mass (GeV/#it{c}^{2});", kTH2F, {axisPtV0s, axisLambdaMass}); registry.add("MassGVsPt", ";;Inv. Mass (GeV/#it{c}^{2});", kTH2F, {axisPtV0s, axisGammaMass}); - // registry.add("NclFindable", ";;Findable Ncl TPC", kTH2F, {axisPtNcl, axisNcl}); - // registry.add("NclFindablep", ";;Findable #LTNcl#GT TPC", kTProfile, {axisPtNcl}); registry.add("NclVsPhipBeforeCut", Form("Found #LTNcl#GT TPC;%s (GeV/#it{c});#varphi", titlePorPt.data()), kTProfile2D, {{{axisXPhiCut}, {350, 0.0, 0.35}}}); registry.add("NclVsPhipBeforeCutPID", Form("#LTNcl#GT used for PID;%s (GeV/#it{c});#varphi", titlePorPt.data()), kTProfile2D, {{{axisXPhiCut}, {350, 0.0, 0.35}}}); registry.add("NclVsPhipAfterCut", Form("Found #LTNcl#GT TPC;%s (GeV/#it{c});#varphi", titlePorPt.data()), kTProfile2D, {{{axisXPhiCut}, {350, 0.0, 0.35}}}); registry.add("NclVsPhipAfterCutPID", Form("#LTNcl#GT used for PID;%s (GeV/#it{c});#varphi", titlePorPt.data()), kTProfile2D, {{{axisXPhiCut}, {350, 0.0, 0.35}}}); - registry.add("NclVsEta", ";#eta;Found Ncl TPC", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); - registry.add("NclVsEtap", ";#eta;Found #LTNcl#GT TPC", kTProfile, {axisEta}); registry.add("NclVsEtaPiMIP", "MIP #pi^{+} + #pi^{-} (0.4 < #it{p} < 0.6 GeV/#it{c}, 40 < dE/dx < 60);#eta;Ncl TPC", kTH2F, {{{axisEta}, {161, -0.5, 160.5}}}); registry.add("NclVsEtaPiMIPp", "MIP #pi^{+} + #pi^{-} (0.4 < #it{p} < 0.6 GeV/#it{c}, 40 < dE/dx < 60);#eta;#LTNcl#GT TPC", kTProfile, {axisEta}); @@ -448,12 +512,10 @@ struct PiKpRAA { registry.add("EtaVsYPrAL", ";#eta;#it{y};", kTH2F, {axisEta, axisY}); registry.add("EtaVsYG", ";#eta;#it{y};", kTH2F, {axisEta, axisY}); - // registry.add("TOFExpPi2TOF", ";Momentum (GeV/#it{c});t^{#pi}_{Exp}/t_{TOF}", kTH2F, {{{axisPtV0s}, {100, 0.2, 1.2}}}); - registry.add("DCAxyDCAzPiK0s", ";DCA_{xy} (cm); DCA_{z} (cm)", kTH2F, {axisDCAxy, axisDCAxy}); - registry.add("DCAxyDCAzPrL", ";DCA_{xy} (cm); DCA_{z} (cm)", kTH2F, {axisDCAxy, axisDCAxy}); - registry.add("DCAxyDCAzPrAL", ";DCA_{xy} (cm); DCA_{z} (cm)", kTH2F, {axisDCAxy, axisDCAxy}); + registry.add("DCAxyPtPiK0s", ";DCA_{xy} (cm); p_{T} (GeV/c)", kTH2F, {axisDCAxy, axisPt}); + registry.add("DCAxyPtPrL", ";DCA_{xy} (cm); p_{T} (GeV/c)", kTH2F, {axisDCAxy, axisPt}); + registry.add("DCAxyPtPrAL", ";DCA_{xy} (cm); p_{T} (GeV/c)", kTH2F, {axisDCAxy, axisPt}); - // registry.add("betaVsMomentum", ";Momentum (GeV/#it{c}); #beta", kTH2F, {{{axisPtV0s}, {500, 0, 1.2}}}); registry.add("dEdxVsEtaPiMIP", "MIP #pi^{+} + #pi^{-} (0.4 < #it{p} < 0.6 GeV/#it{c});#eta; dE/dx;", kTH2F, {{{axisEta}, {100, 0, 100}}}); registry.add("dEdxVsEtaPiMIPp", "MIP #pi^{+} + #pi^{-} (0.4 < #it{p} < 0.6 GeV/#it{c});#eta; #LTdE/dx#GT", kTProfile, {axisEta}); registry.add("dEdxVsEtaElMIP", "MIP e^{+} + e^{-} (0.3 < #it{p} < 0.45 GeV/#it{c});#eta; dE/dx;", kTH2F, {{{axisEta}, {100, 0, 100}}}); @@ -468,13 +530,9 @@ struct PiKpRAA { for (int i = 0; i < kNEtaHists; ++i) { dEdx[i] = registry.add(Form("dEdx_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPt, axisdEdx, axisCent}); pTVsP[i] = registry.add(Form("pTVsP_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});#it{p}_{T} (GeV/#it{c});", latexEta[i]), kTH2F, {axisPt, axisPt}); - dEdxPiV0[i] = registry.add(Form("dEdxPiV0_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - dEdxPrV0[i] = registry.add(Form("dEdxPrV0_%s", endingEta[i]), Form("p + #bar{p}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - dEdxElV0[i] = registry.add(Form("dEdxElV0_%s", endingEta[i]), Form("e^{+} + e^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - dEdxPiTOF[i] = registry.add(Form("dEdxPiTOF_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH3F, {axisPtV0s, axisdEdx, axisCent}); - nClVsdEdxPiV0[i] = registry.add(Form("NclVsdEdxPiV0_%s", endingEta[i]), Form("%s;#it{N}_{cl} used for PID;dE/dx;", latexEta[i]), kTH2F, {axisNcl, axisdEdx}); - nClVsdEdxElV0[i] = registry.add(Form("NclVsdEdxElV0_%s", endingEta[i]), Form("%s;#it{N}_{cl} used for PID;dE/dx;", latexEta[i]), kTH2F, {axisNcl, axisdEdx}); - nClVsdEdxPrV0[i] = registry.add(Form("NclVsdEdxPrV0_%s", endingEta[i]), Form("%s;#it{N}_{cl} used for PID;dE/dx;", latexEta[i]), kTH2F, {axisNcl, axisdEdx}); + dEdxPiV0[i] = registry.add(Form("dEdxPiV0_%s", endingEta[i]), Form("#pi^{+} + #pi^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxPrV0[i] = registry.add(Form("dEdxPrV0_%s", endingEta[i]), Form("p + #bar{p}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxElV0[i] = registry.add(Form("dEdxElV0_%s", endingEta[i]), Form("e^{+} + e^{-}, %s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); nClVsP[i] = registry.add(Form("NclVsPPrimaries_%s", endingEta[i]), Form("%s;;Ncl TPC", latexEta[i]), kTH2F, {axisPtNcl, axisNcl}); nClVsPElV0[i] = registry.add(Form("NclVsPElV0_%s", endingEta[i]), Form("%s;;Ncl TPC", latexEta[i]), kTH2F, {axisPtNcl, axisNcl}); nClVsPPiV0[i] = registry.add(Form("NclVsPPiV0_%s", endingEta[i]), Form("%s;;Ncl TPC", latexEta[i]), kTH2F, {axisPtNcl, axisNcl}); @@ -483,9 +541,6 @@ struct PiKpRAA { nClVsPpElV0[i] = registry.add(Form("NclVsPElV0p_%s", endingEta[i]), Form("%s;;#LT#it{N}_{cl}#GT TPC", latexEta[i]), kTProfile, {axisPtNcl}); nClVsPpPiV0[i] = registry.add(Form("NclVsPPiV0p_%s", endingEta[i]), Form("%s;;#LT#it{N}_{cl}#GT TPC", latexEta[i]), kTProfile, {axisPtNcl}); nClVsPpPrV0[i] = registry.add(Form("NclVsPPrV0p_%s", endingEta[i]), Form("%s;;#LT#it{N}_{cl}#GT TPC", latexEta[i]), kTProfile, {axisPtNcl}); - nClVsdEdxpElV0[i] = registry.add(Form("NclVsdEdxElV0p_%s", endingEta[i]), Form("%s;;#LTd#it{E}/d#it{x}#GT", latexEta[i]), kTProfile, {axisNcl}); - nClVsdEdxpPiV0[i] = registry.add(Form("NclVsdEdxPiV0p_%s", endingEta[i]), Form("%s;;#LTd#it{E}/d#it{x}#GT", latexEta[i]), kTProfile, {axisNcl}); - nClVsdEdxpPrV0[i] = registry.add(Form("NclVsdEdxPrV0p_%s", endingEta[i]), Form("%s;;#LTd#it{E}/d#it{x}#GT", latexEta[i]), kTProfile, {axisNcl}); } auto htrkSel = registry.get(HIST("TrackDaughterCounter")); @@ -504,7 +559,7 @@ struct PiKpRAA { xtrkSel->SetBinLabel(12, "Passed all"); } - if (doprocessMC || doprocessSim) { + if (doprocessSim) { registry.add("zPosMC", "Generated Events With at least One Rec. Collision + Sel. criteria;;Entries;", kTH1F, {axisZpos}); registry.add("dcaVsPtPiDec", "Secondary pions from decays;#it{p}_{T} (GeV/#it{c});DCA_{xy} (cm);Centrality Perc.;", kTH3F, {axisPt, axisDCAxy, axisCent}); registry.add("dcaVsPtPrDec", "Secondary protons from decays;#it{p}_{T} (GeV/#it{c});DCA_{xy} (cm);Centrality Perc.;", kTH3F, {axisPt, axisDCAxy, axisCent}); @@ -513,19 +568,6 @@ struct PiKpRAA { registry.add("NclVsPhip", Form("#LTNcl#GT used for PID;%s (GeV/#it{c});#varphi", titlePorPt.data()), kTProfile2D, {{{axisXPhiCut}, {350, 0.0, 0.35}}}); } - if (doprocessMC) { - - registry.add("EventCounterMC", "Event counter", kTH1F, {axisEvent}); - - registry.add("PtPiVsCent", "", kTH2F, {axisPt, axisCent}); - registry.add("PtKaVsCent", "", kTH2F, {axisPt, axisCent}); - registry.add("PtPrVsCent", "", kTH2F, {axisPt, axisCent}); - - registry.add("PtPiVsCentMC", "", kTH2F, {axisPt, axisCent}); - registry.add("PtKaVsCentMC", "", kTH2F, {axisPt, axisCent}); - registry.add("PtPrVsCentMC", "", kTH2F, {axisPt, axisCent}); - } - if (doprocessSim) { // MC events passing the TVX requirement @@ -541,16 +583,20 @@ struct PiKpRAA { registry.add("PtKaVsCent_WithRecoEvt", "Generated Events With at least One Rec. Collision + Sel. criteria;;;", kTH2F, {axisPt, axisCent}); registry.add("PtPrVsCent_WithRecoEvt", "Generated Events With at least One Rec. Collision + Sel. criteria;;;", kTH2F, {axisPt, axisCent}); + registry.add("PtGenPiVsCent_WithRecoEvt", "Generated Events With at least One Rec. Collision + Sel. criteria;;;", kTH2F, {axisPt, axisCent}); + registry.add("PtGenKaVsCent_WithRecoEvt", "Generated Events With at least One Rec. Collision + Sel. criteria;;;", kTH2F, {axisPt, axisCent}); + registry.add("PtGenPrVsCent_WithRecoEvt", "Generated Events With at least One Rec. Collision + Sel. criteria;;;", kTH2F, {axisPt, axisCent}); + // Needed to calculate the denominator of the Acceptance X Efficiency registry.add("PtPiVsCentMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;;", kTH2F, {axisPt, axisCent}); registry.add("PtKaVsCentMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;;", kTH2F, {axisPt, axisCent}); registry.add("PtPrVsCentMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;;", kTH2F, {axisPt, axisCent}); // Needed for the Gen. Nch to Centrality conversion - registry.add("NchMCVsCent", "Generated Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Gen. Nch", kTH2F, {{axisCent, {nBinsNch, minNch, maxNch}}}); + registry.add("NchMCVsCent", "Generated Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Gen. Nch MC (|#eta|<0.8)", kTH2F, {{axisCent, {nBinsNch, minNch, maxNch}}}); // Needed to measure Event Loss - registry.add("NchMC_WithRecoEvt", "Generated Nch of Evts With at least one Rec. Coll. + Sel. criteria;Gen. Nch MC;Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); + registry.add("NchMC_WithRecoEvt", "Generated Nch of Evts With at least one Rec. Coll. + Sel. criteria;Gen. Nch MC (|#eta|<0.8);Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); registry.add("NchMC_AllGen", "Generated Nch of All Gen. Evts.;Gen. Nch;Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); // Needed to measure Event Splitting @@ -559,42 +605,51 @@ struct PiKpRAA { registry.add("Centrality_AllRecoEvt", "Generated Events Irrespective of the number of times it was reconstructed + Evt. Selections;;Entries", kTH1F, {axisCent}); // Needed to calculate the numerator of the Signal Loss correction - registry.add("PtPiVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("PtKaVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("PtPrVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPiVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtKaVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPrVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + + registry.add("PtPiVsNchMC_WithRecoEvt_has_FT0_and_TVX", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtKaVsNchMC_WithRecoEvt_has_FT0_and_TVX", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPrVsNchMC_WithRecoEvt_has_FT0_and_TVX", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); // Needed to calculate the denominator of the Signal Loss correction - registry.add("PtPiVsNchMC_AllGen", "All Generated Events;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("PtKaVsNchMC_AllGen", "All Generated Events;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("PtPrVsNchMC_AllGen", "All Generated Events;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPiVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtKaVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("PtPrVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("MCclosure_PtMCPiVsNchMC", "All Generated Events 4 MC closure;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("MCclosure_PtMCKaVsNchMC", "All Generated Events 4 MC closure;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("MCclosure_PtMCPrVsNchMC", "All Generated Events 4 MC closure;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("MCclosure_PtMCPiVsNchMC", "All Generated Events 4 MC closure;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("MCclosure_PtMCKaVsNchMC", "All Generated Events 4 MC closure;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("MCclosure_PtMCPrVsNchMC", "All Generated Events 4 MC closure;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("MCclosure_PtPiVsNchMC", "Gen Evts With at least one Rec. Coll. + Sel. criteria 4 MC closure;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("MCclosure_PtKaVsNchMC", "Gen Evts With at least one Rec. Coll. + Sel. criteria 4 MC closure;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); - registry.add("MCclosure_PtPrVsNchMC", "Gen Evts With at least one Rec. Coll. + Sel. criteria 4 MC closure;;Gen. Nch;", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("MCclosure_PtPiVsNchMC", "Gen Evts With at least one Rec. Coll. + Sel. criteria 4 MC closure;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("MCclosure_PtKaVsNchMC", "Gen Evts With at least one Rec. Coll. + Sel. criteria 4 MC closure;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + registry.add("MCclosure_PtPrVsNchMC", "Gen Evts With at least one Rec. Coll. + Sel. criteria 4 MC closure;;Gen. Nch (|#eta|<0.8);", kTH2F, {{axisPt, {nBinsNch, minNch, maxNch}}}); + + for (int i = 0; i < kNEtaHists; ++i) { + nClVsPPiMC[i] = registry.add(Form("NclVsPPi_%s", endingEta[i]), Form("%s;;Ncl", latexEta[i]), kTH2F, {axisPtNcl, axisNcl}); + dEdxPiMC[i] = registry.add(Form("dEdxPi_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxMuMC[i] = registry.add(Form("dEdxMu_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxPiMCLoSel[i] = registry.add(Form("dEdxPiLooseSel_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + dEdxMuMCLoSel[i] = registry.add(Form("dEdxMuLooseSel_%s", endingEta[i]), Form("%s;Momentum (GeV/#it{c});dE/dx;", latexEta[i]), kTH2F, {axisPtV0s, axisdEdx}); + } } + LOG(info) << "\trequireGoodRct=" << requireGoodRct.value; LOG(info) << "\tccdbNoLaterThan=" << ccdbNoLaterThan.value; LOG(info) << "\tapplyNchSel=" << applyNchSel.value; LOG(info) << "\tselINELgt0=" << selINELgt0.value; LOG(info) << "\tv0TypeSelection=" << static_cast(v0Selections.v0TypeSelection); LOG(info) << "\tselElecFromGammas=" << v0Selections.selElecFromGammas; - LOG(info) << "\trequireITShit=" << v0Selections.requireITShit; - LOG(info) << "\tminPt=" << v0Selections.minPt; - LOG(info) << "\tmaxPt=" << v0Selections.maxPt; - LOG(info) << "\tminPtDaughter=" << v0Selections.minPtDaughter; - LOG(info) << "\tmaxPtDaughter=" << v0Selections.maxPtDaughter; + LOG(info) << "\tapplyInvMassSel=" << v0Selections.applyInvMassSel; + LOG(info) << "\tminPt=" << trackSelections.minPt; + LOG(info) << "\tmaxPt=" << trackSelections.maxPt; LOG(info) << "\tuseNclsPID=" << v0Selections.useNclsPID; LOG(info) << "\tqTSel=" << v0Selections.qTSel; LOG(info) << "\tarmAlphaSel=" << v0Selections.armAlphaSel; - LOG(info) << "\tapplyTPCTOFCombinedCut=" << v0Selections.applyTPCTOFCombinedCut; - LOG(info) << "\tapplyInvMassSel=" << v0Selections.applyInvMassSel; - LOG(info) << "\tapplyNclSel=" << v0Selections.applyNclSel; - LOG(info) << "\tapplyPhiCut=" << v0Selections.applyPhiCut; - LOG(info) << "\tusePinPhiSelection=" << v0Selections.usePinPhiSelection; + LOG(info) << "\tapplyNclSel=" << trackSelections.applyNclSel; + LOG(info) << "\tapplyPhiCut=" << trackSelections.applyPhiCut; + LOG(info) << "\tusePinPhiSelection=" << trackSelections.usePinPhiSelection; LOG(info) << "\ttitlePorPt=" << titlePorPt; LOG(info) << "\tcurrentRunNumberNchSel=" << currentRunNumberNchSel; LOG(info) << "\tcurrentRunNumberPhiSel=" << currentRunNumberPhiSel; @@ -611,27 +666,27 @@ struct PiKpRAA { LOG(info) << "\tpathSigmaNch=" << pathSigmaNch.value; } - if (v0Selections.applyPhiCut) { + if (trackSelections.applyPhiCut) { LOG(info) << "\tLoading Phi cut!"; LOG(info) << "\tpathPhiCutLow=" << pathPhiCutLow.value; LOG(info) << "\tpathPhiCutHigh=" << pathPhiCutHigh.value; } - if (v0Selections.applyEtaCal) { + if (trackSelections.applyEtaCal) { LOG(info) << "\tLoading Eta Cal!"; LOG(info) << "\tpathEtaCal=" << pathEtaCal.value; loadEtaCalibration(); LOG(info) << "\tisMIPCalLoaded=" << etaCal.isMIPCalLoaded; } - if (v0Selections.applyPlateauSel) { + if (trackSelections.applyPlateauSel) { LOG(info) << "\tLoading Eta Plateau Cal!"; LOG(info) << "\tpathEtaCalPlateau=" << pathEtaCalPlateau.value; loadEtaPlateauCalibration(); LOG(info) << "\tisCalPlateauLoaded=" << etaCal.isCalPlateauLoaded; } - if (v0Selections.applyNclSel) + if (trackSelections.applyNclSel) LOG(info) << "\t minNcl=" << v0Selections.minNcl; } @@ -640,9 +695,6 @@ struct PiKpRAA { // LOG(info) << " Collisions size: " << collisions.size() << " // Table's size: " << collisions.tableSize() << "\n"; // LOG(info) << "Run number: " << foundBC.runNumber() << "\n"; - if (!isEventSelected(collision)) { - return; - } const auto& foundBC = collision.foundBC_as(); const uint64_t timeStamp{foundBC.timestamp()}; @@ -650,6 +702,54 @@ struct PiKpRAA { const double nPV{collision.multNTracksPVeta1() / 1.}; const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; + // Apply RCT selection? + if (requireGoodRct) { + // Checks if collisions passes RCT selection + const bool isFT0Bad{requireBCRct ? foundBC.rct_bit(kFT0Bad) : collision.rct_bit(kFT0Bad)}; + const bool isITSBad{requireBCRct ? foundBC.rct_bit(kITSBad) : collision.rct_bit(kITSBad)}; + const bool isITSLimAcc{requireBCRct ? foundBC.rct_bit(kITSLimAccMCRepr) : collision.rct_bit(kITSLimAccMCRepr)}; + const bool isTOFBad{requireBCRct ? foundBC.rct_bit(kTOFBad) : collision.rct_bit(kTOFBad)}; + const bool isTOFLimAcc{requireBCRct ? foundBC.rct_bit(kTOFLimAccMCRepr) : collision.rct_bit(kTOFLimAccMCRepr)}; + const bool isTPCTrackingBad{requireBCRct ? foundBC.rct_bit(kTPCBadTracking) : collision.rct_bit(kTPCBadTracking)}; + const bool isTPCPIDBad{requireBCRct ? foundBC.rct_bit(kTPCBadPID) : collision.rct_bit(kTPCBadPID)}; + const bool isTPCLimAcc{requireBCRct ? foundBC.rct_bit(kTPCLimAccMCRepr) : collision.rct_bit(kTPCLimAccMCRepr)}; + + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 1.0); + if (!isFT0Bad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 2.0); + if (!isITSBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 3.0); + if (!isITSLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 4.0); + if (!isTOFBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 5.0); + if (!isTOFLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 6.0); + if (!isTPCTrackingBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 7.0); + if (!isTPCPIDBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 8.0); + if (!isTPCLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 9.0); + + registry.fill(HIST("RCTSel"), 1.0); + if (!rctChecker(collision)) + return; + + registry.fill(HIST("RCTSel"), 2.0); + } + + if (!isEventSelected(collision)) + return; + + //--------------------------- + // Control histogram + //--------------------------- + if (selHasFT0 && !collision.has_foundFT0()) { + registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 0.5); + } + registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); + if (applyNchSel) { const int nextRunNumber{foundBC.runNumber()}; if (currentRunNumberNchSel != nextRunNumber) { @@ -705,7 +805,7 @@ struct PiKpRAA { registry.fill(HIST("zPos"), collision.posZ()); registry.fill(HIST("NchVsCent"), centrality, nch); - if (v0Selections.applyPhiCut) { + if (trackSelections.applyPhiCut) { const int nextRunNumber{foundBC.runNumber()}; if (currentRunNumberPhiSel != nextRunNumber) { loadPhiCutSelections(timeStamp); @@ -725,28 +825,28 @@ struct PiKpRAA { if (!trkSelGlobalOpenDCAxy.IsSelected(track)) continue; - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) + if (track.pt() < trackSelections.minPt || track.pt() > trackSelections.maxPt) continue; - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) + if (track.eta() < trackSelections.minEta || track.eta() > trackSelections.maxEta) continue; const float momentum{track.p()}; const float pt{track.pt()}; const float phi{track.phi()}; - const float pOrPt{v0Selections.usePinPhiSelection ? momentum : pt}; + const float pOrPt{trackSelections.usePinPhiSelection ? momentum : pt}; const int16_t nclFound{track.tpcNClsFound()}; const int16_t nclPID{track.tpcNClsPID()}; const int16_t ncl{v0Selections.useNclsPID ? nclPID : nclFound}; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) + if (trackSelections.applyNclSel && ncl < v0Selections.minNcl) continue; float phiPrime{phi}; const int charge{track.sign()}; phiPrimeFunc(phiPrime, magField, charge); - if (v0Selections.applyPhiCut) { + if (trackSelections.applyPhiCut) { if (!passesPhiSelection(pOrPt, phiPrime)) continue; } @@ -769,10 +869,10 @@ struct PiKpRAA { if (!trkSelGlobal.IsSelected(track)) continue; - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) + if (track.pt() < trackSelections.minPt || track.pt() > trackSelections.maxPt) continue; - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) + if (track.eta() < trackSelections.minEta || track.eta() > trackSelections.maxEta) continue; const float momentum{track.p()}; @@ -781,12 +881,12 @@ struct PiKpRAA { const float eta{track.eta()}; float dedx{track.tpcSignal()}; const int charge{track.sign()}; - const float pOrPt{v0Selections.usePinPhiSelection ? momentum : pt}; + const float pOrPt{trackSelections.usePinPhiSelection ? momentum : pt}; const int16_t nclFound{track.tpcNClsFound()}; const int16_t nclPID{track.tpcNClsPID()}; const int16_t ncl{v0Selections.useNclsPID ? nclPID : nclFound}; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) + if (trackSelections.applyNclSel && ncl < v0Selections.minNcl) continue; float phiPrime{phi}; @@ -794,12 +894,12 @@ struct PiKpRAA { registry.fill(HIST("NclVsPhipBeforeCut"), pOrPt, phiPrime, nclFound); registry.fill(HIST("NclVsPhipBeforeCutPID"), pOrPt, phiPrime, nclPID); - if (v0Selections.applyPhiCut) { + if (trackSelections.applyPhiCut) { if (!passesPhiSelection(pOrPt, phiPrime)) continue; } - if (v0Selections.applyEtaCal && etaCal.isMIPCalLoaded) { + if (trackSelections.applyEtaCal && etaCal.isMIPCalLoaded) { const double dedxCal{etaCal.pEtaCal->GetBinContent(etaCal.pEtaCal->FindBin(eta))}; if (dedxCal > kMindEdxMIP && dedxCal < kMaxdEdxMIP) dedx *= (50.0 / dedxCal); @@ -840,27 +940,10 @@ struct PiKpRAA { registry.fill(HIST("NclVsEtap"), eta, nclFound); registry.fill(HIST("NclVsEtaPID"), eta, nclPID); registry.fill(HIST("NclVsEtaPIDp"), eta, nclPID); - // registry.fill(HIST("NclFindable"), pOrPt, track.tpcNClsFindable()); - // registry.fill(HIST("NclFindablep"), pOrPt, track.tpcNClsFindable()); registry.fill(HIST("NclVsPhipAfterCut"), pOrPt, phiPrime, nclFound); registry.fill(HIST("NclVsPhipAfterCutPID"), pOrPt, phiPrime, nclPID); - - if (track.hasTOF() && track.goodTOFMatch()) { - const float tTOF{track.tofSignal()}; - const float trkLength{track.length()}; - const float tExpPiTOF{track.tofExpSignalPi(tTOF)}; - // const float tExpElTOF{track.tofExpSignalEl(tTOF)}; - - if (trkLength > kZero && tTOF > kZero) { - // registry.fill(HIST("betaVsMomentum"), momentum, track.beta()); - // registry.fill(HIST("TOFExpPi2TOF"), momentum, tExpPiTOF / tTOF); - // registry.fill(HIST("TOFExpEl2TOF"), momentum, tExpElTOF / tTOF); - - if (std::abs((tExpPiTOF / tTOF) - kOne) < v0Selections.maxExpTOFPi) { - dEdxPiTOF[indexEta]->Fill(momentum, dedx, centrality); - } - } - } + registry.fill(HIST("NclVsPt"), pt, nclFound); + registry.fill(HIST("NclVsPtPID"), pt, nclPID); } for (const auto& v0 : v0s) { @@ -893,15 +976,15 @@ struct PiKpRAA { phiPrimeFunc(posTrackPhiPrime, magField, posTrackCharge); phiPrimeFunc(negTrackPhiPrime, magField, negTrackCharge); - const float posPorPt{v0Selections.usePinPhiSelection ? posTrkP : posTrkPt}; - const float negPorPt{v0Selections.usePinPhiSelection ? negTrkP : negTrkPt}; + const float posPorPt{trackSelections.usePinPhiSelection ? posTrkP : posTrkPt}; + const float negPorPt{trackSelections.usePinPhiSelection ? negTrkP : negTrkPt}; // Skip v0s with like-sig daughters if (posTrack.sign() == negTrack.sign()) continue; // Passes Geometrical (Phi) cut? - if (v0Selections.applyPhiCut) { + if (trackSelections.applyPhiCut) { if (!(passesPhiSelection(posPorPt, posTrackPhiPrime) && passesPhiSelection(negPorPt, negTrackPhiPrime))) continue; } @@ -910,10 +993,12 @@ struct PiKpRAA { if (!(passesTrackSelectionDaughters(posTrack) && passesTrackSelectionDaughters(negTrack))) continue; - if (v0Selections.applyNclSel && !(posNcl >= v0Selections.minNcl && negNcl >= v0Selections.minNcl)) + // Selection based on Ncl for PID + if (trackSelections.applyNclSel && !(posNcl >= v0Selections.minNcl && negNcl >= v0Selections.minNcl)) continue; - if (v0Selections.applyEtaCal && etaCal.isMIPCalLoaded) { + // Eta calibration positive-charge track + if (trackSelections.applyEtaCal && etaCal.isMIPCalLoaded) { const double dedxCal{etaCal.pEtaCal->GetBinContent(etaCal.pEtaCal->FindBin(posTrkEta))}; if (dedxCal > kMindEdxMIP && dedxCal < kMaxdEdxMIP) posTrkdEdx *= (50.0 / dedxCal); @@ -921,7 +1006,8 @@ struct PiKpRAA { continue; } - if (v0Selections.applyEtaCal && etaCal.isMIPCalLoaded) { + // Eta calibration negative-charge track + if (trackSelections.applyEtaCal && etaCal.isMIPCalLoaded) { const double dedxCal{etaCal.pEtaCal->GetBinContent(etaCal.pEtaCal->FindBin(negTrkEta))}; if (dedxCal > kMindEdxMIP && dedxCal < kMaxdEdxMIP) negTrkdEdx *= (50.0 / dedxCal); @@ -944,11 +1030,6 @@ struct PiKpRAA { if (!passesTopoSel) continue; - const double dMassK0s{std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short)}; - const double dMassL{std::abs(v0.mLambda() - o2::constants::physics::MassLambda0)}; - const double dMassAL{std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0)}; - const double dMassG{std::abs(v0.mGamma() - o2::constants::physics::MassGamma)}; - int posIndexEta{-999}; int negIndexEta{-999}; for (int i = 0; i < kNEtaHists; ++i) { @@ -975,154 +1056,109 @@ struct PiKpRAA { registry.fill(HIST("dcaDauVsPt"), v0.pt(), v0.dcapostopv()); registry.fill(HIST("dcaDauVsPt"), v0.pt(), v0.dcanegtopv()); - bool isMassK0s{true}; - bool isMassL{true}; - bool isMassAL{true}; - bool isMassG{true}; - if (v0Selections.applyInvMassSel) { // apply Inv. Mass selection? - if (!(dMassK0s < v0Selections.dMassSel && dMassL > v0Selections.dMassSel && dMassAL > v0Selections.dMassSel && dMassG > v0Selections.dMassSelG)) - isMassK0s = false; - - if (!(dMassL < v0Selections.dMassSel && dMassK0s > v0Selections.dMassSel && dMassG > v0Selections.dMassSelG)) - isMassL = false; - - if (!(dMassAL < v0Selections.dMassSel && dMassK0s > v0Selections.dMassSel && dMassG > v0Selections.dMassSelG)) - isMassAL = false; - - if (!(dMassK0s > v0Selections.dMassSel && dMassL > v0Selections.dMassSel && dMassAL > v0Selections.dMassSel && dMassG < v0Selections.dMassSel)) - isMassG = false; - } - - if (passesK0Selection(collision, v0)) { // nSigma TPC and y cuts - if (isMassK0s) { // apply Inv. Mass selection? - registry.fill(HIST("ArmK0NOSel"), alpha, qT); - if (v0Selections.armPodCut * qT > std::abs(alpha)) { // Armenters selection - registry.fill(HIST("V0sCounter"), V0sCounter::K0s); - registry.fill(HIST("ArmK0"), alpha, qT); - registry.fill(HIST("MassK0sVsPt"), v0.pt(), v0.mK0Short()); - registry.fill(HIST("nSigPiFromK0s"), posTrkPt, posTrack.tpcNSigmaPi()); - registry.fill(HIST("nSigPiFromK0s"), negTrkPt, negTrack.tpcNSigmaPi()); - registry.fill(HIST("NclVsEtaPiV0"), posTrkEta, posNcl); - registry.fill(HIST("NclVsEtaPiV0p"), posTrkEta, posNcl); - registry.fill(HIST("NclVsEtaPiV0"), negTrkEta, negNcl); - registry.fill(HIST("NclVsEtaPiV0p"), negTrkEta, negNcl); - nClVsPPiV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsPpPiV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsPPiV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsdEdxPiV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - nClVsdEdxpPiV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - nClVsdEdxPiV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - nClVsdEdxpPiV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - nClVsPpPiV0[negIndexEta]->Fill(negPorPt, negNcl); - dEdxPiV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); - dEdxPiV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); - registry.fill(HIST("DCAxyDCAzPiK0s"), posTrack.dcaXY(), posTrack.dcaZ()); - - if (posTrkP > kMinPMIP && posTrkP < kMaxPMIP && posTrkdEdx > kMindEdxMIP && posTrkdEdx < kMaxdEdxMIP) { - registry.fill(HIST("dEdxVsEtaPiMIPV0"), posTrkEta, posTrkdEdx); - registry.fill(HIST("dEdxVsEtaPiMIPV0p"), posTrkEta, posTrkdEdx); - } - if (negTrkP > kMinPMIP && negTrkP < kMaxPMIP && negTrkdEdx > kMindEdxMIP && negTrkdEdx < kMaxdEdxMIP) { - registry.fill(HIST("dEdxVsEtaPiMIPV0"), negTrkEta, negTrkdEdx); - registry.fill(HIST("dEdxVsEtaPiMIPV0p"), negTrkEta, negTrkdEdx); - } + if (passesK0Selection(collision, v0)) { + registry.fill(HIST("ArmK0NOSel"), alpha, qT); + if (v0Selections.armPodCut * qT > std::abs(alpha)) { // Armenters selection + registry.fill(HIST("V0sCounter"), V0sCounter::K0s); + registry.fill(HIST("ArmK0"), alpha, qT); + registry.fill(HIST("MassK0sVsPt"), v0.pt(), v0.mK0Short()); + registry.fill(HIST("nSigPiFromK0s"), posTrkPt, posTrack.tpcNSigmaPi()); + registry.fill(HIST("nSigPiFromK0s"), negTrkPt, negTrack.tpcNSigmaPi()); + registry.fill(HIST("NclVsEtaPiV0"), posTrkEta, posNcl); + registry.fill(HIST("NclVsEtaPiV0p"), posTrkEta, posNcl); + registry.fill(HIST("NclVsEtaPiV0"), negTrkEta, negNcl); + registry.fill(HIST("NclVsEtaPiV0p"), negTrkEta, negNcl); + nClVsPPiV0[posIndexEta]->Fill(posPorPt, posNcl); + nClVsPpPiV0[posIndexEta]->Fill(posPorPt, posNcl); + nClVsPPiV0[negIndexEta]->Fill(negPorPt, negNcl); + nClVsPpPiV0[negIndexEta]->Fill(negPorPt, negNcl); + dEdxPiV0[posIndexEta]->Fill(posTrkP, posTrkdEdx); + dEdxPiV0[negIndexEta]->Fill(negTrkP, negTrkdEdx); + + if (posTrkP > kMinPMIP && posTrkP < kMaxPMIP && posTrkdEdx > kMindEdxMIP && posTrkdEdx < kMaxdEdxMIP) { + registry.fill(HIST("dEdxVsEtaPiMIPV0"), posTrkEta, posTrkdEdx); + registry.fill(HIST("dEdxVsEtaPiMIPV0p"), posTrkEta, posTrkdEdx); + } + if (negTrkP > kMinPMIP && negTrkP < kMaxPMIP && negTrkdEdx > kMindEdxMIP && negTrkdEdx < kMaxdEdxMIP) { + registry.fill(HIST("dEdxVsEtaPiMIPV0"), negTrkEta, negTrkdEdx); + registry.fill(HIST("dEdxVsEtaPiMIPV0p"), negTrkEta, negTrkdEdx); } } } if (passesLambdaSelection(collision, v0)) { - if (isMassL) { - registry.fill(HIST("V0sCounter"), V0sCounter::Lambda); - registry.fill(HIST("ArmL"), alpha, qT); - registry.fill(HIST("MassLVsPt"), v0.pt(), v0.mLambda()); - if (posTrackCharge > kZero) { - registry.fill(HIST("nSigPrFromL"), posTrkPt, posTrack.tpcNSigmaPr()); - registry.fill(HIST("NclVsEtaPrV0"), posTrkEta, posNcl); - registry.fill(HIST("NclVsEtaPrV0p"), posTrkEta, posNcl); - nClVsPPrV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsPpPrV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsdEdxPrV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - nClVsdEdxpPrV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - dEdxPrV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); - registry.fill(HIST("DCAxyDCAzPrL"), posTrack.dcaXY(), posTrack.dcaZ()); - } - if (negTrackCharge < kZero) { - registry.fill(HIST("nSigPiFromL"), negTrkPt, negTrack.tpcNSigmaPi()); - registry.fill(HIST("NclVsEtaPiV0"), negTrkEta, negNcl); - registry.fill(HIST("NclVsEtaPiV0p"), negTrkEta, negNcl); - nClVsPPiV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsPpPiV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsdEdxPiV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - nClVsdEdxpPiV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - dEdxPiV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); - } + registry.fill(HIST("V0sCounter"), V0sCounter::Lambda); + registry.fill(HIST("ArmL"), alpha, qT); + registry.fill(HIST("MassLVsPt"), v0.pt(), v0.mLambda()); + if (posTrackCharge > kZero) { + registry.fill(HIST("nSigPrFromL"), posTrkPt, posTrack.tpcNSigmaPr()); + registry.fill(HIST("NclVsEtaPrV0"), posTrkEta, posNcl); + registry.fill(HIST("NclVsEtaPrV0p"), posTrkEta, posNcl); + nClVsPPrV0[posIndexEta]->Fill(posPorPt, posNcl); + nClVsPpPrV0[posIndexEta]->Fill(posPorPt, posNcl); + dEdxPrV0[posIndexEta]->Fill(posTrkP, posTrkdEdx); + } + if (negTrackCharge < kZero) { + registry.fill(HIST("nSigPiFromL"), negTrkPt, negTrack.tpcNSigmaPi()); + // registry.fill(HIST("NclVsEtaPiV0"), negTrkEta, negNcl); + // registry.fill(HIST("NclVsEtaPiV0p"), negTrkEta, negNcl); + // nClVsPPiV0[negIndexEta]->Fill(negPorPt, negNcl); + // nClVsPpPiV0[negIndexEta]->Fill(negPorPt, negNcl); + // dEdxPiV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); } } if (passesAntiLambdaSelection(collision, v0)) { - if (isMassAL) { - registry.fill(HIST("V0sCounter"), V0sCounter::AntiLambda); - registry.fill(HIST("ArmAL"), alpha, qT); - registry.fill(HIST("MassALVsPt"), v0.pt(), v0.mAntiLambda()); - if (posTrackCharge > kZero) { - registry.fill(HIST("nSigPiFromAL"), posTrkPt, posTrack.tpcNSigmaPi()); - registry.fill(HIST("NclVsEtaPiV0"), posTrkEta, posNcl); - registry.fill(HIST("NclVsEtaPiV0p"), posTrkEta, posNcl); - nClVsPPiV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsPpPiV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsdEdxPiV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - nClVsdEdxpPiV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - dEdxPiV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); - } - if (negTrackCharge < kZero) { - registry.fill(HIST("nSigPrFromAL"), negTrkPt, negTrack.tpcNSigmaPr()); - registry.fill(HIST("NclVsEtaPrV0"), negTrkEta, negNcl); - registry.fill(HIST("NclVsEtaPrV0p"), negTrkEta, negNcl); - nClVsPPrV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsPpPrV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsdEdxPrV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - nClVsdEdxpPrV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - registry.fill(HIST("DCAxyDCAzPrAL"), negTrack.dcaXY(), negTrack.dcaZ()); - dEdxPrV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); - } + registry.fill(HIST("V0sCounter"), V0sCounter::AntiLambda); + registry.fill(HIST("ArmAL"), alpha, qT); + registry.fill(HIST("MassALVsPt"), v0.pt(), v0.mAntiLambda()); + if (posTrackCharge > kZero) { + registry.fill(HIST("nSigPiFromAL"), posTrkPt, posTrack.tpcNSigmaPi()); + // registry.fill(HIST("NclVsEtaPiV0"), posTrkEta, posNcl); + // registry.fill(HIST("NclVsEtaPiV0p"), posTrkEta, posNcl); + // nClVsPPiV0[posIndexEta]->Fill(posPorPt, posNcl); + // nClVsPpPiV0[posIndexEta]->Fill(posPorPt, posNcl); + // dEdxPiV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); + } + if (negTrackCharge < kZero) { + registry.fill(HIST("nSigPrFromAL"), negTrkPt, negTrack.tpcNSigmaPr()); + registry.fill(HIST("NclVsEtaPrV0"), negTrkEta, negNcl); + registry.fill(HIST("NclVsEtaPrV0p"), negTrkEta, negNcl); + nClVsPPrV0[negIndexEta]->Fill(negPorPt, negNcl); + nClVsPpPrV0[negIndexEta]->Fill(negPorPt, negNcl); + dEdxPrV0[negIndexEta]->Fill(negTrkP, negTrkdEdx); } } if (passesGammaSelection(collision, v0)) { - if (isMassG) { - if (std::abs(alpha) < v0Selections.armAlphaSel && qT < v0Selections.qTSel) { - - if (v0Selections.applyPlateauSel && etaCal.isCalPlateauLoaded) { - const double posDedxCal{etaCal.pEtaCalPlateau->GetBinContent(etaCal.pEtaCalPlateau->FindBin(posTrkEta))}; - const double negDedxCal{etaCal.pEtaCalPlateau->GetBinContent(etaCal.pEtaCalPlateau->FindBin(negTrkEta))}; - if (!(std::abs(posTrkdEdx - posDedxCal) < v0Selections.dEdxPlateauSel && std::abs(negTrkdEdx - negDedxCal) < v0Selections.dEdxPlateauSel)) - continue; - } + if (std::abs(alpha) < v0Selections.armAlphaSel && qT < v0Selections.qTSel) { - registry.fill(HIST("V0sCounter"), V0sCounter::Gamma); - registry.fill(HIST("ArmG"), alpha, qT); - registry.fill(HIST("MassGVsPt"), v0.pt(), v0.mGamma()); - registry.fill(HIST("nSigElFromG"), negTrkPt, negTrack.tpcNSigmaEl()); - registry.fill(HIST("nSigElFromG"), posTrkPt, posTrack.tpcNSigmaEl()); - registry.fill(HIST("NclVsEtaElV0"), posTrkEta, posNcl); - registry.fill(HIST("NclVsEtaElV0p"), posTrkEta, posNcl); - registry.fill(HIST("NclVsEtaElV0"), negTrkEta, negNcl); - registry.fill(HIST("NclVsEtaElV0p"), negTrkEta, negNcl); - nClVsPElV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsPpElV0[negIndexEta]->Fill(negPorPt, negNcl); - nClVsPElV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsPpElV0[posIndexEta]->Fill(posPorPt, posNcl); - nClVsdEdxElV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - nClVsdEdxpElV0[negIndexEta]->Fill(negNcl, negTrkdEdx); - nClVsdEdxElV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - nClVsdEdxpElV0[posIndexEta]->Fill(posNcl, posTrkdEdx); - registry.fill(HIST("dEdxVsEtaElMIPV0"), posTrkEta, posTrkdEdx); - registry.fill(HIST("dEdxVsEtaElMIPV0p"), posTrkEta, posTrkdEdx); - registry.fill(HIST("dEdxVsEtaElMIPV0"), negTrkEta, negTrkdEdx); - registry.fill(HIST("dEdxVsEtaElMIPV0p"), negTrkEta, negTrkdEdx); - dEdxElV0[posIndexEta]->Fill(posTrkP, posTrkdEdx, centrality); - dEdxElV0[negIndexEta]->Fill(negTrkP, negTrkdEdx, centrality); + if (trackSelections.applyPlateauSel && etaCal.isCalPlateauLoaded) { + const double posDedxCal{etaCal.pEtaCalPlateau->GetBinContent(etaCal.pEtaCalPlateau->FindBin(posTrkEta))}; + const double negDedxCal{etaCal.pEtaCalPlateau->GetBinContent(etaCal.pEtaCalPlateau->FindBin(negTrkEta))}; + if (!(std::abs(posTrkdEdx - posDedxCal) < v0Selections.dEdxPlateauSel && std::abs(negTrkdEdx - negDedxCal) < v0Selections.dEdxPlateauSel)) + continue; } + + registry.fill(HIST("V0sCounter"), V0sCounter::Gamma); + registry.fill(HIST("ArmG"), alpha, qT); + registry.fill(HIST("MassGVsPt"), v0.pt(), v0.mGamma()); + registry.fill(HIST("nSigElFromG"), negTrkPt, negTrack.tpcNSigmaEl()); + registry.fill(HIST("nSigElFromG"), posTrkPt, posTrack.tpcNSigmaEl()); + registry.fill(HIST("NclVsEtaElV0"), posTrkEta, posNcl); + registry.fill(HIST("NclVsEtaElV0p"), posTrkEta, posNcl); + registry.fill(HIST("NclVsEtaElV0"), negTrkEta, negNcl); + registry.fill(HIST("NclVsEtaElV0p"), negTrkEta, negNcl); + nClVsPElV0[negIndexEta]->Fill(negPorPt, negNcl); + nClVsPpElV0[negIndexEta]->Fill(negPorPt, negNcl); + nClVsPElV0[posIndexEta]->Fill(posPorPt, posNcl); + nClVsPpElV0[posIndexEta]->Fill(posPorPt, posNcl); + registry.fill(HIST("dEdxVsEtaElMIPV0"), posTrkEta, posTrkdEdx); + registry.fill(HIST("dEdxVsEtaElMIPV0p"), posTrkEta, posTrkdEdx); + registry.fill(HIST("dEdxVsEtaElMIPV0"), negTrkEta, negTrkdEdx); + registry.fill(HIST("dEdxVsEtaElMIPV0p"), negTrkEta, negTrkdEdx); + dEdxElV0[posIndexEta]->Fill(posTrkP, posTrkdEdx); + dEdxElV0[negIndexEta]->Fill(negTrkP, negTrkdEdx); } } } // v0s @@ -1131,264 +1167,6 @@ struct PiKpRAA { Preslice perCollision = aod::track::collisionId; Service pdg; - void processMC(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::McParticles const& mcParticles, TracksMC const& tracksMC) - { - for (const auto& collision : collisions) { - // Event selection - if (!isEventSelected(collision)) { - continue; - } - // MC collision? - if (!collision.has_mcCollision()) { - continue; - } - - registry.fill(HIST("EventCounterMC"), EvCutLabel::All); - - if (std::fabs(mccollision.posZ()) > posZcut) - continue; - - registry.fill(HIST("zPos"), collision.posZ()); - registry.fill(HIST("zPosMC"), mccollision.posZ()); - registry.fill(HIST("EventCounterMC"), EvCutLabel::VtxZ); - - const auto& foundBC = collision.foundBC_as(); - uint64_t timeStamp{foundBC.timestamp()}; - const int magField{getMagneticField(timeStamp)}; - - if (v0Selections.applyPhiCut) { - const int nextRunNumber{foundBC.runNumber()}; - if (currentRunNumberPhiSel != nextRunNumber) { - loadPhiCutSelections(timeStamp); - currentRunNumberPhiSel = nextRunNumber; - LOG(info) << "\tcurrentRunNumberPhiSel= " << currentRunNumberPhiSel << " timeStamp = " << timeStamp; - } - - // return if phi cut objects are nullptr - if (!(phiCut.hPhiCutHigh && phiCut.hPhiCutLow)) - return; - } - - // Remove collisions if reconstructed more than once - if (skipRecoColGTOne && (collisions.size() > kOne)) - continue; - - const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; - registry.fill(HIST("T0Ccent"), centrality); - - const auto& groupedTracks{tracksMC.sliceBy(perCollision, collision.globalIndex())}; - - // Track selection with Open DCAxy - for (const auto& track : groupedTracks) { - // Track Selection - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) - continue; - - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) - continue; - - if (!trkSelGlobalOpenDCAxy.IsSelected(track)) - continue; - - if (!track.has_mcParticle()) - continue; - - // Get the MC particle - const auto& particle{track.mcParticle()}; - auto charge{0.}; - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) - charge = pdgParticle->Charge(); - else - continue; - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - float phiPrime{track.phi()}; - phiPrimeFunc(phiPrime, magField, charge); - - const float pOrPt{v0Selections.usePinPhiSelection ? track.p() : track.pt()}; - if (v0Selections.applyPhiCut) { - if (!passesPhiSelection(pOrPt, phiPrime)) - continue; - } - - const int16_t nclFound{track.tpcNClsFound()}; - const int16_t nclPID{track.tpcNClsPID()}; - const int16_t ncl = v0Selections.useNclsPID ? nclPID : nclFound; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) - continue; - - bool isPrimary{false}; - bool isDecay{false}; - bool isMaterial{false}; - if (particle.isPhysicalPrimary()) - isPrimary = true; - else if (particle.getProcess() == TMCProcess::kPDecay) - isDecay = true; - else - isMaterial = true; - - bool isPi{false}; - bool isPr{false}; - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) - isPi = true; - else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) - isPr = true; - else - continue; - - if (isPrimary && !isDecay && !isMaterial) { - if (isPi && !isPr) - registry.fill(HIST("dcaVsPtPi"), track.pt(), track.dcaXY(), centrality); - if (isPr && !isPi) - registry.fill(HIST("dcaVsPtPr"), track.pt(), track.dcaXY(), centrality); - } - - if (isDecay && !isPrimary && !isMaterial) { - if (isPi && !isPr) - registry.fill(HIST("dcaVsPtPiDec"), track.pt(), track.dcaXY(), centrality); - if (isPr && !isPi) - registry.fill(HIST("dcaVsPtPrDec"), track.pt(), track.dcaXY(), centrality); - } - - if (isMaterial && !isPrimary && !isDecay) { - if (isPi && !isPr) - registry.fill(HIST("dcaVsPtPiMat"), track.pt(), track.dcaXY(), centrality); - if (isPr && !isPi) - registry.fill(HIST("dcaVsPtPrMat"), track.pt(), track.dcaXY(), centrality); - } - } - - // Global track + DCAxy selections - for (const auto& track : groupedTracks) { - // Track Selection - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) - continue; - - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) - continue; - - if (!trkSelGlobal.IsSelected(track)) - continue; - - // Has MC particle? - if (!track.has_mcParticle()) - continue; - - // Get the MC particle - const auto& particle{track.mcParticle()}; - auto charge{0.}; - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) - charge = pdgParticle->Charge(); - else - continue; - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - float phiPrime{track.phi()}; - phiPrimeFunc(phiPrime, magField, charge); - - const float pOrPt{v0Selections.usePinPhiSelection ? track.p() : track.pt()}; - if (v0Selections.applyPhiCut) { - if (!passesPhiSelection(pOrPt, phiPrime)) - continue; - } - - const int16_t nclFound{track.tpcNClsFound()}; - const int16_t nclPID{track.tpcNClsPID()}; - const int16_t ncl = v0Selections.useNclsPID ? nclPID : nclFound; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) - continue; - - int indexEta{-999}; - const float eta{track.eta()}; - for (int i = 0; i < kNEtaHists; ++i) { - if (eta >= kLowEta[i] && eta < kHighEta[i]) { - indexEta = i; - break; - } - } - - if (indexEta < kZeroInt || indexEta > kSevenInt) - continue; - - registry.fill(HIST("NclVsPhip"), pOrPt, phiPrime, ncl); - registry.fill(HIST("NclVsEtaPID"), eta, ncl); - registry.fill(HIST("NclVsEtaPIDp"), eta, ncl); - - bool isPrimary{false}; - if (particle.isPhysicalPrimary()) - isPrimary = true; - - if (!isPrimary) - continue; - - bool isPi{false}; - bool isKa{false}; - bool isPr{false}; - - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) - isPi = true; - else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) - isKa = true; - else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) - isPr = true; - else - continue; - - if (isPi && !isKa && !isPr) - registry.fill(HIST("PtPiVsCent"), track.pt(), centrality); - if (isKa && !isPi && !isPr) - registry.fill(HIST("PtKaVsCent"), track.pt(), centrality); - if (isPr && !isPi && !isKa) - registry.fill(HIST("PtPrVsCent"), track.pt(), centrality); - } - - // Generated MC - for (const auto& particle : mcParticles) { - if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) - continue; - - if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) - continue; - - auto charge{0.}; - // Get the MC particle - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) - charge = pdgParticle->Charge(); - else - continue; - - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; - - // Is it a primary particle? - bool isPrimary{true}; - if (!particle.isPhysicalPrimary()) - isPrimary = false; - - if (isPrimary) { - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) // pion - registry.fill(HIST("PtPiVsCentMC"), particle.pt(), centrality); - else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) // kaon - registry.fill(HIST("PtKaVsCentMC"), particle.pt(), centrality); - else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) // proton - registry.fill(HIST("PtPrVsCentMC"), particle.pt(), centrality); - else - continue; - } - } - } // Collisions - } - PROCESS_SWITCH(PiKpRAA, processMC, "Process MC closure", false); void processSim(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::McParticles const& mcParticles, TracksMC const& tracksMC) { @@ -1398,6 +1176,7 @@ struct PiKpRAA { // By counting number of primary charged particles in |eta| < 1 //--------------------------- int nChMC{0}; + int nChMCEta08{0}; int nChFT0A{0}; int nChFT0C{0}; for (const auto& particle : mcParticles) { @@ -1430,6 +1209,10 @@ struct PiKpRAA { nChFT0C++; } + if (std::abs(eta) < tpcNchAcceptance) { + nChMCEta08++; + } + // INEL > 0 if (std::abs(eta) > kOne) continue; @@ -1464,12 +1247,65 @@ struct PiKpRAA { } } - const auto& nRecColls{collisions.size()}; - registry.fill(HIST("NumberOfRecoCollisions"), nRecColls); + //--------------------------- + // All Generated events irrespective of whether there is an associated reconstructed collision + // Consequently, the centrality being a reconstructed quantity, might not always be available + // Therefore it is expressed as a function of the generated pT and the generated Nch in ∣eta∣ < 0.8 + // This is used for the denominator of the signal loss correction + // Also for MC closure: True Pt vs Generated Nch + //--------------------------- + for (const auto& particle : mcParticles) { + if (particle.eta() < trackSelections.minEta || particle.eta() > trackSelections.maxEta) + continue; + + if (particle.pt() < trackSelections.minPt || particle.pt() > trackSelections.maxPt) + continue; + + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) + continue; + + // Is it a primary particle? + bool isPrimary{true}; + if (!particle.isPhysicalPrimary()) + isPrimary = false; + + if (isPrimary) { + if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { + registry.fill(HIST("PtPiVsNchMC_AllGen"), particle.pt(), nChMCEta08); + registry.fill(HIST("MCclosure_PtMCPiVsNchMC"), particle.pt(), nChMCEta08); + } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { + registry.fill(HIST("PtKaVsNchMC_AllGen"), particle.pt(), nChMCEta08); + registry.fill(HIST("MCclosure_PtMCKaVsNchMC"), particle.pt(), nChMCEta08); + } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { + registry.fill(HIST("PtPrVsNchMC_AllGen"), particle.pt(), nChMCEta08); + registry.fill(HIST("MCclosure_PtMCPrVsNchMC"), particle.pt(), nChMCEta08); + } else { + continue; + } + } + } // Loop over Generated Particles + + //--------------------------- + // This is used for the denominator of the event loss correction + //--------------------------- + registry.fill(HIST("NchMC_AllGen"), nChMCEta08); //--------------------------- // Only Generated evets with at least one reconstrued collision //--------------------------- + const auto& nRecColls{collisions.size()}; + registry.fill(HIST("NumberOfRecoCollisions"), nRecColls); + if (nRecColls > kZeroInt) { // Finds the collisions with the largest number of contributors @@ -1488,42 +1324,61 @@ struct PiKpRAA { bestCollisionIndex = collision.globalIndex(); } - // Needed to calculate denominator of the Event Splitting correction - if (isEventSelected(collision)) { - registry.fill(HIST("Centrality_AllRecoEvt"), centrality); - } - } + if (selHasBC && !collision.has_foundBC()) + continue; - //--------------------------- - // Loop over the reconstructed collisions - // Only that one with the largest number of contributors is considered - //--------------------------- - for (const auto& collision : collisions) { + if (selHasFT0 && !collision.has_foundFT0()) + continue; - const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; + if (useSel8 && !collision.sel8()) + continue; - //--------------------------- - // Reject collisions if has_foundFT0() returns false - //--------------------------- - if (selHasFT0 && !collision.has_foundFT0()) { - registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 0.5); + // kIsTriggerTVX + if (selTriggerTVX && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) + continue; + + // kNoITSROFrameBorder + if (selNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // kNoTimeFrameBorder + if (selNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + + // Zvtx + if (isZvtxPosSel && std::fabs(collision.posZ()) > posZcut) continue; - } - registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); + + if (selIsGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + if (selNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + + // Needed to calculate denominator of the Event Splitting correction + registry.fill(HIST("Centrality_AllRecoEvt"), centrality); + } + + //--------------------------- + // Loop over the reconstructed collisions + // Only that one with the largest number of contributors is considered + //--------------------------- + for (const auto& collision : collisions) { + + const float centrality{isT0Ccent ? collision.centFT0C() : collision.centFT0M()}; //--------------------------- // Pick the collisions with the largest number of contributors //--------------------------- - if (bestCollisionIndex != collision.globalIndex()) { + if (bestCollisionIndex != collision.globalIndex()) continue; - } // Needed to load the Phi selection from the CCDB const auto& foundBC = collision.foundBC_as(); uint64_t timeStamp{foundBC.timestamp()}; const int magField{getMagneticField(timeStamp)}; - if (v0Selections.applyPhiCut) { + if (trackSelections.applyPhiCut) { const int nextRunNumber{foundBC.runNumber()}; if (currentRunNumberPhiSel != nextRunNumber) { loadPhiCutSelections(timeStamp); @@ -1539,20 +1394,103 @@ struct PiKpRAA { //--------------------------- // Needed to construct the correlation between MC Nch v.s. centrality //--------------------------- - registry.fill(HIST("Centrality_WRecoEvt"), centrality); registry.fill(HIST("zPosMC"), mccollision.posZ()); + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 1.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 1.0); + + if (collision.has_foundBC()) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 2.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 2.0); + } + + if (collision.has_foundBC() && collision.has_foundFT0()) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 3.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 3.0); + } + + if (collision.has_foundBC() && collision.has_foundFT0() && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 4.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 4.0); + } + + //--------------------------- + // RCT Selection + //--------------------------- + if (requireGoodRct) { + // Checks if collisions passes RCT selection + const bool isFT0Bad{requireBCRct ? foundBC.rct_bit(kFT0Bad) : collision.rct_bit(kFT0Bad)}; + const bool isITSBad{requireBCRct ? foundBC.rct_bit(kITSBad) : collision.rct_bit(kITSBad)}; + const bool isITSLimAcc{requireBCRct ? foundBC.rct_bit(kITSLimAccMCRepr) : collision.rct_bit(kITSLimAccMCRepr)}; + const bool isTOFBad{requireBCRct ? foundBC.rct_bit(kTOFBad) : collision.rct_bit(kTOFBad)}; + const bool isTOFLimAcc{requireBCRct ? foundBC.rct_bit(kTOFLimAccMCRepr) : collision.rct_bit(kTOFLimAccMCRepr)}; + const bool isTPCTrackingBad{requireBCRct ? foundBC.rct_bit(kTPCBadTracking) : collision.rct_bit(kTPCBadTracking)}; + const bool isTPCPIDBad{requireBCRct ? foundBC.rct_bit(kTPCBadPID) : collision.rct_bit(kTPCBadPID)}; + const bool isTPCLimAcc{requireBCRct ? foundBC.rct_bit(kTPCLimAccMCRepr) : collision.rct_bit(kTPCLimAccMCRepr)}; + + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 1.0); + if (!isFT0Bad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 2.0); + if (!isITSBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 3.0); + if (!isITSLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 4.0); + if (!isTOFBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 5.0); + if (!isTOFLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 6.0); + if (!isTPCTrackingBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 7.0); + if (!isTPCPIDBad) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 8.0); + if (!isTPCLimAcc) + registry.fill(HIST("T0CcentVsRCTSel"), centrality, 9.0); + + registry.fill(HIST("RCTSel"), 1.0); + if (!rctChecker(collision)) + return; + + registry.fill(HIST("RCTSel"), 2.0); + } + + //--------------------------- + // Event Selection + //--------------------------- + if (!isEventSelected(collision)) + return; + + registry.fill(HIST("Centrality_WRecoEvtWSelCri"), centrality); + registry.fill(HIST("NchMCVsCent"), centrality, nChMCEta08); + registry.fill(HIST("NchMC_WithRecoEvt"), nChMCEta08); // Numerator of event loss correction + registry.fill(HIST("zPos"), collision.posZ()); + registry.fill(HIST("T0Ccent"), centrality); + + //--------------------------- + // has_foundFT0() ? + //--------------------------- + + if (collision.has_foundBC() && collision.has_foundFT0() && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST("T0CcentVsBCVsFT0VsTVXVsEvSel"), centrality, 5.0); + registry.fill(HIST("HasBCVsFT0VsTVXVsEvSel"), 5.0); + } + + if (collision.has_foundFT0()) + registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 1.5); + else + registry.fill(HIST("T0CcentVsFoundFT0"), centrality, 0.5); + //--------------------------- // All Generated events with at least one associated reconstructed collision // The Generated events are not subjected to any selection criteria + // However, the associated reconstructed collisions pass the selection criteria // This histograms are used for the denominator of the tracking efficiency //--------------------------- for (const auto& particle : mcParticles) { - if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) + if (particle.eta() < trackSelections.minEta || particle.eta() > trackSelections.maxEta) continue; - if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) + if (particle.pt() < trackSelections.minPt || particle.pt() > trackSelections.maxPt) continue; auto charge{0.}; @@ -1576,33 +1514,59 @@ struct PiKpRAA { if (isPrimary) { if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { registry.fill(HIST("PtPiVsCentMC_WithRecoEvt"), particle.pt(), centrality); // Denominator of tracking efficiency - registry.fill(HIST("PtPiVsNchMC_WithRecoEvt"), particle.pt(), nChMC); // Numerator of signal loss + registry.fill(HIST("PtPiVsNchMC_WithRecoEvt"), particle.pt(), nChMCEta08); // Numerator of signal loss } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { registry.fill(HIST("PtKaVsCentMC_WithRecoEvt"), particle.pt(), centrality); - registry.fill(HIST("PtKaVsNchMC_WithRecoEvt"), particle.pt(), nChMC); + registry.fill(HIST("PtKaVsNchMC_WithRecoEvt"), particle.pt(), nChMCEta08); } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { registry.fill(HIST("PtPrVsCentMC_WithRecoEvt"), particle.pt(), centrality); - registry.fill(HIST("PtPrVsNchMC_WithRecoEvt"), particle.pt(), nChMC); + registry.fill(HIST("PtPrVsNchMC_WithRecoEvt"), particle.pt(), nChMCEta08); } else { continue; } } } // Loop over generated particles per generated collision - //--------------------------- - // Reconstructed collisions subjected to selection criteria - //--------------------------- + // Generated events with FT0 information but not TVX triggered + if (selHasFT0 && collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + for (const auto& particle : mcParticles) { + if (particle.eta() < trackSelections.minEta || particle.eta() > trackSelections.maxEta) + continue; - // Event selection - if (!isEventSelected(collision)) { - continue; - } + if (particle.pt() < trackSelections.minPt || particle.pt() > trackSelections.maxPt) + continue; - registry.fill(HIST("Centrality_WRecoEvtWSelCri"), centrality); - registry.fill(HIST("NchMCVsCent"), centrality, nChMC); - registry.fill(HIST("NchMC_WithRecoEvt"), nChMC); - registry.fill(HIST("T0Ccent"), centrality); - registry.fill(HIST("zPos"), collision.posZ()); + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) + continue; + + // Is it a primary particle? + bool isPrimary{true}; + if (!particle.isPhysicalPrimary()) + isPrimary = false; + + if (isPrimary) { + if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { + registry.fill(HIST("PtPiVsNchMC_WithRecoEvt_has_FT0_and_TVX"), particle.pt(), nChMCEta08); // Numerator of signal loss + } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { + registry.fill(HIST("PtKaVsNchMC_WithRecoEvt_has_FT0_and_TVX"), particle.pt(), nChMCEta08); + } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { + registry.fill(HIST("PtPrVsNchMC_WithRecoEvt_has_FT0_and_TVX"), particle.pt(), nChMCEta08); + } else { + continue; + } + } + } // Loop over generated particles per generated collision + } const auto& groupedTracks{tracksMC.sliceBy(perCollision, collision.globalIndex())}; @@ -1612,10 +1576,10 @@ struct PiKpRAA { //--------------------------- for (const auto& track : groupedTracks) { // Track Selection - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) + if (track.eta() < trackSelections.minEta || track.eta() > trackSelections.maxEta) continue; - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) + if (track.pt() < trackSelections.minPt || track.pt() > trackSelections.maxPt) continue; if (!trkSelGlobalOpenDCAxy.IsSelected(track)) @@ -1641,8 +1605,8 @@ struct PiKpRAA { float phiPrime{track.phi()}; phiPrimeFunc(phiPrime, magField, charge); - const float pOrPt{v0Selections.usePinPhiSelection ? track.p() : track.pt()}; - if (v0Selections.applyPhiCut) { + const float pOrPt{trackSelections.usePinPhiSelection ? track.p() : track.pt()}; + if (trackSelections.applyPhiCut) { if (!passesPhiSelection(pOrPt, phiPrime)) continue; } @@ -1650,7 +1614,7 @@ struct PiKpRAA { const int16_t nclFound{track.tpcNClsFound()}; const int16_t nclPID{track.tpcNClsPID()}; const int16_t ncl = v0Selections.useNclsPID ? nclPID : nclFound; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) + if (trackSelections.applyNclSel && ncl < v0Selections.minNcl) continue; bool isPrimary{false}; @@ -1697,17 +1661,16 @@ struct PiKpRAA { } //--------------------------- + // Needed for the number of the Tracking Efficiency // Global track + DCAxy selections - // This is needed for the number of the Tracking Efficiency - // and the spectra to be corrected //--------------------------- int nCh{0}; for (const auto& track : groupedTracks) { // Track Selection - if (track.eta() < v0Selections.minEtaDaughter || track.eta() > v0Selections.maxEtaDaughter) + if (track.eta() < trackSelections.minEta || track.eta() > trackSelections.maxEta) continue; - if (track.pt() < v0Selections.minPt || track.pt() > v0Selections.maxPt) + if (track.pt() < trackSelections.minPt || track.pt() > trackSelections.maxPt) continue; if (!trkSelGlobal.IsSelected(track)) @@ -1734,8 +1697,8 @@ struct PiKpRAA { float phiPrime{track.phi()}; phiPrimeFunc(phiPrime, magField, charge); - const float pOrPt{v0Selections.usePinPhiSelection ? track.p() : track.pt()}; - if (v0Selections.applyPhiCut) { + const float pOrPt{trackSelections.usePinPhiSelection ? track.p() : track.pt()}; + if (trackSelections.applyPhiCut) { if (!passesPhiSelection(pOrPt, phiPrime)) continue; } @@ -1743,7 +1706,7 @@ struct PiKpRAA { const int16_t nclFound{track.tpcNClsFound()}; const int16_t nclPID{track.tpcNClsPID()}; const int16_t ncl = v0Selections.useNclsPID ? nclPID : nclFound; - if (v0Selections.applyNclSel && ncl < v0Selections.minNcl) + if (trackSelections.applyNclSel && ncl < v0Selections.minNcl) continue; int indexEta{-999}; @@ -1761,6 +1724,10 @@ struct PiKpRAA { registry.fill(HIST("NclVsPhip"), pOrPt, phiPrime, ncl); registry.fill(HIST("NclVsEtaPID"), eta, ncl); registry.fill(HIST("NclVsEtaPIDp"), eta, ncl); + registry.fill(HIST("NclVsEta"), eta, nclFound); + registry.fill(HIST("NclVsEtap"), eta, nclFound); + registry.fill(HIST("NclVsPt"), pOrPt, nclFound); + registry.fill(HIST("NclVsPtPID"), pOrPt, nclPID); nCh++; bool isPrimary{false}; @@ -1785,80 +1752,117 @@ struct PiKpRAA { } if (isPi && !isKa && !isPr) { - registry.fill(HIST("PtPiVsCent_WithRecoEvt"), track.pt(), centrality); // Numerator of tracking efficiency - registry.fill(HIST("MCclosure_PtPiVsNchMC"), track.pt(), nChMC); + registry.fill(HIST("PtPiVsCent_WithRecoEvt"), track.pt(), centrality); // Numerator of tracking efficiency + registry.fill(HIST("PtGenPiVsCent_WithRecoEvt"), particle.pt(), centrality); // Numerator of tracking efficiency + registry.fill(HIST("MCclosure_PtPiVsNchMC"), track.pt(), nChMCEta08); } if (isKa && !isPi && !isPr) { registry.fill(HIST("PtKaVsCent_WithRecoEvt"), track.pt(), centrality); - registry.fill(HIST("MCclosure_PtKaVsNchMC"), track.pt(), nChMC); + registry.fill(HIST("PtGenKaVsCent_WithRecoEvt"), particle.pt(), centrality); + registry.fill(HIST("MCclosure_PtKaVsNchMC"), track.pt(), nChMCEta08); } if (isPr && !isPi && !isKa) { registry.fill(HIST("PtPrVsCent_WithRecoEvt"), track.pt(), centrality); - registry.fill(HIST("MCclosure_PtPrVsNchMC"), track.pt(), nChMC); + registry.fill(HIST("PtGenPrVsCent_WithRecoEvt"), particle.pt(), centrality); + registry.fill(HIST("MCclosure_PtPrVsNchMC"), track.pt(), nChMCEta08); } registry.fill(HIST("PtResolution"), particle.pt(), (track.pt() - particle.pt()) / particle.pt()); } // Loop over reconstructed tracks - registry.fill(HIST("NchVsCent"), centrality, nCh); - } // Loop over Reco. Collisions: Only the collisions with the largest number of contributors - } // If condition: Only simulated evets with at least one reconstrued collision - //--------------------------- - // All Generated events irrespective of whether there is an associated reconstructed collision - // Consequently, the centrality being a reconstructed quantity, might not always be available - // Therefore it is expressed as a function of the generated pT and the generated Nch in ∣eta∣ < 0.8 - //--------------------------- + //------------------------------ + // Clean Pions and Muons + //------------------------------ - //--------------------------- - // Generated Pt spectra of all INEL > 0 Generated evets - // irrespective of whether there is a reconstructed collision - // This is used for the denominator of the signal loss correction - // Also for MC closure: True Pt vs Generated Nch - //--------------------------- - for (const auto& particle : mcParticles) { - if (particle.eta() < v0Selections.minEtaDaughter || particle.eta() > v0Selections.maxEtaDaughter) - continue; + for (const auto& track : groupedTracks) { + // Track Selection + if (track.eta() < trackSelections.minEta || track.eta() > trackSelections.maxEta) + continue; - if (particle.pt() < v0Selections.minPt || particle.pt() > v0Selections.maxPt) - continue; + if (track.pt() < trackSelections.minPt || track.pt() > trackSelections.maxPt) + continue; - auto charge{0.}; - // Get the MC particle - auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); - if (pdgParticle != nullptr) { - charge = pdgParticle->Charge(); - } else { - continue; - } + // Has MC particle? + if (!track.has_mcParticle()) + continue; - // Is it a charged particle? - if (std::abs(charge) < kMinCharge) - continue; + // Get the MC particle + const auto& particle{track.mcParticle()}; + auto charge{0.}; + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } - // Is it a primary particle? - bool isPrimary{true}; - if (!particle.isPhysicalPrimary()) - isPrimary = false; + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) + continue; - if (isPrimary) { - if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { - registry.fill(HIST("PtPiVsNchMC_AllGen"), particle.pt(), nChMC); - registry.fill(HIST("MCclosure_PtMCPiVsNchMC"), particle.pt(), nChMC); - } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { - registry.fill(HIST("PtKaVsNchMC_AllGen"), particle.pt(), nChMC); - registry.fill(HIST("MCclosure_PtMCKaVsNchMC"), particle.pt(), nChMC); - } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { - registry.fill(HIST("PtPrVsNchMC_AllGen"), particle.pt(), nChMC); - registry.fill(HIST("MCclosure_PtMCPrVsNchMC"), particle.pt(), nChMC); - } else { - continue; - } - } - } // Loop over Generated Particles + float phiPrime{track.phi()}; + phiPrimeFunc(phiPrime, magField, charge); - //--------------------------- - // This is used for the denominator of the event loss correction - //--------------------------- - registry.fill(HIST("NchMC_AllGen"), nChMC); + const float pOrPt{trackSelections.usePinPhiSelection ? track.p() : track.pt()}; + if (trackSelections.applyPhiCut) { + if (!passesPhiSelection(pOrPt, phiPrime)) + continue; + } + + const int16_t nclFound{track.tpcNClsFound()}; + const int16_t nclPID{track.tpcNClsPID()}; + const int16_t ncl{v0Selections.useNclsPID ? nclPID : nclFound}; + if (trackSelections.applyNclSel && ncl < v0Selections.minNcl) + continue; + + int indexEta{-999}; + const float eta{track.eta()}; + for (int i = 0; i < kNEtaHists; ++i) { + if (eta >= kLowEta[i] && eta < kHighEta[i]) { + indexEta = i; + break; + } + } + + if (indexEta < kZeroInt || indexEta > kSevenInt) + continue; + + bool isPrimary{false}; + if (particle.isPhysicalPrimary()) + isPrimary = true; + + if (!isPrimary) + continue; + + bool isPi{false}; + bool isMu{false}; + + if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) + isPi = true; + else if (particle.pdgCode() == PDG_t::kMuonPlus || particle.pdgCode() == PDG_t::kMuonMinus) + isMu = true; + else + continue; + + // Passes daughters track-selection? + if (passesTrackSelectionDaughters(track)) { + if (isPi && !isMu) { + nClVsPPiMC[indexEta]->Fill(track.p(), ncl); + dEdxPiMCLoSel[indexEta]->Fill(track.p(), track.tpcSignal()); + } + if (isMu && !isPi) + dEdxMuMCLoSel[indexEta]->Fill(track.p(), track.tpcSignal()); + } + + if (trkSelGlobal.IsSelected(track)) { + if (isPi && !isMu) + dEdxPiMC[indexEta]->Fill(track.p(), track.tpcSignal()); + if (isMu && !isPi) + dEdxMuMC[indexEta]->Fill(track.p(), track.tpcSignal()); + } + } // Loop over reconstructed tracks + registry.fill(HIST("NchVsCent"), centrality, nCh); + } // Loop over Reco. Collisions: Only the collisions with the largest number of contributors + } // If condition: Only simulated evets with at least one reconstrued collision } PROCESS_SWITCH(PiKpRAA, processSim, "Process Sim", false); @@ -1889,98 +1893,31 @@ struct PiKpRAA { alpha = (pLpos - pLneg) / denom; // equivalently / pV0mag } - // Daughters DCA selection - template - bool passesDCASelectionDaughters(const T& v0) - { - - bool isSelected{false}; - const double dcaPos{std::fabs(v0.dcapostopv())}; - const double dcaNeg{std::fabs(v0.dcanegtopv())}; - - isSelected = dcaPos > v0Selections.dcapostopv && dcaNeg > v0Selections.dcanegtopv ? true : false; - return isSelected; - } - template bool passesTrackSelectionDaughters(const T& track) { - // Secondary particle selection are basically Global tracks excluding the DCAxy selection - // This approach was used in the Run 2 analyses + // Decay daughters used Global tracks excluding the DCAxy selection; this approach was used in the Run 2 analyses // https://github.com/AliceO2Group/O2Physics/blob/b178c96d03ede873ee769ef8a4d7c1e21bf78332/Common/Core/TrackSelectionDefaults.cxx - const float pt{track.pt()}; + + // In the V0s analysis only the selection on eta (|eta|<0.8) and the selection on number of crossed rows was used: nCrossedRows >= 70 const float eta{track.eta()}; const int16_t nCrossedRows{track.tpcNClsCrossedRows()}; - const float nCrossedRowsOverFindableCls{track.tpcCrossedRowsOverFindableCls()}; - const float chi2PerClsTPC{track.tpcChi2NCl()}; - const float chi2PerClsITS{track.itsChi2NCl()}; - const bool refitITS{track.passedITSRefit()}; - const bool refitTPC{track.passedTPCRefit()}; - const bool goldeChi2{track.passedGoldenChi2()}; - const bool oneHitITSib{track.passedITSHitsFB1()}; bool etaSel{false}; - bool ptSel{false}; bool xRows{false}; - bool xRowsToFindCls{false}; - bool chi2TPC{false}; - bool chi2ITS{false}; - bool itsrefit{false}; - bool tpcrefit{false}; - bool golden{false}; - bool itshit{false}; registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::AllTrks); - if (eta > v0Selections.minEtaDaughter && eta < v0Selections.maxEtaDaughter) { - etaSel = true; + if (eta > trackSelections.minEta && eta < trackSelections.maxEta) { registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Eta); + etaSel = true; } - if (pt > v0Selections.minPtDaughter && pt < v0Selections.maxPtDaughter) { - ptSel = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Pt); - } - if (nCrossedRows >= v0Selections.minNCrossedRows) { - xRows = true; + if (nCrossedRows >= trackSelections.minNCrossedRows) { registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::XRows); - } - if (nCrossedRowsOverFindableCls >= v0Selections.minNCrossedRowsOverFindableCls) { - xRowsToFindCls = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::XRowsOverFindableCls); - } - if (chi2PerClsTPC < v0Selections.maxChi2ClsTPC) { - chi2TPC = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Chi2TPC); - } - if (chi2PerClsITS < v0Selections.maxChi2ClsITS) { - chi2ITS = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Chi2ITS); - } - if (refitITS == v0Selections.itsRefit) { - itsrefit = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Itsrefit); - } - if (refitTPC == v0Selections.tpcRefit) { - tpcrefit = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Tpcrefit); - } - if (goldeChi2 == v0Selections.chi2Golden) { - golden = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Golden); - } - if (oneHitITSib == v0Selections.its1HitIB) { - itshit = true; - registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::Itshit); + xRows = true; } - bool isSelected{false}; - if (!v0Selections.selElecFromGammas && v0Selections.requireITShit) - isSelected = etaSel && ptSel && xRows && xRowsToFindCls && chi2TPC && chi2ITS && itsrefit && tpcrefit && golden && itshit ? true : false; - if (!v0Selections.selElecFromGammas && !v0Selections.requireITShit) - isSelected = etaSel && ptSel && xRows && xRowsToFindCls && chi2TPC && chi2ITS && itsrefit && tpcrefit && golden ? true : false; - if (v0Selections.selElecFromGammas) { - isSelected = etaSel && ptSel && xRows && xRowsToFindCls && chi2TPC && chi2ITS && tpcrefit && golden ? true : false; - } + const bool isSelected{etaSel && xRows ? true : false}; if (isSelected == true) registry.fill(HIST("TrackDaughterCounter"), TrkSelLabel::PassedAll); @@ -1988,93 +1925,177 @@ struct PiKpRAA { return isSelected; } - // V0 topological selection + // V0 topological selection: + // *) V0 decay radius (cm) + // *) V0 cosine of pointing angle + // *) DCA between V0 daughters (cm) template bool passesV0TopologicalSelection(const T& v0) { - - bool isSelected = v0.v0radius() > v0Selections.v0radius && v0.v0radius() < v0Selections.v0radiusMax && passesDCASelectionDaughters(v0) && v0.v0cosPA() > v0Selections.v0cospa && v0.dcaV0daughters() < v0Selections.dcav0dau ? true : false; - + // bool isSelected = v0.v0radius() > v0Selections.v0radius && v0.v0radius() < v0Selections.v0radiusMax && v0.v0cosPA() > v0Selections.v0cospa && v0.dcaV0daughters() < v0Selections.dcav0dau && passesDCASelectionDaughters(v0) ? true : false; + bool isSelected = v0.v0radius() > v0Selections.v0radius && v0.v0radius() < v0Selections.v0radiusMax && v0.v0cosPA() > v0Selections.v0cospa && v0.dcaV0daughters() < v0Selections.dcav0dau ? true : false; return isSelected; } + // K0s topological selection: + // *) V0 Lifetime (cm) + // *) Rapidity selection + // *) DCA of pions to prim. vtx (cm) template bool passesK0Selection(const C& collision, const T& v0) { - // Selection on rapiditty, proper lifetime, and Nsigma Pion const auto& posTrack = v0.template posTrack_as(); const auto& negTrack = v0.template negTrack_as(); + const bool hasToF{posTrack.hasTOF() && negTrack.hasTOF() ? true : false}; + const bool goodToFmatch{posTrack.goodTOFMatch() && negTrack.goodTOFMatch() ? true : false}; + const double dcaPos{std::fabs(v0.dcapostopv())}; + const double dcaNeg{std::fabs(v0.dcanegtopv())}; const float posTPCNsigma{std::fabs(posTrack.tpcNSigmaPi())}; const float negTPCNsigma{std::fabs(negTrack.tpcNSigmaPi())}; const float posTOFNsigma{std::fabs(posTrack.tofNSigmaPi())}; const float negTOFNsigma{std::fabs(negTrack.tofNSigmaPi())}; - const double posRadiusNsigma{std::sqrt(std::pow(posTPCNsigma, 2.) + std::pow(posTOFNsigma, 2.))}; - const double negRadiusNsigma{std::sqrt(std::pow(negTPCNsigma, 2.) + std::pow(negTOFNsigma, 2.))}; - - registry.fill(HIST("EtaVsYK0s"), negTrack.eta(), v0.yK0Short()); - registry.fill(HIST("EtaVsYK0s"), posTrack.eta(), v0.yK0Short()); + const double dMassK0s{std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short)}; + const double dMassL{std::abs(v0.mLambda() - o2::constants::physics::MassLambda0)}; + const double dMassAL{std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0)}; + const double dMassG{std::abs(v0.mGamma() - o2::constants::physics::MassGamma)}; + const double rapidity{std::abs(v0.yK0Short())}; + const double lifeTime{v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short}; + + // Checks if DCA of daughters to PV passes selection + const bool dcaDaugToPV{dcaPos > v0Selections.dcapostopv && dcaNeg > v0Selections.dcanegtopv ? true : false}; + + // Rejects V0 if its invariant mass is not compatible with the K0s proper mass + if (v0Selections.applyInvMassSel) { + if (!(dMassK0s < v0Selections.dMassSel && dMassL > v0Selections.dMassSel && dMassAL > v0Selections.dMassSel && dMassG > v0Selections.dMassSelG)) + return false; + } bool isSelected{false}; - if (v0Selections.applyTPCTOFCombinedCut) - isSelected = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < lifetimecut->get("lifetimecutK0S") && std::abs(v0.yK0Short()) < v0Selections.rapidityCut && posTrack.hasTOF() && negTrack.hasTOF() && posRadiusNsigma < v0Selections.tpcPidNsigmaCut && negRadiusNsigma < v0Selections.tpcPidNsigmaCut ? true : false; - else - isSelected = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short < lifetimecut->get("lifetimecutK0S") && std::abs(v0.yK0Short()) < v0Selections.rapidityCut && posTPCNsigma < v0Selections.tpcPidNsigmaCut && negTPCNsigma < v0Selections.tpcPidNsigmaCut ? true : false; + if (v0Selections.useOfficialV0sSelOfDaughters) { + isSelected = lifeTime < v0Selections.lifeTimeCutK0s && rapidity < v0Selections.rapidityCut && dcaDaugToPV ? true : false; + } + if (!v0Selections.useOfficialV0sSelOfDaughters) { + if (v0Selections.useTPCNsigma) + isSelected = lifeTime < v0Selections.lifeTimeCutK0s && rapidity < v0Selections.rapidityCut && posTPCNsigma < v0Selections.pidNsigmaCut && negTPCNsigma < v0Selections.pidNsigmaCut && dcaDaugToPV ? true : false; + if (!v0Selections.useTPCNsigma) + isSelected = lifeTime < v0Selections.lifeTimeCutK0s && rapidity < v0Selections.rapidityCut && posTOFNsigma < v0Selections.pidNsigmaCut && negTOFNsigma < v0Selections.pidNsigmaCut && hasToF && goodToFmatch && dcaDaugToPV ? true : false; + } + if (isSelected) { + registry.fill(HIST("EtaVsYK0s"), negTrack.eta(), v0.yK0Short()); + registry.fill(HIST("EtaVsYK0s"), posTrack.eta(), v0.yK0Short()); + registry.fill(HIST("DCAxyPtPiK0s"), v0.dcapostopv(), posTrack.pt()); + registry.fill(HIST("DCAxyPtPiK0s"), v0.dcanegtopv(), negTrack.pt()); + } return isSelected; } + // Lambda topological selection: + // *) V0 Lifetime (cm) + // *) Rapidity selection + // *) DCA of pions and protons to prim. vtx (cm) template bool passesLambdaSelection(const C& collision, const T& v0) { - // Selection on rapiditty, proper lifetime, and Nsigma Pion const auto& posTrack = v0.template posTrack_as(); const auto& negTrack = v0.template negTrack_as(); + const bool hasToF{posTrack.hasTOF() && negTrack.hasTOF() ? true : false}; + const bool goodToFmatch{posTrack.goodTOFMatch() && negTrack.goodTOFMatch() ? true : false}; + const double dcaPos{std::fabs(v0.dcapostopv())}; + const double dcaNeg{std::fabs(v0.dcanegtopv())}; const float posTPCNsigma{std::fabs(posTrack.tpcNSigmaPr())}; const float negTPCNsigma{std::fabs(negTrack.tpcNSigmaPi())}; const float posTOFNsigma{std::fabs(posTrack.tofNSigmaPr())}; const float negTOFNsigma{std::fabs(negTrack.tofNSigmaPi())}; - const double posRadiusNsigma{std::sqrt(std::pow(posTPCNsigma, 2.) + std::pow(posTOFNsigma, 2.))}; - const double negRadiusNsigma{std::sqrt(std::pow(negTPCNsigma, 2.) + std::pow(negTOFNsigma, 2.))}; - - registry.fill(HIST("EtaVsYPiL"), negTrack.eta(), v0.yLambda()); - registry.fill(HIST("EtaVsYPrL"), posTrack.eta(), v0.yLambda()); + const double dMassK0s{std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short)}; + const double dMassL{std::abs(v0.mLambda() - o2::constants::physics::MassLambda0)}; + const double dMassG{std::abs(v0.mGamma() - o2::constants::physics::MassGamma)}; + const double rapidity{std::abs(v0.yLambda())}; + const double lifeTime{v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0}; + + // Checks if DCA of daughters to PV passes selection + const bool dcaDaugToPV{dcaPos > v0Selections.dcaProtonFromLambda && dcaNeg > v0Selections.dcaPionFromLambda ? true : false}; + + // Rejects V0 if the invariant mass is not compatible with the Lambda proper mass + if (v0Selections.applyInvMassSel) { + if (!(dMassL < v0Selections.dMassSel && dMassK0s > v0Selections.dMassSel && dMassG > v0Selections.dMassSelG)) + return false; + } bool isSelected{false}; - if (v0Selections.applyTPCTOFCombinedCut) - isSelected = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < lifetimecut->get("lifetimecutLambda") && std::abs(v0.yLambda()) < v0Selections.rapidityCut && posTrack.hasTOF() && negTrack.hasTOF() && posRadiusNsigma < v0Selections.tpcPidNsigmaCut && negRadiusNsigma < v0Selections.tpcPidNsigmaCut ? true : false; - else - isSelected = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < lifetimecut->get("lifetimecutLambda") && std::abs(v0.yLambda()) < v0Selections.rapidityCut && posTPCNsigma < v0Selections.tpcPidNsigmaCut && negTPCNsigma < v0Selections.tpcPidNsigmaCut ? true : false; + if (v0Selections.useOfficialV0sSelOfDaughters) { + isSelected = lifeTime < v0Selections.lifeTimeCutLambda && rapidity < v0Selections.rapidityCut && dcaDaugToPV ? true : false; + } + if (!v0Selections.useOfficialV0sSelOfDaughters) { + if (v0Selections.useTPCNsigma) + isSelected = lifeTime < v0Selections.lifeTimeCutLambda && rapidity < v0Selections.rapidityCut && posTPCNsigma < v0Selections.pidNsigmaCut && negTPCNsigma < v0Selections.pidNsigmaCut && dcaDaugToPV ? true : false; + if (!v0Selections.useTPCNsigma) + isSelected = lifeTime < v0Selections.lifeTimeCutLambda && rapidity < v0Selections.rapidityCut && posTOFNsigma < v0Selections.pidNsigmaCut && negTOFNsigma < v0Selections.pidNsigmaCut && hasToF && goodToFmatch && dcaDaugToPV ? true : false; + } + + if (isSelected) { + registry.fill(HIST("DCAxyPtPrL"), v0.dcapostopv(), posTrack.pt()); + registry.fill(HIST("EtaVsYPiL"), negTrack.eta(), v0.yLambda()); + registry.fill(HIST("EtaVsYPrL"), posTrack.eta(), v0.yLambda()); + } return isSelected; } + // Anti Lambda topological selection: + // *) V0 Lifetime (cm) + // *) Rapidity selection + // *) DCA of pions and protons to prim. vtx (cm) template bool passesAntiLambdaSelection(const C& collision, const T& v0) { - // Selection on rapiditty, proper lifetime, and Nsigma Pion const auto& posTrack = v0.template posTrack_as(); const auto& negTrack = v0.template negTrack_as(); + const bool hasToF{posTrack.hasTOF() && negTrack.hasTOF() ? true : false}; + const bool goodToFmatch{posTrack.goodTOFMatch() && negTrack.goodTOFMatch() ? true : false}; + const double dcaPos{std::fabs(v0.dcapostopv())}; + const double dcaNeg{std::fabs(v0.dcanegtopv())}; const float posTPCNsigma{std::fabs(posTrack.tpcNSigmaPi())}; const float negTPCNsigma{std::fabs(negTrack.tpcNSigmaPr())}; const float posTOFNsigma{std::fabs(posTrack.tofNSigmaPi())}; const float negTOFNsigma{std::fabs(negTrack.tofNSigmaPr())}; - const double posRadiusNsigma{std::sqrt(std::pow(posTPCNsigma, 2.) + std::pow(posTOFNsigma, 2.))}; - const double negRadiusNsigma{std::sqrt(std::pow(negTPCNsigma, 2.) + std::pow(negTOFNsigma, 2.))}; - - registry.fill(HIST("EtaVsYPiAL"), posTrack.eta(), v0.yLambda()); - registry.fill(HIST("EtaVsYPrAL"), negTrack.eta(), v0.yLambda()); + const double dMassK0s{std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short)}; + const double dMassAL{std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0)}; + const double dMassG{std::abs(v0.mGamma() - o2::constants::physics::MassGamma)}; + const double rapidity{std::abs(v0.yLambda())}; + const double lifeTime{v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0}; + + // Checks if DCA of daughters to PV passes selection + const bool dcaDaugToPV{dcaPos > v0Selections.dcaPionFromLambda && dcaNeg > v0Selections.dcaProtonFromLambda ? true : false}; + + // Rejects V0 if the invariant mass is not compatible with the Lambda proper mass + if (v0Selections.applyInvMassSel) { + if (!(dMassAL < v0Selections.dMassSel && dMassK0s > v0Selections.dMassSel && dMassG > v0Selections.dMassSelG)) + return false; + } bool isSelected{false}; - if (v0Selections.applyTPCTOFCombinedCut) - isSelected = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < lifetimecut->get("lifetimecutLambda") && std::abs(v0.yLambda()) < v0Selections.rapidityCut && posTrack.hasTOF() && negTrack.hasTOF() && posRadiusNsigma < v0Selections.tpcPidNsigmaCut && negRadiusNsigma < v0Selections.tpcPidNsigmaCut ? true : false; - else - isSelected = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 < lifetimecut->get("lifetimecutLambda") && std::abs(v0.yLambda()) < v0Selections.rapidityCut && posTPCNsigma < v0Selections.tpcPidNsigmaCut && negTPCNsigma < v0Selections.tpcPidNsigmaCut ? true : false; + if (v0Selections.useOfficialV0sSelOfDaughters) { + isSelected = lifeTime < v0Selections.lifeTimeCutLambda && rapidity < v0Selections.rapidityCut && dcaDaugToPV ? true : false; + } + if (!v0Selections.useOfficialV0sSelOfDaughters) { + if (v0Selections.useTPCNsigma) + isSelected = lifeTime < v0Selections.lifeTimeCutLambda && rapidity < v0Selections.rapidityCut && posTPCNsigma < v0Selections.pidNsigmaCut && negTPCNsigma < v0Selections.pidNsigmaCut && dcaDaugToPV ? true : false; + if (!v0Selections.useTPCNsigma) + isSelected = lifeTime < v0Selections.lifeTimeCutLambda && rapidity < v0Selections.rapidityCut && posTOFNsigma < v0Selections.pidNsigmaCut && negTOFNsigma < v0Selections.pidNsigmaCut && hasToF && goodToFmatch && dcaDaugToPV ? true : false; + } + + if (isSelected) { + registry.fill(HIST("DCAxyPtPrAL"), v0.dcanegtopv(), negTrack.pt()); + registry.fill(HIST("EtaVsYPiAL"), posTrack.eta(), v0.yLambda()); + registry.fill(HIST("EtaVsYPrAL"), negTrack.eta(), v0.yLambda()); + } return isSelected; } @@ -2085,25 +2106,37 @@ struct PiKpRAA { const auto& posTrack = v0.template posTrack_as(); const auto& negTrack = v0.template negTrack_as(); + const double dcaPos{std::fabs(v0.dcapostopv())}; + const double dcaNeg{std::fabs(v0.dcanegtopv())}; const float posTPCNsigma{std::fabs(posTrack.tpcNSigmaEl())}; const float negTPCNsigma{std::fabs(negTrack.tpcNSigmaEl())}; - const float posTOFNsigma{std::fabs(posTrack.tofNSigmaEl())}; - const float negTOFNsigma{std::fabs(negTrack.tofNSigmaEl())}; - const double posRadiusNsigma{std::sqrt(std::pow(posTPCNsigma, 2.) + std::pow(posTOFNsigma, 2.))}; - const double negRadiusNsigma{std::sqrt(std::pow(negTPCNsigma, 2.) + std::pow(negTOFNsigma, 2.))}; + const double dMassK0s{std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short)}; + const double dMassL{std::abs(v0.mLambda() - o2::constants::physics::MassLambda0)}; + const double dMassAL{std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0)}; + const double dMassG{std::abs(v0.mGamma() - o2::constants::physics::MassGamma)}; const float yGamma = RecoDecay::y(std::array{v0.px(), v0.py(), v0.pz()}, o2::constants::physics::MassGamma); - registry.fill(HIST("EtaVsYG"), negTrack.eta(), yGamma); - registry.fill(HIST("EtaVsYG"), posTrack.eta(), yGamma); + // Checks if DCA of daughters to PV passes selection + const bool dcaDaugToPV{dcaPos > v0Selections.dcaElectronFromGamma && dcaNeg > v0Selections.dcaElectronFromGamma ? true : false}; + + if (v0Selections.applyInvMassSel) { + if (!(dMassK0s > v0Selections.dMassSel && dMassL > v0Selections.dMassSel && dMassAL > v0Selections.dMassSel && dMassG < v0Selections.dMassSel)) + return false; + } if (!(std::abs(yGamma) < v0Selections.rapidityCut)) return false; bool isSelected{false}; - if (v0Selections.applyTPCTOFCombinedCut) - isSelected = posTrack.hasTOF() && negTrack.hasTOF() && posRadiusNsigma < v0Selections.tpcPidNsigmaCut && negRadiusNsigma < v0Selections.tpcPidNsigmaCut ? true : false; - else - isSelected = posTPCNsigma < v0Selections.tpcPidNsigmaCut && negTPCNsigma < v0Selections.tpcPidNsigmaCut ? true : false; + if (v0Selections.useOfficialV0sSelOfDaughters) + isSelected = dcaDaugToPV ? true : false; + if (!v0Selections.useOfficialV0sSelOfDaughters) + isSelected = dcaDaugToPV && posTPCNsigma < v0Selections.pidNsigmaCut && negTPCNsigma < v0Selections.pidNsigmaCut ? true : false; + + if (isSelected) { + registry.fill(HIST("EtaVsYG"), negTrack.eta(), yGamma); + registry.fill(HIST("EtaVsYG"), posTrack.eta(), yGamma); + } return isSelected; } @@ -2158,16 +2191,60 @@ struct PiKpRAA { bool isEventSelected(CheckCol const& col) { registry.fill(HIST("EventCounter"), EvCutLabel::All); - if (!col.sel8()) { - return false; + + // Has BC? + if (selHasBC) { + if (!col.has_foundBC()) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::HasBC); } - registry.fill(HIST("EventCounter"), EvCutLabel::SelEigth); - if (selNoSameBunchPileup) { - if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // Has FT0 information? + if (selHasFT0) { + if (!col.has_foundFT0()) { return false; } - registry.fill(HIST("EventCounter"), EvCutLabel::NoSameBunchPileup); + registry.fill(HIST("EventCounter"), EvCutLabel::HasFT0); + } + + if (useSel8) { + if (!col.sel8()) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelEigth); + } + + // kIsTriggerTVX + if (selTriggerTVX) { + if (!col.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelTriggerTVX); + } + + // kNoITSROFrameBorder + if (selNoITSROFrameBorder) { + if (!col.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelNoITSROFrameBorder); + } + + // kNoTimeFrameBorder + if (selNoTimeFrameBorder) { + if (!col.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::SelNoTimeFrameBorder); + } + + // Zvtx + if (isZvtxPosSel) { + if (std::fabs(col.posZ()) > posZcut) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::VtxZ); } if (selIsGoodZvtxFT0vsPV) { @@ -2177,6 +2254,13 @@ struct PiKpRAA { registry.fill(HIST("EventCounter"), EvCutLabel::IsGoodZvtxFT0vsPV); } + if (selNoSameBunchPileup) { + if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + registry.fill(HIST("EventCounter"), EvCutLabel::NoSameBunchPileup); + } + if (isNoCollInTimeRangeStrict) { if (!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; @@ -2229,13 +2313,6 @@ struct PiKpRAA { registry.fill(HIST("EventCounter"), EvCutLabel::OccuCut); } - if (selHasFT0) { - if (!col.has_foundFT0()) { - return false; - } - registry.fill(HIST("EventCounter"), EvCutLabel::HasFT0); - } - if (isCentSel) { if (col.centFT0C() < minT0CcentCut || col.centFT0C() > maxT0CcentCut) { return false; @@ -2243,13 +2320,6 @@ struct PiKpRAA { registry.fill(HIST("EventCounter"), EvCutLabel::Centrality); } - if (isZvtxPosSel) { - if (std::fabs(col.posZ()) > posZcut) { - return false; - } - registry.fill(HIST("EventCounter"), EvCutLabel::VtxZ); - } - if (selINELgt0) { if (!col.isInelGt0()) { return false; diff --git a/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx b/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx index 60b8c616131..e891477a770 100644 --- a/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx +++ b/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx @@ -99,15 +99,20 @@ struct KinkBuilder { Configurable maxDCAMothToPV{"maxDCAMothToPV", 0.2, "Max DCA of the mother to the PV"}; Configurable minDCADaugToPV{"minDCADaugToPV", 0.1, "Min DCA of the daughter to the PV"}; Configurable minPtMoth{"minPtMoth", 0.15, "Minimum pT of the hypercandidate"}; + Configurable minPtDaug{"minPtDaug", 0.15, "Minimum pT of the daughter candidate"}; Configurable maxZDiff{"maxZDiff", 20., "Max z difference between the kink daughter and the mother"}; Configurable maxPhiDiff{"maxPhiDiff", 100, "Max phi difference between the kink daughter and the mother"}; Configurable timeMarginNS{"timeMarginNS", 600, "Additional time res tolerance in ns"}; + Configurable timeMarginNSDaughter{"timeMarginNSDaughter", 200, "time tolerance for daughter candidate in ns"}; Configurable etaMaxDaug{"etaMaxDaug", 1., "eta max daughter"}; Configurable etaMaxMoth{"etaMaxMoth", 1., "eta max Mother"}; Configurable nTPCClusMinDaug{"nTPCClusMinDaug", 30, "mother NTPC clusters cut"}; Configurable itsChi2cut{"itsChi2cut", 36, "mother itsChi2 cut"}; Configurable askTOFforDaug{"askTOFforDaug", false, "If true, ask for TOF signal"}; Configurable kaontopologhy{"kaontopologhy", true, "If true, selected mother have both ITS+TPC "}; + Configurable ismc{"ismc", false, "If true, additional selection crideria for daughter "}; + Configurable minradiusKink{"minradiusKink", 130.0, "minradiuscut for kink vertex"}; + Configurable maxradiusKink{"maxradiusKink", 200.0, "maxradiuscut for kink vertex"}; o2::vertexing::DCAFitterN<2> fitter; o2::base::MatLayerCylSet* lut = nullptr; @@ -205,76 +210,122 @@ struct KinkBuilder { if (askTOFforDaug && !candidate.hasTOF()) { return false; } + if (ismc && candidate.trackTimeRes() > timeMarginNSDaughter) { + return false; // ns + } + if (ismc && candidate.pt() < minPtDaug) { + return false; // ns + } + return true; } template - void fillCandidateData(const Tcolls& collisions, const Ttracks& tracks, aod::AmbiguousTracks const& ambiguousTracks, aod::BCsWithTimestamps const& bcs) + void fillCandidateData(const Tcolls& collisions, + const Ttracks& tracks, + aod::AmbiguousTracks const& ambiguousTracks, + aod::BCsWithTimestamps const& bcs) { svCreator.clearPools(); svCreator.fillBC2Coll(collisions, bcs); - bool isDaug; - bool isMoth; + + bool isDaug = false; + bool isMoth = false; + for (const auto& track : tracks) { - if (!track.hasTPC()) + if (!track.hasTPC()) { continue; + } isDaug = false; isMoth = false; + + // Daughter: TPC-only, not PV contributor if (!track.hasITS() && !track.isPVContributor()) { isDaug = selectDaugTrack(track); } + + // Mother: PV contributor, ITS (+TPC if kaon topology), no TOF if (track.hasITS() && !track.hasTOF() && track.isPVContributor()) { isMoth = selectMothTrack(track); } - if (!isDaug && !isMoth) + + if (!isDaug && !isMoth) { continue; - if (isMoth && std::abs(track.eta()) > etaMaxMoth) + } + + if (isMoth && std::abs(track.eta()) > etaMaxMoth) { continue; - if (isDaug && std::abs(track.eta()) > etaMaxDaug) + } + if (isDaug && std::abs(track.eta()) > etaMaxDaug) { continue; + } + int pdgHypo = isMoth ? 1 : 0; svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); } - auto& kinkPool = svCreator.getSVCandPool(collisions, !unlikeSignBkg); + auto& kinkPool = svCreator.getSVCandPool(collisions, /*combineLikeSign=*/!unlikeSignBkg); for (const auto& svCand : kinkPool) { KinkCandidate kinkCand; auto trackMoth = tracks.rawIteratorAt(svCand.tr0Idx); auto trackDaug = tracks.rawIteratorAt(svCand.tr1Idx); + + // Mother must have collision (PV contributor) + if (!trackMoth.has_collision()) { + continue; + } + auto const& collision = trackMoth.template collision_as(); + if (!collision.has_bc()) { + continue; + } auto const& bc = collision.template bc_as(); initCCDB(bc); 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()); + primaryVertex.setCov(collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ()); kinkCand.primVtx = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; o2::track::TrackParCov trackParCovMoth = getTrackParCov(trackMoth); o2::track::TrackParCov trackParCovMothPV{trackParCovMoth}; + std::array dcaInfoMoth; - bool okMoth = o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovMothPV, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoMoth); + bool okMoth = o2::base::Propagator::Instance()->propagateToDCABxByBz( + {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, + trackParCovMothPV, 2.f, + static_cast(cfgMaterialCorrection.value), + &dcaInfoMoth); + if (!okMoth) { continue; } + o2::track::TrackParCov trackParCovDaug = getTrackParCov(trackDaug); - // propagate to PV std::array dcaInfoDaug; - bool okDaug = o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovDaug, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoDaug); + + bool okDaug = o2::base::Propagator::Instance()->propagateToDCABxByBz( + {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, + trackParCovDaug, 2.f, + static_cast(cfgMaterialCorrection.value), + &dcaInfoDaug); + if (!okDaug) { continue; } + if (std::abs(dcaInfoMoth[1]) > maxDCAMothToPV) { continue; } if (std::abs(dcaInfoDaug[1]) < minDCADaugToPV) { continue; } + int nCand = 0; try { nCand = fitter.process(trackParCovMoth, trackParCovDaug); } catch (...) { - LOG(error) << "Exception caught in DCA fitter process call!"; continue; } if (nCand == 0) { @@ -283,13 +334,19 @@ struct KinkBuilder { if (!fitter.propagateTracksToVertex()) { continue; } + auto propMothTrack = fitter.getTrack(0); auto propDaugTrack = fitter.getTrack(1); + kinkCand.decVtx = fitter.getPCACandidatePos(); const int vtxp = 3; for (int i = 0; i < vtxp; i++) { kinkCand.decVtx[i] -= kinkCand.primVtx[i]; } + double radiusxy = std::sqrt(kinkCand.decVtx[0] * kinkCand.decVtx[0] + kinkCand.decVtx[1] * kinkCand.decVtx[1]); + if (radiusxy < minradiusKink || radiusxy > maxradiusKink) { + continue; + } propMothTrack.getPxPyPzGlo(kinkCand.momMoth); propDaugTrack.getPxPyPzGlo(kinkCand.momDaug); for (int i = 0; i < vtxp; i++) { @@ -380,6 +437,7 @@ struct SpectraKinkPiKa { Configurable pid{"pid", 321, ""}; Configurable dpid{"dpid", 13, ""}; Configurable dpidCut{"dpidCut", 0, ""}; + Configurable dradiusCrossrow{"dradiusCrossrow", 0, ""}; Configurable dptCut{"dptCut", 0, ""}; Configurable qa{"qa", 0, ""}; Configurable maxtpcncle{"maxtpcncle", 0, "max tpc find ncle"}; @@ -517,28 +575,28 @@ struct SpectraKinkPiKa { return ptd; } - double maxKinkAngle(double pMother, double M, double mDaughter) + double maxKinkAngle(double pMother, double M, double beta) { - double pStar = (M * M - mDaughter * mDaughter) / (2 * M); // rest-frame momentum - double denom = std::sqrt(pMother * pMother + mDaughter * mDaughter); - double sinTheta = pStar / denom; - if (sinTheta > 1.0) - sinTheta = 1.0; - return std::asin(sinTheta) * o2::constants::math::Rad2Deg; + double num = M * beta; // rest-frame momentum + double denom = std::sqrt(pMother * pMother * (1 - beta * beta) - (M * M * beta * beta)); + double tanTheta = num / denom; + return std::atan(tanTheta) * o2::constants::math::Rad2Deg; } double f1(double p) // K → μ ν { + double betak = 0.9127037; return maxKinkAngle(p, o2::constants::physics::MassKaonCharged, - o2::constants::physics::MassMuon); + betak); } inline double f2(double p) // π → μ ν { + double betapi = 0.2731374; return maxKinkAngle(p, o2::constants::physics::MassPionCharged, - o2::constants::physics::MassMuon); + betapi); } void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const&) @@ -636,6 +694,9 @@ struct SpectraKinkPiKa { double radiusxy = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); if (radiusxy < minradius || radiusxy > maxradius) continue; + + if (dradiusCrossrow && (mothTrack.tpcNClsFound() > (-31.67 + ((11.0 / 12.0) * radiusxy)) || mothTrack.tpcNClsFound() < (-85.5 + ((65.0 / 95.0) * radiusxy)))) + continue; rpiKkink.fill(HIST("h1_tracks_data"), 10.0); if (std::abs(kinkCand.zDecVtx()) < minzcut || std::abs(kinkCand.zDecVtx()) > maxzcut) continue; @@ -748,15 +809,19 @@ struct SpectraKinkPiKa { for (const auto& kinkCand : kinkCandPerColl) { auto dauTrack = kinkCand.trackDaug_as(); auto mothTrack = kinkCand.trackMoth_as(); + if (mothTrack.collisionId() != collision.globalIndex()) { + continue; // not from this event + } + if (!mothTrack.has_collision() || !dauTrack.has_collision()) { continue; } if (mothTrack.collisionId() != dauTrack.collisionId()) { continue; // skip mismatched collision tracks } - if (mothTrack.collisionId() != collision.globalIndex()) { - continue; // not from this event - } + // if (mothTrack.collisionId() != collision.globalIndex()) { + // continue; // not from this event + // } if (dauTrack.sign() != mothTrack.sign()) { LOG(info) << "Skipping kink candidate with opposite sign daughter and mother: " << kinkCand.globalIndex(); continue; // Skip if the daughter has the opposite sign as the mother @@ -771,6 +836,8 @@ struct SpectraKinkPiKa { double radiusxy = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); if (radiusxy < minradius || radiusxy > maxradius) continue; + if (dradiusCrossrow && (mothTrack.tpcNClsFound() > (-31.67 + ((11.0 / 12.0) * radiusxy)) || mothTrack.tpcNClsFound() < (-85.5 + ((65.0 / 95.0) * radiusxy)))) + continue; rpiKkink.fill(HIST("h1_tracks"), 3.0); if (std::abs(kinkCand.zDecVtx()) < minzcut || std::abs(kinkCand.zDecVtx()) > maxzcut) continue; @@ -853,6 +920,9 @@ struct SpectraKinkPiKa { continue; rpiKkink.fill(HIST("h1_tracks"), 12.0); + if (std::abs(v0.Rapidity()) > rapCut) { + continue; + } if (additionalhist) { rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec"), v0.Pt(), v0.Eta(), multiplicity); rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec"), v1.Pt(), v1.Eta(), multiplicity); diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index 3a24f382bff..8c49a9595dd 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -78,7 +78,22 @@ std::array, NpCharge> hDecayLengthMCNotHF; // Decay Length std::array, NpCharge> hPtNumTOFMatchWithPIDSignalPrm; // Pt distribution of particles with a hit in the TOF and a compatible signal -std::array, NpCharge>, 3> hMCpdg_nsigmaTPC; // 2D array of nsigmaTPC histograms [Selection: pi,K,p][True PDG: 18 species] +std::array, NpCharge>, 3> hMCPdgNsigmaTPC; // 2D array of nsigmaTPC histograms [Selection: pi,K,p][True PDG: 18 species] +std::array, NpCharge>, 3> hMCPdgNsigmaTOF; // 2D array of nsigmaTOF histograms [Selection: pi,K,p][True PDG: 18 species] + +// inel cut constants +static constexpr int EvSelInelGt0Cut = 1; +static constexpr int EvSelInelGt1Cut = 2; + +// mc dca filling constants +static constexpr float DcaMaxCombinedSigma = 2.f; +static constexpr float DcaMaxTPCSigma = 1.f; +static constexpr float DcaTrkPtCut = 0.4f; +static constexpr float DcaPhiPtMin = 0.9f; +static constexpr float DcaPhiPtMax = 1.1f; + +// PDG code (HF) +static constexpr int kD0 = 421; // Spectra task struct tofSpectra { @@ -153,7 +168,7 @@ struct tofSpectra { Configurable usePDGcode{"usePDGcode", false, "choose if include PDG code for MC closure test"}; Configurable enableTPCTOFVsMult{"enableTPCTOFVsMult", false, "Produce TPC-TOF plots vs multiplicity"}; Configurable includeCentralityToTracks{"includeCentralityToTracks", false, "choose if include Centrality to tracks"}; - Configurable min_ITS_nClusters{"min_ITS_nClusters", 5, "minimum number of found ITS clusters"}; + Configurable minITSnClusters{"minITSnClusters", 5, "minimum number of found ITS clusters"}; // Histograms HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -229,7 +244,7 @@ struct tofSpectra { LOG(info) << "\tmaxChi2PerClusterTPC=" << maxChi2PerClusterTPC.value; LOG(info) << "\tminChi2PerClusterTPC=" << minChi2PerClusterTPC.value; LOG(info) << "\tminNCrossedRowsTPC=" << minNCrossedRowsTPC.value; - LOG(info) << "\tmin_ITS_nClusters=" << min_ITS_nClusters.value; + LOG(info) << "\tminITSnClusters=" << minITSnClusters.value; LOG(info) << "\tminTPCNClsFound=" << minTPCNClsFound.value; LOG(info) << "\tmaxChi2PerClusterITS=" << maxChi2PerClusterITS.value; LOG(info) << "\tmaxDcaZ=" << maxDcaZ.value; @@ -239,7 +254,7 @@ struct tofSpectra { LOG(info) << "Customizing track cuts:"; customTrackCuts.SetRequireITSRefit(requireITS.value); customTrackCuts.SetRequireTPCRefit(requireTPC.value); - customTrackCuts.SetMinNClustersITS(min_ITS_nClusters.value); + customTrackCuts.SetMinNClustersITS(minITSnClusters.value); customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); @@ -297,22 +312,39 @@ struct tofSpectra { histos.add("event/vertexz", "", HistType::kTH1D, {vtxZAxis}); histos.add("test_occupancy/event/vertexz", "", HistType::kTH1D, {vtxZAxis}); + enum EEvSelBin { + kEventsRead = 1, + kInelGt0Frac, + kInelGt1Frac, + kEvSelPassed, + kNoITSROFrameBorder1, + kNoITSROFrameBorder2, + kNoSameBunchPileup, + kIsGoodZvtxFT0vsPV, + kIsVertexITSTPC, + kNoTimeFrameBorder, + kInelGt0FracRepeat, + kInelGt1FracRepeat, + kPosZPassed, + kInelGt0Final, + kInelGt1Final + }; auto h = histos.add("evsel", "evsel", HistType::kTH1D, {{20, 0.5, 20.5}}); - h->GetXaxis()->SetBinLabel(1, "Events read"); - h->GetXaxis()->SetBinLabel(2, "INEL>0 (fraction)"); - h->GetXaxis()->SetBinLabel(3, "INEL>1 (fraction)"); - h->GetXaxis()->SetBinLabel(4, "Ev. sel. passed"); - h->GetXaxis()->SetBinLabel(5, "NoITSROFrameBorder"); - 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->GetXaxis()->SetBinLabel(kEventsRead, "Events read"); + h->GetXaxis()->SetBinLabel(kInelGt0Frac, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(kInelGt1Frac, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(kEvSelPassed, "Ev. sel. passed"); + h->GetXaxis()->SetBinLabel(kNoITSROFrameBorder1, "NoITSROFrameBorder"); + h->GetXaxis()->SetBinLabel(kNoITSROFrameBorder2, "NoITSROFrameBorder"); + h->GetXaxis()->SetBinLabel(kNoSameBunchPileup, "NoSameBunchPileup"); + h->GetXaxis()->SetBinLabel(kIsGoodZvtxFT0vsPV, "IsGoodZvtxFT0vsPV"); + h->GetXaxis()->SetBinLabel(kIsVertexITSTPC, "IsVertexITSTPC"); + h->GetXaxis()->SetBinLabel(kNoTimeFrameBorder, "NoTimeFrameBorder"); + h->GetXaxis()->SetBinLabel(kInelGt0FracRepeat, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(kInelGt1FracRepeat, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(kPosZPassed, "posZ passed"); + h->GetXaxis()->SetBinLabel(kInelGt0Final, evselOptions.cfgINELCut.value == EvSelInelGt0Cut ? "INEL>0" : "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(kInelGt1Final, evselOptions.cfgINELCut.value == EvSelInelGt1Cut ? "INEL>1" : "INEL>1 (fraction)"); h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); h->GetXaxis()->SetBinLabel(1, "Tracks read"); @@ -452,6 +484,7 @@ struct tofSpectra { histos.add("Data/cent/neg/pt/its_tof", "neg ITS-TOF", kTH3D, {ptAxis, multAxis, occupancyAxis}); } const AxisSpec nsigmaTPCAxisOccupancy{binsOptions.binsnsigmaTPC, "nsigmaTPC"}; + const AxisSpec nsigmaTOFAxisOccupancy{binsOptions.binsnsigmaTOF, "nsigmaTOF"}; if (doprocessMCclosure) { histos.add("nsigmatpc/mc_closure/pos/pi", "mc_closure dependent pion", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis}); histos.add("nsigmatpc/mc_closure/neg/pi", "mc_closure dependent pion", kTHnSparseD, {ptAxis, nsigmaTPCAxisOccupancy, multAxis}); @@ -561,7 +594,7 @@ 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) { + if (doprocessMCgenRecoEvs) { histos.add("MC/test/RecoEvs/pi/pos/prm/pt/num", "generated MC #pi^{+} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); histos.add("MC/test/RecoEvs/pi/neg/prm/pt/num", "generated MC #pi^{-} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); histos.add("MC/test/RecoEvs/ka/pos/prm/pt/num", "generated MC K^{+} from recons. events", kTHnSparseD, {ptAxis, impParamAxis}); @@ -588,9 +621,10 @@ struct tofSpectra { histos.add("MC/MultiplicityMCINELgt1", "MC multiplicity", kTH1D, {multAxis}); } if (doprocessTrackMCLabels) { - for (int par = 2; par <= 4; par++) { + for (int par = PID::Pion; par <= PID::Proton; par++) { for (int i = 0; i < NpCharge; i++) { - hMCpdg_nsigmaTPC[par - 2][i] = histos.add(Form("test_mclabels/nsigmatpc/%s/%s/pdg_%i", (i < Np) ? "pos" : "neg", pN[par], PDGs[i % Np]), Form("True %s (%i) in %s selection", pTCharge[i], PDGs[i], (i < Np) ? pTCharge[par] : pTCharge[par + Np]), kTH3D, {ptAxis, nsigmaTPCAxisOccupancy, multAxis}); + hMCPdgNsigmaTPC[par - 2][i] = histos.add(Form("test_mclabels/nsigmatpc/%s/%s/pdg_%i", (i < Np) ? "pos" : "neg", pN[par], PDGs[i % Np]), Form("True %s (%i) in %s selection", pTCharge[i], PDGs[i], (i < Np) ? pTCharge[par] : pTCharge[par + Np]), kTH3D, {ptAxis, nsigmaTPCAxisOccupancy, multAxis}); + hMCPdgNsigmaTOF[par - 2][i] = histos.add(Form("test_mclabels/nsigmatof/%s/%s/pdg_%i", (i < Np) ? "pos" : "neg", pN[par], PDGs[i % Np]), Form("True %s (%i) in %s selection", pTCharge[i], PDGs[i], (i < Np) ? pTCharge[par] : pTCharge[par + Np]), kTH3D, {ptAxis, nsigmaTOFAxisOccupancy, multAxis}); } } } @@ -1053,12 +1087,12 @@ struct tofSpectra { } } // Filling DCA info with the TPC+TOF PID - bool isDCAPureSample = (std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.f); - if (track.pt() <= 0.4) { - isDCAPureSample = (nsigmaTPC < 1.f); + bool isDCAPureSample = (std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < DcaMaxCombinedSigma); + if (track.pt() <= DcaTrkPtCut) { + isDCAPureSample = (nsigmaTPC < DcaMaxTPCSigma); } if (isDCAPureSample) { - const bool isInPtRangeForPhi = track.pt() < 1.1f && track.pt() > 0.9f; + const bool isInPtRangeForPhi = track.pt() < DcaPhiPtMax && track.pt() > DcaPhiPtMin; if (enableDCAxyzHistograms) { if (track.sign() > 0) { hDcaXYZ[id]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); @@ -1178,12 +1212,12 @@ struct tofSpectra { histos.fill(HIST("evsel"), 13.f); if (collision.isInelGt0()) { histos.fill(HIST("evsel"), 14.f); - } else if (evselOptions.cfgINELCut == 1) { + } else if (evselOptions.cfgINELCut == EvSelInelGt0Cut) { return false; } if (collision.isInelGt1()) { histos.fill(HIST("evsel"), 15.f); - } else if (evselOptions.cfgINELCut == 2) { + } else if (evselOptions.cfgINELCut == EvSelInelGt1Cut) { return false; } histos.fill(HIST("event/vertexz"), collision.posZ()); @@ -1406,13 +1440,17 @@ struct tofSpectra { } return true; } - + // constants for mismatch track + static constexpr int ItsMaxLayer = 7; // bit runs from 0-6 + static constexpr int TrdBit = 10; + static constexpr int TofBit = 11; + static constexpr int GlobalMismatchBit = 15; template bool isMismatchedTrack(const ParticleType& track, const int detector) { switch (detector) { case 0: // ITS - for (int i = 0; i < 7; i++) { + for (int i = 0; i < ItsMaxLayer; i++) { if (track.mcMask() & 1 << i) { return true; } @@ -1420,26 +1458,26 @@ struct tofSpectra { return false; break; case 1: // TPC - for (int i = 7; i < 10; i++) { + for (int i = ItsMaxLayer; i < TrdBit; i++) { if (track.mcMask() & 1 << i) { return true; } } break; case 2: // TRD - if (track.mcMask() & 1 << 10) { + if (track.mcMask() & 1 << TrdBit) { return true; } return false; break; case 3: // TOF - if (track.mcMask() & 1 << 11) { + if (track.mcMask() & 1 << TofBit) { return true; } return false; break; default: // All - if (track.mcMask() & 1 << 15) { + if (track.mcMask() & 1 << GlobalMismatchBit) { return true; } return false; @@ -1506,9 +1544,9 @@ struct tofSpectra { if (mcParticle.isPhysicalPrimary()) { if (isTPCPion && rapidityPi <= trkselOptions.cfgCutY) { if (usePDGcode) { - if (pdgCode == 211) { + if (pdgCode == kPiPlus) { histos.fill(HIST("nsigmatpc/mc_closure/pos/pi"), track.pt(), nsigmaTPCPi, multiplicity); - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { histos.fill(HIST("nsigmatpc/mc_closure/neg/pi"), track.pt(), nsigmaTPCPi, multiplicity); } } else { @@ -1518,9 +1556,9 @@ struct tofSpectra { } if (isTPCKaon && rapidityKa <= trkselOptions.cfgCutY) { if (usePDGcode) { - if (pdgCode == 321) { + if (pdgCode == kKPlus) { histos.fill(HIST("nsigmatpc/mc_closure/pos/ka"), track.pt(), nsigmaTPCKa, multiplicity); - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { histos.fill(HIST("nsigmatpc/mc_closure/neg/ka"), track.pt(), nsigmaTPCKa, multiplicity); } } else { @@ -1530,9 +1568,9 @@ struct tofSpectra { } if (isTPCProton && rapidityPr <= trkselOptions.cfgCutY) { if (usePDGcode) { - if (pdgCode == 2212) { + if (pdgCode == kProton) { histos.fill(HIST("nsigmatpc/mc_closure/pos/pr"), track.pt(), nsigmaTPCPr, multiplicity); - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { histos.fill(HIST("nsigmatpc/mc_closure/neg/pr"), track.pt(), nsigmaTPCPr, multiplicity); } } else { @@ -1544,9 +1582,9 @@ struct tofSpectra { // TOF Selection and Histogram Filling if (isTOFPion && rapidityPi <= trkselOptions.cfgCutY) { if (usePDGcode) { - if (pdgCode == 211) { + if (pdgCode == kPiPlus) { histos.fill(HIST("nsigmatof/mc_closure/pos/pi"), track.pt(), nsigmaTOFPi, multiplicity); - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { histos.fill(HIST("nsigmatof/mc_closure/neg/pi"), track.pt(), nsigmaTOFPi, multiplicity); } } else { @@ -1556,9 +1594,9 @@ struct tofSpectra { } if (isTOFKaon && rapidityKa <= trkselOptions.cfgCutY) { if (usePDGcode) { - if (pdgCode == 321) { + if (pdgCode == kKPlus) { histos.fill(HIST("nsigmatof/mc_closure/pos/ka"), track.pt(), nsigmaTOFKa, multiplicity); - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { histos.fill(HIST("nsigmatof/mc_closure/neg/ka"), track.pt(), nsigmaTOFKa, multiplicity); } } else { @@ -1568,9 +1606,9 @@ struct tofSpectra { } if (isTOFProton && rapidityPr <= trkselOptions.cfgCutY) { if (usePDGcode) { - if (pdgCode == 2212) { + if (pdgCode == kProton) { histos.fill(HIST("nsigmatof/mc_closure/pos/pr"), track.pt(), nsigmaTOFPr, multiplicity); - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { histos.fill(HIST("nsigmatof/mc_closure/neg/pr"), track.pt(), nsigmaTOFPr, multiplicity); } } else { @@ -1610,7 +1648,7 @@ struct tofSpectra { for (const auto& track : tracks) { // Track selection criteria /* if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC || track.tpcChi2NCl() > maxChi2PerClusterTPC || track.tpcChi2NCl() > maxChi2PerClusterTPC || - track.itsChi2NCl() > maxChi2PerClusterITS || std::abs(track.dcaXY()) > maxDcaXYFactor.value * (0.0105f + 0.0350f / pow(track.pt(), 1.1f)) || std::abs(track.dcaZ()) > maxDcaZ.value || track.eta() < trkselOptions.cfgCutEtaMin || track.eta() > trkselOptions.cfgCutEtaMax || track.tpcCrossedRowsOverFindableCls() < minNCrossedRowsOverFindableClustersTPC || track.tpcNClsFound() < minTPCNClsFound || + track.itsChi2NCl() > maxChi2PerClusterITS || std::abs(track.dcaXY()) > maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)) || std::abs(track.dcaZ()) > maxDcaZ.value || track.eta() < trkselOptions.cfgCutEtaMin || track.eta() > trkselOptions.cfgCutEtaMax || track.tpcCrossedRowsOverFindableCls() < minNCrossedRowsOverFindableClustersTPC || track.tpcNClsFound() < minTPCNClsFound || !(o2::aod::track::ITSrefit) || !(o2::aod::track::TPCrefit)) { continue; }*/ @@ -1723,7 +1761,7 @@ struct tofSpectra { } // end of the process function PROCESS_SWITCH(tofSpectra, processDerived, "Derived data processor", false); -#define makeProcessFunction(processorName, inputPid, particleId, isFull, tofTable, tpcTable) \ +#define MAKE_PROCESS_FUNCTION(processorName, inputPid, particleId, isFull, tofTable, tpcTable) \ void process##processorName##inputPid(CollisionCandidates::iterator const& collision, \ soa::Join float getMultiplicity(const CollisionType& collision) @@ -1850,39 +1888,39 @@ struct tofSpectra { template bool isParticleEnabled() { - if constexpr (id == 0 || id == Np) { + if constexpr (id == PID::Electron || id == Np) { if (doprocessFullEl == true || doprocessLfFullEl == true) { return true; } - } else if constexpr (id == 1 || id == Np + 1) { + } else if constexpr (id == PID::Muon || id == Np + PID::Muon) { if (doprocessFullMu == true || doprocessLfFullMu == true) { return true; } - } else if constexpr (id == 2 || id == Np + 2) { + } else if constexpr (id == PID::Pion || id == Np + PID::Pion) { if (doprocessFullPi == true || doprocessLfFullPi == true) { return true; } - } else if constexpr (id == 3 || id == Np + 3) { + } else if constexpr (id == PID::Kaon || id == Np + PID::Kaon) { if (doprocessFullKa == true || doprocessLfFullKa == true) { return true; } - } else if constexpr (id == 4 || id == Np + 4) { + } else if constexpr (id == PID::Proton || id == Np + PID::Proton) { if (doprocessFullPr == true || doprocessLfFullPr == true) { return true; } - } else if constexpr (id == 5 || id == Np + 5) { + } else if constexpr (id == PID::Deuteron || id == Np + PID::Deuteron) { if (doprocessFullDe == true || doprocessLfFullDe == true) { return true; } - } else if constexpr (id == 6 || id == Np + 6) { + } else if constexpr (id == PID::Triton || id == Np + PID::Triton) { if (doprocessFullTr == true || doprocessLfFullTr == true) { return true; } - } else if constexpr (id == 7 || id == Np + 7) { + } else if constexpr (id == PID::Helium3 || id == Np + PID::Helium3) { if (doprocessFullHe == true || doprocessLfFullHe == true) { return true; } - } else if constexpr (id == 8 || id == Np + 8) { + } else if constexpr (id == PID::Alpha || id == Np + PID::Alpha) { if (doprocessFullAl == true || doprocessLfFullAl == true) { return true; } @@ -1894,10 +1932,10 @@ struct tofSpectra { using RecoMCCollisions = soa::Join; // RD template - void fillTrackHistograms_MC(TrackType const& track, - ParticleType::iterator const& mcParticle, - RecoMCCollisions::iterator const& collision, - ParticleType const& mcParticles) + void fillTrackHistogramsMC(TrackType const& track, + ParticleType::iterator const& mcParticle, + RecoMCCollisions::iterator const& collision, + ParticleType const& mcParticles) { if (!isParticleEnabled()) { // Check if the particle is enabled return; @@ -1928,9 +1966,9 @@ struct tofSpectra { const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); // Filling DCA info with the TPC+TOF PID - bool isDCAPureSample = (std::sqrt(nsigmaTOFKa * nsigmaTOFKa + nsigmaTPCKa * nsigmaTPCKa) < 2.f); - if (track.pt() <= 0.4) { - isDCAPureSample = (nsigmaTPCKa < 1.f); + bool isDCAPureSample = (std::sqrt(nsigmaTOFKa * nsigmaTOFKa + nsigmaTPCKa * nsigmaTPCKa) < DcaMaxCombinedSigma); + if (track.pt() <= DcaTrkPtCut) { + isDCAPureSample = (nsigmaTPCKa < DcaMaxTPCSigma); } if (isDCAPureSample) { @@ -1939,8 +1977,8 @@ struct tofSpectra { hDcaZMC[i]->Fill(track.pt(), track.dcaZ()); } - if (!mcParticle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if (mcParticle.getProcess() == 4) { // Particles from decay + if (!mcParticle.isPhysicalPrimary()) { // Secondaries (weak decays and material) + if (mcParticle.getProcess() == kPDecay) { // Particles from decay if (enableDCAxyzHistograms) { hDcaXYZStr[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); } else { @@ -1990,7 +2028,7 @@ struct tofSpectra { const int charmOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, false); for (const auto& mother : mcParticle.template mothers_as()) { const int motherPdgCode = std::abs(mother.pdgCode()); - if (motherPdgCode == 421) { + if (motherPdgCode == kD0) { IsD0Mother = true; } if (charmOrigin == RecoDecay::OriginType::NonPrompt) { @@ -2047,7 +2085,7 @@ struct tofSpectra { } } else { if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // particles from decay histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); } else { histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); @@ -2059,7 +2097,7 @@ struct tofSpectra { if ((collision.has_mcCollision() && (mcParticle.mcCollisionId() != collision.mcCollisionId())) || !collision.has_mcCollision()) { if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // particles from decay hDcaXYWrongCollisionStr[i]->Fill(track.pt(), track.dcaXY()); } else { hDcaXYWrongCollisionMat[i]->Fill(track.pt(), track.dcaXY()); @@ -2089,8 +2127,8 @@ struct tofSpectra { const bool isKaonTOF = std::abs(nsigmaTOFKa) < trkselOptions.cfgCutNsigma; const bool isProtonTOF = std::abs(nsigmaTOFPr) < trkselOptions.cfgCutNsigma; - if (!mcParticle.isPhysicalPrimary()) { // Is not physical primary - if (mcParticle.getProcess() == 4) { // Is from decay + if (!mcParticle.isPhysicalPrimary()) { // Is not physical primary + if (mcParticle.getProcess() == kPDecay) { // Is from decay if (includeCentralityMC) { if (includeCentralityMC) { histos.fill(HIST(hpt_num_str[i]), track.pt(), multiplicity, track.dcaXY()); @@ -2129,11 +2167,11 @@ struct tofSpectra { histos.fill(HIST(hpt_num_prm[i]), track.pt(), multiplicity); } if (isPionTPC || isKaonTPC || isProtonTPC) { - if (pdgCode == 2212) { + if (pdgCode == kProton) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pr/pos/prm/pt/num"), track.pt(), impParam); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // particles from decay histos.fill(HIST("MC/withPID/pr/pos/prm/pt/num_str"), track.pt(), impParam); } else { histos.fill(HIST("MC/withPID/pr/pos/prm/pt/num_mat"), track.pt(), impParam); @@ -2142,18 +2180,18 @@ struct tofSpectra { } else { histos.fill(HIST("MC/withPID/pr/pos/prm/pt/num"), track.pt(), multiplicity); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // particles from decay histos.fill(HIST("MC/withPID/pr/pos/prm/pt/num_str"), track.pt(), multiplicity); } else { histos.fill(HIST("MC/withPID/pr/pos/prm/pt/num_mat"), track.pt(), multiplicity); } } } - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pr/neg/prm/pt/num"), track.pt(), impParam); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // particles from decay histos.fill(HIST("MC/withPID/pr/neg/prm/pt/num_str"), track.pt(), impParam); } else { histos.fill(HIST("MC/withPID/pr/neg/prm/pt/num_mat"), track.pt(), impParam); @@ -2162,18 +2200,18 @@ struct tofSpectra { } else { histos.fill(HIST("MC/withPID/pr/neg/prm/pt/num"), track.pt(), multiplicity); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // particles from decay histos.fill(HIST("MC/withPID/pr/neg/prm/pt/num_str"), track.pt(), multiplicity); } else { histos.fill(HIST("MC/withPID/pr/neg/prm/pt/num_mat"), track.pt(), multiplicity); } } } - } else if (pdgCode == 211) { + } else if (pdgCode == kPiPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pi/pos/prm/pt/num"), track.pt(), impParam); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/pi/pos/prm/pt/num_str"), track.pt(), impParam); } else { histos.fill(HIST("MC/withPID/pi/pos/prm/pt/num_mat"), track.pt(), impParam); @@ -2182,18 +2220,18 @@ struct tofSpectra { } else { histos.fill(HIST("MC/withPID/pi/pos/prm/pt/num"), track.pt(), multiplicity); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/pi/pos/prm/pt/num_str"), track.pt(), multiplicity); } else { histos.fill(HIST("MC/withPID/pi/pos/prm/pt/num_mat"), track.pt(), multiplicity); } } } - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pi/neg/prm/pt/num"), track.pt(), impParam); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/pi/neg/prm/pt/num_str"), track.pt(), impParam); } else { histos.fill(HIST("MC/withPID/pi/neg/prm/pt/num_mat"), track.pt(), impParam); @@ -2202,18 +2240,18 @@ struct tofSpectra { } else { histos.fill(HIST("MC/withPID/pi/neg/prm/pt/num"), track.pt(), multiplicity); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/pi/neg/prm/pt/num_str"), track.pt(), multiplicity); } else { histos.fill(HIST("MC/withPID/pi/neg/prm/pt/num_mat"), track.pt(), multiplicity); } } } - } else if (pdgCode == 321) { + } else if (pdgCode == kKPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/ka/pos/prm/pt/num"), track.pt(), impParam); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/ka/pos/prm/pt/num_str"), track.pt(), impParam); } else { histos.fill(HIST("MC/withPID/ka/pos/prm/pt/num_mat"), track.pt(), impParam); @@ -2222,18 +2260,18 @@ struct tofSpectra { } else { histos.fill(HIST("MC/withPID/ka/pos/prm/pt/num"), track.pt(), multiplicity); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/ka/pos/prm/pt/num_str"), track.pt(), multiplicity); } else { histos.fill(HIST("MC/withPID/ka/pos/prm/pt/num_mat"), track.pt(), multiplicity); } } } - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/ka/neg/prm/pt/num"), track.pt(), impParam); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/ka/neg/prm/pt/num_str"), track.pt(), impParam); } else { histos.fill(HIST("MC/withPID/ka/neg/prm/pt/num_mat"), track.pt(), impParam); @@ -2242,7 +2280,7 @@ struct tofSpectra { } else { histos.fill(HIST("MC/withPID/ka/neg/prm/pt/num"), track.pt(), multiplicity); if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST("MC/withPID/ka/neg/prm/pt/num_str"), track.pt(), multiplicity); } else { histos.fill(HIST("MC/withPID/ka/neg/prm/pt/num_mat"), track.pt(), multiplicity); @@ -2266,7 +2304,7 @@ struct tofSpectra { if (track.hasTOF()) { if (isPionTOF || isKaonTOF || isProtonTOF) { // Proton (positive) - if (pdgCode == 2212) { + if (pdgCode == kProton) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pr/pos/prm/pt/numtof"), track.pt(), impParam); } else { @@ -2280,7 +2318,7 @@ struct tofSpectra { histos.fill(HIST("MC/withPID/pr/pos/prm/pt/numtof_matched"), track.pt(), multiplicity); } } - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pr/neg/prm/pt/numtof"), track.pt(), impParam); } else { @@ -2293,7 +2331,7 @@ struct tofSpectra { histos.fill(HIST("MC/withPID/pr/neg/prm/pt/numtof_matched"), track.pt(), multiplicity); } } - } else if (pdgCode == 211) { + } else if (pdgCode == kPiPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pi/pos/prm/pt/numtof"), track.pt(), impParam); } else { @@ -2307,7 +2345,7 @@ struct tofSpectra { histos.fill(HIST("MC/withPID/pi/pos/prm/pt/numtof_matched"), track.pt(), multiplicity); } } - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/pi/neg/prm/pt/numtof"), track.pt(), impParam); } else { @@ -2321,7 +2359,7 @@ struct tofSpectra { histos.fill(HIST("MC/withPID/pi/neg/prm/pt/numtof_matched"), track.pt(), multiplicity); } } - } else if (pdgCode == 321) { + } else if (pdgCode == kKPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/ka/pos/prm/pt/numtof"), track.pt(), impParam); } else { @@ -2335,7 +2373,7 @@ struct tofSpectra { histos.fill(HIST("MC/withPID/ka/pos/prm/pt/numtof_matched"), track.pt(), multiplicity); } } - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { if (isImpactParam) { histos.fill(HIST("MC/withPID/ka/neg/prm/pt/numtof"), track.pt(), impParam); } else { @@ -2408,7 +2446,7 @@ struct tofSpectra { } template - void fillParticleHistograms_MC(const float multiplicity, ParticleType const& mcParticle) + void fillParticleHistogramsMC(const float multiplicity, ParticleType const& mcParticle) { if (!isParticleEnabled()) { // Check if the particle is enabled return; @@ -2419,7 +2457,7 @@ struct tofSpectra { } if (!mcParticle.isPhysicalPrimary()) { - if (mcParticle.getProcess() == 4) { + if (mcParticle.getProcess() == kPDecay) { // Particles from decay histos.fill(HIST(hpt_den_str[i]), mcParticle.pt(), multiplicity); } else { histos.fill(HIST(hpt_den_mat[i]), mcParticle.pt(), multiplicity); @@ -2434,7 +2472,7 @@ struct tofSpectra { } template - void fillParticleHistograms_MCRecoEvs(ParticleType const& mcParticle, RecoMCCollisions::iterator const& collision) + void fillParticleHistogramsMCRecoEvs(ParticleType const& mcParticle, RecoMCCollisions::iterator const& collision) { if (!isParticleEnabled()) { // Check if the particle is enabled return; @@ -2492,7 +2530,7 @@ struct tofSpectra { } template - void fillParticleHistograms_MCGenEvs(ParticleType const& mcParticle, GenMCCollisions::iterator const& mcCollision) + void fillParticleHistogramsMCGenEvs(ParticleType const& mcParticle, GenMCCollisions::iterator const& mcCollision) { if (!isParticleEnabled()) { // Check if the particle is enabled @@ -2556,7 +2594,7 @@ struct tofSpectra { const auto& mcParticle = track.mcParticle(); static_for<0, 17>([&](auto i) { - fillTrackHistograms_MC(track, mcParticle, track.collision_as(), mcParticles); + fillTrackHistogramsMC(track, mcParticle, track.collision_as(), mcParticles); }); } if (includeCentralityMC) { @@ -2573,7 +2611,7 @@ struct tofSpectra { continue; } static_for<0, 17>([&](auto i) { - fillParticleHistograms_MC(multiplicity, mcParticle); + fillParticleHistogramsMC(multiplicity, mcParticle); }); } } @@ -2587,7 +2625,7 @@ struct tofSpectra { const float multiplicity = getMultiplicityMC(mcCollision); static_for<0, 17>([&](auto i) { - fillParticleHistograms_MC(multiplicity, mcParticle); + fillParticleHistogramsMC(multiplicity, mcParticle); }); } } @@ -2617,7 +2655,7 @@ struct tofSpectra { continue; } static_for<0, 17>([&](auto i) { - fillParticleHistograms_MCRecoEvs(mcParticle, collision); + fillParticleHistogramsMCRecoEvs(mcParticle, collision); }); } } @@ -2631,13 +2669,13 @@ struct tofSpectra { const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); bool hasParticleInFT0C = false; bool hasParticleInFT0A = false; - if (evselOptions.cfgINELCut.value == 1) { + if (evselOptions.cfgINELCut.value == EvSelInelGt0Cut) { if (!o2::pwglf::isINELgt0mc(particlesInCollision, pdgDB)) { continue; } } histos.fill(HIST("MC/MultiplicityMCINELgt0"), getMultiplicityMC(mcCollision)); - if (evselOptions.cfgINELCut.value == 2) { + if (evselOptions.cfgINELCut.value == EvSelInelGt1Cut) { if (!o2::pwglf::isINELgt1mc(particlesInCollision, pdgDB)) { continue; } @@ -2648,7 +2686,7 @@ struct tofSpectra { continue; } static_for<0, 17>([&](auto i) { - fillParticleHistograms_MCGenEvs(mcParticle, mcCollision); + fillParticleHistogramsMCGenEvs(mcParticle, mcCollision); }); } if (mcCollision.isInelGt0()) { @@ -2679,29 +2717,29 @@ struct tofSpectra { continue; } - if (pdgCode == 2212) { + if (pdgCode == kProton) { histos.fill(HIST("MC/test/pr/pos/prm/pt/den"), pt, multiplicity); - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { histos.fill(HIST("MC/test/pr/neg/prm/pt/den"), pt, multiplicity); - } else if (pdgCode == 211) { + } else if (pdgCode == kPiPlus) { histos.fill(HIST("MC/test/pi/pos/prm/pt/den"), pt, multiplicity); - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { histos.fill(HIST("MC/test/pi/neg/prm/pt/den"), pt, multiplicity); - } else if (pdgCode == 321) { + } else if (pdgCode == kKPlus) { histos.fill(HIST("MC/test/ka/pos/prm/pt/den"), pt, multiplicity); - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { histos.fill(HIST("MC/test/ka/neg/prm/pt/den"), pt, multiplicity); } } } PROCESS_SWITCH(tofSpectra, processMCgen, "process generated MC", false); - void processMCgen_RecoEvs(soa::Join const& tracks, - aod::McTrackLabels const& mcTrackLabels, - GenMCCollisions const&, - RecoMCCollisions const& collisions, - aod::McParticles const& mcParticles) + void processMCgenRecoEvs(soa::Join const& tracks, + aod::McTrackLabels const& mcTrackLabels, + GenMCCollisions const&, + RecoMCCollisions const& collisions, + aod::McParticles const& mcParticles) { for (const auto& collision : collisions) { if (!collision.has_mcCollision()) { @@ -2714,15 +2752,15 @@ struct tofSpectra { const float multiplicity = mcCollision.impactParameter(); for (const auto& track : tracks) { - if (track.tpcNClsCrossedRows() < 70 || - track.tpcChi2NCl() > 4 || - track.tpcChi2NCl() < 0.5 || - track.itsChi2NCl() > 36 || - std::abs(track.dcaXY()) > 0.05 || - std::abs(track.dcaZ()) > 2.0 || - std::abs(track.eta()) > 0.8 || - track.tpcCrossedRowsOverFindableCls() < 0.8 || - track.tpcNClsFound() < 100 || + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC || + track.tpcChi2NCl() > maxChi2PerClusterTPC || + track.tpcChi2NCl() < minChi2PerClusterTPC || + track.itsChi2NCl() > maxChi2PerClusterITS || + !passesDCAxyCut(track) || + std::abs(track.dcaZ()) > maxDcaZ || + std::abs(track.eta()) > trkselOptions.cfgCutEtaMax.value || + track.tpcCrossedRowsOverFindableCls() < minNCrossedRowsOverFindableClustersTPC || + track.tpcNClsFound() < minTPCNClsFound || !(o2::aod::track::TPCrefit) || !(o2::aod::track::ITSrefit)) { continue; @@ -2760,40 +2798,40 @@ struct tofSpectra { const bool isProtonTOF = track.hasTOF() && std::abs(nsigmaTOFPr) < trkselOptions.cfgCutNsigma; if (isPionTPC || isKaonTPC || isProtonTPC) { - if (pdgCode == 2212) { + if (pdgCode == kProton) { histos.fill(HIST("MC/test/RecoEvs/pr/pos/prm/pt/num"), pt, multiplicity); - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { histos.fill(HIST("MC/test/RecoEvs/pr/neg/prm/pt/num"), pt, multiplicity); - } else if (pdgCode == 211) { + } else if (pdgCode == kPiPlus) { histos.fill(HIST("MC/test/RecoEvs/pi/pos/prm/pt/num"), pt, multiplicity); - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { histos.fill(HIST("MC/test/RecoEvs/pi/neg/prm/pt/num"), pt, multiplicity); - } else if (pdgCode == 321) { + } else if (pdgCode == kKPlus) { histos.fill(HIST("MC/test/RecoEvs/ka/pos/prm/pt/num"), pt, multiplicity); - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { histos.fill(HIST("MC/test/RecoEvs/ka/neg/prm/pt/num"), pt, multiplicity); } } if (isPionTOF || isKaonTOF || isProtonTOF) { - if (pdgCode == 2212) { + if (pdgCode == kProton) { histos.fill(HIST("MC/test/RecoEvs/pr/pos/prm/pt/numtof"), pt, multiplicity); - } else if (pdgCode == -2212) { + } else if (pdgCode == -kProton) { histos.fill(HIST("MC/test/RecoEvs/pr/neg/prm/pt/numtof"), pt, multiplicity); - } else if (pdgCode == 211) { + } else if (pdgCode == kPiPlus) { histos.fill(HIST("MC/test/RecoEvs/pi/pos/prm/pt/numtof"), pt, multiplicity); - } else if (pdgCode == -211) { + } else if (pdgCode == -kPiPlus) { histos.fill(HIST("MC/test/RecoEvs/pi/neg/prm/pt/numtof"), pt, multiplicity); - } else if (pdgCode == 321) { + } else if (pdgCode == kKPlus) { histos.fill(HIST("MC/test/RecoEvs/ka/pos/prm/pt/numtof"), pt, multiplicity); - } else if (pdgCode == -321) { + } else if (pdgCode == -kKPlus) { histos.fill(HIST("MC/test/RecoEvs/ka/neg/prm/pt/numtof"), pt, multiplicity); } } } } } - PROCESS_SWITCH(tofSpectra, processMCgen_RecoEvs, "process generated MC (reconstructed events)", false); + PROCESS_SWITCH(tofSpectra, processMCgenRecoEvs, "process generated MC (reconstructed events)", false); void processTrackMCLabels(CollisionCandidates::iterator const& collisions, soa::Join([&](auto par) { + static_for([&](auto par) { // for pi, K, p only const auto& nsigmaTPCpar = o2::aod::pidutils::tpcNSigma(track); + const auto& nsigmaTOFpar = o2::aod::pidutils::tofNSigma(track); bool isTPCpar = std::abs(nsigmaTPCpar) < trkselOptions.cfgCutNsigma; // Precompute rapidity values to avoid redundant calculations double rapiditypar = std::abs(track.rapidity(PID::getMass(par))); // TPC Selection and histogram filling if (isTPCpar && rapiditypar <= trkselOptions.cfgCutY) { - static_for<0, 17>([&](auto i) { + static_for<0, NpCharge - 1>([&](auto i) { if (pdgCode == PDGs[i]) { - hMCpdg_nsigmaTPC[par - 2][i]->Fill(track.pt(), nsigmaTPCpar, multiplicity); + hMCPdgNsigmaTPC[par - 2][i]->Fill(track.pt(), nsigmaTPCpar, multiplicity); + hMCPdgNsigmaTOF[par - 2][i]->Fill(track.pt(), nsigmaTOFpar, multiplicity); } }); } diff --git a/PWGLF/Tasks/QC/CMakeLists.txt b/PWGLF/Tasks/QC/CMakeLists.txt index 319d21d9d96..e1618a43d06 100644 --- a/PWGLF/Tasks/QC/CMakeLists.txt +++ b/PWGLF/Tasks/QC/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(v0cascades-qa SOURCES v0cascadesqa.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(track-checks diff --git a/PWGLF/Tasks/QC/findableStudy.cxx b/PWGLF/Tasks/QC/findableStudy.cxx index 512f5dd6b4d..dc67b02dc40 100644 --- a/PWGLF/Tasks/QC/findableStudy.cxx +++ b/PWGLF/Tasks/QC/findableStudy.cxx @@ -62,7 +62,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using recoStraCollisions = soa::Join; +using recoStraCollisions = soa::Join; using reconstructedV0s = soa::Join; using reconstructedV0sNoMC = soa::Join; @@ -261,7 +261,7 @@ struct findableStudy { bool hasBeenFound = false; int nCandidatesWithTPC = 0; - for (auto& recv0 : recv0s) { + for (const auto& recv0 : recv0s) { if (recv0.v0Type() != 1) continue; // skip anything other than a standard V0 diff --git a/PWGLF/Tasks/QC/hypertriton3bodyQa.cxx b/PWGLF/Tasks/QC/hypertriton3bodyQa.cxx index c0b2c1dfd55..1820bc935da 100644 --- a/PWGLF/Tasks/QC/hypertriton3bodyQa.cxx +++ b/PWGLF/Tasks/QC/hypertriton3bodyQa.cxx @@ -22,7 +22,8 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" diff --git a/PWGLF/Tasks/QC/v0cascadesqa.cxx b/PWGLF/Tasks/QC/v0cascadesqa.cxx index c22ac235cfd..962687d2869 100644 --- a/PWGLF/Tasks/QC/v0cascadesqa.cxx +++ b/PWGLF/Tasks/QC/v0cascadesqa.cxx @@ -9,17 +9,22 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // +/// \file v0cascadesqa.cxx /// \brief QA task for V0s and Cascades /// +/// /// In case of questions please write to: /// \author Aimeric Landou (aimeric.landou@cern.ch) /// \author Chiara De Martin (chiara.de.martin@cern.ch) /// \author Francesca Ercolessi (francesca.ercolessi@cern.ch) +/// \author Romain Schotter (romain.schotter@cern.ch) #include // #include +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" @@ -36,200 +41,393 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" +#include + +using namespace o2::aod::rctsel; + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using MyTracks = soa::Join; -using MyTracksMC = soa::Join; +enum ParticleType : uint8_t { kPhoton = 0, + kK0s, + kLambda, + kAntiLambda, + kXiM, + kXiP, + kOmegaM, + kOmegaP }; + // using DaughterTracks = soa::Join; -using DaughterTracks = soa::Join; +using DaughterTracks = soa::Join; struct v0cascadesQA { + HistogramRegistry histos_event{"histos_event", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histos_V0{"histos_V0", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histos_Casc{"histos_Casc", {}, OutputObjHandlingPolicy::AnalysisObject}; + // configurable event properties - Configurable isMC{"isMC", false, "does the data have MC info"}; - Configurable sel8{"sel8", 0, "Apply sel8 event selection"}; - Configurable doextraanalysis{"doextraanalysis", 0, "Add extra histograms"}; - - // configurable track properties - Configurable checkDauTPC{"checkDauTPC", false, "check if daughter tracks have TPC match"}; - - // configurable binning of histograms - ConfigurableAxis binPt{"binPt", {100, 0.0f, 10.0f}, ""}; - ConfigurableAxis binPtsmall{"binPtsmall", {50, 0.0f, 10.0f}, ""}; - ConfigurableAxis binV0CosPA{"binV0CosPA", {200, 0.8f, 1.0f}, ""}; - ConfigurableAxis binV0PA{"binV0PA", {1000, 0.f, 1.0f}, ""}; - ConfigurableAxis binV0Radius{"binV0Radius", {100, 0.0f, 10.0f}, ""}; - ConfigurableAxis binV0DecayLength{"binV0DecayLength", {100, 0.0f, 10.0f}, ""}; - ConfigurableAxis binV0DCANegToPV{"binV0DCANegToPV", {100, -1.0f, 1.0f}, ""}; - ConfigurableAxis binV0DCAPosToPV{"binV0DCAPosToPV", {100, -1.0f, 1.0f}, ""}; - ConfigurableAxis binV0DCAV0Dau{"binV0DCAV0Dau", {55, 0.0f, 2.20f}, ""}; - ConfigurableAxis binCtauK0s{"binCtauK0s", {65, 0.0f, 13.0f}, ""}; - ConfigurableAxis binCtauLambda{"binCtauLambda", {100, 0.0f, 40.0f}, ""}; - ConfigurableAxis binCtauAntiLambda{"binCtauAntiLambda", {100, 0.0f, 40.0f}, ""}; - ConfigurableAxis binDecayLengthK0s{"binDecayLengthK0s", {100, 0.0f, 40.0f}, ""}; - ConfigurableAxis binDecayLengthLambda{"binDecayLengthLambda", {100, 0.0f, 80.0f}, ""}; - ConfigurableAxis binDecayLengthAntiLambda{"binDecayLengthAntiLambda", {100, 0.0f, 80.0f}, ""}; - ConfigurableAxis binV0DCAV0ToPVK0S{"binV0DCAV0ToPVK0S", {250, 0.0f, 0.25f}, ""}; - ConfigurableAxis binV0DCAV0ToPVLambda{"binV0DCAV0ToPVLambda", {250, 0.0f, 0.25f}, ""}; - ConfigurableAxis binV0DCAV0ToPVAntiLambda{"binV0DCAV0ToPVAntiLambda", {250, 0.0f, 0.25f}, ""}; - ConfigurableAxis binInvMassK0S{"binInvMassK0S", {200, 0.4f, 0.6f}, ""}; - ConfigurableAxis binInvMassLambda{"binInvMassLambda", {200, 1.07f, 1.17f}, ""}; - ConfigurableAxis binInvMassAntiLambda{"binInvMassAntiLambda", {200, 1.07f, 1.17f}, ""}; - ConfigurableAxis binResponsePionFromLambda{"binResponsePionFromLambda", {200, -20.f, 20.f}, ""}; - ConfigurableAxis binResponseProtonFromLambda{"binResponseProtonFromLambda", {200, -20.f, 20.f}, ""}; - ConfigurableAxis binEtaFlag{"binEtaFlag", {3, -1.5f, 1.5f}, ""}; - 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 binRadius{"binRadius", {100, 0.0f, 50.0f}, ""}; - ConfigurableAxis binRadiussmall{"binRadiussmall", {30, 0.0f, 30.0f}, ""}; - ConfigurableAxis binITSMapDaughters{"binITSMapDaughters", {8, -0.5f, 7.5f}, ""}; - ConfigurableAxis binInvMassCasc{"binInvMassCasc", {1000, 0.f, 1.0f}, ""}; + bool isMC = false; + Configurable doextraanalysis{"doextraanalysis", false, "Add extra histograms"}; + Configurable doTreatPiToMuon{"doTreatPiToMuon", true, "Take pi decay into muon into account in MC"}; + Configurable irSource{"irSource", "", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; + + struct : ConfigurableGroup { + std::string prefix = "eventSelections"; // JSON group name + Configurable requireSel8{"requireSel8", true, "require sel8 event selection"}; + Configurable requireTriggerTVX{"requireTriggerTVX", true, "require FT0 vertex (acceptable FT0C-FT0A time difference) at trigger level"}; + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border (Run 3 only)"}; + Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border (Run 3 only)"}; + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track (Run 3 only)"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", false, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference (Run 3 only)"}; + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "require events with at least one of vertex contributors matched to TOF (Run 3 only)"}; + Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", false, "require events with at least one of vertex contributors matched to TRD (Run 3 only)"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", false, "reject collisions in case of pileup with another collision in the same foundBC (Run 3 only)"}; + Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds or mult above a certain threshold in -4 - -2 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds (Run 3 only)"}; + Configurable requireNoCollInTimeRangeNarrow{"requireNoCollInTimeRangeNarrow", false, "reject collisions corrupted by the cannibalism, with other collisions within +/- 2 microseconds (Run 3 only)"}; + Configurable requireNoCollInROFStd{"requireNoCollInROFStd", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF with mult. above a certain threshold (Run 3 only)"}; + Configurable requireNoCollInROFStrict{"requireNoCollInROFStrict", false, "reject collisions corrupted by the cannibalism, with other collisions within the same ITS ROF (Run 3 only)"}; + Configurable requireINEL0{"requireINEL0", false, "require INEL>0 event selection"}; + Configurable requireINEL1{"requireINEL1", false, "require INEL>1 event selection"}; + + Configurable maxZVtxPosition{"maxZVtxPosition", 10., "max Z vtx position"}; + + Configurable useEvtSelInDenomEff{"useEvtSelInDenomEff", false, "Consider event selections in the recoed <-> gen collision association for the denominator (or numerator) of the acc. x eff. (or signal loss)?"}; + Configurable applyZVtxSelOnMCPV{"applyZVtxSelOnMCPV", false, "Apply Z-vtx cut on the PV of the generated collision?"}; + Configurable useFT0CbasedOccupancy{"useFT0CbasedOccupancy", false, "Use sum of FT0-C amplitudes for estimating occupancy? (if not, use track-based definition)"}; + // fast check on occupancy + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + // fast check on interaction rate + Configurable minIR{"minIR", -1, "minimum IR collisions"}; + Configurable maxIR{"maxIR", -1, "maximum IR collisions"}; + } eventSelections; + + struct : ConfigurableGroup { + std::string prefix = "rctConfigurations"; // JSON group name + Configurable cfgRCTLabel{"cfgRCTLabel", "", "Which detector condition requirements? (CBT, CBT_hadronPID, CBT_electronPID, CBT_calo, CBT_muon, CBT_muon_glo)"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "Include ZDC flags in the bit selection (for Pb-Pb only)"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + } rctConfigurations; + + RCTFlagsChecker rctFlagsChecker{rctConfigurations.cfgRCTLabel.value}; + + static constexpr float DefaultLifetimeCuts[1][2] = {{30., 20.}}; + + struct : ConfigurableGroup { + std::string prefix = "v0Selections"; // JSON group name + 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)"}; + Configurable> lifetimecut{"lifetimecut", {DefaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0s"}}, "lifetimecut"}; + + // invariant mass selection + Configurable compMassRejection{"compMassRejection", -1, "Competing mass rejection (GeV/#it{c}^{2})"}; + + // 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 maxFractionTPCSharedClusters{"maxFractionTPCSharedClusters", 1e+09, "maximum fraction of TPC shared clusters"}; + Configurable maxITSchi2PerNcls{"maxITSchi2PerNcls", 1e+09, "maximum ITS chi2 per clusters"}; + Configurable maxTPCchi2PerNcls{"maxTPCchi2PerNcls", 1e+09, "maximum TPC chi2 per 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)"}; + Configurable rejectPosITSafterburner{"rejectPosITSafterburner", false, "reject positive track formed out of afterburner ITS tracks"}; + Configurable rejectNegITSafterburner{"rejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; + Configurable requirePosITSafterburnerOnly{"requirePosITSafterburnerOnly", false, "require positive track formed out of afterburner ITS tracks"}; + Configurable requireNegITSafterburnerOnly{"requireNegITSafterburnerOnly", false, "require negative track formed out of afterburner ITS tracks"}; + Configurable requireAtLeastOneHasTOF{"requireAtLeastOneHasTOF", false, "require that at least one of daughter tracks has an associated TOF signal"}; + Configurable requirePosHasTOF{"requirePosHasTOF", false, "require that positive track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requireNegHasTOF{"requireNegHasTOF", false, "require that negative track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requirePosHasTRD{"requirePosHasTRD", false, "require that positive track is formed out of TRD track."}; + Configurable requireNegHasTRD{"requireNegHasTRD", false, "require that negative track is formed out of TRD track."}; + Configurable minTRDclusters{"minTRDclusters", -1, "minimum TRD clusters IF track is formed out of a TRD track"}; + + // PID (TPC/TOF) + Configurable tpcPidNsigmaCutLaPr{"tpcPidNsigmaCutLaPr", 5, "tpcPidNsigmaCutLaPr"}; + Configurable tpcPidNsigmaCutLaPi{"tpcPidNsigmaCutLaPi", 5, "tpcPidNsigmaCutLaPi"}; + Configurable tpcPidNsigmaCutK0Pi{"tpcPidNsigmaCutK0Pi", 5, "tpcPidNsigmaCutK0Pi"}; + + // PID (TOF) + Configurable tofPidNsigmaCutLaPr{"tofPidNsigmaCutLaPr", 1e+6, "tofPidNsigmaCutLaPr"}; + Configurable tofPidNsigmaCutLaPi{"tofPidNsigmaCutLaPi", 1e+6, "tofPidNsigmaCutLaPi"}; + Configurable tofPidNsigmaCutK0Pi{"tofPidNsigmaCutK0Pi", 1e+6, "tofPidNsigmaCutK0Pi"}; + } v0Selections; + + struct : ConfigurableGroup { + std::string prefix = "cascadeSelections"; // JSON group name + // Selection criteria: acceptance + Configurable rapidityCut{"rapidityCut", 0.5, "rapidity"}; + Configurable daughterEtaCut{"daughterEtaCut", 0.8, "max eta for daughters"}; + + // Standard 6 topological criteria on V0 + Configurable v0cospa{"v0cospa", 0.97, "min V0 CosPA"}; + Configurable dcav0dau{"dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable dcav0topv{"dcav0topv", .05, "min DCA V0 to PV (cm)"}; + Configurable dcapiontopv{"dcapiontopv", .05, "min DCA Pion To PV (cm)"}; + Configurable dcaprotontopv{"dcaprotontopv", .05, "min DCA Proton To PV (cm)"}; + Configurable v0radius{"v0radius", 1.2, "minimum V0 radius (cm)"}; + Configurable v0radiusMax{"v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + + // Standard 6 topological criteria on cascades + Configurable casccospa{"casccospa", 0.97, "min Cascade CosPA"}; + Configurable dcacascdau{"dcacascdau", 1.0, "max DCA Cascade Daughters (cm)"}; + Configurable dcaxybachbaryontopv{"dcaxybachbaryontopv", -1, "DCAxy Bachelor-Baryon to PV (cm)"}; + Configurable bachbaryoncospa{"bachbaryoncospa", -1, "Bachelor-Baryon CosPA"}; + Configurable dcabachtopv{"dcabachtopv", .05, "min DCA Bachelor To PV (cm)"}; + Configurable cascradius{"cascradius", 0.5, "minimum Cascade radius (cm)"}; + Configurable cascradiusMax{"cascradiusMax", 1E5, "maximum Cascade radius (cm)"}; + Configurable cascProperLifeTime{"cascProperLifeTime", 3, "maximum lifetime (ctau)"}; + + // invariant mass selection + Configurable v0MassWindow{"v0MassWindow", 0.008, "#Lambda mass (GeV/#it{c}^{2})"}; + Configurable compMassRejection{"compMassRejection", 0.008, "Competing mass rejection (GeV/#it{c}^{2})"}; + + // 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 requireBachITSonly{"requireBachITSonly", false, "require that bachelor track is ITSonly (overrides TPC quality)"}; + 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)"}; + Configurable requireAtLeastOneHasTOF{"requireAtLeastOneHasTOF", false, "require that at least one of daughter tracks has an associated TOF signal"}; + Configurable requireBachHasTOF{"requireBachHasTOF", false, "require that bachelor track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requirePosHasTOF{"requirePosHasTOF", false, "require that positive track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requireNegHasTOF{"requireNegHasTOF", false, "require that negative track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requireBachHasTRD{"requireBachHasTRD", false, "require that bachelor track is formed out of TRD track."}; + Configurable requirePosHasTRD{"requirePosHasTRD", false, "require that positive track is formed out of TRD track."}; + Configurable requireNegHasTRD{"requireNegHasTRD", false, "require that negative track is formed out of TRD track."}; + Configurable minTRDclusters{"minTRDclusters", -1, "minimum TRD clusters IF track is formed out of a TRD track"}; + + // PID (TPC/TOF) + Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; + Configurable tofPidNsigmaCutLaPr{"tofPidNsigmaCutLaPr", 1e+6, "tofPidNsigmaCutLaPr"}; + Configurable tofPidNsigmaCutLaPi{"tofPidNsigmaCutLaPi", 1e+6, "tofPidNsigmaCutLaPi"}; + Configurable tofPidNsigmaCutXiPi{"tofPidNsigmaCutXiPi", 1e+6, "tofPidNsigmaCutXiPi"}; + Configurable tofPidNsigmaCutOmKa{"tofPidNsigmaCutOmKa", 1e+6, "tofPidNsigmaCutOmKa"}; + } cascSelections; + + // CCDB options + struct : ConfigurableGroup { + std::string prefix = "ccdbConfigurations"; // JSON group name + Configurable ccdbUrl{"ccdbUrl", "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 mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + + // manual + Configurable useCustomMagField{"useCustomMagField", false, "Use custom magnetic field value"}; + Configurable customMagField{"customMagField", 5.0f, "Manually set magnetic field"}; + } ccdbConfigurations; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + ctpRateFetcher rateFetcher; + + struct : ConfigurableGroup { + std::string prefix = "axisConfigurations"; // JSON group name + // configurable binning of histograms + 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}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtCoarse{"axisPtCoarse", {50, 0.0f, 10.0f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisV0CosPA{"axisV0CosPA", {100, 0.95f, 1.0f}, "V0 cos(PA)"}; + ConfigurableAxis axisV0PA{"axisV0PA", {1000, 0.f, 1.0f}, "Pointing angle (rad)"}; + ConfigurableAxis axisV0Radius{"axisV0Radius", {100, 0.0f, 50.0f}, "V0 radius (cm)"}; + ConfigurableAxis axisV0RadiusCoarse{"axisV0RadiusCoarse", {30, 0.0f, 30.0f}, "V0 radius (cm)"}; + ConfigurableAxis axisV0DecayLength{"axisV0DecayLength", {100, 0.0f, 80.0f}, "Decay length (cm)"}; + ConfigurableAxis axisV0DCANegToPV{"axisV0DCANegToPV", {100, -1.0f, 1.0f}, "DCA neg. to PV (cm)"}; + ConfigurableAxis axisV0DCAPosToPV{"axisV0DCAPosToPV", {100, -1.0f, 1.0f}, "DCA pos. to PV (cm)"}; + ConfigurableAxis axisV0DCAV0Dau{"axisV0DCAV0Dau", {100, 0.0f, 2.f}, "DCA between V0 daughters (cm)"}; + ConfigurableAxis axisLifetimeK0s{"axisLifetimeK0s", {100, 0.0f, 40.0f}, "K^{0}_{S} lifetime (cm)"}; + ConfigurableAxis axisLifetimeLambda{"axisLifetimeLambda", {100, 0.0f, 80.0f}, "#Lambda lifetime (cm)"}; + ConfigurableAxis axisDecayLengthK0s{"axisDecayLengthK0s", {100, 0.0f, 40.0f}, "K^{0}_{S} decay length (cm)"}; + ConfigurableAxis axisDecayLengthLambda{"axisDecayLengthLambda", {100, 0.0f, 80.0f}, "#Lambda decay length (cm)"}; + ConfigurableAxis axisV0DCAV0ToPVK0s{"axisV0DCAV0ToPVK0s", {250, 0.0f, 0.25f}, "DCA V0 to PV (cm)"}; + ConfigurableAxis axisV0DCAV0ToPVLambda{"axisV0DCAV0ToPVLambda", {250, 0.0f, 0.25f}, "DCA V0 to PV (cm)"}; + ConfigurableAxis axisInvMassK0s{"axisInvMassK0s", {200, 0.4f, 0.6f}, "Inv. mass (GeV/#it{c}%{2})"}; + ConfigurableAxis axisInvMassLambda{"axisInvMassLambda", {200, 1.07f, 1.17f}, "Inv. mass (GeV/#it{c}%{2})"}; + ConfigurableAxis axisTPCPIDPion{"axisTPCPIDPion", {100, -10.f, 10.f}, "TPC PID Pion N_{#sigma}"}; + ConfigurableAxis axisTPCPIDProton{"axisTPCPIDProton", {100, -10.f, 10.f}, "TPC PID Proton N_{#sigma}"}; + ConfigurableAxis axisEtaFlag{"axisEtaFlag", {3, -1.5f, 1.5f}, "Pseudorapidity"}; + ConfigurableAxis axisEta{"axisEta", {100, -1.0f, 1.0f}, "Pseudorapidity"}; + ConfigurableAxis axisPhi{"axisPhi", {90, 0.0f, constants::math::TwoPI}, "Azimuthal angle (#rad)"}; + ConfigurableAxis axisITSMapDaughters{"axisITSMapDaughters", {8, -0.5f, 7.5f}, ""}; + + ConfigurableAxis axisPtCasc{"axisPtCasc", {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}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisCascDecayLength{"axisCascDecayLength", {200, 0.0f, 20.0f}, "Decay length (cm)"}; + ConfigurableAxis axisCascRadius{"axisCascRadius", {100, 0.0f, 30.0f}, "Decay length (cm)"}; + ConfigurableAxis axisCascCosPA{"axisCascCosPA", {100, 0.95f, 1.0f}, "Casc cos(PA)"}; + ConfigurableAxis axisCascRapidity{"axisCascRapidity", {100, -1.0f, 1.0f}, "Rapidity"}; + ConfigurableAxis axisCascLifetimeXi{"axisLifetimeXi", {100, 0.0f, 40.0f}, "#Xi lifetime (cm)"}; + ConfigurableAxis axisCascLifetimeOmega{"axisLifetimeOmega", {100, 0.0f, 30.0f}, "#Omega lifetime (cm)"}; + ConfigurableAxis axisCascDCAV0Dau{"axisCascDCAV0Dau", {100, 0.0f, 2.f}, "DCA between casc. daughters (cm)"}; + ConfigurableAxis axisCascDCABachToPV{"axisCascDCABachToPV", {100, -1.0f, 1.0f}, "DCA bach. to PV (cm)"}; + ConfigurableAxis axisInvMassXi{"axisInvMassXi", {80, 1.28f, 1.36f}, "Inv. mass (GeV/#it{c}%{2})"}; + ConfigurableAxis axisInvMassOmega{"axisInvMassOmega", {80, 1.63f, 1.71f}, "Inv. mass (GeV/#it{c}%{2})"}; + + } axisConfigurations; int dauEtaFlag = 0; - OutputObj V0SelectionSummary{TH1F("V0SelectionSummary", "V0SelectionSummary; Selections; Cut", 10, 0., 10.)}; - - HistogramRegistry histos_eve{ - "histos-eve", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hEventCounterMC", "hEventCounterMC", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - }, - OutputObjHandlingPolicy::AnalysisObject, - false, - true}; - - HistogramRegistry histos_V0{ - "histos-V0", - {}, - OutputObjHandlingPolicy::AnalysisObject, - false, - true}; - - HistogramRegistry histos_Casc{ - "histos-Casc", - { - {"CascSelectionSummary", "CascSelectionSummary", {HistType::kTH1F, {{10, 0.f, 10.f}}}}, - {"QA_XiMinusCandidates", "QA_XiMinusCandidates", {HistType::kTH1F, {{10, 0.f, 10.f}}}}, - {"XiProgSelections", "XiProgSelections", {HistType::kTH2F, {{30, 0.5f, 30.5f}, {2, -2, 2}}}}, - {"OmegaProgSelections", "OmegaProgSelections", {HistType::kTH2F, {{30, 0.5f, 30.5f}, {2, -2, 2}}}}, - {"CascCosPA", "CascCosPA", {HistType::kTH2F, {{200, 0.6f, 1.0f}, {2, -2, 2}}}}, - {"V0CosPA", "V0CosPA", {HistType::kTH2F, {{300, 0.7f, 1.0f}, {2, -2, 2}}}}, - {"V0CosPAToXi", "V0CosPAToXi", {HistType::kTH2F, {{100, 0.9f, 1.0f}, {2, -2, 2}}}}, - {"CascDecayLength", "CascDecayLength", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {2, -2, 2}}}}, - {"CascDecayLengthXi", "CascDecayLengthXi", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {2, -2, 2}}}}, - {"CascDecayLengthOmega", "CascDecayLengthOmega", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {2, -2, 2}}}}, - {"CascRadius", "CascRadius", {HistType::kTH2F, {{100, 0.0f, 10.0f}, {2, -2, 2}}}}, - {"V0Radius", "V0Radius", {HistType::kTH2D, {{100, 0.0f, 10.0f}, {2, -2, 2}}}}, // asked for D instead of F - {"CascyXi", "CascyXi", {HistType::kTH2F, {{200, -2.0f, 2.0f}, {2, -2, 2}}}}, - {"CascyOmega", "CascyOmega", {HistType::kTH2F, {{200, -2.0f, 2.0f}, {2, -2, 2}}}}, - {"CascCtauXi", "CascCtauXi", {HistType::kTH2F, {{100, 0.0f, 100.0f}, {2, -2, 2}}}}, - {"CascCtauOmega", "CascCtauOmega", {HistType::kTH2F, {{100, 0.0f, 100.0f}, {2, -2, 2}}}}, - {"V0Ctau", "V0Ctau", {HistType::kTH2F, {{100, 0.0f, 100.0f}, {2, -2, 2}}}}, - {"CascPt", "CascPt", {HistType::kTH2F, {{100, 0.0f, 25.0f}, {2, -2, 2}}}}, - {"DcaV0Daughters", "DcaV0Daughters", {HistType::kTH2F, {{110, 0.0f, 2.2f}, {2, -2, 2}}}}, - {"DcaCascDaughters", "DcaCascDaughters", {HistType::kTH2F, {{110, 0.0f, 2.2f}, {2, -2, 2}}}}, - {"DcaV0ToPV", "DcaV0ToPV", {HistType::kTH2F, {{200, 0.0f, 2.f}, {2, -2, 2}}}}, - {"DcaBachToPV", "DcaBachToPV", {HistType::kTH2F, {{80, -0.2f, 0.2f}, {2, -2, 2}}}}, - {"DcaPosToPV", "DcaPosToPV", {HistType::kTH2F, {{80, -0.2f, 0.2f}, {2, -2, 2}}}}, - {"DcaNegToPV", "DcaNegToPV", {HistType::kTH2F, {{80, -0.2f, 0.2f}, {2, -2, 2}}}}, - {"InvMassLambdaDaughter", "InvMassLambdaDaughter", {HistType::kTH2F, {{100, 1.1f, 1.13f}, {2, -2, 2}}}}, - {"InvMassXiPlus", "InvMassXiPlus", {HistType::kTH3F, {{100, 0.f, 10.f}, {80, 1.28f, 1.36f}, {2, -1.0f, 1.0f}}}}, - {"InvMassXiMinus", "InvMassXiMinus", {HistType::kTH3F, {{100, 0.f, 10.f}, {80, 1.28f, 1.36f}, {2, -1.0f, 1.0f}}}}, - {"InvMassXiPlus_Radius", "InvMassXiPlus_Radius", {HistType::kTH2F, {{100, 0.f, 50.f}, {80, 1.28f, 1.36f}}}}, - {"InvMassXiMinus_Radius", "InvMassXiMinus_Radius", {HistType::kTH2F, {{100, 0.f, 50.f}, {80, 1.28f, 1.36f}}}}, - {"InvMassOmegaPlus", "InvMassOmegaPlus", {HistType::kTH3F, {{100, 0.f, 10.f}, {80, 1.63f, 1.71f}, {2, -1.0f, 1.0f}}}}, - {"InvMassOmegaMinus", "InvMassOmegaMinus", {HistType::kTH3F, {{100, 0.f, 10.f}, {80, 1.63f, 1.71f}, {2, -1.0f, 1.0f}}}}, - }, - OutputObjHandlingPolicy::AnalysisObject, - false, - true}; - void init(InitContext const&) { - const AxisSpec axisPt{binPt, "p_{T} (GeV/c)"}; - const AxisSpec axisPtsmall{binPtsmall, "p_{T} (GeV/c)"}; - const AxisSpec axisV0CosPA{binV0CosPA, "V0 Cos(PA)"}; - const AxisSpec axisV0PA{binV0PA, "Pointing Angle"}; - const AxisSpec axisV0Radius{binV0Radius, "V0 Radius (cm)"}; - const AxisSpec axisV0DecayLength{binV0DecayLength, "V0 Decay Length (cm)"}; - const AxisSpec axisV0DCANegToPV{binV0DCANegToPV, "V0 DCA Neg To PV (cm)"}; - const AxisSpec axisV0DCAPosToPV{binV0DCAPosToPV, "V0 DCA Pos To PV (cm)"}; - const AxisSpec axisV0DCAV0Dau{binV0DCAV0Dau, "V0 DCA V0 Daughters (cm)"}; - const AxisSpec axisCtauK0s{binCtauK0s, "K0s c#tau (cm)"}; - const AxisSpec axisCtauLambda{binCtauLambda, "Lambda c#tau (cm)"}; - const AxisSpec axisCtauAntiLambda{binCtauAntiLambda, "AntiLambda c#tau (cm)"}; - const AxisSpec axisDecayLengthK0s{binDecayLengthK0s, "Decay length K0s (cm)"}; - const AxisSpec axisDecayLengthLambda{binDecayLengthLambda, "Decay length Lambda (cm)"}; - const AxisSpec axisDecayLengthAntiLambda{binDecayLengthAntiLambda, "Decay length AntiLambda (cm)"}; - const AxisSpec axisV0DCAV0ToPVK0S{binV0DCAV0ToPVK0S, "DCAV0ToPV K0s"}; - const AxisSpec axisV0DCAV0ToPVLambda{binV0DCAV0ToPVLambda, "DCAV0ToPV Lambda"}; - const AxisSpec axisV0DCAV0ToPVAntiLambda{binV0DCAV0ToPVAntiLambda, "DCAV0ToPV AntiLambda"}; - const AxisSpec axisInvMassK0S{binInvMassK0S, "InvMass K0s"}; - const AxisSpec axisInvMassLambda{binInvMassLambda, "InvMass Lambda"}; - const AxisSpec axisInvMassAntiLambda{binInvMassAntiLambda, "InvMass AntiLambda"}; - const AxisSpec axisInvMassCasc{binInvMassCasc, "InvMass Cascades"}; - const AxisSpec axisResponsePionFromLambda{binResponsePionFromLambda, "Response Pion From Lambda"}; - const AxisSpec axisResponseProtonFromLambda{binResponseProtonFromLambda, "Response Proton From Lambda"}; - const AxisSpec axisEta{binEta, "Eta"}; - const AxisSpec axisPhi{binPhi, "Phi"}; - const AxisSpec axisEtaFlag{binEtaFlag, "Eta"}; - const AxisSpec axisRadius{binRadius, "Radius"}; - const AxisSpec axisRadiussmall{binRadiussmall, "Radius"}; - const AxisSpec axisITSMapDaughters{binITSMapDaughters, "ITS Map Daughters"}; - - histos_V0.add("CosPA", "CosPA", kTH1F, {axisV0CosPA}); - histos_V0.add("V0Radius", "V0Radius", kTH1D, {axisV0Radius}); - histos_V0.add("DecayLength", "DecayLength", kTH1F, {axisV0DecayLength}); - histos_V0.add("V0DCANegToPV", "V0DCANegToPV", kTH1F, {axisV0DCANegToPV}); - histos_V0.add("V0DCAPosToPV", "V0DCAPosToPV", kTH1F, {axisV0DCAPosToPV}); - histos_V0.add("V0DCAV0Daughters", "V0DCAV0Daughters", kTH1F, {axisV0DCAV0Dau}); - histos_V0.add("CtauK0s", "CtauK0s", kTH1F, {axisCtauK0s}); - histos_V0.add("CtauLambda", "CtauLambda", kTH1F, {axisCtauLambda}); - histos_V0.add("CtauAntiLambda", "CtauAntiLambda", kTH1F, {axisCtauAntiLambda}); - histos_V0.add("DecayLengthK0s", "DecayLengthK0s", kTH1F, {axisDecayLengthK0s}); - histos_V0.add("DecayLengthLambda", "DecayLengthLambda", kTH1F, {axisDecayLengthLambda}); - histos_V0.add("DecayLengthAntiLambda", "DecayLengthAntiLambda", kTH1F, {axisDecayLengthAntiLambda}); - histos_V0.add("V0DCAV0ToPVK0S", "V0DCAV0ToPVK0S", kTH1F, {axisV0DCAV0ToPVK0S}); - histos_V0.add("V0DCAV0ToPVLambda", "V0DCAV0ToPVLambda", kTH1F, {axisV0DCAV0ToPVLambda}); - histos_V0.add("V0DCAV0ToPVAntiLambda", "V0DCAV0ToPVAntiLambda", kTH1F, {axisV0DCAV0ToPVAntiLambda}); - histos_V0.add("InvMassK0S", "InvMassK0S", kTH3F, {axisPt, axisInvMassK0S, axisEtaFlag}); - histos_V0.add("InvMassLambda", "InvMassLambda", kTH3F, {axisPt, axisInvMassLambda, axisEtaFlag}); - histos_V0.add("InvMassAntiLambda", "InvMassAntiLambda", kTH3F, {axisPt, axisInvMassAntiLambda, axisEtaFlag}); - histos_V0.add("ResponsePionFromLambda", "ResponsePionFromLambda", kTH2F, {axisPt, axisResponsePionFromLambda}); - histos_V0.add("ResponseProtonFromLambda", "ResponseProtonFromLambda", kTH2F, {axisPt, axisResponseProtonFromLambda}); - if (doextraanalysis) { - histos_V0.add("InvMassK0S_Radius", "InvMassK0S_Radius", kTH2F, {axisRadius, axisInvMassK0S}); - histos_V0.add("InvMassLambda_Radius", "InvMassLambda_Radius", kTH2F, {axisRadius, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambda_Radius", "InvMassAntiLambda_Radius", kTH2F, {axisRadius, axisInvMassAntiLambda}); - histos_V0.add("InvMassK0S_EtaDaughters", "InvMassK0S_EtaDaughters", kTH3F, {axisEta, axisEta, axisInvMassK0S}); - histos_V0.add("InvMassLambda_EtaDaughters", "InvMassLambda_EtaDaughters", kTH3F, {axisEta, axisEta, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambda_EtaDaughters", "InvMassAntiLambda_EtaDaughters", kTH3F, {axisEta, axisEta, axisInvMassAntiLambda}); - histos_V0.add("InvMassK0S_Ctau", "InvMassK0S_Ctau", kTH2F, {axisCtauK0s, axisInvMassK0S}); - histos_V0.add("InvMassLambda_Ctau", "InvMassLambda_Ctau", kTH2F, {axisCtauLambda, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambda_Ctau", "InvMassAntiLambda_Ctau", kTH2F, {axisCtauAntiLambda, axisInvMassAntiLambda}); - histos_V0.add("InvMassK0S_PhiDaughters", "InvMassK0S_PhiDaughters", kTH3F, {axisPhi, axisPhi, axisInvMassK0S}); - histos_V0.add("InvMassLambda_PhiDaughters", "InvMassLambda_PhiDaughters", kTH3F, {axisPhi, axisPhi, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambda_PhiDaughters", "InvMassAntiLambda_PhiDaughters", kTH3F, {axisPhi, axisPhi, axisInvMassAntiLambda}); - histos_V0.add("InvMassK0S_ITSMapDaughters", "InvMassK0S_ITSMapDaughters", kTH3F, {axisITSMapDaughters, axisITSMapDaughters, axisInvMassK0S}); - histos_V0.add("InvMassLambda_ITSMapDaughters", "InvMassLambda_ITSMapDaughters", kTH3F, {axisITSMapDaughters, axisITSMapDaughters, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambda_ITSMapDaughters", "InvMassAntiLambda_ITSMapDaughters", kTH3F, {axisITSMapDaughters, axisITSMapDaughters, axisInvMassAntiLambda}); - histos_V0.add("InvMassK0S_PtRadius", "InvMassK0S_PtRadius", kTH3F, {axisPtsmall, axisRadiussmall, axisInvMassK0S}); - histos_V0.add("InvMassLambda_PtRadius", "InvMassLambda_PtRadius", kTH3F, {axisPtsmall, axisRadiussmall, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambda_PtRadius", "InvMassAntiLambda_PtRadius", kTH3F, {axisPtsmall, axisRadiussmall, axisInvMassAntiLambda}); - } - histos_V0.add("InvMassK0SVsPtVsPA", "InvMassK0SVsPtVsPA", kTH3F, {axisPt, axisV0PA, axisInvMassK0S}); + if (doprocessGenerated || doprocessMonteCarlo) { + isMC = true; + } + // setting CCDB service + ccdb->setURL(ccdbConfigurations.ccdbUrl); + ccdb->setCaching(true); + ccdb->setFatalWhenNull(false); + + // Event Counters + histos_event.add("hEventCounter", "hEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}); + histos_event.add("hEventCounterMC", "hEventCounterMC", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}); + histos_event.add("hEventSelection", "hEventSelection", kTH1D, {{24, -0.5f, +23.5f}}); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(3, "kIsTriggerTVX"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(6, "posZ cut"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(7, "kIsVertexITSTPC"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(8, "kIsGoodZvtxFT0vsPV"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(9, "kIsVertexTOFmatched"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(10, "kIsVertexTRDmatched"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(11, "kNoSameBunchPileup"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(12, "kNoCollInTimeRangeStd"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(13, "kNoCollInTimeRangeStrict"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(14, "kNoCollInTimeRangeNarrow"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(15, "kNoCollInRofStd"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(16, "kNoCollInRofStrict"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(17, "Below min occup."); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(18, "Above max occup."); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(19, "Below min IR"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(20, "Above max IR"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(21, "INEL>0"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(22, "INEL>1"); + histos_event.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(23, "RCT flags"); + + histos_V0.add("CosPA", "CosPA", kTH1F, {axisConfigurations.axisV0CosPA}); + histos_V0.add("Radius", "Radius", kTH1D, {axisConfigurations.axisV0Radius}); + histos_V0.add("DecayLength", "DecayLength", kTH1F, {axisConfigurations.axisV0DecayLength}); + histos_V0.add("DCANegToPV", "DCANegToPV", kTH1F, {axisConfigurations.axisV0DCANegToPV}); + histos_V0.add("DCAPosToPV", "DCAPosToPV", kTH1F, {axisConfigurations.axisV0DCAPosToPV}); + histos_V0.add("DCAV0Daughters", "DCAV0Daughters", kTH1F, {axisConfigurations.axisV0DCAV0Dau}); + histos_V0.add("CosPAK0s", "CosPAK0s", kTH1F, {axisConfigurations.axisV0CosPA}); + histos_V0.add("CosPALambda", "CosPALambda", kTH1F, {axisConfigurations.axisV0CosPA}); + histos_V0.add("CosPAAntiLambda", "CosPAAntiLambda", kTH1F, {axisConfigurations.axisV0CosPA}); + histos_V0.add("RadiusK0s", "RadiusK0s", kTH1D, {axisConfigurations.axisV0Radius}); + histos_V0.add("RadiusLambda", "RadiusLambda", kTH1D, {axisConfigurations.axisV0Radius}); + histos_V0.add("RadiusAntiLambda", "RadiusAntiLambda", kTH1D, {axisConfigurations.axisV0Radius}); + histos_V0.add("DCANegToPVK0s", "DCANegToPVK0s", kTH1F, {axisConfigurations.axisV0DCANegToPV}); + histos_V0.add("DCANegToPVLambda", "DCANegToPVLambda", kTH1F, {axisConfigurations.axisV0DCANegToPV}); + histos_V0.add("DCANegToPVAntiLambda", "DCANegToPVAntiLambda", kTH1F, {axisConfigurations.axisV0DCANegToPV}); + histos_V0.add("DCAPosToPVK0s", "DCAPosToPVK0s", kTH1F, {axisConfigurations.axisV0DCAPosToPV}); + histos_V0.add("DCAPosToPVLambda", "DCAPosToPVLambda", kTH1F, {axisConfigurations.axisV0DCAPosToPV}); + histos_V0.add("DCAPosToPVAntiLambda", "DCAPosToPVAntiLambda", kTH1F, {axisConfigurations.axisV0DCAPosToPV}); + histos_V0.add("DCAV0DaughtersK0s", "DCAV0DaughtersK0s", kTH1F, {axisConfigurations.axisV0DCAV0Dau}); + histos_V0.add("DCAV0DaughtersLambda", "DCAV0DaughtersLambda", kTH1F, {axisConfigurations.axisV0DCAV0Dau}); + histos_V0.add("DCAV0DaughtersAntiLambda", "DCAV0DaughtersAntiLambda", kTH1F, {axisConfigurations.axisV0DCAV0Dau}); + histos_V0.add("LifetimeK0s", "LifetimeK0s", kTH1F, {axisConfigurations.axisLifetimeK0s}); + histos_V0.add("LifetimeLambda", "LifetimeLambda", kTH1F, {axisConfigurations.axisLifetimeLambda}); + histos_V0.add("LifetimeAntiLambda", "LifetimeAntiLambda", kTH1F, {axisConfigurations.axisLifetimeLambda}); + histos_V0.add("DecayLengthK0s", "DecayLengthK0s", kTH1F, {axisConfigurations.axisDecayLengthK0s}); + histos_V0.add("DecayLengthLambda", "DecayLengthLambda", kTH1F, {axisConfigurations.axisDecayLengthLambda}); + histos_V0.add("DecayLengthAntiLambda", "DecayLengthAntiLambda", kTH1F, {axisConfigurations.axisDecayLengthLambda}); + histos_V0.add("DCAV0ToPVK0s", "DCAV0ToPVK0s", kTH1F, {axisConfigurations.axisV0DCAV0ToPVK0s}); + histos_V0.add("DCAV0ToPVLambda", "DCAV0ToPVLambda", kTH1F, {axisConfigurations.axisV0DCAV0ToPVLambda}); + histos_V0.add("DCAV0ToPVAntiLambda", "DCAV0ToPVAntiLambda", kTH1F, {axisConfigurations.axisV0DCAV0ToPVLambda}); + histos_V0.add("InvMassK0s", "InvMassK0s", kTH3F, {axisConfigurations.axisPt, axisConfigurations.axisInvMassK0s, axisConfigurations.axisEtaFlag}); + histos_V0.add("InvMassLambda", "InvMassLambda", kTH3F, {axisConfigurations.axisPt, axisConfigurations.axisInvMassLambda, axisConfigurations.axisEtaFlag}); + histos_V0.add("InvMassAntiLambda", "InvMassAntiLambda", kTH3F, {axisConfigurations.axisPt, axisConfigurations.axisInvMassLambda, axisConfigurations.axisEtaFlag}); + histos_V0.add("TPCPIDPosPionFromK0s", "TPCPIDPosPionFromK0s", kTH2F, {axisConfigurations.axisPt, axisConfigurations.axisTPCPIDPion}); + histos_V0.add("TPCPIDNegPionFromK0s", "TPCPIDNegPionFromK0s", kTH2F, {axisConfigurations.axisPt, axisConfigurations.axisTPCPIDProton}); + histos_V0.add("TPCPIDPionFromLambda", "TPCPIDPionFromLambda", kTH2F, {axisConfigurations.axisPt, axisConfigurations.axisTPCPIDPion}); + histos_V0.add("TPCPIDProtonFromLambda", "TPCPIDProtonFromLambda", kTH2F, {axisConfigurations.axisPt, axisConfigurations.axisTPCPIDProton}); + histos_V0.add("TPCPIDPionFromAntiLambda", "TPCPIDPionFromAntiLambda", kTH2F, {axisConfigurations.axisPt, axisConfigurations.axisTPCPIDPion}); + histos_V0.add("TPCPIDProtonFromAntiLambda", "TPCPIDProtonFromAntiLambda", kTH2F, {axisConfigurations.axisPt, axisConfigurations.axisTPCPIDProton}); if (doextraanalysis) { - histos_V0.add("InvMassLambdaVsPtVsPA", "InvMassLambdaVsPtVsPA", kTH3F, {axisPt, axisV0PA, axisInvMassLambda}); - histos_V0.add("InvMassAntiLambdaVsPtVsPA", "InvMassAntiLambdaVsPtVsPA", kTH3F, {axisPt, axisV0PA, axisInvMassAntiLambda}); + histos_V0.add("InvMassK0s_Radius", "InvMassK0s_Radius", kTH2F, {axisConfigurations.axisV0Radius, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambda_Radius", "InvMassLambda_Radius", kTH2F, {axisConfigurations.axisV0Radius, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambda_Radius", "InvMassAntiLambda_Radius", kTH2F, {axisConfigurations.axisV0Radius, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassK0s_EtaDaughters", "InvMassK0s_EtaDaughters", kTH3F, {axisConfigurations.axisEta, axisConfigurations.axisEta, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambda_EtaDaughters", "InvMassLambda_EtaDaughters", kTH3F, {axisConfigurations.axisEta, axisConfigurations.axisEta, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambda_EtaDaughters", "InvMassAntiLambda_EtaDaughters", kTH3F, {axisConfigurations.axisEta, axisConfigurations.axisEta, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassK0s_Lifetime", "InvMassK0s_Lifetime", kTH2F, {axisConfigurations.axisLifetimeK0s, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambda_Lifetime", "InvMassLambda_Lifetime", kTH2F, {axisConfigurations.axisLifetimeLambda, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambda_Lifetime", "InvMassAntiLambda_Lifetime", kTH2F, {axisConfigurations.axisLifetimeLambda, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassK0s_PhiDaughters", "InvMassK0s_PhiDaughters", kTH3F, {axisConfigurations.axisPhi, axisConfigurations.axisPhi, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambda_PhiDaughters", "InvMassLambda_PhiDaughters", kTH3F, {axisConfigurations.axisPhi, axisConfigurations.axisPhi, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambda_PhiDaughters", "InvMassAntiLambda_PhiDaughters", kTH3F, {axisConfigurations.axisPhi, axisConfigurations.axisPhi, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassK0s_ITSMapDaughters", "InvMassK0s_ITSMapDaughters", kTH3F, {axisConfigurations.axisITSMapDaughters, axisConfigurations.axisITSMapDaughters, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambda_ITSMapDaughters", "InvMassLambda_ITSMapDaughters", kTH3F, {axisConfigurations.axisITSMapDaughters, axisConfigurations.axisITSMapDaughters, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambda_ITSMapDaughters", "InvMassAntiLambda_ITSMapDaughters", kTH3F, {axisConfigurations.axisITSMapDaughters, axisConfigurations.axisITSMapDaughters, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassK0s_PtRadius", "InvMassK0s_PtRadius", kTH3F, {axisConfigurations.axisPtCoarse, axisConfigurations.axisV0RadiusCoarse, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambda_PtRadius", "InvMassLambda_PtRadius", kTH3F, {axisConfigurations.axisPtCoarse, axisConfigurations.axisV0RadiusCoarse, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambda_PtRadius", "InvMassAntiLambda_PtRadius", kTH3F, {axisConfigurations.axisPtCoarse, axisConfigurations.axisV0RadiusCoarse, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassK0sVsPtVsPA", "InvMassK0sVsPtVsPA", kTH3F, {axisConfigurations.axisPtCoarse, axisConfigurations.axisV0PA, axisConfigurations.axisInvMassK0s}); + histos_V0.add("InvMassLambdaVsPtVsPA", "InvMassLambdaVsPtVsPA", kTH3F, {axisConfigurations.axisPtCoarse, axisConfigurations.axisV0PA, axisConfigurations.axisInvMassLambda}); + histos_V0.add("InvMassAntiLambdaVsPtVsPA", "InvMassAntiLambdaVsPtVsPA", kTH3F, {axisConfigurations.axisPtCoarse, axisConfigurations.axisV0PA, axisConfigurations.axisInvMassLambda}); } - if (isMC) { - histos_eve.add("GeneratedParticles", "GeneratedParticles", {HistType::kTH3F, {{14, 0.0f, 14.0f}, {100, 0, 10}, {100, 0.f, 50.f}}}); - histos_V0.add("InvMassK0STrue", "InvMassK0STrue", {HistType::kTH3F, {{100, 0.0f, 10.0f}, {100, 0.f, 50.f}, {200, 0.4f, 0.6f}}}); + histos_Casc.add("QA_CascadeCandidates", "QA_CascadeCandidates", {HistType::kTH1F, {{10, 0.f, 10.f}}}); + histos_Casc.add("CascCosPA", "CascCosPA", kTH2D, {axisConfigurations.axisV0CosPA, {2, -2, 2}}); + histos_Casc.add("V0CosPA", "V0CosPA", kTH2D, {axisConfigurations.axisV0CosPA, {2, -2, 2}}); + histos_Casc.add("V0CosPAToXi", "V0CosPAToXi", kTH2D, {axisConfigurations.axisV0CosPA, {2, -2, 2}}); + histos_Casc.add("CascDecayLength", "CascDecayLength", kTH2D, {axisConfigurations.axisCascDecayLength, {2, -2, 2}}); + histos_Casc.add("CascRadius", "CascRadius", kTH2F, {axisConfigurations.axisCascRadius, {2, -2, 2}}); + histos_Casc.add("V0Radius", "V0Radius", kTH2F, {axisConfigurations.axisV0Radius, {2, -2, 2}}); + histos_Casc.add("CascRapidityXi", "CascRapidityXi", kTH2F, {axisConfigurations.axisCascRapidity, {2, -2, 2}}); + histos_Casc.add("CascRapidityOmega", "CascRapidityOmega", kTH2F, {axisConfigurations.axisCascRapidity, {2, -2, 2}}); + histos_Casc.add("CascLifetimeXi", "CascLifetimeXi", kTH2F, {axisConfigurations.axisCascLifetimeXi, {2, -2, 2}}); + histos_Casc.add("CascLifetimeOmega", "CascLifetimeOmega", kTH2F, {axisConfigurations.axisCascLifetimeOmega, {2, -2, 2}}); + histos_Casc.add("V0Lifetime", "V0Lifetime", kTH2F, {axisConfigurations.axisLifetimeLambda, {2, -2, 2}}); + histos_Casc.add("CascPt", "CascPt", kTH2F, {axisConfigurations.axisPtCasc, {2, -2, 2}}); + histos_Casc.add("DcaV0Daughters", "DcaV0Daughters", kTH2F, {axisConfigurations.axisV0DCAV0Dau, {2, -2, 2}}); + histos_Casc.add("DcaCascDaughters", "DcaCascDaughters", kTH2F, {axisConfigurations.axisCascDCAV0Dau, {2, -2, 2}}); + histos_Casc.add("DcaV0ToPV", "DcaV0ToPV", kTH2F, {axisConfigurations.axisV0DCAV0ToPVLambda, {2, -2, 2}}); + histos_Casc.add("DcaBachToPV", "DcaBachToPV", kTH2F, {axisConfigurations.axisCascDCABachToPV, {2, -2, 2}}); + histos_Casc.add("DcaPosToPV", "DcaPosToPV", kTH2F, {axisConfigurations.axisV0DCAPosToPV, {2, -2, 2}}); + histos_Casc.add("DcaNegToPV", "DcaNegToPV", kTH2F, {axisConfigurations.axisV0DCANegToPV, {2, -2, 2}}); + histos_Casc.add("InvMassLambda", "InvMassLambda", kTH2F, {axisConfigurations.axisInvMassLambda, {2, -2, 2}}); + histos_Casc.add("InvMassXiPlus", "InvMassXiPlus", kTH3F, {axisConfigurations.axisPtCasc, axisConfigurations.axisInvMassXi, {2, -1.f, 1.f}}); + histos_Casc.add("InvMassXiMinus", "InvMassXiMinus", kTH3F, {axisConfigurations.axisPtCasc, axisConfigurations.axisInvMassXi, {2, -1.f, 1.f}}); + histos_Casc.add("InvMassXiPlus_Radius", "InvMassXiPlus_Radius", kTH2F, {axisConfigurations.axisCascRadius, axisConfigurations.axisInvMassXi}); + histos_Casc.add("InvMassXiMinus_Radius", "InvMassXiMinus_Radius", kTH2F, {axisConfigurations.axisCascRadius, axisConfigurations.axisInvMassXi}); + histos_Casc.add("InvMassOmegaPlus", "InvMassOmegaPlus", kTH3F, {axisConfigurations.axisPtCasc, axisConfigurations.axisInvMassOmega, {2, -1.f, 1.f}}); + histos_Casc.add("InvMassOmegaMinus", "InvMassOmegaMinus", kTH3F, {axisConfigurations.axisPtCasc, axisConfigurations.axisInvMassOmega, {2, -1.f, 1.f}}); + + if (isMC) { + histos_event.add("GeneratedV0s", "GeneratedV0s", kTH3D, {{3, 0.0f, 3.0f}, axisConfigurations.axisPt, axisConfigurations.axisV0Radius}); + histos_event.get(HIST("GeneratedV0s"))->GetXaxis()->SetBinLabel(1, "K^{0}_{S}"); + histos_event.get(HIST("GeneratedV0s"))->GetXaxis()->SetBinLabel(2, "#Lambda"); + histos_event.get(HIST("GeneratedV0s"))->GetXaxis()->SetBinLabel(3, "#bar{#Lambda}"); + histos_event.add("GeneratedCascades", "GeneratedCascades", kTH3D, {{4, 0.0f, 4.0f}, axisConfigurations.axisPtCasc, axisConfigurations.axisCascRadius}); + histos_event.get(HIST("GeneratedCascades"))->GetXaxis()->SetBinLabel(1, "#Xi^{#minus}"); + histos_event.get(HIST("GeneratedCascades"))->GetXaxis()->SetBinLabel(2, "#bar{#Xi}^{+}"); + histos_event.get(HIST("GeneratedCascades"))->GetXaxis()->SetBinLabel(3, "#Omega^{#minus}"); + histos_event.get(HIST("GeneratedCascades"))->GetXaxis()->SetBinLabel(4, "#bar{#Omega}^{+}"); + + histos_V0.add("InvMassK0sTrue", "InvMassK0sTrue", {HistType::kTH3F, {{100, 0.0f, 10.0f}, {100, 0.f, 50.f}, {200, 0.4f, 0.6f}}}); histos_V0.add("InvMassLambdaTrue", "InvMassLambdaTrue", {HistType::kTH3F, {{100, 0.0f, 10.0f}, {100, 0.f, 50.f}, {200, 1.07f, 1.17f}}}); histos_V0.add("InvMassAntiLambdaTrue", "InvMassAntiLambdaTrue", {HistType::kTH3F, {{100, 0.0f, 10.0f}, {100, 0.f, 50.f}, {200, 1.07f, 1.17f}}}); @@ -238,384 +436,777 @@ struct v0cascadesQA { histos_Casc.add("InvMassOmegaPlusTrue", "InvMassOmegaPlusTrue", {HistType::kTH3F, {{100, 0.f, 10.f}, {100, 0.f, 50.f}, {80, 1.63f, 1.71f}}}); histos_Casc.add("InvMassOmegaMinusTrue", "InvMassOmegaMinusTrue", {HistType::kTH3F, {{100, 0.f, 10.f}, {100, 0.f, 50.f}, {80, 1.63f, 1.71f}}}); } - } - /////////////////////////////////////////////////// - ////////// Collisions QA - reconstructed ////////// - /////////////////////////////////////////////////// + // Initialise the RCTFlagsChecker + rctFlagsChecker.init(rctConfigurations.cfgRCTLabel.value, rctConfigurations.cfgCheckZDC, rctConfigurations.cfgTreatLimitedAcceptanceAsBad); + } - void processReconstructedEvent(soa::Join::iterator const& Collision) + template + bool isEventAccepted(TCollision collision, bool fillHists) + // check whether the collision passes our collision selections { - histos_eve.fill(HIST("hEventCounter"), 0.5); + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 0. /* all collisions */); + } - if (sel8 && !Collision.sel8()) { - return; + if (eventSelections.requireSel8 && !collision.sel8()) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 1 /* sel8 collisions */); } - histos_eve.fill(HIST("hEventCounter"), 1.5); - } - PROCESS_SWITCH(v0cascadesQA, processReconstructedEvent, "Process reconstructed level Event", true); + if (eventSelections.requireTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 2 /* FT0 vertex (acceptable FT0C-FT0A time difference) collisions */); + } - /////////////////////////////////////// - ////////// Collision QA - MC ////////// - /////////////////////////////////////// + if (eventSelections.rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 3 /* Not at ITS ROF border */); + } - void processMcEvent(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions) - { - histos_eve.fill(HIST("hEventCounterMC"), 0.5); + if (eventSelections.rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 4 /* Not at TF border */); + } - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - for (const auto& collision : collisions) { - if (sel8 && !collision.sel8()) { - continue; - } - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + if (std::abs(collision.posZ()) > eventSelections.maxZVtxPosition) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 5 /* vertex-Z selected */); } - SelectedEvents.resize(nevts); - const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); + if (eventSelections.requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 6 /* Contains at least one ITS-TPC track */); + } - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection - return; + if (eventSelections.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 7 /* PV position consistency check */); } - histos_eve.fill(HIST("hEventCounterMC"), 1.5); + if (eventSelections.requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 8 /* PV with at least one contributor matched with TOF */); + } - double posx = mcCollision.posX(); - double posy = mcCollision.posY(); + if (eventSelections.requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 9 /* PV with at least one contributor matched with TRD */); + } - for (auto& mcparticle : mcParticles) { + if (eventSelections.rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 10 /* Not at same bunch pile-up */); + } - if (!mcparticle.has_daughters()) { - continue; - } + if (eventSelections.requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 11 /* No other collision within +/- 2 microseconds or mult above a certain threshold in -4 - -2 microseconds*/); + } - double vx = 0; - double vy = 0; - for (auto& mcparticleDaughter0 : mcparticle.daughters_as()) { - vx = mcparticleDaughter0.vx() - posx; - vy = mcparticleDaughter0.vy() - posy; - if (vx != 0 && vy != 0) - break; - } - double R_Decay = TMath::Sqrt(vx * vx + vy * vy); - - if (mcparticle.isPhysicalPrimary() && TMath::Abs(mcparticle.y()) < V0_rapidity) { - if (mcparticle.pdgCode() == 310) - histos_eve.fill(HIST("GeneratedParticles"), 0.5, mcparticle.pt(), R_Decay); // K0s - if (mcparticle.pdgCode() == 3122) - histos_eve.fill(HIST("GeneratedParticles"), 2.5, mcparticle.pt(), R_Decay); // Lambda - if (mcparticle.pdgCode() == -3122) - histos_eve.fill(HIST("GeneratedParticles"), 4.5, mcparticle.pt(), R_Decay); // AntiLambda - } - if (mcparticle.isPhysicalPrimary() && TMath::Abs(mcparticle.y()) < Casc_rapidity) { - if (mcparticle.pdgCode() == 3312) - histos_eve.fill(HIST("GeneratedParticles"), 6.5, mcparticle.pt(), R_Decay); // Xi- - if (mcparticle.pdgCode() == -3312) - histos_eve.fill(HIST("GeneratedParticles"), 8.5, mcparticle.pt(), R_Decay); // Xi+ - if (mcparticle.pdgCode() == 3334) - histos_eve.fill(HIST("GeneratedParticles"), 10.5, mcparticle.pt(), R_Decay); // Omega- - if (mcparticle.pdgCode() == -3334) - histos_eve.fill(HIST("GeneratedParticles"), 12.5, mcparticle.pt(), R_Decay); // Omega+ + if (eventSelections.requireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 12 /* No other collision within +/- 10 microseconds */); + } - // if (!IsParticleFromOutOfBunchPileupCollision){fill the 1.5, 3.5 etc} AliPhysics analysis - } + if (eventSelections.requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 13 /* No other collision within +/- 2 microseconds */); } - } - PROCESS_SWITCH(v0cascadesQA, processMcEvent, "Process MC level Event", true); - //////////////////////////////////////////// - ////////// V0 QA - Reconstructed /////////// - //////////////////////////////////////////// + if (eventSelections.requireNoCollInROFStd && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 14 /* No other collision within the same ITS ROF with mult. above a certain threshold */); + } - Configurable V0_rapidity{"V0_rapidity", 0.5, "rapidity"}; - Configurable V0_cosPA{"V0_cosPA", 0.995, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable V0_dcav0dau{"V0_dcav0dau", 1, "DCA V0 Daughters"}; - Configurable V0_dcapostopv{"V0_dcapostopv", 0.1, "DCA Pos To PV"}; - Configurable V0_dcanegtopv{"V0_dcanegtopv", 0.1, "DCA Neg To PV"}; - Configurable V0_radius{"V0_radius", 5, "v0radius"}; - Configurable NSigmaV0Pion{"NSigmaV0Pion", 6, "NSigmaV0Pion"}; - Configurable NSigmaV0Proton{"NSigmaV0Proton", 6, "NSigmaV0Proton"}; + if (eventSelections.requireNoCollInROFStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 15 /* No other collision within the same ITS ROF */); + } - static constexpr float defaultLifetimeCuts[1][2] = {{25., 20.}}; - Configurable> lifetimecut{"lifetimecut", {defaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0S"}}, "lifetimecut"}; - int ncoll = 0; + float collisionOccupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); + if (eventSelections.minOccupancy >= 0 && collisionOccupancy < eventSelections.minOccupancy) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 16 /* Below min occupancy */); + } - void processReconstructedV0(soa::Join::iterator const& collision, aod::V0Datas const& fullV0s, DaughterTracks&) - { - if (sel8 && !collision.sel8()) { - return; + if (eventSelections.maxOccupancy >= 0 && collisionOccupancy > eventSelections.maxOccupancy) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 17 /* Above max occupancy */); } - if (ncoll == 0) { - V0SelectionSummary->SetBinContent(1, V0_rapidity); - V0SelectionSummary->SetBinContent(2, V0_cosPA); - V0SelectionSummary->SetBinContent(3, V0_dcav0dau); - V0SelectionSummary->SetBinContent(4, V0_dcapostopv); - V0SelectionSummary->SetBinContent(5, V0_dcanegtopv); - V0SelectionSummary->SetBinContent(6, V0_radius); - V0SelectionSummary->SetBinContent(7, NSigmaV0Pion); - V0SelectionSummary->SetBinContent(8, NSigmaV0Proton); - V0SelectionSummary->SetBinContent(9, lifetimecut->get("lifetimecutLambda")); - V0SelectionSummary->SetBinContent(10, lifetimecut->get("lifetimecutK0S")); - - V0SelectionSummary->GetXaxis()->SetBinLabel(1, "rapidity"); - V0SelectionSummary->GetXaxis()->SetBinLabel(2, "cosPA"); - V0SelectionSummary->GetXaxis()->SetBinLabel(3, "dcav0dau"); - V0SelectionSummary->GetXaxis()->SetBinLabel(4, "dcapostopv"); - V0SelectionSummary->GetXaxis()->SetBinLabel(5, "dcanegtopv"); - V0SelectionSummary->GetXaxis()->SetBinLabel(6, "radius"); - V0SelectionSummary->GetXaxis()->SetBinLabel(7, "NSigmaV0Pion"); - V0SelectionSummary->GetXaxis()->SetBinLabel(8, "NSigmaV0Proton"); - V0SelectionSummary->GetXaxis()->SetBinLabel(9, "lifetimecutLambda"); - V0SelectionSummary->GetXaxis()->SetBinLabel(10, "lifetimecutK0S"); - } - ncoll++; - - for (auto& v0 : fullV0s) { + // Fetch interaction rate only if required (in order to limit ccdb calls) + auto bc = collision.template bc_as(); + double interactionRate = ((eventSelections.minIR >= 0 || eventSelections.maxIR >= 0) && !irSource.value.empty()) ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), irSource) * 1.e-3 : -1; + if (eventSelections.minIR >= 0 && interactionRate < eventSelections.minIR) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 18 /* Below min IR */); + } - // fillV0s(v0, collision.posX(), collision.posY(), collision.posZ()); + if (eventSelections.maxIR >= 0 && interactionRate > eventSelections.maxIR) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 19 /* Above max IR */); + } - auto posdau = v0.posTrack_as(); - auto negdau = v0.negTrack_as(); + if (eventSelections.requireINEL0 && !collision.isInelGt0()) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 20 /* INEL > 0 */); + } - if (posdau.eta() < 0. && negdau.eta() < 0.) { - dauEtaFlag = -1; - } else if (posdau.eta() >= 0. && negdau.eta() >= 0.) { - dauEtaFlag = 1; - } else { - dauEtaFlag = 0; - } + if (eventSelections.requireINEL1 && !collision.isInelGt1()) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 21 /* INEL > 1 */); + } - // check TPC - if (checkDauTPC && (!posdau.hasTPC() || !negdau.hasTPC())) { - continue; - } + if (!rctConfigurations.cfgRCTLabel.value.empty() && !rctFlagsChecker(collision)) { + return false; + } + if (fillHists) { + histos_event.fill(HIST("hEventSelection"), 22 /* Pass CBT condition */); + } - Int_t posITSNhits = 0, negITSNhits = 0; - for (unsigned int i = 0; i < 7; i++) { - if (posdau.itsClusterMap() & (1 << i)) { - posITSNhits++; - } - if (negdau.itsClusterMap() & (1 << i)) { - negITSNhits++; - } - } + return true; + } - histos_V0.fill(HIST("CosPA"), v0.v0cosPA()); - histos_V0.fill(HIST("V0Radius"), v0.v0radius()); - histos_V0.fill(HIST("V0DCANegToPV"), v0.dcanegtopv()); - histos_V0.fill(HIST("V0DCAPosToPV"), v0.dcapostopv()); - histos_V0.fill(HIST("V0DCAV0Daughters"), v0.dcaV0daughters()); + template + bool isV0Accepted(TV0 v0, TCollision collision, float rapidity, int v0Type) + // precalculate this information so that a check is one mask operation, not many + { + // Base topological variables + if (v0.v0radius() < v0Selections.v0radius) + return false; + if (v0.v0radius() > v0Selections.v0radiusMax) + return false; + if (std::abs(v0.dcapostopv()) < v0Selections.dcapostopv) + return false; + if (std::abs(v0.dcanegtopv()) < v0Selections.dcanegtopv) + return false; + if (v0.v0cosPA() < v0Selections.v0cospa) + return false; + if (v0.dcaV0daughters() > v0Selections.dcav0dau) + return false; + + // proper lifetime + if ((v0Type == kLambda || v0Type == kAntiLambda) && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 > v0Selections.lifetimecut->get("lifetimecutLambda")) + return false; + if (v0Type == kK0s && v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short > v0Selections.lifetimecut->get("lifetimecutK0s")) + return false; + + // armenteros (for K0s only) + if (v0Type == kK0s && v0Selections.armPodCut > 1e-4 && v0.qtarm() * v0Selections.armPodCut < std::abs(v0.alpha())) + return false; + + // rapidity + if (std::abs(rapidity) > v0Selections.rapidityCut) + return false; + + // competing mass rejection + if ((v0Type == kLambda || v0Type == kAntiLambda) && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0Selections.compMassRejection) + return false; + if (v0Type == kK0s && std::fabs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0Selections.compMassRejection) + return false; + + auto posTrackExtra = v0.template posTrack_as(); + auto negTrackExtra = v0.template negTrack_as(); + + // ITS quality flags + bool posIsFromAfterburner = posTrackExtra.isITSAfterburner(); + bool negIsFromAfterburner = negTrackExtra.isITSAfterburner(); + + // reject afterburner track or not + if (v0Selections.rejectPosITSafterburner && posIsFromAfterburner) + return false; + if (v0Selections.rejectNegITSafterburner && negIsFromAfterburner) + return false; + + // keep afterburner track or not + if (v0Selections.requirePosITSafterburnerOnly && !posIsFromAfterburner) + return false; + if (v0Selections.requireNegITSafterburnerOnly && !negIsFromAfterburner) + return false; + + // check minium ITS clusters + if (posTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; + if (negTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; + + // check maximum ITS chi2 per clusters + if (posTrackExtra.itsChi2NCl() > v0Selections.maxITSchi2PerNcls) + return false; + if (negTrackExtra.itsChi2NCl() > v0Selections.maxITSchi2PerNcls) + return false; + + // ITS only tag + if (v0Selections.requirePosITSonly) { + if (posTrackExtra.tpcNClsCrossedRows() > 0) + return false; + } + if (v0Selections.requireNegITSonly) { + if (negTrackExtra.tpcNClsCrossedRows() > 0) + return false; + } - float decayLength = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::sqrtSumOfSquares(v0.px(), v0.py(), v0.pz()); - histos_V0.fill(HIST("DecayLength"), decayLength); + // check minimum TPC crossed rows + if (posTrackExtra.tpcNClsCrossedRows() < v0Selections.minTPCrows) + return false; + if (negTrackExtra.tpcNClsCrossedRows() < v0Selections.minTPCrows) + return false; + + // check maximum TPC chi2 per clusters + if (posTrackExtra.tpcChi2NCl() > v0Selections.maxTPCchi2PerNcls) + return false; + if (negTrackExtra.tpcChi2NCl() > v0Selections.maxTPCchi2PerNcls) + return false; + + // check the maximum fraction of allowed shared TPC + if (posTrackExtra.tpcFractionSharedCls() > v0Selections.maxFractionTPCSharedClusters) + return false; + if (negTrackExtra.tpcFractionSharedCls() > v0Selections.maxFractionTPCSharedClusters) + return false; + + // TPC only tag + if (v0Selections.skipTPConly) { + if (posTrackExtra.hasTPC()) + return false; + if (negTrackExtra.hasTPC()) + return false; + } - float CtauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; - float CtauK0s = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; + // TPC PID + if (v0Type == kK0s) { + if (std::fabs(posTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCutK0Pi) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCutK0Pi) + return false; + } + if (v0Type == kLambda) { + if (std::fabs(posTrackExtra.tpcNSigmaPr()) > v0Selections.tpcPidNsigmaCutLaPr) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCutLaPi) + return false; + } + if (v0Type == kAntiLambda) { + if (std::fabs(posTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCutLaPi) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPr()) > v0Selections.tpcPidNsigmaCutLaPr) + return false; + } - if (v0.v0cosPA() > V0_cosPA && - v0.v0radius() > V0_radius && - v0.dcaV0daughters() < V0_dcav0dau && - TMath::Abs(v0.dcapostopv()) > V0_dcapostopv && TMath::Abs(v0.dcanegtopv()) > V0_dcanegtopv) { - - // K0Short - if (TMath::Abs(v0.yK0Short()) < V0_rapidity && - CtauK0s < lifetimecut->get("lifetimecutK0S") && - TMath::Abs(posdau.tpcNSigmaPi()) < NSigmaV0Pion && TMath::Abs(negdau.tpcNSigmaPi()) < NSigmaV0Pion) { - - histos_V0.fill(HIST("CtauK0s"), CtauK0s); - histos_V0.fill(HIST("DecayLengthK0s"), decayLength); - histos_V0.fill(HIST("InvMassK0S"), v0.pt(), v0.mK0Short(), dauEtaFlag); - histos_V0.fill(HIST("InvMassK0SVsPtVsPA"), v0.pt(), TMath::ACos(v0.v0cosPA()), v0.mK0Short()); - histos_V0.fill(HIST("V0DCAV0ToPVK0S"), v0.dcav0topv()); - if (doextraanalysis) { - histos_V0.fill(HIST("InvMassK0S_Radius"), v0.v0radius(), v0.mK0Short()); - histos_V0.fill(HIST("InvMassK0S_PtRadius"), v0.pt(), v0.v0radius(), v0.mK0Short()); - histos_V0.fill(HIST("InvMassK0S_EtaDaughters"), posdau.eta(), negdau.eta(), v0.mK0Short()); - histos_V0.fill(HIST("InvMassK0S_PhiDaughters"), posdau.phi(), negdau.phi(), v0.mK0Short()); - histos_V0.fill(HIST("InvMassK0S_ITSMapDaughters"), posITSNhits, negITSNhits, v0.mK0Short()); - } - } + // TOF Requirement checks + if (v0Selections.requirePosHasTOF && !v0.positiveHasTOF()) { + return false; + } + if (v0Selections.requireNegHasTOF && !v0.negativeHasTOF()) { + return false; + } - // Lambda - if (TMath::Abs(v0.yLambda()) < V0_rapidity && - CtauLambda < lifetimecut->get("lifetimecutLambda") && - TMath::Abs(posdau.tpcNSigmaPr()) < NSigmaV0Proton && TMath::Abs(negdau.tpcNSigmaPi()) < NSigmaV0Pion) { - - histos_V0.fill(HIST("DecayLengthLambda"), decayLength); - histos_V0.fill(HIST("CtauLambda"), CtauLambda); - histos_V0.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), dauEtaFlag); - if (doextraanalysis) - histos_V0.fill(HIST("InvMassLambdaVsPtVsPA"), v0.pt(), TMath::ACos(v0.v0cosPA()), v0.mLambda()); - histos_V0.fill(HIST("V0DCAV0ToPVLambda"), v0.dcav0topv()); - if (v0.v0cosPA() > 0.999 && v0.dcaV0daughters() < 1 && TMath::Abs(v0.mK0Short() - o2::constants::physics::MassK0Short) > 0.012 && TMath::Abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) > 0.08 && TMath::Abs(v0.mLambda() - o2::constants::physics::MassLambda0) < 0.002) { - histos_V0.fill(HIST("ResponsePionFromLambda"), v0.pt(), negdau.tpcNSigmaPi()); - histos_V0.fill(HIST("ResponseProtonFromLambda"), v0.pt(), posdau.tpcNSigmaPr()); - } - if (doextraanalysis) { - histos_V0.fill(HIST("InvMassLambda_Radius"), v0.v0radius(), v0.mLambda()); - histos_V0.fill(HIST("InvMassLambda_PtRadius"), v0.pt(), v0.v0radius(), v0.mLambda()); - histos_V0.fill(HIST("InvMassLambda_Ctau"), CtauLambda, v0.mLambda()); - histos_V0.fill(HIST("InvMassLambda_EtaDaughters"), posdau.eta(), negdau.eta(), v0.mLambda()); - histos_V0.fill(HIST("InvMassLambda_PhiDaughters"), posdau.phi(), negdau.phi(), v0.mLambda()); - histos_V0.fill(HIST("InvMassLambda_ITSMapDaughters"), posITSNhits, negITSNhits, v0.mLambda()); - } - } + if (v0Selections.requireAtLeastOneHasTOF && !v0.positiveHasTOF() && !v0.negativeHasTOF()) { + return false; + } - // AntiLambda - if (TMath::Abs(v0.yLambda()) < V0_rapidity && - CtauLambda < lifetimecut->get("lifetimecutLambda") && - TMath::Abs(posdau.tpcNSigmaPi()) < NSigmaV0Pion && TMath::Abs(negdau.tpcNSigmaPr()) < NSigmaV0Proton) { - - histos_V0.fill(HIST("DecayLengthAntiLambda"), decayLength); - histos_V0.fill(HIST("CtauAntiLambda"), CtauLambda); - histos_V0.fill(HIST("InvMassAntiLambda"), v0.pt(), v0.mAntiLambda(), dauEtaFlag); - if (doextraanalysis) - histos_V0.fill(HIST("InvMassAntiLambdaVsPtVsPA"), v0.pt(), TMath::ACos(v0.v0cosPA()), v0.mAntiLambda()); - histos_V0.fill(HIST("V0DCAV0ToPVAntiLambda"), v0.dcav0topv()); - if (doextraanalysis) { - histos_V0.fill(HIST("InvMassAntiLambda_Radius"), v0.v0radius(), v0.mAntiLambda()); - histos_V0.fill(HIST("InvMassAntiLambda_PtRadius"), v0.pt(), v0.v0radius(), v0.mAntiLambda()); - histos_V0.fill(HIST("InvMassAntiLambda_Ctau"), CtauLambda, v0.mAntiLambda()); - histos_V0.fill(HIST("InvMassAntiLambda_EtaDaughters"), posdau.eta(), negdau.eta(), v0.mAntiLambda()); - histos_V0.fill(HIST("InvMassAntiLambda_PhiDaughters"), posdau.phi(), negdau.phi(), v0.mAntiLambda()); - histos_V0.fill(HIST("InvMassAntiLambda_ITSMapDaughters"), posITSNhits, negITSNhits, v0.mAntiLambda()); - } - } + // TOF Nsigma + if (v0Type == kK0s) { + if (v0Selections.tofPidNsigmaCutK0Pi < 1e+5 && v0.positiveHasTOF() && std::fabs(v0.tofNSigmaK0PiPlus()) > v0Selections.tofPidNsigmaCutK0Pi) { + return false; + } + if (v0Selections.tofPidNsigmaCutK0Pi < 1e+5 && v0.negativeHasTOF() && std::fabs(v0.tofNSigmaK0PiMinus()) > v0Selections.tofPidNsigmaCutK0Pi) { + return false; + } + } + if (v0Type == kLambda) { + if (v0Selections.tofPidNsigmaCutLaPr < 1e+5 && v0.positiveHasTOF() && std::fabs(v0.tofNSigmaLaPr()) > v0Selections.tofPidNsigmaCutLaPr) { + return false; + } + if (v0Selections.tofPidNsigmaCutLaPi < 1e+5 && v0.negativeHasTOF() && std::fabs(v0.tofNSigmaLaPi()) > v0Selections.tofPidNsigmaCutLaPi) { + return false; + } + } + if (v0Type == kAntiLambda) { + if (v0Selections.tofPidNsigmaCutLaPi < 1e+5 && v0.positiveHasTOF() && std::fabs(v0.tofNSigmaLaPi()) > v0Selections.tofPidNsigmaCutLaPi) { + return false; + } + if (v0Selections.tofPidNsigmaCutLaPr < 1e+5 && v0.negativeHasTOF() && std::fabs(v0.tofNSigmaLaPr()) > v0Selections.tofPidNsigmaCutLaPr) { + return false; } } - } - PROCESS_SWITCH(v0cascadesQA, processReconstructedV0, "Process reconstructed level V0s", true); - //////////////////////////////// - ////////// V0 QA - MC ////////// - //////////////////////////////// + // TRD Requirement checks + if (v0Selections.requirePosHasTRD && !posTrackExtra.hasTRD()) { + return false; + } + if (v0Selections.requireNegHasTRD && !negTrackExtra.hasTRD()) { + return false; + } + + int posTRDhits = 0, negTRDhits = 0; + for (unsigned int i = 0; i <= 5; i++) { + if (posTrackExtra.trdPattern() & (1 << i)) { + posTRDhits++; + } + if (negTrackExtra.trdPattern() & (1 << i)) { + negTRDhits++; + } + } + + if (posTrackExtra.hasTRD() && posTRDhits < v0Selections.minTRDclusters) { + return false; + } + if (negTrackExtra.hasTRD() && negTRDhits < v0Selections.minTRDclusters) { + return false; + } + + return true; + } - void processMcV0(soa::Join::iterator const& collision, soa::Join const& fullV0s, aod::McParticles const&, MyTracksMC const&) + template + bool isCascadeSelected(TCascade casc, TCollision collision, float rapidity, int cascType) + // precalculate this information so that a check is one mask operation, not many { - if (sel8 && !collision.sel8()) { - return; + // + // Base topological variables + // + + // v0 radius min/max selections + if (casc.v0radius() < cascSelections.v0radius) + return false; + if (casc.v0radius() > cascSelections.v0radiusMax) + return false; + // DCA proton and pion to PV for Lambda and AntiLambda decay hypotheses + if (casc.sign() < 0) { // Xi- or Omega- --> positive/negative daughter = proton/pion + if (std::fabs(casc.dcapostopv()) < cascSelections.dcaprotontopv) + return false; + if (std::fabs(casc.dcanegtopv()) < cascSelections.dcapiontopv) + return false; + } else { // Xi+ or Omega+ --> positive/negative daughter = pion/proton + if (std::fabs(casc.dcapostopv()) < cascSelections.dcapiontopv) + return false; + if (std::fabs(casc.dcanegtopv()) < cascSelections.dcaprotontopv) + return false; + } + // V0 cosine of pointing angle + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelections.v0cospa) + return false; + // DCA between v0 daughters + if (casc.dcaV0daughters() > cascSelections.dcav0dau) + return false; + // DCA V0 to prim vtx + if (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) < cascSelections.dcav0topv) + return false; + + // casc radius min/max selections + if (casc.cascradius() < cascSelections.cascradius) + return false; + if (casc.cascradius() > cascSelections.cascradiusMax) + return false; + // DCA bachelor selection + if (std::fabs(casc.dcabachtopv()) < cascSelections.dcabachtopv) + return false; + // Bachelor-baryon cosPA selection + if (casc.bachBaryonCosPA() < cascSelections.bachbaryoncospa) + return false; + // DCA bachelor-baryon selection + if (std::fabs(casc.bachBaryonDCAxyToPV()) < cascSelections.dcaxybachbaryontopv) + return false; + // casc cosine of pointing angle + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascSelections.casccospa) + return false; + // DCA between casc daughters + if (casc.dcacascdaughters() > cascSelections.dcacascdau) + return false; + + if (casc.sign() < 0 && (cascType == kXiP || cascType == kOmegaP)) + return false; + if (casc.sign() > 0 && (cascType == kXiM || cascType == kOmegaM)) + return false; + + // + // proper lifetime + float distOverTotMom = std::sqrt(std::pow(casc.x() - collision.posX(), 2) + std::pow(casc.y() - collision.posY(), 2) + std::pow(casc.z() - collision.posZ(), 2)) / (casc.p() + 1E-10); + if ((cascType == kXiM || cascType == kXiP) && distOverTotMom * o2::constants::physics::MassXiMinus > cascSelections.cascProperLifeTime) + return false; + if ((cascType == kOmegaM || cascType == kOmegaP) && distOverTotMom * o2::constants::physics::MassOmegaMinus > cascSelections.cascProperLifeTime) + return false; + + // rapidity + if (std::fabs(rapidity) > cascSelections.rapidityCut) + return false; + + // + // invariant mass window + // + if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascSelections.v0MassWindow) + return false; + + // + // competing mass rejection + // + if ((cascType == kXiM || cascType == kXiP) && std::fabs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < cascSelections.compMassRejection) + return false; + if ((cascType == kOmegaM || cascType == kOmegaP) && std::fabs(casc.mXi() - o2::constants::physics::MassXiMinus) < cascSelections.compMassRejection) + return false; + + auto bachTrackExtra = casc.template bachelor_as(); + auto posTrackExtra = casc.template posTrack_as(); + auto negTrackExtra = casc.template negTrack_as(); + + // ITS quality flags + if (bachTrackExtra.itsNCls() < cascSelections.minITSclusters) + return false; + if (posTrackExtra.itsNCls() < cascSelections.minITSclusters) + return false; + if (negTrackExtra.itsNCls() < cascSelections.minITSclusters) + return false; + + // TPC quality flags + if (bachTrackExtra.tpcNClsCrossedRows() < cascSelections.minTPCrows) + return false; + if (posTrackExtra.tpcNClsCrossedRows() < cascSelections.minTPCrows) + return false; + if (negTrackExtra.tpcNClsCrossedRows() < cascSelections.minTPCrows) + return false; + + // TPC PID + if ((cascType == kXiM || cascType == kXiP) && std::fabs(bachTrackExtra.tpcNSigmaPi()) > cascSelections.tpcPidNsigmaCut) + return false; + if ((cascType == kOmegaM || cascType == kOmegaP) && std::fabs(bachTrackExtra.tpcNSigmaKa()) > cascSelections.tpcPidNsigmaCut) + return false; + if (casc.sign() < 0) { // Xi- or Omega- --> positive/negative daughter = proton/pion + if (std::fabs(posTrackExtra.tpcNSigmaPr()) > cascSelections.tpcPidNsigmaCut) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPi()) > cascSelections.tpcPidNsigmaCut) + return false; + } else { // Xi+ or Omega+ --> positive/negative daughter = pion/proton + if (std::fabs(posTrackExtra.tpcNSigmaPi()) > cascSelections.tpcPidNsigmaCut) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPr()) > cascSelections.tpcPidNsigmaCut) + return false; + } + + // TOF Requirement checks + if (cascSelections.requireBachHasTOF && !casc.bachelorHasTOF()) { + return false; + } + if (cascSelections.requirePosHasTOF && !casc.positiveHasTOF()) { + return false; + } + if (cascSelections.requireNegHasTOF && !casc.negativeHasTOF()) { + return false; } - for (auto& v0 : fullV0s) { + if (cascSelections.requireAtLeastOneHasTOF && !casc.bachelorHasTOF() && !casc.positiveHasTOF() && !casc.negativeHasTOF()) { + return false; + } - if (!v0.has_mcParticle()) { - continue; + // + // TOF PID in NSigma + // Bachelor track + if (casc.bachelorHasTOF()) { + if ((cascType == kXiM || cascType == kXiP) && std::fabs(casc.tofNSigmaXiPi()) > cascSelections.tofPidNsigmaCutXiPi) + return false; + if ((cascType == kOmegaM || cascType == kOmegaP) && std::fabs(casc.tofNSigmaOmKa()) > cascSelections.tofPidNsigmaCutOmKa) + return false; + } + // Positive track + if (casc.positiveHasTOF()) { + if (casc.sign() < 0) { // Xi- or Omega- --> positive daughter = proton + if (cascType == kXiM && std::fabs(casc.tofNSigmaXiLaPr()) > cascSelections.tofPidNsigmaCutLaPr) + return false; + if (cascType == kOmegaM && std::fabs(casc.tofNSigmaOmLaPr()) > cascSelections.tofPidNsigmaCutLaPr) + return false; + } else { // Xi+ or Omega+ --> positive daughter = pion + if (cascType == kXiP && std::fabs(casc.tofNSigmaXiLaPi()) > cascSelections.tofPidNsigmaCutLaPi) + return false; + if (cascType == kOmegaP && std::fabs(casc.tofNSigmaOmLaPi()) > cascSelections.tofPidNsigmaCutLaPi) + return false; } - auto v0mcparticle = v0.mcParticle(); - Int_t lPDG = 0; - if (TMath::Abs(v0mcparticle.pdgCode()) == 310 || TMath::Abs(v0mcparticle.pdgCode()) == 3122) { - lPDG = v0mcparticle.pdgCode(); + } + // Negative track + if (casc.negativeHasTOF()) { + if (casc.sign() < 0) { // Xi- or Omega- --> negative daughter = pion + if (cascType == kXiM && std::fabs(casc.tofNSigmaXiLaPr()) > cascSelections.tofPidNsigmaCutLaPi) + return false; + if (cascType == kOmegaM && std::fabs(casc.tofNSigmaOmLaPr()) > cascSelections.tofPidNsigmaCutLaPi) + return false; + } else { // Xi+ or Omega+ --> negative daughter = proton + if (cascType == kXiP && std::fabs(casc.tofNSigmaXiLaPi()) > cascSelections.tofPidNsigmaCutLaPr) + return false; + if (cascType == kOmegaP && std::fabs(casc.tofNSigmaOmLaPi()) > cascSelections.tofPidNsigmaCutLaPr) + return false; } + } - float CtauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; - float CtauK0s = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; + // TRD Requirement checks + if (cascSelections.requireBachHasTRD && !bachTrackExtra.hasTRD()) { + return false; + } + if (cascSelections.requirePosHasTRD && !posTrackExtra.hasTRD()) { + return false; + } + if (cascSelections.requireNegHasTRD && !negTrackExtra.hasTRD()) { + return false; + } - if (v0.v0cosPA() > V0_cosPA && - v0.v0radius() > V0_radius && - v0.dcaV0daughters() < V0_dcav0dau && - TMath::Abs(v0.dcapostopv()) > V0_dcapostopv && - TMath::Abs(v0.dcanegtopv()) > V0_dcanegtopv) { - - // K0Short - if (lPDG == 310) { - if (TMath::Abs(v0.yK0Short()) < V0_rapidity && CtauK0s < lifetimecut->get("lifetimecutK0S")) { - histos_V0.fill(HIST("InvMassK0STrue"), v0.pt(), v0.v0radius(), v0.mK0Short()); - } - } - if (lPDG == 3122) { - if (TMath::Abs(v0.yLambda()) < V0_rapidity && CtauLambda < lifetimecut->get("lifetimecutLambda")) { - histos_V0.fill(HIST("InvMassLambdaTrue"), v0.pt(), v0.v0radius(), v0.mLambda()); - } - } - if (lPDG == -3122) { - if (TMath::Abs(v0.yLambda()) < V0_rapidity && CtauLambda < lifetimecut->get("lifetimecutLambda")) { - histos_V0.fill(HIST("InvMassAntiLambdaTrue"), v0.pt(), v0.v0radius(), v0.mAntiLambda()); - } - } + int bachTRDhits = 0, posTRDhits = 0, negTRDhits = 0; + for (unsigned int i = 0; i <= 5; i++) { + if (bachTrackExtra.trdPattern() & (1 << i)) { + bachTRDhits++; + } + if (posTrackExtra.trdPattern() & (1 << i)) { + posTRDhits++; + } + if (negTrackExtra.trdPattern() & (1 << i)) { + negTRDhits++; } } + + if (bachTrackExtra.hasTRD() && bachTRDhits < cascSelections.minTRDclusters) { + return false; + } + if (posTrackExtra.hasTRD() && posTRDhits < cascSelections.minTRDclusters) { + return false; + } + if (negTrackExtra.hasTRD() && negTRDhits < cascSelections.minTRDclusters) { + return false; + } + + return true; + } + + template + bool checkV0MCAssociation(TV0 v0, int v0Type) + // precalculate this information so that a check is one mask operation, not many + { + if (!v0.isPhysicalPrimary()) + return false; + + bool isPositiveProton = v0.pdgCodePositive() == PDG_t::kProton; + bool isPositivePion = v0.pdgCodePositive() == PDG_t::kPiPlus || (doTreatPiToMuon && v0.pdgCodePositive() == PDG_t::kMuonPlus); + bool isNegativeProton = v0.pdgCodeNegative() == PDG_t::kProtonBar; + bool isNegativePion = v0.pdgCodeNegative() == PDG_t::kPiMinus || (doTreatPiToMuon && v0.pdgCodeNegative() == PDG_t::kMuonMinus); + + if (v0Type == kK0s && v0.pdgCode() == PDG_t::kK0Short && isPositivePion && isNegativePion) { + return true; + } + if (v0Type == kLambda && v0.pdgCode() == PDG_t::kLambda0 && isPositiveProton && isNegativePion) { + return true; + } + if (v0Type == kAntiLambda && v0.pdgCode() == PDG_t::kLambda0Bar && isPositivePion && isNegativeProton) { + return true; + } + return false; + } + + template + bool checkCascadeMCAssociation(TCascade casc, int cascType) + // precalculate this information so that a check is one mask operation, not many + { + if (!casc.isPhysicalPrimary()) + return false; + + bool isBachelorPionPlus = casc.pdgCodeBachelor() == PDG_t::kPiPlus || (doTreatPiToMuon && casc.pdgCodeBachelor() == PDG_t::kMuonPlus); + bool isBachelorKaonPlus = casc.pdgCodeBachelor() == PDG_t::kKPlus; + bool isBachelorPionMinus = casc.pdgCodeBachelor() == PDG_t::kPiMinus || (doTreatPiToMuon && casc.pdgCodeBachelor() == PDG_t::kMuonMinus); + bool isBachelorKaonMinus = casc.pdgCodeBachelor() == PDG_t::kKMinus; + bool isPositiveProton = casc.pdgCodePositive() == PDG_t::kProton; + bool isPositivePion = casc.pdgCodePositive() == PDG_t::kPiPlus || (doTreatPiToMuon && casc.pdgCodePositive() == PDG_t::kMuonPlus); + bool isNegativeProton = casc.pdgCodeNegative() == PDG_t::kProtonBar; + bool isNegativePion = casc.pdgCodeNegative() == PDG_t::kPiMinus || (doTreatPiToMuon && casc.pdgCodeNegative() == PDG_t::kMuonMinus); + + if (cascType == kXiM && casc.pdgCode() == PDG_t::kXiMinus && isPositiveProton && isNegativePion && isBachelorPionMinus) { + return true; + } + if (cascType == kXiP && casc.pdgCode() == PDG_t::kXiPlusBar && isPositivePion && isNegativeProton && isBachelorPionPlus) { + return true; + } + if (cascType == kOmegaM && casc.pdgCode() == PDG_t::kOmegaMinus && isPositiveProton && isNegativePion && isBachelorKaonMinus) { + return true; + } + if (cascType == kOmegaP && casc.pdgCode() == PDG_t::kOmegaPlusBar && isPositivePion && isNegativeProton && isBachelorKaonPlus) { + return true; + } + return false; } - PROCESS_SWITCH(v0cascadesQA, processMcV0, "Process MC level V0s", false); - - ////////////////////////////////////// - ///// Cascade QA - Reconstructed ///// - ////////////////////////////////////// - - Configurable Casc_rapidity{"Casc_rapidity", 0.5, "rapidity"}; - Configurable Casc_v0cospa{"Casc_V0cospa", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable Casc_casccospa{"Casc_casccospa", 0.98, "Cascade CosPA"}; // AliAnalysisTaskStrAODqa: 0.9992 //double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable Casc_dcav0dau{"Casc_dcav0dau", 1.0, "DCA V0 Daughters"}; // AliAnalysisTaskStrAODqa: 1. different scale - Configurable Casc_dcacascdau{"Casc_dcacascdau", 0.6, "DCA Casc Daughters"}; // AliAnalysisTaskStrAODqa: 0.3 different scale - Configurable Casc_dcav0topv{"Casc_dcav0topv", 0.1, "DCA Pos To PV"}; // AliAnalysisTaskStrAODqa: 0.15 different scale - Configurable Casc_dcabachtopv{"Casc_dcabachtopv", .1, "DCA Bach To PV"}; // AliAnalysisTaskStrAODqa: 0.17 different scale - Configurable Casc_dcapostopv{"Casc_dcapostopv", 0.1, "DCA V0 To PV"}; // AliAnalysisTaskStrAODqa: if( fCasc_charge>0 &&(fCasc_DcaPosToPV < 0.3 || fCasc_DcaNegToPV < 0.11)) return kFALSE; different scale - Configurable Casc_dcanegtopv{"Casc_dcanegtopv", 0.1, "DCA Neg To PV"}; // AliAnalysisTaskStrAODqa: if( fCasc_charge<0 &&(fCasc_DcaPosToPV < 0.11 || fCasc_DcaNegToPV < 0.3)) return kFALSE; different scale - Configurable Casc_v0radius{"Casc_v0radius", 0.9, "v0 radius"}; // AliAnalysisTaskStrAODqa: 5. - Configurable Casc_cascradius{"Casc_cascradius", 1.0, "cascade radius"}; // AliAnalysisTaskStrAODqa: 1. - Configurable NSigmaCascPion{"NSigmaCascPion", 6, "NSigmaCascPion"}; - Configurable NSigmaCascProton{"NSigmaCascProton", 6, "NSigmaCascProton"}; - Configurable NSigmaCascKaon{"NSigmaCascKaon", 6, "NSigmaCascKaon"}; - - // additional AliAnalysisTaskStrAODqa.cxx cuts not present here - // if( fCasc_LeastCRaws<70 ) return kFALSE; //assume LeastCRows - - // if( fCasc_V0CosPAToXi<0.99 ) return kFALSE; - - // if( TMath::Abs(fCasc_InvMassLambda-1.115683)>0.005) return kFALSE; - // if( (part > 4) && TMath::Abs(fCasc_InvMassXi-1.32171)<0.003) return kFALSE; - // if( (part<5) && (fCasc_CascCtauXi> (4.91*3)) ) return kFALSE; //4.91 is the ctau of xi in cm - // if( (part>=5) && (fCasc_CascCtauOmega > (2.461*3)) ) return kFALSE; //2.461 is the ctau of om in cm - - // if( (part==3) && (TMath::Abs(fCasc_NSigPosPion)>3 || TMath::Abs(fCasc_NSigNegProton)>3 || TMath::Abs(fCasc_NSigBacPion)>3) ) return kFALSE; - // if( (part==4) && (TMath::Abs(fCasc_NSigNegPion)>3 || TMath::Abs(fCasc_NSigPosProton)>3 || TMath::Abs(fCasc_NSigBacPion)>3) ) return kFALSE; - // if( (part==5) && (TMath::Abs(fCasc_NSigPosPion)>3 || TMath::Abs(fCasc_NSigNegProton)>3 || TMath::Abs(fCasc_NSigBacKaon)>3) ) return kFALSE; - // if( (part==6) && (TMath::Abs(fCasc_NSigNegPion)>3 || TMath::Abs(fCasc_NSigPosProton)>3 || TMath::Abs(fCasc_NSigBacKaon)>3) ) return kFALSE; - - void processReconstructedCascade(soa::Join::iterator const& collision, aod::CascDataExt const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, DaughterTracks&) + + //////////////////////////////////////////// + /////////// QA - Reconstructed ///////////// + //////////////////////////////////////////// + + void processReconstructed(soa::Join::iterator const& collision, soa::Join const& fullV0s, soa::Join const& fullCascades, DaughterTracks const&, aod::BCsWithTimestamps const&) { - if (sel8 && !collision.sel8()) { + histos_event.fill(HIST("hEventCounter"), 0.5); + if (!isEventAccepted(collision, true)) { return; } + histos_event.fill(HIST("hEventCounter"), 1.5); - for (auto& casc : Cascades) { - auto bachelor = casc.bachelor_as(); - auto posdau = casc.posTrack_as(); - auto negdau = casc.negTrack_as(); + for (auto const& v0 : fullV0s) { + 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 (posdau.eta() < 0. && negdau.eta() < 0. && bachelor.eta() < 0.) { + if (v0Selections.v0TypeSelection > -1 && v0.v0Type() != v0Selections.v0TypeSelection) + continue; // skip V0s that are not standard + + // fillV0s(v0, collision.posX(), collision.posY(), collision.posZ()); + + auto posdau = v0.posTrack_as(); + auto negdau = v0.negTrack_as(); + + if (v0.negativeeta() < 0. && v0.positiveeta() < 0.) { dauEtaFlag = -1; - } else if (posdau.eta() >= 0. && negdau.eta() >= 0. && bachelor.eta() >= 0.) { + } else if (v0.negativeeta() >= 0. && v0.positiveeta() >= 0.) { dauEtaFlag = 1; } else { dauEtaFlag = 0; } - // check TPC - if (checkDauTPC && (!posdau.hasTPC() || !negdau.hasTPC() || !bachelor.hasTPC())) { - continue; + histos_V0.fill(HIST("CosPA"), v0.v0cosPA()); + histos_V0.fill(HIST("Radius"), v0.v0radius()); + histos_V0.fill(HIST("DCANegToPV"), v0.dcanegtopv()); + histos_V0.fill(HIST("DCAPosToPV"), v0.dcapostopv()); + histos_V0.fill(HIST("DCAV0Daughters"), v0.dcaV0daughters()); + + float decayLength = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::sqrtSumOfSquares(v0.px(), v0.py(), v0.pz()); + histos_V0.fill(HIST("DecayLength"), decayLength); + + float CtauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + float CtauK0s = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; + + // K0Short + if (isV0Accepted(v0, collision, v0.rapidity(0), kK0s)) { + histos_V0.fill(HIST("CosPAK0s"), v0.v0cosPA()); + histos_V0.fill(HIST("RadiusK0s"), v0.v0radius()); + histos_V0.fill(HIST("DCANegToPVK0s"), v0.dcanegtopv()); + histos_V0.fill(HIST("DCAPosToPVK0s"), v0.dcapostopv()); + histos_V0.fill(HIST("DCAV0DaughtersK0s"), v0.dcaV0daughters()); + histos_V0.fill(HIST("DecayLengthK0s"), decayLength); + histos_V0.fill(HIST("LifetimeK0s"), CtauK0s); + histos_V0.fill(HIST("InvMassK0s"), v0.pt(), v0.mK0Short(), dauEtaFlag); + histos_V0.fill(HIST("DCAV0ToPVK0s"), v0.dcav0topv()); + histos_V0.fill(HIST("TPCPIDPosPionFromK0s"), v0.pt(), posdau.tpcNSigmaPi()); + histos_V0.fill(HIST("TPCPIDNegPionFromK0s"), v0.pt(), negdau.tpcNSigmaPi()); + if (doextraanalysis) { + histos_V0.fill(HIST("InvMassK0s_Radius"), v0.v0radius(), v0.mK0Short()); + histos_V0.fill(HIST("InvMassK0s_PtRadius"), v0.pt(), v0.v0radius(), v0.mK0Short()); + histos_V0.fill(HIST("InvMassK0s_Lifetime"), CtauK0s, v0.mK0Short()); + histos_V0.fill(HIST("InvMassK0s_EtaDaughters"), posdau.eta(), negdau.eta(), v0.mK0Short()); + histos_V0.fill(HIST("InvMassK0s_PhiDaughters"), posdau.phi(), negdau.phi(), v0.mK0Short()); + histos_V0.fill(HIST("InvMassK0s_ITSMapDaughters"), posdau.itsNCls(), negdau.itsNCls(), v0.mK0Short()); + histos_V0.fill(HIST("InvMassK0sVsPtVsPA"), v0.pt(), std::acos(v0.v0cosPA()), v0.mK0Short()); + } + } + + // Lambda + if (isV0Accepted(v0, collision, v0.rapidity(1), kLambda)) { + histos_V0.fill(HIST("CosPALambda"), v0.v0cosPA()); + histos_V0.fill(HIST("RadiusLambda"), v0.v0radius()); + histos_V0.fill(HIST("DCANegToPVLambda"), v0.dcanegtopv()); + histos_V0.fill(HIST("DCAPosToPVLambda"), v0.dcapostopv()); + histos_V0.fill(HIST("DCAV0DaughtersLambda"), v0.dcaV0daughters()); + histos_V0.fill(HIST("DecayLengthLambda"), decayLength); + histos_V0.fill(HIST("LifetimeLambda"), CtauLambda); + histos_V0.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), dauEtaFlag); + histos_V0.fill(HIST("DCAV0ToPVLambda"), v0.dcav0topv()); + histos_V0.fill(HIST("TPCPIDPionFromLambda"), v0.pt(), negdau.tpcNSigmaPi()); + histos_V0.fill(HIST("TPCPIDProtonFromLambda"), v0.pt(), posdau.tpcNSigmaPr()); + if (doextraanalysis) { + histos_V0.fill(HIST("InvMassLambda_Radius"), v0.v0radius(), v0.mLambda()); + histos_V0.fill(HIST("InvMassLambda_PtRadius"), v0.pt(), v0.v0radius(), v0.mLambda()); + histos_V0.fill(HIST("InvMassLambda_Lifetime"), CtauLambda, v0.mLambda()); + histos_V0.fill(HIST("InvMassLambda_EtaDaughters"), posdau.eta(), negdau.eta(), v0.mLambda()); + histos_V0.fill(HIST("InvMassLambda_PhiDaughters"), posdau.phi(), negdau.phi(), v0.mLambda()); + histos_V0.fill(HIST("InvMassLambda_ITSMapDaughters"), posdau.itsNCls(), negdau.itsNCls(), v0.mLambda()); + histos_V0.fill(HIST("InvMassLambdaVsPtVsPA"), v0.pt(), std::acos(v0.v0cosPA()), v0.mLambda()); + } } - // histos_Casc.fill(HIST("XiProgSelections"), ); - // histos_Casc.fill(HIST("OmegaProgSelections"), ); + // AntiLambda + if (isV0Accepted(v0, collision, v0.rapidity(2), kAntiLambda)) { + histos_V0.fill(HIST("CosPAAntiLambda"), v0.v0cosPA()); + histos_V0.fill(HIST("RadiusAntiLambda"), v0.v0radius()); + histos_V0.fill(HIST("DCANegToPVAntiLambda"), v0.dcanegtopv()); + histos_V0.fill(HIST("DCAPosToPVAntiLambda"), v0.dcapostopv()); + histos_V0.fill(HIST("DCAV0DaughtersAntiLambda"), v0.dcaV0daughters()); + histos_V0.fill(HIST("DecayLengthAntiLambda"), decayLength); + histos_V0.fill(HIST("LifetimeAntiLambda"), CtauLambda); + histos_V0.fill(HIST("InvMassAntiLambda"), v0.pt(), v0.mAntiLambda(), dauEtaFlag); + histos_V0.fill(HIST("DCAV0ToPVAntiLambda"), v0.dcav0topv()); + histos_V0.fill(HIST("TPCPIDPionFromAntiLambda"), v0.pt(), posdau.tpcNSigmaPi()); + histos_V0.fill(HIST("TPCPIDProtonFromAntiLambda"), v0.pt(), negdau.tpcNSigmaPr()); + if (doextraanalysis) { + histos_V0.fill(HIST("InvMassAntiLambda_Radius"), v0.v0radius(), v0.mAntiLambda()); + histos_V0.fill(HIST("InvMassAntiLambda_PtRadius"), v0.pt(), v0.v0radius(), v0.mAntiLambda()); + histos_V0.fill(HIST("InvMassAntiLambda_Lifetime"), CtauLambda, v0.mAntiLambda()); + histos_V0.fill(HIST("InvMassAntiLambda_EtaDaughters"), posdau.eta(), negdau.eta(), v0.mAntiLambda()); + histos_V0.fill(HIST("InvMassAntiLambda_PhiDaughters"), posdau.phi(), negdau.phi(), v0.mAntiLambda()); + histos_V0.fill(HIST("InvMassAntiLambda_ITSMapDaughters"), posdau.itsNCls(), negdau.itsNCls(), v0.mAntiLambda()); + histos_V0.fill(HIST("InvMassAntiLambdaVsPtVsPA"), v0.pt(), std::acos(v0.v0cosPA()), v0.mAntiLambda()); + } + } + } + + for (auto const& casc : fullCascades) { + if (std::abs(casc.negativeeta()) > cascSelections.daughterEtaCut || + std::abs(casc.positiveeta()) > cascSelections.daughterEtaCut || + std::abs(casc.bacheloreta()) > cascSelections.daughterEtaCut) + continue; // remove acceptance that's badly reproduced by MC / superfluous in future + histos_Casc.fill(HIST("CascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.sign()); histos_Casc.fill(HIST("V0CosPA"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.sign()); - // double v0cospatoxi = RecoDecay::CPA(array{casc.x(), casc.y(), casc.z()}, array{casc.xlambda(), casc.ylambda(), casc.zlambda()}, array{v0.px(), v0.py(), v0.pz()}); - double v0cospatoxi = RecoDecay::cpa(array{casc.x(), casc.y(), casc.z()}, array{casc.xlambda(), casc.ylambda(), casc.zlambda()}, array{casc.pxpos() + casc.pxneg(), casc.pypos() + casc.pyneg(), casc.pzpos() + casc.pzneg()}); + double v0cospatoxi = RecoDecay::cpa(std::array{casc.x(), casc.y(), casc.z()}, array{casc.xlambda(), casc.ylambda(), casc.zlambda()}, std::array{casc.pxpos() + casc.pxneg(), casc.pypos() + casc.pyneg(), casc.pzpos() + casc.pzneg()}); histos_Casc.fill(HIST("V0CosPAToXi"), v0cospatoxi, casc.sign()); histos_Casc.fill(HIST("CascRadius"), casc.cascradius(), casc.sign()); histos_Casc.fill(HIST("V0Radius"), casc.v0radius(), casc.sign()); - histos_Casc.fill(HIST("CascyXi"), casc.yXi(), casc.sign()); - histos_Casc.fill(HIST("CascyOmega"), casc.yOmega(), casc.sign()); + histos_Casc.fill(HIST("CascRapidityXi"), casc.yXi(), casc.sign()); + histos_Casc.fill(HIST("CascRapidityOmega"), casc.yOmega(), casc.sign()); float cascDecayLength = std::sqrt(std::pow(casc.x() - collision.posX(), 2) + std::pow(casc.y() - collision.posY(), 2) + std::pow(casc.z() - collision.posZ(), 2)); histos_Casc.fill(HIST("CascDecayLength"), cascDecayLength, casc.sign()); - histos_Casc.fill(HIST("CascDecayLengthXi"), cascDecayLength, casc.sign()); - histos_Casc.fill(HIST("CascDecayLengthOmega"), cascDecayLength, casc.sign()); float cascTotalMomentum = RecoDecay::sqrtSumOfSquares(casc.px(), casc.py(), casc.pz()); float CtauXi = cascDecayLength / (cascTotalMomentum + 1E-10) * o2::constants::physics::MassXi0; // see O2Physics/Common/Core/MC.h for codes and names accepted @@ -625,9 +1216,9 @@ struct v0cascadesQA { float v0DecayLength = std::sqrt(std::pow(casc.xlambda() - casc.x(), 2) + std::pow(casc.ylambda() - casc.y(), 2) + std::pow(casc.zlambda() - casc.z(), 2)); float CtauV0 = v0DecayLength / (v0TotalMomentum + 1E-10) * o2::constants::physics::MassLambda0; - histos_Casc.fill(HIST("CascCtauXi"), CtauXi, casc.sign()); - histos_Casc.fill(HIST("CascCtauOmega"), CtauOmega, casc.sign()); - histos_Casc.fill(HIST("V0Ctau"), CtauV0, casc.sign()); + histos_Casc.fill(HIST("CascLifetimeXi"), CtauXi, casc.sign()); + histos_Casc.fill(HIST("CascLifetimeOmega"), CtauOmega, casc.sign()); + histos_Casc.fill(HIST("V0Lifetime"), CtauV0, casc.sign()); histos_Casc.fill(HIST("CascPt"), casc.pt(), casc.sign()); histos_Casc.fill(HIST("DcaV0Daughters"), casc.dcaV0daughters(), casc.sign()); histos_Casc.fill(HIST("DcaCascDaughters"), casc.dcacascdaughters(), casc.sign()); @@ -635,176 +1226,196 @@ struct v0cascadesQA { histos_Casc.fill(HIST("DcaBachToPV"), casc.dcabachtopv(), casc.sign()); histos_Casc.fill(HIST("DcaPosToPV"), casc.dcapostopv(), casc.sign()); histos_Casc.fill(HIST("DcaNegToPV"), casc.dcanegtopv(), casc.sign()); - histos_Casc.fill(HIST("InvMassLambdaDaughter"), casc.mLambda(), casc.sign()); - - if (casc.v0radius() > Casc_v0radius && - casc.cascradius() > Casc_cascradius && - casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > Casc_v0cospa && - casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > Casc_casccospa && - TMath::Abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) > Casc_dcav0topv && - TMath::Abs(casc.dcapostopv()) > Casc_dcapostopv && TMath::Abs(casc.dcanegtopv()) > Casc_dcanegtopv && TMath::Abs(casc.dcabachtopv()) > Casc_dcabachtopv && - casc.dcaV0daughters() < Casc_dcav0dau && casc.dcacascdaughters() < Casc_dcacascdau) { - if (casc.sign() < 0) { - if (TMath::Abs(posdau.tpcNSigmaPr()) < NSigmaCascProton && TMath::Abs(negdau.tpcNSigmaPi()) < NSigmaCascPion) { - if (TMath::Abs(casc.yXi()) < Casc_rapidity && TMath::Abs(bachelor.tpcNSigmaPi()) < NSigmaCascPion) { - histos_Casc.fill(HIST("InvMassXiMinus"), casc.pt(), casc.mXi(), casc.eta()); - histos_Casc.fill(HIST("InvMassXiMinus_Radius"), casc.cascradius(), casc.mXi()); - } - if (TMath::Abs(casc.yOmega()) < Casc_rapidity && TMath::Abs(bachelor.tpcNSigmaKa()) < NSigmaCascKaon) { - histos_Casc.fill(HIST("InvMassOmegaMinus"), casc.pt(), casc.mOmega(), casc.eta()); - } - } - } else { - if (TMath::Abs(posdau.tpcNSigmaPi()) < NSigmaCascPion && TMath::Abs(negdau.tpcNSigmaPr()) < NSigmaCascProton) { - if (TMath::Abs(casc.yXi()) < Casc_rapidity && TMath::Abs(bachelor.tpcNSigmaPi()) < NSigmaCascPion) { - histos_Casc.fill(HIST("InvMassXiPlus"), casc.pt(), casc.mXi(), casc.eta()); - histos_Casc.fill(HIST("InvMassXiPlus_Radius"), casc.cascradius(), casc.mXi()); - } - if (TMath::Abs(casc.yOmega()) < Casc_rapidity && TMath::Abs(bachelor.tpcNSigmaKa()) < NSigmaCascKaon) { - histos_Casc.fill(HIST("InvMassOmegaPlus"), casc.pt(), casc.mOmega(), casc.eta()); - } - } - } + histos_Casc.fill(HIST("InvMassLambda"), casc.mLambda(), casc.sign()); + + if (isCascadeSelected(casc, collision, casc.rapidity(0), kXiM)) { + histos_Casc.fill(HIST("InvMassXiMinus"), casc.pt(), casc.mXi(), casc.eta()); + histos_Casc.fill(HIST("InvMassXiMinus_Radius"), casc.cascradius(), casc.mXi()); + } + if (isCascadeSelected(casc, collision, casc.rapidity(0), kXiP)) { + histos_Casc.fill(HIST("InvMassXiPlus"), casc.pt(), casc.mXi(), casc.eta()); + histos_Casc.fill(HIST("InvMassXiPlus_Radius"), casc.cascradius(), casc.mXi()); + } + if (isCascadeSelected(casc, collision, casc.rapidity(2), kOmegaM)) { + histos_Casc.fill(HIST("InvMassOmegaMinus"), casc.pt(), casc.mOmega(), casc.eta()); + } + if (isCascadeSelected(casc, collision, casc.rapidity(2), kOmegaP)) { + histos_Casc.fill(HIST("InvMassOmegaPlus"), casc.pt(), casc.mOmega(), casc.eta()); } } } - PROCESS_SWITCH(v0cascadesQA, processReconstructedCascade, "Process reconstructed level Cascades", true); - ////////////////////////////////////// - ////////// Cascade QA - MC /////////// - ////////////////////////////////////// + //////////////////////////////// + ////////// QA - MC ///////////// + //////////////////////////////// - void processMcCascade(soa::Join::iterator const& collision, aod::CascDataExt const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, MyTracksMC const&, aod::McParticles const&) + void processMonteCarlo(soa::Join::iterator const& collision, soa::Join const&, soa::Join const& fullV0s, soa::Join const&, soa::Join const& fullCascades, soa::Join const&, DaughterTracks const&, aod::BCsWithTimestamps const&) { - if (sel8 && !collision.sel8()) { + if (!isEventAccepted(collision, false)) { + return; + } + if (!collision.has_mcCollision()) + return; + auto mcCollision = collision.mcCollision_as>(); + // Apply selections on MC collisions + if (eventSelections.applyZVtxSelOnMCPV && std::abs(mcCollision.posZ()) > eventSelections.maxZVtxPosition) { + return; + } + if (eventSelections.requireINEL0 && mcCollision.multMCNParticlesEta10() < 1) { + return; + } + if (eventSelections.requireINEL1 && mcCollision.multMCNParticlesEta10() < 2) { return; } - for (auto& casc : Cascades) { + for (auto const& v0 : fullV0s) { + 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 - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 0.5); + if (v0Selections.v0TypeSelection > -1 && v0.v0Type() != v0Selections.v0TypeSelection) + continue; // skip V0s that are not standard - if (casc.v0radius() > Casc_v0radius && - casc.cascradius() > Casc_cascradius && - casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > Casc_v0cospa && - casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > Casc_casccospa && - TMath::Abs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) > Casc_dcav0topv && - TMath::Abs(casc.dcapostopv()) > Casc_dcapostopv && TMath::Abs(casc.dcanegtopv()) > Casc_dcanegtopv && TMath::Abs(casc.dcabachtopv()) > Casc_dcabachtopv && - casc.dcaV0daughters() < Casc_dcav0dau && casc.dcacascdaughters() < Casc_dcacascdau) { + if (!v0.has_v0MCCore()) + continue; - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 1.5); + auto v0MC = v0.template v0MCCore_as>(); - auto reconegtrack = casc.negTrack_as(); - auto recopostrack = casc.posTrack_as(); - auto recobachelor = casc.bachelor_as(); - if (!reconegtrack.has_mcParticle() || !recopostrack.has_mcParticle() || !recobachelor.has_mcParticle()) { - continue; - } - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 2.5); + // K0Short + if (isV0Accepted(v0, collision, v0MC.rapidityMC(0), kK0s) && checkV0MCAssociation(v0MC, kK0s)) { + histos_V0.fill(HIST("InvMassK0sTrue"), v0MC.ptMC(), v0.v0radius(), v0.mK0Short()); + } + // Lambda + if (isV0Accepted(v0, collision, v0MC.rapidityMC(1), kLambda) && checkV0MCAssociation(v0MC, kLambda)) { + histos_V0.fill(HIST("InvMassLambdaTrue"), v0MC.ptMC(), v0.v0radius(), v0.mLambda()); + } + // AntiLambda + if (isV0Accepted(v0, collision, v0MC.rapidityMC(2), kAntiLambda) && checkV0MCAssociation(v0MC, kAntiLambda)) { + histos_V0.fill(HIST("InvMassAntiLambdaTrue"), v0MC.ptMC(), v0.v0radius(), v0.mAntiLambda()); + } + } - auto mcnegtrack = reconegtrack.mcParticle_as(); - auto mcpostrack = recopostrack.mcParticle_as(); - auto bachelor = recobachelor.mcParticle_as(); - if (!mcnegtrack.has_mothers() || !mcpostrack.has_mothers() || !bachelor.has_mothers()) { - continue; + for (auto const& casc : fullCascades) { + if (std::abs(casc.negativeeta()) > cascSelections.daughterEtaCut || + std::abs(casc.positiveeta()) > cascSelections.daughterEtaCut || + std::abs(casc.bacheloreta()) > cascSelections.daughterEtaCut) + continue; // remove acceptance that's badly reproduced by MC / superfluous in future + + if (!casc.has_cascMCCore()) + continue; + + auto cascMC = casc.template cascMCCore_as>(); + + histos_Casc.fill(HIST("QA_CascadeCandidates"), 0.5); + + if (isCascadeSelected(casc, collision, cascMC.rapidityMC(0), kXiM)) { + histos_Casc.fill(HIST("QA_CascCandidates"), 1.5); + if (checkCascadeMCAssociation(cascMC, kXiM)) { + histos_Casc.fill(HIST("QA_CascadeCandidates"), 2.5); + histos_Casc.fill(HIST("InvMassXiMinusTrue"), cascMC.ptMC(), casc.cascradius(), casc.mXi()); } - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 3.5); - - for (auto& particleMotherOfBach : bachelor.mothers_as()) { - for (auto& particleMotherOfNeg : mcnegtrack.mothers_as()) { - for (auto& particleMotherOfPos : mcpostrack.mothers_as()) { - for (auto& particleMotherOfV0 : particleMotherOfNeg.mothers_as()) { - - bool MomOfBachIsPrimary = particleMotherOfBach.isPhysicalPrimary(); - bool MomOfNegIsPrimary = particleMotherOfNeg.isPhysicalPrimary(); - bool MomOfPosIsPrimary = particleMotherOfPos.isPhysicalPrimary(); - - bool isXiMinusCascade = MomOfBachIsPrimary && !(MomOfNegIsPrimary) && !(MomOfPosIsPrimary) && - particleMotherOfNeg == particleMotherOfPos && - particleMotherOfV0 == particleMotherOfBach && - particleMotherOfBach.pdgCode() == 3312 && - bachelor.pdgCode() == -211 && - particleMotherOfNeg.pdgCode() == 3122 && - mcnegtrack.pdgCode() == -211 && - mcpostrack.pdgCode() == 2212; - - bool isOmegaMinusCascade = MomOfBachIsPrimary && !(MomOfNegIsPrimary) && !(MomOfPosIsPrimary) && - particleMotherOfNeg == particleMotherOfPos && - particleMotherOfV0 == particleMotherOfBach && - particleMotherOfBach.pdgCode() == 3334 && - bachelor.pdgCode() == -321 && - particleMotherOfNeg.pdgCode() == 3122 && - mcnegtrack.pdgCode() == -211 && - mcpostrack.pdgCode() == 2212; - - bool isXiPlusCascade = MomOfBachIsPrimary && !(MomOfNegIsPrimary) && !(MomOfPosIsPrimary) && - particleMotherOfNeg == particleMotherOfPos && - particleMotherOfV0 == particleMotherOfBach && - particleMotherOfBach.pdgCode() == -3312 && - bachelor.pdgCode() == 211 && - particleMotherOfNeg.pdgCode() == -3122 && - mcnegtrack.pdgCode() == -2212 && - mcpostrack.pdgCode() == 211; - - bool isOmegaPlusCascade = MomOfBachIsPrimary && !(MomOfNegIsPrimary) && !(MomOfPosIsPrimary) && - particleMotherOfNeg == particleMotherOfPos && - particleMotherOfV0 == particleMotherOfBach && - particleMotherOfBach.pdgCode() == -3334 && - bachelor.pdgCode() == 321 && - particleMotherOfNeg.pdgCode() == -3122 && - mcnegtrack.pdgCode() == -2212 && - mcpostrack.pdgCode() == 211; - - if (isXiMinusCascade) { - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 8.5); - if (TMath::Abs(casc.yXi()) < Casc_rapidity) { - histos_Casc.fill(HIST("InvMassXiMinusTrue"), casc.pt(), casc.cascradius(), casc.mXi()); - } - } - - if (isOmegaMinusCascade) { - if (TMath::Abs(casc.yOmega()) < Casc_rapidity) { - histos_Casc.fill(HIST("InvMassOmegaMinusTrue"), casc.pt(), casc.cascradius(), casc.mOmega()); - } - } - - if (isXiPlusCascade) { - if (TMath::Abs(casc.yXi()) < Casc_rapidity) { - histos_Casc.fill(HIST("InvMassXiPlusTrue"), casc.pt(), casc.cascradius(), casc.mXi()); - } - } - - if (isOmegaPlusCascade) { - if (TMath::Abs(casc.yOmega()) < Casc_rapidity) { - histos_Casc.fill(HIST("InvMassOmegaPlusTrue"), casc.pt(), casc.cascradius(), casc.mOmega()); - } - } - - // QA section - XiMinus - if (MomOfBachIsPrimary && !(MomOfNegIsPrimary) && !(MomOfPosIsPrimary)) { - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 4.5); - } - if ((particleMotherOfNeg.pdgCode() == particleMotherOfPos.pdgCode())) { - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 5.5); - } - if ((particleMotherOfV0 == particleMotherOfBach)) { - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 6.5); - } - if (particleMotherOfBach.pdgCode() == 3312 && - bachelor.pdgCode() == -211 && - particleMotherOfNeg.pdgCode() == 3122 && - mcnegtrack.pdgCode() == -211 && - mcpostrack.pdgCode() == 2212) { - histos_Casc.fill(HIST("QA_XiMinusCandidates"), 7.5); - } - } - } - } + } + if (isCascadeSelected(casc, collision, cascMC.rapidityMC(0), kXiP)) { + histos_Casc.fill(HIST("QA_CascadeCandidates"), 3.5); + if (checkCascadeMCAssociation(cascMC, kXiP)) { + histos_Casc.fill(HIST("QA_CascadeCandidates"), 4.5); + histos_Casc.fill(HIST("InvMassXiPlusTrue"), cascMC.ptMC(), casc.cascradius(), casc.mXi()); + } + } + if (isCascadeSelected(casc, collision, cascMC.rapidityMC(2), kOmegaM)) { + histos_Casc.fill(HIST("QA_CascCandidates"), 5.5); + if (checkCascadeMCAssociation(cascMC, kOmegaM)) { + histos_Casc.fill(HIST("QA_CascadeCandidates"), 6.5); + histos_Casc.fill(HIST("InvMassOmegaMinusTrue"), cascMC.ptMC(), casc.cascradius(), casc.mOmega()); + } + } + if (isCascadeSelected(casc, collision, cascMC.rapidityMC(2), kOmegaP)) { + histos_Casc.fill(HIST("QA_CascadeCandidates"), 7.5); + if (checkCascadeMCAssociation(cascMC, kOmegaP)) { + histos_Casc.fill(HIST("QA_CascadeCandidates"), 8.5); + histos_Casc.fill(HIST("InvMassOmegaPlusTrue"), cascMC.ptMC(), casc.cascradius(), casc.mOmega()); } } } } - PROCESS_SWITCH(v0cascadesQA, processMcCascade, "Process MC level Cascades", false); + + /////////////////////////////////////// + ////////// Collision QA - MC ////////// + /////////////////////////////////////// + + void processGenerated(soa::Join::iterator const& mcCollision, aod::McParticles const& mcParticles, soa::SmallGroups> const& collisions) + { + // Apply selections on MC collisions + if (eventSelections.applyZVtxSelOnMCPV && std::abs(mcCollision.posZ()) > eventSelections.maxZVtxPosition) { + return; + } + if (eventSelections.requireINEL0 && mcCollision.multMCNParticlesEta10() < 1) { + return; + } + if (eventSelections.requireINEL1 && mcCollision.multMCNParticlesEta10() < 2) { + return; + } + + histos_event.fill(HIST("hEventCounterMC"), 0.5); + + // Check if there is at least one of the reconstructed collisions associated to this MC collision + // If so, we consider it + bool atLeastOne = false; + for (const auto& collision : collisions) { + if (!isEventAccepted(collision, false)) { + continue; + } + atLeastOne = true; + } + + if (!atLeastOne) { // Check that the event is reconstructed and that the reconstructed events pass the selection + return; + } + + histos_event.fill(HIST("hEventCounterMC"), 1.5); + + for (auto const& mcparticle : mcParticles) { + + if (!mcparticle.has_daughters()) { + continue; + } + + double vx = 0; + double vy = 0; + for (auto const& mcparticleDaughter0 : mcparticle.daughters_as()) { + vx = mcparticleDaughter0.vx(); + vy = mcparticleDaughter0.vy(); + if (vx != 0 && vy != 0) + break; + } + double R_Decay = std::sqrt(vx * vx + vy * vy); + + if (mcparticle.isPhysicalPrimary() && std::abs(mcparticle.y()) < v0Selections.rapidityCut) { + if (mcparticle.pdgCode() == PDG_t::kK0Short) + histos_event.fill(HIST("GeneratedV0s"), 0.5, mcparticle.pt(), R_Decay); // K0s + if (mcparticle.pdgCode() == PDG_t::kLambda0) + histos_event.fill(HIST("GeneratedV0s"), 1.5, mcparticle.pt(), R_Decay); // Lambda + if (mcparticle.pdgCode() == PDG_t::kLambda0Bar) + histos_event.fill(HIST("GeneratedV0s"), 2.5, mcparticle.pt(), R_Decay); // AntiLambda + } + if (mcparticle.isPhysicalPrimary() && std::abs(mcparticle.y()) < cascSelections.rapidityCut) { + if (mcparticle.pdgCode() == PDG_t::kXiMinus) + histos_event.fill(HIST("GeneratedCascades"), 0.5, mcparticle.pt(), R_Decay); // Xi- + if (mcparticle.pdgCode() == PDG_t::kXiPlusBar) + histos_event.fill(HIST("GeneratedCascades"), 1.5, mcparticle.pt(), R_Decay); // Xi+ + if (mcparticle.pdgCode() == PDG_t::kOmegaMinus) + histos_event.fill(HIST("GeneratedCascades"), 2.5, mcparticle.pt(), R_Decay); // Omega- + if (mcparticle.pdgCode() == PDG_t::kOmegaPlusBar) + histos_event.fill(HIST("GeneratedCascades"), 3.5, mcparticle.pt(), R_Decay); // Omega+ + + // if (!IsParticleFromOutOfBunchPileupCollision){fill the 1.5, 3.5 etc} AliPhysics analysis + } + } + } + + PROCESS_SWITCH(v0cascadesQA, processReconstructed, "Process reconstructed event and V0s+cascades in data", true); + PROCESS_SWITCH(v0cascadesQA, processMonteCarlo, "Process reconstructed event and V0s+cascades in MC", false); + PROCESS_SWITCH(v0cascadesQA, processGenerated, "Process MC level event and V0s+cascades in MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index e4bc31fc311..e129ce85dcf 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -254,8 +254,13 @@ o2physics_add_dpl_workflow(kstarinoo PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(phioo - SOURCES phiOO.cxx +o2physics_add_dpl_workflow(kstar0analysis + SOURCES kstar0analysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(phi1020analysis + SOURCES phi1020analysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -268,30 +273,37 @@ o2physics_add_dpl_workflow(phispectrapbpbqa SOURCES phispectrapbpbqa.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phi-1020-spherocity-analysis SOURCES phi1020SpherocityAnalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial SOURCES phitutorial.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(phitutorial-step0 + +o2physics_add_dpl_workflow(phitutorial-step0 SOURCES phitutorial_step0.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial-step1 SOURCES phitutorial_step1.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial-step2 SOURCES phitutorial_step2.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phitutorial-step3 SOURCES phitutorial_step3.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(k892hadronphoton SOURCES k892hadronphoton.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB diff --git a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx index 8ddda3fb237..6081e136eec 100644 --- a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx @@ -17,8 +17,11 @@ /// \author Navneet Kumar , Protay #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/inelGt.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" @@ -67,6 +70,8 @@ #include #include #include +#include +#include #include using namespace o2; @@ -74,6 +79,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; +using namespace o2::aod::rctsel; struct Chargedkstaranalysis { @@ -81,6 +87,9 @@ struct Chargedkstaranalysis { FT0C = 1, FT0M = 2 }; + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + struct : ConfigurableGroup { 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., 1., 5., 10., 30., 50., 70., 100., 110.}, "Mixing bins - multiplicity"}; @@ -103,7 +112,7 @@ struct Chargedkstaranalysis { Configurable activateProductionFrame{"activateProductionFrame", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; Configurable activateBeamAxisFrame{"activateBeamAxisFrame", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; Configurable activateRandomFrame{"activateRandomFrame", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; - Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; + Configurable cRotations{"cRotations", 5, "Number of random rotations in the rotational background"}; Configurable cBoostKShot{"cBoostKShot", true, "Boost the Kshot in Charged Kstar frame of reference"}; // Other cuts on Ks Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; @@ -122,9 +131,15 @@ struct Chargedkstaranalysis { using TrackCandidates = soa::Join; using V0Candidates = aod::V0Datas; + // for MC reco using MCEventCandidates = soa::Join; using MCTrackCandidates = soa::Join; using MCV0Candidates = soa::Join; + // for MC truth + using MCTrueEventCandidates = aod::McCollisions; + using MCTrueTrackCandidates = aod::McParticles; + + using LorentzVectorSetXYZM = ROOT::Math::LorentzVector>; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry hChaKstar{"hChaKstar", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -154,6 +169,17 @@ struct Chargedkstaranalysis { // Configurables Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; + struct RCTCut : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + + RCTFlagsChecker rctChecker; + }; + + RCTCut rctCut; + /// Event cuts o2::analysis::CollisonCuts colCuts; struct : ConfigurableGroup { @@ -170,6 +196,19 @@ struct Chargedkstaranalysis { Configurable confEvtNoITSROBorderCut{"confEvtNoITSROBorderCut", false, "Evt sel: apply NoITSRO border cut"}; Configurable confincludeCentralityMC{"confincludeCentralityMC", false, "Include centrality in MC"}; Configurable confEvtCollInTimeRangeStandard{"confEvtCollInTimeRangeStandard", true, "Evt sel: apply NoCollInTimeRangeStandard"}; + Configurable confEvtCollInTimeRangeNarrow{"confEvtCollInTimeRangeNarrow", false, "Evt sel: apply NoCollInTimeRangeNarrow"}; + + Configurable confEvtCollInTimeRangeStrict{"confEvtCollInTimeRangeStrict", false, "Evt sel: apply NoCollInTimeRangeStrict"}; + Configurable confEvtNoCollInRofStandard{"confEvtNoCollInRofStandard", false, "Evt sel: apply NoCollInRofStandard"}; + Configurable confEvtNoCollInRofStrict{"confEvtNoCollInRofStrict", false, "Evt sel: apply NoCollInRofStrict"}; + Configurable confEvtNoHighMultCollInPrevRof{"confEvtNoHighMultCollInPrevRof", false, "Evt sel: apply NoHighMultCollInPrevRof"}; + Configurable confEvtGoodITSLayersAll{"confEvtGoodITSLayersAll", false, "Evt sel: require all good ITS layers"}; + Configurable confEvtGoodITSLayer3{"confEvtGoodITSLayer3", false, "Evt sel: require good ITS layer 3"}; + Configurable confEvtGoodITSLayer0123{"confEvtGoodITSLayer0123", false, "Evt sel: require good ITS layers 0–3"}; + Configurable confEvtVertexTRDmatched{"confEvtVertexTRDmatched", false, "Evt sel: require TRD-matched vertex"}; + Configurable confEvtBBT0A{"confEvtBBT0A", false, "Evt sel: apply BBT0A cut"}; + Configurable confEvtBBT0C{"confEvtBBT0C", false, "Evt sel: apply BBT0C cut"}; + Configurable cfgEventCentralityMin{"cfgEventCentralityMin", 0.0f, "Event sel: minimum centrality"}; Configurable cfgEventCentralityMax{"cfgEventCentralityMax", 100.0f, "Event sel: maximum centrality"}; Configurable cfgCentEst{"cfgCentEst", static_cast(CentralityEstimator::FT0C), "Centrality estimator: 1=FT0C, 2=FT0M"}; @@ -202,6 +241,7 @@ struct Chargedkstaranalysis { Configurable cfgHasTPC{"cfgHasTPC", false, "Require TPC"}; Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; Configurable cfgpTdepDCAxyCut{"cfgpTdepDCAxyCut", true, "pT-dependent DCAxy cut"}; + Configurable cfgpTdepDCAzCut{"cfgpTdepDCAzCut", false, "pT-dependent DCAz cut"}; Configurable cfgMaxbDCArToPVcut{"cfgMaxbDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; Configurable cfgMaxbDCAzToPVcut{"cfgMaxbDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; } trackCutCfgs; @@ -220,9 +260,6 @@ struct Chargedkstaranalysis { struct : ConfigurableGroup { // Secondary Selection - Configurable cfgReturnFlag{"cfgReturnFlag", false, "Return Flag for debugging"}; - Configurable cSecondaryRequire{"cSecondaryRequire", true, "Secondary cuts on/off"}; - Configurable cfgByPassDauPIDSelection{"cfgByPassDauPIDSelection", true, "Bypass Daughters PID selection"}; Configurable cSecondaryDauDCAMax{"cSecondaryDauDCAMax", 1., "Maximum DCA Secondary daughters to PV"}; Configurable cSecondaryDauPosDCAtoPVMin{"cSecondaryDauPosDCAtoPVMin", 0.0, "Minimum DCA Secondary positive daughters to PV"}; @@ -236,6 +273,9 @@ struct Chargedkstaranalysis { Configurable cSecondaryDCAtoPVMax{"cSecondaryDCAtoPVMax", 0.3, "Maximum DCA Secondary to PV"}; Configurable cSecondaryProperLifetimeMax{"cSecondaryProperLifetimeMax", 20, "Maximum Secondary Lifetime"}; Configurable cSecondaryMassWindow{"cSecondaryMassWindow", 0.075, "Secondary inv mass selciton window"}; + Configurable cfgSecondaryparamArmenterosCut{"cfgSecondaryparamArmenterosCut", 0.2, "parameter for Armenteros Cut"}; + Configurable cfgSecondaryCrossMassHypothesisCut{"cfgSecondaryCrossMassHypothesisCut", false, "Apply cut based on the lambda mass hypothesis"}; + Configurable cfgSecondaryCrossMassCutWindow{"cfgSecondaryCrossMassCutWindow", 0.05, "Secondary inv mass selection window with (anti)lambda hypothesis"}; } secondaryCutsCfgs; @@ -245,14 +285,7 @@ struct Chargedkstaranalysis { Configurable cKstarMinRap{"cKstarMinRap", -0.5, "Kstar minimum rapidity"}; } kstarCutCfgs; - struct : ConfigurableGroup { - // For rotational background - Configurable cFillRotBkg{"cFillRotBkg", true, "Fill rotated background"}; - Configurable confMinRot{"confMinRot", 5.0 * o2::constants::math::PI / 6.0, "Minimum of rotation"}; - Configurable confMaxRot{"confMaxRot", 7.0 * o2::constants::math::PI / 6.0, "Maximum of rotation"}; - Configurable nBkgRotations{"nBkgRotations", 9, "Number of rotated copies (background) per each original candidate"}; - } rotBkgEstCfgs; - + Configurable isQaRequired{"isQaRequired", false, "Fill QA plots"}; float centrality; // PDG code @@ -268,15 +301,28 @@ struct Chargedkstaranalysis { { centrality = -999; - colCuts.setCuts(eventCutCfgs.confEvtZvtx, eventCutCfgs.confEvtTriggerCheck, eventCutCfgs.confEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, eventCutCfgs.confEvtOccupancyInTimeRangeMax, eventCutCfgs.confEvtOccupancyInTimeRangeMin); + colCuts.setCuts(eventCutCfgs.confEvtZvtx, eventCutCfgs.confEvtTriggerCheck, eventCutCfgs.confEvtOfflineCheck, /*checkRun3*/ true, eventCutCfgs.confEvtTriggerTVXSel, eventCutCfgs.confEvtOccupancyInTimeRangeMax, eventCutCfgs.confEvtOccupancyInTimeRangeMin); colCuts.init(&histos); colCuts.setTriggerTVX(eventCutCfgs.confEvtTriggerTVXSel); colCuts.setApplyTFBorderCut(eventCutCfgs.confEvtTFBorderCut); + colCuts.setApplyNoITSROBorderCut(eventCutCfgs.confEvtNoITSROBorderCut); colCuts.setApplyITSTPCvertex(eventCutCfgs.confEvtUseITSTPCvertex); colCuts.setApplyZvertexTimedifference(eventCutCfgs.confEvtZvertexTimedifference); colCuts.setApplyPileupRejection(eventCutCfgs.confEvtPileupRejection); - colCuts.setApplyNoITSROBorderCut(eventCutCfgs.confEvtNoITSROBorderCut); colCuts.setApplyCollInTimeRangeStandard(eventCutCfgs.confEvtCollInTimeRangeStandard); + colCuts.setApplyCollInTimeRangeNarrow(eventCutCfgs.confEvtCollInTimeRangeNarrow); + colCuts.setApplyCollInTimeRangeStrict(eventCutCfgs.confEvtCollInTimeRangeStrict); + colCuts.setApplyCollInRofStandard(eventCutCfgs.confEvtNoCollInRofStandard); + colCuts.setApplyCollInRofStrict(eventCutCfgs.confEvtNoCollInRofStrict); + colCuts.setApplyHighMultCollInPrevRof(eventCutCfgs.confEvtNoHighMultCollInPrevRof); + colCuts.setApplyGoodITSLayersAll(eventCutCfgs.confEvtGoodITSLayersAll); + colCuts.setApplyGoodITSLayer3(eventCutCfgs.confEvtGoodITSLayer3); + colCuts.setApplyGoodITSLayer0123(eventCutCfgs.confEvtGoodITSLayer0123); + colCuts.setApplyVertexTRDmatched(eventCutCfgs.confEvtVertexTRDmatched); + colCuts.setApplyBBT0A(eventCutCfgs.confEvtBBT0A); + colCuts.setApplyBBT0C(eventCutCfgs.confEvtBBT0C); + + rctCut.rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); AxisSpec centAxis = {axisCfgs.cfgBinsCent, "T0M (%)"}; AxisSpec vtxzAxis = {axisCfgs.cfgBinsVtxZ, "Z Vertex (cm)"}; @@ -289,7 +335,7 @@ struct Chargedkstaranalysis { AxisSpec dcaxyAxis = {200, 0, 2, "DCA_{#it{xy}} (cm)"}; AxisSpec dcazAxis = {200, 0, 2, "DCA_{#it{z}} (cm)"}; AxisSpec yAxis = {100, -1, 1, "Rapidity"}; - AxisSpec invMassAxisK0s = {400 / cNbinsDiv, 0.3, 0.7, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 + AxisSpec invMassAxisK0s = {800 / cNbinsDiv, 0.46, 0.54, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 AxisSpec invMassAxisReso = {900 / cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 AxisSpec invMassAxisScan = {150, 0, 1.5, "Invariant Mass (GeV/#it{c}^2)"}; // For selection AxisSpec pidQAAxis = {130, -6.5, 6.5}; @@ -300,171 +346,235 @@ struct Chargedkstaranalysis { // THnSparse AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; - histos.add("QA/K0sCutCheck", "Check K0s cut", HistType::kTH1D, {AxisSpec{12, -0.5, 11.5, "Check"}}); - - histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); - histos.add("QA/before/CentDist1", "Centrality distribution", o2::framework::kTH1F, {{110, 0, 110}}); - histos.add("QA/before/VtxZ", "Centrality distribution", {HistType::kTH1D, {vtxzAxis}}); - histos.add("QA/before/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); - - histos.add("QA/trkbpionTPCPIDME", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - - // Bachelor pion - histos.add("QA/before/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/before/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QA/before/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - histos.add("QA/after/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/after/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QA/after/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - // Secondary pion 1 - histos.add("QA/before/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/before/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/before/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); - - histos.add("QA/after/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/after/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/after/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); - - // Secondary pion 2 - histos.add("QA/before/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/before/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/before/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); - - histos.add("QA/after/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/after/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/after/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); - - // K0s - histos.add("QA/before/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); - histos.add("QA/before/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); - histos.add("QA/before/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); - histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); - histos.add("QA/before/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); - - histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); - histos.add("QA/after/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); - histos.add("QA/after/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); - histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); - histos.add("QA/after/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); - - // Kstar - // Invariant mass nSparse - histos.add("QA/before/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); - histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hInvmass_KstarME", "Invariant mass of unlike-sign chK(892)ME", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisReso}); - histos.add("hInvmass_KstarRotated", "Invariant mass of unlike-sign chK(892)Rota", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisReso}); - - // Mass QA (quick check) - histos.add("QA/before/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); - histos.add("QA/before/kstarinvmass_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTH1D, {invMassAxisReso}); - - histos.add("QA/after/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); - histos.add("QA/after/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); - histos.add("QA/after/kstarinvmass_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTH1D, {invMassAxisReso}); - - if (!helicityCfgs.qAOptimisation) { - hChaKstar.add("h3ChaKstarInvMassDS", "h3ChaKstarInvMassDS", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL, thnAxisPhi}, true); - hChaKstar.add("h3ChaKstarInvMassME", "h3ChaKstarInvMassME", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL, thnAxisPhi}, true); - hChaKstar.add("h3ChaKstarInvMassRot", "h3ChaKstarInvMassRot", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL, thnAxisPhi}, true); - } + if (!doprocessMC) { + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{5, 0, 5.0}}); + auto hCutFlow = histos.get(HIST("hEvtSelInfo")); + hCutFlow->GetXaxis()->SetBinLabel(1, "All Events"); + hCutFlow->GetXaxis()->SetBinLabel(2, "coll cuts"); + hCutFlow->GetXaxis()->SetBinLabel(3, "rctChecker"); + hCutFlow->GetXaxis()->SetBinLabel(4, "Multiplicity"); + hCutFlow->GetXaxis()->SetBinLabel(5, "IsINELgt0"); + if (isQaRequired) { + constexpr int kNTrackCuts = 22; + + histos.add("QA/hTrackCutFlow", "Track cut flow", kTH1I, {{kNTrackCuts, 0.5, kNTrackCuts + 0.5}}); + + auto hTrackCutFlow = histos.get(HIST("QA/hTrackCutFlow")); + + int bin = 1; + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "All tracks"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "pT min"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "|eta| max"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "ITS clusters"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "TPC clusters"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "TPC crossed rows ratio"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "ITS chi2/Ncl"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "TPC chi2/Ncl"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "Has ITS"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "Has TPC"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "Has TOF"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "ITS refit"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "TPC refit"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "PV contributor"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "Global w/o DCA"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "Global track"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "Primary track"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "DCAxy max"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "DCAz max"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "pT-dep DCAxy"); + hTrackCutFlow->GetXaxis()->SetBinLabel(bin++, "pT-dep DCAz"); + + constexpr int kNK0sCuts = 14; + int iK0sbin = 1; + histos.add("QA/K0sCutCheck", "K0s cut flow", kTH1I, {{kNK0sCuts, 0.5, kNK0sCuts + 0.5}}); + auto hK0sCut = histos.get(HIST("QA/K0sCutCheck")); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "All PASS"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "DauDCA>max"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "PosDCAtoPVGetXaxis()->SetBinLabel(iK0sbin++, "NegDCAtoPVGetXaxis()->SetBinLabel(iK0sbin++, "pTGetXaxis()->SetBinLabel(iK0sbin++, "|y|>max"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "Rmax"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "DCAtoPV>max"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "cosPAGetXaxis()->SetBinLabel(iK0sbin++, "ctau>max"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "qtarmGetXaxis()->SetBinLabel(iK0sbin++, "|M(K0s)-m0|>win"); + hK0sCut->GetXaxis()->SetBinLabel(iK0sbin++, "cross-mass veto"); + + histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); + histos.add("QA/before/CentDist1", "Centrality distribution", o2::framework::kTH1F, {{110, 0, 110}}); + histos.add("QA/before/VtxZ", "Centrality distribution", {HistType::kTH1D, {vtxzAxis}}); + histos.add("QA/before/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); + + histos.add("QA/trkbpionTPCPIDME", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + + // Bachelor pion + histos.add("QA/before/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QA/before/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + + histos.add("QA/after/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QA/after/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + + // Secondary pion 1 + histos.add("QA/before/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + // Secondary pion 2 + histos.add("QA/before/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s + histos.add("QA/before/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QA/before/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QA/before/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/before/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QA/after/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QA/after/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/after/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + // Kstar + // Invariant mass nSparse + histos.add("QA/before/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + + // Mass QA (quick check) + histos.add("QA/before/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); + histos.add("QA/before/kstarinvmass_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTH1D, {invMassAxisReso}); + + histos.add("QA/after/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + histos.add("QA/after/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); + histos.add("QA/after/kstarinvmass_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTH1D, {invMassAxisReso}); + } + if (!helicityCfgs.qAOptimisation) { + hChaKstar.add("h3ChaKstarInvMassDS", "h3ChaKstarInvMassDS", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL}, true); + hChaKstar.add("h3ChaKstarInvMassRot", "h3ChaKstarInvMassRot", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL}, true); - if (rotBkgEstCfgs.cFillRotBkg) { - histos.add("hRotation", "hRotation", kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); + // hChaKstar.add("h3ChaKstarInvMassDS", "h3ChaKstarInvMassDS", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL, thnAxisPhi}, true); + // hChaKstar.add("h3ChaKstarInvMassRot", "h3ChaKstarInvMassRot", kTHnSparseF, {centAxis, ptAxis, invMassAxisReso, thnAxisPOL, thnAxisPhi}, true); + } } // MC if (doprocessMC) { + if (isQaRequired) { + histos.add("QA/MC/QACent_woCut", "Centrality without cut", HistType::kTH1F, {centAxis}); + histos.add("QA/MC/QACent_woCentCut", "Centrality without cent cut", HistType::kTH1F, {centAxis}); + histos.add("QA/MC/QACent_wCentCut", "Centrality with cent cut", HistType::kTH1F, {centAxis}); + histos.add("QA/MC/QAvtxz_woCut", "z-vertex without cut", HistType::kTH1F, {vtxzAxis}); + histos.add("QA/MC/QAvtxz_wVtxzCut", "z-vertex with vtxz cut", HistType::kTH1F, {vtxzAxis}); + + histos.add("QAMC/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); + // Bachelor pion + histos.add("QAMC/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QAMC/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QAMC/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxis}); + histos.add("QAMC/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + + // Secondary pion 1 + histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QAMC/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QAMC/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxis}); + histos.add("QAMC/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + + // Secondary pion 2 + histos.add("QAMC/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); + histos.add("QAMC/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); + histos.add("QAMC/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QAMC/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxis}); + histos.add("QAMC/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QAMC/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + // Secondary Resonance (K0s cand) + histos.add("QAMC/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QAMC/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QAMC/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + + histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxis}); + histos.add("QAMC/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QAMC/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QAMC/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QAMC/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QAMC/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QAMC/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QAMC/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + // K892 + histos.add("QAMC/KstarOA", "Opening angle of chK(892)", HistType::kTH1D, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QAMC/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + + histos.add("QAMC/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); + histos.add("QAMC/kstarinvmass_noKstar", "Invariant mass of unlike-sign no chK(892)", HistType::kTH1D, {invMassAxisReso}); + } + histos.add("EffKstar/genKstar", "Gen Kstar (|y|<0.5)", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("EffKstar/genKstar_pri", "Gen primary Kstar (|y|<0.5)", HistType::kTH2F, {ptAxis, centAxis}); - histos.add("QAMC/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); - // Bachelor pion - histos.add("QAMC/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QAMC/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QAMC/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - // Secondary pion 1 - histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QAMC/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QAMC/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - // Secondary pion 2 - histos.add("QAMC/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QAMC/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QAMC/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); - - // Secondary Resonance (K0s cand) - histos.add("QAMC/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QAMC/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QAMC/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - - histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); - histos.add("QAMC/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); - histos.add("QAMC/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); - histos.add("QAMC/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QAMC/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); - histos.add("QAMC/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAMC/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); - - // K892 - histos.add("QAMC/KstarOA", "Opening angle of chK(892)", HistType::kTH1D, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QAMC/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); - - histos.add("QAMC/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); - histos.add("QAMC/kstarinvmass_noKstar", "Invariant mass of unlike-sign no chK(892)", HistType::kTH1D, {invMassAxisReso}); - - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisReso}); - - ccdb->setURL(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()); + histos.add("EffKstar/recoKstar", "Kstar Reco matched (final all)", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("MCReco/hInvmass_Kstar_true", "MC-reco truth-tagged chK(892)", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisReso}); } + ccdb->setURL(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()); + // Print output histograms statistics LOG(info) << "Size of the histograms in chK(892) Analysis Task"; histos.print(); } + + std::unordered_set allowedMcIds; + std::unordered_map centTruthByAllowed; + float lMultiplicity; template float getCentrality(CollisionType const& collision) @@ -481,59 +591,86 @@ struct Chargedkstaranalysis { } } - // Track selection template bool trackCut(TrackType const& track) { - // basic track cuts - if (std::abs(track.pt()) < trackCutCfgs.cMinPtcut) + int ibin = 1; + + auto applyCut = [&](bool condition) -> bool { + if (!condition) + return false; + if (!doprocessMC && isQaRequired) + histos.fill(HIST("QA/hTrackCutFlow"), ibin); + ibin++; + return true; + }; + + // First bin (before any cuts) + if (!doprocessMC && isQaRequired) + histos.fill(HIST("QA/hTrackCutFlow"), ibin++); + + // Cuts + if (!applyCut(std::abs(track.pt()) >= trackCutCfgs.cMinPtcut)) return false; - if (std::abs(track.eta()) > trackCutCfgs.cMaxEtacut) + if (!applyCut(std::abs(track.eta()) <= trackCutCfgs.cMaxEtacut)) return false; - if (track.itsNCls() < trackCutCfgs.cfgITScluster) + if (!applyCut(track.itsNCls() >= trackCutCfgs.cfgITScluster)) return false; - if (track.tpcNClsFound() < trackCutCfgs.cfgTPCcluster) + if (!applyCut(track.tpcNClsFound() >= trackCutCfgs.cfgTPCcluster)) return false; - if (track.tpcCrossedRowsOverFindableCls() < trackCutCfgs.cfgRatioTPCRowsOverFindableCls) + if (!applyCut(track.tpcCrossedRowsOverFindableCls() >= trackCutCfgs.cfgRatioTPCRowsOverFindableCls)) return false; - if (track.itsChi2NCl() >= trackCutCfgs.cfgITSChi2NCl) + if (!applyCut(track.itsChi2NCl() < trackCutCfgs.cfgITSChi2NCl)) return false; - if (track.tpcChi2NCl() >= trackCutCfgs.cfgTPCChi2NCl) + if (!applyCut(track.tpcChi2NCl() < trackCutCfgs.cfgTPCChi2NCl)) return false; - if (trackCutCfgs.cfgHasITS && !track.hasITS()) + + if (!applyCut(!trackCutCfgs.cfgHasITS || track.hasITS())) return false; - if (trackCutCfgs.cfgHasTPC && !track.hasTPC()) + if (!applyCut(!trackCutCfgs.cfgHasTPC || track.hasTPC())) return false; - if (trackCutCfgs.cfgHasTOF && !track.hasTOF()) + if (!applyCut(!trackCutCfgs.cfgHasTOF || track.hasTOF())) return false; - if (trackCutCfgs.cfgUseITSRefit && !track.passedITSRefit()) + + if (!applyCut(!trackCutCfgs.cfgUseITSRefit || track.passedITSRefit())) return false; - if (trackCutCfgs.cfgUseTPCRefit && !track.passedTPCRefit()) + if (!applyCut(!trackCutCfgs.cfgUseTPCRefit || track.passedTPCRefit())) return false; - if (trackCutCfgs.cfgPVContributor && !track.isPVContributor()) + + if (!applyCut(!trackCutCfgs.cfgPVContributor || track.isPVContributor())) return false; - if (trackCutCfgs.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (!applyCut(!trackCutCfgs.cfgGlobalWoDCATrack || track.isGlobalTrackWoDCA())) return false; - if (trackCutCfgs.cfgGlobalTrack && !track.isGlobalTrack()) + if (!applyCut(!trackCutCfgs.cfgGlobalTrack || track.isGlobalTrack())) return false; - if (trackCutCfgs.cfgPrimaryTrack && !track.isPrimaryTrack()) + if (!applyCut(!trackCutCfgs.cfgPrimaryTrack || track.isPrimaryTrack())) return false; - if (std::abs(track.dcaXY()) > trackCutCfgs.cMaxbDCArToPVcut) + + if (!applyCut(std::abs(track.dcaXY()) <= trackCutCfgs.cMaxbDCArToPVcut)) return false; - if (std::abs(track.dcaZ()) > trackCutCfgs.cMaxbDCAzToPVcut) + if (!applyCut(std::abs(track.dcaZ()) <= trackCutCfgs.cMaxbDCAzToPVcut)) return false; + + // pT dependent DCA XY if (trackCutCfgs.cfgpTdepDCAxyCut) { - if (std::abs(track.dcaXY()) > (0.004 + (0.013 / track.pt()))) + if (!applyCut(std::abs(track.dcaXY()) <= (0.004 + (0.013 / track.pt())))) return false; } else { - if (std::abs(track.dcaXY()) > trackCutCfgs.cfgMaxbDCArToPVcut) + if (!applyCut(std::abs(track.dcaXY()) <= trackCutCfgs.cfgMaxbDCArToPVcut)) return false; } - if (std::abs(track.dcaZ()) > trackCutCfgs.cfgMaxbDCAzToPVcut) - return false; + + // pT dependent DCA Z + if (trackCutCfgs.cfgpTdepDCAzCut) { + if (!applyCut(std::abs(track.dcaZ()) <= (0.004 + (0.013 / track.pt())))) + return false; + } else { + if (!applyCut(std::abs(track.dcaZ()) <= trackCutCfgs.cfgMaxbDCAzToPVcut)) + return false; + } + return true; } - // PID selection tools template bool selectionPIDPion(TrackType const& candidate) @@ -560,130 +697,52 @@ struct Chargedkstaranalysis { template bool selectionK0s(CollisionType const& collision, K0sType const& candidate) { - auto dauDCA = candidate.dcaV0daughters(); - auto dauPosDCAtoPV = candidate.dcapostopv(); - auto dauNegDCAtoPV = candidate.dcanegtopv(); + int ibin = 1; + bool returnFlag = true; + + auto applyCut = [&](bool condition) { + if (!condition) { + returnFlag = false; + } + if (returnFlag && (!doprocessMC && isQaRequired)) { + histos.fill(HIST("QA/K0sCutCheck"), ibin); + } + ibin++; + }; + + // Precompute variables + auto dauDCA = std::fabs(candidate.dcaV0daughters()); + auto dauPosDCAtoPV = std::fabs(candidate.dcapostopv()); + auto dauNegDCAtoPV = std::fabs(candidate.dcanegtopv()); auto pT = candidate.pt(); auto rapidity = candidate.yK0Short(); auto v0Radius = candidate.v0radius(); - auto dcaToPV = candidate.dcav0topv(); + auto dcaToPV = std::fabs(candidate.dcav0topv()); auto cosPA = candidate.v0cosPA(); auto propTauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0s; auto mK0s = candidate.mK0Short(); - - if (secondaryCutsCfgs.cfgReturnFlag) { - bool returnFlag = true; - - if (secondaryCutsCfgs.cSecondaryRequire) { - histos.fill(HIST("QA/K0sCutCheck"), 0); - if (dauDCA > secondaryCutsCfgs.cSecondaryDauDCAMax) { - histos.fill(HIST("QA/K0sCutCheck"), 1); - returnFlag = false; - } - if (dauPosDCAtoPV < secondaryCutsCfgs.cSecondaryDauPosDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 2); - returnFlag = false; - } - if (dauNegDCAtoPV < secondaryCutsCfgs.cSecondaryDauNegDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 3); - returnFlag = false; - } - if (pT < secondaryCutsCfgs.cSecondaryPtMin) { - histos.fill(HIST("QA/K0sCutCheck"), 4); - returnFlag = false; - } - if (rapidity > secondaryCutsCfgs.cSecondaryRapidityMax) { - histos.fill(HIST("QA/K0sCutCheck"), 5); - returnFlag = false; - } - if (v0Radius < secondaryCutsCfgs.cSecondaryRadiusMin || v0Radius > secondaryCutsCfgs.cSecondaryRadiusMax) { - histos.fill(HIST("QA/K0sCutCheck"), 6); - returnFlag = false; - } - if (dcaToPV > secondaryCutsCfgs.cSecondaryDCAtoPVMax) { - histos.fill(HIST("QA/K0sCutCheck"), 7); - returnFlag = false; - } - if (cosPA < secondaryCutsCfgs.cSecondaryCosPAMin) { - histos.fill(HIST("QA/K0sCutCheck"), 8); - returnFlag = false; - } - if (propTauK0s > secondaryCutsCfgs.cSecondaryProperLifetimeMax) { - histos.fill(HIST("QA/K0sCutCheck"), 9); - returnFlag = false; - } - if (std::fabs(mK0s - massK0s) > secondaryCutsCfgs.cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - returnFlag = false; - } - - return returnFlag; - - } else { - if (std::fabs(mK0s - massK0s) > secondaryCutsCfgs.cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - returnFlag = false; - } - - return returnFlag; - } - - } else { - if (secondaryCutsCfgs.cSecondaryRequire) { - - histos.fill(HIST("QA/K0sCutCheck"), 0); - if (dauDCA > secondaryCutsCfgs.cSecondaryDauDCAMax) { - histos.fill(HIST("QA/K0sCutCheck"), 1); - return false; - } - if (dauPosDCAtoPV < secondaryCutsCfgs.cSecondaryDauPosDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 2); - return false; - } - if (dauNegDCAtoPV < secondaryCutsCfgs.cSecondaryDauNegDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 3); - return false; - } - if (pT < secondaryCutsCfgs.cSecondaryPtMin) { - histos.fill(HIST("QA/K0sCutCheck"), 4); - return false; - } - if (rapidity > secondaryCutsCfgs.cSecondaryRapidityMax) { - histos.fill(HIST("QA/K0sCutCheck"), 5); - return false; - } - if (v0Radius < secondaryCutsCfgs.cSecondaryRadiusMin || v0Radius > secondaryCutsCfgs.cSecondaryRadiusMax) { - histos.fill(HIST("QA/K0sCutCheck"), 6); - return false; - } - if (dcaToPV > secondaryCutsCfgs.cSecondaryDCAtoPVMax) { - histos.fill(HIST("QA/K0sCutCheck"), 7); - return false; - } - if (cosPA < secondaryCutsCfgs.cSecondaryCosPAMin) { - histos.fill(HIST("QA/K0sCutCheck"), 8); - return false; - } - if (propTauK0s > secondaryCutsCfgs.cSecondaryProperLifetimeMax) { - histos.fill(HIST("QA/K0sCutCheck"), 9); - return false; - } - if (std::fabs(mK0s - massK0s) > secondaryCutsCfgs.cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - return false; - } - return true; - - } else { - if (std::fabs(mK0s - massK0s) > secondaryCutsCfgs.cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - return false; - } - return true; - } - } - } // selectionK0s - + auto mLambda = candidate.mLambda(); + auto mALambda = candidate.mAntiLambda(); + + if (!doprocessMC && isQaRequired) + histos.fill(HIST("QA/K0sCutCheck"), ibin); + + applyCut(dauDCA <= secondaryCutsCfgs.cSecondaryDauDCAMax); + applyCut(dauPosDCAtoPV >= secondaryCutsCfgs.cSecondaryDauPosDCAtoPVMin); + applyCut(dauNegDCAtoPV >= secondaryCutsCfgs.cSecondaryDauNegDCAtoPVMin); + applyCut(pT >= secondaryCutsCfgs.cSecondaryPtMin); + applyCut(std::fabs(rapidity) <= secondaryCutsCfgs.cSecondaryRapidityMax); + applyCut(v0Radius >= secondaryCutsCfgs.cSecondaryRadiusMin && v0Radius <= secondaryCutsCfgs.cSecondaryRadiusMax); + applyCut(dcaToPV <= secondaryCutsCfgs.cSecondaryDCAtoPVMax); + applyCut(cosPA >= secondaryCutsCfgs.cSecondaryCosPAMin); + applyCut(propTauK0s <= secondaryCutsCfgs.cSecondaryProperLifetimeMax); + applyCut(candidate.qtarm() >= secondaryCutsCfgs.cfgSecondaryparamArmenterosCut * std::fabs(candidate.alpha())); + applyCut(std::fabs(mK0s - MassK0Short) <= secondaryCutsCfgs.cSecondaryMassWindow); + + applyCut(!secondaryCutsCfgs.cfgSecondaryCrossMassHypothesisCut || ((std::fabs(mLambda - MassLambda0) >= secondaryCutsCfgs.cfgSecondaryCrossMassCutWindow) && (std::fabs(mALambda - MassLambda0Bar) >= secondaryCutsCfgs.cfgSecondaryCrossMassCutWindow))); + + return returnFlag; + } template bool isTrueKstar(const TrackTemplate& bTrack, const V0Template& K0scand) { @@ -722,6 +781,53 @@ struct Chargedkstaranalysis { double massPi = o2::constants::physics::MassPionCharged; double massK0s = o2::constants::physics::MassK0Short; + template + bool matchRecoToTruthKstar(V0T const& v0, TrkT const& trk) + { + if (!v0.has_mcParticle() || !trk.has_mcParticle()) + return false; + + auto mcK0s = v0.template mcParticle_as(); + auto mcPi = trk.template mcParticle_as(); + + if (std::abs(mcK0s.pdgCode()) != kPDGK0s) + return false; + if (std::abs(mcPi.pdgCode()) != kPiPlus) + return false; + + MCTrueTrackCandidates::iterator kstarFromPi; + bool havePiKstar = false; + for (const auto& m1 : mcPi.template mothers_as()) { + if (std::abs(m1.pdgCode()) == kKstarPlus) { + kstarFromPi = m1; + havePiKstar = true; + break; + } + } + if (!havePiKstar) { + return false; + } + + bool shareSameKstar = false; + for (const auto& m1 : mcK0s.template mothers_as()) { + if (std::abs(m1.pdgCode()) == kPDGK0) { + for (const auto& m2 : m1.template mothers_as()) { + if (m2.globalIndex() == kstarFromPi.globalIndex()) { + shareSameKstar = true; + break; + } + } + if (shareSameKstar) + break; + } + } + if (!shareSameKstar) { + return false; + } + + return true; + } // matchRecoToTruthKstar + template void fillInvMass(const T& mother, float multiplicity, const T& daughter1, const T& daughter2, bool isMix) { @@ -775,7 +881,7 @@ struct Chargedkstaranalysis { auto cosThetaStarHelicity = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); if (!isMix) { if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity, anglePhi); + hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); //, anglePhi); } for (int i = 0; i < helicityCfgs.cRotations; i++) { @@ -791,18 +897,14 @@ struct Chargedkstaranalysis { auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); auto phiHelicityRot = std::atan2(yaxisHE.Dot(daughterRotCM.Vect().Unit()), xaxisHE.Dot(daughterRotCM.Vect().Unit())); phiHelicityRot = RecoDecay::constrainAngle(phiHelicityRot, 0.0); - if (motherRot.Rapidity() < helicityCfgs.rapidityMotherData) - hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot, phiHelicityRot); - } - } else { - if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity, anglePhi); + if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) + hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot); //, phiHelicityRot); } } } else if (helicityCfgs.activateCollinsSoperFrame) { if (!isMix) { if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarCS, phiCS); + hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarCS); //, phiCS); } for (int i = 0; i < helicityCfgs.cRotations; i++) { @@ -819,12 +921,8 @@ struct Chargedkstaranalysis { auto phiCSrot = std::atan2(yAxisCS.Dot(daughterRotCM.Vect().Unit()), xAxisCS.Dot(daughterRotCM.Vect().Unit())); phiCSrot = RecoDecay::constrainAngle(phiCSrot, 0.0); - if (motherRot.Rapidity() < helicityCfgs.rapidityMotherData) - hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarCSrot, phiCSrot); - } - } else { - if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarCS, phiCS); + if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) + hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarCSrot); //, phiCSrot); } } } else if (helicityCfgs.activateProductionFrame) { @@ -832,38 +930,30 @@ struct Chargedkstaranalysis { auto cosThetaProduction = normalVec.Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(normalVec.Mag2())); if (!isMix) { if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaProduction, anglePhi); + hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaProduction); //, anglePhi); } for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); motherRot = ROOT::Math::PxPyPzMVector(mother.Px() * std::cos(theta2) - mother.Py() * std::sin(theta2), mother.Px() * std::sin(theta2) + mother.Py() * std::cos(theta2), mother.Pz(), mother.M()); if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaProduction, anglePhi); + hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaProduction); //, anglePhi); } } - } else { - if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaProduction, anglePhi); - } } } else if (helicityCfgs.activateBeamAxisFrame) { beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); auto cosThetaStarBeam = beamVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); if (!isMix) { if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam, anglePhi); + hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); //, anglePhi); } for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); motherRot = ROOT::Math::PxPyPzMVector(mother.Px() * std::cos(theta2) - mother.Py() * std::sin(theta2), mother.Px() * std::sin(theta2) + mother.Py() * std::cos(theta2), mother.Pz(), mother.M()); if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam, anglePhi); + hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam); //, anglePhi); } } - } else { - if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam, anglePhi); - } } } else if (helicityCfgs.activateRandomFrame) { auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); @@ -873,19 +963,15 @@ struct Chargedkstaranalysis { auto cosThetaStarRandom = randomVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); if (!isMix) { if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom, phiRandom); + hChaKstar.fill(HIST("h3ChaKstarInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); //, phiRandom); } for (int i = 0; i < helicityCfgs.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / helicityCfgs.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / helicityCfgs.rotationalCut); motherRot = ROOT::Math::PxPyPzMVector(mother.Px() * std::cos(theta2) - mother.Py() * std::sin(theta2), mother.Px() * std::sin(theta2) + mother.Py() * std::cos(theta2), mother.Pz(), mother.M()); if (std::abs(motherRot.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom, phiRandom); + hChaKstar.fill(HIST("h3ChaKstarInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom); //, phiRandom); } } - } else { - if (std::abs(mother.Rapidity()) < helicityCfgs.rapidityMotherData) { - hChaKstar.fill(HIST("h3ChaKstarInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom, phiRandom); - } } } // } @@ -894,69 +980,82 @@ struct Chargedkstaranalysis { template void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksTypeK0s& dTracks2) { - histos.fill(HIST("QA/before/CentDist"), collision.centFT0M()); - histos.fill(HIST("QA/before/CentDist1"), collision.centFT0M()); - ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResoSecondary, lDecayDaughter_bach, lResoKstar, chargeKstarrot; - std::vector trackIndicies = {}; - std::vector k0sIndicies = {}; + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/before/CentDist"), collision.centFT0M()); + histos.fill(HIST("QA/before/CentDist1"), collision.centFT0M()); + } + + ROOT::Math::PxPyPzMVector lResoSecondary, lDecayDaughter_bach, lResoKstar, chargeKstarrot; + std::vector trackIndicies; + std::vector k0sIndicies; + + // ========================= + // Bachelor tracks + // ========================= for (const auto& bTrack : dTracks1) { + auto trkbpt = bTrack.pt(); auto istrkbhasTOF = bTrack.hasTOF(); auto trkbNSigmaPiTPC = bTrack.tpcNSigmaPi(); - auto trkbNSigmaPiTOF = (istrkbhasTOF) ? bTrack.tofNSigmaPi() : -999.; + auto trkbNSigmaPiTOF = istrkbhasTOF ? bTrack.tofNSigmaPi() : -999.; if constexpr (!IsMix) { - // Bachelor pion QA plots - histos.fill(HIST("QA/before/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); - if (istrkbhasTOF) { - histos.fill(HIST("QA/before/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); - histos.fill(HIST("QA/before/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/before/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); + if (istrkbhasTOF) { + histos.fill(HIST("QA/before/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); + histos.fill(HIST("QA/before/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trkbpionpT"), trkbpt); + histos.fill(HIST("QA/before/trkbpionDCAxy"), bTrack.dcaXY()); + histos.fill(HIST("QA/before/trkbpionDCAz"), bTrack.dcaZ()); } - histos.fill(HIST("QA/before/trkbpionpT"), trkbpt); - histos.fill(HIST("QA/before/trkbpionDCAxy"), bTrack.dcaXY()); - histos.fill(HIST("QA/before/trkbpionDCAz"), bTrack.dcaZ()); } else { - - histos.fill(HIST("QA/trkbpionTPCPIDME"), trkbpt, trkbNSigmaPiTPC); + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/trkbpionTPCPIDME"), trkbpt, trkbNSigmaPiTPC); + } } - if (!trackCut(bTrack)) - continue; - if (!selectionPIDPion(bTrack)) + if (!trackCut(bTrack) || !selectionPIDPion(bTrack)) continue; if constexpr (!IsMix) { - // Bachelor pion QA plots after applying cuts - histos.fill(HIST("QA/after/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); - if (istrkbhasTOF) { - histos.fill(HIST("QA/after/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); - histos.fill(HIST("QA/after/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/after/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); + if (istrkbhasTOF) { + histos.fill(HIST("QA/after/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); + histos.fill(HIST("QA/after/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkbpionpT"), trkbpt); + histos.fill(HIST("QA/after/trkbpionDCAxy"), bTrack.dcaXY()); + histos.fill(HIST("QA/after/trkbpionDCAz"), bTrack.dcaZ()); } - histos.fill(HIST("QA/after/trkbpionpT"), trkbpt); - histos.fill(HIST("QA/after/trkbpionDCAxy"), bTrack.dcaXY()); - histos.fill(HIST("QA/after/trkbpionDCAz"), bTrack.dcaZ()); } + trackIndicies.push_back(bTrack.index()); } + // ========================= + // K0s loop + // ========================= for (const auto& K0scand : dTracks2) { - auto posDauTrack = K0scand.template posTrack_as(); - auto negDauTrack = K0scand.template negTrack_as(); - - /// Daughters - // Positve pion - auto trkppt = posDauTrack.pt(); - auto istrkphasTOF = posDauTrack.hasTOF(); - auto trkpNSigmaPiTPC = posDauTrack.tpcNSigmaPi(); - auto trkpNSigmaPiTOF = (istrkphasTOF) ? posDauTrack.tofNSigmaPi() : -999.; - // Negative pion - auto trknpt = negDauTrack.pt(); - auto istrknhasTOF = negDauTrack.hasTOF(); - auto trknNSigmaPiTPC = negDauTrack.tpcNSigmaPi(); - auto trknNSigmaPiTOF = (istrknhasTOF) ? negDauTrack.tofNSigmaPi() : -999.; - - /// K0s + + auto pos = K0scand.template posTrack_as(); + auto neg = K0scand.template negTrack_as(); + + auto trkppt = pos.pt(); + auto trknpt = neg.pt(); + + auto istrkphasTOF = pos.hasTOF(); + auto istrknhasTOF = neg.hasTOF(); + + auto trkpNSigmaPiTPC = pos.tpcNSigmaPi(); + auto trknNSigmaPiTPC = neg.tpcNSigmaPi(); + + auto trkpNSigmaPiTOF = istrkphasTOF ? pos.tofNSigmaPi() : -999.; + auto trknNSigmaPiTOF = istrknhasTOF ? neg.tofNSigmaPi() : -999.; + auto trkkDauDCA = K0scand.dcaV0daughters(); auto trkkDauDCAPostoPV = K0scand.dcapostopv(); auto trkkDauDCANegtoPV = K0scand.dcanegtopv(); @@ -968,139 +1067,99 @@ struct Chargedkstaranalysis { auto trkkMass = K0scand.mK0Short(); if constexpr (!IsMix) { - // Seconddary QA plots - histos.fill(HIST("QA/before/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); - if (istrkphasTOF) { - histos.fill(HIST("QA/before/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); - histos.fill(HIST("QA/before/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); - } - histos.fill(HIST("QA/before/trkppionpT"), trkppt); - histos.fill(HIST("QA/before/trkppionDCAxy"), posDauTrack.dcaXY()); - histos.fill(HIST("QA/before/trkppionDCAz"), posDauTrack.dcaZ()); - - histos.fill(HIST("QA/before/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); - if (istrknhasTOF) { - histos.fill(HIST("QA/before/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); - histos.fill(HIST("QA/before/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); + if (!doprocessMC && isQaRequired) { + // positive pion + histos.fill(HIST("QA/before/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); + if (istrkphasTOF) { + histos.fill(HIST("QA/before/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); + histos.fill(HIST("QA/before/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); + } + + // negative pion + histos.fill(HIST("QA/before/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); + if (istrknhasTOF) { + histos.fill(HIST("QA/before/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); + histos.fill(HIST("QA/before/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); + } + + // K0s + histos.fill(HIST("QA/before/hDauDCASecondary"), trkkDauDCA); + histos.fill(HIST("QA/before/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); + histos.fill(HIST("QA/before/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); + histos.fill(HIST("QA/before/hpT_Secondary"), trkkpt); + histos.fill(HIST("QA/before/hy_Secondary"), trkky); + histos.fill(HIST("QA/before/hRadiusSecondary"), trkkRadius); + histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); + histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); + histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); } - histos.fill(HIST("QA/before/trknpionpT"), trknpt); - histos.fill(HIST("QA/before/trknpionDCAxy"), negDauTrack.dcaXY()); - histos.fill(HIST("QA/before/trknpionDCAz"), negDauTrack.dcaZ()); - - histos.fill(HIST("QA/before/hDauDCASecondary"), trkkDauDCA); - histos.fill(HIST("QA/before/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); - histos.fill(HIST("QA/before/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); - - histos.fill(HIST("QA/before/hpT_Secondary"), trkkpt); - histos.fill(HIST("QA/before/hy_Secondary"), trkky); - histos.fill(HIST("QA/before/hRadiusSecondary"), trkkRadius); - histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); - histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); - histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); } - if (!secondaryCutsCfgs.cfgByPassDauPIDSelection && !selectionPIDPion(posDauTrack)) // Perhaps it's already applied in trackCut (need to check QA plots) - continue; - if (!secondaryCutsCfgs.cfgByPassDauPIDSelection && !selectionPIDPion(negDauTrack)) - continue; - if (!selectionK0s(collision, K0scand)) + if ((!secondaryCutsCfgs.cfgByPassDauPIDSelection && + (!selectionPIDPion(pos) || !selectionPIDPion(neg))) || + !selectionK0s(collision, K0scand)) continue; if constexpr (!IsMix) { - // Seconddary QA plots after applying cuts - - histos.fill(HIST("QA/after/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); - if (istrkphasTOF) { - histos.fill(HIST("QA/after/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); - histos.fill(HIST("QA/after/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/after/hDauDCASecondary"), trkkDauDCA); + histos.fill(HIST("QA/after/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); + histos.fill(HIST("QA/after/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); + histos.fill(HIST("QA/after/hpT_Secondary"), trkkpt); + histos.fill(HIST("QA/after/hy_Secondary"), trkky); + histos.fill(HIST("QA/after/hRadiusSecondary"), trkkRadius); + histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); + histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); + histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); } - histos.fill(HIST("QA/after/trkppionpT"), trkppt); - histos.fill(HIST("QA/after/trkppionDCAxy"), posDauTrack.dcaXY()); - histos.fill(HIST("QA/after/trkppionDCAz"), posDauTrack.dcaZ()); - - histos.fill(HIST("QA/after/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); - if (istrknhasTOF) { - histos.fill(HIST("QA/after/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); - histos.fill(HIST("QA/after/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); - } - histos.fill(HIST("QA/after/trknpionpT"), trknpt); - histos.fill(HIST("QA/after/trknpionDCAxy"), negDauTrack.dcaXY()); - histos.fill(HIST("QA/after/trknpionDCAz"), negDauTrack.dcaZ()); - - histos.fill(HIST("QA/after/hDauDCASecondary"), trkkDauDCA); - histos.fill(HIST("QA/after/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); - histos.fill(HIST("QA/after/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); - - histos.fill(HIST("QA/after/hpT_Secondary"), trkkpt); - histos.fill(HIST("QA/after/hy_Secondary"), trkky); - histos.fill(HIST("QA/after/hRadiusSecondary"), trkkRadius); - histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); - histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); - histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); } + k0sIndicies.push_back(K0scand.index()); } - for (const auto& trackIndex : trackIndicies) { - for (const auto& k0sIndex : k0sIndicies) { - auto bTrack = dTracks1.rawIteratorAt(trackIndex); - auto k0Scand = dTracks2.rawIteratorAt(k0sIndex); - lDecayDaughter_bach = ROOT::Math::PxPyPzMVector(bTrack.px(), bTrack.py(), bTrack.pz(), massPi); - lResoSecondary = ROOT::Math::PxPyPzMVector(k0Scand.px(), k0Scand.py(), k0Scand.pz(), massK0s); + // ========================= + // Pairing + // ========================= + for (auto tIdx : trackIndicies) { + for (auto kIdx : k0sIndicies) { + + auto bTrack = dTracks1.rawIteratorAt(tIdx); + auto k0s = dTracks2.rawIteratorAt(kIdx); + + lDecayDaughter_bach = {bTrack.px(), bTrack.py(), bTrack.pz(), massPi}; + lResoSecondary = {k0s.px(), k0s.py(), k0s.pz(), massK0s}; lResoKstar = lResoSecondary + lDecayDaughter_bach; - // QA plots if constexpr (!IsMix) { - histos.fill(HIST("QA/before/KstarRapidity"), lResoKstar.Rapidity()); - histos.fill(HIST("QA/before/kstarinvmass"), lResoKstar.M()); + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/before/KstarRapidity"), lResoKstar.Rapidity()); + histos.fill(HIST("QA/before/kstarinvmass"), lResoKstar.M()); + } } - if (lResoKstar.Rapidity() > kstarCutCfgs.cKstarMaxRap || lResoKstar.Rapidity() < kstarCutCfgs.cKstarMinRap) + if (lResoKstar.Rapidity() > kstarCutCfgs.cKstarMaxRap || + lResoKstar.Rapidity() < kstarCutCfgs.cKstarMinRap) continue; if constexpr (!IsMix) { + if (!doprocessMC && isQaRequired) { + histos.fill(HIST("QA/after/KstarRapidity"), lResoKstar.Rapidity()); + histos.fill(HIST("QA/after/kstarinvmass"), lResoKstar.M()); + } - histos.fill(HIST("QA/after/KstarRapidity"), lResoKstar.Rapidity()); - histos.fill(HIST("QA/after/kstarinvmass"), lResoKstar.M()); - histos.fill(HIST("hInvmass_Kstar"), collision.centFT0M(), lResoKstar.Pt(), lResoKstar.M()); if (helicityCfgs.cBoostKShot) { fillInvMass(lResoKstar, collision.centFT0M(), lResoSecondary, lDecayDaughter_bach, IsMix); } else { fillInvMass(lResoKstar, collision.centFT0M(), lDecayDaughter_bach, lResoSecondary, IsMix); } } else { - - histos.fill(HIST("hInvmass_KstarME"), collision.centFT0M(), lResoKstar.Pt(), lResoKstar.M()); fillInvMass(lResoKstar, collision.centFT0M(), lResoSecondary, lDecayDaughter_bach, IsMix); } - if constexpr (!IsMix) { - if (rotBkgEstCfgs.cFillRotBkg) { - for (int nrotbkg = 0; nrotbkg < rotBkgEstCfgs.nBkgRotations; nrotbkg++) { - auto rotangle = o2::constants::math::PI; // If there is only one rotation then it should be pi ): - if (rotBkgEstCfgs.nBkgRotations > 1) { - auto anglestart = rotBkgEstCfgs.confMinRot; - auto angleend = rotBkgEstCfgs.confMaxRot; - auto anglestep = (angleend - anglestart) / (1.0 * (rotBkgEstCfgs.nBkgRotations - 1)); - rotangle = anglestart + nrotbkg * anglestep; - } - histos.fill(HIST("hRotation"), rotangle); - auto rotpionPx = lDecayDaughter_bach.Px() * std::cos(rotangle) - lDecayDaughter_bach.Py() * std::sin(rotangle); - auto rotpionPy = lDecayDaughter_bach.Px() * std::sin(rotangle) + lDecayDaughter_bach.Py() * std::cos(rotangle); - ROOT::Math::PtEtaPhiMVector pionrot; - pionrot = ROOT::Math::PxPyPzMVector(rotpionPx, rotpionPy, lDecayDaughter_bach.Pz(), massPi); - chargeKstarrot = pionrot + lResoSecondary; - if (chargeKstarrot.Rapidity() > kstarCutCfgs.cKstarMaxRap || chargeKstarrot.Rapidity() < kstarCutCfgs.cKstarMinRap) - continue; - histos.fill(HIST("hInvmass_KstarRotated"), collision.centFT0M(), chargeKstarrot.Pt(), chargeKstarrot.M()); - } - } - } - } // K0scand - } // bTrack + } + } count++; - - } // fillHistograms + } // process data void processDataSE(EventCandidates::iterator const& collision, @@ -1108,19 +1167,27 @@ struct Chargedkstaranalysis { V0Candidates const& v0s, aod::BCsWithTimestamps const&) { + histos.fill(HIST("hEvtSelInfo"), 0.5); if (!colCuts.isSelected(collision)) // Default event selection return; + histos.fill(HIST("hEvtSelInfo"), 1.5); + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(collision)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 2.5); + lMultiplicity = getCentrality(collision); if (lMultiplicity < eventCutCfgs.cfgEventCentralityMin || lMultiplicity > eventCutCfgs.cfgEventCentralityMax) return; + histos.fill(HIST("hEvtSelInfo"), 3.5); if (!collision.isInelGt0()) return; + histos.fill(HIST("hEvtSelInfo"), 4.5); colCuts.fillQA(collision); fillHistograms(collision, tracks, v0s); } PROCESS_SWITCH(Chargedkstaranalysis, processDataSE, "Process Event for data without Partitioning", true); - SliceCache cache; using BinningTypeVertexContributor = ColumnBinningPolicy; BinningTypeVertexContributor binningOnPositions{{axisCfgs.cfgvtxbins, axisCfgs.cfgmultbins}, true}; Pair pair{binningOnPositions, nEvtMixing, -1, &cache}; @@ -1166,15 +1233,178 @@ struct Chargedkstaranalysis { } PROCESS_SWITCH(Chargedkstaranalysis, processDataME, "Process Event for data without Partitioning", true); - // process MC reconstructed level - void processMC(MCEventCandidates::iterator const& collision, - MCTrackCandidates const& tracks, - MCV0Candidates const& v0s) + void processMC(soa::Join const&, aod::McParticles& mcParticles, soa::Join const& events, MCV0Candidates const& v0s, MCTrackCandidates const& tracks) { + allowedMcIds.clear(); + centTruthByAllowed.clear(); + + // To apply event selection and store the collision IDs of reconstructed tracks that pass the selection criteria + for (const auto& coll : events) { + + if (!coll.has_mcCollision()) + continue; + + const auto mcid = coll.mcCollisionId(); + + const auto mccoll = coll.template mcCollision_as>(); + const float lCentrality = mccoll.centFT0M(); + + if (doprocessMC && isQaRequired) { + histos.fill(HIST("QA/MC/QACent_woCut"), lCentrality); + histos.fill(HIST("QA/MC/QAvtxz_woCut"), coll.posZ()); + } + + if (!colCuts.isSelected(coll)) + continue; + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(coll)) + continue; + if (!coll.isInelGt0()) + continue; + + if (doprocessMC && isQaRequired) { + histos.fill(HIST("QA/MC/QACent_woCentCut"), lCentrality); + histos.fill(HIST("QA/MC/QAvtxz_wVtxzCut"), coll.posZ()); + } + + if (lCentrality < eventCutCfgs.cfgEventCentralityMin || lCentrality > eventCutCfgs.cfgEventCentralityMax) + continue; + + if (doprocessMC && isQaRequired) { + histos.fill(HIST("QA/MC/QACent_wCentCut"), lCentrality); + } + allowedMcIds.insert(mcid); + centTruthByAllowed.emplace(mcid, lCentrality); + } - // histos.fill(HIST("QAMC/hEvent"), 1.0); + // Calculating the generated Kstar + for (const auto& part : mcParticles) { + if (!part.has_mcCollision()) + continue; + if (std::abs(part.pdgCode()) != kKstarPlus) + continue; + if (std::abs(part.y()) > kstarCutCfgs.cKstarMaxRap) + continue; + + const int pionWanted = (part.pdgCode() > 0) ? +kPiPlus : -kPiPlus; + bool hasRightPion = false; + bool hasK0sToPipi = false; + + for (const auto& d1 : part.template daughters_as()) { + const int pdg1 = d1.pdgCode(); + if (pdg1 == pionWanted) { + hasRightPion = true; + } else if (std::abs(pdg1) == kPDGK0) { + for (const auto& d2 : d1.template daughters_as()) { + if (std::abs(d2.pdgCode()) == kPDGK0s) { + bool seenPip = false, seenPim = false; + for (const auto& d3 : d2.template daughters_as()) { + if (d3.pdgCode() == +kPiPlus) + seenPip = true; + else if (d3.pdgCode() == -kPiPlus) + seenPim = true; + } + if (seenPip && seenPim) { + hasK0sToPipi = true; + break; + } + } + } + } + if (hasRightPion && hasK0sToPipi) + break; + } + + if (!(hasRightPion && hasK0sToPipi)) + continue; + + const auto mcid = part.mcCollisionId(); + if (allowedMcIds.count(mcid) == 0) + continue; + + auto iter = centTruthByAllowed.find(mcid); + if (iter == centTruthByAllowed.end()) + continue; + + const float lCentrality = iter->second; + + histos.fill(HIST("EffKstar/genKstar"), part.pt(), lCentrality); + + if (part.vt() == 0) { + histos.fill(HIST("EffKstar/genKstar_pri"), part.pt(), lCentrality); // To check the primary particle + } + } + // To store the recoKstar + for (const auto& v0 : v0s) { + auto coll = v0.template collision_as(); - fillHistograms(collision, tracks, v0s); + if (!coll.has_mcCollision()) + continue; + + const auto mcid = coll.mcCollisionId(); + + if (allowedMcIds.count(mcid) == 0) + continue; // To check the event is allowed or not + + const auto mccoll = coll.template mcCollision_as>(); + const float lCentrality = mccoll.centFT0M(); + + if (!secondaryCutsCfgs.cfgByPassDauPIDSelection) { + auto posDauTrack = v0.template posTrack_as(); + auto negDauTrack = v0.template negTrack_as(); + if (!selectionPIDPion(posDauTrack)) + continue; + if (!selectionPIDPion(negDauTrack)) + continue; + } + if (!selectionK0s(coll, v0)) + continue; + + auto trks = tracks.sliceBy(perCollision, v0.collisionId()); // Grouping the tracks with the v0s, means only those tracks that belong to the same collision as v0 + for (const auto& bTrack : trks) { + if (bTrack.collisionId() != v0.collisionId()) + continue; + if (!trackCut(bTrack)) + continue; + if (!selectionPIDPion(bTrack)) + continue; + + LorentzVectorSetXYZM lResoSecondary, lDecayDaughter_bach, lResoKstar, lDaughterRot; + + lResoSecondary = LorentzVectorSetXYZM(v0.px(), v0.py(), v0.pz(), MassK0Short); + lDecayDaughter_bach = LorentzVectorSetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); + lResoKstar = lResoSecondary + lDecayDaughter_bach; + + const double ptreco = lResoKstar.Pt(); + const double yreco = lResoKstar.Rapidity(); + if (std::abs(yreco) > kstarCutCfgs.cKstarMaxRap) + continue; + + // Since we are doing the MC study and we know about the PDG code of each particle let's try to check the things which we have + if (!v0.has_mcParticle() || !bTrack.has_mcParticle()) + continue; + auto mcK0s = v0.template mcParticle_as(); // To get the MC truth particle corressponds to the V0 candidate + auto mcPi = bTrack.template mcParticle_as(); + if (std::abs(mcK0s.pdgCode()) != kPDGK0s) + continue; + if (std::abs(mcPi.pdgCode()) != kPiPlus) + continue; + MCTrueTrackCandidates::iterator kstarFromPi; + bool havePiKstar = false; + // Loops over all the mother's of pions and check if this pion comming from a kstar + for (const auto& m1 : mcPi.template mothers_as()) { + if (std::abs(m1.pdgCode()) == kKstarPlus) { + kstarFromPi = m1; + havePiKstar = true; + break; + } + } + if (!havePiKstar) { + continue; + } + histos.fill(HIST("EffKstar/recoKstar"), ptreco, lCentrality); + histos.fill(HIST("MCReco/hInvmass_Kstar_true"), lCentrality, ptreco, lResoKstar.M()); + } + } } PROCESS_SWITCH(Chargedkstaranalysis, processMC, "Process Event for MC", false); }; diff --git a/PWGLF/Tasks/Resonances/chk892Flow.cxx b/PWGLF/Tasks/Resonances/chk892Flow.cxx index 901a602c87e..f71d11397f0 100644 --- a/PWGLF/Tasks/Resonances/chk892Flow.cxx +++ b/PWGLF/Tasks/Resonances/chk892Flow.cxx @@ -23,7 +23,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -145,9 +146,9 @@ struct Chk892Flow { // Configurables struct : ConfigurableGroup { - ConfigurableAxis cfgBinsPt{"cfgBinsPt", {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 cfgBinsPt{"cfgBinsPt", {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}, "Binning of the pT axis"}; ConfigurableAxis cfgBinsPtQA{"cfgBinsPtQA", {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 cfgBinsCent{"cfgBinsCent", {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 cfgBinsCent{"cfgBinsCent", {VARIABLE_WIDTH, 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 110.0}, "Binning of the centrality axis"}; ConfigurableAxis cfgBinsVtxZ{"cfgBinsVtxZ", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "Binning of the z-vertex 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"}; ConfigurableAxis cfgBinsOccu{"cfgBinsOccu", {VARIABLE_WIDTH, 0, 500, 1000, 2500, 10000, 999999}, "Binning of the occupancy axis"}; @@ -175,13 +176,13 @@ struct Chk892Flow { // Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; // Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; Configurable cfgEvtTriggerCheck{"cfgEvtTriggerCheck", false, "Evt sel: check for trigger"}; - Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", true, "Evt sel: check for offline selection"}; - Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", false, "Evt sel: triggerTVX selection (MB)"}; - Configurable cfgEvtTFBorderCut{"cfgEvtTFBorderCut", false, "Evt sel: apply TF border cut"}; + Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtTFBorderCut{"cfgEvtTFBorderCut", true, "Evt sel: apply TF border cut"}; Configurable cfgEvtUseITSTPCvertex{"cfgEvtUseITSTPCvertex", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; - Configurable cfgEvtZvertexTimedifference{"cfgEvtZvertexTimedifference", true, "Evt sel: apply Z-vertex time difference"}; + Configurable cfgEvtZvertexTimedifference{"cfgEvtZvertexTimedifference", false, "Evt sel: apply Z-vertex time difference"}; Configurable cfgEvtPileupRejection{"cfgEvtPileupRejection", true, "Evt sel: apply pileup rejection"}; - Configurable cfgEvtNoITSROBorderCut{"cfgEvtNoITSROBorderCut", false, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgEvtNoITSROBorderCut{"cfgEvtNoITSROBorderCut", true, "Evt sel: apply NoITSRO border cut"}; Configurable cfgEvtCollInTimeRangeStandard{"cfgEvtCollInTimeRangeStandard", true, "Evt sel: apply NoCollInTimeRangeStandard"}; Configurable cfgEventCentralityMin{"cfgEventCentralityMin", 0.0f, "Event sel: minimum centrality"}; Configurable cfgEventCentralityMax{"cfgEventCentralityMax", 80.0f, "Event sel: maximum centrality"}; @@ -195,8 +196,8 @@ struct Chk892Flow { /// PID Selections, pion struct : ConfigurableGroup { Configurable cfgTPConly{"cfgTPConly", false, "Use only TPC for PID"}; // bool - Configurable cfgMaxTPCnSigmaPion{"cfgMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cfgMaxTOFnSigmaPion{"cfgMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cfgMaxTPCnSigmaPion{"cfgMaxTPCnSigmaPion", 2.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cfgMaxTOFnSigmaPion{"cfgMaxTOFnSigmaPion", 2.0, "TOF nSigma cut for Pion"}; // TOF Configurable cfgNsigmaCutCombinedPion{"cfgNsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined Configurable cfgTOFVeto{"cfgTOFVeto", true, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto Configurable cfgTOFMinPt{"cfgTOFMinPt", 0.6, "Minimum TOF pT cut for Pion"}; // TOF pT cut @@ -210,7 +211,8 @@ struct Chk892Flow { Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor - Configurable cfgpTdepDCAxyCut{"cfgpTdepDCAxyCut", false, "pT-dependent DCAxy cut"}; + Configurable cfgpTdepDCAxyCut{"cfgpTdepDCAxyCut", true, "pT-dependent DCAxy cut"}; + Configurable cfgpTdepDCAzCut{"cfgpTdepDCAzCut", true, "pT-dependent DCAz cut"}; 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"}; @@ -234,7 +236,7 @@ struct Chk892Flow { Configurable cfgSecondaryCrossMassHypothesisCut{"cfgSecondaryCrossMassHypothesisCut", false, "Apply cut based on the lambda mass hypothesis"}; Configurable cfgByPassDauPIDSelection{"cfgByPassDauPIDSelection", true, "Bypass Daughters PID selection"}; - Configurable cfgByPassDauRapiditySelection{"cfgByPassDauRapiditySelection", false, "Bypass Daughters Rapidity selection"}; + Configurable cfgByPassDauRapiditySelection{"cfgByPassDauRapiditySelection", true, "Bypass Daughters Rapidity selection"}; Configurable cfgSecondaryDauDCAMax{"cfgSecondaryDauDCAMax", 0.2, "Maximum DCA Secondary daughters to PV"}; Configurable cfgSecondaryDauPosDCAtoPVMin{"cfgSecondaryDauPosDCAtoPVMin", 0.1, "Minimum DCA Secondary positive daughters to PV"}; Configurable cfgSecondaryDauNegDCAtoPVMin{"cfgSecondaryDauNegDCAtoPVMin", 0.1, "Minimum DCA Secondary negative daughters to PV"}; @@ -314,7 +316,7 @@ struct Chk892Flow { AxisSpec epAxis = {100, -1.0 * constants::math::PI, constants::math::PI}; AxisSpec ptAxis = {AxisConfig.cfgBinsPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxisQA = {AxisConfig.cfgBinsPtQA, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec v2Axis = {AxisConfig.cfgAxisV2, "#v_{2}"}; + AxisSpec v2Axis = {AxisConfig.cfgAxisV2, "#it{v}_{2}"}; AxisSpec phiAxis = {AxisConfig.cfgAxisPhi, "2(#phi-#Psi_{2})"}; AxisSpec occuAxis = {AxisConfig.cfgBinsOccu, "Occupancy"}; AxisSpec radiusAxis = {50, 0, 5, "Radius (cm)"}; @@ -410,6 +412,7 @@ struct Chk892Flow { histos.add("QA/before/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/before/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); @@ -417,6 +420,7 @@ struct Chk892Flow { histos.add("QA/after/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/after/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); // Mass QA (quick check) @@ -578,8 +582,14 @@ struct Chk892Flow { if (std::abs(track.dcaXY()) > TrackCuts.cfgMaxbDCArToPVcut) return false; } - if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) - return false; + if (TrackCuts.cfgpTdepDCAzCut) { + // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution + if (std::abs(track.dcaZ()) > (0.004 + (0.013 / track.pt()))) + return false; + } else { + if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) + return false; + } return true; } @@ -818,7 +828,7 @@ struct Chk892Flow { if (AnalysisConfig.cfgFillQAPlots) { // Bachelor pion QA plots after applying cuts histos.fill(HIST("QA/after/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); - if (istrkbhasTOF) { + if (istrkbhasTOF && trkbpt > PIDCuts.cfgTOFMinPt) { histos.fill(HIST("QA/after/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); histos.fill(HIST("QA/after/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); } @@ -856,7 +866,7 @@ struct Chk892Flow { auto trkkPropTau = k0sCand.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; auto trkkMass = k0sCand.mK0Short(); - lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); + lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); auto lPhiMinusPsiK0s = RecoDecay::constrainAngle(lResoSecondary.Phi() - lEPDet, 0.0, 2); // constrain angle to range 0, Pi // auto v2K0s = std::cos(static_cast(nmode) * lPhiMinusPsiK0s); @@ -889,9 +899,10 @@ struct Chk892Flow { histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); histos.fill(HIST("QA/before/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/before/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); - histos.fill(HIST("QA/before/k0sv2vsinvmass"), lResoSecondary.M(), v2K0s); + histos.fill(HIST("QA/before/k0sv2vsinvmass"), trkkMass, v2K0s); } } @@ -932,20 +943,21 @@ struct Chk892Flow { histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); histos.fill(HIST("QA/after/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/after/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); - histos.fill(HIST("QA/after/k0sv2vsinvmass"), lResoSecondary.M(), v2K0s); + histos.fill(HIST("QA/after/k0sv2vsinvmass"), trkkMass, v2K0s); if (AnalysisConfig.cfgFillAdditionalAxis) { if (AnalysisConfig.cfgFillOccupancy) { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s, collision.trackOccupancyInTimeRange()); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), trkkMass, v2K0s, static_cast(nmode) * lPhiMinusPsiK0s, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), trkkMass, v2K0s, static_cast(nmode) * lPhiMinusPsiK0s); } } else { if (AnalysisConfig.cfgFillOccupancy) { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, collision.trackOccupancyInTimeRange()); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), trkkMass, v2K0s, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), trkkMass, v2K0s); } } } @@ -957,10 +969,9 @@ struct Chk892Flow { for (const auto& k0sIndex : k0sIndicies) { auto bTrack = dTracks1.rawIteratorAt(trackIndex); auto k0sCand = dTracks2.rawIteratorAt(k0sIndex); - auto trkkMass = k0sCand.mK0Short(); lDecayDaughter_bach = LorentzVectorSetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); - lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); + lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); lResoKstar = lResoSecondary + lDecayDaughter_bach; auto resoPhi = lResoKstar.Phi(); // EP method diff --git a/PWGLF/Tasks/Resonances/chk892flow_pp.cxx b/PWGLF/Tasks/Resonances/chk892flow_pp.cxx deleted file mode 100644 index 088d532680d..00000000000 --- a/PWGLF/Tasks/Resonances/chk892flow_pp.cxx +++ /dev/null @@ -1,924 +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 chk892_pp.cxx -/// \brief Reconstruction of track-track decay resonance candidates -/// -/// -/// \author Su-Jeong Ji - -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/Utils/collisionCuts.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/StaticFor.h" -#include "Framework/StepTHn.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "TF1.h" -#include "TRandom3.h" -#include "TVector2.h" -#include // FIXME -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // FIXME - -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::constants::physics; - -struct chk892_pp { - enum binType : unsigned int { - kKstarP = 0, - kKstarN, - kKstarP_Mix, - kKstarN_Mix, - kKstarP_GenINEL10, - kKstarN_GenINEL10, - kKstarP_GenINELgt10, - kKstarN_GenINELgt10, - kKstarP_GenTrig10, - kKstarN_GenTrig10, - kKstarP_GenEvtSel, - kKstarN_GenEvtSel, - kKstarP_Rec, - kKstarN_Rec, - kTYEnd - }; - - SliceCache cache; - Preslice perCollision = aod::track::collisionId; - - using EventCandidates = soa::Join; - // using EventCandidates = soa::Join; - using TrackCandidates = soa::Join; - using V0Candidates = aod::V0Datas; - - using MCEventCandidates = soa::Join; - using MCTrackCandidates = soa::Join; - using MCV0Candidates = soa::Join; - - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - Service ccdb; - Service pdg; - o2::ccdb::CcdbApi ccdbApi; - - 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"}; - - // Configurables - ConfigurableAxis cfgBinsPt{"cfgBinsPt", {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 cfgBinsPtQA{"cfgBinsPtQA", {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 cfgBinsCent{"cfgBinsCent", {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 cfgBinsVtxZ{"cfgBinsVtxZ", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "Binning of the z-vertex axis"}; - Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; - - /// Event cuts - o2::analysis::CollisonCuts colCuts; - Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; - Configurable ConfEvtOccupancyInTimeRangeMax{"ConfEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; - Configurable ConfEvtOccupancyInTimeRangeMin{"ConfEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; - Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", false, "Evt sel: check for trigger"}; - Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", true, "Evt sel: check for offline selection"}; - Configurable ConfEvtTriggerTVXSel{"ConfEvtTriggerTVXSel", false, "Evt sel: triggerTVX selection (MB)"}; - Configurable ConfEvtTFBorderCut{"ConfEvtTFBorderCut", false, "Evt sel: apply TF border cut"}; - Configurable ConfEvtUseITSTPCvertex{"ConfEvtUseITSTPCvertex", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; - Configurable ConfEvtZvertexTimedifference{"ConfEvtZvertexTimedifference", true, "Evt sel: apply Z-vertex time difference"}; - Configurable ConfEvtPileupRejection{"ConfEvtPileupRejection", true, "Evt sel: apply pileup rejection"}; - Configurable ConfEvtNoITSROBorderCut{"ConfEvtNoITSROBorderCut", false, "Evt sel: apply NoITSRO border cut"}; - Configurable ConfincludeCentralityMC{"ConfincludeCentralityMC", false, "Include centrality in MC"}; - Configurable ConfEvtCollInTimeRangeStandard{"ConfEvtCollInTimeRangeStandard", true, "Evt sel: apply NoCollInTimeRangeStandard"}; - - /// Track selections - Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; - Configurable cMaxEtacut{"cMaxEtacut", 0.8, "Track maximum eta cut"}; - - /* - // Cuts from polarization analysis - Configurable cfgOccupancySel{"cfgOccupancySel", false, "Occupancy selection"}; - Configurable cfgMaxOccupancy{"cfgMaxOccupancy", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; - Configurable cfgMinOccupancy{"cfgMinOccupancy", -100, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; - Configurable cfgNCollinTR{"cfgNCollinTR", false, "Additional selection for the number of coll in time range"}; -*/ - Configurable cfgCentEst{"cfgCentEst", 1, "Centrality estimator, 1: FT0C, 2: FT0M"}; - - // DCAr to PV - Configurable cMaxbDCArToPVcut{"cMaxbDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; - // DCAz to PV - Configurable cMaxbDCAzToPVcut{"cMaxbDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; - - /// PID Selections, pion - Configurable cTPConly{"cTPConly", true, "Use only TPC for PID"}; // bool - Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF - Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined - Configurable cTOFVeto{"cTOFVeto", true, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto - - // Track selections - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor - - 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"}; - - // Secondary Selection - Configurable cfgReturnFlag{"boolReturnFlag", false, "Return Flag for debugging"}; - Configurable cSecondaryRequire{"bool", true, "Secondary cuts on/off"}; - Configurable cSecondaryArmenterosCut{"boolArmenterosCut", true, "cut on Armenteros-Podolanski graph"}; - - Configurable cfgByPassDauPIDSelection{"cfgByPassDauPIDSelection", true, "Bypass Daughters PID selection"}; - Configurable cSecondaryDauDCAMax{"cSecondaryDauDCAMax", 1., "Maximum DCA Secondary daughters to PV"}; - Configurable cSecondaryDauPosDCAtoPVMin{"cSecondaryDauPosDCAtoPVMin", 0.0, "Minimum DCA Secondary positive daughters to PV"}; - Configurable cSecondaryDauNegDCAtoPVMin{"cSecondaryDauNegDCAtoPVMin", 0.0, "Minimum DCA Secondary negative daughters to PV"}; - - Configurable cSecondaryPtMin{"cSecondaryPtMin", 0.f, "Minimum transverse momentum of Secondary"}; - Configurable cSecondaryRapidityMax{"cSecondaryRapidityMax", 0.5, "Maximum rapidity of Secondary"}; - Configurable cSecondaryRadiusMin{"cSecondaryRadiusMin", 1.2, "Minimum transverse radius of Secondary"}; - Configurable cSecondaryCosPAMin{"cSecondaryCosPAMin", 0.995, "Mininum cosine pointing angle of Secondary"}; - Configurable cSecondaryDCAtoPVMax{"cSecondaryDCAtoPVMax", 0.3, "Maximum DCA Secondary to PV"}; - Configurable cSecondaryProperLifetimeMax{"cSecondaryProperLifetimeMax", 20, "Maximum Secondary Lifetime"}; - Configurable cSecondaryparamArmenterosCut{"paramArmenterosCut", 0.2, "parameter for Armenteros Cut"}; - Configurable cSecondaryMassWindow{"cSecondaryMassWindow", 0.075, "Secondary inv mass selciton window"}; - - // K* selection - Configurable cKstarMaxRap{"cKstarMaxRap", 0.5, "Kstar maximum rapidity"}; - Configurable cKstarMinRap{"cKstarMinRap", -0.5, "Kstar minimum rapidity"}; - - float centrality; - - // PDG code - int kPDGK0s = 310; - int kPDGK0 = 311; - int kKstarPlus = 323; - int kPiPlus = 211; - - void init(o2::framework::InitContext&) - { - centrality = -999; - - colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, ConfEvtOccupancyInTimeRangeMax, ConfEvtOccupancyInTimeRangeMin); - colCuts.init(&histos); - colCuts.setTriggerTVX(ConfEvtTriggerTVXSel); - colCuts.setApplyTFBorderCut(ConfEvtTFBorderCut); - colCuts.setApplyITSTPCvertex(ConfEvtUseITSTPCvertex); - colCuts.setApplyZvertexTimedifference(ConfEvtZvertexTimedifference); - colCuts.setApplyPileupRejection(ConfEvtPileupRejection); - colCuts.setApplyNoITSROBorderCut(ConfEvtNoITSROBorderCut); - colCuts.setApplyCollInTimeRangeStandard(ConfEvtCollInTimeRangeStandard); - - AxisSpec centAxis = {cfgBinsCent, "T0M (%)"}; - AxisSpec vtxzAxis = {cfgBinsVtxZ, "Z Vertex (cm)"}; - AxisSpec epAxis = {100, -1.0 * constants::math::PI, constants::math::PI}; - AxisSpec epresAxis = {100, -1.02, 1.02}; - AxisSpec ptAxis = {cfgBinsPt, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec ptAxisQA = {cfgBinsPtQA, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec radiusAxis = {50, 0, 5, "Radius (cm)"}; - AxisSpec cpaAxis = {50, 0.95, 1.0, "CPA"}; - AxisSpec tauAxis = {250, 0, 25, "Lifetime (cm)"}; - AxisSpec dcaAxis = {200, 0, 2, "DCA (cm)"}; - AxisSpec dcaxyAxis = {200, 0, 2, "DCA_{#it{xy}} (cm)"}; - AxisSpec dcazAxis = {200, 0, 2, "DCA_{#it{z}} (cm)"}; - AxisSpec yAxis = {100, -1, 1, "Rapidity"}; - AxisSpec invMassAxisK0s = {400 / cNbinsDiv, 0.3, 0.7, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 - AxisSpec invMassAxisReso = {900 / cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 - AxisSpec invMassAxisScan = {150, 0, 1.5, "Invariant Mass (GeV/#it{c}^2)"}; // For selection - AxisSpec pidQAAxis = {130, -6.5, 6.5}; - AxisSpec dataTypeAxis = {9, 0, 9, "Histogram types"}; - AxisSpec mcTypeAxis = {4, 0, 4, "Histogram types"}; - - // THnSparse - AxisSpec axisType = {binType::kTYEnd, 0, binType::kTYEnd, "Type of bin with charge and mix"}; - AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; - - histos.add("QA/K0sCutCheck", "Check K0s cut", HistType::kTH1D, {AxisSpec{12, -0.5, 11.5, "Check"}}); - - histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); - histos.add("QA/before/VtxZ", "Centrality distribution", {HistType::kTH1D, {vtxzAxis}}); - histos.add("QA/before/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); - - // Bachelor pion - histos.add("QA/before/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/before/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QA/before/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - histos.add("QA/after/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/after/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QA/after/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - // Secondary pion 1 - histos.add("QA/before/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/before/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/before/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); - - histos.add("QA/after/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/after/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/after/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); - - // Secondary pion 2 - histos.add("QA/before/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/before/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/before/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/before/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); - - histos.add("QA/after/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos.add("QA/after/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QA/after/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QA/after/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); - - // K0s - histos.add("QA/before/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/before/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); - histos.add("QA/before/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); - histos.add("QA/before/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); - histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); - histos.add("QA/before/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); - - histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); - histos.add("QA/after/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); - histos.add("QA/after/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); - histos.add("QA/after/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); - histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); - histos.add("QA/after/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); - - // Kstar - // Invariant mass nSparse - histos.add("QA/before/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); - histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso}); - histos.add("hInvmass_Kstar_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso}); - - // Mass QA (quick check) - histos.add("QA/before/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); - histos.add("QA/before/kstarinvmass_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTH1D, {invMassAxisReso}); - - histos.add("QA/after/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); - histos.add("QA/after/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); - histos.add("QA/after/kstarinvmass_Mix", "Invariant mass of unlike-sign chK(892) from mixed event", HistType::kTH1D, {invMassAxisReso}); - - // MC - if (doprocessMC) { - - histos.add("QAMC/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); - // Bachelor pion - histos.add("QAMC/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QAMC/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QAMC/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - // Secondary pion 1 - histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QAMC/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); - histos.add("QAMC/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - // Secondary pion 2 - histos.add("QAMC/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxis, pidQAAxis}); - histos.add("QAMC/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - histos.add("QAMC/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); - histos.add("QAMC/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); - - // Secondary Resonance (K0s cand) - histos.add("QAMC/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QAMC/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QAMC/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); - - histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxis}); - histos.add("QAMC/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); - histos.add("QAMC/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); - histos.add("QAMC/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); - histos.add("QAMC/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); - histos.add("QAMC/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); - histos.add("QAMC/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAMC/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); - - // K892 - histos.add("QAMC/KstarOA", "Opening angle of chK(892)", HistType::kTH1D, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QAMC/KstarPairAsym", "Pair asymmetry of chK(892)", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAMC/KstarRapidity", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); - - histos.add("QAMC/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisReso}); - histos.add("QAMC/kstarinvmass_noKstar", "Invariant mass of unlike-sign no chK(892)", HistType::kTH1D, {invMassAxisReso}); - - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso}); - - ccdb->setURL(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()); - } - - // Print output histograms statistics - LOG(info) << "Size of the histograms in chK(892) Analysis Task"; - histos.print(); - } - - template - float GetCentrality(CollisionType const& collision) - { - if (cfgCentEst == 1) { - return collision.multFT0C(); - } else if (cfgCentEst == 2) { - return collision.multFT0M(); - } else { - return -999; - } - } - - template - int GetDetId(DetNameType const& name) - { - LOGF(info, "GetDetID running"); - 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 { - return false; - } - } - - // Track selection - template - bool trackCut(TrackType const& track) - { - // basic track cuts - if (std::abs(track.pt()) < cMinPtcut) - return false; - if (std::abs(track.eta()) > cMaxEtacut) - 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 (cfgUseTPCRefit && !track.passedTPCRefit()) - return false; - if (cfgPVContributor && !track.isPVContributor()) - return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) - return false; - if (cfgGlobalTrack && !track.isGlobalTrack()) - return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) - return false; - if (std::abs(track.dcaXY()) > cMaxbDCArToPVcut) - return false; - if (std::abs(track.dcaZ()) > cMaxbDCAzToPVcut) - return false; - return true; - } - - // PID selection tools - template - bool selectionPIDPion(TrackType const& candidate) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - - if (cTPConly) { - - if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { - tpcPIDPassed = true; - } else { - return false; - } - tofPIDPassed = true; - - } else { - - if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { - tpcPIDPassed = true; - } else { - return false; - } - 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 { - if (!cTOFVeto) { - return false; - } - tofPIDPassed = true; - } - } - - if (tpcPIDPassed && tofPIDPassed) { - return true; - } - return false; - } - - template - bool selectionK0s(CollisionType const& collision, K0sType const& candidate) - { - auto DauDCA = candidate.dcaV0daughters(); - auto DauPosDCAtoPV = candidate.dcapostopv(); - auto DauNegDCAtoPV = candidate.dcanegtopv(); - auto pT = candidate.pt(); - auto Rapidity = candidate.yK0Short(); - auto Radius = candidate.v0radius(); - auto DCAtoPV = candidate.dcav0topv(); - auto CPA = candidate.v0cosPA(); - auto PropTauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; - auto mK0s = candidate.mK0Short(); - - if (cfgReturnFlag) { - bool returnFlag = true; - - if (cSecondaryRequire) { - histos.fill(HIST("QA/K0sCutCheck"), 0); - if (DauDCA > cSecondaryDauDCAMax) { - histos.fill(HIST("QA/K0sCutCheck"), 1); - returnFlag = false; - } - if (DauPosDCAtoPV < cSecondaryDauPosDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 2); - returnFlag = false; - } - if (DauNegDCAtoPV < cSecondaryDauNegDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 3); - returnFlag = false; - } - if (pT < cSecondaryPtMin) { - histos.fill(HIST("QA/K0sCutCheck"), 4); - returnFlag = false; - } - if (Rapidity > cSecondaryRapidityMax) { - histos.fill(HIST("QA/K0sCutCheck"), 5); - returnFlag = false; - } - if (Radius < cSecondaryRadiusMin) { - histos.fill(HIST("QA/K0sCutCheck"), 6); - returnFlag = false; - } - if (DCAtoPV > cSecondaryDCAtoPVMax) { - histos.fill(HIST("QA/K0sCutCheck"), 7); - returnFlag = false; - } - if (CPA < cSecondaryCosPAMin) { - histos.fill(HIST("QA/K0sCutCheck"), 8); - returnFlag = false; - } - if (PropTauK0s > cSecondaryProperLifetimeMax) { - histos.fill(HIST("QA/K0sCutCheck"), 9); - returnFlag = false; - } - if (candidate.qtarm() < cSecondaryparamArmenterosCut * TMath::Abs(candidate.alpha())) { - histos.fill(HIST("QA/K0sCutCheck"), 11); - returnFlag = false; - } - if (fabs(mK0s - MassK0Short) > cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - returnFlag = false; - } - - return returnFlag; - - } else { - if (fabs(mK0s - MassK0Short) > cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - returnFlag = false; - } - - return returnFlag; - } - - } else { - if (cSecondaryRequire) { - - histos.fill(HIST("QA/K0sCutCheck"), 0); - if (DauDCA > cSecondaryDauDCAMax) { - histos.fill(HIST("QA/K0sCutCheck"), 1); - return false; - } - if (DauPosDCAtoPV < cSecondaryDauPosDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 2); - return false; - } - if (DauNegDCAtoPV < cSecondaryDauNegDCAtoPVMin) { - histos.fill(HIST("QA/K0sCutCheck"), 3); - return false; - } - if (pT < cSecondaryPtMin) { - histos.fill(HIST("QA/K0sCutCheck"), 4); - return false; - } - if (Rapidity > cSecondaryRapidityMax) { - histos.fill(HIST("QA/K0sCutCheck"), 5); - return false; - } - if (Radius < cSecondaryRadiusMin) { - histos.fill(HIST("QA/K0sCutCheck"), 6); - return false; - } - if (DCAtoPV > cSecondaryDCAtoPVMax) { - histos.fill(HIST("QA/K0sCutCheck"), 7); - return false; - } - if (CPA < cSecondaryCosPAMin) { - histos.fill(HIST("QA/K0sCutCheck"), 8); - return false; - } - if (PropTauK0s > cSecondaryProperLifetimeMax) { - histos.fill(HIST("QA/K0sCutCheck"), 9); - return false; - } - if (candidate.qtarm() < cSecondaryparamArmenterosCut * TMath::Abs(candidate.alpha())) { - histos.fill(HIST("QA/K0sCutCheck"), 11); - return false; - } - if (fabs(mK0s - MassK0Short) > cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - return false; - } - return true; - - } else { - if (fabs(mK0s - MassK0Short) > cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - return false; - } - return true; - } - } - } // selectionK0s - - 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; - } - - template - bool isTrueKstar(const TrackTemplate& bTrack, const V0Template& K0scand) - { - if (abs(bTrack.PDGCode()) != kPiPlus) // Are you pion? - return false; - if (abs(K0scand.PDGCode()) != kPDGK0s) // Are you K0s? - return false; - - auto motherbTrack = bTrack.template mothers_as(); - auto motherkV0 = K0scand.template mothers_as(); - - // Check bTrack first - if (abs(motherbTrack.pdgCode()) != kKstarPlus) // Are you charged Kstar's daughter? - return false; // Apply first since it's more restrictive - - if (abs(motherkV0.pdgCode()) != 310) // Is it K0s? - return false; - // Check if K0s's mother is K0 (311) - auto motherK0 = motherkV0.template mothers_as(); - if (abs(motherK0.pdgCode()) != 311) - return false; - - // Check if K0's mother is Kstar (323) - auto motherKstar = motherK0.template mothers_as(); - if (abs(motherKstar.pdgCode()) != 323) - return false; - - // Check if bTrack and K0 have the same mother (global index) - if (motherbTrack.globalIndex() != motherK0.globalIndex()) - return false; - - return true; - } - - int count = 0; - - template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksTypeK0s& dTracks2) - { - histos.fill(HIST("QA/before/CentDist"), centrality); - - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResoSecondary, lDecayDaughter_bach, lResoKstar; - std::vector trackIndicies = {}; - std::vector k0sIndicies = {}; - - for (auto& bTrack : dTracks1) { - auto trkbpt = bTrack.pt(); - auto istrkbhasTOF = bTrack.hasTOF(); - auto trkbNSigmaPiTPC = bTrack.tpcNSigmaPi(); - auto trkbNSigmaPiTOF = (istrkbhasTOF) ? bTrack.tofNSigmaPi() : -999.; - - if constexpr (!IsMix) { - // Bachelor pion QA plots - histos.fill(HIST("QA/before/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); - if (istrkbhasTOF) { - histos.fill(HIST("QA/before/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); - histos.fill(HIST("QA/before/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); - } - histos.fill(HIST("QA/before/trkbpionpT"), trkbpt); - histos.fill(HIST("QA/before/trkbpionDCAxy"), bTrack.dcaXY()); - histos.fill(HIST("QA/before/trkbpionDCAz"), bTrack.dcaZ()); - } - - if (!trackCut(bTrack)) - continue; - if (!selectionPIDPion(bTrack)) - continue; - - if constexpr (!IsMix) { - // Bachelor pion QA plots after applying cuts - histos.fill(HIST("QA/after/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); - if (istrkbhasTOF) { - histos.fill(HIST("QA/after/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); - histos.fill(HIST("QA/after/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); - } - histos.fill(HIST("QA/after/trkbpionpT"), trkbpt); - histos.fill(HIST("QA/after/trkbpionDCAxy"), bTrack.dcaXY()); - histos.fill(HIST("QA/after/trkbpionDCAz"), bTrack.dcaZ()); - } - trackIndicies.push_back(bTrack.index()); - } - - for (auto& K0scand : dTracks2) { - auto posDauTrack = K0scand.template posTrack_as(); - auto negDauTrack = K0scand.template negTrack_as(); - - /// Daughters - // Positve pion - auto trkppt = posDauTrack.pt(); - auto istrkphasTOF = posDauTrack.hasTOF(); - auto trkpNSigmaPiTPC = posDauTrack.tpcNSigmaPi(); - auto trkpNSigmaPiTOF = (istrkphasTOF) ? posDauTrack.tofNSigmaPi() : -999.; - // Negative pion - auto trknpt = negDauTrack.pt(); - auto istrknhasTOF = negDauTrack.hasTOF(); - auto trknNSigmaPiTPC = negDauTrack.tpcNSigmaPi(); - auto trknNSigmaPiTOF = (istrknhasTOF) ? negDauTrack.tofNSigmaPi() : -999.; - - /// K0s - auto trkkDauDCA = K0scand.dcaV0daughters(); - auto trkkDauDCAPostoPV = K0scand.dcapostopv(); - auto trkkDauDCANegtoPV = K0scand.dcanegtopv(); - auto trkkpt = K0scand.pt(); - auto trkky = K0scand.yK0Short(); - auto trkkRadius = K0scand.v0radius(); - auto trkkDCAtoPV = K0scand.dcav0topv(); - auto trkkCPA = K0scand.v0cosPA(); - auto trkkPropTau = K0scand.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; - auto trkkMass = K0scand.mK0Short(); - - if constexpr (!IsMix) { - // Seconddary QA plots - histos.fill(HIST("QA/before/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); - if (istrkphasTOF) { - histos.fill(HIST("QA/before/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); - histos.fill(HIST("QA/before/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); - } - histos.fill(HIST("QA/before/trkppionpT"), trkppt); - histos.fill(HIST("QA/before/trkppionDCAxy"), posDauTrack.dcaXY()); - histos.fill(HIST("QA/before/trkppionDCAz"), posDauTrack.dcaZ()); - - histos.fill(HIST("QA/before/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); - if (istrknhasTOF) { - histos.fill(HIST("QA/before/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); - histos.fill(HIST("QA/before/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); - } - histos.fill(HIST("QA/before/trknpionpT"), trknpt); - histos.fill(HIST("QA/before/trknpionDCAxy"), negDauTrack.dcaXY()); - histos.fill(HIST("QA/before/trknpionDCAz"), negDauTrack.dcaZ()); - - histos.fill(HIST("QA/before/hDauDCASecondary"), trkkDauDCA); - histos.fill(HIST("QA/before/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); - histos.fill(HIST("QA/before/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); - - histos.fill(HIST("QA/before/hpT_Secondary"), trkkpt); - histos.fill(HIST("QA/before/hy_Secondary"), trkky); - histos.fill(HIST("QA/before/hRadiusSecondary"), trkkRadius); - histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); - histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); - histos.fill(HIST("QA/before/hPropTauSecondary"), trkkPropTau); - histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); - } - - // if (!trackCut(posDauTrack) || !trackCut(negDauTrack)) // Too tight cut for K0s daugthers - // continue; - if (!cfgByPassDauPIDSelection && !selectionPIDPion(posDauTrack)) // Perhaps it's already applied in trackCut (need to check QA plots) - continue; - if (!cfgByPassDauPIDSelection && !selectionPIDPion(negDauTrack)) - continue; - if (!selectionK0s(collision, K0scand)) - continue; - - if constexpr (!IsMix) { - // Seconddary QA plots after applying cuts - - histos.fill(HIST("QA/after/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); - if (istrkphasTOF) { - histos.fill(HIST("QA/after/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); - histos.fill(HIST("QA/after/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); - } - histos.fill(HIST("QA/after/trkppionpT"), trkppt); - histos.fill(HIST("QA/after/trkppionDCAxy"), posDauTrack.dcaXY()); - histos.fill(HIST("QA/after/trkppionDCAz"), posDauTrack.dcaZ()); - - histos.fill(HIST("QA/after/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); - if (istrknhasTOF) { - histos.fill(HIST("QA/after/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); - histos.fill(HIST("QA/after/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); - } - histos.fill(HIST("QA/after/trknpionpT"), trknpt); - histos.fill(HIST("QA/after/trknpionDCAxy"), negDauTrack.dcaXY()); - histos.fill(HIST("QA/after/trknpionDCAz"), negDauTrack.dcaZ()); - - histos.fill(HIST("QA/after/hDauDCASecondary"), trkkDauDCA); - histos.fill(HIST("QA/after/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); - histos.fill(HIST("QA/after/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); - - histos.fill(HIST("QA/after/hpT_Secondary"), trkkpt); - histos.fill(HIST("QA/after/hy_Secondary"), trkky); - histos.fill(HIST("QA/after/hRadiusSecondary"), trkkRadius); - histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); - histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); - histos.fill(HIST("QA/after/hPropTauSecondary"), trkkPropTau); - histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); - } - k0sIndicies.push_back(K0scand.index()); - } - - for (auto& trackIndex : trackIndicies) { - for (auto& k0sIndex : k0sIndicies) { - auto bTrack = dTracks1.rawIteratorAt(trackIndex); - auto K0scand = dTracks2.rawIteratorAt(k0sIndex); - - lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); - lResoSecondary.SetXYZM(K0scand.px(), K0scand.py(), K0scand.pz(), MassK0Short); - lResoKstar = lResoSecondary + lDecayDaughter_bach; - - // QA plots - if constexpr (!IsMix) { - histos.fill(HIST("QA/before/KstarRapidity"), lResoKstar.Rapidity()); - histos.fill(HIST("QA/before/kstarinvmass"), lResoKstar.M()); - } - - if (lResoKstar.Rapidity() > cKstarMaxRap || lResoKstar.Rapidity() < cKstarMinRap) - continue; - - if constexpr (!IsMix) { - unsigned int typeKstar = bTrack.sign() > 0 ? binType::kKstarP : binType::kKstarN; - - histos.fill(HIST("QA/after/KstarRapidity"), lResoKstar.Rapidity()); - histos.fill(HIST("QA/after/kstarinvmass"), lResoKstar.M()); - histos.fill(HIST("hInvmass_Kstar"), typeKstar, centrality, lResoKstar.Pt(), lResoKstar.M()); - - } // IsMix - } // K0scand - } // bTrack - - count++; - - } // fillHistograms - - // process data - void processData(EventCandidates::iterator const& collision, - TrackCandidates const& tracks, - V0Candidates const& v0s, - aod::BCsWithTimestamps const&) - { - if (!colCuts.isSelected(collision)) // Default event selection - return; - colCuts.fillQA(collision); - centrality = GetCentrality(collision); - - fillHistograms(collision, tracks, v0s); // second order - } - PROCESS_SWITCH(chk892_pp, processData, "Process Event for data without Partitioning", true); - - // process MC reconstructed level - void processMC(EventCandidates::iterator const& collision, - MCTrackCandidates const& tracks, - MCV0Candidates const& v0s) - { - - histos.fill(HIST("QAMC/hEvent"), 1.0); - - fillHistograms(collision, tracks, v0s); - } - PROCESS_SWITCH(chk892_pp, processMC, "Process Event for MC", false); -}; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-chk892pp"})}; -} diff --git a/PWGLF/Tasks/Resonances/chk892pp.cxx b/PWGLF/Tasks/Resonances/chk892pp.cxx index fd4e7d8d75d..817b069f6c4 100644 --- a/PWGLF/Tasks/Resonances/chk892pp.cxx +++ b/PWGLF/Tasks/Resonances/chk892pp.cxx @@ -35,7 +35,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" @@ -152,9 +153,9 @@ struct Chk892pp { // Configurables struct : ConfigurableGroup { - ConfigurableAxis cfgBinsPt{"cfgBinsPt", {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 cfgBinsPtQA{"cfgBinsPtQA", {VARIABLE_WIDTH, 0.0, 0.8, 1.3, 1.8, 2.3, 2.8, 3.4, 4.0, 5.0, 6.0, 7.0, 8.0}, "Binning of the pT axis"}; - ConfigurableAxis cfgBinsCent{"cfgBinsCent", {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 cfgBinsPt{"cfgBinsPt", {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}, "Binning of the pT axis"}; + ConfigurableAxis cfgBinsPtQA{"cfgBinsPtQA", {VARIABLE_WIDTH, 0.0, 0.3, 0.6, 1.2, 1.8, 2.4, 3.0, 3.6, 4.2, 4.8, 5.4, 6.0, 7.0, 10.0}, "Binning of the pT axis"}; + ConfigurableAxis cfgBinsCent{"cfgBinsCent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0, 110.0}, "Binning of the centrality axis"}; ConfigurableAxis cfgBinsVtxZ{"cfgBinsVtxZ", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "Binning of the z-vertex axis"}; Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; Configurable cNbinsDivQA{"cNbinsDivQA", 1, "Integer to divide the number of bins for QA"}; @@ -190,9 +191,9 @@ struct Chk892pp { /// PID Selections, pion struct : ConfigurableGroup { - Configurable cfgTPConly{"cfgTPConly", false, "Use only TPC for PID"}; // bool - Configurable cfgMaxTPCnSigmaPion{"cfgMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cfgMaxTOFnSigmaPion{"cfgMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cfgTPConly{"cfgTPConly", true, "Use only TPC for PID"}; // bool + Configurable cfgMaxTPCnSigmaPion{"cfgMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cfgMaxTOFnSigmaPion{"cfgMaxTOFnSigmaPion", 5.0, "TOF nSigma cut for Pion"}; // TOF Configurable cfgNsigmaCutCombinedPion{"cfgNsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined Configurable cfgTOFVeto{"cfgTOFVeto", false, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto Configurable cfgTOFMinPt{"cfgTOFMinPt", 0.6, "Minimum TOF pT cut for Pion"}; // TOF pT cut @@ -208,6 +209,7 @@ struct Chk892pp { Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor Configurable cfgpTdepDCAxyCut{"cfgpTdepDCAxyCut", true, "pT-dependent DCAxy cut"}; + Configurable cfgpTdepDCAzCut{"cfgpTdepDCAzCut", true, "pT-dependent DCAz cut"}; 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"}; @@ -273,6 +275,7 @@ struct Chk892pp { int kPDGK0 = kK0; int kKstarPlus = o2::constants::physics::Pdg::kKPlusStar892; // int kPiPlus = 211; + double fMaxPosPV = 1e-2; void init(o2::framework::InitContext&) { @@ -398,6 +401,7 @@ struct Chk892pp { histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); histos.add("QA/before/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/before/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); @@ -410,6 +414,7 @@ struct Chk892pp { histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); histos.add("QA/after/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/after/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); // Kstar @@ -436,14 +441,20 @@ struct Chk892pp { histos.add("QAvtxz_woCut", "z-vertex without cut", HistType::kTH1F, {vtxzAxis}); histos.add("QAvtxz_wVtxzCut", "z-vertex with vtxz cut", HistType::kTH1F, {vtxzAxis}); - histos.add("EffK0s/genK0s", "Gen K0s (|y<0.8|)", HistType::kTH2F, {ptAxisQA, centAxis}); - histos.add("EffK0s/recoK0s", "Reco K0s (|y<0.8|)", HistType::kTH2F, {ptAxisQA, centAxis}); + histos.add("EffK0s/genK0s", "Gen K0s (|y<0.8|)", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("EffK0s/recoK0s", "Reco K0s (|y<0.8|)", HistType::kTH2F, {ptAxis, centAxis}); - histos.add("EffKstar/genKstar", "Gen Kstar (|y|<0.5)", HistType::kTH2F, {ptAxisQA, centAxis}); - histos.add("EffKstar/recoKstar", "Kstar Reco matched (final all)", HistType::kTH2F, {ptAxisQA, centAxis}); + histos.add("EffKstar/genKstar", "Gen Kstar (|y|<0.5)", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("EffKstar/genKstar_pri", "Gen primary Kstar (|y|<0.5)", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("EffKstar/genKstar_pri_pos", "Gen primary Kstar selected by vertex position (|y|<0.5)", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("EffKstar/recoKstar", "Kstar Reco matched (final all)", HistType::kTH2F, {ptAxis, centAxis}); - histos.add("Correction/sigLoss_den", "Gen Kstar (|y|<0.5) in truth class", HistType::kTH2F, {ptAxisQA, centAxis}); - histos.add("Correction/sigLoss_num", "Gen Kstar (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxisQA, centAxis}); + histos.add("Correction/sigLoss_den", "Gen Kstar (|y|<0.5) in truth class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_den_pri", "Gen primary Kstar (|y|<0.5) in truth class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_den_pri_pos", "Gen primary Kstar selected by vertex position (|y|<0.5) in truth class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_num", "Gen Kstar (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_num_pri", "Gen primary Kstar (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxis, centAxis}); + histos.add("Correction/sigLoss_num_pri_pos", "Gen primary Kstar selected by vertex position (|y|<0.5, selected events) in reco class", HistType::kTH2F, {ptAxis, centAxis}); histos.add("Correction/EF_den", "Gen events (truth class)", HistType::kTH1F, {centAxis}); histos.add("Correction/EF_num", "Reco events (selected events)", HistType::kTH1F, {centAxis}); histos.add("Correction/MCTruthCent_all", "MC truth FT0M centrality (all mcCollisions)", HistType::kTH1F, {centAxis}); @@ -539,8 +550,14 @@ struct Chk892pp { if (std::abs(track.dcaXY()) > TrackCuts.cfgMaxbDCArToPVcut) return false; } - if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) - return false; + if (TrackCuts.cfgpTdepDCAzCut) { + // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution + if (std::abs(track.dcaZ()) > (0.004 + (0.013 / track.pt()))) + return false; + } else { + if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) + return false; + } return true; } @@ -720,7 +737,6 @@ struct Chk892pp { centTruthByAllowed.clear(); for (const auto& coll : events) { - // lCentrality = getCentrality(coll); if (!coll.has_mcCollision()) continue; @@ -902,7 +918,7 @@ struct Chk892pp { return true; } // matchRecoToTruthKstar - void effKstarProcessGen(MCTrueTrackCandidates const& mcparts) + void effKstarProcessGen(soa::Join const&, MCTrueTrackCandidates const& mcparts) { for (const auto& part : mcparts) { if (!part.has_mcCollision()) @@ -912,6 +928,38 @@ struct Chk892pp { if (std::abs(part.y()) > KstarCuts.cfgKstarMaxRap) continue; + const int pionWanted = (part.pdgCode() > 0) ? +kPiPlus : -kPiPlus; + bool hasRightPion = false; + bool hasK0sToPipi = false; + + for (const auto& d1 : part.template daughters_as()) { + const int pdg1 = d1.pdgCode(); + if (pdg1 == pionWanted) { + hasRightPion = true; + } else if (std::abs(pdg1) == kPDGK0) { + for (const auto& d2 : d1.template daughters_as()) { + if (std::abs(d2.pdgCode()) == kPDGK0s) { + bool seenPip = false, seenPim = false; + for (const auto& d3 : d2.template daughters_as()) { + if (d3.pdgCode() == +kPiPlus) + seenPip = true; + else if (d3.pdgCode() == -kPiPlus) + seenPim = true; + } + if (seenPip && seenPim) { + hasK0sToPipi = true; + break; + } + } + } + } + if (hasRightPion && hasK0sToPipi) + break; + } + + if (!(hasRightPion && hasK0sToPipi)) + continue; + const auto mcid = part.mcCollisionId(); if (allowedMcIds.count(mcid) == 0) continue; @@ -923,6 +971,22 @@ struct Chk892pp { const float lCentrality = iter->second; histos.fill(HIST("EffKstar/genKstar"), part.pt(), lCentrality); + + if (part.vt() == 0) { + histos.fill(HIST("EffKstar/genKstar_pri"), part.pt(), lCentrality); + } + + const auto mcc = part.mcCollision_as>(); + + const float dx = part.vx() - mcc.posX(); + const float dy = part.vy() - mcc.posY(); + const float dz = part.vz() - mcc.posZ(); + + const float distanceFromPV = std::sqrt(dx * dx + dy * dy + dz * dz); + + if (distanceFromPV < fMaxPosPV) { + histos.fill(HIST("EffKstar/genKstar_pri_pos"), part.pt(), lCentrality); + } } } // effKstarProcessGen @@ -965,7 +1029,7 @@ struct Chk892pp { LorentzVectorSetXYZM lResoSecondary, lDecayDaughter_bach, lResoKstar, lDaughterRot, lResonanceRot; - lResoSecondary = LorentzVectorSetXYZM(v0.px(), v0.py(), v0.pz(), v0.mK0Short()); + lResoSecondary = LorentzVectorSetXYZM(v0.px(), v0.py(), v0.pz(), MassK0Short); lDecayDaughter_bach = LorentzVectorSetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); lResoKstar = lResoSecondary + lDecayDaughter_bach; @@ -990,7 +1054,7 @@ struct Chk892pp { } } // effKstarProcessReco - void fillSigLossNum(MCTrueTrackCandidates const& mcparts) + void fillSigLossNum(soa::Join const&, MCTrueTrackCandidates const& mcparts) { for (auto const& part : mcparts) { if (!part.has_mcCollision()) @@ -1011,10 +1075,25 @@ struct Chk892pp { const float lCentrality = iter->second; histos.fill(HIST("Correction/sigLoss_num"), part.pt(), lCentrality); + if (part.vt() == 0) { + histos.fill(HIST("Correction/sigLoss_num_pri"), part.pt(), lCentrality); + } + + const auto mcc = part.mcCollision_as>(); + + const float dx = part.vx() - mcc.posX(); + const float dy = part.vy() - mcc.posY(); + const float dz = part.vz() - mcc.posZ(); + + const float distanceFromPV = std::sqrt(dx * dx + dy * dy + dz * dz); + + if (distanceFromPV < fMaxPosPV) { + histos.fill(HIST("Correction/sigLoss_num_pri_pos"), part.pt(), lCentrality); + } } } // fillSigLossNum - void fillSigLossDen(MCTrueTrackCandidates const& mcparts) + void fillSigLossDen(soa::Join const&, MCTrueTrackCandidates const& mcparts) { for (auto const& part : mcparts) { if (!part.has_mcCollision()) @@ -1035,6 +1114,21 @@ struct Chk892pp { const float lCentrality = iter->second; histos.fill(HIST("Correction/sigLoss_den"), part.pt(), lCentrality); + if (part.vt() == 0) { + histos.fill(HIST("Correction/sigLoss_den_pri"), part.pt(), lCentrality); + } + + const auto mcc = part.mcCollision_as>(); + + const float dx = part.vx() - mcc.posX(); + const float dy = part.vy() - mcc.posY(); + const float dz = part.vz() - mcc.posZ(); + + const float distanceFromPV = std::sqrt(dx * dx + dy * dy + dz * dz); + + if (distanceFromPV < fMaxPosPV) { + histos.fill(HIST("Correction/sigLoss_den_pri_pos"), part.pt(), lCentrality); + } } } // fillSigLossDen @@ -1121,8 +1215,6 @@ struct Chk892pp { auto trkkpt = k0sCand.pt(); auto trkkRadius = k0sCand.v0radius(); - lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); - if constexpr (!IsMix) { if (cfgFillQAPlots) { // Seconddary QA plots @@ -1154,6 +1246,7 @@ struct Chk892pp { histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); histos.fill(HIST("QA/before/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/before/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); } } @@ -1197,9 +1290,10 @@ struct Chk892pp { histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); histos.fill(HIST("QA/after/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/after/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); } - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M()); + histos.fill(HIST("hInvmass_K0s"), lCentrality, trkkpt, trkkMass); } k0sIndicies.push_back(k0sCand.index()); } @@ -1209,10 +1303,8 @@ struct Chk892pp { for (const auto& k0sIndex : k0sIndicies) { auto k0sCand = dTracks2.rawIteratorAt(k0sIndex); - auto trkkMass = k0sCand.mK0Short(); - lDecayDaughter_bach = LorentzVectorSetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); - lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); + lResoSecondary = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); lResoKstar = lResoSecondary + lDecayDaughter_bach; // QA plots @@ -1299,10 +1391,10 @@ struct Chk892pp { buildReferenceMcIds(mccolls, mcpart); effK0sProcessGen(mcpart); effK0sProcessReco(v0s); - effKstarProcessGen(mcpart); + effKstarProcessGen(mccolls, mcpart); effKstarProcessReco(v0s, tracks); - fillSigLossNum(mcpart); - fillSigLossDen(mcpart); + fillSigLossNum(mccolls, mcpart); + fillSigLossDen(mccolls, mcpart); for (const auto& mcid : refClassIds) { histos.fill(HIST("Correction/EF_den"), refCentByMcId[mcid]); @@ -1380,7 +1472,7 @@ struct Chk892pp { auto id = collision.mcCollisionId(); auto mccoll = mccolls.iteratorAt(id); - const float lCentrality = mccoll.centFT0M(); + lCentrality = mccoll.centFT0M(); if (lCentrality < EventCuts.cfgEventCentralityMin || lCentrality > EventCuts.cfgEventCentralityMax) return; diff --git a/PWGLF/Tasks/Resonances/cksspinalignder.cxx b/PWGLF/Tasks/Resonances/cksspinalignder.cxx index ae29ab6a6fc..9546b96d9d0 100644 --- a/PWGLF/Tasks/Resonances/cksspinalignder.cxx +++ b/PWGLF/Tasks/Resonances/cksspinalignder.cxx @@ -38,12 +38,15 @@ #include // for std::fabs #include // #include +#include #include +#include #include // <<< CHANGED: for dedup sets #include #include #include #include // <<< CHANGED: for seenMap +#include #include #include @@ -77,14 +80,18 @@ struct cksspinalignder { Configurable ptMax{"ptMax", 10.0, "V0 Pt maximum"}; Configurable v0eta{"v0eta", 0.8, "Eta cut on lambda"}; // pion sel///////// - Configurable nsigmaCutTPC{"nsigmaCutTPC", 3.0, "N sigma TPC cut for bachelor pions"}; - Configurable nsigmaCutTOF{"nsigmaCutTOF", 3.0, "N sigma TOF cut for bachelor pions"}; - Configurable usePID{"usePID", false, "Flag for using PID selection"}; + Configurable usePID{"usePID", false, "Enable PID selection using stored bitmask"}; + // Choose which PID bit to require (1..4). If pidExclusive=true -> require ONLY that PID. + Configurable pidChoice{"pidChoice", 2, "PID choice: 1,2,3,4"}; + Configurable pidExclusive{"pidExclusive", false, "If true require ONLY the chosen PID (mask == bit). If false require (mask & bit)!=0"}; // Event Mixing Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; ConfigurableAxis cfgVtxBins{"cfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; ConfigurableAxis cfgMultBins{"cfgMultBins", {8, 0.0, 80}, "Mixing bins - centrality"}; + Configurable ptMix{"ptMix", 0.2f, "ME: pT bin width"}; + Configurable etaMix{"etaMix", 0.2f, "ME: eta bin width"}; + Configurable phiMix{"phiMix", 0.3f, "ME: phi bin width"}; // THnsparse bining ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {50, 1.09, 1.14}, "#it{M} (GeV/#it{c}^{2})"}; @@ -153,25 +160,47 @@ struct cksspinalignder { return true; } - template - bool selectionPID(const T& candidate) + // ----- PID via stored bitmask (no selectionPID function needed) ----- + // Assumes your PionTracks table has a uint8_t column named pionPidMask(). + // Bit mapping: PID1=1, PID2=2, PID3=4, PID4=8. + static constexpr uint8_t kPID1 = 1u << 0; + static constexpr uint8_t kPID2 = 1u << 1; + static constexpr uint8_t kPID3 = 1u << 2; + static constexpr uint8_t kPID4 = 1u << 3; + + uint8_t requiredPidBit() const { - auto px = candidate.pionBachPx(); - auto py = candidate.pionBachPy(); - auto pz = candidate.pionBachPz(); - auto p = std::sqrt(px * px + py * py + pz * pz); - float lowmom = 0.5; - if (p < lowmom) { - if (!candidate.pionBachTOFHit() && std::abs(candidate.pionBachTPC()) < nsigmaCutTPC) { - return true; - } else if (candidate.pionBachTOFHit() && std::sqrt(candidate.pionBachTPC() * candidate.pionBachTPC() + candidate.pionBachTOF() * candidate.pionBachTOF()) < nsigmaCutTOF) { - return true; - } - } else if (candidate.pionBachTOFHit() && std::sqrt(candidate.pionBachTPC() * candidate.pionBachTPC() + candidate.pionBachTOF() * candidate.pionBachTOF()) < nsigmaCutTOF) { + const int choice = pidChoice.value; + switch (choice) { + case 1: + return kPID1; + case 2: + return kPID2; + case 3: + return kPID3; + case 4: + return kPID4; + default: + LOGF(warn, "pidChoice=%d is invalid. Using PID2.", choice); + return kPID2; + } + } + + template + bool passSelectedPID(const TPion& pion) const + { + if (!usePID.value) { return true; } - return false; + const uint8_t bit = requiredPidBit(); + const uint8_t mask = pion.pionPidMask(); + + if (pidExclusive.value) { + return mask == bit; // ONLY chosen PID + } + return (mask & bit) != 0; // chosen PID (maybe others too) } + // --------------------------------------------------------------- std::tuple computePtEtaPhi(float px, float py, float pz) { @@ -207,15 +236,17 @@ struct cksspinalignder { histos.fill(HIST("hKShortMass"), kshort.M()); for (const auto& piontrack : piontracks) { + + // PID selection via stored mask + if (!passSelectedPID(piontrack)) { + continue; + } auto [pionPt, pionEta, pionPhi] = computePtEtaPhi(piontrack.pionBachPx(), piontrack.pionBachPy(), piontrack.pionBachPz()); pion = ROOT::Math::PtEtaPhiMVector(pionPt, pionEta, pionPhi, o2::constants::physics::MassPionCharged); if (piontrack.pionBachIndex() == v0.pionIndex1() || piontrack.pionBachIndex() == v0.pionIndex2()) continue; // checking if bachelor pion is khort daughter or not -> skip further processing if such is the case - if (usePID && !selectionPID(piontrack)) - continue; // checking PID - chkstar = kshort + pion; ROOT::Math::Boost boost{chkstar.BoostToCM()}; @@ -254,9 +285,11 @@ struct cksspinalignder { auto [kshortPtmix, kshortEtamix, kshortPhimix] = computePtEtaPhi(t1.kShortPx(), t1.kShortPy(), t1.kShortPz()); kshortmix = ROOT::Math::PtEtaPhiMVector(kshortPtmix, kshortEtamix, kshortPhimix, t1.kShortMass()); + // PID selection via stored mask (on the bachelor pion from the mixed event) + if (!passSelectedPID(t2)) { + continue; + } auto [pionPtmix, pionEtamix, pionPhimix] = computePtEtaPhi(t2.pionBachPx(), t2.pionBachPy(), t2.pionBachPz()); - if (usePID && !selectionPID(t2)) - continue; // checking PID pionmix = ROOT::Math::PtEtaPhiMVector(pionPtmix, pionEtamix, pionPhimix, o2::constants::physics::MassPionCharged); chkstarmix = kshortmix + pionmix; @@ -272,6 +305,526 @@ struct cksspinalignder { } } PROCESS_SWITCH(cksspinalignder, processMixedData, "Process mixed data", true); + + // ===================================================================================== + // MEV2-style mixing for Charged K* : KEEP K0s (from event E) FIXED, MIX bachelor pion + // pion is taken from other events E' but matched in (event class + pion pt/eta/phi) + // ===================================================================================== + + // One status bin (unused dimension, kept for compatibility with linearKey) + static constexpr int N_STATUS = 1; + + // ---------- Binner for bachelor-pion kinematics ---------- + struct MixBinnerPi { + float ptMin, ptMax, ptStep; + float etaMin, etaMax, etaStep; + float phiMin, phiMax, phiStep; + + // Dummy "mass" axis (we keep 1 bin to keep the same 6D infrastructure) + static constexpr float mMin = 0.f; + static constexpr float mMax = 1.f; + static constexpr int nM_ = 1; + static constexpr float mStep = (mMax - mMin) / nM_; + + int nPt_{1}, nEta_{1}, nPhi_{1}; + + MixBinnerPi(float ptMin_, float ptMax_, float ptStep_, + float etaAbsMax_, float etaStep_, + float phiStep_) + : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax_), etaMax(+etaAbsMax_), etaStep(etaStep_), phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), phiStep(phiStep_) + { + ptStep = (ptStep > 0.f ? ptStep : 0.2f); + etaStep = (etaStep > 0.f ? etaStep : 0.2f); + phiStep = (phiStep > 0.f ? phiStep : 0.2f); + + nPt_ = std::max(1, static_cast(std::floor((ptMax - ptMin) / ptStep + 0.5f))); + nEta_ = std::max(1, static_cast(std::floor((etaMax - etaMin) / etaStep + 0.5f))); + nPhi_ = std::max(1, static_cast(std::ceil((phiMax - phiMin) / phiStep))); + } + + inline int nPt() const { return nPt_; } + inline int nEta() const { return nEta_; } + inline int nPhi() const { return nPhi_; } + inline int nM() const { return nM_; } + + inline int binFromValue(float v, float vmin, float step, int nBins) const + { + if (!std::isfinite(v)) + return -1; + const float x = (v - vmin) / step; + int b = static_cast(std::floor(x + 1e-6f)); + if (b < 0) + return -1; + if (b >= nBins) + b = nBins - 1; + return b; + } + + inline int ptBin(float pt) const { return binFromValue(pt, ptMin, ptStep, nPt_); } + inline int etaBin(float eta) const { return binFromValue(eta, etaMin, etaStep, nEta_); } + inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } + inline int massBin(float m) const { return binFromValue(m, mMin, mStep, nM_); } // always 0 if finite + }; + + // Buffer candidate: one pion stored in a bin + struct BufferCandPi { + int64_t collisionIdx; // to enforce different event + int64_t rowIndex; // row id in PionTracks (for iteratorAt) + uint16_t ptBin, etaBin, phiBin, mBin; + }; + + struct MatchRef { + int64_t collisionIdx; + int64_t rowIndex; + }; + + // Key: (colBin, stat, pt, eta, phi, m) + static inline size_t linearKey(int colBin, int statBin, + int ptBin, int etaBin, int phiBin, int mBin, + int nStat, int nPt, int nEta, int nPhi, int nM) + { + return ((((((static_cast(colBin) * nStat + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin)); + } + + // ===================================================================================== + // Mixed-event method: + // PASS 1: build buffer of pions by (event-class bin) + (pi pt/eta/phi bins) + // PASS 2: loop same-event (K0, piSame) pairs; replace piSame by piX from buffer + // keep K0 from current event fixed; use psiFT0C of current event. + // ===================================================================================== + void processMixedDataMEV2_Pion(EventCandidates const& collisions, + aod::KShortTracks const& V0s, + aod::PionTracks const& piontracks) + { + static thread_local std::mt19937 rng(0xBADC0FFE); + + // Build pion binner from your configurables + // Use your own pt range config for bachelor pions if you have it; otherwise reuse ptMin/ptMax + MixBinnerPi mb{ + ptMin, ptMax, /*ptStep*/ ptMix.value, + /*|eta|max*/ v0eta.value, /*etaStep*/ etaMix.value, + /*phiStep*/ phiMix.value}; + + const int nCol = colBinning.getAllBinsCount(); // event-class bins (vz, cent) + const int nStat = N_STATUS; // 1 + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; + std::vector> buffer(nKeys); + + // ---------------- PASS 1: fill 6D buffer with bachelor pions ---------------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); + if (colBin < 0) + continue; + + auto slicePi = piontracks.sliceBy(tracksPerCollisionBach, col.index()); + + for (auto const& pi : slicePi) { + + // apply configurable PID selection stored in bitmask (your passSelectedPID) + if (!passSelectedPID(pi)) + continue; + + auto [pt, eta, phi] = computePtEtaPhi(pi.pionBachPx(), pi.pionBachPy(), pi.pionBachPz()); + phi = RecoDecay::constrainAngle(phi, 0.0F); + + const int ptB = mb.ptBin(pt); + const int etaB = mb.etaBin(eta); + const int phiB = mb.phiBin(phi); + const int mB = 0; // dummy axis has 1 bin + if (ptB < 0 || etaB < 0 || phiB < 0) + continue; + + const int stat = 0; + const size_t key = linearKey(colBin, stat, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM); + + const int64_t row = static_cast(pi.globalIndex()); + + buffer[key].push_back(BufferCandPi{ + .collisionIdx = static_cast(col.index()), + .rowIndex = row, + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB)}); + } + } + + // ---------------- PASS 2: same-event (K0,piSame), replace ONLY pion by piX ---------------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); + if (colBin < 0) + continue; + + auto poolK0 = V0s.sliceBy(tracksPerCollisionV0, col1.index()); + auto poolPi = piontracks.sliceBy(tracksPerCollisionBach, col1.index()); + if (poolK0.size() == 0 || poolPi.size() == 0) + continue; + + const float centrality = col1.cent(); + const float psiFT0Cmix = col1.psiFT0C(); + + // Loop over K0s from the *current* event (fixed object) + for (auto const& k0 : poolK0) { + if (!selectionV0(k0)) + continue; + + // Build K0 4-vector once + auto [kpt, keta, kphi] = computePtEtaPhi(k0.kShortPx(), k0.kShortPy(), k0.kShortPz()); + kphi = RecoDecay::constrainAngle(kphi, 0.0F); + kshortmix = ROOT::Math::PtEtaPhiMVector(kpt, keta, kphi, k0.kShortMass()); + + // Loop over same-event pions to define the "same-event pair" base + for (auto const& piSame : poolPi) { + if (!passSelectedPID(piSame)) + continue; + + // avoid self-combination: bachelor pion can't be a K0 daughter + if (piSame.pionBachIndex() == k0.pionIndex1() || piSame.pionBachIndex() == k0.pionIndex2()) { + continue; + } + + // Compute the kinematic bin of THIS pion (this defines where to pick mixed pions) + auto [ppt, peta, pphi] = computePtEtaPhi(piSame.pionBachPx(), piSame.pionBachPy(), piSame.pionBachPz()); + pphi = RecoDecay::constrainAngle(pphi, 0.0F); + + const int ptB = mb.ptBin(ppt); + const int etaB = mb.etaBin(peta); + const int phiB = mb.phiBin(pphi); + const int mB = 0; + if (ptB < 0 || etaB < 0 || phiB < 0) + continue; + + const int stat = 0; + const size_t key = linearKey(colBin, stat, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM); + auto const& binVec = buffer[key]; + if (binVec.empty()) + continue; + + // collect partners from same bin but different collision + std::vector matches; + matches.reserve(binVec.size()); + const int64_t curColIdx = static_cast(col1.index()); + + for (auto const& bc : binVec) { + if (bc.collisionIdx == curColIdx) + continue; + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + if (matches.empty()) + continue; + + // random unique sampling (cap = nEvtMixing) + const int cap = nEvtMixing.value; + if (cap > 0 && cap < static_cast(matches.size())) { + std::uniform_int_distribution dist(0, static_cast(matches.size()) - 1); + std::unordered_set chosen; + chosen.reserve(static_cast(cap) * 2); + while (static_cast(chosen.size()) < cap) + chosen.insert(dist(rng)); + + std::vector subset; + subset.reserve(cap); + for (const int& idx : chosen) + subset.push_back(matches[idx]); + matches.swap(subset); + } else { + std::shuffle(matches.begin(), matches.end(), rng); + } + + // const float wBase = 1.0f / static_cast(matches.size()); + const float wBase = 1.0; + + // Replace pion by mixed pion piX, keep k0 fixed + for (auto const& m : matches) { + auto piX = piontracks.iteratorAt(m.rowIndex); // must match PASS 1 rowIndex convention + + // safety: PID selection again + if (!passSelectedPID(piX)) + continue; + + // OPTIONAL keep: also avoid piX being a K0 daughter (same k0 from current event) + if (piX.pionBachIndex() == k0.pionIndex1() || piX.pionBachIndex() == k0.pionIndex2()) { + continue; + } + + auto [xpt, xeta, xphi] = computePtEtaPhi(piX.pionBachPx(), piX.pionBachPy(), piX.pionBachPz()); + xphi = RecoDecay::constrainAngle(xphi, 0.0F); + pionmix = ROOT::Math::PtEtaPhiMVector(xpt, xeta, xphi, o2::constants::physics::MassPionCharged); + + chkstarmix = kshortmix + pionmix; + + ROOT::Math::Boost boost{chkstarmix.BoostToCM()}; + fourVecDauCMmix = boost(kshortmix); + threeVecDauCMmix = fourVecDauCMmix.Vect(); + + eventplaneVecNormmix = ROOT::Math::XYZVector(std::sin(2.f * psiFT0Cmix), + -std::cos(2.f * psiFT0Cmix), 0.f); + + const float cosThetaStarmix = + eventplaneVecNormmix.Dot(threeVecDauCMmix) / + std::sqrt(threeVecDauCMmix.Mag2()) / + std::sqrt(eventplaneVecNormmix.Mag2()); + + histos.fill(HIST("hSparsemix"), + chkstarmix.M(), chkstarmix.Pt(), cosThetaStarmix, centrality, wBase); + } + } + } + } + } + + PROCESS_SWITCH(cksspinalignder, processMixedDataMEV2_Pion, "Process mixed data MEV4 (keep K0 fixed, replace pion with mixed pion)", true); + + /* +// ---- Configuration knobs (already in your task or add similarly) ---- +// ptMix: step for K0 pT binning, etaMix step for eta, phiMix step for phi +// configThnAxisInvMass etc are your histogram axes (not used for binning here) + +// We can keep one status bin for now +static constexpr int N_STATUS = 1; + +// Binner for K0 kinematics +struct MixBinnerK0 { + float ptMin, ptMax, ptStep; + float etaMin, etaMax, etaStep; + float phiMin, phiMax, phiStep; + + // K0 mass binning (you can widen if you want) + static constexpr float mMin = 0.45f; + static constexpr float mMax = 0.55f; // exclusive-ish + static constexpr int nM_ = 1; + static constexpr float mStep = (mMax - mMin) / nM_; + + int nPt_, nEta_, nPhi_; + + MixBinnerK0(float ptMin_, float ptMax_, float ptStep_, + float etaAbsMax_, float etaStep_, + float phiStep_) + : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), + etaMin(-etaAbsMax_), etaMax(+etaAbsMax_), etaStep(etaStep_), + phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), phiStep(phiStep_) + { + ptStep = (ptStep > 0.f ? ptStep : 0.1f); + etaStep = (etaStep > 0.f ? etaStep : 0.1f); + phiStep = (phiStep > 0.f ? phiStep : 0.1f); + + nPt_ = std::max(1, static_cast(std::floor((ptMax - ptMin) / ptStep + 0.5f))); + nEta_ = std::max(1, static_cast(std::floor((etaMax - etaMin) / etaStep + 0.5f))); + nPhi_ = std::max(1, static_cast(std::ceil((phiMax - phiMin) / phiStep))); + } + + inline int nPt() const { return nPt_; } + inline int nEta() const { return nEta_; } + inline int nPhi() const { return nPhi_; } + inline int nM() const { return nM_; } + + inline int binFromValue(float v, float vmin, float step, int nBins) const + { + if (!std::isfinite(v)) return -1; + const float x = (v - vmin) / step; + int b = static_cast(std::floor(x + 1e-6f)); + if (b < 0) return -1; + if (b >= nBins) b = nBins - 1; + return b; + } + + inline int ptBin(float pt) const { return binFromValue(pt, ptMin, ptStep, nPt_); } + inline int etaBin(float eta) const { return binFromValue(eta, etaMin, etaStep, nEta_); } + inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } + inline int massBin(float m) const { return binFromValue(m, mMin, mStep, nM_); } +}; + + struct BufferCandK0 { + int64_t collisionIdx; // to enforce different event + int64_t rowIndex; // row id in KShortTracks (for iteratorAt) + uint16_t ptBin, etaBin, phiBin, mBin; + }; + + struct MatchRef { + int64_t collisionIdx; + int64_t rowIndex; + }; + + // Key: (colBin, stat, pt, eta, phi, m) + static inline size_t linearKey(int colBin, int statBin, + int ptBin, int etaBin, int phiBin, int mBin, + int nStat, int nPt, int nEta, int nPhi, int nM) + { + return ((((((static_cast(colBin) * nStat + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin)); + } + + void processMixedDataMEV4(EventCandidates const& collisions, + aod::KShortTracks const& V0s, + aod::PionTracks const& piontracks) + { + static thread_local std::mt19937 rng(0xBADC0FFE); + + // Build K0 binner from your configurables + MixBinnerK0 mb{ + ptMin.value, ptMax.value, ptMix.value, + v0eta.value, etaMix.value, + phiMix.value + }; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; + std::vector> buffer(nKeys); + + // ---------------- PASS 1: fill 6D buffer with K0s ---------------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); + if (colBin < 0) continue; + + auto sliceK0 = V0s.sliceBy(tracksPerCollisionV0, col.index()); + + for (auto const& k0 : sliceK0) { + if (!selectionV0(k0)) continue; + + auto [kpt, keta, kphi] = computePtEtaPhi(k0.kShortPx(), k0.kShortPy(), k0.kShortPz()); + kphi = RecoDecay::constrainAngle(kphi, 0.0F); + + const int ptB = mb.ptBin(kpt); + const int etaB = mb.etaBin(keta); + const int phiB = mb.phiBin(kphi); + const int mB = mb.massBin(k0.kShortMass()); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) continue; + + const int stat = 0; + const size_t key = linearKey(colBin, stat, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM); + + // IMPORTANT: rowIndex must match iteratorAt accessor below. + const int64_t row = static_cast(k0.globalIndex()); // if this fails -> use k0.index() consistently + + buffer[key].push_back(BufferCandK0{ + .collisionIdx = static_cast(col.index()), + .rowIndex = row, + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB) + }); + } + } + + // ---------------- PASS 2: build same-event (K0,π) pairs, replace only K0 by K0X ---------------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); + if (colBin < 0) continue; + + auto poolK0 = V0s.sliceBy(tracksPerCollisionV0, col1.index()); + auto poolPi = piontracks.sliceBy(tracksPerCollisionBach, col1.index()); + + if (poolK0.size() == 0 || poolPi.size() == 0) continue; // no .empty() in ASoA slice + + const float centrality = col1.cent(); + const float psiFT0Cmix = col1.psiFT0C(); + + // same-event pair loop + for (auto const& k0 : poolK0) { + if (!selectionV0(k0)) continue; + + auto [kpt, keta, kphi] = computePtEtaPhi(k0.kShortPx(), k0.kShortPy(), k0.kShortPz()); + kphi = RecoDecay::constrainAngle(kphi, 0.0F); + + const int ptB = mb.ptBin(kpt); + const int etaB = mb.etaBin(keta); + const int phiB = mb.phiBin(kphi); + const int mB = mb.massBin(k0.kShortMass()); + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) continue; + + const int stat = 0; + const size_t key = linearKey(colBin, stat, ptB, etaB, phiB, mB, nStat, nPt, nEta, nPhi, nM); + auto const& binVec = buffer[key]; + if (binVec.empty()) continue; + + // pre-collect eligible K0 partners from other events (same bin, different collision) + std::vector matches; + matches.reserve(binVec.size()); + const int64_t curColIdx = static_cast(col1.index()); + + for (auto const& bc : binVec) { + if (bc.collisionIdx == curColIdx) continue; + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + if (matches.empty()) continue; + + // choose random unique subset of K0 partners + const int cap = nEvtMixing.value; + if (cap > 0 && cap < static_cast(matches.size())) { + std::uniform_int_distribution dist(0, static_cast(matches.size()) - 1); + std::unordered_set chosen; + chosen.reserve(static_cast(cap) * 2); + while (static_cast(chosen.size()) < cap) chosen.insert(dist(rng)); + + std::vector subset; + subset.reserve(cap); + for (const int& idx : chosen) subset.push_back(matches[idx]); + matches.swap(subset); + } else { + std::shuffle(matches.begin(), matches.end(), rng); + } + + const float wBase = 1.0f / static_cast(matches.size()); + + // Now keep π from SAME event fixed (this is your requirement) + for (auto const& piSame : poolPi) { + if (!passSelectedPID(piSame)) continue; + + // avoid self-combination if you stored K0 daughter indices + if (piSame.pionBachIndex() == k0.pionIndex1() || piSame.pionBachIndex() == k0.pionIndex2()) { + continue; + } + + auto [ppt, peta, pphi] = computePtEtaPhi(piSame.pionBachPx(), piSame.pionBachPy(), piSame.pionBachPz()); + pphi = RecoDecay::constrainAngle(pphi, 0.0F); + pionmix = ROOT::Math::PtEtaPhiMVector(ppt, peta, pphi, o2::constants::physics::MassPionCharged); + + // replace K0 by mixed K0X from other event, but keep piSame + for (auto const& m : matches) { + auto k0X = V0s.iteratorAt(m.rowIndex); // if globalIndex fails -> use index consistently in PASS1 + + if (!selectionV0(k0X)) continue; + + auto [xpt, xeta, xphi] = computePtEtaPhi(k0X.kShortPx(), k0X.kShortPy(), k0X.kShortPz()); + xphi = RecoDecay::constrainAngle(xphi, 0.0F); + kshortmix = ROOT::Math::PtEtaPhiMVector(xpt, xeta, xphi, k0X.kShortMass()); + + chkstarmix = kshortmix + pionmix; + + ROOT::Math::Boost boost{chkstarmix.BoostToCM()}; + fourVecDauCMmix = boost(kshortmix); + threeVecDauCMmix = fourVecDauCMmix.Vect(); + + eventplaneVecNormmix = ROOT::Math::XYZVector(std::sin(2.f * psiFT0Cmix), + -std::cos(2.f * psiFT0Cmix), 0.f); + + const float cosThetaStarmix = + eventplaneVecNormmix.Dot(threeVecDauCMmix) / + std::sqrt(threeVecDauCMmix.Mag2()) / + std::sqrt(eventplaneVecNormmix.Mag2()); + + histos.fill(HIST("hSparsemix"), + chkstarmix.M(), chkstarmix.Pt(), cosThetaStarmix, centrality, wBase); + } + } + } + } + } + + PROCESS_SWITCH(cksspinalignder, processMixedDataMEV4, + "Process mixed data MEV4 (replace K0, keep same-event pion)", true); + */ }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Resonances/doublephimeson.cxx b/PWGLF/Tasks/Resonances/doublephimeson.cxx index 38a7f31ed21..c7ac23a8e0b 100644 --- a/PWGLF/Tasks/Resonances/doublephimeson.cxx +++ b/PWGLF/Tasks/Resonances/doublephimeson.cxx @@ -82,7 +82,10 @@ struct doublephimeson { ConfigurableAxis configThnAxisNumPhi{"configThnAxisNumPhi", {101, -0.5, 100.5}, "cos #theta{*}"}; ConfigurableAxis configThnAxisDeltaPt{"configThnAxisDeltaPt", {100, 0.0, 1.0}, "delta pt"}; Configurable maxDeltaMPhi{"maxDeltaMPhi", 0.01f, "Delta-m cut on the two phi masses: sqrt((m1-mPDG)^2 + (m2-mPDG)^2) < maxDeltaMPhi (GeV/c^2)"}; - + // --- NEW: steerable axes from JSON --- + ConfigurableAxis configThnAxisDeltaRPhi{"configThnAxisDeltaRPhi", {120, 0.0, 6.0}, "ΔR(φ,φ)"}; + ConfigurableAxis configThnAxisZ{"configThnAxisZ", {100, 0.0, 1.0}, "z"}; + ConfigurableAxis configThnAxisA{"configThnAxisA", {100, 0.0, 1.0}, "A"}; // Initialize the ananlysis task void init(o2::framework::InitContext&) { @@ -109,10 +112,15 @@ struct doublephimeson { const AxisSpec thnAxisCosTheta{configThnAxisCosTheta, "cos #theta"}; const AxisSpec thnAxisNumPhi{configThnAxisNumPhi, "Number of phi meson"}; const AxisSpec thnAxisPtCorr{configThnAxisPtCorr, "Pt Corr var"}; - + const AxisSpec thnAxisDeltaRPhi{configThnAxisDeltaRPhi, "#Delta R(#phi,#phi)"}; + const AxisSpec thnAxisZ{configThnAxisZ, "z = p_{T1}/(p_{T1}+p_{T2})"}; + const AxisSpec thnAxisA{configThnAxisA, "A = |p_{T1}-p_{T2}|/(p_{T1}+p_{T2})"}; histos.add("SEMassUnlike", "SEMassUnlike", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisDeltaR, thnAxisPt, thnAxisDeltaR, thnAxisInvMassDeltaPhi, thnAxisPtCorr}); // histos.add("SEMassLike", "SEMassLike", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisDeltaR, thnAxisInvMassPhi, thnAxisInvMassPhi, thnAxisNumPhi}); histos.add("MEMassUnlike", "MEMassUnlike", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisDeltaR, thnAxisPt, thnAxisDeltaR, thnAxisInvMassDeltaPhi, thnAxisPtCorr}); + // --- NEW THnSparse storing (ΔRphi, z, A) WITHOUT applying cuts --- + histos.add("SEMassUnlike_DeltaRZA", "SEMassUnlike_DeltaRZA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisDeltaRPhi, thnAxisZ, thnAxisA, thnAxisInvMassDeltaPhi}); + histos.add("MEMassUnlike_DeltaRZA", "MEMassUnlike_DeltaRZA", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisDeltaRPhi, thnAxisZ, thnAxisA, thnAxisInvMassDeltaPhi}); } // get kstar @@ -806,7 +814,6 @@ struct doublephimeson { const double dR_k1p_k2m = deltaR(kplusA.Phi(), kplusA.Eta(), kminusB.Phi(), kminusB.Eta()); const double dR_k2p_k1m = deltaR(kplusB.Phi(), kplusB.Eta(), kminusA.Phi(), kminusA.Eta()); const double dR_k2p_k2m = deltaR(kplusB.Phi(), kplusB.Eta(), kminusB.Phi(), kminusB.Eta()); - double minDR = dRkplus; minDR = std::min(minDR, dRkminus); minDR = std::min(minDR, dR_k1p_k1m); @@ -926,6 +933,225 @@ struct doublephimeson { } PROCESS_SWITCH(doublephimeson, processopti3, "Process Optimized same event", false); + void processopti4(aod::RedPhiEvents::iterator const& collision, aod::PhiTracks const& phitracks) + { + if (additionalEvsel && (collision.numPos() < 2 || collision.numNeg() < 2)) + return; + + // --- φ multiplicity with PID --- + int phimult = 0; + for (auto const& t : phitracks) { + const double kpluspt = std::hypot(t.phid1Px(), t.phid1Py()); + const double kminuspt = std::hypot(t.phid2Px(), t.phid2Py()); + + // PID QA before + histos.fill(HIST("hnsigmaTPCTOFKaonBefore"), t.phid1TPC(), t.phid1TOF(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonPlusBefore"), t.phid1TPC(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonMinusBefore"), t.phid2TPC(), kminuspt); + + if (t.phiMass() < minPhiMass1 || t.phiMass() > maxPhiMass1) + continue; + if (kpluspt > maxKaonPt || kminuspt > maxKaonPt) + continue; + if (!selectionPID(t.phid1TPC(), t.phid1TOF(), t.phid1TOFHit(), strategyPID1, kpluspt)) + continue; + if (!selectionPID(t.phid2TPC(), t.phid2TOF(), t.phid2TOFHit(), strategyPID2, kminuspt)) + continue; + + // PID QA after + histos.fill(HIST("hnsigmaTPCTOFKaon"), t.phid1TPC(), t.phid1TOF(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonPlus"), t.phid1TPC(), kpluspt); + histos.fill(HIST("hnsigmaTPCKaonMinus"), t.phid2TPC(), kminuspt); + + ++phimult; + } + if (phimult < 2) + return; + + // --- helpers --- + constexpr double mPhiPDG = 1.019461; // GeV/c^2 + constexpr double mKPDG = 0.493677; // GeV/c^2 + + const auto deltaMPhi = [=](double m1, double m2) { + const double d1 = m1 - mPhiPDG, d2 = m2 - mPhiPDG; + return std::sqrt(d1 * d1 + d2 * d2); + }; + + const auto deltaR = [](double phi1, double eta1, double phi2, double eta2) { + const double dphi = TVector2::Phi_mpi_pi(phi1 - phi2); + const double deta = eta1 - eta2; + return std::sqrt(dphi * dphi + deta * deta); + }; + + // minimum ΔR among all kaons in the candidate (4 kaons → 6 combinations) + const auto minKaonDeltaR = [&](const ROOT::Math::PtEtaPhiMVector& kplusA, + const ROOT::Math::PtEtaPhiMVector& kplusB, + const ROOT::Math::PtEtaPhiMVector& kminusA, + const ROOT::Math::PtEtaPhiMVector& kminusB) { + // same-sign first (keep your QA histos) + const double dRkplus = deltaR(kplusA.Phi(), kplusA.Eta(), kplusB.Phi(), kplusB.Eta()); + const double dRkminus = deltaR(kminusA.Phi(), kminusA.Eta(), kminusB.Phi(), kminusB.Eta()); + histos.fill(HIST("hDeltaRkaonplus"), dRkplus); + histos.fill(HIST("hDeltaRkaonminus"), dRkminus); + + // all other combinations + const double dR_k1p_k1m = deltaR(kplusA.Phi(), kplusA.Eta(), kminusA.Phi(), kminusA.Eta()); + const double dR_k1p_k2m = deltaR(kplusA.Phi(), kplusA.Eta(), kminusB.Phi(), kminusB.Eta()); + const double dR_k2p_k1m = deltaR(kplusB.Phi(), kplusB.Eta(), kminusA.Phi(), kminusA.Eta()); + const double dR_k2p_k2m = deltaR(kplusB.Phi(), kplusB.Eta(), kminusB.Phi(), kminusB.Eta()); + + double minDR = dRkplus; + minDR = std::min(minDR, dRkminus); + minDR = std::min(minDR, dR_k1p_k1m); + minDR = std::min(minDR, dR_k1p_k2m); + minDR = std::min(minDR, dR_k2p_k1m); + minDR = std::min(minDR, dR_k2p_k2m); + return minDR; + }; + + // --- collect candidates once --- + std::vector pairV, phi1V, phi2V; + std::vector minDRV; // store minimum ΔR for each pair + + // optional: swapped-cross-mass veto window (minimal new knobs) + const double crossPhiLow = 1.01; // or a dedicated config + const double crossPhiHigh = 1.03; // or a dedicated config + + for (auto const& t1 : phitracks) { + const double kplus1pt = std::hypot(t1.phid1Px(), t1.phid1Py()); + const double kminus1pt = std::hypot(t1.phid2Px(), t1.phid2Py()); + + if (kplus1pt > maxKaonPt || kminus1pt > maxKaonPt) + continue; + if (!selectionPID(t1.phid1TPC(), t1.phid1TOF(), t1.phid1TOFHit(), strategyPID1, kplus1pt)) + continue; + if (!selectionPID(t1.phid2TPC(), t1.phid2TOF(), t1.phid2TOFHit(), strategyPID2, kminus1pt)) + continue; + + TLorentzVector phi1, k1p, k1m; + phi1.SetXYZM(t1.phiPx(), t1.phiPy(), t1.phiPz(), t1.phiMass()); + k1p.SetXYZM(t1.phid1Px(), t1.phid1Py(), t1.phid1Pz(), mKPDG); + k1m.SetXYZM(t1.phid2Px(), t1.phid2Py(), t1.phid2Pz(), mKPDG); + + // φ1 mass window + φ1 pT + if (t1.phiMass() < minPhiMass1 || t1.phiMass() > maxPhiMass1) + continue; + if (phi1.Pt() < minPhiPt || phi1.Pt() > maxPhiPt) + continue; + + const auto id1 = t1.index(); + + for (auto const& t2 : phitracks) { + const auto id2 = t2.index(); + if (id2 <= id1) + continue; + + const double kplus2pt = std::hypot(t2.phid1Px(), t2.phid1Py()); + const double kminus2pt = std::hypot(t2.phid2Px(), t2.phid2Py()); + if (kplus2pt > maxKaonPt || kminus2pt > maxKaonPt) + continue; + if (!selectionPID(t2.phid1TPC(), t2.phid1TOF(), t2.phid1TOFHit(), strategyPID1, kplus2pt)) + continue; + if (!selectionPID(t2.phid2TPC(), t2.phid2TOF(), t2.phid2TOFHit(), strategyPID2, kminus2pt)) + continue; + + // FIX + robust: block ANY shared daughter (4-way) + if (t1.phid1Index() == t2.phid1Index() || t1.phid1Index() == t2.phid2Index() || + t1.phid2Index() == t2.phid1Index() || t1.phid2Index() == t2.phid2Index()) + continue; + + TLorentzVector phi2, k2p, k2m; + phi2.SetXYZM(t2.phiPx(), t2.phiPy(), t2.phiPz(), t2.phiMass()); + k2p.SetXYZM(t2.phid1Px(), t2.phid1Py(), t2.phid1Pz(), mKPDG); + k2m.SetXYZM(t2.phid2Px(), t2.phid2Py(), t2.phid2Pz(), mKPDG); + + // φ2 mass window + FIX: apply pT cut to phi2 (not phi1) + if (t2.phiMass() < minPhiMass2 || t2.phiMass() > maxPhiMass2) + continue; + if (phi2.Pt() < minPhiPt || phi2.Pt() > maxPhiPt) + continue; + + // NEW: cross (swapped) K+K- mass veto + // veto if either cross-pair lands in φ window (tune to be looser/tighter) + const double mCross12 = (k1p + k2m).M(); // K+1 + K-2 + const double mCross21 = (k2p + k1m).M(); // K+2 + K-1 + if ((mCross12 > crossPhiLow && mCross12 < crossPhiHigh) || + (mCross21 > crossPhiLow && mCross21 < crossPhiHigh)) { + continue; + } + + // Δm cut (configurable) + const double dM = deltaMPhi(phi1.M(), phi2.M()); + if (dM > maxDeltaMPhi) + continue; + + TLorentzVector pair = phi1 + phi2; + if (pair.M() < minExoticMass || pair.M() > maxExoticMass) + continue; + + histos.fill(HIST("hPhiMass"), phi1.M(), phi2.M(), pair.Pt()); + + // daughter ΔR QA and minΔR (NO CUT) + ROOT::Math::PtEtaPhiMVector k1pV(k1p.Pt(), k1p.Eta(), k1p.Phi(), mKPDG); + ROOT::Math::PtEtaPhiMVector k1mV(k1m.Pt(), k1m.Eta(), k1m.Phi(), mKPDG); + ROOT::Math::PtEtaPhiMVector k2pV(k2p.Pt(), k2p.Eta(), k2p.Phi(), mKPDG); + ROOT::Math::PtEtaPhiMVector k2mV(k2m.Pt(), k2m.Eta(), k2m.Phi(), mKPDG); + const double minDR = minKaonDeltaR(k1pV, k2pV, k1mV, k2mV); + + // store for one-pass fill + pairV.emplace_back(pair.Pt(), pair.Eta(), pair.Phi(), pair.M()); + phi1V.emplace_back(phi1.Pt(), phi1.Eta(), phi1.Phi(), phi1.M()); + phi2V.emplace_back(phi2.Pt(), phi2.Eta(), phi2.Phi(), phi2.M()); + minDRV.emplace_back(minDR); + } + } + + if (pairV.empty()) + return; + + // --- fill the single THnSparse --- + for (size_t i = 0; i < pairV.size(); ++i) { + TLorentzVector p1, p2, pair; + p1.SetPtEtaPhiM(phi1V[i].Pt(), phi1V[i].Eta(), phi1V[i].Phi(), phi1V[i].M()); + p2.SetPtEtaPhiM(phi2V[i].Pt(), phi2V[i].Eta(), phi2V[i].Phi(), phi2V[i].M()); + pair.SetPtEtaPhiM(pairV[i].Pt(), pairV[i].Eta(), pairV[i].Phi(), pairV[i].M()); + + const double dM = deltaMPhi(p1.M(), p2.M()); + const double M = pair.M(); + const double dR = deltaR(p1.Phi(), p1.Eta(), p2.Phi(), p2.Eta()); + const double minDR = minDRV[i]; + + // (optional but recommended) protect ptcorr from blow-ups + const double denom = (pair.Pt() - p1.Pt()); + if (std::abs(denom) < 1e-9) + continue; + const double ptcorr = p1.Pt() / denom; + + histos.fill(HIST("hPtCorrelation"), pair.Pt(), ptcorr); + + // NOTE: second axis is minΔR(all kaons), ΔpT/pT has been removed + histos.fill(HIST("SEMassUnlike"), + M, + minDR, + pair.Pt(), + dR, + dM, + ptcorr); + + // --- NEW: compute z and A from phi candidates (no cuts) --- + const double pt1 = p1.Pt(); + const double pt2 = p2.Pt(); + const double ptsum = pt1 + pt2; + if (ptsum <= 0.0) + continue; + const double z = pt1 / ptsum; + const double A = std::abs(pt1 - pt2) / ptsum; + // --- Fill NEW THnSparse (no cuts) --- + histos.fill(HIST("SEMassUnlike_DeltaRZA"), M, pair.Pt(), pair.Pt() * dR, z, A, dM); + } + } + PROCESS_SWITCH(doublephimeson, processopti4, "Process Optimized same event", true); + SliceCache cache; using BinningTypeVertexContributor = ColumnBinningPolicy; @@ -1103,6 +1329,17 @@ struct doublephimeson { dR, // ΔR(phi1, phi2) dM, // Δm(phi) ptcorr); // pT correlation + + // --- NEW: compute z and A from phi candidates (no cuts) --- + const double pt1 = phi1.Pt(); + const double pt2 = phi2.Pt(); + const double ptsum = pt1 + pt2; + if (ptsum <= 0.0) + continue; + const double z = pt1 / ptsum; + const double A = std::abs(pt1 - pt2) / ptsum; + // --- Fill NEW THnSparse (no cuts) --- + histos.fill(HIST("MEMassUnlike_DeltaRZA"), pair.M(), pair.Pt(), pair.Pt() * dR, z, A, dM); } } } diff --git a/PWGLF/Tasks/Resonances/f0980analysis.cxx b/PWGLF/Tasks/Resonances/f0980analysis.cxx index c8d1873eb22..81446f9937a 100644 --- a/PWGLF/Tasks/Resonances/f0980analysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980analysis.cxx @@ -15,23 +15,26 @@ /// \since 01/07/2024 #include "PWGLF/DataModel/LFResonanceTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "CommonConstants/MathConstants.h" #include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPObject.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include #include "Math/LorentzVector.h" #include "Math/Vector4D.h" #include "TVector2.h" +#include #include using namespace o2; @@ -45,25 +48,21 @@ struct f0980analysis { SliceCache cache; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + using ResoMCCols = o2::soa::Join; + using ResoMCColsEP = o2::soa::Join; + // Event selections 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.5, "Maximum transverse DCA"}; - Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, "Maximum longitudinal DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 0.2, "Maximum longitudinal DCA"}; Configurable cfgMinRap{"cfgMinRap", -0.5, "Minimum rapidity for pair"}; Configurable cfgMaxRap{"cfgMaxRap", 0.5, "Maximum rapidity for pair"}; // Track selections - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", false, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | - // kTPCNCls | kTPCCrossedRows | - // kTPCCrossedRowsOverNCls | - // kTPCChi2NDF | kTPCRefit | - // kITSNCls | kITSChi2NDF | - // kITSRefit | kITSHits) | - // kInAcceptanceTracks (kPtRange | - // kEtaRange) + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", false, "Primary track selection"}; + Configurable cfgGlobalTrack{"cfgGlobalTrack", true, "Global track selection"}; + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", false, "Global track selection without DCA"}; Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; @@ -75,7 +74,7 @@ struct f0980analysis { Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; Configurable cMaxTPCnSigmaPionWoTOF{"cMaxTPCnSigmaPionWoTOF", 2.0, "TPC nSigma cut without TOF for Pion"}; Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; - Configurable selectType{"selectType", 0, "PID selection type"}; + Configurable selectType{"selectType", 3, "PID selection type"}; // Axis ConfigurableAxis massAxis{"massAxis", {400, 0.2, 2.2}, "Invariant mass axis"}; @@ -84,10 +83,19 @@ struct f0980analysis { Configurable cfgFindRT{"cfgFindRT", false, "boolean for RT analysis"}; Configurable cfgFindEP{"cfgFindEP", false, "boolean for Event plane analysis"}; + + Configurable cRecoINELgt0{"cRecoINELgt0", true, "check if INEL>0 for reco events"}; + Configurable cfgQAEPLT{"cfgQAEPLT", false, "Fill QA histograms for Event Plane and Leading Track"}; + Configurable cfgQACutflow{"cfgQACutflow", true, "Fill cutflow QA histograms"}; + Configurable cfgQAPairQA{"cfgQAPairQA", true, "Fill pair-level QA histograms"}; + Configurable cfgQATrackStages{"cfgQATrackStages", true, "Fill track QA at each stage"}; Configurable cfgQASelection{"cfgQASelection", true, "Fill QA histograms for Selection"}; Configurable cfgQAMCTrue{"cfgQAMCTrue", false, "Fill QA histograms for MC True Selection"}; + // MC event selection + Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; + void init(o2::framework::InitContext&) { std::vector lptBinning = {0, 5.0, 13.0, 20.0, 50.0, 1000.0}; @@ -105,8 +113,12 @@ struct f0980analysis { AxisSpec rapqaAxis = {60, -1.5, 1.5, "#it{y}"}; // Rapidity axis AxisSpec dcaxyAxis = {200, -5.0, 5.0, "DCA_{xy} (cm)"}; // DCAxy axis AxisSpec dcazAxis = {200, -5.0, 5.0, "DCA_{z} (cm)"}; // DCAz axis + AxisSpec invMass1DAxis = {400, 0.2, 2.2, "M_{#pi#pi} (GeV/#it{c}^{2})"}; - AxisSpec collCutAxis = {4, -0.5, 3.5, "Collision cut index for MC"}; + AxisSpec evtCutflowAxis = {5, -1.5, 3.5, "Event cutflow step"}; + AxisSpec trkCutflowAxis = {8, -0.5, 7.5, "Track cutflow step"}; + AxisSpec pairRapAxis = {80, -2.0, 2.0, "y_{#pi#pi}"}; + AxisSpec mcSelAxis = {5, -1.5, 3.5, "MC event selection step"}; if (cfgFindRT) { histos.add("hInvMass_f0980_US_RT", "unlike invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, rtAxis, lptAxis}}); @@ -132,33 +144,56 @@ struct f0980analysis { histos.add("QA/LTpt", "", {HistType::kTH3F, {pTqaAxis, centAxis, phiqaAxis}}); } if (cfgQASelection) { - // General QA - histos.add("QA/TrackPt", "", {HistType::kTH1F, {pTqaAxis}}); - histos.add("QA/TrackEta", "", {HistType::kTH1F, {etaqaAxis}}); - histos.add("QA/TrackPhi", "", {HistType::kTH1F, {phiqaAxis}}); + // Event QA + histos.add("QAevent/hMultiplicityPercentSameE", "Multiplicity percentile of collision", HistType::kTH1F, {centAxis}); + // General track QA + if (cfgQACutflow) { + histos.add("QAtrack/hTrackCutflow", "Track cutflow; step; counts", HistType::kTH1F, {trkCutflowAxis}); + } + if (cfgQATrackStages) { + // stage: 0=input(initializer tracks), 1=base(kin/quality), 2=type(global/primary), 3=DCA, 4=PID(final pion candidates) + histos.add("QAtrack/stage/hPt_stage", "track pT vs stage; pT; stage", {HistType::kTH2F, {pTqaAxis, trkCutflowAxis}}); + histos.add("QAtrack/stage/hEta_stage", "track eta vs stage; eta; stage", {HistType::kTH2F, {etaqaAxis, trkCutflowAxis}}); + histos.add("QAtrack/stage/hPhi_stage", "track phi vs stage; phi; stage", {HistType::kTH2F, {phiqaAxis, trkCutflowAxis}}); + } + histos.add("QAtrack/TrackPt", "", {HistType::kTH1F, {pTqaAxis}}); + histos.add("QAtrack/TrackEta", "", {HistType::kTH1F, {etaqaAxis}}); + histos.add("QAtrack/TrackPhi", "", {HistType::kTH1F, {phiqaAxis}}); // Track selection QA - histos.add("QA/trkDCAxy_BC", "DCA_{xy} for pion tracks (before cuts)", HistType::kTH2F, {pTqaAxis, dcaxyAxis}); - histos.add("QA/trkDCAz_BC", "DCA_{z} for pion tracks (before cuts)", HistType::kTH2F, {pTqaAxis, dcazAxis}); - histos.add("QA/trkDCAxy", "DCA_{xy} for pion tracks (after cuts)", HistType::kTH2F, {pTqaAxis, dcaxyAxis}); - histos.add("QA/trkDCAz", "DCA_{z} for pion tracks (after cuts)", HistType::kTH2F, {pTqaAxis, dcazAxis}); + histos.add("QAtrack/trkDCAxy_BC", "DCA_{xy} for pion tracks (before cuts)", HistType::kTH2F, {pTqaAxis, dcaxyAxis}); + histos.add("QAtrack/trkDCAz_BC", "DCA_{z} for pion tracks (before cuts)", HistType::kTH2F, {pTqaAxis, dcazAxis}); + histos.add("QAtrack/trkDCAxy", "DCA_{xy} for pion tracks (after cuts)", HistType::kTH2F, {pTqaAxis, dcaxyAxis}); + histos.add("QAtrack/trkDCAz", "DCA_{z} for pion tracks (after cuts)", HistType::kTH2F, {pTqaAxis, dcazAxis}); // PID QA - histos.add("QA/Nsigma_TPC_BC", "TPC n#sigma^{#pi} (before PID cuts); p_{T} (GeV/c); n#sigma_{TPC}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); - histos.add("QA/Nsigma_TOF_BC", "TOF n#sigma^{#pi} (before PID cuts); p_{T} (GeV/c); n#sigma_{TOF}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); - histos.add("QA/Nsigma_TPC_TOF_BC", "", {HistType::kTH2F, {pidqaAxis, pidqaAxis}}); - histos.add("QA/Nsigma_TPC", "TPC n#sigma^{#pi} (after PID cuts); p_{T} (GeV/c); n#sigma_{TPC}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); - histos.add("QA/Nsigma_TOF", "TOF n#sigma^{#pi} (after PID cuts); p_{T} (GeV/c); n#sigma_{TOF}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); - histos.add("QA/Nsigma_TPC_TOF", "", {HistType::kTH2F, {pidqaAxis, pidqaAxis}}); + histos.add("QApid/Nsigma_TPC_BC", "TPC n#sigma^{#pi} (before PID cuts); p_{T} (GeV/c); n#sigma_{TPC}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); + histos.add("QApid/Nsigma_TOF_BC", "TOF n#sigma^{#pi} (before PID cuts); p_{T} (GeV/c); n#sigma_{TOF}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); + histos.add("QApid/Nsigma_TPC_TOF_BC", "", {HistType::kTH2F, {pidqaAxis, pidqaAxis}}); + histos.add("QApid/Nsigma_TPC", "TPC n#sigma^{#pi} (after PID cuts); p_{T} (GeV/c); n#sigma_{TPC}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); + histos.add("QApid/Nsigma_TOF", "TOF n#sigma^{#pi} (after PID cuts); p_{T} (GeV/c); n#sigma_{TOF}^{#pi}", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); + histos.add("QApid/Nsigma_TPC_TOF", "", {HistType::kTH2F, {pidqaAxis, pidqaAxis}}); + if (cfgQAPairQA) { + histos.add("QApair/hYpipi_BC", "y_{#pi#pi} (before y cut); y; counts", HistType::kTH1F, {pairRapAxis}); + histos.add("QApair/hYpipi_AC", "y_{#pi#pi} (after y cut); y; counts", HistType::kTH1F, {pairRapAxis}); + // low-dimensional mass QA (for quick visual sanity) + histos.add("QApair/hMass_US", "M_{#pi#pi} US; M; counts", HistType::kTH1F, {invMass1DAxis}); + histos.add("QApair/hMass_LSpp", "M_{#pi#pi} ++; M; counts", HistType::kTH1F, {invMass1DAxis}); + histos.add("QApair/hMass_LSmm", "M_{#pi#pi} --; M; counts", HistType::kTH1F, {invMass1DAxis}); + } } if (doprocessMCRec) { - histos.add("MCL/hpT_f0980_REC", "Reconstructed f0 signals", HistType::kTH3F, {massAxis, pTqaAxis, centAxis}); + histos.add("MCL/hMass_f0980_REC", "M_{REC} f0", HistType::kTH3F, {massAxis, pTqaAxis, centAxis}); + histos.add("MCL/hpT_f0980_REC", "REC truth-matched f0; p_{T}; Centrality (%)", HistType::kTH2F, {pTqaAxis, centAxis}); + histos.add("MCL/hpT_f0980_REC_truePt", "REC truth-matched f0; p_{T}^{true mother}; Centrality (%)", HistType::kTH2F, {pTqaAxis, centAxis}); } if (doprocessMCTrue) { - // histos.add("MCL/hpT_f0980_GEN", "Generated f0 signals", HistType::kTH2F, {pTqaAxis, centAxis}); - histos.add("MCL/hpT_f0980_GEN", "Generated f0 signals; selIdx; p_{T} (GeV/c); Centrality (%)", HistType::kTH3F, {collCutAxis, pTqaAxis, centAxis}); + // histos.add("MCL/hpT_f0980_GEN", "GEN f0; p_{T} (GeV/c); Centrality (%)", HistType::kTH2F, {pTqaAxis, centAxis}); + histos.add("MCL/hpT_f0980_GEN", "GEN f0; step; p_{T} (GeV/c); centFT0M (%)", HistType::kTH3F, {mcSelAxis, pTqaAxis, centAxis}); if (cfgQAMCTrue) { histos.add("QAMCTrue/f0_pt_y", "Generated f0 ; #it{p}_{T} (GeV/#it{c}) ; #it{y}", HistType::kTH2F, {pTqaAxis, rapqaAxis}); histos.add("QAMCTrue/f0_pt_cent", "Generated f0 ; #it{p}_{T} (GeV/#it{c}); Centrality (%)", HistType::kTH2F, {pTqaAxis, centAxis}); + histos.add("QAMCTrue/f0YieldSteps", "MC true f0 counts per event-selection; step; counts", HistType::kTH1F, {evtCutflowAxis}); + // histos.add("QAMCTrue/trueINELgt0", "MC true INEL>0 flag; flag; counts", HistType::kTH1F, {inelAxis}); } } histos.print(); @@ -185,29 +220,56 @@ struct f0980analysis { } template - bool selTrack(const TrackType track) + bool selTrackBase(const TrackType& track) { if (std::abs(track.pt()) < cfgMinpT) return false; if (std::fabs(track.eta()) > cfgMaxEta) return false; - if (std::abs(track.dcaXY()) > cfgMaxDCArToPVcut) + if (track.tpcNClsFound() < cfgTPCcluster) return false; - if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) + if (cfgPVContributor && !track.isPVContributor()) return false; - if (track.tpcNClsFound() < cfgTPCcluster) + if (cfgUseITSRefit && !track.passedITSRefit()) + return false; + if (cfgUseTPCRefit && !track.passedTPCRefit()) return false; + + return true; + } + + template + bool selTrackType(const TrackType& track) + { if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; if (cfgGlobalTrack && !track.isGlobalTrack()) return false; if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cfgPVContributor && !track.isPVContributor()) + + return true; + } + + template + bool selTrackDCA(const TrackType& track) + { + if (std::abs(track.dcaXY()) > cfgMaxDCArToPVcut) return false; - if (cfgUseITSRefit && !track.passedITSRefit()) + if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) return false; - if (cfgUseTPCRefit && !track.passedTPCRefit()) + + return true; + } + + template + bool selTrack(const TrackType& track) + { + if (!selTrackBase(track)) + return false; + if (!selTrackType(track)) + return false; + if (!selTrackDCA(track)) return false; if (cfgHasTOF && !track.hasTOF()) return false; @@ -245,8 +307,14 @@ struct f0980analysis { } template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks) + void fillHistograms(const CollisionType& collision, const TracksType& dTracks, + aod::McParticles const* mcParticles = nullptr, + float centOverride = NAN) { + const float cent = std::isfinite(centOverride) ? centOverride : collision.cent(); + if (cfgQASelection) { + histos.fill(HIST("QAevent/hMultiplicityPercentSameE"), cent); + } double lhpT = 0.; double lhphi = 0.; double relphi = 0.; @@ -258,53 +326,115 @@ struct f0980analysis { } } if (cfgQAEPLT) - histos.fill(HIST("QA/LTpt"), lhpT, collision.cent(), lhphi); + histos.fill(HIST("QA/LTpt"), lhpT, cent, lhphi); } else if (cfgFindEP) { if (cfgQAEPLT) { - histos.fill(HIST("QA/EPhist"), collision.cent(), collision.evtPl()); - histos.fill(HIST("QA/hEPResAB"), collision.cent(), collision.evtPlResAB()); - histos.fill(HIST("QA/hEPResBC"), collision.cent(), collision.evtPlResBC()); - histos.fill(HIST("QA/hEPResAC"), collision.cent(), collision.evtPlResAC()); + histos.fill(HIST("QA/EPhist"), cent, collision.evtPl()); + histos.fill(HIST("QA/hEPResAB"), cent, collision.evtPlResAB()); + histos.fill(HIST("QA/hEPResBC"), cent, collision.evtPlResBC()); + histos.fill(HIST("QA/hEPResAC"), cent, collision.evtPlResAC()); } } ROOT::Math::LorentzVector> pion1, pion2, reco; - for (const auto& [trk1, trk2] : combinations(CombinationsStrictlyUpperIndexPolicy(dTracks, dTracks))) { - if (cfgQASelection) { - histos.fill(HIST("QA/trkDCAxy_BC"), trk1.pt(), trk1.dcaXY()); - histos.fill(HIST("QA/trkDCAz_BC"), trk1.pt(), trk1.dcaZ()); + // Single-track QA + if (cfgQASelection) { + for (const auto& trk : dTracks) { + if (cfgQACutflow) { + histos.fill(HIST("QAtrack/hTrackCutflow"), 0); // all tracks (initializer track) + } + if (cfgQATrackStages) { + histos.fill(HIST("QAtrack/stage/hPt_stage"), trk.pt(), 0); + histos.fill(HIST("QAtrack/stage/hEta_stage"), trk.eta(), 0); + histos.fill(HIST("QAtrack/stage/hPhi_stage"), trk.phi(), 0); + } + histos.fill(HIST("QAtrack/trkDCAxy_BC"), trk.pt(), trk.dcaXY()); + histos.fill(HIST("QAtrack/trkDCAz_BC"), trk.pt(), trk.dcaZ()); + + if (!selTrackBase(trk)) { + continue; + } + if (cfgQACutflow) { + histos.fill(HIST("QAtrack/hTrackCutflow"), 1); // after kinematics cut + } + if (cfgQATrackStages) { + histos.fill(HIST("QAtrack/stage/hPt_stage"), trk.pt(), 1); + histos.fill(HIST("QAtrack/stage/hEta_stage"), trk.eta(), 1); + histos.fill(HIST("QAtrack/stage/hPhi_stage"), trk.phi(), 1); + } + histos.fill(HIST("QApid/Nsigma_TPC_BC"), trk.pt(), trk.tpcNSigmaPi()); + if (trk.hasTOF()) { + histos.fill(HIST("QApid/Nsigma_TOF_BC"), trk.pt(), trk.tofNSigmaPi()); + histos.fill(HIST("QApid/Nsigma_TPC_TOF_BC"), trk.tpcNSigmaPi(), trk.tofNSigmaPi()); + } + + if (!selTrackType(trk)) { + continue; + } + if (cfgQACutflow) { + histos.fill(HIST("QAtrack/hTrackCutflow"), 2); // after track type + } + if (cfgQATrackStages) { + histos.fill(HIST("QAtrack/stage/hPt_stage"), trk.pt(), 2); + histos.fill(HIST("QAtrack/stage/hEta_stage"), trk.eta(), 2); + histos.fill(HIST("QAtrack/stage/hPhi_stage"), trk.phi(), 2); + } + + if (!selTrackDCA(trk)) { + continue; + } + histos.fill(HIST("QAtrack/trkDCAxy"), trk.pt(), trk.dcaXY()); + histos.fill(HIST("QAtrack/trkDCAz"), trk.pt(), trk.dcaZ()); + if (cfgQACutflow) { + histos.fill(HIST("QAtrack/hTrackCutflow"), 3); // after DCA + } + if (cfgQATrackStages) { + histos.fill(HIST("QAtrack/stage/hPt_stage"), trk.pt(), 3); + histos.fill(HIST("QAtrack/stage/hEta_stage"), trk.eta(), 3); + histos.fill(HIST("QAtrack/stage/hPhi_stage"), trk.phi(), 3); + } + + if (!selPion(trk)) { + continue; + } + if (cfgQACutflow) { + histos.fill(HIST("QAtrack/hTrackCutflow"), 4); // after PID for pion selection + } + if (cfgQATrackStages) { + histos.fill(HIST("QAtrack/stage/hPt_stage"), trk.pt(), 4); + histos.fill(HIST("QAtrack/stage/hEta_stage"), trk.eta(), 4); + histos.fill(HIST("QAtrack/stage/hPhi_stage"), trk.phi(), 4); + } + histos.fill(HIST("QApid/Nsigma_TPC"), trk.pt(), trk.tpcNSigmaPi()); + if (trk.hasTOF()) { + histos.fill(HIST("QApid/Nsigma_TOF"), trk.pt(), trk.tofNSigmaPi()); + histos.fill(HIST("QApid/Nsigma_TPC_TOF"), trk.tpcNSigmaPi(), trk.tofNSigmaPi()); + } + + histos.fill(HIST("QAtrack/TrackPt"), trk.pt()); + histos.fill(HIST("QAtrack/TrackEta"), trk.eta()); + histos.fill(HIST("QAtrack/TrackPhi"), trk.phi()); } + } + + for (const auto& [trk1, trk2] : combinations(CombinationsStrictlyUpperIndexPolicy(dTracks, dTracks))) { if (!selTrack(trk1) || !selTrack(trk2)) continue; - if (cfgQASelection) { - histos.fill(HIST("QA/trkDCAxy"), trk1.pt(), trk1.dcaXY()); - histos.fill(HIST("QA/trkDCAz"), trk1.pt(), trk1.dcaZ()); - - histos.fill(HIST("QA/Nsigma_TPC_BC"), trk1.pt(), trk1.tpcNSigmaPi()); - if (trk1.hasTOF()) { - histos.fill(HIST("QA/Nsigma_TOF_BC"), trk1.pt(), trk1.tofNSigmaPi()); - histos.fill(HIST("QA/Nsigma_TPC_TOF_BC"), trk1.tpcNSigmaPi(), trk1.tofNSigmaPi()); - } - } if (!selPion(trk1) || !selPion(trk2)) continue; - if (cfgQASelection) { - histos.fill(HIST("QA/Nsigma_TPC"), trk1.pt(), trk1.tpcNSigmaPi()); - if (trk1.hasTOF()) { - histos.fill(HIST("QA/Nsigma_TOF"), trk1.pt(), trk1.tofNSigmaPi()); - histos.fill(HIST("QA/Nsigma_TPC_TOF"), trk1.tpcNSigmaPi(), trk1.tofNSigmaPi()); - } - - histos.fill(HIST("QA/TrackPt"), trk1.pt()); - histos.fill(HIST("QA/TrackEta"), trk1.eta()); - histos.fill(HIST("QA/TrackPhi"), trk1.phi()); - } pion1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); pion2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); reco = pion1 + pion2; + if (cfgQASelection && cfgQAPairQA) { + histos.fill(HIST("QApair/hYpipi_BC"), reco.Rapidity()); + } + if (reco.Rapidity() > cfgMaxRap || reco.Rapidity() < cfgMinRap) continue; + if (cfgQASelection && cfgQAPairQA) { + histos.fill(HIST("QApair/hYpipi_AC"), reco.Rapidity()); + } if (cfgFindEP) { relphi = TVector2::Phi_0_2pi(reco.Phi() - collision.evtPl()); @@ -314,60 +444,119 @@ struct f0980analysis { } if (trk1.sign() * trk2.sign() < 0) { + if (cfgQASelection && cfgQAPairQA) { + histos.fill(HIST("QApair/hMass_US"), reco.M()); + } if (cfgFindRT) { - histos.fill(HIST("hInvMass_f0980_US_RT"), reco.M(), reco.Pt(), collision.cent(), rtIndex(reco.Phi(), lhphi), lhpT); + histos.fill(HIST("hInvMass_f0980_US_RT"), reco.M(), reco.Pt(), cent, rtIndex(reco.Phi(), lhphi), lhpT); } else if (cfgFindEP) { - histos.fill(HIST("hInvMass_f0980_US_EPA"), reco.M(), reco.Pt(), collision.cent(), relphi); + histos.fill(HIST("hInvMass_f0980_US_EPA"), reco.M(), reco.Pt(), cent, relphi); } else { - histos.fill(HIST("hInvMass_f0980_US"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_f0980_US"), reco.M(), reco.Pt(), cent); } if constexpr (IsMC) { + // truth-matched f0 -> pi+pi- (signal-only REC) if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kPiPlus) continue; if (trk1.motherId() != trk2.motherId()) continue; if (std::abs(trk1.motherPDG()) != 9010221) continue; - histos.fill(HIST("MCL/hpT_f0980_REC"), reco.M(), reco.Pt(), collision.cent()); + + histos.fill(HIST("MCL/hMass_f0980_REC"), reco.M(), reco.Pt(), cent); + histos.fill(HIST("MCL/hpT_f0980_REC"), reco.Pt(), cent); + if (mcParticles && trk1.motherId() >= 0) { + auto mother = mcParticles->iteratorAt(trk1.motherId()); + histos.fill(HIST("MCL/hpT_f0980_REC_truePt"), mother.pt(), cent); + } } } else if (trk1.sign() > 0 && trk2.sign() > 0) { + if (cfgQASelection && cfgQAPairQA) { + histos.fill(HIST("QApair/hMass_LSpp"), reco.M()); + } if (cfgFindRT) { - histos.fill(HIST("hInvMass_f0980_LSpp_RT"), reco.M(), reco.Pt(), collision.cent(), rtIndex(reco.Phi(), lhphi), lhpT); + histos.fill(HIST("hInvMass_f0980_LSpp_RT"), reco.M(), reco.Pt(), cent, rtIndex(reco.Phi(), lhphi), lhpT); } else if (cfgFindEP) { - histos.fill(HIST("hInvMass_f0980_LSpp_EPA"), reco.M(), reco.Pt(), collision.cent(), relphi); + histos.fill(HIST("hInvMass_f0980_LSpp_EPA"), reco.M(), reco.Pt(), cent, relphi); } else { - histos.fill(HIST("hInvMass_f0980_LSpp"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_f0980_LSpp"), reco.M(), reco.Pt(), cent); } } else if (trk1.sign() < 0 && trk2.sign() < 0) { + if (cfgQASelection && cfgQAPairQA) { + histos.fill(HIST("QApair/hMass_LSmm"), reco.M()); + } if (cfgFindRT) { - histos.fill(HIST("hInvMass_f0980_LSmm_RT"), reco.M(), reco.Pt(), collision.cent(), rtIndex(reco.Phi(), lhphi), lhpT); + histos.fill(HIST("hInvMass_f0980_LSmm_RT"), reco.M(), reco.Pt(), cent, rtIndex(reco.Phi(), lhphi), lhpT); } else if (cfgFindEP) { - histos.fill(HIST("hInvMass_f0980_LSmm_EPA"), reco.M(), reco.Pt(), collision.cent(), relphi); + histos.fill(HIST("hInvMass_f0980_LSmm_EPA"), reco.M(), reco.Pt(), cent, relphi); } else { - histos.fill(HIST("hInvMass_f0980_LSmm"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_f0980_LSmm"), reco.M(), reco.Pt(), cent); } } } } - void processData(o2::soa::Join::iterator const& collision, + void processData(o2::soa::Join::iterator const& resoCollision, + o2::aod::ResoCollisionColls const& collisionIndex, + o2::soa::Join const& collisions, o2::aod::ResoTracks const& resotracks) { - fillHistograms(collision, resotracks); + if (cRecoINELgt0) { + auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); + auto collId = linkRow.collisionId(); + if (collId < 0) + return; + auto coll = collisions.iteratorAt(collId); + if (!coll.isInelGt0()) + return; + } + fillHistograms(resoCollision, resotracks); } PROCESS_SWITCH(f0980analysis, processData, "Process Event for data", true); - void processMCRec(o2::soa::Join::iterator const& collision, - o2::soa::Join const& resotracks) + void processMCRec(ResoMCColsEP::iterator const& collision, + o2::aod::ResoCollisionColls const& collisionIndex, + o2::soa::Join const& collisionsMC, + o2::soa::Join const& resotracks, + o2::aod::McParticles const& mcParticles, + o2::soa::Join const&) { - fillHistograms(collision, resotracks); + auto linkRow = collisionIndex.iteratorAt(collision.globalIndex()); + auto collId = linkRow.collisionId(); + if (collId < 0) { + return; + } + auto coll = collisionsMC.iteratorAt(collId); + if (cRecoINELgt0 && !coll.isInelGt0()) + return; + auto mcColl = coll.mcCollision_as>(); + const float centFT0M = mcColl.centFT0M(); + if (!collision.isInAfterAllCuts() || (std::abs(collision.posZ()) > cZvertCutMC)) { + return; + } + + fillHistograms(collision, resotracks, &mcParticles, centFT0M); } - PROCESS_SWITCH(f0980analysis, processMCRec, "Process Event for MC", false); + PROCESS_SWITCH(f0980analysis, processMCRec, "Process Event for MC (REC)", false); - void processMCTrue(o2::soa::Join::iterator const& resoCollision, - o2::aod::ResoMCParents const& resoParents) + void processMCTrue(ResoMCCols::iterator const& resoCollision, + o2::aod::ResoCollisionColls const& collisionIndex, + o2::aod::ResoMCParents const& resoParents, + o2::aod::ResoCollisionCandidatesMC const& collisionsMC, + o2::soa::Join const&) { + auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); + auto collId = linkRow.collisionId(); + if (collId < 0) { + return; + } + auto coll = collisionsMC.iteratorAt(collId); + if (cRecoINELgt0 && !coll.isInelGt0()) + return; + auto mcColl = coll.mcCollision_as>(); + const float centFT0M = mcColl.centFT0M(); + for (const auto& part : resoParents) { // loop over all pre-filtered MC particles if (std::abs(part.pdgCode()) != 9010221) continue; @@ -376,29 +565,36 @@ struct f0980analysis { if (part.y() < cfgMinRap || part.y() > cfgMaxRap) { continue; } - bool pass = false; - if ((std::abs(part.daughterPDG1()) == kPiPlus && std::abs(part.daughterPDG2()) == kPiPlus)) { - pass = true; - } - if (!pass) // If we have both decay products + const bool decayPions = (std::abs(part.daughterPDG1()) == kPiPlus && std::abs(part.daughterPDG2()) == kPiPlus); + if (!decayPions) continue; - // no event selection - histos.fill(HIST("MCL/hpT_f0980_GEN"), 0, part.pt(), resoCollision.cent()); - // |zvtx|<10 cm + // no event selection: baseline + histos.fill(HIST("MCL/hpT_f0980_GEN"), -1, part.pt(), centFT0M); + histos.fill(HIST("QAMCTrue/f0YieldSteps"), -1); + // |zvtx|<10 if (resoCollision.isVtxIn10()) { - histos.fill(HIST("MCL/hpT_f0980_GEN"), 1, part.pt(), resoCollision.cent()); + histos.fill(HIST("MCL/hpT_f0980_GEN"), 0, part.pt(), centFT0M); + histos.fill(HIST("QAMCTrue/f0YieldSteps"), 0); + } + // |zvtx|<10 && sel8 + if (resoCollision.isVtxIn10() && resoCollision.isInSel8()) { + histos.fill(HIST("MCL/hpT_f0980_GEN"), 1, part.pt(), centFT0M); + histos.fill(HIST("QAMCTrue/f0YieldSteps"), 1); } - // |zvtx|<10 cm & TVX trigger + // |zvtx|<10 && TVX if (resoCollision.isVtxIn10() && resoCollision.isTriggerTVX()) { - histos.fill(HIST("MCL/hpT_f0980_GEN"), 2, part.pt(), resoCollision.cent()); + histos.fill(HIST("MCL/hpT_f0980_GEN"), 2, part.pt(), centFT0M); + histos.fill(HIST("QAMCTrue/f0YieldSteps"), 2); } + // after all event cuts if (resoCollision.isInAfterAllCuts()) { - histos.fill(HIST("MCL/hpT_f0980_GEN"), 3, part.pt(), resoCollision.cent()); + histos.fill(HIST("MCL/hpT_f0980_GEN"), 3, part.pt(), centFT0M); + histos.fill(HIST("QAMCTrue/f0YieldSteps"), 3); } if (cfgQAMCTrue) { histos.fill(HIST("QAMCTrue/f0_pt_y"), part.pt(), part.y()); - histos.fill(HIST("QAMCTrue/f0_pt_cent"), part.pt(), resoCollision.cent()); + histos.fill(HIST("QAMCTrue/f0_pt_cent"), part.pt(), centFT0M); } } }; diff --git a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx index 6cf4b2b176c..5c2884459a0 100644 --- a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx @@ -50,6 +50,7 @@ #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" +#include #include #include "Math/GenVector/Boost.h" @@ -81,83 +82,107 @@ struct F0980pbpbanalysis { Configurable cfgURL{"cfgURL", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; - // Evnet Selection Configurables - Configurable cfgEventCutVertex{"cfgEventCutVertex", 10.0, "PV selection"}; - Configurable cfgEventQvecSel{"cfgEventQvecSel", true, "Reject events when no QVector"}; - Configurable cfgEventOccupancySel{"cfgEventOccupancySel", false, "Occupancy selection"}; - Configurable cfgEventOccupancyMax{"cfgEventOccupancyMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; - Configurable cfgEventOccupancyMin{"cfgEventOccupancyMin", -100, "minimum occupancy of tracks in neighbouring collisions in a given time range"}; - Configurable cfgEventGoodZvtxSel{"cfgEventGoodZvtxSel", true, "kIsGoodZvtxFT0vsPV selection"}; - Configurable cfgEventNSamePileupSel{"cfgEventNSamePileupSel", true, "kNoSameBunchPileup selection"}; - Configurable cfgEventNCollinTRSel{"cfgEventNCollinTRSel", true, "kNoCollInTimeRangeStandard selection"}; - Configurable cfgEventPVSel{"cfgEventPVSel", false, "Additional PV selection flag for syst"}; - Configurable cfgEventPV{"cfgEventPV", 8.0, "Additional PV selection range for syst"}; - - Configurable cfgEventCentMax{"cfgEventCentMax", 80., "CentralityMax cut"}; - Configurable cfgEventCentEst{"cfgEventCentEst", 1, "Centrality estimator, 1: FT0C, 2: FT0M"}; + // Event Selection Configurables + struct : ConfigurableGroup { + Configurable cfgEventCutVertex{"cfgEventCutVertex", 10.0, "PV selection"}; + Configurable cfgEventQvecSel{"cfgEventQvecSel", true, "Reject events when no QVector"}; + Configurable cfgEventOccupancySel{"cfgEventOccupancySel", false, "Occupancy selection"}; + Configurable cfgEventOccupancyMax{"cfgEventOccupancyMax", 999999, "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgEventOccupancyMin{"cfgEventOccupancyMin", -100, "minimum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgEventGoodZvtxSel{"cfgEventGoodZvtxSel", true, "kIsGoodZvtxFT0vsPV selection"}; + Configurable cfgEventNSamePileupSel{"cfgEventNSamePileupSel", true, "kNoSameBunchPileup selection"}; + Configurable cfgEventNCollinTRSel{"cfgEventNCollinTRSel", true, "kNoCollInTimeRangeStandard selection"}; + Configurable cfgEventPVSel{"cfgEventPVSel", false, "Additional PV selection flag for syst"}; + Configurable cfgEventPV{"cfgEventPV", 8.0, "Additional PV selection range for syst"}; + + Configurable cfgEventCentMax{"cfgEventCentMax", 80., "CentralityMax cut"}; + Configurable cfgEventCentEst{"cfgEventCentEst", 1, "Centrality estimator, 1: FT0C, 2: FT0M"}; + } EventConfig; // Track Selection Configurables - Configurable cfgTrackPtMin{"cfgTrackPtMin", 0.15, "Minimum transverse momentum for charged track"}; - Configurable cfgTrackEtaMax{"cfgTrackEtaMax", 0.8, "Maximum pseudorapidiy for charged track"}; - Configurable cfgTrackDCArToPVcutMax{"cfgTrackDCArToPVcutMax", 0.5, "Maximum transverse DCA"}; - Configurable cfgTrackDCAzToPVcutMax{"cfgTrackDCAzToPVcutMax", 2.0, "Maximum longitudinal DCA"}; - Configurable cfgTrackRapMin{"cfgTrackRapMin", -0.5, "Minimum rapidity for pair"}; - Configurable cfgTrackRapMax{"cfgTrackRapMax", 0.5, "Maximum rapidity for pair"}; + struct : ConfigurableGroup { + Configurable cfgTrackPtMin{"cfgTrackPtMin", 0.15, "Minimum transverse momentum for charged track"}; + Configurable cfgTrackEtaMax{"cfgTrackEtaMax", 0.8, "Maximum pseudorapidity for charged track"}; + Configurable cfgTrackRapMin{"cfgTrackRapMin", -0.5, "Minimum rapidity for pair"}; + Configurable cfgTrackRapMax{"cfgTrackRapMax", 0.5, "Maximum rapidity for pair"}; - Configurable cfgTrackIsPrimaryTrack{"cfgTrackIsPrimaryTrack", true, "Primary track selection"}; - Configurable cfgTrackIsGlobalWoDCATrack{"cfgTrackIsGlobalWoDCATrack", true, "Global track selection without DCA"}; - Configurable cfgTrackIsPVContributor{"cfgTrackIsPVContributor", true, "PV contributor track selection"}; + Configurable cfgTrackIsPVContributor{"cfgTrackIsPVContributor", true, "PV contributor track selection"}; + Configurable cfgTrackIsGlobalWoDCATrack{"cfgTrackIsGlobalWoDCATrack", true, "Global track selection without DCA"}; + Configurable cfgTrackIsPrimaryTrack{"cfgTrackIsPrimaryTrack", true, "Primary track selection"}; - Configurable cfgTrackNTPCCrossedRows{"cfgTrackNTPCCrossedRows", 70, "nCrossed TPC Rows"}; - Configurable cfgTrackNFindableTPCClusters{"cfgTrackNFindableTPCClusters", 50, "nFindable TPC Clusters"}; - Configurable cfgTrackNRowsOverFindable{"cfgTrackNRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; - Configurable cfgTrackNTPCChi2{"cfgTrackNTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; + Configurable cfgTrackTPCCrossedRows{"cfgTrackTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfgTrackTPCFindableClusters{"cfgTrackTPCFindableClusters", 50, "nFindable TPC Clusters"}; + Configurable cfgTrackTPCRatioMin{"cfgTrackTPCRatioMin", 0.8, "Minimum nRowsOverFindable TPC Clusters"}; + Configurable cfgTrackTPCRatioMax{"cfgTrackTPCRatioMax", 1.2, "Maximum nRowsOverFindable TPC Clusters"}; + Configurable cfgTrackTPCChi2{"cfgTrackTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; - Configurable cfgTrackNITSChi2{"cfgTrackNITSChi2", 36.0, "nITS Chi2 per Cluster"}; + Configurable cfgTrackITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; - // PID Configurables - Configurable cfgPIDUSETOF{"cfgPIDUSETOF", true, "TOF usage"}; + Configurable cfgTrackDCArToPVcutMax{"cfgTrackDCArToPVcutMax", 0.5, "Maximum transverse DCA"}; + Configurable cfgTrackDCAzToPVcutMax{"cfgTrackDCAzToPVcutMax", 2.0, "Maximum longitudinal DCA"}; - Configurable cfgPIDMaxTOFnSigmaPion{"cfgPIDMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF - Configurable cfgPIDMaxTPCnSigmaPion{"cfgPIDMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cfgPIDMaxTPCnSigmaPionS{"cfgPIDMaxTPCnSigmaPionS", 3.0, "TPC nSigma cut for Pion as a standalone"}; - Configurable cfgPIDMaxTiednSigmaPion{"cfgPIDMaxTiednSigmaPion", 3.0, "Combined nSigma cut for Pion"}; + Configurable cfgTrackDCArDepPTSel{"cfgTrackDCArDepPTSel", false, "Flag for pT dependent transverse DCA cut"}; // 7 - sigma cut + Configurable cfgTrackDCArDepPTP0{"cfgTrackDCArDepPTP0", 0.004, "Coeff. of transverse DCA for p0"}; + Configurable cfgTrackDCArDepPTExp{"cfgTrackDCArDepPTExp", 0.013, "Coeff. of transverse DCA for power law term"}; - // Flow Configurables - Configurable cfgQvecNMods{"cfgQvecNMods", 1, "The number of modulations of interest starting from 2"}; - Configurable cfgQvecNum{"cfgQvecNum", 7, "The number of total Qvectors for looping over the task"}; + Configurable cfgTrackDCAzDepPTSel{"cfgTrackDCAzDepPTSel", false, "Flag for pT dependent longitudinal DCA cut"}; // 7 - sigma cut + Configurable cfgTrackDCAzDepPTP0{"cfgTrackDCAzDepPTP0", 0.004, "Coeff. of longitudinal DCA for p0"}; + Configurable cfgTrackDCAzDepPTExp{"cfgTrackDCAzDepPTExp", 0.013, "Coeff. of longitudinal DCA for power law term"}; + } TrackConfig; - Configurable cfgQvecDetName{"cfgQvecDetName", "FT0C", "The name of detector to be analyzed"}; - Configurable cfgQvecRefAName{"cfgQvecRefAName", "TPCpos", "The name of detector for reference A"}; - Configurable cfgQvecRefBName{"cfgQvecRefBName", "TPCneg", "The name of detector for reference B"}; + // PID Configurables + struct : ConfigurableGroup { + Configurable cfgPIDUSETOF{"cfgPIDUSETOF", true, "TOF usage"}; - // Rotational Background Configurables - Configurable cfgBkgRotSel{"cfgBkgRotSel", false, "flag to construct rotational backgrounds"}; - Configurable cfgBkgRotNum{"cfgBkgRotNum", 5, "the number of rotational backgrounds"}; + Configurable cfgPIDMaxTOFnSigmaPion{"cfgPIDMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cfgPIDMaxTPCnSigmaPion{"cfgPIDMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cfgPIDMaxTPCnSigmaPionS{"cfgPIDMaxTPCnSigmaPionS", 3.0, "TPC nSigma cut for Pion as a standalone"}; + Configurable cfgPIDMaxTiednSigmaPion{"cfgPIDMaxTiednSigmaPion", 3.0, "Combined nSigma cut for Pion"}; + } PIDConfig; - // Mixed Event Background Configurables - SliceCache cache; - Configurable cfgBkgMixedNum{"cfgBkgMixedNum", 5, "Number of mixed events per event"}; + // Flow Configurables + struct : ConfigurableGroup { + Configurable cfgQvecNMods{"cfgQvecNMods", 2, "The number of modulations of interest starting from 2"}; + Configurable cfgQvecNum{"cfgQvecNum", 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", "TPCpos", "The name of detector for reference A"}; + Configurable cfgQvecRefBName{"cfgQvecRefBName", "TPCneg", "The name of detector for reference B"}; + } FlowConfig; + + struct : ConfigurableGroup { + // Rotational Background Configurables + Configurable cfgBkgRotSel{"cfgBkgRotSel", false, "flag to construct rotational backgrounds"}; + Configurable cfgBkgRotNum{"cfgBkgRotNum", 5, "the number of rotational backgrounds"}; + // Mixed Event Background Configurables + Configurable cfgBkgMixedNum{"cfgBkgMixedNum", 5, "Number of mixed events per event"}; + } BkgMethodConfig; + // Mixed Event Background Config Axis ConfigurableAxis mixAxisVertex{"mixAxisVertex", {10, -10, 10}, "Vertex axis for mixing bin"}; ConfigurableAxis mixAxisCent{"mixAxisCent", {VARIABLE_WIDTH, 0, 10, 20, 50, 100}, "multiplicity percentile for mixing bin"}; // ConfigurableAxis mixingAxisMultiplicity{"mixingAxisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin"}; + SliceCache cache; // for Mixed Event Background // List Configurables Configurable cfgListPID{"cfgListPID", 0, "PID selection type"}; Configurable cfgListPtl{"cfgListPtl", 0, "Particle selection type"}; // Histogram QA Configurables - Configurable cfgQAEventCut{"cfgQAEventCut", true, "Enable Event QA Hists"}; - Configurable cfgQATrackCut{"cfgQATrackCut", true, "Enable Track QA Hists"}; - Configurable cfgQAPIDCut{"cfgQAPIDCut", true, "Enable PID QA Hists"}; - Configurable cfgQAEPCut{"cfgQAEPCut", true, "Enable Event Plane QA Hists"}; - Configurable cfgQAEventFlowCut{"cfgQAEventFlowCut", true, "Enable Event Flow QA Hists"}; + struct : ConfigurableGroup { + Configurable cfgQAEventCut{"cfgQAEventCut", false, "Enable Event QA Hists"}; + Configurable cfgQATrackCut{"cfgQATrackCut", false, "Enable Track QA Hists"}; + Configurable cfgQAPIDCut{"cfgQAPIDCut", false, "Enable PID QA Hists"}; + Configurable cfgQAEPCut{"cfgQAEPCut", false, "Enable Event Plane QA Hists"}; + Configurable cfgQAPairCut{"cfgQAPairCut", false, "Enable Pair QA Hists"}; + Configurable cfgQAEventFlowCut{"cfgQAEventFlowCut", false, "Enable Event Flow QA Hists"}; + Configurable cfgQATrackFlowCut{"cfgQATrackFlowCut", false, "Enable Track Flow QA Hists"}; + } QAConfig; ConfigurableAxis histAxisDCAz{"histAxisDCAz", {40, -0.2, 0.2}, "DCAz axis"}; ConfigurableAxis histAxisDCAr{"histAxisDCAr", {40, -0.2, 0.2}, "DCAxy axis"}; ConfigurableAxis histAxisOccupancy{"histAxisOccupancy", {100, 0.0, 20000}, "Occupancy axis"}; - Configurable cfgAnalysisMethod{"cfgAnalysisMethod", true, "true: Two for-loop, false: Combination"}; + // Configurable cfgAnalysisMethod{"cfgAnalysisMethod", true, "true: Two for-loop, false: Combination"}; // Configurable for axis ConfigurableAxis axisMass{"axisMass", {400, 0.2, 2.2}, "Invariant mass axis"}; @@ -166,17 +191,19 @@ struct F0980pbpbanalysis { ConfigurableAxis axisEp{"axisEp", {6, 0.0, o2::constants::math::TwoPI}, "EP axis"}; // for phi test - Configurable cfgPhiITSClsSel{"cfgPhiITSClsSel", false, "ITS cluster selection flag"}; - Configurable cfgPhiITScluster{"cfgPhiITScluster", 0, "Number of ITS cluster"}; - Configurable cfgPhiTOFBetaSel{"cfgPhiTOFBetaSel", false, "TOF beta cut selection flag"}; - Configurable cfgPhiTOFBetaCut{"cfgPhiTOFBetaCut", 0.0, "cut TOF beta"}; - Configurable cfgPhiDeepAngleSel{"cfgPhiDeepAngleSel", false, "Deep Angle cut"}; - Configurable cfgPhiDeepAngle{"cfgPhiDeepAngle", 0.04, "Deep Angle cut value"}; + struct : ConfigurableGroup { + Configurable cfgPhiITSClsSel{"cfgPhiITSClsSel", false, "ITS cluster selection flag"}; + Configurable cfgPhiITScluster{"cfgPhiITScluster", 0, "Number of ITS cluster"}; + Configurable cfgPhiTOFBetaSel{"cfgPhiTOFBetaSel", false, "TOF beta cut selection flag"}; + Configurable cfgPhiTOFBetaCut{"cfgPhiTOFBetaCut", 0.0, "cut TOF beta"}; + Configurable cfgPhiDeepAngleSel{"cfgPhiDeepAngleSel", false, "Deep Angle cut"}; + Configurable cfgPhiDeepAngle{"cfgPhiDeepAngle", 0.04, "Deep Angle cut value"}; + } PhiTestConfig; TF1* fMultPVCutLow = nullptr; TF1* fMultPVCutHigh = nullptr; - int nmode = 2; + int nmode = FlowConfig.cfgQvecNMods; static constexpr double QvecAmpMin = 1e-4; int detId; @@ -224,19 +251,17 @@ struct F0980pbpbanalysis { QAEP = 2, QATrack = 3, QAPID = 4, + QAPair = 5, }; TRandom* rn = new TRandom(); - using EventCandidatesOrigin = soa::Join; - using TrackCandidatesOrigin = soa::Join; - - Filter collisionFilter = nabs(aod::collision::posZ) < cfgEventCutVertex; - Filter acceptanceFilter = (nabs(aod::track::eta) < cfgTrackEtaMax && nabs(aod::track::pt) > cfgTrackPtMin); - Filter cutDCAFilter = (nabs(aod::track::dcaXY) < cfgTrackDCArToPVcutMax) && (nabs(aod::track::dcaZ) < cfgTrackDCAzToPVcutMax); + Filter collisionFilter = nabs(aod::collision::posZ) < EventConfig.cfgEventCutVertex; + Filter acceptanceFilter = (nabs(aod::track::eta) < TrackConfig.cfgTrackEtaMax && nabs(aod::track::pt) > TrackConfig.cfgTrackPtMin); // kinematic cut + // Filter cutDCAFilter = (nabs(aod::track::dcaXY) < cfgTrackDCArToPVcutMax) && (nabs(aod::track::dcaZ) < cfgTrackDCAzToPVcutMax); - using EventCandidates = soa::Filtered; - using TrackCandidates = soa::Filtered; + using EventCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; using BinningTypeVertexContributor = ColumnBinningPolicy; @@ -292,25 +317,27 @@ struct F0980pbpbanalysis { if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { if (objecttype == QATrack) { if (!pass) { - histos.fill(HIST("TrackQA/DCArToPv_BC"), obj.dcaXY()); - histos.fill(HIST("TrackQA/DCAzToPv_BC"), obj.dcaZ()); - histos.fill(HIST("TrackQA/IsPrim_BC"), obj.isPrimaryTrack()); - histos.fill(HIST("TrackQA/IsGood_BC"), obj.isGlobalTrackWoDCA()); - histos.fill(HIST("TrackQA/IsPrimCont_BC"), obj.isPVContributor()); - histos.fill(HIST("TrackQA/FindableTPCClusters_BC"), obj.tpcNClsFindable()); - histos.fill(HIST("TrackQA/FindableTPCRows_BC"), obj.tpcNClsCrossedRows()); - histos.fill(HIST("TrackQA/ClustersVsRows_BC"), obj.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("TrackQA/TPCChi2_BC"), obj.tpcChi2NCl()); + histos.fill(HIST("TrackQA/DCArToPv_BC"), obj.pt(), centrality, obj.dcaXY()); + histos.fill(HIST("TrackQA/DCAzToPv_BC"), obj.pt(), centrality, obj.dcaZ()); + histos.fill(HIST("TrackQA/IsPrim_BC"), centrality, obj.isPrimaryTrack()); + histos.fill(HIST("TrackQA/IsGood_BC"), centrality, obj.isGlobalTrackWoDCA()); + histos.fill(HIST("TrackQA/IsPrimCont_BC"), centrality, obj.isPVContributor()); + histos.fill(HIST("TrackQA/TPCFindableClusters_BC"), centrality, obj.tpcNClsFindable()); + histos.fill(HIST("TrackQA/TPCCrossedRows_BC"), centrality, obj.tpcNClsCrossedRows()); + histos.fill(HIST("TrackQA/TPCRatioRowsOverFindable_BC"), centrality, obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("TrackQA/TPCChi2_BC"), centrality, obj.tpcChi2NCl()); + histos.fill(HIST("TrackQA/ITSChi2_BC"), centrality, obj.itsChi2NCl()); } else { - histos.fill(HIST("TrackQA/DCArToPv_AC"), obj.dcaXY()); - histos.fill(HIST("TrackQA/DCAzToPv_AC"), obj.dcaZ()); - histos.fill(HIST("TrackQA/IsPrim_AC"), obj.isPrimaryTrack()); - histos.fill(HIST("TrackQA/IsGood_AC"), obj.isGlobalTrackWoDCA()); - histos.fill(HIST("TrackQA/IsPrimCont_AC"), obj.isPVContributor()); - histos.fill(HIST("TrackQA/FindableTPCClusters_AC"), obj.tpcNClsFindable()); - histos.fill(HIST("TrackQA/FindableTPCRows_AC"), obj.tpcNClsCrossedRows()); - histos.fill(HIST("TrackQA/ClustersVsRows_AC"), obj.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("TrackQA/TPCChi2_AC"), obj.tpcChi2NCl()); + histos.fill(HIST("TrackQA/DCArToPv_AC"), obj.pt(), centrality, obj.dcaXY()); + histos.fill(HIST("TrackQA/DCAzToPv_AC"), obj.pt(), centrality, obj.dcaZ()); + histos.fill(HIST("TrackQA/IsPrim_AC"), centrality, obj.isPrimaryTrack()); + histos.fill(HIST("TrackQA/IsGood_AC"), centrality, obj.isGlobalTrackWoDCA()); + histos.fill(HIST("TrackQA/IsPrimCont_AC"), centrality, obj.isPVContributor()); + histos.fill(HIST("TrackQA/TPCFindableClusters_AC"), centrality, obj.tpcNClsFindable()); + histos.fill(HIST("TrackQA/TPCCrossedRows_AC"), centrality, obj.tpcNClsCrossedRows()); + histos.fill(HIST("TrackQA/TPCRatioRowsOverFindable_AC"), centrality, obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("TrackQA/TPCChi2_AC"), centrality, obj.tpcChi2NCl()); + histos.fill(HIST("TrackQA/ITSChi2_AC"), centrality, obj.itsChi2NCl()); } } if (objecttype == QAPID) { @@ -318,67 +345,81 @@ struct F0980pbpbanalysis { histos.fill(HIST("PIDQA/Nsigma_TPC_BC"), obj.pt(), getTpcNSigma(obj)); histos.fill(HIST("PIDQA/Nsigma_TOF_BC"), obj.pt(), getTofNSigma(obj)); histos.fill(HIST("PIDQA/TPC_TOF_BC"), getTpcNSigma(obj), getTofNSigma(obj)); + histos.fill(HIST("PIDQA/TPC_Cent_BC"), centrality, getTpcNSigma(obj)); + histos.fill(HIST("PIDQA/TOF_Cent_BC"), centrality, getTofNSigma(obj)); } else { histos.fill(HIST("PIDQA/Nsigma_TPC_AC"), obj.pt(), getTpcNSigma(obj)); histos.fill(HIST("PIDQA/Nsigma_TOF_AC"), obj.pt(), getTofNSigma(obj)); histos.fill(HIST("PIDQA/TPC_TOF_AC"), getTpcNSigma(obj), getTofNSigma(obj)); + histos.fill(HIST("PIDQA/TPC_Cent_AC"), centrality, getTpcNSigma(obj)); + histos.fill(HIST("PIDQA/TOF_Cent_AC"), centrality, getTofNSigma(obj)); + } + } + } + if constexpr (requires { obj.Rapidity(); }) { + if (objecttype == QAPair) { + if (!pass) { + histos.fill(HIST("PairQA/hYpipiPair_BC"), obj.Rapidity()); + } else { + histos.fill(HIST("PairQA/hYpipiPair_AC"), obj.Rapidity()); } } } } + // Event selection template bool eventSelected(TCollision collision, const bool QA) { - if (cfgQAEventCut && QA) + if (QAConfig.cfgQAEventCut && QA) fillQA(false, collision, 1); - if (cfgQAEPCut && QA) + if (QAConfig.cfgQAEPCut && QA) fillQA(false, collision, 2); // if (cfgQAEventFlowCut) histos.fill(HIST("EventQA/hnEvents"), 0); // - if (std::abs(collision.posZ()) > cfgEventCutVertex) { + if (std::abs(collision.posZ()) > EventConfig.cfgEventCutVertex) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 1); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 1); // Vertex cut if (!collision.sel8()) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 2); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 2); // sel8 cut - if (cfgEventGoodZvtxSel && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (EventConfig.cfgEventGoodZvtxSel && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 3); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 3); // Good Zvtx cut - if (cfgEventNSamePileupSel && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (EventConfig.cfgEventNSamePileupSel && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 4); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 4); // Same bunch pileup cut - if (cfgEventNCollinTRSel && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (EventConfig.cfgEventNCollinTRSel && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 5); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 5); // Collision time range standard cut - if (cfgEventQvecSel && (collision.qvecAmp()[detId] < QvecAmpMin || collision.qvecAmp()[refAId] < QvecAmpMin || collision.qvecAmp()[refBId] < QvecAmpMin)) { + if (EventConfig.cfgEventQvecSel && (collision.qvecAmp()[detId] < QvecAmpMin || collision.qvecAmp()[refAId] < QvecAmpMin || collision.qvecAmp()[refBId] < QvecAmpMin)) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 6); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 6); // Qvector cut - if (cfgEventOccupancySel && (collision.trackOccupancyInTimeRange() > cfgEventOccupancyMax || collision.trackOccupancyInTimeRange() < cfgEventOccupancyMin)) { + if (EventConfig.cfgEventOccupancySel && (collision.trackOccupancyInTimeRange() > EventConfig.cfgEventOccupancyMax || collision.trackOccupancyInTimeRange() < EventConfig.cfgEventOccupancyMin)) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 7); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 7); // Occupancy cut - if (cfgEventCentMax < centrality) { + if (EventConfig.cfgEventCentMax < centrality) { return 0; } /* @@ -390,66 +431,101 @@ struct F0980pbpbanalysis { return 0; } */ - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 8); + if (QAConfig.cfgQAEventFlowCut && QA) + histos.fill(HIST("EventQA/hnEvents"), 8); // Centrality cut - if (cfgEventPVSel && std::abs(collision.posZ()) > cfgEventPV) { + if (EventConfig.cfgEventPVSel && std::abs(collision.posZ()) > EventConfig.cfgEventPV) { return 0; } - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 9); - - // All passed - if (cfgQAEventFlowCut && QA) - histos.fill(HIST("EventQA/hnEvents"), 10); + if (QAConfig.cfgQAEventFlowCut && QA) { + histos.fill(HIST("EventQA/hnEvents"), 9); // Additional PV cut + histos.fill(HIST("EventQA/hnEvents"), 10); // All passed + } return 1; - } // event selection + } // Event selection + // Track selection template bool trackSelected(const TrackType track, const bool QA) { - if (cfgQATrackCut && QA) + if (QAConfig.cfgQATrackCut && QA) fillQA(false, track, 3); + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 0); // All passed // - if (std::abs(track.pt()) < cfgTrackPtMin) { + // Kinematic + if (std::abs(track.pt()) < TrackConfig.cfgTrackPtMin) { return 0; } - if (std::abs(track.eta()) > cfgTrackEtaMax) { + if (std::abs(track.eta()) > TrackConfig.cfgTrackEtaMax) { return 0; } - if (std::abs(track.dcaXY()) > cfgTrackDCArToPVcutMax) { + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 1); // Kinematic + // Primary Vertex(PV) Contributing to the PV fit + if (TrackConfig.cfgTrackIsPVContributor && !track.isPVContributor()) { return 0; } - if (std::abs(track.dcaZ()) > cfgTrackDCAzToPVcutMax) { + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 2); // PV Contributor + // Global Track without DCA + if (TrackConfig.cfgTrackIsGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) { return 0; } - if (cfgTrackIsPVContributor && !track.isPVContributor()) { + if (TrackConfig.cfgTrackTPCCrossedRows > 0 && track.tpcNClsCrossedRows() < TrackConfig.cfgTrackTPCCrossedRows) { return 0; } - if (cfgTrackIsPrimaryTrack && !track.isPrimaryTrack()) { + if (TrackConfig.cfgTrackTPCRatioMin > 0 && track.tpcCrossedRowsOverFindableCls() < TrackConfig.cfgTrackTPCRatioMin) { return 0; } - if (cfgTrackIsGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) { + if (TrackConfig.cfgTrackTPCChi2 > 0 && track.tpcChi2NCl() > TrackConfig.cfgTrackTPCChi2) { return 0; } - if (cfgTrackNTPCCrossedRows > 0 && track.tpcNClsCrossedRows() < cfgTrackNTPCCrossedRows) { + if (TrackConfig.cfgTrackITSChi2 > 0 && track.itsChi2NCl() > TrackConfig.cfgTrackITSChi2) { return 0; } - if (cfgTrackNFindableTPCClusters > 0 && track.tpcNClsFindable() < cfgTrackNFindableTPCClusters) { - return 0; + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 4); // GlobalWoDCATrack + // DCA cuts + if (TrackConfig.cfgTrackDCArDepPTSel) { + if (std::abs(track.dcaXY()) > (TrackConfig.cfgTrackDCArDepPTP0 + (TrackConfig.cfgTrackDCArDepPTExp / track.pt()))) { + return 0; + } + } else { + if (std::abs(track.dcaXY()) > TrackConfig.cfgTrackDCArToPVcutMax) { + return 0; + } } - if (cfgTrackNRowsOverFindable > 0 && track.tpcCrossedRowsOverFindableCls() > cfgTrackNRowsOverFindable) { + if (TrackConfig.cfgTrackDCAzDepPTSel) { + if (std::abs(track.dcaZ()) > (TrackConfig.cfgTrackDCAzDepPTP0 + (TrackConfig.cfgTrackDCAzDepPTExp / track.pt()))) { + return 0; + } + } else { + if (std::abs(track.dcaZ()) > TrackConfig.cfgTrackDCAzToPVcutMax) { + return 0; + } + } + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 5); // DCA cuts + // Primary Track + if (TrackConfig.cfgTrackIsPrimaryTrack && !track.isPrimaryTrack()) { return 0; } - if (cfgTrackNTPCChi2 > 0 && track.tpcChi2NCl() > cfgTrackNTPCChi2) { + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 6); // Primary Track + // Additional TPC cuts + if (TrackConfig.cfgTrackTPCFindableClusters > 0 && track.tpcNClsFindable() < TrackConfig.cfgTrackTPCFindableClusters) { return 0; } - if (cfgTrackNITSChi2 > 0 && track.itsChi2NCl() > cfgTrackNITSChi2) { + if (TrackConfig.cfgTrackTPCRatioMax > 0 && track.tpcCrossedRowsOverFindableCls() > TrackConfig.cfgTrackTPCRatioMax) { return 0; } + if (QAConfig.cfgQATrackFlowCut && QA) + histos.fill(HIST("TrackQA/hnTracks"), 7); // Additional TPC cuts return 1; - } + } // track selection + // PID selection template bool selectionPID(const TrackType track, const bool QA) { @@ -457,55 +533,59 @@ struct F0980pbpbanalysis { fillQA(false, track, 4); // if (cfgListPID == PIDList::PIDRun3) { - if (cfgPIDUSETOF) { - if (std::abs(track.tofNSigmaPi()) > cfgPIDMaxTOFnSigmaPion) { + if (PIDConfig.cfgPIDUSETOF) { + if (std::abs(track.tofNSigmaPi()) > PIDConfig.cfgPIDMaxTOFnSigmaPion) { return 0; } - if (std::abs(track.tpcNSigmaPi()) > cfgPIDMaxTPCnSigmaPion) { + if (std::abs(track.tpcNSigmaPi()) > PIDConfig.cfgPIDMaxTPCnSigmaPion) { return 0; } } - if (std::abs(track.tpcNSigmaPi()) > cfgPIDMaxTPCnSigmaPionS) { + if (std::abs(track.tpcNSigmaPi()) > PIDConfig.cfgPIDMaxTPCnSigmaPionS) { return 0; } } else if (cfgListPID == PIDList::PIDRun2) { - if (cfgPIDUSETOF) { + if (PIDConfig.cfgPIDUSETOF) { if (track.hasTOF()) { - if (std::abs(track.tofNSigmaPi()) > cfgPIDMaxTOFnSigmaPion) { + if (std::abs(track.tofNSigmaPi()) > PIDConfig.cfgPIDMaxTOFnSigmaPion) { return 0; } - if (std::abs(track.tpcNSigmaPi()) > cfgPIDMaxTPCnSigmaPion) { + if (std::abs(track.tpcNSigmaPi()) > PIDConfig.cfgPIDMaxTPCnSigmaPion) { return 0; } } else { - if (std::abs(track.tpcNSigmaPi()) > cfgPIDMaxTPCnSigmaPionS) { + if (std::abs(track.tpcNSigmaPi()) > PIDConfig.cfgPIDMaxTPCnSigmaPionS) { return 0; } } } else { - if (std::abs(track.tpcNSigmaPi()) > cfgPIDMaxTPCnSigmaPionS) { + if (std::abs(track.tpcNSigmaPi()) > PIDConfig.cfgPIDMaxTPCnSigmaPionS) { return 0; } } } else if (cfgListPID == PIDList::PIDTest) { - if (cfgPIDUSETOF) { + if (PIDConfig.cfgPIDUSETOF) { if (track.hasTOF()) { - if ((getTpcNSigma(track) * getTpcNSigma(track) + getTofNSigma(track) * getTofNSigma(track)) > (cfgPIDMaxTiednSigmaPion * cfgPIDMaxTiednSigmaPion)) { + if ((getTpcNSigma(track) * getTpcNSigma(track) + getTofNSigma(track) * getTofNSigma(track)) > (PIDConfig.cfgPIDMaxTiednSigmaPion * PIDConfig.cfgPIDMaxTiednSigmaPion)) { return 0; } } else { - if (std::abs(getTpcNSigma(track)) > cfgPIDMaxTPCnSigmaPionS) { + if (std::abs(getTpcNSigma(track)) > PIDConfig.cfgPIDMaxTPCnSigmaPionS) { return 0; } } } else { - if (std::abs(getTpcNSigma(track)) > cfgPIDMaxTPCnSigmaPionS) { + if (std::abs(getTpcNSigma(track)) > PIDConfig.cfgPIDMaxTPCnSigmaPionS) { return 0; } } } + if (QAConfig.cfgQATrackFlowCut && QA) { + histos.fill(HIST("TrackQA/hnTracks"), 8); // PID + histos.fill(HIST("TrackQA/hnTracks"), 9); // Passed Tracks + } return 1; - } + } // PID selection template bool pairAngleSelection(const TrackType1 track1, const TrackType2 track2) @@ -518,7 +598,7 @@ struct F0980pbpbanalysis { p1 = track1.p(); p2 = track2.p(); angle = std::acos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); - if (cfgPhiDeepAngleSel && angle < cfgPhiDeepAngle) { + if (PhiTestConfig.cfgPhiDeepAngleSel && angle < PhiTestConfig.cfgPhiDeepAngle) { return 0; } return 1; @@ -547,9 +627,9 @@ struct F0980pbpbanalysis { template void fillHistograms(const CollisionType& collision, const TracksType& dTracks) { - qVecDetInd = detId * 4 + 3 + (nmode - 2) * cfgQvecNum * 4; - qVecRefAInd = refAId * 4 + 3 + (nmode - 2) * cfgQvecNum * 4; - qVecRefBInd = refBId * 4 + 3 + (nmode - 2) * cfgQvecNum * 4; + qVecDetInd = detId * 4 + 3 + (nmode - 2) * FlowConfig.cfgQvecNum * 4; + qVecRefAInd = refAId * 4 + 3 + (nmode - 2) * FlowConfig.cfgQvecNum * 4; + qVecRefBInd = refBId * 4 + 3 + (nmode - 2) * FlowConfig.cfgQvecNum * 4; eventPlaneDet = std::atan2(collision.qvecIm()[qVecDetInd], collision.qvecRe()[qVecDetInd]) / static_cast(nmode); eventPlaneRefA = std::atan2(collision.qvecIm()[qVecRefAInd], collision.qvecRe()[qVecRefAInd]) / static_cast(nmode); @@ -562,7 +642,7 @@ struct F0980pbpbanalysis { if (!trackSelected(trk1, true)) { continue; } - if (cfgQATrackCut) + if (QAConfig.cfgQATrackCut) fillQA(true, trk1, 3); if (!selectionPID(trk1, true)) { @@ -584,7 +664,7 @@ struct F0980pbpbanalysis { continue; } - if (cfgPhiDeepAngleSel && !pairAngleSelection(trk1, trk2)) { + if (PhiTestConfig.cfgPhiDeepAngleSel && !pairAngleSelection(trk1, trk2)) { continue; } @@ -592,9 +672,17 @@ struct F0980pbpbanalysis { pion2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPtl); reco = pion1 + pion2; - if (reco.Rapidity() > cfgTrackRapMax || reco.Rapidity() < cfgTrackRapMin) { + if (QAConfig.cfgQAPairCut) { + fillQA(false, reco, 5); + } + // Pair Rapidity cut + if (reco.Rapidity() > TrackConfig.cfgTrackRapMax || reco.Rapidity() < TrackConfig.cfgTrackRapMin) { continue; } + // + if (QAConfig.cfgQAPairCut) { + fillQA(true, reco, 5); + } relPhi = TVector2::Phi_0_2pi((reco.Phi() - eventPlaneDet) * static_cast(nmode)); @@ -606,8 +694,8 @@ struct F0980pbpbanalysis { histos.fill(HIST("hInvMass_f0980_LSmm_EPA"), reco.M(), reco.Pt(), centrality, relPhi); } - if (cfgBkgRotSel && trk1.sign() * trk2.sign() < 0) { - for (int nr = 0; nr < cfgBkgRotNum; nr++) { + if (BkgMethodConfig.cfgBkgRotSel && trk1.sign() * trk2.sign() < 0) { + for (int nr = 0; nr < BkgMethodConfig.cfgBkgRotNum; nr++) { auto randomPhi = rn->Uniform(o2::constants::math::PI * 5.0 / 6.0, o2::constants::math::PI * 7.0 / 6.0); randomPhi += pion2.Phi(); pion2Rot = ROOT::Math::PxPyPzMVector(pion2.Pt() * std::cos(randomPhi), pion2.Pt() * std::sin(randomPhi), trk2.pz(), massPtl); @@ -623,16 +711,16 @@ struct F0980pbpbanalysis { void processEventMixing(EventCandidates const& collisions, TrackCandidates const& tracks) { // nmode = 2; // second order - qVecDetInd = detId * 4 + 3 + (nmode - 2) * cfgQvecNum * 4; + qVecDetInd = detId * 4 + 3 + (nmode - 2) * FlowConfig.cfgQvecNum * 4; auto trackTuple = std::make_tuple(tracks); BinningTypeVertexContributor binningOnPositions{{mixAxisVertex, mixAxisCent}, true}; - SameKindPair pair{binningOnPositions, cfgBkgMixedNum, -1, collisions, trackTuple, &cache}; + SameKindPair pair{binningOnPositions, BkgMethodConfig.cfgBkgMixedNum, -1, collisions, trackTuple, &cache}; ROOT::Math::PxPyPzMVector ptl1, ptl2, recoPtl; for (const auto& [c1, t1, c2, t2] : pair) { - if (cfgEventCentEst == CentEstList::FT0C) { + if (EventConfig.cfgEventCentEst == CentEstList::FT0C) { centrality = c1.centFT0C(); - } else if (cfgEventCentEst == CentEstList::FT0M) { + } else if (EventConfig.cfgEventCentEst == CentEstList::FT0M) { centrality = c1.centFT0M(); } if (!eventSelected(c1, false) || !eventSelected(c2, false)) { @@ -661,13 +749,13 @@ struct F0980pbpbanalysis { // if (!pairIndexSelection(trk1, trk2)) { // continue; // } - if (cfgPhiDeepAngleSel && !pairAngleSelection(trk1, trk2)) { + if (PhiTestConfig.cfgPhiDeepAngleSel && !pairAngleSelection(trk1, trk2)) { continue; } ptl1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPtl); ptl2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPtl); recoPtl = ptl1 + ptl2; - if (recoPtl.Rapidity() > cfgTrackRapMax || recoPtl.Rapidity() < cfgTrackRapMin) { + if (recoPtl.Rapidity() > TrackConfig.cfgTrackRapMax || recoPtl.Rapidity() < TrackConfig.cfgTrackRapMin) { continue; } @@ -682,9 +770,9 @@ struct F0980pbpbanalysis { } PROCESS_SWITCH(F0980pbpbanalysis, processEventMixing, "Process Event mixing", false); - void processTotalEvent(EventCandidatesOrigin const& events) + void processTotalEvent(aod::Collisions const& events) { - if (cfgQAEventFlowCut) { + if (QAConfig.cfgQAEventFlowCut) { nTotalEvents += events.size(); auto hTotalEvents = histos.get(HIST("EventQA/hnEvents")); if (hTotalEvents) { @@ -702,9 +790,10 @@ struct F0980pbpbanalysis { AxisSpec qaPtAxis = {200, 0, 20}; AxisSpec qaEpAxis = {100, -1.0 * o2::constants::math::PI, o2::constants::math::PI}; AxisSpec epresAxis = {102, -1.02, 1.02}; + AxisSpec qaRapAxis = {80, -2, 2}; // Event QA - if (cfgQAEventCut) { + if (QAConfig.cfgQAEventCut) { histos.add("EventQA/CentDist_BC", "", {HistType::kTH1F, {qaCentAxis}}); histos.add("EventQA/Vz_BC", "", {HistType::kTH1F, {qaVzAxis}}); histos.add("EventQA/Occupancy_BC", "", kTH1F, {{histAxisOccupancy}}); @@ -714,45 +803,56 @@ struct F0980pbpbanalysis { histos.add("EventQA/Occupancy_AC", "", kTH1F, {{histAxisOccupancy}}); // Track QA - if (cfgQATrackCut) { - histos.add("TrackQA/DCArToPv_BC", "", {HistType::kTH1F, {histAxisDCAz}}); - histos.add("TrackQA/DCAzToPv_BC", "", {HistType::kTH1F, {histAxisDCAz}}); - histos.add("TrackQA/IsPrim_BC", "", kTH1F, {{2, -0.5, 1.5}}); - histos.add("TrackQA/IsGood_BC", "", kTH1F, {{2, -0.5, 1.5}}); - histos.add("TrackQA/IsPrimCont_BC", "", kTH1F, {{2, -0.5, 1.5}}); - histos.add("TrackQA/FindableTPCClusters_BC", "", kTH1F, {{200, 0, 200}}); - histos.add("TrackQA/FindableTPCRows_BC", "", kTH1F, {{200, 0, 200}}); - histos.add("TrackQA/ClustersVsRows_BC", "", kTH1F, {{200, 0, 2}}); - histos.add("TrackQA/TPCChi2_BC", "", kTH1F, {{200, 0, 100}}); - histos.add("TrackQA/ITSChi2_BC", "", kTH1F, {{200, 0, 100}}); + if (QAConfig.cfgQATrackCut) { + histos.add("TrackQA/DCArToPv_BC", "", {HistType::kTH3F, {qaPtAxis, qaCentAxis, histAxisDCAr}}); + histos.add("TrackQA/DCAzToPv_BC", "", {HistType::kTH3F, {qaPtAxis, qaCentAxis, histAxisDCAz}}); + histos.add("TrackQA/IsPrim_BC", "", {HistType::kTH2F, {qaCentAxis, {2, -0.5, 1.5}}}); + histos.add("TrackQA/IsGood_BC", "", {HistType::kTH2F, {qaCentAxis, {2, -0.5, 1.5}}}); + histos.add("TrackQA/IsPrimCont_BC", "", {HistType::kTH2F, {qaCentAxis, {2, -0.5, 1.5}}}); + histos.add("TrackQA/TPCFindableClusters_BC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 200}}}); + histos.add("TrackQA/TPCCrossedRows_BC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 200}}}); + histos.add("TrackQA/TPCRatioRowsOverFindable_BC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 2}}}); + histos.add("TrackQA/TPCChi2_BC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 100}}}); + histos.add("TrackQA/ITSChi2_BC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 100}}}); // - histos.add("TrackQA/DCArToPv_AC", "", {HistType::kTH1F, {histAxisDCAz}}); - histos.add("TrackQA/DCAzToPv_AC", "", {HistType::kTH1F, {histAxisDCAz}}); - histos.add("TrackQA/IsPrim_AC", "", kTH1F, {{2, -0.5, 1.5}}); - histos.add("TrackQA/IsGood_AC", "", kTH1F, {{2, -0.5, 1.5}}); - histos.add("TrackQA/IsPrimCont_AC", "", kTH1F, {{2, -0.5, 1.5}}); - histos.add("TrackQA/FindableTPCClusters_AC", "", kTH1F, {{200, 0, 200}}); - histos.add("TrackQA/FindableTPCRows_AC", "", kTH1F, {{200, 0, 200}}); - histos.add("TrackQA/ClustersVsRows_AC", "", kTH1F, {{200, 0, 2}}); - histos.add("TrackQA/TPCChi2_AC", "", kTH1F, {{200, 0, 100}}); - histos.add("TrackQA/ITSChi2_AC", "", kTH1F, {{200, 0, 100}}); + histos.add("TrackQA/DCArToPv_AC", "", {HistType::kTH3F, {qaPtAxis, qaCentAxis, histAxisDCAr}}); + histos.add("TrackQA/DCAzToPv_AC", "", {HistType::kTH3F, {qaPtAxis, qaCentAxis, histAxisDCAz}}); + histos.add("TrackQA/IsPrim_AC", "", {HistType::kTH2F, {qaCentAxis, {2, -0.5, 1.5}}}); + histos.add("TrackQA/IsGood_AC", "", {HistType::kTH2F, {qaCentAxis, {2, -0.5, 1.5}}}); + histos.add("TrackQA/IsPrimCont_AC", "", {HistType::kTH2F, {qaCentAxis, {2, -0.5, 1.5}}}); + histos.add("TrackQA/TPCFindableClusters_AC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 200}}}); + histos.add("TrackQA/TPCCrossedRows_AC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 200}}}); + histos.add("TrackQA/TPCRatioRowsOverFindable_AC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 2}}}); + histos.add("TrackQA/TPCChi2_AC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 100}}}); + histos.add("TrackQA/ITSChi2_AC", "", {HistType::kTH2F, {qaCentAxis, {200, 0, 100}}}); } // PID QA histos.add("PIDQA/Nsigma_TPC_BC", "", {HistType::kTH2F, {qaPtAxis, qaPIDAxis}}); histos.add("PIDQA/Nsigma_TOF_BC", "", {HistType::kTH2F, {qaPtAxis, qaPIDAxis}}); histos.add("PIDQA/TPC_TOF_BC", "", {HistType::kTH2F, {qaPIDAxis, qaPIDAxis}}); + histos.add("PIDQA/TPC_Cent_BC", "", {HistType::kTH2F, {qaCentAxis, qaPIDAxis}}); + histos.add("PIDQA/TOF_Cent_BC", "", {HistType::kTH2F, {qaCentAxis, qaPIDAxis}}); // histos.add("PIDQA/Nsigma_TPC_AC", "", {HistType::kTH2F, {qaPtAxis, qaPIDAxis}}); histos.add("PIDQA/Nsigma_TOF_AC", "", {HistType::kTH2F, {qaPtAxis, qaPIDAxis}}); histos.add("PIDQA/TPC_TOF_AC", "", {HistType::kTH2F, {qaPIDAxis, qaPIDAxis}}); + histos.add("PIDQA/TPC_Cent_AC", "", {HistType::kTH2F, {qaCentAxis, qaPIDAxis}}); + histos.add("PIDQA/TOF_Cent_AC", "", {HistType::kTH2F, {qaCentAxis, qaPIDAxis}}); // // histos.add("PIDQA/Nsigma_TPC_selected", "", {HistType::kTH2F, {qaPtAxis, qaPIDAxis}}); // histos.add("PIDQA/Nsigma_TOF_selected", "", {HistType::kTH2F, {qaPtAxis, qaPIDAxis}}); // histos.add("PIDQA/TPC_TOF_selected", "", {HistType::kTH2F, {qaPIDAxis, qaPIDAxis}}); + // Pair QA + if (QAConfig.cfgQAPairCut) { + histos.add("PairQA/hYpipiPair_BC", "", {HistType::kTH1F, {qaRapAxis}}); + // + histos.add("PairQA/hYpipiPair_AC", "", {HistType::kTH1F, {qaRapAxis}}); + } + // Event Plane QA - if (cfgQAEPCut) { + if (QAConfig.cfgQAEPCut) { histos.add("EventQA/EPhist_BC", "", {HistType::kTH2F, {qaCentAxis, qaEpAxis}}); histos.add("EventQA/EPhistAB_BC", "", {HistType::kTH2F, {qaCentAxis, epresAxis}}); histos.add("EventQA/EPhistAC_BC", "", {HistType::kTH2F, {qaCentAxis, epresAxis}}); @@ -780,8 +880,8 @@ struct F0980pbpbanalysis { // histos.add("MCL/hpT_f0980_REC", "reconstructed f0 signals", HistType::kTH3F, {axisMass, qaPtAxis, axisCent}); // } - // Event Histograms - if (cfgQAEventFlowCut) { + // Event Flow Histograms + if (QAConfig.cfgQAEventFlowCut) { histos.add("EventQA/hnEvents", "Event selection steps", {HistType::kTH1F, {{11, -0.5, 10.5}}}); std::shared_ptr hEventsCutFlow = histos.get(HIST("EventQA/hnEvents")); std::vector eventCutLabels = { @@ -801,9 +901,28 @@ struct F0980pbpbanalysis { } } - detId = getDetId(cfgQvecDetName); - refAId = getDetId(cfgQvecRefAName); - refBId = getDetId(cfgQvecRefBName); + // Track Flow Histograms + if (QAConfig.cfgQATrackFlowCut) { + histos.add("TrackQA/hnTracks", "Track selection steps", {HistType::kTH1F, {{8, -0.5, 7.5}}}); + std::shared_ptr hTracksCutFlow = histos.get(HIST("TrackQA/hnTracks")); + std::vector trackCutLabels = { + "All Tracks", + "Kinematic", + "PV Contributor", + "GlobalWoDCA", + "DCA cuts", + "PrimaryTrack", + "Additional TPC cut", + "PID", + "Passed Tracks"}; + for (size_t i = 0; i < trackCutLabels.size(); ++i) { + hTracksCutFlow->GetXaxis()->SetBinLabel(i + 1, trackCutLabels[i].c_str()); + } + } + + detId = getDetId(FlowConfig.cfgQvecDetName); + refAId = getDetId(FlowConfig.cfgQvecRefAName); + refBId = getDetId(FlowConfig.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 TPCpos and TPCneg will be used as reference systems"); @@ -833,9 +952,9 @@ struct F0980pbpbanalysis { void processData(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCsWithTimestamps const&) { - if (cfgEventCentEst == CentEstList::FT0C) { + if (EventConfig.cfgEventCentEst == CentEstList::FT0C) { centrality = collision.centFT0C(); - } else if (cfgEventCentEst == CentEstList::FT0M) { + } else if (EventConfig.cfgEventCentEst == CentEstList::FT0M) { centrality = collision.centFT0M(); } if (!eventSelected(collision, true)) { diff --git a/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx b/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx index 5424379d0b7..eb563fd9970 100644 --- a/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx +++ b/PWGLF/Tasks/Resonances/f1protoncorrelation.cxx @@ -33,12 +33,19 @@ #include #include #include +#include #include +#include +#include #include #include +#include +#include #include +#include +#include using namespace o2; using namespace o2::framework; @@ -65,6 +72,7 @@ struct f1protoncorrelation { Configurable typeofCombined{"typeofCombined", 1, "type of combined"}; // PID selection Configurable fillSparse{"fillSparse", 1, "Fill Sparse"}; + Configurable doold{"doold", 0, "Do old calculation"}; Configurable fillRotation{"fillRotation", 1, "Fill rotation"}; Configurable pdepPID{"pdepPID", 1, "Momentum dependent pi, k PID"}; Configurable strategyPIDPion{"strategyPIDPion", 0, "PID strategy Pion"}; @@ -84,55 +92,344 @@ struct f1protoncorrelation { // Event Mixing Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; Configurable nEvtMixingBkg{"nEvtMixingBkg", 5, "Number of events to mix for background reconstruction"}; - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 10.0}, "Mixing bins - z-vertex"}; ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0, 40.0, 80.0, 500.0}, "Mixing bins - number of contributor"}; // THnsparse bining ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {100, 1.0, 1.4}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisMultiplicity{"configThnAxisMultiplicity", {100, 0.0, 500}, "multiplicity"}; ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis configThnAxisMt{"configThnAxisMt", {100, 0.0, 10.}, "#it{M}_{T} (GeV/#it{c})"}; ConfigurableAxis configThnAxisKstar{"configThnAxisKstar", {100, 0.0, 1.0}, "#it{k}^{*} (GeV/#it{c})"}; ConfigurableAxis configThnAxisPtProton{"configThnAxisPtProton", {20, 0.0, 4.}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis configThnAxisNsigma{"configThnAxisNsigma", {90, -9.0, 9.0}, "NsigmaCombined"}; ConfigurableAxis configThnAxisCharge{"configThnAxisCharge", {5, -2.5, 2.5}, "Charge"}; - // mix event bining policy - ColumnBinningPolicy colBinningFemto{{CfgVtxBins, CfgMultBins}, true}; + // ------------------------- + // Systematics control + // ------------------------- + Configurable nSysRand{"nSysRand", 500, "Number of random systematic combinations (in addition to default sysId=0)"}; + Configurable sysSeed{"sysSeed", 12345u, "Seed for systematics (reproducible)"}; + + struct SysCuts { + // Primary tracks (π/K/p) + float maxDcaxy; + float maxDcaz; + int minTPCCrossedRows; + int minTPCClusters; + + // V0 (K0s) + float minCPA; + float minRadius; + float maxDcaDaughters; + float maxDcaV0; + float maxLifetime; + float minDcaD1; + float minDcaD2; + + // PID modes + int pidPi; // 0/1/2 depending on what you use + int pidK; // 0/1/2 + int pidP; // 0/1/2 + }; + + std::vector sysCuts; // sysCuts[0] = default; sysCuts[1..] random unique + int nSysTotal = 1; + + // ------------------------- + // Build sysCuts (default + N random unique) + // ------------------------- + void buildSystematicCuts() + { + // 3 options per cut: index 0 = DEFAULT, index 1/2 = variations + // Fill these with the exact values you want (I used your def as index 0 + your old options as 1/2) + const std::array optDcaxy{0.05f, 0.01f, 0.03f}; + const std::array optDcaz{0.05f, 0.01f, 0.03f}; + const std::array optNcrs{80, 90, 100}; + const std::array optNcls{80, 90, 100}; + + const std::array optCPA{0.985f, 0.99f, 0.995f}; + const std::array optRad{0.50f, 0.80f, 1.00f}; + const std::array optDcaDD{1.00f, 0.90f, 0.80f}; + const std::array optDcaV0{0.30f, 0.20f, 0.15f}; + const std::array optLife{20.f, 16.f, 18.f}; + const std::array optDcaD1{0.05f, 0.06f, 0.08f}; + const std::array optDcaD2{0.05f, 0.06f, 0.08f}; + + // PID modes: also allow default (0) to appear in random variations + const std::array optPidPi{0, 1, 2}; + const std::array optPidK{0, 1, 2}; + const std::array optPidP{0, 1, 2}; + + // Helper: build SysCuts from chosen indices (0..2) + auto buildFromIdx = [&](int i0, int i1, int i2, int i3, + int i4, int i5, int i6, int i7, int i8, int i9, int i10, + int i11, int i12, int i13) -> SysCuts { + SysCuts c{}; + c.maxDcaxy = optDcaxy[i0]; + c.maxDcaz = optDcaz[i1]; + c.minTPCCrossedRows = optNcrs[i2]; + c.minTPCClusters = optNcls[i3]; + + c.minCPA = optCPA[i4]; + c.minRadius = optRad[i5]; + c.maxDcaDaughters = optDcaDD[i6]; + c.maxDcaV0 = optDcaV0[i7]; + c.maxLifetime = optLife[i8]; + c.minDcaD1 = optDcaD1[i9]; + c.minDcaD2 = optDcaD2[i10]; + + c.pidPi = optPidPi[i11]; + c.pidK = optPidK[i12]; + c.pidP = optPidP[i13]; + return c; + }; + + // sysId=0 must be strict default (all indices = 0) + SysCuts def = buildFromIdx(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + std::mt19937 rng(sysSeed); + std::uniform_int_distribution pick012(0, 2); + + // Optional: keep unique combinations (by packing indices in 2 bits each) + auto packCode = [&](const std::array& idx) -> uint32_t { + uint32_t code = 0u; + for (int k = 0; k < 14; ++k) { + code |= (uint32_t(idx[k] & 0x3) << (2 * k)); + } + return code; + }; + + sysCuts.clear(); + sysCuts.reserve(1 + (size_t)nSysRand); + sysCuts.push_back(def); // sysId=0 + + std::unordered_set used; + used.reserve((size_t)nSysRand * 2); + used.insert(0u); // all-default code + + const int nPick = std::max(0, (int)nSysRand); + while ((int)sysCuts.size() < 1 + nPick) { + + std::array idx{}; + for (int k = 0; k < 14; ++k) + idx[k] = pick012(rng); + + uint32_t code = packCode(idx); + if (!used.insert(code).second) + continue; // already have this combination + + // (optional) avoid generating exactly default again + if (code == 0u) + continue; + + sysCuts.push_back(buildFromIdx( + idx[0], idx[1], idx[2], idx[3], + idx[4], idx[5], idx[6], idx[7], idx[8], idx[9], idx[10], + idx[11], idx[12], idx[13])); + } + + nSysTotal = (int)sysCuts.size(); + } + + // ------------------------- + // Helpers for systematics selections + // ------------------------- + inline bool passPrimary(float dcaxy, float dcaz, float ncrs, float ncls, const SysCuts& c) const + { + if (std::abs(dcaxy) > c.maxDcaxy) + return false; + if (std::abs(dcaz) > c.maxDcaz) + return false; + if ((int)ncrs < c.minTPCCrossedRows) + return false; + if ((int)ncls < c.minTPCClusters) + return false; + return true; + } + + inline bool passV0(const aod::F1Tracks::iterator& t, const SysCuts& c) const + { + if (t.k0Cpa() < c.minCPA) + return false; + if (t.k0Radius() < c.minRadius) + return false; + if (t.k0DcaDaughters() > c.maxDcaDaughters) + return false; + if (t.k0Dca() > c.maxDcaV0) + return false; + if (t.k0LifeTime() > c.maxLifetime) + return false; + if (std::abs(t.k0D1Dcaxy()) < c.minDcaD1) + return false; + if (std::abs(t.k0D2Dcaxy()) < c.minDcaD2) + return false; + + return true; + } + + // PID dispatchers + inline bool passPionPID(int pidMode, + const aod::F1Tracks::iterator& f1track, + const TLorentzVector& pion, + float maxMomPi) const + { + // pidMode: + // 0 = default: no TOF -> |TPC|<2.5 ; with TOF -> sqrt(TPC^2 + TOF^2)<2.5 + // 1 = syst-1: same but use 2.0 instead of 2.5 everywhere + // 2 = syst-2: no TOF -> |TPC|<2.0 ; with TOF -> sqrt(TPC^2 + TOF^2)<2.5 + + if (pion.Pt() > maxMomPi) { + return false; + } + + const float nsTPC = f1track.f1d1TPC(); + const float nsTOF = f1track.pionTOF(); // TOF nσ stored in reduced table + + const float cutNoTOF = (pidMode == 0) ? 2.5f : 2.0f; // mode0:2.5, mode1:2.0, mode2:2.0 + const float cutWithTOF = (pidMode == 1) ? 2.0f : 2.5f; // mode0:2.5, mode1:2.0, mode2:2.5 + + if (f1track.f1d1TOFHit() != 1) { + return (std::abs(nsTPC) < cutNoTOF); + } + return (std::abs(nsTPC) < cutNoTOF && std::abs(nsTOF) < cutWithTOF); + // const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + // return (comb < cutWithTOF); + } + inline bool passKaonPID(int pidMode, + const aod::F1Tracks::iterator& f1track, + const TLorentzVector& kaon, + float maxMomK) const + { + // pidMode: + // 0 = default: no TOF -> momentum-dependent TPC cut (original ladder) with TOF -> circular cut sqrt(TPC^2 + TOF^2) < 2.5 + // 1 = syst-1: same, but use 2.0 instead of 2.5 everywhere (including ladder upper edges) + // 2 = syst-2: no TOF -> ladder with "tight" = 2.0 (upper edges also 2.0) + // with TOF -> circular cut < 2.5 + + if (kaon.Pt() > maxMomK) { + return false; + } + + const float nsTPC = f1track.f1d2TPC(); + const float nsTOF = f1track.kaonTOF(); // TOF nσ stored in reduced table + + const float cutNoTOFBase = (pidMode == 0) ? 2.5f : 2.0f; // mode0:2.5, mode1/2:2.0 + const float cutWithTOF = (pidMode == 1) ? 2.0f : 2.5f; // mode0:2.5, mode1:2.0, mode2:2.5 + + // --- no TOF: momentum-dependent TPC ladder + if (f1track.f1d2TOFHit() != 1) { + const float pt = kaon.Pt(); + + if (pt <= 0.5f) { + if (nsTPC < -cutNoTOFBase || nsTPC > cutNoTOFBase) + return false; + } else if (pt <= 0.7f) { + const float low = -1.5f; + const float high = cutNoTOFBase; // original high=+2.5 + if (nsTPC < low || nsTPC > high) + return false; + } else if (pt <= 1.0f) { + const float low = -1.0f; + const float high = cutNoTOFBase; // original high=+2.5 + if (nsTPC < low || nsTPC > high) + return false; + } else { + if (nsTPC < -cutNoTOFBase || nsTPC > cutNoTOFBase) + return false; + } + return true; + } + return (std::abs(nsTPC) < cutNoTOFBase && std::abs(nsTOF) < cutWithTOF); + // --- TOF available: circular cut in (TPC,TOF) nσ plane + // const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + // return (comb < cutWithTOF); + } + inline bool passProtonPID(int pidMode, + const aod::ProtonTracks::iterator& ptrack, + const TLorentzVector& proton, + float pMin, + float pMax, + float pTofThr) const + { + // pidMode: + // 0 = default: p < thr -> |TPC| < 2.5 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.0 + // 1 = syst-1: p < thr -> |TPC| < 2.0 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.0 + // 2 = syst-2: p < thr -> |TPC| < 2.5 ; p >= thr -> TOF mandatory AND circular(TPC,TOF) < 2.5 + + if (proton.Pt() > pMax || proton.Pt() < pMin) { + return false; + } + + const float cutTPC = + (pidMode == 1) ? 2.0f : 2.5f; // mode0:2.5, mode1:2.0, mode2:2.5 + const float cutCircle = + (pidMode == 2) ? 2.0f : 2.5f; // mode0:2.5, mode1:2.5, mode2:2.0 + + // below threshold: TPC-only + if (proton.P() < pTofThr) { + return (std::abs(ptrack.protonNsigmaTPC()) < cutTPC); + } + + // above threshold: TOF must exist + if (ptrack.protonTOFHit() != 1) { + return false; + } + + // circular cut in (TPC,TOF) + const float nsTPC = ptrack.protonNsigmaTPC(); + const float nsTOF = ptrack.protonNsigmaTOF(); + return (std::abs(nsTPC) < cutTPC && std::abs(nsTOF) < cutCircle); + // const float comb = std::sqrt(nsTPC * nsTPC + nsTOF * nsTOF); + // return (comb < cutCircle); + } + // Initialize the ananlysis task void init(o2::framework::InitContext&) { - colBinningFemto = {{CfgVtxBins, CfgMultBins}, true}; + buildSystematicCuts(); + nSysTotal = (int)sysCuts.size(); // or whatever vector you fill + LOGF(info, "sysCuts.size()=%zu nSysTotal=%d", sysCuts.size(), nSysTotal); + const AxisSpec thnAxisSys{nSysTotal, -0.5f, float(nSysTotal) - 0.5f, "sysId"}; const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; const AxisSpec thnAxisPt{configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisMt{configThnAxisMt, "#it{M}_{T} (GeV/#it{c})"}; const AxisSpec thnAxisPtProton{configThnAxisPtProton, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec thnAxisKstar{configThnAxisKstar, "#it{k}^{*} (GeV/#it{c})"}; const AxisSpec thnAxisNsigma{configThnAxisNsigma, "NsigmaCombined"}; const AxisSpec thnAxisCharge{configThnAxisCharge, "Charge"}; - const AxisSpec thnAxisMultiplicity{CfgMultBins, "Multiplicity"}; + const AxisSpec thnAxisMultiplicity{configThnAxisMultiplicity, "Multiplicity"}; // register histograms - histos.add("hPhaseSpaceProtonKaonSame", "hPhaseSpaceProtonKaonSame", kTH3F, {{40, -2.0f, 2.0f}, {180, -2.0 * TMath::Pi(), 2.0 * TMath::Pi()}, {100, 0.0, 1.0}}); - histos.add("hPhaseSpaceProtonPionSame", "hPhaseSpaceProtonPionSame", kTH3F, {{40, -2.0f, 2.0f}, {180, -2.0 * TMath::Pi(), 2.0 * TMath::Pi()}, {100, 0.0, 1.0}}); - histos.add("hPhaseSpaceProtonKaonMix", "hPhaseSpaceProtonKaonMix", kTH3F, {{40, -2.0f, 2.0f}, {180, -2.0 * TMath::Pi(), 2.0 * TMath::Pi()}, {100, 0.0, 1.0}}); - histos.add("hPhaseSpaceProtonPionMix", "hPhaseSpaceProtonPionMix", kTH3F, {{40, -2.0f, 2.0f}, {180, -2.0 * TMath::Pi(), 2.0 * TMath::Pi()}, {100, 0.0, 1.0}}); + histos.add("hPhaseSpaceProtonKaonSame", "hPhaseSpaceProtonKaonSame", kTH3F, {{100, -0.3f, 0.3f}, {100, -0.3, 0.3}, {10, 0.0, 1.0}}); + histos.add("hPhaseSpaceProtonPionSame", "hPhaseSpaceProtonPionSame", kTH3F, {{100, -0.3f, 0.3f}, {100, -0.3, 0.3}, {10, 0.0, 1.0}}); + histos.add("hPhaseSpaceProtonKaonMix", "hPhaseSpaceProtonKaonMix", kTH3F, {{100, -0.3f, 0.3f}, {100, -0.3, 0.3}, {10, 0.0, 1.0}}); + histos.add("hPhaseSpaceProtonPionMix", "hPhaseSpaceProtonPionMix", kTH3F, {{100, -0.3f, 0.3f}, {100, -0.3, 0.3}, {10, 0.0, 1.0}}); - histos.add("hNsigmaProtonTPC", "Nsigma Proton TPC distribution", kTH2F, {{100, -5.0f, 5.0f}, {100, 0.0f, 10.0f}}); + histos.add("hNsigmaProtonTPC", "Nsigma Proton TPC distribution", kTH3F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}, {100, 0.0f, 10.0f}}); histos.add("hNsigmaKaonTPC", "Nsigma Kaon TPC distribution", kTH2F, {{100, -5.0f, 5.0f}, {100, 0.0f, 10.0f}}); histos.add("hNsigmaPionTPC", "Nsigma Pion TPC distribution", kTH2F, {{100, -5.0f, 5.0f}, {100, 0.0f, 10.0f}}); histos.add("hNsigmaPionKaonTPC", "Nsigma Pion Kaon TPC correlation", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); histos.add("h2SameEventPtCorrelation", "Pt correlation of F1 and proton", kTH3F, {{100, 0.0f, 1.0f}, {100, 0.0, 10.0}, {100, 0.0, 10.0}}); + histos.add("h2SameEventf1pptCorrelation", "h2SameEventf1pptCorrelation", kTH3F, {{100, 1.0, 1.4}, {300, 0.0f, 3.0f}, {100, 0.0, 10.0}}); + histos.add("h2SameEventInvariantMassUnlike_mass_SYS", "SE unlike (SYS)", kTHnSparseF, {thnAxisSys, thnAxisKstar, thnAxisMt, thnAxisInvMass, thnAxisMultiplicity}); + histos.add("h2SameEventInvariantMassLike_mass_SYS", "SE like (SYS)", kTHnSparseF, {thnAxisSys, thnAxisKstar, thnAxisMt, thnAxisInvMass, thnAxisMultiplicity}); + histos.add("h2MixEventInvariantMassUnlike_mass_SYS", "ME unlike (SYS)", kTHnSparseF, {thnAxisSys, thnAxisKstar, thnAxisMt, thnAxisInvMass, thnAxisMultiplicity}); + histos.add("h2MixEventInvariantMassLike_mass_SYS", "ME like (SYS)", kTHnSparseF, {thnAxisSys, thnAxisKstar, thnAxisMt, thnAxisInvMass, thnAxisMultiplicity}); - histos.add("h2SameEventInvariantMassUnlike_mass", "Unlike Sign Invariant mass of f1 same event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); - histos.add("h2SameEventInvariantMassLike_mass", "Like Sign Invariant mass of f1 same event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); - histos.add("h2SameEventInvariantMassRot_mass", "Rotational Invariant mass of f1 same event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); + if (doold) { + histos.add("h2SameEventInvariantMassUnlike_mass", "Unlike Sign Invariant mass of f1 same event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); + histos.add("h2SameEventInvariantMassLike_mass", "Like Sign Invariant mass of f1 same event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); + histos.add("h2SameEventInvariantMassRot_mass", "Rotational Invariant mass of f1 same event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); - histos.add("h2MixEventInvariantMassUnlike_mass", "Unlike Sign Invariant mass of f1 mix event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); - histos.add("h2MixEventInvariantMassLike_mass", "Like Sign Invariant mass of f1 mix event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); - histos.add("h2MixEventInvariantMassRot_mass", "Rotational Sign Invariant mass of f1 mix event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); - - histos.add("h2MixEventInvariantMassUnlike_mass_SEFP", "Unlike-sign invariant mass of f1 mix event (SE-F1P: π mixed, p same event)", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); - histos.add("h2MixEventInvariantMassUnlike_mass_DEFP", "Unlike-sign invariant mass of f1 mix event (DE-F1P: π + p mixed)", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); + histos.add("h2MixEventInvariantMassUnlike_mass", "Unlike Sign Invariant mass of f1 mix event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); + histos.add("h2MixEventInvariantMassLike_mass", "Like Sign Invariant mass of f1 mix event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge, thnAxisMultiplicity}); + histos.add("h2MixEventInvariantMassRot_mass", "Rotational Sign Invariant mass of f1 mix event", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); + histos.add("h2MixEventInvariantMassUnlike_mass_SEFP", "Unlike-sign invariant mass of f1 mix event (SE-F1P: π mixed, p same event)", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); + histos.add("h2MixEventInvariantMassUnlike_mass_DEFP", "Unlike-sign invariant mass of f1 mix event (DE-F1P: π + p mixed)", kTHnSparseF, {thnAxisKstar, thnAxisPt, thnAxisInvMass, thnAxisCharge}); + } if (fillSparse) { histos.add("SEMassUnlike", "SEMassUnlike", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisPtProton, thnAxisKstar, thnAxisNsigma, thnAxisCharge}); histos.add("SEMassLike", "SEMassLike", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisPtProton, thnAxisKstar, thnAxisNsigma, thnAxisCharge}); @@ -142,7 +439,6 @@ struct f1protoncorrelation { histos.add("MEMassLike", "MEMassLike", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisPtProton, thnAxisKstar, thnAxisNsigma, thnAxisCharge}); histos.add("MEMassRot", "MEMassRot", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisPtProton, thnAxisKstar, thnAxisNsigma, thnAxisCharge}); } - ccdb->setURL(cfgCcdbParam.cfgURL); ccdbApi.init("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -219,6 +515,14 @@ struct f1protoncorrelation { trackRelK = PartOneCMS - PartTwoCMS; return 0.5 * trackRelK.P(); } + + float getmT(const TLorentzVector part1, const TLorentzVector part2) + { + trackSum = part1 + part2; + float kT = 0.5 * trackSum.Pt(); + return std::sqrt((kT * kT) + 0.25 * (part1.M() + part2.M()) * (part1.M() + part2.M())); + } + float combinedTPC; TLorentzVector F1, Proton, F1ProtonPair, Pion, Kaon, Kshort; TLorentzVector F1Rot, PionRot, KaonKshortPair; @@ -227,7 +531,7 @@ struct f1protoncorrelation { int currentRunNumber = -999; int lastRunNumber = -999; - void process(aod::RedF1PEvents::iterator const& collision, aod::F1Tracks const& f1tracks, aod::ProtonTracks const& protontracks) + void processSE(aod::RedF1PEvents::iterator const& collision, aod::F1Tracks const& f1tracks, aod::ProtonTracks const& protontracks) { // auto bc = collision.template bc_as(); @@ -304,10 +608,10 @@ struct f1protoncorrelation { } auto relative_momentum = getkstar(F1, Proton); if (relative_momentum <= 0.5) { - histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), Proton.Pt()); + histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), protontrack.protonNsigmaTOF(), Proton.Pt()); } histos.fill(HIST("h2SameEventPtCorrelation"), relative_momentum, F1.Pt(), Proton.Pt()); - + auto mT = getmT(F1, Proton); if (f1track.f1SignalStat() > 0) { // check charge float pairCharge = f1track.f1SignalStat() * protontrack.protonCharge(); @@ -318,9 +622,13 @@ struct f1protoncorrelation { pionCharge = 1; kaonCharge = -1; } - histos.fill(HIST("hPhaseSpaceProtonKaonSame"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, protontrack.protonCharge(), kaonCharge, bz, bz), relative_momentum); // Phase Space Proton kaon - histos.fill(HIST("hPhaseSpaceProtonPionSame"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, protontrack.protonCharge(), pionCharge, bz, bz), relative_momentum); // Phase Space Proton Pion - histos.fill(HIST("h2SameEventInvariantMassUnlike_mass"), relative_momentum, F1.Pt(), F1.M(), pairCharge, collision.numContrib()); // F1 sign = 1 unlike, F1 sign = -1 like + if (kaonCharge == protontrack.protonCharge()) + histos.fill(HIST("hPhaseSpaceProtonKaonSame"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, protontrack.protonCharge(), kaonCharge, bz, bz), relative_momentum); // Phase Space Proton kaon + if (pionCharge == protontrack.protonCharge()) + histos.fill(HIST("hPhaseSpaceProtonPionSame"), Proton.Eta() - Pion.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, protontrack.protonCharge(), pionCharge, bz, bz), relative_momentum); // Phase Space Proton Pionsyst + + histos.fill(HIST("h2SameEventInvariantMassUnlike_mass"), relative_momentum, F1.Pt(), F1.M(), pairCharge, collision.numContrib()); // F1 sign = 1 unlike, F1 sign = -1 like + histos.fill(HIST("h2SameEventInvariantMassUnlike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision.numContrib()); if (fillSparse) { histos.fill(HIST("SEMassUnlike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, pairCharge); } @@ -346,6 +654,7 @@ struct f1protoncorrelation { } } if (f1track.f1SignalStat() == -1) { + histos.fill(HIST("h2SameEventInvariantMassLike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision.numContrib()); histos.fill(HIST("h2SameEventInvariantMassLike_mass"), relative_momentum, F1.Pt(), F1.M(), protontrack.protonCharge(), collision.numContrib()); if (fillSparse) { histos.fill(HIST("SEMassLike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, protontrack.protonCharge()); @@ -354,7 +663,7 @@ struct f1protoncorrelation { } } } - + PROCESS_SWITCH(f1protoncorrelation, processSE, "Process same event", false); // Processing Event Mixing SliceCache cache; using BinningType = ColumnBinningPolicy; @@ -591,6 +900,7 @@ struct f1protoncorrelation { continue; } auto relative_momentum = getkstar(F1, Proton); + auto mT = getmT(F1, Proton); if (t1.f1SignalStat() > 0) { float pairCharge = t1.f1SignalStat() * t2.protonCharge(); int f1Charge = t1.f1SignalStat(); @@ -600,9 +910,10 @@ struct f1protoncorrelation { pionCharge = 1; kaonCharge = -1; } + histos.fill(HIST("h2MixEventInvariantMassUnlike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision1.numContrib()); histos.fill(HIST("h2MixEventInvariantMassUnlike_mass"), relative_momentum, F1.Pt(), F1.M(), pairCharge, collision1.numContrib()); // F1 sign = 1 unlike, F1 sign = -1 like histos.fill(HIST("hPhaseSpaceProtonKaonMix"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, t2.protonCharge(), kaonCharge, bz, bz2), relative_momentum); // Phase Space Proton kaon - histos.fill(HIST("hPhaseSpaceProtonPionMix"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, t2.protonCharge(), pionCharge, bz, bz2), relative_momentum); // Phase Space Proton Pion + histos.fill(HIST("hPhaseSpaceProtonPionMix"), Proton.Eta() - Pion.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, t2.protonCharge(), pionCharge, bz, bz2), relative_momentum); // Phase Space Proton Pion if (fillSparse) { histos.fill(HIST("MEMassUnlike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, pairCharge); } @@ -631,6 +942,7 @@ struct f1protoncorrelation { } } if (t1.f1SignalStat() == -1) { + histos.fill(HIST("h2MixEventInvariantMassLike_mass_SYS"), 0, relative_momentum, mT, F1.M(), collision1.numContrib()); histos.fill(HIST("h2MixEventInvariantMassLike_mass"), relative_momentum, F1.Pt(), F1.M(), t2.protonCharge(), collision1.numContrib()); if (fillSparse) { histos.fill(HIST("MEMassLike"), F1.M(), F1.Pt(), Proton.Pt(), relative_momentum, combinedTPC, t2.protonCharge()); @@ -640,6 +952,244 @@ struct f1protoncorrelation { } } PROCESS_SWITCH(f1protoncorrelation, processMEOpti, "Process EventMixing for combinatorial background Optimal", false); + + void processSys(aod::RedF1PEvents::iterator const& collision, + aod::F1Tracks const& f1tracks, + aod::ProtonTracks const& protontracks) + { + const float maxMomPi = maxMomentumPion; + const float maxMomK = maxMomentumKaon; + // const float pTofPiMin = momentumTOFPionMin; + // const float pTofPiMax = momentumTOFPionMax; + // const float pTofKMin = momentumTOFKaonMin; + // const float pTofKMax = momentumTOFKaonMax; + const float pTofP = momentumTOFProton; + const float pMaxP = momentumProtonMax; + const float pMinP = momentumProtonMin; + + currentRunNumber = collision.runNumber(); + if (currentRunNumber != lastRunNumber) { + bz = getMagneticField(collision.timestamp()); + } + lastRunNumber = currentRunNumber; + auto countf1 = 0; + + for (auto f1track : f1tracks) { + + if (f1track.f1MassKaonKshort() > maxKKS0Mass) + continue; + + F1.SetXYZM(f1track.f1Px(), f1track.f1Py(), f1track.f1Pz(), f1track.f1Mass()); + Pion.SetXYZM(f1track.f1d1Px(), f1track.f1d1Py(), f1track.f1d1Pz(), 0.139); + Kaon.SetXYZM(f1track.f1d2Px(), f1track.f1d2Py(), f1track.f1d2Pz(), 0.493); + Kshort.SetXYZM(f1track.f1d3Px(), f1track.f1d3Py(), f1track.f1d3Pz(), 0.497); + KaonKshortPair = Kaon + Kshort; + if (F1.Pt() < lowPtF1 || F1.Pt() > 50.0) + continue; + std::vector activeSys; + activeSys.reserve((size_t)nSysTotal); + + for (int sysId = 0; sysId < nSysTotal; ++sysId) { + const auto& sc = sysCuts[sysId]; + // Primary π + if (!passPrimary(f1track.pionDcaxy(), f1track.pionDcaz(), + f1track.pionTPCNcrs(), f1track.pionTPCNcls(), sc)) + continue; + // Primary K + if (!passPrimary(f1track.kaonDcaxy(), f1track.kaonDcaz(), + f1track.kaonTPCNcrs(), f1track.kaonTPCNcls(), sc)) + continue; + // V0 (K0s) + if (!passV0(f1track, sc)) + continue; + + if (!passPionPID(sc.pidPi, f1track, Pion, maxMomPi)) + continue; + if (!passKaonPID(sc.pidK, f1track, Kaon, maxMomK)) + continue; + if (sysId == 0) { + histos.fill(HIST("hNsigmaKaonTPC"), f1track.f1d2TPC(), Kaon.Pt()); + histos.fill(HIST("hNsigmaPionTPC"), f1track.f1d1TPC(), Pion.Pt()); + histos.fill(HIST("hNsigmaPionKaonTPC"), f1track.f1d1TPC(), f1track.f1d2TPC()); + countf1 = countf1 + 1; + } + activeSys.push_back(sysId); + } + + if (activeSys.empty()) + continue; + + // Proton loop + for (auto protontrack : protontracks) { + Proton.SetXYZM(protontrack.protonPx(), protontrack.protonPy(), protontrack.protonPz(), 0.938); + + if ((f1track.f1PionIndex() == protontrack.f1ProtonIndex()) || + (f1track.f1KaonIndex() == protontrack.f1ProtonIndex()) || + (f1track.f1KshortPositiveIndex() == protontrack.f1ProtonIndex()) || + (f1track.f1KshortNegativeIndex() == protontrack.f1ProtonIndex())) + continue; + + const auto& sc0 = sysCuts[0]; + + if (countf1 && passPrimary(protontrack.protonDcaxy(), protontrack.protonDcaz(), protontrack.protonTPCNcrs(), protontrack.protonTPCNcls(), sc0) && passProtonPID(0, protontrack, Proton, pMinP, pMaxP, pTofP)) { + histos.fill(HIST("hNsigmaProtonTPC"), protontrack.protonNsigmaTPC(), protontrack.protonNsigmaTOF(), Proton.Pt()); + } + + // physics variables + auto relative_momentum = getkstar(F1, Proton); + auto mT = getmT(F1, Proton); + + std::vector activePair; + activePair.reserve(activeSys.size()); + + for (int sysId : activeSys) { + const auto& sc = sysCuts[sysId]; + + if (!passPrimary(protontrack.protonDcaxy(), protontrack.protonDcaz(), + protontrack.protonTPCNcrs(), protontrack.protonTPCNcls(), sc)) + continue; + + if (!passProtonPID(sc.pidP, protontrack, Proton, pMinP, pMaxP, pTofP)) + continue; + if (sysId == 0) { + int f1Charge = f1track.f1SignalStat(); + int pionCharge = -1; + int kaonCharge = 1; + if (f1Charge == 2) { + pionCharge = 1; + kaonCharge = -1; + } + if (kaonCharge == protontrack.protonCharge()) + histos.fill(HIST("hPhaseSpaceProtonKaonSame"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, protontrack.protonCharge(), kaonCharge, bz, bz), relative_momentum); // Phase Space Proton kaon + if (pionCharge == protontrack.protonCharge()) + histos.fill(HIST("hPhaseSpaceProtonPionSame"), Proton.Eta() - Pion.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, protontrack.protonCharge(), pionCharge, bz, bz), relative_momentum); // Phase Space Proton Pion + histos.fill(HIST("h2SameEventf1pptCorrelation"), F1.M(), relative_momentum, Proton.Pt()); + } + activePair.push_back(sysId); + } + if (activePair.empty()) + continue; + if (f1track.f1SignalStat() > 0) { + for (int sysId : activePair) { + histos.fill(HIST("h2SameEventInvariantMassUnlike_mass_SYS"), sysId, relative_momentum, mT, F1.M(), collision.numContrib()); + } + } + if (f1track.f1SignalStat() == -1) { + for (int sysId : activePair) { + histos.fill(HIST("h2SameEventInvariantMassLike_mass_SYS"), sysId, relative_momentum, mT, F1.M(), collision.numContrib()); + } + } + } + } + } + PROCESS_SWITCH(f1protoncorrelation, processSys, "Process SAME-EVENT with systematics (sysId axis, default + random)", false); + + void processMESysOpti(aod::RedF1PEvents& collisions, + aod::F1Tracks& f1tracks, + aod::ProtonTracks& protontracks) + { + const float maxMomPi = maxMomentumPion; + const float maxMomK = maxMomentumKaon; + + // const float pTofPiMin = momentumTOFPionMin; + // const float pTofPiMax = momentumTOFPionMax; + // const float pTofKMin = momentumTOFKaonMin; + // const float pTofKMax = momentumTOFKaonMax; + + const float pTofP = momentumTOFProton; + const float pMaxP = momentumProtonMax; + const float pMinP = momentumProtonMin; + // const bool doPdep = pdepPID; + + for (auto const& [collision1, collision2] : selfCombinations(colBinning, nEvtMixing, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) + continue; + + currentRunNumber = collision1.runNumber(); + if (currentRunNumber != lastRunNumber) { + bz = getMagneticField(collision1.timestamp()); + bz2 = getMagneticField(collision2.timestamp()); + } + lastRunNumber = currentRunNumber; + + auto groupF1 = f1tracks.sliceBy(tracksPerCollisionPresliceF1, collision1.globalIndex()); + auto groupProton = protontracks.sliceBy(tracksPerCollisionPresliceP, collision2.globalIndex()); + + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupF1, groupProton))) { + + if (t1.f1MassKaonKshort() > maxKKS0Mass) + continue; + + // 4-vectors + F1.SetXYZM(t1.f1Px(), t1.f1Py(), t1.f1Pz(), t1.f1Mass()); + Pion.SetXYZM(t1.f1d1Px(), t1.f1d1Py(), t1.f1d1Pz(), 0.139); + Kaon.SetXYZM(t1.f1d2Px(), t1.f1d2Py(), t1.f1d2Pz(), 0.493); + Kshort.SetXYZM(t1.f1d3Px(), t1.f1d3Py(), t1.f1d3Pz(), 0.497); + KaonKshortPair = Kaon + Kshort; + Proton.SetXYZM(t2.protonPx(), t2.protonPy(), t2.protonPz(), 0.938); + if (F1.Pt() < lowPtF1 || F1.Pt() > 50.0) + continue; + auto relative_momentum = getkstar(F1, Proton); + auto mT = getmT(F1, Proton); + // sys list for this (F1, p) pair + std::vector activePair; + activePair.reserve((size_t)nSysTotal); + + for (int sysId = 0; sysId < nSysTotal; ++sysId) { + const auto& sc = sysCuts[sysId]; + + // π/K primary + if (!passPrimary(t1.pionDcaxy(), t1.pionDcaz(), t1.pionTPCNcrs(), t1.pionTPCNcls(), sc)) + continue; + if (!passPrimary(t1.kaonDcaxy(), t1.kaonDcaz(), t1.kaonTPCNcrs(), t1.kaonTPCNcls(), sc)) + continue; + + // V0 cuts + if (!passV0(t1, sc)) + continue; + + // PID (F1 side) + if (!passPionPID(sc.pidPi, t1, Pion, maxMomPi)) + continue; + if (!passKaonPID(sc.pidK, t1, Kaon, maxMomK)) + continue; + + // proton primary + PID + if (!passPrimary(t2.protonDcaxy(), t2.protonDcaz(), t2.protonTPCNcrs(), t2.protonTPCNcls(), sc)) + continue; + if (!passProtonPID(sc.pidP, t2, Proton, pMinP, pMaxP, pTofP)) + continue; + activePair.push_back(sysId); + if (sysId == 0) { + int f1Charge = t1.f1SignalStat(); + int pionCharge = -1; + int kaonCharge = 1; + if (f1Charge == 2) { + pionCharge = 1; + kaonCharge = -1; + } + if (kaonCharge == t2.protonCharge()) + histos.fill(HIST("hPhaseSpaceProtonKaonMix"), Proton.Eta() - Kaon.Eta(), PhiAtSpecificRadiiTPC(Proton, Kaon, t2.protonCharge(), kaonCharge, bz, bz), relative_momentum); // Phase Space Proton kaon + if (pionCharge == t2.protonCharge()) + histos.fill(HIST("hPhaseSpaceProtonPionMix"), Proton.Eta() - Pion.Eta(), PhiAtSpecificRadiiTPC(Proton, Pion, t2.protonCharge(), pionCharge, bz, bz), relative_momentum); // Phase Space Proton Pion + } + } + if (activePair.empty()) + continue; + if (t1.f1SignalStat() > 0) { + for (int sysId : activePair) { + histos.fill(HIST("h2MixEventInvariantMassUnlike_mass_SYS"), sysId, relative_momentum, mT, F1.M(), collision1.numContrib()); + } + } + if (t1.f1SignalStat() == -1) { + for (int sysId : activePair) { + histos.fill(HIST("h2MixEventInvariantMassLike_mass_SYS"), sysId, relative_momentum, mT, F1.M(), collision1.numContrib()); + } + } + } + } + } + PROCESS_SWITCH(f1protoncorrelation, processMESysOpti, "Process MIX-EVENT OPTI with systematics (sysId axis, default + random)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/Resonances/heptaquark.cxx b/PWGLF/Tasks/Resonances/heptaquark.cxx index 407c3199073..824c39601ac 100644 --- a/PWGLF/Tasks/Resonances/heptaquark.cxx +++ b/PWGLF/Tasks/Resonances/heptaquark.cxx @@ -12,28 +12,33 @@ /// \brief this is a starting point for the Resonances tutorial /// \author junlee kim +#include "PWGLF/DataModel/ReducedHeptaQuarkTables.h" + +#include "Common/Core/trackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include -#include + #include -#include #include +#include +#include #include #include + #include + +#include #include #include #include #include -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/ReducedHeptaQuarkTables.h" -#include "CommonConstants/PhysicsConstants.h" - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -47,14 +52,23 @@ struct heptaquark { Configurable cfgPIDStrategy{"cfgPIDStrategy", 3, "PID strategy 1"}; Configurable cfgPIDPrPi{"cfgPIDPrPi", 3, "PID selection for proton and pion"}; - Configurable minPhiMass{"minPhiMass", 1.01, "Minimum phi mass"}; - Configurable maxPhiMass{"maxPhiMass", 1.03, "Maximum phi mass"}; + Configurable cfgMinPhiMass{"cfgMinPhiMass", 1.01, "Minimum phi mass"}; + Configurable cfgMaxPhiMass{"cfgMaxPhiMass", 1.03, "Maximum phi mass"}; + + Configurable cfgMinLambdaMass{"cfgMinLambdaMass", 1.1, "Minimum lambda mass"}; + Configurable cfgMaxLambdaMass{"cfgMaxLambdaMass", 1.13, "Maximum lambda mass"}; + + Configurable cfgNsigmaTPC{"cfgNsigmaTPC", 2.5, "nsigma cut TPC"}; + Configurable cfgNsigmaTOF{"cfgNsigmaTOF", 3.0, "nsigma cut TOF"}; - Configurable minLambdaMass{"minLambdaMass", 1.1, "Minimum lambda mass"}; - Configurable maxLambdaMass{"maxLambdaMass", 1.13, "Maximum lambda mass"}; + Configurable cfgSelectHQ{"cfgSelectHQ", true, "switch to select HQ"}; - Configurable cutNsigmaTPC{"cutNsigmaTPC", 2.5, "nsigma cut TPC"}; - Configurable cutNsigmaTOF{"cutNsigmaTOF", 3.0, "nsigma cut TOF"}; + Configurable cfgMinPhiPt{"cfgMinPhiPt", 0.2, "Minimum phi pt"}; + Configurable cfgMinLambdaPt{"cfgMinLambdaPt", 0.5, "Minimum lambda pt"}; + + Configurable cfgSoftFraction{"cfgSoftFraction", 0.01, "Minimum allowed softest fraction"}; + Configurable cfgCollinear{"cfgCollinear", 0.98, "Maximum allowed collinear selection"}; + Configurable cfgCosPoint{"cfgCosPoint", 0.95, "Minimum pointing angle selection"}; ConfigurableAxis massAxis{"massAxis", {600, 2.8, 3.4}, "Invariant mass axis"}; ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.5, 8.0, 10.0, 100.0}, "Transverse momentum bins"}; @@ -84,6 +98,18 @@ struct heptaquark { histos.add("hDalitzRot", "hDalitzRot", {HistType::kTHnSparseF, {massPPAxis, massPLAxis, massAxis, ptAxis, {2, -0.5f, 1.5f}, centAxis}}); } + template + static inline TLorentzVector makeP4FromHQRow(HQRow const& hq) + { + const double px = hq.hqPx(); + const double py = hq.hqPy(); + const double pz = hq.hqPz(); + const double m = hq.hqMass(); + TLorentzVector v; + v.SetXYZM(px, py, pz, m); + return v; + } + double massLambda = o2::constants::physics::MassLambda; double massPr = o2::constants::physics::MassProton; double massPi = o2::constants::physics::MassPionCharged; @@ -95,76 +121,76 @@ struct heptaquark { { if (PIDStrategy == 0) { if (TOFHit != 1) { - if (TMath::Abs(nsigmaTPC) < cutNsigmaTPC) { + if (TMath::Abs(nsigmaTPC) < cfgNsigmaTPC) { return true; } } if (TOFHit == 1) { - if (TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } } } if (PIDStrategy == 1) { if (ptcand < 0.5) { - if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cutNsigmaTPC) { + if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cfgNsigmaTPC) { return true; } - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } } if (ptcand >= 0.5) { - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } } } if (PIDStrategy == 2) { if (ptcand < 0.5) { - if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cutNsigmaTPC) { + if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cfgNsigmaTPC) { return true; } - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } } if (ptcand >= 0.5 && ptcand < 1.2) { - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } - if (TOFHit != 1 && nsigmaTPC > -1.5 && nsigmaTPC < cutNsigmaTPC) { + if (TOFHit != 1 && nsigmaTPC > -1.5 && nsigmaTPC < cfgNsigmaTPC) { return true; } } if (ptcand >= 1.2) { - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } - if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cutNsigmaTPC) { + if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cfgNsigmaTPC) { return true; } } } if (PIDStrategy == 3) { if (ptcand < 0.5) { - if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cutNsigmaTPC) { + if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cfgNsigmaTPC) { return true; } - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } } if (ptcand >= 0.5 && ptcand < 1.2) { - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } } if (ptcand >= 1.2) { - if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cutNsigmaTOF) { + if (TOFHit == 1 && TMath::Abs(nsigmaTOF) < cfgNsigmaTOF) { return true; } - if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cutNsigmaTPC) { + if (TOFHit != 1 && TMath::Abs(nsigmaTPC) < cfgNsigmaTPC) { return true; } } @@ -172,28 +198,53 @@ struct heptaquark { return false; } - template - ROOT::Math::XYZVector getDCAofV0V0(V01 const& v01, V02 const& v02) + template + int selectHQ(HQRow1 const& hq1r, HQRow2 const& hq2r, HQRow3 const& hq3r, ColRow const& col) { - ROOT::Math::XYZVector v01pos, v02pos, v01mom, v02mom; - v01pos.SetXYZ(v01.x(), v01.y(), v01.z()); - v02pos.SetXYZ(v02.x(), v02.y(), v02.z()); - v01mom.SetXYZ(v01.px(), v01.py(), v01.pz()); - v02mom.SetXYZ(v02.px(), v02.py(), v02.pz()); - - ROOT::Math::XYZVector posdiff = v02pos - v01pos; - ROOT::Math::XYZVector cross = v01mom.Cross(v02mom); - ROOT::Math::XYZVector dcaVec = (posdiff.Dot(cross) / cross.Mag2()) * cross; - return dcaVec; - } + int selection = 0; - template - float getCPA(V01 const& v01, V02 const& v02) - { - ROOT::Math::XYZVector v01mom, v02mom; - v01mom.SetXYZ(v01.px() / v01.p(), v01.py() / v01.p(), v01.pz() / v01.p()); - v02mom.SetXYZ(v02.px() / v02.p(), v02.py() / v02.p(), v02.pz() / v02.p()); - return v01mom.Dot(v02mom); + auto hq1 = makeP4FromHQRow(hq1r); + auto hq2 = makeP4FromHQRow(hq2r); + auto hq3 = makeP4FromHQRow(hq3r); + + if (hq1.Pt() < cfgMinPhiPt || hq2.Pt() < cfgMinPhiPt || hq3.Pt() < cfgMinLambdaPt) { + selection += 1; + } + + const double sumE = hq1.E() + hq2.E() + hq3.E(); + const double emin = std::min({hq1.E(), hq2.E(), hq3.E()}); + const double fmin = emin / std::max(1e-9, sumE); + if (fmin < cfgSoftFraction) { + selection += 2; + } + + auto ex = hq1 + hq2 + hq3; + TVector3 boost = -ex.BoostVector(); + + auto hqphipair_boost = hq1 + hq2; + auto hqlambda_boost = hq3; + hqphipair_boost.Boost(boost); + hqlambda_boost.Boost(boost); + + const double denom = (hqlambda_boost.Vect().Mag() * hqphipair_boost.Vect().Mag()); + const double cosHel = (denom > 0.) ? (hqlambda_boost.Vect().Dot(hqphipair_boost.Vect()) / denom) : 1.0; + if (std::abs(cosHel) > cfgCollinear) { + selection += 4; + } + + ROOT::Math::XYZVector rPV(col.posX(), col.posY(), col.posZ()); + ROOT::Math::XYZVector rSV(hq3r.hqx(), hq3r.hqy(), hq3r.hqz()); + + ROOT::Math::XYZVector L = rSV - rPV; + ROOT::Math::XYZVector exMom(ex.Px(), ex.Py(), ex.Pz()); + + const double denom2 = (L.R() * exMom.R() + 1e-9); + const double cosPoint = L.Dot(exMom) / denom2; + if (cosPoint < cfgCosPoint) { + selection += 8; + } + + return selection; } ROOT::Math::PxPyPzMVector DauVec1, DauVec2; @@ -214,7 +265,7 @@ struct heptaquark { if (hqtrackd1.hqId() != 333) continue; - if (hqtrackd1.hqMass() < minPhiMass || hqtrackd1.hqMass() > maxPhiMass) + if (hqtrackd1.hqMass() < cfgMinPhiMass || hqtrackd1.hqMass() > cfgMaxPhiMass) continue; DauVec1 = ROOT::Math::PxPyPzMVector(hqtrackd1.hqd1Px(), hqtrackd1.hqd1Py(), hqtrackd1.hqd1Pz(), massKa); @@ -246,7 +297,7 @@ struct heptaquark { if (hqtrackd2.hqId() != 333) continue; - if (hqtrackd2.hqMass() < minPhiMass || hqtrackd2.hqMass() > maxPhiMass) + if (hqtrackd2.hqMass() < cfgMinPhiMass || hqtrackd2.hqMass() > cfgMaxPhiMass) continue; DauVec1 = ROOT::Math::PxPyPzMVector(hqtrackd2.hqd1Px(), hqtrackd2.hqd1Py(), hqtrackd2.hqd1Pz(), massKa); @@ -278,7 +329,7 @@ struct heptaquark { if (std::abs(hqtrackd3.hqId()) != 3122) continue; - if (hqtrackd3.hqMass() < minLambdaMass || hqtrackd3.hqMass() > maxLambdaMass) + if (hqtrackd3.hqMass() < cfgMinLambdaMass || hqtrackd3.hqMass() > cfgMaxLambdaMass) continue; int isLambda = static_cast(hqtrackd3.hqId() < 0); @@ -321,6 +372,9 @@ struct heptaquark { HQ12 = HQ1 + HQ2; HQ13 = HQ1 + HQ3; + if (cfgSelectHQ && selectHQ(hqtrackd1, hqtrackd2, hqtrackd3, collision)) + continue; + histos.fill(HIST("h_InvMass_same"), exotic.M(), exotic.Pt(), collision.centrality()); histos.fill(HIST("hDalitz"), HQ12.M2(), HQ13.M2(), exotic.M(), exotic.Pt(), isLambda, collision.centrality()); diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index 60e8f97f1c8..1902184a496 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -15,7 +15,9 @@ // #include #include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" // +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" @@ -64,6 +66,7 @@ using namespace o2::soa; using namespace o2::aod::rctsel; // using namespace o2::constants::physics; using std::array; +// FixME: Add INEL>0 selection for the derived data struct HigherMassResonances { SliceCache cache; @@ -108,7 +111,7 @@ struct HigherMassResonances { // Configurable isSel8{"isSel8", false, "Event Selection 8"}; // Configurables for event selection - // Configurable isINELgt0{"isINELgt0", true, "INEL>0 selection"}; + Configurable isINELgt0{"isINELgt0", true, "INEL>0 selection"}; Configurable isTriggerTVX{"isTriggerTVX", false, "TriggerTVX"}; // Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", false, "IsGoodZvtxFT0vsPV"}; // Configurable isApplyOccCut{"isApplyOccCut", true, "Apply occupancy cut"}; @@ -144,7 +147,7 @@ struct HigherMassResonances { Configurable isApplyEtaCutK0s{"isApplyEtaCutK0s", false, "Apply eta cut on K0s daughters"}; Configurable cfgETAcut{"cfgETAcut", 0.8f, "Track ETA cut"}; Configurable deltaRDaugherCut{"deltaRDaugherCut", 0.001f, "DeltaR cut on V0 daughters"}; - Configurable deltaRK0sCut{"deltaRK0sCut", false, "Apply deltaR cut between two K0s"}; + Configurable deltaRK0sCut{"deltaRK0sCut", 0.1f, "Apply deltaR cut between two K0s"}; // Configurable for track selection and multiplicity Configurable cfgPTcut{"cfgPTcut", 0.2f, "Track PT cut"}; @@ -156,7 +159,7 @@ struct HigherMassResonances { Configurable isavoidsplitrackMC{"isavoidsplitrackMC", false, "avoid split track in MC"}; Configurable isapplyRapidityMC{"isapplyRapidityMC", true, "Apply rapidity cut on generated and reconstructed particles"}; Configurable selectMCparticles{"selectMCparticles", 1, "0: f0(1710), 1: f2(1525), 2: a2(1320), 3: f0(1370), 4: f0(1500), 5: f2(1270)"}; - std::vector pdgCodes = {10331, 335, 115, 10221, 9030221, 225}; + std::vector pdgCodes = {10331, 335, 115, 10221, 9030221, 225, 313}; // output THnSparses Configurable activateHelicityFrame{"activateHelicityFrame", false, "Activate the THnSparse with cosThStar w.r.t. helicity axis"}; @@ -270,8 +273,8 @@ struct HigherMassResonances { hCutFlow->GetXaxis()->SetBinLabel(8, "Occupancy Cut"); hCutFlow->GetXaxis()->SetBinLabel(9, "rctChecker"); hCutFlow->GetXaxis()->SetBinLabel(10, "kIsTriggerTVX"); - // hCutFlow->GetXaxis()->SetBinLabel(11, "kIsGoodZvtxFT0vsPV"); - // hCutFlow->GetXaxis()->SetBinLabel(12, "IsINELgt0"); + hCutFlow->GetXaxis()->SetBinLabel(11, "No selection"); + hCutFlow->GetXaxis()->SetBinLabel(12, "IsINELgt0"); // hCutFlow->GetXaxis()->SetBinLabel(13, "isVertexITSTPC"); // hCutFlow->GetXaxis()->SetBinLabel(14, "isVertexTOFMatched"); @@ -366,10 +369,15 @@ struct HigherMassResonances { // For MC if (doprocessGen || doprocessRec) { + hMChists.add("MCcorrections/hGenNo", "Generated collisions before and after event selection", kTH1F, {{5, 0.0f, 5.0f}}); hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, thnAxisPOL}); + hMChists.add("Genf1710Calib", "Calibrated Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, thnAxisPOL}); hMChists.add("Genf17102", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, thnAxisPOL}); + hMChists.add("Genf1710Calib2", "Calibrated Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, thnAxisPOL}); hMChists.add("Recf1710_pt1", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + hMChists.add("Recf1710Calib_pt1", "Calibrated Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); hMChists.add("Recf1710_pt2", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + hMChists.add("Recf1710Calib_pt2", "Calibrated Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); hMChists.add("h1Recsplit", "Rec p_{T}2", kTH1F, {ptAxis}); hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); hMChists.add("Genf1710_mass2", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); @@ -388,6 +396,22 @@ struct HigherMassResonances { hMChists.add("Rec_Multiplicity", "Multiplicity in MC", kTH1F, {multiplicityAxis}); hMChists.add("MC_mult_after_event_sel", "Multiplicity in MC", kTH1F, {multiplicityAxis}); } + + if (doprocessEvtLossSigLossMC) { + hMChists.add("MCcorrections/hSignalLossDenominator", "Kstar generated before event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/hSignalLossNumerator", "Kstar generated after event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/MultiplicityRec", "Multiplicity in generated MC with at least 1 reconstruction", kTH1F, {multiplicityAxis}); + hMChists.add("MCcorrections/MultiplicityGen", "Multiplicity in generated MC", kTH1F, {multiplicityAxis}); + hMChists.add("MCcorrections/hSignalLossDenominator2", "Kstar generated before event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/hSignalLossNumerator2", "Kstar generated after event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/MultiplicityRec2", "Multiplicity in generated MC with at least 1 reconstruction", kTH1F, {multiplicityAxis}); + hMChists.add("MCcorrections/MultiplicityGen2", "Multiplicity in generated MC", kTH1F, {multiplicityAxis}); + + hMChists.add("MCcorrections/hSignalLossDenominator3", "Kstar generated before event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/hSignalLossDenominator4", "Kstar generated before event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/hSignalLossNumerator3", "Kstar generated after event selection", kTH2F, {{ptAxis}, {multiplicityAxis}}); + hMChists.add("MCcorrections/hMultvsCent", "Kstar generated after event selection", kTH2F, {{multiplicityAxis}, {multiplicityAxis}}); + } } template @@ -447,13 +471,13 @@ struct HigherMassResonances { // if (config.isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) // return false; // if (fillHist) - // rEventSelection.fill(HIST("hEventCut"), 10); + rEventSelection.fill(HIST("hEventCut"), 10); - // if (config.isINELgt0 && !collision.isInelGt0()) { - // return false; - // } - // if (fillHist) - // rEventSelection.fill(HIST("hEventCut"), 11); + if (config.isINELgt0 && !collision.isInelGt0()) { + return false; + } + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 11); // if (config.isVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { // return false; @@ -470,6 +494,63 @@ struct HigherMassResonances { return true; } + template + bool selectionEventDerived(const Coll& collision, bool fillHist = true) + { + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 0); + + if (std::abs(collision.posZ()) > config.cutzvertex) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 1); + + // if (config.isSel8 && !collision.sel8()) + // return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 2); + + if (config.isNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 3); + + if (config.isNoITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 4); + + // if (config.isNoSameBunchPileup && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup))) + // return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 5); + + if (config.isAllLayersGoodITS && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 6); + + // if (config.isNoCollInTimeRangeStandard && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) + // return false; + + // if (config.isApplyOccCut && (std::abs(collision.trackOccupancyInTimeRange()) > config.configOccCut)) + // return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 7); + + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 8); + + if (config.isTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 9); + + return true; + } + template bool selectionV0(Collision const& collision, V0 const& candidate, float /*multiplicity*/) { @@ -714,9 +795,10 @@ struct HigherMassResonances { using TrackCandidates = soa::Filtered>; using V0TrackCandidate = soa::Join; // For Monte Carlo - using EventCandidatesMC = soa::Join; + using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; using V0TrackCandidatesMC = soa::Filtered>; + using EventMCGenerated = soa::Join; // zBeam direction in lab frame template @@ -1053,7 +1135,8 @@ struct HigherMassResonances { motherRot = daughterRot + daughter2; - double pTcorrRot = std::abs(daughterRot.Pt() + daughter2.Pt()) / motherRot.Pt(); + // double pTcorrRot = std::abs(daughterRot.Pt() + daughter2.Pt()) / motherRot.Pt(); + double pTcorrRot = (motherRot.Pt() - daughterRot.Pt() != 0.) ? daughterRot.Pt() / (motherRot.Pt() - daughterRot.Pt()) : 0.; if (motherRot.Rapidity() < config.rapidityMotherData) hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), deltaMass, deltaRvalue, pTcorrRot); @@ -1174,7 +1257,8 @@ struct HigherMassResonances { if (config.qAOptimisation) { double deltaRvalue = std::sqrt(TVector2::Phi_mpi_pi(daughter1.phi() - daughter2.phi()) * TVector2::Phi_mpi_pi(daughter1.phi() - daughter2.phi()) + (daughter1.eta() - daughter2.eta()) * (daughter1.eta() - daughter2.eta())); const double deltaMass = deltaM(t1.mK0Short(), t2.mK0Short()); - const double ptCorr = std::abs(daughter1.Pt() + daughter2.Pt()) / mother.Pt(); + // const double ptCorr = std::abs(daughter1.Pt() + daughter2.Pt()) / mother.Pt(); + const double ptCorr = (mother.Pt() - daughter1.Pt() != 0.) ? daughter1.Pt() / (mother.Pt() - daughter1.Pt()) : 0.; if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), deltaMass, deltaRvalue, ptCorr); } @@ -1200,19 +1284,32 @@ struct HigherMassResonances { std::vector passKs; ROOT::Math::PxPyPzMVector lResonanceGen1; ROOT::Math::PxPyPzEVector lResonanceGen; + Service pdgDB; - void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) + // void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) + void processGen(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { // if (config.isMC == false) { // return; // } hMChists.fill(HIST("events_check"), 0.5); + bool isINELgt0true = false; + + if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + isINELgt0true = true; + } + if (config.isINELgt0 && !isINELgt0true) { + return; + } + std::vector selectedEvents(collisions.size()); int nevts = 0; multiplicityGen = -999.0; for (const auto& collision : collisions) { + hMChists.fill(HIST("MCcorrections/hGenNo"), 0.5); + // multiplicityGen = collision.centFT0M(); if (config.cSelectMultEstimator == kFT0M) { multiplicityGen = collision.centFT0M(); @@ -1230,7 +1327,7 @@ struct HigherMassResonances { continue; } - selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); } selectedEvents.resize(nevts); hMChists.fill(HIST("events_check"), 1.5); @@ -1240,6 +1337,10 @@ struct HigherMassResonances { return; } hMChists.fill(HIST("events_check"), 2.5); + hMChists.fill(HIST("MCcorrections/hGenNo"), 1.5); + + double genMultiplicity = mcCollision.centFT0M(); + for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.pdgCode()) != config.pdgCodes[config.selectMCparticles]) // f2(1525), f0(1710) @@ -1290,6 +1391,7 @@ struct HigherMassResonances { auto helicityGen1 = lResonanceGen1.Vect().Dot(fourVecDauCM1.Vect()) / (std::sqrt(fourVecDauCM1.Vect().Mag2()) * std::sqrt(lResonanceGen1.Vect().Mag2())); hMChists.fill(HIST("Genf1710"), multiplicityGen, lResonanceGen.pt(), helicityGen); + hMChists.fill(HIST("Genf1710Calib"), genMultiplicity, lResonanceGen.pt(), helicityGen); hMChists.fill(HIST("Genf1710_mass"), lResonanceGen.M()); hMChists.fill(HIST("GenRapidity"), mcParticle.y()); hMChists.fill(HIST("GenEta"), mcParticle.eta()); @@ -1300,6 +1402,7 @@ struct HigherMassResonances { } hMChists.fill(HIST("Genf17102"), multiplicityGen, lResonanceGen1.pt(), helicityGen1); + hMChists.fill(HIST("Genf1710Calib2"), genMultiplicity, lResonanceGen1.pt(), helicityGen1); hMChists.fill(HIST("Genf1710_mass2"), lResonanceGen1.M()); hMChists.fill(HIST("GenRapidity2"), lResonanceGen1.Rapidity()); hMChists.fill(HIST("GenEta2"), lResonanceGen1.Eta()); @@ -1310,13 +1413,120 @@ struct HigherMassResonances { } PROCESS_SWITCH(HigherMassResonances, processGen, "Process Generated", false); + void processEvtLossSigLossMC(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + { + // auto multiplicityRec = -1; + bool isSelectedEvent = false; + auto multiplicity1 = -999.; + const int multMC = mcCollision.multMCNParticlesEta05(); + + for (const auto& RecCollision : recCollisions) { + if (!RecCollision.has_mcCollision()) + continue; + if (!selectionEvent(RecCollision, false)) // don't fill event cut histogram + continue; + + // const auto& mcCollisionRec = RecCollision.mcCollision_as(); + // multiplicityRec = mcCollisionRec.centFT0M(); + + if (config.cSelectMultEstimator == kFT0M) { + multiplicity1 = RecCollision.centFT0M(); + } else if (config.cSelectMultEstimator == kFT0A) { + multiplicity1 = RecCollision.centFT0A(); + } else if (config.cSelectMultEstimator == kFT0C) { + multiplicity1 = RecCollision.centFT0C(); + } else if (config.cSelectMultEstimator == kFV0A) { + multiplicity1 = RecCollision.centFV0A(); + } else { + multiplicity1 = RecCollision.centFT0M(); // default + } + + isSelectedEvent = true; + } + + bool isINELgt0true = false; + + if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + isINELgt0true = true; + } + if (config.isINELgt0 && !isINELgt0true) { + return; + } + + if (std::abs(mcCollision.posZ()) > config.cutzvertex) { + return; + } + + auto multiplicityGen = -1; + multiplicityGen = mcCollision.centFT0M(); + hMChists.fill(HIST("MCcorrections/MultiplicityGen"), multiplicityGen); + hMChists.fill(HIST("MCcorrections/MultiplicityGen2"), multiplicity1); + hMChists.fill(HIST("MCcorrections/hMultvsCent"), multiplicity1, multMC); + + // Event loss + if (isSelectedEvent) { + hMChists.fill(HIST("MCcorrections/MultiplicityRec"), multiplicityGen); + hMChists.fill(HIST("MCcorrections/MultiplicityRec2"), multiplicity1); + } + + // Generated MC + for (const auto& mcPart : mcParticles) { + if (std::abs(mcPart.y()) >= config.rapidityMotherData || std::abs(mcPart.pdgCode()) != config.pdgCodes[config.selectMCparticles]) + continue; + + hMChists.fill(HIST("MCcorrections/hSignalLossDenominator"), mcPart.pt(), multiplicityGen); + hMChists.fill(HIST("MCcorrections/hSignalLossDenominator2"), mcPart.pt(), multiplicity1); + hMChists.fill(HIST("MCcorrections/hSignalLossDenominator3"), mcPart.pt(), multMC); + if (isSelectedEvent) { + hMChists.fill(HIST("MCcorrections/hSignalLossNumerator"), mcPart.pt(), multiplicityGen); + hMChists.fill(HIST("MCcorrections/hSignalLossNumerator2"), mcPart.pt(), multiplicity1); + hMChists.fill(HIST("MCcorrections/hSignalLossNumerator3"), mcPart.pt(), multMC); + } + + auto kDaughters = mcPart.daughters_as(); + if (kDaughters.size() != config.noOfDaughters) { + continue; + } + + for (const auto& kCurrentDaughter : kDaughters) { + // int daupdg = std::abs(kCurrentDaughter.pdgCode()); + + // if (!kCurrentDaughter.isPhysicalPrimary()) { + // continue; + // } + if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kK0Short) { + passKs.push_back(true); + if (passKs.size() == 1) { + daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); + } else if (static_cast(passKs.size()) == config.noOfDaughters) { + daughter2 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); + } + } + } + if (static_cast(passKs.size()) == config.noOfDaughters) { + lResonanceGen1 = daughter1 + daughter2; + hMChists.fill(HIST("MCcorrections/hSignalLossDenominator4"), lResonanceGen1.pt(), multiplicity1); + } + passKs.clear(); + } // end loop on gen particles + } + PROCESS_SWITCH(HigherMassResonances, processEvtLossSigLossMC, "Process Signal Loss, Event Loss", false); + int eventCounter = 0; std::vector gindex1, gindex2; - void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const&, V0TrackCandidatesMC const& V0s, aod::McParticles const&, aod::McCollisions const& /*mcCollisions*/) + void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const&, V0TrackCandidatesMC const& V0s, aod::McParticles const&, EventMCGenerated const&) { // if (config.isMC == false) { // return; // } + if (!collision.has_mcCollision()) { + return; + } + + double multiplicityRec = -1.0; + // multiplicityRec = collision.mcCollision_as().centFT0M(); + const auto& mcCollisionRec = collision.mcCollision_as(); + multiplicityRec = mcCollisionRec.centFT0M(); auto multiplicity = -999.0; if (config.cSelectMultEstimator == kFT0M) { @@ -1335,10 +1545,7 @@ struct HigherMassResonances { return; } hMChists.fill(HIST("Rec_Multiplicity"), multiplicity); - - if (!collision.has_mcCollision()) { - return; - } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); hMChists.fill(HIST("MC_mult_after_event_sel"), multiplicity); eventCounter++; @@ -1472,6 +1679,7 @@ struct HigherMassResonances { // } hMChists.fill(HIST("Recf1710_pt1"), multiplicity, mothertrack1.pt(), mother1.M(), helicityRec2); + hMChists.fill(HIST("Recf1710Calib_pt1"), multiplicityRec, mothertrack1.pt(), mother1.M(), helicityRec2); hMChists.fill(HIST("RecRapidity"), mothertrack1.y()); hMChists.fill(HIST("RecPhi"), mothertrack1.phi()); hMChists.fill(HIST("RecEta"), mothertrack1.eta()); @@ -1481,6 +1689,7 @@ struct HigherMassResonances { } hMChists.fill(HIST("Recf1710_pt2"), multiplicity, mother.Pt(), mother.M(), helicityRec); + hMChists.fill(HIST("Recf1710Calib_pt2"), multiplicityRec, mother.Pt(), mother.M(), helicityRec); hMChists.fill(HIST("RecRapidity2"), mother.Rapidity()); hMChists.fill(HIST("RecPhi2"), mother.Phi()); hMChists.fill(HIST("RecEta2"), mother.Eta()); @@ -1508,7 +1717,7 @@ struct HigherMassResonances { multiplicity = collision.centFT0M(); // default } - if (!selectionEvent(collision, true)) { + if (!selectionEventDerived(collision, true)) { return; } @@ -1593,7 +1802,8 @@ struct HigherMassResonances { daughterRot = ROOT::Math::PxPyPzMVector(daughter1.Px() * std::cos(theta2) - daughter1.Py() * std::sin(theta2), daughter1.Px() * std::sin(theta2) + daughter1.Py() * std::cos(theta2), daughter1.Pz(), daughter1.M()); motherRot = daughterRot + daughter2; - double pTcorrRot = std::abs(daughterRot.Pt() + daughter2.Pt()) / motherRot.Pt(); + // double pTcorrRot = std::abs(daughterRot.Pt() + daughter2.Pt()) / motherRot.Pt(); + double pTcorrRot = (motherRot.Pt() - daughterRot.Pt() != 0.) ? daughterRot.Pt() / (motherRot.Pt() - daughterRot.Pt()) : 0.; if (motherRot.Rapidity() < config.rapidityMotherData) hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), deltaMass, deltaRvalue, pTcorrRot); } @@ -1617,7 +1827,7 @@ struct HigherMassResonances { multiplicity = 0.0; multiplicity = c1.centFT0M(); - if (!selectionEvent(c1, false) || !selectionEvent(c2, false)) { + if (!selectionEventDerived(c1, false) || !selectionEventDerived(c2, false)) { continue; } @@ -1661,7 +1871,8 @@ struct HigherMassResonances { if (config.qAOptimisation) { double deltaRvalue = std::sqrt(TVector2::Phi_mpi_pi(daughter1.phi() - daughter2.phi()) * TVector2::Phi_mpi_pi(daughter1.phi() - daughter2.phi()) + (daughter1.eta() - daughter2.eta()) * (daughter1.eta() - daughter2.eta())); const double deltaMass = deltaM(t1.mK0Short(), t2.mK0Short()); - const double ptCorr = std::abs(daughter1.Pt() + daughter2.Pt()) / mother.Pt(); + // const double ptCorr = std::abs(daughter1.Pt() + daughter2.Pt()) / mother.Pt(); + const double ptCorr = (mother.Pt() - daughter1.Pt() != 0.) ? daughter1.Pt() / (mother.Pt() - daughter1.Pt()) : 0.; if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), deltaMass, deltaRvalue, ptCorr); } diff --git a/PWGLF/Tasks/Resonances/k1analysis.cxx b/PWGLF/Tasks/Resonances/k1analysis.cxx index a743c349c51..02ac98be89b 100644 --- a/PWGLF/Tasks/Resonances/k1analysis.cxx +++ b/PWGLF/Tasks/Resonances/k1analysis.cxx @@ -13,23 +13,67 @@ /// \brief Reconstruction of track-track decay resonance candidates /// /// -/// \author Bong-Hwi Lim - -#include "PWGLF/DataModel/LFResonanceTables.h" - +/// \author Su-Jeong Ji , Bong-Hwi Lim + +#include +#include +#include +#include +#include +#include +#include +#include +// #include // FIXME +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" - +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/MathConstants.h" #include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StaticFor.h" +#include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" - -#include // FIXME -#include +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/RotationZ.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include "TVector2.h" +#include #include // FIXME +#include +#include +#include +#include +#include +#include +#include #include using namespace o2; @@ -37,693 +81,1019 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; +using namespace o2::constants::math; +using namespace o2::aod::rctsel; -struct k1analysis { - enum binAnti : unsigned int { - kNormal = 0, - kAnti, - kNAEnd - }; - enum binType : unsigned int { +struct K1analysis { + enum BinType : unsigned int { kK1P = 0, - kK1N, - kK1P_Mix, - kK1N_Mix, - kK1P_GenINEL10, - kK1N_GenINEL10, - kK1P_GenINELgt10, - kK1N_GenINELgt10, - kK1P_GenTrig10, - kK1N_GenTrig10, - kK1P_GenEvtSel, - kK1N_GenEvtSel, - kK1P_Rec, - kK1N_Rec, + kK1A, + kK1P_Like, + kK1A_Like, + kK1P_Rot, + kK1A_Rot, kTYEnd }; + + enum EvtStep { + kAll = 0, + kZvtx, + kINELgt0, + kAssocReco, + kNSteps + }; + + enum class K1MassRegion : uint8_t { + Outside = 0, + Signal, + SBLeft, + SBRight + }; + + const int nSteps = static_cast(EvtStep::kNSteps); + SliceCache cache; - Preslice perRCol = aod::resodaughter::resoCollisionId; Preslice perCollision = aod::track::collisionId; + // Preslice perCollisionV0 = aod::v0data::collisionId; + Preslice perCollisionV0 = aod::v0data::collisionId; + Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Join; + using V0Candidates = aod::V0Datas; + + // for MC reco + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Join; //, aod::McParticles>; + using MCV0Candidates = soa::Join; + + // for MC truth + using MCTrueEventCandidates = aod::McCollisions; + using MCTrueTrackCandidates = aod::McParticles; + + using LorentzVectorSetXYZM = ROOT::Math::LorentzVector>; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - using ResoMCCols = soa::Join; - - ///// Configurables - Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; - /// 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, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; - /// Pre-selection cuts - Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; - - /// DCA Selections - // DCAr to PV - Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; - // DCAz to PV - Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; - Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; - - /// 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 nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined - Configurable cTOFVeto{"cTOFVeto", true, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto - Configurable cUseOnlyTOFTrackPi{"cUseOnlyTOFTrackPi", false, "Use only TOF track for PID selection"}; // Use only TOF track for Pion PID selection - // Kaon - Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC - Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF - Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", -999, "Combined nSigma cut for Kaon"}; // Combined - Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection + + Service ccdb; + Service pdg; + o2::ccdb::CcdbApi ccdbApi; + + struct : ConfigurableGroup { + Configurable cfgURL{"cfgURL", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + } CCDBConfig; + // 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"}; + + // Configurables + struct : ConfigurableGroup { + ConfigurableAxis cfgBinsPt{"cfgBinsPt", {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}, "Binning of the pT axis"}; + ConfigurableAxis cfgBinsPtQA{"cfgBinsPtQA", {VARIABLE_WIDTH, 0.0, 0.3, 0.6, 1.2, 1.8, 2.4, 3.0, 3.6, 4.2, 4.8, 5.4, 6.0, 7.0, 10.0}, "Binning of the pT axis"}; + ConfigurableAxis cfgBinsCent{"cfgBinsCent", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0, 110.0}, "Binning of the centrality axis"}; + ConfigurableAxis cfgBinsVtxZ{"cfgBinsVtxZ", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "Binning of the z-vertex axis"}; + Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; + Configurable cNbinsDivQA{"cNbinsDivQA", 1, "Integer to divide the number of bins for QA"}; + } AxisConfig; + + /// Event cuts + o2::analysis::CollisonCuts colCuts; + struct : ConfigurableGroup { + Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; + Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; + Configurable cfgEvtTriggerCheck{"cfgEvtTriggerCheck", false, "Evt sel: check for trigger"}; + Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtTFBorderCut{"cfgEvtTFBorderCut", true, "Evt sel: apply TF border cut"}; + Configurable cfgEvtUseITSTPCvertex{"cfgEvtUseITSTPCvertex", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; + Configurable cfgEvtZvertexTimedifference{"cfgEvtZvertexTimedifference", false, "Evt sel: apply Z-vertex time difference"}; + Configurable cfgEvtPileupRejection{"cfgEvtPileupRejection", false, "Evt sel: apply pileup rejection"}; + Configurable cfgEvtNoITSROBorderCut{"cfgEvtNoITSROBorderCut", true, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgincludeCentralityMC{"cfgincludeCentralityMC", false, "Include centrality in MC"}; + Configurable cfgEvtCollInTimeRangeStandard{"cfgEvtCollInTimeRangeStandard", false, "Evt sel: apply NoCollInTimeRangeStandard"}; + Configurable cfgEventCentralityMin{"cfgEventCentralityMin", 0.0f, "Event sel: minimum centrality"}; + Configurable cfgEventCentralityMax{"cfgEventCentralityMax", 100.0f, "Event sel: maximum centrality"}; + Configurable cfgEvtUseRCTFlagChecker{"cfgEvtUseRCTFlagChecker", false, "Evt sel: use RCT flag checker"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + } EventCuts; + RCTFlagsChecker rctChecker; + + Configurable cfgFillQAPlots{"cfgFillQAPlots", true, "Fill QA plots"}; + Configurable cfgCentEst{"cfgCentEst", 2, "Centrality estimator, 1: FT0C, 2: FT0M"}; + + /// PID Selections, pion + struct : ConfigurableGroup { + Configurable cfgTPConly{"cfgTPConly", true, "Use only TPC for PID"}; // bool + Configurable cfgMaxTPCnSigmaPion{"cfgMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cfgMaxTOFnSigmaPion{"cfgMaxTOFnSigmaPion", 5.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cfgNsigmaCutCombinedPion{"cfgNsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined + Configurable cfgTOFVeto{"cfgTOFVeto", false, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto + Configurable cfgTOFMinPt{"cfgTOFMinPt", 0.6, "Minimum TOF pT cut for Pion"}; // TOF pT cut + } PIDCuts; + // Track selections - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) - Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor - Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; - Configurable tof_at_high_pt{"tof_at_high_pt", false, "Use TOF at high pT"}; - Configurable additionalEvsel{"additionalEvsel", true, "Additional event selcection"}; - Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; - Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; - Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; - Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; - - // Secondary selection - Configurable cfgModeK892orRho{"cfgModeK892orRho", true, "Secondary scenario for K892 (true) or Rho (false)"}; - Configurable cSecondaryMasswindow{"cSecondaryMasswindow", 0.1, "Secondary inv mass selection window"}; - Configurable cMinAnotherSecondaryMassCut{"cMinAnotherSecondaryMassCut", 0, "Min inv. mass selection of another secondary scenario"}; - Configurable cMaxAnotherSecondaryMassCut{"cMaxAnotherSecondaryMassCut", 999, "MAx inv. mass selection of another secondary scenario"}; - Configurable cMinPiKaMassCut{"cMinPiKaMassCut", 0, "bPion-Kaon pair inv mass selection minimum"}; - Configurable cMaxPiKaMassCut{"cMaxPiKaMassCut", 999, "bPion-Kaon pair inv mass selection maximum"}; - Configurable cMinAngle{"cMinAngle", 0, "Minimum angle between K(892)0 and bachelor pion"}; - Configurable cMaxAngle{"cMaxAngle", 4, "Maximum angle between K(892)0 and bachelor pion"}; - Configurable cMinPairAsym{"cMinPairAsym", -1, "Minimum pair asymmetry"}; - Configurable cMaxPairAsym{"cMaxPairAsym", 1, "Maximum pair asymmetry"}; + struct : ConfigurableGroup { + Configurable cfgMinPtcut{"cfgMinPtcut", 0.15, "Track minium pt cut"}; + Configurable cfgMaxEtacut{"cfgMaxEtacut", 0.8, "Track maximum eta cut"}; + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor + + Configurable cfgpTdepDCAxyCut{"cfgpTdepDCAxyCut", true, "pT-dependent DCAxy cut"}; + Configurable cfgpTdepDCAzCut{"cfgpTdepDCAzCut", true, "pT-dependent DCAz cut"}; + 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"}; + // DCAr to PV + Configurable cfgMaxbDCArToPVcut{"cfgMaxbDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cfgMaxbDCAzToPVcut{"cfgMaxbDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; + } TrackCuts; + + // Secondary Selection + struct : ConfigurableGroup { + Configurable cfgReturnFlag{"cfgReturnFlag", false, "Return Flag for debugging"}; + Configurable cfgSecondaryRequire{"cfgSecondaryRequire", true, "Secondary cuts on/off"}; + Configurable cfgSecondaryArmenterosCut{"cfgSecondaryArmenterosCut", true, "cut on Armenteros-Podolanski graph"}; + Configurable cfgSecondaryCrossMassHypothesisCut{"cfgSecondaryCrossMassHypothesisCut", false, "Apply cut based on the lambda mass hypothesis"}; + + Configurable cfgByPassDauPIDSelection{"cfgByPassDauPIDSelection", true, "Bypass Daughters PID selection"}; + Configurable cfgSecondaryDauDCAMax{"cfgSecondaryDauDCAMax", 1., "Maximum DCA Secondary daughters to PV"}; + Configurable cfgSecondaryDauPosDCAtoPVMin{"cfgSecondaryDauPosDCAtoPVMin", 0.1, "Minimum DCA Secondary positive daughters to PV"}; + Configurable cfgSecondaryDauNegDCAtoPVMin{"cfgSecondaryDauNegDCAtoPVMin", 0.1, "Minimum DCA Secondary negative daughters to PV"}; + + Configurable cfgSecondaryPtMin{"cfgSecondaryPtMin", 0.f, "Minimum transverse momentum of Secondary"}; + Configurable cfgSecondaryRapidityMax{"cfgSecondaryRapidityMax", 0.8, "Maximum rapidity of Secondary"}; + Configurable cfgSecondaryRadiusMin{"cfgSecondaryRadiusMin", 0, "Minimum transverse radius of Secondary"}; + Configurable cfgSecondaryRadiusMax{"cfgSecondaryRadiusMax", 999.9, "Maximum transverse radius of Secondary"}; + Configurable cfgSecondaryCosPAMin{"cfgSecondaryCosPAMin", 0.995, "Mininum cosine pointing angle of Secondary"}; + Configurable cfgSecondaryDCAtoPVMax{"cfgSecondaryDCAtoPVMax", 0.4, "Maximum DCA Secondary to PV"}; + Configurable cfgSecondaryProperLifetimeMax{"cfgSecondaryProperLifetimeMax", 20, "Maximum Secondary Lifetime"}; + Configurable cfgSecondaryparamArmenterosCut{"cfgSecondaryparamArmenterosCut", 0.2, "parameter for Armenteros Cut"}; + Configurable cfgSecondaryMassWindow{"cfgSecondaryMassWindow", 0.03, "Secondary inv mass selciton window"}; + Configurable cfgSecondaryCrossMassCutWindow{"cfgSecondaryCrossMassCutWindow", 0.05, "Secondary inv mass selection window with (anti)lambda hypothesis"}; + } SecondaryCuts; + + // K* selection + struct : ConfigurableGroup { + Configurable cfgKstarMinPt{"cfgKstarMinPt", 0.0, "Kstar minimum pT"}; + Configurable cfgKstarMaxRap{"cfgKstarMaxRap", 0.5, "Kstar maximum rapidity"}; + Configurable cfgKstarMinRap{"cfgKstarMinRap", -0.5, "Kstar minimum rapidity"}; + Configurable cfgKstarMassWindow{"cfgKstarMassWindow", 0.05, "Kstar inv mass selection window"}; + } KstarCuts; // K1 selection - Configurable cK1MaxRap{"cK1MaxRap", 0.5, "K1 maximum rapidity"}; - Configurable cK1MinRap{"cK1MinRap", -0.5, "K1 minimum rapidity"}; + struct : ConfigurableGroup { + Configurable cfgK1MinPt{"cfgK1MinPt", 0.0, "K1 minimum pT"}; + Configurable cfgK1MaxRap{"cfgK1MaxRap", 0.5, "K1 maximum rapidity"}; + Configurable cfgK1MinRap{"cfgK1MinRap", -0.5, "K1 minimum rapidity"}; + } K1Cuts; + + // Bkg estimation + struct : ConfigurableGroup { + Configurable cfgFillRotBkg{"cfgFillRotBkg", true, "Fill rotated background"}; + Configurable cfgMinRot{"cfgMinRot", 5.0 * constants::math::PI / 6.0, "Minimum of rotation"}; + Configurable cfgMaxRot{"cfgMaxRot", 7.0 * constants::math::PI / 6.0, "Maximum of rotation"}; + Configurable cfgRotPion{"cfgRotPion", true, "Rotate pion"}; + Configurable cfgNrotBkg{"cfgNrotBkg", 4, "Number of rotated copies (background) per each original candidate"}; + } BkgEstimationConfig; + + Configurable cfgTruthUseInelGt0{"cfgTruthUseInelGt0", true, "Truth denominator: require INEL>0"}; + Configurable cfgTruthIncludeZvtx{"cfgTruthIncludeZvtx", true, "Truth denominator: also require |vtxz| cfgHasPair{"cfgHasPair", true, "Check the existence of pairs"}; + Configurable cfgPiPiMinPt{"cfgPiPiMinPt", 0.5, "bachelor pion and secondary pion minimum pT cut"}; + + float lCentrality; + + // PDG code + int kPDGK0s = kK0Short; + int kPDGK0 = kK0; + int kPDGKstarPlus = o2::constants::physics::Pdg::kKPlusStar892; + int kPDGPiPlus = kPiPlus; + int kPDGK10 = 10313; + double fMaxPosPV = 1e-2; void init(o2::framework::InitContext&) { - std::vector centBinning = {0., 1., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 80., 90., 100., 200.}; - AxisSpec centAxis = {centBinning, "T0M (%)"}; - AxisSpec ptAxis = {150, 0, 15, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec dcaxyAxis = {300, 0, 3, "DCA_{#it{xy}} (cm)"}; - AxisSpec dcazAxis = {500, 0, 5, "DCA_{#it{xy}} (cm)"}; - AxisSpec invMassAxisK892 = {1400 / cNbinsDiv, 0.6, 2.0, "Invariant Mass (GeV/#it{c}^2)"}; // K(892)0 - AxisSpec invMassAxisRho = {2000 / cNbinsDiv, 0.0, 2.0, "Invariant Mass (GeV/#it{c}^2)"}; // rho - AxisSpec invMassAxisReso = {1600 / cNbinsDiv, 0.9f, 2.5f, "Invariant Mass (GeV/#it{c}^2)"}; // K1 - AxisSpec invMassAxisScan = {250, 0, 2.5, "Invariant Mass (GeV/#it{c}^2)"}; // For selection - AxisSpec pidQAAxis = {130, -6.5, 6.5}; - AxisSpec dataTypeAxis = {9, 0, 9, "Histogram types"}; - AxisSpec mcTypeAxis = {4, 0, 4, "Histogram types"}; + lCentrality = -999; + + colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, EventCuts.cfgEvtTriggerTVXSel, EventCuts.cfgEvtOccupancyInTimeRangeMax, EventCuts.cfgEvtOccupancyInTimeRangeMin); + colCuts.init(&histos); + colCuts.setTriggerTVX(EventCuts.cfgEvtTriggerTVXSel); + colCuts.setApplyTFBorderCut(EventCuts.cfgEvtTFBorderCut); + colCuts.setApplyNoITSROBorderCut(EventCuts.cfgEvtNoITSROBorderCut); + colCuts.setApplyITSTPCvertex(EventCuts.cfgEvtUseITSTPCvertex); + colCuts.setApplyZvertexTimedifference(EventCuts.cfgEvtZvertexTimedifference); + colCuts.setApplyPileupRejection(EventCuts.cfgEvtPileupRejection); + colCuts.setApplyCollInTimeRangeStandard(EventCuts.cfgEvtCollInTimeRangeStandard); + colCuts.printCuts(); + + rctChecker.init(EventCuts.cfgEvtRCTFlagCheckerLabel, EventCuts.cfgEvtRCTFlagCheckerZDCCheck, EventCuts.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + + AxisSpec centAxis = {AxisConfig.cfgBinsCent, "T0M (%)"}; + AxisSpec vtxzAxis = {AxisConfig.cfgBinsVtxZ, "Z Vertex (cm)"}; + AxisSpec ptAxis = {AxisConfig.cfgBinsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisQA = {AxisConfig.cfgBinsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec radiusAxis = {50, 0, 5, "Radius (cm)"}; + AxisSpec cpaAxis = {50, 0.95, 1.0, "CPA"}; + AxisSpec tauAxis = {250, 0, 25, "Lifetime (cm)"}; + AxisSpec dcaAxis = {200, 0, 2, "DCA (cm)"}; + AxisSpec dcaxyAxis = {200, 0, 2, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {200, 0, 2, "DCA_{#it{z}} (cm)"}; + AxisSpec yAxis = {100, -1, 1, "Rapidity"}; + AxisSpec invMassAxisK0s = {800 / AxisConfig.cNbinsDiv, 0.46, 0.54, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 + AxisSpec invMassAxisChk892 = {900 / AxisConfig.cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 + AxisSpec invMassAxisReso = {1600 / AxisConfig.cNbinsDiv, 0.9f, 2.5f, "Invariant Mass (GeV/#it{c}^2)"}; // K1 + AxisSpec pidQAAxis = {130 / AxisConfig.cNbinsDivQA, -6.5, 6.5}; + AxisSpec cutAxis{14, 0.5, 14.5, "Check"}; // 1..14 // THnSparse - AxisSpec axisAnti = {binAnti::kNAEnd, 0, binAnti::kNAEnd, "Type of bin: Normal or Anti"}; - AxisSpec axisType = {binType::kTYEnd, 0, binType::kTYEnd, "Type of bin with charge and mix"}; + AxisSpec axisType = {BinType::kTYEnd, 0, BinType::kTYEnd, "Type of bin with charge and mix"}; AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; - // DCA QA - // Primary pion - histos.add("QA/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAcut/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAcut/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + histos.add("QA/K0sCutCheck", "Check K0s cut", HistType::kTH1D, {AxisSpec{13, -0.5, 12.5, "Check"}}); + histos.add("QA/K0sCutFlow", "Check K0s cut (first-fail or pass)", HistType::kTH1F, {cutAxis}); + auto hcut = histos.get(HIST("QA/K0sCutFlow")); + hcut->GetXaxis()->SetBinLabel(1, "TOTAL"); + hcut->GetXaxis()->SetBinLabel(2, "PASS"); + hcut->GetXaxis()->SetBinLabel(3, "DauDCA>max"); + hcut->GetXaxis()->SetBinLabel(4, "PosDCAtoPVGetXaxis()->SetBinLabel(5, "NegDCAtoPVGetXaxis()->SetBinLabel(6, "pTGetXaxis()->SetBinLabel(7, "|y|>max"); + hcut->GetXaxis()->SetBinLabel(8, "Rmax"); + hcut->GetXaxis()->SetBinLabel(9, "DCAtoPV>max"); + hcut->GetXaxis()->SetBinLabel(10, "cosPAGetXaxis()->SetBinLabel(11, "ctau>max"); + hcut->GetXaxis()->SetBinLabel(12, "qtarmGetXaxis()->SetBinLabel(13, "|M(K0s)-m0|>win"); + hcut->GetXaxis()->SetBinLabel(14, "cross-mass veto"); + + histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); + histos.add("QA/before/VtxZ", "Centrality distribution", {HistType::kTH1D, {vtxzAxis}}); + histos.add("QA/before/hEvent", "Number of Events", HistType::kTH1F, {{1, 0.5, 1.5}}); + + if (BkgEstimationConfig.cfgFillRotBkg) { + histos.add("QA/RotBkg/hRotBkg", "Rotated angle of rotated background", HistType::kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); + } + + // Bachelor pion + histos.add("QA/before/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QA/before/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + + histos.add("QA/after/trkbpionDCAxy", "DCAxy distribution of bachelor pion candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkbpionDCAz", "DCAz distribution of bachelor pion candidates", HistType::kTH1D, {dcazAxis}); + histos.add("QA/after/trkbpionpT", "pT distribution of bachelor pion candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkbpionTPCPID", "TPC PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkbpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkbpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); // Secondary pion - histos.add("QA/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAcut/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAcut/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - // Kaon - histos.add("QA/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QA/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); - histos.add("QA/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QA/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAcut/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAcut/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAcut/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAcut/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkspionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkspionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkspionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkspionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkspionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trkspionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkspionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trkspionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkspionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkspionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s pion 1 + histos.add("QA/before/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trkppionTPCPID", "TPC PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkppionTOFPID", "TOF PID of secondary pion 1 (positive) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trkppionTPCTOFPID", "TPC-TOF PID map of secondary pion 1 (positive) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trkppionpT", "pT distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trkppionDCAxy", "DCAxy distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trkppionDCAz", "DCAz distribution of secondary pion 1 (positive) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s pion 2 + histos.add("QA/before/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/before/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/before/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/before/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + histos.add("QA/after/trknpionTPCPID", "TPC PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trknpionTOFPID", "TOF PID of secondary pion 2 (negative) candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); + histos.add("QA/after/trknpionTPCTOFPID", "TPC-TOF PID map of secondary pion 2 (negative) candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); + histos.add("QA/after/trknpionpT", "pT distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/trknpionDCAxy", "DCAxy distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcaxyAxis}); + histos.add("QA/after/trknpionDCAz", "DCAz distribution of secondary pion 2 (negative) candidates", HistType::kTH1D, {dcazAxis}); + + // K0s + histos.add("QA/before/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QA/before/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QA/before/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QA/before/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/before/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/before/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/before/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); + histos.add("QA/before/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + histos.add("QA/after/hDauDCASecondary", "DCA of daughters of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hDauPosDCAtoPVSecondary", "Pos DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hDauNegDCAtoPVSecondary", "Neg DCA to PV of daughters secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/hy_Secondary", "Rapidity distribution of secondary resonance", HistType::kTH1D, {yAxis}); + histos.add("QA/after/hRadiusSecondary", "Radius distribution of secondary resonance", HistType::kTH1D, {radiusAxis}); + histos.add("QA/after/hCPASecondary", "Cosine pointing angle distribution of secondary resonance", HistType::kTH1D, {cpaAxis}); + histos.add("QA/after/hDCAtoPVSecondary", "DCA to PV distribution of secondary resonance", HistType::kTH1D, {dcaAxis}); + histos.add("QA/after/hPropTauSecondary", "Proper Lifetime distribution of secondary resonance", HistType::kTH1D, {tauAxis}); + histos.add("QA/after/hPtAsymSecondary", "pT asymmetry distribution of secondary resonance", HistType::kTH1D, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/after/hArmSecondary", "Armenteros distribution of secondary resonance", HistType::kTH2D, {AxisSpec{100, -1, 1, "alpha"}, {200, 0, 0.5, "qtArm"}}); + histos.add("QA/after/hInvmassSecondary", "Invariant mass of unlike-sign secondary resonance", HistType::kTH1D, {invMassAxisK0s}); + + // charged Kstar + histos.add("QA/before/hpT_Kstar", "pT distribution of chK(892)", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/before/hy_Kstar", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + histos.add("QA/before/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisChk892}); + + histos.add("QA/after/hpT_Kstar", "pT distribution of chK(892)", HistType::kTH1D, {ptAxisQA}); + histos.add("QA/after/hy_Kstar", "Rapidity distribution of chK(892)", HistType::kTH1D, {yAxis}); + histos.add("QA/after/kstarinvmass", "Invariant mass of unlike-sign chK(892)", HistType::kTH1D, {invMassAxisChk892}); // K1 - histos.add("QA/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QA/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QA/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); - histos.add("QA/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); - histos.add("QA/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); - histos.add("QA/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); - - histos.add("QAcut/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QAcut/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAcut/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); - histos.add("QAcut/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); - histos.add("QAcut/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); - histos.add("QAcut/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + histos.add("QA/before/hpT_K1", "pT distribution of K1(1270)", HistType::kTH1F, {ptAxisQA}); + histos.add("QA/before/hy_K1", "Rapidity distribution of K1(1270)", HistType::kTH1F, {yAxis}); + histos.add("QA/before/K1CPA", "Cosine pointing angle distribution of K1(1270)", HistType::kTH1F, {cpaAxis}); + histos.add("QA/before/K1PtAsym", "pT asymmetry distribution of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/before/K1DalitzOS", "Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/before/K1DalitzLS", "Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/before/K1invmass", "Invariant mass of K1(1270) (US)", HistType::kTH1F, {invMassAxisReso}); + histos.add("QA/before/K1invmassLS", "Invariant mass of K1(1270) (LS)", HistType::kTH1F, {invMassAxisReso}); + + histos.add("QA/after/hpT_K1", "pT distribution of K1(1270)", HistType::kTH1F, {ptAxisQA}); + histos.add("QA/after/hy_K1", "Rapidity distribution of K1(1270)", HistType::kTH1F, {yAxis}); + histos.add("QA/after/K1CPA", "Cosine pointing angle of K1(1270)", HistType::kTH1F, {cpaAxis}); + histos.add("QA/after/K1PtAsym", "pT asymmetry distribution of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/after/K1DalitzOS_Signal", "(Signal region) Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzOS_SBLeft", "(SB left) Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzOS_SBRight", "(SB right) Dalitz plot of opposite-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzLS_Signal", "(Signal region) Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzLS_SBLeft", "(SB left) Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1DalitzLS_SBRight", "(SB right) Dalitz plot of like-sign combination of K1(1270)", HistType::kTH2F, {AxisSpec{300, 0.0, 3.0, "#it{M}^{2}_{K_{s}^{0}#pi_{sec}}"}, {300, 0.0, 3.0, "#it{M}^{2}_{#pi_{sec}#pi_{bach}}"}}); + histos.add("QA/after/K1invmass", "Invariant mass of K1(1270) (US)", HistType::kTH1F, {invMassAxisReso}); + histos.add("QA/after/K1invmassLS", "Invariant mass of K1(1270) (LS)", HistType::kTH1F, {invMassAxisReso}); // Invariant mass - histos.add("hInvmass_K1", "Invariant mass of K1(1270)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); - // Mass QA (quick check) - histos.add("k1invmass", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - histos.add("k1invmass_Mix", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - - // MC - if (doprocessMC) { - histos.add("k1invmass_MC", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - histos.add("k1invmass_MC_noK1", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); - - histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAMC/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAMC/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAMC/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAMC/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); - histos.add("QAMC/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAMC/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); - histos.add("QAMC/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); - - histos.add("QAMC/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); - histos.add("QAMC/K1PairAssym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); - histos.add("QAMC/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); - histos.add("QAMC/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisK892, invMassAxisK892}); - histos.add("QAMC/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); - histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); - } + histos.add("hInvmass_K1", "Invariant mass of K1(1270)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso}); + histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisChk892}); + histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s}); + + ccdb->setURL(CCDBConfig.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()); + // Print output histograms statistics LOG(info) << "Size of the histograms in K1 Analysis Task"; histos.print(); - } + } // init - double massKa = MassKaonCharged; - double massPi = MassPionCharged; - // double massRho770 = MassRho770; - // double massK892 = MassKStar892; - double massRho770 = 0.77526; - double massK892 = 0.892; + const int kCentFT0C = 1; + const int kCentFT0M = 2; + const float kInvalidCentrality = -999.f; - // PDG code - int kPDGRho770 = 113; - int kK1Plus = 10323; + template + float getCentrality(CollisionType const& collision) + { + if (cfgCentEst == kCentFT0C) { + return collision.centFT0C(); + } else if (cfgCentEst == kCentFT0M) { + return collision.centFT0M(); + } else { + return kInvalidCentrality; + } + } + // Track selection template - bool trackCut(const TrackType track) + bool trackCut(TrackType const& track) { - // basic track cuts - if (std::abs(track.pt()) < cMinPtcut) + if (std::abs(track.pt()) < TrackCuts.cfgMinPtcut) return false; - if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + if (std::abs(track.eta()) > TrackCuts.cfgMaxEtacut) return false; - if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) + if (track.itsNCls() < TrackCuts.cfgITScluster) return false; - if (track.tpcNClsFound() < cfgTPCcluster) + if (track.tpcNClsFound() < TrackCuts.cfgTPCcluster) return false; - if (cfgHasTOF && !track.hasTOF()) + if (track.tpcCrossedRowsOverFindableCls() < TrackCuts.cfgRatioTPCRowsOverFindableCls) return false; - if (cfgUseITSRefit && !track.passedITSRefit()) + if (track.itsChi2NCl() >= TrackCuts.cfgITSChi2NCl) return false; - if (cfgUseTPCRefit && !track.passedTPCRefit()) + if (track.tpcChi2NCl() >= TrackCuts.cfgTPCChi2NCl) return false; - if (cfgPVContributor && !track.isPVContributor()) + if (TrackCuts.cfgHasITS && !track.hasITS()) return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) + if (TrackCuts.cfgHasTPC && !track.hasTPC()) return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (TrackCuts.cfgHasTOF && !track.hasTOF()) return false; - if (cfgGlobalTrack && !track.isGlobalTrack()) + if (TrackCuts.cfgUseITSRefit && !track.passedITSRefit()) return false; - - return true; - } - - // PID selection tools - template - bool selectionPIDPion(const T& candidate) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { - tpcPIDPassed = true; - } else { + if (TrackCuts.cfgUseTPCRefit && !track.passedTPCRefit()) return false; - } - 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; - } + if (TrackCuts.cfgPVContributor && !track.isPVContributor()) + return false; + if (TrackCuts.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (TrackCuts.cfgGlobalTrack && !track.isGlobalTrack()) + return false; + if (TrackCuts.cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (TrackCuts.cfgpTdepDCAxyCut) { + // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution + if (std::abs(track.dcaXY()) > (0.004 + (0.013 / track.pt()))) + return false; } else { - if (!cTOFVeto) { + if (std::abs(track.dcaXY()) > TrackCuts.cfgMaxbDCArToPVcut) return false; - } - tofPIDPassed = true; } - if (tpcPIDPassed && tofPIDPassed) { - return true; + if (TrackCuts.cfgpTdepDCAzCut) { + // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution + if (std::abs(track.dcaZ()) > (0.004 + (0.013 / track.pt()))) + return false; + } else { + if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) + return false; } - return false; + return true; } - template - bool selectionPIDKaon(const T& candidate) + + // PID selection tools + template + bool selectionPIDPion(TrackType const& candidate) { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { - tpcPIDPassed = true; - } else { + if (std::abs(candidate.tpcNSigmaPi()) >= PIDCuts.cfgMaxTPCnSigmaPion) return false; - } + if (PIDCuts.cfgTPConly) + return true; + // if (candidate.pt() <= PIDCuts.cfgTOFMinPt) + // 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; - } + const bool tofPIDPassed = std::abs(candidate.tofNSigmaPi()) < PIDCuts.cfgMaxTOFnSigmaPion; + const bool combo = (PIDCuts.cfgNsigmaCutCombinedPion > 0) && + (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < + PIDCuts.cfgNsigmaCutCombinedPion * PIDCuts.cfgNsigmaCutCombinedPion); + return tofPIDPassed || combo; } else { - if (!cTOFVeto) { - return false; - } - tofPIDPassed = true; + return PIDCuts.cfgTOFVeto; } - if (tpcPIDPassed && tofPIDPassed) { - return true; - } - return false; } - template - bool isTrueK1(const T& trk1, const T& trk2, const T2& bTrack) + // selection K0s + template + bool selectionK0s(CollisionType const& collision, K0sType const& candidate) { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) - return false; - if (abs(bTrack.pdgCode()) != kPiPlus) - return false; - if (cfgModeK892orRho) { // K892 mode - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 != mother2) + auto lDauDCA = std::fabs(candidate.dcaV0daughters()); + auto lDauPosDCAtoPV = std::fabs(candidate.dcapostopv()); + auto lDauNegDCAtoPV = std::fabs(candidate.dcanegtopv()); + auto lPt = candidate.pt(); + auto lRapidity = candidate.yK0Short(); + auto lRadius = candidate.v0radius(); + auto lDCAtoPV = std::fabs(candidate.dcav0topv()); + auto lCPA = candidate.v0cosPA(); + auto lPropTauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; + auto lMk0s = candidate.mK0Short(); + auto lMLambda = candidate.mLambda(); + auto lMALambda = candidate.mAntiLambda(); + + auto checkCommonCuts = [&]() { + if (std::fabs(lDauDCA) > SecondaryCuts.cfgSecondaryDauDCAMax) return false; - if (abs(trk1.motherPDG()) != kK0Star892) + if (std::fabs(lDauPosDCAtoPV) < SecondaryCuts.cfgSecondaryDauPosDCAtoPVMin) return false; - if (abs(bTrack.motherPDG()) != kK1Plus) + if (std::fabs(lDauNegDCAtoPV) < SecondaryCuts.cfgSecondaryDauNegDCAtoPVMin) return false; - auto siblings = bTrack.siblingIds(); - if (siblings[0] != mother1 && siblings[1] != mother1) + if (lPt < SecondaryCuts.cfgSecondaryPtMin) return false; - return true; - } else { // Rho mode - auto mother1 = trk1.motherId(); - auto motherb = bTrack.motherId(); - if (mother1 != motherb) + if (std::fabs(lRapidity) > SecondaryCuts.cfgSecondaryRapidityMax) + return false; + if (lRadius < SecondaryCuts.cfgSecondaryRadiusMin || lRadius > SecondaryCuts.cfgSecondaryRadiusMax) return false; - if (abs(trk1.motherPDG()) != kPDGRho770) + if (std::fabs(lDCAtoPV) > SecondaryCuts.cfgSecondaryDCAtoPVMax) return false; - if (abs(trk2.motherPDG()) != kK1Plus) + if (lCPA < SecondaryCuts.cfgSecondaryCosPAMin) return false; - auto siblings = trk2.siblingIds(); - if (siblings[0] != mother1 && siblings[1] != mother1) + if (lPropTauK0s > SecondaryCuts.cfgSecondaryProperLifetimeMax) + return false; + if (candidate.qtarm() < SecondaryCuts.cfgSecondaryparamArmenterosCut * std::fabs(candidate.alpha())) + return false; + if (std::fabs(lMk0s - MassK0Short) > SecondaryCuts.cfgSecondaryMassWindow) + return false; + if (SecondaryCuts.cfgSecondaryCrossMassHypothesisCut && + ((std::fabs(lMLambda - MassLambda0) < SecondaryCuts.cfgSecondaryCrossMassCutWindow) || (std::fabs(lMALambda - MassLambda0Bar) < SecondaryCuts.cfgSecondaryCrossMassCutWindow))) return false; return true; + }; + + if (SecondaryCuts.cfgReturnFlag) { // For cut study + bool returnFlag = true; + histos.fill(HIST("QA/K0sCutCheck"), 0); + if (lDauDCA > SecondaryCuts.cfgSecondaryDauDCAMax) { + histos.fill(HIST("QA/K0sCutCheck"), 1); + returnFlag = false; + } + if (lDauPosDCAtoPV < SecondaryCuts.cfgSecondaryDauPosDCAtoPVMin) { + histos.fill(HIST("QA/K0sCutCheck"), 2); + returnFlag = false; + } + if (lDauNegDCAtoPV < SecondaryCuts.cfgSecondaryDauNegDCAtoPVMin) { + histos.fill(HIST("QA/K0sCutCheck"), 3); + returnFlag = false; + } + if (lPt < SecondaryCuts.cfgSecondaryPtMin) { + histos.fill(HIST("QA/K0sCutCheck"), 4); + returnFlag = false; + } + if (std::fabs(lRapidity) > SecondaryCuts.cfgSecondaryRapidityMax) { + histos.fill(HIST("QA/K0sCutCheck"), 5); + returnFlag = false; + } + if (lRadius < SecondaryCuts.cfgSecondaryRadiusMin || lRadius > SecondaryCuts.cfgSecondaryRadiusMax) { + histos.fill(HIST("QA/K0sCutCheck"), 6); + returnFlag = false; + } + if (lDCAtoPV > SecondaryCuts.cfgSecondaryDCAtoPVMax) { + histos.fill(HIST("QA/K0sCutCheck"), 7); + returnFlag = false; + } + if (lCPA < SecondaryCuts.cfgSecondaryCosPAMin) { + histos.fill(HIST("QA/K0sCutCheck"), 8); + returnFlag = false; + } + if (lPropTauK0s > SecondaryCuts.cfgSecondaryProperLifetimeMax) { + histos.fill(HIST("QA/K0sCutCheck"), 9); + returnFlag = false; + } + if (candidate.qtarm() < SecondaryCuts.cfgSecondaryparamArmenterosCut * std::fabs(candidate.alpha())) { + histos.fill(HIST("QA/K0sCutCheck"), 10); + returnFlag = false; + } + if (std::fabs(lMk0s - MassK0Short) > SecondaryCuts.cfgSecondaryMassWindow) { + histos.fill(HIST("QA/K0sCutCheck"), 11); + returnFlag = false; + } + if (SecondaryCuts.cfgSecondaryCrossMassHypothesisCut && + ((std::fabs(lMLambda - MassLambda0) < SecondaryCuts.cfgSecondaryCrossMassCutWindow) || (std::fabs(lMALambda - MassLambda0Bar) < SecondaryCuts.cfgSecondaryCrossMassCutWindow))) { + histos.fill(HIST("QA/K0sCutCheck"), 12); + returnFlag = false; + } + return returnFlag; + } else { // normal usage + if (SecondaryCuts.cfgSecondaryRequire) { + return checkCommonCuts(); + } else { + return std::fabs(lMk0s - MassK0Short) <= SecondaryCuts.cfgSecondaryMassWindow; // always apply mass window cut + } } - } + } // selectionK0s - template - bool isTrueK892(const T& trk1, const T& trk2) + K1MassRegion getK1MassRegion(float mass) { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) - return false; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 != mother2) - return false; - if (abs(trk1.motherPDG()) != kK0Star892) - return false; - return true; - } + constexpr float SigMin = 1.22f; + constexpr float SigMax = 1.32f; - template - bool isTrueRho(const T& trk1, const T& trk2) - { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kPiPlus) - return false; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 != mother2) - return false; - if (abs(trk1.motherPDG()) != kPDGRho770) - return false; - return true; + constexpr float SBLMin = 1.10f; + constexpr float SBLMax = 1.18f; + + constexpr float SBRMin = 1.36f; + constexpr float SBRMax = 1.44f; + + if (mass > SigMin && mass < SigMax) + return K1MassRegion::Signal; + if (mass > SBLMin && mass < SBLMax) + return K1MassRegion::SBLeft; + if (mass > SBRMin && mass < SBRMax) + return K1MassRegion::SBRight; + + return K1MassRegion::Outside; } - template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + int count = 0; + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2, const TracksTypeK0s& dTracks3) { - auto multiplicity = collision.cent(); - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceSecondary, lDecayDaughter_bach, lResonanceK1; - for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks2, 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. - // Trk1: Pion, Trk2: Kaon - // apply the track cut - if (!trackCut(trk1) || !trackCut(trk2)) - continue; - auto isTrk1hasTOF = trk1.hasTOF(); - auto isTrk2hasTOF = trk2.hasTOF(); - auto trk1pt = trk1.pt(); - auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); - auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; - auto trk2pt = trk2.pt(); - auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); - auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; - // for rho mode - auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); - auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; - - //// PID selections - if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) - continue; - if (cUseOnlyTOFTrackKa && !isTrk2hasTOF) - continue; + using TrackTarget = std::decay_t; - if (cfgModeK892orRho) { // K892 mode - if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) - continue; - } else { // Rho mode - if (!selectionPIDPion(trk1) || !selectionPIDPion(trk2)) - continue; - } + histos.fill(HIST("QA/before/CentDist"), lCentrality); + + LorentzVectorSetXYZM lBachelor_pi, lDecayDaughter_K0s, lDecayDaughter_pi, lResoKstar, lResonanceK1, lDaughterRot, lResonanceRot; + LorentzVectorSetXYZM lPairK0sPiSec, lPairK0sPiBach, lPairPiPi; + + std::vector btrackIndices = {}; + std::vector strackIndices = {}; + std::vector k0sIndices = {}; + std::vector chK892Indices = {}; + + // check the existence of the pairs + if (cfgHasPair && (dTracks1.size() < 1 || dTracks2.size() < 1 || dTracks3.size() < 1)) + return; + + for (const auto& bTrack : dTracks1) { + auto trkbpt = bTrack.pt(); + auto istrkbhasTOF = bTrack.hasTOF(); + auto trkbNSigmaPiTPC = bTrack.tpcNSigmaPi(); + auto trkbNSigmaPiTOF = (istrkbhasTOF) ? bTrack.tofNSigmaPi() : -999.; - //// QA plots after the selection if constexpr (!IsMix) { - // --- PID QA Pion - histos.fill(HIST("QA/trkspionTPCPID"), trk1pt, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/trkspionTOFPID"), trk1pt, trk1NSigmaPiTOF); - histos.fill(HIST("QA/trkspionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); - } - histos.fill(HIST("QA/trkspionpT"), trk1pt); - histos.fill(HIST("QA/trkspionDCAxy"), trk1.dcaXY()); - histos.fill(HIST("QA/trkspionDCAz"), trk1.dcaZ()); - - if (cfgModeK892orRho) { // K892 mode - // --- PID QA Kaon - histos.fill(HIST("QA/trkkaonTPCPID"), trk2pt, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/trkkaonTOFPID"), trk2pt, trk2NSigmaKaTOF); - histos.fill(HIST("QA/trkkaonTPCTOFPID"), trk2NSigmaKaTPC, trk2NSigmaKaTOF); - } - histos.fill(HIST("QA/trkkaonpT"), trk2pt); - histos.fill(HIST("QA/trkkaonDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QA/trkkaonDCAz"), trk2.dcaZ()); - } else { // Rho mode - // --- PID QA Pion - histos.fill(HIST("QA/trkppionTPCPID"), trk2pt, trk2NSigmaPiTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QA/trkppionTOFPID"), trk2pt, trk2NSigmaPiTOF); - histos.fill(HIST("QA/trkppionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + if (cfgFillQAPlots) { + // Bachelor pion QA plots + histos.fill(HIST("QA/before/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); + if (istrkbhasTOF) { + histos.fill(HIST("QA/before/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); + histos.fill(HIST("QA/before/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); } - histos.fill(HIST("QA/trkppionpT"), trk2pt); - histos.fill(HIST("QA/trkppionDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QA/trkppionDCAz"), trk2.dcaZ()); + histos.fill(HIST("QA/before/trkbpionpT"), trkbpt); + histos.fill(HIST("QA/before/trkbpionDCAxy"), bTrack.dcaXY()); + histos.fill(HIST("QA/before/trkbpionDCAz"), bTrack.dcaZ()); } } - //// Resonance reconstruction - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), (cfgModeK892orRho) ? massKa : massPi); - lResonanceSecondary = lDecayDaughter1 + lDecayDaughter2; + if (!trackCut(bTrack)) + continue; + if (!selectionPIDPion(bTrack)) + continue; if constexpr (!IsMix) { - histos.fill(HIST("QA/hInvmassSecon"), lResonanceSecondary.M()); + if (cfgFillQAPlots) { + // Bachelor pion QA plots after applying cuts + histos.fill(HIST("QA/after/trkbpionTPCPID"), trkbpt, trkbNSigmaPiTPC); + if (istrkbhasTOF) { + histos.fill(HIST("QA/after/trkbpionTOFPID"), trkbpt, trkbNSigmaPiTOF); + histos.fill(HIST("QA/after/trkbpionTPCTOFPID"), trkbNSigmaPiTPC, trkbNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkbpionpT"), trkbpt); + histos.fill(HIST("QA/after/trkbpionDCAxy"), bTrack.dcaXY()); + histos.fill(HIST("QA/after/trkbpionDCAz"), bTrack.dcaZ()); + } } + btrackIndices.push_back(bTrack.index()); + } // bTrack + + for (const auto& sTrack : dTracks2) { + auto trkspt = sTrack.pt(); + auto istrkshasTOF = sTrack.hasTOF(); + auto trksNSigmaPiTPC = sTrack.tpcNSigmaPi(); + auto trksNSigmaPiTOF = (istrkshasTOF) ? sTrack.tofNSigmaPi() : -999.; - if constexpr (IsMC) { // MC Check - if (cfgModeK892orRho) { - if (isTrueK892(trk1, trk2)) - histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); - } else { - if (isTrueRho(trk1, trk2)) - histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Secondary pion QA plots + histos.fill(HIST("QA/before/trkspionTPCPID"), trkspt, trksNSigmaPiTPC); + if (istrkshasTOF) { + histos.fill(HIST("QA/before/trkspionTOFPID"), trkspt, trksNSigmaPiTOF); + histos.fill(HIST("QA/before/trkspionTPCTOFPID"), trksNSigmaPiTPC, trksNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trkspionpT"), trkspt); + histos.fill(HIST("QA/before/trkspionDCAxy"), sTrack.dcaXY()); + histos.fill(HIST("QA/before/trkspionDCAz"), sTrack.dcaZ()); } } - // Mass window cut - double massCut = cfgModeK892orRho ? massK892 : massRho770; - if (std::abs(lResonanceSecondary.M() - massCut) > cSecondaryMasswindow) + if (!trackCut(sTrack)) + continue; + if (!selectionPIDPion(sTrack)) continue; - // bTrack loop for K1 reconstruction - for (auto bTrack : dTracks1) { - if (bTrack.index() == trk1.index() || bTrack.index() == trk2.index()) - continue; - if (!trackCut(bTrack)) - continue; - - // Kaon or Pion - if (cfgModeK892orRho && !selectionPIDPion(bTrack)) - continue; - if (!cfgModeK892orRho && !selectionPIDKaon(bTrack)) - continue; - - // K1 reconstruction - lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), cfgModeK892orRho ? massPi : massKa); - lResonanceK1 = lResonanceSecondary + lDecayDaughter_bach; + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Secondary pion QA plots after applying cuts + histos.fill(HIST("QA/after/trkspionTPCPID"), trkspt, trksNSigmaPiTPC); + if (istrkshasTOF) { + histos.fill(HIST("QA/after/trkspionTOFPID"), trkspt, trksNSigmaPiTOF); + histos.fill(HIST("QA/after/trkspionTPCTOFPID"), trksNSigmaPiTPC, trksNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkspionpT"), trkspt); + histos.fill(HIST("QA/after/trkspionDCAxy"), sTrack.dcaXY()); + histos.fill(HIST("QA/after/trkspionDCAz"), sTrack.dcaZ()); + } + } + strackIndices.push_back(sTrack.index()); + } // sTrack + + for (const auto& k0sCand : dTracks3) { + + auto posDauTrack = k0sCand.template posTrack_as(); + auto negDauTrack = k0sCand.template negTrack_as(); + + /// Daughters + // Positve pion + auto trkppt = posDauTrack.pt(); + auto istrkphasTOF = posDauTrack.hasTOF(); + auto trkpNSigmaPiTPC = posDauTrack.tpcNSigmaPi(); + auto trkpNSigmaPiTOF = (istrkphasTOF) ? posDauTrack.tofNSigmaPi() : -999.; + // Negative pion + auto trknpt = negDauTrack.pt(); + auto istrknhasTOF = negDauTrack.hasTOF(); + auto trknNSigmaPiTPC = negDauTrack.tpcNSigmaPi(); + auto trknNSigmaPiTOF = (istrknhasTOF) ? negDauTrack.tofNSigmaPi() : -999.; + + /// K0s + auto trkkDauDCA = k0sCand.dcaV0daughters(); + auto trkky = k0sCand.yK0Short(); + auto trkkDCAtoPV = k0sCand.dcav0topv(); + auto trkkCPA = k0sCand.v0cosPA(); + auto trkkPropTau = k0sCand.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; + auto trkkMass = k0sCand.mK0Short(); + auto trkkDauDCAPostoPV = k0sCand.dcapostopv(); + auto trkkDauDCANegtoPV = k0sCand.dcanegtopv(); + auto trkkpt = k0sCand.pt(); + auto trkkRadius = k0sCand.v0radius(); - // Cuts - if (lResonanceK1.Rapidity() > cK1MaxRap || lResonanceK1.Rapidity() < cK1MinRap) - continue; + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Seconddary QA plots + histos.fill(HIST("QA/before/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); + if (istrkphasTOF) { + histos.fill(HIST("QA/before/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); + histos.fill(HIST("QA/before/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trkppionpT"), trkppt); + histos.fill(HIST("QA/before/trkppionDCAxy"), posDauTrack.dcaXY()); + histos.fill(HIST("QA/before/trkppionDCAz"), posDauTrack.dcaZ()); + + histos.fill(HIST("QA/before/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); + if (istrknhasTOF) { + histos.fill(HIST("QA/before/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); + histos.fill(HIST("QA/before/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); + } + histos.fill(HIST("QA/before/trknpionpT"), trknpt); + histos.fill(HIST("QA/before/trknpionDCAxy"), negDauTrack.dcaXY()); + histos.fill(HIST("QA/before/trknpionDCAz"), negDauTrack.dcaZ()); + + histos.fill(HIST("QA/before/hDauDCASecondary"), trkkDauDCA); + histos.fill(HIST("QA/before/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); + histos.fill(HIST("QA/before/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); + + histos.fill(HIST("QA/before/hpT_Secondary"), trkkpt); + histos.fill(HIST("QA/before/hy_Secondary"), trkky); + histos.fill(HIST("QA/before/hRadiusSecondary"), trkkRadius); + histos.fill(HIST("QA/before/hDCAtoPVSecondary"), trkkDCAtoPV); + histos.fill(HIST("QA/before/hCPASecondary"), trkkCPA); + histos.fill(HIST("QA/before/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/before/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); + histos.fill(HIST("QA/before/hInvmassSecondary"), trkkMass); + } + } - auto lK1Angle = lResonanceSecondary.Angle(lDecayDaughter_bach.Vect()); - auto lPairAsym = (lResonanceSecondary.E() - lDecayDaughter_bach.E()) / (lResonanceSecondary.E() + lDecayDaughter_bach.E()); + if (!SecondaryCuts.cfgByPassDauPIDSelection && !selectionPIDPion(posDauTrack)) + continue; + if (!SecondaryCuts.cfgByPassDauPIDSelection && !selectionPIDPion(negDauTrack)) + continue; + if (!selectionK0s(collision, k0sCand)) + continue; - TLorentzVector temp13 = lDecayDaughter1 + lDecayDaughter_bach; - TLorentzVector temp23 = lDecayDaughter2 + lDecayDaughter_bach; + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + // Seconddary QA plots after applying cuts - // QA histograms - if constexpr (!IsMix) { - histos.fill(HIST("QA/K1OA"), lK1Angle); - histos.fill(HIST("QA/K1PairAssym"), lPairAsym); - if (cfgModeK892orRho) { - histos.fill(HIST("QA/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); - } else { - histos.fill(HIST("QA/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + histos.fill(HIST("QA/after/trkppionTPCPID"), trkppt, trkpNSigmaPiTPC); + if (istrkphasTOF) { + histos.fill(HIST("QA/after/trkppionTOFPID"), trkppt, trkpNSigmaPiTOF); + histos.fill(HIST("QA/after/trkppionTPCTOFPID"), trkpNSigmaPiTPC, trkpNSigmaPiTOF); + } + histos.fill(HIST("QA/after/trkppionpT"), trkppt); + histos.fill(HIST("QA/after/trkppionDCAxy"), posDauTrack.dcaXY()); + histos.fill(HIST("QA/after/trkppionDCAz"), posDauTrack.dcaZ()); + + histos.fill(HIST("QA/after/trknpionTPCPID"), trknpt, trknNSigmaPiTPC); + if (istrknhasTOF) { + histos.fill(HIST("QA/after/trknpionTOFPID"), trknpt, trknNSigmaPiTOF); + histos.fill(HIST("QA/after/trknpionTPCTOFPID"), trknNSigmaPiTPC, trknNSigmaPiTOF); } - histos.fill(HIST("QA/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); - histos.fill(HIST("QA/hpT_Secondary"), lResonanceSecondary.Pt()); + histos.fill(HIST("QA/after/trknpionpT"), trknpt); + histos.fill(HIST("QA/after/trknpionDCAxy"), negDauTrack.dcaXY()); + histos.fill(HIST("QA/after/trknpionDCAz"), negDauTrack.dcaZ()); + + histos.fill(HIST("QA/after/hDauDCASecondary"), trkkDauDCA); + histos.fill(HIST("QA/after/hDauPosDCAtoPVSecondary"), trkkDauDCAPostoPV); + histos.fill(HIST("QA/after/hDauNegDCAtoPVSecondary"), trkkDauDCANegtoPV); + + histos.fill(HIST("QA/after/hpT_Secondary"), trkkpt); + histos.fill(HIST("QA/after/hy_Secondary"), trkky); + histos.fill(HIST("QA/after/hRadiusSecondary"), trkkRadius); + histos.fill(HIST("QA/after/hDCAtoPVSecondary"), trkkDCAtoPV); + histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); + histos.fill(HIST("QA/after/hPropTauSecondary"), trkkPropTau); + histos.fill(HIST("QA/after/hArmSecondary"), k0sCand.alpha(), k0sCand.qtarm()); + histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); } + histos.fill(HIST("hInvmass_K0s"), lCentrality, trkkpt, trkkMass); + } + k0sIndices.push_back(k0sCand.index()); + } // K0s - // Selection cuts - if (temp13.M() < cMinAnotherSecondaryMassCut || temp13.M() > cMaxAnotherSecondaryMassCut) - continue; - if (temp23.M() < cMinPiKaMassCut || temp23.M() > cMaxPiKaMassCut) - continue; - if (lK1Angle < cMinAngle || lK1Angle > cMaxAngle) - continue; - if (lPairAsym < cMinPairAsym || lPairAsym > cMaxPairAsym) + for (const auto& btrackIndex : btrackIndices) { + auto bTrack = dTracks1.rawIteratorAt(btrackIndex); + for (const auto& strackIndex : strackIndices) { + auto sTrack = dTracks2.rawIteratorAt(strackIndex); + + if (bTrack.index() == sTrack.index()) continue; - // QA histograms after the cuts - if constexpr (!IsMix) { - histos.fill(HIST("QAcut/K1OA"), lK1Angle); - histos.fill(HIST("QAcut/K1PairAssym"), lPairAsym); - if (cfgModeK892orRho) { - histos.fill(HIST("QAcut/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); - } else { - histos.fill(HIST("QAcut/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + for (const auto& k0sIndex : k0sIndices) { + auto k0sCand = dTracks3.rawIteratorAt(k0sIndex); + + auto posDauTrack = k0sCand.template posTrack_as(); + auto negDauTrack = k0sCand.template negTrack_as(); + + if (bTrack.index() == posDauTrack.index() || bTrack.index() == negDauTrack.index()) + continue; + if (sTrack.index() == posDauTrack.index() || sTrack.index() == negDauTrack.index()) + continue; + + lBachelor_pi = LorentzVectorSetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); + lDecayDaughter_pi = LorentzVectorSetXYZM(sTrack.px(), sTrack.py(), sTrack.pz(), MassPionCharged); + lDecayDaughter_K0s = LorentzVectorSetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + lResoKstar = lDecayDaughter_pi + lDecayDaughter_K0s; + lResonanceK1 = lResoKstar + lBachelor_pi; + + // QA plots for Kstar + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/before/hpT_Kstar"), lResoKstar.Pt()); + histos.fill(HIST("QA/before/hy_Kstar"), lResoKstar.Rapidity()); + histos.fill(HIST("QA/before/kstarinvmass"), lResoKstar.M()); + } } - histos.fill(HIST("QAcut/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); - histos.fill(HIST("QAcut/hInvmassSecon"), lResonanceSecondary.M()); - histos.fill(HIST("QAcut/hpT_Secondary"), lResonanceSecondary.Pt()); - } - if constexpr (!IsMix) { - unsigned int typeK1 = bTrack.sign() > 0 ? binType::kK1P : binType::kK1N; - unsigned int typeNormal = cfgModeK892orRho ? (trk1.sign() < 0 ? binAnti::kNormal : binAnti::kAnti) : binAnti::kNormal; - histos.fill(HIST("k1invmass"), lResonanceK1.M()); - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - - if constexpr (IsMC) { - if (isTrueK1(trk1, trk2, bTrack)) { - typeK1 = bTrack.sign() > 0 ? binType::kK1P_Rec : binType::kK1N_Rec; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); - histos.fill(HIST("QAMC/K1OA"), lK1Angle); - histos.fill(HIST("QAMC/K1PairAssym"), lPairAsym); - if (cfgModeK892orRho) { - histos.fill(HIST("QAMC/hInvmassK892_Rho"), lResonanceSecondary.M(), temp13.M()); + if (lResoKstar.Rapidity() > KstarCuts.cfgKstarMaxRap || lResoKstar.Rapidity() < KstarCuts.cfgKstarMinRap) + continue; + if (lResoKstar.Pt() < KstarCuts.cfgKstarMinPt) + continue; + if (std::fabs(lResoKstar.M() - MassKPlusStar892) > KstarCuts.cfgKstarMassWindow) + continue; + + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/after/hpT_Kstar"), lResoKstar.Pt()); + histos.fill(HIST("QA/after/hy_Kstar"), lResoKstar.Rapidity()); + histos.fill(HIST("QA/after/kstarinvmass"), lResoKstar.M()); + } + histos.fill(HIST("hInvmass_Kstar"), lCentrality, lResoKstar.Pt(), lResoKstar.M()); + } // IsMix + + lPairK0sPiSec = lDecayDaughter_K0s + lDecayDaughter_pi; + lPairK0sPiBach = lDecayDaughter_K0s + lBachelor_pi; + lPairPiPi = lDecayDaughter_pi + lBachelor_pi; + + float m2K0sPiSec = lPairK0sPiSec.M2(); + // float m2K0sPiBach = lPairK0sPiBach.M2(); + float m2PiPi = lPairPiPi.M2(); + + // QA plots for K1 + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/before/hpT_K1"), lResonanceK1.Pt()); + histos.fill(HIST("QA/before/hy_K1"), lResonanceK1.Rapidity()); + if (bTrack.sign() * sTrack.sign() < 0) { + histos.fill(HIST("QA/before/K1invmass"), lResonanceK1.M()); + histos.fill(HIST("QA/before/K1DalitzOS"), m2K0sPiSec, m2PiPi); } else { - histos.fill(HIST("QAMC/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); - } - histos.fill(HIST("QAMC/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); - histos.fill(HIST("QAMC/hInvmassSecon"), lResonanceSecondary.M()); - histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); - - // --- PID QA Pion - histos.fill(HIST("QAMC/trkspionTPCPID"), trk1pt, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAMC/trkspionTOFPID"), trk1pt, trk1NSigmaPiTOF); - histos.fill(HIST("QAMC/trkspionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + histos.fill(HIST("QA/before/K1invmassLS"), lResonanceK1.M()); + histos.fill(HIST("QA/before/K1DalitzLS"), m2K0sPiSec, m2PiPi); } - histos.fill(HIST("QAMC/trkspionpT"), trk1pt); - histos.fill(HIST("QAMC/trkspionDCAxy"), trk1.dcaXY()); - histos.fill(HIST("QAMC/trkspionDCAz"), trk1.dcaZ()); - - if (cfgModeK892orRho) { // K892 mode - // --- PID QA Kaon - histos.fill(HIST("QAMC/trkkaonTPCPID"), trk2pt, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAMC/trkkaonTOFPID"), trk2pt, trk2NSigmaKaTOF); - histos.fill(HIST("QAMC/trkkaonTPCTOFPID"), trk2NSigmaKaTPC, trk2NSigmaKaTOF); + } + } // IsMix + + if (lResonanceK1.Rapidity() > K1Cuts.cfgK1MaxRap || lResonanceK1.Rapidity() < K1Cuts.cfgK1MinRap) + continue; + if (lResonanceK1.Pt() < K1Cuts.cfgK1MinPt) + continue; + if (lPairPiPi.Pt() < cfgPiPiMinPt) + continue; + + auto k1Region = getK1MassRegion(lResonanceK1.M()); + + if constexpr (!IsMix) { + if (cfgFillQAPlots) { + histos.fill(HIST("QA/after/hpT_K1"), lResonanceK1.Pt()); + histos.fill(HIST("QA/after/hy_K1"), lResonanceK1.Rapidity()); + if (bTrack.sign() * sTrack.sign() < 0) { + histos.fill(HIST("QA/after/K1invmass"), lResonanceK1.M()); + // histos.fill(HIST("QA/after/K1DalitzOS"), m2K0sPiSec, m2PiPi); + if (k1Region == K1MassRegion::Signal) { + histos.fill(HIST("QA/after/K1DalitzOS_Signal"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBLeft) { + histos.fill(HIST("QA/after/K1DalitzOS_SBLeft"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBRight) { + histos.fill(HIST("QA/after/K1DalitzOS_SBRight"), m2K0sPiSec, m2PiPi); } - histos.fill(HIST("QAMC/trkkaonpT"), trk2pt); - histos.fill(HIST("QAMC/trkkaonDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QAMC/trkkaonDCAz"), trk2.dcaZ()); - } else { // Rho mode - // --- PID QA Pion - histos.fill(HIST("QAMC/trkppionTPCPID"), trk2pt, trk2NSigmaPiTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QAMC/trkppionTOFPID"), trk2pt, trk2NSigmaPiTOF); - histos.fill(HIST("QAMC/trkppionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } else { + histos.fill(HIST("QA/after/K1invmassLS"), lResonanceK1.M()); + // histos.fill(HIST("QA/after/K1DalitzLS"), m2K0sPiSec, m2PiPi); + if (k1Region == K1MassRegion::Signal) { + histos.fill(HIST("QA/after/K1DalitzLS_Signal"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBLeft) { + histos.fill(HIST("QA/after/K1DalitzLS_SBLeft"), m2K0sPiSec, m2PiPi); + } else if (k1Region == K1MassRegion::SBRight) { + histos.fill(HIST("QA/after/K1DalitzLS_SBRight"), m2K0sPiSec, m2PiPi); } - histos.fill(HIST("QAMC/trkppionpT"), trk2pt); - histos.fill(HIST("QAMC/trkppionDCAxy"), trk2.dcaXY()); - histos.fill(HIST("QAMC/trkppionDCAz"), trk2.dcaZ()); } + } + + if (bTrack.sign() * sTrack.sign() < 0) { + // bTrack sign minus for particle, plus for anti-particle + unsigned int typeK1 = bTrack.sign() < 0 ? BinType::kK1P : BinType::kK1A; + histos.fill(HIST("hInvmass_K1"), typeK1, lCentrality, lResonanceK1.Pt(), lResonanceK1.M()); } else { - histos.fill(HIST("k1invmass_MC_noK1"), lResonanceK1.M()); + unsigned int typeK1 = bTrack.sign() < 0 ? BinType::kK1P_Like : BinType::kK1A_Like; + histos.fill(HIST("hInvmass_K1"), typeK1, lCentrality, lResonanceK1.Pt(), lResonanceK1.M()); } - } // MC - } else { // Mixed event handling - unsigned int typeK1 = bTrack.sign() > 0 ? binType::kK1P_Mix : binType::kK1N_Mix; - unsigned int typeNormal = cfgModeK892orRho ? (trk1.sign() < 0 ? binAnti::kNormal : binAnti::kAnti) : binAnti::kNormal; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); - histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); - } - } // bTrack - } - } - void processData(aod::ResoCollision& collision, - aod::ResoTracks const& resotracks) - { - fillHistograms(collision, resotracks, resotracks); - } - PROCESS_SWITCH(k1analysis, processData, "Process Event for data without Partitioning", true); + if (BkgEstimationConfig.cfgFillRotBkg) { + for (int i = 0; i < BkgEstimationConfig.cfgNrotBkg; i++) { + auto lRotAngle = BkgEstimationConfig.cfgMinRot + i * ((BkgEstimationConfig.cfgMaxRot - BkgEstimationConfig.cfgMinRot) / (BkgEstimationConfig.cfgNrotBkg - 1)); + if (cfgFillQAPlots) { + histos.fill(HIST("QA/RotBkg/hRotBkg"), lRotAngle); + } + if (BkgEstimationConfig.cfgRotPion) { + lDaughterRot = lBachelor_pi; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot.Vect(); + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lDaughterRot + lResoKstar; + } else { + lDaughterRot = lResoKstar; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot; + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lBachelor_pi + lDaughterRot; + } + unsigned int typeK1 = bTrack.sign() < 0 ? BinType::kK1P_Rot : BinType::kK1A_Rot; + histos.fill(HIST("hInvmass_K1"), typeK1, lCentrality, lResonanceRot.Pt(), lResonanceRot.M()); - void processMC(aod::ResoCollision& collision, - soa::Join const& resotracks) - { - fillHistograms(collision, resotracks, resotracks); - } - PROCESS_SWITCH(k1analysis, processMC, "Process Event for MC", false); + } // NrotBkg + } // cfgFillRotBkg + } // IsMix + } // k0sIndex + } // strackIndex + } // btrackIndex + + count++; - void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents& resoParents) + } // fillHistograms + + void processData(EventCandidates::iterator const& collision, + TrackCandidates const& tracks, + V0Candidates const& v0s, + aod::BCsWithTimestamps const&) { - auto multiplicity = collision.cent(); - for (auto& part : resoParents) { // loop over all pre-filtered MC particles - if (abs(part.pdgCode()) != kK1Plus) // K892(0) - continue; - if (abs(part.y()) > 0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - if (cfgModeK892orRho) { - if (abs(part.daughterPDG1()) == 313 || abs(part.daughterPDG2()) == 313) { // At least one decay to K892 - pass2 = true; - } - if (abs(part.daughterPDG1()) == kPiPlus || abs(part.daughterPDG2()) == kPiPlus) { // At least one decay to Pion - pass1 = true; - } - if (!pass1 || !pass2) // If we have both decay products - continue; - } else { - if (abs(part.daughterPDG1()) == kPDGRho770 || abs(part.daughterPDG2()) == kPDGRho770) { // At least one decay to Rho - pass2 = true; - } - if (abs(part.daughterPDG1()) == kKPlus || abs(part.daughterPDG2()) == kKPlus) { // At least one decay to Kaon - pass1 = true; - } - if (!pass1 || !pass2) // If we have both decay products - continue; - } - auto typeNormal = part.pdgCode() > 0 ? binAnti::kNormal : binAnti::kAnti; - if (collision.isVtxIn10()) // INEL10 - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenINEL10 : binType::kK1N_GenINEL10; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } - if (collision.isVtxIn10() && collision.isInSel8()) // INEL>10, vtx10 - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenINELgt10 : binType::kK1N_GenINELgt10; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } - if (collision.isVtxIn10() && collision.isTriggerTVX()) // vtx10, TriggerTVX - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenTrig10 : binType::kK1N_GenTrig10; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } - if (collision.isInAfterAllCuts()) // after all event selection - { - auto typeK1 = part.pdgCode() > 0 ? binType::kK1P_GenEvtSel : binType::kK1N_GenEvtSel; - histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); - } + if (!colCuts.isSelected(collision)) // Default event selection + return; + if (EventCuts.cfgEvtUseRCTFlagChecker && !rctChecker(collision)) { + return; } + lCentrality = getCentrality(collision); + if (lCentrality < EventCuts.cfgEventCentralityMin || lCentrality > EventCuts.cfgEventCentralityMax) + return; + if (!collision.isInelGt0()) + return; + colCuts.fillQA(collision); + + fillHistograms(collision, tracks, tracks, v0s); } - PROCESS_SWITCH(k1analysis, processMCTrue, "Process Event for MC", false); - - // Processing Event Mixing - using BinningTypeVtxZT0M = ColumnBinningPolicy; - void processME(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) - { - auto tracksTuple = std::make_tuple(resotracks); - BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + PROCESS_SWITCH(K1analysis, processData, "Process Event for data without Partitioning", true); - for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { - fillHistograms(collision1, tracks1, tracks2); - } - }; - PROCESS_SWITCH(k1analysis, processME, "Process EventMixing light without partition", false); -}; +}; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-k1analysis"})}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/Resonances/k892analysispbpb.cxx b/PWGLF/Tasks/Resonances/k892analysispbpb.cxx index f0d2db3a2f7..93e1407027b 100644 --- a/PWGLF/Tasks/Resonances/k892analysispbpb.cxx +++ b/PWGLF/Tasks/Resonances/k892analysispbpb.cxx @@ -114,6 +114,7 @@ struct K892analysispbpb { Configurable cTPClowpt{"cTPClowpt", true, "apply TPC at low pt"}; Configurable cTOFonlyHighpt{"cTOFonlyHighpt", false, "apply TOF only at high pt"}; Configurable cTOFandTPCHighpt{"cTOFandTPCHighpt", false, "apply TOF and TPC at high pt"}; + Configurable circularCut{"circularCut", false, "apply TOF and TPC circular cut (applied only if cTOFandTPCHighpt is true)"}; // rotational bkg Configurable cfgNoRotations{"cfgNoRotations", 3, "Number of rotations per pair for rotbkg"}; @@ -409,10 +410,16 @@ struct K892analysispbpb { } else if (cTOFandTPCHighpt) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) <= cMaxTOFnSigmaKaon && candidate.hasTPC() && std::abs(candidate.tpcNSigmaKa()) <= cMaxTPCnSigmaKaon) { // tof and tpc cut - return true; - } + if (circularCut) { + + if (candidate.hasTOF() && candidate.hasTPC() && std::sqrt(std::pow(candidate.tpcNSigmaKa(), 2) + std::pow(candidate.tofNSigmaKa(), 2)) <= cMaxTPCnSigmaKaon) // tof and tpc circular cut + return true; + } else { + + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) <= cMaxTOFnSigmaKaon && candidate.hasTPC() && std::abs(candidate.tpcNSigmaKa()) <= cMaxTPCnSigmaKaon) // tof and tpc cut + return true; + } } else { if (candidate.hasTPC() && std::abs(candidate.tpcNSigmaKa()) <= cMaxTPCnSigmaKaon) { // tpc cut, tof when available @@ -447,8 +454,15 @@ struct K892analysispbpb { } else if (cTOFandTPCHighpt) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) <= cMaxTOFnSigmaPion && candidate.hasTPC() && std::abs(candidate.tpcNSigmaPi()) <= cMaxTPCnSigmaPion) { // tof and tpc cut - return true; + if (circularCut) { + + if (candidate.hasTOF() && candidate.hasTPC() && std::sqrt(std::pow(candidate.tpcNSigmaPi(), 2) + std::pow(candidate.tofNSigmaPi(), 2)) <= cMaxTPCnSigmaPion) // tof and tpc circular cut + return true; + + } else { + + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) <= cMaxTOFnSigmaPion && candidate.hasTPC() && std::abs(candidate.tpcNSigmaPi()) <= cMaxTPCnSigmaPion) // tof and tpc cut + return true; } } else { @@ -838,7 +852,7 @@ struct K892analysispbpb { Preslice trackPerCollision = aod::track::collisionId; - template + template void callFillHistoswithPartitions(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&) { if (cTPClowpt) { @@ -846,39 +860,51 @@ struct K892analysispbpb { auto candPosPitpc = posPitpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candNegKatpc = negKatpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candPosPitpc, candNegKatpc); - //-+ auto candNegPitpc = negPitpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candPosKatpc = posKatpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candNegPitpc, candPosKatpc); + if constexpr (!isLikeSig) { + fillHistograms(collision1, candPosPitpc, candNegKatpc); + fillHistograms(collision1, candNegPitpc, candPosKatpc); + } else { + fillHistograms(collision1, candPosPitpc, candPosKatpc); + fillHistograms(collision1, candNegPitpc, candNegKatpc); + } } else if (cTOFandTPCHighpt) { //+- auto candPosPitoftpc = posPitoftpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candNegKatoftpc = negKatoftpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candPosPitoftpc, candNegKatoftpc); - //-+ auto candNegPitoftpc = negPitoftpc->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candPosKatoftpc = posKatoftpc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candNegPitoftpc, candPosKatoftpc); + if constexpr (!isLikeSig) { + fillHistograms(collision1, candPosPitoftpc, candNegKatoftpc); + fillHistograms(collision1, candNegPitoftpc, candPosKatoftpc); + } else { + fillHistograms(collision1, candPosPitoftpc, candPosKatoftpc); + fillHistograms(collision1, candNegPitoftpc, candNegKatoftpc); + } } else if (cTOFonlyHighpt) { //+- auto candPosPitof = posPitof->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candNegKatof = negKatof->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candPosPitof, candNegKatof); - //-+ auto candNegPitof = negPitof->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto candPosKatof = posKatof->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - fillHistograms(collision1, candNegPitof, candPosKatof); + if constexpr (!isLikeSig) { + fillHistograms(collision1, candPosPitof, candNegKatof); + fillHistograms(collision1, candNegPitof, candPosKatof); + } else { + fillHistograms(collision1, candPosPitof, candPosKatof); + fillHistograms(collision1, candNegPitof, candNegKatof); + } } } @@ -898,8 +924,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hCollisionIndexSameE"), collision.globalIndex()); histos.fill(HIST("TestME/hnTrksSameE"), tracks.size()); } - // - callFillHistoswithPartitions(collision, tracks, collision, tracks); + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); } PROCESS_SWITCH(K892analysispbpb, processSameEvent, "Process Same event", true); @@ -918,8 +944,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hnTrksSameE"), tracks.size()); } - // - callFillHistoswithPartitions(collision, tracks, collision, tracks); + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); } PROCESS_SWITCH(K892analysispbpb, processSameEventRun2, "Process Same event Run2", false); @@ -929,8 +955,8 @@ struct K892analysispbpb { if (!myEventSelections(collision)) return; - // - callFillHistoswithPartitions(collision, tracks, collision, tracks); + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); } PROCESS_SWITCH(K892analysispbpb, processRotationalBkg, "Process Rotational Background", false); @@ -945,6 +971,17 @@ struct K892analysispbpb { } PROCESS_SWITCH(K892analysispbpb, processRotationalBkgMC, "Process Rotational Background MC", false); + void processLikeSign(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) + { + + if (!myEventSelections(collision)) + return; + + // + callFillHistoswithPartitions(collision, tracks, collision, tracks); + } + PROCESS_SWITCH(K892analysispbpb, processLikeSign, "Process Like Sign", false); + void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -966,8 +1003,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hnTrksMixedE"), tracks1.size()); } - // - callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); + // + callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); } } PROCESS_SWITCH(K892analysispbpb, processMixedEvent, "Process Mixed event", true); @@ -991,8 +1028,8 @@ struct K892analysispbpb { histos.fill(HIST("TestME/hnTrksMixedE"), tracks1.size()); } - // - callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); + // + callFillHistoswithPartitions(collision1, tracks1, collision2, tracks2); } } PROCESS_SWITCH(K892analysispbpb, processMixedEventRun2, "Process Mixed event Run2", false); diff --git a/PWGLF/Tasks/Resonances/kstar0analysis.cxx b/PWGLF/Tasks/Resonances/kstar0analysis.cxx new file mode 100644 index 00000000000..6fa7b2b21aa --- /dev/null +++ b/PWGLF/Tasks/Resonances/kstar0analysis.cxx @@ -0,0 +1,947 @@ +// 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 kstar0analysis.cxx +/// \brief the reconstruction of k*0(892) resonance analysis using K\pi decay channel +/// \author Hirak Kumar Koley + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct kstar0analysis { + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + //================================== + //|| + //|| Selection + //|| + //================================== + + // Event Selection + Configurable cfgEventSelections{"cfgEventSelections", "sel8", "Set event selection"}; + Configurable cfgEventVtxCut{"cfgEventVtxCut", 10.0, "V_z cut selection"}; + ConfigurableAxis cfgCentAxis{"cfgCentAxis", {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}, "Binning of the centrality axis"}; + Configurable cfgOccupancySel{"cfgOccupancySel", false, "Occupancy selection"}; + Configurable cfgOccupancyMax{"cfgOccupancyMax", 999999., "maximum occupancy of tracks in neighbouring collisions in a given time range"}; + Configurable cfgOccupancyMin{"cfgOccupancyMin", -100., "minimum occupancy of tracks in neighbouring collisions in a given time range"}; + + // Track Selection + // General + Configurable cfgTrackMinPt{"cfgTrackMinPt", 0.15, "set track min pT"}; + Configurable cfgTrackMaxEta{"cfgTrackMaxEta", 0.8, "set track max Eta"}; + Configurable cfgTrackMaxDCArToPVcut{"cfgTrackMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + Configurable cfgTrackMaxDCAzToPVcut{"cfgTrackMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cfgTrackGlobalSel{"cfgTrackGlobalSel", true, "Global track selection"}; + Configurable cfgTrackPrimaryTrack{"cfgTrackPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgTrackConnectedToPV{"cfgTrackConnectedToPV", true, "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgTrackGlobalWoDCATrack{"cfgTrackGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + + // TPC + Configurable cfgTrackFindableTPCClusters{"cfgTrackFindableTPCClusters", 50, "nFindable TPC Clusters"}; + Configurable cfgTrackTPCCrossedRows{"cfgTrackTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfgTrackRowsOverFindable{"cfgTrackRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; + Configurable cfgTrackTPCChi2{"cfgTrackTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; + + // ITS + Configurable cfgTrackITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; + + // PID + Configurable cfgTrackTPCPID{"cfgTrackTPCPID", true, "Enables TPC PID"}; + Configurable cfgTrackTOFPID{"cfgTrackTOFPID", true, "Enables TOF PID"}; + Configurable cfgTrackSquarePIDCut{"cfgTrackSqurePIDCut", true, "Enables PID cut shape square switch"}; + Configurable cfgTrackCirclePIDCut{"cfgTrackCirclePIDCut", true, "Enables PID cut shape circle switch"}; + Configurable cfgTrackCircleValue{"cfgTrackCircleValue", 2, "Enables TOF TPC PID circle cut value"}; + Configurable cfgTrackTOFHard{"cfgTrackTOFHard", false, "Enables TOF Hard"}; + + Configurable cfgTrackTPCPIDnSig{"cfgTrackTPCPIDnSig", 4.0, "nTPC PID sigma"}; + Configurable cfgTrackTOFPIDnSig{"cfgTrackTOFPIDnSig", 4.0, "nTOF PID sigma"}; + Configurable cDebugLevel{"cDebugLevel", 0, "Resolution of Debug"}; + + // Mixing + ConfigurableAxis cfgBinsMixMult{"cfgBinsCent", {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 cfgBinsMixVtx{"cfgBinsMixVtx", {VARIABLE_WIDTH, -10.0f, -5.f, 0.f, 5.f, 10.f}, "Mixing bins - z-vertex"}; + Configurable cfgMixNMixedEvents{"cfgMixNMixedEvents", 10, "Number of mixed events per event"}; + Configurable cfgVtxMixCut{"cfgVtxMixCut", 10, "Vertex Mix Cut"}; + + // MCGen + Configurable cfgForceGenReco{"cfgForceGenReco", false, "Only consider events which are reconstructed (neglect event-loss)"}; + Configurable cfgReqMcEffPID{"cfgReqMcEffPID", false, "Request McEfficiency PID"}; + + // Pair + Configurable cfgMinvNBins{"cfgMinvNBins", 300, "Number of bins for Minv axis"}; + Configurable cfgMinvMin{"cfgMinvMin", 0.60, "Minimum Minv value"}; + Configurable cfgMinvMax{"cfgMinvMax", 1.20, "Maximum Minv value"}; + + // Histogram + ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2, 0.2}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; + Configurable cfgEventCutQA{"cfgEventCutsQA", false, "Enable Event QA Hists"}; + Configurable cfgTrackCutQA{"cfgTrackCutQA", false, "Enable Track QA Hists"}; + + Configurable cfgMCHistos{"cfgMCHistos", false, "Enable MC Hists"}; + Configurable cfgMixedHistos{"cfgMixedHistos", false, "Enable Mixed Histos"}; + Configurable cfgManualEvSel{"cfgManualEvSel", false, "Enable Manual EvSel"}; + + // Main + void init(o2::framework::InitContext&) + { + // HISTOGRAMS + const AxisSpec axisEta{30, -1.5, +1.5, "#eta"}; + const AxisSpec axisPhi{200, -1, +7, "#phi"}; + const AxisSpec ptAxis = {200, 0, 20.0}; + const AxisSpec pidAxis = {120, -6, 6}; + const AxisSpec minvAxis = {cfgMinvNBins, cfgMinvMin, cfgMinvMax}; + const AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; + const AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; + + if (cfgEventCutQA) { + histos.add("hEvent_Cut", "Number of event after cuts", kTH1D, {{13, -0.5, 12.5}}); + histos.add("hPosZ_BC", "hPosZ_BC", kTH1F, {{300, -15.0, 15.0}}); + histos.add("hPosZ_AC", "hPosZ_AC", kTH1F, {{300, -15.0, 15.0}}); + histos.add("hcentFT0C_BC", "centFT0C_BC", kTH1F, {{110, 0.0, 110.0}}); + histos.add("hcentFT0C_AC", "centFT0C_AC", kTH1F, {{110, 0.0, 110.0}}); + } + if (cfgTrackCutQA) { + histos.add("hDCArToPv_BC", "DCArToPv_BC", kTH1F, {axisDCAxy}); + histos.add("hDCAzToPv_BC", "DCAzToPv_BC", kTH1F, {axisDCAz}); + histos.add("hIsPrim_BC", "hIsPrim_BC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsGood_BC", "hIsGood_BC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsPrimCont_BC", "hIsPrimCont_BC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hFindableTPCClusters_BC", "hFindableTPCClusters_BC", kTH1F, {{200, 0, 200}}); + histos.add("hFindableTPCRows_BC", "hFindableTPCRows_BC", kTH1F, {{200, 0, 200}}); + histos.add("hClustersVsRows_BC", "hClustersVsRows_BC", kTH1F, {{200, 0, 2}}); + histos.add("hTPCChi2_BC", "hTPCChi2_BC", kTH1F, {{200, 0, 100}}); + histos.add("hITSChi2_BC", "hITSChi2_BC", kTH1F, {{200, 0, 100}}); + histos.add("QA_nSigma_pion_TPC_BC", "QA_nSigma_pion_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_pion_TOF_BC", "QA_nSigma_pion_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_pion_TPC_TOF_BC", "QA_pion_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TPC_BC", "QA_nSigma_kaon_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TOF_BC", "QA_nSigma_kaon_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_kaon_TPC_TOF_BC", "QA_kaon_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_track_pT_BC", "QA_track_pT_BC", kTH1F, {{13, 0.0, 13.0}}); + + histos.add("hDCArToPv_AC", "DCArToPv_AC", kTH1F, {axisDCAxy}); + histos.add("hDCAzToPv_AC", "DCAzToPv_AC", kTH1F, {axisDCAz}); + histos.add("hIsPrim_AC", "hIsPrim_AC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsGood_AC", "hIsGood_AC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hIsPrimCont_AC", "hIsPrimCont_AC", kTH1F, {{2, -0.5, 1.5}}); + histos.add("hFindableTPCClusters_AC", "hFindableTPCClusters_AC", kTH1F, {{200, 0, 200}}); + histos.add("hFindableTPCRows_AC", "hFindableTPCRows_AC", kTH1F, {{200, 0, 200}}); + histos.add("hClustersVsRows_AC", "hClustersVsRows_AC", kTH1F, {{200, 0, 2}}); + histos.add("hTPCChi2_AC", "hTPCChi2_AC", kTH1F, {{200, 0, 100}}); + histos.add("hITSChi2_AC", "hITSChi2_AC", kTH1F, {{200, 0, 100}}); + histos.add("QA_nSigma_pion_TPC_AC", "QA_nSigma_pion_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_pion_TOF_AC", "QA_nSigma_pion_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_pion_TPC_TOF_AC", "QA_pion_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TPC_AC", "QA_nSigma_kaon_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_nSigma_kaon_TOF_AC", "QA_nSigma_kaon_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA_kaon_TPC_TOF_AC", "QA_kaon_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); + histos.add("QA_track_pT_AC", "QA_track_pT_AC", kTH1F, {{13, 0.0, 13.0}}); + } + + //////////////////////////////////// + histos.add("nEvents", "nEvents", kTH1F, {{7, 0.0, 7.0}}); + histos.add("hUSS_KPi", "hUSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hUSS_PiK", "hUSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hLSS_KPi", "hLSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hLSS_PiK", "hLSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + + if (cfgMixedHistos) { + histos.add("hUSS_KPi_Mix", "hUSS_KPi_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hUSS_PiK_Mix", "hUSS_PiK_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + } + if (cfgMCHistos) { + histos.add("nEvents_Gen", "nEvents_Gen", kTH1F, {{4, 0.0, 4.0}}); + histos.add("hUSS_TrueRec", "hUSS_TrueRec", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hGen_pT_Raw", "Gen_pT_Raw (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hGen_pT_GoodEv", "hGen_pT_GoodEv", kTHnSparseF, {cfgCentAxis, ptAxis}); + } + + if (cfgEventCutQA) { + std::shared_ptr hCutFlow = histos.get(HIST("hEvent_Cut")); + std::vector eventCutLabels = { + "All Events", + "sel8", + Form("|Vz| < %.1f", cfgEventVtxCut.value), + "kIsGoodZvtxFT0vsPV", + "kNoSameBunchPileup", + "kNoTimeFrameBorder", + "kNoITSROFrameBorder", + "kNoCollInTimeRangeStandard", + "kIsGoodITSLayersAll", + Form("Occupancy < %.0f", cfgOccupancyMax.value), + "All passed events"}; + + for (size_t i = 0; i < eventCutLabels.size(); ++i) { + hCutFlow->GetXaxis()->SetBinLabel(i + 1, eventCutLabels[i].c_str()); + } + } + } // end of init + + //====================== + //|| For LF Analysis + //====================== + using EventCandidates = soa::Join; //, aod::CentFT0Ms, aod::CentFT0As + using EventCandidatesTrue = aod::McCollisions; + using TrackCandidates = soa::Join; + using TrackCandidatesMC = soa::Join; + + // For Mixed Event + using BinningType = ColumnBinningPolicy; + + Partition kaon = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfgTrackTPCPIDnSig); + Partition pion = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaPi) <= cfgTrackTPCPIDnSig); + Partition kaonMC = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfgTrackTPCPIDnSig); + Partition pionMC = !cfgTrackTPCPID || (nabs(aod::pidtpc::tpcNSigmaPi) <= cfgTrackTPCPIDnSig); + + double massKa = o2::constants::physics::MassKPlus; + double massPi = o2::constants::physics::MassPiMinus; + + //================================== + //|| + //|| Helper Templates + //|| + //================================== + template + void fillQA(const bool pass, const objType& obj, const int objecttype = 0) + { + if (objecttype == 1) { + if constexpr (requires { obj.posZ(); }) { + if (!pass) { + histos.fill(HIST("hPosZ_BC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); + } else { + histos.fill(HIST("hPosZ_AC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); + } + } + } // eventSelection histogram + + if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { + if (objecttype == 3) { + if (!pass) { + histos.fill(HIST("hDCArToPv_BC"), obj.dcaXY()); + histos.fill(HIST("hDCAzToPv_BC"), obj.dcaZ()); + histos.fill(HIST("hIsPrim_BC"), obj.isPrimaryTrack()); + histos.fill(HIST("hIsGood_BC"), obj.isGlobalTrackWoDCA()); + histos.fill(HIST("hIsPrimCont_BC"), obj.isPVContributor()); + histos.fill(HIST("hFindableTPCClusters_BC"), obj.tpcNClsFindable()); + histos.fill(HIST("hFindableTPCRows_BC"), obj.tpcNClsCrossedRows()); + histos.fill(HIST("hClustersVsRows_BC"), obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hTPCChi2_BC"), obj.tpcChi2NCl()); + histos.fill(HIST("hITSChi2_BC"), obj.itsChi2NCl()); + histos.fill(HIST("QA_track_pT_BC"), obj.pt()); + } else { + histos.fill(HIST("hDCArToPv_AC"), obj.dcaXY()); + histos.fill(HIST("hDCAzToPv_AC"), obj.dcaZ()); + histos.fill(HIST("hIsPrim_AC"), obj.isPrimaryTrack()); + histos.fill(HIST("hIsGood_AC"), obj.isGlobalTrackWoDCA()); + histos.fill(HIST("hIsPrimCont_AC"), obj.isPVContributor()); + histos.fill(HIST("hFindableTPCClusters_AC"), obj.tpcNClsFindable()); + histos.fill(HIST("hFindableTPCRows_AC"), obj.tpcNClsCrossedRows()); + histos.fill(HIST("hClustersVsRows_AC"), obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hTPCChi2_AC"), obj.tpcChi2NCl()); + histos.fill(HIST("hITSChi2_AC"), obj.itsChi2NCl()); + histos.fill(HIST("QA_track_pT_AC"), obj.pt()); + } + } + } // trackSelection + if (objecttype == 4) { + if constexpr (requires { obj.pt(); }) { + if (!pass) { + histos.fill(HIST("QA_nSigma_kaon_TPC_BC"), obj.pt(), obj.tpcNSigmaKa()); + histos.fill(HIST("QA_nSigma_kaon_TOF_BC"), obj.pt(), obj.tofNSigmaKa()); + histos.fill(HIST("QA_kaon_TPC_TOF_BC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); + } else { + histos.fill(HIST("QA_nSigma_kaon_TPC_AC"), obj.pt(), obj.tpcNSigmaKa()); + histos.fill(HIST("QA_nSigma_kaon_TOF_AC"), obj.pt(), obj.tofNSigmaKa()); + histos.fill(HIST("QA_kaon_TPC_TOF_AC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); + } + } + } // kaon pid Selection + if (objecttype == 5) { + if constexpr (requires { obj.pt(); }) { + if (!pass) { + histos.fill(HIST("QA_nSigma_pion_TPC_BC"), obj.pt(), obj.tpcNSigmaPi()); + histos.fill(HIST("QA_nSigma_pion_TOF_BC"), obj.pt(), obj.tofNSigmaPi()); + histos.fill(HIST("QA_pion_TPC_TOF_BC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + } else { + histos.fill(HIST("QA_nSigma_pion_TPC_AC"), obj.pt(), obj.tpcNSigmaPi()); + histos.fill(HIST("QA_nSigma_pion_TOF_AC"), obj.pt(), obj.tofNSigmaPi()); + histos.fill(HIST("QA_pion_TPC_TOF_AC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + } + } + } // pion pid Selection + } // fill QA + + enum class objectType { MB, + MBRecParticle }; + + template + void fillMinv(objectType type, const TrackType& trk1, const TrackType& trk2, const ROOT::Math::PxPyPzMVector& lReso, double centrality, bool IsMix, bool flip) + { + double conjugate = trk1.sign() * trk2.sign(); + switch (type) { + case objectType::MB: + if (IsMix && cfgMixedHistos) { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi_Mix"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK_Mix"), centrality, lReso.Pt(), lReso.M()); + } + } else { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK"), centrality, lReso.Pt(), lReso.M()); + } else if (conjugate > 0) { + if (!flip) + histos.fill(HIST("hLSS_KPi"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hLSS_PiK"), centrality, lReso.Pt(), lReso.M()); + } + } + break; + + case objectType::MBRecParticle: + if (cfgMCHistos) { + if (conjugate < 0) { + histos.fill(HIST("hUSS_TrueRec"), centrality, lReso.Pt(), lReso.M()); + } + } + break; + } // switch + } // fillMinv + //====================================================================== + + template + std::pair eventSelection(const EventType event, const bool QA) + { + if (cfgEventCutQA && QA) { + fillQA(false, event, 1); + histos.fill(HIST("hEvent_Cut"), 0); + } + + if (!event.sel8()) + return {false, 1}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 1); + } + if (std::abs(event.posZ()) > cfgEventVtxCut) + return {false, 2}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 2); + } + if (!event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) + return {false, 3}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 3); + } + if (!event.selection_bit(aod::evsel::kNoSameBunchPileup)) + return {false, 4}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 4); + } + if (!event.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return {false, 5}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 5); + } + if (!event.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return {false, 6}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 6); + } + if (!event.selection_bit(aod::evsel::kNoCollInTimeRangeStandard)) + return {false, 7}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 7); + } + if (!event.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return {false, 8}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 8); + } + if (cfgOccupancySel && (event.trackOccupancyInTimeRange() > cfgOccupancyMax || event.trackOccupancyInTimeRange() < cfgOccupancyMin)) + return {false, 9}; + if (cfgEventCutQA && QA) { + histos.fill(HIST("hEvent_Cut"), 9); + } + + if (cfgEventCutQA && QA) { + fillQA(true, event, 1); + histos.fill(HIST("hEvent_Cut"), 10); + } + return {true, 11}; + }; + + template + bool trackSelection(const TracksType track, const bool QA) + { + if (cfgTrackCutQA && QA) { + fillQA(false, track, 3); + } + + if (cfgTrackGlobalSel && !track.isGlobalTrack()) + return false; + if (track.pt() < cfgTrackMinPt) + return false; + if (std::abs(track.eta()) > cfgTrackMaxEta) + return false; + if (std::abs(track.dcaXY()) > cfgTrackMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cfgTrackMaxDCAzToPVcut) + return false; + if (cfgTrackPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgTrackGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgTrackFindableTPCClusters > 0 && track.tpcNClsFindable() < cfgTrackFindableTPCClusters) + return false; + if (track.tpcNClsCrossedRows() < cfgTrackTPCCrossedRows) + return false; + if (cfgTrackRowsOverFindable > 0 && track.tpcCrossedRowsOverFindableCls() > cfgTrackRowsOverFindable) + return false; + if (track.tpcChi2NCl() > cfgTrackTPCChi2) + return false; + if (track.itsChi2NCl() > cfgTrackITSChi2) + return false; + if (cfgTrackConnectedToPV && !track.isPVContributor()) + return false; + + if (cfgTrackCutQA && QA) { + fillQA(true, track, 3); + } + return true; + }; + + template + bool trackPIDKaon(const TrackPID& candidate, const bool QA) + { + double tpcpid = 0; + double tofpid = 0; + bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfgTrackCutQA && QA) { + fillQA(false, candidate, 4); + } + + // TPC + if (cfgTrackSquarePIDCut) { + if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) + tpcPIDPassed = true; + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cfgTrackTOFPIDnSig) { + tofPIDPassed = true; + } + } else { + if (!cfgTrackTOFHard) { + tofPIDPassed = true; + } else { + tofPIDPassed = false; + } + } + } // end of square cut + if (cfgTrackCirclePIDCut) { + if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) + tpcpid = std::abs(candidate.tpcNSigmaKa()); + tofpid = 0; + + if (candidate.hasTOF()) { + tofpid = std::abs(candidate.tofNSigmaKa()); + } else { + if (cfgTrackTOFHard) { + tofpid = 999; + } + } + if (tpcpid * tpcpid + tofpid * tofpid < cfgTrackCircleValue) { + tpcPIDPassed = true; + tofPIDPassed = true; + } + } // circular cut + + // TPC & TOF + if (tpcPIDPassed && tofPIDPassed) { + if (cfgTrackCutQA && QA) { + fillQA(true, candidate, 4); + } + return true; + } + return false; + } + + template + bool trackPIDPion(const TrackPID& candidate, const bool QA) + { + double tpcpid = 0; + double tofpid = 0; + bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfgTrackCutQA && QA) { + fillQA(false, candidate, 5); + } + + // TPC + if (cfgTrackSquarePIDCut) { + if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) + tpcPIDPassed = true; + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cfgTrackTOFPIDnSig) { + tofPIDPassed = true; + } + } else { + if (!cfgTrackTOFHard) { + tofPIDPassed = true; + } else { + tofPIDPassed = false; + } + } + } // end of square cut + if (cfgTrackCirclePIDCut) { + if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) + tpcpid = std::abs(candidate.tpcNSigmaPi()); + tofpid = 0; + + if (candidate.hasTOF()) { + tofpid = std::abs(candidate.tofNSigmaPi()); + } else { + if (cfgTrackTOFHard) { + tofpid = 999; + } + } + if (tpcpid * tpcpid + tofpid * tofpid < cfgTrackCircleValue) { + tpcPIDPassed = true; + tofPIDPassed = true; + } + } // circular cut + + // TPC & TOF + if (tpcPIDPassed && tofPIDPassed) { + if (cfgTrackCutQA && QA) { + fillQA(true, candidate, 5); + } + return true; + } + return false; + } + + template + ROOT::Math::PxPyPzMVector minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA, const bool flip) + { + if (!trackSelection(trk1, false) || !trackSelection(trk2, false)) + return {}; + + if (!trackPIDKaon(trk1, QA) || !trackPIDPion(trk2, QA)) + return {}; + + if (trk1.globalIndex() >= trk2.globalIndex()) + return {}; + + ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResonance; + if (!flip) { + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massKa); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); + } else { + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massKa); + } + lResonance = lDecayDaughter1 + lDecayDaughter2; + + if (std::abs(lResonance.Eta()) > cfgTrackMaxEta) + return {}; + return {lResonance}; + } + + template + ROOT::Math::PxPyPzMVector TrueReconstruction(const TracksType& trk1, const TracksType& trk2) + { + double conjugate = trk1.sign() * trk2.sign(); + if (conjugate > 0) + return {}; + + auto particle1 = trk1.mcParticle(); + auto particle2 = trk2.mcParticle(); + + if (!particle1.has_mothers() || !particle2.has_mothers()) { + return {}; + } + + std::vector mothers1{}; + std::vector mothers1PDG{}; + for (auto& particle1_mom : particle1.template mothers_as()) { + mothers1.push_back(particle1_mom.globalIndex()); + mothers1PDG.push_back(particle1_mom.pdgCode()); + } + + std::vector mothers2{}; + std::vector mothers2PDG{}; + for (auto& particle2_mom : particle2.template mothers_as()) { + mothers2.push_back(particle2_mom.globalIndex()); + mothers2PDG.push_back(particle2_mom.pdgCode()); + } + + if (mothers1PDG[0] != 313) + return {}; // mother not K*0 + if (mothers2PDG[0] != 313) + return {}; // mothers not K*0 + + if (mothers1[0] != mothers2[0]) + return {}; // Kaon and pion not from the same K*0 + + if (std::fabs(particle1.pdgCode()) != 211 && std::fabs(particle1.pdgCode()) != 321) + return {}; + if (std::fabs(particle2.pdgCode()) != 211 && std::fabs(particle2.pdgCode()) != 321) + return {}; + + double track1_mass, track2_mass; + if (std::fabs(particle1.pdgCode()) == 211) { + track1_mass = massPi; + } else { + track1_mass = massKa; + } + + if (std::fabs(particle2.pdgCode()) == 211) { + track2_mass = massPi; + } else { + track2_mass = massKa; + } + + if (track1_mass == track2_mass) { + return {}; + } + + ROOT::Math::PxPyPzMVector lTrueDaughter1, lTrueDaughter2, lTrueReso; + lTrueDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), track1_mass); + lTrueDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), track2_mass); + lTrueReso = lTrueDaughter1 + lTrueDaughter2; + + if (lTrueReso.M() < 0) + return {}; + + return {lTrueReso}; + } + + template + void TrackSlicing(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) + { + auto tracks1 = kaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto tracks2 = pion->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + auto centrality = collision1.centFT0C(); + + for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (bool flip : {false, true}) { + auto lReso = minvReconstruction(trk1, trk2, QA, flip); + if (lReso.M() < 0) + continue; + + fillMinv(objectType::MB, trk1, trk2, lReso, centrality, IsMix, flip); + } // flip + } // for + } // TrackSlicing + + template + void TrackSlicingMC(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) + { + auto tracks1 = kaonMC->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto tracks2 = pionMC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + auto centrality = collision1.centFT0C(); + + for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) + continue; + + for (bool flip : {false, true}) { + auto lReso = minvReconstruction(trk1, trk2, QA, flip); + if (lReso.M() < 0) + continue; + + fillMinv(objectType::MB, trk1, trk2, lReso, centrality, IsMix, flip); + } // flip + + //============================ + //| True Reconstruction + //============================ + auto lTrueReso = TrueReconstruction(trk1, trk2); + fillMinv(objectType::MBRecParticle, trk1, trk2, lTrueReso, centrality, IsMix, false); + } // tracks + } // TrackSlicingMC + + //======================================================= + //| + //| DATA STUFF (SE) + //| + //======================================================= + int nEvents = 0; + void processDataSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks) + { + if (cDebugLevel > 0) { + nEvents++; + if ((nEvents + 1) % 10000 == 0) { + std::cout << "Processed Data Events: " << nEvents << std::endl; + } + } + + auto [goodEv, code] = eventSelection(collision, true); + histos.fill(HIST("nEvents"), 0.5); + + if (!goodEv) + return; + + bool INELgt0 = false; + for (const auto& track : tracks) { + if (!trackSelection(track, true)) + continue; + if (std::fabs(track.eta()) < cfgTrackMaxEta) { + INELgt0 = true; + } + } + if (!INELgt0) + return; + histos.fill(HIST("nEvents"), 1.5); + + TrackSlicing(collision, tracks, collision, tracks, false, true); + + } // processSameEvents + PROCESS_SWITCH(kstar0analysis, processDataSameEvent, "process Data Same Event", false); + + //======================================================= + //| + //| DATA STUFF (ME) + //| + //======================================================= + int nEventsMix = 0; + void processDataMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + BinningType colBinning{{cfgBinsMixVtx, cfgBinsMixMult}, true}; // true is for 'ignore overflows' (true by default) + SameKindPair pairs{colBinning, cfgMixNMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (cDebugLevel > 0) { + nEventsMix++; + if ((nEventsMix + 1) % 10000 == 0) { + std::cout << "Processed DATA Mixed Events : " << nEventsMix << std::endl; + } + } + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); + bool VtxMixFlag = false; + bool CentMixFlag = false; + // bool OccupanacyMixFlag = false; + if (std::fabs(collision1.posZ() - collision2.posZ()) <= cfgVtxMixCut) // set default to maybe 10 + VtxMixFlag = true; + if (std::fabs(collision1.centFT0C() - collision2.centFT0C()) <= cfgVtxMixCut) // set default to maybe 10 + CentMixFlag = true; + + if (!goodEv1 || !goodEv2) + continue; + if (!CentMixFlag) + continue; + if (!VtxMixFlag) + continue; + + TrackSlicing(collision1, tracks1, collision2, tracks2, true, false); + } + } + PROCESS_SWITCH(kstar0analysis, processDataMixedEvent, "process DATA Mixed Event", false); + + //======================================================= + //| + //| MC STUFF (SE) + //| + //========================================================= + int nEventsMC = 0; + void processSameEventMC(EventCandidates::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&) + { + if (cDebugLevel > 0) { + nEventsMC++; + if ((nEventsMC + 1) % 10000 == 0) { + double histmem = histos.getSize(); + std::cout << histmem << std::endl; + std::cout << "process_SameEvent_MC: " << nEventsMC << std::endl; + } + } + auto [goodEv, code] = eventSelection(collision, true); + + histos.fill(HIST("nEvents"), 0.5); + + if (!goodEv) + return; + + bool INELgt0 = false; + for (const auto& track : tracks) { + if (!trackSelection(track, true)) + continue; + if (std::fabs(track.eta()) < cfgTrackMaxEta) { + INELgt0 = true; + } + } + if (!INELgt0) + return; + + histos.fill(HIST("nEvents"), 1.5); + + TrackSlicingMC(collision, tracks, collision, tracks, false, true); + } // processSameEvents_MC + PROCESS_SWITCH(kstar0analysis, processSameEventMC, "process Same Event MC", false); + + //======================================================= + //| + //| MC STUFF (ME) + //| + //======================================================= + int nEventsMCMix = 0; + void processMixedEventMC(EventCandidates const& collisions, TrackCandidatesMC const& tracks, aod::McParticles const&) + { + auto tracksTuple = std::make_tuple(tracks); + BinningType colBinning{{cfgBinsMixVtx, cfgBinsMixMult}, true}; // true is for 'ignore overflows' (true by default) + SameKindPair pairs{colBinning, cfgMixNMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (cDebugLevel > 0) { + nEventsMCMix++; + if ((nEventsMCMix + 1) % 10000 == 0) { + std::cout << "Processed Mixed Events: " << nEventsMCMix << std::endl; + } + } + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); + if (!goodEv1 || !goodEv2) { + continue; + } + + TrackSlicingMC(collision1, tracks1, collision2, tracks2, true, false); + } // mixing + } // processMixedEvent_MC + PROCESS_SWITCH(kstar0analysis, processMixedEventMC, "process Mixed Event MC", false); + + //====================================== + //| + //| GENERATED STUFF + //| + //====================================== + int nEventsGen = 0; + void processGen(EventCandidatesTrue::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles) + { + if (cDebugLevel > 0) { + ++nEventsGen; + if (nEventsGen % 10000 == 0) { + std::cout << "Processed MC (GEN) Events: " << nEventsGen << std::endl; + } + } + //======================= + //|| Event & Signal loss + //======================= + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 0.5); + } + + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + if (fabs(collision.posZ()) > cfgEventVtxCut) + break; + + if (cfgMCHistos) { + histos.fill(HIST("hGen_pT_Raw"), particle.pt()); + } + } // Unreconstructed collisions(=Raw coll) for correction + + if (recocolls.size() <= 0) { // not reconstructed + if (cfgForceGenReco) { + return; + } + } + double centrality = -1; + for (auto& recocoll : recocolls) { + centrality = recocoll.centFT0C(); + auto [goodEv, code] = eventSelection(recocoll, true); + + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 1.5); + } + if (!goodEv) + continue; + } // recocolls (=reconstructed collisions) + + //================= + //|| Efficiency + //================= + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; // Not K*0 + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 2.5); + histos.fill(HIST("hGen_pT_GoodEv"), centrality, particle.pt()); + } // cfgMCHistos + } // loop over particles + } // processMCTrue + PROCESS_SWITCH(kstar0analysis, processGen, "process Generated Particles", false); + + void processEventsDummy(EventCandidates::iterator const&, TrackCandidates const&) + { + return; + } + PROCESS_SWITCH(kstar0analysis, processEventsDummy, "dummy", false); +}; // kstar0analysis +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx index 19c0e261938..47a723d44d4 100644 --- a/PWGLF/Tasks/Resonances/kstar892LightIon.cxx +++ b/PWGLF/Tasks/Resonances/kstar892LightIon.cxx @@ -14,6 +14,8 @@ /// \author Subhadeep Mandal /// \since 22/11/2025 +#include "PWGLF/Utils/inelGt.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" @@ -30,6 +32,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" @@ -79,6 +82,8 @@ struct Kstar892LightIon { struct : ConfigurableGroup { // Configurables for event selections Configurable cfgVrtxZCut{"cfgVrtxZCut", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable isApplysel8{"isApplysel8", true, "Apply sel8 event selection"}; + Configurable isApplyINELgt0{"isApplyINELgt0", true, "INEL>0 selection"}; Configurable isTriggerTVX{"isTriggerTVX", true, "TriggerTVX"}; Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", true, "IsGoodZvtxFT0vsPV"}; Configurable isApplyOccCut{"isApplyOccCut", false, "Apply occupancy cut"}; @@ -92,6 +97,13 @@ struct Kstar892LightIon { Configurable isVertexITSTPC{"isVertexITSTPC", false, "Vertex ITS TPC"}; Configurable isVertexTOFMatched{"isVertexTOFMatched", false, "Vertex TOF Matched"}; + Configurable isApplyhasFT0{"isApplyhasFT0", false, "Apply has_foundFT0 event selection"}; + + // check + Configurable isApplyMCGenInelgt0{"isApplyMCGenInelgt0", true, "Apply INEL>0 cut in MC Gen Collisions"}; + Configurable isApplyMCGenTVX{"isApplyMCGenTVX", true, "Apply TVX cut in MC Gen Collisions"}; + Configurable isApplyMCGenVz{"isApplyMCGenVz", true, "Apply Vz cut in MC Gen Collisions"}; + // Configurables for track selections Configurable isPVContributor{"isPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor Configurable isPrimaryTrack{"isPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz @@ -129,6 +141,9 @@ struct Kstar892LightIon { Configurable onlyTOFHIT{"onlyTOFHIT", false, "accept only TOF hit tracks at high pt"}; Configurable onlyTPC{"onlyTPC", false, "only TPC tracks"}; Configurable isApplypTdepPID{"isApplypTdepPID", false, "Apply pT dependent PID"}; + Configurable isApplypTdepPIDwTOF{"isApplypTdepPIDwTOF", false, "Apply pT dependent PID with compulsory TOF condition in a pT range"}; + Configurable isApplyMID{"isApplyMID", false, "Apply particle MID"}; + Configurable isApplypTdepMID{"isApplypTdepMID", false, "Apply pT dependent particle MID"}; Configurable nsigmaCutTPCPi{"nsigmaCutTPCPi", 3.0, "TPC Nsigma cut for pions"}; Configurable nsigmaCutTPCKa{"nsigmaCutTPCKa", 3.0, "TPC Nsigma cut for kaons"}; @@ -137,8 +152,16 @@ struct Kstar892LightIon { Configurable nsigmaCutCombinedKa{"nsigmaCutCombinedKa", 3.0, "Combined Nsigma cut for kaon"}; Configurable nsigmaCutCombinedPi{"nsigmaCutCombinedPi", 3.0, "Combined Nsigma cut for pion"}; + Configurable nsigmaCutCombinedMID{"nsigmaCutCombinedMID", 3.0, "Combined Nsigma cut for pion in MID"}; + Configurable nsigmaCutTPCMID{"nsigmaCutTPCMID", 1.0, "MID Nsigma cut for pion in TPC"}; + // Fixed variables float lowPtCutPID = 0.5; + + Configurable selHasFT0MC{"selHasFT0MC", true, "Has FT0?"}; + Configurable isZvtxPosSelMC{"isZvtxPosSelMC", true, "Zvtx position selection for MC events?"}; + Configurable selTVXMC{"selTVXMC", true, "apply TVX selection in MC?"}; + Configurable selINELgt0MC{"selINELgt0MC", true, "Select INEL > 0?"}; } selectionConfig; Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; @@ -152,6 +175,12 @@ struct Kstar892LightIon { Configurable selectCentEstimator{"selectCentEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C, 3 - FV0A"}; + Configurable nchAcceptance{"nchAcceptance", 0.5, "Eta window to measure Nch MC for Nch vs Cent distribution"}; + + Configurable nBinsNch{"nBinsNch", 400, "N bins Nch (|eta|<0.8)"}; + Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; + Configurable maxNch{"maxNch", 400, "Max Nch (|eta|<0.8)"}; + // Configurable for histograms ConfigurableAxis binsCentPlot{"binsCentPlot", {110, 0.0, 110}, "Centrality axis"}; ConfigurableAxis axisdEdx{"axisdEdx", {1, 0.0f, 200.0f}, "dE/dx (a.u.)"}; @@ -161,7 +190,7 @@ struct Kstar892LightIon { ConfigurableAxis binsImpactPar{"binsImpactPar", {100, 0, 25}, "Binning of the impact parameter axis"}; ConfigurableAxis axisNch{"axisNch", {100, 0.0f, 100.0f}, "Number of charged particles in |y| < 0.5"}; - enum MultEstimator { + enum CentEstimator { kFT0M, kFT0A, kFT0C, @@ -179,6 +208,8 @@ struct Kstar892LightIon { int noOfDaughters = 2; + double pionPIDpTlow = 1, pionPIDpThigh = 2.5, kaonPIDpTlow = 0.7, kaonPIDpThigh = 2.5; + TRandom* rn = new TRandom(); void init(InitContext const&) @@ -202,7 +233,7 @@ struct Kstar892LightIon { std::vector eveCutLabels = { "All Events", Form("|Vz| < %.1f", selectionConfig.cfgVrtxZCut.value), - "sel8", + std::string("sel8") + check(selectionConfig.isApplysel8.value), std::string("kNoTimeFrameBorder") + check(selectionConfig.isNoTimeFrameBorder.value), std::string("kNoITSROFrameBorder") + check(selectionConfig.isNoITSROFrameBorder.value), std::string("kIsTriggerTVX") + check(selectionConfig.isTriggerTVX.value), @@ -213,7 +244,10 @@ struct Kstar892LightIon { std::string("rctChecker") + check(rctCut.requireRCTFlagChecker.value), std::string("kIsGoodZvtxFT0vsPV") + check(selectionConfig.isGoodZvtxFT0vsPV.value), std::string("isVertexITSTPC") + check(selectionConfig.isVertexITSTPC.value), - std::string("isVertexTOFMatched") + check(selectionConfig.isVertexTOFMatched.value)}; + std::string("isVertexTOFMatched") + check(selectionConfig.isVertexTOFMatched.value), + std::string("INEL > 0") + check(selectionConfig.isApplyINELgt0.value), + std::string("hasFT0") + check(selectionConfig.isApplyhasFT0.value)}; + // assign labels for (size_t i = 0; i < eveCutLabels.size(); ++i) { hEventSelection.get(HIST("hEventCut"))->GetXaxis()->SetBinLabel(i + 1, eveCutLabels[i].c_str()); @@ -305,23 +339,6 @@ struct Kstar892LightIon { hMC.add("ImpactCorr/hKstarGenAfterEvtSel", "K*0 after event selections", kTH2F, {ptAxis, impactParAxis}); } - if (doprocessCorrFactors) { - hMC.add("CorrFactors/hCentralityVsMultMC", "Event centrality vs MC centrality", kTH2F, {{101, 0.0f, 101.0f}, axisNch}); - hMC.add("CorrFactors/hEventCentrality", "Event centrality", kTH1F, {{101, 0, 101}}); - hMC.add("CorrFactors/hNrecInGen", "Number of collisions in MC", kTH1F, {{4, -0.5, 3.5}}); - hMC.add("CorrFactors/hGenEvents", "Generated events", kTH2F, {{axisNch}, {4, 0, 4}}); - auto hGenEvents = hMC.get(HIST("CorrFactors/hGenEvents")); - hGenEvents->GetYaxis()->SetBinLabel(1, "All generated events"); - hGenEvents->GetYaxis()->SetBinLabel(2, "Generated events with Mc collision V_{z} cut"); - hGenEvents->GetYaxis()->SetBinLabel(3, "Generated events with at least one reconstructed event"); - hMC.add("CorrFactors/h2dGenKstar", "Centrality vs p_{T}", kTH2D, {{101, 0.0f, 101.0f}, ptAxis}); - hMC.add("CorrFactors/h3dGenKstarVsMultMCVsCentrality", "MC centrality vs centrality vs p_{T}", kTH3D, {axisNch, {101, 0.0f, 101.0f}, ptAxis}); - } - - if (doprocessRecMisID) { - hMC.add("RecMisID/hMassMisID", "Reconstruction misidentification", kTH3F, {ptAxis, centralityAxis, invmassAxis}); - } - if (doprocessLossMCMultiplicity) { hMC.add("LossMult/hMultMC", "Charged Paticle multiplicity in generated MC before event selection", kTH1F, {axisNch}); hMC.add("LossMult/hCentVsMultMC", "Centrality vs Charged Particle Multiplicity", kTH2F, {centralityAxis, axisNch}); @@ -331,6 +348,71 @@ struct Kstar892LightIon { hMC.add("LossMult/hGenKstar_vs_pt_vs_multMC", "pT vs Charged particle multiplicity", kTH2F, {ptAxis, axisNch}); hMC.add("LossMult/hGenKstarRecoEvt_vs_pt_vs_multMC", "pT vs Charged particle multiplicity with reconstruction", kTH2F, {ptAxis, axisNch}); } + + if (doprocessAllLossMC) { + hMC.add("AllLoss/hImpactParameterGen", "Impact parameter of generated MC events", kTH1F, {impactParAxis}); + hMC.add("AllLoss/hMultEta05Gen", "Charged Paticle multiplicity in generated MC before event selection in #eta 0.5", kTH1F, {axisNch}); + hMC.add("AllLoss/hMultEta08Gen", "Charged Paticle multiplicity in generated MC before event selection in #eta 0.8", kTH1F, {axisNch}); + hMC.add("AllLoss/hImpactParvsCentr", "Impact parameter of all MC events vs centrality", kTH2F, {{centralityAxis}, impactParAxis}); + hMC.add("AllLoss/hMultEta05vsCentr", "Centrality vs Charged Particle Multiplicity in #eta 0.5 for all MC", kTH2F, {centralityAxis, axisNch}); + hMC.add("AllLoss/hMultEta08vsCentr", "Centrality vs Charged Particle Multiplicity in #eta 0.8 for all MC", kTH2F, {centralityAxis, axisNch}); + hMC.add("AllLoss/hImpactParameterRec", "Impact parameter of reconstructed MC events", kTH1F, {impactParAxis}); + hMC.add("AllLoss/hImpactParvsCentrRec", "Impact parameter of selected MC events vs centrality", kTH2F, {{centralityAxis}, impactParAxis}); + hMC.add("AllLoss/hMultEta05Rec", "Charged Paticle multiplicity in reconstructed MC before event selection in #eta 0.5", kTH1F, {axisNch}); + hMC.add("AllLoss/hMultEta05vsCentrRec", "Centrality vs Charged Particle Multiplicity in #eta 0.5 after event selection", kTH2F, {centralityAxis, axisNch}); + hMC.add("AllLoss/hMultEta08Rec", "Charged Paticle multiplicity in reconstructed MC before event selection in #eta 0.8", kTH1F, {axisNch}); + hMC.add("AllLoss/hMultEta08vsCentrRec", "Centrality vs Charged Particle Multiplicity in #eta 0.8 after event selection", kTH2F, {centralityAxis, axisNch}); + hMC.add("AllLoss/hKstarpTGenVsImpactParBeforeEvtSel", "K*0 before event selections", kTH2F, {ptAxis, impactParAxis}); + hMC.add("AllLoss/hKstarpTGenVsMultEta05BeforeEvtSel", "pT vs Charged particle multiplicity in #eta 0.5 before event selection", kTH2F, {ptAxis, axisNch}); + hMC.add("AllLoss/hKstarpTGenVsMultEta08BeforeEvtSel", "pT vs Charged particle multiplicity in #eta 0.8 before event selection", kTH2F, {ptAxis, axisNch}); + hMC.add("AllLoss/hKstarpTGenVsImpactParAfterEvtSel", "K*0 after event selections", kTH2F, {ptAxis, impactParAxis}); + hMC.add("AllLoss/hKstarpTGenVsMultEta05AfterEvtSel", "pT vs Charged particle multiplicity in #eta 0.5 after event selection", kTH2F, {ptAxis, axisNch}); + hMC.add("AllLoss/hKstarpTGenVsMultEta08AfterEvtSel", "pT vs Charged particle multiplicity in #eta 0.8 after event selection", kTH2F, {ptAxis, axisNch}); + } + + if (doprocessRecMisID) { + hMC.add("RecMisID/hMassMisID", "Reconstruction misidentification", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + } + + if (doprocessRecReflection) { + hMC.add("Reflections/hRhoToKpi", "Refelction template of Rho", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hOmegaToKpi", "Refelction template of Omega", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hPhiToKpi", "Refelction template of Phi", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + hMC.add("Reflections/hKstarSelf", "Refelction template of Kstar", kTH3F, {ptAxis, centralityAxis, invmassAxis}); + } + + if (doprocessMCCheck) { + hMC.add("MCCheck/CentVsFoundFT0", "Found(=1.5) NOT Found(=0.5);;Status;", kTH2F, {{{centralityAxis}, {2, 0, 2}}}); + hMC.add("MCCheck/zPosMC", "Generated Events With at least One Rec. Collision + Sel. criteria;;Entries;", kTH1F, {vertexZAxis}); + hMC.add("MCCheck/zPos", "With Event Selection;;Entries;", kTH1F, {vertexZAxis}); + hMC.add("MCCheck/Cent", ";;Entries", kTH1F, {centralityAxis}); + hMC.add("MCCheck/NchVsCent", "Measured Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Nch", kTH2F, {{centralityAxis, {nBinsNch, minNch, maxNch}}}); + + // MC events passing the TVX requirement + hMC.add("MCCheck/NchMCcentVsTVX", ";Passed(=1.5) NOT Passed(=0.5);", kTH2F, {{{nBinsNch, minNch, maxNch}, {2, 0, 2}}}); + + hMC.add("MCCheck/NumberOfRecoCollisions", "Number of times Gen. Coll.are reconstructed;N;Entries", kTH1F, {{10, -0.5, 9.5}}); + + // Needed for the Gen. Nch to Centrality conversion + hMC.add("MCCheck/NchMCVsCent", "Generated Nch v.s. Centrality (At least Once Rec. Coll. + Sel. criteria);;Gen. Nch MC (|#eta|<0.8)", kTH2F, {{centralityAxis, {nBinsNch, minNch, maxNch}}}); + + // Needed to measure Event Loss + hMC.add("MCCheck/NchMC_WithRecoEvt", "Generated Nch of Evts With at least one Rec. Coll. + Sel. criteria;Gen. Nch MC (|#eta|<0.8);Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); + hMC.add("MCCheck/NchMC_AllGen", "Generated Nch of All Gen. Evts.;Gen. Nch;Entries", kTH1F, {{nBinsNch, minNch, maxNch}}); + + // Needed to measure Event Splitting + hMC.add("MCCheck/Centrality_WRecoEvt", "Generated Events With at least One Rec. Collision And NO Sel. criteria;;Entries", kTH1F, {centralityAxis}); + hMC.add("MCCheck/Centrality_WRecoEvtWSelCri", "Generated Events With at least One Rec. Collision + Sel. criteria;;Entries", kTH1F, {centralityAxis}); + hMC.add("MCCheck/Centrality_AllRecoEvt", "Generated Events Irrespective of the number of times it was reconstructed + Evt. Selections;;Entries", kTH1F, {centralityAxis}); + + hMC.add("MCCheck/PtKstarVsCentMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;;", kTH2F, {ptAxis, centralityAxis}); + + // Needed to calculate the numerator of the Signal Loss correction + hMC.add("MCCheck/PtKstarVsNchMC_WithRecoEvt", "Generated Events With at least One Rec. Collision;;Gen. Nch (|#eta|<0.8);", kTH2F, {{ptAxis, {nBinsNch, minNch, maxNch}}}); + + // Needed to calculate the denominator of the Signal Loss correction + hMC.add("MCCheck/PtKstarVsNchMC_AllGen", "All Generated Events;;Gen. Nch (|#eta|<0.8);", kTH2F, {{ptAxis, {nBinsNch, minNch, maxNch}}}); + } } double massPi = o2::constants::physics::MassPiPlus; @@ -347,7 +429,7 @@ struct Kstar892LightIon { if (fillHist) hEventSelection.fill(HIST("hEventCut"), 1); - if (!collision.sel8()) + if (selectionConfig.isApplysel8 && !collision.sel8()) return false; if (fillHist) hEventSelection.fill(HIST("hEventCut"), 2); @@ -409,6 +491,18 @@ struct Kstar892LightIon { if (fillHist) hEventSelection.fill(HIST("hEventCut"), 13); + if (selectionConfig.isApplyINELgt0 && !collision.isInelGt0()) { + return false; + } + if (fillHist) + hEventSelection.fill(HIST("hEventCut"), 14); + + if (selectionConfig.isApplyhasFT0 && !collision.has_foundFT0()) { + return false; + } + if (fillHist) + hEventSelection.fill(HIST("hEventCut"), 15); + return true; } @@ -552,7 +646,7 @@ struct Kstar892LightIon { } template - bool selectionPIDNew(const T& candidate, int PID) + bool selectionPIDpTdep(const T& candidate, int PID) { if (PID == PIDParticle::kPion) { if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { @@ -578,6 +672,101 @@ struct Kstar892LightIon { return false; } + template + bool selectionPIDpTdepTOF(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + if (candidate.pt() < pionPIDpTlow || candidate.pt() > pionPIDpThigh) { + if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && !candidate.hasTOF()) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedPi * selectionConfig.nsigmaCutCombinedPi)) { + return true; + } + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() < kaonPIDpTlow || candidate.pt() > kaonPIDpThigh) { + if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && !candidate.hasTOF()) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa)) { + return true; + } + } + } + return false; + } + + template + bool selectionMID(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + if (selectionConfig.onlyTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } else if (selectionConfig.onlyTPC) { + if (std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedMID * selectionConfig.nsigmaCutCombinedMID)) { + return true; + } + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } + } else if (PID == PIDParticle::kKaon) { + if (selectionConfig.onlyTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } else if (selectionConfig.onlyTPC) { + if (std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedMID * selectionConfig.nsigmaCutCombinedMID)) { + return true; + } + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } + } + return false; + } + + template + bool selectionMIDpTdep(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + if (candidate.pt() >= pionPIDpTlow && candidate.pt() < pionPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() >= kaonPIDpTlow && candidate.pt() < kaonPIDpThigh && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } + return false; + } + //*********Varibles declaration*************** float centrality{-1.0}, theta2; ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, mother, motherRot; @@ -633,7 +822,7 @@ struct Kstar892LightIon { using EventCandidates = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs using TrackCandidates = soa::Join; - using EventMCGenerated = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs + using EventMCGenerated = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Join; @@ -714,14 +903,25 @@ struct Kstar892LightIon { } // 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 (!selectionConfig.isApplypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + continue; + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !selectionPID(track2, 0)) // Track 2 is checked with Pion continue; - if (!selectionConfig.isApplypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion + + if (selectionConfig.isApplypTdepPID && !selectionPIDpTdep(track1, 1)) // Track 1 is checked with Kaon + continue; + if (selectionConfig.isApplypTdepPID && !selectionPIDpTdep(track2, 0)) // Track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPIDwTOF && !selectionPIDpTdepTOF(track1, 1)) // Track 1 is checked with Kaon + continue; + if (selectionConfig.isApplypTdepPIDwTOF && !selectionPIDpTdepTOF(track2, 0)) // Track 2 is checked with Pion continue; - if (selectionConfig.isApplypTdepPID && !selectionPIDNew(track1, 1)) // Track 1 is checked with Kaon + if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) continue; - if (selectionConfig.isApplypTdepPID && !selectionPIDNew(track2, 0)) // Track 2 is checked with Pion + + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) continue; if (cQAplots) { @@ -847,10 +1047,19 @@ struct Kstar892LightIon { } // 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 (!selectionConfig.isApplypTdepPID && (!selectionPID(track1, 1) || !selectionPID(track2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && (!selectionPID(track1, 1) || !selectionPID(track2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion continue; - if (selectionConfig.isApplypTdepPID && (!selectionPIDNew(track1, 1) || !selectionPIDNew(track2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + if (selectionConfig.isApplypTdepPID && (!selectionPIDpTdep(track1, 1) || !selectionPIDpTdep(track2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPIDwTOF && (!selectionPIDpTdepTOF(track1, 1) || !selectionPIDpTdepTOF(track2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) + continue; + + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) continue; if (cQAplots) { @@ -940,10 +1149,19 @@ struct Kstar892LightIon { continue; } - if (!selectionConfig.isApplypTdepPID && (!selectionPID(t1, 1) || !selectionPID(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && (!selectionPID(t1, 1) || !selectionPID(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPID && (!selectionPIDpTdep(t1, 1) || !selectionPIDpTdep(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPIDwTOF && (!selectionPIDpTdepTOF(t1, 1) || !selectionPIDpTdepTOF(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplyMID && (selectionMID(t1, 0) || selectionMID(t2, 1))) continue; - if (selectionConfig.isApplypTdepPID && (!selectionPIDNew(t1, 1) || !selectionPIDNew(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(t1, 0) || selectionMIDpTdep(t2, 1))) continue; daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); @@ -1008,10 +1226,19 @@ struct Kstar892LightIon { continue; } - if (!selectionConfig.isApplypTdepPID && (!selectionPID(t1, 1) || !selectionPID(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && (!selectionPID(t1, 1) || !selectionPID(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion continue; - if (selectionConfig.isApplypTdepPID && (!selectionPIDNew(t1, 1) || !selectionPIDNew(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + if (selectionConfig.isApplypTdepPID && (!selectionPIDpTdep(t1, 1) || !selectionPIDpTdep(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplypTdepPIDwTOF && (!selectionPIDpTdepTOF(t1, 1) || !selectionPIDpTdepTOF(t2, 0))) // Track 1 is checked with Kaon, track 2 is checked with Pion + continue; + + if (selectionConfig.isApplyMID && (selectionMID(t1, 0) || selectionMID(t2, 1))) + continue; + + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(t1, 0) || selectionMIDpTdep(t2, 1))) continue; if (!t1.has_mcParticle() || !t2.has_mcParticle()) { @@ -1050,6 +1277,19 @@ struct Kstar892LightIon { void processGen(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { + + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } + std::vector selectedEvents(collisions.size()); int nevts = 0; centrality = -1.0; @@ -1272,12 +1512,20 @@ struct Kstar892LightIon { } if (track1PDG == PDG_t::kPiPlus) { - if (!selectionConfig.isApplypTdepPID && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + continue; + } else if (selectionConfig.isApplypTdepPID && !(selectionPIDpTdep(track1, 0) && selectionPIDpTdep(track2, 1))) { // pion and kaon continue; - } else if (selectionConfig.isApplypTdepPID && !(selectionPIDNew(track1, 0) && selectionPIDNew(track2, 1))) { // pion and kaon + } else if (selectionConfig.isApplypTdepPIDwTOF && !(selectionPIDpTdepTOF(track1, 0) && selectionPIDpTdepTOF(track2, 1))) { continue; } + if (selectionConfig.isApplyMID && (selectionMID(track1, 1) || selectionMID(track2, 0))) + continue; + + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 1) || selectionMIDpTdep(track2, 0))) + continue; + if (cQAplots) { if (track1.sign() < 0 && track2.sign() > 0) { hPID.fill(HIST("After/hTPCnsigPi_Neg_mult_pt"), track1.tpcNSigmaPi(), centrality, track1.pt()); @@ -1293,12 +1541,20 @@ struct Kstar892LightIon { } } else if (track1PDG == PDG_t::kKPlus) { - if (!selectionConfig.isApplypTdepPID && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion + if ((!selectionConfig.isApplypTdepPID && !selectionConfig.isApplypTdepPIDwTOF) && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion continue; - } else if (selectionConfig.isApplypTdepPID && !(selectionPIDNew(track1, 1) && selectionPIDNew(track2, 0))) { // kaon and pion + } else if (selectionConfig.isApplypTdepPID && !(selectionPIDpTdep(track1, 1) && selectionPIDpTdep(track2, 0))) { // kaon and pion + continue; + } else if (selectionConfig.isApplypTdepPIDwTOF && !(selectionPIDpTdepTOF(track1, 1) && selectionPIDpTdepTOF(track2, 0))) { continue; } + if (selectionConfig.isApplyMID && (selectionMID(track1, 0) || selectionMID(track2, 1))) + continue; + + if (selectionConfig.isApplypTdepMID && (selectionMIDpTdep(track1, 0) || selectionMIDpTdep(track2, 1))) + continue; + if (cQAplots) { if (track1.sign() < 0 && track2.sign() > 0) { hPID.fill(HIST("After/hTPCnsigKa_Neg_mult_pt"), track1.tpcNSigmaKa(), centrality, track1.pt()); @@ -1352,13 +1608,26 @@ struct Kstar892LightIon { } PROCESS_SWITCH(Kstar892LightIon, processRec, "Process Reconstructed", false); - void processEvtLossSigLossMC(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + void processEvtLossSigLossMC(EventMCGenerated::iterator const& mcCollision, const soa::SmallGroups& recCollisions, aod::McParticles const& mcParticles) { + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } + auto impactPar = mcCollision.impactParameter(); hMC.fill(HIST("ImpactCorr/hImpactParameterGen"), impactPar); bool isSelectedEvent = false; - auto centrality = -999.; + centrality = -1.f; + for (const auto& RecCollision : recCollisions) { if (!RecCollision.has_mcCollision()) continue; @@ -1400,22 +1669,30 @@ struct Kstar892LightIon { } PROCESS_SWITCH(Kstar892LightIon, processEvtLossSigLossMC, "Process Signal Loss, Event Loss using impact parameter", false); - using McCollisionMults = soa::Join; - using LabeledTracks = soa::Join; - - void processCorrFactors(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, LabeledTracks const& /*particles*/, aod::McParticles const& mcParticles) + void processLossMCMultiplicity(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, soa::SmallGroups const& recCollisions) { - hMC.fill(HIST("CorrFactors/hGenEvents"), mcCollision.multMCNParticlesEta08(), 0.5); - if (std::abs(mcCollision.posZ()) > selectionConfig.cfgVrtxZCut) + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } + + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { return; + } - hMC.fill(HIST("CorrFactors/hGenEvents"), mcCollision.multMCNParticlesEta08(), 1.5); + const int multMC = mcCollision.multMCNParticlesEta05(); + hMC.fill(HIST("LossMult/hMultMC"), multMC); - float centrality = 100.5f; - for (auto const& collision : collisions) { + bool isSelectedEvent = false; + centrality = -1.f; - if (!selectionEvent(collision, false)) // don't fill event cut histogram + for (auto const& collision : recCollisions) { + + if (!selectionEvent(collision, false)) continue; if (selectCentEstimator == kFT0M) { @@ -1429,71 +1706,58 @@ struct Kstar892LightIon { } else { centrality = collision.centFT0M(); // default } - } - hMC.fill(HIST("CorrFactors/hCentralityVsMultMC"), centrality, mcCollision.multMCNParticlesEta08()); - hMC.fill(HIST("CorrFactors/hNrecInGen"), collisions.size()); - - for (const auto& mcParticle : mcParticles) { - if (mcParticle.y() < selectionConfig.motherRapidityMin || mcParticle.y() > selectionConfig.motherRapidityMax) { - continue; - } - - if (std::abs(mcParticle.pdgCode()) == o2::constants::physics::kK0Star892) { - - auto kDaughters = mcParticle.daughters_as(); - if (kDaughters.size() != noOfDaughters) { - continue; - } + isSelectedEvent = true; + } - bool hasPos = false; - bool hasNeg = false; + hMC.fill(HIST("LossMult/hCentVsMultMC"), centrality, multMC); - auto passkaon = false; - auto passpion = false; - for (const auto& kCurrentDaughter : kDaughters) { - // if (!kCurrentDaughter.isPhysicalPrimary()) - // continue; + // Event loss histograms + hMC.fill(HIST("LossMult/hGenEvt_vs_multMC"), multMC); - int pdgDau = kCurrentDaughter.pdgCode(); - int sign = (pdgDau > 0) - (pdgDau < 0); + if (isSelectedEvent) { + hMC.fill(HIST("LossMult/hCentVsMultMC_EvtSel"), centrality, multMC); + hMC.fill(HIST("LossMult/hGenEvtRecoEvt_vs_multMC"), multMC); + } - if (sign > 0) - hasPos = true; - if (sign < 0) - hasNeg = true; + // Signal loss histograms + for (auto const& mcPart : mcParticles) { - if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { - passkaon = true; - daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + if ((mcPart.y() < selectionConfig.motherRapidityMin || mcPart.y() > selectionConfig.motherRapidityMax) || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) + continue; - } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kPiPlus) { - passpion = true; - daughter2 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massPi); - } - } + const float pt = mcPart.pt(); - if ((passkaon && passpion) && (hasPos && hasNeg)) { - mother = daughter1 + daughter2; // Kstar meson + hMC.fill(HIST("LossMult/hGenKstar_vs_pt_vs_multMC"), pt, multMC); - hMC.fill(HIST("CorrFactors/h2dGenKstar"), centrality, mother.Pt()); - hMC.fill(HIST("CorrFactors/h3dGenKstarVsMultMCVsCentrality"), mcCollision.multMCNParticlesEta08(), centrality, mother.Pt()); - } + if (isSelectedEvent) { + hMC.fill(HIST("LossMult/hGenKstarRecoEvt_vs_pt_vs_multMC"), pt, multMC); } } + } + PROCESS_SWITCH(Kstar892LightIon, processLossMCMultiplicity, "Signal + Event loss (using MC multiplicity)", false); - if (collisions.size() == 0) + void processAllLossMC(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + { + if (selectionConfig.isApplyMCGenInelgt0 && !mcCollision.isInelGt0()) { return; + } - hMC.fill(HIST("CorrFactors/hGenEvents"), mcCollision.multMCNParticlesEta08(), 2.5); - } - PROCESS_SWITCH(Kstar892LightIon, processCorrFactors, "Process Signal Loss, Event Loss using chaged particle multiplicity", false); + if (selectionConfig.isApplyMCGenTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } - void processLossMCMultiplicity(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, soa::SmallGroups const& recCollisions) - { - const int multMC = mcCollision.multMCNParticlesEta05(); - hMC.fill(HIST("LossMult/hMultMC"), multMC); + if (selectionConfig.isApplyMCGenVz && std::abs(mcCollision.posZ()) >= selectionConfig.cfgVrtxZCut) { + return; + } + // Event loss estimation + auto impactPar = mcCollision.impactParameter(); + auto mult05 = mcCollision.multMCNParticlesEta05(); + auto mult08 = mcCollision.multMCNParticlesEta08(); + hMC.fill(HIST("AllLoss/hImpactParameterGen"), impactPar); + hMC.fill(HIST("AllLoss/hMultEta05Gen"), mult05); + hMC.fill(HIST("AllLoss/hMultEta08Gen"), mult08); bool isSelectedEvent = false; float centrality = -1.f; @@ -1517,32 +1781,40 @@ struct Kstar892LightIon { isSelectedEvent = true; } - hMC.fill(HIST("LossMult/hCentVsMultMC"), centrality, multMC); - - // Event loss histograms - hMC.fill(HIST("LossMult/hGenEvt_vs_multMC"), multMC); + hMC.fill(HIST("AllLoss/hImpactParvsCentr"), centrality, impactPar); + hMC.fill(HIST("AllLoss/hMultEta05vsCentr"), centrality, mult05); + hMC.fill(HIST("AllLoss/hMultEta08vsCentr"), centrality, mult08); if (isSelectedEvent) { - hMC.fill(HIST("LossMult/hCentVsMultMC_EvtSel"), centrality, multMC); - hMC.fill(HIST("LossMult/hGenEvtRecoEvt_vs_multMC"), multMC); + hMC.fill(HIST("AllLoss/hImpactParameterRec"), impactPar); + hMC.fill(HIST("AllLoss/hImpactParvsCentrRec"), centrality, impactPar); + hMC.fill(HIST("AllLoss/hMultEta05Rec"), mult05); + hMC.fill(HIST("AllLoss/hMultEta05vsCentrRec"), centrality, mult05); + hMC.fill(HIST("AllLoss/hMultEta08Rec"), mult08); + hMC.fill(HIST("AllLoss/hMultEta08vsCentrRec"), centrality, mult08); } - // Signal loss histograms - for (auto const& mcPart : mcParticles) { + // Generated MC + for (const auto& mcPart : mcParticles) { if ((mcPart.y() < selectionConfig.motherRapidityMin || mcPart.y() > selectionConfig.motherRapidityMax) || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) continue; const float pt = mcPart.pt(); - hMC.fill(HIST("LossMult/hGenKstar_vs_pt_vs_multMC"), pt, multMC); - + // signal loss estimation + hMC.fill(HIST("AllLoss/hKstarpTGenVsImpactParBeforeEvtSel"), pt, impactPar); + hMC.fill(HIST("AllLoss/hKstarpTGenVsMultEta05BeforeEvtSel"), pt, mult05); + hMC.fill(HIST("AllLoss/hKstarpTGenVsMultEta08BeforeEvtSel"), pt, mult08); if (isSelectedEvent) { - hMC.fill(HIST("LossMult/hGenKstarRecoEvt_vs_pt_vs_multMC"), pt, multMC); + // signal loss estimation + hMC.fill(HIST("AllLoss/hKstarpTGenVsImpactParAfterEvtSel"), pt, impactPar); + hMC.fill(HIST("AllLoss/hKstarpTGenVsMultEta05AfterEvtSel"), pt, mult05); + hMC.fill(HIST("AllLoss/hKstarpTGenVsMultEta08AfterEvtSel"), pt, mult08); } - } + } // end loop on gen particles } - PROCESS_SWITCH(Kstar892LightIon, processLossMCMultiplicity, "Signal + Event loss (using MC multiplicity)", false); + PROCESS_SWITCH(Kstar892LightIon, processAllLossMC, "Process All Signal Loss, Event Loss", false); void processRecMisID(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, EventMCGenerated const&) { @@ -1618,6 +1890,378 @@ struct Kstar892LightIon { } } PROCESS_SWITCH(Kstar892LightIon, processRecMisID, "Process Reconstructed MisID Background", false); + + void processRecReflection(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, EventMCGenerated const&) + { + if (!collision.has_mcCollision()) + return; + + if (!selectionEvent(collision, false)) + return; + + centrality = -1.f; + + if (selectCentEstimator == kFT0M) { + centrality = collision.centFT0M(); + } else if (selectCentEstimator == kFT0A) { + centrality = collision.centFT0A(); + } else if (selectCentEstimator == kFT0C) { + centrality = collision.centFT0C(); + } else if (selectCentEstimator == kFV0A) { + centrality = collision.centFV0A(); + } else { + centrality = collision.centFT0M(); + } + + for (const auto& [track1, track2] : + combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + + if (!selectionTrack(track1) || !selectionTrack(track2)) + continue; + + if (track1.index() >= track2.index()) + continue; + + if (track1.sign() * track2.sign() >= 0) + continue; + + if (!track1.has_mcParticle() || !track2.has_mcParticle()) + continue; + + const auto mc1 = track1.mcParticle(); + const auto mc2 = track2.mcParticle(); + + if (!mc1.isPhysicalPrimary() || !mc2.isPhysicalPrimary()) + continue; + + bool sameMother = false; + int motherPDG = 0; + + for (const auto& m1 : mc1.mothers_as()) { + for (const auto& m2 : mc2.mothers_as()) { + if (m1.globalIndex() == m2.globalIndex()) { + sameMother = true; + motherPDG = std::abs(m1.pdgCode()); + break; + } + } + if (sameMother) + break; + } + + if (!sameMother) + continue; + + int pdg1 = std::abs(mc1.pdgCode()); + int pdg2 = std::abs(mc2.pdgCode()); + + // ===================================================== + // Rho0 (770) -> pi pi -> K pi + // ===================================================== + if (motherPDG == PDG_t::kRho770_0 && pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kPiPlus) { + + // track 1 -> K + ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); + ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); + auto fake1 = p1K + p2Pi; + + if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hRhoToKpi"), fake1.Pt(), centrality, fake1.M()); + + // track 2 -> K + ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); + ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); + auto fake2 = p1Pi + p2K; + + if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hRhoToKpi"), fake2.Pt(), centrality, fake2.M()); + } + + // ===================================================== + // Omega (782) -> pi pi(pi0) -> K pi + // ===================================================== + if (motherPDG == o2::constants::physics::kOmega && pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kPiPlus) { + + // track 1 -> K + ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); + ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); + auto fake1 = p1K + p2Pi; + + if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hOmegaToKpi"), fake1.Pt(), centrality, fake1.M()); + + // track 2 -> K + ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); + ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); + auto fake2 = p1Pi + p2K; + + if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hOmegaToKpi"), fake2.Pt(), centrality, fake2.M()); + } + + // ===================================================== + // Phi (1020) -> KK -> K pi + // ===================================================== + if (motherPDG == o2::constants::physics::kPhi && pdg1 == PDG_t::kKPlus && pdg2 == PDG_t::kKPlus) { + + // track 1 -> pi + ROOT::Math::PxPyPzMVector p1Pi(track1.px(), track1.py(), track1.pz(), massPi); + ROOT::Math::PxPyPzMVector p2K(track2.px(), track2.py(), track2.pz(), massKa); + auto fake1 = p1Pi + p2K; + + if (fake1.Rapidity() > selectionConfig.motherRapidityMin && fake1.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hPhiToKpi"), fake1.Pt(), centrality, fake1.M()); + + // track 2 -> pi + ROOT::Math::PxPyPzMVector p1K(track1.px(), track1.py(), track1.pz(), massKa); + ROOT::Math::PxPyPzMVector p2Pi(track2.px(), track2.py(), track2.pz(), massPi); + auto fake2 = p1K + p2Pi; + + if (fake2.Rapidity() > selectionConfig.motherRapidityMin && fake2.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hPhiToKpi"), fake2.Pt(), centrality, fake2.M()); + } + + // ===================================================== + // K*0 Self-reflection + // ===================================================== + if (motherPDG == o2::constants::physics::kK0Star892 && ((pdg1 == PDG_t::kPiPlus && pdg2 == PDG_t::kKPlus) || (pdg1 == PDG_t::kKPlus && pdg2 == PDG_t::kPiPlus))) { + + ROOT::Math::PxPyPzMVector p1Swap(track1.px(), track1.py(), track1.pz(), pdg1 == PDG_t::kKPlus ? massPi : massKa); + + ROOT::Math::PxPyPzMVector p2Swap(track2.px(), track2.py(), track2.pz(), pdg2 == PDG_t::kKPlus ? massPi : massKa); + + auto fake = p1Swap + p2Swap; + + if (fake.Rapidity() > selectionConfig.motherRapidityMin && fake.Rapidity() < selectionConfig.motherRapidityMax) + hMC.fill(HIST("Reflections/hKstarSelf"), fake.Pt(), centrality, fake.M()); + } + } + } + PROCESS_SWITCH(Kstar892LightIon, processRecReflection, "Process reconstructed reflections", false); + + Service pdg; + + void processMCCheck(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles, TrackCandidatesMC const&) + { + + //--------------------------- + // Only INEL > 0 generated collisions + // By counting number of primary charged particles in |eta| < 1 + //--------------------------- + int nChMC{0}; + int nChMCEta08{0}; + int nChFT0A{0}; + int nChFT0C{0}; + static constexpr float MinCharge{3.f}; + static constexpr float MinFT0A{3.5f}; + static constexpr float MaxFT0A{4.9f}; + static constexpr float MinFT0C{-3.3f}; + static constexpr float MaxFT0C{-2.1f}; + static constexpr float One{1.0f}; + static constexpr int ZeroInt{0}; + + for (const auto& particle : mcParticles) { + + auto charge{0.}; + // Get the MC particle + const auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < MinCharge) + continue; + + // Is it a primary particle? + if (!particle.isPhysicalPrimary()) + continue; + + const float eta{particle.eta()}; + + // TVX requirement + if (eta > MinFT0A && eta < MaxFT0A) { + nChFT0A++; + } + + if (eta > MinFT0C && eta < MaxFT0C) { + nChFT0C++; + } + + if (std::abs(eta) < nchAcceptance) { + nChMCEta08++; + } + + // INEL > 0 + if (std::abs(eta) > One) + continue; + + nChMC++; + } + + //--------------------------- + // Only events with at least one charged particle in the FT0A and FT0C acceptances + //--------------------------- + if (selectionConfig.selTVXMC) { + if (!(nChFT0A > ZeroInt && nChFT0C > ZeroInt)) { + hMC.fill(HIST("MCCheck/NchMCcentVsTVX"), nChMC, 0.5); + return; + } + hMC.fill(HIST("MCCheck/NchMCcentVsTVX"), nChMC, 1.5); + } + + //--------------------------- + // Only MC events with |Vtx Z| < 10 cm + //--------------------------- + if (selectionConfig.isZvtxPosSelMC && (std::fabs(mccollision.posZ()) > selectionConfig.cfgVrtxZCut)) { + return; + } + + //--------------------------- + // Only INEL > 0 generated events + //--------------------------- + if (selectionConfig.selINELgt0MC) { + if (!(nChMC > ZeroInt)) { + return; + } + } + + const auto& nRecColls{collisions.size()}; + hMC.fill(HIST("MCCheck/NumberOfRecoCollisions"), nRecColls); + + //--------------------------- + // Only Generated evets with at least one reconstrued collision + //--------------------------- + if (nRecColls > ZeroInt) { + + // Finds the collisions with the largest number of contributors + // in case nRecColls is larger than One + int biggestNContribs{-1}; + int bestCollisionIndex{-1}; + centrality = -1.f; + for (const auto& collision : collisions) { + + if (selectCentEstimator == kFT0M) { + centrality = collision.centFT0M(); + } else if (selectCentEstimator == kFT0A) { + centrality = collision.centFT0A(); + } else if (selectCentEstimator == kFT0C) { + centrality = collision.centFT0C(); + } else if (selectCentEstimator == kFV0A) { + centrality = collision.centFV0A(); + } else { + centrality = collision.centFT0M(); // default + } + + if (selectionConfig.selHasFT0MC && !collision.has_foundFT0()) { + continue; + } + + if (biggestNContribs < collision.numContrib()) { + biggestNContribs = collision.numContrib(); + bestCollisionIndex = collision.globalIndex(); + } + + // Needed to calculate denominator of the Event Splitting correction + if (selectionEvent(collision, false)) { + hMC.fill(HIST("MCCheck/Centrality_AllRecoEvt"), centrality); + } + } + + //--------------------------- + // Loop over the reconstructed collisions + // Only that one with the largest number of contributors is considered + //--------------------------- + centrality = -1.f; + for (const auto& collision : collisions) { + + if (selectCentEstimator == kFT0M) { + centrality = collision.centFT0M(); + } else if (selectCentEstimator == kFT0A) { + centrality = collision.centFT0A(); + } else if (selectCentEstimator == kFT0C) { + centrality = collision.centFT0C(); + } else if (selectCentEstimator == kFV0A) { + centrality = collision.centFV0A(); + } else { + centrality = collision.centFT0M(); // default + } + + //--------------------------- + // Reject collisions if has_foundFT0() returns false + //--------------------------- + if (selectionConfig.selHasFT0MC && !collision.has_foundFT0()) { + hMC.fill(HIST("MCCheck/CentVsFoundFT0"), centrality, 0.5); + continue; + } + hMC.fill(HIST("MCCheck/CentVsFoundFT0"), centrality, 1.5); + + //--------------------------- + // Pick the collisions with the largest number of contributors + //--------------------------- + if (bestCollisionIndex != collision.globalIndex()) { + continue; + } + + //--------------------------- + // Needed to construct the correlation between MC Nch v.s. centrality + //--------------------------- + + hMC.fill(HIST("MCCheck/Centrality_WRecoEvt"), centrality); + hMC.fill(HIST("MCCheck/zPosMC"), mccollision.posZ()); + + //--------------------------- + // Event selection + // for reconstructed collisions + //--------------------------- + if (!selectionEvent(collision, false)) { + continue; + } + + hMC.fill(HIST("MCCheck/Centrality_WRecoEvtWSelCri"), centrality); + hMC.fill(HIST("MCCheck/NchMCVsCent"), centrality, nChMCEta08); + hMC.fill(HIST("MCCheck/NchMC_WithRecoEvt"), nChMCEta08); // Numerator of event loss correction + hMC.fill(HIST("MCCheck/zPos"), collision.posZ()); + hMC.fill(HIST("MCCheck/Cent"), centrality); + + //--------------------------- + // All Generated events with at least one associated reconstructed collision + // The Generated events are not subjected to any selection criteria + // However, the associated reconstructed collisions pass the selection criteria + // This histograms are used for the denominator of the tracking efficiency + //--------------------------- + for (const auto& mcPart : mcParticles) { + if ((mcPart.y() < selectionConfig.motherRapidityMin || mcPart.y() > selectionConfig.motherRapidityMax) || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) + continue; + + hMC.fill(HIST("MCCheck/PtKstarVsCentMC_WithRecoEvt"), mcPart.pt(), centrality); + hMC.fill(HIST("MCCheck/PtKstarVsNchMC_WithRecoEvt"), mcPart.pt(), nChMCEta08); // Numerator of signal loss + } // Loop over generated particles per generated collision + // hMC.fill(HIST("MCCheck/NchVsCent"), centrality, nCh); + } // Loop over Reco. Collisions: Only the collisions with the largest number of contributors + } // If condition: Only simulated evets with at least one reconstrued collision + + //--------------------------- + // All Generated events irrespective of whether there is an associated reconstructed collision + // Consequently, the centrality being a reconstructed quantity, might not always be available + // Therefore it is expressed as a function of the generated pT and the generated Nch in ∣eta∣ < 0.8 + // This is used for the denominator of the signal loss correction + //--------------------------- + for (const auto& mcPart : mcParticles) { + if ((mcPart.y() < selectionConfig.motherRapidityMin || mcPart.y() > selectionConfig.motherRapidityMax) || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) + continue; + + hMC.fill(HIST("MCCheck/PtKstarVsNchMC_AllGen"), mcPart.pt(), nChMCEta08); + } // Loop over Generated Particles + + //--------------------------- + // This is used for the denominator of the event loss correction + //--------------------------- + hMC.fill(HIST("MCCheck/NchMC_AllGen"), nChMCEta08); + } + PROCESS_SWITCH(Kstar892LightIon, processMCCheck, "Cross-check MC analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Resonances/kstarInOO.cxx b/PWGLF/Tasks/Resonances/kstarInOO.cxx index 628e2a6fddb..d295aa655eb 100644 --- a/PWGLF/Tasks/Resonances/kstarInOO.cxx +++ b/PWGLF/Tasks/Resonances/kstarInOO.cxx @@ -33,6 +33,15 @@ #include #include +// jet +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/TrackJetQa.h" + +#include + #include #include #include @@ -67,6 +76,7 @@ struct kstarInOO { //================================== // Event Selection + Configurable cfgEventSelections{"cfgEventSelections", "sel8", "Set event selection"}; Configurable cfgEventVtxCut{"cfgEventVtxCut", 10.0, "V_z cut selection"}; ConfigurableAxis cfgCentAxis{"cfgCentAxis", {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}, "Binning of the centrality axis"}; Configurable cfgOccupancySel{"cfgOccupancySel", false, "Occupancy selection"}; @@ -84,13 +94,13 @@ struct kstarInOO { Configurable cfgTrackConnectedToPV{"cfgTrackConnectedToPV", true, "PV contributor track selection"}; // PV Contriuibutor Configurable cfgTrackGlobalWoDCATrack{"cfgTrackGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) // TPC - Configurable cfgTracknFindableTPCClusters{"cfgTrackFindableTPCClusters", 50, "nFindable TPC Clusters"}; - Configurable cfgTracknTPCCrossedRows{"cfgTrackTPCCrossedRows", 70, "nCrossed TPC Rows"}; - Configurable cfgTracknRowsOverFindable{"cfgTrackRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; - Configurable cfgTracknTPCChi2{"cfgTrackTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; + Configurable cfgTrackFindableTPCClusters{"cfgTrackFindableTPCClusters", 50, "nFindable TPC Clusters"}; + Configurable cfgTrackTPCCrossedRows{"cfgTrackTPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfgTrackRowsOverFindable{"cfgTrackRowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; + Configurable cfgTrackTPCChi2{"cfgTrackTPCChi2", 4.0, "nTPC Chi2 per Cluster"}; // ITS - Configurable cfgTracknITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; + Configurable cfgTrackITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; // PID Configurable cfgTrackTPCPID{"cfgTrackTPCPID", true, "Enables TPC PID"}; @@ -112,6 +122,7 @@ struct kstarInOO { // MCGen Configurable cfgForceGenReco{"cfgForceGenReco", false, "Only consider events which are reconstructed (neglect event-loss)"}; + Configurable cfgReqMcEffPID{"cfgReqMcEffPID", false, "Request McEfficiency PID"}; // Pair Configurable cfgMinvNBins{"cfgMinvNBins", 300, "Number of bins for Minv axis"}; @@ -123,9 +134,36 @@ struct kstarInOO { ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; Configurable cfgEventCutQA{"cfgEventCutsQA", false, "Enable Event QA Hists"}; Configurable cfgTrackCutQA{"cfgTrackCutQA", false, "Enable Track QA Hists"}; - Configurable cfgDataHistos{"cfgDataHistos", false, "Enable Data Hists"}; - Configurable cfgMcHistos{"cfgMcHistos", false, "Enable MC Hists"}; + Configurable cfgJetQAHistos{"cfgJetQAHistos", false, "Enable Jet QA Histos"}; + + Configurable cfgMCHistos{"cfgMCHistos", false, "Enable MC Hists"}; + Configurable cfgMixedHistos{"cfgMixedHistos", false, "Enable Mixed Histos"}; + Configurable cfgJetHistos{"cfgJetHistos", false, "Enable Jet Histos"}; + Configurable cfgJetMCHistos{"cfgJetMCHistos", false, "Enable Jet MC Histos"}; + Configurable cfgCutonTrig{"cfgCutonTrig", false, "Enable Jet Cut on Trig"}; + Configurable cfgManualEvSel{"cfgManualEvSel", false, "Enable Manual EvSel"}; + Configurable cfgJetEvSel{"cfgJetEvSel", false, "Enable Manual JetEvSel"}; + + //====================== + //|| + //|| JET + //|| + //====================== + Configurable cfgJetpT{"cfgJetpT", 8.0, "Set Jet pT minimum"}; + Configurable cfgJetR{"cfgJetR", 0.4, "Set Jet radius parameter"}; + Configurable cfgSingleJet{"cfgSingleJet", false, "Enforces strict phi-jet correspondance"}; + Configurable cfgReqJets{"cfgReqJets", false, "False: MB, True: Inside Jets"}; + Configurable cfgRealTriggerMasks{"cfgRealTriggerMasks", "", "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 cfgTriggerMasksTest1{"cfgTriggerMasksTest1", "", "possible JE Trigger masks Test1"}; + Configurable cfgTriggerMasksTest2{"cfgTriggerMasksTest2", "", "possible JE Trigger masks Test2"}; + Configurable cfgTriggerMasksTest3{"cfgTriggerMasksTest3", "", "possible JE Trigger masks Test3"}; + + std::vector eventSelectionBits; + std::vector RealTriggerMaskBits; + std::vector triggerMaskBitsTest1; + std::vector triggerMaskBitsTest2; + std::vector triggerMaskBitsTest3; // Main void init(o2::framework::InitContext&) { @@ -137,15 +175,15 @@ struct kstarInOO { const AxisSpec minvAxis = {cfgMinvNBins, cfgMinvMin, cfgMinvMax}; const AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; const AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; + const AxisSpec dRAxis = {100, 0, 100}; if (cfgEventCutQA) { - histos.add("hEvent_Cut", "Number of event after cuts", kTH1D, {{12, 0, 12}}); - histos.add("hPosZ_BC", "hPosZ_Bc", kTH1F, {{300, -15.0, 15.0}}); + histos.add("hEvent_Cut", "Number of event after cuts", kTH1D, {{13, -0.5, 12.5}}); + histos.add("hPosZ_BC", "hPosZ_BC", kTH1F, {{300, -15.0, 15.0}}); histos.add("hPosZ_AC", "hPosZ_AC", kTH1F, {{300, -15.0, 15.0}}); histos.add("hcentFT0C_BC", "centFT0C_BC", kTH1F, {{110, 0.0, 110.0}}); histos.add("hcentFT0C_AC", "centFT0C_AC", kTH1F, {{110, 0.0, 110.0}}); } - if (cfgTrackCutQA) { histos.add("hDCArToPv_BC", "DCArToPv_BC", kTH1F, {axisDCAxy}); histos.add("hDCAzToPv_BC", "DCAzToPv_BC", kTH1F, {axisDCAz}); @@ -156,6 +194,7 @@ struct kstarInOO { histos.add("hFindableTPCRows_BC", "hFindableTPCRows_BC", kTH1F, {{200, 0, 200}}); histos.add("hClustersVsRows_BC", "hClustersVsRows_BC", kTH1F, {{200, 0, 2}}); histos.add("hTPCChi2_BC", "hTPCChi2_BC", kTH1F, {{200, 0, 100}}); + histos.add("hITSChi2_BC", "hITSChi2_BC", kTH1F, {{200, 0, 100}}); histos.add("QA_nSigma_pion_TPC_BC", "QA_nSigma_pion_TPC_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); histos.add("QA_nSigma_pion_TOF_BC", "QA_nSigma_pion_TOF_BC", {HistType::kTH2F, {ptAxis, pidAxis}}); histos.add("QA_pion_TPC_TOF_BC", "QA_pion_TPC_TOF_BC", {HistType::kTH2F, {pidAxis, pidAxis}}); @@ -173,6 +212,7 @@ struct kstarInOO { histos.add("hFindableTPCRows_AC", "hFindableTPCRows_AC", kTH1F, {{200, 0, 200}}); histos.add("hClustersVsRows_AC", "hClustersVsRows_AC", kTH1F, {{200, 0, 2}}); histos.add("hTPCChi2_AC", "hTPCChi2_AC", kTH1F, {{200, 0, 100}}); + histos.add("hITSChi2_AC", "hITSChi2_AC", kTH1F, {{200, 0, 100}}); histos.add("QA_nSigma_pion_TPC_AC", "QA_nSigma_pion_TPC_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); histos.add("QA_nSigma_pion_TOF_AC", "QA_nSigma_pion_TOF_AC", {HistType::kTH2F, {ptAxis, pidAxis}}); histos.add("QA_pion_TPC_TOF_AC", "QA_pion_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); @@ -181,33 +221,70 @@ struct kstarInOO { histos.add("QA_kaon_TPC_TOF_AC", "QA_kaon_TPC_TOF_AC", {HistType::kTH2F, {pidAxis, pidAxis}}); histos.add("QA_track_pT_AC", "QA_track_pT_AC", kTH1F, {{13, 0.0, 13.0}}); } + if (cfgJetQAHistos) { + histos.add("nTriggerQA", "nTriggerQA", kTH1F, {{8, 0.0, 8.0}}); + histos.add("nTriggerQA_GoodEv", "nTriggerQA_GoodEv", kTH1F, {{8, 0.0, 8.0}}); + histos.add("nTriggerQA_GoodTrig", "nTriggerQA_GoodTrig", kTH1F, {{8, 0.0, 8.0}}); + histos.add("nTriggerQA_GoodEvTrig", "nTriggerQA_GoodEvTrig", kTH1F, {{8, 0.0, 8.0}}); + + histos.add("JetpT", "Jet pT (GeV/c)", kTH1F, {{4000, 0., 200.}}); + histos.add("JetEta", "Jet Eta", kTH1F, {{100, -1.0, 1.0}}); + histos.add("JetPhi", "Jet Phi", kTH1F, {{80, -1.0, 7.0}}); + + histos.add("rawDimpT", "rawDimpT", kTH2F, {{1000, 0.0, 10.0}, {100, -0.5, 0.5}}); + histos.add("jetTrackEta", "Jet Track Eta", kTH1F, {{100, -1.0, 1.0}}); + histos.add("jetTrackPhi", "Jet Track Phi", kTH1F, {{80, -1.0, 7.0}}); + + histos.add("nJetsPerEvent", "nJetsPerEvent", kTH1I, {{4, -0.5, 3.5}}); + histos.add("nGoodJets", "nGoodJets", kTH1I, {{4, -0.5, 3.5}}); + } + + //////////////////////////////////// + histos.add("nEvents", "nEvents", kTH1F, {{7, 0.0, 7.0}}); + histos.add("hUSS_KPi", "hUSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hUSS_PiK", "hUSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hLSS_KPi", "hLSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hLSS_PiK", "hLSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - if (cfgDataHistos) { - histos.add("nEvents", "nEvents", kTH1F, {{4, 0.0, 4.0}}); - histos.add("hUSS_KPi", "hUSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hUSS_PiK", "hUSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hLSS_KPi", "hLSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hLSS_PiK", "hLSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + if (cfgMixedHistos) { histos.add("hUSS_KPi_Mix", "hUSS_KPi_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); histos.add("hUSS_PiK_Mix", "hUSS_PiK_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); } - - if (cfgMcHistos) { - histos.add("nEvents_MC", "nEvents_MC", kTH1F, {{4, 0.0, 4.0}}); - histos.add("nEvents_MC_True", "nEvents_MC_True", kTH1F, {{4, 0.0, 4.0}}); - histos.add("hMC_kstar_True", "hMC_kstar_True", kTHnSparseF, {cfgCentAxis, ptAxis}); - - histos.add("hMC_USS_True", "hMC_USS_True", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hMC_USS_KPi", "hMC_USS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hMC_USS_PiK", "hMC_USS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hMC_LSS_KPi", "hMC_LSS_KPi", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hMC_LSS_PiK", "hMC_LSS_PiK", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - - histos.add("hMC_USS_KPi_Mix", "hMC_USS_KPi_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hMC_USS_PiK_Mix", "hMC_USS_PiK_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - - histos.add("hMC_USS_KPi_True", "hMC_USS_KPi_True", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); - histos.add("hMC_USS_PiK_True", "hMC_USS_PiK_True", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + if (cfgMCHistos) { + histos.add("nEvents_Gen", "nEvents_Gen", kTH1F, {{4, 0.0, 4.0}}); + histos.add("hUSS_TrueRec", "hUSS_TrueRec", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hGen_pT_Raw", "Gen_pT_Raw (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hGen_pT_GoodEv", "hGen_pT_GoodEv", kTHnSparseF, {cfgCentAxis, ptAxis}); + } + if (cfgJetHistos) { + histos.add("hUSS_KPi_INSIDE", "hUSS_KPi_INSIDE", kTHnSparseF, {cfgCentAxis, dRAxis, ptAxis, minvAxis}); + histos.add("hUSS_PiK_INSIDE", "hUSS_PiK_INSIDE", kTHnSparseF, {cfgCentAxis, dRAxis, ptAxis, minvAxis}); + histos.add("hLSS_KPi_INSIDE", "hLSS_KPi_INSIDE", kTHnSparseF, {cfgCentAxis, dRAxis, ptAxis, minvAxis}); + histos.add("hLSS_PiK_INSIDE", "hLSS_PiK_INSIDE", kTHnSparseF, {cfgCentAxis, dRAxis, ptAxis, minvAxis}); + } + if (cfgJetMCHistos) { + histos.add("nEvents_Gen", "nEvents_Gen", kTH1F, {{7, -.0, 7.0}}); + histos.add("hUSS_TrueRec", "hUSS_TrueRec", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hUSS_TrueRec_INSIDE", "hUSS_TrueRec_INSIDE", kTHnSparseF, {cfgCentAxis, dRAxis, ptAxis, minvAxis}); + + histos.add("hGen_pT_Raw", "Gen_pT_Raw (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hGen_pT_GoodEv", "Gen_pT_GoodTrig (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hGen_pT_GoodTrig", "Gen_pT_GoodTrig (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hGen_pT_GoodEvTrig", "Gen_pT_GoodEvTrig (GeV/c)", kTH1F, {{800, 0., 40.}}); + + histos.add("hEffRec_pT", "EffRec_pT (GeV/c)", kTH1F, {{1600, 0., 80.}}); + histos.add("hEffRecTest1_pT", "EffRecTest1_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest2_pT", "EffRecTest2_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest3_pT", "EffRecTest3_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest4_pT", "EffRecTest4_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest5_pT", "EffRecTest5_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest6_pT", "EffRecTest6_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest7_pT", "EffRecTest7_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffRecTest8_pT", "EffRecTest8_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + histos.add("hEffGen_pT", "EffGen_pT (GeV/c)", kTH1F, {{800, 0., 40.}}); + + histos.add("hMotherPdg1", "hMotherPdg1", kTH1F, {{5000, 0., 5000.}}); + histos.add("hMotherPdg2", "hMotherPdg2", kTH1F, {{5000, 0., 5000.}}); } std::shared_ptr hCutFlow = histos.get(HIST("hEvent_Cut")); @@ -227,14 +304,36 @@ struct kstarInOO { hCutFlow->GetXaxis()->SetBinLabel(i + 1, eventCutLabels[i].c_str()); } + // Jet + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(cfgEventSelections)); + RealTriggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(cfgRealTriggerMasks); + triggerMaskBitsTest1 = jetderiveddatautilities::initialiseTriggerMaskBits(cfgTriggerMasksTest1); + triggerMaskBitsTest2 = jetderiveddatautilities::initialiseTriggerMaskBits(cfgTriggerMasksTest2); + triggerMaskBitsTest3 = jetderiveddatautilities::initialiseTriggerMaskBits(cfgTriggerMasksTest3); } // end of init + //====================== + //|| For LF Analysis + //====================== using EventCandidates = soa::Join; //, aod::CentFT0Ms, aod::CentFT0As using EventCandidatesTrue = aod::McCollisions; using TrackCandidates = soa::Join; using TrackCandidatesMC = soa::Join; + + //============== + //|| For jets + //============== + Filter JEPosZFilter = nabs(aod::jcollision::posZ) < cfgEventVtxCut; + Filter JEMCPosZFilter = nabs(aod::jmccollision::posZ) < cfgEventVtxCut; + Filter jetCuts = aod::jet::pt > cfgJetpT&& aod::jet::r == nround(cfgJetR.node() * 100.0f); + + using JetTrackCandidates = soa::Join; + using JetTrackCandidatesMC = soa::Join; + + using JetFilteredJets = soa::Filtered>; + // For Mixed Event using BinningType = ColumnBinningPolicy; @@ -251,82 +350,244 @@ struct kstarInOO { //|| Helper Templates //|| //================================== + template + void fillQA(const bool pass, const objType& obj, const int objecttype = 0) + { + if (objecttype == 1) { + if constexpr (requires { obj.posZ(); }) { + if (!pass) { + histos.fill(HIST("hPosZ_BC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); + } else { + histos.fill(HIST("hPosZ_AC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); + } + } + } // eventSelection histogram + if (objecttype == 2) { + if constexpr (requires { obj.posZ(); }) { + if (!pass) { + histos.fill(HIST("hPosZ_BC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); + } else { + histos.fill(HIST("hPosZ_AC"), obj.posZ()); + histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); + } + } + } // Jet eventSelection histogram + if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { + if (objecttype == 3) { + if (!pass) { + histos.fill(HIST("hDCArToPv_BC"), obj.dcaXY()); + histos.fill(HIST("hDCAzToPv_BC"), obj.dcaZ()); + histos.fill(HIST("hIsPrim_BC"), obj.isPrimaryTrack()); + histos.fill(HIST("hIsGood_BC"), obj.isGlobalTrackWoDCA()); + histos.fill(HIST("hIsPrimCont_BC"), obj.isPVContributor()); + histos.fill(HIST("hFindableTPCClusters_BC"), obj.tpcNClsFindable()); + histos.fill(HIST("hFindableTPCRows_BC"), obj.tpcNClsCrossedRows()); + histos.fill(HIST("hClustersVsRows_BC"), obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hTPCChi2_BC"), obj.tpcChi2NCl()); + histos.fill(HIST("hITSChi2_BC"), obj.itsChi2NCl()); + histos.fill(HIST("QA_track_pT_BC"), obj.pt()); + } else { + histos.fill(HIST("hDCArToPv_AC"), obj.dcaXY()); + histos.fill(HIST("hDCAzToPv_AC"), obj.dcaZ()); + histos.fill(HIST("hIsPrim_AC"), obj.isPrimaryTrack()); + histos.fill(HIST("hIsGood_AC"), obj.isGlobalTrackWoDCA()); + histos.fill(HIST("hIsPrimCont_AC"), obj.isPVContributor()); + histos.fill(HIST("hFindableTPCClusters_AC"), obj.tpcNClsFindable()); + histos.fill(HIST("hFindableTPCRows_AC"), obj.tpcNClsCrossedRows()); + histos.fill(HIST("hClustersVsRows_AC"), obj.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("hTPCChi2_AC"), obj.tpcChi2NCl()); + histos.fill(HIST("hITSChi2_AC"), obj.itsChi2NCl()); + histos.fill(HIST("QA_track_pT_AC"), obj.pt()); + } + } + } // trackSelection + if (objecttype == 4) { + if constexpr (requires { obj.pt(); }) { + if (!pass) { + histos.fill(HIST("QA_nSigma_kaon_TPC_BC"), obj.pt(), obj.tpcNSigmaKa()); + histos.fill(HIST("QA_nSigma_kaon_TOF_BC"), obj.pt(), obj.tofNSigmaKa()); + histos.fill(HIST("QA_kaon_TPC_TOF_BC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); + } else { + histos.fill(HIST("QA_nSigma_kaon_TPC_AC"), obj.pt(), obj.tpcNSigmaKa()); + histos.fill(HIST("QA_nSigma_kaon_TOF_AC"), obj.pt(), obj.tofNSigmaKa()); + histos.fill(HIST("QA_kaon_TPC_TOF_AC"), obj.tpcNSigmaKa(), obj.tofNSigmaKa()); + } + } + } // kaon pid Selection + if (objecttype == 5) { + if constexpr (requires { obj.pt(); }) { + if (!pass) { + histos.fill(HIST("QA_nSigma_pion_TPC_BC"), obj.pt(), obj.tpcNSigmaPi()); + histos.fill(HIST("QA_nSigma_pion_TOF_BC"), obj.pt(), obj.tofNSigmaPi()); + histos.fill(HIST("QA_pion_TPC_TOF_BC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + } else { + histos.fill(HIST("QA_nSigma_pion_TPC_AC"), obj.pt(), obj.tpcNSigmaPi()); + histos.fill(HIST("QA_nSigma_pion_TOF_AC"), obj.pt(), obj.tofNSigmaPi()); + histos.fill(HIST("QA_pion_TPC_TOF_AC"), obj.tpcNSigmaPi(), obj.tofNSigmaPi()); + } + } + } // pion pid Selection + } // fill QA + + enum class objectType { MB, + Jets, + MBRecParticle, + JetsRecParticle }; + template + void fillMinv(objectType type, const TrackType& trk1, const TrackType& trk2, const ROOT::Math::PxPyPzMVector& lReso, double centrality, double jetpt, bool IsMix, bool flip) + { + double conjugate = trk1.sign() * trk2.sign(); + switch (type) { + case objectType::MB: + if (IsMix && cfgMixedHistos) { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi_Mix"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK_Mix"), centrality, lReso.Pt(), lReso.M()); + } + } else { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK"), centrality, lReso.Pt(), lReso.M()); + } else if (conjugate > 0) { + if (!flip) + histos.fill(HIST("hLSS_KPi"), centrality, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hLSS_PiK"), centrality, lReso.Pt(), lReso.M()); + } + } + break; + + case objectType::Jets: + if (!IsMix && cfgJetHistos) { + if (conjugate < 0) { + if (!flip) + histos.fill(HIST("hUSS_KPi_INSIDE"), centrality, jetpt, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hUSS_PiK_INSIDE"), centrality, jetpt, lReso.Pt(), lReso.M()); + } else { + if (conjugate > 0) { + if (!flip) + histos.fill(HIST("hLSS_KPi_INSIDE"), centrality, jetpt, lReso.Pt(), lReso.M()); + else + histos.fill(HIST("hLSS_PiK_INSIDE"), centrality, jetpt, lReso.Pt(), lReso.M()); + } + } + } + break; + + case objectType::MBRecParticle: + if (cfgMCHistos) { + if (conjugate < 0) { + histos.fill(HIST("hUSS_TrueRec"), centrality, lReso.Pt(), lReso.M()); + } + } + break; + + case objectType::JetsRecParticle: + if (cfgJetMCHistos) { + if (conjugate < 0) { + histos.fill(HIST("hUSS_TrueRec_INSIDE"), centrality, jetpt, lReso.Pt(), lReso.M()); + } + } + break; + } // switch + } // fillMinv + //====================================================================== + template - bool eventSelection(const EventType event) + std::pair eventSelection(const EventType event, const bool QA) { - if (cfgEventCutQA) { + if (cfgEventCutQA && QA) { + fillQA(false, event, 1); histos.fill(HIST("hEvent_Cut"), 0); - histos.fill(HIST("hPosZ_BC"), event.posZ()); - histos.fill(HIST("hcentFT0C_BC"), event.centFT0C()); } + if (!event.sel8()) - return false; - if (cfgEventCutQA) + return {false, 1}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 1); - + } if (std::abs(event.posZ()) > cfgEventVtxCut) - return false; - if (cfgEventCutQA) + return {false, 2}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 2); - + } if (!event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) - return false; - if (cfgEventCutQA) + return {false, 3}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 3); - + } if (!event.selection_bit(aod::evsel::kNoSameBunchPileup)) - return false; - if (cfgEventCutQA) + return {false, 4}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 4); - + } if (!event.selection_bit(aod::evsel::kNoTimeFrameBorder)) - return false; - if (cfgEventCutQA) + return {false, 5}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 5); - + } if (!event.selection_bit(aod::evsel::kNoITSROFrameBorder)) - return false; - if (cfgEventCutQA) + return {false, 6}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 6); - + } if (!event.selection_bit(aod::evsel::kNoCollInTimeRangeStandard)) - return false; - if (cfgEventCutQA) + return {false, 7}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 7); - + } if (!event.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) - return false; - if (cfgEventCutQA) + return {false, 8}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 8); - + } if (cfgOccupancySel && (event.trackOccupancyInTimeRange() > cfgOccupancyMax || event.trackOccupancyInTimeRange() < cfgOccupancyMin)) - return false; - if (cfgEventCutQA) + return {false, 9}; + if (cfgEventCutQA && QA) { histos.fill(HIST("hEvent_Cut"), 9); + } - if (cfgEventCutQA) { + if (cfgEventCutQA && QA) { + fillQA(true, event, 1); histos.fill(HIST("hEvent_Cut"), 10); - histos.fill(HIST("hPosZ_AC"), event.posZ()); - histos.fill(HIST("hcentFT0C_AC"), event.centFT0C()); } - return true; + return {true, 11}; + }; + + template + std::pair JeteventSelection(const EventType event, const bool QA) + { + if (cfgEventCutQA && QA) { + fillQA(false, event, 2); + } + + if (!jetderiveddatautilities::selectCollision(event, eventSelectionBits)) { // sel8 + return {false, 1}; + } + if (std::abs(event.posZ()) > cfgEventVtxCut) + return {false, 2}; + + if (cfgEventCutQA && QA) { + fillQA(true, event, 2); + } + return {true, 8}; }; template bool trackSelection(const TracksType track, const bool QA) { if (cfgTrackCutQA && QA) { - histos.fill(HIST("hDCArToPv_BC"), track.dcaXY()); - histos.fill(HIST("hDCAzToPv_BC"), track.dcaZ()); - histos.fill(HIST("hIsPrim_BC"), track.isPrimaryTrack()); - histos.fill(HIST("hIsGood_BC"), track.isGlobalTrackWoDCA()); - histos.fill(HIST("hIsPrimCont_BC"), track.isPVContributor()); - histos.fill(HIST("hFindableTPCClusters_BC"), track.tpcNClsFindable()); - histos.fill(HIST("hFindableTPCRows_BC"), track.tpcNClsCrossedRows()); - histos.fill(HIST("hClustersVsRows_BC"), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hTPCChi2_BC"), track.tpcChi2NCl()); - histos.fill(HIST("QA_track_pT_BC"), track.pt()); + fillQA(false, track, 3); } + if (cfgTrackGlobalSel && !track.isGlobalTrack()) return false; if (track.pt() < cfgTrackMinPt) @@ -341,30 +602,21 @@ struct kstarInOO { return false; if (cfgTrackGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cfgTracknFindableTPCClusters > 0 && track.tpcNClsFindable() < cfgTracknFindableTPCClusters) + if (cfgTrackFindableTPCClusters > 0 && track.tpcNClsFindable() < cfgTrackFindableTPCClusters) return false; - if (track.tpcNClsCrossedRows() < cfgTracknTPCCrossedRows) + if (track.tpcNClsCrossedRows() < cfgTrackTPCCrossedRows) return false; - if (cfgTracknRowsOverFindable > 0 && track.tpcCrossedRowsOverFindableCls() > cfgTracknRowsOverFindable) + if (cfgTrackRowsOverFindable > 0 && track.tpcCrossedRowsOverFindableCls() > cfgTrackRowsOverFindable) return false; - if (track.tpcChi2NCl() > cfgTracknTPCChi2) + if (track.tpcChi2NCl() > cfgTrackTPCChi2) return false; - if (track.itsChi2NCl() > cfgTracknITSChi2) + if (track.itsChi2NCl() > cfgTrackITSChi2) return false; if (cfgTrackConnectedToPV && !track.isPVContributor()) return false; if (cfgTrackCutQA && QA) { - histos.fill(HIST("hDCArToPv_AC"), track.dcaXY()); - histos.fill(HIST("hDCAzToPv_AC"), track.dcaZ()); - histos.fill(HIST("hIsPrim_AC"), track.isPrimaryTrack()); - histos.fill(HIST("hIsGood_AC"), track.isGlobalTrackWoDCA()); - histos.fill(HIST("hIsPrimCont_AC"), track.isPVContributor()); - histos.fill(HIST("hFindableTPCClusters_AC"), track.tpcNClsFindable()); - histos.fill(HIST("hFindableTPCRows_AC"), track.tpcNClsCrossedRows()); - histos.fill(HIST("hClustersVsRows_AC"), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("hTPCChi2_AC"), track.tpcChi2NCl()); - histos.fill(HIST("QA_track_pT_AC"), track.pt()); + fillQA(true, track, 3); } return true; }; @@ -372,14 +624,14 @@ struct kstarInOO { template bool trackPIDKaon(const TrackPID& candidate, const bool QA) { - if (cfgTrackCutQA && QA) { - histos.fill(HIST("QA_nSigma_kaon_TPC_BC"), candidate.pt(), candidate.tpcNSigmaKa()); - histos.fill(HIST("QA_nSigma_kaon_TOF_BC"), candidate.pt(), candidate.tofNSigmaKa()); - histos.fill(HIST("QA_kaon_TPC_TOF_BC"), candidate.tpcNSigmaKa(), candidate.tofNSigmaKa()); - } double tpcpid = 0; double tofpid = 0; bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfgTrackCutQA && QA) { + fillQA(false, candidate, 4); + } + // TPC if (cfgTrackSquarePIDCut) { if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) @@ -413,12 +665,11 @@ struct kstarInOO { tofPIDPassed = true; } } // circular cut + // TPC & TOF if (tpcPIDPassed && tofPIDPassed) { if (cfgTrackCutQA && QA) { - histos.fill(HIST("QA_nSigma_kaon_TPC_AC"), candidate.pt(), candidate.tpcNSigmaKa()); - histos.fill(HIST("QA_nSigma_kaon_TOF_AC"), candidate.pt(), candidate.tofNSigmaKa()); - histos.fill(HIST("QA_kaon_TPC_TOF_AC"), candidate.tpcNSigmaKa(), candidate.tofNSigmaKa()); + fillQA(true, candidate, 4); } return true; } @@ -428,14 +679,14 @@ struct kstarInOO { template bool trackPIDPion(const TrackPID& candidate, const bool QA) { - if (cfgTrackCutQA && QA) { - histos.fill(HIST("QA_nSigma_pion_TPC_BC"), candidate.pt(), candidate.tpcNSigmaPi()); - histos.fill(HIST("QA_nSigma_pion_TOF_BC"), candidate.pt(), candidate.tofNSigmaPi()); - histos.fill(HIST("QA_pion_TPC_TOF_BC"), candidate.tpcNSigmaPi(), candidate.tofNSigmaPi()); - } double tpcpid = 0; double tofpid = 0; bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfgTrackCutQA && QA) { + fillQA(false, candidate, 5); + } + // TPC if (cfgTrackSquarePIDCut) { if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) @@ -473,15 +724,109 @@ struct kstarInOO { // TPC & TOF if (tpcPIDPassed && tofPIDPassed) { if (cfgTrackCutQA && QA) { - histos.fill(HIST("QA_nSigma_pion_TPC_AC"), candidate.pt(), candidate.tpcNSigmaPi()); - histos.fill(HIST("QA_nSigma_pion_TOF_AC"), candidate.pt(), candidate.tofNSigmaPi()); - histos.fill(HIST("QA_pion_TPC_TOF_AC"), candidate.tpcNSigmaPi(), candidate.tofNSigmaPi()); + fillQA(true, candidate, 5); } return true; } return false; } + template + ROOT::Math::PxPyPzMVector minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA, const bool flip) + { + if (!trackSelection(trk1, false) || !trackSelection(trk2, false)) + return {}; + + if (!trackPIDKaon(trk1, QA) || !trackPIDPion(trk2, QA)) + return {}; + + if (trk1.globalIndex() >= trk2.globalIndex()) + return {}; + + ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResonance; + if (!flip) { + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massKa); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); + } else { + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massKa); + } + lResonance = lDecayDaughter1 + lDecayDaughter2; + + if (std::abs(lResonance.Eta()) > cfgTrackMaxEta) + return {}; + return {lResonance}; + } + + template + ROOT::Math::PxPyPzMVector TrueReconstruction(const TracksType& trk1, const TracksType& trk2) + { + double conjugate = trk1.sign() * trk2.sign(); + if (conjugate > 0) + return {}; + + auto particle1 = trk1.mcParticle(); + auto particle2 = trk2.mcParticle(); + + if (!particle1.has_mothers() || !particle2.has_mothers()) { + return {}; + } + + std::vector mothers1{}; + std::vector mothers1PDG{}; + for (auto& particle1_mom : particle1.template mothers_as()) { + mothers1.push_back(particle1_mom.globalIndex()); + mothers1PDG.push_back(particle1_mom.pdgCode()); + } + + std::vector mothers2{}; + std::vector mothers2PDG{}; + for (auto& particle2_mom : particle2.template mothers_as()) { + mothers2.push_back(particle2_mom.globalIndex()); + mothers2PDG.push_back(particle2_mom.pdgCode()); + } + + if (mothers1PDG[0] != 313) + return {}; // mother not K*0 + if (mothers2PDG[0] != 313) + return {}; // mothers not K*0 + + if (mothers1[0] != mothers2[0]) + return {}; // Kaon and pion not from the same K*0 + + if (std::fabs(particle1.pdgCode()) != 211 && std::fabs(particle1.pdgCode()) != 321) + return {}; + if (std::fabs(particle2.pdgCode()) != 211 && std::fabs(particle2.pdgCode()) != 321) + return {}; + + double track1_mass, track2_mass; + if (std::fabs(particle1.pdgCode()) == 211) { + track1_mass = massPi; + } else { + track1_mass = massKa; + } + + if (std::fabs(particle2.pdgCode()) == 211) { + track2_mass = massPi; + } else { + track2_mass = massKa; + } + + if (track1_mass == track2_mass) { + return {}; + } + + ROOT::Math::PxPyPzMVector lTrueDaughter1, lTrueDaughter2, lTrueReso; + lTrueDaughter1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), track1_mass); + lTrueDaughter2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), track2_mass); + lTrueReso = lTrueDaughter1 + lTrueDaughter2; + + if (lTrueReso.M() < 0) + return {}; + + return {lTrueReso}; + } + template void TrackSlicing(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix, const bool QA) { @@ -490,30 +835,13 @@ struct kstarInOO { auto centrality = collision1.centFT0C(); for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (bool flip : {false, true}) { + auto lReso = minvReconstruction(trk1, trk2, QA, flip); + if (lReso.M() < 0) + continue; - auto [KstarPt_Kpi, Minv_Kpi] = minvReconstruction(trk1, trk2, QA, false); - auto [KstarPt_piK, Minv_piK] = minvReconstruction(trk1, trk2, QA, true); - - if (Minv_Kpi < 0) - continue; - - double conjugate = trk1.sign() * trk2.sign(); - if (cfgDataHistos) { - if (!IsMix) { - if (conjugate < 0) { - histos.fill(HIST("hUSS_KPi"), centrality, KstarPt_Kpi, Minv_Kpi); - histos.fill(HIST("hUSS_PiK"), centrality, KstarPt_piK, Minv_piK); - } else if (conjugate > 0) { - histos.fill(HIST("hLSS_KPi"), centrality, KstarPt_Kpi, Minv_Kpi); - histos.fill(HIST("hLSS_PiK"), centrality, KstarPt_piK, Minv_piK); - } - } else { - if (conjugate < 0) { - histos.fill(HIST("hUSS_KPi_Mix"), centrality, KstarPt_Kpi, Minv_Kpi); - histos.fill(HIST("hUSS_PiK_Mix"), centrality, KstarPt_piK, Minv_piK); - } - } - } + fillMinv(objectType::MB, trk1, trk2, lReso, centrality, -1.0, IsMix, flip); + } // flip } // for } // TrackSlicing @@ -524,45 +852,402 @@ struct kstarInOO { auto tracks2 = pionMC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); auto centrality = collision1.centFT0C(); - std::vector mcMemory; - for (const auto& [trk1, trk2] : combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) continue; - auto [KstarPt_Kpi, Minv_Kpi] = minvReconstruction(trk1, trk2, QA, false); - auto [KstarPt_piK, Minv_piK] = minvReconstruction(trk1, trk2, QA, true); + for (bool flip : {false, true}) { + auto lReso = minvReconstruction(trk1, trk2, QA, flip); + if (lReso.M() < 0) + continue; - if (Minv_Kpi < 0) + fillMinv(objectType::MB, trk1, trk2, lReso, centrality, -1.0, IsMix, flip); + } // flip + + //============================ + //| True Reconstruction + //============================ + auto lTrueReso = TrueReconstruction(trk1, trk2); + fillMinv(objectType::MBRecParticle, trk1, trk2, lTrueReso, centrality, -1.0, IsMix, false); + } // tracks + } // TrackSlicingMC + + template + double DistinguishJets(const JetType& jets, ROOT::Math::PxPyPzMVector lResonance) + { + if (cDebugLevel > 0) + std::cout << "Finded multiple jets to the same phi." << std::endl; + + double bestR = 0; + double bestJetpT = 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((phidiff * phidiff) + (etadiff * etadiff)); + if (R < cfgJetR && bestR == 0) { + bestR = R; + bestJetpT = jet.pt(); + } else if (R < bestR) { + bestR = R; + bestJetpT = jet.pt(); + } + } // jet + return bestJetpT; + } + + template + void JetTrackSlicing(aod::JetCollision const& collision, TracksType const& jetTracks, const JetType& chargedjets, const bool IsMix, const bool QA) + { + //============================ + //| MB: Track Reconstruction + //============================ + auto centrality = collision.centFT0C(); + for (const auto& [track1, track2] : combinations(o2::soa::CombinationsUpperIndexPolicy(jetTracks, jetTracks))) { + auto trk1 = track1.template track_as(); + auto trk2 = track2.template track_as(); + + for (bool flip : {false, true}) { + auto lResonance = minvReconstruction(trk1, trk2, QA, flip); + if (lResonance.M() < 0) + continue; + + fillMinv(objectType::MB, trk1, trk2, lResonance, centrality, -1.0, IsMix, flip); + + //============================== + //| Jets: Track Reconstruction + //============================== + bool jetFlag = false; + int goodjets = 0; + double jetpt = 0; + for (auto const& jet : chargedjets) { + 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) { + jetFlag = true; + jetpt = jet.pt(); + goodjets++; + } + } + if (cfgJetQAHistos) { + histos.fill(HIST("nGoodJets"), goodjets); + } + if (!cfgSingleJet) { + if (goodjets > 1) { + jetpt = DistinguishJets(chargedjets, lResonance); + } + } + + if (jetFlag) { + fillMinv(objectType::Jets, trk1, trk2, lResonance, centrality, jetpt, IsMix, flip); + } // jetFlag + } // flip + } // jetTracks + } // JetTrackSlicing + + template + void JetTrackSlicingMC(aod::JetCollision const& collision, TracksType const& jetTracks, const JetType& chargedjets, const bool IsMix, const bool QA) + { + //============================ + //| MB: Track Reconstruction + //============================ + auto centrality = collision.centFT0C(); + for (const auto& [track1, track2] : combinations(o2::soa::CombinationsUpperIndexPolicy(jetTracks, jetTracks))) { + auto trk1 = track1.template track_as(); + auto trk2 = track2.template track_as(); + + if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) continue; - double conjugate = trk1.sign() * trk2.sign(); - if (cfgMcHistos) { - if (!IsMix) { - if (conjugate < 0) { - histos.fill(HIST("hMC_USS_KPi"), centrality, KstarPt_Kpi, Minv_Kpi); - histos.fill(HIST("hMC_USS_PiK"), centrality, KstarPt_piK, Minv_piK); - } else if (conjugate > 0) { - histos.fill(HIST("hMC_LSS_KPi"), centrality, KstarPt_Kpi, Minv_Kpi); - histos.fill(HIST("hMC_LSS_PiK"), centrality, KstarPt_piK, Minv_piK); + for (bool flip : {false, true}) { + auto lResonance = minvReconstruction(trk1, trk2, QA, flip); + if (lResonance.M() < 0) + continue; + + fillMinv(objectType::MB, trk1, trk2, lResonance, centrality, -1.0, IsMix, flip); + + //============================== + //| Jets: Track Reconstruction + //============================== + bool jetFlag = false; + int goodjets = 0; + double jetpt = 0; + for (auto const& jet : chargedjets) { + 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) { + jetFlag = true; + jetpt = jet.pt(); + goodjets++; } - } else { - if (conjugate < 0) { - histos.fill(HIST("hMC_USS_KPi_Mix"), centrality, KstarPt_Kpi, Minv_Kpi); - histos.fill(HIST("hMC_USS_PiK_Mix"), centrality, KstarPt_piK, Minv_piK); + } + if (cfgJetQAHistos) { + histos.fill(HIST("nGoodJets"), goodjets); + } + if (!cfgSingleJet) { + if (goodjets > 1) { + jetpt = DistinguishJets(chargedjets, lResonance); } } + + if (jetFlag) { + fillMinv(objectType::Jets, trk1, trk2, lResonance, centrality, jetpt, IsMix, flip); + } // jetFlag + + //=============================== + //| MB: Particle Reconstruction + //=============================== + auto lTrueReso = TrueReconstruction(trk1, trk2); + fillMinv(objectType::MBRecParticle, trk1, trk2, lTrueReso, centrality, -1.0, IsMix, false); + + //================================== + //| Jets: Particle Reconstruction + //================================== + if (jetFlag) { + fillMinv(objectType::JetsRecParticle, trk1, trk2, lTrueReso, centrality, jetpt, IsMix, false); + } // jetFlag + } // filp + } // Tracks loop + } // JetTrackSlicingMC + + //======================================================= + //| + //| JET DATA STUFF + //| + //======================================================= + int nJetEvents = 0; + void processDataJets(o2::aod::JetCollision const& collision, JetFilteredJets const& chargedjets, JetTrackCandidates const& jetTracks, TrackCandidates const&) + { + if (cDebugLevel > 0) { + nJetEvents++; + if ((nJetEvents + 1) % 10000 == 0) { + std::cout << "Processed Jet Data Events: " << nJetEvents << std::endl; + } + } + + histos.fill(HIST("nEvents"), 0.5); // Raw event + + // Trigger before we start jet finding + if (cfgCutonTrig) { + bool RT = false; + bool VTtest1 = false; + bool VTtest2 = false; + bool VTtest3 = false; + if (jetderiveddatautilities::selectTrigger(collision, RealTriggerMaskBits)) { + RT = true; + if (cfgJetQAHistos) { + histos.fill(HIST("nTriggerQA"), 0.5); + } + } + if (jetderiveddatautilities::selectTrigger(collision, triggerMaskBitsTest1)) { + VTtest1 = true; + if (cfgJetQAHistos) { + histos.fill(HIST("nTriggerQA"), 1.5); + } + } + if (jetderiveddatautilities::selectTrigger(collision, triggerMaskBitsTest2)) { + VTtest2 = true; + if (cfgJetQAHistos) { + histos.fill(HIST("nTriggerQA"), 2.5); + } + } + if (jetderiveddatautilities::selectTrigger(collision, triggerMaskBitsTest3)) { + VTtest3 = true; + if (cfgJetQAHistos) { + histos.fill(HIST("nTriggerQA"), 3.5); + } + } + if (!RT) { + return; + } else if (RT && (VTtest1 || VTtest2 || VTtest3)) { + return; } - //====================== - // Gen MC + } // Trigger cut + + histos.fill(HIST("nEvents"), 1.5); // Before passing the condition + + if (cfgManualEvSel) { + auto [goodEv, code] = JeteventSelection(collision, true); + if (!goodEv) + return; + } + + if (cfgJetEvSel) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + } + histos.fill(HIST("nEvents"), 2.5); // Events after event quality selection for Inclusive + + std::vector jetpT{}; + std::vector jetEta{}; + std::vector jetPhi{}; + bool HasJets = false; + int nJets = 0; + for (auto chargedjet : chargedjets) { + jetpT.push_back(chargedjet.pt()); + jetEta.push_back(chargedjet.eta()); + jetPhi.push_back(chargedjet.phi()); + nJets++; + if (cfgJetQAHistos) { + histos.fill(HIST("JetpT"), chargedjet.pt()); + histos.fill(HIST("JetEta"), chargedjet.eta()); + histos.fill(HIST("JetPhi"), chargedjet.phi()); + } + if (chargedjet.pt() > cfgJetpT) + HasJets = true; + } + if (cfgJetQAHistos) { + histos.fill(HIST("nJetsPerEvent"), nJets); + } + + //==================== + //|| Has Jets + //==================== + if (cfgReqJets) { + if (!HasJets) + return; + } + histos.fill(HIST("nEvents"), 3.5); // Has jets + + bool INELgt0 = false; + for (auto& jetTrack : jetTracks) { + auto originTrack = jetTrack.track_as(); + if (!trackSelection(originTrack, true)) + continue; + INELgt0 = true; + + if (cfgJetQAHistos) { + histos.fill(HIST("rawDimpT"), jetTrack.pt(), jetTrack.pt() - originTrack.pt()); + histos.fill(HIST("jetTrackEta"), jetTrack.eta()); + histos.fill(HIST("jetTrackPhi"), jetTrack.phi()); + } + } // jetTrack loop + if (!INELgt0) + return; + + JetTrackSlicing(collision, jetTracks, chargedjets, false, true); + + } // ProcessDataJets + PROCESS_SWITCH(kstarInOO, processDataJets, "process Data Jets", false); + + //======================================================= + //| + //| JET MC STUFF + //| + //======================================================= + int nJetMCEvents = 0; + void processMCJets(o2::aod::JetCollision const& collision, soa::Filtered const& mcdjets, JetTrackCandidatesMC const& jetTracks, TrackCandidatesMC const&, aod::McParticles const&) + { + if (cDebugLevel > 0) { + nJetMCEvents++; + if ((nJetMCEvents + 1) % 10000 == 0) { + std::cout << "Processed Jet MC Events: " << nJetMCEvents << std::endl; + } + } + histos.fill(HIST("nEvents"), 0.5); // Raw event + + if (std::abs(collision.posZ()) > cfgEventVtxCut) + return; + + if (!jetderiveddatautilities::selectTrigger(collision, RealTriggerMaskBits)) + return; + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + histos.fill(HIST("nEvents"), 1.5); // Before passing the condition + + bool INELgt0 = false; + for (auto& jetTrack : jetTracks) { + if (std::fabs(jetTrack.eta()) < cfgTrackMaxEta) { + INELgt0 = true; + break; + } + } // jetTrack loop + if (!INELgt0) + return; + + histos.fill(HIST("nEvents"), 2.5); // Events after event quality selection for Inclusive + + std::vector mcdjetpT{}; + std::vector mcdjetEta{}; + std::vector mcdjetPhi{}; + + bool HasJets = false; + int nJets = 0; + for (auto mcdjet : mcdjets) { + mcdjetpT.push_back(mcdjet.pt()); + mcdjetEta.push_back(mcdjet.eta()); + mcdjetPhi.push_back(mcdjet.phi()); + nJets++; + if (cfgJetQAHistos) { + histos.fill(HIST("JetpT"), mcdjet.pt()); + histos.fill(HIST("JetEta"), mcdjet.eta()); + histos.fill(HIST("JetPhi"), mcdjet.phi()); + } + if (mcdjet.pt() > cfgJetpT) { + HasJets = true; + } + } + if (cfgJetQAHistos) { + histos.fill(HIST("nJetsPerEvent"), nJets); + } + + //==================== + //|| Has Jets + //==================== + if (cfgReqJets) { + if (!HasJets) { + return; + } + } + histos.fill(HIST("nEvents"), 3.5); // Has jets + + // JetTrackSlicingMC(collision, jetTracks, chargedjets, false, true); + + for (auto& [track1, track2] : combinations(o2::soa::CombinationsUpperIndexPolicy(jetTracks, jetTracks))) { + auto trk1 = track1.track_as(); + auto trk2 = track2.track_as(); + + // Each section, test pT. which section we lost the entries + ROOT::Math::PxPyPzMVector lDecayDaughterTest1, lDecayDaughterTest2, lResonanceTest1; + lDecayDaughterTest1 = ROOT::Math::PxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massKa); + lDecayDaughterTest2 = ROOT::Math::PxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); + lResonanceTest1 = lDecayDaughterTest1 + lDecayDaughterTest2; + + if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) + continue; + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest1_pT"), lResonanceTest1.Pt()); + } + + if (!trackSelection(trk1, true) || !trackSelection(trk2, false)) + continue; + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest2_pT"), lResonanceTest1.Pt()); + } + + if (cfgReqMcEffPID) { + if (!trackPIDKaon(trk1, true) || !trackPIDPion(trk2, true)) + continue; + } + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest3_pT"), lResonanceTest1.Pt()); + } + auto particle1 = trk1.mcParticle(); auto particle2 = trk2.mcParticle(); - + //////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// if (!particle1.has_mothers() || !particle2.has_mothers()) { continue; } - int mcindex1 = trk1.globalIndex(); - int mcindex2 = trk2.globalIndex(); + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest4_pT"), lResonanceTest1.Pt()); + } + //////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// std::vector mothers1{}; std::vector mothers1PDG{}; @@ -571,98 +1256,55 @@ struct kstarInOO { mothers1PDG.push_back(particle1_mom.pdgCode()); } + if (cfgJetMCHistos) { + histos.fill(HIST("hMotherPdg1"), std::fabs(mothers1PDG[0])); + } std::vector mothers2{}; std::vector mothers2PDG{}; for (auto& particle2_mom : particle2.template mothers_as()) { mothers2.push_back(particle2_mom.globalIndex()); mothers2PDG.push_back(particle2_mom.pdgCode()); } - - if (mothers1PDG[0] != 313) - continue; // mother not K*0 - if (mothers2PDG[0] != 313) - continue; // mothers not K*0 + if (cfgJetMCHistos) { + histos.fill(HIST("hMotherPdg2"), std::fabs(mothers2PDG[0])); + } if (mothers1[0] != mothers2[0]) continue; // Kaon and pion not from the same K*0 - if (std::fabs(particle1.pdgCode()) != 211 && std::fabs(particle1.pdgCode()) != 321) - continue; - if (std::fabs(particle2.pdgCode()) != 211 && std::fabs(particle2.pdgCode()) != 321) - continue; - - double track1_mass, track2_mass; - bool track1f{false}; // true means pion - - if (std::fabs(particle1.pdgCode()) == 211) { - track1f = true; - track1_mass = massPi; - } else { - track1_mass = massKa; + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest5_pT"), lResonanceTest1.Pt()); } - if (std::fabs(particle2.pdgCode()) == 211) { - track2_mass = massPi; - } else { - track2_mass = massKa; - } + if (std::fabs(particle1.pdgCode()) != 321) // kaon + continue; - if (track1_mass == track2_mass) { - return; + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest6_pT"), lResonanceTest1.Pt()); } - bool exists1 = std::find(mcMemory.begin(), mcMemory.end(), mcindex1) != mcMemory.end(); - bool exists2 = std::find(mcMemory.begin(), mcMemory.end(), mcindex2) != mcMemory.end(); - if (exists1 || exists2) { + if (std::fabs(particle2.pdgCode()) != 211) // pion continue; - } else { - mcMemory.push_back(trk1.globalIndex()); - mcMemory.push_back(trk2.globalIndex()); - } - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), track1_mass); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), track2_mass); - lResonance = lDecayDaughter1 + lDecayDaughter2; - - if (cfgMcHistos) { - histos.fill(HIST("hMC_USS_True"), centrality, lResonance.Pt(), lResonance.M()); - if (track1f) { - histos.fill(HIST("hMC_USS_PiK_True"), centrality, lResonance.Pt(), lResonance.M()); - } else { - histos.fill(HIST("hMC_USS_KPi_True"), centrality, lResonance.Pt(), lResonance.M()); - } + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest7_pT"), lResonanceTest1.Pt()); } - //====================== - } // for - } // TrackSlicingMC - - template - std::pair minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA, const bool flip) - { - if (!trackSelection(trk1, false) || !trackSelection(trk2, false)) - return {-1.0, -1.0}; - if (!trackPIDKaon(trk1, QA) || !trackPIDPion(trk2, QA)) - return {-1.0, -1.0}; - - if (trk1.globalIndex() >= trk2.globalIndex()) - return {-1.0, -1.0}; + if (std::fabs(mothers1PDG[0]) != 313) + continue; // mother not K*0 + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRecTest8_pT"), lResonanceTest1.Pt()); + } - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - if (!flip) { - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); - } else { - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); - } - lResonance = lDecayDaughter1 + lDecayDaughter2; + if (std::fabs(mothers2PDG[0]) != 313) + continue; // mothers not K*0 - if (std::abs(lResonance.Eta()) > cfgTrackMaxEta) - return {-1.0, -1.0}; - return {lResonance.Pt(), lResonance.M()}; - } + if (cfgJetMCHistos) { + histos.fill(HIST("hEffRec_pT"), lResonanceTest1.Pt()); + } + } // track loop + } // process loop + PROCESS_SWITCH(kstarInOO, processMCJets, "process MC Jets", false); //======================================================= //| @@ -679,10 +1321,9 @@ struct kstarInOO { } } - auto goodEv = eventSelection(collision); - if (cfgDataHistos) { - histos.fill(HIST("nEvents"), 0.5); - } + auto [goodEv, code] = eventSelection(collision, true); + histos.fill(HIST("nEvents"), 0.5); + if (!goodEv) return; @@ -696,10 +1337,8 @@ struct kstarInOO { } if (!INELgt0) return; + histos.fill(HIST("nEvents"), 1.5); - if (cfgDataHistos) { - histos.fill(HIST("nEvents"), 1.5); - } TrackSlicing(collision, tracks, collision, tracks, false, true); } // processSameEvents @@ -723,8 +1362,8 @@ struct kstarInOO { std::cout << "Processed DATA Mixed Events : " << nEventsMix << std::endl; } } - auto goodEv1 = eventSelection(collision1); - auto goodEv2 = eventSelection(collision2); + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); bool VtxMixFlag = false; bool CentMixFlag = false; // bool OccupanacyMixFlag = false; @@ -761,10 +1400,10 @@ struct kstarInOO { std::cout << "process_SameEvent_MC: " << nEventsMC << std::endl; } } - auto goodEv = eventSelection(collision); - if (cfgMcHistos) { - histos.fill(HIST("nEvents_MC"), 0.5); - } + auto [goodEv, code] = eventSelection(collision, true); + + histos.fill(HIST("nEvents"), 0.5); + if (!goodEv) return; @@ -779,9 +1418,8 @@ struct kstarInOO { if (!INELgt0) return; - if (cfgMcHistos) { - histos.fill(HIST("nEvents_MC"), 1.5); - } + histos.fill(HIST("nEvents"), 1.5); + TrackSlicingMC(collision, tracks, collision, tracks, false, true); } // processSameEvents_MC PROCESS_SWITCH(kstarInOO, processSameEventMC, "process Same Event MC", false); @@ -804,8 +1442,8 @@ struct kstarInOO { std::cout << "Processed Mixed Events: " << nEventsMCMix << std::endl; } } - auto goodEv1 = eventSelection(collision1); - auto goodEv2 = eventSelection(collision2); + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); if (!goodEv1 || !goodEv2) { continue; } @@ -815,54 +1453,203 @@ struct kstarInOO { } // processMixedEvent_MC PROCESS_SWITCH(kstarInOO, processMixedEventMC, "process Mixed Event MC", false); - //======================================================= + //====================================== //| - //| GENERATED MC STUFF (TRUE) + //| GENERATED STUFF //| - //======================================================= - int nEventsTrue = 0; - void processMCTrue(EventCandidatesTrue::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& particles) + //====================================== + int nEventsGen = 0; + void processGen(EventCandidatesTrue::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& mcParticles) { if (cDebugLevel > 0) { - ++nEventsTrue; + ++nEventsGen; + if (nEventsGen % 10000 == 0) { + std::cout << "Processed MC (GEN) Events: " << nEventsGen << std::endl; + } + } + //======================= + //|| Event & Signal loss + //======================= + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 0.5); } - if (fabs(collision.posZ()) > cfgEventVtxCut) - return; + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + if (fabs(collision.posZ()) > cfgEventVtxCut) + break; + + if (cfgMCHistos) { + histos.fill(HIST("hGen_pT_Raw"), particle.pt()); + } + } // Unreconstructed collisions(=Raw coll) for correction + if (recocolls.size() <= 0) { // not reconstructed if (cfgForceGenReco) { return; } } - double centrality = -1; for (auto& recocoll : recocolls) { centrality = recocoll.centFT0C(); - auto goodEv = eventSelection(recocoll); + auto [goodEv, code] = eventSelection(recocoll, true); - if (cfgMcHistos) { - histos.fill(HIST("nEvents_MC_True"), 0.5); + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 1.5); } if (!goodEv) continue; - } // for + } // recocolls (=reconstructed collisions) - for (auto& particle : particles) { + //================= + //|| Efficiency + //================= + for (auto& particle : mcParticles) { if (particle.pdgCode() != 313) continue; // Not K*0 if (std::fabs(particle.eta()) > cfgTrackMaxEta) continue; - if (cfgMcHistos) { - histos.fill(HIST("hMC_kstar_True"), centrality, particle.pt()); + if (cfgMCHistos) { + histos.fill(HIST("nEvents_Gen"), 2.5); + histos.fill(HIST("hGen_pT_GoodEv"), centrality, particle.pt()); + } // cfgMCHistos + } // loop over particles + } // processMCTrue + PROCESS_SWITCH(kstarInOO, processGen, "process Generated Particles", false); + + //============================================== + //| + //| GENERATED STUFF (INCLUSIVE & JETS) + //| + //============================================== + int nprocessGenEvents = 0; + void processJetsGen(o2::aod::JetMcCollision const& collision, soa::SmallGroups> const& recocolls, aod::JetParticles const& mcParticles) + { + if (cDebugLevel > 0) { + ++nprocessGenEvents; + if (nprocessGenEvents % 10000 == 0) { + std::cout << "Processed MC (GEN) Events: " << nprocessGenEvents << std::endl; + } + } + //======================= + //|| Event & Signal loss + //======================= + if (cfgJetMCHistos) { + histos.fill(HIST("nEvents_Gen"), 0.5); + } + + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + if (fabs(collision.posZ()) > cfgEventVtxCut) + break; + + if (cfgJetMCHistos) { + histos.fill(HIST("hGen_pT_Raw"), particle.pt()); + } + } // Unrecon. collision(=Raw coll) for correction + + if (recocolls.size() <= 0) { // not reconstructed + return; + } + + for (auto& recocoll : recocolls) { // poorly reconstructed + if (recocoll.posZ() > cfgEventVtxCut) + continue; + auto goodEv = jetderiveddatautilities::selectCollision(recocoll, eventSelectionBits); + auto goodTrig = jetderiveddatautilities::selectTrigger(recocoll, RealTriggerMaskBits); + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + if (cfgJetMCHistos) { + // check K* PID + if (goodEv) { + histos.fill(HIST("hGen_pT_GoodEv"), particle.pt()); + + } // goodEv + + if (goodTrig) { + histos.fill(HIST("hGen_pT_GoodTrig"), particle.pt()); + + } // goodTrig + + if (goodEv && goodTrig) { + histos.fill(HIST("hGen_pT_GoodEvTrig"), particle.pt()); + + if (cfgJetQAHistos) { + histos.fill(HIST("nTriggerQA"), 7.5); + } + + } // goodEvTrig + } // cfgJetMCHistos + } // mcParticles + } // recocolls (=reconstructed collisions) + + //================= + //|| Efficiency + //================= + // if (fabs(collision.posZ()) > cfgEventVtxCut) + // return; + + for (auto& recocoll : recocolls) { // poorly reconstructed + auto goodEv = jetderiveddatautilities::selectCollision(recocoll, eventSelectionBits); + if (goodEv) { + goodEv = jetderiveddatautilities::selectTrigger(recocoll, RealTriggerMaskBits); } - if (cfgMcHistos) { - histos.fill(HIST("nEvents_MC_True"), 1.5); + if (cfgJetMCHistos) { + histos.fill(HIST("nEvents_Gen"), 1.5); } + if (!goodEv) + return; + } + if (cfgJetMCHistos) { + histos.fill(HIST("nEvents_Gen"), 2.5); + } + for (auto& particle : mcParticles) { + if (particle.pdgCode() != 313) + continue; + if (std::fabs(particle.eta()) > cfgTrackMaxEta) + continue; + if (particle.pt() < cfgTrackMinPt) + continue; + + /* // Not Yet + if (cfg_Force_BR) { + bool baddecay = false; + for (auto& phidaughter : particle.daughters_as()) { + if (std::fabs(phidaughter.pdgCode()) != 321) { + baddecay = true; + break; + } + if (cfg_Force_Kaon_Acceptence) { + if (std::fabs(phidaughter.eta()) > cfg_Track_MaxEta) { + baddecay = true; + break; + } + } + } // loop over daughters + + if (baddecay) + continue; + } // enforce BR restriction + */ + + if (cfgJetMCHistos) { + histos.fill(HIST("nEvents_Gen"), 3.5); + histos.fill(HIST("hEffGen_pT"), particle.pt()); + } // cfgJetMCHistos } // loop over particles - } // processMCTrue - PROCESS_SWITCH(kstarInOO, processMCTrue, "process MC True", false); + } // end of process + PROCESS_SWITCH(kstarInOO, processJetsGen, "Process Generated Particles Inclusive&Jets", false); void processEventsDummy(EventCandidates::iterator const&, TrackCandidates const&) { diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index 06c608cbbd5..e581299b318 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -86,12 +87,18 @@ struct Kstarqa { Configurable isGoodITSLayersAll{"isGoodITSLayersAll", true, "Require all ITS layers to be good"}; Configurable isNoTimeFrameBorder{"isNoTimeFrameBorder", true, "kNoTimeFrameBorder"}; Configurable isNoITSROFrameBorder{"isNoITSROFrameBorder", true, "kNoITSROFrameBorder"}; - // Configurable isApplyParticleMID{"isApplyParticleMID", true, "Apply particle misidentification"}; + Configurable isapplypTdepPID{"isapplypTdepPID", false, "Apply pT dependent PID"}; + Configurable isapplypTdepPIDTOF{"isapplypTdepPIDTOF", false, "Apply pT dependent PID for TOF"}; + Configurable isApplyParticleMID{"isApplyParticleMID", false, "Apply particle misidentification"}; + Configurable isApplyParticleMIDPtDep{"isApplyParticleMIDPtDep", false, "Apply pT dependent MID selection"}; + Configurable AllGenEvents{"AllGenEvents", false, "Fill all generated events in MC for signal loss calculations"}; + Configurable checkVzEvSigLoss{"checkVzEvSigLoss", false, "Check Vz event signal loss"}; Configurable isApplyDeepAngle{"isApplyDeepAngle", false, "Deep Angle cut"}; Configurable isApplyMCchecksClosure{"isApplyMCchecksClosure", true, "Apply MC checks for closure test"}; + Configurable deltaRCut{"deltaRCut", 0.0f, "Apply deltaR cut between two daughters"}; - // Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; Configurable configOccCut{"configOccCut", 1000., "Occupancy cut"}; // Configurables for track selections @@ -137,20 +144,20 @@ struct Kstarqa { Configurable nsigmaCutTOFKa{"nsigmaCutTOFKa", 3.0, "TOF Nsigma cut for kaons"}; Configurable nsigmaCutCombinedKa{"nsigmaCutCombinedKa", 3.0, "Combined Nsigma cut for kaon"}; Configurable nsigmaCutCombinedPi{"nsigmaCutCombinedPi", 3.0, "Combined Nsigma cut for pion"}; - /* Configurable nsigmaCutCombinedMIDKa{"nsigmaCutCombinedMIDKa", 3.0, "Combined Nsigma cut for kaon in MID"}; - Configurable nsigmaCutCombinedMIDPi{"nsigmaCutCombinedMIDPi", 3.0, "Combined Nsigma cut for pion in MID"}; - Configurable nsigmaCutTPCMIDPi{"nsigmaCutTPCMIDPi", 1.0, "MID Nsigma cut for pion in TPC"}; - Configurable nsigmaCutTPCMIDKa{"nsigmaCutTPCMIDKa", 1.0, "MID Nsigma cut for kaon in TPC"}; - Configurable nsigmaCutTOFMIDPi{"nsigmaCutTOFMIDPi", 1.0, "MID Nsigma cut for pion in TOF"}; - Configurable nsigmaCutTOFMIDKa{"nsigmaCutTOFMIDKa", 1.0, "MID Nsigma cut for kaon in TOF"}; - Configurable nsigmaCutTPCMIDPr{"nsigmaCutTPCMIDPr", 3.0, "TPC Nsigma cut for protons (for MID)"}; - Configurable nsigmaCutTOFMIDPr{"nsigmaCutTOFMIDPr", 3.0, "TOF Nsigma cut for protons (for MID)"}; */ + // Configurable nsigmaCutCombinedMIDKa{"nsigmaCutCombinedMIDKa", 3.0, "Combined Nsigma cut for kaon in MID"}; + Configurable nsigmaCutCombinedMID{"nsigmaCutCombinedMID", 3.0, "Combined Nsigma cut for pion in MID"}; + Configurable nsigmaCutTPCMID{"nsigmaCutTPCMID", 1.0, "MID Nsigma cut for pion in TPC"}; + // Configurable nsigmaCutTPCMIDKa{"nsigmaCutTPCMIDKa", 1.0, "MID Nsigma cut for kaon in TPC"}; + // Configurable nsigmaCutTOFMIDPi{"nsigmaCutTOFMIDPi", 1.0, "MID Nsigma cut for pion in TOF"}; + // Configurable nsigmaCutTOFMIDKa{"nsigmaCutTOFMIDKa", 1.0, "MID Nsigma cut for kaon in TOF"}; + // Configurable nsigmaCutTPCMIDPr{"nsigmaCutTPCMIDPr", 3.0, "TPC Nsigma cut for protons (for MID)"}; + // Configurable nsigmaCutTOFMIDPr{"nsigmaCutTOFMIDPr", 3.0, "TOF Nsigma cut for protons (for MID)"}; // Other fixed variables float lowPtCutPID = 0.5; int noOfDaughters = 2; // float rapidityMotherData = 0.5; - float cutzvertex = 10.0f; + // float cutzvertex = 10.0f; float cfgCutEtaMax = 0.8f; float cfgCutPT = 0.2f; float cfgDeepAngle = 0.04; @@ -193,7 +200,6 @@ struct Kstarqa { Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; Configurable cSelectMultEstimator{"cSelectMultEstimator", 0, "Select multiplicity estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C, 3 - FV0A"}; Configurable applyRecMotherRapidity{"applyRecMotherRapidity", true, "Apply rapidity cut on reconstructed mother track"}; - Configurable applypTdepPID{"applypTdepPID", false, "Apply pT dependent PID"}; // Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", false, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) Configurable cBetaCutTOF{"cBetaCutTOF", 0.0, "cut TOF beta"}; @@ -247,7 +253,7 @@ struct Kstarqa { std::vector eveCutLabels = { "All Events", - Form("|Vz| < %.1f", selectionConfig.cutzvertex), + "|Vz| < 10", "sel8", std::string("kNoTimeFrameBorder") + check(selectionConfig.isNoTimeFrameBorder.value), std::string("kNoITSROFrameBorder") + check(selectionConfig.isNoITSROFrameBorder.value), @@ -364,7 +370,7 @@ struct Kstarqa { hInvMass.add("MCcorrections/hKstarGenAfterEvtSel", "K*0 after event selections", kTH2F, {ptAxis, impactParAxis}); } - if (doprocessEvSigLossFactors) { + if (doprocessEvSigLossFactors || doprocessEvSigLossFactorsPhi) { hInvMass.add("CorrFactors/hMultiplicityVsMultMC", "Event centrality vs MC centrality", kTH2F, {{101, 0.0f, 101.0f}, axisNch}); hInvMass.add("CorrFactors/hEventCentrality", "Event centrality", kTH1F, {{101, 0, 101}}); hInvMass.add("CorrFactors/hNrecInGen", "Number of collisions in MC", kTH1F, {{4, -0.5, 3.5}}); @@ -377,8 +383,8 @@ struct Kstarqa { hInvMass.add("CorrFactors/h2dGenKstar", "Centrality vs p_{T}", kTH2D, {{101, 0.0f, 101.0f}, ptAxis}); hInvMass.add("CorrFactors/h3dGenKstarVsMultMCVsMultiplicity", "MC centrality vs centrality vs p_{T}", kTH3D, {axisNch, {101, 0.0f, 101.0f}, ptAxis}); - hInvMass.add("CorrFactors/hSignalLossDenominator", "Kstar generated before event selection", kTH2F, {{ptAxis}, {axisNch}}); - hInvMass.add("CorrFactors/hSignalLossNumerator", "Kstar generated after event selection", kTH2F, {{ptAxis}, {axisNch}}); + hInvMass.add("CorrFactors/hSignalLoss1", "Kstar generated before event selection", kTH2F, {{ptAxis}, {axisNch}}); + hInvMass.add("CorrFactors/hSignalLoss2", "Kstar generated after event selection", kTH2F, {{ptAxis}, {axisNch}}); hInvMass.add("CorrFactors/MultiplicityRec", "Multiplicity in generated MC with at least 1 reconstruction", kTH1F, {axisNch}); hInvMass.add("CorrFactors/MultiplicityGen", "Multiplicity in generated MC", kTH1F, {axisNch}); } @@ -420,7 +426,8 @@ struct Kstarqa { hGenTracks->GetXaxis()->SetBinLabel(1, "All events"); hGenTracks->GetXaxis()->SetBinLabel(2, "INELgt0+vtz"); hGenTracks->GetXaxis()->SetBinLabel(3, "INELgt0"); - hGenTracks->GetXaxis()->SetBinLabel(4, "Event Reconstructed"); + hGenTracks->GetXaxis()->SetBinLabel(4, "All Collisions"); + hGenTracks->GetXaxis()->SetBinLabel(5, "Event Reconstructed"); // Multplicity distribution if (cQAevents) { @@ -617,6 +624,10 @@ struct Kstarqa { if (selectionConfig.isApplyDeepAngle && angle < selectionConfig.cfgDeepAngle) { return false; } + double deltaRvalue = std::sqrt(TVector2::Phi_mpi_pi(candidate1.phi() - candidate2.phi()) * TVector2::Phi_mpi_pi(candidate1.phi() - candidate2.phi()) + (candidate1.eta() - candidate2.eta()) * (candidate1.eta() - candidate2.eta())); + if (deltaRvalue < selectionConfig.deltaRCut) { + return false; + } return true; } @@ -686,84 +697,86 @@ struct Kstarqa { return false; } - /* template + template bool selectionMID(const T& candidate, int PID) { if (PID == PIDParticle::kPion) { if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFMIDPi && candidate.beta() > cBetaCutTOF) { - return true; - } - } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFMIDPi && candidate.beta() > cBetaCutTOF) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMIDPi) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { return true; } } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMIDPi) { + if (std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { return true; } } else { - if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedMIDPi * selectionConfig.nsigmaCutCombinedMIDPi) && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedMID * selectionConfig.nsigmaCutCombinedMID)) { return true; } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMIDPi) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { return true; } } } else if (PID == PIDParticle::kKaon) { if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFMIDKa && candidate.beta() > cBetaCutTOF) { - return true; - } - } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFMIDKa && candidate.beta() > cBetaCutTOF) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMIDKa) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { return true; } } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMIDKa) { + if (std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { return true; } } else { - if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedMIDKa * selectionConfig.nsigmaCutCombinedMIDKa) && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedMID * selectionConfig.nsigmaCutCombinedMID)) { return true; } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMIDKa) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { return true; } } - } else if (PID == PIDParticle::kProton) { // for proton - if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr && candidate.beta() > cBetaCutTOF) { - return true; - } - } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr && candidate.beta() > cBetaCutTOF) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { - return true; - } - } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { - return true; - } - } else { - if (candidate.hasTOF() && (candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < (selectionConfig.nsigmaCutTOFPr * selectionConfig.nsigmaCutTOFPr) && candidate.beta() > cBetaCutTOF) { - return true; - } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { - return true; - } + } + // else if (PID == PIDParticle::kProton) { // for proton + // if (onlyTOF) { + // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr && candidate.beta() > cBetaCutTOF) { + // return true; + // } + // } else if (onlyTOFHIT) { + // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr && candidate.beta() > cBetaCutTOF) { + // return true; + // } + // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { + // return true; + // } + // } else if (onlyTPC) { + // if (std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { + // return true; + // } + // } else { + // if (candidate.hasTOF() && (candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < (selectionConfig.nsigmaCutTOFPr * selectionConfig.nsigmaCutTOFPr) && candidate.beta() > cBetaCutTOF) { + // return true; + // } + // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { + // return true; + // } + // } + // } + return false; + } + + template + bool selectionMIDPtDep(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + if (candidate.pt() >= 1.0 && candidate.pt() < 2.5 && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCMID) { + return true; + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() >= 0.7 && candidate.pt() < 2.5 && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCMID) { + return true; } } return false; - } */ + } template bool selectionPIDPtDep(const T& candidate, int PID) @@ -817,10 +830,49 @@ struct Kstarqa { } } if (candidate.pt() >= selectionConfig.lowPtCutPID && candidate.hasTOF()) { - if (candidate.pt() < 2.0 && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (2.5 * 2.5)) { + if (candidate.pt() < 2.0 && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa)) { return true; } - if (candidate.pt() >= 2.0 && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa)) { + if (candidate.pt() >= 2.0 && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (1.0 * 1.0)) { + return true; + } + } + } + return false; + } + + template + bool selectionPIDptDepTOF(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + if (candidate.pt() < 1 || candidate.pt() > 2.5) { + if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi && !candidate.hasTOF()) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedPi * selectionConfig.nsigmaCutCombinedPi)) { + return true; + } + } + } else if (PID == PIDParticle::kKaon) { + if (candidate.pt() < 0.7 || candidate.pt() > 2.5) { + if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa && !candidate.hasTOF()) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa)) { return true; } } @@ -1081,14 +1133,19 @@ struct Kstarqa { } // 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 (!applypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPID(track1, 1)) // Track 1 is checked with Kaon continue; - if (!applypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPID(track2, 0)) // Track 2 is checked with Pion continue; - if (applypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon + if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon continue; - if (applypTdepPID && !selectionPIDPtDep(track2, 0)) // Track 2 is checked with Pion + if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPIDPtDep(track2, 0)) // Track 2 is checked with Pion + continue; + + if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !selectionPIDptDepTOF(track1, 1)) // Track 1 is checked with Kaon + continue; + if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !selectionPIDptDepTOF(track2, 0)) // Track 2 is checked with Pion continue; rEventSelection.fill(HIST("tracksCheckData"), 2.5); @@ -1106,16 +1163,23 @@ struct Kstarqa { continue; rEventSelection.fill(HIST("tracksCheckData"), 4.5); - /* if (selectionConfig.isApplyParticleMID) { + if (selectionConfig.isApplyParticleMID) { if (selectionMID(track1, 0)) // Kaon misidentified as pion continue; - if (selectionMID(track1, 2)) // Kaon misidentified as proton - continue; + // if (selectionMID(track1, 2)) // Kaon misidentified as proton + // continue; if (selectionMID(track2, 1)) // Pion misidentified as kaon continue; - if (selectionMID(track2, 2)) // Pion misidentified as proton + // if (selectionMID(track2, 2)) // Pion misidentified as proton + // continue; + } + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(track1, 0)) // Kaon misidentified as pion continue; - } */ + if (selectionMIDPtDep(track2, 1)) // Pion misidentified as kaon + continue; + } rEventSelection.fill(HIST("tracksCheckData"), 5.5); @@ -1135,9 +1199,9 @@ struct Kstarqa { hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track2.tpcNSigmaPi(), track2.tofNSigmaPi(), track2.pt()); } - // if (!selectionPair(track1, track2)) { - // continue; - // } + if (!selectionPair(track1, track2)) { + continue; + } rEventSelection.fill(HIST("tracksCheckData"), 6.5); daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); @@ -1214,7 +1278,21 @@ struct Kstarqa { o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (!selectionTrack(t1) || !selectionTrack(t2)) continue; - if (!selectionPID(t1, 1) || !selectionPID(t2, 0)) + // if (!selectionPID(t1, 1) || !selectionPID(t2, 0)) + // continue; + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPID(t1, 1)) // Track 1 is checked with Kaon + continue; + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPID(t2, 0)) // Track 2 is checked with Pion + continue; + + if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPIDPtDep(t1, 1)) // Track 1 is checked with Kaon + continue; + if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !selectionPIDPtDep(t2, 0)) // Track 2 is checked with Pion + continue; + + if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !selectionPIDptDepTOF(t1, 1)) // Track 1 is checked with Kaon + continue; + if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !selectionPIDptDepTOF(t2, 0)) // Track 2 is checked with Pion continue; if (std::abs(t1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) @@ -1228,20 +1306,27 @@ struct Kstarqa { // if (cFakeTrack && isFakeTrack(t2, 0)) // Pion // continue; - /* if (selectionConfig.isApplyParticleMID) { + if (selectionConfig.isApplyParticleMID) { if (selectionMID(t1, 0)) // Kaon misidentified as pion continue; - if (selectionMID(t1, 2)) // Kaon misidentified as proton - continue; + // if (selectionMID(t1, 2)) // Kaon misidentified as proton + // continue; if (selectionMID(t2, 1)) // Pion misidentified as kaon continue; - if (selectionMID(t2, 2)) // Pion misidentified as proton + // if (selectionMID(t2, 2)) // Pion misidentified as proton + // continue; + } + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(t1, 0)) // Kaon misidentified as pion continue; - } */ + if (selectionMIDPtDep(t2, 1)) // Pion misidentified as kaon + continue; + } - // if (!selectionPair(t1, t2)) { - // continue; - // } + if (!selectionPair(t1, t2)) { + continue; + } daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massPi); @@ -1288,19 +1373,35 @@ struct Kstarqa { for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (!selectionTrack(t1) || !selectionTrack(t2)) continue; - if (!selectionPID(t1, 1) || !selectionPID(t2, 0)) + // if (!selectionPID(t1, 1) || !selectionPID(t2, 0)) + // continue; + if (!selectionConfig.isapplypTdepPID && !selectionPID(t1, 1)) // Track 1 is checked with Kaon + continue; + if (!selectionConfig.isapplypTdepPID && !selectionPID(t2, 0)) // Track 2 is checked with Pion continue; - /* if (selectionConfig.isApplyParticleMID) { + if (selectionConfig.isapplypTdepPID && !selectionPIDPtDep(t1, 1)) // Track 1 is checked with Kaon + continue; + if (selectionConfig.isapplypTdepPID && !selectionPIDPtDep(t2, 0)) // Track 2 is checked with Pion + continue; + + if (selectionConfig.isApplyParticleMID) { if (selectionMID(t1, 0)) // Kaon misidentified as pion continue; - if (selectionMID(t1, 2)) // Kaon misidentified as proton - continue; + // if (selectionMID(t1, 2)) // Kaon misidentified as proton + // continue; if (selectionMID(t2, 1)) // Pion misidentified as kaon continue; - if (selectionMID(t2, 2)) // Pion misidentified as proton + // if (selectionMID(t2, 2)) // Pion misidentified as proton + // continue; + } + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(t1, 0)) // Kaon misidentified as pion continue; - } */ + if (selectionMIDPtDep(t2, 1)) // Pion misidentified as kaon + continue; + } if (selectionConfig.isApplyMCchecksClosure && (!t1.has_mcParticle() || !t2.has_mcParticle())) { continue; // skip if no MC particle associated @@ -1425,28 +1526,35 @@ struct Kstarqa { } // 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 (!applypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (!selectionConfig.isapplypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon continue; - if (!applypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion + if (!selectionConfig.isapplypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion continue; rEventSelection.fill(HIST("tracksCheckData"), 2.5); - if (applypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon + if (selectionConfig.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon continue; - if (applypTdepPID && !selectionPIDPtDep(track2, 0)) // Track 2 is checked with Pion + if (selectionConfig.isapplypTdepPID && !selectionPIDPtDep(track2, 0)) // Track 2 is checked with Pion continue; rEventSelection.fill(HIST("tracksCheckData"), 3.5); - /* if (selectionConfig.isApplyParticleMID) { + if (selectionConfig.isApplyParticleMID) { if (selectionMID(track1, 0)) // Kaon misidentified as pion continue; - if (selectionMID(track1, 2)) // Kaon misidentified as proton - continue; + // if (selectionMID(track1, 2)) // Kaon misidentified as proton + // continue; if (selectionMID(track2, 1)) // Pion misidentified as kaon continue; - if (selectionMID(track2, 2)) // Pion misidentified as proton + // if (selectionMID(track2, 2)) // Pion misidentified as proton + // continue; + } + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(track1, 0)) // Kaon misidentified as pion continue; - } */ + if (selectionMIDPtDep(track2, 1)) // Pion misidentified as kaon + continue; + } rEventSelection.fill(HIST("tracksCheckData"), 4.5); if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) @@ -1570,6 +1678,8 @@ struct Kstarqa { rEventSelection.fill(HIST("eventsCheckGen"), 2.5); for (const auto& collision : collisions) { + rEventSelection.fill(HIST("eventsCheckGen"), 3.5); + if (!selectionEvent(collision, false)) { // don't fill event cut histogram continue; } @@ -1616,7 +1726,7 @@ struct Kstarqa { hInvMass.fill(HIST("sigEvLossFromGenRec/MultiplicityRec"), genMultiplicity); hInvMass.fill(HIST("h1GenMult2"), genMultiplicity); hInvMass.fill(HIST("hAllGenCollisions1Rec"), multiplicity); - rEventSelection.fill(HIST("eventsCheckGen"), 3.5); + rEventSelection.fill(HIST("eventsCheckGen"), 4.5); } for (const auto& mcParticle : mcParticles) { @@ -1715,7 +1825,7 @@ struct Kstarqa { return; } - if (selectionConfig.checkVzEvSigLoss && (std::abs(mcCollision.posZ()) >= selectionConfig.cutzvertex)) { + if (selectionConfig.checkVzEvSigLoss && (std::abs(mcCollision.posZ()) > selectionConfig.cutzvertex)) { return; } @@ -1838,9 +1948,9 @@ struct Kstarqa { hInvMass.fill(HIST("CorrFactors/h2dGenKstar"), multiplicity, mother.Pt()); hInvMass.fill(HIST("CorrFactors/h3dGenKstarVsMultMCVsMultiplicity"), multiplicityNch, multiplicity, mother.Pt()); - hInvMass.fill(HIST("CorrFactors/hSignalLossDenominator"), mother.pt(), multiplicityNch); + hInvMass.fill(HIST("CorrFactors/hSignalLoss1"), mother.pt(), multiplicityNch); if (isSelectedEvent) { - hInvMass.fill(HIST("CorrFactors/hSignalLossNumerator"), mother.pt(), multiplicityNch); + hInvMass.fill(HIST("CorrFactors/hSignalLoss2"), mother.pt(), multiplicityNch); } } } @@ -1991,22 +2101,32 @@ struct Kstarqa { rEventSelection.fill(HIST("recMCparticles"), 11.5); if (selectionConfig.isPDGCheckMC && (track1PDG == PDG_t::kPiPlus)) { - if (!applypTdepPID && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon continue; - } else if (applypTdepPID && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon + } else if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon + continue; + } else if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 0) && selectionPIDptDepTOF(track2, 1))) { // pion and kaon continue; } + rEventSelection.fill(HIST("recMCparticles"), 12.5); - /* if (selectionConfig.isApplyParticleMID) { + if (selectionConfig.isApplyParticleMID) { if (selectionMID(track2, 0)) // Kaon misidentified as pion continue; - if (selectionMID(track2, 2)) // Kaon misidentified as proton - continue; + // if (selectionMID(track2, 2)) // Kaon misidentified as proton + // continue; if (selectionMID(track1, 1)) // Pion misidentified as kaon continue; - if (selectionMID(track1, 2)) // Pion misidentified as proton + // if (selectionMID(track1, 2)) // Pion misidentified as proton + // continue; + } + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(track1, 1)) // Kaon misidentified as pion + continue; + if (selectionMIDPtDep(track2, 0)) // Pion misidentified as kaon continue; - } */ + } rEventSelection.fill(HIST("recMCparticles"), 13.5); if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > selectionConfig.ctrackRapidity) @@ -2024,24 +2144,32 @@ struct Kstarqa { } } else if (selectionConfig.isPDGCheckMC && (track1PDG == PDG_t::kKPlus)) { - if (!applypTdepPID && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // pion and kaon continue; - } else if (applypTdepPID && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 0))) { // kaon and pion + } else if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 0))) { // pion and kaon + continue; + } else if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 1) && selectionPIDptDepTOF(track2, 0))) { // pion and kaon continue; } rEventSelection.fill(HIST("recMCparticles"), 12.5); - /* if (selectionConfig.isApplyParticleMID) { - if (selectionMID(track1, 0)) // Kaon misidentified as pion + if (selectionConfig.isApplyParticleMID) { + if (selectionMID(track2, 1)) // Pion misidentified as kaon continue; - if (selectionMID(track1, 2)) // Kaon misidentified as proton + // if (selectionMID(track2, 2)) // Kaon misidentified as proton + // continue; + if (selectionMID(track1, 0)) // Kaon misidentified as pion continue; - if (selectionMID(track2, 1)) // Pion misidentified as kaon + // if (selectionMID(track1, 2)) // Pion misidentified as proton + // continue; + } + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(track1, 0)) // Kaon misidentified as pion continue; - if (selectionMID(track2, 2)) // Pion misidentified as proton + if (selectionMIDPtDep(track2, 1)) // Pion misidentified as kaon continue; - } */ - rEventSelection.fill(HIST("recMCparticles"), 13.5); + } if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) continue; @@ -2071,9 +2199,9 @@ struct Kstarqa { } rEventSelection.fill(HIST("recMCparticles"), 15.5); - // if (!selectionPair(track1, track2)) { - // continue; - // } + if (!selectionPair(track1, track2)) { + continue; + } rEventSelection.fill(HIST("recMCparticles"), 16.5); oldindex = mothertrack1.globalIndex(); @@ -2244,24 +2372,33 @@ struct Kstarqa { } rEventSelection.fill(HIST("recMCparticles"), 10.5); - if (!applypTdepPID && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { + if (!selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon continue; - } else if (applypTdepPID && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 0))) { + } else if (selectionConfig.isapplypTdepPID && !selectionConfig.isapplypTdepPIDTOF && !(selectionPIDPtDep(track1, 0) && selectionPIDPtDep(track2, 1))) { // pion and kaon + continue; + } else if (!selectionConfig.isapplypTdepPID && selectionConfig.isapplypTdepPIDTOF && !(selectionPIDptDepTOF(track1, 0) && selectionPIDptDepTOF(track2, 1))) { // pion and kaon continue; } rEventSelection.fill(HIST("recMCparticles"), 11.5); - /* if (selectionConfig.isApplyParticleMID) { - if (selectionMID(track1, 0)) // Kaon misidentified as pion + if (selectionConfig.isApplyParticleMID) { + if (selectionMID(track1, 1)) // Pion misidentified as kaon continue; - if (selectionMID(track1, 2)) // Kaon misidentified as proton + // if (selectionMID(track1, 2)) // Kaon misidentified as proton + // continue; + if (selectionMID(track2, 0)) // Kaon misidentified as pion continue; - if (selectionMID(track2, 1)) // Pion misidentified as kaon + // if (selectionMID(track2, 2)) // Pion misidentified as proton + // continue; + } + rEventSelection.fill(HIST("recMCparticles"), 12.5); + + if (selectionConfig.isApplyParticleMIDPtDep) { + if (selectionMIDPtDep(track1, 1)) // Pion misidentified as kaon continue; - if (selectionMID(track2, 2)) // Pion misidentified as proton + if (selectionMIDPtDep(track2, 0)) // Kaon misidentified as pion continue; - } */ - rEventSelection.fill(HIST("recMCparticles"), 12.5); + } if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) continue; @@ -2284,9 +2421,9 @@ struct Kstarqa { } rEventSelection.fill(HIST("recMCparticles"), 14.5); - // if (!selectionPair(track1, track2)) { - // continue; - // } + if (!selectionPair(track1, track2)) { + continue; + } rEventSelection.fill(HIST("recMCparticles"), 15.5); oldindex = mothertrack1.globalIndex(); @@ -2394,14 +2531,14 @@ struct Kstarqa { } // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with kaon - if (!applypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (!selectionConfig.isapplypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon continue; - if (!applypTdepPID && !selectionPID(track2, 1)) // Track 2 is checked with kaon + if (!selectionConfig.isapplypTdepPID && !selectionPID(track2, 1)) // Track 2 is checked with kaon continue; - if (applypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon + if (selectionConfig.isapplypTdepPID && !selectionPIDPtDep(track1, 1)) // Track 1 is checked with Kaon continue; - if (applypTdepPID && !selectionPIDPtDep(track2, 1)) // Track 2 is checked with kaon + if (selectionConfig.isapplypTdepPID && !selectionPIDPtDep(track2, 1)) // Track 2 is checked with kaon continue; rEventSelection.fill(HIST("tracksCheckData"), 2.5); @@ -2590,6 +2727,8 @@ struct Kstarqa { rEventSelection.fill(HIST("eventsCheckGen"), 2.5); for (const auto& collision : collisions) { + rEventSelection.fill(HIST("eventsCheckGen"), 3.5); + if (!selectionEvent(collision, false)) { // don't fill event cut histogram continue; } @@ -2623,13 +2762,13 @@ struct Kstarqa { const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); hInvMass.fill(HIST("hAllGenCollisions"), multiplicity); - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + if (!selectionConfig.AllGenEvents && !evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } double genMultiplicity = mcCollision.centFT0M(); hInvMass.fill(HIST("h1GenMult2"), genMultiplicity); hInvMass.fill(HIST("hAllGenCollisions1Rec"), multiplicity); - rEventSelection.fill(HIST("eventsCheckGen"), 3.5); + rEventSelection.fill(HIST("eventsCheckGen"), 4.5); for (const auto& mcParticle : mcParticles) { @@ -2682,6 +2821,114 @@ struct Kstarqa { } PROCESS_SWITCH(Kstarqa, processGenPhi, "Process Generated for Phi meson", false); + void processEvSigLossFactorsPhi(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, LabeledTracks const&, aod::McParticles const& mcParticles) + { + auto multiplicityNch = -1; + multiplicityNch = mcCollision.multMCNParticlesEta05(); + hInvMass.fill(HIST("CorrFactors/hGenEvents"), multiplicityNch, 0.5); + + if (selectionConfig.checkVzEvSigLoss && std::abs(mcCollision.posZ()) > selectionConfig.cutzvertex) + return; + + hInvMass.fill(HIST("CorrFactors/hGenEvents"), multiplicityNch, 1.5); + + if (selectionConfig.isINELgt0 && !mcCollision.isInelGt0()) { + return; + } + hInvMass.fill(HIST("CorrFactors/hGenEvents"), multiplicityNch, 2.5); + + float multiplicity = -1.0; + bool isSelectedEvent = false; + + for (auto const& collision : collisions) { + if (!collision.has_mcCollision()) + continue; + if (!selectionEvent(collision, false)) // don't fill event cut histogram + continue; + + if (cSelectMultEstimator == kFT0M) { + multiplicity = collision.centFT0M(); + } else if (cSelectMultEstimator == kFT0A) { + multiplicity = collision.centFT0A(); + } else if (cSelectMultEstimator == kFT0C) { + multiplicity = collision.centFT0C(); + } else if (cSelectMultEstimator == kFV0A) { + multiplicity = collision.centFV0A(); + } else { + multiplicity = collision.centFT0M(); // default + } + isSelectedEvent = true; + } + + // auto multiplicityGen = -1; + // multiplicityGen = mcCollision.centFT0M(); + + hInvMass.fill(HIST("CorrFactors/hMultiplicityVsMultMC"), multiplicity, multiplicityNch); + hInvMass.fill(HIST("CorrFactors/hNrecInGen"), collisions.size()); + hInvMass.fill(HIST("CorrFactors/MultiplicityGen"), multiplicityNch); + if (isSelectedEvent) { + hInvMass.fill(HIST("CorrFactors/MultiplicityRec"), multiplicityNch); + } + + for (const auto& mcParticle : mcParticles) { + + if (std::abs(mcParticle.y()) >= selectionConfig.rapidityMotherData) + continue; + + if (std::abs(mcParticle.pdgCode()) == o2::constants::physics::kPhi) { + + auto kDaughters = mcParticle.daughters_as(); + if (kDaughters.size() != selectionConfig.noOfDaughters) { + continue; + } + + bool hasPos = false; + bool hasNeg = false; + + auto passkaon = false; + auto passpion = false; + for (const auto& kCurrentDaughter : kDaughters) { + // if (!kCurrentDaughter.isPhysicalPrimary()) + // continue; + + int pdgDau = kCurrentDaughter.pdgCode(); + int sign = (pdgDau > 0) - (pdgDau < 0); + + if (sign > 0) + hasPos = true; + if (sign < 0) + hasNeg = true; + + if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { + passkaon = true; + daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { + passpion = true; + daughter2 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + } + } + + if ((passkaon && passpion) && (hasPos && hasNeg)) { + mother = daughter1 + daughter2; // Kstar meson + + hInvMass.fill(HIST("CorrFactors/h2dGenKstar"), multiplicity, mother.Pt()); + hInvMass.fill(HIST("CorrFactors/h3dGenKstarVsMultMCVsMultiplicity"), multiplicityNch, multiplicity, mother.Pt()); + hInvMass.fill(HIST("CorrFactors/hSignalLoss1"), mother.pt(), multiplicityNch); + if (isSelectedEvent) { + hInvMass.fill(HIST("CorrFactors/hSignalLoss2"), mother.pt(), multiplicityNch); + } + } + } + } + + if (collisions.size() == 0) + return; + + hInvMass.fill(HIST("CorrFactors/hGenEvents"), multiplicityNch, 3.5); + } + PROCESS_SWITCH(Kstarqa, processEvSigLossFactorsPhi, "Process Event and Signal loss", false); + void processRecPhi(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, EventMCGenerated const&) { @@ -2819,9 +3066,9 @@ struct Kstarqa { } rEventSelection.fill(HIST("recMCparticles"), 11.5); - if (!applypTdepPID && !(selectionPID(track1, 1) && selectionPID(track2, 1))) { // kaon and kaon + if (!selectionConfig.isapplypTdepPID && !(selectionPID(track1, 1) && selectionPID(track2, 1))) { // kaon and kaon continue; - } else if (applypTdepPID && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 1))) { // kaon and kaon + } else if (selectionConfig.isapplypTdepPID && !(selectionPIDPtDep(track1, 1) && selectionPIDPtDep(track2, 1))) { // kaon and kaon continue; } rEventSelection.fill(HIST("recMCparticles"), 12.5); @@ -2960,7 +3207,7 @@ struct Kstarqa { return; } - if (selectionConfig.checkVzEvSigLoss && (std::abs(mcCollision.posZ()) >= selectionConfig.cutzvertex)) { + if (selectionConfig.checkVzEvSigLoss && (std::abs(mcCollision.posZ()) > selectionConfig.cutzvertex)) { return; } diff --git a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx index 16c44ab832b..bd0964bbea5 100644 --- a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx @@ -17,9 +17,6 @@ #include "PWGLF/DataModel/LFResonanceTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" - #include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" @@ -29,9 +26,6 @@ #include #include -#include -#include - #include using namespace o2; @@ -44,19 +38,34 @@ struct lambdaAnalysis_pb { Preslice perRCol = aod::resodaughter::resoCollisionId; Preslice perCollision = aod::track::collisionId; // Configurables. - + aod::ResoMCParents const* mResoParents = nullptr; Configurable ConfEvtOccupancyInTimeRange{"ConfEvtOccupancyInTimeRange", false, "occupancy selection true or false"}; Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histogram"}; Configurable nBinsInvM{"nBinsInvM", 120, "N bins in InvMass histogram"}; Configurable lambda1520id{"lambda1520id", 3124, "pdg"}; Configurable doRotate{"doRotate", true, "rotated inv mass spectra"}; - // Tracks Configurable cPtMin{"cPtMin", 0.15, "Minimum Track pT"}; Configurable cPMin{"cPMin", 0., "Minimum Track p"}; Configurable cEtaCut{"cEtaCut", 0.8, "Pseudorapidity cut"}; Configurable cDcaz{"cDcazMin", 1., "Minimum DCAz"}; - Configurable cDcaxy{"cDcaxyMin", 0.1, "Minimum DCAxy"}; + Configurable cfgRapidityShift{"cfgRapidityShift", 0., " rapidity shift"}; + Configurable cfgRapidityCut{"cfgRapidityCut", 0.5, "Rapidity window"}; + // TPC crossed rows (absolute) + Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min TPC crossed rows"}; + Configurable cfgUseCrossedRows{"cfgUseCrossedRows", false, "apply crossed rows cut"}; + + Configurable cfgMinTPCcls{"cfgMinTPCcls", 70, "min TPC clusters found"}; + Configurable cfgUseTPCcls{"cfgUseTPCcls", false, "apply TPC clusters cut"}; + + Configurable> cDcaPtBinsPr{"cDcaPtBinsPr", {0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 1000.0f}, "Proton pT bin edges for DCAxy cut"}; + + Configurable> cDcaXYBinsPr{"cDcaXYBinsPr", {0.020f, 0.015f, 0.010f, 0.007f, 0.005f, 0.004f}, "Proton max |DCAxy| per pT bin (cm)"}; + + // Kaon DCAxy — pT binned + Configurable> cDcaPtBinsKa{"cDcaPtBinsKa", {0.0f, 0.3f, 0.6f, 1.0f, 2.0f, 1000.0f}, "Kaon pT bin edges for DCAxy cut"}; + + Configurable> cDcaXYBinsKa{"cDcaXYBinsKa", {0.025f, 0.018f, 0.012f, 0.008f, 0.004f}, "Kaon max |DCAxy| per pT bin (cm)"}; Configurable isonlyQC{"isonlyQC", false, "only QC"}; Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; @@ -102,11 +111,22 @@ struct lambdaAnalysis_pb { Configurable> kaonTOFPIDcut{"kaonTOFPIDcut", {3.0}, "TOF nsigma cuts kaons"}; // Event Mixing. Configurable cNumMixEv{"cNumMixEv", 20, "Number of Events to be mixed"}; + ConfigurableAxis cDCAzBins{"dcazbins", {VARIABLE_WIDTH, -1.2f, -1.0f, -0.9f, -0.8f, -0.7f, -0.6f, -0.5f, -0.4f, -0.3f, -0.2f, -0.1f, 0.f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f}, "DCA - z-vertex"}; ConfigurableAxis cMixVtxBins{"cMixVtxBins", {VARIABLE_WIDTH, -10.0f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f}, "Mixing bins - z-vertex"}; ConfigurableAxis cMixMultBins{"cMixMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 200.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis cMixEPAngle{"cMixEPAngle", {VARIABLE_WIDTH, -1.5708f, -1.25664f, -0.942478f, -0.628319f, 0.f, 0.628319f, 0.942478f, 1.25664f, 1.5708f}, "event plane"}; ConfigurableAxis occupancy_bins{"occupancy_bins", {VARIABLE_WIDTH, 0.0, 100, 500, 600, 1000, 1100, 1500, 1600, 2000, 2100, 2500, 2600, 3000, 3100, 3500, 3600, 4000, 4100, 4500, 4600, 5000, 5100, 9999}, "Binning of the occupancy axis"}; + Configurable cNofRotations{"cNofRotations", 10, "Number of rotations for rotational background"}; + Configurable rotationalcut{"rotationalcut", 6.f, "Rotational background angle window: PI/rotationalcut"}; + + // ── MC Event Selection Configurables ───────────────────────────────────── + Configurable cEvtMCAfterAllCuts{"cEvtMCAfterAllCuts", false, "MC event sel: isInAfterAllCuts"}; + Configurable cEvtMCINELgt0{"cEvtMCINELgt0", false, "MC event sel: isINELgt0"}; + Configurable cEvtMCSel8{"cEvtMCSel8", false, "MC event sel: isInSel8"}; + Configurable cEvtMCVtxIn10{"cEvtMCVtxIn10", false, "MC event sel: isVtxIn10"}; + Configurable cEvtMCTriggerTVX{"cEvtMCTriggerTVX", false, "MC event sel: isTriggerTVX"}; + Configurable cEvtMCRecINELgt0{"cEvtMCRecINELgt0", false, "MC event sel: isRecINELgt0"}; // Histogram Registry. HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -117,7 +137,7 @@ struct lambdaAnalysis_pb { const AxisSpec axisPt_pid(200, 0., 10., "p_{T} (GeV/c)"); const AxisSpec axisPt(nBinsPt, 0., 10., "p_{T} (GeV/c)"); const AxisSpec axisEta(40, -1, 1, "#eta"); - const AxisSpec axisDCAz(500, -0.5, 0.5, {"DCA_{z} (cm)"}); + // const AxisSpec axisDCAz(500, -0.5, 0.5, {"DCA_{z} (cm)"}); const AxisSpec axisDCAxy(240, -0.12, 0.12, {"DCA_{xy} (cm)"}); const AxisSpec axisTPCNCls(200, 0, 200, {"TPCNCls"}); const AxisSpec axisTPCNsigma(401, -10.025, 10.025, {"n#sigma^{TPC}"}); @@ -125,14 +145,20 @@ struct lambdaAnalysis_pb { 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})"}); + const AxisSpec axisInvM(nBinsInvM, 1.4, 2.0, {"M_{inv} (GeV/c^{2})"}); AxisSpec axisOccupancy = {occupancy_bins, "Occupancy [-40,100]"}; + AxisSpec axisDCAz = {cDCAzBins, "DCA_{z} (cm)"}; histos.add("Event/h1d_ft0_mult_percentile", "FT0 (%)", kTH2F, {axisCent, axisOccupancy}); + histos.add("Event/h_ft0_vz", "Collision Vertex Z position", kTH1F, {{100, -15., 15.}}); if (doprocessMix || doprocessMixDF || doprocessMixepDF) { histos.add("Event/mixing_vzVsmultpercentile", "FT0(%)", kTH3F, {axisCent, axisVz, axisEP}); } - // QA Before + // QA Beforei + histos.add("QAbefore/hEta_rec", "Reco dN/d#eta; #eta; dN/d#eta", kTH1F, {{50, -1.0, 1.0}}); + histos.add("QAbefore/hPt_rec", "Reco pT; p_{T} (GeV/c); Tracks", kTH1F, {axisP_pid}); + histos.add("QAbefore/hPhi_rec", "Reco #varphi; #varphi (rad); Tracks", kTH1F, {{72, 0, 6.2832}}); + histos.add("QAbefore/hEtaPhi_rec", "Reco #eta vs #varphi; #eta; #varphi", kTH2F, {axisEta, {72, 0, 6.2832}}); histos.add("QAbefore/Proton/h2d_pr_nsigma_tpc_p", "n#sigma^{TPC} Protons", kTH2F, {axisP_pid, axisTPCNsigma}); histos.add("QAbefore/Proton/h2d_pr_nsigma_tof_p", "n#sigma^{TOF} Protons", kTH2F, {axisP_pid, axisTOFNsigma}); histos.add("QAbefore/Proton/h2d_pr_nsigma_tof_vs_tpc", "n#sigma^{TPC} vs n#sigma^{TOF} Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); @@ -154,6 +180,8 @@ struct lambdaAnalysis_pb { histos.add("QAafter/Proton/h2d_Prpi_nsigma_tof_p", " Protons pion", kTH2F, {axisP_pid, axisTOFNsigma}); histos.add("QAafter/Proton/h2d_Prka_nsigma_tof_p", " Protons kaon", 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/Proton/hTPCNClsCrossedRowsVsPt", "TPC Crossed Rows vs pT;p_{T} (GeV/c);N_{cls,crossed};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); + histos.add("QAafter/Proton/hTPCNClsFoundVsPt", "TPC Found Clusters vs pT;p_{T} (GeV/c);N_{cls,found};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); histos.add("QAafter/Kaon/hd_ka_pt", "p_{T}-spectra Kaons", kTH2F, {axisPt_pid, axisCent}); 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}); @@ -167,7 +195,8 @@ struct lambdaAnalysis_pb { histos.add("QAafter/Kaon/h2d_Kapi_nsigma_tof_p", " Kaons pion", kTH2F, {axisP_pid, axisTOFNsigma}); histos.add("QAafter/Kaon/h2d_Kapr_nsigma_tof_p", " Kaons proton", kTH2F, {axisP_pid, axisTOFNsigma}); histos.add("QAafter/Kaon/h2d_ka_nsigma_tof_vs_tpc", "n#sigma(TOF) vs n#sigma(TPC) Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); - + histos.add("QAafter/Kaon/hTPCNClsCrossedRowsVsPt", "TPC Crossed Rows vs pT;p_{T} (GeV/c);N_{cls,crossed};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); + histos.add("QAafter/Kaon/hTPCNClsFoundVsPt", "TPC Found Clusters vs pT;p_{T} (GeV/c);N_{cls,found};Counts", kTH2F, {axisPt_pid, {200, 0, 200}}); // Analysis // Lambda Invariant Mass if (!doprocessMC) { @@ -175,7 +204,8 @@ struct lambdaAnalysis_pb { histos.add("Analysis/h4d_lstar_invm_US_MP", "THn #bar #Lambda(1520)", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); histos.add("Analysis/h4d_lstar_invm_PP", "THn Like Signs p K^{+}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); histos.add("Analysis/h4d_lstar_invm_MM", "THn Like Signs #bar{p} K^{-}", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); - histos.add("Analysis/h4d_lstar_invm_rot", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_rot_PM", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); + histos.add("Analysis/h4d_lstar_invm_rot_MP", "THn Rotated", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); histos.add("Analysis/h4d_lstar_invm_US_PM_mix", "THn Mixed Events", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); histos.add("Analysis/h4d_lstar_invm_US_MP_mix", "THn anti Mixed Events", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); histos.add("Analysis/h4d_lstar_invm_LS_PP_mix", "THn Mixed Events PP", kTHnSparseF, {axisInvM, axisPt, axisCent, axisOccupancy}); @@ -183,7 +213,7 @@ struct lambdaAnalysis_pb { } // MC if (doprocessMC) { - + histos.add("Event/hMCEventCutflow", "MC Event Cutflow", kTH1F, {{7, 0, 7}}); histos.add("QAChecks/h1d_pr_rec_pt", "Reconstructed p_{T}-spectra Protons", kTH1F, {axisPt_pid}); histos.add("QAChecks/h1d_ka_rec_pt", "Recondstucted p_{T}-spectra Kaons", kTH1F, {axisPt_pid}); histos.add("QAChecks/h1d_pr_gen_pt", "Generated p_{T}-spectra Protons", kTH1F, {axisPt_pid}); @@ -193,32 +223,78 @@ struct lambdaAnalysis_pb { histos.add("Analysis/h3d_gen_lstar_MP", "Generated #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); histos.add("Analysis/h3d_rec_lstar_PM", "Reconstructed #Lambda(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); histos.add("Analysis/h3d_rec_lstar_MP", "Reconstructed #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {axisInvM, axisPt, axisCent}); + histos.add("Analysis/h3d_reso_lstar_PM", "Resolution #Lambda(1520) p_{T}", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCent}); + histos.add("Analysis/h3d_reso_lstar_MP", "Resolution #bar{#Lambda}(1520) p_{T}", kTHnSparseF, {{200, -0.05, 0.05}, axisPt, axisCent}); } } template bool selTracks(T const& track) { - if (track.pt() < cPtMin) return false; if (std::abs(track.eta()) > cEtaCut) return false; - if (std::abs(track.dcaZ()) > cDcaz) + if (cPrimaryTrack && !track.isPrimaryTrack()) return false; - if (std::abs(track.dcaXY()) > cDcaxy) + if (cGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cPrimaryTrack && !track.isPrimaryTrack()) + if (cPVContributor && !track.isPVContributor()) return false; - if (cGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (cfgUseCrossedRows && track.tpcNClsCrossedRows() < cfgMinCrossedRows) return false; - if (cPVContributor && !track.isPVContributor()) + if (cfgUseTPCcls && track.tpcNClsFound() < cfgMinTPCcls) + return false; + + return true; + } + + template + bool dcaSelectionProton(T const& track, float p) + { + auto ptBinsPr = static_cast>(cDcaPtBinsPr); + auto dcaXYPr = static_cast>(cDcaXYBinsPr); + int nBinsPr = static_cast(ptBinsPr.size()) - 1; + + bool dcaXYPassed = false; + for (int i = 0; i < nBinsPr; i++) { + if (p >= ptBinsPr[i] && p < ptBinsPr[i + 1] && + std::abs(track.dcaXY()) < dcaXYPr[i]) + dcaXYPassed = true; + } + if (!dcaXYPassed) + return false; + + if (std::abs(track.dcaZ()) > cDcaz) + return false; + + return true; + } + + // ── Kaon DCA Selection ──────────────────────────────────────────────────── + template + bool dcaSelectionKaon(T const& track, float p) + { + auto ptBinsKa = static_cast>(cDcaPtBinsKa); + auto dcaXYKa = static_cast>(cDcaXYBinsKa); + int nBinsKa = static_cast(ptBinsKa.size()) - 1; + + bool dcaXYPassed = false; + for (int i = 0; i < nBinsKa; i++) { + if (p >= ptBinsKa[i] && p < ptBinsKa[i + 1] && + std::abs(track.dcaXY()) < dcaXYKa[i]) + dcaXYPassed = true; + } + if (!dcaXYPassed) + return false; + + if (std::abs(track.dcaZ()) > cDcaz) return false; return true; @@ -285,6 +361,7 @@ struct lambdaAnalysis_pb { } } if (tpcPIDPassed && tofPIDPassed) { + return true; } return false; @@ -351,6 +428,7 @@ struct lambdaAnalysis_pb { } } if (tpcPIDPassed && tofPIDPassed) { + return true; } return false; @@ -360,19 +438,16 @@ struct lambdaAnalysis_pb { void fillDataHistos(trackType const& trk1, trackType const& trk2, float mult, int occup = 100) { - TLorentzVector p1, p2, p; - TRandom* rn = new TRandom(); float p_ptot = 0., k_ptot = 0.; for (auto const& [trkPr, trkKa] : soa::combinations(soa::CombinationsFullIndexPolicy(trk1, trk2))) { - // Do not analyse same index tracks. - if (trkPr.index() == trkKa.index() && !mix) + if (trkPr.index() == trkKa.index()) // && !mix) continue; - // pT, DCA, Global Tracks and PVcontrib selection. if (!selTracks(trkPr) || !selTracks(trkKa)) continue; + // LOGF(info, "eork 4 %d, %d %d ",trkPr.index(),trk1.size(),trkPr.size()); auto _pxPr = trkPr.px(); auto _pyPr = trkPr.py(); @@ -387,7 +462,6 @@ struct lambdaAnalysis_pb { // Fill QA before track selection. if (!mix) { auto _tpcnsigmaPr = trkPr.tpcNSigmaPr(); - histos.fill(HIST("QAbefore/Proton/h2d_pr_nsigma_tpc_p"), p_ptot, _tpcnsigmaPr); if (trkPr.hasTOF()) { auto _tofnsigmaPr = trkPr.tofNSigmaPr(); @@ -410,6 +484,9 @@ struct lambdaAnalysis_pb { continue; if (!selectionPIDProton(trkPr, p_ptot) || !selectionPIDKaon(trkKa, k_ptot)) continue; + if (!dcaSelectionProton(trkPr, p_ptot) || !dcaSelectionKaon(trkKa, k_ptot)) + continue; + if (isDeepAngle && TMath::ACos((trkPr.pt() * trkKa.pt() + _pzPr * _pzKa) / (p_ptot * k_ptot)) < cfgDeepAngle) continue; @@ -427,6 +504,9 @@ struct lambdaAnalysis_pb { histos.fill(HIST("QAafter/Proton/h2d_Prka_nsigma_tpc_p"), p_ptot, trkPr.tpcNSigmaKa()); histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_p"), p_ptot, _tpcnsigmaPr); histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tpc_pt"), _ptPr, _tpcnsigmaPr); + histos.fill(HIST("QAafter/Proton/hTPCNClsCrossedRowsVsPt"), _ptPr, trkPr.tpcNClsCrossedRows()); + histos.fill(HIST("QAafter/Proton/hTPCNClsFoundVsPt"), _ptPr, trkPr.tpcNClsFound()); + if (!cUseTpcOnly && trkPr.hasTOF()) { auto _tofnsigmaPr = trkPr.tofNSigmaPr(); histos.fill(HIST("QAafter/Proton/h2d_pr_nsigma_tof_p"), p_ptot, _tofnsigmaPr); @@ -447,6 +527,9 @@ struct lambdaAnalysis_pb { histos.fill(HIST("QAafter/Kaon/h2d_Kapr_nsigma_tpc_p"), k_ptot, trkKa.tpcNSigmaPr()); histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_p"), k_ptot, _tpcnsigmaKa); histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tpc_pt"), _ptKa, _tpcnsigmaKa); + histos.fill(HIST("QAafter/Kaon/hTPCNClsCrossedRowsVsPt"), _ptKa, trkKa.tpcNClsCrossedRows()); + histos.fill(HIST("QAafter/Kaon/hTPCNClsFoundVsPt"), _ptKa, trkKa.tpcNClsFound()); + if (!cUseTpcOnly && trkKa.hasTOF()) { auto _tofnsigmaKa = trkKa.tofNSigmaKa(); histos.fill(HIST("QAafter/Kaon/h2d_ka_nsigma_tof_p"), k_ptot, _tofnsigmaKa); @@ -459,39 +542,73 @@ struct lambdaAnalysis_pb { if (isonlyQC) continue; - // Invariant mass reconstruction. - p1.SetXYZM(_pxPr, _pyPr, _pzPr, MassProton); - p2.SetXYZM(_pxKa, _pyKa, _pzKa, MassKaonCharged); - p = p1 + p2; - if (std::abs(p.Rapidity()) > 0.5) - continue; + std::array pvec0 = {_pxPr, _pyPr, _pzPr}; + std::array pvec1 = {_pxKa, _pyKa, _pzKa}; + std::array, 2> arrMomrec = {pvec0, pvec1}; + + float _M = RecoDecay::m(arrMomrec, std::array{MassProton, MassKaonCharged}); + float _pt = RecoDecay::pt(std::array{_pxPr + _pxKa, _pyPr + _pyKa}); - auto _M = p.M(); - auto _pt = p.Pt(); + float _y = std::abs(RecoDecay::y(std::array{_pxPr + _pxKa, _pyPr + _pyKa, _pzPr + _pzKa}, _M)); + float _yshift = _y - cfgRapidityShift; + + if (std::abs(_yshift) > cfgRapidityCut) + continue; // Apply kinematic cuts. - if (cKinCuts) { - TVector3 v1(_pxPr, _pyPr, _pzPr); - TVector3 v2(_pxKa, _pyKa, _pzKa); - float alpha = v1.Angle(v2); - if (alpha > 1.4 && alpha < 2.4) - continue; - } // Fill Invariant Mass Histograms. if constexpr (!mix && !mc) { if (trkPr.sign() * trkKa.sign() < 0) { + if (trkPr.sign() > 0) histos.fill(HIST("Analysis/h4d_lstar_invm_US_PM"), _M, _pt, mult, occup); else histos.fill(HIST("Analysis/h4d_lstar_invm_US_MP"), _M, _pt, mult, occup); + if (doRotate) { - float theta = rn->Uniform(1.56, 1.58); - p1.RotateZ(theta); - p = p1 + p2; - if (std::abs(p.Rapidity()) < 0.5) { - histos.fill(HIST("Analysis/h4d_lstar_invm_rot"), p.M(), p.Pt(), mult, occup); + for (int i = 0; i < cNofRotations; i++) { + + float delta = o2::constants::math::PI / rotationalcut; + float theta2; + if (cNofRotations == 1) { + // Single rotation — just rotate by exactly PI + theta2 = o2::constants::math::PI; + } else { + theta2 = (o2::constants::math::PI - delta) + + i * (2.f * delta / (cNofRotations - 1)); + } + + float phiRot = trkKa.phi() + theta2; + if (phiRot > o2::constants::math::TwoPI) + phiRot -= o2::constants::math::TwoPI; + if (phiRot < 0.f) + phiRot += o2::constants::math::TwoPI; + + float _pxKaRot = trkKa.pt() * std::cos(phiRot); + float _pyKaRot = trkKa.pt() * std::sin(phiRot); + + std::array pvec0rot = {_pxPr, _pyPr, _pzPr}; + std::array pvec1rot = {_pxKaRot, _pyKaRot, _pzKa}; + std::array, 2> arrMomRot = {pvec0rot, pvec1rot}; + + float _Mrot = RecoDecay::m(arrMomRot, std::array{MassProton, MassKaonCharged}); + float _ptRot = RecoDecay::pt(std::array{_pxPr + _pxKaRot, _pyPr + _pyKaRot}); + + float _yrot = std::abs(RecoDecay::y(std::array{_pxPr + _pxKaRot, _pyPr + _pyKaRot, _pzPr + _pzKa}, MassLambda1520)); + + float _yshiftrot = _yrot - cfgRapidityShift; + + if (std::abs(_yshiftrot) > cfgRapidityCut) + continue; + + if (trkPr.sign() * trkKa.sign() < 0) { + if (trkPr.sign() > 0) + histos.fill(HIST("Analysis/h4d_lstar_invm_rot_PM"), _Mrot, _ptRot, mult, occup); + else + histos.fill(HIST("Analysis/h4d_lstar_invm_rot_MP"), _Mrot, _ptRot, mult, occup); + } } } } else { @@ -516,7 +633,6 @@ struct lambdaAnalysis_pb { histos.fill(HIST("Analysis/h4d_lstar_invm_LS_MM_mix"), _M, _pt, mult, occup); } } - if constexpr (mc) { if (trkPr.sign() * trkKa.sign() < 0) { if (std::abs(trkPr.pdgCode()) != 2212 || std::abs(trkKa.pdgCode()) != 321) @@ -524,15 +640,34 @@ struct lambdaAnalysis_pb { if (trkPr.motherId() != trkKa.motherId()) continue; + if (trkPr.motherPDG() != trkKa.motherPDG()) + continue; + + if (trkPr.pdgCode() == 0 || trkKa.pdgCode() == 0) + continue; + + if (trkPr.motherPDG() == -1 || trkKa.motherPDG() == -1) + continue; if (std::abs(trkPr.motherPDG()) != lambda1520id) // L* pdg_code = 3124 continue; - // MC histograms + float massParent = 0.; + for (auto const& _part : *mResoParents) { + if (_part.mcParticleId() == trkPr.motherId()) { + std::array pvecParent = {_part.px(), _part.py(), _part.pz()}; + massParent = RecoDecay::m(pvecParent, _part.e()); + break; + } + } + + float _MRes = _M - massParent; if (trkPr.motherPDG() > 0) { histos.fill(HIST("Analysis/h3d_rec_lstar_PM"), _M, _pt, mult); + histos.fill(HIST("Analysis/h3d_reso_lstar_PM"), _MRes, _pt, mult); } else { histos.fill(HIST("Analysis/h3d_rec_lstar_MP"), _M, _pt, mult); + histos.fill(HIST("Analysis/h3d_reso_lstar_MP"), _MRes, _pt, mult); } } } @@ -540,56 +675,92 @@ struct lambdaAnalysis_pb { } using resoCols = soa::Join; + using resoMCCols = soa::Join; + using resoTracks = aod::ResoTracks; void processData(resoCols::iterator const& collision, resoTracks const& tracks) { - // LOGF(info, " collisions: Index = %d %d", collision.globalIndex(),tracks.size()); histos.fill(HIST("Event/h1d_ft0_mult_percentile"), collision.cent(), 100); + histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); + fillDataHistos(tracks, tracks, collision.cent()); } PROCESS_SWITCH(lambdaAnalysis_pb, processData, "Process for Same Event Data", true); - void processMC(resoCols::iterator const& collision, + void processMC(resoMCCols::iterator const& collision, soa::Join const& tracks, aod::ResoMCParents const& resoParents) { + histos.fill(HIST("Event/hMCEventCutflow"), 0); // All collisions + + if (cEvtMCTriggerTVX && !collision.isTriggerTVX()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 1); // After TriggerTVX + + if (cEvtMCVtxIn10 && !collision.isVtxIn10()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 2); // After VtxIn10 + + if (cEvtMCINELgt0 && !collision.isINELgt0()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 3); // After INELgt0 + + if (cEvtMCSel8 && !collision.isInSel8()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 4); // After Sel8 + + if (cEvtMCRecINELgt0 && !collision.isRecINELgt0()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 5); // After RecINELgt0 + + if (cEvtMCAfterAllCuts && !collision.isInAfterAllCuts()) + return; + histos.fill(HIST("Event/hMCEventCutflow"), 6); // After AfterAllCuts auto mult = collision.cent(); auto mult = collision.cent(); histos.fill(HIST("Event/h1d_ft0_mult_percentile"), mult, 100); + histos.fill(HIST("Event/h_ft0_vz"), collision.posZ()); + mResoParents = &resoParents; fillDataHistos(tracks, tracks, mult); // get MC pT-spectra for (auto const& track : tracks) { + histos.fill(HIST("QAbefore/hEta_rec"), track.eta()); + histos.fill(HIST("QAbefore/hPt_rec"), track.pt()); + histos.fill(HIST("QAbefore/hPhi_rec"), track.phi()); + histos.fill(HIST("QAbefore/hEtaPhi_rec"), track.eta(), track.phi()); // get the generated level pT spectra of protons and kaons if (std::abs(track.pdgCode()) == 321) histos.fill(HIST("QAChecks/h1d_ka_gen_pt"), track.pt()); - if (std::abs(track.pdgCode()) == 2212) histos.fill(HIST("QAChecks/h1d_pr_gen_pt"), track.pt()); - // get the reconstructed level pT spectra of protons and kaons if (!selTracks(track)) continue; float p = TMath::Sqrt(track.px() * track.px() + track.py() * track.py() + track.pz() * track.pz()); - if (selectionPIDKaon(track, p) && std::abs(track.pdgCode()) == 321) { - histos.fill(HIST("QAChecks/h1d_ka_rec_pt"), track.pt()); + if (selectionPIDKaon(track, p)) { + if (std::abs(track.pdgCode()) == 321) { + histos.fill(HIST("QAChecks/h1d_ka_rec_pt"), track.pt()); + } } - if (selectionPIDProton(track, p) && std::abs(track.pdgCode()) == 2212) { - histos.fill(HIST("QAChecks/h1d_pr_rec_pt"), track.pt()); + if (selectionPIDProton(track, p)) { + if (std::abs(track.pdgCode()) == 2212) { + histos.fill(HIST("QAChecks/h1d_pr_rec_pt"), track.pt()); + } } } for (auto const& part : resoParents) { - if (abs(part.pdgCode()) != lambda1520id) // // L* pdg_code = 3124 - continue; - if (abs(part.y()) > 0.5) { // rapidity cut + if (std::abs(part.pdgCode()) != lambda1520id) // // L* pdg_code = 3124 continue; - } + // if (std::abs(part.y()) > 0.5) { // rapidity cut + // continue; + // } bool pass1 = false; bool pass2 = false; @@ -603,10 +774,8 @@ struct lambdaAnalysis_pb { if (!pass1 || !pass2) // If we have both decay products continue; - - TLorentzVector p4; - p4.SetPxPyPzE(part.px(), part.py(), part.pz(), part.e()); - auto mass = p4.M(); + std::array pvec = {part.px(), part.py(), part.pz()}; + float mass = RecoDecay::m(pvec, part.e()); if (part.pdgCode() > 0) histos.fill(HIST("Analysis/h3d_gen_lstar_PM"), mass, part.pt(), mult); else @@ -619,7 +788,6 @@ struct lambdaAnalysis_pb { void processMix(resoCols& collisions, resoTracks const& tracks) { - LOGF(debug, "Event Mixing Started"); BinningType2 binningPositions2{{cMixVtxBins, cMixMultBins}, true}; @@ -633,7 +801,7 @@ struct lambdaAnalysis_pb { } } - PROCESS_SWITCH(lambdaAnalysis_pb, processMix, "Process for Mixed Events", false); + PROCESS_SWITCH(lambdaAnalysis_pb, processMix, "Process for Mixed Events", true); Preslice perRColdf = aod::resodaughter::resoCollisionDFId; diff --git a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx index 3d3aac5b773..6c6d0a66b25 100644 --- a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx @@ -14,6 +14,7 @@ /// \author Hirak Kumar Koley #include "PWGLF/Utils/collisionCuts.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" @@ -92,15 +93,15 @@ struct Lambda1520analysisinpp { Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.0f, "Evt sel: Max. z-Vertex (cm)"}; Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; - Configurable cfgEvtTriggerCheck{"cfgEvtTriggerCheck", false, "Evt sel: check for trigger"}; - Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", true, "Evt sel: check for offline selection"}; - Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", false, "Evt sel: triggerTVX selection (MB)"}; - Configurable cfgEvtTFBorderCut{"cfgEvtTFBorderCut", false, "Evt sel: apply TF border cut"}; - Configurable cfgEvtUseITSTPCvertex{"cfgEvtUseITSTPCvertex", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; - Configurable cfgEvtZvertexTimedifference{"cfgEvtZvertexTimedifference", false, "Evt sel: apply Z-vertex time difference"}; - Configurable cfgEvtPileupRejection{"cfgEvtPileupRejection", false, "Evt sel: apply pileup rejection"}; - Configurable cfgEvtNoITSROBorderCut{"cfgEvtNoITSROBorderCut", false, "Evt sel: apply NoITSRO border cut"}; - Configurable cfgEvtCollInTimeRangeStandard{"cfgEvtCollInTimeRangeStandard", false, "Evt sel: apply NoCollInTimeRangeStandard"}; + Configurable cfgEvtSel8{"cfgEvtSel8", false, "Evt Sel 8 check for offline selection"}; + Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", true, "Evt sel: triggerTVX selection (MB)"}; + Configurable cfgEvtNoTFBorderCut{"cfgEvtNoTFBorderCut", true, "Evt sel: apply TF border cut"}; + Configurable cfgEvtIsVertexITSTPC{"cfgEvtIsVertexITSTPC", false, "Evt sel: use at lease on ITS-TPC track for vertexing"}; + Configurable cfgEvtIsGoodZvtxFT0vsPV{"cfgEvtIsGoodZvtxFT0vsPV", true, "Evt sel: apply Z-vertex time difference"}; + Configurable cfgEvtNoSameBunchPileup{"cfgEvtNoSameBunchPileup", false, "Evt sel: apply pileup rejection"}; + Configurable cfgEvtNoITSROFrameBorderCut{"cfgEvtNoITSROFrameBorderCut", false, "Evt sel: apply NoITSRO border cut"}; + Configurable cfgEvtNoCollInTimeRangeStandard{"cfgEvtNoCollInTimeRangeStandard", false, "Evt sel: apply NoNoCollInTimeRangeStandard"}; + Configurable cfgEvtIsVertexTOFmatched{"cfgEvtIsVertexTOFmatched", true, "kIsVertexTOFmatched: apply vertex TOF matched"}; } configEvents; struct : ConfigurableGroup { @@ -157,7 +158,7 @@ struct Lambda1520analysisinpp { /// Event Mixing Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}, "Mixing bins - z-vertex"}; - ConfigurableAxis cfgMultBins{"cfgMultBins", {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, 110.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis cfgMultPercentileBins{"cfgMultPercentileBins", {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, 110.0f}, "Mixing bins - multiplicity"}; // Rotational background Configurable rotationalcut{"rotationalcut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; @@ -174,7 +175,6 @@ struct Lambda1520analysisinpp { Configurable cfgUseDaughterEtaCutMC{"cfgUseDaughterEtaCutMC", false, "Switch to turn on/off eta cuts for daughters in MC"}; // MC selection cut - Configurable cZvertCutMC{"cZvertCutMC", 10.0f, "MC Z-vertex cut"}; Configurable cEtacutMC{"cEtacutMC", 0.5f, "MC eta cut"}; Configurable cUseRapcutMC{"cUseRapcutMC", true, "MC eta cut"}; Configurable cUseEtacutMC{"cUseEtacutMC", true, "MC eta cut"}; @@ -218,7 +218,7 @@ struct Lambda1520analysisinpp { // Filter primarytrackFilter = requirePVContributor() && requirePrimaryTrack() && requireGlobalTrackWoDCA(); using EventCandidates = soa::Join; - using TrackCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; using MCEventCandidates = soa::Join; using MCTrackCandidates = soa::Filtered>; @@ -237,16 +237,17 @@ struct Lambda1520analysisinpp { void init(framework::InitContext&) { - colCuts.setCuts(configEvents.cfgEvtZvtx, configEvents.cfgEvtTriggerCheck, configEvents.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, configEvents.cfgEvtOccupancyInTimeRangeMax, configEvents.cfgEvtOccupancyInTimeRangeMin); + colCuts.setCuts(configEvents.cfgEvtZvtx, /* configEvents.cfgEvtTriggerCheck */ false, configEvents.cfgEvtSel8, /*checkRun3*/ true, /*triggerTVXsel*/ false, configEvents.cfgEvtOccupancyInTimeRangeMax, configEvents.cfgEvtOccupancyInTimeRangeMin); colCuts.init(&histos); colCuts.setTriggerTVX(configEvents.cfgEvtTriggerTVXSel); - colCuts.setApplyTFBorderCut(configEvents.cfgEvtTFBorderCut); - colCuts.setApplyITSTPCvertex(configEvents.cfgEvtUseITSTPCvertex); - colCuts.setApplyZvertexTimedifference(configEvents.cfgEvtZvertexTimedifference); - colCuts.setApplyPileupRejection(configEvents.cfgEvtPileupRejection); - colCuts.setApplyNoITSROBorderCut(configEvents.cfgEvtNoITSROBorderCut); - colCuts.setApplyCollInTimeRangeStandard(configEvents.cfgEvtCollInTimeRangeStandard); + colCuts.setApplyTFBorderCut(configEvents.cfgEvtNoTFBorderCut); + colCuts.setApplyITSTPCvertex(configEvents.cfgEvtIsVertexITSTPC); + colCuts.setApplyZvertexTimedifference(configEvents.cfgEvtIsGoodZvtxFT0vsPV); + colCuts.setApplyPileupRejection(configEvents.cfgEvtNoSameBunchPileup); + colCuts.setApplyNoITSROBorderCut(configEvents.cfgEvtNoITSROFrameBorderCut); + colCuts.setApplyCollInTimeRangeStandard(configEvents.cfgEvtNoCollInTimeRangeStandard); + colCuts.setApplyVertexTOFmatched(configEvents.cfgEvtIsVertexTOFmatched); colCuts.printCuts(); // axes @@ -255,26 +256,27 @@ struct Lambda1520analysisinpp { AxisSpec axisEta{binsEta, "#eta"}; AxisSpec axisRap{binsEta, "#it{y}"}; AxisSpec axisMassLambda1520{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; - AxisSpec axisMult{binsMult, "mult_{V0M}"}; + AxisSpec axisMult{binsMult, "mult_{FT0M}"}; AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; AxisSpec axisPIDQA{binsnSigma, "#sigma"}; AxisSpec axisTPCSignal{binsnTPCSignal, ""}; - AxisSpec axisMClabel{6, -1.5f, 5.5f, "MC Label"}; + AxisSpec axisMClabel{9, -1.f, 8.f, "MC Label"}; AxisSpec axisEtaPhi{binsEtaPhi, ""}; AxisSpec axisPhi{350, 0, 7, "#Phi"}; - AxisSpec axisMultMix{configBkg.cfgMultBins, "Multiplicity"}; + AxisSpec axisMultMix{configBkg.cfgMultPercentileBins, "Multiplicity Percentile"}; AxisSpec axisVtxMix{configBkg.cfgVtxBins, "Vertex Z (cm)"}; AxisSpec idxMCAxis = {26, -0.5f, 25.5f, "Index"}; if (cFilladditionalQAeventPlots) { // event histograms if (doprocessData) { + histos.add("QAevent/hEvents", "INEL>0 Events", HistType::kTH1F, {{2, 0.5f, 2.5f}}); histos.add("QAevent/hPairsCounterSameE", "total valid no. of pairs sameE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); histos.add("QAevent/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0, 1000.0}}); } - // Test on Mixed event + // Gen on Mixed event if (doprocessME) { // Histograms for Mixed Event Pool characteristics @@ -287,6 +289,9 @@ struct Lambda1520analysisinpp { histos.add("QAevent/hMultiplicityPercentMixedE", "Multiplicity percentile of collision", HistType::kTH1F, {{120, 0.0f, 120.0f}}); histos.add("QAevent/hnTrksMixedE", "n tracks per event MixedE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); } + if (doprocessMCRec) { + histos.add("QAevent/hEventsMC", "INEL>0 Events MC", HistType::kTH1F, {{2, 0.5f, 2.5f}}); + } } if (doprocessData) { @@ -395,7 +400,8 @@ struct Lambda1520analysisinpp { // MC QA histos.add("Event/hMCEventIndices", "hMCEventIndices", kTH2D, {axisMult, idxMCAxis}); - if (doprocessMCTrue) { + if (doprocessMCGen) { + histos.add("QA/Gen", "Gen histogram", kTH1D, {{10, 0, 10, "index"}}); histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("QA/MC/h2GenEtaPt_afterEtaRapCut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); @@ -406,7 +412,7 @@ struct Lambda1520analysisinpp { histos.add("Result/MC/Genlambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTH3F, {axisMClabel, axisPt, axisMult}); histos.add("Result/MC/Genantilambda1520pt", "pT distribution of True MC Anti-#Lambda(1520)0", kTH3F, {axisMClabel, axisPt, axisMult}); } - if (doprocessMC) { + if (doprocessMCRec) { histos.add("QA/MC/h2RecoEtaPt_after", " #eta-#it{p}_{T} distribution of Reconstructed #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); @@ -422,6 +428,11 @@ struct Lambda1520analysisinpp { histos.add("Result/MC/h3lambda1520Recoinvmass", "Invariant mass of Reconstructed MC #Lambda(1520)0", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); histos.add("Result/MC/h3antilambda1520Recoinvmass", "Invariant mass of Reconstructed MC Anti-#Lambda(1520)0", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); } + if (doprocessdummy) { + histos.add("Result/dummy/Genprotonpt", "pT distribution of #Lambda(1520) from Proton", kTH3F, {axisMClabel, axisPt, axisMult}); + histos.add("Result/dummy/Genlambdapt", "pT distribution of #Lambda(1520) from #Lambda", kTH3F, {axisMClabel, axisPt, axisMult}); + histos.add("Result/dummy/Genxipt", "pT distribution of #Lambda(1520) from #Xi^{-}", kTH3F, {axisMClabel, axisPt, axisMult}); + } // Print output histograms statistics LOG(info) << "Size of the histograms in Lambda1520analysisinpp:"; @@ -453,26 +464,6 @@ struct Lambda1520analysisinpp { return returnValue; } - auto static constexpr TripleCharge = 3.0f; - - // Check if the collision is INEL>0 - template - bool isTrueINEL0(MCColl const& /*mccoll*/, MCPart const& mcparts) - { - for (auto const& mcparticle : mcparts) { - if (!mcparticle.isPhysicalPrimary()) - continue; - auto p = pdg->GetParticle(mcparticle.pdgCode()); - if (p != nullptr) { - if (std::abs(p->Charge()) >= TripleCharge) { // check if the particle is charged - if (std::abs(mcparticle.eta()) < 1.0f) - return true; - } - } - } - return false; - } - template bool trackCut(const TrackType track) { @@ -1039,6 +1030,17 @@ struct Lambda1520analysisinpp { if (!colCuts.isSelected(collision)) // Default event selection return; + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEvents"), 1); + } + + if (!collision.isInelGt0()) // <-- + return; + + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEvents"), 2); + } + colCuts.fillQA(collision); fillHistograms(collision, tracks, tracks); @@ -1050,32 +1052,51 @@ struct Lambda1520analysisinpp { if (!colCuts.isSelected(collision, false)) // Default event selection return; + if (!collision.isInelGt0()) // <-- + return; + fillHistograms(collision, tracks, tracks); } PROCESS_SWITCH(Lambda1520analysisinpp, processRotational, "Process Rotational Background", false); - void processMC(MCEventCandidates::iterator const& collision, - aod::McCollisions const&, - MCTrackCandidates const& tracks, aod::McParticles const&) + void processMCRec(MCEventCandidates::iterator const& collision, + aod::McCollisions const&, + MCTrackCandidates const& tracks, aod::McParticles const&) { - colCuts.fillQA(collision); + if (!colCuts.isSelected(collision)) + return; + + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEventsMC"), 1); + } - if (std::abs(collision.posZ()) > cZvertCutMC) // Z-vertex cut + if (!collision.isInelGt0()) // <-- return; + if (cFilladditionalQAeventPlots) { + histos.fill(HIST("QAevent/hEventsMC"), 2); + } + + colCuts.fillQA(collision); + fillHistograms(collision, tracks, tracks); } - PROCESS_SWITCH(Lambda1520analysisinpp, processMC, "Process Event for MC Light without partition", false); + PROCESS_SWITCH(Lambda1520analysisinpp, processMCRec, "Process Event for MC Rec without partition", false); Partition selectedMCParticles = (nabs(aod::mcparticle::pdgCode) == static_cast(Pdg::kLambda1520_Py)); // Lambda(1520) - void processMCTrue(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) + void processMCGen(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { - bool isInAfterAllCuts = colCuts.isSelected(collision); + bool isInAfterAllCuts = colCuts.isSelected(collision, false); bool inVtx10 = (std::abs(collision.mcCollision().posZ()) > configEvents.cfgEvtZvtx) ? false : true; bool isTriggerTVX = collision.selection_bit(aod::evsel::kIsTriggerTVX); bool isSel8 = collision.sel8(); - bool isTrueINELgt0 = isTrueINEL0(collision, mcParticles); + + auto mcPartsAll = mcParticles.sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + + bool isTrueINELgt0 = pwglf::isINELgt0mc(mcPartsAll, pdg); + // bool isTrueINELgt0 = collision.isInelGt0(); + auto centrality = centEst(collision); auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); @@ -1123,21 +1144,23 @@ struct Lambda1520analysisinpp { histos.fill(HIST("QA/MC/h2GenEtaPt_afterEtaRapCut"), part.eta(), part.pt()); histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterEtaRapCut"), part.phi(), part.y()); - // without any event selection - if (part.pdgCode() > 0) + histos.fill(HIST("QA/Gen"), 1); + if (part.pdgCode() > 0) // without any event selection histos.fill(HIST("Result/MC/Genlambda1520pt"), 0, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 0, part.pt(), centrality); - if (inVtx10) // INEL10 + if (inVtx10) // vtx10 { + histos.fill(HIST("QA/Gen"), 2); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 1, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 1, part.pt(), centrality); } - if (inVtx10 && isSel8) // INEL>10, vtx10 + if (inVtx10 && isSel8) // vtx10, sel8 { + histos.fill(HIST("QA/Gen"), 3); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 2, part.pt(), centrality); else @@ -1145,18 +1168,36 @@ struct Lambda1520analysisinpp { } if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX { + histos.fill(HIST("QA/Gen"), 4); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 3, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 3, part.pt(), centrality); } - if (isInAfterAllCuts) // after all event selection + if (inVtx10 && isTrueINELgt0) // vtx10, INEL>0 { + histos.fill(HIST("QA/Gen"), 5); if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 4, part.pt(), centrality); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 4, part.pt(), centrality); } + if (isInAfterAllCuts) // after all event selection + { + histos.fill(HIST("QA/Gen"), 6); + if (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), 5, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 5, part.pt(), centrality); + } + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + { + histos.fill(HIST("QA/Gen"), 7); + if (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), 6, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 6, part.pt(), centrality); + } } // QA for Trigger efficiency @@ -1198,7 +1239,7 @@ struct Lambda1520analysisinpp { if (isInAfterAllCuts && isTrueINELgt0 && inVtx10) histos.fill(HIST("Event/hMCEventIndices"), centrality, AllCutsINELg010); } - PROCESS_SWITCH(Lambda1520analysisinpp, processMCTrue, "Process Event for MC only", false); + PROCESS_SWITCH(Lambda1520analysisinpp, processMCGen, "Process Event for MC only", false); // Processing Event Mixing using BinningTypeVtxZT0M = ColumnBinningPolicy; @@ -1208,7 +1249,7 @@ struct Lambda1520analysisinpp { { auto tracksTuple = std::make_tuple(tracks); - BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultBins}, true}; + BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultPercentileBins}, true}; SameKindPair pairs{colBinning, configBkg.nEvtMixing, -1, collision, tracksTuple, &cache}; // -1 is the number of the bin to skip for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { @@ -1218,6 +1259,18 @@ struct Lambda1520analysisinpp { // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d)", t1.index(), t2.index(), collision1.index(), collision2.index()); // } + if (!colCuts.isSelected(collision1, false)) // Default event selection + continue; + + if (!colCuts.isSelected(collision2, false)) // Default event selection + continue; + + if (!collision1.isInelGt0()) // <-- + continue; + + if (!collision2.isInelGt0()) // <-- + continue; + if (cFilladditionalQAeventPlots) { // Fill histograms for the characteristics of the *mixed* events (collision1 and collision2) // This will show the distribution of events that are actually being mixed. @@ -1236,6 +1289,119 @@ struct Lambda1520analysisinpp { } } PROCESS_SWITCH(Lambda1520analysisinpp, processME, "Process EventMixing light without partition", false); + + void processdummy(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) + { + bool isInAfterAllCuts = colCuts.isSelected(collision, false); + bool inVtx10 = (std::abs(collision.mcCollision().posZ()) > configEvents.cfgEvtZvtx) ? false : true; + bool isTriggerTVX = collision.selection_bit(aod::evsel::kIsTriggerTVX); + bool isSel8 = collision.sel8(); + + auto mcPartsAll = mcParticles.sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + + bool isTrueINELgt0 = pwglf::isINELgt0mc(mcPartsAll, pdg); + // bool isTrueINELgt0 = collision.isInelGt0(); + + auto centrality = centEst(collision); + + auto computePtL = [&](float pt, float m_ref) { + float ptL2 = pt * pt + m_ref * m_ref - MassLambda1520 * MassLambda1520; + return (ptL2 > 0) ? std::sqrt(ptL2) : -1.f; + }; + + for (auto& part : mcPartsAll) { + + if (!part.isPhysicalPrimary()) + continue; + + float pt = part.pt(); + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) // rapidity cut + continue; + + if (std::abs(part.pdgCode()) == kProton) { + + float ptL = computePtL(pt, massPr); + if (ptL < 0) + continue; + + histos.fill(HIST("Result/dummy/Genprotonpt"), 0, ptL, centrality); + + if (inVtx10) // vtx10 + histos.fill(HIST("Result/dummy/Genprotonpt"), 1, ptL, centrality); + + if (inVtx10 && isSel8) // vtx10, sel8 + histos.fill(HIST("Result/dummy/Genprotonpt"), 2, ptL, centrality); + + if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX + histos.fill(HIST("Result/dummy/Genprotonpt"), 3, ptL, centrality); + + if (inVtx10 && isTrueINELgt0) // vtx10, INEL>0 + histos.fill(HIST("Result/dummy/Genprotonpt"), 4, ptL, centrality); + + if (isInAfterAllCuts) // after all event selection + histos.fill(HIST("Result/dummy/Genprotonpt"), 5, ptL, centrality); + + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + histos.fill(HIST("Result/dummy/Genprotonpt"), 6, ptL, centrality); + } + + if (std::abs(part.pdgCode()) == kLambda0) { + + float ptL = computePtL(pt, MassLambda0); + if (ptL < 0) + continue; + + histos.fill(HIST("Result/dummy/Genlambdapt"), 0, ptL, centrality); + + if (inVtx10) // vtx10 + histos.fill(HIST("Result/dummy/Genlambdapt"), 1, ptL, centrality); + + if (inVtx10 && isSel8) // vtx10, sel8 + histos.fill(HIST("Result/dummy/Genlambdapt"), 2, ptL, centrality); + + if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX + histos.fill(HIST("Result/dummy/Genlambdapt"), 3, ptL, centrality); + + if (inVtx10 && isTrueINELgt0) // vtx10, INEL>0 + histos.fill(HIST("Result/dummy/Genlambdapt"), 4, ptL, centrality); + + if (isInAfterAllCuts) // after all event selection + histos.fill(HIST("Result/dummy/Genlambdapt"), 5, ptL, centrality); + + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + histos.fill(HIST("Result/dummy/Genlambdapt"), 6, ptL, centrality); + } + + if (std::abs(part.pdgCode()) == PDG_t::kXiMinus) { + + float ptL = computePtL(pt, MassXiMinus); + if (ptL < 0) + continue; + + histos.fill(HIST("Result/dummy/Genxipt"), 0, ptL, centrality); + + if (inVtx10) // vtx10 + histos.fill(HIST("Result/dummy/Genxipt"), 1, ptL, centrality); + + if (inVtx10 && isSel8) // vtx10, sel8 + histos.fill(HIST("Result/dummy/Genxipt"), 2, ptL, centrality); + + if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX + histos.fill(HIST("Result/dummy/Genxipt"), 3, ptL, centrality); + + if (inVtx10 && isTrueINELgt0) // vtx10, INEL>0 + histos.fill(HIST("Result/dummy/Genxipt"), 4, ptL, centrality); + + if (isInAfterAllCuts) // after all event selection + histos.fill(HIST("Result/dummy/Genxipt"), 5, ptL, centrality); + + if (isInAfterAllCuts && isTrueINELgt0) // after all event selection && INEL>0 + histos.fill(HIST("Result/dummy/Genxipt"), 6, ptL, centrality); + } + } + } + PROCESS_SWITCH(Lambda1520analysisinpp, processdummy, "Process dummy", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Resonances/phiOO.cxx b/PWGLF/Tasks/Resonances/phi1020analysis.cxx similarity index 94% rename from PWGLF/Tasks/Resonances/phiOO.cxx rename to PWGLF/Tasks/Resonances/phi1020analysis.cxx index 9c7e6005264..c56a71e68c4 100644 --- a/PWGLF/Tasks/Resonances/phiOO.cxx +++ b/PWGLF/Tasks/Resonances/phi1020analysis.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file phiInJets.cxx +/// \file phi1020analysis.cxx /// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance OO analysis /// /// @@ -61,7 +61,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct phiOO { +struct phi1020analysis { SliceCache cache; Preslice perCollision = aod::track::collisionId; @@ -77,6 +77,7 @@ struct phiOO { Configurable cfg_Event_Pileup{"cfg_Event_Pileup", true, "Pileup border cut"}; Configurable cfg_Event_OccupancyCut{"cfg_Event_OccupancyCut", true, "Occupancy border cut"}; Configurable cfg_Event_MaxOccupancy{"cfg_Event_MaxOccupancy", 1, "Max TPC Occupancy"}; + Configurable centEstimator{"centEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; // Track configurables Configurable cfg_Track_Sel{"cfg_Track_Sel", "globalTracks", "set track selections"}; @@ -136,10 +137,10 @@ struct phiOO { // Event QA if (cfg_Event_CutQA) { histos.add("hPosZ_BC", "PosZ_BC", kTH1F, {{240, -12.0, 12.0}}); - histos.add("hcentFT0C_BC", "centFT0C_BC", kTH1F, {{110, 0.0, 110.0}}); + histos.add("hcentFT0_BC", "centFT0_BC", kTH1F, {{110, 0.0, 110.0}}); histos.add("hOccupancy_BC", "Occupancy_BC", kTH1F, {{100, 0.0, 20000}}); // - histos.add("hcentFT0C_AC", "centFT0C_AC", kTH1F, {{110, 0.0, 110.0}}); + histos.add("hcentFT0_AC", "centFT0_AC", kTH1F, {{110, 0.0, 110.0}}); histos.add("hPosZ_AC", "PosZ_AC", kTH1F, {{240, -12.0, 12.0}}); histos.add("hOccupancy_AC", "Occupancy_AC", kTH1F, {{100, 0.0, 20000}}); } @@ -198,7 +199,7 @@ struct phiOO { Filter collisionFilter = nabs(aod::collision::posZ) <= cfg_Event_VtxCut; Filter collisionFilter_MC = nabs(aod::mccollision::posZ) <= cfg_Event_VtxCut; - Filter centralityFilter = nabs(aod::cent::centFT0C) <= cfg_Event_CentralityMax; + // Filter centralityFilter = nabs(aod::cent::centFT0C) <= cfg_Event_CentralityMax; Filter acceptanceFilter = (nabs(aod::track::eta) < cfg_Track_MaxEta && nabs(aod::track::pt) >= cfg_Track_MinPt); using EventCandidates = soa::Filtered>; using EventCandidates_True = soa::Filtered; @@ -208,7 +209,7 @@ struct phiOO { using TrackCandidates_MC = soa::Filtered>; - using BinningTypeVtxCent = ColumnBinningPolicy; + using BinningTypeVtxCent = ColumnBinningPolicy; Partition PosKaon_MC = (aod::track::signed1Pt > static_cast(0)) && @@ -224,6 +225,29 @@ struct phiOO { (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); double massKa = o2::constants::physics::MassKPlus; + + // Centralicity estimator selection + template + float centEst(Coll collisions) + { + float returnValue = -999.0f; + switch (centEstimator) { + case 0: + returnValue = collisions.centFT0M(); + break; + case 1: + returnValue = collisions.centFT0A(); + break; + case 2: + returnValue = collisions.centFT0C(); + break; + default: + returnValue = collisions.centFT0M(); + break; + } + return returnValue; + } + //***********************************// // First, we declare some helper functions template @@ -234,10 +258,10 @@ struct phiOO { if constexpr (requires { obj.posZ(); }) { if (!pass) { histos.fill(HIST("hPosZ_BC"), obj.posZ()); - histos.fill(HIST("hcentFT0C_BC"), obj.centFT0C()); + histos.fill(HIST("hcentFT0_BC"), centEst(obj)); } else { histos.fill(HIST("hPosZ_AC"), obj.posZ()); - histos.fill(HIST("hcentFT0C_AC"), obj.centFT0C()); + histos.fill(HIST("hcentFT0_AC"), centEst(obj)); } } } @@ -300,7 +324,7 @@ struct phiOO { return {false, 4}; if (cfg_Event_Pileup && (!event.selection_bit(aod::evsel::kNoSameBunchPileup) || !event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) return {false, 5}; - if (cfg_Event_Centrality && (event.centFT0C() > cfg_Event_CentralityMax)) + if (cfg_Event_Centrality && (centEst(event) > cfg_Event_CentralityMax)) return {false, 6}; if (cfg_Event_OccupancyCut && (event.trackOccupancyInTimeRange() > cfg_Event_MaxOccupancy)) return {false, 7}; @@ -375,7 +399,7 @@ struct phiOO { tofPIDPassed = true; } if (!candidate.hasTOF()) { - std::cout << candidate.tofNSigmaKa() << std::endl; + // std::cout << candidate.tofNSigmaKa() << std::endl; } } if (tpcPIDPassed && tofPIDPassed) { @@ -392,7 +416,7 @@ struct phiOO { { auto slicedtracks1 = PosKaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto slicedtracks2 = NegKaon->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = collision1.centFT0C(); + auto centrality = centEst(collision1); for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); if (Minv < 0) @@ -419,7 +443,7 @@ struct phiOO { { auto slicedtracks1 = PosKaon_MC->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); auto slicedtracks2 = NegKaon_MC->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - auto centrality = collision1.centFT0C(); + auto centrality = centEst(collision1); for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); if (Minv < 0) @@ -526,7 +550,7 @@ struct phiOO { } // end of process - PROCESS_SWITCH(phiOO, processSameEvent, "Process Same events", true); + PROCESS_SWITCH(phi1020analysis, processSameEvent, "Process Same events", true); //***************// // DATA (MIX) @@ -553,7 +577,7 @@ struct phiOO { TrackSlicing(collision1, tracks1, collision2, tracks2, false, true); } // mixing } // end of process - PROCESS_SWITCH(phiOO, processMixedEvent, "Process Mixed events", false); + PROCESS_SWITCH(phi1020analysis, processMixedEvent, "Process Mixed events", false); //***************// // RECONSTRUCTED MC @@ -576,7 +600,7 @@ struct phiOO { TrackSlicing_MC(collision, tracks, collision, tracks, true, false); } // end of process - PROCESS_SWITCH(phiOO, processSameEvent_MC, "Process Same events (MC)", true); + PROCESS_SWITCH(phi1020analysis, processSameEvent_MC, "Process Same events (MC)", true); //***************// // RECONSTRUCTED MC (MIX) @@ -602,7 +626,7 @@ struct phiOO { TrackSlicing_MC(collision1, tracks1, collision2, tracks2, false, true); } // mixing } // end of process - PROCESS_SWITCH(phiOO, processMixedEvent_MC, "Process Mixed events (MC)", false); + PROCESS_SWITCH(phi1020analysis, processMixedEvent_MC, "Process Mixed events (MC)", false); //***************// // GENERATED MC @@ -629,7 +653,7 @@ struct phiOO { double centrality = -1; for (auto& recocoll : recocolls) { // poorly reconstructed - centrality = recocoll.centFT0C(); + centrality = centEst(recocoll); auto [goodEv, code] = eventSelection(recocoll, false); histos.fill(HIST("hnEvents_MC_True"), code); if (!goodEv) @@ -665,11 +689,11 @@ struct phiOO { } // loop over particles } // end of process - PROCESS_SWITCH(phiOO, processParticles, "Process Particles", false); + PROCESS_SWITCH(phi1020analysis, processParticles, "Process Particles", false); }; // end of main struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; }; diff --git a/PWGLF/Tasks/Resonances/phianalysisTHnSparse.cxx b/PWGLF/Tasks/Resonances/phianalysisTHnSparse.cxx index 27d4ed55de3..b8a921c29c6 100644 --- a/PWGLF/Tasks/Resonances/phianalysisTHnSparse.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisTHnSparse.cxx @@ -108,9 +108,10 @@ struct PhianalysisTHnSparse { // other axes ConfigurableAxis axisNch{"axisNch", {1000, 0.0f, +1000.0f}, "Number of charged particles."}; ConfigurableAxis axisResolutionPt{"axisResolutionPt", {1001, -1.0f, +1.0f}, "Resolution of Pt."}; - ConfigurableAxis axisResolutionPtPhi{"axisResolutionPtPhi", {1001, -0.0001f, +0.0001f}, "Resolution of Pt and Phi."}; - ConfigurableAxis axisResolutionMass{"axisResolutionMass", {1001, -0.05f, +0.05f}, "Resolution of Mass."}; + ConfigurableAxis axisResolutionPtPhi{"axisResolutionPtPhi", {1001, -0.01f, +0.01f}, "Resolution of Pt and Phi."}; + ConfigurableAxis axisResolutionMass{"axisResolutionMass", {1001, -0.01f, +0.01f}, "Resolution of Mass."}; ConfigurableAxis axisResolutionVz{"axisResolutionVz", {1001, -3.0f, +3.0f}, "Resolution of Vz."}; + ConfigurableAxis massShiftAxis{"massShiftAxis", {1001, -0.02f, 0.02f}, "Mass correction axis."}; // Axes specifications AxisSpec posZaxis = {400, -20., 20., "V_{z} (cm)"}; @@ -118,6 +119,7 @@ struct PhianalysisTHnSparse { AxisSpec dcaZaxis = {1000, -1.0, 1.0, "DCA_{z} (cm)"}; AxisSpec etaQAaxis = {1000, -1.0, 1.0, "#eta"}; AxisSpec tpcNClsFoundQAaxis = {110, 50., 160., "tpcNClsFound"}; + AxisSpec massShiftRelAxis = {101, -0.03f, 0.03f, ""}; HistogramRegistry registry{"registry"}; o2::analysis::rsn::Output* rsnOutput = nullptr; @@ -127,9 +129,12 @@ struct PhianalysisTHnSparse { int n = 0; float massPos = o2::track::PID::getMass(3); float massNeg = o2::track::PID::getMass(3); + int pion = 2; + int kaon = 3; + int proton = 4; double* pointPair = nullptr; double* pointSys = nullptr; - ROOT::Math::PxPyPzMVector d1, d2, mother; + ROOT::Math::PxPyPzMVector d1, d2, mother, motherGen; bool produceTrue, produceLikesign, produceQA, produceStats, produceRotational, dataQA, MCTruthQA, globalTrack, inelGrater0, tpcPidOnly = false; float tpcnSigmaPos = 100.0f; float tpcnSigmaNeg = 100.0f; @@ -145,7 +150,7 @@ struct PhianalysisTHnSparse { using EventCandidates = soa::Join; using EventCandidate = EventCandidates::iterator; - using TrackCandidates = soa::Join; + using TrackCandidates = soa::Join; using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Join; @@ -417,17 +422,28 @@ struct PhianalysisTHnSparse { hResVz->GetYaxis()->SetTitle("#DeltaV_{z} = V_{z}^{rec} - V_{z}^{gen} (cm)"); registry.add("Factors/h2ResolutionPt", "Resolution of charged particles p_{T}", kTH2F, {ptaxis, axisResolutionPt}); auto hResPt = registry.get(HIST("Factors/h2ResolutionPt")); - ; + hResPt->GetXaxis()->SetTitle("p_{T}^{rec} (GeV/c)"); hResPt->GetYaxis()->SetTitle("#Deltap_{T} = p_{T}^{rec} - p_{T}^{gen} (GeV/c)"); - registry.add("Factors/h2ResolutionPtPhi", "Resolution of Phi p_{T}", kTH2F, {ptaxis, axisResolutionPtPhi}); + registry.add("Factors/h2ResolutionPtPhi", "p_{T} resolution vs p_{T}^{rec}", kTH2F, {ptaxis, axisResolutionPtPhi}); auto hResPtPhi = registry.get(HIST("Factors/h2ResolutionPtPhi")); hResPtPhi->GetXaxis()->SetTitle("p_{T}^{rec} (GeV/c)"); hResPtPhi->GetYaxis()->SetTitle("#Deltap_{T} = p_{T}^{rec} - p_{T}^{gen} (GeV/c)"); - registry.add("Factors/h2ResolutionMass", "Resolution of mass vs p_{T}^{rec}", kTH2F, {ptaxis, axisResolutionMass}); - auto hResMass = registry.get(HIST("Factors/h2ResolutionMass")); + + registry.add("Factors/h2MassResolution", "Mass resolution vs p_{T}^{rec}", kTH2F, {ptaxis, axisResolutionMass}); + auto hResMass = registry.get(HIST("Factors/h2MassResolution")); hResMass->GetXaxis()->SetTitle("p_{T}^{rec} (GeV/c)"); - hResMass->GetYaxis()->SetTitle("#Deltam = m^{rec} - m^{gen} (GeV/c^{2})"); + hResMass->GetYaxis()->SetTitle("#Deltam = m^{gen}_{KK} - m^{rec}_{KK} (GeV/c^{2})"); + + registry.add("Factors/h2MassShift", "Mass shift vs p_{T}^{rec}", kTH2F, {ptaxis, massShiftAxis}); + auto hResMassGen = registry.get(HIST("Factors/h2MassShift")); + hResMassGen->GetXaxis()->SetTitle("p_{T}^{rec} (GeV/c)"); + hResMassGen->GetYaxis()->SetTitle("#Deltam = m^{gen}_{#phi} - m^{gen}_{KK} (GeV/c^{2})"); + + registry.add("Factors/h2MassShiftRel", "Relative mass shift vs p_{T}^{rec}", kTH2F, {ptaxis, massShiftRelAxis}); + auto hMassCorr = registry.get(HIST("Factors/h2MassShiftRel")); + hMassCorr->GetXaxis()->SetTitle("p_{T}^{rec} (GeV/c)"); + hMassCorr->GetYaxis()->SetTitle("m^{gen}_{#phi} - m^{gen}_{KK}/m^{gen}_{#phi}"); } } // Factors @@ -445,6 +461,34 @@ struct PhianalysisTHnSparse { registry.add("Factors/h3dGenPhiVsMultMCVsCentrality", "MC multiplicity vs centrality vs p_{T}", kTH3D, {axisNch, {101, 0.0f, 101.0f}, ptaxis}); } + template + float tpcNsigma(const T& track) + { + float tpcNsigma = 0.0f; + int particleType = (track.sign() > 0) ? static_cast(daughterPos) : static_cast(daughterNeg); + + if (particleType == pion) + tpcNsigma = track.tpcNSigmaPi(); + else if (particleType == kaon) + tpcNsigma = track.tpcNSigmaKa(); + else if (particleType == proton) + tpcNsigma = track.tpcNSigmaPr(); + return tpcNsigma; + } + template + float tofNsigma(const T& track) + { + float tofNsigma = 0.0f; + int particleType = (track.sign() > 0) ? static_cast(daughterPos) : static_cast(daughterNeg); + + if (particleType == pion) + tofNsigma = track.tofNSigmaPi(); + else if (particleType == kaon) + tofNsigma = track.tofNSigmaKa(); + else if (particleType == proton) + tofNsigma = track.tofNSigmaPr(); + return tofNsigma; + } template bool selectedTrack(const T& track, bool isPositive) { @@ -473,10 +517,10 @@ struct PhianalysisTHnSparse { // PID selection: TPC-only for pt < threshold value, TPC+TOF for pt >= threshold value and have TOF, else TPC-only float nSigmaCut = isPositive ? tpcnSigmaPos : tpcnSigmaNeg; if (track.pt() < ptTOFThreshold || !track.hasTOF() || tpcPidOnly) { - if (std::abs(track.tpcNSigmaKa()) >= nSigmaCut) + if (std::abs(tpcNsigma(track)) >= nSigmaCut) return false; } else { - if (std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa()) >= combinedNSigma) + if (std::sqrt(tpcNsigma(track) * tpcNsigma(track) + tofNsigma(track) * tofNsigma(track)) >= combinedNSigma) return false; } if (produceQA && dataQA) @@ -512,15 +556,16 @@ struct PhianalysisTHnSparse { return true; } template - bool selectedPair(ROOT::Math::PxPyPzMVector& mother, const T& track1, const T& track2) + ROOT::Math::PxPyPzMVector calculateMother(const T& track1, const T& track2) { d1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massPos); d2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massNeg); - mother = d1 + d2; - + return d1 + d2; + } + bool seletectedMother(const ROOT::Math::PxPyPzMVector& mother) + { if (std::abs(mother.Rapidity()) > static_cast(cut.rapidity)) return false; - return true; } template @@ -613,24 +658,25 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, false)) // track2 is negative continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; if (produceQA) { - registry.fill(HIST("QAPID/h2TPCnSigma"), track1.tpcNSigmaKa(), track2.tpcNSigmaKa()); - registry.fill(HIST("QAPID/h2TPCnSigmaPt"), track1.pt(), track1.tpcNSigmaKa()); - registry.fill(HIST("QAPID/h2TPCnSigmaPt"), track2.pt(), track2.tpcNSigmaKa()); + registry.fill(HIST("QAPID/h2TPCnSigma"), tpcNsigma(track1), tpcNsigma(track2)); + registry.fill(HIST("QAPID/h2TPCnSigmaPt"), track1.pt(), tpcNsigma(track1)); + registry.fill(HIST("QAPID/h2TPCnSigmaPt"), track2.pt(), tpcNsigma(track2)); - registry.fill(HIST("QAPID/h2TOFnSigma"), track1.tofNSigmaKa(), track2.tofNSigmaKa()); - registry.fill(HIST("QAPID/h2TOFnSigmaPt"), track1.pt(), track1.tofNSigmaKa()); - registry.fill(HIST("QAPID/h2TOFnSigmaPt"), track2.pt(), track2.tofNSigmaKa()); + registry.fill(HIST("QAPID/h2TOFnSigma"), tofNsigma(track1), tofNsigma(track2)); + registry.fill(HIST("QAPID/h2TOFnSigmaPt"), track1.pt(), tofNsigma(track1)); + registry.fill(HIST("QAPID/h2TOFnSigmaPt"), track2.pt(), tofNsigma(track2)); - registry.fill(HIST("QAPID/hTPCnSigma"), track1.tpcNSigmaKa()); - registry.fill(HIST("QAPID/hTPCnSigma"), track2.tpcNSigmaKa()); + registry.fill(HIST("QAPID/hTPCnSigma"), tpcNsigma(track1)); + registry.fill(HIST("QAPID/hTPCnSigma"), tpcNsigma(track2)); if (track1.hasTOF()) - registry.fill(HIST("QAPID/hTOFnSigma"), track1.tofNSigmaKa()); + registry.fill(HIST("QAPID/hTOFnSigma"), tofNsigma(track1)); if (track2.hasTOF()) - registry.fill(HIST("QAPID/hTOFnSigma"), track2.tofNSigmaKa()); + registry.fill(HIST("QAPID/hTOFnSigma"), tofNsigma(track2)); registry.fill(HIST("QATrack/hEta"), track1.eta()); registry.fill(HIST("QATrack/hEta"), track2.eta()); @@ -657,8 +703,8 @@ struct PhianalysisTHnSparse { mother.Pt(), getMultiplicity(collision), getCentrality(collision), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), collision.posZ(), @@ -688,8 +734,8 @@ struct PhianalysisTHnSparse { mother.Pt(), getMultiplicity(collision), getCentrality(collision), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), collision.posZ(), @@ -710,7 +756,8 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, true)) // both positive continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; if (static_cast(verbose.verboselevel) > 1) @@ -720,8 +767,8 @@ struct PhianalysisTHnSparse { mother.Pt(), getMultiplicity(collision), getCentrality(collision), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), collision.posZ(), @@ -738,7 +785,8 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, false)) // both negative continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; if (static_cast(verbose.verboselevel) > 1) @@ -748,8 +796,8 @@ struct PhianalysisTHnSparse { mother.Pt(), getMultiplicity(collision), getCentrality(collision), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), collision.posZ(), @@ -849,12 +897,9 @@ struct PhianalysisTHnSparse { if (std::abs(mothertrack1.pdgCode()) != motherPDG) continue; - if (static_cast(verbose.verboselevel) > 1) { - LOGF(info, "True: %d, d1=%d (%ld), d2=%d (%ld), mother=%d (%ld)", n, mctrack1.pdgCode(), mctrack1.globalIndex(), mctrack2.pdgCode(), mctrack2.globalIndex(), mothertrack1.pdgCode(), mothertrack1.globalIndex()); - LOGF(info, "%d px: %f, py=%f, pz=%f, px: %f, py=%f, pz=%f", n, mctrack1.px(), mctrack1.py(), mctrack1.pz(), mctrack2.px(), mctrack2.py(), mctrack2.pz()); - } - - if (!selectedPair(mother, mctrack1, mctrack2)) + mother = calculateMother(track1, track2); + motherGen = calculateMother(mctrack1, mctrack2); + if (!seletectedMother(mother)) continue; if (n > 0) { @@ -863,12 +908,18 @@ struct PhianalysisTHnSparse { continue; } + if (static_cast(verbose.verboselevel) > 1) { + LOGF(info, "Collision: %ld True: %d, d1=%d (%ld), d2=%d (%ld), mother=%d (%ld)", collision.globalIndex(), n, mctrack1.pdgCode(), mctrack1.globalIndex(), mctrack2.pdgCode(), mctrack2.globalIndex(), mothertrack1.pdgCode(), mothertrack1.globalIndex()); + LOGF(info, "Track %d px: %f, py=%f, pz=%f, px: %f, py=%f, pz=%f", n, track1.px(), track1.py(), track1.pz(), track2.px(), track2.py(), track2.pz()); + LOGF(info, "mcTrack %d px: %f, py=%f, pz=%f, px: %f, py=%f, pz=%f", n, mctrack1.px(), mctrack1.py(), mctrack1.pz(), mctrack2.px(), mctrack2.py(), mctrack2.pz()); + } + pointPair = fillPointPair(mother.M(), mother.Pt(), getMultiplicity(collision), getCentrality(collision), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), collision.posZ(), @@ -881,12 +932,33 @@ struct PhianalysisTHnSparse { auto phiP = mothertrack1.p(); auto phiE = mothertrack1.e(); - auto phiMass = std::sqrt(phiE * phiE - phiP * phiP); + auto massGen = std::sqrt(phiE * phiE - phiP * phiP); + + registry.fill(HIST("Factors/h2ResolutionPtPhi"), mother.Pt(), (mother.Pt() - mothertrack1.pt())); + registry.fill(HIST("Factors/h2MassResolution"), mother.Pt(), (motherGen.M() - mother.M())); + registry.fill(HIST("Factors/h2MassShift"), mother.Pt(), (massGen - motherGen.M())); + registry.fill(HIST("Factors/h2MassShiftRel"), mother.Pt(), (massGen - motherGen.M()) / massGen); - registry.fill(HIST("Factors/h2ResolutionPtPhi"), mother.pt(), (mother.pt() - mothertrack1.pt())); - registry.fill(HIST("Factors/h2ResolutionMass"), mother.Pt(), (mother.M() - phiMass)); + if (static_cast(verbose.verboselevel) > 1) + LOGF(info, "mother.M()=%f, motherGen.M()=%f, massGen =%f", mother.M(), motherGen.M(), massGen); rsnOutput->fillUnliketrue(pointPair); + + pointPair = fillPointPair(motherGen.M(), + motherGen.Pt(), + getMultiplicity(collision), + getCentrality(collision), + tpcNsigma(track1), + tpcNsigma(track2), + motherGen.Eta(), + motherGen.Rapidity(), + collision.posZ(), + 0, + 0, + 0); + + rsnOutput->fillUnlikegenOld(pointPair); + n++; } } @@ -1007,15 +1079,16 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, false)) // track2 is negative continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; pointPair = fillPointPair(mother.M(), mother.Pt(), getMultiplicity(c1), getCentrality(c1), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), c1.posZ(), @@ -1033,15 +1106,16 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, false)) // track2 is negative continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; pointPair = fillPointPair(mother.M(), mother.Pt(), getMultiplicity(c1), getCentrality(c1), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), c1.posZ(), @@ -1077,15 +1151,16 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, false)) // track2 is negative continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; pointPair = fillPointPair(mother.M(), mother.Pt(), getMultiplicity(c1), getCentrality(c1), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), c1.posZ(), @@ -1104,15 +1179,16 @@ struct PhianalysisTHnSparse { if (!selectedTrack(track2, false)) continue; - if (!selectedPair(mother, track1, track2)) + mother = calculateMother(track1, track2); + if (!seletectedMother(mother)) continue; pointPair = fillPointPair(mother.M(), mother.Pt(), getMultiplicity(c1), getCentrality(c1), - track1.tpcNSigmaKa(), - track2.tpcNSigmaKa(), + tpcNsigma(track1), + tpcNsigma(track2), mother.Eta(), mother.Rapidity(), c1.posZ(), diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx index d3a4430b660..78e07fbd4f4 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx @@ -13,13 +13,15 @@ /// \author Sarjeeta Gami #include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/Utils/inelGt.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" @@ -93,6 +95,9 @@ struct phianalysisrun3_PbPb { Configurable additionalEvSel4{"additionalEvSel4", true, "Additional evsel4"}; Configurable additionalEvSel5{"additionalEvSel5", true, "Additional evsel5"}; Configurable additionalEvSel6{"additionalEvSel6", true, "Additional evsel6"}; + Configurable cutvz{"cutvz", true, "Vz cut"}; + Configurable cutvzgen{"cutvzgen", true, "Vz cut"}; + Configurable isINELgt0{"isINELgt0", true, "INEL>0 selection"}; } selectionConfig; Configurable cfgMultFT0{"cfgMultFT0", true, "cfgMultFT0"}; Configurable pid{"pid", 0, "pid"}; @@ -129,8 +134,9 @@ struct phianalysisrun3_PbPb { Configurable centestimator{"centestimator", 0, "Select multiplicity estimator: 0 - FT0C, 1 - FT0A, 2 - FT0M, 3 - FV0A, 4 - PVTracks"}; ConfigurableAxis binsMult{"binsMult", {500, 0.0f, +500.0f}, ""}; Configurable isApplyCentFT0C{"isApplyCentFT0C", true, "Centrality based on FT0C"}; - Configurable isApplyCentFT0M{"isApplyCentFV0A", false, "Centrality based on FT0M"}; - + Configurable isApplyCentFT0M{"isApplyCentFV0M", false, "Centrality based on FT0M"}; + Configurable isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"}; + Configurable isApplyTVX{"isApplyTVX", false, "Enable TVX trigger sel"}; Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; // MC Configurable isMC{"isMC", false, "Run MC"}; @@ -147,7 +153,7 @@ struct phianalysisrun3_PbPb { histos.add("hCentrality", "Centrality distribution", kTH1F, {centAxisphi}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); histos.add("hOccupancy", "Occupancy distribution", kTH1F, {{500, 0, 50000}}); - histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{11, 0, 11.0}}); histos.add("h3PhiInvMassUnlikeSign", "Invariant mass of Phi meson Unlike Sign", kTH3F, {centAxisphi, ptAxisphi, massAxisphi}); histos.add("h3PhiInvMassMixed", "Invariant mass of Phi meson Mixed", kTH3F, {centAxisphi, ptAxisphi, massAxisphi}); histos.add("h3PhiInvMassRot", "Invariant mass of Phi meson Rotation", kTH3F, {centAxisphi, ptAxisphi, massAxisphi}); @@ -252,22 +258,22 @@ struct phianalysisrun3_PbPb { histos.add("TPC_Nsigma1_MC", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3D, {{200, -12, 12}, centAxisphi, ptAxisphi}}); histos.add("trkDCAxy", "DCAxy distribution of positive kaon track candidates", HistType::kTH3F, {{150, -1.0f, 1.0f}, centAxisphi, ptAxisphi}); histos.add("trkDCAz", "DCAxy distribution of negative kaon track candidates", HistType::kTH3F, {{150, -1.0f, 1.0f}, centAxisphi, ptAxisphi}); - registry.add("Factors/hCentralityVsMultMC", "Event centrality vs MC multiplicity", kTH2F, {{101, 0.0f, 101.0f}, axisNch}); - registry.add("Factors/hEventCentrality", "Event centrality", kTH1F, {{101, 0, 101}}); - registry.add("Factors/hNrecInGen", "Number of collisions in MC", kTH1F, {{4, -0.5, 3.5}}); - registry.add("Factors/hGenEvents", "Generated events", HistType::kTH2F, {{axisNch}, {4, 0, 4}}); - auto hGenEvents = registry.get(HIST("Factors/hGenEvents")); - hGenEvents->GetYaxis()->SetBinLabel(1, "All generated events"); - hGenEvents->GetYaxis()->SetBinLabel(2, "Generated events with Mc collision V_{z} cut"); - hGenEvents->GetYaxis()->SetBinLabel(3, "Generated events with at least one reconstructed event"); - registry.add("Factors/h2dGenPhi", "Centrality vs p_{T}", kTH2D, {{101, 0.0f, 101.0f}, ptAxisphi}); - registry.add("Factors/h3dGenPhiVsMultMCVsCentrality", "MC multiplicity vs centrality vs p_{T}", kTH3D, {axisNch, {101, 0.0f, 101.0f}, ptAxisphi}); if (doprocessEvtLossSigLossMC) { histos.add("QAevent/hImpactParameterGen", "Impact parameter of generated MC events", kTH1F, {impactParAxis}); histos.add("QAevent/hImpactParameterRec", "Impact parameter of selected MC events", kTH1F, {impactParAxis}); histos.add("QAevent/hImpactParvsCentrRec", "Impact parameter of selected MC events vs centrality", kTH2F, {{120, 0.0f, 120.0f}, impactParAxis}); histos.add("QAevent/phigenBeforeEvtSel", "phi before event selections", kTH2F, {ptAxis, impactParAxis}); histos.add("QAevent/phigenAfterEvtSel", "phi after event selections", kTH2F, {ptAxis, impactParAxis}); + histos.add("QAevent/hMultEta05Rec", "multiplicity in eta<0.5 of selected MC events", kTH1F, {multAxis}); + histos.add("QAevent/hMultEta05vsCentrRec", "multiplicity in eta<0.5 of selected MC events vs centrality", kTH2F, {centAxis, multAxis}); + histos.add("QAevent/hMultEta05Gen", "multiplicity in eta<0.5 of generated MC events", kTH1F, {multAxis}); + histos.add("QAevent/hgendndetaVsMultEta05BeforeEvtSel", "hgendndetaBeforeEvtSel vs multiplicity in eta<0.5", kTH2F, {ptAxis, multAxis}); + histos.add("QAevent/hgendndetaVsMultEta05AfterEvtSel", "hgendndetaAfterEvtSel vs multiplicity in eta<0.5", kTH2F, {ptAxis, multAxis}); + histos.add("QAevent/hMultEta08Rec", "multiplicity in eta<0.5 of selected MC events", kTH1F, {multAxis}); + histos.add("QAevent/hMultEta08vsCentrRec", "multiplicity in eta<0.5 of selected MC events vs centrality", kTH2F, {centAxis, multAxis}); + histos.add("QAevent/hMultEta08Gen", "multiplicity in eta<0.5 of generated MC events", kTH1F, {multAxis}); + histos.add("QAevent/hgendndetaVsMultEta08BeforeEvtSel", "hgendndetaBeforeEvtSel vs multiplicity in eta<0.5", kTH2F, {ptAxis, multAxis}); + histos.add("QAevent/hgendndetaVsMultEta08AfterEvtSel", "hgendndetaAfterEvtSel vs multiplicity in eta<0.5", kTH2F, {ptAxis, multAxis}); } if (doprocessEvtLossSigLossMC1) { histos.add("MCEventHist", "MCEventHist", kTH1F, {axisEvent}, false); @@ -372,7 +378,7 @@ struct phianalysisrun3_PbPb { template bool myEventSelections(const CollType& collision) { - if (std::abs(collision.posZ()) > selectionConfig.cfgCutVertex) + if (selectionConfig.cutvz && !(std::abs(collision.posZ()) < selectionConfig.cfgCutVertex)) return false; if (!collision.sel8()) @@ -393,6 +399,9 @@ struct phianalysisrun3_PbPb { return false; if (selectionConfig.additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) return false; + if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { + return false; + } int occupancy = collision.trackOccupancyInTimeRange(); if (selectionConfig.fillOccupancy && (occupancy < cfgMinOccupancy || occupancy > cfgMaxOccupancy)) return false; @@ -419,7 +428,7 @@ struct phianalysisrun3_PbPb { cent = col.centFT0C(); } if (isApplyCentFT0M) { - cent = col.centFT0A(); + cent = col.centFT0M(); } return cent; } @@ -475,7 +484,9 @@ struct phianalysisrun3_PbPb { } } } - Filter collisionFilter = nabs(aod::collision::posZ) < selectionConfig.cfgCutVertex; + Filter collisionFilter = + (!selectionConfig.cutvz) || + (nabs(aod::collision::posZ) < selectionConfig.cfgCutVertex); Filter acceptanceFilter = (nabs(aod::track::eta) < selectionConfig.cfgCutEta && nabs(aod::track::pt) > selectionConfig.cfgCutPT); Filter dcacutFilter = (nabs(aod::track::dcaXY) < selectionConfig.cfgCutDCAxy) && (nabs(aod::track::dcaZ) < selectionConfig.cfgCutDCAz); @@ -514,7 +525,7 @@ struct phianalysisrun3_PbPb { return; } histos.fill(HIST("hEvtSelInfo"), 1.5); - if (!collision.sel8()) { + if (cfgDoSel8 && !collision.sel8()) { return; } histos.fill(HIST("hEvtSelInfo"), 2.5); @@ -547,6 +558,10 @@ struct phianalysisrun3_PbPb { return; } histos.fill(HIST("hEvtSelInfo"), 9.5); + if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 10.5); float multiplicity{-1}; const int kCentFT0C = 0; const int kCentFT0A = 1; @@ -697,6 +712,11 @@ struct phianalysisrun3_PbPb { if (selectionConfig.additionalEvSel6 && (!c1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } + if (selectionConfig.isINELgt0 && + (!c1.isInelGt0() || !c2.isInelGt0())) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); int occupancy2 = c2.trackOccupancyInTimeRange(); @@ -768,6 +788,11 @@ struct phianalysisrun3_PbPb { if (selectionConfig.additionalEvSel6 && (!c1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } + if (selectionConfig.isINELgt0 && + (!c1.isInelGt0() || !c2.isInelGt0())) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); int occupancy2 = c2.trackOccupancyInTimeRange(); @@ -840,6 +865,11 @@ struct phianalysisrun3_PbPb { if (selectionConfig.additionalEvSel6 && (!c1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } + if (selectionConfig.isINELgt0 && + (!c1.isInelGt0() || !c2.isInelGt0())) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); int occupancy2 = c2.trackOccupancyInTimeRange(); @@ -912,6 +942,11 @@ struct phianalysisrun3_PbPb { if (selectionConfig.additionalEvSel6 && (!c1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { continue; } + if (selectionConfig.isINELgt0 && + (!c1.isInelGt0() || !c2.isInelGt0())) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); int occupancy2 = c2.trackOccupancyInTimeRange(); @@ -1660,54 +1695,77 @@ struct phianalysisrun3_PbPb { } } PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEventMC, "Process Mixed event MC", true); - void processGen1(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) + void processGen1(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { + // all events histos.fill(HIST("hMC1"), 0.5); - if (std::abs(mcCollision.posZ()) < selectionConfig.cfgCutVertex) { + + // vertex QA (not selection) + if (!selectionConfig.cutvzgen || + std::abs(mcCollision.posZ()) < selectionConfig.cfgCutVertex) { histos.fill(HIST("hMC1"), 1.5); } + + // INEL>0 selection + if (isApplyInelgt0 && !mcCollision.isInelGt0()) + return; + + histos.fill(HIST("hMC1"), 2.5); + + // TVX selection + if (isApplyTVX && + !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) + return; + + histos.fill(HIST("hMC1"), 3.5); std::vector selectedEvents(collisions.size()); int nevts = 0; auto multiplicity = -1.0; for (const auto& collision : collisions) { - histos.fill(HIST("hMC1"), 2.5); + histos.fill(HIST("hMC1"), 4.5); if (cfgDoSel8 && !collision.sel8()) { continue; } - if (std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { + histos.fill(HIST("hMC1"), 5.5); + if (selectionConfig.cutvz && + std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { continue; } - histos.fill(HIST("hMC1"), 3.5); + histos.fill(HIST("hMC1"), 6.5); if (selectionConfig.additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { continue; } - histos.fill(HIST("hMC1"), 4.5); + histos.fill(HIST("hMC1"), 7.5); if (selectionConfig.additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { continue; } - histos.fill(HIST("hMC1"), 5.5); + histos.fill(HIST("hMC1"), 8.5); if (selectionConfig.additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { continue; } - histos.fill(HIST("hMC1"), 6.5); + histos.fill(HIST("hMC1"), 9.5); if (selectionConfig.additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } - histos.fill(HIST("hMC1"), 7.5); + histos.fill(HIST("hMC1"), 10.5); if (selectionConfig.additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - histos.fill(HIST("hMC1"), 8.5); + histos.fill(HIST("hMC1"), 11.5); if (selectionConfig.additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { continue; } - histos.fill(HIST("hMC1"), 9.5); + histos.fill(HIST("hMC1"), 12.5); + if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { + continue; + } + histos.fill(HIST("hMC1"), 13.5); int occupancy = collision.trackOccupancyInTimeRange(); if (selectionConfig.fillOccupancy && (occupancy < cfgMinOccupancy || occupancy > cfgMaxOccupancy)) { continue; } - histos.fill(HIST("hMC1"), 10.5); + histos.fill(HIST("hMC1"), 14.5); const int kCentFT0C = 0; const int kCentFT0A = 1; const int kCentFT0M = 2; @@ -1727,11 +1785,11 @@ struct phianalysisrun3_PbPb { } selectedEvents.resize(nevts); const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); - histos.fill(HIST("hMC1"), 11.5); + histos.fill(HIST("hMC1"), 15.5); if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } - histos.fill(HIST("hMC1"), 12.5); + histos.fill(HIST("hMC1"), 16.5); for (const auto& mcParticle : mcParticles) { if (mcParticle.y() < rapiditycut1 || mcParticle.y() > rapiditycut2) { @@ -1776,7 +1834,8 @@ struct phianalysisrun3_PbPb { if (cfgDoSel8 && !collision.sel8()) { return; } - if (std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { + if (selectionConfig.cutvz && + std::abs(collision.mcCollision().posZ()) > selectionConfig.cfgCutVertex) { return; } if (selectionConfig.additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { @@ -1800,6 +1859,9 @@ struct phianalysisrun3_PbPb { if (selectionConfig.additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return; } + if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { + return; + } int occupancy = collision.trackOccupancyInTimeRange(); if (selectionConfig.fillOccupancy && (occupancy < cfgMinOccupancy || occupancy > cfgMaxOccupancy)) { return; @@ -1819,7 +1881,7 @@ struct phianalysisrun3_PbPb { multiplicity = collision.centFV0A(); } histos.fill(HIST("Centrec1"), multiplicity); - histos.fill(HIST("hMC1"), 13.5); + histos.fill(HIST("hMC1"), 17.5); auto oldindex = -999; for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { @@ -1913,104 +1975,95 @@ struct phianalysisrun3_PbPb { } PROCESS_SWITCH(phianalysisrun3_PbPb, processRec1, "Process Reconstructed", false); - void processEvtLossSigLossMC(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + void processEvtLossSigLossMC(McCollisionMults::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) { + if (selectionConfig.cutvzgen && + std::abs(mcCollision.posZ()) > selectionConfig.cfgCutVertex) { + return; + } + if (isApplyInelgt0 && !mcCollision.isInelGt0()) { + return; + } + + if (isApplyTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { + return; + } // Event loss estimation auto impactPar = mcCollision.impactParameter(); histos.fill(HIST("QAevent/hImpactParameterGen"), impactPar); - + histos.fill(HIST("QAevent/hMultEta05Gen"), mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("QAevent/hMultEta08Gen"), mcCollision.multMCNParticlesEta08()); bool isSel = false; auto centrality = -999.; for (const auto& RecCollision : recCollisions) { if (!myEventSelections(RecCollision)) continue; - centrality = RecCollision.centFT0C(); + const int kCentFT0C = 0; + const int kCentFT0A = 1; + const int kCentFT0M = 2; + const int kCentFV0A = 3; + + if (centestimator == kCentFT0C) { + centrality = RecCollision.centFT0C(); + + } else if (centestimator == kCentFT0A) { + centrality = RecCollision.centFT0A(); + + } else if (centestimator == kCentFT0M) { + centrality = RecCollision.centFT0M(); + + } else if (centestimator == kCentFV0A) { + centrality = RecCollision.centFV0A(); + } + isSel = true; } if (isSel) { histos.fill(HIST("QAevent/hImpactParameterRec"), impactPar); histos.fill(HIST("QAevent/hImpactParvsCentrRec"), centrality, impactPar); + histos.fill(HIST("QAevent/hMultEta05Rec"), mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("QAevent/hMultEta05vsCentrRec"), centrality, mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("QAevent/hMultEta08Rec"), mcCollision.multMCNParticlesEta08()); + histos.fill(HIST("QAevent/hMultEta08vsCentrRec"), centrality, mcCollision.multMCNParticlesEta08()); } // Generated MC for (const auto& mcPart : mcParticles) { - const double kMaxRapidity = 0.5; - - if (std::abs(mcPart.y()) >= kMaxRapidity || std::abs(mcPart.pdgCode()) != o2::constants::physics::kPhi) + if (mcPart.y() < rapiditycut1 || mcPart.y() > rapiditycut2) + continue; + // select phi meson + if (std::abs(mcPart.pdgCode()) != o2::constants::physics::kPhi) continue; // signal loss estimation histos.fill(HIST("QAevent/phigenBeforeEvtSel"), mcPart.pt(), impactPar); + histos.fill(HIST("QAevent/hgendndetaVsMultEta05BeforeEvtSel"), mcPart.pt(), mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("QAevent/hgendndetaVsMultEta08BeforeEvtSel"), mcPart.pt(), mcCollision.multMCNParticlesEta08()); if (isSel) { // signal loss estimation histos.fill(HIST("QAevent/phigenAfterEvtSel"), mcPart.pt(), impactPar); + histos.fill(HIST("QAevent/hgendndetaVsMultEta05AfterEvtSel"), mcPart.pt(), mcCollision.multMCNParticlesEta05()); + histos.fill(HIST("QAevent/hgendndetaVsMultEta08AfterEvtSel"), mcPart.pt(), mcCollision.multMCNParticlesEta08()); } } // end loop on gen particles } PROCESS_SWITCH(phianalysisrun3_PbPb, processEvtLossSigLossMC, "Process Signal Loss, Event Loss", false); - void processFactors(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles) + void processEvtLossSigLossMC1(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& GenParticles) { - registry.fill(HIST("Factors/hGenEvents"), mcCollision.multMCNParticlesEta08(), 0.5); - - if (std::abs(mcCollision.posZ()) > selectionConfig.cfgCutVertex) + if (selectionConfig.cutvzgen && + std::abs(mcCollision.posZ()) > selectionConfig.cfgCutVertex) { return; - - registry.fill(HIST("Factors/hGenEvents"), mcCollision.multMCNParticlesEta08(), 1.5); - - float centrality = 100.5f; - for (auto const& collision : collisions) { - centrality = collision.centFT0M(); } - - registry.fill(HIST("Factors/hCentralityVsMultMC"), centrality, mcCollision.multMCNParticlesEta08()); - registry.fill(HIST("Factors/hNrecInGen"), collisions.size()); - - for (const auto& particle : mcParticles) { - - if (std::abs(particle.y()) > confRapidity) - continue; - - if (particle.pdgCode() == o2::constants::physics::kPhi) { - int dauSize = 2; - auto daughters = particle.daughters_as(); - if (daughters.size() != dauSize) - continue; - - auto daup = false; - auto daun = false; - - for (const auto& dau : daughters) { - if (dau.pdgCode() == PDG_t::kKPlus) { - daup = true; - d1 = ROOT::Math::PxPyPzMVector(dau.px(), dau.py(), dau.pz(), massKa); - } else if (dau.pdgCode() == PDG_t::kKMinus) { - daun = true; - d2 = ROOT::Math::PxPyPzMVector(dau.px(), dau.py(), dau.pz(), massKa); - } - } - if (!daup || !daun) - continue; - - mother = d1 + d2; - - registry.fill(HIST("Factors/h2dGenPhi"), centrality, mother.Pt()); - registry.fill(HIST("Factors/h3dGenPhiVsMultMCVsCentrality"), mcCollision.multMCNParticlesEta08(), centrality, mother.Pt()); - } - } - - if (collisions.size() == 0) + if (isApplyInelgt0 && !mcCollision.isInelGt0()) { return; + } - registry.fill(HIST("Factors/hGenEvents"), mcCollision.multMCNParticlesEta08(), 2.5); - } - PROCESS_SWITCH(phianalysisrun3_PbPb, processFactors, "Process Signal Loss, Event Loss", false); - void processEvtLossSigLossMC1(McCollisionMults::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& GenParticles) - { - if (std::abs(mcCollision.posZ()) > selectionConfig.cfgCutVertex) + if (isApplyTVX && !(mcCollision.multMCFT0C() > 0 && mcCollision.multMCFT0A() > 0)) { return; + } // All generated events histos.fill(HIST("MCEventHist"), 1); histos.fill(HIST("hImpactParameterGen1"), mcCollision.impactParameter()); @@ -2042,7 +2095,7 @@ struct phianalysisrun3_PbPb { } for (const auto& particle : GenParticles) { - if (std::abs(particle.y()) > confRapidity) + if (particle.y() < rapiditycut1 || particle.y() > rapiditycut2) continue; if (particle.pdgCode() != o2::constants::physics::kPhi) diff --git a/PWGLF/Tasks/Resonances/phipbpb.cxx b/PWGLF/Tasks/Resonances/phipbpb.cxx index 2468059b1de..87d75fc8a2a 100644 --- a/PWGLF/Tasks/Resonances/phipbpb.cxx +++ b/PWGLF/Tasks/Resonances/phipbpb.cxx @@ -93,7 +93,7 @@ struct phipbpb { Configurable fillSA{"fillSA", false, "fill spin alignment"}; // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Accepted maximum Centrality"}; + Configurable cfgCutCentrality{"cfgCutCentrality", 100.0f, "Accepted maximum Centrality"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 3000, "Occupancy cut"}; // track Configurable cqvas{"cqvas", false, "change q vectors after shift correction"}; @@ -198,6 +198,9 @@ struct phipbpb { AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; AxisSpec spAxis = {spNbins, lbinsp, hbinsp, "Sp"}; + histos.add("hImpactParameterVsEvrStatusGen", "hImpactParameterVsEvrStatusGen", HistType::kTH2F, {{200, 0.0, 20.0}, {5, 0.0, 5.0}}, true); + histos.add("hImpactParameterVsEvrStatusRec", "hImpactParameterVsEvrStatusRec", HistType::kTH3F, {{200, 0.0, 20.0}, {100, 0.0, 100.0}, {10, 0.0, 10.0}}, true); + histos.add("hINumRecCollisionVsEvrStatusRec", "hINumRecCollisionVsEvrStatusRec", HistType::kTH3F, {{21, -0.5, 20.5}, {100, 0.0, 100.0}, {10, 0.0, 10.0}}, true); if (fillv1) { histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); @@ -792,7 +795,7 @@ struct phipbpb { Npostrack = Npostrack + 1; } } - PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", true); + PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", false); void processSameEventv1(EventCandidatesv1::iterator const& collision, TrackCandidates const& /*tracks, aod::BCs const&*/, aod::BCsWithTimestamps const&) { @@ -1045,7 +1048,7 @@ struct phipbpb { } } } - PROCESS_SWITCH(phipbpb, processMEAcc, "Process ME Acceptance", true); + PROCESS_SWITCH(phipbpb, processMEAcc, "Process ME Acceptance", false); void processMEAccv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) { @@ -1303,7 +1306,7 @@ struct phipbpb { } } } - PROCESS_SWITCH(phipbpb, processMixedEventOpti, "Process Mixed event new", true); + PROCESS_SWITCH(phipbpb, processMixedEventOpti, "Process Mixed event new", false); void processMixedEventOptiv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) { @@ -1877,6 +1880,47 @@ struct phipbpb { } // process MC PROCESS_SWITCH(phipbpb, processMCPhiWeight, "Process MC Phi Weight", false); + + using McCollisionMults = soa::Join; + using EventCandidatesMC = soa::Join; + void processEvtLossMC(McCollisionMults::iterator const& mcCollision, const soa::SmallGroups& recCollisions) + { + auto impactPar = mcCollision.impactParameter(); + histos.fill(HIST("hImpactParameterVsEvrStatusGen"), impactPar, 0.5); + if (mcCollision.isInelGt0()) { + histos.fill(HIST("hImpactParameterVsEvrStatusGen"), impactPar, 1.5); + } + auto numberRecCollision = recCollisions.size(); + for (const auto& RecCollision : recCollisions) { + auto isTVX = RecCollision.selection_bit(o2::aod::evsel::kIsTriggerTVX); + auto vz = TMath::Abs(RecCollision.posZ()); + auto issel8 = RecCollision.sel8(); + auto isITSGoodLayer = RecCollision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + auto isGoodVtxzFT0vsPV = RecCollision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + auto isSameBunchPileup = RecCollision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + auto centrality = RecCollision.centFT0C(); + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 0.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 0.5); + if (isTVX) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 1.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 1.5); + } + if (isTVX && vz < 7) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 2.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 2.5); + } + if (isTVX && vz < 7 && issel8) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 3.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 3.5); + } + if (isTVX && vz < 7 && issel8 && isITSGoodLayer && isGoodVtxzFT0vsPV && isSameBunchPileup) { + histos.fill(HIST("hImpactParameterVsEvrStatusRec"), impactPar, centrality, 4.5); + histos.fill(HIST("hINumRecCollisionVsEvrStatusRec"), numberRecCollision, centrality, 4.5); + } + } + //} + } + PROCESS_SWITCH(phipbpb, processEvtLossMC, "Process to calculate Event Loss", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Resonances/phitutorial.cxx b/PWGLF/Tasks/Resonances/phitutorial.cxx index 5e93f7c39bc..705ead18669 100644 --- a/PWGLF/Tasks/Resonances/phitutorial.cxx +++ b/PWGLF/Tasks/Resonances/phitutorial.cxx @@ -16,7 +16,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGLF/Tasks/Resonances/phitutorial_step0.cxx b/PWGLF/Tasks/Resonances/phitutorial_step0.cxx index 16394389c91..475c18aa7ce 100644 --- a/PWGLF/Tasks/Resonances/phitutorial_step0.cxx +++ b/PWGLF/Tasks/Resonances/phitutorial_step0.cxx @@ -16,7 +16,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGLF/Tasks/Resonances/phitutorial_step1.cxx b/PWGLF/Tasks/Resonances/phitutorial_step1.cxx index 32b1760b809..0c679729e70 100644 --- a/PWGLF/Tasks/Resonances/phitutorial_step1.cxx +++ b/PWGLF/Tasks/Resonances/phitutorial_step1.cxx @@ -16,7 +16,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGLF/Tasks/Resonances/phitutorial_step2.cxx b/PWGLF/Tasks/Resonances/phitutorial_step2.cxx index 0a97f6d1afe..9bbd282d6c9 100644 --- a/PWGLF/Tasks/Resonances/phitutorial_step2.cxx +++ b/PWGLF/Tasks/Resonances/phitutorial_step2.cxx @@ -16,7 +16,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGLF/Tasks/Resonances/phitutorial_step3.cxx b/PWGLF/Tasks/Resonances/phitutorial_step3.cxx index 1ccf59aa9c2..34f4d8213a8 100644 --- a/PWGLF/Tasks/Resonances/phitutorial_step3.cxx +++ b/PWGLF/Tasks/Resonances/phitutorial_step3.cxx @@ -16,7 +16,8 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" diff --git a/PWGLF/Tasks/Resonances/rho770analysis.cxx b/PWGLF/Tasks/Resonances/rho770analysis.cxx index 48ba715031d..6715835c8ea 100644 --- a/PWGLF/Tasks/Resonances/rho770analysis.cxx +++ b/PWGLF/Tasks/Resonances/rho770analysis.cxx @@ -12,28 +12,42 @@ /// \file rho770analysis.cxx /// \brief rho(770)0 analysis in pp 13 & 13.6 TeV /// \author Hyunji Lim (hyunji.lim@cern.ch) -/// \since 03/12/2025 +/// \since 05/03/2026 #include "PWGLF/DataModel/LFResonanceTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "CommonConstants/PhysicsConstants.h" #include "DataFormatsParameters/GRPObject.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include -#include "TVector2.h" -#include +#include "Math/Vector4D.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; +using LorentzVectorPxPyPzMVector = ROOT::Math::PxPyPzMVector; +using LorentzVectorPxPyPzEVector = ROOT::Math::PxPyPzEVector; + +enum class TrackPIDMode : int { + TPCOrTOF = 0, + OnlyTPC = 1, + Combined = 2, + TPCWithTOFVeto = 3 +}; struct rho770analysis { SliceCache cache; @@ -43,13 +57,21 @@ struct rho770analysis { 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.15, "Maximum transverse DCA"}; - Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, "Maximum longitudinal DCA"}; Configurable cfgMaxTPC{"cfgMaxTPC", 5.0, "Maximum TPC PID with TOF"}; Configurable cfgMaxTOF{"cfgMaxTOF", 5.0, "Maximum TOF PID with TPC"}; Configurable cfgMinRap{"cfgMinRap", -0.5, "Minimum rapidity for pair"}; Configurable cfgMaxRap{"cfgMaxRap", 0.5, "Maximum rapidity for pair"}; + // DCA cuts + Configurable cDCAxyToPVAsPt{"cDCAxyToPVAsPt", true, "DCAxy to PV selection as pt"}; + Configurable cDCAzToPVAsPt{"cDCAzToPVAsPt", true, "DCAz to PV selection as pt"}; + Configurable cfgMaxDCAxyToPVcut{"cfgMaxDCAxyToPVcut", 0.10, "Maximum transverse DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 0.10, "Maximum longitudinal DCA"}; + Configurable cDCAxytoPVByPtPiFirstP0{"cDCAxytoPVByPtPiFirstP0", 0.0105, "Coeff. Track DCAxy cut to PV by pt for Pion First (p0)"}; + Configurable cDCAxyToPVByPtPiFirstExp{"cDCAxyToPVByPtPiFirstExp", 0.035, "Coeff. Track DCAxy cut to PV by pt for Pion First (exp)"}; + Configurable cDCAztoPVByPtPiFirstP0{"cDCAztoPVByPtPiFirstP0", 0.0105, "Coeff. Track DCAz cut to PV by pt for Pion First (p0)"}; + Configurable cDCAzToPVByPtPiFirstExp{"cDCAzToPVByPtPiFirstExp", 0.035, "Coeff. Track DCAz cut to PV by pt for Pion First (exp)"}; + // Track selection Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | @@ -62,24 +84,25 @@ struct rho770analysis { // kEtaRange) Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor Configurable cfgGlobalTrack{"cfgGlobalTrack", false, "Global track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; - Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; // refit is included in global track selection Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 1, "Number of TPC cluster"}; + Configurable cfgTPCRows{"cfgTPCRows", 70, "Minimum Number of TPC Crossed Rows "}; // PID Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 5.0, "TPC nSigma cut for Pion"}; // TPC Configurable cMaxTPCnSigmaPionnoTOF{"cMaxTPCnSigmaPionnoTOF", 2.0, "TPC nSigma cut for Pion in no TOF case"}; // TPC Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", 3.0, "Combined nSigma cut for Pion"}; - Configurable selectType{"selectType", 0, "PID selection type"}; + Configurable selectTypeInt{"selectTypeInt", static_cast(TrackPIDMode::OnlyTPC), "Pion PID selection mode: 0=TPCOrTOF, 1=OnlyTPC, 2=Combined, 3=TPCWithTOFVeto"}; // Axis ConfigurableAxis massAxis{"massAxis", {400, 0.2, 2.2}, "Invariant mass axis"}; ConfigurableAxis massK0sAxis{"massK0sAxis", {200, 0.46, 0.54}, "K0s Invariant mass axis"}; - ConfigurableAxis massKstarAxis{"massKstarAxis", {200, 0.7, 1.1}, "Kstar Invariant mass axis"}; + ConfigurableAxis massKstarAxis{"massKstarAxis", {200, 0.6, 1.3}, "Kstar 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"}; + 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, 85.0, 90.0, 95.0, 100.0, 105.0}, "Centrality Binning"}; void init(o2::framework::InitContext&) { @@ -99,6 +122,8 @@ struct rho770analysis { histos.add("hInvMass_Kstar_LSpp", "Kstar ++ invariant mass", {HistType::kTHnSparseF, {massKstarAxis, ptAxis, centAxis}}); histos.add("hInvMass_Kstar_LSmm", "Kstar -- invariant mass", {HistType::kTHnSparseF, {massKstarAxis, ptAxis, centAxis}}); + histos.add("QA/hMultiplicityPercent", "Multiplicity percentile of collision", HistType::kTH1F, {centAxis}); + histos.add("QA/Nsigma_TPC_BF", "", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); histos.add("QA/Nsigma_TOF_BF", "", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); histos.add("QA/TPC_TOF_BF", "", {HistType::kTH2F, {pidqaAxis, pidqaAxis}}); @@ -128,27 +153,39 @@ struct rho770analysis { { if (std::abs(track.pt()) < cfgMinPt) return false; - if (std::fabs(track.eta()) > cfgMaxEta) + if (std::abs(track.eta()) > cfgMaxEta) return false; - if (std::abs(track.dcaXY()) > cfgMaxDCArToPVcut) + if (cDCAxyToPVAsPt) { + if (std::abs(track.dcaXY()) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + return false; + } else { + if (std::abs(track.dcaXY()) > cfgMaxDCAxyToPVcut) + return false; + } + if (cDCAzToPVAsPt) { + if (std::abs(track.dcaZ()) > (cDCAztoPVByPtPiFirstP0 + cDCAzToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + return false; + } else { + if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) + return false; + } + if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; - if (std::abs(track.dcaZ()) > cfgMaxDCAzToPVcut) + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (track.tpcNClsFound() < cfgTPCcluster) + if (cfgPVContributor && !track.isPVContributor()) return false; - if (cfgHasTOF && !track.hasTOF()) + if (cfgGlobalTrack && !track.isGlobalTrack()) return false; if (cfgUseITSRefit && !track.passedITSRefit()) return false; if (cfgUseTPCRefit && !track.passedTPCRefit()) return false; - if (cfgPVContributor && !track.isPVContributor()) - return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) + if (cfgHasTOF && !track.hasTOF()) return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (track.tpcNClsFound() < cfgTPCcluster) return false; - if (cfgGlobalTrack && !track.isGlobalTrack()) + if (track.tpcNClsCrossedRows() < cfgTPCRows) return false; return true; @@ -157,19 +194,21 @@ struct rho770analysis { template bool selPion(const TrackType track) { - if (selectType == 0) { - if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) + const auto mode = static_cast(selectTypeInt.value); + + if (mode == TrackPIDMode::TPCOrTOF) { // TPC or TOF + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion && std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) return false; } - if (selectType == 1) { + if (mode == TrackPIDMode::OnlyTPC) { // only TPC if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion) return false; } - if (selectType == 2) { + if (mode == TrackPIDMode::Combined) { // combining if (track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi() >= nsigmaCutCombinedPion * nsigmaCutCombinedPion) return false; } - if (selectType == 3) { + if (mode == TrackPIDMode::TPCWithTOFVeto) { // TPC TOF veto if (track.hasTOF()) { if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) return false; @@ -184,19 +223,21 @@ struct rho770analysis { template bool selKaon(const TrackType track) { - if (selectType == 0) { - if (std::fabs(track.tpcNSigmaKa()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaKa()) >= cMaxTOFnSigmaPion) + const auto mode = static_cast(selectTypeInt.value); + + if (mode == TrackPIDMode::TPCOrTOF) { + if (std::fabs(track.tpcNSigmaKa()) >= cMaxTPCnSigmaPion && std::fabs(track.tofNSigmaKa()) >= cMaxTOFnSigmaPion) return false; } - if (selectType == 1) { + if (mode == TrackPIDMode::OnlyTPC) { if (std::fabs(track.tpcNSigmaKa()) >= cMaxTPCnSigmaPion) return false; } - if (selectType == 2) { + if (mode == TrackPIDMode::Combined) { if (track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa() >= nsigmaCutCombinedPion * nsigmaCutCombinedPion) return false; } - if (selectType == 3) { + if (mode == TrackPIDMode::TPCWithTOFVeto) { if (track.hasTOF()) { if (std::fabs(track.tpcNSigmaKa()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaKa()) >= cMaxTOFnSigmaPion) return false; @@ -208,10 +249,12 @@ struct rho770analysis { return true; } - template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks) + template + void fillHistograms(const CollisionType& /*collision*/, const CenMult& multiplicity, const TracksType& dTracks) { - TLorentzVector part1, part2, reco; + histos.fill(HIST("QA/hMultiplicityPercent"), multiplicity); + + LorentzVectorPxPyPzMVector part1, part2, reco; for (const auto& [trk1, trk2] : combinations(CombinationsUpperIndexPolicy(dTracks, dTracks))) { if (trk1.index() == trk2.index()) { @@ -232,51 +275,52 @@ struct rho770analysis { continue; if (selPion(trk1) && selPion(trk2)) { - part1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - part2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); + + part1 = LorentzVectorPxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); + part2 = LorentzVectorPxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); reco = part1 + part2; if (reco.Rapidity() > cfgMaxRap || reco.Rapidity() < cfgMinRap) continue; if (trk1.sign() * trk2.sign() < 0) { - histos.fill(HIST("hInvMass_rho770_US"), reco.M(), reco.Pt(), collision.cent()); - histos.fill(HIST("hInvMass_K0s_US"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_rho770_US"), reco.M(), reco.Pt(), multiplicity); + histos.fill(HIST("hInvMass_K0s_US"), reco.M(), reco.Pt(), multiplicity); if constexpr (IsMC) { if (trk1.motherId() != trk2.motherId()) continue; - if (std::abs(trk1.pdgCode()) == 211 && std::abs(trk2.pdgCode()) == 211) { - if (std::abs(trk1.motherPDG()) == 113) { - histos.fill(HIST("MCL/hpT_rho770_REC"), reco.M(), reco.Pt(), collision.cent()); - } else if (std::abs(trk1.motherPDG()) == 223) { - histos.fill(HIST("MCL/hpT_omega_REC"), reco.M(), reco.Pt(), collision.cent()); - } else if (std::abs(trk1.motherPDG()) == 310) { - histos.fill(HIST("MCL/hpT_K0s_REC"), reco.M(), reco.Pt(), collision.cent()); - histos.fill(HIST("MCL/hpT_K0s_pipi_REC"), reco.M(), reco.Pt(), collision.cent()); + if (std::abs(trk1.pdgCode()) == kPiPlus && std::abs(trk2.pdgCode()) == kPiPlus) { + if (std::abs(trk1.motherPDG()) == kRho770_0) { + histos.fill(HIST("MCL/hpT_rho770_REC"), reco.M(), reco.Pt(), multiplicity); + } else if (std::abs(trk1.motherPDG()) == kOmega) { + histos.fill(HIST("MCL/hpT_omega_REC"), reco.M(), reco.Pt(), multiplicity); + } else if (std::abs(trk1.motherPDG()) == kK0Short) { + histos.fill(HIST("MCL/hpT_K0s_REC"), reco.M(), reco.Pt(), multiplicity); + histos.fill(HIST("MCL/hpT_K0s_pipi_REC"), reco.M(), reco.Pt(), multiplicity); } - } else if ((std::abs(trk1.pdgCode()) == 211 && std::abs(trk2.pdgCode()) == 321) || (std::abs(trk1.pdgCode()) == 321 && std::abs(trk2.pdgCode()) == 211)) { - if (std::abs(trk1.motherPDG()) == 313) { - histos.fill(HIST("MCL/hpT_Kstar_REC"), reco.M(), reco.Pt(), collision.cent()); + } else if ((std::abs(trk1.pdgCode()) == kPiPlus && std::abs(trk2.pdgCode()) == kKPlus) || (std::abs(trk1.pdgCode()) == kKPlus && std::abs(trk2.pdgCode()) == kPiPlus)) { + if (std::abs(trk1.motherPDG()) == kK0Star892) { + histos.fill(HIST("MCL/hpT_Kstar_REC"), reco.M(), reco.Pt(), multiplicity); } } } } else if (trk1.sign() > 0 && trk2.sign() > 0) { - histos.fill(HIST("hInvMass_rho770_LSpp"), reco.M(), reco.Pt(), collision.cent()); - histos.fill(HIST("hInvMass_K0s_LSpp"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_rho770_LSpp"), reco.M(), reco.Pt(), multiplicity); + histos.fill(HIST("hInvMass_K0s_LSpp"), reco.M(), reco.Pt(), multiplicity); } else if (trk1.sign() < 0 && trk2.sign() < 0) { - histos.fill(HIST("hInvMass_rho770_LSmm"), reco.M(), reco.Pt(), collision.cent()); - histos.fill(HIST("hInvMass_K0s_LSmm"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_rho770_LSmm"), reco.M(), reco.Pt(), multiplicity); + histos.fill(HIST("hInvMass_K0s_LSmm"), reco.M(), reco.Pt(), multiplicity); } } if ((selPion(trk1) && selKaon(trk2)) || (selKaon(trk1) && selPion(trk2))) { if (selPion(trk1) && selKaon(trk2)) { - part1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - part2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + part1 = LorentzVectorPxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massPi); + part2 = LorentzVectorPxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massKa); } else if (selKaon(trk1) && selPion(trk2)) { - part1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); - part2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); + part1 = LorentzVectorPxPyPzMVector(trk1.px(), trk1.py(), trk1.pz(), massKa); + part2 = LorentzVectorPxPyPzMVector(trk2.px(), trk2.py(), trk2.pz(), massPi); } reco = part1 + part2; @@ -284,68 +328,113 @@ struct rho770analysis { continue; if (trk1.sign() * trk2.sign() < 0) { - histos.fill(HIST("hInvMass_Kstar_US"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_Kstar_US"), reco.M(), reco.Pt(), multiplicity); if constexpr (IsMC) { if (trk1.motherId() != trk2.motherId()) continue; - if ((std::abs(trk1.pdgCode()) == 211 && std::abs(trk2.pdgCode()) == 321) || (std::abs(trk1.pdgCode()) == 321 && std::abs(trk2.pdgCode()) == 211)) { - if (std::abs(trk1.motherPDG()) == 313) { - histos.fill(HIST("MCL/hpT_Kstar_Kpi_REC"), reco.M(), reco.Pt(), collision.cent()); + if ((std::abs(trk1.pdgCode()) == kPiPlus && std::abs(trk2.pdgCode()) == kKPlus) || (std::abs(trk1.pdgCode()) == kKPlus && std::abs(trk2.pdgCode()) == kPiPlus)) { + if (std::abs(trk1.motherPDG()) == kK0Star892) { + histos.fill(HIST("MCL/hpT_Kstar_Kpi_REC"), reco.M(), reco.Pt(), multiplicity); } } } } else if (trk1.sign() > 0 && trk2.sign() > 0) { - histos.fill(HIST("hInvMass_Kstar_LSpp"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_Kstar_LSpp"), reco.M(), reco.Pt(), multiplicity); } else if (trk1.sign() < 0 && trk2.sign() < 0) { - histos.fill(HIST("hInvMass_Kstar_LSmm"), reco.M(), reco.Pt(), collision.cent()); + histos.fill(HIST("hInvMass_Kstar_LSmm"), reco.M(), reco.Pt(), multiplicity); } } } } - void processData(aod::ResoCollision const& collision, aod::ResoTracks const& resotracks) + void processData(aod::ResoCollision const& resoCollision, + aod::ResoCollisionColls const& collisionIndex, + soa::Join const& collisions, + aod::ResoTracks const& resoTracks) { - fillHistograms(collision, resotracks); + auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); + auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision + + auto coll = collisions.iteratorAt(collId); // Take original collision matched with resoCollision + + if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + + auto multiplicity = resoCollision.cent(); + fillHistograms(resoCollision, multiplicity, resoTracks); } PROCESS_SWITCH(rho770analysis, processData, "Process Event for data", true); - void processMCLight(aod::ResoCollision const& collision, soa::Join const& resotracks) + void processMCLight(ResoMCCols::iterator const& resoCollision, + aod::ResoCollisionColls const& collisionIndex, + soa::Join const& collisionsMC, + soa::Join const& resoTracks, + soa::Join const&) { - fillHistograms(collision, resotracks); + auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); + auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision + + auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision + + if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + + auto mcColl = coll.mcCollision_as>(); + auto multiplicity = mcColl.centFT0M(); + + if (!resoCollision.isInAfterAllCuts()) + return; + + fillHistograms(resoCollision, multiplicity, resoTracks); } PROCESS_SWITCH(rho770analysis, processMCLight, "Process Event for MC", false); - void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents const& resoParents) + void processMCTrue(ResoMCCols::iterator const& resoCollision, + aod::ResoCollisionColls const& collisionIndex, + aod::ResoMCParents const& resoParents, + aod::ResoCollisionCandidatesMC const& collisionsMC, + soa::Join const&) { - auto multiplicity = collision.cent(); + auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); + auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision + + auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision + + if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + + auto mcColl = coll.mcCollision_as>(); + auto multiplicity = mcColl.centFT0M(); for (const auto& part : resoParents) { // loop over all pre-filtered MC particles - if (std::abs(part.pdgCode()) != 113) + if (std::abs(part.pdgCode()) != kRho770_0) + continue; + if (!part.isPhysicalPrimary()) continue; if (!part.producedByGenerator()) continue; if (part.y() < cfgMinRap || part.y() > cfgMaxRap) continue; - if (!(std::abs(part.daughterPDG1()) == 211 && std::abs(part.daughterPDG2()) == 211)) + if (!(std::abs(part.daughterPDG1()) == kPiPlus && std::abs(part.daughterPDG2()) == kPiPlus)) continue; - TLorentzVector truthpar; - truthpar.SetPxPyPzE(part.px(), part.py(), part.pz(), part.e()); + LorentzVectorPxPyPzEVector truthpar; + truthpar = LorentzVectorPxPyPzEVector(part.px(), part.py(), part.pz(), part.e()); auto mass = truthpar.M(); histos.fill(HIST("MCL/hpT_rho770_GEN"), 0, mass, part.pt(), multiplicity); - if (collision.isVtxIn10()) { + if (resoCollision.isVtxIn10()) { histos.fill(HIST("MCL/hpT_rho770_GEN"), 1, mass, part.pt(), multiplicity); } - if (collision.isVtxIn10() && collision.isInSel8()) { + if (resoCollision.isVtxIn10() && resoCollision.isInSel8()) { histos.fill(HIST("MCL/hpT_rho770_GEN"), 2, mass, part.pt(), multiplicity); } - if (collision.isVtxIn10() && collision.isTriggerTVX()) { + if (resoCollision.isVtxIn10() && resoCollision.isTriggerTVX()) { histos.fill(HIST("MCL/hpT_rho770_GEN"), 3, mass, part.pt(), multiplicity); } - if (collision.isInAfterAllCuts()) { + if (resoCollision.isInAfterAllCuts()) { histos.fill(HIST("MCL/hpT_rho770_GEN"), 4, mass, part.pt(), multiplicity); } } diff --git a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx index aa98e9fc9b7..64dd2ed25f9 100644 --- a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx +++ b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx @@ -13,7 +13,6 @@ /// \brief Reconstruction of Xi* resonance. /// /// \author Min-jae Kim , Bong-Hwi Lim -// #include #include "PWGLF/DataModel/LFResonanceTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" @@ -29,16 +28,20 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "Math/RotationZ.h" #include "Math/Vector4D.h" #include "TF1.h" #include "TRandom3.h" +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; using LorentzVectorPtEtaPhiMass = ROOT::Math::PtEtaPhiMVector; +using LorentzVectorSetXYZM = ROOT::Math::LorentzVector>; Service pdgDB; enum { @@ -67,235 +70,284 @@ struct Xi1530Analysisqa { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; using ResoMCCols = soa::Join; - Configurable cMassXiminus{"cMassXiminus", 1.32171, "Mass of Xi baryon"}; - // Associated with 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, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0, 110.0}, "Binning of the centrality axis"}; - - Configurable cInvMassStart{"cInvMassStart", 1.4, "Invariant mass start"}; - Configurable cInvMassEnd{"cInvMassEnd", 3.0, "Invariant mass end"}; - Configurable cInvMassBins{"cInvMassBins", 800, "Invariant mass binning"}; - - Configurable invMass1D{"invMass1D", true, "Invariant mass 1D"}; - Configurable studyAntiparticle{"studyAntiparticle", true, "Study anti-particles separately"}; - Configurable pidPlots{"pidPlots", true, "Make TPC and TOF PID plots"}; - Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + struct : ConfigurableGroup { + 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, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0, 101.0, 110.0}, "Binning of the centrality axis"}; + ConfigurableAxis multNTracksAxis{"multNTracksAxis", {500, 0, 500}, "N_{tracks}"}; + ConfigurableAxis impactParameterAxis{"impactParameterAxis", {500, 0, 50}, "IP (fm)"}; + + Configurable cInvMassStart{"cInvMassStart", 1.4, "Invariant mass start"}; + Configurable cInvMassEnd{"cInvMassEnd", 3.0, "Invariant mass end"}; + Configurable cInvMassBins{"cInvMassBins", 800, "Invariant mass binning"}; + + Configurable invMass1D{"invMass1D", true, "Invariant mass 1D"}; + Configurable pidPlots{"pidPlots", true, "Make TPC and TOF PID plots"}; + Configurable additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable truthQA{"truthQA", true, "Truth particle's QA plots"}; + Configurable multQA{"multQA", true, "Multiplicity QA after all cuts"}; + Configurable eventQA{"eventQA", true, "Event QA after all cuts"}; + } histoConfig; // Event Mixing - Configurable nEvtMixing{"nEvtMixing", 10, "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"}; + struct : ConfigurableGroup { + Configurable nEvtMixing{"nEvtMixing", 10, "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"}; + + } mixingConfig; //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// // Track selections (Except DCA selelctions) // - // Primary track selections - Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; - Configurable cMaxetacut{"cMaxetacut", 0.8, "Track maximum eta cut"}; + struct : ConfigurableGroup { + // Primary track selections + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; + Configurable cMaxetacut{"cMaxetacut", 0.8, "Track maximum eta cut"}; - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; - Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; + Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; - Configurable tofAtHighPt{"tofAtHighPt", false, "Use TOF at high pT"}; - Configurable cfgTPCcluster{"cfgTPCcluster", 1, "Minimum Number of TPC cluster"}; // Minmimum + Configurable cfgTPCcluster{"cfgTPCcluster", 1, "Minimum Number of TPC cluster"}; // Minmimum - Configurable cfgTPCRows{"cfgTPCRows", 80, "Minimum Number of TPC Crossed Rows "}; - Configurable cfgRatioTPCRowsOverFindableCls{"cfgRatioTPCRowsOverFindableCls", 0.8, "Minimum of TPC Crossed Rows to Findable Clusters"}; // Minmimum + Configurable cfgTPCRows{"cfgTPCRows", 80, "Minimum Number of TPC Crossed Rows "}; - // Configurable cfgUseTPCRefit{"cfgUseTPCRefit", true, "Require TPC Refit"}; //refit is included in global track selection - // Configurable cfgUseITSRefit{"cfgUseITSRefit", true, "Require ITS Refit"}; + Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; - Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + Configurable cfgRapidityMinCut{"cfgRapidityMinCut", -0.5, "Rapidity cut for tracks"}; + Configurable cfgRapidityMaxCut{"cfgRapidityMaxCut", 0.5, "Rapidity cut for tracks"}; - Configurable cfgRapidityCut{"cfgRapidityCut", 0.5, "Rapidity cut for tracks"}; + // Primary track DCAxy to PV + ConfigurableAxis cDCAtoPVBins{"cDCAtoPVBins", {1500, 0, 0.3}, "Bins for track DCA to PV"}; - //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// + Configurable cDCAxytoPVByPtPiFirstP0{"cDCAxytoPVByPtPiFirstP0", 0.004, "Coeff. Track DCAxy cut to PV by pt for Pion First (p0)"}; + Configurable cDCAxyToPVByPtPiFirstExp{"cDCAxyToPVByPtPiFirstExp", 0.013, "Coeff. Track DCAxy cut to PV by pt for Pion First (exp)"}; - // Cascade and V0 selections // + Configurable cDCAxyToPVAsPtForCasc{"cDCAxyToPVAsPtForCasc", true, "Set DCAxy to PV selection as pt cut"}; + Configurable cDCAxyToPVByPtCascP0{"cDCAxyToPVByPtCascP0", 999., "Coeff. for Track DCAxy cut to PV by pt for Cascade (p0)"}; + Configurable cDCAxyToPVByPtCascExp{"cDCAxyToPVByPtCascExp", 1., "Coeff. Track DCAxy cut to PV by pt for Cascade (exp)"}; - // Primary track DCAxy to PV - Configurable cDCAxytoPVByPtPiFirstP0{"cDCAxytoPVByPtPiFirstP0", 0.004, "Coeff. Track DCAxy cut to PV by pt for Pion First (p0)"}; - Configurable cDCAxyToPVByPtPiFirstExp{"cDCAxyToPVByPtPiFirstExp", 0.013, "Coeff. Track DCAxy cut to PV by pt for Pion First (exp)"}; + // Primary track DCAz to PV + Configurable cDCAzToPVAsPt{"cDCAzToPVAsPt", true, "DCAz to PV selection as pt"}; + Configurable cDCAzToPVAsPtForCasc{"cDCAzToPVAsPtForCasc", true, "Set DCA to PV selection as pt cut"}; + Configurable cMaxDCAzToPVCut{"cMaxDCAzToPVCut", 0.5, "Track DCAz cut to PV Maximum"}; + Configurable cMaxDCAzToPVCutCasc{"cMaxDCAzToPVCutCasc", 0.5, "Track DCAz cut to PV Maximum for casc"}; - Configurable cDCAxyToPVAsPtForCasc{"cDCAxyToPVAsPtForCasc", true, "Set DCAxy to PV selection as pt cut"}; - Configurable cDCAxyToPVByPtCascP0{"cDCAxyToPVByPtCascP0", 999., "Coeff. for Track DCAxy cut to PV by pt for Cascade (p0)"}; - Configurable cDCAxyToPVByPtCascExp{"cDCAxyToPVByPtCascExp", 1., "Coeff. Track DCAxy cut to PV by pt for Cascade (exp)"}; + } primarytrackConfig; - // Primary track DCAz to PV - Configurable cDCAzToPVAsPt{"cDCAzToPVAsPt", true, "DCAz to PV selection as pt"}; - Configurable cDCAzToPVAsPtForCasc{"cDCAzToPVAsPtForCasc", true, "Set DCA to PV selection as pt cut"}; - Configurable cMaxDCAzToPVCut{"cMaxDCAzToPVCut", 0.5, "Track DCAz cut to PV Maximum"}; - Configurable cMaxDCAzToPVCutCasc{"cMaxDCAzToPVCutCasc", 0.5, "Track DCAz cut to PV Maximum for casc"}; + //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// - // Topological selections for V0 - Configurable cDCALambdaDaugtherscut{"cDCALambdaDaugtherscut", 0.7, "Lambda dauthers DCA cut"}; - Configurable cDCALambdaToPVcut{"cDCALambdaToPVcut", 0.02, "Lambda DCA cut to PV"}; - Configurable cDCAPionToPVcut{"cDCAPionToPVcut", 0.06, "pion DCA cut to PV"}; - Configurable cDCAProtonToPVcut{"cDCAProtonToPVcut", 0.07, "proton DCA cut to PV"}; + // Cascade and V0 selections // - Configurable cV0CosPACutPtDepP0{"cV0CosPACutPtDepP0", 0.25, "Coeff. for Cosine Pointing angle for V0 as pt (p0)"}; - Configurable cV0CosPACutPtDepP1{"cV0CosPACutPtDepP1", 0.022, "Coeff. for Cosine Pointing angle for V0 as pt (p1)"}; + struct : ConfigurableGroup { + // Topological selections for V0s + ConfigurableAxis cDCADaughtersBins{"cDCADaughtersBins", {1000, 0, 0.1}, "Bins for DCA to daughters"}; + ConfigurableAxis cTransRadiusBins{"cTransRadiusBins", {500, 0, 100}, "Bins for transverse radius"}; + Configurable cDCALambdaDaugtherscut{"cDCALambdaDaugtherscut", 0.7, "Lambda dauthers DCA cut"}; + Configurable cDCALambdaToPVcut{"cDCALambdaToPVcut", 0.02, "Lambda DCA cut to PV"}; + Configurable cDCAPionToPVcut{"cDCAPionToPVcut", 0.06, "pion DCA cut to PV"}; + Configurable cDCAProtonToPVcut{"cDCAProtonToPVcut", 0.07, "proton DCA cut to PV"}; + + Configurable cV0CosPACutPtDepP0{"cV0CosPACutPtDepP0", 0.25, "Coeff. for Cosine Pointing angle for V0 as pt (p0)"}; + Configurable cV0CosPACutPtDepP1{"cV0CosPACutPtDepP1", 0.022, "Coeff. for Cosine Pointing angle for V0 as pt (p1)"}; + + Configurable cMaxV0radiuscut{"cMaxV0radiuscut", 200., "V0 radius cut Maximum"}; + Configurable cMinV0radiuscut{"cMinV0radiuscut", 2.5, "V0 radius cut Minimum"}; + Configurable cMasswindowV0cut{"cMasswindowV0cut", 0.005, "V0 Mass window cut"}; + + } v0sConfig; + + struct : ConfigurableGroup { + // Topological selections for Cascades + ConfigurableAxis cDCASecondaryBins{"cDCASecondaryBins", {1000, 0, 0.1}, "Bins for DCA to Cascade secondary"}; + ConfigurableAxis cProperLifetimeBins{"cProperLifetimeBins", {300, 0, 30}, "Bins for proper lifetime"}; + ConfigurableAxis cDCABachelorToPVBins{"cDCABachelorToPVcutBins", {1000, 0, 0.1}, "Bins for DCA bachelor to PV cut"}; + Configurable cDCABachlorToPVcut{"cDCABachlorToPVcut", 0.06, "Bachelor DCA cut to PV"}; + Configurable cDCAXiDaugthersCutPtRangeLower{"cDCAXiDaugthersCutPtRangeLower", 1., "Xi- DCA cut to PV as pt range lower"}; + Configurable cDCAXiDaugthersCutPtRangeUpper{"cDCAXiDaugthersCutPtRangeUpper", 4., "Xi- DCA cut to PV as pt range upper"}; + Configurable cDCAXiDaugthersCutPtDepLower{"cDCAXiDaugthersCutPtDepLower", 0.8, "Xi- DCA cut to PV as pt Under 1 GeV/c"}; + Configurable cDCAXiDaugthersCutPtDepMiddle{"cDCAXiDaugthersCutPtDepMiddle", 0.5, "Xi- DCA cut to PV as pt 1 - 4 GeV/c"}; + Configurable cDCAXiDaugthersCutPtDepUpper{"cDCAXiDaugthersCutPtDepUpper", 0.2, "Xi- DCA cut to PV as pt Over 4 GeV/c"}; + + ConfigurableAxis cCosPABins{"cCosPABins", {3000, 0, 0.06}, "Bins for Cosine Pointing Angle"}; + Configurable cCosPACascCutPtDepP0{"cCosPACascCutPtDepP0", 0.2, "Coeff. for Cosine Pointing angle for Cascade as pt (p0)"}; + Configurable cCosPACascCutPtDepP1{"cCosPACascCutPtDepP1", 0.022, "Coeff. for Cosine Pointing angle for Cascade as pt (p1)"}; + + Configurable cMaxCascradiuscut{"cMaxCascradiuscut", 200., "Cascade radius cut Maximum"}; + Configurable cMinCascradiuscut{"cMinCascradiuscut", 1.1, "Cascade radius cut Minimum"}; + Configurable cMasswindowCasccut{"cMasswindowCasccut", 0.008, "Cascade Mass window cut"}; + Configurable cMassXiminus{"cMassXiminus", 1.32171, "Mass of Xi baryon"}; + + Configurable cMaxProperLifetimeCut{"cMaxProperLifetimeCut", 4.7, "Maximum proper lifetime cut for Xi- candidates"}; + + } cascadeConfig; - Configurable cMaxV0radiuscut{"cMaxV0radiuscut", 200., "V0 radius cut Maximum"}; - Configurable cMinV0radiuscut{"cMinV0radiuscut", 2.5, "V0 radius cut Minimum"}; - Configurable cMasswindowV0cut{"cMasswindowV0cut", 0.005, "V0 Mass window cut"}; + //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// - // Topological selections for Cascade + // PID Selections// - Configurable cDCABachlorToPVcut{"cDCABachlorToPVcut", 0.06, "Bachelor DCA cut to PV"}; - Configurable cDCAXiDaugthersCutPtRangeLower{"cDCAXiDaugthersCutPtRangeLower", 1., "Xi- DCA cut to PV as pt range lower"}; - Configurable cDCAXiDaugthersCutPtRangeUpper{"cDCAXiDaugthersCutPtRangeUpper", 4., "Xi- DCA cut to PV as pt range upper"}; - Configurable cDCAXiDaugthersCutPtDepLower{"cDCAXiDaugthersCutPtDepLower", 0.8, "Xi- DCA cut to PV as pt Under 1 GeV/c"}; - Configurable cDCAXiDaugthersCutPtDepMiddle{"cDCAXiDaugthersCutPtDepMiddle", 0.5, "Xi- DCA cut to PV as pt 1 - 4 GeV/c"}; - Configurable cDCAXiDaugthersCutPtDepUpper{"cDCAXiDaugthersCutPtDepUpper", 0.2, "Xi- DCA cut to PV as pt Over 4 GeV/c"}; + struct : ConfigurableGroup { - Configurable cCosPACascCutPtDepP0{"cCosPACascCutPtDepP0", 0.2, "Coeff. for Cosine Pointing angle for Cascade as pt (p0)"}; - Configurable cCosPACascCutPtDepP1{"cCosPACascCutPtDepP1", 0.022, "Coeff. for Cosine Pointing angle for Cascade as pt (p1)"}; + // Genenral selections + Configurable cPIDBound{"cPIDBound", 6.349, "configurable for replacing to .has"}; + ConfigurableAxis cPIDnSigmaBins{"cPIDnSigmaBins", {131, -6.5, 6.5}, "Bins for nSigma PID"}; - Configurable cMaxCascradiuscut{"cMaxCascradiuscut", 200., "Cascade radius cut Maximum"}; - Configurable cMinCascradiuscut{"cMinCascradiuscut", 1.1, "Cascade radius cut Minimum"}; - Configurable cMasswindowCasccut{"cMasswindowCasccut", 0.008, "Cascade Mass window cut"}; + Configurable tofAtHighPt{"tofAtHighPt", false, "Use TOF at high pT"}; + Configurable cMinTOFpt{"cMinTOFpt", 0.5, "Maximum TOF pt cut"}; - //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// + // PID Selections for Pion First + Configurable cMaxtpcnSigmaPionFirst{"cMaxtpcnSigmaPionFirst", 4.0, "TPC nSigma cut for Pion First"}; + Configurable cMaxtofnSigmaPionFirst{"cMaxtofnSigmaPionFirst", 3.0, "TOF nSigma cut for Pion First"}; - // PID Selections// + Configurable nsigmaCutCombinedPionFirst{"nsigmaCutCombinedPionFirst", -4.0, "Combined nSigma cut for Pion First"}; - Configurable cPIDBound{"cPIDBound", 6.349, "configurable for replacing to .has"}; + Configurable cUseOnlyTOFTrackPionFirst{"cUseOnlyTOFTrackPionFirst", false, "Use only TOF track for PID selection Pion First"}; + Configurable cByPassTOFPionFirst{"cByPassTOFPionFirst", true, "By pass TOF Pion First PID selection"}; - Configurable cMinTOFpt{"cMinTOFpt", 0.5, "Maximum TOF pt cut"}; + // PID Selections for Pion Bachelor + Configurable cMaxtpcnSigmaPionBachelor{"cMaxtpcnSigmaPionBachelor", 4.0, "TPC nSigma cut for Pion Bachelor"}; + Configurable cMaxtofnSigmaPionBachelor{"cMaxtofnSigmaPionBachelor", 3.0, "TOF nSigma cut for Pion Bachelor"}; - // PID Selections for Pion First - Configurable cMaxtpcnSigmaPionFirst{"cMaxtpcnSigmaPionFirst", 4.0, "TPC nSigma cut for Pion First"}; - Configurable cMaxtofnSigmaPionFirst{"cMaxtofnSigmaPionFirst", 3.0, "TOF nSigma cut for Pion First"}; + Configurable nsigmaCutCombinedPionBachelor{"nsigmaCutCombinedPionBachelor", -4.0, "Combined nSigma cut for Pion Bachelor"}; - Configurable nsigmaCutCombinedPionFirst{"nsigmaCutCombinedPionFirst", -4.0, "Combined nSigma cut for Pion First"}; + Configurable cUseOnlyTOFTrackPionBachelor{"cUseOnlyTOFTrackPionBachelor", false, "Use only TOF track for PID selection Pion Bachelor"}; + Configurable cByPassTOFPionBachelor{"cByPassTOFPionBachelor", true, "By pass TOF Pion Bachelor PID selection"}; - Configurable cUseOnlyTOFTrackPionFirst{"cUseOnlyTOFTrackPionFirst", false, "Use only TOF track for PID selection Pion First"}; - Configurable cByPassTOFPionFirst{"cByPassTOFPionFirst", true, "By pass TOF Pion First PID selection"}; + // PID Selections for Pion + Configurable cMaxtpcnSigmaPion{"cMaxtpcnSigmaPion", 4.0, "TPC nSigma cut for Pion"}; + Configurable cMaxtofnSigmaPion{"cMaxtofnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; - // PID Selections for Pion Bachelor - Configurable cMaxtpcnSigmaPionBachelor{"cMaxtpcnSigmaPionBachelor", 4.0, "TPC nSigma cut for Pion Bachelor"}; - Configurable cMaxtofnSigmaPionBachelor{"cMaxtofnSigmaPionBachelor", 3.0, "TOF nSigma cut for Pion Bachelor"}; + Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -4.0, "Combined nSigma cut for Pion"}; - Configurable nsigmaCutCombinedPionBachelor{"nsigmaCutCombinedPionBachelor", -4.0, "Combined nSigma cut for Pion Bachelor"}; + Configurable cUseOnlyTOFTrackPion{"cUseOnlyTOFTrackPion", false, "Use only TOF track for PID selection Pion"}; + Configurable cByPassTOFPion{"cByPassTOFPion", true, "By pass TOF Pion PID selection"}; - Configurable cUseOnlyTOFTrackPionBachelor{"cUseOnlyTOFTrackPionBachelor", false, "Use only TOF track for PID selection Pion Bachelor"}; - Configurable cByPassTOFPionBachelor{"cByPassTOFPionBachelor", true, "By pass TOF Pion Bachelor PID selection"}; + // PID Selections for Proton + Configurable cMaxtpcnSigmaProton{"cMaxtpcnSigmaProton", 4.0, "TPC nSigma cut for Proton"}; + Configurable cMaxtofnSigmaProton{"cMaxtofnSigmaProton", 3.0, "TOF nSigma cut for Proton"}; - // PID Selections for Pion - Configurable cMaxtpcnSigmaPion{"cMaxtpcnSigmaPion", 4.0, "TPC nSigma cut for Pion"}; - Configurable cMaxtofnSigmaPion{"cMaxtofnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; + Configurable nsigmaCutCombinedProton{"nsigmaCutCombinedProton", -4.0, "Combined nSigma cut for Proton"}; - Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -4.0, "Combined nSigma cut for Pion"}; + Configurable cUseOnlyTOFTrackProton{"cUseOnlyTOFTrackProton", false, "Use only TOF track for PID selection Proton"}; + Configurable cByPassTOFProton{"cByPassTOFProton", true, "By pass TOF Proton PID selection"}; - Configurable cUseOnlyTOFTrackPion{"cUseOnlyTOFTrackPion", false, "Use only TOF track for PID selection Pion"}; - Configurable cByPassTOFPion{"cByPassTOFPion", true, "By pass TOF Pion PID selection"}; + } pidConfig; - // PID Selections for Proton - Configurable cMaxtpcnSigmaProton{"cMaxtpcnSigmaProton", 4.0, "TPC nSigma cut for Proton"}; - Configurable cMaxtofnSigmaProton{"cMaxtofnSigmaProton", 3.0, "TOF nSigma cut for Proton"}; + //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// - Configurable nsigmaCutCombinedProton{"nsigmaCutCombinedProton", -4.0, "Combined nSigma cut for Proton"}; + struct : ConfigurableGroup { - Configurable cUseOnlyTOFTrackProton{"cUseOnlyTOFTrackProton", false, "Use only TOF track for PID selection Proton"}; - Configurable cByPassTOFProton{"cByPassTOFProton", true, "By pass TOF Proton PID selection"}; + // MC Event selection // + Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; + // Cuts on mother particle and others - //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// + Configurable cfgCutsOnMother{"cfgCutsOnMother", true, "Enamble additional cuts on mother"}; + Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 9.0, "Maximum pt of mother cut"}; + Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 3.0, "Maximum Minv of mother cut"}; - // MC Event selection // - Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; + Configurable studyStableXi{"studyStableXi", false, "Study stable Xi"}; - //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// + Configurable cMultNTracksPVFull{"cMultNTracksPVFull", false, "Use full PV track multiplicity"}; + Configurable cMultNTracksPVeta1{"cMultNTracksPVeta1", false, "Use PV track multiplicity within |eta|<1"}; + Configurable cMultNTracksPVetaHalf{"cMultNTracksPVetaHalf", true, "Use PV track multiplicity within |eta|<0.5"}; + + Configurable cRecoINELgt0{"cRecoINELgt0", true, "check if INEL>0 for reco events"}; - // Cuts on mother particle and others - Configurable cfgCutsOnMother{"cfgCutsOnMother", true, "Enamble additional cuts on mother"}; - Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 9.0, "Maximum pt of mother cut"}; - Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 3.0, "Maximum Minv of mother cut"}; + Configurable cUseFixedMassXi{"cUseFixedMassXi", false, "Use fixed mass for Xi-"}; + Configurable cUseTruthRapidity{"cUseTruthRapidity", false, "Use truth rapidity for Xi*"}; - Configurable studyStableXi{"studyStableXi", false, "Study stable Xi"}; + Configurable cConsiderPairOnly{"cConsiderPairOnly", true, "Consider only existing particle pairs in the event"}; + + Configurable cfgFillRotBkg{"cfgFillRotBkg", true, "Fill rotated background"}; + Configurable cfgMinRot{"cfgMinRot", 5.0 * constants::math::PI / 6.0, "Minimum of rotation"}; + Configurable cfgMaxRot{"cfgMaxRot", 7.0 * constants::math::PI / 6.0, "Maximum of rotation"}; + Configurable cfgRotPion{"cfgRotPion", true, "Rotate pion"}; + Configurable cfgNrotBkg{"cfgNrotBkg", 4, "Number of rotated copies (background) per each original candidate"}; + } additionalConfig; - Configurable cMCCent{"cMCCent", true, "Using calibrated MC centrality (for FT0M)"}; - Configurable cRecoINELgt0{"cRecoINELgt0", true, "check if INEL>0 for reco events"}; TRandom* rn = new TRandom(); //*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*//*// struct PidSelectionParam { - double cMaxTPCnSigma; - double cMaxTOFnSigma; + float cMaxTPCnSigma; + float cMaxTOFnSigma; bool cByPassTOF; - double nsigmaCutCombined; + float nsigmaCutCombined; }; void init(o2::framework::InitContext&) { - AxisSpec centAxis = {binsCent, "FT0M (%)"}; - AxisSpec dcaxyAxis = {1500, 0.0, 0.3, "DCA_{#it{xy}} (cm)"}; - AxisSpec dcazAxis = {1500, 0.0, 0.3, "DCA_{#it{z}} (cm)"}; - AxisSpec dcaDaugAxis = {1000, 0.0, 1, "DCA_{#it{Daughter}} (cm)"}; - AxisSpec cosPAAxis = {3000, 0.0, 0.06, "1-cos(PA)"}; + AxisSpec centAxis = {histoConfig.binsCent, "FT0M (%)"}; + AxisSpec dcaxyAxis = {primarytrackConfig.cDCAtoPVBins, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {primarytrackConfig.cDCAtoPVBins, "DCA_{#it{z}} (cm)"}; + AxisSpec dcaSecondaryAxis = {cascadeConfig.cDCASecondaryBins, "DCA_{#it{Secondary}} (cm)"}; + AxisSpec dcaBachAxis = {cascadeConfig.cDCABachelorToPVBins, "DCA_{#it{Bach}} (cm)"}; + AxisSpec dcaDaugAxis = {v0sConfig.cDCADaughtersBins, "DCA_{#it{Daughter}} (cm)"}; + AxisSpec cosPAAxis = {cascadeConfig.cCosPABins, "1-cos(PA)"}; + AxisSpec properLifetimeAxis = {cascadeConfig.cProperLifetimeBins, "Proper lifetime (fm/c)"}; AxisSpec mcLabelAxis = {6, -1.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 invMassAxisCasc = {800, 1.25, 1.65, "Invariant Mass for Casc. (GeV/#it{c}^2)"}; - AxisSpec pidQAAxis = {65, -6.5, 6.5}; + AxisSpec ptAxis = {histoConfig.binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisQA = {histoConfig.binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invMassAxis = {histoConfig.cInvMassBins, histoConfig.cInvMassStart, histoConfig.cInvMassEnd, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec invMassAxisCasc = {400, 1.121, 1.521, "Invariant Mass for Casc. (GeV/#it{c}^2)"}; + AxisSpec invMassAxisLambda = {400, 0.921, 1.321, "Invariant Mass for Lambda (GeV/#it{c}^2)"}; + AxisSpec transRadiusAxis = {v0sConfig.cTransRadiusBins, "Transverse radius (cm)"}; + AxisSpec pidQAAxis = {pidConfig.cPIDnSigmaBins, "nSigma PID"}; AxisSpec flagAxis = {9, 0, 9, "Flags"}; - { - // 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}}); + if (histoConfig.multQA) { + // multiplicity histograms + histos.add("multQA/h2MultCent", "Multiplicity vs Centrality", HistType::kTH2F, {centAxis, histoConfig.multNTracksAxis}); + histos.add("multQA/h2MultCentMC", "Multiplicity vs Centrality MC", HistType::kTH2F, {centAxis, histoConfig.multNTracksAxis}); + } + + // event histograms + if (histoConfig.eventQA) { + histos.add("QAevent/hCollisionIndexSameE", "coll index sameE", HistType::kTH1F, {{500, 0.0f, 500.0f}}); + histos.add("QAevent/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("QAevent/hnTrksSameE", "n tracks per event SameE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); + histos.add("QAevent/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}}); + histos.add("QAevent/hnCascsSameE", "n cascs per event SameE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); + histos.add("QAevent/hnCascsMixedE", "n cascs per event MixedE", HistType::kTH1F, {{1000, 0.0f, 1000.0f}}); - // 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, {centAxis}); - 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, {centAxis}); + + histos.add("QAevent/hRotBkg", "Rotated angle of rotated background", HistType::kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); } - if (invMass1D) { + if (histoConfig.invMass1D) { histos.add("Xi1530invmassDS", "Invariant mass of Xi(1530)0 differnt sign", kTH1F, {invMassAxis}); histos.add("Xi1530invmassLS", "Invariant mass of Xi(1530)0 like sign", kTH1F, {invMassAxis}); - histos.add("Xi1530invmassME", "Invariant mass of Xi(1530)0 mixed event", kTH1F, {invMassAxis}); - - if (studyAntiparticle) { - histos.add("Xi1530invmassDSAnti", "Invariant mass of Anti-Xi(1530)0 differnt sign", kTH1F, {invMassAxis}); - histos.add("Xi1530invmassLSAnti", "Invariant mass of Anti-Xi(1530)0 like sign", kTH1F, {invMassAxis}); - } - } - if (doprocessMEDF || doprocessMEMicro) { - histos.add("Xi1530invmassME_DS", "Invariant mass of Xi(1530)0 mixed event DS", kTH1F, {invMassAxis}); - histos.add("Xi1530invmassME_DSAnti", "Invariant mass of Xi(1530)0 mixed event DSAnti", kTH1F, {invMassAxis}); + histos.add("Xi1530invmassDSAnti", "Invariant mass of Anti-Xi(1530)0 differnt sign", kTH1F, {invMassAxis}); + histos.add("Xi1530invmassLSAnti", "Invariant mass of Anti-Xi(1530)0 like sign", kTH1F, {invMassAxis}); } - // DCA QA to candidates for first pion and Xi- - histos.add("QAbefore/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); - histos.add("QAbefore/trkDCAxy_Xi", "DCAxy distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); + if (histoConfig.additionalQAplots) { + // DCA QA to candidates for first pion and Xi- + histos.add("QAbefore/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); + histos.add("QAbefore/trkDCAxy_Xi", "DCAxy distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); - histos.add("QAbefore/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); - histos.add("QAbefore/trkDCAz_Xi", "DCAz distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); + histos.add("QAbefore/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); + histos.add("QAbefore/trkDCAz_Xi", "DCAz distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); - histos.add("QAafter/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); - histos.add("QAafter/trkDCAxy_Xi", "DCAxy distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); + histos.add("QAafter/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); + histos.add("QAafter/trkDCAxy_Xi", "DCAxy distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcaxyAxis}); - histos.add("QAafter/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); - histos.add("QAafter/trkDCAz_Xi", "DCAz distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); + histos.add("QAafter/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); + histos.add("QAafter/trkDCAz_Xi", "DCAz distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); + } - if (pidPlots) { + if (histoConfig.pidPlots) { // Plots for QA before, Need to pt info. for the daugthers histos.add("QAbefore/TOF_TPC_Map_pi_first_all", "TOF + TPC Combined PID for Pion_{First};#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); histos.add("QAbefore/TOF_Nsigma_pi_first_all", "TOF NSigma for Pion_{First};#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); @@ -342,25 +394,17 @@ struct Xi1530Analysisqa { histos.add("h3XiinvmassDS", "Invariant mass of Xi- differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); histos.add("h3Xi1530invmassLS", "Invariant mass of Xi(1530)0 same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3XiinvmassLS", "Invariant mass of Xi- same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); + histos.add("h3Xi1530invmassRotDS", "Invariant mass of Xi(1530)0 rotated DS", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3Xi1530invmassME", "Invariant mass of Xi(1530)0 mixed event", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3XiinvmassME", "Invariant mass of Xi- mixed event", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); + histos.add("h3Xi1530invmassDSAnti", "Invariant mass of Anti-Xi(1530)0 differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); + histos.add("h3XiinvmassDSAnti", "Invariant mass of Anti-Xi- differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); - if (studyAntiparticle) { - histos.add("h3Xi1530invmassDSAnti", "Invariant mass of Anti-Xi(1530)0 differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3XiinvmassDSAnti", "Invariant mass of Anti-Xi- differnt sign", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); - - histos.add("h3Xi1530invmassLSAnti", "Invariant mass of Anti-Xi(1530)0 same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3XiinvmassLSAnti", "Invariant mass of Anti-Xi- same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); - } + histos.add("h3Xi1530invmassLSAnti", "Invariant mass of Anti-Xi(1530)0 same sign", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); + histos.add("h3Xi1530invmassRotDSAnti", "Invariant mass of Anti-Xi(1530)0 rotated DS", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); if (doprocessMEDF || doprocessMEMicro) { histos.add("h3Xi1530invmassME_DS", "Invariant mass of Xi(1530)0 mixed event DS", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3XiinvmassME_DS", "Invariant mass of Xi- mixed event DS", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); - histos.add("h3Xi1530invmassME_DSAnti", "Invariant mass of Xi(1530)0 mixed event DSAnti", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3XiinvmassME_DSAnti", "Invariant mass of Xi- mixed event DSAnti", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); } if (doprocessMC) { @@ -371,7 +415,7 @@ struct Xi1530Analysisqa { histos.add("QAMCTrue/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); histos.add("QAMCTrue/trkDCAz_xi", "DCAz distribution of Xi- track candidates", HistType::kTH2F, {ptAxis, dcazAxis}); - if (pidPlots) { + if (histoConfig.pidPlots) { histos.add("QAMCTrue/TOF_TPC_Map_pi_first_all", "TOF + TPC Combined PID for Pion_{First};#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); histos.add("QAMCTrue/TOF_Nsigma_pi_first_all", "TOF NSigma for Pion_{First};#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); histos.add("QAMCTrue/TPC_Nsigma_pi_first_all", "TPC NSigma for Pion_{First};#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); @@ -392,108 +436,128 @@ struct Xi1530Analysisqa { histos.add("QAMCTrue/TPC_Nsigma_piminus_all", "TPC NSigma for Pion -;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH3F, {centAxis, ptAxisQA, pidQAAxis}}); } - histos.add("h3RecXi1530invmass", "Invariant mass of Reconstructed MC Xi(1530)0", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3RecXiinvmass", "Invariant mass of Reconstructed MC Xi-", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); + histos.add("h3RecXi1530invmass", "Invariant mass of Reconstructed MC Xi(1530)0", kTHnSparseF, {centAxis, ptAxis, invMassAxis, ptAxis}); + histos.add("h3RecXiinvmass", "Invariant mass of Reconstructed MC Xi-", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, ptAxis}); - histos.add("h3RecXi1530invmassAnti", "Invariant mass of Reconstructed MC Anti-Xi(1530)0", kTHnSparseF, {centAxis, ptAxis, invMassAxis, flagAxis}); - histos.add("h3RecXiinvmassAnti", "Invariant mass of Reconstructed MC Anti-Xi-", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, flagAxis}); + histos.add("h3RecXi1530invmassAnti", "Invariant mass of Reconstructed MC Anti-Xi(1530)0", kTHnSparseF, {centAxis, ptAxis, invMassAxis, ptAxis}); + histos.add("h3RecXiinvmassAnti", "Invariant mass of Reconstructed MC Anti-Xi-", kTHnSparseF, {centAxis, ptAxis, invMassAxisCasc, ptAxis}); - histos.add("h3Xi1530Gen", "pT distribution of True MC Xi(1530)0", kTHnSparseF, {mcLabelAxis, ptAxis, centAxis}); - histos.add("h3Xi1530GenAnti", "pT distribution of True MC Anti-Xi(1530)0", kTHnSparseF, {mcLabelAxis, ptAxis, centAxis}); + histos.add("h3Xi1530Gen", "pT distribution of True MC Xi(1530)0", kTHnSparseF, {ptAxis, centAxis, histoConfig.multNTracksAxis}); + histos.add("h3Xi1530GenAnti", "pT distribution of True MC Anti-Xi(1530)0", kTHnSparseF, {ptAxis, centAxis, histoConfig.multNTracksAxis}); histos.add("Xi1530Rec", "pT distribution of Reconstructed MC Xi(1530)0", kTH2F, {ptAxis, centAxis}); histos.add("Xi1530RecAnti", "pT distribution of Reconstructed MC Anti-Xi(1530)0", kTH2F, {ptAxis, centAxis}); histos.add("Xi1530Recinvmass", "Inv mass distribution of Reconstructed MC Xi(1530)0", kTH1F, {invMassAxis}); } - - if (additionalQAplots) { - histos.add("QAbefore/V0sDCADoughter_aspt", "V0s DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); - histos.add("QAbefore/CascDCADoughter_aspt", "Casc DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); - histos.add("QAbefore/CascMass_aspt", "Casc DCA Bachlor distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisCasc}); - histos.add("QAbefore/V0sCosPA_aspt", "V0s CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); - histos.add("QAbefore/CascCosPA_aspt", "Casc CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); - - histos.add("QAafter/V0sDCADoughter_aspt", "V0s DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); - histos.add("QAafter/CascDCADoughter_aspt", "Casc DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); - histos.add("QAafter/CascMass_aspt", "Casc DCA Bachlor distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisCasc}); - histos.add("QAafter/V0sCosPA_aspt", "V0s CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); - histos.add("QAafter/CascCosPA_aspt", "Casc CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); - - histos.add("QAMCTrue/V0sDCADoughter_aspt", "V0s DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); - histos.add("QAMCTrue/CascDCADoughter_aspt", "Casc DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); - histos.add("QAMCTrue/CascMass_aspt", "Casc DCA Bachlor distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisCasc}); - histos.add("QAMCTrue/V0sCosPA_aspt", "V0s CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); - histos.add("QAMCTrue/CascCosPA_aspt", "Casc CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + // QA for topological, kinematical cut for cascades + if (histoConfig.additionalQAplots) { + histos.add("QAbefore/V0DCATopPV", "V0s DCA to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaxyAxis}); + histos.add("QAbefore/V0DCADoughter", "V0s DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); + histos.add("QAbefore/CascDCADoughter", "Casc DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); + histos.add("QAbefore/CascDCABachPV", "Casc DCA Bachlor to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaBachAxis}); + histos.add("QAbefore/CascDCAPosPV", "Casc DCA Positive to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaSecondaryAxis}); + histos.add("QAbefore/CascDCANegPV", "Casc DCA Negative to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaSecondaryAxis}); + histos.add("QAbefore/V0Mass", "V0 mass distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisLambda}); + histos.add("QAbefore/CascMass", "Casc mass distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisCasc}); + histos.add("QAbefore/V0CosPA", "V0s CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + histos.add("QAbefore/CascCosPA", "Casc CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + histos.add("QAbefore/V0Radius", "V0 Radius distribution as pt", HistType::kTH2F, {ptAxis, transRadiusAxis}); + histos.add("QAbefore/CascRadius", "Casc Radius distribution as pt", HistType::kTH2F, {ptAxis, transRadiusAxis}); + histos.add("QAbefore/ProperLifetime", "Proper Lifetime distribution as pt", HistType::kTH2F, {ptAxis, properLifetimeAxis}); + + histos.add("QAafter/V0DCATopPV", "V0s DCA to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaxyAxis}); + histos.add("QAafter/V0DCADoughter", "V0s DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); + histos.add("QAafter/CascDCADoughter", "Casc DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); + histos.add("QAafter/CascDCABachPV", "Casc DCA Bachlor to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaBachAxis}); + histos.add("QAafter/CascDCAPosPV", "Casc DCA Positive to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaSecondaryAxis}); + histos.add("QAafter/CascDCANegPV", "Casc DCA Negative to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaSecondaryAxis}); + histos.add("QAafter/V0Mass", "V0 mass distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisLambda}); + histos.add("QAafter/CascMass", "Casc mass distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisCasc}); + histos.add("QAafter/V0CosPA", "V0s CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + histos.add("QAafter/CascCosPA", "Casc CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + histos.add("QAafter/V0Radius", "V0 Radius distribution as pt", HistType::kTH2F, {ptAxis, transRadiusAxis}); + histos.add("QAafter/CascRadius", "Casc Radius distribution as pt", HistType::kTH2F, {ptAxis, transRadiusAxis}); + histos.add("QAafter/ProperLifetime", "Proper Lifetime distribution as pt", HistType::kTH2F, {ptAxis, properLifetimeAxis}); + + histos.add("QAMCTrue/V0DCATopPV", "V0s DCA to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaxyAxis}); + histos.add("QAMCTrue/V0DCADoughter", "V0s DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); + histos.add("QAMCTrue/CascDCADoughter", "Casc DCA Doughter distribution as pt", HistType::kTH2F, {ptAxis, dcaDaugAxis}); + histos.add("QAMCTrue/CascDCABachPV", "Casc DCA Bachlor to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaBachAxis}); + histos.add("QAMCTrue/CascDCAPosPV", "Casc DCA Positive to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaSecondaryAxis}); + histos.add("QAMCTrue/CascDCANegPV", "Casc DCA Negative to PV distribution as pt", HistType::kTH2F, {ptAxis, dcaSecondaryAxis}); + histos.add("QAMCTrue/V0Mass", "V0 mass distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisLambda}); + histos.add("QAMCTrue/CascMass", "Casc mass distribution as pt", HistType::kTH2F, {ptAxis, invMassAxisCasc}); + histos.add("QAMCTrue/V0CosPA", "V0s CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + histos.add("QAMCTrue/CascCosPA", "Casc CosPA distribution as pt", HistType::kTH2F, {ptAxis, cosPAAxis}); + histos.add("QAMCTrue/V0Radius", "V0 Radius distribution as pt", HistType::kTH2F, {ptAxis, transRadiusAxis}); + histos.add("QAMCTrue/CascRadius", "Casc Radius distribution as pt", HistType::kTH2F, {ptAxis, transRadiusAxis}); + histos.add("QAMCTrue/ProperLifetime", "Proper Lifetime distribution as pt", HistType::kTH2F, {ptAxis, properLifetimeAxis}); } } - double massPi = MassPionCharged; + float massPi = MassPionCharged; // Primary track selection for the first pion // template bool primaryTrackCut(const TrackType track) { - if (std::abs(track.eta()) > cMaxetacut) + if (std::abs(track.eta()) >= primarytrackConfig.cMaxetacut) return false; - if (std::abs(track.pt()) < cMinPtcut) + if (std::abs(track.pt()) <= primarytrackConfig.cMinPtcut) return false; if constexpr (IsResoMicrotrack) { - if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())) >= (primarytrackConfig.cDCAxytoPVByPtPiFirstP0 + primarytrackConfig.cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.))) return false; - if (cDCAzToPVAsPt) { - if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (primarytrackConfig.cDCAzToPVAsPt) { + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) >= (primarytrackConfig.cDCAxytoPVByPtPiFirstP0 + primarytrackConfig.cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.))) return false; } else { - if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > cMaxDCAzToPVCut) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) >= primarytrackConfig.cMaxDCAzToPVCut) return false; } } else { - if (std::abs(track.dcaXY()) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (std::abs(track.dcaXY()) >= (primarytrackConfig.cDCAxytoPVByPtPiFirstP0 + primarytrackConfig.cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.))) return false; - if (cDCAzToPVAsPt) { - if (std::abs(track.dcaZ()) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (primarytrackConfig.cDCAzToPVAsPt) { + if (std::abs(track.dcaZ()) >= (primarytrackConfig.cDCAxytoPVByPtPiFirstP0 + primarytrackConfig.cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.))) return false; } else { - if (std::abs(track.dcaZ()) > cMaxDCAzToPVCut) + if (std::abs(track.dcaZ()) >= primarytrackConfig.cMaxDCAzToPVCut) return false; } - if (track.tpcNClsFound() < cfgTPCcluster) + if (track.tpcNClsFound() <= primarytrackConfig.cfgTPCcluster) return false; - if (track.tpcNClsCrossedRows() < cfgTPCRows) + if (track.tpcNClsCrossedRows() <= primarytrackConfig.cfgTPCRows) return false; } - if (cfgHasTOF && !track.hasTOF()) + if (primarytrackConfig.cfgHasTOF && !track.hasTOF()) return false; - // if (cfgUseITSRefit && !track.passedITSRefit()) - // return false; - // if (cfgUseTPCRefit && !track.passedTPCRefit()) - // return false; - if (cfgPVContributor && !track.isPVContributor()) + if (primarytrackConfig.cfgPVContributor && !track.isPVContributor()) return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) + if (primarytrackConfig.cfgPrimaryTrack && !track.isPrimaryTrack()) return false; return true; } bool hasSubsystemInfo(float Nsigma) { - return std::abs(Nsigma) < cPIDBound; + return std::abs(Nsigma) < pidConfig.cPIDBound; } // Primary track selection for cascades, Need to more informations for cascades // template bool cascprimaryTrackCut(const TracksTypeCasc track) { - if (std::abs(track.eta()) > cMaxetacut) + if (std::abs(track.eta()) >= primarytrackConfig.cMaxetacut) return false; - if (std::abs(track.pt()) < cMinPtcut) + if (std::abs(track.pt()) <= primarytrackConfig.cMinPtcut) return false; - if (cDCAxyToPVAsPtForCasc) { - if (std::abs(track.dcaXYCascToPV()) > (cDCAxyToPVByPtCascP0 + cDCAxyToPVByPtCascExp * track.pt())) + if (primarytrackConfig.cDCAxyToPVAsPtForCasc) { + if (std::abs(track.dcaXYCascToPV()) >= (primarytrackConfig.cDCAxyToPVByPtCascP0 + primarytrackConfig.cDCAxyToPVByPtCascExp * track.pt())) return false; } - if (cDCAzToPVAsPtForCasc) { - if (std::abs(track.dcaZCascToPV()) > (cDCAxyToPVByPtCascP0 + cDCAxyToPVByPtCascExp * std::pow(track.pt(), -1.1))) + if (primarytrackConfig.cDCAzToPVAsPtForCasc) { + if (std::abs(track.dcaZCascToPV()) >= (primarytrackConfig.cDCAxyToPVByPtCascP0 + primarytrackConfig.cDCAxyToPVByPtCascExp * std::pow(track.pt(), -1.))) return false; } @@ -507,49 +571,49 @@ struct Xi1530Analysisqa { bool casctopCut(const TracksTypeCasc track) { // Topological cuts for V0s - if (std::abs(track.daughDCA()) > cDCALambdaDaugtherscut) + if (std::abs(track.daughDCA()) >= v0sConfig.cDCALambdaDaugtherscut) return false; - if (std::abs(track.dcav0topv()) < cDCALambdaToPVcut) + if (std::abs(track.dcav0topv()) <= v0sConfig.cDCALambdaToPVcut) return false; if (track.sign() < 0) { - if (std::abs(track.dcanegtopv()) < cDCAPionToPVcut) + if (std::abs(track.dcanegtopv()) <= v0sConfig.cDCAPionToPVcut) return false; - if (std::abs(track.dcapostopv()) < cDCAProtonToPVcut) + if (std::abs(track.dcapostopv()) <= v0sConfig.cDCAProtonToPVcut) return false; } else { - if (std::abs(track.dcanegtopv()) < cDCAProtonToPVcut) + if (std::abs(track.dcanegtopv()) <= v0sConfig.cDCAProtonToPVcut) return false; - if (std::abs(track.dcapostopv()) < cDCAPionToPVcut) + if (std::abs(track.dcapostopv()) <= v0sConfig.cDCAPionToPVcut) return false; } - if (track.v0CosPA() < std::cos(cV0CosPACutPtDepP0 - cV0CosPACutPtDepP1 * track.pt())) + if (track.v0CosPA() <= std::cos(v0sConfig.cV0CosPACutPtDepP0 - v0sConfig.cV0CosPACutPtDepP1 * track.pt())) return false; - if (track.transRadius() > cMaxV0radiuscut || track.transRadius() < cMinV0radiuscut) + if (track.transRadius() >= v0sConfig.cMaxV0radiuscut || track.transRadius() <= v0sConfig.cMinV0radiuscut) return false; - if (std::abs(track.mLambda() - MassLambda) > cMasswindowV0cut) + if (std::abs(track.mLambda() - MassLambda) >= v0sConfig.cMasswindowV0cut) return false; // Topological Cuts for Cascades - if (std::abs(track.dcabachtopv()) < cDCABachlorToPVcut) + if (std::abs(track.dcabachtopv()) <= cascadeConfig.cDCABachlorToPVcut) return false; - if (track.pt() < cDCAXiDaugthersCutPtRangeLower) { - if (track.cascDaughDCA() > cDCAXiDaugthersCutPtDepLower) + if (track.pt() <= cascadeConfig.cDCAXiDaugthersCutPtRangeLower) { + if (track.cascDaughDCA() >= cascadeConfig.cDCAXiDaugthersCutPtDepLower) return false; } - if (track.pt() >= cDCAXiDaugthersCutPtRangeLower && track.pt() < cDCAXiDaugthersCutPtRangeUpper) { - if (track.cascDaughDCA() > cDCAXiDaugthersCutPtDepMiddle) + if (track.pt() >= cascadeConfig.cDCAXiDaugthersCutPtRangeLower && track.pt() <= cascadeConfig.cDCAXiDaugthersCutPtRangeUpper) { + if (track.cascDaughDCA() >= cascadeConfig.cDCAXiDaugthersCutPtDepMiddle) return false; } - if (track.pt() >= cDCAXiDaugthersCutPtRangeUpper) { - if (track.cascDaughDCA() > cDCAXiDaugthersCutPtDepUpper) + if (track.pt() >= cascadeConfig.cDCAXiDaugthersCutPtRangeUpper) { + if (track.cascDaughDCA() >= cascadeConfig.cDCAXiDaugthersCutPtDepUpper) return false; } - if (track.cascCosPA() < std::cos(cCosPACascCutPtDepP0 - cCosPACascCutPtDepP1 * track.pt())) + if (track.cascCosPA() <= std::cos(cascadeConfig.cCosPACascCutPtDepP0 - cascadeConfig.cCosPACascCutPtDepP1 * track.pt())) return false; - if (track.cascTransRadius() > cMaxCascradiuscut || track.cascTransRadius() < cMinCascradiuscut) + if (track.cascTransRadius() >= cascadeConfig.cMaxCascradiuscut || track.cascTransRadius() <= cascadeConfig.cMinCascradiuscut) return false; - if (std::abs(track.mXi() - cMassXiminus) > cMasswindowCasccut) + if (std::abs(track.mXi() - cascadeConfig.cMassXiminus) >= cascadeConfig.cMasswindowCasccut) return false; return true; @@ -559,7 +623,7 @@ struct Xi1530Analysisqa { { bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (tofAtHighPt && trackPt > cMinTOFpt) { + if (tofAtHighPt && trackPt > pidConfig.cMinTOFpt) { if (std::abs(TPCNsigma) < params.cMaxTPCnSigma) { tpcPIDPassed = true; } @@ -622,9 +686,9 @@ struct Xi1530Analysisqa { tofNsigmaPionFirst = candidate.tofNSigmaPi(); } - PidSelectionParam pionFirstParams = {cMaxtpcnSigmaPionFirst, cMaxtofnSigmaPionFirst, cByPassTOFPionFirst, nsigmaCutCombinedPionFirst}; + PidSelectionParam pionFirstParams = {pidConfig.cMaxtpcnSigmaPionFirst, pidConfig.cMaxtofnSigmaPionFirst, pidConfig.cByPassTOFPionFirst, pidConfig.nsigmaCutCombinedPionFirst}; - return pidSelector(tpcNsigmaPionFirst, tofNsigmaPionFirst, pionFirstParams, tofAtHighPt, trackPt); + return pidSelector(tpcNsigmaPionFirst, tofNsigmaPionFirst, pionFirstParams, pidConfig.tofAtHighPt, trackPt); } template @@ -658,55 +722,68 @@ struct Xi1530Analysisqa { tofNsigmaProton = candidate.daughterTOFNSigmaNegPr(); } - PidSelectionParam bachelorParams = {cMaxtpcnSigmaPionBachelor, cMaxtofnSigmaPionBachelor, cByPassTOFPionBachelor, nsigmaCutCombinedPionBachelor}; - PidSelectionParam pionParams = {cMaxtpcnSigmaPion, cMaxtofnSigmaPion, cByPassTOFPion, nsigmaCutCombinedPion}; - PidSelectionParam protonParams = {cMaxtpcnSigmaProton, cMaxtofnSigmaProton, cByPassTOFProton, nsigmaCutCombinedProton}; + PidSelectionParam bachelorParams = {pidConfig.cMaxtpcnSigmaPionBachelor, pidConfig.cMaxtofnSigmaPionBachelor, pidConfig.cByPassTOFPionBachelor, pidConfig.nsigmaCutCombinedPionBachelor}; + PidSelectionParam pionParams = {pidConfig.cMaxtpcnSigmaPion, pidConfig.cMaxtofnSigmaPion, pidConfig.cByPassTOFPion, pidConfig.nsigmaCutCombinedPion}; + PidSelectionParam protonParams = {pidConfig.cMaxtpcnSigmaProton, pidConfig.cMaxtofnSigmaProton, pidConfig.cByPassTOFProton, pidConfig.nsigmaCutCombinedProton}; - lConsistentWithXi = pidSelector(tpcNsigmaBachelor, tofNsigmaBachelor, bachelorParams, tofAtHighPt, trackPt); - lConsistentWithPion = pidSelector(tpcNsigmaPion, tofNsigmaPion, pionParams, tofAtHighPt, trackPt); - lConsistentWithProton = pidSelector(tpcNsigmaProton, tofNsigmaProton, protonParams, tofAtHighPt, trackPt); + lConsistentWithXi = pidSelector(tpcNsigmaBachelor, tofNsigmaBachelor, bachelorParams, pidConfig.tofAtHighPt, trackPt); + lConsistentWithPion = pidSelector(tpcNsigmaPion, tofNsigmaPion, pionParams, pidConfig.tofAtHighPt, trackPt); + lConsistentWithProton = pidSelector(tpcNsigmaProton, tofNsigmaProton, protonParams, pidConfig.tofAtHighPt, trackPt); lConsistentWithLambda = lConsistentWithProton && lConsistentWithPion; return lConsistentWithXi && lConsistentWithLambda; } - template - void fillHistograms(const CollisionType& collision, const CenMult& multiplicity, const TracksType& dTracks1, const TracksTypeCasc& dTracks2) // Order: ResoColl, ResoTrack, ResoCascTrack + template + float properLifetime(const CollisionType& collision, const TCascade& candidate) + { + float kSmallMomentumDenominator = 1e-6f; // To avoid division by zero, if momentum is extremely small, we consider it as 1e-6 GeV/c + float dx = candidate.decayVtxX() - collision.posX(); + float dy = candidate.decayVtxY() - collision.posY(); + float dz = candidate.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(candidate.px() * candidate.px() + candidate.py() * candidate.py() + candidate.pz() * candidate.pz()); + auto properLifetime = (l / (p + kSmallMomentumDenominator)) * candidate.mXi(); + return properLifetime; + } + + template + void fillHistograms(const CollisionType& collision, const centType& inCent, const TracksType& dTracks1, const TracksTypeCasc& dTracks2) // Order: ResoColl, ResoTrack, ResoCascTrack { - // auto multiplicity = collision.cent(); + auto Cent = inCent; - { + if (histoConfig.eventQA) { if constexpr (!IsMix) { histos.fill(HIST("QAevent/hVertexZSameE"), collision.posZ()); - histos.fill(HIST("QAevent/hMultiplicityPercentSameE"), multiplicity); - histos.fill(HIST("TestME/hCollisionIndexSameE"), collision.globalIndex()); - histos.fill(HIST("TestME/hnTrksSameE"), dTracks1.size()); + histos.fill(HIST("QAevent/hMultiplicityPercentSameE"), Cent); + histos.fill(HIST("QAevent/hCollisionIndexSameE"), collision.globalIndex()); + histos.fill(HIST("QAevent/hnTrksSameE"), dTracks1.size()); + histos.fill(HIST("QAevent/hnCascsSameE"), dTracks2.size()); } else { histos.fill(HIST("QAevent/hVertexZMixedE"), collision.posZ()); - histos.fill(HIST("QAevent/hMultiplicityPercentMixedE"), multiplicity); - histos.fill(HIST("TestME/hCollisionIndexMixedE"), collision.globalIndex()); - histos.fill(HIST("TestME/hnTrksMixedE"), dTracks1.size()); + histos.fill(HIST("QAevent/hMultiplicityPercentMixedE"), Cent); + histos.fill(HIST("QAevent/hCollisionIndexMixedE"), collision.globalIndex()); + histos.fill(HIST("QAevent/hnTrksMixedE"), dTracks1.size()); + histos.fill(HIST("QAevent/hnCascsMixedE"), dTracks2.size()); } } - LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, lResonance; // It will be replaced to use RecoDecay (In fixing...) - - for (const auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { + if (additionalConfig.cConsiderPairOnly && (dTracks2.size() < 1 || dTracks1.size() < 1)) + return; - { - if constexpr (!IsMix) { - histos.fill(HIST("TestME/hPairsCounterSameE"), 1.0); - } else { - histos.fill(HIST("TestME/hPairsCounterMixedE"), 1.0); - } - } + LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, lResonance, lDaughterRot, lResonanceRot; + std::vector pionCandateIndicies = {}; + std::vector xiCandateIndicies = {}; + pionCandateIndicies.reserve(dTracks1.size()); + xiCandateIndicies.reserve(dTracks2.size()); + for (const auto& trk1 : dTracks1) { auto trk1ptPi = trk1.pt(); - static float trk1DCAXY; - static float trk1DCAZ; - static float trk1NSigmaPiTPC; - static float trk1NSigmaPiTOF; + float trk1DCAXY = -1.f; + float trk1DCAZ = -1.f; + float trk1NSigmaPiTPC = -999.f; + float trk1NSigmaPiTOF = -999.f; if constexpr (IsResoMicrotrack) { trk1DCAXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags()); trk1DCAZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags()); @@ -719,19 +796,67 @@ struct Xi1530Analysisqa { trk1NSigmaPiTOF = trk1.tofNSigmaPi(); } + // QA before + if constexpr (!IsMix) { + if (histoConfig.pidPlots) { + histos.fill(HIST("QAbefore/TPC_Nsigma_pi_first_all"), Cent, trk1ptPi, trk1NSigmaPiTPC); + if (hasSubsystemInfo(trk1NSigmaPiTOF)) { + histos.fill(HIST("QAbefore/TOF_Nsigma_pi_first_all"), Cent, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_first_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + } + if (histoConfig.additionalQAplots) { + histos.fill(HIST("QAbefore/trkDCAxy_pi"), trk1ptPi, trk1DCAXY); + histos.fill(HIST("QAbefore/trkDCAz_pi"), trk1ptPi, trk1DCAZ); + } + } + if (pidConfig.cUseOnlyTOFTrackPionBachelor && hasSubsystemInfo(trk1NSigmaPiTOF)) + continue; + if (!selectionPIDPionFirst(trk1)) // PID selection for the first pion + continue; + if (!primaryTrackCut(trk1)) // Primary track selections + continue; + + if constexpr (!IsMix) { + if (histoConfig.pidPlots) { + histos.fill(HIST("QAafter/TPC_Nsigma_pi_first_all"), Cent, trk1ptPi, trk1NSigmaPiTPC); + + if (hasSubsystemInfo(trk1NSigmaPiTOF)) { + histos.fill(HIST("QAafter/TOF_Nsigma_pi_first_all"), Cent, trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAafter/TOF_TPC_Map_pi_first_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + } + if (histoConfig.additionalQAplots) { + histos.fill(HIST("QAafter/trkDCAxy_pi"), trk1ptPi, trk1DCAXY); + histos.fill(HIST("QAafter/trkDCAz_pi"), trk1ptPi, trk1DCAZ); + } + } + + pionCandateIndicies.push_back(trk1.index()); + } + + for (const auto& trk2 : dTracks2) { + // Kinematic variables for cascades auto trk2ptXi = trk2.pt(); + auto massLambdaCand = trk2.mLambda(); + auto massXiCand = trk2.mXi(); + auto trk2ProperLifetime = properLifetime(collision, trk2); + // Topological variables for cascades + auto trk2DCAV0TopPV = trk2.dcav0topv(); auto trk2DCAXY = trk2.dcaXYCascToPV(); auto trk2DCAZ = trk2.dcaZCascToPV(); - - auto trk2DCAV0sDougthers = trk2.daughDCA(); + auto trk2DCAV0sDougthers = trk2.daughDCA(); // V0s daughter DCA auto trk2DCACascDougthers = trk2.cascDaughDCA(); - auto trk2Mass = trk2.mXi(); + auto trk2DCABachPV = trk2.dcabachtopv(); + auto trk2DCAPosPV = trk2.dcapostopv(); + auto trk2DCANegPV = trk2.dcanegtopv(); + auto trk2V0CosPA = trk2.v0CosPA(); auto trk2CascCosPA = trk2.cascCosPA(); - auto trk2V0sCosPA = trk2.v0CosPA(); + auto trk2V0Radius = trk2.transRadius(); + auto trk2CascRadius = trk2.cascTransRadius(); - // Need to daughther's pt info. in the table - // auto trk2ptPiBachelor = trk2.pt(); + // QA before selections float trk2NSigmaPiBachelorTPC = trk2.daughterTPCNSigmaBachPi(); float trk2NSigmaPiBachelorTOF = trk2.daughterTOFNSigmaBachPi(); @@ -752,417 +877,438 @@ struct Xi1530Analysisqa { if constexpr (!IsMix) { //// QA plots before the selection // // --- PID QA - if (pidPlots) { - histos.fill(HIST("QAbefore/TPC_Nsigma_pi_first_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); - if (hasSubsystemInfo(trk1NSigmaPiTOF)) { - histos.fill(HIST("QAbefore/TOF_Nsigma_pi_first_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_first_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } - - histos.fill(HIST("QAbefore/TPC_Nsigma_pi_bachelor_all"), multiplicity, 0, trk2NSigmaPiBachelorTPC); // can't take pt information for the cascade secondary + if (histoConfig.pidPlots) { + histos.fill(HIST("QAbefore/TPC_Nsigma_pi_bachelor_all"), Cent, 0, trk2NSigmaPiBachelorTPC); // can't take pt information for the cascade secondary if (hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) { histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_bachelor_all"), trk2NSigmaPiBachelorTOF, trk2NSigmaPiBachelorTPC); } - histos.fill(HIST("QAbefore/TPC_Nsigma_pr_all"), multiplicity, 0, trk2NSigmaPrPosTPC); + histos.fill(HIST("QAbefore/TPC_Nsigma_pr_all"), Cent, 0, trk2NSigmaPrPosTPC); if (hasSubsystemInfo(trk2NSigmaPrPosTOF)) { histos.fill(HIST("QAbefore/TOF_TPC_Map_pr_all"), trk2NSigmaPrPosTOF, trk2NSigmaPrPosTPC); } - histos.fill(HIST("QAbefore/TPC_Nsigma_antipr_all"), multiplicity, 0, trk2NSigmaPrNegTPC); + histos.fill(HIST("QAbefore/TPC_Nsigma_antipr_all"), Cent, 0, trk2NSigmaPrNegTPC); if (hasSubsystemInfo(trk2NSigmaPrNegTOF)) { histos.fill(HIST("QAbefore/TOF_TPC_Map_antipr_all"), trk2NSigmaPrNegTOF, trk2NSigmaPrNegTPC); } - histos.fill(HIST("QAbefore/TPC_Nsigma_pi_all"), multiplicity, 0, trk2NSigmaPiPosTPC); + histos.fill(HIST("QAbefore/TPC_Nsigma_pi_all"), Cent, 0, trk2NSigmaPiPosTPC); if (hasSubsystemInfo(trk2NSigmaPiPosTOF)) { histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_all"), trk2NSigmaPiPosTOF, trk2NSigmaPiPosTPC); } - histos.fill(HIST("QAbefore/TPC_Nsigma_piminus_all"), multiplicity, 0, trk2NSigmaPiNegTPC); + histos.fill(HIST("QAbefore/TPC_Nsigma_piminus_all"), Cent, 0, trk2NSigmaPiNegTPC); if (hasSubsystemInfo(trk2NSigmaPiNegTOF)) { histos.fill(HIST("QAbefore/TOF_TPC_Map_piminus_all"), trk2NSigmaPiNegTOF, trk2NSigmaPiNegTPC); } } - histos.fill(HIST("QAbefore/trkDCAxy_pi"), trk1ptPi, trk1DCAXY); - histos.fill(HIST("QAbefore/trkDCAxy_Xi"), trk2ptXi, trk2DCAXY); - - histos.fill(HIST("QAbefore/trkDCAz_pi"), trk1ptPi, trk1DCAZ); - histos.fill(HIST("QAbefore/trkDCAz_Xi"), trk2ptXi, trk2DCAZ); - - if (additionalQAplots) { - histos.fill(HIST("QAbefore/V0sDCADoughter_aspt"), trk2ptXi, trk2DCAV0sDougthers); - histos.fill(HIST("QAbefore/CascDCADoughter_aspt"), trk2ptXi, trk2DCACascDougthers); - histos.fill(HIST("QAbefore/CascMass_aspt"), trk2ptXi, trk2Mass); - histos.fill(HIST("QAbefore/V0sCosPA_aspt"), trk2ptXi, 1. - trk2V0sCosPA); - histos.fill(HIST("QAbefore/CascCosPA_aspt"), trk2ptXi, 1. - trk2CascCosPA); + if (histoConfig.additionalQAplots) { + histos.fill(HIST("QAbefore/V0DCATopPV"), trk2ptXi, trk2DCAV0TopPV); + histos.fill(HIST("QAbefore/trkDCAxy_Xi"), trk2ptXi, trk2DCAXY); + histos.fill(HIST("QAbefore/trkDCAz_Xi"), trk2ptXi, trk2DCAZ); + histos.fill(HIST("QAbefore/V0DCADoughter"), trk2ptXi, trk2DCAV0sDougthers); + histos.fill(HIST("QAbefore/CascDCADoughter"), trk2ptXi, trk2DCACascDougthers); + histos.fill(HIST("QAbefore/CascDCABachPV"), trk2ptXi, trk2DCABachPV); + histos.fill(HIST("QAbefore/CascDCAPosPV"), trk2ptXi, trk2DCAPosPV); + histos.fill(HIST("QAbefore/CascDCANegPV"), trk2ptXi, trk2DCANegPV); + histos.fill(HIST("QAbefore/V0CosPA"), trk2ptXi, 1. - trk2V0CosPA); + histos.fill(HIST("QAbefore/CascCosPA"), trk2ptXi, 1. - trk2CascCosPA); + histos.fill(HIST("QAbefore/V0Radius"), trk2ptXi, trk2V0Radius); + histos.fill(HIST("QAbefore/CascRadius"), trk2ptXi, trk2CascRadius); + histos.fill(HIST("QAbefore/V0Mass"), trk2ptXi, massLambdaCand); + histos.fill(HIST("QAbefore/CascMass"), trk2ptXi, massXiCand); + histos.fill(HIST("QAbefore/ProperLifetime"), trk2ptXi, trk2ProperLifetime); } } - if (!primaryTrackCut(trk1) || !cascprimaryTrackCut(trk2)) // Primary track selections + if (pidConfig.cUseOnlyTOFTrackPionBachelor && !hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) continue; - - // PID selection - if (cUseOnlyTOFTrackPionFirst && !hasSubsystemInfo(trk1NSigmaPiTOF)) - continue; - - if (cUseOnlyTOFTrackPionBachelor && !hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) + if (pidConfig.cUseOnlyTOFTrackProton && !hasSubsystemInfo(trk2NSigmaPrPosTOF)) continue; - - if (cUseOnlyTOFTrackProton && !hasSubsystemInfo(trk2NSigmaPrPosTOF)) + if (pidConfig.cUseOnlyTOFTrackProton && !hasSubsystemInfo(trk2NSigmaPrNegTOF)) continue; - if (cUseOnlyTOFTrackProton && !hasSubsystemInfo(trk2NSigmaPrNegTOF)) + if (pidConfig.cUseOnlyTOFTrackPion && !hasSubsystemInfo(trk2NSigmaPiPosTOF)) continue; - - if (cUseOnlyTOFTrackPion && !hasSubsystemInfo(trk2NSigmaPiPosTOF)) + if (pidConfig.cUseOnlyTOFTrackPion && !hasSubsystemInfo(trk2NSigmaPiNegTOF)) continue; - if (cUseOnlyTOFTrackPion && !hasSubsystemInfo(trk2NSigmaPiNegTOF)) + if (!selectionPIDCascades(trk2)) continue; - - if (!selectionPIDPionFirst(trk1) || !selectionPIDCascades(trk2)) + if (!cascprimaryTrackCut(trk2) || !casctopCut(trk2)) // Primary track selections continue; - - if (!casctopCut(trk2)) + if (trk2ProperLifetime >= cascadeConfig.cMaxProperLifetimeCut) continue; + // QA after selections if constexpr (!IsMix) { //// QA plots after the selection // --- PID QA - if (pidPlots) { - histos.fill(HIST("QAafter/TPC_Nsigma_pi_first_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); - - if (hasSubsystemInfo(trk1NSigmaPiTOF)) { - histos.fill(HIST("QAafter/TOF_Nsigma_pi_first_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAafter/TOF_TPC_Map_pi_first_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } + if (histoConfig.pidPlots) { if (trk2.sign() < 0) { - histos.fill(HIST("QAafter/TPC_Nsigma_pi_bachelor_all"), multiplicity, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. + histos.fill(HIST("QAafter/TPC_Nsigma_pi_bachelor_all"), Cent, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. if (hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) { histos.fill(HIST("QAafter/TOF_TPC_Map_pi_bachelor_all"), trk2NSigmaPiBachelorTOF, trk2NSigmaPiBachelorTPC); } - histos.fill(HIST("QAafter/TPC_Nsigma_pr_all"), multiplicity, 0, trk2NSigmaPrPosTPC); + histos.fill(HIST("QAafter/TPC_Nsigma_pr_all"), Cent, 0, trk2NSigmaPrPosTPC); if (hasSubsystemInfo(trk2NSigmaPrPosTOF)) { histos.fill(HIST("QAafter/TOF_TPC_Map_pr_all"), trk2NSigmaPrPosTOF, trk2NSigmaPrPosTPC); } - histos.fill(HIST("QAafter/TPC_Nsigma_piminus_all"), multiplicity, 0, trk2NSigmaPiNegTPC); + histos.fill(HIST("QAafter/TPC_Nsigma_piminus_all"), Cent, 0, trk2NSigmaPiNegTPC); if (hasSubsystemInfo(trk2NSigmaPiNegTOF)) { histos.fill(HIST("QAafter/TOF_TPC_Map_piminus_all"), trk2NSigmaPiNegTOF, trk2NSigmaPiNegTPC); } } else { - histos.fill(HIST("QAafter/TPC_Nsigma_pi_bachelor_all"), multiplicity, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. + histos.fill(HIST("QAafter/TPC_Nsigma_pi_bachelor_all"), Cent, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. if (hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) { histos.fill(HIST("QAafter/TOF_TPC_Map_pi_bachelor_all"), trk2NSigmaPiBachelorTOF, trk2NSigmaPiBachelorTPC); } - histos.fill(HIST("QAafter/TPC_Nsigma_antipr_all"), multiplicity, 0, trk2NSigmaPrNegTPC); + histos.fill(HIST("QAafter/TPC_Nsigma_antipr_all"), Cent, 0, trk2NSigmaPrNegTPC); if (hasSubsystemInfo(trk2NSigmaPrNegTOF)) { histos.fill(HIST("QAafter/TOF_TPC_Map_antipr_all"), trk2NSigmaPrNegTOF, trk2NSigmaPrNegTPC); } - histos.fill(HIST("QAafter/TPC_Nsigma_pi_all"), multiplicity, 0, trk2NSigmaPiPosTPC); + histos.fill(HIST("QAafter/TPC_Nsigma_pi_all"), Cent, 0, trk2NSigmaPiPosTPC); if (hasSubsystemInfo(trk2NSigmaPiPosTOF)) { histos.fill(HIST("QAafter/TOF_TPC_Map_pi_all"), trk2NSigmaPiPosTOF, trk2NSigmaPiPosTPC); } } } - - histos.fill(HIST("QAafter/trkDCAxy_pi"), trk1ptPi, trk1DCAXY); - histos.fill(HIST("QAafter/trkDCAxy_Xi"), trk2ptXi, trk2DCAXY); - - histos.fill(HIST("QAafter/trkDCAz_pi"), trk1ptPi, trk1DCAZ); - histos.fill(HIST("QAafter/trkDCAz_Xi"), trk2ptXi, trk2DCAZ); - - if (additionalQAplots) { - histos.fill(HIST("QAafter/V0sDCADoughter_aspt"), trk2ptXi, trk2DCAV0sDougthers); - histos.fill(HIST("QAafter/CascDCADoughter_aspt"), trk2ptXi, trk2DCACascDougthers); - histos.fill(HIST("QAafter/CascMass_aspt"), trk2ptXi, trk2Mass); - histos.fill(HIST("QAafter/V0sCosPA_aspt"), trk2ptXi, 1. - trk2V0sCosPA); - histos.fill(HIST("QAafter/CascCosPA_aspt"), trk2ptXi, 1. - trk2CascCosPA); + if (histoConfig.additionalQAplots) { + histos.fill(HIST("QAafter/V0DCATopPV"), trk2ptXi, trk2DCAV0TopPV); + histos.fill(HIST("QAafter/trkDCAxy_Xi"), trk2ptXi, trk2DCAXY); + histos.fill(HIST("QAafter/trkDCAz_Xi"), trk2ptXi, trk2DCAZ); + histos.fill(HIST("QAafter/V0DCADoughter"), trk2ptXi, trk2DCAV0sDougthers); + histos.fill(HIST("QAafter/CascDCADoughter"), trk2ptXi, trk2DCACascDougthers); + histos.fill(HIST("QAafter/CascDCABachPV"), trk2ptXi, trk2DCABachPV); + histos.fill(HIST("QAafter/CascDCAPosPV"), trk2ptXi, trk2DCAPosPV); + histos.fill(HIST("QAafter/CascDCANegPV"), trk2ptXi, trk2DCANegPV); + histos.fill(HIST("QAafter/V0CosPA"), trk2ptXi, 1. - trk2V0CosPA); + histos.fill(HIST("QAafter/CascCosPA"), trk2ptXi, 1. - trk2CascCosPA); + histos.fill(HIST("QAafter/V0Radius"), trk2ptXi, trk2V0Radius); + histos.fill(HIST("QAafter/CascRadius"), trk2ptXi, trk2CascRadius); + histos.fill(HIST("QAafter/V0Mass"), trk2ptXi, massLambdaCand); + histos.fill(HIST("QAafter/CascMass"), trk2ptXi, massXiCand); + histos.fill(HIST("QAafter/ProperLifetime"), trk2ptXi, trk2ProperLifetime); } - } - - lDecayDaughter1 = LorentzVectorPtEtaPhiMass(trk1ptPi, trk1.eta(), trk1.phi(), massPi); - lDecayDaughter2 = LorentzVectorPtEtaPhiMass(trk2ptXi, trk2.eta(), trk2.phi(), trk2.mXi()); - lResonance = lDecayDaughter1 + lDecayDaughter2; - auto lResonancePt = lResonance.Pt(); - auto lResonanceInMass = lResonance.M(); - - if (std::abs(lResonance.Rapidity()) >= cfgRapidityCut) - continue; - - if (cfgCutsOnMother) { - if (lResonancePt >= cMaxPtMotherCut) // excluding candidates in overflow - continue; - if (lResonanceInMass >= cMaxMinvMotherCut) // excluding candidates in overflow - continue; - } - - if (trk1.sign() * trk2.sign() < 0) { - - if constexpr (!IsMix) { - if (studyAntiparticle) { - if (trk1.sign() > 0) { - if (invMass1D) - histos.fill(HIST("Xi1530invmassDS"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassDS"), multiplicity, lResonancePt, lResonanceInMass, kData); - } else if (trk1.sign() < 0) { - if (invMass1D) - histos.fill(HIST("Xi1530invmassDSAnti"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassDSAnti"), multiplicity, lResonancePt, lResonanceInMass, kData); - } - } else { - if (invMass1D) - histos.fill(HIST("Xi1530invmassDS"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassDS"), multiplicity, lResonancePt, lResonanceInMass, kData); - } - - if (studyStableXi) { - if (trk1.sign() > 0) { - histos.fill(HIST("h3XiinvmassDS"), multiplicity, trk2ptXi, trk2Mass, kData); - } else if (trk1.sign() < 0) { - histos.fill(HIST("h3XiinvmassDSAnti"), multiplicity, trk2ptXi, trk2Mass, kData); - } - } - } else { - if (invMass1D) - histos.fill(HIST("Xi1530invmassME"), lResonanceInMass); - if (trk1.sign() > 0) { - if (invMass1D) - histos.fill(HIST("Xi1530invmassME_DS"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassME_DS"), multiplicity, lResonancePt, lResonanceInMass, kMixing); - } else if (trk1.sign() < 0) { - if (invMass1D) - histos.fill(HIST("Xi1530invmassME_DSAnti"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassME_DSAnti"), multiplicity, lResonancePt, lResonanceInMass, kMixing); + if (additionalConfig.studyStableXi) { + if (trk2.sign() < 0) { + histos.fill(HIST("h3XiinvmassDS"), Cent, trk2ptXi, massXiCand, kData); + } else if (trk2.sign() > 0) { + histos.fill(HIST("h3XiinvmassDSAnti"), Cent, trk2ptXi, massXiCand, kData); } - histos.fill(HIST("h3Xi1530invmassME"), multiplicity, lResonancePt, lResonanceInMass, kMixing); - - if (studyStableXi) { - if (trk1.sign() > 0) { - histos.fill(HIST("h3XiinvmassME_DS"), multiplicity, trk2ptXi, trk2Mass, kMixing); - } else if (trk1.sign() < 0) { - histos.fill(HIST("h3XiinvmassME_DSAnti"), multiplicity, trk2ptXi, trk2Mass, kMixing); + if constexpr (IsMC) { + if (trk2.motherPDG() > 0) { + histos.fill(HIST("h3RecXiinvmass"), Cent, trk2ptXi, massXiCand, kMCReco); + } else { + histos.fill(HIST("h3RecXiinvmassAnti"), Cent, trk2ptXi, massXiCand, kMCReco); } } } - if constexpr (IsMC) { - if (std::abs(trk2.motherPDG()) != kXiStar) - continue; - if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kXiMinus) - continue; - if (trk1.motherId() != trk2.motherId()) - continue; - - histos.fill(HIST("QAMCTrue/trkDCAxy_pi"), trk1ptPi, trk1DCAXY); - histos.fill(HIST("QAMCTrue/trkDCAxy_xi"), trk2ptXi, trk2DCAXY); - histos.fill(HIST("QAMCTrue/trkDCAz_pi"), trk1ptPi, trk1DCAZ); - histos.fill(HIST("QAMCTrue/trkDCAz_xi"), trk2ptXi, trk2DCAZ); - - if (additionalQAplots) { - histos.fill(HIST("QAMCTrue/V0sDCADoughter_aspt"), trk2ptXi, trk2DCAV0sDougthers); - histos.fill(HIST("QAMCTrue/CascDCADoughter_aspt"), trk2ptXi, trk2DCACascDougthers); - histos.fill(HIST("QAMCTrue/CascMass_aspt"), trk2ptXi, trk2Mass); - histos.fill(HIST("QAMCTrue/V0sCosPA_aspt"), trk2ptXi, 1. - trk2V0sCosPA); - histos.fill(HIST("QAMCTrue/CascCosPA_aspt"), trk2ptXi, 1. - trk2CascCosPA); - } - - histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_first_all"), multiplicity, trk1ptPi, trk1NSigmaPiTPC); - if (hasSubsystemInfo(trk1NSigmaPiTOF)) { - histos.fill(HIST("QAMCTrue/TOF_Nsigma_pi_first_all"), multiplicity, trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_first_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } + } - if (trk2.sign() < 0) { - histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_bachelor_all"), multiplicity, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. - if (hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) { - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_bachelor_all"), trk2NSigmaPiBachelorTOF, trk2NSigmaPiBachelorTPC); - } + xiCandateIndicies.push_back(trk2.index()); + } - histos.fill(HIST("QAMCTrue/TPC_Nsigma_pr_all"), multiplicity, 0, trk2NSigmaPrPosTPC); - if (hasSubsystemInfo(trk2NSigmaPrPosTOF)) { - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pr_all"), trk2NSigmaPrPosTOF, trk2NSigmaPrPosTPC); - } + for (const auto& trk1cand : pionCandateIndicies) { + auto pionCand = dTracks1.iteratorAt(trk1cand); + for (const auto& trk2cand : xiCandateIndicies) { + auto xiCand = dTracks2.iteratorAt(trk2cand); + auto pionCandPt = pionCand.pt(); + auto xiCandPt = xiCand.pt(); + float massXiCand = xiCand.mXi(); + if (additionalConfig.cUseFixedMassXi) + massXiCand = cascadeConfig.cMassXiminus; - histos.fill(HIST("QAMCTrue/TPC_Nsigma_piminus_all"), multiplicity, 0, trk2NSigmaPiNegTPC); - if (hasSubsystemInfo(trk2NSigmaPiNegTOF)) { - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_piminus_all"), trk2NSigmaPiNegTOF, trk2NSigmaPiNegTPC); - } + lDecayDaughter1 = LorentzVectorPtEtaPhiMass(pionCandPt, pionCand.eta(), pionCand.phi(), massPi); + lDecayDaughter2 = LorentzVectorPtEtaPhiMass(xiCandPt, xiCand.eta(), xiCand.phi(), massXiCand); - } else { + lResonance = lDecayDaughter1 + lDecayDaughter2; + auto lResonanceMass = lResonance.M(); + auto lResonancePt = lResonance.Pt(); - histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_bachelor_all"), multiplicity, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. - if (hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) { - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_bachelor_all"), trk2NSigmaPiBachelorTOF, trk2NSigmaPiBachelorTPC); - } + if ((lResonance.Rapidity() <= primarytrackConfig.cfgRapidityMinCut) || (lResonance.Rapidity() >= primarytrackConfig.cfgRapidityMaxCut)) + continue; - histos.fill(HIST("QAMCTrue/TPC_Nsigma_antipr_all"), multiplicity, 0, trk2NSigmaPrNegTPC); - if (hasSubsystemInfo(trk2NSigmaPrNegTOF)) { - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_antipr_all"), trk2NSigmaPrNegTOF, trk2NSigmaPrNegTPC); - } + if (additionalConfig.cfgCutsOnMother) { + if (lResonancePt >= additionalConfig.cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (lResonanceMass >= additionalConfig.cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } - histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_all"), multiplicity, 0, trk2NSigmaPiPosTPC); - if (hasSubsystemInfo(trk2NSigmaPiPosTOF)) { - histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_all"), trk2NSigmaPiPosTOF, trk2NSigmaPiPosTPC); + if (pionCand.sign() * xiCand.sign() < 0) { // Signal candidates + + if constexpr (!IsMix) { + if (pionCand.sign() > 0) { + if (histoConfig.invMass1D) + histos.fill(HIST("Xi1530invmassDS"), lResonanceMass); + histos.fill(HIST("h3Xi1530invmassDS"), Cent, lResonancePt, lResonanceMass, kData); + if (additionalConfig.cfgFillRotBkg) { + for (int i = 0; i < additionalConfig.cfgNrotBkg; i++) { + auto lRotAngle = additionalConfig.cfgMinRot + i * ((additionalConfig.cfgMaxRot - additionalConfig.cfgMinRot) / (additionalConfig.cfgNrotBkg - 1)); + histos.fill(HIST("QAevent/hRotBkg"), lRotAngle); + if (additionalConfig.cfgRotPion) { + lDaughterRot = lDecayDaughter1; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot.Vect(); + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lDaughterRot + lDecayDaughter2; + } else { + lDaughterRot = lDecayDaughter2; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot.Vect(); + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lDecayDaughter1 + lDaughterRot; + } + histos.fill(HIST("h3Xi1530invmassRotDS"), Cent, lResonanceRot.Pt(), lResonanceRot.M(), kData); + } + } + + } else if (pionCand.sign() < 0) { + if (histoConfig.invMass1D) + histos.fill(HIST("Xi1530invmassDSAnti"), lResonanceMass); + histos.fill(HIST("h3Xi1530invmassDSAnti"), Cent, lResonancePt, lResonanceMass, kData); + if (additionalConfig.cfgFillRotBkg) { + for (int i = 0; i < additionalConfig.cfgNrotBkg; i++) { + auto lRotAngle = additionalConfig.cfgMinRot + i * ((additionalConfig.cfgMaxRot - additionalConfig.cfgMinRot) / (additionalConfig.cfgNrotBkg - 1)); + histos.fill(HIST("QAevent/hRotBkg"), lRotAngle); + if (additionalConfig.cfgRotPion) { + lDaughterRot = lDecayDaughter1; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot.Vect(); + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lDaughterRot + lDecayDaughter2; + } else { + lDaughterRot = lDecayDaughter2; + ROOT::Math::RotationZ rot(lRotAngle); + auto p3 = rot * lDaughterRot.Vect(); + lDaughterRot = LorentzVectorSetXYZM(p3.X(), p3.Y(), p3.Z(), lDaughterRot.M()); + lResonanceRot = lDecayDaughter1 + lDaughterRot; + } + histos.fill(HIST("h3Xi1530invmassRotDSAnti"), Cent, lResonanceRot.Pt(), lResonanceRot.M(), kData); + } + } } - } - // MC histograms - if (trk2.motherPDG() > 0) { - histos.fill(HIST("Xi1530Rec"), lResonancePt, multiplicity); - histos.fill(HIST("Xi1530Recinvmass"), lResonanceInMass); - histos.fill(HIST("h3RecXi1530invmass"), multiplicity, lResonancePt, lResonanceInMass, kMCReco); - histos.fill(HIST("h3RecXiinvmass"), multiplicity, trk2ptXi, trk2Mass, kMCReco); } else { - histos.fill(HIST("Xi1530RecAnti"), lResonancePt, multiplicity); - histos.fill(HIST("Xi1530Recinvmass"), lResonanceInMass); - histos.fill(HIST("h3RecXi1530invmassAnti"), multiplicity, lResonancePt, lResonanceInMass, kMCReco); - histos.fill(HIST("h3RecXiinvmassAnti"), multiplicity, trk2ptXi, trk2Mass, kMCReco); + if (pionCand.sign() > 0) { + histos.fill(HIST("h3Xi1530invmassME_DS"), Cent, lResonancePt, lResonanceMass, kData); + } else if (pionCand.sign() < 0) { + histos.fill(HIST("h3Xi1530invmassME_DSAnti"), Cent, lResonancePt, lResonanceMass, kData); + } } - } - } else { - if constexpr (!IsMix) { - if (studyAntiparticle) { - if (trk1.sign() < 0) { - if (invMass1D) - histos.fill(HIST("Xi1530invmassLS"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassLS"), multiplicity, lResonancePt, lResonanceInMass, kLS); - histos.fill(HIST("h3XiinvmassLS"), multiplicity, trk2ptXi, trk2Mass, kLS); - } else if (trk1.sign() > 0) { - if (invMass1D) - histos.fill(HIST("Xi1530invmassLSAnti"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassLSAnti"), multiplicity, lResonancePt, lResonanceInMass, kLS); - histos.fill(HIST("h3XiinvmassLSAnti"), multiplicity, trk2ptXi, trk2Mass, kLS); + if constexpr (IsMC) { + if (std::abs(xiCand.motherPDG()) != kXiStar) + continue; + if (std::abs(pionCand.pdgCode()) != kPiPlus || std::abs(xiCand.pdgCode()) != kXiMinus) + continue; + if (pionCand.motherId() != xiCand.motherId()) + continue; + auto lResonancePtMC = xiCand.motherPt(); + if (additionalConfig.cUseTruthRapidity) + continue; + if ((xiCand.motherRap() >= primarytrackConfig.cfgRapidityMaxCut) || (xiCand.motherRap() <= primarytrackConfig.cfgRapidityMinCut)) + continue; + if (histoConfig.truthQA) { + float trk1DCAXY = -1.f; + float trk1DCAZ = -1.f; + float trk1NSigmaPiTPC = -999.f; + float trk1NSigmaPiTOF = -999.f; + if constexpr (IsResoMicrotrack) { + trk1DCAXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(pionCand.trackSelectionFlags()); + trk1DCAZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(pionCand.trackSelectionFlags()); + trk1NSigmaPiTPC = o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(pionCand.pidNSigmaPiFlag()); + trk1NSigmaPiTOF = o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(pionCand.pidNSigmaPiFlag()); + } else { + trk1DCAXY = pionCand.dcaXY(); + trk1DCAZ = pionCand.dcaZ(); + trk1NSigmaPiTPC = pionCand.tpcNSigmaPi(); + trk1NSigmaPiTOF = pionCand.tofNSigmaPi(); + } + + auto trk2DCAXY = xiCand.dcaXYCascToPV(); + auto trk2DCAZ = xiCand.dcaZCascToPV(); + auto trk2ProperLifetime = properLifetime(collision, xiCand); + auto massLambdaCand = xiCand.mLambda(); + + auto trk2DCAV0TopPV = xiCand.dcav0topv(); + auto trk2DCAV0sDougthers = xiCand.daughDCA(); // V0s daughter DCA + auto trk2DCACascDougthers = xiCand.cascDaughDCA(); + auto trk2DCABachPV = xiCand.dcabachtopv(); + auto trk2DCAPosPV = xiCand.dcapostopv(); + auto trk2DCANegPV = xiCand.dcanegtopv(); + auto trk2V0CosPA = xiCand.v0CosPA(); + auto trk2CascCosPA = xiCand.cascCosPA(); + auto trk2V0Radius = xiCand.transRadius(); + auto trk2CascRadius = xiCand.cascTransRadius(); + + // auto trk2ptPiBachelor = xiCand.pt(); + float trk2NSigmaPiBachelorTPC = xiCand.daughterTPCNSigmaBachPi(); + float trk2NSigmaPiBachelorTOF = xiCand.daughterTOFNSigmaBachPi(); + // auto trk2ptPr = xiCand.pt(); + float trk2NSigmaPrPosTPC = xiCand.daughterTPCNSigmaPosPr(); + float trk2NSigmaPrNegTPC = xiCand.daughterTPCNSigmaNegPr(); + + float trk2NSigmaPrPosTOF = xiCand.daughterTOFNSigmaPosPr(); + float trk2NSigmaPrNegTOF = xiCand.daughterTOFNSigmaNegPr(); + + // auto trk2ptPi = xiCand.pt(); + float trk2NSigmaPiPosTPC = xiCand.daughterTPCNSigmaPosPi(); + float trk2NSigmaPiNegTPC = xiCand.daughterTPCNSigmaNegPi(); + + float trk2NSigmaPiPosTOF = xiCand.daughterTOFNSigmaPosPi(); + float trk2NSigmaPiNegTOF = xiCand.daughterTOFNSigmaNegPi(); + + histos.fill(HIST("QAMCTrue/trkDCAxy_pi"), pionCandPt, trk1DCAXY); + histos.fill(HIST("QAMCTrue/trkDCAz_pi"), pionCandPt, trk1DCAZ); + histos.fill(HIST("QAMCTrue/V0DCATopPV"), xiCandPt, trk2DCAV0TopPV); + histos.fill(HIST("QAMCTrue/trkDCAxy_Xi"), xiCandPt, trk2DCAXY); + histos.fill(HIST("QAMCTrue/trkDCAz_Xi"), xiCandPt, trk2DCAZ); + + histos.fill(HIST("QAMCTrue/V0DCADoughter"), xiCandPt, trk2DCAV0sDougthers); + histos.fill(HIST("QAMCTrue/CascDCADoughter"), xiCandPt, trk2DCACascDougthers); + histos.fill(HIST("QAMCTrue/CascDCABachPV"), xiCandPt, trk2DCABachPV); + histos.fill(HIST("QAMCTrue/CascDCAPosPV"), xiCandPt, trk2DCAPosPV); + histos.fill(HIST("QAMCTrue/CascDCANegPV"), xiCandPt, trk2DCANegPV); + histos.fill(HIST("QAMCTrue/V0CosPA"), xiCandPt, 1. - trk2V0CosPA); + histos.fill(HIST("QAMCTrue/CascCosPA"), xiCandPt, 1. - trk2CascCosPA); + histos.fill(HIST("QAMCTrue/V0Radius"), xiCandPt, trk2V0Radius); + histos.fill(HIST("QAMCTrue/CascRadius"), xiCandPt, trk2CascRadius); + histos.fill(HIST("QAMCTrue/V0Mass"), xiCandPt, massLambdaCand); + histos.fill(HIST("QAMCTrue/CascMass"), xiCandPt, massXiCand); + histos.fill(HIST("QAMCTrue/ProperLifetime"), xiCandPt, trk2ProperLifetime); + + histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_first_all"), Cent, pionCandPt, trk1NSigmaPiTPC); + if (hasSubsystemInfo(trk1NSigmaPiTOF)) { + histos.fill(HIST("QAMCTrue/TOF_Nsigma_pi_first_all"), Cent, pionCandPt, trk1NSigmaPiTOF); + histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_first_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + + histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_bachelor_all"), Cent, 0, trk2NSigmaPiBachelorTPC); // not exist pt information in resocascade yet. + if (hasSubsystemInfo(trk2NSigmaPiBachelorTOF)) { + histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_bachelor_all"), trk2NSigmaPiBachelorTOF, trk2NSigmaPiBachelorTPC); + } + + histos.fill(HIST("QAMCTrue/TPC_Nsigma_pr_all"), Cent, 0, trk2NSigmaPrPosTPC); + if (hasSubsystemInfo(trk2NSigmaPrPosTOF)) { + histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pr_all"), trk2NSigmaPrPosTOF, trk2NSigmaPrPosTPC); + } + histos.fill(HIST("QAMCTrue/TPC_Nsigma_antipr_all"), Cent, 0, trk2NSigmaPrNegTPC); + if (hasSubsystemInfo(trk2NSigmaPrNegTOF)) { + histos.fill(HIST("QAMCTrue/TOF_TPC_Map_antipr_all"), trk2NSigmaPrNegTOF, trk2NSigmaPrNegTPC); + } + + histos.fill(HIST("QAMCTrue/TPC_Nsigma_piminus_all"), Cent, 0, trk2NSigmaPiNegTPC); + if (hasSubsystemInfo(trk2NSigmaPiNegTOF)) { + histos.fill(HIST("QAMCTrue/TOF_TPC_Map_piminus_all"), trk2NSigmaPiNegTOF, trk2NSigmaPiNegTPC); + } + histos.fill(HIST("QAMCTrue/TPC_Nsigma_pi_all"), Cent, 0, trk2NSigmaPiPosTPC); + if (hasSubsystemInfo(trk2NSigmaPiPosTOF)) { + histos.fill(HIST("QAMCTrue/TOF_TPC_Map_pi_all"), trk2NSigmaPiPosTOF, trk2NSigmaPiPosTPC); + } + + } // truthQA + + // MC histograms + if (xiCand.motherPDG() > 0) { + histos.fill(HIST("Xi1530Rec"), lResonancePt, Cent); + histos.fill(HIST("Xi1530Recinvmass"), lResonanceMass); + histos.fill(HIST("h3RecXi1530invmass"), Cent, lResonancePt, lResonanceMass, lResonancePtMC); + } else { + histos.fill(HIST("Xi1530RecAnti"), lResonancePt, Cent); + histos.fill(HIST("Xi1530Recinvmass"), lResonanceMass); + histos.fill(HIST("h3RecXi1530invmassAnti"), Cent, lResonancePt, lResonanceMass, lResonancePtMC); + } + } // is MC + } else { // Bkg candidates + if constexpr (!IsMix) { + if (pionCand.sign() < 0) { + if (histoConfig.invMass1D) + histos.fill(HIST("Xi1530invmassLS"), lResonanceMass); + histos.fill(HIST("h3Xi1530invmassLS"), Cent, lResonancePt, lResonanceMass, kLS); + } else if (pionCand.sign() > 0) { + if (histoConfig.invMass1D) + histos.fill(HIST("Xi1530invmassLSAnti"), lResonanceMass); + histos.fill(HIST("h3Xi1530invmassLSAnti"), Cent, lResonancePt, lResonanceMass, kLS); } - } else { - if (invMass1D) - histos.fill(HIST("Xi1530invmassLS"), lResonanceInMass); - histos.fill(HIST("h3Xi1530invmassLS"), multiplicity, lResonancePt, lResonanceInMass, kLS); - histos.fill(HIST("h3XiinvmassLS"), multiplicity, trk2ptXi, trk2Mass, kLS); } - } - } - } - } + } // -> End if signal or bkg + } // -> End loop over xi candidates + } // -> End loop over pion and xi candidates + } // -> End fillHistograms void processData(aod::ResoCollision const& resoCollision, - aod::ResoCollisionColls const& collisionIndex, - soa::Join const& collisions, aod::ResoTracks const& resoTracks, aod::ResoCascades const& cascTracks) { - if (cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisions.iteratorAt(collId); // Take original collision matched with resoCollision + auto inCent = resoCollision.cent(); + auto multiplicity = 0.f; - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + if (additionalConfig.cMultNTracksPVFull) + multiplicity = resoCollision.multNTracksPV(); + else if (additionalConfig.cMultNTracksPVeta1) + multiplicity = resoCollision.multNTracksPVeta1(); + else if (additionalConfig.cMultNTracksPVetaHalf) + multiplicity = resoCollision.multNTracksPVetaHalf(); + + if (histoConfig.multQA) { + histos.fill(HIST("multQA/h2MultCent"), inCent, multiplicity); } - - histos.fill(HIST("QAevent/hEvtCounterSameE"), 1.0); - auto multiplicity = resoCollision.cent(); - fillHistograms(resoCollision, multiplicity, resoTracks, cascTracks); + fillHistograms(resoCollision, inCent, resoTracks, cascTracks); } - // Reconstructed level MC for the track + // Calculate numerator for the Acceptance x Efficiency void processMC(ResoMCCols::iterator const& resoCollision, - aod::ResoCollisionColls const& collisionIndex, - soa::Join const& collisionsMC, soa::Join const& cascTracks, - soa::Join const& resoTracks, - soa::Join const&) + soa::Join const& resoTracks) { - float multiplicity; - if (cMCCent && cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision - - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - auto mcColl = coll.mcCollision_as>(); - multiplicity = mcColl.centFT0M(); - } else if (!cMCCent && cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision - - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - multiplicity = resoCollision.cent(); - } else if (cMCCent && !cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision - - auto mcColl = coll.mcCollision_as>(); - multiplicity = mcColl.centFT0M(); - } else { - multiplicity = resoCollision.cent(); - } - - if (!resoCollision.isInAfterAllCuts() || (std::abs(resoCollision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + auto inCent = resoCollision.cent(); + float multiplicity = 0.f; + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision return; - - fillHistograms(resoCollision, multiplicity, resoTracks, cascTracks); + if (additionalConfig.cMultNTracksPVFull) + multiplicity = resoCollision.multNTracksPV(); + else if (additionalConfig.cMultNTracksPVeta1) + multiplicity = resoCollision.multNTracksPVeta1(); + else if (additionalConfig.cMultNTracksPVetaHalf) + multiplicity = resoCollision.multNTracksPVetaHalf(); + + if (!resoCollision.isInAfterAllCuts()) // MC event selection, all cuts missing vtx cut + return; + if (histoConfig.multQA) { + histos.fill(HIST("multQA/h2MultCent"), inCent, multiplicity); + } + fillHistograms(resoCollision, inCent, resoTracks, cascTracks); } - // Truth level MC for the track with reco event + // Calculate denominator for the Acceptance x Efficiency, actually it is not Trueth info... void processMCTrue(ResoMCCols::iterator const& resoCollision, - aod::ResoCollisionColls const& collisionIndex, - aod::ResoMCParents const& resoParents, - aod::ResoCollisionCandidatesMC const& collisionsMC, - soa::Join const&) + aod::ResoMCParents const& resoParents) { - float multiplicity; - if (cMCCent && cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision - - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - auto mcColl = coll.mcCollision_as>(); - multiplicity = mcColl.centFT0M(); - } else if (!cMCCent && cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision - - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; - - multiplicity = resoCollision.cent(); - } else if (cMCCent && !cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisionsMC.iteratorAt(collId); // Take original collision matched with resoCollision - - auto mcColl = coll.mcCollision_as>(); - multiplicity = mcColl.centFT0M(); - } else { - multiplicity = resoCollision.cent(); + auto multiplicity = resoCollision.mcMultiplicity(); + auto inCent = resoCollision.cent(); + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + if (!resoCollision.isInAfterAllCuts()) + return; + if (histoConfig.multQA) { + histos.fill(HIST("multQA/h2MultCentMC"), inCent, multiplicity); } for (const auto& part : resoParents) { // loop over all pre-filtered MC particles - if (std::abs(part.pdgCode()) != kXiStar || std::abs(part.y()) >= cfgRapidityCut) + if (std::abs(part.pdgCode()) != kXiStar) + continue; + if ((part.y() <= primarytrackConfig.cfgRapidityMinCut) || (part.y() >= primarytrackConfig.cfgRapidityMaxCut)) continue; bool pass1 = std::abs(part.daughterPDG1()) == kPiPlus || std::abs(part.daughterPDG2()) == kPiPlus; bool pass2 = std::abs(part.daughterPDG1()) == kXiMinus || std::abs(part.daughterPDG2()) == kXiMinus; @@ -1170,114 +1316,82 @@ struct Xi1530Analysisqa { if (!pass1 || !pass2) continue; - if (part.pdgCode() > 0) // INELt0 or INEL - histos.fill(HIST("h3Xi1530Gen"), -1, part.pt(), multiplicity); - else - histos.fill(HIST("h3Xi1530GenAnti"), -1, part.pt(), multiplicity); - - if (resoCollision.isVtxIn10()) // vtx10 - { - if (part.pdgCode() > 0) - histos.fill(HIST("h3Xi1530Gen"), 0, part.pt(), multiplicity); - else - histos.fill(HIST("h3Xi1530GenAnti"), 0, part.pt(), multiplicity); - } - if (resoCollision.isVtxIn10() && resoCollision.isInSel8()) // vtx10 && sel8 - { - if (part.pdgCode() > 0) - histos.fill(HIST("h3Xi1530Gen"), 1, part.pt(), multiplicity); - else - histos.fill(HIST("h3Xi1530GenAnti"), 1, part.pt(), multiplicity); - } - if (resoCollision.isVtxIn10() && resoCollision.isTriggerTVX()) // vtx10 && TriggerTVX - { - if (part.pdgCode() > 0) - histos.fill(HIST("h3Xi1530Gen"), 2, part.pt(), multiplicity); - else - histos.fill(HIST("h3Xi1530GenAnti"), 2, part.pt(), multiplicity); - } if (resoCollision.isInAfterAllCuts()) // after all event selection { if (part.pdgCode() > 0) - histos.fill(HIST("h3Xi1530Gen"), 3, part.pt(), multiplicity); + histos.fill(HIST("h3Xi1530Gen"), part.pt(), inCent, multiplicity); else - histos.fill(HIST("h3Xi1530GenAnti"), 3, part.pt(), multiplicity); + histos.fill(HIST("h3Xi1530GenAnti"), part.pt(), inCent, multiplicity); } } } void processDataMicro(aod::ResoCollision const& resoCollision, - aod::ResoCollisionColls const& collisionIndex, - soa::Join const& collisions, aod::ResoMicroTracks const& resomicrotracks, aod::ResoCascades const& cascTracks) { - if (cRecoINELgt0) { - auto linkRow = collisionIndex.iteratorAt(resoCollision.globalIndex()); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisions.iteratorAt(collId); // Take original collision matched with resoCollision - - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - return; + float multiplicity = 0.f; + auto inCent = resoCollision.cent(); + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + return; + if (additionalConfig.cMultNTracksPVFull) + multiplicity = resoCollision.multNTracksPV(); + else if (additionalConfig.cMultNTracksPVeta1) + multiplicity = resoCollision.multNTracksPVeta1(); + else if (additionalConfig.cMultNTracksPVetaHalf) + multiplicity = resoCollision.multNTracksPVetaHalf(); + + if (histoConfig.multQA) { + histos.fill(HIST("multQA/h2MultCent"), inCent, multiplicity); } - - histos.fill(HIST("QAevent/hEvtCounterSameE"), 1.0); - auto multiplicity = resoCollision.cent(); - fillHistograms(resoCollision, multiplicity, resomicrotracks, cascTracks); + fillHistograms(resoCollision, inCent, resomicrotracks, cascTracks); } using BinningTypeVtxZT0M = ColumnBinningPolicy; - Preslice perRColdf = aod::resodaughter::resoCollisionDFId; - Preslice perRColdfCasc = aod::resodaughter::resoCollisionDFId; - - void processMEDF(aod::ResoCollisionDFs const& resoCollisions, aod::ResoTrackDFs const& resotracks, aod::ResoCascadeDFs const& cascTracks) + void processMEMicro(aod::ResoCollisions const& resoCollisions, + aod::ResoMicroTracks const& resomicrotracks, + aod::ResoCascades const& cascTracks) { + auto tracksTuple = std::make_tuple(resomicrotracks, cascTracks); - auto tracksTuple = std::make_tuple(resotracks, cascTracks); - - BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; - Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, tracksTuple, &cache}; + BinningTypeVtxZT0M colBinning{{mixingConfig.cfgVtxBins, mixingConfig.cfgMultBins}, true}; + Pair pairs{colBinning, mixingConfig.nEvtMixing, -1, resoCollisions, tracksTuple, &cache}; for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { - histos.fill(HIST("QAevent/hEvtCounterMixedE"), 1.0); - auto multiplicity = collision1.cent(); - fillHistograms(collision1, multiplicity, tracks1, tracks2); + float multiplicity = 0.f; + auto inCent = collision1.cent(); + if (additionalConfig.cRecoINELgt0 && !collision1.isRecINELgt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision + continue; + if (additionalConfig.cMultNTracksPVFull) + multiplicity = collision1.multNTracksPV(); + else if (additionalConfig.cMultNTracksPVeta1) + multiplicity = collision1.multNTracksPVeta1(); + else if (additionalConfig.cMultNTracksPVetaHalf) + multiplicity = collision1.multNTracksPVetaHalf(); + + if (histoConfig.multQA) { + histos.fill(HIST("multQA/h2MultCent"), inCent, multiplicity); + } + fillHistograms(collision1, inCent, tracks1, tracks2); } } - void processDataDF(aod::ResoCollisionDF const& resoCollision, aod::ResoTrackDFs const& resotracks, aod::ResoCascadeDFs const& cascTracks) + void processMEDF(aod::ResoCollisionDFs const& resoCollisions, aod::ResoTrackDFs const& resotracks, aod::ResoCascadeDFs const& cascTracks) { - auto multiplicity = resoCollision.cent(); - fillHistograms(resoCollision, multiplicity, resotracks, cascTracks); - } - void processMEMicro(aod::ResoCollisions const& resoCollisions, - aod::ResoCollisionColls const& collisionIndex, - soa::Join const& collisions, - aod::ResoMicroTracks const& resomicrotracks, - aod::ResoCascades const& cascTracks) - { - auto tracksTuple = std::make_tuple(resomicrotracks, cascTracks); + auto tracksTuple = std::make_tuple(resotracks, cascTracks); - BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; - Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, tracksTuple, &cache}; + BinningTypeVtxZT0M colBinning{{mixingConfig.cfgVtxBins, mixingConfig.cfgMultBins}, true}; + Pair pairs{colBinning, mixingConfig.nEvtMixing, -1, resoCollisions, tracksTuple, &cache}; for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { - if (cRecoINELgt0) { - const auto rcIdx = collision1.globalIndex(); - auto linkRow = collisionIndex.iteratorAt(rcIdx); - auto collId = linkRow.collisionId(); // Take original collision global index matched with resoCollision - - auto coll = collisions.iteratorAt(collId); // Take original collision matched with resoCollision - - if (!coll.isInelGt0()) // Check reco INELgt0 (at least one PV track in |eta| < 1) about the collision - continue; + float multiplicity = 0.f; + auto inCent = collision1.cent(); + if (histoConfig.multQA) { + histos.fill(HIST("multQA/h2MultCent"), inCent, multiplicity); } - histos.fill(HIST("QAevent/hEvtCounterMixedE"), 1.0); - auto multiplicity = collision1.cent(); - fillHistograms(collision1, multiplicity, tracks1, tracks2); + fillHistograms(collision1, inCent, tracks1, tracks2); } } @@ -1286,8 +1400,7 @@ struct Xi1530Analysisqa { PROCESS_SWITCH(Xi1530Analysisqa, processMCTrue, "Process Event for MC (Generated)", false); PROCESS_SWITCH(Xi1530Analysisqa, processDataMicro, "Process Event for Data (MicroTrack)", false); PROCESS_SWITCH(Xi1530Analysisqa, processMEMicro, "Process EventMixing (MicroTrack) ", false); - PROCESS_SWITCH(Xi1530Analysisqa, processMEDF, "Process EventMixing (DF) ", true); - PROCESS_SWITCH(Xi1530Analysisqa, processDataDF, "Process Event for Data (DF) ", true); + PROCESS_SWITCH(Xi1530Analysisqa, processMEDF, "Process EventMixing (DataFrame) ", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Resonances/xi1820Analysis.cxx b/PWGLF/Tasks/Resonances/xi1820Analysis.cxx index 997c68a5015..1528ac712b5 100644 --- a/PWGLF/Tasks/Resonances/xi1820Analysis.cxx +++ b/PWGLF/Tasks/Resonances/xi1820Analysis.cxx @@ -11,7 +11,8 @@ /// \file xi1820Analysis.cxx /// \brief Invariant Mass Reconstruction of Xi(1820) Resonance -/// \author Bong-Hwi Lim +/// +/// \author Bong-Hwi Lim , Minjae Kim #include "PWGLF/DataModel/LFResonanceTables.h" @@ -40,11 +41,12 @@ struct Xi1820Analysis { Preslice perResoCollisionTrack = aod::resodaughter::resoCollisionId; Preslice perResoCollisionMicroTrack = aod::resodaughter::resoCollisionId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + using ResoMCCols = soa::Join; // Constants static constexpr float kSmallMomentumDenominator = 1e-10f; // Small value to avoid division by zero - static constexpr float kMaxDcaToPv = 1.0f; // Maximum DCA to primary vertex - static constexpr int kPdgXi1820 = 123314; // o2-linter: disable=pdg/explicit-code (Xi(1820) PDG code not available in PDG_t or o2::constants::physics::Pdg) + static constexpr int kPdgChagedXi1820 = 123314; // o2-linter: disable=pdg/explicit-code (Xi(1820) PDG code not available in PDG_t or o2::constants::physics::Pdg) + static constexpr int kPdgXi1820Zero = 123324; // o2-linter: disable=pdg/explicit-code (Xi(1820) PDG code not available in PDG_t or o2::constants::physics::Pdg) static constexpr int kExpectedDaughters = 2; // Expected number of daughters for two-body decay // Axes @@ -52,7 +54,7 @@ struct Xi1820Analysis { ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0}, "pT (QA)"}; ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Centrality"}; - // Invariant mass range for Xi(1820) → Λ + K + // Invariant mass range for Xi(1820) to Λ + K Configurable cInvMassStart{"cInvMassStart", 1.6, "Invariant mass start (GeV/c^2)"}; Configurable cInvMassEnd{"cInvMassEnd", 2.2, "Invariant mass end (GeV/c^2)"}; Configurable cInvMassBins{"cInvMassBins", 600, "Invariant mass bins"}; @@ -72,48 +74,64 @@ struct Xi1820Analysis { Configurable cKaonITSNClusMin{"cKaonITSNClusMin", 2, "Minimum ITS clusters for kaon"}; // Kaon PID selections - Configurable cKaonTPCNSigmaMax{"cKaonTPCNSigmaMax", 3.0, "Maximum TPC NSigma for kaon (if not using pT-dependent)"}; - Configurable cKaonTOFNSigmaMax{"cKaonTOFNSigmaMax", 3.0, "Maximum TOF NSigma for kaon (if not using pT-dependent)"}; + Configurable cKaonTPCNSigmaMax{"cKaonTPCNSigmaMax", 3.5, "Maximum TPC NSigma for kaon (if not using pT-dependent)"}; + Configurable cKaonTOFNSigmaMax{"cKaonTOFNSigmaMax", 999., "Maximum TOF NSigma for kaon (if not using pT-dependent)"}; Configurable cKaonUsePtDepPID{"cKaonUsePtDepPID", false, "Use pT-dependent PID cuts"}; Configurable> cKaonPIDPtBins{"cKaonPIDPtBins", {0.0f, 0.5f, 0.8f, 2.0f, 999.0f}, "pT bin edges for PID cuts (N+1 values for N bins)"}; Configurable> cKaonTPCNSigmaCuts{"cKaonTPCNSigmaCuts", {3.0f, 3.0f, 2.0f, 2.0f}, "TPC NSigma cuts per pT bin (N values)"}; Configurable> cKaonTOFNSigmaCuts{"cKaonTOFNSigmaCuts", {3.0f, 3.0f, 3.0f, 3.0f}, "TOF NSigma cuts per pT bin (N values)"}; - Configurable> cKaonTOFRequired{"cKaonTOFRequired", {0, 0, 1, 1}, "Require TOF per pT bin (N values, 0=false, 1=true)"}; + Configurable> cKaonTOFRequired{"cKaonTOFRequired", {0, 0, 0, 0}, "Require TOF per pT bin (N values, 0=false, 1=true)"}; // V0 (Lambda) selections Configurable cV0MinCosPA{"cV0MinCosPA", 0.995, "V0 minimum pointing angle cosine"}; - Configurable cV0MaxDaughDCA{"cV0MaxDaughDCA", 1.0, "V0 daughter DCA Maximum"}; - Configurable cV0MassWindow{"cV0MassWindow", 0.005, "Mass window for Lambda selection"}; + Configurable cV0MaxDaughDCA{"cV0MaxDaughDCA", 0.5, "V0 daughter DCA Maximum"}; + Configurable cV0MassWindow{"cV0MassWindow", 0.01, "Mass window for Lambda selection (GeV/c^2)"}; Configurable cMaxV0Etacut{"cMaxV0Etacut", 0.8, "V0 maximum eta cut"}; Configurable cV0RadiusMin{"cV0RadiusMin", 0.5, "V0 decay radius min"}; Configurable cV0RadiusMax{"cV0RadiusMax", 200.0, "V0 decay radius max"}; Configurable cV0DauPosDCAtoPVMin{"cV0DauPosDCAtoPVMin", 0.05, "V0 positive daughter DCA to PV min"}; Configurable cV0DauNegDCAtoPVMin{"cV0DauNegDCAtoPVMin", 0.05, "V0 negative daughter DCA to PV min"}; Configurable cV0ProperLifetimeMax{"cV0ProperLifetimeMax", 30.0, "Lambda proper lifetime max (cm/c)"}; + Configurable cV0sCrossMassRejection{"cV0sCrossMassRejection", true, "Enable K0s mass rejection for Lambda"}; + Configurable cV0sCrossMassRejectionWindow{"cV0sCrossMassRejectionWindow", 0.005, "K0s mass rejection window for Lambda (GeV/c^2)"}; // K0s selections - Configurable cK0sMinCosPA{"cK0sMinCosPA", 0.97, "K0s minimum pointing angle cosine"}; - Configurable cK0sMaxDaughDCA{"cK0sMaxDaughDCA", 1.0, "K0s daughter DCA Maximum"}; - Configurable cK0sMassWindow{"cK0sMassWindow", 0.0043, "Mass window for K0s selection"}; + Configurable cK0sMinCosPA{"cK0sMinCosPA", 0.98, "K0s minimum pointing angle cosine"}; + Configurable cK0sMaxDaughDCA{"cK0sMaxDaughDCA", 0.5, "K0s daughter DCA Maximum"}; + Configurable cK0sMassWindow{"cK0sMassWindow", 0.025, "Mass window for K0s selection (GeV/c^2)"}; Configurable cK0sProperLifetimeMax{"cK0sProperLifetimeMax", 20.0, "K0s proper lifetime max (cm/c)"}; Configurable cK0sArmenterosQtMin{"cK0sArmenterosQtMin", 0.0, "K0s Armenteros qt min"}; - Configurable cK0sArmenterosAlphaMax{"cK0sArmenterosAlphaMax", 0.8, "K0s Armenteros alpha max"}; - Configurable cK0sDauPosDCAtoPVMin{"cK0sDauPosDCAtoPVMin", 0.1, "K0s positive daughter DCA to PV min"}; - Configurable cK0sDauNegDCAtoPVMin{"cK0sDauNegDCAtoPVMin", 0.1, "K0s negative daughter DCA to PV min"}; + Configurable cK0sArmenterosAlphaCoeff{"cK0sArmenterosAlphaCoeff", 0.2, "K0s Armenteros alpha max"}; + Configurable cK0sDauPosDCAtoPVMin{"cK0sDauPosDCAtoPVMin", 0.05, "K0s positive daughter DCA to PV min"}; + Configurable cK0sDauNegDCAtoPVMin{"cK0sDauNegDCAtoPVMin", 0.05, "K0s negative daughter DCA to PV min"}; Configurable cK0sRadiusMin{"cK0sRadiusMin", 0.5, "K0s decay radius min"}; - Configurable cK0sRadiusMax{"cK0sRadiusMax", 100.0, "K0s decay radius max"}; + Configurable cK0sRadiusMax{"cK0sRadiusMax", 200.0, "K0s decay radius max"}; Configurable cK0sCrossMassRejection{"cK0sCrossMassRejection", true, "Enable Lambda mass rejection for K0s"}; + Configurable cK0sCrossMassRejectionWindow{"cK0sCrossMassRejectionWindow", 0.01, "Lambda mass rejection window for K0s (GeV/c^2)"}; // Event Mixing Configurable nEvtMixing{"nEvtMixing", 10, "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 - centrality"}; - // Track type selection - Configurable cUseMicroTracks{"cUseMicroTracks", false, "Use ResoMicroTracks instead of ResoTracks"}; + // Additional QA and configurations + struct : ConfigurableGroup { + Configurable cRecoINELgt0{"cRecoINELgt0", false, "Apply Reco INEL>0 event selection"}; + Configurable cConsiderPairOnly{"cConsiderPairOnly", true, "Consider only the pair of tracks for the charged K + Lambda analysis"}; + Configurable cConsiderHasV0s{"cConsiderHasV0s", true, "Consider only the pair of tracks for the K0s + Lambda analysis"}; + Configurable cUseTruthRapidity{"cUseTruthRapidity", false, "Use truth rapidity for MC generated target"}; + + Configurable cUsePtDepDCAForKaons{"cUsePtDepDCAForKaons", true, "Use pT dependent DCA cuts for kaon tracks"}; + Configurable cDCAToPVByPtFirstP0{"cDCAToPVByPtFirstP0", 0.004, "pT dependent DCA cut first parameter (cm)"}; + Configurable cDCAToPVByPtFirstExp{"cDCAToPVByPtFirstExp", 0.013, "pT dependent DCA cut second parameter (exponent)"}; + Configurable cMaxDcaToPVV0{"cMaxDcaToPVV0", 1.0, "Maximum DCA to PV for V0 candidates (cm)"}; + + Configurable cfgRapidityCut{"cfgRapidityCut", 0.5, "Rapidity cut"}; + ConfigurableAxis multNTracksAxis{"multNTracksAxis", {500, 0, 500}, "N_{tracks}"}; + + } additionalConfig; using BinningTypeVertexContributor = ColumnBinningPolicy; - BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; void init(InitContext&) { @@ -123,137 +141,181 @@ struct Xi1820Analysis { AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^{2})"}; AxisSpec lambdaMassAxis = {200, 1.08, 1.16, "#Lambda mass (GeV/#it{c}^{2})"}; AxisSpec dcaAxis = {200, 0., 2.0, "DCA (cm)"}; - AxisSpec dcaxyAxis = {200, -1.0, 1.0, "DCA_{xy} (cm)"}; - AxisSpec dcazAxis = {200, -2.0, 2.0, "DCA_{z} (cm)"}; + AxisSpec dcaxyAxis = {400, -0.2, 0.2, "DCA_{xy} (cm)"}; + AxisSpec dcazAxis = {400, -0.2, 0.2, "DCA_{z} (cm)"}; AxisSpec cosPAAxis = {1000, 0.95, 1.0, "cos(PA)"}; AxisSpec radiusAxis = {200, 0, 200, "Radius (cm)"}; AxisSpec lifetimeAxis = {200, 0, 50, "Proper lifetime (cm/c)"}; AxisSpec nsigmaAxis = {100, -5.0, 5.0, "N#sigma"}; + AxisSpec armenterosAlphaAxis = {200, -1.0, 1.0, "Armenteros alpha"}; + AxisSpec armenterosQtAxis = {500, 0.0, 0.5, "Armenteros qt (GeV/c)"}; // Event QA histograms histos.add("Event/posZ", "Event vertex Z position", kTH1F, {{200, -20., 20., "V_{z} (cm)"}}); - histos.add("Event/centrality", "Event centrality distribution", kTH1F, {centAxis}); + histos.add("Event/centrality", "Event centrality distribution", kTH1D, {centAxis}); histos.add("Event/posZvsCent", "Vertex Z vs Centrality", kTH2F, {{200, -20., 20., "V_{z} (cm)"}, centAxis}); histos.add("Event/nV0s", "Number of V0s per event", kTH1F, {{200, 0., 200., "N_{V0s}"}}); - histos.add("Event/nKaons", "Number of kaons per event", kTH1F, {{200, 0., 200., "N_{kaons}"}}); - histos.add("Event/nV0sAfterCuts", "Number of V0s per event after cuts", kTH1F, {{100, 0., 100., "N_{V0s}"}}); - histos.add("Event/nKaonsAfterCuts", "Number of kaons per event after cuts", kTH1F, {{100, 0., 100., "N_{kaons}"}}); - - // Lambda QA histograms - histos.add("QAbefore/lambdaMass", "Lambda mass before cuts", kTH1F, {lambdaMassAxis}); - histos.add("QAbefore/lambdaPt", "Lambda pT before cuts", kTH1F, {ptAxisQA}); - histos.add("QAbefore/lambdaEta", "Lambda eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAbefore/lambdaCosPA", "Lambda CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAbefore/lambdaRadius", "Lambda radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAbefore/lambdaDauDCA", "Lambda daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAbefore/lambdaProperLifetime", "Lambda proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); - histos.add("QAbefore/lambdaDauPosDCA", "Lambda positive daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAbefore/lambdaDauNegDCA", "Lambda negative daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - - histos.add("QAafter/lambdaMass", "Lambda mass after cuts", kTH1F, {lambdaMassAxis}); - histos.add("QAafter/lambdaPt", "Lambda pT after cuts", kTH1F, {ptAxisQA}); - histos.add("QAafter/lambdaEta", "Lambda eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAafter/lambdaCosPA", "Lambda CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAafter/lambdaRadius", "Lambda radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAafter/lambdaDauDCA", "Lambda daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAafter/lambdaProperLifetime", "Lambda proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); - histos.add("QAafter/lambdaDauPosDCA", "Lambda positive daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAafter/lambdaDauNegDCA", "Lambda negative daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - - // Kaon QA histograms - histos.add("QAbefore/kaonPt", "Kaon pT before cuts", kTH1F, {ptAxisQA}); - histos.add("QAbefore/kaonEta", "Kaon eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAbefore/kaonDCAxy", "Kaon DCAxy before cuts", kTH2F, {ptAxisQA, dcaxyAxis}); - histos.add("QAbefore/kaonDCAz", "Kaon DCAz before cuts", kTH2F, {ptAxisQA, dcazAxis}); - histos.add("QAbefore/kaonTPCNcls", "Kaon TPC clusters before cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); - histos.add("QAbefore/kaonITSNcls", "Kaon ITS clusters before cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); - histos.add("QAbefore/kaonTPCNSigma", "Kaon TPC NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); - histos.add("QAbefore/kaonTOFNSigma", "Kaon TOF NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); - - histos.add("QAafter/kaonPt", "Kaon pT after cuts", kTH1F, {ptAxisQA}); - histos.add("QAafter/kaonEta", "Kaon eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAafter/kaonDCAxy", "Kaon DCAxy after cuts", kTH2F, {ptAxisQA, dcaxyAxis}); - histos.add("QAafter/kaonDCAz", "Kaon DCAz after cuts", kTH2F, {ptAxisQA, dcazAxis}); - histos.add("QAafter/kaonTPCNcls", "Kaon TPC clusters after cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); - histos.add("QAafter/kaonITSNcls", "Kaon ITS clusters after cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); - histos.add("QAafter/kaonTPCNSigma", "Kaon TPC NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); - histos.add("QAafter/kaonTOFNSigma", "Kaon TOF NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + histos.add("Event/nKaons", "Number of kaons per event", kTH1F, {{200, 0., 200., "N_{kaon}"}}); + histos.add("Event/nLambdasAfterCuts", "Number of Lambdas per event after cuts", kTH1F, {{100, 0., 100., "N_{Lambda}"}}); + histos.add("Event/nKaonsAfterCuts", "Number of kaons (or K0s) per event after cuts", kTH1F, {{100, 0., 100., "N_{Kaon}"}}); + + if (doprocessDataWithTracks || doprocessDataWithMicroTracks || doprocessMCWithTracks || doprocessK0sLambda || doprocessMCK0sLambda) { + // Lambda QA histograms + histos.add("QAbefore/lambdaMass", "Lambda mass before cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAbefore/lambdaMassAnti", "Anti-Lambda mass before cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAbefore/lambdaPt", "Lambda pT before cuts", kTH1F, {ptAxisQA}); + histos.add("QAbefore/lambdaEta", "Lambda eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAbefore/lambdaCosPA", "Lambda CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAbefore/lambdaRadius", "Lambda radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAbefore/lambdaDauDCA", "Lambda daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/lambdaProperLifetime", "Lambda proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAbefore/lambdaDauPosDCA", "Lambda positive daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/lambdaDauNegDCA", "Lambda negative daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/lambdaArmenterosPodolanski", "Lambda candidate Armenteros-Podolanski before cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + + histos.add("QAafter/lambdaMass", "Lambda mass after cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAafter/lambdaMassAnti", "Anti-Lambda mass after cuts", kTH1F, {lambdaMassAxis}); + histos.add("QAafter/lambdaPt", "Lambda pT after cuts", kTH1F, {ptAxisQA}); + histos.add("QAafter/lambdaEta", "Lambda eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAafter/lambdaCosPA", "Lambda CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAafter/lambdaRadius", "Lambda radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAafter/lambdaDauDCA", "Lambda daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/lambdaProperLifetime", "Lambda proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAafter/lambdaDauPosDCA", "Lambda positive daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/lambdaDauNegDCA", "Lambda negative daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/lambdaArmenterosPodolanski", "Lambda candidate Armenteros-Podolanski after cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + } + + if (doprocessDataWithTracks || doprocessDataWithMicroTracks || doprocessMCWithTracks) { + // Kaon QA histograms + histos.add("QAbefore/kaonPt", "Kaon pT before cuts", kTH1F, {ptAxisQA}); + histos.add("QAbefore/kaonEta", "Kaon eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAbefore/kaonDCAxy", "Kaon DCAxy before cuts", kTH2F, {ptAxisQA, dcaxyAxis}); + histos.add("QAbefore/kaonDCAz", "Kaon DCAz before cuts", kTH2F, {ptAxisQA, dcazAxis}); + histos.add("QAbefore/kaonTPCNcls", "Kaon TPC clusters before cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); + histos.add("QAbefore/kaonITSNcls", "Kaon ITS clusters before cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); + histos.add("QAbefore/kaonTPCNSigma", "Kaon TPC NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + histos.add("QAbefore/kaonTOFNSigma", "Kaon TOF NSigma before cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + + histos.add("QAafter/kaonPt", "Kaon pT after cuts", kTH1F, {ptAxisQA}); + histos.add("QAafter/kaonEta", "Kaon eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAafter/kaonDCAxy", "Kaon DCAxy after cuts", kTH2F, {ptAxisQA, dcaxyAxis}); + histos.add("QAafter/kaonDCAz", "Kaon DCAz after cuts", kTH2F, {ptAxisQA, dcazAxis}); + histos.add("QAafter/kaonTPCNcls", "Kaon TPC clusters after cuts", kTH1F, {{160, 0, 160, "N_{TPC clusters}"}}); + histos.add("QAafter/kaonITSNcls", "Kaon ITS clusters after cuts", kTH1F, {{10, 0, 10, "N_{ITS clusters}"}}); + histos.add("QAafter/kaonTPCNSigma", "Kaon TPC NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + histos.add("QAafter/kaonTOFNSigma", "Kaon TOF NSigma after cuts", kTH2F, {ptAxisQA, nsigmaAxis}); + } // Resonance histograms - 4 combinations // K+ Lambda - histos.add("xi1820/kplus_lambda/hInvMassKplusLambda", "Invariant mass of Xi(1820) → K^{+} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_lambda/hInvMassKplusLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{+} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda", "Xi(1820) mass vs pT vs cent (K^{+}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{+}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - - // K+ Anti-Lambda - histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda", "Invariant mass of Xi(1820) → K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{+}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{+}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - - // K- Lambda - histos.add("xi1820/kminus_lambda/hInvMassKminusLambda", "Invariant mass of Xi(1820) → K^{-} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_lambda/hInvMassKminusLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{-} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda", "Xi(1820) mass vs pT vs cent (K^{-}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{-}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - - // K- Anti-Lambda - histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda", "Invariant mass of Xi(1820) → K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{-}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{-}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); + if (doprocessDataWithTracks || doprocessDataWithMicroTracks || doprocessMixedEventWithTracks || doprocessMixedEventWithMicroTracks || doprocessMCWithTracks) { + histos.add("xi1820/kplus_lambda/hInvMassKplusLambda", "Invariant mass of K^{+} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_lambda/hInvMassKplusLambda_Mix", "Mixed event Invariant mass of K^{+} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda", "K^{+} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix", "Mixed event K^{+} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K+ Anti-Lambda + histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda", "Invariant mass of K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix", "Mixed event Invariant mass of K^{+} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda", "K^{+} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix", "Mixed event K^{+} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K- Lambda + histos.add("xi1820/kminus_lambda/hInvMassKminusLambda", "Invariant mass of K^{-} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_lambda/hInvMassKminusLambda_Mix", "Mixed event Invariant mass of K^{-} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda", "K^{-} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix", "Mixed event K^{-} + #Lambda mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K- Anti-Lambda + histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda", "Invariant mass of K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix", "Mixed event Invariant mass of K^{-} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda", "K^{-} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix", "Mixed event K^{-} + #bar{#Lambda} mass vs pT vs cent", kTH3D, {invMassAxis, ptAxis, centAxis}); + } + + // MC Reco histograms for charged K + Lambda channel + if (doprocessMCWithTracks) { + histos.add("MC/kplus_antilambda/hMCRecoInvMassKplusAntiLambda", "Invariant mass of Xi(1820) to K^{-} + #Lambda (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/kplus_antilambda/hMCRecoMassPtCentKplusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{-} + #Lambda) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + + histos.add("MC/kminus_antilambda/hMCRecoInvMassKminusAntiLambda", "Invariant mass of Xi(1820) to K^{+} + #bar{#Lambda} (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/kminus_antilambda/hMCRecoMassPtCentKminusAntiLambda", "Xi(1820) mass vs pT vs cent (K^{+} + #bar{#Lambda}) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + } + + // K0s QA histograms + if (doprocessK0sLambda || doprocessMCK0sLambda) { + histos.add("QAbefore/k0sMass", "K0s mass before cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); + histos.add("QAbefore/k0sPt", "K0s pT before cuts", kTH1F, {ptAxisQA}); + histos.add("QAbefore/k0sEta", "K0s eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAbefore/k0sCosPA", "K0s CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAbefore/k0sRadius", "K0s radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAbefore/k0sDauDCA", "K0s daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAbefore/k0sProperLifetime", "K0s proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAbefore/k0sArmenterosPodolanski", "K0s candidate Armenteros-Podolanski before cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + + histos.add("QAafter/k0sMass", "K0s mass after cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); + histos.add("QAafter/k0sPt", "K0s pT after cuts", kTH1F, {ptAxisQA}); + histos.add("QAafter/k0sEta", "K0s eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); + histos.add("QAafter/k0sCosPA", "K0s CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); + histos.add("QAafter/k0sRadius", "K0s radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); + histos.add("QAafter/k0sDauDCA", "K0s daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); + histos.add("QAafter/k0sProperLifetime", "K0s proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + histos.add("QAafter/k0sArmenterosPodolanski", "K0s candidate Armenteros-Podolanski after cuts", kTH3F, {armenterosAlphaAxis, armenterosQtAxis, ptAxisQA}); + } // K0s + Lambda - histos.add("xi1820/k0s_lambda/hInvMassK0sLambda", "Invariant mass of Xi(1820) → K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_lambda/hInvMassK0sLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3F, {invMassAxis, ptAxis, centAxis}); + if (doprocessK0sLambda || doprocessK0sLambdaMixedEvent || doprocessMCK0sLambda) { + histos.add("xi1820/k0s_lambda/hInvMassK0sLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_lambda/hInvMassK0sLambda_Mix", "Mixed event Invariant mass of Xi(1820) to K^{0}_{S} + #Lambda", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda)", kTH3D, {invMassAxis, ptAxis, centAxis}); + + // K0s + Anti-Lambda + histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) to K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3D, {invMassAxis, ptAxis, centAxis}); + histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3D, {invMassAxis, ptAxis, centAxis}); + } + + if (doprocessMCK0sLambda) { + histos.add("MC/k0s_lambda/hMCRecoInvMassK0sLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #Lambda (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/k0s_lambda/hMCRecoMassPtCentK0sLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#Lambda) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + + histos.add("MC/k0s_antilambda/hMCRecoInvMassK0sAntiLambda", "Invariant mass of Xi(1820) to K^{0}_{S} + #bar{#Lambda} (MC Reco)", kTH1F, {invMassAxis}); + histos.add("MC/k0s_antilambda/hMCRecoMassPtCentK0sAntiLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda}) (MC Reco)", kTHnSparseD, {invMassAxis, ptAxis, centAxis, ptAxis}); + } - // K0s + Anti-Lambda - histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda", "Invariant mass of Xi(1820) → K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix", "Mixed event Invariant mass of Xi(1820) → K^{0}_{S} + #bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda", "Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); - histos.add("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix", "Mixed event Xi(1820) mass vs pT vs cent (K^{0}_{S}#bar{#Lambda})", kTH3F, {invMassAxis, ptAxis, centAxis}); + if (doprocessMCGen) { + histos.add("multQA/h2MultCentMC", "Multiplicity vs Centrality MC", HistType::kTH2D, {centAxis, additionalConfig.multNTracksAxis}); + // MC truth invariant mass vs pT (2D) + histos.add("MC/hMCGenPtCentMultKminusLambda", "MC Truth Mass vs pT K^{-}#Lambda", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + histos.add("MC/hMCGenPtCentMultKplusAntiLambda", "MC Truth Mass vs pT K^{+}#bar{#Lambda}", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + histos.add("MC/hMCGenPtCentMultK0sLambda", "MC Truth Mass vs pT K^{0}_{S}#Lambda", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + histos.add("MC/hMCGenPtCentMultK0sAntiLambda", "MC Truth Mass vs pT K^{0}_{S}#bar{#Lambda}", kTH3D, {ptAxis, centAxis, additionalConfig.multNTracksAxis}); + } // MC truth histograms AxisSpec etaAxis = {100, -2.0, 2.0, "#eta"}; AxisSpec rapidityAxis = {100, -2.0, 2.0, "y"}; - histos.add("MC/hMCGenXi1820Pt", "MC Generated Xi(1820) pT", kTH1F, {ptAxis}); - histos.add("MC/hMCGenXi1820PtEta", "MC Generated Xi(1820) pT vs eta", kTH2F, {ptAxis, etaAxis}); - histos.add("MC/hMCGenXi1820Y", "MC Generated Xi(1820) rapidity", kTH1F, {rapidityAxis}); - histos.add("MC/hMCRecXi1820Pt", "MC Reconstructed Xi(1820) pT", kTH1F, {ptAxis}); - histos.add("MC/hMCRecXi1820PtEta", "MC Reconstructed Xi(1820) pT vs eta", kTH2F, {ptAxis, etaAxis}); - - // MC truth invariant mass (from MC particles) - histos.add("MC/hMCTruthInvMassKplusLambda", "MC Truth Inv Mass K^{+}#Lambda", kTH1F, {invMassAxis}); - histos.add("MC/hMCTruthInvMassKminusAntiLambda", "MC Truth Inv Mass K^{-}#bar{#Lambda}", kTH1F, {invMassAxis}); - histos.add("MC/hMCTruthInvMassK0sLambda", "MC Truth Inv Mass K^{0}_{S}#Lambda", kTH1F, {invMassAxis}); - histos.add("MC/hMCTruthInvMassK0sAntiLambda", "MC Truth Inv Mass K^{0}_{S}#bar{#Lambda}", kTH1F, {invMassAxis}); - - // MC truth invariant mass vs pT (2D) - histos.add("MC/hMCTruthMassPtKplusLambda", "MC Truth Mass vs pT K^{+}#Lambda", kTH2F, {invMassAxis, ptAxis}); - histos.add("MC/hMCTruthMassPtKminusAntiLambda", "MC Truth Mass vs pT K^{-}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); - histos.add("MC/hMCTruthMassPtK0sLambda", "MC Truth Mass vs pT K^{0}_{S}#Lambda", kTH2F, {invMassAxis, ptAxis}); - histos.add("MC/hMCTruthMassPtK0sAntiLambda", "MC Truth Mass vs pT K^{0}_{S}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); - - // K0s QA histograms - histos.add("QAbefore/k0sMass", "K0s mass before cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); - histos.add("QAbefore/k0sPt", "K0s pT before cuts", kTH1F, {ptAxisQA}); - histos.add("QAbefore/k0sEta", "K0s eta before cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAbefore/k0sCosPA", "K0s CosPA before cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAbefore/k0sRadius", "K0s radius before cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAbefore/k0sDauDCA", "K0s daughter DCA before cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAbefore/k0sProperLifetime", "K0s proper lifetime before cuts", kTH2F, {ptAxisQA, lifetimeAxis}); - - histos.add("QAafter/k0sMass", "K0s mass after cuts", kTH1F, {{100, 0.4, 0.6, "K^{0}_{S} mass (GeV/#it{c}^{2})"}}); - histos.add("QAafter/k0sPt", "K0s pT after cuts", kTH1F, {ptAxisQA}); - histos.add("QAafter/k0sEta", "K0s eta after cuts", kTH1F, {{100, -2.0, 2.0, "#eta"}}); - histos.add("QAafter/k0sCosPA", "K0s CosPA after cuts", kTH2F, {ptAxisQA, cosPAAxis}); - histos.add("QAafter/k0sRadius", "K0s radius after cuts", kTH2F, {ptAxisQA, radiusAxis}); - histos.add("QAafter/k0sDauDCA", "K0s daughter DCA after cuts", kTH2F, {ptAxisQA, dcaAxis}); - histos.add("QAafter/k0sProperLifetime", "K0s proper lifetime after cuts", kTH2F, {ptAxisQA, lifetimeAxis}); + if (doprocessMCTruth) { + histos.add("MC/hMCTruthXi1820Pt", "MC Generated Xi(1820) pT", kTH1F, {ptAxis}); + histos.add("MC/hMCTruthXi1820PtEta", "MC Generated Xi(1820) pT vs eta", kTH2F, {ptAxis, etaAxis}); + histos.add("MC/hMCTruthXi1820Y", "MC Generated Xi(1820) rapidity", kTH1F, {rapidityAxis}); + + // MC truth invariant mass (from MC particles) + histos.add("MC/hMCTruthInvMassKminusLambda", "MC Truth Inv Mass K^{-}#Lambda", kTH1F, {invMassAxis}); + histos.add("MC/hMCTruthInvMassKplusAntiLambda", "MC Truth Inv Mass K^{+}#bar{#Lambda}", kTH1F, {invMassAxis}); + histos.add("MC/hMCTruthInvMassK0sLambda", "MC Truth Inv Mass K^{0}_{S}#Lambda", kTH1F, {invMassAxis}); + histos.add("MC/hMCTruthInvMassK0sAntiLambda", "MC Truth Inv Mass K^{0}_{S}#bar{#Lambda}", kTH1F, {invMassAxis}); + + // MC truth invariant mass vs pT (2D) + histos.add("MC/hMCTruthMassPtKminusLambda", "MC Truth Mass vs pT K^{-}#Lambda", kTH2F, {invMassAxis, ptAxis}); + histos.add("MC/hMCTruthMassPtKplusAntiLambda", "MC Truth Mass vs pT K^{+}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); + histos.add("MC/hMCTruthMassPtK0sLambda", "MC Truth Mass vs pT K^{0}_{S}#Lambda", kTH2F, {invMassAxis, ptAxis}); + histos.add("MC/hMCTruthMassPtK0sAntiLambda", "MC Truth Mass vs pT K^{0}_{S}#bar{#Lambda}", kTH2F, {invMassAxis, ptAxis}); + } } // Lambda/Anti-Lambda selection @@ -279,7 +341,7 @@ struct Xi1820Analysis { return false; // Radius cuts - auto radius = v0.transRadius(); + float radius = v0.transRadius(); if (radius < cV0RadiusMin || radius > cV0RadiusMax) return false; @@ -302,6 +364,14 @@ struct Xi1820Analysis { return false; } + if (cV0sCrossMassRejection) { + if (std::abs(v0.mK0Short() - MassK0Short) < cV0sCrossMassRejectionWindow) + return false; + } + + if (v0.qtarm() > cK0sArmenterosAlphaCoeff * std::fabs(v0.alpha())) + return false; + return true; } @@ -328,12 +398,12 @@ struct Xi1820Analysis { return false; // Radius cuts - auto radius = v0.transRadius(); + float radius = v0.transRadius(); if (radius < cK0sRadiusMin || radius > cK0sRadiusMax) return false; // DCA to PV - if (std::abs(v0.dcav0topv()) > kMaxDcaToPv) + if (std::abs(v0.dcav0topv()) > additionalConfig.cMaxDcaToPVV0) return false; // Proper lifetime cut @@ -352,12 +422,15 @@ struct Xi1820Analysis { // Competing V0 rejection: remove (Anti)Λ if (cK0sCrossMassRejection) { - if (std::abs(v0.mLambda() - MassLambda) < cK0sMassWindow) + if (std::abs(v0.mLambda() - MassLambda) < cK0sCrossMassRejectionWindow) return false; - if (std::abs(v0.mAntiLambda() - MassLambda) < cK0sMassWindow) + if (std::abs(v0.mAntiLambda() - MassLambda) < cK0sCrossMassRejectionWindow) return false; } + if (v0.qtarm() < cK0sArmenterosAlphaCoeff * std::fabs(v0.alpha())) + return false; + return true; } @@ -476,23 +549,44 @@ struct Xi1820Analysis { template bool kaonCut(const TrackType& track) { + float candPt = track.pt(); // Basic kinematic cuts - if (track.pt() < cKaonPtMin) + if (candPt < cKaonPtMin) return false; if (std::abs(track.eta()) > cKaonEtaMax) return false; + float dcaXY = -999.f; + float dcaZ = -999.f; + // DCA cuts - different access for ResoMicroTracks if constexpr (IsResoMicrotrack) { - if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cKaonDCAxyMax) - return false; - if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cKaonDCAzMax) - return false; + dcaXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()); + dcaZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()); + + if (additionalConfig.cUsePtDepDCAForKaons) { // Insert pT dependent DCAxy,z cut (tighter than global-track w DCA cut) + if (std::abs(dcaXY) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + if (std::abs(dcaZ) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + } else { + if (std::abs(dcaXY) > cKaonDCAxyMax) + return false; + if (std::abs(dcaZ) > cKaonDCAzMax) + return false; + } } else { - if (std::abs(track.dcaXY()) > cKaonDCAxyMax) - return false; - if (std::abs(track.dcaZ()) > cKaonDCAzMax) - return false; + if (additionalConfig.cUsePtDepDCAForKaons) { // Insert pT dependent DCAxy,z cut (tighter than global-track w DCA cut) + if (std::abs(track.dcaXY()) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + if (std::abs(track.dcaZ()) > (additionalConfig.cDCAToPVByPtFirstP0 + additionalConfig.cDCAToPVByPtFirstExp * std::pow(candPt, -1.))) + return false; + } else { + if (std::abs(track.dcaXY()) > cKaonDCAxyMax) + return false; + if (std::abs(track.dcaZ()) > cKaonDCAzMax) + return false; + } } // Track quality cuts - check if fields are available (only for ResoTracks) @@ -514,8 +608,8 @@ struct Xi1820Analysis { return true; } - template - void fill(const CollisionT& collision, const V0sT& v0s, const TracksT& tracks) + template + void fillChargedKLambda(const CollisionT& collision, const V0sT& v0s, const TracksT& tracks) // Xi(1820) analysis: charged K + Lambda channel { auto cent = collision.cent(); @@ -528,10 +622,16 @@ struct Xi1820Analysis { histos.fill(HIST("Event/nKaons"), tracks.size()); } + if (additionalConfig.cConsiderPairOnly && (v0s.size() < 1 || tracks.size() < 1)) + return; // skip events that cannot form pairs if the option is enabled (for increasing processing speed when only pairs are of interest) + // Count candidates after cuts int nV0sAfterCuts = 0; int nKaonsAfterCuts = 0; + // Build 4 combinations + ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; + // Loop over kaon candidates for (const auto& kaon : tracks) { // QA before cuts @@ -599,6 +699,7 @@ struct Xi1820Analysis { // Lambda QA before cuts if constexpr (!IsMix) { histos.fill(HIST("QAbefore/lambdaMass"), v0.mLambda()); + histos.fill(HIST("QAbefore/lambdaMassAnti"), v0.mAntiLambda()); histos.fill(HIST("QAbefore/lambdaPt"), v0.pt()); histos.fill(HIST("QAbefore/lambdaEta"), v0.eta()); histos.fill(HIST("QAbefore/lambdaCosPA"), v0.pt(), v0.v0CosPA()); @@ -615,6 +716,7 @@ struct Xi1820Analysis { float p = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; histos.fill(HIST("QAbefore/lambdaProperLifetime"), v0.pt(), properLifetime); + histos.fill(HIST("QAbefore/lambdaArmenterosPodolanski"), v0.alpha(), v0.qtarm(), v0.pt()); } // Try Lambda @@ -632,7 +734,7 @@ struct Xi1820Analysis { histos.fill(HIST("QAafter/lambdaMass"), v0.mLambda()); } if (isAntiLambda) { - histos.fill(HIST("QAafter/lambdaMass"), v0.mAntiLambda()); + histos.fill(HIST("QAafter/lambdaMassAnti"), v0.mAntiLambda()); } histos.fill(HIST("QAafter/lambdaPt"), v0.pt()); histos.fill(HIST("QAafter/lambdaEta"), v0.eta()); @@ -649,55 +751,97 @@ struct Xi1820Analysis { float p = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; histos.fill(HIST("QAafter/lambdaProperLifetime"), v0.pt(), properLifetime); + histos.fill(HIST("QAafter/lambdaArmenterosPodolanski"), v0.alpha(), v0.qtarm(), v0.pt()); } - // Build 4 combinations - ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; pKaon = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(kaon.pt(), kaon.eta(), kaon.phi(), MassKaonCharged)); - // K+ Lambda + // K+ + Lambda -> Bkg channel for charged Xi(1820) if (kaonCharge > 0 && isLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda"), pRes.M()); histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda"), pRes.M(), pRes.Pt(), cent); + } else { histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda_Mix"), pRes.M()); histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix"), pRes.M(), pRes.Pt(), cent); } } - // K+ Anti-Lambda + // K+ + Anti-Lambda -> Signal channel for Anti-charged Xi(1820) if (kaonCharge > 0 && isAntiLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda"), pRes.M()); histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda"), pRes.M(), pRes.Pt(), cent); + if constexpr (IsMC) { // Calculate Acceptance x efficiency for "the particle" channel + if (std::abs(v0.motherPDG()) != kPdgChagedXi1820) + continue; + if (kaon.pdgCode() != PDG_t::kKPlus || v0.pdgCode() != PDG_t::kLambda0Bar) + continue; + if (kaon.motherId() != v0.motherId()) + continue; + auto pMCPt = v0.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(v0.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/kplus_antilambda/hMCRecoInvMassKplusAntiLambda"), pRes.M()); + histos.fill(HIST("MC/kplus_antilambda/hMCRecoMassPtCentKplusAntiLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + + // Detail QA histograms for truth particle -> Will be updated + } } else { histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix"), pRes.M()); histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); } } - // K- Lambda + // K- + Lambda -> Signal channel for Xi(1820)- if (kaonCharge < 0 && isLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda"), pRes.M()); histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda"), pRes.M(), pRes.Pt(), cent); + if constexpr (IsMC) { // Calculate Acceptance x efficiency for "the particle" channel + if (std::abs(v0.motherPDG()) != kPdgChagedXi1820) + continue; + if (kaon.pdgCode() != PDG_t::kKMinus || v0.pdgCode() != PDG_t::kLambda0) + continue; + if (kaon.motherId() != v0.motherId()) + continue; + auto pMCPt = v0.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(v0.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/kminus_lambda/hMCRecoInvMassKminusLambda"), pRes.M()); + histos.fill(HIST("MC/kminus_lambda/hMCRecoMassPtCentKminusLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + + // Detail QA histograms for the truth particle -> Will be updated + } } else { histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda_Mix"), pRes.M()); histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix"), pRes.M(), pRes.Pt(), cent); } } - // K- Anti-Lambda + // K- + Anti-Lambda -> Bkg channel for charged Xi(1820) if (kaonCharge < 0 && isAntiLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); pRes = pKaon + pLambda; + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; if constexpr (!IsMix) { histos.fill(HIST("xi1820/kminus_antilambda/hInvMassKminusAntiLambda"), pRes.M()); histos.fill(HIST("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda"), pRes.M(), pRes.Pt(), cent); @@ -711,203 +855,105 @@ struct Xi1820Analysis { // Fill event QA for after-cuts counters (only for same-event) if constexpr (!IsMix) { - histos.fill(HIST("Event/nV0sAfterCuts"), nV0sAfterCuts); + histos.fill(HIST("Event/nLambdasAfterCuts"), nV0sAfterCuts); histos.fill(HIST("Event/nKaonsAfterCuts"), nKaonsAfterCuts); } } - void processDummy(const aod::ResoCollision& /*collision*/) - { - // Dummy function to satisfy the compiler - } - PROCESS_SWITCH(Xi1820Analysis, processDummy, "Process Dummy", true); - - void processDataWithTracks(const aod::ResoCollision& collision, - aod::ResoV0s const& resov0s, - aod::ResoTracks const& resotracks) - { - fill(collision, resov0s, resotracks); - } - PROCESS_SWITCH(Xi1820Analysis, processDataWithTracks, "Process Event with ResoTracks", false); - - void processDataWithMicroTracks(const aod::ResoCollision& collision, - aod::ResoV0s const& resov0s, - aod::ResoMicroTracks const& resomicrotracks) + template + void fillK0sLambda(const CollisionT& collision, const V0sT& k0sCands, const V0sT& lambdaCands) // Xi(1820) analysis: K0s + Lambda channel, No need to MicroTrack! { - fill(collision, resov0s, resomicrotracks); - } - PROCESS_SWITCH(Xi1820Analysis, processDataWithMicroTracks, "Process Event with ResoMicroTracks", false); - - void processMixedEventWithTracks(const aod::ResoCollisions& collisions, - aod::ResoV0s const& resov0s, - aod::ResoTracks const& resotracks) - { - - auto v0sTracksTuple = std::make_tuple(resov0s, resotracks); - Pair pairs{colBinning, nEvtMixing, -1, collisions, v0sTracksTuple, &cache}; - - for (auto& [collision1, v0s1, collision2, tracks2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) - auto cent = collision1.cent(); - - for (const auto& kaon : tracks2) { - if (!kaonCut(kaon)) - continue; - int kaonCharge = kaon.sign(); - - for (const auto& v0 : v0s1) { - bool isLambda = v0Cut(collision1, v0, true); - bool isAntiLambda = v0Cut(collision1, v0, false); - - if (!isLambda && !isAntiLambda) - continue; - - ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; - pKaon = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(kaon.pt(), kaon.eta(), kaon.phi(), MassKaonCharged)); + auto cent = collision.cent(); - // K+ Lambda - if (kaonCharge > 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + // Fill event QA histograms + if constexpr (!IsMix) { + histos.fill(HIST("Event/posZ"), collision.posZ()); + histos.fill(HIST("Event/centrality"), cent); + histos.fill(HIST("Event/posZvsCent"), collision.posZ(), cent); + histos.fill(HIST("Event/nV0s"), lambdaCands.size()); + histos.fill(HIST("Event/nKaons"), k0sCands.size()); + } - // K+ Anti-Lambda - if (kaonCharge > 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + if (additionalConfig.cConsiderHasV0s && (lambdaCands.size() < 1)) + return; // skip events that do not have V0s if the option is enabled - // K- Lambda - if (kaonCharge < 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + int nV0sAfterCuts = 0; + int nKaonsAfterCuts = 0; - // K- Anti-Lambda - if (kaonCharge < 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - } + // Loop over V0s for K0s + for (const auto& k0s : k0sCands) { + // K0s QA before cuts + if constexpr (!IsMix) { + histos.fill(HIST("QAbefore/k0sMass"), k0s.mK0Short()); + histos.fill(HIST("QAbefore/k0sPt"), k0s.pt()); + histos.fill(HIST("QAbefore/k0sEta"), k0s.eta()); + histos.fill(HIST("QAbefore/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); + histos.fill(HIST("QAbefore/k0sRadius"), k0s.pt(), k0s.transRadius()); + histos.fill(HIST("QAbefore/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); + + float dx = k0s.decayVtxX() - collision.posX(); + float dy = k0s.decayVtxY() - collision.posY(); + float dz = k0s.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(k0s.px() * k0s.px() + k0s.py() * k0s.py() + k0s.pz() * k0s.pz()); + auto k0sProperLifetime = (l / (p + 1e-10)) * MassK0Short; + histos.fill(HIST("QAbefore/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); + histos.fill(HIST("QAbefore/k0sArmenterosPodolanski"), k0s.alpha(), k0s.qtarm(), k0s.pt()); } - } - } - PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithTracks, "Process Mixed Event with ResoTracks", false); - - void processMixedEventWithMicroTracks(const aod::ResoCollisions& collisions, - aod::ResoV0s const& resov0s, - aod::ResoMicroTracks const& resomicrotracks) - { - auto v0sTracksTuple = std::make_tuple(resov0s, resomicrotracks); - Pair pairs{colBinning, nEvtMixing, -1, collisions, v0sTracksTuple, &cache}; + if (!k0sCut(collision, k0s)) + continue; + auto indexK0s = k0s.index(); - for (auto& [collision1, v0s1, collision2, tracks2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) - auto cent = collision1.cent(); + if constexpr (!IsMix) { + nKaonsAfterCuts++; + // K0s QA after cuts + histos.fill(HIST("QAafter/k0sMass"), k0s.mK0Short()); + histos.fill(HIST("QAafter/k0sPt"), k0s.pt()); + histos.fill(HIST("QAafter/k0sEta"), k0s.eta()); + histos.fill(HIST("QAafter/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); + histos.fill(HIST("QAafter/k0sRadius"), k0s.pt(), k0s.transRadius()); + histos.fill(HIST("QAafter/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); + + float dx = k0s.decayVtxX() - collision.posX(); + float dy = k0s.decayVtxY() - collision.posY(); + float dz = k0s.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(k0s.px() * k0s.px() + k0s.py() * k0s.py() + k0s.pz() * k0s.pz()); + auto k0sProperLifetime = (l / (p + 1e-10)) * MassK0Short; + histos.fill(HIST("QAafter/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); + histos.fill(HIST("QAafter/k0sArmenterosPodolanski"), k0s.alpha(), k0s.qtarm(), k0s.pt()); + } - for (const auto& kaon : tracks2) { - if (!kaonCut(kaon)) - continue; - int kaonCharge = kaon.sign(); + // Loop over V0s for Lambda + for (const auto& lambda : lambdaCands) { - for (const auto& v0 : v0s1) { - bool isLambda = v0Cut(collision1, v0, true); - bool isAntiLambda = v0Cut(collision1, v0, false); + auto indexLambda = lambda.index(); - if (!isLambda && !isAntiLambda) + if constexpr (!IsMix) { + if (indexLambda == indexK0s) // Avoid self-combination continue; + histos.fill(HIST("QAbefore/lambdaMass"), lambda.mLambda()); + histos.fill(HIST("QAbefore/lambdaMassAnti"), lambda.mAntiLambda()); + histos.fill(HIST("QAbefore/lambdaPt"), lambda.pt()); + histos.fill(HIST("QAbefore/lambdaEta"), lambda.eta()); + histos.fill(HIST("QAbefore/lambdaCosPA"), lambda.pt(), lambda.v0CosPA()); + histos.fill(HIST("QAbefore/lambdaRadius"), lambda.pt(), lambda.transRadius()); + histos.fill(HIST("QAbefore/lambdaDauDCA"), lambda.pt(), lambda.daughDCA()); + histos.fill(HIST("QAbefore/lambdaDauPosDCA"), lambda.pt(), std::abs(lambda.dcapostopv())); + histos.fill(HIST("QAbefore/lambdaDauNegDCA"), lambda.pt(), std::abs(lambda.dcanegtopv())); - ROOT::Math::PxPyPzEVector pKaon, pLambda, pRes; - pKaon = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(kaon.pt(), kaon.eta(), kaon.phi(), MassKaonCharged)); - - // K+ Lambda - if (kaonCharge > 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_lambda/hInvMassKplusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_lambda/hMassPtCentKplusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - - // K+ Anti-Lambda - if (kaonCharge > 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kplus_antilambda/hInvMassKplusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kplus_antilambda/hMassPtCentKplusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - - // K- Lambda - if (kaonCharge < 0 && isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_lambda/hInvMassKminusLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_lambda/hMassPtCentKminusLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - - // K- Anti-Lambda - if (kaonCharge < 0 && isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(v0.pt(), v0.eta(), v0.phi(), v0.mAntiLambda())); - pRes = pKaon + pLambda; - histos.fill(HIST("xi1820/kminus_antilambda/hInvMassKminusAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/kminus_antilambda/hMassPtCentKminusAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + // Calculate proper lifetime manually + float dx = lambda.decayVtxX() - collision.posX(); + float dy = lambda.decayVtxY() - collision.posY(); + float dz = lambda.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(lambda.px() * lambda.px() + lambda.py() * lambda.py() + lambda.pz() * lambda.pz()); + auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; + histos.fill(HIST("QAbefore/lambdaProperLifetime"), lambda.pt(), properLifetime); + histos.fill(HIST("QAbefore/lambdaArmenterosPodolanski"), lambda.alpha(), lambda.qtarm(), lambda.pt()); } - } - } - } - PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithMicroTracks, "Process Mixed Event with ResoMicroTracks", false); - - // K0s + Lambda analysis - void processK0sLambda(const aod::ResoCollision& collision, - aod::ResoV0s const& resov0s) - { - auto cent = collision.cent(); - - // Fill event QA histograms - histos.fill(HIST("Event/posZ"), collision.posZ()); - histos.fill(HIST("Event/centrality"), cent); - histos.fill(HIST("Event/posZvsCent"), collision.posZ(), cent); - histos.fill(HIST("Event/nV0s"), resov0s.size()); - - // Loop over V0s for K0s - for (const auto& k0s : resov0s) { - // K0s QA before cuts - histos.fill(HIST("QAbefore/k0sMass"), k0s.mK0Short()); - histos.fill(HIST("QAbefore/k0sPt"), k0s.pt()); - histos.fill(HIST("QAbefore/k0sEta"), k0s.eta()); - histos.fill(HIST("QAbefore/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); - histos.fill(HIST("QAbefore/k0sRadius"), k0s.pt(), k0s.transRadius()); - histos.fill(HIST("QAbefore/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); - - float dx = k0s.decayVtxX() - collision.posX(); - float dy = k0s.decayVtxY() - collision.posY(); - float dz = k0s.decayVtxZ() - collision.posZ(); - float l = std::sqrt(dx * dx + dy * dy + dz * dz); - float p = std::sqrt(k0s.px() * k0s.px() + k0s.py() * k0s.py() + k0s.pz() * k0s.pz()); - auto k0sProperLifetime = (l / (p + 1e-10)) * MassK0Short; - histos.fill(HIST("QAbefore/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); - - if (!k0sCut(collision, k0s)) - continue; - // K0s QA after cuts - histos.fill(HIST("QAafter/k0sMass"), k0s.mK0Short()); - histos.fill(HIST("QAafter/k0sPt"), k0s.pt()); - histos.fill(HIST("QAafter/k0sEta"), k0s.eta()); - histos.fill(HIST("QAafter/k0sCosPA"), k0s.pt(), k0s.v0CosPA()); - histos.fill(HIST("QAafter/k0sRadius"), k0s.pt(), k0s.transRadius()); - histos.fill(HIST("QAafter/k0sDauDCA"), k0s.pt(), k0s.daughDCA()); - histos.fill(HIST("QAafter/k0sProperLifetime"), k0s.pt(), k0sProperLifetime); - - // Loop over V0s for Lambda - for (const auto& lambda : resov0s) { // Try Lambda bool isLambda = v0Cut(collision, lambda, true); // Try Anti-Lambda @@ -916,112 +962,270 @@ struct Xi1820Analysis { if (!isLambda && !isAntiLambda) continue; + if constexpr (!IsMix) { + nV0sAfterCuts++; + // QA after cuts (fill for whichever passes) + if (isLambda) { + histos.fill(HIST("QAafter/lambdaMass"), lambda.mLambda()); + } + if (isAntiLambda) { + histos.fill(HIST("QAafter/lambdaMassAnti"), lambda.mAntiLambda()); + } + histos.fill(HIST("QAafter/lambdaPt"), lambda.pt()); + histos.fill(HIST("QAafter/lambdaEta"), lambda.eta()); + histos.fill(HIST("QAafter/lambdaCosPA"), lambda.pt(), lambda.v0CosPA()); + histos.fill(HIST("QAafter/lambdaRadius"), lambda.pt(), lambda.transRadius()); + histos.fill(HIST("QAafter/lambdaDauDCA"), lambda.pt(), lambda.daughDCA()); + histos.fill(HIST("QAafter/lambdaDauPosDCA"), lambda.pt(), std::abs(lambda.dcapostopv())); + histos.fill(HIST("QAafter/lambdaDauNegDCA"), lambda.pt(), std::abs(lambda.dcanegtopv())); + + float dx = lambda.decayVtxX() - collision.posX(); + float dy = lambda.decayVtxY() - collision.posY(); + float dz = lambda.decayVtxZ() - collision.posZ(); + float l = std::sqrt(dx * dx + dy * dy + dz * dz); + float p = std::sqrt(lambda.px() * lambda.px() + lambda.py() * lambda.py() + lambda.pz() * lambda.pz()); + auto properLifetime = (l / (p + kSmallMomentumDenominator)) * MassLambda; + histos.fill(HIST("QAafter/lambdaProperLifetime"), lambda.pt(), properLifetime); + histos.fill(HIST("QAafter/lambdaArmenterosPodolanski"), lambda.alpha(), lambda.qtarm(), lambda.pt()); + } + // 4-vectors ROOT::Math::PxPyPzEVector pK0s, pLambda, pRes; pK0s = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(k0s.pt(), k0s.eta(), k0s.phi(), MassK0Short)); - // K0s + Lambda if (isLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mLambda())); pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda"), pRes.M()); - histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda"), pRes.M(), pRes.Pt(), cent); + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; + if constexpr (!IsMix) { + histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda"), pRes.M()); + histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda"), pRes.M(), pRes.Pt(), cent); + if constexpr (IsMC) { // Calculate Acceptance x efficiency + if (std::abs(lambda.motherPDG()) != kPdgXi1820Zero) + continue; + if (std::abs(k0s.pdgCode()) != PDG_t::kK0Short || lambda.pdgCode() != PDG_t::kLambda0) + continue; + if (k0s.motherId() != lambda.motherId()) + continue; + auto pMCPt = lambda.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(lambda.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/k0s_lambda/hMCRecoInvMassK0sLambda"), pRes.M()); + histos.fill(HIST("MC/k0s_lambda/hMCRecoMassPtCentK0sLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + // Detail QA histograms for truth particle -> Will be updated + } + } else { + histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda_Mix"), pRes.M()); + histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix"), pRes.M(), pRes.Pt(), cent); + } } - // K0s + Anti-Lambda if (isAntiLambda) { pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mAntiLambda())); pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda"), pRes.M()); - histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda"), pRes.M(), pRes.Pt(), cent); + auto pCandRapidity = pRes.Rapidity(); + if (std::abs(pCandRapidity) >= additionalConfig.cfgRapidityCut) // skip candidate if reconstructed rapidity is outside of cut + continue; + if constexpr (!IsMix) { + histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda"), pRes.M()); + histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda"), pRes.M(), pRes.Pt(), cent); + + if constexpr (IsMC) { // Calculate Acceptance x efficiency + if (std::abs(lambda.motherPDG()) != kPdgXi1820Zero) + continue; + if (std::abs(k0s.pdgCode()) != PDG_t::kK0Short || lambda.pdgCode() != PDG_t::kLambda0Bar) + continue; + if (k0s.motherId() != lambda.motherId()) + continue; + auto pMCPt = lambda.motherPt(); // Check particle's pT resolution + if (additionalConfig.cUseTruthRapidity && std::abs(lambda.motherRap()) >= additionalConfig.cfgRapidityCut) // skip candidate if True rapidity of mother particle is outside of cut + continue; + histos.fill(HIST("MC/k0s_antilambda/hMCRecoInvMassK0sAntiLambda"), pRes.M()); + histos.fill(HIST("MC/k0s_antilambda/hMCRecoMassPtCentK0sAntiLambda"), pRes.M(), pRes.Pt(), cent, pMCPt); + // Detail QA histograms for truth particle -> Will be updated + } + } else { + histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix"), pRes.M()); + histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); + } } - } + } // End of loop over Lambda candidates + } // End of loop over K0s candidates + + // Fill event QA for after-cuts counters (only for same-event) + if constexpr (!IsMix) { + histos.fill(HIST("Event/nLambdasAfterCuts"), nV0sAfterCuts); + histos.fill(HIST("Event/nKaonsAfterCuts"), nKaonsAfterCuts); } } - PROCESS_SWITCH(Xi1820Analysis, processK0sLambda, "Process K0s + Lambda", false); - // K0s + Lambda mixed event analysis - void processK0sLambdaMixedEvent(const aod::ResoCollisions& collisions, - aod::ResoV0s const& resov0s) + void processDummy(const aod::ResoCollision& /*collision*/) { + // Dummy function to satisfy the compiler + } + PROCESS_SWITCH(Xi1820Analysis, processDummy, "Process Dummy", true); - auto v0sV0sTuple = std::make_tuple(resov0s, resov0s); - Pair pairs{colBinning, nEvtMixing, -1, collisions, v0sV0sTuple, &cache}; + void processDataWithTracks(const aod::ResoCollision& resoCollision, + aod::ResoV0s const& resoV0s, + aod::ResoTracks const& resoTracks) + { + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(resoCollision, resoV0s, resoTracks); + } + PROCESS_SWITCH(Xi1820Analysis, processDataWithTracks, "Process Event with ResoTracks", false); - for (auto& [collision1, k0s1, collision2, lambda2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) - auto cent = collision1.cent(); + void processDataWithMicroTracks(const aod::ResoCollision& resoCollision, + aod::ResoV0s const& resoV0s, + aod::ResoMicroTracks const& resoMicroTracks) + { + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(resoCollision, resoV0s, resoMicroTracks); + } + PROCESS_SWITCH(Xi1820Analysis, processDataWithMicroTracks, "Process Event with ResoMicroTracks", false); - for (const auto& k0s : k0s1) { - if (!k0sCut(collision1, k0s)) - continue; + void processMixedEventWithTracks(const aod::ResoCollisions& resoCollisions, + aod::ResoV0s const& resoV0s, + aod::ResoTracks const& resoTracks) + { - for (const auto& lambda : lambda2) { - bool isLambda = v0Cut(collision2, lambda, true); - bool isAntiLambda = v0Cut(collision2, lambda, false); + auto v0sTracksTuple = std::make_tuple(resoTracks, resoV0s); + BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; + Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, v0sTracksTuple, &cache}; - if (!isLambda && !isAntiLambda) - continue; + for (auto& [collision1, tracks1, collision2, v0s2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) + if (additionalConfig.cRecoINELgt0 && !collision1.isRecINELgt0()) + continue; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(collision1, v0s2, tracks1); + } + } + PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithTracks, "Process Mixed Event with ResoTracks", false); - ROOT::Math::PxPyPzEVector pK0s, pLambda, pRes; - pK0s = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(k0s.pt(), k0s.eta(), k0s.phi(), MassK0Short)); + void processMixedEventWithMicroTracks(const aod::ResoCollisions& resoCollisions, + aod::ResoV0s const& resoV0s, + aod::ResoMicroTracks const& resoMicroTracks) + { - // K0s + Lambda - if (isLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mLambda())); - pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_lambda/hInvMassK0sLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/k0s_lambda/hMassPtCentK0sLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } + auto v0sTracksTuple = std::make_tuple(resoV0s, resoMicroTracks); + BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; + Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, v0sTracksTuple, &cache}; - // K0s + Anti-Lambda - if (isAntiLambda) { - pLambda = ROOT::Math::PxPyPzEVector(ROOT::Math::PtEtaPhiMVector(lambda.pt(), lambda.eta(), lambda.phi(), lambda.mAntiLambda())); - pRes = pK0s + pLambda; - histos.fill(HIST("xi1820/k0s_antilambda/hInvMassK0sAntiLambda_Mix"), pRes.M()); - histos.fill(HIST("xi1820/k0s_antilambda/hMassPtCentK0sAntiLambda_Mix"), pRes.M(), pRes.Pt(), cent); - } - } - } + for (auto& [collision1, v0s1, collision2, tracks2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) + if (additionalConfig.cRecoINELgt0 && !collision2.isRecINELgt0()) + continue; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillChargedKLambda(collision2, v0s1, tracks2); + } + } + PROCESS_SWITCH(Xi1820Analysis, processMixedEventWithMicroTracks, "Process Mixed Event with ResoMicroTracks", false); + + // K0s + Lambda analysis + void processK0sLambda(const aod::ResoCollision& resoCollision, + aod::ResoV0s const& resoV0s) + { + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillK0sLambda(resoCollision, resoV0s, resoV0s); + } + PROCESS_SWITCH(Xi1820Analysis, processK0sLambda, "Process K0s + Lambda", false); + + // K0s + Lambda mixed event analysis + void processK0sLambdaMixedEvent(const aod::ResoCollisions& resoCollisions, + aod::ResoV0s const& resoV0s) + { + + auto v0sV0sTuple = std::make_tuple(resoV0s, resoV0s); + BinningTypeVertexContributor colBinning{{cfgVtxBins, cfgMultBins}, true}; + Pair pairs{colBinning, nEvtMixing, -1, resoCollisions, v0sV0sTuple, &cache}; + + for (auto& [collision1, k0s1, collision2, lambda2] : pairs) { // o2-linter: disable=const-ref-in-for-loop (structured bindings from Pair iterator cannot be const) + if (additionalConfig.cRecoINELgt0 && !collision1.isRecINELgt0()) + continue; // skip event if RecoINEL>0 selection is enabled and event does not pass it + fillK0sLambda(collision1, k0s1, lambda2); } } PROCESS_SWITCH(Xi1820Analysis, processK0sLambdaMixedEvent, "Process K0s + Lambda Mixed Event", false); - // MC processes - placeholder for future implementation - void processMCWithTracks(const aod::ResoCollision& /*collision*/, - aod::ResoV0s const& /*resov0s*/, - aod::ResoTracks const& /*resotracks*/, - aod::McParticles const& /*mcParticles*/) + // MC processes for charged K + Lambda analysis + void processMCWithTracks(ResoMCCols::iterator const& resoMCcollision, + soa::Join const& resoMCV0s, + soa::Join const& resoMCTracks) + { + if (additionalConfig.cRecoINELgt0 && !resoMCcollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + if (!resoMCcollision.isInAfterAllCuts()) // MC event selection + return; + fillChargedKLambda(resoMCcollision, resoMCV0s, resoMCTracks); + } + PROCESS_SWITCH(Xi1820Analysis, processMCWithTracks, "Process MC for charged K + Lambda", false); + + void processMCK0sLambda(ResoMCCols::iterator const& resoMCCollision, + soa::Join const& resoMCV0s) { - // TODO: Implement MC truth matching for K± + Lambda - // - Match reconstructed kaons to MC kaons - // - Match reconstructed Lambdas to MC Lambdas - // - Fill MC truth histograms - // - Fill reconstruction efficiency histograms + if (additionalConfig.cRecoINELgt0 && !resoMCCollision.isRecINELgt0()) + return; // skip event if RecoINEL>0 selection is enabled and event does not pass it + if (!resoMCCollision.isInAfterAllCuts()) // MC event selection + return; + fillK0sLambda(resoMCCollision, resoMCV0s, resoMCV0s); } - PROCESS_SWITCH(Xi1820Analysis, processMCWithTracks, "Process MC with ResoTracks (placeholder)", false); + PROCESS_SWITCH(Xi1820Analysis, processMCK0sLambda, "Process MC K0s + Lambda", false); - void processMCWithMicroTracks(const aod::ResoCollision& /*collision*/, - aod::ResoV0s const& /*resov0s*/, - aod::ResoMicroTracks const& /*resomicrotracks*/, + void processMCWithMicroTracks(const aod::ResoCollision& /*resoCollision*/, + aod::ResoV0s const& /*resoV0s*/, + aod::ResoMicroTracks const& /*resoMicroTracks*/, aod::McParticles const& /*mcParticles*/) { // TODO: Implement MC truth matching for K± + Lambda with MicroTracks + // But is this really necessary? -> Most of the injected MC sizes are already within small-train limit. } PROCESS_SWITCH(Xi1820Analysis, processMCWithMicroTracks, "Process MC with ResoMicroTracks (placeholder)", false); - void processMCK0sLambda(const aod::ResoCollision& /*collision*/, - aod::ResoV0s const& /*resov0s*/, - aod::McParticles const& /*mcParticles*/) + void processMCGen(ResoMCCols::iterator const& resoCollision, // Calculate denominator for the acceptance x efficiency and a part of Event-factor (for selected evennts) + aod::ResoMCParents const& resoParents) { - // TODO: Implement MC truth matching for K0s + Lambda - // - Match reconstructed K0s to MC K0s - // - Match reconstructed Lambdas to MC Lambdas - // - Fill MC truth histograms - // - Fill reconstruction efficiency histograms + auto multiplicity = resoCollision.mcMultiplicity(); + auto inCent = resoCollision.cent(); + if (additionalConfig.cRecoINELgt0 && !resoCollision.isRecINELgt0()) // Check reco INELgt0 + return; + if (!resoCollision.isInAfterAllCuts()) + return; + histos.fill(HIST("multQA/h2MultCentMC"), inCent, multiplicity); + for (const auto& part : resoParents) { // loop over all pre-filtered Gen particle on selected events + auto pdgMother = part.pdgCode(); + if (std::abs(pdgMother) != kPdgChagedXi1820 && std::abs(pdgMother) != kPdgXi1820Zero) + continue; + if (std::abs(part.y()) >= additionalConfig.cfgRapidityCut) + continue; // skip if rapidity of the particle is outside of cut + auto motherPt = part.pt(); + auto daughter1PDG = part.daughterPDG1(); + auto daughter2PDG = part.daughterPDG2(); + + if (std::abs(pdgMother) == kPdgChagedXi1820) { // Explicity check for the safety. + // K- + Anti-Lambda, K+ + Anti-Lambda + if ((daughter1PDG == PDG_t::kKMinus && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kKMinus)) { + histos.fill(HIST("MC/hMCGenPtCentMultKminusLambda"), motherPt, inCent, multiplicity); + } else if ((daughter1PDG == PDG_t::kKPlus && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kKPlus)) { + histos.fill(HIST("MC/hMCGenPtCentMultKplusAntiLambda"), motherPt, inCent, multiplicity); + } + } else { + // K0s + Lambda, K0s + Anti-Lambda + if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && std::abs(daughter2PDG) == PDG_t::kK0Short)) { + histos.fill(HIST("MC/hMCGenPtCentMultK0sLambda"), motherPt, inCent, multiplicity); + } else if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && std::abs(daughter2PDG) == PDG_t::kK0Short)) { + histos.fill(HIST("MC/hMCGenPtCentMultK0sAntiLambda"), motherPt, inCent, multiplicity); + } + } + } } - PROCESS_SWITCH(Xi1820Analysis, processMCK0sLambda, "Process MC K0s + Lambda (placeholder)", false); + PROCESS_SWITCH(Xi1820Analysis, processMCGen, "Process Event for MC (Generated at selected events)", false); - void processMCGenerated(aod::McParticles const& mcParticles) + void processMCTruth(aod::McParticles const& mcParticles) // ->Let's keep it and use for injected MC QA...! { // Process MC generated particles (no reconstruction requirement) // Xi(1820)0 PDG code: 123314 (neutral, decays to K+ Lambda or K0s Lambda) @@ -1033,7 +1237,7 @@ struct Xi1820Analysis { // Xi(1820)0: PDG 123314 // Check if it's Xi(1820) or similar resonance - if (std::abs(pdg) != kPdgXi1820) + if (std::abs(pdg) != kPdgChagedXi1820 && std::abs(pdg) != kPdgXi1820Zero) continue; // Fill generated level histograms @@ -1041,9 +1245,9 @@ struct Xi1820Analysis { auto eta = mcParticle.eta(); auto y = mcParticle.y(); - histos.fill(HIST("MC/hMCGenXi1820Pt"), pt); - histos.fill(HIST("MC/hMCGenXi1820PtEta"), pt, eta); - histos.fill(HIST("MC/hMCGenXi1820Y"), y); + histos.fill(HIST("MC/hMCTruthXi1820Pt"), pt); + histos.fill(HIST("MC/hMCTruthXi1820PtEta"), pt, eta); + histos.fill(HIST("MC/hMCTruthXi1820Y"), y); // Get daughters auto daughters = mcParticle.daughters_as(); @@ -1064,43 +1268,42 @@ struct Xi1820Analysis { } iDaughter++; } - pMother = p1 + p2; // Check decay channels auto motherPt = pMother.Pt(); auto motherM = pMother.M(); - // K+ + Lambda - if ((daughter1PDG == PDG_t::kKPlus && daughter2PDG == PDG_t::kLambda0) || - (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kKPlus)) { - histos.fill(HIST("MC/hMCTruthInvMassKplusLambda"), motherM); - histos.fill(HIST("MC/hMCTruthMassPtKplusLambda"), motherM, motherPt); + // K- + Lambda + if ((daughter1PDG == PDG_t::kKMinus && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kKMinus)) { + histos.fill(HIST("MC/hMCTruthInvMassKminusLambda"), motherM); + histos.fill(HIST("MC/hMCTruthMassPtKminusLambda"), motherM, motherPt); } - // K- + Anti-Lambda - if ((daughter1PDG == PDG_t::kKMinus && daughter2PDG == PDG_t::kLambda0Bar) || - (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kKMinus)) { - histos.fill(HIST("MC/hMCTruthInvMassKminusAntiLambda"), motherM); - histos.fill(HIST("MC/hMCTruthMassPtKminusAntiLambda"), motherM, motherPt); + // K+ + Anti-Lambda + if ((daughter1PDG == PDG_t::kKPlus && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kKPlus)) { + histos.fill(HIST("MC/hMCTruthInvMassKplusAntiLambda"), motherM); + histos.fill(HIST("MC/hMCTruthMassPtKplusAntiLambda"), motherM, motherPt); } // K0s + Lambda - if ((daughter1PDG == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0) || - (daughter1PDG == PDG_t::kLambda0 && daughter2PDG == PDG_t::kK0Short)) { + if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0) || + (daughter1PDG == PDG_t::kLambda0 && std::abs(daughter2PDG) == PDG_t::kK0Short)) { histos.fill(HIST("MC/hMCTruthInvMassK0sLambda"), motherM); histos.fill(HIST("MC/hMCTruthMassPtK0sLambda"), motherM, motherPt); } // K0s + Anti-Lambda - if ((daughter1PDG == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0Bar) || - (daughter1PDG == PDG_t::kLambda0Bar && daughter2PDG == PDG_t::kK0Short)) { + if ((std::abs(daughter1PDG) == PDG_t::kK0Short && daughter2PDG == PDG_t::kLambda0Bar) || + (daughter1PDG == PDG_t::kLambda0Bar && std::abs(daughter2PDG) == PDG_t::kK0Short)) { histos.fill(HIST("MC/hMCTruthInvMassK0sAntiLambda"), motherM); histos.fill(HIST("MC/hMCTruthMassPtK0sAntiLambda"), motherM, motherPt); } } } - PROCESS_SWITCH(Xi1820Analysis, processMCGenerated, "Process MC generated particles", false); + PROCESS_SWITCH(Xi1820Analysis, processMCTruth, "Process MC Truth particles", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/CMakeLists.txt b/PWGLF/Tasks/Strangeness/CMakeLists.txt index e3d115324c6..d59685bc93d 100644 --- a/PWGLF/Tasks/Strangeness/CMakeLists.txt +++ b/PWGLF/Tasks/Strangeness/CMakeLists.txt @@ -166,6 +166,11 @@ o2physics_add_dpl_workflow(lambdajetpolarization PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambdajetpolarizationionsderived + SOURCES lambdaJetPolarizationIonsDerived.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(lambdaspincorrderived SOURCES lambdaspincorrderived.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.cxx b/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.cxx index aba22a2f900..e0f2198d899 100644 --- a/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.cxx +++ b/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.cxx @@ -43,6 +43,9 @@ #include #include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -96,6 +99,9 @@ struct CascadeAnalysisLightIonsDerivedData { 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 applyZVtxSelOnMCPV{"applyZVtxSelOnMCPV", false, "Apply Z-vtx cut on the PV of the generated collision?"}; + Configurable requireInel0{"requireInel0", false, "Enable INEL > 0 selection"}; + Configurable requireInel0OnMC{"requireInel0OnMC", false, "Enable INEL > 0 selection for MC gen events"}; // Track analysis Parameters Configurable minITSnCls{"minITSnCls", 4.0f, "min number of ITS clusters"}; @@ -129,6 +135,7 @@ struct CascadeAnalysisLightIonsDerivedData { Configurable minimumCascRadius{"minimumCascRadius", 1.1f, "Minimum Cascade Radius"}; Configurable v0masswindow{"v0masswindow", 0.005, "v0 mass window"}; Configurable competingmassrej{"competingmassrej", 0.008, "Competing mass rejection"}; + // Axes parameters ConfigurableAxis centEstimatorHistBin{"centEstimatorHistBin", {101, 0.0f, 101.0f}, ""}; ConfigurableAxis centralityBinning{"centralityBinning", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, ""}; @@ -145,7 +152,7 @@ struct CascadeAnalysisLightIonsDerivedData { kNGlobal }; // For manual sliceBy - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted> perMcCollision = aod::cascdata::straMCCollisionId; void init(InitContext const&) { @@ -183,6 +190,7 @@ struct CascadeAnalysisLightIonsDerivedData { registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(11, "kINELgr0"); registryData.add("number_of_events_data_vs_centrality", "number of events in data vs centrality", HistType::kTH2D, {{20, -0.5f, +19.5f}, {101, 0.0f, 101.0f}}); registryData.get(HIST("number_of_events_data_vs_centrality"))->GetXaxis()->SetBinLabel(1, "All collisions"); @@ -195,6 +203,7 @@ struct CascadeAnalysisLightIonsDerivedData { registryData.get(HIST("number_of_events_data_vs_centrality"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); registryData.get(HIST("number_of_events_data_vs_centrality"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); registryData.get(HIST("number_of_events_data_vs_centrality"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + registryData.get(HIST("number_of_events_data_vs_centrality"))->GetXaxis()->SetBinLabel(11, "kINELgr0"); registryData.get(HIST("number_of_events_data_vs_centrality"))->GetYaxis()->SetTitle("Centrality (%)"); // QC Histograms @@ -244,6 +253,7 @@ struct CascadeAnalysisLightIonsDerivedData { registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(11, "kINELgr0"); registryMC.add("number_of_events_mc_rec_vs_centrality", "number of events in mc_rec vs centrality", HistType::kTH2D, {{20, -0.5f, +19.5f}, {101, 0.0f, 101.0f}}); registryMC.get(HIST("number_of_events_mc_rec_vs_centrality"))->GetXaxis()->SetBinLabel(1, "All collisions"); @@ -256,6 +266,7 @@ struct CascadeAnalysisLightIonsDerivedData { registryMC.get(HIST("number_of_events_mc_rec_vs_centrality"))->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); registryMC.get(HIST("number_of_events_mc_rec_vs_centrality"))->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); registryMC.get(HIST("number_of_events_mc_rec_vs_centrality"))->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + registryMC.get(HIST("number_of_events_mc_rec_vs_centrality"))->GetXaxis()->SetBinLabel(11, "kINELgr0"); registryMC.get(HIST("number_of_events_mc_rec_vs_centrality"))->GetYaxis()->SetTitle("Centrality (%)"); // QC Histograms @@ -313,9 +324,11 @@ struct CascadeAnalysisLightIonsDerivedData { registryMC.add("h2dGenOmegaPlus", "h2dGenOmegaPlus", HistType::kTH2D, {centAxis, ptAxis}); // Histograms for event loss/splitting - registryMC.add("hGenEvents", "hGenEvents", HistType::kTH2D, {{axisNch}, {2, -0.5f, +1.5f}}); + registryMC.add("hGenEvents", "hGenEvents", HistType::kTH2D, {{axisNch}, {4, -0.5f, +3.5f}}); registryMC.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(1, "All gen. events"); - registryMC.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(2, "Gen. with at least 1 rec. events"); + registryMC.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(2, "All gen. events in INEL > 0"); + registryMC.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(3, "Gen. with at least 1 rec. events"); + registryMC.get(HIST("hGenEvents"))->GetYaxis()->SetBinLabel(4, "Gen. with at least 1 rec. events in INEL > 0"); registryMC.add("hGenEventCentrality", "hGenEventCentrality", kTH1D, {{101, 0.0f, 101.0f}}); registryMC.add("hCentralityVsNcoll_beforeEvSel", "hCentralityVsNcoll_beforeEvSel", HistType::kTH2D, {centAxis, {50, -0.5f, 49.5f}}); @@ -631,6 +644,10 @@ struct CascadeAnalysisLightIonsDerivedData { continue; } + if (requireInel0 && collision.multNTracksPVeta1() < 1) { + continue; + } + // Find the collision with the biggest nbr of PV contributors // Follows what was done here: https://github.com/AliceO2Group/O2Physics/blob/master/Common/TableProducer/mcCollsExtra.cxx#L93 if (biggestNContribs < collision.multPVTotalContributors()) { @@ -650,11 +667,16 @@ struct CascadeAnalysisLightIonsDerivedData { std::vector listBestCollisionIdx(mcCollisions.size()); for (auto const& mcCollision : mcCollisions) { // event selections - if (applyVtxZ && std::fabs(mcCollision.posZ()) > zVtx) + if (applyZVtxSelOnMCPV && std::fabs(mcCollision.posZ()) > zVtx) continue; registryMC.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 0 /* all gen. events*/); + if (requireInel0OnMC && mcCollision.multMCNParticlesEta10() < 1) { + continue; + } + registryMC.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 1 /* all gen. events in INEL > 0*/); + auto groupedCollisions = getGroupedCollisions(collisions, mcCollision.globalIndex()); // Check if there is at least one of the reconstructed collisions associated to this MC collision // If so, we consider it @@ -698,6 +720,10 @@ struct CascadeAnalysisLightIonsDerivedData { continue; } + if (requireInel0 && collision.multNTracksPVeta1() < 1) { + continue; + } + if (biggestNContribs < collision.multPVTotalContributors()) { biggestNContribs = collision.multPVTotalContributors(); if (centralityEstimator == Option::kFT0C) @@ -721,8 +747,8 @@ struct CascadeAnalysisLightIonsDerivedData { registryQC.fill(HIST("hVertexZGen"), mcCollision.posZ()); if (atLeastOne) { - registryMC.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 1 /* at least 1 rec. event*/); - + registryMC.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 2 /* at least 1 rec. event*/); + registryMC.fill(HIST("hGenEvents"), mcCollision.multMCNParticlesEta05(), 3 /* at least 1 rec. event in INEL > 0*/); registryMC.fill(HIST("hGenEventCentrality"), centralitydata); } } @@ -815,6 +841,12 @@ struct CascadeAnalysisLightIonsDerivedData { registryData.fill(HIST("number_of_events_data"), 9 /* Not at same bunch pile-up */); registryData.fill(HIST("number_of_events_data_vs_centrality"), 9, centrality); + if (requireInel0 && collision.multNTracksPVeta1() < 1) { + return; + } + registryData.fill(HIST("number_of_events_data"), 10 /* INEL > 0 */); + registryData.fill(HIST("number_of_events_data_vs_centrality"), 10, centrality); + // Store the Zvtx registryQC.fill(HIST("hVertexZdata"), collision.posZ()); @@ -874,168 +906,188 @@ struct CascadeAnalysisLightIonsDerivedData { PROCESS_SWITCH(CascadeAnalysisLightIonsDerivedData, processData, "Process data", true); - void processMonteCarloRec(SimCollisions const& RecCols, CascadeMCCandidates const& fullCascades, DaughterTracks const&, CascadeMCCores const&) + void processMonteCarloRec(SimCollisions::iterator const& RecCol, CascadeMCCandidates const& fullCascades, DaughterTracks const&, CascadeMCCores const&) { - for (const auto& RecCol : RecCols) { - // Fill event counter before event selection - registryMC.fill(HIST("number_of_events_mc_rec"), 0); + // Fill event counter before event selection + registryMC.fill(HIST("number_of_events_mc_rec"), 0); - // Initialize CCDB objects using the BC info - initCCDB(RecCol); + // Initialize CCDB objects using the BC info + initCCDB(RecCol); - // Define the event centrality using different estimators - float centralityMcRec = -1; - float multiplicityMcRec = -1; + // Define the event centrality using different estimators + float centralityMcRec = -1; + float multiplicityMcRec = -1; - if (centralityEstimator == Option::kFT0C) { - centralityMcRec = RecCol.centFT0C(); - multiplicityMcRec = RecCol.multFT0C(); - } - if (centralityEstimator == Option::kFT0M) { - centralityMcRec = RecCol.centFT0M(); - multiplicityMcRec = RecCol.multFT0C() + RecCol.multFT0A(); - } - if (centralityEstimator == Option::kFV0A) { - centralityMcRec = RecCol.centFV0A(); - multiplicityMcRec = RecCol.multFV0A(); - } - if (centralityEstimator == Option::kNGlobal) { - centralityMcRec = RecCol.centNGlobal(); - multiplicityMcRec = RecCol.multNTracksGlobal(); - } + if (centralityEstimator == Option::kFT0C) { + centralityMcRec = RecCol.centFT0C(); + multiplicityMcRec = RecCol.multFT0C(); + } + if (centralityEstimator == Option::kFT0M) { + centralityMcRec = RecCol.centFT0M(); + multiplicityMcRec = RecCol.multFT0C() + RecCol.multFT0A(); + } + if (centralityEstimator == Option::kFV0A) { + centralityMcRec = RecCol.centFV0A(); + multiplicityMcRec = RecCol.multFV0A(); + } + if (centralityEstimator == Option::kNGlobal) { + centralityMcRec = RecCol.centNGlobal(); + multiplicityMcRec = RecCol.multNTracksGlobal(); + } - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 0, centralityMcRec); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 0, centralityMcRec); - // event selections - if (applySel8 && !RecCol.sel8()) - continue; - registryMC.fill(HIST("number_of_events_mc_rec"), 1); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 1, centralityMcRec); + // event selections + if (applySel8 && !RecCol.sel8()) + return; + registryMC.fill(HIST("number_of_events_mc_rec"), 1); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 1, centralityMcRec); - if (applyVtxZ && std::fabs(RecCol.posZ()) > zVtx) - continue; - registryMC.fill(HIST("number_of_events_mc_rec"), 2); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 2, centralityMcRec); + if (applyVtxZ && std::fabs(RecCol.posZ()) > zVtx) + return; + registryMC.fill(HIST("number_of_events_mc_rec"), 2); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 2, centralityMcRec); - if (rejectITSROFBorder && !RecCol.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 3 /* Not at ITS ROF border */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 3, centralityMcRec); + if (rejectITSROFBorder && !RecCol.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 3 /* Not at ITS ROF border */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 3, centralityMcRec); - if (rejectTFBorder && !RecCol.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 4 /* Not at TF border */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 4, centralityMcRec); + if (rejectTFBorder && !RecCol.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 4 /* Not at TF border */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 4, centralityMcRec); - if (requireVertexITSTPC && !RecCol.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 5 /* Contains at least one ITS-TPC track */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 5, centralityMcRec); + if (requireVertexITSTPC && !RecCol.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 5 /* Contains at least one ITS-TPC track */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 5, centralityMcRec); - if (requireIsGoodZvtxFT0VsPV && !RecCol.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 6 /* PV position consistency check */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 6, centralityMcRec); + if (requireIsGoodZvtxFT0VsPV && !RecCol.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 6 /* PV position consistency check */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 6, centralityMcRec); - if (requireIsVertexTOFmatched && !RecCol.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 7 /* PV with at least one contributor matched with TOF */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 7, centralityMcRec); + if (requireIsVertexTOFmatched && !RecCol.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 7 /* PV with at least one contributor matched with TOF */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 7, centralityMcRec); - if (requireIsVertexTRDmatched && !RecCol.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 8 /* PV with at least one contributor matched with TRD */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 8, centralityMcRec); + if (requireIsVertexTRDmatched && !RecCol.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 8 /* PV with at least one contributor matched with TRD */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 8, centralityMcRec); - if (rejectSameBunchPileup && !RecCol.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - continue; - } - registryMC.fill(HIST("number_of_events_mc_rec"), 9 /* Not at same bunch pile-up */); - registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 9, centralityMcRec); + if (rejectSameBunchPileup && !RecCol.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 9 /* Not at same bunch pile-up */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 9, centralityMcRec); - // Store the Zvtx - registryQC.fill(HIST("hVertexZRec"), RecCol.posZ()); + if (requireInel0 && RecCol.multNTracksPVeta1() < 1) { + return; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 10 /* INEL > 0 */); + registryMC.fill(HIST("number_of_events_mc_rec_vs_centrality"), 10, centralityMcRec); - // Store the event centrality - registryMC.fill(HIST("hCentEstimator_truerec"), centralityMcRec); - registryMC.fill(HIST("hCentralityVsNch_truerec"), centralityMcRec, RecCol.multNTracksPVeta1()); - registryMC.fill(HIST("hCentralityVsMultiplicity_truerec"), centralityMcRec, multiplicityMcRec); + // Store the Zvtx + registryQC.fill(HIST("hVertexZRec"), RecCol.posZ()); - for (const auto& casc : fullCascades) { - if (etaMin > casc.bacheloreta() || casc.bacheloreta() > etaMax || - etaMin > casc.negativeeta() || casc.negativeeta() > etaMax || - etaMin > casc.positiveeta() || casc.positiveeta() > etaMax) - continue; // remove acceptance that's badly reproduced by MC / superfluous in future + // Store the event centrality + registryMC.fill(HIST("hCentEstimator_truerec"), centralityMcRec); + registryMC.fill(HIST("hCentralityVsNch_truerec"), centralityMcRec, RecCol.multNTracksPVeta1()); + registryMC.fill(HIST("hCentralityVsMultiplicity_truerec"), centralityMcRec, multiplicityMcRec); - if (!casc.has_cascMCCore()) - continue; + for (const auto& casc : fullCascades) { + if (etaMin > casc.bacheloreta() || casc.bacheloreta() > etaMax || + etaMin > casc.negativeeta() || casc.negativeeta() > etaMax || + etaMin > casc.positiveeta() || casc.positiveeta() > etaMax) + continue; // remove acceptance that's badly reproduced by MC / superfluous in future - auto cascMC = casc.template cascMCCore_as(); + if (!casc.has_cascMCCore()) + continue; - auto bach = casc.bachTrackExtra_as(); - auto pos = casc.posTrackExtra_as(); - auto neg = casc.negTrackExtra_as(); + auto cascMC = casc.template cascMCCore_as(); - int pdgParent = cascMC.pdgCode(); - bool isPhysPrim = cascMC.isPhysicalPrimary(); - if (pdgParent == 0) - continue; - if (!isPhysPrim) - continue; + auto bach = casc.bachTrackExtra_as(); + auto pos = casc.posTrackExtra_as(); + auto neg = casc.negTrackExtra_as(); + + int pdgParent = cascMC.pdgCode(); + bool isPhysPrim = cascMC.isPhysicalPrimary(); + if (pdgParent == 0) + continue; + if (!isPhysPrim) + continue; + + float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + + // ------------------------------------- Store selctions distribution for QC + registryQC.fill(HIST("hv0cosPARec"), casc.v0cosPA(RecCol.posX(), RecCol.posY(), RecCol.posZ())); + registryQC.fill(HIST("hcasccosPARec"), casc.casccosPA(RecCol.posX(), RecCol.posY(), RecCol.posZ())); + registryQC.fill(HIST("hv0radiusRec"), casc.v0radius()); + registryQC.fill(HIST("hcascradiusRec"), casc.cascradius()); + registryQC.fill(HIST("hdcaV0daughtersRec"), casc.dcaV0daughters()); + registryQC.fill(HIST("hdcacascdaughtersRec"), casc.dcacascdaughters()); + registryQC.fill(HIST("hdcapostopvRec"), casc.dcapostopv()); + registryQC.fill(HIST("hdcanegtopvRec"), casc.dcanegtopv()); + registryQC.fill(HIST("hdcabachtopvRec"), casc.dcabachtopv()); + registryQC.fill(HIST("hdcav0topvRec"), casc.dcav0topv(RecCol.posX(), RecCol.posY(), RecCol.posZ())); - float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); - - // ------------------------------------- Store selctions distribution for QC - registryQC.fill(HIST("hv0cosPARec"), casc.v0cosPA(RecCol.posX(), RecCol.posY(), RecCol.posZ())); - registryQC.fill(HIST("hcasccosPARec"), casc.casccosPA(RecCol.posX(), RecCol.posY(), RecCol.posZ())); - registryQC.fill(HIST("hv0radiusRec"), casc.v0radius()); - registryQC.fill(HIST("hcascradiusRec"), casc.cascradius()); - registryQC.fill(HIST("hdcaV0daughtersRec"), casc.dcaV0daughters()); - registryQC.fill(HIST("hdcacascdaughtersRec"), casc.dcacascdaughters()); - registryQC.fill(HIST("hdcapostopvRec"), casc.dcapostopv()); - registryQC.fill(HIST("hdcanegtopvRec"), casc.dcanegtopv()); - registryQC.fill(HIST("hdcabachtopvRec"), casc.dcabachtopv()); - registryQC.fill(HIST("hdcav0topvRec"), casc.dcav0topv(RecCol.posX(), RecCol.posY(), RecCol.posZ())); - - // ------------------------------------- Store selctions distribution for analysis - if (casc.sign() < 0) { - if (pdgParent == kXiMinus) { - registryMC.fill(HIST("hMassXineg_truerec"), centralityMcRec, ptmc, casc.mXi()); - } - if (pdgParent == kOmegaMinus) { - registryMC.fill(HIST("hMassOmeganeg_truerec"), centralityMcRec, ptmc, casc.mOmega()); - } + // ------------------------------------- Store selctions distribution for analysis + if (casc.sign() < 0) { + if (pdgParent == kXiMinus) { + registryMC.fill(HIST("hMassXineg_truerec"), centralityMcRec, ptmc, casc.mXi()); } + if (pdgParent == kOmegaMinus) { + registryMC.fill(HIST("hMassOmeganeg_truerec"), centralityMcRec, ptmc, casc.mOmega()); + } + } - if (casc.sign() > 0) { - if (pdgParent == kXiPlusBar) { - registryMC.fill(HIST("hMassXipos_truerec"), centralityMcRec, ptmc, casc.mXi()); - } - if (pdgParent == kOmegaPlusBar) { - registryMC.fill(HIST("hMassOmegapos_truerec"), centralityMcRec, ptmc, casc.mOmega()); - } + if (casc.sign() > 0) { + if (pdgParent == kXiPlusBar) { + registryMC.fill(HIST("hMassXipos_truerec"), centralityMcRec, ptmc, casc.mXi()); + } + if (pdgParent == kOmegaPlusBar) { + registryMC.fill(HIST("hMassOmegapos_truerec"), centralityMcRec, ptmc, casc.mOmega()); } + } - if (casc.sign() < 0 && pdgParent == kXiMinus && passedXiSelection(casc, pos, neg, bach, RecCol)) { + // compute MC association + const bool isXiMC = (std::abs(pdgParent) == PDG_t::kXiMinus); + const bool isOmegaMC = (std::abs(pdgParent) == PDG_t::kOmegaMinus); + bool isTrueMCCascade = false; + bool isTrueMCCascadeDecay = false; + bool isCorrectLambdaDecay = false; + + if (isPhysPrim && (isXiMC || isOmegaMC)) + isTrueMCCascade = true; + if (isTrueMCCascade && ((casc.sign() > 0 && cascMC.pdgCodePositive() == PDG_t::kPiPlus && cascMC.pdgCodeNegative() == PDG_t::kProtonBar) || (casc.sign() < 0 && cascMC.pdgCodePositive() == PDG_t::kProton && cascMC.pdgCodeNegative() == PDG_t::kPiMinus))) + isCorrectLambdaDecay = true; + if (isTrueMCCascade && isCorrectLambdaDecay && ((isXiMC && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kPiPlus) || (isOmegaMC && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kKPlus))) + isTrueMCCascadeDecay = true; + + if (isTrueMCCascadeDecay) { + if (pdgParent == kXiMinus && passedXiSelection(casc, pos, neg, bach, RecCol)) { registryMC.fill(HIST("hMassXinegSelected_truerec"), centralityMcRec, ptmc, casc.mXi()); } - if (casc.sign() < 0 && pdgParent == kOmegaMinus && passedOmegaSelection(casc, pos, neg, bach, RecCol)) { + if (pdgParent == kOmegaMinus && passedOmegaSelection(casc, pos, neg, bach, RecCol)) { registryMC.fill(HIST("hMassOmeganegSelected_truerec"), centralityMcRec, ptmc, casc.mOmega()); } - if (casc.sign() > 0 && pdgParent == kXiPlusBar && passedXiSelection(casc, pos, neg, bach, RecCol)) { + if (pdgParent == kXiPlusBar && passedXiSelection(casc, pos, neg, bach, RecCol)) { registryMC.fill(HIST("hMassXiposSelected_truerec"), centralityMcRec, ptmc, casc.mXi()); } - if (casc.sign() > 0 && pdgParent == kOmegaPlusBar && passedOmegaSelection(casc, pos, neg, bach, RecCol)) { + if (pdgParent == kOmegaPlusBar && passedOmegaSelection(casc, pos, neg, bach, RecCol)) { registryMC.fill(HIST("hMassOmegaposSelected_truerec"), centralityMcRec, ptmc, casc.mOmega()); } - } // casc loop - } // rec.collision loop + } + } // casc loop } PROCESS_SWITCH(CascadeAnalysisLightIonsDerivedData, processMonteCarloRec, "Process MC Rec", false); @@ -1055,17 +1107,20 @@ struct CascadeAnalysisLightIonsDerivedData { if (!isPhysPrim) continue; - float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + float ptmc = cascMC.ptMC(); auto mcCollision = cascMC.template straMCCollision_as(); // event selections - if (applyVtxZ && std::abs(mcCollision.posZ()) > zVtx) + if (applyZVtxSelOnMCPV && std::abs(mcCollision.posZ()) > zVtx) continue; - // Store the Zvtx registryQC.fill(HIST("hVertexZGen"), mcCollision.posZ()); + if (requireInel0OnMC && mcCollision.multMCNParticlesEta10() < 1) { + continue; + } + float centralityMC = 100.5f; if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { diff --git a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx index 098251faf28..0cf6ba274e5 100644 --- a/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx +++ b/PWGLF/Tasks/Strangeness/cascpostprocessing.cxx @@ -243,6 +243,8 @@ struct cascpostprocessing { bool isCorrectlyRec = 0; for (auto& candidate : mycascades) { + isCandidate = false; + isCorrectlyRec = false; switch (evSelFlag) { case 1: { diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index 949709c68fc..28a6759f51e 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -107,6 +107,7 @@ struct derivedlambdakzeroanalysis { Configurable doPPAnalysis{"doPPAnalysis", false, "if in pp, set to true"}; Configurable irSource{"irSource", "T0VTX", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; Configurable centralityEstimator{"centralityEstimator", kCentFT0C, "Run 3 centrality estimator (0:CentFT0C, 1:CentFT0M, 2:CentFT0CVariant1, 3:CentMFT, 4:CentNGlobal, 5:CentFV0A)"}; + Configurable doUPCanalysis{"doUPCanalysis", true, "Study V0s in hadronic and UPC collisions"}; Configurable doEventQA{"doEventQA", false, "do event QA histograms"}; Configurable doCompleteTopoQA{"doCompleteTopoQA", false, "do topological variable QA histograms"}; @@ -214,6 +215,9 @@ struct derivedlambdakzeroanalysis { Configurable rejectNegITSafterburner{"rejectNegITSafterburner", false, "reject negative track formed out of afterburner ITS tracks"}; Configurable requirePosITSafterburnerOnly{"requirePosITSafterburnerOnly", false, "require positive track formed out of afterburner ITS tracks"}; Configurable requireNegITSafterburnerOnly{"requireNegITSafterburnerOnly", false, "require negative track formed out of afterburner ITS tracks"}; + Configurable requireAtLeastOneHasTOF{"requireAtLeastOneHasTOF", false, "require that at least one of daughter tracks has an associated TOF signal"}; + Configurable requirePosHasTOF{"requirePosHasTOF", false, "require that positive track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; + Configurable requireNegHasTOF{"requireNegHasTOF", false, "require that negative track has an associated TOF signal. On false, TOF requirement (if any) is only applied IF the track has an associated TOF signal."}; Configurable rejectTPCsectorBoundary{"rejectTPCsectorBoundary", false, "reject tracks close to the TPC sector boundaries"}; Configurable phiLowCut{"phiLowCut", "0.06/x+pi/18.0-0.06", "Low azimuth cut parametrisation"}; Configurable phiHighCut{"phiHighCut", "0.1/x+pi/18.0+0.06", "High azimuth cut parametrisation"}; @@ -526,15 +530,15 @@ struct derivedlambdakzeroanalysis { BITSET(maskAntiLambdaSpecific, selTPCPIDPositivePion); } // TOF PID - if (v0Selections.tofPidNsigmaCutK0Pi < 1e+5) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskK0ShortSpecific, selTOFNSigmaPositivePionK0Short); BITSET(maskK0ShortSpecific, selTOFDeltaTPositivePionK0Short); } - if (v0Selections.tofPidNsigmaCutLaPr < 1e+5) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut BITSET(maskLambdaSpecific, selTOFNSigmaPositiveProtonLambda); BITSET(maskLambdaSpecific, selTOFDeltaTPositiveProtonLambda); } - if (v0Selections.tofPidNsigmaCutLaPi < 1e+5) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requirePosHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskAntiLambdaSpecific, selTOFNSigmaPositivePionLambda); BITSET(maskAntiLambdaSpecific, selTOFDeltaTPositivePionLambda); } @@ -552,15 +556,15 @@ struct derivedlambdakzeroanalysis { BITSET(maskAntiLambdaSpecific, selTPCPIDNegativeProton); } // TOF PID - if (v0Selections.tofPidNsigmaCutK0Pi < 1e+5) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutK0Pi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskK0ShortSpecific, selTOFNSigmaNegativePionK0Short); BITSET(maskK0ShortSpecific, selTOFDeltaTNegativePionK0Short); } - if (v0Selections.tofPidNsigmaCutLaPi < 1e+5) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPi < 1e+5 || v0Selections.maxDeltaTimePion < 1e+6) { // safeguard for no cut BITSET(maskLambdaSpecific, selTOFNSigmaNegativePionLambda); BITSET(maskLambdaSpecific, selTOFDeltaTNegativePionLambda); } - if (v0Selections.tofPidNsigmaCutLaPr < 1e+5) { // safeguard for no cut + if (v0Selections.requireAtLeastOneHasTOF || v0Selections.requireNegHasTOF || v0Selections.tofPidNsigmaCutLaPr < 1e+5 || v0Selections.maxDeltaTimeProton < 1e+6) { // safeguard for no cut BITSET(maskAntiLambdaSpecific, selTOFNSigmaNegativeProtonLambda); BITSET(maskAntiLambdaSpecific, selTOFDeltaTNegativeProtonLambda); } @@ -705,9 +709,11 @@ struct derivedlambdakzeroanalysis { histos.add("hEventOccupancy", "hEventOccupancy", kTH1D, {axisConfigurations.axisOccupancy}); histos.add("hCentralityVsOccupancy", "hCentralityVsOccupancy", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisOccupancy}); - histos.add("hGapSide", "Gap side; Entries", kTH1D, {{5, -0.5, 4.5}}); - histos.add("hSelGapSide", "Selected gap side; Entries", kTH1D, {axisConfigurations.axisSelGap}); - histos.add("hEventCentralityVsSelGapSide", ";Centrality (%); Selected gap side", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisSelGap}); + if (doUPCanalysis) { + histos.add("hGapSide", "Gap side; Entries", kTH1D, {{5, -0.5, 4.5}}); + histos.add("hSelGapSide", "Selected gap side; Entries", kTH1D, {axisConfigurations.axisSelGap}); + histos.add("hEventCentralityVsSelGapSide", ";Centrality (%); Selected gap side", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisSelGap}); + } histos.add("hInteractionRate", "hInteractionRate", kTH1D, {axisConfigurations.axisIRBinning}); histos.add("hCentralityVsInteractionRate", "hCentralityVsInteractionRate", kTH2D, {{101, 0.0f, 101.0f}, axisConfigurations.axisIRBinning}); @@ -773,12 +779,14 @@ struct derivedlambdakzeroanalysis { if (analyseK0Short) { histos.add("h2dNbrOfK0ShortVsCentrality", "h2dNbrOfK0ShortVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); histos.add("h3dMassK0Short", "h3dMassK0Short", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); - // Non-UPC info - histos.add("h3dMassK0ShortHadronic", "h3dMassK0ShortHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); - // UPC info - histos.add("h3dMassK0ShortSGA", "h3dMassK0ShortSGA", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); - histos.add("h3dMassK0ShortSGC", "h3dMassK0ShortSGC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); - histos.add("h3dMassK0ShortDG", "h3dMassK0ShortDG", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); + if (doUPCanalysis) { + // Non-UPC info + histos.add("h3dMassK0ShortHadronic", "h3dMassK0ShortHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); + // UPC info + histos.add("h3dMassK0ShortSGA", "h3dMassK0ShortSGA", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); + histos.add("h3dMassK0ShortSGC", "h3dMassK0ShortSGC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); + histos.add("h3dMassK0ShortDG", "h3dMassK0ShortDG", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisK0Mass}); + } if (doTPCQA) { histos.add("K0Short/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); histos.add("K0Short/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); @@ -845,12 +853,14 @@ struct derivedlambdakzeroanalysis { if (analyseLambda) { histos.add("h2dNbrOfLambdaVsCentrality", "h2dNbrOfLambdaVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); histos.add("h3dMassLambda", "h3dMassLambda", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - // Non-UPC info - histos.add("h3dMassLambdaHadronic", "h3dMassLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - // UPC info - histos.add("h3dMassLambdaSGA", "h3dMassLambdaSGA", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - histos.add("h3dMassLambdaSGC", "h3dMassLambdaSGC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - histos.add("h3dMassLambdaDG", "h3dMassLambdaDG", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + if (doUPCanalysis) { + // Non-UPC info + histos.add("h3dMassLambdaHadronic", "h3dMassLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + // UPC info + histos.add("h3dMassLambdaSGA", "h3dMassLambdaSGA", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("h3dMassLambdaSGC", "h3dMassLambdaSGC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("h3dMassLambdaDG", "h3dMassLambdaDG", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + } if (doTPCQA) { histos.add("Lambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); histos.add("Lambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); @@ -917,12 +927,14 @@ struct derivedlambdakzeroanalysis { if (analyseAntiLambda) { histos.add("h2dNbrOfAntiLambdaVsCentrality", "h2dNbrOfAntiLambdaVsCentrality", kTH2D, {axisConfigurations.axisCentrality, {10, -0.5f, 9.5f}}); histos.add("h3dMassAntiLambda", "h3dMassAntiLambda", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - // Non-UPC info - histos.add("h3dMassAntiLambdaHadronic", "h3dMassAntiLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - // UPC info - histos.add("h3dMassAntiLambdaSGA", "h3dMassAntiLambdaSGA", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - histos.add("h3dMassAntiLambdaSGC", "h3dMassAntiLambdaSGC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); - histos.add("h3dMassAntiLambdaDG", "h3dMassAntiLambdaDG", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + if (doUPCanalysis) { + // Non-UPC info + histos.add("h3dMassAntiLambdaHadronic", "h3dMassAntiLambdaHadronic", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + // UPC info + histos.add("h3dMassAntiLambdaSGA", "h3dMassAntiLambdaSGA", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("h3dMassAntiLambdaSGC", "h3dMassAntiLambdaSGC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + histos.add("h3dMassAntiLambdaDG", "h3dMassAntiLambdaDG", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisLambdaMass}); + } if (doTPCQA) { histos.add("AntiLambda/h3dPosNsigmaTPC", "h3dPosNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); histos.add("AntiLambda/h3dNegNsigmaTPC", "h3dNegNsigmaTPC", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPtCoarse, axisConfigurations.axisNsigmaTPC}); @@ -987,10 +999,14 @@ struct derivedlambdakzeroanalysis { } } - if (analyseLambda && calculateFeeddownMatrix && (doprocessMonteCarloRun3 || doprocessMonteCarloRun2)) + if (analyseLambda && calculateFeeddownMatrix && (doprocessMonteCarloRun3 || doprocessMonteCarloRun2)) { histos.add("h3dLambdaFeeddown", "h3dLambdaFeeddown", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisPtXi}); - if (analyseAntiLambda && calculateFeeddownMatrix && (doprocessMonteCarloRun3 || doprocessMonteCarloRun2)) + histos.add("h3dLambdaFeeddownFromXi0", "h3dLambdaFeeddownFromXi0", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisPtXi}); + } + if (analyseAntiLambda && calculateFeeddownMatrix && (doprocessMonteCarloRun3 || doprocessMonteCarloRun2)) { histos.add("h3dAntiLambdaFeeddown", "h3dAntiLambdaFeeddown", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisPtXi}); + histos.add("h3dAntiLambdaFeeddownFromXi0", "h3dAntiLambdaFeeddownFromXi0", kTH3D, {axisConfigurations.axisCentrality, axisConfigurations.axisPt, axisConfigurations.axisPtXi}); + } if (analyseK0Short) histos.add("hMassK0Short", "hMassK0Short", kTH1D, {axisConfigurations.axisK0Mass}); @@ -1299,35 +1315,119 @@ struct derivedlambdakzeroanalysis { // TOF PID in DeltaT // Positive track - if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) - BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTPositivePionLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + if (v0Selections.requirePosHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) { + BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFDeltaTNegativePionLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) { + BITSET(bitMap, selTOFDeltaTPositivePionLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) { + BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + } + } + } else { // only apply TOF requirement if available + if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTPositivePionLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.posTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + } // Negative track - if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) - BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTNegativePionLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) - BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + if (v0Selections.requireNegHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) { + BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFDeltaTPositivePionLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) { + BITSET(bitMap, selTOFDeltaTNegativePionLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFDeltaTPositiveProtonLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) { + BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFDeltaTPositivePionK0Short); + } + } + } else { // only apply TOF requirement if available + if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTLaPr()) < v0Selections.maxDeltaTimeProton) + BITSET(bitMap, selTOFDeltaTNegativeProtonLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTLaPi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTNegativePionLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.negTOFDeltaTK0Pi()) < v0Selections.maxDeltaTimePion) + BITSET(bitMap, selTOFDeltaTNegativePionK0Short); + } // TOF PID in NSigma // Positive track - if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) - BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) - BITSET(bitMap, selTOFNSigmaPositivePionLambda); - if (!posTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) - BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + if (v0Selections.requirePosHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) { + BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFNSigmaNegativePionLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) { + BITSET(bitMap, selTOFNSigmaPositivePionLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); + } + } + if (v0.positiveHasTOF() && std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) { + BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // positive has a TOF hit --> no need to check for negative + BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + } + } + } else { // only apply TOF requirement if available + if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaLaPr()) < v0Selections.tofPidNsigmaCutLaPr) + BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaALaPi()) < v0Selections.tofPidNsigmaCutLaPi) + BITSET(bitMap, selTOFNSigmaPositivePionLambda); + if (!v0.positiveHasTOF() || std::fabs(v0.tofNSigmaK0PiPlus()) < v0Selections.tofPidNsigmaCutK0Pi) + BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + } // Negative track - if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) - BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) - BITSET(bitMap, selTOFNSigmaNegativePionLambda); - if (!negTrackExtra.hasTOF() || std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) - BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + if (v0Selections.requireNegHasTOF || v0Selections.requireAtLeastOneHasTOF) { + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) { + BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFNSigmaPositivePionLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) { + BITSET(bitMap, selTOFNSigmaNegativePionLambda); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFNSigmaPositiveProtonLambda); + } + } + if (v0.negativeHasTOF() && std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) { + BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + if (v0Selections.requireAtLeastOneHasTOF) { // negative has a TOF hit --> no need to check for positive + BITSET(bitMap, selTOFNSigmaPositivePionK0Short); + } + } + } else { // only apply TOF requirement if available + if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaALaPr()) < v0Selections.tofPidNsigmaCutLaPr) + BITSET(bitMap, selTOFNSigmaNegativeProtonLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaLaPi()) < v0Selections.tofPidNsigmaCutLaPi) + BITSET(bitMap, selTOFNSigmaNegativePionLambda); + if (!v0.negativeHasTOF() || std::fabs(v0.tofNSigmaK0PiMinus()) < v0Selections.tofPidNsigmaCutK0Pi) + BITSET(bitMap, selTOFNSigmaNegativePionK0Short); + } // ITS only tag if (posTrackExtra.tpcCrossedRows() < 1) @@ -1635,14 +1735,16 @@ struct derivedlambdakzeroanalysis { histos.fill(HIST("GeneralQA/hSelectionV0s"), selPhysPrimAntiLambda + 2); // 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()); - else if (gapSide == 1) - histos.fill(HIST("h3dMassK0ShortSGC"), centrality, pt, v0.mK0Short()); - else if (gapSide == 2) - histos.fill(HIST("h3dMassK0ShortDG"), centrality, pt, v0.mK0Short()); - else - histos.fill(HIST("h3dMassK0ShortHadronic"), centrality, pt, v0.mK0Short()); + if (doUPCanalysis) { + if (gapSide == 0) + histos.fill(HIST("h3dMassK0ShortSGA"), centrality, pt, v0.mK0Short()); + else if (gapSide == 1) + histos.fill(HIST("h3dMassK0ShortSGC"), centrality, pt, v0.mK0Short()); + else if (gapSide == 2) + histos.fill(HIST("h3dMassK0ShortDG"), centrality, pt, v0.mK0Short()); + else + histos.fill(HIST("h3dMassK0ShortHadronic"), centrality, pt, v0.mK0Short()); + } histos.fill(HIST("hMassK0Short"), v0.mK0Short()); if (doPlainTopoQA) { histos.fill(HIST("K0Short/hPosDCAToPV"), v0.dcapostopv()); @@ -1718,14 +1820,16 @@ struct derivedlambdakzeroanalysis { if (passLambdaSelections && analyseLambda) { histos.fill(HIST("GeneralQA/hSelectionV0s"), selPhysPrimAntiLambda + 2); // histos.fill(HIST("h3dMassLambda"), centrality, pt, v0.mLambda()); - if (gapSide == 0) - histos.fill(HIST("h3dMassLambdaSGA"), centrality, pt, v0.mLambda()); - else if (gapSide == 1) - histos.fill(HIST("h3dMassLambdaSGC"), centrality, pt, v0.mLambda()); - else if (gapSide == 2) - histos.fill(HIST("h3dMassLambdaDG"), centrality, pt, v0.mLambda()); - else - histos.fill(HIST("h3dMassLambdaHadronic"), centrality, pt, v0.mLambda()); + if (doUPCanalysis) { + if (gapSide == 0) + histos.fill(HIST("h3dMassLambdaSGA"), centrality, pt, v0.mLambda()); + else if (gapSide == 1) + histos.fill(HIST("h3dMassLambdaSGC"), centrality, pt, v0.mLambda()); + else if (gapSide == 2) + histos.fill(HIST("h3dMassLambdaDG"), centrality, pt, v0.mLambda()); + else + histos.fill(HIST("h3dMassLambdaHadronic"), centrality, pt, v0.mLambda()); + } histos.fill(HIST("hMassLambda"), v0.mLambda()); if (doPlainTopoQA) { histos.fill(HIST("Lambda/hPosDCAToPV"), v0.dcapostopv()); @@ -1801,14 +1905,16 @@ struct derivedlambdakzeroanalysis { if (passAntiLambdaSelections && analyseAntiLambda) { histos.fill(HIST("GeneralQA/hSelectionV0s"), selPhysPrimAntiLambda + 2); // histos.fill(HIST("h3dMassAntiLambda"), centrality, pt, v0.mAntiLambda()); - if (gapSide == 0) - histos.fill(HIST("h3dMassAntiLambdaSGA"), centrality, pt, v0.mAntiLambda()); - else if (gapSide == 1) - histos.fill(HIST("h3dMassAntiLambdaSGC"), centrality, pt, v0.mAntiLambda()); - else if (gapSide == 2) - histos.fill(HIST("h3dMassAntiLambdaDG"), centrality, pt, v0.mAntiLambda()); - else - histos.fill(HIST("h3dMassAntiLambdaHadronic"), centrality, pt, v0.mAntiLambda()); + if (doUPCanalysis) { + if (gapSide == 0) + histos.fill(HIST("h3dMassAntiLambdaSGA"), centrality, pt, v0.mAntiLambda()); + else if (gapSide == 1) + histos.fill(HIST("h3dMassAntiLambdaSGC"), centrality, pt, v0.mAntiLambda()); + else if (gapSide == 2) + histos.fill(HIST("h3dMassAntiLambdaDG"), centrality, pt, v0.mAntiLambda()); + else + histos.fill(HIST("h3dMassAntiLambdaHadronic"), centrality, pt, v0.mAntiLambda()); + } histos.fill(HIST("hMassAntiLambda"), v0.mAntiLambda()); if (doPlainTopoQA) { histos.fill(HIST("AntiLambda/hPosDCAToPV"), v0.dcapostopv()); @@ -1956,18 +2062,31 @@ struct derivedlambdakzeroanalysis { return; // does not have mother particle in record, skip auto v0mother = v0.motherMCPart(); - float rapidityXi = RecoDecay::y(std::array{v0mother.px(), v0mother.py(), v0mother.pz()}, o2::constants::physics::MassXiMinus); + float rapidityXi = 999.; + if (std::abs(v0mother.pdgCode()) == PDG_t::kXiMinus) + rapidityXi = RecoDecay::y(std::array{v0mother.px(), v0mother.py(), v0mother.pz()}, o2::constants::physics::MassXiMinus); + if (std::abs(v0mother.pdgCode()) == o2::constants::physics::Pdg::kXi0) + rapidityXi = RecoDecay::y(std::array{v0mother.px(), v0mother.py(), v0mother.pz()}, o2::constants::physics::MassXi0); + if (std::fabs(rapidityXi) > 0.5f) return; // not a valid mother rapidity (PDG selection is later) // __________________________________________ if (verifyMask(selMap, secondaryMaskSelectionLambda) && analyseLambda) { - if (v0mother.pdgCode() == PDG_t::kXiMinus && v0mother.isPhysicalPrimary()) - histos.fill(HIST("h3dLambdaFeeddown"), centrality, pt, std::hypot(v0mother.px(), v0mother.py())); + if (v0mother.isPhysicalPrimary()) { + if (v0mother.pdgCode() == PDG_t::kXiMinus) + histos.fill(HIST("h3dLambdaFeeddown"), centrality, pt, std::hypot(v0mother.px(), v0mother.py())); + if (v0mother.pdgCode() == PDG_t::kXiMinus || v0mother.pdgCode() == o2::constants::physics::Pdg::kXi0) + histos.fill(HIST("h3dLambdaFeeddownFromXi0"), centrality, pt, std::hypot(v0mother.px(), v0mother.py())); + } } if (verifyMask(selMap, secondaryMaskSelectionAntiLambda) && analyseAntiLambda) { - if (v0mother.pdgCode() == PDG_t::kXiPlusBar && v0mother.isPhysicalPrimary()) - histos.fill(HIST("h3dAntiLambdaFeeddown"), centrality, pt, std::hypot(v0mother.px(), v0mother.py())); + if (v0mother.isPhysicalPrimary()) { + if (v0mother.pdgCode() == PDG_t::kXiPlusBar) + histos.fill(HIST("h3dAntiLambdaFeeddown"), centrality, pt, std::hypot(v0mother.px(), v0mother.py())); + if (v0mother.pdgCode() == PDG_t::kXiPlusBar || v0mother.pdgCode() == -o2::constants::physics::Pdg::kXi0) + histos.fill(HIST("h3dAntiLambdaFeeddownFromXi0"), centrality, pt, std::hypot(v0mother.px(), v0mother.py())); + } } } @@ -2375,21 +2494,23 @@ struct derivedlambdakzeroanalysis { centrality = hRawCentrality->GetBinContent(hRawCentrality->FindBin(doPPAnalysis ? collision.multFT0A() + collision.multFT0C() : collision.multFT0C())); } - // gap side - gapSide = collision.gapSide(); - // -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); + if (doUPCanalysis) { + // gap side + gapSide = collision.gapSide(); + // -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("hEventCentralityVsSelGapSide"), centrality, selGapSide <= 2 ? selGapSide : -1); + } } else { // no, we are in Run 2 centrality = eventSelections.useSPDTrackletsCent ? collision.centRun2SPDTracklets() : collision.centRun2V0M(); } - histos.fill(HIST("hGapSide"), gapSide); - histos.fill(HIST("hSelGapSide"), selGapSide); - histos.fill(HIST("hEventCentralityVsSelGapSide"), centrality, selGapSide <= 2 ? selGapSide : -1); - histos.fill(HIST("hEventCentrality"), centrality); histos.fill(HIST("hCentralityVsNch"), centrality, collision.multNTracksPVeta1()); diff --git a/PWGLF/Tasks/Strangeness/derivedupcanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedupcanalysis.cxx index 6b43f823c12..9f340ebbf6c 100644 --- a/PWGLF/Tasks/Strangeness/derivedupcanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedupcanalysis.cxx @@ -65,18 +65,17 @@ using NeutronsMC = soa::Join; using CascMCCoresFull = soa::Join; -using StraCollisonsFull = soa::Join; -using StraCollisonFull = soa::Join::iterator; +using StraCollisonsFull = soa::Join; +using StraCollisonFull = soa::Join::iterator; -using StraCollisonsFullMC = soa::Join; -using StraCollisonFullMC = soa::Join::iterator; +using StraCollisonsFullMC = soa::Join; +using StraCollisonFullMC = soa::Join::iterator; using StraMCCollisionsFull = soa::Join; using V0MCCoresFull = soa::Join; struct Derivedupcanalysis { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - // master analysis switches Configurable analyseK0Short{"analyseK0Short", true, "process K0Short-like candidates"}; Configurable analyseLambda{"analyseLambda", true, "process Lambda-like candidates"}; @@ -168,6 +167,13 @@ struct Derivedupcanalysis { Configurable ft0a{"ft0a", 100., "FT0A threshold"}; Configurable ft0c{"ft0c", 50., "FT0C threshold"}; Configurable zdc{"zdc", 1., "ZDC threshold"}; + Configurable fddaTimeCut{"fddaTimeCut", -1., "FDDA timing cut (ns); negative: no cut"}; + Configurable fddcTimeCut{"fddcTimeCut", -1., "FDDC timing cut (ns); negative: no cut"}; + Configurable fv0aTimeCut{"fv0aTimeCut", -1., "FV0A timing cut (ns); negative: no cut"}; + Configurable ft0aTimeCut{"ft0aTimeCut", -1., "FT0A timing cut (ns); negative: no cut"}; + Configurable ft0cTimeCut{"ft0cTimeCut", -1., "FT0C timing cut (ns); negative: no cut"}; + Configurable zdcTimeCut{"zdcTimeCut", 2., "ZDC timing cut (ns)"}; + Configurable requireZDCTiming{"requireZDCTiming", true, "require valid ZDC timing for gap-side selection"}; Configurable genGapSide{"genGapSide", 0, "0 -- A, 1 -- C, 2 -- double"}; } upcCuts; @@ -213,6 +219,8 @@ struct Derivedupcanalysis { ConfigurableAxis axisFDDCampl{"axisFDDCampl", {100, 0.0f, 2000.0f}, "FDDCamplitude"}; ConfigurableAxis axisZNAampl{"axisZNAampl", {100, 0.0f, 250.0f}, "ZNAamplitude"}; ConfigurableAxis axisZNCampl{"axisZNCampl", {100, 0.0f, 250.0f}, "ZNCamplitude"}; + ConfigurableAxis axisFitTime{"axisFitTime", {166, -42.5f, 40.5f}, "FIT time (ns)"}; + ConfigurableAxis axisZdcTime{"axisZdcTime", {110, -12.5f, 10.0f}, "ZDC time (ns)"}; } axisDetectors; // for MC @@ -268,7 +276,7 @@ struct Derivedupcanalysis { ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 250.0f, 500.0f, 750.0f, 1000.0f, 1500.0f, 2000.0f, 3000.0f, 4500.0f, 6000.0f, 8000.0f, 10000.0f, 50000.0f}, "Occupancy"}; // UPC axes - ConfigurableAxis axisSelGap{"axisSelGap", {4, -1.5, 2.5}, "Gap side"}; + ConfigurableAxis axisSelGap{"axisSelGap", {7, -1.5, 5.5}, "Gap side"}; // AP plot axes ConfigurableAxis axisAPAlpha{"axisAPAlpha", {220, -1.1f, 1.1f}, "V0 AP alpha"}; @@ -297,6 +305,8 @@ struct Derivedupcanalysis { ConfigurableAxis axisCtau{"axisCtau", {200, 0.0f, 20.0f}, "c x tau (cm)"}; static constexpr std::string_view kParticlenames[] = {"K0Short", "Lambda", "AntiLambda", "Xi", "AntiXi", "Omega", "AntiOmega"}; + static constexpr uint8_t kFT0TriggerBitIsActiveA = 5; + static constexpr uint8_t kFT0TriggerBitIsActiveC = 6; void setBits(std::bitset& mask, std::initializer_list selections) { @@ -931,6 +941,22 @@ struct Derivedupcanalysis { histos.add("eventQA/hFT0", "hFT0", kTH3D, {axisDetectors.axisFT0Aampl, axisDetectors.axisFT0Campl, axisSelGap}); histos.add("eventQA/hFDD", "hFDD", kTH3D, {axisDetectors.axisFDDAampl, axisDetectors.axisFDDCampl, axisSelGap}); histos.add("eventQA/hZN", "hZN", kTH3D, {axisDetectors.axisZNAampl, axisDetectors.axisZNCampl, axisSelGap}); + histos.add("eventQA/hTimeFT0A", "hTimeFT0A", kTH2D, {axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hTimeFT0C", "hTimeFT0C", kTH2D, {axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hTimeFV0A", "hTimeFV0A", kTH2D, {axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hTimeFDDA", "hTimeFDDA", kTH2D, {axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hTimeFDDC", "hTimeFDDC", kTH2D, {axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hTimeFT0APreSel", "hTimeFT0APreSel", kTH1D, {axisDetectors.axisFitTime}); + histos.add("eventQA/hTimeFT0CPreSel", "hTimeFT0CPreSel", kTH1D, {axisDetectors.axisFitTime}); + histos.add("eventQA/hTimeFV0APreSel", "hTimeFV0APreSel", kTH1D, {axisDetectors.axisFitTime}); + histos.add("eventQA/hTimeFDDAPreSel", "hTimeFDDAPreSel", kTH1D, {axisDetectors.axisFitTime}); + histos.add("eventQA/hTimeFDDCPreSel", "hTimeFDDCPreSel", kTH1D, {axisDetectors.axisFitTime}); + histos.add("eventQA/hFT0Time", "hFT0Time", kTH3D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hFDDTime", "hFDDTime", kTH3D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime, axisSelGap}); + histos.add("eventQA/hZNTime", "hZNTime", kTH3D, {axisDetectors.axisZdcTime, axisDetectors.axisZdcTime, axisSelGap}); + histos.add("eventQA/hFT0TimePreSel", "hFT0TimePreSel", kTH2D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime}); + histos.add("eventQA/hFDDTimePreSel", "hFDDTimePreSel", kTH2D, {axisDetectors.axisFitTime, axisDetectors.axisFitTime}); + histos.add("eventQA/hZNTimePreSel", "hZNTimePreSel", kTH2D, {axisDetectors.axisZdcTime, axisDetectors.axisZdcTime}); if (doprocessGenerated) { histos.add("eventQA/mc/hEventSelectionMC", "hEventSelectionMC", kTH3D, {{3, -0.5, 2.5}, axisNTracksPVeta1, axisGeneratorIds}); @@ -955,7 +981,7 @@ struct Derivedupcanalysis { histos.add("eventQA/mc/hNTracksPVeta1vsMCNParticlesEta10rec", "hNTracksPVeta1vsMCNParticlesEta10rec", kTH2D, {axisNTracksPVeta1, axisNTracksPVeta1}); histos.add("eventQA/mc/hNTracksGlobalvstotalMultMCParticles", "hNTracksGlobalvstotalMultMCParticles", kTH2D, {axisNTracksGlobal, axisNchInvMass}); histos.add("eventQA/mc/hNTracksPVeta1vstotalMultMCParticles", "hNTracksPVeta1vstotalMultMCParticles", kTH2D, {axisNTracksPVeta1, axisNchInvMass}); - histos.add("eventQA/hSelGapSideNoNeutrons", "Selected gap side (no n); Entries", kTH1D, {{5, -0.5, 4.5}}); + histos.add("eventQA/hSelGapSideNoNeutrons", "Selected gap side (no n); Entries", kTH1D, {axisSelGap}); } if (doprocessV0sMC) { @@ -1050,12 +1076,164 @@ struct Derivedupcanalysis { } template - int getGapSide(TCollision const& collision) + int applyZDCTiming(int selGapSide, TCollision const& collision) { - int selGapSide = sgSelector.trueGap(collision, upcCuts.fv0a, upcCuts.ft0a, upcCuts.ft0c, upcCuts.zdc); + if (!upcCuts.requireZDCTiming) { + return selGapSide; + } + if (selGapSide == o2::aod::sgselector::SingleGapA || + selGapSide == o2::aod::sgselector::SingleGapC || + selGapSide == o2::aod::sgselector::DoubleGap) { + + const float timeZNA = collision.timeZNA(); + const float timeZNC = collision.timeZNC(); + const float cut = upcCuts.zdcTimeCut; + + auto isInvalidTime = [](float time) { + return !std::isfinite(time) || (std::abs(time) == 999.f); + }; + + const bool gapA = isInvalidTime(timeZNA) || (std::abs(timeZNA) > cut); + const bool gapC = isInvalidTime(timeZNC) || (std::abs(timeZNC) > cut); + const bool neutronA = !isInvalidTime(timeZNA) && (std::abs(timeZNA) < cut); + const bool neutronC = !isInvalidTime(timeZNC) && (std::abs(timeZNC) < cut); + + if (selGapSide == o2::aod::sgselector::SingleGapA) { // 0nXn + if (!(gapA && neutronC)) { + selGapSide = o2::aod::sgselector::NoGap; + } + } else if (selGapSide == o2::aod::sgselector::SingleGapC) { // Xn0n + if (!(neutronA && gapC)) { + selGapSide = o2::aod::sgselector::NoGap; + } + } else if (selGapSide == o2::aod::sgselector::DoubleGap) { + if (!(gapA && gapC)) { + selGapSide = o2::aod::sgselector::NoGap; + } + } + } + return selGapSide; } + bool isInvalidTime(float time) const + { + return !std::isfinite(time) || (std::abs(time) >= 998.f); + } + + bool isTimingCutEnabled(float cut) const + { + return cut >= 0.f; + } + + bool isTimingGap(float time, float cut) const + { + return isInvalidTime(time) || (std::abs(time) > cut); + } + + bool isTimingActivity(float time, float cut) const + { + return !isInvalidTime(time) && (std::abs(time) < cut); + } + + bool hasFT0Activity(uint8_t triggerMask, uint8_t bit) const + { + return (triggerMask & (static_cast(1u) << bit)) != 0; + } + + template + int applyFITTiming(int selGapSide, TCollision const& collision) + { + if (selGapSide != o2::aod::sgselector::SingleGapA && + selGapSide != o2::aod::sgselector::SingleGapC && + selGapSide != o2::aod::sgselector::DoubleGap) { + return selGapSide; + } + + const bool useFDDA = isTimingCutEnabled(upcCuts.fddaTimeCut); + const bool useFDDC = isTimingCutEnabled(upcCuts.fddcTimeCut); + const bool useFV0A = isTimingCutEnabled(upcCuts.fv0aTimeCut); + const bool useFT0A = isTimingCutEnabled(upcCuts.ft0aTimeCut); + const bool useFT0C = isTimingCutEnabled(upcCuts.ft0cTimeCut); + + if (!(useFDDA || useFDDC || useFV0A || useFT0A || useFT0C)) { + return selGapSide; + } + + const bool ft0ActiveA = hasFT0Activity(collision.triggerMaskFT0(), kFT0TriggerBitIsActiveA); + const bool ft0ActiveC = hasFT0Activity(collision.triggerMaskFT0(), kFT0TriggerBitIsActiveC); + + const bool gapFDDA = !useFDDA || isTimingGap(collision.timeFDDA(), upcCuts.fddaTimeCut); + const bool actFDDA = !useFDDA || isTimingActivity(collision.timeFDDA(), upcCuts.fddaTimeCut); + const bool gapFDDC = !useFDDC || isTimingGap(collision.timeFDDC(), upcCuts.fddcTimeCut); + const bool actFDDC = !useFDDC || isTimingActivity(collision.timeFDDC(), upcCuts.fddcTimeCut); + const bool gapFV0A = !useFV0A || isTimingGap(collision.timeFV0A(), upcCuts.fv0aTimeCut); + const bool actFV0A = !useFV0A || isTimingActivity(collision.timeFV0A(), upcCuts.fv0aTimeCut); + const bool gapFT0A = !useFT0A || !ft0ActiveA || isTimingGap(collision.timeFT0A(), upcCuts.ft0aTimeCut); + const bool actFT0A = !useFT0A || (ft0ActiveA && isTimingActivity(collision.timeFT0A(), upcCuts.ft0aTimeCut)); + const bool gapFT0C = !useFT0C || !ft0ActiveC || isTimingGap(collision.timeFT0C(), upcCuts.ft0cTimeCut); + const bool actFT0C = !useFT0C || (ft0ActiveC && isTimingActivity(collision.timeFT0C(), upcCuts.ft0cTimeCut)); + + if (selGapSide == o2::aod::sgselector::SingleGapA) { + if (!(gapFV0A && gapFDDA && gapFT0A && actFDDC && actFT0C)) { + selGapSide = o2::aod::sgselector::NoGap; + } + } else if (selGapSide == o2::aod::sgselector::SingleGapC) { + if (!(actFV0A && actFDDA && actFT0A && gapFDDC && gapFT0C)) { + selGapSide = o2::aod::sgselector::NoGap; + } + } else if (selGapSide == o2::aod::sgselector::DoubleGap) { + if (!(gapFV0A && gapFDDA && gapFT0A && gapFDDC && gapFT0C)) { + selGapSide = o2::aod::sgselector::NoGap; + } + } + + return selGapSide; + } + + template + int getGapSide(TCollision const& collision) + { + int selGapSide = o2::aod::sgselector::NoGap; + selGapSide = sgSelector.trueGap(collision, upcCuts.fv0a, upcCuts.ft0a, upcCuts.ft0c, upcCuts.zdc); + selGapSide = applyZDCTiming(selGapSide, collision); + return applyFITTiming(selGapSide, collision); + } + float sanitizeZdcTime(float time) const + { + if (!std::isfinite(time)) { + return -12.f; + } + if (std::abs(time) >= 998.f) { + return -11.f; + } + return time; + } + + float sanitizeFITTime(float time) const + { + if (!std::isfinite(time)) { + return -42.f; + } + if (std::abs(time) >= 998.f) { + return -41.f; + } + return time; + } + + template + void fillPreSelTimingHistograms(TCollision const& collision) + { + histos.fill(HIST("eventQA/hFT0TimePreSel"), sanitizeFITTime(collision.timeFT0A()), sanitizeFITTime(collision.timeFT0C())); + histos.fill(HIST("eventQA/hFDDTimePreSel"), sanitizeFITTime(collision.timeFDDA()), sanitizeFITTime(collision.timeFDDC())); + histos.fill(HIST("eventQA/hZNTimePreSel"), sanitizeZdcTime(collision.timeZNA()), sanitizeZdcTime(collision.timeZNC())); + histos.fill(HIST("eventQA/hTimeFT0APreSel"), sanitizeFITTime(collision.timeFT0A())); + histos.fill(HIST("eventQA/hTimeFT0CPreSel"), sanitizeFITTime(collision.timeFT0C())); + histos.fill(HIST("eventQA/hTimeFV0APreSel"), sanitizeFITTime(collision.timeFV0A())); + histos.fill(HIST("eventQA/hTimeFDDAPreSel"), sanitizeFITTime(collision.timeFDDA())); + histos.fill(HIST("eventQA/hTimeFDDCPreSel"), sanitizeFITTime(collision.timeFDDC())); + } + template void fillHistogramsQA(TCollision const& collision, int const& gap) { @@ -1091,14 +1269,26 @@ struct Derivedupcanalysis { auto znc = collision.energyCommonZNC(); constexpr float inf_f = std::numeric_limits::infinity(); - if (zna == -inf_f) + if (zna == -inf_f) { histos.fill(HIST("eventQA/hZN"), -1, znc, gap); - else if (znc == -inf_f) + } else if (znc == -inf_f) { histos.fill(HIST("eventQA/hZN"), zna, -1, gap); - else if (zna == -999 && znc == -999) + } else if (zna == -999 && znc == -999) { histos.fill(HIST("eventQA/hZN"), -2, -2, gap); - else if (zna == -999 || znc == -999) + } else if (zna == -999 || znc == -999) { LOG(warning) << "Only one ZDC signal is -999"; + } else { + histos.fill(HIST("eventQA/hZN"), zna, znc, gap); + } + + histos.fill(HIST("eventQA/hFT0Time"), sanitizeFITTime(collision.timeFT0A()), sanitizeFITTime(collision.timeFT0C()), gap); + histos.fill(HIST("eventQA/hFDDTime"), sanitizeFITTime(collision.timeFDDA()), sanitizeFITTime(collision.timeFDDC()), gap); + histos.fill(HIST("eventQA/hZNTime"), sanitizeZdcTime(collision.timeZNA()), sanitizeZdcTime(collision.timeZNC()), gap); + histos.fill(HIST("eventQA/hTimeFT0A"), sanitizeFITTime(collision.timeFT0A()), gap); + histos.fill(HIST("eventQA/hTimeFT0C"), sanitizeFITTime(collision.timeFT0C()), gap); + histos.fill(HIST("eventQA/hTimeFV0A"), sanitizeFITTime(collision.timeFV0A()), gap); + histos.fill(HIST("eventQA/hTimeFDDA"), sanitizeFITTime(collision.timeFDDA()), gap); + histos.fill(HIST("eventQA/hTimeFDDC"), sanitizeFITTime(collision.timeFDDC()), gap); } template @@ -1868,13 +2058,13 @@ struct Derivedupcanalysis { } } - if (evSels.studyUPConly && (selGapSide != static_cast(upcCuts.genGapSide))) - continue; - - ++nCollisions; - atLeastOne = true; + const bool passStd = !evSels.studyUPConly || (selGapSide == static_cast(upcCuts.genGapSide)); + if (passStd) { + ++nCollisions; + atLeastOne = true; + } - if (biggestNContribs < collision.multPVTotalContributors()) { + if (passStd && biggestNContribs < collision.multPVTotalContributors()) { biggestNContribs = collision.multPVTotalContributors(); if (static_cast(upcCuts.genGapSide) == 0) { ft0ampl = collision.totalFT0AmplitudeC(); @@ -1946,6 +2136,9 @@ struct Derivedupcanalysis { continue; } // event is accepted + if (collision.isUPC()) { + fillPreSelTimingHistograms(collision); + } histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide()); int selGapSide = collision.isUPC() ? getGapSide(collision) : -1; @@ -2002,6 +2195,9 @@ struct Derivedupcanalysis { continue; } // event is accepted + if (collision.isUPC()) { + fillPreSelTimingHistograms(collision); + } histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide()); int selGapSide = collision.isUPC() ? getGapSide(collision) : -1; @@ -2087,6 +2283,9 @@ struct Derivedupcanalysis { continue; } // event is accepted + if (collision.isUPC()) { + fillPreSelTimingHistograms(collision); + } histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide()); int selGapSide = collision.isUPC() ? getGapSide(collision) : -1; @@ -2139,6 +2338,9 @@ struct Derivedupcanalysis { continue; } // event is accepted + if (collision.isUPC()) { + fillPreSelTimingHistograms(collision); + } histos.fill(HIST("eventQA/hRawGapSide"), collision.gapSide()); int selGapSide = collision.isUPC() ? getGapSide(collision) : -1; diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index ed61b5d07bd..0c0c04f1448 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -41,6 +41,7 @@ #include +#include #include #include @@ -67,26 +68,32 @@ struct HStrangeCorrelation { Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; + struct : ConfigurableGroup { + std::string prefix = "masterConfigurations"; + Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; + Configurable collisionHasTriggOrAssoc{"collisionHasTriggOrAssoc", 0, "require the collisions containing (0:no requirement 1:trig 2:assoc 3:trig or assoc 4:trig and assoc"}; + Configurable doFullCorrelationStudy{"doFullCorrelationStudy", true, "if true, do full correlation study by creating all THnSparse histograms for the correlation function"}; + Configurable doCorrelationHadron{"doCorrelationHadron", false, "do Hadron correlation"}; + Configurable doCorrelationK0Short{"doCorrelationK0Short", true, "do K0Short correlation"}; + Configurable doCorrelationLambda{"doCorrelationLambda", false, "do Lambda correlation"}; + Configurable doCorrelationAntiLambda{"doCorrelationAntiLambda", false, "do AntiLambda correlation"}; + Configurable doCorrelationXiMinus{"doCorrelationXiMinus", false, "do XiMinus correlation"}; + Configurable doCorrelationXiPlus{"doCorrelationXiPlus", false, "do XiMinus correlation"}; + 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 requireAllGoodITSLayers{"requireAllGoodITSLayers", false, " require that in the event all ITS are good"}; + 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 applyNewMCSelection{"applyNewMCSelection", false, "apply new MC Generated selection"}; + } masterConfigurations; + // master analysis switches - Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; - Configurable doFullCorrelationStudy{"doFullCorrelationStudy", true, "if true, do full correlation study by creating all THnSparse histograms for the correlation function"}; - Configurable doCorrelationHadron{"doCorrelationHadron", false, "do Hadron correlation"}; - Configurable doCorrelationK0Short{"doCorrelationK0Short", true, "do K0Short correlation"}; - Configurable doCorrelationLambda{"doCorrelationLambda", false, "do Lambda correlation"}; - Configurable doCorrelationAntiLambda{"doCorrelationAntiLambda", false, "do AntiLambda correlation"}; - Configurable doCorrelationXiMinus{"doCorrelationXiMinus", false, "do XiMinus correlation"}; - Configurable doCorrelationXiPlus{"doCorrelationXiPlus", false, "do XiPlus correlation"}; - 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 requireAllGoodITSLayers{"requireAllGoodITSLayers", false, " require that in the event all ITS are good"}; - 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 doAssocPhysicalPrimaryInGen{"doAssocPhysicalPrimaryInGen", false, "require physical primary for associated particles in Generated Partilces"}; Configurable doLambdaPrimary{"doLambdaPrimary", false, "do primary selection for lambda"}; @@ -100,12 +107,14 @@ struct HStrangeCorrelation { Configurable etaSel{"etaSel", 0.8, "Selection in eta for trigger and associated particles"}; Configurable ySel{"ySel", 0.5, "Selection in rapidity for consistency checks"}; + Configurable useTheLeadingParticleAsTrigger{"useTheLeadingParticleAsTrigger", false, "if true, use the leading particle in the event as trigger particle"}; // used for event selections in Pb-Pb Configurable cfgCutOccupancyHigh{"cfgCutOccupancyHigh", 3000, "High cut on TPC occupancy"}; Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low cut on TPC occupancy"}; // Axes - configurable for smaller sizes struct : ConfigurableGroup { + std::string prefix = "axesConfigurations"; 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"}; ConfigurableAxis axisPhi{"axisPhi", {72, 0, TwoPI}, "#phi"}; @@ -121,6 +130,7 @@ struct HStrangeCorrelation { // for topo var QA struct : ConfigurableGroup { + std::string prefix = "massWindowConfigurations"; 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)"}; @@ -129,20 +139,21 @@ struct HStrangeCorrelation { // Implementation of on-the-spot efficiency correction struct : ConfigurableGroup { + std::string prefix = "efficiencyFlags"; Configurable applyEfficiencyCorrection{"applyEfficiencyCorrection", false, "apply efficiency correction"}; Configurable applyEfficiencyForTrigger{"applyEfficiencyForTrigger", false, "apply efficiency correction for the trigger particle"}; Configurable applyEfficiencyPropagation{"applyEfficiencyPropagation", false, "propagate also the efficiency uncertainty"}; Configurable applyPurityHadron{"applyPurityHadron", false, "apply the purity correction for associated hadrons"}; Configurable applyPurityTrigger{"applyPurityTrigger", false, "apply the purity correction for trigger particle"}; Configurable applyEffAsFunctionOfMult{"applyEffAsFunctionOfMult", false, "apply efficiency as a function of multiplicity as well"}; + Configurable applyEffAsFunctionOfMultAndPhi{"applyEffAsFunctionOfMultAndPhi", false, "apply efficiency as a function of multiplicity and phi"}; } efficiencyFlags; Configurable ccdburl{"ccdburl", "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"; + std::string prefix = "trackSelection"; // --- 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)"}; @@ -152,16 +163,22 @@ struct HStrangeCorrelation { Configurable assocMaxTPCSharedClusters{"assocMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive) for assoc primary tracks"}; Configurable triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"}; Configurable assocRequireL0{"assocRequireL0", true, "require ITS L0 cluster for assoc primary track"}; - // Track quality in PbPb - Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; + Configurable minTPCChi2PerClusterAssociated{"minTPCChi2PerClusterAssociated", 4.0f, "Minimum TPC chi2 per cluster for associated primary tracks"}; + Configurable checksRequireTPCChi2{"checksRequireTPCChi2", false, "require TPC chi2 per cluster for trigger and associated primary tracks"}; + Configurable requireClusterInITS{"requireClusterInITS", false, "require cluster in ITS for V0 and cascade daughter tracks"}; + Configurable minITSClustersForDaughterTracks{"minITSClustersForDaughterTracks", 1, "Minimum number of ITS clusters for V0 daughter tracks"}; // --- 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"}; - + // --- Assoc track: DCA variation from basic formula: |DCAxy| < 0.004f + (0.013f / pt) Configurable dcaXYconstantAssoc{"dcaXYconstantAssoc", 0.004, "[0] in |DCAxy| < [0]+[1]/pT"}; Configurable dcaXYpTdepAssoc{"dcaXYpTdepAssoc", 0.013, "[1] in |DCAxy| < [0]+[1]/pT"}; - + Configurable dEdxCompatibility{"dEdxCompatibility", 1, "0: loose, 1: normal, 2: tight. Defined in HStrangeCorrelationFilter"}; + } trackSelection; + struct : ConfigurableGroup { + std::string prefix = "v0Selection"; + // --- V0 selections (both K0Short and Lambda, but some can be Lambda specific, see below) // --- 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"}; @@ -169,63 +186,107 @@ struct HStrangeCorrelation { Configurable dcapostopv{"dcapostopv", 0.06, "DCA Pos To PV"}; Configurable v0RadiusMin{"v0RadiusMin", 0.5, "v0radius"}; Configurable v0RadiusMax{"v0RadiusMax", 200, "v0radius"}; - // more V0 selections in PbPb + Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.2, "DCA of baryon daughter track To PV"}; + Configurable dcaMesonToPV{"dcaMesonToPV", 0.05, "DCA of meson daughter track To PV"}; Configurable lifetimecutK0S{"lifetimecutK0S", 20, "lifetimecutK0S"}; Configurable lifetimecutLambda{"lifetimecutLambda", 30, "lifetimecutLambda"}; - Configurable dcanegtopvK0S{"dcanegtopvK0S", 0.1, "DCA Neg To PV"}; - Configurable dcapostopvK0S{"dcapostopvK0S", 0.1, "DCA Pos To PV"}; - Configurable dcanegtopvLambda{"dcanegtopvLambda", 0.05, "DCA Neg To PV"}; - Configurable dcapostopvLambda{"dcapostopvLambda", 0.2, "DCA Pos To PV"}; - Configurable dcanegtopvAntiLambda{"dcanegtopvAntiLambda", 0.2, "DCA Neg To PV"}; - Configurable dcapostopvAntiLambda{"dcapostopvAntiLambda", 0.05, "DCA Pos To PV"}; // original equation: lArmPt*2>TMath::Abs(lArmAlpha) only for K0S Configurable armPodCut{"armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; + } v0Selection; - // cascade selections + struct : ConfigurableGroup { + std::string prefix = "cascadeSelections"; Configurable cascCospa{"cascCospa", 0.95, "cascCospa"}; - Configurable cascDcacascdau{"cascDcacascdau", 1.0, "cascDcacascdau"}; - Configurable cascDcabachtopv{"cascDcabachtopv", 0.1, "cascDcabachtopv"}; + Configurable dcaCascDaughters{"dcaCascDaughters", 1.0, "DCA between the V0 candidate and the bachelor track"}; + // Configurable cascDcabachtopv{"cascDcabachtopv", 0.1, "cascDcabachtopv"}; Configurable cascRadius{"cascRadius", 0.5, "cascRadius"}; Configurable cascV0masswindow{"cascV0masswindow", 0.01, "cascV0masswindow"}; - Configurable cascMindcav0topv{"cascMindcav0topv", 0.01, "cascMindcav0topv"}; - // more cascade selections in PbPb Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; - Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.05, "DCA of baryon doughter track To PV"}; - Configurable dcaMesonToPV{"dcaMesonToPV", 0.1, "DCA of meson doughter track To PV"}; - Configurable dcaBachToPV{"dcaBachToPV", 0.07, "DCA Bach To PV"}; Configurable cascdcaV0dau{"cascdcaV0dau", 0.5, "DCA V0 Daughters"}; + Configurable proplifetime{"proplifetime", 3, "ctau/"}; + Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; + Configurable rapCut{"rapCut", 0.8, "Rapidity acceptance"}; Configurable dcaCacsDauPar0{"dcaCacsDauPar0", 0.8, " par for pt dep DCA cascade daughter cut, p_T < 1 GeV/c"}; Configurable dcaCacsDauPar1{"dcaCacsDauPar1", 0.5, " par for pt dep DCA cascade daughter cut, 1< p_T < 4 GeV/c"}; Configurable dcaCacsDauPar2{"dcaCacsDauPar2", 0.2, " par for pt dep DCA cascade daughter cut, p_T > 4 GeV/c"}; Configurable cascdcaV0ToPV{"cascdcaV0ToPV", 0.06, "DCA V0 To PV"}; Configurable cascv0cospa{"cascv0cospa", 0.98, "V0 CosPA"}; Configurable cascv0RadiusMin{"cascv0RadiusMin", 2.5, "v0radius"}; - Configurable proplifetime{"proplifetime", 3, "ctau/"}; - Configurable lambdaMassWin{"lambdaMassWin", 0.005, "V0 Mass window limit"}; - Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; - Configurable rapCut{"rapCut", 0.8, "Rapidity acceptance"}; + Configurable dcaBaryonToPV{"dcaBaryonToPV", 0.05, "DCA of baryon doughter track To PV"}; + Configurable dcaMesonToPV{"dcaMesonToPV", 0.1, "DCA of meson doughter track To PV"}; + Configurable dcaBachToPV{"dcaBachToPV", 0.07, "DCA Bach To PV"}; + // pt Range for pt dep cuts + Configurable highPtForCascDaugPtDep{"highPtForCascDaugPtDep", 4.0, "high pt range for pt dep cuts"}; + Configurable lowPtForCascDaugPtDep{"lowPtForCascDaugPtDep", 1.0, "low pt range for pt dep cuts"}; - // dE/dx for associated daughters - Configurable dEdxCompatibility{"dEdxCompatibility", 1, "0: loose, 1: normal, 2: tight. Defined in HStrangeCorrelationFilter"}; + } cascadeSelections; + struct : ConfigurableGroup { + std::string prefix = "`"; + // cascade selections + // more cascade selections in PbPb + // Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; + // Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.08, "DCA bachelor baryon to PV"}; + // // on the fly correction instead of mixingParameter Configurable doOnTheFlyFlattening{"doOnTheFlyFlattening", 0, "enable an on-the-fly correction instead of using mixing"}; + // delta eta ranges for toward and transverse checks + Configurable transwerseDeltaEtaRangeMin{"transwerseDeltaEtaRangeMin", 1.0, "minimum delta eta for transverse region"}; + Configurable transwerseDeltaEtaRangeMax{"transwerseDeltaEtaRangeMax", 2.0, "maximum delta eta for transverse region"}; + Configurable towardDeltaEtaRange{"towardDeltaEtaRange", 0.8, "delta eta range for toward region"}; // (N.B.: sources that can be investigated in post are not listed!) - } systCuts; + } checks; + + struct ValidCollision { + struct ValidParticle { + float eta; + float phi; + float pt; + int region; + float efficiency; + float efficiencyError; + int type; + }; + float pvz; + float mult; + std::vector trigParticles; + std::vector assocParticles; + void addValidParticle(float eta, float phi, float pt, int region, float efficiency, float efficiencyError, int type) + { + ValidParticle particle{eta, phi, pt, region, efficiency, efficiencyError, type}; + + if (type == -1) { + trigParticles.push_back(particle); + } else { + assocParticles.push_back(particle); + } + } + }; + + using ValidCollisions = std::vector>; + ValidCollisions validCollisions; // objects to use for efficiency corrections TH2F* hEfficiencyTrigger; TH3F* hEfficiencyTriggerMult; + THnF* hEfficiencyTriggerMultVsPhi; TH2F* hEfficiencyPion; TH2F* hEfficiencyK0Short; + THnF* hEfficiencyK0ShortMultVsPhi; TH2F* hEfficiencyLambda; + THnF* hEfficiencyLambdaMultVsPhi; TH2F* hEfficiencyAntiLambda; + THnF* hEfficiencyAntiLambdaMultVsPhi; TH2F* hEfficiencyXiMinus; + THnF* hEfficiencyXiMinusMultVsPhi; TH2F* hEfficiencyXiPlus; + THnF* hEfficiencyXiPlusMultVsPhi; TH2F* hEfficiencyOmegaMinus; + THnF* hEfficiencyOmegaMinusMultVsPhi; TH2F* hEfficiencyOmegaPlus; + THnF* hEfficiencyOmegaPlusMultVsPhi; TH2F* hEfficiencyHadron; TH3F* hEfficiencyHadronMult; TH1F* hPurityHadron; @@ -257,10 +318,19 @@ struct HStrangeCorrelation { Preslice collisionSliceHadrons = aod::assocHadrons::collisionId; Preslice perCollision = aod::mcparticle::mcCollisionId; - static constexpr std::string_view kV0names[] = {"K0Short", "Lambda", "AntiLambda"}; - static constexpr std::string_view kCascadenames[] = {"XiMinus", "XiPlus", "OmegaMinus", "OmegaPlus"}; - static constexpr std::string_view kParticlenames[] = {"K0Short", "Lambda", "AntiLambda", "XiMinus", "XiPlus", "OmegaMinus", "OmegaPlus", "Pion", "Hadron"}; - static constexpr int kPdgCodes[] = {310, 3122, -3122, 3312, -3312, 3334, -3334, 211}; + 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[] = {"K0Short", "Lambda", "AntiLambda", "XiMinus", "XiPlus", "OmegaMinus", "OmegaPlus", "Pion", "Hadron"}; + static constexpr int PdgCodes[] = {310, 3122, -3122, 3312, -3312, 3334, -3334, 211}; + + static constexpr int IndexPion = 7; + static constexpr int IndexXiMinus = 0; + static constexpr int IndexXiPlus = 1; + static constexpr int IndexOmegaMinus = 2; + static constexpr int IndexOmegaPlus = 3; + static constexpr int IndexK0 = 0; + static constexpr int IndexLambda = 1; + static constexpr int IndexAntiLambda = 2; uint16_t doCorrelation; int mRunNumber; @@ -268,8 +338,16 @@ struct HStrangeCorrelation { std::vector> axisRanges; - const float ctauxiPDG = 4.91; // from PDG - const float ctauomegaPDG = 2.461; // from PDG + const float ctauxi = 4.91; // from PDG + const float ctauomega = 2.461; // from PDG + + static constexpr float MinRadiusTPC = 0.8; + static constexpr float MaxRadiusTPC = 2.5; + + static constexpr float Neutral = 0.0; + + static constexpr int AssocParticleTypes = 9; // K0S, Lambda, AntiLambda, Xi-, Xi+, Omega-, Omega+, Pion, Hadron + static constexpr int AssocParticleTypesNoHadron = 8; // K0S, Lambda, AntiLambda, Xi-, Xi+, Omega-, Omega+, Pion /// Function to aid in calculating delta-phi /// \param phi1 first phi value @@ -314,13 +392,21 @@ struct HStrangeCorrelation { hEfficiencyTrigger = static_cast(listEfficiencies->FindObject("hEfficiencyTrigger")); hEfficiencyTriggerMult = static_cast(listEfficiencies->FindObject("hEfficiencyTriggerMult")); + hEfficiencyTriggerMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyTriggerMultVsPhi")); hEfficiencyK0Short = static_cast(listEfficiencies->FindObject("hEfficiencyK0Short")); + hEfficiencyK0ShortMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyK0ShortMultVsPhi")); hEfficiencyLambda = static_cast(listEfficiencies->FindObject("hEfficiencyLambda")); + hEfficiencyLambdaMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyLambdaMultVsPhi")); hEfficiencyAntiLambda = static_cast(listEfficiencies->FindObject("hEfficiencyAntiLambda")); + hEfficiencyAntiLambdaMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyAntiLambdaMultVsPhi")); hEfficiencyXiMinus = static_cast(listEfficiencies->FindObject("hEfficiencyXiMinus")); + hEfficiencyXiMinusMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyXiMinusMultVsPhi")); hEfficiencyXiPlus = static_cast(listEfficiencies->FindObject("hEfficiencyXiPlus")); + hEfficiencyXiPlusMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyXiPlusMultVsPhi")); hEfficiencyOmegaMinus = static_cast(listEfficiencies->FindObject("hEfficiencyOmegaMinus")); + hEfficiencyOmegaMinusMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyOmegaMinusMultVsPhi")); hEfficiencyOmegaPlus = static_cast(listEfficiencies->FindObject("hEfficiencyOmegaPlus")); + hEfficiencyOmegaPlusMultVsPhi = static_cast(listEfficiencies->FindObject("hEfficiencyOmegaPlusMultVsPhi")); hEfficiencyHadron = static_cast(listEfficiencies->FindObject("hEfficiencyHadron")); hEfficiencyHadronMult = static_cast(listEfficiencies->FindObject("hEfficiencyHadronMult")); hEfficiencyPion = static_cast(listEfficiencies->FindObject("hEfficiencyPion")); @@ -340,132 +426,135 @@ struct HStrangeCorrelation { hEfficiencyUncertaintyHadronMult = static_cast(listEfficiencies->FindObject("hEfficiencyUncertaintyHadronMult")); hPurityUncertaintyHadron = static_cast(listEfficiencies->FindObject("hPurityUncertaintyHadron")); hPurityUncertaintyHadronMult = static_cast(listEfficiencies->FindObject("hPurityUncertaintyHadronMult")); - if (efficiencyFlags.applyEfficiencyPropagation && !hEfficiencyUncertaintyTrigger) + if (efficiencyFlags.applyEfficiencyPropagation && !efficiencyFlags.applyEffAsFunctionOfMultAndPhi && !hEfficiencyUncertaintyTrigger) LOG(fatal) << "Problem getting hEfficiencyUncertaintyTrigger!"; + if (efficiencyFlags.applyEffAsFunctionOfMult && !hEfficiencyTriggerMult) + LOG(fatal) << "Problem getting hEfficiencyTriggerMult!"; LOG(info) << "Efficiencies now loaded for " << mRunNumber; } template - uint64_t V0selectionBitmap(TV0 v0, float pvx, float pvy, float pvz) + uint64_t v0selectionBitmap(TV0 v0, float pvx, float pvy, float pvz) // precalculate this information so that a check is one mask operation, not many { uint64_t bitMap = 0; // proper lifetime , DCA daughter to prim.vtx - if (doCorrelationK0Short) { + if (masterConfigurations.doCorrelationK0Short) { // proper lifetime - if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassK0Short < systCuts.lifetimecutK0S) + if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassK0Short < v0Selection.lifetimecutK0S) SETBIT(bitMap, 0); // DCA daughter to prim.vtx and armenteros - if (std::abs(v0.dcapostopv()) > systCuts.dcapostopvK0S && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvK0S && v0.qtarm() * systCuts.armPodCut > std::abs(v0.alpha())) + if (std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV && v0.qtarm() * v0Selection.armPodCut > std::abs(v0.alpha())) SETBIT(bitMap, 3); } - if (doCorrelationLambda) { + if (masterConfigurations.doCorrelationLambda) { // proper lifetime - if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < systCuts.lifetimecutLambda) + if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda) SETBIT(bitMap, 1); // DCA daughter to prim.vtx - if (std::abs(v0.dcapostopv()) > systCuts.dcapostopvLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvLambda) + if (std::abs(v0.dcapostopv()) > v0Selection.dcaBaryonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaMesonToPV) SETBIT(bitMap, 4); } - if (doCorrelationAntiLambda) { + if (masterConfigurations.doCorrelationAntiLambda) { // proper lifetime - if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < systCuts.lifetimecutLambda) + if (v0.distovertotmom(pvx, pvy, pvz) * o2::constants::physics::MassLambda0 < v0Selection.lifetimecutLambda) SETBIT(bitMap, 2); // DCA daughter to prim.vtx - if (std::abs(v0.dcapostopv()) > systCuts.dcapostopvAntiLambda && std::abs(v0.dcanegtopv()) > systCuts.dcanegtopvAntiLambda) + if (std::abs(v0.dcapostopv()) > v0Selection.dcaMesonToPV && std::abs(v0.dcanegtopv()) > v0Selection.dcaBaryonToPV) SETBIT(bitMap, 5); } return bitMap; } template - uint64_t CascadeselectionBitmap(TCascade casc, float pvx, float pvy, float pvz) + uint64_t cascadeselectionBitmap(TCascade casc, float pvx, float pvy, float pvz) { uint64_t bitMap = 0; float cascpos = std::hypot(casc.x() - pvx, casc.y() - pvy, casc.z() - pvz); float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxiPDG); - float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomegaPDG); + float ctauXi = o2::constants::physics::MassXiMinus * cascpos / ((cascptotmom + 1e-13) * ctauxi); + float ctauOmega = o2::constants::physics::MassOmegaMinus * cascpos / ((cascptotmom + 1e-13) * ctauomega); + + bool isGoodDCANegCasc = std::abs(casc.dcabachtopv()) > cascadeSelections.dcaBachToPV && std::abs(casc.dcapostopv()) > cascadeSelections.dcaBaryonToPV && + std::abs(casc.dcanegtopv()) > cascadeSelections.dcaMesonToPV; + bool isGoodDCAPosCasc = std::abs(casc.dcabachtopv()) > cascadeSelections.dcaBachToPV && std::abs(casc.dcapostopv()) > cascadeSelections.dcaMesonToPV && + std::abs(casc.dcanegtopv()) > cascadeSelections.dcaBaryonToPV; // TPC PID and DCA daughter to prim.vtx and comopeting casc.rej and life time - if (doCorrelationXiMinus) { + if (masterConfigurations.doCorrelationXiMinus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaMesonToPV) + if (isGoodDCANegCasc) SETBIT(bitMap, 0); // comopeting casc.rej - if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > systCuts.rejcomp) + if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 4); - if (ctauXi < systCuts.proplifetime) + if (ctauXi < cascadeSelections.proplifetime) SETBIT(bitMap, 8); // y cut - if (std::abs(casc.yXi()) < systCuts.rapCut) + if (std::abs(casc.yXi()) < cascadeSelections.rapCut) SETBIT(bitMap, 12); } - if (doCorrelationXiPlus) { + if (masterConfigurations.doCorrelationXiPlus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaBaryonToPV) + if (isGoodDCAPosCasc) SETBIT(bitMap, 1); // comopeting casc.rej - if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > systCuts.rejcomp) + if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 5); // life time - if (ctauXi < systCuts.proplifetime) + if (ctauXi < cascadeSelections.proplifetime) SETBIT(bitMap, 9); // y cut - if (std::abs(casc.yXi()) > systCuts.rapCut) + if (std::abs(casc.yXi()) > cascadeSelections.rapCut) SETBIT(bitMap, 13); } - if (doCorrelationOmegaMinus) { + if (masterConfigurations.doCorrelationOmegaMinus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaBaryonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaMesonToPV) + if (isGoodDCANegCasc) SETBIT(bitMap, 2); // comopeting casc.rej - if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > systCuts.rejcomp) + if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 6); // life time - if (ctauOmega < systCuts.proplifetime) + if (ctauOmega < cascadeSelections.proplifetime) SETBIT(bitMap, 10); // y cut - if (std::abs(casc.yOmega()) < systCuts.rapCut) + if (std::abs(casc.yOmega()) < cascadeSelections.rapCut) SETBIT(bitMap, 14); } - if (doCorrelationOmegaPlus) { + if (masterConfigurations.doCorrelationOmegaPlus) { // DCA daughter to prim.vtx - if (std::abs(casc.dcabachtopv()) > systCuts.dcaBachToPV && std::abs(casc.dcapostopv()) > systCuts.dcaMesonToPV && - std::abs(casc.dcanegtopv()) > systCuts.dcaBaryonToPV) + if (isGoodDCAPosCasc) SETBIT(bitMap, 3); // comopeting casc.rej - if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > systCuts.rejcomp) + if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > cascadeSelections.rejcomp) SETBIT(bitMap, 7); // life time - if (ctauOmega < systCuts.proplifetime) + if (ctauOmega < cascadeSelections.proplifetime) SETBIT(bitMap, 11); // y cut - if (std::abs(casc.yOmega()) > systCuts.rapCut) + if (std::abs(casc.yOmega()) > cascadeSelections.rapCut) SETBIT(bitMap, 15); } return bitMap; } template - bool isValidTrigger(TTrack track) + bool isValidTrigger(TTrack track, bool isLeading) { - if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsTrigger) { + if (track.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsTrigger) { return false; // crossed rows } - if (!track.hasITS() && systCuts.triggerRequireITS) { + if (!track.hasITS() && trackSelection.triggerRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } - if (track.tpcNClsShared() > systCuts.triggerMaxTPCSharedClusters) { + if (track.tpcNClsShared() > trackSelection.triggerMaxTPCSharedClusters) { return false; // skip, has shared clusters } - if (!(TESTBIT(track.itsClusterMap(), 0)) && systCuts.triggerRequireL0) { + if (!(TESTBIT(track.itsClusterMap(), 0)) && trackSelection.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())) { + if (std::abs(track.dcaXY()) > trackSelection.dcaXYconstant + trackSelection.dcaXYpTdep * std::abs(track.signed1Pt())) { return false; } if (track.pt() > axisRanges[3][1] || track.pt() < axisRanges[3][0]) { @@ -477,25 +566,28 @@ struct HStrangeCorrelation { if (triggerParticleCharge < 0 && track.sign() > 0) { return false; } + if (useTheLeadingParticleAsTrigger && !isLeading) { + return false; + } return true; } template bool isValidAssocHadron(TTrack track) { - if (track.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) { + if (track.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) { return false; // crossed rows } - if (!track.hasITS() && systCuts.assocRequireITS) { + if (!track.hasITS() && trackSelection.assocRequireITS) { return false; // skip, doesn't have ITS signal (skips lots of TPC-only!) } - if (track.tpcNClsShared() > systCuts.assocMaxTPCSharedClusters) { + if (track.tpcNClsShared() > trackSelection.assocMaxTPCSharedClusters) { return false; // skip, has shared clusters } - if (!(TESTBIT(track.itsClusterMap(), 0)) && systCuts.assocRequireL0) { + if (!(TESTBIT(track.itsClusterMap(), 0)) && trackSelection.assocRequireL0) { return false; // skip, doesn't have cluster in ITS L0 } // systematic variations: trigger DCAxy - if (std::abs(track.dcaXY()) > systCuts.dcaXYconstantAssoc + systCuts.dcaXYpTdepAssoc * std::abs(track.signed1Pt())) { + if (std::abs(track.dcaXY()) > trackSelection.dcaXYconstantAssoc + trackSelection.dcaXYpTdepAssoc * std::abs(track.signed1Pt())) { return false; } if (track.pt() > axisRanges[2][1] || track.pt() < axisRanges[2][0]) { @@ -505,60 +597,60 @@ struct HStrangeCorrelation { } // V0selection in PbPb template - bool V0SelectedPbPb(TV0 v0) + bool v0SelectedPbPb(TV0 v0) { // v0radius - if (v0.v0radius() < systCuts.v0RadiusMin) + if (v0.v0radius() < v0Selection.v0RadiusMin) return false; - if (v0.v0radius() > systCuts.v0RadiusMax) + if (v0.v0radius() > v0Selection.v0RadiusMax) return false; // v0cosPA - if (v0.v0cosPA() < systCuts.v0cospa) + if (v0.v0cosPA() < v0Selection.v0cospa) return false; // dcaV0daughters - if (v0.dcaV0daughters() > systCuts.dcaV0dau) + if (v0.dcaV0daughters() > v0Selection.dcaV0dau) return false; return true; } // cascadeselection in PbPb template - bool CascadeSelectedPbPb(TCascade casc, float pvx, float pvy, float pvz) + bool cascadeSelectedPbPb(TCascade casc, float pvx, float pvy, float pvz) { // bachBaryonCosPA - if (casc.bachBaryonCosPA() < systCuts.bachBaryonCosPA) + if (casc.bachBaryonCosPA() < cascadeSelections.bachBaryonCosPA) return false; // bachBaryonDCAxyToPV - if (std::abs(casc.bachBaryonDCAxyToPV()) > systCuts.bachBaryonDCAxyToPV) + if (std::abs(casc.bachBaryonDCAxyToPV()) > cascadeSelections.bachBaryonDCAxyToPV) return false; // casccosPA - if (casc.casccosPA(pvx, pvy, pvz) < systCuts.cascCospa) + if (casc.casccosPA(pvx, pvy, pvz) < cascadeSelections.cascCospa) return false; // dcacascdaughters - float ptDepCut = systCuts.dcaCacsDauPar0; - if (casc.pt() > 1 && casc.pt() < 4) - ptDepCut = systCuts.dcaCacsDauPar1; - else if (casc.pt() > 4) - ptDepCut = systCuts.dcaCacsDauPar2; + float ptDepCut = cascadeSelections.dcaCacsDauPar0; + if (casc.pt() > cascadeSelections.lowPtForCascDaugPtDep && casc.pt() < cascadeSelections.highPtForCascDaugPtDep) + ptDepCut = cascadeSelections.dcaCacsDauPar1; + else if (casc.pt() > cascadeSelections.highPtForCascDaugPtDep) + ptDepCut = cascadeSelections.dcaCacsDauPar2; if (casc.dcacascdaughters() > ptDepCut) return false; // dcaV0daughters - if (casc.dcaV0daughters() > systCuts.dcaV0dau) + if (casc.dcaV0daughters() > cascadeSelections.cascdcaV0dau) return false; // dcav0topv - if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < systCuts.cascdcaV0ToPV) + if (std::abs(casc.dcav0topv(pvx, pvy, pvz)) < cascadeSelections.cascdcaV0ToPV) return false; // cascradius - if (casc.cascradius() < systCuts.cascRadius) + if (casc.cascradius() < cascadeSelections.cascRadius) return false; // v0radius - if (casc.v0radius() < systCuts.cascv0RadiusMin) + if (casc.v0radius() < cascadeSelections.cascv0RadiusMin) return false; // v0cosPA - if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < systCuts.cascv0cospa) + if (casc.v0cosPA(casc.x(), casc.y(), casc.z()) < cascadeSelections.cascv0cospa) return false; // lambdaMassWin - if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.lambdaMassWin) + if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascadeSelections.cascV0masswindow) return false; return true; } @@ -571,7 +663,7 @@ struct HStrangeCorrelation { double phaseProton = (-0.3 * B * assoc[2]) / (2 * assoc[1]); double phaseTrack = (-0.3 * B * trigg[2]) / (2 * trigg[1]); - for (double r = 0.8; r <= 2.5; r += 0.05) { + for (double r = MinRadiusTPC; r <= MaxRadiusTPC; r += 0.05) { dPhiStar = dPhi + std::asin(phaseProton * r) - std::asin(phaseTrack * r); dPhiStarMean += (dPhiStar / 34); } @@ -600,20 +692,35 @@ struct HStrangeCorrelation { hist->SetBinContent(bin, currentContent); hist->SetBinError2(bin, currentError2); } - void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) + void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, bool mixingInBf, float pvx, float pvy, float pvz, float mult, double bField) { + ValidCollision currentCollision; + int binMult = 0; + int nBinsMult = 0; + int nBinsVtxZ = 0; + int binVtxZ = 0; + currentCollision.pvz = pvz; + currentCollision.mult = mult; + if (mixingInBf) { + nBinsMult = histos.get(HIST("axes/hMultAxis"))->GetNbinsX(); + binMult = histos.get(HIST("axes/hMultAxis"))->GetXaxis()->FindBin(mult) - 1; + nBinsVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetNbinsX(); + binVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetXaxis()->FindBin(pvz) - 1; + } + bool firstLoop = false; for (auto const& triggerTrack : triggers) { - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; auto trigg = triggerTrack.track_as(); - if (!isValidTrigger(trigg)) + if (!isValidTrigger(trigg, triggerTrack.isLeading())) continue; float efficiencyTrigg = 1.0f; float efficiencyTriggError = 0.0f; float purityTrigg = 1.0f; float purityTriggErr = 0.0; - if (!mixing) { - if (efficiencyFlags.applyEfficiencyForTrigger) { + double bintrig[4] = {trigg.pt(), trigg.eta(), trigg.phi(), mult}; + if (efficiencyFlags.applyEfficiencyForTrigger) { + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { efficiencyTrigg = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); if (efficiencyFlags.applyPurityTrigger) purityTrigg = hPurityHadron->Interpolate(trigg.pt()); @@ -622,47 +729,67 @@ struct HStrangeCorrelation { if (efficiencyFlags.applyPurityTrigger) purityTriggErr = hPurityHadron->Interpolate(trigg.pt()); } - if (efficiencyTrigg == 0) { // check for zero efficiency, do not apply if the case - efficiencyTrigg = 1; - efficiencyTriggError = 0; + } else { + efficiencyTrigg = hEfficiencyTriggerMultVsPhi->GetBinContent(hEfficiencyTriggerMultVsPhi->GetBin(bintrig)); + if (efficiencyFlags.applyEfficiencyPropagation) { + efficiencyTriggError = hEfficiencyTriggerMultVsPhi->GetBinError(hEfficiencyTriggerMultVsPhi->GetBin(bintrig)); } } + if (efficiencyTrigg == 0) { // check for zero efficiency, do not apply if the case + efficiencyTrigg = 1; + efficiencyTriggError = 0; + } + } + if (!mixing) { + fillTriggerHistogram(histos.get(HIST("sameEvent/TriggerParticlesV0")), trigg.pt(), mult, efficiencyTrigg, efficiencyTriggError, purityTrigg, purityTriggErr); } double triggSign = trigg.sign(); double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + if (mixingInBf) { + currentCollision.addValidParticle(trigg.eta(), trigg.phi(), trigg.pt(), -1, efficiencyTrigg, efficiencyTriggError, -1); + if (firstLoop) + continue; + } for (auto const& assocCandidate : assocs) { + firstLoop = true; auto assoc = assocCandidate.v0Core_as(); //---] syst cuts [--- - if ((doPPAnalysis && (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))) + if ((masterConfigurations.doPPAnalysis && (assoc.v0radius() < v0Selection.v0RadiusMin || assoc.v0radius() > v0Selection.v0RadiusMax || + std::abs(assoc.dcapostopv()) < v0Selection.dcapostopv || std::abs(assoc.dcanegtopv()) < v0Selection.dcanegtopv || + assoc.v0cosPA() < v0Selection.v0cospa || assoc.dcaV0daughters() > v0Selection.dcaV0dau))) continue; - if (!doPPAnalysis && !V0SelectedPbPb(assoc)) + if (!masterConfigurations.doPPAnalysis && !v0SelectedPbPb(assoc)) continue; - uint64_t selMap = V0selectionBitmap(assoc, pvx, pvy, pvz); + uint64_t selMap = v0selectionBitmap(assoc, pvx, pvy, pvz); //---] removing autocorrelations [--- auto postrack = assoc.posTrack_as(); auto negtrack = assoc.negTrack_as(); - if (doAutocorrelationRejection) { - if (trigg.globalIndex() == postrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); - continue; - } - if (trigg.globalIndex() == negtrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); - continue; + if (!mixingInBf) { + if (doAutocorrelationRejection) { + if (trigg.globalIndex() == postrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); + continue; + } + if (trigg.globalIndex() == negtrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsV0"), 0.5); + continue; + } } } //---] track quality check [--- - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; float deltaphi = computeDeltaPhi(trigg.phi(), assoc.phi()); @@ -679,17 +806,24 @@ struct HStrangeCorrelation { continue; TH2F* hEfficiencyV0[3]; - hEfficiencyV0[0] = hEfficiencyK0Short; - hEfficiencyV0[1] = hEfficiencyLambda; - hEfficiencyV0[2] = hEfficiencyAntiLambda; - TH2F* hEfficiencyUncertaintyV0[3]; - hEfficiencyUncertaintyV0[0] = hEfficiencyUncertaintyK0Short; - hEfficiencyUncertaintyV0[1] = hEfficiencyUncertaintyLambda; - hEfficiencyUncertaintyV0[2] = hEfficiencyUncertaintyAntiLambda; + THnF* hEfficiencyV0MultVsPhi[3]; + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + hEfficiencyV0MultVsPhi[0] = hEfficiencyK0ShortMultVsPhi; + hEfficiencyV0MultVsPhi[1] = hEfficiencyLambdaMultVsPhi; + hEfficiencyV0MultVsPhi[2] = hEfficiencyAntiLambdaMultVsPhi; + } else { + hEfficiencyV0[0] = hEfficiencyK0Short; + hEfficiencyV0[1] = hEfficiencyLambda; + hEfficiencyV0[2] = hEfficiencyAntiLambda; + + hEfficiencyUncertaintyV0[0] = hEfficiencyUncertaintyK0Short; + hEfficiencyUncertaintyV0[1] = hEfficiencyUncertaintyLambda; + hEfficiencyUncertaintyV0[2] = hEfficiencyUncertaintyAntiLambda; + } float etaWeight = 1; - if (systCuts.doOnTheFlyFlattening) { + if (checks.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } @@ -701,7 +835,7 @@ struct HStrangeCorrelation { double ptProton = postrack.pt(); double ptPion = negtrack.pt(); double signProton = postrack.sign(); - if (assocCandidate.compatible(2, systCuts.dEdxCompatibility)) { + if (assocCandidate.compatible(2, trackSelection.dEdxCompatibility)) { phiProton = negtrack.phi(); etaProton = negtrack.eta(); ptProton = negtrack.pt(); @@ -716,9 +850,16 @@ struct HStrangeCorrelation { float totalEffUncert = 0.0; float efficiencyError = 0.0f; if (efficiencyFlags.applyEfficiencyCorrection) { - efficiency = hEfficiencyV0[Index]->Interpolate(ptassoc, assoc.eta()); - if (efficiencyFlags.applyEfficiencyPropagation) - efficiencyError = hEfficiencyUncertaintyV0[Index]->Interpolate(ptassoc, assoc.eta()); + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + double bin[4] = {ptassoc, assoc.eta(), assoc.phi(), mult}; + efficiency = hEfficiencyV0MultVsPhi[Index]->GetBinContent(hEfficiencyV0MultVsPhi[Index]->GetBin(bin)); + if (efficiencyFlags.applyEfficiencyPropagation) + efficiencyError = hEfficiencyV0MultVsPhi[Index]->GetBinError(hEfficiencyV0MultVsPhi[Index]->GetBin(bin)); + } else { + efficiency = hEfficiencyV0[Index]->Interpolate(ptassoc, assoc.eta()); + if (efficiencyFlags.applyEfficiencyPropagation) + efficiencyError = hEfficiencyUncertaintyV0[Index]->Interpolate(ptassoc, assoc.eta()); + } } if (efficiency == 0) { // check for zero efficiency, do not apply if the case efficiency = 1; @@ -728,163 +869,256 @@ struct HStrangeCorrelation { totalEffUncert = std::sqrt(std::pow(efficiencyTrigg * efficiencyError, 2) + std::pow(efficiencyTriggError * efficiency, 2)); } double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; - if (TESTBIT(doCorrelation, Index) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0) && (doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { - fillCorrelationHistogram(histos.get(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (TESTBIT(doCorrelation, Index) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0) && (masterConfigurations.doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + fillCorrelationHistogram(histos.get(HIST("sameEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); double deltaPhiStarPion = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStarPion, bField); - if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign > 0) || (Index == 2 && triggSign < 0)) { - histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); - if (Index == 0) { - histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); + if ((Index == IndexK0 && triggSign > Neutral) || (Index == IndexLambda && triggSign > Neutral) || (Index == IndexAntiLambda && triggSign < Neutral)) { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if (Index == IndexK0) { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); } } else { - histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); - if (Index == 0) { - histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); + histos.fill(HIST("sameEvent/LeftBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + if (Index == IndexK0) { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); } } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { - fillCorrelationHistogram(histos.get(HIST("sameEvent/Signal/") + HIST(kV0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (std::abs(deltaphi) < 0.8 && doITSClustersQA) { - histos.fill(HIST("hITSClusters") + HIST(kV0names[Index]) + HIST("NegativeDaughterToward"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); - histos.fill(HIST("hITSClusters") + HIST(kV0names[Index]) + HIST("PositiveDaughterToward"), ptassoc, postrack.itsNCls(), assoc.v0radius()); + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + fillCorrelationHistogram(histos.get(HIST("sameEvent/Signal/") + HIST(V0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (std::abs(deltaphi) < checks.towardDeltaEtaRange && doITSClustersQA) { + histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("NegativeDaughterToward"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); + histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("PositiveDaughterToward"), ptassoc, postrack.itsNCls(), assoc.v0radius()); } - if (std::abs(deltaphi) > 1 && std::abs(deltaphi) < 2 && doITSClustersQA) { - histos.fill(HIST("hITSClusters") + HIST(kV0names[Index]) + HIST("NegativeDaughterTransverse"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); - histos.fill(HIST("hITSClusters") + HIST(kV0names[Index]) + HIST("PositiveDaughterTransverse"), ptassoc, postrack.itsNCls(), assoc.v0radius()); + if (std::abs(deltaphi) > checks.transwerseDeltaEtaRangeMin && std::abs(deltaphi) < checks.transwerseDeltaEtaRangeMax && doITSClustersQA) { + histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("NegativeDaughterTransverse"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); + histos.fill(HIST("hITSClusters") + HIST(V0names[Index]) + HIST("PositiveDaughterTransverse"), ptassoc, postrack.itsNCls(), assoc.v0radius()); } if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); double deltaPhiStarPion = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStarPion, bField); - if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign > 0) || (Index == 2 && triggSign < 0)) { - histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); - if (Index == 0) { - histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); + if ((Index == IndexK0 && triggSign > Neutral) || (Index == IndexLambda && triggSign > Neutral) || (Index == IndexAntiLambda && triggSign < Neutral)) { + histos.fill(HIST("sameEvent/Signal/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if (Index == IndexK0) { + histos.fill(HIST("sameEvent/Signal/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); } } else { - histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); - if (Index == 0) { - histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); + histos.fill(HIST("sameEvent/Signal/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + if (Index == IndexK0) { + histos.fill(HIST("sameEvent/Signal/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); } } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { - fillCorrelationHistogram(histos.get(HIST("sameEvent/RightBg/") + HIST(kV0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + fillCorrelationHistogram(histos.get(HIST("sameEvent/RightBg/") + HIST(V0names[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); double deltaPhiStarPion = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStarPion, bField); - if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign > 0) || (Index == 2 && triggSign < 0)) { - histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); - if (Index == 0) { - histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); + if ((Index == IndexK0 && triggSign > Neutral) || (Index == IndexLambda && triggSign > Neutral) || (Index == IndexAntiLambda && triggSign < Neutral)) { + histos.fill(HIST("sameEvent/RightBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if (Index == IndexK0) { + histos.fill(HIST("sameEvent/RightBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); } } else { - histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); - if (Index == 0) { - histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); + histos.fill(HIST("sameEvent/RightBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + if (Index == IndexK0) { + histos.fill(HIST("sameEvent/RightBg/") + HIST(V0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); } } } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(kV0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(kV0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(kV0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 0, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiencyTrigg, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiencyTrigg, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(V0names[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } } }); } } + if (!mixingInBf || binVtxZ < 0 || binVtxZ > nBinsVtxZ - 1 || binMult < 0 || binMult > nBinsMult - 1) + return; + int binnumb = binMult * nBinsVtxZ + binVtxZ; + int hastirgorassoc = masterConfigurations.collisionHasTriggOrAssoc; + if ((hastirgorassoc == 1 && currentCollision.trigParticles.empty()) || + (hastirgorassoc == 2 && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 3 && currentCollision.trigParticles.empty() && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 4 && (currentCollision.trigParticles.empty() || currentCollision.assocParticles.empty()))) + return; + for (const auto& collision : validCollisions[binnumb]) { + BinningTypePP colBinning{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}; + // When 'collisionHasTriggOrAssoc' = 0: + // binContent(hMECollisionBins) = Σ(RunNumbers)[binContent(the same bin of hSECollisionBins) * masterConfigurations.mixingParameter - Σ(k=0 to min(masterConfigurations.mixingParameter,binContent)) k] + // When 'collisionHasTriggOrAssoc' = 3 + // More collision loss at higher peripheral centrality (fewer target particles); higher bincontent of HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index]) + // due to avoiding vector occupancy by collisions with no trigger&associated particles + histos.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision.pvz, collision.mult})); + for (const auto& trigger : collision.trigParticles) { + for (const auto& assoc : currentCollision.assocParticles) { + float deltaeta = trigger.eta - assoc.eta; + float deltaphi = computeDeltaPhi(trigger.phi, assoc.phi); + float efficiencyTrigg = trigger.efficiency; + float efficiencyAssoc = assoc.efficiency; + float efficiencyTriggError = trigger.efficiencyError; + float efficiencyAssocError = assoc.efficiencyError; + float totalEffUncert = 0.0; + float ptassoc = assoc.pt; + float pttrigger = trigger.pt; + if (efficiencyFlags.applyEfficiencyPropagation) { + totalEffUncert = std::sqrt(std::pow(efficiencyTrigg * efficiencyAssocError, 2) + std::pow(efficiencyTriggError * efficiencyAssoc, 2)); + } + double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; + static_for<0, 2>([&](auto i) { + constexpr int Index = i.value; + if (Index == assoc.type && assoc.region == 0) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(V0names[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 1) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(V0names[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 2) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(V0names[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + }); + } + } + } + if (validCollisions[binnumb].size() >= static_cast(masterConfigurations.mixingParameter)) { + validCollisions[binnumb].erase(validCollisions[binnumb].begin()); + } + validCollisions[binnumb].push_back(currentCollision); } - void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) + void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, bool mixingInBf, float pvx, float pvy, float pvz, float mult, double bField) { + ValidCollision currentCollision; + int nBinsMult = 0; + int binMult = 0; + int nBinsVtxZ = 0; + int binVtxZ = 0; + currentCollision.pvz = pvz; + currentCollision.mult = mult; + if (mixingInBf) { + nBinsMult = histos.get(HIST("axes/hMultAxis"))->GetNbinsX(); + binMult = histos.get(HIST("axes/hMultAxis"))->GetXaxis()->FindBin(mult) - 1; + nBinsVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetNbinsX(); + binVtxZ = histos.get(HIST("axes/hVertexZAxis"))->GetXaxis()->FindBin(pvz) - 1; + } + bool firstLoop = false; for (auto const& triggerTrack : triggers) { - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; auto trigg = triggerTrack.track_as(); - if (!isValidTrigger(trigg)) + if (!isValidTrigger(trigg, triggerTrack.isLeading())) continue; float efficiencyTrigg = 1.0f; float efficiencyTriggError = 0.0f; float purityTrigg = 1.0f; float purityTriggErr = 0.0f; - if (!mixing) { - if (efficiencyFlags.applyEfficiencyForTrigger) { - if (efficiencyFlags.applyEffAsFunctionOfMult) { - efficiencyTrigg = hEfficiencyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); - } else { - efficiencyTrigg = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); - } + if (efficiencyFlags.applyEfficiencyForTrigger) { + double bintrig[4] = {trigg.pt(), trigg.eta(), trigg.phi(), mult}; + if (efficiencyFlags.applyEffAsFunctionOfMult) { + efficiencyTrigg = hEfficiencyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); + } else if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + efficiencyTrigg = hEfficiencyTriggerMultVsPhi->GetBinContent(hEfficiencyTriggerMultVsPhi->GetBin(bintrig)); + } else { + efficiencyTrigg = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); + } + if (efficiencyFlags.applyPurityTrigger) { + if (efficiencyFlags.applyEffAsFunctionOfMult) + purityTrigg = hPurityHadronMult->Interpolate(trigg.pt(), mult); + else + purityTrigg = hPurityHadron->Interpolate(trigg.pt()); + } + if (efficiencyFlags.applyEfficiencyPropagation) { + if (efficiencyFlags.applyEffAsFunctionOfMult) + efficiencyTriggError = hEfficiencyUncertaintyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); + else if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) + efficiencyTriggError = hEfficiencyTriggerMultVsPhi->GetBinError(hEfficiencyTriggerMultVsPhi->GetBin(bintrig)); + else + efficiencyTriggError = hEfficiencyUncertaintyTrigger->Interpolate(trigg.pt(), trigg.eta()); if (efficiencyFlags.applyPurityTrigger) { if (efficiencyFlags.applyEffAsFunctionOfMult) - purityTrigg = hPurityHadronMult->Interpolate(trigg.pt(), mult); + purityTriggErr = hPurityUncertaintyHadronMult->Interpolate(trigg.pt(), mult); else - purityTrigg = hPurityHadron->Interpolate(trigg.pt()); - } - if (efficiencyFlags.applyEfficiencyPropagation) { - if (efficiencyFlags.applyEffAsFunctionOfMult) - efficiencyTriggError = hEfficiencyUncertaintyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); - else - efficiencyTriggError = hEfficiencyUncertaintyTrigger->Interpolate(trigg.pt(), trigg.eta()); - if (efficiencyFlags.applyPurityTrigger) { - if (efficiencyFlags.applyEffAsFunctionOfMult) - purityTriggErr = hPurityUncertaintyHadronMult->Interpolate(trigg.pt(), mult); - else - purityTriggErr = hPurityUncertaintyHadron->Interpolate(trigg.pt()); - } - } - if (efficiencyTrigg == 0) { // check for zero efficiency, do not apply if the case - efficiencyTrigg = 1; - efficiencyTriggError = 0; + purityTriggErr = hPurityUncertaintyHadron->Interpolate(trigg.pt()); } } + if (efficiencyTrigg == 0) { // check for zero efficiency, do not apply if the case + efficiencyTrigg = 1; + efficiencyTriggError = 0; + } + } + if (!mixing) { fillTriggerHistogram(histos.get(HIST("sameEvent/TriggerParticlesCascade")), trigg.pt(), mult, efficiencyTrigg, efficiencyTriggError, purityTrigg, purityTriggErr); } double triggSign = trigg.sign(); double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + if (mixingInBf) { + currentCollision.addValidParticle(trigg.eta(), trigg.phi(), trigg.pt(), -1, efficiencyTrigg, efficiencyTriggError, -1); + if (firstLoop) + continue; + } for (auto const& assocCandidate : assocs) { + firstLoop = true; auto assoc = assocCandidate.cascData(); //---] syst cuts [--- - if (doPPAnalysis && (std::abs(assoc.dcapostopv()) < systCuts.dcapostopv || - std::abs(assoc.dcanegtopv()) < systCuts.dcanegtopv || - std::abs(assoc.dcabachtopv()) < systCuts.cascDcabachtopv || - assoc.dcaV0daughters() > systCuts.dcaV0dau || - assoc.dcacascdaughters() > systCuts.cascDcacascdau || - assoc.v0cosPA(pvx, pvy, pvz) < systCuts.v0cospa || - assoc.casccosPA(pvx, pvy, pvz) < systCuts.cascCospa || - assoc.cascradius() < systCuts.cascRadius || - std::abs(assoc.dcav0topv(pvx, pvy, pvz)) < systCuts.cascMindcav0topv || - std::abs(assoc.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (masterConfigurations.doPPAnalysis && (std::abs(assoc.dcapostopv()) < v0Selection.dcapostopv || + std::abs(assoc.dcanegtopv()) < v0Selection.dcanegtopv || + std::abs(assoc.dcabachtopv()) < cascadeSelections.dcaBachToPV || + assoc.dcaV0daughters() > cascadeSelections.cascdcaV0dau || + assoc.dcacascdaughters() > cascadeSelections.dcaCascDaughters || + assoc.v0cosPA(pvx, pvy, pvz) < cascadeSelections.cascv0cospa || + assoc.casccosPA(pvx, pvy, pvz) < cascadeSelections.cascCospa || + assoc.cascradius() < cascadeSelections.cascRadius || + std::abs(assoc.dcav0topv(pvx, pvy, pvz)) < cascadeSelections.cascdcaV0ToPV || + std::abs(assoc.mLambda() - o2::constants::physics::MassLambda0) > cascadeSelections.cascV0masswindow)) continue; - if (!doPPAnalysis && !CascadeSelectedPbPb(assoc, pvx, pvy, pvz)) + if (!masterConfigurations.doPPAnalysis && !cascadeSelectedPbPb(assoc, pvx, pvy, pvz)) continue; - uint64_t CascselMap = CascadeselectionBitmap(assoc, pvx, pvy, pvz); + uint64_t cascselMap = cascadeselectionBitmap(assoc, pvx, pvy, pvz); //---] removing autocorrelations [--- auto postrack = assoc.posTrack_as(); auto negtrack = assoc.negTrack_as(); auto bachtrack = assoc.bachelor_as(); - if (doAutocorrelationRejection) { - if (trigg.globalIndex() == postrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); - continue; - } - if (trigg.globalIndex() == negtrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); - continue; - } - if (trigg.globalIndex() == bachtrack.globalIndex()) { - histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); - continue; + if (!mixingInBf) { + if (doAutocorrelationRejection) { + if (trigg.globalIndex() == postrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); + continue; + } + if (trigg.globalIndex() == negtrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); + continue; + } + if (trigg.globalIndex() == bachtrack.globalIndex()) { + histos.fill(HIST("hNumberOfRejectedPairsCascades"), 0.5); + continue; + } } } double phiProton = postrack.phi(); @@ -899,7 +1133,11 @@ struct HStrangeCorrelation { } double assocForDeltaPhiStar[] = {phiProton, ptProton, signProton}; //---] track quality check [--- - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || bachtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || bachtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; float deltaphi = computeDeltaPhi(trigg.phi(), assoc.phi()); @@ -916,10 +1154,18 @@ struct HStrangeCorrelation { continue; TH2F* hEfficiencyCascade[4]; - hEfficiencyCascade[0] = hEfficiencyXiMinus; - hEfficiencyCascade[1] = hEfficiencyXiPlus; - hEfficiencyCascade[2] = hEfficiencyOmegaMinus; - hEfficiencyCascade[3] = hEfficiencyOmegaPlus; + THnF* hEfficiencyCascadeMultVsPhi[4]; + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + hEfficiencyCascadeMultVsPhi[0] = hEfficiencyXiMinusMultVsPhi; + hEfficiencyCascadeMultVsPhi[1] = hEfficiencyXiPlusMultVsPhi; + hEfficiencyCascadeMultVsPhi[2] = hEfficiencyOmegaMinusMultVsPhi; + hEfficiencyCascadeMultVsPhi[3] = hEfficiencyOmegaPlusMultVsPhi; + } else { + hEfficiencyCascade[0] = hEfficiencyXiMinus; + hEfficiencyCascade[1] = hEfficiencyXiPlus; + hEfficiencyCascade[2] = hEfficiencyOmegaMinus; + hEfficiencyCascade[3] = hEfficiencyOmegaPlus; + } TH2F* hEfficiencyUncertaintyCascade[4]; hEfficiencyUncertaintyCascade[0] = hEfficiencyUncertaintyXiMinus; @@ -928,7 +1174,7 @@ struct HStrangeCorrelation { hEfficiencyUncertaintyCascade[3] = hEfficiencyUncertaintyOmegaPlus; float etaWeight = 1; - if (systCuts.doOnTheFlyFlattening) { + if (checks.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } @@ -939,9 +1185,16 @@ struct HStrangeCorrelation { float totalEffUncert = 0.0; float efficiencyError = 0.0f; if (efficiencyFlags.applyEfficiencyCorrection) { - efficiency = hEfficiencyCascade[Index]->Interpolate(ptassoc, assoc.eta()); - if (efficiencyFlags.applyEfficiencyPropagation) - efficiencyError = hEfficiencyUncertaintyCascade[Index]->Interpolate(ptassoc, assoc.eta()); + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + double bin[4] = {ptassoc, assoc.eta(), assoc.phi(), mult}; + efficiency = hEfficiencyCascadeMultVsPhi[Index]->GetBinContent(hEfficiencyCascadeMultVsPhi[Index]->GetBin(bin)); + if (efficiencyFlags.applyEfficiencyPropagation) + efficiencyError = hEfficiencyCascadeMultVsPhi[Index]->GetBinError(hEfficiencyCascadeMultVsPhi[Index]->GetBin(bin)); + } else { + efficiency = hEfficiencyCascade[Index]->Interpolate(ptassoc, assoc.eta()); + if (efficiencyFlags.applyEfficiencyPropagation) + efficiencyError = hEfficiencyUncertaintyCascade[Index]->Interpolate(ptassoc, assoc.eta()); + } } if (efficiency == 0) { // check for zero efficiency, do not apply if the case efficiency = 1; @@ -951,93 +1204,153 @@ struct HStrangeCorrelation { totalEffUncert = std::sqrt(std::pow(efficiencyTrigg * efficiencyError, 2) + std::pow(efficiencyTriggError * efficiency, 2)); } double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; - if (TESTBIT(doCorrelation, Index + 3) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0) && (doPPAnalysis || (TESTBIT(CascselMap, Index) && TESTBIT(CascselMap, Index + 4) && TESTBIT(CascselMap, Index + 8) && TESTBIT(CascselMap, Index + 12)))) { - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { - fillCorrelationHistogram(histos.get(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (TESTBIT(doCorrelation, Index + 3) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0) && (masterConfigurations.doPPAnalysis || (TESTBIT(cascselMap, Index) && TESTBIT(cascselMap, Index + 4) && TESTBIT(cascselMap, Index + 8) && TESTBIT(cascselMap, Index + 12)))) { + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + fillCorrelationHistogram(histos.get(HIST("sameEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); - if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign < 0) || (Index == 2 && triggSign > 0) || (Index == 3 && triggSign < 0)) - histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if ((Index == IndexXiMinus && triggSign > Neutral) || (Index == IndexXiPlus && triggSign < Neutral) || (Index == IndexOmegaMinus && triggSign > Neutral) || (Index == IndexOmegaPlus && triggSign < 0)) + histos.fill(HIST("sameEvent/LeftBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); else - histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + histos.fill(HIST("sameEvent/LeftBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { - fillCorrelationHistogram(histos.get(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + fillCorrelationHistogram(histos.get(HIST("sameEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); - if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign < 0) || (Index == 2 && triggSign > 0) || (Index == 3 && triggSign < 0)) - histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if ((Index == IndexXiMinus && triggSign > Neutral) || (Index == IndexXiPlus && triggSign < Neutral) || (Index == IndexOmegaMinus && triggSign > Neutral) || (Index == IndexOmegaPlus && triggSign < 0)) + histos.fill(HIST("sameEvent/Signal/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); else - histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + histos.fill(HIST("sameEvent/Signal/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { - fillCorrelationHistogram(histos.get(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + fillCorrelationHistogram(histos.get(HIST("sameEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, etaWeight, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); if (doDeltaPhiStarCheck) { double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); - if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign < 0) || (Index == 2 && triggSign > 0) || (Index == 3 && triggSign < 0)) - histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if ((Index == IndexXiMinus && triggSign > Neutral) || (Index == IndexXiPlus && triggSign < Neutral) || (Index == IndexOmegaMinus && triggSign > Neutral) || (Index == IndexOmegaPlus && triggSign < 0)) + histos.fill(HIST("sameEvent/RightBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); else - histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + histos.fill(HIST("sameEvent/RightBg/") + HIST(Cascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + } + } + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 0, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 1, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); + } + } + if (assocCandidate.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { + if (mixingInBf) { + currentCollision.addValidParticle(assoc.eta(), assoc.phi(), assoc.pt(), 2, efficiency, efficiencyError, Index); + } else { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(kCascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(kCascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) - fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(kCascadenames[Index])), binFillThn, 1, efficiency * efficiencyTrigg, totalEffUncert, purityTrigg, purityTriggErr); } }); } } + if (!mixingInBf || binVtxZ < 0 || binVtxZ > nBinsVtxZ - 1 || binMult < 0 || binMult > nBinsMult - 1) + return; + int binnumb = binMult * nBinsVtxZ + binVtxZ; + int hastirgorassoc = masterConfigurations.collisionHasTriggOrAssoc; + if ((hastirgorassoc == 1 && currentCollision.trigParticles.empty()) || + (hastirgorassoc == 2 && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 3 && currentCollision.trigParticles.empty() && currentCollision.assocParticles.empty()) || + (hastirgorassoc == 4 && (currentCollision.trigParticles.empty() || currentCollision.assocParticles.empty()))) + return; + for (const auto& collision : validCollisions[binnumb]) { + BinningTypePP colBinning{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}; + histos.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision.pvz, collision.mult})); + for (const auto& trigger : collision.trigParticles) { + for (const auto& assoc : currentCollision.assocParticles) { + float deltaeta = trigger.eta - assoc.eta; + float deltaphi = computeDeltaPhi(trigger.phi, assoc.phi); + float efficiencyTrigg = trigger.efficiency; + float efficiencyAssoc = assoc.efficiency; + float efficiencyTriggError = trigger.efficiencyError; + float efficiencyAssocError = assoc.efficiencyError; + float totalEffUncert = 0.0; + float ptassoc = assoc.pt; + float pttrigger = trigger.pt; + if (efficiencyFlags.applyEfficiencyPropagation) { + totalEffUncert = std::sqrt(std::pow(efficiencyTrigg * efficiencyAssocError, 2) + std::pow(efficiencyTriggError * efficiencyAssoc, 2)); + } + double binFillThn[6] = {deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult}; + static_for<0, 3>([&](auto i) { + constexpr int Index = i.value; + if (Index == assoc.type && assoc.region == 0) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/LeftBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 1) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/Signal/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + if (Index == assoc.type && assoc.region == 2) { + fillCorrelationHistogram(histos.get(HIST("mixedEvent/RightBg/") + HIST(Cascadenames[Index])), binFillThn, 1, efficiencyTrigg * efficiencyAssoc, totalEffUncert, 1., 0.); + } + }); + } + } + } + if (validCollisions[binnumb].size() >= static_cast(masterConfigurations.mixingParameter)) { + validCollisions[binnumb].erase(validCollisions[binnumb].begin()); + } + validCollisions[binnumb].push_back(currentCollision); } template void fillCorrelationsHadron(TTriggers const& triggers, THadrons const& assocs, bool mixing, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; auto trigg = triggerTrack.template track_as(); - if (!isValidTrigger(trigg)) + if (!isValidTrigger(trigg, triggerTrack.isLeading())) continue; float efficiencyTrigger = 1.0f; float efficiencyTriggerError = 0.0f; float purityTrigger = 1.0f; float purityTriggerError = 0.0f; - if (!mixing) { - - if (efficiencyFlags.applyEfficiencyForTrigger) { + if (efficiencyFlags.applyEfficiencyForTrigger) { + if (efficiencyFlags.applyEffAsFunctionOfMult) + efficiencyTrigger = hEfficiencyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); + else + efficiencyTrigger = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); + if (efficiencyFlags.applyPurityTrigger) { if (efficiencyFlags.applyEffAsFunctionOfMult) - efficiencyTrigger = hEfficiencyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); + purityTrigger = hPurityHadronMult->Interpolate(trigg.pt(), mult); else - efficiencyTrigger = hEfficiencyTrigger->Interpolate(trigg.pt(), trigg.eta()); + purityTrigger = hPurityHadron->Interpolate(trigg.pt()); + } + if (efficiencyFlags.applyEfficiencyPropagation) { + if (efficiencyFlags.applyEffAsFunctionOfMult) + efficiencyTriggerError = hEfficiencyUncertaintyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); + else + efficiencyTriggerError = hEfficiencyUncertaintyTrigger->Interpolate(trigg.pt(), trigg.eta()); if (efficiencyFlags.applyPurityTrigger) { if (efficiencyFlags.applyEffAsFunctionOfMult) - purityTrigger = hPurityHadronMult->Interpolate(trigg.pt(), mult); + purityTriggerError = hPurityUncertaintyHadronMult->Interpolate(trigg.pt(), mult); else - purityTrigger = hPurityHadron->Interpolate(trigg.pt()); - } - if (efficiencyFlags.applyEfficiencyPropagation) { - if (efficiencyFlags.applyEffAsFunctionOfMult) - efficiencyTriggerError = hEfficiencyUncertaintyTriggerMult->Interpolate(trigg.pt(), trigg.eta(), mult); - else - efficiencyTriggerError = hEfficiencyUncertaintyTrigger->Interpolate(trigg.pt(), trigg.eta()); - if (efficiencyFlags.applyPurityTrigger) { - if (efficiencyFlags.applyEffAsFunctionOfMult) - purityTriggerError = hPurityUncertaintyHadronMult->Interpolate(trigg.pt(), mult); - else - purityTriggerError = hPurityUncertaintyHadron->Interpolate(trigg.pt()); - } - } - if (efficiencyTrigger == 0) { // check for zero efficiency, do not apply if the case - efficiencyTrigger = 1; - efficiencyTriggerError = 0; + purityTriggerError = hPurityUncertaintyHadron->Interpolate(trigg.pt()); } } + if (efficiencyTrigger == 0) { // check for zero efficiency, do not apply if the case + efficiencyTrigger = 1; + efficiencyTriggerError = 0; + } + } + if (!mixing) { if constexpr (requires { triggerTrack.extra(); }) fillTriggerHistogram(histos.get(HIST("sameEvent/TriggerParticlesPion")), trigg.pt(), mult, efficiencyTrigger, efficiencyTriggerError, purityTrigger, purityTriggerError); else @@ -1073,7 +1386,7 @@ struct HStrangeCorrelation { double assocForDeltaPhiStar[] = {assoc.phi(), assoc.pt(), assocSign}; float etaWeight = 1.; - if (systCuts.doOnTheFlyFlattening) { + if (checks.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } @@ -1189,23 +1502,23 @@ struct HStrangeCorrelation { // set bitmap for convenience doCorrelation = 0; - if (doCorrelationK0Short) + if (masterConfigurations.doCorrelationK0Short) SETBIT(doCorrelation, 0); - if (doCorrelationLambda) + if (masterConfigurations.doCorrelationLambda) SETBIT(doCorrelation, 1); - if (doCorrelationAntiLambda) + if (masterConfigurations.doCorrelationAntiLambda) SETBIT(doCorrelation, 2); - if (doCorrelationXiMinus) + if (masterConfigurations.doCorrelationXiMinus) SETBIT(doCorrelation, 3); - if (doCorrelationXiPlus) + if (masterConfigurations.doCorrelationXiPlus) SETBIT(doCorrelation, 4); - if (doCorrelationOmegaMinus) + if (masterConfigurations.doCorrelationOmegaMinus) SETBIT(doCorrelation, 5); - if (doCorrelationOmegaPlus) + if (masterConfigurations.doCorrelationOmegaPlus) SETBIT(doCorrelation, 6); - if (doCorrelationPion) + if (masterConfigurations.doCorrelationPion) SETBIT(doCorrelation, 7); - if (doCorrelationHadron) + if (masterConfigurations.doCorrelationHadron) SETBIT(doCorrelation, 8); // Store axis ranges to prevent spurious filling @@ -1272,7 +1585,7 @@ struct HStrangeCorrelation { // this feature is meant to save memory conveniently. // it should actually be implemented centrally in ROOT but ok, this will do it for now. - int offset = skipUnderOverflowInTHn ? 1 : 0; + int offset = masterConfigurations.skipUnderOverflowInTHn ? 1 : 0; // ===] delta-phi [=== if (!preAxisDeltaPhi.nBins.has_value()) { // variable binning, use bins provided @@ -1359,7 +1672,14 @@ struct HStrangeCorrelation { const AxisSpec axisPtTriggerNDim{edgesPtTrigger, "#it{p}_{T}^{trigger} (GeV/c)"}; const AxisSpec axisVtxZNDim{edgesVtxZ, "vertex Z (cm)"}; const AxisSpec axisMultNDim{edgesMult, "mult percentile"}; - if (!doPPAnalysis) { + + if (doprocessMixedEventHV0sInBuffer || doprocessMixedEventHCascadesInBuffer) { + validCollisions.resize(histos.get(HIST("axes/hMultAxis"))->GetNbinsX() * histos.get(HIST("axes/hVertexZAxis"))->GetNbinsX()); + for (auto& inner_vec : validCollisions) { + inner_vec.reserve(masterConfigurations.mixingParameter); + } + } + if (!masterConfigurations.doPPAnalysis) { // event selections in Pb-Pb histos.add("hEventSelection", "hEventSelection", kTH1F, {{10, 0, 10}}); TString eventSelLabel[] = {"all", "sel8", "kIsTriggerTVX", "PV_{z}", "kIsGoodITSLayersAll", "kIsGoodZvtxFT0vsPV", "OccupCut", "kNoITSROFrameBorder", "kNoSameBunchPileup ", " kNoCollInTimeRangeStandard"}; @@ -1385,7 +1705,11 @@ struct HStrangeCorrelation { histos.add("hNegativeTriggerPrimaryEtaVsPt", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); // QA and THn Histograms histos.add("hTriggerPtResolution", ";p_{T}^{reconstructed} (GeV/c); p_{T}^{generated} (GeV/c)", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisPtQA}); - histos.add("hTriggerPrimaryEtaVsPt", "hTriggerPrimaryEtaVsPt", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.add("hTriggerPrimaryEtaVsPt", "hTriggerPrimaryEtaVsPt", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + } else { + histos.add("hTriggerPrimaryEtaVsPt", "hTriggerPrimaryEtaVsPt", kTHnF, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi, axesConfigurations.axisMult}); + } histos.add("hTrackEtaVsPtVsPhi", "hTrackEtaVsPtVsPhi", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); histos.add("hAssocTrackEtaVsPtVsPhi", "hAssocTrackEtaVsPtVsPhi", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); // histos.add("hTrackAttempt", "Attempt", kTH3F, {axisPtQA, axisEta, axisPhi}); @@ -1416,24 +1740,29 @@ struct HStrangeCorrelation { } bool hStrange = false; - for (int i = 0; i < 9; i++) { + for (int i = 0; i < AssocParticleTypes; i++) { if (TESTBIT(doCorrelation, i)) { - if (doFullCorrelationStudy) - histos.add(fmt::format("sameEvent/Signal/{}", kParticlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); - if (doDeltaPhiStarCheck && doFullCorrelationStudy) { - histos.add(fmt::format("sameEvent/Signal/{}DeltaPhiStar", kParticlenames[i]).c_str(), "", kTH3F, {{100, -0.3, 0.3}, {50, -0.05, 0.05}, {2, -1, 1}}); // -1 oposite charge, 1 same charge - } - if (i < 7) { - histos.add(fmt::format("h{}EtaVsPtVsPhi", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); - histos.add(fmt::format("h3d{}Spectrum", kParticlenames[i]).c_str(), fmt::format("h3d{}Spectrum", kParticlenames[i]).c_str(), kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult, axesConfigurations.axisMassNSigma}); - histos.add(fmt::format("h3d{}SpectrumY", kParticlenames[i]).c_str(), fmt::format("h3d{}SpectrumY", kParticlenames[i]).c_str(), kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult, axesConfigurations.axisMassNSigma}); + if (masterConfigurations.doFullCorrelationStudy) + histos.add(fmt::format("sameEvent/Signal/{}", Particlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + if (doDeltaPhiStarCheck && masterConfigurations.doFullCorrelationStudy) { + histos.add(fmt::format("sameEvent/Signal/{}DeltaPhiStar", Particlenames[i]).c_str(), "", kTH3F, {{100, -0.3, 0.3}, {50, -0.05, 0.05}, {2, -1, 1}}); // -1 oposite charge, 1 same charge + } + if (i < IndexPion) { + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.add(fmt::format("h{}EtaVsPtVsPhi", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); + histos.add(fmt::format("h{}EtaVsPtVsPhiBg", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); + } else { + histos.add(fmt::format("h{}EtaVsPtVsPhiVsCent", Particlenames[i]).c_str(), "", kTHnF, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi, axesConfigurations.axisMult}); + histos.add(fmt::format("h{}EtaVsPtVsPhiVsCentBg", Particlenames[i]).c_str(), "", kTHnF, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi, axesConfigurations.axisMult}); + } + histos.add(fmt::format("h3d{}Spectrum", Particlenames[i]).c_str(), fmt::format("h3d{}Spectrum", Particlenames[i]).c_str(), kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult, axesConfigurations.axisMassNSigma}); + histos.add(fmt::format("h3d{}SpectrumY", Particlenames[i]).c_str(), fmt::format("h3d{}SpectrumY", Particlenames[i]).c_str(), kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult, axesConfigurations.axisMassNSigma}); hStrange = true; - histos.add(fmt::format("h{}EtaVsPtVsPhiBg", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); if (doITSClustersQA) { - histos.add(fmt::format("hITSClusters{}NegativeDaughterToward", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); - histos.add(fmt::format("hITSClusters{}PositiveDaughterToward", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); - histos.add(fmt::format("hITSClusters{}NegativeDaughterTransverse", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); - histos.add(fmt::format("hITSClusters{}PositiveDaughterTransverse", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); + histos.add(fmt::format("hITSClusters{}NegativeDaughterToward", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); + histos.add(fmt::format("hITSClusters{}PositiveDaughterToward", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); + histos.add(fmt::format("hITSClusters{}NegativeDaughterTransverse", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); + histos.add(fmt::format("hITSClusters{}PositiveDaughterTransverse", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtAssoc, {8, -0.5, 7.5}, {20, 0, 10}}); } } } @@ -1451,51 +1780,59 @@ struct HStrangeCorrelation { histos.add("hAssocPtResolution", ";p_{T}^{reconstructed} (GeV/c); p_{T}^{generated} (GeV/c)", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisPtQA}); } - if (hStrange && doFullCorrelationStudy) { + if (hStrange && masterConfigurations.doFullCorrelationStudy) { histos.addClone("sameEvent/Signal/", "sameEvent/LeftBg/"); histos.addClone("sameEvent/Signal/", "sameEvent/RightBg/"); } LOGF(info, "Init THnFs done"); // mixed-event correlation functions - if ((doprocessMixedEventHV0s || doprocessMixedEventHCascades || doprocessMixedEventHPions || doprocessMixedEventHHadrons) && doFullCorrelationStudy) { + if ((doprocessMixedEventHV0sInBuffer || doprocessMixedEventHCascadesInBuffer || doprocessMixedEventHV0s || doprocessMixedEventHCascades || doprocessMixedEventHPions || doprocessMixedEventHHadrons) && masterConfigurations.doFullCorrelationStudy) { histos.addClone("sameEvent/", "mixedEvent/"); } - if (doprocessSameEventHHadrons && doFullCorrelationStudy) + if (doprocessSameEventHHadrons && masterConfigurations.doFullCorrelationStudy) histos.add("sameEvent/TriggerParticlesHadron", "TriggersHadron", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); - if (doprocessSameEventHV0s && doFullCorrelationStudy) + if (doprocessSameEventHV0s && masterConfigurations.doFullCorrelationStudy) histos.add("sameEvent/TriggerParticlesV0", "TriggersV0", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); - if (doprocessSameEventHCascades && doFullCorrelationStudy) + if (doprocessSameEventHCascades && masterConfigurations.doFullCorrelationStudy) histos.add("sameEvent/TriggerParticlesCascade", "TriggersCascade", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); - if (doprocessSameEventHPions && doFullCorrelationStudy) + if (doprocessSameEventHPions && masterConfigurations.doFullCorrelationStudy) histos.add("sameEvent/TriggerParticlesPion", "TriggersPion", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); // MC generated plots if (doprocessMCGenerated) { - histos.add("Generated/hTrigger", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.add("Generated/hTrigger", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + } else { + histos.add("Generated/hTrigger", "", kTHnF, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi, axesConfigurations.axisMult}); + } histos.add("Generated/hPositiveTrigger", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); histos.add("Generated/hNegativeTrigger", "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); - for (int i = 0; i < 9; i++) { - histos.add(fmt::format("Generated/h{}", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); - if (i == 7) { - histos.add(fmt::format("Generated/hPositive{}", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); - histos.add(fmt::format("Generated/hNegative{}", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + for (int i = 0; i < AssocParticleTypes; i++) { + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.add(fmt::format("Generated/h{}", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + } else { + histos.add(fmt::format("Generated/h{}", Particlenames[i]).c_str(), "", kTHnF, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi, axesConfigurations.axisMult}); + } + if (i == IndexPion) { + histos.add(fmt::format("Generated/hPositive{}", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); + histos.add(fmt::format("Generated/hNegative{}", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); } } histos.addClone("Generated/", "GeneratedWithPV/"); // histograms within |y|<0.5, vs multiplicity - for (int i = 0; i < 8; i++) { - histos.add(fmt::format("GeneratedWithPV/h{}_MidYVsMult", kParticlenames[i]).c_str(), "", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); - histos.add(fmt::format("GeneratedWithPV/h{}_MidYVsMult_TwoPVsOrMore", kParticlenames[i]).c_str(), "", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); + for (int i = 0; i < AssocParticleTypesNoHadron; i++) { + histos.add(fmt::format("GeneratedWithPV/h{}_MidYVsMult", Particlenames[i]).c_str(), "", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); + histos.add(fmt::format("GeneratedWithPV/h{}_MidYVsMult_TwoPVsOrMore", Particlenames[i]).c_str(), "", kTH2F, {axesConfigurations.axisPtQA, axesConfigurations.axisMult}); } } if (doprocessClosureTest) { - for (int i = 0; i < 9; i++) { + for (int i = 0; i < AssocParticleTypes; i++) { if (TESTBIT(doCorrelation, i)) - histos.add(fmt::format("ClosureTest/sameEvent/{}", kParticlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + histos.add(fmt::format("ClosureTest/sameEvent/{}", Particlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); if (TESTBIT(doCorrelation, i)) - histos.add(fmt::format("ClosureTest/h{}", kParticlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); + histos.add(fmt::format("ClosureTest/h{}", Particlenames[i]).c_str(), "", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisPhi}); } histos.add("ClosureTest/hTrigger", "Trigger Tracks", kTH3F, {axesConfigurations.axisPtQA, axesConfigurations.axisEta, axesConfigurations.axisMult}); } @@ -1538,16 +1875,16 @@ struct HStrangeCorrelation { if (!collision.sel8()) { return false; } - if (std::abs(collision.posZ()) > zVertexCut) { + if (std::abs(collision.posZ()) > masterConfigurations.zVertexCut) { return false; } if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return false; } - if (!collision.isInelGt0() && selectINELgtZERO) { + if (!collision.isInelGt0() && masterConfigurations.selectINELgtZERO) { return false; } - if (!collision.selection_bit(aod::evsel::kIsGoodITSLayersAll) && requireAllGoodITSLayers) { + if (!collision.selection_bit(aod::evsel::kIsGoodITSLayersAll) && masterConfigurations.requireAllGoodITSLayers) { return false; } if (zorroMask.value != "") { @@ -1581,7 +1918,7 @@ struct HStrangeCorrelation { if (fillHists) histos.fill(HIST("hEventSelection"), 2.5 /* FT0 vertex (acceptable FT0C-FT0A time difference) collisions */); - if (std::abs(collision.posZ()) > zVertexCut) { + if (std::abs(collision.posZ()) > masterConfigurations.zVertexCut) { return false; } if (fillHists) @@ -1681,7 +2018,7 @@ struct HStrangeCorrelation { for (auto const& triggerTrack : slicedTriggerTracks) { auto track = triggerTrack.track_as(); - if (!isValidTrigger(track)) { + if (!isValidTrigger(track, triggerTrack.isLeading())) { continue; } auto binNumber = histos.get(HIST("axes/hPtTriggerAxis"))->FindFixBin(track.pt()) - 1; @@ -1725,7 +2062,7 @@ struct HStrangeCorrelation { if (!doprocessSameEventHCascades && !doprocessSameEventHV0s && !doprocessSameEventHPions) { for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); - if (!isValidTrigger(track)) + if (!isValidTrigger(track, triggerTrack.isLeading())) continue; float efficiency = 1.0f; if (efficiencyFlags.applyEfficiencyCorrection) { @@ -1737,7 +2074,7 @@ struct HStrangeCorrelation { float weight = efficiencyFlags.applyEfficiencyCorrection ? 1. / efficiency : 1.0f; histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTriggerPtResolution"), track.pt(), triggerTrack.mcOriginalPt()); - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTrackEtaVsPtVsPhi"), track.pt(), track.eta(), track.phi(), weight); @@ -1768,7 +2105,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - hadron correlations - if (doFullCorrelationStudy) + if (masterConfigurations.doFullCorrelationStudy) fillCorrelationsHadron(triggerTracks, assocHadrons, false, collision.posZ(), collision.centFT0M(), bField); } @@ -1777,12 +2114,12 @@ struct HStrangeCorrelation { V0DatasWithoutTrackX const&, TracksComplete const&, aod::BCsWithTimestamps const&) { std::variant colBinning = - doPPAnalysis + masterConfigurations.doPPAnalysis ? std::variant{ BinningTypePP{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}} : std::variant{BinningTypePbPb{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}}; - double cent = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + double cent = masterConfigurations.doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); // ________________________________________________ // skip if desired trigger not found if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { @@ -1791,7 +2128,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Perform basic event selection - if (((doPPAnalysis && !isCollisionSelected(collision))) || (!doPPAnalysis && !isCollisionSelectedPbPb(collision, true))) { + if (((masterConfigurations.doPPAnalysis && !isCollisionSelected(collision))) || (!masterConfigurations.doPPAnalysis && !isCollisionSelectedPbPb(collision, true))) { return; } // ________________________________________________ @@ -1811,9 +2148,16 @@ struct HStrangeCorrelation { initEfficiencyFromCCDB(bc); } TH2F* hEfficiencyV0[3]; - hEfficiencyV0[0] = hEfficiencyK0Short; - hEfficiencyV0[1] = hEfficiencyLambda; - hEfficiencyV0[2] = hEfficiencyAntiLambda; + THnF* hEfficiencyV0MultVsPhi[3]; + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + hEfficiencyV0MultVsPhi[0] = hEfficiencyK0ShortMultVsPhi; + hEfficiencyV0MultVsPhi[1] = hEfficiencyLambdaMultVsPhi; + hEfficiencyV0MultVsPhi[2] = hEfficiencyAntiLambdaMultVsPhi; + } else { + hEfficiencyV0[0] = hEfficiencyK0Short; + hEfficiencyV0[1] = hEfficiencyLambda; + hEfficiencyV0[2] = hEfficiencyAntiLambda; + } for (auto const& v0 : associatedV0s) { auto v0Data = v0.v0Core_as(); @@ -1821,39 +2165,58 @@ struct HStrangeCorrelation { //---] track quality check [--- auto postrack = v0Data.posTrack_as(); auto negtrack = v0Data.negTrack_as(); - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; - //---] syst cuts [--- - if (doPPAnalysis && (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)) + if (masterConfigurations.doPPAnalysis && (v0Data.v0radius() < v0Selection.v0RadiusMin || v0Data.v0radius() > v0Selection.v0RadiusMax || + std::abs(v0Data.dcapostopv()) < v0Selection.dcapostopv || std::abs(v0Data.dcanegtopv()) < v0Selection.dcanegtopv || + v0Data.v0cosPA() < v0Selection.v0cospa || v0Data.dcaV0daughters() > v0Selection.dcaV0dau)) continue; - if (!doPPAnalysis && !V0SelectedPbPb(v0Data)) + if (!masterConfigurations.doPPAnalysis && !v0SelectedPbPb(v0Data)) continue; - uint64_t selMap = V0selectionBitmap(v0Data, collision.posX(), collision.posY(), collision.posZ()); + uint64_t selMap = v0selectionBitmap(v0Data, collision.posX(), collision.posY(), collision.posZ()); static_for<0, 2>([&](auto i) { constexpr int Index = i.value; float efficiency = 1.0f; - if (efficiencyFlags.applyEfficiencyCorrection) { - efficiency = hEfficiencyV0[Index]->Interpolate(v0Data.pt(), v0Data.eta()); + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + if (efficiencyFlags.applyEfficiencyCorrection) { + double bin[4] = {v0Data.pt(), v0Data.eta(), v0Data.phi(), cent}; + efficiency = hEfficiencyV0MultVsPhi[Index]->GetBinContent(hEfficiencyV0MultVsPhi[Index]->GetBin(bin)); + } + } else { + if (efficiencyFlags.applyEfficiencyCorrection) { + efficiency = hEfficiencyV0[Index]->Interpolate(v0Data.pt(), v0Data.eta()); + } } if (efficiency == 0) { // check for zero efficiency, do not apply if the case efficiency = 1; } float weight = efficiencyFlags.applyEfficiencyCorrection ? 1. / efficiency : 1.0f; - if (v0.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || v0.mcTrue(Index)) && (!doAssocPhysicalPrimary || v0.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { - if ((TESTBIT(doCorrelation, Index)) && (doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { - histos.fill(HIST("h3d") + HIST(kV0names[Index]) + HIST("Spectrum"), v0Data.pt(), cent, v0.invMassNSigma(Index), weight); + if (v0.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || v0.mcTrue(Index)) && (!doAssocPhysicalPrimary || v0.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { + if ((TESTBIT(doCorrelation, Index)) && (masterConfigurations.doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { + histos.fill(HIST("h3d") + HIST(V0names[Index]) + HIST("Spectrum"), v0Data.pt(), cent, v0.invMassNSigma(Index), weight); if (std::abs(v0Data.rapidity(Index)) < ySel) { - histos.fill(HIST("h3d") + HIST(kV0names[Index]) + HIST("SpectrumY"), v0Data.pt(), cent, v0.invMassNSigma(Index), weight); + histos.fill(HIST("h3d") + HIST(V0names[Index]) + HIST("SpectrumY"), v0Data.pt(), cent, v0.invMassNSigma(Index), 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(kV0names[Index]) + HIST("EtaVsPtVsPhiBg"), v0Data.pt(), v0Data.eta(), v0Data.phi(), weight); - } - if (-massWindowConfigurations.maxPeakNSigma < v0.invMassNSigma(Index) && v0.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { - histos.fill(HIST("h") + HIST(kV0names[Index]) + HIST("EtaVsPtVsPhi"), v0Data.pt(), v0Data.eta(), v0Data.phi(), weight); + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + 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 (-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); + } + } else { + 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("EtaVsPtVsPhiVsCentBg"), v0Data.pt(), v0Data.eta(), v0Data.phi(), cent, weight); + } + if (-massWindowConfigurations.maxPeakNSigma < v0.invMassNSigma(Index) && v0.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + histos.fill(HIST("h") + HIST(V0names[Index]) + HIST("EtaVsPtVsPhiVsCent"), v0Data.pt(), v0Data.eta(), v0Data.phi(), cent, weight); + } } } } @@ -1862,21 +2225,25 @@ struct HStrangeCorrelation { if (!doprocessSameEventHCascades) { for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); - if (!isValidTrigger(track)) + if (!isValidTrigger(track, triggerTrack.isLeading())) continue; histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), cent); histos.fill(HIST("hTriggerPtResolution"), track.pt(), triggerTrack.mcOriginalPt()); - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; - histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), cent); + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), cent); + } else { + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), track.phi(), cent); + } histos.fill(HIST("hTrackEtaVsPtVsPhi"), track.pt(), track.eta(), track.phi()); } } // ________________________________________________ // Do hadron - V0 correlations - if (doFullCorrelationStudy) - fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsV0(triggerTracks, associatedV0s, false, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHCascades(soa::Join::iterator const& collision, @@ -1884,12 +2251,12 @@ struct HStrangeCorrelation { V0DatasWithoutTrackX const&, aod::CascDatas const&, TracksComplete const&, aod::BCsWithTimestamps const&) { std::variant colBinning = - doPPAnalysis + masterConfigurations.doPPAnalysis ? std::variant{ BinningTypePP{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}} : std::variant{BinningTypePbPb{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}}; - double cent = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + double cent = masterConfigurations.doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); // ________________________________________________ // skip if desired trigger not found if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { @@ -1898,7 +2265,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Perform basic event selection - if (((doPPAnalysis && !isCollisionSelected(collision))) || (!doPPAnalysis && !isCollisionSelectedPbPb(collision, true))) { + if (((masterConfigurations.doPPAnalysis && !isCollisionSelected(collision))) || (!masterConfigurations.doPPAnalysis && !isCollisionSelectedPbPb(collision, true))) { return; } // ________________________________________________ @@ -1917,60 +2284,87 @@ struct HStrangeCorrelation { initEfficiencyFromCCDB(bc); } TH2F* hEfficiencyCascade[4]; - hEfficiencyCascade[0] = hEfficiencyXiMinus; - hEfficiencyCascade[1] = hEfficiencyXiPlus; - hEfficiencyCascade[2] = hEfficiencyOmegaMinus; - hEfficiencyCascade[3] = hEfficiencyOmegaPlus; - + THnF* hEfficiencyCascadeMultVsPhi[4]; + if (efficiencyFlags.applyEfficiencyCorrection) { + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + hEfficiencyCascadeMultVsPhi[0] = hEfficiencyXiMinusMultVsPhi; + hEfficiencyCascadeMultVsPhi[1] = hEfficiencyXiPlusMultVsPhi; + hEfficiencyCascadeMultVsPhi[2] = hEfficiencyOmegaMinusMultVsPhi; + hEfficiencyCascadeMultVsPhi[3] = hEfficiencyOmegaPlusMultVsPhi; + } else { + hEfficiencyCascade[0] = hEfficiencyXiMinus; + hEfficiencyCascade[1] = hEfficiencyXiPlus; + hEfficiencyCascade[2] = hEfficiencyOmegaMinus; + hEfficiencyCascade[3] = hEfficiencyOmegaPlus; + } + } for (auto const& casc : associatedCascades) { auto cascData = casc.cascData(); //---] syst cuts [--- - if (doPPAnalysis && (std::abs(cascData.dcapostopv()) < systCuts.dcapostopv || - std::abs(cascData.dcanegtopv()) < systCuts.dcanegtopv || - std::abs(cascData.dcabachtopv()) < systCuts.cascDcabachtopv || - cascData.dcaV0daughters() > systCuts.dcaV0dau || - cascData.dcacascdaughters() > systCuts.cascDcacascdau || - cascData.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.v0cospa || - cascData.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < systCuts.cascCospa || - cascData.cascradius() < systCuts.cascRadius || - std::abs(cascData.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < systCuts.cascMindcav0topv || - std::abs(cascData.mLambda() - o2::constants::physics::MassLambda0) > systCuts.cascV0masswindow)) + if (masterConfigurations.doPPAnalysis && (std::abs(cascData.dcapostopv()) < v0Selection.dcapostopv || + std::abs(cascData.dcanegtopv()) < v0Selection.dcanegtopv || + std::abs(cascData.dcabachtopv()) < cascadeSelections.dcaBachToPV || + cascData.dcaV0daughters() > cascadeSelections.cascdcaV0dau || + cascData.dcacascdaughters() > cascadeSelections.dcaCascDaughters || + cascData.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeSelections.cascv0cospa || + cascData.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascadeSelections.cascCospa || + cascData.cascradius() < cascadeSelections.cascRadius || + std::abs(cascData.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascadeSelections.cascdcaV0ToPV || + std::abs(cascData.mLambda() - o2::constants::physics::MassLambda0) > cascadeSelections.cascV0masswindow)) continue; - if (!doPPAnalysis && !CascadeSelectedPbPb(cascData, collision.posX(), collision.posY(), collision.posZ())) + if (!masterConfigurations.doPPAnalysis && !cascadeSelectedPbPb(cascData, collision.posX(), collision.posY(), collision.posZ())) continue; - uint64_t CascselMap = CascadeselectionBitmap(cascData, collision.posX(), collision.posY(), collision.posZ()); + uint64_t cascselMap = cascadeselectionBitmap(cascData, collision.posX(), collision.posY(), collision.posZ()); //---] 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) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated) + continue; + if (trackSelection.checksRequireTPCChi2 && (postrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || negtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated || bachtrack.tpcChi2NCl() < trackSelection.minTPCChi2PerClusterAssociated)) + continue; + if (trackSelection.requireClusterInITS && (postrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks || negtrack.itsNCls() < trackSelection.minITSClustersForDaughterTracks)) continue; static_for<0, 3>([&](auto i) { constexpr int Index = i.value; - if ((Index == 2 || Index == 3) && casc.compatible(Index, systCuts.dEdxCompatibility) && std::abs(casc.invMassNSigma(Index - 2)) < massWindowConfigurations.nSigmaNearXiMassCenter) { + if ((Index == IndexOmegaMinus || Index == IndexOmegaPlus) && casc.compatible(Index, trackSelection.dEdxCompatibility) && std::abs(casc.invMassNSigma(Index - 2)) < massWindowConfigurations.nSigmaNearXiMassCenter) { return; } float efficiency = 1.0f; if (efficiencyFlags.applyEfficiencyCorrection) { - efficiency = hEfficiencyCascade[Index]->Interpolate(cascData.pt(), cascData.eta()); + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + double bin[4] = {cascData.pt(), cascData.eta(), cascData.phi(), cent}; + efficiency = hEfficiencyCascadeMultVsPhi[Index]->GetBinContent(hEfficiencyCascadeMultVsPhi[Index]->GetBin(bin)); + } else { + efficiency = hEfficiencyCascade[Index]->Interpolate(cascData.pt(), cascData.eta()); + } } if (efficiency == 0) { // check for zero efficiency, do not apply if the case efficiency = 1; } float weight = efficiencyFlags.applyEfficiencyCorrection ? 1. / efficiency : 1.0f; - if (casc.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || casc.mcTrue(Index)) && (!doAssocPhysicalPrimary || casc.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { - if (TESTBIT(doCorrelation, Index + 3) && (doPPAnalysis || (TESTBIT(CascselMap, Index) && TESTBIT(CascselMap, Index + 4) && TESTBIT(CascselMap, Index + 8) && TESTBIT(CascselMap, Index + 12)))) { - histos.fill(HIST("h3d") + HIST(kCascadenames[Index]) + HIST("Spectrum"), cascData.pt(), cent, casc.invMassNSigma(Index), weight); + if (casc.compatible(Index, trackSelection.dEdxCompatibility) && (!masterConfigurations.doMCassociation || casc.mcTrue(Index)) && (!doAssocPhysicalPrimary || casc.mcPhysicalPrimary()) && (!efficiencyFlags.applyEfficiencyCorrection || efficiency != 0)) { + if (TESTBIT(doCorrelation, Index + 3) && (masterConfigurations.doPPAnalysis || (TESTBIT(cascselMap, Index) && TESTBIT(cascselMap, Index + 4) && TESTBIT(cascselMap, Index + 8) && TESTBIT(cascselMap, Index + 12)))) { + histos.fill(HIST("h3d") + HIST(Cascadenames[Index]) + HIST("Spectrum"), cascData.pt(), cent, casc.invMassNSigma(Index), weight); if (std::abs(cascData.rapidity(Index)) < ySel) { - histos.fill(HIST("h3d") + HIST(kCascadenames[Index]) + HIST("SpectrumY"), cascData.pt(), cent, casc.invMassNSigma(Index), weight); - } - if (-massWindowConfigurations.maxPeakNSigma < casc.invMassNSigma(Index) && casc.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { - histos.fill(HIST("h") + HIST(kCascadenames[Index]) + HIST("EtaVsPtVsPhi"), cascData.pt(), cascData.eta(), cascData.phi(), weight); + histos.fill(HIST("h3d") + HIST(Cascadenames[Index]) + HIST("SpectrumY"), cascData.pt(), cent, casc.invMassNSigma(Index), 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(kCascadenames[Index]) + HIST("EtaVsPtVsPhiBg"), cascData.pt(), cascData.eta(), cascData.phi(), weight); + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + 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); + } + } else { + if (-massWindowConfigurations.maxPeakNSigma < casc.invMassNSigma(Index) && casc.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { + histos.fill(HIST("h") + HIST(Cascadenames[Index]) + HIST("EtaVsPtVsPhiVsCent"), cascData.pt(), cascData.eta(), cascData.phi(), cent, 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("EtaVsPtVsPhiVsCentBg"), cascData.pt(), cascData.eta(), cascData.phi(), cent, weight); + } } } } @@ -1978,13 +2372,17 @@ struct HStrangeCorrelation { } for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); - if (!isValidTrigger(track)) + if (!isValidTrigger(track, triggerTrack.isLeading())) continue; histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), cent); histos.fill(HIST("hTriggerPtResolution"), track.pt(), triggerTrack.mcOriginalPt()); - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; - histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), cent); + if (!efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), cent); + } else { + histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), track.phi(), cent); + } if (track.sign() > 0) histos.fill(HIST("hPositiveTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), cent); else @@ -1994,8 +2392,8 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - cascade correlations - if (doFullCorrelationStudy) - fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsCascade(triggerTracks, associatedCascades, false, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHPions(soa::Join::iterator const& collision, soa::Join const& associatedPions, soa::Join const& triggerTracks, @@ -2034,7 +2432,7 @@ struct HStrangeCorrelation { histos.fill(HIST("hPionEtaVsPtAllSelected"), pionTrack.pt(), pionTrack.eta(), collision.centFT0M()); if (doAssocPhysicalPrimary && !pion.mcPhysicalPrimary()) continue; - if (doMCassociation && std::abs(pion.pdgCode()) != 211) + if (masterConfigurations.doMCassociation && std::abs(pion.pdgCode()) != PdgCodes[IndexPion]) continue; histos.fill(HIST("hPionEtaVsPt"), pionTrack.pt(), pionTrack.eta(), collision.centFT0M()); if (pionTrack.sign() > 0) @@ -2045,11 +2443,11 @@ struct HStrangeCorrelation { if (!doprocessSameEventHCascades && !doprocessSameEventHV0s) { for (auto const& triggerTrack : triggerTracks) { auto track = triggerTrack.track_as(); - if (!isValidTrigger(track)) + if (!isValidTrigger(track, triggerTrack.isLeading())) continue; histos.fill(HIST("hTriggerAllSelectedEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTriggerPtResolution"), track.pt(), triggerTrack.mcOriginalPt()); - if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) + if (masterConfigurations.doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) continue; histos.fill(HIST("hTriggerPrimaryEtaVsPt"), track.pt(), track.eta(), collision.centFT0M()); histos.fill(HIST("hTrackEtaVsPtVsPhi"), track.pt(), track.eta(), track.phi()); @@ -2058,7 +2456,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - Pion correlations - if (doFullCorrelationStudy) + if (masterConfigurations.doFullCorrelationStudy) fillCorrelationsHadron(triggerTracks, associatedPions, false, collision.posZ(), collision.centFT0M(), bField); } @@ -2067,7 +2465,7 @@ struct HStrangeCorrelation { TracksComplete const&, aod::BCsWithTimestamps const&) { BinningTypePP colBinning{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}; - for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, masterConfigurations.mixingParameter, -1, collisions, collisions)) { auto bc = collision1.bc_as(); auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ @@ -2103,7 +2501,7 @@ struct HStrangeCorrelation { auto slicedAssocHadrons = assocHadrons.sliceBy(collisionSliceHadrons, collision2.globalIndex()); // ________________________________________________ // Do hadron - hadron correlations - if (doFullCorrelationStudy) + if (masterConfigurations.doFullCorrelationStudy) fillCorrelationsHadron(slicedTriggerTracks, slicedAssocHadrons, true, collision1.posZ(), collision1.centFT0M(), bField); } } @@ -2113,15 +2511,15 @@ struct HStrangeCorrelation { V0DatasWithoutTrackX const&, TracksComplete const&, aod::BCsWithTimestamps const&) { std::variant colBinning = - doPPAnalysis + masterConfigurations.doPPAnalysis ? std::variant{ BinningTypePP{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}} : std::variant{BinningTypePbPb{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}}; std::visit([&](auto const& binning) { - for (auto const& [collision1, collision2] : soa::selfCombinations(binning, mixingParameter, -1, collisions, collisions)) { - double cent1 = doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); - double cent2 = doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); + for (auto const& [collision1, collision2] : soa::selfCombinations(binning, masterConfigurations.mixingParameter, -1, collisions, collisions)) { + double cent1 = masterConfigurations.doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); + double cent2 = masterConfigurations.doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); auto bc = collision1.template bc_as(); auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ @@ -2135,7 +2533,7 @@ struct HStrangeCorrelation { } // Perform basic event selection on both collisions - if ((doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!doPPAnalysis && (!isCollisionSelectedPbPb(collision1, true) || (!isCollisionSelectedPbPb(collision2, true))))) { + if ((masterConfigurations.doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision1, false) || (!isCollisionSelectedPbPb(collision2, false))))) { continue; } if (cent1 > axisRanges[5][1] || cent1 < axisRanges[5][0]) @@ -2157,8 +2555,8 @@ struct HStrangeCorrelation { auto slicedAssocV0s = associatedV0s.sliceBy(collisionSliceV0s, collision2.globalIndex()); // ________________________________________________ // Do hadron - V0 correlations - if (doFullCorrelationStudy) - fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, false, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } }, colBinning); @@ -2169,15 +2567,15 @@ struct HStrangeCorrelation { V0DatasWithoutTrackX const&, aod::CascDatas const&, TracksComplete const&, aod::BCsWithTimestamps const&) { std::variant colBinning = - doPPAnalysis + masterConfigurations.doPPAnalysis ? std::variant{ BinningTypePP{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}} : std::variant{BinningTypePbPb{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}}; std::visit([&](auto const& binning) { - for (auto const& [collision1, collision2] : soa::selfCombinations(binning, mixingParameter, -1, collisions, collisions)) { - double cent1 = doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); - double cent2 = doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); + for (auto const& [collision1, collision2] : soa::selfCombinations(binning, masterConfigurations.mixingParameter, -1, collisions, collisions)) { + double cent1 = masterConfigurations.doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); + double cent2 = masterConfigurations.doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); // ________________________________________________ auto bc = collision1.template bc_as(); auto bField = getMagneticField(bc.timestamp()); @@ -2191,7 +2589,7 @@ struct HStrangeCorrelation { } // Perform basic event selection on both collisions - if ((doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!doPPAnalysis && (!isCollisionSelectedPbPb(collision1, true) || (!isCollisionSelectedPbPb(collision2, true))))) { + if ((masterConfigurations.doPPAnalysis && (!isCollisionSelected(collision1) || !isCollisionSelected(collision2))) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision1, false) || (!isCollisionSelectedPbPb(collision2, false))))) { continue; } if (cent1 > axisRanges[5][1] || cent1 < axisRanges[5][0]) @@ -2212,8 +2610,8 @@ struct HStrangeCorrelation { auto slicedAssocCascades = associatedCascades.sliceBy(collisionSliceCascades, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - if (doFullCorrelationStudy) - fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, false, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } }, colBinning); @@ -2224,7 +2622,7 @@ struct HStrangeCorrelation { TracksComplete const&, aod::BCsWithTimestamps const&) { BinningTypePP colBinning{{axesConfigurations.axisVtxZ, axesConfigurations.axisMult}, true}; - for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, masterConfigurations.mixingParameter, -1, collisions, collisions)) { auto bc = collision1.bc_as(); auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ @@ -2260,12 +2658,12 @@ struct HStrangeCorrelation { auto slicedAssocPions = assocPions.sliceBy(collisionSliceHadrons, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - if (doFullCorrelationStudy) + if (masterConfigurations.doFullCorrelationStudy) fillCorrelationsHadron(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M(), bField); } } - void processMCGenerated(aod::McCollision const& /*mcCollision*/, 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); @@ -2276,13 +2674,13 @@ struct HStrangeCorrelation { } double gpt = mcParticle.pt(); if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { - if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (!masterConfigurations.doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { histos.fill(HIST("hGeneratedQAPtTrigger"), gpt, 0.0f); // step 1: before all selections } } if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { - if (mcParticle.pdgCode() == PDG_t::kK0Short && doCorrelationK0Short) { + if (mcParticle.pdgCode() == PDG_t::kK0Short && masterConfigurations.doCorrelationK0Short) { histos.fill(HIST("hGeneratedQAPtAssociatedK0"), gpt, 0.0f); // step 1: before all selections } } @@ -2293,18 +2691,10 @@ struct HStrangeCorrelation { continue; static_for<0, 7>([&](auto i) { constexpr int Index = i.value; - if (i == 0 || i == 7) { - if (std::abs(mcParticle.pdgCode()) == kPdgCodes[i]) { - histos.fill(HIST("Generated/h") + HIST(kParticlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); - if (i == 7 && mcParticle.pdgCode() > 0) - histos.fill(HIST("Generated/hPositive") + HIST(kParticlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); - else if (i == 7 && mcParticle.pdgCode() < 0) - histos.fill(HIST("Generated/hNegative") + HIST(kParticlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); - } - } else { - if (mcParticle.pdgCode() == kPdgCodes[i]) - histos.fill(HIST("Generated/h") + HIST(kParticlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); - } + if (i == IndexPion && mcParticle.pdgCode() > Neutral) + histos.fill(HIST("Generated/hPositive") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); + else if (i == IndexPion && mcParticle.pdgCode() < Neutral) + histos.fill(HIST("Generated/hNegative") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), 1); }); } if (collisions.size() < 1) @@ -2313,18 +2703,25 @@ struct HStrangeCorrelation { // determine best collision properties int biggestNContribs = -1; int bestCollisionFT0Mpercentile = -1; + int bestCollisionFT0Cpercentile = -1; float bestCollisionVtxZ = 0.0f; bool bestCollisionSel8 = false; bool bestCollisionINELgtZERO = false; + bool isCollisionSelect = false; uint32_t bestCollisionTriggerPresenceMap = 0; for (auto const& collision : collisions) { if (biggestNContribs < collision.numContrib()) { biggestNContribs = collision.numContrib(); bestCollisionFT0Mpercentile = collision.centFT0M(); - bestCollisionSel8 = collision.sel8(); - bestCollisionVtxZ = collision.posZ(); - bestCollisionINELgtZERO = collision.isInelGt0(); + bestCollisionFT0Cpercentile = collision.centFT0C(); + if (masterConfigurations.applyNewMCSelection) { + isCollisionSelect = ((masterConfigurations.doPPAnalysis && isCollisionSelected(collision)) || (!masterConfigurations.doPPAnalysis && isCollisionSelectedPbPb(collision, false))); + } else { + bestCollisionSel8 = collision.sel8(); + bestCollisionVtxZ = collision.posZ(); + bestCollisionINELgtZERO = collision.isInelGt0(); + } if (triggerPresenceMap.size() > 0) bestCollisionTriggerPresenceMap = triggerPresenceMap[collision.globalIndex()]; } @@ -2338,14 +2735,9 @@ struct HStrangeCorrelation { continue; static_for<0, 7>([&](auto i) { constexpr int Index = i.value; - if (i == 0 || i == 7) { - if (std::abs(mcParticle.pdgCode()) == kPdgCodes[i]) { - histos.fill(HIST("GeneratedWithPV/h") + HIST(kParticlenames[Index]) + HIST("_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); - } - } else { - if (mcParticle.pdgCode() == kPdgCodes[i]) - histos.fill(HIST("GeneratedWithPV/h") + HIST(kParticlenames[Index]) + HIST("_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); - } + + if (mcParticle.pdgCode() == PdgCodes[i]) + histos.fill(HIST("GeneratedWithPV/h") + HIST(Particlenames[Index]) + HIST("_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); }); } } @@ -2359,12 +2751,17 @@ struct HStrangeCorrelation { if (triggerPresenceMap.size() > 0 && !TESTBIT(bestCollisionTriggerPresenceMap, triggerBinToSelect)) { return; } - if (!bestCollisionSel8) - return; - if (std::abs(bestCollisionVtxZ) > 10.0f) - return; - if (!bestCollisionINELgtZERO) - return; + if (masterConfigurations.applyNewMCSelection) { + if (!isCollisionSelect) + return; + } else { + if (!bestCollisionSel8) + return; + if (std::abs(bestCollisionVtxZ) > masterConfigurations.zVertexCut) + return; + if (!bestCollisionINELgtZERO) + return; + } histos.fill(HIST("hClosureTestEventCounter"), 3.5f); @@ -2375,13 +2772,13 @@ struct HStrangeCorrelation { } double gpt = mcParticle.pt(); if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { - if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (!masterConfigurations.doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { histos.fill(HIST("hGeneratedQAPtTrigger"), gpt, 1.0f); // step 2: after event selection } } if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { - if (mcParticle.pdgCode() == PDG_t::kK0Short && doCorrelationK0Short) { + if (mcParticle.pdgCode() == PDG_t::kK0Short && masterConfigurations.doCorrelationK0Short) { histos.fill(HIST("hGeneratedQAPtAssociatedK0"), gpt, 1.0f); // step 2: before all selections } } @@ -2394,7 +2791,11 @@ struct HStrangeCorrelation { double geta = mcParticle.eta(); double gpt = mcParticle.pt(); if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { - histos.fill(HIST("GeneratedWithPV/hTrigger"), gpt, geta, bestCollisionFT0Mpercentile); + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.fill(HIST("GeneratedWithPV/hTrigger"), gpt, geta, mcParticle.phi(), bestCollisionFT0Mpercentile); + } else { + histos.fill(HIST("GeneratedWithPV/hTrigger"), gpt, geta, bestCollisionFT0Cpercentile); + } if (mcParticle.pdgCode() > 0) histos.fill(HIST("GeneratedWithPV/hPositiveTrigger"), gpt, geta, bestCollisionFT0Mpercentile); else @@ -2411,11 +2812,11 @@ struct HStrangeCorrelation { if (std::abs(lamParticleMother.eta()) > etaSel) { continue; } - if (lamParticleMother.pdgCode() == PDG_t::kXiMinus) // Xi Minus Mother Matched + if (doprocessFeedDown && lamParticleMother.pdgCode() == PDG_t::kXiMinus) // Xi Minus Mother Matched { histos.fill(HIST("GeneratedWithPV/hLambdaFromXiMinus"), gpt, geta); } - if (lamParticleMother.pdgCode() == o2::constants::physics::Pdg::kXi0) // Xi Zero Mother Matched + if (doprocessFeedDown && lamParticleMother.pdgCode() == o2::constants::physics::Pdg::kXi0) // Xi Zero Mother Matched { histos.fill(HIST("GeneratedWithPV/hLambdaFromXiZero"), gpt, geta); } @@ -2432,10 +2833,10 @@ struct HStrangeCorrelation { if (std::abs(lamParticleMother.eta()) > etaSel) { continue; } - if (lamParticleMother.pdgCode() == PDG_t::kXiPlusBar) { + if (doprocessFeedDown && lamParticleMother.pdgCode() == PDG_t::kXiPlusBar) { histos.fill(HIST("GeneratedWithPV/hAntiLambdaFromXiPlus"), gpt, geta); } - if (lamParticleMother.pdgCode() == -o2::constants::physics::Pdg::kXi0) // Xi Zero Mother Matched + if (doprocessFeedDown && lamParticleMother.pdgCode() == -o2::constants::physics::Pdg::kXi0) // Xi Zero Mother Matched { histos.fill(HIST("GeneratedWithPV/hAntiLambdaFromXiZero"), gpt, geta); } @@ -2444,23 +2845,20 @@ struct HStrangeCorrelation { } static_for<0, 7>([&](auto i) { constexpr int Index = i.value; - if (i == 0 || i == 7) { - if (std::abs(mcParticle.pdgCode()) == kPdgCodes[i]) { - histos.fill(HIST("GeneratedWithPV/h") + HIST(kParticlenames[Index]), gpt, geta, bestCollisionFT0Mpercentile); - if (std::abs(mcParticle.y()) < ySel) - histos.fill(HIST("GeneratedWithPV/h") + HIST(kParticlenames[Index]) + HIST("_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); - if (i == 7 && mcParticle.pdgCode() > 0) - histos.fill(HIST("GeneratedWithPV/hPositive") + HIST(kParticlenames[Index]), mcParticle.pt(), mcParticle.eta(), bestCollisionFT0Mpercentile); - else if (i == 7 && mcParticle.pdgCode() < 0) - histos.fill(HIST("GeneratedWithPV/hNegative") + HIST(kParticlenames[Index]), mcParticle.pt(), mcParticle.eta(), bestCollisionFT0Mpercentile); - } + if (i == IndexPion && mcParticle.pdgCode() == PdgCodes[i] && mcParticle.pdgCode() > Neutral) { + histos.fill(HIST("GeneratedWithPV/hPositive") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), bestCollisionFT0Mpercentile); + } else if (i == IndexPion && mcParticle.pdgCode() == PdgCodes[i] && mcParticle.pdgCode() < Neutral) { + histos.fill(HIST("GeneratedWithPV/hNegative") + HIST(Particlenames[Index]), mcParticle.pt(), mcParticle.eta(), bestCollisionFT0Mpercentile); + } - } else { - if (mcParticle.pdgCode() == kPdgCodes[i]) { - histos.fill(HIST("GeneratedWithPV/h") + HIST(kParticlenames[Index]), gpt, geta, bestCollisionFT0Mpercentile); - if (std::abs(mcParticle.y()) < ySel) - histos.fill(HIST("GeneratedWithPV/h") + HIST(kParticlenames[Index]) + HIST("_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == PdgCodes[i]) { + if (efficiencyFlags.applyEffAsFunctionOfMultAndPhi) { + histos.fill(HIST("GeneratedWithPV/h") + HIST(Particlenames[Index]), gpt, geta, mcParticle.phi(), bestCollisionFT0Cpercentile); + } else { + histos.fill(HIST("GeneratedWithPV/h") + HIST(Particlenames[Index]), gpt, geta, bestCollisionFT0Mpercentile); } + if (std::abs(mcParticle.y()) < ySel) + histos.fill(HIST("GeneratedWithPV/h") + HIST(Particlenames[Index]) + HIST("_MidYVsMult"), gpt, bestCollisionFT0Mpercentile); } }); } @@ -2487,13 +2885,13 @@ struct HStrangeCorrelation { } double gpt = mcParticle.pt(); if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { - if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (!masterConfigurations.doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { histos.fill(HIST("hClosureQAPtTrigger"), gpt, 0.0f); // step 1: no event selection whatsoever } } if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { - if (mcParticle.pdgCode() == PDG_t::kK0Short && doCorrelationK0Short) { + if (mcParticle.pdgCode() == PDG_t::kK0Short && masterConfigurations.doCorrelationK0Short) { histos.fill(HIST("hClosureQAPtAssociatedK0"), gpt, 0.0f); // step 1: no event selection whatsoever } } @@ -2525,10 +2923,10 @@ struct HStrangeCorrelation { return; } - if (doGenEventSelection) { + if (masterConfigurations.doGenEventSelection) { if (!bestCollisionSel8) return; - if (std::abs(bestCollisionVtxZ) > zVertexCut) + if (std::abs(bestCollisionVtxZ) > masterConfigurations.zVertexCut) return; if (!bestCollisionINELgtZERO) return; @@ -2546,13 +2944,13 @@ struct HStrangeCorrelation { } double gpt = mcParticle.pt(); if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { - if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (!masterConfigurations.doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { histos.fill(HIST("hClosureQAPtTrigger"), gpt, 1.0f); // step 2: after event selection } } if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { - if (mcParticle.pdgCode() == PDG_t::kK0Short && doCorrelationK0Short) { + if (mcParticle.pdgCode() == PDG_t::kK0Short && masterConfigurations.doCorrelationK0Short) { histos.fill(HIST("hClosureQAPtAssociatedK0"), gpt, 1.0f); // step 2: after event selection } } @@ -2568,11 +2966,11 @@ struct HStrangeCorrelation { continue; } if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus || std::abs(mcParticle.pdgCode()) == PDG_t::kProton || std::abs(mcParticle.pdgCode()) == PDG_t::kElectron || std::abs(mcParticle.pdgCode()) == PDG_t::kMuonMinus) { - if (!doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { + if (!masterConfigurations.doTriggPhysicalPrimary || mcParticle.isPhysicalPrimary()) { triggerIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hTrigger"), gpt, geta, bestCollisionFT0Mpercentile); } - if (doCorrelationHadron) { + if (masterConfigurations.doCorrelationHadron) { if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { assocHadronIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hHadron"), gpt, geta, gphi); @@ -2580,35 +2978,35 @@ struct HStrangeCorrelation { } } if (!doAssocPhysicalPrimary || mcParticle.isPhysicalPrimary()) { - if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus && doCorrelationPion) { + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus && masterConfigurations.doCorrelationPion) { piIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hPion"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kK0Short && doCorrelationK0Short) { + if (mcParticle.pdgCode() == PDG_t::kK0Short && masterConfigurations.doCorrelationK0Short) { k0ShortIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hK0Short"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kLambda0 && doCorrelationLambda) { + if (mcParticle.pdgCode() == PDG_t::kLambda0 && masterConfigurations.doCorrelationLambda) { lambdaIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hLambda"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kLambda0Bar && doCorrelationAntiLambda) { + if (mcParticle.pdgCode() == PDG_t::kLambda0Bar && masterConfigurations.doCorrelationAntiLambda) { antiLambdaIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hAntiLambda"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kXiMinus && doCorrelationXiMinus) { + if (mcParticle.pdgCode() == PDG_t::kXiMinus && masterConfigurations.doCorrelationXiMinus) { xiMinusIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hXiMinus"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kXiPlusBar && doCorrelationXiPlus) { + if (mcParticle.pdgCode() == PDG_t::kXiPlusBar && masterConfigurations.doCorrelationXiPlus) { xiPlusIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hXiPlus"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kOmegaMinus && doCorrelationOmegaMinus) { + if (mcParticle.pdgCode() == PDG_t::kOmegaMinus && masterConfigurations.doCorrelationOmegaMinus) { omegaMinusIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hOmegaMinus"), gpt, geta, gphi); } - if (mcParticle.pdgCode() == PDG_t::kOmegaPlusBar && doCorrelationOmegaPlus) { + if (mcParticle.pdgCode() == PDG_t::kOmegaPlusBar && masterConfigurations.doCorrelationOmegaPlus) { omegaPlusIndices.emplace_back(iteratorNum); histos.fill(HIST("ClosureTest/hOmegaPlus"), gpt, geta, gphi); } @@ -2655,7 +3053,7 @@ struct HStrangeCorrelation { if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; if (TESTBIT(doCorrelation, i)) - histos.fill(HIST("ClosureTest/sameEvent/") + HIST(kParticlenames[Index]), computeDeltaPhi(gphitrigger, gphiassoc), deltaeta, ptassoc, pttrigger, bestCollisionVtxZ, bestCollisionFT0Mpercentile); + histos.fill(HIST("ClosureTest/sameEvent/") + HIST(Particlenames[Index]), computeDeltaPhi(gphitrigger, gphiassoc), deltaeta, ptassoc, pttrigger, bestCollisionVtxZ, bestCollisionFT0Mpercentile); } } }); @@ -2677,13 +3075,13 @@ struct HStrangeCorrelation { //---] track quality check [--- auto postrack = v0Data.posTrack_as(); auto negtrack = v0Data.negTrack_as(); - if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) + if (postrack.tpcNClsCrossedRows() < trackSelection.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < trackSelection.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) + if (v0Data.v0radius() < v0Selection.v0RadiusMin || v0Data.v0radius() > v0Selection.v0RadiusMax || + std::abs(v0Data.dcapostopv()) < v0Selection.dcapostopv || std::abs(v0Data.dcanegtopv()) < v0Selection.dcanegtopv || + v0Data.v0cosPA() < v0Selection.v0cospa || v0Data.dcaV0daughters() > v0Selection.dcaV0dau) continue; if (v0Data.has_mcParticle()) { @@ -2741,6 +3139,63 @@ struct HStrangeCorrelation { } } } + void processMixedEventHV0sInBuffer(soa::Join::iterator const& collision, + aod::AssocV0s const& associatedV0s, aod::TriggerTracks const& triggerTracks, + V0DatasWithoutTrackX const&, TracksComplete const&, aod::BCsWithTimestamps const&) + { + + double cent = masterConfigurations.doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + + auto bc = collision.template bc_as(); + auto bField = getMagneticField(bc.timestamp()); + // ________________________________________________ + if (efficiencyFlags.applyEfficiencyCorrection) { + initEfficiencyFromCCDB(bc); + } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + + // Perform basic event selection on both collisions + if (((masterConfigurations.doPPAnalysis && !isCollisionSelected(collision))) || (!masterConfigurations.doPPAnalysis && !isCollisionSelectedPbPb(collision, true))) { + return; + } + if (cent > axisRanges[5][1] || cent < axisRanges[5][0]) + return; + + // ________________________________________________ + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsV0(triggerTracks, associatedV0s, true, true, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + } + void processMixedEventHCascadesInBuffer(soa::Join::iterator const& collision, + aod::AssocV0s const&, aod::AssocCascades const& associatedCascades, aod::TriggerTracks const& triggerTracks, + V0DatasWithoutTrackX const&, aod::CascDatas const&, TracksComplete const&, aod::BCsWithTimestamps const&) + { + double cent = masterConfigurations.doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + // ________________________________________________ + auto bc = collision.template bc_as(); + auto bField = getMagneticField(bc.timestamp()); + if (efficiencyFlags.applyEfficiencyCorrection) { + initEfficiencyFromCCDB(bc); + } + // ________________________________________________ + // skip if desired trigger not found + if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { + return; + } + // Perform basic event selection on both collisions + if ((masterConfigurations.doPPAnalysis && !isCollisionSelected(collision)) || (!masterConfigurations.doPPAnalysis && (!isCollisionSelectedPbPb(collision, true)))) { + return; + } + if (cent > axisRanges[5][1] || cent < axisRanges[5][0]) + return; + // ________________________________________________ + // Do hadron - cascade correlations + if (masterConfigurations.doFullCorrelationStudy) + fillCorrelationsCascade(triggerTracks, associatedCascades, true, true, collision.posX(), collision.posY(), collision.posZ(), cent, bField); + } PROCESS_SWITCH(HStrangeCorrelation, processSelectEventWithTrigger, "Select events with trigger only", true); PROCESS_SWITCH(HStrangeCorrelation, processSameEventHV0s, "Process same events, h-V0s", true); PROCESS_SWITCH(HStrangeCorrelation, processSameEventHCascades, "Process same events, h-Cascades", true); @@ -2751,6 +3206,8 @@ struct HStrangeCorrelation { PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHCascades, "Process mixed events, h-Cascades", true); PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHPions, "Process mixed events, h-Pion", true); PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHHadrons, "Process mixed events, h-h", true); + PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHV0sInBuffer, "Process mixed events in buffer, h-h", true); + PROCESS_SWITCH(HStrangeCorrelation, processMixedEventHCascadesInBuffer, "Process mixed events in buffer, h-h", true); PROCESS_SWITCH(HStrangeCorrelation, processMCGenerated, "Process MC generated", false); PROCESS_SWITCH(HStrangeCorrelation, processClosureTest, "Process Closure Test", false); diff --git a/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx new file mode 100644 index 00000000000..dcf28b07b7f --- /dev/null +++ b/PWGLF/Tasks/Strangeness/lambdaJetPolarizationIonsDerived.cxx @@ -0,0 +1,782 @@ +// 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 lambdajetpolarizationionsderived.cxx +/// \brief Lambda and antiLambda polarization analysis task using derived data +/// +/// \author Cicero Domenico Muncinelli , Campinas State University +// +// Jet Polarization Ions task -- Derived data +// ================ +// +// This code loops over custom derived data tables defined on +// lambdaJetPolarizationIons.h (JetsRing, LambdaLikeV0sRing). +// From this derived data, calculates polarization on an EbE +// basis (see TProfiles). +// Signal extraction is done out of the framework, based on +// the AnalysisResults of this code. +// +// +// Comments, questions, complaints, suggestions? +// Please write to: +// cicero.domenico.muncinelli@cern.ch +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Custom data model: +#include "PWGLF/DataModel/lambdaJetPolarizationIons.h" + +#include +#include +#include +#include + +// #include +// #include +// New recommended format: +#include // clang-tidy usually confuses this! Careful! +#include +#include +#include +#include // For perpendicular jet direction QAs + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using ROOT::Math::PtEtaPhiMVector; +using ROOT::Math::XYZVector; +// using namespace o2::aod::lambdajetpol; // Used it explicitly along the code for clarity + +// Declaring constants: +constexpr double protonMass = o2::constants::physics::MassProton; // Assumes particle identification for daughter is perfect +constexpr double lambdaWeakDecayConstant = 0.749; // DPG 2025 update +constexpr double antiLambdaWeakDecayConstant = -0.758; // DPG 2025 update +constexpr double polPrefactorLambda = 3.0 / lambdaWeakDecayConstant; +constexpr double polPrefactorAntiLambda = 3.0 / antiLambdaWeakDecayConstant; + +enum CentEstimator { + kCentFT0C = 0, + kCentFT0M, + kCentFV0A +}; + +// Helper macro to avoid writing the histogram fills 4 times for about 20 histograms: +#define RING_OBSERVABLE_FILL_LIST(X, FOLDER) \ + /* Counters */ \ + X(FOLDER "/QA/hDeltaPhi", deltaPhiJet) \ + X(FOLDER "/QA/hDeltaTheta", deltaThetaJet) \ + X(FOLDER "/QA/hIntegrated", 0.) \ + /* Lambda pT variation -- Youpeng's proposal */ \ + X(FOLDER "/QA/hLambdaPt", v0pt) \ + /* Counters */ \ + X(FOLDER "/QA/h2dDeltaPhiVsLambdaPt", deltaPhiJet, v0pt) \ + X(FOLDER "/QA/h2dDeltaThetaVsLambdaPt", deltaThetaJet, v0pt) \ + /* Additional plots for instant gratification - 1D Profiles */ \ + X(FOLDER "/pRingObservableDeltaPhi", deltaPhiJet, ringObservable) \ + X(FOLDER "/pRingObservableDeltaTheta", deltaThetaJet, ringObservable) \ + X(FOLDER "/pRingObservableIntegrated", 0., ringObservable) \ + X(FOLDER "/pRingObservableLambdaPt", v0pt, ringObservable) \ + /* 2D Profiles */ \ + X(FOLDER "/p2dRingObservableDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaThetaVsLambdaPt", deltaThetaJet, v0pt, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaPhiVsLeadJetPt", deltaPhiJet, leadingJetPt, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaThetaVsLeadJetPt", deltaThetaJet, leadingJetPt, ringObservable) \ + /* 1D Mass */ \ + X(FOLDER "/QA/hMass", v0LambdaLikeMass) \ + X(FOLDER "/QA/hRingObservableNumMass", v0LambdaLikeMass, ringObservable) \ + X(FOLDER "/hMassSigExtract", v0LambdaLikeMass) \ + /* Counters */ \ + X(FOLDER "/QA/h2dDeltaPhiVsMass", deltaPhiJet, v0LambdaLikeMass) \ + X(FOLDER "/QA/h2dDeltaThetaVsMass", deltaThetaJet, v0LambdaLikeMass) \ + X(FOLDER "/QA/h3dDeltaPhiVsMassVsLambdaPt", deltaPhiJet, v0LambdaLikeMass, v0pt) \ + X(FOLDER "/QA/h3dDeltaThetaVsMassVsLambdaPt", deltaThetaJet, v0LambdaLikeMass, v0pt) \ + X(FOLDER "/QA/h3dDeltaPhiVsMassVsLeadJetPt", deltaPhiJet, v0LambdaLikeMass, leadingJetPt) \ + X(FOLDER "/QA/h3dDeltaThetaVsMassVsLeadJetPt", deltaThetaJet, v0LambdaLikeMass, leadingJetPt) \ + X(FOLDER "/QA/h3dDeltaPhiVsMassVsCent", deltaPhiJet, v0LambdaLikeMass, centrality) \ + X(FOLDER "/QA/h3dDeltaThetaVsMassVsCent", deltaThetaJet, v0LambdaLikeMass, centrality) \ + /* TProfile of Ring vs Mass */ \ + X(FOLDER "/pRingObservableMass", v0LambdaLikeMass, ringObservable) \ + /* TProfile of Ring vs Mass -- Leading Particle and 2nd-to-leading jet - QA */ \ + X(FOLDER "/pRingObservableLeadPMass", v0LambdaLikeMass, ringObservableLeadP) \ + X(FOLDER "/pRingObservable2ndJetMass", v0LambdaLikeMass, ringObservable2ndJet) \ + /* 2D Profiles: Angle vs Mass */ \ + X(FOLDER "/p2dRingObservableDeltaPhiVsMass", deltaPhiJet, v0LambdaLikeMass, ringObservable) \ + X(FOLDER "/p2dRingObservableDeltaThetaVsMass", deltaThetaJet, v0LambdaLikeMass, ringObservable) \ + /* 3D Profiles: Angle vs Mass vs Lambda pT */ \ + X(FOLDER "/p3dRingObservableDeltaPhiVsMassVsLambdaPt", deltaPhiJet, v0LambdaLikeMass, v0pt, ringObservable) \ + X(FOLDER "/p3dRingObservableDeltaThetaVsMassVsLambdaPt", deltaThetaJet, v0LambdaLikeMass, v0pt, ringObservable) \ + /* 3D Profiles: Angle vs Mass vs Lead Jet pT */ \ + X(FOLDER "/p3dRingObservableDeltaPhiVsMassVsLeadJetPt", deltaPhiJet, v0LambdaLikeMass, leadingJetPt, ringObservable) \ + X(FOLDER "/p3dRingObservableDeltaThetaVsMassVsLeadJetPt", deltaThetaJet, v0LambdaLikeMass, leadingJetPt, ringObservable) \ + /* 2D Profile: Mass vs Centrality */ \ + X(FOLDER "/p2dRingObservableMassVsCent", v0LambdaLikeMass, centrality, ringObservable) \ + /* 3D Profiles: Angle vs Mass vs Centrality */ \ + X(FOLDER "/p3dRingObservableDeltaPhiVsMassVsCent", deltaPhiJet, v0LambdaLikeMass, centrality, ringObservable) \ + X(FOLDER "/p3dRingObservableDeltaThetaVsMassVsCent", deltaThetaJet, v0LambdaLikeMass, centrality, ringObservable) \ + X(FOLDER "/pRingIntVsCentrality", centrality, ringObservable) +// (TODO: add counters for regular TH2Ds about centrality) + +// For leading particle +#define RING_OBSERVABLE_LEADP_FILL_LIST(X, FOLDER) \ + X(FOLDER "/pRingObservableLeadPDeltaPhi", deltaPhiLeadP, ringObservableLeadP) \ + X(FOLDER "/pRingObservableLeadPDeltaTheta", deltaThetaLeadP, ringObservableLeadP) \ + X(FOLDER "/pRingObservableLeadPIntegrated", 0., ringObservableLeadP) \ + X(FOLDER "/pRingObservableLeadPLambdaPt", v0pt, ringObservableLeadP) + +// For subleading jet: +#define RING_OBSERVABLE_2NDJET_FILL_LIST(X, FOLDER) \ + X(FOLDER "/pRingObservable2ndJetDeltaPhi", deltaPhi2ndJet, ringObservable2ndJet) \ + X(FOLDER "/pRingObservable2ndJetDeltaTheta", deltaTheta2ndJet, ringObservable2ndJet) \ + X(FOLDER "/pRingObservable2ndJetIntegrated", 0., ringObservable2ndJet) \ + X(FOLDER "/pRingObservable2ndJetLambdaPt", v0pt, ringObservable2ndJet) + +#define POLARIZATION_PROFILE_FILL_LIST(X, FOLDER) \ + /* =============================== */ \ + /* 1D TProfiles vs v0phi */ \ + /* =============================== */ \ + X(FOLDER "/QA/pPxStarPhi", v0phiToFillHists, PolStarX) \ + X(FOLDER "/QA/pPyStarPhi", v0phiToFillHists, PolStarY) \ + X(FOLDER "/QA/pPzStarPhi", v0phiToFillHists, PolStarZ) \ + /* =============================== */ \ + /* 1D TProfiles vs DeltaPhi_jet */ \ + /* =============================== */ \ + X(FOLDER "/QA/pPxStarDeltaPhi", deltaPhiJet, PolStarX) \ + X(FOLDER "/QA/pPyStarDeltaPhi", deltaPhiJet, PolStarY) \ + X(FOLDER "/QA/pPzStarDeltaPhi", deltaPhiJet, PolStarZ) \ + /* =============================== */ \ + /* 2D TProfiles vs DeltaPhi_jet and Lambda pT */ \ + /* =============================== */ \ + X(FOLDER "/QA/p2dPxStarDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, PolStarX) \ + X(FOLDER "/QA/p2dPyStarDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, PolStarY) \ + X(FOLDER "/QA/p2dPzStarDeltaPhiVsLambdaPt", deltaPhiJet, v0pt, PolStarZ) + +// Apply the macros (notice I had to include the semicolon (";") after the function, so you don't need to +// write that when calling this APPLY_HISTO_FILL. The code will look weird, but without this the compiler +// would not know to end each statement with a semicolon): +#define APPLY_HISTO_FILL(NAME, ...) histos.fill(HIST(NAME), __VA_ARGS__); + +struct lambdajetpolarizationionsderived { + + // Define histogram registries: + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Master analysis switches + Configurable analyseLambda{"analyseLambda", true, "process Lambda-like candidates"}; + Configurable analyseAntiLambda{"analyseAntiLambda", false, "process AntiLambda-like candidates"}; + Configurable doPPAnalysis{"doPPAnalysis", false, "if in pp, set to true. Default is HI"}; + + // Centrality: + Configurable centralityEstimator{"centralityEstimator", kCentFT0M, "Run 3 centrality estimator (0:CentFT0C, 1:CentFT0M, 2:CentFV0A)"}; // Default is FT0M + + // QAs that purposefully break the analysis + // -- All of these tests should give us zero signal if the source is truly Lambda Polarization from vortices + Configurable forcePolSignQA{"forcePolSignQA", false, "force antiLambda decay constant to be positive: should kill all the signal, if any. For QA"}; + Configurable forcePerpToJet{"forcePerpToJet", false, "force jet direction to be perpendicular to jet estimator. For QA"}; + Configurable forceJetDirectionSmudge{"forceJetDirectionSmudge", false, "fluctuate jet direction by 10% of R around original axis. For QA (tests sensibility)"}; + Configurable jetRForSmuding{"jetRForSmuding", 0.4, "QA quantity: the chosen R scale for the jet direction smudge"}; + + ///////////////////////// + // Configurable blocks: + // Histogram axes configuration: + struct : ConfigurableGroup { + std::string prefix = "axisConfigurations"; // JSON group name + 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 analysis"}; + ConfigurableAxis axisPtCoarseQA{"axisPtCoarse", {VARIABLE_WIDTH, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 7.0f, 10.0f, 15.0f}, "pt axis for QA"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {450, 1.08f, 1.15f}, "Lambda mass in GeV/c"}; // Default is {200, 1.101f, 1.131f} + + // Jet axes: + ConfigurableAxis axisLeadingParticlePt{"axisLeadingParticlePt", {100, 0.f, 200.f}, "Leading particle p_{T} (GeV/c)"}; // Simpler version! + ConfigurableAxis axisJetPt{"axisJetPt", {50, 0.f, 200.f}, "Jet p_{t} (GeV)"}; + ConfigurableAxis axisDeltaTheta{"axisDeltaTheta", {40, 0, constants::math::PI}, "#Delta #theta_{jet}"}; + ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {40, -constants::math::PI, constants::math::PI}, "#Delta #phi_{jet}"}; + + // Coarser axes for signal extraction: + ConfigurableAxis axisPtSigExtract{"axisPtSigExtract", {VARIABLE_WIDTH, 0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 2.0f, 2.5f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 15.0f, 20.0f, 30.0f, 50.0f}, "pt axis for signal extraction"}; + // ConfigurableAxis axisLambdaMassSigExtract{"axisLambdaMassSigExtract", {175, 1.08f, 1.15f}, "Lambda mass in GeV/c"}; // With a sigma of 0.002 GeV/c, this has about 5 bins per sigma, so that the window is properly grasped. + // A coarser axis (sigma is still well estimated, with about 8 bins in the peak region) + ConfigurableAxis axisLambdaMassSigExtract{ + "axisLambdaMassSigExtract", + {VARIABLE_WIDTH, + // Left sideband (7 bins, 0.004 width) + 1.0800, 1.0840, 1.0880, 1.0920, + 1.0960, 1.1000, 1.1040, 1.1080, + // Fine peak region (8 bins, 0.0016 width) + 1.1096, 1.1112, 1.1128, 1.1144, + 1.1160, 1.1176, 1.1192, 1.1208, + // Right sideband (7 bins, 0.004 width) + 1.1248, 1.1288, 1.1328, 1.1368, + 1.1408, 1.1448, 1.1488}, + "Lambda mass in GeV/c"}; + ConfigurableAxis axisLeadingParticlePtSigExtract{"axisLeadingParticlePtSigExtract", {VARIABLE_WIDTH, 0, 4, 8, 12, 16, 20, 25, 30, 35, 40, 60, 100, 200}, "Leading particle p_{T} (GeV/c)"}; // Simpler version! + ConfigurableAxis axisJetPtSigExtract{"axisJetPtSigExtract", {VARIABLE_WIDTH, 0, 5, 10, 12, 16, 20, 25, 30, 35, 40, 60, 100, 200}, "Jet p_{t} (GeV)"}; + + // (TODO: add a lambdaPt axis that is pre-selected only on the 0.5 to 1.5 Pt region for the Ring observable with lambda cuts to not store a huge histogram with empty bins by construction) + + ConfigurableAxis axisCentrality{"axisCentrality", {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}, "Centrality"}; + } axisConfigurations; + + // Helper functions: + // Fast wrapping into [-PI, PI) (restricted to this interval for function speed) + inline double wrapToPiFast(double phi) + { + constexpr double TwoPi = o2::constants::math::TwoPI; + constexpr double Pi = o2::constants::math::PI; + if (phi >= Pi) + phi -= TwoPi; + else if (phi < -Pi) + phi += TwoPi; + return phi; + } + + void init(InitContext const&) + { + // Ring observable histograms: + // Helper to register one full histogram family (kinematic cut variation of ring observable) + auto addRingObservableFamily = [&](const std::string& folder) { + // =============================== + // QA histograms: angle and pT distributions + // (No mass dependency -- useful to check kinematic sculpting from cuts) + // =============================== + histos.add((folder + "/QA/hDeltaPhi").c_str(), "hDeltaPhi", kTH1D, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/hDeltaTheta").c_str(), "hDeltaTheta", kTH1D, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/QA/hIntegrated").c_str(), "hIntegrated", kTH1D, {{1, -0.5, 0.5}}); + // =============================== + // Lambda pT dependence + // =============================== + histos.add((folder + "/QA/hLambdaPt").c_str(), "hLambdaPt", kTH1D, {axisConfigurations.axisPt}); + histos.add((folder + "/QA/h2dDeltaPhiVsLambdaPt").c_str(), "h2dDeltaPhiVsLambdaPt", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPt}); + histos.add((folder + "/QA/h2dDeltaThetaVsLambdaPt").c_str(), "h2dDeltaThetaVsLambdaPt", kTH2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisPt}); + // =============================== + // Polarization observable QAs + // (not Ring: actual polarization!) + // =============================== + // Will implement these as TProfiles, as polarization is also a measure like P_\Lambda = (3/\alpha_\Lambda) * , so the error is similar + // =============================== + // 1D TProfiles + // =============================== + histos.add((folder + "/QA/pPxStarPhi").c_str(), "pPxStarPhi;#varphi_{#Lambda};_{x}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPyStarPhi").c_str(), "pPyStarPhi;#varphi_{#Lambda};_{y}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPzStarPhi").c_str(), "pPzStarPhi;#varphi_{#Lambda};_{z}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPxStarDeltaPhi").c_str(), "pPxStarDeltaPhi;#Delta#varphi_{jet};_{x}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPyStarDeltaPhi").c_str(), "pPyStarDeltaPhi;#Delta#varphi_{jet};_{y}", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/QA/pPzStarDeltaPhi").c_str(), "pPzStarDeltaPhi;#Delta#varphi_{jet};_{z}", kTProfile, {axisConfigurations.axisDeltaPhi}); + // =============================== + // 2D TProfiles (Lambda correlations) + // =============================== + histos.add((folder + "/QA/p2dPxStarDeltaPhiVsLambdaPt").c_str(), "p2dPxStarDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};_{x}", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPtSigExtract}); + histos.add((folder + "/QA/p2dPyStarDeltaPhiVsLambdaPt").c_str(), "p2dPyStarDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};_{y}", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPtSigExtract}); + histos.add((folder + "/QA/p2dPzStarDeltaPhiVsLambdaPt").c_str(), "p2dPzStarDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};_{z}", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPtSigExtract}); + + // TProfiles with correct error bars:: + // -- TProfiles will handle the error estimate of the Ring Observable via the variance, even though + // they still lack the proper signal extraction and possible efficiency corrections in the current state + // -- If any efficiency corrections arise, you can fill with the kTH1D as (deltaPhiJet, ringObservable, weight) + // instead of the simple (deltaPhiJet, ringObservable) --> Notice TProfile knows how to accept 3 entries + // for a TH1D-like object! + // -- CAUTION! The TProfile does not utilize unbiased variance estimators with N-1 instead of N in the denominator, + // so you might get biased errors when counts are too low in higher-dimensional profiles (i.e., kTProfile2Ds) + // =============================== + // 1D TProfiles + // =============================== + histos.add((folder + "/pRingObservableDeltaPhi").c_str(), "pRingObservableDeltaPhi;#Delta#varphi_{jet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/pRingObservableDeltaTheta").c_str(), "pRingObservableDeltaTheta;#Delta#theta_{jet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/pRingObservableIntegrated").c_str(), "pRingObservableIntegrated; ;<#it{R}>", kTProfile, {{1, -0.5, 0.5}}); + histos.add((folder + "/pRingObservableLambdaPt").c_str(), "pRingObservableLambdaPt;#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile, {axisConfigurations.axisPt}); + // For the leading particle: + histos.add((folder + "/pRingObservableLeadPDeltaPhi").c_str(), "pRingObservableLeadPDeltaPhi;#Delta#varphi_{leadP};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/pRingObservableLeadPDeltaTheta").c_str(), "pRingObservableLeadPDeltaTheta;#Delta#theta_{leadP};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/pRingObservableLeadPIntegrated").c_str(), "pRingObservableLeadPIntegrated; ;<#it{R}>", kTProfile, {{1, -0.5, 0.5}}); + histos.add((folder + "/pRingObservableLeadPLambdaPt").c_str(), "pRingObservableLeadPLambdaPt;#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile, {axisConfigurations.axisPt}); + // For the second-to-leading jet: + histos.add((folder + "/pRingObservable2ndJetDeltaPhi").c_str(), "pRingObservable2ndJetDeltaPhi;#Delta#varphi_{2ndJet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaPhi}); + histos.add((folder + "/pRingObservable2ndJetDeltaTheta").c_str(), "pRingObservable2ndJetDeltaTheta;#Delta#theta_{2ndJet};<#it{R}>", kTProfile, {axisConfigurations.axisDeltaTheta}); + histos.add((folder + "/pRingObservable2ndJetIntegrated").c_str(), "pRingObservable2ndJetIntegrated; ;<#it{R}>", kTProfile, {{1, -0.5, 0.5}}); + histos.add((folder + "/pRingObservable2ndJetLambdaPt").c_str(), "pRingObservable2ndJetLambdaPt;#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile, {axisConfigurations.axisPt}); + // =============================== + // 2D TProfiles (Lambda correlations) + // =============================== + histos.add((folder + "/p2dRingObservableDeltaPhiVsLambdaPt").c_str(), "p2dRingObservableDeltaPhiVsLambdaPt;#Delta#varphi_{jet};#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisPt}); + histos.add((folder + "/p2dRingObservableDeltaThetaVsLambdaPt").c_str(), "p2dRingObservableDeltaThetaVsLambdaPt;#Delta#theta_{jet};#it{p}_{T}^{#Lambda};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisPt}); + // =============================== + // 2D TProfiles (Jet correlations) + // =============================== + histos.add((folder + "/p2dRingObservableDeltaPhiVsLeadJetPt").c_str(), "p2dRingObservableDeltaPhiVsLeadJetPt;#Delta#varphi_{jet};#it{p}_{T}^{lead jet};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisJetPt}); + histos.add((folder + "/p2dRingObservableDeltaThetaVsLeadJetPt").c_str(), "p2dRingObservableDeltaThetaVsLeadJetPt;#Delta#theta_{jet};#it{p}_{T}^{lead jet};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisJetPt}); + + // =============================== + // Multi-dimensional histograms for signal extraction + // (Mass-dependent polarization extraction) + // =============================== + // Simple invariant mass plot for QA: + histos.add((folder + "/QA/hMass").c_str(), "hMass", kTH1D, {axisConfigurations.axisLambdaMass}); + histos.add((folder + "/hMassSigExtract").c_str(), "hMassSigExtract", kTH1D, {axisConfigurations.axisLambdaMassSigExtract}); + // 1D Mass dependence of observable numerator: + histos.add((folder + "/QA/hRingObservableNumMass").c_str(), "hRingObservableNumMass", kTH1D, {axisConfigurations.axisLambdaMassSigExtract}); + // --- 2D counters: Angle vs Mass vs --- + histos.add((folder + "/QA/h2dDeltaPhiVsMass").c_str(), "h2dDeltaPhiVsMass", kTH2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract}); + histos.add((folder + "/QA/h2dDeltaThetaVsMass").c_str(), "h2dDeltaThetaVsMass", kTH2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract}); + // --- 3D counters: Angle vs Mass vs Lambda pT --- + histos.add((folder + "/QA/h3dDeltaPhiVsMassVsLambdaPt").c_str(), "h3dDeltaPhiVsMassVsLambdaPt", kTH3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + histos.add((folder + "/QA/h3dDeltaThetaVsMassVsLambdaPt").c_str(), "h3dDeltaThetaVsMassVsLambdaPt", kTH3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + // --- 3D counters: Angle vs Mass vs Lead Jet pT --- + histos.add((folder + "/QA/h3dDeltaPhiVsMassVsLeadJetPt").c_str(), "h3dDeltaPhiVsMassVsLeadJetPt", kTH3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + histos.add((folder + "/QA/h3dDeltaThetaVsMassVsLeadJetPt").c_str(), "h3dDeltaThetaVsMassVsLeadJetPt", kTH3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + + // =============================== + // TProfiles vs Mass: quick glancing before signal extraction + // =============================== + // TProfile of ring vs mass (integrated in all phi, and properly normalized by N_\Lambda): + histos.add((folder + "/pRingObservableMass").c_str(), "pRingObservableMass;m_{p#pi};<#it{R}>", kTProfile, {axisConfigurations.axisLambdaMassSigExtract}); + histos.add((folder + "/pRingObservableLeadPMass").c_str(), "pRingObservableLeadPMass;m_{p#pi};<#it{R}>", kTProfile, {axisConfigurations.axisLambdaMassSigExtract}); + histos.add((folder + "/pRingObservable2ndJetMass").c_str(), "pRingObservable2ndJetMass;m_{p#pi};<#it{R}>", kTProfile, {axisConfigurations.axisLambdaMassSigExtract}); + // TProfile2D: vs Mass (DeltaPhi) + histos.add((folder + "/p2dRingObservableDeltaPhiVsMass").c_str(), "p2dRingObservableDeltaPhiVsMass;#Delta#varphi;m_{p#pi};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract}); + // TProfile2D: vs Mass (DeltaTheta) + histos.add((folder + "/p2dRingObservableDeltaThetaVsMass").c_str(), "p2dRingObservableDeltaThetaVsMass;#Delta#theta;m_{p#pi};<#it{R}>", kTProfile2D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract}); + // --- TProfile3D: vs DeltaPhi vs Mass vs LambdaPt --- + histos.add((folder + "/p3dRingObservableDeltaPhiVsMassVsLambdaPt").c_str(), "p3dRingObservableDeltaPhiVsMassVsLambdaPt;#Delta#varphi;m_{p#pi};p_{T}^{#Lambda};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + // --- TProfile3D: vs DeltaTheta vs Mass vs LambdaPt --- + histos.add((folder + "/p3dRingObservableDeltaThetaVsMassVsLambdaPt").c_str(), "p3dRingObservableDeltaThetaVsMassVsLambdaPt;#Delta#theta;m_{p#pi};p_{T}^{#Lambda};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisPtSigExtract}); + // --- TProfile3D: vs DeltaPhi vs Mass vs LeadJetPt --- + histos.add((folder + "/p3dRingObservableDeltaPhiVsMassVsLeadJetPt").c_str(), "p3dRingObservableDeltaPhiVsMassVsLeadJetPt;#Delta#varphi;m_{p#pi};p_{T}^{jet};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + // --- TProfile3D: vs DeltaTheta vs Mass vs LeadJetPt --- + histos.add((folder + "/p3dRingObservableDeltaThetaVsMassVsLeadJetPt").c_str(), "p3dRingObservableDeltaThetaVsMassVsLeadJetPt;#Delta#theta;m_{p#pi};p_{T}^{jet};<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisJetPtSigExtract}); + + // =============================== + // Mass histograms with centrality + // =============================== + // Counters + histos.add((folder + "/QA/h3dDeltaPhiVsMassVsCent").c_str(), "h3dDeltaPhiVsMassVsCent", kTH3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + histos.add((folder + "/QA/h3dDeltaThetaVsMassVsCent").c_str(), "h3dDeltaThetaVsMassVsCent", kTH3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + // Useful TProfiles: + // --- TProfile1D: Integrated vs Centrality: + histos.add((folder + "/pRingIntVsCentrality").c_str(), "pRingIntVsCentrality; Centrality (%);<#it{R}>", kTProfile, {axisConfigurations.axisCentrality}); + // --- TProfile2D: vs Mass vs Centrality --- + histos.add((folder + "/p2dRingObservableMassVsCent").c_str(), "p2dRingObservableMassVsCent;m_{p#pi};Centrality;<#it{R}>", kTProfile2D, {axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + // --- TProfile3D: vs DeltaPhi vs Mass vs Centrality --- + histos.add((folder + "/p3dRingObservableDeltaPhiVsMassVsCent").c_str(), "p3dRingObservableDeltaPhiVsMassVsCent;#Delta#varphi;m_{p#pi};Centrality;<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaPhi, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + // --- TProfile3D: vs DeltaTheta vs Mass vs Centrality --- + histos.add((folder + "/p3dRingObservableDeltaThetaVsMassVsCent").c_str(), "p3dRingObservableDeltaThetaVsMassVsCent;#Delta#theta;m_{p#pi};Centrality;<#it{R}>", kTProfile3D, {axisConfigurations.axisDeltaTheta, axisConfigurations.axisLambdaMassSigExtract, axisConfigurations.axisCentrality}); + + // =============================== + // QA histograms - Useful numbers + // =============================== + // (TODO: implement these!) + // (TODO: implement momentum imbalance checks for jets!) + // Added to a separate folder for further control (changed the usage of the "folder" string): + // histos.add(("QA_Numbers/" + folder + "/hValidLeadJets").c_str(), "hValidLeadJets", kTH1D, {{1,0,1}}); + // TODO: Add "frequency of jets per pT" histograms either here or in the TableProducer + }; + // Execute local lambda to register histogram families: + addRingObservableFamily("Ring"); + addRingObservableFamily("RingKinematicCuts"); + addRingObservableFamily("JetKinematicCuts"); + addRingObservableFamily("JetAndLambdaKinematicCuts"); + + histos.add("pRingCuts", "pRingCuts; ;<#it{R}>", kTProfile, {{4, 0, 4}}); + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(1, "All #Lambda"); + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(2, "p_{T}^{#Lambda}@[0.5,1.5],|y_{#Lambda}|<0.5"); // (v0pt > 0.5 && v0pt < 1.5) && std::abs(lambdaRapidity) < 0.5; + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(3, "|Jet_{#eta}|<0.5"); + histos.get(HIST("pRingCuts"))->GetXaxis()->SetBinLabel(4, "#Lambda + Jet cuts"); + + // Same for subleading jet and leading particle: + histos.add("pRingCutsSubLeadingJet", "pRingCutsSubLeadingJet; ;<#it{R}>", kTProfile, {{4, 0, 4}}); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(1, "All #Lambda"); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(2, "p_{T,#Lambda}@[0.5,1.5],|y_{#Lambda}|<0.5"); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(3, "|SubJet_{#eta}|<0.5"); + histos.get(HIST("pRingCutsSubLeadingJet"))->GetXaxis()->SetBinLabel(4, "#Lambda + SubJet cuts"); + + histos.add("pRingCutsLeadingP", "pRingCutsLeadingP; ;<#it{R}>", kTProfile, {{4, 0, 4}}); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(1, "All #Lambda"); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(2, "p_{T}^{#Lambda}@[0.5,1.5],|y_{#Lambda}|<0.5"); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(3, "|LeadP_{#eta}|<0.5"); + histos.get(HIST("pRingCutsLeadingP"))->GetXaxis()->SetBinLabel(4, "#Lambda + LeadP cuts"); + } + + // Helper to get centrality (same from TableProducer, thanks to templating!): + template + auto getCentrality(TCollision const& collision) + { + if (centralityEstimator == kCentFT0M) + return collision.centFT0M(); + else if (centralityEstimator == kCentFT0C) + return collision.centFT0C(); + else if (centralityEstimator == kCentFV0A) + return collision.centFV0A(); + return -1.f; + } + + // Initializing a random number generator for the worker (for perpendicular-to-jet direction QAs): + TRandom3 randomGen{0}; // 0 means we auto-seed from machine entropy. This is called once per device in the pipeline, so we should not see repeated seeds across workers + + // Preslices for correct collisions association: + // (TODO: test using custom grouping) + Preslice perColJets = o2::aod::lambdajetpol::ringCollisionId; + Preslice perColV0s = o2::aod::lambdajetpol::ringCollisionId; + Preslice perColLeadPs = o2::aod::lambdajetpol::ringCollisionId; + void processPolarizationData(o2::aod::RingCollisions const& collisions, o2::aod::RingJets const& jets, o2::aod::RingLaV0s const& v0s, + o2::aod::RingLeadPs const& leadPs) + { + for (auto const& collision : collisions) { + const auto collId = collision.globalIndex(); // The self-index accessor + const double centrality = getCentrality(collision); + + // Slice jets, V0s and leading particle belonging to this collision: + // (global collision indices repeat a lot, but they are unique to a same TimeFrame (TF) subfolder in the derived data) + auto v0sInColl = v0s.sliceBy(perColV0s, collId); + auto leadPsInColl = leadPs.sliceBy(perColLeadPs, collId); + + // Check if there is at least one V0 and one jet in the collision: + // (in the way I fill the table, there is always at least one V0 in + // the stored collision, but the jets table can not be filled for + // that collision, and a collision may not be filled when the jets + // table is. Be mindful of that!) + // 1) Require at least one V0: + if (!v0sInColl.size()) + continue; + + // 2) We require at least a leading particle, then we get the leading jet only if it exists: + // (The goal is to see how diluted the signal gets with events which don't even have a loose FastJet jet) + // (The leading particle is built from all tracks that passed the pseudojet + // selection, so it exists whenever FastJet was run on this collision. + // Events that have a leading jet always have a leading particle too, but + // the converse is not true: events can have a leading particle with no jet + // if no jet survives the pT threshold/the background subtraction) + float leadPPt = -1.; // pT = -1 means "table entry not found for this collision". + float leadPEta = 0.; + float leadPPhi = 0.; + float leadPPx = 0., leadPPy = 0., leadPPz = 0.; + for (auto const& lp : leadPsInColl) { + // Table should contain exactly one entry per collision, + // but we break immediately to be safe: + leadPPt = lp.leadParticlePt(); + leadPEta = lp.leadParticleEta(); + leadPPhi = lp.leadParticlePhi(); + // Using dynamic columns to make code cleaner: + leadPPx = lp.leadParticlePx(); + leadPPy = lp.leadParticlePy(); + leadPPz = lp.leadParticlePz(); + break; + } + // Discard events with no leading particle (FastJet didn't even run in these cases!): + if (leadPPt < 0.) + continue; + + // Build leading particle unit vector, outside the V0 loop for performance: + XYZVector leadPUnitVec = XYZVector(leadPPx, leadPPy, leadPPz).Unit(); + + // 3) Checking if the event has a leading jet: + auto jetsInColl = jets.sliceBy(perColJets, collId); + float leadingJetPt = -1.; + float subleadingJetPt = -1.; + // std::optional avoids undefined behaviour from a default-constructed iterator: + // (essentially, just protection for when we fetch jetEta() and the such) + std::optional leadingJet; + std::optional subleadingJet; + for (auto const& jet : jetsInColl) { + const auto jetpt = jet.jetPt(); + if (jetpt > leadingJetPt) { + // Current leading becomes subleading: + subleadingJetPt = leadingJetPt; + subleadingJet = leadingJet; // may still be std::nullopt on first pass -- that is fine! + // Now update the leading jet: + leadingJetPt = jetpt; + leadingJet = jet; + } else if (jetpt > subleadingJetPt) { // Update subleading only: + subleadingJetPt = jetpt; + subleadingJet = jet; + } + } + + // Some useful bools to check if we have a leading jet and a subleading jet: + const bool hasValidLeadingJet = leadingJetPt > 0.; + const bool hasValidSubJet = subleadingJetPt > 0.; + + // Build jet vectors (only when the corresponding jet exists): + // Dummy initialisations are safe: all jet-dependent fills are gated on hasValidLeadingJet / hasValidSubJet. + float leadingJetEta = 0.; + float leadingJetPhi = 0.; + XYZVector leadingJetUnitVec(1., 0., 0.); // dummy (overwritten below) + if (hasValidLeadingJet) { + leadingJetEta = leadingJet->jetEta(); + leadingJetPhi = leadingJet->jetPhi(); + // Using internal getters to make code cleaner: + leadingJetUnitVec = XYZVector(leadingJet->jetPx(), leadingJet->jetPy(), leadingJet->jetPz()).Unit(); + + // QA block -- Purposefully changing the jet direction (should kill signal, if any): + if (forcePerpToJet) { // Use modified jet direction (done outside loop to guarantee all V0s inside event use same fake jet) + // First, we build a vector perpendicular to the jet by picking an arbitrary vector not parallel to the jet + XYZVector refVec(1., 0., 0.); + if (std::abs(leadingJetUnitVec.Dot(refVec)) > 0.99) + refVec = XYZVector(0., 1., 0.); + // Now we get a perpendicular vector to the jet direction: + XYZVector perpVec = leadingJetUnitVec.Cross(refVec).Unit(); + // Now we rotate around the jet axis by a random angle, just to make sure we are not introducing a bias in the QA: + // We will use Rodrigues' rotation formula (v_rot = v*cos(randomAngle) + (Jet \cross v)*sin(randomAngle)) + double randomAngle = randomGen.Uniform(0., o2::constants::math::TwoPI); + leadingJetUnitVec = perpVec * std::cos(randomAngle) + leadingJetUnitVec.Cross(perpVec) * std::sin(randomAngle); + } else if (forceJetDirectionSmudge) { + // Smear the jet direction by a small random angle to estimate sensitivity to + // jet axis uncertainty. We rotate the jet axis by angle theta around a uniformly + // random perpendicular axis -- this is isotropic and coordinate-independent, + // unlike smearing eta and phi separately (which would break azimuthal symmetry + // around the jet axis and depend on where in eta the jet sits). + + // 1) We pick a uniformly random axis perpendicular to the jet. + // (re-using the same Rodrigues formula as in the forcePerpToJet block above) + XYZVector refVec(1., 0., 0.); + if (std::abs(leadingJetUnitVec.Dot(refVec)) > 0.99) + refVec = XYZVector(0., 1., 0.); + XYZVector perpVec = leadingJetUnitVec.Cross(refVec).Unit(); + // Rotate perpVec around the jet axis by a uniform random azimuth to get + // a uniformly distributed random perpendicular direction (the smear axis): + double smearAzimuth = randomGen.Uniform(0., o2::constants::math::TwoPI); + XYZVector smearAxis = perpVec * std::cos(smearAzimuth) + leadingJetUnitVec.Cross(perpVec) * std::sin(smearAzimuth); + + // Step 2: draw the smearing polar angle from a Gaussian: + // sigma = 0.05 * R --> ~68% of events smeared within 5% of R, + // ~95% of events smeared within 10% of R, + // ~5% see a displacement > 0.1*R (a very "badly determined jet", for our QA purposes) + // std::abs() folds the symmetric Gaussian onto a half-normal ([0, inf)) + // -- R is not really an angle: just gives me a scale for the angular shift I am performing. + // -- This may pose problems for forward jets: a small displacemente in \theta becomes a large displacement in \eta space + double smearSigma = 0.05 * jetRForSmuding; + double smearAngle = std::abs(randomGen.Gaus(0., smearSigma)); + + // Step 3: rotate the jet axis by smearAngle around smearAxis. + // Rodrigues is v_rot = v*cos(theta) + (k \croos v)*sin(theta) + k*(k \cdot v)*(1-cos(theta)) + // But the last term vanishes because smearAxis is perpendicular to leadingJetUnitVec: + leadingJetUnitVec = leadingJetUnitVec * std::cos(smearAngle) + smearAxis.Cross(leadingJetUnitVec) * std::sin(smearAngle); + // Also, rotation preserves the norm, so no re-normalisation is needed for this to be a unit vector. + } + } + + float subleadingJetEta = 0.; + float subleadingJetPhi = 0.; + XYZVector subJetUnitVec(1., 0., 0.); + if (hasValidSubJet) { + subleadingJetEta = subleadingJet->jetEta(); + subleadingJetPhi = subleadingJet->jetPhi(); + // Using internal getters to make code cleaner: + subJetUnitVec = XYZVector(subleadingJet->jetPx(), subleadingJet->jetPy(), subleadingJet->jetPz()).Unit(); + } + + // (jet eta cuts only meaningful when the jet actually exists) + const bool kinematicJetCheck = hasValidLeadingJet && (std::abs(leadingJetEta) < 0.5); + const bool kinematic2ndJetCheck = hasValidSubJet && (std::abs(subleadingJetEta) < 0.5); + const bool kinematicLeadPCheck = std::abs(leadPEta) < 0.5; + + for (auto const& v0 : v0sInColl) { + const bool isLambda = v0.isLambda(); + const bool isAntiLambda = v0.isAntiLambda(); + // For now, removing the ambiguous candidates from the analysis. Derived data permits handling both. + // (From Podolanski-Armenteros plots, the population of ambiguous is ~2% without TOF, and without + // competing mass rejection. From those, ~99% seem to be K0s, so no real gain in considering the + // ambiguous candidates in the analysis) + if (isLambda && isAntiLambda) + continue; + const float v0pt = v0.v0Pt(); + const float v0eta = v0.v0Eta(); + const float v0phi = v0.v0Phi(); + + float v0LambdaLikeMass = 0; // Initialized just to catch any stray behavior + float protonLikePt = 0; + float protonLikeEta = 0; + float protonLikePhi = 0; + if (isLambda) { + if (!analyseLambda) + continue; + v0LambdaLikeMass = v0.massLambda(); + protonLikePt = v0.posPt(); + protonLikeEta = v0.posEta(); + protonLikePhi = v0.posPhi(); + } else if (isAntiLambda) { // (TODO: add a split histogram where you consider Lambda and AntiLambda polarization separately?) + if (!analyseAntiLambda) + continue; + v0LambdaLikeMass = v0.massAntiLambda(); + protonLikePt = v0.negPt(); + protonLikeEta = v0.negEta(); + protonLikePhi = v0.negPhi(); + } + + PtEtaPhiMVector lambdaLike4Vec(v0pt, v0eta, v0phi, v0LambdaLikeMass); + PtEtaPhiMVector protonLike4Vec(protonLikePt, protonLikeEta, protonLikePhi, protonMass); + float lambdaRapidity = lambdaLike4Vec.Rapidity(); // For further kinematic selections + + // Boosting proton into lambda frame: + XYZVector beta = -lambdaLike4Vec.BoostToCM(); // Boost trivector that goes from laboratory frame to the rest frame + auto protonLike4VecStar = ROOT::Math::VectorUtil::boost(protonLike4Vec, beta); + + // Getting unit vectors and 3-components: + XYZVector lambdaLike3Vec = lambdaLike4Vec.Vect(); + XYZVector protonLikeStarUnit3Vec = protonLike4VecStar.Vect().Unit(); + + //////////////////////////////////////////// + // Ring observable: Leading particle proxy + // Always computed -- leading particle existence is guaranteed by the second check above + //////////////////////////////////////////// + // Cross product + XYZVector crossLeadP = leadPUnitVec.Cross(lambdaLike3Vec); + float ringObservableLeadP = protonLikeStarUnit3Vec.Dot(crossLeadP) / crossLeadP.R(); + // Adding the prefactor related to the CP-violating decay (decay constants have different signs) + if (!forcePolSignQA) + ringObservableLeadP *= (isLambda) ? polPrefactorLambda : polPrefactorAntiLambda; + else + ringObservableLeadP *= (isLambda) ? polPrefactorLambda : -1.0 * polPrefactorAntiLambda; + // Angular variables + float deltaPhiLeadP = wrapToPiFast(v0phi - leadPPhi); // Wrapped to [-PI, pi), for convenience + float deltaThetaLeadP = ROOT::Math::VectorUtil::Angle(leadPUnitVec, lambdaLike3Vec); // 3D angular separation + + ////////////////////////////////////////// + // Ring observable: Leading jet proxy + // Only computed when a leading jet exists in this collision. + ////////////////////////////////////////// + float ringObservable = 0.; + float deltaPhiJet = 0.; + float deltaThetaJet = 0.; + if (hasValidLeadingJet) { + // Cross product + XYZVector cross = leadingJetUnitVec.Cross(lambdaLike3Vec); + ringObservable = protonLikeStarUnit3Vec.Dot(cross) / cross.R(); + // Adding prefactor + if (!forcePolSignQA) + ringObservable *= (isLambda) ? polPrefactorLambda : polPrefactorAntiLambda; + else + ringObservable *= (isLambda) ? polPrefactorLambda : -1.0 * polPrefactorAntiLambda; + // Angular variables + deltaPhiJet = wrapToPiFast(v0phi - leadingJetPhi); + deltaThetaJet = ROOT::Math::VectorUtil::Angle(leadingJetUnitVec, lambdaLike3Vec); + } + + ////////////////////////////////////////// + // Ring observable: Subleading jet proxy + // Only computed when a subleading jet exists in this collision. + ////////////////////////////////////////// + float ringObservable2ndJet = 0.; + float deltaPhi2ndJet = 0.; + float deltaTheta2ndJet = 0.; + if (hasValidSubJet) { + XYZVector cross2ndJet = subJetUnitVec.Cross(lambdaLike3Vec); + ringObservable2ndJet = protonLikeStarUnit3Vec.Dot(cross2ndJet) / cross2ndJet.R(); + // Adding prefactor + if (!forcePolSignQA) + ringObservable2ndJet *= (isLambda) ? polPrefactorLambda : polPrefactorAntiLambda; + else + ringObservable2ndJet *= (isLambda) ? polPrefactorLambda : -1.0 * polPrefactorAntiLambda; + // Angular variables + deltaPhi2ndJet = wrapToPiFast(v0phi - subleadingJetPhi); + deltaTheta2ndJet = ROOT::Math::VectorUtil::Angle(subJetUnitVec, lambdaLike3Vec); + } + + // Calculating polarization observables (in the Lambda frame, because that is easier -- does not require boosts): + // To be precise, not actually the polarization, but a part of the summand in P^*_\Lambda = (3/\alpha_\Lambda) * + float PolStarX = 0, PolStarY = 0, PolStarZ = 0; // Dummy initialization: avoid warnings in compile time + if (isLambda) { // Notice there is no need to check analyseLambda again due to previous checks. + PolStarX = polPrefactorLambda * protonLikeStarUnit3Vec.X(); + PolStarY = polPrefactorLambda * protonLikeStarUnit3Vec.Y(); + PolStarZ = polPrefactorLambda * protonLikeStarUnit3Vec.Z(); + } else if (isAntiLambda) { + PolStarX = polPrefactorAntiLambda * protonLikeStarUnit3Vec.X(); + PolStarY = polPrefactorAntiLambda * protonLikeStarUnit3Vec.Y(); + PolStarZ = polPrefactorAntiLambda * protonLikeStarUnit3Vec.Z(); + } + + float v0phiToFillHists = wrapToPiFast(v0phi); // A short wrap to reuse some predefined axes + + // Fill ring histograms: (1D, lambda 2D correlations and jet 2D correlations): + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "Ring") // Notice the usage of macros! If you change the variable names, this WILL break the code! + // No, there should NOT be any ";" here! Read the macro definition for an explanation + histos.fill(HIST("pRingCutsLeadingP"), 0, ringObservableLeadP); // First bin of comparison + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "Ring") + + if (hasValidLeadingJet) { + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "Ring") + histos.fill(HIST("pRingCuts"), 0, ringObservable); + } + if (hasValidSubJet) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "Ring") + histos.fill(HIST("pRingCutsSubLeadingJet"), 0, ringObservable2ndJet); + } + + // Extra kinematic criteria for Lambda candidates (removes polarization background): + const bool kinematicLambdaCheck = (v0pt > 0.5 && v0pt < 1.5) && std::abs(lambdaRapidity) < 0.5; + if (kinematicLambdaCheck) { + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + histos.fill(HIST("pRingCutsLeadingP"), 1, ringObservableLeadP); + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + if (hasValidLeadingJet) { + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + histos.fill(HIST("pRingCuts"), 1, ringObservable); + } + if (hasValidSubJet) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "RingKinematicCuts") + histos.fill(HIST("pRingCutsSubLeadingJet"), 1, ringObservable2ndJet); + } + } + + // Extra selection criteria on jet candidates: + // (redundant for jets with R=0.4, but for jets with R<0.4 the leading jet may be farther in eta) + if (kinematicJetCheck) { // Already includes hasValidLeadingJet in the bool! (no need to check again) + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + histos.fill(HIST("pRingCuts"), 2, ringObservable); + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + } + + // Extra selection criteria on both Lambda and jet candidates: + if (kinematicLambdaCheck && kinematicJetCheck) { + RING_OBSERVABLE_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + histos.fill(HIST("pRingCuts"), 3, ringObservable); + POLARIZATION_PROFILE_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + } + + // Same variations for the leading particle and for the subleading jet: + if (kinematicLeadPCheck) { + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + histos.fill(HIST("pRingCutsLeadingP"), 2, ringObservableLeadP); + } + if (kinematic2ndJetCheck) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "JetKinematicCuts") + histos.fill(HIST("pRingCutsSubLeadingJet"), 2, ringObservable2ndJet); + } + if (kinematicLambdaCheck && kinematicLeadPCheck) { + RING_OBSERVABLE_LEADP_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + histos.fill(HIST("pRingCutsLeadingP"), 3, ringObservableLeadP); + } + if (kinematicLambdaCheck && kinematic2ndJetCheck) { + RING_OBSERVABLE_2NDJET_FILL_LIST(APPLY_HISTO_FILL, "JetAndLambdaKinematicCuts") + histos.fill(HIST("pRingCutsSubLeadingJet"), 3, ringObservable2ndJet); + } + } // end v0s loop + } // end collisions + } + + PROCESS_SWITCH(lambdajetpolarizationionsderived, processPolarizationData, "Process derived data in Run 3 Data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} + +// Avoid macro leakage! +#undef APPLY_HISTO_FILL diff --git a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx index 402f7ba017f..2a77ca5a462 100644 --- a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx @@ -24,7 +24,8 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" @@ -52,6 +53,8 @@ #include // #include +#include "PWGLF/DataModel/mcCentrality.h" + #include #include @@ -126,12 +129,13 @@ struct LambdaJetpolarization { Configurable requireTPC{"requireTPC", true, "require TPC hit"}; Configurable yMin{"yMin", -0.5f, "minimum y"}; Configurable yMax{"yMax", +0.5f, "maximum y"}; + Configurable yMCcut{"yMCcut", +0.5f, "maximum y"}; Configurable v0rejLambda{"v0rejLambda", 0.01, "V0 rej Lambda"}; Configurable v0accLambda{"v0accLambda", 0.075, "V0 acc Lambda"}; Configurable ifinitpasslambda{"ifinitpasslambda", 0, "ifinitpasslambda"}; Configurable ifpasslambda{"ifpasslambda", 1, "ifpasslambda"}; Configurable paramArmenterosCut{"paramArmenterosCut", 0.2, "parameter Armenteros Cut"}; - Configurable doArmenterosCut{"doArmenterosCut", 1, "do Armenteros Cut"}; + Configurable doArmenterosCut{"doArmenterosCut", 0, "do Armenteros Cut"}; Configurable noSameBunchPileUp{"noSameBunchPileUp", true, "reject SameBunchPileUp"}; Configurable v0TypeSelection{"v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; Configurable notITSAfterburner{"notITSAfterburner", 0, "notITSAfterburner"}; @@ -139,20 +143,20 @@ struct LambdaJetpolarization { Configurable evSel{"evSel", 1, "evSel"}; Configurable hasTOF2Leg{"hasTOF2Leg", 0, "hasTOF2Leg"}; Configurable hasTOF1Leg{"hasTOF1Leg", 0, "hasTOF1Leg"}; + Configurable isMC{"isMC", 1, "fill MC histograms"}; - // Jet background subtraction - JetBkgSubUtils backgroundSub; void init(InitContext const&) { + const AxisSpec axisPx{100, -10, 10, "#px (GeV/c)"}; const AxisSpec axisPy{100, -10, 10, "#py (GeV/c)"}; const AxisSpec axisPz{100, -10, 10, "#pz (GeV/c)"}; const AxisSpec axisPT{200, 0, 50, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisPhi{200, -TMath::Pi(), TMath::Pi(), "#Phi"}; - const AxisSpec axisDeltaPhi{200, 0, TMath::Pi(), "#Phi"}; + const AxisSpec axisDeltaPhi{10, 0, TMath::Pi(), "#Phi"}; const AxisSpec axisTheta{100, -TMath::Pi(), TMath::Pi(), "#Theta"}; const AxisSpec axisMass{100, 0.9, 1.0, "Mass(GeV/c^{2})"}; - const AxisSpec axisCostheta{100, -1, 1, "Cos(#theta^{*}_{p})"}; + const AxisSpec axisCostheta{10, -1, 1, "Cos(#theta^{*}_{p})"}; const AxisSpec axisSinPhi{100, -1, 1, "Sin(#phi^{*}_{p})"}; const AxisSpec JetaxisEta{30, -1.5, +1.5, "#eta"}; @@ -366,6 +370,58 @@ struct LambdaJetpolarization { registryData.get(HIST("QA/hv0sSelection"))->GetXaxis()->SetBinLabel(19, "TPC nsigma Pos Dau"); registryData.get(HIST("QA/hv0sSelection"))->GetXaxis()->SetBinLabel(20, "Armenteros-Podolansky"); } + if (isMC) { + registryData.add("MC/hNEventsMCReco", "hNEventsMCReco", {HistType::kTH1D, {{4, 0.f, 4.f}}}); + registryData.get(HIST("MC/hNEventsMCReco"))->GetXaxis()->SetBinLabel(1, "all"); + registryData.get(HIST("MC/hNEventsMCReco"))->GetXaxis()->SetBinLabel(2, "pass ev sel"); + registryData.get(HIST("MC/hNEventsMCReco"))->GetXaxis()->SetBinLabel(3, "INELgt0"); + registryData.get(HIST("MC/hNEventsMCReco"))->GetXaxis()->SetBinLabel(4, "check"); + registryData.add("MC/Reconstructed_MCRecoColl_INEL_Lambda", "Reconstructed_MCRecoColl_INEL_Lambda", {HistType::kTH2F, {{250, 0.f, 25.f}, {1000, 0.f, 100.f}}}); + registryData.add("MC/Reconstructed_MCRecoColl_INEL_AntiLambda", "Reconstructed_MCRecoColl_INEL_AntiLambda", {HistType::kTH2F, {{250, 0.f, 25.f}, {1000, 0.f, 100.f}}}); + registryData.add("MC/Reconstructed_MCRecoColl_INELgt0_Lambda", "Reconstructed_MCRecoColl_INELgt0_Lambda", {HistType::kTH2F, {{250, 0.f, 25.f}, {1000, 0.f, 100.f}}}); + registryData.add("MC/Reconstructed_MCRecoColl_INELgt0_AntiLambda", "Reconstructed_MCRecoColl_INELgt0_AntiLambda", {HistType::kTH2F, {{250, 0.f, 25.f}, {1000, 0.f, 100.f}}}); + registryData.add("MC/hMassLambda_MC", "hMassLambda", {HistType::kTH1F, {{200, 1.016f, 1.216f}}}); + registryData.add("MC/hMassVsPtLambdaVsCentFT0M_MC", ";p_{T} [GeV/c];M_{p^{+}#pi^{-}} [GeV/c^{2}]", {HistType::kTH3F, {{250, 0.0f, 25.0f}, {100, 0.f, 100.f}, {200, 1.936f - (massPr + massPi), massPr + massPi + (massPr + massPi)}}}); + registryData.add("MC/hFDVsPtLambdaVsMotherPt_DoubleCharged_MC", ";p_{T} [GeV/c] (V0);p_{T}^{gen} [GeV/c] (#Xi^{-}); percentile", {HistType::kTH3F, {{250, 0.0f, 25.0f}, {250, 0.0f, 25.0f}, {100, 0.f, 100.f}}}); + registryData.add("MC/hFDVsPtLambdaVsMotherPt_MCRatio_MC", ";p_{T} [GeV/c] (V0);p_{T}^{gen} [GeV/c] (#Xi^{-/0}); percentile", {HistType::kTH3F, {{250, 0.0f, 25.0f}, {250, 0.0f, 25.0f}, {100, 0.f, 100.f}}}); + registryData.add("MC/hMassAntiLambda_MC", "hMassAntiLambda", {HistType::kTH1F, {{200, 1.016f, 1.216f}}}); + registryData.add("MC/hMassVsPtAntiLambdaVsCentFT0M_MC", ";p_{T} [GeV/c];M_{p^{+}#pi^{-}} [GeV/c^{2}]", {HistType::kTH3F, {{250, 0.0f, 25.0f}, {100, 0.f, 100.f}, {200, 1.936f - (massPr + massPi), massPr + massPi + (massPr + massPi)}}}); + registryData.add("MC/h_MCtrack_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", kTH1F, {{200, 0., 200.}}); + registryData.add("MC/h_MCtrack_eta", "track #eta;#eta_{track};entries", kTH1F, {{100, -1.f, 1.f}}); + registryData.add("MC/h_MCtrack_phi", "track #varphi;#varphi_{track};entries", kTH1F, {{80, -1.f, 7.f}}); + registryData.add("MC/h_MCtrack_pt_sel", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", kTH1F, {{200, 0., 200.}}); + registryData.add("MC/h_MCtrack_eta_sel", "track #eta;#eta_{track};entries", kTH1F, {{100, -1.f, 1.f}}); + registryData.add("MC/h_MCtrack_phi_sel", "track #varphi;#varphi_{track};entries", kTH1F, {{80, -1.f, 7.f}}); + + registryData.add("MC/MCFJetaHistogram", "FJetaHistogram", kTH1F, {JetaxisEta}); + registryData.add("MC/MCFJphiHistogram", "FJphiHistogram", kTH1F, {JetaxisPhi}); + registryData.add("MC/MCFJptHistogram", "FJptHistogram", kTH1F, {JetaxisPt}); + registryData.add("MC/MCFJetaHistogramsel", "FJetaHistogramsel", kTH1F, {JetaxisEta}); + registryData.add("MC/MCFJphiHistogramsel", "FJphiHistogramsel", kTH1F, {JetaxisPhi}); + registryData.add("MC/MCFJptHistogramsel", "FJptHistogramsel", kTH1F, {JetaxisPt}); + + registryData.add("MC/MCFLeadingJetaHistogramsel", "FLeadingJetaHistogramsel", kTH1F, {JetaxisEta}); + registryData.add("MC/MCFLeadingJphiHistogramsel", "FLeadingJphiHistogramsel", kTH1F, {JetaxisPhi}); + registryData.add("MC/MCFLeadingJptHistogramsel", "FLeadingJptHistogramsel", kTH1F, {JetaxisPt}); + registryData.add("MC/MCnJetsPerEvent", "nJetsPerEvent", kTH1F, {{10, 0.0, 10.0}}); + registryData.add("MC/MCnJetsPerEventsel", "nJetsPerEventsel", kTH1F, {{10, 0.0, 10.0}}); + registryData.add("MC/MCnumber_of_events_vsmultiplicity", "number of events in data vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + registryData.add("MC/MCnV0sPerEvent", "nV0sPerEvent", kTH1F, {{10, 0.0, 10.0}}); + + registryData.add("MC/V0pxInRest_frame", "V0pxInRest_frame", kTH1F, {axisPx}); + registryData.add("MC/V0pyInRest_frame", "V0pyInRest_frame", kTH1F, {axisPy}); + registryData.add("MC/V0pzInRest_frame", "V0pzInRest_frame", kTH1F, {axisPz}); + + // Jet-V0 frame messages + registryData.add("MC/TH2FprotonCosThetaInJetV0", "TH2FprotonCosThetaInJetV0", kTH2F, {{200, 0.9, 1.2}, {200, -1.0, 1.0}}); + registryData.add("MC/TProfile1DprotonCosThetaInJetV0", "TProfile1DprotonCosThetaInJetV0", {HistType::kTProfile, {{200, 0.9, 1.2}}}); + registryData.add("MC/TProfile1DprotonCos2ThetaInJetV0", "TProfile1DprotonCos2ThetaInJetV0", {HistType::kTProfile, {{200, 0.9, 1.2}}}); + registryData.add("MC/TProfile2DprotonCosThetaInJetV0", "TProfile2DprotonCosThetaInJetV0", kTProfile2D, {tprofile2DaxisMass, axisDeltaPhi}); + registryData.add("MC/TProfile2DprotonCos2ThetaInJetV0", "TProfile2DprotonCos2ThetaInJetV0", kTProfile2D, {tprofile2DaxisMass, axisDeltaPhi}); + registryData.add("MC/TH1FprotonCosThetaInJetV0", "TH1FprotonCosThetaInJetV0", kTH1F, {{200, -1.0, 1.0}}); + registryData.add("MC/TH2FprotonCosThetaPhiInJetV0", "TH2FprotonCosThetaPhiInJetV0", kTH2F, {{200, -1.0, 1.0}, {200, 0.0, TMath::Pi()}}); + registryData.add({"MC/TH3DLambdaMassDeltaPhiDeltaCosTheta", "; Mass (GeV/c^{2}); #Delta #varphi_{jet} (rad); Cos(#theta^{*}_{p})", {HistType::kTH3D, {invMassLambdaAxis, axisDeltaPhi, axisCostheta}}}); + } } double massPr = o2::constants::physics::MassProton; double massLambda = o2::constants::physics::MassLambda; @@ -834,6 +890,124 @@ struct LambdaJetpolarization { return true; } + // MC Lambda Selections + template + bool registryMCAcceptV0Lambda(const MCLambda& v0, const MCTrackPos& ptrack, const MCTrackNeg& ntrack, const MCTCollision& collision) + { + + int evFlag = 0; + if (collision.isInelGt0()) { + evFlag = 1; + } + + if (v0.pt() < v0Ptmin) { + return false; + } + + registryData.fill(HIST("QA/hv0sSelection"), 0.5); + + if (evSel && evFlag < 1) + return false; + + registryData.fill(HIST("QA/hv0sSelection"), 1.5); + + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + return false; + + registryData.fill(HIST("QA/hv0sSelection"), 2.5); + + if (TMath::Abs(ptrack.eta()) > v0TracketaMax || TMath::Abs(ntrack.eta()) > v0TracketaMax) { + return false; + } + registryData.fill(HIST("QA/hv0sSelection"), 3.5); + + if (std::fabs(v0.dcapostopv()) < dcapostoPVmin) + return false; + if (std::fabs(v0.dcanegtopv()) < dcanegtoPVmin) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 4.5); + + if (std::fabs(v0.dcaV0daughters()) > dcaV0DaughtersMax) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 5.5); + + if (requireITS && ptrack.itsNCls() < minITSnCls) + return false; + if (requireITS && ntrack.itsNCls() < minITSnCls) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 6.5); + + if (hasTOF1Leg && !ptrack.hasTOF() && !ntrack.hasTOF()) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 7.5); + + if (hasTOF2Leg && (!ptrack.hasTOF() || !ntrack.hasTOF())) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 8.5); + + if (ptrack.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + if (ntrack.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 9.5); + + if (requireMaxTPCSharedCls && ptrack.tpcNClsShared() > maxTPCSharedCls) + return false; + if (requireMaxTPCSharedCls && ntrack.tpcNClsShared() > maxTPCSharedCls) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 10.5); + + if (ptrack.itsChi2NCl() > maxChi2ITS) + return false; + if (ntrack.itsChi2NCl() > maxChi2ITS) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 11.5); + + if (ptrack.tpcChi2NCl() > maxChi2TPC) + return false; + if (ntrack.tpcChi2NCl() > maxChi2TPC) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 12.5); + + if (v0.v0cosPA() < v0cospaMin) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 13.5); + + if (v0.yLambda() < yMin || v0.yLambda() > yMax) { + return false; + } + registryData.fill(HIST("QA/hv0sSelection"), 14.5); + // For MC ,these cuts is not applied + /* + float ctauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0; + if (ctauLambda >= cTau) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 15.5); + + if (TMath::Abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0rejLambda) { + return false; + } + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) > v0accLambda) { + return false; + } + + registryData.fill(HIST("QA/hv0sSelection"), 16.5); + + + if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 17.5); + + if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 18.5); + + if (doArmenterosCut && v0.qtarm() > (paramArmenterosCut * std::abs(v0.alpha()))) + return false; + registryData.fill(HIST("QA/hv0sSelection"), 19.5); + */ + return true; + } template bool registryDataAcceptV0AntiLambda(const Lambda& v0, const TrackPos& ptrack, const TrackNeg& ntrack, const TCollision& collision) @@ -903,23 +1077,24 @@ struct LambdaJetpolarization { } float ctauAntiLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0Bar; - if (ctauAntiLambda >= cTau) + if (ctauAntiLambda >= cTau) { return false; - + } if (TMath::Abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0rejLambda) { return false; } if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) > v0accLambda) { return false; } - if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) { return false; - - if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + } + if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) { return false; - - if (doArmenterosCut && v0.qtarm() > (paramArmenterosCut * std::abs(v0.alpha()))) + } + if (doArmenterosCut && v0.qtarm() > (paramArmenterosCut * std::abs(v0.alpha()))) { return false; + } return true; } @@ -1196,6 +1371,7 @@ struct LambdaJetpolarization { using SelCollisions = soa::Join; using SelV0Collisions = soa::Join; using StrHadronDaughterTracks = soa::Join; + // using StrHadronDaughterTracksMC = soa::Join; void processData(SelV0Collisions::iterator const& collision, aod::V0Datas const& fullV0s, StrHadronDaughterTracks const& tracks) { registryData.fill(HIST("hNEvents"), 0.5); @@ -2004,9 +2180,435 @@ struct LambdaJetpolarization { } } PROCESS_SWITCH(LambdaJetpolarization, processLambdaJetPolarization, "processLambdaJetPolarization", true); + + Preslice> perCol = aod::track::collisionId; + Preslice perMCCol = aod::mcparticle::mcCollisionId; + SliceCache cache1; + Service pdgDB; + using DauTracksMC = soa::Join; + Preslice perColtrack = aod::track::collisionId; + void processRun3MCReconstructed(soa::Join const& collisions, + soa::Join const& /*mcCollisions*/, + soa::Join const& V0s, + aod::McParticles const& /*mcParticles*/, DauTracksMC const& tracks) + { + for (const auto& collision : collisions) { + if (!AcceptEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + const auto& mcCollision = collision.mcCollision_as>(); + registryData.fill(HIST("MC/hNEventsMCReco"), 3.5); + // const float cent = 0.f; + // Event flags + int evFlag = 0; + if (collision.isInelGt0()) { + evFlag = 1; + } + auto v0sThisCollision = V0s.sliceBy(perCol, collision.globalIndex()); + auto tracksThisCollision = tracks.sliceBy(perColtrack, collision.globalIndex()); + std::vector fjParticles; + for (const auto& track : tracksThisCollision) { + registryData.fill(HIST("MC/h_MCtrack_pt"), track.pt()); + registryData.fill(HIST("MC/h_MCtrack_eta"), track.eta()); + registryData.fill(HIST("MC/h_MCtrack_phi"), track.phi()); + if (ispassdTrackSelectionForJetReconstruction && !passedTrackSelectionForJetReconstruction(track)) { + continue; + } + registryData.fill(HIST("MC/h_MCtrack_pt_sel"), track.pt()); + registryData.fill(HIST("MC/h_MCtrack_eta_sel"), track.eta()); + registryData.fill(HIST("MC/h_MCtrack_phi_sel"), track.phi()); + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); + fjParticles.emplace_back(fourMomentum); + } + // reject empty events + if (fjParticles.size() < 1) + return; + // cluster particles using the anti-kt algorithm + fastjet::RecombinationScheme recombScheme = fastjet::E_scheme; + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet, recombScheme); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + + // jet selection + bool isAtLeastOneJetSelected = false; + int nJets = 0; + int nJetssel = 0; + // select most large momentum jet + float maxJetpx = 0; + float maxJetpy = 0; + float maxJetpz = 0; + float maxJeteta = 0; + float maxJetphi = 0; + float maxJetE = 0; + float maxJetpT = 0; + float maxJetPt = -999; + + for (const auto& jet : jets) { + nJets++; + registryData.fill(HIST("MC/MCFJetaHistogram"), jet.eta()); + registryData.fill(HIST("MC/MCFJphiHistogram"), jet.phi()); + registryData.fill(HIST("MC/MCFJptHistogram"), jet.pt()); + // jet must be fully contained in the acceptance + if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) { + continue; + } + + if (jet.pt() < cfgjetPtMin) { + continue; + } + nJetssel++; + registryData.fill(HIST("MC/MCFJetaHistogramsel"), jet.eta()); + registryData.fill(HIST("MC/MCFJphiHistogramsel"), jet.phi()); + registryData.fill(HIST("MC/MCFJptHistogramsel"), jet.pt()); + + if (jet.pt() > maxJetPt) { + maxJetpx = jet.px(); + maxJetpy = jet.py(); + maxJetpz = jet.pz(); + maxJeteta = jet.eta(); + maxJetE = jet.E(); + maxJetphi = jet.phi(); + maxJetpT = jet.pt(); + maxJetPt = maxJetpT; + } + } + if (maxJetpT > 0) { + registryData.fill(HIST("MC/MCFLeadingJetaHistogramsel"), maxJeteta); + registryData.fill(HIST("MC/MCFLeadingJphiHistogramsel"), maxJetphi); + registryData.fill(HIST("MC/MCFLeadingJptHistogramsel"), maxJetpT); + } + registryData.fill(HIST("MC/MCnJetsPerEvent"), nJets); + registryData.fill(HIST("MC/MCnJetsPerEventsel"), nJetssel); + isAtLeastOneJetSelected = true; + if (!isAtLeastOneJetSelected) { + return; + } + // Event multiplicity + const float multiplicity = mcCollision.centFT0M(); + registryData.fill(HIST("MC/MCnumber_of_events_vsmultiplicity"), multiplicity); + // v0 loop + int V0Numbers = 0; + int AntiV0Numbers = 0; + + // loop over V0s + for (const auto& v0 : v0sThisCollision) { + if (!v0.has_mcParticle()) { + continue; + } + auto v0mcparticle = v0.mcParticle(); + if (std::abs(v0mcparticle.y()) > yMCcut) { + continue; + } + if (v0.v0Type() != v0TypeSelection) { + continue; + } + if (notITSAfterburner && (v0.negTrack_as().isITSAfterburner() || v0.posTrack_as().isITSAfterburner())) { + continue; + } + if (v0mcparticle.isPhysicalPrimary()) { + if (v0mcparticle.pdgCode() == 3122) { + registryData.fill(HIST("MC/Reconstructed_MCRecoColl_INEL_Lambda"), v0mcparticle.pt(), mcCollision.centFT0M()); // Lambda + if (evFlag == 1) { + registryData.fill(HIST("MC/Reconstructed_MCRecoColl_INELgt0_Lambda"), v0mcparticle.pt(), mcCollision.centFT0M()); // Lambda + } + } + if (v0mcparticle.pdgCode() == -3122) { + registryData.fill(HIST("MC/Reconstructed_MCRecoColl_INEL_AntiLambda"), v0mcparticle.pt(), mcCollision.centFT0M()); // AntiLambda + if (evFlag == 1) { + registryData.fill(HIST("MC/Reconstructed_MCRecoColl_INELgt0_AntiLambda"), v0mcparticle.pt(), mcCollision.centFT0M()); // AntiLambda + } + } + } + int lPDG = 0; + bool isDauLambda = false, isDauAntiLambda = false; + bool isprimary = false; + if (std::abs(v0mcparticle.pdgCode()) == 310 || std::abs(v0mcparticle.pdgCode()) == 3122) { // K0S or Lambda + lPDG = v0mcparticle.pdgCode(); + isprimary = v0mcparticle.isPhysicalPrimary(); + } + for (const auto& mcparticleDaughter0 : v0mcparticle.daughters_as()) { + for (const auto& mcparticleDaughter1 : v0mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == -211 && mcparticleDaughter1.pdgCode() == 2212) { // proton + pion^{-} + isDauLambda = true; + } + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -2212) { // antiproton + pion^{+} + isDauAntiLambda = true; + } + } + } + float ptMotherMC = 0.; + float pdgMother = 0.; + + if (std::abs(v0mcparticle.pdgCode()) == 3122 && v0mcparticle.has_mothers()) { + for (const auto& mcparticleMother0 : v0mcparticle.mothers_as()) { + if (std::abs(mcparticleMother0.pdgCode()) == 3312 || std::abs(mcparticleMother0.pdgCode()) == 3322) { + ptMotherMC = mcparticleMother0.pt(); + pdgMother = mcparticleMother0.pdgCode(); + } + } + } + + if (registryMCAcceptV0Lambda(v0, v0.posTrack_as(), v0.negTrack_as(), collision)) { + if (isMC && lPDG == 3122) { + if (isprimary == 1 && isDauLambda) { + V0Numbers = V0Numbers + 1; + registryData.fill(HIST("MC/hMassLambda_MC"), v0.mLambda()); + registryData.fill(HIST("MC/hMassVsPtLambdaVsCentFT0M_MC"), v0.pt(), mcCollision.centFT0M(), v0.mLambda()); + } + + } else if (isMC && lPDG == -3122) { + if (isprimary == 1 && isDauAntiLambda) { + AntiV0Numbers = AntiV0Numbers + 1; + registryData.fill(HIST("MC/hMassAntiLambda_MC"), v0.mAntiLambda()); + registryData.fill(HIST("MC/hMassVsPtAntiLambdaVsCentFT0M_MC"), v0.pt(), mcCollision.centFT0M(), v0.mAntiLambda()); + } + + } else if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0rejLambda) { + if (pdgMother == 3312) { + registryData.fill(HIST("MC/hFDVsPtLambdaVsMotherPt_DoubleCharged_MC"), v0.pt(), ptMotherMC, mcCollision.centFT0M()); + } + if (pdgMother == 3312 || pdgMother == 3322) { + registryData.fill(HIST("MC/hFDVsPtLambdaVsMotherPt_MCRatio_MC"), v0.pt(), ptMotherMC, mcCollision.centFT0M()); + } + } + } + } + registryData.fill(HIST("MC/MCnV0sPerEvent"), V0Numbers); + // calculate lambda polarization induced by jet + if (V0Numbers == 0 && AntiV0Numbers == 0) { + return; + } + if (maxJetpx == 0) { + return; + } + + // second loop over V0s + for (const auto& v0 : v0sThisCollision) { + if (!v0.has_mcParticle()) { + continue; + } + auto v0mcparticle = v0.mcParticle(); + if (std::abs(v0mcparticle.y()) > yMCcut) { + continue; + } + if (v0.v0Type() != v0TypeSelection) { + continue; + } + if (notITSAfterburner && (v0.negTrack_as().isITSAfterburner() || v0.posTrack_as().isITSAfterburner())) { + continue; + } + + int lPDG = 0; + bool isDauLambda = false, isDauAntiLambda = false; + bool isprimary = false; + if (std::abs(v0mcparticle.pdgCode()) == 310 || std::abs(v0mcparticle.pdgCode()) == 3122) { // K0S or Lambda + lPDG = v0mcparticle.pdgCode(); + isprimary = v0mcparticle.isPhysicalPrimary(); + } + for (const auto& mcparticleDaughter0 : v0mcparticle.daughters_as()) { + for (const auto& mcparticleDaughter1 : v0mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == -211 && mcparticleDaughter1.pdgCode() == 2212) { // proton + pion^{-} + isDauLambda = true; + } + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -2212) { // antiproton + pion^{+} + isDauAntiLambda = true; + } + } + } + // float ptMotherMC = 0.; + float pdgMother = 0.; + if (std::abs(v0mcparticle.pdgCode()) == 3122 && v0mcparticle.has_mothers()) { + for (const auto& mcparticleMother0 : v0mcparticle.mothers_as()) { + if (std::abs(mcparticleMother0.pdgCode()) == 3312 || std::abs(mcparticleMother0.pdgCode()) == 3322) { + // ptMotherMC = mcparticleMother0.pt(); + pdgMother = mcparticleMother0.pdgCode(); + } + } + } + + if (registryMCAcceptV0Lambda(v0, v0.posTrack_as(), v0.negTrack_as(), collision)) { + if (isMC && lPDG == 3122) { + if (isprimary == 1 && isDauLambda) { + const auto& pos = v0.posTrack_as(); + // const auto& neg = v0.negTrack_as(); + double PLambda = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + double ELambda = std::sqrt(v0.mLambda() * v0.mLambda() + PLambda * PLambda); + double protonE = std::sqrt(massPr * massPr + pos.px() * pos.px() + pos.py() * pos.py() + pos.pz() * pos.pz()); + + TMatrixD pLabJet(4, 1); + pLabJet(0, 0) = maxJetE; + pLabJet(1, 0) = maxJetpx; + pLabJet(2, 0) = maxJetpy; + pLabJet(3, 0) = maxJetpz; + + TMatrixD pLabV0(4, 1); + pLabV0(0, 0) = ELambda; + pLabV0(1, 0) = v0.px(); + pLabV0(2, 0) = v0.py(); + pLabV0(3, 0) = v0.pz(); + + TMatrixD V0InV0(4, 1); + V0InV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabV0; + registryData.fill(HIST("MC/V0pxInRest_frame"), V0InV0(1, 0)); + registryData.fill(HIST("MC/V0pyInRest_frame"), V0InV0(2, 0)); + registryData.fill(HIST("MC/V0pzInRest_frame"), V0InV0(3, 0)); + + TMatrixD lambdaInJet(4, 1); + lambdaInJet = MyTMatrixTranslationToJet(maxJetpx, maxJetpy, maxJetpz, v0.px(), v0.py(), v0.pz()) * pLabV0; + + TMatrixD pLabproton(4, 1); + pLabproton(0, 0) = protonE; + pLabproton(1, 0) = pos.px(); + pLabproton(2, 0) = pos.py(); + pLabproton(3, 0) = pos.pz(); + + TMatrixD protonInJetV0(4, 1); + protonInJetV0 = LorentzTransInV0frame(ELambda, lambdaInJet(1, 0), lambdaInJet(2, 0), lambdaInJet(3, 0)) * MyTMatrixTranslationToJet(maxJetpx, maxJetpy, maxJetpz, v0.px(), v0.py(), v0.pz()) * pLabproton; + double protonPinJetV0 = std::sqrt(protonInJetV0(1, 0) * protonInJetV0(1, 0) + protonInJetV0(2, 0) * protonInJetV0(2, 0) + protonInJetV0(3, 0) * protonInJetV0(3, 0)); + double protonCosThetainJetV0 = protonInJetV0(3, 0) / protonPinJetV0; + double protonCosThetaInJetV0frame = protonCosThetainJetV0; + registryData.fill(HIST("MC/TH2FprotonCosThetaInJetV0"), v0.mLambda(), protonCosThetaInJetV0frame); + registryData.fill(HIST("MC/TProfile1DprotonCosThetaInJetV0"), v0.mLambda(), protonCosThetaInJetV0frame); + registryData.fill(HIST("MC/TProfile1DprotonCos2ThetaInJetV0"), v0.mLambda(), protonCosThetaInJetV0frame * protonCosThetaInJetV0frame); + registryData.fill(HIST("MC/TProfile2DprotonCosThetaInJetV0"), v0.mLambda(), TMath::ATan2(lambdaInJet(2, 0), lambdaInJet(1, 0)), protonCosThetaInJetV0frame); + registryData.fill(HIST("MC/TProfile2DprotonCos2ThetaInJetV0"), v0.mLambda(), TMath::ATan2(lambdaInJet(2, 0), lambdaInJet(1, 0)), protonCosThetaInJetV0frame * protonCosThetaInJetV0frame); + registryData.fill(HIST("MC/TH1FprotonCosThetaInJetV0"), protonCosThetaInJetV0frame); + registryData.fill(HIST("MC/TH2FprotonCosThetaPhiInJetV0"), protonCosThetaInJetV0frame, TMath::ATan2(lambdaInJet(2, 0), lambdaInJet(1, 0))); + registryData.fill(HIST("MC/TH3DLambdaMassDeltaPhiDeltaCosTheta"), v0.mLambda(), TMath::ATan2(lambdaInJet(2, 0), lambdaInJet(1, 0)), protonCosThetaInJetV0frame); + } + } else if (isMC && lPDG == -3122) { + if (isprimary == 1 && isDauAntiLambda) { + continue; + } + + } else if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0rejLambda) { + if (pdgMother == 3312) { + continue; + } + if (pdgMother == 3312 || pdgMother == 3322) { + continue; + } + } + } + } + } + } + PROCESS_SWITCH(LambdaJetpolarization, processRun3MCReconstructed, "processRun3MCReconstructed", true); +}; + +struct LambdaJetpolarizationMCcount { + // Basic checks + HistogramRegistry registry{ + "registry", + { + {"hK0ShortCount", "hK0ShortCount", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hLambdaCount", "hLambdaCount", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hAntiLambdaCount", "hAntiLambdaCount", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hK0ShortCount_PtDiff", "hK0ShortCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hLambdaCount_PtDiff", "hLambdaCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hAntiLambdaCount_PtDiff", "hAntiLambdaCount_PtDiff", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + + {"hEventSelection", "hEventSelection", {HistType::kTH1F, {{1, 0.0f, 3.0f}}}}, + }, + }; + + void init(InitContext&) + { + registry.get(HIST("hK0ShortCount"))->GetXaxis()->SetBinLabel(1, "primary K0S mothers"); + registry.get(HIST("hK0ShortCount"))->GetXaxis()->SetBinLabel(2, "decaying into V0"); + registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(1, "primary Lambda mothers"); + registry.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(2, "decaying into V0"); + registry.get(HIST("hAntiLambdaCount"))->GetXaxis()->SetBinLabel(1, "primary AntiLambda mothers"); + registry.get(HIST("hAntiLambdaCount"))->GetXaxis()->SetBinLabel(2, "decaying into V0"); + + registry.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + registry.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(2, "Sel8 cut"); + registry.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(3, "posZ cut"); + } + + Configurable rapidityMCcut{"rapidityMCcut", 0.5f, "rapidity cut MC count"}; + Configurable eventSel8selection{"eventSel8selection", true, "event selection MC count post sel8 cut"}; + Configurable eventPosZselection{"eventPosZselection", true, "event selection MC count post posZ cut"}; + Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; + void processMC(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions) + { + std::vector SelectedEvents(collisions.size()); + int nevts = 0; + for (const auto& collision : collisions) { + if (eventSel8selection && !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(); + + registry.fill(HIST("hEventSelection"), 0.5); + if (!evtReconstructedAndSelected) { + return; + } + registry.fill(HIST("hEventSelection"), 1.5); + if (eventPosZselection && std::abs(mcCollision.posZ()) > zVtx) { + return; + } + registry.fill(HIST("hEventSelection"), 2.5); + + for (const auto& mcparticle : mcParticles) { + if (TMath::Abs(mcparticle.y()) < rapidityMCcut) { + if (mcparticle.isPhysicalPrimary()) { + if (!mcparticle.has_daughters()) { + continue; + } + if (mcparticle.pdgCode() == 310) { + registry.fill(HIST("hK0ShortCount"), 0.5); + registry.fill(HIST("hK0ShortCount_PtDiff"), mcparticle.pt()); + for (const auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (const auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -211) { + registry.fill(HIST("hK0ShortCount"), 1.5); + } + } + } + } + if (mcparticle.pdgCode() == 3122) { + registry.fill(HIST("hLambdaCount"), 0.5); + registry.fill(HIST("hLambdaCount_PtDiff"), mcparticle.pt()); + for (const auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (const auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == -211 && mcparticleDaughter1.pdgCode() == 2212) { + registry.fill(HIST("hLambdaCount"), 1.5); + } + } + } + } + if (mcparticle.pdgCode() == -3122) { + registry.fill(HIST("hAntiLambdaCount"), 0.5); + registry.fill(HIST("hAntiLambdaCount_PtDiff"), mcparticle.pt()); + for (const auto& mcparticleDaughter0 : mcparticle.daughters_as()) { + for (const auto& mcparticleDaughter1 : mcparticle.daughters_as()) { + if (mcparticleDaughter0.pdgCode() == 211 && mcparticleDaughter1.pdgCode() == -2212) { + registry.fill(HIST("hAntiLambdaCount"), 1.5); + } + } + } + } + } + } + } + } + PROCESS_SWITCH(LambdaJetpolarizationMCcount, processMC, "processMC", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; // TaskName{"lambdaJetpolarization"} + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/Strangeness/lambdapolarization.cxx b/PWGLF/Tasks/Strangeness/lambdapolarization.cxx index 772b5d04e7f..e098bc622e4 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolarization.cxx @@ -63,7 +63,7 @@ using namespace o2::constants::physics; struct lambdapolarization { // using EventCandidates = soa::Filtered>; - using EventCandidates = soa::Join; + using EventCandidates = soa::Join; using TrackCandidates = soa::Join; using V0TrackCandidate = aod::V0Datas; @@ -84,6 +84,7 @@ struct lambdapolarization { Configurable cfgCentSel{"cfgCentSel", 80., "Centrality selection"}; Configurable cfgCentEst{"cfgCentEst", 1, "Centrality estimator, 1: FT0C, 2: FT0M"}; + Configurable cfgCentEstFT0CVariant2{"cfgCentEstFT0CVariant2", false, "flag to replace the estimator with centFT0CVariant2"}; Configurable cfgPVSel{"cfgPVSel", false, "Additional PV selection flag for syst"}; Configurable cfgPV{"cfgPV", 8.0, "Additional PV selection range for syst"}; @@ -918,6 +919,9 @@ struct lambdapolarization { { if (cfgCentEst == 1) { centrality = collision.centFT0C(); + if (cfgCentEstFT0CVariant2) { + centrality = collision.centFT0CVariant2(); + } } else if (cfgCentEst == 2) { centrality = collision.centFT0M(); } diff --git a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx index 1f2ecd4b580..c181e4293c0 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx @@ -88,6 +88,9 @@ struct lambdapolsp { Service pdg; o2::ccdb::CcdbApi ccdbApi; TH1D* hwgtAL; + TH1D* heffL; + TH1D* heffAL; + TH1D* hwgtRESO; // fill output struct : ConfigurableGroup { Configurable additionalEvSel{"additionalEvSel", false, "additionalEvSel"}; @@ -99,6 +102,7 @@ struct lambdapolsp { } evselGrp; Configurable globalpt{"globalpt", true, "select tracks based on pt global vs tpc"}; Configurable cqvas{"cqvas", false, "change q vectors after shift correction"}; + Configurable normbymag{"normbymag", false, "normalize by magnitude of q vectors for SP"}; Configurable useprofile{"useprofile", 3, "flag to select profile vs Sparse"}; Configurable sys{"sys", 1, "flag to select systematic source"}; Configurable centestim{"centestim", 0, "flag to select centrality estimator"}; @@ -151,10 +155,16 @@ struct lambdapolsp { Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for Lambda daughters"}; Configurable usesubdet{"usesubdet", false, "use subdet"}; Configurable useAccCorr{"useAccCorr", false, "use acceptance correction"}; + Configurable useResoRBR{"useResoRBR", false, "use resolution correction RBR"}; Configurable useyldwgt{"useyldwgt", false, "use yield weight"}; + Configurable useeffwgt{"useeffwgt", false, "use eff weight"}; + Configurable usepsisubbeforeshift{"usepsisubbeforeshift", false, "use psi for sub detectors before shift modification"}; Configurable ConfAccPathL{"ConfAccPathL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_28032025/acccorrL", "Path to acceptance correction for Lambda"}; Configurable ConfAccPathAL{"ConfAccPathAL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_28032025/acccorrAL", "Path to acceptance correction for AntiLambda"}; Configurable ConfWgtPathAL{"ConfWgtPathAL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_10082025/yieldweight2050", "Path to yield weight correction for AntiLambda"}; + Configurable ConfEffWgtPathL{"ConfEffWgtPathL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_10082025/yieldweight2050", "Path to eff weight correction for Lambda"}; + Configurable ConfEffWgtPathAL{"ConfEffWgtPathAL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_10082025/yieldweight2050", "Path to eff weight correction for AntiLambda"}; + Configurable ConfResoPath{"ConfResoPath", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_28032025/acccorrL", "Path to resolution correction run by run"}; struct : ConfigurableGroup { Configurable QxyNbins{"QxyNbins", 100, "Number of bins in QxQy histograms"}; @@ -184,6 +194,16 @@ struct lambdapolsp { ConfigurableAxis configbinAxis{"configbinAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "BA"}; */ // ConfigurableAxis configphiAxis{"configphiAxis", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.8, 1.0, 2.0, 2.5, 3.0, 4.0, 5.0, 5.5, 6.28}, "PhiAxis"}; + + struct : ConfigurableGroup { + Configurable isQA{"isQA", true, "Flag to fill QA"}; + ConfigurableAxis centfineAxis{"centfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Cent V0M"}; + ConfigurableAxis vxfineAxis{"vxfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "vx fine axis"}; + ConfigurableAxis vyfineAxis{"vyfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "vy fine axis"}; + ConfigurableAxis vzfineAxis{"vzfineAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "vz fine axis"}; + ConfigurableAxis qxZDCAxis{"qxZDCAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "qx axis"}; + ConfigurableAxis psiAxis{"psiAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "psi axis"}; + } QAgrp; struct : ConfigurableGroup { Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; @@ -197,12 +217,13 @@ struct lambdapolsp { ConfigurableAxis configthnAxisPol{"configthnAxisPol", {VARIABLE_WIDTH, -1.0, -0.6, -0.2, 0, 0.2, 0.4, 0.8}, "Pol"}; ConfigurableAxis configbinAxis{"configbinAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "BA"}; } axisGrp; + /* struct : ConfigurableGroup { ConfigurableAxis axisVertex{"axisVertex", {5, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {8, 0, 80}, "multiplicity percentile for bin"}; Configurable nMix{"nMix", 5, "number of event mixing"}; } meGrp; - + */ struct : ConfigurableGroup { ConfigurableAxis axisCosine{"axisCosine", {100, 0, 1}, "cosine axis"}; ConfigurableAxis axisRadius{"axisRadius", {200, 0, 100}, "radius axis"}; @@ -214,6 +235,8 @@ struct lambdapolsp { Configurable filldist{"filldist", true, "fill topo distr"}; Configurable lowmasscut{"lowmasscut", 1.11, "low mass cut"}; Configurable highmasscut{"highmasscut", 1.12, "high mass cut"}; + ConfigurableAxis axiscosphiminuspsi{"axiscosphiminuspsi", {200, -1, 1}, "cosphiminuspsi"}; + ConfigurableAxis axiseta{"axiseta", {16, -0.8, 0.8}, "eta axis"}; } distGrp; RCTFlagsChecker rctChecker; @@ -360,6 +383,12 @@ struct lambdapolsp { histos.add("hcentQyZDCA", "hcentQyZDCA", kTH2F, {axisGrp.configcentAxis, spAxis}); histos.add("hcentQxZDCC", "hcentQxZDCC", kTH2F, {axisGrp.configcentAxis, spAxis}); histos.add("hcentQyZDCC", "hcentQyZDCC", kTH2F, {axisGrp.configcentAxis, spAxis}); + + histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); } if (usesubdet) { histos.add("hSparseLambdaCosPsiA", "hSparseLambdaCosPsiA", HistType::kTHnSparseF, runaxes, true); @@ -414,7 +443,7 @@ struct lambdapolsp { } if (distGrp.filldist) { - histos.add("hcosinelambda", "hcosinelambda", HistType::kTH1D, {distGrp.axisCosine}, true); + /*histos.add("hcosinelambda", "hcosinelambda", HistType::kTH1D, {distGrp.axisCosine}, true); histos.add("hdcabwv0daughlambda", "hdcabwv0daughlambda", HistType::kTH1D, {distGrp.axisDca}, true); histos.add("hlifetimelambda", "hlifetimelambda", HistType::kTH1D, {distGrp.axisLT}, true); histos.add("hradiuslambda", "hradiuslambda", HistType::kTH1D, {distGrp.axisRadius}, true); @@ -437,6 +466,13 @@ struct lambdapolsp { histos.add("htpcnegantilambda", "htpcnegantilambda", HistType::kTH1D, {distGrp.axisnsig}, true); histos.add("hptposantilambda", "hptposantilambda", HistType::kTH1D, {distGrp.axispt}, true); histos.add("hptnegantilambda", "hptnegantilambda", HistType::kTH1D, {distGrp.axispt}, true); + */ + histos.add("hALcosphiminuspsiCvseta", "hALcosphiminuspsiCvseta", HistType::kTH2D, {{distGrp.axiscosphiminuspsi}, {distGrp.axiseta}}); + histos.add("hALcosphiminuspsiAvseta", "hALcosphiminuspsiAvseta", HistType::kTH2D, {{distGrp.axiscosphiminuspsi}, {distGrp.axiseta}}); + histos.add("hALcosphiminuspsivseta", "hALcosphiminuspsivseta", HistType::kTH2D, {{distGrp.axiscosphiminuspsi}, {distGrp.axiseta}}); + histos.add("hLcosphiminuspsiCvseta", "hLcosphiminuspsiCvseta", HistType::kTH2D, {{distGrp.axiscosphiminuspsi}, {distGrp.axiseta}}); + histos.add("hLcosphiminuspsiAvseta", "hLcosphiminuspsiAvseta", HistType::kTH2D, {{distGrp.axiscosphiminuspsi}, {distGrp.axiseta}}); + histos.add("hLcosphiminuspsivseta", "hLcosphiminuspsivseta", HistType::kTH2D, {{distGrp.axiscosphiminuspsi}, {distGrp.axiseta}}); } histos.add("hSparseGenLambda", "hSparseGenLambda", HistType::kTHnSparseF, runaxes2, true); @@ -444,6 +480,32 @@ struct lambdapolsp { histos.add("hSparseRecLambda", "hSparseRecLambda", HistType::kTHnSparseF, runaxes2, true); histos.add("hSparseRecAntiLambda", "hSparseRecAntiLambda", HistType::kTHnSparseF, runaxes2, true); + if (QAgrp.isQA) { + histos.add("hCentQxZDCA", "hCentQxZDCA", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hCentQyZDCA", "hCentQyZDCA", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hCentQxZDCC", "hCentQxZDCC", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hCentQyZDCC", "hCentQyZDCC", kTH2F, {{QAgrp.centfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("hvxQxZDCA", "hvxQxZDCA", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvxQyZDCA", "hvxQyZDCA", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvxQxZDCC", "hvxQxZDCC", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvxQyZDCC", "hvxQyZDCC", kTH2F, {{QAgrp.vxfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("hvyQxZDCA", "hvyQxZDCA", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvyQyZDCA", "hvyQyZDCA", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvyQxZDCC", "hvyQxZDCC", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvyQyZDCC", "hvyQyZDCC", kTH2F, {{QAgrp.vyfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("hvzQxZDCA", "hvzQxZDCA", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvzQyZDCA", "hvzQyZDCA", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvzQxZDCC", "hvzQxZDCC", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + histos.add("hvzQyZDCC", "hvzQyZDCC", kTH2F, {{QAgrp.vzfineAxis}, {QAgrp.qxZDCAxis}}); + + histos.add("PsiZDCC", "PsiZDCC", kTH2F, {QAgrp.centfineAxis, QAgrp.psiAxis}); + histos.add("PsiZDCA", "PsiZDCA", kTH2F, {QAgrp.centfineAxis, QAgrp.psiAxis}); + histos.add("PsiZDC", "PsiZDC", kTH2F, {QAgrp.centfineAxis, QAgrp.psiAxis}); + } + ccdb->setURL(cfgCcdbParam.cfgURL); ccdbApi.init("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -451,6 +513,12 @@ struct lambdapolsp { ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); LOGF(info, "Getting alignment offsets from the CCDB..."); hwgtAL = ccdb->getForTimeStamp(ConfWgtPathAL.value, cfgCcdbParam.nolaterthan.value); + if (useeffwgt) { + heffL = ccdb->getForTimeStamp(ConfEffWgtPathL.value, cfgCcdbParam.nolaterthan.value); + heffAL = ccdb->getForTimeStamp(ConfEffWgtPathAL.value, cfgCcdbParam.nolaterthan.value); + } + if (useResoRBR) + hwgtRESO = ccdb->getForTimeStamp(ConfResoPath.value, cfgCcdbParam.nolaterthan.value); } template @@ -683,7 +751,7 @@ struct lambdapolsp { void fillHistograms(bool tag1, bool tag2, const ROOT::Math::PxPyPzMVector& particle, const ROOT::Math::PxPyPzMVector& daughter, double psiZDCC, double psiZDCA, double psiZDC, double centrality, - double candmass, double candpt, float desbinvalue, double acvalue, double wgtfactor) + double candmass, double candpt, float desbinvalue, double acvalue, double wgtfactor, double resowgt) { TRandom3 randPhi(0); @@ -705,14 +773,17 @@ struct lambdapolsp { auto PolC = TMath::Sin(phiminuspsiC); auto PolA = TMath::Sin(phiminuspsiA); auto Pol = TMath::Sin(phiminuspsi); - // auto PolSP = uy * TMath::Cos(psiZDC) - ux * TMath::Sin(psiZDC); - auto PolSP = uy * (modqxZDCC - modqxZDCA) - ux * (modqyZDCC - modqyZDCA); auto sinPhiStar = TMath::Sin(GetPhiInRange(phiangle)); auto cosPhiStar = TMath::Cos(GetPhiInRange(phiangle)); // auto sinThetaStarcosphiphiStar = sinThetaStar * TMath::Cos(2 * GetPhiInRange(particle.Phi() - phiangle)); // auto phiphiStar = GetPhiInRange(particle.Phi() - phiangle); acvalue = (4 / 3.14) * acvalue; + if (useResoRBR) { + Pol = Pol / resowgt; + PolA = PolA / resowgt; + PolC = PolC / resowgt; + } // PolC = PolC / acvalue; // PolA = PolA / acvalue; // Pol = Pol / acvalue; @@ -720,8 +791,26 @@ struct lambdapolsp { auto PolAwgt = PolA / acvalue; auto PolCwgt = PolC / acvalue; - if (randGrp.useSP) + // for SP calculation + const double qx = (modqxZDCC - modqxZDCA); + const double qy = (modqyZDCC - modqyZDCA); + const double qmag = std::sqrt(qx * qx + qy * qy); + auto PolSP = uy * (modqxZDCC - modqxZDCA) - ux * (modqyZDCC - modqyZDCA); + if (normbymag && qmag > 0.0) + PolSP = PolSP / qmag; + // SP numerators with A and C separately (use Q components) + auto PolSP_A = uy * modqxZDCA - ux * modqyZDCA; // u_y QxA - u_x QyA + auto PolSP_C = uy * modqxZDCC - ux * modqyZDCC; // u_y QxC - u_x QyC + + if (randGrp.useSP) { + Pol = PolSP; + PolA = PolSP_A; + PolC = PolSP_C; Polwgt = PolSP / acvalue; + PolAwgt = PolSP_A / acvalue; + PolCwgt = PolSP_C / acvalue; + } + ////////////////////////////// // Fill histograms using constructed names if (tag2) { @@ -773,6 +862,10 @@ struct lambdapolsp { // histos.fill(HIST("hSparseAntiLambda_corr1c"), candmass, candpt, phiphiStar, centrality, wgtfactor); histos.fill(HIST("hSparseAntiLambda_corr2a"), candmass, candpt, sinThetaStar, centrality, wgtfactor); // histos.fill(HIST("hSparseAntiLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality, wgtfactor); + if (randGrp.useSP) { + histos.fill(HIST("hSparseAntiLambda_avgux"), candmass, candpt, ux, centrality); + histos.fill(HIST("hSparseAntiLambda_avguy"), candmass, candpt, uy, centrality); + } } } if (tag1) { @@ -824,6 +917,10 @@ struct lambdapolsp { // histos.fill(HIST("hSparseLambda_corr1c"), candmass, candpt, phiphiStar, centrality, wgtfactor); histos.fill(HIST("hSparseLambda_corr2a"), candmass, candpt, sinThetaStar, centrality, wgtfactor); // histos.fill(HIST("hSparseLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality, wgtfactor); + if (randGrp.useSP) { + histos.fill(HIST("hSparseLambda_avgux"), candmass, candpt, ux, centrality); + histos.fill(HIST("hSparseLambda_avguy"), candmass, candpt, uy, centrality); + } } } } @@ -901,13 +998,20 @@ struct lambdapolsp { // currentRunNumber = collision.foundBC_as().runNumber(); auto bc = collision.foundBC_as(); + auto vz = collision.vz(); + auto vx = collision.vx(); + auto vy = collision.vy(); + auto qxZDCA = collision.qxZDCA(); auto qxZDCC = collision.qxZDCC(); auto qyZDCA = collision.qyZDCA(); auto qyZDCC = collision.qyZDCC(); auto psiZDCC = collision.psiZDCC(); auto psiZDCA = collision.psiZDCA(); - + if (usepsisubbeforeshift) { + psiZDCC = 1.0 * std::atan2(qyZDCC, qxZDCC); + psiZDCA = 1.0 * std::atan2(qyZDCA, qxZDCA); + } if (cqvas) { modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); @@ -921,20 +1025,42 @@ struct lambdapolsp { } auto psiZDC = TMath::ATan2((modqyZDCC - modqyZDCA), (modqxZDCC - modqxZDCA)); // full event plane*/ + /*if (useonlypsis) { psiZDC = psiZDCC - psiZDCA; }*/ + if (QAgrp.isQA) { + histos.fill(HIST("hCentQxZDCA"), centrality, modqxZDCA); + histos.fill(HIST("hCentQyZDCA"), centrality, modqyZDCA); + histos.fill(HIST("hCentQxZDCC"), centrality, modqxZDCC); + histos.fill(HIST("hCentQyZDCC"), centrality, modqyZDCC); + + histos.fill(HIST("hvxQxZDCA"), vx, modqxZDCA); + histos.fill(HIST("hvxQyZDCA"), vx, modqyZDCA); + histos.fill(HIST("hvxQxZDCC"), vx, modqxZDCC); + histos.fill(HIST("hvxQyZDCC"), vx, modqyZDCC); + + histos.fill(HIST("hvyQxZDCA"), vy, modqxZDCA); + histos.fill(HIST("hvyQyZDCA"), vy, modqyZDCA); + histos.fill(HIST("hvyQxZDCC"), vy, modqxZDCC); + histos.fill(HIST("hvyQyZDCC"), vy, modqyZDCC); + + histos.fill(HIST("hvzQxZDCA"), vz, modqxZDCA); + histos.fill(HIST("hvzQyZDCA"), vz, modqyZDCA); + histos.fill(HIST("hvzQxZDCC"), vz, modqxZDCC); + histos.fill(HIST("hvzQyZDCC"), vz, modqyZDCC); + + histos.fill(HIST("PsiZDCA"), centrality, psiZDCA); + histos.fill(HIST("PsiZDCC"), centrality, psiZDCC); + histos.fill(HIST("PsiZDC"), centrality, psiZDC); + } + histos.fill(HIST("hCentrality"), centrality); if (!checkwithpub) { // histos.fill(HIST("hVtxZ"), collision.posZ()); if (randGrp.useSP) { histos.fill(HIST("hpRes"), centrality, ((modqxZDCA * modqxZDCC) + (modqyZDCA * modqyZDCC))); - // histos.fill(HIST("hpResSin"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA - psiZDCC)))); - /*histos.fill(HIST("hpCosPsiA"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA)))); - histos.fill(HIST("hpCosPsiC"), centrality, (TMath::Cos(GetPhiInRange(psiZDCC)))); - histos.fill(HIST("hpSinPsiA"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA)))); - histos.fill(HIST("hpSinPsiC"), centrality, (TMath::Sin(GetPhiInRange(psiZDCC))));*/ histos.fill(HIST("hcentQxZDCA"), centrality, modqxZDCA); histos.fill(HIST("hcentQyZDCA"), centrality, modqyZDCA); histos.fill(HIST("hcentQxZDCC"), centrality, modqxZDCC); @@ -944,6 +1070,15 @@ struct lambdapolsp { } } + double resowgt = 1.0; + + if (useResoRBR) { + int binxreso = hwgtRESO->GetXaxis()->FindBin(centrality + 0.000001); + resowgt = hwgtRESO->GetBinContent(binxreso); + } else { + resowgt = 1.0; + } + ///////////checking v1//////////////////////////////// if (checkwithpub) { @@ -1138,7 +1273,6 @@ struct lambdapolsp { int taga = LambdaTag; int tagb = aLambdaTag; - // if (useAccCorr && (currentRunNumber != lastRunNumber)) { if (useAccCorr) { accprofileL = ccdb->getForTimeStamp(ConfAccPathL.value, bc.timestamp()); accprofileAL = ccdb->getForTimeStamp(ConfAccPathAL.value, bc.timestamp()); @@ -1153,142 +1287,74 @@ struct lambdapolsp { wgtvalue = 1.0; } - float desbinvalue = 0.0; - if (dosystematic) { - //////////////////////////////////////////////////// - float LTsys = TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda); - float CPAsys = v0.v0cosPA(); - float DCADaughsys = TMath::Abs(v0.dcaV0daughters()); - float DCApossys = TMath::Abs(v0.dcapostopv()); - float DCAnegsys = TMath::Abs(v0.dcanegtopv()); - float sysvar = -999.9; - double syst[10]; - if (sys == 1) { - double temp[10] = {26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = LTsys; - } - if (sys == 2) { - double temp[10] = {0.992, 0.993, 0.9935, 0.994, 0.9945, 0.995, 0.9955, 0.996, 0.9965, 0.997}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = CPAsys; - } - if (sys == 3) { - double temp[10] = {0.8, 0.85, 0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = DCADaughsys; - } - if (sys == 4) { - double temp[10] = {0.05, 0.07, 0.1, 0.15, 0.18, 0.2, 0.22, 0.25, 0.28, 0.3}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = DCApossys; + if (LambdaTag) { + Lambda = Proton + AntiPion; + tagb = 0; + if (useAccCorr) { + int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); + int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); + acvalue = accprofileL->GetBinContent(binx, biny); + } else { + acvalue = 1.0; } - if (sys == 5) { - double temp[10] = {0.05, 0.07, 0.1, 0.15, 0.18, 0.2, 0.22, 0.25, 0.28, 0.3}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = DCAnegsys; + if (distGrp.filldist && aLambdaTag == 0 && Lambda.M() > distGrp.lowmasscut && Lambda.M() < distGrp.highmasscut) { + /*histos.fill(HIST("hcosinelambda"), v0.v0cosPA()); + histos.fill(HIST("hdcabwv0daughlambda"), v0.dcaV0daughters()); + histos.fill(HIST("hlifetimelambda"), TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda)); + histos.fill(HIST("hradiuslambda"), v0.v0radius()); + histos.fill(HIST("htpcCRlambda"), postrack.tpcNClsCrossedRows()); + histos.fill(HIST("hdcaposlambda"), v0.dcapostopv()); + histos.fill(HIST("hdcaneglambda"), v0.dcanegtopv()); + histos.fill(HIST("htpcposlambda"), postrack.tpcNSigmaPr()); + histos.fill(HIST("htpcneglambda"), negtrack.tpcNSigmaPi()); + histos.fill(HIST("hptposlambda"), Proton.Pt()); + histos.fill(HIST("hptneglambda"), AntiPion.Pt());*/ + auto phiL = TMath::ATan2(v0.py(), v0.px()); + auto LcosphiminuspsiC = TMath::Cos(GetPhiInRange(phiL - psiZDCC)); + auto LcosphiminuspsiA = TMath::Cos(GetPhiInRange(phiL - psiZDCA)); + auto Lcosphiminuspsi = TMath::Cos(GetPhiInRange(phiL - psiZDC)); + histos.fill(HIST("hLcosphiminuspsiCvseta"), LcosphiminuspsiC, v0.eta()); + histos.fill(HIST("hLcosphiminuspsiAvseta"), LcosphiminuspsiA, v0.eta()); + histos.fill(HIST("hLcosphiminuspsivseta"), Lcosphiminuspsi, v0.eta()); } + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue, 1.0, resowgt); + } - for (int i = 0; i < 10; i++) { - if (sys == 1 || sys == 3) { - if (sysvar < syst[i]) - desbinvalue = i + 0.5; - else - continue; - } - if (sys == 2 || sys == 4 || sys == 5) { - if (sysvar > syst[i]) - desbinvalue = i + 0.5; - else - continue; - } - - /////////////////////////////////////////////////// - if (LambdaTag) { - Lambda = Proton + AntiPion; - tagb = 0; - if (useAccCorr) { - int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); - int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); - acvalue = accprofileL->GetBinContent(binx, biny); - } else { - acvalue = 1.0; - } - - fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), desbinvalue, acvalue, 1.0); - } - - tagb = aLambdaTag; - if (aLambdaTag) { - AntiLambda = AntiProton + Pion; - taga = 0; - if (useAccCorr) { - int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); - int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); - acvalue = accprofileAL->GetBinContent(binx, biny); - } else { - acvalue = 1.0; - } - fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), desbinvalue, acvalue, 1.0); - } - } - } else { - if (LambdaTag) { - Lambda = Proton + AntiPion; - tagb = 0; - if (useAccCorr) { - int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); - int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); - acvalue = accprofileL->GetBinContent(binx, biny); - } else { - acvalue = 1.0; - } - if (distGrp.filldist && aLambdaTag == 0 && Lambda.M() > distGrp.lowmasscut && Lambda.M() < distGrp.highmasscut) { - histos.fill(HIST("hcosinelambda"), v0.v0cosPA()); - histos.fill(HIST("hdcabwv0daughlambda"), v0.dcaV0daughters()); - histos.fill(HIST("hlifetimelambda"), TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda)); - histos.fill(HIST("hradiuslambda"), v0.v0radius()); - histos.fill(HIST("htpcCRlambda"), postrack.tpcNClsCrossedRows()); - histos.fill(HIST("hdcaposlambda"), v0.dcapostopv()); - histos.fill(HIST("hdcaneglambda"), v0.dcanegtopv()); - histos.fill(HIST("htpcposlambda"), postrack.tpcNSigmaPr()); - histos.fill(HIST("htpcneglambda"), negtrack.tpcNSigmaPi()); - histos.fill(HIST("hptposlambda"), Proton.Pt()); - histos.fill(HIST("hptneglambda"), AntiPion.Pt()); - } - fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue, 1.0); + tagb = aLambdaTag; + if (aLambdaTag) { + AntiLambda = AntiProton + Pion; + taga = 0; + if (useAccCorr) { + int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); + int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); + acvalue = accprofileAL->GetBinContent(binx, biny); + } else { + acvalue = 1.0; } - - tagb = aLambdaTag; - if (aLambdaTag) { - AntiLambda = AntiProton + Pion; - taga = 0; - if (useAccCorr) { - int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); - int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); - acvalue = accprofileAL->GetBinContent(binx, biny); - } else { - acvalue = 1.0; - } - if (distGrp.filldist && LambdaTag == 0 && AntiLambda.M() > distGrp.lowmasscut && AntiLambda.M() < distGrp.highmasscut) { - histos.fill(HIST("hcosineantilambda"), v0.v0cosPA()); - histos.fill(HIST("hdcabwv0daughantilambda"), v0.dcaV0daughters()); - histos.fill(HIST("hlifetimeantilambda"), TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda)); - histos.fill(HIST("hradiusantilambda"), v0.v0radius()); - histos.fill(HIST("htpcCRantilambda"), postrack.tpcNClsCrossedRows()); - histos.fill(HIST("hdcaposantilambda"), v0.dcapostopv()); - histos.fill(HIST("hdcanegantilambda"), v0.dcanegtopv()); - histos.fill(HIST("htpcposantilambda"), postrack.tpcNSigmaPi()); - histos.fill(HIST("htpcnegantilambda"), negtrack.tpcNSigmaPr()); - histos.fill(HIST("hptposantilambda"), Pion.Pt()); - histos.fill(HIST("hptnegantilambda"), AntiProton.Pt()); - } - fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, wgtvalue); + if (distGrp.filldist && LambdaTag == 0 && AntiLambda.M() > distGrp.lowmasscut && AntiLambda.M() < distGrp.highmasscut) { + /*histos.fill(HIST("hcosineantilambda"), v0.v0cosPA()); + histos.fill(HIST("hdcabwv0daughantilambda"), v0.dcaV0daughters()); + histos.fill(HIST("hlifetimeantilambda"), TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda)); + histos.fill(HIST("hradiusantilambda"), v0.v0radius()); + histos.fill(HIST("htpcCRantilambda"), postrack.tpcNClsCrossedRows()); + histos.fill(HIST("hdcaposantilambda"), v0.dcapostopv()); + histos.fill(HIST("hdcanegantilambda"), v0.dcanegtopv()); + histos.fill(HIST("htpcposantilambda"), postrack.tpcNSigmaPi()); + histos.fill(HIST("htpcnegantilambda"), negtrack.tpcNSigmaPr()); + histos.fill(HIST("hptposantilambda"), Pion.Pt()); + histos.fill(HIST("hptnegantilambda"), AntiProton.Pt());*/ + auto phiAL = TMath::ATan2(v0.py(), v0.px()); + auto ALcosphiminuspsiC = TMath::Cos(GetPhiInRange(phiAL - psiZDCC)); + auto ALcosphiminuspsiA = TMath::Cos(GetPhiInRange(phiAL - psiZDCA)); + auto ALcosphiminuspsi = TMath::Cos(GetPhiInRange(phiAL - psiZDC)); + histos.fill(HIST("hALcosphiminuspsiCvseta"), ALcosphiminuspsiC, v0.eta()); + histos.fill(HIST("hALcosphiminuspsiAvseta"), ALcosphiminuspsiA, v0.eta()); + histos.fill(HIST("hALcosphiminuspsivseta"), ALcosphiminuspsi, v0.eta()); } + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, wgtvalue, resowgt); } } } - // lastRunNumber = currentRunNumber; } PROCESS_SWITCH(lambdapolsp, processData, "Process data", true); @@ -1310,8 +1376,11 @@ struct lambdapolsp { else if (centestim == 3) centrality = collision.centFV0A(); + auto vz = collision.posZ(); + auto vx = collision.posX(); + auto vy = collision.posY(); + auto runnumber = collision.runNumber(); - // auto centrality = collision.centFT0C(); if (!collision.triggereventsp()) { // provided by StraZDCSP return; } @@ -1337,14 +1406,6 @@ struct lambdapolsp { return; } - /*currentRunNumber = collision.foundBC_as().runNumber(); - auto bc = collision.foundBC_as(); - - if (useAccCorr && (currentRunNumber != lastRunNumber)) { - accprofileL = ccdb->getForTimeStamp(ConfAccPathL.value, bc.timestamp()); - accprofileAL = ccdb->getForTimeStamp(ConfAccPathAL.value, bc.timestamp()); - } - */ auto timestamps = ccdb->getRunDuration(runnumber, 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 @@ -1363,11 +1424,10 @@ struct lambdapolsp { auto qyZDCC = collision.qyZDCC(); auto psiZDCC = collision.psiZDCC(); auto psiZDCA = collision.psiZDCA(); - /*double modqxZDCA; - double modqyZDCA; - double modqxZDCC; - double modqyZDCC;*/ - + if (usepsisubbeforeshift) { + psiZDCC = 1.0 * std::atan2(qyZDCC, qxZDCC); + psiZDCA = 1.0 * std::atan2(qyZDCA, qxZDCA); + } if (cqvas) { modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); @@ -1382,26 +1442,76 @@ struct lambdapolsp { auto psiZDC = TMath::ATan2((modqyZDCC - modqyZDCA), (modqxZDCC - modqxZDCA)); // full event plane + if (QAgrp.isQA) { + histos.fill(HIST("hCentQxZDCA"), centrality, modqxZDCA); + histos.fill(HIST("hCentQyZDCA"), centrality, modqyZDCA); + histos.fill(HIST("hCentQxZDCC"), centrality, modqxZDCC); + histos.fill(HIST("hCentQyZDCC"), centrality, modqyZDCC); + + histos.fill(HIST("hvxQxZDCA"), vx, modqxZDCA); + histos.fill(HIST("hvxQyZDCA"), vx, modqyZDCA); + histos.fill(HIST("hvxQxZDCC"), vx, modqxZDCC); + histos.fill(HIST("hvxQyZDCC"), vx, modqyZDCC); + + histos.fill(HIST("hvyQxZDCA"), vy, modqxZDCA); + histos.fill(HIST("hvyQyZDCA"), vy, modqyZDCA); + histos.fill(HIST("hvyQxZDCC"), vy, modqxZDCC); + histos.fill(HIST("hvyQyZDCC"), vy, modqyZDCC); + + histos.fill(HIST("hvzQxZDCA"), vz, modqxZDCA); + histos.fill(HIST("hvzQyZDCA"), vz, modqyZDCA); + histos.fill(HIST("hvzQxZDCC"), vz, modqxZDCC); + histos.fill(HIST("hvzQyZDCC"), vz, modqyZDCC); + + histos.fill(HIST("PsiZDCA"), centrality, psiZDCA); + histos.fill(HIST("PsiZDCC"), centrality, psiZDCC); + histos.fill(HIST("PsiZDC"), centrality, psiZDC); + } + // fill histograms histos.fill(HIST("hCentrality"), centrality); if (!checkwithpub) { // histos.fill(HIST("hVtxZ"), collision.posZ()); if (randGrp.useSP) { - histos.fill(HIST("hpRes"), centrality, ((modqxZDCA * modqxZDCC) + (modqyZDCA * modqyZDCC))); - // histos.fill(HIST("hpResSin"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA - psiZDCC)))); - /*histos.fill(HIST("hpCosPsiA"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA)))); - histos.fill(HIST("hpCosPsiC"), centrality, (TMath::Cos(GetPhiInRange(psiZDCC)))); - histos.fill(HIST("hpSinPsiA"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA)))); - histos.fill(HIST("hpSinPsiC"), centrality, (TMath::Sin(GetPhiInRange(psiZDCC))));*/ + const double magA = std::sqrt(modqxZDCA * modqxZDCA + modqyZDCA * modqyZDCA); + const double magC = std::sqrt(modqxZDCC * modqxZDCC + modqyZDCC * modqyZDCC); + double cosPsiAminusC = 0.0; + if (normbymag && magA > 0. && magC > 0.) { + cosPsiAminusC = (modqxZDCA * modqxZDCC + modqyZDCA * modqyZDCC) / (magA * magC); + } else { + cosPsiAminusC = (modqxZDCA * modqxZDCC + modqyZDCA * modqyZDCC); + } + // histos.fill(HIST("hpRes"), centrality, ((modqxZDCA * modqxZDCC) + (modqyZDCA * modqyZDCC))); + histos.fill(HIST("hpRes"), centrality, cosPsiAminusC); histos.fill(HIST("hcentQxZDCA"), centrality, modqxZDCA); histos.fill(HIST("hcentQyZDCA"), centrality, modqyZDCA); histos.fill(HIST("hcentQxZDCC"), centrality, modqxZDCC); histos.fill(HIST("hcentQyZDCC"), centrality, modqyZDCC); + + auto QxtQxp = modqxZDCA * modqxZDCC; + auto QytQyp = modqyZDCA * modqyZDCC; + auto Qxytp = QxtQxp + QytQyp; + auto QxpQyt = modqxZDCA * modqyZDCC; + auto QxtQyp = modqxZDCC * modqyZDCA; + + histos.fill(HIST("hpQxtQxpvscent"), centrality, QxtQxp); + histos.fill(HIST("hpQytQypvscent"), centrality, QytQyp); + histos.fill(HIST("hpQxytpvscent"), centrality, Qxytp); + histos.fill(HIST("hpQxpQytvscent"), centrality, QxpQyt); + histos.fill(HIST("hpQxtQypvscent"), centrality, QxtQyp); } else { histos.fill(HIST("hpRes"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA - psiZDCC)))); } } + double resowgt = 1.0; + if (useResoRBR) { + int binxreso = hwgtRESO->GetXaxis()->FindBin(centrality + 0.000001); + resowgt = hwgtRESO->GetBinContent(binxreso); + } else { + resowgt = 1.0; + } + //___________________________________________________________________________________________________ // loop over V0s as necessary for (const auto& v0 : V0s) { @@ -1430,13 +1540,11 @@ struct lambdapolsp { Proton = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); AntiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); Lambdadummy = Proton + AntiPion; - // angleLambda = calculateAngleBetweenLorentzVectors(Proton, AntiPion); } if (aLambdaTag) { AntiProton = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); Pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); AntiLambdadummy = AntiProton + Pion; - // angleAntiLambda = calculateAngleBetweenLorentzVectors(AntiProton, Pion); } if (shouldReject(LambdaTag, aLambdaTag, Lambdadummy, AntiLambdadummy)) { @@ -1459,129 +1567,93 @@ struct lambdapolsp { int tagb = aLambdaTag; int tagc = K0sTag; - float desbinvalue = 0.0; - if (analyzeK0s && K0sTag) { K0s = Pion + AntiPion; double acvalue = 1.0; - fillHistograms(tagc, 0, K0s, Pion, psiZDCC, psiZDCA, psiZDC, centrality, v0.mK0Short(), v0.pt(), v0.eta(), acvalue, 1.0); - } - - if (analyzeLambda && dosystematic) { - //////////////////////////////////////////////////// - float LTsys = TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda); - float CPAsys = v0.v0cosPA(); - float DCADaughsys = TMath::Abs(v0.dcaV0daughters()); - float DCApossys = TMath::Abs(v0.dcapostopv()); - float DCAnegsys = TMath::Abs(v0.dcanegtopv()); - float sysvar = -999.9; - double syst[10]; - if (sys == 1) { - double temp[10] = {26, 27, 28, 29, 30, 31, 32, 33, 34, 35}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = LTsys; - } - if (sys == 2) { - double temp[10] = {0.992, 0.993, 0.9935, 0.994, 0.9945, 0.995, 0.9955, 0.996, 0.9965, 0.997}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = CPAsys; - } - if (sys == 3) { - double temp[10] = {0.8, 0.85, 0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = DCADaughsys; - } - if (sys == 4) { - double temp[10] = {0.05, 0.07, 0.1, 0.15, 0.18, 0.2, 0.22, 0.25, 0.28, 0.3}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = DCApossys; - } - if (sys == 5) { - double temp[10] = {0.05, 0.07, 0.1, 0.15, 0.18, 0.2, 0.22, 0.25, 0.28, 0.3}; - std::copy(std::begin(temp), std::end(temp), std::begin(syst)); - sysvar = DCAnegsys; - } - - for (int i = 0; i < 10; i++) { - if (sys == 1 || sys == 3) { - if (sysvar < syst[i]) - desbinvalue = i + 0.5; - else - continue; - } - if (sys == 2 || sys == 4 || sys == 5) { - if (sysvar > syst[i]) - desbinvalue = i + 0.5; - else - continue; - } + fillHistograms(tagc, 0, K0s, Pion, psiZDCC, psiZDCA, psiZDC, centrality, v0.mK0Short(), v0.pt(), v0.eta(), acvalue, 1.0, resowgt); + } - /////////////////////////////////////////////////// - if (analyzeLambda && LambdaTag) { - Lambda = Proton + AntiPion; - tagb = 0; - double acvalue = 1.0; - fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), desbinvalue, acvalue, 1.0); - } + int binxwgt; + double wgtvalue; + int binxwgtAL; + double effwgtvalueAL; + double effwgtvalueL; - tagb = aLambdaTag; - if (analyzeLambda && aLambdaTag) { - AntiLambda = AntiProton + Pion; - taga = 0; - double acvalue = 1.0; - fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), desbinvalue, acvalue, 1.0); - } - } + if (useyldwgt) { + binxwgt = hwgtAL->GetXaxis()->FindBin(v0.pt()); + wgtvalue = hwgtAL->GetBinContent(binxwgt); } else { + wgtvalue = 1.0; + } + if (useeffwgt) { + binxwgtAL = heffAL->GetXaxis()->FindBin(v0.pt()); + effwgtvalueAL = heffAL->GetBinContent(binxwgtAL); + effwgtvalueL = heffL->GetBinContent(binxwgtAL); + } else { + effwgtvalueAL = 1.0; + effwgtvalueL = 1.0; + } - int binxwgt; - double wgtvalue; - if (useyldwgt) { - binxwgt = hwgtAL->GetXaxis()->FindBin(v0.pt()); - wgtvalue = hwgtAL->GetBinContent(binxwgt); + if (analyzeLambda && LambdaTag) { + Lambda = Proton + AntiPion; + tagb = 0; + double acvalue = 1.0; + if (useAccCorr) { + int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); + int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); + acvalue = accprofileL->GetBinContent(binx, biny); } else { - wgtvalue = 1.0; + acvalue = 1.0; } - if (analyzeLambda && LambdaTag) { - Lambda = Proton + AntiPion; - tagb = 0; - double acvalue = 1.0; - if (useAccCorr) { - int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); - int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); - acvalue = accprofileL->GetBinContent(binx, biny); - } else { - acvalue = 1.0; - } - // double acvalue = 1.0; - fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue, 1.0); + + if (distGrp.filldist && aLambdaTag == 0 && Lambda.M() > distGrp.lowmasscut && Lambda.M() < distGrp.highmasscut) { + auto phiL = TMath::ATan2(v0.py(), v0.px()); + auto LcosphiminuspsiC = TMath::Cos(GetPhiInRange(phiL - psiZDCC)); + auto LcosphiminuspsiA = TMath::Cos(GetPhiInRange(phiL - psiZDCA)); + auto Lcosphiminuspsi = TMath::Cos(GetPhiInRange(phiL - psiZDC)); + histos.fill(HIST("hLcosphiminuspsiCvseta"), LcosphiminuspsiC, v0.eta()); + histos.fill(HIST("hLcosphiminuspsiAvseta"), LcosphiminuspsiA, v0.eta()); + histos.fill(HIST("hLcosphiminuspsivseta"), Lcosphiminuspsi, v0.eta()); } - tagb = aLambdaTag; - if (analyzeLambda && aLambdaTag) { - AntiLambda = AntiProton + Pion; - taga = 0; - double acvalue = 1.0; - if (useAccCorr) { - int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); - int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); - acvalue = accprofileAL->GetBinContent(binx, biny); - } else { - acvalue = 1.0; - } - // double acvalue = 1.0; - fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, wgtvalue); + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue, (1. / effwgtvalueL), resowgt); + } + + tagb = aLambdaTag; + if (analyzeLambda && aLambdaTag) { + AntiLambda = AntiProton + Pion; + taga = 0; + double acvalue = 1.0; + if (useAccCorr) { + int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); + int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); + acvalue = accprofileAL->GetBinContent(binx, biny); + } else { + acvalue = 1.0; } + + if (distGrp.filldist && LambdaTag == 0 && AntiLambda.M() > distGrp.lowmasscut && AntiLambda.M() < distGrp.highmasscut) { + auto phiAL = TMath::ATan2(v0.py(), v0.px()); + auto ALcosphiminuspsiC = TMath::Cos(GetPhiInRange(phiAL - psiZDCC)); + auto ALcosphiminuspsiA = TMath::Cos(GetPhiInRange(phiAL - psiZDCA)); + auto ALcosphiminuspsi = TMath::Cos(GetPhiInRange(phiAL - psiZDC)); + histos.fill(HIST("hALcosphiminuspsiCvseta"), ALcosphiminuspsiC, v0.eta()); + histos.fill(HIST("hALcosphiminuspsiAvseta"), ALcosphiminuspsiA, v0.eta()); + histos.fill(HIST("hALcosphiminuspsivseta"), ALcosphiminuspsi, v0.eta()); + } + + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, wgtvalue * (1. / effwgtvalueAL), resowgt); } } // lastRunNumber = currentRunNumber; } PROCESS_SWITCH(lambdapolsp, processDerivedData, "Process derived data", false); + /* using TrackMCTrueTable = aod::McParticles; ROOT::Math::PxPyPzMVector lambdadummymc, antiLambdadummymc, protonmc, pionmc, antiProtonmc, antiPionmc; - void processMC(EventCandidatesMC::iterator const& collision, AllTrackCandidates const& /*tracks*/, TrackMCTrueTable const& GenParticles, ResoV0s const& V0s) + void processMC(EventCandidatesMC::iterator const& collision, AllTrackCandidates const& tracks, TrackMCTrueTable const& GenParticles, ResoV0s const& V0s) { if (!collision.sel8()) { return; @@ -1711,7 +1783,7 @@ struct lambdapolsp { } } PROCESS_SWITCH(lambdapolsp, processMC, "Process MC", false); - +*/ // Processing Event Mixing /* using BinningType = ColumnBinningPolicy; diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 9040c6bf16d..bb7e91da1f0 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -59,6 +59,118 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +namespace mcacc +{ +// event +template +static inline float cent(const Coll& c) +{ + return c.centmc(); +} + +template +static inline float posz(const Coll& c) +{ + return c.poszmc(); +} + +// pair / v0 candidate +template +static inline int v0Status(const T& t) +{ + return t.v0Statusmc(); +} + +template +static inline bool doubleStatus(const T& t) +{ + return t.doubleStatusmc(); +} + +template +static inline float v0CosPA(const T& t) +{ + return t.v0Cospamc(); +} + +template +static inline float v0Radius(const T& t) +{ + return t.v0Radiusmc(); +} + +template +static inline float dcaPos(const T& t) +{ + return t.dcaPositivemc(); +} + +template +static inline float dcaNeg(const T& t) +{ + return t.dcaNegativemc(); +} + +template +static inline float dcaDau(const T& t) +{ + return t.dcaBetweenDaughtermc(); +} + +template +static inline float lamPt(const T& t) +{ + return t.lambdaPtmc(); +} + +template +static inline float lamEta(const T& t) +{ + return t.lambdaEtamc(); +} + +template +static inline float lamPhi(const T& t) +{ + return t.lambdaPhimc(); +} + +template +static inline float lamMass(const T& t) +{ + return t.lambdaMassmc(); +} + +template +static inline float prPt(const T& t) +{ + return t.protonPtmc(); +} + +template +static inline float prEta(const T& t) +{ + return t.protonEtamc(); +} + +template +static inline float prPhi(const T& t) +{ + return t.protonPhimc(); +} + +template +static inline int prIdx(const T& t) +{ + return t.protonIndexmc(); +} + +template +static inline int piIdx(const T& t) +{ + return t.pionIndexmc(); +} +} // namespace mcacc struct lambdaspincorrderived { // BinningType colBinning; @@ -67,6 +179,10 @@ struct lambdaspincorrderived { 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; + struct : ConfigurableGroup { + ConfigurableAxis cfgMixRadiusBins{"cfgMixRadiusBins", {VARIABLE_WIDTH, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0}, "Radius bins for V6 radius buffer"}; + } cfgMixRadiusParam; + // Enable access to the CCDB for the offset and correction constants and save them in dedicated variables. Service ccdb; o2::ccdb::CcdbApi ccdbApi; @@ -80,27 +196,47 @@ struct lambdaspincorrderived { TH3D* hweight32; TH3D* hweight42; + // ---------- NUA single-particle weights in (phi, eta) ---------- + TH2D* hNUALambda = nullptr; + TH2D* hNUAAntiLambda = nullptr; + Configurable ConfWeightPathLL{"ConfWeightPathLL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; Configurable ConfWeightPathALAL{"ConfWeightPathALAL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; Configurable ConfWeightPathLAL{"ConfWeightPathLAL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; Configurable ConfWeightPathALL{"ConfWeightPathALL", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path"}; - Configurable ConfWeightPathLL2{"ConfWeightPathLL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; Configurable ConfWeightPathALAL2{"ConfWeightPathALAL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; Configurable ConfWeightPathLAL2{"ConfWeightPathLAL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; Configurable ConfWeightPathALL2{"ConfWeightPathALL2", "Users/s/skundu/My/Object/spincorr/cent010LL", "Weight path 2"}; - - // event sel///////// + Configurable useNUA{"useNUA", false, "Apply single-candidate NUA weight in (phi,eta)"}; + Configurable ConfNUAPathLambda{"ConfNUAPathLambda", "", "CCDB path for Lambda NUA TH2D(phi,eta)"}; + Configurable ConfNUAPathAntiLambda{"ConfNUAPathAntiLambda", "", "CCDB path for AntiLambda NUA TH2D(phi,eta)"}; + Configurable> massMixEdges{"massMixEdges", {1.09f, 1.108f, 1.122f, 1.14f}, "Mass-mixing region edges: [SB low | signal | SB high]"}; + Configurable cfgMixLegMode{"cfgMixLegMode", 0, "0=replace leg-1 only, 1=replace leg-2 only, 2=do both one-leg replacements"}; + Configurable cfgV5MassBins{"cfgV5MassBins", 5, "Number of fixed mass bins for V5 mixing"}; + Configurable cfgV5NeighborPt{"cfgV5NeighborPt", 0, "v5: neighbor bins in pT (use symmetric ±N, edge-safe)"}; + Configurable cfgV5NeighborEta{"cfgV5NeighborEta", 0, "v5: neighbor bins in eta (use symmetric ±N, edge-safe)"}; + Configurable cfgV5NeighborPhi{"cfgV5NeighborPhi", 0, "v5: neighbor bins in phi (use symmetric ±N, periodic wrap)"}; + Configurable usePairKineMatch{"usePairKineMatch", true, "Require pair-level matching between (A,B) and (C,B)"}; + Configurable cfgV5MaxMatches{"cfgV5MaxMatches", 50, "v5: max ME replacements per SE pair (after all cuts)"}; + Configurable cfgMixSeed{"cfgMixSeed", 0xdecafbadULL, "RNG seed for downsampling matches (deterministic)"}; Configurable centMin{"centMin", 0, "Minimum Centrality"}; Configurable centMax{"centMax", 80, "Maximum Centrality"}; Configurable rngSeed{"rngSeed", 12345, "Seed for random mixing (reproducible)"}; std::mt19937 rng{12345}; + Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0, 110}, "Mixing bins - centrality"}; + Configurable etaMix{"etaMix", 0.1, "Eta cut on event mixing"}; + Configurable ptMix{"ptMix", 0.1, "Pt cut on event mixing"}; + Configurable phiMix{"phiMix", 0.1, "Phi cut on event mixing"}; + Configurable massMix{"massMix", 0.0028, "Masscut on event mixing"}; + Configurable userapidity{"userapidity", 1, "Use Rapidity for mixing"}; + // Lambda selection //////////// Configurable harmonic{"harmonic", 1, "Harmonic phi"}; Configurable harmonicDphi{"harmonicDphi", 2, "Harmonic delta phi"}; Configurable useweight{"useweight", 0, "Use weight"}; - Configurable usebothweight{"usebothweight", 1, "Use both weight"}; - // Configurable useNUA{"useNUA", 0, "Use NUA weight"}; Configurable usePDGM{"usePDGM", 1, "Use PDG mass"}; Configurable useAdditionalHisto{"useAdditionalHisto", 0, "Use additional histogram"}; Configurable checkDoubleStatus{"checkDoubleStatus", 0, "Check Double status"}; @@ -115,62 +251,72 @@ struct lambdaspincorrderived { Configurable MassMin{"MassMin", 1.09, "V0 Mass minimum"}; Configurable MassMax{"MassMax", 1.14, "V0 Mass maximum"}; Configurable rapidity{"rapidity", 0.5, "Rapidity cut on lambda"}; + Configurable v0etaMixBuffer{"v0etaMixBuffer", 0.8, "Eta cut on mix event buffer"}; Configurable v0eta{"v0eta", 0.8, "Eta cut on lambda"}; // Event Mixing Configurable cosDef{"cosDef", 1, "Defination of cos"}; - Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {8, 0.0, 80}, "Mixing bins - centrality"}; - Configurable etaMix{"etaMix", 0.1, "Eta cut on event mixing"}; - Configurable ptMix{"ptMix", 0.1, "Pt cut on event mixing"}; - Configurable phiMix{"phiMix", 0.1, "Phi cut on event mixing"}; - Configurable massMix{"massMix", 0.0028, "Masscut on event mixing"}; - ConfigurableAxis ax_dphi_h{"ax_dphi_h", {72, 0.0, 2.0 * TMath::Pi()}, "Δφ_h"}; - ConfigurableAxis ax_deta{"ax_deta", {40, -1.0, 1.0}, "Δη"}; - ConfigurableAxis ax_ptpair{"ax_ptpair", {100, 0.0, 10.0}, "p_{T,pair} (GeV/c)"}; + ConfigurableAxis ax_dphi_h{"ax_dphi_h", {VARIABLE_WIDTH, 0.0, 2.0 * TMath::Pi()}, "Δφ_h"}; + ConfigurableAxis ax_deta{"ax_deta", {VARIABLE_WIDTH, -1.0, 1.0}, "Δη"}; + ConfigurableAxis ax_ptpair{"ax_ptpair", {VARIABLE_WIDTH, 0.0, 10.0}, "p_{T,pair} (GeV/c)"}; // THnsparse bining ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {50, 1.09, 1.14}, "#it{M} (GeV/#it{c}^{2})"}; - ConfigurableAxis configThnAxisR{"configThnAxisR", {80, 0.0, 8.0}, "#it{R}"}; - ConfigurableAxis configThnAxisPol{"configThnAxisPol", {80, 0.0, 8.0}, "cos#it{#theta *}"}; - ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0.0, 80.0}, "Centrality"}; - ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {5, 0.0, 1.0}, "Rapidity"}; - ConfigurableAxis configThnAxisPairMass{"configThnAxisPairMass", {100, 2.0, 3.0}, "PairMass"}; - ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {18, 0.0, 2.0 * TMath::Pi()}, "Phi"}; + ConfigurableAxis configThnAxisR{"configThnAxisR", {VARIABLE_WIDTH, 0.0, 8.0}, "#it{R}"}; + ConfigurableAxis configThnAxisPol{"configThnAxisPol", {VARIABLE_WIDTH, 0.0, 8.0}, "cos#it{#theta *}"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {VARIABLE_WIDTH, 0.0, 80.0}, "Centrality"}; + ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {VARIABLE_WIDTH, 0.0, 1.0}, "Rapidity"}; + ConfigurableAxis configThnAxisPairMass{"configThnAxisPairMass", {VARIABLE_WIDTH, 2.0, 3.0}, "PairMass"}; + ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {VARIABLE_WIDTH, 0.0, 2.0 * TMath::Pi()}, "Phi"}; + + ConfigurableAxis configThnAxisDeltaPhi{"configThnAxisDeltaPhi", {VARIABLE_WIDTH, 0.0, TMath::Pi() / 6, 2.0 * TMath::Pi() / 6, 3.0 * TMath::Pi() / 6, 4.0 * TMath::Pi() / 6, 5.0 * TMath::Pi() / 6, TMath::Pi()}, "Delta Phi"}; + ConfigurableAxis configThnAxisDeltaR{"configThnAxisDeltaR", {VARIABLE_WIDTH, 0.0, 0.5, 1.2, 2.0, 3.1, 4.0}, "Delta R"}; + ConfigurableAxis configThnAxisDeltaRap{"configThnAxisDeltaRap", {VARIABLE_WIDTH, 0.0, 0.2, 0.5, 1.0, 1.6}, "Delta Rap"}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { + histos.add("hPtRadiusV0", "V0 QA;#it{p}_{T}^{V0} (GeV/#it{c});V0 decay radius (cm)", kTH2F, {{100, 0.0, 10.0}, {120, 0.0, 45.0}}); histos.add("hPtYSame", "hPtYSame", kTH2F, {{100, 0.0, 10.0}, {200, -1.0, 1.0}}); histos.add("hPtYMix", "hPtYMix", kTH2F, {{100, 0.0, 10.0}, {200, -1.0, 1.0}}); + histos.add("hPhiEtaSame", "hPhiEtaSame", kTH2F, {{720, 0.0, 2.0 * TMath::Pi()}, {200, -1.0, 1.0}}); + histos.add("hPhiEtaMix", "hPhiEtaMix", kTH2F, {{720, 0.0, 2.0 * TMath::Pi()}, {200, -1.0, 1.0}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{configThnAxisCentrality}}); - histos.add("deltaPhiSame", "deltaPhiSame", HistType::kTH1D, {{72, 0.0, 2.0 * TMath::Pi()}}, true); - histos.add("deltaPhiMix", "deltaPhiMix", HistType::kTH1D, {{72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("deltaPhiSame", "deltaPhiSame", HistType::kTH1D, {{72, -TMath::Pi(), TMath::Pi()}}, true); + histos.add("deltaPhiMix", "deltaPhiMix", HistType::kTH1D, {{72, -TMath::Pi(), TMath::Pi()}}, true); histos.add("ptCent", "ptCent", HistType::kTH2D, {{100, 0.0, 10.0}, {8, 0.0, 80.0}}, true); histos.add("etaCent", "etaCent", HistType::kTH2D, {{32, -0.8, 0.8}, {8, 0.0, 80.0}}, true); - // --- 3D SE/ME pair-space maps per category (LL, LAL, ALL, ALAL) - histos.add("SE_LL", "SE pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("SE_LAL", "SE pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("SE_ALL", "SE pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("SE_ALAL", "SE pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("hEtaPhiLambdaRaw", "Lambda raw;#phi;#eta", kTH2D, + {{360, 0.0, 2.0 * TMath::Pi()}, {32, -0.8, 0.8}}); + histos.add("hEtaPhiAntiLambdaRaw", "AntiLambda raw;#phi;#eta", kTH2D, + {{360, 0.0, 2.0 * TMath::Pi()}, {32, -0.8, 0.8}}); - histos.add("ME_LL", "ME pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_LAL", "ME pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_ALL", "ME pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_ALAL", "ME pairs", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("hNUAWeightLambda", "Lambda NUA weight", kTH1D, {{200, 0.0, 5.0}}); + histos.add("hNUAWeightAntiLambda", "AntiLambda NUA weight", kTH1D, {{200, 0.0, 5.0}}); - histos.add("SE_LL2", "SE pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("SE_LAL2", "SE pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("SE_ALL2", "SE pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("SE_ALAL2", "SE pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + // --- target/replacement single-leg occupancy maps for replacement correction + histos.add("TGT_LL_leg1", "Target LL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("TGT_LAL_leg1", "Target LAL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("TGT_ALL_leg1", "Target ALL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("TGT_ALAL_leg1", "Target ALAL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_LL2", "ME pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_LAL2", "ME pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_ALL2", "ME pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); - histos.add("ME_ALAL2", "ME pairs 2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_LL_leg1", "Repl LL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_LAL_leg1", "Repl LAL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_ALL_leg1", "Repl ALL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_ALAL_leg1", "Repl ALAL leg1", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + + histos.add("TGT_LL_leg2", "Target LL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("TGT_LAL_leg2", "Target LAL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("TGT_ALL_leg2", "Target ALL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("TGT_ALAL_leg2", "Target ALAL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + + histos.add("REP_LL_leg2", "Repl LL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_LAL_leg2", "Repl LAL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_ALL_leg2", "Repl ALL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); + histos.add("REP_ALAL_leg2", "Repl ALAL leg2", HistType::kTH3D, {ax_dphi_h, ax_deta, ax_ptpair}, true); histos.add("hSparseLambdaLambda", "hSparseLambdaLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); histos.add("hSparseLambdaAntiLambda", "hSparseLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); @@ -181,6 +327,17 @@ struct lambdaspincorrderived { histos.add("hSparseLambdaAntiLambdaMixed", "hSparseLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); histos.add("hSparseAntiLambdaLambdaMixed", "hSparseAntiLambdaLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); histos.add("hSparseAntiLambdaAntiLambdaMixed", "hSparseAntiLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisR}, true); + + histos.add("hSparseLambdaLambdaAnalysis", "hSparseLambdaLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseLambdaAntiLambdaAnalysis", "hSparseLambdaAntiLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaLambdaAnalysis", "hSparseAntiLambdLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaAntiLambdaAnalysis", "hSparseAntiLambdaAntiLambdaAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + + histos.add("hSparseLambdaLambdaMixedAnalysis", "hSparseLambdaLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseLambdaAntiLambdaMixedAnalysis", "hSparseLambdaAntiLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaLambdaMixedAnalysis", "hSparseAntiLambdaLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + histos.add("hSparseAntiLambdaAntiLambdaMixedAnalysis", "hSparseAntiLambdaAntiLambdaMixedAnalysis", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisDeltaR, configThnAxisDeltaRap, configThnAxisDeltaPhi}, true); + if (useAdditionalHisto) { histos.add("hSparseRapLambdaLambda", "hSparseRapLambdaLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisRapidity}, true); histos.add("hSparseRapLambdaAntiLambda", "hSparseRapLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisRapidity}, true); @@ -230,6 +387,17 @@ struct lambdaspincorrderived { hweight32 = ccdb->getForTimeStamp(ConfWeightPathALL2.value, cfgCcdbParam.nolaterthan.value); hweight42 = ccdb->getForTimeStamp(ConfWeightPathALAL2.value, cfgCcdbParam.nolaterthan.value); } + if (useNUA) { + hNUALambda = ccdb->getForTimeStamp(ConfNUAPathLambda.value, cfgCcdbParam.nolaterthan.value); + hNUAAntiLambda = ccdb->getForTimeStamp(ConfNUAPathAntiLambda.value, cfgCcdbParam.nolaterthan.value); + + if (!hNUALambda) { + LOGF(fatal, "NUA enabled but Lambda NUA histogram not found at path: %s", ConfNUAPathLambda.value.data()); + } + if (!hNUAAntiLambda) { + LOGF(fatal, "NUA enabled but AntiLambda NUA histogram not found at path: %s", ConfNUAPathAntiLambda.value.data()); + } + } } template @@ -273,32 +441,65 @@ struct lambdaspincorrderived { } template - bool checkKinematics(T1 const& candidate1, T2 const& candidate2) + bool checkKinematics(T1 const& c1, T2 const& c2) { - if (candidate1.v0Status() != candidate2.v0Status()) { + if (c1.v0Status() != c2.v0Status()) { return false; } - if (std::abs(candidate1.lambdaPt() - candidate2.lambdaPt()) > ptMix) { + + if (std::abs(c1.lambdaPt() - c2.lambdaPt()) > ptMix) { return false; } - if (std::abs(candidate1.lambdaEta() - candidate2.lambdaEta()) > etaMix) { - return false; + + if (!userapidity) { + if (std::abs(c1.lambdaEta() - c2.lambdaEta()) > etaMix) { + return false; + } + } else { + const auto l1 = ROOT::Math::PtEtaPhiMVector(c1.lambdaPt(), c1.lambdaEta(), c1.lambdaPhi(), c1.lambdaMass()); + const auto l2 = ROOT::Math::PtEtaPhiMVector(c2.lambdaPt(), c2.lambdaEta(), c2.lambdaPhi(), c2.lambdaMass()); + if (std::abs(l1.Rapidity() - l2.Rapidity()) > etaMix) { // etaMix used as Δy + return false; + } } - if (std::abs(RecoDecay::constrainAngle(candidate1.lambdaPhi(), 0.0F, harmonic) - RecoDecay::constrainAngle(candidate2.lambdaPhi(), 0.0F, harmonic)) > phiMix) { + + const float dphi = deltaPhiMinusPiToPi((float)c1.lambdaPhi(), (float)c2.lambdaPhi()); + if (std::abs(dphi) > phiMix) { return false; } - if (std::abs(candidate1.lambdaMass() - candidate2.lambdaMass()) > massMix) { + + if (std::abs(c1.lambdaMass() - c2.lambdaMass()) > massMix) { return false; } + return true; } + double getNUAWeight(int v0Status, double phi, double eta) + { + if (!useNUA) { + return 1.0; + } + + TH2D* h = (v0Status == 0) ? hNUALambda : hNUAAntiLambda; + if (!h) { + return 1.0; + } + + const double phiWrap = RecoDecay::constrainAngle(phi, 0.0F, harmonic); // [0,2pi) + const int bin = h->FindBin(phiWrap, eta); // assumes axes are (phi, eta) + const double w = h->GetBinContent(bin); + + if (!std::isfinite(w) || w <= 0.0) { + return 1.0; + } + return w; + } void fillHistograms(int tag1, int tag2, const ROOT::Math::PtEtaPhiMVector& particle1, const ROOT::Math::PtEtaPhiMVector& particle2, const ROOT::Math::PtEtaPhiMVector& daughpart1, const ROOT::Math::PtEtaPhiMVector& daughpart2, - int datatype, float mixpairweight) + int datatype, float mixpairweight, int replacedLeg = 1) { - auto lambda1Mass = 0.0; auto lambda2Mass = 0.0; if (!usePDGM) { @@ -308,47 +509,43 @@ struct lambdaspincorrderived { lambda1Mass = o2::constants::physics::MassLambda; lambda2Mass = o2::constants::physics::MassLambda; } + auto particle1Dummy = ROOT::Math::PtEtaPhiMVector(particle1.Pt(), particle1.Eta(), particle1.Phi(), lambda1Mass); auto particle2Dummy = ROOT::Math::PtEtaPhiMVector(particle2.Pt(), particle2.Eta(), particle2.Phi(), lambda2Mass); auto pairDummy = particle1Dummy + particle2Dummy; - ROOT::Math::Boost boostPairToCM{pairDummy.BoostToCM()}; // boosting vector for pair CM + ROOT::Math::Boost boostPairToCM{pairDummy.BoostToCM()}; - // Step1: Boosting both Lambdas to Lambda-Lambda pair rest frame + // Step1: Boost both Lambdas to pair rest frame auto lambda1CM = boostPairToCM(particle1Dummy); auto lambda2CM = boostPairToCM(particle2Dummy); - // Step 2: Boost Each Lambda to its Own Rest Frame + // Step2: Boost each Lambda to its own rest frame ROOT::Math::Boost boostLambda1ToCM{lambda1CM.BoostToCM()}; ROOT::Math::Boost boostLambda2ToCM{lambda2CM.BoostToCM()}; - // Also boost the daughter protons to the same frame - auto proton1pairCM = boostPairToCM(daughpart1); // proton1 to pair CM - auto proton2pairCM = boostPairToCM(daughpart2); // proton2 to pair CM + // Also boost daughter protons to pair CM + auto proton1pairCM = boostPairToCM(daughpart1); + auto proton2pairCM = boostPairToCM(daughpart2); - // Boost protons into their respective Lambda rest frames + // Then into each Lambda rest frame auto proton1LambdaRF = boostLambda1ToCM(proton1pairCM); auto proton2LambdaRF = boostLambda2ToCM(proton2pairCM); - // --- STAR-style Δθ (as written: dot product of proton directions in their own Λ RFs) --- - - // Boost each proton into its parent's rest frame - ROOT::Math::Boost boostL1_LabToRF{particle1Dummy.BoostToCM()}; // Λ1 velocity in lab - ROOT::Math::Boost boostL2_LabToRF{particle2Dummy.BoostToCM()}; // Λ2 velocity in lab + // STAR-style alternative + ROOT::Math::Boost boostL1_LabToRF{particle1Dummy.BoostToCM()}; + ROOT::Math::Boost boostL2_LabToRF{particle2Dummy.BoostToCM()}; auto p1_LRF = boostL1_LabToRF(daughpart1); auto p2_LRF = boostL2_LabToRF(daughpart2); - // Unit 3-vectors (in different rest frames!) TVector3 u1 = TVector3(p1_LRF.Px(), p1_LRF.Py(), p1_LRF.Pz()).Unit(); TVector3 u2 = TVector3(p2_LRF.Px(), p2_LRF.Py(), p2_LRF.Pz()).Unit(); - // Proton unit directions in Λ rest frames TVector3 k1(proton1LambdaRF.Px(), proton1LambdaRF.Py(), proton1LambdaRF.Pz()); k1 = k1.Unit(); TVector3 k2(proton2LambdaRF.Px(), proton2LambdaRF.Py(), proton2LambdaRF.Pz()); k2 = k2.Unit(); - // STAR-style cosΔθ definition double cosDeltaTheta_STAR_naive = u1.Dot(u2); if (cosDeltaTheta_STAR_naive > 1.0) cosDeltaTheta_STAR_naive = 111.0; @@ -361,12 +558,7 @@ struct lambdaspincorrderived { if (cosDeltaTheta_hel < -1.0) cosDeltaTheta_hel = -111.0; - auto cosThetaDiff = -999.0; - if (cosDef == 0) { - cosThetaDiff = cosDeltaTheta_STAR_naive; - } else { - cosThetaDiff = cosDeltaTheta_hel; - } + double cosThetaDiff = (cosDef == 0) ? cosDeltaTheta_STAR_naive : cosDeltaTheta_hel; double pt1 = particle1.Pt(); double dphi1 = RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic); @@ -376,11 +568,13 @@ struct lambdaspincorrderived { double dphi2 = RecoDecay::constrainAngle(particle2.Phi(), 0.0F, harmonic); double deta2 = particle2.Eta(); - double deta_pair = std::abs(deta1 - deta2); - double dphi_pair = RecoDecay::constrainAngle(particle1.Phi() - particle2.Phi(), 0.0F, harmonicDphi); + double nuaWeight1 = getNUAWeight(tag1, particle1.Phi(), particle1.Eta()); + double nuaWeight2 = getNUAWeight(tag2, particle2.Phi(), particle2.Eta()); + const double pairNUAWeight = nuaWeight1 * nuaWeight2; - double deltaR = TMath::Sqrt(deta_pair * deta_pair + dphi_pair * dphi_pair); + double dphi_pair = RecoDecay::constrainAngle(dphi1 - dphi2, -TMath::Pi(), harmonicDphi); double deltaRap = std::abs(particle1.Rapidity() - particle2.Rapidity()); + double deltaR = TMath::Sqrt(deltaRap * deltaRap + dphi_pair * dphi_pair); double epsWeight1 = 1.0; double epsWeight2 = 1.0; @@ -402,89 +596,90 @@ struct lambdaspincorrderived { } if (datatype == 0) { - mixpairweight = 1.0; - histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), mixpairweight); + const double weight = pairNUAWeight; if (tag1 == 0 && tag2 == 0) { - histos.fill(HIST("SE_LL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_LL2"), dphi2, deta2, pt2, mixpairweight); - histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); + histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), nuaWeight1); + histos.fill(HIST("hPhiEtaSame"), dphi1, particle1.Eta(), nuaWeight1); + histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 0 && tag2 == 1) { - histos.fill(HIST("SE_LAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_LAL2"), dphi2, deta2, pt2, mixpairweight); - histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); + histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 0) { - histos.fill(HIST("hSparseAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); - histos.fill(HIST("SE_ALL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_ALL2"), dphi2, deta2, pt2, mixpairweight); + histos.fill(HIST("hSparseAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassAntiLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 1) { - histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, mixpairweight); - histos.fill(HIST("SE_ALAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("SE_ALAL2"), dphi2, deta2, pt2, mixpairweight); + histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaAntiLambdaAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { - histos.fill(HIST("hSparseRapAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, mixpairweight); - histos.fill(HIST("hSparsePhiAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, mixpairweight); - histos.fill(HIST("hSparsePairMassAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), mixpairweight); + histos.fill(HIST("hSparseRapAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); + histos.fill(HIST("hSparsePhiAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); + histos.fill(HIST("hSparsePairMassAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } + } else if (datatype == 1) { double weight = mixpairweight; + if (useweight) { - if (usebothweight) { - weight = mixpairweight / (epsWeight1 * epsWeight2); - } else { - weight = mixpairweight / (epsWeight1); + const double epsWeightReplaced = (replacedLeg == 2) ? epsWeight2 : epsWeight1; + if (!std::isfinite(epsWeightReplaced) || epsWeightReplaced <= 0.0) { + return; } + weight = mixpairweight / epsWeightReplaced; } - if (weight <= 0.0) { - weight = 1.0; + weight *= pairNUAWeight; + if (!std::isfinite(weight) || weight <= 0.0) { + return; } - histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), weight); + if (tag1 == 0 && tag2 == 0) { - histos.fill(HIST("ME_LL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_LL2"), dphi2, deta2, pt2, mixpairweight); + if (replacedLeg == 1) { + histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity(), nuaWeight1 * mixpairweight); + histos.fill(HIST("hPhiEtaMix"), dphi1, particle1.Eta(), nuaWeight1 * mixpairweight); + } histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); histos.fill(HIST("hSparsePairMassLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } + } else if (tag1 == 0 && tag2 == 1) { - histos.fill(HIST("ME_LAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_LAL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); histos.fill(HIST("hSparsePairMassLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 0) { - histos.fill(HIST("ME_ALL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_ALL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); histos.fill(HIST("hSparsePairMassAntiLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, pairDummy.M(), weight); } } else if (tag1 == 1 && tag2 == 1) { - histos.fill(HIST("ME_ALAL"), dphi1, deta1, pt1, mixpairweight); - histos.fill(HIST("ME_ALAL2"), dphi2, deta2, pt2, mixpairweight); histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, weight); + histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixedAnalysis"), particle1.M(), particle2.M(), cosThetaDiff, deltaR, deltaRap, std::abs(dphi_pair), weight); if (useAdditionalHisto) { histos.fill(HIST("hSparseRapAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, deltaRap, weight); histos.fill(HIST("hSparsePhiAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, dphi_pair, weight); @@ -493,6 +688,36 @@ struct lambdaspincorrderived { } } } + static inline int pairTypeCode(int tag1, int tag2) + { + if (tag1 == 0 && tag2 == 0) { + return 0; // LL + } else if (tag1 == 0 && tag2 == 1) { + return 1; // LAL + } else if (tag1 == 1 && tag2 == 0) { + return 2; // ALL + } else { + return 3; // ALAL + } + } + + template + static inline bool hasSharedDaughters(const A& a, const B& b) + { + return (a.protonIndex() == b.protonIndex()) || + (a.pionIndex() == b.pionIndex()) || + (a.protonIndex() == b.pionIndex()) || + (a.pionIndex() == b.protonIndex()); + } + + template + static inline bool hasSharedDaughtersMC(const A& a, const B& b) + { + return (a.protonIndexmc() == b.protonIndexmc()) || + (a.pionIndexmc() == b.pionIndexmc()) || + (a.protonIndexmc() == b.pionIndexmc()) || + (a.pionIndexmc() == b.protonIndexmc()); + } ROOT::Math::PtEtaPhiMVector lambda0, proton0; ROOT::Math::PtEtaPhiMVector lambda, proton; @@ -510,11 +735,19 @@ struct lambdaspincorrderived { if (!selectionV0(v0)) { continue; } + histos.fill(HIST("hPtRadiusV0"), v0.lambdaPt(), v0.v0Radius()); histos.fill(HIST("ptCent"), v0.lambdaPt(), centrality); histos.fill(HIST("etaCent"), v0.lambdaEta(), centrality); proton = ROOT::Math::PtEtaPhiMVector(v0.protonPt(), v0.protonEta(), v0.protonPhi(), o2::constants::physics::MassProton); lambda = ROOT::Math::PtEtaPhiMVector(v0.lambdaPt(), v0.lambdaEta(), v0.lambdaPhi(), v0.lambdaMass()); + const double phi = RecoDecay::constrainAngle(v0.lambdaPhi(), 0.0F, harmonic); + const double eta = v0.lambdaEta(); + if (v0.v0Status() == 0) { + histos.fill(HIST("hEtaPhiLambdaRaw"), phi, eta, getNUAWeight(0, v0.lambdaPhi(), v0.lambdaEta())); + } else { + histos.fill(HIST("hEtaPhiAntiLambdaRaw"), phi, eta, getNUAWeight(1, v0.lambdaPhi(), v0.lambdaEta())); + } for (const auto& v02 : V0s) { if (v02.index() <= v0.index()) { continue; @@ -522,21 +755,12 @@ struct lambdaspincorrderived { if (!selectionV0(v02)) { continue; } - if (v0.protonIndex() == v02.protonIndex()) { + if (hasSharedDaughters(v0, v02)) continue; - } - if (v0.pionIndex() == v02.pionIndex()) { - continue; - } - if (v0.protonIndex() == v02.pionIndex()) { - continue; - } - if (v0.pionIndex() == v02.protonIndex()) { - continue; - } proton2 = ROOT::Math::PtEtaPhiMVector(v02.protonPt(), v02.protonEta(), v02.protonPhi(), o2::constants::physics::MassProton); lambda2 = ROOT::Math::PtEtaPhiMVector(v02.lambdaPt(), v02.lambdaEta(), v02.lambdaPhi(), v02.lambdaMass()); - histos.fill(HIST("deltaPhiSame"), RecoDecay::constrainAngle(v0.lambdaPhi() - v02.lambdaPhi(), 0.0F, harmonicDphi)); + histos.fill(HIST("deltaPhiSame"), RecoDecay::constrainAngle(v0.lambdaPhi() - v02.lambdaPhi(), -TMath::Pi(), harmonicDphi)); + // const int ptype = pairTypeCode(v0.v0Status(), v02.v0Status()); if (v0.v0Status() == 0 && v02.v0Status() == 0) { fillHistograms(0, 0, lambda, lambda2, proton, proton2, 0, 1.0); } @@ -554,165 +778,71 @@ struct lambdaspincorrderived { } PROCESS_SWITCH(lambdaspincorrderived, processData, "Process data", true); - // Processing Event Mixing - SliceCache cache; - using BinningType = ColumnBinningPolicy; - BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; - Preslice tracksPerCollisionV0 = aod::lambdapair::lambdaeventId; - void processME(EventCandidates const& collisions, AllTrackCandidates const& V0s) - { - auto collOldIndex = -999; - std::vector t1Used; - for (auto& [collision1, collision2] : selfCombinations(colBinning, nEvtMixing, -1, collisions, collisions)) { - // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.index(), collision2.index()); - // auto centrality = collision1.cent(); - auto groupV01 = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - auto groupV02 = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - auto groupV03 = V0s.sliceBy(tracksPerCollisionV0, collision2.index()); - auto collNewIndex = collision1.index(); - // LOGF(info, "Mixed event collisions: (%d, %d)", collNewIndex, collOldIndex); - if (collOldIndex != collNewIndex) { - t1Used.resize(groupV01.size(), false); - // std::fill(t1Used.begin(), t1Used.end(), false); - // std::vector t1Used(groupV01.size(), false); // <-- reset here - collOldIndex = collNewIndex; - } - for (auto& [t1, t3] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV03))) { - if (t1Used[t1.index()]) { - continue; - } - if (!checkKinematics(t1, t3)) { - continue; - } - if (!selectionV0(t1)) { - continue; - } - if (!selectionV0(t3)) { - continue; - } - t1Used[t1.index()] = true; - for (const auto& t2 : groupV02) { - if (t2.index() <= t1.index()) { - continue; - } - if (!selectionV0(t2)) { - continue; - } - if (t1.protonIndex() == t2.protonIndex()) { - continue; - } - if (t1.pionIndex() == t2.pionIndex()) { - continue; - } - proton = ROOT::Math::PtEtaPhiMVector(t3.protonPt(), t3.protonEta(), t3.protonPhi(), o2::constants::physics::MassProton); - lambda = ROOT::Math::PtEtaPhiMVector(t3.lambdaPt(), t3.lambdaEta(), t3.lambdaPhi(), t3.lambdaMass()); - proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); - histos.fill(HIST("deltaPhiMix"), RecoDecay::constrainAngle(t3.lambdaPhi() - t2.lambdaPhi(), 0.0F, harmonicDphi)); - if (t3.v0Status() == 0 && t2.v0Status() == 0) { - fillHistograms(0, 0, lambda, lambda2, proton, proton2, 1, 1.0); - } - if (t3.v0Status() == 0 && t2.v0Status() == 1) { - fillHistograms(0, 1, lambda, lambda2, proton, proton2, 1, 1.0); - } - if (t3.v0Status() == 1 && t2.v0Status() == 0) { - fillHistograms(1, 0, lambda, lambda2, proton, proton2, 1, 1.0); - } - if (t3.v0Status() == 1 && t2.v0Status() == 1) { - fillHistograms(1, 1, lambda, lambda2, proton, proton2, 1, 1.0); - } - } - } // replacement track pair - } // collision pair - } - PROCESS_SWITCH(lambdaspincorrderived, processME, "Process data ME", false); - - void processMEV2(EventCandidates const& collisions, AllTrackCandidates const& V0s) + template + void fillReplacementControlMap(int tag1, int tag2, int leg, bool isTarget, LV const& particle, float weight) { - auto nBins = colBinning.getAllBinsCount(); - std::vector>> eventPools(nBins); - - for (auto& collision1 : collisions) { - int bin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent())); - auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - // float centrality = collision1.cent(); - - // <<< CHANGED: map old collision index → set of (t2.idx, t3.idx) we've already filled - std::unordered_map>> seenMap; - - for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - if (!selectionV0(t1) || !selectionV0(t2)) - continue; - if (t2.index() <= t1.index()) - continue; - if (t1.protonIndex() == t2.protonIndex()) - continue; - if (t1.pionIndex() == t2.pionIndex()) - continue; - - int mixes = 0; - for (auto it = eventPools[bin].rbegin(); it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { - int collision2idx = it->first; - AllTrackCandidates& poolB = it->second; - - int nRepl = 0; - for (auto& t3 : poolB) { - if (selectionV0(t3) && checkKinematics(t1, t3)) { - ++nRepl; - } - } - if (nRepl == 0) - continue; - float invN = 1.0f / static_cast(nRepl); + const double pt = particle.Pt(); + const double phi = RecoDecay::constrainAngle(particle.Phi(), 0.0F, harmonic); - for (auto& t3 : poolB) { - if (!(selectionV0(t3) && checkKinematics(t1, t3))) { - continue; - } - if (collision1.index() == collision2idx) { - continue; - } - - // <<< CHANGED: dedupe (t2, t3) pairs per prior collision - auto key = std::make_pair(t2.index(), t3.index()); - auto& seen = seenMap[collision2idx]; - if (!seen.insert(key).second) { - continue; - } + double etaOrY = particle.Eta(); + if (userapidity) { + etaOrY = particle.Rapidity(); + } - // reconstruct 4-vectors - proton = ROOT::Math::PtEtaPhiMVector(t3.protonPt(), t3.protonEta(), t3.protonPhi(), o2::constants::physics::MassProton); - lambda = ROOT::Math::PtEtaPhiMVector(t3.lambdaPt(), t3.lambdaEta(), t3.lambdaPhi(), t3.lambdaMass()); - proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + if (leg == 1 && isTarget) { + if (tag1 == 0 && tag2 == 0) + histos.fill(HIST("TGT_LL_leg1"), phi, etaOrY, pt, weight); + else if (tag1 == 0 && tag2 == 1) + histos.fill(HIST("TGT_LAL_leg1"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 0) + histos.fill(HIST("TGT_ALL_leg1"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 1) + histos.fill(HIST("TGT_ALAL_leg1"), phi, etaOrY, pt, weight); + return; + } - float dPhi = std::fabs(RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic)); - histos.fill(HIST("deltaPhiMix"), dPhi, invN); + if (leg == 1 && !isTarget) { + if (tag1 == 0 && tag2 == 0) + histos.fill(HIST("REP_LL_leg1"), phi, etaOrY, pt, weight); + else if (tag1 == 0 && tag2 == 1) + histos.fill(HIST("REP_LAL_leg1"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 0) + histos.fill(HIST("REP_ALL_leg1"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 1) + histos.fill(HIST("REP_ALAL_leg1"), phi, etaOrY, pt, weight); + return; + } - if (t3.v0Status() == 0 && t2.v0Status() == 0) { - fillHistograms(0, 0, lambda, lambda2, proton, proton2, 1, invN); - } - if (t3.v0Status() == 0 && t2.v0Status() == 1) { - fillHistograms(0, 1, lambda, lambda2, proton, proton2, 1, invN); - } - if (t3.v0Status() == 1 && t2.v0Status() == 0) { - fillHistograms(1, 0, lambda, lambda2, proton, proton2, 1, invN); - } - if (t3.v0Status() == 1 && t2.v0Status() == 1) { - fillHistograms(1, 1, lambda, lambda2, proton, proton2, 1, invN); - } - } - } // end mixing-event loop - } // end same-event pair loop + if (leg == 2 && isTarget) { + if (tag1 == 0 && tag2 == 0) + histos.fill(HIST("TGT_LL_leg2"), phi, etaOrY, pt, weight); + else if (tag1 == 0 && tag2 == 1) + histos.fill(HIST("TGT_LAL_leg2"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 0) + histos.fill(HIST("TGT_ALL_leg2"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 1) + histos.fill(HIST("TGT_ALAL_leg2"), phi, etaOrY, pt, weight); + return; + } - auto sliced = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if (static_cast(eventPools[bin].size()) > nEvtMixing) { - eventPools[bin].pop_front(); - } - } // end primary-event loop + if (leg == 2 && !isTarget) { + if (tag1 == 0 && tag2 == 0) + histos.fill(HIST("REP_LL_leg2"), phi, etaOrY, pt, weight); + else if (tag1 == 0 && tag2 == 1) + histos.fill(HIST("REP_LAL_leg2"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 0) + histos.fill(HIST("REP_ALL_leg2"), phi, etaOrY, pt, weight); + else if (tag1 == 1 && tag2 == 1) + histos.fill(HIST("REP_ALAL_leg2"), phi, etaOrY, pt, weight); + return; + } } - PROCESS_SWITCH(lambdaspincorrderived, processMEV2, "Process data ME", false); + + // Processing Event Mixing + SliceCache cache; + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; + Preslice tracksPerCollisionV0 = aod::lambdapair::lambdaeventId; void processMEV3(EventCandidates const& collisions, AllTrackCandidates const& V0s) { @@ -721,121 +851,254 @@ struct lambdaspincorrderived { for (auto& collision1 : collisions) { const int bin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent())); + if (bin < 0) { + continue; + } + + auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); // if pool empty, push and continue if (eventPools[bin].empty()) { - auto sliced = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if ((int)eventPools[bin].size() > nEvtMixing) + eventPools[bin].emplace_back(collision1.index(), std::move(poolA)); + if ((int)eventPools[bin].size() > nEvtMixing) { eventPools[bin].pop_front(); + } continue; } - // current event slice - auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); - - // loop over SE unordered pairs (t1,t2) for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { - if (!selectionV0(t1) || !selectionV0(t2)) - continue; - if (t2.index() <= t1.index()) - continue; - if (t1.protonIndex() == t2.protonIndex()) + if (!selectionV0(t1) || !selectionV0(t2)) { continue; - if (t1.pionIndex() == t2.pionIndex()) - continue; - if (t1.protonIndex() == t2.pionIndex()) + } + if (t2.index() <= t1.index()) { continue; - if (t1.pionIndex() == t2.protonIndex()) + } + if (hasSharedDaughters(t1, t2)) continue; + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); + + if (doMixLeg1) { + fillReplacementControlMap(t1.v0Status(), t2.v0Status(), 1, true, + ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()), + 1.0f); + } + if (doMixLeg2) { + fillReplacementControlMap(t1.v0Status(), t2.v0Status(), 2, true, + ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()), + 1.0f); + } - // scan prior events for replacements for t1 struct PV { AllTrackCandidates* pool; - int nRepl; + int nRepl1 = 0; + int nRepl2 = 0; }; + std::vector usable; int totalRepl = 0; int mixes = 0; - for (auto it = eventPools[bin].rbegin(); - it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { + for (auto it = eventPools[bin].rbegin(); it != eventPools[bin].rend() && mixes < nEvtMixing; ++it, ++mixes) { const int collision2idx = it->first; auto& poolB = it->second; - if (collision2idx == collision1.index()) + + if (collision2idx == collision1.index()) { continue; + } + + int nRepl1 = 0; + int nRepl2 = 0; - int nRepl = 0; for (auto& tX : poolB) { - if (!selectionV0(tX)) + if (!selectionV0(tX)) { continue; - if (checkKinematics(t1, tX)) - ++nRepl; + } + + if (doMixLeg1) { + if (checkKinematics(t1, tX)) { + ++nRepl1; + } + } + + if (doMixLeg2) { + if (checkKinematics(t2, tX)) { + ++nRepl2; + } + } } - if (nRepl > 0) { - usable.push_back(PV{&poolB, nRepl}); - totalRepl += nRepl; + + if (nRepl1 > 0 || nRepl2 > 0) { + usable.push_back(PV{&poolB, nRepl1, nRepl2}); + totalRepl += nRepl1 + nRepl2; } } - if (totalRepl == 0) + if (totalRepl <= 0) { continue; + } + const float wBase = 1.0f / static_cast(totalRepl); - // emit mixed pairs: tX replaces t1; t2 stays for (auto& pv : usable) { auto& poolB = *pv.pool; + for (auto& tX : poolB) { - if (!selectionV0(tX)) - continue; - if (!checkKinematics(t1, tX)) + if (!selectionV0(tX)) { continue; + } - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()); - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + // -------- leg-1 replacement: (tX, t2) + if (doMixLeg1) { + if (checkKinematics(t1, tX)) { + fillReplacementControlMap(tX.v0Status(), t2.v0Status(), 1, false, + ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()), + wBase); + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), + t2.lambdaMass()); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(tX.v0Status(), t2.v0Status(), + lambda, lambda2, proton, proton2, + 1, wBase, 1); + } + } - const float dPhi = std::fabs(RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic)); - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, wBase); + // -------- leg-2 replacement: (t1, tX) + if (doMixLeg2) { + if (checkKinematics(t2, tX)) { + fillReplacementControlMap(t1.v0Status(), tX.v0Status(), 2, false, + ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()), + wBase); + auto proton = ROOT::Math::PtEtaPhiMVector(t1.protonPt(), t1.protonEta(), t1.protonPhi(), + o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), + t1.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), + o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), + tX.lambdaMass()); + + const float dPhi = RecoDecay::constrainAngle( + RecoDecay::constrainAngle(lambda.Phi(), 0.0F, harmonic) - + RecoDecay::constrainAngle(lambda2.Phi(), 0.0F, harmonic), + -TMath::Pi(), harmonicDphi); + + histos.fill(HIST("deltaPhiMix"), dPhi, wBase); + fillHistograms(t1.v0Status(), tX.v0Status(), + lambda, lambda2, proton, proton2, + 1, wBase, 2); + } + } } } } + // push current event into pool auto sliced = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); eventPools[bin].emplace_back(collision1.index(), std::move(sliced)); - if ((int)eventPools[bin].size() > nEvtMixing) + if ((int)eventPools[bin].size() > nEvtMixing) { eventPools[bin].pop_front(); + } } } PROCESS_SWITCH(lambdaspincorrderived, processMEV3, "Process data ME (first-leg, pair-3D maps)", false); static constexpr int N_STATUS = 2; // v0Status ∈ {0,1} + struct MatchRef { + int64_t collisionIdx; + int64_t rowIndex; + }; - struct MixBinner { - // constructed from the task's configurables; φ is assumed already constrained into [0, 2π) - float ptMin, ptMax, ptStep; - float etaMin, etaMax, etaStep; - float phiMin, phiMax, phiStep; - - // Mass binning: [1.09, 1.14) with 50 bins (1e-3 GeV/c^2) - static constexpr float mMin = 1.09f; - static constexpr float mMax = 1.14f; // exclusive - static constexpr int nM_ = 1; - static constexpr float mStep = (mMax - mMin) / nM_; + static inline void limitMatchesToNEvents(std::vector& matches, int nMixEvents) + { + if (nMixEvents <= 0 || matches.empty()) { + return; + } + std::vector kept; + kept.reserve(matches.size()); - int nPt_, nEta_, nPhi_; + std::unordered_set usedEvents; + usedEvents.reserve(nMixEvents * 2); - MixBinner(float ptMin_, float ptMax_, float ptStep_, - float etaAbsMax, float etaStep_, - float phiStep_) - : ptMin(ptMin_), ptMax(ptMax_), ptStep(ptStep_), etaMin(-etaAbsMax), etaMax(+etaAbsMax), etaStep(etaStep_), phiMin(0.f), phiMax(static_cast(2.0 * TMath::Pi())), phiStep(phiStep_) + for (const auto& m : matches) { + if (usedEvents.count(m.collisionIdx) || (int)usedEvents.size() < nMixEvents) { + kept.push_back(m); + usedEvents.insert(m.collisionIdx); + } + } + matches.swap(kept); + } + + struct MixBinnerR { + float ptMin, ptMax, ptStep; + float etaMin, etaMax, etaStep; + float phiMin, phiMax, phiStep; + + float mMin, mMax, mStep; + int nM_; + + std::vector rEdges; + int nR_; + + int nPt_, nEta_, nPhi_; + + MixBinnerR(float ptMin_, float ptMax_, float ptStep_, + float etaAbsMax, float etaStep_, + float phiStep_, + float mMin_, float mMax_, int nMassBins_, + std::vector rEdges_) + : ptMin(ptMin_), + ptMax(ptMax_), + ptStep(ptStep_), + etaMin(-etaAbsMax), + etaMax(+etaAbsMax), + etaStep(etaStep_), + phiMin(0.f), + phiMax(static_cast(2.0 * TMath::Pi())), + phiStep(phiStep_), + mMin(mMin_), + mMax(mMax_), + mStep(0.f), + nM_(std::max(1, nMassBins_)), + rEdges(std::move(rEdges_)), + nR_(0), + nPt_(0), + nEta_(0), + nPhi_(0) { ptStep = (ptStep > 0.f ? ptStep : 0.1f); etaStep = (etaStep > 0.f ? etaStep : 0.1f); phiStep = (phiStep > 0.f ? phiStep : 0.1f); + if (!(mMax > mMin)) { + mMin = 1.09f; + mMax = 1.14f; + } + mStep = (mMax - mMin) / static_cast(nM_); + if (!(mStep > 0.f)) { + nM_ = 5; + mMin = 1.09f; + mMax = 1.14f; + mStep = (mMax - mMin) / static_cast(nM_); + } + + if (rEdges.size() < 2) { + rEdges = {3.0, 5.0, 7.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0}; + } + nR_ = static_cast(rEdges.size()) - 1; + nPt_ = std::max(1, static_cast(std::floor((ptMax - ptMin) / ptStep + 0.5f))); nEta_ = std::max(1, static_cast(std::floor((etaMax - etaMin) / etaStep + 0.5f))); nPhi_ = std::max(1, static_cast(std::ceil((phiMax - phiMin) / phiStep))); @@ -845,199 +1108,1069 @@ struct lambdaspincorrderived { inline int nEta() const { return nEta_; } inline int nPhi() const { return nPhi_; } inline int nM() const { return nM_; } + inline int nR() const { return nR_; } inline int binFromValue(float v, float vmin, float step, int nBins) const { - if (!std::isfinite(v)) + if (!std::isfinite(v) || !std::isfinite(vmin) || !std::isfinite(step) || step <= 0.f || nBins <= 0) { return -1; + } const float x = (v - vmin) / step; int b = static_cast(std::floor(x + 1e-6f)); - if (b < 0) + if (b < 0) { return -1; - if (b >= nBins) - b = nBins - 1; // clamp exact-top edge + } + if (b >= nBins) { + b = nBins - 1; + } return b; } inline int ptBin(float pt) const { return binFromValue(pt, ptMin, ptStep, nPt_); } inline int etaBin(float eta) const { return binFromValue(eta, etaMin, etaStep, nEta_); } - inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } // φ already constrained upstream + inline int phiBin(float phi) const { return binFromValue(phi, phiMin, phiStep, nPhi_); } inline int massBin(float m) const { return binFromValue(m, mMin, mStep, nM_); } - }; - struct BufferCand { - int64_t collisionIdx; // from col.index() - int64_t rowIndex; // global row id in V0s - uint8_t v0Status; - uint16_t ptBin, etaBin, phiBin, mBin; + inline int radiusBin(float r) const + { + if (!std::isfinite(r) || nR_ <= 0) { + return -1; + } + if (r < rEdges.front() || r >= rEdges.back()) { + return -1; + } + auto it = std::upper_bound(rEdges.begin(), rEdges.end(), static_cast(r)); + return static_cast(it - rEdges.begin()) - 1; + } }; - struct MatchRef { + struct BufferCandR { int64_t collisionIdx; int64_t rowIndex; + uint8_t v0Status; + uint16_t ptBin, etaBin, phiBin, mBin, rBin; }; - // 6D key: (colBin, status, pt, eta, phi, mass) - static inline size_t linearKey(int colBin, int statBin, - int ptBin, int etaBin, int phiBin, int mBin, - int nStatus, int nPt, int nEta, int nPhi, int nM) + static inline size_t linearKeyR(int colBin, int statBin, + int ptBin, int etaBin, int phiBin, int mBin, int rBin, + int nStatus, int nPt, int nEta, int nPhi, int nM, int nR) { - return ((((((static_cast(colBin) * nStatus + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin)); + return (((((((static_cast(colBin) * nStatus + statBin) * nPt + ptBin) * nEta + etaBin) * nPhi + phiBin) * nM + mBin) * nR + rBin)); } - // ===================== Main mixing (with mass-bin + random unique sampling) ===================== - void processMEV4(EventCandidates const& collisions, AllTrackCandidates const& V0s) + // ------------------------------------- + // 2) MC-only selection + kinematics cuts + // ------------------------------------- + template + bool selectionV0MC(T const& candidate) { - // Build binner from your existing configurables - MixBinner mb{ - ptMin.value, ptMax.value, ptMix.value, // pT range & step - v0eta.value, etaMix.value, // |eta| max & step - phiMix.value // φ step; φ range fixed to [0, 2π) - }; + auto particle = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate), + mcacc::lamEta(candidate), + mcacc::lamPhi(candidate), + mcacc::lamMass(candidate)); + if (std::abs(particle.Rapidity()) > rapidity || std::abs(particle.Eta()) > v0eta) { + return false; + } + if (mcacc::lamMass(candidate) < MassMin || mcacc::lamMass(candidate) > MassMax) { + return false; + } + if (mcacc::v0CosPA(candidate) < cosPA) { + return false; + } + if (checkDoubleStatus && mcacc::doubleStatus(candidate)) { + return false; + } + if (mcacc::v0Radius(candidate) > radiusMax) { + return false; + } + if (mcacc::v0Radius(candidate) < radiusMin) { + return false; + } + if (mcacc::dcaDau(candidate) > dcaDaughters) { + return false; + } + if (mcacc::v0Status(candidate) == 0 && (std::abs(mcacc::dcaPos(candidate)) < dcaProton || std::abs(mcacc::dcaNeg(candidate)) < dcaPion)) { + return false; + } + if (mcacc::v0Status(candidate) == 1 && (std::abs(mcacc::dcaPos(candidate)) < dcaPion || std::abs(mcacc::dcaNeg(candidate)) < dcaProton)) { + return false; + } + if (mcacc::lamPt(candidate) < ptMin) { + return false; + } + if (mcacc::lamPt(candidate) > ptMax) { + return false; + } + return true; + } + + template + bool checkKinematicsMC(T1 const& candidate1, T2 const& candidate2) + { + // keep same species/status + if (mcacc::v0Status(candidate1) != mcacc::v0Status(candidate2)) { + return false; + } + + // pT window + if (std::abs(mcacc::lamPt(candidate1) - mcacc::lamPt(candidate2)) > ptMix) { + return false; + } + + // eta or rapidity window (etaMix used as Δη or Δy) + if (!userapidity) { + if (std::abs(mcacc::lamEta(candidate1) - mcacc::lamEta(candidate2)) > etaMix) { + return false; + } + } else { + const auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate1), mcacc::lamEta(candidate1), + mcacc::lamPhi(candidate1), mcacc::lamMass(candidate1)); + const auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(candidate2), mcacc::lamEta(candidate2), + mcacc::lamPhi(candidate2), mcacc::lamMass(candidate2)); + if (std::abs(l1.Rapidity() - l2.Rapidity()) > etaMix) { + return false; + } + } + + // delta-phi window (wrapped) + const float dphi = deltaPhiMinusPiToPi((float)mcacc::lamPhi(candidate1), + (float)mcacc::lamPhi(candidate2)); + if (std::abs(dphi) > phiMix) { + return false; + } + + // mass window (optional but consistent with data) + if (std::abs(mcacc::lamMass(candidate1) - mcacc::lamMass(candidate2)) > massMix) { + return false; + } + + return true; + } + + // ----------------------------------------- + // 3) MC filter + aliases (distinct from data) + // ----------------------------------------- + Filter centralityFilterMC = (nabs(aod::lambdaeventmc::centmc) < centMax && nabs(aod::lambdaeventmc::centmc) > centMin); + + using EventCandidatesMC = soa::Filtered; + using AllTrackCandidatesMC = aod::LambdaPairmcs; + + // IMPORTANT: MC preslice uses the MC event index column + Preslice tracksPerCollisionV0mc = aod::lambdapairmc::lambdaeventmcId; + + // ----------------------------------------- + // 4) MC Same-event processing (like processData) + // ----------------------------------------- + void processMC(EventCandidatesMC::iterator const& collision, AllTrackCandidatesMC const& V0sMC) + { + const float centrality = mcacc::cent(collision); - const int nCol = colBinning.getAllBinsCount(); // event-class bins (vz, centrality) - const int nStat = N_STATUS; // 2 + for (const auto& v0 : V0sMC) { + if (!selectionV0MC(v0)) { + continue; + } + histos.fill(HIST("hPtRadiusV0"), mcacc::lamPt(v0), mcacc::v0Radius(v0)); + histos.fill(HIST("ptCent"), mcacc::lamPt(v0), centrality); + histos.fill(HIST("etaCent"), mcacc::lamEta(v0), centrality); + + proton = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(v0), mcacc::prEta(v0), mcacc::prPhi(v0), + o2::constants::physics::MassProton); + lambda = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(v0), mcacc::lamEta(v0), mcacc::lamPhi(v0), + mcacc::lamMass(v0)); + if (mcacc::v0Status(v0) == 0) { + histos.fill(HIST("hEtaPhiLambdaRaw"), lambda.Phi(), lambda.Eta(), getNUAWeight(0, lambda.Phi(), lambda.Eta())); + } else { + histos.fill(HIST("hEtaPhiAntiLambdaRaw"), lambda.Phi(), lambda.Eta(), getNUAWeight(1, lambda.Phi(), lambda.Eta())); + } + + for (const auto& v02 : V0sMC) { + if (v02.index() <= v0.index()) { + continue; + } + if (!selectionV0MC(v02)) { + continue; + } + if (hasSharedDaughtersMC(v0, v02)) + continue; + proton2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(v02), mcacc::prEta(v02), mcacc::prPhi(v02), + o2::constants::physics::MassProton); + lambda2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(v02), mcacc::lamEta(v02), mcacc::lamPhi(v02), + mcacc::lamMass(v02)); + + histos.fill(HIST("deltaPhiSame"), + RecoDecay::constrainAngle(mcacc::lamPhi(v0) - mcacc::lamPhi(v02), + -TMath::Pi(), harmonicDphi)); + + // const int ptype = pairTypeCode(mcacc::v0Status(v0), mcacc::v0Status(v02)); + // datatype=0 (same event) + fillHistograms(mcacc::v0Status(v0), mcacc::v0Status(v02), + lambda, lambda2, proton, proton2, + /*datatype=*/0, /*mixpairweight=*/1.0f); + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMC, "Process MC (SE)", false); + + static inline float phi0To2Pi(float phi) + { + // harmonic=1, min=0 => [0, 2pi) + return RecoDecay::constrainAngle(phi, 0.0f, 1); + } + + static inline float deltaPhiMinusPiToPi(float phiA, float phiB) + { + // returns in [-pi, pi) + const float d = phi0To2Pi(phiA) - phi0To2Pi(phiB); + return RecoDecay::constrainAngle(d, -TMath::Pi(), 1); + } + + static inline float absDeltaPhi(float phiA, float phiB) + { + return std::abs(deltaPhiMinusPiToPi(phiA, phiB)); + } + // symmetric neighbors for phi: no wrap at edge + static inline void collectNeighborBinsPhi(int b, int nPhi, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb >= 0 && bb < nPhi) { + out.push_back(bb); + } + } + std::sort(out.begin(), out.end()); + out.erase(std::unique(out.begin(), out.end()), out.end()); + } + static inline void collectNeighborBinsClamp(int b, int nBins, int nNeighbor, std::vector& out) + { + out.clear(); + out.reserve(2 * nNeighbor + 1); + for (int d = -nNeighbor; d <= nNeighbor; ++d) { + const int bb = b + d; + if (bb >= 0 && bb < nBins) { + out.push_back(bb); + } + } + } + static inline int getMassRegionFromEdges(float m, const std::vector& edges) + { + if (edges.size() != 4) { + return -1; + } + + if (m >= edges[0] && m < edges[1]) + return 0; // low sideband + if (m >= edges[1] && m < edges[2]) + return 1; // signal + if (m >= edges[2] && m < edges[3]) + return 2; // high sideband + + return -1; + } + static inline int getMassMixClassFromEdges(float m, const std::vector& edges) + { + // no mass separation + if (edges.size() == 2) { + if (m >= edges[0] && m < edges[1]) + return 0; + return -1; + } + + // 3 regions: SB low, signal, SB high + if (edges.size() == 4) { + if (m >= edges[0] && m < edges[1]) + return 0; // low sideband + if (m >= edges[1] && m < edges[2]) + return 1; // signal + if (m >= edges[2] && m < edges[3]) + return 0; // high sideband merged with low sideband + return -1; + } + + return -1; + } + static inline uint64_t splitmix64(uint64_t x) + { + // simple deterministic hash for reproducible shuffling + x += 0x9e3779b97f4a7c15ULL; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; + x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; + return x ^ (x >> 31); + } + + void processMEV6(EventCandidates const& collisions, AllTrackCandidates const& V0s) + { + MixBinnerR mb{ + ptMin.value, + ptMax.value, + ptMix.value, + v0etaMixBuffer.value, + etaMix.value, + phiMix.value, + MassMin.value, + MassMax.value, + cfgV5MassBins.value, + cfgMixRadiusParam.cfgMixRadiusBins.value}; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; const int nPt = mb.nPt(); const int nEta = mb.nEta(); const int nPhi = mb.nPhi(); const int nM = mb.nM(); + const int nR = mb.nR(); - const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM; - std::vector> buffer(nKeys); + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM * nR; + std::vector> buffer(nKeys); - // ---- PASS 1: fill 6D buffer ---- + // -------- PASS 1: fill buffer -------- for (auto const& col : collisions) { const int colBin = colBinning.getBin(std::make_tuple(col.posz(), col.cent())); + if (colBin < 0) { + continue; + } + auto slice = V0s.sliceBy(tracksPerCollisionV0, col.index()); for (auto const& t : slice) { - if (!selectionV0(t)) + if (!selectionV0(t)) { continue; + } const int status = static_cast(t.v0Status()); - if (status < 0 || status >= nStat) + if (status < 0 || status >= nStat) { continue; + } - // Bin kinematics (φ already constrained via your call-site) const int ptB = mb.ptBin(t.lambdaPt()); - const int etaB = mb.etaBin(t.lambdaEta()); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), 0.0F, harmonic)); - const int mB = mb.massBin(t.lambdaMass()); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) + + int etaB = mb.etaBin(t.lambdaEta()); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(t.lambdaPt(), t.lambdaEta(), t.lambdaPhi(), t.lambdaMass()); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(t.lambdaPhi(), 0.0, harmonic)); + const int mB = getMassMixClassFromEdges(t.lambdaMass(), massMixEdges.value); + const int rB = mb.radiusBin(t.v0Radius()); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { continue; + } - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); + const size_t key = linearKeyR(colBin, status, ptB, etaB, phiB, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR); - buffer[key].push_back(BufferCand{ + buffer[key].push_back(BufferCandR{ .collisionIdx = static_cast(col.index()), - .rowIndex = static_cast(t.globalIndex()), // adapt accessor if needed + .rowIndex = static_cast(t.globalIndex()), .v0Status = static_cast(status), .ptBin = static_cast(ptB), .etaBin = static_cast(etaB), .phiBin = static_cast(phiB), - .mBin = static_cast(mB)}); + .mBin = static_cast(mB), + .rBin = static_cast(rB)}); } } - // ---- PASS 2: mixing over same-event pairs ---- - for (auto const& collision1 : collisions) { - const int colBin = colBinning.getBin(std::make_tuple(collision1.posz(), collision1.cent())); - auto poolA = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); + const int nN_pt = std::max(0, cfgV5NeighborPt.value); + const int nN_eta = std::max(0, cfgV5NeighborEta.value); + const int nN_phi = std::max(0, cfgV5NeighborPhi.value); - for (auto const& [t1, t2] : - soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + std::vector ptBins, etaBins, phiBins; + std::vector matches1, matches2; + matches1.reserve(256); + matches2.reserve(256); - if (!selectionV0(t1) || !selectionV0(t2)) - continue; - if (t2.index() <= t1.index()) - continue; + auto collectMatchesForReplacedLeg = [&](auto const& tRep, auto const& tKeep, int colBin, int64_t curColIdx, std::vector& matches) { + matches.clear(); - // no shared daughters - if (t1.protonIndex() == t2.protonIndex()) - continue; - if (t1.pionIndex() == t2.pionIndex()) + const int status = static_cast(tRep.v0Status()); + if (status < 0 || status >= nStat) { + return; + } + + const int ptB = mb.ptBin(tRep.lambdaPt()); + + int etaB = mb.etaBin(tRep.lambdaEta()); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(tRep.lambdaPt(), tRep.lambdaEta(), tRep.lambdaPhi(), tRep.lambdaMass()); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(tRep.lambdaPhi(), 0.0, harmonic)); + const int mB = getMassMixClassFromEdges(tRep.lambdaMass(), massMixEdges.value); + const int rB = mb.radiusBin(tRep.v0Radius()); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { + return; + } + auto collectFromBins = [&](const std::vector& ptUseBins, + const std::vector& etaUseBins, + const std::vector& phiUseBins) { + for (int ptUse : ptUseBins) { + for (int etaUse : etaUseBins) { + for (int phiUse : phiUseBins) { + const auto& vec = buffer[linearKeyR(colBin, status, ptUse, etaUse, phiUse, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR)]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) + continue; + + auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); + + if (!selectionV0(tX)) + continue; + if (!checkKinematics(tRep, tX)) + continue; + + if (tX.globalIndex() == tRep.globalIndex()) + continue; + if (tX.globalIndex() == tKeep.globalIndex()) + continue; + + if (hasSharedDaughters(tX, tKeep)) + continue; + if (hasSharedDaughters(tX, tRep)) + continue; + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } + } + } + }; + + matches.clear(); + + // 1) exact bin first + ptBins.clear(); + etaBins.clear(); + phiBins.clear(); + + ptBins.push_back(ptB); + etaBins.push_back(etaB); + phiBins.push_back(phiB); + + collectFromBins(ptBins, etaBins, phiBins); + + // 2) if exact bin gives fewer than required matches, also search neighbors + const int targetMatches = (cfgV5MaxMatches.value > 0) ? cfgV5MaxMatches.value : 1; + + if ((int)matches.size() < targetMatches) { + std::vector ptBinsN, etaBinsN, phiBinsN; + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBinsN); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBinsN); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBinsN); + + for (int ptUse : ptBinsN) { + for (int etaUse : etaBinsN) { + for (int phiUse : phiBinsN) { + if (ptUse == ptB && etaUse == etaB && phiUse == phiB) + continue; + + const auto& vec = buffer[linearKeyR(colBin, status, ptUse, etaUse, phiUse, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR)]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) + continue; + + auto tX = V0s.iteratorAt(static_cast(bc.rowIndex)); + + if (!selectionV0(tX)) + continue; + if (!checkKinematics(tRep, tX)) + continue; + + if (tX.globalIndex() == tRep.globalIndex()) + continue; + if (tX.globalIndex() == tKeep.globalIndex()) + continue; + + if (hasSharedDaughters(tX, tKeep)) + continue; + if (hasSharedDaughters(tX, tRep)) + continue; + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } + } + } + } + + std::sort(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); + }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; + }), + matches.end()); + }; + + auto downsampleMatches = [&](std::vector& matches, uint64_t seedBase) { + if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { + uint64_t seed = cfgMixSeed.value ^ splitmix64(seedBase); + const int K = cfgV5MaxMatches.value; + for (int i = 0; i < K; ++i) { + seed = splitmix64(seed); + const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); + std::swap(matches[i], matches[j]); + } + matches.resize(K); + } + }; + + // -------- PASS 2: configurable one-leg / two-leg mixing -------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(col1.posz(), col1.cent())); + if (colBin < 0) { + continue; + } + + const int64_t curColIdx = static_cast(col1.index()); + auto poolA = V0s.sliceBy(tracksPerCollisionV0, col1.index()); + + for (auto const& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + if (!selectionV0(t1) || !selectionV0(t2)) { continue; - if (t1.protonIndex() == t2.pionIndex()) + } + if (t2.index() <= t1.index()) { continue; - if (t1.pionIndex() == t2.protonIndex()) + } + if (hasSharedDaughters(t1, t2)) continue; + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); + + if (doMixLeg1) { + collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + limitMatchesToNEvents(matches1, nEvtMixing.value); + downsampleMatches(matches1, (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches1.clear(); + } + + if (doMixLeg2) { + collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + limitMatchesToNEvents(matches2, nEvtMixing.value); + downsampleMatches(matches2, (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches2.clear(); + } + + // --- fill target distributions for the original SE leg that is to be replaced + if (doMixLeg1) { + fillReplacementControlMap(t1.v0Status(), t2.v0Status(), 1, true, + ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()), + 1.0f); + } + + if (doMixLeg2) { + fillReplacementControlMap(t1.v0Status(), t2.v0Status(), 2, true, + ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()), + 1.0f); + } + int nFill1 = 0; + int nFill2 = 0; + // count actual accepted fills for leg-1 replacement + if (doMixLeg1) { + for (auto const& m : matches1) { + auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); + if (!selectionV0(tX)) + continue; + if (!checkKinematics(t1, tX)) + continue; + if (tX.globalIndex() == t1.globalIndex()) + continue; + if (tX.globalIndex() == t2.globalIndex()) + continue; + if (hasSharedDaughters(tX, t2)) + continue; + if (hasSharedDaughters(tX, t1)) + continue; + ++nFill1; + } + } + + // count actual accepted fills for leg-2 replacement + if (doMixLeg2) { + for (auto const& m : matches2) { + auto tY = V0s.iteratorAt(static_cast(m.rowIndex)); + if (!checkKinematics(t2, tY)) + continue; + if (!selectionV0(tY)) + continue; + if (tY.globalIndex() == t2.globalIndex()) + continue; + if (tY.globalIndex() == t1.globalIndex()) + continue; + if (hasSharedDaughters(tY, t2)) + continue; + if (hasSharedDaughters(tY, t1)) + continue; + ++nFill2; + } + } - const int status = static_cast(t1.v0Status()); - if (status < 0 || status >= nStat) + if (nFill1 <= 0 && nFill2 <= 0) { continue; + } + const int nUse = nFill1 + nFill2; + const float wSE = (nUse > 0) ? 1.0f / static_cast(nUse) : 0.0f; + + if (doMixLeg1 && nFill1 > 0) { + for (auto const& m : matches1) { + auto tX = V0s.iteratorAt(static_cast(m.rowIndex)); + if (!selectionV0(tX)) { + continue; + } + if (!checkKinematics(t1, tX)) + continue; + if (tX.globalIndex() == t1.globalIndex()) + continue; + if (tX.globalIndex() == t2.globalIndex()) + continue; + if (hasSharedDaughters(tX, t1)) + continue; + if (hasSharedDaughters(tX, t2)) + continue; + fillReplacementControlMap(tX.v0Status(), t2.v0Status(), 1, false, + ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()), + wSE); + auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + + // const int ptype = pairTypeCode(tX.v0Status(), t2.v0Status()); + + const float meWeight = wSE; + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight, 1); + } + } + + if (doMixLeg2 && nFill2 > 0) { + for (auto const& m : matches2) { + auto tY = V0s.iteratorAt(static_cast(m.rowIndex)); + if (!selectionV0(tY)) { + continue; + } + if (!checkKinematics(t2, tY)) + continue; + if (tY.globalIndex() == t2.globalIndex()) + continue; + if (tY.globalIndex() == t1.globalIndex()) + continue; + if (hasSharedDaughters(tY, t1)) + continue; + if (hasSharedDaughters(tY, t2)) + continue; + fillReplacementControlMap(t1.v0Status(), tY.v0Status(), 2, false, + ROOT::Math::PtEtaPhiMVector(tY.lambdaPt(), tY.lambdaEta(), tY.lambdaPhi(), tY.lambdaMass()), + wSE); + auto proton = ROOT::Math::PtEtaPhiMVector(t1.protonPt(), t1.protonEta(), t1.protonPhi(), o2::constants::physics::MassProton); + auto lambda = ROOT::Math::PtEtaPhiMVector(t1.lambdaPt(), t1.lambdaEta(), t1.lambdaPhi(), t1.lambdaMass()); + auto proton2 = ROOT::Math::PtEtaPhiMVector(tY.protonPt(), tY.protonEta(), tY.protonPhi(), o2::constants::physics::MassProton); + auto lambda2 = ROOT::Math::PtEtaPhiMVector(tY.lambdaPt(), tY.lambdaEta(), tY.lambdaPhi(), tY.lambdaMass()); + + // const int ptype = pairTypeCode(t1.v0Status(), tY.v0Status()); + const float meWeight = wSE; + const float dPhi = deltaPhiMinusPiToPi((float)lambda.Phi(), (float)lambda2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + fillHistograms(t1.v0Status(), tY.v0Status(), lambda, lambda2, proton, proton2, 1, meWeight, 2); + } + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processMEV6, "Process data ME v6 with radius buffer", false); + void processMCMEV6(EventCandidatesMC const& collisions, AllTrackCandidatesMC const& V0sMC) + { + MixBinnerR mb{ + ptMin.value, + ptMax.value, + ptMix.value, + v0etaMixBuffer.value, + etaMix.value, + phiMix.value, + MassMin.value, + MassMax.value, + cfgV5MassBins.value, + cfgMixRadiusParam.cfgMixRadiusBins.value}; + + const int nCol = colBinning.getAllBinsCount(); + const int nStat = N_STATUS; + const int nPt = mb.nPt(); + const int nEta = mb.nEta(); + const int nPhi = mb.nPhi(); + const int nM = mb.nM(); + const int nR = mb.nR(); + + const size_t nKeys = static_cast(nCol) * nStat * nPt * nEta * nPhi * nM * nR; + std::vector> buffer(nKeys); + + // -------- PASS 1: fill buffer -------- + for (auto const& col : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col), mcacc::cent(col))); + if (colBin < 0) { + continue; + } - // Bin of t1 defines where to search (exact 6D bin) - const int ptB = mb.ptBin(t1.lambdaPt()); - const int etaB = mb.etaBin(t1.lambdaEta()); - const int phiB = mb.phiBin(RecoDecay::constrainAngle(t1.lambdaPhi(), 0.0F, harmonic)); // φ already constrained upstream - const int mB = mb.massBin(t1.lambdaMass()); - if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0) + auto slice = V0sMC.sliceBy(tracksPerCollisionV0mc, col.index()); + + for (auto const& t : slice) { + if (!selectionV0MC(t)) { continue; + } - const size_t key = linearKey(colBin, status, ptB, etaB, phiB, mB, - nStat, nPt, nEta, nPhi, nM); - auto const& binVec = buffer[key]; - if (binVec.empty()) + const int status = mcacc::v0Status(t); + if (status < 0 || status >= nStat) { continue; + } - // Collect all partners from this 6D bin but different collision - std::vector matches; - matches.reserve(binVec.size()); - const int64_t curColIdx = static_cast(collision1.index()); + const int ptB = mb.ptBin(mcacc::lamPt(t)); - for (const auto& bc : binVec) { - if (bc.collisionIdx == curColIdx) - continue; // ensure different event - matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + int etaB = mb.etaBin(mcacc::lamEta(t)); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t), mcacc::lamEta(t), mcacc::lamPhi(t), mcacc::lamMass(t)); + etaB = mb.etaBin(lv.Rapidity()); } - if (matches.empty()) + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(t), 0.0, harmonic)); + const int mB = getMassMixClassFromEdges(mcacc::lamMass(t), massMixEdges.value); + const int rB = mb.radiusBin(mcacc::v0Radius(t)); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { continue; + } + + const size_t key = linearKeyR(colBin, status, ptB, etaB, phiB, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR); + + buffer[key].push_back(BufferCandR{ + .collisionIdx = static_cast(col.index()), + .rowIndex = static_cast(t.globalIndex()), + .v0Status = static_cast(status), + .ptBin = static_cast(ptB), + .etaBin = static_cast(etaB), + .phiBin = static_cast(phiB), + .mBin = static_cast(mB), + .rBin = static_cast(rB)}); + } + } + + const int nN_pt = std::max(0, cfgV5NeighborPt.value); + const int nN_eta = std::max(0, cfgV5NeighborEta.value); + const int nN_phi = std::max(0, cfgV5NeighborPhi.value); + + std::vector ptBins, etaBins, phiBins; + std::vector matches1, matches2; + matches1.reserve(256); + matches2.reserve(256); + + auto collectMatchesForReplacedLeg = [&](auto const& tRep, auto const& tKeep, int colBin, int64_t curColIdx, std::vector& matches) { + matches.clear(); + + const int status = mcacc::v0Status(tRep); + if (status < 0 || status >= nStat) { + return; + } + + const int ptB = mb.ptBin(mcacc::lamPt(tRep)); - // ---------- YOUR PREFERRED RANDOM UNIQUE SAMPLING BLOCK ---------- - const int cap = nEvtMixing.value; - const int n = static_cast(matches.size()); - if (cap > 0 && cap < n) { - std::uniform_int_distribution dist(0, n - 1); - // pick cap unique indices - std::unordered_set chosen; - chosen.reserve(cap * 2); - while ((int)chosen.size() < cap) { - chosen.insert(dist(rng)); + int etaB = mb.etaBin(mcacc::lamEta(tRep)); + if (userapidity) { + const auto lv = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tRep), mcacc::lamEta(tRep), mcacc::lamPhi(tRep), mcacc::lamMass(tRep)); + etaB = mb.etaBin(lv.Rapidity()); + } + + const int phiB = mb.phiBin(RecoDecay::constrainAngle(mcacc::lamPhi(tRep), 0.0, harmonic)); + const int mB = getMassMixClassFromEdges(mcacc::lamMass(tRep), massMixEdges.value); + const int rB = mb.radiusBin(mcacc::v0Radius(tRep)); + + if (ptB < 0 || etaB < 0 || phiB < 0 || mB < 0 || rB < 0) { + return; + } + auto collectFromBins = [&](const std::vector& ptUseBins, + const std::vector& etaUseBins, + const std::vector& phiUseBins) { + for (int ptUse : ptUseBins) { + for (int etaUse : etaUseBins) { + for (int phiUse : phiUseBins) { + const auto& vec = buffer[linearKeyR(colBin, status, ptUse, etaUse, phiUse, mB, rB, + nStat, nPt, nEta, nPhi, nM, nR)]; + + for (auto const& bc : vec) { + if (bc.collisionIdx == curColIdx) + continue; + + auto tX = V0sMC.iteratorAt(static_cast(bc.rowIndex)); + + if (!selectionV0MC(tX)) + continue; + if (!checkKinematicsMC(tRep, tX)) + continue; + + if (tX.globalIndex() == tRep.globalIndex()) + continue; + if (tX.globalIndex() == tKeep.globalIndex()) + continue; + + if (hasSharedDaughtersMC(tX, tKeep)) + continue; + if (hasSharedDaughtersMC(tX, tRep)) + continue; + + matches.push_back(MatchRef{bc.collisionIdx, bc.rowIndex}); + } + } } - std::vector subset; - subset.reserve(cap); - for (int idx : chosen) - subset.push_back(matches[idx]); - matches.swap(subset); + } + }; + + matches.clear(); + // 1) try exact bin only + ptBins.clear(); + etaBins.clear(); + phiBins.clear(); + + ptBins.push_back(ptB); + etaBins.push_back(etaB); + phiBins.push_back(phiB); + + collectFromBins(ptBins, etaBins, phiBins); + + // 2) if exact bin does not give enough, top up from neighbors + const int targetMatches = (cfgV5MaxMatches.value > 0) ? cfgV5MaxMatches.value : 1; + + if ((int)matches.size() < targetMatches) { + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); + + collectFromBins(ptBins, etaBins, phiBins); + } + + // if nothing found, then try neighboring bins + if (matches.empty()) { + collectNeighborBinsClamp(ptB, nPt, nN_pt, ptBins); + collectNeighborBinsClamp(etaB, nEta, nN_eta, etaBins); + collectNeighborBinsPhi(phiB, nPhi, nN_phi, phiBins); + + collectFromBins(ptBins, etaBins, phiBins); + } + + std::sort(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return std::tie(a.collisionIdx, a.rowIndex) < std::tie(b.collisionIdx, b.rowIndex); + }); + matches.erase(std::unique(matches.begin(), matches.end(), + [](auto const& a, auto const& b) { + return a.collisionIdx == b.collisionIdx && a.rowIndex == b.rowIndex; + }), + matches.end()); + }; + + auto downsampleMatches = [&](std::vector& matches, uint64_t seedBase) { + if (cfgV5MaxMatches.value > 0 && (int)matches.size() > cfgV5MaxMatches.value) { + uint64_t seed = cfgMixSeed.value ^ splitmix64(seedBase); + const int K = cfgV5MaxMatches.value; + for (int i = 0; i < K; ++i) { + seed = splitmix64(seed); + const int j = i + (int)(seed % (uint64_t)(matches.size() - i)); + std::swap(matches[i], matches[j]); + } + matches.resize(K); + } + }; + + // -------- PASS 2: configurable one-leg / two-leg mixing -------- + for (auto const& col1 : collisions) { + const int colBin = colBinning.getBin(std::make_tuple(mcacc::posz(col1), mcacc::cent(col1))); + if (colBin < 0) { + continue; + } + + const int64_t curColIdx = static_cast(col1.index()); + auto poolA = V0sMC.sliceBy(tracksPerCollisionV0mc, col1.index()); + + for (auto const& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(poolA, poolA))) { + if (!selectionV0MC(t1) || !selectionV0MC(t2)) { + continue; + } + if (t2.index() <= t1.index()) { + continue; + } + if (hasSharedDaughtersMC(t1, t2)) + continue; + const bool doMixLeg1 = (cfgMixLegMode.value == 0 || cfgMixLegMode.value == 2); + const bool doMixLeg2 = (cfgMixLegMode.value == 1 || cfgMixLegMode.value == 2); + + if (doMixLeg1) { + collectMatchesForReplacedLeg(t1, t2, colBin, curColIdx, matches1); + limitMatchesToNEvents(matches1, nEvtMixing.value); + downsampleMatches(matches1, (uint64_t)t1.globalIndex() ^ (splitmix64((uint64_t)t2.globalIndex()) + 0x111ULL) ^ splitmix64((uint64_t)curColIdx)); } else { - std::shuffle(matches.begin(), matches.end(), rng); + matches1.clear(); + } + if (doMixLeg2) { + collectMatchesForReplacedLeg(t2, t1, colBin, curColIdx, matches2); + limitMatchesToNEvents(matches2, nEvtMixing.value); + downsampleMatches(matches2, (uint64_t)t2.globalIndex() ^ (splitmix64((uint64_t)t1.globalIndex()) + 0x222ULL) ^ splitmix64((uint64_t)curColIdx)); + } else { + matches2.clear(); + } + if (doMixLeg1) { + fillReplacementControlMap(mcacc::v0Status(t1), mcacc::v0Status(t2), 1, true, + ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), mcacc::lamPhi(t1), mcacc::lamMass(t1)), + 1.0f); } - // ---------------------------------------------------------------- - const float wBase = 1.0f / static_cast(matches.size()); + if (doMixLeg2) { + fillReplacementControlMap(mcacc::v0Status(t1), mcacc::v0Status(t2), 2, true, + ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), mcacc::lamMass(t2)), + 1.0f); + } - // Emit mixed pairs: tX replaces t1; keep t2 - for (const auto& m : matches) { - auto tX = V0s.iteratorAt(m.rowIndex); // replace accessor if different - if (!selectionV0(tX)) - continue; // optional extra guard - if (!checkKinematics(t1, tX)) - continue; + int nFill1 = 0; + int nFill2 = 0; + + // count actual accepted fills for leg-1 replacement + if (doMixLeg1) { + for (auto const& m : matches1) { + auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + if (!selectionV0MC(tX)) + continue; + if (!checkKinematicsMC(t1, tX)) + continue; + if (tX.globalIndex() == t1.globalIndex()) + continue; + if (tX.globalIndex() == t2.globalIndex()) + continue; + if (hasSharedDaughtersMC(tX, t1)) + continue; + if (hasSharedDaughtersMC(tX, t2)) + continue; + ++nFill1; + } + } + + // count actual accepted fills for leg-2 replacement + if (doMixLeg2) { + for (auto const& m : matches2) { + auto tY = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + if (!selectionV0MC(tY)) + continue; + if (!checkKinematicsMC(t2, tY)) + continue; + if (tY.globalIndex() == t2.globalIndex()) + continue; + if (tY.globalIndex() == t1.globalIndex()) + continue; + if (hasSharedDaughtersMC(tY, t1)) + continue; + if (hasSharedDaughtersMC(tY, t2)) + continue; + ++nFill2; + } + } + + if (nFill1 <= 0 && nFill2 <= 0) { + continue; + } + const int nUse = nFill1 + nFill2; + const float wSE = (nUse > 0) ? 1.0f / static_cast(nUse) : 0.0f; - auto proton = ROOT::Math::PtEtaPhiMVector(tX.protonPt(), tX.protonEta(), tX.protonPhi(), o2::constants::physics::MassProton); - auto lambda = ROOT::Math::PtEtaPhiMVector(tX.lambdaPt(), tX.lambdaEta(), tX.lambdaPhi(), tX.lambdaMass()); - auto proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); - auto lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + if (doMixLeg1 && nFill1 > 0) { + for (auto const& m : matches1) { + auto tX = V0sMC.iteratorAt(static_cast(m.rowIndex)); + + if (!selectionV0MC(tX)) + continue; + if (!checkKinematicsMC(t1, tX)) + continue; + if (tX.globalIndex() == t1.globalIndex()) + continue; + if (tX.globalIndex() == t2.globalIndex()) + continue; + if (hasSharedDaughtersMC(tX, t1)) + continue; + if (hasSharedDaughtersMC(tX, t2)) + continue; + fillReplacementControlMap(mcacc::v0Status(tX), mcacc::v0Status(t2), 1, false, + ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), mcacc::lamMass(tX)), + wSE); + + auto pX = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tX), mcacc::prEta(tX), mcacc::prPhi(tX), + o2::constants::physics::MassProton); + auto lX = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tX), mcacc::lamEta(tX), mcacc::lamPhi(tX), + mcacc::lamMass(tX)); + auto p2 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t2), mcacc::prEta(t2), mcacc::prPhi(t2), + o2::constants::physics::MassProton); + auto l2 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t2), mcacc::lamEta(t2), mcacc::lamPhi(t2), + mcacc::lamMass(t2)); + + // const int ptype = pairTypeCode(mcacc::v0Status(tX), mcacc::v0Status(t2)); + const float meWeight = wSE; + const float dPhi = deltaPhiMinusPiToPi((float)lX.Phi(), (float)l2.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + fillHistograms(mcacc::v0Status(tX), mcacc::v0Status(t2), + lX, l2, pX, p2, + 1, meWeight, 1); + } + } + if (doMixLeg2 && nFill2 > 0) { + for (auto const& m : matches2) { + auto tY = V0sMC.iteratorAt(static_cast(m.rowIndex)); - const float dPhi = std::fabs(RecoDecay::constrainAngle(lambda.Phi() - lambda2.Phi(), 0.0F, harmonicDphi)); - histos.fill(HIST("deltaPhiMix"), dPhi, wBase); - fillHistograms(tX.v0Status(), t2.v0Status(), lambda, lambda2, proton, proton2, 1, wBase); + if (!selectionV0MC(tY)) + continue; + if (!checkKinematicsMC(t2, tY)) + continue; + if (tY.globalIndex() == t2.globalIndex()) + continue; + if (tY.globalIndex() == t1.globalIndex()) + continue; + if (hasSharedDaughtersMC(tY, t1)) + continue; + if (hasSharedDaughtersMC(tY, t2)) + continue; + fillReplacementControlMap(mcacc::v0Status(t1), mcacc::v0Status(tY), 2, false, + ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tY), mcacc::lamEta(tY), mcacc::lamPhi(tY), mcacc::lamMass(tY)), + wSE); + + auto p1 = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(t1), mcacc::prEta(t1), mcacc::prPhi(t1), + o2::constants::physics::MassProton); + auto l1 = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(t1), mcacc::lamEta(t1), mcacc::lamPhi(t1), + mcacc::lamMass(t1)); + auto pY = ROOT::Math::PtEtaPhiMVector(mcacc::prPt(tY), mcacc::prEta(tY), mcacc::prPhi(tY), + o2::constants::physics::MassProton); + auto lY = ROOT::Math::PtEtaPhiMVector(mcacc::lamPt(tY), mcacc::lamEta(tY), mcacc::lamPhi(tY), + mcacc::lamMass(tY)); + + // const int ptype = pairTypeCode(mcacc::v0Status(t1), mcacc::v0Status(tY)); + const float meWeight = wSE; + const float dPhi = deltaPhiMinusPiToPi((float)l1.Phi(), (float)lY.Phi()); + histos.fill(HIST("deltaPhiMix"), dPhi, wSE); + fillHistograms(mcacc::v0Status(t1), mcacc::v0Status(tY), + l1, lY, p1, pY, + 1, meWeight, 2); + } } } } } - PROCESS_SWITCH(lambdaspincorrderived, processMEV4, "Process data ME (5d buffer)", false); + PROCESS_SWITCH(lambdaspincorrderived, processMCMEV6, "Process MC ME v6 with radius buffer", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index bd9fa236ca6..2085067c176 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -9,6 +9,9 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "PWGLF/DataModel/LFNonPromptCascadeTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" @@ -24,7 +27,6 @@ #include "DCAFitter/DCAFitterN.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/Propagator.h" #include "DetectorsVertexing/PVertexer.h" #include "Framework/ASoA.h" @@ -32,7 +34,11 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "MathUtils/BetheBlochAleph.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/Vertex.h" #include "Math/Vector4D.h" @@ -41,16 +47,12 @@ #include "TParticlePDG.h" #include "TTree.h" +#include #include +#include #include #include #include -// #include "PWGHF/Core/PDG.h" -#include "PWGLF/DataModel/LFNonPromptCascadeTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" using namespace o2; using namespace o2::framework; @@ -175,18 +177,22 @@ std::vector gCandidatesNT; } // namespace struct NonPromptCascadeTask { - Produces NPCTable; Produces NPCTableMC; Produces NPCTableNT; Produces NPCTableMCNT; Produces NPCTableGen; + // + Produces NPCollsTable; + Produces NPMCNTable; + Produces NPRecoCandTable; using TracksExtData = soa::Join; using TracksExtMC = soa::Join; using CollisionCandidatesRun3 = soa::Join; using CollisionCandidatesRun3MC = soa::Join; using TracksWithLabel = soa::Join; + using TracksWithSel = soa::Join; Preslice perCollision = aod::track::collisionId; Preslice perCollisionMC = aod::track::collisionId; @@ -215,6 +221,7 @@ struct NonPromptCascadeTask { Configurable cfgMaxMult{"cfgMaxMult", 8000.f, "Upper range of multiplicty histo"}; Configurable cfgMaxMultFV0{"cfgMaxMultFV0", 10000.f, "Upper range of multiplicty FV0 histo"}; Configurable cfgPtEdgesdNdeta{"ptEdges", "0,0.2,0.4,0.6,0.8,1,1.2,1.6,2.0,2.4,2.8,3.2,3.6,4,4.5,5,5.5,6,7,8,10", "Pt bin edges (comma-separated)"}; + Configurable cfgDownscaleMB{"cfgDownscaleMB", 1, "Downscaling for pile up study sample"}; Zorro mZorro; OutputObj mZorroSummary{"ZorroSummary"}; @@ -227,6 +234,7 @@ struct NonPromptCascadeTask { std::array mProcessCounter = {0, 0}; // {Tracked, All} std::map mToiMap; // + Service pdgDB; HistogramRegistry mRegistryMults{"Multhistos"}; HistogramRegistry mRegistrydNdeta{"dNdetahistos"}; @@ -315,9 +323,10 @@ struct NonPromptCascadeTask { AxisSpec centAxisFV0{centBinning, "Centrality FV0 (%)"}; AxisSpec trackAxisMC{trackBinning, "NTracks MC"}; AxisSpec trackAxis{trackBinning, "NTracks Global Reco"}; + AxisSpec numContribAxis{trackBinning, "Num of Contrib"}; AxisSpec runsAxis{runsBinning, "Run Number"}; - mRegistryMults.add("hCentMultsRuns", "hCentMultsRuns", HistType::kTHnSparseF, {centAxisFT0M, multAxis, centAxisFV0, multAxisFV0, nTracksAxis, runsAxis}); + mRegistryMults.add("hCentMultsRuns", "hCentMultsRuns", HistType::kTHnSparseF, {centAxisFT0M, multAxis, numContribAxis, nTracksAxis, runsAxis}); // // dN/deta // @@ -411,11 +420,10 @@ struct NonPromptCascadeTask { for (const auto& coll : collisions) { float centFT0M = coll.centFT0M(); float multFT0M = coll.multFT0M(); - float centFV0A = coll.centFV0A(); - float multFV0A = coll.multFV0A(); float multNTracks = coll.multNTracksGlobal(); - float run = mRunNumber; - mRegistryMults.fill(HIST("hCentMultsRuns"), centFT0M, multFT0M, centFV0A, multFV0A, multNTracks, run); + float runNumber = mRunNumber; + float numContrib = coll.numContrib(); + mRegistryMults.fill(HIST("hCentMultsRuns"), centFT0M, multFT0M, numContrib, multNTracks, runNumber); } }; @@ -729,7 +737,7 @@ struct NonPromptCascadeTask { fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates); fillMCtable(mcParticles, collisions, gCandidates); } - PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesMC, "process cascades from strangeness tracking: MC analysis", true); + PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesMC, "process cascades from strangeness tracking: MC analysis", false); void processCascadesMC(CollisionCandidatesRun3MC const& collisions, aod::Cascades const& cascades, aod::V0s const& /*v0s*/, TracksExtMC const& tracks, @@ -737,7 +745,7 @@ struct NonPromptCascadeTask { { fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT); fillMCtable(mcParticles, collisions, gCandidatesNT); - fillMultHistos(collisions); + // fillMultHistos(collisions); } PROCESS_SWITCH(NonPromptCascadeTask, processCascadesMC, "process cascades: MC analysis", false); @@ -788,7 +796,7 @@ struct NonPromptCascadeTask { zorroAccounting(collisions); fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT); fillDataTable(gCandidatesNT); - fillMultHistos(collisions); + // fillMultHistos(collisions); } PROCESS_SWITCH(NonPromptCascadeTask, processCascadesData, "process cascades: Data analysis", false); @@ -808,7 +816,7 @@ struct NonPromptCascadeTask { std::vector mcMult(mcCollisions.size(), 0); for (auto const& mcp : mcParticles) { int mcid = mcp.mcCollisionId(); - if (mcid < 0 || mcid >= (int)mcMult.size()) + if (mcid < 0 || static_cast(mcid) >= mcMult.size()) continue; // apply your primary/eta/charge definition here @@ -817,8 +825,8 @@ struct NonPromptCascadeTask { if (std::abs(mcp.eta()) > 0.5f) continue; int q = 0; - if (auto pdg = TDatabasePDG::Instance()->GetParticle(mcp.pdgCode())) { - q = int(std::round(pdg->Charge() / 3.0)); + if (auto pdg = pdgDB->GetParticle(mcp.pdgCode())) { + q = static_cast(std::round(pdg->Charge() / 3.0)); } if (q == 0) continue; @@ -833,14 +841,14 @@ struct NonPromptCascadeTask { // ------------------------------------------------------------ int maxCollRowId = -1; for (auto const& trk : tracks) { - maxCollRowId = std::max(maxCollRowId, (int)trk.collisionId()); + maxCollRowId = std::max(maxCollRowId, static_cast(trk.collisionId())); } std::vector collRowIdToDense(maxCollRowId + 1, -1); int dense = 0; for (auto const& col : colls) { const int collRowId = col.globalIndex(); // row id in aod::Collisions - if (collRowId >= 0 && collRowId < (int)collRowIdToDense.size()) { + if (collRowId >= 0 && static_cast(collRowId) < collRowIdToDense.size()) { collRowIdToDense[collRowId] = dense; } ++dense; @@ -855,7 +863,7 @@ struct NonPromptCascadeTask { continue; } const int collRowId = trk.collisionId(); - if (collRowId < 0 || collRowId >= (int)collRowIdToDense.size()) { + if (collRowId < 0 || static_cast(collRowId) >= collRowIdToDense.size()) { continue; } const int dIdx = collRowIdToDense[collRowId]; @@ -885,7 +893,7 @@ struct NonPromptCascadeTask { // Map track's collision row id -> dense colls index const int collRowId = trk.collisionId(); - if (collRowId < 0 || collRowId >= (int)collRowIdToDense.size()) { + if (collRowId < 0 || static_cast(collRowId) >= collRowIdToDense.size()) { continue; } const int dIdx = collRowIdToDense[collRowId]; @@ -898,14 +906,14 @@ struct NonPromptCascadeTask { // MC collision id (row index in aod::McCollisions) const int mcCollId = col.mcCollisionId(); - if (mcCollId < 0 || mcCollId >= (int)mcCollisions.size()) { + if (mcCollId < 0 || static_cast(mcCollId) >= mcCollisions.size()) { continue; } mcReconstructed[mcCollId] = 1; // MC particle id (row index in aod::McParticles) const int mcPid = trk.mcParticleId(); - if (mcPid < 0 || mcPid >= (int)mcParticles.size()) { + if (mcPid < 0 || static_cast(mcPid) >= mcParticles.size()) { continue; } @@ -928,8 +936,8 @@ struct NonPromptCascadeTask { } int q = 0; - if (auto pdgEntry = TDatabasePDG::Instance()->GetParticle(mcPar.pdgCode())) { - q = int(std::round(pdgEntry->Charge() / 3.0)); + if (auto pdgEntry = pdgDB->GetParticle(mcPar.pdgCode())) { + q = static_cast(std::round(pdgEntry->Charge() / 3.0)); } if (q == 0) { continue; @@ -944,33 +952,111 @@ struct NonPromptCascadeTask { const float ptMC = mcPar.pt(); mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRM"), mult, multReco, ptMC, ptReco); + NPMCNTable(ptMC, ptReco, mult, multReco); } // ------------------------------------------------------------ // MC particles with no reco track (iterate by row index) // ------------------------------------------------------------ - for (int pid = 0; pid < (int)mcParticles.size(); ++pid) { + for (int pid = 0; pid < static_cast(mcParticles.size()); ++pid) { if (!isReco[pid]) { auto mcp = mcParticles.rawIteratorAt(pid); mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoTrk"), isRecoMult[pid], mcp.pt()); + NPMCNTable(mcp.pt(), -1, isRecoMult[pid], -1); } } // ------------------------------------------------------------ // Unreconstructed MC collisions (iterate by row index) // ------------------------------------------------------------ - for (int mcid = 0; mcid < (int)mcCollisions.size(); ++mcid) { + for (int mcid = 0; mcid < static_cast(mcCollisions.size()); ++mcid) { if (!mcReconstructed[mcid]) { std::vector mcptvec; const int mult = mcMult[mcid]; for (auto const& pt : mcptvec) { mRegistrydNdeta.fill(HIST("hdNdetaRM/hdNdetaRMNotInRecoCol"), mult, pt); + NPMCNTable(pt, -2, mult, -2); } } } } PROCESS_SWITCH(NonPromptCascadeTask, processdNdetaMC, "process mc dN/deta", false); + // + void processdNdeta(CollisionCandidatesRun3 const& collisions, TracksWithSel const& tracks) + { + int ds = 1; + uint32_t orbitO = 0; + bool writeFlag = 0; + for (const auto& coll : collisions) { + auto bc = coll.template bc_as(); + uint64_t globalBC = bc.globalBC(); + uint32_t orbit = globalBC / 3564; + if (orbitO != orbit) { + orbitO = orbit; + if ((ds % cfgDownscaleMB) == 0) { + writeFlag = 1; + } else { + writeFlag = 0; + } + ds++; + } + if (writeFlag) { + if (mRunNumber != bc.runNumber()) { + mRunNumber = bc.runNumber(); + } + NPCollsTable(mRunNumber, + coll.bc().globalBC(), + coll.numContrib(), + coll.multNTracksGlobal(), + coll.centFT0M(), + coll.multFT0M()); + + auto collIdx = NPCollsTable.lastIndex(); + auto tracksThisColl = tracks.sliceBy(perCollision, coll.globalIndex()); + for (auto const& track : tracksThisColl) { + if (std::fabs(track.eta()) < 0.8 && track.tpcNClsFound() >= 80 && track.tpcNClsCrossedRows() >= 100) { + if (track.isGlobalTrack()) { + // mults.multGlobalTracks++; + NPRecoCandTable(collIdx, track.pt()); + } + } + } + } + } + } + PROCESS_SWITCH(NonPromptCascadeTask, processdNdeta, "process dN/deta", false); + + void processPileUp(CollisionCandidatesRun3 const& collisions, aod::BCsWithTimestamps const&) + { + // std::cout << "Processing pile up" << std::endl; + int ds = 1; + uint32_t orbitO = 0; + bool writeFlag = 0; + for (const auto& coll : collisions) { + auto bc = coll.template bc_as(); + uint64_t globalBC = bc.globalBC(); + uint32_t orbit = globalBC / 3564; + if (orbitO != orbit) { + orbitO = orbit; + if ((ds % cfgDownscaleMB) == 0) { + writeFlag = 1; + } else { + writeFlag = 0; + } + ds++; + } + if (writeFlag) { + if (mRunNumber != bc.runNumber()) { + mRunNumber = bc.runNumber(); + } + float centFT0M = coll.centFT0M(); + float multFT0M = coll.multFT0M(); + NPCollsTable(mRunNumber, globalBC, coll.numContrib(), coll.multNTracksGlobal(), centFT0M, multFT0M); + } + } + }; + PROCESS_SWITCH(NonPromptCascadeTask, processPileUp, "pile up studies", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index bfa459f6502..30cacfa6002 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -18,6 +18,7 @@ #include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/inelGt.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TableHelper.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -37,7 +38,10 @@ #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" +#include +#include #include #include @@ -59,11 +63,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -71,27 +77,39 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -static constexpr std::array phiMassRegionLabels{"Signal", "Sideband"}; +enum AnalysisMode { + kOldNormalization = 0, + kMassvsMass, + kDeltaYvsDeltaPhi +}; enum ParticleOfInterest { Phi = 0, K0S, - PionTPC, - PionTPCTOF + Pion, + /*PionTPC, + PionTPCTOF*/ + ParticleOfInterestSize }; -static constexpr std::array particleOfInterestLabels{"Phi", "K0S", "PionTPC", "PionTPCTOF"}; - /* #define LIST_OF_PARTICLES_OF_INTEREST \ X(Phi) \ X(K0S) \ - X(PionTPC) \ - X(PionTPCTOF) + X(Pion) \ + //X(PionTPC) \ + //X(PionTPCTOF) enum ParticleOfInterest { #define X(name) name, LIST_OF_PARTICLES_OF_INTEREST +#undef X + ParticleOfInterestSize +}; + +static constexpr std::array particleOfInterestLabels{ +#define X(name) #name, + LIST_OF_PARTICLES_OF_INTEREST #undef X }; @@ -132,22 +150,14 @@ struct BoundEfficiencyMap { } }; -/* -struct AnalysisRegion { - std::string suffix; - float minMass; - float maxMass; -}; -*/ - struct PhiStrangenessCorrelation { HistogramRegistry histos{"phiStrangenessCorrelation", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for selection type - Configurable selectionType{"selectionType", 1, "Selection type: 0 - default selection only, 1 - default + phi meson selection"}; + Configurable eventSelectionType{"eventSelectionType", 0, "Event selection type: 0 - default selection only, 1 - default + phi meson selection"}; // Configurable for analysis mode - Configurable analysisMode{"analysisMode", 1, "Analysis mode: 0 - old method with online normalization, 1 - new method with correlations"}; + Configurable analysisMode{"analysisMode", kMassvsMass, "Analysis mode: 0 - old method with online normalization, 1 - new method with offline normlization, 2 - deltay vs deltaphi"}; // Configurable for event selection Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; // TO BE REMOVED @@ -155,63 +165,28 @@ struct PhiStrangenessCorrelation { // Configurable on multiplicity bins Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; - // Configurables for tracks selection + // Configurables on phi mass selection struct : ConfigurableGroup { - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; - Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; - Configurable cMinKaonPtcut{"cMinKaonPtcut", 0.15f, "Track minimum pt cut"}; - Configurable etaMax{"etaMax", 0.8f, "eta max"}; - Configurable pTToUseTOF{"pTToUseTOF", 0.5f, "pT above which use TOF"}; - Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0f, "Track DCAz cut to PV Maximum"}; - Configurable> cMaxDCArToPVPhi{"cMaxDCArToPVPhi", {0.004f, 0.013f, 1.0f}, "Track DCAr cut to PV for Phi"}; - - Configurable cfgIsTOFChecked{"cfgIsTOFChecked", true, "Is TOF checked in PID for pions"}; - Configurable> cMaxDCArToPVPion{"cMaxDCArToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAr cut to PV for Pions"}; - Configurable cfgIsDCAzParameterized{"cfgIsDCAzParameterized", false, "IsDCAzParameterized"}; - Configurable> cMaxDCAzToPVPion{"cMaxDCAzToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAz cut to PV for Pions"}; - - Configurable nSigmaCutTPCKa{"nSigmaCutTPCKa", 2.0f, "Value of the TPC Nsigma cut for Kaons"}; - Configurable nSigmaCutCombinedKa{"nSigmaCutCombinedKa", 2.0f, "Value of the TPC and TOF Nsigma cut for Kaons"}; - - Configurable nSigmaCutTPCPrimPion{"nSigmaCutTPCPrimPion", 2.0f, "Value of the TPC Nsigma cut for primary Pions"}; - Configurable nSigmaCutTPCSecPion{"nSigmaCutTPCSecPion", 4.0f, "Value of the TPC Nsigma cut for secondary Pions"}; - Configurable nSigmaCutCombinedPi{"nSigmaCutCombinedPi", 2.0f, "Value of the TPC and TOF Nsigma cut for Pions"}; - Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; - - Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "min number of TPC crossed rows"}; - Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; - Configurable minITSnCls{"minITSnCls", 4, "min number of ITS clusters"}; - Configurable maxChi2ITS{"maxChi2ITS", 36.0f, "max chi2 per cluster ITS"}; - } trackConfigs; - - // Configurables on phi selection - struct : ConfigurableGroup { - Configurable minPhiPt{"minPhiPt", 0.4f, "Minimum pT for Phi candidates"}; Configurable> rangeMPhiSignal{"rangeMPhiSignal", {1.0095f, 1.029f}, "Phi mass range for signal extraction"}; Configurable> rangeMPhiSideband{"rangeMPhiSideband", {1.1f, 1.2f}, "Phi mass range for sideband extraction"}; } phiConfigs; - // Configurables on phi pT bins - Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; - - // Configurables for V0 selection + // Configurables for K0s selection struct : ConfigurableGroup { - Configurable v0SettingCosPA{"v0SettingCosPA", 0.98f, "V0 CosPA"}; - Configurable v0SettingRadius{"v0SettingRadius", 0.5f, "v0radius"}; - Configurable v0SettingDCAV0Dau{"v0SettingDCAV0Dau", 1.0f, "DCA V0 Daughters"}; - Configurable v0SettingDCAPosToPV{"v0SettingDCAPosToPV", 0.1f, "DCA Pos To PV"}; - Configurable v0SettingDCANegToPV{"v0SettingDCANegToPV", 0.1f, "DCA Neg To PV"}; - Configurable v0SettingMinPt{"v0SettingMinPt", 0.1f, "V0 min pt"}; + Configurable selectK0sInSigRegion{"selectK0sInSigRegion", false, "Select K0s candidates in signal region"}; + Configurable> rangeMK0sSignal{"rangeMK0sSignal", {0.47f, 0.53f}, "K0S mass range for signal extraction"}; + } k0sConfigs; - Configurable cfgFurtherV0Selection{"cfgFurtherV0Selection", false, "Further V0 selection"}; - Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0s(cm)"}; - Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "parameter Armenteros Cut"}; - Configurable v0rejK0s{"v0rejK0s", 0.005f, "V0 rej K0s"}; + // Configurables for Pions selection + struct : ConfigurableGroup { + Configurable selectPionInSigRegion{"selectPionInSigRegion", false, "Select Pion candidates in signal region"}; + Configurable pidTPCMax{"pidTPCMax", 2.0f, "Maximum nSigma TPC"}; + Configurable pidTOFMax{"pidTOFMax", 2.0f, "Maximum nSigma TOF"}; + Configurable tofPIDThreshold{"tofPIDThreshold", 0.5f, "Minimum pT after which TOF PID is applicable"}; + } pionConfigs; - Configurable lowMK0S{"lowMK0S", 0.48f, "Lower limit on K0Short mass"}; - Configurable upMK0S{"upMK0S", 0.52f, "Upper limit on K0Short mass"}; - } v0Configs; + // Configurables on phi pT bins + Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; // Configurable on K0S pT bins Configurable> binspTK0S{"binspTK0S", {0.1, 0.5, 0.8, 1.2, 1.6, 2.0, 2.5, 3.0, 4.0, 6.0}, "pT bin limits for K0S"}; @@ -236,57 +211,55 @@ struct PhiStrangenessCorrelation { // Configurables for CCDB Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; - Configurable ccdbEfficiencyPath{"ccdbEfficiencyPath", "Users/s/scannito/Efficiencies", "Correction path to file"}; + Configurable ccdbEfficiencyPath{"ccdbEfficiencyPath", "Users/s/scannito/Efficiencies/h3EffMap", "Correction path to file"}; - // Constants - double massPi = o2::constants::physics::MassPiPlus; - double massK0S = o2::constants::physics::MassK0Short; - double massLambda = o2::constants::physics::MassLambda0; + // Configurables for minimum pt selection in McGen + struct : ConfigurableGroup { + Configurable minPhiPt{"minPhiPt", 0.4f, "Minimum pT for Phi candidates"}; + Configurable v0SettingMinPt{"v0SettingMinPt", 0.1f, "V0 min pt"}; + Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; + } minPtMcGenConfigs; // Filter on phi selected collisions - Filter collisionFilter = aod::lf_selection_phi_collision::phimesonSel == true; - - // Defining filters on V0s (cannot filter on dynamic columns) - Filter v0PreFilter = (nabs(aod::v0data::dcapostopv) > v0Configs.v0SettingDCAPosToPV && nabs(aod::v0data::dcanegtopv) > v0Configs.v0SettingDCANegToPV && aod::v0data::dcaV0daughters < v0Configs.v0SettingDCAV0Dau); + Filter collisionFilter = (eventSelectionType == 0 && aod::lf_selection_event::defaultSel == true) || + (eventSelectionType == 1 && aod::lf_selection_event::defaultSel == true && aod::lf_selection_event::phimesonSel == true); // Defining the type of the collisions for data and MC - using SelCollisions = soa::Filtered>; - using SimCollisions = soa::Join; - using MCCollisions = soa::Filtered>; + using SelCollisions = soa::Filtered>; + using SimCollisions = soa::Filtered>; + using MCCollisions = soa::Filtered>; - // Defining the type of the V0s and corresponding daughter tracks for data and MC - using FullV0s = soa::Filtered; - using FullMCV0s = soa::Join; + // Slice cache and Preslices for table slicing + SliceCache cache; - using V0DauTracks = soa::Join; - using V0DauMCTracks = soa::Join; + struct : PresliceGroup { + Preslice phiCandDataPerCollision = aod::lf_selection_phi_candidate::collisionId; + // PresliceUnsorted phiCandMcRecoPerCollision = aod::lf_selection_phi_candidate::collisionId; + Preslice phiCandMcRecoPerCollision = aod::lf_selection_phi_candidate::collisionId; - // Defining the type of the tracks for data and MC - using FullTracks = soa::Join; - using FullMCTracks = soa::Join; + Preslice k0sDataPerCollision = aod::v0::collisionId; + Preslice k0sMcRecoPerCollision = aod::v0::collisionId; - // using FilteredTracks = soa::Filtered; - // using FilteredMCTracks = soa::Filtered; + Preslice pionTrackDataPerCollision = aod::track::collisionId; + Preslice pionTrackMcRecoPerCollision = aod::track::collisionId; - // Preslice for manual slicing - struct : PresliceGroup { - PresliceUnsorted collPerMCCollision = aod::mccollisionlabel::mcCollisionId; - Preslice phiCandPerCollision = aod::lf_selection_phi_candidate::collisionId; - Preslice v0PerCollision = aod::v0::collisionId; - Preslice trackPerCollision = aod::track::collisionId; - // Preslice mcPartPerMCCollision = aod::mcparticle::mcCollisionId; + Preslice mcPartPerMcCollision = aod::mcparticle::mcCollisionId; } preslices; // Necessary service to retrieve efficiency maps from CCDB Service ccdb; - // Efficiency maps - /*std::shared_ptr effMapPhi = nullptr; - std::shared_ptr effMapK0S = nullptr; - std::shared_ptr effMapPionTPC = nullptr; - std::shared_ptr effMapPionTPCTOF = nullptr;*/ + std::array, ParticleOfInterestSize> effMaps{}; + + // Binning policy and axes for mixed event + ConfigurableAxis axisVertexMixing{"axisVertexMixing", {20, -10, 10}, "Z vertex axis binning for mixing"}; + ConfigurableAxis axisCentralityMixing{"axisCentralityMixing", {20, 0, 100}, "Multiplicity percentil binning for mixing"}; + + using BinningTypeVertexCent = ColumnBinningPolicy; + BinningTypeVertexCent binningOnVertexAndCent{{axisVertexMixing, axisCentralityMixing}, true}; - std::array, 4> effMaps{}; + static constexpr std::array phiMassRegionLabels{"Signal", "Sideband"}; + static constexpr std::array particleOfInterestLabels{"Phi", "K0S", "Pion" /*"PionTPC", "PionTPCTOF"*/}; void init(InitContext&) { @@ -299,20 +272,30 @@ struct PhiStrangenessCorrelation { AxisSpec massPhiAxis = {200, 0.9f, 1.2f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec pTPhiAxis = {120, 0.0f, 12.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec binnedpTPhiAxis{(std::vector)binspTPhi, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec massK0SAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec pTK0SAxis = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec binnedpTK0SAxis{(std::vector)binspTK0S, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaPiAxis = {100, -10.0f, 10.0f, "N#sigma #pi"}; AxisSpec pTPiAxis = {50, 0.0f, 5.0f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec binnedpTPiAxis{(std::vector)binspTPi, "#it{p}_{T} (GeV/#it{c})"}; histos.add("phi/h3PhiData", "Invariant mass of Phi in Data", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + + histos.add("phiK0S/h6PhiK0SData", "Invariant mass of Phi vs Invariant mass of K0Short in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, massPhiAxis, massK0SAxis}); + histos.add("phiPi/h6PhiPiTPCData", "Invariant mass of Phi vs nSigmaTPC Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + histos.add("phiPi/h6PhiPiTOFData", "Invariant mass of Phi vs nSigmaTOF Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + + histos.add("phiK0S/h6PhiK0SDataME", "Invariant mass of Phi vs Invariant mass of K0Short in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, massPhiAxis, massK0SAxis}); + histos.add("phiPi/h6PhiPiTPCDataME", "Invariant mass of Phi vs nSigmaTPC Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + histos.add("phiPi/h6PhiPiTOFDataME", "Invariant mass of Phi vs nSigmaTOF Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, massPhiAxis, nSigmaPiAxis}); + for (const auto& label : phiMassRegionLabels) { - histos.add(fmt::format("phiK0S/h5PhiK0SData2PartCorr{}", label).c_str(), "Deltay vs deltaphi for Phi and K0Short in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, deltaphiAxis}); - histos.add(fmt::format("phiPi/h5PhiPiData2PartCorr{}", label).c_str(), "Deltay vs deltaphi for Phi and Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, deltaphiAxis}); - } + histos.add(fmt::format("phiK0S/h5PhiK0SData{}", label).c_str(), "Deltay vs deltaphi for Phi and K0Short in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, deltaphiAxis}); + histos.add(fmt::format("phiPi/h5PhiPiData{}", label).c_str(), "Deltay vs deltaphi for Phi and Pion in Data", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, deltaphiAxis}); - // histos.add("phiK0S/h5PhiK0SDataNewProc", "2D Invariant mass of Phi and K0Short in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, massPhiAxis}); - // histos.add("phiPi/h5PhiPiTPCDataNewProc", "Phi Invariant mass vs Pion nSigma TPC in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); - // histos.add("phiPi/h5PhiPiTOFDataNewProc", "Phi Invariant mass vs Pion nSigma TOF in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + histos.add(fmt::format("phiK0S/h5PhiK0SDataME{}", label).c_str(), "Deltay vs deltaphi for Phi and K0Short in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTK0SAxis, deltayAxis, deltaphiAxis}); + histos.add(fmt::format("phiPi/h5PhiPiDataME{}", label).c_str(), "Deltay vs deltaphi for Phi and Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, deltaphiAxis}); + } histos.add("event/hRecoMCMultiplicityPercent", "RecoMC Multiplicity Percentile", kTH1F, {binnedmultAxis}); histos.add("event/h2RecoMCVertexZvsMult", "RecoMC Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); @@ -333,10 +316,6 @@ struct PhiStrangenessCorrelation { histos.add("pi/h3PiMCGen", "Pion in MC Gen", kTH3F, {binnedmultAxis, binnedpTPiAxis, yAxis}); histos.add("pi/h4PiMCGenAssocReco", "Pion in MC Gen Assoc Reco", kTHnSparseF, {vertexZAxis, binnedmultAxis, binnedpTPiAxis, yAxis}); - histos.add("pi/h2RecMCDCAxyPrimPi", "Dcaxy distribution vs pt for Primary Pions", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - histos.add("pi/h2RecMCDCAxySecWeakDecayPi", "Dcaz distribution vs pt for Secondary Pions from Weak Decay", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - histos.add("pi/h2RecMCDCAxySecMaterialPi", "Dcaxy distribution vs pt for Secondary Pions from Material", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - // Load efficiency maps from CCDB if (applyEfficiency) { ccdb->setURL(ccdbUrl); @@ -344,9 +323,7 @@ struct PhiStrangenessCorrelation { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - // getEfficiencyMapsFromCCDB(); - - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < ParticleOfInterestSize; ++i) { loadEfficiencyMapFromCCDB(static_cast(i)); } } @@ -354,18 +331,12 @@ struct PhiStrangenessCorrelation { void loadEfficiencyMapFromCCDB(ParticleOfInterest poi) { - effMaps[poi] = std::shared_ptr(ccdb->get(fmt::format("{}/h3EffMap{}", ccdbEfficiencyPath.value, particleOfInterestLabels[poi]))); + effMaps[poi] = std::shared_ptr(ccdb->get(fmt::format("{}{}", ccdbEfficiencyPath.value, particleOfInterestLabels[poi]))); if (!effMaps[poi]) LOG(fatal) << "Could not load efficiency map for " << particleOfInterestLabels[poi] << "!"; LOG(info) << "Efficiency map for " << particleOfInterestLabels[poi] << " loaded from CCDB"; } - /* - void getEfficiencyMapsFromCCDB() - { - } - */ - // Compute weight based on efficiencies template float computeWeight(const BoundEffMaps&... boundEffMaps) @@ -378,323 +349,450 @@ struct PhiStrangenessCorrelation { return totalEfficiency <= 0.0f ? 1.0f : 1.0f / totalEfficiency; } - // Single track selection for strangeness sector - template - bool selectionTrackStrangeness(const T& track) + float getDeltaPhi(float phiTrigger, float phiAssociated) { - if (!track.hasTPC()) - return false; - if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) - return false; - if (track.tpcNClsCrossedRows() < trackConfigs.minNCrossedRowsTPC) - return false; - if (track.tpcChi2NCl() > trackConfigs.maxChi2TPC) - return false; - - if (std::abs(track.eta()) > trackConfigs.etaMax) - return false; - return true; + return RecoDecay::constrainAngle(phiTrigger - phiAssociated, -o2::constants::math::PIHalf); } - // V0 selection - template - bool selectionV0(const T1& v0, const T2& collision) + template + void processPhiK0SPionSE(TCollision const& collision, TPhiCands const& phiCandidates, TK0SCands const& k0sReduced, TPionCands const& pionTracks) { - const auto& posDaughterTrack = v0.template posTrack_as(); - const auto& negDaughterTrack = v0.template negTrack_as(); + float multiplicity = collision.centFT0M(); - if (!selectionTrackStrangeness(posDaughterTrack) || !selectionTrackStrangeness(negDaughterTrack)) - return false; + const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; - if constexpr (!isMC) { - if (std::abs(posDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) - return false; - if (std::abs(negDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) - return false; - } + const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + auto isK0sValid = [&](const auto& k0s) { + return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); + }; - if (v0.v0cosPA() < v0Configs.v0SettingCosPA) - return false; - if (v0.v0radius() < v0Configs.v0SettingRadius) - return false; - if (v0.pt() < v0Configs.v0SettingMinPt) - return false; - - if (v0Configs.cfgFurtherV0Selection) { - if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0S > v0Configs.ctauK0s) - return false; - if (v0.qtarm() < (v0Configs.paramArmenterosCut * std::abs(v0.alpha()))) - return false; - if (std::abs(v0.mLambda() - massLambda) < v0Configs.v0rejK0s) - return false; - } + const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi) && pionConfigs.selectPionInSigRegion; + const float& pidTPCMax = pionConfigs.pidTPCMax; + const float& pidTOFMax = pionConfigs.pidTOFMax; + const float& tofPIDThreshold = pionConfigs.tofPIDThreshold; - if (std::abs(v0.yK0Short()) > yConfigs.cfgYAcceptance) - return false; + auto isPionValid = [&](const auto& pion) { + return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); + }; - return true; - } + for (const auto& phiCand : phiCandidates) { + float weightPhi = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y())); - // Topological selection for pions - template - bool selectionPion(const T& track) - { - if (!track.isGlobalTrackWoDCA()) - return false; - - if (track.itsNCls() < trackConfigs.minITSnCls) - return false; - if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) - return false; - - if (track.pt() < trackConfigs.cMinPionPtcut) - return false; - - if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPVPion->at(0) + (trackConfigs.cMaxDCArToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCArToPVPion->at(2)))) - return false; - if (trackConfigs.cfgIsDCAzParameterized) { - if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVPion->at(0) + (trackConfigs.cMaxDCAzToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCAzToPVPion->at(2)))) - return false; - } else { - if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVcut) - return false; - } + histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); + + auto processCorrelations = [&](auto fillK0S, auto fillPion) { + // Loop over all reduced K0S candidates + for (const auto& k0s : k0sReduced) { + if (!isK0sValid(k0s)) + continue; + + float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); + fillK0S(k0s, weightPhiK0S); + } - if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.pTToUseTOF && !track.hasTOF()) - return false; + // Loop over all primary pion candidates + for (const auto& pionTrack : pionTracks) { + if (!isPionValid(pionTrack)) + continue; - if (analysisMode == 1) { - if (track.pt() < trackConfigs.pTToUseTOF && std::abs(track.tpcNSigmaPi()) >= trackConfigs.nSigmaCutTPCPrimPion) - return false; - if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.pTToUseTOF && (std::pow(track.tofNSigmaPi(), 2) + std::pow(track.tpcNSigmaPi(), 2)) >= std::pow(trackConfigs.nSigmaCutCombinedPi, 2)) - return false; + float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[Pion], multiplicity, pionTrack.pt(), pionTrack.y())); + fillPion(pionTrack, weightPhiPion); + } + }; + + if (analysisMode == kMassvsMass) { + auto k0sHistID = HIST("phiK0S/h6PhiK0SData"); + auto piTPCHistID = HIST("phiPi/h6PhiPiTPCData"); + auto piTOFHistID = HIST("phiPi/h6PhiPiTOFData"); + + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(k0sHistID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + }, + [&](const auto& pion, float w) { + histos.fill(piTPCHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + histos.fill(piTOFHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + }); + } else if (analysisMode == kDeltaYvsDeltaPhi) { + auto k0sHistID = std::make_tuple(HIST("phiK0S/h5PhiK0SDataSignal"), HIST("phiK0S/h5PhiK0SDataSideband")); + auto piHistID = std::make_tuple(HIST("phiPi/h5PhiPiDataSignal"), HIST("phiPi/h5PhiPiDataSideband")); + + static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + // auto k0sHistID = HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]); + // auto piHistID = HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]); + + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(std::get(k0sHistID), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + }, + [&](const auto& pion, float w) { + histos.fill(std::get(piHistID), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + }); + }); + } + + /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + // Loop over all reduced K0S candidates + for (const auto& k0s : k0sReduced) { + if (k0sConfigs.selectK0sInSigRegion) { + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + if (!k0s.inMassRegion(minMassK0s, maxMassK0s)) + continue; + } + + float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); + + histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); + } + + // Loop over all primary pion candidates + for (const auto& pionTrack : pionTracks) { + float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[Pion], multiplicity, pionTrack.pt(), pionTrack.y())); + + histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pionTrack.pt(), phiCand.y() - pionTrack.y(), getDeltaPhi(phiCand.phi(), pionTrack.phi()), weightPhiPion); + } + });*/ } + } - if (std::abs(track.rapidity(massPi)) > yConfigs.cfgYAcceptance) - return false; + // PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionSE, "Process function for Phi-K0S and Phi-Pion Deltay and Deltaphi 2D Correlations in SE", true); - return true; + void processPhiK0SPionSEDataLike(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced, aod::PionTracksData const& pionTracks) + { + processPhiK0SPionSE(collision, phiCandidates, k0sReduced, pionTracks); } - /* - void processPhiK0SPionDeltayDeltaphiData2D(SelCollisions::iterator const& collision, aod::PhimesonCandidates const& phiCandidates, FullTracks const& fullTracks, FullV0s const& V0s, V0DauTracks const&) + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionSEDataLike, "Process function for Phi-K0S and Phi-Pion 2D Correlations in Data or MC w/o PDG SE", true); + + void processPhiK0SPionSEMCWithPDG(SimCollisions::iterator const& collision, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced, aod::PionTracksMcReco const& pionTracks) { - float multiplicity = collision.centFT0M(); + processPhiK0SPionSE(collision, phiCandidates, k0sReduced, pionTracks); + } - std::vector analysisRegions = { - {"Signal", phiConfigs.rangeMPhiSignal.first, phiConfigs.rangeMPhiSignal.second}, - {"Sideband", phiConfigs.rangeMPhiSideband.first, phiConfigs.rangeMPhiSideband.second}}; + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionSEMCWithPDG, "Process function for Phi-K0S and Phi-Pion 2D Correlations in MC with PDG SE", true); - // Loop over all positive tracks - for (const auto& phiCand : phiCandidates) { - float weightPhi = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y())); + template + void processPhiK0SME(TCollisions const& collisions, TPhiCands const& phiCandidates, TK0SCands const& k0sReduced) + { + const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; - histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); + const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; - for (const auto& region : analysisRegions) { - if (!phiCand.inMassRegion(region.minMass, region.maxMass)) - continue; + auto isK0sValid = [&](const auto& k0s) { + return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); + }; - // V0 already reconstructed by the builder - for (const auto& v0 : V0s) { - // Cut on V0 dynamic columns - if (!selectionV0(v0, collision)) - continue; + auto tuplePhiK0S = std::make_tuple(phiCandidates, k0sReduced); + Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiK0S, &cache}; + + for (const auto& [c1, phiCands, c2, k0sRed] : pairPhiK0S) { - float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapK0S, multiplicity, v0.pt(), v0.yK0Short())); + float multiplicity = c1.centFT0M(); + + for (const auto& [phiCand, k0s] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, k0sRed))) { + if (!isK0sValid(k0s)) + continue; - histos.fill(HIST("phiK0S/h5PhiK0SData2PartCorr"), multiplicity, phiCand.pt(), v0.pt(), phiCand.y() - v0.yK0Short(), phiCand.phi() - v0.phi(), weightPhiK0S); + auto processCorrelations = [&](auto fillK0S) { + float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); + fillK0S(k0s, weightPhiK0S); + }; + + if (analysisMode == kMassvsMass) { + auto k0sHistID = HIST("phiK0S/h6PhiK0SDataME"); + + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(k0sHistID, multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), phiCand.m(), k0s.m(), w); + }); + } else if (analysisMode == kDeltaYvsDeltaPhi) { + auto k0sHistID = std::make_tuple(HIST("phiK0S/h5PhiK0SDataMESignal"), HIST("phiK0S/h5PhiK0SDataMESideband")); + + static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + processCorrelations( + [&](const auto& k0s, float w) { + histos.fill(std::get(k0sHistID), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), w); + }); + }); } - // Loop over all primary pion candidates - for (const auto& track : fullTracks) { - if (!selectionPion(track)) - continue; + /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; - float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - track.pt() < trackConfigs.pTToUseTOF ? BoundEfficiencyMap(effMapPionTPC, multiplicity, track.pt(), track.rapidity(massPi)) : BoundEfficiencyMap(effMapPionTPCTOF, multiplicity, track.pt(), track.rapidity(massPi))); + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; - histos.fill(HIST("phiPi/h5PhiPiData2PartCorr"), multiplicity, phiCand.pt(), track.pt(), phiCand.y() - track.rapidity(massPi), phiCand.phi() - track.phi(), weightPhiPion); - } + if (k0sConfigs.selectK0sInSigRegion) { + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + if (!k0s.inMassRegion(minMassK0s, maxMassK0s)) + return; + } + + float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); + + histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); + });*/ } } } - PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionDeltayDeltaphiData2D, "Process function for Phi-K0S and Phi-Pion Deltay and Deltaphi 2D Correlations in Data", true); - */ + // PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SME, "Process function for Phi-K0S and Deltay and Deltaphi 2D Correlations in Data ME", false); - void processPhiK0SPionDeltayDeltaphiData2D(SelCollisions::iterator const& collision, aod::PhimesonCandidates const& phiCandidates, FullTracks const& fullTracks, FullV0s const& V0s, V0DauTracks const&) + void processPhiK0SMEDataLike(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced) { - float multiplicity = collision.centFT0M(); + processPhiK0SME(collisions, phiCandidates, k0sReduced); + } - const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SMEDataLike, "Process function for Phi-K0S 2D Correlations in Data or MC w/o PDG ME", true); - // Loop over all positive tracks - for (const auto& phiCand : phiCandidates) { - float weightPhi = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y())); + void processPhiK0SMEMCWithPDG(SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced) + { + processPhiK0SME(collisions, phiCandidates, k0sReduced); + } - // float weightPhi = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y())); + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SMEMCWithPDG, "Process function for Phi-K0S 2D Correlations in MC with PDG ME", true); - histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); + template + void processPhiPionME(TCollisions const& collisions, TPhiCands const& phiCandidates, TPionCands const& pionTracks) + { + const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; - static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { - constexpr unsigned int i = i_idx.value; + const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi) && pionConfigs.selectPionInSigRegion; + const float& pidTPCMax = pionConfigs.pidTPCMax; + const float& pidTOFMax = pionConfigs.pidTOFMax; + const float& tofPIDThreshold = pionConfigs.tofPIDThreshold; - const auto& [minMass, maxMass] = phiMassRegions[i]; - if (!phiCand.inMassRegion(minMass, maxMass)) - return; + auto isPionValid = [&](const auto& pion) { + return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); + }; - // V0 already reconstructed by the builder - for (const auto& v0 : V0s) { - // Cut on V0 dynamic columns - if (!selectionV0(v0, collision)) - continue; + auto tuplePhiPion = std::make_tuple(phiCandidates, pionTracks); + Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; - float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMaps[K0S], multiplicity, v0.pt(), v0.yK0Short())); + for (const auto& [c1, phiCands, c2, piTracks] : pairPhiPion) { - /*float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapK0S, multiplicity, v0.pt(), v0.yK0Short()));*/ + float multiplicity = c1.centFT0M(); + + for (const auto& [phiCand, piTrack] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, piTracks))) { + if (!isPionValid(piTrack)) + continue; - histos.fill(HIST("phiK0S/h5PhiK0SData2PartCorr") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), v0.pt(), phiCand.y() - v0.yK0Short(), phiCand.phi() - v0.phi(), weightPhiK0S); + auto processCorrelations = [&](auto fillPion) { + float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), + BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); + fillPion(piTrack, weightPhiPion); + }; + + if (analysisMode == kMassvsMass) { + auto piTPCHistID = HIST("phiPi/h6PhiPiTPCDataME"); + auto piTOFHistID = HIST("phiPi/h6PhiPiTOFDataME"); + + processCorrelations( + [&](const auto& pion, float w) { + histos.fill(piTPCHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTPC(), w); + histos.fill(piTOFHistID, multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), phiCand.m(), pion.nSigmaTOF(), w); + }); + } else if (analysisMode == kDeltaYvsDeltaPhi) { + auto piHistID = std::make_tuple(HIST("phiPi/h5PhiPiDataMESignal"), HIST("phiPi/h5PhiPiDataMESideband")); + + static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; + + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; + + processCorrelations( + [&](const auto& pion, float w) { + histos.fill(std::get(piHistID), multiplicity, phiCand.pt(), pion.pt(), phiCand.y() - pion.y(), getDeltaPhi(phiCand.phi(), pion.phi()), w); + }); + }); } - // Loop over all primary pion candidates - for (const auto& track : fullTracks) { - if (!selectionPion(track)) - continue; + /*static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { + constexpr unsigned int i = i_idx.value; - auto Pion = track.pt() < trackConfigs.pTToUseTOF ? PionTPC : PionTPCTOF; + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) + return; float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMaps[Pion], multiplicity, track.pt(), track.rapidity(massPi))); + BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); + + histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), piTrack.pt(), phiCand.y() - piTrack.y(), getDeltaPhi(phiCand.phi(), piTrack.phi()), weightPhiPion); + });*/ + } + } + } - /*auto effMapPion = track.pt() < trackConfigs.pTToUseTOF ? effMapPionTPC : effMapPionTPCTOF; + // PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionME, "Process function for Phi-Pion Deltay and Deltaphi 2D Correlations in Data ME", false); - float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapPion, multiplicity, track.pt(), track.rapidity(massPi)));*/ + void processPhiPionMEDataLike(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::PionTracksData const& pionTracks) + { + processPhiPionME(collisions, phiCandidates, pionTracks); + } - histos.fill(HIST("phiPi/h5PhiPiData2PartCorr") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), track.pt(), phiCand.y() - track.rapidity(massPi), phiCand.phi() - track.phi(), weightPhiPion); - } - }); - } + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionMEDataLike, "Process function for Phi-Pion 2D Correlations in Data or MC w/o PDG ME", true); + + void processPhiPionMEMCWithPDG(SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::PionTracksMcReco const& pionTracks) + { + processPhiPionME(collisions, phiCandidates, pionTracks); } - PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionDeltayDeltaphiData2D, "Process function for Phi-K0S and Phi-Pion Deltay and Deltaphi 2D Correlations in Data", true); + PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionMEMCWithPDG, "Process function for Phi-Pion 2D Correlations in MC with PDG ME", true); - void processParticleEfficiency(MCCollisions::iterator const& mcCollision, SimCollisions const& collisions, FullMCTracks const& fullMCTracks, FullMCV0s const& V0s, V0DauMCTracks const&, aod::McParticles const& mcParticles, aod::PhimesonCandidates const& phiCandidates) + void processParticleEfficiency(MCCollisions const& mcCollisions, SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced, aod::PionTracksMcReco const& pionTracks, aod::McParticles const& mcParticles) { - uint16_t numberAssocColls{0}; - std::vector zVtxs; + const bool applyK0sMassCut = (analysisMode == kDeltaYvsDeltaPhi) && k0sConfigs.selectK0sInSigRegion; + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + auto isK0sValid = [&](const auto& k0s) { + return !applyK0sMassCut || k0s.inMassRegion(minMassK0s, maxMassK0s); + }; - const auto collsThisMCColl = collisions.sliceBy(preslices.collPerMCCollision, mcCollision.globalIndex()); + const bool applyPionNSigmaCut = (analysisMode == kDeltaYvsDeltaPhi) && pionConfigs.selectPionInSigRegion; + const float& pidTPCMax = pionConfigs.pidTPCMax; + const float& pidTOFMax = pionConfigs.pidTOFMax; + const float& tofPIDThreshold = pionConfigs.tofPIDThreshold; - for (const auto& collision : collsThisMCColl) { - histos.fill(HIST("event/hRecoMCMultiplicityPercent"), mcCollision.centFT0M()); - histos.fill(HIST("event/h2RecoMCVertexZvsMult"), collision.posZ(), mcCollision.centFT0M()); + auto isPionValid = [&](const auto& pion) { + return !applyPionNSigmaCut || pion.inNSigmaRegion(pidTPCMax, tofPIDThreshold, pidTOFMax); + }; - zVtxs.push_back(collision.posZ()); + std::unordered_map> collsGrouped; + collsGrouped.reserve(mcCollisions.size()); - if (selectionType == 0) { - const auto phiCandidatesThisColl = phiCandidates.sliceBy(preslices.phiCandPerCollision, collision.globalIndex()); - for (const auto& phiCand : phiCandidatesThisColl) { - histos.fill(HIST("phi/h4PhiMCReco"), collision.posZ(), mcCollision.centFT0M(), phiCand.pt(), phiCand.y()); - } - } + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) + continue; + const auto& mcCollision = collision.mcCollision_as(); + collsGrouped[mcCollision.globalIndex()].push_back(collision.globalIndex()); + } - const auto v0sThisColl = V0s.sliceBy(preslices.v0PerCollision, collision.globalIndex()); - const auto fullMCTracksThisColl = fullMCTracks.sliceBy(preslices.trackPerCollision, collision.globalIndex()); + std::vector zVtxs; + zVtxs.reserve(3); // Reasonable number of associated collisions to expect at most - for (const auto& v0 : v0sThisColl) { - if (!selectionV0(v0, collision)) - continue; + for (const auto& mcCollision : mcCollisions) { + uint16_t numberAssocColls{0}; + zVtxs.clear(); - if (!v0.has_mcParticle()) - continue; + // const auto& collIndexesThisMcColl = collsGrouped[mcCollision.globalIndex()]; + auto it = collsGrouped.find(mcCollision.globalIndex()); + if (it != collsGrouped.end()) { + const auto& collIndexesThisMcColl = it->second; - const auto& v0McParticle = mcParticles.rawIteratorAt(v0.mcParticleId()); - if (std::abs(v0McParticle.pdgCode()) != PDG_t::kK0Short || !v0McParticle.isPhysicalPrimary()) - continue; + for (const auto& collIndex : collIndexesThisMcColl) { + const auto& collision = collisions.rawIteratorAt(collIndex); - histos.fill(HIST("k0s/h4K0SMCReco"), collision.posZ(), mcCollision.centFT0M(), v0McParticle.pt(), v0McParticle.y()); - } + histos.fill(HIST("event/hRecoMCMultiplicityPercent"), mcCollision.centFT0M()); + histos.fill(HIST("event/h2RecoMCVertexZvsMult"), collision.posZ(), mcCollision.centFT0M()); - for (const auto& track : fullMCTracksThisColl) { - if (!selectionPion(track)) - continue; + zVtxs.push_back(collision.posZ()); - if (!track.has_mcParticle()) - continue; + if (eventSelectionType == 0) { + const auto phiCandidatesThisColl = phiCandidates.sliceBy(preslices.phiCandMcRecoPerCollision, collision.globalIndex()); + for (const auto& phiCand : phiCandidatesThisColl) { + histos.fill(HIST("phi/h4PhiMCReco"), collision.posZ(), mcCollision.centFT0M(), phiCand.pt(), phiCand.y()); + } + } - const auto& trackMcParticle = mcParticles.rawIteratorAt(track.mcParticleId()); - if (std::abs(trackMcParticle.pdgCode()) != PDG_t::kPiPlus) - continue; + const auto k0sThisColl = k0sReduced.sliceBy(preslices.k0sMcRecoPerCollision, collision.globalIndex()); + const auto pionTracksThisColl = pionTracks.sliceBy(preslices.pionTrackMcRecoPerCollision, collision.globalIndex()); - if (trackMcParticle.isPhysicalPrimary()) { - histos.fill(HIST("pi/h2RecMCDCAxyPrimPi"), track.pt(), track.dcaXY()); - } else { - if (trackMcParticle.getProcess() == TMCProcess::kPDecay) { // Selection of secondary pions from weak decay - histos.fill(HIST("pi/h2RecMCDCAxySecWeakDecayPi"), track.pt(), track.dcaXY()); - } else { // Selection of secondary pions from material interactions - histos.fill(HIST("pi/h2RecMCDCAxySecMaterialPi"), track.pt(), track.dcaXY()); + for (const auto& k0s : k0sThisColl) { + if (!isK0sValid(k0s)) + continue; + + histos.fill(HIST("k0s/h4K0SMCReco"), collision.posZ(), mcCollision.centFT0M(), k0s.pt(), k0s.y()); } - continue; - } - histos.fill(HIST("pi/h4PiMCReco"), collision.posZ(), mcCollision.centFT0M(), trackMcParticle.pt(), trackMcParticle.y()); - } + for (const auto& pionTrack : pionTracksThisColl) { + if (!isPionValid(pionTrack)) + continue; - numberAssocColls++; - } + histos.fill(HIST("pi/h4PiMCReco"), collision.posZ(), mcCollision.centFT0M(), pionTrack.pt(), pionTrack.y()); + } + + numberAssocColls++; + } + } - histos.fill(HIST("event/hGenMCMultiplicityPercent"), mcCollision.centFT0M()); + histos.fill(HIST("event/hGenMCMultiplicityPercent"), mcCollision.centFT0M()); - const bool hasAssoc = (numberAssocColls > 0); - const float zVtxRef = hasAssoc ? zVtxs[0] : 0.0f; + const bool hasAssoc = (numberAssocColls > 0); + const float zVtxRef = hasAssoc ? zVtxs[0] : 0.0f; - //////TOBECHANGED////// - if (hasAssoc) { - if (zVtxs.size() > 1) { - for (size_t i = 1; i < zVtxs.size(); ++i) { - histos.fill(HIST("event/hSplitVertexZ"), zVtxs[i] - zVtxRef); + //////TOBECHANGED////// + if (hasAssoc) { + if (zVtxs.size() > 1) { + for (size_t i = 1; i < zVtxs.size(); ++i) { + histos.fill(HIST("event/hSplitVertexZ"), zVtxs[i] - zVtxRef); + } } + + histos.fill(HIST("event/hGenMCAssocRecoMultiplicityPercent"), mcCollision.centFT0M()); + histos.fill(HIST("event/h2GenMCAssocRecoVertexZvsMult"), zVtxRef, mcCollision.centFT0M()); } + /////////////////////// - histos.fill(HIST("event/hGenMCAssocRecoMultiplicityPercent"), mcCollision.centFT0M()); - histos.fill(HIST("event/h2GenMCAssocRecoVertexZvsMult"), zVtxRef, mcCollision.centFT0M()); - } - /////////////////////// + const auto mcParticlesThisMcColl = mcParticles.sliceBy(preslices.mcPartPerMcCollision, mcCollision.globalIndex()); - auto inYAcceptance = [&](const auto& mcParticle) { - return std::abs(mcParticle.y()) <= yConfigs.cfgYAcceptance; - }; + auto inYAcceptance = [&](const auto& mcParticle) { + return std::abs(mcParticle.y()) <= yConfigs.cfgYAcceptance; + }; - auto fillGenHistos = [&](auto h3Key, auto h4Key, const auto& mcParticle) { - histos.fill(h3Key, mcCollision.centFT0M(), mcParticle.pt(), mcParticle.y()); - if (hasAssoc) - histos.fill(h4Key, zVtxRef, mcCollision.centFT0M(), mcParticle.pt(), mcParticle.y()); - }; + auto fillGenHistos = [&](auto h3Key, auto h4Key, const auto& mcParticle) { + histos.fill(h3Key, mcCollision.centFT0M(), mcParticle.pt(), mcParticle.y()); + if (hasAssoc) + histos.fill(h4Key, zVtxRef, mcCollision.centFT0M(), mcParticle.pt(), mcParticle.y()); + }; - for (const auto& mcParticle : mcParticles /*| std::views::filter(inYAcceptance)*/) { - if (!inYAcceptance(mcParticle)) - continue; + for (const auto& mcParticle : mcParticlesThisMcColl /*| std::views::filter(inYAcceptance)*/) { + if (!inYAcceptance(mcParticle)) + continue; - switch (std::abs(mcParticle.pdgCode())) { - case o2::constants::physics::Pdg::kPhi: - if (selectionType == 0 && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= phiConfigs.minPhiPt) - fillGenHistos(HIST("phi/h3PhiMCGen"), HIST("phi/h4PhiMCGenAssocReco"), mcParticle); - break; - case PDG_t::kK0Short: - if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= v0Configs.v0SettingMinPt) - fillGenHistos(HIST("k0s/h3K0SMCGen"), HIST("k0s/h4K0SMCGenAssocReco"), mcParticle); - break; - case PDG_t::kPiPlus: - if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= trackConfigs.cMinPionPtcut) - fillGenHistos(HIST("pi/h3PiMCGen"), HIST("pi/h4PiMCGenAssocReco"), mcParticle); - break; - default: - break; + switch (std::abs(mcParticle.pdgCode())) { + case o2::constants::physics::Pdg::kPhi: + if (eventSelectionType == 0 && mcParticle.pt() >= minPtMcGenConfigs.minPhiPt) + fillGenHistos(HIST("phi/h3PhiMCGen"), HIST("phi/h4PhiMCGenAssocReco"), mcParticle); + break; + case PDG_t::kK0Short: + if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= minPtMcGenConfigs.v0SettingMinPt) + fillGenHistos(HIST("k0s/h3K0SMCGen"), HIST("k0s/h4K0SMCGenAssocReco"), mcParticle); + break; + case PDG_t::kPiPlus: + if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= minPtMcGenConfigs.cMinPionPtcut) + fillGenHistos(HIST("pi/h3PiMCGen"), HIST("pi/h4PiMCGenAssocReco"), mcParticle); + break; + default: + break; + } } } } diff --git a/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx b/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx index 3b6bd0b0730..fd6b48609e1 100644 --- a/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/sigmaanalysis.cxx @@ -30,7 +30,6 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" @@ -61,8 +60,10 @@ using namespace o2::framework; using namespace o2::framework::expressions; using std::array; -using MCSigma0s = soa::Join; using Sigma0s = soa::Join; +using MCSigma0s = soa::Join; +using Sigma0sWithEMCal = soa::Join; +using MCSigma0sWithEMCal = soa::Join; static const std::vector PhotonSels = {"NoSel", "V0Type", "DCADauToPV", "DCADau", "DauTPCCR", "TPCNSigmaEl", "V0pT", @@ -75,19 +76,25 @@ static const std::vector LambdaSels = {"NoSel", "V0Radius", "DCADau static const std::vector DirList = {"BeforeSel", "AfterSel"}; +enum CentEstimator { + kCentFT0C = 0, + kCentFT0M, + kCentFT0CVariant1, + kCentMFT, + kCentNGlobal, + kCentFV0A +}; + struct sigmaanalysis { Service ccdb; ctpRateFetcher rateFetcher; //__________________________________________________ - // For manual sliceBy - // SliceCache cache; - PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Event level Configurable doPPAnalysis{"doPPAnalysis", true, "if in pp, set to true"}; + Configurable centralityEstimator{"centralityEstimator", kCentFT0C, "Run 3 centrality estimator (0:CentFT0C, 1:CentFT0M, 2:CentFT0CVariant1, 3:CentMFT, 4:CentNGlobal, 5:CentFV0A)"}; Configurable fGetIR{"fGetIR", false, "Flag to retrieve the IR info."}; Configurable fIRCrashOnNull{"fIRCrashOnNull", false, "Flag to avoid CTP RateFetcher crash."}; Configurable irSource{"irSource", "T0VTX", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; @@ -211,6 +218,23 @@ struct sigmaanalysis { Configurable PhotonPhiMax2{"PhotonPhiMax2", -1, "Phi min value to reject photons, region 2 (leave negative if no selection desired)"}; } photonSelections; + //// Photon criteria: + struct : ConfigurableGroup { + std::string prefix = "EMCalPhotonSelections"; // JSON group name + Configurable definition{"definition", 13, "Cluster definitions to be accepted (e.g. 13 for kV3MostSplitLowSeed)"}; + Configurable MinCells{"MinCells", 1, "Min number of cells in cluster"}; + Configurable MinEnergy{"MinEnergy", 0.0, "Minimum energy of selected clusters (GeV)"}; + Configurable MaxEnergy{"MaxEnergy", 5, "Max energy of selected clusters (GeV)"}; + Configurable MaxEta{"MaxEta", 1.0, "Max absolute cluster Eta"}; + Configurable MinTime{"MinTime", -50, "Minimum time of selected clusters (ns)"}; + Configurable MaxTime{"MaxTime", 50, "Max time of selected clusters (ns)"}; + Configurable RemoveExotic{"RemoveExotic", false, "Flag to enable the removal of exotic clusters"}; + Configurable MinM02{"MinM02", -1., "Minimum shower shape long axis"}; + Configurable MaxM02{"MaxM02", 5., "Max shower shape long axis"}; + Configurable RemoveMatchedTrack{"RemoveMatchedTrack", true, "Flag to enable the removal of clusters matched to tracks"}; + + } EMCalPhotonSelections; + struct : ConfigurableGroup { std::string prefix = "sigma0Selections"; // JSON group name Configurable Sigma0MinRapidity{"Sigma0MinRapidity", -0.5, "sigma0 min rapidity"}; @@ -268,6 +292,13 @@ struct sigmaanalysis { ConfigurableAxis axisPhi{"axisPhi", {200, 0, 2 * o2::constants::math::PI}, "Phi for photons"}; ConfigurableAxis axisZ{"axisZ", {120, -120.0f, 120.0f}, "V0 Z position (cm)"}; + // EMCal-specifc + ConfigurableAxis axisClrDefinition{"axisClrDefinition", {51, -0.5, 50.5}, "Cluster Definition"}; + ConfigurableAxis axisClrNCells{"axisClrNCells", {25, 0.0, 25}, "N cells per cluster"}; + ConfigurableAxis axisClrEnergy{"axisClrEnergy", {400, 0.0, 10}, "Energy per cluster"}; + ConfigurableAxis axisClrTime{"axisClrTime", {300, -30.0, 30.0}, "cluster time (ns)"}; + ConfigurableAxis axisClrShape{"axisClrShape", {100, 0.0, 1.0}, "cluster shape"}; + ConfigurableAxis axisCandSel{"axisCandSel", {20, 0.5f, +20.5f}, "Candidate Selection"}; // ML @@ -277,7 +308,7 @@ struct sigmaanalysis { void init(InitContext const&) { LOGF(info, "Initializing now: cross-checking correctness..."); - if ((doprocessRealData + doprocessMonteCarlo + doprocessPi0RealData + doprocessPi0MonteCarlo > 1) || + if ((doprocessRealData + doprocessRealDataWithEMCal + doprocessMonteCarlo + doprocessMonteCarloWithEMCal + doprocessPi0RealData + doprocessPi0MonteCarlo > 1) || (doprocessGeneratedRun3 + doprocessPi0GeneratedRun3 > 1)) { LOGF(fatal, "You have enabled more than one process function. Please check your configuration! Aborting now."); } @@ -289,6 +320,7 @@ struct sigmaanalysis { // Event Counters histos.add("hEventCentrality", "hEventCentrality", kTH1D, {axisCentrality}); + histos.add("hCentralityVsNch", "hCentralityVsNch", kTH2D, {{101, 0.0f, 101.0f}, axisNch}); histos.add("hEventSelection", "hEventSelection", kTH1D, {{21, -0.5f, +20.5f}}); histos.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); @@ -323,33 +355,52 @@ struct sigmaanalysis { histos.add("GeneralQA/hCentralityVsInteractionRate", "hCentralityVsInteractionRate", kTH2D, {axisCentrality, axisIRBinning}); } - if (doprocessRealData || doprocessMonteCarlo) { + if (doprocessRealData || doprocessRealDataWithEMCal || doprocessMonteCarlo || doprocessMonteCarloWithEMCal) { for (const auto& histodir : DirList) { if (fillSelhistos) { - histos.add(histodir + "/Photon/hTrackCode", "hTrackCode", kTH1D, {{11, 0.5f, 11.5f}}); - histos.add(histodir + "/Photon/hV0Type", "hV0Type", kTH1D, {{8, 0.5f, 8.5f}}); - histos.add(histodir + "/Photon/hDCANegToPV", "hDCANegToPV", kTH1D, {axisDCAtoPV}); - histos.add(histodir + "/Photon/hDCAPosToPV", "hDCAPosToPV", kTH1D, {axisDCAtoPV}); - histos.add(histodir + "/Photon/hDCADau", "hDCADau", kTH1D, {axisDCAdau}); - histos.add(histodir + "/Photon/hPosTPCCR", "hPosTPCCR", kTH1D, {axisTPCrows}); - histos.add(histodir + "/Photon/hNegTPCCR", "hNegTPCCR", kTH1D, {axisTPCrows}); - histos.add(histodir + "/Photon/hPosTPCNSigmaEl", "hPosTPCNSigmaEl", kTH1D, {axisTPCNSigma}); - histos.add(histodir + "/Photon/hNegTPCNSigmaEl", "hNegTPCNSigmaEl", kTH1D, {axisTPCNSigma}); - - histos.add(histodir + "/Photon/hpT", "hpT", kTH1D, {axisPt}); - histos.add(histodir + "/Photon/hY", "hY", kTH1D, {axisRapidity}); - histos.add(histodir + "/Photon/hPosEta", "hPosEta", kTH1D, {axisRapidity}); - histos.add(histodir + "/Photon/hNegEta", "hNegEta", kTH1D, {axisRapidity}); - histos.add(histodir + "/Photon/hRadius", "hRadius", kTH1D, {axisV0Radius}); - histos.add(histodir + "/Photon/hZ", "hZ", kTH1D, {axisZ}); - histos.add(histodir + "/Photon/h2dRZCut", "h2dRZCut", kTH2D, {axisZ, axisV0Radius}); - histos.add(histodir + "/Photon/h2dRZPlane", "h2dRZPlane", kTH2D, {axisZ, axisV0Radius}); - histos.add(histodir + "/Photon/hCosPA", "hCosPA", kTH1D, {axisCosPA}); - histos.add(histodir + "/Photon/hPsiPair", "hPsiPair", kTH1D, {axisPsiPair}); - histos.add(histodir + "/Photon/hPhi", "hPhi", kTH1D, {axisPhi}); - histos.add(histodir + "/Photon/h3dMass", "h3dMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); - histos.add(histodir + "/Photon/hMass", "hMass", kTH1D, {axisPhotonMass}); + + if (doprocessRealData || doprocessMonteCarlo) { + + histos.add(histodir + "/Photon/hTrackCode", "hTrackCode", kTH1D, {{11, 0.5f, 11.5f}}); + histos.add(histodir + "/Photon/hV0Type", "hV0Type", kTH1D, {{8, 0.5f, 8.5f}}); + histos.add(histodir + "/Photon/hDCANegToPV", "hDCANegToPV", kTH1D, {axisDCAtoPV}); + histos.add(histodir + "/Photon/hDCAPosToPV", "hDCAPosToPV", kTH1D, {axisDCAtoPV}); + histos.add(histodir + "/Photon/hDCADau", "hDCADau", kTH1D, {axisDCAdau}); + histos.add(histodir + "/Photon/hPosTPCCR", "hPosTPCCR", kTH1D, {axisTPCrows}); + histos.add(histodir + "/Photon/hNegTPCCR", "hNegTPCCR", kTH1D, {axisTPCrows}); + histos.add(histodir + "/Photon/hPosTPCNSigmaEl", "hPosTPCNSigmaEl", kTH1D, {axisTPCNSigma}); + histos.add(histodir + "/Photon/hNegTPCNSigmaEl", "hNegTPCNSigmaEl", kTH1D, {axisTPCNSigma}); + + // PCM photons + histos.add(histodir + "/Photon/hpT", "hpT", kTH1D, {axisPt}); + histos.add(histodir + "/Photon/hY", "hY", kTH1D, {axisRapidity}); + histos.add(histodir + "/Photon/hPosEta", "hPosEta", kTH1D, {axisRapidity}); + histos.add(histodir + "/Photon/hNegEta", "hNegEta", kTH1D, {axisRapidity}); + histos.add(histodir + "/Photon/hRadius", "hRadius", kTH1D, {axisV0Radius}); + histos.add(histodir + "/Photon/hZ", "hZ", kTH1D, {axisZ}); + histos.add(histodir + "/Photon/h2dRZCut", "h2dRZCut", kTH2D, {axisZ, axisV0Radius}); + histos.add(histodir + "/Photon/h2dRZPlane", "h2dRZPlane", kTH2D, {axisZ, axisV0Radius}); + histos.add(histodir + "/Photon/hCosPA", "hCosPA", kTH1D, {axisCosPA}); + histos.add(histodir + "/Photon/hPsiPair", "hPsiPair", kTH1D, {axisPsiPair}); + histos.add(histodir + "/Photon/hPhi", "hPhi", kTH1D, {axisPhi}); + histos.add(histodir + "/Photon/h3dMass", "h3dMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); + histos.add(histodir + "/Photon/hMass", "hMass", kTH1D, {axisPhotonMass}); + histos.add(histodir + "/Photon/h3dPhotonYSigma0Mass", "h3dPhotonYSigma0Mass", kTH3D, {axisRapidity, axisPt, axisSigmaMass}); + histos.add(histodir + "/Photon/h3dPhotonRadiusSigma0Mass", "h3dPhotonRadiusSigma0Mass", kTH3D, {axisV0Radius, axisPt, axisSigmaMass}); + } + + if (doprocessRealDataWithEMCal || doprocessMonteCarloWithEMCal) { + // EMCal photons + histos.add(histodir + "/EMCalPhotonSel/hpT", "hpT", kTH1D, {axisPt}); + histos.add(histodir + "/EMCalPhotonSel/hDefinition", "hDefinition", kTH1D, {axisClrDefinition}); + histos.add(histodir + "/EMCalPhotonSel/hNCells", "hNCells", kTH1D, {axisClrNCells}); + histos.add(histodir + "/EMCalPhotonSel/hEnergy", "hEnergy", kTH1D, {axisClrEnergy}); + histos.add(histodir + "/EMCalPhotonSel/h2dEtaVsPhi", "h2dEtaVsPhi", kTH2D, {axisRapidity, axisPhi}); + histos.add(histodir + "/EMCalPhotonSel/hTime", "hTime", kTH1D, {axisClrTime}); + histos.add(histodir + "/EMCalPhotonSel/hExotic", "hExotic", kTH1D, {{2, -0.5f, 1.5f}}); + histos.add(histodir + "/EMCalPhotonSel/hShape", "hShape", kTH1D, {axisClrShape}); + } histos.add(histodir + "/Lambda/hTrackCode", "hTrackCode", kTH1D, {{11, 0.5f, 11.5f}}); histos.add(histodir + "/Lambda/hRadius", "hRadius", kTH1D, {axisV0Radius}); @@ -390,8 +441,6 @@ struct sigmaanalysis { histos.add(histodir + "/Sigma0/h2dRadiusVspT", "h2dRadiusVspT", kTH2D, {axisV0PairRadius, axisPt}); histos.add(histodir + "/Sigma0/hDCAPairDau", "hDCAPairDau", kTH1D, {axisDCAdau}); histos.add(histodir + "/Sigma0/h3dMass", "h3dMass", kTH3D, {axisCentrality, axisPt, axisSigmaMass}); - histos.add(histodir + "/Sigma0/h3dPhotonYMass", "h3dPhotonYMass", kTH3D, {axisRapidity, axisPt, axisSigmaMass}); - histos.add(histodir + "/Sigma0/h3dPhotonRadiusMass", "h3dPhotonRadiusMass", kTH3D, {axisV0Radius, axisPt, axisSigmaMass}); histos.add(histodir + "/Sigma0/h3dOPAngleVsMass", "h3dOPAngleVsMass", kTH3D, {{140, 0.0f, +7.0f}, axisPt, axisSigmaMass}); histos.add(histodir + "/ASigma0/hMass", "hMass", kTH1D, {axisSigmaMass}); @@ -401,22 +450,21 @@ struct sigmaanalysis { histos.add(histodir + "/ASigma0/h2dRadiusVspT", "h2dRadiusVspT", kTH2D, {axisV0PairRadius, axisPt}); histos.add(histodir + "/ASigma0/hDCAPairDau", "hDCAPairDau", kTH1D, {axisDCAdau}); histos.add(histodir + "/ASigma0/h3dMass", "h3dMass", kTH3D, {axisCentrality, axisPt, axisSigmaMass}); - histos.add(histodir + "/ASigma0/h3dPhotonYMass", "h3dPhotonYMass", kTH3D, {axisRapidity, axisPt, axisSigmaMass}); - histos.add(histodir + "/ASigma0/h3dPhotonRadiusMass", "h3dPhotonRadiusMass", kTH3D, {axisV0Radius, axisPt, axisSigmaMass}); histos.add(histodir + "/ASigma0/h3dOPAngleVsMass", "h3dOPAngleVsMass", kTH3D, {{140, 0.0f, +7.0f}, axisPt, axisSigmaMass}); // Process MC - if (doprocessMonteCarlo) { + if (doprocessMonteCarlo || doprocessMonteCarloWithEMCal) { if (fillSelhistos) { histos.add(histodir + "/MC/Photon/hV0ToCollAssoc", "hV0ToCollAssoc", kTH1D, {{2, 0.0f, 2.0f}}); histos.add(histodir + "/MC/Photon/hPt", "hPt", kTH1D, {axisPt}); histos.add(histodir + "/MC/Photon/hMCPt", "hMCPt", kTH1D, {axisPt}); - histos.add(histodir + "/MC/Photon/hPosTPCNSigmaEl", "hPosTPCNSigmaEl", kTH1D, {axisTPCNSigma}); - histos.add(histodir + "/MC/Photon/hNegTPCNSigmaEl", "hNegTPCNSigmaEl", kTH1D, {axisTPCNSigma}); - histos.add(histodir + "/MC/Photon/h2dPAVsPt", "h2dPAVsPt", kTH2D, {axisPA, axisPt}); - histos.add(histodir + "/MC/Photon/hPt_BadCollAssig", "hPt_BadCollAssig", kTH1D, {axisPt}); - histos.add(histodir + "/MC/Photon/h2dPAVsPt_BadCollAssig", "h2dPAVsPt_BadCollAssig", kTH2D, {axisPA, axisPt}); + + if (doprocessMonteCarlo) { + histos.add(histodir + "/MC/Photon/h2dPAVsPt", "h2dPAVsPt", kTH2D, {axisPA, axisPt}); + histos.add(histodir + "/MC/Photon/hPt_BadCollAssig", "hPt_BadCollAssig", kTH1D, {axisPt}); + histos.add(histodir + "/MC/Photon/h2dPAVsPt_BadCollAssig", "h2dPAVsPt_BadCollAssig", kTH2D, {axisPA, axisPt}); + } histos.add(histodir + "/MC/Lambda/hV0ToCollAssoc", "hV0ToCollAssoc", kTH1D, {{2, 0.0f, 2.0f}}); histos.add(histodir + "/MC/Lambda/hPt", "hPt", kTH1D, {axisPt}); @@ -431,8 +479,6 @@ struct sigmaanalysis { histos.add(histodir + "/MC/ALambda/h3dTPCvsTOFNSigma_Pi", "h3dTPCvsTOFNSigma_Pi", kTH3D, {axisTPCNSigma, axisTOFNSigma, axisPt}); } - histos.add(histodir + "/MC/h2dArmenteros", "h2dArmenteros", kTH2D, {axisAPAlpha, axisAPQt}); - histos.add(histodir + "/MC/Sigma0/hPt", "hPt", kTH1D, {axisPt}); histos.add(histodir + "/MC/Sigma0/hMCPt", "hMCPt", kTH1D, {axisPt}); histos.add(histodir + "/MC/Sigma0/hMass", "hMass", kTH1D, {axisSigmaMass}); @@ -455,11 +501,10 @@ struct sigmaanalysis { histos.add(histodir + "/MC/ASigma0/h3dMass", "h3dMass", kTH3D, {axisCentrality, axisPt, axisSigmaMass}); histos.add(histodir + "/MC/ASigma0/h3dMCProcess", "h3dMCProcess", kTH3D, {{50, -0.5f, 49.5f}, axisPt, axisSigmaMass}); - // 1/pT Resolution: + // pT Resolution: if (fillResoQAhistos && histodir == "BeforeSel") { - histos.add(histodir + "/MC/Reso/h3dGammaPtResoVsTPCCR", "h3dGammaPtResoVsTPCCR", kTH3D, {axisInvPt, axisDeltaPt, axisTPCrows}); - histos.add(histodir + "/MC/Reso/h3dGammaPtResoVsTPCCR", "h3dGammaPtResoVsTPCCR", kTH3D, {axisInvPt, axisDeltaPt, axisTPCrows}); - histos.add(histodir + "/MC/Reso/h2dGammaPtResolution", "h2dGammaPtResolution", kTH2D, {axisInvPt, axisDeltaPt}); + histos.add(histodir + "/MC/Reso/h2dGammaInvPtResolution", "h2dGammaPtResolution", kTH2D, {axisInvPt, axisDeltaPt}); + histos.add(histodir + "/MC/Reso/h2dGammaInvPtResolution", "h2dGammaInvPtResolution", kTH2D, {axisInvPt, axisDeltaPt}); histos.add(histodir + "/MC/Reso/h2dLambdaPtResolution", "h2dLambdaPtResolution", kTH2D, {axisInvPt, axisDeltaPt}); histos.add(histodir + "/MC/Reso/h3dLambdaPtResoVsTPCCR", "h3dLambdaPtResoVsTPCCR", kTH3D, {axisInvPt, axisDeltaPt, axisTPCrows}); histos.add(histodir + "/MC/Reso/h3dLambdaPtResoVsTPCCR", "h3dLambdaPtResoVsTPCCR", kTH3D, {axisInvPt, axisDeltaPt, axisTPCrows}); @@ -467,6 +512,7 @@ struct sigmaanalysis { histos.add(histodir + "/MC/Reso/h3dAntiLambdaPtResoVsTPCCR", "h3dAntiLambdaPtResoVsTPCCR", kTH3D, {axisInvPt, axisDeltaPt, axisTPCrows}); histos.add(histodir + "/MC/Reso/h3dAntiLambdaPtResoVsTPCCR", "h3dAntiLambdaPtResoVsTPCCR", kTH3D, {axisInvPt, axisDeltaPt, axisTPCrows}); histos.add(histodir + "/MC/Reso/h2dSigma0PtResolution", "h2dSigma0PtResolution", kTH2D, {axisInvPt, axisDeltaPt}); + histos.add(histodir + "/MC/Reso/h2dSigma0InvPtResolution", "h2dSigma0InvPtResolution", kTH2D, {axisInvPt, axisDeltaPt}); histos.add(histodir + "/MC/Reso/h2dAntiSigma0PtResolution", "h2dAntiSigma0PtResolution", kTH2D, {axisInvPt, axisDeltaPt}); histos.add(histodir + "/MC/Reso/h2dSigma0RadiusResolution", "h2dSigma0RadiusResolution", kTH2D, {axisPt, axisDeltaPt}); histos.add(histodir + "/MC/Reso/h2dASigma0RadiusResolution", "h2dASigma0RadiusResolution", kTH2D, {axisPt, axisDeltaPt}); @@ -574,6 +620,26 @@ struct sigmaanalysis { histos.print(); } + // Auxiliary function to get the centrality of a collision according to the selected estimator + template + auto getCentralityRun3(TCollision const& collision) + { + if (centralityEstimator == kCentFT0C) + return collision.centFT0C(); + else if (centralityEstimator == kCentFT0M) + return collision.centFT0M(); + else if (centralityEstimator == kCentFT0CVariant1) + return collision.centFT0CVariant1(); + else if (centralityEstimator == kCentMFT) + return collision.centMFT(); + else if (centralityEstimator == kCentNGlobal) + return collision.centNGlobal(); + else if (centralityEstimator == kCentFV0A) + return collision.centFV0A(); + + return -1.f; + } + // ______________________________________________________ // Check whether the collision passes our collision selections // Should work with collisions, mccollisions, stracollisions and stramccollisions tables! @@ -684,7 +750,7 @@ struct sigmaanalysis { // Fetch interaction rate only if required (in order to limit ccdb calls) float interactionRate = (fGetIR) ? rateFetcher.fetch(ccdb.service, collision.timestamp(), collision.runNumber(), irSource, fIRCrashOnNull) * 1.e-3 : -1; - float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + float centrality = getCentralityRun3(collision); if (fGetIR) { if (interactionRate < 0) @@ -709,6 +775,7 @@ struct sigmaanalysis { // Fill centrality histogram after event selection if (fillHists) histos.fill(HIST("hEventCentrality"), centrality); + histos.fill(HIST("hCentralityVsNch"), centrality, collision.multNTracksPVeta1()); return true; } @@ -720,12 +787,21 @@ struct sigmaanalysis { std::vector getListOfRecoCollIndices(TMCollisions const& mcCollisions, TCollisions const& collisions) { std::vector listBestCollisionIdx(mcCollisions.size()); + + // Custom grouping + std::vector> groupedCollisions(mcCollisions.size()); + + for (const auto& coll : collisions) { + groupedCollisions[coll.straMCCollisionId()].push_back(coll.globalIndex()); + } + for (auto const& mcCollision : mcCollisions) { - auto groupedCollisions = collisions.sliceBy(perMcCollision, mcCollision.globalIndex()); int biggestNContribs = -1; int bestCollisionIndex = -1; - for (auto const& collision : groupedCollisions) { + for (size_t i = 0; i < groupedCollisions[mcCollision.globalIndex()].size(); i++) { // consider event selections in the recoed <-> gen collision association, for the denominator (or numerator) of the efficiency (or signal loss)? + auto collision = collisions.rawIteratorAt(groupedCollisions[mcCollision.globalIndex()][i]); + if (eventSelections.useEvtSelInDenomEff) { if (!IsEventAccepted(collision, false)) { continue; @@ -750,6 +826,14 @@ struct sigmaanalysis { void fillGeneratedEventProperties(TMCCollisions const& mcCollisions, TCollisions const& collisions) { std::vector listBestCollisionIdx(mcCollisions.size()); + + // Custom grouping + std::vector> groupedCollisions(mcCollisions.size()); + + for (const auto& coll : collisions) { + groupedCollisions[coll.straMCCollisionId()].push_back(coll.globalIndex()); + } + for (auto const& mcCollision : mcCollisions) { // Apply selections on MC collisions if (eventSelections.applyZVtxSelOnMCPV && std::abs(mcCollision.posZ()) > eventSelections.maxZVtxPosition) { @@ -767,14 +851,14 @@ struct sigmaanalysis { histos.fill(HIST("Gen/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; float centrality = 100.5f; int nCollisions = 0; - for (auto const& collision : groupedCollisions) { + for (size_t i = 0; i < groupedCollisions[mcCollision.globalIndex()].size(); i++) { + auto collision = collisions.rawIteratorAt(groupedCollisions[mcCollision.globalIndex()][i]); if (!IsEventAccepted(collision, false)) { continue; @@ -782,7 +866,7 @@ struct sigmaanalysis { if (biggestNContribs < collision.multPVTotalContributors()) { biggestNContribs = collision.multPVTotalContributors(); - centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + centrality = getCentralityRun3(collision); } nCollisions++; @@ -852,7 +936,7 @@ struct sigmaanalysis { if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { auto collision = collisions.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); - centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + centrality = getCentralityRun3(collision); if (genParticle.isSigma0()) histos.fill(HIST("Gen/h2dGenSigma0VsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); @@ -895,14 +979,16 @@ struct sigmaanalysis { int TrkCode = 10; // 1: TPC-only, 2: TPC+Something, 3: ITS-Only, 4: ITS+TPC + Something, 10: anything else if (isGamma) { - if (sigma.photonPosTrackCode() == 1 && sigma.photonNegTrackCode() == 1) - TrkCode = 1; - if ((sigma.photonPosTrackCode() != 1 && sigma.photonNegTrackCode() == 1) || (sigma.photonPosTrackCode() == 1 && sigma.photonNegTrackCode() != 1)) - TrkCode = 2; - if (sigma.photonPosTrackCode() == 3 && sigma.photonNegTrackCode() == 3) - TrkCode = 3; - if (sigma.photonPosTrackCode() == 2 || sigma.photonNegTrackCode() == 2) - TrkCode = 4; + if constexpr (requires { sigma.photonV0Type(); }) { + if (sigma.photonPosTrackCode() == 1 && sigma.photonNegTrackCode() == 1) + TrkCode = 1; + if ((sigma.photonPosTrackCode() != 1 && sigma.photonNegTrackCode() == 1) || (sigma.photonPosTrackCode() == 1 && sigma.photonNegTrackCode() != 1)) + TrkCode = 2; + if (sigma.photonPosTrackCode() == 3 && sigma.photonNegTrackCode() == 3) + TrkCode = 3; + if (sigma.photonPosTrackCode() == 2 || sigma.photonNegTrackCode() == 2) + TrkCode = 4; + } } else { if (sigma.lambdaPosTrackCode() == 1 && sigma.lambdaNegTrackCode() == 1) TrkCode = 1; @@ -925,9 +1011,8 @@ struct sigmaanalysis { // Gamma MC association if (sigma.photonPDGCode() == 22) { if (sigma.photonmcpt() > 0) { - histos.fill(HIST("BeforeSel/MC/Reso/h3dGammaPtResoVsTPCCR"), 1.f / sigma.lambdamcpt(), 1.f / sigma.lambdaPt() - 1.f / sigma.lambdamcpt(), -1 * sigma.photonNegTPCCrossedRows()); // 1/pT resolution - histos.fill(HIST("BeforeSel/MC/Reso/h3dGammaPtResoVsTPCCR"), 1.f / sigma.lambdamcpt(), 1.f / sigma.lambdaPt() - 1.f / sigma.lambdamcpt(), sigma.photonPosTPCCrossedRows()); // 1/pT resolution - histos.fill(HIST("BeforeSel/MC/Reso/h2dGammaPtResolution"), 1.f / sigma.photonmcpt(), 1.f / sigma.photonPt() - 1.f / sigma.photonmcpt()); // pT resolution + histos.fill(HIST("BeforeSel/MC/Reso/h2dGammaPtResolution"), sigma.photonmcpt(), sigma.photonPt() - sigma.photonmcpt()); // pT resolution + histos.fill(HIST("BeforeSel/MC/Reso/h2dGammaInvPtResolution"), 1.f / sigma.photonmcpt(), 1.f / sigma.photonPt() - 1.f / sigma.photonmcpt()); // pT resolution } } @@ -955,8 +1040,10 @@ struct sigmaanalysis { // Sigma and AntiSigma MC association if (sigma.isSigma0()) { histos.fill(HIST("BeforeSel/MC/Reso/h2dSigma0RadiusResolution"), sigma.mcpt(), sigma.radius() - sigma.mcradius()); // pT resolution - if (sigma.mcpt() > 0) - histos.fill(HIST("BeforeSel/MC/Reso/h2dSigma0PtResolution"), 1.f / sigma.mcpt(), 1.f / sigma.pt() - 1.f / sigma.mcpt()); // pT resolution + if (sigma.mcpt() > 0) { + histos.fill(HIST("BeforeSel/MC/Reso/h2dSigma0PtResolution"), sigma.mcpt(), sigma.pt() - sigma.mcpt()); // pT resolution + histos.fill(HIST("BeforeSel/MC/Reso/h2dSigma0InvPtResolution"), 1.f / sigma.mcpt(), 1.f / sigma.pt() - 1.f / sigma.mcpt()); // pT resolution + } } if (sigma.isAntiSigma0()) { histos.fill(HIST("BeforeSel/MC/Reso/h2dASigma0RadiusResolution"), sigma.mcpt(), sigma.radius() - sigma.mcradius()); // pT resolution @@ -1013,39 +1100,61 @@ struct sigmaanalysis { // Check whether it is before or after selections static constexpr std::string_view MainDir[] = {"BeforeSel", "AfterSel"}; - // Get V0trackCode - int GammaTrkCode = retrieveV0TrackCode(sigma); - int LambdaTrkCode = retrieveV0TrackCode(sigma); - - float photonRZLineCut = TMath::Abs(sigma.photonZconv()) * TMath::Tan(2 * TMath::ATan(TMath::Exp(-photonSelections.PhotonMaxDauEta))) - photonSelections.PhotonLineCutZ0; - float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + float centrality = getCentralityRun3(collision); if (fillSelhistos) { - //_______________________________________ - // Photon - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hTrackCode"), GammaTrkCode); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hV0Type"), sigma.photonV0Type()); - - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hDCANegToPV"), sigma.photonDCANegPV()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hDCAPosToPV"), sigma.photonDCAPosPV()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hDCADau"), sigma.photonDCADau()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPosTPCCR"), sigma.photonPosTPCCrossedRows()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hNegTPCCR"), sigma.photonNegTPCCrossedRows()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPosTPCNSigmaEl"), sigma.photonPosTPCNSigmaEl()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hNegTPCNSigmaEl"), sigma.photonNegTPCNSigmaEl()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hpT"), sigma.photonPt()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hY"), sigma.photonY()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPosEta"), sigma.photonPosEta()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hNegEta"), sigma.photonNegEta()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hRadius"), sigma.photonRadius()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hZ"), sigma.photonZconv()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h2dRZCut"), sigma.photonRadius(), photonRZLineCut); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h2dRZPlane"), sigma.photonZconv(), sigma.photonRadius()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hCosPA"), sigma.photonCosPA()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPsiPair"), sigma.photonPsiPair()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPhi"), sigma.photonPhi()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h3dMass"), centrality, sigma.photonPt(), sigma.photonMass()); - histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hMass"), sigma.photonMass()); + + // Get V0trackCode + int LambdaTrkCode = retrieveV0TrackCode(sigma); + + if constexpr (requires { sigma.photonV0Type(); }) { // Processing PCM photon + + // Base properties + int GammaTrkCode = retrieveV0TrackCode(sigma); + float photonRZLineCut = TMath::Abs(sigma.photonZconv()) * TMath::Tan(2 * TMath::ATan(TMath::Exp(-photonSelections.PhotonMaxDauEta))) - photonSelections.PhotonLineCutZ0; + + //_______________________________________ + // Photon + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hTrackCode"), GammaTrkCode); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hV0Type"), sigma.photonV0Type()); + + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hDCANegToPV"), sigma.photonDCANegPV()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hDCAPosToPV"), sigma.photonDCAPosPV()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hDCADau"), sigma.photonDCADau()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPosTPCCR"), sigma.photonPosTPCCrossedRows()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hNegTPCCR"), sigma.photonNegTPCCrossedRows()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPosTPCNSigmaEl"), sigma.photonPosTPCNSigmaEl()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hNegTPCNSigmaEl"), sigma.photonNegTPCNSigmaEl()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hpT"), sigma.photonPt()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hY"), sigma.photonY()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPosEta"), sigma.photonPosEta()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hNegEta"), sigma.photonNegEta()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hRadius"), sigma.photonRadius()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hZ"), sigma.photonZconv()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h2dRZCut"), sigma.photonRadius(), photonRZLineCut); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h2dRZPlane"), sigma.photonZconv(), sigma.photonRadius()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hCosPA"), sigma.photonCosPA()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPsiPair"), sigma.photonPsiPair()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hPhi"), sigma.photonPhi()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h3dMass"), centrality, sigma.photonPt(), sigma.photonMass()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/hMass"), sigma.photonMass()); + + histos.fill(HIST(MainDir[mode]) + HIST("/h2dArmenteros"), sigma.photonAlpha(), sigma.photonQt()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h3dPhotonYSigma0Mass"), sigma.photonY(), sigma.pt(), sigma.sigma0Mass()); + histos.fill(HIST(MainDir[mode]) + HIST("/Photon/h3dPhotonRadiusSigma0Mass"), sigma.photonRadius(), sigma.pt(), sigma.sigma0Mass()); + } + + if constexpr (requires { sigma.photonDefinition(); }) { // Processing EMCal photon + + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hpT"), sigma.photonPt()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hDefinition"), sigma.photonDefinition()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hNCells"), sigma.photonNCells()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hEnergy"), sigma.photonEnergy()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/h2dEtaVsPhi"), sigma.photonEMCEta(), sigma.photonEMCPhi()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hTime"), sigma.photonTime()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hExotic"), sigma.photonIsExotic()); + histos.fill(HIST(MainDir[mode]) + HIST("/EMCalPhotonSel/hShape"), sigma.photonM02()); + } //_______________________________________ // Lambdas @@ -1063,13 +1172,12 @@ struct sigmaanalysis { histos.fill(HIST(MainDir[mode]) + HIST("/Lambda/hPosChi2PerNc"), sigma.lambdaPosChi2PerNcl()); histos.fill(HIST(MainDir[mode]) + HIST("/Lambda/hNegChi2PerNc"), sigma.lambdaNegChi2PerNcl()); histos.fill(HIST(MainDir[mode]) + HIST("/Lambda/hLifeTime"), sigma.lambdaLifeTime()); + + histos.fill(HIST(MainDir[mode]) + HIST("/h2dArmenteros"), sigma.lambdaAlpha(), sigma.lambdaQt()); } //_______________________________________ // Sigmas and Lambdas - histos.fill(HIST(MainDir[mode]) + HIST("/h2dArmenteros"), sigma.photonAlpha(), sigma.photonQt()); - histos.fill(HIST(MainDir[mode]) + HIST("/h2dArmenteros"), sigma.lambdaAlpha(), sigma.lambdaQt()); - if (sigma.lambdaAlpha() > 0) { if (fillSelhistos) { histos.fill(HIST(MainDir[mode]) + HIST("/Lambda/h2dTPCvsTOFNSigma_LambdaPr"), sigma.lambdaPosPrTPCNSigma(), sigma.lambdaPrTOFNSigma()); @@ -1088,8 +1196,6 @@ struct sigmaanalysis { histos.fill(HIST(MainDir[mode]) + HIST("/Sigma0/h2dRadiusVspT"), sigma.radius(), sigma.pt()); histos.fill(HIST(MainDir[mode]) + HIST("/Sigma0/hDCAPairDau"), sigma.dcadaughters()); histos.fill(HIST(MainDir[mode]) + HIST("/Sigma0/h3dMass"), centrality, sigma.pt(), sigma.sigma0Mass()); - histos.fill(HIST(MainDir[mode]) + HIST("/Sigma0/h3dPhotonYMass"), sigma.photonY(), sigma.pt(), sigma.sigma0Mass()); - histos.fill(HIST(MainDir[mode]) + HIST("/Sigma0/h3dPhotonRadiusMass"), sigma.photonRadius(), sigma.pt(), sigma.sigma0Mass()); histos.fill(HIST(MainDir[mode]) + HIST("/Sigma0/h3dOPAngleVsMass"), sigma.opAngle(), sigma.pt(), sigma.sigma0Mass()); } else { if (fillSelhistos) { @@ -1109,8 +1215,6 @@ struct sigmaanalysis { histos.fill(HIST(MainDir[mode]) + HIST("/ASigma0/h2dRadiusVspT"), sigma.radius(), sigma.pt()); histos.fill(HIST(MainDir[mode]) + HIST("/ASigma0/hDCAPairDau"), sigma.dcadaughters()); histos.fill(HIST(MainDir[mode]) + HIST("/ASigma0/h3dMass"), centrality, sigma.pt(), sigma.sigma0Mass()); - histos.fill(HIST(MainDir[mode]) + HIST("/ASigma0/h3dPhotonYMass"), sigma.photonY(), sigma.pt(), sigma.sigma0Mass()); - histos.fill(HIST(MainDir[mode]) + HIST("/ASigma0/h3dPhotonRadiusMass"), sigma.photonRadius(), sigma.pt(), sigma.sigma0Mass()); histos.fill(HIST(MainDir[mode]) + HIST("/ASigma0/h3dOPAngleVsMass"), sigma.opAngle(), sigma.pt(), sigma.sigma0Mass()); } @@ -1123,17 +1227,18 @@ struct sigmaanalysis { //_______________________________________ // Gamma MC association if (sigma.photonPDGCode() == 22) { + histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hV0ToCollAssoc"), sigma.photonIsCorrectlyAssoc()); histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hPt"), sigma.photonPt()); histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hMCPt"), sigma.photonmcpt()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hPosTPCNSigmaEl"), sigma.photonPosTPCNSigmaEl()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hNegTPCNSigmaEl"), sigma.photonNegTPCNSigmaEl()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/h2dPAVsPt"), TMath::ACos(sigma.photonCosPA()), sigma.photonmcpt()); + if constexpr (requires { sigma.photonV0Type(); }) { // Processing PCM photon + histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/h2dPAVsPt"), TMath::ACos(sigma.photonCosPA()), sigma.photonmcpt()); - if (!sigma.photonIsCorrectlyAssoc()) { - histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hPt_BadCollAssig"), sigma.photonmcpt()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/h2dPAVsPt_BadCollAssig"), TMath::ACos(sigma.photonCosPA()), sigma.photonmcpt()); + if (!sigma.photonIsCorrectlyAssoc()) { + histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/hPt_BadCollAssig"), sigma.photonmcpt()); + histos.fill(HIST(MainDir[mode]) + HIST("/MC/Photon/h2dPAVsPt_BadCollAssig"), TMath::ACos(sigma.photonCosPA()), sigma.photonmcpt()); + } } } @@ -1160,9 +1265,6 @@ struct sigmaanalysis { //_______________________________________ // Sigma0 MC association if (sigma.isSigma0()) { - histos.fill(HIST(MainDir[mode]) + HIST("/MC/h2dArmenteros"), sigma.photonAlpha(), sigma.photonQt()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/h2dArmenteros"), sigma.lambdaAlpha(), sigma.lambdaQt()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/Sigma0/hPt"), sigma.pt()); histos.fill(HIST(MainDir[mode]) + HIST("/MC/Sigma0/hMCPt"), sigma.mcpt()); @@ -1180,9 +1282,6 @@ struct sigmaanalysis { //_______________________________________ // AntiSigma0 MC association if (sigma.isAntiSigma0()) { - histos.fill(HIST(MainDir[mode]) + HIST("/MC/h2dArmenteros"), sigma.photonAlpha(), sigma.photonQt()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/h2dArmenteros"), sigma.lambdaAlpha(), sigma.lambdaQt()); - histos.fill(HIST(MainDir[mode]) + HIST("/MC/ASigma0/hPt"), sigma.pt()); histos.fill(HIST(MainDir[mode]) + HIST("/MC/ASigma0/hMCPt"), sigma.mcpt()); @@ -1351,6 +1450,48 @@ struct sigmaanalysis { return true; } + // Apply specific selections for photons + template + bool selectEMCalPhoton(TClusterObject const& cand) + { + // Clusterizer + if (cand.photonDefinition() != EMCalPhotonSelections.definition && EMCalPhotonSelections.definition > -1) + return false; + + // Number of Cells + if (cand.photonNCells() < EMCalPhotonSelections.MinCells) + return false; + + // Energy + if (cand.photonEnergy() < EMCalPhotonSelections.MinEnergy || cand.photonEnergy() > EMCalPhotonSelections.MaxEnergy) + return false; + + // Eta + if (TMath::Abs(cand.photonEMCEta()) > EMCalPhotonSelections.MaxEta) + return false; + + // Timing + if (cand.photonTime() < EMCalPhotonSelections.MinTime || cand.photonTime() > EMCalPhotonSelections.MaxTime) + return false; + + // Exotic Clusters + if (cand.photonIsExotic() && EMCalPhotonSelections.RemoveExotic) { + return false; + } + + // Shower shape long axis + if (cand.photonNCells() > 1) { // Only if we have more than one + if (cand.photonM02() < EMCalPhotonSelections.MinM02 || cand.photonM02() > EMCalPhotonSelections.MaxM02) { + return false; + } + } + // Has matched track? + if (cand.photonHasAssocTrk() && EMCalPhotonSelections.RemoveMatchedTrack) + return false; + + return true; + } + // Apply specific selections for lambdas template bool selectLambda(TV0Object const& cand) @@ -1461,8 +1602,15 @@ struct sigmaanalysis { bool processSigma0Candidate(TSigma0Object const& cand) { // Photon specific selections - if (!selectPhoton(cand)) - return false; + if constexpr (requires { cand.photonV0Type(); }) { // Processing PCM photon + if (!selectPhoton(cand)) + return false; + } + + if constexpr (requires { cand.photonDefinition(); }) { // Processing EMCal photon + if (!selectEMCalPhoton(cand)) + return false; + } // Lambda specific selections if (!selectLambda(cand)) @@ -1508,7 +1656,7 @@ struct sigmaanalysis { for (const auto& coll : collisions) { // Event selection - if (!IsEventAccepted(coll, true)) + if (!IsEventAccepted(coll, true)) // TODO: Should I Add event selection for events without EMCal? continue; // Sigma0s loop @@ -1658,7 +1806,7 @@ struct sigmaanalysis { continue; // Pi0s loop - float centrality = doPPAnalysis ? coll.centFT0M() : coll.centFT0C(); + float centrality = getCentralityRun3(coll); for (size_t i = 0; i < pi0grouped[coll.globalIndex()].size(); i++) { auto pi0 = fullPi0s.rawIteratorAt(pi0grouped[coll.globalIndex()][i]); @@ -1690,11 +1838,21 @@ struct sigmaanalysis { analyzeRecoeSigma0s(collisions, fullSigma0s); } + void processRealDataWithEMCal(soa::Join const& collisions, Sigma0sWithEMCal const& fullSigma0s) + { + analyzeRecoeSigma0s(collisions, fullSigma0s); + } + void processMonteCarlo(soa::Join const& collisions, MCSigma0s const& fullSigma0s) { analyzeRecoeSigma0s(collisions, fullSigma0s); } + void processMonteCarloWithEMCal(soa::Join const& collisions, MCSigma0sWithEMCal const& fullSigma0s) + { + analyzeRecoeSigma0s(collisions, fullSigma0s); + } + // Simulated processing in Run 3 void processGeneratedRun3(soa::Join const& mcCollisions, soa::Join const& collisions, soa::Join const& Sigma0Gens) { @@ -1720,7 +1878,9 @@ struct sigmaanalysis { // _____________________________________________________ PROCESS_SWITCH(sigmaanalysis, processRealData, "Do real data analysis", true); + PROCESS_SWITCH(sigmaanalysis, processRealDataWithEMCal, "Do real data analysis with EMCal photons", false); PROCESS_SWITCH(sigmaanalysis, processMonteCarlo, "Do Monte-Carlo-based analysis", false); + PROCESS_SWITCH(sigmaanalysis, processMonteCarloWithEMCal, "Do Monte-Carlo-based analysis with EMCal photons", false); PROCESS_SWITCH(sigmaanalysis, processGeneratedRun3, "process MC generated Run 3", false); PROCESS_SWITCH(sigmaanalysis, processPi0RealData, "Do real data analysis for pi0 QA", false); PROCESS_SWITCH(sigmaanalysis, processPi0MonteCarlo, "Do Monte-Carlo-based analysis for pi0 QA", false); diff --git a/PWGLF/Tasks/Strangeness/strangeCascTrack.cxx b/PWGLF/Tasks/Strangeness/strangeCascTrack.cxx index 6bfff6476de..de8e38ecbfb 100644 --- a/PWGLF/Tasks/Strangeness/strangeCascTrack.cxx +++ b/PWGLF/Tasks/Strangeness/strangeCascTrack.cxx @@ -45,13 +45,13 @@ using namespace o2::framework; using namespace o2::framework::expressions; // tables for derived data -using DerCollisionWMults = soa::Join; +using DerCollisionWMults = soa::Join; using DerCascDatas = soa::Join; using DerTraCascDatas = soa::Join; // tables for derived MC using DerMCGenCascades = soa::Join; -using DerMCRecCollisions = soa::Join; +using DerMCRecCollisions = soa::Join; using DerMCRecCascDatas = soa::Join; using DerMCRecTraCascDatas = soa::Join; @@ -60,19 +60,17 @@ using DauTracks = soa::Join; struct StrangeCascTrack { - Service ccdb; + //* Service ccdb; Service pdgDB; PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + PresliceUnsorted cascsPerMcCollision = aod::cascdata::straMCCollisionId; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // subprocess switches: - Configurable doProcesspp{"doProcesspp", true, "true for pp"}; - Configurable doProcessPbPb{"doProcessPbPb", false, "true for PbPb"}; - Configurable doProcessOO{"doProcessOO", false, "true for OO"}; - Configurable doProcesspO{"doProcesspO", false, "true for pO"}; + Configurable doProcessIons{"doProcessIons", false, "true for PbPb and OO, false for pp and pO"}; Configurable doApplyEventCuts{"doApplyEventCuts", true, "apply general event cuts"}; // event filter - PVz, sel8, INEL>0 // Xi selections @@ -86,30 +84,36 @@ struct StrangeCascTrack { Configurable doApplyTPCPIDOmega{"doApplyTPCPIDOmega", true, "apply tpc pid to dau tracks (Omega)"}; Configurable doApplyTOFPIDOmega{"doApplyTOFPIDOmega", true, "apply tof pid to dau tracks (Omega)"}; Configurable doCompetingMassRej{"doCompetingMassRej", true, "competing mass rejection (Omega)"}; - // efficiency and purity corrections on the fly (warning: to be avoided because interpolation causes errors): - // only correct by pt - Configurable doApplyEfficiency1D{"doApplyEfficiency1D", false, "apply efficiency correction"}; - Configurable doPropagateEfficiency1D{"doPropagateEfficiency1D", false, "apply efficiency propagation"}; - Configurable doApplyPurity1D{"doApplyPurity1D", false, "apply purity correction"}; - Configurable doPropagatePurity1D{"doPropagatePurity1D", false, "apply purity propagation"}; - // correct by both pt and mult - Configurable doApplyEfficiency2D{"doApplyEfficiency2D", false, "apply efficiency correction"}; - Configurable doPropagateEfficiency2D{"doPropagateEfficiency2D", false, "apply efficiency propagation"}; - Configurable doApplyPurity2D{"doApplyPurity2D", false, "apply purity correction"}; - Configurable doPropagatePurity2D{"doPropagatePurity2D", false, "apply purity propagation"}; - Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; - Configurable efficiencyCCDBPathpp{"efficiencyCCDBPathpp", "Users/y/yparovia/LHC24f4d", "Path of the efficiency and purity corrections (pp)"}; - Configurable efficiencyCCDBPathPbPb{"efficiencyCCDBPathPbPb", "Users/y/yparovia/LHC25f3", "Path of the efficiency and purity corrections (PbPb)"}; - Configurable efficiencyCCDBPathOO{"efficiencyCCDBPathOO", "Users/y/yparovia/LHC25h3", "Path of the efficiency and purity corrections (OO)"}; - Configurable efficiencyCCDBPathpO{"efficiencyCCDBPathpO", "Users/y/yparovia/LHC25h2", "Path of the efficiency and purity corrections (pO)"}; - // event and dau track selection + // axes struct : ConfigurableGroup { - // event cuts + std::string prefix = "axes"; + ConfigurableAxis axisEta{"axisEta", {102, -2.01, 2.01}, "#eta"}; + ConfigurableAxis axisDCAxy{"axisDCAxy", {500, 0., 0.5}, "cm"}; + ConfigurableAxis axisDCAz{"axisDCAz", {500, 0., 0.5}, "cm"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 10}, "p_{T} (GeV/c)"}; + ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0.0f, 5.0, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 100.0f}, "FT0 mult %"}; + ConfigurableAxis axisOmegaMass{"axisOmegaMass", {2000, 1.6, 1.8}, "#Omega M_{inv} (GeV/c^{2})"}; + ConfigurableAxis axisXiMass{"axisXiMass", {2000, 1.2, 1.4}, "#Xi M_{inv} (GeV/c^{2})"}; + } axesConfig; + + // event selections + struct : ConfigurableGroup { + std::string prefix = "eventSelections"; Configurable cutDoINEL{"cutDoINEL", true, "choose events with INEL>0"}; Configurable cutZVertex{"cutZVertex", 10.0f, "max Z-vertex position"}; Configurable cutDoSel8{"cutDoSel8", true, "choose events with sel8"}; - // cascade cuts + Configurable cutDoNoPileup{"cutDoNoPileup", true, "choose events with no bunch pileup"}; + Configurable cutDoGoodFT0{"cutDoGoodFT0", true, "choose events with IsGoodZvtxFT0VsPV"}; + Configurable doINELMCGen{"doINELMCGen", true, "apply INEL>0 for gen MC events"}; + Configurable doITSTPCVertexEventCut{"doITSTPCVertexEventCut", true, ">=1 ITS-TPC track"}; + Configurable doNoCollInRofStandardCut{"doNoCollInRofStandardCut", true, "rejects if there are other events within the same ITS ROF with mult above threshold"}; + Configurable doTimeRangeStandardCut{"doTimeRangeStandardCut", true, "rejects if there are events nearby in dtime +/- 2 μs, or mult above some threshold in -4..-2 μs"}; + } eventCuts; + + // cascade selections + struct : ConfigurableGroup { + std::string prefix = "cascadeSelections"; Configurable cutDoPropagateDCA{"cutDoPropagateDCA", false, "choose events with sel8"}; Configurable cutPropDCAtoPVxy{"cutPropDCAtoPVxy", 0.02f, "max cascade dca to PV in xy - propagated"}; Configurable cutPropDCAtoPVz{"cutPropDCAtoPVz", 0.02f, "max cascade dca to PV in z - propagated"}; @@ -118,7 +122,10 @@ struct StrangeCascTrack { Configurable cutMaxV0CosPA{"cutMaxV0CosPA", 1.1f, "max V0 cosPA"}; Configurable cutMinBachCosPA{"cutMinBachCosPA", -1.1f, "min Bachelor cosPA"}; Configurable cutMaxBachCosPA{"cutMaxBachCosPA", 1.1f, "max Bachelor cosPA"}; - Configurable cutMinCascCosPA{"cutMinCascCosPA", 0.995f, "min cascade cosPA"}; + Configurable> cutMinCascCosPaVsPt{ + "cutMinCascCosPaVsPt", + {0.993, 0.993, 0.994, 0.995, 0.996, 0.997, 0.997, 0.998, 0.998, 0.999, 0.999}, + "Min Casc CosPA per pT bin (same binning as axisPt)"}; Configurable cutRapidity{"cutRapidity", 0.5f, "max rapidity"}; Configurable cutDauEta{"cutDauEta", 1.0f, "max eta of dau tracks"}; Configurable cutCompMassRej{"cutCompMassRej", 0.008f, "Competing mass rejection"}; @@ -138,143 +145,17 @@ struct StrangeCascTrack { // TOF PID selection Configurable cutNSigmaTOFXi{"cutNSigmaTOFXi", 3, "cutNSigmaTOFXi"}; Configurable cutNSigmaTOFOmega{"cutNSigmaTOFOmega", 3, "cutNSigmaTOFOmega"}; - } selCuts; - - // axes - struct : ConfigurableGroup { - ConfigurableAxis axisEta{"axisEta", {102, -2.01, 2.01}, "#eta"}; - ConfigurableAxis axisDCAxy{"axisDCAxy", {500, 0., 0.5}, "cm"}; - ConfigurableAxis axisDCAz{"axisDCAz", {500, 0., 0.5}, "cm"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0, 10.0}, "p_{T} (GeV/c)"}; - ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0.0f, 5.0, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 100.0f}, "FT0 mult %"}; - ConfigurableAxis axisOmegaMass{"axisOmegaMass", {2000, 1.6, 1.8}, "#Omega M_{inv} (GeV/c^{2})"}; - ConfigurableAxis axisXiMass{"axisXiMass", {2000, 1.2, 1.4}, "#Xi M_{inv} (GeV/c^{2})"}; - } axesConfig; + } cascCuts; // cascade reconstruction Types static constexpr std::string_view TypeNames[] = {"Standard", "Tracked"}; - // for efficiency and purity corrections - TH1F* hEfficiencyOmegaStd1D; - TH1F* hEfficiencyOmegaTra1D; - TH1F* hEfficiencyXiStd1D; - TH1F* hEfficiencyXiTra1D; - - TH1F* hEfficiencyErrOmegaStd1D; - TH1F* hEfficiencyErrOmegaTra1D; - TH1F* hEfficiencyErrXiStd1D; - TH1F* hEfficiencyErrXiTra1D; - - TH1F* hPurityOmegaStd1D; - TH1F* hPurityOmegaTra1D; - TH1F* hPurityXiStd1D; - TH1F* hPurityXiTra1D; - - TH1F* hPurityErrOmegaStd1D; - TH1F* hPurityErrOmegaTra1D; - TH1F* hPurityErrXiStd1D; - TH1F* hPurityErrXiTra1D; - - TH2F* hEfficiencyOmegaStd2D; - TH2F* hEfficiencyOmegaTra2D; - TH2F* hEfficiencyXiStd2D; - TH2F* hEfficiencyXiTra2D; - - TH2F* hEfficiencyErrOmegaStd2D; - TH2F* hEfficiencyErrOmegaTra2D; - TH2F* hEfficiencyErrXiStd2D; - TH2F* hEfficiencyErrXiTra2D; - - TH2F* hPurityOmegaStd2D; - TH2F* hPurityOmegaTra2D; - TH2F* hPurityXiStd2D; - TH2F* hPurityXiTra2D; - - TH2F* hPurityErrOmegaStd2D; - TH2F* hPurityErrOmegaTra2D; - TH2F* hPurityErrXiStd2D; - TH2F* hPurityErrXiTra2D; - - int mRunNumber; - // loads efficiencies and purities - void initEfficiencyFromCCDB(int64_t runNumber, int64_t timestamp) - { - if (mRunNumber == runNumber) { - return; - } - mRunNumber = runNumber; - LOG(info) << "Loading efficiencies and purities from CCDB for run " << mRunNumber << " now..."; - auto timeStamp = timestamp; - - std::string efficiencyCCDBPath = [&]() { - if (doProcesspp) { - return efficiencyCCDBPathpp; - } else if (doProcesspO) { - return efficiencyCCDBPathpO; - } else if (doProcessPbPb) { - return efficiencyCCDBPathPbPb; - } - return efficiencyCCDBPathOO; - }(); - - TList* listEfficiencies = ccdb->getForTimeStamp(efficiencyCCDBPath, timeStamp); - - if (!listEfficiencies) { - LOG(fatal) << "Problem getting TList object with efficiencies and purities!"; - } - - hEfficiencyOmegaStd1D = static_cast(listEfficiencies->FindObject("Eff_Omega_Standard_byPt")); - hEfficiencyOmegaTra1D = static_cast(listEfficiencies->FindObject("Eff_Omega_Tracked_byPt")); - hEfficiencyXiStd1D = static_cast(listEfficiencies->FindObject("Eff_Xi_Standard_byPt")); - hEfficiencyXiTra1D = static_cast(listEfficiencies->FindObject("Eff_Xi_Tracked_byPt")); - hEfficiencyErrOmegaStd1D = static_cast(listEfficiencies->FindObject("EffErr_Omega_Standard_byPt")); - hEfficiencyErrOmegaTra1D = static_cast(listEfficiencies->FindObject("EffErr_Omega_Tracked_byPt")); - hEfficiencyErrXiStd1D = static_cast(listEfficiencies->FindObject("EffErr_Xi_Standard_byPt")); - hEfficiencyErrXiTra1D = static_cast(listEfficiencies->FindObject("EffErr_Xi_Tracked_byPt")); - hPurityOmegaStd1D = static_cast(listEfficiencies->FindObject("Pur_Omega_Standard_byPt")); - hPurityOmegaTra1D = static_cast(listEfficiencies->FindObject("Pur_Omega_Tracked_byPt")); - hPurityXiStd1D = static_cast(listEfficiencies->FindObject("Pur_Xi_Standard_byPt")); - hPurityXiTra1D = static_cast(listEfficiencies->FindObject("Pur_Xi_Tracked_byPt")); - hPurityErrOmegaStd1D = static_cast(listEfficiencies->FindObject("PurErr_Omega_Standard_byPt")); - hPurityErrOmegaTra1D = static_cast(listEfficiencies->FindObject("PurErr_Omega_Tracked_byPt")); - hPurityErrXiStd1D = static_cast(listEfficiencies->FindObject("PurErr_Xi_Standard_byPt")); - hPurityErrXiTra1D = static_cast(listEfficiencies->FindObject("PurErr_Xi_Tracked_byPt")); - - hEfficiencyOmegaStd2D = static_cast(listEfficiencies->FindObject("Eff_Omega_Standard_byPtMult")); - hEfficiencyOmegaTra2D = static_cast(listEfficiencies->FindObject("Eff_Omega_Tracked_byPtMult")); - hEfficiencyXiStd2D = static_cast(listEfficiencies->FindObject("Eff_Xi_Standard_byPtMult")); - hEfficiencyXiTra2D = static_cast(listEfficiencies->FindObject("Eff_Xi_Tracked_byPtMult")); - hEfficiencyErrOmegaStd2D = static_cast(listEfficiencies->FindObject("EffErr_Omega_Standard_byPtMult")); - hEfficiencyErrOmegaTra2D = static_cast(listEfficiencies->FindObject("EffErr_Omega_Tracked_byPtMult")); - hEfficiencyErrXiStd2D = static_cast(listEfficiencies->FindObject("EffErr_Xi_Standard_byPtMult")); - hEfficiencyErrXiTra2D = static_cast(listEfficiencies->FindObject("EffErr_Xi_Tracked_byPtMult")); - hPurityOmegaStd2D = static_cast(listEfficiencies->FindObject("Pur_Omega_Standard_byPtMult")); - hPurityOmegaTra2D = static_cast(listEfficiencies->FindObject("Pur_Omega_Tracked_byPtMult")); - hPurityXiStd2D = static_cast(listEfficiencies->FindObject("Pur_Xi_Standard_byPtMult")); - hPurityXiTra2D = static_cast(listEfficiencies->FindObject("Pur_Xi_Tracked_byPtMult")); - hPurityErrOmegaStd2D = static_cast(listEfficiencies->FindObject("PurErr_Omega_Standard_byPtMult")); - hPurityErrOmegaTra2D = static_cast(listEfficiencies->FindObject("PurErr_Omega_Tracked_byPtMult")); - hPurityErrXiStd2D = static_cast(listEfficiencies->FindObject("PurErr_Xi_Standard_byPtMult")); - hPurityErrXiTra2D = static_cast(listEfficiencies->FindObject("PurErr_Xi_Tracked_byPtMult")); - - if (doPropagateEfficiency1D && (!hEfficiencyErrOmegaStd1D || !hEfficiencyErrOmegaTra1D || !hEfficiencyErrXiStd1D || !hEfficiencyErrXiTra1D)) - LOG(fatal) << "Problem getting hEfficiencyUncertainty!"; - if (doPropagatePurity1D && (!hPurityErrOmegaStd1D || !hPurityErrOmegaTra1D || !hPurityErrXiStd1D || !hPurityErrXiTra1D)) - LOG(fatal) << "Problem getting hPurityUncertainty!"; - LOG(info) << "Efficiencies and purities now loaded for " << mRunNumber; - - if (doPropagateEfficiency2D && (!hEfficiencyErrOmegaStd2D || !hEfficiencyErrOmegaTra2D || !hEfficiencyErrXiStd2D || !hEfficiencyErrXiTra2D)) - LOG(fatal) << "Problem getting hEfficiencyUncertainty!"; - if (doPropagatePurity2D && (!hPurityErrOmegaStd2D || !hPurityErrOmegaTra2D || !hPurityErrXiStd2D || !hPurityErrXiTra2D)) - LOG(fatal) << "Problem getting hPurityUncertainty!"; - LOG(info) << "Efficiencies and purities now loaded for " << mRunNumber; - } // general info about processed events template void fillEvents(TEvent const& collision) { histos.fill(HIST("NoSel-Events/EvCounter"), 0.5); - double mult = (doProcesspp || doProcesspO) ? collision.centFT0M() : collision.centFT0C(); + double mult = (doProcessIons) ? collision.centFT0C() : collision.centFT0M(); histos.fill(HIST("NoSel-Events/Mult"), mult); double pvx = collision.posX(); double pvy = collision.posY(); @@ -284,23 +165,70 @@ struct StrangeCascTrack { } // checks general selection criteria for collisions template - bool isValidEvent(TEvent collision) + bool isValidEvent(TEvent collision, bool fillHists) { bool passedAllSels = true; - if (!selCuts.cutDoINEL || collision.multNTracksPVeta1() > 0) - histos.fill(HIST("Rec-Events/EvFilter"), 0.5); - else + //* inel>0 cut + if (!eventCuts.cutDoINEL || collision.multNTracksPVeta1() > 0) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 0.5); + } else { passedAllSels = false; - if (std::abs(collision.posZ()) < selCuts.cutZVertex) - histos.fill(HIST("Rec-Events/EvFilter"), 1.5); - else + } + //* pvz cut + if (std::abs(collision.posZ()) < eventCuts.cutZVertex) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 1.5); + } else { passedAllSels = false; - if (!selCuts.cutDoSel8 || collision.sel8()) - histos.fill(HIST("Rec-Events/EvFilter"), 2.5); - else + } + //* sel8 cut + if (!eventCuts.cutDoSel8 || collision.sel8()) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 2.5); + } else { + passedAllSels = false; + } + //* pileup cut + if (!eventCuts.cutDoNoPileup || collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 3.5); + } else { + passedAllSels = false; + } + //* good ft0 z-vertex vs pv cut + if (!eventCuts.cutDoGoodFT0 || collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 4.5); + } else { + passedAllSels = false; + } + //* + if (!eventCuts.doITSTPCVertexEventCut || collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 5.5); + } else { + passedAllSels = false; + } + //* + if (!eventCuts.doNoCollInRofStandardCut || collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 6.5); + } else { + passedAllSels = false; + } + //* + if (!eventCuts.doTimeRangeStandardCut || collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 7.5); + } else { passedAllSels = false; - if (passedAllSels) - histos.fill(HIST("Rec-Events/EvFilter"), 3.5); + } + //* all cuts + if (passedAllSels) { + if (fillHists) + histos.fill(HIST("Rec-Events/EvFilter"), 8.5); + } return passedAllSels; } // checks cascade pt @@ -311,24 +239,23 @@ struct StrangeCascTrack { double ptMin = 0.0; double ptMax = 0.0; if (Type == 1 && particle == "Xi") { - ptMin = selCuts.cutMinPtXiTra; - ptMax = selCuts.cutMaxPtXiTra; + ptMin = cascCuts.cutMinPtXiTra; + ptMax = cascCuts.cutMaxPtXiTra; } if (Type == 1 && particle == "Omega") { - ptMin = selCuts.cutMinPtOmegaTra; - ptMax = selCuts.cutMaxPtOmegaTra; + ptMin = cascCuts.cutMinPtOmegaTra; + ptMax = cascCuts.cutMaxPtOmegaTra; } if (Type == 0 && particle == "Xi") { - ptMin = selCuts.cutMinPtXiStd; - ptMax = selCuts.cutMaxPtXiStd; + ptMin = cascCuts.cutMinPtXiStd; + ptMax = cascCuts.cutMaxPtXiStd; } if (Type == 0 && particle == "Omega") { - ptMin = selCuts.cutMinPtOmegaStd; - ptMax = selCuts.cutMaxPtOmegaStd; + ptMin = cascCuts.cutMinPtOmegaStd; + ptMax = cascCuts.cutMaxPtOmegaStd; } if (cascade.pt() < ptMin || cascade.pt() > ptMax) passedSel = false; - // histos.fill(HIST(Form("%s/Rec/Filters%s", TypeNames[Type].data(), particle)), 0.5); return passedSel; } // checks general selection criteria for cascades @@ -343,7 +270,7 @@ struct StrangeCascTrack { y = std::abs(cascade.yXi()); else y = std::abs(cascade.yOmega()); - if (y > selCuts.cutRapidity) { + if (y > cascCuts.cutRapidity) { passedRapidity = false; passedAllSels = false; } @@ -352,7 +279,7 @@ struct StrangeCascTrack { double bachEta = std::abs(cascade.bacheloreta()); double negEta = std::abs(cascade.negativeeta()); double posEta = std::abs(cascade.positiveeta()); - if (bachEta > selCuts.cutDauEta || negEta > selCuts.cutDauEta || posEta > selCuts.cutDauEta) { + if (bachEta > cascCuts.cutDauEta || negEta > cascCuts.cutDauEta || posEta > cascCuts.cutDauEta) { passedDauEta = false; passedAllSels = false; } @@ -364,40 +291,45 @@ struct StrangeCascTrack { double posCls = posTrack.tpcClusters(); double negCls = negTrack.tpcClusters(); double bachCls = bachTrack.tpcClusters(); - if (posCls < selCuts.cutNClsTPC || negCls < selCuts.cutNClsTPC || bachCls < selCuts.cutNClsTPC) { + if (posCls < cascCuts.cutNClsTPC || negCls < cascCuts.cutNClsTPC || bachCls < cascCuts.cutNClsTPC) { passedTPCCls = false; passedAllSels = false; } // V0 cosPA bool passedV0CosPA = true; double v0cospa = cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); - if (v0cospa < selCuts.cutMinV0CosPA || v0cospa > selCuts.cutMaxV0CosPA) { + if (v0cospa < cascCuts.cutMinV0CosPA || v0cospa > cascCuts.cutMaxV0CosPA) { passedV0CosPA = false; passedAllSels = false; } // Bachelor cosPA bool passedBachCosPA = true; double bachcospa = stdcasc.bachBaryonCosPA(); - if (bachcospa < selCuts.cutMinBachCosPA || bachcospa > selCuts.cutMaxBachCosPA) { + if (bachcospa < cascCuts.cutMinBachCosPA || bachcospa > cascCuts.cutMaxBachCosPA) { passedBachCosPA = false; passedAllSels = false; } // Cascade cosPA bool passedCascCosPA = true; double casccospa = cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()); - if (casccospa < selCuts.cutMinCascCosPA) { + const auto& edges = axesConfig.axisPt.value; + int ptBin = std::upper_bound(edges.begin(), edges.end(), cascade.pt()) - edges.begin() - 1; + if (ptBin < 0 || ptBin >= static_cast(cascCuts.cutMinCascCosPaVsPt->size())) { + ptBin = 1; + } // safety check - if pt bin not determined, default to loosest cut + if (casccospa < cascCuts.cutMinCascCosPaVsPt->at(ptBin)) { passedCascCosPA = false; passedAllSels = false; } // Propagated cacade DCAxy to PV bool passedPropDCAxy = true; - if (selCuts.cutDoPropagateDCA && cascade.dcaXYCascToPV() > selCuts.cutPropDCAtoPVxy) { + if (cascCuts.cutDoPropagateDCA && cascade.dcaXYCascToPV() > cascCuts.cutPropDCAtoPVxy) { passedPropDCAxy = false; passedAllSels = false; } // Propagated cacade DCAz to PV bool passedPropDCAz = true; - if (selCuts.cutDoPropagateDCA && cascade.dcaZCascToPV() > selCuts.cutPropDCAtoPVz) { + if (cascCuts.cutDoPropagateDCA && cascade.dcaZCascToPV() > cascCuts.cutPropDCAtoPVz) { passedPropDCAz = false; passedAllSels = false; } @@ -412,25 +344,25 @@ struct StrangeCascTrack { const auto& negTrack = cascade.template negTrackExtra_as(); const auto& bachTrack = cascade.template bachTrackExtra_as(); if (cascade.sign() < 0) { - if (std::abs(posTrack.tpcNSigmaPr()) > selCuts.cutNSigmaTPCProton) { + if (std::abs(posTrack.tpcNSigmaPr()) > cascCuts.cutNSigmaTPCProton) { passedSel = false; } - if (std::abs(negTrack.tpcNSigmaPi()) > selCuts.cutNSigmaTPCPion) { + if (std::abs(negTrack.tpcNSigmaPi()) > cascCuts.cutNSigmaTPCPion) { passedSel = false; } - if ((particle == "Xi" && std::abs(bachTrack.tpcNSigmaPi()) > selCuts.cutNSigmaTPCPion) || - (particle == "Omega" && std::abs(bachTrack.tpcNSigmaKa()) > selCuts.cutNSigmaTPCKaon)) { + if ((particle == "Xi" && std::abs(bachTrack.tpcNSigmaPi()) > cascCuts.cutNSigmaTPCPion) || + (particle == "Omega" && std::abs(bachTrack.tpcNSigmaKa()) > cascCuts.cutNSigmaTPCKaon)) { passedSel = false; } } else { - if (std::abs(negTrack.tpcNSigmaPr()) > selCuts.cutNSigmaTPCProton) { + if (std::abs(negTrack.tpcNSigmaPr()) > cascCuts.cutNSigmaTPCProton) { passedSel = false; } - if (std::abs(posTrack.tpcNSigmaPi()) > selCuts.cutNSigmaTPCPion) { + if (std::abs(posTrack.tpcNSigmaPi()) > cascCuts.cutNSigmaTPCPion) { passedSel = false; } - if ((particle == "Xi" && std::abs(bachTrack.tpcNSigmaPi()) > selCuts.cutNSigmaTPCPion) || - (particle == "Omega" && std::abs(bachTrack.tpcNSigmaKa()) > selCuts.cutNSigmaTPCKaon)) { + if ((particle == "Xi" && std::abs(bachTrack.tpcNSigmaPi()) > cascCuts.cutNSigmaTPCPion) || + (particle == "Omega" && std::abs(bachTrack.tpcNSigmaKa()) > cascCuts.cutNSigmaTPCKaon)) { passedSel = false; } } @@ -442,9 +374,9 @@ struct StrangeCascTrack { { bool passedSel = true; if (particle == "Xi") - passedSel = cascade.tofXiCompatibility(selCuts.cutNSigmaTOFXi); + passedSel = cascade.tofXiCompatibility(cascCuts.cutNSigmaTOFXi); if (particle == "Omega") - passedSel = cascade.tofOmegaCompatibility(selCuts.cutNSigmaTOFOmega); + passedSel = cascade.tofOmegaCompatibility(cascCuts.cutNSigmaTOFOmega); return passedSel; } // checks whether gen cascade corresponds to PDG code @@ -473,29 +405,7 @@ struct StrangeCascTrack { } return false; } - // applies purities and efficiencies - void fillHist(std::shared_ptr hist, double binFillThn[], float efficiency, float effUncert, float purity, float purityUncert) - { - float previousContent, previousError2, currentContent, currentError2; - int bin = hist->GetBin(binFillThn); - previousContent = hist->GetBinContent(bin); - previousError2 = hist->GetBinError2(bin); - currentContent = previousContent + purity / (efficiency); - currentError2 = previousError2 + std::pow(purity / (efficiency), 2) + std::pow(purityUncert / (efficiency), 2) + std::pow(effUncert * purity, 2) / std::pow(efficiency, 4); - hist->SetBinContent(bin, currentContent); - hist->SetBinError2(bin, currentError2); - } - // calculates DCA from cosPA - template - double calculateDCA(TEvent collision, double cosPA, double decX, double decY, double decZ) - { - double pvX = collision.posX(); - double pvY = collision.posX(); - double pvZ = collision.posX(); - double sinPA = std::sqrt(1 - cosPA * cosPA); - double dca = sinPA * std::sqrt(std::pow(decX - pvX, 2) + std::pow(decY - pvY, 2) + std::pow(decZ - pvZ, 2)); - return dca; - } + // applies selections for and fills histograms template void analyseCascs(TEvent collision, TCascs cascades) @@ -530,152 +440,7 @@ struct StrangeCascTrack { } }(); - float efficiencyOmega = 1.0f; - float efficiencyXi = 1.0f; - float efficiencyOmegaErr = 0.0f; - float efficiencyXiErr = 0.0f; - float purityOmega = 1.0f; - float purityXi = 1.0f; - float purityOmegaErr = 0.0f; - float purityXiErr = 0.0f; - - double mult = (doProcesspp || doProcesspO) ? collision.centFT0M() : collision.centFT0C(); // ion collisions use FT0C for multiplicity, pp uses both - - if (doApplyEfficiency1D) { - if constexpr (requires { cascade.topologyChi2(); }) { - efficiencyOmega = hEfficiencyOmegaTra1D->Interpolate(cascade.pt()); - efficiencyXi = hEfficiencyXiTra1D->Interpolate(cascade.pt()); - if (doPropagateEfficiency1D) { - efficiencyOmegaErr = hEfficiencyErrOmegaTra1D->Interpolate(cascade.pt()); - efficiencyXiErr = hEfficiencyErrXiTra1D->Interpolate(cascade.pt()); - } - if (efficiencyOmega == 0) { // check for zero efficiency, do not apply if the case - efficiencyOmega = 1.; - efficiencyOmegaErr = 0.; - } - if (efficiencyXi == 0) { // check for zero efficiency, do not apply if the case - efficiencyXi = 1.; - efficiencyXiErr = 0.; - } - } else { - efficiencyOmega = hEfficiencyOmegaStd1D->Interpolate(cascade.pt()); - efficiencyXi = hEfficiencyXiStd1D->Interpolate(cascade.pt()); - if (doPropagateEfficiency1D) { - efficiencyOmegaErr = hEfficiencyErrOmegaStd1D->Interpolate(cascade.pt()); - efficiencyXiErr = hEfficiencyErrXiStd1D->Interpolate(cascade.pt()); - } - if (efficiencyOmega == 0) { // check for zero efficiency, do not apply if the case - efficiencyOmega = 1.; - efficiencyOmegaErr = 0.; - } - if (efficiencyXi == 0) { // check for zero efficiency, do not apply if the case - efficiencyXi = 1.; - efficiencyXiErr = 0.; - } - } - } - - if (doApplyEfficiency2D) { - if constexpr (requires { cascade.topologyChi2(); }) { - efficiencyOmega = hEfficiencyOmegaTra2D->Interpolate(cascade.pt(), mult); - efficiencyXi = hEfficiencyXiTra2D->Interpolate(cascade.pt(), mult); - if (doPropagateEfficiency2D) { - efficiencyOmegaErr = hEfficiencyErrOmegaTra2D->Interpolate(cascade.pt(), mult); - efficiencyXiErr = hEfficiencyErrXiTra2D->Interpolate(cascade.pt(), mult); - } - if (efficiencyOmega == 0) { // check for zero efficiency, do not apply if the case - efficiencyOmega = 1.; - efficiencyOmegaErr = 0.; - } - if (efficiencyXi == 0) { // check for zero efficiency, do not apply if the case - efficiencyXi = 1.; - efficiencyXiErr = 0.; - } - } else { - efficiencyOmega = hEfficiencyOmegaStd2D->Interpolate(cascade.pt(), mult); - efficiencyXi = hEfficiencyXiStd2D->Interpolate(cascade.pt(), mult); - if (doPropagateEfficiency2D) { - efficiencyOmegaErr = hEfficiencyErrOmegaStd2D->Interpolate(cascade.pt(), mult); - efficiencyXiErr = hEfficiencyErrXiStd2D->Interpolate(cascade.pt(), mult); - } - if (efficiencyOmega == 0) { // check for zero efficiency, do not apply if the case - efficiencyOmega = 1.; - efficiencyOmegaErr = 0.; - } - if (efficiencyXi == 0) { // check for zero efficiency, do not apply if the case - efficiencyXi = 1.; - efficiencyXiErr = 0.; - } - } - } - - if (doApplyPurity1D) { - if constexpr (requires { cascade.topologyChi2(); }) { - purityOmega = hPurityOmegaTra1D->Interpolate(cascade.pt()); - purityXi = hPurityXiTra1D->Interpolate(cascade.pt()); - if (doPropagatePurity1D) { - purityOmegaErr = hPurityErrOmegaTra1D->Interpolate(cascade.pt()); - purityXiErr = hPurityErrXiTra1D->Interpolate(cascade.pt()); - } - if (purityOmega == 0) { // check for zero purity, do not apply if the case - purityOmega = 1.; - purityOmegaErr = 0.; - } - if (purityXi == 0) { // check for zero purity, do not apply if the case - purityXi = 1.; - purityXiErr = 0.; - } - } else { - purityOmega = hPurityOmegaStd1D->Interpolate(cascade.pt()); - purityXi = hPurityXiStd1D->Interpolate(cascade.pt()); - if (doPropagatePurity1D) { - purityOmegaErr = hPurityErrOmegaStd1D->Interpolate(cascade.pt()); - purityXiErr = hPurityErrXiStd1D->Interpolate(cascade.pt()); - } - if (purityOmega == 0) { // check for zero purity, do not apply if the case - purityOmega = 1.; - purityOmegaErr = 0.; - } - if (purityXi == 0) { // check for zero purity, do not apply if the case - purityXi = 1.; - purityXiErr = 0.; - } - } - } - - if (doApplyPurity2D) { - if constexpr (requires { cascade.topologyChi2(); }) { - purityOmega = hPurityOmegaTra2D->Interpolate(cascade.pt(), mult); - purityXi = hPurityXiTra2D->Interpolate(cascade.pt(), mult); - if (doPropagatePurity2D) { - purityOmegaErr = hPurityErrOmegaTra2D->Interpolate(cascade.pt(), mult); - purityXiErr = hPurityErrXiTra2D->Interpolate(cascade.pt(), mult); - } - if (purityOmega == 0) { // check for zero purity, do not apply if the case - purityOmega = 1.; - purityOmegaErr = 0.; - } - if (purityXi == 0) { // check for zero purity, do not apply if the case - purityXi = 1.; - purityXiErr = 0.; - } - } else { - purityOmega = hPurityOmegaStd2D->Interpolate(cascade.pt(), mult); - purityXi = hPurityXiStd2D->Interpolate(cascade.pt(), mult); - if (doPropagatePurity2D) { - purityOmegaErr = hPurityErrOmegaStd2D->Interpolate(cascade.pt(), mult); - purityXiErr = hPurityErrXiStd2D->Interpolate(cascade.pt(), mult); - } - if (purityOmega == 0) { // check for zero purity, do not apply if the case - purityOmega = 1.; - purityOmegaErr = 0.; - } - if (purityXi == 0) { // check for zero purity, do not apply if the case - purityXi = 1.; - purityXiErr = 0.; - } - } - } + double mult = (doProcessIons) ? collision.centFT0C() : collision.centFT0M(); // ion collisions use FT0C for multiplicity, pp uses both // fill multiplicity for events with >=1 cascade if (collision.index() != casccollid) { @@ -693,19 +458,20 @@ struct StrangeCascTrack { double pt = cascade.pt(); double v0cosPA = cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); double casccosPA = cascade.casccosPA(collision.posX(), collision.posY(), collision.posZ()); - double calcDCA = calculateDCA(collision, casccosPA, cascade.x(), cascade.y(), cascade.z()); double bachEta = cascade.bacheloreta(); double negEta = cascade.negativeeta(); double posEta = cascade.positiveeta(); + // fill filters for no cascade selections histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/PropDCAxy"), cascade.dcaXYCascToPV()); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/PropDCAz"), cascade.dcaZCascToPV()); - histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/CalcDCA"), calcDCA); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/BachCosPA"), stdCasc.bachBaryonCosPA()); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/V0CosPA"), v0cosPA); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/CascCosPA"), casccosPA); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/RapidityXi"), cascade.yXi()); + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/PtVsRapidityXi"), pt, cascade.yXi()); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/RapidityOmega"), cascade.yOmega()); + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/PtVsRapidityOmega"), pt, cascade.yOmega()); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/EtaDau"), bachEta); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/EtaDau"), negEta); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/Filters/EtaDau"), posEta); @@ -717,7 +483,6 @@ struct StrangeCascTrack { if (isMCTruth(stdCasc, "Xi") || isMCTruth(stdCasc, "Omega")) { histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/Filters/PropDCAxy"), cascade.dcaXYCascToPV()); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/Filters/PropDCAz"), cascade.dcaZCascToPV()); - histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/Filters/CalcDCA"), calcDCA); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/Filters/BachCosPA"), stdCasc.bachBaryonCosPA()); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/Filters/V0CosPA"), v0cosPA); histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/Filters/CascCosPA"), casccosPA); @@ -843,7 +608,7 @@ struct StrangeCascTrack { } // apply competing mass rej if (doCompetingMassRej) { - if ((std::abs(massXi - o2::constants::physics::MassXiMinus) > selCuts.cutCompMassRej)) { + if ((std::abs(massXi - o2::constants::physics::MassXiMinus) > cascCuts.cutCompMassRej)) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/FiltersOmega"), 4.5); if (fillTruthOmega) histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/FiltersOmega"), 4.5); @@ -857,22 +622,24 @@ struct StrangeCascTrack { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/EvMult"), mult); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/PropDCAxy"), cascade.dcaXYCascToPV()); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/PropDCAz"), cascade.dcaZCascToPV()); - histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/CalcDCA"), calcDCA); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/BachCosPA"), stdCasc.bachBaryonCosPA()); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/V0CosPA"), v0cosPA); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/CascCosPA"), casccosPA); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/EtaDau"), bachEta); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/EtaDau"), negEta); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/EtaDau"), posEta); - if (passedAllSelsXi) + if (passedAllSelsXi) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/RapidityXi"), cascade.yXi()); - if (passedAllSelsOmega) + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/PtVsRapidityXi"), pt, cascade.yXi()); + } + if (passedAllSelsOmega) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/RapidityOmega"), cascade.yOmega()); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Filters/PtVsRapidityOmega"), pt, cascade.yOmega()); + } if (fillTruthXi || fillTruthOmega) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/EvMult"), mult); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/PropDCAxy"), cascade.dcaXYCascToPV()); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/PropDCAz"), cascade.dcaZCascToPV()); - histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/CalcDCA"), calcDCA); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/BachCosPA"), stdCasc.bachBaryonCosPA()); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/V0CosPA"), v0cosPA); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/CascCosPA"), casccosPA); @@ -885,46 +652,83 @@ struct StrangeCascTrack { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Filters/RapidityOmega"), cascade.yOmega()); } } - double binFillXi[3] = {massXi, pt, mult}; if (passedAllSelsXi) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/FiltersXi"), 4.5); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/MassXi"), massXi); - fillHist(histos.get(HIST(TypeNames[Type]) + HIST("/Rec/Xi")), binFillXi, efficiencyXi, efficiencyXiErr, purityXi, purityXiErr); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Xi"), massXi, pt, mult); // fill for particle-antiparticle type if (cascade.sign() < 0) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/MassXiMinus"), massXi); - fillHist(histos.get(HIST(TypeNames[Type]) + HIST("/Rec/XiMinus")), binFillXi, efficiencyXi, efficiencyXiErr, purityXi, purityXiErr); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/XiMinus"), massXi, pt, mult); } if (cascade.sign() > 0) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/MassXiPlus"), massXi); - fillHist(histos.get(HIST(TypeNames[Type]) + HIST("/Rec/XiPlus")), binFillXi, efficiencyXi, efficiencyXiErr, purityXi, purityXiErr); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/XiPlus"), massXi, pt, mult); } // fill truth if (fillTruthXi) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/FiltersXi"), 4.5); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/MassXi"), massXi); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Xi"), massXi, pt, mult); + // + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/RapCheck_TH3_Truth_Xi"), pt, mult, cascade.yXi()); } } - double binFillOmega[3] = {massOmega, pt, mult}; if (passedAllSelsOmega) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/FiltersOmega"), 5.5); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/MassOmega"), massOmega); - fillHist(histos.get(HIST(TypeNames[Type]) + HIST("/Rec/Omega")), binFillOmega, efficiencyOmega, efficiencyOmegaErr, purityOmega, purityOmegaErr); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Xi"), massXi, pt, mult); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/Omega"), massOmega, pt, mult); // fill for particle-antiparticle type if (cascade.sign() < 0) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/MassOmegaMinus"), massOmega); - fillHist(histos.get(HIST(TypeNames[Type]) + HIST("/Rec/OmegaMinus")), binFillOmega, efficiencyOmega, efficiencyOmegaErr, purityOmega, purityOmegaErr); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/OmegaMinus"), massOmega, pt, mult); } if (cascade.sign() > 0) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/MassOmegaPlus"), massOmega); - fillHist(histos.get(HIST(TypeNames[Type]) + HIST("/Rec/OmegaPlus")), binFillOmega, efficiencyOmega, efficiencyOmegaErr, purityOmega, purityOmegaErr); + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/OmegaPlus"), massOmega, pt, mult); } // fill truth if (fillTruthOmega) { histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/FiltersOmega"), 5.5); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/MassOmega"), massOmega); histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/Omega"), massOmega, pt, mult); + // + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/RapCheck_TH3_Truth_Omega"), pt, mult, cascade.yOmega()); + } + } + + // statistics - compare gen and reco pt and rapidity + if constexpr (requires { collision.straMCCollisionId(); }) { + if constexpr (requires { stdCasc.has_cascMCCore(); }) { + auto cascmccore = stdCasc.template cascMCCore_as(); + double genPt = cascmccore.ptMC(); + double genYXi = cascmccore.rapidityMC(0); + double genYOmega = cascmccore.rapidityMC(2); + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/GenRecPt"), genPt, pt); + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/GenRecRapidityXi"), genYXi, cascade.yXi()); + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel/GenRecRapidityOmega"), genYOmega, cascade.yOmega()); + if (fillTruthXi || fillTruthOmega) + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/GenRecPt"), genPt, pt); + if (passedAllSelsOmega || passedAllSelsXi) { + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/GenRecPt"), genPt, pt); + if (fillTruthXi || fillTruthOmega) + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/GenRecPt"), genPt, pt); + } + if (fillTruthXi) + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/GenRecRapidityXi"), genYXi, cascade.yXi()); + if (passedAllSelsXi) { + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/GenRecRapidityXi"), genYXi, cascade.yXi()); + if (fillTruthXi) + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/GenRecRapidityXi"), genYXi, cascade.yXi()); + } + if (fillTruthOmega) + histos.fill(HIST(TypeNames[Type]) + HIST("/NoSel-Truth/GenRecRapidityOmega"), genYOmega, cascade.yOmega()); + if (passedAllSelsOmega) { + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec/GenRecRapidityOmega"), genYOmega, cascade.yOmega()); + if (fillTruthOmega) + histos.fill(HIST(TypeNames[Type]) + HIST("/Rec-Truth/GenRecRapidityOmega"), genYOmega, cascade.yOmega()); + } } } } @@ -932,6 +736,10 @@ struct StrangeCascTrack { void init(InitContext const&) { + // check if cut configuration is valid + if (cascCuts.cutMinCascCosPaVsPt->size() != axesConfig.axisPt.value.size() - 1) { + LOGF(fatal, "cutMinCascCosPaVsPt size does not match axisPt binning"); + } // for all events processing histos.add("NoSel-Events/EvCounter", "Event Counter", kTH1D, {{1, 0, 1}}); histos.add("NoSel-Events/PVxy", "PV xy position", kTH2D, {{200, -0.1, 0.1}, {200, -0.1, 0.1}}); @@ -942,30 +750,38 @@ struct StrangeCascTrack { histos.add("Rec-Events/PVxy", "PV xy position", kTH2D, {{200, -0.1, 0.1}, {200, -0.1, 0.1}}); histos.add("Rec-Events/PVz", "PV z position", kTH1D, {{100, -20, 20}}); histos.add("Rec-Events/Mult", "Multiplicity", kTH1D, {axesConfig.axisMult}); - histos.add("Rec-Events/EvFilter", "Event Filter", kTH1D, {{4, 0, 4}}); + histos.add("Rec-Events/EvFilter", "Event Filter", kTH1D, {{9, 0, 9}}); histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(1, "INEL>0"); histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(2, "PVz cut"); histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(3, "sel8"); - histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(4, "all"); + histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(4, "NoSameBunchPileup"); + histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(5, "IsGoodZvtxFT0VsPV"); + histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(6, "ITSTPCVertexEventCut"); + histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(7, "NoCollInRofStandardCut"); + histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(8, "TimeRangeStandardCut"); + histos.get(HIST("Rec-Events/EvFilter"))->GetXaxis()->SetBinLabel(9, "all"); // for cascade processing static_for<0, 1>([&](auto Type) { // no selections applied histos.add(Form("%s/NoSel/Filters/PropDCAxy", TypeNames[Type].data()), "DCA to xy (propagated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/NoSel/Filters/PropDCAz", TypeNames[Type].data()), "DCA to z (propagated)", kTH1D, {axesConfig.axisDCAz}); - histos.add(Form("%s/NoSel/Filters/CalcDCA", TypeNames[Type].data()), "DCA (calculated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/NoSel/Filters/BachCosPA", TypeNames[Type].data()), "Bachelor cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/NoSel/Filters/V0CosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/NoSel/Filters/CascCosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/NoSel/Filters/RapidityXi", TypeNames[Type].data()), "y under Xi hypothesis", kTH1D, {{200, -1.0, 1.0}}); + histos.add(Form("%s/NoSel/Filters/PtVsRapidityXi", TypeNames[Type].data()), "pt vs y under Xi hypothesis", kTH2D, {axesConfig.axisPt, {200, -1.0, 1.0}}); histos.add(Form("%s/NoSel/Filters/RapidityOmega", TypeNames[Type].data()), "y under Omega hypothesis", kTH1D, {{200, -1.0, 1.0}}); + histos.add(Form("%s/NoSel/Filters/PtVsRapidityOmega", TypeNames[Type].data()), "pt vs y under Xi hypothesis", kTH2D, {axesConfig.axisPt, {200, -1.0, 1.0}}); histos.add(Form("%s/NoSel/Filters/EtaDau", TypeNames[Type].data()), "|#eta| of dau tracks", kTH1D, {axesConfig.axisEta}); histos.add(Form("%s/NoSel/EvMult", TypeNames[Type].data()), "Multiplicity of events with >=1 cascade", kTH1D, {axesConfig.axisMult}); + histos.add(Form("%s/NoSel/GenRecPt", TypeNames[Type].data()), "Generated vs reconstructed pt", kTH2D, {axesConfig.axisPt, axesConfig.axisPt}); + histos.add(Form("%s/NoSel/GenRecRapidityXi", TypeNames[Type].data()), "Generated vs reconstructed y (Xi)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); + histos.add(Form("%s/NoSel/GenRecRapidityOmega", TypeNames[Type].data()), "Generated vs reconstructed y (Omega)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); histos.add(Form("%s/NoSel/MassXi", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisXiMass}); histos.add(Form("%s/NoSel/MassOmega", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); // mc truth for no selectrion histos.add(Form("%s/NoSel-Truth/Filters/PropDCAxy", TypeNames[Type].data()), "DCA to xy (propagated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/NoSel-Truth/Filters/PropDCAz", TypeNames[Type].data()), "DCA to z (propagated)", kTH1D, {axesConfig.axisDCAz}); - histos.add(Form("%s/NoSel-Truth/Filters/CalcDCA", TypeNames[Type].data()), "DCA (calculated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/NoSel-Truth/Filters/BachCosPA", TypeNames[Type].data()), "Bachelor cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/NoSel-Truth/Filters/V0CosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/NoSel-Truth/Filters/CascCosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); @@ -973,74 +789,103 @@ struct StrangeCascTrack { histos.add(Form("%s/NoSel-Truth/Filters/RapidityOmega", TypeNames[Type].data()), "y under Omega hypothesis", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/NoSel-Truth/Filters/EtaDau", TypeNames[Type].data()), "|#eta| of dau tracks", kTH1D, {axesConfig.axisEta}); histos.add(Form("%s/NoSel-Truth/EvMult", TypeNames[Type].data()), "Multiplicity of events with >=1 cascade", kTH1D, {axesConfig.axisMult}); + histos.add(Form("%s/NoSel-Truth/GenRecPt", TypeNames[Type].data()), "Generated vs reconstructed pt", kTH2D, {axesConfig.axisPt, axesConfig.axisPt}); + histos.add(Form("%s/NoSel-Truth/GenRecRapidityXi", TypeNames[Type].data()), "Generated vs reconstructed y (Xi)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); + histos.add(Form("%s/NoSel-Truth/GenRecRapidityOmega", TypeNames[Type].data()), "Generated vs reconstructed y (Omega)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); histos.add(Form("%s/NoSel-Truth/MassXi", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisXiMass}); histos.add(Form("%s/NoSel-Truth/MassOmega", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); // xi and omega selection statistics - histos.add(Form("%s/Rec/FiltersXi", TypeNames[Type].data()), "main cascade filters for Xi", kTH1D, {{5, 0, 5}}); - histos.add(Form("%s/Rec/GenFiltersXi", TypeNames[Type].data()), "general cascade filters for Xi", kTH1D, {{9, 0, 9}}); - histos.add(Form("%s/Rec/FiltersOmega", TypeNames[Type].data()), "main cascade filters for Omega", kTH1D, {{6, 0, 6}}); - histos.add(Form("%s/Rec/GenFiltersOmega", TypeNames[Type].data()), "general cascade filters for Omega", kTH1D, {{9, 0, 9}}); histos.add(Form("%s/Rec/Filters/PropDCAxy", TypeNames[Type].data()), "DCA to xy (propagated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/Rec/Filters/PropDCAz", TypeNames[Type].data()), "DCA to z (propagated)", kTH1D, {axesConfig.axisDCAz}); - histos.add(Form("%s/Rec/Filters/CalcDCA", TypeNames[Type].data()), "DCA (calculated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/Rec/Filters/BachCosPA", TypeNames[Type].data()), "Bachelor cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec/Filters/V0CosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec/Filters/CascCosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec/Filters/RapidityXi", TypeNames[Type].data()), "y under Xi hypothesis", kTH1D, {{200, -1.0, 1.0}}); + histos.add(Form("%s/Rec/Filters/PtVsRapidityXi", TypeNames[Type].data()), "pt vs y under Xi hypothesis", kTH2D, {axesConfig.axisPt, {200, -1.0, 1.0}}); histos.add(Form("%s/Rec/Filters/RapidityOmega", TypeNames[Type].data()), "y under Omega hypothesis", kTH1D, {{200, -1.0, 1.0}}); + histos.add(Form("%s/Rec/Filters/PtVsRapidityOmega", TypeNames[Type].data()), "pt vs y under Omega hypothesis", kTH2D, {axesConfig.axisPt, {200, -1.0, 1.0}}); histos.add(Form("%s/Rec/Filters/EtaDau", TypeNames[Type].data()), "|#eta| of dau tracks", kTH1D, {axesConfig.axisEta}); - // passed all applied sels - histos.add(Form("%s/Rec/EvMult", TypeNames[Type].data()), "Multiplicity of events with >=1 cascade", kTH1D, {axesConfig.axisMult}); + histos.add(Form("%s/Rec/EvMult", TypeNames[Type].data()), "Multiplicity of events with >=1 selected cascade", kTH1D, {axesConfig.axisMult}); + histos.add(Form("%s/Rec/GenRecPt", TypeNames[Type].data()), "Generated vs reconstructed pt", kTH2D, {axesConfig.axisPt, axesConfig.axisPt}); + histos.add(Form("%s/Rec/GenRecRapidityXi", TypeNames[Type].data()), "Generated vs reconstructed y (Xi)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); + histos.add(Form("%s/Rec/GenRecRapidityOmega", TypeNames[Type].data()), "Generated vs reconstructed y (Omega)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); + // selected xi + histos.add(Form("%s/Rec/FiltersXi", TypeNames[Type].data()), "main cascade filters for Xi", kTH1D, {{5, 0, 5}}); + histos.add(Form("%s/Rec/GenFiltersXi", TypeNames[Type].data()), "general cascade filters for Xi", kTH1D, {{9, 0, 9}}); histos.add(Form("%s/Rec/MassXi", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisXiMass}); - histos.add(Form("%s/Rec/MassOmega", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); - histos.add(Form("%s/Rec/Xi", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); - histos.add(Form("%s/Rec/Omega", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); histos.add(Form("%s/Rec/MassXiMinus", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisXiMass}); - histos.add(Form("%s/Rec/MassOmegaMinus", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); - histos.add(Form("%s/Rec/XiMinus", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); - histos.add(Form("%s/Rec/OmegaMinus", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); histos.add(Form("%s/Rec/MassXiPlus", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisXiMass}); + histos.add(Form("%s/Rec/Xi", TypeNames[Type].data()), "", kTHnSparseD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); + histos.add(Form("%s/Rec/XiMinus", TypeNames[Type].data()), "", kTHnSparseD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); + histos.add(Form("%s/Rec/XiPlus", TypeNames[Type].data()), "", kTHnSparseD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); + // selected omega + histos.add(Form("%s/Rec/FiltersOmega", TypeNames[Type].data()), "main cascade filters for Omega", kTH1D, {{6, 0, 6}}); + histos.add(Form("%s/Rec/GenFiltersOmega", TypeNames[Type].data()), "general cascade filters for Omega", kTH1D, {{9, 0, 9}}); + histos.add(Form("%s/Rec/MassOmega", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); + histos.add(Form("%s/Rec/MassOmegaMinus", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); histos.add(Form("%s/Rec/MassOmegaPlus", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); - histos.add(Form("%s/Rec/XiPlus", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); - histos.add(Form("%s/Rec/OmegaPlus", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); + histos.add(Form("%s/Rec/Omega", TypeNames[Type].data()), "", kTHnSparseD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); + histos.add(Form("%s/Rec/OmegaMinus", TypeNames[Type].data()), "", kTHnSparseD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); + histos.add(Form("%s/Rec/OmegaPlus", TypeNames[Type].data()), "", kTHnSparseD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); // mc truth for all passed selections // xi and omega truth selection statistics - histos.add(Form("%s/Rec-Truth/FiltersXi", TypeNames[Type].data()), "main cascade filters for Xi", kTH1D, {{5, 0, 5}}); - histos.add(Form("%s/Rec-Truth/GenFiltersXi", TypeNames[Type].data()), "general cascade filters for Xi", kTH1D, {{9, 0, 9}}); - histos.add(Form("%s/Rec-Truth/FiltersOmega", TypeNames[Type].data()), "main cascade filters for Omega", kTH1D, {{6, 0, 6}}); - histos.add(Form("%s/Rec-Truth/GenFiltersOmega", TypeNames[Type].data()), "general cascade filters for Omega", kTH1D, {{9, 0, 9}}); histos.add(Form("%s/Rec-Truth/Filters/PropDCAxy", TypeNames[Type].data()), "DCA to xy (propagated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/Rec-Truth/Filters/PropDCAz", TypeNames[Type].data()), "DCA to z (propagated)", kTH1D, {axesConfig.axisDCAz}); - histos.add(Form("%s/Rec-Truth/Filters/CalcDCA", TypeNames[Type].data()), "DCA (calculated)", kTH1D, {axesConfig.axisDCAxy}); histos.add(Form("%s/Rec-Truth/Filters/BachCosPA", TypeNames[Type].data()), "Bachelor cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec-Truth/Filters/V0CosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec-Truth/Filters/CascCosPA", TypeNames[Type].data()), "V0 cosPA", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec-Truth/Filters/RapidityXi", TypeNames[Type].data()), "y under Xi hypothesis", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec-Truth/Filters/RapidityOmega", TypeNames[Type].data()), "y under Omega hypothesis", kTH1D, {{200, -1.0, 1.0}}); histos.add(Form("%s/Rec-Truth/Filters/EtaDau", TypeNames[Type].data()), "|#eta| of dau tracks", kTH1D, {axesConfig.axisEta}); - // truth that passed all sels histos.add(Form("%s/Rec-Truth/EvMult", TypeNames[Type].data()), "Multiplicity of events with >=1 cascade", kTH1D, {axesConfig.axisMult}); + histos.add(Form("%s/Rec-Truth/GenRecPt", TypeNames[Type].data()), "Generated vs reconstructed pt", kTH2D, {axesConfig.axisPt, axesConfig.axisPt}); + histos.add(Form("%s/Rec-Truth/GenRecRapidityXi", TypeNames[Type].data()), "Generated vs reconstructed y (Xi)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); + histos.add(Form("%s/Rec-Truth/GenRecRapidityOmega", TypeNames[Type].data()), "Generated vs reconstructed y (Omega)", kTH2D, {{200, -1.0, 1.0}, {200, -1.0, 1.0}}); + histos.add(Form("%s/Rec-Truth/FiltersXi", TypeNames[Type].data()), "main cascade filters for Xi", kTH1D, {{5, 0, 5}}); + histos.add(Form("%s/Rec-Truth/GenFiltersXi", TypeNames[Type].data()), "general cascade filters for Xi", kTH1D, {{9, 0, 9}}); histos.add(Form("%s/Rec-Truth/MassXi", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisXiMass}); + histos.add(Form("%s/Rec-Truth/Xi", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); + histos.add(Form("%s/Rec-Truth/FiltersOmega", TypeNames[Type].data()), "main cascade filters for Omega", kTH1D, {{6, 0, 6}}); + histos.add(Form("%s/Rec-Truth/GenFiltersOmega", TypeNames[Type].data()), "general cascade filters for Omega", kTH1D, {{9, 0, 9}}); histos.add(Form("%s/Rec-Truth/MassOmega", TypeNames[Type].data()), "Invariant mass hypothesis", kTH1D, {axesConfig.axisOmegaMass}); histos.add(Form("%s/Rec-Truth/Omega", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisOmegaMass, axesConfig.axisPt, axesConfig.axisMult}); - histos.add(Form("%s/Rec-Truth/Xi", TypeNames[Type].data()), "", kTHnD, {axesConfig.axisXiMass, axesConfig.axisPt, axesConfig.axisMult}); + /// + histos.add(Form("%s/Rec-Truth/RapCheck_TH3_Truth_Xi", TypeNames[Type].data()), "Rapidity check (pt, mult, y)", kTHnD, {axesConfig.axisPt, axesConfig.axisMult, {200, -1.0, 1.0}}); + histos.add(Form("%s/Rec-Truth/RapCheck_TH3_Truth_Omega", TypeNames[Type].data()), "Rapidity check (pt, mult, y)", kTHnD, {axesConfig.axisPt, axesConfig.axisMult, {200, -1.0, 1.0}}); }); // for MC-specific processing + // all generated events: histos.add("MC/Gen/EvCounter", "Event Counter", kTH1D, {{1, 0, 1}}); - histos.add("MC/Gen/Xi", "Xi", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated Xis - histos.add("MC/Gen/Omega", "Omega", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated Omegas - histos.add("MC/Gen/PrimaryXi", "Xi primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis - histos.add("MC/Gen/PrimaryOmega", "Omega primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas - histos.add("MC/Gen/PrimaryXiRapidity", "Xi primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis in selected rapidity range - histos.add("MC/Gen/PrimaryOmegaRapidity", "Omega primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas in selected rapidity range - histos.add("MC/Gen/PrimaryXiMinus", "Xi- primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis - histos.add("MC/Gen/PrimaryOmegaMinus", "Omega- primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas - histos.add("MC/Gen/PrimaryXiMinusRapidity", "Xi- primaries in |y| ", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis in selected rapidity range - histos.add("MC/Gen/PrimaryOmegaMinusRapidity", "Omega- primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas in selected rapidity range - histos.add("MC/Gen/PrimaryXiPlus", "Xi+ primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis - histos.add("MC/Gen/PrimaryOmegaPlus", "Omega+ primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas - histos.add("MC/Gen/PrimaryXiPlusRapidity", "Xi+ primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis in selected rapidity range - histos.add("MC/Gen/PrimaryOmegaPlusRapidity", "Omega+ primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas in selected rapidity range + histos.add("MC/Gen/Mult", "Event charged multiplicty (all gen events)", kTH1D, {{1600, 0, 3200}}); + histos.add("MC/Gen/RapidityXi", "Generated y (Xi)", kTH1D, {{200, -1.0, 1.0}}); + histos.add("MC/Gen/Xi", "Xi", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated Xis + histos.add("MC/Gen/PrimaryXi", "Xi primaries", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Xis + histos.add("MC/Gen/PrimaryXiRapidity", "Xi primaries in |y|", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Xis in selected rapidity range + histos.add("MC/Gen/PrimaryXiMinusRapidity", "Xi- primaries in |y| ", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Xi-minus in selected rapidity range + histos.add("MC/Gen/PrimaryXiPlusRapidity", "Xi+ primaries in |y|", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Xi-plus in selected rapidity range + histos.add("MC/Gen/RapidityOmega", "Generated y (Omega)", kTH1D, {{200, -1.0, 1.0}}); + histos.add("MC/Gen/Omega", "Omega", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated Omegas + histos.add("MC/Gen/PrimaryOmega", "Omega primaries", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Omegas + histos.add("MC/Gen/PrimaryOmegaRapidity", "Omega primaries in |y|", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Omegas in selected rapidity range + histos.add("MC/Gen/PrimaryOmegaMinusRapidity", "Omega- primaries in |y| ", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Omega-minus in selected rapidity range + histos.add("MC/Gen/PrimaryOmegaPlusRapidity", "Omega+ primaries in |y|", kTH2D, {{1600, 0, 3200}, {100, 0.0, 10.0}}); // generated primary Omega-plus in selected rapidity range + // generated events with reco >= 1: + histos.add("MC/EvRec/EvCounter", "Event Counter", kTH1D, {{1, 0, 1}}); + histos.add("MC/EvRec/Mult", "Event charged multiplicty (gen events with reco>=1)", kTH1D, {{1600, 0, 3200}}); + histos.add("MC/EvRec/MultCent", "Gen multiplicity vs reco centrality", kTH2D, {{100, 0, 100}, {1600, 0, 3200}}); + histos.add("MC/EvRec/Cent", "FT0 Centality", kTH1D, {axesConfig.axisMult}); + histos.add("MC/EvRec/Xi", "Xi", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated Xis in reco>=1 + histos.add("MC/EvRec/PrimaryXi", "Xi primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis in reco>=1 + histos.add("MC/EvRec/PrimaryXiRapidity", "Xi primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xis in selected rapidity range in reco>=1 + histos.add("MC/EvRec/PrimaryXiMinusRapidity", "Xi- primaries in |y| ", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xi-minus in selected rapidity range in reco>=1 + histos.add("MC/EvRec/PrimaryXiPlusRapidity", "Xi+ primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Xi-plus in selected rapidity range in reco>=1 + histos.add("MC/EvRec/Omega", "Omega", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated Omegas in reco>=1 + histos.add("MC/EvRec/PrimaryOmega", "Omega primaries", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas in reco>=1 + histos.add("MC/EvRec/PrimaryOmegaRapidity", "Omega primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omegas in selected rapidity range in reco>=1 + histos.add("MC/EvRec/PrimaryOmegaMinusRapidity", "Omega- primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omega-minus in selected rapidity range in reco>=1 + histos.add("MC/EvRec/PrimaryOmegaPlusRapidity", "Omega+ primaries in |y|", kTH2D, {axesConfig.axisPt, axesConfig.axisMult}); // generated primary Omega-plus in selected rapidity range in reco>=1 + histos.add("MC/EvRec/RapCheck_TH3_Gen_Xi", "Xi (primary, y<0.5) from pt, cent, rapidity", kTH3D, {axesConfig.axisPt, axesConfig.axisMult, {200, -1.0, 1.0}}); + histos.add("MC/EvRec/RapCheck_TH3_Gen_Omega", "Omega (primary, y<0.5) from pt, cent, rapidity", kTH3D, {axesConfig.axisPt, axesConfig.axisMult, {200, -1.0, 1.0}}); // label filter statistic bins for standard cascs histos.get(HIST("Standard/Rec/FiltersXi"))->GetXaxis()->SetBinLabel(1, "p_{T}"); histos.get(HIST("Standard/Rec/FiltersXi"))->GetXaxis()->SetBinLabel(2, "gen"); @@ -1164,85 +1009,136 @@ struct StrangeCascTrack { void processDerivedData(DerCollisionWMults::iterator const& collision, DerCascDatas const& allCascs, DerTraCascDatas const& traCascs, DauTracks const&) { fillEvents(collision); // save info about all processed events - if (doApplyEfficiency1D || doApplyPurity1D || doApplyEfficiency2D || doApplyPurity2D) { - initEfficiencyFromCCDB(collision.runNumber(), collision.timestamp()); - } - if (isValidEvent(collision)) { + if (isValidEvent(collision, true)) { histos.fill(HIST("Rec-Events/EvCounter"), 0.5); histos.fill(HIST("Rec-Events/PVxy"), collision.posX(), collision.posY()); histos.fill(HIST("Rec-Events/PVz"), collision.posZ()); - double mult = (doProcesspp || doProcesspO) ? collision.centFT0M() : collision.centFT0C(); + double mult = (doProcessIons) ? collision.centFT0C() : collision.centFT0M(); histos.fill(HIST("Rec-Events/Mult"), mult); analyseCascs(collision, allCascs); // process all cascades analyseCascs(collision, traCascs); // process tracked cascades } } - void processDerivedMCGen(aod::StraMCCollisions const& genColls, DerMCGenCascades const& genCascs, soa::Join const& recColls) + void processDerivedMCGen(soa::Join const& genColls, DerMCGenCascades const& genCascs, DerMCRecCollisions const& recColls) { for (auto const& genColl : genColls) { + if (eventCuts.doINELMCGen && genColl.multMCNParticlesEta10() <= 0) + continue; // skip zero gen mult events histos.fill(HIST("MC/Gen/EvCounter"), 0.5); // generated events statistics - // (for efficiency calculation) only take reconstructed events + double genMult = genColl.multMCNParticlesEta05(); + histos.fill(HIST("MC/Gen/Mult"), genMult); + // loop over generated cascades to obtain pt-genMult distribution + auto slicedGenCascs = genCascs.sliceBy(cascsPerMcCollision, genColl.globalIndex()); + for (auto const& casc : slicedGenCascs) { + if (casc.straMCCollisionId() != genColl.index()) + continue; // safety check for correct slicing + // fill generated Xi and Omega (all) for statistics + double cascPt = casc.ptMC(); + if (isValidPDG(casc, "Xi")) + histos.fill(HIST("MC/Gen/Xi"), genMult, cascPt); + if (isValidPDG(casc, "Omega")) + histos.fill(HIST("MC/Gen/Omega"), genMult, cascPt); + if (casc.isPhysicalPrimary()) { + // fill generated primary Xi and Omega for statistics + if (isValidPDG(casc, "Xi")) + histos.fill(HIST("MC/Gen/PrimaryXi"), genMult, cascPt); + if (isValidPDG(casc, "Omega")) + histos.fill(HIST("MC/Gen/PrimaryOmega"), genMult, cascPt); + // fill generated primary Xi within rapidity for corrections + if (isValidPDG(casc, "Xi") && std::abs(casc.rapidityMC(0)) < cascCuts.cutRapidity) { + histos.fill(HIST("MC/Gen/PrimaryXiRapidity"), genMult, cascPt); + if (casc.pdgCode() == PDG_t::kXiMinus) + histos.fill(HIST("MC/Gen/PrimaryXiMinusRapidity"), genMult, cascPt); + if (casc.pdgCode() == PDG_t::kXiPlusBar) + histos.fill(HIST("MC/Gen/PrimaryXiPlusRapidity"), genMult, cascPt); + } + // fill generated primary Omega within rapidity for corrections + if (isValidPDG(casc, "Omega") && std::abs(casc.rapidityMC(2)) < cascCuts.cutRapidity) { + histos.fill(HIST("MC/Gen/PrimaryOmegaRapidity"), genMult, cascPt); + if (casc.pdgCode() == PDG_t::kOmegaMinus) + histos.fill(HIST("MC/Gen/PrimaryOmegaMinusRapidity"), genMult, cascPt); + if (casc.pdgCode() == PDG_t::kOmegaPlusBar) + histos.fill(HIST("MC/Gen/PrimaryOmegaPlusRapidity"), genMult, cascPt); + } + } + // fill gen rapidity for statistics + if (isValidPDG(casc, "Xi")) + histos.fill(HIST("MC/Gen/RapidityXi"), casc.rapidityMC(0)); + if (isValidPDG(casc, "Omega")) + histos.fill(HIST("MC/Gen/RapidityOmega"), casc.rapidityMC(2)); + } + // look at reco>= 1 for corrections auto slicedRecColls = recColls.sliceBy(perMcCollision, genColl.globalIndex()); + bool recoCounter = false; + int biggestNContribs = -1; + float bestCentrality = 100.5; for (auto const& recColl : slicedRecColls) { - double cascMult = (doProcesspp || doProcesspO) ? recColl.centFT0M() : recColl.centFT0C(); + if (!isValidEvent(recColl, false)) + continue; // from this point on - only gen events (and cascades from such events) that were reconstructed int64_t genCollId = recColl.straMCCollisionId(); - for (auto const& casc : genCascs) { + if (genColl.index() != genCollId) + continue; // safety check for correct slicing + if (!recoCounter) { // fill counting histograms only once for each gen reco>=1 event + histos.fill(HIST("MC/EvRec/EvCounter"), 0.5); + histos.fill(HIST("MC/EvRec/Mult"), genMult); + recoCounter = true; + } + if (biggestNContribs < recColl.multPVTotalContributors()) { + biggestNContribs = recColl.multPVTotalContributors(); + bestCentrality = (doProcessIons) ? recColl.centFT0C() : recColl.centFT0M(); + } + // look at generated cascades within reconstructed events + for (auto const& casc : slicedGenCascs) { if (casc.straMCCollisionId() != genCollId) - continue; // safety check - double cascPt = std::sqrt(std::pow(casc.pxMC(), 2) + std::pow(casc.pyMC(), 2)); + continue; // check for cascades belonging to the correct reco collision + double cascPt = casc.ptMC(); if (isValidPDG(casc, "Xi")) - histos.fill(HIST("MC/Gen/Xi"), cascPt, cascMult); + histos.fill(HIST("MC/EvRec/Xi"), cascPt, bestCentrality); if (isValidPDG(casc, "Omega")) - histos.fill(HIST("MC/Gen/Omega"), cascPt, cascMult); + histos.fill(HIST("MC/EvRec/Omega"), cascPt, bestCentrality); if (casc.isPhysicalPrimary()) { if (isValidPDG(casc, "Xi")) { - histos.fill(HIST("MC/Gen/PrimaryXi"), cascPt, cascMult); - if (std::abs(casc.rapidityMC(0)) < selCuts.cutRapidity) - histos.fill(HIST("MC/Gen/PrimaryXiRapidity"), cascPt, cascMult); - if (casc.pdgCode() == PDG_t::kXiMinus) { - histos.fill(HIST("MC/Gen/PrimaryXiMinus"), cascPt, cascMult); - if (std::abs(casc.rapidityMC(0)) < selCuts.cutRapidity) - histos.fill(HIST("MC/Gen/PrimaryXiMinusRapidity"), cascPt, cascMult); - } - if (casc.pdgCode() == PDG_t::kXiPlusBar) { - histos.fill(HIST("MC/Gen/PrimaryXiPlus"), cascPt, cascMult); - if (std::abs(casc.rapidityMC(0)) < selCuts.cutRapidity) - histos.fill(HIST("MC/Gen/PrimaryXiPlusRapidity"), cascPt, cascMult); + histos.fill(HIST("MC/EvRec/PrimaryXi"), cascPt, bestCentrality); + if (std::abs(casc.rapidityMC(0)) < cascCuts.cutRapidity) { + histos.fill(HIST("MC/EvRec/PrimaryXiRapidity"), cascPt, bestCentrality); + histos.fill(HIST("MC/EvRec/RapCheck_TH3_Gen_Xi"), cascPt, bestCentrality, casc.rapidityMC(0)); + if (casc.pdgCode() == PDG_t::kXiMinus) + histos.fill(HIST("MC/EvRec/PrimaryXiMinusRapidity"), cascPt, bestCentrality); + if (casc.pdgCode() == PDG_t::kXiPlusBar) + histos.fill(HIST("MC/EvRec/PrimaryXiPlusRapidity"), cascPt, bestCentrality); } } if (isValidPDG(casc, "Omega")) { - histos.fill(HIST("MC/Gen/PrimaryOmega"), cascPt, cascMult); - if (std::abs(casc.rapidityMC(2)) < selCuts.cutRapidity) - histos.fill(HIST("MC/Gen/PrimaryOmegaRapidity"), cascPt, cascMult); - if (casc.pdgCode() == PDG_t::kOmegaMinus) { - histos.fill(HIST("MC/Gen/PrimaryOmegaMinus"), cascPt, cascMult); - if (std::abs(casc.rapidityMC(2)) < selCuts.cutRapidity) - histos.fill(HIST("MC/Gen/PrimaryOmegaMinusRapidity"), cascPt, cascMult); - } - if (casc.pdgCode() == PDG_t::kOmegaPlusBar) { - histos.fill(HIST("MC/Gen/PrimaryOmegaPlus"), cascPt, cascMult); - if (std::abs(casc.rapidityMC(2)) < selCuts.cutRapidity) - histos.fill(HIST("MC/Gen/PrimaryOmegaPlusRapidity"), cascPt, cascMult); + histos.fill(HIST("MC/EvRec/PrimaryOmega"), cascPt, bestCentrality); + if (std::abs(casc.rapidityMC(2)) < cascCuts.cutRapidity) { + histos.fill(HIST("MC/EvRec/PrimaryOmegaRapidity"), cascPt, bestCentrality); + histos.fill(HIST("MC/EvRec/RapCheck_TH3_Gen_Omega"), cascPt, bestCentrality, casc.rapidityMC(2)); + if (casc.pdgCode() == PDG_t::kOmegaMinus) + histos.fill(HIST("MC/EvRec/PrimaryOmegaMinusRapidity"), cascPt, bestCentrality); + if (casc.pdgCode() == PDG_t::kOmegaPlusBar) + histos.fill(HIST("MC/EvRec/PrimaryOmegaPlusRapidity"), cascPt, bestCentrality); } } } } } + // fill centrality exactly once for each rec gen event + if (biggestNContribs >= 0) { + histos.fill(HIST("MC/EvRec/MultCent"), bestCentrality, genMult); + histos.fill(HIST("MC/EvRec/Cent"), bestCentrality); + } } } void processDerivedMCRec(DerMCRecCollisions::iterator const& collision, DerMCRecCascDatas const& allCascs, DerMCRecTraCascDatas const& traCascs, DauTracks const&, DerMCGenCascades const&) { fillEvents(collision); // save info about all processed events - if (doApplyEfficiency1D || doApplyPurity1D || doApplyEfficiency2D || doApplyPurity2D) { - initEfficiencyFromCCDB(collision.runNumber(), collision.timestamp()); - } - if (isValidEvent(collision)) { + if (isValidEvent(collision, true)) { histos.fill(HIST("Rec-Events/EvCounter"), 0.5); histos.fill(HIST("Rec-Events/PVxy"), collision.posX(), collision.posY()); histos.fill(HIST("Rec-Events/PVz"), collision.posZ()); - double mult = (doProcesspp || doProcesspO) ? collision.centFT0M() : collision.centFT0C(); + double mult = (doProcessIons) ? collision.centFT0C() : collision.centFT0M(); histos.fill(HIST("Rec-Events/Mult"), mult); analyseCascs(collision, allCascs); // process all cascades analyseCascs(collision, traCascs); // process tracked cascades diff --git a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx index 1d662ae5d74..571fe9b7292 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx @@ -67,14 +67,10 @@ #include #include -using namespace std; using namespace o2; -using namespace o2::soa; -using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::math; -using std::array; // Define convenient aliases for joined AOD tables using SelCollisions = soa::Join; @@ -84,6 +80,60 @@ using DaughterTracks = soa::Join; using DaughterTracksMC = soa::Join; +struct ParticlePositionWithRespectToJet { + ParticlePositionWithRespectToJet(const float px, const float py, const float pz, + const TVector3& jet, + const TVector3& ue1, + const TVector3& ue2) + { + const TVector3 candidateDirection(px, py, pz); + const double deltaEtaJet = candidateDirection.Eta() - jet.Eta(); + const double deltaPhiJet = getDeltaPhi(candidateDirection.Phi(), jet.Phi()); + const double deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + const double deltaEtaUe1 = candidateDirection.Eta() - ue1.Eta(); + const double deltaPhiUe1 = getDeltaPhi(candidateDirection.Phi(), ue1.Phi()); + const double deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + const double deltaEtaUe2 = candidateDirection.Eta() - ue2.Eta(); + const double deltaPhiUe2 = getDeltaPhi(candidateDirection.Phi(), ue2.Phi()); + const double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + mInJet = deltaRjet < mJetRadius; + mInUE1 = deltaRue1 < mJetRadius; + mInUE2 = deltaRue2 < mJetRadius; + } + bool isInJet() const { return mInJet; } + bool isInUE1() const { return mInUE1; } + bool isInUE2() const { return mInUE2; } + + static double mJetRadius; + + // Delta phi calculation + static double getDeltaPhi(const double a1, const double a2) + { + const double phi1 = TVector2::Phi_0_2pi(a1); + const double phi2 = TVector2::Phi_0_2pi(a2); + const double diff = std::fabs(phi1 - phi2); + if (diff <= PI) + return diff; + if (diff > PI) + return TwoPI - diff; + return diff; // should not happen + } + + private: + bool mInJet = false; + bool mInUE1 = false; + bool mInUE2 = false; +}; +double ParticlePositionWithRespectToJet::mJetRadius = 0.0; + +// Reduced particle container with pions from K0s +struct PionsFromK0 { + double ptRec; + double ptGen; + int pdgCode; + int idParent; +}; + struct StrangenessInJets { // Instantiate the CCDB service and API interface @@ -132,6 +182,12 @@ struct StrangenessInJets { Configurable nsigmaTOFmax{"nsigmaTOFmax", +3.0f, "Maximum nsigma TOF"}; Configurable requireITS{"requireITS", false, "Require ITS hit"}; Configurable requireTOF{"requireTOF", false, "Require TOF hit"}; + Configurable doK0sRej{"doK0sRej", false, "K0 mass rejection for Lambda candidates"}; + Configurable doLamRej{"doLamRej", false, "Lambda mass rejection for K0s candidates"}; + Configurable lamRejWindow{"lamRejWindow", 0.01f, "Mass window for Lam rejection"}; + Configurable k0sRejWindow{"k0sRejWindow", 0.01f, "Mass window for K0 rejection"}; + Configurable lamMassWindow{"lamMassWindow", 0.01f, "Mass window for Lambda selection"}; + Configurable k0sMassWindow{"k0sMassWindow", 0.03f, "Mass window for K0s selection"}; // V0 analysis parameters Configurable minimumV0Radius{"minimumV0Radius", 0.5f, "Minimum V0 Radius"}; @@ -153,11 +209,17 @@ struct StrangenessInJets { Configurable deltaMassLambda{"deltaMassLambda", 0.02f, "Mass window for Lambda inclusion"}; struct : ConfigurableGroup { + std::string prefix = "longLivedOptions"; // JSON group name ConfigurableAxis longLivedBinsNsigma{"longLivedBinsNsigma", {200, -10.f, 10.f}, "Binning of nSigma axis"}; - ConfigurableAxis longLivedBinsPt{"longLivedBinsPt", {VARIABLE_WIDTH, -5.0, -4.8, -4.6, -4.4, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.95, -0.9, -0.85, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.25, -0.2, -0.18, -0.16, -0.14, -0.12, -0.1, 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, 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.2, 4.4, 4.6, 4.8, 5.0}, "Binning of the pT axis"}; + ConfigurableAxis longLivedBinsPt{"longLivedBinsPt", {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, 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.2, 4.4, 4.6, 4.8, 5.0}, "Binning of the pT axis"}; ConfigurableAxis longLivedBinsDca{"longLivedBinsDca", {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"}; } longLivedOptions; + struct : ConfigurableGroup { + std::string prefix = "axisOptions"; // JSON group name + ConfigurableAxis multBinning{"multBinning", {VARIABLE_WIDTH, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "Binning of multiplicity axis"}; + } axisOptions; + // Instantiate utility class for jet background subtraction JetBkgSubUtils backgroundSub; @@ -172,6 +234,7 @@ struct StrangenessInJets { void init(InitContext const&) { + ParticlePositionWithRespectToJet::mJetRadius = rJet.value; if (cfgSkimmedProcessing) { zorroSummary.setObject(zorro.getZorroSummary()); } @@ -191,12 +254,11 @@ struct StrangenessInJets { enabled += checkEnabled(ParticleOfInterest::kKaons); enabled += checkEnabled(ParticleOfInterest::kProtons); if (enabled == 0) { - LOG(fatal) << "At least one particle species must be enabled for the analysis. Please check the configuration of the task." << endl; + LOG(fatal) << "At least one particle species must be enabled for the analysis. Please check the configuration of the task."; } // Define binning and axis specifications for multiplicity, eta, pT, PID, and invariant mass histograms - std::vector multBinning = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; - AxisSpec multAxis = {multBinning, "FT0C percentile"}; + AxisSpec multAxis = {axisOptions.multBinning, "FT0C percentile"}; const AxisSpec ptAxis{100, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec invMassK0sAxis{200, 0.44, 0.56, "m_{#pi#pi} (GeV/#it{c}^{2})"}; const AxisSpec invMassLambdaAxis{200, 1.09, 1.14, "m_{p#pi} (GeV/#it{c}^{2})"}; @@ -209,20 +271,20 @@ struct StrangenessInJets { // Histograms for real data if (doprocessDerivedAnalysis) { - registryData.add("Lambda_in_jet", "Lambda_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("AntiLambda_in_jet", "AntiLambda_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("Lambda_in_ue", "Lambda_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("AntiLambda_in_ue", "AntiLambda_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("K0s_in_jet", "K0s_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassK0sAxis}); - registryData.add("K0s_in_ue", "K0s_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassK0sAxis}); - registryData.add("XiPos_in_jet", "XiPos_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("XiPos_in_ue", "XiPos_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("XiNeg_in_jet", "XiNeg_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("XiNeg_in_ue", "XiNeg_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("OmegaPos_in_jet", "OmegaPos_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - registryData.add("OmegaPos_in_ue", "OmegaPos_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - registryData.add("OmegaNeg_in_jet", "OmegaNeg_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - registryData.add("OmegaNeg_in_ue", "OmegaNeg_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); + registryData.add("Lambda_in_jet", "Lambda_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("AntiLambda_in_jet", "AntiLambda_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("Lambda_in_ue", "Lambda_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("AntiLambda_in_ue", "AntiLambda_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("K0s_in_jet", "K0s_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); + registryData.add("K0s_in_ue", "K0s_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); + registryData.add("XiPos_in_jet", "XiPos_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("XiPos_in_ue", "XiPos_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("XiNeg_in_jet", "XiNeg_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("XiNeg_in_ue", "XiNeg_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("OmegaPos_in_jet", "OmegaPos_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryData.add("OmegaPos_in_ue", "OmegaPos_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryData.add("OmegaNeg_in_jet", "OmegaNeg_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryData.add("OmegaNeg_in_ue", "OmegaNeg_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); } if (doprocessData) { @@ -230,37 +292,35 @@ struct StrangenessInJets { // Event counters registryData.add("number_of_events_data", "number of events in data", HistType::kTH1D, {{20, 0, 20, "Event Cuts"}}); registryData.add("number_of_events_vsmultiplicity", "number of events in data vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + registryData.add("number_of_jets_vsmultiplicity", "number of jets in data vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); // Histograms for analysis of strange hadrons if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryData.add("Lambda_in_jet", "Lambda_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("AntiLambda_in_jet", "AntiLambda_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("Lambda_in_ue", "Lambda_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("AntiLambda_in_ue", "AntiLambda_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassLambdaAxis}); - registryData.add("K0s_in_jet", "K0s_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassK0sAxis}); - registryData.add("K0s_in_ue", "K0s_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassK0sAxis}); + registryData.add("Lambda_in_jet", "Lambda_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("AntiLambda_in_jet", "AntiLambda_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("Lambda_in_ue", "Lambda_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("AntiLambda_in_ue", "AntiLambda_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassLambdaAxis}); + registryData.add("K0s_in_jet", "K0s_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); + registryData.add("K0s_in_ue", "K0s_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassK0sAxis}); } if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryData.add("XiPos_in_jet", "XiPos_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("XiPos_in_ue", "XiPos_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("XiNeg_in_jet", "XiNeg_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("XiNeg_in_ue", "XiNeg_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassXiAxis}); - registryData.add("OmegaPos_in_jet", "OmegaPos_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - registryData.add("OmegaPos_in_ue", "OmegaPos_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - registryData.add("OmegaNeg_in_jet", "OmegaNeg_in_jet", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - registryData.add("OmegaNeg_in_ue", "OmegaNeg_in_ue", HistType::kTH3F, {multBinning, ptAxis, invMassOmegaAxis}); - } - if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryData.add("Pion_in_jet", "Pion_in_jet", HistType::kTHnSparseF, {multBinning, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); - registryData.add("Pion_in_ue", "Pion_in_ue", HistType::kTHnSparseF, {multBinning, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); - } - if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryData.add("Kaon_in_jet", "Kaon_in_jet", HistType::kTHnSparseF, {multBinning, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); - registryData.add("Kaon_in_ue", "Kaon_in_ue", HistType::kTHnSparseF, {multBinning, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); + registryData.add("XiPos_in_jet", "XiPos_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("XiPos_in_ue", "XiPos_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("XiNeg_in_jet", "XiNeg_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("XiNeg_in_ue", "XiNeg_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassXiAxis}); + registryData.add("OmegaPos_in_jet", "OmegaPos_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryData.add("OmegaPos_in_ue", "OmegaPos_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryData.add("OmegaNeg_in_jet", "OmegaNeg_in_jet", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); + registryData.add("OmegaNeg_in_ue", "OmegaNeg_in_ue", HistType::kTH3F, {multAxis, ptAxis, invMassOmegaAxis}); } - if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryData.add("Proton_in_jet", "Proton_in_jet", HistType::kTHnSparseF, {multBinning, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); - registryData.add("Proton_in_ue", "Proton_in_ue", HistType::kTHnSparseF, {multBinning, ptAxisLongLived, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); + if (enabledSignals.value[ParticleOfInterest::kPions] || + enabledSignals.value[ParticleOfInterest::kKaons] || + enabledSignals.value[ParticleOfInterest::kProtons]) { // Long lived are enabled + // First we count how many they are + const AxisSpec axisInJetOutOfJet = AxisSpec{2, -2., 2., "In jet / Out of jet"}; + const AxisSpec axisCharge = AxisSpec{2, -2., 2., "Charge"}; + const AxisSpec axisParticleType = AxisSpec{3, -0.5, 2.5, "Particle Type"}; + registryData.add("LongLived", "LongLived", HistType::kTHnSparseF, {axisInJetOutOfJet, axisParticleType, axisCharge, ptAxisLongLived, multAxis, nsigmaTPCAxis, nsigmaTOFAxis, dcaAxis}); } } @@ -270,53 +330,69 @@ struct StrangenessInJets { // Event counter registryMC.add("number_of_events_mc_gen", "number of gen events in mc", HistType::kTH1D, {{10, 0, 10, "Event Cuts"}}); registryMC.add("number_of_events_vsmultiplicity_gen", "number of events vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); + registryMC.add("number_of_jets_vsmultiplicity", "number of jets in mc gen vs multiplicity", HistType::kTH1D, {{101, 0, 101, "Multiplicity percentile"}}); // Histograms for analysis if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.add("K0s_generated_jet", "K0s_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("K0s_generated_ue", "K0s_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_generated_jet", "Lambda_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_generated_ue", "Lambda_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_generated_jet", "AntiLambda_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_generated_ue", "AntiLambda_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("K0s_generated_jet", "K0s_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_ue", "K0s_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_jet", "Lambda_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_ue", "Lambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_jet", "AntiLambda_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_ue", "AntiLambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + // Histograms to calculate probability of hyperons to be found within jets + registryMC.add("K0s_generated_fullevent", "K0s_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_fullevent", "Lambda_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_fullevent", "AntiLambda_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); } if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.add("XiPos_generated_jet", "XiPos_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiPos_generated_ue", "XiPos_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_generated_jet", "XiNeg_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_generated_ue", "XiNeg_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_generated_jet", "OmegaPos_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_generated_ue", "OmegaPos_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_generated_jet", "OmegaNeg_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_generated_ue", "OmegaNeg_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_generated_jet", "XiPos_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiPos_generated_ue", "XiPos_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_generated_jet", "XiNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_generated_ue", "XiNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_generated_jet", "OmegaPos_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_generated_ue", "OmegaPos_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_generated_jet", "OmegaNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_generated_ue", "OmegaNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + // Histograms to calculate probability of hyperons to be found within jets + registryMC.add("XiPos_generated_fullevent", "XiPos_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_generated_fullevent", "XiNeg_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_generated_fullevent", "OmegaPos_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_generated_fullevent", "OmegaNeg_generated_fullevent", HistType::kTH2F, {multAxis, ptAxis}); } if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryMC.add("Pion_generated_in_jet", "Pion_generated_in_jet", HistType::kTH2F, {multBinning, ptAxisLongLived}); - registryMC.add("Pion_generated_in_ue", "Pion_generated_in_ue", HistType::kTH2F, {multBinning, ptAxisLongLived}); + registryMC.add("Pion_Plus_generated_fullevent", "Pion_Plus_generated_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("Pion_Minus_generated_fullevent", "Pion_Minus_generated_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryMC.add("Kaon_generated_in_jet", "Kaon_generated_in_jet", HistType::kTH2F, {multBinning, ptAxisLongLived}); - registryMC.add("Kaon_generated_in_ue", "Kaon_generated_in_ue", HistType::kTH2F, {multBinning, ptAxisLongLived}); + registryMC.add("Kaon_Plus_generated_fullevent", "Kaon_Plus_generated_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("Kaon_Minus_generated_fullevent", "Kaon_Minus_generated_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryMC.add("Proton_generated_in_jet", "Proton_generated_in_jet", HistType::kTH2F, {multBinning, ptAxisLongLived}); - registryMC.add("Proton_generated_in_ue", "Proton_generated_in_ue", HistType::kTH2F, {multBinning, ptAxisLongLived}); + registryMC.add("Proton_Plus_generated_fullevent", "Proton_Plus_generated_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("Proton_Minus_generated_fullevent", "Proton_Minus_generated_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); } - - // Histograms to calculate probability of hyperons to be found within jets - if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.add("K0s_generated_fullevent", "K0s_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_generated_fullevent", "Lambda_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_generated_fullevent", "AntiLambda_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - } - if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.add("XiPos_generated_fullevent", "XiPos_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_generated_fullevent", "XiNeg_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_generated_fullevent", "OmegaPos_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_generated_fullevent", "OmegaNeg_generated_fullevent", HistType::kTH2F, {multBinning, ptAxis}); + if (enabledSignals.value[ParticleOfInterest::kPions] || + enabledSignals.value[ParticleOfInterest::kKaons] || + enabledSignals.value[ParticleOfInterest::kProtons]) { + const AxisSpec axisInJetOutOfJet = AxisSpec{2, -2., 2., "In jet / Out of jet"}; + const AxisSpec axisCharge = AxisSpec{2, -2., 2., "Charge"}; + const AxisSpec axisParticleType = AxisSpec{3, -0.5, 2.5, "Particle Type"}; + registryMC.add("LongLivedGenerated", "LongLivedGenerated", HistType::kTHnSparseF, {axisInJetOutOfJet, axisParticleType, axisCharge, ptAxisLongLived, multAxis}); } } + if (doprocessMCRecK0inJet) { + registryMC.add("K0s_reconstructed_jet_withK0", "K0s_reconstructed_jet_withK0", HistType::kTH2F, {multAxis, ptAxis}); + } + + // Histograms for MC K0 short in jets + if (doprocessMCK0shortInJets) { + registryMC.add("ptSpectrumK0DaughtersAll", "ptSpectrumK0DaughtersAll", HistType::kTH1D, {{1000, 0, 100, "p_{T}"}}); + registryMC.add("fractionJetPtCarriedByK0", "fractionJetPtCarriedByK0", HistType::kTH1D, {{1000, 0, 1, "fraction"}}); + registryMC.add("ptSpectrumK0DaughtersInJet", "ptSpectrumK0DaughtersInJet", HistType::kTH1D, {{1000, 0, 100, "p_{T}"}}); + } + // Histograms for mc reconstructed if (doprocessMCreconstructed) { @@ -326,80 +402,104 @@ struct StrangenessInJets { // Histograms for analysis if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.add("K0s_reconstructed_jet", "K0s_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("K0s_reconstructed_ue", "K0s_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_reconstructed_jet", "Lambda_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_reconstructed_ue", "Lambda_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_reconstructed_jet", "AntiLambda_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_reconstructed_ue", "AntiLambda_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("K0s_reconstructed_jet", "K0s_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_reconstructed_ue", "K0s_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_jet", "Lambda_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_ue", "Lambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_jet", "AntiLambda_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_ue", "AntiLambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); // Histograms for secondary hadrons - registryMC.add("K0s_reconstructed_jet_incl", "K0s_reconstructed_jet_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("K0s_reconstructed_ue_incl", "K0s_reconstructed_ue_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_reconstructed_jet_incl", "Lambda_reconstructed_jet_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_reconstructed_ue_incl", "Lambda_reconstructed_ue_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_reconstructed_jet_incl", "AntiLambda_reconstructed_jet_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_reconstructed_ue_incl", "AntiLambda_reconstructed_ue_incl", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("K0s_reconstructed_jet_incl", "K0s_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_reconstructed_ue_incl", "K0s_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_jet_incl", "Lambda_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_ue_incl", "Lambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_jet_incl", "AntiLambda_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_ue_incl", "AntiLambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); + // Histograms to calculate probability of hyperons to be found within jets + registryMC.add("K0s_reconstructed_fullevent", "K0s_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_fullevent", "Lambda_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_fullevent", "AntiLambda_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_reconstructed_eventwjet", "K0s_reconstructed_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_eventwjet", "Lambda_reconstructed_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_eventwjet", "AntiLambda_reconstructed_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_eventwjet", "K0s_generated_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_eventwjet", "Lambda_generated_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_eventwjet", "AntiLambda_generated_eventwjet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_recoevent", "K0s_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_recoevent", "Lambda_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_recoevent", "AntiLambda_generated_recoevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_recojet_jet", "K0s_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_recojet_jet", "Lambda_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_recojet_jet", "AntiLambda_generated_recojet_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_generated_recojet_ue", "K0s_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_recojet_ue", "Lambda_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_recojet_ue", "AntiLambda_generated_recojet_ue", HistType::kTH2F, {multAxis, ptAxis}); } if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.add("XiPos_reconstructed_jet", "XiPos_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiPos_reconstructed_ue", "XiPos_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_reconstructed_jet", "XiNeg_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_reconstructed_ue", "XiNeg_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_reconstructed_jet", "OmegaPos_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_reconstructed_ue", "OmegaPos_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_reconstructed_jet", "OmegaNeg_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_reconstructed_ue", "OmegaNeg_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_reconstructed_jet", "XiPos_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiPos_reconstructed_ue", "XiPos_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_reconstructed_jet", "XiNeg_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_reconstructed_ue", "XiNeg_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_reconstructed_jet", "OmegaPos_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_reconstructed_ue", "OmegaPos_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_jet", "OmegaNeg_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_ue", "OmegaNeg_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + // Histograms to calculate probability of hyperons to be found within jets + registryMC.add("XiPos_reconstructed_fullevent", "XiPos_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_reconstructed_fullevent", "XiNeg_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_reconstructed_fullevent", "OmegaPos_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_fullevent", "OmegaNeg_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxis}); } if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryMC.add("Pion_reconstructed_in_jet", "Pion_reconstructed_in_jet", HistType::kTH2F, {multBinning, ptAxisLongLived}); - registryMC.add("Pion_reconstructed_in_ue", "Pion_reconstructed_in_ue", HistType::kTH2F, {multBinning, ptAxisLongLived}); + registryMC.add("Pion_Plus_reconstructed_fullevent", "Pion_Plus_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("Pion_Minus_reconstructed_fullevent", "Pion_Minus_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryMC.add("Kaon_reconstructed_in_jet", "Kaon_reconstructed_in_jet", HistType::kTH2F, {multBinning, ptAxisLongLived}); - registryMC.add("Kaon_reconstructed_in_ue", "Kaon_reconstructed_in_ue", HistType::kTH2F, {multBinning, ptAxisLongLived}); + registryMC.add("Kaon_Plus_reconstructed_fullevent", "Kaon_Plus_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("Kaon_Minus_reconstructed_fullevent", "Kaon_Minus_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryMC.add("Proton_reconstructed_in_jet", "Proton_reconstructed_in_jet", HistType::kTH2F, {multBinning, ptAxisLongLived}); - registryMC.add("Proton_reconstructed_in_ue", "Proton_reconstructed_in_ue", HistType::kTH2F, {multBinning, ptAxisLongLived}); + registryMC.add("Proton_Plus_reconstructed_fullevent", "Proton_Plus_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("Proton_Minus_reconstructed_fullevent", "Proton_Minus_reconstructed_fullevent", HistType::kTH2F, {multAxis, ptAxisLongLived}); } - - // Histograms to calculate probability of hyperons to be found within jets - if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.add("K0s_reconstructed_fullevent", "K0s_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_reconstructed_fullevent", "Lambda_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_reconstructed_fullevent", "AntiLambda_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - } - if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.add("XiPos_reconstructed_fullevent", "XiPos_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_reconstructed_fullevent", "XiNeg_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_reconstructed_fullevent", "OmegaPos_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_reconstructed_fullevent", "OmegaNeg_reconstructed_fullevent", HistType::kTH2F, {multBinning, ptAxis}); + if (enabledSignals.value[ParticleOfInterest::kPions] || + enabledSignals.value[ParticleOfInterest::kKaons] || + enabledSignals.value[ParticleOfInterest::kProtons]) { + const AxisSpec axisInJetOutOfJet = AxisSpec{2, -2., 2., "In jet / Out of jet"}; + const AxisSpec axisCharge = AxisSpec{2, -2., 2., "Charge"}; + const AxisSpec axisParticleType = AxisSpec{3, -0.5, 2.5, "Particle Type"}; + const AxisSpec axisDetector = AxisSpec{2, -0.5, 1.5, "TPC / TOF"}; + registryMC.add("LongLivedReconstructed", "LongLivedReconstructed", HistType::kTHnSparseF, {axisInJetOutOfJet, axisParticleType, axisCharge, ptAxisLongLived, multAxis, axisDetector}); } } } - // Delta phi calculation - double getDeltaPhi(double a1, double a2) + bool pdgToLongLivedIndex(const int pdg, float& particle, float& charge) { - double deltaPhi(0); - double phi1 = TVector2::Phi_0_2pi(a1); - double phi2 = TVector2::Phi_0_2pi(a2); - double diff = std::fabs(phi1 - phi2); - - if (diff <= PI) - deltaPhi = diff; - if (diff > PI) - deltaPhi = TwoPI - diff; - - return deltaPhi; + switch (std::abs(pdg)) { + case PDG_t::kPiPlus: + particle = 0; // pion + charge = (pdg > 0) ? 1 : -1; + return enabledSignals.value[ParticleOfInterest::kPions]; + case PDG_t::kKPlus: + particle = 1; // kaon + charge = (pdg > 0) ? 1 : -1; + return enabledSignals.value[ParticleOfInterest::kKaons]; + case PDG_t::kProton: + particle = 2; // proton + charge = (pdg > 0) ? 1 : -1; + return enabledSignals.value[ParticleOfInterest::kProtons]; + default: + return false; + } } // Check if particle is a physical primary or a decay product of a heavy-flavor hadron bool isPhysicalPrimaryOrFromHF(aod::McParticle const& particle, aod::McParticles const& mcParticles) { // Keep only pi, K, p, e, mu - int pdg = std::abs(particle.pdgCode()); + const int pdg = std::abs(particle.pdgCode()); if (!(pdg == PDG_t::kPiPlus || pdg == PDG_t::kKPlus || pdg == PDG_t::kProton || pdg == PDG_t::kElectron || pdg == PDG_t::kMuonMinus)) return false; @@ -412,8 +512,8 @@ struct StrangenessInJets { // Check if particle is from heavy-flavor decay bool fromHF = false; if (particle.has_mothers()) { - auto mother = mcParticles.iteratorAt(particle.mothersIds()[0]); - int motherPdg = std::abs(mother.pdgCode()); + const auto& mother = mcParticles.iteratorAt(particle.mothersIds()[0]); + const int motherPdg = std::abs(mother.pdgCode()); fromHF = (motherPdg / Hundreds == CharmQuark || motherPdg / Hundreds == BottomQuark || motherPdg / Thousands == CharmQuark || motherPdg / Thousands == BottomQuark); } @@ -425,15 +525,15 @@ struct StrangenessInJets { void getPerpendicularDirections(const TVector3& p, TVector3& u1, TVector3& u2) { // Get momentum components - double px = p.X(); - double py = p.Y(); - double pz = p.Z(); + const double px = p.X(); + const double py = p.Y(); + const double pz = p.Z(); // Precompute squared terms - double px2 = px * px; - double py2 = py * py; - double pz2 = pz * pz; - double pz4 = pz2 * pz2; + const double px2 = px * px; + const double py2 = py * py; + const double pz2 = pz * pz; + const double pz4 = pz2 * pz2; // Case 1: vector along z-axis -> undefined perpendiculars if (px == 0 && py == 0) { @@ -444,8 +544,8 @@ struct StrangenessInJets { // Case 2: px = 0 -> avoid division by zero if (px == 0 && py != 0) { - double ux = std::sqrt(py2 - pz4 / py2); - double uy = -pz2 / py; + const double ux = std::sqrt(py2 - pz4 / py2); + const double uy = -pz2 / py; u1.SetXYZ(ux, uy, pz); u2.SetXYZ(-ux, uy, pz); return; @@ -453,18 +553,18 @@ struct StrangenessInJets { // Case 3: py = 0 -> avoid division by zero if (py == 0 && px != 0) { - double ux = -pz2 / px; - double uy = std::sqrt(px2 - pz4 / px2); + const double ux = -pz2 / px; + const double uy = std::sqrt(px2 - pz4 / px2); u1.SetXYZ(ux, uy, pz); u2.SetXYZ(ux, -uy, pz); return; } // General case: solve quadratic for perpendicular vectors - double a = px2 + py2; - double b = 2.0 * px * pz2; - double c = pz4 - py2 * py2 - px2 * py2; - double delta = b * b - 4.0 * a * c; + const double a = px2 + py2; + const double b = 2.0 * px * pz2; + const double c = pz4 - py2 * py2 - px2 * py2; + const double delta = b * b - 4.0 * a * c; // Invalid or degenerate solutions if (delta < 0 || a == 0) { @@ -474,13 +574,13 @@ struct StrangenessInJets { } // Solution 1 - double u1x = (-b + std::sqrt(delta)) / (2.0 * a); - double u1y = (-pz2 - px * u1x) / py; + const double u1x = (-b + std::sqrt(delta)) / (2.0 * a); + const double u1y = (-pz2 - px * u1x) / py; u1.SetXYZ(u1x, u1y, pz); // Solution 2 - double u2x = (-b - std::sqrt(delta)) / (2.0 * a); - double u2y = (-pz2 - px * u2x) / py; + const double u2x = (-b - std::sqrt(delta)) / (2.0 * a); + const double u2y = (-pz2 - px * u2x) / py; u2.SetXYZ(u2x, u2y, pz); } @@ -488,7 +588,7 @@ struct StrangenessInJets { template bool hasITSHitOnLayer(const TrackIts& track, int layer) { - int ibit = layer - 1; + const int ibit = layer - 1; return (track.itsClusterMap() & (1 << ibit)); } @@ -538,8 +638,8 @@ struct StrangenessInJets { return false; // Momentum of lambda daughters - TVector3 proton(v0.pxpos(), v0.pypos(), v0.pzpos()); - TVector3 pion(v0.pxneg(), v0.pyneg(), v0.pzneg()); + const TVector3 proton(v0.pxpos(), v0.pypos(), v0.pzpos()); + const TVector3 pion(v0.pxneg(), v0.pyneg(), v0.pzneg()); // Selection on pt of Lambda daughters if (proton.Pt() < ptMinV0Proton || proton.Pt() > ptMaxV0Proton) @@ -565,6 +665,12 @@ struct StrangenessInJets { if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) return false; + if (doK0sRej && std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < k0sRejWindow) + return false; + + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda) > lamMassWindow) + return false; + // PID selections (TOF): positive track = proton, negative track = pion if (requireTOF) { if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) @@ -584,8 +690,8 @@ struct StrangenessInJets { return false; // Momentum AntiLambda daughters - TVector3 pion(v0.pxpos(), v0.pypos(), v0.pzpos()); - TVector3 proton(v0.pxneg(), v0.pyneg(), v0.pzneg()); + const TVector3 pion(v0.pxpos(), v0.pypos(), v0.pzpos()); + const TVector3 proton(v0.pxneg(), v0.pyneg(), v0.pzneg()); // Selections on pt of Antilambda daughters if (proton.Pt() < ptMinV0Proton || proton.Pt() > ptMaxV0Proton) @@ -605,6 +711,12 @@ struct StrangenessInJets { if (std::fabs(v0.dcanegtopv()) < dcanegtoPVmin) return false; + if (doK0sRej && std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < k0sRejWindow) + return false; + + if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda) > lamMassWindow) + return false; + // PID selections (TPC): negative track = proton, positive track = pion if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) return false; @@ -630,8 +742,8 @@ struct StrangenessInJets { return false; // Momentum of K0s daughters - TVector3 pionPos(v0.pxpos(), v0.pypos(), v0.pzpos()); - TVector3 pionNeg(v0.pxneg(), v0.pyneg(), v0.pzneg()); + const TVector3 pionPos(v0.pxpos(), v0.pypos(), v0.pzpos()); + const TVector3 pionNeg(v0.pxneg(), v0.pyneg(), v0.pzneg()); // Selections on pt of K0s daughters if (pionPos.Pt() < ptMinK0Pion || pionPos.Pt() > ptMaxK0Pion) @@ -657,6 +769,12 @@ struct StrangenessInJets { if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) return false; + if (doLamRej && (std::abs(v0.mLambda() - o2::constants::physics::MassLambda) < lamRejWindow || std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda) < lamRejWindow)) + return false; + + if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) > k0sMassWindow) + return false; + // PID selections (TOF) if (requireTOF) { if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) @@ -991,7 +1109,7 @@ struct StrangenessInJets { isAtLeastOneJetSelected = true; // Calculation of perpendicular cones - TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + const TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { @@ -1002,7 +1120,10 @@ struct StrangenessInJets { selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); + + registryData.fill(HIST("number_of_jets_vsmultiplicity"), collision.centFT0M()); } + if (!isAtLeastOneJetSelected) return; @@ -1022,43 +1143,34 @@ struct StrangenessInJets { // Get V0 daughters const auto& pos = v0.posTrack_as(); const auto& neg = v0.negTrack_as(); - TVector3 v0dir(v0.px(), v0.py(), v0.pz()); // Calculate distance from jet and UE axes - const float deltaEtaJet = v0dir.Eta() - selectedJet[i].Eta(); - const float deltaPhiJet = getDeltaPhi(v0dir.Phi(), selectedJet[i].Phi()); - const float deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - const float deltaEtaUe1 = v0dir.Eta() - ue1[i].Eta(); - const float deltaPhiUe1 = getDeltaPhi(v0dir.Phi(), ue1[i].Phi()); - const float deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - const float deltaEtaUe2 = v0dir.Eta() - ue2[i].Eta(); - const float deltaPhiUe2 = getDeltaPhi(v0dir.Phi(), ue2[i].Phi()); - const float deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + const ParticlePositionWithRespectToJet position{v0.px(), v0.py(), v0.pz(), selectedJet[i], ue1[i], ue2[i]}; // K0s if (passedK0ShortSelection(v0, pos, neg)) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("K0s_in_jet"), multiplicity, v0.pt(), v0.mK0Short()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("K0s_in_ue"), multiplicity, v0.pt(), v0.mK0Short()); } } // Lambda if (passedLambdaSelection(v0, pos, neg)) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("Lambda_in_jet"), multiplicity, v0.pt(), v0.mLambda()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("Lambda_in_ue"), multiplicity, v0.pt(), v0.mLambda()); } } // AntiLambda if (passedAntiLambdaSelection(v0, pos, neg)) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("AntiLambda_in_jet"), multiplicity, v0.pt(), v0.mAntiLambda()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("AntiLambda_in_ue"), multiplicity, v0.pt(), v0.mAntiLambda()); } } @@ -1074,91 +1186,77 @@ struct StrangenessInJets { TVector3 cascadeDir(casc.px(), casc.py(), casc.pz()); // Calculate distance from jet and UE axes - const double deltaEtaJet = cascadeDir.Eta() - selectedJet[i].Eta(); - const double deltaPhiJet = getDeltaPhi(cascadeDir.Phi(), selectedJet[i].Phi()); - const double deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - const double deltaEtaUe1 = cascadeDir.Eta() - ue1[i].Eta(); - const double deltaPhiUe1 = getDeltaPhi(cascadeDir.Phi(), ue1[i].Phi()); - const double deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - const double deltaEtaUe2 = cascadeDir.Eta() - ue2[i].Eta(); - const double deltaPhiUe2 = getDeltaPhi(cascadeDir.Phi(), ue2[i].Phi()); - const double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + const ParticlePositionWithRespectToJet position{casc.px(), casc.py(), casc.pz(), selectedJet[i], ue1[i], ue2[i]}; // Xi+ if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("XiPos_in_jet"), multiplicity, casc.pt(), casc.mXi()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("XiPos_in_ue"), multiplicity, casc.pt(), casc.mXi()); } } // Xi- if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("XiNeg_in_jet"), multiplicity, casc.pt(), casc.mXi()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("XiNeg_in_ue"), multiplicity, casc.pt(), casc.mXi()); } } // Omega+ if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("OmegaPos_in_jet"), multiplicity, casc.pt(), casc.mOmega()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("OmegaPos_in_ue"), multiplicity, casc.pt(), casc.mOmega()); } } // Omega- if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryData.fill(HIST("OmegaNeg_in_jet"), multiplicity, casc.pt(), casc.mOmega()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryData.fill(HIST("OmegaNeg_in_ue"), multiplicity, casc.pt(), casc.mOmega()); } } } } - if (enabledSignals.value[ParticleOfInterest::kPions] || enabledSignals.value[ParticleOfInterest::kKaons] || enabledSignals.value[ParticleOfInterest::kProtons]) { + if (enabledSignals.value[ParticleOfInterest::kPions] || + enabledSignals.value[ParticleOfInterest::kKaons] || + enabledSignals.value[ParticleOfInterest::kProtons]) { for (const auto& trk : tracks) { if (!passedSingleTrackSelection(trk)) { continue; } - const double deltaEtaJet = trk.eta() - selectedJet[i].Eta(); - const double deltaPhiJet = getDeltaPhi(trk.phi(), selectedJet[i].Phi()); - const double deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - const double deltaEtaUe1 = trk.eta() - ue1[i].Eta(); - const double deltaPhiUe1 = getDeltaPhi(trk.phi(), ue1[i].Phi()); - const double deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - const double deltaEtaUe2 = trk.eta() - ue2[i].Eta(); - const double deltaPhiUe2 = getDeltaPhi(trk.phi(), ue2[i].Phi()); - const double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - - if (deltaRjet < rJet) { + const ParticlePositionWithRespectToJet position{trk.px(), trk.py(), trk.pz(), selectedJet[i], ue1[i], ue2[i]}; + + if (position.isInJet()) { if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryData.fill(HIST("Pion_in_jet"), multiplicity, trk.pt() * trk.sign(), trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.dcaXY()); + registryData.fill(HIST("LongLived"), 1.f, 0.f, trk.sign(), trk.pt(), multiplicity, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.dcaXY()); } if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryData.fill(HIST("Kaon_in_jet"), multiplicity, trk.pt() * trk.sign(), trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.dcaXY()); + registryData.fill(HIST("LongLived"), 1.f, 1.f, trk.sign(), trk.pt(), multiplicity, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.dcaXY()); } if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryData.fill(HIST("Proton_in_jet"), multiplicity, trk.pt() * trk.sign(), trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.dcaXY()); + registryData.fill(HIST("LongLived"), 1.f, 2.f, trk.sign(), trk.pt(), multiplicity, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.dcaXY()); } } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryData.fill(HIST("Pion_in_ue"), multiplicity, trk.pt() * trk.sign(), trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.dcaXY()); + registryData.fill(HIST("LongLived"), -1.f, 0.f, trk.sign(), trk.pt(), multiplicity, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.dcaXY()); } if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryData.fill(HIST("Kaon_in_ue"), multiplicity, trk.pt() * trk.sign(), trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.dcaXY()); + registryData.fill(HIST("LongLived"), -1.f, 1.f, trk.sign(), trk.pt(), multiplicity, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.dcaXY()); } if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryData.fill(HIST("Proton_in_ue"), multiplicity, trk.pt() * trk.sign(), trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.dcaXY()); + registryData.fill(HIST("LongLived"), -1.f, 2.f, trk.sign(), trk.pt(), multiplicity, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.dcaXY()); } } } @@ -1178,8 +1276,7 @@ struct StrangenessInJets { { // Define per-event particle containers std::vector fjParticles; - std::vector strHadronMomentum; - std::vector pdg; + std::vector> hadronMomentum; // Jet and area definitions fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); @@ -1190,8 +1287,7 @@ struct StrangenessInJets { // Clear containers at the start of the event loop fjParticles.clear(); - strHadronMomentum.clear(); - pdg.clear(); + hadronMomentum.clear(); // Fill event counter before any selection registryMC.fill(HIST("number_of_events_mc_gen"), 0.5); @@ -1200,32 +1296,45 @@ struct StrangenessInJets { registryMC.fill(HIST("number_of_events_mc_gen"), 1.5); // Require vertex position within the allowed z range - if (std::fabs(collision.posZ()) > zVtx) + if (std::fabs(collision.posZ()) > zVtx) { continue; + } // Fill event counter after selection on z-vertex registryMC.fill(HIST("number_of_events_mc_gen"), 2.5); // Multiplicity of generated event - double genMultiplicity = collision.centFT0M(); + const float genMultiplicity = collision.centFT0M(); // MC particles per collision - auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); + const auto& mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); // Loop over all MC particles and select physical primaries within acceptance for (const auto& particle : mcParticlesPerColl) { // Store properties of strange hadrons - int pdgAbs = std::abs(particle.pdgCode()); - if (particle.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0 || pdgAbs == kXiMinus || pdgAbs == kOmegaMinus)) { - pdg.emplace_back(particle.pdgCode()); - strHadronMomentum.emplace_back(particle.px(), particle.py(), particle.pz()); + const int pdgAbs = std::abs(particle.pdgCode()); + if (particle.isPhysicalPrimary()) { + switch (pdgAbs) { + case kK0Short: + case kLambda0: + case kXiMinus: + case kOmegaMinus: + case kPiPlus: + case kKPlus: + case kProton: + hadronMomentum.emplace_back(TVector3(particle.px(), particle.py(), particle.pz()), particle.pdgCode()); + break; + default: + break; + } } // Eta and pt selection - double minPtParticle = 0.1; - if (particle.eta() < etaMin || particle.eta() > etaMax || particle.pt() < minPtParticle) + const float minPtParticle = 0.1f; + if (particle.eta() < etaMin || particle.eta() > etaMax || particle.pt() < minPtParticle) { continue; + } // Fill generated histograms for full event if (particle.isPhysicalPrimary()) { @@ -1265,14 +1374,45 @@ struct StrangenessInJets { registryMC.fill(HIST("OmegaPos_generated_fullevent"), genMultiplicity, particle.pt()); } break; + case kPiPlus: + if (enabledSignals.value[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("Pion_Plus_generated_fullevent"), genMultiplicity, particle.pt()); + } + break; + case kPiMinus: + if (enabledSignals.value[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("Pion_Minus_generated_fullevent"), genMultiplicity, particle.pt()); + } + break; + case kKPlus: + if (enabledSignals.value[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("Kaon_Plus_generated_fullevent"), genMultiplicity, particle.pt()); + } + break; + case kKMinus: + if (enabledSignals.value[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("Kaon_Minus_generated_fullevent"), genMultiplicity, particle.pt()); + } + break; + case kProton: + if (enabledSignals.value[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("Proton_Plus_generated_fullevent"), genMultiplicity, particle.pt()); + } + break; + case kProtonBar: + if (enabledSignals.value[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("Proton_Minus_generated_fullevent"), genMultiplicity, particle.pt()); + } + break; default: break; } } // Select physical primary particles or HF decay products - if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) { continue; + } // Build 4-momentum assuming charged pion mass static constexpr float MassPionChargedSquared = o2::constants::physics::MassPionCharged * o2::constants::physics::MassPionCharged; @@ -1283,8 +1423,9 @@ struct StrangenessInJets { } // Skip events with no particles - if (fjParticles.size() < 1) + if (fjParticles.size() < 1) { continue; + } registryMC.fill(HIST("number_of_events_mc_gen"), 3.5); // Cluster MC particles into jets using anti-kt algorithm @@ -1298,112 +1439,92 @@ struct StrangenessInJets { for (const auto& jet : jets) { // Jet must be fully contained in acceptance - if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) + if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) { continue; + } // Subtract background energy from jet - auto jetForSub = jet; + const auto& jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); // Apply jet pT threshold - if (jetMinusBkg.pt() < minJetPt) + if (jetMinusBkg.pt() < minJetPt) { continue; + } registryMC.fill(HIST("number_of_events_mc_gen"), 4.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_gen"), genMultiplicity); // Set up two perpendicular cone axes for underlying event estimation - TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - double coneRadius = std::sqrt(jet.area() / PI); + const TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + const double coneRadius = std::sqrt(jet.area() / PI); TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularDirections(jetAxis, ueAxis1, ueAxis2); if (ueAxis1.Mag() == 0 || ueAxis2.Mag() == 0) { continue; } - // Loop over strange hadrons - int index = -1; - for (const auto& hadron : strHadronMomentum) { - - // Particle index - index++; + registryMC.fill(HIST("number_of_jets_vsmultiplicity"), genMultiplicity); + // Loop over strange hadrons + for (const auto& hadron : hadronMomentum) { // Compute distance of particles from jet and UE axes - double deltaEtaJet = hadron.Eta() - jetAxis.Eta(); - double deltaPhiJet = getDeltaPhi(hadron.Phi(), jetAxis.Phi()); - double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - double deltaEtaUe1 = hadron.Eta() - ueAxis1.Eta(); - double deltaPhiUe1 = getDeltaPhi(hadron.Phi(), ueAxis1.Phi()); - double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - double deltaEtaUe2 = hadron.Eta() - ueAxis2.Eta(); - double deltaPhiUe2 = getDeltaPhi(hadron.Phi(), ueAxis2.Phi()); - double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + const double deltaEtaJet = hadron.first.Eta() - jetAxis.Eta(); + const double deltaPhiJet = ParticlePositionWithRespectToJet::getDeltaPhi(hadron.first.Phi(), jetAxis.Phi()); + const double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + const double deltaEtaUe1 = hadron.first.Eta() - ueAxis1.Eta(); + const double deltaPhiUe1 = ParticlePositionWithRespectToJet::getDeltaPhi(hadron.first.Phi(), ueAxis1.Phi()); + const double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + const double deltaEtaUe2 = hadron.first.Eta() - ueAxis2.Eta(); + const double deltaPhiUe2 = ParticlePositionWithRespectToJet::getDeltaPhi(hadron.first.Phi(), ueAxis2.Phi()); + const double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); // Select particles inside jet if (deltaRJet < coneRadius) { - switch (pdg[index]) { + switch (hadron.second) { case kK0Short: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.fill(HIST("K0s_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("K0s_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kLambda0: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.fill(HIST("Lambda_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("Lambda_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kLambda0Bar: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.fill(HIST("AntiLambda_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("AntiLambda_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kXiMinus: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("XiNeg_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("XiNeg_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kXiPlusBar: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("XiPos_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("XiPos_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kOmegaMinus: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("OmegaNeg_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("OmegaNeg_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kOmegaPlusBar: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("OmegaPos_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("OmegaPos_generated_jet"), genMultiplicity, hadron.first.Pt()); } break; case kPiPlus: - if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("ll_generated_in_jet"), genMultiplicity, hadron.Pt()); - } - break; - case kKPlus: - if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("ll_generated_in_jet"), genMultiplicity, hadron.Pt()); - } - break; - case kProton: - if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("ll_generated_in_jet"), genMultiplicity, hadron.Pt()); - } - break; case kPiMinus: - if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("ll_generated_in_jet"), genMultiplicity, hadron.Pt() * -1.f); - } - break; + case kKPlus: case kKMinus: - if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("ll_generated_in_jet"), genMultiplicity, hadron.Pt() * -1.f); - } - break; + case kProton: case kProtonBar: - if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("ll_generated_in_jet"), genMultiplicity, hadron.Pt() * -1.f); + float particleId, chargeId; + if (pdgToLongLivedIndex(hadron.second, particleId, chargeId)) { + registryMC.fill(HIST("LongLivedGenerated"), 1.f, particleId, chargeId, hadron.first.Pt(), genMultiplicity); } break; default: @@ -1413,70 +1534,51 @@ struct StrangenessInJets { // Select particles inside UE cones if (deltaRUe1 < coneRadius || deltaRUe2 < coneRadius) { - switch (pdg[index]) { + switch (hadron.second) { case kK0Short: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.fill(HIST("K0s_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("K0s_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kLambda0: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.fill(HIST("Lambda_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("Lambda_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kLambda0Bar: if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { - registryMC.fill(HIST("AntiLambda_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("AntiLambda_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kXiMinus: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("XiNeg_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("XiNeg_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kXiPlusBar: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("XiPos_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("XiPos_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kOmegaMinus: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("OmegaNeg_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("OmegaNeg_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kOmegaPlusBar: if (enabledSignals.value[ParticleOfInterest::kCascades]) { - registryMC.fill(HIST("OmegaPos_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("OmegaPos_generated_ue"), genMultiplicity, hadron.first.Pt()); } break; case kPiPlus: - if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("ll_generated_in_ue"), genMultiplicity, hadron.Pt()); - } - break; - case kKPlus: - if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("ll_generated_in_ue"), genMultiplicity, hadron.Pt()); - } - break; - case kProton: - if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("ll_generated_in_ue"), genMultiplicity, hadron.Pt()); - } - break; case kPiMinus: - if (enabledSignals.value[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("ll_generated_in_ue"), genMultiplicity, hadron.Pt() * -1.f); - } - break; + case kKPlus: case kKMinus: - if (enabledSignals.value[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("ll_generated_in_ue"), genMultiplicity, hadron.Pt() * -1.f); - } - break; + case kProton: case kProtonBar: - if (enabledSignals.value[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("ll_generated_in_ue"), genMultiplicity, hadron.Pt() * -1.f); + float particleId, chargeId; + if (pdgToLongLivedIndex(hadron.second, particleId, chargeId)) { + registryMC.fill(HIST("LongLivedGenerated"), -1.f, particleId, chargeId, hadron.first.Pt(), genMultiplicity); } break; default: @@ -1536,9 +1638,10 @@ struct StrangenessInJets { const float multiplicity = mcCollision.centFT0M(); // Number of V0 and cascades per collision - auto v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); - auto cascPerColl = Cascades.sliceBy(perCollisionCasc, collision.globalIndex()); - auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + const auto& v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); + const auto& cascPerColl = Cascades.sliceBy(perCollisionCasc, collision.globalIndex()); + const auto& tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + const auto& mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, mcCollision.globalIndex()); // V0 particles if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { @@ -1562,6 +1665,9 @@ struct StrangenessInJets { if (!motherPos.isPhysicalPrimary()) continue; + if (std::abs(motherPos.eta()) > 0.8) + continue; + // K0s if (passedK0ShortSelection(v0, pos, neg) && motherPos.pdgCode() == kK0Short) { registryMC.fill(HIST("K0s_reconstructed_fullevent"), multiplicity, v0.pt()); @@ -1623,13 +1729,96 @@ struct StrangenessInJets { } } + // Long lived + if (enabledSignals.value[ParticleOfInterest::kPions] || + enabledSignals.value[ParticleOfInterest::kKaons] || + enabledSignals.value[ParticleOfInterest::kProtons]) { + for (const auto& trk : tracksPerColl) { + + if (!trk.has_mcParticle()) { + continue; + } + if (!passedSingleTrackSelection(trk)) { + continue; + } + const auto& mcParticle = trk.mcParticle_as(); + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + + if (std::abs(mcParticle.eta()) > 0.8) { + continue; + } + + switch (mcParticle.pdgCode()) { + case kPiPlus: + if (enabledSignals.value[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("Pion_Plus_reconstructed_fullevent"), multiplicity, trk.pt()); + } + break; + case kPiMinus: + if (enabledSignals.value[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("Pion_Minus_reconstructed_fullevent"), multiplicity, trk.pt()); + } + break; + case kKPlus: + if (enabledSignals.value[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("Kaon_Plus_reconstructed_fullevent"), multiplicity, trk.pt()); + } + break; + case kKMinus: + if (enabledSignals.value[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("Kaon_Minus_reconstructed_fullevent"), multiplicity, trk.pt()); + } + break; + case kProton: + if (enabledSignals.value[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("Proton_Plus_reconstructed_fullevent"), multiplicity, trk.pt()); + } + break; + case kProtonBar: + if (enabledSignals.value[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("Proton_Minus_reconstructed_fullevent"), multiplicity, trk.pt()); + } + break; + default: + break; + } + } + } + + for (auto& particle : mcParticlesPerColl) { + + if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= 0.8) { + switch (particle.pdgCode()) { + case kK0Short: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_recoevent"), multiplicity, particle.pt()); + } + break; + case kLambda0: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_recoevent"), multiplicity, particle.pt()); + } + break; + case kLambda0Bar: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_recoevent"), multiplicity, particle.pt()); + } + break; + default: + break; + } + } + } + // Loop over reconstructed tracks - for (auto const& track : tracksPerColl) { - if (!passedTrackSelectionForJetReconstruction(track)) + for (auto const& trk : tracksPerColl) { + if (!passedTrackSelectionForJetReconstruction(trk)) continue; // 4-momentum representation of a particle - fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); + fastjet::PseudoJet fourMomentum(trk.px(), trk.py(), trk.pz(), trk.energy(o2::constants::physics::MassPionCharged)); fjParticles.emplace_back(fourMomentum); } @@ -1680,66 +1869,166 @@ struct StrangenessInJets { registryMC.fill(HIST("number_of_events_mc_rec"), 4.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_rec"), multiplicity); + // V0 particles + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + auto posParticle = pos.mcParticle_as(); + auto negParticle = neg.mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) + continue; + + // Get Mothers + auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + if (!motherPos.isPhysicalPrimary()) + continue; + + if (std::abs(motherPos.eta()) > 0.8) + continue; + + // K0s + if (passedK0ShortSelection(v0, pos, neg) && motherPos.pdgCode() == kK0Short) { + registryMC.fill(HIST("K0s_reconstructed_eventwjet"), multiplicity, v0.pt()); + } + // Lambda + if (passedLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0) { + registryMC.fill(HIST("Lambda_reconstructed_eventwjet"), multiplicity, v0.pt()); + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0Bar) { + registryMC.fill(HIST("AntiLambda_reconstructed_eventwjet"), multiplicity, v0.pt()); + } + } + } + + for (auto& particle : mcParticlesPerColl) { + + if (particle.isPhysicalPrimary() && std::abs(particle.eta()) <= 0.8) { + switch (particle.pdgCode()) { + case kK0Short: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_eventwjet"), multiplicity, particle.pt()); + } + break; + case kLambda0: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_eventwjet"), multiplicity, particle.pt()); + } + break; + case kLambda0Bar: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_eventwjet"), multiplicity, particle.pt()); + } + break; + default: + break; + } + } + } + // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { + for (auto& particle : mcParticlesPerColl) { + + const ParticlePositionWithRespectToJet positionMC{particle.px(), particle.py(), particle.pz(), selectedJet[i], ue1[i], ue2[i]}; + + if (particle.isPhysicalPrimary()) { + switch (particle.pdgCode()) { + case kK0Short: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + if (positionMC.isInJet()) { + registryMC.fill(HIST("K0s_generated_recojet_jet"), multiplicity, particle.pt()); + } + if (positionMC.isInUE1() || positionMC.isInUE2()) { + registryMC.fill(HIST("K0s_generated_recojet_ue"), multiplicity, particle.pt()); + } + } + break; + case kLambda0: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + if (positionMC.isInJet()) { + registryMC.fill(HIST("Lambda_generated_recojet_jet"), multiplicity, particle.pt()); + } + if (positionMC.isInUE1() || positionMC.isInUE2()) { + registryMC.fill(HIST("Lambda_generated_recojet_ue"), multiplicity, particle.pt()); + } + } + break; + case kLambda0Bar: + if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { + if (positionMC.isInJet()) { + registryMC.fill(HIST("AntiLambda_generated_recojet_jet"), multiplicity, particle.pt()); + } + if (positionMC.isInUE1() || positionMC.isInUE2()) { + registryMC.fill(HIST("AntiLambda_generated_recojet_ue"), multiplicity, particle.pt()); + } + } + break; + default: + break; + } + } + } + // V0 particles if (enabledSignals.value[ParticleOfInterest::kV0Particles]) { for (const auto& v0 : v0sPerColl) { const auto& pos = v0.posTrack_as(); const auto& neg = v0.negTrack_as(); - TVector3 v0dir(v0.px(), v0.py(), v0.pz()); // Get MC particles if (!pos.has_mcParticle() || !neg.has_mcParticle()) continue; - auto posParticle = pos.mcParticle_as(); - auto negParticle = neg.mcParticle_as(); - if (!posParticle.has_mothers() || !negParticle.has_mothers()) + const auto& posParticle = pos.mcParticle_as(); + const auto& negParticle = neg.mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) { continue; + } // Select particles originating from the same parent - auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); - auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); - if (motherPos != motherNeg) + const auto& motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + const auto& motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + if (motherPos != motherNeg) { continue; - bool isPhysPrim = motherPos.isPhysicalPrimary(); + } + const bool isPhysPrim = motherPos.isPhysicalPrimary(); // Compute distance from jet and UE axes - double deltaEtaJet = v0dir.Eta() - selectedJet[i].Eta(); - double deltaPhiJet = getDeltaPhi(v0dir.Phi(), selectedJet[i].Phi()); - double deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - double deltaEtaUe1 = v0dir.Eta() - ue1[i].Eta(); - double deltaPhiUe1 = getDeltaPhi(v0dir.Phi(), ue1[i].Phi()); - double deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - double deltaEtaUe2 = v0dir.Eta() - ue2[i].Eta(); - double deltaPhiUe2 = getDeltaPhi(v0dir.Phi(), ue2[i].Phi()); - double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + const ParticlePositionWithRespectToJet position{v0.px(), v0.py(), v0.pz(), selectedJet[i], ue1[i], ue2[i]}; // K0s if (passedK0ShortSelection(v0, pos, neg) && motherPos.pdgCode() == kK0Short && isPhysPrim) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("K0s_reconstructed_jet"), multiplicity, v0.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("K0s_reconstructed_ue"), multiplicity, v0.pt()); } } // Lambda if (passedLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0 && isPhysPrim) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("Lambda_reconstructed_jet"), multiplicity, v0.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("Lambda_reconstructed_ue"), multiplicity, v0.pt()); } } // AntiLambda if (passedAntiLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0Bar && isPhysPrim) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("AntiLambda_reconstructed_jet"), multiplicity, v0.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("AntiLambda_reconstructed_ue"), multiplicity, v0.pt()); } } @@ -1747,28 +2036,28 @@ struct StrangenessInJets { // Fill inclusive spectra // K0s if (passedK0ShortSelection(v0, pos, neg) && motherPos.pdgCode() == kK0Short) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("K0s_reconstructed_jet_incl"), multiplicity, v0.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("K0s_reconstructed_ue_incl"), multiplicity, v0.pt()); } } // Lambda if (passedLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("Lambda_reconstructed_jet_incl"), multiplicity, v0.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("Lambda_reconstructed_ue_incl"), multiplicity, v0.pt()); } } // AntiLambda if (passedAntiLambdaSelection(v0, pos, neg) && motherPos.pdgCode() == kLambda0Bar) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("AntiLambda_reconstructed_jet_incl"), multiplicity, v0.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("AntiLambda_reconstructed_ue_incl"), multiplicity, v0.pt()); } } @@ -1778,23 +2067,23 @@ struct StrangenessInJets { // Cascades if (enabledSignals.value[ParticleOfInterest::kCascades]) { for (const auto& casc : cascPerColl) { - auto bach = casc.bachelor_as(); - auto pos = casc.posTrack_as(); - auto neg = casc.negTrack_as(); + const auto& bach = casc.bachelor_as(); + const auto& pos = casc.posTrack_as(); + const auto& neg = casc.negTrack_as(); // Get MC particles if (!bach.has_mcParticle() || !pos.has_mcParticle() || !neg.has_mcParticle()) continue; - auto posParticle = pos.mcParticle_as(); - auto negParticle = neg.mcParticle_as(); - auto bachParticle = bach.mcParticle_as(); + const auto& posParticle = pos.mcParticle_as(); + const auto& negParticle = neg.mcParticle_as(); + const auto& bachParticle = bach.mcParticle_as(); if (!posParticle.has_mothers() || !negParticle.has_mothers() || !bachParticle.has_mothers()) continue; // Select particles originating from the same parent - auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); - auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); - auto motherBach = mcParticles.iteratorAt(bachParticle.mothersIds()[0]); + const auto& motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + const auto& motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + const auto& motherBach = mcParticles.iteratorAt(bachParticle.mothersIds()[0]); if (motherPos != motherNeg) continue; if (std::abs(motherPos.pdgCode()) != kLambda0) @@ -1803,55 +2092,78 @@ struct StrangenessInJets { continue; // Compute distances from jet and UE axes - TVector3 cascadeDir(casc.px(), casc.py(), casc.pz()); - double deltaEtaJet = cascadeDir.Eta() - selectedJet[i].Eta(); - double deltaPhiJet = getDeltaPhi(cascadeDir.Phi(), selectedJet[i].Phi()); - double deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - double deltaEtaUe1 = cascadeDir.Eta() - ue1[i].Eta(); - double deltaPhiUe1 = getDeltaPhi(cascadeDir.Phi(), ue1[i].Phi()); - double deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - double deltaEtaUe2 = cascadeDir.Eta() - ue2[i].Eta(); - double deltaPhiUe2 = getDeltaPhi(cascadeDir.Phi(), ue2[i].Phi()); - double deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + const ParticlePositionWithRespectToJet position{casc.px(), casc.py(), casc.pz(), selectedJet[i], ue1[i], ue2[i]}; // Xi+ if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && motherBach.pdgCode() == kXiPlusBar) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("XiPos_reconstructed_jet"), multiplicity, casc.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("XiPos_reconstructed_ue"), multiplicity, casc.pt()); } } // Xi- if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && motherBach.pdgCode() == kXiMinus) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("XiNeg_reconstructed_jet"), multiplicity, casc.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("XiNeg_reconstructed_ue"), multiplicity, casc.pt()); } } // Omega+ if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && motherBach.pdgCode() == kOmegaPlusBar) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("OmegaPos_reconstructed_jet"), multiplicity, casc.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("OmegaPos_reconstructed_ue"), multiplicity, casc.pt()); } } // Omega- if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && motherBach.pdgCode() == kOmegaMinus) { - if (deltaRjet < rJet) { + if (position.isInJet()) { registryMC.fill(HIST("OmegaNeg_reconstructed_jet"), multiplicity, casc.pt()); } - if (deltaRue1 < rJet || deltaRue2 < rJet) { + if (position.isInUE1() || position.isInUE2()) { registryMC.fill(HIST("OmegaNeg_reconstructed_ue"), multiplicity, casc.pt()); } } } } + + // Long lived + if (enabledSignals.value[ParticleOfInterest::kPions] || + enabledSignals.value[ParticleOfInterest::kKaons] || + enabledSignals.value[ParticleOfInterest::kProtons]) { + for (const auto& trk : tracksPerColl) { + + if (!trk.has_mcParticle()) { + continue; + } + const auto& mcParticle = trk.mcParticle_as(); + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + if (!passedSingleTrackSelection(trk)) { + continue; + } + + // Compute distances from jet and UE axes + const ParticlePositionWithRespectToJet position{trk.px(), trk.py(), trk.pz(), selectedJet[i], ue1[i], ue2[i]}; + + float particleId, chargeId; + if (pdgToLongLivedIndex(mcParticle.pdgCode(), particleId, chargeId)) { + if (position.isInJet()) { + registryMC.fill(HIST("LongLivedReconstructed"), 1.f, particleId, chargeId, trk.pt(), multiplicity, (trk.hasTOF() ? 1 : 0)); + } + if (position.isInUE1() || position.isInUE2()) { + registryMC.fill(HIST("LongLivedReconstructed"), -1.f, particleId, chargeId, trk.pt(), multiplicity, (trk.hasTOF() ? 1 : 0)); + } + } + } + } } } } @@ -1883,7 +2195,7 @@ struct StrangenessInJets { continue; // PID selections - Bool_t isPIDK0s = false, isPIDLam = false, isPIDALam = false; + bool isPIDK0s = false, isPIDLam = false, isPIDALam = false; // PID selections (TPC) -- K0s if (v0.ntpcsigmapospi() >= nsigmaTPCmin && v0.ntpcsigmapospi() <= nsigmaTPCmax && @@ -1903,38 +2215,44 @@ struct StrangenessInJets { isPIDALam = true; } + bool isK0Comp = std::abs(v0.massk0short() - o2::constants::physics::MassK0Short) < k0sRejWindow; + bool isLamComp = (std::abs(v0.masslambda() - o2::constants::physics::MassLambda) < lamRejWindow) || (std::abs(v0.massantilambda() - o2::constants::physics::MassLambda) < lamRejWindow); + + bool acceptAsK0s = isPIDK0s && (!doLamRej || !isLamComp); + bool acceptAsLam = isPIDLam && (!doK0sRej || !isK0Comp); + bool acceptAsALam = isPIDALam && (!doK0sRej || !isK0Comp); + if (v0.isUE()) { - if (isPIDK0s) { + if (acceptAsK0s) registryData.fill(HIST("K0s_in_ue"), v0.multft0m(), v0.pt(), v0.massk0short()); - } - if (isPIDLam) { + if (acceptAsLam) registryData.fill(HIST("Lambda_in_ue"), v0.multft0m(), v0.pt(), v0.masslambda()); - } - if (isPIDALam) { + if (acceptAsALam) registryData.fill(HIST("AntiLambda_in_ue"), v0.multft0m(), v0.pt(), v0.massantilambda()); - } - } else if (v0.isJC()) { - if (isPIDK0s) { + } + + if (v0.isJC()) { + if (acceptAsK0s) registryData.fill(HIST("K0s_in_jet"), v0.multft0m(), v0.pt(), v0.massk0short()); - } - if (isPIDLam) { + if (acceptAsLam) registryData.fill(HIST("Lambda_in_jet"), v0.multft0m(), v0.pt(), v0.masslambda()); - } - if (isPIDALam) { + if (acceptAsALam) registryData.fill(HIST("AntiLambda_in_jet"), v0.multft0m(), v0.pt(), v0.massantilambda()); - } } } for (const auto& casc : cascades) { - if (casc.v0negITSlayers() < minITSnCls || casc.v0posITSlayers() < minITSnCls || casc.bachITSlayers() < minITSnCls) + // Track selections + if (requireITS && (casc.v0negITSlayers() < minITSnCls || casc.v0posITSlayers() < minITSnCls || casc.bachITSlayers() < minITSnCls)) continue; if (casc.v0negtpcCrossedRows() < minNCrossedRowsTPC || casc.v0postpcCrossedRows() < minNCrossedRowsTPC || casc.bachtpcCrossedRows() < minNCrossedRowsTPC) continue; if (casc.v0negTPCChi2() > maxChi2TPC || casc.v0posTPCChi2() > maxChi2TPC || casc.bachTPCChi2() > maxChi2TPC) continue; + + // Topological selections if (casc.v0cospa() < v0cospaMin) continue; if (casc.casccospa() < casccospaMin) @@ -1955,128 +2273,373 @@ struct StrangenessInJets { continue; if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) continue; - // Xi - // Xi+ selection (Xi+ -> antiL + pi+) - if (casc.sign() > 0) { - // PID selections (TPC) - if (casc.ntpcsigmanegpr() < nsigmaTPCmin || casc.ntpcsigmanegpr() > nsigmaTPCmax) - continue; - if (casc.ntpcsigmapospi() < nsigmaTPCmin || casc.ntpcsigmapospi() > nsigmaTPCmax) - continue; - // PID selections (TOF) - if (requireTOF) { - if (casc.ntofsigmanegpr() < nsigmaTOFmin || casc.ntofsigmanegpr() > nsigmaTOFmax) - continue; - if (casc.ntofsigmapospi() < nsigmaTOFmin || casc.ntofsigmapospi() > nsigmaTOFmax) - continue; - } - } - // Xi- selection (Xi- -> L + pi-) - if (casc.sign() < 0) { - // PID selections (TPC) - if (casc.ntpcsigmapospr() < nsigmaTPCmin || casc.ntpcsigmapospr() > nsigmaTPCmax) - continue; - if (casc.ntpcsigmanegpi() < nsigmaTPCmin || casc.ntpcsigmanegpi() > nsigmaTPCmax) - continue; + // PID selection + bool isPIDXiminus = false, isPIDXiplus = false, isPIDOmminus = false, isPIDOmplus = false; - // PID selections (TOF) - if (requireTOF) { - if (casc.ntofsigmapospr() < nsigmaTOFmin || casc.ntofsigmapospr() > nsigmaTOFmax) - continue; - if (casc.ntofsigmanegpi() < nsigmaTOFmin || casc.ntofsigmanegpi() > nsigmaTOFmax) - continue; + // PID selection bachelor + bool isPIDLam = false, isPIDALam = false; + if (casc.sign() > 0) { + // antiLambda: (p-)neg + (pi+)pos + if (casc.ntpcsigmanegpr() >= nsigmaTPCmin && casc.ntpcsigmanegpr() <= nsigmaTPCmax && + casc.ntpcsigmapospi() >= nsigmaTPCmin && casc.ntpcsigmapospi() <= nsigmaTPCmax) { + isPIDALam = true; + } + } else if (casc.sign() < 0) { + // lambda: (p+)pos + (pi-)neg + if (casc.ntpcsigmapospr() >= nsigmaTPCmin && casc.ntpcsigmapospr() <= nsigmaTPCmax && + casc.ntpcsigmanegpi() >= nsigmaTPCmin && casc.ntpcsigmanegpi() <= nsigmaTPCmax) { + isPIDLam = true; } } - // PID selection on bachelor - if (casc.ntpcsigmabachpi() < nsigmaTPCmin || casc.ntpcsigmabachpi() > nsigmaTPCmax) + if (!(isPIDLam || isPIDALam)) continue; - // PID selections (TOF) - if (requireTOF) { - if (casc.ntofsigmabachpi() < nsigmaTOFmin || casc.ntofsigmabachpi() > nsigmaTOFmax) - continue; - } // V0 mass window if (std::fabs(casc.masslambda() - o2::constants::physics::MassLambda0) > deltaMassLambda) continue; - // Reject candidates compatible with Omega - if (std::fabs(casc.massomega() - o2::constants::physics::MassOmegaMinus) < deltaMassOmega) - continue; - // Omega - // Omega+ selection (Omega+ -> antiL + K+) + // PID selection on bachelor + const bool isBachPi = + (casc.ntpcsigmabachpi() >= nsigmaTPCmin && casc.ntpcsigmabachpi() <= nsigmaTPCmax); + + const bool isBachKa = + (casc.ntpcsigmabachka() >= nsigmaTPCmin && casc.ntpcsigmabachka() <= nsigmaTPCmax); + + // Cross-contamination rejection flags + const bool isOmegaLike = (std::fabs(casc.massomega() - o2::constants::physics::MassOmegaMinus) < deltaMassOmega); + const bool isXiLike = (std::fabs(casc.massxi() - o2::constants::physics::MassXiMinus) < deltaMassXi); + + // Final PID flags if (casc.sign() > 0) { - // PID selections (TPC) - if (casc.ntpcsigmanegpr() < nsigmaTPCmin || casc.ntpcsigmanegpr() > nsigmaTPCmax) + if (isPIDALam && isBachPi && !isOmegaLike) + isPIDXiplus = true; + if (isPIDALam && isBachKa && !isXiLike) + isPIDOmplus = true; + } else if (casc.sign() < 0) { + if (isPIDLam && isBachPi && !isOmegaLike) + isPIDXiminus = true; + if (isPIDLam && isBachKa && !isXiLike) + isPIDOmminus = true; + } + + if (casc.isUE()) { + if (isPIDXiminus) + registryData.fill(HIST("XiNeg_in_ue"), casc.multft0m(), casc.pt(), casc.massxi()); + if (isPIDXiplus) + registryData.fill(HIST("XiPos_in_ue"), casc.multft0m(), casc.pt(), casc.massxi()); + if (isPIDOmminus) + registryData.fill(HIST("OmegaNeg_in_ue"), casc.multft0m(), casc.pt(), casc.massomega()); + if (isPIDOmplus) + registryData.fill(HIST("OmegaPos_in_ue"), casc.multft0m(), casc.pt(), casc.massomega()); + } else if (casc.isJC()) { + if (isPIDXiminus) + registryData.fill(HIST("XiNeg_in_jet"), casc.multft0m(), casc.pt(), casc.massxi()); + if (isPIDXiplus) + registryData.fill(HIST("XiPos_in_jet"), casc.multft0m(), casc.pt(), casc.massxi()); + if (isPIDOmminus) + registryData.fill(HIST("OmegaNeg_in_jet"), casc.multft0m(), casc.pt(), casc.massomega()); + if (isPIDOmplus) + registryData.fill(HIST("OmegaPos_in_jet"), casc.multft0m(), casc.pt(), casc.massomega()); + } + } + } + PROCESS_SWITCH(StrangenessInJets, processDerivedAnalysis, "Postprocessing for derived data analysis", false); + + // Process MC K0 short in jets + void processMCK0shortInJets(SimCollisions const& collisions, soa::Join const&, + DaughterTracksMC const& mcTracks, aod::V0Datas const& fullV0s, aod::McParticles const& mcParticles) + { + // Define particle container for FastJet and array of vectors for selected jets + std::vector fjParticles; + std::vector selectedJet; + + // Jet and area definitions + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over all reconstructed collisions + for (const auto& collision : collisions) { + + // Clear containers at the start of the event loop + fjParticles.clear(); + selectedJet.clear(); + + // Apply event selection: require sel8 and vertex position to be within 10 cm from ALICE center + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + continue; + + // Reject events near the ITS Read-Out Frame border + if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + + // Reject events at the Time Frame border + if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + + // Require at least one ITS-TPC matched track + if (!collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + + // Reject events with same-bunch pileup + if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + + // Require consistent FT0 vs PV z-vertex + if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + + const auto& v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); + const auto& tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + + // Loop over reconstructed tracks + int id(-1); + for (auto const& track : tracksPerColl) { + id++; + + // Ensure tracks have corresponding MC particles + if (!track.has_mcParticle()) continue; - if (casc.ntpcsigmapospi() < nsigmaTPCmin || casc.ntpcsigmapospi() > nsigmaTPCmax) + + // Apply track selection for jet reconstruction + if (!passedTrackSelectionForJetReconstruction(track)) continue; - // PID selections (TOF) - if (requireTOF) { - if (casc.ntofsigmanegpr() < nsigmaTOFmin || casc.ntofsigmanegpr() > nsigmaTOFmax) - continue; - if (casc.ntofsigmapospi() < nsigmaTOFmin || casc.ntofsigmapospi() > nsigmaTOFmax) - continue; - } + // Store particle in particle container + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(o2::constants::physics::MassPionCharged)); + fourMomentum.set_user_index(id); + fjParticles.emplace_back(fourMomentum); } - // Omega- selection (Omega- -> L + K-) - if (casc.sign() < 0) { - // PID selections (TPC) - if (casc.ntpcsigmapospr() < nsigmaTPCmin || casc.ntpcsigmapospr() > nsigmaTPCmax) + // Reject empty events + if (fjParticles.empty()) + continue; + + // Cluster particles using the anti-kt algorithm + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); + + // Loop over reconstructed jets + for (const auto& jet : jets) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) continue; - if (casc.ntpcsigmanegpi() < nsigmaTPCmin || casc.ntpcsigmanegpi() > nsigmaTPCmax) + + // Jet pt must be larger than threshold + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < minJetPt) continue; - // PID selections (TOF) - if (requireTOF) { - if (casc.ntofsigmapospr() < nsigmaTOFmin || casc.ntofsigmapospr() > nsigmaTOFmax) + // Jet axis + TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + selectedJet.emplace_back(jetAxis); + + // Containers + std::vector pions; + std::vector jetConstituents = jet.constituents(); + + // Loop over jet constituents + for (const auto& particle : jetConstituents) { + + auto const& track = mcTracks.iteratorAt(particle.user_index()); + const auto mcparticle = track.mcParticle(); + if (std::abs(mcparticle.pdgCode()) != PDG_t::kPiPlus) + continue; + + auto motherId = mcparticle.mothersIds()[0]; + if (motherId < 0) continue; - if (casc.ntofsigmanegpi() < nsigmaTOFmin || casc.ntofsigmanegpi() > nsigmaTOFmax) + + auto mother = mcParticles.iteratorAt(motherId); + if (std::abs(mother.pdgCode()) != kK0Short) continue; + + pions.push_back({track.pt(), mcparticle.pt(), mcparticle.pdgCode(), motherId}); } - } - // PID selection on bachelor - if (casc.ntpcsigmabachka() < nsigmaTPCmin || casc.ntpcsigmabachka() > nsigmaTPCmax) + const int minimumSize = 2; + if (static_cast(pions.size()) < minimumSize) + continue; + + for (int i = 0; i < static_cast(pions.size()); i++) { + for (int j = i + 1; j < static_cast(pions.size()); j++) { + + if (pions[i].idParent != pions[j].idParent) + continue; + if (pions[i].pdgCode == pions[j].pdgCode) + continue; + + registryMC.fill(HIST("fractionJetPtCarriedByK0"), (pions[i].ptRec + pions[j].ptRec) / jetMinusBkg.pt()); + registryMC.fill(HIST("ptSpectrumK0DaughtersInJet"), pions[i].ptGen + pions[j].ptGen); + } + } + } // end loop over jets + + for (int i = 0; i < static_cast(selectedJet.size()); i++) { + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + const auto& posParticle = pos.mcParticle_as(); + const auto& negParticle = neg.mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) + continue; + + // Select particles originating from the same parent + if (posParticle.mothersIds()[0] != negParticle.mothersIds()[0]) + continue; + + const auto& mother = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + if (mother.pdgCode() != kK0Short) + continue; + + TVector3 v0dir(v0.px(), v0.py(), v0.pz()); + float deltaEtaJet = v0dir.Eta() - selectedJet[i].Eta(); + float deltaPhiJet = ParticlePositionWithRespectToJet::getDeltaPhi(v0dir.Phi(), selectedJet[i].Phi()); + float deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + + if (deltaRjet < rJet && passedK0ShortSelection(v0, pos, neg)) + registryMC.fill(HIST("ptSpectrumK0DaughtersAll"), mother.pt()); + } // end loop on V0s + } // end loop on selected jets + } // end loop on collisions + } + PROCESS_SWITCH(StrangenessInJets, processMCK0shortInJets, "process reconstructed events", false); + + // Reconstructed jets including K0s + void processMCRecK0inJet(SimCollisions const& collisions, soa::Join const&, + DaughterTracksMC const& mcTracks, aod::V0Datas const& fullV0s, aod::McParticles const& mcParticles) + { + // Define per-event containers + std::vector fjParticles; + std::vector selectedJet; + + // Jet and area definitions + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + + // Loop over reconstructed collisions + for (const auto& collision : collisions) { + + // Select reconstructed collisions with corresponding MC generated collision + if (!collision.has_mcCollision()) continue; + const auto& mcCollision = collision.mcCollision_as>(); - // PID selections (TOF) - if (requireTOF) { - if (casc.ntofsigmabachka() < nsigmaTOFmin || casc.ntofsigmabachka() > nsigmaTOFmax) + // Clear containers at the start of the event loop + fjParticles.clear(); + selectedJet.clear(); + + // Apply event selection + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + continue; + + // Event multiplicity + const float multiplicity = mcCollision.centFT0M(); + + // Number of V0 and tracks per collision + const auto& v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); + const auto& tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + + // Loop over reconstructed tracks + for (auto const& trk : tracksPerColl) { + if (!passedTrackSelectionForJetReconstruction(trk)) continue; + + // 4-momentum representation of a particle + fastjet::PseudoJet fourMomentum(trk.px(), trk.py(), trk.pz(), trk.energy(o2::constants::physics::MassPionCharged)); + fjParticles.emplace_back(fourMomentum); } - // V0 mass window - if (std::fabs(casc.masslambda() - o2::constants::physics::MassLambda0) > deltaMassLambda) + + // Add K0s daughters to particle container + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + if (passedK0ShortSelection(v0, pos, neg)) { + double energy = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz() + o2::constants::physics::MassK0Short * o2::constants::physics::MassK0Short); + fastjet::PseudoJet fourMomentum(v0.px(), v0.py(), v0.pz(), energy); + fjParticles.emplace_back(fourMomentum); + } + } + + // Reject empty events + if (fjParticles.size() < 1) continue; - // Reject candidates compatible with Xi - if (std::fabs(casc.massxi() - o2::constants::physics::MassXiMinus) < deltaMassXi) + // Cluster particles using the anti-kt algorithm + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + if (jets.empty()) continue; + auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); - if (casc.isUE()) { - if (casc.sign() < 0) { - registryData.fill(HIST("XiNeg_in_ue"), casc.multft0m(), casc.pt(), casc.massxi()); - registryData.fill(HIST("OmegaNeg_in_ue"), casc.multft0m(), casc.pt(), casc.massomega()); - } else if (casc.sign() > 0) { - registryData.fill(HIST("XiPos_in_ue"), casc.multft0m(), casc.pt(), casc.massxi()); - registryData.fill(HIST("OmegaPos_in_ue"), casc.multft0m(), casc.pt(), casc.massomega()); - } - } else if (casc.isJC()) { - if (casc.sign() < 0) { - registryData.fill(HIST("XiNeg_in_jet"), casc.multft0m(), casc.pt(), casc.massxi()); - registryData.fill(HIST("OmegaNeg_in_jet"), casc.multft0m(), casc.pt(), casc.massomega()); - } else if (casc.sign() > 0) { - registryData.fill(HIST("XiPos_in_jet"), casc.multft0m(), casc.pt(), casc.massxi()); - registryData.fill(HIST("OmegaPos_in_jet"), casc.multft0m(), casc.pt(), casc.massomega()); - } + // Jet selection + bool isAtLeastOneJetSelected = false; + + // Loop over clustered jets + for (const auto& jet : jets) { + + // jet must be fully contained in the acceptance + if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) + continue; + + // jet pt must be larger than threshold + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < minJetPt) + continue; + isAtLeastOneJetSelected = true; + + // Store selected jet axis + TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + selectedJet.emplace_back(jetAxis); } + if (!isAtLeastOneJetSelected) + continue; + + // Loop over selected jets + for (int i = 0; i < static_cast(selectedJet.size()); i++) { + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.posTrack_as(); + const auto& neg = v0.negTrack_as(); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + const auto& posParticle = pos.mcParticle_as(); + const auto& negParticle = neg.mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) + continue; + + // Select particles originating from the same parent + const auto& motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + const auto& motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + const bool isPhysPrim = motherPos.isPhysicalPrimary(); + + // Distance of K0s from jet axis + TVector3 v0dir(v0.px(), v0.py(), v0.pz()); + const double deltaEtaJet = v0dir.Eta() - selectedJet[i].Eta(); + const double deltaPhiJet = ParticlePositionWithRespectToJet::getDeltaPhi(v0dir.Phi(), selectedJet[i].Phi()); + const double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + + // Fill histogram + if (passedK0ShortSelection(v0, pos, neg) && motherPos.pdgCode() == kK0Short && isPhysPrim && deltaRJet < rJet) { + registryMC.fill(HIST("K0s_reconstructed_jet_withK0"), multiplicity, v0.pt()); + } + } // end loop on V0s + } // end loop on jets } } - PROCESS_SWITCH(StrangenessInJets, processDerivedAnalysis, "Postprocessing for derived data analysis", false); + PROCESS_SWITCH(StrangenessInJets, processMCRecK0inJet, "process reconstructed K0s in jets", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx index 7d23099b6ff..cefeec99ce6 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJetsIons.cxx @@ -76,11 +76,13 @@ using namespace o2::constants::math; using std::array; // Define convenient aliases for joined AOD tables -using SelCollisions = soa::Join; +using SelCollisions = soa::Join; using SimCollisions = soa::Join; + aod::EvSels>; using DaughterTracks = soa::Join; @@ -118,67 +120,87 @@ struct StrangenessInJetsIons { Configurable> particleOfInterest{"particleOfInterest", {0, 0, 0, 0, 0}, "Particles to study: [K0 and Lambda, Xi and Omega, Pion, Kaon, Proton]"}; Configurable minJetPt{"minJetPt", 10.0, "Minimum reconstructed pt of the jet (GeV/c)"}; - Configurable rJet{"rJet", 0.3, "Jet resolution parameter (R)"}; + Configurable rJet{"rJet", 0.4, "Jet resolution parameter (R)"}; Configurable zVtx{"zVtx", 10.0, "Maximum z-vertex position"}; Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from detector edge"}; Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Enable processing of skimmed data"}; Configurable triggerName{"triggerName", "fOmega", "Software trigger name"}; + Configurable centrEstimator{"centrEstimator", 1, "Select centrality estimator. Options: 0 = FT0C, 1 = FT0M. CCDB objects available only for FT0M."}; // Event selection Configurable requireNoSameBunchPileup{"requireNoSameBunchPileup", true, "Require kNoSameBunchPileup selection"}; Configurable requireGoodZvtxFT0vsPV{"requireGoodZvtxFT0vsPV", true, "Require kIsGoodZvtxFT0vsPV selection"}; // Track analysis parameters - Configurable minITSnCls{"minITSnCls", 4, "Minimum number of ITS clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "Minimum number of TPC crossed rows"}; - Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "Maximum chi2 per cluster TPC"}; - Configurable etaMin{"etaMin", -0.8f, "Minimum eta"}; - Configurable etaMax{"etaMax", +0.8f, "Maximum eta"}; - Configurable ptMinV0Proton{"ptMinV0Proton", 0.0f, "Minimum pt of protons from V0"}; - Configurable ptMaxV0Proton{"ptMaxV0Proton", 100.0f, "Maximum pt of protons from V0"}; - Configurable ptMinV0Pion{"ptMinV0Pion", 0.0f, "Minimum pt of pions from V0"}; - Configurable ptMaxV0Pion{"ptMaxV0Pion", 100.0f, "Maximum pt of pions from V0"}; - Configurable ptMinK0Pion{"ptMinK0Pion", 0.0f, "Minimum pt of pions from K0"}; - Configurable ptMaxK0Pion{"ptMaxK0Pion", 100.0f, "Maximum pt of pions from K0"}; - Configurable nsigmaTPCmin{"nsigmaTPCmin", -3.0f, "Minimum nsigma TPC"}; - Configurable nsigmaTPCmax{"nsigmaTPCmax", +3.0f, "Maximum nsigma TPC"}; - Configurable nsigmaTOFmin{"nsigmaTOFmin", -3.0f, "Minimum nsigma TOF"}; - Configurable nsigmaTOFmax{"nsigmaTOFmax", +3.0f, "Maximum nsigma TOF"}; - Configurable requireITS{"requireITS", false, "Require ITS hit"}; - Configurable requireTOF{"requireTOF", false, "Require TOF hit"}; + struct : ConfigurableGroup { + // std::string prefix = "configTracks"; // name in JSON + Configurable minITSnCls{"minITSnCls", 4, "Minimum number of ITS clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "Minimum number of TPC crossed rows"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "Maximum chi2 per cluster TPC"}; + Configurable etaMin{"etaMin", -0.8f, "Minimum eta"}; + Configurable etaMax{"etaMax", +0.8f, "Maximum eta"}; + Configurable ptMinV0Proton{"ptMinV0Proton", 0.0f, "Minimum pt of protons from V0"}; + Configurable ptMaxV0Proton{"ptMaxV0Proton", 100.0f, "Maximum pt of protons from V0"}; + Configurable ptMinV0Pion{"ptMinV0Pion", 0.0f, "Minimum pt of pions from V0"}; + Configurable ptMaxV0Pion{"ptMaxV0Pion", 100.0f, "Maximum pt of pions from V0"}; + Configurable ptMinK0Pion{"ptMinK0Pion", 0.0f, "Minimum pt of pions from K0"}; + Configurable ptMaxK0Pion{"ptMaxK0Pion", 100.0f, "Maximum pt of pions from K0"}; + Configurable nsigmaTPCmin{"nsigmaTPCmin", -3.0f, "Minimum nsigma TPC"}; + Configurable nsigmaTPCmax{"nsigmaTPCmax", +3.0f, "Maximum nsigma TPC"}; + Configurable nsigmaTOFmin{"nsigmaTOFmin", -3.0f, "Minimum nsigma TOF"}; + Configurable nsigmaTOFmax{"nsigmaTOFmax", +3.0f, "Maximum nsigma TOF"}; + Configurable requireITS{"requireITS", false, "Require ITS hit"}; + Configurable requireTOF{"requireTOF", false, "Require TOF hit"}; + } configTracks; // V0 analysis parameters - Configurable minimumV0Radius{"minimumV0Radius", 1.2f, "Minimum V0 Radius (cm)"}; - Configurable maximumV0Radius{"maximumV0Radius", 40.0f, "Maximum V0 Radius (cm)"}; - Configurable v0cospaMin{"v0cospaMin", 0.995f, "Minimum V0 cosine of pointing angle"}; - Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 1.0f, "Maximum DCA between V0 daughters"}; - Configurable requireV0type{"requireV0type", true, "Require V0 type Cut"}; - Configurable v0type{"v0type", 1, "0: 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"}; - // K0S parameters - Configurable dcaNegToPVminK0s{"dcaNegToPVminK0s", 0.1f, "Minimum DCA of negative track to primary vertex in K0S decays (cm)"}; - Configurable dcaPosToPVminK0s{"dcaPosToPVminK0s", 0.1f, "Minimum DCA of positive track to primary vertex in K0S decays (cm)"}; - Configurable requireArmenterosCut{"requireArmenterosCut", true, "Require Armenteros Cut"}; - Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "Parameter Armenteros Cut (K0S only). This parameters multiplies alphaArm (Check if: qtarm >= this * |alphaArm|)"}; - Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0S (cm)"}; - // Lambda/anti-Lambda paramaters - Configurable dcaProtonToPVmin{"dcaProtonToPVmin", 0.05f, "Minimum DCA of proton/anti-proton track to primary vertex in Lambda/anti-Lambda decays (cm)"}; - Configurable dcaPionToPVmin{"dcaPionToPVmin", 0.2f, "Minimum DCA of pion-/pion+ track to primary vertex in Lambda/anti-Lambda decays (cm)"}; - Configurable ctauLambda{"ctauLambda", 30.0f, "C tau Lambda (cm)"}; + struct : ConfigurableGroup { + // std::string prefix = "configV0"; // name in JSON + Configurable minimumV0Radius{"minimumV0Radius", 1.2f, "Minimum V0 Radius (cm)"}; + // Configurable maximumV0Radius{"maximumV0Radius", 40.0f, "Maximum V0 Radius (cm)"}; + Configurable v0cospaMin{"v0cospaMin", 0.995f, "Minimum V0 cosine of pointing angle"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 1.0f, "Maximum DCA between V0 daughters"}; + Configurable requireV0type{"requireV0type", true, "Require V0 type Cut"}; + Configurable v0type{"v0type", 1, "0: 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"}; + // K0S parameters + Configurable dcaNegToPVminK0s{"dcaNegToPVminK0s", 0.1f, "Minimum DCA of negative track to primary vertex in K0S decays (cm)"}; + Configurable dcaPosToPVminK0s{"dcaPosToPVminK0s", 0.1f, "Minimum DCA of positive track to primary vertex in K0S decays (cm)"}; + Configurable requireArmenterosCut{"requireArmenterosCut", true, "Require Armenteros Cut"}; + Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "Parameter Armenteros Cut (K0S only). This parameters multiplies alphaArm (Check if: qtarm >= this * |alphaArm|)"}; + Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0S (cm)"}; + Configurable requireK0sMassCuts{"requireK0sMassCuts", true, "[K0S] Require mass window for K0S selection and for Lambda rejection"}; + Configurable lamRejWindow{"lamRejWindow", 0.005f, "[K0S] Mass window for Lambda rejection"}; + Configurable k0sMassWindow{"k0sMassWindow", 0.1f, "[K0S] Mass window for K0S selection"}; + // Lambda/anti-Lambda paramaters + Configurable dcaProtonToPVmin{"dcaProtonToPVmin", 0.05f, "Minimum DCA of proton/anti-proton track to primary vertex in Lambda/anti-Lambda decays (cm)"}; + Configurable dcaPionToPVmin{"dcaPionToPVmin", 0.2f, "Minimum DCA of pion-/pion+ track to primary vertex in Lambda/anti-Lambda decays (cm)"}; + Configurable ctauLambda{"ctauLambda", 30.0f, "C tau Lambda (cm)"}; + Configurable requireLambdaMassCuts{"requireLambdaMassCuts", true, "[Lambda] Require mass window for Lambda selection and for K0S rejection"}; + Configurable k0sRejWindow{"k0sRejWindow", 0.010f, "[Lambda] Mass window for K0S rejection"}; + Configurable lamMassWindow{"lamMassWindow", 0.1f, "[Lambda] Mass window for Lambda selection"}; + } configV0; // Cascade analysis parameters - Configurable minimumCascRadius{"minimumCascRadius", 0.1f, "Minimum cascade radius"}; - Configurable maximumCascRadius{"maximumCascRadius", 40.0f, "Maximum cascade radius"}; - Configurable casccospaMin{"casccospaMin", 0.99f, "Minimum cascade cosine of pointing angle"}; - Configurable dcabachtopvMin{"dcabachtopvMin", 0.1f, "Minimum DCA of bachelor to primary vertex"}; - Configurable dcaV0topvMin{"dcaV0topvMin", 0.1f, "Minimum DCA of V0 to primary vertex"}; - Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 0.5f, "Maximum DCA between daughters"}; - Configurable dcaNegToPVminV0{"dcaNegToPVminV0", 0.1f, "Minimum DCA of V0 negative track to primary vertex in cascades"}; - Configurable dcaPosToPVminV0{"dcaPosToPVminV0", 0.1f, "Minimum DCA of V0 positive track to primary vertex in cascades"}; - Configurable deltaMassXi{"deltaMassXi", 0.02f, "Mass window for Xi rejection"}; - Configurable deltaMassOmega{"deltaMassOmega", 0.02f, "Mass window for Omega rejection"}; - Configurable deltaMassLambda{"deltaMassLambda", 0.02f, "Mass window for Lambda inclusion"}; + struct : ConfigurableGroup { + // std::string prefix = "configCasc"; // name in JSON + Configurable minimumCascRadius{"minimumCascRadius", 0.1f, "Minimum cascade radius"}; + // Configurable maximumCascRadius{"maximumCascRadius", 40.0f, "Maximum cascade radius"}; + Configurable casccospaMin{"casccospaMin", 0.99f, "Minimum cascade cosine of pointing angle"}; + Configurable dcabachtopvMin{"dcabachtopvMin", 0.1f, "Minimum DCA of bachelor to primary vertex"}; + Configurable dcaV0topvMin{"dcaV0topvMin", 0.1f, "Minimum DCA of V0 to primary vertex"}; + Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 0.5f, "Maximum DCA between daughters"}; + Configurable dcaNegToPVminV0{"dcaNegToPVminV0", 0.1f, "Minimum DCA of V0 negative track to primary vertex in cascades"}; + Configurable dcaPosToPVminV0{"dcaPosToPVminV0", 0.1f, "Minimum DCA of V0 positive track to primary vertex in cascades"}; + Configurable deltaMassXi{"deltaMassXi", 0.02f, "Mass window for Xi rejection"}; + Configurable deltaMassOmega{"deltaMassOmega", 0.02f, "Mass window for Omega rejection"}; + Configurable deltaMassLambda{"deltaMassLambda", 0.02f, "Mass window for Lambda inclusion"}; + } configCasc; + + // Axes + ConfigurableAxis multBinning{"multBinning", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "Binning of the centrality axis"}; struct : ConfigurableGroup { + // std::string prefix = "longLivedOptions"; // name in JSON ConfigurableAxis longLivedBinsNsigma{"longLivedBinsNsigma", {200, -10.f, 10.f}, "Binning of nSigma axis"}; ConfigurableAxis longLivedBinsPt{"longLivedBinsPt", {VARIABLE_WIDTH, -5.0, -4.8, -4.6, -4.4, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.95, -0.9, -0.85, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.25, -0.2, -0.18, -0.16, -0.14, -0.12, -0.1, 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, 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.2, 4.4, 4.6, 4.8, 5.0}, "Binning of the pT axis"}; ConfigurableAxis longLivedBinsDca{"longLivedBinsDca", {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"}; @@ -203,9 +225,20 @@ struct StrangenessInJetsIons { } // Define binning and axis specifications for multiplicity, eta, pT, PID, and invariant mass histograms - std::vector multBinning = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; - AxisSpec multAxis = {multBinning, "FT0C percentile"}; + std::string multAxTitle; + if (centrEstimator == 0) { + multAxTitle = "FT0C percentile"; + LOG(warning) << "FT0C ccdb object not available yet." << endl; + } else if (centrEstimator == 1) { + multAxTitle = "FT0M percentile"; + } else { + LOG(fatal) << "Centrality estimator " << centrEstimator << " not available. Exit." << endl; + } + AxisSpec multAxis = {multBinning, multAxTitle}; + const AxisSpec ptAxis{100, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ptJetAxis{101, 0.0, 100.0, "#it{p}_{T,jet} (GeV/#it{c})"}; + const AxisSpec numJets{21, -0.5, 20.5, "Number of jets per collision"}; const AxisSpec invMassK0sAxis{200, 0.44, 0.56, "m_{#pi#pi} (GeV/#it{c}^{2})"}; const AxisSpec invMassLambdaAxis{200, 1.09, 1.14, "m_{p#pi} (GeV/#it{c}^{2})"}; const AxisSpec invMassXiAxis{200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}; @@ -234,7 +267,7 @@ struct StrangenessInJetsIons { } // Histograms for checks - registryQC.add("V0_type", "V0_type", HistType::kTH1F, {{10, -0.5, 9.5, "V0 type"}}); + // registryQC.add("V0_type", "V0_type", HistType::kTH1F, {{10, -0.5, 9.5, "V0 type"}}); // Histograms for real data if (doprocessData) { @@ -252,8 +285,12 @@ struct StrangenessInJetsIons { registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(7, "No empty events"); registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(8, "At least one jet"); + // Jet counters + registryData.add("n_jets_vs_mult_pT", "n_jets_vs_mult_pT", HistType::kTH2F, {multAxis, ptJetAxis}); + registryData.add("n_jets_vs_mult", "n_jets_vs_mult", HistType::kTH2F, {multAxis, numJets}); + // Armenteros-Podolanski plot - registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); + // registryQC.add("ArmenterosPreSel_DATA", "ArmenterosPreSel_DATA", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); // Histograms for analysis of strange hadrons if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { @@ -302,6 +339,10 @@ struct StrangenessInJetsIons { // Add histogram to store multiplicity of the event registryMC.add("number_of_events_vsmultiplicity_gen", "number of events vs multiplicity", HistType::kTH1D, {{101, -0.5, 100.5, "Multiplicity percentile"}}); + // Jet counters + registryMC.add("n_jets_vs_mult_pT_mc_gen", "n_jets_vs_mult_pT_mc_gen", HistType::kTH2F, {multAxis, ptJetAxis}); + registryMC.add("n_jets_vs_mult_mc_gen", "n_jets_vs_mult_mc_gen", HistType::kTH2F, {multAxis, numJets}); + // Histograms for analysis if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { registryMC.add("K0s_generated_jet", "K0s_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -310,6 +351,11 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_generated_ue", "Lambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_jet", "AntiLambda_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_generated_ue", "AntiLambda_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("K0s_generated_MB", "K0s_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_generated_MB", "Lambda_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_generated_MB", "AntiLambda_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kCascades]) { registryMC.add("XiPos_generated_jet", "XiPos_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -320,18 +366,42 @@ struct StrangenessInJetsIons { registryMC.add("OmegaPos_generated_ue", "OmegaPos_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_generated_jet", "OmegaNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_generated_ue", "OmegaNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("XiPos_generated_MB", "XiPos_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_generated_MB", "XiNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_generated_MB", "OmegaPos_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_generated_MB", "OmegaNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.add("Pion_generated_jet", "Pion_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); - registryMC.add("Pion_generated_ue", "Pion_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionPos_generated_jet", "PionPos_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_generated_jet", "PionNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionPos_generated_ue", "PionPos_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_generated_ue", "PionNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("PionPos_generated_MB", "PionPos_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_generated_MB", "PionNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.add("Kaon_generated_jet", "Kaon_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); - registryMC.add("Kaon_generated_ue", "Kaon_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonPos_generated_jet", "KaonPos_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_generated_jet", "KaonNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonPos_generated_ue", "KaonPos_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_generated_ue", "KaonNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("KaonPos_generated_MB", "KaonPos_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_generated_MB", "KaonNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.add("Proton_generated_jet", "Proton_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); - registryMC.add("Proton_generated_ue", "Proton_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonPos_generated_jet", "ProtonPos_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_generated_jet", "ProtonNeg_generated_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonPos_generated_ue", "ProtonPos_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_generated_ue", "ProtonNeg_generated_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("ProtonPos_generated_MB", "ProtonPos_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_generated_MB", "ProtonNeg_generated_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } } @@ -352,8 +422,12 @@ struct StrangenessInJetsIons { // Add histogram to store multiplicity of the event registryMC.add("number_of_events_vsmultiplicity_rec", "number of events vs multiplicity", HistType::kTH1D, {{101, -0.5, 100.5, "Multiplicity percentile"}}); + // Jet counters + registryMC.add("n_jets_vs_mult_pT_mc_rec", "n_jets_vs_mult_pT_mc_rec", HistType::kTH2F, {multAxis, ptJetAxis}); + registryMC.add("n_jets_vs_mult_mc_rec", "n_jets_vs_mult_mc_rec", HistType::kTH2F, {multAxis, numJets}); + // Armenteros-Podolanski plot - registryQC.add("ArmenterosPreSel_REC", "ArmenterosPreSel_REC", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); + // registryQC.add("ArmenterosPreSel_REC", "ArmenterosPreSel_REC", HistType::kTH2F, {alphaArmAxis, qtarmAxis}); // Histograms for analysis if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { @@ -363,6 +437,7 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_reconstructed_ue", "Lambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet", "AntiLambda_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue", "AntiLambda_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + // Histograms for secondary hadrons registryMC.add("K0s_reconstructed_jet_incl", "K0s_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("K0s_reconstructed_ue_incl", "K0s_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); @@ -370,6 +445,19 @@ struct StrangenessInJetsIons { registryMC.add("Lambda_reconstructed_ue_incl", "Lambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet_incl", "AntiLambda_reconstructed_jet_incl", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue_incl", "AntiLambda_reconstructed_ue_incl", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for generated particles in reconstructed events + registryMC.add("K0s_gen_recoEvent_jet", "K0s_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("K0s_gen_recoEvent_ue", "K0s_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_gen_recoEvent_jet", "Lambda_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_gen_recoEvent_ue", "Lambda_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_gen_recoEvent_jet", "AntiLambda_gen_recoEvent_jet", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_gen_recoEvent_ue", "AntiLambda_gen_recoEvent_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("K0s_reconstructed_MB", "K0s_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("Lambda_reconstructed_MB", "Lambda_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("AntiLambda_reconstructed_MB", "AntiLambda_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kCascades]) { registryMC.add("XiPos_reconstructed_jet", "XiPos_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); @@ -380,71 +468,39 @@ struct StrangenessInJetsIons { registryMC.add("OmegaPos_reconstructed_ue", "OmegaPos_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_reconstructed_jet", "OmegaNeg_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxis}); registryMC.add("OmegaNeg_reconstructed_ue", "OmegaNeg_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxis}); + + // Histograms for the full event (without jets) + registryMC.add("XiPos_reconstructed_MB", "XiPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("XiNeg_reconstructed_MB", "XiNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaPos_reconstructed_MB", "OmegaPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_MB", "OmegaNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxis}); } if (particleOfInterestDict[ParticleOfInterest::kPions]) { registryMC.add("Pion_reconstructed_jet", "Pion_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); registryMC.add("Pion_reconstructed_ue", "Pion_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("PionPos_reconstructed_MB", "PionPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("PionNeg_reconstructed_MB", "PionNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kKaons]) { registryMC.add("Kaon_reconstructed_jet", "Kaon_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); registryMC.add("Kaon_reconstructed_ue", "Kaon_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); + + // Histograms for the full event (without jets) + registryMC.add("KaonPos_reconstructed_MB", "KaonPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("KaonNeg_reconstructed_MB", "KaonNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); } if (particleOfInterestDict[ParticleOfInterest::kProtons]) { registryMC.add("Proton_reconstructed_jet", "Proton_reconstructed_jet", HistType::kTH2F, {multAxis, ptAxisLongLived}); registryMC.add("Proton_reconstructed_ue", "Proton_reconstructed_ue", HistType::kTH2F, {multAxis, ptAxisLongLived}); - } - } - } - - /* - // Calculation of perpendicular axes - void getPerpendicularAxis(TVector3 p, TVector3& u, double sign) - { - // initialization - double ux(0), uy(0), uz(0); - - // components of vector p - const double px = p.X(); - const double py = p.Y(); - const double pz = p.Z(); - - // protection 1 - if (px == 0 && py != 0) { - uy = -(pz * pz) / py; - ux = sign * std::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 * std::sqrt(px * px - (pz * pz * pz * pz) / (px * px)); - uz = pz; - u.SetXYZ(ux, uy, uz); - return; - } - - // equation parameters - const double a = px * px + py * py; - const double b = 2.0 * px * pz * pz; - const double c = pz * pz * pz * pz - py * py * py * py - px * px * py * py; - const double delta = b * b - 4.0 * a * c; - - // protection agains delta<0 - if (delta < 0) { - return; + // Histograms for the full event (without jets) + registryMC.add("ProtonPos_reconstructed_MB", "ProtonPos_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + registryMC.add("ProtonNeg_reconstructed_MB", "ProtonNeg_reconstructed_MB", HistType::kTH2F, {multAxis, ptAxisLongLived}); + } } - - // solutions - ux = (-b + sign * std::sqrt(delta)) / (2.0 * a); - uy = (-pz * pz - px * ux) / py; - uz = pz; - u.SetXYZ(ux, uy, uz); - return; } - */ // Delta phi calculation double getDeltaPhi(double a1, double a2) @@ -609,40 +665,49 @@ struct StrangenessInJetsIons { TVector3 pion(v0.pxneg(), v0.pyneg(), v0.pzneg()); // Selection on pt of Lambda daughters - if (proton.Pt() < ptMinV0Proton || proton.Pt() > ptMaxV0Proton) + if (proton.Pt() < configTracks.ptMinV0Proton || proton.Pt() > configTracks.ptMaxV0Proton) return false; - if (pion.Pt() < ptMinV0Pion || pion.Pt() > ptMaxV0Pion) + if (pion.Pt() < configTracks.ptMinV0Pion || pion.Pt() > configTracks.ptMaxV0Pion) return false; // V0 selections - if (v0.v0cosPA() < v0cospaMin) - return false; - if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + if (v0.v0cosPA() < configV0.v0cospaMin) return false; - if (v0.distovertotmom(vtxPos.X(), vtxPos.Y(), vtxPos.Z()) * o2::constants::physics::MassLambda0 > ctauLambda) + // if (v0.v0radius() < configV0.minimumV0Radius || v0.v0radius() > configV0.maximumV0Radius) + if (v0.v0radius() < configV0.minimumV0Radius) return false; - if (std::fabs(v0.dcaV0daughters()) > dcaV0DaughtersMax) + if (v0.distovertotmom(vtxPos.X(), vtxPos.Y(), vtxPos.Z()) * o2::constants::physics::MassLambda0 > configV0.ctauLambda) return false; - if (std::fabs(v0.dcapostopv()) < dcaProtonToPVmin) + if (std::fabs(v0.dcaV0daughters()) > configV0.dcaV0DaughtersMax) return false; - if (std::fabs(v0.dcanegtopv()) < dcaPionToPVmin) + if (std::fabs(v0.dcapostopv()) < configV0.dcaProtonToPVmin) return false; - if (v0.v0Type() != v0type && requireV0type) { - registryQC.fill(HIST("V0_type"), v0.v0Type()); + if (std::fabs(v0.dcanegtopv()) < configV0.dcaPionToPVmin) return false; - } + // if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { + // registryQC.fill(HIST("V0_type"), v0.v0Type()); + // return false; + // } // PID selections (TPC): positive track = proton, negative track = pion - if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) + return false; + if (ntrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) + return false; + + if (configV0.requireLambdaMassCuts && + std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < configV0.k0sRejWindow) return false; - if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + + if (configV0.requireLambdaMassCuts && + std::abs(v0.mLambda() - o2::constants::physics::MassLambda) > configV0.lamMassWindow) return false; // PID selections (TOF): positive track = proton, negative track = pion - if (requireTOF) { - if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ptrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) return false; - if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + if (ntrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } return true; @@ -661,40 +726,49 @@ struct StrangenessInJetsIons { TVector3 proton(v0.pxneg(), v0.pyneg(), v0.pzneg()); // Selections on pt of Antilambda daughters - if (proton.Pt() < ptMinV0Proton || proton.Pt() > ptMaxV0Proton) + if (proton.Pt() < configTracks.ptMinV0Proton || proton.Pt() > configTracks.ptMaxV0Proton) return false; - if (pion.Pt() < ptMinV0Pion || pion.Pt() > ptMaxV0Pion) + if (pion.Pt() < configTracks.ptMinV0Pion || pion.Pt() > configTracks.ptMaxV0Pion) return false; // V0 selections - if (v0.v0cosPA() < v0cospaMin) + if (v0.v0cosPA() < configV0.v0cospaMin) return false; - if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + // if (v0.v0radius() < configV0.minimumV0Radius || v0.v0radius() > configV0.maximumV0Radius) + if (v0.v0radius() < configV0.minimumV0Radius) return false; - if (v0.distovertotmom(vtxPos.X(), vtxPos.Y(), vtxPos.Z()) * o2::constants::physics::MassLambda0 > ctauLambda) + if (v0.distovertotmom(vtxPos.X(), vtxPos.Y(), vtxPos.Z()) * o2::constants::physics::MassLambda0 > configV0.ctauLambda) return false; - if (std::fabs(v0.dcaV0daughters()) > dcaV0DaughtersMax) + if (std::fabs(v0.dcaV0daughters()) > configV0.dcaV0DaughtersMax) return false; - if (std::fabs(v0.dcapostopv()) < dcaPionToPVmin) + if (std::fabs(v0.dcapostopv()) < configV0.dcaPionToPVmin) return false; - if (std::fabs(v0.dcanegtopv()) < dcaProtonToPVmin) + if (std::fabs(v0.dcanegtopv()) < configV0.dcaProtonToPVmin) return false; - if (v0.v0Type() != v0type && requireV0type) { - registryQC.fill(HIST("V0_type"), v0.v0Type()); - return false; - } + // if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { + // registryQC.fill(HIST("V0_type"), v0.v0Type()); + // return false; + // } // PID selections (TPC): negative track = proton, positive track = pion - if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; - if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) + return false; + + if (configV0.requireLambdaMassCuts && + std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < configV0.k0sRejWindow) + return false; + + if (configV0.requireLambdaMassCuts && + std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda) > configV0.lamMassWindow) return false; // PID selections (TOF): negative track = proton, positive track = pion - if (requireTOF) { - if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ptrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; - if (ntrack.tofNSigmaPr() < nsigmaTOFmin || ntrack.tofNSigmaPr() > nsigmaTOFmax) + if (ntrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) return false; } return true; @@ -713,45 +787,55 @@ struct StrangenessInJetsIons { TVector3 pionNeg(v0.pxneg(), v0.pyneg(), v0.pzneg()); // Selections on pt of K0s daughters - if (pionPos.Pt() < ptMinK0Pion || pionPos.Pt() > ptMaxK0Pion) + if (pionPos.Pt() < configTracks.ptMinK0Pion || pionPos.Pt() > configTracks.ptMaxK0Pion) return false; - if (pionNeg.Pt() < ptMinK0Pion || pionNeg.Pt() > ptMaxK0Pion) + if (pionNeg.Pt() < configTracks.ptMinK0Pion || pionNeg.Pt() > configTracks.ptMaxK0Pion) return false; // V0 selections - if (v0.v0cosPA() < v0cospaMin) + if (v0.v0cosPA() < configV0.v0cospaMin) return false; - if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + // if (v0.v0radius() < configV0.minimumV0Radius || v0.v0radius() > configV0.maximumV0Radius) + if (v0.v0radius() < configV0.minimumV0Radius) return false; - if (v0.distovertotmom(vtxPos.X(), vtxPos.Y(), vtxPos.Z()) * o2::constants::physics::MassK0Short > ctauK0s) + if (v0.distovertotmom(vtxPos.X(), vtxPos.Y(), vtxPos.Z()) * o2::constants::physics::MassK0Short > configV0.ctauK0s) return false; - if (std::fabs(v0.dcaV0daughters()) > dcaV0DaughtersMax) + if (std::fabs(v0.dcaV0daughters()) > configV0.dcaV0DaughtersMax) return false; - if (std::fabs(v0.dcapostopv()) < dcaPosToPVminK0s) + if (std::fabs(v0.dcapostopv()) < configV0.dcaPosToPVminK0s) return false; - if (std::fabs(v0.dcanegtopv()) < dcaNegToPVminK0s) + if (std::fabs(v0.dcanegtopv()) < configV0.dcaNegToPVminK0s) return false; // Armenteros-Podolanski cut - if (v0.qtarm() < (paramArmenterosCut * std::abs(v0.alpha())) && (requireArmenterosCut)) + if (v0.qtarm() < (configV0.paramArmenterosCut * std::abs(v0.alpha())) && (configV0.requireArmenterosCut)) return false; - if (v0.v0Type() != v0type && requireV0type) { - registryQC.fill(HIST("V0_type"), v0.v0Type()); - return false; - } + // if (v0.v0Type() != configV0.v0type && configV0.requireV0type) { + // registryQC.fill(HIST("V0_type"), v0.v0Type()); + // return false; + // } // PID selections (TPC) - if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; - if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) + return false; + + if (configV0.requireK0sMassCuts && + (std::abs(v0.mLambda() - o2::constants::physics::MassLambda) < configV0.lamRejWindow || + std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda) < configV0.lamRejWindow)) + return false; + + if (configV0.requireK0sMassCuts && + std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) > configV0.k0sMassWindow) return false; // PID selections (TOF) - if (requireTOF) { - if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ptrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; - if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + if (ntrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } return true; @@ -771,22 +855,22 @@ struct StrangenessInJetsIons { // Xi+ selection (Xi+ -> antiL + pi+) if (btrack.sign() > 0) { - if (ntrack.pt() < ptMinV0Proton || ntrack.pt() > ptMaxV0Proton) + if (ntrack.pt() < configTracks.ptMinV0Proton || ntrack.pt() > configTracks.ptMaxV0Proton) return false; - if (ptrack.pt() < ptMinV0Pion || ptrack.pt() > ptMaxV0Pion) + if (ptrack.pt() < configTracks.ptMinV0Pion || ptrack.pt() > configTracks.ptMaxV0Pion) return false; // PID selections (TPC) - if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) return false; - if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; // PID selections (TOF) - if (requireTOF) { - if (ntrack.tofNSigmaPr() < nsigmaTOFmin || ntrack.tofNSigmaPr() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ntrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) return false; - if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + if (ptrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } @@ -796,28 +880,28 @@ struct StrangenessInJetsIons { pProton.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), o2::constants::physics::MassProton); pPion.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), o2::constants::physics::MassPionCharged); double mLambda = (pProton + pPion).M(); - if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > deltaMassLambda) + if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > configCasc.deltaMassLambda) return false; } // Xi- selection (Xi- -> L + pi-) if (btrack.sign() < 0) { - if (ptrack.pt() < ptMinV0Proton || ptrack.pt() > ptMaxV0Proton) + if (ptrack.pt() < configTracks.ptMinV0Proton || ptrack.pt() > configTracks.ptMaxV0Proton) return false; - if (ntrack.pt() < ptMinV0Pion || ntrack.pt() > ptMaxV0Pion) + if (ntrack.pt() < configTracks.ptMinV0Pion || ntrack.pt() > configTracks.ptMaxV0Pion) return false; // PID selections (TPC) - if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) return false; - if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; // PID selections (TOF) - if (requireTOF) { - if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ptrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) return false; - if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + if (ntrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } @@ -827,46 +911,48 @@ struct StrangenessInJetsIons { pProton.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), o2::constants::physics::MassProton); pPion.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), o2::constants::physics::MassPionCharged); const double mLambda = (pProton + pPion).M(); - if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > deltaMassLambda) + if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > configCasc.deltaMassLambda) return false; } // V0 selections - if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < v0cospaMin) + if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < configV0.v0cospaMin) return false; - if (casc.v0radius() < minimumV0Radius || casc.v0radius() > maximumV0Radius) + // if (casc.v0radius() < configV0.minimumV0Radius || casc.v0radius() > configV0.maximumV0Radius) + if (casc.v0radius() < configV0.minimumV0Radius) return false; - if (std::fabs(casc.dcaV0daughters()) > dcaV0DaughtersMax) + if (std::fabs(casc.dcaV0daughters()) > configV0.dcaV0DaughtersMax) return false; - if (std::fabs(casc.dcapostopv()) < dcaPosToPVminV0) + if (std::fabs(casc.dcapostopv()) < configCasc.dcaPosToPVminV0) return false; - if (std::fabs(casc.dcanegtopv()) < dcaNegToPVminV0) + if (std::fabs(casc.dcanegtopv()) < configCasc.dcaNegToPVminV0) return false; // Cascade selections - if (casc.cascradius() < minimumCascRadius || casc.cascradius() > maximumCascRadius) + // if (casc.cascradius() < configCasc.minimumCascRadius || casc.cascradius() > configCasc.maximumCascRadius) + if (casc.cascradius() < configCasc.minimumCascRadius) return false; - if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < casccospaMin) + if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < configCasc.casccospaMin) return false; - if (std::fabs(casc.dcabachtopv()) < dcabachtopvMin) + if (std::fabs(casc.dcabachtopv()) < configCasc.dcabachtopvMin) return false; - if (std::fabs(casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ())) < dcaV0topvMin) + if (std::fabs(casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ())) < configCasc.dcaV0topvMin) return false; - if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) + if (std::fabs(casc.dcacascdaughters()) > configCasc.dcaCascDaughtersMax) return false; // PID selection on bachelor - if (btrack.tpcNSigmaPi() < nsigmaTPCmin || btrack.tpcNSigmaPi() > nsigmaTPCmax) + if (btrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || btrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; // PID selections (TOF) - if (requireTOF) { - if (btrack.tofNSigmaPi() < nsigmaTOFmin || btrack.tofNSigmaPi() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (btrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || btrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } // Reject candidates compatible with Omega - if (std::fabs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < deltaMassOmega) + if (std::fabs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < configCasc.deltaMassOmega) return false; return true; } @@ -885,22 +971,22 @@ struct StrangenessInJetsIons { // Omega+ selection (Omega+ -> antiL + K+) if (btrack.sign() > 0) { - if (ntrack.pt() < ptMinV0Proton || ntrack.pt() > ptMaxV0Proton) + if (ntrack.pt() < configTracks.ptMinV0Proton || ntrack.pt() > configTracks.ptMaxV0Proton) return false; - if (ptrack.pt() < ptMinV0Pion || ptrack.pt() > ptMaxV0Pion) + if (ptrack.pt() < configTracks.ptMinV0Pion || ptrack.pt() > configTracks.ptMaxV0Pion) return false; // PID selections (TPC) - if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) return false; - if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; // PID selections (TOF) - if (requireTOF) { - if (ntrack.tofNSigmaPr() < nsigmaTOFmin || ntrack.tofNSigmaPr() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ntrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) return false; - if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + if (ptrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } @@ -910,28 +996,28 @@ struct StrangenessInJetsIons { pProton.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), o2::constants::physics::MassProton); pPion.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), o2::constants::physics::MassPionCharged); double mLambda = (pProton + pPion).M(); - if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > deltaMassLambda) + if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > configCasc.deltaMassLambda) return false; } // Omega- selection (Omega- -> L + K-) if (btrack.sign() < 0) { - if (ptrack.pt() < ptMinV0Proton || ptrack.pt() > ptMaxV0Proton) + if (ptrack.pt() < configTracks.ptMinV0Proton || ptrack.pt() > configTracks.ptMaxV0Proton) return false; - if (ntrack.pt() < ptMinV0Pion || ntrack.pt() > ptMaxV0Pion) + if (ntrack.pt() < configTracks.ptMinV0Pion || ntrack.pt() > configTracks.ptMaxV0Pion) return false; // PID selections (TPC) - if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) + if (ptrack.tpcNSigmaPr() < configTracks.nsigmaTPCmin || ptrack.tpcNSigmaPr() > configTracks.nsigmaTPCmax) return false; - if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + if (ntrack.tpcNSigmaPi() < configTracks.nsigmaTPCmin || ntrack.tpcNSigmaPi() > configTracks.nsigmaTPCmax) return false; // PID selections (TOF) - if (requireTOF) { - if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (ptrack.tofNSigmaPr() < configTracks.nsigmaTOFmin || ptrack.tofNSigmaPr() > configTracks.nsigmaTOFmax) return false; - if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + if (ntrack.tofNSigmaPi() < configTracks.nsigmaTOFmin || ntrack.tofNSigmaPi() > configTracks.nsigmaTOFmax) return false; } @@ -941,46 +1027,48 @@ struct StrangenessInJetsIons { pProton.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), o2::constants::physics::MassProton); pPion.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), o2::constants::physics::MassPionCharged); double mLambda = (pProton + pPion).M(); - if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > deltaMassLambda) + if (std::fabs(mLambda - o2::constants::physics::MassLambda0) > configCasc.deltaMassLambda) return false; } // V0 selections - if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < v0cospaMin) + if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < configV0.v0cospaMin) return false; - if (casc.v0radius() < minimumV0Radius || casc.v0radius() > maximumV0Radius) + // if (casc.v0radius() < configV0.minimumV0Radius || casc.v0radius() > configV0.maximumV0Radius) + if (casc.v0radius() < configV0.minimumV0Radius) return false; - if (std::fabs(casc.dcaV0daughters()) > dcaV0DaughtersMax) + if (std::fabs(casc.dcaV0daughters()) > configV0.dcaV0DaughtersMax) return false; - if (std::fabs(casc.dcapostopv()) < dcaPosToPVminV0) + if (std::fabs(casc.dcapostopv()) < configCasc.dcaPosToPVminV0) return false; - if (std::fabs(casc.dcanegtopv()) < dcaNegToPVminV0) + if (std::fabs(casc.dcanegtopv()) < configCasc.dcaNegToPVminV0) return false; // Cascade selections - if (casc.cascradius() < minimumCascRadius || casc.cascradius() > maximumCascRadius) + // if (casc.cascradius() < configCasc.minimumCascRadius || casc.cascradius() > configCasc.maximumCascRadius) + if (casc.cascradius() < configCasc.minimumCascRadius) return false; - if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < casccospaMin) + if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < configCasc.casccospaMin) return false; - if (std::fabs(casc.dcabachtopv()) < dcabachtopvMin) + if (std::fabs(casc.dcabachtopv()) < configCasc.dcabachtopvMin) return false; - if (std::fabs(casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ())) < dcaV0topvMin) + if (std::fabs(casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ())) < configCasc.dcaV0topvMin) return false; - if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) + if (std::fabs(casc.dcacascdaughters()) > configCasc.dcaCascDaughtersMax) return false; // PID selection on bachelor - if (btrack.tpcNSigmaKa() < nsigmaTPCmin || btrack.tpcNSigmaKa() > nsigmaTPCmax) + if (btrack.tpcNSigmaKa() < configTracks.nsigmaTPCmin || btrack.tpcNSigmaKa() > configTracks.nsigmaTPCmax) return false; // PID selections (TOF) - if (requireTOF) { - if (btrack.tofNSigmaKa() < nsigmaTOFmin || btrack.tofNSigmaKa() > nsigmaTOFmax) + if (configTracks.requireTOF) { + if (btrack.tofNSigmaKa() < configTracks.nsigmaTOFmin || btrack.tofNSigmaKa() > configTracks.nsigmaTOFmax) return false; } // Reject candidates compatible with Xi - if (std::fabs(casc.mXi() - o2::constants::physics::MassXiMinus) < deltaMassXi) + if (std::fabs(casc.mXi() - o2::constants::physics::MassXiMinus) < configCasc.deltaMassXi) return false; return true; } @@ -989,19 +1077,19 @@ struct StrangenessInJetsIons { template bool passedSingleTrackSelection(const Track& track) { - if (requireITS && (!track.hasITS())) + if (configTracks.requireITS && (!track.hasITS())) return false; - if (requireITS && track.itsNCls() < minITSnCls) + if (configTracks.requireITS && track.itsNCls() < configTracks.minITSnCls) return false; if (!track.hasTPC()) return false; - if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + if (track.tpcNClsCrossedRows() < configTracks.minNCrossedRowsTPC) return false; - if (track.tpcChi2NCl() > maxChi2TPC) + if (track.tpcChi2NCl() > configTracks.maxChi2TPC) return false; - if (track.eta() < etaMin || track.eta() > etaMax) + if (track.eta() < configTracks.etaMin || track.eta() > configTracks.etaMax) return false; - if (requireTOF && (!track.hasTOF())) + if (configTracks.requireTOF && (!track.hasTOF())) return false; return true; } @@ -1025,6 +1113,241 @@ struct StrangenessInJetsIons { return true; } + void FillFullEventHistoMCGEN(aod::McParticle const& particle, + const double& genMultiplicity) + { + if (particle.isPhysicalPrimary()) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kXiMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kXiPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("XiPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kOmegaMinus: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kOmegaPlusBar: + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + registryMC.fill(HIST("OmegaPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kPiPlus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kKPlus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kProton: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonPos_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kPiMinus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kKMinus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + case kProtonBar: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonNeg_generated_MB"), genMultiplicity, particle.pt()); + } + break; + default: + break; + } + } + } + + template + void FillFullEventHistoMCREC(MCRecoCollision collision, + aod::McParticles const& mcParticles, + V0PerColl const& v0sPerColl, + CascPerColl const& cascPerColl, + TracksPerColl const& tracksPerColl, + const double& multiplicity) + { + // V0 particles + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + for (const auto& v0 : v0sPerColl) { + const auto& pos = v0.template posTrack_as(); + const auto& neg = v0.template negTrack_as(); + TVector3 v0dir(v0.px(), v0.py(), v0.pz()); + + // Get MC particles + if (!pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + auto posParticle = pos.template mcParticle_as(); + auto negParticle = neg.template mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) + continue; + + // Get Mothers + auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + if (!motherPos.isPhysicalPrimary()) + continue; + + if (std::abs(motherPos.eta()) > 0.8) + continue; + + // Vertex position vector + TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); + + // K0s + if (passedK0ShortSelection(v0, pos, neg, vtxPos) && motherPos.pdgCode() == kK0Short) { + registryMC.fill(HIST("K0s_reconstructed_MB"), multiplicity, v0.pt()); + } + // Lambda + if (passedLambdaSelection(v0, pos, neg, vtxPos) && motherPos.pdgCode() == kLambda0) { + registryMC.fill(HIST("Lambda_reconstructed_MB"), multiplicity, v0.pt()); + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg, vtxPos) && motherPos.pdgCode() == kLambda0Bar) { + registryMC.fill(HIST("AntiLambda_reconstructed_MB"), multiplicity, v0.pt()); + } + } + } + + // Cascades + if (particleOfInterestDict[ParticleOfInterest::kCascades]) { + for (const auto& casc : cascPerColl) { + auto bach = casc.template bachelor_as(); + auto pos = casc.template posTrack_as(); + auto neg = casc.template negTrack_as(); + + // Get MC particles + if (!bach.has_mcParticle() || !pos.has_mcParticle() || !neg.has_mcParticle()) + continue; + auto posParticle = pos.template mcParticle_as(); + auto negParticle = neg.template mcParticle_as(); + auto bachParticle = bach.template mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers() || !bachParticle.has_mothers()) + continue; + + // Select particles originating from the same parent + auto motherPos = mcParticles.iteratorAt(posParticle.mothersIds()[0]); + auto motherNeg = mcParticles.iteratorAt(negParticle.mothersIds()[0]); + auto motherBach = mcParticles.iteratorAt(bachParticle.mothersIds()[0]); + if (motherPos != motherNeg) + continue; + if (std::abs(motherPos.pdgCode()) != kLambda0) + continue; + if (!motherBach.isPhysicalPrimary()) + continue; + + if (std::abs(motherPos.eta()) > 0.8) + continue; + + // Xi+ + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && motherBach.pdgCode() == kXiPlusBar) { + registryMC.fill(HIST("XiPos_reconstructed_MB"), multiplicity, casc.pt()); + } + // Xi- + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && motherBach.pdgCode() == kXiMinus) { + registryMC.fill(HIST("XiNeg_reconstructed_MB"), multiplicity, casc.pt()); + } + // Omega+ + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && motherBach.pdgCode() == kOmegaPlusBar) { + registryMC.fill(HIST("OmegaPos_reconstructed_MB"), multiplicity, casc.pt()); + } + // Omega- + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && motherBach.pdgCode() == kOmegaMinus) { + registryMC.fill(HIST("OmegaNeg_reconstructed_MB"), multiplicity, casc.pt()); + } + } + } + + if (particleOfInterestDict[ParticleOfInterest::kPions] || + particleOfInterestDict[ParticleOfInterest::kKaons] || + particleOfInterestDict[ParticleOfInterest::kProtons]) { + for (const auto& trk : tracksPerColl) { + + if (!trk.has_mcParticle()) { + continue; + } + if (!passedSingleTrackSelection(trk)) { + continue; + } + const auto& mcParticle = trk.template mcParticle_as(); + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + + if (std::abs(mcParticle.eta()) > 0.8) { + continue; + } + + switch (mcParticle.pdgCode()) { + case kPiPlus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionPos_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kPiMinus: + if (particleOfInterestDict[ParticleOfInterest::kPions]) { + registryMC.fill(HIST("PionNeg_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kKPlus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonPos_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kKMinus: + if (particleOfInterestDict[ParticleOfInterest::kKaons]) { + registryMC.fill(HIST("KaonNeg_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kProton: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonPos_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + case kProtonBar: + if (particleOfInterestDict[ParticleOfInterest::kProtons]) { + registryMC.fill(HIST("ProtonNeg_reconstructed_MB"), multiplicity, trk.pt()); + } + break; + default: + break; + } + } + } + } + // Process data void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, DaughterTracks const& tracks, @@ -1105,12 +1428,13 @@ struct StrangenessInJetsIons { std::vector selectedJet; std::vector ue1; std::vector ue2; + std::vector jetPt; // Loop over reconstructed jets for (const auto& jet : jets) { // Jet must be fully contained in the acceptance - if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) + if ((std::fabs(jet.eta()) + rJet) > (configTracks.etaMax - deltaEtaEdge)) continue; // Jet pt must be larger than threshold @@ -1132,6 +1456,7 @@ struct StrangenessInJetsIons { selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); + jetPt.emplace_back(jetMinusBkg.pt()); } if (!isAtLeastOneJetSelected) return; @@ -1140,13 +1465,23 @@ struct StrangenessInJetsIons { registryData.fill(HIST("number_of_events_data"), 7.5); // Event multiplicity - const float multiplicity = collision.centFT0C(); + float multiplicity; + if (centrEstimator == 0) { + multiplicity = collision.centFT0C(); + } else { + multiplicity = collision.centFT0M(); + } // Fill event multiplicity registryData.fill(HIST("number_of_events_vsmultiplicity"), multiplicity); + registryData.fill(HIST("n_jets_vs_mult"), multiplicity, static_cast(selectedJet.size())); // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { + + // Fill jet counter + registryData.fill(HIST("n_jets_vs_mult_pT"), multiplicity, jetPt[i]); + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { // V0s for (const auto& v0 : fullV0s) { @@ -1170,7 +1505,7 @@ struct StrangenessInJetsIons { TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); // Fill Armenteros-Podolanski TH2 - registryQC.fill(HIST("ArmenterosPreSel_DATA"), v0.alpha(), v0.qtarm()); + // registryQC.fill(HIST("ArmenterosPreSel_DATA"), v0.alpha(), v0.qtarm()); // K0s if (passedK0ShortSelection(v0, pos, neg, vtxPos)) { @@ -1322,8 +1657,7 @@ struct StrangenessInJetsIons { Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; Preslice perCollisionTrk = o2::aod::track::collisionId; - void processMCgenerated(aod::McCollisions const& collisions, - SimCollisions const& mcRecoCollisions, + void processMCgenerated(soa::Join const& collisions, aod::McParticles const& mcParticles) { // Define per-event particle containers @@ -1337,7 +1671,7 @@ struct StrangenessInJetsIons { // Loop over MC collisions for (const auto& collision : collisions) { - // Get multiplicity from RECO MC + /* // Get multiplicity from RECO MC // Select RECO collisions for which "mcCollisionsID" = collision.globalIndex() float multiplicity = -999; @@ -1351,7 +1685,11 @@ struct StrangenessInJetsIons { if (!selectRecoEvent(recoColl)) continue; - multiplicity = recoColl.centFT0C(); + if (centrEstimator == 0) { + multiplicity = recoColl.centFT0C(); + } else { + multiplicity = recoColl.centFT0M(); + } // LOGF(info, " MC GEN index: %d", collision.globalIndex()); // LOGF(info, " MC RECO index: %d", recoColl.mcCollisionId()); // LOGF(info, " multiplicity: %f", multiplicity); @@ -1360,7 +1698,7 @@ struct StrangenessInJetsIons { } if (multiplicity == -999) - continue; + continue; */ // Clear containers at the start of the event loop fjParticles.clear(); @@ -1372,13 +1710,21 @@ struct StrangenessInJetsIons { // Require vertex position within the allowed z range if (std::fabs(collision.posZ()) > zVtx) - return; + continue; // Fill event counter after selection on z-vertex registryMC.fill(HIST("number_of_events_mc_gen"), 1.5); // Multiplicity of generated event retrived from corresponding MC RECO collision - float genMultiplicity = multiplicity; + // float genMultiplicity = multiplicity; + + // Multiplicity of generated event + float genMultiplicity; + if (centrEstimator == 0) { + genMultiplicity = collision.centFT0C(); + } else { + genMultiplicity = collision.centFT0M(); + } // MC particles per collision auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); @@ -1387,16 +1733,19 @@ struct StrangenessInJetsIons { for (const auto& particle : mcParticlesPerColl) { // Store properties of strange hadrons int pdgAbs = std::abs(particle.pdgCode()); - if (particle.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0 || pdgAbs == kXiMinus || pdgAbs == kOmegaMinus)) { + if (particle.isPhysicalPrimary() && (pdgAbs == kK0Short || pdgAbs == kLambda0 || pdgAbs == kXiMinus || pdgAbs == kOmegaMinus)) { // TODO: add protons, kaons, pions pdg.emplace_back(particle.pdgCode()); strHadronMomentum.emplace_back(particle.px(), particle.py(), particle.pz()); } - // Select physical primary particles or HF decay products - if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) + + double minPtParticle = 0.1f; + if (particle.eta() < configTracks.etaMin || particle.eta() > configTracks.etaMax || particle.pt() < minPtParticle) continue; - double minPtParticle = 0.1; - if (particle.eta() < etaMin || particle.eta() > etaMax || particle.pt() < minPtParticle) + FillFullEventHistoMCGEN(particle, genMultiplicity); + + // Select physical primary particles or HF decay products + if (!isPhysicalPrimaryOrFromHF(particle, mcParticles)) continue; // Build 4-momentum assuming charged pion mass @@ -1420,10 +1769,11 @@ struct StrangenessInJetsIons { auto [rhoPerp, rhoMPerp] = jetutilities::estimateRhoPerpCone(fjParticles, jets[0], rJet); // Loop over clustered jets + int countSelJet = 0; // number of selected jets for (const auto& jet : jets) { // Jet must be fully contained in acceptance - if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) + if ((std::fabs(jet.eta()) + rJet) > (configTracks.etaMax - deltaEtaEdge)) continue; // Subtract background energy from jet @@ -1433,9 +1783,13 @@ struct StrangenessInJetsIons { // Apply jet pT threshold if (jetMinusBkg.pt() < minJetPt) continue; + countSelJet++; registryMC.fill(HIST("number_of_events_mc_gen"), 3.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_gen"), genMultiplicity); + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_pT_mc_gen"), genMultiplicity, jetMinusBkg.pt()); + // Set up two perpendicular cone axes for underlying event estimation TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); double coneRadius = std::sqrt(jet.area() / PI); @@ -1502,32 +1856,32 @@ struct StrangenessInJetsIons { break; case kPiPlus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("PionPos_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kKPlus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("KaonPos_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kProton: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_jet"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("ProtonPos_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kPiMinus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_jet"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("PionNeg_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kKMinus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_jet"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("KaonNeg_generated_jet"), genMultiplicity, hadron.Pt()); } break; case kProtonBar: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_jet"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("ProtonNeg_generated_jet"), genMultiplicity, hadron.Pt()); } break; default: @@ -1575,32 +1929,32 @@ struct StrangenessInJetsIons { break; case kPiPlus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("PionPos_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kKPlus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("KaonPos_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kProton: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_ue"), genMultiplicity, hadron.Pt()); + registryMC.fill(HIST("ProtonPos_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kPiMinus: if (particleOfInterestDict[ParticleOfInterest::kPions]) { - registryMC.fill(HIST("Pion_generated_ue"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("PionNeg_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kKMinus: if (particleOfInterestDict[ParticleOfInterest::kKaons]) { - registryMC.fill(HIST("Kaon_generated_ue"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("KaonNeg_generated_ue"), genMultiplicity, hadron.Pt()); } break; case kProtonBar: if (particleOfInterestDict[ParticleOfInterest::kProtons]) { - registryMC.fill(HIST("Proton_generated_ue"), genMultiplicity, hadron.Pt() * -1.f); + registryMC.fill(HIST("ProtonNeg_generated_ue"), genMultiplicity, hadron.Pt()); } break; default: @@ -1609,14 +1963,17 @@ struct StrangenessInJetsIons { } } } + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_mc_gen"), genMultiplicity, countSelJet); } } PROCESS_SWITCH(StrangenessInJetsIons, processMCgenerated, "Process MC generated events", false); // Reconstructed MC events void processMCreconstructed(SimCollisions const& collisions, + soa::Join const&, DaughterTracksMC const& mcTracks, aod::V0Datas const& fullV0s, - aod::CascDataExt const& Cascades, const aod::McParticles&) + aod::CascDataExt const& Cascades, aod::McParticles const& mcParticles) { // Define per-event containers std::vector fjParticles; @@ -1634,6 +1991,8 @@ struct StrangenessInJetsIons { continue; } + const auto& mcCollision = collision.mcCollision_as>(); + // Clear containers at the start of the event loop fjParticles.clear(); selectedJet.clear(); @@ -1668,12 +2027,21 @@ struct StrangenessInJetsIons { registryMC.fill(HIST("number_of_events_mc_rec"), 4.5); // Event multiplicity - const float multiplicity = collision.centFT0C(); + float multiplicity; + if (centrEstimator == 0) { + multiplicity = mcCollision.centFT0C(); + } else { + multiplicity = mcCollision.centFT0M(); + } // Number of V0 and cascades per collision auto v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); auto cascPerColl = Cascades.sliceBy(perCollisionCasc, collision.globalIndex()); auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + const auto& mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, mcCollision.globalIndex()); + + FillFullEventHistoMCREC(collision, mcParticles, v0sPerColl, + cascPerColl, tracksPerColl, multiplicity); // Loop over reconstructed tracks for (auto const& track : tracksPerColl) { @@ -1697,12 +2065,13 @@ struct StrangenessInJetsIons { // Jet selection bool isAtLeastOneJetSelected = false; + std::vector jetPt; // Loop over clustered jets for (const auto& jet : jets) { // jet must be fully contained in the acceptance - if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) + if ((std::fabs(jet.eta()) + rJet) > (configTracks.etaMax - deltaEtaEdge)) continue; // jet pt must be larger than threshold @@ -1724,6 +2093,7 @@ struct StrangenessInJetsIons { selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); + jetPt.emplace_back(jetMinusBkg.pt()); } if (!isAtLeastOneJetSelected) continue; @@ -1731,10 +2101,83 @@ struct StrangenessInJetsIons { // Fill event counter for events with at least one selected jet registryMC.fill(HIST("number_of_events_mc_rec"), 6.5); registryMC.fill(HIST("number_of_events_vsmultiplicity_rec"), multiplicity); + registryMC.fill(HIST("n_jets_vs_mult_mc_rec"), multiplicity, static_cast(selectedJet.size())); // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { + // Fill jet counter + registryMC.fill(HIST("n_jets_vs_mult_pT_mc_rec"), multiplicity, jetPt[i]); + + // ------------------------------------------------ + // --- Generated hadrons in reconstructed jets ---- + for (auto& particle : mcParticlesPerColl) { + if (!particle.isPhysicalPrimary() || std::abs(particle.eta()) > 0.8) + continue; + + int absPdg = std::abs(particle.pdgCode()); + if (absPdg != kK0Short && absPdg != kLambda0) + continue; + + TVector3 momVec(particle.px(), particle.py(), particle.pz()); + + // Compute distance of particles from jet and UE axes + const double deltaEtaJet = momVec.Eta() - selectedJet[i].Eta(); + const double deltaPhiJet = getDeltaPhi(momVec.Phi(), selectedJet[i].Phi()); + const double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + const double deltaEtaUe1 = momVec.Eta() - ue1[i].Eta(); + const double deltaPhiUe1 = getDeltaPhi(momVec.Phi(), ue1[i].Phi()); + const double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + const double deltaEtaUe2 = momVec.Eta() - ue2[i].Eta(); + const double deltaPhiUe2 = getDeltaPhi(momVec.Phi(), ue2[i].Phi()); + const double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Select particles inside jet + if (deltaRJet < rJet) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_gen_recoEvent_jet"), multiplicity, momVec.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_gen_recoEvent_jet"), multiplicity, momVec.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_gen_recoEvent_jet"), multiplicity, momVec.Pt()); + } + break; + default: + break; + } + } + if (deltaRUe1 < rJet || deltaRUe2 < rJet) { + switch (particle.pdgCode()) { + case kK0Short: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("K0s_gen_recoEvent_ue"), multiplicity, momVec.Pt()); + } + break; + case kLambda0: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("Lambda_gen_recoEvent_ue"), multiplicity, momVec.Pt()); + } + break; + case kLambda0Bar: + if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { + registryMC.fill(HIST("AntiLambda_gen_recoEvent_ue"), multiplicity, momVec.Pt()); + } + break; + default: + break; + } + } + } + // ---------------------------------------- + // V0 particles if (particleOfInterestDict[ParticleOfInterest::kV0Particles]) { for (const auto& v0 : v0sPerColl) { @@ -1779,7 +2222,7 @@ struct StrangenessInJetsIons { TVector3 vtxPos(collision.posX(), collision.posY(), collision.posZ()); // Fill Armenteros-Podolanski TH2 - registryQC.fill(HIST("ArmenterosPreSel_REC"), v0.alpha(), v0.qtarm()); + // registryQC.fill(HIST("ArmenterosPreSel_REC"), v0.alpha(), v0.qtarm()); // K0s if (passedK0ShortSelection(v0, pos, neg, vtxPos) && pdgParent == kK0Short && isPhysPrim) { @@ -1927,6 +2370,7 @@ struct StrangenessInJetsIons { } } } + jetPt.clear(); } } PROCESS_SWITCH(StrangenessInJetsIons, processMCreconstructed, "process reconstructed events", false); diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index 01439b81844..b3dca4c0a5c 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -15,17 +15,18 @@ /// \author Roman Lietava (roman.lietava@cern.ch) /*Description -This task creates up to 30 histograms that are filled with the V0 invariant mass under the K0, Lambda and Antilambda mass assumption +This task creates up to 30 histograms that are filled with the V0 invariant mass under the K0, Lambda and AntiLambda mass assumption for different pt ranges (constituting bins). The values are inserted as configurable strings for convinience. Also feed-down matrices for the Lambda and Anti-Lambda are produced. This analysis includes three processes, one for Real Data and two for MC at the Generated and Reconstructed level*/ +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/inelGt.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "CommonConstants/PhysicsConstants.h" #include "CommonUtils/StringUtils.h" @@ -61,14 +62,15 @@ using namespace o2::constants::physics; struct V0PtInvMassPlots { // Histogram Registries HistogramRegistry rPtAnalysis{"PtAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rKaonshMassPlotsPerPtBin{"KaonshMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0shMassPlotsPerPtBin{"K0shMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rLambdaMassPlotsPerPtBin{"LambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rAntilambdaMassPlotsPerPtBin{"AntilambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rKaonshSplitMassPlotsPerPtBin{"KaonshSplitMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntilambdaMassPlotsPerPtBin{"AntiLambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rK0shSplitMassPlotsPerPtBin{"K0shSplitMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rLambdaSplitMassPlotsPerPtBin{"LambdaSplitMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rAntilambdaSplitMassPlotsPerPtBin{"AntilambdaSplitMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rAntilambdaSplitMassPlotsPerPtBin{"AntiLambdaSplitMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rFeeddownMatrices{"FeeddownMatrices", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rMCCorrections{"MCCorrections", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rNchAnalysis{"NchAnalysis", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for histograms Configurable nBins{"nBins", 100, "N bins in all histos"}; @@ -80,6 +82,7 @@ struct V0PtInvMassPlots { Configurable nSigmaTPCProton{"nSigmaTPCProton", 4, "nSigmaTPCProton"}; Configurable compv0masscut{"compv0masscut", 0.01, "CompetitiveV0masscut (GeV)"}; Configurable etadau{"etadau", 0.8, "Eta Daughters"}; + Configurable etagen{"etagen", 0.8, "Eta Generated"}; Configurable rapidityCut{"rapidityCut", 0.5, "V0 Rapidity Window"}; Configurable itsMinHits{"itsMinHits", 1.0, "Minimum Hits of Daughter Tracks in the ITS"}; @@ -101,7 +104,7 @@ struct V0PtInvMassPlots { Configurable doitsMinHits{"doitsMinHits", true, "Enable ITS Minimum hits"}; // Configurables switches for K0sh selection - Configurable dotruthk0sh{"dotruthk0sh", true, "Enable K0sh MC Matching"}; + Configurable dotruthK0sh{"dotruthK0sh", true, "Enable K0sh MC Matching"}; Configurable doK0shTPCPID{"doK0shTPCPID", true, "Enable K0sh TPC PID"}; Configurable doK0shcomptmasscut{"doK0shcomptmasscut", true, "Enable K0sh Competitive V0 Mass Cut"}; Configurable doK0shMaxct{"doK0shMaxct", true, "Enable K0sh Max ct Cut"}; @@ -124,25 +127,25 @@ struct V0PtInvMassPlots { Configurable doLambdadcaposdautopv{"doLambdadcaposdautopv", true, "Enable Lambda DCA pos daughter to PV Topological Cut"}; Configurable doLambdadcanegdautopv{"doLambdadcanegdautopv", true, "Enable Lambda DCA neg daughter to PV Topological Cut"}; - // Configurables switches for Lambda selection - Configurable dotruthAntilambda{"dotruthAntilambda", true, "Enable Antilambda MC Matching"}; - Configurable doAntilambdaTPCPID{"doAntilambdaTPCPID", true, "Enable Antilambda TPC PID"}; - Configurable doAntilambdacomptmasscut{"doAntilambdacomptmasscut", true, "Enable Antilambda Competitive V0 Mass Cut"}; - Configurable doAntilambdaMaxct{"doAntilambdaMaxct", true, "Enable Antilambda Max ct Cut"}; - Configurable doAntilambdaArmenterosCut{"doAntilambdaArmenterosCut", true, "Enable Antilambda Armenteros Cut"}; - Configurable doAntilambdacosPACut{"doAntilambdacosPACut", true, "Enable Antilambda cosPA Topological Cut"}; - Configurable doAntilambdaDCAdauCut{"doAntilambdaDCAdauCut", true, "Enable Antilambda DCA daughters Topological Cut"}; - Configurable doAntilambdav0radiusCut{"doAntilambdav0radiusCut", true, "Enable Antilambda v0radius Topological Cut"}; - Configurable doAntilambdadcaposdautopv{"doAntilambdadcaposdautopv", true, "Enable Antilambda DCA pos daughter to PV Topological Cut"}; - Configurable doAntilambdadcanegdautopv{"doAntilambdadcanegdautopv", true, "Enable Antilambda DCA neg daughter to PV Topological Cut"}; - - // Configurable Kaonsh Cuts (best cuts determined by v0topologicalcuts task) - Configurable kaonshSettingdcav0dau{"kaonshSettingdcav0dau", 0.3, "DCA V0 Daughters"}; - Configurable kaonshSettingdcapostopv{"kaonshSettingdcapostopv", 0.05, "DCA Pos To PV"}; - Configurable kaonshSettingdcanegtopv{"kaonshSettingdcanegtopv", 0.05, "DCA Neg To PV"}; - Configurable kaonshSettingcosPA{"kaonshSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 - Configurable kaonshSettingradius{"kaonshSettingradius", 0.50, "v0radius"}; - Configurable kaonshmaxct{"kaonshmaxct", 20.00, "K0sh maximum ct value"}; + // Configurables switches for AntiLambda selection + Configurable dotruthAntiLambda{"dotruthAntiLambda", true, "Enable AntiLambda MC Matching"}; + Configurable doAntilambdaTPCPID{"doAntilambdaTPCPID", true, "Enable AntiLambda TPC PID"}; + Configurable doAntilambdacomptmasscut{"doAntilambdacomptmasscut", true, "Enable AntiLambda Competitive V0 Mass Cut"}; + Configurable doAntilambdaMaxct{"doAntilambdaMaxct", true, "Enable AntiLambda Max ct Cut"}; + Configurable doAntilambdaArmenterosCut{"doAntilambdaArmenterosCut", true, "Enable AntiLambda Armenteros Cut"}; + Configurable doAntilambdacosPACut{"doAntilambdacosPACut", true, "Enable AntiLambda cosPA Topological Cut"}; + Configurable doAntilambdaDCAdauCut{"doAntilambdaDCAdauCut", true, "Enable AntiLambda DCA daughters Topological Cut"}; + Configurable doAntilambdav0radiusCut{"doAntilambdav0radiusCut", true, "Enable AntiLambda v0radius Topological Cut"}; + Configurable doAntilambdadcaposdautopv{"doAntilambdadcaposdautopv", true, "Enable AntiLambda DCA pos daughter to PV Topological Cut"}; + Configurable doAntilambdadcanegdautopv{"doAntilambdadcanegdautopv", true, "Enable AntiLambda DCA neg daughter to PV Topological Cut"}; + + // Configurable K0sh Cuts (best cuts determined by v0topologicalcuts task) + Configurable k0shSettingdcav0dau{"k0shSettingdcav0dau", 0.3, "DCA V0 Daughters"}; + Configurable k0shSettingdcapostopv{"k0shSettingdcapostopv", 0.05, "DCA Pos To PV"}; + Configurable k0shSettingdcanegtopv{"k0shSettingdcanegtopv", 0.05, "DCA Neg To PV"}; + Configurable k0shSettingcosPA{"k0shSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 + Configurable k0shSettingradius{"k0shSettingradius", 0.50, "v0radius"}; + Configurable k0shmaxct{"k0shmaxct", 20.00, "K0sh maximum ct value"}; Configurable k0shparamArmenterosCut{"k0shparamArmenterosCut", 0.2, "K0sh Armenteros Cut on parameter"}; // Configurable Lambda Cuts (best cuts determined by v0topologicalcuts task) @@ -154,24 +157,25 @@ struct V0PtInvMassPlots { Configurable lambdamaxct{"lambdamaxct", 30.00, "Lambda maximum ct value"}; Configurable lambdaparamArmenterosCut{"lambdaparamArmenterosCut", 0.2, "Lambda Armenteros Cut on parameter"}; - // Configurable Antilambda Cuts (best cuts determined by v0topologicalcuts task) + // Configurable AntiLambda Cuts (best cuts determined by v0topologicalcuts task) Configurable antilambdaSettingdcav0dau{"antilambdaSettingdcav0dau", 0.3, "DCA V0 Daughters"}; Configurable antilambdaSettingdcapostopv{"antilambdaSettingdcapostopv", 0.09, "DCA Pos To PV"}; Configurable antilambdaSettingdcanegtopv{"antilambdaSettingdcanegtopv", 0.05, "DCA Neg To PV"}; Configurable antilambdaSettingcosPA{"antilambdaSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 Configurable antilambdaSettingradius{"antilambdaSettingradius", 0.50, "v0radius"}; - Configurable antilambdamaxct{"antilambdamaxct", 30.00, "Antilambda maximum ct value"}; - Configurable antilambdaparamArmenterosCut{"antilambdaparamArmenterosCut", 0.2, "Antilambda Armenteros Cut on parameter"}; + Configurable antilambdamaxct{"antilambdamaxct", 30.00, "AntiLambda maximum ct value"}; + Configurable antilambdaparamArmenterosCut{"antilambdaparamArmenterosCut", 0.2, "AntiLambda Armenteros Cut on parameter"}; - // Configurables for Specific V0s analysis - Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable Kzerosh Pt Analysis"}; + // Configurables for Specific Analysis + Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable K0sh Pt Analysis"}; Configurable lambdaAnalysis{"lambdaAnalysis", true, "Enable Lambda Pt Analysis"}; - Configurable antiLambdaAnalysis{"antiLambdaAnalysis", true, "Enable Antilambda Pt Analysis"}; + Configurable antiLambdaAnalysis{"antiLambdaAnalysis", true, "Enable AntiLambda Pt Analysis"}; + Configurable doNchAnalysis{"doNchAnalysis", true, "Enable Nch vs Centrality Analysis"}; // Configurable string for Different Pt Bins - Configurable kzeroSettingPtBinsString{"kzeroSettingPtBinsString", {"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 kzeroSettingPtBinsString{"kzeroSettingPtBinsString", {"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"}, "K0sh Pt Bin Values"}; Configurable lambdaSettingPtBinsString{"lambdaSettingPtBinsString", {"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 antilambdaSettingPtBinsString{"antilambdaSettingPtBinsString", {"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"}; + Configurable antilambdaSettingPtBinsString{"antilambdaSettingPtBinsString", {"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&) { @@ -187,15 +191,15 @@ struct V0PtInvMassPlots { pthistos::kaonPt.resize(nKaonHistograms); // number of Kaon Pt histograms to expect pthistos::lambdaPt.resize(nLambdaHistograms); // number of Lambda histograms to expect - pthistos::antilambdaPt.resize(nAntilambdaHistograms); // number of Antilambda histograms to expect + pthistos::antilambdaPt.resize(nAntilambdaHistograms); // number of AntiLambda histograms to expect pthistos::kaonSplit.resize(nKaonHistograms); // number of Kaon Split Pt histograms to expect pthistos::lambdaSplit.resize(nLambdaHistograms); // number of Lambda Split Pt histograms to expect - pthistos::antilambdaSplit.resize(nAntilambdaHistograms); // number of Antilambda Split Pt histograms to expect + pthistos::antilambdaSplit.resize(nAntilambdaHistograms); // number of AntiLambda Split Pt histograms to expect // initialize and convert tokenized strings into vector of doubles for AxisSpec std::vector kaonptedgevalues(pthistos::kaonPtBins.size()); std::vector lambdaptedgevalues(pthistos::lambdaPtBins.size()); - std::vector antilambdaPtedgevalues(pthistos::antilambdaPtBins.size()); + std::vector antilambdaptedgevalues(pthistos::antilambdaPtBins.size()); for (size_t i = 0; i < pthistos::kaonPtBins.size(); i++) { kaonptedgevalues[i] = std::stod(pthistos::kaonPtBins[i]); } @@ -203,7 +207,7 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); } for (size_t i = 0; i < pthistos::antilambdaPtBins.size(); i++) { - antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); + antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } // Axes @@ -212,8 +216,9 @@ struct V0PtInvMassPlots { AxisSpec antiLambdaMassAxis = {nBins, 1.085f, 1.145f, "#it{M} p^{-}#pi^{+} [GeV/#it{c}^{2}]"}; AxisSpec k0ShortPtAxis = {kaonptedgevalues, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec lambdaPtAxis = {lambdaptedgevalues, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec antilambdaPtAxis = {antilambdaPtedgevalues, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec antilambdaPtAxis = {antilambdaptedgevalues, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec centAxis = {100, 0.0f, 100.0f, "#it{Centrality} (%)"}; + AxisSpec nchAxis = {100, 0.0f, 100.0f, "#it{N}_{ch} (%)"}; AxisSpec armenterosQtAxis = {nBinsArmenteros, 0.0f, 0.3f, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec armenterosasymAxis = {nBinsArmenteros, -1.f, 1.f, "#it{p}^{+}_{||}-#it{p}^{-}_{||}/#it{p}^{+}_{||}+#it{p}^{-}_{||}"}; AxisSpec vertexZAxis = {nBins, -11.0f, 11.0f, "vrtx_{Z} [cm]"}; @@ -245,17 +250,18 @@ struct V0PtInvMassPlots { } // General Plots - rPtAnalysis.add("hNEvents", "hNEvents", {HistType::kTH1D, {{7, 0.f, 7.f}}}); - rPtAnalysis.add("hNV0s", "hNV0s", {HistType::kTH1D, {{10, 0.f, 10.f}}}); - rPtAnalysis.add("hNK0sh", "hNK0sh", {HistType::kTH1D, {{11, 0.f, 11.f}}}); - rPtAnalysis.add("hNLambda", "hNLambda", {HistType::kTH1D, {{11, 0.f, 11.f}}}); - rPtAnalysis.add("hNAntilambda", "hNAntilambda", {HistType::kTH1D, {{11, 0.f, 11.f}}}); + rPtAnalysis.add("hNEvents", "hNEvents", {HistType::kTH2D, {{7, 0.f, 7.f}, centAxis}}); + rPtAnalysis.add("hNRecEvents", "hNRecEvents", {HistType::kTH2D, {{1, 0.f, 1.f}, centAxis}}); + rPtAnalysis.add("hNV0s", "hNV0s", {HistType::kTH2D, {{10, 0.f, 10.f}, centAxis}}); + rPtAnalysis.add("hNK0sh", "hNK0sh", {HistType::kTH2D, {{11, 0.f, 11.f}, centAxis}}); + rPtAnalysis.add("hNLambda", "hNLambda", {HistType::kTH2D, {{11, 0.f, 11.f}, centAxis}}); + rPtAnalysis.add("hNAntiLambda", "hNAntiLambda", {HistType::kTH2D, {{11, 0.f, 11.f}, centAxis}}); rPtAnalysis.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); rPtAnalysis.add("hArmenterosPodolanskiPlot", "hArmenterosPodolanskiPlot", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); rPtAnalysis.add("hV0EtaDaughters", "hV0EtaDaughters", {HistType::kTH1F, {{nBins, -1.2f, 1.2f}}}); rPtAnalysis.add("V0Rapidity", "V0Rapidity", {HistType::kTH1F, {{nBins, -1.0f, 1.0f}}}); - // Adding Kzerosh Histograms to registry + // Adding K0sh Histograms to registry if (kzeroAnalysis == true) { rPtAnalysis.add("hMassK0ShortvsCuts", "hMassK0ShortvsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); rPtAnalysis.add("hArmenterosPodolanskiPlotK0sh", "hArmenterosPodolanskiPlotK0sh", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); @@ -267,15 +273,15 @@ struct V0PtInvMassPlots { rPtAnalysis.add("hK0shDCAPosDaughter", "hK0shDCAPosDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); rPtAnalysis.add("hK0shDCANegDaughter", "hK0shDCANegDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); for (int i = 0; i < nKaonHistograms; i++) { - pthistos::kaonPt[i] = rKaonshMassPlotsPerPtBin.add(fmt::format("hK0shPt_vs_Cent_from_{0}_to_{1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), fmt::format("K0s mass vs centrality, pT from {0} to {1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), {HistType::kTH2D, {{k0ShortMassAxis}, {centAxis}}}); - pthistos::kaonSplit[i] = rKaonshSplitMassPlotsPerPtBin.add(fmt::format("hK0shSplitPt_vs_Cent_from_{0}_to_{1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), fmt::format("Split K0s mass vs centrality, pT from {0} to {1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), {HistType::kTH2D, {{k0ShortMassAxis}, {centAxis}}}); + pthistos::kaonPt[i] = rK0shMassPlotsPerPtBin.add(fmt::format("hK0shPt_vs_Cent_from_{0}_to_{1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), fmt::format("K0s mass vs centrality, pT from {0} to {1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), {HistType::kTH2D, {{k0ShortMassAxis}, {centAxis}}}); + pthistos::kaonSplit[i] = rK0shSplitMassPlotsPerPtBin.add(fmt::format("hK0shSplitPt_vs_Cent_from_{0}_to_{1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), fmt::format("Split K0s mass vs centrality, pT from {0} to {1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), {HistType::kTH2D, {{k0ShortMassAxis}, {centAxis}}}); } rFeeddownMatrices.add("hK0shFeeddownMatrix", "hK0shFeeddownMatrix", {HistType::kTH3D, {k0ShortPtAxis, k0ShortPtAxis, centAxis}}); rFeeddownMatrices.add("hK0shPhiFeeddownMatrix", "hK0shPhiFeeddownMatrix", {HistType::kTH3D, {k0ShortPtAxis, k0ShortPtAxis, centAxis}}); } // Adding Lambda Histograms if (lambdaAnalysis == true) { - // same method as in Kzerosh above + // same method as in K0sh above rPtAnalysis.add("hMassLambdavsCuts", "hMassLambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); rPtAnalysis.add("hArmenterosPodolanskiPlotLambda", "hArmenterosPodolanskiPlotLambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); rPtAnalysis.add("hNSigmaPosProtonFromLambdas", "hNSigmaPosProtonFromLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {lambdaPtAxis}}}); @@ -296,21 +302,21 @@ struct V0PtInvMassPlots { rFeeddownMatrices.add("hLambdaXiZeroFeeddownMatrix", "hLambdaXiZeroFeeddownMatrix", {HistType::kTH3D, {lambdaPtAxis, lambdaPtAxis, centAxis}}); rFeeddownMatrices.add("hLambdaOmegaFeeddownMatrix", "hLambdaOmegaFeeddownMatrix", {HistType::kTH3D, {lambdaPtAxis, lambdaPtAxis, centAxis}}); } - // Adding Antilambda Histograms + // Adding AntiLambda Histograms if (antiLambdaAnalysis == true) { - // same method as in Lambda and Kzerosh above - rPtAnalysis.add("hMassAntilambdavsCuts", "hMassAntilambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); - rPtAnalysis.add("hArmenterosPodolanskiPlotAntilambda", "hArmenterosPodolanskiPlotAntilambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); - rPtAnalysis.add("hNSigmaPosPionFromAntilambdas", "hNSigmaPosPionFromAntilambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); - rPtAnalysis.add("hNSigmaNegProtonFromAntilambdas", "hNSigmaNegProtonFromAntilambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); - rPtAnalysis.add("hAntilambdaV0radius", "hAntilambdaV0radius", {HistType::kTH1F, {{nBins, 0.0f, 50.0f}}}); - rPtAnalysis.add("hAntilambdacosPA", "hAntilambdacosPA", {HistType::kTH1F, {{nBins, 0.95f, 1.0f}}}); - rPtAnalysis.add("hAntilambdaDCAV0Daughters", "hAntilambdaDCAV0Daughters", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); - rPtAnalysis.add("hAntilambdaDCAPosDaughter", "hAntilambdaDCAPosDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); - rPtAnalysis.add("hAntilambdaDCANegDaughter", "hAntilambdaDCANegDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); + // same method as in Lambda and K0sh above + rPtAnalysis.add("hMassAntiLambdavsCuts", "hMassAntiLambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); + rPtAnalysis.add("hArmenterosPodolanskiPlotAntiLambda", "hArmenterosPodolanskiPlotAntiLambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); + rPtAnalysis.add("hNSigmaPosPionFromAntiLambdas", "hNSigmaPosPionFromAntiLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); + rPtAnalysis.add("hNSigmaNegProtonFromAntiLambdas", "hNSigmaNegProtonFromAntiLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); + rPtAnalysis.add("hAntiLambdaV0radius", "hAntiLambdaV0radius", {HistType::kTH1F, {{nBins, 0.0f, 50.0f}}}); + rPtAnalysis.add("hAntiLambdacosPA", "hAntiLambdacosPA", {HistType::kTH1F, {{nBins, 0.95f, 1.0f}}}); + rPtAnalysis.add("hAntiLambdaDCAV0Daughters", "hAntiLambdaDCAV0Daughters", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); + rPtAnalysis.add("hAntiLambdaDCAPosDaughter", "hAntiLambdaDCAPosDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); + rPtAnalysis.add("hAntiLambdaDCANegDaughter", "hAntiLambdaDCANegDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); for (int i = 0; i < nAntilambdaHistograms; i++) { - pthistos::antilambdaPt[i] = rAntilambdaMassPlotsPerPtBin.add(fmt::format("hAntilambdaPt_vs_Cent_from_{0}_to_{1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), fmt::format("Antilambda mass vs centrality, pT from {0} to {1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), {HistType::kTH2D, {{antiLambdaMassAxis}, {centAxis}}}); - pthistos::antilambdaSplit[i] = rAntilambdaSplitMassPlotsPerPtBin.add(fmt::format("hAntilambdaSplitPt_vs_Cent_from_{0}_to_{1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), fmt::format("Split Antilambda mass vs centrality, pT from {0} to {1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), {HistType::kTH2D, {{antiLambdaMassAxis}, {centAxis}}}); + pthistos::antilambdaPt[i] = rAntilambdaMassPlotsPerPtBin.add(fmt::format("hAntiLambdaPt_vs_Cent_from_{0}_to_{1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), fmt::format("AntiLambda mass vs centrality, pT from {0} to {1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), {HistType::kTH2D, {{antiLambdaMassAxis}, {centAxis}}}); + pthistos::antilambdaSplit[i] = rAntilambdaSplitMassPlotsPerPtBin.add(fmt::format("hAntiLambdaSplitPt_vs_Cent_from_{0}_to_{1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), fmt::format("Split AntiLambda mass vs centrality, pT from {0} to {1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), {HistType::kTH2D, {{antiLambdaMassAxis}, {centAxis}}}); } // antilambdafeeddown matrices rFeeddownMatrices.add("hAntiLambdaFeeddownMatrix", "hAntiLambdaFeeddownMatrix", {HistType::kTH3D, {antilambdaPtAxis, antilambdaPtAxis, centAxis}}); @@ -320,23 +326,21 @@ struct V0PtInvMassPlots { } // Particle Level Corrections - rMCCorrections.add("hK0ShNoMCParticle", "hK0ShNoMCParticle", {HistType::kTH1D, {k0ShortPtAxis}}); - rMCCorrections.add("hK0ShBeforeEventSelectionPtSpectrum", "hK0ShBeforeEventSelectionPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + rMCCorrections.add("hK0shBeforeEventSelectionPtSpectrum", "hK0shBeforeEventSelectionPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); // not filled rMCCorrections.add("hLambdaBeforeEventSelectionPtSpectrum", "hLambdaBeforeEventSelectionPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); - rMCCorrections.add("hAntilambdaBeforeEventSelectionPtSpectrum", "hAntilambdaBeforeEventSelectionPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); - rMCCorrections.add("hK0ShAfterEventSelectionPtSpectrum", "hK0ShAfterEventSelectionPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + rMCCorrections.add("hAntiLambdaBeforeEventSelectionPtSpectrum", "hAntiLambdaBeforeEventSelectionPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hK0shAfterEventSelectionPtSpectrum", "hK0shAfterEventSelectionPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); rMCCorrections.add("hLambdaAfterEventSelectionPtSpectrum", "hLambdaAfterEventSelectionPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); - rMCCorrections.add("hAntilambdaAfterEventSelectionPtSpectrum", "hAntilambdaAfterEventSelectionPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hAntiLambdaAfterEventSelectionPtSpectrum", "hAntiLambdaAfterEventSelectionPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); // Event and V0s Corrections rMCCorrections.add("hNEvents_Corrections", "hNEvents_Corrections", {HistType::kTH2D, {{10, 0.f, 10.f}, centAxis}}); - rMCCorrections.add("hNRecEvents", "hNRecEvents", {HistType::kTH2D, {{1, 0.f, 1.f}, centAxis}}); // Generated Level Pt Spectrums (with rapidity cut) rMCCorrections.add("GenParticleRapidity", "GenParticleRapidity", {HistType::kTH1F, {{nBins, -10.0f, 10.0f}}}); - rMCCorrections.add("hK0ShGeneratedPtSpectrum", "hK0ShGeneratedPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + rMCCorrections.add("hK0shGeneratedPtSpectrum", "hK0shGeneratedPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); rMCCorrections.add("hLambdaGeneratedPtSpectrum", "hLambdaGeneratedPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); - rMCCorrections.add("hAntilambdaGeneratedPtSpectrum", "hAntilambdaGeneratedPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); + rMCCorrections.add("hAntiLambdaGeneratedPtSpectrum", "hAntiLambdaGeneratedPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); rMCCorrections.add("hXiMinusGeneratedPtSpectrum", "hXiMinusGeneratedPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); rMCCorrections.add("hXiZeroGeneratedPtSpectrum", "hXiZeroGeneratedPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); rMCCorrections.add("hOmegaGeneratedPtSpectrum", "hOmegaGeneratedPtSpectrum", {HistType::kTH2D, {lambdaPtAxis, centAxis}}); @@ -344,73 +348,110 @@ struct V0PtInvMassPlots { rMCCorrections.add("hAntiXiZeroGeneratedPtSpectrum", "hAntiXiZeroGeneratedPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); rMCCorrections.add("hAntiOmegaGeneratedPtSpectrum", "hAntiOmegaGeneratedPtSpectrum", {HistType::kTH2D, {antilambdaPtAxis, centAxis}}); rMCCorrections.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH2D, {k0ShortPtAxis, centAxis}}); + rMCCorrections.add("hGenPartcles", "hGenPartcles", {HistType::kTH2D, {nchAxis, centAxis}}); + + // NCh Analysis + rNchAnalysis.add("hNchCentralityGenerated", "hNchCentralityGenerated", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality Generated + rNchAnalysis.add("hNchCentralityGeneratedAfterEventSelection", "hNchCentralityGeneratedAfterEventSelection", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality Generated After Event Selection + rNchAnalysis.add("hNchCentrality", "hNchCentrality", {HistType::kTH2D, {centAxis, nchAxis}}); // Nch vs Centrality } // Event selection function template bool acceptEvent(TCollision const& collision) { - rPtAnalysis.fill(HIST("hNEvents"), 0.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); + rPtAnalysis.fill(HIST("hNEvents"), 0.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); if (dosel8 && !collision.sel8()) { return false; } - rPtAnalysis.fill(HIST("hNEvents"), 1.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "sel 8"); + rPtAnalysis.fill(HIST("hNEvents"), 1.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "sel 8"); if (doNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { return false; } - rPtAnalysis.fill(HIST("hNEvents"), 2.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "NoTimeFrameBorder"); + rPtAnalysis.fill(HIST("hNEvents"), 2.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "NoTimeFrameBorder"); if (doNoITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return false; } - rPtAnalysis.fill(HIST("hNEvents"), 3.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "NoITSROFrameBorder"); + rPtAnalysis.fill(HIST("hNEvents"), 3.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "NoITSROFrameBorder"); if (doIsTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { return false; } - rPtAnalysis.fill(HIST("hNEvents"), 4.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "IsTriggerTVX"); + rPtAnalysis.fill(HIST("hNEvents"), 4.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "IsTriggerTVX"); if (docutZVertex && !(std::abs(collision.posZ()) < cutZVertex)) { return false; } - rPtAnalysis.fill(HIST("hNEvents"), 5.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "cutZVertex"); - if (doisInelGt0 && !collision.isInelGt0()) { + rPtAnalysis.fill(HIST("hNEvents"), 5.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "cutZVertex"); + if (doisInelGt0 && !(collision.multNTracksPVeta1() > 0)) { + // if (doisInelGt0 && !(collision.multMCNParticlesEta10() > 0)) { //CHANGE TO THIS return false; } - rPtAnalysis.fill(HIST("hNEvents"), 6.5); - rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "isInelGt0"); + rPtAnalysis.fill(HIST("hNEvents"), 6.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "isInelGt0"); // Cut Plots rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); return true; } - // V0 selection function - template - bool acceptV0(TV0 const& v0) + // Charged Particle Selection Function + template + bool acceptGeneratedParticle(TParticle const& particle, TCollision const& mcCollision) { - const auto& posDaughterTrack = v0.template posTrack_as(); // Positive Daughter track - const auto& negDaughterTrack = v0.template negTrack_as(); // Negative Daughter track + rMCCorrections.fill(HIST("hGenPartcles"), 0.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(1, "All Gen Particles"); + if (!particle.isPhysicalPrimary()) { // Daughters Pseudorapidity Cut + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 1.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(2, "Physical Primary"); + if (!particle.producedByGenerator()) { + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 2.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(3, "Produced by Generator"); + if (std::abs(particle.eta()) > etagen) { // Eta cut + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 3.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(4, "Eta Cut"); + auto pdgParticle = pdgDB->GetParticle(particle.pdgCode()); + if (pdgParticle == nullptr) { + return false; + } + if (std::abs(pdgParticle->Charge()) < 3) { + return false; + } + rMCCorrections.fill(HIST("hGenPartcles"), 4.5, mcCollision.centFT0M()); + rMCCorrections.get(HIST("hGenPartcles"))->GetXaxis()->SetBinLabel(4, "Charge Cut"); + return true; + } - rPtAnalysis.fill(HIST("hNV0s"), 0.5); - rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(1, "All V0s"); + // V0 selection function + template + bool acceptV0(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) + { + rPtAnalysis.fill(HIST("hNV0s"), 0.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(1, "All V0s"); if (doDaughterPseudorapidityCut && !(std::abs(posDaughterTrack.eta()) < etadau && std::abs(negDaughterTrack.eta()) < etadau)) { // Daughters Pseudorapidity Cut return false; } - rPtAnalysis.fill(HIST("hNV0s"), 1.5); - rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(2, "Dau Pseudorapidity"); + rPtAnalysis.fill(HIST("hNV0s"), 1.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(2, "Dau Pseudorapidity"); if (doisNotITSAfterburner && (posDaughterTrack.isITSAfterburner() || negDaughterTrack.isITSAfterburner())) { // ITS After Burner on daughter tracks return false; } - rPtAnalysis.fill(HIST("hNV0s"), 2.5); - rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(3, "ITS Afterburner"); + rPtAnalysis.fill(HIST("hNV0s"), 2.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(3, "ITS Afterburner"); if (doitsMinHits && !(posDaughterTrack.itsNCls() >= itsMinHits && negDaughterTrack.itsNCls() >= itsMinHits)) { // Minimum hits in the ITS return false; } - rPtAnalysis.fill(HIST("hNV0s"), 3.5); - rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(4, "ITS Min Hits"); + rPtAnalysis.fill(HIST("hNV0s"), 3.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(4, "ITS Min Hits"); // Cut Plots rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.template posTrack_as().eta()); rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.template negTrack_as().eta()); @@ -419,81 +460,78 @@ struct V0PtInvMassPlots { } // K0sh selection function - template - bool acceptK0sh(TV0 const& v0) + template + bool acceptK0sh(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) { - const auto& posDaughterTrack = v0.template posTrack_as(); // Positive Daughter track - const auto& negDaughterTrack = v0.template negTrack_as(); // Negative Daughter track - - rPtAnalysis.fill(HIST("hNK0sh"), 0.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(1, "All"); + rPtAnalysis.fill(HIST("hNK0sh"), 0.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(1, "All"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 0.5, v0.mK0Short()); if (doRapidityCut && (std::abs(v0.rapidity(0)) > rapidityCut)) { // V0 Rapidity Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 1.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(2, "Rapidity"); + rPtAnalysis.fill(HIST("hNK0sh"), 1.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(2, "Rapidity"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 1.5, v0.mK0Short()); if (doK0shTPCPID && (std::abs(posDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion || std::abs(negDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion)) { // TPC PID for two pions return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 2.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); + rPtAnalysis.fill(HIST("hNK0sh"), 2.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 2.5, v0.mK0Short()); - if (doK0shcomptmasscut && ((std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut) || (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + if (doK0shcomptmasscut && ((std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut) || (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // K0sh competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 3.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); + rPtAnalysis.fill(HIST("hNK0sh"), 3.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 3.5, v0.mK0Short()); - if (doK0shMaxct && (v0.v0radius() > kaonshmaxct)) { // K0sh max ct + if (doK0shMaxct && (v0.v0radius() > k0shmaxct)) { // K0sh max ct return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 4.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(5, "Max_ct"); + rPtAnalysis.fill(HIST("hNK0sh"), 4.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(5, "Max_ct"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 4.5, v0.mK0Short()); if (doK0shArmenterosCut && (v0.qtarm() < (k0shparamArmenterosCut * std::abs(v0.alpha())))) { // K0sh Armenteros Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 5.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(6, "Armenteros"); + rPtAnalysis.fill(HIST("hNK0sh"), 5.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(6, "Armenteros"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 5.5, v0.mK0Short()); - if (doK0shcosPACut && (v0.v0cosPA() < kaonshSettingcosPA)) { // K0sh cosPA Topological Cut + if (doK0shcosPACut && (v0.v0cosPA() < k0shSettingcosPA)) { // K0sh cosPA Topological Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 6.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(7, "cosPA"); + rPtAnalysis.fill(HIST("hNK0sh"), 6.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(7, "cosPA"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 6.5, v0.mK0Short()); - if (doK0shDCAdauCut && (v0.dcaV0daughters() > kaonshSettingdcav0dau)) { // K0sh DCAdaughters Topological Cut + if (doK0shDCAdauCut && (v0.dcaV0daughters() > k0shSettingdcav0dau)) { // K0sh DCAdaughters Topological Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 7.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(8, "DCAdau"); + rPtAnalysis.fill(HIST("hNK0sh"), 7.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(8, "DCAdau"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 7.5, v0.mK0Short()); - if (doK0shv0radiusCut && (v0.v0radius() < kaonshSettingradius)) { // K0sh v0radius Topological Cut + if (doK0shv0radiusCut && (v0.v0radius() < k0shSettingradius)) { // K0sh v0radius Topological Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 8.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(9, "v0radius"); + rPtAnalysis.fill(HIST("hNK0sh"), 8.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(9, "v0radius"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 8.5, v0.mK0Short()); - if (doK0shdcaposdautopv && (std::abs(v0.dcapostopv()) < kaonshSettingdcapostopv)) { // K0sh DCAPosDaughterToPV Topological Cut + if (doK0shdcaposdautopv && (std::abs(v0.dcapostopv()) < k0shSettingdcapostopv)) { // K0sh DCAPosDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 9.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hNK0sh"), 9.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 9.5, v0.mK0Short()); - if (doK0shdcanegdautopv && (std::abs(v0.dcanegtopv()) < kaonshSettingdcanegtopv)) { // K0sh DCANegDaughterToPV Topological Cut + if (doK0shdcanegdautopv && (std::abs(v0.dcanegtopv()) < k0shSettingdcanegtopv)) { // K0sh DCANegDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNK0sh"), 10.5); - rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hNK0sh"), 10.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 10.5, v0.mK0Short()); // Cut Plots rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotK0sh"), v0.alpha(), v0.qtarm()); - rPtAnalysis.fill(HIST("hNSigmaPosPionFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPionFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + // rPtAnalysis.fill(HIST("hNSigmaPosPionFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + // rPtAnalysis.fill(HIST("hNSigmaNegPionFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); rPtAnalysis.fill(HIST("hK0shcosPA"), v0.v0cosPA()); rPtAnalysis.fill(HIST("hK0shV0radius"), v0.v0radius()); rPtAnalysis.fill(HIST("hK0shDCAV0Daughters"), v0.dcaV0daughters()); @@ -504,81 +542,78 @@ struct V0PtInvMassPlots { } // Lambda selection function - template - bool acceptLambda(TV0 const& v0) + template + bool acceptLambda(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) { - const auto& posDaughterTrack = v0.template posTrack_as(); // Positive Daughter track - const auto& negDaughterTrack = v0.template negTrack_as(); // Negative Daughter track - - rPtAnalysis.fill(HIST("hNLambda"), 0.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(1, "All"); + rPtAnalysis.fill(HIST("hNLambda"), 0.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(1, "All"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 0.5, v0.mLambda()); if (doRapidityCut && (std::abs(v0.rapidity(1)) > rapidityCut)) { // V0 Rapidity Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 1.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(2, "Rapidity"); + rPtAnalysis.fill(HIST("hNLambda"), 1.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(2, "Rapidity"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 1.5, v0.mLambda()); if (doLambdaTPCPID && ((std::abs(posDaughterTrack.tpcNSigmaPr()) > nSigmaTPCProton) || (std::abs(negDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion))) { // TPC PID on daughter pion and proton for Lambda return false; } - rPtAnalysis.fill(HIST("hNLambda"), 2.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); + rPtAnalysis.fill(HIST("hNLambda"), 2.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 2.5, v0.mLambda()); if (doLambdacomptmasscut && ((std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut) || (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // Lambda competitive v0 mass cut (cut out Kaons) return false; } - rPtAnalysis.fill(HIST("hNLambda"), 3.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); + rPtAnalysis.fill(HIST("hNLambda"), 3.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 3.5, v0.mLambda()); if (doLambdaMaxct && (v0.v0radius() > lambdamaxct)) { // Lambda max ct return false; } - rPtAnalysis.fill(HIST("hNLambda"), 4.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(5, "Max_ct"); + rPtAnalysis.fill(HIST("hNLambda"), 4.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(5, "Max_ct"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 4.5, v0.mLambda()); if (doLambdaArmenterosCut && v0.qtarm() < (lambdaparamArmenterosCut * std::abs(v0.alpha()))) { // Lambda Armenteros Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 5.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(6, "Armenteros"); + rPtAnalysis.fill(HIST("hNLambda"), 5.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(6, "Armenteros"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 5.5, v0.mLambda()); if (doLambdacosPACut && (v0.v0cosPA() < lambdaSettingcosPA)) { // Lambda cosPA Topological Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 6.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(7, "cosPA"); + rPtAnalysis.fill(HIST("hNLambda"), 6.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(7, "cosPA"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 6.5, v0.mLambda()); if (doLambdaDCAdauCut && (v0.dcaV0daughters() > lambdaSettingdcav0dau)) { // Lambda DCAdaughters Topological Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 7.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(8, "DCAdau"); + rPtAnalysis.fill(HIST("hNLambda"), 7.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(8, "DCAdau"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 7.5, v0.mLambda()); if (doLambdav0radiusCut && (v0.v0radius() < lambdaSettingradius)) { // Lambda v0radius Topological Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 8.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(9, "v0radius"); + rPtAnalysis.fill(HIST("hNLambda"), 8.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(9, "v0radius"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 8.5, v0.mLambda()); if (doLambdadcaposdautopv && (std::abs(v0.dcapostopv()) < lambdaSettingdcapostopv)) { // Lambda DCAPosDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 9.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hNLambda"), 9.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 9.5, v0.mLambda()); if (doLambdadcanegdautopv && (std::abs(v0.dcanegtopv()) < lambdaSettingdcanegtopv)) { // Lambda DCANegDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNLambda"), 10.5); - rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hNLambda"), 10.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 10.5, v0.mLambda()); // Cut Plots rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotLambda"), v0.alpha(), v0.qtarm()); - rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambdas"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambdas"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + // rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambdas"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); + // rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambdas"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); rPtAnalysis.fill(HIST("hLambdacosPA"), v0.v0cosPA()); rPtAnalysis.fill(HIST("hLambdaV0radius"), v0.v0radius()); rPtAnalysis.fill(HIST("hLambdaDCAV0Daughters"), v0.dcaV0daughters()); @@ -588,125 +623,153 @@ struct V0PtInvMassPlots { return true; } - // Antilambda selection function - template - bool acceptAntilambda(TV0 const& v0) + // AntiLambda selection function + template + bool acceptAntilambda(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) { - const auto& posDaughterTrack = v0.template posTrack_as(); // Positive Daughter track - const auto& negDaughterTrack = v0.template negTrack_as(); // Negative Daughter track - - rPtAnalysis.fill(HIST("hNAntilambda"), 0.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(1, "All"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 0.5, v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hNAntiLambda"), 0.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(1, "All"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 0.5, v0.mAntiLambda()); if (doRapidityCut && (std::abs(v0.rapidity(2)) > rapidityCut)) { // V0 Rapidity Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 1.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(2, "Rapidity"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 1.5, v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hNAntiLambda"), 1.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(2, "Rapidity"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 1.5, v0.mAntiLambda()); if (doAntilambdaTPCPID && (std::abs(negDaughterTrack.tpcNSigmaPr()) > nSigmaTPCProton || std::abs(posDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion)) { // TPC PID on daughter pion and proton for AntiLambda return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 2.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 2.5, v0.mAntiLambda()); - if (doAntilambdacomptmasscut && ((std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut) || (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // Antilambda competitive v0 mass cut (cut out Kaons) + rPtAnalysis.fill(HIST("hNAntiLambda"), 2.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(3, "TPC_PID"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 2.5, v0.mAntiLambda()); + if (doAntilambdacomptmasscut && ((std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut) || (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut))) { // AntiLambda competitive v0 mass cut (cut out Kaons) return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 3.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 3.5, v0.mAntiLambda()); - if (doAntilambdaMaxct && (v0.v0radius() > antilambdamaxct)) { // Antilambda max ct + rPtAnalysis.fill(HIST("hNAntiLambda"), 3.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(4, "Compt_Mass"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 3.5, v0.mAntiLambda()); + if (doAntilambdaMaxct && (v0.v0radius() > antilambdamaxct)) { // AntiLambda max ct return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 4.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(5, "Max_ct"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 4.5, v0.mAntiLambda()); - if (doAntilambdaArmenterosCut && (v0.qtarm() < (antilambdaparamArmenterosCut * std::abs(v0.alpha())))) { // Antilambda Armenteros Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 4.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(5, "Max_ct"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 4.5, v0.mAntiLambda()); + if (doAntilambdaArmenterosCut && (v0.qtarm() < (antilambdaparamArmenterosCut * std::abs(v0.alpha())))) { // AntiLambda Armenteros Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 5.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(6, "Armenteros"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 5.5, v0.mAntiLambda()); - if (doAntilambdacosPACut && (v0.v0cosPA() < antilambdaSettingcosPA)) { // Antilambda cosPA Topological Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 5.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(6, "Armenteros"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 5.5, v0.mAntiLambda()); + if (doAntilambdacosPACut && (v0.v0cosPA() < antilambdaSettingcosPA)) { // AntiLambda cosPA Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 6.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(7, "cosPA"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 6.5, v0.mAntiLambda()); - if (doAntilambdaDCAdauCut && (v0.dcaV0daughters() > antilambdaSettingdcav0dau)) { // Antilambda DCAdaughters Topological Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 6.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(7, "cosPA"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 6.5, v0.mAntiLambda()); + if (doAntilambdaDCAdauCut && (v0.dcaV0daughters() > antilambdaSettingdcav0dau)) { // AntiLambda DCAdaughters Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 7.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(8, "DCAdau"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 7.5, v0.mAntiLambda()); - if (doAntilambdav0radiusCut && (v0.v0radius() < antilambdaSettingradius)) { // Antilambda v0radius Topological Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 7.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(8, "DCAdau"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 7.5, v0.mAntiLambda()); + if (doAntilambdav0radiusCut && (v0.v0radius() < antilambdaSettingradius)) { // AntiLambda v0radius Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 8.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(9, "v0radius"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 8.5, v0.mAntiLambda()); - if (doAntilambdadcaposdautopv && (std::abs(v0.dcapostopv()) < antilambdaSettingdcapostopv)) { // Antilambda DCAPosDaughterToPV Topological Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 8.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(9, "v0radius"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 8.5, v0.mAntiLambda()); + if (doAntilambdadcaposdautopv && (std::abs(v0.dcapostopv()) < antilambdaSettingdcapostopv)) { // AntiLambda DCAPosDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 9.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 9.5, v0.mAntiLambda()); - if (doAntilambdadcanegdautopv && (std::abs(v0.dcanegtopv()) < antilambdaSettingdcanegtopv)) { // Antilambda DCANegDaughterToPV Topological Cut + rPtAnalysis.fill(HIST("hNAntiLambda"), 9.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(10, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 9.5, v0.mAntiLambda()); + if (doAntilambdadcanegdautopv && (std::abs(v0.dcanegtopv()) < antilambdaSettingdcanegtopv)) { // AntiLambda DCANegDaughterToPV Topological Cut return false; } - rPtAnalysis.fill(HIST("hNAntilambda"), 10.5); - rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); - rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 10.5, v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hNAntiLambda"), 10.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNAntiLambda"))->GetXaxis()->SetBinLabel(11, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hMassAntiLambdavsCuts"), 10.5, v0.mAntiLambda()); // Cut plots - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntilambda"), v0.alpha(), v0.qtarm()); - rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambdas"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambdas"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hAntilambdacosPA"), v0.v0cosPA()); - rPtAnalysis.fill(HIST("hAntilambdaV0radius"), v0.v0radius()); - rPtAnalysis.fill(HIST("hAntilambdaDCAV0Daughters"), v0.dcaV0daughters()); - rPtAnalysis.fill(HIST("hAntilambdaDCAPosDaughter"), v0.dcapostopv()); - rPtAnalysis.fill(HIST("hAntilambdaDCANegDaughter"), v0.dcanegtopv()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), v0.alpha(), v0.qtarm()); + // rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambdas"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); + // rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambdas"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hAntiLambdacosPA"), v0.v0cosPA()); + rPtAnalysis.fill(HIST("hAntiLambdaV0radius"), v0.v0radius()); + rPtAnalysis.fill(HIST("hAntiLambdaDCAV0Daughters"), v0.dcaV0daughters()); + rPtAnalysis.fill(HIST("hAntiLambdaDCAPosDaughter"), v0.dcapostopv()); + rPtAnalysis.fill(HIST("hAntiLambdaDCANegDaughter"), v0.dcanegtopv()); rPtAnalysis.fill(HIST("V0Rapidity"), v0.rapidity(2)); return true; } + // V0 selection function + template + bool acceptV0Derived(TV0 const& v0, Track const& posDaughterTrack, Track const& negDaughterTrack, TCollision const& collision) + { + rPtAnalysis.fill(HIST("hNV0s"), 0.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(1, "All V0s"); + if (doDaughterPseudorapidityCut && !(std::abs(v0.positiveeta()) < etadau && std::abs(v0.negativeeta()) < etadau)) { // Daughters Pseudorapidity Cut + return false; + } + rPtAnalysis.fill(HIST("hNV0s"), 1.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(2, "Dau Pseudorapidity"); + if (doisNotITSAfterburner && (posDaughterTrack.isITSAfterburner() || negDaughterTrack.isITSAfterburner())) { // ITS After Burner on daughter tracks + return false; + } + rPtAnalysis.fill(HIST("hNV0s"), 2.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(3, "ITS Afterburner"); + if (doitsMinHits && !(posDaughterTrack.itsNCls() >= itsMinHits && negDaughterTrack.itsNCls() >= itsMinHits)) { // Minimum hits in the ITS + return false; + } + rPtAnalysis.fill(HIST("hNV0s"), 3.5, collision.centFT0M()); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(4, "ITS Min Hits"); + // Cut Plots + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.positiveeta()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negativeeta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), v0.alpha(), v0.qtarm()); + return true; + } + // Defining the type of the daughter tracks using DaughterTracks = soa::Join; + using DaughterTracksDerived = soa::Join; o2::framework::Service pdgDB; - void genMCProcess( - soa::Join::iterator const& mcCollision, - soa::SmallGroups> const& collisions, - aod::McParticles const& mcParticles) + // This is the process for Generated Particles + void genMCProcess(soa::Join::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + aod::McParticles const& mcParticles) { // Event Efficiency, Event Split and V0 Signal Loss Corrections rMCCorrections.fill(HIST("hNEvents_Corrections"), 0.5, mcCollision.centFT0M()); // All Events if (std::abs(mcCollision.posZ()) > cutZVertex) { return; } - if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + if (!(mcCollision.multMCNParticlesEta10() > 0)) { // TRY TO CHANGE TO THIS + // if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { return; } rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5, mcCollision.centFT0M()); // Event Efficiency Denominator + int NParticlesPerCollision = 0; // Counter for the number of particles per collision for the Nch analysis // Particles (of interest) Generated Pt Spectrum and Signal Loss Denominator Loop for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.y()) < rapidityCut) { if (mcParticle.isPhysicalPrimary()) { rMCCorrections.fill(HIST("GenParticleRapidity"), mcParticle.y()); - if (mcParticle.pdgCode() == kK0Short) // kzero matched + if (mcParticle.pdgCode() == kK0Short) // K0sh matched { - rMCCorrections.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hK0shGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kLambda0) // lambda matched + if (mcParticle.pdgCode() == kLambda0) // Lambda matched { rMCCorrections.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } - if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + if (mcParticle.pdgCode() == kLambda0Bar) // AntiLambda matched { - rMCCorrections.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hAntiLambdaGeneratedPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched { @@ -738,7 +801,11 @@ struct V0PtInvMassPlots { } } } + if (acceptGeneratedParticle(mcParticle, mcCollision)) { + NParticlesPerCollision++; + } } + rNchAnalysis.fill(HIST("hNchCentralityGenerated"), mcCollision.centFT0M(), NParticlesPerCollision); // Signal Loss Numenator Loop for (const auto& collision : collisions) { rMCCorrections.fill(HIST("hNEvents_Corrections"), 2.5, mcCollision.centFT0M()); // Number of Events Reconsctructed @@ -747,6 +814,9 @@ struct V0PtInvMassPlots { } rMCCorrections.fill(HIST("hNEvents_Corrections"), 3.5, mcCollision.centFT0M()); // Event Split Denomimator and Event Efficiency Numenator for (const auto& mcParticle : mcParticles) { + if (acceptGeneratedParticle(mcParticle, mcCollision)) { + NParticlesPerCollision++; // Counter to fill the NchCerntralityPlot after the loop + } if (!mcParticle.isPhysicalPrimary()) { continue; } @@ -755,7 +825,7 @@ struct V0PtInvMassPlots { } if (mcParticle.pdgCode() == kK0Short) // kzero matched { - rMCCorrections.fill(HIST("hK0ShAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hK0shAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } if (mcParticle.pdgCode() == kLambda0) // lambda matched { @@ -763,15 +833,17 @@ struct V0PtInvMassPlots { } if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched { - rMCCorrections.fill(HIST("hAntilambdaAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); + rMCCorrections.fill(HIST("hAntiLambdaAfterEventSelectionPtSpectrum"), mcParticle.pt(), mcCollision.centFT0M()); } } } + rNchAnalysis.fill(HIST("hNchCentralityGeneratedAfterEventSelection"), mcCollision.centFT0M(), NParticlesPerCollision); // End of Signal Loss Numenator Loop } // This is the Process for the MC reconstructed Data - void recMCProcess(soa::Join::iterator const& collision, - // soa::Join const& /*mcCollisions*/, + // void recMCProcess(soa::Join::iterator const& collision, + void recMCProcess(soa::Join::iterator const& collision, + soa::Join const& /*mcCollisions*/, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly aod::McParticles const& /*mcParticles*/) @@ -790,7 +862,10 @@ struct V0PtInvMassPlots { // initialize and convert tokenized strings into vector of doubles for Pt Bin Edges std::vector kaonptedgevalues(nKaonHistograms + 1); std::vector lambdaptedgevalues(nLambdaHistograms + 1); - std::vector antilambdaPtedgevalues(nAntilambdaHistograms + 1); + std::vector antilambdaptedgevalues(nAntilambdaHistograms + 1); + + // For centrality estimation + const auto& mcCollision = collision.mcCollision_as>(); for (int i = 0; i < nKaonHistograms + 1; i++) { kaonptedgevalues[i] = std::stod(pthistos::kaonPtBins[i]); @@ -799,34 +874,37 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); } for (int i = 0; i < nAntilambdaHistograms + 1; i++) { - antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); + antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } if (!acceptEvent(collision)) { // Event Selection return; } - rMCCorrections.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Event Split Numenator + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, mcCollision.centFT0M()); // Event Split Numenator + rNchAnalysis.fill(HIST("hNchCentrality"), mcCollision.centFT0M(), collision.multNTracksGlobal()); // Nch vs Centrality for (const auto& v0 : V0s) { // 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 (!acceptV0(v0)) { // V0 Selections + const auto& posDaughterTrack = v0.template posTrack_as(); + const auto& negDaughterTrack = v0.template negTrack_as(); + if (!acceptV0(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // V0 Selections continue; } // kzero analysis if (kzeroAnalysis == true) { - if (acceptK0sh(v0)) { // K0sh Selection + if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // K0sh Selection // K0sh Signal Split Numerator Start for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges for K0sh Splitting Numerator - pthistos::kaonSplit[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator + pthistos::kaonSplit[i]->Fill(v0.mK0Short(), mcCollision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator } } // K0sh Signla Split Numerator End if (v0.has_mcParticle()) { auto v0mcParticle = v0.mcParticle(); - if (dotruthk0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched + if (dotruthK0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges - pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms + pthistos::kaonPt[i]->Fill(v0.mK0Short(), mcCollision.centFT0M()); // filling the k0s namespace histograms } } } @@ -834,9 +912,9 @@ struct V0PtInvMassPlots { auto v0mothers = v0mcParticle.mothers_as(); // Get mothers if (!v0mothers.empty()) { auto& v0mcParticleMother = v0mothers.front(); // First mother - rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); if (v0mcParticleMother.pdgCode() == kPhi) { // Phi Mother Matched - rFeeddownMatrices.fill(HIST("hK0shPhiFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hK0shPhiFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } } } @@ -846,11 +924,11 @@ struct V0PtInvMassPlots { } // lambda analysis if (lambdaAnalysis == true) { - if (acceptLambda(v0)) { // Lambda Selections + if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // Lambda Selections // Lambda Signal Split Numerator Start for (int i = 0; i < nLambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaSplit[i]->Fill(v0.mLambda(), collision.centFT0M()); + pthistos::lambdaSplit[i]->Fill(v0.mLambda(), mcCollision.centFT0M()); } } // Lambda Signal Split Numerator End @@ -860,7 +938,7 @@ struct V0PtInvMassPlots { if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nLambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda(), collision.centFT0M()); + pthistos::lambdaPt[i]->Fill(v0.mLambda(), mcCollision.centFT0M()); } } } @@ -868,15 +946,15 @@ struct V0PtInvMassPlots { auto v0mothers = v0mcParticle.mothers_as(); // Get mothers if (!v0mothers.empty()) { auto& v0mcParticleMother = v0mothers.front(); // First mother - rFeeddownMatrices.fill(HIST("hLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); if (v0mcParticleMother.pdgCode() == kXiMinus) { // Xi Minus Mother Matched - rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == kXi0) { // Xi Zero Mother Matched - rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == kOmegaMinus) { // Omega Mother Matched - rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } } } @@ -886,21 +964,21 @@ struct V0PtInvMassPlots { } // antilambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0)) { // Antilambda Selections - // Antilambda Signal Split Numerator End + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, mcCollision)) { // AntiLambda Selections + // AntiLambda Signal Split Numerator End for (int i = 0; i < nAntilambdaHistograms; i++) { - if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { - pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { + pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), mcCollision.centFT0M()); } } - // Antilambda Signal Split Numerator End + // AntiLambda Signal Split Numerator End if (v0.has_mcParticle()) { auto v0mcParticle = v0.mcParticle(); - if (dotruthAntilambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched + if (dotruthAntiLambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched if (v0mcParticle.isPhysicalPrimary()) { for (int i = 0; i < nAntilambdaHistograms; i++) { - if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), mcCollision.centFT0M()); } } } @@ -908,15 +986,15 @@ struct V0PtInvMassPlots { auto v0mothers = v0mcParticle.mothers_as(); // Get mothers if (!v0mothers.empty()) { auto& v0mcParticleMother = v0mothers.front(); // First mother - rFeeddownMatrices.fill(HIST("hAntiLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); if (v0mcParticleMother.pdgCode() == kXiPlusBar) { // Xi Plus Mother Matched - rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == -kXi0) { // Anti-Xi Zero Mother Matched - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) { // Anti-Omega (minus) Mother Matched - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), collision.centFT0M()); + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt(), mcCollision.centFT0M()); } } } @@ -927,7 +1005,7 @@ struct V0PtInvMassPlots { } } // This is the process for Real Data - void dataProcess(soa::Join::iterator const& collision, + void dataProcess(soa::Join::iterator const& collision, aod::V0Datas const& V0s, DaughterTracks const&) { @@ -945,7 +1023,7 @@ struct V0PtInvMassPlots { // initialize and convert tokenized strings into vector of doubles for Pt Bin Edges std::vector kaonptedgevalues(nKaonHistograms + 1); std::vector lambdaptedgevalues(nLambdaHistograms + 1); - std::vector antilambdaPtedgevalues(nAntilambdaHistograms + 1); + std::vector antilambdaptedgevalues(nAntilambdaHistograms + 1); for (int i = 0; i < nKaonHistograms + 1; i++) { kaonptedgevalues[i] = std::stod(pthistos::kaonPtBins[i]); @@ -954,21 +1032,23 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); } for (int i = 0; i < nAntilambdaHistograms + 1; i++) { - antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); + antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - if (!acceptEvent(collision)) { // Event Selection return; } - rMCCorrections.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events + rNchAnalysis.fill(HIST("hNchCentrality"), collision.centFT0M(), collision.multNTracksGlobal()); // Nch vs Centrality for (const auto& v0 : V0s) { // 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 (!acceptV0(v0)) { // V0 Selection + const auto& posDaughterTrack = v0.template posTrack_as(); + const auto& negDaughterTrack = v0.template negTrack_as(); + if (!acceptV0(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selection continue; } - // kzero analysis + // K0sh analysis if (kzeroAnalysis == true) { - if (acceptK0sh(v0)) { // K0sh Selection + if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection for (int i = 0; i < nKaonHistograms; i++) { if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms @@ -976,9 +1056,9 @@ struct V0PtInvMassPlots { } } } - // lambda analysis + // Lambda analysis if (lambdaAnalysis == true) { - if (acceptLambda(v0)) { // Lambda Selection + if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selection for (int i = 0; i < nLambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { pthistos::lambdaPt[i]->Fill(v0.mLambda(), collision.centFT0M()); @@ -986,9 +1066,9 @@ struct V0PtInvMassPlots { } } } - // anti-lambda analysis + // Anti-Lambda analysis if (antiLambdaAnalysis == true) { - if (acceptAntilambda(v0)) { // Antilambda Selection + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // AntiLambda Selection for (int i = 0; i < nAntilambdaHistograms; i++) { if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); @@ -998,12 +1078,234 @@ struct V0PtInvMassPlots { } } } + // This is the process for Real Derived Data + void dataProcessDerived(soa::Join::iterator const& collision, + soa::Join const& V0s, + DaughterTracksDerived const&) + { + // tokenise strings into individual values + pthistos::kaonPtBins = o2::utils::Str::tokenize(kzeroSettingPtBinsString, ','); + pthistos::lambdaPtBins = o2::utils::Str::tokenize(lambdaSettingPtBinsString, ','); + pthistos::antilambdaPtBins = o2::utils::Str::tokenize(antilambdaSettingPtBinsString, ','); + pthistos::kaonPtBins = o2::utils::Str::tokenize(kzeroSettingPtBinsString, ','); + + // Calculate number of histograms for each particle type + int nKaonHistograms = pthistos::kaonPtBins.size() - 1; + int nLambdaHistograms = pthistos::lambdaPtBins.size() - 1; + int nAntilambdaHistograms = pthistos::antilambdaPtBins.size() - 1; + + // initialize and convert tokenized strings into vector of doubles for Pt Bin Edges + std::vector kaonptedgevalues(nKaonHistograms + 1); + std::vector lambdaptedgevalues(nLambdaHistograms + 1); + std::vector antilambdaptedgevalues(nAntilambdaHistograms + 1); + + for (int i = 0; i < nKaonHistograms + 1; i++) { + kaonptedgevalues[i] = std::stod(pthistos::kaonPtBins[i]); + } + for (int i = 0; i < nLambdaHistograms + 1; i++) { + lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); + } + for (int i = 0; i < nAntilambdaHistograms + 1; i++) { + antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); + } + + // if (!acceptEvent(collision)) { // Event Selection + // return; + // } + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Number of recorded events + for (const auto& v0 : V0s) { + // 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) + const auto& posDaughterTrack = v0.template posTrackExtra_as(); // Positive Daughter track + const auto& negDaughterTrack = v0.template negTrackExtra_as(); // Negative Daughter track + if (!acceptV0Derived(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selection + continue; + } + // K0sh analysis + if (kzeroAnalysis == true) { + if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection + for (int i = 0; i < nKaonHistograms; i++) { + if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges + pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms + } + } + } + } + // Lambda analysis + if (lambdaAnalysis == true) { + if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selection + for (int i = 0; i < nLambdaHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda(), collision.centFT0M()); + } + } + } + } + // Anti-Lambda analysis + if (antiLambdaAnalysis == true) { + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // AntiLambda Selection + for (int i = 0; i < nAntilambdaHistograms; i++) { + if (antilambdaptedgevalues[i] <= v0.pt() && v0.pt() < antilambdaptedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + } + } + } + } + } + } + void recMCProcessDerived(soa::Join::iterator const& collision, + // To add McCentFT0Ms + soa::Join const& V0s, + DaughterTracksDerived const&) + { + // tokenise strings into individual values + pthistos::kaonPtBins = o2::utils::Str::tokenize(kzeroSettingPtBinsString, ','); + pthistos::lambdaPtBins = o2::utils::Str::tokenize(lambdaSettingPtBinsString, ','); + pthistos::antilambdaPtBins = o2::utils::Str::tokenize(antilambdaSettingPtBinsString, ','); + pthistos::kaonPtBins = o2::utils::Str::tokenize(kzeroSettingPtBinsString, ','); + + // Calculate number of histograms for each particle type + int nKaonHistograms = pthistos::kaonPtBins.size() - 1; + int nLambdaHistograms = pthistos::lambdaPtBins.size() - 1; + int nAntilambdaHistograms = pthistos::antilambdaPtBins.size() - 1; + + // initialize and convert tokenized strings into vector of doubles for Pt Bin Edges + std::vector kaonptedgevalues(nKaonHistograms + 1); + std::vector lambdaptedgevalues(nLambdaHistograms + 1); + std::vector antilambdaptedgevalues(nAntilambdaHistograms + 1); + + for (int i = 0; i < nKaonHistograms + 1; i++) { + kaonptedgevalues[i] = std::stod(pthistos::kaonPtBins[i]); + } + for (int i = 0; i < nLambdaHistograms + 1; i++) { + lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); + } + for (int i = 0; i < nAntilambdaHistograms + 1; i++) { + antilambdaptedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); + } + // if (!acceptEvent(collision)) { // Event Selection + // return; + // } + rPtAnalysis.fill(HIST("hNRecEvents"), 0.5, collision.centFT0M()); // Event Split Numenator + for (const auto& v0 : V0s) { + // 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) + const auto& posDaughterTrack = v0.template posTrackExtra_as(); // Positive Daughter track + const auto& negDaughterTrack = v0.template negTrackExtra_as(); // Negative Daughter track + if (!acceptV0Derived(v0, posDaughterTrack, negDaughterTrack, collision)) { // V0 Selections + continue; + } + // K0sh Analysis + if (kzeroAnalysis == true) { + if (acceptK0sh(v0, posDaughterTrack, negDaughterTrack, collision)) { // K0sh Selection + // K0sh Signal Split Numerator Start + for (int i = 0; i < nKaonHistograms; i++) { + if (kaonptedgevalues[i] <= v0.ptMC() && v0.ptMC() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges for K0sh Splitting Numerator + pthistos::kaonSplit[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms for K0sh Splitting Numerator + } + } + // K0sh SignaL Split Numerator End + if (v0.has_v0MCCore()) { + auto v0mcParticle = v0.v0MCCore_as(); + if (dotruthK0sh && (v0mcParticle.pdgCode() == kK0Short)) { // kzero matched + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nKaonHistograms; i++) { + if (kaonptedgevalues[i] <= v0.ptMC() && v0.ptMC() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges + pthistos::kaonPt[i]->Fill(v0.mK0Short(), collision.centFT0M()); // filling the k0s namespace histograms + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mother = v0.motherMCPart(); // Get mothers + rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + if (v0mother.pdgCode() == kPhi) { // Phi Mother Matched + rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + } + } + } + } + } + // Lambda analysis + if (lambdaAnalysis == true) { + if (acceptLambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // Lambda Selections + // Lambda Signal Split Numerator Start + for (int i = 0; i < nLambdaHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaSplit[i]->Fill(v0.mLambda(), collision.centFT0M()); + } + } + // Lambda Signal Split Numerator End + if (v0.has_v0MCCore()) { + auto v0mcParticle = v0.v0MCCore_as(); + if (dotruthLambda && (v0mcParticle.pdgCode() == kLambda0)) { // lambda matched + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nLambdaHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda(), collision.centFT0M()); + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mother = v0.motherMCPart(); // Get mothers + rFeeddownMatrices.fill(HIST("hLambdaFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + if (v0mother.pdgCode() == kXiMinus) { // Xi Minus Mother Matched + rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + if (v0mother.pdgCode() == kXi0) { // Xi Zero Mother Matched + rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + if (v0mother.pdgCode() == kOmegaMinus) { // Omega Mother Matched + rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + } + } + } + } + } + // AntiLambda analysis + if (antiLambdaAnalysis == true) { + if (acceptAntilambda(v0, posDaughterTrack, negDaughterTrack, collision)) { // AntiLambda Selections + // AntiLambda Signal Split Numerator End + for (int i = 0; i < nAntilambdaHistograms; i++) { + if (antilambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < antilambdaptedgevalues[i + 1]) { + pthistos::antilambdaSplit[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + } + } + // AntiLambda Signal Split Numerator End + if (v0.has_v0MCCore()) { + auto v0mcParticle = v0.v0MCCore_as(); + if (dotruthAntiLambda && (v0mcParticle.pdgCode() == kLambda0Bar)) { // antilambda matched + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nAntilambdaHistograms; i++) { + if (antilambdaptedgevalues[i] <= v0.ptMC() && v0.ptMC() < antilambdaptedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda(), collision.centFT0M()); + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mother = v0.motherMCPart(); // Get mothers + rFeeddownMatrices.fill(HIST("hAntiLambdaFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + if (v0mother.pdgCode() == kXiPlusBar) { // Xi Plus Mother Matched + rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + if (v0mother.pdgCode() == -kXi0) { // Anti-Xi Zero Mother Matched + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + if (v0mother.pdgCode() == kOmegaPlusBar) { // Anti-Omega (minus) Mother Matched + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.ptMC(), std::hypot(v0mother.px(), v0mother.py()), collision.centFT0M()); + } + } + } + } + } + } + } + } PROCESS_SWITCH(V0PtInvMassPlots, genMCProcess, "Process Run 3 MC Generated", false); PROCESS_SWITCH(V0PtInvMassPlots, recMCProcess, "Process Run 3 MC Reconstructed", false); PROCESS_SWITCH(V0PtInvMassPlots, dataProcess, "Process Run 3 Data,", false); // PROCESS_SWITCH(V0PtInvMassPlots, genMCProcessDerived, "Process Run 3 MC Generated", false); - // PROCESS_SWITCH(V0PtInvMassPlots, recMCProcessDerived, "Process Run 3 MC Reconstructed", false); - // PROCESS_SWITCH(V0PtInvMassPlots, dataProcessDerived, "Process Run 3 Data,", true); + PROCESS_SWITCH(V0PtInvMassPlots, recMCProcessDerived, "Process Run 3 MC Reconstructed", false); + PROCESS_SWITCH(V0PtInvMassPlots, dataProcessDerived, "Process Run 3 Data,", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/zdccalderived.cxx b/PWGLF/Tasks/Strangeness/zdccalderived.cxx index 5d8776345d1..f92540cca05 100644 --- a/PWGLF/Tasks/Strangeness/zdccalderived.cxx +++ b/PWGLF/Tasks/Strangeness/zdccalderived.cxx @@ -116,8 +116,8 @@ struct zdccalderived { Configurable useShift{"useShift", false, "shift histograms"}; Configurable ispolarization{"ispolarization", false, "Flag to check polarization"}; Configurable followpub{"followpub", true, "flag to use alphaZDC"}; - Configurable useGainCallib{"useGainCallib", false, "use gain calibration"}; - Configurable useCallibvertex{"useCallibvertex", false, "use calibration for vxy"}; + // Configurable useGainCallib{"useGainCallib", false, "use gain calibration"}; + // Configurable useCallibvertex{"useCallibvertex", false, "use calibration for vxy"}; Configurable coarse1{"coarse1", false, "RE1"}; Configurable fine1{"fine1", false, "REfine1"}; Configurable coarse2{"coarse2", false, "RE2"}; @@ -133,8 +133,6 @@ struct zdccalderived { Configurable useRecentereSp{"useRecentereSp", false, "use Recentering with Sparse or THn"}; Configurable useRecenterefineSp{"useRecenterefineSp", false, "use fine Recentering with THn"}; - Configurable confGainPath{"confGainPath", "Users/p/prottay/My/Object/NewPbPbpass4_10092024/gaincallib", "Path to gain calibration"}; - Configurable confGainPathVxy{"confGainPathVxy", "Users/p/prottay/My/Object/swapcoords/PbPbpass4_20112024/recentervert", "Path to gain calibration for vxy"}; Configurable confRecentereSp{"confRecentereSp", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse or THn path for recentering"}; Configurable confRecentereSp2{"confRecentereSp2", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse or THn path for recentering 2"}; Configurable confRecentereSp3{"confRecentereSp3", "Users/p/prottay/My/Object/Testingwithsparse/NewPbPbpass4_17092024/recenter", "Sparse or THn path for recentering 3"}; @@ -354,20 +352,20 @@ struct zdccalderived { auto vx = collision.vx(); auto vy = collision.vy(); - 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; + double psiZDCC = -99; + double psiZDCA = -99; + auto qxZDCA = collision.qxA(); + auto qxZDCC = collision.qxC(); + auto qyZDCA = collision.qyA(); + auto qyZDCC = collision.qyC(); + // auto sumA = 0.0; + // auto sumC = 0.0; auto timestamps = ccdb->getRunDuration(currentRunNumber, 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 - + /* std::array znaEnergy = { collision.znaE0(), collision.znaE1(), @@ -442,14 +440,14 @@ struct zdccalderived { qyZDCC = 0.0; return; } - + */ histos.fill(HIST("hEvtSelInfo"), 8.5); histos.fill(HIST("hCentrality"), centrality); histos.fill(HIST("Vz"), vz); histos.fill(HIST("AvgVxy"), 0.5, vx); histos.fill(HIST("AvgVxy"), 1.5, vy); - + /* if (useCallibvertex && (currentRunNumber != lastRunNumber)) { gainprofilevxy = ccdb->getForTimeStamp(confGainPathVxy.value, ts); } @@ -458,7 +456,7 @@ struct zdccalderived { vx = vx - gainprofilevxy->GetBinContent(1); vy = vy - gainprofilevxy->GetBinContent(2); } - + */ bool res = 0; bool resfine = 0; int check = 1; diff --git a/PWGLF/Utils/EventSelectionFlagsMapping.def b/PWGLF/Utils/EventSelectionFlagsMapping.def index 3e23ba89cdd..06b4cb5c03a 100644 --- a/PWGLF/Utils/EventSelectionFlagsMapping.def +++ b/PWGLF/Utils/EventSelectionFlagsMapping.def @@ -49,6 +49,7 @@ EVSEL_FLAG(kNoITSROFrameBorder, applyNoITSROBorderCut, false, kFlagITSROFrameBor // Vertex quality EVSEL_FLAG(kIsVertexITSTPC, applyITSTPCvertex, false, kFlagVertexITSTPC, setApplyITSTPCvertex, ApplyITSTPCvertex, "IsVertexITSTPC", "Apply ITS-TPC vertex") EVSEL_FLAG(kIsGoodZvtxFT0vsPV, applyZvertexTimedifference, false, kFlagZvtxFT0vsPV, setApplyZvertexTimedifference, ApplyZvertexTimedifference, "IsGoodZvtxFT0vsPV", "Apply Z-vertex time difference") +EVSEL_FLAG(kIsVertexTOFmatched, applyVertexTOFmatched, false, kFlagVertexTOFmatched, setApplyVertexTOFmatched, ApplyVertexTOFmatched, "IsVertexTOFmatched", "Vertex has TOF-matched track") EVSEL_FLAG(kIsVertexTRDmatched, applyVertexTRDmatched, false, kFlagVertexTRDmatched, setApplyVertexTRDmatched, ApplyVertexTRDmatched, "IsVertexTRDmatched", "Vertex has TRD-matched track") // Pileup rejection @@ -74,5 +75,4 @@ EVSEL_FLAG(kIsBBT0A, applyBBT0A, false, kFlagBBT0A, setApplyBBT0A, ApplyBBT0A, " EVSEL_FLAG(kIsBBT0C, applyBBT0C, false, kFlagBBT0C, setApplyBBT0C, ApplyBBT0C, "IsBBT0C", "T0C in beam-beam window") // Future flags can be easily added here, for example: -// EVSEL_FLAG(kIsVertexTOFmatched, applyVertexTOFmatched, false, kFlagVertexTOFmatched, setApplyVertexTOFmatched, ApplyVertexTOFmatched, "IsVertexTOFmatched", "Apply vertex TOF matched") // EVSEL_FLAG(kNoCollInTimeRangeStrict, applyCollInTimeRangeStrict, false, kNoCollInTimeRangeStrict, setApplyCollInTimeRangeStrict, ApplyCollInTimeRangeStrict, "NoCollInTimeRangeStrict", "Apply NoCollInTimeRangeStrict") diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index 7b23620ee64..ebb6fd34436 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -46,11 +46,11 @@ class CollisonCuts kFlagTrigerTVX, kFlagTimeFrameBorder, kFlagITSROFrameBorder, - kFlagSel8, kFlagVertexITSTPC, - kFlagBunchPileup, kFlagZvtxFT0vsPV, - kFlagOccupancy, + kFlagVertexTOFmatched, + kFlagVertexTRDmatched, + kFlagBunchPileup, kNoCollInTimeRangeStandard, kNoCollInTimeRangeNarrow, kNoCollInTimeRangeStrict, @@ -60,9 +60,10 @@ class CollisonCuts kIsGoodITSLayersAll, kIsGoodITSLayer3, kIsGoodITSLayer0123, - kFlagVertexTRDmatched, kFlagBBT0A, kFlagBBT0C, + kFlagSel8, + kFlagOccupancy, kAllpassed }; @@ -111,9 +112,9 @@ class CollisonCuts mHistogramRegistry->add("Event/posZ", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); // z-vertex histogram after event selections mHistogramRegistry->add("Event/posZ_noCut", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); // z-vertex histogram before all selections if (mCheckIsRun3) { - mHistogramRegistry->add("Event/CentFT0M", "; vCentT0M; Entries", o2::framework::kTH1F, {{110, 0, 110}}); - mHistogramRegistry->add("Event/CentFT0C", "; vCentT0C; Entries", o2::framework::kTH1F, {{110, 0, 110}}); - mHistogramRegistry->add("Event/CentFT0A", "; vCentT0A; Entries", o2::framework::kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0M", "; FT0M Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0C", "; FT0C Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0A", "; FT0A Percentile; Entries", o2::framework::kTH1F, {{110, 0, 110}}); mHistogramRegistry->add("Event/posZ_ITSOnly", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); mHistogramRegistry->add("Event/posZ_ITSTPC", "; vtx_{z} (cm); Entries", o2::framework::kTH1F, {{250, -12.5, 12.5}}); mHistogramRegistry->add("Event/trackOccupancyInTimeRange_noCut", "; Occupancy; Entries", o2::framework::kTH1F, {{500, 0., 20000.}}); @@ -131,6 +132,7 @@ class CollisonCuts mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagSel8), "sel8"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagOccupancy), "LowOccupancy"); + mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kFlagVertexTOFmatched), "VertexTOFmatched"); mHistogramRegistry->get(HIST("CollCutCounts"))->GetXaxis()->SetBinLabel(binLabel(EvtSel::kAllpassed), "Allpassed"); } @@ -268,6 +270,13 @@ class CollisonCuts setSelection(EvtSel::kNoHighMultCollInPrevRof, apply); } + /// Set the VertexTOFmatched cut + void setApplyVertexTOFmatched(bool apply) + { + mApplyVertexTOFmatched = apply; + setSelection(EvtSel::kFlagVertexTOFmatched, apply); + } + /// Set the VertexTRDmatched cut void setApplyVertexTRDmatched(bool apply) { @@ -531,6 +540,7 @@ class CollisonCuts bool mApplyCollInRofStandard = false; ///< Apply NoCollInRofStandard selection bool mApplyCollInRofStrict = false; ///< Apply NoCollInRofStrict selection bool mApplyHighMultCollInPrevRof = false; ///< Apply NoHighMultCollInPrevRof selection + bool mApplyVertexTOFmatched = false; ///< Apply vertex TOF matched selection bool mApplyVertexTRDmatched = false; ///< Apply vertex TRD matched selection bool mApplyBBT0A = false; ///< Apply T0A beam-beam timing selection bool mApplyBBT0C = false; ///< Apply T0C beam-beam timing selection diff --git a/PWGLF/Utils/nucleiUtils.h b/PWGLF/Utils/nucleiUtils.h index c6783df13a8..e322db1b024 100644 --- a/PWGLF/Utils/nucleiUtils.h +++ b/PWGLF/Utils/nucleiUtils.h @@ -14,19 +14,20 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTOF.h" #include "Common/TableProducer/PID/pidTOFBase.h" -#include "MathUtils/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Framework/HistogramRegistry.h" #include "Framework/HistogramSpec.h" +#include "MathUtils/BetheBlochAleph.h" #include "TMCProcess.h" #include +#include #include #include @@ -102,6 +103,8 @@ struct SlimCandidate { float phiGenerated = -999.f; float centrality = -1.f; uint64_t mcProcess = TMCProcess::kPNoProcess; + float nsigmaTpc = -999.f; + float nsigmaTof = -999.f; }; enum Species { @@ -534,11 +537,11 @@ class PidManager float pScaled = p * mMomScaling[0] + mMomScaling[1]; float betaGamma = pScaled / masses[mSpecies]; return o2::common::BetheBlochAleph(betaGamma, - mTpcBetheBlochParams[0], - mTpcBetheBlochParams[1], - mTpcBetheBlochParams[2], - mTpcBetheBlochParams[3], - mTpcBetheBlochParams[4]); + mTpcBetheBlochParams[0], + mTpcBetheBlochParams[1], + mTpcBetheBlochParams[2], + mTpcBetheBlochParams[3], + mTpcBetheBlochParams[4]); } template diff --git a/PWGLF/Utils/strangenessBuilderModule.h b/PWGLF/Utils/strangenessBuilderModule.h index cf838ec507a..06c2f969817 100644 --- a/PWGLF/Utils/strangenessBuilderModule.h +++ b/PWGLF/Utils/strangenessBuilderModule.h @@ -897,6 +897,9 @@ class BuilderModule // handle TPC-only tracks properly (photon conversions) if (v0BuilderOpts.moveTPCOnlyTracks) { + if (collision.has_bc()) { + mVDriftMgr.update(collision.template bc_as().timestamp()); + } if (isPosTPCOnly) { // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate posTrackPar.setPID(o2::track::PID::Electron); @@ -1368,6 +1371,9 @@ class BuilderModule pvX = collision.posX(); pvY = collision.posY(); pvZ = collision.posZ(); + if (v0BuilderOpts.generatePhotonCandidates && v0BuilderOpts.moveTPCOnlyTracks && collision.has_bc()) { + mVDriftMgr.update(collision.template bc_as().timestamp()); + } } auto const& posTrack = tracks.rawIteratorAt(v0.posTrackId); auto const& negTrack = tracks.rawIteratorAt(v0.negTrackId); @@ -1384,7 +1390,8 @@ class BuilderModule negTrackPar.setPID(o2::track::PID::Electron); auto const& collision = collisions.rawIteratorAt(v0.collisionId); - if (!mVDriftMgr.moveTPCTrack(collision, posTrack, posTrackPar)) { + // if track cannot be uniquely identified with a collision or cannot be assigned to a collision at all (collisionId = -1), do not attempt to move the TPC track and move on + if (!posTrack.has_collision() || !mVDriftMgr.moveTPCTrack(collision, posTrack, posTrackPar)) { products.v0dataLink(-1, -1); continue; } @@ -1397,7 +1404,8 @@ class BuilderModule negTrackPar.setPID(o2::track::PID::Electron); auto const& collision = collisions.rawIteratorAt(v0.collisionId); - if (!mVDriftMgr.moveTPCTrack(collision, negTrack, negTrackPar)) { + // if track cannot be uniquely identified with a collision or cannot be assigned to a collision at all (collisionId = -1), do not attempt to move the TPC track and move on + if (!negTrack.has_collision() || !mVDriftMgr.moveTPCTrack(collision, negTrack, negTrackPar)) { products.v0dataLink(-1, -1); continue; } diff --git a/PWGLF/Utils/svPoolCreator.h b/PWGLF/Utils/svPoolCreator.h index c0b32c2574e..ce3473ed65f 100644 --- a/PWGLF/Utils/svPoolCreator.h +++ b/PWGLF/Utils/svPoolCreator.h @@ -22,11 +22,6 @@ #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisDataModel.h" -using namespace o2; -using namespace o2::constants; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; using CollBracket = o2::math_utils::Bracket; constexpr uint64_t bOffsetMax = 241; // track compatibility can never go beyond 6 mus (ITS) @@ -89,7 +84,7 @@ class svPoolCreator void appendTrackCand(const T& trackCand, const C& collisions, int pdgHypo, o2::aod::AmbiguousTracks const& ambiTracks, BC const&) { if (pdgHypo != track0Pdg && pdgHypo != track1Pdg) { - LOG(debug) << "Wrong pdg hypothesis"; + LOGP(debug, "Wrong pdg hypothesis"); return; } bool isDau0 = pdgHypo == track0Pdg; @@ -134,12 +129,12 @@ class svPoolCreator } // now loop over all the collisions to make the pool - for (int i = firstCollIdx; i < collisions.size(); i++) { - const auto& collision = collisions.rawIteratorAt(i); + for (int collIdx = firstCollIdx; collIdx < collisions.size(); collIdx++) { + const auto& collision = collisions.rawIteratorAt(collIdx); float collTime = collision.collisionTime(); float collTimeRes2 = collision.collisionTimeRes() * collision.collisionTimeRes(); uint64_t collBC = collision.template bc_as().globalBC(); - int collIdx = collision.globalIndex(); + // int collIdx = collision.globalIndex(); int64_t bcOffset = globalBC - static_cast(collBC); if (static_cast(std::abs(bcOffset)) > bOffsetMax) { if (bcOffset < 0) { @@ -153,13 +148,13 @@ class svPoolCreator float trackTimeRes{0.}; if (trackCand.isPVContributor()) { trackTime = trackCand.template collision_as().collisionTime(); // if PV contributor, we assume the time to be the one of the collision - trackTimeRes = constants::lhc::LHCBunchSpacingNS; // 1 BC + trackTimeRes = o2::constants::lhc::LHCBunchSpacingNS; // 1 BC } else { trackTime = trackCand.trackTime(); trackTimeRes = trackCand.trackTimeRes(); } - const float deltaTime = trackTime - collTime + bcOffset * constants::lhc::LHCBunchSpacingNS; + const float deltaTime = trackTime - collTime + bcOffset * o2::constants::lhc::LHCBunchSpacingNS; float sigmaTimeRes2 = collTimeRes2 + trackTimeRes * trackTimeRes; float thresholdTime = 0.; diff --git a/PWGMM/Lumi/Tasks/CMakeLists.txt b/PWGMM/Lumi/Tasks/CMakeLists.txt index 5bd93ae27d8..000f831a5c8 100644 --- a/PWGMM/Lumi/Tasks/CMakeLists.txt +++ b/PWGMM/Lumi/Tasks/CMakeLists.txt @@ -50,3 +50,8 @@ o2physics_add_dpl_workflow(lumi-stability-p-p SOURCES lumiStabilityPP.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCCDB O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lumi-zdc-qa + SOURCES lumiZdcQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCCDB O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx b/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx index c5609cbbd9a..629c2a7078d 100644 --- a/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx +++ b/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx @@ -10,36 +10,33 @@ // or submit itself to any jurisdiction. // author: akhuntia@cern.ch -#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "CommonConstants/GeomConstants.h" -#include "CommonUtils/NameConf.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "DataFormatsFDD/Digit.h" -#include "DataFormatsFIT/Triggers.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexer.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/PrimaryVertex.h" -#include "ReconstructionDataFormats/Vertex.h" - -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include #include +#include +#include #include using namespace o2; diff --git a/PWGMM/Lumi/Tasks/fitLumi.cxx b/PWGMM/Lumi/Tasks/fitLumi.cxx index a62771cda66..4bcc73496c9 100644 --- a/PWGMM/Lumi/Tasks/fitLumi.cxx +++ b/PWGMM/Lumi/Tasks/fitLumi.cxx @@ -11,21 +11,25 @@ // author: arvind.khuntia@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/EventSelection.h" -#include "DataFormatsFDD/Digit.h" -#include "DataFormatsFIT/Triggers.h" -#include "Common/DataModel/FT0Corrected.h" - -#include "CCDB/CcdbApi.h" -#include "CommonDataFormat/BunchFilling.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "TH1F.h" -#include "TH2F.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -111,7 +115,7 @@ struct VdMAO2D { registry.get(HIST("FT0/bcVertexCollBC"))->Fill(localBC); } } // vertex - } // ft0 + } // ft0 nTF++; } // process @@ -174,7 +178,7 @@ struct VdMAO2D { } } // vertex - } // fdd + } // fdd } PROCESS_SWITCH(VdMAO2D, processFDD, "Process FDD trigger rates for VdM", true); diff --git a/PWGMM/Lumi/Tasks/lumi.cxx b/PWGMM/Lumi/Tasks/lumi.cxx index cc0149dbde7..b1fcd5910d5 100644 --- a/PWGMM/Lumi/Tasks/lumi.cxx +++ b/PWGMM/Lumi/Tasks/lumi.cxx @@ -15,43 +15,30 @@ // o2-analysis-trackselection -b --isRun3 0 | o2-analysis-mm-lumi -b // --configuration json://./config.json -#include -#include -#include -#include - -#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonUtils/NameConf.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" - -#include "DetectorsVertexing/PVertexer.h" - -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/PrimaryVertex.h" -#include "ReconstructionDataFormats/Vertex.h" - -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" - -#include "CommonConstants/GeomConstants.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" - -#include "DataFormatsCalibration/MeanVertexObject.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include namespace o2::aod { diff --git a/PWGMM/Lumi/Tasks/lumiStability.cxx b/PWGMM/Lumi/Tasks/lumiStability.cxx index 9584561af67..ab1dca52f6e 100644 --- a/PWGMM/Lumi/Tasks/lumiStability.cxx +++ b/PWGMM/Lumi/Tasks/lumiStability.cxx @@ -16,22 +16,32 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/BunchFilling.h" -#include "DataFormatsFDD/Digit.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsFV0/Digit.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include #include #include #include @@ -55,7 +65,8 @@ struct LumiStabilityTask { Configurable nOrbitsPerTF{"nOrbitsPerTF", 128, "number of orbits per time frame"}; Configurable minOrbitConf{"minOrbitConf", 0, "minimum orbit"}; Configurable is2022Data{"is2022Data", true, "To 2022 data"}; - Configurable minEmpty{"minEmpty", 5, "number of BCs empty for leading BC"}; + Configurable minEmpty{"minEmpty", 13, "number of BCs empty for leading BC"}; + Configurable nBCsOffSet{"nBCsOffSet", 7, "number of BCs offset for FDD"}; Service ccdb; parameters::GRPLHCIFData* grplhcif = nullptr; @@ -74,6 +85,7 @@ struct LumiStabilityTask { std::bitset bcPatternA; std::bitset bcPatternC; std::bitset bcPatternB; + std::bitset bcPatternL; std::bitset bcPatternE; void init(InitContext const&) @@ -287,6 +299,7 @@ struct LumiStabilityTask { bcPatternC = ~beamPatternA & beamPatternC; bcPatternB = beamPatternA & beamPatternC; bcPatternE = ~beamPatternA & ~beamPatternC; + bcPatternL = beamPatternA & beamPatternC; for (int i = 0; i < nBCsPerOrbit; i++) { if (bcPatternA[i]) { @@ -297,18 +310,23 @@ struct LumiStabilityTask { } if (bcPatternB[i]) { histos.fill(HIST("hBcB"), i); + } + if (bcPatternL[i]) { bool isLeadBC = true; for (int jbit = i - minEmpty; jbit < i; jbit++) { int kbit = jbit; if (kbit < 0) kbit += nbin; - if (bcPatternB[kbit]) { + if (!bcPatternE[kbit]) { + bcPatternL[i] = false; isLeadBC = false; break; } } - if (isLeadBC) + if (isLeadBC) { + // bcPatternL[i] = true; histos.fill(HIST("hBcBL"), i); + } } if (bcPatternE[i]) { histos.fill(HIST("hBcE"), i); @@ -379,8 +397,8 @@ struct LumiStabilityTask { } if (trgFDD) { - histos.fill(HIST("FDD/bcVertexTriggerCTP"), localBC + 7); - if (bcPatternB[localBC]) { + histos.fill(HIST("FDD/bcVertexTriggerCTP"), localBC + nBCsOffSet); + if (bcPatternB[localBC + nBCsOffSet]) { histos.fill(HIST("FDD/nBCsVsTime"), timeSinceSOF); histos.fill(HIST("FDD/hTimeForRateCTP"), (bc.timestamp() - tsSOR) * 1.e-3); // Converting ms into seconds } @@ -398,21 +416,13 @@ struct LumiStabilityTask { histos.fill(HIST("FV0/hTimeForRateCTP"), (bc.timestamp() - tsSOR) * 1.e-3); // Converting ms into seconds } } - bool isLeadBC = true; - for (int jbit = localBC - minEmpty; jbit < localBC; jbit++) { - int kbit = jbit; - if (kbit < 0) - kbit += nbin; - if (bcPatternB[kbit]) { - isLeadBC = false; - break; - } - } - if (isLeadBC) { + if (bcPatternL[localBC + nBCsOffSet]) { if (trgFDD) { histos.fill(HIST("FDD/nBCsVsTimeLeadingBC"), timeSinceSOF); histos.fill(HIST("FDD/hTimeForRateLeadingBCCTP"), (bc.timestamp() - tsSOR) * 1.e-3); } + } + if (bcPatternL[localBC]) { if (trgFT0) { histos.fill(HIST("FT0/nBCsVsTimeLeadingBC"), timeSinceSOF); histos.fill(HIST("FT0/hTimeForRateLeadingBCCTP"), (bc.timestamp() - tsSOR) * 1.e-3); @@ -420,8 +430,7 @@ struct LumiStabilityTask { if (trgFV0) { histos.fill(HIST("FV0/hTimeForRateLeadingBCCTP"), (bc.timestamp() - tsSOR) * 1.e-3); } - } - // } + } // if over leading pattern } // loop over bcs for (auto const& fdd : fdds) { @@ -465,18 +474,9 @@ struct LumiStabilityTask { if (bcPatternB[localBC]) { histos.fill(HIST("FDD/hTimeForRate"), (bc.timestamp() - tsSOR) * 1.e-3); // Converting ms into seconds - bool isLeadBC = true; - for (int jbit = localBC - minEmpty; jbit < localBC; jbit++) { - int kbit = jbit; - if (kbit < 0) - kbit += nbin; - if (bcPatternB[kbit]) { - isLeadBC = false; - break; - } - } - if (isLeadBC) - histos.fill(HIST("FDD/hTimeForRateLeadingBC"), (bc.timestamp() - tsSOR) * 1.e-3); + } + if (bcPatternL[localBC]) { + histos.fill(HIST("FDD/hTimeForRateLeadingBC"), (bc.timestamp() - tsSOR) * 1.e-3); } int deltaIndex = 0; // backward move counts @@ -514,18 +514,6 @@ struct LumiStabilityTask { if (bcPatternB[localBC]) { histos.fill(HIST("FDD/timeACbcBVertex"), fdd.timeA(), fdd.timeC()); histos.fill(HIST("FDD/hBcBVertex"), localBC); - bool isLeadBC = true; - for (int jbit = localBC - minEmpty; jbit < localBC; jbit++) { - int kbit = jbit; - if (kbit < 0) - kbit += nbin; - if (bcPatternB[kbit]) { - isLeadBC = false; - break; - } - } - if (isLeadBC) - histos.fill(HIST("FDD/hBcBVertexL"), localBC); histos.fill(HIST("FDD/hTimeAVertex"), fdd.timeA()); histos.fill(HIST("FDD/hTimeCVertex"), fdd.timeC()); if (is2022Data) { @@ -555,6 +543,9 @@ struct LumiStabilityTask { } } } + if (bcPatternL[localBC]) { + histos.fill(HIST("FDD/hBcBVertexL"), localBC); + } if (bcPatternE[localBC]) { histos.fill(HIST("FDD/timeACbcEVertex"), fdd.timeA(), fdd.timeC()); histos.fill(HIST("FDD/hBcEVertex"), localBC); @@ -577,18 +568,6 @@ struct LumiStabilityTask { if (bcPatternB[localBC]) { histos.fill(HIST("FDD/timeACbcB"), fdd.timeA(), fdd.timeC()); histos.fill(HIST("FDD/hBcB"), localBC); - bool isLeadBC = true; - for (int jbit = localBC - minEmpty; jbit < localBC; jbit++) { - int kbit = jbit; - if (kbit < 0) - kbit += nbin; - if (bcPatternB[kbit]) { - isLeadBC = false; - break; - } - } - if (isLeadBC) - histos.fill(HIST("FDD/hBcBL"), localBC); histos.fill(HIST("FDD/hTimeACoinc"), fdd.timeA()); histos.fill(HIST("FDD/hTimeCCoinc"), fdd.timeC()); if (!is2022Data) { @@ -618,6 +597,9 @@ struct LumiStabilityTask { } } } + if (bcPatternL[localBC]) { + histos.fill(HIST("FDD/hBcBL"), localBC); + } if (bcPatternE[localBC]) { histos.fill(HIST("FDD/timeACbcE"), fdd.timeA(), fdd.timeC()); histos.fill(HIST("FDD/hBcE"), localBC); @@ -738,20 +720,6 @@ struct LumiStabilityTask { histos.fill(HIST("FT0/timeACbcB"), ft0.timeA(), ft0.timeC()); histos.fill(HIST("FT0/hBcB"), localBC); histos.fill(HIST("FT0/hTimeForRate"), (bc.timestamp() - tsSOR) * 1.e-3); // Converting ms into seconds - bool isLeadBC = true; - for (int jbit = localBC - minEmpty; jbit < localBC; jbit++) { - int kbit = jbit; - if (kbit < 0) - kbit += nbin; - if (bcPatternB[kbit]) { - isLeadBC = false; - break; - } - } - if (isLeadBC) { - histos.fill(HIST("FT0/hTimeForRateLeadingBC"), (bc.timestamp() - tsSOR) * 1.e-3); // Converting ms into seconds - histos.fill(HIST("FT0/hBcBL"), localBC); - } histos.fill(HIST("FT0/hTimeA"), ft0.timeA()); histos.fill(HIST("FT0/hTimeC"), ft0.timeC()); @@ -780,6 +748,10 @@ struct LumiStabilityTask { histos.fill(HIST("FT0/hValidTimevsBC"), localBC); } } + if (bcPatternL[localBC]) { + histos.fill(HIST("FT0/hTimeForRateLeadingBC"), (bc.timestamp() - tsSOR) * 1.e-3); // Converting ms into seconds + histos.fill(HIST("FT0/hBcBL"), localBC); + } if (bcPatternE[localBC]) { histos.fill(HIST("FT0/timeACbcE"), ft0.timeA(), ft0.timeC()); histos.fill(HIST("FT0/hBcE"), localBC); diff --git a/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx b/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx index aaee1103dfb..068801a64c5 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityLightIons.cxx @@ -12,151 +12,198 @@ /// \file lumiStabilityLightIons.cxx /// \brief Analysis over BCs to study the luminosity stability along time /// -/// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt, Stefanie Mrozinski (stefanie.mrozinski@cern.ch) - Goethe University Frankfurt +/// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt +/// \author Stefanie Mrozinski (stefanie.mrozinski@cern.ch) - Goethe University Frankfurt +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/MetadataHelper.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include #include #include +#include #include +#include #include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -o2::common::core::MetadataHelper metadataInfo; // Metadata helper - -namespace o2::aod -{ -namespace myBc_aod -{ -DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); -DECLARE_SOA_COLUMN(BCid, bcId, int); -DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); -DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); -DECLARE_SOA_COLUMN(AmplitudeZNA, amplitudeZNA, float); -DECLARE_SOA_COLUMN(AmplitudeZNC, amplitudeZNC, float); -} // namespace myBc_aod -DECLARE_SOA_TABLE(MyBCaod, "AOD", "MYBCAOD", myBc_aod::Timestamp, myBc_aod::BCid, myBc_aod::TimeZNA, myBc_aod::TimeZNC, myBc_aod::AmplitudeZNA, myBc_aod::AmplitudeZNC); -} // namespace o2::aod +o2::common::core::MetadataHelper metadataInfo; using MyBCs = soa::Join; struct LumiStabilityLightIons { - Produces BCaod; Configurable cfgDoFT0Vtx{"cfgDoFT0Vtx", true, "Create and fill histograms for the FT0 vertex trigger"}; Configurable cfgDoFT0CE{"cfgDoFT0CE", true, "Create and fill histograms for the FT0 centrality trigger"}; Configurable cfgDoFDD{"cfgDoFDD", true, "Create and fill histograms for the FDD trigger"}; Configurable cfgDo1ZNC{"cfgDo1ZNC", true, "Create and fill histograms for the 1ZNC trigger"}; - Configurable cfgDoBCA{"cfgDoBCA", false, "Create and fill histograms for the BCs of type A"}; + Configurable cfgDoBCA{"cfgDoBCA", true, "Create and fill histograms for the BCs of type A"}; Configurable cfgDoBCB{"cfgDoBCB", true, "Create and fill histograms for the BCs of type B"}; - Configurable cfgDoBCC{"cfgDoBCC", false, "Create and fill histograms for the BCs of type C"}; - Configurable cfgDoBCE{"cfgDoBCE", false, "Create and fill histograms for the BCs of type E"}; - Configurable cfgDoBCL{"cfgDoBCL", false, "Create and fill histograms for leading BCs of type B"}; - Configurable cfgDoBCSL{"cfgDoBCSL", false, "Create and fill histograms for super-leading BCs (no preceding FT0/FDD activity) of type B"}; - - Configurable cfgRequireZDCTriggerForZDCQA{"cfgRequireZDCTriggerForZDCQA", false, "Require ZDC trigger (1ZNC) for filling QA histograms"}; - Configurable cfgRequireTVXTriggerForZDCQA{"cfgRequireTVXTriggerForZDCQA", false, "Require FT0 vertex trigger (MTVX) for filling ZDC QA histograms"}; + Configurable cfgDoBCC{"cfgDoBCC", true, "Create and fill histograms for the BCs of type C"}; + Configurable cfgDoBCE{"cfgDoBCE", true, "Create and fill histograms for the BCs of type E"}; + Configurable cfgDoBCL{"cfgDoBCL", true, "Create and fill histograms for leading BCs of type B (non-B BCs before)"}; + Configurable cfgDoBCLE{"cfgDoBCLE", true, "Create and fill histograms for leading BCs of type B (strictly empty BCs before)"}; + Configurable cfgDoBCNL{"cfgDoBCNL", true, "Create and fill histograms for non-leading BCs of type B (complement of BCL)"}; + Configurable cfgDoBCNLE{"cfgDoBCNLE", true, "Create and fill histograms for non-leading BCs of type B (complement of BCLE)"}; + Configurable cfgDoBCSLFDD{"cfgDoBCSLFDD", true, "Create and fill histograms for super-leading BCs w.r.t. FDD activity"}; + Configurable cfgDoBCSLFT0{"cfgDoBCSLFT0", true, "Create and fill histograms for super-leading BCs w.r.t. FT0 activity"}; + Configurable cfgDoBCNSLFDD{"cfgDoBCNSLFDD", true, "Create and fill histograms for non-super-leading BCs w.r.t. FDD activity"}; + Configurable cfgDoBCNSLFT0{"cfgDoBCNSLFT0", true, "Create and fill histograms for non-super-leading BCs w.r.t. FT0 activity"}; Configurable cfgRequireNoT0ForSLBC{"cfgRequireNoT0ForSLBC", false, "Require no T0 signal for definition of super leading BC (otherwise only no FDD)"}; - Configurable cfgEmptyBCsBeforeLeadingBC{"cfgEmptyBCsBeforeLeadingBC", 5, "Minimum number of empty BCs before a leading BC to identify it as such"}; + Configurable cfgEmptyBCsBeforeLeadingBC{"cfgEmptyBCsBeforeLeadingBC", 5, "Minimum number of non-B BCs before a BCL leading BC"}; + Configurable cfgEmptyBCsBeforeLeadingBCLE{"cfgEmptyBCsBeforeLeadingBCLE", 5, "Minimum number of strictly empty (E-type) BCs before a BCLE leading BC"}; + Configurable cfgBCsBeforeSuperLeading{"cfgBCsBeforeSuperLeading", 5, "Minimum number of BCs without FDD/FT0 activity before a super-leading BC"}; - // Configurables specific to VdM analysis: output ao2d with timestamps and ZDC times - Configurable cfgFillBCao2d{"cfgFillBCao2d", false, "Fill BC ao2d with timestamps and ZDC times"}; - Configurable cfgTstampStartFillingBCao2d{"cfgTstampStartFillingBCao2d", 0, "Minimum value of timestamp for output bc ao2d to be filled"}; - Configurable cfgTstampEndFillingBCao2d{"cfgTstampEndFillingBCao2d", 0, "Maximum value of timestamp for output bc ao2d to be filled"}; + Configurable cfgBcShiftFDDForData2023{"cfgBcShiftFDDForData2023", 7, "Number of BCs to shift FDD, applied for 2023 data only"}; std::bitset beamPatternA, beamPatternC; - std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL; - - std::string strLPMProductionTag = ""; // MC production tag to be retrieved from AO2D metadata + std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE; + std::bitset bcPatternL; + std::bitset bcPatternLE; + std::string strLPMProductionTag = ""; const int nBCsPerOrbit = 3564; parameters::GRPLHCIFData* mLHCIFdata = nullptr; int mRunNumber = -1; + bool isData23 = false; + int mBcShiftFDD = 0; ctpRateFetcher mRateFetcher; - bool isLeadingBC = false; HistogramRegistry mHistManager{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - const int nTriggers = 5; - enum TriggerAliases { kAllBCs = 0, - kFT0Vtx = 1, - kFT0CE = 2, - kFDD = 3, - k1ZNC = 4 }; - - const int nBCCategories = 6; - enum BCCategories { kBCA = 0, // A side BCs (bunch-crossings that had beam only from A side) - kBCB = 1, // B type BCs (bunch-crossings that had beam from both sides) - kBCC = 2, // C side BCs (bunch-crossings that had beam only from C side) - kBCE = 3, // empty BCs (bunch-crossings that did not have beam from either side) - kBCL = 4, // leading BCs (bunch-crossings that did not have interacting bunches for a configurable number of preceding BCs) - kBCSL = 5 }; // super-leading BCs (bunch-crossings that did not have FDD/FT0 activity for a configurable number of preceding BCs) - - static constexpr std::string_view NBCsVsTimeHistNames[5][6] = - {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_SL/nBCsVsTime"}, - {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_SL/nBCsVsTime"}, - {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_SL/nBCsVsTime"}, - {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_SL/nBCsVsTime"}, - {"1ZNC/BC_A/nBCsVsTime", "1ZNC/BC_B/nBCsVsTime", "1ZNC/BC_C/nBCsVsTime", "1ZNC/BC_E/nBCsVsTime", "1ZNC/BC_L/nBCsVsTime", "1ZNC/BC_SL/nBCsVsTime"}}; - - static constexpr std::string_view NBCsVsBCIDHistNames[5][6] = - {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_SL/nBCsVsBCID"}, - {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_SL/nBCsVsBCID"}, - {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_SL/nBCsVsBCID"}, - {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_SL/nBCsVsBCID"}, - {"1ZNC/BC_A/nBCsVsBCID", "1ZNC/BC_B/nBCsVsBCID", "1ZNC/BC_C/nBCsVsBCID", "1ZNC/BC_E/nBCsVsBCID", "1ZNC/BC_L/nBCsVsBCID", "1ZNC/BC_SL/nBCsVsBCID"}}; - - int64_t bcSOR; - int nBCsPerTF; + static constexpr int nTriggers = 5; + enum TriggerAliases { + kAllBCs = 0, + kFT0Vtx = 1, + kFT0CE = 2, + kFDD = 3, + k1ZNC = 4 + }; + + static constexpr int nBCCategories = 12; + enum BCCategories { + kBCA = 0, + kBCB = 1, + kBCC = 2, + kBCE = 3, + kBCL = 4, + kBCLE = 5, + kBCNL = 6, + kBCNLE = 7, + kBCSLFDD = 8, + kBCSLFT0 = 9, + kBCNSLFDD = 10, + kBCNSLFT0 = 11 + }; + + static constexpr std::string_view NBCsVsTimeHistNames[5][12] = { + {"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_LE/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NLE/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime"}, + {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_LE/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NLE/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime"}, + {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_LE/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NLE/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime"}, + {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_LE/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NLE/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime"}, + {"1ZNC/BC_A/nBCsVsTime", "1ZNC/BC_B/nBCsVsTime", "1ZNC/BC_C/nBCsVsTime", "1ZNC/BC_E/nBCsVsTime", "1ZNC/BC_L/nBCsVsTime", "1ZNC/BC_LE/nBCsVsTime", "1ZNC/BC_NL/nBCsVsTime", "1ZNC/BC_NLE/nBCsVsTime", "1ZNC/BC_SL_FDD/nBCsVsTime", "1ZNC/BC_SL_FT0/nBCsVsTime", "1ZNC/BC_NSL_FDD/nBCsVsTime", "1ZNC/BC_NSL_FT0/nBCsVsTime"}}; + + static constexpr std::string_view NBCsVsBCIDHistNames[5][12] = { + {"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_LE/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NLE/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_LE/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NLE/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_LE/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NLE/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID"}, + {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_LE/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NLE/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID"}, + {"1ZNC/BC_A/nBCsVsBCID", "1ZNC/BC_B/nBCsVsBCID", "1ZNC/BC_C/nBCsVsBCID", "1ZNC/BC_E/nBCsVsBCID", "1ZNC/BC_L/nBCsVsBCID", "1ZNC/BC_LE/nBCsVsBCID", "1ZNC/BC_NL/nBCsVsBCID", "1ZNC/BC_NLE/nBCsVsBCID", "1ZNC/BC_SL_FDD/nBCsVsBCID", "1ZNC/BC_SL_FT0/nBCsVsBCID", "1ZNC/BC_NSL_FDD/nBCsVsBCID", "1ZNC/BC_NSL_FT0/nBCsVsBCID"}}; + + static constexpr std::string_view NBCsInspectedVsBCIDHistNames[5][12] = { + {"AllBCs/BC_A/nBCsInspectedVsBCID", "AllBCs/BC_B/nBCsInspectedVsBCID", "AllBCs/BC_C/nBCsInspectedVsBCID", "AllBCs/BC_E/nBCsInspectedVsBCID", "AllBCs/BC_L/nBCsInspectedVsBCID", "AllBCs/BC_LE/nBCsInspectedVsBCID", "AllBCs/BC_NL/nBCsInspectedVsBCID", "AllBCs/BC_NLE/nBCsInspectedVsBCID", "AllBCs/BC_SL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_SL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0VTx/BC_A/nBCsInspectedVsBCID", "FT0VTx/BC_B/nBCsInspectedVsBCID", "FT0VTx/BC_C/nBCsInspectedVsBCID", "FT0VTx/BC_E/nBCsInspectedVsBCID", "FT0VTx/BC_L/nBCsInspectedVsBCID", "FT0VTx/BC_LE/nBCsInspectedVsBCID", "FT0VTx/BC_NL/nBCsInspectedVsBCID", "FT0VTx/BC_NLE/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0CE/BC_A/nBCsInspectedVsBCID", "FT0CE/BC_B/nBCsInspectedVsBCID", "FT0CE/BC_C/nBCsInspectedVsBCID", "FT0CE/BC_E/nBCsInspectedVsBCID", "FT0CE/BC_L/nBCsInspectedVsBCID", "FT0CE/BC_LE/nBCsInspectedVsBCID", "FT0CE/BC_NL/nBCsInspectedVsBCID", "FT0CE/BC_NLE/nBCsInspectedVsBCID", "FT0CE/BC_SL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_SL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FDD/BC_A/nBCsInspectedVsBCID", "FDD/BC_B/nBCsInspectedVsBCID", "FDD/BC_C/nBCsInspectedVsBCID", "FDD/BC_E/nBCsInspectedVsBCID", "FDD/BC_L/nBCsInspectedVsBCID", "FDD/BC_LE/nBCsInspectedVsBCID", "FDD/BC_NL/nBCsInspectedVsBCID", "FDD/BC_NLE/nBCsInspectedVsBCID", "FDD/BC_SL_FDD/nBCsInspectedVsBCID", "FDD/BC_SL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FDD/nBCsInspectedVsBCID", "FDD/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"1ZNC/BC_A/nBCsInspectedVsBCID", "1ZNC/BC_B/nBCsInspectedVsBCID", "1ZNC/BC_C/nBCsInspectedVsBCID", "1ZNC/BC_E/nBCsInspectedVsBCID", "1ZNC/BC_L/nBCsInspectedVsBCID", "1ZNC/BC_LE/nBCsInspectedVsBCID", "1ZNC/BC_NL/nBCsInspectedVsBCID", "1ZNC/BC_NLE/nBCsInspectedVsBCID", "1ZNC/BC_SL_FDD/nBCsInspectedVsBCID", "1ZNC/BC_SL_FT0/nBCsInspectedVsBCID", "1ZNC/BC_NSL_FDD/nBCsInspectedVsBCID", "1ZNC/BC_NSL_FT0/nBCsInspectedVsBCID"}}; + + std::array, nBCCategories>, nTriggers> mInspectedHistos{}; + + int64_t bcSOR = 0; + int nBCsPerTF = 0; int64_t currentTFid = -1; + int64_t globalBCIdOfLastBCWithActivityFDD{std::numeric_limits::min() / 2}; + int64_t globalBCIdOfLastBCWithActivityFT0{std::numeric_limits::min() / 2}; + int64_t globalBCLastInspectedBC{-1}; + + using DenomCounter = std::vector, nTriggers>>; + + bool hasAnyFDDTrigger(const std::bitset<64>& ctpInputMask) const + { + return ctpInputMask.test(12) || ctpInputMask.test(14) || ctpInputMask.test(15) || + ctpInputMask.test(16) || ctpInputMask.test(17); + } + + bool hasAnyFT0Trigger(const std::bitset<64>& ctpInputMask) const + { + return ctpInputMask.test(0) || ctpInputMask.test(1) || ctpInputMask.test(2) || + ctpInputMask.test(3) || ctpInputMask.test(4); + } + void init(InitContext&) { - strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag + strLPMProductionTag = metadataInfo.get("LPMProductionTag"); LOG(info) << "strLPMProductionTag: " << strLPMProductionTag; - AxisSpec timeAxis{1440, 0., 1440., "#bf{t-t_{SOF} (min)}"}, bcIDAxis{3600, 0., 3600., "#bf{BC ID in orbit}"}; + AxisSpec timeAxis{1440, 0., 1440., "#bf{t-t_{SOF} (min)}"}; + AxisSpec bcIDAxis{3600, 0., 3600., "#bf{BC ID in orbit}"}; for (int iTrigger = 0; iTrigger < nTriggers; iTrigger++) { if ((iTrigger == kAllBCs) || (iTrigger == kFT0Vtx && cfgDoFT0Vtx) || (iTrigger == kFT0CE && cfgDoFT0CE) || (iTrigger == kFDD && cfgDoFDD) || (iTrigger == k1ZNC && cfgDo1ZNC)) { for (int iBCCategory = 0; iBCCategory < nBCCategories; iBCCategory++) { - if ((iBCCategory == kBCA && cfgDoBCA) || (iBCCategory == kBCB && cfgDoBCB) || (iBCCategory == kBCC && cfgDoBCC) || (iBCCategory == kBCE && cfgDoBCE) || (iBCCategory == kBCL && cfgDoBCL)) { + if ((iBCCategory == kBCA && cfgDoBCA) || (iBCCategory == kBCB && cfgDoBCB) || (iBCCategory == kBCC && cfgDoBCC) || (iBCCategory == kBCE && cfgDoBCE) || + (iBCCategory == kBCL && cfgDoBCL) || (iBCCategory == kBCLE && cfgDoBCLE) || + (iBCCategory == kBCNL && cfgDoBCNL) || (iBCCategory == kBCNLE && cfgDoBCNLE) || + (iBCCategory == kBCSLFDD && cfgDoBCSLFDD) || (iBCCategory == kBCSLFT0 && cfgDoBCSLFT0) || + (iBCCategory == kBCNSLFDD && cfgDoBCNSLFDD) || (iBCCategory == kBCNSLFT0 && cfgDoBCNSLFT0)) { mHistManager.add(Form("%s", std::string(NBCsVsTimeHistNames[iTrigger][iBCCategory]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); mHistManager.add(Form("%s", std::string(NBCsVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); + mInspectedHistos[iTrigger][iBCCategory] = mHistManager.add(Form("%s", std::string(NBCsInspectedVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "Inspected BC ID (denominator for mu);#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); } } - if (cfgDoBCSL && (iTrigger == kFT0Vtx || iTrigger == kFDD || iTrigger == kAllBCs)) { // only for FT0Vtx and FDD fill super-leading BC histograms - mHistManager.add(Form("%s", std::string(NBCsVsTimeHistNames[iTrigger][5]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); - mHistManager.add(Form("%s", std::string(NBCsVsBCIDHistNames[iTrigger][5]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); - } } } - if (cfgDoBCSL) { + if (cfgDoBCSLFDD || cfgDoBCSLFT0 || cfgDoBCNSLFDD || cfgDoBCNSLFT0) { mHistManager.add("FITQA/BCHasFT0", "Does the BC have FT0?;BC has FT0;TVX triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetYaxis()->SetBinLabel(1, "No CTP trigger"); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetYaxis()->SetBinLabel(2, "CTP triggered"); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetXaxis()->SetBinLabel(1, "No found FT0"); mHistManager.get(HIST("FITQA/BCHasFT0")).get()->GetXaxis()->SetBinLabel(2, "Found FT0"); + mHistManager.add("FITQA/BCHasFDD", "Does the BC have FDD?;BC has FDD;FDD triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); mHistManager.get(HIST("FITQA/BCHasFDD")).get()->GetYaxis()->SetBinLabel(1, "No CTP trigger"); mHistManager.get(HIST("FITQA/BCHasFDD")).get()->GetYaxis()->SetBinLabel(2, "CTP triggered"); @@ -167,35 +214,31 @@ struct LumiStabilityLightIons { mHistManager.add("FT0Vtx_EvSel/nBCsVsTime", "Time of TVX triggered BCs since the start of fill;;#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); mHistManager.add("nBCsVsBCID", "Time of TVX triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); mHistManager.add("TFsPerMinute", "TFs seen in this minute (to account for failed jobs);#bf{t-t_{SOF} (min)};#bf{#it{N}_{TFs}}", HistType::kTH1D, {timeAxis}); - - if (cfgDo1ZNC) { - AxisSpec zdcTimeAxis{200, -50., 50.}; - mHistManager.add("ZDCQA/BCHasZDC", "Does the BC have ZDC?;BC has ZDC;Has ZNC according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); - mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetYaxis()->SetBinLabel(1, "No CTP trigger"); - mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetYaxis()->SetBinLabel(2, "CTP triggered"); - mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetXaxis()->SetBinLabel(1, "No found ZDC"); - mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetXaxis()->SetBinLabel(2, "Good ZDC"); - mHistManager.add("ZDCQA/ZNCTimeVsEnergy", "ZDC properties in BCs with found ZDC;Energy;#bf{ZNC arrival time (ns)};#bf{#it{N}_{BC}}", HistType::kTH2D, {{1501, -10, 1.5E4}, zdcTimeAxis}); - mHistManager.add("ZDCQA/ZDCTimes", "Correlation between ZNA and ZNC timing;#bf{ZNC arrival time (ns)};#bf{ZNA arrival time (ns)}", HistType::kTH2D, {zdcTimeAxis, zdcTimeAxis}); - mHistManager.add("ZDCQA/ZNATime", "Time of the ZNA signal;#bf{ZNA arrival time (ns)};#bf{#it{N}_{BC}}", HistType::kTH1D, {zdcTimeAxis}); - mHistManager.add("ZDCQA/ZNCTime", "Time of the ZNC signal;#bf{ZNC arrival time (ns)};#bf{#it{N}_{BC}}", HistType::kTH1D, {zdcTimeAxis}); - } } void setLHCIFData(const auto& bc) { - if (mRunNumber == bc.runNumber()) + if (mRunNumber == bc.runNumber()) { return; + } auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); uint64_t timeStamp = bc.timestamp(); + const int runStart2023{535069}; + const int runStop2023{543113}; + isData23 = (bc.runNumber() >= runStart2023 && bc.runNumber() <= runStop2023); + mBcShiftFDD = isData23 ? static_cast(cfgBcShiftFDDForData2023) : 0; + std::map metadata; mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); - if (mLHCIFdata == nullptr) + if (mLHCIFdata == nullptr) { LOG(fatal) << "GRPLHCIFData not in database, timestamp:" << timeStamp; + } + mRunNumber = bc.runNumber(); - LOG(info) << "LHCIF data fetched for run " << mRunNumber << " and timestamp " << timeStamp; + LOG(info) << "LHCIF data fetched for run " << mRunNumber << " and timestamp " << timeStamp + << " (isData23=" << isData23 << ", bcShiftFDD=" << mBcShiftFDD << ")"; beamPatternA = mLHCIFdata->getBunchFilling().getBeamPattern(0); beamPatternC = mLHCIFdata->getBunchFilling().getBeamPattern(1); @@ -204,42 +247,60 @@ struct LumiStabilityLightIons { bcPatternB = beamPatternA & beamPatternC; bcPatternE = ~beamPatternA & ~beamPatternC; - // Create bcPatternL: leading BCs of type B that follow at least "cfgEmptyBCsBeforeLeadingBC" empty BCs - bcPatternL.reset(); // Initialize all bits to false - LOG(info) << "Starting to create bcPatternL from bcPatternB"; - LOG(info) << "Total number of BCs to check: " << o2::constants::lhc::LHCMaxBunches; + bcPatternL.reset(); + bcPatternLE.reset(); + + int totalLeadingBCsL = 0; + int totalLeadingBCsLE = 0; - int totalLeadingBCs = 0; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { - if (bcPatternB[iBC]) { // Check if current BC is of type B - int emptyBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B - for (int j = 1; j <= cfgEmptyBCsBeforeLeadingBC; j++) { - int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit - if (!bcPatternB[prevBC]) { - emptyBCsBefore++; - } else { - break; // Stop counting if we hit a type B BC - } + if (!bcPatternB[iBC]) { + continue; + } + + int nonBBefore = 0; + int emptyBefore = 0; + + for (int j = 1; j <= cfgEmptyBCsBeforeLeadingBC; j++) { + int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; + if (!bcPatternB[prevBC]) { + nonBBefore++; + } else { + break; } - if (emptyBCsBefore >= cfgEmptyBCsBeforeLeadingBC) { // If we found at least cfgEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading - bcPatternL[iBC] = true; - totalLeadingBCs++; + } + + for (int j = 1; j <= cfgEmptyBCsBeforeLeadingBCLE; j++) { + int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; + if (bcPatternE[prevBC]) { + emptyBefore++; + } else { + break; } } + + if (nonBBefore >= cfgEmptyBCsBeforeLeadingBC) { + bcPatternL[iBC] = true; + totalLeadingBCsL++; + } + if (emptyBefore >= cfgEmptyBCsBeforeLeadingBCLE) { + bcPatternLE[iBC] = true; + totalLeadingBCsLE++; + } } - LOG(info) << "bcPatternL creation complete. Total leading BCs found: " << totalLeadingBCs; + + LOG(info) << "bcPatternL (non-B before) complete. Leading BCs found: " << totalLeadingBCsL; + LOG(info) << "bcPatternLE (empty before) complete. Leading BCs found: " << totalLeadingBCsLE; auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), mRunNumber, strLPMProductionTag); - bcSOR = runInfo.orbitSOR * nBCsPerOrbit; // first bc of the first orbit + bcSOR = runInfo.orbitSOR * nBCsPerOrbit; LOG(info) << "BC SOR: " << bcSOR << " (orbit SOR: " << runInfo.orbitSOR << ") NBCs per orbit: " << nBCsPerOrbit; - nBCsPerTF = runInfo.orbitsPerTF * nBCsPerOrbit; // duration of TF in bcs - - return; + nBCsPerTF = runInfo.orbitsPerTF * nBCsPerOrbit; } float getTimeSinceSOF(const auto& bc) { - return (bc.timestamp() - mLHCIFdata->getFillNumberTime()) / 1e3 / 60; // Convert to minutes + return (bc.timestamp() - mLHCIFdata->getFillNumberTime()) / 1e3 / 60.f; } template @@ -249,188 +310,335 @@ struct LumiStabilityLightIons { mHistManager.fill(HIST(NBCsVsBCIDHistNames[iTrigger][iBCCategory]), localBC); } - void processZDCQA(MyBCs const& bcs, aod::Zdcs const&) + template + void countInspectedBC(DenomCounter& nBCsPerBcId, + int iLBC, + int iLBCFDD, + int64_t iGBC, + int64_t lastFT0ActivityBC, + int64_t lastFDDActivityBC) { - const int maxTimeZDC = 50; // Maximum time the histogram allows before setting a dummy value - const int dummyZDCTime = 42.f; // Time value to indicate missing ZDC time - for (const auto& bc : bcs) { - - std::bitset<64> ctpInputMask(bc.inputMask()); - if (cfgRequireTVXTriggerForZDCQA && !(ctpInputMask.test(2))) // 2 = 3 - 1 -> MTVX - continue; - if (cfgRequireZDCTriggerForZDCQA && !(ctpInputMask.test(25))) // 25 = 26 - 1 -> 1ZNC - continue; - - bool zdcHit = !bc.has_zdc() ? 0 : ((bc.zdc().energyCommonZNC() > -1 && std::abs(bc.zdc().timeZNC()) < 1E5) ? 1 : 0); - mHistManager.fill(HIST("ZDCQA/BCHasZDC"), zdcHit, ctpInputMask.test(25) ? 1 : 0); - if (!bc.has_zdc()) - continue; - - mHistManager.fill(HIST("ZDCQA/ZNCTimeVsEnergy"), bc.zdc().energyCommonZNC() > -1 ? bc.zdc().energyCommonZNC() : -1, std::abs(bc.zdc().timeZNC()) < maxTimeZDC ? bc.zdc().timeZNC() : dummyZDCTime); - - float timeZNA = bc.zdc().timeZNA(); - float timeZNC = bc.zdc().timeZNC(); - - if (std::abs(timeZNA) > maxTimeZDC) { - timeZNA = dummyZDCTime; // set dummy value for missing ZDC times to be able to plot them - mHistManager.fill(HIST("ZDCQA/ZNCTime"), timeZNC); + if constexpr (iTrigger == kFDD) { + if (bcPatternA[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCA]++; } - if (std::abs(timeZNC) > maxTimeZDC) { - timeZNC = dummyZDCTime; // set dummy value for missing ZDC times to be able to plot them - if (timeZNA != dummyZDCTime) // If ZNA and ZNC are both missing, do not fill the ZNA histogram with the dummy value - mHistManager.fill(HIST("ZDCQA/ZNATime"), timeZNA); + if (bcPatternB[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCB]++; } + if (bcPatternC[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCC]++; + } + if (bcPatternE[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCE]++; + } + if (bcPatternL[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCL]++; + } + if (bcPatternLE[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCLE]++; + } + if (bcPatternB[iLBCFDD] && !bcPatternL[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCNL]++; + } + if (bcPatternB[iLBCFDD] && !bcPatternLE[iLBCFDD]) { + nBCsPerBcId[iLBCFDD][iTrigger][kBCNLE]++; + } + if (bcPatternB[iLBCFDD]) { + const bool slFDD = ((iGBC + mBcShiftFDD) - lastFDDActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBCFDD][iTrigger][slFDD ? kBCSLFDD : kBCNSLFDD]++; - mHistManager.fill(HIST("ZDCQA/ZDCTimes"), timeZNA, timeZNC); - - // For VdM analysis: fill timestamps and ZDC times in output tree, if enabled - // Fill BC idx and ZNA and ZNC amplitudes as well - uint64_t timestamp = bc.timestamp(); - int64_t globalBC = bc.globalBC(); - int localBC = globalBC % nBCsPerOrbit; - float amplitudeZNA = bc.zdc().amplitudeZNA(); - float amplitudeZNC = bc.zdc().amplitudeZNC(); - if (cfgFillBCao2d && timestamp >= cfgTstampStartFillingBCao2d && timestamp <= cfgTstampEndFillingBCao2d) { - BCaod(timestamp, localBC, timeZNA, timeZNC, amplitudeZNA, amplitudeZNC); + const bool slFT0 = (iGBC - lastFT0ActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBCFDD][iTrigger][slFT0 ? kBCSLFT0 : kBCNSLFT0]++; + } + } else { + if (bcPatternA[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCA]++; + } + if (bcPatternB[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCB]++; + } + if (bcPatternC[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCC]++; + } + if (bcPatternE[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCE]++; + } + if (bcPatternL[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCL]++; + } + if (bcPatternLE[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCLE]++; + } + if (bcPatternB[iLBC] && !bcPatternL[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCNL]++; + } + if (bcPatternB[iLBC] && !bcPatternLE[iLBC]) { + nBCsPerBcId[iLBC][iTrigger][kBCNLE]++; + } + if (bcPatternB[iLBC]) { + const bool slFT0 = (iGBC - lastFT0ActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBC][iTrigger][slFT0 ? kBCSLFT0 : kBCNSLFT0]++; + } + if (bcPatternB[iLBCFDD]) { + const bool slFDD = ((iGBC + mBcShiftFDD) - lastFDDActivityBC >= cfgBCsBeforeSuperLeading); + nBCsPerBcId[iLBCFDD][iTrigger][slFDD ? kBCSLFDD : kBCNSLFDD]++; } } } - PROCESS_SWITCH(LumiStabilityLightIons, processZDCQA, "process QA for the ZDC triggers (light ions and PbPb)", false); - void processSLBunches(MyBCs const& bcs, aod::FT0s const&, aod::FDDs const&) + void process(MyBCs const& bcs, aod::FT0s const&, aod::FDDs const&) { - int64_t globalBCIdOfLastBCWithActivity = 0; + DenomCounter nBCsPerBcId(nBCsPerOrbit); + for (auto& triggerArr : nBCsPerBcId) { + for (auto& catArr : triggerArr) { + catArr.fill(0); + } + } + for (const auto& bc : bcs) { if (bc.timestamp() == 0) continue; setLHCIFData(bc); - std::bitset<64> ctpInputMask(bc.inputMask()); + float timeSinceSOF = getTimeSinceSOF(bc); - mHistManager.fill(HIST("FITQA/BCHasFT0"), bc.has_ft0(), ctpInputMask.test(2)); - mHistManager.fill(HIST("FITQA/BCHasFDD"), bc.has_fdd(), ctpInputMask.test(15)); + if (bc.selection_bit(aod::evsel::kIsTriggerTVX)) + mHistManager.fill(HIST("FT0Vtx_EvSel/nBCsVsTime"), timeSinceSOF); int64_t globalBC = bc.globalBC(); + int localBC = static_cast(globalBC % nBCsPerOrbit); - if (globalBC - globalBCIdOfLastBCWithActivity < cfgEmptyBCsBeforeLeadingBC) - continue; // not a super-leading BC + int64_t globalBCFDD = globalBC + mBcShiftFDD; + int localBCFDD = static_cast((globalBCFDD % nBCsPerOrbit + nBCsPerOrbit) % nBCsPerOrbit); - if (bc.has_fdd() || (cfgRequireNoT0ForSLBC && bc.has_ft0())) - globalBCIdOfLastBCWithActivity = globalBC; + int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; + if (thisTFid != currentTFid) { + currentTFid = thisTFid; + mHistManager.fill(HIST("TFsPerMinute"), timeSinceSOF); + } - float timeSinceSOF = getTimeSinceSOF(bc); + std::bitset<64> ctpInputMask(bc.inputMask()); - int localBC = globalBC % nBCsPerOrbit; + const bool anyFT0Trigger = hasAnyFT0Trigger(ctpInputMask); + const bool anyFDDTrigger = hasAnyFDDTrigger(ctpInputMask); - if (!bcPatternB[localBC]) - continue; + bool isSuperLeadingBcFDD = bcPatternB[localBCFDD] && + (globalBCFDD - globalBCIdOfLastBCWithActivityFDD >= cfgBCsBeforeSuperLeading); - fillHistograms(timeSinceSOF, localBC); + bool isSuperLeadingBcFT0 = bcPatternB[localBC] && + (globalBC - globalBCIdOfLastBCWithActivityFT0 >= cfgBCsBeforeSuperLeading); - if (ctpInputMask.test(2)) - fillHistograms(timeSinceSOF, localBC); - if (ctpInputMask.test(15)) - fillHistograms(timeSinceSOF, localBC); - } - } - PROCESS_SWITCH(LumiStabilityLightIons, processSLBunches, "process trigger counting of TVX and FDD for bunches without preceding single-arm activity", false); + if (cfgDoBCSLFDD || cfgDoBCSLFT0 || cfgDoBCNSLFDD || cfgDoBCNSLFT0) { + mHistManager.fill(HIST("FITQA/BCHasFT0"), bc.has_ft0(), ctpInputMask.test(2)); + mHistManager.fill(HIST("FITQA/BCHasFDD"), bc.has_fdd(), anyFDDTrigger); + } - void process(MyBCs const& bcs, aod::FT0s const&) - { - for (const auto& bc : bcs) { + int64_t globalBCStart = (globalBCLastInspectedBC >= 0 && globalBCLastInspectedBC < globalBC) ? globalBCLastInspectedBC + 1 : globalBC; + const int64_t maxBcGap = 2LL * nBCsPerOrbit; + if (globalBC - globalBCStart > maxBcGap) + globalBCStart = globalBC; - if (bc.timestamp() == 0) - continue; + for (int64_t iGBC = globalBCStart; iGBC <= globalBC; ++iGBC) { + const int iLBC = static_cast((iGBC % nBCsPerOrbit + nBCsPerOrbit) % nBCsPerOrbit); + const int iLBCFDD = static_cast(((iGBC + mBcShiftFDD) % nBCsPerOrbit + nBCsPerOrbit) % nBCsPerOrbit); - setLHCIFData(bc); + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); - float timeSinceSOF = getTimeSinceSOF(bc); + if (cfgDoFT0Vtx && ctpInputMask.test(2)) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } - if (bc.selection_bit(aod::evsel::kIsTriggerTVX)) - mHistManager.fill(HIST("FT0Vtx_EvSel/nBCsVsTime"), timeSinceSOF); + if (cfgDoFT0CE && ctpInputMask.test(4)) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } - int64_t globalBC = bc.globalBC(); - int localBC = globalBC % nBCsPerOrbit; + if (cfgDoFDD && anyFDDTrigger) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } - int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; + if (cfgDo1ZNC && ctpInputMask.test(25)) { + countInspectedBC(nBCsPerBcId, iLBC, iLBCFDD, iGBC, + globalBCIdOfLastBCWithActivityFT0, + globalBCIdOfLastBCWithActivityFDD); + } + } - if (thisTFid != currentTFid) { - currentTFid = thisTFid; - mHistManager.fill(HIST("TFsPerMinute"), timeSinceSOF); + if (anyFDDTrigger) + globalBCIdOfLastBCWithActivityFDD = globalBCFDD; + if (anyFT0Trigger) + globalBCIdOfLastBCWithActivityFT0 = globalBC; + + globalBCLastInspectedBC = globalBC; + + if (cfgDoBCA && bcPatternA[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCB && bcPatternB[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCC && bcPatternC[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCE && bcPatternE[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCL && bcPatternL[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCLE && bcPatternLE[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) { + fillHistograms(timeSinceSOF, localBCFDD); + } + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) { + fillHistograms(timeSinceSOF, localBC); + } + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) { + fillHistograms(timeSinceSOF, localBCFDD); + } + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) { + fillHistograms(timeSinceSOF, localBC); } - std::bitset<64> ctpInputMask(bc.inputMask()); + if (cfgDoFT0Vtx && ctpInputMask.test(2)) { + if (cfgDoBCA && bcPatternA[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCB && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCC && bcPatternC[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCE && bcPatternE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCL && bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + } + + if (cfgDoFT0CE && ctpInputMask.test(4)) { + if (cfgDoBCA && bcPatternA[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCB && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCC && bcPatternC[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCE && bcPatternE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCL && bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + } + + if (cfgDoFDD && anyFDDTrigger) { + if (cfgDoBCA && bcPatternA[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCB && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCC && bcPatternC[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCE && bcPatternE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCL && bcPatternL[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCLE && bcPatternLE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNL && bcPatternB[localBCFDD] && !bcPatternL[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNLE && bcPatternB[localBCFDD] && !bcPatternLE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && bcPatternB[localBCFDD] && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBCFDD] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBCFDD); + } - for (int iTrigger = 0; iTrigger < nTriggers; iTrigger++) { - if ((iTrigger == kAllBCs) || (iTrigger == kFT0Vtx && cfgDoFT0Vtx) || (iTrigger == kFT0CE && cfgDoFT0CE) || (iTrigger == kFDD && cfgDoFDD) || (iTrigger == k1ZNC && cfgDo1ZNC)) { - for (int iBCCategory = 0; iBCCategory < nBCCategories - 1; iBCCategory++) { // Don't do SL BCs here - if ((iBCCategory == kBCA && cfgDoBCA) || (iBCCategory == kBCB && cfgDoBCB) || (iBCCategory == kBCC && cfgDoBCC) || (iBCCategory == kBCE && cfgDoBCE) || (iBCCategory == kBCL && cfgDoBCL)) { - if (iTrigger == kAllBCs) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == kFT0Vtx && ctpInputMask.test(2)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == kFT0CE && ctpInputMask.test(4)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == kFDD && ctpInputMask.test(15)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - if (iTrigger == k1ZNC && ctpInputMask.test(25)) { - if (iBCCategory == kBCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == kBCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - } - } + if (cfgDo1ZNC && ctpInputMask.test(25)) { + if (cfgDoBCA && bcPatternA[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCB && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCC && bcPatternC[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCE && bcPatternE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCL && bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNL && bcPatternB[localBC] && !bcPatternL[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNLE && bcPatternB[localBC] && !bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (cfgDoBCNSLFDD && bcPatternB[localBCFDD] && !isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (cfgDoBCNSLFT0 && bcPatternB[localBC] && !isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + } + + mHistManager.fill(HIST("nBCsVsBCID"), localBC); + } + + for (int iT = 0; iT < nTriggers; ++iT) { + for (int iC = 0; iC < nBCCategories; ++iC) { + if (!mInspectedHistos[iT][iC]) { + continue; + } + for (int iBcId = 0; iBcId < nBCsPerOrbit; ++iBcId) { + const int value = nBCsPerBcId[iBcId][iT][iC]; + if (value > 0) { + mInspectedHistos[iT][iC]->Fill(iBcId, value); } } } - mHistManager.fill(HIST("nBCsVsBCID"), localBC); } } }; diff --git a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx index 3d7e1a0674c..bf0cae99e81 100644 --- a/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx +++ b/PWGMM/Lumi/Tasks/lumiStabilityPP.cxx @@ -13,25 +13,37 @@ /// \brief Analysis over BCs to study the luminosity stability along time for pp collisions /// /// \author Fabrizio Grosa (fabrizio.grosa@cern.ch), CERN +/// \author Fabrizio Chinu (fabrizio.chinu@cern.ch), INFN and University of Turin #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/MetadataHelper.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsFT0/Digit.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include #include +#include #include +#include #include o2::common::core::MetadataHelper metadataInfo; // Metadata helper @@ -45,21 +57,22 @@ enum TriggerAliases { AllBCs = 0, FT0CE = 2, FDD = 3, NTriggerAliases }; + +// SL types must be after all the others enum BCCategories { BCA = 0, // A side BCs (bunch-crossings that had beam only from A side) - BCB = 1, // B type BCs (bunch-crossings that had beam from both sides) - BCC = 2, // C side BCs (bunch-crossings that had beam only from C side) - BCE = 3, // empty BCs (bunch-crossings that did not have beam from either side) - BCL = 4, // leading BCs (bunch-crossings that did not have interacting bunches for a configurable number of preceding BCs) - BCSL = 5, // super-leading BCs (bunch-crossings that did not have FDD/FT0 activity for a configurable number of preceding BCs) + BCB, // B type BCs (bunch-crossings that had beam from both sides) + BCC, // C side BCs (bunch-crossings that had beam only from C side) + BCE, // empty BCs (bunch-crossings that did not have beam from either side) + BCL, // leading BCs (bunch-crossings that have not-B BCs for a configurable number of preceding BCs) + BCLE, // leading BCs (bunch-crossings that did not have interacting bunches for a configurable number of preceding BCs) + BCNL, // non-leading BCs of type B (bunch-crossings that come after a BCL and are of type B) + BCNLE, // non-leading BCs of type B (bunch-crossings that come after a BCLE and are of type B) + BCSLFDD, // super-leading BCs for FDD (bunch-crossings that had beam from both sides but did not have FDD activity for a configurable number of preceding BCs) + BCSLFT0, // super-leading BCs for FT0 (bunch-crossings that had beam from both sides but did not have FT0 activity for a configurable number of preceding BCs) + BCNSLFDD, // non-super-leading BCs for FDD of type B (bunch-crossings that had beam from both sides but are not SL for FDD activity for a configurable number of preceding BCs) + BCNSLFT0, // non-super-leading BCs for FT0 of type B (bunch-crossings that had beam from both sides but are not SL for FT0 activity for a configurable number of preceding BCs) NBCCategories }; } // namespace lumi -namespace aod -{ -// Columns to store the information about the presence of FT0 and FDD signals associated to a given BC -DECLARE_SOA_TABLE(BcDetectorInfo, "AOD", "BCDETECTORINFO", //! - indices::FT0Id, - indices::FDDId); -} // namespace aod } // namespace o2 using namespace o2; @@ -67,77 +80,62 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::lumi; -using BCsWithTimeStamps = soa::Join; - -struct BuildBcFlagTable { - - Produces bcFlags; - - void init(InitContext&) {} - - void process(aod::BC const& bc, - aod::FT0s const& ft0s, - aod::FDDs const& fdds) - { - int64_t idxFT0{-1}, idxFDD{-1}; - for (const auto& ft0 : ft0s) { - if (ft0.bcId() == bc.globalIndex()) { - idxFT0 = ft0.globalIndex(); - break; - } - } - for (const auto& fdd : fdds) { - if (fdd.bcId() == bc.globalIndex()) { - idxFDD = fdd.globalIndex(); - break; - } - } - bcFlags(idxFT0, idxFDD); - } -}; +using BCsWithTimeStamps = soa::Join; struct LumiStabilityPP { - Configurable doBCA{"doBCA", false, "Create and fill histograms for the BCs of type A"}; - Configurable doBCB{"doBCB", true, "Create and fill histograms for the BCs of type B"}; - Configurable doBCC{"doBCC", false, "Create and fill histograms for the BCs of type C"}; - Configurable doBCE{"doBCE", false, "Create and fill histograms for the BCs of type E"}; - Configurable doBCL{"doBCL", false, "Create and fill histograms for leading BCs of type B"}; - Configurable doBCSL{"doBCSL", false, "Create and fill histograms for super-leading BCs (no preceding FT0/FDD activity) of type B"}; - Configurable numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", 5, "Number of empty BCs before a leading BC"}; - Configurable requireNoT0ForSLBC{"requireNoT0ForSLBC", false, "Require no T0 signal for definition of super leading BC (otherwise only no FDD)"}; + static constexpr int defaulFlags[1][NBCCategories] = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; + Configurable> doTypeBC{"doTypeBC", {defaulFlags[0], NBCCategories, {"BCA", "BCB", "BCC", "BCE", "BCL", "BCLE", "BCSLFDD", "BCSLFT0", "BCNL", "BCNLE", "BCNSLFDD", "BCNSLFT0"}}, "Create and fill histograms for different BC types"}; + + static constexpr int defaulNumBCsBeforeLeadingBC[1][3] = {{5, 5, 5}}; + Configurable> numEmptyBCsBeforeLeadingBC{"numEmptyBCsBeforeLeadingBC", {defaulNumBCsBeforeLeadingBC[0], 3, {"BCL", "BCLE", "BCSL"}}, "Create and fill histograms for different BC types"}; + Configurable bcShiftFDDForData2023{"bcShiftFDDForData2023", 7, "Number of bc to shift for FDD to be applied for 2023 data only"}; std::bitset beamPatternA, beamPatternC; - std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL; + std::bitset bcPatternA, bcPatternC, bcPatternB, bcPatternE, bcPatternL, bcPatternLE; const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; + o2::framework::Service ccdb; parameters::GRPLHCIFData* mLHCIFdata = nullptr; int runNumber{-1}; + bool isData23{false}; ctpRateFetcher mRateFetcher; + int nBunchesFillingScheme; HistogramRegistry registry{"registry"}; std::array>, NBCCategories>, NTriggerAliases> histBcVsTime; std::array>, NBCCategories>, NTriggerAliases> histBcVsBcId; + std::array>, NBCCategories>, NTriggerAliases> histBcInspectVsBcId; + std::array>, BCSLFDD> histBcPattern; // undefined for BC(N)SL std::map> histNBcsVsTime; std::map> histNBcsVsBcId; std::map> histTfPerMin; - std::map> histBcHasFT0; - std::map> histBcHasFDD; + std::map> histFillingScheme; + std::map> histFillTime; + std::map> histInteractionRate; static constexpr std::string_view NBCsVsTimeHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_SL/nBCsVsTime"}, - {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_SL/nBCsVsTime"}, - {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_SL/nBCsVsTime"}, - {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_SL/nBCsVsTime"}}; + {{"AllBCs/BC_A/nBCsVsTime", "AllBCs/BC_B/nBCsVsTime", "AllBCs/BC_C/nBCsVsTime", "AllBCs/BC_E/nBCsVsTime", "AllBCs/BC_L/nBCsVsTime", "AllBCs/BC_LE/nBCsVsTime", "AllBCs/BC_NL/nBCsVsTime", "AllBCs/BC_NLE/nBCsVsTime", "AllBCs/BC_SL_FDD/nBCsVsTime", "AllBCs/BC_SL_FT0/nBCsVsTime", "AllBCs/BC_NSL_FDD/nBCsVsTime", "AllBCs/BC_NSL_FT0/nBCsVsTime"}, + {"FT0VTx/BC_A/nBCsVsTime", "FT0VTx/BC_B/nBCsVsTime", "FT0VTx/BC_C/nBCsVsTime", "FT0VTx/BC_E/nBCsVsTime", "FT0VTx/BC_L/nBCsVsTime", "FT0VTx/BC_LE/nBCsVsTime", "FT0VTx/BC_NL/nBCsVsTime", "FT0VTx/BC_NLE/nBCsVsTime", "FT0VTx/BC_SL_FDD/nBCsVsTime", "FT0VTx/BC_SL_FT0/nBCsVsTime", "FT0VTx/BC_NSL_FDD/nBCsVsTime", "FT0VTx/BC_NSL_FT0/nBCsVsTime"}, + {"FT0CE/BC_A/nBCsVsTime", "FT0CE/BC_B/nBCsVsTime", "FT0CE/BC_C/nBCsVsTime", "FT0CE/BC_E/nBCsVsTime", "FT0CE/BC_L/nBCsVsTime", "FT0CE/BC_LE/nBCsVsTime", "FT0CE/BC_NL/nBCsVsTime", "FT0CE/BC_NLE/nBCsVsTime", "FT0CE/BC_SL_FDD/nBCsVsTime", "FT0CE/BC_SL_FT0/nBCsVsTime", "FT0CE/BC_NSL_FDD/nBCsVsTime", "FT0CE/BC_NSL_FT0/nBCsVsTime"}, + {"FDD/BC_A/nBCsVsTime", "FDD/BC_B/nBCsVsTime", "FDD/BC_C/nBCsVsTime", "FDD/BC_E/nBCsVsTime", "FDD/BC_L/nBCsVsTime", "FDD/BC_LE/nBCsVsTime", "FDD/BC_NL/nBCsVsTime", "FDD/BC_NLE/nBCsVsTime", "FDD/BC_SL_FDD/nBCsVsTime", "FDD/BC_SL_FT0/nBCsVsTime", "FDD/BC_NSL_FDD/nBCsVsTime", "FDD/BC_NSL_FT0/nBCsVsTime"}}; static constexpr std::string_view NBCsVsBCIDHistNames[NTriggerAliases][NBCCategories] = - {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_SL/nBCsVsBCID"}, - {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_SL/nBCsVsBCID"}, - {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_SL/nBCsVsBCID"}, - {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_SL/nBCsVsBCID"}}; + {{"AllBCs/BC_A/nBCsVsBCID", "AllBCs/BC_B/nBCsVsBCID", "AllBCs/BC_C/nBCsVsBCID", "AllBCs/BC_E/nBCsVsBCID", "AllBCs/BC_L/nBCsVsBCID", "AllBCs/BC_LE/nBCsVsBCID", "AllBCs/BC_NL/nBCsVsBCID", "AllBCs/BC_NLE/nBCsVsBCID", "AllBCs/BC_SL_FDD/nBCsVsBCID", "AllBCs/BC_SL_FT0/nBCsVsBCID", "AllBCs/BC_NSL_FDD/nBCsVsBCID", "AllBCs/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0VTx/BC_A/nBCsVsBCID", "FT0VTx/BC_B/nBCsVsBCID", "FT0VTx/BC_C/nBCsVsBCID", "FT0VTx/BC_E/nBCsVsBCID", "FT0VTx/BC_L/nBCsVsBCID", "FT0VTx/BC_LE/nBCsVsBCID", "FT0VTx/BC_NL/nBCsVsBCID", "FT0VTx/BC_NLE/nBCsVsBCID", "FT0VTx/BC_SL_FDD/nBCsVsBCID", "FT0VTx/BC_SL_FT0/nBCsVsBCID", "FT0VTx/BC_NSL_FDD/nBCsVsBCID", "FT0VTx/BC_NSL_FT0/nBCsVsBCID"}, + {"FT0CE/BC_A/nBCsVsBCID", "FT0CE/BC_B/nBCsVsBCID", "FT0CE/BC_C/nBCsVsBCID", "FT0CE/BC_E/nBCsVsBCID", "FT0CE/BC_L/nBCsVsBCID", "FT0CE/BC_LE/nBCsVsBCID", "FT0CE/BC_NL/nBCsVsBCID", "FT0CE/BC_NLE/nBCsVsBCID", "FT0CE/BC_SL_FDD/nBCsVsBCID", "FT0CE/BC_SL_FT0/nBCsVsBCID", "FT0CE/BC_NSL_FDD/nBCsVsBCID", "FT0CE/BC_NSL_FT0/nBCsVsBCID"}, + {"FDD/BC_A/nBCsVsBCID", "FDD/BC_B/nBCsVsBCID", "FDD/BC_C/nBCsVsBCID", "FDD/BC_E/nBCsVsBCID", "FDD/BC_L/nBCsVsBCID", "FDD/BC_LE/nBCsVsBCID", "FDD/BC_NL/nBCsVsBCID", "FDD/BC_NLE/nBCsVsBCID", "FDD/BC_SL_FDD/nBCsVsBCID", "FDD/BC_SL_FT0/nBCsVsBCID", "FDD/BC_NSL_FDD/nBCsVsBCID", "FDD/BC_NSL_FT0/nBCsVsBCID"}}; + + static constexpr std::string_view NBCsInspectVsBCIDHistNames[NTriggerAliases][NBCCategories] = + {{"AllBCs/BC_A/nBCsInspectedVsBCID", "AllBCs/BC_B/nBCsInspectedVsBCID", "AllBCs/BC_C/nBCsInspectedVsBCID", "AllBCs/BC_E/nBCsInspectedVsBCID", "AllBCs/BC_L/nBCsInspectedVsBCID", "AllBCs/BC_LE/nBCsInspectedVsBCID", "AllBCs/BC_NL/nBCsInspectedVsBCID", "AllBCs/BC_NLE/nBCsInspectedVsBCID", "AllBCs/BC_SL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_SL_FT0/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FDD/nBCsInspectedVsBCID", "AllBCs/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0VTx/BC_A/nBCsInspectedVsBCID", "FT0VTx/BC_B/nBCsInspectedVsBCID", "FT0VTx/BC_C/nBCsInspectedVsBCID", "FT0VTx/BC_E/nBCsInspectedVsBCID", "FT0VTx/BC_L/nBCsInspectedVsBCID", "FT0VTx/BC_LE/nBCsInspectedVsBCID", "FT0VTx/BC_NL/nBCsInspectedVsBCID", "FT0VTx/BC_NLE/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_SL_FT0/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0VTx/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FT0CE/BC_A/nBCsInspectedVsBCID", "FT0CE/BC_B/nBCsInspectedVsBCID", "FT0CE/BC_C/nBCsInspectedVsBCID", "FT0CE/BC_E/nBCsInspectedVsBCID", "FT0CE/BC_L/nBCsInspectedVsBCID", "FT0CE/BC_LE/nBCsInspectedVsBCID", "FT0CE/BC_NL/nBCsInspectedVsBCID", "FT0CE/BC_NLE/nBCsInspectedVsBCID", "FT0CE/BC_SL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_SL_FT0/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FDD/nBCsInspectedVsBCID", "FT0CE/BC_NSL_FT0/nBCsInspectedVsBCID"}, + {"FDD/BC_A/nBCsInspectedVsBCID", "FDD/BC_B/nBCsInspectedVsBCID", "FDD/BC_C/nBCsInspectedVsBCID", "FDD/BC_E/nBCsInspectedVsBCID", "FDD/BC_L/nBCsInspectedVsBCID", "FDD/BC_LE/nBCsInspectedVsBCID", "FDD/BC_NL/nBCsInspectedVsBCID", "FDD/BC_NLE/nBCsInspectedVsBCID", "FDD/BC_SL_FDD/nBCsInspectedVsBCID", "FDD/BC_SL_FT0/nBCsInspectedVsBCID", "FDD/BC_NSL_FDD/nBCsInspectedVsBCID", "FDD/BC_NSL_FT0/nBCsInspectedVsBCID"}}; + + static constexpr std::string_view PatternHistNames[BCSLFDD] = {"BC_A/BcPattern", "BC_B/BcPattern", "BC_C/BcPattern", "BC_E/BcPattern", "BC_L/BcPattern", "BC_LE/BcPattern", "BC_NL/BcPattern", "BC_NLE/BcPattern"}; - const AxisSpec timeAxis{1440, 0., 1440., "#bf{t-t_{SOF} (min)}"}, bcIDAxis{nBCsPerOrbit, -0.5, static_cast(nBCsPerOrbit) - 0.5, "#bf{BC ID in orbit}"}; + const AxisSpec timeAxis{2880, 0., 2880., "#bf{t-t_{SOF} (min)}"}, bcIDAxis{nBCsPerOrbit, -0.5, static_cast(nBCsPerOrbit) - 0.5, "#bf{BC ID in orbit}"}; int64_t bcSOR; int nBCsPerTF; @@ -154,39 +152,42 @@ struct LumiStabilityPP { histNBcsVsTime[runNumber] = registry.add(Form("%d/FT0Vtx_EvSel/nBCsVsTime", runNumber), "Time of TVX triggered BCs since the start of fill;;#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); histNBcsVsBcId[runNumber] = registry.add(Form("%d/nBCsVsBCID", runNumber), "Time of TVX triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); histTfPerMin[runNumber] = registry.add(Form("%d/TFsPerMinute", runNumber), "TFs seen in this minute (to account for failed jobs);#bf{t-t_{SOF} (min)};#bf{#it{N}_{TFs}}", HistType::kTH1D, {timeAxis}); - - histBcHasFT0[runNumber] = registry.add(Form("%d/FITQA/BCHasFT0", runNumber), "Does the BC have FT0?;BC has FT0;TVX triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); - histBcHasFT0[runNumber]->GetYaxis()->SetBinLabel(1, "No CTP trigger"); - histBcHasFT0[runNumber]->GetYaxis()->SetBinLabel(2, "CTP triggered"); - histBcHasFT0[runNumber]->GetXaxis()->SetBinLabel(1, "No found FT0"); - histBcHasFT0[runNumber]->GetXaxis()->SetBinLabel(2, "Found FT0"); - histBcHasFDD[runNumber] = registry.add(Form("%d/FITQA/BCHasFDD", runNumber), "Does the BC have FDD?;BC has FDD;FDD triggered according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); - histBcHasFDD[runNumber]->GetYaxis()->SetBinLabel(1, "No CTP trigger"); - histBcHasFDD[runNumber]->GetYaxis()->SetBinLabel(2, "CTP triggered"); - histBcHasFDD[runNumber]->GetXaxis()->SetBinLabel(1, "No found FDD"); - histBcHasFDD[runNumber]->GetXaxis()->SetBinLabel(2, "Found FDD"); + histFillingScheme[runNumber] = registry.add(Form("%d/FillingScheme", runNumber), "Filling Scheme;Filling Scheme;", HistType::kTH1D, {{1, 0, 1}}); + histFillTime[runNumber] = registry.add(Form("%d/FillTime", runNumber), "Fill time;Fill time;", HistType::kTH1D, {{1, 0, 1}}); + histInteractionRate[runNumber] = registry.add(Form("%d/InteractionRate", runNumber), "Interaction rate (kHz);Interaction rate (kHz);", HistType::kTH1D, {{3000, 0., 3000.}}); for (int iTrigger{0}; iTrigger < NTriggerAliases; ++iTrigger) { - for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { // Don't do SL BCs here - if ((iBCCategory == BCA && doBCA) || (iBCCategory == BCB && doBCB) || (iBCCategory == BCC && doBCC) || (iBCCategory == BCE && doBCE) || (iBCCategory == BCL && doBCL) || (iBCCategory == BCSL && doBCSL)) { + for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { + if (doTypeBC->get(0u, iBCCategory)) { histBcVsTime[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsVsTimeHistNames[iTrigger][iBCCategory]).c_str()), "Time of triggered BCs since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1D, {timeAxis}); histBcVsBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of triggered BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); + histBcInspectVsBcId[iTrigger][iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(NBCsInspectVsBCIDHistNames[iTrigger][iBCCategory]).c_str()), "BC ID of inspecred BCs;#bf{BC ID in orbit};#bf{#it{N}_{BC}}", HistType::kTH1D, {bcIDAxis}); } } } + + for (int iBCCategory{0}; iBCCategory < BCSLFDD; ++iBCCategory) { + histBcPattern[iBCCategory][runNumber] = registry.add(Form("%d/%s", runNumber, std::string(PatternHistNames[iBCCategory]).c_str()), "BC Pattern;#bf{BC ID in orbit};", HistType::kTH1D, {bcIDAxis}); + } } void setLHCIFData(const auto& bc) { + if (runNumber == bc.runNumber()) { return; } - auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + const int runStart2023{535069}; + const int runStop2023{543113}; + if (bc.runNumber() >= runStart2023 && bc.runNumber() <= runStop2023) { + isData23 = true; + } + uint64_t timeStamp = bc.timestamp(); std::map metadata; - mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); + mLHCIFdata = ccdb.service->getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); if (mLHCIFdata == nullptr) { LOG(fatal) << "GRPLHCIFData not in database, timestamp:" << timeStamp; } @@ -195,6 +196,16 @@ struct LumiStabilityPP { LOG(info) << "LHCIF data fetched for run " << runNumber << " and timestamp " << timeStamp; createHistograms(); + std::string_view injectionScheme = mLHCIFdata->getInjectionScheme(); + size_t underScorePos = injectionScheme.find('_'); + size_t bPos = injectionScheme.find('b', underScorePos); + if (underScorePos != std::string_view::npos && bPos != std::string_view::npos && bPos > underScorePos) { + std::string_view nBunchesFillingSchemeStr = injectionScheme.substr(underScorePos + 1, bPos - (underScorePos + 1)); + nBunchesFillingScheme = std::stoi(std::string(nBunchesFillingSchemeStr)); + } + histFillingScheme[runNumber]->Fill(std::string(injectionScheme).c_str(), 0); + histFillTime[runNumber]->Fill(0.5, mLHCIFdata->getFillNumberTime()); + beamPatternA = mLHCIFdata->getBunchFilling().getBeamPattern(0); beamPatternC = mLHCIFdata->getBunchFilling().getBeamPattern(1); bcPatternA = beamPatternA & ~beamPatternC; @@ -202,30 +213,68 @@ struct LumiStabilityPP { bcPatternB = beamPatternA & beamPatternC; bcPatternE = ~beamPatternA & ~beamPatternC; - // Create bcPatternL: leading BCs of type B that follow at least "numEmptyBCsBeforeLeadingBC" empty BCs + // Create bcPatternL: leading BCs of type B that follow at least "numEmptyBCsBeforeLeadingBC" non-B BCs bcPatternL.reset(); // Initialize all bits to false + bcPatternLE.reset(); LOG(info) << "Starting to create bcPatternL from bcPatternB"; LOG(info) << "Total number of BCs to check: " << o2::constants::lhc::LHCMaxBunches; - int totalLeadingBCs = 0; + std::array totalLeadingBCs = {0, 0}; for (int iBC = 0; iBC < o2::constants::lhc::LHCMaxBunches; iBC++) { - if (bcPatternB[iBC]) { // Check if current BC is of type B - int emptyBCsBefore = 0; // Count how many consecutive BCs before this one are NOT type B - for (int j = 1; j <= numEmptyBCsBeforeLeadingBC; j++) { + if (bcPatternB[iBC]) { // Check if current BC is of type B + int nonBtypeBCsBefore{0}, emptyBCsBefore{0}; // Count how many consecutive BCs before this one are non-B + for (int j = 1; j <= numEmptyBCsBeforeLeadingBC->get(0u, 0u); j++) { int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit if (!bcPatternB[prevBC]) { + nonBtypeBCsBefore++; + } else { + break; // Stop counting if we hit a BCB + } + } + for (int j = 1; j <= numEmptyBCsBeforeLeadingBC->get(0u, 1u); j++) { + int prevBC = (iBC - j + o2::constants::lhc::LHCMaxBunches) % o2::constants::lhc::LHCMaxBunches; // Protection for BCs at small indices to check the end of the orbit + if (bcPatternE[prevBC]) { emptyBCsBefore++; } else { - break; // Stop counting if we hit a type B BC + break; // Stop counting if we hit a non BCE } } - if (emptyBCsBefore >= numEmptyBCsBeforeLeadingBC) { // If we found at least numEmptyBCsBeforeLeadingBC empty BCs before this one, mark it as leading + if (nonBtypeBCsBefore >= numEmptyBCsBeforeLeadingBC->get(0u, 0u)) { // If we found at least numEmptyBCsBeforeLeadingBC[0] non-B BCs before this one, mark it as leading bcPatternL[iBC] = true; - totalLeadingBCs++; + totalLeadingBCs[0]++; + } + if (emptyBCsBefore >= numEmptyBCsBeforeLeadingBC->get(0u, 1u)) { // If we found at least numEmptyBCsBeforeLeadingBC[1] empty BCs before this one, mark it as leading + bcPatternLE[iBC] = true; + totalLeadingBCs[1]++; + } + } + if (bcPatternA[iBC]) { + histBcPattern[BCA][runNumber]->Fill(iBC); + } + if (bcPatternB[iBC]) { + histBcPattern[BCB][runNumber]->Fill(iBC); + if (!bcPatternL[iBC]) { + histBcPattern[BCNL][runNumber]->Fill(iBC); + } + if (!bcPatternLE[iBC]) { + histBcPattern[BCNLE][runNumber]->Fill(iBC); } } + if (bcPatternC[iBC]) { + histBcPattern[BCC][runNumber]->Fill(iBC); + } + if (bcPatternE[iBC]) { + histBcPattern[BCE][runNumber]->Fill(iBC); + } + if (bcPatternL[iBC]) { + histBcPattern[BCL][runNumber]->Fill(iBC); + } + if (bcPatternLE[iBC]) { + histBcPattern[BCLE][runNumber]->Fill(iBC); + } } - LOG(info) << "bcPatternL creation complete. Total leading BCs found: " << totalLeadingBCs; + LOG(info) << "bcPatternL creation complete. Total leading BCs found: " << totalLeadingBCs[0]; + LOG(info) << "bcPatternLE creation complete. Total leading BCs found: " << totalLeadingBCs[1]; auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), runNumber, metadataInfo.get("LPMProductionTag")); bcSOR = runInfo.orbitSOR * nBCsPerOrbit; // first bc of the first orbit @@ -251,7 +300,12 @@ struct LumiStabilityPP { aod::FT0s const&, aod::FDDs const&) { - int64_t globalBCIdOfLastBCWithActivity = 0; + int64_t globalBCIdOfLastBCWithActivityFDD{0}, globalBCIdOfLastBCWithActivityFT0{0}, globalBCLastInspectedBC{-1}; + std::vector> nBCsPerBcId; + nBCsPerBcId.resize(nBCsPerOrbit); + std::fill(&nBCsPerBcId[0][0], &nBCsPerBcId[0][0] + (static_cast(nBCsPerOrbit) * static_cast(NBCCategories)), 0); // Initialize to 0 + + double rate{-1.}; for (const auto& bc : bcs) { if (bc.timestamp() == 0) { @@ -259,45 +313,105 @@ struct LumiStabilityPP { } setLHCIFData(bc); - + int bcShiftFDD{0}; + if (isData23) { + bcShiftFDD = bcShiftFDDForData2023; + } else { + bcShiftFDD = 0; + } float timeSinceSOF = getTimeSinceSOF(bc); - bool isTriggerTVX = (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : false); - if (isTriggerTVX) { + std::bitset<64> ctpInputMask(bc.inputMask()); + if (ctpInputMask.test(2)) { histNBcsVsTime[runNumber]->Fill(timeSinceSOF); + int runVdM23Start{542757}; + int runVdM23Stop{542768}; + if (runNumber < runVdM23Start || runNumber > runVdM23Stop) { + rate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), std::string("T0VTX"), true) * 1.e-3; // kHz + } + histInteractionRate[runNumber]->Fill(rate); } int64_t globalBC = bc.globalBC(); + int64_t globalBCFDD = bc.globalBC() + bcShiftFDD; int localBC = globalBC % nBCsPerOrbit; + int localBCFDD = globalBCFDD % nBCsPerOrbit; - bool isSuperLeadingBc{true}; - if (globalBC - globalBCIdOfLastBCWithActivity < numEmptyBCsBeforeLeadingBC) { - isSuperLeadingBc = false; // not a super-leading BC + bool isSuperLeadingBcFDD{true}, isSuperLeadingBcFT0{true}; + if (globalBCFDD - globalBCIdOfLastBCWithActivityFDD < numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { + isSuperLeadingBcFDD = false; // not a super-leading BC for FDD } - - if (bc.has_fdd() || (requireNoT0ForSLBC && bc.has_ft0())) { - globalBCIdOfLastBCWithActivity = globalBC; + if (globalBC - globalBCIdOfLastBCWithActivityFT0 < numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { + isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 } + if (!bcPatternB[localBCFDD]) { + isSuperLeadingBcFDD = false; // not a super-leading BC for FDD + } if (!bcPatternB[localBC]) { - isSuperLeadingBc = false; // not a super-leading BC + isSuperLeadingBcFT0 = false; // not a super-leading BC for FT0 + } + + int64_t globalBCStart = (globalBCLastInspectedBC >= 0 && globalBCLastInspectedBC < globalBC) ? globalBCLastInspectedBC + 1 : globalBC; + int64_t maxBcDiff = (rate > 0) ? 15 * static_cast(nBunchesFillingScheme * constants::lhc::LHCRevFreq / rate / 1.e3) : 1500; + if (globalBC - globalBCStart > maxBcDiff) { // we have a big jump in global BCs, we should not count all BCs between the current and the previous one + globalBCStart = globalBC; + } + for (int64_t iGlobalBC{globalBCStart}; iGlobalBC <= globalBC; ++iGlobalBC) { // we count all BCs in between one and another stored in the AO2Ds + int iLocalBC = iGlobalBC % nBCsPerOrbit; + if (bcPatternA[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCA]++; + } + if (bcPatternB[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCB]++; + if (iGlobalBC - globalBCIdOfLastBCWithActivityFDD >= numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { + nBCsPerBcId[iLocalBC][BCSLFDD]++; + } else { + nBCsPerBcId[iLocalBC][BCNSLFDD]++; + } + if (iGlobalBC - globalBCIdOfLastBCWithActivityFT0 >= numEmptyBCsBeforeLeadingBC->get(0u, 2u)) { + nBCsPerBcId[iLocalBC][BCSLFT0]++; + } else { + nBCsPerBcId[iLocalBC][BCNSLFT0]++; + } + if (!bcPatternL[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCNL]++; + } + if (!bcPatternLE[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCNLE]++; + } + } + if (bcPatternC[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCC]++; + } + if (bcPatternE[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCE]++; + } + if (bcPatternL[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCL]++; + } + if (bcPatternLE[iLocalBC]) { + nBCsPerBcId[iLocalBC][BCLE]++; + } + } + + if (ctpInputMask.test(12) || ctpInputMask.test(14) || ctpInputMask.test(15) || ctpInputMask.test(16) || ctpInputMask.test(17)) { // 5 FDD triggers + globalBCIdOfLastBCWithActivityFDD = globalBCFDD; + } + if (ctpInputMask.test(0) || ctpInputMask.test(1) || ctpInputMask.test(2) || ctpInputMask.test(3) || ctpInputMask.test(4)) { // 5 FT0 triggers + globalBCIdOfLastBCWithActivityFT0 = globalBC; } int64_t thisTFid = (globalBC - bcSOR) / nBCsPerTF; if (thisTFid != currentTFid) { currentTFid = thisTFid; - histNBcsVsTime[runNumber]->Fill(timeSinceSOF); + histTfPerMin[runNumber]->Fill(timeSinceSOF); } - std::bitset<64> ctpInputMask(bc.inputMask()); - - histBcHasFT0[runNumber]->Fill(bc.has_ft0(), ctpInputMask.test(2)); - histBcHasFDD[runNumber]->Fill(bc.has_fdd(), ctpInputMask.test(15)); - for (int iTrigger{0}; iTrigger < NTriggerAliases; ++iTrigger) { - for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { // Don't do SL BCs here - if ((iBCCategory == BCA && doBCA) || (iBCCategory == BCB && doBCB) || (iBCCategory == BCC && doBCC) || (iBCCategory == BCE && doBCE) || (iBCCategory == BCL && doBCL)) { + for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { + if (doTypeBC->get(0u, iBCCategory)) { if (iTrigger == AllBCs) { if (iBCCategory == BCA && bcPatternA[localBC]) fillHistograms(timeSinceSOF, localBC); @@ -309,8 +423,20 @@ struct LumiStabilityPP { fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCL && bcPatternL[localBC]) fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCSL && isSuperLeadingBc) - fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNLE && !bcPatternLE[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); } if (iTrigger == FT0Vtx && ctpInputMask.test(2)) { if (iBCCategory == BCA && bcPatternA[localBC]) @@ -323,8 +449,20 @@ struct LumiStabilityPP { fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCL && bcPatternL[localBC]) fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCSL && isSuperLeadingBc) - fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNLE && !bcPatternLE[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); } if (iTrigger == FT0CE && ctpInputMask.test(4)) { if (iBCCategory == BCA && bcPatternA[localBC]) @@ -337,25 +475,66 @@ struct LumiStabilityPP { fillHistograms(timeSinceSOF, localBC); if (iBCCategory == BCL && bcPatternL[localBC]) fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCLE && bcPatternLE[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNL && !bcPatternL[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNLE && !bcPatternLE[localBC] && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBC]) + fillHistograms(timeSinceSOF, localBC); } if (iTrigger == FDD && ctpInputMask.test(15)) { - if (iBCCategory == BCA && bcPatternA[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCB && bcPatternB[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCC && bcPatternC[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCE && bcPatternE[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCL && bcPatternL[localBC]) - fillHistograms(timeSinceSOF, localBC); - if (iBCCategory == BCSL && isSuperLeadingBc) - fillHistograms(timeSinceSOF, localBC); + if (iBCCategory == BCA && bcPatternA[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCB && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCC && bcPatternC[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCE && bcPatternE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCL && bcPatternL[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCLE && bcPatternLE[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCSLFDD && isSuperLeadingBcFDD) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCSLFT0 && isSuperLeadingBcFT0) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCNL && !bcPatternL[localBCFDD] && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCNLE && !bcPatternLE[localBCFDD] && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCNSLFDD && !isSuperLeadingBcFDD && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); + if (iBCCategory == BCNSLFT0 && !isSuperLeadingBcFT0 && bcPatternB[localBCFDD]) + fillHistograms(timeSinceSOF, localBCFDD); } } } } histNBcsVsBcId[runNumber]->Fill(localBC); + if (globalBCLastInspectedBC < globalBC) { + globalBCLastInspectedBC = globalBC; + } else { + globalBCLastInspectedBC = -1; + } + } + // fill histogram for mu + for (int iTrigger{0}; iTrigger < NTriggerAliases; ++iTrigger) { + for (int iBCCategory{0}; iBCCategory < NBCCategories; ++iBCCategory) { + if (doTypeBC->get(0u, iBCCategory)) { + for (int iBcId{0}; iBcId < nBCsPerOrbit; ++iBcId) { + histBcInspectVsBcId[iTrigger][iBCCategory][runNumber]->Fill(iBcId, nBCsPerBcId[iBcId][iBCCategory]); + } + } + } } } }; @@ -363,5 +542,5 @@ struct LumiStabilityPP { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { metadataInfo.initMetadata(cfgc); - return WorkflowSpec{adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGMM/Lumi/Tasks/lumiZdcQa.cxx b/PWGMM/Lumi/Tasks/lumiZdcQa.cxx new file mode 100644 index 00000000000..80f2012a164 --- /dev/null +++ b/PWGMM/Lumi/Tasks/lumiZdcQa.cxx @@ -0,0 +1,165 @@ +// 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 lumiStabilityLightIons.cxx +/// \brief Analysis over BCs to study the luminosity stability along time +/// +/// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt +/// \author Stefanie Mrozinski (stefanie.mrozinski@cern.ch) - Goethe University Frankfurt +/// \author Lorenzo Mattei (lorenzo.mattei@cern.ch) - Turin University + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/MetadataHelper.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +o2::common::core::MetadataHelper metadataInfo; + +namespace o2::aod +{ +namespace myBc_aod +{ +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); +DECLARE_SOA_COLUMN(BCid, bcId, int); +DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); +DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +DECLARE_SOA_COLUMN(AmplitudeZNA, amplitudeZNA, float); +DECLARE_SOA_COLUMN(AmplitudeZNC, amplitudeZNC, float); +} // namespace myBc_aod +DECLARE_SOA_TABLE(MyBCaod, "AOD", "MYBCAOD", + myBc_aod::Timestamp, + myBc_aod::BCid, + myBc_aod::TimeZNA, + myBc_aod::TimeZNC, + myBc_aod::AmplitudeZNA, + myBc_aod::AmplitudeZNC); +} // namespace o2::aod + +using MyBCs = soa::Join; + +struct LumiZdcQa { + Produces BCaod; + + Configurable cfgRequireZDCTriggerForZDCQA{"cfgRequireZDCTriggerForZDCQA", true, "Require ZDC trigger (1ZNC) for filling QA histograms"}; + Configurable cfgRequireTVXTriggerForZDCQA{"cfgRequireTVXTriggerForZDCQA", true, "Require FT0 vertex trigger (MTVX) for filling ZDC QA histograms"}; + Configurable cfgRequireZEDTriggerForZDCQA{"cfgRequireZEDTriggerForZDCQA", true, "Require ZED trigger (1ZNC||1ZNA) for filling QA histograms"}; + + Configurable cfgFillBCao2d{"cfgFillBCao2d", false, "Fill BC ao2d with timestamps and ZDC times"}; + Configurable cfgTstampStartFillingBCao2d{"cfgTstampStartFillingBCao2d", 0, "Minimum value of timestamp for output bc ao2d to be filled"}; + Configurable cfgTstampEndFillingBCao2d{"cfgTstampEndFillingBCao2d", 0, "Maximum value of timestamp for output bc ao2d to be filled"}; + + const int nBCsPerOrbit = 3564; + + HistogramRegistry mHistManager{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + void init(InitContext&) + { + AxisSpec zdcTimeAxis{200, -50., 50.}; + mHistManager.add("ZDCQA/BCHasZDC", "Does the BC have ZDC?;BC has ZDC;Has ZNC according to CTP;#bf{#it{N}_{BC}}", HistType::kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); + mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetYaxis()->SetBinLabel(1, "No CTP trigger"); + mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetYaxis()->SetBinLabel(2, "CTP triggered"); + mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetXaxis()->SetBinLabel(1, "No found ZDC"); + mHistManager.get(HIST("ZDCQA/BCHasZDC")).get()->GetXaxis()->SetBinLabel(2, "Good ZDC"); + mHistManager.add("ZDCQA/ZNCTimeVsEnergy", "ZDC properties in BCs with found ZDC;Energy;#bf{ZNC arrival time (ns)};#bf{#it{N}_{BC}}", HistType::kTH2D, {{1501, -10, 1.5E4}, zdcTimeAxis}); + mHistManager.add("ZDCQA/ZDCTimes", "Correlation between ZNA and ZNC timing;#bf{ZNC arrival time (ns)};#bf{ZNA arrival time (ns)}", HistType::kTH2D, {zdcTimeAxis, zdcTimeAxis}); + mHistManager.add("ZDCQA/ZNATime", "Time of the ZNA signal;#bf{ZNA arrival time (ns)};#bf{#it{N}_{BC}}", HistType::kTH1D, {zdcTimeAxis}); + mHistManager.add("ZDCQA/ZNCTime", "Time of the ZNC signal;#bf{ZNC arrival time (ns)};#bf{#it{N}_{BC}}", HistType::kTH1D, {zdcTimeAxis}); + } + + void process(MyBCs const& bcs, aod::Zdcs const&) + { + const int maxTimeZDC = 50; + const float dummyZDCTime = 42.f; + + for (const auto& bc : bcs) { + std::bitset<64> ctpInputMask(bc.inputMask()); + + if (cfgRequireTVXTriggerForZDCQA && !(ctpInputMask.test(2))) { + continue; + } + if (cfgRequireZDCTriggerForZDCQA && !(ctpInputMask.test(25))) { + continue; + } + if (cfgRequireZEDTriggerForZDCQA && !(ctpInputMask.test(24))) { + continue; + } + + bool zdcHit = !bc.has_zdc() ? 0 : ((bc.zdc().energyCommonZNC() > -1 && std::abs(bc.zdc().timeZNC()) < 1E5) ? 1 : 0); + mHistManager.fill(HIST("ZDCQA/BCHasZDC"), zdcHit, ctpInputMask.test(25) ? 1 : 0); + + if (!bc.has_zdc()) { + continue; + } + + mHistManager.fill(HIST("ZDCQA/ZNCTimeVsEnergy"), + bc.zdc().energyCommonZNC() > -1 ? bc.zdc().energyCommonZNC() : -1, + std::abs(bc.zdc().timeZNC()) < maxTimeZDC ? bc.zdc().timeZNC() : dummyZDCTime); + + float timeZNA = bc.zdc().timeZNA(); + float timeZNC = bc.zdc().timeZNC(); + + if (std::abs(timeZNA) > maxTimeZDC) { + timeZNA = dummyZDCTime; + mHistManager.fill(HIST("ZDCQA/ZNCTime"), timeZNC); + } + if (std::abs(timeZNC) > maxTimeZDC) { + timeZNC = dummyZDCTime; + if (timeZNA != dummyZDCTime) { + mHistManager.fill(HIST("ZDCQA/ZNATime"), timeZNA); + } + } + + mHistManager.fill(HIST("ZDCQA/ZDCTimes"), timeZNA, timeZNC); + + uint64_t timestamp = bc.timestamp(); + int64_t globalBC = bc.globalBC(); + int localBC = globalBC % nBCsPerOrbit; + float amplitudeZNA = bc.zdc().amplitudeZNA(); + float amplitudeZNC = bc.zdc().amplitudeZNC(); + + if (cfgFillBCao2d && timestamp >= cfgTstampStartFillingBCao2d && timestamp <= cfgTstampEndFillingBCao2d) { + BCaod(timestamp, localBC, timeZNA, timeZNC, amplitudeZNA, amplitudeZNC); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + metadataInfo.initMetadata(cfgc); + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGMM/Lumi/macros/merger.C b/PWGMM/Lumi/macros/merger.C index f3759a277ef..1ad2cd5f920 100644 --- a/PWGMM/Lumi/macros/merger.C +++ b/PWGMM/Lumi/macros/merger.C @@ -13,6 +13,15 @@ // merge all trees into one tree to construct event by event log-likelihood // function. +#include +#include +#include +#include +#include +#include + +#include + void merger() { TFile* fin = new TFile("../data/PbPb_NF/AnalysisResults_trees.root", "read"); diff --git a/PWGMM/Lumi/macros/non_fac.C b/PWGMM/Lumi/macros/non_fac.C index 34022f82f8b..ea858e409f0 100644 --- a/PWGMM/Lumi/macros/non_fac.C +++ b/PWGMM/Lumi/macros/non_fac.C @@ -12,6 +12,21 @@ /// \since November 2021 // code for fitting the luminous region for each step +#include +#include +#include +#include +#include // IWYU pragma: keep (do not replace with TMatrixDfwd.h) +#include +#include +#include +#include + +#include + +#include +#include + TFile* fin = new TFile("mergedOutput.root", "read"); TTree* tin; @@ -193,7 +208,7 @@ void non_fac() FunMinuit[i]->mnexcm("MIGRAD", arglist, 2, ierflg); for (int p = 0; p < 10; p++) { FunMinuit[i]->GetParameter(p, FitRes_cntl[i][p], FitRes_stat[i][p]); - cout << FitRes_cntl[i][p] << ", " << FitRes_stat[i][p] << endl; + std::cout << FitRes_cntl[i][p] << ", " << FitRes_stat[i][p] << std::endl; } hResults[i] = new TH1D(Form("hResults%d", i), "", 12, 0, 12); for (int p = 0; p < 10; p++) { diff --git a/PWGMM/Mult/Core/include/Axes.h b/PWGMM/Mult/Core/include/Axes.h index c215a8ba357..9528e5a84ac 100644 --- a/PWGMM/Mult/Core/include/Axes.h +++ b/PWGMM/Mult/Core/include/Axes.h @@ -11,35 +11,39 @@ #ifndef PWGMM_MULT_CORE_INCLUDE_AXES_H_ #define PWGMM_MULT_CORE_INCLUDE_AXES_H_ -#include "Framework/HistogramSpec.h" -#include "CommonConstants/MathConstants.h" + +#include +#include + +#include +#include +#include namespace pwgmm::mult { -using namespace o2::framework; static constexpr std::string_view ptAxisName = "p_{T} (GeV/c)"; // common axis definitions -AxisSpec ZAxis = {301, -30.1, 30.1, "Z_{vtx} (cm)"}; // Z vertex in cm -AxisSpec DeltaZAxis = {61, -6.1, 6.1, "#Delta Z (cm)"}; // Z vertex difference in cm -AxisSpec DCAAxis = {601, -3.01, 3.01}; // DCA in cm -AxisSpec EtaAxis = {22, -2.2, 2.2, "#eta"}; // Eta +o2::framework::AxisSpec ZAxis = {301, -30.1, 30.1, "Z_{vtx} (cm)"}; // Z vertex in cm +o2::framework::AxisSpec DeltaZAxis = {61, -6.1, 6.1, "#Delta Z (cm)"}; // Z vertex difference in cm +o2::framework::AxisSpec DCAAxis = {601, -3.01, 3.01}; // DCA in cm +o2::framework::AxisSpec EtaAxis = {22, -2.2, 2.2, "#eta"}; // Eta -AxisSpec PhiAxis = {629, 0, o2::constants::math::TwoPI, "#phi"}; // Phi (azimuthal angle) -AxisSpec PtAxis = {2401, -0.005, 24.005, ptAxisName.data()}; // Large fine-binned Pt +o2::framework::AxisSpec PhiAxis = {629, 0, o2::constants::math::TwoPI, "#phi"}; // Phi (azimuthal angle) +o2::framework::AxisSpec PtAxis = {2401, -0.005, 24.005, ptAxisName.data()}; // Large fine-binned Pt // Large wide-binned Pt (for efficiency) -AxisSpec PtAxisEff = {{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, 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, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, - ptAxisName.data()}; -AxisSpec PtAxis_wide = {1041, -0.05, 104.05, ptAxisName.data()}; // Smaller wider-binned Pt -AxisSpec FT0CAxis = {1001, -0.5, 1000.5, "FT0C amplitude (arb. units)"}; // FT0C amplitudes -AxisSpec FT0AAxis = {3001, -0.5, 3000.5, "FT0A amplitude (arb. units)"}; // FT0A amplitudes -AxisSpec FDAAxis = {3001, -0.5, 3000.5, "FDA amplitude (arb. units)"}; // FDD amplitudes -AxisSpec FDCAxis = {3001, -0.5, 3000.5, "FDC amplitude (arb. units)"}; // FDD amplitudes -AxisSpec RapidityAxis = {102, -10.2, 10.2, "Y"}; // Rapidity -AxisSpec ScaleAxis = {121, -0.5, 120.5, "Event scale (GeV)"}; // Event scale -AxisSpec MPIAxis = {51, -0.5, 50.5, "N_{MPI}"}; // N_{MPI} -AxisSpec ProcAxis = {21, 89.5, 110.5}; // Process flag -AxisSpec SpeciesAxis = {5, 0.5, 5.5}; // Particle species +o2::framework::AxisSpec PtAxisEff = {{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, 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, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}, + ptAxisName.data()}; +o2::framework::AxisSpec PtAxis_wide = {1041, -0.05, 104.05, ptAxisName.data()}; // Smaller wider-binned Pt +o2::framework::AxisSpec FT0CAxis = {1001, -0.5, 1000.5, "FT0C amplitude (arb. units)"}; // FT0C amplitudes +o2::framework::AxisSpec FT0AAxis = {3001, -0.5, 3000.5, "FT0A amplitude (arb. units)"}; // FT0A amplitudes +o2::framework::AxisSpec FDAAxis = {3001, -0.5, 3000.5, "FDA amplitude (arb. units)"}; // FDD amplitudes +o2::framework::AxisSpec FDCAxis = {3001, -0.5, 3000.5, "FDC amplitude (arb. units)"}; // FDD amplitudes +o2::framework::AxisSpec RapidityAxis = {102, -10.2, 10.2, "Y"}; // Rapidity +o2::framework::AxisSpec ScaleAxis = {121, -0.5, 120.5, "Event scale (GeV)"}; // Event scale +o2::framework::AxisSpec MPIAxis = {51, -0.5, 50.5, "N_{MPI}"}; // N_{MPI} +o2::framework::AxisSpec ProcAxis = {21, 89.5, 110.5}; // Process flag +o2::framework::AxisSpec SpeciesAxis = {5, 0.5, 5.5}; // Particle species // event selection/efficiency binning enum struct EvSelBins : int { @@ -78,4 +82,5 @@ std::array(EvEffBins::kSelectedPVgt0) + 1> "Selected INEL>0", "Selected INEL>0 (PV)"}; } // namespace pwgmm::mult + #endif // PWGMM_MULT_CORE_INCLUDE_AXES_H_ diff --git a/PWGMM/Mult/Core/include/Histograms.h b/PWGMM/Mult/Core/include/Histograms.h index 2b41c9ecefe..17828d1edcb 100644 --- a/PWGMM/Mult/Core/include/Histograms.h +++ b/PWGMM/Mult/Core/include/Histograms.h @@ -11,7 +11,8 @@ #ifndef PWGMM_MULT_CORE_INCLUDE_HISTOGRAMS_H_ #define PWGMM_MULT_CORE_INCLUDE_HISTOGRAMS_H_ -#include "TPDGCode.h" +#include + #include #include diff --git a/PWGMM/Mult/Core/include/Selections.h b/PWGMM/Mult/Core/include/Selections.h index 2532da6ccce..8240410c462 100644 --- a/PWGMM/Mult/Core/include/Selections.h +++ b/PWGMM/Mult/Core/include/Selections.h @@ -11,30 +11,30 @@ #ifndef PWGMM_MULT_CORE_INCLUDE_SELECTIONS_H_ #define PWGMM_MULT_CORE_INCLUDE_SELECTIONS_H_ + #include "Common/DataModel/TrackSelectionTables.h" namespace pwgmm::mult { -using namespace o2::aod::track; // default quality criteria for tracks with ITS contribution -static constexpr TrackSelectionFlags::flagtype trackSelectionITS = - TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | - TrackSelectionFlags::kITSHits; +static constexpr o2::aod::track::TrackSelectionFlags::flagtype trackSelectionITS = + o2::aod::track::TrackSelectionFlags::kITSNCls | o2::aod::track::TrackSelectionFlags::kITSChi2NDF | + o2::aod::track::TrackSelectionFlags::kITSHits; // default quality criteria for tracks with TPC contribution -static constexpr TrackSelectionFlags::flagtype trackSelectionTPC = - TrackSelectionFlags::kTPCNCls | - TrackSelectionFlags::kTPCCrossedRowsOverNCls | - TrackSelectionFlags::kTPCChi2NDF; +static constexpr o2::aod::track::TrackSelectionFlags::flagtype trackSelectionTPC = + o2::aod::track::TrackSelectionFlags::kTPCNCls | + o2::aod::track::TrackSelectionFlags::kTPCCrossedRowsOverNCls | + o2::aod::track::TrackSelectionFlags::kTPCChi2NDF; // default standard DCA cuts -static constexpr TrackSelectionFlags::flagtype trackSelectionDCA = - TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy; +static constexpr o2::aod::track::TrackSelectionFlags::flagtype trackSelectionDCA = + o2::aod::track::TrackSelectionFlags::kDCAz | o2::aod::track::TrackSelectionFlags::kDCAxy; // default standard transversal-only DCA cuts -static constexpr TrackSelectionFlags::flagtype trackSelectionDCAXYonly = - TrackSelectionFlags::kDCAxy; +static constexpr o2::aod::track::TrackSelectionFlags::flagtype trackSelectionDCAXYonly = + o2::aod::track::TrackSelectionFlags::kDCAxy; } // namespace pwgmm::mult #endif // PWGMM_MULT_CORE_INCLUDE_SELECTIONS_H_ diff --git a/PWGMM/Mult/DataModel/Gencentralities.h b/PWGMM/Mult/DataModel/Gencentralities.h index 112072fa2c8..fb7de9da0e8 100644 --- a/PWGMM/Mult/DataModel/Gencentralities.h +++ b/PWGMM/Mult/DataModel/Gencentralities.h @@ -12,7 +12,7 @@ #ifndef PWGMM_MULT_DATAMODEL_GENCENTRALITIES_H_ #define PWGMM_MULT_DATAMODEL_GENCENTRALITIES_H_ -#include "Framework/AnalysisDataModel.h" +#include namespace o2::aod { namespace gencents diff --git a/PWGMM/Mult/DataModel/Index.h b/PWGMM/Mult/DataModel/Index.h index b3c71f534a2..ba4c29ef606 100644 --- a/PWGMM/Mult/DataModel/Index.h +++ b/PWGMM/Mult/DataModel/Index.h @@ -9,10 +9,11 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2_ANALYSIS_INDEX_H_ -#define O2_ANALYSIS_INDEX_H_ +#ifndef PWGMM_MULT_DATAMODEL_INDEX_H_ +#define PWGMM_MULT_DATAMODEL_INDEX_H_ + +#include -#include "Framework/AnalysisDataModel.h" namespace o2::aod { namespace idx @@ -23,4 +24,5 @@ DECLARE_SOA_ARRAY_INDEX_COLUMN(MFTTrack, mfttracks); DECLARE_SOA_TABLE(ParticlesToTracks, "AOD", "P2T", idx::TrackIds); DECLARE_SOA_TABLE(ParticlesToMftTracks, "AOD", "P2MFTT", idx::MFTTrackIds); } // namespace o2::aod -#endif // O2_ANALYSIS_INDEX_H_ + +#endif // PWGMM_MULT_DATAMODEL_INDEX_H_ diff --git a/PWGMM/Mult/DataModel/ReducedTables.h b/PWGMM/Mult/DataModel/ReducedTables.h index fbdd68b89db..60eb29ac659 100644 --- a/PWGMM/Mult/DataModel/ReducedTables.h +++ b/PWGMM/Mult/DataModel/ReducedTables.h @@ -11,13 +11,14 @@ #ifndef PWGMM_MULT_DATAMODEL_REDUCEDTABLES_H_ #define PWGMM_MULT_DATAMODEL_REDUCEDTABLES_H_ -#include - -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" +#include + +#include + namespace o2::aod { diff --git a/PWGMM/Mult/DataModel/bestCollisionTable.h b/PWGMM/Mult/DataModel/bestCollisionTable.h index 0b4ee5440bc..27b524b5b89 100644 --- a/PWGMM/Mult/DataModel/bestCollisionTable.h +++ b/PWGMM/Mult/DataModel/bestCollisionTable.h @@ -19,7 +19,9 @@ #ifndef PWGMM_MULT_DATAMODEL_BESTCOLLISIONTABLE_H_ #define PWGMM_MULT_DATAMODEL_BESTCOLLISIONTABLE_H_ -#include "Framework/AnalysisDataModel.h" +#include + +#include namespace o2::aod { diff --git a/PWGMM/Mult/TableProducer/ambiguousTrackPropagation.cxx b/PWGMM/Mult/TableProducer/ambiguousTrackPropagation.cxx index 69c0845e0e0..af3a895eec3 100644 --- a/PWGMM/Mult/TableProducer/ambiguousTrackPropagation.cxx +++ b/PWGMM/Mult/TableProducer/ambiguousTrackPropagation.cxx @@ -20,30 +20,40 @@ #include "bestCollisionTable.h" +#include "Common/Core/fwdtrackUtilities.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/GeomConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Math/MatrixFunctions.h" -#include "Math/SMatrix.h" -#include "TGeoGlobalMagField.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include #include #include -using SMatrix55 = ROOT::Math::SMatrix>; -using SMatrix5 = ROOT::Math::SVector; - // This is a special version of the propagation task chosing the closest vertex // among the compatible, which is defined by track-to-collision-associator @@ -53,20 +63,19 @@ using namespace o2::aod::track; struct AmbiguousTrackPropagation { Produces fwdtracksBestCollisions; + Produces fwdtracksBestCollExtra; Produces fwdtracksBestCollisions3d; Produces fwdtracksBestCollisions3dExtra; - Produces fwdtracksBestCollExtra; Produces tracksReassignedCore; Produces tracksReassignedExtra; Service ccdb; int runNumber = -1; float bZ = 0; // Magnetic field for MFT - static constexpr double kCenterMFT[3] = {0, 0, -61.4}; // Field at center of MFT - - o2::base::Propagator::MatCorrType matCorr = - o2::base::Propagator::MatCorrType::USEMatCorrNONE; + static constexpr double CcenterMFT[3] = {0, 0, -61.4}; // Field at center of MFT + float mZShift = 0; // z-vertex shift + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; o2::parameters::GRPMagField* grpmag = nullptr; Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -77,6 +86,11 @@ struct AmbiguousTrackPropagation { Configurable produceExtra{"produceExtra", false, "Produce table with refitted track parameters"}; Configurable produceHistos{"produceHistos", false, "Produce control histograms"}; Configurable removeTrivialAssoc{"removeTrivialAssoc", false, "Skip trivial associations"}; + Configurable cfgDCAtype{"cfgDCAtype", 2, "DCA coordinate type [0: DCA-X, 1: DCA-Y, 2: DCA-XY]"}; + + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift from CCDB"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0.0f, "manual z-shift for propagation of global muon to PV"}; ConfigurableAxis binsDCAxy{"binsDCAxy", {200, -1., 1.}, ""}; ConfigurableAxis binsDCAz{"binsDCAz", {200, -1., 1.}, ""}; @@ -102,6 +116,8 @@ struct AmbiguousTrackPropagation { if (produceHistos) { if (doprocessMFT || doprocessMFTReassoc || doprocessMFTReassoc3D) { + registry.add({"DeltaX", " ; #Delta#it{x}", {HistType::kTH1F, {{201, -10.1, 10.1}}}}); + registry.add({"DeltaY", " ; #Delta#it{y}", {HistType::kTH1F, {{201, -10.1, 10.1}}}}); registry.add({"DeltaZ", " ; #Delta#it{z}", {HistType::kTH1F, {{201, -10.1, 10.1}}}}); registry.add({"TracksDCAXY", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaXYAxis}}}); registry.add({"ReassignedDCAXY", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaXYAxis}}}); @@ -114,6 +130,8 @@ struct AmbiguousTrackPropagation { registry.add({"TracksFirstDCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcaZAxis}}}); registry.add({"TracksDCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcaZAxis}}}); registry.add({"ReassignedDCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcaZAxis}}}); + registry.add({"AssignedDCAXY", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaXYAxis}}}); + registry.add({"AssignedDCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcaZAxis}}}); registry.add({"TracksOrigDCAZ", " ; DCA_{Z} (wrt orig coll) (cm)", {HistType::kTH1F, {dcaZAxis}}}); } } @@ -144,16 +162,30 @@ struct AmbiguousTrackPropagation { if (doprocessMFT || doprocessMFTReassoc || doprocessMFTReassoc3D) { o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); - bZ = field->getBz(kCenterMFT); + bZ = field->getBz(CcenterMFT); LOG(info) << "The field at the center of the MFT is bZ = " << bZ; } + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } } - static constexpr TrackSelectionFlags::flagtype kTrackSelectionITS = + static constexpr TrackSelectionFlags::flagtype CtrackSelectionITS = TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | TrackSelectionFlags::kITSHits; - static constexpr TrackSelectionFlags::flagtype kTrackSelectionTPC = + static constexpr TrackSelectionFlags::flagtype CtrackSelectionTPC = TrackSelectionFlags::kTPCNCls | TrackSelectionFlags::kTPCCrossedRowsOverNCls | TrackSelectionFlags::kTPCChi2NDF; @@ -180,11 +212,11 @@ struct AmbiguousTrackPropagation { bestDCA[1] = dcaInfo[1]; auto bestCol = track.has_collision() ? track.collisionId() : -1; - if ((track.trackCutFlag() & kTrackSelectionITS) != kTrackSelectionITS) { + if ((track.trackCutFlag() & CtrackSelectionITS) != CtrackSelectionITS) { continue; } if ((track.detectorMap() & (uint8_t)o2::aod::track::TPC) == (uint8_t)o2::aod::track::TPC) { - if ((track.trackCutFlag() & kTrackSelectionTPC) != kTrackSelectionTPC) { + if ((track.trackCutFlag() & CtrackSelectionTPC) != CtrackSelectionTPC) { continue; } } @@ -266,10 +298,7 @@ struct AmbiguousTrackPropagation { auto track = atrack.mfttrack(); auto bestCol = track.has_collision() ? track.collisionId() : -1; - 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()}; + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, mZShift); int degree = 0; // degree of ambiguity of the track @@ -352,7 +381,6 @@ struct AmbiguousTrackPropagation { auto bestCol = track.has_collision() ? track.collisionId() : -1; // auto ids = track.compatibleCollIds(); - // if (ids.empty() || (ids.size() == 1 && bestCol == ids[0])) // { // continue; @@ -360,10 +388,7 @@ struct AmbiguousTrackPropagation { auto compatibleColls = track.compatibleColl(); - 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()}; + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, mZShift); for (auto const& collision : compatibleColls) { @@ -453,15 +478,19 @@ struct AmbiguousTrackPropagation { auto compatibleColls = track.compatibleColl(); - 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()}; + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, mZShift); for (auto const& collision : compatibleColls) { trackPar.propagateToDCAhelix(bZ, {collision.posX(), collision.posY(), collision.posZ()}, dcaInfOrig); - dcaInfo[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + + if (cfgDCAtype == 0) { + dcaInfo[0] = dcaInfOrig[0]; + } else if (cfgDCAtype == 1) { + dcaInfo[0] = dcaInfOrig[1]; + } else if (cfgDCAtype == 2) { + dcaInfo[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + } dcaInfo[1] = dcaInfOrig[2]; if ((std::abs(dcaInfo[0]) < std::abs(bestDCA[0])) && (std::abs(dcaInfo[1]) < std::abs(bestDCA[1]))) { @@ -470,8 +499,11 @@ struct AmbiguousTrackPropagation { bestDCA[1] = dcaInfo[1]; bestTrackPar = trackPar; } + if ((track.collisionId() != collision.globalIndex()) && produceHistos) { registry.fill(HIST("DeltaZ"), track.collision().posZ() - collision.posZ()); // deltaZ between the 1st coll zvtx and the other compatible ones + registry.fill(HIST("DeltaX"), track.collision().posX() - collision.posX()); + registry.fill(HIST("DeltaY"), track.collision().posY() - collision.posY()); registry.fill(HIST("TracksFirstDCAXY"), dcaInfo[0]); registry.fill(HIST("TracksFirstDCAZ"), dcaInfo[1]); } @@ -479,12 +511,15 @@ struct AmbiguousTrackPropagation { registry.fill(HIST("TracksDCAXY"), dcaInfo[0]); registry.fill(HIST("TracksDCAZ"), dcaInfo[1]); } - if ((collision.globalIndex() == track.collisionId()) && produceHistos) { registry.fill(HIST("TracksOrigDCAXY"), dcaInfo[0]); registry.fill(HIST("TracksOrigDCAZ"), dcaInfo[1]); } } + if ((bestCol == track.collisionId()) && produceHistos) { + registry.fill(HIST("AssignedDCAXY"), bestDCA[0]); + registry.fill(HIST("AssignedDCAZ"), bestDCA[1]); + } if ((bestCol != track.collisionId()) && produceHistos) { // reassigned registry.fill(HIST("ReassignedDCAXY"), bestDCA[0]); @@ -500,7 +535,9 @@ struct AmbiguousTrackPropagation { } fwdtracksBestCollisions3d(track.globalIndex(), compatibleColls.size(), bestCol, bestDCA[0], bestDCA[1]); + // LOGP(info, "track {}: {} {} {} {}", track.globalIndex(), compatibleColls.size(), bestCol, bestDCA[0], bestDCA[1]); if (produceExtra) { + // LOGP(info, "track {}: {} {} {} {} {}", track.globalIndex(), bestTrackPar.getX(), bestTrackPar.getY(), bestTrackPar.getZ(), bestTrackPar.getTgl(), bestTrackPar.getInvQPt()); fwdtracksBestCollisions3dExtra(bestTrackPar.getX(), bestTrackPar.getY(), bestTrackPar.getZ(), bestTrackPar.getTgl(), bestTrackPar.getInvQPt(), bestTrackPar.getPt(), bestTrackPar.getP(), bestTrackPar.getEta(), bestTrackPar.getPhi()); diff --git a/PWGMM/Mult/TableProducer/particles2tracks.cxx b/PWGMM/Mult/TableProducer/particles2tracks.cxx index 6b7e7db6a17..662bd34dd69 100644 --- a/PWGMM/Mult/TableProducer/particles2tracks.cxx +++ b/PWGMM/Mult/TableProducer/particles2tracks.cxx @@ -16,12 +16,17 @@ /// \brief A task to create a reverse index from McParticles to Tracks /// -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" - #include "Index.h" +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/TableProducer/percentiles.cxx b/PWGMM/Mult/TableProducer/percentiles.cxx index c11fca858f8..d34802ab2ae 100644 --- a/PWGMM/Mult/TableProducer/percentiles.cxx +++ b/PWGMM/Mult/TableProducer/percentiles.cxx @@ -8,19 +8,30 @@ // 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 "Gencentralities.h" #include "Selections.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include #include +#include #include #include -#include -#include "Common/DataModel/Centrality.h" -#include +#include +#include +#include +#include #include -#include #include -#include "Gencentralities.h" +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/TableProducer/reducer.cxx b/PWGMM/Mult/TableProducer/reducer.cxx index de9d516703b..6d290692e55 100644 --- a/PWGMM/Mult/TableProducer/reducer.cxx +++ b/PWGMM/Mult/TableProducer/reducer.cxx @@ -9,14 +9,34 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" - -#include "Selections.h" #include "ReducedTables.h" +#include "Selections.h" -#include "Framework/runDataProcessing.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/TableProducer/reducerPostprocess.cxx b/PWGMM/Mult/TableProducer/reducerPostprocess.cxx index d05f5534eb0..29bfecf43e4 100644 --- a/PWGMM/Mult/TableProducer/reducerPostprocess.cxx +++ b/PWGMM/Mult/TableProducer/reducerPostprocess.cxx @@ -9,11 +9,14 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/AnalysisTask.h" - #include "ReducedTables.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/Tasks/CMakeLists.txt b/PWGMM/Mult/Tasks/CMakeLists.txt index aae28c5eef1..b9e85153285 100644 --- a/PWGMM/Mult/Tasks/CMakeLists.txt +++ b/PWGMM/Mult/Tasks/CMakeLists.txt @@ -39,6 +39,12 @@ o2physics_add_dpl_workflow(dndeta-mft-pbpb PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(mft-reassociation-validation + SOURCES mftReassociationValidation.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(flatenicity-fv0 SOURCES flatenicityFV0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGMM/Mult/Tasks/assessment-mft.cxx b/PWGMM/Mult/Tasks/assessment-mft.cxx index 70304229e1e..735e95e9a6c 100644 --- a/PWGMM/Mult/Tasks/assessment-mft.cxx +++ b/PWGMM/Mult/Tasks/assessment-mft.cxx @@ -15,11 +15,15 @@ // \brief This code loops over MFT tracks and fills basic histograms // close to the QC ones -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include -#include "MathUtils/Utils.h" -#include "CommonConstants/LHCConstants.h" +#include using namespace o2; using namespace o2::framework; @@ -35,7 +39,7 @@ struct AssessmentMFT { {"TracksChi2", "; #chi^{2}; tracks", {HistType::kTH1F, {{600, 0, 20}}}}, // {"TracksNclustersEta", "; nClusters; #eta; tracks", {HistType::kTH2F, {{7, 4, 10}, {100, -8, 8}}}}, // {"TracksTime", "; time; #count", {HistType::kTH1D, {{6000000, 0, 60000}}}}, // - } // + } // }; void process(aod::Collisions::iterator const& collision, aod::MFTTracks const& tracks, aod::BCs const& bcs) diff --git a/PWGMM/Mult/Tasks/dndeta-hi.cxx b/PWGMM/Mult/Tasks/dndeta-hi.cxx index d479a3138e3..630922994cb 100644 --- a/PWGMM/Mult/Tasks/dndeta-hi.cxx +++ b/PWGMM/Mult/Tasks/dndeta-hi.cxx @@ -10,47 +10,41 @@ // or submit itself to any jurisdiction. #include "Index.h" -#include "bestCollisionTable.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RuntimeError.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" -#include "ReconstructionDataFormats/Track.h" - -#include -#include -#include -#include -#include -#include - -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include #include +#include #include -#include +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -58,7 +52,6 @@ using namespace o2::framework::expressions; using namespace o2::aod::track; using namespace o2::aod; -using namespace o2::analysis; using BCsRun3 = soa::Join; using MyCollisions = soa::Join; diff --git a/PWGMM/Mult/Tasks/dndeta-mft.cxx b/PWGMM/Mult/Tasks/dndeta-mft.cxx index f70cc1d638a..e7ff487021d 100644 --- a/PWGMM/Mult/Tasks/dndeta-mft.cxx +++ b/PWGMM/Mult/Tasks/dndeta-mft.cxx @@ -15,27 +15,34 @@ // \brief This code loops over MFT tracks and collisions and fills histograms // useful to compute dNdeta -#include -#include - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RuntimeError.h" -#include "Framework/runDataProcessing.h" +#include "bestCollisionTable.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "MathUtils/Utils.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" -#include "TDatabasePDG.h" -#include "bestCollisionTable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -108,7 +115,7 @@ struct PseudorapidityDensityMFT { {"EventSelection", ";status;events", {HistType::kTH1F, {{7, 0.5, 7.5}}}}, // - } // + } // }; void init(InitContext&) diff --git a/PWGMM/Mult/Tasks/dndeta.cxx b/PWGMM/Mult/Tasks/dndeta.cxx index 220bdbdebb8..df1ebc63cd8 100644 --- a/PWGMM/Mult/Tasks/dndeta.cxx +++ b/PWGMM/Mult/Tasks/dndeta.cxx @@ -9,26 +9,40 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include -#include - +#include "Axes.h" +#include "Functions.h" #include "Gencentralities.h" +#include "Histograms.h" #include "Index.h" +#include "Selections.h" #include "bestCollisionTable.h" -#include "Axes.h" -#include "Functions.h" -#include "Selections.h" -#include "Histograms.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod::track; diff --git a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx index c8a26100cbd..97425d586c6 100644 --- a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx +++ b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx @@ -19,36 +19,63 @@ #include "Index.h" #include "bestCollisionTable.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/fwdtrackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RuntimeError.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" - -#include "TMCProcess.h" -#include "TPDGCode.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include +#include #include #include +#include +#include +#include +#include #include #include +#include #include #include +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix5 = ROOT::Math::SVector; + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -59,9 +86,15 @@ using namespace o2::constants::math; using namespace pwgmm::mult; using namespace o2::aod::rctsel; -auto static constexpr kMinCharge = 3.f; -auto static constexpr kIntZero = 0; -auto static constexpr kZero = 0.f; +auto static constexpr CminCharge = 3.f; +auto static constexpr CintZero = 0; +auto static constexpr Czero = 0.f; +auto static constexpr Cninety = 90.f; +auto static constexpr ConeHeighty = 180.f; +auto static constexpr CminAccFT0A = 3.5f; +auto static constexpr CmaxAccFT0A = 4.9f; +auto static constexpr CminAccFT0C = -3.3f; +auto static constexpr CmaxAccFT0C = -2.1f; enum TrkSel { trkSelAll, @@ -92,12 +125,17 @@ enum AmbTrkType { nAmbTrkType }; +std::unordered_map mapVtxXrec; +std::unordered_map mapVtxYrec; +std::unordered_map mapVtxZrec; +std::unordered_map mapMcCollIdPerRecColl; + struct DndetaMFTPbPb { SliceCache cache; std::array, 4> hCollAssoc; std::array, 4> hReAssoc; - std::array, 6> hDCAMc; + std::array, 8> hDCAMc; enum OccupancyEst { TrkITS = 1, Ft0C }; @@ -113,13 +151,25 @@ struct DndetaMFTPbPb { false, true}; - Configurable cfgDoIR{"cfgDoIR", false, "Flag to retrieve Interaction rate from CCDB"}; - Configurable cfgUseIRCut{"cfgUseIRCut", false, "Flag to cut on IR rate"}; - Configurable cfgIRCrashOnNull{"cfgIRCrashOnNull", false, "Flag to avoid CTP RateFetcher crash"}; - Configurable cfgIRSource{"cfgIRSource", "ZNC hadronic", "Estimator of the interaction rate (Pb-Pb: ZNC hadronic)"}; - Configurable cfgUseTrackSel{"cfgUseTrackSel", false, "Flag to apply track selection"}; - Configurable cfgUseParticleSel{"cfgUseParticleSel", false, "Flag to apply particle selection"}; - Configurable cfgRemoveReassigned{"cfgRemoveReassigned", false, "Remove reassgined tracks"}; + HistogramRegistry registryAlign{"registryAlign", {}}; + std::array mftQuadrant = {"Q0", "Q1", "Q2", "Q3"}; + std::array, 3>, 4>, 2> hAlignment; + + struct : ConfigurableGroup { + Configurable cfgDoIR{"cfgDoIR", false, "Flag to retrieve Interaction rate from CCDB"}; + Configurable cfgUseIRCut{"cfgUseIRCut", false, "Flag to cut on IR rate"}; + Configurable cfgIRCrashOnNull{"cfgIRCrashOnNull", false, "Flag to avoid CTP RateFetcher crash"}; + Configurable cfgIRSource{"cfgIRSource", "ZNC hadronic", "Estimator of the interaction rate (Pb-Pb: ZNC hadronic)"}; + Configurable cfgUseTrackSel{"cfgUseTrackSel", false, "Flag to apply track selection"}; + Configurable cfgUseParticleSel{"cfgUseParticleSel", false, "Flag to apply particle selection"}; + Configurable cfgRemoveTrivialAssoc{"cfgRemoveTrivialAssoc", false, "Skip trivial associations"}; + Configurable cfgRemoveReassigned{"cfgRemoveReassigned", false, "Remove reassgined tracks"}; + Configurable cfgUseTrackParExtra{"cfgUseTrackParExtra", false, "Use table with refitted track parameters"}; + Configurable cfgUseInelgt0{"cfgUseInelgt0", false, "Use INEL > 0 condition"}; + Configurable cfgUseInelgt0wMFT{"cfgUseInelgt0wMFT", false, "Use INEL > 0 condition with MFT acceptance"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable cfgDCAtype{"cfgDCAtype", 2, "DCA coordinate type [0: DCA-X, 1: DCA-Y, 2: DCA-XY]"}; + } gConf; struct : ConfigurableGroup { ConfigurableAxis interactionRateBins{"interactionRateBins", {500, 0, 50}, "Binning for the interaction rate (kHz)"}; @@ -140,6 +190,8 @@ struct DndetaMFTPbPb { ConfigurableAxis etaBins{"etaBins", {20, -4., -2.}, "#eta binning"}; ConfigurableAxis chiSqPerNclBins{"chiSqPerNclBins", {100, 0, 100}, "#chi^{2} binning"}; ConfigurableAxis nClBins{"nClBins", {10, 0.5, 10.5}, "number of clusters binning"}; + ConfigurableAxis tanLambdaBins{"tanLambdaBins", {100, -25, 0}, "binning for tan(lambda)"}; + ConfigurableAxis invQPtBins{"invQPtBins", {200, -10, 10}, "binning for q/p_{T}"}; } binOpt; struct : ConfigurableGroup { @@ -171,13 +223,14 @@ struct DndetaMFTPbPb { Configurable minZvtx{"minZvtx", -20.0f, "minimum cut on z-vtx (cm)"}; Configurable useZDiffCut{"useZDiffCut", false, "use Zvtx reco-mc diff. cut"}; Configurable maxZvtxDiff{"maxZvtxDiff", 1.0f, "max allowed Z vtx difference for reconstruced collisions (cm)"}; + Configurable useZVtxCutMC{"useZVtxCutMC", false, "use Zvtx cut in MC"}; 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 requireRejectSameBunchPileup{"requireRejectSameBunchPileup", true, "reject collisions in case of pileup with another collision in the same foundBC"}; - Configurable requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", true, " requireNoCollInTimeRangeStrict"}; - Configurable requireNoCollInRofStrict{"requireNoCollInRofStrict", false, "requireNoCollInRofStrict"}; + Configurable requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", false, " requireNoCollInTimeRangeStrict"}; + Configurable requireNoCollInRofStrict{"requireNoCollInRofStrict", true, "requireNoCollInRofStrict"}; Configurable requireNoCollInRofStandard{"requireNoCollInRofStandard", false, "requireNoCollInRofStandard"}; Configurable requireNoHighMultCollInPrevRof{"requireNoHighMultCollInPrevRof", false, "requireNoHighMultCollInPrevRof"}; - Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", true, "reject collisions corrupted by the cannibalism, with other collisions within +/- 10 microseconds"}; + Configurable requireNoCollInTimeRangeStd{"requireNoCollInTimeRangeStd", false, "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 occupancyEstimator{"occupancyEstimator", 1, "Occupancy estimator: 1 = trackOccupancyInTimeRange, 2 = ft0cOccupancyInTimeRange"}; Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; @@ -190,6 +243,9 @@ struct DndetaMFTPbPb { Service 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 ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", false, "flag to apply z shift from CCDB"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0.0f, "manual z-shift for propagation of global muon to PV"}; int mRunNumber{-1}; uint64_t mSOR{0}; @@ -199,6 +255,12 @@ struct DndetaMFTPbPb { TH2* gCurrentHadronicRate; RCTFlagsChecker rctChecker; + float bZ = 0; // Magnetic field for MFT + static constexpr double CcenterMFT[3] = {0, 0, -61.4}; // Field at center of MFT + float mZShift = 0; // z-vertex shift + + o2::parameters::GRPMagField* grpmag = nullptr; + std::vector ambiguousTrkIds; std::vector reassignedTrkIds; std::vector ambiguousTrkIdsMC; @@ -224,6 +286,8 @@ struct DndetaMFTPbPb { const AxisSpec etaAxis = {binOpt.etaBins, "#eta axis"}; const AxisSpec chiSqAxis = {binOpt.chiSqPerNclBins, "Chi2 axis"}; const AxisSpec nclsAxis = {binOpt.nClBins, "Number of clusters axis"}; + const AxisSpec tanLambdaAxis{binOpt.tanLambdaBins, "tan(#lambda)"}; + const AxisSpec invQPtAxis{binOpt.invQPtBins, "q/p_{T} (1/GeV)"}; rctChecker.init(rctCuts.cfgEvtRCTFlagCheckerLabel, rctCuts.cfgEvtRCTFlagCheckerZDCCheck, rctCuts.cfgEvtRCTFlagCheckerLimitAcceptAsBad); @@ -368,6 +432,11 @@ struct DndetaMFTPbPb { "; N_{ch}; occupancy", {HistType::kTH2F, {multAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/TanLambda", "; TanLambda; centrality; occupancy", {HistType::kTH2F, {tanLambdaAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/InvQPt", "; InvQPt; centrality; occupancy", {HistType::kTH2F, {invQPtAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Eta", "; #eta; centrality; occupancy", {HistType::kTH2F, {etaAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Phi", "; #varphi; centrality; occupancy", {HistType::kTH2F, {phiAxis, occupancyAxis}}}); + if (doprocessDatawBestTracksInclusive) { registry.add( {"Events/NtrkZvtxBest", @@ -416,6 +485,10 @@ struct DndetaMFTPbPb { qaregistry.add({"Tracks/TrackAmbDegree", "; N_{coll}^{comp}; occupancy", {HistType::kTH2F, {{51, -0.5, 50.5}, occupancyAxis}}}); + qaregistry.add({"Tracks/TanLambdaExtra", "; TanLambda; occupancy", {HistType::kTH2F, {tanLambdaAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/InvQPtExtra", "; InvQPt; occupancy", {HistType::kTH2F, {invQPtAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/EtaExtra", "; #eta; occupancy", {HistType::kTH2F, {etaAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/PhiExtra", "; #varphi; occupancy", {HistType::kTH2F, {phiAxis, occupancyAxis}}}); } } @@ -483,6 +556,11 @@ struct DndetaMFTPbPb { {HistType::kTHnSparseF, {nclsAxis, etaAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/TanLambda", "; TanLambda; centrality; occupancy", {HistType::kTHnSparseF, {tanLambdaAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/InvQPt", "; InvQPt; centrality; occupancy", {HistType::kTHnSparseF, {invQPtAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/Eta", "; #eta; centrality; occupancy", {HistType::kTHnSparseF, {etaAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/Phi", "; #varphi; centrality; occupancy", {HistType::kTHnSparseF, {phiAxis, centralityAxis, occupancyAxis}}}); + if (doprocessDatawBestTracksCentFT0C || doprocessDatawBestTracksCentFT0CVariant1 || doprocessDatawBestTracksCentFT0M || @@ -509,6 +587,10 @@ struct DndetaMFTPbPb { "; N_{coll}^{comp}; centrality; occupancy", {HistType::kTHnSparseF, {{51, -0.5, 50.5}, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/TanLambdaExtra", "; TanLambda; centrality; occupancy", {HistType::kTHnSparseF, {tanLambdaAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/InvQPtExtra", "; InvQPt; centrality; occupancy", {HistType::kTHnSparseF, {invQPtAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/EtaExtra", "; #eta; centrality; occupancy", {HistType::kTHnSparseF, {etaAxis, centralityAxis, occupancyAxis}}}); + qaregistry.add({"Tracks/Centrality/PhiExtra", "; #varphi; centrality; occupancy", {HistType::kTHnSparseF, {phiAxis, centralityAxis, occupancyAxis}}}); qaregistry.add( {"Tracks/Centrality/DCA3d", "; p_{T} (GeV/c); #eta; DCA_{XY} (cm); DCA_{Z} (cm); centrality; occupancy", @@ -855,28 +937,58 @@ struct DndetaMFTPbPb { } if (doprocessCollAssocMC) { + + registry.add("Events/hNAssocColls", "Number of times generated collisions are reconstructed; N; Counts", HistType::kTH1F, {{10, -0.5, 9.5}}); + // tracks not associated to any collision - hCollAssoc[0] = qaregistry.add("TrackToColl/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[0] = qaregistry.add("TrackToColl/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associasted to a collision - hCollAssoc[1] = qaregistry.add("TrackToColl/hAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[1] = qaregistry.add("TrackToColl/hAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) - hCollAssoc[2] = qaregistry.add("TrackToColl/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[2] = qaregistry.add("TrackToColl/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) - hCollAssoc[3] = qaregistry.add("TrackToColl/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + hCollAssoc[3] = qaregistry.add("TrackToColl/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + qaregistry.add("TrackToColl/histFracTracksFakeMcColl", "Fraction of tracks originating from fake collision; fraction; entries", {HistType::kTH1F, {{101, 0., 1.01}}}); qaregistry.add("TrackToColl/histFracGoodTracks", "Fraction of tracks originating from the correct collision; fraction; entries", {HistType::kTH1F, {{101, 0., 1.01}}}); qaregistry.add("TrackToColl/histAmbTrackNumColls", "Number of collisions associated to an ambiguous track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); + qaregistry.add("TrackToColl/histTrackNumColls", "Number of collisions associated to track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); + qaregistry.add("TrackToColl/histNonAmbTrackNumColls", "Number of collisions associated to non-ambiguous track; no. collisions; entries", {HistType::kTH1F, {{30, -0.5, 29.5}}}); + qaregistry.add("TrackToColl/histAmbTrackZvtxRMS", "RMS of #it{Z}^{reco} of collisions associated to a track; RMS(#it{Z}^{reco}) (cm); entries", {HistType::kTH1F, {{100, 0., 0.5}}}); } if (doprocessReAssocMC) { - // tracks not associated to any collision - hReAssoc[0] = qaregistry.add("ReAssoc/hNonAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); - // tracks associasted to a collision - hReAssoc[1] = qaregistry.add("ReAssoc/hAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); - // tracks associated to the correct collision considering only first reco collision (based on the MC collision index) - hReAssoc[2] = qaregistry.add("ReAssoc/hGoodAssocTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); - // tracks associated to the correct collision considering all ambiguous reco collisions (based on the MC collision index) - hReAssoc[3] = qaregistry.add("ReAssoc/hGoodAssocTracksAmb", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis}); + + registry.add("Events/hNReAssocColls", "Number of times generated collisions are reconstructed; N; Counts", HistType::kTH1F, {{10, -0.5, 9.5}}); + + registry.add("Events/ReAssocMCStatus", ";status", {HistType::kTH1F, {{12, 0.5, 12.5}}}); + auto hstat = registry.get(HIST("Events/ReAssocMCStatus")); + hstat->GetXaxis()->SetBinLabel(1, "All compatible"); + hstat->GetXaxis()->SetBinLabel(2, "Selected"); + hstat->GetXaxis()->SetBinLabel(3, "Has collision"); + hstat->GetXaxis()->SetBinLabel(4, "Reassigned"); + hstat->GetXaxis()->SetBinLabel(5, "Has particle"); + hstat->GetXaxis()->SetBinLabel(6, "Pos z MC cut"); + hstat->GetXaxis()->SetBinLabel(7, "Associated"); + hstat->GetXaxis()->SetBinLabel(8, "Associated true"); + hstat->GetXaxis()->SetBinLabel(9, "Associated wrong"); + hstat->GetXaxis()->SetBinLabel(10, "Reassociated"); + hstat->GetXaxis()->SetBinLabel(11, "Reassociated true"); + hstat->GetXaxis()->SetBinLabel(12, "Reassociated wrong"); + + hReAssoc[0] = qaregistry.add("ReAssoc/hAssocBestTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[1] = qaregistry.add("ReAssoc/hAssocBestWrong", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[2] = qaregistry.add("ReAssoc/hReAssocBestTrue", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + hReAssoc[3] = qaregistry.add("ReAssoc/hReAssocBestWrong", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, deltaZAxis, deltaZAxis, deltaZAxis}); + + hDCAMc[0] = qaregistry.add("ReAssoc/hAssocBestTrueDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[1] = qaregistry.add("ReAssoc/hAssocBestTrueDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[2] = qaregistry.add("ReAssoc/hAssocBestWrongDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[3] = qaregistry.add("ReAssoc/hAssocBestWrongDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[4] = qaregistry.add("ReAssoc/hReAssocBestTrueDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[5] = qaregistry.add("ReAssoc/hReAssocBestTrueDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[6] = qaregistry.add("ReAssoc/hReAssocBestWrongDCAPrim", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); + hDCAMc[7] = qaregistry.add("ReAssoc/hReAssocBestWrongDCASec", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY} (cm)^{reco}; DCA_{Z} (cm)^{reco}; DCA_{XY} (cm); DCA_{Z} (cm)", HistType::kTHnSparseF, {ptAxis, etaAxis, dcaxyAxis, dcazAxis, dcaxyAxis, dcazAxis}); } if (doprocessEfficiencyInclusive) { @@ -955,56 +1067,91 @@ struct DndetaMFTPbPb { } } - if (doprocessDCAReassocMcInclusive || doprocessDCAReassocMcCentFT0C) { - auto hNevt = registry.add("Events/hNGenRecCollsReassoc", "Number of generated and reconstructed MC collisions", HistType::kTH1F, {{3, 0.5, 3.5}}); + if (doprocessAlignmentInclusive) { + for (size_t j = 0; j < mftQuadrant.size(); j++) { + const auto& quadrant = mftQuadrant[j]; + std::string hPath = std::string("Alignment/") + quadrant + "/"; + hAlignment[0][j][0]["DCA_x_vs_z"] = registryAlign.add((hPath + "DCA_x_vs_z").c_str(), std::format("DCA(x) vs. z - {}", quadrant).c_str(), {HistType::kTH2F, {zAxis, dcaxyAxis}}); + hAlignment[0][j][0]["DCA_y_vs_z"] = registryAlign.add((hPath + "DCA_y_vs_z").c_str(), std::format("DCA(y) vs. z - {}", quadrant).c_str(), {HistType::kTH2F, {zAxis, dcaxyAxis}}); + } + } + + if (doprocessReassocEfficiency) { + registry.add("Events/hNReEffColls", "Number of times generated collisions are reconstructed; N; Counts", HistType::kTH1F, {{10, -0.5, 9.5}}); + registry.add("Events/hNchTVX", "; status;", HistType::kTH2F, {multAxis, {2, 0, 2}}); + + registry.add("Events/Centrality/ReEffStatus", ";status;centrality", HistType::kTH2F, {{9, 0.5, 9.5}, centralityAxis}); + auto hstat = registry.get(HIST("Events/Centrality/ReEffStatus")); + hstat->GetXaxis()->SetBinLabel(1, "All tracks"); + hstat->GetXaxis()->SetBinLabel(2, "Ambiguous tracks"); + hstat->GetXaxis()->SetBinLabel(3, "Reassigned tracks"); + hstat->GetXaxis()->SetBinLabel(4, "Extra tracks"); + hstat->GetXaxis()->SetBinLabel(5, "Originally correctly reassgined"); + hstat->GetXaxis()->SetBinLabel(6, "Correctly reassigned"); + hstat->GetXaxis()->SetBinLabel(7, "Not reassigned (reassigned)"); + hstat->GetXaxis()->SetBinLabel(8, "Not reassigned"); + hstat->GetXaxis()->SetBinLabel(9, "Correctly assigned true"); + + registry.add({"AmbTracks/hVtxzMCrec", " ; Z_{vtx} (cm)", {HistType::kTH1F, {zAxis}}}); + registry.add({"AmbTracks/DCAXY", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAZ", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + registry.add({"AmbTracks/DCAXYBest", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAZBest", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + registry.add({"AmbTracks/DCAXYBestPrim", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAZBestPrim", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + registry.add({"AmbTracks/DCAXYBestTrue", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAZBestTrue", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + registry.add({"AmbTracks/DCAXYBestFalse", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAZBestFalse", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + registry.add({"AmbTracks/DCAXYBestTrueOrigAssoc", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAXYBestTrueOrigReAssoc", " ; DCA_{XY} (cm)", {HistType::kTH1F, {dcaxyAxis}}}); + registry.add({"AmbTracks/DCAZBestTrueOrigAssoc", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + registry.add({"AmbTracks/DCAZBestTrueOrigReAssoc", " ; DCA_{Z} (cm)", {HistType::kTH1F, {dcazAxis}}}); + + registry.add({"AmbTracks/Centrality/THnDCAxyBestGen", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + registry.add({"AmbTracks/Centrality/THnDCAxyBestGenPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + registry.add({"AmbTracks/Centrality/THnDCAxyBestTrue", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + registry.add({"AmbTracks/Centrality/THnDCAxyBestFalse", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + registry.add({"AmbTracks/Centrality/THnDCAxyBestTrueOrigAssoc", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + registry.add({"AmbTracks/Centrality/THnDCAxyBestTrueOrigReAssoc", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); + + registry.add({"AmbTracks/BestGenDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestPrimDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestTrueDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestFalseDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestTrueOrigReAssocDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + registry.add({"AmbTracks/BestTrueOrigAssocDxyz", "; #Delta X (cm); #Delta Y (cm); #Delta Z (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {deltaZAxis, deltaZAxis, deltaZAxis, dcaxyAxis, dcazAxis}}}); + } + + if (doprocessEventAndSignalLossCentFT0C) { + auto hNevt = registry.add("Events/Centrality/hNRecCollsSigEvtLoss", "Number of reconstructed MC collisions", HistType::kTH1F, {{1, 0.5, 1.5}}); hNevt->GetXaxis()->SetBinLabel(1, "Reconstructed collisions"); - hNevt->GetXaxis()->SetBinLabel(2, "Generated collisions"); - if (doprocessDCAReassocMcInclusive) { - registry.add({"Events/EvtGenRecReassoc", ";status", {HistType::kTH2F, {{3, 0.5, 3.5}, occupancyAxis}}}); - auto heff = registry.get(HIST("Events/EvtGenRecReassoc")); - auto* h = heff->GetXaxis(); - h->SetBinLabel(1, "All generated"); - h->SetBinLabel(2, "All reconstructed"); - h->SetBinLabel(3, "Selected reconstructed"); - registry.add({"Tracks/THnDCAxyBestRec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestRecFake", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenTruthSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSecWeak", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - registry.add({"Tracks/THnDCAxyBestGenSecMat", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm)", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis}}}); - } - if (doprocessDCAReassocMcCentFT0C) { - registry.add({"Events/Centrality/EvtGenRecReassoc", ";status;centrality", {HistType::kTHnSparseF, {{3, 0.5, 3.5}, centralityAxis, occupancyAxis}}}); - auto heff = registry.get(HIST("Events/Centrality/EvtGenRecReassoc")); - heff->GetAxis(0)->SetBinLabel(1, "All generated"); - heff->GetAxis(0)->SetBinLabel(2, "All reconstructed"); - heff->GetAxis(0)->SetBinLabel(3, "Selected reconstructed"); - registry.add({"Tracks/Centrality/THnDCAxyBestRec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestRecFake", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthPrim", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthPrimWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthSec", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenTruthSecWrongColl", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSecWeak", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - registry.add({"Tracks/Centrality/THnDCAxyBestGenSecMat", "; p_{T} (GeV/c); #eta; Z_{vtx} (cm); DCA_{XY} (cm); DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {ptAxis, etaAxis, zAxis, dcaxyAxis, dcazAxis, centralityAxis}}}); - } + + registry.add("Events/Centrality/EvtSigLossStatus", ";status;centrality", {HistType::kTH2F, {{3, 0.5, 3.5}, centralityAxis}}); + auto hstat = registry.get(HIST("Events/Centrality/EvtSigLossStatus")); + hstat->GetXaxis()->SetBinLabel(1, "All MC gen events"); + hstat->GetXaxis()->SetBinLabel(2, "MC gen events with rec event with event selection"); + hstat->GetXaxis()->SetBinLabel(3, "MC gen events with no rec events"); + + registry.add("Events/Centrality/hMultGenVsCent", "event mult MC gen", {HistType::kTH2F, {centralityAxis, multFT0cAxis}}); + registry.add("Events/Centrality/hMultGenVsCentNParticlesEta05", "event mult MC gen", {HistType::kTH2F, {centralityAxis, multAxis}}); + registry.add("Events/Centrality/hMultGenVsCentNParticlesEtaMFT", "event mult MC gen", {HistType::kTH2F, {centralityAxis, multAxis}}); + registry.add("Events/Centrality/hMultGenVsCentRec", "event mult MC gen vs centrality", {HistType::kTH2F, {centralityAxis, multFT0cAxis}}); + registry.add("Events/Centrality/hMultGenVsCentRecNParticlesEta05", "event mult MC gen vs centrality", {HistType::kTH2F, {centralityAxis, multAxis}}); + registry.add("Events/Centrality/hMultGenVsCentRecNParticlesEtaMFT", "event mult MC gen vs centrality", {HistType::kTH2F, {centralityAxis, multAxis}}); + + registry.add({"Tracks/Centrality/EtaCentVsMultGen_t", "; #eta; centrality; mult gen", {HistType::kTHnSparseF, {etaAxis, centralityAxis, multFT0cAxis}}}); + registry.add({"Tracks/Centrality/EtaCentVsMultGen", "; #eta; centrality; mult gen", {HistType::kTHnSparseF, {etaAxis, centralityAxis, multFT0cAxis}}}); + + registry.add({"Tracks/Centrality/EtaGen_t", "; #eta; centrality; occupancy", {HistType::kTH2F, {etaAxis, centralityAxis}}}); + registry.add({"Tracks/Centrality/EtaGen", "; #eta; centrality; occupancy", {HistType::kTH2F, {etaAxis, centralityAxis}}}); } } /// Filters - tracks Filter filtTrkEta = (aod::fwdtrack::eta < trackCuts.maxEta) && (aod::fwdtrack::eta > trackCuts.minEta); - Filter filtATrackID = (aod::fwdtrack::bestCollisionId >= kIntZero); + Filter filtATrackID = (aod::fwdtrack::bestCollisionId >= CintZero); Filter filtATrackDCAxy = (nabs(aod::fwdtrack::bestDCAXY) < trackCuts.maxDCAxy); Filter filtATrackDCAz = (nabs(aod::fwdtrack::bestDCAZ) < trackCuts.maxDCAz); @@ -1014,6 +1161,8 @@ struct DndetaMFTPbPb { /// Joined tables using FullBCs = soa::Join; using CollBCs = soa::Join; + using ExtBCs = soa::Join; + // Collisions using Colls = soa::Join; using Coll = Colls::iterator; @@ -1028,14 +1177,14 @@ struct DndetaMFTPbPb { using CollsGenCentFT0C = soa::Join; using CollisionsWithMCLabels = soa::Join; - using CollGenCent = CollsGenCentFT0C::iterator; using CollsCorr = soa::Join; + using CollsMCExtra = soa::Join; + // Tracks using MFTTracksLabeled = soa::Join; using MftTracksWColls = soa::Join; using MftTracksWCollsMC = soa::Join; - using BestTracksMC = soa::Join; /// Filtered tables @@ -1046,13 +1195,61 @@ struct DndetaMFTPbPb { using FiltParticles = soa::Filtered; + /// \brief RMS calculation + /// \param vec vector of values to compute RMS + template + T computeRMS(std::vector& vec) + { + T sum = std::accumulate(vec.begin(), vec.end(), 0.0); + T mean = sum / vec.size(); + + std::vector diff(vec.size()); + std::transform(vec.begin(), vec.end(), diff.begin(), [mean](T x) { return x - mean; }); + T sqSum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); + T stdev = std::sqrt(sqSum / vec.size()); + + return stdev; + } + + void initCCDB(ExtBCs::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + grpmag = ccdb->getForTimeStamp(gConf.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); + mRunNumber = bc.runNumber(); + + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + bZ = field->getBz(CcenterMFT); + LOG(info) << "The field at the center of the MFT is bZ = " << bZ; + + if (cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", cfgManualZShift.value); + mZShift = cfgManualZShift; + } + } + template bool isBestTrackSelected(const B& besttrack) { if constexpr (fillHis) { registry.fill(HIST("Tracks/hBestTrkSel"), trkBestSelAll); } - if (besttrack.bestCollisionId() < kIntZero) { + if (besttrack.bestCollisionId() < CintZero) { return false; } if constexpr (fillHis) { @@ -1153,15 +1350,23 @@ struct DndetaMFTPbPb { if (fillHis) { float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + if (phi < Czero || TwoPI < phi) { continue; } if constexpr (has_reco_cent) { registry.fill(HIST("Tracks/Centrality/EtaZvtx"), track.eta(), z, c, occ); registry.fill(HIST("Tracks/Centrality/PhiEta"), phi, track.eta(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/TanLambda"), track.tgl(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/InvQPt"), track.signed1Pt(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/Eta"), track.eta(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/Phi"), phi, c, occ); } else { registry.fill(HIST("Tracks/EtaZvtx"), track.eta(), z, occ); registry.fill(HIST("Tracks/PhiEta"), phi, track.eta(), occ); + qaregistry.fill(HIST("Tracks/TanLambda"), track.tgl(), c, occ); + qaregistry.fill(HIST("Tracks/InvQPt"), track.signed1Pt(), c, occ); + qaregistry.fill(HIST("Tracks/Eta"), track.eta(), c, occ); + qaregistry.fill(HIST("Tracks/Phi"), phi, c, occ); } } ++nTrk; @@ -1176,6 +1381,35 @@ struct DndetaMFTPbPb { return nTrk; } + template + void countBestTracksExtra(B const& besttracksExtra, float c, float occ) + { + for (auto const& etrack : besttracksExtra) { + if (fillHis) { + float phi = etrack.phis(); + o2::math_utils::bringTo02Pi(phi); + if (phi < Czero || TwoPI < phi) { + continue; + } + if constexpr (has_reco_cent) { + if (gConf.cfgUseTrackParExtra) { + qaregistry.fill(HIST("Tracks/Centrality/TanLambdaExtra"), etrack.tgl(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/InvQPtExtra"), etrack.signed1Pt(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/EtaExtra"), etrack.etas(), c, occ); + qaregistry.fill(HIST("Tracks/Centrality/PhiExtra"), phi, c, occ); + } + } else { + if (gConf.cfgUseTrackParExtra) { + qaregistry.fill(HIST("Tracks/TanLambdaExtra"), etrack.tgl(), occ); + qaregistry.fill(HIST("Tracks/InvQPtExtra"), etrack.signed1Pt(), occ); + qaregistry.fill(HIST("Tracks/EtaExtra"), etrack.etas(), occ); + qaregistry.fill(HIST("Tracks/PhiExtra"), phi, occ); + } + } + } + } + } + template int countBestTracks(T const& tracks, B const& besttracks, float z, float c, float occ) @@ -1196,7 +1430,7 @@ struct DndetaMFTPbPb { if (fillHis) { float phi = itrack.phi(); o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + if (phi < Czero || TwoPI < phi) { continue; } if constexpr (has_reco_cent) { @@ -1220,7 +1454,7 @@ struct DndetaMFTPbPb { registry.fill(HIST("Tracks/hBestTrkSel"), trkBestSelNumReassoc); float phi = itrack.phi(); o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + if (phi < Czero || TwoPI < phi) { continue; } if constexpr (has_reco_cent) { @@ -1240,7 +1474,7 @@ struct DndetaMFTPbPb { } float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + if (phi < Czero || TwoPI < phi) { continue; } if (fillHis) { @@ -1297,7 +1531,7 @@ struct DndetaMFTPbPb { if (!isChrgParticle(particle.pdgCode())) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } if (particle.eta() < trackCuts.minEta || particle.eta() > trackCuts.maxEta) { @@ -1308,6 +1542,46 @@ struct DndetaMFTPbPb { return nCharged; } + template + bool isInelGt0wMft(P const& particles) + { + int nChrgMc = 0; + int nChrgFT0A = 0; + int nChrgFT0C = 0; + for (auto const& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { + continue; + } + if (!particle.isPhysicalPrimary()) { + continue; + } + // trigger TVX + if (particle.eta() > CminAccFT0A && particle.eta() < CmaxAccFT0A) { + nChrgFT0A++; + } + if (particle.eta() > CminAccFT0C && particle.eta() < CmaxAccFT0C) { + nChrgFT0C++; + } + // acceptance MFT + if (particle.eta() < trackCuts.minEta || particle.eta() > trackCuts.maxEta) { + continue; + } + nChrgMc++; + } + + if (nChrgFT0A == CintZero || nChrgFT0C == CintZero) { + registry.fill(HIST("Events/hNchTVX"), nChrgMc, 0.5); + return false; + } + registry.fill(HIST("Events/hNchTVX"), nChrgMc, 1.5); + + if (nChrgMc == CintZero) { + return false; + } + + return true; + } + template bool isParticleSelected(P const& particle) { @@ -1466,7 +1740,7 @@ struct DndetaMFTPbPb { if (p != nullptr) { charge = p->Charge(); } - return std::abs(charge) >= kMinCharge; + return std::abs(charge) >= CminCharge; } template @@ -1477,13 +1751,13 @@ struct DndetaMFTPbPb { if (!isChrgParticle(particle.pdgCode())) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } float phi = particle.phi(); o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + if (phi < Czero || TwoPI < phi) { continue; } if constexpr (isCent) { @@ -1499,7 +1773,7 @@ struct DndetaMFTPbPb { if (gtZeroColl) { float phi = particle.phi(); o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + if (phi < Czero || TwoPI < phi) { continue; } if constexpr (isCent) { @@ -1565,16 +1839,16 @@ struct DndetaMFTPbPb { return; } - if (cfgDoIR) { + if (gConf.cfgDoIR) { initHadronicRate(bc); - float ir = !cfgIRSource.value.empty() ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), cfgIRSource, cfgIRCrashOnNull) * 1.e-3 : -1; + float ir = !gConf.cfgIRSource.value.empty() ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), gConf.cfgIRSource, gConf.cfgIRCrashOnNull) * 1.e-3 : -1; if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/hInteractionRate"), c, occ, ir); } else { registry.fill(HIST("Events/hInteractionRate"), occ, ir); } float seconds = bc.timestamp() * 1.e-3 - mMinSeconds; - if (cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate + if (gConf.cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate return; } gCurrentHadronicRate->Fill(seconds, ir); @@ -1601,7 +1875,7 @@ struct DndetaMFTPbPb { template void processDatawBestTracks( typename C::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& /*bcs*/) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& /*bcs*/) { auto occ = getOccupancy(collision, eventCuts.occupancyEstimator); float c = getRecoCent(collision); @@ -1616,16 +1890,16 @@ struct DndetaMFTPbPb { return; } - if (cfgDoIR) { + if (gConf.cfgDoIR) { initHadronicRate(bc); - float ir = !cfgIRSource.value.empty() ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), cfgIRSource, cfgIRCrashOnNull) * 1.e-3 : -1; + float ir = !gConf.cfgIRSource.value.empty() ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), gConf.cfgIRSource, gConf.cfgIRCrashOnNull) * 1.e-3 : -1; if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/hInteractionRate"), c, occ, ir); } else { registry.fill(HIST("Events/hInteractionRate"), occ, ir); } float seconds = bc.timestamp() * 1.e-3 - mMinSeconds; - if (cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate + if (gConf.cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate return; } gCurrentHadronicRate->Fill(seconds, ir); @@ -1641,6 +1915,7 @@ struct DndetaMFTPbPb { } auto nBestTrks = countBestTracks(tracks, besttracks, z, c, occ); + countBestTracksExtra(besttracksExtra, c, occ); if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/NtrkZvtxBest"), nBestTrks, z, c, @@ -1707,9 +1982,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksInclusive( Colls::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& bcs) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, bcs); + processDatawBestTracks(collision, tracks, besttracks, besttracksExtra, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksInclusive, @@ -1718,9 +1993,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentFT0C( CollsCentFT0C::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& bcs) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, bcs); + processDatawBestTracks(collision, tracks, besttracks, besttracksExtra, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentFT0C, @@ -1730,9 +2005,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentFT0CVariant1( CollsCentFT0CVariant1::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& bcs) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, bcs); + processDatawBestTracks(collision, tracks, besttracks, besttracksExtra, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentFT0CVariant1, @@ -1742,9 +2017,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentFT0M( CollsCentFT0M::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& bcs) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, bcs); + processDatawBestTracks(collision, tracks, besttracks, besttracksExtra, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentFT0M, @@ -1753,9 +2028,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentNGlobal( CollsCentNGlobal::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& bcs) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, bcs); + processDatawBestTracks(collision, tracks, besttracks, besttracksExtra, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentNGlobal, @@ -1765,9 +2040,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentMFT( CollsCentMFT::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, CollBCs const& bcs) + soa::SmallGroups const& besttracks, aod::BestCollisionsFwd3dExtra const& besttracksExtra, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, bcs); + processDatawBestTracks(collision, tracks, besttracks, besttracksExtra, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentMFT, @@ -2203,7 +2478,7 @@ struct DndetaMFTPbPb { if (!isChrgParticle(particle.pdgCode())) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } @@ -2348,7 +2623,7 @@ struct DndetaMFTPbPb { if (!isChrgParticle(particle.pdgCode())) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } @@ -2478,7 +2753,7 @@ struct DndetaMFTPbPb { if (!isChrgParticle(particle.pdgCode())) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } if constexpr (has_reco_cent) { @@ -2712,65 +2987,116 @@ struct DndetaMFTPbPb { aod::McCollisions const& /*mccollisions*/ ) { - for (const auto& collision : collisions) { - if (!collision.has_mcCollision()) { - continue; - } - // auto mcCollision = collision.template mcCollision_as(); - auto tracksInColl = tracksInAcc->sliceByCached(aod::fwdtrack::collisionId, collision.globalIndex(), cache); - int nTrk = 0, nFakeTrk = 0, nGoodTrk = 0; - for (const auto& track : tracksInColl) { - if (!track.has_mcParticle()) { + const auto& nRecoColls = collisions.size(); + registry.fill(HIST("Events/hNAssocColls"), 1.f, nRecoColls); + // Generated evets with >= 1 reco collisions + if (nRecoColls > CintZero) { + auto maxNcontributors = -1; + auto bestCollIndex = -1; + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { continue; } - nTrk++; - auto particle = track.mcParticle(); + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + } + } - if ((particle.mcCollisionId() != collision.mcCollision().globalIndex())) { - nFakeTrk++; + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + // Select collisions with the largest number of contributors + if (bestCollIndex != collision.globalIndex()) { continue; } - if (collision.mcCollisionId() == particle.mcCollisionId()) { - nGoodTrk++; + // auto mcCollision = collision.template mcCollision_as(); + auto tracksInColl = tracksInAcc->sliceByCached(aod::fwdtrack::collisionId, collision.globalIndex(), cache); + int nTrk = 0, nFakeTrk = 0, nGoodTrk = 0; + for (const auto& track : tracksInColl) { + if (!track.has_mcParticle()) { + continue; + } + nTrk++; + auto particle = track.mcParticle(); + + if ((particle.mcCollisionId() != collision.mcCollision().globalIndex())) { + nFakeTrk++; + continue; + } + if (collision.mcCollisionId() == particle.mcCollisionId()) { + nGoodTrk++; + } } + float frac = (nTrk > 0) ? static_cast(nGoodTrk) / nTrk : -1.; + qaregistry.fill(HIST("TrackToColl/histFracGoodTracks"), frac); + float fracFake = (nTrk > 0) ? static_cast(nFakeTrk) / nTrk : -1.; + qaregistry.fill(HIST("TrackToColl/histFracTracksFakeMcColl"), fracFake); } - float frac = (nTrk > 0) ? static_cast(nGoodTrk) / nTrk : -1.; - qaregistry.fill(HIST("TrackToColl/histFracGoodTracks"), frac); - float fracFake = (nTrk > 0) ? static_cast(nFakeTrk) / nTrk : -1.; - qaregistry.fill(HIST("TrackToColl/histFracTracksFakeMcColl"), fracFake); } - for (auto const& track : tracks) { + for (const auto& track : tracks) { uint index = uint(track.collisionId() >= 0); if (track.has_mcParticle()) { // auto particle = track.mcParticle_as(); - auto particle = track.mcParticle(); - bool isAmbiguous = (track.compatibleCollIds().size() != 1); + const auto& particle = track.mcParticle(); + + qaregistry.fill(HIST("TrackToColl/histTrackNumColls"), track.compatibleCollIds().size()); + + if (gConf.cfgRemoveTrivialAssoc) { + if (track.compatibleCollIds().empty() || (track.compatibleCollIds().size() == 1 && track.collisionId() == track.compatibleCollIds()[0])) { + qaregistry.fill(HIST("TrackToColl/histNonAmbTrackNumColls"), track.compatibleCollIds().size()); + continue; + } + } + + bool isAmbiguous = (track.compatibleCollIds().size() > 1); if (isAmbiguous) { qaregistry.fill(HIST("TrackToColl/histAmbTrackNumColls"), track.compatibleCollIds().size()); + std::vector ambVtxZ{}; + for (const auto& collIdx : track.compatibleCollIds()) { + const auto& ambColl = collisions.rawIteratorAt(collIdx); + ambVtxZ.push_back(ambColl.posZ()); + } + if (!ambVtxZ.empty()) { + qaregistry.fill(HIST("TrackToColl/histAmbTrackZvtxRMS"), computeRMS(ambVtxZ)); + } } + + float deltaX = -999.f; + float deltaY = -999.f; float deltaZ = -999.f; if (index) { - auto collision = track.collision_as(); - auto mcCollision = particle.mcCollision_as(); + const auto& collision = track.collision_as(); + const auto& mcCollision = particle.mcCollision_as(); + deltaX = collision.posX() - mcCollision.posX(); + deltaY = collision.posY() - mcCollision.posY(); deltaZ = collision.posZ() - mcCollision.posZ(); if (collision.has_mcCollision() && collision.mcCollisionId() == particle.mcCollisionId()) { - hCollAssoc[index + 1]->Fill(track.pt(), track.eta(), deltaZ); + hCollAssoc[index + 1]->Fill(track.pt(), track.eta(), deltaX, deltaY, deltaZ); } else { if (isAmbiguous) { for (const auto& collIdx : track.compatibleCollIds()) { - auto ambCollision = collisions.rawIteratorAt(collIdx); - if (ambCollision.has_mcCollision() && ambCollision.mcCollisionId() == particle.mcCollisionId()) { - hCollAssoc[index + 2]->Fill(track.pt(), track.eta(), deltaZ); + auto ambColl = collisions.rawIteratorAt(collIdx); + if (ambColl.has_mcCollision() && ambColl.mcCollisionId() == particle.mcCollisionId()) { + hCollAssoc[index + 2]->Fill(track.pt(), track.eta(), deltaX, deltaY, deltaZ); + // hCollAssoc[index + 2]->Fill(track.pt(), track.eta(), ambColl.posX() - mcCollision.posX(), ambColl.posY() - mcCollision.posY(), ambColl.posZ() - mcCollision.posZ()); break; } } } } + hCollAssoc[index]->Fill(track.pt(), track.eta(), deltaX, deltaY, deltaZ); } - hCollAssoc[index]->Fill(track.pt(), track.eta(), deltaZ); } else { - hCollAssoc[index]->Fill(track.pt(), track.eta(), -999.f); + hCollAssoc[index]->Fill(track.pt(), track.eta(), -999.f, -999.f, -999.f); } } } @@ -2785,46 +3111,173 @@ struct DndetaMFTPbPb { PROCESS_SWITCH(DndetaMFTPbPb, processCollAssocMC, "Process collision-association information, requires extra table from TrackToCollisionAssociation task (fillTableOfCollIdsPerTrack=true)", false); template - void processCheckReAssocMC(C const& /*collisions*/, + void processCheckReAssocMC(C const& collisions, soa::SmallGroups const& besttracks, FiltMcMftTracks const& /*tracks*/, FiltParticles const& /*particles*/, aod::McCollisions const& /*mccollisions*/ ) { - for (auto const& track : besttracks) { - uint index = uint(track.bestCollisionId() >= 0); // assigned - if (!isBestTrackSelected(track)) { - continue; + const auto& nRecoColls = collisions.size(); + registry.fill(HIST("Events/hNReAssocColls"), 1.f, nRecoColls); + // Generated evets with >= 1 reco collisions + if (nRecoColls > CintZero) { + + mapVtxXrec.clear(); + mapVtxYrec.clear(); + mapVtxZrec.clear(); + mapMcCollIdPerRecColl.clear(); + mapVtxXrec.reserve(collisions.size()); + mapVtxYrec.reserve(collisions.size()); + mapVtxZrec.reserve(collisions.size()); + mapMcCollIdPerRecColl.reserve(collisions.size()); + + auto maxNcontributors = -1; + auto bestCollIndex = -1; + for (auto const& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + mapVtxXrec.emplace(collision.globalIndex(), collision.posX()); + mapVtxYrec.emplace(collision.globalIndex(), collision.posY()); + mapVtxZrec.emplace(collision.globalIndex(), collision.posZ()); + mapMcCollIdPerRecColl.emplace(collision.globalIndex(), collision.mcCollisionId()); + } } - auto itrack = track.mfttrack_as(); - if (cfgRemoveReassigned) { - if (itrack.collisionId() != track.bestCollisionId()) { + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (!collision.has_mcCollision()) { + continue; + } + // Select collisions with the largest number of contributors + if (bestCollIndex != collision.globalIndex()) { continue; } - } - if (!isTrackSelected(itrack)) { - continue; - } - if (itrack.has_mcParticle()) { - auto particle = itrack.mcParticle_as(); - float deltaZ = -999.f; - if (index) { - auto collision = itrack.collision_as(); - auto mcCollision = particle.mcCollision_as(); - deltaZ = collision.posZ() - mcCollision.posZ(); - if (collision.has_mcCollision() && collision.mcCollisionId() == particle.mcCollisionId()) { - hReAssoc[index + 1]->Fill(itrack.pt(), itrack.eta(), deltaZ); - } else { - hReAssoc[index + 2]->Fill(itrack.pt(), itrack.eta(), deltaZ); + auto perCollisionASample = besttracks.sliceBy(perColU, collision.globalIndex()); + for (auto const& atrack : perCollisionASample) { + registry.fill(HIST("Events/ReAssocMCStatus"), 1); + if (!isBestTrackSelected(atrack)) { + continue; + } + registry.fill(HIST("Events/ReAssocMCStatus"), 2); + auto itrack = atrack.template mfttrack_as(); + if (!isTrackSelected(itrack)) { + continue; + } + float phi = itrack.phi(); + o2::math_utils::bringTo02Pi(phi); + if (phi < Czero || TwoPI < phi) { + continue; + } + if (!itrack.has_collision()) { + continue; + } + registry.fill(HIST("Events/ReAssocMCStatus"), 3); + if (gConf.cfgRemoveReassigned) { + if (itrack.collisionId() != atrack.bestCollisionId()) { + continue; + } + registry.fill(HIST("Events/ReAssocMCStatus"), 4); + } + if (itrack.has_mcParticle()) { + registry.fill(HIST("Events/ReAssocMCStatus"), 5); + auto particle = itrack.template mcParticle_as(); + auto collision = itrack.template collision_as(); + auto mcCollision = particle.template mcCollision_as(); + + if (eventCuts.useZVtxCutMC && (std::abs(mcCollision.posZ()) >= eventCuts.maxZvtx)) { + continue; + } + + registry.fill(HIST("Events/ReAssocMCStatus"), 6); + + float deltaX = -999.f; + float deltaY = -999.f; + float deltaZ = -999.f; + + if (mapVtxXrec.find(atrack.bestCollisionId()) == mapVtxXrec.end()) { + continue; + } + if (mapVtxYrec.find(atrack.bestCollisionId()) == mapVtxYrec.end()) { + continue; + } + if (mapVtxZrec.find(atrack.bestCollisionId()) == mapVtxZrec.end()) { + continue; + } + if (mapMcCollIdPerRecColl.find(atrack.bestCollisionId()) == mapMcCollIdPerRecColl.end()) { + continue; + } + const float vtxXbest = mapVtxXrec.find(atrack.bestCollisionId())->second; + const float vtxYbest = mapVtxYrec.find(atrack.bestCollisionId())->second; + const float vtxZbest = mapVtxZrec.find(atrack.bestCollisionId())->second; + // LOGP(info, "\t ---> \t .... \t vtxZrec: {} - collision.posZ(): {}", vtxZrec, collision.posZ()); + const float mcCollIdRec = mapMcCollIdPerRecColl.find(atrack.bestCollisionId())->second; + // LOGP(info, "\t ---> \t .... \t mcCollIdRec: {} - bestMCCol: {}", mcCollIdRec, bestMCCol); + deltaX = vtxXbest - mcCollision.posX(); + deltaY = vtxYbest - mcCollision.posY(); + deltaZ = vtxZbest - mcCollision.posZ(); + + const auto dcaXtruth(particle.vx() - particle.mcCollision().posX()); + const auto dcaYtruth(particle.vy() - particle.mcCollision().posY()); + const auto dcaZtruth(particle.vz() - particle.mcCollision().posZ()); + auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); + + if (itrack.collisionId() == atrack.bestCollisionId()) { // associated + registry.fill(HIST("Events/ReAssocMCStatus"), 7); + if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { + registry.fill(HIST("Events/ReAssocMCStatus"), 8); + hReAssoc[0]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[1]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[0]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } + } else { + registry.fill(HIST("Events/ReAssocMCStatus"), 9); + hReAssoc[1]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[3]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[2]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } + } + } else { + registry.fill(HIST("Events/ReAssocMCStatus"), 10); + if (collision.has_mcCollision() && mcCollIdRec == particle.mcCollisionId()) { + registry.fill(HIST("Events/ReAssocMCStatus"), 11); + hReAssoc[2]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[5]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[4]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } + } else { + registry.fill(HIST("Events/ReAssocMCStatus"), 12); + hReAssoc[3]->Fill(particle.pt(), particle.eta(), deltaX, deltaY, deltaZ); + if (!particle.isPhysicalPrimary()) { + hDCAMc[7]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { // Primaries + hDCAMc[6]->Fill(particle.pt(), particle.eta(), atrack.bestDCAXY(), atrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } + } + } } } - hReAssoc[index]->Fill(itrack.pt(), itrack.eta(), deltaZ); - } else { - hReAssoc[index]->Fill(itrack.pt(), itrack.eta(), -999.f); } + mapVtxXrec.clear(); + mapVtxYrec.clear(); + mapVtxZrec.clear(); + mapMcCollIdPerRecColl.clear(); } } @@ -3026,7 +3479,7 @@ struct DndetaMFTPbPb { if (particle.eta() <= trackCuts.minEta || particle.eta() >= trackCuts.maxEta) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } @@ -3068,8 +3521,8 @@ struct DndetaMFTPbPb { } else { if (isAmbiguous) { for (const auto& collIdx : track.compatibleCollIds()) { - auto ambCollision = collisions.rawIteratorAt(collIdx); - if (ambCollision.has_mcCollision() && ambCollision.mcCollisionId() == particle.mcCollisionId()) { + auto ambColl = collisions.rawIteratorAt(collIdx); + if (ambColl.has_mcCollision() && ambColl.mcCollisionId() == particle.mcCollisionId()) { if (!particle.isPhysicalPrimary()) { // Secondaries (weak decays and material) if constexpr (has_reco_cent) { registry.fill(HIST("Tracks/Centrality/THnGenSecAmb"), particle.pt(), particle.eta(), particle.mcCollision().posZ(), crec); @@ -3126,244 +3579,416 @@ struct DndetaMFTPbPb { PROCESS_SWITCH(DndetaMFTPbPb, processSecondariesMCCentFT0C, "Process secondaries checks (in FT0C centrality bins)", false); - template - void processDCAReassocMc(typename soa::Join const& collisions, - MC const& mcCollisions, - aod::McParticles const& /*particles*/, - BestTracksMC const& besttracks, - FiltMcMftTracks const& /*tracks*/ - ) + template + void processCorrelationwBestTracks(typename C::iterator const& collision, FiltMftTracks const& /*tracks*/, soa::SmallGroups const& besttracks) { - registry.fill(HIST("Events/hNGenRecCollsReassoc"), 1.f, collisions.size()); - registry.fill(HIST("Events/hNGenRecCollsReassoc"), 2.f, mcCollisions.size()); + if (!isGoodEvent(collision)) { + return; + } - float cGen = -1; - if constexpr (has_reco_cent) { - float crecMin = 105.f; - for (const auto& collision : collisions) { - if (isGoodEvent(collision)) { - float c = getRecoCent(collision); - if (c < crecMin) { - crecMin = c; - } - } + auto nBestTrks = 0; + for (auto const& atrack : besttracks) { + if (gConf.cfgUseTrackSel && !isBestTrackSelected(atrack)) { + continue; } - if (cGen < 0) - cGen = crecMin; - } - float occGen = -1.; - for (const auto& collision : collisions) { - if (isGoodEvent(collision)) { - float o = getOccupancy(collision, eventCuts.occupancyEstimator); - if (o > occGen) { - occGen = o; - } + auto itrack = atrack.template mfttrack_as(); + if (itrack.eta() < trackCuts.minEta || itrack.eta() > trackCuts.maxEta) { + continue; + } + if (gConf.cfgUseTrackSel && !isTrackSelected(itrack)) { + continue; } + nBestTrks++; } + qaregistry.fill(HIST("Events/hMultMFTvsFT0A"), nBestTrks, collision.multFT0A()); + qaregistry.fill(HIST("Events/hMultMFTvsFT0C"), nBestTrks, collision.multFT0C()); + qaregistry.fill(HIST("Events/hNPVtracksVsFT0C"), collision.multNTracksPV(), collision.multFT0C()); + qaregistry.fill(HIST("Events/hMultMFTvsFV0A"), nBestTrks, collision.multFV0A()); + qaregistry.fill(HIST("Events/hNPVtracksVsMultMFT"), collision.multNTracksPV(), nBestTrks); + } - if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtGenRecReassoc"), 1., cGen, occGen); - } else { - registry.fill(HIST("Events/EvtGenRecReassoc"), 1., occGen); + void processCorrelationwBestTracksInclusive(CollsCorr::iterator const& collision, FiltMftTracks const& tracks, soa::SmallGroups const& besttracks) + { + processCorrelationwBestTracks(collision, tracks, besttracks); + } + + PROCESS_SWITCH(DndetaMFTPbPb, processCorrelationwBestTracksInclusive, "Do correlation study based on BestCollisionsFwd3d table", false); + + int getQuadrantPhi(float phi) + { + if (phi >= Czero && phi < Cninety) { + return 0; + } + if (phi >= Cninety && phi <= ConeHeighty) { + return 1; + } + if (phi >= -ConeHeighty && phi < -Cninety) { + return 2; } + if (phi >= -Cninety && phi < Czero) { + return 3; + } + return -1; + } - for (const auto& collision : collisions) { - auto occ = getOccupancy(collision, eventCuts.occupancyEstimator); - float crec = getRecoCent(collision); + template + int getQuadrantTrack(T const& track) + { + float phi = static_cast(track.phi()) * ConeHeighty / PI; + return getQuadrantPhi(phi); + } - if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtGenRecReassoc"), 2., crec, occ); - } else { - registry.fill(HIST("Events/EvtGenRecReassoc"), 2., occ); + /// @brief process function to check MFT alignment (based on BestCollisionsFwd3d table) + template + void processAlignment(typename C::iterator const& collision, + FiltMftTracks const& /*tracks*/, + soa::SmallGroups const& besttracks, + CollBCs const& /*bcs*/ + ) + { + auto bc = collision.template foundBC_as(); + if (!isGoodEvent(collision)) { + return; + } + + if (gConf.cfgDoIR) { + initHadronicRate(bc); + float ir = !gConf.cfgIRSource.value.empty() ? rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), gConf.cfgIRSource, gConf.cfgIRCrashOnNull) * 1.e-3 : -1; + float seconds = bc.timestamp() * 1.e-3 - mMinSeconds; + if (gConf.cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate + return; } + gCurrentHadronicRate->Fill(seconds, ir); + } - if (!isGoodEvent(collision)) { + auto z = collision.posZ(); + for (auto const& atrack : besttracks) { + if (!isBestTrackSelected(atrack)) { continue; } - - if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtGenRecReassoc"), 3., crec, occ); - } else { - registry.fill(HIST("Events/EvtGenRecReassoc"), 3., occ); + auto itrack = atrack.template mfttrack_as(); + if (!isTrackSelected(itrack)) { + continue; } - if (!collision.has_mcCollision()) { + int quadrant = getQuadrantTrack(itrack); + if (quadrant < 0) { continue; } + std::get>(hAlignment[0][quadrant][0]["DCA_x_vs_z"])->Fill(z, atrack.bestDCAXY()); + } + } + + void processAlignmentInclusive(Colls::iterator const& collision, + FiltMftTracks const& tracks, + soa::SmallGroups const& besttracks, + CollBCs const& bcs) + { + processAlignment(collision, tracks, besttracks, bcs); + } + + PROCESS_SWITCH(DndetaMFTPbPb, processAlignmentInclusive, "Check MFT alignment using tracks based on BestCollisionsFwd3d table (inclusive)", false); + + Preslice compCollPerCol = o2::aod::fwdtrack::collisionId; + + /// @brief process function to check reassociation efficiency + void processReassocEfficiency(CollsMCExtra::iterator const& mcCollision, + soa::SmallGroups const& collisions, + MftTracksWCollsMC const& tracks, + aod::McParticles const& particles, + ExtBCs const& bcs) + { + if (bcs.size() == 0) { + return; + } + auto bc = bcs.begin(); + initCCDB(bc); - auto perCollisionASample = besttracks.sliceBy(perColU, collision.globalIndex()); - for (auto const& atrack : perCollisionASample) { - if (!isBestTrackSelected(atrack)) { + // At least one generated primary in MFT acceptance + TVX triggered collisions + if (gConf.cfgUseInelgt0wMFT && !isInelGt0wMft(particles)) { + return; + } + if (eventCuts.useZVtxCutMC && (std::abs(mcCollision.posZ()) >= eventCuts.maxZvtx)) { + return; + } + + const auto& nRecoColls = collisions.size(); + registry.fill(HIST("Events/hNReEffColls"), 1.f, nRecoColls); + + // Generated evets with >= 1 reco collisions + if (nRecoColls > CintZero) { + + auto maxNcontributors = -1; + auto bestCollIndex = -1; + auto crec = -1; + for (auto const& collision : collisions) { + if (!isGoodEvent(collision)) { continue; } - auto itrack = atrack.template mfttrack_as(); + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + bestCollIndex = collision.globalIndex(); + crec = getRecoCent(collision); + } + } + + registry.fill(HIST("AmbTracks/hVtxzMCrec"), mcCollision.posZ()); - if (!isTrackSelected(itrack)) { + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { continue; } - float phi = itrack.phi(); - o2::math_utils::bringTo02Pi(phi); - if (phi < kZero || TwoPI < phi) { + // Select collisions with the largest number of contributors + if (bestCollIndex != collision.globalIndex()) { continue; } - if (!itrack.has_collision()) { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 1, crec); + + if (!collision.has_mcCollision()) { continue; } - if (cfgRemoveReassigned) { - if (itrack.collisionId() != atrack.bestCollisionId()) { + + std::array dcaInfOrig; + std::array dcaInfo; + double bestDCA[2]; + auto trkPerColl = tracks.sliceBy(compCollPerCol, collision.globalIndex()); + + for (auto const& track : trkPerColl) { + dcaInfOrig[0] = 999.f; // original DCAx from propagation + dcaInfOrig[1] = 999.f; // original DCAy from propagation + dcaInfOrig[2] = 999.f; // original DCAz from propagation + dcaInfo[0] = 999.f; // calcualted DCAxy + dcaInfo[1] = 999.f; // calculated DCAz - same as original + bestDCA[0] = 999.f; // minimal DCAxy + bestDCA[1] = 999.f; // minimal DCAz + + if (!isTrackSelected(track)) { continue; } - } - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestRec"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestRec"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - } + auto bestCol = track.has_collision() ? track.collisionId() : -1; + uint index = uint(track.collisionId() >= 0); + bool isAmbiguous = (track.compatibleCollIds().size() > 1); - if (itrack.has_mcParticle()) { - auto particle = itrack.template mcParticle_as(); + if (!track.has_mcParticle()) { + continue; + } + auto particle = track.mcParticle_as(); if (!isChrgParticle(particle.pdgCode())) { continue; } if (particle.eta() <= trackCuts.minEta || particle.eta() >= trackCuts.maxEta) { continue; } - if (cfgUseParticleSel && !isParticleSelected(particle)) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } - const auto dcaXtruth(particle.vx() - particle.mcCollision().posX()); - const auto dcaYtruth(particle.vy() - particle.mcCollision().posY()); - const auto dcaZtruth(particle.vz() - particle.mcCollision().posZ()); - auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); - auto mcCollision = particle.template mcCollision_as(); - - if (eventCuts.useZDiffCut) { - if (std::abs(collision.posZ() - mcCollision.posZ()) > eventCuts.maxZvtxDiff) { + if (gConf.cfgRemoveReassigned) { + if (track.compatibleCollIds().empty() || (track.compatibleCollIds().size() == 1 && bestCol == track.compatibleCollIds()[0])) { continue; } } - if (collision.has_mcCollision() && collision.mcCollisionId() == particle.mcCollisionId()) { - if (!particle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSec"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthSec"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenSec"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthSec"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); + int bestMCCol = -1; + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, mZShift); + + if (index) { + auto mcCollision = particle.mcCollision_as(); + if (eventCuts.useZDiffCut) { + if (std::abs(collision.posZ() - mcCollision.posZ()) > eventCuts.maxZvtxDiff) { + continue; } - if (particle.getProcess() == TMCProcess::kPDecay) { // Particles from decay - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSecWeak"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenSecWeak"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); + } + + if (isAmbiguous) { + for (const auto& collIdx : track.compatibleCollIds()) { + auto ambColl = collisions.rawIteratorAt(collIdx); + if (!ambColl.has_mcCollision()) { + continue; } - } else { // Particles from the material - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSecMat"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenSecMat"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); + + trackPar.propagateToDCAhelix(bZ, {ambColl.posX(), ambColl.posY(), ambColl.posZ()}, dcaInfOrig); + + if (gConf.cfgDCAtype == 0) { + dcaInfo[0] = dcaInfOrig[0]; + } else if (gConf.cfgDCAtype == 1) { + dcaInfo[0] = dcaInfOrig[1]; + } else if (gConf.cfgDCAtype == 2) { + dcaInfo[0] = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); } + dcaInfo[1] = dcaInfOrig[2]; + + if ((std::abs(dcaInfo[0]) < std::abs(bestDCA[0])) && (std::abs(dcaInfo[1]) < std::abs(bestDCA[1]))) { + bestCol = ambColl.globalIndex(); + bestMCCol = ambColl.mcCollisionId(); + bestDCA[0] = dcaInfo[0]; + bestDCA[1] = dcaInfo[1]; + } + + // LOGP(info, "-> track {}: {}", track.globalIndex(), dcaInfo[0]); + registry.fill(HIST("AmbTracks/DCAXY"), dcaInfo[0]); + registry.fill(HIST("AmbTracks/DCAZ"), dcaInfo[1]); } - } else { // Primaries - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); - } - } - } else { // Wrong collision - if (!particle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthSecWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); + + registry.fill(HIST("AmbTracks/DCAXYBest"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBest"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestGen"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestGenDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("AmbTracks/DCAXYBestPrim"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestPrim"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestGenPrim"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestPrimDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); } - } else { // Primaries - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestGenTruthPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth, crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestGenPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - registry.fill(HIST("Tracks/THnDCAxyBestGenTruthPrimWrongColl"), particle.pt(), particle.eta(), mcCollision.posZ(), dcaXYtruth, dcaZtruth); + + auto mcCollID = particle.mcCollisionId(); + registry.fill(HIST("Events/Centrality/ReEffStatus"), 2, crec); + + if (!track.has_collision()) { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 4, crec); + if (bestMCCol == mcCollID) // correctly assigned to bestCol + { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 6, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrue"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrue"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrue"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } else { + registry.fill(HIST("AmbTracks/DCAXYBestFalse"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestFalse"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestFalse"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestFalseDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } + } else if (track.collisionId() != bestCol) { // reassgined + auto collOrig = collisions.rawIteratorAt(track.collisionId()); + registry.fill(HIST("Events/Centrality/ReEffStatus"), 3, crec); + if (bestMCCol == mcCollID) // correctly reassigned + { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 6, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrue"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrue"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrue"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } else { // uncorrectly reassigned + registry.fill(HIST("AmbTracks/DCAXYBestFalse"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestFalse"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestFalse"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestFalseDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } + if (collOrig.mcCollisionId() == mcCollID) { // initially correctly assigned + registry.fill(HIST("Events/Centrality/ReEffStatus"), 5, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrueOrigReAssoc"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrueOrigReAssoc"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrueOrigReAssoc"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueOrigReAssocDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } + } else { // not reassigned - the track has a collision and track.collisionId() == bestCol + if (track.collisionId() != bestCol) { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 7, crec); + // LOGP(info, "-> track id {}: bestCollid {}", track.collisionId(), bestCol); + } + registry.fill(HIST("Events/Centrality/ReEffStatus"), 8, crec); + if (bestMCCol == mcCollID) // correctly assigned + { + registry.fill(HIST("Events/Centrality/ReEffStatus"), 9, crec); + registry.fill(HIST("AmbTracks/DCAXYBestTrueOrigAssoc"), bestDCA[0]); + registry.fill(HIST("AmbTracks/DCAZBestTrueOrigAssoc"), bestDCA[1]); + registry.fill(HIST("AmbTracks/Centrality/THnDCAxyBestTrueOrigAssoc"), particle.pt(), particle.eta(), mcCollision.posZ(), bestDCA[0], bestDCA[1], crec); + registry.fill(HIST("AmbTracks/BestTrueOrigAssocDxyz"), collision.posX() - mcCollision.posX(), collision.posY() - mcCollision.posY(), collision.posZ() - mcCollision.posZ(), bestDCA[0], bestDCA[1]); + } } } } - } else { - LOGP(debug, "No MC particle for ambiguous itrack, skip..."); - if constexpr (has_reco_cent) { - registry.fill(HIST("Tracks/Centrality/THnDCAxyBestRecFake"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ(), crec); - } else { - registry.fill(HIST("Tracks/THnDCAxyBestRecFake"), itrack.pt(), itrack.eta(), collision.posZ(), atrack.bestDCAXY(), atrack.bestDCAZ()); - } } } } } - void processDCAReassocMcInclusive(soa::Join const& collisions, - aod::McCollisions const& mccollisions, - aod::McParticles const& particles, - BestTracksMC const& besttracks, - FiltMcMftTracks const& tracks) + PROCESS_SWITCH(DndetaMFTPbPb, processReassocEfficiency, "Process collision-reassociation efficiency based on track propagation DCA 3D (in FT0C centrality bins)", false); + + /// @brief process function to calculate signal loss based on MC + void processEventAndSignalLossCentFT0C(CollsMCExtra::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + FiltParticles const& particles) { - processDCAReassocMc(collisions, mccollisions, particles, besttracks, tracks); - } + registry.fill(HIST("Events/Centrality/hNRecCollsSigEvtLoss"), 1.f, collisions.size()); + + if (gConf.cfgUseInelgt0 && !mcCollision.isInelGt0()) { + return; + } + if (eventCuts.useZVtxCutMC && (std::abs(mcCollision.posZ()) >= eventCuts.maxZvtx)) { + return; + } - PROCESS_SWITCH(DndetaMFTPbPb, processDCAReassocMcInclusive, "Process MC DCA checks using re-association information based on BestCollisionsFwd3d table (Inclusive)", false); + bool gtZeroColl = false; + auto maxNcontributors = -1; + auto centrality = -1; + for (auto const& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + if (std::abs(collision.posZ()) >= eventCuts.maxZvtx) { + continue; + } + if (maxNcontributors < collision.numContrib()) { + maxNcontributors = collision.numContrib(); + centrality = getRecoCent(collision); + } + gtZeroColl = true; + } - void processDCAReassocMcCentFT0C(soa::Join const& collisions, - aod::McCollisions const& mccollisions, - aod::McParticles const& particles, - BestTracksMC const& besttracks, - FiltMcMftTracks const& tracks) - { - processDCAReassocMc(collisions, mccollisions, particles, besttracks, tracks); - } + auto perCollMCsample = mcSample->sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + auto multMCNParticlesEtaMFT = countPart(perCollMCsample); - PROCESS_SWITCH(DndetaMFTPbPb, processDCAReassocMcCentFT0C, "Process MC DCA checks using re-association information based on BestCollisionsFwd3d table (in FT0C centrality bins)", false); + registry.fill(HIST("Events/Centrality/EvtSigLossStatus"), 1., centrality); + registry.fill(HIST("Events/Centrality/hMultGenVsCent"), centrality, mcCollision.multMCFT0C()); + registry.fill(HIST("Events/Centrality/hMultGenVsCentNParticlesEta05"), centrality, mcCollision.multMCNParticlesEta05()); + registry.fill(HIST("Events/Centrality/hMultGenVsCentNParticlesEtaMFT"), centrality, multMCNParticlesEtaMFT); - template - void processCorrelationwBestTracks(typename C::iterator const& collision, FiltMftTracks const& /*tracks*/, soa::SmallGroups const& besttracks) - { - if (!isGoodEvent(collision)) { - return; + if (collisions.size() == 0) { + registry.fill(HIST("Events/Centrality/EvtSigLossStatus"), 3., centrality); } - auto nBestTrks = 0; - for (auto const& atrack : besttracks) { - if (cfgUseTrackSel && !isBestTrackSelected(atrack)) { + if (gtZeroColl) { + registry.fill(HIST("Events/Centrality/EvtSigLossStatus"), 2., centrality); + registry.fill(HIST("Events/Centrality/hMultGenVsCentRec"), centrality, mcCollision.multMCFT0C()); + registry.fill(HIST("Events/Centrality/hMultGenVsCentRecNParticlesEta05"), centrality, mcCollision.multMCNParticlesEta05()); + registry.fill(HIST("Events/Centrality/hMultGenVsCentRecNParticlesEtaMFT"), centrality, multMCNParticlesEtaMFT); + } + + for (auto const& particle : particles) { + if (!isChrgParticle(particle.pdgCode())) { continue; } - auto itrack = atrack.template mfttrack_as(); - if (itrack.eta() < trackCuts.minEta || itrack.eta() > trackCuts.maxEta) { + if (gConf.cfgUseParticleSel && !isParticleSelected(particle)) { continue; } - if (cfgUseTrackSel && !isTrackSelected(itrack)) { + + float phi = particle.phi(); + o2::math_utils::bringTo02Pi(phi); + if (phi < Czero || TwoPI < phi) { continue; } - nBestTrks++; - } - qaregistry.fill(HIST("Events/hMultMFTvsFT0A"), nBestTrks, collision.multFT0A()); - qaregistry.fill(HIST("Events/hMultMFTvsFT0C"), nBestTrks, collision.multFT0C()); - qaregistry.fill(HIST("Events/hNPVtracksVsFT0C"), collision.multNTracksPV(), collision.multFT0C()); - qaregistry.fill(HIST("Events/hMultMFTvsFV0A"), nBestTrks, collision.multFV0A()); - qaregistry.fill(HIST("Events/hNPVtracksVsMultMFT"), collision.multNTracksPV(), nBestTrks); - } - void processCorrelationwBestTracksInclusive(CollsCorr::iterator const& collision, FiltMftTracks const& tracks, soa::SmallGroups const& besttracks) - { - processCorrelationwBestTracks(collision, tracks, besttracks); + registry.fill(HIST("Tracks/Centrality/EtaCentVsMultGen_t"), particle.eta(), centrality, mcCollision.multMCFT0C()); + registry.fill(HIST("Tracks/Centrality/EtaGen_t"), particle.eta(), centrality); + + if (gtZeroColl) { + float phi = particle.phi(); + o2::math_utils::bringTo02Pi(phi); + if (phi < Czero || TwoPI < phi) { + continue; + } + registry.fill(HIST("Tracks/Centrality/EtaCentVsMultGen"), particle.eta(), centrality, mcCollision.multMCFT0C()); + registry.fill(HIST("Tracks/Centrality/EtaGen"), particle.eta(), centrality); + } + } } - PROCESS_SWITCH(DndetaMFTPbPb, processCorrelationwBestTracksInclusive, "Do correlation study based on BestCollisionsFwd3d table", false); + PROCESS_SWITCH(DndetaMFTPbPb, processEventAndSignalLossCentFT0C, "Signal/event loss based on MC (in FT0C centrality bins)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGMM/Mult/Tasks/effpt-mft.cxx b/PWGMM/Mult/Tasks/effpt-mft.cxx index 2d3a9919922..c34dea1def2 100644 --- a/PWGMM/Mult/Tasks/effpt-mft.cxx +++ b/PWGMM/Mult/Tasks/effpt-mft.cxx @@ -9,25 +9,26 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include "Framework/Configurable.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RuntimeError.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "ReconstructionDataFormats/GlobalTrackID.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "TDatabasePDG.h" -#include "MathUtils/Utils.h" #include "Index.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -219,9 +220,9 @@ struct EffPtMFT { registry.fill(HIST("TracksPhiEtaGenDuplicates"), particle.phi(), particle.eta()); } } // the particle has a track - } // loop on particlesI - } // loop on collisions - } // end of processTrackEfficiencyIndexed + } // loop on particlesI + } // loop on collisions + } // end of processTrackEfficiencyIndexed PROCESS_SWITCH(EffPtMFT, processTrackEfficiencyIndexed, "Calculate tracking efficiency vs pt (indexed)", false); }; diff --git a/PWGMM/Mult/Tasks/flatenicityFV0.cxx b/PWGMM/Mult/Tasks/flatenicityFV0.cxx index 3a403d9ea1b..0c7c3565676 100644 --- a/PWGMM/Mult/Tasks/flatenicityFV0.cxx +++ b/PWGMM/Mult/Tasks/flatenicityFV0.cxx @@ -8,24 +8,32 @@ // 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 "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" - -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/Tasks/flattenicty-chrg.cxx b/PWGMM/Mult/Tasks/flattenicty-chrg.cxx index fbfa4ab578d..2f84c6603bb 100644 --- a/PWGMM/Mult/Tasks/flattenicty-chrg.cxx +++ b/PWGMM/Mult/Tasks/flattenicty-chrg.cxx @@ -17,28 +17,37 @@ // // \since 2024 +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include #include +#include +#include #include -#include #include -#include "EventFiltering/filterTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "DataFormatsFT0/Digit.h" -#include "ReconstructionDataFormats/Track.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/Tasks/heavy-ion-mult.cxx b/PWGMM/Mult/Tasks/heavy-ion-mult.cxx index 9d8fdf30a2a..d281fb37ac7 100644 --- a/PWGMM/Mult/Tasks/heavy-ion-mult.cxx +++ b/PWGMM/Mult/Tasks/heavy-ion-mult.cxx @@ -18,38 +18,42 @@ // 3. https://github.com/AliceO2Group/O2Physics/blob/master/PWGMM/Mult/Tasks/puremc-dndeta.cxx // 4. O2 analysis tutorial: https://indico.cern.ch/event/1267433/ -#include "Index.h" -#include "bestCollisionTable.h" - #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include +#include +#include + +#include +#include #include +#include #include -#include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGMM/Mult/Tasks/mcdata_split_test.cxx b/PWGMM/Mult/Tasks/mcdata_split_test.cxx index 5d5194be4be..32f85d3e946 100644 --- a/PWGMM/Mult/Tasks/mcdata_split_test.cxx +++ b/PWGMM/Mult/Tasks/mcdata_split_test.cxx @@ -13,20 +13,24 @@ /// /// \author hhesouno -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" - -#include "ReconstructionDataFormats/GlobalTrackID.h" - #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGMM/Mult/Tasks/mftReassociationValidation.cxx b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx new file mode 100644 index 00000000000..31e8e78df72 --- /dev/null +++ b/PWGMM/Mult/Tasks/mftReassociationValidation.cxx @@ -0,0 +1,1613 @@ +// 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 mftReassociationValidation.cxx +/// \brief validation task for MFT DCAxy and DCAxyz reassociation +/// \author Alexian Lejeune , Czech Technical University in Prague + +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod::rctsel; +using namespace o2::aod::track; +using namespace o2::constants::math; +using namespace o2::framework; +using namespace o2::framework::expressions; + +enum Reassociation2dMftTracks { + AllAmbiguousTracksAfterTrackSelectionsFor2d = 0, + NotReassociated2dMftTracks, + Reassociated2dMftTracks, + NReassociation2dMftTracksSteps +}; + +enum Reassociation3dMftTracks { + AllAmbiguousTracksAfterTrackSelectionsFor3d = 0, + NotReassociated3dMftTracks, + Reassociated3dMftTracks, + NReassociation3dMftTracksSteps +}; + +enum MatchedToTrueCollisionStep { + AllTracks = 0, + IsNotMatchedToTrueCollision, + IsMatchedToTrueCollision, + NMatchedToTrueCollisionSteps +}; + +enum DataType { + Data, + Mc +}; + +enum SpecificEventSelectionStep { + AllEventsPrecise = 0, + HasMcCollision, + IsNotSplitVertex, + IsSel8, + IsNoSameBunchPileup, + IsGoodItsLayersAll, + IsGoodZvtxFT0vsPV, + IsNoCollInRofStandard, + IsNoCollInRofStrict, + IsNoCollInTimeRangeStandard, + IsNoCollInTimeRangeStrict, + IsNoHighMultCollInPrevRof, + IsRctFlagChecked, + IsWithinZvtxWindow, + NSpecificEventSelectionSteps +}; + +enum SpecificTrackSelectionStep { + AllTracksPrecise = 0, + IsTrueTrack, + AfterOrphanCut, + AfterEtaCut, + AfterClusterCut, + AfterPtCut, + AfterDcaXYCut, + AfterDcaZCut, + IsCATrack, + IsLTFTrack, + HasMcParticle, + NSpecificTrackSelectionSteps +}; + +enum TrackAmbiguityCheckStep { + AllTracksCheck = 0, + IsAmbDegreeEqualToCompatibleCollIdsSize, + NTrackAmbiguityCheckSteps +}; + +enum MonteCarloEventSelectionStep { + AllMonteCarloEvents = 0, + MonteCarloEventsAfterEventSelection, + HasMonteCarloCollision, + HasNotMonteCarloCollision, + NMonteCarloEventSelectionSteps +}; + +enum MonteCarloTrackSelectionStep { + AllMonteCarloTracks = 0, + MonteCarloTracksAfterTrackSelection, + HasMonteCarloParticle, + HasNotMonteCarloParticle, + NMonteCarloTrackSelectionSteps +}; + +enum MftTrackAmbiguityStep { + AllMftTracks = 0, + AfterTrackSelection, + NumberOfAmbiguousTracks, + NumberOfNonAmbiguousTracks, + NMftAmbiguitySteps +}; + +enum MftAmbiguousAndMatchedToTrueCollisionStep { + IsAmbiguous = 0, + IsAmbiguousAndMatchedToTrueCollision, + IsAmbiguousAndNotMatchedToTrueCollision, + NMftAmbiguousAndMatchedToTrueCollisionSteps +}; + +enum MftNonAmbiguousAndMatchedToTrueCollisionStep { + IsNonAmbiguous = 0, + IsNonAmbiguousAndMatchedToTrueCollision, + IsNonAmbiguousAndNotMatchedToTrueCollision, + NMftNonAmbiguousAndMatchedToTrueCollisionSteps +}; + +enum Mft2dReassociatedAndMatchedToTrueCollisionStep { + Is2dReassociated = 0, + Is2dReassociatedAndMatchedToTrueCollision, + Is2dReassociatedAndNotMatchedToTrueCollision, + NMft2dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum Mft3dReassociatedAndMatchedToTrueCollisionStep { + Is3dReassociated = 0, + Is3dReassociatedAndMatchedToTrueCollision, + Is3dReassociatedAndNotMatchedToTrueCollision, + NMft3dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum MftNot2dReassociatedAndMatchedToTrueCollisionStep { + IsNot2dReassociated = 0, + IsNot2dReassociatedAndMatchedToTrueCollision, + IsNot2dReassociatedAndNotMatchedToTrueCollision, + NMftNot2dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum MftNot3dReassociatedAndMatchedToTrueCollisionStep { + IsNot3dReassociated = 0, + IsNot3dReassociatedAndMatchedToTrueCollision, + IsNot3dReassociatedAndNotMatchedToTrueCollision, + NMftNot3dReassociatedAndMatchedToTrueCollisionSteps +}; + +enum MftIsTrueCollisionAmongCompatibleCollisionsStep { + AllWronglyAssociatedTracks = 0, + IsTrueCollisionAmongCompatibleCollisions, + IsNotTrueCollisionAmongCompatibleCollisions, + NMftIsTrueCollisionAmongCompatibleCollisionsSteps +}; + +enum MftTrackSelectionStep { + NoSelection = 0, + Eta, + Cluster, + Pt, + IsCA, + IsLTF, + NMftTrackSelectionSteps +}; + +enum MultiplicityEstimators { + MultNTracksPV = 0, + MultNumContrib, + MultFT0C, + MultFT0M +}; + +static constexpr std::string_view WhatDataType[] = {"Data/", "MC/"}; +static constexpr std::string_view WhatMultiplicityEstimator[] = {"multNTracksPV", "multNumContrib", "multFT0C", "multFT0M"}; +std::unordered_map recoVtxX; +std::unordered_map recoVtxY; +std::unordered_map recoVtxZ; +std::unordered_map recoMcCollisionId; +std::unordered_map recoMcCollBestCollisionIndex; + +struct MftReassociationValidation { + + struct : ConfigurableGroup { + std::string prefix = "ConfigCcdb_group"; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + Configurable noLaterThan{"noLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; + } configCcdb; + + // configurables for processing options + + struct : ConfigurableGroup { + std::string prefix = "ConfigTask_group"; + Configurable centralityBinsForMc{"centralityBinsForMc", false, "falsce = OFF, true = ON for data like multiplicity/centrality bins for MC steps"}; + Configurable keepOnlyPhysicalPrimary{"keepOnlyPhysicalPrimary", true, "Keep only physical primary particles"}; + Configurable keepOnlySecondaries{"keepOnlySecondaries", false, "Keep only secondary particles"}; + Configurable cfgApplyZShiftFromCCDB{"cfgApplyZShiftFromCCDB", true, "flag to apply z shift from CCDB"}; + Configurable cfgZShiftPath{"cfgZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z shift to apply to forward tracks"}; + Configurable cfgManualZShift{"cfgManualZShift", 0.0f, "manual z-shift for propagation of global muon to PV"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + } configTask; + + // configurables for collisions + struct : ConfigurableGroup { + std::string prefix = "ConfigCollision_group"; + Configurable isApplyGoodItsLayersAll{"isApplyGoodItsLayersAll", false, "Enable GoodITSLayersAll"}; + Configurable isApplyGoodZvtxFT0vsPV{"isApplyGoodZvtxFT0vsPV", false, "Enable GoodZvtxFT0vsPV cut"}; + Configurable isApplySameBunchPileup{"isApplySameBunchPileup", false, "Enable SameBunchPileup cut"}; + Configurable maxMultiplicity{"maxMultiplicity", 300, "maximum multiplicity selection for collision"}; + Configurable minMultiplicity{"minMultiplicity", 0, "minimum multiplicity selection for collision"}; + Configurable multiplicityEstimator{"multiplicityEstimator", 0, "0: multNTracksPV, 1: numContrib, 2: multFT0C, 3: multFT0M, 4: centFT0C, 5: centFT0CVariants1s, 6: centFT0M, 7: centFV0A, 8: centNTracksPV, 9: centNGlobal, 10: centMFT"}; + Configurable isApplyNoCollInTimeRangeStrict{"isApplyNoCollInTimeRangeStrict", false, ""}; + Configurable isApplyNoCollInTimeRangeStandard{"isApplyNoCollInTimeRangeStandard", false, ""}; + Configurable isApplyNoCollInRofStrict{"isApplyNoCollInRofStrict", false, ""}; + Configurable isApplyNoCollInRofStandard{"isApplyNoCollInRofStandard", false, ""}; + Configurable isApplyNoHighMultCollInPrevRof{"isApplyNoHighMultCollInPrevRof", false, ""}; + Configurable zVertexMaxInFilter{"zVertexMaxInFilter", 30.0f, "Accepted z-vertex range"}; + Configurable zVertexMax{"zVertexMax", 10.0f, "Accepted z-vertex range"}; + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable requireCorrelationAnalysisRCTFlagChecker{"requireCorrelationAnalysisRCTFlagChecker", false, "Check event quality in run condition table for correlation analysis"}; + Configurable requireMcCollBestCollIndex{"requireMcCollBestCollIndex", false, "check for split vertices"}; + Configurable setRCTFlagCheckerLabel{"setRCTFlagCheckerLabel", "CBT_muon_global", "Evt sel: RCT flag checker label"}; + Configurable requireRCTFlagCheckerLimitAcceptanceAsBad{"requireRCTFlagCheckerLimitAcceptanceAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + Configurable requireZDCCheck{"requireZDCCheck", false, "Evt sel: RCT flag checker ZDC check"}; + } configCollision; + + // configurables for MFT tracks + struct : ConfigurableGroup { + std::string prefix = "ConfigMft_group"; + Configurable cutBestCollisionId{"cutBestCollisionId", 0, "cut on the best collision Id used in a filter"}; + Configurable cutFakeTracks{"cutFakeTracks", false, "if true, cut fake tracks using McMask"}; + Configurable cutOrphanTracksExplicitly{"cutOrphanTracksExplicitly", false, "if true, cut orphan tracks explicitly"}; + Configurable cutOnDcaXY{"cutOnDcaXY", false, "if true, cut on DCA XY"}; + Configurable cutOnDcaZ{"cutOnDcaZ", false, "if true, cut on DCA Z"}; + Configurable dcaXYMax{"dcaXYMax", 2.0f, "Maximum value for DCA XY"}; + Configurable dcaZMax{"dcaZMax", 10.0f, "Maximum value for DCA Z"}; + Configurable etaMftTrackMax{"etaMftTrackMax", -2.4f, "Maximum value for the eta of MFT tracks when used in cut function"}; + Configurable etaMftTrackMin{"etaMftTrackMin", -3.36f, "Minimum value for the eta of MFT tracks when used in cut function"}; + Configurable etaMftTrackMaxFilter{"etaMftTrackMaxFilter", -2.0f, "Maximum value for the eta of MFT tracks when used in filter"}; + Configurable etaMftTrackMinFilter{"etaMftTrackMinFilter", -3.9f, "Minimum value for the eta of MFT tracks when used in filter"}; + Configurable mftMaxDCAxy{"mftMaxDCAxy", 2.0f, "Cut on dcaXY for MFT tracks"}; + Configurable mftMaxDCAz{"mftMaxDCAz", 2.0f, "Cut on dcaZ for MFT tracks"}; + Configurable nClustersMftTrack{"nClustersMftTrack", 5, "Minimum number of clusters for the reconstruction of MFT tracks"}; + Configurable ptMftTrackMax{"ptMftTrackMax", 10.0f, "max value of MFT tracks pT when used in cut function"}; + Configurable ptMftTrackMin{"ptMftTrackMin", 0.f, "min value of MFT tracks pT when used in cut function"}; + Configurable useMftPtCut{"useMftPtCut", false, "if true, use the Mft pt function cut"}; + Configurable useOnlyCATracks{"useOnlyCATracks", false, "if true, use strictly MFT tracks reconstructed with CA algo."}; + Configurable useOnlyLTFTracks{"useOnlyLTFTracks", false, "if true, use strictly MFT tracks reconstructed with LTF algo."}; + } configMft; + + float mZShift = 0; // z-vertex shift + float bZ = 0; // Magnetic field for MFT + static constexpr double CcenterMFT[3] = {0, 0, -61.4}; // Field at center of MFT + SliceCache cache; + Service pdg; + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + o2::parameters::GRPMagField* grpmag = nullptr; + RCTFlagsChecker rctChecker; + RCTFlagsChecker correlationAnalysisRctChecker{kFT0Bad, kITSBad, kTPCBadTracking, kTPCBadPID, kMFTBad}; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNonAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiff2dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNot2dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiff3dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNot3dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hZVtxDiffNotMatchedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNonAmbiguousTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDca2dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNot2dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDca3dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNot3dReassociatedTracks; + std::array, MatchedToTrueCollisionStep::NMatchedToTrueCollisionSteps> hDcaNotMatchedTracks; + + // ========================= + // using declarations : DATA + // ========================= + + using FilteredCollisionsWSelMult = soa::Filtered>; + using FilteredMftTracks = soa::Filtered; + using FilteredMftTracksWColls = soa::Filtered>; + + // ========================= + // using declarations : MONTE-CARLO + // ========================= + + using FilteredCollisionsWSelMultMcLabels = soa::Filtered>; + using FilteredMftTracksWCollsMcLabels = soa::Filtered>; + // using MftReasso3dTracksWCollsMcLabels = soa::Join; + // using MftReasso2dTracksWCollsMcLabels = soa::Join; + // using MftReasso2dTracksWCollsMcLabels = soa::Join; + // using MftReasso3dTracksWCollsMcLabels = soa::Join; + using FilteredMcParticles = soa::Filtered; + + // ========================= + // Filters & partitions : DATA + // ========================= + + // Collision filters + Filter collisionVtxZFilter = nabs(aod::collision::posZ) < configCollision.zVertexMaxInFilter; + + Filter mftTrackEtaFilter = ((aod::fwdtrack::eta < configMft.etaMftTrackMaxFilter) && (aod::fwdtrack::eta > configMft.etaMftTrackMinFilter)); + + Filter mftTrackCollisionIdFilter = (aod::fwdtrack::bestCollisionId >= 0); + // Filter mftTrackDcaXYFilter = (nabs(aod::fwdtrack::bestDCAXY) < configMft.mftMaxDCAxy); + // Filter mftTrackDcaZFilter = (nabs(aod::fwdtrack::bestDCAZ) < configMft.mftMaxDCAz); + + // ========================= + // Filters & partitions : MONTE-CARLO + // ========================= + + Filter mcParticleEtaFilter = (aod::mcparticle::eta < configMft.etaMftTrackMaxFilter) && (aod::mcparticle::eta > configMft.etaMftTrackMinFilter); + + Partition mcParticlesSample = (aod::mcparticle::eta < configMft.etaMftTrackMaxFilter) && (aod::mcparticle::eta > configMft.etaMftTrackMinFilter); + + // ========================= + // Preslice : DATA + // ========================= + + Preslice perColMftTracks = o2::aod::fwdtrack::collisionId; + + struct : ConfigurableGroup { + std::string prefix = "ConfigAxis_group"; + ConfigurableAxis axisEta{"axisEta", {48, -4, -2}, "eta axis for MFT histograms"}; + ConfigurableAxis axisDcaX{"axisDcaX", {800, -1., 1.}, "DCAx binning (cm)"}; + ConfigurableAxis axisDcaY{"axisDcaY", {800, -1., 1.}, "DCAy binning (cm)"}; + ConfigurableAxis axisDcaZ{"axisDcaZ", {800, -1., 1.}, "DCAz binning (cm)"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity axis for histograms"}; + ConfigurableAxis axisPhi{"axisPhi", {72, 0, TwoPI}, "phi axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {72, 0, 36}, "pt axis for histograms"}; + ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis axisVertexEfficiency{"axisVertexEfficiency", {1, -10, 10}, "vertex axis for efficiency histograms"}; + } configAxis; + + HistogramRegistry registry{"registry"}; + + template + void addMftHistograms() + { + registry.add(Form("%shAmbiguityOfMftTracks", WhatDataType[DataType].data()), "hAmbiguityOfMftTracks", {HistType::kTH1D, {{MftTrackAmbiguityStep::NMftAmbiguitySteps, -0.5, +MftTrackAmbiguityStep::NMftAmbiguitySteps - 0.5}}}); + std::string labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NMftAmbiguitySteps]; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::AllMftTracks] = "all MFT tracks"; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::AfterTrackSelection] = "MFT tracks after selection"; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NumberOfAmbiguousTracks] = "how much tracks are ambigous"; + labelsAmbiguityOfMftTracks[MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks] = "how much tracks are non-ambiguous"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hAmbiguityOfMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftTrackAmbiguityStep::NMftAmbiguitySteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hAmbiguityOfMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsAmbiguityOfMftTracks[iBin].data()); + } + + registry.add(Form("%shMftTracksSelection", WhatDataType[DataType].data()), "hMftTracksSelection", {HistType::kTH1D, {{MftTrackSelectionStep::NMftTrackSelectionSteps, -0.5, +MftTrackSelectionStep::NMftTrackSelectionSteps - 0.5}}}); + std::string labelsMftTracksSelection[MftTrackSelectionStep::NMftTrackSelectionSteps]; + labelsMftTracksSelection[MftTrackSelectionStep::NoSelection] = "all MFT tracks"; + labelsMftTracksSelection[MftTrackSelectionStep::Eta] = "MFT tracks after eta selection"; + labelsMftTracksSelection[MftTrackSelectionStep::Cluster] = "MFT tracks after clusters selection"; + labelsMftTracksSelection[MftTrackSelectionStep::Pt] = "MFT tracks after pT selection"; + labelsMftTracksSelection[MftTrackSelectionStep::IsCA] = "MFT tracks reconstructed with CA"; + labelsMftTracksSelection[MftTrackSelectionStep::IsLTF] = "MFT tracks reconstructed with LTF"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hMftTracksSelection"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftTrackSelectionStep::NMftTrackSelectionSteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hMftTracksSelection"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftTracksSelection[iBin].data()); + } + + registry.add(Form("%shReassociation2dMftTracks", WhatDataType[DataType].data()), "hReassociation2dMftTracks", {HistType::kTH1D, {{Reassociation2dMftTracks::NReassociation2dMftTracksSteps, -0.5, +Reassociation2dMftTracks::NReassociation2dMftTracksSteps - 0.5}}}); + std::string labelsReassociation2dMftTracks[Reassociation2dMftTracks::NReassociation2dMftTracksSteps]; + labelsReassociation2dMftTracks[Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d] = "Ambiguous MFT tracks after track selection"; + labelsReassociation2dMftTracks[Reassociation2dMftTracks::NotReassociated2dMftTracks] = "Not reassociated MFT tracks by DCAxy method"; + labelsReassociation2dMftTracks[Reassociation2dMftTracks::Reassociated2dMftTracks] = "Reassociated MFT tracks by DCAxy method"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation2dMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < Reassociation2dMftTracks::NReassociation2dMftTracksSteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation2dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation2dMftTracks[iBin].data()); + } + + registry.add(Form("%shReassociation3dMftTracks", WhatDataType[DataType].data()), "hReassociation3dMftTracks", {HistType::kTH1D, {{Reassociation3dMftTracks::NReassociation3dMftTracksSteps, -0.5, +Reassociation3dMftTracks::NReassociation3dMftTracksSteps - 0.5}}}); + std::string labelsReassociation3dMftTracks[Reassociation3dMftTracks::NReassociation3dMftTracksSteps]; + labelsReassociation3dMftTracks[Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d] = "Ambiguous MFT tracks after track selection"; + labelsReassociation3dMftTracks[Reassociation3dMftTracks::NotReassociated3dMftTracks] = "Not reassociated MFT tracks by DCAxyz method"; + labelsReassociation3dMftTracks[Reassociation3dMftTracks::Reassociated3dMftTracks] = "Reassociated MFT tracks by DCAxyz method"; + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation3dMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < Reassociation3dMftTracks::NReassociation3dMftTracksSteps; iBin++) { + registry.get(HIST(WhatDataType[DataType]) + HIST("hReassociation3dMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsReassociation3dMftTracks[iBin].data()); + } + } + + void addMftMonteCarloHistograms() + { + // AmbiguousTracks ZVtxDiff dist. (contains matched to true and not matched to true collision) + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + // AmbiguousTracks NOT matched to true collisions ZVtxDiff dist. + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + // AmbiguousTracks matched to true collisions ZVtxDiff dist. + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNonAmbiguousTrackMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiff2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiff2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiff2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiff3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiff3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiff3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hZVtxDiffNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hZVtxDiffNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/hZVtxDiffNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hZVtxDiffNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hZVtxDiffNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{X}_{vtx}^{reco}#minus#it{X}_{vtx}^{gen} (cm);#it{Y}_{vtx}^{reco}#minus#it{Y}_{vtx}^{gen} (cm);#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaY, configAxis.axisDcaZ}); + + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaNonAmbiguousTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaNonAmbiguousTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaNonAmbiguousTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDca2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDca2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDca2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaNot2dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaNot2dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaNot2dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{XY}^{gen} (cm);", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaX}); + + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDca3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDca3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDca3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks] = registry.add("MC/hDcaNot3dReassociatedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision] = registry.add("MC/hDcaNot3dReassociatedTracksNotMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision] = registry.add("MC/hDcaNot3dReassociatedTracksMatchedToTrueCollision", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = registry.add("MC/hDcaNotMatchedTracks", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hDcaNotMatchedTracksWithCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = registry.add("MC/hDcaNotMatchedTracksWithoutCollAmongCompatible", ";#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};DCA_{XY}^{reco} (cm); DCA_{Z}^{reco} (cm); DCA_{XY}^{gen} (cm); DCA_{Z}^{gen} (cm)", HistType::kTHnSparseF, {configAxis.axisPt, configAxis.axisEta, configAxis.axisDcaX, configAxis.axisDcaZ, configAxis.axisDcaX, configAxis.axisDcaZ}); + + registry.add("MC/hIsAmbiguousTrackMatchedToTrueCollision", "hIsAmbiguousTrackMatchedToTrueCollision", {HistType::kTH1D, {{MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps]; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous] = "number of MFT ambiguous tracks"; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision] = "number of MFT ambiguous tracks matched to true collision"; + labelsMftAmbiguousAndMatchedToTrueCollisionStep[MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision] = "number of MFT ambiguous tracks NOT matched to true collision"; + registry.get(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftAmbiguousAndMatchedToTrueCollisionStep::NMftAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIsNonAmbiguousTrackMatchedToTrueCollision", "hIsNonAmbiguousTrackMatchedToTrue", {HistType::kTH1D, {{MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps, -0.5, +MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps]; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous] = "number of MFT Non ambiguous tracks"; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision] = "number of MFT Non ambiguous tracks matched to true collision"; + labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision] = "number of MFT Non ambiguous tracks NOT matched to true collision"; + registry.get(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNonAmbiguousAndMatchedToTrueCollisionStep::NMftNonAmbiguousAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNonAmbiguousAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIs2dReassociatedAndMatchedToTrueCollision", "Is2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated] = "number of MFT 2d reassociated tracks"; + labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision] = "number of MFT 2d reassociated tracks matched to true collision"; + labelsMft2dReassociatedAndMatchedToTrueCollisionStep[Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision] = "number of MFT 2d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < Mft2dReassociatedAndMatchedToTrueCollisionStep::NMft2dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIsNot2dReassociatedAndMatchedToTrueCollision", "IsNot2dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated] = "number of MFT NOT 2d reassociated tracks"; + labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision] = "number of MFT NOT 2d reassociated tracks matched to true collision"; + labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision] = "number of MFT NOT 2d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNot2dReassociatedAndMatchedToTrueCollisionStep::NMftNot2dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot2dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIs3dReassociatedAndMatchedToTrueCollision", "Is3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated] = "number of MFT 3d reassociated tracks"; + labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision] = "number of MFT 3d reassociated tracks matched to true collision"; + labelsMft3dReassociatedAndMatchedToTrueCollisionStep[Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision] = "number of MFT 3d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < Mft3dReassociatedAndMatchedToTrueCollisionStep::NMft3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMft3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIsNot3dReassociatedAndMatchedToTrueCollision", "IsNot3dReassociatedAndMatchedToTrueCollision", {HistType::kTH1D, {{MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps, -0.5, +MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps - 0.5}}}); + std::string labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps]; + labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated] = "number of MFT NOT 3d reassociated tracks"; + labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision] = "number of MFT NOT 3d reassociated tracks matched to true collision"; + labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision] = "number of MFT NOT 3d reassociated tracks NOT matched to true collision"; + registry.get(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftNot3dReassociatedAndMatchedToTrueCollisionStep::NMftNot3dReassociatedAndMatchedToTrueCollisionSteps; iBin++) { + registry.get(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftNot3dReassociatedAndMatchedToTrueCollisionStep[iBin].data()); + } + + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisions", "IsTrueCollisionAmongCompatibleCollisions", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + registry.add("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", "hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated", {HistType::kTH1D, {{MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps, -0.5, +MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps - 0.5}}}); + std::string labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps]; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks] = "number of wrongly associated tracks"; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks with True Coll. among Compatible"; + labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions] = "number of MFT tracks WITHOUT True Coll. among Compatible"; + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"))->SetMinimum(0); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->SetMinimum(0); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftIsTrueCollisionAmongCompatibleCollisionsStep::NMftIsTrueCollisionAmongCompatibleCollisionsSteps; iBin++) { + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + registry.get(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftIsTrueCollisionAmongCompatibleCollisionsStep[iBin].data()); + } + } + + // ========================= + // init() + // ========================= + void init(InitContext&) + { + ccdb->setURL(configCcdb.ccdbUrl); + 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()); + rctChecker.init(configCollision.setRCTFlagCheckerLabel, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad, true); + correlationAnalysisRctChecker.init({kFT0Bad, kITSBad, kTPCBadTracking, kTPCBadPID, kMFTBad}, configCollision.requireZDCCheck, configCollision.requireRCTFlagCheckerLimitAcceptanceAsBad, true); + + // ========================= + // Event histograms + // ========================= + + registry.add("Data/hVtxZ", "v_{z} (cm)", {HistType::kTH1D, {configAxis.axisVertex}}); + // registry.add("Data/hNTracks", "", {HistType::kTH1F, {configAxis.axisMultiplicity}}); + registry.add(Form("Data/hMultiplicity_%s", WhatMultiplicityEstimator[configCollision.multiplicityEstimator].data()), "", {HistType::kTH1D, {configAxis.axisMultiplicity}}); + + registry.add("hPreciseEventCounter", "hPreciseEventCounter", {HistType::kTH1D, {{SpecificEventSelectionStep::NSpecificEventSelectionSteps, -0.5, +SpecificEventSelectionStep::NSpecificEventSelectionSteps - 0.5}}}); + std::string labels[SpecificEventSelectionStep::NSpecificEventSelectionSteps]; + labels[SpecificEventSelectionStep::AllEventsPrecise] = "all"; + labels[SpecificEventSelectionStep::HasMcCollision] = "has MC coll?"; + labels[SpecificEventSelectionStep::IsNotSplitVertex] = "Is not split vertex (BestCollisionIndex)"; + labels[SpecificEventSelectionStep::IsSel8] = "sel8"; + labels[SpecificEventSelectionStep::IsNoSameBunchPileup] = "IsNoSameBunchPileup"; + labels[SpecificEventSelectionStep::IsGoodItsLayersAll] = "IsGoodItsLayersAll"; + labels[SpecificEventSelectionStep::IsGoodZvtxFT0vsPV] = "IsGoodZvtxFT0vsPV"; + labels[SpecificEventSelectionStep::IsNoCollInRofStandard] = "IsNoCollInRofStandard"; + labels[SpecificEventSelectionStep::IsNoCollInRofStrict] = "IsNoCollInRofStrict"; + labels[SpecificEventSelectionStep::IsNoCollInTimeRangeStandard] = "IsNoCollInTimeRangeStandard"; + labels[SpecificEventSelectionStep::IsNoCollInTimeRangeStrict] = "IsNoCollInTimeRangeStrict"; + labels[SpecificEventSelectionStep::IsNoHighMultCollInPrevRof] = "IsNoHighMultCollInPrevRof"; + labels[SpecificEventSelectionStep::IsRctFlagChecked] = "IsRctFlagChecked"; + labels[SpecificEventSelectionStep::IsWithinZvtxWindow] = "IsWithinZvtxWindow"; + registry.get(HIST("hPreciseEventCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < SpecificEventSelectionStep::NSpecificEventSelectionSteps; iBin++) { + registry.get(HIST("hPreciseEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + + registry.add("MC/hPreciseTrackSelectionCounter", "hPreciseTrackSelectionCounter", {HistType::kTH1D, {{SpecificTrackSelectionStep::NSpecificTrackSelectionSteps, -0.5, +SpecificTrackSelectionStep::NSpecificTrackSelectionSteps - 0.5}}}); + std::string labelsTrackSelection[SpecificTrackSelectionStep::NSpecificTrackSelectionSteps]; + labelsTrackSelection[SpecificTrackSelectionStep::AllTracksPrecise] = "all tracks"; + labelsTrackSelection[SpecificTrackSelectionStep::IsTrueTrack] = "true tracks"; + labelsTrackSelection[SpecificTrackSelectionStep::AfterOrphanCut] = "after orphan cut"; + labelsTrackSelection[SpecificTrackSelectionStep::AfterEtaCut] = "after eta cut"; + labelsTrackSelection[SpecificTrackSelectionStep::AfterClusterCut] = "after cluster cut"; + labelsTrackSelection[SpecificTrackSelectionStep::AfterPtCut] = "after pt cut"; + labelsTrackSelection[SpecificTrackSelectionStep::AfterDcaXYCut] = "after DCA XY cut"; + labelsTrackSelection[SpecificTrackSelectionStep::AfterDcaZCut] = "after DCA Z cut"; + labelsTrackSelection[SpecificTrackSelectionStep::IsCATrack] = "is CA track"; + labelsTrackSelection[SpecificTrackSelectionStep::IsLTFTrack] = "is LTF track"; + labelsTrackSelection[SpecificTrackSelectionStep::HasMcParticle] = "has MC particle"; + registry.get(HIST("MC/hPreciseTrackSelectionCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < SpecificTrackSelectionStep::NSpecificTrackSelectionSteps; iBin++) { + registry.get(HIST("MC/hPreciseTrackSelectionCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackSelection[iBin].data()); + } + + registry.add("MC/hTrackAmbiguityCheck", "hTrackAmbiguityCheck", {HistType::kTH1D, {{TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps, -0.5, +TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps - 0.5}}}); + std::string labelsTrackAmbiguityCheck[TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps]; + labelsTrackAmbiguityCheck[TrackAmbiguityCheckStep::AllTracksCheck] = "all tracks"; + labelsTrackAmbiguityCheck[TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize] = "ambDegree == compatibleCollIds.size"; + registry.get(HIST("MC/hTrackAmbiguityCheck"))->SetMinimum(0); + + for (int iBin = 0; iBin < TrackAmbiguityCheckStep::NTrackAmbiguityCheckSteps; iBin++) { + registry.get(HIST("MC/hTrackAmbiguityCheck"))->GetXaxis()->SetBinLabel(iBin + 1, labelsTrackAmbiguityCheck[iBin].data()); + } + + registry.add("MC/hMonteCarloEventCounter", "hMonteCarloEventCounter", {HistType::kTH1D, {{MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps, -0.5, +MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps - 0.5}}}); + std::string labelsMonteCarloEvents[MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps]; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::AllMonteCarloEvents] = "all collisions"; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection] = "collisions after event selection"; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::HasMonteCarloCollision] = "has MC collision"; + labelsMonteCarloEvents[MonteCarloEventSelectionStep::HasNotMonteCarloCollision] = "has not MC collision"; + registry.get(HIST("MC/hMonteCarloEventCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < MonteCarloEventSelectionStep::NMonteCarloEventSelectionSteps; iBin++) { + registry.get(HIST("MC/hMonteCarloEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloEvents[iBin].data()); + } + + registry.add("MC/hMonteCarloTrackCounter", "hMonteCarloTrackCounter", {HistType::kTH1D, {{MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps, -0.5, +MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps - 0.5}}}); + std::string labelsMonteCarloTracks[MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps]; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::AllMonteCarloTracks] = "all tracks"; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection] = "tracks after track selection"; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::HasMonteCarloParticle] = "has MC particle"; + labelsMonteCarloTracks[MonteCarloTrackSelectionStep::HasNotMonteCarloParticle] = "has not MC particle"; + registry.get(HIST("MC/hMonteCarloTrackCounter"))->SetMinimum(0); + + for (int iBin = 0; iBin < MonteCarloTrackSelectionStep::NMonteCarloTrackSelectionSteps; iBin++) { + registry.get(HIST("MC/hMonteCarloTrackCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMonteCarloTracks[iBin].data()); + } + + // ========================= + // Process functions initialization + // ========================= + + if (doprocessData) { + addMftHistograms(); + } + + if (doprocessMcReassociated2d) { + addMftHistograms(); + addMftMonteCarloHistograms(); + } + + if (doprocessMcReassociated3d) { + addMftHistograms(); + addMftMonteCarloHistograms(); + } + + } // End of init() function + + // ========================= + // Helper functions + // ========================= + + template + float getMultiplicityEstimator(TCollision collision, bool isSameEvent) + { + switch (configCollision.multiplicityEstimator) { + case MultiplicityEstimators::MultNTracksPV: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multNTracksPV"), collision.multNTracksPV()); + } + return collision.multNTracksPV(); + case MultiplicityEstimators::MultNumContrib: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multNumContrib"), collision.numContrib()); + } + return collision.numContrib(); + case MultiplicityEstimators::MultFT0C: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multFT0C"), collision.multFT0C()); + } + return collision.multFT0C(); + case MultiplicityEstimators::MultFT0M: + if (isSameEvent) { + registry.fill(HIST("Data/hMultiplicity_multFT0M"), collision.multFT0M()); + } + return collision.multFT0M(); + default: + return collision.multNTracksPV(); + } + } + + int getMagneticField(uint64_t timestamp) + { + // Get the magnetic field + static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("/GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + template + bool isTrueCollisionAmongCompatibleCollisions(TTrack track) + { + + auto const& compatibleIds = track.compatibleCollIds(); + + // For this track, check if *any* reco collision that corresponds to its TRUE MC collision + // is present among the compatible collisions. + bool recoOfTrueInCompatible = false; + if (track.ambDegree() != 0) { + const int mcTrueCollisionId = track.mcParticle().mcCollisionId(); + // Fast membership test using compatibleCollIds() if available. + // If compatibleIds is empty, it means the table is missing or no compatible collisions were stored. + if (!compatibleIds.empty()) { + for (auto const& id : compatibleIds) { + + auto iterator = recoMcCollisionId.find(id); + + if (iterator != recoMcCollisionId.end()) { + if (iterator->second == mcTrueCollisionId) { + + recoOfTrueInCompatible = true; + return recoOfTrueInCompatible; + } + } else { + return recoOfTrueInCompatible; + } + } + } + } + return recoOfTrueInCompatible; + } + + template + void loadZVertexShiftCorrection(TBc const& bc) + { + + grpmag = ccdb->getForTimeStamp(configTask.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); + + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + bZ = field->getBz(CcenterMFT); + LOG(info) << "The field at the center of the MFT is bZ = " << bZ; + + if (configTask.cfgApplyZShiftFromCCDB) { + auto* zShift = ccdb->getForTimeStamp>(configTask.cfgZShiftPath, bc.timestamp()); + if (zShift != nullptr && !zShift->empty()) { + LOGF(info, "reading z shift %f from %s", (*zShift)[0], configTask.cfgZShiftPath.value); + mZShift = (*zShift)[0]; + } else { + LOGF(info, "z shift is not found in ccdb path %s. set to 0 cm", configTask.cfgZShiftPath.value); + mZShift = 0; + } + } else { + LOGF(info, "z shift is manually set to %f cm", configTask.cfgManualZShift.value); + mZShift = configTask.cfgManualZShift; + } + } + + // ========================= + // Cuts with functions + // ========================= + + // FIXME: Some collisions are rejected here, what causes (part of) differences with the D0 task + template + bool isAcceptedCollision(TCollision const& collision, bool fillHistograms = false) + { + + if (!collision.sel8()) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsSel8); + } + if (configCollision.isApplySameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoSameBunchPileup); + } + if (configCollision.isApplyGoodItsLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodItsLayersAll); + } + if (configCollision.isApplyGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsGoodZvtxFT0vsPV); + } + if (configCollision.isApplyNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStandard); + } + if (configCollision.isApplyNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInRofStrict); + } + if (configCollision.isApplyNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStandard); + } + if (configCollision.isApplyNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoCollInTimeRangeStrict); + } + if (configCollision.isApplyNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNoHighMultCollInPrevRof); + } + if (configCollision.requireRCTFlagChecker && !rctChecker(collision)) { + return false; + } + if (configCollision.requireCorrelationAnalysisRCTFlagChecker && !correlationAnalysisRctChecker(collision)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsRctFlagChecked); + } + if (collision.posZ() > configCollision.zVertexMax || collision.posZ() < (-configCollision.zVertexMax)) { + return false; + } + if (fillHistograms) { + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsWithinZvtxWindow); + } + + registry.fill(HIST("Data/hVtxZ"), collision.posZ()); + + return true; + } + + // TODO: Check how to put this into a Filter + // I tried to put it as a filter, but filters for normal TPC tracks also apply to MFT tracks I think + // and it seems that they are not compatible + template + bool isAcceptedMftTrack(TTrack const& mftTrack, bool fillHistograms, bool isData, float dcaXY, float dcaZ) + { + // cut on the eta of MFT tracks + if (mftTrack.eta() > configMft.etaMftTrackMax || mftTrack.eta() < configMft.etaMftTrackMin) { + return false; + } + + if (fillHistograms) { + if (isData) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Eta); + } else { + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterEtaCut); + } + } + + // cut on the number of clusters of the reconstructed MFT track + if (mftTrack.nClusters() < configMft.nClustersMftTrack) { + return false; + } + + if (fillHistograms) { + if (isData) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Cluster); + } else { + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterClusterCut); + } + } + + // cut on the pT of MFT tracks (for test purposes) + if (configMft.useMftPtCut && (mftTrack.pt() > configMft.ptMftTrackMax || mftTrack.pt() < configMft.ptMftTrackMin)) { + return false; + } + + if (fillHistograms) { + if (isData) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::Pt); + } else { + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterPtCut); + } + } + + if (configMft.cutOnDcaXY && std::abs(dcaXY) > configMft.dcaXYMax) { + return false; + } + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterDcaXYCut); + if (configMft.cutOnDcaZ && std::abs(dcaZ) > configMft.dcaZMax) { + return false; + } + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterDcaZCut); + + // cut on the track algorithm of MFT tracks + if (mftTrack.isCA()) { + if (fillHistograms) { + if (isData) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::IsCA); + } else { + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsCATrack); + } + } + + if (configMft.useOnlyLTFTracks) { + return false; + } + + } else { + if (fillHistograms) { + if (isData) { + registry.fill(HIST("Data/hMftTracksSelection"), MftTrackSelectionStep::IsLTF); + } else { + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsLTFTrack); + } + } + + if (configMft.useOnlyCATracks) { + return false; + } + } + + return true; + } + + // Cut on ambiguous MFT tracks + template + bool isAmbiguousMftTrack(TTrack const& mftTrack, bool fillHistograms) + { + if (mftTrack.ambDegree() > 1) { + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + } + return true; + if (mftTrack.ambDegree() > 1) { + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + } + return true; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + } + return false; + } + + if (fillHistograms) { + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + } + return false; + } + + //============================================================================================ + // + // PROCESS FUNCTIONS + // + //============================================================================================ + + void processData(FilteredCollisionsWSelMult::iterator const& collision, + FilteredMftTracks const& /*mftTracks*/, + soa::SmallGroups const& reassociated2dMftTracks, + aod::BCsWithTimestamps const&) + { + auto bc = collision.template bc_as(); + loadZVertexShiftCorrection(bc); + + if (!(isAcceptedCollision(collision, true))) { + return; + } + + // const auto multiplicity = getMultiplicityEstimator(collision, true); + + for (const auto& reassociated2dMftTrack : reassociated2dMftTracks) { + + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + auto templatedMftTrack = reassociated2dMftTrack.template mfttrack_as(); + + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(templatedMftTrack, mZShift); + std::array dcaInfOrig; + trackPar.propagateToDCAhelix(bZ, {collision.posX(), collision.posY(), collision.posZ()}, dcaInfOrig); + auto dcaXYoriginal = 999.f; + dcaXYoriginal = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + + if (!isAcceptedMftTrack(templatedMftTrack, false, true, dcaXYoriginal, dcaInfOrig[2])) { + continue; + } + + registry.fill(HIST("Data/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + + if (isAmbiguousMftTrack(reassociated2dMftTrack, true)) { + registry.fill(HIST("Data/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); + } + + } // end of loop over reassociated MFT tracks + + // TO-DO the same for reassociated3d (change the histograms) + } + PROCESS_SWITCH(MftReassociationValidation, processData, "Process MFT reassociation validation for DATA", false); + + void processCreateLookupTable(FilteredCollisionsWSelMultMcLabels const& collisions, soa::Join const& mcCollisions) + { + recoVtxX.clear(); + recoVtxY.clear(); + recoVtxZ.clear(); + recoMcCollisionId.clear(); + recoMcCollBestCollisionIndex.clear(); + + recoVtxX.reserve(collisions.size()); + recoVtxY.reserve(collisions.size()); + recoVtxZ.reserve(collisions.size()); + recoMcCollisionId.reserve(collisions.size()); + recoMcCollBestCollisionIndex.reserve(mcCollisions.size()); + + for (auto const& col : collisions) { + recoVtxX.emplace(col.globalIndex(), col.posX()); + recoVtxY.emplace(col.globalIndex(), col.posY()); + recoVtxZ.emplace(col.globalIndex(), col.posZ()); + recoMcCollisionId.emplace(col.globalIndex(), col.mcCollisionId()); + } + + for (auto const& mcCol : mcCollisions) { + recoMcCollBestCollisionIndex.emplace(mcCol.globalIndex(), mcCol.bestCollisionIndex()); + } + } + PROCESS_SWITCH(MftReassociationValidation, processCreateLookupTable, "Process look uptable creation", false); + + void processMcReassociated2d(FilteredCollisionsWSelMultMcLabels::iterator const& collision, + FilteredMftTracksWCollsMcLabels const& /*mftTracks*/, + soa::SmallGroups> const& reassociated2dMftTracks, + aod::McCollisions const& /*mcCollisions*/, + aod::McParticles const& /*particles*/, + aod::BCsWithTimestamps const& /*bcs*/) + { + auto bc = collision.template bc_as(); + loadZVertexShiftCorrection(bc); + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); + + if (!collision.has_mcCollision()) { + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); + + const int mcCollisionId = collision.mcCollisionId(); + auto iteratorMcCollisionBestCollIndex = recoMcCollBestCollisionIndex.find(mcCollisionId); + if (iteratorMcCollisionBestCollIndex == recoMcCollBestCollisionIndex.end()) { + return; + } + const float mcCollisionBestCollIndex = iteratorMcCollisionBestCollIndex->second; + + if (configCollision.requireMcCollBestCollIndex && (collision.globalIndex() != mcCollisionBestCollIndex)) { + return; + } + + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNotSplitVertex); + + if (!isAcceptedCollision(collision, true)) { + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); + + for (auto const& reassociated2dMftTrack : reassociated2dMftTracks) { + + if (reassociated2dMftTrack.has_mcParticle()) { + if (configTask.keepOnlyPhysicalPrimary && !reassociated2dMftTrack.mcParticle().isPhysicalPrimary()) { + continue; + } + if (configTask.keepOnlySecondaries && reassociated2dMftTrack.mcParticle().isPhysicalPrimary()) { + continue; + } + } + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); + registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::AllTracksCheck); + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AllTracksPrecise); + + auto templatedTrack = reassociated2dMftTrack.template mfttrack_as(); + + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(templatedTrack, mZShift); + std::array dcaInfOrig; + trackPar.propagateToDCAhelix(bZ, {collision.posX(), collision.posY(), collision.posZ()}, dcaInfOrig); + auto dcaXYoriginal = 999.f; + dcaXYoriginal = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + + if (configMft.cutFakeTracks && templatedTrack.mcMask() != 0) { + continue; + } + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsTrueTrack); + if (configMft.cutOrphanTracksExplicitly && reassociated2dMftTrack.ambDegree() == 0) { + continue; + } + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterOrphanCut); + + if (!isAcceptedMftTrack(templatedTrack, true, false, dcaXYoriginal, dcaInfOrig[2])) { + continue; + } + + if (reassociated2dMftTrack.ambDegree() == static_cast(reassociated2dMftTrack.compatibleCollIds().size())) { + registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize); + } + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); + + if (templatedTrack.has_mcParticle()) { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::HasMcParticle); + + auto particle = templatedTrack.template mcParticle_as(); + float deltaX = -999.f; + float deltaY = -999.f; + float deltaZ = -999.f; + float reassociatedDeltaX = -999.f; + float reassociatedDeltaY = -999.f; + float reassociatedDeltaZ = -999.f; + auto collision = templatedTrack.collision_as(); + auto xPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posX(); + auto yPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posY(); + auto zPosTrue = reassociated2dMftTrack.mcParticle().mcCollision().posZ(); + + const int bestRecoColl = reassociated2dMftTrack.bestCollisionId(); + const int originalRecoColl = templatedTrack.collisionId(); + + auto iteratorOriginalCollVtxX = recoVtxX.find(originalRecoColl); + auto iteratorOriginalCollVtxY = recoVtxY.find(originalRecoColl); + auto iteratorOriginalCollVtxZ = recoVtxZ.find(originalRecoColl); + auto iteratorBestCollVtxX = recoVtxX.find(bestRecoColl); + auto iteratorBestCollVtxY = recoVtxY.find(bestRecoColl); + auto iteratorBestCollVtxZ = recoVtxZ.find(bestRecoColl); + auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoColl); + + if (iteratorOriginalCollVtxX == recoVtxX.end()) { + // bestRecoColl not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorOriginalCollVtxY == recoVtxY.end()) { + continue; + } + if (iteratorOriginalCollVtxZ == recoVtxZ.end()) { + continue; + } + if (iteratorBestCollVtxX == recoVtxX.end()) { + continue; + } + if (iteratorBestCollVtxY == recoVtxY.end()) { + continue; + } + if (iteratorBestCollVtxZ == recoVtxZ.end()) { + continue; + } + if (iteratorRecoMcCollisionId == recoMcCollisionId.end()) { + continue; + } + + const float xPosOriginalColl = iteratorOriginalCollVtxX->second; + const float yPosOriginalColl = iteratorOriginalCollVtxY->second; + const float zPosOriginalColl = iteratorOriginalCollVtxZ->second; + const float xPosBestColl = iteratorBestCollVtxX->second; + const float yPosBestColl = iteratorBestCollVtxY->second; + const float zPosBestColl = iteratorBestCollVtxZ->second; + const int mcCollisionIdReco = iteratorRecoMcCollisionId->second; + + deltaX = xPosOriginalColl - xPosTrue; + deltaY = yPosOriginalColl - yPosTrue; + deltaZ = zPosOriginalColl - zPosTrue; + + reassociatedDeltaX = xPosBestColl - xPosTrue; + reassociatedDeltaY = yPosBestColl - yPosTrue; + reassociatedDeltaZ = zPosBestColl - zPosTrue; + + const auto dcaXtruth(particle.vx() - particle.mcCollision().posX()); + const auto dcaYtruth(particle.vy() - particle.mcCollision().posY()); + const auto dcaZtruth(particle.vz() - particle.mcCollision().posZ()); + auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); + + if (reassociated2dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); + registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor2d); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } + + if (templatedTrack.collisionId() == reassociated2dMftTrack.bestCollisionId()) { // IS NOT 2D REASSOCIATED + + registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::NotReassociated2dMftTracks); + registry.fill(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociated); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); + + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndMatchedToTrueCollision); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); + } else { + registry.fill(HIST("MC/hIsNot2dReassociatedAndMatchedToTrueCollision"), MftNot2dReassociatedAndMatchedToTrueCollisionStep::IsNot2dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiffNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNot2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + } + } + + } else { // IS 2D REASSOCIATED + + registry.fill(HIST("MC/hReassociation2dMftTracks"), Reassociation2dMftTracks::Reassociated2dMftTracks); + registry.fill(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociated); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); + + // is collision.mcCollisionId() the reassociated collision vertex ? or the initial collision + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndMatchedToTrueCollision); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); + } else { + registry.fill(HIST("MC/hIs2dReassociatedAndMatchedToTrueCollision"), Mft2dReassociatedAndMatchedToTrueCollisionStep::Is2dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiff2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDca2dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), dcaXYtruth); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + if (isTrueCollisionAmongCompatibleCollisions(reassociated2dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated2dMftTrack.bestDCAXY(), 0, dcaXYtruth, 0); + } + } + } + + } else { // NON AMBI TRACKS + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } + + } // end of if non ambi + } else { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); + } + } // end of loop over reassociated2dMftTracks + } + PROCESS_SWITCH(MftReassociationValidation, processMcReassociated2d, "Process MFT reassociation2d validation for MONTE-CARLO", false); + + void processMcReassociated3d(FilteredCollisionsWSelMultMcLabels::iterator const& collision, + FilteredMftTracksWCollsMcLabels const& /*mftTracks*/, + soa::SmallGroups> const& reassociated3dMftTracks, + aod::McCollisions const& /*mcCollisions*/, + aod::McParticles const& /*particles*/, + aod::BCsWithTimestamps const& /*bcs*/) + { + auto bc = collision.template bc_as(); + loadZVertexShiftCorrection(bc); + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::AllMonteCarloEvents); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::AllEventsPrecise); + + if (!collision.has_mcCollision()) { + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasNotMonteCarloCollision); + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::HasMonteCarloCollision); + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::HasMcCollision); + + const int mcCollisionId = collision.mcCollisionId(); + auto iteratorMcCollisionBestCollIndex = recoMcCollBestCollisionIndex.find(mcCollisionId); + if (iteratorMcCollisionBestCollIndex == recoMcCollBestCollisionIndex.end()) { + return; + } + const float mcCollisionBestCollIndex = iteratorMcCollisionBestCollIndex->second; + + if (configCollision.requireMcCollBestCollIndex && (collision.globalIndex() != mcCollisionBestCollIndex)) { + return; + } + + registry.fill(HIST("hPreciseEventCounter"), SpecificEventSelectionStep::IsNotSplitVertex); + + if (!isAcceptedCollision(collision, true)) { + return; + } + + registry.fill(HIST("MC/hMonteCarloEventCounter"), MonteCarloEventSelectionStep::MonteCarloEventsAfterEventSelection); + + for (auto const& reassociated3dMftTrack : reassociated3dMftTracks) { + + if (reassociated3dMftTrack.has_mcParticle()) { + if (configTask.keepOnlyPhysicalPrimary && !reassociated3dMftTrack.mcParticle().isPhysicalPrimary()) { + continue; + } + if (configTask.keepOnlySecondaries && reassociated3dMftTrack.mcParticle().isPhysicalPrimary()) { + continue; + } + } + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::AllMonteCarloTracks); + registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::AllTracksCheck); + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AllTracksPrecise); + + auto templatedTrack = reassociated3dMftTrack.template mfttrack_as(); + + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(templatedTrack, mZShift); + std::array dcaInfOrig; + trackPar.propagateToDCAhelix(bZ, {collision.posX(), collision.posY(), collision.posZ()}, dcaInfOrig); + auto dcaXYoriginal = 999.f; + dcaXYoriginal = std::sqrt(dcaInfOrig[0] * dcaInfOrig[0] + dcaInfOrig[1] * dcaInfOrig[1]); + + if (configMft.cutFakeTracks && templatedTrack.mcMask() != 0) { + continue; + } + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::IsTrueTrack); + if (configMft.cutOrphanTracksExplicitly && reassociated3dMftTrack.ambDegree() == 0) { + continue; + } + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::AfterOrphanCut); + + if (!isAcceptedMftTrack(templatedTrack, true, false, dcaXYoriginal, dcaInfOrig[2])) { + continue; + } + + if (reassociated3dMftTrack.ambDegree() == static_cast(reassociated3dMftTrack.compatibleCollIds().size())) { + registry.fill(HIST("MC/hTrackAmbiguityCheck"), TrackAmbiguityCheckStep::IsAmbDegreeEqualToCompatibleCollIdsSize); + } + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::MonteCarloTracksAfterTrackSelection); + + if (templatedTrack.has_mcParticle()) { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasMonteCarloParticle); + registry.fill(HIST("MC/hPreciseTrackSelectionCounter"), SpecificTrackSelectionStep::HasMcParticle); + + auto particle = templatedTrack.template mcParticle_as(); + float deltaX = -999.f; + float deltaY = -999.f; + float deltaZ = -999.f; + float reassociatedDeltaX = -999.f; + float reassociatedDeltaY = -999.f; + float reassociatedDeltaZ = -999.f; + auto collision = templatedTrack.collision_as(); + auto xPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posX(); + auto yPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posY(); + auto zPosTrue = reassociated3dMftTrack.mcParticle().mcCollision().posZ(); + + const int bestRecoColl = reassociated3dMftTrack.bestCollisionId(); + const int originalRecoColl = templatedTrack.collisionId(); + + auto iteratorOriginalCollVtxX = recoVtxX.find(originalRecoColl); + auto iteratorOriginalCollVtxY = recoVtxY.find(originalRecoColl); + auto iteratorOriginalCollVtxZ = recoVtxZ.find(originalRecoColl); + auto iteratorBestCollVtxX = recoVtxX.find(bestRecoColl); + auto iteratorBestCollVtxY = recoVtxY.find(bestRecoColl); + auto iteratorBestCollVtxZ = recoVtxZ.find(bestRecoColl); + auto iteratorRecoMcCollisionId = recoMcCollisionId.find(bestRecoColl); + + if (iteratorOriginalCollVtxX == recoVtxX.end()) { + // bestRecoColl not found in reco collisions map -> skip or count separately + continue; + } + if (iteratorOriginalCollVtxY == recoVtxY.end()) { + continue; + } + if (iteratorOriginalCollVtxZ == recoVtxZ.end()) { + continue; + } + if (iteratorBestCollVtxX == recoVtxX.end()) { + continue; + } + if (iteratorBestCollVtxY == recoVtxY.end()) { + continue; + } + if (iteratorBestCollVtxZ == recoVtxZ.end()) { + continue; + } + if (iteratorRecoMcCollisionId == recoMcCollisionId.end()) { + continue; + } + + const float xPosOriginalColl = iteratorOriginalCollVtxX->second; + const float yPosOriginalColl = iteratorOriginalCollVtxY->second; + const float zPosOriginalColl = iteratorOriginalCollVtxZ->second; + const float xPosBestColl = iteratorBestCollVtxX->second; + const float yPosBestColl = iteratorBestCollVtxY->second; + const float zPosBestColl = iteratorBestCollVtxZ->second; + const int mcCollisionIdReco = iteratorRecoMcCollisionId->second; + + deltaX = xPosOriginalColl - xPosTrue; + deltaY = yPosOriginalColl - yPosTrue; + deltaZ = zPosOriginalColl - zPosTrue; + + reassociatedDeltaX = xPosBestColl - xPosTrue; + reassociatedDeltaY = yPosBestColl - yPosTrue; + reassociatedDeltaZ = zPosBestColl - zPosTrue; + + const auto dcaXtruth(particle.vx() - particle.mcCollision().posX()); + const auto dcaYtruth(particle.vy() - particle.mcCollision().posY()); + const auto dcaZtruth(particle.vz() - particle.mcCollision().posZ()); + auto dcaXYtruth = std::sqrt(dcaXtruth * dcaXtruth + dcaYtruth * dcaYtruth); + + if (reassociated3dMftTrack.ambDegree() > 1) { // AMBIGUOUS TRACKS + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguous); + registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::AllAmbiguousTracksAfterTrackSelectionsFor3d); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsAmbiguousTrackMatchedToTrueCollision"), MftAmbiguousAndMatchedToTrueCollisionStep::IsAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } + + if (templatedTrack.collisionId() == reassociated3dMftTrack.bestCollisionId()) { // IS NOT 3D REASSOCIATED + + registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::NotReassociated3dMftTracks); + registry.fill(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociated); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndMatchedToTrueCollision); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsNot3dReassociatedAndMatchedToTrueCollision"), MftNot3dReassociatedAndMatchedToTrueCollisionStep::IsNot3dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiffNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNot3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaNotReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } + } + + } else { // IS 3D REASSOCIATED + + registry.fill(HIST("MC/hReassociation3dMftTracks"), Reassociation3dMftTracks::Reassociated3dMftTracks); + registry.fill(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociated); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + + if (mcCollisionIdReco == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndMatchedToTrueCollision); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIs3dReassociatedAndMatchedToTrueCollision"), Mft3dReassociatedAndMatchedToTrueCollisionStep::Is3dReassociatedAndNotMatchedToTrueCollision); + hZVtxDiff3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDca3dReassociatedTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::AllWronglyAssociatedTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + if (isTrueCollisionAmongCompatibleCollisions(reassociated3dMftTrack)) { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisions"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + registry.fill(HIST("MC/hIsTrueCollisionAmongCompatibleCollisionsDcaReassociated"), MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions); + hZVtxDiffNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociatedDeltaX, reassociatedDeltaY, reassociatedDeltaZ); + hDcaNotMatchedTracks[MftIsTrueCollisionAmongCompatibleCollisionsStep::IsNotTrueCollisionAmongCompatibleCollisions]->Fill(templatedTrack.pt(), templatedTrack.eta(), reassociated3dMftTrack.bestDCAXY(), reassociated3dMftTrack.bestDCAZ(), dcaXYtruth, dcaZtruth); + } + } + } + + } else { // NON AMBI TRACKS + + registry.fill(HIST("MC/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguous); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::AllTracks]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + + if (collision.mcCollisionId() == particle.mcCollisionId()) { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } else { + registry.fill(HIST("MC/hIsNonAmbiguousTrackMatchedToTrueCollision"), MftNonAmbiguousAndMatchedToTrueCollisionStep::IsNonAmbiguousAndNotMatchedToTrueCollision); + hZVtxDiffNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), deltaX, deltaY, deltaZ); + hDcaNonAmbiguousTracks[MatchedToTrueCollisionStep::IsNotMatchedToTrueCollision]->Fill(templatedTrack.pt(), templatedTrack.eta(), dcaXYoriginal, dcaInfOrig[2], dcaXYtruth, dcaZtruth); + } + + } // end of if non ambi + } else { + registry.fill(HIST("MC/hMonteCarloTrackCounter"), MonteCarloTrackSelectionStep::HasNotMonteCarloParticle); + } + } // end of loop over reassociated3dMftTracks + } + PROCESS_SWITCH(MftReassociationValidation, processMcReassociated3d, "Process MFT reassociation3d validation for MONTE-CARLO", false); + +}; // End of struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGMM/Mult/Tasks/multiplicityPbPb.cxx b/PWGMM/Mult/Tasks/multiplicityPbPb.cxx index 367b7e991a6..70f62629b54 100644 --- a/PWGMM/Mult/Tasks/multiplicityPbPb.cxx +++ b/PWGMM/Mult/Tasks/multiplicityPbPb.cxx @@ -13,17 +13,21 @@ /// /// \author hhesouno -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" - -#include "ReconstructionDataFormats/GlobalTrackID.h" - #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/Mult/Tasks/pseudoEffMFT.cxx b/PWGMM/Mult/Tasks/pseudoEffMFT.cxx index d8dc1990329..7a47c760094 100644 --- a/PWGMM/Mult/Tasks/pseudoEffMFT.cxx +++ b/PWGMM/Mult/Tasks/pseudoEffMFT.cxx @@ -16,40 +16,47 @@ /// \since OCT 2025 #include "Functions.h" -#include "Index.h" #include "bestCollisionTable.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Configurable.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RuntimeError.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" + +#include +#include #include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include +#include + +#include +#include +#include +#include -#include "TPDGCode.h" +#include #include +#include #include #include -#include +#include #include #include +#include #include #include diff --git a/PWGMM/Mult/Tasks/puremc-dndeta.cxx b/PWGMM/Mult/Tasks/puremc-dndeta.cxx index 86e52b38850..f634755a3dd 100644 --- a/PWGMM/Mult/Tasks/puremc-dndeta.cxx +++ b/PWGMM/Mult/Tasks/puremc-dndeta.cxx @@ -9,17 +9,30 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include -#include - #include "Axes.h" #include "Histograms.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGMM/Mult/Tasks/run2dndeta.cxx b/PWGMM/Mult/Tasks/run2dndeta.cxx index 9db9fd291d9..84e7fca4123 100644 --- a/PWGMM/Mult/Tasks/run2dndeta.cxx +++ b/PWGMM/Mult/Tasks/run2dndeta.cxx @@ -8,24 +8,29 @@ // 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 "Framework/Configurable.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RuntimeError.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "ReconstructionDataFormats/GlobalTrackID.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "TDatabasePDG.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -56,7 +61,7 @@ struct PseudorapidityDensity { {"TracksEtaZvtx_gt0", "; #eta; Z_{vtx}; tracks", {HistType::kTH2F, {{21, -2.1, 2.1}, {201, -20.1, 20.1}}}}, // {"TracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {{600, 0, 2 * M_PI}, {21, -2.1, 2.1}}}}, // {"EventSelection", ";status;events", {HistType::kTH1F, {{4, 0.5, 4.5}}}} // - } // + } // }; void init(InitContext&) diff --git a/PWGMM/Mult/Tasks/vertexing-fwd.cxx b/PWGMM/Mult/Tasks/vertexing-fwd.cxx index aecb9e7cd9c..f5dd786acc7 100644 --- a/PWGMM/Mult/Tasks/vertexing-fwd.cxx +++ b/PWGMM/Mult/Tasks/vertexing-fwd.cxx @@ -16,18 +16,27 @@ // \brief This code loops over every ambiguous MFT tracks and associates // them to a collision that has the smallest DCAxy +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include #include -#include "ReconstructionDataFormats/TrackFwd.h" -#include "Math/MatrixFunctions.h" -#include "Math/SMatrix.h" -#include "MathUtils/Utils.h" -#include "Framework/Configurable.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/runDataProcessing.h" - -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/LHCConstants.h" +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/UE/Tasks/dedxAnalysis.cxx b/PWGMM/UE/Tasks/dedxAnalysis.cxx index a4ea4bb22ac..cb8e1cbbc0d 100644 --- a/PWGMM/UE/Tasks/dedxAnalysis.cxx +++ b/PWGMM/UE/Tasks/dedxAnalysis.cxx @@ -16,29 +16,33 @@ #include "PWGLF/DataModel/LFStrangenessTables.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/Multiplicity.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/V0.h" - -#include "TF1.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/UE/Tasks/dedx_analysys.cxx b/PWGMM/UE/Tasks/dedx_analysys.cxx deleted file mode 100644 index 3a4bb9a2843..00000000000 --- a/PWGMM/UE/Tasks/dedx_analysys.cxx +++ /dev/null @@ -1,569 +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. -/// -/// \author Paola Vargas -/// \since January 8, 2025 - -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -using namespace o2; -using namespace o2::framework; - -using PIDTracks = soa::Join< - aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::pidTOFbeta, - aod::pidTOFmass, aod::TrackSelection, aod::TrackSelectionExtension, - aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullDe, - aod::pidTPCFullTr, aod::pidTPCFullHe, aod::pidTOFFullPi, aod::pidTOFFullKa, - aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullTr, aod::pidTOFFullHe, aod::pidTOFFullEl>; - -using SelectedCollisions = soa::Join; - -struct dedx_analysys { - - // dE/dx for all charged particles - HistogramRegistry registryDeDx{ - "registryDeDx", - {}, - OutputObjHandlingPolicy::AnalysisObject, - true, - true}; - - // Corrections - // constexpr double Correc[8]{54.3344, 55.1277, 56.0811, 56.7974, 56.9533, 56.4622, 55.8873, 55.1449}; - // constexpr double Correc[9]{-0.8, -0.6, -0.4, -0.2, 0., 0.2, 0.4, 0.6, 0.8}; - - // Configurable Parameters - Configurable minTPCnClsFound{"minTPCnClsFound", 70.0f, - "min number of found TPC clusters"}; - Configurable minNCrossedRowsTPC{ - "minNCrossedRowsTPC", 70.0f, "min number of found TPC crossed rows"}; - Configurable minNClsTPCdEdx{ - "minNClsTPCdEdx", 50.0f, "min number of TPC clusters for PID"}; - Configurable maxChi2TPC{"maxChi2TPC", 4.0f, - "max chi2 per cluster TPC"}; - Configurable maxChi2ITS{"maxChi2ITS", 36.0f, - "max chi2 per cluster ITS"}; - Configurable etaMin{"etaMin", -0.8f, "etaMin"}; - Configurable etaMax{"etaMax", +0.8f, "etaMax"}; - Configurable v0cospaMin{"v0cospaMin", 0.998f, "Minimum V0 CosPA"}; - Configurable minimumV0Radius{"minimumV0Radius", 0.5f, - "Minimum V0 Radius"}; - Configurable maximumV0Radius{"maximumV0Radius", 100.0f, - "Maximum V0 Radius"}; - Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, - "Maximum DCA Daughters"}; - Configurable nsigmaTOFmax{"nsigmaTOFmax", 3.0f, "Maximum nsigma TOF"}; - Configurable minMassK0s{"minMassK0s", 0.4f, "Minimum Mass K0s"}; - Configurable maxMassK0s{"maxMassK0s", 0.6f, "Maximum Mass K0s"}; - Configurable minMassLambda{"minMassLambda", 1.1f, - "Minimum Mass Lambda"}; - Configurable maxMassLambda{"maxMassLambda", 1.2f, - "Maximum Mass Lambda"}; - Configurable minMassGamma{"minMassGamma", 0.000922f, - "Minimum Mass Gamma"}; - Configurable maxMassGamma{"maxMassGamma", 0.002022f, - "Maximum Mass Gamma"}; - Configurable minReqClusterITS{ - "minReqClusterITS", 4.0f, "min number of clusters required in ITS"}; - Configurable maxDCAxy{"maxDCAxy", 0.1f, "maxDCAxy"}; - Configurable maxDCAz{"maxDCAz", 0.1f, "maxDCAz"}; - Configurable eventSelection{"eventSelection", true, "event selection"}; - // Histograms names - static constexpr std::string_view Armenteros[5] = {"Armenteros", "Armenteros_K0S", "Armenteros_Lambda", "Armenteros_AntiLambda", "Armenteros_Gamma"}; - static constexpr std::string_view Qt_vs_alpha[5] = {"Qt_vs_alpha", "Qt_vs_alpha_K0S", "Qt_vs_alpha_Lambda", "Qt_vs_alpha_AntiLambda", "Qt_vs_alpha_Gamma"}; - static constexpr std::string_view dEdx_vs_Momentum[5] = {"dEdx_vs_Momentum_all", "dEdx_vs_Momentum_02", "dEdx_vs_Momentum_0204", "dEdx_vs_Momentum_0406", "dEdx_vs_Momentum_0608"}; - static constexpr std::string_view dEdx_vs_Momentum_neg[4] = {"dEdx_vs_Momentum_02neg", "dEdx_vs_Momentum_0204neg", "dEdx_vs_Momentum_0406neg", "dEdx_vs_Momentum_0608neg"}; - static constexpr std::string_view dEdx_vs_Momentum_pos[4] = {"dEdx_vs_Momentum_02pos", "dEdx_vs_Momentum_0204pos", "dEdx_vs_Momentum_0406pos", "dEdx_vs_Momentum_0608pos"}; - static constexpr std::string_view dEdx_vs_Momentum_v0[3] = {"dEdx_vs_Momentum_Pi_v0", "dEdx_vs_Momentum_Pr_v0", "dEdx_vs_Momentum_El_v0"}; - static constexpr std::string_view hInvMass[4] = {"InvMass_K0S", "InvMass_Lambda", "InvMass_AntiLambda", "InvMass_Gamma"}; - static constexpr double EtaCut[9] = {-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}; - static constexpr double Correction[8] = {54.3344, 55.1277, 56.0811, 56.7974, 56.9533, 56.4622, 55.8873, 55.1449}; - - void init(InitContext const&) - { - - // MIP for pions - registryDeDx.add( - "dEdxMIP_vs_eta", "dE/dx", HistType::kTH2F, - {{100, -0.8, 0.8, "#eta"}, {100, 0.0, 600.0, "dE/dx MIP (a. u.)"}}); - - registryDeDx.add( - "dEdxMIP_vs_phi", "dE/dx", HistType::kTH2F, - {{100, 0.0, 6.4, "#phi"}, {100, 0.0, 600.0, "dE/dx MIP (a. u.)"}}); - - registryDeDx.add( - "dEdxMIP_vs_eta_AfterCorr", "dE/dx", HistType::kTH2F, - {{100, -0.8, 0.8, "#eta"}, {100, 0.0, 600.0, "dE/dx MIP (a. u.)"}}); - - //////////////////////////////// - registryDeDx.add(hInvMass[0].data(), "mass", HistType::kTH1F, - {{100, 400, 600, "m (MeV/c)"}}); - registryDeDx.add(hInvMass[1].data(), "mass", HistType::kTH1F, - {{100, 1.08, 1.25, "m (GeV/c)"}}); - registryDeDx.add(hInvMass[2].data(), "mass", HistType::kTH1F, - {{100, 1.08, 1.25, "m (GeV/c)"}}); - registryDeDx.add(hInvMass[3].data(), "mass", HistType::kTH1F, - {{100, 0, 2, "m (MeV/c)"}}); - // Armenteros plot and De/Dx for eta cut inclusive - for (int i = 0; i < 5; ++i) { - registryDeDx.add(Armenteros[i].data(), Qt_vs_alpha[i].data(), HistType::kTH2F, - {{100, -1., 1., "#alpha (a. u.)"}, {100, 0.0, 0.3, "q_T (GeV/c)"}}); - registryDeDx.add(dEdx_vs_Momentum[i].data(), "dE/dx", HistType::kTH2F, - {{100, -20.0, 20.0, "#it{p}/Z (GeV/c)"}, {100, 0.0, 600.0, "dE/dx (a. u.)"}}); - } - // De/Dx for eta cut negative and positive - for (int i = 0; i < 4; ++i) { - - registryDeDx.add(dEdx_vs_Momentum_neg[i].data(), "dE/dx", HistType::kTH2F, - {{100, -20.0, 20.0, "#it{p}/Z (GeV/c)"}, {100, 0.0, 600.0, "dE/dx (a. u.)"}}); - - registryDeDx.add(dEdx_vs_Momentum_pos[i].data(), "dE/dx", HistType::kTH2F, - {{100, -20.0, 20.0, "#it{p}/Z (GeV/c)"}, {100, 0.0, 600.0, "dE/dx (a. u.)"}}); - } - - // De/Dx for v0 particles - for (int i = 0; i < 3; ++i) { - - registryDeDx.add(dEdx_vs_Momentum_v0[i].data(), "dE/dx", HistType::kTH2F, - {{100, -20.0, 20.0, "#it{p}/Z (GeV/c)"}, {100, 0.0, 600.0, "dE/dx (a. u.)"}}); - } - - // Event Counter - registryDeDx.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{100, -20.0, +20.0, "z_{vtx} (cm)"}}); - } - - // Single-Track Selection - template - bool passedSingleTrackSelection(const T1& track, const C& /*collision*/) - { - // Single-Track Selections - 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.eta() < etaMin || track.eta() > etaMax) - return false; - - return true; - } - - // General V0 Selections - template - bool passedV0Selection(const T1& v0, const C& /*collision*/) - { - if (v0.v0cosPA() < v0cospaMin) - return false; - if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) - return false; - - return true; - } - - // K0s Selections - template - bool passedK0Selection(const T1& v0, const T2& ntrack, const T2& ptrack, - const C& collision) - { - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack, collision)) - return false; - if (!passedSingleTrackSelection(ntrack, collision)) - return false; - - if (ptrack.tpcInnerParam() > 0.6) { - if (!ptrack.hasTOF()) - return false; - if (TMath::Abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) - return false; - } - - if (ntrack.tpcInnerParam() > 0.6) { - if (!ntrack.hasTOF()) - return false; - if (TMath::Abs(ntrack.tofNSigmaPi()) > nsigmaTOFmax) - return false; - } - - // Invariant-Mass Selection - if (v0.mK0Short() < minMassK0s || v0.mK0Short() > maxMassK0s) - return false; - - return true; - } - - // Lambda Selections - template - bool passedLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, - const C& collision) - { - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack, collision)) - return false; - if (!passedSingleTrackSelection(ntrack, collision)) - return false; - - if (ptrack.tpcInnerParam() > 0.6) { - if (!ptrack.hasTOF()) - return false; - if (TMath::Abs(ptrack.tofNSigmaPr()) > nsigmaTOFmax) - return false; - } - - if (ntrack.tpcInnerParam() > 0.6) { - if (!ntrack.hasTOF()) - return false; - if (TMath::Abs(ntrack.tofNSigmaPi()) > nsigmaTOFmax) - return false; - } - - // Invariant-Mass Selection - if (v0.mLambda() < minMassLambda || v0.mLambda() > maxMassLambda) - return false; - - return true; - } - - // AntiLambda Selections - template - bool passedAntiLambdaSelection(const T1& v0, const T2& ntrack, - const T2& ptrack, const C& collision) - { - - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack, collision)) - return false; - if (!passedSingleTrackSelection(ntrack, collision)) - return false; - - if (ptrack.tpcInnerParam() > 0.6) { - if (!ptrack.hasTOF()) - return false; - if (TMath::Abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) - return false; - } - - if (ntrack.tpcInnerParam() > 0.6) { - if (!ntrack.hasTOF()) - return false; - if (TMath::Abs(ntrack.tofNSigmaPr()) > nsigmaTOFmax) - return false; - } - - // Invariant-Mass Selection - if (v0.mAntiLambda() < minMassLambda || v0.mAntiLambda() > maxMassLambda) - return false; - - return true; - } - - // Gamma Selections - template - bool passedGammaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, - const C& collision) - { - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack, collision)) - return false; - if (!passedSingleTrackSelection(ntrack, collision)) - return false; - - if (ptrack.tpcInnerParam() > 0.6) { - if (!ptrack.hasTOF()) - return false; - if (TMath::Abs(ptrack.tofNSigmaEl()) > nsigmaTOFmax) - return false; - } - - if (ntrack.tpcInnerParam() > 0.6) { - if (!ntrack.hasTOF()) - return false; - if (TMath::Abs(ntrack.tofNSigmaEl()) > nsigmaTOFmax) - return false; - } - - // Invariant-Mass Selection - if (v0.mGamma() < minMassGamma || v0.mGamma() > maxMassGamma) - return false; - - return true; - } - - // Process Data - void process(SelectedCollisions::iterator const& collision, - aod::V0Datas const& fullV0s, PIDTracks const& tracks) - { - // Event Selection - if (!collision.sel8()) - return; - - // Event Counter - registryDeDx.fill(HIST("histRecVtxZData"), collision.posZ()); - - // Centrality - float centrality = collision.centFT0C(); - if (centrality < 0.0 || centrality > 100.0) - centrality = 1.0; - - // Kaons - for (auto& trk : tracks) { - - if (!passedSingleTrackSelection(trk, collision)) - continue; - if (!trk.passedTPCRefit()) - continue; - float signedP = trk.sign() * trk.tpcInnerParam(); - - // DeDx all particles - registryDeDx.fill(HIST(dEdx_vs_Momentum[0]), signedP, trk.tpcSignal()); - - //////////////////////////////// - - // MIP for pions - - // TODO: 0.25 TO 0.35 - // range 0.2 to 0.6 - // float pion_m = 0.139; //GeV - if (trk.tpcInnerParam() >= 0.25 && trk.tpcInnerParam() <= 0.35) { - registryDeDx.fill(HIST("dEdxMIP_vs_eta"), trk.eta(), trk.tpcSignal()); - registryDeDx.fill(HIST("dEdxMIP_vs_phi"), trk.phi(), trk.tpcSignal()); - // After calibration - - for (int i = 0; i < 8; ++i) { - if (trk.eta() > EtaCut[i] && trk.eta() < EtaCut[i + 1]) { - registryDeDx.fill(HIST("dEdxMIP_vs_eta_AfterCorr"), trk.eta(), trk.tpcSignal() * 50 / Correction[i]); - } - } - } - - // After calibration - for (int i = 0; i < 8; ++i) { - if (trk.eta() > EtaCut[i] && trk.eta() < EtaCut[i + 1]) { - if (i == 0) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_neg[0]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[4]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 1) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_neg[1]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[3]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 2) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_neg[2]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[2]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 3) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_neg[3]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[1]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 4) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_pos[0]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[1]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 5) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_pos[1]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[2]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 6) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_pos[2]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[3]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } else if (i == 7) { - registryDeDx.fill(HIST(dEdx_vs_Momentum_pos[3]), signedP, trk.tpcSignal() * 50 / Correction[i]); - registryDeDx.fill(HIST(dEdx_vs_Momentum[4]), signedP, trk.tpcSignal() * 50 / Correction[i]); - } - } - } - } - - // Loop over Reconstructed V0s - for (auto& v0 : fullV0s) { - - // Standard V0 Selections - if (!passedV0Selection(v0, collision)) { - continue; - } - - if (v0.dcaV0daughters() > dcaV0DaughtersMax) { - continue; - } - - // Positive and Negative Tracks - const auto& posTrack = v0.posTrack_as(); - const auto& negTrack = v0.negTrack_as(); - - if (!posTrack.passedTPCRefit()) - continue; - if (!negTrack.passedTPCRefit()) - continue; - - float signedPpos = posTrack.sign() * posTrack.tpcInnerParam(); - float signedPneg = negTrack.sign() * negTrack.tpcInnerParam(); - - float px_v0 = v0.px(); - float py_v0 = v0.py(); - float pz_v0 = v0.pz(); - float p_v0 = sqrt(px_v0 * px_v0 + py_v0 * py_v0 + pz_v0 * pz_v0); - - float px_pos = posTrack.px(); - float py_pos = posTrack.py(); - float pz_pos = posTrack.pz(); - - float px_neg = negTrack.px(); - float py_neg = negTrack.py(); - float pz_neg = negTrack.pz(); - - const float protonMass = 0.938; // GeV/c^2 - const float piMass = 0.13957; // GeV/c^2 - const float K0SMass = 493.677; // MeV/c^2 - const float LambdaMass = 1.115; // GeV/c^2 - const float GammaMass = 1.022; // MeV/c^2 - const float eMass = 0.511; // MeV/c^2 - - // float E_pos_man = std::sqrt(px_pos * px_pos + py_pos * py_pos + pz_pos * pz_pos + piMass * piMass); - - //-------------------Armenteros plots-------- - - float pl_pos = (px_pos * px_v0 + py_pos * py_v0 + pz_pos * pz_v0) / p_v0; - float pl_neg = (px_neg * px_v0 + py_neg * py_v0 + pz_neg * pz_v0) / p_v0; - - float alpha = (pl_pos - pl_neg) / (pl_pos + pl_neg); - float p_pos = sqrt(px_pos * px_pos + py_pos * py_pos + pz_pos * pz_pos); - float qt = sqrt(p_pos * p_pos - pl_pos * pl_pos); - - registryDeDx.fill(HIST(Armenteros[0]), alpha, qt); - - //------------------------------------------- - - // K0s Selection - if (passedK0Selection(v0, negTrack, posTrack, collision)) { - float E_pos_pi = posTrack.energy(piMass); - float E_neg_pi = negTrack.energy(piMass); - - float InvMass = sqrt((E_neg_pi + E_pos_pi) * (E_neg_pi + E_pos_pi) - ((px_neg + px_pos) * (px_neg + px_pos) + (py_neg + py_pos) * (py_neg + py_pos) + (pz_neg + pz_pos) * (pz_neg + pz_pos))); - - if (TMath::Abs(InvMass * 1000 - K0SMass) > 10) { - continue; - } - - registryDeDx.fill(HIST(hInvMass[0]), InvMass * 1000); - registryDeDx.fill(HIST(Armenteros[1]), alpha, qt); - - for (int i = 0; i < 8; ++i) { - if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[0]), signedPneg, negTrack.tpcSignal() * 50 / Correction[i]); - } - if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[0]), signedPpos, posTrack.tpcSignal() * 50 / Correction[i]); - } - } - } - - // Lambda Selection - if (passedLambdaSelection(v0, negTrack, posTrack, collision)) { - float E_pos_p = posTrack.energy(protonMass); - float E_neg_pi = negTrack.energy(piMass); - - float InvMass = sqrt((E_neg_pi + E_pos_p) * (E_neg_pi + E_pos_p) - ((px_neg + px_pos) * (px_neg + px_pos) + (py_neg + py_pos) * (py_neg + py_pos) + (pz_neg + pz_pos) * (pz_neg + pz_pos))); - - if (TMath::Abs(InvMass - LambdaMass) > 0.01) { - continue; - } - - registryDeDx.fill(HIST(hInvMass[1]), InvMass); - registryDeDx.fill(HIST(Armenteros[2]), alpha, qt); - - for (int i = 0; i < 8; ++i) { - if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[0]), signedPneg, negTrack.tpcSignal() * 50 / Correction[i]); - } - if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[1]), signedPpos, posTrack.tpcSignal() * 50 / Correction[i]); - } - } - } - - // AntiLambda Selection - if (passedAntiLambdaSelection(v0, negTrack, posTrack, collision)) { - - float E_pos_pi = posTrack.energy(piMass); - float E_neg_p = negTrack.energy(protonMass); - - float InvMass = sqrt((E_neg_p + E_pos_pi) * (E_neg_p + E_pos_pi) - ((px_neg + px_pos) * (px_neg + px_pos) + (py_neg + py_pos) * (py_neg + py_pos) + (pz_neg + pz_pos) * (pz_neg + pz_pos))); - - if (TMath::Abs(InvMass - LambdaMass) > 0.01) { - continue; - } - - registryDeDx.fill(HIST(hInvMass[2]), InvMass); - registryDeDx.fill(HIST(Armenteros[3]), alpha, qt); - - for (int i = 0; i < 8; ++i) { - if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[1]), signedPneg, negTrack.tpcSignal() * 50 / Correction[i]); - } - if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[0]), signedPpos, posTrack.tpcSignal() * 50 / Correction[i]); - } - } - } - - // Gamma Selection - if (passedGammaSelection(v0, negTrack, posTrack, collision)) { - - float E_pos_e = posTrack.energy(eMass); - float E_neg_e = negTrack.energy(eMass); - - float InvMass = sqrt((E_neg_e + E_pos_e) * (E_neg_e + E_pos_e) - ((px_neg + px_pos) * (px_neg + px_pos) + (py_neg + py_pos) * (py_neg + py_pos) + (pz_neg + pz_pos) * (pz_neg + pz_pos))); - - if (TMath::Abs(InvMass - GammaMass) > 10) { - continue; - } - - registryDeDx.fill(HIST(hInvMass[3]), InvMass); - registryDeDx.fill(HIST(Armenteros[4]), alpha, qt); - - for (int i = 0; i < 8; ++i) { - if (negTrack.eta() > EtaCut[i] && negTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[2]), signedPneg, negTrack.tpcSignal() * 50 / Correction[i]); - } - if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { - - registryDeDx.fill(HIST(dEdx_vs_Momentum_v0[2]), signedPpos, posTrack.tpcSignal() * 50 / Correction[i]); - } - } - } - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/PWGMM/UE/Tasks/ue-zdc-analysys.cxx b/PWGMM/UE/Tasks/ue-zdc-analysys.cxx index ec5294f7248..bf632017ee4 100644 --- a/PWGMM/UE/Tasks/ue-zdc-analysys.cxx +++ b/PWGMM/UE/Tasks/ue-zdc-analysys.cxx @@ -12,22 +12,21 @@ /// \brief Task for ZDC /// \author /// \since -#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/Core/TrackSelection.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" -#include "ReconstructionDataFormats/Track.h" -#include "TH1F.h" -#include "TH2F.h" -#include "TObjArray.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGMM/UE/Tasks/uecharged.cxx b/PWGMM/UE/Tasks/uecharged.cxx index 04c618be339..5f8908db124 100644 --- a/PWGMM/UE/Tasks/uecharged.cxx +++ b/PWGMM/UE/Tasks/uecharged.cxx @@ -13,33 +13,37 @@ /// \file uecharged.cxx /// \brief Underlying event analysis task /// \since November 2021 -/// \last update: January 2026 +/// \last update: March 2026 -#include "PWGLF/DataModel/mcCentrality.h" -#include "PWGLF/Utils/collisionCuts.h" #include "PWGLF/Utils/inelGt.h" -#include "PWGLF/Utils/mcParticle.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include #include #include #include +#include #include using namespace o2; @@ -50,58 +54,35 @@ using FT0s = aod::FT0s; struct ueCharged { - TrackSelection myTrackSelectionPrim() - { - TrackSelection selectedTracks; - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); // Run3ITSibAny - selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / std::pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(0.1f); - return selectedTracks; - } - - TrackSelection myTrackSelectionOpenDCA() - { - TrackSelection selectedTracks; - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1, 2}); // Run3ITSibAny - selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(0.1f); - return selectedTracks; - } - - TrackSelection mySelectionPrim; - TrackSelection mySelectionOpenDCA; - - Service pdg; - // Configurable for event selection Configurable isRun3{"isRun3", true, "is Run3 dataset"}; - Configurable pileuprejection{"pileuprejection", true, "Pileup rejection"}; - Configurable goodzvertex{"goodzvertex", true, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference"}; - Configurable sel8{"sel8", true, "Apply the sel8 event selection"}; - Configurable removeITSROFBorder{"removeITSROFBorder", false, "Remove ITS Read-Out Frame border and only apply kIsTriggerTVX & kNoTimeFrameBorder (recommended for MC)"}; - Configurable cfgINELCut{"cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; + Configurable pileuprejection{"event_pileuprejection", true, "Pileup rejection"}; + Configurable goodzvertex{"event_goodzvertex", true, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference"}; + Configurable sel8{"event_sel8", true, "Apply the sel8 event selection"}; + Configurable removeITSROFBorder{"event_removeITSROFBorder", false, "Remove ITS Read-Out Frame border and only apply kIsTriggerTVX & kNoTimeFrameBorder (recommended for MC)"}; + Configurable cfgINELCut{"event_cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; Configurable analyzeEvandTracksel{"analyzeEvandTracksel", true, "Analyze the event and track selection"}; - // acceptance cuts - Configurable cfgTrkEtaCut{"cfgTrkEtaCut", 0.8f, "Eta range for tracks"}; + + // Track selection configurables + TrackSelection myTrkSel; Configurable cfgTrkLowPtCut{"cfgTrkLowPtCut", 0.15f, "Minimum constituent pT"}; + Configurable isCustomTracks{"trkcfg_isCustomTracks", true, "Use custom track cuts"}; + Configurable setITSreq{"trkcfg_setITSreq", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable minPt{"trkcfg_minPt", 0.1f, "Set minimum pT of tracks"}; + Configurable maxPt{"trkcfg_maxPt", 1e10f, "Set maximum pT of tracks"}; + Configurable requireEta{"trkcfg_requireEta", 0.8f, "Set eta range of tracks"}; + Configurable requireITSRefit{"trkcfg_requireITSRefit", true, "Additional cut on the ITS requirement"}; + Configurable requireTPCRefit{"trkcfg_requireTPCRefit", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"trkcfg_requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable maxChi2PerClusterTPC{"trkcfg_maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"trkcfg_maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + // Configurable minITSnClusters{"trkcfg_minITSnClusters", 5, "minimum number of found ITS clusters"}; + Configurable minNCrossedRowsTPC{"trkcfg_minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"trkcfg_minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxDcaXYFactor{"trkcfg_maxDcaXYFactor", 1.f, "Multiplicative factor on the maximum value of the DCA xy"}; + Configurable maxDcaZ{"trkcfg_maxDcaZ", 0.1f, "Additional cut on the maximum value of the DCA z"}; + + Service pdg; // Data table definitions using ColDataTable = soa::Join; @@ -152,6 +133,24 @@ struct ueCharged { void init(InitContext const&) { + if (isCustomTracks.value) { + myTrkSel = getGlobalTrackSelectionRun3ITSMatch(setITSreq.value); + myTrkSel.SetPtRange(minPt.value, maxPt.value); + myTrkSel.SetEtaRange(-requireEta.value, requireEta.value); + myTrkSel.SetRequireITSRefit(requireITSRefit.value); + myTrkSel.SetRequireTPCRefit(requireTPCRefit.value); + myTrkSel.SetRequireGoldenChi2(requireGoldenChi2.value); + myTrkSel.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + myTrkSel.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + // myTrkSel.SetMinNClustersITS(minITSnClusters.value); + myTrkSel.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + myTrkSel.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + // myTrkSel.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + myTrkSel.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); + myTrkSel.SetMaxDcaZ(maxDcaZ.value); + myTrkSel.print(); + } + 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, @@ -170,12 +169,13 @@ struct ueCharged { AxisSpec ptAxis = {ptBinning, "#it{p}_{T}^{assoc} (GeV/#it{c})"}; fEff.setObject(new TF1("fpara", - "(x<0.3)*((0.315318)+x*(2.38596)+x*x*(-4.388)) +" - "(x>=0.3&&x<1.8)*((0.604051)+(0.154763)*x+(-0.103004)*" - "x*x+(0.0266487)*x*x*x) +" - "(x>=1.8&&x<14.)*((0.700444)+(-0.00115506)*x+(0." - "000667608)*x*x+(-3.82915e-05)*x*x*x) +" - "(x>=14)*((0.731778)+(-0.000994634)*x)", + "(x<0.33)*((0.384347)+x*(1.77554)+x*x*(-2.9172)) +" + "(x>=0.33&&x<1.2)*((0.58547)+(0.293843)*x+(-0.293957)*" + "x*x+(0.109855)*x*x*x) +" + "(x>=1.2&&x<5.6)*((0.581232)+(0.205847)*x+" + "(-0.12133)*x*x+(0.0347906)*x*x*x+" + "(-0.0048334)*x*x*x*x+(0.000261644)*x*x*x*x*x)+(x>=5.6)*((0.711869)+(0.00364573)*x" + "+(-0.00019009)*x*x+(3.09894e-06)*x*x*x+(-1.81785e-08)*x*x*x*x)", 0., 1e5)); if (doprocessMC || doprocessMCTrue) { @@ -290,6 +290,9 @@ struct ueCharged { ue.add("postselection_track/hvtxXY", "vtxXY after track selection", HistType::kTH1D, {{121, -3.025, 3.025, "#it{DCA}_{xy} (cm)"}}); ue.add("postselection_track/htracks", "tracks after track selection", HistType::kTH1D, {{100, 0., 100., "N_{tracks}"}}); } + + ue.add("hPtAssoc_True", "pT mc True; pT; ", HistType::kTH1D, {ptAxis}); + ue.add("hPtAssoc_Rec", "pT mc Rec; pT; ", HistType::kTH1D, {ptAxis}); } float deltaPhi(float phia, float phib, @@ -322,16 +325,41 @@ struct ueCharged { if (!track.has_collision()) { return false; } - if (!mySelectionPrim.IsSelected(track)) { + if (track.pt() < cfgTrkLowPtCut) { return false; } - if (std::abs(track.eta()) >= cfgTrkEtaCut) { - return false; + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (!myTrkSel.IsSelected(track, static_cast(i))) { + return false; + } + } + return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); } - if (track.pt() < cfgTrkLowPtCut) { - return false; + return track.isGlobalTrack(); + } + + template + bool isDCAxyWoCut(T const& track) // function to skip DCA track selections + { + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (i == static_cast(TrackSelection::TrackCuts::kDCAz)) { + continue; + } + if (!myTrkSel.IsSelected(track, static_cast(i))) { + return false; + } + } + return true; } - return true; + return track.isGlobalTrackWoDCA(); } template @@ -347,7 +375,7 @@ struct ueCharged { if (!pdgParticle || pdgParticle->Charge() == 0.) { return false; } - if (std::abs(particle.eta()) >= cfgTrkEtaCut) { + if (std::abs(particle.eta()) >= requireEta) { return false; } if (particle.pt() < cfgTrkLowPtCut) { @@ -505,7 +533,7 @@ struct ueCharged { std::vector indexArray; for (const auto& track : tracks) { - if (mySelectionOpenDCA.IsSelected(track)) + if (isDCAxyWoCut(track)) ue.fill(HIST("hPTVsDCAData"), track.pt(), track.dcaXY()); if (isTrackSelected(track)) { @@ -664,6 +692,10 @@ struct ueCharged { if (!foundRec) return; + if (analyzeEvandTracksel) { + analyzeEventAndTrackSelection(chosenRec, RecTracks.sliceBy(perCollision, chosenRecGlobalIndex)); + } + // compute truth-level leading particle and truth-region observables double flPtTrue = 0.; double flPhiTrue = 0.; @@ -679,6 +711,7 @@ struct ueCharged { flPhiTrue = particle.phi(); flIndexTrue = particle.globalIndex(); } + ue.fill(HIST("hPtAssoc_True"), particle.pt()); } ue.fill(HIST("hPtLeadingTrue"), flPtTrue); @@ -758,7 +791,7 @@ struct ueCharged { if (!pdgParticle || pdgParticle->Charge() == 0.) { continue; } - if (std::abs(particle.eta()) >= cfgTrkEtaCut) { + if (std::abs(particle.eta()) >= requireEta) { continue; } @@ -807,6 +840,7 @@ struct ueCharged { flPhi = track.phi(); flIndex = track.globalIndex(); } + ue.fill(HIST("hPtAssoc_Rec"), track.pt()); } ue.fill(HIST("hPtLeadingVsTracks"), flPt, track_multiplicity); @@ -827,7 +861,7 @@ struct ueCharged { if (track.collisionId() != chosenRecGlobalIndex) continue; - if (mySelectionOpenDCA.IsSelected(track)) + if (isDCAxyWoCut(track)) ue.fill(HIST("hPTVsDCAData"), track.pt(), track.dcaXY()); if (track.has_mcParticle()) { @@ -838,20 +872,20 @@ struct ueCharged { if (isTrackSelected(track)) ue.fill(HIST("hPtOut"), track.pt()); - if (mySelectionOpenDCA.IsSelected(track)) + if (isDCAxyWoCut(track)) ue.fill(HIST("hPtDCAall"), track.pt(), track.dcaXY()); if (particle.isPhysicalPrimary() && particle.producedByGenerator()) { // primary particles if (isTrackSelected(track) && isParticleSelected(particle)) { // TODO check if this condition ue.fill(HIST("hPtOutPrim"), particle.pt()); } - if (mySelectionOpenDCA.IsSelected(track)) { + if (isDCAxyWoCut(track)) { ue.fill(HIST("hPtDCAPrimary"), track.pt(), track.dcaXY()); } } else { // Secondaries (weak decays and material) if (isTrackSelected(track)) ue.fill(HIST("hPtOutSec"), track.pt()); - if (mySelectionOpenDCA.IsSelected(track)) { + if (isDCAxyWoCut(track)) { if (particle.getProcess() == 4) ue.fill(HIST("hPtDCAWeak"), track.pt(), track.dcaXY()); else @@ -991,7 +1025,7 @@ struct ueCharged { auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle || pdgParticle->Charge() == 0.) continue; - if (std::abs(particle.eta()) >= cfgTrkEtaCut) + if (std::abs(particle.eta()) >= requireEta) continue; multTrue++; if (particle.pt() < cfgTrkLowPtCut) @@ -1140,7 +1174,7 @@ struct ueCharged { tracks_before++; } - if (mySelectionPrim.IsSelected(track)) { + if (isTrackSelected(track)) { if (track.hasITS() && track.hasTPC()) { ue.fill(HIST("postselection_track/ITS/itsNCls"), track.itsNCls()); ue.fill(HIST("postselection_track/ITS/itsChi2NCl"), track.itsChi2NCl()); diff --git a/PWGUD/AQC/FITtest.cxx b/PWGUD/AQC/FITtest.cxx index 8cada664d74..e1f2ac5a19a 100644 --- a/PWGUD/AQC/FITtest.cxx +++ b/PWGUD/AQC/FITtest.cxx @@ -14,20 +14,24 @@ /// \since 04.08.2023 #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/LHCConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/BCRange.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "TLorentzVector.h" +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/AQC/udQC.cxx b/PWGUD/AQC/udQC.cxx index 3da67d1f683..0edcdc28117 100644 --- a/PWGUD/AQC/udQC.cxx +++ b/PWGUD/AQC/udQC.cxx @@ -14,17 +14,38 @@ /// \author Paul Buehler, paul.buehler@oeaw.ac.at /// \since 04.05.2023 -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/BCRange.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/DataModel/FT0Corrected.h" +#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UDHelpers.h" -#include "Framework/StaticFor.h" -#include "TLorentzVector.h" -#include "TMath.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/AQC/udQCmidRap.cxx b/PWGUD/AQC/udQCmidRap.cxx index acb35f21f57..6a2ea533d4c 100644 --- a/PWGUD/AQC/udQCmidRap.cxx +++ b/PWGUD/AQC/udQCmidRap.cxx @@ -14,16 +14,31 @@ /// \author Paul Buehler /// \since 17.01.2023 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/BCRange.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/DataModel/FT0Corrected.h" +#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UDHelpers.h" -#include "Framework/StaticFor.h" -#include "TLorentzVector.h" -#include "TMath.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/AQC/udQcMuon.cxx b/PWGUD/AQC/udQcMuon.cxx index eaa5f59bc8b..9f09ee2d2c9 100644 --- a/PWGUD/AQC/udQcMuon.cxx +++ b/PWGUD/AQC/udQcMuon.cxx @@ -16,18 +16,37 @@ /// \author Sara Haidlova, sara.haidlova@cern.ch /// \since 28.09.2025 +#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UDHelpers.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/StaticFor.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/BCRange.h" - +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include #include using namespace o2; diff --git a/PWGUD/Core/CMakeLists.txt b/PWGUD/Core/CMakeLists.txt index 7686edd8eea..3a7fe0950cf 100644 --- a/PWGUD/Core/CMakeLists.txt +++ b/PWGUD/Core/CMakeLists.txt @@ -64,3 +64,11 @@ o2physics_add_library(decayTree o2physics_target_root_dictionary(decayTree HEADERS decayTree.h LINKDEF decayTreeLinkDef.h) + +o2physics_add_library(FITCutParHolder + SOURCES FITCutParHolder.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + +o2physics_target_root_dictionary(FITCutParHolder + HEADERS FITCutParHolder.h + LINKDEF FITCutParHolderLinkDef.h) \ No newline at end of file diff --git a/PWGUD/Core/DGCutparHolder.cxx b/PWGUD/Core/DGCutparHolder.cxx index 5775a7dd47e..ee003684f5a 100644 --- a/PWGUD/Core/DGCutparHolder.cxx +++ b/PWGUD/Core/DGCutparHolder.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "DGCutparHolder.h" +#include "PWGUD/Core/DGCutparHolder.h" #include diff --git a/PWGUD/Core/DGCutparHolder.h b/PWGUD/Core/DGCutparHolder.h index 8312d72ac32..a67aefc4080 100644 --- a/PWGUD/Core/DGCutparHolder.h +++ b/PWGUD/Core/DGCutparHolder.h @@ -13,6 +13,7 @@ #define PWGUD_CORE_DGCUTPARHOLDER_H_ #include + #include // object to hold customizable cut values diff --git a/PWGUD/Core/DGPIDSelector.cxx b/PWGUD/Core/DGPIDSelector.cxx index 04dab87ef7a..7e0de287e48 100644 --- a/PWGUD/Core/DGPIDSelector.cxx +++ b/PWGUD/Core/DGPIDSelector.cxx @@ -8,11 +8,22 @@ // 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 "CommonConstants/PhysicsConstants.h" #include "DGPIDSelector.h" +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + // ----------------------------------------------------------------------------- float particleMass(TDatabasePDG* pdg, int pid) { diff --git a/PWGUD/Core/DGPIDSelector.h b/PWGUD/Core/DGPIDSelector.h index 74ad6b54a58..de825ab3568 100644 --- a/PWGUD/Core/DGPIDSelector.h +++ b/PWGUD/Core/DGPIDSelector.h @@ -12,12 +12,16 @@ #ifndef PWGUD_CORE_DGPIDSELECTOR_H_ #define PWGUD_CORE_DGPIDSELECTOR_H_ -#include -#include +#include + +#include +#include #include -#include "TDatabasePDG.h" -#include "TLorentzVector.h" -#include "Framework/Logger.h" + +#include +#include +#include +#include const int numDGPIDCutParameters = 9; float particleMass(TDatabasePDG* pdg, int pid); diff --git a/PWGUD/Core/DGSelector.h b/PWGUD/Core/DGSelector.h index c9349da9247..5c9afa99d00 100644 --- a/PWGUD/Core/DGSelector.h +++ b/PWGUD/Core/DGSelector.h @@ -12,14 +12,19 @@ #ifndef PWGUD_CORE_DGSELECTOR_H_ #define PWGUD_CORE_DGSELECTOR_H_ -#include - -#include "TDatabasePDG.h" -#include "TLorentzVector.h" -#include "Framework/Logger.h" -#include "Framework/AnalysisTask.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/DGCutparHolder.h" +#include "PWGUD/Core/UDHelpers.h" + +#include + +#include +#include +#include + +#include + +#include +#include // ----------------------------------------------------------------------------- // add here Selectors for different types of diffractive events diff --git a/PWGUD/Core/FITCutParHolder.cxx b/PWGUD/Core/FITCutParHolder.cxx new file mode 100644 index 00000000000..d57e2c8e12f --- /dev/null +++ b/PWGUD/Core/FITCutParHolder.cxx @@ -0,0 +1,55 @@ +// 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. +// +// \FIT bit thresholds +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#include "FITCutParHolder.h" + +// setter +void FITCutParHolder::SetSaveFITbitsets(bool saveFITbitsets) +{ + mSaveFITbitsets = saveFITbitsets; +} +void FITCutParHolder::SetThr1FV0A(float thr1_FV0A) +{ + mThr1FV0A = thr1_FV0A; +} +void FITCutParHolder::SetThr1FT0A(float thr1_FT0A) +{ + mThr1FT0A = thr1_FT0A; +} +void FITCutParHolder::SetThr1FT0C(float thr1_FT0C) +{ + mThr1FT0C = thr1_FT0C; +} +void FITCutParHolder::SetThr2FV0A(float thr2_FV0A) +{ + mThr2FV0A = thr2_FV0A; +} +void FITCutParHolder::SetThr2FT0A(float thr2_FT0A) +{ + mThr2FT0A = thr2_FT0A; +} +void FITCutParHolder::SetThr2FT0C(float thr2_FT0C) +{ + mThr2FT0C = thr2_FT0C; +} + +// getter +bool FITCutParHolder::saveFITbitsets() const { return mSaveFITbitsets; } +float FITCutParHolder::thr1_FV0A() const { return mThr1FV0A; } +float FITCutParHolder::thr1_FT0A() const { return mThr1FT0A; } +float FITCutParHolder::thr1_FT0C() const { return mThr1FT0C; } +float FITCutParHolder::thr2_FV0A() const { return mThr2FV0A; } +float FITCutParHolder::thr2_FT0A() const { return mThr2FT0A; } +float FITCutParHolder::thr2_FT0C() const { return mThr2FT0C; } diff --git a/PWGUD/Core/FITCutParHolder.h b/PWGUD/Core/FITCutParHolder.h new file mode 100644 index 00000000000..e03c4161c27 --- /dev/null +++ b/PWGUD/Core/FITCutParHolder.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. +// +// \FIT bit thresholds +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#ifndef PWGUD_CORE_FITCUTPARHOLDER_H_ +#define PWGUD_CORE_FITCUTPARHOLDER_H_ + +#include + +// object to hold customizable FIT bit thresholds +class FITCutParHolder +{ + public: + // constructor + FITCutParHolder(bool saveFITbitsets = true, + float thr1_FV0A = 8., + float thr1_FT0A = 8., + float thr1_FT0C = 8., + float thr2_FV0A = 20., + float thr2_FT0A = 20., + float thr2_FT0C = 20.) + : mSaveFITbitsets{saveFITbitsets}, + mThr1FV0A{thr1_FV0A}, + mThr1FT0A{thr1_FT0A}, + mThr1FT0C{thr1_FT0C}, + mThr2FV0A{thr2_FV0A}, + mThr2FT0A{thr2_FT0A}, + mThr2FT0C{thr2_FT0C} + { + } + + // setters + void SetSaveFITbitsets(bool); + void SetThr1FV0A(float); + void SetThr1FT0A(float); + void SetThr1FT0C(float); + void SetThr2FV0A(float); + void SetThr2FT0A(float); + void SetThr2FT0C(float); + + // getters + bool saveFITbitsets() const; + float thr1_FV0A() const; + float thr1_FT0A() const; + float thr1_FT0C() const; + float thr2_FV0A() const; + float thr2_FT0A() const; + float thr2_FT0C() const; + + private: + bool mSaveFITbitsets; + + float mThr1FV0A; + float mThr1FT0A; + float mThr1FT0C; + + float mThr2FV0A; + float mThr2FT0A; + float mThr2FT0C; + + ClassDefNV(FITCutParHolder, 1); +}; + +#endif // PWGUD_CORE_FITCUTPARHOLDER_H_ diff --git a/PWGUD/Core/FITCutParHolderLinkDef.h b/PWGUD/Core/FITCutParHolderLinkDef.h new file mode 100644 index 00000000000..3194a6754b2 --- /dev/null +++ b/PWGUD/Core/FITCutParHolderLinkDef.h @@ -0,0 +1,24 @@ +// 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. +// +// \FIT bit thresholds +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#ifndef PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_ +#define PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +#pragma link C++ class FITCutParHolder + ; + +#endif // PWGUD_CORE_FITCUTPARHOLDERLINKDEF_H_ diff --git a/PWGUD/Core/SGCutParHolder.cxx b/PWGUD/Core/SGCutParHolder.cxx index d171bd45a61..ba180a97280 100644 --- a/PWGUD/Core/SGCutParHolder.cxx +++ b/PWGUD/Core/SGCutParHolder.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include "SGCutParHolder.h" +#include "PWGUD/Core/SGCutParHolder.h" #include diff --git a/PWGUD/Core/SGCutParHolder.h b/PWGUD/Core/SGCutParHolder.h index 753e9f0c96f..fcee2d79703 100644 --- a/PWGUD/Core/SGCutParHolder.h +++ b/PWGUD/Core/SGCutParHolder.h @@ -13,6 +13,7 @@ #define PWGUD_CORE_SGCUTPARHOLDER_H_ #include + #include // object to hold customizable cut values diff --git a/PWGUD/Core/SGCutParHolderLinkDef.h b/PWGUD/Core/SGCutParHolderLinkDef.h index f9216fa0c37..5dcadadc69e 100644 --- a/PWGUD/Core/SGCutParHolderLinkDef.h +++ b/PWGUD/Core/SGCutParHolderLinkDef.h @@ -8,6 +8,7 @@ // 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 PWGUD_CORE_SGCUTPARHOLDERLINKDEF_H_ #define PWGUD_CORE_SGCUTPARHOLDERLINKDEF_H_ diff --git a/PWGUD/Core/SGSelector.h b/PWGUD/Core/SGSelector.h index 881cfb603bb..4e2cef35a85 100644 --- a/PWGUD/Core/SGSelector.h +++ b/PWGUD/Core/SGSelector.h @@ -24,16 +24,17 @@ #include "Common/CCDB/RCTSelectionFlags.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" +#include +#include #include +#include #include #include template struct SelectionResult { - int value; // The original integer return value + int value; // The original integer return value std::shared_ptr bc; // Pointer to the BC object }; diff --git a/PWGUD/Core/SGTrackSelector.h b/PWGUD/Core/SGTrackSelector.h index 455eaf24ac1..b571faf07f7 100644 --- a/PWGUD/Core/SGTrackSelector.h +++ b/PWGUD/Core/SGTrackSelector.h @@ -16,18 +16,10 @@ #ifndef PWGUD_CORE_SGTRACKSELECTOR_H_ #define PWGUD_CORE_SGTRACKSELECTOR_H_ -#include "PWGUD/Core/SGSelector.h" -#include "PWGUD/DataModel/UDTables.h" +#include -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "TVector3.h" -#include - -#include +#include +#include #include template diff --git a/PWGUD/Core/UDFSParser.cxx b/PWGUD/Core/UDFSParser.cxx index 08c6b947ab2..961412106c8 100644 --- a/PWGUD/Core/UDFSParser.cxx +++ b/PWGUD/Core/UDFSParser.cxx @@ -11,13 +11,18 @@ #include "UDFSParser.h" -#include "CommonConstants/LHCConstants.h" -#include "CommonDataFormat/BunchFilling.h" -#include "Framework/Logger.h" +#include +#include +#include +#include +#include +#include #include #include +#include + // ----------------------------------------------------------------------------- UDFSParser::UDFSParser(const char* filename) { diff --git a/PWGUD/Core/UDFSParser.h b/PWGUD/Core/UDFSParser.h index 6ceddafa5df..a48fb9f8a4f 100644 --- a/PWGUD/Core/UDFSParser.h +++ b/PWGUD/Core/UDFSParser.h @@ -12,7 +12,6 @@ #ifndef PWGUD_CORE_UDFSPARSER_H_ #define PWGUD_CORE_UDFSPARSER_H_ -// #include #include #include diff --git a/PWGUD/Core/UDGoodRunSelector.cxx b/PWGUD/Core/UDGoodRunSelector.cxx index c9c7d317ec7..c8203a7a569 100644 --- a/PWGUD/Core/UDGoodRunSelector.cxx +++ b/PWGUD/Core/UDGoodRunSelector.cxx @@ -11,10 +11,10 @@ #include "PWGUD/Core/UDGoodRunSelector.h" -#include "Framework/Logger.h" +#include -#include "rapidjson/document.h" -#include "rapidjson/filereadstream.h" +#include +#include #include #include diff --git a/PWGUD/Core/UDGoodRunSelector.h b/PWGUD/Core/UDGoodRunSelector.h index 4cf49330698..1b73f2c3ac4 100644 --- a/PWGUD/Core/UDGoodRunSelector.h +++ b/PWGUD/Core/UDGoodRunSelector.h @@ -12,8 +12,8 @@ #ifndef PWGUD_CORE_UDGOODRUNSELECTOR_H_ #define PWGUD_CORE_UDGOODRUNSELECTOR_H_ -#include #include +#include #include // A class to select good runs diff --git a/PWGUD/Core/UDHelpers.h b/PWGUD/Core/UDHelpers.h index a4137784ac5..94d356501a7 100644 --- a/PWGUD/Core/UDHelpers.h +++ b/PWGUD/Core/UDHelpers.h @@ -19,18 +19,25 @@ #include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UPCHelpers.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFIT/Triggers.h" -#include "DataFormatsFT0/Digit.h" -#include "Framework/Logger.h" +#include +#include +#include +#include +#include -#include "TLorentzVector.h" +#include -#include +#include + +#include +#include +#include +#include +#include +#include #include // namespace with helpers for UD framework @@ -534,6 +541,160 @@ bool FITveto(T const& bc, DGCutparHolder const& diffCuts) return false; } +inline void setBit(uint64_t w[4], int bit, bool val) +{ + if (!val) { + return; + } + const int word = bit >> 6; + const int offs = bit & 63; + w[word] |= (static_cast(1) << offs); +} + +template +inline void buildFT0FV0Words(TFT0 const& ft0, TFV0A const& fv0a, + uint64_t thr1[4], uint64_t thr2[4], + float thr1_FT0A = 25., float thr1_FT0C = 50., float thr1_FV0A = 50., + float thr2_FT0A = 50., float thr2_FT0C = 100., float thr2_FV0A = 100.) +{ + thr1[0] = thr1[1] = thr1[2] = thr1[3] = 0ull; + thr2[0] = thr2[1] = thr2[2] = thr2[3] = 0ull; + + constexpr int kFT0AOffset = 0; + constexpr int kFT0COffset = 96; + constexpr int kFV0Offset = 208; + + auto ampsA = ft0.amplitudeA(); + const int nA = std::min(ampsA.size(), 96); + for (int i = 0; i < nA; ++i) { + const auto a = ampsA[i]; + setBit(thr1, kFT0AOffset + i, a >= thr1_FT0A); + setBit(thr2, kFT0AOffset + i, a >= thr2_FT0A); + } + + auto ampsC = ft0.amplitudeC(); + const int nC = std::min(ampsC.size(), 112); + for (int i = 0; i < nC; ++i) { + const auto a = ampsC[i]; + setBit(thr1, kFT0COffset + i, a >= thr1_FT0C); + setBit(thr2, kFT0COffset + i, a >= thr2_FT0C); + } + + auto ampsV = fv0a.amplitude(); + const int nV = std::min(ampsV.size(), 48); + for (int i = 0; i < nV; ++i) { + const auto a = ampsV[i]; + setBit(thr1, kFV0Offset + i, a >= thr1_FV0A); + setBit(thr2, kFV0Offset + i, a >= thr2_FV0A); + } +} + +// ----------------------------------------------------------------------------- +// return eta and phi of a given FIT channel based on the bitset +// Bit layout contract: +constexpr int kFT0Bits = 208; // FT0 total channels +constexpr int kFV0Bits = 48; // FV0A channels +constexpr int kTotalBits = 256; // 4*64 + +// FT0 side split +constexpr int kFT0AChannels = 96; // FT0A channels are [0..95] +constexpr int kFT0CChannels = 112; // FT0C channels are [96..207] +static_assert(kFT0AChannels + kFT0CChannels == kFT0Bits); + +using Bits256 = std::array; + +inline Bits256 makeBits256(uint64_t w0, uint64_t w1, uint64_t w2, uint64_t w3) +{ + return {w0, w1, w2, w3}; +} + +inline bool testBit(Bits256 const& w, int bit) +{ + if (bit < 0 || bit >= kTotalBits) { + return false; + } + return (w[bit >> 6] >> (bit & 63)) & 1ULL; +} + +struct FitBitRef { + enum class Det : uint8_t { FT0, + FV0, + Unknown }; + Det det = Det::Unknown; + int ch = -1; // FT0: 0..207, FV0: 0..47 + bool isC = false; // only meaningful for FT0 +}; + +inline FitBitRef decodeFitBit(int bit) +{ + FitBitRef out; + if (bit >= 0 && bit < kFT0Bits) { + out.det = FitBitRef::Det::FT0; + out.ch = bit; // FT0 channel id + out.isC = (bit >= kFT0AChannels); // C side if in upper range + return out; + } + if (bit >= kFT0Bits && bit < kTotalBits) { + out.det = FitBitRef::Det::FV0; + out.ch = bit - kFT0Bits; // FV0A channel id 0..47 + return out; + } + return out; +} + +template +inline double getPhiFT0_fromChannel(FT0DetT& ft0Det, int ft0Ch, OffsetsT const& offsetFT0, int i) +{ + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(ft0Ch); + + const double x = chPos.X() + offsetFT0[i].getX(); + const double y = chPos.Y() + offsetFT0[i].getY(); + + return RecoDecay::phi(x, y); +} + +template +inline double getEtaFT0_fromChannel(FT0DetT& ft0Det, int ft0Ch, OffsetsT const& offsetFT0, int i) +{ + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(ft0Ch); + + double x = chPos.X() + offsetFT0[i].getX(); + double y = chPos.Y() + offsetFT0[i].getY(); + double z = chPos.Z() + offsetFT0[i].getZ(); + + // If this channel belongs to FT0C, flip z (matches your original intent) + const bool isC = (ft0Ch >= kFT0AChannels); + if (isC) { + z = -z; + } + + const double r = std::sqrt(x * x + y * y); + const double theta = std::atan2(r, z); + return -std::log(std::tan(0.5 * theta)); +} + +template +inline bool getPhiEtaFromFitBit(FT0DetT& ft0Det, + int bit, + OffsetsT const& offsetFT0, + int iRunOffset, + double& phi, + double& eta) +{ + auto ref = decodeFitBit(bit); + if (ref.det != FitBitRef::Det::FT0) { + return false; + } + + // FT0A: 0..95, FT0C: 96..207 + const int ft0Ch = bit; + phi = getPhiFT0_fromChannel(ft0Det, ft0Ch, offsetFT0, iRunOffset); + eta = getEtaFT0_fromChannel(ft0Det, ft0Ch, offsetFT0, iRunOffset); + return true; +} + // ----------------------------------------------------------------------------- template diff --git a/PWGUD/Core/UPCHelpers.h b/PWGUD/Core/UPCHelpers.h index 9dfa5fe3776..8495f9c5adc 100644 --- a/PWGUD/Core/UPCHelpers.h +++ b/PWGUD/Core/UPCHelpers.h @@ -14,13 +14,14 @@ #include "UPCCutparHolder.h" -#include "PWGUD/DataModel/UDTables.h" - -#include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include -#include "CommonConstants/LHCConstants.h" -#include "Framework/AnalysisDataModel.h" +#include using BCsWithBcSels = o2::soa::Join; diff --git a/PWGUD/Core/UPCJpsiCentralBarrelCorrHelper.h b/PWGUD/Core/UPCJpsiCentralBarrelCorrHelper.h index 2a53f2f41f8..83a3eed9053 100644 --- a/PWGUD/Core/UPCJpsiCentralBarrelCorrHelper.h +++ b/PWGUD/Core/UPCJpsiCentralBarrelCorrHelper.h @@ -16,9 +16,17 @@ #ifndef PWGUD_CORE_UPCJPSICENTRALBARRELCORRHELPER_H_ #define PWGUD_CORE_UPCJPSICENTRALBARRELCORRHELPER_H_ -#include "CommonConstants/MathConstants.h" +#include + +#include + +#include #include +#include +#include +#include +#include #include #include diff --git a/PWGUD/Core/UPCPairCuts.h b/PWGUD/Core/UPCPairCuts.h index f53b419ffda..817e4a86cfd 100644 --- a/PWGUD/Core/UPCPairCuts.h +++ b/PWGUD/Core/UPCPairCuts.h @@ -18,10 +18,13 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" +#include +#include +#include +#include +#include + +#include #include diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index 41af7ec5d78..ea4652b9b77 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -18,11 +18,14 @@ #ifndef PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ #define PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include + +#include #include +#include +#include #include enum MyParticle { diff --git a/PWGUD/Core/decayTree.cxx b/PWGUD/Core/decayTree.cxx index ed05772364e..ded7c2fa329 100644 --- a/PWGUD/Core/decayTree.cxx +++ b/PWGUD/Core/decayTree.cxx @@ -11,10 +11,20 @@ #include "decayTree.h" +#include +#include + +#include + #include #include +#include +#include +#include #include +#include +#include #include #include #include diff --git a/PWGUD/Core/decayTree.h b/PWGUD/Core/decayTree.h index 59421098605..162a1859181 100644 --- a/PWGUD/Core/decayTree.h +++ b/PWGUD/Core/decayTree.h @@ -12,15 +12,19 @@ #ifndef PWGUD_CORE_DECAYTREE_H_ #define PWGUD_CORE_DECAYTREE_H_ -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include -#include "TDatabasePDG.h" -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include #include +#include #include #include #include diff --git a/PWGUD/DataModel/McPIDTable.h b/PWGUD/DataModel/McPIDTable.h index 3e2bf256db9..7f9cf4ea875 100644 --- a/PWGUD/DataModel/McPIDTable.h +++ b/PWGUD/DataModel/McPIDTable.h @@ -8,10 +8,11 @@ // 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 O2_ANALYSIS_UDDIFFMCSCAN_H -#define O2_ANALYSIS_UDDIFFMCSCAN_H -#include "Framework/AnalysisDataModel.h" +#ifndef PWGUD_DATAMODEL_MCPIDTABLE_H_ +#define PWGUD_DATAMODEL_MCPIDTABLE_H_ + +#include namespace o2::aod { @@ -33,4 +34,4 @@ DECLARE_SOA_TABLE(UDnSigmas, "AOD", "UDNSIGMAS", //! MCTruth of particle PID and } // namespace o2::aod -#endif // O2_ANALYSIS_UDDIFFMCSCAN_H +#endif // PWGUD_DATAMODEL_MCPIDTABLE_H_ diff --git a/PWGUD/DataModel/SGTables.h b/PWGUD/DataModel/SGTables.h index bf9ef68da96..4e959cf886f 100644 --- a/PWGUD/DataModel/SGTables.h +++ b/PWGUD/DataModel/SGTables.h @@ -12,14 +12,11 @@ #ifndef PWGUD_DATAMODEL_SGTABLES_H_ #define PWGUD_DATAMODEL_SGTABLES_H_ -#include +#include +#include + #include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/DataTypes.h" -#include "MathUtils/Utils.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include namespace o2::aod { diff --git a/PWGUD/DataModel/TauEventTables.h b/PWGUD/DataModel/TauEventTables.h index f508cbc2c4d..ae0fd33496e 100644 --- a/PWGUD/DataModel/TauEventTables.h +++ b/PWGUD/DataModel/TauEventTables.h @@ -16,10 +16,12 @@ /// \brief A table to store information about events preselected to be candidates for UPC gammagamma->tautau /// -#ifndef ALISW_TAUEVENTTABLES_H -#define ALISW_TAUEVENTTABLES_H +#ifndef PWGUD_DATAMODEL_TAUEVENTTABLES_H_ +#define PWGUD_DATAMODEL_TAUEVENTTABLES_H_ -#include "Framework/AnalysisDataModel.h" +#include + +#include namespace o2::aod { @@ -221,4 +223,4 @@ DECLARE_SOA_TABLE(TrueTauTwoTracks, "AOD", "TRUETAUTWOTRACK", } // namespace o2::aod -#endif // ALISW_TAUEVENTTABLES_H +#endif // PWGUD_DATAMODEL_TAUEVENTTABLES_H_ diff --git a/PWGUD/DataModel/TauThreeProngEventTables.h b/PWGUD/DataModel/TauThreeProngEventTables.h index b670e8b7f69..bd7da95f14c 100644 --- a/PWGUD/DataModel/TauThreeProngEventTables.h +++ b/PWGUD/DataModel/TauThreeProngEventTables.h @@ -19,7 +19,9 @@ #ifndef PWGUD_DATAMODEL_TAUTHREEPRONGEVENTTABLES_H_ #define PWGUD_DATAMODEL_TAUTHREEPRONGEVENTTABLES_H_ -#include "Framework/AnalysisDataModel.h" +#include + +#include // derived tables for tautau->4 (=1+3) tracks namespace o2::aod { @@ -84,7 +86,7 @@ DECLARE_SOA_COLUMN(TrkTOFnSigmaMu, trkTOFnSigmaMu, float[6]); DECLARE_SOA_COLUMN(TrkTOFchi2, trkTOFchi2, float[6]); // truth event DECLARE_SOA_COLUMN(TrueChannel, trueChannel, int); -DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); +// DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); // DECLARE_SOA_COLUMN(TruePosX, truePosX, float); // DECLARE_SOA_COLUMN(TruePosY, truePosY, float); DECLARE_SOA_COLUMN(TruePosZ, truePosZ, float); @@ -145,7 +147,7 @@ DECLARE_SOA_TABLE(TrueTauFourTracks, "AOD", "TRUETAU", tautree::TrkTOFbeta, tautree::TrkTOFnSigmaEl, tautree::TrkTOFnSigmaPi, tautree::TrkTOFnSigmaKa, tautree::TrkTOFnSigmaPr, tautree::TrkTOFnSigmaMu, tautree::TrkTOFchi2, tautree::TrueChannel, - tautree::TrueHasRecoColl, + // tautree::TrueHasRecoColl, tautree::TruePosZ, tautree::TrueTauPx, tautree::TrueTauPy, tautree::TrueTauPz, tautree::TrueDaugPx, tautree::TrueDaugPy, tautree::TrueDaugPz, diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h index 73be3f3c438..0f50fe2f493 100644 --- a/PWGUD/DataModel/TwoTracksEventTables.h +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -21,7 +21,9 @@ #ifndef PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ #define PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ -#include "Framework/AnalysisDataModel.h" +#include + +#include namespace o2::aod { @@ -29,7 +31,7 @@ namespace two_tracks_tree { // event info DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); -DECLARE_SOA_COLUMN(Bc, bc, int); +DECLARE_SOA_COLUMN(Bc, bc, uint64_t); DECLARE_SOA_COLUMN(TotalTracks, totalTracks, int); DECLARE_SOA_COLUMN(NumContrib, numContrib, int); DECLARE_SOA_COLUMN(GlobalNonPVtracks, globalNonPVtracks, int); diff --git a/PWGUD/DataModel/UDIndex.h b/PWGUD/DataModel/UDIndex.h index 8a4a236c5af..16a7ed3a5ed 100644 --- a/PWGUD/DataModel/UDIndex.h +++ b/PWGUD/DataModel/UDIndex.h @@ -19,9 +19,10 @@ #ifndef PWGUD_DATAMODEL_UDINDEX_H_ #define PWGUD_DATAMODEL_UDINDEX_H_ -#include "UDTables.h" +#include "PWGUD/DataModel/UDTables.h" // IWYU pragma: keep + +#include -#include "Framework/AnalysisDataModel.h" namespace o2::aod { namespace udidx @@ -32,4 +33,5 @@ DECLARE_SOA_ARRAY_INDEX_COLUMN(UDCollision, udcollisions); DECLARE_SOA_TABLE(UDMcParticlesToUDTracks, "AOD", "UDP2UDT", udidx::UDTrackIds); DECLARE_SOA_TABLE(UDMcCollisionsToUDCollisions, "AOD", "UDMCC2UDC", udidx::UDCollisionIds); } // namespace o2::aod + #endif // PWGUD_DATAMODEL_UDINDEX_H_ diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index 8a4251ec74d..afb7728a5ab 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -21,15 +21,17 @@ #ifndef PWGUD_DATAMODEL_UDTABLES_H_ #define PWGUD_DATAMODEL_UDTABLES_H_ -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/DataTypes.h" -#include "MathUtils/Utils.h" +#include +#include + +#include #include +#include #include namespace o2::aod @@ -406,6 +408,31 @@ DECLARE_SOA_TABLE(UDTracksFlags, "AOD", "UDTRACKFLAG", DECLARE_SOA_TABLE(UDTracksLabels, "AOD", "UDTRACKLABEL", udtrack::TrackId); +namespace udcollfitbits +{ +DECLARE_SOA_COLUMN(Thr1W0, thr1W0, uint64_t); /// 1 MIP thresholds for FT0A ch 0 - ch 63 +DECLARE_SOA_COLUMN(Thr1W1, thr1W1, uint64_t); /// 1 MIP thresholds for FT0A ch 64 - ch 96 & FT0C ch 0 - ch 31 +DECLARE_SOA_COLUMN(Thr1W2, thr1W2, uint64_t); /// 1 MIP thresholds for FT0C ch 32 - ch 96 +DECLARE_SOA_COLUMN(Thr1W3, thr1W3, uint64_t); /// 1 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 + +DECLARE_SOA_COLUMN(Thr2W0, thr2W0, uint64_t); /// 2 MIP thresholds for FT0A ch 0 - ch 63 +DECLARE_SOA_COLUMN(Thr2W1, thr2W1, uint64_t); /// 2 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31 +DECLARE_SOA_COLUMN(Thr2W2, thr2W2, uint64_t); /// 2 MIP thresholds for FT0C ch 32 - ch 96 +DECLARE_SOA_COLUMN(Thr2W3, thr2W3, uint64_t); /// 2 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 +} // namespace udcollfitbits + +DECLARE_SOA_TABLE(UDCollisionFITBits, "AOD", "UDCOLLFITBITS", + o2::soa::Index<>, + udcollfitbits::Thr1W0, /// 1 MIP thresholds for FT0A ch 0 - ch 63 + udcollfitbits::Thr1W1, /// 1 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31 + udcollfitbits::Thr1W2, /// 1 MIP thresholds for FT0C ch 32 - ch 96 + udcollfitbits::Thr1W3, /// 1 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 + udcollfitbits::Thr2W0, /// 2 MIP thresholds for FT0A ch 0 - ch 63 + udcollfitbits::Thr2W1, /// 2 MIP thresholds for FT0A ch 63 - ch 96 & FT0C ch 0 - ch 31 + udcollfitbits::Thr2W2, /// 2 MIP thresholds for FT0C ch 32 - ch 96 + udcollfitbits::Thr2W3 /// 2 MIP thresholds for FT0C ch 97 - 112 & FV0 0 - 47 +); + using UDTrack = UDTracks::iterator; using UDTrackCov = UDTracksCov::iterator; using UDTrackExtra = UDTracksExtra::iterator; diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index c2fa718ddd0..c16870f0603 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -11,14 +11,14 @@ add_subdirectory(Converters) -o2physics_add_dpl_workflow(dgcand-producer - SOURCES DGCandProducer.cxx +o2physics_add_dpl_workflow(dg-cand-producer + SOURCES dgCandProducer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(sgcand-producer SOURCES SGCandProducer.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::SGCutParHolder O2Physics::AnalysisCCDB O2Physics::FITCutParHolder COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dgbccand-producer @@ -65,3 +65,8 @@ o2physics_add_dpl_workflow(upc-cand-producer-muon SOURCES upcCandProducerMuon.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upc-cand-producer-global-muon + SOURCES upcCandProducerGlobalMuon.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::UPCCutparHolder O2::GlobalTracking + COMPONENT_NAME Analysis) diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx index 1fa1882e7d5..38ecb5abeb3 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasConverter.cxx @@ -20,11 +20,13 @@ /// \author Sasha Bylinkin -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "PWGUD/DataModel/UDTables.h" +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx index b10b467ec4d..d2b4d6408b4 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV002Converter.cxx @@ -13,11 +13,15 @@ /// \brief Converts UDCollisionSelExtras table from version 000 to 002 and 001 to 002 /// \author Roman Lavicka -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "PWGUD/DataModel/UDTables.h" +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx index a41b2c4efa6..e52b6fce784 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx @@ -15,9 +15,12 @@ #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx b/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx index 8be7bce717b..99de6088fb4 100644 --- a/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx +++ b/PWGUD/TableProducer/Converters/UDCollisionsConverter.cxx @@ -20,11 +20,13 @@ /// \author Sasha Bylinkin -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "PWGUD/DataModel/UDTables.h" +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx b/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx index f9b1f2d0d22..4806232f490 100644 --- a/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx +++ b/PWGUD/TableProducer/Converters/UDFwdTracksExtraConverter.cxx @@ -21,11 +21,13 @@ /// \author Andrea Giovanni Riffero -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "PWGUD/DataModel/UDTables.h" +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/DGBCCandProducer.cxx b/PWGUD/TableProducer/DGBCCandProducer.cxx index 97b60c42c9e..eb272397af3 100644 --- a/PWGUD/TableProducer/DGBCCandProducer.cxx +++ b/PWGUD/TableProducer/DGBCCandProducer.cxx @@ -14,15 +14,45 @@ /// \author Paul Buehler, paul.buehler@oeaw.ac.at /// \since 30.09.2022 -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/Vertex.h" -#include "PWGUD/DataModel/UDTables.h" +#include "DGBCCandProducer.h" + +#include "PWGUD/Core/DGCutparHolder.h" +#include "PWGUD/Core/DGSelector.h" #include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/Core/DGSelector.h" -#include "DGBCCandProducer.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/DGBCCandProducer.h b/PWGUD/TableProducer/DGBCCandProducer.h index 5bdc09498c6..64d30453dbf 100644 --- a/PWGUD/TableProducer/DGBCCandProducer.h +++ b/PWGUD/TableProducer/DGBCCandProducer.h @@ -16,13 +16,10 @@ #ifndef PWGUD_TABLEPRODUCER_DGBCCANDPRODUCER_H_ #define PWGUD_TABLEPRODUCER_DGBCCANDPRODUCER_H_ -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/DataTypes.h" -#include "MathUtils/Utils.h" +#include +#include -#include -#include +#include namespace o2::aod { diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index c3cb33cb43e..a45493d792e 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -12,37 +12,49 @@ /// \file SGCandProducer.cxx /// \brief Produces PWGUD derived table from standard tables /// -/// \author Alexander Bylinkin , Uniersity of Bergen -/// \since 23.11.2023 +/// \author Alexander Bylinkin , University of Bergen +/// \since 23.11.2023 /// \author Adam Matyja , INP PAN Krakow, Poland -/// \since May 2025 +/// \since May 2025 // +#include "PWGUD/Core/FITCutParHolder.h" +#include "PWGUD/Core/SGCutParHolder.h" #include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/EventSelection.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFIT/Triggers.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Vertex.h" - +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include #include +#include #include +#include #include #include @@ -75,6 +87,8 @@ struct SGCandProducer { // get an SGCutparHolder SGCutParHolder sameCuts = SGCutParHolder(); // SGCutparHolder Configurable SGCuts{"SGCuts", {}, "SG event cuts"}; + FITCutParHolder fitCuts = FITCutParHolder(); + Configurable FITCuts{"FITCuts", {}, "FIT bitset cuts"}; Configurable verboseInfo{"verboseInfo", false, "Print general info to terminal; default it false."}; Configurable saveAllTracks{"saveAllTracks", true, "save only PV contributors or all tracks associated to a collision"}; Configurable savenonPVCITSOnlyTracks{"savenonPVCITSOnlyTracks", false, "save non PV contributors with ITS only information"}; @@ -87,6 +101,8 @@ struct SGCandProducer { Configurable storeSG{"storeSG", true, "Store SG events in the output"}; Configurable storeDG{"storeDG", true, "Store DG events in the output"}; + Configurable saveFITbitsets{"saveFITbitsets", true, "Write FT0 and FV0 bitset tables to output"}; + Configurable isGoodRCTCollision{"isGoodRCTCollision", true, "Check RCT flags for FT0,ITS,TPC and tracking"}; Configurable isGoodRCTZdc{"isGoodRCTZdc", false, "Check RCT flags for ZDC if present in run"}; @@ -94,7 +110,7 @@ struct SGCandProducer { Configurable fillTrackTables{"fillTrackTables", true, "Fill track tables"}; Configurable fillFwdTrackTables{"fillFwdTrackTables", true, "Fill forward track tables"}; - // SG selector + // SG selector SGSelector sgSelector; ctpRateFetcher mRateFetcher; @@ -119,6 +135,7 @@ struct SGCandProducer { Produces outputFwdTracks; Produces outputFwdTracksExtra; Produces outputTracksLabel; + Produces outputFITBits; // initialize histogram registry HistogramRegistry registry{ @@ -205,78 +222,6 @@ struct SGCandProducer { outputTracksLabel(track.globalIndex()); } - // function to process trigger counters, accounting for BC selection bits - void processCountersTrg(BCs const& bcs, aod::FT0s const&, aod::Zdcs const&) - { - const auto& firstBc = bcs.iteratorAt(0); - if (runNumber != firstBc.runNumber()) - runNumber = firstBc.runNumber(); - - auto hCountersTrg = getHist(TH1, "reco/hCountersTrg"); - auto hCountersTrgBcSel = getHist(TH1, "reco/hCountersTrgBcSel"); - auto hLumi = getHist(TH1, "reco/hLumi"); - auto hLumiBcSel = getHist(TH1, "reco/hLumiBcSel"); - - // Cross sections in ub. Using dummy -1 if lumi estimator is not reliable - float csTCE = 10.36e6; - const float csZEM = 415.2e6; // see AN: https://alice-notes.web.cern.ch/node/1515 - const float csZNC = 214.5e6; // see AN: https://alice-notes.web.cern.ch/node/1515 - if (runNumber > 543437 && runNumber < 543514) { - csTCE = 8.3e6; - } - if (runNumber >= 543514) { - csTCE = 4.10e6; // see AN: https://alice-notes.web.cern.ch/node/1515 - } - - for (const auto& bc : bcs) { - bool hasFT0 = bc.has_foundFT0(); - bool hasZDC = bc.has_foundZDC(); - if (!hasFT0 && !hasZDC) - continue; - bool isSelectedBc = true; - if (rejectAtTFBoundary && !bc.selection_bit(aod::evsel::kNoTimeFrameBorder)) - isSelectedBc = false; - if (noITSROFrameBorder && !bc.selection_bit(aod::evsel::kNoITSROFrameBorder)) - isSelectedBc = false; - if (hasFT0) { - auto ft0TrgMask = bc.ft0().triggerMask(); - if (TESTBIT(ft0TrgMask, o2::fit::Triggers::bitVertex)) { - hCountersTrg->Fill("TVX", 1); - if (isSelectedBc) - hCountersTrgBcSel->Fill("TVX", 1); - } - if (TESTBIT(ft0TrgMask, o2::fit::Triggers::bitVertex) && TESTBIT(ft0TrgMask, o2::fit::Triggers::bitCen)) { - hCountersTrg->Fill("TCE", 1); - hLumi->Fill("TCE", 1. / csTCE); - if (isSelectedBc) { - hCountersTrgBcSel->Fill("TCE", 1); - hLumiBcSel->Fill("TCE", 1. / csTCE); - } - } - } - if (hasZDC) { - if (bc.selection_bit(aod::evsel::kIsBBZNA) || bc.selection_bit(aod::evsel::kIsBBZNC)) { - hCountersTrg->Fill("ZEM", 1); - hLumi->Fill("ZEM", 1. / csZEM); - if (isSelectedBc) { - hCountersTrgBcSel->Fill("ZEM", 1); - hLumiBcSel->Fill("ZEM", 1. / csZEM); - } - } - if (bc.selection_bit(aod::evsel::kIsBBZNC)) { - hCountersTrg->Fill("ZNC", 1); - hLumi->Fill("ZNC", 1. / csZNC); - if (isSelectedBc) { - hCountersTrgBcSel->Fill("ZNC", 1); - hLumiBcSel->Fill("ZNC", 1. / csZNC); - } - } - } - } - } - - PROCESS_SWITCH(SGCandProducer, processCountersTrg, "Produce trigger counters and luminosity histograms", true); - // function to process reconstructed data template void processReco(std::string histdir, TCol const& collision, BCs const& bcs, @@ -284,7 +229,7 @@ struct SGCandProducer { aod::FV0As const& fv0as, aod::FT0s const& ft0s, aod::FDDs const& fdds) { if (verboseInfo) - LOGF(debug, " collision %d", collision.globalIndex()); + LOGF(debug, " collision %d", collision.globalIndex()); getHist(TH1, histdir + "/Stat")->Fill(0., 1.); // reject collisions at TF boundaries if (rejectAtTFBoundary && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { @@ -389,7 +334,26 @@ struct SGCandProducer { fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, collision.rct_raw()); + if (verboseInfo) + LOGF(info, "%s Coll GID %d", histdir, collision.globalIndex()); outputCollsLabels(collision.globalIndex()); + + uint64_t w1[4] = {0ull, 0ull, 0ull, 0ull}; + uint64_t w2[4] = {0ull, 0ull, 0ull, 0ull}; + + if (fitCuts.saveFITbitsets() && newbc.has_foundFT0() && newbc.has_fv0a()) { + udhelpers::buildFT0FV0Words(newbc.ft0(), newbc.fv0a(), w1, w2, + fitCuts.thr1_FT0A(), + fitCuts.thr1_FT0C(), + fitCuts.thr1_FV0A(), + fitCuts.thr2_FT0A(), + fitCuts.thr2_FT0C(), + fitCuts.thr2_FV0A()); + } + + outputFITBits(w1[0], w1[1], w1[2], w1[3], + w2[0], w2[1], w2[2], w2[3]); + if (newbc.has_zdc()) { auto zdc = newbc.zdc(); udZdcsReduced(outputCollisions.lastIndex(), zdc.timeZNA(), zdc.timeZNC(), zdc.energyCommonZNA(), zdc.energyCommonZNC()); @@ -405,7 +369,7 @@ struct SGCandProducer { } else if (saveAllTracks) { if (track.itsClusterSizes() && track.itsChi2NCl() > 0 && ((track.tpcNClsFindable() == 0 && savenonPVCITSOnlyTracks) || track.tpcNClsFindable() > 50)) updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); - // if (track.isPVContributor()) updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); + // if (track.isPVContributor()) updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); } } } @@ -428,6 +392,7 @@ struct SGCandProducer { ccdb->setCaching(true); ccdb->setFatalWhenNull(false); sameCuts = (SGCutParHolder)SGCuts; + fitCuts = (FITCutParHolder)FITCuts; // add histograms for the different process functions histPointers.clear(); @@ -481,7 +446,7 @@ struct SGCandProducer { if (std::find(generatorIds->begin(), generatorIds->end(), mccol.getGeneratorId()) != generatorIds->end()) { if (verboseInfo) - LOGF(info, "Event with good generatorId"); + LOGF(info, "Event with good generatorId %d", mccol.getGeneratorId()); processReco(std::string("MCreco"), collision, bcs, tracks, fwdtracks, fv0as, ft0s, fdds); } } @@ -589,7 +554,7 @@ struct McSGCandProducer { for (const auto& oldmid : oldmids) { auto m = McParts.rawIteratorAt(oldmid); if (verboseInfoMC) - LOGF(debug, " m %d", m.globalIndex()); + LOGF(debug, "m %d", m.globalIndex()); if (mcPartIsSaved.find(oldmid) != mcPartIsSaved.end()) { newval = mcPartIsSaved[oldmid]; } else { @@ -688,6 +653,8 @@ struct McSGCandProducer { // loop over McCollisions and UDCCs simultaneously auto mccol = mccols.iteratorAt(0); auto mcOfInterest = std::find(generatorIds->begin(), generatorIds->end(), mccol.getGeneratorId()) != generatorIds->end(); + if (verboseInfoMC) + LOGF(info, "Is Generator ID OK %d, MCcoll GenId %d, SubGenID %d, SourceId %d, Set in json ID %d", mcOfInterest, mccol.getGeneratorId(), mccol.getSubGeneratorId(), mccol.getSourceId(), *(generatorIds->begin())); auto lastmccol = mccols.iteratorAt(mccols.size() - 1); auto mccolAtEnd = false; @@ -701,6 +668,7 @@ struct McSGCandProducer { bool goon = true; while (goon) { auto globBC = mccol.bc_as().globalBC(); + // check if dgcand has an associated McCollision if (sgcand.has_collision()) { auto sgcandCol = sgcand.collision_as(); @@ -735,7 +703,7 @@ struct McSGCandProducer { if (mcsgId >= 0 && mcOfInterest) { if (mcColIsSaved.find(mcsgId) == mcColIsSaved.end()) { if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", mcsgId); + LOGF(info, "Saving McCollision %d", mcsgId); // update UDMcCollisions auto sgcandMcCol = sgcand.collision_as().mcCollision(); updateUDMcCollisions(sgcandMcCol, globBC); @@ -756,7 +724,7 @@ struct McSGCandProducer { // If the sgcand has no associated McCollision then only the McParticles which are associated // with the tracks of the sgcand are saved if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", -1); + LOGF(info, "Saving McCollision %d", -1); // update UDMcColsLabels (for each UDCollision -> UDMcCollisions) outputMcCollsLabels(-1); @@ -798,7 +766,7 @@ struct McSGCandProducer { // but only consider generated events of interest if (mcOfInterest && mcColIsSaved.find(mccolId) == mcColIsSaved.end()) { if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", mccolId); + LOGF(info, "Saving McCollision %d", mccolId); // update UDMcCollisions updateUDMcCollisions(mccol, globBC); mcColIsSaved[mccolId] = outputMcCollisions.lastIndex(); @@ -842,7 +810,7 @@ struct McSGCandProducer { // update UDMcCollisions and UDMcParticles if (mcColIsSaved.find(mccolId) == mcColIsSaved.end()) { if (verboseInfoMC) - LOGF(info, " Saving McCollision %d", mccolId); + LOGF(info, "Saving McCollision %d", mccolId); // update UDMcCollisions updateUDMcCollisions(mccol, globBC); @@ -875,6 +843,7 @@ struct McSGCandProducer { LOGF(info, "Number of McCollisions %d", mccols.size()); LOGF(info, "Number of SG candidates %d", sgcands.size()); LOGF(info, "Number of UD tracks %d", udtracks.size()); + LOGF(info, "Number of McParticles %d", mcparts.size()); } if (mccols.size() > 0) { if (sgcands.size() > 0) { diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 2208060bd59..d58c98ac587 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -11,6 +11,8 @@ /// \author Nazar Burmasov, nazar.burmasov@cern.ch /// \author Diana Krupova, diana.krupova@cern.ch /// \since 04.06.2024 +/// \author Andrea Riffero, andrea.giovanni.riffero@cern.ch +/// \since 19.03.2026 #include "PWGUD/Core/UPCCutparHolder.h" #include "PWGUD/Core/UPCHelpers.h" @@ -18,17 +20,36 @@ #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" - -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFIT/Triggers.h" -#include "DataFormatsITSMFT/ROFRecord.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include #include +#include +#include +#include #include #include +#include #include #include #include @@ -603,17 +624,25 @@ struct UpcCandProducer { // "uncorrected" bcs template void collectAmbTrackBCs(std::unordered_map& ambTrIds, + TBCs const& bcs, TAmbTracks ambTracks) { for (const auto& ambTrk : ambTracks) { auto trkId = getAmbTrackId(ambTrk); - const auto& bcSlice = ambTrk.template bc_as(); - uint64_t trackBC = -1; - if (bcSlice.size() != 0) { - auto first = bcSlice.begin(); - trackBC = first.globalBC(); + + const auto& bcIds = ambTrk.bcIds(); + if (bcIds.size() == 0) + continue; + + const auto firstBcId = static_cast(*bcIds.begin()); + if (firstBcId < 0 || firstBcId >= static_cast(bcs.size())) { + LOGP(debug, + "Skipping ambiguous track {}: invalid first bcId {} (nBCs = {})", + trkId, firstBcId, bcs.size()); + continue; } - ambTrIds[trkId] = trackBC; + + ambTrIds[trkId] = bcs.iteratorAt(firstBcId).globalBC(); } } @@ -649,16 +678,22 @@ struct UpcCandProducer { continue; int64_t trkId = trk.globalIndex(); int32_t nContrib = -1; + bool hasTrackBC = false; uint64_t trackBC = 0; if (trk.has_collision()) { const auto& col = trk.collision(); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); + hasTrackBC = true; } else { auto ambIter = ambBarrelTrBCs.find(trkId); - if (ambIter != ambBarrelTrBCs.end()) + if (ambIter != ambBarrelTrBCs.end()) { trackBC = ambIter->second; + hasTrackBC = true; + } } + if (!hasTrackBC) + continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fBarrelTrackTShift)); uint64_t bc = trackBC + tint; if (nContrib > upcCuts.getMaxNContrib()) @@ -683,15 +718,22 @@ struct UpcCandProducer { continue; int64_t trkId = trk.globalIndex(); int32_t nContrib = -1; + bool hasTrackBC = false; uint64_t trackBC = 0; auto ambIter = ambFwdTrBCs.find(trkId); if (ambIter == ambFwdTrBCs.end()) { + if (!trk.has_collision()) + continue; const auto& col = trk.collision(); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); + hasTrackBC = true; } else { trackBC = ambIter->second; + hasTrackBC = true; } + if (!hasTrackBC) + continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fMuonTrackTShift)); uint64_t bc = trackBC + tint; if (nContrib > upcCuts.getMaxNContrib()) @@ -716,9 +758,12 @@ struct UpcCandProducer { continue; int64_t trkId = trk.globalIndex(); int32_t nContrib = -1; + bool hasTrackBC = false; uint64_t trackBC = 0; auto ambIter = ambFwdTrBCs.find(trkId); if (ambIter == ambFwdTrBCs.end()) { + if (!trk.has_collision()) + continue; const auto& col = trk.collision(); nContrib = col.numContrib(); trackBC = col.bc_as().globalBC(); @@ -729,9 +774,13 @@ struct UpcCandProducer { if (fRequireNoITSROFrameBorder && !bc.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { continue; // skip this track if the kNoITSROFrameBorder bit is required but not set } + hasTrackBC = true; } else { trackBC = ambIter->second; + hasTrackBC = true; } + if (!hasTrackBC) + continue; int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + static_cast(fMuonTrackTShift)); uint64_t bc = trackBC + tint; if (nContrib > upcCuts.getMaxNContrib()) @@ -800,7 +849,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambBarrelTrBCs; if (upcCuts.getAmbigSwitch() != 1) - collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, ambBarrelTracks); + collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, bcs, ambBarrelTracks); collectBarrelTracks(bcsMatchedTrIdsTOF, 0, @@ -1101,10 +1150,10 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambBarrelTrBCs; - collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, ambBarrelTracks); + collectAmbTrackBCs<0, BCsWithBcSels>(ambBarrelTrBCs, bcs, ambBarrelTracks); std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs, ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack, @@ -1301,7 +1350,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs, ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack, @@ -1556,7 +1605,7 @@ struct UpcCandProducer { // trackID -> index in amb. track table std::unordered_map ambFwdTrBCs; - collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, ambFwdTracks); + collectAmbTrackBCs<1, BCsWithBcSels>(ambFwdTrBCs, bcs, ambFwdTracks); collectForwardTracks(bcsMatchedTrIdsMID, o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack, diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/dgCandProducer.cxx similarity index 96% rename from PWGUD/TableProducer/DGCandProducer.cxx rename to PWGUD/TableProducer/dgCandProducer.cxx index 5f9a4d4bb79..6c075229fb1 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/dgCandProducer.cxx @@ -12,21 +12,46 @@ // \brief Saves relevant information of DG candidates // \author Paul Buehler, paul.buehler@oeaw.ac.at +#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/DGSelector.h" +#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" +#include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/Zorro.h" #include "Common/Core/ZorroSummary.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Vertex.h" - +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include #include +#include #include #include @@ -36,7 +61,7 @@ using namespace o2::framework::expressions; #define getHist(type, name) std::get>(histPointers[name]) -struct DGCandProducer { +struct DgCandProducer { // data tables Produces outputCollisions; Produces outputCollisionsSels; @@ -449,7 +474,7 @@ struct DGCandProducer { { processReco(std::string("reco"), collision, bcs, tracks, fwdtracks, fv0as, ft0s, fdds); } - PROCESS_SWITCH(DGCandProducer, processData, "Produce UD table with data", true); + PROCESS_SWITCH(DgCandProducer, processData, "Produce UD table with data", true); // process function for reconstructed MC data void processMcData(MCCC const& collision, aod::McCollisions const& /*mccollisions*/, BCs const& bcs, @@ -465,10 +490,10 @@ struct DGCandProducer { processReco(std::string("MCreco"), collision, bcs, tracks, fwdtracks, fv0as, ft0s, fdds); } } - PROCESS_SWITCH(DGCandProducer, processMcData, "Produce UD tables with MC data", false); + PROCESS_SWITCH(DgCandProducer, processMcData, "Produce UD tables with MC data", false); }; -struct McDGCandProducer { +struct McDgCandProducer { // MC tables Produces outputMcCollisions; Produces outputMcParticles; @@ -886,21 +911,21 @@ struct McDGCandProducer { } } } - PROCESS_SWITCH(McDGCandProducer, processMCTruth, "Produce MC tables", false); + PROCESS_SWITCH(McDgCandProducer, processMCTruth, "Produce MC tables", false); void processDummy(aod::Collisions const& /*collisions*/) { // do nothing LOGF(info, "Running dummy process function!"); } - PROCESS_SWITCH(McDGCandProducer, processDummy, "Dummy function", true); + PROCESS_SWITCH(McDgCandProducer, processDummy, "Dummy function", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc, TaskName{"dgcandproducer"}), - adaptAnalysisTask(cfgc, TaskName{"mcdgcandproducer"})}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGUD/TableProducer/fwdTrackPropagation.cxx b/PWGUD/TableProducer/fwdTrackPropagation.cxx index 64099fac4ed..655e78535a1 100644 --- a/PWGUD/TableProducer/fwdTrackPropagation.cxx +++ b/PWGUD/TableProducer/fwdTrackPropagation.cxx @@ -17,21 +17,30 @@ #include "PWGUD/DataModel/UDTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "MCHTracking/TrackExtrap.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Math/SMatrix.h" -#include "TGeoGlobalMagField.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include #include #include #include diff --git a/PWGUD/TableProducer/tauEventTableProducer.cxx b/PWGUD/TableProducer/tauEventTableProducer.cxx index ec08a426f35..d91c5dffe8d 100644 --- a/PWGUD/TableProducer/tauEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauEventTableProducer.cxx @@ -16,32 +16,29 @@ /// \since 09.04.2025 // -// C++ headers -#include -#include -#include -#include -#include - -// O2 headers -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -// O2Physics headers #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/TauEventTables.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/CCDB/EventSelectionParams.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -52,7 +49,7 @@ struct TauEventTableProducer { Produces tauTwoTracks; Produces trueTauTwoTracks; - // Global varialbes + // Global variables Service pdg; SGSelector sgSelector; diff --git a/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx b/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx index baea03e1d59..87878b7b364 100644 --- a/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauThreeProngEventTableProducer.cxx @@ -23,40 +23,38 @@ // oopts="--aod-writer-json saveDerivedConfigData.json" // o2-analysis-ud-tau-three-prong-event-table-producer $copts $oopts > output.log -//// C++ headers -#include "Math/Vector4D.h" - -#include -#include -#include -#include -#include -// -//// O2 headers -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -// #include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -// -//// O2Physics headers -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/TrackSelectionTables.h" -// #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" -#include "PWGUD/Core/DGPIDSelector.h" #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/TauThreeProngEventTables.h" #include "PWGUD/DataModel/UDTables.h" #include "Common/Core/RecoDecay.h" -#include "TPDGCode.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -67,7 +65,8 @@ enum MyRecoProblem { NO_PROBLEM = 0, // no problem MANY_RECO = 1, // more than 1 reconstructed collision TOO_MANY_DAUGHTERS = 2, // more than 6 daughters from 2 taus - TWO_TRACKS = 3 // more than 1 associated track to MC particle (tau daughter) + TWO_TRACKS = 3, // more than 1 associated track to MC particle (tau daughter) + NO_TRACK = 4 // No associated track to MC particle (tau daughter) }; enum MyParticle { @@ -1019,9 +1018,10 @@ struct TauThreeProngEventTableProducer { const int sixTracks = 6; const int oneProng = 1; const int threeProng = 3; + const float epsilon = 0.000001; if (verbose) - LOGF(info, "0. UDMcCollision size %d, Collisions size %d, UDtracks %d, UDMcParticles %d", mcCollisions.size(), collisions.size(), tracks.size(), mcParticles.size()); + LOGF(info, " UDMcCollision size %d, Collisions size %d, UDtracks %d, UDMcParticles %d", mcCollisions.size(), collisions.size(), tracks.size(), mcParticles.size()); // temporary variables float tmpRapidity = -999.; @@ -1038,6 +1038,8 @@ struct TauThreeProngEventTableProducer { // start loop over generated collisions for (const auto& mccoll : mcCollisions) { + if (verbose) + LOGF(info, "-- McColl GID %d", mccoll.globalIndex()); registrySkim.get(HIST("skim/efficiencyMC"))->Fill(0., 1.); // all MC collisions // set up default values per colission @@ -1052,14 +1054,16 @@ struct TauThreeProngEventTableProducer { partFromTauInEta = true; // get particles associated to generated collision + // auto const& tmpPartsFromMcColl = mcParticles.sliceBy(partPerMcCollision, (int64_t)mccoll.globalIndex()); auto const& tmpPartsFromMcColl = mcParticles.sliceBy(partPerMcCollision, mccoll.globalIndex()); + if (verbose) - LOGF(info, "1. part from MC coll %d", tmpPartsFromMcColl.size()); + LOGF(info, "- part from MC coll %d", tmpPartsFromMcColl.size()); int countMothers = 0; const int desiredNMothers = 2; for (const auto& particle : tmpPartsFromMcColl) { if (verbose) - LOGF(info, "2. MC part pdg %d", particle.pdgCode()); + LOGF(info, "-- MC part pdg %d", particle.pdgCode()); if (std::abs(particle.pdgCode()) != kTauMinus) continue; // 15 = tau_minus // if (std::abs(particle.pdgCode()) != 15) continue; // 15 = tau_minus @@ -1073,7 +1077,7 @@ struct TauThreeProngEventTableProducer { trueTauPhi[countMothers] = RecoDecay::phi(particle.px(), particle.py()); if (verbose) - LOGF(info, "tau P(%f,%f,%f), e %f, y %f", particle.px(), particle.py(), particle.pz(), particle.e(), tmpRapidity); + LOGF(info, "-- tau P(%f,%f,%f), e %f, y %f", particle.px(), particle.py(), particle.pz(), particle.e(), tmpRapidity); registrySkim.get(HIST("skim/tauRapidityMC"))->Fill(tmpRapidity); registrySkim.get(HIST("skim/tauPhiMC"))->Fill(trueTauPhi[countMothers]); registrySkim.get(HIST("skim/tauEtaMC"))->Fill(trueTauEta[countMothers]); @@ -1081,15 +1085,16 @@ struct TauThreeProngEventTableProducer { if (std::abs(tmpRapidity) > trkEtacut) { // 0.9 tauInRapidity = false; if (verbose) - LOGF(info, "tau y %f", tmpRapidity); + LOGF(info, "--- tau y %f", tmpRapidity); } // rapidity check } // number of taus countMothers++; } // end of loop over MC paricles + // LOGF(info, "1b. countMothers %d", countMothers); registrySkim.get(HIST("skim/nTauMC"))->Fill(countMothers); if (countMothers != desiredNMothers) { // 2 if (verbose) - LOGF(info, "Truth collision has number of mother particles (taus) %d different than 2. Jump to the next MC event.", countMothers); + LOGF(info, "-- Truth collision has number of mother particles (taus) %d different than 2. Jump to the next MC event.", countMothers); continue; } @@ -1097,7 +1102,7 @@ struct TauThreeProngEventTableProducer { if (!tauInRapidity) { // tau NOT in rapidity -> continue if (verbose) - LOGF(info, "At least one mother particle (taus) out of rapidity (|y|<0.9). Jump to the next MC event."); + LOGF(info, "-- At least one mother particle (taus) out of rapidity (|y|<0.9). Jump to the next MC event."); continue; } @@ -1149,9 +1154,10 @@ struct TauThreeProngEventTableProducer { // check number of charged particles in MC event if ((nChargedDaughtersTau[0] + nChargedDaughtersTau[1] != fourTracks) && (nChargedDaughtersTau[0] + nChargedDaughtersTau[1] != sixTracks)) { if (verbose) - LOGF(info, "Different from 4/6 charged particles (%d) from both taus. Jump to the next MC event.", nChargedDaughtersTau[0] + nChargedDaughtersTau[1]); + LOGF(info, "-- Different from 4/6 charged particles (%d) from both taus. Jump to the next MC event.", nChargedDaughtersTau[0] + nChargedDaughtersTau[1]); continue; } + registrySkim.get(HIST("skim/efficiencyMC"))->Fill(3., 1.); // 1+3 (3+3) topology if (nChargedDaughtersTau[0] + nChargedDaughtersTau[1] == fourTracks) { // 4 registrySkim.get(HIST("skim/efficiencyMC"))->Fill(4., 1.); @@ -1161,9 +1167,10 @@ struct TauThreeProngEventTableProducer { if (!partFromTauInEta) { if (verbose) - LOGF(info, "At least one daughter particle from taus out of pseudo-rapidity (|eta|<0.9). Jump to the next MC event."); + LOGF(info, "-- At least one daughter particle from taus out of pseudo-rapidity (|eta|<0.9). Jump to the next MC event."); continue; } + registrySkim.get(HIST("skim/efficiencyMC"))->Fill(6., 1.); // particles from tau in |eta|<0.9 if (nChargedDaughtersTau[0] + nChargedDaughtersTau[1] == fourTracks) { // 4 registrySkim.get(HIST("skim/efficiencyMC"))->Fill(7., 1.); @@ -1179,12 +1186,12 @@ struct TauThreeProngEventTableProducer { zerothTau = 0; // prepare local variables for output table - int32_t runNumber = -999; + int32_t runNumber = -999; // when no reconstructed collisions is associated to MCcoll it should remain = -999 int bc = -999; // int nTrks[3] = {-999, -999, -999}; // totalTracks, numContrib, globalNonPVtracks int totalTracks = -999; int8_t nPVcontrib = -99; - int rct = -999; + int rct = -99; // float vtxPos[3] = {-999., -999., -999.}; float zVertex = -999; @@ -1232,10 +1239,10 @@ struct TauThreeProngEventTableProducer { // float tofEP[2] = {-999, -999}; float chi2TOF[6] = {-999., -999., -999., -999., -999., -999.}; - bool trueHasRecoColl = false; - float trueDaugX[6] = {-999., -999., -999., -999., -999., -999.}; - float trueDaugY[6] = {-999., -999., -999., -999., -999., -999.}; - float trueDaugZ[6] = {-999., -999., -999., -999., -999., -999.}; + // bool trueHasRecoColl = false; + float trueDaugX[6] = {-998., -998., -998., -998., -998., -998.}; + float trueDaugY[6] = {-998., -998., -998., -998., -998., -998.}; + float trueDaugZ[6] = {-998., -998., -998., -998., -998., -998.}; int trueDaugPdgCode[6] = {-999, -999, -999, -999, -999, -999}; // bool problem = false; MyRecoProblem problem = NO_PROBLEM; @@ -1256,180 +1263,233 @@ struct TauThreeProngEventTableProducer { else if (nPi == sixTracks) // 6 trueChannel = 4; + // LOGF(info, "MC Coll global index %d", mccoll.globalIndex()); + // LOGF(info, "2. UDMcCollision size %d, Collisions size %d, UDtracks %d, UDMcParticles %d", mcCollisions.size(), collisions.size(), tracks.size(), mcParticles.size()); + // for (const auto& coll : collisions) { + // LOGF(info, "coll global index %d", coll.globalIndex()); + // } + // find reconstructed collisions associated to the generated collision auto const& collFromMcColls = collisions.sliceBy(colPerMcCollision, mccoll.globalIndex()); if (verbose) - LOGF(info, "coll from MC Coll %d", collFromMcColls.size()); + LOGF(info, "-- coll from MC Coll %d", collFromMcColls.size()); // check the generated collision was reconstructed if (collFromMcColls.size() > 0) { // get the truth and reco-level info if (verbose) - LOGF(info, "MC Collision has reconstructed collision!"); - trueHasRecoColl = true; + LOGF(info, "--- MC Collision has reconstructed collision!"); + // trueHasRecoColl = true; // check there is exactly one reco-level collision associated to generated collision if (collFromMcColls.size() > 1) { if (verbose) - LOGF(info, "Truth collision has more than 1 reco collision. Skipping this event."); - // histos.get(HIST("Truth/hTroubles"))->Fill(1); - // problem = true; + LOGF(info, "---- Truth collision has more than 1 reco collision. Event remains."); + // LOGF(info, "Truth collision has more than 1 reco collision. Skipping this event."); + // histos.get(HIST("Truth/hTroubles"))->Fill(1); + // problem = true; problem = MANY_RECO; registrySkim.get(HIST("skim/problemMC"))->Fill(MANY_RECO); - continue; + // continue; + } else { + if (verbose) + LOGF(info, "---- Truth collision has 1 reco collision. Record event."); } - // grap reco-level collision - auto const& collFromMcColl = collFromMcColls.iteratorAt(0); - // grab tracks from the reco-level collision to get info to match measured data tables (processDataSG function) - auto const& trksFromColl = tracks.sliceBy(trackPerCollision, collFromMcColl.globalIndex()); - // int countTracksPerCollision = 0; - // int countGoodNonPVtracks = 0; - // for (auto const& trkFromColl : trksFromColl) { - // // countTracksPerCollision++; - // if (!trkFromColl.isPVContributor()) { - // countGoodNonPVtracks++; - // continue; - // } - // } - - // fill info for reconstructed collision - runNumber = collFromMcColl.runNumber(); - bc = collFromMcColl.globalBC(); - totalTracks = trksFromColl.size(); - // nTrks[0] = countTracksPerCollision; - nPVcontrib = collFromMcColl.numContrib(); - // nTrks[1] = collFromMcColl.numContrib(); - // nTrks[2] = countGoodNonPVtracks; - rct = isGoodRCTflag(collFromMcColl); - zVertex = collFromMcColl.posZ(); - // vtxPos[0] = collFromMcColl.posX(); - // vtxPos[1] = collFromMcColl.posY(); - // vtxPos[2] = collFromMcColl.posZ(); - - recoMode = collFromMcColl.flags(); - occupancy = collFromMcColl.occupancyInTime(); - hadronicRate = collFromMcColl.hadronicRate(); - bcSels[0] = collFromMcColl.trs(); - bcSels[1] = collFromMcColl.trofs(); - bcSels[2] = collFromMcColl.hmpr(); - bcSels[3] = collFromMcColl.tfb(); - bcSels[4] = collFromMcColl.itsROFb(); - bcSels[5] = collFromMcColl.sbp(); - bcSels[6] = collFromMcColl.zVtxFT0vPV(); - bcSels[7] = collFromMcColl.vtxITSTPC(); - // energyZNA = collFromMcColl.energyCommonZNA(); - // energyZNC = collFromMcColl.energyCommonZNC(); - // if (energyZNA < 0) - // energyZNA = -1.; - // if (energyZNC < 0) - // energyZNC = -1.; - - amplitudesFIT[0] = collFromMcColl.totalFT0AmplitudeA(); - amplitudesFIT[1] = collFromMcColl.totalFT0AmplitudeC(); - amplitudesFIT[2] = collFromMcColl.totalFV0AmplitudeA(); - // timesFIT[0] = collFromMcColl.timeFT0A(); - // timesFIT[1] = collFromMcColl.timeFT0C(); - // timesFIT[2] = collFromMcColl.timeFV0A(); - // get particles associated to generated collision - auto const& partsFromMcColl = mcParticles.sliceBy(partPerMcCollision, mccoll.globalIndex()); - if (verbose) - LOGF(info, "part from MC coll %d", partsFromMcColl.size()); - // int countMothers = 0; - int countDaughters = 0; - countPi0 = 0; - for (const auto& particle : partsFromMcColl) { - if (verbose) - LOGF(info, "Reco coll; part pdg %d", particle.pdgCode()); - // select only tauons with checking if particle has no mother - // in UPC MC taus have mothers - // if (particle.has_mothers()) - if (std::abs(particle.pdgCode()) != kTauMinus) - continue; // 15 = tau_minus + // grab reco-level collision + for (const auto& collFromMcColl : collFromMcColls) { + if (verbose) { + LOGF(info, "---- ###### Collision %d #########", collFromMcColl.index()); + LOGF(info, "---- Coll GID %d, Vertex (%f,%f,%f)", collFromMcColl.globalIndex(), collFromMcColl.posX(), collFromMcColl.posY(), collFromMcColl.posZ()); + } + // auto const& collFromMcColl = collFromMcColls.iteratorAt(0); + // grab tracks from the reco-level collision to get info to match measured data tables (processDataSG function) + auto const& trksFromColl = tracks.sliceBy(trackPerCollision, collFromMcColl.globalIndex()); + // int countTracksPerCollision = 0; + // int countGoodNonPVtracks = 0; + // for (auto const& trkFromColl : trksFromColl) { + // // countTracksPerCollision++; + // if (!trkFromColl.isPVContributor()) { + // countGoodNonPVtracks++; + // continue; + // } + // } - // get daughters of the tau - const auto& daughters = particle.daughters_as(); - // int countDaughters = 0; - for (const auto& daughter : daughters) { + // fill info for reconstructed collision + runNumber = collFromMcColl.runNumber(); + bc = collFromMcColl.globalBC(); + totalTracks = trksFromColl.size(); + // nTrks[0] = countTracksPerCollision; + nPVcontrib = collFromMcColl.numContrib(); + // nTrks[1] = collFromMcColl.numContrib(); + // nTrks[2] = countGoodNonPVtracks; + rct = isGoodRCTflag(collFromMcColl); + zVertex = collFromMcColl.posZ(); + // vtxPos[0] = collFromMcColl.posX(); + // vtxPos[1] = collFromMcColl.posY(); + // vtxPos[2] = collFromMcColl.posZ(); + + recoMode = collFromMcColl.flags(); + occupancy = collFromMcColl.occupancyInTime(); + hadronicRate = collFromMcColl.hadronicRate(); + bcSels[0] = collFromMcColl.trs(); + bcSels[1] = collFromMcColl.trofs(); + bcSels[2] = collFromMcColl.hmpr(); + bcSels[3] = collFromMcColl.tfb(); + bcSels[4] = collFromMcColl.itsROFb(); + bcSels[5] = collFromMcColl.sbp(); + bcSels[6] = collFromMcColl.zVtxFT0vPV(); + bcSels[7] = collFromMcColl.vtxITSTPC(); + // energyZNA = collFromMcColl.energyCommonZNA(); + // energyZNC = collFromMcColl.energyCommonZNC(); + // if (energyZNA < 0) + // energyZNA = -1.; + // if (energyZNC < 0) + // energyZNC = -1.; + + amplitudesFIT[0] = collFromMcColl.totalFT0AmplitudeA(); + amplitudesFIT[1] = collFromMcColl.totalFT0AmplitudeC(); + amplitudesFIT[2] = collFromMcColl.totalFV0AmplitudeA(); + // timesFIT[0] = collFromMcColl.timeFT0A(); + // timesFIT[1] = collFromMcColl.timeFT0C(); + // timesFIT[2] = collFromMcColl.timeFV0A(); + + // get particles associated to generated collision + auto const& partsFromMcColl = mcParticles.sliceBy(partPerMcCollision, mccoll.globalIndex()); + if (verbose) + LOGF(info, "---- part from MC coll %d", partsFromMcColl.size()); + // int countMothers = 0; + int countDaughters = 0; + countPi0 = 0; + for (const auto& particle : partsFromMcColl) { if (verbose) - LOGF(info, "With Coll; daug pdg %d", daughter.pdgCode()); - // check if it is the charged particle (= no pi0 or neutrino) - if (enumMyParticle(daughter.pdgCode()) == MyOtherParticle) // -1 - continue; - countDaughters++; - if (daughter.pdgCode() == kPi0) - countPi0++; - - // check whether 1+3 or 3+3 topology is present - if (countDaughters > sixTracks) { // 6 + LOGF(info, "----- Reco coll; part pdg %d, GID %d", particle.pdgCode(), particle.globalIndex()); + // select only tauons with checking if particle has no mother + // in UPC MC taus have mothers + // if (particle.has_mothers()) + if (std::abs(particle.pdgCode()) != kTauMinus) + continue; // 15 = tau_minus + + // get daughters of the tau + const auto& daughters = particle.daughters_as(); + // int countDaughters = 0; + for (const auto& daughter : daughters) { if (verbose) - LOGF(info, "Truth collision has more than 6 charged daughters from 2 taus. Breaking the daughter loop."); - // histos.get(HIST("Truth/hTroubles"))->Fill(3); - // problem = true; - problem = TOO_MANY_DAUGHTERS; - registrySkim.get(HIST("skim/problemMC"))->Fill(TOO_MANY_DAUGHTERS); - - break; - } - - // fill info for each daughter - trueDaugX[countDaughters - 1] = daughter.px(); - trueDaugY[countDaughters - 1] = daughter.py(); - trueDaugZ[countDaughters - 1] = daughter.pz(); - trueDaugPdgCode[countDaughters - 1] = daughter.pdgCode(); - - // get tracks associated to MC daughter (how well the daughter was reconstructed) - auto const& tracksFromDaughter = tracks.sliceBy(trackPerMcParticle, daughter.globalIndex()); - // check there is exactly 1 track per 1 particle - if (tracksFromDaughter.size() > 1) { + LOGF(info, "----- With Coll; daug pdg %d, GID %d", daughter.pdgCode(), daughter.globalIndex()); + + if (daughter.pdgCode() == kPi0) + countPi0++; + + // check if it is the charged particle (= no pi0 or neutrino) + if (enumMyParticle(daughter.pdgCode()) == MyOtherParticle) // -1 + continue; + countDaughters++; + + // check whether 1+3 or 3+3 topology is present + if (countDaughters > sixTracks) { // 6 + if (verbose) + LOGF(info, "------ Truth collision has more than 6 charged daughters from 2 taus. Breaking the daughter loop."); + // histos.get(HIST("Truth/hTroubles"))->Fill(3); + // problem = true; + problem = TOO_MANY_DAUGHTERS; + registrySkim.get(HIST("skim/problemMC"))->Fill(TOO_MANY_DAUGHTERS); + + break; + } + + // fill info for each daughter + trueDaugX[countDaughters - 1] = daughter.px(); + trueDaugY[countDaughters - 1] = daughter.py(); + trueDaugZ[countDaughters - 1] = daughter.pz(); + trueDaugPdgCode[countDaughters - 1] = daughter.pdgCode(); if (verbose) - LOGF(info, "Daughter has more than 1 associated track. Skipping this daughter."); - // histos.get(HIST("Truth/hTroubles"))->Fill(4); - // problem = true; - problem = TWO_TRACKS; - registrySkim.get(HIST("skim/problemMC"))->Fill(TWO_TRACKS); - continue; - } - // grab the track and fill info for reconstructed track (should be done 4 or 6 times) - const auto& trk = tracksFromDaughter.iteratorAt(0); - if (verbose) - LOGF(info, "p(%f,%f,%f)", trk.px(), trk.py(), trk.pz()); - px[countDaughters - 1] = trk.px(); - py[countDaughters - 1] = trk.py(); - pz[countDaughters - 1] = trk.pz(); - sign[countDaughters - 1] = trk.sign(); - dcaXY[countDaughters - 1] = trk.dcaXY(); - dcaZ[countDaughters - 1] = trk.dcaZ(); - // trkTimeRes[countMothers - 1] = trk.trackTimeRes(); - // if (countMothers == 1) { - // itsClusterSizesTrk1 = trk.itsClusterSizes(); - // } else { - // itsClusterSizesTrk2 = trk.itsClusterSizes(); - // } - - nclTPCcrossedRows[countDaughters - 1] = trk.tpcNClsCrossedRows(); - nclTPCfind[countDaughters - 1] = trk.tpcNClsFindable(); - nclTPCchi2[countDaughters - 1] = trk.tpcChi2NCl(); - trkITSchi2[countDaughters - 1] = trk.itsChi2NCl(); - trkITScl[countDaughters - 1] = numberOfItsClustersCheck(trk); - - tpcSignal[countDaughters - 1] = trk.tpcSignal(); - tpcEl[countDaughters - 1] = trk.tpcNSigmaEl(); - tpcMu[countDaughters - 1] = trk.tpcNSigmaMu(); - tpcPi[countDaughters - 1] = trk.tpcNSigmaPi(); - tpcKa[countDaughters - 1] = trk.tpcNSigmaKa(); - tpcPr[countDaughters - 1] = trk.tpcNSigmaPr(); - // tpcIP[countDaughters - 1] = trk.tpcInnerParam(); - - tofSignal[countDaughters - 1] = trk.beta(); - tofEl[countDaughters - 1] = trk.tofNSigmaEl(); - tofMu[countDaughters - 1] = trk.tofNSigmaMu(); - tofPi[countDaughters - 1] = trk.tofNSigmaPi(); - tofKa[countDaughters - 1] = trk.tofNSigmaKa(); - tofPr[countDaughters - 1] = trk.tofNSigmaPr(); - // tofEP[countMothers - 1] = trk.tofExpMom(); - if (trk.hasTOF()) - chi2TOF[countDaughters - 1] = trk.tofChi2(); - - } // daughters - } // particles + LOGF(info, "----- tau daug pxpypz (%f, %f, %f) pdg %d", daughter.px(), daughter.py(), daughter.pz(), daughter.pdgCode()); + // get tracks associated to MC daughter (how well the daughter was reconstructed) + auto const& tracksFromDaughter = tracks.sliceBy(trackPerMcParticle, daughter.globalIndex()); + // check there is exactly 1 track per 1 particle + if (tracksFromDaughter.size() > 1) { + if (verbose) + LOGF(info, "------ Daughter has more than 1 associated track. Ntracks = %d.", tracksFromDaughter.size()); + // LOGF(info, "Daughter has more than 1 associated track. Ntracks = %d. Skipping this daughter.", tracksFromDaughter.size()); + + // make sure that track momentum is the same (difference is smaller than epsilon=0.000001) for multiple reconstructed tracks, if not reject + // tracks are accocated to 2 different collisions (!?) + float tmptrk[3]; + bool firstObject = true; + int counter = 0; + for (const auto& trk : tracksFromDaughter) { + if (verbose) + LOGF(info, "------- track GID %d, p(%f,%f,%f)", trk.globalIndex(), trk.px(), trk.py(), trk.pz()); + if (firstObject) { + tmptrk[0] = trk.px(); + tmptrk[1] = trk.py(); + tmptrk[2] = trk.pz(); + firstObject = false; + counter++; + } else { + if ((std::abs(tmptrk[0] - trk.px()) > epsilon) || (std::abs(tmptrk[1] - trk.py()) > epsilon) || (std::abs(tmptrk[2] - trk.pz()) > epsilon)) + counter++; + } + } // end of loop over tracks from 1 McParticle + if (verbose) + LOGF(info, "------ Corrected number of associated tracks to MC particle %d", counter); + + if (counter > 1) { + if (verbose) + LOGF(info, "------ Daughter has more than 1 associated track. Ntracks = %d. Skipping this daughter.", counter); + problem = TWO_TRACKS; + registrySkim.get(HIST("skim/problemMC"))->Fill(TWO_TRACKS); + continue; + } + } else if (tracksFromDaughter.size() < 1) { + // what if no track is associated to mc particle??? + if (verbose) + LOGF(info, "----- Daughter has no associated track. Ntracks = %d. Skipping this daughter.", tracksFromDaughter.size()); + problem = NO_TRACK; + registrySkim.get(HIST("skim/problemMC"))->Fill(NO_TRACK); + continue; + } + + // grab the track and fill info for reconstructed track (should be done 4 or 6 times) + const auto& trk = tracksFromDaughter.iteratorAt(0); + + px[countDaughters - 1] = trk.px(); + py[countDaughters - 1] = trk.py(); + pz[countDaughters - 1] = trk.pz(); + sign[countDaughters - 1] = trk.sign(); + dcaXY[countDaughters - 1] = trk.dcaXY(); + dcaZ[countDaughters - 1] = trk.dcaZ(); + // trkTimeRes[countMothers - 1] = trk.trackTimeRes(); + // if (countMothers == 1) { + // itsClusterSizesTrk1 = trk.itsClusterSizes(); + // } else { + // itsClusterSizesTrk2 = trk.itsClusterSizes(); + // } + + nclTPCcrossedRows[countDaughters - 1] = trk.tpcNClsCrossedRows(); + nclTPCfind[countDaughters - 1] = trk.tpcNClsFindable(); + nclTPCchi2[countDaughters - 1] = trk.tpcChi2NCl(); + trkITSchi2[countDaughters - 1] = trk.itsChi2NCl(); + trkITScl[countDaughters - 1] = numberOfItsClustersCheck(trk); + + tpcSignal[countDaughters - 1] = trk.tpcSignal(); + tpcEl[countDaughters - 1] = trk.tpcNSigmaEl(); + tpcMu[countDaughters - 1] = trk.tpcNSigmaMu(); + tpcPi[countDaughters - 1] = trk.tpcNSigmaPi(); + tpcKa[countDaughters - 1] = trk.tpcNSigmaKa(); + tpcPr[countDaughters - 1] = trk.tpcNSigmaPr(); + // tpcIP[countDaughters - 1] = trk.tpcInnerParam(); + + tofSignal[countDaughters - 1] = trk.beta(); + tofEl[countDaughters - 1] = trk.tofNSigmaEl(); + tofMu[countDaughters - 1] = trk.tofNSigmaMu(); + tofPi[countDaughters - 1] = trk.tofNSigmaPi(); + tofKa[countDaughters - 1] = trk.tofNSigmaKa(); + tofPr[countDaughters - 1] = trk.tofNSigmaPr(); + // tofEP[countMothers - 1] = trk.tofExpMom(); + if (trk.hasTOF()) + chi2TOF[countDaughters - 1] = trk.tofChi2(); + + } // end of loop over daughters of taus + } // end of loop over MC particles + } // end of loop over collisions associated to MC collision } else { // get only the truth information. The reco-level info is left on default if (verbose) LOGF(info, "MC Collision has NO reconstructed collision!"); @@ -1470,12 +1530,14 @@ struct TauThreeProngEventTableProducer { for (const auto& daughter : daughters) { if (verbose) LOGF(info, "NO Coll; daug id %d, pdg %d", daughter.globalIndex(), daughter.pdgCode()); + + if (daughter.pdgCode() == kPi0) + countPi0++; + // select only the charged particle (= no pi0 or neutrino) if (enumMyParticle(daughter.pdgCode()) == -1) continue; countDaughters++; - if (daughter.pdgCode() == kPi0) - countPi0++; // check whether 1+3 or 3+3 topology is present if (countDaughters > sixTracks) { // 6 @@ -1526,7 +1588,7 @@ struct TauThreeProngEventTableProducer { chi2TOF, // trueChannel, - trueHasRecoColl, + // trueHasRecoColl, mccoll.posZ(), trueTauX, trueTauY, trueTauZ, trueDaugX, trueDaugY, trueDaugZ, diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index 55e5396df12..36c5c44112f 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -16,35 +16,33 @@ /// \since 20.06.2025 // -// C++ headers -#include -#include -#include -#include -#include - -// O2 headers -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -// O2Physics headers #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/TwoTracksEventTables.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/CCDB/EventSelectionParams.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include -// ROOT -#include "Math/Vector4D.h" +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -116,7 +114,7 @@ struct TwoTracksEventTableProducer { Configurable preselBothAreTOFtracks{"preselBothAreTOFtracks", false, {"Both tracks are required to hit TOF."}}; Configurable preselUseMinMomentumOnBothTracks{"preselUseMinMomentumOnBothTracks", false, {"Both tracks are required to fill requirement on minimum momentum."}}; Configurable preselMinTrackMomentum{"preselMinTrackMomentum", 0.1, {"Requirement on minimum momentum of the track."}}; - Configurable preselSystemPtCut{"preselSystemPtCut", 0.0, {"By default, cut on maximum system pT."}}; + Configurable preselSystemPtCut{"preselSystemPtCut", 2.0, {"By default, cut on maximum system pT."}}; Configurable preselUseOppositeSystemPtCut{"preselUseOppositeSystemPtCut", false, {"Negates the system pT cut (cut on minimum system pT)."}}; Configurable preselMinInvariantMass{"preselMinInvariantMass", 2.0, {"Requirement on minimum system invariant mass."}}; Configurable preselMaxInvariantMass{"preselMaxInvariantMass", 5.0, {"Requirement on maximum system invariant mass."}}; @@ -137,8 +135,10 @@ struct TwoTracksEventTableProducer { mySetITShitsRule(cutGlobalTrack.cutITShitsRule); - histos.add("Reco/hSelections", "Effect of selections;;Number of events (-)", HistType::kTH1D, {{50, 0.5, 50.5}}); - histos.add("Truth/hTroubles", "Counter of unwanted issues;;Number of troubles (-)", HistType::kTH1D, {{15, 0.5, 15.5}}); + histos.add("Reco/hSelections", "Effect of selections;;Number of events (-)", HistType::kTH1D, {{50, 0.5, 50.5}}); + histos.add("Reco/hNanalyzedPerRun", "N analyzed events per run;Run number (-);Number of analyzed events (-)", HistType::kTH1D, {{1, 0., 1.}}); + histos.add("Reco/hNselectedPerRun", "N selected events per run;Run number (-);Number of selected events (-)", HistType::kTH1D, {{1, 0., 1.}}); + histos.add("Truth/hTroubles", "Counter of unwanted issues;;Number of troubles (-)", HistType::kTH1D, {{15, 0.5, 15.5}}); } // end init @@ -358,6 +358,9 @@ struct TwoTracksEventTableProducer { void processDataSG(FullSGUDCollision const& collision, FullUDTracks const& tracks) { + int run = collision.runNumber(); + const char* srun = Form("%d", run); + histos.get(HIST("Reco/hNanalyzedPerRun"))->Fill(srun, 1); nSelection = 0; histos.get(HIST("Reco/hSelections"))->Fill(nSelection); @@ -490,6 +493,8 @@ struct TwoTracksEventTableProducer { float tofEP[2] = {trk1.tofExpMom(), trk2.tofExpMom()}; float infoZDC[4] = {collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC()}; + histos.get(HIST("Reco/hNselectedPerRun"))->Fill(srun, 1); + twoTracks(collision.runNumber(), collision.globalBC(), countTracksPerCollision, collision.numContrib(), countGoodNonPVtracks, collision.posX(), collision.posY(), collision.posZ(), collision.flags(), collision.occupancyInTime(), collision.hadronicRate(), collision.trs(), collision.trofs(), collision.hmpr(), collision.tfb(), collision.itsROFb(), collision.sbp(), collision.zVtxFT0vPV(), collision.vtxITSTPC(), @@ -500,7 +505,7 @@ struct TwoTracksEventTableProducer { tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); } - PROCESS_SWITCH(TwoTracksEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); + PROCESS_SWITCH(TwoTracksEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", true); PresliceUnsorted partPerMcCollision = aod::udmcparticle::udMcCollisionId; PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; @@ -619,6 +624,7 @@ struct TwoTracksEventTableProducer { // get particles associated to generated collision auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); int countMothers = 0; + int totalChargedDaughters = 0; for (const auto& particle : partsFromMcColl) { // select only mothers with checking if particle has no mother if (particle.has_mothers()) @@ -637,74 +643,85 @@ struct TwoTracksEventTableProducer { trueMotherY[countMothers - 1] = particle.py(); trueMotherZ[countMothers - 1] = particle.pz(); - // get daughters of the tau + // get daughters of the mother const auto& daughters = particle.daughters_as(); - int countDaughters = 0; for (const auto& daughter : daughters) { // check if it is the charged particle (= no pi0 or neutrino) if (enumMyParticle(daughter.pdgCode()) == -1) continue; - countDaughters++; - // check there is only 1 charged daughter related to 1 tau - if (countDaughters > 1) { + // check we do not have more than 2 charged daughters in total + if (totalChargedDaughters >= 2) { if (verboseInfo) - printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + printLargeMessage("Truth collision has more than 2 total charged daughters. Breaking the daughter loop."); histos.get(HIST("Truth/hTroubles"))->Fill(3); problem = true; break; } // fill info for each daughter - trueDaugX[countMothers - 1] = daughter.px(); - trueDaugY[countMothers - 1] = daughter.py(); - trueDaugZ[countMothers - 1] = daughter.pz(); - trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + trueDaugX[totalChargedDaughters] = daughter.px(); + trueDaugY[totalChargedDaughters] = daughter.py(); + trueDaugZ[totalChargedDaughters] = daughter.pz(); + trueDaugPdgCode[totalChargedDaughters] = daughter.pdgCode(); // get tracks associated to MC daughter (how well the daughter was reconstructed) auto const& tracksFromDaughter = trks.sliceBy(trackPerMcParticle, daughter.globalIndex()); // check there is exactly 1 track per 1 particle + if (tracksFromDaughter.size() == 0) { + if (verboseInfo) + printLargeMessage("Daughter has no associated track. Skipping this daughter."); + histos.get(HIST("Truth/hTroubles"))->Fill(5); + problem = true; + totalChargedDaughters++; + continue; + } if (tracksFromDaughter.size() > 1) { if (verboseInfo) printLargeMessage("Daughter has more than 1 associated track. Skipping this daughter."); histos.get(HIST("Truth/hTroubles"))->Fill(4); problem = true; + totalChargedDaughters++; continue; } - // grab the track and fill info for reconstructed track (should be done twice) + // grab the track and fill info for reconstructed track const auto& trk = tracksFromDaughter.iteratorAt(0); - px[countMothers - 1] = trk.px(); - py[countMothers - 1] = trk.py(); - pz[countMothers - 1] = trk.pz(); - sign[countMothers - 1] = trk.sign(); - dcaxy[countMothers - 1] = trk.dcaXY(); - dcaz[countMothers - 1] = trk.dcaZ(); - trkTimeRes[countMothers - 1] = trk.trackTimeRes(); - if (countMothers == 1) { + px[totalChargedDaughters] = trk.px(); + py[totalChargedDaughters] = trk.py(); + pz[totalChargedDaughters] = trk.pz(); + sign[totalChargedDaughters] = trk.sign(); + dcaxy[totalChargedDaughters] = trk.dcaXY(); + dcaz[totalChargedDaughters] = trk.dcaZ(); + trkTimeRes[totalChargedDaughters] = trk.trackTimeRes(); + if (totalChargedDaughters == 0) { itsClusterSizesTrk1 = trk.itsClusterSizes(); } else { itsClusterSizesTrk2 = trk.itsClusterSizes(); } - tpcSignal[countMothers - 1] = trk.tpcSignal(); - tpcEl[countMothers - 1] = trk.tpcNSigmaEl(); - tpcMu[countMothers - 1] = trk.tpcNSigmaMu(); - tpcPi[countMothers - 1] = trk.tpcNSigmaPi(); - tpcKa[countMothers - 1] = trk.tpcNSigmaKa(); - tpcPr[countMothers - 1] = trk.tpcNSigmaPr(); - tpcIP[countMothers - 1] = trk.tpcInnerParam(); - tofSignal[countMothers - 1] = trk.tofSignal(); - tofEl[countMothers - 1] = trk.tofNSigmaEl(); - tofMu[countMothers - 1] = trk.tofNSigmaMu(); - tofPi[countMothers - 1] = trk.tofNSigmaPi(); - tofKa[countMothers - 1] = trk.tofNSigmaKa(); - tofPr[countMothers - 1] = trk.tofNSigmaPr(); - tofEP[countMothers - 1] = trk.tofExpMom(); + tpcSignal[totalChargedDaughters] = trk.tpcSignal(); + tpcEl[totalChargedDaughters] = trk.tpcNSigmaEl(); + tpcMu[totalChargedDaughters] = trk.tpcNSigmaMu(); + tpcPi[totalChargedDaughters] = trk.tpcNSigmaPi(); + tpcKa[totalChargedDaughters] = trk.tpcNSigmaKa(); + tpcPr[totalChargedDaughters] = trk.tpcNSigmaPr(); + tpcIP[totalChargedDaughters] = trk.tpcInnerParam(); + tofSignal[totalChargedDaughters] = trk.tofSignal(); + tofEl[totalChargedDaughters] = trk.tofNSigmaEl(); + tofMu[totalChargedDaughters] = trk.tofNSigmaMu(); + tofPi[totalChargedDaughters] = trk.tofNSigmaPi(); + tofKa[totalChargedDaughters] = trk.tofNSigmaKa(); + tofPr[totalChargedDaughters] = trk.tofNSigmaPr(); + tofEP[totalChargedDaughters] = trk.tofExpMom(); + totalChargedDaughters++; } // daughters + if (problem) + break; } // particles } else { // get only the truth information. The reco-level info is left on default // get particles associated to generated collision auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); int countMothers = 0; + int totalChargedDaughters = 0; for (const auto& particle : partsFromMcColl) { - // select only tauons with checking if particle has no mother + // select only motherless particles if (particle.has_mothers()) continue; countMothers++; @@ -716,39 +733,42 @@ struct TwoTracksEventTableProducer { problem = true; break; } - // fill info for each tau + // fill info for each mother trueMotherX[countMothers - 1] = particle.px(); trueMotherY[countMothers - 1] = particle.py(); trueMotherZ[countMothers - 1] = particle.pz(); - // get daughters of the tau + // get daughters of the mother const auto& daughters = particle.daughters_as(); - int countDaughters = 0; for (const auto& daughter : daughters) { // select only the charged particle (= no pi0 or neutrino) if (enumMyParticle(daughter.pdgCode()) == -1) continue; - countDaughters++; - // check there is only 1 charged daughter related to 1 tau - if (countDaughters > 1) { + // check we do not have more than 2 charged daughters in total + if (totalChargedDaughters >= 2) { if (verboseInfo) - printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + printLargeMessage("Truth collision has more than 2 total charged daughters. Breaking the daughter loop."); histos.get(HIST("Truth/hTroubles"))->Fill(13); problem = true; break; } // fill info for each daughter - trueDaugX[countMothers - 1] = daughter.px(); - trueDaugY[countMothers - 1] = daughter.py(); - trueDaugZ[countMothers - 1] = daughter.pz(); - trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + trueDaugX[totalChargedDaughters] = daughter.px(); + trueDaugY[totalChargedDaughters] = daughter.py(); + trueDaugZ[totalChargedDaughters] = daughter.pz(); + trueDaugPdgCode[totalChargedDaughters] = daughter.pdgCode(); + totalChargedDaughters++; } // daughters + if (problem) + break; } // particles } // collisions - // decide the channel and set the variable. Only two cahnnels suported now. + // decide the channel and set the variable if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && (enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON)) trueChannel = CH_EE; + if ((enumMyParticle(trueDaugPdgCode[0]) == P_MUON) && (enumMyParticle(trueDaugPdgCode[1]) == P_MUON)) + trueChannel = CH_MUMU; if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[1]) == P_PION) || (enumMyParticle(trueDaugPdgCode[1]) == P_MUON))) trueChannel = CH_EMUPI; if ((enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[0]) == P_PION) || (enumMyParticle(trueDaugPdgCode[0]) == P_MUON))) diff --git a/PWGUD/TableProducer/udMcCollisions2udCollisions.cxx b/PWGUD/TableProducer/udMcCollisions2udCollisions.cxx index cea35fb70ea..f97fe33a3f3 100644 --- a/PWGUD/TableProducer/udMcCollisions2udCollisions.cxx +++ b/PWGUD/TableProducer/udMcCollisions2udCollisions.cxx @@ -16,13 +16,17 @@ /// \brief A task to create a reverse index from UDMcCollisions to UDCollisions /// -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "PWGUD/DataModel/UDTables.h" #include "PWGUD/DataModel/UDIndex.h" +#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/udMcParticles2udTracks.cxx b/PWGUD/TableProducer/udMcParticles2udTracks.cxx index 4a876a72fb3..e4f18bc20d9 100644 --- a/PWGUD/TableProducer/udMcParticles2udTracks.cxx +++ b/PWGUD/TableProducer/udMcParticles2udTracks.cxx @@ -16,13 +16,17 @@ /// \brief A task to create a reverse index from UDMcParticles to UDTracks /// -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "PWGUD/DataModel/UDTables.h" #include "PWGUD/DataModel/UDIndex.h" +#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx b/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx new file mode 100644 index 00000000000..744b4e8523a --- /dev/null +++ b/PWGUD/TableProducer/upcCandProducerGlobalMuon.cxx @@ -0,0 +1,909 @@ +// 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 upcCandProducerGlobalMuon.cxx +/// \brief UPC candidate producer for forward muons with MFT support - UNDER DEVELOPMENT +/// \author Roman Lavicka, roman.lavicka@cern.ch +/// \since 11.02.2026 + +#include "PWGUD/Core/UPCCutparHolder.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/Core/fwdtrackUtilities.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct UpcCandProducerGlobalMuon { + bool fDoMC{false}; + + std::map fNewPartIDs; + + Produces udMCCollisions; + Produces udMCParticles; + Produces udFwdTrackLabels; + + Produces udFwdTracks; + Produces udFwdTracksExtra; + Produces udFwdIndices; + Produces udFwdTrkClusters; // Added for MFT clusters + Produces eventCandidates; + Produces eventCandidatesSelsFwd; + Produces udZdcsReduced; + + Configurable fSignalGenID{"fSignalGenID", 1, "Signal generator ID"}; + + UPCCutparHolder fUpcCuts = UPCCutparHolder(); + MutableConfigurable fUpcCutsConf{"fUpcCutsConf", {}, "UPC event cuts"}; + Configurable fBcWindowFITAmps{"fBcWindowFITAmps", 20, "BC range for T0A/V0A amplitudes array [-range, +(range-1)]"}; + Configurable fBcWindowMCH{"fBcWindowMCH", 20, "Time window for MCH-MID to MCH-only matching for Muon candidates"}; + Configurable fMaxFV0Amp{"fMaxFV0Amp", 100.f, "Max FV0 amplitude in the same BC"}; + + // NEW: MFT/Global track support configurables + Configurable fEnableMFT{"fEnableMFT", true, "Enable MFT/global track processing"}; + Configurable fSaveMFTClusters{"fSaveMFTClusters", true, "Save MFT cluster information"}; + + // Ambiguous track propagation configurables + Configurable fApplyZShiftFromCCDB{"fApplyZShiftFromCCDB", false, "Apply z-shift from CCDB for global muon propagation"}; + Configurable fZShiftPath{"fZShiftPath", "Users/m/mcoquet/ZShift", "CCDB path for z-shift"}; + Configurable fManualZShift{"fManualZShift", 0.0f, "Manual z-shift for global muon propagation to PV"}; + Configurable fMaxDCAxy{"fMaxDCAxy", 999.f, "Maximum DCAxy for global muon track selection (cm)"}; + Configurable fBcWindowCollision{"fBcWindowCollision", 4, "BC window for collision search for DCA-based vertex assignment"}; + Configurable fMaxChi2MatchMCHMFT{"fMaxChi2MatchMCHMFT", 4.f, "Maximum chi2 for MCH-MFT matching quality filter"}; + Configurable fBcWindowMCHMFT{"fBcWindowMCHMFT", 20, "BC window for searching MCH-MFT tracks around MCH-MID-MFT anchors"}; + + using ForwardTracks = o2::soa::Join; + + HistogramRegistry histRegistry{"HistRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + int fRun{0}; + Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; + o2::globaltracking::MatchGlobalFwd fMatching; + + // Ambiguous track propagation members + float fBz{0}; // Magnetic field at MFT center + static constexpr double fCcenterMFT[3] = {0, 0, -61.4}; // Field evaluation point at center of MFT + float fZShift{0}; // z-vertex shift for forward track propagation + + void init(InitContext&) + { + fUpcCuts = (UPCCutparHolder)fUpcCutsConf; + if (fUpcCuts.getUseFwdCuts() || fEnableMFT) { + fCCDB->setURL("http://alice-ccdb.cern.ch"); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDBApi.init("http://alice-ccdb.cern.ch"); + } + const AxisSpec axisSelFwd{upchelpers::kNFwdSels, 0., static_cast(upchelpers::kNFwdSels), ""}; + histRegistry.add("MuonsSelCounter", "", kTH1F, {axisSelFwd}); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelAll + 1, "All"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelPt + 1, "Pt"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelEta + 1, "Eta"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelRabs + 1, "Rabs"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelpDCA + 1, "pDCA"); + histRegistry.get(HIST("MuonsSelCounter"))->GetXaxis()->SetBinLabel(upchelpers::kFwdSelChi2 + 1, "Chi2"); + + // NEW: Add histograms for global track monitoring + if (fEnableMFT) { + const AxisSpec axisTrackType{5, -0.5, 4.5, "Track Type"}; + histRegistry.add("hTrackTypes", "Track type distribution", kTH1F, {axisTrackType}); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(1, "MuonStandalone"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(2, "MCHStandalone"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(3, "GlobalMuon"); + histRegistry.get(HIST("hTrackTypes"))->GetXaxis()->SetBinLabel(4, "GlobalFwd"); + + const AxisSpec axisEta{100, -4.0, -2.0, "#eta"}; + histRegistry.add("hEtaGlobal", "Global track eta", kTH1F, {axisEta}); + + const AxisSpec axisDCAxy{200, 0., 10., "DCA_{xy} (cm)"}; + const AxisSpec axisDCAz{200, -10., 10., "DCA_{z} (cm)"}; + histRegistry.add("hDCAxyGlobal", "DCAxy of global tracks to best collision", kTH1F, {axisDCAxy}); + histRegistry.add("hDCAzGlobal", "DCAz of global tracks to best collision", kTH1F, {axisDCAz}); + histRegistry.add("hNCompatColls", "Number of compatible collisions per global track", kTH1F, {{21, -0.5, 20.5}}); + + const AxisSpec axisChi2Match{200, 0., 100., "#chi^{2}_{MCH-MFT}"}; + histRegistry.add("hChi2MatchMCHMFT", "Chi2 of MCH-MFT matching (before cut)", kTH1F, {axisChi2Match}); + + const AxisSpec axisMass{500, 0., 10., "m_{inv} (GeV/c^{2})"}; + histRegistry.add("hMassGlobalMuon", "Invariant mass from MCH-MID-MFT tracks only", kTH1F, {axisMass}); + histRegistry.add("hMassGlobalMuonWithMCHMFT", "Invariant mass from MCH-MID-MFT + MCH-MFT tracks", kTH1F, {axisMass}); + } + } + + bool cut(const o2::dataformats::GlobalFwdTrack& pft, const ForwardTracks::iterator& fwdTrack) + { + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelAll, 1); + auto pt = pft.getPt(); + auto eta = pft.getEta(); + auto pdca = fwdTrack.pDca(); + auto rabs = fwdTrack.rAtAbsorberEnd(); + auto chi2 = fwdTrack.chi2(); + bool passPt = pt > fUpcCuts.getFwdPtLow() && pt < fUpcCuts.getFwdPtHigh(); + bool passEta = eta > fUpcCuts.getFwdEtaLow() && eta < fUpcCuts.getFwdEtaHigh(); + bool passRabs = rabs > fUpcCuts.getMuonRAtAbsorberEndLow() && rabs < fUpcCuts.getMuonRAtAbsorberEndHigh(); + bool passPDca = rabs < upchelpers::AbsorberMid ? pdca < fUpcCuts.getMuonPDcaHighFirst() : pdca < fUpcCuts.getMuonPDcaHighSecond(); + bool passChi2 = chi2 > fUpcCuts.getFwdChi2Low() && chi2 < fUpcCuts.getFwdChi2High(); + if (passPt) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelPt, 1); + if (passEta) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelEta, 1); + if (passRabs) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelRabs, 1); + if (passPDca) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelpDCA, 1); + if (passChi2) + histRegistry.fill(HIST("MuonsSelCounter"), upchelpers::kFwdSelChi2, 1); + return passPt && passEta && passRabs && passPDca && passChi2; + } + + void skimMCInfo(o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles) + { + std::vector newEventIDs(mcCollisions.size(), -1); + + int32_t newPartID = 0; + int32_t newEventID = 0; + int32_t nMCParticles = mcParticles.size(); + // loop over MC particles to select only the ones from signal events + // and calculate new MC table IDs + for (int32_t mcPartID = 0; mcPartID < nMCParticles; mcPartID++) { + const auto& mcPart = mcParticles.iteratorAt(mcPartID); + if (!mcPart.has_mcCollision()) + continue; + int32_t mcEventID = mcPart.mcCollisionId(); + const auto& mcEvent = mcCollisions.iteratorAt(mcEventID); + bool isSignal = mcEvent.getGeneratorId() == fSignalGenID; + if (!isSignal) { + continue; + } + fNewPartIDs[mcPartID] = newPartID; + newPartID++; + if (newEventIDs[mcEventID] == -1) { + newEventIDs[mcEventID] = newEventID; + newEventID++; + } + } + + std::vector newMotherIDs{}; + + // storing MC particles + for (const auto& item : fNewPartIDs) { + int32_t mcPartID = item.first; + const auto& mcPart = mcParticles.iteratorAt(mcPartID); + int32_t mcEventID = mcPart.mcCollisionId(); + int32_t newEventID = newEventIDs[mcEventID]; + // collecting new mother IDs + if (mcPart.has_mothers()) { + const auto& motherIDs = mcPart.mothersIds(); + for (const auto& motherID : motherIDs) { + if (motherID >= nMCParticles) { + continue; + } + auto it = fNewPartIDs.find(motherID); + if (it != fNewPartIDs.end()) { + newMotherIDs.push_back(it->second); + } + } + } + // collecting new daughter IDs + int32_t newDaughterIDs[2] = {-1, -1}; + if (mcPart.has_daughters()) { + const auto& daughterIDs = mcPart.daughtersIds(); + int32_t firstDaughter = daughterIDs.front(); + int32_t lastDaughter = daughterIDs.back(); + if (firstDaughter >= nMCParticles || lastDaughter >= nMCParticles) { + continue; + } + auto itFirst = fNewPartIDs.find(firstDaughter); + auto itLast = fNewPartIDs.find(lastDaughter); + if (itFirst != fNewPartIDs.end() && itLast != fNewPartIDs.end()) { + newDaughterIDs[0] = fNewPartIDs.at(daughterIDs.front()); + newDaughterIDs[1] = fNewPartIDs.at(daughterIDs.back()); + } + } + udMCParticles(newEventID, mcPart.pdgCode(), mcPart.getHepMCStatusCode(), mcPart.flags(), newMotherIDs, newDaughterIDs, + mcPart.weight(), mcPart.px(), mcPart.py(), mcPart.pz(), mcPart.e()); + newMotherIDs.clear(); + } + + // storing MC events + for (int32_t i = 0; i < mcCollisions.size(); i++) { + if (newEventIDs[i] == -1) { + continue; + } + const auto& mcEvent = mcCollisions.iteratorAt(i); + const auto& bc = mcEvent.bc(); + udMCCollisions(bc.globalBC(), mcEvent.generatorsID(), mcEvent.posX(), mcEvent.posY(), mcEvent.posZ(), + mcEvent.t(), mcEvent.weight(), mcEvent.impactParameter()); + } + + newEventIDs.clear(); + } + + int64_t bcDiff(uint64_t bc1, uint64_t bc2) + { + return bc1 > bc2 ? bc1 - bc2 : bc2 - bc1; + } + + // find starting point for scrolling in some BC map -- closest to the input gbc + template + T::iterator getStartForScroll(uint64_t inGbc, T& gbcMap) + { + auto it1 = gbcMap.lower_bound(inGbc); + typename T::iterator it; + if (it1 != gbcMap.end()) { // found lower bound + auto it2 = it1; + uint64_t bc1 = it1->first; + if (it2 != gbcMap.begin()) + --it2; + uint64_t bc2 = it2->first; + uint64_t dbc1 = bcDiff(bc1, inGbc); + uint64_t dbc2 = bcDiff(bc2, inGbc); + it = (dbc1 <= dbc2) ? it1 : it2; + } else { // ended up in the end + it = it1; + --it; + } + return it; + } + + // scroll over gbcMap and do some operation on container + template + void scrollBackForth(uint64_t inGbc, uint64_t maxDbc, T& gbcMap, F&& func) + { + auto it = getStartForScroll(inGbc, gbcMap); + uint64_t gbc = it->first; + uint64_t dbc = bcDiff(inGbc, gbc); + + // start scrolling backward + int count = 0; + while (dbc <= maxDbc) { + func(it, gbc); + count++; + if (it == gbcMap.begin()) + break; + --it; + gbc = it->first; + dbc = bcDiff(inGbc, gbc); + } + + std::advance(it, count + 1); // move back to the starting point + 1 + + if (it == gbcMap.end()) // ended up in the end of map + return; + + gbc = it->first; + dbc = bcDiff(inGbc, gbc); + + // start scrolling forward + while (dbc <= maxDbc) { + func(it, gbc); + ++it; + if (it == gbcMap.end()) + break; + gbc = it->first; + dbc = bcDiff(inGbc, gbc); + } + } + + void getMchTrackIds(uint64_t inGbc, std::map>& mchTracksPerBC, + uint64_t maxDbc, std::map& outMchTrkIds) + { + auto fillMchIds = [&outMchTrkIds](std::map>::iterator& inIt, uint64_t gbc) { + std::vector& ids = inIt->second; + for (const auto& id : ids) + outMchTrkIds[id] = gbc; + }; + scrollBackForth(inGbc, maxDbc, mchTracksPerBC, fillMchIds); + } + + void getFV0Amplitudes(uint64_t inGbc, o2::aod::FV0As const& fv0s, uint64_t maxDbc, + std::map& mapBcs, std::vector& amps, std::vector& relBcs) + { + + auto fillAmps = [this, &fv0s, &s, &relBcs, inGbc](std::map::iterator& inIt, uint64_t gbc) { + int64_t fv0Id = inIt->second; + const auto& fv0 = fv0s.iteratorAt(fv0Id); + const auto& amplitudes = fv0.amplitude(); + float totalAmp = std::accumulate(amplitudes.begin(), amplitudes.end(), 0.f); + if (totalAmp > 0.f) { + amps.push_back(totalAmp); + auto relBc = static_cast(bcDiff(gbc, inGbc)); + if (gbc < inGbc) + relBc *= -1; + relBcs.push_back(relBc); + } + }; + scrollBackForth(inGbc, maxDbc, mapBcs, fillAmps); + } + + auto propagateToZero(ForwardTracks::iterator const& muon) + { + using SMatrix55 = ROOT::Math::SMatrix>; + using SMatrix5 = ROOT::Math::SVector; + 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::dataformats::GlobalFwdTrack propmuon; + o2::dataformats::GlobalFwdTrack track; + track.setParameters(tpars); + track.setZ(muon.z()); + track.setCovariances(tcovs); + auto mchTrack = fMatching.FwdtoMCH(track); + o2::mch::TrackExtrap::extrapToVertex(mchTrack, 0., 0., 0., 0., 0.); + auto proptrack = fMatching.MCHtoFwd(mchTrack); + propmuon.setParameters(proptrack.getParameters()); + propmuon.setZ(proptrack.getZ()); + propmuon.setCovariances(proptrack.getCovariances()); + return propmuon; + } + + bool addToFwdTable(int64_t candId, int64_t trackId, uint64_t gbc, float trackTime, ForwardTracks const& fwdTracks, const o2::aod::McFwdTrackLabels* mcFwdTrackLabels) + { + const auto& track = fwdTracks.iteratorAt(trackId); + float px, py, pz; + int sign; + + // NEW: Fill track type histogram if MFT enabled + if (fEnableMFT) { + histRegistry.fill(HIST("hTrackTypes"), track.trackType()); + if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || + track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack) { + histRegistry.fill(HIST("hEtaGlobal"), track.eta()); + } + } + + if (fUpcCuts.getUseFwdCuts()) { + bool isGlobal = track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || + track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack; + o2::dataformats::GlobalFwdTrack pft; + if (isGlobal && fEnableMFT) { + // For global tracks, use MFT helix propagation to vertex instead of + // MCH extrapolation, which fails because the track z is upstream of + // the front absorber (z ~ -60 cm vs absorber at z ~ -90 cm) + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, fZShift); + trackPar.propagateToZhelix(0., fBz); + pft.setParameters(trackPar.getParameters()); + pft.setZ(trackPar.getZ()); + pft.setCovariances(trackPar.getCovariances()); + } else { + pft = propagateToZero(track); + } + bool pass = cut(pft, track); + if (!pass) + return false; + px = pft.getPx(); + py = pft.getPy(); + pz = pft.getPz(); + sign = (pft.getInvQPt() > 0) ? 1 : -1; + } else { + px = track.px(); + py = track.py(); + pz = track.pz(); + sign = track.sign(); + } + + udFwdTracks(candId, px, py, pz, sign, gbc, trackTime, track.trackTimeRes()); + + // NEW: Enhanced extra info for global tracks + float mchmftChi2 = -1.; + if (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || + track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack) { + mchmftChi2 = track.chi2MatchMCHMFT(); + } + + udFwdTracksExtra(track.trackType(), track.nClusters(), track.pDca(), track.rAtAbsorberEnd(), + track.chi2(), track.chi2MatchMCHMID(), mchmftChi2, + track.mchBitMap(), track.midBitMap(), track.midBoards()); + + // NEW: Store MFT index for global tracks + int64_t mftIndex = -1; + if (fEnableMFT && (track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || + track.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack)) { + mftIndex = track.matchMFTTrackId(); + } + + udFwdIndices(candId, trackId, track.matchMCHTrackId(), mftIndex); + + if (fDoMC) { + const auto& label = mcFwdTrackLabels->iteratorAt(trackId); + uint16_t mcMask = label.mcMask(); + auto it = fNewPartIDs.find(label.mcParticleId()); + int32_t newPartID = it != fNewPartIDs.end() ? it->second : -1; + udFwdTrackLabels(newPartID, mcMask); + } + return true; + } + + // NEW: Function to fill MFT cluster information + void fillFwdClusters(const std::vector& trackIds, o2::aod::FwdTrkCls const& fwdTrkCls) + { + if (!fSaveMFTClusters) + return; + + std::map> clustersPerTrack; + for (const auto& cls : fwdTrkCls) { + clustersPerTrack[cls.fwdtrackId()].push_back(cls.globalIndex()); + } + + int newId = 0; + for (auto trackId : trackIds) { + auto it = clustersPerTrack.find(trackId); + if (it != clustersPerTrack.end()) { + const auto& clusters = it->second; + for (auto clsId : clusters) { + const auto& clsInfo = fwdTrkCls.iteratorAt(clsId); + udFwdTrkClusters(newId, clsInfo.x(), clsInfo.y(), clsInfo.z(), clsInfo.clInfo()); + } + } + newId++; + } + } + + // Propagate global muon track to collision vertex using helix propagation + // and compute DCA (adapted from ambiguousTrackPropagation) + // Returns {DCAxy, DCAz, DCAx, DCAy} + std::array propagateGlobalToDCA(ForwardTracks::iterator const& track, + double colX, double colY, double colZ) + { + o2::track::TrackParCovFwd trackPar = o2::aod::fwdtrackutils::getTrackParCovFwdShift(track, fZShift); + std::array dcaOrig; + trackPar.propagateToDCAhelix(fBz, {colX, colY, colZ}, dcaOrig); + double dcaXY = std::sqrt(dcaOrig[0] * dcaOrig[0] + dcaOrig[1] * dcaOrig[1]); + return {dcaXY, dcaOrig[2], dcaOrig[0], dcaOrig[1]}; + } + + void createCandidates(ForwardTracks const& fwdTracks, + o2::aod::FwdTrkCls const& fwdTrkCls, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + o2::aod::BCs const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FV0As const& fv0s, + o2::aod::Zdcs const& zdcs, + const o2::aod::McFwdTrackLabels* mcFwdTrackLabels) + { + using o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalForwardTrack; + using o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack; + using o2::aod::fwdtrack::ForwardTrackTypeEnum::MCHStandaloneTrack; + using o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack; + + int32_t runNumber = bcs.iteratorAt(0).runNumber(); + if (fUpcCuts.getUseFwdCuts() || fEnableMFT) { + if (runNumber != fRun) { + fRun = runNumber; + std::map metadata; + auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(fCCDBApi, fRun); + auto ts = soreor.second; + auto grpmag = fCCDBApi.retrieveFromTFileAny("GLO/Config/GRPMagField", metadata, ts); + o2::base::Propagator::initFieldFromGRP(grpmag); + if (!o2::base::GeometryManager::isGeometryLoaded()) + fCCDB->get("GLO/Config/GeometryAligned"); + if (fUpcCuts.getUseFwdCuts()) { + o2::mch::TrackExtrap::setField(); + } + // Initialize MFT magnetic field and z-shift for ambiguous track propagation + if (fEnableMFT) { + o2::field::MagneticField* field = static_cast(TGeoGlobalMagField::Instance()->GetField()); + fBz = field->getBz(fCcenterMFT); + LOG(info) << "Magnetic field at MFT center: bZ = " << fBz; + if (fApplyZShiftFromCCDB) { + auto* zShift = fCCDB->getForTimeStamp>(fZShiftPath, ts); + if (zShift != nullptr && !zShift->empty()) { + fZShift = (*zShift)[0]; + LOGF(info, "z-shift from CCDB: %f cm", fZShift); + } else { + fZShift = 0; + LOGF(info, "z-shift not found in CCDB path %s, set to 0 cm", fZShiftPath.value); + } + } else { + fZShift = fManualZShift; + LOGF(info, "z-shift manually set to %f cm", fZShift); + } + } + } + } + + auto nBcs = bcs.size(); + std::vector vGlobalBCs(nBcs, 0); + for (const auto& bc : bcs) { + vGlobalBCs[bc.globalIndex()] = bc.globalBC(); + } + + auto nCols = collisions.size(); + std::vector vColIndexBCs(nCols, -1); + for (const auto& col : collisions) { + vColIndexBCs[col.globalIndex()] = col.bcId(); + } + + std::map mapGlobalBcWithV0A{}; + constexpr float FV0ValidTime = 15.f; + for (const auto& fv0 : fv0s) { + if (std::abs(fv0.time()) > FV0ValidTime) + continue; + uint64_t globalBC = vGlobalBCs[fv0.bcId()]; + mapGlobalBcWithV0A[globalBC] = fv0.globalIndex(); + } + auto nFV0s = mapGlobalBcWithV0A.size(); + + std::map mapGlobalBcWithZdc{}; + constexpr float ZDCValidTime = 2.f; + for (const auto& zdc : zdcs) { + if (std::abs(zdc.timeZNA()) > ZDCValidTime && std::abs(zdc.timeZNC()) > ZDCValidTime) + continue; + uint64_t globalBC = vGlobalBCs[zdc.bcId()]; + mapGlobalBcWithZdc[globalBC] = zdc.globalIndex(); + } + auto nZdcs = mapGlobalBcWithZdc.size(); + + auto nFwdTracks = fwdTracks.size(); + auto nAmbFwdTracks = ambFwdTracks.size(); + std::vector vAmbFwdTrackIndex(nFwdTracks, -1); + std::vector vAmbFwdTrackIndexBCs(nAmbFwdTracks, -1); + for (const auto& ambTr : ambFwdTracks) { + vAmbFwdTrackIndex[ambTr.fwdtrackId()] = ambTr.globalIndex(); + vAmbFwdTrackIndexBCs[ambTr.globalIndex()] = ambTr.bcIds()[0]; + } + + std::map> mapGlobalBcsWithMCHMIDTrackIds; + std::map> mapGlobalBcsWithMCHTrackIds; + std::map> mapGlobalBcsWithGlobalMuonTrackIds; // MCH-MID-MFT (good timing from MID) + std::map> mapGlobalBcsWithMCHMFTTrackIds; // MCH-MFT only (poor timing) + + for (const auto& fwdTrack : fwdTracks) { + auto trackType = fwdTrack.trackType(); + + // Skip if not a relevant track type + if (trackType != MCHStandaloneTrack && + trackType != MuonStandaloneTrack && + trackType != GlobalMuonTrack && + trackType != GlobalForwardTrack) + continue; + + auto trackId = fwdTrack.globalIndex(); + int64_t indexBC = vAmbFwdTrackIndex[trackId] < 0 ? vColIndexBCs[fwdTrack.collisionId()] : vAmbFwdTrackIndexBCs[vAmbFwdTrackIndex[trackId]]; + auto globalBC = vGlobalBCs[indexBC] + TMath::FloorNint(fwdTrack.trackTime() / o2::constants::lhc::LHCBunchSpacingNS + 1.); + + if (trackType == MuonStandaloneTrack) { // MCH-MID + mapGlobalBcsWithMCHMIDTrackIds[globalBC].push_back(trackId); + } else if (trackType == MCHStandaloneTrack) { // MCH-only + mapGlobalBcsWithMCHTrackIds[globalBC].push_back(trackId); + } else if (fEnableMFT && trackType == GlobalMuonTrack) { // MCH-MID-MFT: good timing, used as anchor + histRegistry.fill(HIST("hChi2MatchMCHMFT"), fwdTrack.chi2MatchMCHMFT()); + if (fwdTrack.chi2MatchMCHMFT() > 0 && fwdTrack.chi2MatchMCHMFT() < fMaxChi2MatchMCHMFT) { + mapGlobalBcsWithGlobalMuonTrackIds[globalBC].push_back(trackId); + } + } else if (fEnableMFT && trackType == GlobalForwardTrack) { // MCH-MFT: poor timing, matched to anchors + histRegistry.fill(HIST("hChi2MatchMCHMFT"), fwdTrack.chi2MatchMCHMFT()); + if (fwdTrack.chi2MatchMCHMFT() > 0 && fwdTrack.chi2MatchMCHMFT() < fMaxChi2MatchMCHMFT) { + mapGlobalBcsWithMCHMFTTrackIds[globalBC].push_back(trackId); + } + } + } + + // Map global BC to collisions for DCA-based vertex assignment + std::map> mapGlobalBCtoCollisions; + if (fEnableMFT) { + for (const auto& col : collisions) { + uint64_t gbc = vGlobalBCs[col.bcId()]; + mapGlobalBCtoCollisions[gbc].push_back(col.globalIndex()); + } + } + + std::vector selTrackIds{}; // NEW: For cluster saving + + int32_t candId = 0; + + // Process global tracks: MCH-MID-MFT anchors + MCH-MFT in BC window + // MCH-MID-MFT tracks have good timing (from MID) and serve as anchors. + // MCH-MFT tracks have poor timing and are searched in a BC window around anchors. + if (fEnableMFT && !mapGlobalBcsWithGlobalMuonTrackIds.empty()) { + for (const auto& gbc_anchorids : mapGlobalBcsWithGlobalMuonTrackIds) { + uint64_t globalBcAnchor = gbc_anchorids.first; + auto itFv0Id = mapGlobalBcWithV0A.find(globalBcAnchor); + if (itFv0Id != mapGlobalBcWithV0A.end()) { + auto fv0Id = itFv0Id->second; + const auto& fv0 = fv0s.iteratorAt(fv0Id); + float fv0Amp = 0.f; + for (const auto& amp : fv0.amplitude()) + fv0Amp += amp; + if (fv0Amp > fMaxFV0Amp) + continue; + } + + auto& vAnchorIds = gbc_anchorids.second; // MCH-MID-MFT tracks at this BC + + // Search MCH-MFT tracks in BC window around anchor (analogous to MCH-only matching) + std::map mapMchMftIdBc{}; + getMchTrackIds(globalBcAnchor, mapGlobalBcsWithMCHMFTTrackIds, fBcWindowMCHMFT, mapMchMftIdBc); + + // Collect all track IDs for vertex finding (anchors + matched MCH-MFT) + std::vector allTrackIds; + allTrackIds.reserve(vAnchorIds.size() + mapMchMftIdBc.size()); + for (const auto& id : vAnchorIds) + allTrackIds.push_back(id); + for (const auto& [id, gbc] : mapMchMftIdBc) + allTrackIds.push_back(id); + + // Step 1: Find best collision vertex using DCA-based propagation + float bestVtxX = 0., bestVtxY = 0., bestVtxZ = 0.; + double bestAvgDCA = 999.; + bool hasVertex = false; + int nCompatColls = 0; + + for (int dbc = -static_cast(fBcWindowCollision); dbc <= static_cast(fBcWindowCollision); dbc++) { + uint64_t searchBC = globalBcAnchor + dbc; + auto itCol = mapGlobalBCtoCollisions.find(searchBC); + if (itCol == mapGlobalBCtoCollisions.end()) + continue; + for (auto colIdx : itCol->second) { + nCompatColls++; + const auto& col = collisions.iteratorAt(colIdx); + double sumDCAxy = 0.; + int nTracks = 0; + for (const auto& iglobal : allTrackIds) { + const auto& trk = fwdTracks.iteratorAt(iglobal); + auto dca = propagateGlobalToDCA(trk, col.posX(), col.posY(), col.posZ()); + sumDCAxy += dca[0]; + nTracks++; + } + double avgDCA = nTracks > 0 ? sumDCAxy / nTracks : 999.; + if (!hasVertex || avgDCA < bestAvgDCA) { + bestAvgDCA = avgDCA; + bestVtxX = col.posX(); + bestVtxY = col.posY(); + bestVtxZ = col.posZ(); + hasVertex = true; + } + } + } + + histRegistry.fill(HIST("hNCompatColls"), nCompatColls); + + // Step 2: Write anchor tracks (MCH-MID-MFT) with DCA quality cut + constexpr double kMuonMass = o2::constants::physics::MassMuon; + uint16_t numContrib = 0; + double sumPx = 0., sumPy = 0., sumPz = 0., sumE = 0.; + for (const auto& ianchor : vAnchorIds) { + if (hasVertex) { + const auto& trk = fwdTracks.iteratorAt(ianchor); + auto dca = propagateGlobalToDCA(trk, bestVtxX, bestVtxY, bestVtxZ); + histRegistry.fill(HIST("hDCAxyGlobal"), dca[0]); + histRegistry.fill(HIST("hDCAzGlobal"), dca[1]); + if (dca[0] > static_cast(fMaxDCAxy)) + continue; + } + if (!addToFwdTable(candId, ianchor, globalBcAnchor, 0., fwdTracks, mcFwdTrackLabels)) + continue; + const auto& trk = fwdTracks.iteratorAt(ianchor); + double p2 = trk.px() * trk.px() + trk.py() * trk.py() + trk.pz() * trk.pz(); + sumPx += trk.px(); + sumPy += trk.py(); + sumPz += trk.pz(); + sumE += std::sqrt(p2 + kMuonMass * kMuonMass); + numContrib++; + selTrackIds.push_back(ianchor); + } + + // Fill invariant mass from MCH-MID-MFT anchors only + uint16_t numContribAnch = numContrib; + if (numContribAnch >= 2) { + double mass2 = sumE * sumE - sumPx * sumPx - sumPy * sumPy - sumPz * sumPz; + histRegistry.fill(HIST("hMassGlobalMuon"), mass2 > 0. ? std::sqrt(mass2) : 0.); + } + + // Step 3: Write matched MCH-MFT tracks with DCA quality cut and adjusted track time + for (const auto& [imchMft, gbc] : mapMchMftIdBc) { + if (hasVertex) { + const auto& trk = fwdTracks.iteratorAt(imchMft); + auto dca = propagateGlobalToDCA(trk, bestVtxX, bestVtxY, bestVtxZ); + histRegistry.fill(HIST("hDCAxyGlobal"), dca[0]); + histRegistry.fill(HIST("hDCAzGlobal"), dca[1]); + if (dca[0] > static_cast(fMaxDCAxy)) + continue; + } + if (!addToFwdTable(candId, imchMft, gbc, (gbc - globalBcAnchor) * o2::constants::lhc::LHCBunchSpacingNS, fwdTracks, mcFwdTrackLabels)) + continue; + const auto& trk = fwdTracks.iteratorAt(imchMft); + double p2 = trk.px() * trk.px() + trk.py() * trk.py() + trk.pz() * trk.pz(); + sumPx += trk.px(); + sumPy += trk.py(); + sumPz += trk.pz(); + sumE += std::sqrt(p2 + kMuonMass * kMuonMass); + numContrib++; + selTrackIds.push_back(imchMft); + } + + // Fill invariant mass including MCH-MFT tracks (only if MCH-MFT tracks were added) + if (numContrib > numContribAnch && numContrib >= 2) { + double mass2 = sumE * sumE - sumPx * sumPx - sumPy * sumPy - sumPz * sumPz; + histRegistry.fill(HIST("hMassGlobalMuonWithMCHMFT"), mass2 > 0. ? std::sqrt(mass2) : 0.); + } + + if (numContrib < 1) + continue; + + eventCandidates(globalBcAnchor, runNumber, bestVtxX, bestVtxY, bestVtxZ, 0, numContrib, 0, 0); + std::vector amplitudesV0A{}; + std::vector relBCsV0A{}; + std::vector amplitudesT0A{}; + std::vector relBCsT0A{}; + if (nFV0s > 0) { + getFV0Amplitudes(globalBcAnchor, fv0s, fBcWindowFITAmps, mapGlobalBcWithV0A, amplitudesV0A, relBCsV0A); + } + eventCandidatesSelsFwd(0., 0., amplitudesT0A, relBCsT0A, amplitudesV0A, relBCsV0A); + if (nZdcs > 0) { + auto itZDC = mapGlobalBcWithZdc.find(globalBcAnchor); + if (itZDC != mapGlobalBcWithZdc.end()) { + const auto& zdc = zdcs.iteratorAt(itZDC->second); + float timeZNA = zdc.timeZNA(); + float timeZNC = zdc.timeZNC(); + float eComZNA = zdc.energyCommonZNA(); + float eComZNC = zdc.energyCommonZNC(); + udZdcsReduced(candId, timeZNA, timeZNC, eComZNA, eComZNC); + } + } + candId++; + } + } + + // Process MCH-MID tracks (original logic) + for (const auto& gbc_muids : mapGlobalBcsWithMCHMIDTrackIds) { + uint64_t globalBcMid = gbc_muids.first; + auto itFv0Id = mapGlobalBcWithV0A.find(globalBcMid); + if (itFv0Id != mapGlobalBcWithV0A.end()) { + auto fv0Id = itFv0Id->second; + const auto& fv0 = fv0s.iteratorAt(fv0Id); + float fv0Amp = 0.f; + for (const auto& amp : fv0.amplitude()) + fv0Amp += amp; + if (fv0Amp > fMaxFV0Amp) + continue; + } + uint16_t numContrib = 0; + auto& vMuonIds = gbc_muids.second; + // writing MCH-MID tracks + for (const auto& imuon : vMuonIds) { + if (!addToFwdTable(candId, imuon, globalBcMid, 0., fwdTracks, mcFwdTrackLabels)) + continue; + numContrib++; + selTrackIds.push_back(imuon); + } + if (numContrib < 1) // didn't save any MCH-MID tracks + continue; + std::map mapMchIdBc{}; + getMchTrackIds(globalBcMid, mapGlobalBcsWithMCHTrackIds, fBcWindowMCH, mapMchIdBc); + // writing MCH-only tracks + for (const auto& [imch, gbc] : mapMchIdBc) { + if (!addToFwdTable(candId, imch, gbc, (gbc - globalBcMid) * o2::constants::lhc::LHCBunchSpacingNS, fwdTracks, mcFwdTrackLabels)) + continue; + numContrib++; + selTrackIds.push_back(imch); + } + eventCandidates(globalBcMid, runNumber, 0., 0., 0., 0, numContrib, 0, 0); + std::vector amplitudesV0A{}; + std::vector relBCsV0A{}; + std::vector amplitudesT0A{}; + std::vector relBCsT0A{}; + if (nFV0s > 0) { + getFV0Amplitudes(globalBcMid, fv0s, fBcWindowFITAmps, mapGlobalBcWithV0A, amplitudesV0A, relBCsV0A); + } + eventCandidatesSelsFwd(0., 0., amplitudesT0A, relBCsT0A, amplitudesV0A, relBCsV0A); + if (nZdcs > 0) { + auto itZDC = mapGlobalBcWithZdc.find(globalBcMid); + if (itZDC != mapGlobalBcWithZdc.end()) { + const auto& zdc = zdcs.iteratorAt(itZDC->second); + float timeZNA = zdc.timeZNA(); + float timeZNC = zdc.timeZNC(); + float eComZNA = zdc.energyCommonZNA(); + float eComZNC = zdc.energyCommonZNC(); + udZdcsReduced(candId, timeZNA, timeZNC, eComZNA, eComZNC); + } + } + candId++; + } + + // NEW: Fill MFT cluster information + if (fEnableMFT && fSaveMFTClusters && !selTrackIds.empty()) { + fillFwdClusters(selTrackIds, fwdTrkCls); + } + + vGlobalBCs.clear(); + vColIndexBCs.clear(); + mapGlobalBcWithV0A.clear(); + mapGlobalBcWithZdc.clear(); + vAmbFwdTrackIndex.clear(); + vAmbFwdTrackIndexBCs.clear(); + mapGlobalBcsWithMCHMIDTrackIds.clear(); + mapGlobalBcsWithMCHTrackIds.clear(); + mapGlobalBcsWithGlobalMuonTrackIds.clear(); + mapGlobalBcsWithMCHMFTTrackIds.clear(); + mapGlobalBCtoCollisions.clear(); + selTrackIds.clear(); + } + + void processFwd(ForwardTracks const& fwdTracks, + o2::aod::FwdTrkCls const& fwdTrkCls, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + o2::aod::BCs const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FV0As const& fv0s, + o2::aod::Zdcs const& zdcs) + { + fDoMC = false; + createCandidates(fwdTracks, fwdTrkCls, ambFwdTracks, bcs, collisions, fv0s, zdcs, (o2::aod::McFwdTrackLabels*)nullptr); + } + + void processFwdMC(ForwardTracks const& fwdTracks, + o2::aod::FwdTrkCls const& fwdTrkCls, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + o2::aod::BCs const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FV0As const& fv0s, + o2::aod::Zdcs const& zdcs, + o2::aod::McCollisions const& mcCollisions, + o2::aod::McParticles const& mcParticles, + o2::aod::McFwdTrackLabels const& mcFwdTrackLabels) + { + fDoMC = true; + skimMCInfo(mcCollisions, mcParticles); + createCandidates(fwdTracks, fwdTrkCls, ambFwdTracks, bcs, collisions, fv0s, zdcs, &mcFwdTrackLabels); + fNewPartIDs.clear(); + } + + PROCESS_SWITCH(UpcCandProducerGlobalMuon, processFwd, "Produce candidates in forward region", true); + PROCESS_SWITCH(UpcCandProducerGlobalMuon, processFwdMC, "Produce candidates in forward region with MC information", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/TableProducer/upcCandProducerMuon.cxx b/PWGUD/TableProducer/upcCandProducerMuon.cxx index 329a83b432c..0ac8458d60f 100644 --- a/PWGUD/TableProducer/upcCandProducerMuon.cxx +++ b/PWGUD/TableProducer/upcCandProducerMuon.cxx @@ -16,24 +16,37 @@ #include "PWGUD/Core/UPCCutparHolder.h" #include "PWGUD/Core/UPCHelpers.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "Field/MagneticField.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "GlobalTracking/MatchGlobalFwd.h" -#include "MCHTracking/TrackExtrap.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Math/SMatrix.h" -#include "TGeoGlobalMagField.h" - -#include +#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include #include +#include #include #include diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index 62c6abc732f..d8aa575b906 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -268,3 +268,8 @@ o2physics_add_dpl_workflow(sg-exclusive-jpsi-midrapidity SOURCES sgExclusiveJpsiMidrapidity.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(fitbit-mapping + SOURCES upcTestFITBitMapping.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGUD/Tasks/FwdMuonsUPC.cxx b/PWGUD/Tasks/FwdMuonsUPC.cxx index 0c4b3d81e3b..b3351965727 100644 --- a/PWGUD/Tasks/FwdMuonsUPC.cxx +++ b/PWGUD/Tasks/FwdMuonsUPC.cxx @@ -16,22 +16,28 @@ /// \author Andrea Giovanni Riffero -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/O2DatabasePDGPlugin.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" -#include "TRandom3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include // table for saving tree with info on data namespace dimu diff --git a/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx b/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx index 4347871377a..26d8c91c0e0 100644 --- a/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx +++ b/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx @@ -13,18 +13,28 @@ /// /// \author Simone Ragoni -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -// #include "TDatabasePDG.h" -#include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" -// #include "TLorentzVector.h" -// #include "TVector3.h" -#include "Math/LorentzVector.h" // ROOT::Math::LorentzVector -#include "Math/PxPyPzM4D.h" // ROOT::Math::PxPyPzM4D -#include "TMath.h" + +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/decayTreeAnalyzer.cxx b/PWGUD/Tasks/decayTreeAnalyzer.cxx index c725a2ca72a..5a46ed7c8cb 100644 --- a/PWGUD/Tasks/decayTreeAnalyzer.cxx +++ b/PWGUD/Tasks/decayTreeAnalyzer.cxx @@ -13,18 +13,27 @@ // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since 01.03.2024 -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "CommonConstants/LHCConstants.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UDGoodRunSelector.h" +#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/decayTree.h" +#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/dgCandAnalyzer.cxx b/PWGUD/Tasks/dgCandAnalyzer.cxx index d7283115434..79b5b6c5f02 100644 --- a/PWGUD/Tasks/dgCandAnalyzer.cxx +++ b/PWGUD/Tasks/dgCandAnalyzer.cxx @@ -18,12 +18,31 @@ #include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/UDTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include #include #include diff --git a/PWGUD/Tasks/diffMCDataScanner.cxx b/PWGUD/Tasks/diffMCDataScanner.cxx index 8ad8d7ae853..06fa70f5220 100644 --- a/PWGUD/Tasks/diffMCDataScanner.cxx +++ b/PWGUD/Tasks/diffMCDataScanner.cxx @@ -13,9 +13,32 @@ /// \author Paul Buehler, paul.buehler@oeaw.ac.at /// \since 01.10.2021 -#include "Framework/AnalysisTask.h" -#include "PWGUD/DataModel/McPIDTable.h" #include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/McPIDTable.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include using namespace o2; using namespace o2::framework; @@ -25,7 +48,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(ConfigParamSpec{"runCase", VariantType::Int, 0, {"runCase: 0 - histos, 1 - mcTruth, 2 - mc only, else - tree"}}); } -#include "Framework/runDataProcessing.h" +#include using namespace o2::framework::expressions; diff --git a/PWGUD/Tasks/diffMCQA.cxx b/PWGUD/Tasks/diffMCQA.cxx index 19bf3016a97..c6b1f650db2 100644 --- a/PWGUD/Tasks/diffMCQA.cxx +++ b/PWGUD/Tasks/diffMCQA.cxx @@ -13,13 +13,35 @@ /// \author Paul Buehler, paul.buehler@oeaw.ac.at /// \since 01.10.2021 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "TLorentzVector.h" -#include "ReconstructionDataFormats/BCRange.h" -#include "CommonConstants/PhysicsConstants.h" +#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UDHelpers.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGUD/Tasks/diffQA.cxx b/PWGUD/Tasks/diffQA.cxx index a1e9ec34185..59bdd9a67eb 100644 --- a/PWGUD/Tasks/diffQA.cxx +++ b/PWGUD/Tasks/diffQA.cxx @@ -13,14 +13,38 @@ /// \author Paul Buehler, paul.buehler@oeaw.ac.at /// \since 20.05.2022 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "TLorentzVector.h" -#include "CommonConstants/LHCConstants.h" -#include "ReconstructionDataFormats/BCRange.h" -#include "CommonConstants/PhysicsConstants.h" +#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/UDHelpers.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGUD/Tasks/eventByevent.cxx b/PWGUD/Tasks/eventByevent.cxx index 072ae2d961c..913319bd785 100644 --- a/PWGUD/Tasks/eventByevent.cxx +++ b/PWGUD/Tasks/eventByevent.cxx @@ -10,16 +10,27 @@ // or submit itself to any jurisdiction. // -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include #include -#include "TLorentzVector.h" -#include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/SGTrackSelector.h" + +#include +#include using namespace std; using namespace o2; diff --git a/PWGUD/Tasks/exclusivePentaquark.cxx b/PWGUD/Tasks/exclusivePentaquark.cxx index eb5170bb400..8f21b5f333f 100644 --- a/PWGUD/Tasks/exclusivePentaquark.cxx +++ b/PWGUD/Tasks/exclusivePentaquark.cxx @@ -11,15 +11,25 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include -#include -using std::array; +#include +#include +#include + using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/exclusivePhi.cxx b/PWGUD/Tasks/exclusivePhi.cxx index c0850b4b84d..499f8e1046f 100644 --- a/PWGUD/Tasks/exclusivePhi.cxx +++ b/PWGUD/Tasks/exclusivePhi.cxx @@ -11,17 +11,27 @@ // #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include + +#include -#include +#include +#include #include -using std::array; using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/exclusivePhiLeptons.cxx b/PWGUD/Tasks/exclusivePhiLeptons.cxx index cb2d8834862..ae4e80c31ed 100644 --- a/PWGUD/Tasks/exclusivePhiLeptons.cxx +++ b/PWGUD/Tasks/exclusivePhiLeptons.cxx @@ -11,16 +11,27 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include -#include +#include +#include +#include #include -using std::array; + using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/exclusivePhiLeptonsTrees.cxx b/PWGUD/Tasks/exclusivePhiLeptonsTrees.cxx index ecc65174f26..577f25e63c6 100644 --- a/PWGUD/Tasks/exclusivePhiLeptonsTrees.cxx +++ b/PWGUD/Tasks/exclusivePhiLeptonsTrees.cxx @@ -8,19 +8,30 @@ // 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 "PWGUD/Core/SGSelector.h" + #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "TLorentzVector.h" +#include +#include +#include #include -#include +#include +#include +#include #include -using std::array; + using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index 8cefae2262c..c295a40df6e 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -14,26 +14,33 @@ /// \author Anantha Padmanabhan M Nair #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/UDTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "TPDGCode.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include #include #include +#include +#include +#include #include #include diff --git a/PWGUD/Tasks/exclusiveTwoProtons.cxx b/PWGUD/Tasks/exclusiveTwoProtons.cxx index d22c92cccbc..bc3c4783aba 100644 --- a/PWGUD/Tasks/exclusiveTwoProtons.cxx +++ b/PWGUD/Tasks/exclusiveTwoProtons.cxx @@ -11,15 +11,28 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include + +#include + +#include +#include +#include -#include -using std::array; using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/exclusiveTwoProtonsSG.cxx b/PWGUD/Tasks/exclusiveTwoProtonsSG.cxx index 521096634e9..7d8e3ed9326 100644 --- a/PWGUD/Tasks/exclusiveTwoProtonsSG.cxx +++ b/PWGUD/Tasks/exclusiveTwoProtonsSG.cxx @@ -11,15 +11,28 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include + +#include + +#include +#include +#include -#include -using std::array; using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index baf24af6f94..061eda25566 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -11,33 +11,34 @@ /// \file flowCorrelationsUpc.cxx /// \brief Provides a sparse with usefull two particle correlation info -/// \author Mingrui Zhao (mingrui.zhao@cern.ch, mingrui.zhao@mail.labz0.org) +/// \author Yongxi Du (yongxi.du@cern.ch), Mingrui Zhao (mingrui.zhao@cern.ch, mingrui.zhao@mail.labz0.org) /// copied from Thor Jensen (thor.kjaersgaard.jensen@cern.ch) and Debojit Sarkar (debojit.sarkar@cern.ch) #include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" - -#include "TRandom3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include #include namespace o2::aod @@ -45,33 +46,42 @@ namespace o2::aod namespace flowcorrupc { DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int); -} +DECLARE_SOA_COLUMN(Truegapside, truegapside, int); +} // namespace flowcorrupc DECLARE_SOA_TABLE(Multiplicity, "AOD", "MULTIPLICITY", flowcorrupc::Multiplicity); - +DECLARE_SOA_TABLE(Truegapside, "AOD", "TRUEGAPSIDE", flowcorrupc::Truegapside); } // namespace o2::aod using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::math; // define the filtered collisions and tracks #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; struct CalcNchUpc { O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.1f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") + // Added UPC Cuts + SGSelector sgSelector; + Configurable cfgCutFV0{"cfgCutFV0", 50., "FV0A threshold"}; + Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; + Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; + Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; + // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); using UdTracks = soa::Join; using UdTracksFull = soa::Join; - using UDCollisionsFull = soa::Join; + using UDCollisionsFull = soa::Join; Produces multiplicityNch; + Produces truegapside; HistogramRegistry registry{"registry"}; @@ -79,14 +89,25 @@ struct CalcNchUpc { { AxisSpec axisNch = {100, 0, 100}; AxisSpec axisVrtx = {10, -10, 10}; + // AxisSpec axisgap = {12, -6, 6}; + // std::vector trueGapBins = {-2, -1, 0, 1, 2, 3}; + // AxisSpec axisgap = {trueGapBins, "true gap side"}; + + std::vector binEdges = {-1.5, -0.5, 0.5, 1.5, 2.5, 3.5}; + AxisSpec axisgap = {binEdges, "true gap side"}; + registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); registry.add("Ncharge", "N_{charge}", {HistType::kTH1D, {axisNch}}); registry.add("zVtx_all", "zVtx_all", {HistType::kTH1D, {axisVrtx}}); + registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVrtx, axisNch}}); + // registry.add("truegap", "truegap", {HistType::kTH1D, {axisgap}}); } void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { multiplicityNch(tracks.size()); + truegapside(sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC)); + // LOG(info) << "truegapside=" << sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); registry.fill(HIST("Ncharge"), tracks.size()); registry.fill(HIST("zVtx_all"), collision.posZ()); } @@ -94,15 +115,30 @@ struct CalcNchUpc { struct FlowCorrelationsUpc { O2_DEFINE_CONFIGURABLE(cfgZVtxCut, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.2f, "minimum accepted track pT") + O2_DEFINE_CONFIGURABLE(cfgIfVertex, bool, false, "choose vertex or not") + O2_DEFINE_CONFIGURABLE(cfgPtCutMin, float, 0.1f, "minimum accepted track pT") O2_DEFINE_CONFIGURABLE(cfgPtCutMax, float, 10.0f, "maximum accepted track pT") - O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.8f, "Eta cut") + O2_DEFINE_CONFIGURABLE(cfgEtaCut, float, 0.9f, "Eta cut") O2_DEFINE_CONFIGURABLE(cfgMinMixEventNum, int, 5, "Minimum number of events to mix") O2_DEFINE_CONFIGURABLE(cfgMinMult, int, 0, "Minimum multiplicity for collision") O2_DEFINE_CONFIGURABLE(cfgMaxMult, int, 10, "Maximum multiplicity for collision") O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") O2_DEFINE_CONFIGURABLE(cfgUsePtOrder, bool, true, "enable trigger pT < associated pT cut") O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, true, "enable trigger pT < associated pT cut in mixed event") + O2_DEFINE_CONFIGURABLE(cfgCutMerging, float, 0.02, "Merging cut on track merge") + O2_DEFINE_CONFIGURABLE(cfgRadiusLow, float, 0.8, "Low radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgRadiusHigh, float, 2.5, "High radius for merging cut") + O2_DEFINE_CONFIGURABLE(cfgIsGoodItsLayers, bool, false, "whether choose itslayers") + O2_DEFINE_CONFIGURABLE(cfgGapSide, int, 1, "0: gapside A;1:C") + O2_DEFINE_CONFIGURABLE(cfgGapSideMerge, bool, false, "whether merge A and C side together") + O2_DEFINE_CONFIGURABLE(cfgDcaxy, bool, true, "choose dcaxy") + O2_DEFINE_CONFIGURABLE(cfgDcaz, bool, false, "choose dcaz") + O2_DEFINE_CONFIGURABLE(cfgDcazCut, float, 10.0, "dcaz cut") + O2_DEFINE_CONFIGURABLE(cfgItsClusterSize, unsigned int, 5, "ITS cluster size") + O2_DEFINE_CONFIGURABLE(cfgMaxTPCChi2NCl, int, 4, "tpcchi2") + O2_DEFINE_CONFIGURABLE(cfgEvSelOccupancy, bool, true, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 1000, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; @@ -127,15 +163,15 @@ struct FlowCorrelationsUpc { Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; - Configurable cfgGapSideSelection{"cfgGapSideSelection", 2, "gap selection"}; // make the filters and cuts. - // Filter collisionFilter = (nabs(aod::collision::posZ) < cfgZVtxCut) && (aod::flowcorrupc::multiplicity) > cfgMinMult && (aod::flowcorrupc::multiplicity) < cfgMaxMult && (aod::evsel::sel8) == true; - // Filter trackFilter = (nabs(aod::track::eta) < cfgEtaCut) && (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); + Filter trackFilter = (aod::udtrack::isPVContributor == true); + Filter collisionFilter = ((aod::udcollision::gapSide == (uint8_t)1 || aod::udcollision::gapSide == (uint8_t)0) && (cfgIfVertex == false || aod::collision::posZ < cfgZVtxCut) && (aod::udcollision::occupancyInTime > 0 && aod::udcollision::occupancyInTime < cfgCutOccupancyHigh) && (aod::flowcorrupc::truegapside == 1 || aod::flowcorrupc::truegapside == 0)); - using UdTracks = soa::Join; - using UdTracksFull = soa::Join; - using UDCollisionsFull = soa::Join; + using UdTracks = soa::Filtered>; + using UdTracksFull = soa::Filtered>; + + using UDCollisionsFull = soa::Filtered>; // Define the outputs OutputObj same{Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; @@ -145,6 +181,8 @@ struct FlowCorrelationsUpc { void init(InitContext&) { + LOG(info) << "cfgGapSide = " << cfgGapSide; + LOG(info) << "cfgGapSide value type: " << typeid(cfgGapSide).name(); LOGF(info, "Starting init"); // Make histograms to check the distributions after cuts registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution @@ -154,10 +192,17 @@ struct FlowCorrelationsUpc { registry.add("pT", "pT", {HistType::kTH1D, {axisPtTrigger}}); registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("Nch_vs_zVtx", "Nch vs zVtx", {HistType::kTH2D, {axisVertex, axisMultiplicity}}); + registry.add("Nch_same", "Nch same event", {HistType::kTH1D, {axisMultiplicity}}); + registry.add("Nch_mixed", "Nch mixed event", {HistType::kTH1D, {axisMultiplicity}}); registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); - registry.add("eventcount", "bin", {HistType::kTH1F, {{3, 0, 3, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount_same", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many events are in the same and mixed event + registry.add("eventcount_mixed", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many events are in the same and mixed event + + registry.add("trackcount_same", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many tracks are in the same and mixed event + registry.add("trackcount_mixed", "bin", {HistType::kTH1F, {{10, 0, 10, "bin"}}}); // histogram to see how many tracks are in the same and mixed event std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, @@ -180,6 +225,58 @@ struct FlowCorrelationsUpc { MixedEvent = 3 }; + template + float getDPhiStar(TTrack const& track1, TTrack const& track2, float radius, int runnum, float phi1, float phi2) + { + float charge1 = track1.sign(); + float charge2 = track2.sign(); + + float pt1 = track1.pt(); + float pt2 = track2.pt(); + + int fbSign = 1; + + int zzo = 544868; + if (runnum >= zzo) { + fbSign = -1; + } + + float dPhiStar = phi1 - phi2 - charge1 * fbSign * std::asin(0.075 * radius / pt1) + charge2 * fbSign * std::asin(0.075 * radius / pt2); + + if (dPhiStar > constants::math::PI) + dPhiStar = constants::math::TwoPI - dPhiStar; + return dPhiStar; + } + + template + bool trackSelected(TTrack track) + { + // registry.fill(HIST("hTrackCount"), 0.5); + // UPC selection + if (track.pt() < cfgPtCutMin || track.pt() > cfgPtCutMax) { + return false; + } + // registry.fill(HIST("hTrackCount"), 1.5); + if (cfgDcaz && !(std::fabs(track.dcaZ()) < cfgDcazCut)) { + return false; + } + // registry.fill(HIST("hTrackCount"), 2.5); + double dcaLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); + if (cfgDcaxy && !(std::fabs(track.dcaXY()) < dcaLimit)) { + return false; + } + // registry.fill(HIST("hTrackCount"), 3.5); + if (track.itsClusterSizes() <= cfgItsClusterSize) { + return false; + } + // registry.fill(HIST("hTrackCount"), 4.5); + if (track.tpcChi2NCl() >= cfgMaxTPCChi2NCl) { + return false; + } + // registry.fill(HIST("hTrackCount"), 5.5); + return true; + } + // fill multiple histograms template void fillYield(TCollision collision, TTracks tracks) // function to fill the yield and etaphi histograms. @@ -196,7 +293,7 @@ struct FlowCorrelationsUpc { } template - void fillCorrelations(TTracks tracks1, TTracks tracks2, float posZ, int system) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelations(TTracks tracks1, TTracks tracks2, float posZ, int system, int runnum) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); @@ -204,11 +301,16 @@ struct FlowCorrelationsUpc { // loop over all tracks for (auto const& track1 : tracks1) { + if (!trackSelected(track1)) + continue; + if (system == SameEvent) { registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt()); } for (auto const& track2 : tracks2) { + if (!trackSelected(track2)) + continue; if (track1.globalIndex() == track2.globalIndex()) continue; // For pt-differential correlations, skip if the trigger and associate are the same track @@ -222,6 +324,28 @@ struct FlowCorrelationsUpc { float deltaPhi = RecoDecay::constrainAngle(phi1 - phi2, -PIHalf); float deltaEta = RecoDecay::eta(momentum1) - RecoDecay::eta(momentum2); + if (std::abs(deltaEta) < cfgCutMerging) { + + double dPhiStarHigh = getDPhiStar(track1, track2, cfgRadiusHigh, runnum, phi1, phi2); + double dPhiStarLow = getDPhiStar(track1, track2, cfgRadiusLow, runnum, phi1, phi2); + + const double kLimit = 3.0 * cfgCutMerging; + + bool bIsBelow = false; + + if (std::abs(dPhiStarLow) < kLimit || std::abs(dPhiStarHigh) < kLimit || dPhiStarLow * dPhiStarHigh < 0) { + for (double rad(cfgRadiusLow); rad < cfgRadiusHigh; rad += 0.01) { + double dPhiStar = getDPhiStar(track1, track2, rad, runnum, phi1, phi2); + if (std::abs(dPhiStar) < kLimit) { + bIsBelow = true; + break; + } + } + if (bIsBelow) + continue; + } + } + // fill the right sparse and histograms if (system == SameEvent) { same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); @@ -236,29 +360,17 @@ struct FlowCorrelationsUpc { void processSame(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) { - if (std::abs(collision.posZ()) > cfgZVtxCut) { - return; - } + // LOG(info) << "Event passed filter: truegapside=" << collision.truegapside(); if (tracks.size() < cfgMinMult || tracks.size() > cfgMaxMult) { return; } + registry.fill(HIST("eventcount_same"), 3.5); + int runIndex = collision.runNumber(); - int gapSide = collision.gapSide(); - const int minGapSide = 0; - const int maxGapSide = 2; - if (gapSide < minGapSide || gapSide > maxGapSide) { - return; - } - - int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - gapSide = trueGapSide; - if (gapSide == cfgGapSideSelection) { - return; - } - - registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + // registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin + registry.fill(HIST("Nch_vs_zVtx"), collision.posZ(), tracks.size()); fillYield(collision, tracks); - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent); // fill the SE histogram and Sparse + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, runIndex); // fill the SE histogram and Sparse } PROCESS_SWITCH(FlowCorrelationsUpc, processSame, "Process same event", true); @@ -275,8 +387,12 @@ struct FlowCorrelationsUpc { SameKindPair pairs{binningOnVtxAndMult, cfgMinMixEventNum, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) { - registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + // registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin + if (tracks1.size() < cfgMinMult || tracks1.size() > cfgMaxMult || tracks2.size() < cfgMinMult || tracks2.size() > cfgMaxMult) { + continue; + } + registry.fill(HIST("eventcount_same"), 4.5); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, collision1.runNumber()); // fill the ME histogram and Sparse } } PROCESS_SWITCH(FlowCorrelationsUpc, processMixed, "Process mixed events", true); diff --git a/PWGUD/Tasks/flowCumulantsUpc.cxx b/PWGUD/Tasks/flowCumulantsUpc.cxx index b97b8e26edc..9624c1a5c86 100644 --- a/PWGUD/Tasks/flowCumulantsUpc.cxx +++ b/PWGUD/Tasks/flowCumulantsUpc.cxx @@ -10,48 +10,55 @@ // or submit itself to any jurisdiction. /// \file flowCumulantsUpc.cxx -/// \author Mingrui Zhao (mingrui.zhao@mail.labz0.org, mingrui.zhao@cern.ch) +/// \author Yongxi Du (yongxi.du@cern.ch), Mingrui Zhao (mingrui.zhao@mail.labz0.org, mingrui.zhao@cern.ch) /// \since Mar/2025 /// \brief jira: , task to measure flow observables with cumulant method -#include "FlowContainer.h" -#include "GFW.h" -#include "GFWCumulant.h" -#include "GFWPowerArray.h" -#include "GFWWeights.h" - #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" +// +#include "PWGCF/GenericFramework/Core/FlowContainer.h" +#include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include -#include "Math/LorentzVector.h" -#include "Math/PxPyPzM4D.h" -#include "TList.h" -#include "TMath.h" -#include "TVector3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include +#include +#include +#include #include #include #include +#include + +#include + +#include #include +#include #include +#include #include #include #include @@ -65,20 +72,16 @@ using namespace o2::framework::expressions; struct FlowCumulantsUpc { - // resort - // Preslice perCollision = aod::track::collisionId; - PresliceUnsorted perMcCollision = o2::aod::udmcparticle::udMcCollisionId; - // Preslice perCol = aod::track::collisionId; - O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgIfVertex, bool, false, "choose vertex or not") O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") O2_DEFINE_CONFIGURABLE(cfgCentFT0CMin, float, 0.0f, "Minimum centrality (FT0C) to cut events in filter") O2_DEFINE_CONFIGURABLE(cfgCentFT0CMax, float, 100.0f, "Maximum centrality (FT0C) to cut events in filter") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.1f, "Minimal pT for poi tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtRefMin, float, 0.2f, "Minimal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtRefMin, float, 0.1f, "Minimal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtRefMax, float, 3.0f, "Maximal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for all tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.1f, "Minimal pT for all tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for all tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") @@ -86,22 +89,22 @@ struct FlowCumulantsUpc { O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") O2_DEFINE_CONFIGURABLE(cfgCutDCAxyppPass3Enabled, bool, false, "switch of ppPass3 DCAxy pt dependent cut") - O2_DEFINE_CONFIGURABLE(cfgCutDCAzPtDepEnabled, bool, false, "switch of DCAz pt dependent cut") - O2_DEFINE_CONFIGURABLE(cfgTrkSelSwitch, bool, false, "switch for self-defined track selection") - O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") - O2_DEFINE_CONFIGURABLE(cfgUseTentativeEventCounter, bool, false, "After sel8(), count events regardless of real event selection") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") - O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "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") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") - O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") - O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") - O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") - O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") - 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(cfgCutMaxIR, float, 50.0f, "maximum interaction rate (kHz)") - O2_DEFINE_CONFIGURABLE(cfgCutMinIR, float, 0.0f, "minimum interaction rate (kHz)") + // O2_DEFINE_CONFIGURABLE(cfgCutDCAzPtDepEnabled, bool, false, "switch of DCAz pt dependent cut") + // O2_DEFINE_CONFIGURABLE(cfgTrkSelSwitch, bool, false, "switch for self-defined track selection") + // O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") + // O2_DEFINE_CONFIGURABLE(cfgUseTentativeEventCounter, bool, false, "After sel8(), count events regardless of real event selection") + // O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") + // O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodZvtxFT0vsPV, bool, false, "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") + // O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInTimeRangeStandard, bool, false, "no collisions in specified time range") + // O2_DEFINE_CONFIGURABLE(cfgEvSelkIsGoodITSLayersAll, bool, true, "cut time intervals with dead ITS staves") + // O2_DEFINE_CONFIGURABLE(cfgEvSelkNoCollInRofStandard, bool, false, "no other collisions in this Readout Frame with per-collision multiplicity above threshold") + // O2_DEFINE_CONFIGURABLE(cfgEvSelkNoHighMultCollInPrevRof, bool, false, "veto an event if FT0C amplitude in previous ITS ROF is above threshold") + // O2_DEFINE_CONFIGURABLE(cfgEvSelMultCorrelation, bool, true, "Multiplicity correlation cut") + // O2_DEFINE_CONFIGURABLE(cfgEvSelV0AT0ACut, bool, true, "V0A T0A 5 sigma cut") + // 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(cfgCutMaxIR, float, 50.0f, "maximum interaction rate (kHz)") + // O2_DEFINE_CONFIGURABLE(cfgCutMinIR, float, 0.0f, "minimum interaction rate (kHz)") O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 30, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") @@ -111,12 +114,29 @@ struct FlowCumulantsUpc { O2_DEFINE_CONFIGURABLE(cfgAcceptanceList, std::string, "", "CCDB path to acceptance lsit object") O2_DEFINE_CONFIGURABLE(cfgAcceptanceListEnabled, bool, false, "switch of acceptance list") O2_DEFINE_CONFIGURABLE(cfgEvSelOccupancy, bool, true, "Occupancy cut") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 1000, "High cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgUseSmallMemory, bool, false, "Use small memory mode") + O2_DEFINE_CONFIGURABLE(cfgIsGoodItsLayers, bool, false, "whether choose itslayers") + O2_DEFINE_CONFIGURABLE(cfgGapSideA, bool, true, "choose gapside A") + O2_DEFINE_CONFIGURABLE(cfgGapSideC, bool, false, "choose gapside C") + O2_DEFINE_CONFIGURABLE(cfgDcaxy, bool, true, "choose dcaxy") + O2_DEFINE_CONFIGURABLE(cfgDcaz, bool, false, "choose dcaz") + O2_DEFINE_CONFIGURABLE(cfgDcazCut, float, 10.0, "dcaz cut") + O2_DEFINE_CONFIGURABLE(cfgItsClusterSize, unsigned int, 5, "ITS cluster size") + O2_DEFINE_CONFIGURABLE(cfgMaxTPCChi2NCl, int, 4, "tpcchi2") + O2_DEFINE_CONFIGURABLE(cfgConsistentEventFlag, int, 0, "Flag to select consistent events - 0: off, 1: v2{2} gap calculable, 2: v2{4} full calculable, 4: v2{4} gap calculable, 8: v2{4} 3sub calculable") + 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"}; Configurable> cfgRunRemoveList{"cfgRunRemoveList", std::vector{-1}, "excluded run numbers"}; + Configurable> cfgConsistentEventVector{"cfgConsistentEventVector", std::vector{-0.8, -0.5, -0.4, 0.4, 0.5, 0.8}, "eta regions: left(min,max), mid(min,max), right(min,max)"}; + struct AcceptedTracks { + int nNeg; + int nMid; + int nPos; + int nFull; + }; 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"}; @@ -131,7 +151,6 @@ struct FlowCumulantsUpc { Configurable cfgCutFT0A{"cfgCutFT0A", 150., "FT0A threshold"}; Configurable cfgCutFT0C{"cfgCutFT0C", 50., "FT0C threshold"}; Configurable cfgCutZDC{"cfgCutZDC", 10., "ZDC threshold"}; - Configurable cfgGapSideSelection{"cfgGapSideSelection", 2, "gap selection"}; // Corrections TH1D* mEfficiency = nullptr; @@ -175,10 +194,9 @@ struct FlowCumulantsUpc { TH2* gCurrentHadronicRate; // - // using MCparticles = aod::UDMcParticles::iterator; using UdTracks = soa::Join; using UdTracksFull = soa::Join; - // using UDCollisionsFull = soa::Join; + using UDCollisionsFull = soa::Join; // Track selection TrackSelection myTrackSel; @@ -208,12 +226,21 @@ struct FlowCumulantsUpc { // Add some output objects to the histogram registry // Event QA - registry.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{5, 0, 5}}}); + registry.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{6, 0, 6}}}); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "after supicious Runs removal"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "after additional event cut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "after correction loads"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "after gapside selection"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "after its selection"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "after pt selection"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "after occupancy"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "after consistency check"); + + registry.add("hTrackCount", "Number of tracks;; Count", {HistType::kTH1D, {{7, 0, 7}}}); + registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(1, "after event selection"); + registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(2, "PVContributor"); + registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(3, "dcaz"); + registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(4, "dcaxy"); + registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(5, "its clusters"); + registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(6, "tpc chi2"); registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); @@ -225,26 +252,22 @@ struct FlowCumulantsUpc { registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "occupancy"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "MultCorrelation"); registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); - if (cfgUseTentativeEventCounter) { - registry.add("hEventCountTentative", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(1, "after sel8"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(8, "occupancy"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(9, "MultCorrelation"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); - } + // if (cfgUseTentativeEventCounter) { + // registry.add("hEventCountTentative", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(1, "after sel8"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(8, "occupancy"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(9, "MultCorrelation"); + // registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); + // } registry.add("hVtxZ", "Vexter Z distribution", {HistType::kTH1D, {axisVertex}}); registry.add("hMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); - registry.add("hCentMC", hCentTitle.c_str(), {HistType::kTH1D, {{90, 0, 90}}}); - registry.add("hVtxZMC", "Vexter Z distribution", {HistType::kTH1D, {axisVertex}}); - registry.add("hMultMC", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); - registry.add("numberOfTracksMC", "Number of tracks per event", {HistType::kTH1D, {{1000, 0, 1000}}}); registry.add("hCent", hCentTitle.c_str(), {HistType::kTH1D, {{90, 0, 90}}}); if (!cfgUseSmallMemory) { registry.add("BeforeSel8_globalTracks_centT0C", "before sel8;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); @@ -280,11 +303,8 @@ struct FlowCumulantsUpc { registry.add("hDCAz", "DCAz after cuts; DCAz (cm); Pt", {HistType::kTH2D, {{200, -0.5, 0.5}, {200, 0, 5}}}); registry.add("hDCAxy", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{200, -0.5, 0.5}, {200, 0, 5}}}); registry.add("hTrackCorrection2d", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisNch, axisNch}}); + registry.add("hEtaNch2D", "Eta vs Nch; #eta; Nch", {HistType::kTH2D, {axisEta, axisNch}}); - registry.add("hPxMc", "Px distribution of MC truth particles", {HistType::kTH1D, {{100, -10, 10}}}); - registry.add("hPyMc", "Px distribution of MC truth particles", {HistType::kTH1D, {{100, -10, 10}}}); - registry.add("hPzMc", "Px distribution of MC truth particles", {HistType::kTH1D, {{100, -10, 10}}}); - registry.add("hweightMc", "weight distribution of MC truth particles", {HistType::kTH1D, {{100, 0, 1}}}); registry.add("hPhiMC", "#phi distribution", {HistType::kTH1D, {axisPhi}}); registry.add("hPhiWeightedMC", "corrected #phi distribution", {HistType::kTH1D, {axisPhi}}); registry.add("hEtaMC", "#eta distribution", {HistType::kTH1D, {axisEta}}); @@ -297,9 +317,15 @@ struct FlowCumulantsUpc { registry.add("hnTPCCrossedRowMC", "Number of crossed TPC Rows", {HistType::kTH1D, {{100, 40, 180}}}); registry.add("hDCAzMC", "DCAz after cuts; DCAz (cm); Pt", {HistType::kTH2D, {{200, -0.5, 0.5}, {200, 0, 5}}}); registry.add("hDCAxyMC", "DCAxy after cuts; DCAxy (cm); Pt", {HistType::kTH2D, {{200, -0.5, 0.5}, {200, 0, 5}}}); - registry.add("eventCounterMC", "Number of MC Event;; Count", {HistType::kTH1D, {{5, 0, 5}}}); registry.add("hTrackCorrection2dMC", "Correlation table for number of tracks table; uncorrected track; corrected track", {HistType::kTH2D, {axisNch, axisNch}}); + // // MC event QA histograms + // registry.add("eventCounterMC", "Number of MC Events;; Count", {HistType::kTH1D, {{5, 0, 5}}}); + // registry.add("hVtxZMC", "Vexter Z distribution (MC)", {HistType::kTH1D, {axisVertex}}); + // registry.add("hMultMC", "Multiplicity distribution (MC)", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); + // registry.add("hCentMC", "Centrality distribution (MC)", {HistType::kTH1D, {{90, 0, 90}}}); + // registry.add("numberOfTracksMC", "Number of MC tracks;; Count", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); + o2::framework::AxisSpec axis = axisPt; int nPtBins = axis.binEdges.size() - 1; double* ptBins = &(axis.binEdges)[0]; @@ -524,28 +550,26 @@ struct FlowCumulantsUpc { } 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)); - corrconfigsmc.push_back(fGFWMC->GetCorrelatorConfig(userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str(), kFALSE)); } } fGFW->CreateRegions(); - fGFWMC->CreateRegions(); - - if (cfgUseAdditionalEventCut) { - fMultPVCutLow = new TF1("fMultPVCutLow", "[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); - 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); - } + + // if (cfgUseAdditionalEventCut) { + // fMultPVCutLow = new TF1("fMultPVCutLow", "[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); + // 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); + // } myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); myTrackSel.SetMinNClustersTPC(cfgCutTPCclu); @@ -644,8 +668,6 @@ struct FlowCumulantsUpc { return; } - // ... 其余代码保持不变 ... - void loadCorrections(uint64_t timestamp, int runNumber) { if (correctionsLoaded) { @@ -700,142 +722,153 @@ struct FlowCumulantsUpc { return true; } - template - bool eventSelected(TCollision collision, const int multTrk, const float centrality) - { - registry.fill(HIST("hEventCountSpecific"), 0.5); - if (cfgEvSelkNoSameBunchPileup && !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; - } - if (cfgEvSelkNoSameBunchPileup) { - registry.fill(HIST("hEventCountSpecific"), 1.5); - } - if (cfgEvSelkIsGoodZvtxFT0vsPV && !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; - } - if (cfgEvSelkIsGoodZvtxFT0vsPV) { - registry.fill(HIST("hEventCountSpecific"), 2.5); - } - if (cfgEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { - // no collisions in specified time range - return 0; - } - if (cfgEvSelkNoCollInTimeRangeStandard) { - registry.fill(HIST("hEventCountSpecific"), 3.5); - } - if (cfgEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { - // from Jan 9 2025 AOT meeting - // cut time intervals with dead ITS staves - return 0; - } - if (cfgEvSelkIsGoodITSLayersAll) { - registry.fill(HIST("hEventCountSpecific"), 4.5); - } - if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { - // no other collisions in this Readout Frame with per-collision multiplicity above threshold - return 0; - } - if (cfgEvSelkNoCollInRofStandard) { - registry.fill(HIST("hEventCountSpecific"), 5.5); - } - if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { - // veto an event if FT0C amplitude in previous ITS ROF is above threshold - return 0; - } - if (cfgEvSelkNoHighMultCollInPrevRof) { - registry.fill(HIST("hEventCountSpecific"), 6.5); - } - auto multNTracksPV = collision.multNTracksPV(); - auto occupancy = collision.trackOccupancyInTimeRange(); - if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - return 0; - } - if (cfgEvSelOccupancy) { - registry.fill(HIST("hEventCountSpecific"), 7.5); - } + // template + // bool eventSelected(TCollision collision, const int multTrk, const float centrality) + // { + // registry.fill(HIST("hEventCountSpecific"), 0.5); + // if (cfgEvSelkNoSameBunchPileup && !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; + // } + // // if (cfgEvSelkNoSameBunchPileup) { + // // registry.fill(HIST("hEventCountSpecific"), 1.5); + // // } + // if (cfgEvSelkIsGoodZvtxFT0vsPV && !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; + // } + // if (cfgEvSelkIsGoodZvtxFT0vsPV) { + // registry.fill(HIST("hEventCountSpecific"), 2.5); + // } + // if (cfgEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // // no collisions in specified time range + // return 0; + // } + // if (cfgEvSelkNoCollInTimeRangeStandard) { + // registry.fill(HIST("hEventCountSpecific"), 3.5); + // } + // if (cfgEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // // from Jan 9 2025 AOT meeting + // // cut time intervals with dead ITS staves + // return 0; + // } + // if (cfgEvSelkIsGoodITSLayersAll) { + // registry.fill(HIST("hEventCountSpecific"), 4.5); + // } + // if (cfgEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // // no other collisions in this Readout Frame with per-collision multiplicity above threshold + // return 0; + // } + // if (cfgEvSelkNoCollInRofStandard) { + // registry.fill(HIST("hEventCountSpecific"), 5.5); + // } + // if (cfgEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // // veto an event if FT0C amplitude in previous ITS ROF is above threshold + // return 0; + // } + // if (cfgEvSelkNoHighMultCollInPrevRof) { + // registry.fill(HIST("hEventCountSpecific"), 6.5); + // } + // auto multNTracksPV = collision.multNTracksPV(); + // auto occupancy = collision.occupancyInTime(); + // if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + // return 0; + // } + // if (cfgEvSelOccupancy) { + // registry.fill(HIST("hEventCountSpecific"), 7.5); + // } - if (cfgEvSelMultCorrelation) { - 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; - } - if (cfgEvSelMultCorrelation) { - registry.fill(HIST("hEventCountSpecific"), 8.5); - } + // if (cfgEvSelMultCorrelation) { + // 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; + // } + // if (cfgEvSelMultCorrelation) { + // registry.fill(HIST("hEventCountSpecific"), 8.5); + // } - // V0A T0A 5 sigma cut - constexpr int kSigmaCut = 5; - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > kSigmaCut * fT0AV0ASigma->Eval(collision.multFT0A()))) { - return 0; - } - if (cfgEvSelV0AT0ACut) { - registry.fill(HIST("hEventCountSpecific"), 9.5); - } + // // V0A T0A 5 sigma cut + // constexpr int kSigmaCut = 5; + // if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > kSigmaCut * fT0AV0ASigma->Eval(collision.multFT0A()))) { + // return 0; + // } + // if (cfgEvSelV0AT0ACut) { + // registry.fill(HIST("hEventCountSpecific"), 9.5); + // } - return 1; - } + // return 1; + // } - template - void eventCounterQA(TCollision collision, const int multTrk, const float centrality) - { - registry.fill(HIST("hEventCountTentative"), 0.5); - // Regradless of the event selection, fill the event counter histograms - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - registry.fill(HIST("hEventCountTentative"), 1.5); - } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - registry.fill(HIST("hEventCountTentative"), 2.5); - } - if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { - registry.fill(HIST("hEventCountTentative"), 3.5); - } - if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { - registry.fill(HIST("hEventCountTentative"), 4.5); - } - if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { - registry.fill(HIST("hEventCountTentative"), 5.5); - } - if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { - registry.fill(HIST("hEventCountTentative"), 6.5); - } - auto multNTracksPV = collision.multNTracksPV(); - auto occupancy = collision.trackOccupancyInTimeRange(); - if (!(occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { - registry.fill(HIST("hEventCountTentative"), 7.5); - } - if (!((multNTracksPV < fMultPVCutLow->Eval(centrality)) || (multNTracksPV > fMultPVCutHigh->Eval(centrality)) || (multTrk < fMultCutLow->Eval(centrality)) || (multTrk > fMultCutHigh->Eval(centrality)))) { - registry.fill(HIST("hEventCountTentative"), 8.5); - } - constexpr int kSigmaCut = 5; - if (!(std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > kSigmaCut * fT0AV0ASigma->Eval(collision.multFT0A()))) { - registry.fill(HIST("hEventCountTentative"), 9.5); - } - } + // // template + // // void eventCounterQA(TCollision collision, const int multTrk, const float centrality) + // // { + // // registry.fill(HIST("hEventCountTentative"), 0.5); + // // // Regradless of the event selection, fill the event counter histograms + // // if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // // registry.fill(HIST("hEventCountTentative"), 1.5); + // // } + // // if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // // registry.fill(HIST("hEventCountTentative"), 2.5); + // } + // if (collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // registry.fill(HIST("hEventCountTentative"), 3.5); + // } + // if (collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // registry.fill(HIST("hEventCountTentative"), 4.5); + // } + // if (collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + // registry.fill(HIST("hEventCountTentative"), 5.5); + // } + // if (collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + // registry.fill(HIST("hEventCountTentative"), 6.5); + // } + // auto multNTracksPV = collision.multNTracksPV(); + // auto occupancy = collision.trackOccupancyInTimeRange(); + // if (!(occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + // registry.fill(HIST("hEventCountTentative"), 7.5); + // } + // if (!((multNTracksPV < fMultPVCutLow->Eval(centrality)) || (multNTracksPV > fMultPVCutHigh->Eval(centrality)) || (multTrk < fMultCutLow->Eval(centrality)) || (multTrk > fMultCutHigh->Eval(centrality)))) { + // registry.fill(HIST("hEventCountTentative"), 8.5); + // } + // // constexpr int kSigmaCut = 5; + // // if (!(std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > kSigmaCut * fT0AV0ASigma->Eval(collision.multFT0A()))) { + // // registry.fill(HIST("hEventCountTentative"), 9.5); + // // } + // } template bool trackSelected(TTrack track) { + registry.fill(HIST("hTrackCount"), 0.5); // UPC selection if (!track.isPVContributor()) { return false; } - constexpr float kDcazCut = 2.0; - if (!(std::fabs(track.dcaZ()) < kDcazCut)) { + registry.fill(HIST("hTrackCount"), 1.5); + if (cfgDcaz && !(std::fabs(track.dcaZ()) < cfgDcazCut)) { return false; } + registry.fill(HIST("hTrackCount"), 2.5); double dcaLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); - if (!(std::fabs(track.dcaXY()) < dcaLimit)) { + if (cfgDcaxy && !(std::fabs(track.dcaXY()) < dcaLimit)) { + return false; + } + registry.fill(HIST("hTrackCount"), 3.5); + if (track.itsClusterSizes() <= cfgItsClusterSize) { + return false; + } + registry.fill(HIST("hTrackCount"), 4.5); + if (track.tpcChi2NCl() >= cfgMaxTPCChi2NCl) { return false; } + registry.fill(HIST("hTrackCount"), 5.5); return true; } @@ -856,204 +889,270 @@ struct FlowCumulantsUpc { gCurrentHadronicRate = gHadronicRate[mRunNumber]; } - // void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) - // { - // std::cout << "Processing collision============================================== " << std::endl; - - // registry.fill(HIST("hEventCount"), 0.5); - // int gapSide = collision.gapSide(); - // constexpr int kGapSideSelection = 0; - // constexpr int kGapSideOppositeSelection = 2; - // if (gapSide < kGapSideSelection || gapSide > kGapSideOppositeSelection) { - // return; - // } - - // int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); - // gapSide = trueGapSide; - // if (gapSide == cfgGapSideSelection) { - // return; - // } - // registry.fill(HIST("hEventCount"), 1.5); - // float cent = 100; - // float lRandom = fRndm->Rndm(); - // float vtxz = collision.posZ(); - // registry.fill(HIST("hVtxZ"), vtxz); - // registry.fill(HIST("hMult"), tracks.size()); - // registry.fill(HIST("hCent"), cent); - // fGFW->Clear(); - - // // // track weights - // float weff = 1, wacc = 1; - // double nTracksCorrected = 0; - // float independent = cent; - // if (cfgUseNch) { - // independent = static_cast(tracks.size()); - // } - - // for (const auto& track : tracks) { - // if (!trackSelected(track)) - // continue; - // auto momentum = std::array{track.px(), track.py(), track.pz()}; - // double pt = RecoDecay::pt(momentum); - // double phi = RecoDecay::phi(momentum); - // double eta = RecoDecay::eta(momentum); - // bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range - // bool withinPtRef = (cfgCutPtRefMin < pt) && (pt < cfgCutPtRefMax); // within RF pT range - // if (cfgOutputNUAWeights) { - // if (cfgOutputNUAWeightsRefPt) { - // if (withinPtRef) { - // fWeights->fill(phi, eta, vtxz, pt, cent, 0); - // } - // } else { - // fWeights->fill(phi, eta, vtxz, pt, cent, 0); - // } - // } - // if (!setCurrentParticleWeights(weff, wacc, phi, eta, pt, vtxz)) { - // continue; - // } - // registry.fill(HIST("hPt"), track.pt()); - // if (withinPtRef) { - // registry.fill(HIST("hPhi"), phi); - // registry.fill(HIST("hPhiWeighted"), phi, wacc); - // registry.fill(HIST("hEta"), eta); - // registry.fill(HIST("hPtRef"), pt); - // registry.fill(HIST("hDCAz"), track.dcaZ(), track.pt()); - // registry.fill(HIST("hDCAxy"), track.dcaXY(), track.pt()); - // nTracksCorrected += weff; - // } - // if (withinPtRef) { - // fGFW->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 1); - // } - // if (withinPtPOI) { - // fGFW->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 2); - // } - // if (withinPtPOI && withinPtRef) { - // fGFW->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 4); - // } - // } - // registry.fill(HIST("hTrackCorrection2d"), tracks.size(), nTracksCorrected); - - // // Filling Flow Container - // for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { - // fillFC(corrconfigs.at(l_ind), independent, lRandom); - // } - // } - // PROCESS_SWITCH(FlowCumulantsUpc, process, "process", false); - - //----------------------------------------------------------------------------------------------------------------------- - void processSim(aod::UDMcCollisions const& mcCollisions, aod::UDMcParticles const& mcParticles) + template + float getDPhiStar(TTrack const& track1, TTrack const& track2, float radius, int runnum) { - LOG(info) << "Processing MC collision======================== " << std::endl; + float charge1 = track1.sign(); + float charge2 = track2.sign(); - // std::cout << mcParicles::IndexudmcCollisions.is_sorted(); + float phi1 = track1.phi(); + float phi2 = track2.phi(); - for (const auto& mcCollision : mcCollisions) { - auto groupedUDMcParticles = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); - registry.fill(HIST("eventCounterMC"), 0.5); + float pt1 = track1.pt(); + float pt2 = track2.pt(); - // registry.fill(HIST("hEventCount"), 1.5); - float cent = 50; - float vtxz = 0; + int fbSign = 1; - vtxz = mcCollision.posZ(); - registry.fill(HIST("hVtxZMC"), vtxz); - registry.fill(HIST("eventCounterMC"), mcCollision.size()); - registry.fill(HIST("hMultMC"), groupedUDMcParticles.size()); - registry.fill(HIST("hCentMC"), cent); + int zzo = 544868; + if (runnum >= zzo) { + fbSign = -1; + } - auto massPion = o2::constants::physics::MassPionCharged; - registry.fill(HIST("numberOfTracksMC"), groupedUDMcParticles.size()); - // LOGF(info, "New event! mcParticles.size() = %d", mcParticles.size()); + float dPhiStar = phi1 - phi2 - charge1 * fbSign * std::asin(0.075 * radius / pt1) + charge2 * fbSign * std::asin(0.075 * radius / pt2); - float lRandomMc = fRndmMc->Rndm(); - fGFWMC->Clear(); + if (dPhiStar > constants::math::PI) + dPhiStar = constants::math::TwoPI - dPhiStar; + if (dPhiStar < -constants::math::PI) + dPhiStar = -constants::math::TwoPI - dPhiStar; - // // track weights - float weff = 1, wacc = 1; - double nTracksCorrected = 0; - float independent = cent; - if (cfgUseNch) { - independent = static_cast(groupedUDMcParticles.size()); - } - - // LOG(info) << "mcParticles.size() = " << groupedUDMcParticles.size() << std::endl; + return dPhiStar; + } - for (const auto& mcParticle : groupedUDMcParticles) { + void process(UDCollisionsFull::iterator const& collision, UdTracksFull const& tracks) + { + registry.fill(HIST("hEventCount"), 0.5); + // if(!eventSelected(collision, tracks.size(), 100.0f)) { + // eventCounterQA(collision, tracks.size(), 100.0f); + // return; + // } + int gapSide = collision.gapSide(); + if (gapSide == 0) { + if (!cfgGapSideA) { + return; + } + } + if (gapSide == 1) { + if (!cfgGapSideC) { + return; + } + } + if (gapSide != 0 && gapSide != 1) { + return; + } + int trueGapSide = sgSelector.trueGap(collision, cfgCutFV0, cfgCutFT0A, cfgCutFT0C, cfgCutZDC); + gapSide = trueGapSide; + if (gapSide == 0) { + if (!cfgGapSideA) { + return; + } + } + if (gapSide == 1) { + if (!cfgGapSideC) { + return; + } + } + if (gapSide != 0 && gapSide != 1) { + return; + } + registry.fill(HIST("hEventCount"), 1.5); + if (cfgIsGoodItsLayers && collision.trs() == 0) { + return; + } + registry.fill(HIST("hEventCount"), 2.5); + float cent = 100; + float lRandom = fRndm->Rndm(); + float vtxz = collision.posZ(); + registry.fill(HIST("hVtxZ"), vtxz); + registry.fill(HIST("hMult"), tracks.size()); + registry.fill(HIST("hCent"), cent); + fGFW->Clear(); + if (cfgIfVertex && std::abs(vtxz) > cfgCutVertex) { + return; + } + registry.fill(HIST("hEventCount"), 3.5); + int occupancy = collision.occupancyInTime(); + if (cfgEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + return; + } + registry.fill(HIST("hEventCount"), 4.5); + // // track weights + float weff = 1, wacc = 1; + double nTracksCorrected = 0; + float independent = cent; + if (cfgUseNch) { + independent = static_cast(tracks.size()); + } + AcceptedTracks acceptedTracks{0, 0, 0, 0}; + std::vector consistentEventVector = cfgConsistentEventVector; - // LOG(info) << "filling mc particle px: " << mcParticle.px() << ", py: " << mcParticle.py() << ", pz: " << mcParticle.pz() << std::endl; + for (const auto& track : tracks) { + registry.fill(HIST("hChi2prTPCcls"), track.tpcChi2NCl()); + if (!trackSelected(track)) { + continue; + } + auto momentum = std::array{track.px(), track.py(), track.pz()}; + double pt = RecoDecay::pt(momentum); + double phi = RecoDecay::phi(momentum); + double eta = RecoDecay::eta(momentum); + bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range + bool withinPtRef = (cfgCutPtRefMin < pt) && (pt < cfgCutPtRefMax); // within RF pT range + if (cfgOutputNUAWeights) { + if (cfgOutputNUAWeightsRefPt) { + if (withinPtRef) { + fWeights->fill(phi, eta, vtxz, pt, cent, 0); + } + } else { + fWeights->fill(phi, eta, vtxz, pt, cent, 0); + } + } + if (!setCurrentParticleWeights(weff, wacc, phi, eta, pt, vtxz)) { + continue; + } + registry.fill(HIST("hPt"), track.pt()); + + if (cfgConsistentEventFlag && consistentEventVector.size() == 6) { // o2-linter: disable=magic-number (size match) + acceptedTracks.nFull += 1; + if (eta > consistentEventVector[0] && eta < consistentEventVector[1]) + acceptedTracks.nNeg += 1; + if (eta > consistentEventVector[2] && eta < consistentEventVector[3]) + acceptedTracks.nMid += 1; + if (eta > consistentEventVector[4] && eta < consistentEventVector[5]) + acceptedTracks.nPos += 1; + } + if (withinPtRef) { + registry.fill(HIST("hPhi"), phi); + registry.fill(HIST("hPhiWeighted"), phi, wacc); + registry.fill(HIST("hEta"), eta); + registry.fill(HIST("hPtRef"), pt); + registry.fill(HIST("hDCAz"), track.dcaZ(), track.pt()); + registry.fill(HIST("hDCAxy"), track.dcaXY(), track.pt()); + nTracksCorrected += weff; + } + if (withinPtRef) { + fGFW->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 1); + } + if (withinPtPOI) { + fGFW->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 2); + } + if (withinPtPOI && withinPtRef) { + fGFW->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 4); + } + registry.fill(HIST("hEtaNch2D"), eta, tracks.size()); + } + registry.fill(HIST("hTrackCorrection2d"), tracks.size(), nTracksCorrected); + if (cfgConsistentEventFlag) { + if (cfgConsistentEventFlag & 1) { + if (!acceptedTracks.nPos || !acceptedTracks.nNeg) + return; + } else if (cfgConsistentEventFlag & 2) { + if (acceptedTracks.nFull < 4) // o2-linter: disable=magic-number (at least four tracks in full acceptance) + return; + } else if (cfgConsistentEventFlag & 4) { + if (acceptedTracks.nPos < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in each subevent) + return; + } + if (cfgConsistentEventFlag & 8) { + if (acceptedTracks.nPos < 2 || acceptedTracks.nMid < 2 || acceptedTracks.nNeg < 2) // o2-linter: disable=magic-number (at least two tracks in all three subevents) + return; + } + } + registry.fill(HIST("hEventCount"), 5.5); - // output information from mcparticles - registry.fill(HIST("hPxMc"), mcParticle.px()); - registry.fill(HIST("hPyMc"), mcParticle.py()); - registry.fill(HIST("hPzMc"), mcParticle.pz()); - registry.fill(HIST("hweightMc"), mcParticle.weight()); + // Filling Flow Container + for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { + fillFC(corrconfigs.at(l_ind), independent, lRandom); + } + } + PROCESS_SWITCH(FlowCumulantsUpc, process, "process", true); - if (!mcParticle.isPhysicalPrimary()) { - // LOG(info) << "mcParticle.isPhysicalPrimary() = " << mcParticle.isPhysicalPrimary() << std::endl; - continue; - } + //----------------------------------------------------------------------------------------------------------------------- + void processSim(aod::UDMcCollision const& mcCollision, aod::UDMcParticles const& mcParticles) + { + registry.fill(HIST("eventCounterMC"), 0.5); + + registry.fill(HIST("hEventCount"), 1.5); + float cent = 100; + float vtxz = mcCollision.posZ(); + registry.fill(HIST("hVtxZMC"), vtxz); + registry.fill(HIST("hMultMC"), mcParticles.size()); + registry.fill(HIST("hCentMC"), cent); + + auto massPion = o2::constants::physics::MassPionCharged; + registry.fill(HIST("numberOfTracksMC"), mcParticles.size()); + // LOGF(info, "New event! mcParticles.size() = %d", mcParticles.size()); + + float lRandomMc = fRndmMc->Rndm(); + fGFWMC->Clear(); + + // // track weights + float weff = 1, wacc = 1; + double nTracksCorrected = 0; + float independent = cent; + if (cfgUseNch) { + independent = static_cast(mcParticles.size()); + } - std::array momentum = {mcParticle.px(), mcParticle.py(), mcParticle.pz()}; - double energy = std::sqrt(momentum[0] * momentum[0] + momentum[1] * momentum[1] + momentum[2] * momentum[2] + massPion * massPion); - ROOT::Math::LorentzVector> protoMC(momentum[0], momentum[1], momentum[2], energy); - constexpr double kEtaCut = 0.8; - constexpr double kPtCut = 0.1; - if (!(std::fabs(protoMC.Eta()) < kEtaCut && protoMC.Pt() > kPtCut)) { - // LOG(info) << "protoMC.Eta() = " << protoMC.Eta() << ", protoMC.Pt() = " << protoMC.Pt() << std::endl; - continue; - } - // auto momentum = std::array{mcParticle.px(), mcParticle.py(), mcParticle.pz()}; - double pt = RecoDecay::pt(momentum); - double phi = RecoDecay::phi(momentum); - double eta = RecoDecay::eta(momentum); - bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range - bool withinPtRef = (cfgCutPtRefMin < pt) && (pt < cfgCutPtRefMax); // within RF pT range - if (cfgOutputNUAWeights) { - if (cfgOutputNUAWeightsRefPt) { - if (withinPtRef) { - fWeightsMc->fill(phi, eta, vtxz, pt, cent, 0); - } - } else { + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + std::array momentum = {mcParticle.px(), mcParticle.py(), mcParticle.pz()}; + double energy = std::sqrt(momentum[0] * momentum[0] + momentum[1] * momentum[1] + momentum[2] * momentum[2] + massPion * massPion); + ROOT::Math::LorentzVector> protoMC(momentum[0], momentum[1], momentum[2], energy); + constexpr double kEtaCut = 0.8; + constexpr double kPtCut = 0.1; + if (!(std::fabs(protoMC.Eta()) < kEtaCut && protoMC.Pt() > kPtCut)) { + continue; + } + // auto momentum = std::array{mcParticle.px(), mcParticle.py(), mcParticle.pz()}; + double pt = RecoDecay::pt(momentum); + double phi = RecoDecay::phi(momentum); + double eta = RecoDecay::eta(momentum); + bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range + bool withinPtRef = (cfgCutPtRefMin < pt) && (pt < cfgCutPtRefMax); // within RF pT range + if (cfgOutputNUAWeights) { + if (cfgOutputNUAWeightsRefPt) { + if (withinPtRef) { fWeightsMc->fill(phi, eta, vtxz, pt, cent, 0); } + } else { + fWeightsMc->fill(phi, eta, vtxz, pt, cent, 0); } - if (!setCurrentParticleWeights(weff, wacc, phi, eta, pt, vtxz)) { - continue; - } - - if (withinPtRef) { - registry.fill(HIST("hPhiMC"), phi); - registry.fill(HIST("hPhiWeightedMC"), phi, wacc); - registry.fill(HIST("hEtaMC"), eta); - registry.fill(HIST("hPtRefMC"), pt); - // registry.fill(HIST("hDCAzMC"), track.dcaZ(), track.pt()); - // registry.fill(HIST("hDCAxyMC"), track.dcaXY(), track.pt()); - nTracksCorrected += weff; - } - if (withinPtRef) { - fGFWMC->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 1); - } - if (withinPtPOI) { - fGFWMC->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 2); - } - if (withinPtPOI && withinPtRef) { - fGFWMC->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 4); - } - // LOG(info) << "successfully filled" << std::endl; } - registry.fill(HIST("hTrackCorrection2dMC"), mcParticles.size(), nTracksCorrected); - // Filling Flow Container - for (uint l_ind = 0; l_ind < corrconfigsmc.size(); l_ind++) { - // LOG(info) << "filling flow container for MC" << std::endl; - fillFCMC(corrconfigsmc.at(l_ind), independent, lRandomMc); + if (!setCurrentParticleWeights(weff, wacc, phi, eta, pt, vtxz)) { + continue; + } + if (withinPtRef) { + registry.fill(HIST("hPhiMC"), phi); + registry.fill(HIST("hPhiWeightedMC"), phi, wacc); + registry.fill(HIST("hEtaMC"), eta); + registry.fill(HIST("hPtRefMC"), pt); + // registry.fill(HIST("hDCAzMC"), track.dcaZ(), track.pt()); + // registry.fill(HIST("hDCAxyMC"), track.dcaXY(), track.pt()); + nTracksCorrected += weff; + } + if (withinPtRef) { + fGFWMC->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 1); + } + if (withinPtPOI) { + fGFWMC->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 2); + } + if (withinPtPOI && withinPtRef) { + fGFWMC->Fill(eta, fPtAxis->FindBin(pt) - 1, phi, wacc * weff, 4); } } + registry.fill(HIST("hTrackCorrection2dMC"), mcParticles.size(), nTracksCorrected); + + // Filling Flow Container + for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { + fillFCMC(corrconfigs.at(l_ind), independent, lRandomMc); + } } - PROCESS_SWITCH(FlowCumulantsUpc, processSim, "processSim", true); + PROCESS_SWITCH(FlowCumulantsUpc, processSim, "processSim", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + }; } diff --git a/PWGUD/Tasks/polarisationRho.cxx b/PWGUD/Tasks/polarisationRho.cxx index c10e86baad6..386bd5de510 100644 --- a/PWGUD/Tasks/polarisationRho.cxx +++ b/PWGUD/Tasks/polarisationRho.cxx @@ -8,13 +8,26 @@ // 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 #include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include -#include "TLorentzVector.h" +#include + +#include + +#include +#include using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/sgD0Analyzer.cxx b/PWGUD/Tasks/sgD0Analyzer.cxx index 7e4c2019434..149683c1c40 100644 --- a/PWGUD/Tasks/sgD0Analyzer.cxx +++ b/PWGUD/Tasks/sgD0Analyzer.cxx @@ -17,15 +17,21 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "TLorentzVector.h" -#include +#include -#include +#include +#include using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/sgExcUniverse.cxx b/PWGUD/Tasks/sgExcUniverse.cxx index 6178d4cb0b0..a02a30b621d 100644 --- a/PWGUD/Tasks/sgExcUniverse.cxx +++ b/PWGUD/Tasks/sgExcUniverse.cxx @@ -15,15 +15,21 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "TFile.h" -#include "TTree.h" -#include "TVector3.h" +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/sgExclOmega.cxx b/PWGUD/Tasks/sgExclOmega.cxx index 858b0499caa..cb8c298ce0f 100644 --- a/PWGUD/Tasks/sgExclOmega.cxx +++ b/PWGUD/Tasks/sgExclOmega.cxx @@ -17,20 +17,28 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "TLorentzVector.h" -#include +#include + +#include +#include -#include using namespace std; using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; + struct SGExclOmega { SGSelector sgSelector; Service pdg; diff --git a/PWGUD/Tasks/sgExclusiveJpsiMidrapidity.cxx b/PWGUD/Tasks/sgExclusiveJpsiMidrapidity.cxx index b0b2058a27d..73d2d5884a5 100644 --- a/PWGUD/Tasks/sgExclusiveJpsiMidrapidity.cxx +++ b/PWGUD/Tasks/sgExclusiveJpsiMidrapidity.cxx @@ -17,12 +17,21 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TMath.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include #include #include diff --git a/PWGUD/Tasks/sgExclusivePhi.cxx b/PWGUD/Tasks/sgExclusivePhi.cxx index c4bed3d1456..a68d9ba8cdb 100644 --- a/PWGUD/Tasks/sgExclusivePhi.cxx +++ b/PWGUD/Tasks/sgExclusivePhi.cxx @@ -12,17 +12,29 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include +#include + +#include -#include +#include +#include +#include #include -using std::array; using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/sgExclusivePhiITSselections.cxx b/PWGUD/Tasks/sgExclusivePhiITSselections.cxx index 1e3fe149e59..d3d8a580b4b 100644 --- a/PWGUD/Tasks/sgExclusivePhiITSselections.cxx +++ b/PWGUD/Tasks/sgExclusivePhiITSselections.cxx @@ -12,17 +12,26 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include #include -#include +#include +#include +#include #include -using std::array; using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/sgFITAnalyzer.cxx b/PWGUD/Tasks/sgFITAnalyzer.cxx index 60464ed6cf4..f3369b3a7cb 100644 --- a/PWGUD/Tasks/sgFITAnalyzer.cxx +++ b/PWGUD/Tasks/sgFITAnalyzer.cxx @@ -15,18 +15,29 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/DataModel/PIDResponseTOF.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include -#include "TFile.h" -#include "TTree.h" -#include "TVector3.h" +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/sgFourPiAnalyzer.cxx b/PWGUD/Tasks/sgFourPiAnalyzer.cxx index 13979d87c38..ef6f1b17a0b 100644 --- a/PWGUD/Tasks/sgFourPiAnalyzer.cxx +++ b/PWGUD/Tasks/sgFourPiAnalyzer.cxx @@ -17,25 +17,27 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" +#include +#include -#include "TLorentzVector.h" -#include +#include -#include using namespace std; using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; + struct SGFourPiAnalyzer { SGSelector sgSelector; Service pdg; diff --git a/PWGUD/Tasks/sgInclJpsi.cxx b/PWGUD/Tasks/sgInclJpsi.cxx index eba36e3845c..4ead557224a 100644 --- a/PWGUD/Tasks/sgInclJpsi.cxx +++ b/PWGUD/Tasks/sgInclJpsi.cxx @@ -17,20 +17,27 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "TLorentzVector.h" -#include +#include + +#include -#include using namespace std; using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; + struct SGInclJpsi { SGSelector sgSelector; Service pdg; diff --git a/PWGUD/Tasks/sgPIDAnalyzer.cxx b/PWGUD/Tasks/sgPIDAnalyzer.cxx index c3038cee058..f68d3b0ddf9 100644 --- a/PWGUD/Tasks/sgPIDAnalyzer.cxx +++ b/PWGUD/Tasks/sgPIDAnalyzer.cxx @@ -13,19 +13,16 @@ // \author Sasha Bylinkin, alexander.bylinkin@gmail.com // \since April 2023 -#include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/SGTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include -#include "TFile.h" -#include "TTree.h" -#include "TVector3.h" -#include -#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/sgPIDSpectra.cxx b/PWGUD/Tasks/sgPIDSpectra.cxx index 2792dee4be2..706c34a1150 100644 --- a/PWGUD/Tasks/sgPIDSpectra.cxx +++ b/PWGUD/Tasks/sgPIDSpectra.cxx @@ -15,15 +15,21 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include -#include "TFile.h" -#include "TTree.h" -#include "TVector3.h" +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/sgPIDSpectraTable.cxx b/PWGUD/Tasks/sgPIDSpectraTable.cxx index bd781969afc..75b81336c3d 100644 --- a/PWGUD/Tasks/sgPIDSpectraTable.cxx +++ b/PWGUD/Tasks/sgPIDSpectraTable.cxx @@ -12,18 +12,21 @@ // \Single Gap Event Analyzer // \author Sasha Bylinkin, alexander.bylinkin@gmail.com // \since April 2023 + #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/SGTables.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include -#include "TFile.h" -#include "TTree.h" -#include "TVector3.h" +#include #include diff --git a/PWGUD/Tasks/sgSixPiAnalyzer.cxx b/PWGUD/Tasks/sgSixPiAnalyzer.cxx index 1a3ed6604e2..ff288249dc2 100644 --- a/PWGUD/Tasks/sgSixPiAnalyzer.cxx +++ b/PWGUD/Tasks/sgSixPiAnalyzer.cxx @@ -17,20 +17,20 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" +#include +#include -#include "TLorentzVector.h" -#include - -#include +#include using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/sgSpectraAnalyzer.cxx b/PWGUD/Tasks/sgSpectraAnalyzer.cxx index 1d73df42642..b17c699970f 100644 --- a/PWGUD/Tasks/sgSpectraAnalyzer.cxx +++ b/PWGUD/Tasks/sgSpectraAnalyzer.cxx @@ -17,20 +17,31 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include -// #include "PWGUD/Core/RLhelper.h" -#include "TLorentzVector.h" -#include +#include +#include + using namespace std; using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; + namespace excl_fs { DECLARE_SOA_COLUMN(GS, gs, int); diff --git a/PWGUD/Tasks/sgTwoPiAnalyzer.cxx b/PWGUD/Tasks/sgTwoPiAnalyzer.cxx index 7a2c8aefc3c..77c6e4f2d94 100644 --- a/PWGUD/Tasks/sgTwoPiAnalyzer.cxx +++ b/PWGUD/Tasks/sgTwoPiAnalyzer.cxx @@ -17,20 +17,21 @@ #include "PWGUD/Core/SGTrackSelector.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "MathUtils/Utils.h" +#include +#include -#include "TLorentzVector.h" -#include - -#include +#include +#include using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx index 1800150c1a3..a67bd2bd325 100644 --- a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx +++ b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx @@ -16,24 +16,35 @@ #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/SGTrackSelector.h" -#include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Vertex.h" - -#include "Math/GenVector/Boost.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "TPDGCode.h" -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include #include +#include #include #include #include @@ -175,9 +186,6 @@ struct SginclusivePhiKstarSD { 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("nPVContributors_data", "Multiplicity_dist_before track cut gap A", kTH1F, {{110, 0, 110}}); - registry.add("nPVContributors_data_1", "Multiplicity_dist_before track cut gap C", kTH1F, {{110, 0, 110}}); - registry.add("hRotation", "hRotation", kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); if (phi) { @@ -333,6 +341,9 @@ struct SginclusivePhiKstarSD { registry.add("MC/genM_1", "Generated events; Mass (GeV/#it{c}^2)", {HistType::kTH1F, {{220, 0.98, 1.2}}}); registry.add("MC/accMPtRap_phi_G", "Generated Phi; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{220, 0.98, 1.20}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); + registry.add("MC/accMPtRap_phi_G1", "Generated Phi1; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{220, 0.98, 1.20}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); + registry.add("MC/accMPtRap_phi_G11", "Generated Phi11; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{220, 0.98, 1.20}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); + registry.add("MC/accMPtRap_phi_G2", "Generated Phi2; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{220, 0.98, 1.20}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); registry.add("MC/accEtaPt", "Generated events in acceptance; eta (1); #it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{60, -1.5, 1.5}, {250, 0.0, 5.0}}}); registry.add("MC/accRap", "Generated events in acceptance; Rapidity (1)", {HistType::kTH1F, {{60, -1.5, 1.5}}}); @@ -344,6 +355,9 @@ struct SginclusivePhiKstarSD { registry.add("MC/pDiff", "McTruth - reconstructed track momentum; McTruth - reconstructed track momentum; Entries", {HistType::kTH2F, {{240, -6., 6.}, {3, -1.5, 1.5}}}); // K*0 registry.add("MC/accMPtRap_kstar_G", "Generated K*0; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{400, 0., 2.0}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); + registry.add("MC/accMPtRap_kstar_G1", "Generated K*0 from kp; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{400, 0., 2.0}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); + registry.add("MC/accMPtRap_kstar_G11", "Generated K*0 from kp1; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{400, 0., 2.0}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); + registry.add("MC/accMPtRap_kstar_G2", "Generated K*0 from kp2; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{400, 0., 2.0}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); registry.add("MC/genEtaPt_k", "Generated events; eta (1); #it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{60, -1.5, 1.5}, {250, 0.0, 5.0}}}); registry.add("MC/genRap_k", "Generated events; Rapidity (1)", {HistType::kTH1F, {{60, -1.5, 1.5}}}); registry.add("MC/genMPt_k", "Generated events; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{400, 0., 2.0}, {200, 0.0, 10.0}}}); @@ -365,6 +379,7 @@ struct SginclusivePhiKstarSD { "All Events", "has_udMcCollision", Form("generatorsID = %d", generatedId.value), + Form("upcFlag = %d%s", upcflag.value, check(upcflag.value != -1)), Form("GapsideMC = %d", gapsideMC.value), Form("|Vz| < %.1f", vzCut.value), Form("Occupancy < %.0f%s", confgOccCut.value, check(useOccCut.value)), @@ -378,7 +393,6 @@ struct SginclusivePhiKstarSD { std::string("kIsGoodZvtxFT0vsPV") + check(useZvtxftovpv.value), std::string("kIsVertexITSTPC") + check(useVtxItsTpc.value), Form("RCTFlag = %d%s", cutRCTflag.value, check(cutRCTflag.value > 0)), - Form("upcFlag = %d%s", upcflag.value, check(upcflag.value != -1)), Form("%d < numContrib < %d%s", mintrack.value, maxtrack.value, check(usenumContrib.value))}; for (size_t i = 0; i < eveCutLabelsMC.size(); ++i) { @@ -386,7 +400,6 @@ struct SginclusivePhiKstarSD { } registry.add("Reco/Stat", "Count reconstruted events; ; Entries", {HistType::kTH1F, {{5, -0.5, 4.5}}}); - registry.add("Reco/nPVContributors", "Number of PV contributors per collision; Number of PV contributors; Entries", {HistType::kTH1F, {{51, -0.5, 50.5}}}); registry.add("Reco/selRap", "Selected events in acceptance; Rapidity (1)", {HistType::kTH1F, {{60, -1.5, 1.5}}}); registry.add("Reco/selMPt", "Reconstructed events in acceptance; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{220, 0.98, 1.20}, {200, 0.0, 10.0}}}); registry.add("Reco/selMPtRap", "Reconstructed events in acceptance; Mass (GeV/#it{c}^2); #it{p}_{T} (GeV/#it{c})", {HistType::kTH3F, {{220, 0.98, 1.20}, {200, 0.0, 10.0}, {60, -1.5, 1.5}}}); @@ -474,6 +487,7 @@ struct SginclusivePhiKstarSD { // Rapidity, pseudorapisdity rQA.add("hEta_all_after_mc", "Pseudorapidity of all tracks after track selection; #eta; Counts", kTH1F, {{400, -1.0, 1.0}}); + rQA.add("hphi_all_after_mc", "phi of all tracks after track selection; #eta; Counts", kTH1F, {{400, -4.0, 4.0}}); rQA.add("hEta_ka_mc", "Pseudorapidity of selected Kaons; #eta; Counts", kTH1F, {{400, -1.0, 1.0}}); rQA.add("hRap_ka_mc", "Rapidity of selected Kaons; y; Counts", kTH1F, {{400, -1.0, 1.0}}); @@ -595,67 +609,67 @@ struct SginclusivePhiKstarSD { if (fillHist) registry.fill(HIST("hEventCutFlow"), 1); - if (std::abs(collision.posZ()) > vzCut) + if (upcflag != -1 && collision.flags() != upcflag) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 2); - if (useOccCut && (std::abs(collision.occupancyInTime()) > confgOccCut)) + if (std::abs(collision.posZ()) > vzCut) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 3); - if (useHadronicRateCut && (std::abs(collision.hadronicRate()) > confgHadronicRateMax || std::abs(collision.hadronicRate()) < confgHadronicRateMin)) + if (useOccCut && (std::abs(collision.occupancyInTime()) > confgOccCut)) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 4); - if (useTrs && collision.trs() != 1) + if (useHadronicRateCut && (std::abs(collision.hadronicRate()) > confgHadronicRateMax || std::abs(collision.hadronicRate()) < confgHadronicRateMin)) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 5); - if (useTrofs && collision.trofs() != 1) + if (useTrs && collision.trs() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 6); - if (useHmpr && collision.hmpr() != 1) + if (useTrofs && collision.trofs() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 7); - if (useTfb && collision.tfb() != 1) + if (useHmpr && collision.hmpr() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 8); - if (useItsrofb && collision.itsROFb() != 1) + if (useTfb && collision.tfb() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 9); - if (useSbp && collision.sbp() != 1) + if (useItsrofb && collision.itsROFb() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 10); - if (useZvtxftovpv && collision.zVtxFT0vPV() != 1) + if (useSbp && collision.sbp() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 11); - if (useVtxItsTpc && collision.vtxITSTPC() != 1) + if (useZvtxftovpv && collision.zVtxFT0vPV() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 12); - if (!isGoodRCTflag(collision)) + if (useVtxItsTpc && collision.vtxITSTPC() != 1) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 13); - if (upcflag != -1 && collision.flags() != upcflag) + if (!isGoodRCTflag(collision)) return {false, gapSide}; if (fillHist) registry.fill(HIST("hEventCutFlow"), 14); @@ -1195,7 +1209,7 @@ struct SginclusivePhiKstarSD { PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; PresliceUnsorted trackPerMcParticle = aod::udmctracklabel::udMcParticleId; - void processMCTruth(aod::UDMcCollisions const& mccollisions, CCs const& collisions, aod::UDMcParticles const& McParts, TCs const& tracks) + void processMCTruth(aod::UDMcCollisions const& mccollisions, CCs const& collisions, aod::UDMcParticles const& McParts, TCs const& /*tracks*/) { // number of McCollisions in DF ROOT::Math::PxPyPzMVector v0; @@ -1215,6 +1229,75 @@ struct SginclusivePhiKstarSD { // get McParticles which belong to mccollision auto partSlice = McParts.sliceBy(partPerMcCollision, mccollision.globalIndex()); registry.get(HIST("MC/nParts"))->Fill(partSlice.size(), 1.); + for (const auto& trk1 : partSlice) { + if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { + vkstar.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassK0Star892); + auto kDaughters = trk1.daughters_as(); + const size_t kExpectedNumberOfDaughters = 2; + if (kDaughters.size() != kExpectedNumberOfDaughters) { + continue; + } + auto daughtp = false; + auto daughtm = false; + for (const auto& kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { + continue; + } + if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { + daughtp = true; + v0.SetCoordinates(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassKaonCharged); + } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kPiPlus) { + daughtm = true; + v1.SetCoordinates(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassPionCharged); + } + } + if (daughtp && daughtm) { + v01 = v0 + v1; + if (std::abs(v01.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_kstar_G"))->Fill(v01.M(), v01.Pt(), v01.Rapidity(), 1.); + } + if (std::abs(vkstar.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_kstar_G2"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + } + } + } + // phi + if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + if (trk1.has_mothers()) { + continue; + } + vphi.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassPhi); + auto kDaughters = trk1.daughters_as(); + const size_t kExpectedNumberOfDaughters1 = 2; + if (kDaughters.size() != kExpectedNumberOfDaughters1) { + continue; + } + auto daughtp1 = false; + auto daughtm1 = false; + for (const auto& kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { + continue; + } + if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { + daughtp1 = true; + v0.SetCoordinates(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassKaonCharged); + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { + daughtm1 = true; + v1.SetCoordinates(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassKaonCharged); + } + } + if (daughtp1 && daughtm1) { + v01 = v0 + v1; + if (std::abs(v01.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_phi_G"))->Fill(v01.M(), v01.Pt(), v01.Rapidity(), 1.); + } + if (std::abs(vphi.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_phi_G2"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + } + } + } + } + /* for (const auto& [tr1, tr2] : combinations(partSlice, partSlice)) { if ((tr1.pdgCode() == kKPlus && tr2.pdgCode() == kPiMinus) || (tr1.pdgCode() == kKMinus && tr2.pdgCode() == kPiPlus) || (tr1.pdgCode() == kPiPlus && tr2.pdgCode() == kKMinus) || (tr1.pdgCode() == kPiMinus && tr2.pdgCode() == kKPlus)) { if (std::abs(tr1.pdgCode()) == kKPlus) { @@ -1238,7 +1321,7 @@ struct SginclusivePhiKstarSD { for (const auto& mother : tr1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { vkstar.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); - registry.get(HIST("MC/accMPtRap_kstar_G"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + // registry.get(HIST("MC/accMPtRap_kstar_G"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); flag = true; } } @@ -1279,7 +1362,7 @@ struct SginclusivePhiKstarSD { for (const auto& mother : tr1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kPhi) { vphi.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); - registry.get(HIST("MC/accMPtRap_phi_G"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + // registry.get(HIST("MC/accMPtRap_phi_G"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); flag = true; } } @@ -1316,13 +1399,16 @@ struct SginclusivePhiKstarSD { registry.get(HIST("MC/pDiff"))->Fill(-5.9, -1, 1.); } } + */ } } PROCESS_SWITCH(SginclusivePhiKstarSD, processMCTruth, "Process MC truth", true); // ............................................................................................................... - void processReco(CC const& collision, TCs const& tracks, aod::UDMcCollisions const& /*mccollisions*/, aod::UDMcParticles const& /*McParts*/) + void processReco(CC const& collision, TCs const& tracks, aod::UDMcCollisions const& /*mccollisions*/, aod::UDMcParticles const& McParts) { registry.fill(HIST("Reco/hEventCutFlowMC"), 0); + ROOT::Math::PxPyPzMVector vkstar; + ROOT::Math::PxPyPzMVector vphi; if (!collision.has_udMcCollision()) return; @@ -1336,66 +1422,129 @@ struct SginclusivePhiKstarSD { return; registry.fill(HIST("Reco/hEventCutFlowMC"), 2); + if (upcflag != -1 && collision.flags() != upcflag) + return; + registry.fill(HIST("Reco/hEventCutFlowMC"), 3); + float fitCut[5] = {fv0Cut, ft0aCut, ft0cCut, fddaCut, fddcCut}; std::vector parameters = {pvCut, dcazCut, dcaxyCut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, ptCut}; int truegapSide = sgSelector.trueGap(collision, fitCut[0], fitCut[1], fitCut[2], zdcCut); registry.get(HIST("Reco/Stat"))->Fill(4.0, 1.); registry.get(HIST("Reco/Stat"))->Fill(truegapSide, 1.); - if (truegapSide != gapsideMC) - return; - registry.fill(HIST("Reco/hEventCutFlowMC"), 3); - // Partition pvContributors = aod::udtrack::isPVContributor == true; - // pvContributors.bindTable(tracks); - if (std::abs(collision.posZ()) > vzCut) + auto partSlice = McParts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + for (const auto& trk1 : partSlice) { + if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { + vkstar.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassK0Star892); + auto kDaughters = trk1.daughters_as(); + const size_t kExpectedNumberOfDaughters = 2; + if (kDaughters.size() != kExpectedNumberOfDaughters) { + continue; + } + auto daughtp = false; + auto daughtm = false; + for (const auto& kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { + continue; + } + if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { + daughtp = true; + } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kPiPlus) { + daughtm = true; + } + } + if (daughtp && daughtm) { + if (std::abs(vkstar.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_kstar_G1"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + if (truegapSide == gapsideMC) { + registry.get(HIST("MC/accMPtRap_kstar_G11"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + } + } + } + } + // phi + if (std::abs(trk1.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + if (trk1.has_mothers()) { + continue; + } + vphi.SetCoordinates(trk1.px(), trk1.py(), trk1.pz(), o2::constants::physics::MassPhi); + auto kDaughters = trk1.daughters_as(); + const size_t kExpectedNumberOfDaughters1 = 2; + if (kDaughters.size() != kExpectedNumberOfDaughters1) { + continue; + } + auto daughtp1 = false; + auto daughtm1 = false; + for (const auto& kCurrentDaughter : kDaughters) { + if (!kCurrentDaughter.isPhysicalPrimary()) { + continue; + } + if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { + daughtp1 = true; + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { + daughtm1 = true; + } + } + if (daughtp1 && daughtm1) { + if (std::abs(vphi.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_phi_G1"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + if (truegapSide == gapsideMC) { + registry.get(HIST("MC/accMPtRap_phi_G11"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + } + } + } + } + } + + if (truegapSide != gapsideMC) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 4); - if (useOccCut && (std::abs(collision.occupancyInTime()) > confgOccCut)) + if (std::abs(collision.posZ()) > vzCut) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 5); - if (useHadronicRateCut && (std::abs(collision.hadronicRate()) > confgHadronicRateMax || std::abs(collision.hadronicRate()) < confgHadronicRateMin)) + if (useOccCut && (std::abs(collision.occupancyInTime()) > confgOccCut)) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 6); - if (useTrs && collision.trs() != 1) + if (useHadronicRateCut && (std::abs(collision.hadronicRate()) > confgHadronicRateMax || std::abs(collision.hadronicRate()) < confgHadronicRateMin)) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 7); - if (useTrofs && collision.trofs() != 1) + if (useTrs && collision.trs() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 8); - if (useHmpr && collision.hmpr() != 1) + if (useTrofs && collision.trofs() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 9); - if (useTfb && collision.tfb() != 1) + if (useHmpr && collision.hmpr() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 10); - if (useItsrofb && collision.itsROFb() != 1) + if (useTfb && collision.tfb() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 11); - if (useSbp && collision.sbp() != 1) + if (useItsrofb && collision.itsROFb() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 12); - if (useZvtxftovpv && collision.zVtxFT0vPV() != 1) + if (useSbp && collision.sbp() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 13); - if (useVtxItsTpc && collision.vtxITSTPC() != 1) + if (useZvtxftovpv && collision.zVtxFT0vPV() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 14); - if (!isGoodRCTflag(collision)) + if (useVtxItsTpc && collision.vtxITSTPC() != 1) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 15); - if (upcflag != -1 && collision.flags() != upcflag) + if (!isGoodRCTflag(collision)) return; registry.fill(HIST("Reco/hEventCutFlowMC"), 16); @@ -1403,12 +1552,13 @@ struct SginclusivePhiKstarSD { return; registry.fill(HIST("Reco/hEventCutFlowMC"), 17); - if (qaMC) + if (qaMC) { rQA.fill(HIST("hOcc_after_mc"), collision.occupancyInTime()); + rQA.fill(HIST("hVertexX_mc"), collision.posX()); + rQA.fill(HIST("hVertexY_mc"), collision.posY()); + rQA.fill(HIST("hVertexZ_mc"), collision.posZ()); + } - // registry.get(HIST("Reco/nPVContributors"))->Fill(pvContributors.size(), 1.); - ROOT::Math::PxPyPzMVector vphi; - ROOT::Math::PxPyPzMVector vkstar; ROOT::Math::PxPyPzMVector v0; ROOT::Math::PxPyPzMVector vr0; ROOT::Math::PxPyPzMVector vr1; @@ -1465,6 +1615,7 @@ struct SginclusivePhiKstarSD { rQA.fill(HIST("hDcaxy_all_after_mc"), tr1.dcaXY()); rQA.fill(HIST("hDcaz_all_after_mc"), tr1.dcaZ()); rQA.fill(HIST("hEta_all_after_mc"), v0.Eta()); + rQA.fill(HIST("hphi_all_after_mc"), v0.Phi()); rQA.fill(HIST("tpc_dedx_mc"), v0.P(), tr1.tpcSignal()); rQA.fill(HIST("tof_beta_mc"), v0.P(), tr1.beta()); @@ -1519,8 +1670,8 @@ struct SginclusivePhiKstarSD { continue; vr1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); auto mcPart2 = tr2.udMcParticle(); - if (std::abs(mcPart2.globalIndex() - mcPart1.globalIndex()) != 1) - continue; + // if (std::abs(mcPart2.globalIndex() - mcPart1.globalIndex()) != 1) + // continue; if (std::abs(mcPart1.pdgCode()) != kKPlus || std::abs(mcPart2.pdgCode()) != kKPlus) continue; if (mcPart1.pdgCode() == mcPart2.pdgCode()) @@ -1529,17 +1680,28 @@ struct SginclusivePhiKstarSD { continue; bool flag = false; bool flag1 = false; + int gIndex1 = 0; + int gIndex2 = 0; if (mcPart1.has_mothers() && mcPart2.has_mothers()) { for (const auto& mother : mcPart1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + if (mother.has_mothers()) { + continue; + } vphi.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); - registry.get(HIST("MC/accMPtRap_phi_T"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + if (std::abs(vphi.Rapidity()) > 0.5) + continue; flag = true; + gIndex1 = mother.globalIndex(); } } for (const auto& mother1 : mcPart1.mothers_as()) { if (std::abs(mother1.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + vphi.SetCoordinates(mother1.px(), mother1.py(), mother1.pz(), o2::constants::physics::MassPhi); + if (std::abs(vphi.Rapidity()) > 0.5) + continue; flag1 = true; + gIndex2 = mother1.globalIndex(); } } } @@ -1547,15 +1709,21 @@ struct SginclusivePhiKstarSD { vr1g.SetCoordinates(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); vr01g = vr0g + vr1g; vr01 = vr0 + vr1; - - if (flag && flag1) { - registry.get(HIST("Reco/selMPt"))->Fill(vr01.M(), vr01.Pt(), 1.); + if (flag && flag1 && (gIndex1 == gIndex2)) { + if (std::abs(vr01g.Rapidity()) < 0.5) { + registry.get(HIST("Reco/selMPt"))->Fill(vr01g.M(), vr01g.Pt(), 1.); + } + if (std::abs(vr01.Rapidity()) < 0.5) { + registry.get(HIST("Reco/selMPtRap"))->Fill(vr01.M(), vr01.Pt(), vr01.Rapidity(), 1.); + } + if (std::abs(vphi.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_phi_T"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); + } } registry.get(HIST("Reco/selRap"))->Fill(vr01.Rapidity(), 1.); - registry.get(HIST("Reco/selMPtRap"))->Fill(vr01.M(), vr01.Pt(), vr01.Rapidity(), 1.); registry.get(HIST("Reco/selPt"))->Fill(vr01.Pt(), 1.); registry.get(HIST("Reco/selM"))->Fill(vr01.M(), 1.); - registry.get(HIST("Reco/selMPtRap_gen"))->Fill(vr01g.M(), vr01g.Pt(), vr01g.Rapidity(), 1.); + // registry.get(HIST("Reco/selMPtRap_gen"))->Fill(vr01g.M(), vr01g.Pt(), vr01g.Rapidity(), 1.); } } } @@ -1573,8 +1741,8 @@ struct SginclusivePhiKstarSD { continue; if (!mcPart1.isPhysicalPrimary() || !mcPart2.isPhysicalPrimary()) continue; - if (std::abs(mcPart2.globalIndex() - mcPart1.globalIndex()) != 1) - continue; + // if (std::abs(mcPart2.globalIndex() - mcPart1.globalIndex()) != 1) + // continue; if (tr1.sign() * tr2.sign() > 0) continue; @@ -1591,26 +1759,43 @@ struct SginclusivePhiKstarSD { if (trackselector(tr1, parameters) && trackselector(tr2, parameters)) { bool flag = false; bool flag1 = false; + int gIndex1 = 0; + int gIndex2 = 0; if (mcPart1.has_mothers() && mcPart2.has_mothers()) { for (const auto& mother : mcPart1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { vkstar.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); - registry.get(HIST("MC/accMPtRap_kstar_T"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + // registry.get(HIST("MC/accMPtRap_kstar_T"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + if (std::abs(vkstar.Rapidity()) > 0.5) + continue; flag = true; + gIndex1 = mother.globalIndex(); } } for (const auto& mother1 : mcPart2.mothers_as()) { if (std::abs(mother1.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { + vkstar.SetCoordinates(mother1.px(), mother1.py(), mother1.pz(), o2::constants::physics::MassK0Star892); + if (std::abs(vkstar.Rapidity()) > 0.5) + continue; flag1 = true; + gIndex2 = mother1.globalIndex(); } } } - if (flag && flag1) { - registry.get(HIST("Reco/selMPt_k"))->Fill(vr01.M(), vr01.Pt(), 1.); + if (flag && flag1 && (gIndex1 == gIndex2)) { + if (std::abs(vr01g.Rapidity()) < 0.5) { + registry.get(HIST("Reco/selMPt_k"))->Fill(vr01g.M(), vr01g.Pt(), 1.); + } + if (std::abs(vr01.Rapidity()) < 0.5) { + registry.get(HIST("Reco/selMPtRap_k"))->Fill(vr01.M(), vr01.Pt(), vr01.Rapidity(), 1.); + } + if (std::abs(vkstar.Rapidity()) < 0.5) { + registry.get(HIST("MC/accMPtRap_kstar_T"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); + } } registry.get(HIST("Reco/selM_k_K"))->Fill(vr01.M(), 1.); registry.get(HIST("Reco/selRap_k"))->Fill(vr01.Rapidity(), 1.); - registry.get(HIST("Reco/selMPtRap_k"))->Fill(vr01.M(), vr01.Pt(), vr01.Rapidity(), 1.); + registry.get(HIST("Reco/selPt_k"))->Fill(vr01.Pt(), 1.); registry.get(HIST("Reco/selMPtRap_k_gen"))->Fill(vr01g.M(), vr01g.Pt(), vr01g.Rapidity(), 1.); } diff --git a/PWGUD/Tasks/testMcStdTabsRl.cxx b/PWGUD/Tasks/testMcStdTabsRl.cxx index 9748b28784f..7651b5e5c2a 100644 --- a/PWGUD/Tasks/testMcStdTabsRl.cxx +++ b/PWGUD/Tasks/testMcStdTabsRl.cxx @@ -16,24 +16,25 @@ /// \since 12.02.2025 // -// C++ headers -#include -#include -#include -#include - -// O2 headers -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -// O2Physics headers #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" -// ROOT headers -#include "Math/Vector4D.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/upcAnalysis.cxx b/PWGUD/Tasks/upcAnalysis.cxx index 74a007314e0..f6dc8ba1323 100644 --- a/PWGUD/Tasks/upcAnalysis.cxx +++ b/PWGUD/Tasks/upcAnalysis.cxx @@ -9,16 +9,22 @@ // 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 "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include + +#include +#include +#include -#include -#include -#include "TLorentzVector.h" +#include +#include using namespace o2; using namespace o2::aod::evsel; diff --git a/PWGUD/Tasks/upcCandidateAnalyzer.cxx b/PWGUD/Tasks/upcCandidateAnalyzer.cxx index 568ecacb872..dcf23797803 100644 --- a/PWGUD/Tasks/upcCandidateAnalyzer.cxx +++ b/PWGUD/Tasks/upcCandidateAnalyzer.cxx @@ -9,12 +9,23 @@ // 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 "PWGUD/DataModel/UDTables.h" -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/upcEventITSROFcounter.cxx b/PWGUD/Tasks/upcEventITSROFcounter.cxx index 51241be5d69..c33c17ecfe4 100644 --- a/PWGUD/Tasks/upcEventITSROFcounter.cxx +++ b/PWGUD/Tasks/upcEventITSROFcounter.cxx @@ -15,23 +15,32 @@ /// \author Roman Lavicka , Austrian Academy of Sciences & SMI /// \since 09.08.2024 -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ITSMFTBase/DPLAlpideParam.h" -#include "CCDB/BasicCCDBManager.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/DataModel/UDTables.h" -#include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/SGSelector.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/upcForward.cxx b/PWGUD/Tasks/upcForward.cxx index bebcf0b2be2..49325f3e0db 100644 --- a/PWGUD/Tasks/upcForward.cxx +++ b/PWGUD/Tasks/upcForward.cxx @@ -14,16 +14,26 @@ o2-analysis-timestamp| o2-analysis-upc-forward | o2-analysis-event-selection -- for now AO2D.root I am using is alien:///alice/data/2015/LHC15o/000246392/pass5_lowIR/PWGZZ/Run3_Conversion/148_20210304-0829_child_1/AOD/001/AO2D.root */ -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include -#include -#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include -#include "TLorentzVector.h" -#include "Common/CCDB/TriggerAliases.h" + +#include + +#include using namespace std; using namespace o2; diff --git a/PWGUD/Tasks/upcJpsiCorr.cxx b/PWGUD/Tasks/upcJpsiCorr.cxx index ad0145dae34..1732869e0d6 100644 --- a/PWGUD/Tasks/upcJpsiCorr.cxx +++ b/PWGUD/Tasks/upcJpsiCorr.cxx @@ -15,25 +15,33 @@ /// \author Sara Haidlova, sara.haidlova@cern.ch /// \since March 2024 -#include -#include - -// O2 headers -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -// O2Physics headers #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/UPCJpsiCentralBarrelCorrHelper.h" #include "PWGUD/DataModel/UDTables.h" #include "Common/Core/RecoDecay.h" -// ROOT headers -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/upcMft.cxx b/PWGUD/Tasks/upcMft.cxx index a3ae2b03287..6349589e6b4 100644 --- a/PWGUD/Tasks/upcMft.cxx +++ b/PWGUD/Tasks/upcMft.cxx @@ -9,31 +9,35 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// c++ headers -#include - -// root headers -#include -#include -#include "TMath.h" -#include "TLorentzVector.h" - -// framework headers -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - -// for track propagation -#include "ReconstructionDataFormats/TrackFwd.h" -#include "Math/MatrixFunctions.h" -#include "Math/SMatrix.h" -#include "MathUtils/Utils.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/Propagator.h" -#include "TGeoGlobalMagField.h" -#include "Field/MagneticField.h" -#include "DataFormatsMFT/TrackMFT.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include // define namespaces using namespace o2; diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index fd1b467951b..0ae2035f93a 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -18,25 +18,25 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/CCDB/EventSelectionParams.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 "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/StepTHn.h" -#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include using namespace o2; @@ -47,6 +47,19 @@ namespace o2::aod { namespace tree { +DECLARE_SOA_COLUMN(GapSide, gapSide, float); +DECLARE_SOA_COLUMN(GapSideTimeZN, gapSideTimeZN, float); +DECLARE_SOA_COLUMN(Sbp, sbp, int); +DECLARE_SOA_COLUMN(ITSROFb, itsROFb, int); +DECLARE_SOA_COLUMN(VtxITSTPCCut, vtxITSTPCCut, int); +DECLARE_SOA_COLUMN(ZVtxFT0vsPvCut, zVtxFT0vsPvCut, int); +DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); +DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +DECLARE_SOA_COLUMN(EnergyZNA, energyZNA, float); +DECLARE_SOA_COLUMN(EnergyZNC, energyZNC, float); +DECLARE_SOA_COLUMN(AmplitudeFV0A, amplitudeFV0A, float); +DECLARE_SOA_COLUMN(Occupancy, occupancy, float); +DECLARE_SOA_COLUMN(UPCMode, upcMode, float); DECLARE_SOA_COLUMN(PtSideA, ptSideA, std::vector); DECLARE_SOA_COLUMN(RapSideA, rapSideA, std::vector); DECLARE_SOA_COLUMN(PhiSideA, phiSideA, std::vector); @@ -71,6 +84,19 @@ DECLARE_SOA_COLUMN(NchSideC, nchSideC, int); DECLARE_SOA_COLUMN(MultiplicitySideC, multiplicitySideC, int); } // namespace tree DECLARE_SOA_TABLE(TREE, "AOD", "Tree", + tree::GapSide, + tree::GapSideTimeZN, + tree::Sbp, + tree::ITSROFb, + tree::VtxITSTPCCut, + tree::ZVtxFT0vsPvCut, + tree::TimeZNA, + tree::TimeZNC, + tree::EnergyZNA, + tree::EnergyZNC, + tree::AmplitudeFV0A, + tree::Occupancy, + tree::UPCMode, tree::PtSideA, tree::RapSideA, tree::PhiSideA, @@ -117,17 +143,37 @@ struct UpcPhotonuclearAnalysisJMG { Configurable nEventsMixed{"nEventsMixed", 3, {"Events to be Mixed"}}; Configurable factorEventsMixed{"factorEventsMixed", 100, {"factorEventsMixed to events mixed"}}; Configurable myZVtxCut{"myZVtxCut", 10., {"My collision cut"}}; - Configurable myTimeZNACut{"myTimeZNACut", 2., {"My collision cut"}}; - Configurable myTimeZNCCut{"myTimeZNCCut", 2., {"My collision cut"}}; + Configurable useSBP{"useSBP", false, {"My collision cut"}}; + Configurable sbpCut{"sbpCut", 1, {"My collision cut"}}; + Configurable useITSROFb{"useITSROFb", false, {"My collision cut"}}; + Configurable itsROFbCut{"itsROFbCut", 1, {"My collision cut"}}; + Configurable useVtxITSTPC{"useVtxITSTPC", false, {"My collision cut"}}; + Configurable vtxITSTPCCut{"vtxITSTPCCut", 1, {"My collision cut"}}; + Configurable useZVtxFT0vsPv{"useZVtxFT0vsPv", false, {"My collision cut"}}; + Configurable zVtxFT0vsPvCut{"zVtxFT0vsPvCut", 1, {"My collision cut"}}; + Configurable useEnergyZN{"useEnergyZN", false, {"My collision cut"}}; + Configurable useGapSideVariable{"useGapSideVariable", false, {"My collision cut"}}; + Configurable useUPCMode{"useUPCMode", false, {"My collision cut"}}; + Configurable upcModeCut{"upcModeCut", 1, {"My collision cut"}}; + Configurable useOccupancy{"useOccupancy", false, {"My collision cut"}}; + Configurable cutOccupancy{"cutOccupancy", 1000, {"My collision cut"}}; // Declare configurables on side A gap - Configurable cutGapAMyEnergyZNA{"cutGapAMyEnergyZNA", 0., {"My collision cut. A Gap"}}; - // Configurable cutAGapMyAmplitudeFT0AMax{"cutAGapMyAmplitudeFT0AMax", 200., {"My collision cut. A Gap"}}; - Configurable cutGapAMyEnergyZNC{"cutGapAMyEnergyZNC", 1., {"My collision cut. A Gap"}}; + Configurable cutGapATimeZNA{"cutGapATimeZNA", 2., {"My collision cut. Gap Side A"}}; + Configurable cutGapATimeZNC{"cutGapATimeZNC", 2., {"My collision cut. Gap Side A"}}; + Configurable cutGapAMyEnergyZNA{"cutGapAMyEnergyZNA", 0., {"My collision cut. Gap Side A"}}; + Configurable useFT0AGapA{"useFT0AGapA", false, {"My collision cut. Gap Side A"}}; + Configurable cutGapAMyAmplitudeFT0A{"cutGapAMyAmplitudeFT0A", 100., {"My collision cut. A Gap"}}; + Configurable cutGapAMyEnergyZNC{"cutGapAMyEnergyZNC", 1., {"My collision cut. Gap Side A"}}; + Configurable useFV0{"useFV0", false, {"My collision cut. Gap Side A"}}; + Configurable cutGapAFV0Amplitude{"cutGapAFV0Amplitude", 50, {"My collision cut. Gap Side A"}}; // Configurable cutAGapMyAmplitudeFT0CMin{"cutAGapMyAmplitudeFT0CMin", 0., {"My collision cut. A Gap"}}; // Declare configurables on side C gap - Configurable cutGapCMyEnergyZNA{"cutGapCMyEnergyZNA", 1., {"My collision cut. C Gap"}}; - // Configurable cutCGapMyAmplitudeFT0AMin{"cutCGapMyAmplitudeFT0AMin", 0., {"My collision cut. A Gap"}}; - Configurable cutGapCMyEnergyZNC{"cutGapCMyEnergyZNC", 0., {"My collision cut. C Gap"}}; + Configurable cutGapCTimeZNA{"cutGapCTimeZNA", 2., {"My collision cut. Gap Side C"}}; + Configurable cutGapCTimeZNC{"cutGapCTimeZNC", 2., {"My collision cut. Gap Side C"}}; + Configurable cutGapCMyEnergyZNA{"cutGapCMyEnergyZNA", 1., {"My collision cut. Gap Side C"}}; + Configurable useFT0CGapC{"useFT0CGapC", false, {"My collision cut. Gap Side A"}}; + Configurable cutGapCMyAmplitudeFT0C{"cutGapCMyAmplitudeFT0C", 50., {"My collision cut. A Gap"}}; + Configurable cutGapCMyEnergyZNC{"cutGapCMyEnergyZNC", 0., {"My collision cut. Gap Side C"}}; // Configurable cutCGapMyAmplitudeFT0CMax{"cutCGapMyAmplitudeFT0CMax", 200., {"My collision cut. A Gap"}}; // Declare configurables on tracks Configurable cutMyptMin{"cutMyptMin", 0.2, {"My Track cut"}}; @@ -147,11 +193,6 @@ struct UpcPhotonuclearAnalysisJMG { Configurable cutMyTPCNClsCrossedRowsOverNClsFindableMin{"cutMyTPCNClsCrossedRowsOverNClsFindableMin", 0.8f, {"My Track cut"}}; Configurable cutMyTPCNClsOverFindableNClsMin{"cutMyTPCNClsOverFindableNClsMin", 0.5f, {"My Track cut"}}; Configurable cutMyTPCChi2NclMax{"cutMyTPCChi2NclMax", 4.f, {"My Track cut"}}; - Configurable myWeightMin{"myWeightMin", 0.2f, {"My Track cut"}}; - Configurable myWeightMax{"myWeightMax", 5.f, {"My Track cut"}}; - Configurable myEpsilonToWeight{"myEpsilonToWeight", 1e-6f, {"NUA correction"}}; - Configurable useEpsilon{"useEpsilon", false, {"NUA correction"}}; - Configurable useNMax{"useNMax", true, {"NUA correction"}}; Configurable> cfgPairCut{"cfgPairCut", {CFGPairCutDefaults[0], 5, @@ -168,12 +209,13 @@ struct UpcPhotonuclearAnalysisJMG { ConfigurableAxis axisEtaEfficiency{"axisEtaEfficiency", {20, -1.0, 1.0}, "eta axis for efficiency histograms"}; ConfigurableAxis axisPtEfficiency{"axisPtEfficiency", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0}, "pt axis for efficiency histograms"}; - Filter collisionZVtxFilter = nabs(aod::collision::posZ) < myZVtxCut; - Filter collisionZNTimeFilter = nabs(aod::udzdc::timeZNA) < myTimeZNACut && nabs(aod::udzdc::timeZNC) < myTimeZNCCut; - Filter collisionZNeEnergyFilter = (aod::udzdc::energyCommonZNA < cutGapAMyEnergyZNA && aod::udzdc::energyCommonZNC >= cutGapAMyEnergyZNC) || (aod::udzdc::energyCommonZNA >= cutGapCMyEnergyZNA && aod::udzdc::energyCommonZNC < cutGapCMyEnergyZNC); - Filter collisioSGFilter = aod::udcollision::gapSide == uint8_t(0) || aod::udcollision::gapSide == uint8_t(1); + // Filter collisionZVtxFilter = nabs(aod::collision::posZ) < myZVtxCut; + // Filter collisionZNTimeFilterGapA = (nabs(aod::udzdc::timeZNA) > cutGapATimeZNA && nabs(aod::udzdc::timeZNC) < cutGapATimeZNC) || (nabs(aod::udzdc::timeZNA) < cutGapCTimeZNA && nabs(aod::udzdc::timeZNC) > cutGapCTimeZNC); + // Filter collisionZNeEnergyFilter = (aod::udzdc::energyCommonZNA < cutGapAMyEnergyZNA && aod::udzdc::energyCommonZNC >= cutGapAMyEnergyZNC) || (aod::udzdc::energyCommonZNA >= cutGapCMyEnergyZNA && aod::udzdc::energyCommonZNC < cutGapCMyEnergyZNC); + // Filter collisioSGFilter = aod::udcollision::gapSide == uint8_t(0) || aod::udcollision::gapSide == uint8_t(1); - using FullSGUDCollision = soa::Filtered>; + // using FullSGUDCollision = soa::Filtered>; + using FullSGUDCollision = soa::Join; using FullUDTracks = soa::Join; // Output definitions @@ -190,6 +232,7 @@ struct UpcPhotonuclearAnalysisJMG { void init(InitContext const&) { const AxisSpec axisCollision{4, -0.5, 3.5}; + const AxisSpec axisCollisionFlow{13, -0.5, 12.5}; const AxisSpec axisZvtx{20, -10., 10.}; const AxisSpec axisPt{402, -0.05, 20.05}; const AxisSpec axisP{402, -10.05, 10.05}; @@ -235,6 +278,7 @@ struct UpcPhotonuclearAnalysisJMG { } histos.add("Events/hCountCollisions", "0 total - 1 side A - 2 side C - 3 both side; Number of analysed collision; counts", kTH1F, {axisCollision}); histos.add("Events/hCountCollisionsMixed", "0 total - 1 side A - 2 side C - 3 both side; Number of analysed collision; counts", kTH1F, {axisCollision}); + histos.add("Events/hCollisionsFlow", "; ; counts", kTH1F, {axisCollisionFlow}); histos.add("Tracks/hTracksAfterCuts", " ; ; counts", kTH1F, {axisCountTracks}); // histos to selection gap in side A @@ -322,9 +366,9 @@ struct UpcPhotonuclearAnalysisJMG { std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -7.0f, -5.0f, -2.5f, 0.0f, 2.5f, 5.0f, 7.0f, 10.0f}; std::vector gapSideBinsEdges{VARIABLE_WIDTH, -0.5, 0.5, 1.5}; - struct SameEventTag { - }; - struct MixedEventTag { + enum EventType { + SameEvent = 1, + MixedEvent = 2 }; SliceCache cache; @@ -333,41 +377,82 @@ struct UpcPhotonuclearAnalysisJMG { // int countGapC = 0; // Binning only on PosZ without multiplicity - using BinningType = ColumnBinningPolicy; + // using BinningType = ColumnBinningPolicy; // BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; - // using BinningType = ColumnBinningPolicy; + using BinningType = ColumnBinningPolicy; // BinningType bindingOnVtx{{vtxBinsEdges}, true}; // SameKindPair pairs{bindingOnVtx, nEventsMixed, -1, &cache}; template bool isCollisionCutSG(CSG const& collision, int SideGap) { - bool gapSideA = (collision.energyCommonZNA() < cutGapAMyEnergyZNA) && (collision.energyCommonZNC() >= cutGapAMyEnergyZNC); - bool gapSideC = (collision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (collision.energyCommonZNC() < cutGapCMyEnergyZNC); + if (std::abs(collision.posZ()) > myZVtxCut) { + return false; + } + if (useSBP && collision.sbp() != sbpCut) { + return false; + } + if (useITSROFb && collision.itsROFb() != itsROFbCut) { + return false; + } + if (useVtxITSTPC && collision.vtxITSTPC() != vtxITSTPCCut) { + return false; + } + if (useZVtxFT0vsPv && collision.zVtxFT0vPV() != zVtxFT0vsPvCut) { + return false; + } + if (useOccupancy && collision.occupancyInTime() > cutOccupancy) { + return false; + } + if (useUPCMode && collision.flags() != upcModeCut) { + return false; + } switch (SideGap) { - case 0: // Gap in A side - return gapSideA; // 0n - A side && Xn - C Side - // if ((collision.totalFT0AmplitudeA() < cutAGapMyAmplitudeFT0AMax && collision.totalFT0AmplitudeC() >= cutAGapMyAmplitudeFT0CMin) == false) { - // return false; - // } + case 0: // Gap in A side + if (!(std::abs(collision.timeZNA()) > cutGapATimeZNA && std::abs(collision.timeZNC()) < cutGapATimeZNC)) { + return false; + } + if (useEnergyZN && !((collision.energyCommonZNA() < cutGapAMyEnergyZNA) && (collision.energyCommonZNC() >= cutGapAMyEnergyZNC))) { + return false; + } // 0n - A side && Xn - C Side + if (useGapSideVariable && collision.gapSide() != uint8_t(0)) { + return false; + } + if (useFV0 && collision.totalFV0AmplitudeA() > cutGapAFV0Amplitude) { + return false; + } + if (useFT0AGapA && (collision.totalFT0AmplitudeA() > cutGapAMyAmplitudeFT0A)) { + return false; + } break; - case 1: // Gap in C side - return gapSideC; // Xn - A side && 0n - C Side - // if ((collision.totalFT0AmplitudeA() >= cutCGapMyAmplitudeFT0AMin && collision.totalFT0AmplitudeC() < cutCGapMyAmplitudeFT0CMax) == false) { - // return false; - // } + case 1: // Gap in C side + if (!(std::abs(collision.timeZNA()) < cutGapCTimeZNA && std::abs(collision.timeZNC()) > cutGapCTimeZNC)) { + return false; + } + if (useEnergyZN && !((collision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (collision.energyCommonZNC() < cutGapCMyEnergyZNC))) { + return false; + } // Xn - A side && 0n - C Side + if (useGapSideVariable && collision.gapSide() != uint8_t(1)) { + return false; + } + if (useFT0CGapC && (collision.totalFT0AmplitudeC() > cutGapCMyAmplitudeFT0C)) { + return false; + } break; default: return false; break; } + return true; } template bool isCollisionCutSG(CSG const& collision) { - return isCollisionCutSG(collision, 0) || isCollisionCutSG(collision, 1); + bool passGapA = isCollisionCutSG(collision, 0); + bool passGapC = isCollisionCutSG(collision, 1); + return passGapA || passGapC; } template @@ -455,8 +540,8 @@ struct UpcPhotonuclearAnalysisJMG { return true; } - template - void fillCorrelationsUD(TTarget target, const TTracks& tracks1, const TTracks& tracks2, float multiplicity, float posZ, TTag) + template + void fillCorrelationsUD(TTarget target, const TTracks& tracks1, const TTracks& tracks2, float multiplicity, float posZ, int system) { for (const auto& track1 : tracks1) { if (isTrackCut(track1) == false) { @@ -488,7 +573,7 @@ struct UpcPhotonuclearAnalysisJMG { multiplicity, deltaPhi, posZ); - if constexpr (std::is_same_v) { + if (system == SameEvent) { if (minMultiplicity <= multiplicity) { histos.fill(HIST("sameEvent2D"), deltaEta, deltaPhi); } @@ -507,7 +592,7 @@ struct UpcPhotonuclearAnalysisJMG { if (range5Min <= multiplicity && multiplicity <= range5Max) { histos.fill(HIST("sameEvent_41_50"), deltaEta, deltaPhi); } - } else if constexpr (std::is_same_v) { + } else if (system == MixedEvent) { if (minMultiplicity <= multiplicity) { histos.fill(HIST("mixedEvent2D"), deltaEta, deltaPhi); } @@ -535,6 +620,7 @@ struct UpcPhotonuclearAnalysisJMG { { histos.fill(HIST("Events/hCountCollisions"), 0); int sgSide = reconstructedCollision.gapSide(); + int sgSideTimeZN = -1; int nTracksCharged = 0; float sumPt = 0; int nchPVGapSideA = 0; @@ -546,7 +632,6 @@ struct UpcPhotonuclearAnalysisJMG { int nTracksChargedSideA(-222), nTracksChargedSideC(-222); int multiplicitySideA(-222), multiplicitySideC(-222); - for (const auto& track : reconstructedTracks) { if (isTrackCut(track) == false) { continue; @@ -554,8 +639,16 @@ struct UpcPhotonuclearAnalysisJMG { float phiVal = RecoDecay::constrainAngle(phi(track.px(), track.py()), 0.f); histos.fill(HIST("etaphiVtx"), reconstructedCollision.posZ(), eta(track.px(), track.py(), track.pz()), phiVal); } + bool isGapATimeZN = (std::abs(reconstructedCollision.timeZNA()) > cutGapATimeZNA) && (std::abs(reconstructedCollision.timeZNC()) < cutGapATimeZNC); + bool isGapCTimeZN = (std::abs(reconstructedCollision.timeZNA()) < cutGapCTimeZNA) && (std::abs(reconstructedCollision.timeZNC()) > cutGapCTimeZNC); + if (isGapATimeZN) { + sgSideTimeZN = 0; + } + if (isGapCTimeZN) { + sgSideTimeZN = 1; + } - switch (sgSide) { + switch (sgSideTimeZN) { case 0: // gap for side A if (isCollisionCutSG(reconstructedCollision, 0) == false) { return; @@ -681,7 +774,41 @@ struct UpcPhotonuclearAnalysisJMG { return; break; } - tree(vTrackPtSideA, vTrackEtaSideA, vTrackPhiSideA, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, vTrackPtSideC, vTrackEtaSideC, vTrackPhiSideC, vTrackTPCSignalSideA, vTrackTOFSignalSideA, vTrackTPCNSigmaPiSideA, vTrackTOFNSigmaPiSideA, vTrackTPCNSigmaKaSideA, vTrackTOFNSigmaKaSideA, nTracksChargedSideA, multiplicitySideA, nTracksChargedSideC, multiplicitySideC); + tree(sgSide, + sgSideTimeZN, + reconstructedCollision.sbp(), + reconstructedCollision.itsROFb(), + reconstructedCollision.vtxITSTPC(), + reconstructedCollision.zVtxFT0vPV(), + reconstructedCollision.timeZNA(), + reconstructedCollision.timeZNC(), + reconstructedCollision.energyCommonZNA(), + reconstructedCollision.energyCommonZNC(), + reconstructedCollision.totalFV0AmplitudeA(), + reconstructedCollision.occupancyInTime(), + reconstructedCollision.flags(), + vTrackPtSideA, + vTrackEtaSideA, + vTrackPhiSideA, + vTrackTPCSignalSideA, + vTrackTOFSignalSideA, + vTrackTPCNSigmaPiSideA, + vTrackTOFNSigmaPiSideA, + vTrackTPCNSigmaKaSideA, + vTrackTOFNSigmaKaSideA, + vTrackPtSideC, + vTrackEtaSideC, + vTrackPhiSideC, + vTrackTPCSignalSideA, + vTrackTOFSignalSideA, + vTrackTPCNSigmaPiSideA, + vTrackTOFNSigmaPiSideA, + vTrackTPCNSigmaKaSideA, + vTrackTOFNSigmaKaSideA, + nTracksChargedSideA, + multiplicitySideA, + nTracksChargedSideC, + multiplicitySideC); // nTracksChargedSideA = nTracksChargedSideC = multiplicitySideA = multiplicitySideC = 0; } @@ -693,21 +820,8 @@ struct UpcPhotonuclearAnalysisJMG { // int sgSide = reconstructedCollision.gapSide(); // int sgSide = 0; - // int maxCount = 0; - // int maxCountGapA = 0; - // int maxCountGapC = 0; - - // if (auto histEventCount = histos.get(HIST("eventcount"))) { - // int binA = histEventCount->GetXaxis()->FindBin(-2); Gap A - // int binC = histEventCount->GetXaxis()->FindBin(-1); Gap C - - // maxCount = histEventCount->GetBinContent(binA) * factorEventsMixed; - // maxCountGapA = histEventCount->GetBinContent(binA) * factorEventsMixed; - // maxCountGapC = histEventCount->GetBinContent(binC) * factorEventsMixed; - // } - - BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; - // BinningType bindingOnVtx{{vtxBinsEdges}, true}; + // BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; + BinningType bindingOnVtx{{vtxBinsEdges}, true}; auto tracksTuple = std::make_tuple(reconstructedTracks); SameKindPair pairs{bindingOnVtx, nEventsMixed, -1, reconstructedCollision, tracksTuple, &cache}; @@ -717,10 +831,6 @@ struct UpcPhotonuclearAnalysisJMG { continue; } - // if (countGapA >= maxCountGapA && countGapC >= maxCountGapC) { - // break; - // } - float multiplicity = 0; histos.fill(HIST("Events/hCountCollisionsMixed"), 0); @@ -744,42 +854,7 @@ struct UpcPhotonuclearAnalysisJMG { histos.fill(HIST("Events/hCountCollisionsMixed"), 2); // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.gapSide()})); - fillCorrelationsUD(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), MixedEventTag{}); - // LOGF(info, "Filling mixed events"); - - // if (collision1.gapSide() == 0 && collision2.gapSide() == 0) { gap on side A - // if (isCollisionCutSG(collision1, 0) == false && isCollisionCutSG(collision2, 0) == false) { - // continue; - // } - // std::cout << "Counts for Gap A: " << countGapA << " Maximum Count for Gap A " << maxCountGapA << std::endl; - // ++countGapA; - // LOGF(info, "In the pairs loop, gap side A"); - // multiplicity = tracks1.size(); - // if (fillCollisionUD(mixedGapSideA, multiplicity) == false) { - // return; - // } - // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); - // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.gapSide()})); - // fillCorrelationsUD(mixedGapSideA, tracks1, tracks2, multiplicity, collision1.posZ()); - // LOGF(info, "Filling mixedGapSideA events, Gap for side A"); - // } - - // if (collision1.gapSide() == 1 && collision2.gapSide() == 1) { gap on side C - // if (isCollisionCutSG(collision1, 1) == false && isCollisionCutSG(collision2, 1) == false) { - // continue; - // } - // std::cout << "Counts for Gap C: " << countGapC << " Maximum Count for Gap C" << maxCountGapC << std::endl; - // ++countGapC; - // LOGF(info, "In the pairs loop, gap side C"); - // multiplicity = tracks1.size(); - // if (fillCollisionUD(mixedGapSideC, multiplicity) == false) { - // return; - // } - // fillCorrelationsUD(mixedGapSideC, tracks1, tracks2, multiplicity, collision1.posZ()); - // LOGF(info, "Filling mixedGapSideC events, Gap for side C"); - // } else { - // continue; - // } + fillCorrelationsUD(mixed, tracks1, tracks2, multiplicity, collision1.posZ(), MixedEvent); } } @@ -790,6 +865,80 @@ struct UpcPhotonuclearAnalysisJMG { // int sgSide = reconstructedCollision.gapSide(); float multiplicity = 0; + auto hEventFlow = histos.get(HIST("Events/hCollisionsFlow")); + hEventFlow->GetXaxis()->SetBinLabel(1, "All events"); + hEventFlow->GetXaxis()->SetBinLabel(2, "Z Vtx"); + hEventFlow->GetXaxis()->SetBinLabel(3, "SBP"); + hEventFlow->GetXaxis()->SetBinLabel(4, "ITS ROFb"); + hEventFlow->GetXaxis()->SetBinLabel(5, "Vtx ITS-TPC"); + hEventFlow->GetXaxis()->SetBinLabel(6, "Z Vtx FT0vsPv"); + hEventFlow->GetXaxis()->SetBinLabel(7, "Occupancy"); + hEventFlow->GetXaxis()->SetBinLabel(8, "UPC Mode"); + hEventFlow->GetXaxis()->SetBinLabel(9, "Time ZN"); + hEventFlow->GetXaxis()->SetBinLabel(10, "Energy ZN"); + hEventFlow->GetXaxis()->SetBinLabel(11, "FV0-A Amplitude"); + hEventFlow->GetXaxis()->SetBinLabel(12, "FT0 Amplitude"); + hEventFlow->GetXaxis()->SetBinLabel(13, "GapSide Variable"); + + histos.fill(HIST("Events/hCollisionsFlow"), 0); + if (std::abs(reconstructedCollision.posZ()) > myZVtxCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 1); + if (useSBP && reconstructedCollision.sbp() != sbpCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 2); + if (useITSROFb && reconstructedCollision.itsROFb() != itsROFbCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 3); + if (useVtxITSTPC && reconstructedCollision.vtxITSTPC() != vtxITSTPCCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 4); + if (useZVtxFT0vsPv && reconstructedCollision.zVtxFT0vPV() != zVtxFT0vsPvCut) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 5); + if (useOccupancy && reconstructedCollision.occupancyInTime() > cutOccupancy) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 6); + if (useUPCMode && reconstructedCollision.flags() != 1) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 7); + bool isGapATimeZN = (std::abs(reconstructedCollision.timeZNA()) > cutGapATimeZNA) && (std::abs(reconstructedCollision.timeZNC()) < cutGapATimeZNC); + bool isGapCTimeZN = (std::abs(reconstructedCollision.timeZNA()) < cutGapCTimeZNA) && (std::abs(reconstructedCollision.timeZNC()) > cutGapCTimeZNC); + if (!(isGapATimeZN || isGapCTimeZN)) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 8); + + bool isGapAMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() < cutGapAMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() >= cutGapAMyEnergyZNC)); + bool isGapCMyEnergyZN = useEnergyZN && ((reconstructedCollision.energyCommonZNA() >= cutGapCMyEnergyZNA) && (reconstructedCollision.energyCommonZNC() < cutGapCMyEnergyZNC)); + if (useEnergyZN && !(isGapAMyEnergyZN || isGapCMyEnergyZN)) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 9); + if (isGapATimeZN && useFV0 && reconstructedCollision.totalFV0AmplitudeA() > cutGapAFV0Amplitude) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 10); + bool cutFT0AGapA = useFT0AGapA && reconstructedCollision.totalFT0AmplitudeA() > cutGapAMyAmplitudeFT0A; + bool cutFT0CGapC = useFT0CGapC && reconstructedCollision.totalFT0AmplitudeC() > cutGapCMyAmplitudeFT0C; + if (cutFT0AGapA || cutFT0CGapC) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 11); + bool cutGapSideAVariable = useGapSideVariable && reconstructedCollision.gapSide() != uint8_t(0); + bool cutGapSideCVariable = useGapSideVariable && reconstructedCollision.gapSide() != uint8_t(1); + if (cutGapSideAVariable || cutGapSideCVariable) { + return; + } + histos.fill(HIST("Events/hCollisionsFlow"), 12); + if (isCollisionCutSG(reconstructedCollision) == false) { return; } @@ -914,38 +1063,7 @@ struct UpcPhotonuclearAnalysisJMG { histos.fill(HIST("eventcount"), 5); } fillQAUD(reconstructedTracks, multiplicity); - fillCorrelationsUD(same, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ(), SameEventTag{}); - - /*switch (sgSide) { - case 0: // gap for side A - if (isCollisionCutSG(reconstructedCollision, 0) == false) { - return; - } - multiplicity = reconstructedTracks.size(); - if (fillCollisionUD(sameGapSideA, multiplicity) == false) { - return; - } - LOGF(info, "Filling sameGapSideA events"); - histos.fill(HIST("eventcount"), -2); - fillQAUD(reconstructedTracks); - fillCorrelationsUD(sameGapSideA, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); - break; - case 1: // gap for side C - if (isCollisionCutSG(reconstructedCollision, 1) == false) { - return; - } - multiplicity = reconstructedTracks.size(); - if (fillCollisionUD(sameGapSideC, multiplicity) == false) { - return; - } - histos.fill(HIST("eventcount"), -1); - // LOGF(info, "Filling sameGapSideC events"); - fillCorrelationsUD(sameGapSideC, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); - break; - default: - return; - break; - }*/ + fillCorrelationsUD(same, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ(), SameEvent); } PROCESS_SWITCH(UpcPhotonuclearAnalysisJMG, processSame, "Process same event", true); diff --git a/PWGUD/Tasks/upcPionAnalysis.cxx b/PWGUD/Tasks/upcPionAnalysis.cxx index fc215ea1822..470281f0a77 100644 --- a/PWGUD/Tasks/upcPionAnalysis.cxx +++ b/PWGUD/Tasks/upcPionAnalysis.cxx @@ -9,18 +9,35 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include -#include "PWGUD/DataModel/UDTables.h" -#include -#include -#include "TLorentzVector.h" #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/SGTrackSelector.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include using namespace std; using namespace o2; using namespace o2::aod; diff --git a/PWGUD/Tasks/upcPolarisationJpsiIncoh.cxx b/PWGUD/Tasks/upcPolarisationJpsiIncoh.cxx index 88d8f36d18d..d026d6ce962 100644 --- a/PWGUD/Tasks/upcPolarisationJpsiIncoh.cxx +++ b/PWGUD/Tasks/upcPolarisationJpsiIncoh.cxx @@ -19,19 +19,25 @@ #include "Common/Core/RecoDecay.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPECSObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TMath.h" -#include "TRandom3.h" -#include "TSystem.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include #include #include diff --git a/PWGUD/Tasks/upcQuarkoniaCentralBarrel.cxx b/PWGUD/Tasks/upcQuarkoniaCentralBarrel.cxx index 8baf7f42206..b87d5f3eb29 100644 --- a/PWGUD/Tasks/upcQuarkoniaCentralBarrel.cxx +++ b/PWGUD/Tasks/upcQuarkoniaCentralBarrel.cxx @@ -31,36 +31,31 @@ // #include "PWGUD/Core/SGSelector.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/Zorro.h" -#include "Common/Core/ZorroSummary.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" - -#include -#include -#include -#include -#include -#include - +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include #include #include +#include #include -#include #include #include diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 6aa5c7ad47a..18c3eb5f08a 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -19,13 +19,31 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TPDGCode.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include #include #include #include @@ -49,7 +67,23 @@ namespace reco_tree // event info DECLARE_SOA_COLUMN(RecoSetting, recoSetting, uint16_t); DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(OccupancyInTime, occupancyInTime, float); +DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, float); +DECLARE_SOA_COLUMN(LocalBC, localBC, int); +// FIT info +DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); +DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFDDAmplitudeA, totalFDDAmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFDDAmplitudeC, totalFDDAmplitudeC, float); +DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float); +DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float); +DECLARE_SOA_COLUMN(TimeFV0A, timeFV0A, float); +DECLARE_SOA_COLUMN(TimeFDDA, timeFDDA, float); +DECLARE_SOA_COLUMN(TimeFDDC, timeFDDC, float); // ZDC info DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); @@ -75,7 +109,9 @@ DECLARE_SOA_COLUMN(LeadingTrackPrPID, leadingTrackPrPID, float); DECLARE_SOA_COLUMN(SubleadingTrackPrPID, subleadingTrackPrPID, float); } // namespace reco_tree DECLARE_SOA_TABLE(RecoTree, "AOD", "RECOTREE", - reco_tree::RecoSetting, reco_tree::RunNumber, reco_tree::PosZ, + reco_tree::RecoSetting, reco_tree::RunNumber, reco_tree::PosX, reco_tree::PosY, reco_tree::PosZ, reco_tree::OccupancyInTime, reco_tree::HadronicRate, reco_tree::LocalBC, + reco_tree::TotalFT0AmplitudeA, reco_tree::TotalFT0AmplitudeC, reco_tree::TotalFV0AmplitudeA, reco_tree::TotalFDDAmplitudeA, reco_tree::TotalFDDAmplitudeC, + reco_tree::TimeFT0A, reco_tree::TimeFT0C, reco_tree::TimeFV0A, reco_tree::TimeFDDA, reco_tree::TimeFDDC, reco_tree::EnergyCommonZNA, reco_tree::EnergyCommonZNC, reco_tree::TimeZNA, reco_tree::TimeZNC, reco_tree::NeutronClass, reco_tree::LeadingTrackSign, reco_tree::SubleadingTrackSign, reco_tree::LeadingTrackPt, reco_tree::SubleadingTrackPt, @@ -90,7 +126,10 @@ namespace mc_tree { // misc event info DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(LocalBC, localBC, int); // tracks DECLARE_SOA_COLUMN(LeadingTrackSign, leadingTrackSign, int); DECLARE_SOA_COLUMN(SubleadingTrackSign, subleadingTrackSign, int); @@ -102,52 +141,86 @@ DECLARE_SOA_COLUMN(LeadingTrackPhi, leadingTrackPhi, float); DECLARE_SOA_COLUMN(SubleadingTrackPhi, subleadingTrackPhi, float); } // namespace mc_tree DECLARE_SOA_TABLE(McTree, "AOD", "MCTREE", - mc_tree::RunNumber, mc_tree::PosZ, + mc_tree::RunNumber, mc_tree::PosX, mc_tree::PosY, mc_tree::PosZ, mc_tree::LocalBC, mc_tree::LeadingTrackSign, mc_tree::SubleadingTrackSign, mc_tree::LeadingTrackPt, mc_tree::SubleadingTrackPt, mc_tree::LeadingTrackEta, mc_tree::SubleadingTrackEta, mc_tree::LeadingTrackPhi, mc_tree::SubleadingTrackPhi); + +namespace resolution_tree +{ +// vertex info +DECLARE_SOA_COLUMN(GenPosX, genPosX, float); +DECLARE_SOA_COLUMN(GenPosY, genPosY, float); +DECLARE_SOA_COLUMN(GenPosZ, genPosZ, float); +DECLARE_SOA_COLUMN(RecoPosX, recoPosX, float); +DECLARE_SOA_COLUMN(RecoPosY, recoPosY, float); +DECLARE_SOA_COLUMN(RecoPosZ, recoPosZ, float); +// track info +DECLARE_SOA_COLUMN(LeadingSign, leadingSign, int); +DECLARE_SOA_COLUMN(LeadingGenPt, leadingGenPt, float); +DECLARE_SOA_COLUMN(LeadingGenEta, leadingGenEta, float); +DECLARE_SOA_COLUMN(LeadingGenPhi, leadingGenPhi, float); +DECLARE_SOA_COLUMN(LeadingRecoPt, leadingRecoPt, float); +DECLARE_SOA_COLUMN(LeadingRecoEta, leadingRecoEta, float); +DECLARE_SOA_COLUMN(LeadingRecoPhi, leadingRecoPhi, float); +DECLARE_SOA_COLUMN(SubleadingSign, subleadingSign, int); +DECLARE_SOA_COLUMN(SubleadingGenPt, subleadingGenPt, float); +DECLARE_SOA_COLUMN(SubleadingGenEta, subleadingGenEta, float); +DECLARE_SOA_COLUMN(SubleadingGenPhi, subleadingGenPhi, float); +DECLARE_SOA_COLUMN(SubleadingRecoPt, subleadingRecoPt, float); +DECLARE_SOA_COLUMN(SubleadingRecoEta, subleadingRecoEta, float); +DECLARE_SOA_COLUMN(SubleadingRecoPhi, subleadingRecoPhi, float); +} // namespace resolution_tree +DECLARE_SOA_TABLE(ResolutionTree, "AOD", "RESOLUTIONTREE", + resolution_tree::GenPosX, resolution_tree::GenPosY, resolution_tree::GenPosZ, + resolution_tree::RecoPosX, resolution_tree::RecoPosY, resolution_tree::RecoPosZ, + resolution_tree::LeadingSign, resolution_tree::LeadingGenPt, resolution_tree::LeadingGenEta, resolution_tree::LeadingGenPhi, + resolution_tree::LeadingRecoPt, resolution_tree::LeadingRecoEta, resolution_tree::LeadingRecoPhi, + resolution_tree::SubleadingSign, resolution_tree::SubleadingGenPt, resolution_tree::SubleadingGenEta, resolution_tree::SubleadingGenPhi, + resolution_tree::SubleadingRecoPt, resolution_tree::SubleadingRecoEta, resolution_tree::SubleadingRecoPhi); } // namespace o2::aod struct UpcRhoAnalysis { Produces recoTree; Produces mcTree; + Produces resolutionTree; SGSelector sgSelector; const float pcEtaCut = 0.9; // physics coordination recommendation + const int nPions = 2; // only study dipion final states const std::vector runNumbers = {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544911, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544991, 544992, 545004, 545008, 545009, 545041, 545042, 545044, 545047, 545060, 545062, 545063, 545064, 545066, 545086, 545103, 545117, 545171, 545184, 545185, 545210, 545222, 545223, 545246, 545249, 545262, 545289, 545291, 545294, 545295, 545296, 545311, 545312, 545332, 545345, 545367}; AxisSpec runNumberAxis = {static_cast(runNumbers.size()), 0.5, static_cast(runNumbers.size()) + 0.5, "run number"}; - Configurable numPions{"numPions", 2, "required number of pions in the event"}; + Configurable isPO{"isPO", false, "processing p-O data?"}; - Configurable isPO{"isPO", false, "process proton-oxygen data"}; - - Configurable cutGapSide{"cutGapSide", true, "apply gap side cut"}; + Configurable cutGapSide{"cutGapSide", true, "apply gap side cut?"}; Configurable gapSide{"gapSide", 2, "required gap side"}; - Configurable useTrueGap{"useTrueGap", false, "use true gap"}; + Configurable useTrueGap{"useTrueGap", false, "use true gap?"}; Configurable cutTrueGapSideFV0{"cutTrueGapSideFV0", 180000, "FV0A threshold for SG selector"}; Configurable cutTrueGapSideFT0A{"cutTrueGapSideFT0A", 150., "FT0A threshold for SG selector"}; Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; - Configurable requireTof{"requireTof", false, "require TOF signal"}; - Configurable useRecoFlag{"useRecoFlag", false, "use reco flag for event selection"}; + Configurable requireTof{"requireTof", false, "require TOF signal?"}; + Configurable useRecoFlag{"useRecoFlag", false, "use UPC/STD reconstruction flag for event selection?"}; Configurable cutRecoFlag{"cutRecoFlag", 1, "0 = std mode, 1 = upc mode"}; - Configurable useRctFlag{"useRctFlag", false, "use RCT flags for event selection"}; + Configurable useRctFlag{"useRctFlag", false, "use RCT flags for event selection?"}; Configurable cutRctFlag{"cutRctFlag", 0, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; - Configurable selectRuns{"selectRuns", false, "select runs from the list"}; + Configurable selectRuns{"selectRuns", false, "select runs?"}; Configurable> selectedRuns{"selectedRuns", {544013, 544028, 544032, 544091, 544095, 544098, 544116, 544121, 544122, 544123, 544124, 544184, 544185, 544389, 544390, 544391, 544392, 544451, 544454, 544474, 544475, 544476, 544477, 544490, 544491, 544492, 544508, 544510, 544511, 544512, 544514, 544515, 544518, 544548, 544549, 544550, 544551, 544564, 544565, 544567, 544568, 544580, 544582, 544583, 544585, 544614, 544640, 544652, 544653, 544672, 544674, 544692, 544693, 544694, 544696, 544739, 544742, 544754, 544767, 544794, 544795, 544797, 544813, 544868, 544886, 544887, 544896, 544913, 544914, 544917, 544931, 544947, 544961, 544963, 544964, 544968, 544992, 545009, 545044, 545047, 545063, 545064, 545066, 545185, 545210, 545223, 545249, 545291, 545294, 545295, 545296, 545312}, "list of selected runs"}; Configurable collisionsPosZMaxCut{"collisionsPosZMaxCut", 10.0, "max Z position cut on collisions"}; - Configurable cutNumContribs{"cutNumContribs", true, "cut on number of contributors"}; + Configurable cutNumContribs{"cutNumContribs", true, "cut on number of contributors?"}; Configurable collisionsNumContribsMaxCut{"collisionsNumContribsMaxCut", 2, "max number of contributors cut on collisions"}; - Configurable znCommonEnergyCut{"znCommonEnergyCut", 0.0, "ZN common energy cut"}; - Configurable znTimeCut{"znTimeCut", 2.0, "ZN time cut"}; + Configurable znTimeCut{"znTimeCut", 2.0, "ZN time cut (ns)"}; + Configurable cutOccupancy{"cutOccupancy", true, "cut on collision occupancy?"}; + Configurable occupancyCut{"occupancyCut", 1000.0, "occupancy cut"}; Configurable tracksTpcNSigmaPiCut{"tracksTpcNSigmaPiCut", 3.0, "TPC nSigma pion cut"}; - Configurable rejectLowerProbPairs{"rejectLowerProbPairs", true, "reject track pairs with lower El or Ka PID radii"}; + Configurable rejectLowerProbPairs{"rejectLowerProbPairs", true, "reject track pairs with smaller El/Ka/Pr PID radii?"}; Configurable tracksDcaMaxCut{"tracksDcaMaxCut", 1.0, "max DCA cut on tracks"}; Configurable tracksMinItsNClsCut{"tracksMinItsNClsCut", 4, "min ITS clusters cut"}; Configurable tracksMaxItsChi2NClCut{"tracksMaxItsChi2NClCut", 3.0, "max ITS chi2/Ncls cut"}; @@ -172,123 +245,132 @@ struct UpcRhoAnalysis { ConfigurableAxis deltaPhiAxis{"deltaPhiAxis", {182, -o2::constants::math::PI, o2::constants::math::PI}, "#Delta#it{#phi} (rad)"}; ConfigurableAxis znCommonEnergyAxis{"znCommonEnergyAxis", {250, -5.0, 20.0}, "ZN common energy (TeV)"}; ConfigurableAxis znTimeAxis{"znTimeAxis", {200, -10.0, 10.0}, "ZN time (ns)"}; - ConfigurableAxis nSigmaAxis{"nSigmaAxis", {600, -30.0, 30.0}, "TPC #it{n#sigma}"}; + ConfigurableAxis nSigmaAxis{"nSigmaAxis", {400, -20.0, 20.0}, "TPC #it{n#sigma}"}; + ConfigurableAxis resolutionAxis{"resolutionAxis", {2000, -1.0, 1.0}, "resolution"}; HistogramRegistry rQC{"rQC", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry rTracks{"rTracks", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry rSystem{"rSystem", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry rMC{"rMC", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry rResolution{"rResolution", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext& context) { - // QA // - // collisions - rQC.add("QC/collisions/all/hPosXY", ";vertex #it{x} (cm);vertex #it{y} (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); - rQC.add("QC/collisions/all/hPosZ", ";vertex #it{z} (cm);counts", kTH1D, {{400, -20.0, 20.0}}); - rQC.add("QC/collisions/all/hNumContrib", ";number of PV contributors;counts", kTH1D, {{36, -0.5, 35.5}}); - rQC.add("QC/collisions/all/hZdcCommonEnergy", ";ZNA common energy (TeV);ZNC common energy (TeV);counts", kTH2D, {znCommonEnergyAxis, znCommonEnergyAxis}); - rQC.add("QC/collisions/all/hZdcTime", ";ZNA time (ns);ZNC time (ns);counts", kTH2D, {znTimeAxis, znTimeAxis}); - rQC.add("QC/collisions/all/hTotalFT0AmplitudeA", ";FT0A amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); - rQC.add("QC/collisions/all/hTotalFT0AmplitudeC", ";FT0C amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); - rQC.add("QC/collisions/all/hTotalFV0AmplitudeA", ";FV0A amplitude;counts", kTH1D, {{300, 0.0, 300.0}}); - rQC.add("QC/collisions/all/hTotalFDDAmplitudeA", ";FDDA amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); - rQC.add("QC/collisions/all/hTotalFDDAmplitudeC", ";FDDC amplitude;counts", kTH1D, {{50, 0.0, 50.0}}); - rQC.add("QC/collisions/all/hTimeFT0A", ";FT0A time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFT0C", ";FT0C time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFV0A", ";FV0A time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{500, -10.0, 40.0}}); - // events with selected rho candidates - rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); - rQC.addClone("QC/collisions/all/", "QC/collisions/systemSelections/"); - - std::vector collisionSelectionCounterLabels = {"all collisions", "rapidity gap", "ITS-TPC vertex", "same bunch pile-up", "ITS ROF border", "TF border", "#it{z} position", "number of contributors", "RCT selections", "reco flag selection"}; - rQC.add("QC/collisions/hSelectionCounter", ";;collisions passing selections", kTH1D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}}); - rQC.add("QC/collisions/hSelectionCounterPerRun", ";;run number;collisions passing selections", kTH2D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}, runNumberAxis}); - for (int i = 0; i < static_cast(collisionSelectionCounterLabels.size()); ++i) { - rQC.get(HIST("QC/collisions/hSelectionCounter"))->GetXaxis()->SetBinLabel(i + 1, collisionSelectionCounterLabels[i].c_str()); - rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetXaxis()->SetBinLabel(i + 1, collisionSelectionCounterLabels[i].c_str()); - } - // tracks - rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC #it{n#sigma}(e);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC #it{n#sigma}(K);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hTpcNSigmaPr", ";TPC #it{n#sigma}(p);counts", kTH1D, {nSigmaAxis}); - rQC.add("QC/tracks/all/hDcaXYZ", ";track #it{DCA}_{z} (cm);track #it{DCA}_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {400, -2.0, 2.0}}); - rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{11, -0.5, 10.5}}); - rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{200, 0.0, 20.0}}); - rQC.add("QC/tracks/all/hTpcChi2NCl", ";TPC #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{200, 0.0, 20.0}}); - rQC.add("QC/tracks/all/hTpcNCls", ";found TPC #it{N}_{cls};counts", kTH1D, {{160, 0.0, 160.0}}); // tpcNClsFindable() - track.tpcNClsFindableMinusFound - rQC.add("QC/tracks/all/hTpcNClsCrossedRows", ";TPC crossed rows;counts", kTH1D, {{160, 0.0, 160.0}}); - rQC.add("QC/tracks/all/hTpcNClsCrossedRowsOverNClsFindable", ";TPC crossed rows/findable #it{N}_{cls};counts", kTH1D, {{300, 0.5, 2.5}}); - rQC.add("QC/tracks/all/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); - rQC.add("QC/tracks/all/hEta", ";#it{#eta};counts", kTH1D, {etaAxis}); - rQC.add("QC/tracks/all/hPhi", ";#it{#phi} (rad);counts", kTH1D, {phiAxis}); - rQC.add("QC/tracks/all/hTpcSignalVsP", ";|#it{p}| (GeV/#it{c});TPC d#it{E}/d#it{x} signal (arb. units);counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); - rQC.add("QC/tracks/all/hTpcSignalVsPt", ";#it{p}_{T} (GeV/#it{c});TPC d#it{E}/d#it{x} signal (arb. units);counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); - // tracks passing selections - rQC.addClone("QC/tracks/all/", "QC/tracks/trackSelections/"); - rQC.addClone("QC/tracks/all/", "QC/tracks/systemSelections/"); - rQC.add("QC/tracks/trackSelections/hRemainingTracks", ";remaining tracks;counts", kTH1D, {{21, -0.5, 20.5}}); - rQC.add("QC/tracks/trackSelections/hTpcNSigmaPi2D", ";TPC #it{n#sigma}(#pi)_{leading};TPC #it{n#sigma}(#pi)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); - rQC.add("QC/tracks/trackSelections/hTpcNSigmaEl2D", ";TPC #it{n#sigma}(e)_{leading};TPC #it{n#sigma}(e)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); - rQC.add("QC/tracks/trackSelections/hTpcNSigmaKa2D", ";TPC #it{n#sigma}(K)_{leading};TPC #it{n#sigma}(K)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); - rQC.add("QC/tracks/trackSelections/hTpcNSigmaPr2D", ";TPC #it{n#sigma}(p)_{leading};TPC #it{n#sigma}(p)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); - // selection counter - std::vector trackSelectionCounterLabels = {"all tracks", "PV contributor", "ITS hit", "ITS #it{N}_{cls}", "itsClusterMap check", "ITS #it{#chi}^{2}/#it{N}_{cls}", "TPC hit", "found TPC #it{N}_{cls}", "TPC #it{#chi}^{2}/#it{N}_{cls}", "TPC crossed rows", - "TPC crossed rows/#it{N}_{cls}", - "TOF requirement", - "#it{p}_{T}", "#it{DCA}", "#it{#eta}", "exactly 2 tracks", "PID"}; - rQC.add("QC/tracks/hSelectionCounter", ";;tracks passing selections", kTH1D, {{static_cast(trackSelectionCounterLabels.size()), -0.5, static_cast(trackSelectionCounterLabels.size()) - 0.5}}); - rQC.add("QC/tracks/hSelectionCounterPerRun", ";;run number;tracks passing selections", kTH2D, {{static_cast(trackSelectionCounterLabels.size()), -0.5, static_cast(trackSelectionCounterLabels.size()) - 0.5}, runNumberAxis}); - for (int i = 0; i < static_cast(trackSelectionCounterLabels.size()); ++i) { - rQC.get(HIST("QC/tracks/hSelectionCounter"))->GetXaxis()->SetBinLabel(i + 1, trackSelectionCounterLabels[i].c_str()); - rQC.get(HIST("QC/tracks/hSelectionCounterPerRun"))->GetXaxis()->SetBinLabel(i + 1, trackSelectionCounterLabels[i].c_str()); - } - for (int i = 0; i < static_cast(runNumbers.size()); ++i) { - rQC.get(HIST("QC/tracks/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); + if (context.mOptions.get("processSGdata") || context.mOptions.get("processDGdata")) { + // QA // + // collisions + rQC.add("QC/collisions/all/hPosXY", ";vertex #it{x} (cm);vertex #it{y} (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); + rQC.add("QC/collisions/all/hPosZ", ";vertex #it{z} (cm);counts", kTH1D, {{400, -20.0, 20.0}}); + rQC.add("QC/collisions/all/hNumContrib", ";number of PV contributors;counts", kTH1D, {{36, -0.5, 35.5}}); + rQC.add("QC/collisions/all/hZdcCommonEnergy", ";ZNA common energy (TeV);ZNC common energy (TeV);counts", kTH2D, {znCommonEnergyAxis, znCommonEnergyAxis}); + rQC.add("QC/collisions/all/hZdcTime", ";ZNA time (ns);ZNC time (ns);counts", kTH2D, {znTimeAxis, znTimeAxis}); + rQC.add("QC/collisions/all/hZNTimeVsZNCommonEnergy", ";ZNA/C common energy (TeV);ZNA/C time (ns);counts", kTH2D, {znCommonEnergyAxis, znTimeAxis}); + rQC.add("QC/collisions/all/hTotalFT0AmplitudeA", ";FT0A amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); + rQC.add("QC/collisions/all/hTotalFT0AmplitudeC", ";FT0C amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); + rQC.add("QC/collisions/all/hTotalFV0AmplitudeA", ";FV0A amplitude;counts", kTH1D, {{300, 0.0, 300.0}}); + rQC.add("QC/collisions/all/hTotalFDDAmplitudeA", ";FDDA amplitude;counts", kTH1D, {{160, 0.0, 160.0}}); + rQC.add("QC/collisions/all/hTotalFDDAmplitudeC", ";FDDC amplitude;counts", kTH1D, {{50, 0.0, 50.0}}); + rQC.add("QC/collisions/all/hTimeFT0A", ";FT0A time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFT0C", ";FT0C time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFV0A", ";FV0A time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{400, -5.0, 35.0}}); + rQC.add("QC/collisions/all/hOccupancyInTime", ";occupancy in time;counts", kTH1D, {{1100, 0.0, 1100.0}}); + // events with selected rho candidates + rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); + rQC.addClone("QC/collisions/all/", "QC/collisions/systemSelections/"); + + std::vector collisionSelectionCounterLabels = {"all collisions", "rapidity gap", "ITS-TPC vertex", "same bunch pile-up", "ITS ROF border", "TF border", "#it{z} position", "number of contributors", "RCT selections", "reco flag selection", "occupancy selection"}; + rQC.add("QC/collisions/hSelectionCounter", ";;collisions passing selections", kTH1D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}}); + rQC.add("QC/collisions/hSelectionCounterPerRun", ";;run number;collisions passing selections", kTH2D, {{static_cast(collisionSelectionCounterLabels.size()), -0.5, static_cast(collisionSelectionCounterLabels.size()) - 0.5}, runNumberAxis}); + for (int i = 0; i < static_cast(collisionSelectionCounterLabels.size()); ++i) { + rQC.get(HIST("QC/collisions/hSelectionCounter"))->GetXaxis()->SetBinLabel(i + 1, collisionSelectionCounterLabels[i].c_str()); + rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetXaxis()->SetBinLabel(i + 1, collisionSelectionCounterLabels[i].c_str()); + } + for (int i = 0; i < static_cast(runNumbers.size()); ++i) + rQC.get(HIST("QC/collisions/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); + // tracks + rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC #it{n#sigma}(#pi);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC #it{n#sigma}(e);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC #it{n#sigma}(K);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hTpcNSigmaPr", ";TPC #it{n#sigma}(p);counts", kTH1D, {nSigmaAxis}); + rQC.add("QC/tracks/all/hDcaXYZ", ";track #it{DCA}_{z} (cm);track #it{DCA}_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {400, -2.0, 2.0}}); + rQC.add("QC/tracks/all/hItsNCls", ";ITS #it{N}_{cls};counts", kTH1D, {{9, -0.5, 8.5}}); + rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); + rQC.add("QC/tracks/all/hTpcChi2NCl", ";TPC #it{#chi}^{2}/#it{N}_{cls};counts", kTH1D, {{150, 0.0, 15.0}}); + rQC.add("QC/tracks/all/hTpcNCls", ";found TPC #it{N}_{cls};counts", kTH1D, {{160, 0.0, 160.0}}); // tpcNClsFindable() - track.tpcNClsFindableMinusFound + rQC.add("QC/tracks/all/hTpcNClsCrossedRows", ";TPC crossed rows;counts", kTH1D, {{160, 0.0, 160.0}}); + rQC.add("QC/tracks/all/hTpcNClsCrossedRowsOverNClsFindable", ";TPC crossed rows/findable #it{N}_{cls};counts", kTH1D, {{160, 0.6, 2.2}}); + rQC.add("QC/tracks/all/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + rQC.add("QC/tracks/all/hEta", ";#it{#eta};counts", kTH1D, {etaAxis}); + rQC.add("QC/tracks/all/hPhi", ";#it{#phi} (rad);counts", kTH1D, {phiAxis}); + rQC.add("QC/tracks/all/hTpcSignalVsP", ";|#it{p}| (GeV/#it{c});TPC d#it{E}/d#it{x} signal (arb. units);counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); + rQC.add("QC/tracks/all/hTpcSignalVsPt", ";#it{p}_{T} (GeV/#it{c});TPC d#it{E}/d#it{x} signal (arb. units);counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); + // tracks passing selections + rQC.addClone("QC/tracks/all/", "QC/tracks/trackSelections/"); + rQC.addClone("QC/tracks/all/", "QC/tracks/systemSelections/"); + rQC.add("QC/tracks/trackSelections/hRemainingTracks", ";remaining tracks;counts", kTH1D, {{21, -0.5, 20.5}}); + rQC.add("QC/tracks/trackSelections/hTpcNSigmaPi2D", ";TPC #it{n#sigma}(#pi)_{leading};TPC #it{n#sigma}(#pi)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); + rQC.add("QC/tracks/trackSelections/hTpcNSigmaEl2D", ";TPC #it{n#sigma}(e)_{leading};TPC #it{n#sigma}(e)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); + rQC.add("QC/tracks/trackSelections/hTpcNSigmaKa2D", ";TPC #it{n#sigma}(K)_{leading};TPC #it{n#sigma}(K)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); + rQC.add("QC/tracks/trackSelections/hTpcNSigmaPr2D", ";TPC #it{n#sigma}(p)_{leading};TPC #it{n#sigma}(p)_{subleading};counts", kTH2D, {nSigmaAxis, nSigmaAxis}); + // selection counter + std::vector trackSelectionCounterLabels = {"all tracks", "PV contributor", "ITS hit", "ITS #it{N}_{cls}", "itsClusterMap check", "ITS #it{#chi}^{2}/#it{N}_{cls}", "TPC hit", "found TPC #it{N}_{cls}", "TPC #it{#chi}^{2}/#it{N}_{cls}", "TPC crossed rows", + "TPC crossed rows/#it{N}_{cls}", + "TOF requirement", + "#it{p}_{T}", "#it{DCA}", "#it{#eta}", "exactly 2 tracks", "PID"}; + rQC.add("QC/tracks/hSelectionCounter", ";;tracks passing selections", kTH1D, {{static_cast(trackSelectionCounterLabels.size()), -0.5, static_cast(trackSelectionCounterLabels.size()) - 0.5}}); + rQC.add("QC/tracks/hSelectionCounterPerRun", ";;run number;tracks passing selections", kTH2D, {{static_cast(trackSelectionCounterLabels.size()), -0.5, static_cast(trackSelectionCounterLabels.size()) - 0.5}, runNumberAxis}); + for (int i = 0; i < static_cast(trackSelectionCounterLabels.size()); ++i) { + rQC.get(HIST("QC/tracks/hSelectionCounter"))->GetXaxis()->SetBinLabel(i + 1, trackSelectionCounterLabels[i].c_str()); + rQC.get(HIST("QC/tracks/hSelectionCounterPerRun"))->GetXaxis()->SetBinLabel(i + 1, trackSelectionCounterLabels[i].c_str()); + } + for (int i = 0; i < static_cast(runNumbers.size()); ++i) + rQC.get(HIST("QC/tracks/hSelectionCounterPerRun"))->GetYaxis()->SetBinLabel(i + 1, std::to_string(runNumbers[i]).c_str()); + + rQC.add("QC/tracks/hTofHitCheck", ";leading track TOF hit;subleading track TOF hit;counts", kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); + rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetXaxis()->SetBinLabel(1, "no hit"); + rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetXaxis()->SetBinLabel(2, "hit"); + rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetYaxis()->SetBinLabel(1, "no hit"); + rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetYaxis()->SetBinLabel(2, "hit"); + // PID "radii" plots + rQC.add("QC/tracks/hPiPIDRadius", ";#it{n#sigma}(#pi) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); + rQC.add("QC/tracks/hElPIDRadius", ";#it{n#sigma}(e) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); + rQC.add("QC/tracks/hKaPIDRadius", ";#it{n#sigma}(K) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); + rQC.add("QC/tracks/hPrPIDRadius", ";#it{n#sigma}(p) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); + + // TRACKS (2D) + rTracks.add("tracks/trackSelections/unlike-sign/hPt", ";#it{p}_{T leading} (GeV/#it{c});#it{p}_{T subleading} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + rTracks.add("tracks/trackSelections/unlike-sign/hEta", ";#it{#eta}_{leading};#it{#eta}_{subleading};counts", kTH2D, {etaAxis, etaAxis}); + rTracks.add("tracks/trackSelections/unlike-sign/hPhi", ";#it{#phi}_{leading} (rad);#it{#phi}_{subleading} (rad);counts", kTH2D, {phiAxis, phiAxis}); + rTracks.addClone("tracks/trackSelections/unlike-sign/", "tracks/trackSelections/like-sign/positive/"); + rTracks.addClone("tracks/trackSelections/unlike-sign/", "tracks/trackSelections/like-sign/negative/"); + rTracks.addClone("tracks/trackSelections/", "tracks/systemSelections/"); + + // SYSTEM + rSystem.add("system/all/unlike-sign/hM", ";#it{m} (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + rSystem.add("system/all/unlike-sign/hRecoSettingVsM", ";#it{m} (GeV/#it{c}^{2});reco setting;counts", kTH2D, {mAxis, {2, -0.5, 1.5}}); + rSystem.add("system/all/unlike-sign/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + rSystem.add("system/all/unlike-sign/hPt2", ";#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); + rSystem.add("system/all/unlike-sign/hPtVsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + rSystem.add("system/all/unlike-sign/hPt2VsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH2D, {mAxis, pt2Axis}); + rSystem.add("system/all/unlike-sign/hY", ";#it{y};counts", kTH1D, {yAxis}); + rSystem.add("system/all/unlike-sign/hPhi", ";#it{#phi} (rad);counts", kTH1D, {phiAxis}); + rSystem.add("system/all/unlike-sign/hPhiRandom", ";#Delta#it{#phi}_{random} (rad);counts", kTH1D, {deltaPhiAxis}); + rSystem.add("system/all/unlike-sign/hPhiCharge", ";#Delta#it{#phi}_{charge} (rad);counts", kTH1D, {deltaPhiAxis}); + rSystem.add("system/all/unlike-sign/hPhiRandomVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi}_{random} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); + rSystem.add("system/all/unlike-sign/hPhiChargeVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi}_{charge} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); + // clones for like-sign + rSystem.addClone("system/all/unlike-sign/", "system/all/like-sign/positive/"); + rSystem.addClone("system/all/unlike-sign/", "system/all/like-sign/negative/"); + // selected rhos + rSystem.addClone("system/all/", "system/selected/AnAn/"); + // clones for neutron classes + rSystem.addClone("system/selected/AnAn/", "system/selected/0n0n/"); + rSystem.addClone("system/selected/AnAn/", "system/selected/Xn0n/"); + rSystem.addClone("system/selected/AnAn/", "system/selected/0nXn/"); + rSystem.addClone("system/selected/AnAn/", "system/selected/XnXn/"); } - rQC.add("QC/tracks/hTofHitCheck", ";leading track TOF hit;subleading track TOF hit;counts", kTH2D, {{2, -0.5, 1.5}, {2, -0.5, 1.5}}); - rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetXaxis()->SetBinLabel(1, "no hit"); - rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetXaxis()->SetBinLabel(2, "hit"); - rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetYaxis()->SetBinLabel(1, "no hit"); - rQC.get(HIST("QC/tracks/hTofHitCheck"))->GetYaxis()->SetBinLabel(2, "hit"); - // PID "radii" plots - rQC.add("QC/tracks/hPiPIDRadius", ";#it{n#sigma}(#pi) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); - rQC.add("QC/tracks/hElPIDRadius", ";#it{n#sigma}(e) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); - rQC.add("QC/tracks/hKaPIDRadius", ";#it{n#sigma}(K) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); - rQC.add("QC/tracks/hPrPIDRadius", ";#it{n#sigma}(p) radius;counts", kTH1D, {{1000, 0.0, 10.0}}); - - // TRACKS (2D) - rTracks.add("tracks/trackSelections/unlike-sign/hPt", ";#it{p}_{T leading} (GeV/#it{c});#it{p}_{T subleading} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); - rTracks.add("tracks/trackSelections/unlike-sign/hEta", ";#it{#eta}_{leading};#it{#eta}_{subleading};counts", kTH2D, {etaAxis, etaAxis}); - rTracks.add("tracks/trackSelections/unlike-sign/hPhi", ";#it{#phi}_{leading} (rad);#it{#phi}_{subleading} (rad);counts", kTH2D, {phiAxis, phiAxis}); - rTracks.addClone("tracks/trackSelections/unlike-sign/", "tracks/trackSelections/like-sign/positive/"); - rTracks.addClone("tracks/trackSelections/unlike-sign/", "tracks/trackSelections/like-sign/negative/"); - rTracks.addClone("tracks/trackSelections/", "tracks/systemSelections/"); - - // SYSTEM - rSystem.add("system/all/unlike-sign/hM", ";#it{m} (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); - rSystem.add("system/all/unlike-sign/hRecoSettingVsM", ";#it{m} (GeV/#it{c}^{2});reco setting;counts", kTH2D, {mAxis, {2, -0.5, 1.5}}); - rSystem.add("system/all/unlike-sign/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); - rSystem.add("system/all/unlike-sign/hPt2", ";#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); - rSystem.add("system/all/unlike-sign/hPtVsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); - rSystem.add("system/all/unlike-sign/hY", ";#it{y};counts", kTH1D, {yAxis}); - rSystem.add("system/all/unlike-sign/hPhi", ";#it{#phi} (rad);counts", kTH1D, {phiAxis}); - rSystem.add("system/all/unlike-sign/hPhiRandom", ";#Delta#it{#phi}_{random} (rad);counts", kTH1D, {deltaPhiAxis}); - rSystem.add("system/all/unlike-sign/hPhiCharge", ";#Delta#it{#phi}_{charge} (rad);counts", kTH1D, {deltaPhiAxis}); - rSystem.add("system/all/unlike-sign/hPhiRandomVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi}_{random} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); - rSystem.add("system/all/unlike-sign/hPhiChargeVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi}_{charge} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); - // clones for like-sign - rSystem.addClone("system/all/unlike-sign/", "system/all/like-sign/positive/"); - rSystem.addClone("system/all/unlike-sign/", "system/all/like-sign/negative/"); - // selected rhos - rSystem.addClone("system/all/", "system/selected/AnAn/"); - // clones for neutron classes - rSystem.addClone("system/selected/AnAn/", "system/selected/0n0n/"); - rSystem.addClone("system/selected/AnAn/", "system/selected/Xn0n/"); - rSystem.addClone("system/selected/AnAn/", "system/selected/0nXn/"); - rSystem.addClone("system/selected/AnAn/", "system/selected/XnXn/"); if (context.mOptions.get("processMCdata") || context.mOptions.get("processMCdataWithBCs")) { // MC @@ -296,8 +378,6 @@ struct UpcRhoAnalysis { rMC.add("MC/collisions/hPosXY", ";vertex #it{x} (cm);vertex #it{y} (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); rMC.add("MC/collisions/hPosZ", ";vertex #it{z} (cm);counts", kTH1D, {{400, -20.0, 20.0}}); rMC.add("MC/collisions/hNPions", ";number of pions;counts", kTH1D, {{11, -0.5, 10.5}}); - if (context.mOptions.get("processCollisionRecoCheck")) - rMC.add("MC/collisions/hNumOfCollisionRecos", ";number of collision reconstructions;counts", kTH1D, {{6, -0.5, 5.5}}); // tracks rMC.add("MC/tracks/all/hPdgCode", ";pdg code;counts", kTH1D, {{2001, -1000.5, 1000.5}}); rMC.add("MC/tracks/all/hMotherPdgCode", ";mother pdg code;counts", kTH1D, {{2001, -1000.5, 1000.5}}); @@ -320,6 +400,7 @@ struct UpcRhoAnalysis { rMC.add("MC/system/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); rMC.add("MC/system/hPt2", ";#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); rMC.add("MC/system/hPtVsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); + rMC.add("MC/system/hPt2VsM", ";#it{m} (GeV/#it{c}^{2});#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH2D, {mAxis, pt2Axis}); rMC.add("MC/system/hY", ";#it{y};counts", kTH1D, {yAxis}); rMC.add("MC/system/hPhi", ";#it{#phi} (rad);counts", kTH1D, {phiAxis}); rMC.add("MC/system/hPhiRandom", ";#Delta#it{#phi}_{random} (rad);counts", kTH1D, {deltaPhiAxis}); @@ -328,6 +409,31 @@ struct UpcRhoAnalysis { rMC.add("MC/system/hPhiChargeVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi} (rad);counts", kTH2D, {mAxis, deltaPhiAxis}); rMC.addClone("MC/system/", "MC/system/selected/"); } + + if (context.mOptions.get("processCollisionRecoCheck")) + rMC.add("MC/collisions/hNumOfCollisionRecos", ";number of collision reconstructions;counts", kTH1D, {{6, -0.5, 5.5}}); + + if (context.mOptions.get("processResolution")) { + // collision matching + rResolution.add("MC/resolution/collisions/hMatch", ";matched;counts", kTH1D, {{2, -0.5, 1.5}}); + rResolution.add("MC/resolution/collisions/hPosX", ";vertex #it{x}_{reco} - vertex #it{x}_{true} (cm);counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/collisions/hPosY", ";vertex #it{y}_{reco} - vertex #it{y}_{true} (cm);counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/collisions/hPosZ", ";vertex #it{z}_{reco} - vertex #it{z}_{true} (cm);counts", kTH1D, {resolutionAxis}); + // track matching and resolutions + rResolution.add("MC/resolution/tracks/hMatch", ";matched;counts", kTH1D, {{2, -0.5, 1.5}}); + rResolution.add("MC/resolution/tracks/hPt", ";1/#it{p}_{T, reco} - 1/#it{p}_{T, true} (1/(GeV/#it{c}));counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/tracks/hEta", ";#it{#eta}_{reco} - #it{#eta}_{true};counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/tracks/hPhi", ";#it{#phi}_{reco} - #it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); + // dipion system resolutions (1D and 2D) + rResolution.add("MC/resolution/system/1D/hM", ";#it{m}_{reco} - #it{m}_{true} (GeV/#it{c}^{2});counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/system/2D/hMVsM", ";#it{m}_{true} (GeV/#it{c}^{2});#it{m}_{reco} (GeV/#it{c}^{2});counts", kTH2D, {mAxis, mAxis}); + rResolution.add("MC/resolution/system/1D/hPt", ";1/#it{p}_{T, reco} - 1/#it{p}_{T, true} (1/(GeV/#it{c}));counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/system/2D/hPtVsPt", ";1/#it{p}_{T, true} (GeV/#it{c});#it{p}_{T, reco} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + rResolution.add("MC/resolution/system/1D/hY", ";#it{y}_{reco} - #it{y}_{true};counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/system/2D/hYVsY", ";#it{y}_{true};#it{y}_{reco};counts", kTH2D, {yAxis, yAxis}); + rResolution.add("MC/resolution/system/1D/hDeltaPhi", ";#Delta#it{#phi}_{reco} - #Delta#it{#phi}_{true} (rad);counts", kTH1D, {resolutionAxis}); + rResolution.add("MC/resolution/system/2D/hDeltaPhiVsDeltaPhi", ";#Delta#it{#phi}_{true} (rad);#Delta#it{#phi}_{reco} (rad);counts", kTH2D, {deltaPhiAxis, deltaPhiAxis}); + } } static constexpr std::string_view AppliedSelections[3] = {"all/", "trackSelections/", "systemSelections/"}; @@ -341,6 +447,8 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hPosZ"), collision.posZ()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hZdcCommonEnergy"), collision.energyCommonZNA(), collision.energyCommonZNC()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hZdcTime"), collision.timeZNA(), collision.timeZNC()); + rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hZNTimeVsZNCommonEnergy"), collision.energyCommonZNA(), collision.timeZNA()); + rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hZNTimeVsZNCommonEnergy"), collision.energyCommonZNC(), collision.timeZNC()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hNumContrib"), collision.numContrib()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTotalFT0AmplitudeA"), collision.totalFT0AmplitudeA()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTotalFT0AmplitudeC"), collision.totalFT0AmplitudeC()); @@ -352,6 +460,7 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTimeFV0A"), collision.timeFV0A()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTimeFDDA"), collision.timeFDDA()); rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hTimeFDDC"), collision.timeFDDC()); + rQC.fill(HIST("QC/collisions/") + HIST(AppliedSelections[cuts]) + HIST("hOccupancyInTime"), collision.occupancyInTime()); } template @@ -363,6 +472,7 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPi"), track.tpcNSigmaPi()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaEl"), track.tpcNSigmaEl()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaKa"), track.tpcNSigmaKa()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNSigmaPr"), track.tpcNSigmaPr()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hDcaXYZ"), track.dcaZ(), track.dcaXY()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsNCls"), track.itsNCls()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hItsChi2NCl"), track.itsChi2NCl()); @@ -390,6 +500,7 @@ struct UpcRhoAnalysis { rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPt"), pt); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPt2"), pt * pt); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPtVsM"), mass, pt); + rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPt2VsM"), mass, pt * pt); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hY"), rapidity); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPhi"), phi); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPhiRandom"), phiRandom); @@ -401,6 +512,7 @@ struct UpcRhoAnalysis { rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt"), pt); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt2"), pt * pt); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPtVsM"), mass, pt); + rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt2VsM"), mass, pt * pt); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hY"), rapidity); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhi"), phi); rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhiRandom"), phiRandom); @@ -414,9 +526,9 @@ struct UpcRhoAnalysis { { std::vector>> requiredITSHits{}; requiredITSHits.push_back(std::make_pair(1, std::array{0, 1, 2})); // at least one hit in the innermost layer - constexpr uint8_t kBit = 1; + constexpr uint8_t KnBit = 1; for (const auto& itsRequirement : requiredITSHits) { - auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (kBit << requiredLayer); }); + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (KnBit << requiredLayer); }); if ((itsRequirement.first == -1) && (hits > 0)) { return false; // no hits were required in specified layers @@ -495,6 +607,13 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/collisions/hSelectionCounterPerRun"), 9, runIndex); } + if (cutOccupancy) { + if (collision.occupancyInTime() > occupancyCut) + return false; + rQC.fill(HIST("QC/collisions/hSelectionCounter"), 10); + rQC.fill(HIST("QC/collisions/hSelectionCounterPerRun"), 10, runIndex); + } + // if all selections passed return true; } @@ -698,7 +817,7 @@ struct UpcRhoAnalysis { if (selectRuns && getRunIndex(collision.runNumber(), selectedRuns) == 0) return; - fillCollisionQcHistos<0>(collision); // fill QC histograms before cuts + fillCollisionQcHistos<0>(collision); // fill QC histograms before cuts if (!collisionPassesCuts(collision, runIndex)) // apply collision cuts return; @@ -715,20 +834,19 @@ struct UpcRhoAnalysis { if (std::isinf(timeZNC)) timeZNC = -999; - if (energyCommonZNA <= znCommonEnergyCut && energyCommonZNC <= znCommonEnergyCut) { + if (std::abs(timeZNA) > znTimeCut && std::abs(timeZNC) > znTimeCut) { onon = true; neutronClass = 0; } - if (energyCommonZNA > znCommonEnergyCut && std::abs(timeZNA) <= znTimeCut && energyCommonZNC <= znCommonEnergyCut) { + if (std::abs(timeZNA) <= znTimeCut && std::abs(timeZNC) > znTimeCut) { xnon = true; neutronClass = 1; } - if (energyCommonZNA <= znCommonEnergyCut && energyCommonZNC > znCommonEnergyCut && std::abs(timeZNC) <= znTimeCut) { + if (std::abs(timeZNA) > znTimeCut && std::abs(timeZNC) <= znTimeCut) { onxn = true; neutronClass = 2; } - if (energyCommonZNA > znCommonEnergyCut && std::abs(timeZNA) <= znTimeCut && - energyCommonZNC > znCommonEnergyCut && std::abs(timeZNC) <= znTimeCut) { + if (std::abs(timeZNA) <= znTimeCut && std::abs(timeZNC) <= znTimeCut) { xnxn = true; neutronClass = 3; } @@ -743,9 +861,9 @@ struct UpcRhoAnalysis { } rQC.fill(HIST("QC/tracks/trackSelections/hRemainingTracks"), cutTracks.size()); - if (static_cast(cutTracks.size()) != numPions) // further consider only two pion systems + if (static_cast(cutTracks.size()) != nPions) // further consider only two pion systems return; - for (int i = 0; i < numPions; i++) { + for (int i = 0; i < nPions; i++) { rQC.fill(HIST("QC/tracks/hSelectionCounter"), 15); rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 15, runIndex); } @@ -774,7 +892,9 @@ struct UpcRhoAnalysis { float phiCharge = getPhiCharge(cutTracks, cutTracksLVs); // fill recoTree - recoTree(collision.flags(), collision.runNumber(), collision.posZ(), + recoTree(collision.flags(), collision.runNumber(), collision.posX(), collision.posY(), collision.posZ(), collision.occupancyInTime(), collision.hadronicRate(), collision.globalBC() % o2::constants::lhc::LHCMaxBunches, + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), collision.timeFDDA(), collision.timeFDDC(), energyCommonZNA, energyCommonZNC, timeZNA, timeZNC, neutronClass, leadingTrack.sign(), subleadingTrack.sign(), leadingPt, subleadingPt, @@ -926,7 +1046,7 @@ struct UpcRhoAnalysis { } rMC.fill(HIST("MC/collisions/hNPions"), cutMcParticles.size()); - if (static_cast(cutMcParticles.size()) != numPions) + if (static_cast(cutMcParticles.size()) != 2) return; if (mcParticlesLVs.size() != cutMcParticles.size()) // sanity check return; @@ -950,6 +1070,7 @@ struct UpcRhoAnalysis { rMC.fill(HIST("MC/system/hM"), mass); rMC.fill(HIST("MC/system/hPt"), pT); rMC.fill(HIST("MC/system/hPtVsM"), mass, pT); + rMC.fill(HIST("MC/system/hPt2VsM"), mass, pT * pT); rMC.fill(HIST("MC/system/hPt2"), pT * pT); rMC.fill(HIST("MC/system/hY"), rapidity); rMC.fill(HIST("MC/system/hPhi"), systemPhi); @@ -972,7 +1093,7 @@ struct UpcRhoAnalysis { } // fill mcTree - mcTree(runNumber, mcCollision.posZ(), + mcTree(runNumber, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.globalBC() % o2::constants::lhc::LHCMaxBunches, leadingPion.pdgCode() / std::abs(leadingPion.pdgCode()), subleadingPion.pdgCode() / std::abs(subleadingPion.pdgCode()), pt(leadingPion.px(), leadingPion.py()), pt(subleadingPion.px(), subleadingPion.py()), eta(leadingPion.px(), leadingPion.py(), leadingPion.pz()), eta(subleadingPion.px(), subleadingPion.py(), subleadingPion.pz()), @@ -1029,6 +1150,69 @@ struct UpcRhoAnalysis { } PROCESS_SWITCH(UpcRhoAnalysis, processMCdataWithBCs, "analyse MC data with BCs (only with on-the-fly skimming)", false); + void processResolution(soa::Join::iterator const& collision, soa::Join const& tracks, aod::UDMcCollisions const&, aod::UDMcParticles const&) + { + rResolution.fill(HIST("MC/resolution/collisions/hMatch"), 0); + if (!collision.has_udMcCollision()) + return; + rResolution.fill(HIST("MC/resolution/collisions/hMatch"), 1); + auto mcCollision = collision.udMcCollision(); + rResolution.fill(HIST("MC/resolution/collisions/hPosX"), collision.posX() - mcCollision.posX()); + rResolution.fill(HIST("MC/resolution/collisions/hPosY"), collision.posY() - mcCollision.posY()); + rResolution.fill(HIST("MC/resolution/collisions/hPosZ"), collision.posZ() - mcCollision.posZ()); + + std::vector trueTracks; + std::vector recoTracks; + std::vector truePionLVs, recoPionLVs; + + for (const auto& track : tracks) { + rResolution.fill(HIST("MC/resolution/tracks/hMatch"), 0); + if (!track.has_udMcParticle()) + continue; + rResolution.fill(HIST("MC/resolution/tracks/hMatch"), 1); + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) != kPiPlus && !mcParticle.isPhysicalPrimary()) + continue; + rResolution.fill(HIST("MC/resolution/tracks/hPt"), 1.0 / pt(track.px(), track.py()) - 1.0 / pt(mcParticle.px(), mcParticle.py())); + rResolution.fill(HIST("MC/resolution/tracks/hEta"), eta(track.px(), track.py(), track.pz()) - eta(mcParticle.px(), mcParticle.py(), mcParticle.pz())); + rResolution.fill(HIST("MC/resolution/tracks/hPhi"), phi(track.px(), track.py()) - phi(mcParticle.px(), mcParticle.py())); + truePionLVs.push_back(ROOT::Math::PxPyPzMVector(mcParticle.px(), mcParticle.py(), mcParticle.pz(), o2::constants::physics::MassPionCharged)); + trueTracks.push_back(mcParticle); + recoPionLVs.push_back(ROOT::Math::PxPyPzMVector(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged)); + recoTracks.push_back(track); + } + + if (truePionLVs.size() != 2 || recoPionLVs.size() != 2) + return; + + ROOT::Math::PxPyPzMVector trueSystem = reconstructSystem(truePionLVs); + const float trueDeltaPhi = getPhiChargeMC(trueTracks, truePionLVs); + ROOT::Math::PxPyPzMVector recoSystem = reconstructSystem(recoPionLVs); + const float recoDeltaPhi = getPhiCharge(recoTracks, recoPionLVs); + + rResolution.fill(HIST("MC/resolution/system/1D/hM"), recoSystem.M() - trueSystem.M()); + rResolution.fill(HIST("MC/resolution/system/2D/hMVsM"), trueSystem.M(), recoSystem.M()); + rResolution.fill(HIST("MC/resolution/system/1D/hPt"), 1.0 / recoSystem.Pt() - 1.0 / trueSystem.Pt()); + rResolution.fill(HIST("MC/resolution/system/2D/hPtVsPt"), trueSystem.Pt(), recoSystem.Pt()); + rResolution.fill(HIST("MC/resolution/system/1D/hY"), recoSystem.Rapidity() - trueSystem.Rapidity()); + rResolution.fill(HIST("MC/resolution/system/2D/hYVsY"), trueSystem.Rapidity(), recoSystem.Rapidity()); + rResolution.fill(HIST("MC/resolution/system/1D/hDeltaPhi"), recoDeltaPhi - trueDeltaPhi); + rResolution.fill(HIST("MC/resolution/system/2D/hDeltaPhiVsDeltaPhi"), trueDeltaPhi, recoDeltaPhi); + + auto leadingTruePion = momentum(trueTracks[0].px(), trueTracks[0].py(), trueTracks[0].pz()) > momentum(trueTracks[1].px(), trueTracks[1].py(), trueTracks[1].pz()) ? trueTracks[0] : trueTracks[1]; + auto subleadingTruePion = (leadingTruePion == trueTracks[0]) ? trueTracks[1] : trueTracks[0]; + auto leadingRecoPion = momentum(recoTracks[0].px(), recoTracks[0].py(), recoTracks[0].pz()) > momentum(recoTracks[1].px(), recoTracks[1].py(), recoTracks[1].pz()) ? recoTracks[0] : recoTracks[1]; + auto subleadingRecoPion = (leadingRecoPion == recoTracks[0]) ? recoTracks[1] : recoTracks[0]; + + resolutionTree(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), + collision.posX(), collision.posY(), collision.posZ(), + leadingTruePion.pdgCode() / std::abs(leadingTruePion.pdgCode()), pt(leadingTruePion.px(), leadingTruePion.py()), eta(leadingTruePion.px(), leadingTruePion.py(), leadingTruePion.pz()), phi(leadingTruePion.px(), leadingTruePion.py()), + pt(leadingRecoPion.px(), leadingRecoPion.py()), eta(leadingRecoPion.px(), leadingRecoPion.py(), leadingRecoPion.pz()), phi(leadingRecoPion.px(), leadingRecoPion.py()), + subleadingTruePion.pdgCode() / std::abs(subleadingTruePion.pdgCode()), pt(subleadingTruePion.px(), subleadingTruePion.py()), eta(subleadingTruePion.px(), subleadingTruePion.py(), subleadingTruePion.pz()), phi(subleadingTruePion.px(), subleadingTruePion.py()), + pt(subleadingRecoPion.px(), subleadingRecoPion.py()), eta(subleadingRecoPion.px(), subleadingRecoPion.py(), subleadingRecoPion.pz()), phi(subleadingRecoPion.px(), subleadingRecoPion.py())); + } + PROCESS_SWITCH(UpcRhoAnalysis, processResolution, "check resolution of kinematic variables", false); + void processCollisionRecoCheck(aod::UDMcCollision const& /* mcCollision */, soa::SmallGroups> const& collisions) { checkNumberOfCollisionReconstructions(collisions); diff --git a/PWGUD/Tasks/upcRhoPrimeAnalysis.cxx b/PWGUD/Tasks/upcRhoPrimeAnalysis.cxx index f8f03970ff0..703f0989283 100644 --- a/PWGUD/Tasks/upcRhoPrimeAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoPrimeAnalysis.cxx @@ -15,16 +15,25 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/UDTables.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Math/Vector4D.h" -#include "TH1F.h" -#include "TH2F.h" - -#include "random" -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include + +#include +#include +#include +#include #include #include diff --git a/PWGUD/Tasks/upcTauRl.cxx b/PWGUD/Tasks/upcTauRl.cxx index 78e9f7b48ae..264dae05eb8 100644 --- a/PWGUD/Tasks/upcTauRl.cxx +++ b/PWGUD/Tasks/upcTauRl.cxx @@ -16,35 +16,35 @@ /// \since 12.07.2022 // -// C++ headers -#include -#include -#include -#include -#include - -// O2 headers -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -// O2Physics headers #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/UDTables.h" -#include "Common/CCDB/EventSelectionParams.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include -// ROOT headers -#include "Math/Vector4D.h" -#include "TPDGCode.h" +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/upcTauTau13topo.cxx b/PWGUD/Tasks/upcTauTau13topo.cxx index d2dd61ade0c..a14ebd9cb35 100644 --- a/PWGUD/Tasks/upcTauTau13topo.cxx +++ b/PWGUD/Tasks/upcTauTau13topo.cxx @@ -17,27 +17,35 @@ // copts="--configuration json://tautauConfig.json -b" // o2-analysis-ud-tautau13topo $copts > output.log -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -// #include "TDatabasePDG.h" // not recommended in o2 -#include "Framework/O2DatabasePDGPlugin.h" - -// #include "TLorentzVector.h" -#include "Math/Vector4D.h" -// #include "Common/DataModel/EventSelection.h" -// #include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGUD/Core/DGPIDSelector.h" #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/DataModel/UDTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/PIDResponseTPC.h" -// #include -#include "TPDGCode.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGUD/Tasks/upcTestFITBitMapping.cxx b/PWGUD/Tasks/upcTestFITBitMapping.cxx new file mode 100644 index 00000000000..eefd4f0aa83 --- /dev/null +++ b/PWGUD/Tasks/upcTestFITBitMapping.cxx @@ -0,0 +1,119 @@ +// 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. +// +// \FIT bits to phi, eta mapping +// \author Sandor Lokos, sandor.lokos@cern.ch +// \since March 2026 + +#include "PWGUD/Core/UDHelpers.h" // udhelpers::Bits256, makeBits256, testBit, getPhiEtaFromFitBit +#include "PWGUD/DataModel/UDTables.h" // aod::UDCollisionFITBits + +#include // o2::ft0::Geometry +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; + +struct UpcTestFITBitMapping { + Configurable whichThr{"whichThr", 1, "Use 1=Thr1 bits or 2=Thr2 bits"}; + Configurable maxEvents{"maxEvents", -1, "Process at most this many rows (-1 = all)"}; + + // Minimal offset container compatible with UDHelpers.h expectations: getX/getY/getZ + struct OffsetXYZ { + double x{0}, y{0}, z{0}; + double getX() const { return x; } + double getY() const { return y; } + double getZ() const { return z; } + }; + + std::array offsetFT0{}; // iRunOffset = 0 for now + int iRunOffset = 0; + + o2::ft0::Geometry ft0Det{}; + + HistogramRegistry registry{ + "registry", + { + {"hPhiA", "FT0A #varphi;#varphi;counts", {HistType::kTH1F, {{18, 0.0, 2. * M_PI}}}}, + {"hEtaA", "FT0A #eta;#eta;counts", {HistType::kTH1F, {{8, 3.5, 5.0}}}}, + {"hEtaPhiA", "FT0A #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{8, 3.5, 5.0}, {18, 0.0, 2. * M_PI}}}}, + + {"hPhiC", "FT0C #varphi;#varphi;counts", {HistType::kTH1F, {{18, 0.0, 2. * M_PI}}}}, + {"hEtaC", "FT0C #eta;#eta;counts", {HistType::kTH1F, {{8, -3.5, -2.0}}}}, + {"hEtaPhiC", "FT0C #eta vs #varphi;#eta;#varphi", {HistType::kTH2F, {{8, -3.5, -2.0}, {18, 0.0, 2. * M_PI}}}}, + }}; + + void init(InitContext&) + { + // UDHelpers calls calculateChannelCenter() inside, but doing it once here is fine. + ft0Det.calculateChannelCenter(); + } + + void process(aod::UDCollisionFITBits const& bitsTable) + { + int64_t nProcessed = 0; + + for (auto const& row : bitsTable) { + if (maxEvents >= 0 && nProcessed >= maxEvents) { + break; + } + ++nProcessed; + + // Use udhelpers' canonical packed type + builder + udhelpers::Bits256 w{}; + if (whichThr == 2) { + w = udhelpers::makeBits256(row.thr2W0(), row.thr2W1(), row.thr2W2(), row.thr2W3()); + } else { + w = udhelpers::makeBits256(row.thr1W0(), row.thr1W1(), row.thr1W2(), row.thr1W3()); + } + + // Loop FT0 bits only (0..207). FV0 starts at 208 but ignored here. + for (int bit = 0; bit < udhelpers::kFT0Bits; ++bit) { + if (!udhelpers::testBit(w, bit)) { + continue; + } + + double phi = 0., eta = 0.; + const bool ok = udhelpers::getPhiEtaFromFitBit(ft0Det, bit, offsetFT0, iRunOffset, phi, eta); + if (!ok) { + continue; + } + + if (bit < udhelpers::kFT0AChannels) { + registry.fill(HIST("hPhiA"), phi); + registry.fill(HIST("hEtaA"), eta); + registry.fill(HIST("hEtaPhiA"), eta, phi); + } else { + registry.fill(HIST("hPhiC"), phi); + registry.fill(HIST("hEtaC"), eta); + registry.fill(HIST("hEtaPhiC"), eta, phi); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"fitbit-mapping"})}; +} diff --git a/PWGUD/Tasks/upcTestRctTables.cxx b/PWGUD/Tasks/upcTestRctTables.cxx index 5f6d1bd8db1..2e70f5c2a1a 100644 --- a/PWGUD/Tasks/upcTestRctTables.cxx +++ b/PWGUD/Tasks/upcTestRctTables.cxx @@ -16,18 +16,21 @@ /// \since 27.06.2025 // -// O2 headers -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -// O2Physics headers #include "PWGUD/Core/SGSelector.h" #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" #include "PWGUD/DataModel/UDTables.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGUD/Tasks/upcVetoAnalysis.cxx b/PWGUD/Tasks/upcVetoAnalysis.cxx index 45b3844ed51..fab4246a0f7 100644 --- a/PWGUD/Tasks/upcVetoAnalysis.cxx +++ b/PWGUD/Tasks/upcVetoAnalysis.cxx @@ -8,21 +8,40 @@ // 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include #include +#include +#include #include +#include #include #include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/LHCConstants.h" -#include "DataFormatsFIT/Triggers.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/GRPECSObject.h" using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/Tools/KFparticle/KFUtilities.h b/Tools/KFparticle/KFUtilities.h index bec24fd7adc..b6c6e607a9b 100644 --- a/Tools/KFparticle/KFUtilities.h +++ b/Tools/KFparticle/KFUtilities.h @@ -19,19 +19,19 @@ #define TOOLS_KFPARTICLE_KFUTILITIES_H_ #ifndef HomogeneousField -#define HomogeneousField +#define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include #include +#include #include #include #include -#include // FIXME - #include #include #include @@ -43,6 +43,12 @@ #include #include +constexpr float ArbitrarySmallNumber{1e-8f}; +constexpr float ArbitraryHugeNumber{1e8f}; +constexpr float UndefLdLValue{9999.f}; +constexpr int NumberOfMomentumComponents{3}; +constexpr int NumberOfCovMatrixComponents{21}; + /// @brief Function to create a KFPVertex from the collision table in the AO2Ds. /// The Multiplicity table is required to set the number of real PV Contributors /// This function works only for Run 3 data. @@ -70,24 +76,20 @@ KFPTrack createKFPTrack(const o2::track::TrackParametrizationWithError& t int16_t tpcNClsFound, float tpcChi2NCl) { - std::array trkpos_par; - std::array trkmom_par; - std::array trk_cov; - trackparCov.getXYZGlo(trkpos_par); - trackparCov.getPxPyPzGlo(trkmom_par); - trackparCov.getCovXYZPxPyPzGlo(trk_cov); - float trkpar_KF[6] = {trkpos_par[0], trkpos_par[1], trkpos_par[2], - trkmom_par[0], trkmom_par[1], trkmom_par[2]}; - float trkcov_KF[21]; - for (int i = 0; i < 21; i++) { - trkcov_KF[i] = trk_cov[i]; - } + std::array trkPositionPar{}; + std::array trkMomentumPar{}; + std::array trkCovMatrix{}; + trackparCov.getXYZGlo(trkPositionPar); + trackparCov.getPxPyPzGlo(trkMomentumPar); + trackparCov.getCovXYZPxPyPzGlo(trkCovMatrix); + const float trkParKf[6] = {trkPositionPar[0], trkPositionPar[1], trkPositionPar[2], + trkMomentumPar[0], trkMomentumPar[1], trkMomentumPar[2]}; KFPTrack kfpTrack; - kfpTrack.SetParameters(trkpar_KF); - kfpTrack.SetCovarianceMatrix(trkcov_KF); + kfpTrack.SetParameters(trkParKf); + kfpTrack.SetCovarianceMatrix(trkCovMatrix.data()); kfpTrack.SetCharge(trackSign); kfpTrack.SetNDF(tpcNClsFound - 5); - kfpTrack.SetChi2(tpcNClsFound * tpcChi2NCl); + kfpTrack.SetChi2(static_cast(tpcNClsFound) * tpcChi2NCl); return kfpTrack; } @@ -130,12 +132,12 @@ KFParticle createKFParticleFromTrackParCov(const o2::track::TrackParametrization float xyzpxpypz[6]; trackparCov.getPxPyPzGlo(pxpypz); trackparCov.getXYZGlo(xyz); - for (int i{0}; i < 3; ++i) { + for (int i{0}; i < NumberOfMomentumComponents; ++i) { xyzpxpypz[i] = xyz[i]; xyzpxpypz[i + 3] = pxpypz[i]; } - std::array cv; + std::array cv{}; try { trackparCov.getCovXYZPxPyPzGlo(cv); } catch (std::runtime_error& e) { @@ -143,9 +145,9 @@ KFParticle createKFParticleFromTrackParCov(const o2::track::TrackParametrization } KFParticle kfPart; - float Mini, SigmaMini, M, SigmaM; - kfPart.GetMass(Mini, SigmaMini); - LOG(debug) << "Daughter KFParticle mass before creation: " << Mini << " +- " << SigmaMini; + float mInit{}, sigmaMInit{}, m{}, sigmaM{}; + kfPart.GetMass(mInit, sigmaMInit); + LOG(debug) << "Daughter KFParticle mass before creation: " << mInit << " +- " << sigmaMInit; try { kfPart.Create(xyzpxpypz, cv.data(), charge, mass); @@ -153,8 +155,8 @@ KFParticle createKFParticleFromTrackParCov(const o2::track::TrackParametrization LOG(debug) << "Failed to create KFParticle from daughter TrackParCov" << e.what(); } - kfPart.GetMass(M, SigmaM); - LOG(debug) << "Daughter KFParticle mass after creation: " << M << " +- " << SigmaM; + kfPart.GetMass(m, sigmaM); + LOG(debug) << "Daughter KFParticle mass after creation: " << m << " +- " << sigmaM; return kfPart; } @@ -165,8 +167,8 @@ KFParticle createKFParticleFromTrackParCov(const o2::track::TrackParametrization /// @return o2::track::TrackParametrizationWithError track o2::track::TrackParCov getTrackParCovFromKFP(const KFParticle& kfParticle, const o2::track::PID pid, const int sign) { - std::array xyz, pxpypz; - std::array cv; + std::array xyz{}, pxpypz{}; + std::array cv{}; // get parameters from kfParticle xyz[0] = kfParticle.GetX(); @@ -177,7 +179,7 @@ o2::track::TrackParCov getTrackParCovFromKFP(const KFParticle& kfParticle, const pxpypz[2] = kfParticle.GetPz(); // set covariance matrix elements (lower triangle) - for (int i = 0; i < 21; i++) { + for (int i = 0; i < NumberOfCovMatrixComponents; i++) { cv[i] = kfParticle.GetCovariance(i); } @@ -192,7 +194,7 @@ o2::track::TrackParCov getTrackParCovFromKFP(const KFParticle& kfParticle, const /// @return cpa float cpaFromKF(KFParticle kfp, KFParticle PV) { - float xVtxP, yVtxP, zVtxP, xVtxS, yVtxS, zVtxS, px, py, pz = 0.; + float xVtxP{}, yVtxP{}, zVtxP{}, xVtxS{}, yVtxS{}, zVtxS{}, px{}, py{}, pz{}; xVtxP = PV.GetX(); yVtxP = PV.GetY(); @@ -206,7 +208,7 @@ float cpaFromKF(KFParticle kfp, KFParticle PV) py = kfp.GetPy(); pz = kfp.GetPz(); - float cpa = RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); + const float cpa = static_cast(RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz})); return cpa; } @@ -216,7 +218,7 @@ float cpaFromKF(KFParticle kfp, KFParticle PV) /// @return cpa in xy float cpaXYFromKF(KFParticle kfp, KFParticle PV) { - float xVtxP, yVtxP, xVtxS, yVtxS, px, py = 0.; + float xVtxP{}, yVtxP{}, xVtxS{}, yVtxS{}, px{}, py{}; xVtxP = PV.GetX(); yVtxP = PV.GetY(); @@ -227,7 +229,7 @@ float cpaXYFromKF(KFParticle kfp, KFParticle PV) px = kfp.GetPx(); py = kfp.GetPy(); - float cpaXY = RecoDecay::cpaXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{px, py}); + const float cpaXY = static_cast(RecoDecay::cpaXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{px, py})); return cpaXY; } @@ -239,10 +241,11 @@ float cpaXYFromKF(KFParticle kfp, KFParticle PV) /// @param kfpvtx KFPartice mother /// @param kfpprong0 KFParticle Prong 0 /// @param kfpprong1 KFParticele Prong 1 +/// @param pdgdb Service PDG data base /// @return cos theta star -float cosThetaStarFromKF(int ip, int pdgvtx, int pdgprong0, int pdgprong1, KFParticle kfpprong0, KFParticle kfpprong1) +float cosThetaStarFromKF(int iProng, int pdgvtx, int pdgprong0, int pdgprong1, KFParticle kfpprong0, KFParticle kfpprong1, const o2::framework::Service& pdgdb) { - float px0, py0, pz0, px1, py1, pz1 = 0.; + float px0{}, py0{}, pz0{}, px1{}, py1{}, pz1{}; px0 = kfpprong0.GetPx(); py0 = kfpprong0.GetPy(); @@ -252,12 +255,11 @@ float cosThetaStarFromKF(int ip, int pdgvtx, int pdgprong0, int pdgprong1, KFPar py1 = kfpprong1.GetPy(); pz1 = kfpprong1.GetPz(); std::array m = {0., 0.}; - m[0] = TDatabasePDG::Instance()->GetParticle(pdgprong0)->Mass(); // FIXME: Get from the PDG service of the common header - m[1] = TDatabasePDG::Instance()->GetParticle(pdgprong1)->Mass(); // FIXME: Get from the PDG service of the common header - double mTot = TDatabasePDG::Instance()->GetParticle(pdgvtx)->Mass(); // FIXME: Get from the PDG service of the common header - int iProng = ip; + m[0] = pdgdb->Mass(pdgprong0); + m[1] = pdgdb->Mass(pdgprong1); + const double mTot = pdgdb->Mass(pdgvtx); - float cosThetastar = RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m, mTot, iProng); + const float cosThetastar = static_cast(RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m, mTot, iProng)); return cosThetastar; } @@ -269,7 +271,7 @@ float cosThetaStarFromKF(int ip, int pdgvtx, int pdgprong0, int pdgprong1, KFPar /// @return impact parameter float impParXYFromKF(KFParticle kfpParticle, KFParticle Vertex) { - float xVtxP, yVtxP, zVtxP, xVtxS, yVtxS, zVtxS, px, py, pz = 0.; + float xVtxP{}, yVtxP{}, zVtxP{}, xVtxS{}, yVtxS{}, zVtxS{}, px{}, py{}, pz{}; xVtxP = Vertex.GetX(); yVtxP = Vertex.GetY(); @@ -283,7 +285,7 @@ float impParXYFromKF(KFParticle kfpParticle, KFParticle Vertex) py = kfpParticle.GetPy(); pz = kfpParticle.GetPz(); - float impParXY = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); + const float impParXY = static_cast(RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz})); return impParXY; } @@ -293,17 +295,17 @@ float impParXYFromKF(KFParticle kfpParticle, KFParticle Vertex) /// @return l/delta l float ldlFromKF(KFParticle kfpParticle, KFParticle PV) { - float dx_particle = PV.GetX() - kfpParticle.GetX(); - float dy_particle = PV.GetY() - kfpParticle.GetY(); - float dz_particle = PV.GetZ() - kfpParticle.GetZ(); - float l_particle = sqrt(dx_particle * dx_particle + dy_particle * dy_particle + dz_particle * dz_particle); - float dl_particle = (PV.GetCovariance(0) + kfpParticle.GetCovariance(0)) * dx_particle * dx_particle + (PV.GetCovariance(2) + kfpParticle.GetCovariance(2)) * dy_particle * dy_particle + (PV.GetCovariance(5) + kfpParticle.GetCovariance(5)) * dz_particle * dz_particle + 2 * ((PV.GetCovariance(1) + kfpParticle.GetCovariance(1)) * dx_particle * dy_particle + (PV.GetCovariance(3) + kfpParticle.GetCovariance(3)) * dx_particle * dz_particle + (PV.GetCovariance(4) + kfpParticle.GetCovariance(4)) * dy_particle * dz_particle); - if (fabs(l_particle) < 1.e-8f) - l_particle = 1.e-8f; - dl_particle = dl_particle < 0. ? 1.e8f : sqrt(dl_particle) / l_particle; - if (dl_particle == 0.) - return 9999.; - return l_particle / dl_particle; + const float dxParticle = PV.GetX() - kfpParticle.GetX(); + const float dyParticle = PV.GetY() - kfpParticle.GetY(); + const float dzParticle = PV.GetZ() - kfpParticle.GetZ(); + float lParticle = std::hypot(dxParticle, dyParticle, dzParticle); + float dlParticle = (PV.GetCovariance(0) + kfpParticle.GetCovariance(0)) * dxParticle * dxParticle + (PV.GetCovariance(2) + kfpParticle.GetCovariance(2)) * dyParticle * dyParticle + (PV.GetCovariance(5) + kfpParticle.GetCovariance(5)) * dzParticle * dzParticle + 2 * ((PV.GetCovariance(1) + kfpParticle.GetCovariance(1)) * dxParticle * dyParticle + (PV.GetCovariance(3) + kfpParticle.GetCovariance(3)) * dxParticle * dzParticle + (PV.GetCovariance(4) + kfpParticle.GetCovariance(4)) * dyParticle * dzParticle); + if (std::fabs(lParticle) < ArbitrarySmallNumber) + lParticle = ArbitrarySmallNumber; + dlParticle = dlParticle < 0.f ? ArbitraryHugeNumber : std::sqrt(dlParticle) / lParticle; + if (dlParticle == 0.) + return UndefLdLValue; + return lParticle / dlParticle; } /// @brief distance between production vertex and decay vertex normalised by the uncertainty in xy plane @@ -312,16 +314,16 @@ float ldlFromKF(KFParticle kfpParticle, KFParticle PV) /// @return l/delta l in xy plane float ldlXYFromKF(KFParticle kfpParticle, KFParticle PV) { - float dx_particle = PV.GetX() - kfpParticle.GetX(); - float dy_particle = PV.GetY() - kfpParticle.GetY(); - float l_particle = sqrt(dx_particle * dx_particle + dy_particle * dy_particle); - float dl_particle = (PV.GetCovariance(0) + kfpParticle.GetCovariance(0)) * dx_particle * dx_particle + (PV.GetCovariance(2) + kfpParticle.GetCovariance(2)) * dy_particle * dy_particle + 2 * ((PV.GetCovariance(1) + kfpParticle.GetCovariance(1)) * dx_particle * dy_particle); - if (fabs(l_particle) < 1.e-8f) - l_particle = 1.e-8f; - dl_particle = dl_particle < 0. ? 1.e8f : sqrt(dl_particle) / l_particle; - if (dl_particle == 0.) - return 9999.; - return l_particle / dl_particle; + const float dxParticle = PV.GetX() - kfpParticle.GetX(); + const float dyParticle = PV.GetY() - kfpParticle.GetY(); + float lParticle = std::hypot(dxParticle, dyParticle); + float dlParticle = (PV.GetCovariance(0) + kfpParticle.GetCovariance(0)) * dxParticle * dxParticle + (PV.GetCovariance(2) + kfpParticle.GetCovariance(2)) * dyParticle * dyParticle + 2 * ((PV.GetCovariance(1) + kfpParticle.GetCovariance(1)) * dxParticle * dyParticle); + if (std::fabs(lParticle) < ArbitrarySmallNumber) + lParticle = ArbitrarySmallNumber; + dlParticle = dlParticle < 0.f ? ArbitraryHugeNumber : std::sqrt(dlParticle) / lParticle; + if (dlParticle == 0.) + return UndefLdLValue; + return lParticle / dlParticle; } /// @brief squared distance between track and primary vertex normalised by its uncertainty evaluated in matrix form @@ -330,9 +332,9 @@ float ldlXYFromKF(KFParticle kfpParticle, KFParticle PV) /// @return chi2 to primary vertex float kfCalculateChi2ToPrimaryVertex(KFParticle track, const KFParticle& vtx) { - const float PvPoint[3] = {vtx.X(), vtx.Y(), vtx.Z()}; + const float pvPoint[3] = {vtx.X(), vtx.Y(), vtx.Z()}; - track.TransportToPoint(PvPoint); + track.TransportToPoint(pvPoint); return track.GetDeviationFromVertex(vtx); } @@ -342,9 +344,9 @@ float kfCalculateChi2ToPrimaryVertex(KFParticle track, const KFParticle& vtx) /// @return array with components of prong's momentum in the secondary (decay) vertex std::array kfCalculateProngMomentumInSecondaryVertex(KFParticle track, const KFParticle& vtx) { - const float SvPoint[3] = {vtx.X(), vtx.Y(), vtx.Z()}; + const float svPoint[3] = {vtx.X(), vtx.Y(), vtx.Z()}; - track.TransportToPoint(SvPoint); + track.TransportToPoint(svPoint); return {track.GetPx(), track.GetPy(), track.GetPz()}; } @@ -364,7 +366,7 @@ float kfCalculateDistanceBetweenParticles(KFParticle track1, KFParticle track2) const float dx = params1[0] - params2[0]; const float dy = params1[1] - params2[1]; const float dz = params1[2] - params2[2]; - return std::sqrt(dx * dx + dy * dy + dz * dz); + return std::hypot(dx, dy, dz); } /// @brief squared distance between two tracks normalised by its uncertainty evaluated in matrix form @@ -374,11 +376,11 @@ float kfCalculateDistanceBetweenParticles(KFParticle track1, KFParticle track2) float kfCalculateChi2geoBetweenParticles(KFParticle track1, KFParticle track2) { KFParticle kfPair; - const KFParticle* kfDaughters[3] = {&track1, &track2}; + const KFParticle* kfDaughters[2] = {&track1, &track2}; kfPair.SetConstructMethod(2); kfPair.Construct(kfDaughters, 2); - return kfPair.Chi2() / kfPair.NDF(); + return kfPair.Chi2() / static_cast(kfPair.NDF()); } /// @brief signed distance between primary and secondary vertex and its uncertainty, cm @@ -387,7 +389,7 @@ float kfCalculateChi2geoBetweenParticles(KFParticle track1, KFParticle track2) /// @return pair of l and delta l std::pair kfCalculateLdL(KFParticle candidate, const KFParticle& vtx) { - float l, dl; + float l{}, dl{}; candidate.SetProductionVertex(vtx); candidate.KFParticleBase::GetDecayLength(l, dl); @@ -400,7 +402,7 @@ std::pair kfCalculateLdL(KFParticle candidate, const KFParticle& v /// @return pair of impact parameter and its error std::pair kfCalculateImpactParameterZ(const KFParticle& candidate, const KFParticle& vtx) { - float distanceToVertexXY, errDistanceToVertexXY; + float distanceToVertexXY{}, errDistanceToVertexXY{}; candidate.GetDistanceFromVertexXY(vtx, distanceToVertexXY, errDistanceToVertexXY); const float distanceToVertex = candidate.GetDistanceFromVertex(vtx); const float chi2ToVertex = candidate.GetDeviationFromVertex(vtx); diff --git a/Tools/KFparticle/qaKFEventTrack.cxx b/Tools/KFparticle/qaKFEventTrack.cxx index f3f026a8da7..2242de51154 100644 --- a/Tools/KFparticle/qaKFEventTrack.cxx +++ b/Tools/KFparticle/qaKFEventTrack.cxx @@ -15,47 +15,42 @@ /// \brief Task to test the performance of the KFParticle package /// +#ifndef HomogeneousField +#define HomogeneousField +#endif + #include "Tools/KFparticle/qaKFEventTrack.h" -#include -#include -#include "TableHelper.h" -#include -using namespace std; -/// includes O2 -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" - -/// includes O2Physics #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Tools/KFparticle/KFUtilities.h" -/// includes KFParticle -#include "KFParticle.h" -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFParticleBase.h" -#include "KFVertex.h" - -#ifndef HomogeneousField - -#define HomogeneousField - -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +using namespace std; using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/Tools/KFparticle/qaKFEventTrack.h b/Tools/KFparticle/qaKFEventTrack.h index 399a3139a91..51f505a435e 100644 --- a/Tools/KFparticle/qaKFEventTrack.h +++ b/Tools/KFparticle/qaKFEventTrack.h @@ -15,9 +15,11 @@ #ifndef TOOLS_KFPARTICLE_QAKFEVENTTRACK_H_ #define TOOLS_KFPARTICLE_QAKFEVENTTRACK_H_ -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/Core/trackUtilities.h" +#include + +#include + +#include enum FlagsTracks { kITS = BIT(0), diff --git a/Tools/KFparticle/qaKFParticle.cxx b/Tools/KFparticle/qaKFParticle.cxx index c634d0837a4..4066ed0f49e 100644 --- a/Tools/KFparticle/qaKFParticle.cxx +++ b/Tools/KFparticle/qaKFParticle.cxx @@ -15,52 +15,46 @@ /// \brief Task to test the performance of the KFParticle package /// -#include "Tools/KFparticle/qaKFParticle.h" - -#include "TableHelper.h" - -#include - -#include -#include +#ifndef HomogeneousField +#define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) +#endif -#include +#include "Tools/KFparticle/qaKFParticle.h" -/// includes O2 -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" - -/// includes O2Physics #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/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Tools/KFparticle/KFUtilities.h" -/// includes KFParticle -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFParticle.h" -#include "KFParticleBase.h" -#include "KFVertex.h" - -#ifndef HomogeneousField +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include -#define HomogeneousField +#include +#include +#include -#endif +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -76,6 +70,7 @@ struct qaKFParticle { 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)"}; Service ccdb; + Service pdgdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber; @@ -335,22 +330,22 @@ struct qaKFParticle { bool isSelectedTracks(const T& track1, const T& track2) { /// DCA XY of the daughter tracks to the primaty vertex - if (fabs(track1.dcaXY()) > d_dcaXYTrackPV) { + if (std::fabs(track1.dcaXY()) > d_dcaXYTrackPV) { histos.fill(HIST("DZeroCandTopo/Selections"), 6.f); return false; } /// DCA XY of the daughter tracks to the primaty vertex - if (fabs(track2.dcaXY()) > d_dcaXYTrackPV) { + if (std::fabs(track2.dcaXY()) > d_dcaXYTrackPV) { histos.fill(HIST("DZeroCandTopo/Selections"), 6.f); return false; } /// DCA Z of the daughter tracks to the primaty vertex - if (fabs(track1.dcaZ()) > d_dcaZTrackPV) { + if (std::fabs(track1.dcaZ()) > d_dcaZTrackPV) { histos.fill(HIST("DZeroCandTopo/Selections"), 7.f); return false; } /// DCA Z of the daughter tracks to the primaty vertex - if (fabs(track2.dcaZ()) > d_dcaZTrackPV) { + if (std::fabs(track2.dcaZ()) > d_dcaZTrackPV) { histos.fill(HIST("DZeroCandTopo/Selections"), 7.f); return false; } @@ -462,15 +457,15 @@ struct qaKFParticle { { switch (particle) { case kPiPlus: { - if ((track.pt() <= ptPidTofMinPi) && track.hasTPC() && (abs(track.tpcNSigmaPi()) < nSigmaTpcMaxPi)) { + if ((track.pt() <= ptPidTofMinPi) && track.hasTPC() && (std::abs(track.tpcNSigmaPi()) < nSigmaTpcMaxPi)) { return true; - } else if ((track.pt() > ptPidTofMinPi) && track.hasTPC() && !track.hasTOF() && (abs(track.tpcNSigmaPi()) < nSigmaTpcMaxPi)) { + } else if ((track.pt() > ptPidTofMinPi) && track.hasTPC() && !track.hasTOF() && (std::abs(track.tpcNSigmaPi()) < nSigmaTpcMaxPi)) { return true; - } else if ((track.pt() > ptPidTofMinPi) && !track.hasTPC() && track.hasTOF() && (abs(track.tofNSigmaPi()) < nSigmaTofMaxPi)) { + } else if ((track.pt() > ptPidTofMinPi) && !track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaPi()) < nSigmaTofMaxPi)) { return true; } else if ((track.pt() > ptPidTofMinPi) && track.hasTPC() && track.hasTOF()) { - float CombinednSigma = 1. / sqrt(2) * sqrt((track.tpcNSigmaPi() * track.tpcNSigmaPi()) + (track.tofNSigmaPi() * track.tofNSigmaPi())); - if (abs(CombinednSigma) < nSigmaCombMaxPi) { + float CombinednSigma = 1. / std::sqrt(2) * std::sqrt((track.tpcNSigmaPi() * track.tpcNSigmaPi()) + (track.tofNSigmaPi() * track.tofNSigmaPi())); + if (std::abs(CombinednSigma) < nSigmaCombMaxPi) { return true; } else { return false; @@ -481,15 +476,15 @@ struct qaKFParticle { break; } case kKPlus: { - if ((track.pt() <= ptPidTofMinKa) && track.hasTPC() && (abs(track.tpcNSigmaKa()) < nSigmaTpcMaxKa)) { + if ((track.pt() <= ptPidTofMinKa) && track.hasTPC() && (std::abs(track.tpcNSigmaKa()) < nSigmaTpcMaxKa)) { return true; - } else if ((track.pt() > ptPidTofMinKa) && track.hasTPC() && !track.hasTOF() && (abs(track.tpcNSigmaKa()) < nSigmaTpcMaxKa)) { + } else if ((track.pt() > ptPidTofMinKa) && track.hasTPC() && !track.hasTOF() && (std::abs(track.tpcNSigmaKa()) < nSigmaTpcMaxKa)) { return true; - } else if ((track.pt() > ptPidTofMinKa) && !track.hasTPC() && track.hasTOF() && (abs(track.tofNSigmaKa()) < nSigmaTofMaxKa)) { + } else if ((track.pt() > ptPidTofMinKa) && !track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaKa()) < nSigmaTofMaxKa)) { return true; } else if ((track.pt() > ptPidTofMinKa) && track.hasTPC() && track.hasTOF()) { - float CombinednSigma = 1. / sqrt(2) * sqrt((track.tpcNSigmaKa() * track.tpcNSigmaKa()) + (track.tofNSigmaKa() * track.tofNSigmaKa())); - if (abs(CombinednSigma) < nSigmaCombMaxKa) { + float CombinednSigma = 1. / std::sqrt(2) * std::sqrt((track.tpcNSigmaKa() * track.tpcNSigmaKa()) + (track.tofNSigmaKa() * track.tofNSigmaKa())); + if (std::abs(CombinednSigma) < nSigmaCombMaxKa) { return true; } else { return false; @@ -598,7 +593,7 @@ struct qaKFParticle { float chi2geo = KFDZero.GetChi2() / KFDZero.GetNDF(); float normdecayLength = KFDZero_PV.GetDecayLength() / KFDZero_PV.GetErrDecayLength(); float chi2topo = KFDZero_PV.GetChi2() / KFDZero_PV.GetNDF(); - const double pseudoRndm = track1.pt() * 1000. - (int64_t)(track1.pt() * 1000); + const double pseudoRndm = track1.pt() * 1000. - static_cast((track1.pt() * 1000)); if (pseudoRndm < d_DwnSmplFact) { if (writeTree) { /// Filling the D0 tree @@ -800,7 +795,7 @@ struct qaKFParticle { continue; } /// Apply selection on geometrically reconstructed D0 - cosThetaStar = cosThetaStarFromKF(1, 421, 211, 321, KFPosPion, KFNegKaon); + cosThetaStar = cosThetaStarFromKF(1, 421, 211, 321, KFPosPion, KFNegKaon, pdgdb); if (!isSelectedDoGeo(KFDZero, KFPV, cosThetaStar)) { continue; } @@ -835,7 +830,7 @@ struct qaKFParticle { continue; } /// Apply selection on geometrically reconstructed D0 - cosThetaStar = cosThetaStarFromKF(0, 421, 321, 211, KFPosKaon, KFNegPion); + cosThetaStar = cosThetaStarFromKF(0, 421, 321, 211, KFPosKaon, KFNegPion, pdgdb); if (!isSelectedDoGeo(KFDZeroBar, KFPV, cosThetaStar)) { continue; } @@ -940,7 +935,7 @@ struct qaKFParticle { // KFPV = KFPVNew; // } // if (i > 1) { - // if (abs(matchedCollision.posZ() - collMC.posZ()) == min) { + // if (std::abs(matchedCollision.posZ() - collMC.posZ()) == min) { // kfpVertex = createKFPVertexFromCollision(matchedCollision); // KFParticle KFPVNew(kfpVertex); // KFPV = KFPVNew; @@ -1107,7 +1102,7 @@ struct qaKFParticle { continue; } /// Apply selection on geometrically reconstructed D0 - cosThetaStar = cosThetaStarFromKF(1, 421, 211, 321, KFPosPion, KFNegKaon); + cosThetaStar = cosThetaStarFromKF(1, 421, 211, 321, KFPosPion, KFNegKaon, pdgdb); if (!isSelectedDoGeo(KFDZero, KFPV, cosThetaStar)) { continue; } @@ -1147,7 +1142,7 @@ struct qaKFParticle { continue; } /// Apply selection on geometrically reconstructed D0 - cosThetaStar = cosThetaStarFromKF(0, 421, 321, 211, KFPosKaon, KFNegPion); + cosThetaStar = cosThetaStarFromKF(0, 421, 321, 211, KFPosKaon, KFNegPion, pdgdb); if (!isSelectedDoGeo(KFDZeroBar, KFPV, cosThetaStar)) { continue; } diff --git a/Tools/KFparticle/qaKFParticle.h b/Tools/KFparticle/qaKFParticle.h index afb23851cb5..e9c8f298325 100644 --- a/Tools/KFparticle/qaKFParticle.h +++ b/Tools/KFparticle/qaKFParticle.h @@ -15,9 +15,9 @@ #ifndef TOOLS_KFPARTICLE_QAKFPARTICLE_H_ #define TOOLS_KFPARTICLE_QAKFPARTICLE_H_ -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/Core/trackUtilities.h" +#include + +#include enum Source { kPrompt = BIT(0), diff --git a/Tools/KFparticle/qaKFParticleLc.cxx b/Tools/KFparticle/qaKFParticleLc.cxx index 792acdff439..86902d349cd 100644 --- a/Tools/KFparticle/qaKFParticleLc.cxx +++ b/Tools/KFparticle/qaKFParticleLc.cxx @@ -15,52 +15,40 @@ /// \brief Task to test the performance of the KFParticle package on the Lc to pKpi decay /// -#include "Tools/KFparticle/qaKFParticleLc.h" - -#include "TableHelper.h" - -#include - -#include -#include +#ifndef HomogeneousField +#define HomogeneousField +#endif -#include +#include "Tools/KFparticle/qaKFParticleLc.h" -/// includes O2 -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" - -/// includes O2Physics -#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/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Tools/KFparticle/KFUtilities.h" -/// includes KFParticle -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFParticle.h" -#include "KFParticleBase.h" -#include "KFVertex.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#ifndef HomogeneousField +#include -#define HomogeneousField +#include +#include +#include -#endif +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/Tools/KFparticle/qaKFParticleLc.h b/Tools/KFparticle/qaKFParticleLc.h index 8c57232f99a..29fc5707be4 100644 --- a/Tools/KFparticle/qaKFParticleLc.h +++ b/Tools/KFparticle/qaKFParticleLc.h @@ -15,9 +15,9 @@ #ifndef TOOLS_KFPARTICLE_QAKFPARTICLELC_H_ #define TOOLS_KFPARTICLE_QAKFPARTICLELC_H_ -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/Core/trackUtilities.h" +#include + +#include enum Source { kPrompt = BIT(0), diff --git a/Tools/ML/model.cxx b/Tools/ML/model.cxx index a60abc65af5..6d2098068aa 100644 --- a/Tools/ML/model.cxx +++ b/Tools/ML/model.cxx @@ -23,6 +23,7 @@ #include +#include #include #include diff --git a/Tools/ML/model.h b/Tools/ML/model.h index 468c3dfd733..3be08e72fa9 100644 --- a/Tools/ML/model.h +++ b/Tools/ML/model.h @@ -22,6 +22,7 @@ #include +#include #include #include diff --git a/Tutorials/CMakeLists.txt b/Tutorials/CMakeLists.txt index d99c71adc88..e99e99b9d9d 100644 --- a/Tutorials/CMakeLists.txt +++ b/Tutorials/CMakeLists.txt @@ -122,6 +122,11 @@ o2physics_add_dpl_workflow(ccdbaccess PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::CCDB O2::Framework O2Physics::AnalysisCore COMPONENT_NAME AnalysisTutorial) +o2physics_add_dpl_workflow(ccdbtableaccess + SOURCES src/ccdbtableaccess.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::CCDB O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) + o2physics_add_dpl_workflow(weak-decay-iteration SOURCES src/weakDecayIteration.cxx COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/OpenData/flowAnalysis.cxx b/Tutorials/OpenData/flowAnalysis.cxx index dc5e180b300..29190eee67e 100644 --- a/Tutorials/OpenData/flowAnalysis.cxx +++ b/Tutorials/OpenData/flowAnalysis.cxx @@ -15,20 +15,23 @@ /// \author /// \since -#include -#include -#include -#include -#include -#include -#include #include #include +#include #include +#include +#include #include -#include + #include #include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/Tutorials/PWGEM/emcclustertutorial.cxx b/Tutorials/PWGEM/emcclustertutorial.cxx index a047206e70d..2e2df5912c1 100644 --- a/Tutorials/PWGEM/emcclustertutorial.cxx +++ b/Tutorials/PWGEM/emcclustertutorial.cxx @@ -9,6 +9,23 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "PWGJE/DataModel/EMCALClusters.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/Constants.h" +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + #include #include #include @@ -17,25 +34,6 @@ #include #include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.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 "CommonDataFormat/InteractionRecord.h" - // \struct ClusterTutorial /// \brief Skeleton task for EMCal cluster tutorial /// \author Florian Jonas , Oak Ridge National Laoratory; Joshua König , Goethe-University Frankfurt; Marvin Hemmer , Goethe-University Frankfurt diff --git a/Tutorials/PWGUD/UDTutorial_01.cxx b/Tutorials/PWGUD/UDTutorial_01.cxx index c2cbf7b4f13..d19accd1ee8 100644 --- a/Tutorials/PWGUD/UDTutorial_01.cxx +++ b/Tutorials/PWGUD/UDTutorial_01.cxx @@ -13,13 +13,15 @@ // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since April 2023 -#include "Framework/runDataProcessing.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/DataModel/PIDResponseTOF.h" + #include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "TVector3.h" -#include "Common/DataModel/PIDResponse.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UDHelpers.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/PWGUD/UDTutorial_02a.cxx b/Tutorials/PWGUD/UDTutorial_02a.cxx index 75aa83c87a7..847191d3626 100644 --- a/Tutorials/PWGUD/UDTutorial_02a.cxx +++ b/Tutorials/PWGUD/UDTutorial_02a.cxx @@ -13,14 +13,14 @@ // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since April 2023 -#include "Framework/runDataProcessing.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "TDatabasePDG.h" #include "TLorentzVector.h" -#include "Common/DataModel/PIDResponse.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UDHelpers.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/PWGUD/UDTutorial_02b.cxx b/Tutorials/PWGUD/UDTutorial_02b.cxx index 26a76a98186..ece20563991 100644 --- a/Tutorials/PWGUD/UDTutorial_02b.cxx +++ b/Tutorials/PWGUD/UDTutorial_02b.cxx @@ -13,13 +13,12 @@ // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since April 2023 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" - -#include "Common/DataModel/PIDResponse.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/DGPIDSelector.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/PWGUD/UDTutorial_03a.cxx b/Tutorials/PWGUD/UDTutorial_03a.cxx index 9840123236b..4a7c91d0690 100644 --- a/Tutorials/PWGUD/UDTutorial_03a.cxx +++ b/Tutorials/PWGUD/UDTutorial_03a.cxx @@ -13,15 +13,17 @@ // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since October 2023 -#include "Framework/runDataProcessing.h" +#include "PWGUD/Core/UDHelpers.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "TDatabasePDG.h" #include "TLorentzVector.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "PWGUD/Core/UDHelpers.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/PWGUD/UDTutorial_03b.cxx b/Tutorials/PWGUD/UDTutorial_03b.cxx index 71a144f1d1e..af5c1e1166e 100644 --- a/Tutorials/PWGUD/UDTutorial_03b.cxx +++ b/Tutorials/PWGUD/UDTutorial_03b.cxx @@ -13,15 +13,17 @@ // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since October 2023 -#include "Framework/runDataProcessing.h" +#include "PWGUD/Core/UDHelpers.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "TDatabasePDG.h" #include "TLorentzVector.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "PWGUD/Core/UDHelpers.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/Skimming/DataModel/LFDerived.h b/Tutorials/Skimming/DataModel/LFDerived.h index c89e0da5323..12d7405a98d 100644 --- a/Tutorials/Skimming/DataModel/LFDerived.h +++ b/Tutorials/Skimming/DataModel/LFDerived.h @@ -13,6 +13,9 @@ #ifndef O2_ANALYSIS_LFDERIVED_H #define O2_ANALYSIS_LFDERIVED_H +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" diff --git a/Tutorials/Skimming/spectraNucleiAnalyser.cxx b/Tutorials/Skimming/spectraNucleiAnalyser.cxx index f0647db20a9..699905c2f9b 100644 --- a/Tutorials/Skimming/spectraNucleiAnalyser.cxx +++ b/Tutorials/Skimming/spectraNucleiAnalyser.cxx @@ -10,16 +10,16 @@ // or submit itself to any jurisdiction. // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "DataModel/LFDerived.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" #include diff --git a/Tutorials/Skimming/spectraNucleiProvider.cxx b/Tutorials/Skimming/spectraNucleiProvider.cxx index 7a76882fd7a..76a0bb9dc42 100644 --- a/Tutorials/Skimming/spectraNucleiProvider.cxx +++ b/Tutorials/Skimming/spectraNucleiProvider.cxx @@ -11,16 +11,18 @@ /// \author Nima Zardoshti , CERN // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "MathUtils/Utils.h" #include "DataModel/LFDerived.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "MathUtils/Utils.h" +#include "ReconstructionDataFormats/Track.h" #include diff --git a/Tutorials/Skimming/spectraNucleiReference.cxx b/Tutorials/Skimming/spectraNucleiReference.cxx index 40535297fef..7d3bf950210 100644 --- a/Tutorials/Skimming/spectraNucleiReference.cxx +++ b/Tutorials/Skimming/spectraNucleiReference.cxx @@ -10,18 +10,17 @@ // or submit itself to any jurisdiction. // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" - #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" #include diff --git a/Tutorials/Skimming/spectraTPCAnalyser.cxx b/Tutorials/Skimming/spectraTPCAnalyser.cxx index 769ad0b885a..348e9d1de7c 100644 --- a/Tutorials/Skimming/spectraTPCAnalyser.cxx +++ b/Tutorials/Skimming/spectraTPCAnalyser.cxx @@ -10,14 +10,15 @@ // or submit itself to any jurisdiction. // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "DataModel/LFDerived.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "ReconstructionDataFormats/Track.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -63,7 +64,7 @@ struct TPCSpectraAnalyserTask { histos.fill(HIST(hpt[i]), track.pt()); } - Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; //collision filters not doing anything now? + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; // collision filters not doing anything now? Filter trackFilter = nabs(aod::lftrack::eta) < cfgCutEta; void process(soa::Filtered::iterator const& track) diff --git a/Tutorials/Skimming/spectraTPCProvider.cxx b/Tutorials/Skimming/spectraTPCProvider.cxx index c0bbf087fd3..c79115dd78f 100644 --- a/Tutorials/Skimming/spectraTPCProvider.cxx +++ b/Tutorials/Skimming/spectraTPCProvider.cxx @@ -11,15 +11,17 @@ /// \author Nima Zardoshti , CERN // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "DataModel/LFDerived.h" + #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "MathUtils/Utils.h" -#include "DataModel/LFDerived.h" +#include "ReconstructionDataFormats/Track.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/Skimming/spectraTPCReference.cxx b/Tutorials/Skimming/spectraTPCReference.cxx index 5d23fd202dc..6111c5dba92 100644 --- a/Tutorials/Skimming/spectraTPCReference.cxx +++ b/Tutorials/Skimming/spectraTPCReference.cxx @@ -10,13 +10,14 @@ // or submit itself to any jurisdiction. // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "ReconstructionDataFormats/Track.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -47,7 +48,7 @@ struct TPCSpectraReferenceTask { } } - //Defining filters and input + // Defining filters and input Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; Configurable cfgCutPt{"cfgCutPt", 0.0f, "Pt range for tracks"}; diff --git a/Tutorials/Skimming/spectraUPCAnalyser.cxx b/Tutorials/Skimming/spectraUPCAnalyser.cxx index cdc6c9a0c4b..740a62dc822 100644 --- a/Tutorials/Skimming/spectraUPCAnalyser.cxx +++ b/Tutorials/Skimming/spectraUPCAnalyser.cxx @@ -10,16 +10,17 @@ // or submit itself to any jurisdiction. // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "DataModel/UDDerived.h" -#include "TLorentzVector.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/Track.h" + +#include "TLorentzVector.h" using namespace o2; using namespace o2::framework; diff --git a/Tutorials/Skimming/spectraUPCProvider.cxx b/Tutorials/Skimming/spectraUPCProvider.cxx index 053b7437080..8884c09d99b 100644 --- a/Tutorials/Skimming/spectraUPCProvider.cxx +++ b/Tutorials/Skimming/spectraUPCProvider.cxx @@ -10,18 +10,18 @@ // or submit itself to any jurisdiction. /// \author Nima Zardoshti , CERN -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/PIDResponse.h" -#include "ReconstructionDataFormats/Track.h" +#include "DataModel/UDDerived.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" #include -#include "DataModel/UDDerived.h" using namespace o2; using namespace o2::aod::evsel; diff --git a/Tutorials/src/ccdbtableaccess.cxx b/Tutorials/src/ccdbtableaccess.cxx new file mode 100644 index 00000000000..52688bcebfc --- /dev/null +++ b/Tutorials/src/ccdbtableaccess.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. +/// +/// \brief A tutorial task to retrieve objects from CCDB given a time stamp. +/// \author Daiki Sekihata +/// \since 2026-03-01 + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include + +using namespace o2::framework; +using namespace o2::header; +using namespace o2; + +namespace o2::aod +{ +namespace testccdb +{ +DECLARE_SOA_CCDB_COLUMN(GRPMagField, grpMagField, o2::parameters::GRPMagField, "GLO/Config/GRPMagField"); //! +DECLARE_SOA_CCDB_COLUMN(MeanVertex, meanVertex, o2::dataformats::MeanVertexObject, "GLO/Calib/MeanVertex"); //! +} // namespace testccdb + +DECLARE_SOA_TIMESTAMPED_TABLE(MyCCDBObjects, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "MYCCDBOBJ", //! + testccdb::GRPMagField, testccdb::MeanVertex); +} // namespace o2::aod + +struct TestCCDBTable { + void init(o2::framework::InitContext&) {} + + using MyBCs = soa::Join; + + void process(MyBCs const& bcs) + { + int i = 0; + for (const auto& bc : bcs) { + if (i >= 5) { + return; + } + float l3current = bc.grpMagField().getL3Current(); + float zvtx = bc.meanVertex().getZ(); + LOGF(info, "bc.globalBC() = %llu, bc.timestamp() = %llu, L3 current = %f A, mean zvtx = %f cm", bc.globalBC(), bc.timestamp(), l3current, zvtx); + i++; + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/Tutorials/src/pidTpcTof.cxx b/Tutorials/src/pidTpcTof.cxx index 777c09c1920..dab7d9e425c 100644 --- a/Tutorials/src/pidTpcTof.cxx +++ b/Tutorials/src/pidTpcTof.cxx @@ -17,11 +17,12 @@ // O2 includes #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" // O2Physics includes -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" using namespace o2; using namespace o2::aod::pidutils; diff --git a/cmake/O2PhysicsAddWorkflow.cmake b/cmake/O2PhysicsAddWorkflow.cmake index d432440f816..d2d599c4406 100644 --- a/cmake/O2PhysicsAddWorkflow.cmake +++ b/cmake/O2PhysicsAddWorkflow.cmake @@ -1,4 +1,4 @@ -# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# Copyright 2019-2026 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. # @@ -27,8 +27,7 @@ include_guard() # function(o2physics_add_dpl_workflow baseTargetName) - - cmake_parse_arguments(PARSE_ARGV 1 A "" "COMPONENT_NAME;TARGETVARNAME" + cmake_parse_arguments(PARSE_ARGV 1 A "" "COMPONENT_NAME;TARGETVARNAME;REUSE_FROM" "SOURCES;PUBLIC_LINK_LIBRARIES") if(A_UNPARSED_ARGUMENTS) @@ -48,6 +47,10 @@ function(o2physics_add_dpl_workflow baseTargetName) set_property(TARGET ${targetExeName} PROPERTY JOB_POOL_COMPILE analysis) set_property(TARGET ${targetExeName} PROPERTY JOB_POOL_LINK analysis) + if(A_REUSE_FROM AND NOT DEFINED ENV{USE_RECC}) + target_precompile_headers(${targetExeName} REUSE_FROM ${A_REUSE_FROM}) + endif() + set(jsonFile $.json) add_custom_command(